6
6
7
7
extern crate alloc;
8
8
9
+ use alloc:: boxed:: Box ;
10
+ use alloc:: sync:: Arc ;
9
11
use core:: arch:: { asm, global_asm} ;
10
12
use core:: fmt;
11
13
use core:: mem:: size_of;
12
14
use core:: sync:: atomic:: { AtomicU32 , Ordering } ;
13
15
14
- use alloc:: boxed:: Box ;
15
-
16
- use crate :: address:: { Address , PhysAddr , VirtAddr } ;
16
+ use crate :: address:: { Address , VirtAddr } ;
17
17
use crate :: cpu:: msr:: { rdtsc, read_flags} ;
18
- use crate :: cpu:: percpu:: this_cpu;
18
+ use crate :: cpu:: percpu:: { this_cpu, this_cpu_mut } ;
19
19
use crate :: cpu:: X86GeneralRegs ;
20
20
use crate :: error:: SvsmError ;
21
21
use crate :: locking:: SpinLock ;
22
- use crate :: mm:: alloc:: { allocate_pages, get_order} ;
23
- use crate :: mm:: pagetable:: { get_init_pgtable_locked, PageTable , PageTableRef } ;
24
- use crate :: mm:: {
25
- virt_to_phys, PAGE_SIZE , PGTABLE_LVL3_IDX_PERCPU , SVSM_PERTASK_STACK_BASE ,
26
- SVSM_PERTASK_STACK_TOP ,
27
- } ;
28
- use crate :: utils:: zero_mem_region;
22
+ use crate :: mm:: pagetable:: { get_init_pgtable_locked, PTEntryFlags , PageTableRef } ;
23
+ use crate :: mm:: vm:: { Mapping , VMKernelStack , VMR } ;
24
+ use crate :: mm:: { SVSM_PERTASK_BASE , SVSM_PERTASK_END , SVSM_PERTASK_STACK_BASE } ;
29
25
30
26
pub const INITIAL_TASK_ID : u32 = 1 ;
31
27
32
- const STACK_SIZE : usize = 65536 ;
33
-
34
28
#[ derive( PartialEq , Debug , Copy , Clone , Default ) ]
35
29
pub enum TaskState {
36
30
RUNNING ,
@@ -39,13 +33,6 @@ pub enum TaskState {
39
33
TERMINATED ,
40
34
}
41
35
42
- #[ derive( Debug , Default ) ]
43
- pub struct TaskStack {
44
- pub virt_base : VirtAddr ,
45
- pub virt_top : VirtAddr ,
46
- pub phys : PhysAddr ,
47
- }
48
-
49
36
pub const TASK_FLAG_SHARE_PT : u16 = 0x01 ;
50
37
51
38
#[ derive( Debug , Default ) ]
@@ -183,12 +170,12 @@ pub struct TaskContext {
183
170
pub struct Task {
184
171
pub rsp : u64 ,
185
172
186
- /// Information about the task stack
187
- pub stack : TaskStack ,
188
-
189
173
/// Page table that is loaded when the task is scheduled
190
174
pub page_table : SpinLock < PageTableRef > ,
191
175
176
+ /// Task virtual memory range for use at CPL 0
177
+ vm_kernel_range : VMR ,
178
+
192
179
/// Current state of the task
193
180
pub state : TaskState ,
194
181
@@ -208,7 +195,6 @@ impl fmt::Debug for Task {
208
195
fn fmt ( & self , f : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result {
209
196
f. debug_struct ( "Task" )
210
197
. field ( "rsp" , & self . rsp )
211
- . field ( "stack" , & self . stack )
212
198
. field ( "state" , & self . state )
213
199
. field ( "affinity" , & self . affinity )
214
200
. field ( "id" , & self . id )
@@ -225,12 +211,18 @@ impl Task {
225
211
Self :: allocate_page_table ( ) ?
226
212
} ;
227
213
228
- let ( task_stack, rsp) = Self :: allocate_stack ( entry, & mut pgtable) ?;
214
+ let mut vm_kernel_range = VMR :: new ( SVSM_PERTASK_BASE , SVSM_PERTASK_END , PTEntryFlags :: USER ) ;
215
+ vm_kernel_range. initialize ( ) ?;
216
+
217
+ let ( stack, rsp_offset) = Self :: allocate_stack ( entry) ?;
218
+ vm_kernel_range. insert_at ( SVSM_PERTASK_STACK_BASE , stack) ?;
219
+
220
+ vm_kernel_range. populate ( & mut pgtable) ;
229
221
230
222
let task: Box < Task > = Box :: new ( Task {
231
- rsp : u64:: from ( rsp) ,
232
- stack : task_stack,
223
+ rsp : ( SVSM_PERTASK_STACK_BASE . bits ( ) + rsp_offset. bits ( ) ) as u64 ,
233
224
page_table : SpinLock :: new ( pgtable) ,
225
+ vm_kernel_range,
234
226
state : TaskState :: RUNNING ,
235
227
affinity : None ,
236
228
id : TASK_ID_ALLOCATOR . next_id ( ) ,
@@ -262,35 +254,16 @@ impl Task {
262
254
self . affinity = affinity;
263
255
}
264
256
265
- fn allocate_stack (
266
- entry : extern "C" fn ( ) ,
267
- pgtable : & mut PageTableRef ,
268
- ) -> Result < ( TaskStack , VirtAddr ) , SvsmError > {
269
- let stack_size = SVSM_PERTASK_STACK_TOP - SVSM_PERTASK_STACK_BASE ;
270
- let num_pages = 1 << get_order ( STACK_SIZE ) ;
271
- assert ! ( stack_size == num_pages * PAGE_SIZE ) ;
272
- let pages = allocate_pages ( get_order ( STACK_SIZE ) ) ?;
273
- zero_mem_region ( pages, pages + stack_size) ;
274
-
275
- let task_stack = TaskStack {
276
- virt_base : SVSM_PERTASK_STACK_BASE ,
277
- virt_top : SVSM_PERTASK_STACK_TOP ,
278
- phys : virt_to_phys ( pages) ,
279
- } ;
257
+ fn allocate_stack ( entry : extern "C" fn ( ) ) -> Result < ( Arc < Mapping > , VirtAddr ) , SvsmError > {
258
+ let stack = VMKernelStack :: new ( ) ?;
259
+ let offset = stack. top_of_stack ( VirtAddr :: from ( 0u64 ) ) ;
280
260
281
- // We current have a virtual address in SVSM shared memory for the stack. Configure
282
- // the per-task pagetable to map the stack into the task memory map.
283
- pgtable. map_region_4k (
284
- task_stack. virt_base ,
285
- task_stack. virt_top ,
286
- task_stack. phys ,
287
- PageTable :: task_data_flags ( ) ,
288
- ) ?;
261
+ let mapping = Arc :: new ( Mapping :: new ( stack) ) ;
262
+ let percpu_mapping = this_cpu_mut ( ) . new_mapping ( mapping. clone ( ) ) ?;
289
263
290
264
// We need to setup a context on the stack that matches the stack layout
291
265
// defined in switch_context below.
292
- let stack_pos = pages + stack_size;
293
- let stack_ptr: * mut u64 = stack_pos. as_mut_ptr ( ) ;
266
+ let stack_ptr: * mut u64 = ( percpu_mapping. virt_addr ( ) . bits ( ) + offset. bits ( ) ) as * mut u64 ;
294
267
295
268
// 'Push' the task frame onto the stack
296
269
unsafe {
@@ -302,8 +275,10 @@ impl Task {
302
275
stack_ptr. offset ( -1 ) . write ( task_exit as * const ( ) as u64 ) ;
303
276
}
304
277
305
- let initial_rsp = SVSM_PERTASK_STACK_TOP - ( size_of :: < TaskContext > ( ) + size_of :: < u64 > ( ) ) ;
306
- Ok ( ( task_stack, initial_rsp) )
278
+ Ok ( (
279
+ mapping,
280
+ offset - ( size_of :: < TaskContext > ( ) + size_of :: < u64 > ( ) ) ,
281
+ ) )
307
282
}
308
283
309
284
fn allocate_page_table ( ) -> Result < PageTableRef , SvsmError > {
@@ -323,7 +298,7 @@ extern "C" fn task_exit() {
323
298
extern "C" fn apply_new_context ( new_task : * mut Task ) -> u64 {
324
299
unsafe {
325
300
let mut pt = ( * new_task) . page_table . lock ( ) ;
326
- pt . copy_entry ( & this_cpu ( ) . get_pgtable ( ) , PGTABLE_LVL3_IDX_PERCPU ) ;
301
+ this_cpu ( ) . populate_page_table ( & mut pt ) ;
327
302
pt. cr3_value ( ) . bits ( ) as u64
328
303
}
329
304
}
0 commit comments