66
77extern crate alloc;
88
9+ use alloc:: boxed:: Box ;
910use alloc:: collections:: btree_map:: BTreeMap ;
1011use alloc:: string:: String ;
1112use alloc:: sync:: Arc ;
@@ -50,10 +51,11 @@ use crate::types::{SVSM_USER_CS, SVSM_USER_DS};
5051use crate :: utils:: { MemoryRegion , is_aligned} ;
5152use intrusive_collections:: { LinkedListAtomicLink , intrusive_adapter} ;
5253
53- use super :: WaitQueue ;
54+ use super :: exec :: exec ;
5455use super :: schedule:: complete_task_switch;
5556use super :: schedule:: terminate;
5657use super :: task_mm:: { TaskKernelMapping , TaskMM } ;
58+ use super :: { UserExecInfo , WaitQueue } ;
5759
5860pub const INITIAL_TASK_ID : u32 = 1 ;
5961
@@ -129,7 +131,7 @@ impl KernelThreadStartInfo {
129131#[ derive( Debug ) ]
130132enum ThreadStartInfo {
131133 Kernel ( KernelThreadStartInfo ) ,
132- User ( usize ) ,
134+ User ( * const UserExecInfo ) ,
133135}
134136
135137#[ derive( PartialEq , Debug , Copy , Clone , Default ) ]
@@ -491,7 +493,7 @@ impl Task {
491493
492494 // Call the correct stack creation routine for this task.
493495 let ( stack, raw_bounds, rsp_offset) = match args. start_info {
494- ThreadStartInfo :: User ( entry ) => Self :: allocate_utask_stack ( cpu, entry , xsa_addr) ?,
496+ ThreadStartInfo :: User ( info_ptr ) => Self :: allocate_utask_stack ( cpu, info_ptr , xsa_addr) ?,
495497 ThreadStartInfo :: Kernel ( ref info) => Self :: allocate_ktask_stack (
496498 cpu,
497499 info. entry ,
@@ -552,7 +554,7 @@ impl Task {
552554
553555 pub fn create_user (
554556 cpu : & PerCpu ,
555- user_entry : usize ,
557+ info : Box < UserExecInfo > ,
556558 root : Arc < dyn Directory > ,
557559 name : String ,
558560 ) -> Result < TaskPointer , SvsmError > {
@@ -562,14 +564,23 @@ impl Task {
562564 unsafe {
563565 vm_user_range. initialize_lazy ( ) ?;
564566 }
567+
568+ // Destroy the Box and get the pointer to the raw data
569+ let info_ptr = Box :: into_raw ( info) ;
570+
565571 let create_args = CreateTaskArguments {
566- start_info : ThreadStartInfo :: User ( user_entry ) ,
572+ start_info : ThreadStartInfo :: User ( info_ptr ) ,
567573 name,
568574 vm_user_range : Some ( vm_user_range) ,
569575 rootdir : root,
570576 thread_of : None ,
571577 } ;
572- Self :: create_common ( cpu, create_args)
578+ Self :: create_common ( cpu, create_args) . inspect_err ( |_| {
579+ // In error case, make sure info gets freed
580+ // SAFETY: info_ptr was created above from a Box and not
581+ // dropped in the create_common call-path.
582+ drop ( unsafe { Box :: from_raw ( info_ptr) } ) ;
583+ } )
573584 }
574585
575586 /// Create a new thread for an existing task.
@@ -737,20 +748,14 @@ impl Task {
737748
738749 fn allocate_utask_stack (
739750 cpu : & PerCpu ,
740- user_entry : usize ,
751+ info_ptr : * const UserExecInfo ,
741752 xsa_addr : usize ,
742753 ) -> Result < ( Mapping , MemoryRegion < VirtAddr > , usize ) , SvsmError > {
743- // Do not run user-mode with IRQs enabled on platforms which are not
744- // ready for it.
745- let iret_rflags: usize = if SVSM_PLATFORM . use_interrupts ( ) {
746- 2 | EFLAGS_IF
747- } else {
748- 2
749- } ;
750754 let task_context = UserTaskContext {
751755 task_context : TaskContext {
752756 regs : X86TaskSwitchRegs {
753- rsi : xsa_addr, // XSAVE area addr
757+ rsi : xsa_addr, // XSAVE area addr
758+ r14 : info_ptr as usize , // New task launch info
754759 ..Default :: default ( )
755760 } ,
756761 ret_addr : thread_entry_asm as * const ( ) as u64 ,
@@ -762,20 +767,9 @@ impl Task {
762767 . unwrap ( ) ,
763768 // Setup IRQ return frame. User-mode tasks always run with
764769 // interrupts enabled.
765- excp_context : X86ExceptionContext {
766- frame : X86InterruptFrame {
767- rip : user_entry,
768- cs : ( SVSM_USER_CS | 3 ) . into ( ) ,
769- flags : iret_rflags,
770- rsp : ( USER_MEM_END - 8 ) . into ( ) ,
771- ss : ( SVSM_USER_DS | 3 ) . into ( ) ,
772- } ,
773- ..Default :: default ( )
774- } ,
770+ excp_context : X86ExceptionContext :: default ( ) ,
775771 } ;
776772
777- debug_assert ! ( is_aligned( task_context. excp_context. frame. rsp + 8 , 16 ) ) ;
778-
779773 Self :: allocate_stack_common ( cpu, & task_context)
780774 }
781775
@@ -1038,7 +1032,41 @@ unsafe fn complete_new_thread(prev: usize, xsa_addr: u64) {
10381032/// This is called from assembly code. The caller needs to ensure the
10391033/// parameters are passed correctly.
10401034#[ unsafe( no_mangle) ]
1041- unsafe fn run_user_task ( ) {
1035+ unsafe fn run_user_task (
1036+ info_ptr : * mut UserExecInfo ,
1037+ _unsused : u64 ,
1038+ ctxt : & mut X86ExceptionContext ,
1039+ ) {
1040+ // SAFETY: The raw pointer was extracted from a Box in
1041+ // allocate_utask_stack() to move ownership to a new process.
1042+ let info = unsafe { Box :: from_raw ( info_ptr) } ;
1043+
1044+ let entry = match exec ( * info) {
1045+ Ok ( e) => e,
1046+ Err ( e) => {
1047+ log:: error!( "Failed to load ELF binary: {e:?}" ) ;
1048+ terminate ( ) ;
1049+ }
1050+ } ;
1051+
1052+ // Do not run user-mode with IRQs enabled on platforms which are not
1053+ // ready for it.
1054+ let iret_rflags: usize = if SVSM_PLATFORM . use_interrupts ( ) {
1055+ 2 | EFLAGS_IF
1056+ } else {
1057+ 2
1058+ } ;
1059+
1060+ ctxt. frame = X86InterruptFrame {
1061+ rip : entry as usize ,
1062+ cs : ( SVSM_USER_CS | 3 ) . into ( ) ,
1063+ flags : iret_rflags,
1064+ rsp : ( USER_MEM_END - 8 ) . into ( ) ,
1065+ ss : ( SVSM_USER_DS | 3 ) . into ( ) ,
1066+ } ;
1067+
1068+ debug_assert ! ( is_aligned( ctxt. frame. rsp + 8 , 16 ) ) ;
1069+
10421070 task_attach_console ( ) ;
10431071}
10441072
0 commit comments