1- use core:: alloc:: Layout ;
2-
31use kernutil:: memory:: MemoryType ;
42
53use crate :: {
64 ArchTrait , DCacheOp ,
75 arch:: Arch ,
86 kernel_page_table_paddr,
9- mem:: { __kimage_va , __percpu, dcache_range, page_size, phys_to_virt, stack_size } ,
7+ mem:: { __percpu, dcache_range, page_size, phys_to_virt} ,
108} ;
119
1210mod cpu_iter;
11+ #[ cfg( not( feature = "percpu-prealloc" ) ) ]
12+ mod legacy;
13+ #[ cfg( feature = "percpu-prealloc" ) ]
14+ mod prealloc;
15+
16+ #[ cfg( not( feature = "percpu-prealloc" ) ) ]
17+ use legacy as layout;
18+ #[ cfg( feature = "percpu-prealloc" ) ]
19+ use prealloc as layout;
1320
1421static mut PERCPU_START : usize = 0 ;
1522static mut PERCPU_END : usize = 0 ;
@@ -31,97 +38,8 @@ fn percpu_region_align() -> usize {
3138 page_size ( ) . max ( meta_align ( ) )
3239}
3340
34- fn meta_offset ( ) -> usize {
35- let link_size = percpu_link_range ( ) . len ( ) ;
36- let offset = align_up_pow2 ( link_size, meta_align ( ) ) ;
37- debug_assert_eq ! ( offset % meta_align( ) , 0 ) ;
38- offset
39- }
40-
41- /// Per-CPU data layout:
42- ///
43- ///
44- /// | Linker percpu data | align to 0x8 | PerCpuMeta | align padding to page size | Stack |
4541pub fn alloc_percpu ( ) {
46- println ! ( "Initializing per-CPU data" ) ;
47- let cpu_num = __cpu_id_list ( ) . count ( ) ;
48- let link_range = percpu_link_range ( ) ;
49- let link_size = link_range. len ( ) ;
50-
51- let percpu_size = percpu_data_size ( ) ;
52- println ! ( "Per-CPU data one cpu size: {:#x} bytes" , percpu_size) ;
53- let percpu_all_secondary_size = percpu_size * cpu_num;
54-
55- println ! (
56- "Total per-CPU data size for secondary CPUs: {:#x} bytes ({} CPUs)" ,
57- percpu_all_secondary_size, cpu_num
58- ) ;
59-
60- unsafe { crate :: mem:: ram:: flush_to_memory_map ( MemoryType :: Reserved ) } ;
61-
62- let percpu_data = unsafe {
63- crate :: mem:: ram:: alloc_and_flush_to_memory_map (
64- Layout :: from_size_align ( percpu_all_secondary_size, percpu_region_align ( ) ) . unwrap ( ) ,
65- MemoryType :: PerCpuData ,
66- )
67- . unwrap ( )
68- } ;
69-
70- unsafe {
71- PERCPU_START = percpu_data;
72- PERCPU_END = PERCPU_START + percpu_all_secondary_size;
73-
74- core:: ptr:: write_bytes ( phys_to_virt ( percpu_data) , 0 , percpu_all_secondary_size) ;
75- }
76-
77- println ! (
78- "Per-CPU data allocated at {:#x} - {:#x}" ,
79- unsafe { PERCPU_START } ,
80- unsafe { PERCPU_END }
81- ) ;
82-
83- let entry_virt = __kimage_va ( super :: entry:: secondary_entry as * const ( ) as usize ) ;
84-
85- for ( idx, hard_id) in __cpu_id_list ( ) . enumerate ( ) {
86- let cpu_percpu_start = percpu_data_range ( ) . start + idx * percpu_size;
87- println ! (
88- "Initializing per-CPU RAM for CPU{idx} - hard id {hard_id:#x} @ {cpu_percpu_start:#x}"
89- ) ;
90- unsafe {
91- core:: ptr:: copy_nonoverlapping (
92- phys_to_virt ( link_range. start ) as * const u8 ,
93- phys_to_virt ( cpu_percpu_start) ,
94- link_size,
95- ) ;
96- }
97- let meta_start = cpu_percpu_start + meta_offset ( ) ;
98- let meta_va = phys_to_virt ( meta_start) ;
99- debug_assert_eq ! ( meta_start % meta_align( ) , 0 ) ;
100- debug_assert_eq ! ( ( meta_va as usize ) % meta_align( ) , 0 ) ;
101-
102- let stack_top = cpu_percpu_start + stack_offset ( ) + stack_size ( ) ;
103- let stack_top_virt = __percpu ( stack_top) ;
104-
105- let meta = PerCpuMeta {
106- stack_top,
107- cpu_id : hard_id,
108- cpu_idx : idx,
109- stack_top_virt : stack_top_virt as _ ,
110- entry_virt : entry_virt as _ ,
111- boot_table_paddr : 0 ,
112- primary_table_paddr : 0 ,
113- } ;
114- unsafe {
115- * meta_va. cast :: < PerCpuMeta > ( ) = meta;
116- }
117- }
118-
119- for meta in cpu_meta_list ( ) {
120- println ! (
121- "CPU{} - hard id {:#x}, stack top @{:#x}, stack top virt @{:#x}, entry virt @{:#x}" ,
122- meta. cpu_idx, meta. cpu_id, meta. stack_top, meta. stack_top_virt, meta. entry_virt
123- ) ;
124- }
42+ layout:: alloc_percpu ( ) ;
12543}
12644
12745pub ( crate ) fn init_percpu ( ) {
@@ -153,16 +71,6 @@ pub struct PerCpuMeta {
15371 pub primary_table_paddr : usize ,
15472}
15573
156- fn stack_offset ( ) -> usize {
157- let meta_offset = meta_offset ( ) ;
158- let meta_size = core:: mem:: size_of :: < PerCpuMeta > ( ) ;
159- align_up_pow2 ( meta_offset + meta_size, page_size ( ) )
160- }
161-
162- fn percpu_data_size ( ) -> usize {
163- align_up_pow2 ( stack_offset ( ) + stack_size ( ) , percpu_region_align ( ) )
164- }
165-
16674#[ allow( dead_code) ]
16775/// Physical RAM allocated for per-CPU data should be mapped to this virtual address range in the kernel
16876pub ( crate ) fn percpu_range ( ) -> core:: ops:: Range < usize > {
@@ -189,19 +97,11 @@ pub fn cpu_meta(idx: usize) -> Option<PerCpuMeta> {
18997
19098/// Physical address of cpu meta
19199pub ( crate ) fn cpu_meta_addr ( idx : usize ) -> Option < usize > {
192- let base = percpu_data_range ( ) . start + idx * percpu_data_size ( ) ;
193- if base >= percpu_data_range ( ) . end {
194- return None ;
195- }
196- Some ( base + meta_offset ( ) )
100+ layout:: cpu_meta_addr ( idx)
197101}
198102
199103pub fn percpu_data_ptr ( idx : usize ) -> Option < * mut u8 > {
200- let base = percpu_data_range ( ) . start + idx * percpu_data_size ( ) ;
201- if base >= percpu_data_range ( ) . end {
202- return None ;
203- }
204- Some ( phys_to_virt ( base) )
104+ layout:: percpu_data_ptr ( idx)
205105}
206106
207107pub fn cpu_hart_id ( ) -> usize {
@@ -270,10 +170,6 @@ impl Iterator for CpuMetaIterMutable {
270170 }
271171}
272172
273- fn percpu_data_range ( ) -> core:: ops:: Range < usize > {
274- unsafe { PERCPU_START ..PERCPU_END }
275- }
276-
277173fn percpu_link_range ( ) -> core:: ops:: Range < usize > {
278174 unsafe extern "C" {
279175 fn __percpu_start ( ) ;
@@ -283,3 +179,26 @@ fn percpu_link_range() -> core::ops::Range<usize> {
283179 let end = __percpu_end as * const ( ) as usize ;
284180 start..end
285181}
182+
183+ fn set_percpu_range ( start : usize , end : usize ) {
184+ unsafe {
185+ PERCPU_START = start;
186+ PERCPU_END = end;
187+ }
188+ }
189+
190+ fn percpu_data_range ( ) -> core:: ops:: Range < usize > {
191+ unsafe { PERCPU_START ..PERCPU_END }
192+ }
193+
194+ fn alloc_percpu_region ( size : usize ) -> usize {
195+ unsafe { crate :: mem:: ram:: flush_to_memory_map ( MemoryType :: Reserved ) } ;
196+
197+ unsafe {
198+ crate :: mem:: ram:: alloc_and_flush_to_memory_map (
199+ core:: alloc:: Layout :: from_size_align ( size, percpu_region_align ( ) ) . unwrap ( ) ,
200+ MemoryType :: PerCpuData ,
201+ )
202+ . unwrap ( )
203+ }
204+ }
0 commit comments