@@ -6,16 +6,16 @@ use core::sync::atomic::Ordering;
66use aarch64_cpu:: asm:: barrier:: { SY , isb} ;
77use aarch64_cpu:: registers:: * ;
88use align_address:: Align ;
9- use free_list:: { PageLayout , PageRange } ;
10- use memory_addresses:: { PhysAddr , VirtAddr } ;
9+ use memory_addresses:: VirtAddr ;
1110
1211use crate :: arch:: aarch64:: kernel:: CURRENT_STACK_ADDRESS ;
1312use crate :: arch:: aarch64:: kernel:: core_local:: core_scheduler;
14- use crate :: arch:: aarch64:: mm:: paging:: { BasePageSize , PageSize , PageTableEntryFlags } ;
15- use crate :: mm:: { FrameAlloc , PageAlloc , PageRangeAllocator } ;
13+ use crate :: arch:: aarch64:: mm:: paging:: { BasePageSize , PageSize } ;
1614use crate :: scheduler:: PerCoreSchedulerExt ;
1715use crate :: scheduler:: task:: { Task , TaskFrame } ;
1816use crate :: { DEFAULT_STACK_SIZE , KERNEL_STACK_SIZE } ;
17+ use crate :: arch:: kernel:: CURRENT_STACK ;
18+ use crate :: mm:: stack_alloc:: { allocate_stack, StackAllocation } ;
1919
2020#[ derive( Debug ) ]
2121#[ repr( C , packed) ]
@@ -94,156 +94,52 @@ pub(crate) struct State {
9494 pub x30 : u64 ,
9595}
9696
97- pub struct BootStack {
98- /// Stack for kernel tasks
99- stack : VirtAddr ,
100- }
101-
102- pub struct CommonStack {
103- /// Start address of allocated virtual memory region
104- virt_addr : VirtAddr ,
105- /// Start address of allocated virtual memory region
106- phys_addr : PhysAddr ,
107- /// Total size of all stacks
108- total_size : usize ,
109- }
110-
111- pub enum TaskStacks {
112- Boot ( BootStack ) ,
113- Common ( CommonStack ) ,
97+ pub struct TaskStacks {
98+ kernel_stack : StackAllocation ,
99+ user_stack : Option < StackAllocation > ,
114100}
115101
116102impl TaskStacks {
117- /// Size of the debug marker at the very top of each stack.
118- ///
119- /// We have a marker at the very top of the stack for debugging (`0xdeadbeef`), which should not be overridden.
120- pub const MARKER_SIZE : usize = 0x10 ;
121-
122103 pub fn new ( size : usize ) -> Self {
123104 let user_stack_size = if size < KERNEL_STACK_SIZE {
124105 KERNEL_STACK_SIZE
125106 } else {
126107 size. align_up ( BasePageSize :: SIZE as usize )
127108 } ;
128- let total_size = user_stack_size + DEFAULT_STACK_SIZE ;
129- let layout = PageLayout :: from_size ( total_size + 3 * BasePageSize :: SIZE as usize ) . unwrap ( ) ;
130- let page_range = PageAlloc :: allocate ( layout) . unwrap ( ) ;
131- let virt_addr = VirtAddr :: from ( page_range. start ( ) ) ;
132- let frame_layout = PageLayout :: from_size ( total_size) . unwrap ( ) ;
133- let frame_range = FrameAlloc :: allocate ( frame_layout)
134- . expect ( "Failed to allocate Physical Memory for TaskStacks" ) ;
135- let phys_addr = PhysAddr :: from ( frame_range. start ( ) ) ;
136-
137- debug ! (
138- "Create stacks at {:p} with a size of {} KB" ,
139- virt_addr,
140- total_size >> 10
141- ) ;
142-
143- let mut flags = PageTableEntryFlags :: empty ( ) ;
144- flags. normal ( ) . writable ( ) . execute_disable ( ) ;
145109
146- // map kernel stack into the address space
147- crate :: arch:: mm:: paging:: map :: < BasePageSize > (
148- virt_addr + BasePageSize :: SIZE ,
149- phys_addr,
150- DEFAULT_STACK_SIZE / BasePageSize :: SIZE as usize ,
151- flags,
152- ) ;
110+ let kernel_stack = allocate_stack ( DEFAULT_STACK_SIZE ) ;
111+ let user_stack = allocate_stack ( user_stack_size) ;
153112
154- // map user stack into the address space
155- crate :: arch:: mm:: paging:: map :: < BasePageSize > (
156- virt_addr + DEFAULT_STACK_SIZE + 2 * BasePageSize :: SIZE ,
157- phys_addr + DEFAULT_STACK_SIZE ,
158- user_stack_size / BasePageSize :: SIZE as usize ,
159- flags,
160- ) ;
161-
162- // clear user stack
163- unsafe {
164- ( virt_addr + DEFAULT_STACK_SIZE + 2 * BasePageSize :: SIZE )
165- . as_mut_ptr :: < u8 > ( )
166- . write_bytes ( 0 , user_stack_size) ;
113+ TaskStacks {
114+ kernel_stack, user_stack : Some ( user_stack)
167115 }
168-
169- TaskStacks :: Common ( CommonStack {
170- virt_addr,
171- phys_addr,
172- total_size,
173- } )
174116 }
175117
176118 pub fn from_boot_stacks ( ) -> TaskStacks {
177- let stack = VirtAddr :: from_ptr ( CURRENT_STACK_ADDRESS . load ( Ordering :: Relaxed ) ) ;
178- debug ! ( "Using boot stack {stack:p}" ) ;
179-
180- TaskStacks :: Boot ( BootStack { stack } )
181- }
182-
183- pub fn get_user_stack_size ( & self ) -> usize {
184- match self {
185- TaskStacks :: Boot ( _) => 0 ,
186- TaskStacks :: Common ( stacks) => stacks. total_size - DEFAULT_STACK_SIZE ,
187- }
188- }
119+ let kernel_stack = if let Some ( stack) = CURRENT_STACK . lock ( ) . as_ref ( ) {
120+ stack. weak ( )
121+ } else {
122+ let stack = VirtAddr :: from_ptr ( CURRENT_STACK_ADDRESS . load ( Ordering :: Relaxed ) ) ;
123+ debug ! ( "Using boot stack {stack:p}" ) ;
189124
190- pub fn get_user_stack ( & self ) -> VirtAddr {
191- match self {
192- TaskStacks :: Boot ( _) => VirtAddr :: zero ( ) ,
193- TaskStacks :: Common ( stacks) => {
194- stacks. virt_addr + DEFAULT_STACK_SIZE + 2 * BasePageSize :: SIZE
125+ unsafe {
126+ StackAllocation :: new_external ( stack, KERNEL_STACK_SIZE )
195127 }
196- }
197- }
128+ } ;
198129
199- pub fn get_kernel_stack ( & self ) -> VirtAddr {
200- match self {
201- TaskStacks :: Boot ( stacks) => stacks. stack ,
202- TaskStacks :: Common ( stacks) => stacks. virt_addr + BasePageSize :: SIZE ,
130+ Self {
131+ kernel_stack, user_stack : None
203132 }
204133 }
205134
206- pub fn get_kernel_stack_size ( & self ) -> usize {
207- match self {
208- TaskStacks :: Boot ( _) => KERNEL_STACK_SIZE ,
209- TaskStacks :: Common ( _) => DEFAULT_STACK_SIZE ,
210- }
135+ #[ inline( always) ]
136+ pub fn get_user_stack ( & self ) -> Option < & StackAllocation > {
137+ self . user_stack . as_ref ( )
211138 }
212- }
213-
214- impl Drop for TaskStacks {
215- fn drop ( & mut self ) {
216- // we should never deallocate a boot stack
217- match self {
218- TaskStacks :: Boot ( _) => { }
219- TaskStacks :: Common ( stacks) => {
220- debug ! (
221- "Deallocating stacks at {:p} with a size of {} KB" ,
222- stacks. virt_addr,
223- stacks. total_size >> 10 ,
224- ) ;
225139
226- crate :: arch:: mm:: paging:: unmap :: < BasePageSize > (
227- stacks. virt_addr ,
228- stacks. total_size / BasePageSize :: SIZE as usize + 3 ,
229- ) ;
230- let range = PageRange :: from_start_len (
231- stacks. virt_addr . as_usize ( ) ,
232- stacks. total_size + 3 * BasePageSize :: SIZE as usize ,
233- )
234- . unwrap ( ) ;
235- unsafe {
236- PageAlloc :: deallocate ( range) ;
237- }
238-
239- let range =
240- PageRange :: from_start_len ( stacks. phys_addr . as_usize ( ) , stacks. total_size )
241- . unwrap ( ) ;
242- unsafe {
243- FrameAlloc :: deallocate ( range) ;
244- }
245- }
246- }
140+ #[ inline( always) ]
141+ pub fn get_kernel_stack ( & self ) -> & StackAllocation {
142+ & self . kernel_stack
247143 }
248144}
249145
@@ -288,10 +184,7 @@ impl TaskFrame for Task {
288184 }
289185
290186 unsafe {
291- // Set a marker for debugging at the very top.
292- let mut stack = self . stacks . get_kernel_stack ( ) + self . stacks . get_kernel_stack_size ( )
293- - TaskStacks :: MARKER_SIZE ;
294- * stack. as_mut_ptr :: < u64 > ( ) = 0xdead_beefu64 ;
187+ let mut stack = self . stacks . get_kernel_stack ( ) . top_of_stack ( ) ;
295188
296189 // Put the State structure expected by the ASM switch() function on the stack.
297190 stack -= size_of :: < State > ( ) ;
@@ -314,12 +207,8 @@ impl TaskFrame for Task {
314207
315208 // Set the task's stack pointer entry to the stack we have just crafted.
316209 self . last_stack_pointer = stack;
210+ self . user_stack_pointer = self . stacks . get_user_stack ( ) . unwrap ( ) . top_of_stack ( ) ;
317211
318- // initialize user-level stack
319- self . user_stack_pointer = self . stacks . get_user_stack ( )
320- + self . stacks . get_user_stack_size ( )
321- - TaskStacks :: MARKER_SIZE ;
322- * self . user_stack_pointer . as_mut_ptr :: < u64 > ( ) = 0xdead_beefu64 ;
323212 ( * state) . sp_el0 = self . user_stack_pointer . as_u64 ( ) ;
324213 }
325214 }
0 commit comments