mirror of
https://gitlab.com/sortix/sortix.git
synced 2023-02-13 20:55:38 -05:00
Rename Sortix kernel directory to kernel.
This commit is contained in:
parent
18d2695439
commit
98a87fa1e5
228 changed files with 10 additions and 10 deletions
67
kernel/x64/base.s
Normal file
67
kernel/x64/base.s
Normal file
|
|
@ -0,0 +1,67 @@
|
|||
/*******************************************************************************
|
||||
|
||||
Copyright(C) Jonas 'Sortie' Termansen 2011.
|
||||
|
||||
This file is part of Sortix.
|
||||
|
||||
Sortix is free software: you can redistribute it and/or modify it under the
|
||||
terms of the GNU General Public License as published by the Free Software
|
||||
Foundation, either version 3 of the License, or (at your option) any later
|
||||
version.
|
||||
|
||||
Sortix is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
||||
details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along with
|
||||
Sortix. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
x64/base.s
|
||||
Bootstraps the kernel and passes over control from the boot-loader to the
|
||||
kernel main function.
|
||||
|
||||
*******************************************************************************/
|
||||
|
||||
.section .text
|
||||
|
||||
.global beginkernel
|
||||
.type beginkernel, @function
|
||||
beginkernel:
|
||||
movw $0x736, 0xB83E8
|
||||
movw $0x734, 0xB83EA
|
||||
movw $0x753, 0xB83EE
|
||||
movw $0x74F, 0xB83F0
|
||||
movw $0x752, 0xB83F2
|
||||
movw $0x754, 0xB83F4
|
||||
movw $0x749, 0xB83F6
|
||||
movw $0x758, 0xB83F8
|
||||
|
||||
# Initialize the stack pointer.
|
||||
movq $stack, %rsp
|
||||
addq $65536, %rsp # 64 KiB, see kernel.cpp
|
||||
|
||||
# Reset EFLAGS.
|
||||
# pushl $0
|
||||
# popf
|
||||
|
||||
# Push the pointer to the Multiboot information structure.
|
||||
mov %rbx, %rsi
|
||||
# Push the magic value.
|
||||
mov %rax, %rdi
|
||||
|
||||
call KernelInit
|
||||
.size beginkernel, . - beginkernel
|
||||
|
||||
.global HaltKernel
|
||||
HaltKernel:
|
||||
cli
|
||||
hlt
|
||||
jmp HaltKernel
|
||||
.size HaltKernel, . - HaltKernel
|
||||
|
||||
.global WaitForInterrupt
|
||||
.type WaitForInterrupt, @function # void WaitForInterrupt();
|
||||
WaitForInterrupt:
|
||||
hlt
|
||||
ret
|
||||
197
kernel/x64/boot.s
Normal file
197
kernel/x64/boot.s
Normal file
|
|
@ -0,0 +1,197 @@
|
|||
/*******************************************************************************
|
||||
|
||||
Copyright(C) Jonas 'Sortie' Termansen 2011.
|
||||
|
||||
This file is part of Sortix.
|
||||
|
||||
Sortix is free software: you can redistribute it and/or modify it under the
|
||||
terms of the GNU General Public License as published by the Free Software
|
||||
Foundation, either version 3 of the License, or (at your option) any later
|
||||
version.
|
||||
|
||||
Sortix is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
||||
details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along with
|
||||
Sortix. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
x64/boot.s
|
||||
Bootstraps the kernel and passes over control from the boot-loader to the
|
||||
kernel main function. It also jumps into long mode!
|
||||
|
||||
*******************************************************************************/
|
||||
|
||||
.section .text
|
||||
.text 0x100000
|
||||
|
||||
.global _start
|
||||
.type _start, @function
|
||||
.code32
|
||||
_start:
|
||||
jmp prepare_kernel_execution
|
||||
|
||||
# Align 32 bits boundary.
|
||||
.align 4
|
||||
|
||||
# Multiboot header.
|
||||
multiboot_header:
|
||||
# Magic.
|
||||
.long 0x1BADB002
|
||||
# Flags.
|
||||
.long 0x00000003
|
||||
# Checksum.
|
||||
.long -(0x1BADB002 + 0x00000003)
|
||||
|
||||
prepare_kernel_execution:
|
||||
# We got our multiboot information in various registers. But we are going
|
||||
# to need these registers. But where can we store them then? Oh hey, let's
|
||||
# store then in the code already run!
|
||||
|
||||
# Store the pointer to the Multiboot information structure.
|
||||
mov %ebx, 0x100000
|
||||
|
||||
# Store the magic value.
|
||||
mov %eax, 0x100004
|
||||
|
||||
# Clear the first $0xE000 bytes following 0x21000.
|
||||
movl $0x21000, %edi
|
||||
mov %edi, %cr3
|
||||
xorl %eax, %eax
|
||||
movl $0xE000, %ecx
|
||||
rep stosl
|
||||
movl %cr3, %edi
|
||||
|
||||
# Set the initial page tables.
|
||||
# Note that we OR with 0x7 here to allow user-space access, except in the
|
||||
# first 2 MiB. We also do this with 0x200 to allow forking the page.
|
||||
|
||||
# Page-Map Level 4
|
||||
movl $0x22207, (%edi)
|
||||
addl $0x1000, %edi
|
||||
|
||||
# Page-Directory Pointer Table
|
||||
movl $0x23207, (%edi)
|
||||
addl $0x1000, %edi
|
||||
|
||||
# Page-Directory (no user-space access here)
|
||||
movl $0x24003, (%edi) # (First 2 MiB)
|
||||
movl $0x25003, 8(%edi) # (Second 2 MiB)
|
||||
addl $0x1000, %edi
|
||||
|
||||
# Page-Table
|
||||
# Memory map the first 4 MiB.
|
||||
movl $0x3, %ebx
|
||||
movl $1024, %ecx
|
||||
|
||||
SetEntry:
|
||||
mov %ebx, (%edi)
|
||||
add $0x1000, %ebx
|
||||
add $8, %edi
|
||||
loop SetEntry
|
||||
|
||||
# Enable PAE.
|
||||
mov %cr4, %eax
|
||||
orl $0x20, %eax
|
||||
mov %eax, %cr4
|
||||
|
||||
# Enable long mode.
|
||||
mov $0xC0000080, %ecx
|
||||
rdmsr
|
||||
orl $0x100, %eax
|
||||
wrmsr
|
||||
|
||||
# Enable paging and enter long mode (still 32-bit)
|
||||
mov %cr0, %eax
|
||||
orl $0x80000000, %eax
|
||||
mov %eax, %cr0
|
||||
|
||||
# Load the long mode GDT.
|
||||
mov GDTPointer, %eax
|
||||
lgdtl GDTPointer
|
||||
|
||||
# Now use the 64-bit code segment, and we are in full 64-bit mode.
|
||||
ljmp $0x10, $Realm64
|
||||
|
||||
.code64
|
||||
Realm64:
|
||||
|
||||
# Now, set up the other segment registers.
|
||||
cli
|
||||
mov $0x18, %ax
|
||||
mov %ax, %ds
|
||||
mov %ax, %es
|
||||
mov %ax, %fs
|
||||
mov %ax, %gs
|
||||
|
||||
# Enable the floating point unit.
|
||||
mov %cr0, %rax
|
||||
and $0xFFFD, %ax
|
||||
or $0x10, %ax
|
||||
mov %rax, %cr0
|
||||
fninit
|
||||
|
||||
# Enable Streaming SIMD Extensions.
|
||||
mov %cr0, %rax
|
||||
and $0xFFFB, %ax
|
||||
or $0x2, %ax
|
||||
mov %rax, %cr0
|
||||
mov %cr4, %rax
|
||||
or $0x600, %rax
|
||||
mov %rax, %cr4
|
||||
|
||||
# Alright, that was the bootstrap code. Now begin preparing to run the
|
||||
# actual 64-bit kernel.
|
||||
jmp Main
|
||||
.size _start, . - _start
|
||||
|
||||
.section .data
|
||||
GDT64: # Global Descriptor Table (64-bit).
|
||||
GDTNull: # The null descriptor.
|
||||
.word 0 # Limit (low).
|
||||
.word 0 # Base (low).
|
||||
.byte 0 # Base (middle)
|
||||
.byte 0 # Access.
|
||||
.byte 0 # Granularity.
|
||||
.byte 0 # Base (high).
|
||||
GDTUnused: # The null descriptor.
|
||||
.word 0 # Limit (low).
|
||||
.word 0 # Base (low).
|
||||
.byte 0 # Base (middle)
|
||||
.byte 0 # Access.
|
||||
.byte 0 # Granularity.
|
||||
.byte 0 # Base (high).
|
||||
GDTCode: # The code descriptor.
|
||||
.word 0xFFFF # Limit (low).
|
||||
.word 0 # Base (low).
|
||||
.byte 0 # Base (middle)
|
||||
.byte 0x9A # Access.
|
||||
.byte 0xAF # Granularity.
|
||||
.byte 0 # Base (high).
|
||||
GDTData: # The data descriptor.
|
||||
.word 0xFFFF # Limit (low).
|
||||
.word 0 # Base (low).
|
||||
.byte 0 # Base (middle)
|
||||
.byte 0x92 # Access.
|
||||
.byte 0x8F # Granularity.
|
||||
.byte 0 # Base (high).
|
||||
GDTPointer: # The GDT-pointer.
|
||||
.word GDTPointer - GDT64 - 1 # Limit.
|
||||
.long GDT64 # Base.
|
||||
.long 0
|
||||
|
||||
Main:
|
||||
# Copy the character B onto the screen so we know it works.
|
||||
movq $0x242, %r15
|
||||
movq %r15, %rax
|
||||
movw %ax, 0xB8000
|
||||
|
||||
# Load the pointer to the Multiboot information structure.
|
||||
mov 0x100000, %ebx
|
||||
|
||||
# Load the magic value.
|
||||
mov 0x100004, %eax
|
||||
|
||||
jmp beginkernel
|
||||
.size Main, . - Main
|
||||
57
kernel/x64/calltrace.s
Normal file
57
kernel/x64/calltrace.s
Normal file
|
|
@ -0,0 +1,57 @@
|
|||
/*******************************************************************************
|
||||
|
||||
Copyright(C) Jonas 'Sortie' Termansen 2012, 2013.
|
||||
|
||||
This file is part of Sortix.
|
||||
|
||||
Sortix is free software: you can redistribute it and/or modify it under the
|
||||
terms of the GNU General Public License as published by the Free Software
|
||||
Foundation, either version 3 of the License, or (at your option) any later
|
||||
version.
|
||||
|
||||
Sortix is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
||||
details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along with
|
||||
Sortix. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
x64/calltrace.s
|
||||
Attempts to unwind the stack and prints the code locations where functions
|
||||
were called. This greatly aids debugging.
|
||||
|
||||
*******************************************************************************/
|
||||
|
||||
.section .text
|
||||
|
||||
.global calltrace
|
||||
.type calltrace, @function
|
||||
calltrace:
|
||||
push %rbp
|
||||
push %rbx
|
||||
movq %rsp, %rbp
|
||||
push %rbx
|
||||
movq %rdi, %rbx
|
||||
testq %rbx, %rbx
|
||||
jnz 1f
|
||||
movq %rbp, %rbx
|
||||
1:
|
||||
xorl %edi, %edi
|
||||
|
||||
calltrace_unwind:
|
||||
testq %rbx, %rbx
|
||||
jz calltrace_done
|
||||
movq 8(%rbx), %rsi # Previous RIP
|
||||
movq 0(%rbx), %rbx # Previous RBP
|
||||
pushq %rdi
|
||||
call calltrace_print_function
|
||||
popq %rdi
|
||||
incq %rdi
|
||||
jmp calltrace_unwind
|
||||
|
||||
calltrace_done:
|
||||
popq %rbx
|
||||
popq %rbp
|
||||
retq
|
||||
.size calltrace, . - calltrace
|
||||
39
kernel/x64/crti.s
Normal file
39
kernel/x64/crti.s
Normal file
|
|
@ -0,0 +1,39 @@
|
|||
/*******************************************************************************
|
||||
|
||||
Copyright(C) Jonas 'Sortie' Termansen 2012.
|
||||
|
||||
This file is part of Sortix.
|
||||
|
||||
Sortix is free software: you can redistribute it and/or modify it under the
|
||||
terms of the GNU General Public License as published by the Free Software
|
||||
Foundation, either version 3 of the License, or (at your option) any later
|
||||
version.
|
||||
|
||||
Sortix is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
||||
details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along with
|
||||
Sortix. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
x64/crti.s
|
||||
Provides the header of the _init and _fini functions.
|
||||
|
||||
*******************************************************************************/
|
||||
|
||||
.section .init
|
||||
.global _init
|
||||
.type _init, @function
|
||||
_init:
|
||||
push %rbp
|
||||
movq %rsp, %rbp
|
||||
/* gcc will nicely put the contents of crtbegin.o's .init section here. */
|
||||
|
||||
.section .fini
|
||||
.global _fini
|
||||
.type _fini, @function
|
||||
_fini:
|
||||
push %rbp
|
||||
movq %rsp, %rbp
|
||||
/* gcc will nicely put the contents of crtbegin.o's .fini section here. */
|
||||
33
kernel/x64/crtn.s
Normal file
33
kernel/x64/crtn.s
Normal file
|
|
@ -0,0 +1,33 @@
|
|||
/*******************************************************************************
|
||||
|
||||
Copyright(C) Jonas 'Sortie' Termansen 2012.
|
||||
|
||||
This file is part of Sortix.
|
||||
|
||||
Sortix is free software: you can redistribute it and/or modify it under the
|
||||
terms of the GNU General Public License as published by the Free Software
|
||||
Foundation, either version 3 of the License, or (at your option) any later
|
||||
version.
|
||||
|
||||
Sortix is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
||||
details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along with
|
||||
Sortix. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
x64/crtn.s
|
||||
Provides the tail of the _init and _fini functions.
|
||||
|
||||
*******************************************************************************/
|
||||
|
||||
.section .init
|
||||
/* gcc will nicely put the contents of crtend.o's .init section here. */
|
||||
popq %rbp
|
||||
ret
|
||||
|
||||
.section .fini
|
||||
/* gcc will nicely put the contents of crtend.o's .fini section here. */
|
||||
popq %rbp
|
||||
ret
|
||||
512
kernel/x64/interrupt.s
Normal file
512
kernel/x64/interrupt.s
Normal file
|
|
@ -0,0 +1,512 @@
|
|||
/*******************************************************************************
|
||||
|
||||
Copyright(C) Jonas 'Sortie' Termansen 2011, 2012.
|
||||
|
||||
This file is part of Sortix.
|
||||
|
||||
Sortix is free software: you can redistribute it and/or modify it under the
|
||||
terms of the GNU General Public License as published by the Free Software
|
||||
Foundation, either version 3 of the License, or (at your option) any later
|
||||
version.
|
||||
|
||||
Sortix is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
||||
details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along with
|
||||
Sortix. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
x64/interrupt.s
|
||||
Transfers control to interrupt handlers when interrupts happen.
|
||||
|
||||
*******************************************************************************/
|
||||
|
||||
.section .text
|
||||
|
||||
.global isr0
|
||||
.type isr0, @function
|
||||
isr0:
|
||||
cli
|
||||
pushq $0 # err_code
|
||||
pushq $0 # int_no
|
||||
jmp interrupt_handler_prepare
|
||||
.global isr1
|
||||
.type isr1, @function
|
||||
isr1:
|
||||
cli
|
||||
pushq $0 # err_code
|
||||
pushq $1 # int_no
|
||||
jmp interrupt_handler_prepare
|
||||
.global isr2
|
||||
.type isr2, @function
|
||||
isr2:
|
||||
cli
|
||||
pushq $0 # err_code
|
||||
pushq $2 # int_no
|
||||
jmp interrupt_handler_prepare
|
||||
.global isr3
|
||||
.type isr3, @function
|
||||
isr3:
|
||||
cli
|
||||
pushq $0 # err_code
|
||||
pushq $3 # int_no
|
||||
jmp interrupt_handler_prepare
|
||||
.global isr4
|
||||
.type isr4, @function
|
||||
isr4:
|
||||
cli
|
||||
pushq $0 # err_code
|
||||
pushq $4 # int_no
|
||||
jmp interrupt_handler_prepare
|
||||
.global isr5
|
||||
.type isr5, @function
|
||||
isr5:
|
||||
cli
|
||||
pushq $0 # err_code
|
||||
pushq $5 # int_no
|
||||
jmp interrupt_handler_prepare
|
||||
.global isr6
|
||||
.type isr6, @function
|
||||
isr6:
|
||||
cli
|
||||
pushq $0 # err_code
|
||||
pushq $6 # int_no
|
||||
jmp interrupt_handler_prepare
|
||||
.global isr7
|
||||
.type isr7, @function
|
||||
isr7:
|
||||
cli
|
||||
pushq $0 # err_code
|
||||
pushq $7 # int_no
|
||||
jmp interrupt_handler_prepare
|
||||
.global isr8
|
||||
.type isr8, @function
|
||||
isr8:
|
||||
cli
|
||||
# pushq $0 # err_code pushed by CPU
|
||||
pushq $8 # int_no
|
||||
jmp interrupt_handler_prepare
|
||||
.global isr9
|
||||
.type isr9, @function
|
||||
isr9:
|
||||
cli
|
||||
pushq $0 # err_code
|
||||
pushq $9 # int_no
|
||||
jmp interrupt_handler_prepare
|
||||
.global isr10
|
||||
.type isr10, @function
|
||||
isr10:
|
||||
cli
|
||||
# pushq $0 # err_code pushed by CPU
|
||||
pushq $10 # int_no
|
||||
jmp interrupt_handler_prepare
|
||||
.global isr11
|
||||
.type isr11, @function
|
||||
isr11:
|
||||
cli
|
||||
# pushq $0 # err_code pushed by CPU
|
||||
pushq $11 # int_no
|
||||
jmp interrupt_handler_prepare
|
||||
.global isr12
|
||||
.type isr12, @function
|
||||
isr12:
|
||||
cli
|
||||
# pushq $0 # err_code pushed by CPU
|
||||
pushq $12 # int_no
|
||||
jmp interrupt_handler_prepare
|
||||
.global isr13
|
||||
.type isr13, @function
|
||||
isr13:
|
||||
cli
|
||||
# pushq $0 # err_code pushed by CPU
|
||||
pushq $13 # int_no
|
||||
jmp interrupt_handler_prepare
|
||||
.global isr14
|
||||
.type isr14, @function
|
||||
isr14:
|
||||
cli
|
||||
# pushq $0 # err_code pushed by CPU
|
||||
pushq $14 # int_no
|
||||
jmp interrupt_handler_prepare
|
||||
.global isr15
|
||||
.type isr15, @function
|
||||
isr15:
|
||||
cli
|
||||
pushq $0 # err_code
|
||||
pushq $15 # int_no
|
||||
jmp interrupt_handler_prepare
|
||||
.global isr16
|
||||
.type isr16, @function
|
||||
isr16:
|
||||
cli
|
||||
pushq $0 # err_code
|
||||
pushq $16 # int_no
|
||||
jmp interrupt_handler_prepare
|
||||
.global isr17
|
||||
.type isr17, @function
|
||||
isr17:
|
||||
cli
|
||||
pushq $0 # err_code
|
||||
pushq $17 # int_no
|
||||
jmp interrupt_handler_prepare
|
||||
.global isr18
|
||||
.type isr18, @function
|
||||
isr18:
|
||||
cli
|
||||
pushq $0 # err_code
|
||||
pushq $18 # int_no
|
||||
jmp interrupt_handler_prepare
|
||||
.global isr19
|
||||
.type isr19, @function
|
||||
isr19:
|
||||
cli
|
||||
pushq $0 # err_code
|
||||
pushq $19 # int_no
|
||||
jmp interrupt_handler_prepare
|
||||
.global isr20
|
||||
.type isr20, @function
|
||||
isr20:
|
||||
cli
|
||||
pushq $0 # err_code
|
||||
pushq $20 # int_no
|
||||
jmp interrupt_handler_prepare
|
||||
.global isr21
|
||||
.type isr21, @function
|
||||
isr21:
|
||||
cli
|
||||
pushq $0 # err_code
|
||||
pushq $21 # int_no
|
||||
jmp interrupt_handler_prepare
|
||||
.global isr22
|
||||
.type isr22, @function
|
||||
isr22:
|
||||
cli
|
||||
pushq $0 # err_code
|
||||
pushq $22 # int_no
|
||||
jmp interrupt_handler_prepare
|
||||
.global isr23
|
||||
.type isr23, @function
|
||||
isr23:
|
||||
cli
|
||||
pushq $0 # err_code
|
||||
pushq $23 # int_no
|
||||
jmp interrupt_handler_prepare
|
||||
.global isr24
|
||||
.type isr24, @function
|
||||
isr24:
|
||||
cli
|
||||
pushq $0 # err_code
|
||||
pushq $24 # int_no
|
||||
jmp interrupt_handler_prepare
|
||||
.global isr25
|
||||
.type isr25, @function
|
||||
isr25:
|
||||
cli
|
||||
pushq $0 # err_code
|
||||
pushq $25 # int_no
|
||||
jmp interrupt_handler_prepare
|
||||
.global isr26
|
||||
.type isr26, @function
|
||||
isr26:
|
||||
cli
|
||||
pushq $0 # err_code
|
||||
pushq $26 # int_no
|
||||
jmp interrupt_handler_prepare
|
||||
.global isr27
|
||||
.type isr27, @function
|
||||
isr27:
|
||||
cli
|
||||
pushq $0 # err_code
|
||||
pushq $27 # int_no
|
||||
jmp interrupt_handler_prepare
|
||||
.global isr28
|
||||
.type isr28, @function
|
||||
isr28:
|
||||
cli
|
||||
pushq $0 # err_code
|
||||
pushq $28 # int_no
|
||||
jmp interrupt_handler_prepare
|
||||
.global isr29
|
||||
.type isr29, @function
|
||||
isr29:
|
||||
cli
|
||||
pushq $0 # err_code
|
||||
pushq $29 # int_no
|
||||
jmp interrupt_handler_prepare
|
||||
.global isr30
|
||||
.type isr30, @function
|
||||
isr30:
|
||||
cli
|
||||
pushq $0 # err_code
|
||||
pushq $30 # int_no
|
||||
jmp interrupt_handler_prepare
|
||||
.global isr31
|
||||
.type isr31, @function
|
||||
isr31:
|
||||
cli
|
||||
pushq $0 # err_code
|
||||
pushq $31 # int_no
|
||||
jmp interrupt_handler_prepare
|
||||
.global isr128
|
||||
.type isr128, @function
|
||||
isr128:
|
||||
cli
|
||||
pushq $0 # err_code
|
||||
pushq $128 # int_no
|
||||
jmp interrupt_handler_prepare
|
||||
.global isr130
|
||||
.type isr130, @function
|
||||
isr130:
|
||||
cli
|
||||
pushq $0 # err_code
|
||||
pushq $130 # int_no
|
||||
jmp interrupt_handler_prepare
|
||||
.global isr131
|
||||
.type isr131, @function
|
||||
isr131:
|
||||
cli
|
||||
pushq $0 # err_code
|
||||
pushq $131 # int_no
|
||||
jmp interrupt_handler_prepare
|
||||
.global irq0
|
||||
.type irq0, @function
|
||||
irq0:
|
||||
cli
|
||||
pushq $0 # err_code
|
||||
pushq $32 # int_no
|
||||
jmp interrupt_handler_prepare
|
||||
.global irq1
|
||||
.type irq1, @function
|
||||
irq1:
|
||||
cli
|
||||
pushq $0 # err_code
|
||||
pushq $33 # int_no
|
||||
jmp interrupt_handler_prepare
|
||||
.global irq2
|
||||
.type irq2, @function
|
||||
irq2:
|
||||
cli
|
||||
pushq $0 # err_code
|
||||
pushq $34 # int_no
|
||||
jmp interrupt_handler_prepare
|
||||
.global irq3
|
||||
.type irq3, @function
|
||||
irq3:
|
||||
cli
|
||||
pushq $0 # err_code
|
||||
pushq $35 # int_no
|
||||
jmp interrupt_handler_prepare
|
||||
.global irq4
|
||||
.type irq4, @function
|
||||
irq4:
|
||||
cli
|
||||
pushq $0 # err_code
|
||||
pushq $36 # int_no
|
||||
jmp interrupt_handler_prepare
|
||||
.global irq5
|
||||
.type irq5, @function
|
||||
irq5:
|
||||
cli
|
||||
pushq $0 # err_code
|
||||
pushq $37 # int_no
|
||||
jmp interrupt_handler_prepare
|
||||
.global irq6
|
||||
.type irq6, @function
|
||||
irq6:
|
||||
cli
|
||||
pushq $0 # err_code
|
||||
pushq $38 # int_no
|
||||
jmp interrupt_handler_prepare
|
||||
.global irq7
|
||||
.type irq7, @function
|
||||
irq7:
|
||||
cli
|
||||
pushq $0 # err_code
|
||||
pushq $39 # int_no
|
||||
jmp interrupt_handler_prepare
|
||||
.global irq8
|
||||
.type irq8, @function
|
||||
irq8:
|
||||
cli
|
||||
pushq $0 # err_code
|
||||
pushq $40 # int_no
|
||||
jmp interrupt_handler_prepare
|
||||
.global irq9
|
||||
.type irq9, @function
|
||||
irq9:
|
||||
cli
|
||||
pushq $0 # err_code
|
||||
pushq $41 # int_no
|
||||
jmp interrupt_handler_prepare
|
||||
.global irq10
|
||||
.type irq10, @function
|
||||
irq10:
|
||||
cli
|
||||
pushq $0 # err_code
|
||||
pushq $42 # int_no
|
||||
jmp interrupt_handler_prepare
|
||||
.global irq11
|
||||
.type irq11, @function
|
||||
irq11:
|
||||
cli
|
||||
pushq $0 # err_code
|
||||
pushq $43 # int_no
|
||||
jmp interrupt_handler_prepare
|
||||
.global irq12
|
||||
.type irq12, @function
|
||||
irq12:
|
||||
cli
|
||||
pushq $0 # err_code
|
||||
pushq $44 # int_no
|
||||
jmp interrupt_handler_prepare
|
||||
.global irq13
|
||||
.type irq13, @function
|
||||
irq13:
|
||||
cli
|
||||
pushq $0 # err_code
|
||||
pushq $45 # int_no
|
||||
jmp interrupt_handler_prepare
|
||||
.global irq14
|
||||
.type irq14, @function
|
||||
irq14:
|
||||
cli
|
||||
pushq $0 # err_code
|
||||
pushq $46 # int_no
|
||||
jmp interrupt_handler_prepare
|
||||
.global irq15
|
||||
.type irq15, @function
|
||||
irq15:
|
||||
cli
|
||||
pushq $0 # err_code
|
||||
pushq $47 # int_no
|
||||
jmp interrupt_handler_prepare
|
||||
.global yield_cpu_handler
|
||||
.type yield_cpu_handler, @function
|
||||
yield_cpu_handler:
|
||||
cli
|
||||
pushq $0 # err_code
|
||||
pushq $129 # int_no
|
||||
jmp interrupt_handler_prepare
|
||||
.global thread_exit_handler
|
||||
.type thread_exit_handler, @function
|
||||
thread_exit_handler:
|
||||
cli
|
||||
pushq $0 # err_code
|
||||
pushq $132 # int_no
|
||||
jmp interrupt_handler_prepare
|
||||
|
||||
interrupt_handler_prepare:
|
||||
movq $1, asm_is_cpu_interrupted
|
||||
|
||||
pushq %r15
|
||||
pushq %r14
|
||||
pushq %r13
|
||||
pushq %r12
|
||||
pushq %r11
|
||||
pushq %r10
|
||||
pushq %r9
|
||||
pushq %r8
|
||||
pushq %rax
|
||||
pushq %rcx
|
||||
pushq %rdx
|
||||
pushq %rbx
|
||||
pushq %rsp
|
||||
pushq %rbp
|
||||
pushq %rsi
|
||||
pushq %rdi
|
||||
|
||||
# Push the user-space data segment.
|
||||
movl %ds, %ebp
|
||||
pushq %rbp
|
||||
|
||||
# Load the kernel data segment.
|
||||
movw $0x10, %bp
|
||||
movl %ebp, %ds
|
||||
movl %ebp, %es
|
||||
movl %ebp, %fs
|
||||
movl %ebp, %gs
|
||||
|
||||
# Push CR2 in case of page faults
|
||||
movq %cr2, %rbp
|
||||
pushq %rbp
|
||||
|
||||
# Push the current kernel errno value.
|
||||
movl global_errno, %ebp
|
||||
pushq %rbp
|
||||
|
||||
# Push whether a signal is pending.
|
||||
movq asm_signal_is_pending, %rbp
|
||||
pushq %rbp
|
||||
|
||||
# Now call the interrupt handler.
|
||||
movq %rsp, %rdi
|
||||
call interrupt_handler
|
||||
|
||||
load_interrupted_registers:
|
||||
# Restore whether signals are pending.
|
||||
popq %rbp
|
||||
movq %rbp, asm_signal_is_pending
|
||||
|
||||
# Restore the previous kernel errno.
|
||||
popq %rbp
|
||||
movl %ebp, global_errno
|
||||
|
||||
# Remove CR2 from the stack.
|
||||
addq $8, %rsp
|
||||
|
||||
# Restore the user-space data segment.
|
||||
popq %rbp
|
||||
movl %ebp, %ds
|
||||
movl %ebp, %es
|
||||
movl %ebp, %fs
|
||||
movl %ebp, %gs
|
||||
|
||||
popq %rdi
|
||||
popq %rsi
|
||||
popq %rbp
|
||||
addq $8, %rsp # Don't pop %rsp, may not be defined.
|
||||
popq %rbx
|
||||
popq %rdx
|
||||
popq %rcx
|
||||
popq %rax
|
||||
popq %r8
|
||||
popq %r9
|
||||
popq %r10
|
||||
popq %r11
|
||||
popq %r12
|
||||
popq %r13
|
||||
popq %r14
|
||||
popq %r15
|
||||
|
||||
# Remove int_no and err_code
|
||||
addq $16, %rsp
|
||||
|
||||
movq $0, asm_is_cpu_interrupted
|
||||
|
||||
# Return to where we came from.
|
||||
iretq
|
||||
.size interrupt_handler_prepare, . - interrupt_handler_prepare
|
||||
|
||||
.global interrupt_handler_null
|
||||
.type interrupt_handler_null, @function
|
||||
interrupt_handler_null:
|
||||
iretq
|
||||
.size interrupt_handler_null, . - interrupt_handler_null
|
||||
|
||||
.global asm_interrupts_are_enabled
|
||||
.type asm_interrupts_are_enabled, @function
|
||||
asm_interrupts_are_enabled:
|
||||
pushfq
|
||||
popq %rax
|
||||
andq $0x000200, %rax # FLAGS_INTERRUPT
|
||||
retq
|
||||
.size asm_interrupts_are_enabled, . - asm_interrupts_are_enabled
|
||||
|
||||
.global load_registers
|
||||
.type load_registers, @function
|
||||
load_registers:
|
||||
# Let the register struct become our temporary stack
|
||||
movq %rdi, %rsp
|
||||
jmp load_interrupted_registers
|
||||
.size load_registers, . - load_registers
|
||||
89
kernel/x64/kthread.s
Normal file
89
kernel/x64/kthread.s
Normal file
|
|
@ -0,0 +1,89 @@
|
|||
/*******************************************************************************
|
||||
|
||||
Copyright(C) Jonas 'Sortie' Termansen 2012.
|
||||
|
||||
This file is part of Sortix.
|
||||
|
||||
Sortix is free software: you can redistribute it and/or modify it under the
|
||||
terms of the GNU General Public License as published by the Free Software
|
||||
Foundation, either version 3 of the License, or (at your option) any later
|
||||
version.
|
||||
|
||||
Sortix is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
||||
details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along with
|
||||
Sortix. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
x64/kthread.s
|
||||
Utilities and synchronization mechanisms for x64 kernel threads.
|
||||
|
||||
*******************************************************************************/
|
||||
|
||||
.section .text
|
||||
|
||||
.global kthread_mutex_trylock
|
||||
.type kthread_mutex_trylock, @function
|
||||
kthread_mutex_trylock:
|
||||
pushq %rbp
|
||||
movq %rsp, %rbp
|
||||
movl $-1, %eax
|
||||
xchgl (%rdi), %eax
|
||||
not %eax
|
||||
leaveq
|
||||
retq
|
||||
.size kthread_mutex_trylock, . - kthread_mutex_trylock
|
||||
|
||||
.global kthread_mutex_lock
|
||||
.type kthread_mutex_lock, @function
|
||||
kthread_mutex_lock:
|
||||
pushq %rbp
|
||||
movq %rsp, %rbp
|
||||
kthread_mutex_lock_retry:
|
||||
movl $-1, %eax
|
||||
xchgl (%rdi), %eax
|
||||
testl %eax, %eax
|
||||
jnz kthread_mutex_lock_failed
|
||||
leaveq
|
||||
retq
|
||||
kthread_mutex_lock_failed:
|
||||
int $0x81 # Yield the CPU.
|
||||
jmp kthread_mutex_lock_retry
|
||||
.size kthread_mutex_lock, . - kthread_mutex_lock
|
||||
|
||||
.global kthread_mutex_lock_signal
|
||||
.type kthread_mutex_lock_signal, @function
|
||||
kthread_mutex_lock_signal:
|
||||
pushq %rbp
|
||||
movq %rsp, %rbp
|
||||
kthread_mutex_lock_signal_retry:
|
||||
movq asm_signal_is_pending, %rax
|
||||
testq %rax, %rax
|
||||
jnz kthread_mutex_lock_signal_pending
|
||||
movl $-1, %eax
|
||||
xchgl (%rdi), %eax
|
||||
testl %eax, %eax
|
||||
jnz kthread_mutex_lock_signal_failed
|
||||
inc %eax
|
||||
kthread_mutex_lock_signal_out:
|
||||
leaveq
|
||||
retq
|
||||
kthread_mutex_lock_signal_failed:
|
||||
int $0x81 # Yield the CPU.
|
||||
jmp kthread_mutex_lock_signal_retry
|
||||
kthread_mutex_lock_signal_pending:
|
||||
xorl %eax, %eax
|
||||
jmp kthread_mutex_lock_signal_out
|
||||
.size kthread_mutex_lock_signal, . - kthread_mutex_lock_signal
|
||||
|
||||
.global kthread_mutex_unlock
|
||||
.type kthread_mutex_unlock, @function
|
||||
kthread_mutex_unlock:
|
||||
pushq %rbp
|
||||
movq %rsp, %rbp
|
||||
movl $0, (%rdi)
|
||||
leaveq
|
||||
retq
|
||||
.size kthread_mutex_unlock, . - kthread_mutex_unlock
|
||||
211
kernel/x64/memorymanagement.cpp
Normal file
211
kernel/x64/memorymanagement.cpp
Normal file
|
|
@ -0,0 +1,211 @@
|
|||
/*******************************************************************************
|
||||
|
||||
Copyright(C) Jonas 'Sortie' Termansen 2011, 2012.
|
||||
|
||||
This file is part of Sortix.
|
||||
|
||||
Sortix is free software: you can redistribute it and/or modify it under the
|
||||
terms of the GNU General Public License as published by the Free Software
|
||||
Foundation, either version 3 of the License, or (at your option) any later
|
||||
version.
|
||||
|
||||
Sortix is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
||||
details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along with
|
||||
Sortix. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
x64/memorymanagement.cpp
|
||||
Handles memory for the x64 architecture.
|
||||
|
||||
*******************************************************************************/
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include <sortix/kernel/interrupt.h>
|
||||
#include <sortix/kernel/kernel.h>
|
||||
#include <sortix/kernel/memorymanagement.h>
|
||||
|
||||
#include "multiboot.h"
|
||||
#include "x86-family/memorymanagement.h"
|
||||
|
||||
namespace Sortix
|
||||
{
|
||||
namespace Page
|
||||
{
|
||||
extern size_t stackused;
|
||||
extern size_t stacklength;
|
||||
void ExtendStack();
|
||||
}
|
||||
|
||||
namespace Memory
|
||||
{
|
||||
extern addr_t currentdir;
|
||||
|
||||
void InitCPU()
|
||||
{
|
||||
// The x64 boot code already set up virtual memory and identity
|
||||
// mapped the first 2 MiB. This code finishes the job such that
|
||||
// virtual memory is fully usable and manageable.
|
||||
|
||||
// boot.s already initialized everything from 0x1000UL to 0xE000UL
|
||||
// to zeroes. Since these structures are already used, doing it here
|
||||
// will be very dangerous.
|
||||
|
||||
PML* const BOOTPML4 = (PML* const) 0x21000UL;
|
||||
PML* const BOOTPML3 = (PML* const) 0x26000UL;
|
||||
PML* const BOOTPML2 = (PML* const) 0x27000UL;
|
||||
PML* const BOOTPML1 = (PML* const) 0x28000UL;
|
||||
|
||||
// First order of business is to map the virtual memory structures
|
||||
// to the pre-defined locations in the virtual address space.
|
||||
addr_t flags = PML_PRESENT | PML_WRITABLE;
|
||||
|
||||
// Fractal map the PML1s.
|
||||
BOOTPML4->entry[511] = (addr_t) BOOTPML4 | flags;
|
||||
|
||||
// Fractal map the PML2s.
|
||||
BOOTPML4->entry[510] = (addr_t) BOOTPML3 | flags | PML_FORK;
|
||||
BOOTPML3->entry[511] = (addr_t) BOOTPML4 | flags;
|
||||
|
||||
// Fractal map the PML3s.
|
||||
BOOTPML3->entry[510] = (addr_t) BOOTPML2 | flags | PML_FORK;
|
||||
BOOTPML2->entry[511] = (addr_t) BOOTPML4 | flags;
|
||||
|
||||
// Fractal map the PML4s.
|
||||
BOOTPML2->entry[510] = (addr_t) BOOTPML1 | flags | PML_FORK;
|
||||
BOOTPML1->entry[511] = (addr_t) BOOTPML4 | flags;
|
||||
|
||||
// Add some predefined room for forking address spaces.
|
||||
PML* const FORKPML2 = (PML* const) 0x29000UL;
|
||||
PML* const FORKPML1 = (PML* const) 0x2A000UL;
|
||||
|
||||
BOOTPML3->entry[0] = (addr_t) FORKPML2 | flags | PML_FORK;
|
||||
BOOTPML2->entry[0] = (addr_t) FORKPML1 | flags | PML_FORK;
|
||||
|
||||
currentdir = (addr_t) BOOTPML4;
|
||||
|
||||
// The virtual memory structures are now available on the predefined
|
||||
// locations. This means the virtual memory code is bootstrapped. Of
|
||||
// course, we still have no physical page allocator, so that's the
|
||||
// next step.
|
||||
|
||||
PML* const PHYSPML3 = (PML* const) 0x2B000UL;
|
||||
PML* const PHYSPML2 = (PML* const) 0x2C000UL;
|
||||
PML* const PHYSPML1 = (PML* const) 0x2D000UL;
|
||||
PML* const PHYSPML0 = (PML* const) 0x2E000UL;
|
||||
|
||||
BOOTPML4->entry[509] = (addr_t) PHYSPML3 | flags;
|
||||
PHYSPML3->entry[0] = (addr_t) PHYSPML2 | flags;
|
||||
PHYSPML2->entry[0] = (addr_t) PHYSPML1 | flags;
|
||||
PHYSPML1->entry[0] = (addr_t) PHYSPML0 | flags;
|
||||
|
||||
Page::stackused = 0;
|
||||
Page::stacklength = 4096UL / sizeof(addr_t);
|
||||
|
||||
// The physical memory allocator should now be ready for use. Next
|
||||
// up, the calling function will fill up the physical allocator with
|
||||
// plenty of nice physical pages. (see Page::InitPushRegion)
|
||||
}
|
||||
|
||||
// Please note that even if this function exists, you should still clean
|
||||
// up the address space of a process _before_ calling
|
||||
// DestroyAddressSpace. This is just a hack because it currently is
|
||||
// impossible to clean up PLM1's using the MM api!
|
||||
// ---
|
||||
// TODO: This function is duplicated in {x86,x64}/memorymanagement.cpp!
|
||||
// ---
|
||||
void RecursiveFreeUserspacePages(size_t level, size_t offset)
|
||||
{
|
||||
PML* pml = PMLS[level] + offset;
|
||||
for ( size_t i = 0; i < ENTRIES; i++ )
|
||||
{
|
||||
addr_t entry = pml->entry[i];
|
||||
if ( !(entry & PML_PRESENT) ) { continue; }
|
||||
if ( !(entry & PML_USERSPACE) ) { continue; }
|
||||
if ( !(entry & PML_FORK) ) { continue; }
|
||||
if ( level > 1 ) { RecursiveFreeUserspacePages(level-1, offset * ENTRIES + i); }
|
||||
addr_t addr = pml->entry[i] & PML_ADDRESS;
|
||||
// No need to unmap the page, we just need to mark it as unused.
|
||||
Page::PutUnlocked(addr);
|
||||
}
|
||||
}
|
||||
|
||||
void DestroyAddressSpace(addr_t fallback, void (*func)(addr_t, void*), void* user)
|
||||
{
|
||||
// Look up the last few entries used for the fractal mapping. These
|
||||
// cannot be unmapped as that would destroy the world. Instead, we
|
||||
// will remember them, switch to another adress space, and safely
|
||||
// mark them as unused. Also handling the forking related pages.
|
||||
addr_t fractal3 = (PMLS[4] + 0)->entry[510UL];
|
||||
addr_t fork2 = (PMLS[3] + 510UL)->entry[0];
|
||||
addr_t fractal2 = (PMLS[3] + 510UL)->entry[510];
|
||||
addr_t fork1 = (PMLS[2] + 510UL * 512UL + 510UL)->entry[0];
|
||||
addr_t fractal1 = (PMLS[2] + 510UL * 512UL + 510UL)->entry[510];
|
||||
addr_t dir = currentdir;
|
||||
|
||||
// We want to free the pages, but we are still using them ourselves,
|
||||
// so lock the page allocation structure until we are done.
|
||||
Page::Lock();
|
||||
|
||||
// In case any pages wasn't cleaned at this point.
|
||||
// TODO: Page::Put calls may internally Page::Get and then reusing pages we are not done with just yet
|
||||
RecursiveFreeUserspacePages(TOPPMLLEVEL, 0);
|
||||
|
||||
// Switch to the address space from when the world was originally
|
||||
// created. It should contain the kernel, the whole kernel, and
|
||||
// nothing but the kernel.
|
||||
PML* const BOOTPML4 = (PML* const) 0x21000UL;
|
||||
if ( !fallback )
|
||||
fallback = (addr_t) BOOTPML4;
|
||||
|
||||
if ( func )
|
||||
func(fallback, user);
|
||||
else
|
||||
SwitchAddressSpace(fallback);
|
||||
|
||||
// Ok, now we got marked everything left behind as unused, we can
|
||||
// now safely let another thread use the pages.
|
||||
Page::Unlock();
|
||||
|
||||
// These are safe to free since we switched address space.
|
||||
Page::Put(fractal3 & PML_ADDRESS);
|
||||
Page::Put(fractal2 & PML_ADDRESS);
|
||||
Page::Put(fractal1 & PML_ADDRESS);
|
||||
Page::Put(fork2 & PML_ADDRESS);
|
||||
Page::Put(fork1 & PML_ADDRESS);
|
||||
Page::Put(dir & PML_ADDRESS);
|
||||
}
|
||||
|
||||
const size_t KERNEL_STACK_SIZE = 256UL * 1024UL;
|
||||
const addr_t KERNEL_STACK_END = 0xFFFF800000001000UL;
|
||||
const addr_t KERNEL_STACK_START = KERNEL_STACK_END + KERNEL_STACK_SIZE;
|
||||
|
||||
const addr_t VIRTUAL_AREA_LOWER = KERNEL_STACK_START;
|
||||
const addr_t VIRTUAL_AREA_UPPER = 0xFFFFFE8000000000UL;
|
||||
|
||||
void GetKernelVirtualArea(addr_t* from, size_t* size)
|
||||
{
|
||||
*from = KERNEL_STACK_END;
|
||||
*size = VIRTUAL_AREA_UPPER - VIRTUAL_AREA_LOWER;
|
||||
}
|
||||
|
||||
void GetUserVirtualArea(uintptr_t* from, size_t* size)
|
||||
{
|
||||
*from = 0x400000; // 4 MiB.
|
||||
*size = 0x800000000000 - *from; // 128 TiB - 4 MiB.
|
||||
}
|
||||
|
||||
addr_t GetKernelStack()
|
||||
{
|
||||
return KERNEL_STACK_START;
|
||||
}
|
||||
|
||||
size_t GetKernelStackSize()
|
||||
{
|
||||
return KERNEL_STACK_SIZE;
|
||||
}
|
||||
}
|
||||
}
|
||||
56
kernel/x64/memorymanagement.h
Normal file
56
kernel/x64/memorymanagement.h
Normal file
|
|
@ -0,0 +1,56 @@
|
|||
/*******************************************************************************
|
||||
|
||||
Copyright(C) Jonas 'Sortie' Termansen 2011.
|
||||
|
||||
This file is part of Sortix.
|
||||
|
||||
Sortix is free software: you can redistribute it and/or modify it under the
|
||||
terms of the GNU General Public License as published by the Free Software
|
||||
Foundation, either version 3 of the License, or (at your option) any later
|
||||
version.
|
||||
|
||||
Sortix is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
||||
details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along with
|
||||
Sortix. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
x64/memorymanagement.h
|
||||
Handles memory for the x64 architecture.
|
||||
|
||||
*******************************************************************************/
|
||||
|
||||
#ifndef SORTIX_X64_MEMORYMANAGEMENT_H
|
||||
#define SORTIX_X64_MEMORYMANAGEMENT_H
|
||||
|
||||
namespace Sortix
|
||||
{
|
||||
namespace Memory
|
||||
{
|
||||
const size_t TOPPMLLEVEL = 4;
|
||||
const size_t ENTRIES = 4096UL / sizeof(addr_t);
|
||||
const size_t TRANSBITS = 9;
|
||||
|
||||
PML* const PMLS[TOPPMLLEVEL + 1] =
|
||||
{
|
||||
(PML* const) 0x0,
|
||||
(PML* const) 0xFFFFFF8000000000UL,
|
||||
(PML* const) 0xFFFFFF7FC0000000UL,
|
||||
(PML* const) 0XFFFFFF7FBFE00000UL,
|
||||
(PML* const) 0xFFFFFF7FBFDFF000UL,
|
||||
};
|
||||
|
||||
PML* const FORKPML = (PML* const) 0xFFFFFF0000000000UL;
|
||||
}
|
||||
|
||||
namespace Page
|
||||
{
|
||||
addr_t* const STACK = (addr_t* const) 0xFFFFFE8000000000UL;
|
||||
const size_t MAXSTACKSIZE = (512UL*1024UL*1024UL*1024UL);
|
||||
const size_t MAXSTACKLENGTH = MAXSTACKSIZE / sizeof(addr_t);
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
84
kernel/x64/process.cpp
Normal file
84
kernel/x64/process.cpp
Normal file
|
|
@ -0,0 +1,84 @@
|
|||
/*******************************************************************************
|
||||
|
||||
Copyright(C) Jonas 'Sortie' Termansen 2011, 2012.
|
||||
|
||||
This file is part of Sortix.
|
||||
|
||||
Sortix is free software: you can redistribute it and/or modify it under the
|
||||
terms of the GNU General Public License as published by the Free Software
|
||||
Foundation, either version 3 of the License, or (at your option) any later
|
||||
version.
|
||||
|
||||
Sortix is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
||||
details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along with
|
||||
Sortix. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
x64/process.cpp
|
||||
CPU-specific process code.
|
||||
|
||||
*******************************************************************************/
|
||||
|
||||
#include <sys/types.h>
|
||||
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <sortix/fork.h>
|
||||
|
||||
#include <sortix/kernel/kernel.h>
|
||||
#include <sortix/kernel/process.h>
|
||||
|
||||
namespace Sortix
|
||||
{
|
||||
void Process::ExecuteCPU(int argc, char** argv, int envc, char** envp,
|
||||
addr_t stackpos, addr_t entry,
|
||||
CPU::InterruptRegisters* regs)
|
||||
{
|
||||
const uint64_t CS = 0x18;
|
||||
const uint64_t DS = 0x20;
|
||||
const uint64_t RPL = 0x3;
|
||||
|
||||
regs->rdi = argc;
|
||||
regs->rsi = (size_t) argv;
|
||||
regs->rdx = envc;
|
||||
regs->rcx = (size_t) envp;
|
||||
regs->rip = entry;
|
||||
regs->userrsp = stackpos & ~(15UL);
|
||||
regs->rbp = regs->userrsp;
|
||||
regs->cs = CS | RPL;
|
||||
regs->ds = DS | RPL;
|
||||
regs->ss = DS | RPL;
|
||||
regs->rflags = FLAGS_RESERVED1 | FLAGS_INTERRUPT | FLAGS_ID;
|
||||
}
|
||||
|
||||
void InitializeThreadRegisters(CPU::InterruptRegisters* regs,
|
||||
const tforkregs_t* requested)
|
||||
{
|
||||
memset(regs, 0, sizeof(*regs));
|
||||
regs->rip = requested->rip;
|
||||
regs->userrsp = requested->rsp;
|
||||
regs->rax = requested->rax;
|
||||
regs->rbx = requested->rbx;
|
||||
regs->rcx = requested->rcx;
|
||||
regs->rdx = requested->rdx;
|
||||
regs->rdi = requested->rdi;
|
||||
regs->rsi = requested->rsi;
|
||||
regs->rbp = requested->rbp;
|
||||
regs->r8 = requested->r8;
|
||||
regs->r9 = requested->r9;
|
||||
regs->r10 = requested->r10;
|
||||
regs->r11 = requested->r11;
|
||||
regs->r12 = requested->r12;
|
||||
regs->r13 = requested->r13;
|
||||
regs->r14 = requested->r14;
|
||||
regs->r15 = requested->r15;
|
||||
regs->cs = 0x18 | 0x3;
|
||||
regs->ds = 0x20 | 0x3;
|
||||
regs->ss = 0x20 | 0x3;
|
||||
regs->rflags = FLAGS_RESERVED1 | FLAGS_INTERRUPT | FLAGS_ID;
|
||||
}
|
||||
}
|
||||
83
kernel/x64/syscall.s
Normal file
83
kernel/x64/syscall.s
Normal file
|
|
@ -0,0 +1,83 @@
|
|||
/*******************************************************************************
|
||||
|
||||
Copyright(C) Jonas 'Sortie' Termansen 2011, 2012, 2013.
|
||||
|
||||
This file is part of Sortix.
|
||||
|
||||
Sortix is free software: you can redistribute it and/or modify it under the
|
||||
terms of the GNU General Public License as published by the Free Software
|
||||
Foundation, either version 3 of the License, or (at your option) any later
|
||||
version.
|
||||
|
||||
Sortix is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
||||
details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along with
|
||||
Sortix. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
x64/syscall.s
|
||||
An assembly stub that acts as glue for system calls.
|
||||
|
||||
*******************************************************************************/
|
||||
|
||||
.global syscall_handler
|
||||
|
||||
.section .text
|
||||
.type syscall_handler, @function
|
||||
syscall_handler:
|
||||
# The processor disabled interrupts during the int $0x80 instruction,
|
||||
# however Sortix system calls runs with interrupts enabled such that they
|
||||
# can be pre-empted.
|
||||
sti
|
||||
|
||||
movl $0, global_errno # Reset errno
|
||||
|
||||
pushq %rbp
|
||||
movq %rsp, %rbp
|
||||
|
||||
# Make sure the requested system call is valid, if not, then fix it.
|
||||
cmp SYSCALL_MAX, %rax
|
||||
jae fix_syscall
|
||||
|
||||
valid_syscall:
|
||||
# Read a system call function pointer.
|
||||
xorq %r11, %r11
|
||||
movq syscall_list(%r11,%rax,8), %rax
|
||||
|
||||
# Oh how nice, user-space put the parameters in: rdi, rsi, rdx, rcx, r8, r9
|
||||
|
||||
# Call the system call.
|
||||
callq *%rax
|
||||
|
||||
# Return to user-space, system call result in %rax:%rdx, errno in %ecx.
|
||||
popq %rbp
|
||||
movl global_errno, %ecx
|
||||
|
||||
# If any signals are pending, fire them now.
|
||||
movq asm_signal_is_pending, %rdi
|
||||
testq %rdi, %rdi
|
||||
jnz call_signal_dispatcher
|
||||
|
||||
iretq
|
||||
|
||||
fix_syscall:
|
||||
# Call the null system call instead.
|
||||
xorq %rax, %rax
|
||||
jmp valid_syscall
|
||||
|
||||
call_signal_dispatcher:
|
||||
# We can't return to this location after the signal, since if any system
|
||||
# call is made this stack will get reused and all our nice temporaries wil
|
||||
# be garbage. We therefore pass the kernel the state to return to and it'll
|
||||
# handle it for us when the signal is over.
|
||||
movq 0(%rsp), %rdi # userspace rip
|
||||
movq 16(%rsp), %rsi # userspace rflags
|
||||
movq 24(%rsp), %r8 # userspace rsp, note %rcx is used for errno
|
||||
int $130 # Deliver pending signals.
|
||||
# If we end up here, it means that the signal didn't override anything and
|
||||
# that we should just go ahead and return to userspace ourselves.
|
||||
iretq
|
||||
|
||||
.size syscall_handler, .-syscall_handler
|
||||
155
kernel/x64/thread.cpp
Normal file
155
kernel/x64/thread.cpp
Normal file
|
|
@ -0,0 +1,155 @@
|
|||
/*******************************************************************************
|
||||
|
||||
Copyright(C) Jonas 'Sortie' Termansen 2011, 2012.
|
||||
|
||||
This file is part of Sortix.
|
||||
|
||||
Sortix is free software: you can redistribute it and/or modify it under the
|
||||
terms of the GNU General Public License as published by the Free Software
|
||||
Foundation, either version 3 of the License, or (at your option) any later
|
||||
version.
|
||||
|
||||
Sortix is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
||||
details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along with
|
||||
Sortix. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
x64/thread.cpp
|
||||
x64 specific parts of thread.cpp.
|
||||
|
||||
*******************************************************************************/
|
||||
|
||||
#include <sortix/kernel/kernel.h>
|
||||
#include <sortix/kernel/thread.h>
|
||||
|
||||
namespace Sortix
|
||||
{
|
||||
void Thread::SaveRegisters(const CPU::InterruptRegisters* src)
|
||||
{
|
||||
registers.rip = src->rip;
|
||||
registers.userrsp = src->userrsp;
|
||||
registers.rax = src->rax;
|
||||
registers.rbx = src->rbx;
|
||||
registers.rcx = src->rcx;
|
||||
registers.rdx = src->rdx;
|
||||
registers.rdi = src->rdi;
|
||||
registers.rsi = src->rsi;
|
||||
registers.rbp = src->rbp;
|
||||
registers.r8 = src->r8;
|
||||
registers.r9 = src->r9;
|
||||
registers.r10 = src->r10;
|
||||
registers.r11 = src->r11;
|
||||
registers.r12 = src->r12;
|
||||
registers.r13 = src->r13;
|
||||
registers.r14 = src->r14;
|
||||
registers.r15 = src->r15;
|
||||
registers.cs = src->cs;
|
||||
registers.ds = src->ds;
|
||||
registers.ss = src->ss;
|
||||
registers.rflags = src->rflags;
|
||||
registers.kerrno = src->kerrno;
|
||||
registers.signal_pending = src->signal_pending;
|
||||
}
|
||||
|
||||
void Thread::LoadRegisters(CPU::InterruptRegisters* dest)
|
||||
{
|
||||
dest->rip = registers.rip;
|
||||
dest->userrsp = registers.userrsp;
|
||||
dest->rax = registers.rax;
|
||||
dest->rbx = registers.rbx;
|
||||
dest->rcx = registers.rcx;
|
||||
dest->rdx = registers.rdx;
|
||||
dest->rdi = registers.rdi;
|
||||
dest->rsi = registers.rsi;
|
||||
dest->rbp = registers.rbp;
|
||||
dest->r8 = registers.r8;
|
||||
dest->r9 = registers.r9;
|
||||
dest->r10 = registers.r10;
|
||||
dest->r11 = registers.r11;
|
||||
dest->r12 = registers.r12;
|
||||
dest->r13 = registers.r13;
|
||||
dest->r14 = registers.r14;
|
||||
dest->r15 = registers.r15;
|
||||
dest->cs = registers.cs;
|
||||
dest->ds = registers.ds;
|
||||
dest->ss = registers.ss;
|
||||
dest->rflags = registers.rflags;
|
||||
dest->kerrno = registers.kerrno;
|
||||
dest->signal_pending = registers.signal_pending;
|
||||
}
|
||||
|
||||
void SetupKernelThreadRegs(CPU::InterruptRegisters* regs, ThreadEntry entry,
|
||||
void* user, addr_t stack, size_t stacksize)
|
||||
{
|
||||
// Instead of directly calling the desired entry point, we call a small
|
||||
// stub that calls it for us and then destroys the kernel thread if
|
||||
// the entry function returns. Note that since we use a register based
|
||||
// calling convention, we call BootstrapKernelThread directly.
|
||||
regs->rip = (addr_t) BootstrapKernelThread;
|
||||
regs->userrsp = stack + stacksize - sizeof(size_t);
|
||||
*((size_t*) regs->userrsp) = 0; /* back tracing stops at NULL rip */
|
||||
regs->rax = 0;
|
||||
regs->rbx = 0;
|
||||
regs->rcx = 0;
|
||||
regs->rdx = 0;
|
||||
regs->rdi = (addr_t) user;
|
||||
regs->rsi = (addr_t) entry;
|
||||
regs->rbp = 0;
|
||||
regs->r8 = 0;
|
||||
regs->r9 = 0;
|
||||
regs->r10 = 0;
|
||||
regs->r11 = 0;
|
||||
regs->r12 = 0;
|
||||
regs->r13 = 0;
|
||||
regs->r14 = 0;
|
||||
regs->r15 = 0;
|
||||
regs->cs = KCS | KRPL;
|
||||
regs->ds = KDS | KRPL;
|
||||
regs->ss = KDS | KRPL;
|
||||
regs->rflags = FLAGS_RESERVED1 | FLAGS_INTERRUPT | FLAGS_ID;
|
||||
regs->kerrno = 0;
|
||||
regs->signal_pending = 0;
|
||||
}
|
||||
|
||||
void Thread::HandleSignalFixupRegsCPU(CPU::InterruptRegisters* regs)
|
||||
{
|
||||
if ( regs->InUserspace() )
|
||||
return;
|
||||
regs->rip = regs->rdi;
|
||||
regs->rflags = regs->rsi;
|
||||
regs->userrsp = regs->r8;
|
||||
regs->cs = UCS | URPL;
|
||||
regs->ds = UDS | URPL;
|
||||
regs->ss = UDS | URPL;
|
||||
}
|
||||
|
||||
void Thread::HandleSignalCPU(CPU::InterruptRegisters* regs)
|
||||
{
|
||||
const size_t STACK_ALIGNMENT = 16UL;
|
||||
const size_t RED_ZONE_SIZE = 128UL;
|
||||
regs->userrsp -= RED_ZONE_SIZE;
|
||||
regs->userrsp &= ~(STACK_ALIGNMENT-1UL);
|
||||
regs->rbp = regs->userrsp;
|
||||
regs->rdi = currentsignal;
|
||||
regs->rip = (size_t) sighandler;
|
||||
regs->rflags = FLAGS_RESERVED1 | FLAGS_INTERRUPT | FLAGS_ID;
|
||||
regs->kerrno = 0;
|
||||
regs->signal_pending = 0;
|
||||
}
|
||||
|
||||
void Thread::GotoOnSigKill(CPU::InterruptRegisters* regs)
|
||||
{
|
||||
regs->rip = (unsigned long) Thread__OnSigKill;
|
||||
regs->rdi = (unsigned long) this;
|
||||
regs->userrsp = regs->rbp = kernelstackpos + kernelstacksize;
|
||||
regs->rflags = FLAGS_RESERVED1 | FLAGS_INTERRUPT | FLAGS_ID;
|
||||
regs->cs = KCS | KRPL;
|
||||
regs->ds = KDS | KRPL;
|
||||
regs->ss = KDS | KRPL;
|
||||
regs->kerrno = 0;
|
||||
regs->signal_pending = 0;
|
||||
}
|
||||
}
|
||||
49
kernel/x64/x64.cpp
Normal file
49
kernel/x64/x64.cpp
Normal file
|
|
@ -0,0 +1,49 @@
|
|||
/*******************************************************************************
|
||||
|
||||
Copyright(C) Jonas 'Sortie' Termansen 2011.
|
||||
|
||||
This file is part of Sortix.
|
||||
|
||||
Sortix is free software: you can redistribute it and/or modify it under the
|
||||
terms of the GNU General Public License as published by the Free Software
|
||||
Foundation, either version 3 of the License, or (at your option) any later
|
||||
version.
|
||||
|
||||
Sortix is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
||||
details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along with
|
||||
Sortix. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
x64/x64.cpp
|
||||
CPU stuff for the x64 platform.
|
||||
|
||||
*******************************************************************************/
|
||||
|
||||
#include <sortix/kernel/cpu.h>
|
||||
#include <sortix/kernel/kernel.h>
|
||||
#include <sortix/kernel/log.h>
|
||||
|
||||
namespace Sortix
|
||||
{
|
||||
namespace X64
|
||||
{
|
||||
void InterruptRegisters::LogRegisters() const
|
||||
{
|
||||
Log::PrintF("[cr2=0x%zx,ds=0x%zx,rdi=0x%zx,rsi=0x%zx,rbp=0x%zx,"
|
||||
"rsp=0x%zx,rbx=0x%zx,rdx=0x%zx,rcx=0x%zx,rax=0x%zx,"
|
||||
"r8=0x%zx,r9=0x%zx,r10=0x%zx,r11=0x%zx,r12=0x%zx,"
|
||||
"r13=0x%zx,r14=0x%zx,r15=0x%zx,int_no=0x%zx,"
|
||||
"err_code=0x%zx,rip=0x%zx,cs=0x%zx,rflags=0x%zx,"
|
||||
"userrsp=0x%zx,ss=0x%zx]",
|
||||
cr2, ds, rdi, rsi, rbp,
|
||||
rsp, rbx, rdx, rcx, rax,
|
||||
r8, r9, r10, r11, r12,
|
||||
r13, r14, r15, int_no,
|
||||
err_code, rip, cs, rflags,
|
||||
userrsp, ss);
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue