Skip to content

Commit f4b50dd

Browse files
committed
mm: provide high memory kernel mapping in asm code.
we use the first pml4 entry (+one pdp table) to map phy 0~512G to virt 0~512G for init code. This doesn't change. For the kernel to work in higher half memory, we also need to create mapping for it. We take the 256th entry of pml4 entry (hence one additional pdp table). Entry 0~63 are mapped to to the physical memory (with offset 0xffff_8000_0000_0000) Entry 64~127 are not used Entry 128~191 are mapped to the kernel image (text and code) (with offset 0xffff_8020_0000_0000) details in docs/mem_layout.txt
1 parent ae9df32 commit f4b50dd

File tree

3 files changed

+97
-42
lines changed

3 files changed

+97
-42
lines changed

boot/startup-x86_64.s

Lines changed: 85 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,11 @@
55
STACKSIZE: equ 65536
66

77
; 512 GB maximum RAM size for page table
8-
; DON'T MODIFY THIS UNLESS YOU UPDATE THE setup_paging accordingly
8+
; DON'T MODIFY THIS UNLESS YOU UPDATE THE setup_paging accordingly.
9+
; IMPORTANT! regardless of the initial mapping size, we limit the phy memory to
10+
; 64GB in the actual paging, so that all kernel VMAs could fit into one pml4
11+
; entry and one pdp (level 3) table. See docs/mem_layout.txt
12+
913
MAX_MEM: equ 512
1014

1115
; be careful with the extern and exported symbols when mapping a higher-half
@@ -23,8 +27,8 @@ MAX_MEM: equ 512
2327
[GLOBAL mb_info_addr]
2428
; functions from other parts of rustubs
2529
[EXTERN _entry]
26-
[EXTERN ___BSS_START__]
27-
[EXTERN ___BSS_END__]
30+
[EXTERN ___BSS_PM_START__]
31+
[EXTERN ___BSS_PM_END__]
2832

2933
[SECTION .text]
3034

@@ -68,16 +72,16 @@ setup_paging:
6872
; zero out the initial page tables (2 pages in total)
6973
mov edi, pml4
7074
clear_pt:
71-
mov byte [edi], 0
72-
inc edi
75+
mov dword [edi], 0
76+
add edi, 4
7377
cmp edi, pt_end
74-
jne clear_pt
78+
jl clear_pt
7579

7680
; Provisional identical page mapping, using 1G huge page, therefore only 2
7781
; table levels needed. see docs/x86_paging.txt
7882

7983
; PML4 (Page Map Level 4 / 1st level)
80-
mov eax, pdp
84+
mov eax, pdp0
8185
or eax, 0xf
8286
mov dword [pml4+0], eax
8387
mov dword [pml4+4], 0
@@ -89,8 +93,8 @@ fill_tables2:
8993
; fill one single PDP table, with 1G pages, 512 PDPE maps to 512 GB
9094
cmp ecx, MAX_MEM
9195
je fill_tables2_done
92-
mov dword [pdp + 8*ecx + 0], eax ; low bytes
93-
mov dword [pdp + 8*ecx + 4], ebx ; high bytes
96+
mov dword [pdp0 + 8*ecx + 0], eax ; low bytes
97+
mov dword [pdp0 + 8*ecx + 4], ebx ; high bytes
9498
add eax, 0x40000000 ; 1G per page
9599
adc ebx, 0 ; overflow? -> increment higher-order half of the address
96100
inc ecx
@@ -115,32 +119,74 @@ activate_long_mode:
115119
; jump to 64-bit code segment -> full activation of Long Mode
116120
jmp 2 * 0x8 : longmode_start
117121

122+
123+
; =====================================================================
124+
; MUST NOT USE ANY 64 BIT SYMBOLS BEFORE THIS POINT!
125+
; may include:
126+
; - symbols defined in 64 bit code below, if mapped to higher memory (VA)
127+
; - all symbols exported from rust code or linker script
128+
; =====================================================================
129+
118130
[BITS 64]
119-
; system start, part 2 (in 64-bit Long Mode)
120131
longmode_start:
121-
mov rdi, ___BSS_START__
132+
; now we set the pagetables for higher half memory
133+
; since we have Provisional paging now, why not using 64bit code?
134+
mov eax, pdp1
135+
or eax, 0xf
136+
mov dword [pml4+256], eax
137+
mov dword [pml4+256+4], 0
138+
; PDPE flags, see above
139+
140+
; entry 0~63 is an identical mapping with offset 0x8000_0000_0000
141+
; clear the BSS section before going to rust code
142+
; TODO this should not be executable
143+
mov rax, 0x0
144+
or rax, 0x87
145+
mov rdi, 0
146+
fill_kvma1:
147+
mov qword [pdp1 + 8*rdi], rax
148+
inc rdi
149+
add rax, 0x40000000
150+
cmp rdi, 64
151+
jne fill_kvma1
152+
153+
; entry 64~127 is a hole (also some sort of protection)
154+
; entry 128~191 are mapping of the kernel image itself
155+
mov rax, 0x0
156+
or rax, 0x87
157+
mov rdi, 128
158+
fill_kvma2:
159+
mov qword [pdp1 + 8*rdi], rax
160+
inc rdi
161+
add rax, 0x40000000
162+
cmp rdi, 192
163+
jne fill_kvma2
164+
; done :-)
165+
166+
; clear BSS section for the rust code.
167+
mov rdi, ___BSS_PM_START__
122168
clear_bss:
123169
mov byte [rdi], 0
124170
inc rdi
125-
cmp rdi, ___BSS_END__
171+
cmp rdi, ___BSS_PM_END__
126172
jne clear_bss
127-
fninit ; activate FPU
128-
129-
init_sse:
130-
; init SSE
131-
; NOTE: must NOT use sse target features for rust compiler, if sse not enabled here.
132-
;mov rax, cr0
133-
;and rax, ~(1 << 2) ;clear coprocessor emulation CR0.EM
134-
;or rax, 1 << 1 ;set coprocessor monitoring CR0.MP
135-
;mov cr0, rax
136-
;mov rax, cr4
137-
;or rax, 3 << 9 ;set CR4.OSFXSR and CR4.OSXMMEXCPT at the same time
138-
;mov cr4, rax
139-
140-
call _entry ; call the OS kernel's rust part.
141-
cli ; Usually we should not get here.
173+
; enable FPU
174+
fninit
175+
176+
; NOTE: must NOT use sse target features for rust compiler, if sse not
177+
; enabled here.
178+
179+
; finally go to the rust code!
180+
call _entry
181+
; should not reach below
182+
cli
142183
hlt
143184

185+
; =====================================================================
186+
; data sections they should all have VAs identical to their PAs
187+
; so we map these symbols differently than those generated by rust code
188+
; =====================================================================
189+
144190
[SECTION .data]
145191

146192
gdt:
@@ -195,12 +241,21 @@ init_stack:
195241

196242
[SECTION .global_pagetable]
197243

198-
244+
; create initial page tables wrt. the memory layout
245+
; we use entry 0 and 256 of the PML4 table
246+
; the whole of the first first pdp table (512G)
247+
; and entry 0, 2 of the second pdp table
248+
; all pages here are 1 GiB huge pages
199249
pml4:
200250
resb 4096
201251
alignb 4096
202-
203-
pdp:
252+
; the first PDP covers the lower 512GiB memory
253+
pdp0:
254+
resb 4096
255+
alignb 4096
256+
; pdp1 does the same but in higher half memory with offset
257+
; 0xffff_8000_0000_0000, i.e. the 256th entry of pml4
258+
pdp1:
204259
resb 4096
205260
alignb 4096
206261
pt_end:

defs/x86_64-linker.ld

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ SECTIONS
3030
header_end = .;
3131
}
3232

33-
PROVIDE (___KERNEL_START__ = .);
33+
PROVIDE (___KERNEL_PM_START__ = .);
3434
.text :
3535
{
3636
*(".text")
@@ -71,10 +71,10 @@ SECTIONS
7171

7272
.bss :
7373
{
74-
PROVIDE (___BSS_START__ = .);
74+
PROVIDE (___BSS_PM_START__ = .);
7575
*(".bss")
7676
*(".bss.*")
77-
PROVIDE (___BSS_END__ = .);
77+
PROVIDE (___BSS_PM_END__ = .);
7878
}
7979

8080
/* global page table for 64-bit long mode */
@@ -95,5 +95,5 @@ SECTIONS
9595
*("..global_free_page_stack")
9696
}
9797
. = ALIGN(4096);
98-
PROVIDE (___KERNEL_END__ = .);
98+
PROVIDE (___KERNEL_PM_END__ = .);
9999
}

src/defs.rs

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,25 @@
11
// exported symbols from asm/linker.
22
// They are always unsafe.
33
extern "C" {
4-
fn ___KERNEL_START__();
5-
fn ___KERNEL_END__();
6-
fn ___BSS_START__();
7-
fn ___BSS_END__();
4+
fn ___KERNEL_PM_START__();
5+
fn ___KERNEL_PM_END__();
6+
fn ___BSS_PM_START__();
7+
fn ___BSS_PM_END__();
88
}
99

1010
pub fn pmap_kernel_start() -> u64 {
11-
return ___KERNEL_START__ as u64;
11+
return ___KERNEL_PM_START__ as u64;
1212
}
1313

1414
pub fn pmap_kernel_end() -> u64 {
15-
return ___KERNEL_END__ as u64;
15+
return ___KERNEL_PM_END__ as u64;
1616
}
1717
pub fn pmap_bss_start() -> u64 {
18-
return ___BSS_START__ as u64;
18+
return ___BSS_PM_START__ as u64;
1919
}
2020

2121
pub fn pmap_bss_end() -> u64 {
22-
return ___BSS_END__ as u64;
22+
return ___BSS_PM_END__ as u64;
2323
}
2424

2525
pub fn roundup_4k(addr: u64) -> u64 {

0 commit comments

Comments
 (0)