Commit de806024 authored by Colin Finck's avatar Colin Finck
Browse files

Remove the C version of HermitCore and let the Rust version stand on its own feet.

* Stub out all official syscalls in syscall.rs.
* Linking against LwIP and libpthread currently needs more exports of the C version, which have been moved to dummies.rs.
  They can hopefully be replaced by official syscalls in the future.
* Supporting Go user programs needs the exported variadic function makecontext().
  This cannot be implemented in Rust yet. However, the implementation of the HermitCore C version has been moved into an
  independent library libgosupport.
* libkern is required for LwIP, so build it again.
parent 9af1cea2
[submodule "lwip"]
path = lwip
url = https://github.com/RWTH-OS/LwIP.git
branch = hermit
url = https://github.com/ColinFinck/LwIP.git
branch = path2rs
[submodule "usr/libomp"]
path = usr/libomp
url = https://github.com/RWTH-OS/libomp_oss.git
......
cmake_minimum_required(VERSION 3.7)
include(../../cmake/HermitCore.cmake)
project(arch_x86_kernel C ASM_NASM)
set_parent(X86_KERNEL_TARGET ${PROJECT_NAME})
set_parent(X86_KERNEL_ASM_TARGET ${X86_KERNEL_TARGET}_asm)
set_parent(X86_KERNEL_C_TARGET ${X86_KERNEL_TARGET}_c)
add_custom_target(${X86_KERNEL_TARGET})
# compiling kernel code here
add_definitions(-D__KERNEL__)
### ASM sources ###
add_library(${X86_KERNEL_ASM_TARGET} OBJECT
kernel/entry.asm
libkern/string.asm)
# HACK: We need to post-process the objects by running elfedit on them, but
# there is currently no way to get the list of objects out of CMake
# except for $<TARGET_OBJECTS:tgt>, which only works with add_library()
# and add_executable().
# So predict path to objects and add custom commands that depend on
# the asm target.
#
# Upstream issue: https://gitlab.kitware.com/cmake/cmake/issues/15226
#
set(_BUILD_DIR "${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_FILES_DIRECTORY}")
set(_BUILD_DIR "${_BUILD_DIR}/${X86_KERNEL_ASM_TARGET}.dir")
get_target_property(ASM_SOURCES ${X86_KERNEL_ASM_TARGET} SOURCES)
foreach(SOURCE ${ASM_SOURCES})
set(OBJECT "${SOURCE}.obj")
set(OBJECT_PATH "${_BUILD_DIR}/${OBJECT}")
# slash (/) not allowed in target names
string(REPLACE "/" "-"
OBJECT_TARGET_NAME
"${OBJECT}")
add_custom_target("${OBJECT_TARGET_NAME}"
COMMAND
${CMAKE_ELFEDIT} --output-osabi HermitCore ${OBJECT_PATH}
DEPENDS
${X86_KERNEL_ASM_TARGET})
# make main target depend on this
add_dependencies(${PROJECT_NAME} ${OBJECT_TARGET_NAME})
endforeach()
### C sources ###
file(GLOB KERNEL_SOURCES "kernel/*.c")
file(GLOB MM_SOURCES "mm/*.c")
# add boot.h as source to mark dependency boot.asm -> boot.h -> apic.c
add_library(${X86_KERNEL_C_TARGET} OBJECT
${KERNEL_SOURCES} ${MM_SOURCES}
${GENERATED_CONFIG_DIR}/hermit/boot.h)
target_include_directories(${X86_KERNEL_C_TARGET} BEFORE
PUBLIC ${HERMIT_KERNEL_INCLUDES}
PRIVATE ${GENERATED_CONFIG_DIR})
target_compile_options(${X86_KERNEL_C_TARGET}
PRIVATE ${HERMIT_KERNEL_FLAGS})
# assemble boot.asm and dump to C-array in boot.h
add_custom_command(
OUTPUT
${GENERATED_CONFIG_DIR}/hermit/boot.h
DEPENDS
kernel/boot.asm
COMMAND
echo "static const uint8_t boot_code[] = {" > boot.h
COMMAND
nasm -f bin -o boot.bin ${CMAKE_CURRENT_LIST_DIR}/kernel/boot.asm
COMMAND
hexdump -v -e "7/1 \"0x%02X, \" 1/1 \" 0x%02X,\\n\"" boot.bin >> boot.h
COMMAND
echo "};" >> boot.h
WORKING_DIRECTORY
${GENERATED_CONFIG_DIR}/hermit/
VERBATIM USES_TERMINAL)
This diff is collapsed.
; Copyright 2010-2016 Stefan Lankes, RWTH Aachen University
; All rights reserved.
;
; Redistribution and use in source and binary forms, with or without
; modification, are permitted provided that the following conditions are met:
; * Redistributions of source code must retain the above copyright
; notice, this list of conditions and the following disclaimer.
; * Redistributions in binary form must reproduce the above copyright
; notice, this list of conditions and the following disclaimer in the
; documentation and/or other materials provided with the distribution.
; * Neither the name of the University nor the names of its contributors
; may be used to endorse or promote products derived from this software
; without specific prior written permission.
;
; THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
; ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
; WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
; DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
; DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
; (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
; ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
; (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
; SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
;
; This is the kernel's entry point for the application processors.
; HermitCore switches to the protected mode and jump to its kernel.
; This trampline code is only used by the HemritCore's single kernel version.
KERNEL_STACK_SIZE equ 0x100
kernel_start equ 0x800000
[BITS 16]
SECTION .text
GLOBAL _start
ORG 0x8000
_start:
cli
lgdt [gdtr]
; switch to protected mode by setting PE bit
mov eax, cr0
or al, 0x1
mov cr0, eax
; far jump to the 32bit code
jmp dword codesel : _pmstart
[BITS 32]
ALIGN 4
_pmstart:
xor eax, eax
mov ax, datasel
mov ds, ax
mov es, ax
mov fs, ax
mov gs, ax
mov ss, ax
mov esp, boot_stack+KERNEL_STACK_SIZE-16
jmp short stublet
jmp $
; GDT for the protected mode
ALIGN 4
gdtr: ; descritor table
dw gdt_end-gdt-1 ; limit
dd gdt ; base adresse
gdt:
dd 0,0 ; null descriptor
codesel equ $-gdt
dw 0xFFFF ; segment size 0..15
dw 0x0000 ; segment address 0..15
db 0x00 ; segment address 16..23
db 0x9A ; access permissions und type
db 0xCF ; additional information and segment size 16...19
db 0x00 ; segment address 24..31
datasel equ $-gdt
dw 0xFFFF ; segment size 0..15
dw 0x0000 ; segment address 0..15
db 0x00 ; segment address 16..23
db 0x92 ; access permissions and type
db 0xCF ; additional informationen and degment size 16...19
db 0x00 ; segment address 24..31
gdt_end:
ALIGN 4
GDTR64:
dw GDT64_end - GDT64 - 1 ; Limit.
dq GDT64 ; Base.
; 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 10011010b ; 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).
GDT64_end:
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.
;
; HermitCore's boot processor map its kernel into
; the address space of this trampoline code.
; => more information in apic.c
cpu_init:
; 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, 0xDEADBEAF
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
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 [GDTR64] ; Load the 64-bit global descriptor table.
mov ax, GDT64.Data
mov ss, ax
mov ds, ax
mov es, ax
jmp GDT64.Code:start64 ; Set the code segment and enter 64-bit long mode.
[BITS 64]
ALIGN 8
start64:
push kernel_start
ret
ALIGN 16
global boot_stack
boot_stack:
TIMES (KERNEL_STACK_SIZE) DB 0xcd
; Copyright (c) 2010-2017 Stefan Lankes, RWTH Aachen University
; 2017 Colin Finck, RWTH Aachen University
;
; MIT License
;
; Permission is hereby granted, free of charge, to any person obtaining
; a copy of this software and associated documentation files (the
; "Software"), to deal in the Software without restriction, including
; without limitation the rights to use, copy, modify, merge, publish,
; distribute, sublicense, and/or sell copies of the Software, and to
; permit persons to whom the Software is furnished to do so, subject to
; the following conditions:
;
; The above copyright notice and this permission notice shall be
; included in all copies or substantial portions of the Software.
;
; THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
; EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
; MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
; NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
; LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
; OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
; WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
; This is the kernel's entry point. We could either call main here,
; or we can use this to setup the stack or other nice stuff, like
; perhaps setting up the GDT and segments. Please note that interrupts
; are disabled at this point: More on interrupts later!
%include "hermit/config.asm"
[BITS 64]
extern kernel_start ; defined in linker script
MSR_FS_BASE equ 0xc0000100
; We use a special name to map this section at the begin of our kernel
; => Multiboot expects its magic number at the beginning of the kernel.
SECTION .mboot
global _start
_start:
jmp start64
align 4
global base
global limit
global cpu_freq
global boot_processor
global cpu_online
global possible_cpus
global current_boot_id
global isle
global possible_isles
global phy_rcce_internals
global phy_isle_locks
global heap_phy_start_address
global header_phy_start_address
global heap_start_address
global header_start_address
global heap_size
global header_size
global disable_x2apic
global mb_info
global hbmem_base
global hbmem_size
global uhyve
global image_size
global uartport
global cmdline
global cmdsize
global hcip
global hcgateway
global hcmask
base dq 0
limit dq 0
cpu_freq dd 0
boot_processor dd -1
cpu_online dd 0
possible_cpus dd 0
phy_rcce_internals dq 0
current_boot_id dd 0
isle dd -1
image_size dq 0
phy_isle_locks dq 0
heap_phy_start_address dq 0
header_phy_start_address dq 0
heap_size dd 0
header_size dd 0
possible_isles dd 1
heap_start_address dq 0
header_start_address dq 0
disable_x2apic dd 1
single_kernel dd 1
mb_info dq 0
hbmem_base dq 0
hbmem_size dq 0
uhyve dd 0
uartport dq 0
cmdline dq 0
cmdsize dq 0
hcip db 10,0,5,2
hcgateway db 10,0,5,1
hcmask db 255,255,255,0
; Bootstrap page tables are used during the initialization.
align 4096
boot_pml4:
DQ boot_pdpt + 0x27 ; PG_PRESENT | PG_RW | PG_USER | PG_ACCESSED
times 510 DQ 0 ; PAGE_MAP_ENTRIES - 2
DQ boot_pml4 + 0x223 ; PG_PRESENT | PG_RW | PG_ACCESSED | PG_SELF (self-reference)
boot_pdpt:
DQ boot_pgd + 0x23 ; PG_PRESENT | PG_RW | PG_ACCESSED
times 510 DQ 0 ; PAGE_MAP_ENTRIES - 2
DQ boot_pml4 + 0x223 ; PG_PRESENT | PG_RW | PG_ACCESSED | PG_SELF (self-reference)
boot_pgd:
DQ boot_pgt + 0x23 ; PG_PRESENT | PG_RW | PG_ACCESSED
times 510 DQ 0 ; PAGE_MAP_ENTRIES - 2
DQ boot_pml4 + 0x223 ; PG_PRESENT | PG_RW | PG_ACCESSED | PG_SELF (self-reference)
boot_pgt:
times 512 DQ 0
SECTION .ktext
align 4
start64:
; reset registers to kill any stale realmode selectors
mov eax, 0x10
mov ds, eax
mov ss, eax
mov es, eax
xor eax, eax
mov fs, eax
mov gs, eax
; clear DF flag => default value by entering a function
; => see ABI
cld
xor rax, rax
mov eax, DWORD [cpu_online]
cmp eax, 0
jne Lno_pml4_init
; store pointer to the multiboot information
mov [mb_info], QWORD rdx
;
; 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, 0xA3 ; PG_GLOBAL isn't required because HermitCore is a single-address space OS
xor rcx, rcx
mov rsi, 510*0x200000
sub rsi, kernel_start
mov r11, QWORD [image_size]
Lremap:
mov QWORD [rdi], rax
add rax, 0x200000
add rcx, 0x200000
add rdi, 8
; note: the whole code segement has to fit in the first pgd
cmp rcx, rsi
jnl Lno_pml4_init
cmp rcx, r11
jl Lremap
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
%if MAX_CORES > 1
mov eax, DWORD [cpu_online]
cmp eax, 0
jne Lsmp_main
%endif
; set default stack pointer
mov rsp, boot_stack
add rsp, KERNEL_STACK_SIZE-16
xor rax, rax
mov eax, [boot_processor]
cmp eax, -1
je L1
imul eax, KERNEL_STACK_SIZE
add rsp, rax
L1:
mov rbp, rsp
; jump to the boot processors' entry point
extern boot_processor_main
call boot_processor_main
jmp $
%if MAX_CORES > 1
ALIGN 64
Lsmp_main:
xor rax, rax
mov eax, DWORD [current_boot_id]
; set default stack pointer
imul rax, KERNEL_STACK_SIZE
add rax, boot_stack
add rax, KERNEL_STACK_SIZE-16
mov rsp, rax
mov rbp, rsp
extern application_processor_main
call application_processor_main
jmp $
%endif
; Required for Go applications
global getcontext
align 64
getcontext:
cli
; save general purpose regsiters
mov QWORD [rdi + 0x00], r15
mov QWORD [rdi + 0x08], r14
mov QWORD [rdi + 0x10], r13
mov QWORD [rdi + 0x18], r12
mov QWORD [rdi + 0x20], r9
mov QWORD [rdi + 0x28], r8
mov QWORD [rdi + 0x30], rdi
mov QWORD [rdi + 0x38], rsi
mov QWORD [rdi + 0x40], rbp
mov QWORD [rdi + 0x48], rbx
mov QWORD [rdi + 0x50], rdx
mov QWORD [rdi + 0x58], rcx
lea rax, [rsp + 0x08]
mov QWORD [rdi + 0x60], rax
mov rax, QWORD [rsp]
mov QWORD [rdi + 0x68], rax
; save FPU state
fnstenv [rdi + 0x74]
lea rax, [rdi + 0x70]
stmxcsr [rax]
xor rax, rax
sti
ret
; Required for Go applications
global setcontext
align 64
setcontext:
cli
; restore FPU state
fldenv [rdi + 0x74]
lea rax, [rdi + 0x70]
ldmxcsr [rax]
; restore general purpose registers
mov r15, QWORD [rdi + 0x00]
mov r14, QWORD [rdi + 0x08]
mov r13, QWORD [rdi + 0x10]
mov r12, QWORD [rdi + 0x18]
mov r9, QWORD [rdi + 0x20]
mov r8, QWORD [rdi + 0x28]
mov rdi, QWORD [rdi + 0x30]
mov rsi, QWORD [rdi + 0x38]
mov rbp, QWORD [rdi + 0x40]
mov rbx, QWORD [rdi + 0x48]
mov rdx, QWORD [rdi + 0x50]
mov rcx, QWORD [rdi + 0x58]
mov rsp, QWORD [rdi + 0x60]
push QWORD [rdi + 0x68]
xor rax, rax
sti
ret
; Required for Go applications
global __startcontext
align 64
__startcontext:
mov rsp, rbx