2015-07-27 21:50:29 +02:00
|
|
|
; Copyright (c) 2010-2015, Stefan Lankes, RWTH Aachen University
|
2015-05-23 14:35:45 +02:00
|
|
|
; 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. 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!
|
|
|
|
|
2017-04-03 18:08:12 +02:00
|
|
|
%include "hermit/config.asm"
|
2015-05-23 14:35:45 +02:00
|
|
|
|
2015-07-27 21:50:29 +02:00
|
|
|
[BITS 64]
|
2015-05-23 14:35:45 +02:00
|
|
|
|
|
|
|
extern kernel_start ; defined in linker script
|
|
|
|
|
2015-08-09 14:29:15 +02:00
|
|
|
MSR_FS_BASE equ 0xc0000100
|
|
|
|
MSR_GS_BASE equ 0xc0000101
|
2015-09-13 14:51:25 +02:00
|
|
|
MSR_KERNEL_GS_BASE equ 0xc0000102
|
2015-08-09 14:29:15 +02:00
|
|
|
|
2015-05-23 14:35:45 +02:00
|
|
|
; 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
|
2015-12-29 02:22:41 +01:00
|
|
|
global _start
|
|
|
|
_start:
|
2015-07-27 21:50:29 +02:00
|
|
|
jmp start64
|
2015-05-23 14:35:45 +02:00
|
|
|
|
2015-07-11 00:12:59 +02:00
|
|
|
align 4
|
2015-05-23 14:35:45 +02:00
|
|
|
global base
|
|
|
|
global limit
|
2015-05-24 09:46:44 +02:00
|
|
|
global cpu_freq
|
2015-05-25 09:19:57 +02:00
|
|
|
global boot_processor
|
2015-05-31 00:30:13 +02:00
|
|
|
global cpu_online
|
2015-08-13 22:26:04 +02:00
|
|
|
global possible_cpus
|
|
|
|
global current_boot_id
|
2015-09-13 21:52:45 +02:00
|
|
|
global isle
|
2015-09-30 12:27:02 +02:00
|
|
|
global possible_isles
|
2015-10-17 12:01:46 +02:00
|
|
|
global phy_rcce_internals
|
2015-09-30 12:27:02 +02:00
|
|
|
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
|
2016-02-14 15:24:01 +01:00
|
|
|
global disable_x2apic
|
2016-08-26 23:53:22 +02:00
|
|
|
global mb_info
|
2016-10-21 00:21:01 +02:00
|
|
|
global hbmem_base
|
|
|
|
global hbmem_size
|
2017-01-16 18:47:13 +01:00
|
|
|
global uhyve
|
2017-04-18 00:26:38 +02:00
|
|
|
global image_size
|
2017-05-27 21:26:12 +02:00
|
|
|
global uartport
|
2017-05-31 22:08:21 +02:00
|
|
|
global cmdline
|
|
|
|
global cmdsize
|
2015-07-27 21:50:29 +02:00
|
|
|
base dq 0
|
|
|
|
limit dq 0
|
2015-05-24 09:46:44 +02:00
|
|
|
cpu_freq dd 0
|
2015-05-25 09:19:57 +02:00
|
|
|
boot_processor dd -1
|
2015-05-31 00:30:13 +02:00
|
|
|
cpu_online dd 0
|
2015-08-13 22:26:04 +02:00
|
|
|
possible_cpus dd 0
|
2015-10-17 12:01:46 +02:00
|
|
|
phy_rcce_internals dq 0
|
2015-08-13 22:26:04 +02:00
|
|
|
current_boot_id dd 0
|
2015-09-13 21:52:45 +02:00
|
|
|
isle dd -1
|
2015-08-19 23:13:57 +02:00
|
|
|
image_size dq 0
|
2015-09-30 12:27:02 +02:00
|
|
|
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
|
2016-02-14 15:24:01 +01:00
|
|
|
disable_x2apic dd 1
|
2016-07-25 07:55:38 +02:00
|
|
|
single_kernel dd 1
|
2016-08-26 23:53:22 +02:00
|
|
|
mb_info dq 0
|
2016-10-21 00:21:01 +02:00
|
|
|
hbmem_base dq 0
|
|
|
|
hbmem_size dq 0
|
2017-01-16 18:47:13 +01:00
|
|
|
uhyve dd 0
|
2017-05-27 21:26:12 +02:00
|
|
|
uartport dq 0
|
2017-06-16 01:33:46 +02:00
|
|
|
cmdline dq 0
|
|
|
|
cmdsize dq 0
|
2015-08-19 23:13:57 +02:00
|
|
|
|
|
|
|
; Bootstrap page tables are used during the initialization.
|
|
|
|
align 4096
|
|
|
|
boot_pml4:
|
2016-02-21 17:07:00 +01:00
|
|
|
DQ boot_pdpt + 0x27 ; PG_PRESENT | PG_RW | PG_USER | PG_ACCESSED
|
2015-08-19 23:13:57 +02:00
|
|
|
times 510 DQ 0 ; PAGE_MAP_ENTRIES - 2
|
2016-02-21 17:07:00 +01:00
|
|
|
DQ boot_pml4 + 0x223 ; PG_PRESENT | PG_RW | PG_ACCESSED | PG_SELF (self-reference)
|
2015-08-19 23:13:57 +02:00
|
|
|
boot_pdpt:
|
2016-02-21 17:07:00 +01:00
|
|
|
DQ boot_pgd + 0x23 ; PG_PRESENT | PG_RW | PG_ACCESSED
|
2015-08-19 23:13:57 +02:00
|
|
|
times 510 DQ 0 ; PAGE_MAP_ENTRIES - 2
|
2016-02-21 17:07:00 +01:00
|
|
|
DQ boot_pml4 + 0x223 ; PG_PRESENT | PG_RW | PG_ACCESSED | PG_SELF (self-reference)
|
2015-08-19 23:13:57 +02:00
|
|
|
boot_pgd:
|
2016-02-21 17:07:00 +01:00
|
|
|
DQ boot_pgt + 0x23 ; PG_PRESENT | PG_RW | PG_ACCESSED
|
2015-08-19 23:13:57 +02:00
|
|
|
times 510 DQ 0 ; PAGE_MAP_ENTRIES - 2
|
2016-02-21 17:07:00 +01:00
|
|
|
DQ boot_pml4 + 0x223 ; PG_PRESENT | PG_RW | PG_ACCESSED | PG_SELF (self-reference)
|
2015-08-19 23:13:57 +02:00
|
|
|
boot_pgt:
|
|
|
|
times 512 DQ 0
|
2015-05-23 14:35:45 +02:00
|
|
|
|
2015-12-29 02:22:41 +01:00
|
|
|
SECTION .ktext
|
2015-07-11 00:12:59 +02:00
|
|
|
align 4
|
2015-05-23 14:35:45 +02:00
|
|
|
start64:
|
2015-09-02 14:44:45 +02:00
|
|
|
; reset registers to kill any stale realmode selectors
|
2017-08-19 19:36:51 +02:00
|
|
|
mov eax, 0x10
|
2015-09-02 14:44:45 +02:00
|
|
|
mov ds, eax
|
|
|
|
mov ss, eax
|
|
|
|
mov es, eax
|
2017-08-19 19:36:51 +02:00
|
|
|
xor eax, eax
|
2015-09-02 14:44:45 +02:00
|
|
|
mov fs, eax
|
|
|
|
mov gs, eax
|
|
|
|
|
2016-05-15 07:48:30 +02:00
|
|
|
; clear DF flag => default value by entering a function
|
|
|
|
; => see ABI
|
|
|
|
cld
|
|
|
|
|
2016-07-25 07:55:38 +02:00
|
|
|
xor rax, rax
|
2015-07-27 21:50:29 +02:00
|
|
|
mov eax, DWORD [cpu_online]
|
|
|
|
cmp eax, 0
|
|
|
|
jne Lno_pml4_init
|
|
|
|
|
2017-05-20 14:00:12 +02:00
|
|
|
; store pointer to the multiboot information
|
|
|
|
mov [mb_info], QWORD rdx
|
|
|
|
|
2017-08-04 10:35:16 +02:00
|
|
|
;
|
2015-07-27 21:50:29 +02:00
|
|
|
; 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
|
2015-07-30 22:06:15 +02:00
|
|
|
|
2016-08-26 23:53:22 +02:00
|
|
|
; map multiboot info
|
|
|
|
mov rax, QWORD [mb_info]
|
|
|
|
and rax, ~0xFFF ; page align lower half
|
|
|
|
cmp rax, 0
|
|
|
|
je Lno_mbinfo
|
|
|
|
mov rdi, rax
|
|
|
|
shr rdi, 9 ; (edi >> 12) * 8 (index for boot_pgt)
|
|
|
|
add rdi, boot_pgt
|
2017-04-20 10:46:31 +02:00
|
|
|
or rax, 0x23 ; set present, accessed and writable bits
|
2016-08-26 23:53:22 +02:00
|
|
|
mov QWORD [rdi], rax
|
|
|
|
Lno_mbinfo:
|
2015-07-27 21:50:29 +02:00
|
|
|
; remap kernel
|
|
|
|
mov rdi, kernel_start
|
2016-03-20 00:41:45 +01:00
|
|
|
shr rdi, 18 ; (edi >> 21) * 8 (index for boot_pgd)
|
2015-07-27 21:50:29 +02:00
|
|
|
add rdi, boot_pgd
|
|
|
|
mov rax, [base]
|
2017-04-20 10:46:31 +02:00
|
|
|
or rax, 0xA3 ; PG_GLOBAL isn't required because HermitCore is a single-address space OS
|
2015-08-19 23:13:57 +02:00
|
|
|
xor rcx, rcx
|
2017-04-18 00:26:38 +02:00
|
|
|
mov rsi, 510*0x200000
|
|
|
|
sub rsi, kernel_start
|
2017-07-27 11:01:54 +02:00
|
|
|
mov r11, QWORD [image_size]
|
2015-08-19 23:13:57 +02:00
|
|
|
Lremap:
|
2015-07-27 21:50:29 +02:00
|
|
|
mov QWORD [rdi], rax
|
2015-08-19 23:13:57 +02:00
|
|
|
add rax, 0x200000
|
|
|
|
add rcx, 0x200000
|
|
|
|
add rdi, 8
|
2017-07-26 23:47:02 +02:00
|
|
|
; note: the whole code segement has to fit in the first pgd
|
2017-04-18 00:26:38 +02:00
|
|
|
cmp rcx, rsi
|
2017-08-03 13:50:44 +02:00
|
|
|
jnl Lno_pml4_init
|
2017-07-27 11:01:54 +02:00
|
|
|
cmp rcx, r11
|
2017-08-03 13:50:44 +02:00
|
|
|
jl Lremap
|
2015-07-27 21:50:29 +02:00
|
|
|
|
|
|
|
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
|
2015-05-24 11:23:10 +02:00
|
|
|
|
2015-07-24 21:12:05 +02:00
|
|
|
%if MAX_CORES > 1
|
2015-05-31 00:30:13 +02:00
|
|
|
mov eax, DWORD [cpu_online]
|
|
|
|
cmp eax, 0
|
|
|
|
jne Lsmp_main
|
2015-07-24 21:12:05 +02:00
|
|
|
%endif
|
2015-05-31 00:30:13 +02:00
|
|
|
|
2015-05-23 14:35:45 +02:00
|
|
|
; set default stack pointer
|
|
|
|
mov rsp, boot_stack
|
|
|
|
add rsp, KERNEL_STACK_SIZE-16
|
2015-05-31 00:30:13 +02:00
|
|
|
xor rax, rax
|
|
|
|
mov eax, [boot_processor]
|
|
|
|
cmp eax, -1
|
|
|
|
je L1
|
|
|
|
imul eax, KERNEL_STACK_SIZE
|
|
|
|
add rsp, rax
|
|
|
|
L1:
|
2015-05-24 09:46:44 +02:00
|
|
|
mov rbp, rsp
|
2015-05-23 14:35:45 +02:00
|
|
|
|
|
|
|
; jump to the boot processors's C code
|
2015-12-29 02:22:41 +01:00
|
|
|
extern hermit_main
|
|
|
|
call hermit_main
|
2015-05-23 14:35:45 +02:00
|
|
|
jmp $
|
|
|
|
|
2015-07-24 21:12:05 +02:00
|
|
|
%if MAX_CORES > 1
|
2016-08-26 19:44:02 +02:00
|
|
|
ALIGN 64
|
2015-05-31 00:30:13 +02:00
|
|
|
Lsmp_main:
|
2015-08-13 22:26:04 +02:00
|
|
|
xor rax, rax
|
|
|
|
mov eax, DWORD [current_boot_id]
|
2015-05-31 00:30:13 +02:00
|
|
|
|
|
|
|
; 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
|
2015-07-08 08:12:13 +02:00
|
|
|
|
2015-05-31 00:30:13 +02:00
|
|
|
extern smp_start
|
|
|
|
call smp_start
|
|
|
|
jmp $
|
2015-07-24 21:12:05 +02:00
|
|
|
%endif
|
2015-05-31 00:30:13 +02:00
|
|
|
|
2015-05-23 14:35:45 +02:00
|
|
|
; The first 32 interrupt service routines (ISR) entries correspond to exceptions.
|
|
|
|
; Some exceptions will push an error code onto the stack which is specific to
|
|
|
|
; the exception caused. To decrease the complexity, we handle this by pushing a
|
|
|
|
; Dummy error code of 0 onto the stack for any ISR that doesn't push an error
|
|
|
|
; code already.
|
|
|
|
;
|
|
|
|
; ISRs are registered as "Interrupt Gate".
|
|
|
|
; Therefore, the interrupt flag (IF) is already cleared.
|
|
|
|
|
|
|
|
; NASM macro which pushs also an pseudo error code
|
|
|
|
%macro isrstub_pseudo_error 1
|
|
|
|
global isr%1
|
2016-08-26 19:44:02 +02:00
|
|
|
align 64
|
2015-05-23 14:35:45 +02:00
|
|
|
isr%1:
|
2017-06-16 01:33:46 +02:00
|
|
|
push byte 0 ; pseudo error code
|
|
|
|
push byte %1
|
|
|
|
jmp common_stub
|
2015-05-23 14:35:45 +02:00
|
|
|
%endmacro
|
|
|
|
|
|
|
|
; Similar to isrstub_pseudo_error, but without pushing
|
|
|
|
; a pseudo error code => The error code is already
|
|
|
|
; on the stack.
|
|
|
|
%macro isrstub 1
|
|
|
|
global isr%1
|
2016-08-26 19:44:02 +02:00
|
|
|
align 64
|
2015-05-23 14:35:45 +02:00
|
|
|
isr%1:
|
2017-06-16 01:33:46 +02:00
|
|
|
push byte %1
|
|
|
|
jmp common_stub
|
2015-05-23 14:35:45 +02:00
|
|
|
%endmacro
|
|
|
|
|
|
|
|
; Create isr entries, where the number after the
|
|
|
|
; pseudo error code represents following interrupts:
|
|
|
|
; 0: Divide By Zero Exception
|
|
|
|
; 1: Debug Exception
|
|
|
|
; 2: Non Maskable Interrupt Exception
|
|
|
|
; 3: Int 3 Exception
|
|
|
|
; 4: INTO Exception
|
|
|
|
; 5: Out of Bounds Exception
|
|
|
|
; 6: Invalid Opcode Exception
|
|
|
|
; 7: Coprocessor Not Available Exception
|
|
|
|
%assign i 0
|
|
|
|
%rep 8
|
|
|
|
isrstub_pseudo_error i
|
|
|
|
%assign i i+1
|
|
|
|
%endrep
|
|
|
|
|
|
|
|
; 8: Double Fault Exception (With Error Code!)
|
|
|
|
isrstub 8
|
|
|
|
|
|
|
|
; 9: Coprocessor Segment Overrun Exception
|
|
|
|
isrstub_pseudo_error 9
|
|
|
|
|
|
|
|
; 10: Bad TSS Exception (With Error Code!)
|
|
|
|
; 11: Segment Not Present Exception (With Error Code!)
|
|
|
|
; 12: Stack Fault Exception (With Error Code!)
|
|
|
|
; 13: General Protection Fault Exception (With Error Code!)
|
|
|
|
; 14: Page Fault Exception (With Error Code!)
|
|
|
|
%assign i 10
|
|
|
|
%rep 5
|
|
|
|
isrstub i
|
|
|
|
%assign i i+1
|
|
|
|
%endrep
|
|
|
|
|
|
|
|
; 15: Reserved Exception
|
|
|
|
; 16: Floating Point Exception
|
|
|
|
; 17: Alignment Check Exception
|
2015-09-12 17:13:42 +02:00
|
|
|
; 18: Machine Check Exception
|
2015-05-23 14:35:45 +02:00
|
|
|
; 19-31: Reserved
|
|
|
|
%assign i 15
|
|
|
|
%rep 17
|
|
|
|
isrstub_pseudo_error i
|
|
|
|
%assign i i+1
|
|
|
|
%endrep
|
|
|
|
|
|
|
|
; NASM macro for asynchronous interrupts (no exceptions)
|
|
|
|
%macro irqstub 1
|
|
|
|
global irq%1
|
2016-08-26 19:44:02 +02:00
|
|
|
align 64
|
2015-05-23 14:35:45 +02:00
|
|
|
irq%1:
|
2017-06-16 01:33:46 +02:00
|
|
|
push byte 0 ; pseudo error code
|
|
|
|
push byte 32+%1
|
|
|
|
jmp common_stub
|
2015-05-23 14:35:45 +02:00
|
|
|
%endmacro
|
|
|
|
|
|
|
|
; Create entries for the interrupts 0 to 23
|
|
|
|
%assign i 0
|
|
|
|
%rep 24
|
|
|
|
irqstub i
|
|
|
|
%assign i i+1
|
|
|
|
%endrep
|
|
|
|
|
2016-08-25 17:14:47 +02:00
|
|
|
; Create entries for the interrupts 80 to 82
|
2015-08-20 14:15:52 +02:00
|
|
|
%assign i 80
|
2016-08-25 17:14:47 +02:00
|
|
|
%rep 3
|
2015-08-20 14:15:52 +02:00
|
|
|
irqstub i
|
|
|
|
%assign i i+1
|
|
|
|
%endrep
|
2015-08-20 13:03:54 +02:00
|
|
|
|
2016-08-29 14:22:07 +02:00
|
|
|
global wakeup
|
|
|
|
align 64
|
|
|
|
wakeup:
|
|
|
|
push byte 0 ; pseudo error code
|
2017-06-16 01:33:46 +02:00
|
|
|
push byte 121
|
|
|
|
jmp common_stub
|
2016-08-29 14:22:07 +02:00
|
|
|
|
|
|
|
global mmnif_irq
|
|
|
|
align 64
|
|
|
|
mmnif_irq:
|
|
|
|
push byte 0 ; pseudo error code
|
2017-06-16 01:33:46 +02:00
|
|
|
push byte 122
|
|
|
|
jmp common_stub
|
2016-08-29 14:22:07 +02:00
|
|
|
|
2015-05-23 14:35:45 +02:00
|
|
|
global apic_timer
|
2016-08-26 19:44:02 +02:00
|
|
|
align 64
|
2015-05-23 14:35:45 +02:00
|
|
|
apic_timer:
|
|
|
|
push byte 0 ; pseudo error code
|
|
|
|
push byte 123
|
|
|
|
jmp common_stub
|
|
|
|
|
|
|
|
global apic_lint0
|
2016-08-26 19:44:02 +02:00
|
|
|
align 64
|
2015-05-23 14:35:45 +02:00
|
|
|
apic_lint0:
|
|
|
|
push byte 0 ; pseudo error code
|
|
|
|
push byte 124
|
|
|
|
jmp common_stub
|
|
|
|
|
|
|
|
global apic_lint1
|
2016-08-26 19:44:02 +02:00
|
|
|
align 64
|
2015-05-23 14:35:45 +02:00
|
|
|
apic_lint1:
|
|
|
|
push byte 0 ; pseudo error code
|
|
|
|
push byte 125
|
|
|
|
jmp common_stub
|
|
|
|
|
|
|
|
global apic_error
|
2016-08-26 19:44:02 +02:00
|
|
|
align 64
|
2015-05-23 14:35:45 +02:00
|
|
|
apic_error:
|
|
|
|
push byte 0 ; pseudo error code
|
|
|
|
push byte 126
|
|
|
|
jmp common_stub
|
|
|
|
|
|
|
|
global apic_svr
|
2016-08-26 19:44:02 +02:00
|
|
|
align 64
|
2015-05-23 14:35:45 +02:00
|
|
|
apic_svr:
|
|
|
|
push byte 0 ; pseudo error code
|
|
|
|
push byte 127
|
|
|
|
jmp common_stub
|
|
|
|
|
|
|
|
extern irq_handler
|
|
|
|
extern get_current_stack
|
|
|
|
extern finish_task_switch
|
2015-07-11 00:12:59 +02:00
|
|
|
extern syscall_handler
|
|
|
|
|
2016-09-10 09:59:18 +02:00
|
|
|
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
|
2016-09-10 16:55:33 +02:00
|
|
|
; save FPU state
|
|
|
|
fnstenv [rdi + 0x74]
|
|
|
|
lea rax, [rdi + 0x70]
|
|
|
|
stmxcsr [rax]
|
2016-09-10 09:59:18 +02:00
|
|
|
xor rax, rax
|
|
|
|
sti
|
|
|
|
ret
|
|
|
|
|
|
|
|
global setcontext
|
|
|
|
align 64
|
|
|
|
setcontext:
|
|
|
|
cli
|
|
|
|
; restore FPU state
|
2016-09-10 16:55:33 +02:00
|
|
|
fldenv [rdi + 0x74]
|
|
|
|
lea rax, [rdi + 0x70]
|
|
|
|
ldmxcsr [rax]
|
2016-09-10 09:59:18 +02:00
|
|
|
; 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
|
|
|
|
|
|
|
|
global __startcontext
|
|
|
|
align 64
|
|
|
|
__startcontext:
|
|
|
|
mov rsp, rbx
|
|
|
|
pop rdi
|
|
|
|
cmp rdi, 0
|
|
|
|
je Lno_context
|
|
|
|
|
|
|
|
call setcontext
|
|
|
|
|
|
|
|
Lno_context:
|
|
|
|
extern exit
|
|
|
|
call exit
|
|
|
|
jmp $
|
|
|
|
|
2015-05-23 14:35:45 +02:00
|
|
|
global switch_context
|
2016-08-26 19:44:02 +02:00
|
|
|
align 64
|
2015-05-23 14:35:45 +02:00
|
|
|
switch_context:
|
2016-05-15 07:48:30 +02:00
|
|
|
; by entering a function the DF flag has to be cleared => see ABI
|
|
|
|
cld
|
2015-05-23 14:35:45 +02:00
|
|
|
; create on the stack a pseudo interrupt
|
|
|
|
; afterwards, we switch to the task with iret
|
2015-06-27 20:14:18 +02:00
|
|
|
push QWORD 0x10 ; SS
|
|
|
|
push rsp ; RSP
|
|
|
|
add QWORD [rsp], 0x08 ; => value of rsp before the creation of a pseudo interrupt
|
2015-08-17 12:46:17 +02:00
|
|
|
pushfq ; RFLAGS
|
2015-05-23 14:35:45 +02:00
|
|
|
push QWORD 0x08 ; CS
|
|
|
|
push QWORD rollback ; RIP
|
|
|
|
push QWORD 0x00edbabe ; Error code
|
2016-08-26 18:07:34 +02:00
|
|
|
push QWORD 0x00 ; Interrupt number
|
2015-05-23 14:35:45 +02:00
|
|
|
push rax
|
|
|
|
push rcx
|
|
|
|
push rdx
|
|
|
|
push rbx
|
2015-08-17 12:46:17 +02:00
|
|
|
push QWORD [rsp+9*8]
|
2015-05-23 14:35:45 +02:00
|
|
|
push rbp
|
|
|
|
push rsi
|
|
|
|
push rdi
|
|
|
|
push r8
|
|
|
|
push r9
|
|
|
|
push r10
|
|
|
|
push r11
|
|
|
|
push r12
|
|
|
|
push r13
|
|
|
|
push r14
|
|
|
|
push r15
|
2015-08-09 14:29:15 +02:00
|
|
|
; push fs and gs registers
|
2015-08-09 19:50:34 +02:00
|
|
|
global Lpatch0
|
|
|
|
Lpatch0:
|
|
|
|
jmp short Lrdfsgs1 ; we patch later this jump to enable rdfsbase/rdgsbase
|
|
|
|
rdfsbase rax
|
|
|
|
rdgsbase rdx
|
|
|
|
push rax
|
|
|
|
push rdx
|
|
|
|
jmp short Lgo1
|
|
|
|
Lrdfsgs1:
|
2015-08-09 14:29:15 +02:00
|
|
|
mov ecx, MSR_FS_BASE
|
|
|
|
rdmsr
|
|
|
|
sub rsp, 8
|
|
|
|
mov DWORD [rsp+4], edx
|
|
|
|
mov DWORD [rsp], eax
|
|
|
|
mov ecx, MSR_GS_BASE
|
|
|
|
rdmsr
|
|
|
|
sub rsp, 8
|
|
|
|
mov DWORD [rsp+4], edx
|
|
|
|
mov DWORD [rsp], eax
|
2015-08-09 19:50:34 +02:00
|
|
|
Lgo1:
|
2015-08-09 14:29:15 +02:00
|
|
|
|
|
|
|
mov rax, rdi ; rdi contains the address to store the old rsp
|
2015-05-23 14:35:45 +02:00
|
|
|
|
|
|
|
jmp common_switch
|
|
|
|
|
2016-08-26 19:44:02 +02:00
|
|
|
align 64
|
2015-05-23 14:35:45 +02:00
|
|
|
rollback:
|
|
|
|
ret
|
|
|
|
|
2016-08-26 19:44:02 +02:00
|
|
|
align 64
|
2015-05-23 14:35:45 +02:00
|
|
|
common_stub:
|
|
|
|
push rax
|
|
|
|
push rcx
|
|
|
|
push rdx
|
|
|
|
push rbx
|
2015-08-17 12:46:17 +02:00
|
|
|
push QWORD [rsp+9*8] ; push user-space rsp, which is already on the stack
|
2015-05-23 14:35:45 +02:00
|
|
|
push rbp
|
|
|
|
push rsi
|
|
|
|
push rdi
|
|
|
|
push r8
|
|
|
|
push r9
|
|
|
|
push r10
|
|
|
|
push r11
|
|
|
|
push r12
|
|
|
|
push r13
|
|
|
|
push r14
|
|
|
|
push r15
|
2015-08-09 14:29:15 +02:00
|
|
|
; push fs and gs registers
|
2015-08-09 19:50:34 +02:00
|
|
|
global Lpatch1
|
2015-09-02 14:44:45 +02:00
|
|
|
Lpatch1:
|
2015-08-09 19:50:34 +02:00
|
|
|
jmp short Lrdfsgs2 ; we patch later this jump to enable rdfsbase/rdgsbase
|
|
|
|
rdfsbase rax
|
|
|
|
rdgsbase rdx
|
|
|
|
push rax
|
|
|
|
push rdx
|
|
|
|
jmp short Lgo2
|
|
|
|
Lrdfsgs2:
|
2015-08-09 14:29:15 +02:00
|
|
|
mov ecx, MSR_FS_BASE
|
|
|
|
rdmsr
|
|
|
|
sub rsp, 8
|
|
|
|
mov DWORD [rsp+4], edx
|
|
|
|
mov DWORD [rsp], eax
|
|
|
|
mov ecx, MSR_GS_BASE
|
|
|
|
rdmsr
|
|
|
|
sub rsp, 8
|
|
|
|
mov DWORD [rsp+4], edx
|
|
|
|
mov DWORD [rsp], eax
|
2015-08-09 19:50:34 +02:00
|
|
|
Lgo2:
|
2015-08-10 14:10:27 +02:00
|
|
|
; do we interrupt user-level code?
|
|
|
|
cmp QWORD [rsp+24+18*8], 0x08
|
|
|
|
je short kernel_space1
|
|
|
|
swapgs ; set GS to the kernel selector
|
|
|
|
kernel_space1:
|
2015-05-23 14:35:45 +02:00
|
|
|
|
|
|
|
; use the same handler for interrupts and exceptions
|
|
|
|
mov rdi, rsp
|
|
|
|
call irq_handler
|
|
|
|
|
|
|
|
cmp rax, 0
|
|
|
|
je no_context_switch
|
|
|
|
|
|
|
|
common_switch:
|
2015-07-19 11:12:05 +02:00
|
|
|
mov QWORD [rax], rsp ; store old rsp
|
2015-05-23 14:35:45 +02:00
|
|
|
call get_current_stack ; get new rsp
|
2015-07-19 11:12:05 +02:00
|
|
|
mov rsp, rax
|
2015-05-23 14:35:45 +02:00
|
|
|
|
2017-04-03 18:08:12 +02:00
|
|
|
%ifidn SAVE_FPU,ON
|
2015-05-23 14:35:45 +02:00
|
|
|
; set task switched flag
|
|
|
|
mov rax, cr0
|
2015-07-19 11:12:05 +02:00
|
|
|
or rax, 8
|
2015-05-23 14:35:45 +02:00
|
|
|
mov cr0, rax
|
2016-02-15 11:29:40 +01:00
|
|
|
%endif
|
2015-05-23 14:35:45 +02:00
|
|
|
|
|
|
|
; call cleanup code
|
|
|
|
call finish_task_switch
|
|
|
|
|
|
|
|
no_context_switch:
|
2015-09-13 14:51:25 +02:00
|
|
|
; do we interrupt user-level code?
|
|
|
|
cmp QWORD [rsp+24+18*8], 0x08
|
|
|
|
je short kernel_space2
|
|
|
|
swapgs ; set GS to the user-level selector
|
|
|
|
kernel_space2:
|
2015-08-09 19:50:34 +02:00
|
|
|
; restore fs / gs register
|
|
|
|
global Lpatch2
|
|
|
|
Lpatch2:
|
|
|
|
jmp short Lwrfsgs ; we patch later this jump to enable wrfsbase/wrgsbase
|
2015-09-13 14:51:25 +02:00
|
|
|
pop r15
|
2015-08-14 21:06:16 +02:00
|
|
|
;wrgsbase r15 ; currently, we don't use the gs register
|
2015-08-09 19:50:34 +02:00
|
|
|
pop r15
|
|
|
|
wrfsbase r15
|
|
|
|
jmp short Lgo3
|
|
|
|
Lwrfsgs:
|
2015-08-10 14:10:27 +02:00
|
|
|
;mov ecx, MSR_GS_BASE
|
|
|
|
;mov edx, DWORD [rsp+4]
|
|
|
|
;mov eax, DWORD [rsp]
|
|
|
|
add rsp, 8
|
2015-08-14 21:06:16 +02:00
|
|
|
;wrmsr ; currently, we don't use the gs register
|
2015-08-09 14:29:15 +02:00
|
|
|
mov ecx, MSR_FS_BASE
|
|
|
|
mov edx, DWORD [rsp+4]
|
|
|
|
mov eax, DWORD [rsp]
|
|
|
|
add rsp, 8
|
|
|
|
wrmsr
|
2015-08-09 19:50:34 +02:00
|
|
|
Lgo3:
|
2015-05-23 14:35:45 +02:00
|
|
|
pop r15
|
|
|
|
pop r14
|
|
|
|
pop r13
|
|
|
|
pop r12
|
|
|
|
pop r11
|
|
|
|
pop r10
|
|
|
|
pop r9
|
|
|
|
pop r8
|
|
|
|
pop rdi
|
|
|
|
pop rsi
|
|
|
|
pop rbp
|
|
|
|
add rsp, 8
|
|
|
|
pop rbx
|
|
|
|
pop rdx
|
|
|
|
pop rcx
|
|
|
|
pop rax
|
|
|
|
|
|
|
|
add rsp, 16
|
|
|
|
iretq
|
|
|
|
|
2017-01-16 18:47:13 +01:00
|
|
|
global is_uhyve
|
|
|
|
align 64
|
2017-02-03 15:35:49 +01:00
|
|
|
is_uhyve:
|
2017-01-16 18:47:13 +01:00
|
|
|
mov eax, DWORD [uhyve]
|
|
|
|
ret
|
|
|
|
|
2016-07-25 07:55:38 +02:00
|
|
|
global is_single_kernel
|
2016-08-26 19:57:36 +02:00
|
|
|
align 64
|
2016-08-02 00:06:12 +02:00
|
|
|
is_single_kernel:
|
2016-07-25 07:55:38 +02:00
|
|
|
mov eax, DWORD [single_kernel]
|
|
|
|
ret
|
|
|
|
|
2016-08-25 17:14:47 +02:00
|
|
|
|
|
|
|
global sighandler_epilog
|
|
|
|
sighandler_epilog:
|
|
|
|
; restore only those registers that might have changed between returning
|
|
|
|
; from IRQ and execution of signal handler
|
|
|
|
add rsp, 2 * 8 ; ignore fs, gs
|
|
|
|
pop r15
|
|
|
|
pop r14
|
|
|
|
pop r13
|
|
|
|
pop r12
|
|
|
|
pop r11
|
|
|
|
pop r10
|
|
|
|
pop r9
|
|
|
|
pop r8
|
|
|
|
pop rdi
|
|
|
|
pop rsi
|
|
|
|
pop rbp
|
|
|
|
add rsp, 8 ; ignore rsp
|
|
|
|
pop rbx
|
|
|
|
pop rdx
|
|
|
|
pop rcx
|
|
|
|
pop rax
|
|
|
|
add rsp, 4 * 8 ; ignore int_no, error, rip, cs
|
|
|
|
popfq
|
|
|
|
add rsp, 2 * 8 ; ignore userrsp, ss
|
|
|
|
|
|
|
|
jmp [rsp - 5 * 8] ; jump to rip from saved state
|
|
|
|
|
2015-05-23 14:35:45 +02:00
|
|
|
SECTION .data
|
|
|
|
|
2015-07-11 00:12:59 +02:00
|
|
|
align 4096
|
2015-05-23 14:35:45 +02:00
|
|
|
global boot_stack
|
|
|
|
boot_stack:
|
2015-05-31 00:30:13 +02:00
|
|
|
TIMES (MAX_CORES*KERNEL_STACK_SIZE) DB 0xcd
|
2016-06-03 06:24:46 +02:00
|
|
|
global boot_ist
|
|
|
|
boot_ist:
|
|
|
|
TIMES KERNEL_STACK_SIZE DB 0xcd
|
2015-05-23 14:35:45 +02:00
|
|
|
|
|
|
|
; add some hints to the ELF file
|
|
|
|
SECTION .note.GNU-stack noalloc noexec nowrite progbits
|