1
0
Fork 0
mirror of https://github.com/hermitcore/libhermit.git synced 2025-03-09 00:00:03 +01:00

enable to boot a kernel per NUMA node

- redesign of the startup code => moving of 32bit stuff to the
  trampoline code
- create entry for each numa node in /sys/hermit
This commit is contained in:
Stefan Lankes 2015-07-27 21:50:29 +02:00
parent 00a5719142
commit 787b2a0634
4 changed files with 247 additions and 291 deletions

1
hermit/.gitignore vendored
View file

@ -5,7 +5,6 @@
*.elf32
*.sym
*.bin
*.hex
documentation/html/
include/hermit/config.inc
newlib/examples/hello

View file

@ -1,5 +1,5 @@
; Copyright (c) 2010, Stefan Lankes, RWTH Aachen University
; Copyright (c) 2010-2015, Stefan Lankes, RWTH Aachen University
; All rights reserved.
;
; Redistribution and use in source and binary forms, with or without
@ -31,7 +31,7 @@
%include "config.inc"
[BITS 32]
[BITS 64]
extern kernel_start ; defined in linker script
extern kernel_end
@ -41,288 +41,22 @@ extern kernel_end
SECTION .mboot
global start
start:
; do we have a multiboot info? => no relocation required
cmp ebx, 0
je short Lnoreset
mov ebp, kernel_start
Lnoreset:
; relocate jmp
mov eax, stublet
sub eax, kernel_start
add eax, ebp ; ebp contains the physical address of the kernel
jmp eax
jmp start64
; This part MUST be 4 byte aligned, so we solve that issue using 'ALIGN 4'.
align 4
mboot:
; Multiboot macros to make a few lines more readable later
MULTIBOOT_PAGE_ALIGN equ (1 << 0)
MULTIBOOT_MEMORY_INFO equ (1 << 1)
MULTIBOOT_HEADER_MAGIC equ 0x1BADB002
MULTIBOOT_HEADER_FLAGS equ MULTIBOOT_PAGE_ALIGN | MULTIBOOT_MEMORY_INFO
MULTIBOOT_CHECKSUM equ -(MULTIBOOT_HEADER_MAGIC + MULTIBOOT_HEADER_FLAGS)
; This is the GRUB Multiboot header. A boot signature
dd MULTIBOOT_HEADER_MAGIC
dd MULTIBOOT_HEADER_FLAGS
dd MULTIBOOT_CHECKSUM
dd 0, 0, 0, 0, 0 ; address fields
dd 0, 0, 0, 0,
global base
global limit
global cpu_freq
global boot_processor
global cpu_online
base dd kernel_start
limit dd 0
base dq 0
limit dq 0
cpu_freq dd 0
boot_processor dd -1
cpu_online dd 0
align 4
; we need already a valid GDT to switch in the 64bit modus
GDT64: ; Global Descriptor Table (64-bit).
.Null: equ $ - GDT64 ; The null descriptor.
dw 0 ; Limit (low).
dw 0 ; Base (low).
db 0 ; Base (middle)
db 0 ; Access.
db 0 ; Granularity.
db 0 ; Base (high).
.Code: equ $ - GDT64 ; The code descriptor.
dw 0 ; Limit (low).
dw 0 ; Base (low).
db 0 ; Base (middle)
db 10011000b ; Access.
db 00100000b ; Granularity.
db 0 ; Base (high).
.Data: equ $ - GDT64 ; The data descriptor.
dw 0 ; Limit (low).
dw 0 ; Base (low).
db 0 ; Base (middle)
db 10010010b ; Access.
db 00000000b ; Granularity.
db 0 ; Base (high).
.Pointer: ; The GDT-pointer.
dw $ - GDT64 - 1 ; Limit.
dq GDT64 ; Base.
SECTION .text
align 4
stublet:
; Relocate stack pointer
mov eax, boot_stack
sub eax, kernel_start
add eax, ebp
mov esp, eax
add esp, KERNEL_STACK_SIZE - 16
mov eax, boot_processor
sub eax, kernel_start
add eax, ebp
mov eax, DWORD [eax]
cmp eax, -1
je L0
imul eax, KERNEL_STACK_SIZE
add esp, eax
L0:
; Interpret multiboot information
mov eax, mb_info
sub eax, kernel_start
add eax, ebp
mov DWORD [eax], ebx
; This will set up the x86 control registers:
; Caching and the floating point unit are enabled
; Bootstrap page tables are loaded and page size
; extensions (huge pages) enabled.
cpu_init:
push edi
; do we have to relocate / to intialize the page tables?
; only the boot_processor have to do it
mov eax, cpu_online
sub eax, kernel_start
add eax, ebp
mov eax, DWORD [eax]
cmp eax, 0
je short Lrelocate
mov eax, Lmap_kernel
sub eax, kernel_start
add eax, ebp ; ebp contains the physical address of the kernel
jmp eax
Lrelocate:
; relocate page tables
mov edi, boot_pml4
sub edi, kernel_start
add edi, ebp
mov eax, DWORD [edi]
sub eax, kernel_start
add eax, ebp
mov DWORD [edi], eax
mov eax, DWORD [edi+511*8]
sub eax, kernel_start
add eax, ebp
mov DWORD [edi+511*8], eax
mov edi, boot_pdpt
sub edi, kernel_start
add edi, ebp
mov eax, DWORD [edi]
sub eax, kernel_start
add eax, ebp
mov DWORD [edi], eax
mov eax, DWORD [edi+511*8]
sub eax, kernel_start
add eax, ebp
mov DWORD [edi+511*8], eax
mov edi, boot_pgd
sub edi, kernel_start
add edi, ebp
mov eax, DWORD [edi]
sub eax, kernel_start
add eax, ebp
mov DWORD [edi], eax
mov eax, DWORD [edi+511*8]
sub eax, kernel_start
add eax, ebp
mov DWORD [edi+511*8], eax
; initialize page tables
; map vga 1:1
%ifdef CONFIG_VGA
mov eax, VIDEO_MEM_ADDR ; map vga
and eax, 0xFFFFF000 ; page align lower half
mov edi, eax
shr edi, 9 ; (edi >> 12) * 8 (index for boot_pgt)
add edi, boot_pgt
sub edi, kernel_start
add edi, ebp
or eax, 0x113 ; set present, global, writable and cache disable bits
mov DWORD [edi], eax
%endif
; map multiboot info 1:1
mov eax, mb_info ; map multiboot info
sub eax, kernel_start
add eax, ebp
mov eax, DWORD [eax]
cmp eax, 0
je short Lno_mbinfo
and eax, 0xFFFFF000 ; page align lower half
mov edi, eax
shr edi, 9 ; (edi >> 12) * 8 (index for boot_pgt)
add edi, boot_pgt
sub edi, kernel_start
add edi, ebp
or eax, 0x101 ; set present and global bits
mov DWORD [edi], eax
Lno_mbinfo:
; map kernel at link address, use a page size of 2MB
mov eax, ebp
and eax, 0xFFE00000
mov edi, kernel_start
and edi, 0xFFE00000
shr edi, 18 ; (edi >> 21) * 8 (index for boot_pgd)
add edi, boot_pgd
sub edi, kernel_start
add edi, ebp
or eax, 0x183
mov DWORD [edi], eax
Lmap_kernel:
cmp ebp, kernel_start
je Lno_remap
; map kernel 1:1, use a page size of 2MB
mov eax, ebp
and eax, 0xFFE00000
mov edi, eax
shr edi, 18 ; (edi >> 21) * 8 (index for boot_pgd)
add edi, boot_pgd
sub edi, kernel_start
add edi, ebp
or eax, 0x183
mov DWORD [edi], eax
Lno_remap:
pop edi
; check for long mode
; do we have the instruction cpuid?
pushfd
pop eax
mov ecx, eax
xor eax, 1 << 21
push eax
popfd
pushfd
pop eax
push ecx
popfd
xor eax, ecx
jz $ ; there is no long mode
; cpuid > 0x80000000?
mov eax, 0x80000000
cpuid
cmp eax, 0x80000001
jb $ ; It is less, there is no long mode.
; do we have a long mode?
mov eax, 0x80000001
cpuid
test edx, 1 << 29 ; Test if the LM-bit, which is bit 29, is set in the D-register.
jz $ ; They aren't, there is no long mode.
; we need to enable PAE modus
mov eax, cr4
or eax, 1 << 5
mov cr4, eax
; switch to the compatibility mode (which is part of long mode)
mov ecx, 0xC0000080
rdmsr
or eax, 1 << 8
wrmsr
; Set CR3
mov eax, boot_pml4
sub eax, kernel_start
add eax, ebp
or eax, (1 << 0) ; set present bit
mov cr3, eax
; Set CR4 (PAE is already set)
mov eax, cr4
and eax, 0xfffbf9ff ; disable SSE
or eax, (1 << 7) ; enable PGE
or eax, (1 << 20) ; enable SMEP
mov cr4, eax
; Set CR0 (PM-bit is already set)
mov eax, cr0
and eax, ~(1 << 2) ; disable FPU emulation
or eax, (1 << 1) ; enable FPU montitoring
and eax, ~(1 << 30) ; enable caching
and eax, ~(1 << 29) ; disable write through caching
and eax, ~(1 << 16) ; allow kernel write access to read-only pages
or eax, (1 << 31) ; enable paging
mov cr0, eax
lgdt [GDT64.Pointer] ; Load the 64-bit global descriptor table.
jmp GDT64.Code:start64 ; Set the code segment and enter 64-bit long mode.
[BITS 64]
start64:
; initialize segment registers
mov ax, 0x00
@ -333,16 +67,60 @@ start64:
mov fs, ax
mov gs, ax
cmp ebp, kernel_start
je Lno_unmap
; unmap temporary 1:1 mapping of the kernel
mov edi, ebp
shr edi, 18 ; (edi >> 21) * 8 (index for boot_pgd)
add edi, boot_pgd
mov DWORD [edi], 0
xor rdi, rdi
mov eax, DWORD [cpu_online]
cmp eax, 0
jne Lno_pml4_init
; relocate page tables
mov rdi, boot_pml4
mov rax, QWORD [rdi]
sub rax, kernel_start
add rax, [base]
mov QWORD [rdi], rax
mov rax, QWORD [rdi+511*8]
sub rax, kernel_start
add rax, [base]
mov QWORD [rdi+511*8], rax
mov rdi, boot_pdpt
mov rax, QWORD [rdi]
sub rax, kernel_start
add rax, [base]
mov QWORD [rdi], rax
mov rax, QWORD [rdi+511*8]
sub rax, kernel_start
add rax, [base]
mov QWORD [rdi+511*8], rax
mov rdi, boot_pgd
mov rax, QWORD [rdi]
sub rax, kernel_start
add rax, [base]
mov QWORD [rdi], rax
mov rax, QWORD [rdi+511*8]
sub rax, kernel_start
add rax, [base]
mov QWORD [rdi+511*8], rax
; remap kernel
mov rdi, kernel_start
shr rdi, 18 ; (edi >> 21) * 8 (index for boot_pgd)
add rdi, boot_pgd
mov rax, [base]
or rax, 0x183
mov QWORD [rdi], rax
Lno_pml4_init:
; Set CR3
mov rax, boot_pml4
sub rax, kernel_start
add rax, [base]
or rax, (1 << 0) ; set present bit
mov cr3, rax
Lno_unmap:
%if MAX_CORES > 1
mov eax, DWORD [cpu_online]
cmp eax, 0

View file

@ -21,15 +21,17 @@ endif
default: all
all: init.hex make_initrd initrd.o
all: init.h make_initrd initrd.o
init.bin: init.asm
@echo [NASM] $@
$Q$(NASM) $(NASMFLAGS) -o $@ $<
init.hex: init.bin
init.h: init.bin
@echo [HEXDUMP] $@
$Q$(HEXDUMP) -v -e '"0x" 1/1 "%02X" ", "' $< > $@
$Q@echo "static const uint8_t boot_code[] = {" > $@
$Q$(HEXDUMP) -v -e '"0x" 1/1 "%02X" ", "' $< >> $@
$Q@echo "};" >> $@
initrd.o: initrd.S initrd.img
@echo [CC] Build initrd as object file
@ -44,7 +46,7 @@ make_initrd: make_initrd.o
clean:
@echo Cleaning tools
$Q$(RM) -rf *.o *~ *.bin *.obj *.hex
$Q$(RM) -rf *.o *~ *.bin *.obj *.h
veryclean: clean

View file

@ -26,6 +26,9 @@
; This is the kernel's entry point for the application processors.
; We switch to the protected mode and jump to HermitCore's kernel.
KERNEL_STACK_SIZE equ 0x100
kernel_start equ 0x200000
[BITS 16]
SECTION .text
GLOBAL _start
@ -53,14 +56,12 @@ _pmstart:
mov gs, ax
mov ss, ax
xor ebx, ebx ; invalid multiboot address
mov esp, -16
mov ebp, 0x00 ; dummy value
push DWORD 0x00 ; dummy value
push DWORD 0x00 ; dummy value
jmp codesel : 0x00 ; dummy value
mov esp, boot_stack+KERNEL_STACK_SIZE-16
mov ebp, 0x00 ; dummy value
jmp short stublet
jmp $
; GDT for the protected mode
ALIGN 4
gdtr: ; descritor table
dw gdt_end-gdt-1 ; limit
@ -82,3 +83,179 @@ datasel equ $-gdt
db 0xCF ; additional informationen and degment size 16...19
db 0x00 ; segment address 24..31
gdt_end:
ALIGN 4
; we need a new GDT to switch in the 64bit modus
GDT64: ; Global Descriptor Table (64-bit).
.Null: equ $ - GDT64 ; The null descriptor.
dw 0 ; Limit (low).
dw 0 ; Base (low).
db 0 ; Base (middle)
db 0 ; Access.
db 0 ; Granularity.
db 0 ; Base (high).
.Code: equ $ - GDT64 ; The code descriptor.
dw 0 ; Limit (low).
dw 0 ; Base (low).
db 0 ; Base (middle)
db 10011000b ; Access.
db 00100000b ; Granularity.
db 0 ; Base (high).
.Data: equ $ - GDT64 ; The data descriptor.
dw 0 ; Limit (low).
dw 0 ; Base (low).
db 0 ; Base (middle)
db 10010010b ; Access.
db 00000000b ; Granularity.
db 0 ; Base (high).
.Pointer: ; The GDT-pointer.
dw $ - GDT64 - 1 ; Limit.
dq GDT64 ; Base.
ALIGN 4
stublet:
; This will set up the x86 control registers:
; Caching and the floating point unit are enabled
; Bootstrap page tables are loaded and page size
; extensions (huge pages) enabled.
cpu_init:
; relocate page tables
mov edi, boot_pml4
add edi, ebp
mov eax, DWORD [edi]
add eax, ebp
mov DWORD [edi], eax
mov eax, DWORD [edi+511*8]
add eax, ebp
mov DWORD [edi+511*8], eax
mov edi, boot_pdpt
add edi, ebp
mov eax, DWORD [edi]
add eax, ebp
mov DWORD [edi], eax
mov eax, DWORD [edi+511*8]
add eax, ebp
mov DWORD [edi+511*8], eax
mov edi, boot_pgd
add edi, ebp
mov eax, DWORD [edi]
add eax, ebp
mov DWORD [edi], eax
mov eax, DWORD [edi+511*8]
add eax, ebp
mov DWORD [edi+511*8], eax
; initialize page tables
; map kernel at link address, use a page size of 2M
mov eax, 0x00 ; dummy value
and eax, 0xFFE00000
mov edi, kernel_start
and edi, 0xFFE00000
shr edi, 18 ; (edi >> 21) * 8 (index for boot_pgd)
add edi, boot_pgd
add edi, ebp
or eax, 0x183
mov DWORD [edi], eax
; check for long mode
; do we have the instruction cpuid?
pushfd
pop eax
mov ecx, eax
xor eax, 1 << 21
push eax
popfd
pushfd
pop eax
push ecx
popfd
xor eax, ecx
jz $ ; there is no long mode
; cpuid > 0x80000000?
mov eax, 0x80000000
cpuid
cmp eax, 0x80000001
jb $ ; It is less, there is no long mode.
; do we have a long mode?
mov eax, 0x80000001
cpuid
test edx, 1 << 29 ; Test if the LM-bit, which is bit 29, is set in the D-register.
jz $ ; They aren't, there is no long mode.
; we need to enable PAE modus
mov eax, cr4
or eax, 1 << 5
mov cr4, eax
mov ecx, 0xC0000080
rdmsr
or eax, 1 << 8
wrmsr
; Set CR3
mov eax, boot_pml4
add eax, ebp
or eax, (1 << 0) ; set present bit
mov cr3, eax
; Set CR4 (PAE is already set)
mov eax, cr4
and eax, 0xfffbf9ff ; disable SSE
or eax, (1 << 7) ; enable PGE
or eax, (1 << 20) ; enable SMEP
mov cr4, eax
; Set CR0 (PM-bit is already set)
mov eax, cr0
and eax, ~(1 << 2) ; disable FPU emulation
or eax, (1 << 1) ; enable FPU montitoring
and eax, ~(1 << 30) ; enable caching
and eax, ~(1 << 29) ; disable write through caching
and eax, ~(1 << 16) ; allow kernel write access to read-only pages
or eax, (1 << 31) ; enable paging
mov cr0, eax
lgdt [GDT64.Pointer] ; Load the 64-bit global descriptor table.
jmp GDT64.Code:start64 ; Set the code segment and enter 64-bit long mode.
[BITS 64]
ALIGN 8
start64:
mov rax, kernel_start
jmp rax
ALIGN 16
global boot_stack
boot_stack:
TIMES (KERNEL_STACK_SIZE) DB 0xcd
; Bootstrap page tables are used during the initialization.
ALIGN 4096
boot_pml4:
DQ boot_pdpt + 0x7 ; PG_PRESENT | PG_RW | PG_USER
times 510 DQ 0 ; PAGE_MAP_ENTRIES - 2
DQ boot_pml4 + 0x203 ; PG_PRESENT | PG_RW | PG_SELF (self-reference)
boot_pdpt:
DQ boot_pgd + 0x7 ; PG_PRESENT | PG_RW | PG_USER
times 510 DQ 0 ; PAGE_MAP_ENTRIES - 2
DQ boot_pml4 + 0x203 ; PG_PRESENT | PG_RW | PG_SELF (self-reference)
boot_pgd:
DQ boot_pgt + 0x7 ; PG_PRESENT | PG_RW | PG_USER
times 510 DQ 0 ; PAGE_MAP_ENTRIES - 2
DQ boot_pml4 + 0x203 ; PG_PRESENT | PG_RW | PG_SELF (self-reference)
boot_pgt:
%assign i 0
%rep 512
DQ i*0x1000 + 0x103
%assign i i+1
%endrep