diff --git a/.vscode/extensions.json b/.vscode/extensions.json
index 091659f..3ccb126 100644
--- a/.vscode/extensions.json
+++ b/.vscode/extensions.json
@@ -9,6 +9,6 @@
"ibm.output-colorizer",
"wayou.vscode-todo-highlight",
"gruntfuggly.todo-tree",
- "13xforever.language-x86-64-assembly"
+ "maziac.asm-code-lens"
]
}
\ No newline at end of file
diff --git a/Architecture/amd64/Bootstrap/Multiboot/1/Start.asm b/Architecture/amd64/Bootstrap/Multiboot/1/Start.asm
deleted file mode 100644
index 49bc2c2..0000000
--- a/Architecture/amd64/Bootstrap/Multiboot/1/Start.asm
+++ /dev/null
@@ -1,22 +0,0 @@
-; This file is part of Fennix Kernel.
-;
-; Fennix Kernel 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.
-;
-; Fennix Kernel 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 Fennix Kernel. If not, see .
-
-[bits 32]
-
-section .bootstrap.text
-
-global Multiboot1_start
-Multiboot1_start:
- int3
diff --git a/Architecture/i386/Bootstrap/Multiboot/2/Start.s_fixme b/Architecture/amd64/Bootstrap/Multiboot/1/Start.s
similarity index 90%
rename from Architecture/i386/Bootstrap/Multiboot/2/Start.s_fixme
rename to Architecture/amd64/Bootstrap/Multiboot/1/Start.s
index 8d58c66..8efbeb2 100644
--- a/Architecture/i386/Bootstrap/Multiboot/2/Start.s_fixme
+++ b/Architecture/amd64/Bootstrap/Multiboot/1/Start.s
@@ -15,6 +15,9 @@
along with Fennix Kernel. If not, see .
*/
-.intel_syntax noprefix
-
.code32
+.section .bootstrap.text
+
+.global Multiboot1_start
+Multiboot1_start:
+ jmp .
diff --git a/Architecture/amd64/Bootstrap/Multiboot/2/Detect.s b/Architecture/amd64/Bootstrap/Multiboot/2/Detect.s
index 319d180..cda5c35 100644
--- a/Architecture/amd64/Bootstrap/Multiboot/2/Detect.s
+++ b/Architecture/amd64/Bootstrap/Multiboot/2/Detect.s
@@ -25,7 +25,7 @@ DetectCPUID:
pushfd
pop eax
mov ecx, eax
- xor eax, 1 << 21
+ xor eax, 0x200000
push eax
popfd
pushfd
@@ -34,7 +34,7 @@ DetectCPUID:
popfd
xor eax, ecx
jz .NoCPUID
- mov eax, 1
+ mov eax, 0x1
ret
.NoCPUID:
xor eax, eax
@@ -48,9 +48,9 @@ Detect64Bit:
jb .NoLongMode
mov eax, 0x80000001
cpuid
- test edx, 1 << 29
+ test edx, 0x20000000
jz .NoLongMode
- mov eax, 1
+ mov eax, 0x1
ret
.NoLongMode:
xor eax, eax
@@ -58,11 +58,11 @@ Detect64Bit:
.global DetectPSE
DetectPSE:
- mov eax, 0x00000001
+ mov eax, 0x00000001
cpuid
test edx, 0x00000008
jz .NoPSE
- mov eax, 1
+ mov eax, 0x1
ret
.NoPSE:
xor eax, eax
@@ -70,11 +70,11 @@ DetectPSE:
.global DetectPAE
DetectPAE:
- mov eax, 0x00000001
+ mov eax, 0x00000001
cpuid
test edx, 0x00000040
jz .NoPAE
- mov eax, 1
+ mov eax, 0x1
ret
.NoPAE:
xor eax, eax
diff --git a/Architecture/amd64/Bootstrap/Multiboot/2/GDT32.s b/Architecture/amd64/Bootstrap/Multiboot/2/GDT32.s
index 30974ac..85fe29e 100644
--- a/Architecture/amd64/Bootstrap/Multiboot/2/GDT32.s
+++ b/Architecture/amd64/Bootstrap/Multiboot/2/GDT32.s
@@ -15,8 +15,6 @@
along with Fennix Kernel. If not, see .
*/
-.intel_syntax noprefix
-
.code32
.section .bootstrap.text
@@ -48,19 +46,19 @@ GDT32:
.word 0x4092
.byte 0x00
GDT32_END:
+ nop
.global LoadGDT32
LoadGDT32:
lgdt [gdtr]
+ ljmp $0x8, $ActivateGDT
- jmp 0x8:ActivateGDT
- ActivateGDT:
- mov cx, 0x10
- mov ss, cx
- mov ds, cx
- mov es, cx
- mov fs, cx
- mov cx, 0x18
- mov gs, cx
-
+ActivateGDT:
+ mov $0x10, %cx
+ mov %cx, %ss
+ mov %cx, %ds
+ mov %cx, %es
+ mov %cx, %fs
+ mov $0x18, %cx
+ mov %cx, %gs
ret
diff --git a/Architecture/amd64/Bootstrap/Multiboot/2/GDT64.s b/Architecture/amd64/Bootstrap/Multiboot/2/GDT64.s
index d655c4e..f62ec98 100644
--- a/Architecture/amd64/Bootstrap/Multiboot/2/GDT64.s
+++ b/Architecture/amd64/Bootstrap/Multiboot/2/GDT64.s
@@ -15,49 +15,48 @@
along with Fennix Kernel. If not, see .
*/
-.intel_syntax noprefix
-
.code64
.section .bootstrap.data
/* Access bits */
-.equ A, 1 << 0
-.equ RW, 1 << 1
-.equ DC, 1 << 2
-.equ E, 1 << 3
-.equ S, 1 << 4
-.equ DPL0, 0 << 5
-.equ DPL1, 1 << 5
-.equ P, 1 << 7
+A = 0x1
+RW = 0x2
+DC = 0x4
+E = 0x8
+S = 0x10
+DPL0 = 0x0 /* 0 << 5 ???? */
+DPL1 = 0x20
+P = 0x80
/* Flags bits */
-.equ LONG_MODE, 1 << 5
-.equ SZ_32, 1 << 6
-.equ GRAN_4K, 1 << 7
+LONG_MODE = 0x20
+SZ_32 = 0x40
+GRAN_4K = 0x80
.global GDT64.Null
.global GDT64.Code
.global GDT64.Data
.global GDT64.Tss
.global GDT64.Ptr
+
GDT64:
-.equ GDT64.Null, $ - GDT64
+GDT64.Null = . - GDT64
.quad 0
-.equ GDT64.Code, $ - GDT64
+GDT64.Code = . - GDT64
.long 0xFFFF
.byte 0
.byte P | S | E | RW
.byte GRAN_4K | LONG_MODE | 0xF
.byte 0
-.equ GDT64.Data, $ - GDT64
+GDT64.Data = . - GDT64
.long 0xFFFF
.byte 0
.byte P | S | RW
.byte GRAN_4K | SZ_32 | 0xF
.byte 0
-.equ GDT64.Tss, $ - GDT64
+GDT64.Tss = . - GDT64
.long 0x00000068
.long 0x00CF8900
GDT64.Ptr:
- .word $ - GDT64 - 1
+ .word . - GDT64 - 1
.quad GDT64
diff --git a/Architecture/amd64/Bootstrap/Multiboot/2/Header.s b/Architecture/amd64/Bootstrap/Multiboot/2/Header.s
index 2f8d0f7..2ec235b 100644
--- a/Architecture/amd64/Bootstrap/Multiboot/2/Header.s
+++ b/Architecture/amd64/Bootstrap/Multiboot/2/Header.s
@@ -15,8 +15,6 @@
along with Fennix Kernel. If not, see .
*/
-.intel_syntax noprefix
-
.code32
.extern Multiboot2_start
@@ -91,3 +89,4 @@ EndTag_Start:
.long EndTag_End - EndTag_Start
EndTag_End:
MULTIBOOT2_HEADER_END:
+ nop
diff --git a/Architecture/amd64/Bootstrap/Multiboot/2/Multiboot_PageTable.asm b/Architecture/amd64/Bootstrap/Multiboot/2/Multiboot_PageTable.asm
deleted file mode 100644
index 179233d..0000000
--- a/Architecture/amd64/Bootstrap/Multiboot/2/Multiboot_PageTable.asm
+++ /dev/null
@@ -1,61 +0,0 @@
-; This file is part of Fennix Kernel.
-;
-; Fennix Kernel 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.
-;
-; Fennix Kernel 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 Fennix Kernel. If not, see .
-
-[bits 32]
-
-PAGE_TABLE_SIZE equ 0x4
-
-section .bootstrap.data
-align 0x1000
-global BootPageTable
-BootPageTable:
- times (0x10000) dq 0 ; 0x4000 bytes will be used in UpdatePageTable
-
-section .bootstrap.text
-global UpdatePageTable
-UpdatePageTable:
- mov edi, (BootPageTable + 0x0000) ; First PML4E
- mov eax, (BootPageTable + 0x1000) ; First PDPTE
- or eax, 11b ; Bitwise OR on rax (PDPTE) with 11b (Present, Write)
- mov dword [edi], eax ; Write 11b to PML4E
-
- mov edi, (BootPageTable + 0x1000) ; First PDPTE
- mov eax, (BootPageTable + 0x2000) ; First PDE
- or eax, 11b ; Bitwise OR on rax (PDE) with 11b (Present, Write)
-
- mov ecx, PAGE_TABLE_SIZE ; For loop instruction
- mov ebx, 0x0 ; Value to store in the next 4 bytes
- .FillPageTableLevel3:
- mov dword [edi], eax ; Store modified PDE in PDPTE
- mov dword [edi + 4], ebx ; Store the rbx value in the next 4 bytes
- add eax, 0x1000 ; Increment (page size)
- adc ebx, 0 ; Add 0 to carry flag
- add edi, 8 ; Add 8 to rdi (next PDE)
- loop .FillPageTableLevel3 ; Loop until rcx is 0
-
- mov edi, (BootPageTable + 0x2000) ; First PDE
- mov eax, 10000011b ; Present, Write, Large Page
-
- mov ecx, (512 * PAGE_TABLE_SIZE) ; For loop instruction
- mov ebx, 0x0 ; Value to store in the next 4 bytes
- .FillPageTableLevel2:
- mov dword [edi], eax ; Store modified PDE in PDPTE
- mov dword [edi + 4], ebx ; Store the rbx value in the next 4 bytes
- add eax, 1 << 21 ; Increment (page size)
- adc ebx, 0 ; Add 0 (carry flag) to rbx to increment if there was a carry
- add edi, 8 ; Add 8 to rdi (next PDE)
- loop .FillPageTableLevel2 ; Loop until rcx is 0
-
- ret
diff --git a/Architecture/amd64/Bootstrap/Multiboot/2/Multiboot_PageTable.s b/Architecture/amd64/Bootstrap/Multiboot/2/Multiboot_PageTable.s
new file mode 100644
index 0000000..596f635
--- /dev/null
+++ b/Architecture/amd64/Bootstrap/Multiboot/2/Multiboot_PageTable.s
@@ -0,0 +1,62 @@
+/*
+ This file is part of Fennix Kernel.
+
+ Fennix Kernel 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.
+
+ Fennix Kernel 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 Fennix Kernel. If not, see .
+*/
+
+PAGE_TABLE_SIZE = 0x4
+
+.code32
+.section .bootstrap.data
+.align 0x1000
+.global BootPageTable
+BootPageTable:
+ .space 0x10000 /* 0x4000 bytes will be used in UpdatePageTable */
+
+.section .bootstrap.text
+.global UpdatePageTable
+UpdatePageTable:
+ mov $(BootPageTable + 0x0000), %edi /* First PML4E */
+ mov $(BootPageTable + 0x1000), %eax /* First PDPTE */
+ or $0x3, %eax /* Bitwise OR on eax (PDPTE) with 11b (Present, Write) */
+ mov %eax, (%edi) /* Write 11b to PML4E */
+
+ mov $(BootPageTable + 0x1000), %edi /* First PDPTE */
+ mov $(BootPageTable + 0x2000), %eax /* First PDE */
+ or $0x3, %eax /* Bitwise OR on eax (PDE) with 11b (Present, Write) */
+
+ mov $PAGE_TABLE_SIZE, %ecx /* For loop instruction */
+ mov $0x0, %ebx /* Value to store in the next 4 bytes */
+ .FillPageTableLevel3:
+ mov %eax, (%edi) /* Store modified PDE in PDPTE */
+ mov %ebx, 0x4(%edi) /* Store the ebx value in the next 4 bytes */
+ add $0x1000, %eax /* Increment (page size) */
+ adc $0x0, %ebx /* Add 0 to carry flag */
+ add $0x8, %edi /* Add 8 to edi (next PDE) */
+ loop .FillPageTableLevel3 /* Loop until ecx is 0 */
+
+ mov $(BootPageTable + 0x2000), %edi /* First PDE */
+ mov $0x83, %eax /* Present, Write, Large Page */
+
+ mov $(512 * PAGE_TABLE_SIZE), %ecx /* For loop instruction */
+ mov $0x0, %ebx /* Value to store in the next 4 bytes */
+ .FillPageTableLevel2:
+ mov %eax, (%edi) /* Store modified PDE in PDPTE */
+ mov %ebx, 0x4(%edi) /* Store the ebx value in the next 4 bytes */
+ add $0x200000, %eax /* Increment (page size) */
+ adc $0x0, %ebx /* Add 0 (carry flag) to ebx to increment if there was a carry */
+ add $0x8, %edi /* Add 8 to edi (next PDE) */
+ loop .FillPageTableLevel2 /* Loop until ecx is 0 */
+
+ ret
diff --git a/Architecture/amd64/Bootstrap/Multiboot/2/Multiboot_PageTable.s_fixme b/Architecture/amd64/Bootstrap/Multiboot/2/Multiboot_PageTable.s_fixme
deleted file mode 100644
index 6922f1b..0000000
--- a/Architecture/amd64/Bootstrap/Multiboot/2/Multiboot_PageTable.s_fixme
+++ /dev/null
@@ -1,67 +0,0 @@
-/*
- This file is part of Fennix Kernel.
-
- Fennix Kernel 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.
-
- Fennix Kernel 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 Fennix Kernel. If not, see .
-*/
-
-.intel_syntax noprefix
-
-.code32
-
-.equ PAGE_TABLE_SIZE, 0x4
-
-.section .bootstrap.data
-.align 0x1000
-.global BootPageTable
-BootPageTable:
- .rept 0x10000 /* 0x4000 bytes will be used in UpdatePageTable */
- .long 0
- .endr
-
-.section .bootstrap.text
-.global UpdatePageTable
-UpdatePageTable:
- mov edi, (BootPageTable + 0x0000) /* First PML4E */
- mov eax, (BootPageTable + 0x1000) /* First PDPTE */
- or eax, 0b11 /* Bitwise OR on rax (PDPTE) with 11b (Present, Write) */
- mov dword [edi], eax /* Write 11b to PML4E */
-
- mov edi, (BootPageTable + 0x1000) /* First PDPTE */
- mov eax, (BootPageTable + 0x2000) /* First PDE */
- or eax, 0b11 /* Bitwise OR on rax (PDE) with 11b (Present, Write) */
-
- mov ecx, PAGE_TABLE_SIZE /* For loop instruction */
- mov ebx, 0x0 /* Value to store in the next 4 bytes */
- .FillPageTableLevel3:
- mov dword [edi], eax /* Store modified PDE in PDPTE */
- mov dword [edi + 4], ebx /* Store the rbx value in the next 4 bytes */
- add eax, 0x1000 /* Increment (page size) */
- adc ebx, 0 /* Add 0 to carry flag */
- add edi, 8 /* Add 8 to rdi (next PDE) */
- loop .FillPageTableLevel3 /* Loop until rcx is 0 */
-
- mov edi, (BootPageTable + 0x2000) /* First PDE */
- mov eax, 0b10000011 /* Present, Write, Large Page */
-
- mov ecx, (512 * PAGE_TABLE_SIZE) /* For loop instruction */
- mov ebx, 0x0 /* Value to store in the next 4 bytes */
- .FillPageTableLevel2:
- mov dword [edi], eax /* Store modified PDE in PDPTE */
- mov dword [edi + 4], ebx /* Store the rbx value in the next 4 bytes */
- add eax, 1 << 21 /* Increment (page size) */
- adc ebx, 0 /* Add 0 (carry flag) to rbx to increment if there was a carry */
- add edi, 8 /* Add 8 to rdi (next PDE) */
- loop .FillPageTableLevel2 /* Loop until rcx is 0 */
-
- ret
diff --git a/Architecture/amd64/Bootstrap/Multiboot/2/Start.asm b/Architecture/amd64/Bootstrap/Multiboot/2/Start.asm
deleted file mode 100644
index 9f28534..0000000
--- a/Architecture/amd64/Bootstrap/Multiboot/2/Start.asm
+++ /dev/null
@@ -1,112 +0,0 @@
-; This file is part of Fennix Kernel.
-;
-; Fennix Kernel 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.
-;
-; Fennix Kernel 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 Fennix Kernel. If not, see .
-
-[bits 32]
-KERNEL_STACK_SIZE equ 0x4000 ; 16KB
-
-extern DetectCPUID
-extern Detect64Bit
-extern DetectPSE
-extern DetectPAE
-extern multiboot_main
-extern LoadGDT32
-extern BootPageTable
-extern UpdatePageTable
-extern GDT64.Ptr
-extern GDT64.Code
-extern GDT64.Data
-
-section .bootstrap.data
-MB_HeaderMagic:
- dq 0
-
-MB_HeaderInfo:
- dq 0
-
-section .bootstrap.text
-
-global Multiboot2_start
-Multiboot2_start:
- cli
-
- mov [MB_HeaderMagic], eax
- mov [MB_HeaderInfo], ebx
-
- call DetectCPUID
- cmp eax, 0
- je $
-
- call Detect64Bit
- cmp eax, 0
- je $
-
- call DetectPSE
- cmp eax, 0
- je $
-
- call DetectPAE
- cmp eax, 0
- je $
-
- mov ecx, cr4
- or ecx, 0x00000010 ; Set PSE in CR4
- or ecx, 0x00000020 ; Set PAE in CR4
- mov cr4, ecx
-
- call LoadGDT32
- call UpdatePageTable
-
- mov ecx, BootPageTable
- mov cr3, ecx
-
- mov ecx, 0xC0000080 ; EFER
- rdmsr
- or eax, 0x800 | 0x100 | 0x1 ; Set LME, LMA, SCE
- wrmsr
-
- mov ecx, cr0
- or ecx, 0x80000001 ; Set PG and PE in CR0
- mov cr0, ecx
-
- lgdt [GDT64.Ptr]
- jmp GDT64.Code:HigherHalfStart
-
-extern UpdatePageTable64
-
-[bits 64]
-HigherHalfStart:
- mov ax, GDT64.Data
- mov ds, ax
- mov es, ax
- mov fs, ax
- mov gs, ax
- mov ss, ax
-
- call UpdatePageTable64
-
- mov rsp, KernelStack + KERNEL_STACK_SIZE
- mov rdi, [MB_HeaderMagic]
- mov rsi, [MB_HeaderInfo]
- push rsi
- push rdi
- call multiboot_main
-.Hang:
- hlt
- jmp .Hang
-
-section .bootstrap.bss
-align 16
-KernelStack:
- resb KERNEL_STACK_SIZE
diff --git a/Architecture/amd64/Bootstrap/Multiboot/2/Start.s_fixme b/Architecture/amd64/Bootstrap/Multiboot/2/Start.s
similarity index 64%
rename from Architecture/amd64/Bootstrap/Multiboot/2/Start.s_fixme
rename to Architecture/amd64/Bootstrap/Multiboot/2/Start.s
index 8076319..c9965c6 100644
--- a/Architecture/amd64/Bootstrap/Multiboot/2/Start.s_fixme
+++ b/Architecture/amd64/Bootstrap/Multiboot/2/Start.s
@@ -15,10 +15,8 @@
along with Fennix Kernel. If not, see .
*/
-.intel_syntax noprefix
-
.code32
-.equ KERNEL_STACK_SIZE, 0x4000 /* 16KB */
+KERNEL_STACK_SIZE = 0x4000 /* 16KB */
.extern DetectCPUID
.extern Detect64Bit
@@ -45,67 +43,71 @@ MB_HeaderInfo:
Multiboot2_start:
cli
- mov [MB_HeaderMagic], eax
- mov [MB_HeaderInfo], ebx
+ mov %eax, [MB_HeaderMagic]
+ mov %ebx, [MB_HeaderInfo]
call DetectCPUID
- cmp eax, 0
- je $
+ cmp $0, %eax
+ je .
call Detect64Bit
- cmp eax, 0
- je $
+ cmp $0, %eax
+ je .
call DetectPSE
- cmp eax, 0
- je $
+ cmp $0, %eax
+ je .
call DetectPAE
- cmp eax, 0
- je $
+ cmp $0, %eax
+ je .
- mov ecx, cr4
- or ecx, 0x00000010 /* Set PSE in CR4 */
- or ecx, 0x00000020 /* Set PAE in CR4 */
- mov cr4, ecx
+ mov %cr4, %ecx
+ or $0x00000010, %ecx /* PSE */
+ or $0x00000020, %ecx /* PAE */
+ mov %ecx, %cr4
call LoadGDT32
call UpdatePageTable
- mov ecx, BootPageTable
- mov cr3, ecx
+ mov $BootPageTable, %ecx
+ mov %ecx, %cr3
- mov ecx, 0xC0000080 /* EFER */
+ mov $0xC0000080, %ecx /* EFER */
rdmsr
- or eax, 0x800 | 0x100 | 0x1 /* Set LME, LMA, SCE */
+ or $0x800, %eax /* LME */
+ or $0x100, %eax /* LMA */
+ or $0x1, %eax /* SCE */
wrmsr
- mov ecx, cr0
- or ecx, 0x80000001 /* Set PG and PE in CR0 */
- mov cr0, ecx
+ mov %cr0, %ecx
+ or $0x80000000, %ecx /* PG */
+ or $0x1, %ecx /* PE */
+ mov %ecx, %cr0
lgdt [GDT64.Ptr]
- jmp GDT64.Code:HigherHalfStart
+ ljmp $GDT64.Code, $HigherHalfStart
.extern UpdatePageTable64
.code64
HigherHalfStart:
- mov ax, GDT64.Data
- mov ds, ax
- mov es, ax
- mov fs, ax
- mov gs, ax
- mov ss, ax
+ mov GDT64.Data, %ax
+ mov %ax, %ds
+ mov %ax, %es
+ mov %ax, %fs
+ mov %ax, %gs
+ mov %ax, %ss
call UpdatePageTable64
- mov rsp, KernelStack + KERNEL_STACK_SIZE
- mov rbp, 0
- mov rdi, [MB_HeaderMagic]
- mov rsi, [MB_HeaderInfo]
- push rsi
- push rdi
+ mov $(KernelStack + KERNEL_STACK_SIZE), %rsp
+ mov $0x0, %rbp
+
+ mov [MB_HeaderMagic], %rdi
+ mov [MB_HeaderInfo], %rsi
+ push %rsi
+ push %rdi
call multiboot_main
.Hang:
hlt
diff --git a/Architecture/amd64/cpu/AdvancedProgrammableInterruptController.cpp b/Architecture/amd64/cpu/AdvancedProgrammableInterruptController.cpp
index c19b735..4faa54b 100644
--- a/Architecture/amd64/cpu/AdvancedProgrammableInterruptController.cpp
+++ b/Architecture/amd64/cpu/AdvancedProgrammableInterruptController.cpp
@@ -42,362 +42,363 @@ warning: left shift count >= width of type
namespace APIC
{
- // headache
- // https://www.amd.com/system/files/TechDocs/24593.pdf
- // https://www.naic.edu/~phil/software/intel/318148.pdf
+ // headache
+ // https://www.amd.com/system/files/TechDocs/24593.pdf
+ // https://www.naic.edu/~phil/software/intel/318148.pdf
- uint32_t APIC::Read(uint32_t Register)
- {
+ uint32_t APIC::Read(uint32_t Register)
+ {
#ifdef DEBUG
- if (Register != APIC_ICRLO &&
- Register != APIC_ICRHI &&
- Register != APIC_ID)
- debug("APIC::Read(%#lx) [x2=%d]", Register, x2APICSupported ? 1 : 0);
+ if (Register != APIC_ICRLO &&
+ Register != APIC_ICRHI &&
+ Register != APIC_ID)
+ debug("APIC::Read(%#lx) [x2=%d]", Register, x2APICSupported ? 1 : 0);
#endif
- if (x2APICSupported)
- {
- if (Register != APIC_ICRHI)
- return s_cst(uint32_t, rdmsr((Register >> 4) + 0x800));
- else
- return s_cst(uint32_t, rdmsr(0x30 + 0x800));
- }
- else
- {
- CPU::MemBar::Barrier();
- uint32_t ret = *((volatile uint32_t *)((uintptr_t)APICBaseAddress + Register));
- CPU::MemBar::Barrier();
- return ret;
- }
- }
+ if (x2APICSupported)
+ {
+ if (Register != APIC_ICRHI)
+ return s_cst(uint32_t, rdmsr((Register >> 4) + 0x800));
+ else
+ return s_cst(uint32_t, rdmsr(0x30 + 0x800));
+ }
+ else
+ {
+ CPU::MemBar::Barrier();
+ uint32_t ret = *((volatile uint32_t *)((uintptr_t)APICBaseAddress + Register));
+ CPU::MemBar::Barrier();
+ return ret;
+ }
+ }
- void APIC::Write(uint32_t Register, uint32_t Value)
- {
+ void APIC::Write(uint32_t Register, uint32_t Value)
+ {
#ifdef DEBUG
- if (Register != APIC_EOI &&
- Register != APIC_TDCR &&
- Register != APIC_TIMER &&
- Register != APIC_TICR &&
- Register != APIC_ICRLO &&
- Register != APIC_ICRHI)
- debug("APIC::Write(%#lx, %#lx) [x2=%d]", Register, Value, x2APICSupported ? 1 : 0);
+ if (Register != APIC_EOI &&
+ Register != APIC_TDCR &&
+ Register != APIC_TIMER &&
+ Register != APIC_TICR &&
+ Register != APIC_ICRLO &&
+ Register != APIC_ICRHI)
+ debug("APIC::Write(%#lx, %#lx) [x2=%d]", Register, Value, x2APICSupported ? 1 : 0);
#endif
- if (x2APICSupported)
- {
- if (Register != APIC_ICRHI)
- wrmsr((Register >> 4) + 0x800, Value);
- else
- wrmsr(MSR_X2APIC_ICR, Value);
- }
- else
- {
- CPU::MemBar::Barrier();
- *((volatile uint32_t *)(((uintptr_t)APICBaseAddress) + Register)) = Value;
- CPU::MemBar::Barrier();
- }
- }
+ if (x2APICSupported)
+ {
+ if (Register != APIC_ICRHI)
+ wrmsr((Register >> 4) + 0x800, Value);
+ else
+ wrmsr(MSR_X2APIC_ICR, Value);
+ }
+ else
+ {
+ CPU::MemBar::Barrier();
+ *((volatile uint32_t *)(((uintptr_t)APICBaseAddress) + Register)) = Value;
+ CPU::MemBar::Barrier();
+ }
+ }
- void APIC::IOWrite(uint64_t Base, uint32_t Register, uint32_t Value)
- {
- debug("APIC::IOWrite(%#lx, %#lx, %#lx)", Base, Register, Value);
- CPU::MemBar::Barrier();
- *((volatile uint32_t *)(((uintptr_t)Base))) = Register;
- CPU::MemBar::Barrier();
- *((volatile uint32_t *)(((uintptr_t)Base + 16))) = Value;
- CPU::MemBar::Barrier();
- }
+ void APIC::IOWrite(uint64_t Base, uint32_t Register, uint32_t Value)
+ {
+ debug("APIC::IOWrite(%#lx, %#lx, %#lx)", Base, Register, Value);
+ CPU::MemBar::Barrier();
+ *((volatile uint32_t *)(((uintptr_t)Base))) = Register;
+ CPU::MemBar::Barrier();
+ *((volatile uint32_t *)(((uintptr_t)Base + 16))) = Value;
+ CPU::MemBar::Barrier();
+ }
- uint32_t APIC::IORead(uint64_t Base, uint32_t Register)
- {
- debug("APIC::IORead(%#lx, %#lx)", Base, Register);
- CPU::MemBar::Barrier();
- *((volatile uint32_t *)(((uintptr_t)Base))) = Register;
- CPU::MemBar::Barrier();
- uint32_t ret = *((volatile uint32_t *)(((uintptr_t)Base + 16)));
- CPU::MemBar::Barrier();
- return ret;
- }
+ uint32_t APIC::IORead(uint64_t Base, uint32_t Register)
+ {
+ debug("APIC::IORead(%#lx, %#lx)", Base, Register);
+ CPU::MemBar::Barrier();
+ *((volatile uint32_t *)(((uintptr_t)Base))) = Register;
+ CPU::MemBar::Barrier();
+ uint32_t ret = *((volatile uint32_t *)(((uintptr_t)Base + 16)));
+ CPU::MemBar::Barrier();
+ return ret;
+ }
- void APIC::EOI() { this->Write(APIC_EOI, 0); }
+ void APIC::EOI() { this->Write(APIC_EOI, 0); }
- void APIC::WaitForIPI()
- {
- InterruptCommandRegisterLow icr = {.raw = 0};
- do
- {
- icr.raw = this->Read(APIC_ICRLO);
- } while (icr.DeliveryStatus != Idle);
- }
+ void APIC::WaitForIPI()
+ {
+ InterruptCommandRegisterLow icr = {.raw = 0};
+ do
+ {
+ icr.raw = this->Read(APIC_ICRLO);
+ CPU::Pause();
+ } while (icr.DeliveryStatus != Idle);
+ }
- void APIC::IPI(int CPU, InterruptCommandRegisterLow icr)
- {
- SmartCriticalSection(APICLock);
- if (x2APICSupported)
- {
- wrmsr(MSR_X2APIC_ICR, s_cst(uint32_t, icr.raw));
- this->WaitForIPI();
- }
- else
- {
- this->Write(APIC_ICRHI, (CPU << 24));
- this->Write(APIC_ICRLO, s_cst(uint32_t, icr.raw));
- this->WaitForIPI();
- }
- }
+ void APIC::IPI(int CPU, InterruptCommandRegisterLow icr)
+ {
+ SmartCriticalSection(APICLock);
+ if (x2APICSupported)
+ {
+ wrmsr(MSR_X2APIC_ICR, s_cst(uint32_t, icr.raw));
+ this->WaitForIPI();
+ }
+ else
+ {
+ this->Write(APIC_ICRHI, (CPU << 24));
+ this->Write(APIC_ICRLO, s_cst(uint32_t, icr.raw));
+ this->WaitForIPI();
+ }
+ }
- void APIC::SendInitIPI(int CPU)
- {
- SmartCriticalSection(APICLock);
- if (x2APICSupported)
- {
- InterruptCommandRegisterLow icr = {.raw = 0};
- icr.DeliveryMode = INIT;
- icr.Level = Assert;
- wrmsr(MSR_X2APIC_ICR, s_cst(uint32_t, icr.raw));
- this->WaitForIPI();
- }
- else
- {
- InterruptCommandRegisterLow icr = {.raw = 0};
- icr.DeliveryMode = INIT;
- icr.Level = Assert;
- this->Write(APIC_ICRHI, (CPU << 24));
- this->Write(APIC_ICRLO, s_cst(uint32_t, icr.raw));
- this->WaitForIPI();
- }
- }
+ void APIC::SendInitIPI(int CPU)
+ {
+ SmartCriticalSection(APICLock);
+ if (x2APICSupported)
+ {
+ InterruptCommandRegisterLow icr = {.raw = 0};
+ icr.DeliveryMode = INIT;
+ icr.Level = Assert;
+ wrmsr(MSR_X2APIC_ICR, s_cst(uint32_t, icr.raw));
+ this->WaitForIPI();
+ }
+ else
+ {
+ InterruptCommandRegisterLow icr = {.raw = 0};
+ icr.DeliveryMode = INIT;
+ icr.Level = Assert;
+ this->Write(APIC_ICRHI, (CPU << 24));
+ this->Write(APIC_ICRLO, s_cst(uint32_t, icr.raw));
+ this->WaitForIPI();
+ }
+ }
- void APIC::SendStartupIPI(int CPU, uint64_t StartupAddress)
- {
- SmartCriticalSection(APICLock);
- if (x2APICSupported)
- {
- InterruptCommandRegisterLow icr = {.raw = 0};
- icr.Vector = s_cst(uint8_t, StartupAddress >> 12);
- icr.DeliveryMode = Startup;
- icr.Level = Assert;
- wrmsr(MSR_X2APIC_ICR, s_cst(uint32_t, icr.raw));
- this->WaitForIPI();
- }
- else
- {
- InterruptCommandRegisterLow icr = {.raw = 0};
- icr.Vector = s_cst(uint8_t, StartupAddress >> 12);
- icr.DeliveryMode = Startup;
- icr.Level = Assert;
- this->Write(APIC_ICRHI, (CPU << 24));
- this->Write(APIC_ICRLO, s_cst(uint32_t, icr.raw));
- this->WaitForIPI();
- }
- }
+ void APIC::SendStartupIPI(int CPU, uint64_t StartupAddress)
+ {
+ SmartCriticalSection(APICLock);
+ if (x2APICSupported)
+ {
+ InterruptCommandRegisterLow icr = {.raw = 0};
+ icr.Vector = s_cst(uint8_t, StartupAddress >> 12);
+ icr.DeliveryMode = Startup;
+ icr.Level = Assert;
+ wrmsr(MSR_X2APIC_ICR, s_cst(uint32_t, icr.raw));
+ this->WaitForIPI();
+ }
+ else
+ {
+ InterruptCommandRegisterLow icr = {.raw = 0};
+ icr.Vector = s_cst(uint8_t, StartupAddress >> 12);
+ icr.DeliveryMode = Startup;
+ icr.Level = Assert;
+ this->Write(APIC_ICRHI, (CPU << 24));
+ this->Write(APIC_ICRLO, s_cst(uint32_t, icr.raw));
+ this->WaitForIPI();
+ }
+ }
- uint32_t APIC::IOGetMaxRedirect(uint32_t APICID)
- {
- uint32_t TableAddress = (this->IORead((((ACPI::MADT *)PowerManager->GetMADT())->ioapic[APICID]->Address), GetIOAPICVersion));
- return ((IOAPICVersion *)&TableAddress)->MaximumRedirectionEntry;
- }
+ uint32_t APIC::IOGetMaxRedirect(uint32_t APICID)
+ {
+ uint32_t TableAddress = (this->IORead((((ACPI::MADT *)PowerManager->GetMADT())->ioapic[APICID]->Address), GetIOAPICVersion));
+ return ((IOAPICVersion *)&TableAddress)->MaximumRedirectionEntry;
+ }
- void APIC::RawRedirectIRQ(uint16_t Vector, uint32_t GSI, uint16_t Flags, int CPU, int Status)
- {
- uint64_t Value = Vector;
+ void APIC::RawRedirectIRQ(uint16_t Vector, uint32_t GSI, uint16_t Flags, int CPU, int Status)
+ {
+ uint64_t Value = Vector;
- int64_t IOAPICTarget = -1;
- for (uint64_t i = 0; ((ACPI::MADT *)PowerManager->GetMADT())->ioapic[i] != 0; i++)
- if (((ACPI::MADT *)PowerManager->GetMADT())->ioapic[i]->GSIBase <= GSI)
- if (((ACPI::MADT *)PowerManager->GetMADT())->ioapic[i]->GSIBase + IOGetMaxRedirect(s_cst(uint32_t, i)) > GSI)
- {
- IOAPICTarget = i;
- break;
- }
+ int64_t IOAPICTarget = -1;
+ for (uint64_t i = 0; ((ACPI::MADT *)PowerManager->GetMADT())->ioapic[i] != 0; i++)
+ if (((ACPI::MADT *)PowerManager->GetMADT())->ioapic[i]->GSIBase <= GSI)
+ if (((ACPI::MADT *)PowerManager->GetMADT())->ioapic[i]->GSIBase + IOGetMaxRedirect(s_cst(uint32_t, i)) > GSI)
+ {
+ IOAPICTarget = i;
+ break;
+ }
- if (IOAPICTarget == -1)
- {
- error("No ISO table found for I/O APIC");
- return;
- }
+ if (IOAPICTarget == -1)
+ {
+ error("No ISO table found for I/O APIC");
+ return;
+ }
- // TODO: IOAPICRedirectEntry Entry = {.raw = 0};
+ // TODO: IOAPICRedirectEntry Entry = {.raw = 0};
- if (Flags & ActiveHighLow)
- Value |= (1 << 13);
+ if (Flags & ActiveHighLow)
+ Value |= (1 << 13);
- if (Flags & EdgeLevel)
- Value |= (1 << 15);
+ if (Flags & EdgeLevel)
+ Value |= (1 << 15);
- if (!Status)
- Value |= (1 << 16);
+ if (!Status)
+ Value |= (1 << 16);
- Value |= (((uintptr_t)CPU) << 56);
- uint32_t IORegister = (GSI - ((ACPI::MADT *)PowerManager->GetMADT())->ioapic[IOAPICTarget]->GSIBase) * 2 + 16;
+ Value |= (((uintptr_t)CPU) << 56);
+ uint32_t IORegister = (GSI - ((ACPI::MADT *)PowerManager->GetMADT())->ioapic[IOAPICTarget]->GSIBase) * 2 + 16;
- this->IOWrite(((ACPI::MADT *)PowerManager->GetMADT())->ioapic[IOAPICTarget]->Address, IORegister, (uint32_t)Value);
- this->IOWrite(((ACPI::MADT *)PowerManager->GetMADT())->ioapic[IOAPICTarget]->Address, IORegister + 1, (uint32_t)(Value >> 32));
- }
+ this->IOWrite(((ACPI::MADT *)PowerManager->GetMADT())->ioapic[IOAPICTarget]->Address, IORegister, (uint32_t)Value);
+ this->IOWrite(((ACPI::MADT *)PowerManager->GetMADT())->ioapic[IOAPICTarget]->Address, IORegister + 1, (uint32_t)(Value >> 32));
+ }
- void APIC::RedirectIRQ(int CPU, uint16_t IRQ, int Status)
- {
- for (uint64_t i = 0; i < ((ACPI::MADT *)PowerManager->GetMADT())->iso.size(); i++)
- if (((ACPI::MADT *)PowerManager->GetMADT())->iso[i]->IRQSource == IRQ)
- {
- debug("[ISO %d] Mapping to source IRQ%#d GSI:%#lx on CPU %d",
- i, ((ACPI::MADT *)PowerManager->GetMADT())->iso[i]->IRQSource, ((ACPI::MADT *)PowerManager->GetMADT())->iso[i]->GSI, CPU);
+ void APIC::RedirectIRQ(int CPU, uint16_t IRQ, int Status)
+ {
+ for (uint64_t i = 0; i < ((ACPI::MADT *)PowerManager->GetMADT())->iso.size(); i++)
+ if (((ACPI::MADT *)PowerManager->GetMADT())->iso[i]->IRQSource == IRQ)
+ {
+ debug("[ISO %d] Mapping to source IRQ%#d GSI:%#lx on CPU %d",
+ i, ((ACPI::MADT *)PowerManager->GetMADT())->iso[i]->IRQSource, ((ACPI::MADT *)PowerManager->GetMADT())->iso[i]->GSI, CPU);
- this->RawRedirectIRQ(((ACPI::MADT *)PowerManager->GetMADT())->iso[i]->IRQSource + 0x20, ((ACPI::MADT *)PowerManager->GetMADT())->iso[i]->GSI, ((ACPI::MADT *)PowerManager->GetMADT())->iso[i]->Flags, CPU, Status);
- return;
- }
- debug("Mapping IRQ%d on CPU %d", IRQ, CPU);
- this->RawRedirectIRQ(IRQ + 0x20, IRQ, 0, CPU, Status);
- }
+ this->RawRedirectIRQ(((ACPI::MADT *)PowerManager->GetMADT())->iso[i]->IRQSource + 0x20, ((ACPI::MADT *)PowerManager->GetMADT())->iso[i]->GSI, ((ACPI::MADT *)PowerManager->GetMADT())->iso[i]->Flags, CPU, Status);
+ return;
+ }
+ debug("Mapping IRQ%d on CPU %d", IRQ, CPU);
+ this->RawRedirectIRQ(IRQ + 0x20, IRQ, 0, CPU, Status);
+ }
- void APIC::RedirectIRQs(int CPU)
- {
- SmartCriticalSection(APICLock);
- debug("Redirecting IRQs...");
- for (uint8_t i = 0; i < 16; i++)
- this->RedirectIRQ(CPU, i, 1);
- debug("Redirecting IRQs completed.");
- }
+ void APIC::RedirectIRQs(int CPU)
+ {
+ SmartCriticalSection(APICLock);
+ debug("Redirecting IRQs...");
+ for (uint8_t i = 0; i < 16; i++)
+ this->RedirectIRQ(CPU, i, 1);
+ debug("Redirecting IRQs completed.");
+ }
- APIC::APIC(int Core)
- {
- SmartCriticalSection(APICLock);
- APIC_BASE BaseStruct = {.raw = rdmsr(MSR_APIC_BASE)};
- uint64_t BaseLow = BaseStruct.ApicBaseLo;
- uint64_t BaseHigh = BaseStruct.ApicBaseHi;
- this->APICBaseAddress = BaseLow << 12u | BaseHigh << 32u;
- trace("APIC Address: %#lx", this->APICBaseAddress);
- Memory::Virtual().Map((void *)this->APICBaseAddress, (void *)this->APICBaseAddress, Memory::PTFlag::RW | Memory::PTFlag::PCD);
+ APIC::APIC(int Core)
+ {
+ SmartCriticalSection(APICLock);
+ APIC_BASE BaseStruct = {.raw = rdmsr(MSR_APIC_BASE)};
+ uint64_t BaseLow = BaseStruct.ApicBaseLo;
+ uint64_t BaseHigh = BaseStruct.ApicBaseHi;
+ this->APICBaseAddress = BaseLow << 12u | BaseHigh << 32u;
+ trace("APIC Address: %#lx", this->APICBaseAddress);
+ Memory::Virtual().Map((void *)this->APICBaseAddress, (void *)this->APICBaseAddress, Memory::PTFlag::RW | Memory::PTFlag::PCD);
- bool x2APICSupported = false;
- if (strcmp(CPU::Vendor(), x86_CPUID_VENDOR_AMD) == 0)
- {
- CPU::x86::AMD::CPUID0x00000001 cpuid;
- cpuid.Get();
- if (cpuid.ECX.x2APIC)
- {
- // x2APICSupported = cpuid.ECX.x2APIC;
- fixme("x2APIC is supported");
- }
- }
- else if (strcmp(CPU::Vendor(), x86_CPUID_VENDOR_INTEL) == 0)
- {
- CPU::x86::Intel::CPUID0x00000001 cpuid;
- cpuid.Get();
- if (cpuid.ECX.x2APIC)
- {
- // x2APICSupported = cpuid.ECX.x2APIC;
- fixme("x2APIC is supported");
- }
- }
+ bool x2APICSupported = false;
+ if (strcmp(CPU::Vendor(), x86_CPUID_VENDOR_AMD) == 0)
+ {
+ CPU::x86::AMD::CPUID0x00000001 cpuid;
+ cpuid.Get();
+ if (cpuid.ECX.x2APIC)
+ {
+ // x2APICSupported = cpuid.ECX.x2APIC;
+ fixme("x2APIC is supported");
+ }
+ }
+ else if (strcmp(CPU::Vendor(), x86_CPUID_VENDOR_INTEL) == 0)
+ {
+ CPU::x86::Intel::CPUID0x00000001 cpuid;
+ cpuid.Get();
+ if (cpuid.ECX.x2APIC)
+ {
+ // x2APICSupported = cpuid.ECX.x2APIC;
+ fixme("x2APIC is supported");
+ }
+ }
- if (x2APICSupported)
- {
- this->x2APICSupported = true;
- wrmsr(MSR_APIC_BASE, (rdmsr(MSR_APIC_BASE) | (1 << 11)) & ~(1 << 10));
- BaseStruct.EN = 1;
- wrmsr(MSR_APIC_BASE, BaseStruct.raw);
- }
- else
- {
- BaseStruct.EN = 1;
- wrmsr(MSR_APIC_BASE, BaseStruct.raw);
- }
+ if (x2APICSupported)
+ {
+ this->x2APICSupported = true;
+ wrmsr(MSR_APIC_BASE, (rdmsr(MSR_APIC_BASE) | (1 << 11)) & ~(1 << 10));
+ BaseStruct.EN = 1;
+ wrmsr(MSR_APIC_BASE, BaseStruct.raw);
+ }
+ else
+ {
+ BaseStruct.EN = 1;
+ wrmsr(MSR_APIC_BASE, BaseStruct.raw);
+ }
- this->Write(APIC_TPR, 0x0);
- // this->Write(APIC_SVR, this->Read(APIC_SVR) | 0x100); // 0x1FF or 0x100 ? on https://wiki.osdev.org/APIC is 0x100
+ this->Write(APIC_TPR, 0x0);
+ // this->Write(APIC_SVR, this->Read(APIC_SVR) | 0x100); // 0x1FF or 0x100 ? on https://wiki.osdev.org/APIC is 0x100
- if (!this->x2APICSupported)
- {
- this->Write(APIC_DFR, 0xF0000000);
- this->Write(APIC_LDR, this->Read(APIC_ID));
- }
+ if (!this->x2APICSupported)
+ {
+ this->Write(APIC_DFR, 0xF0000000);
+ this->Write(APIC_LDR, this->Read(APIC_ID));
+ }
- ACPI::MADT *madt = (ACPI::MADT *)PowerManager->GetMADT();
+ ACPI::MADT *madt = (ACPI::MADT *)PowerManager->GetMADT();
- for (size_t i = 0; i < madt->nmi.size(); i++)
- {
- if (madt->nmi[i]->processor != 0xFF && Core != madt->nmi[i]->processor)
- return;
+ for (size_t i = 0; i < madt->nmi.size(); i++)
+ {
+ if (madt->nmi[i]->processor != 0xFF && Core != madt->nmi[i]->processor)
+ return;
- uint32_t nmi = 0x402;
- if (madt->nmi[i]->flags & 2)
- nmi |= 1 << 13;
- if (madt->nmi[i]->flags & 8)
- nmi |= 1 << 15;
- if (madt->nmi[i]->lint == 0)
- this->Write(APIC_LINT0, nmi);
- else if (madt->nmi[i]->lint == 1)
- this->Write(APIC_LINT1, nmi);
- }
+ uint32_t nmi = 0x402;
+ if (madt->nmi[i]->flags & 2)
+ nmi |= 1 << 13;
+ if (madt->nmi[i]->flags & 8)
+ nmi |= 1 << 15;
+ if (madt->nmi[i]->lint == 0)
+ this->Write(APIC_LINT0, nmi);
+ else if (madt->nmi[i]->lint == 1)
+ this->Write(APIC_LINT1, nmi);
+ }
- // Setup the spurrious interrupt vector
- Spurious Spurious = {.raw = this->Read(APIC_SVR)};
- Spurious.Vector = IRQ223; // TODO: Should I map the IRQ to something?
- Spurious.Software = 1;
- this->Write(APIC_SVR, s_cst(uint32_t, Spurious.raw));
+ // Setup the spurrious interrupt vector
+ Spurious Spurious = {.raw = this->Read(APIC_SVR)};
+ Spurious.Vector = IRQ223; // TODO: Should I map the IRQ to something?
+ Spurious.Software = 1;
+ this->Write(APIC_SVR, s_cst(uint32_t, Spurious.raw));
- static int once = 0;
- if (!once++)
- {
- // Disable PIT
- outb(0x43, 0x28);
- outb(0x40, 0x0);
+ static int once = 0;
+ if (!once++)
+ {
+ // Disable PIT
+ outb(0x43, 0x28);
+ outb(0x40, 0x0);
- // Disable PIC
- outb(0x21, 0xFF);
- outb(0xA1, 0xFF);
- }
- }
+ // Disable PIC
+ outb(0x21, 0xFF);
+ outb(0xA1, 0xFF);
+ }
+ }
- APIC::~APIC() {}
+ APIC::~APIC() {}
- void Timer::OnInterruptReceived(TrapFrame *Frame) { UNUSED(Frame); }
+ void Timer::OnInterruptReceived(TrapFrame *Frame) { UNUSED(Frame); }
- void Timer::OneShot(uint32_t Vector, uint64_t Miliseconds)
- {
- SmartCriticalSection(APICLock);
- LVTTimer timer = {.raw = 0};
- timer.Vector = s_cst(uint8_t, Vector);
- timer.TimerMode = 0;
- if (strcmp(CPU::Hypervisor(), x86_CPUID_VENDOR_TCG) != 0)
- this->lapic->Write(APIC_TDCR, DivideBy128);
- else
- this->lapic->Write(APIC_TDCR, DivideBy16);
- this->lapic->Write(APIC_TICR, s_cst(uint32_t, Ticks * Miliseconds));
- this->lapic->Write(APIC_TIMER, s_cst(uint32_t, timer.raw));
- }
+ void Timer::OneShot(uint32_t Vector, uint64_t Miliseconds)
+ {
+ SmartCriticalSection(APICLock);
+ LVTTimer timer = {.raw = 0};
+ timer.Vector = s_cst(uint8_t, Vector);
+ timer.TimerMode = 0;
+ if (strcmp(CPU::Hypervisor(), x86_CPUID_VENDOR_TCG) != 0)
+ this->lapic->Write(APIC_TDCR, DivideBy128);
+ else
+ this->lapic->Write(APIC_TDCR, DivideBy16);
+ this->lapic->Write(APIC_TICR, s_cst(uint32_t, Ticks * Miliseconds));
+ this->lapic->Write(APIC_TIMER, s_cst(uint32_t, timer.raw));
+ }
- Timer::Timer(APIC *apic) : Interrupts::Handler(0) /* IRQ0 */
- {
- SmartCriticalSection(APICLock);
- this->lapic = apic;
- LVTTimerDivide Divider = DivideBy16;
+ Timer::Timer(APIC *apic) : Interrupts::Handler(0) /* IRQ0 */
+ {
+ SmartCriticalSection(APICLock);
+ this->lapic = apic;
+ LVTTimerDivide Divider = DivideBy16;
- trace("Initializing APIC timer on CPU %d", GetCurrentCPU()->ID);
+ trace("Initializing APIC timer on CPU %d", GetCurrentCPU()->ID);
- this->lapic->Write(APIC_TDCR, Divider);
- this->lapic->Write(APIC_TICR, 0xFFFFFFFF);
+ this->lapic->Write(APIC_TDCR, Divider);
+ this->lapic->Write(APIC_TICR, 0xFFFFFFFF);
- TimeManager->Sleep(1, Time::Units::Milliseconds);
+ TimeManager->Sleep(1, Time::Units::Milliseconds);
- // Mask the timer
- this->lapic->Write(APIC_TIMER, 0x10000 /* LVTTimer.Mask flag */);
- Ticks = 0xFFFFFFFF - this->lapic->Read(APIC_TCCR);
+ // Mask the timer
+ this->lapic->Write(APIC_TIMER, 0x10000 /* LVTTimer.Mask flag */);
+ Ticks = 0xFFFFFFFF - this->lapic->Read(APIC_TCCR);
- // Config for IRQ0 timer
- LVTTimer timer = {.raw = 0};
- timer.Vector = IRQ0;
- timer.Mask = Unmasked;
- timer.TimerMode = LVTTimerMode::OneShot;
+ // Config for IRQ0 timer
+ LVTTimer timer = {.raw = 0};
+ timer.Vector = IRQ0;
+ timer.Mask = Unmasked;
+ timer.TimerMode = LVTTimerMode::OneShot;
- // Initialize APIC timer
- this->lapic->Write(APIC_TDCR, Divider);
- this->lapic->Write(APIC_TICR, s_cst(uint32_t, Ticks));
- this->lapic->Write(APIC_TIMER, s_cst(uint32_t, timer.raw));
- trace("%d APIC Timer %d ticks in.", GetCurrentCPU()->ID, Ticks);
- KPrint("APIC Timer: \e8888FF%ld\eCCCCCC ticks.", Ticks);
- }
+ // Initialize APIC timer
+ this->lapic->Write(APIC_TDCR, Divider);
+ this->lapic->Write(APIC_TICR, s_cst(uint32_t, Ticks));
+ this->lapic->Write(APIC_TIMER, s_cst(uint32_t, timer.raw));
+ trace("%d APIC Timer %d ticks in.", GetCurrentCPU()->ID, Ticks);
+ KPrint("APIC Timer: \e8888FF%ld\eCCCCCC ticks.", Ticks);
+ }
- Timer::~Timer()
- {
- }
+ Timer::~Timer()
+ {
+ }
}
diff --git a/Architecture/amd64/cpu/SMPTrampoline.asm b/Architecture/amd64/cpu/SMPTrampoline.asm
deleted file mode 100644
index ca690e6..0000000
--- a/Architecture/amd64/cpu/SMPTrampoline.asm
+++ /dev/null
@@ -1,136 +0,0 @@
-; This file is part of Fennix Kernel.
-;
-; Fennix Kernel 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.
-;
-; Fennix Kernel 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 Fennix Kernel. If not, see .
-
-; This has to be the same as enum SMPTrampolineAddress.
-TRAMPOLINE_PAGE_TABLE equ 0x500
-TRAMPOLINE_START_ADDR equ 0x520
-TRAMPOLINE_STACK equ 0x570
-TRAMPOLINE_GDT equ 0x580
-TRAMPOLINE_IDT equ 0x590
-TRAMPOLINE_CORE equ 0x600
-TRAMPOLINE_START equ 0x2000
-
-[bits 16]
-
-extern StartCPU
-global _trampoline_start
-_trampoline_start:
- cli
- mov ax, 0x0
- mov ds, ax
- mov es, ax
- mov fs, ax
- mov gs, ax
- mov ss, ax
- o32 lgdt [ProtectedMode_gdtr - _trampoline_start + TRAMPOLINE_START]
- mov eax, cr0
- or al, 0x1
- mov cr0, eax
- jmp 0x8:(Trampoline32 - _trampoline_start + TRAMPOLINE_START)
-
-[bits 32]
-section .text
-Trampoline32:
- mov bx, 0x10
- mov ds, bx
- mov es, bx
- mov ss, bx
- mov eax, dword [TRAMPOLINE_PAGE_TABLE]
- mov cr3, eax
- mov eax, cr4
- or eax, 1 << 5 ; Set the PAE-bit, which is the 6th bit (bit 5).
- or eax, 1 << 7
- mov cr4, eax
- mov ecx, 0xc0000080
- rdmsr
- or eax,1 << 8 ; LME
- wrmsr
- mov eax, cr0
- or eax, 1 << 31
- mov cr0, eax
- lgdt [LongMode_gdtr - _trampoline_start + TRAMPOLINE_START]
- jmp 0x8:(Trampoline64 - _trampoline_start + TRAMPOLINE_START)
-
-[bits 64]
-Trampoline64:
- mov ax, 0x10
- mov ds, ax
- mov es, ax
- mov ss, ax
- mov ax, 0x0
- mov fs, ax
- mov gs, ax
- lgdt [TRAMPOLINE_GDT]
- lidt [TRAMPOLINE_IDT]
- mov rsp, [TRAMPOLINE_STACK]
- mov rbp, 0x0 ; Terminate stack traces here.
- ; Reset RFLAGS.
- push 0x0
- popf
- mov rax, qword vcode64
- call vcode64
-
-vcode64:
- push rbp
- ; Set up SSE
- mov rax, cr0
- ; btr eax, 2
- ; bts eax, 1
- ; mov cr0, rax
- mov rax, cr4
- bts eax, 9
- bts eax, 10
- mov cr4, rax
- mov rax, qword TrampolineExit
- call rax
-
-align 16
-LongMode_gdtr:
- dw LongModeGDTEnd - LongModeGDTStart - 1
- dq LongModeGDTStart - _trampoline_start + TRAMPOLINE_START
-
-align 16
-LongModeGDTStart:
- dq 0 ; NULL segment
- dq 0x00AF98000000FFFF ; Code segment
- dq 0x00CF92000000FFFF ; Data segment
-LongModeGDTEnd:
-
-align 16
-ProtectedMode_gdtr:
- dw ProtectedModeGDTEnd - ProtectedModeGDTStart - 1
- dd ProtectedModeGDTStart - _trampoline_start + TRAMPOLINE_START
-
-align 16
-ProtectedModeGDTStart:
- dq 0 ; NULL segment
- dq 0x00CF9A000000FFFF ; Code segment
- dq 0x00CF92000000FFFF ; Data segment
-ProtectedModeGDTEnd:
-
-align 16
-ProtectedMode_idtr:
- dw 0
- dd 0
- dd 0
- align 16
-
-global _trampoline_end
-_trampoline_end:
-
-TrampolineExit:
- call StartCPU
-
-times 512 - ($-$$) db 0
diff --git a/Architecture/amd64/cpu/SMPTrampoline.s b/Architecture/amd64/cpu/SMPTrampoline.s
new file mode 100644
index 0000000..7179443
--- /dev/null
+++ b/Architecture/amd64/cpu/SMPTrampoline.s
@@ -0,0 +1,179 @@
+/*
+ This file is part of Fennix Kernel.
+
+ Fennix Kernel 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.
+
+ Fennix Kernel 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 Fennix Kernel. If not, see .
+*/
+
+/* This has to be the same as enum SMPTrampolineAddress. */
+TRAMPOLINE_PAGE_TABLE = 0x500
+TRAMPOLINE_START_ADDR = 0x520
+TRAMPOLINE_STACK = 0x570
+TRAMPOLINE_GDT = 0x580
+TRAMPOLINE_IDT = 0x590
+TRAMPOLINE_CORE = 0x600
+TRAMPOLINE_START = 0x2000
+
+.section .text
+
+/* ========== 16-bit ========== */
+
+.code16
+.global _trampoline_start
+_trampoline_start:
+ cli
+ cld
+ call Trampoline16
+
+Trampoline16:
+ mov $0x0, %ax
+ mov %ax, %ds
+ mov %ax, %es
+ mov %ax, %fs
+ mov %ax, %gs
+ mov %ax, %ss
+
+ /* Load Protected Mode GDT */
+ lgdt [ProtectedMode_gdtr - _trampoline_start + TRAMPOLINE_START]
+
+ /* Enable Protected Mode */
+ mov %cr0, %eax
+ or $0x1, %al
+ mov %eax, %cr0
+
+ /* Jump to Protected Mode */
+ ljmp $0x8, $(Trampoline32 - _trampoline_start + TRAMPOLINE_START)
+
+/* ========== 32-bit ========== */
+
+.code32
+Trampoline32:
+ mov $0x10, %bx
+ mov %bx, %ds
+ mov %bx, %es
+ mov %bx, %ss
+
+ /* Set a page table */
+ mov [TRAMPOLINE_PAGE_TABLE], %eax
+ mov %eax, %cr3
+
+ /* Enable PAE and PSE */
+ mov %cr4, %eax
+ or $0x20, %eax /* PAE */
+ or $0x80, %eax /* PSE */
+ mov %eax, %cr4
+
+ /* Enable Long Mode */
+ mov $0xC0000080, %ecx
+ rdmsr
+ or $0x100, %eax /* LME */
+ wrmsr
+
+ /* Enable paging */
+ mov %cr0, %eax
+ or $0x80000000, %eax /* PG */
+ mov %eax, %cr0
+
+ /* Load Long Mode GDT */
+ lgdt [LongMode_gdtr - _trampoline_start + TRAMPOLINE_START]
+
+ /* Jump to Long Mode */
+ ljmp $0x8, $(Trampoline64 - _trampoline_start + TRAMPOLINE_START)
+
+/* ========== 64-bit ========== */
+
+.code64
+Trampoline64:
+ mov $0x10, %ax
+ mov %ax, %ds
+ mov %ax, %es
+ mov %ax, %ss
+
+ mov $0x0, %ax
+ mov %ax, %fs
+ mov %ax, %gs
+
+ /* Set custom GDT & IDT */
+ lgdt [TRAMPOLINE_GDT]
+ lidt [TRAMPOLINE_IDT]
+
+ /* Set up stack */
+ mov [TRAMPOLINE_STACK], %rsp
+ mov $0x0, %rbp
+
+ /* Reset RFLAGS */
+ push $0x0
+ popf
+
+ /* Jump to TrampolinePrepareExit */
+ call TrampolineExit
+
+.extern StartCPU
+TrampolineExit:
+ mov $StartCPU, %rax
+ call *%rax
+
+.align 16
+ProtectedMode_gdtr:
+ .word ProtectedModeGDTEnd - ProtectedModeGDTStart - 1
+ .long ProtectedModeGDTStart - _trampoline_start + TRAMPOLINE_START
+
+.align 16
+ProtectedModeGDTStart:
+ /* NULL segment */
+ .quad 0x0
+
+ /* Code segment */
+ .word 0xFFFF
+ .word 0x0000
+ .byte 0x00
+ .word 0xCF9A
+ .byte 0x00
+
+ /* Data segment */
+ .word 0xFFFF
+ .word 0x0000
+ .byte 0x00
+ .word 0xCF92
+ .byte 0x00
+ProtectedModeGDTEnd:
+ nop
+
+.align 16
+LongMode_gdtr:
+ .word LongModeGDTEnd - LongModeGDTStart - 1
+ .quad LongModeGDTStart - _trampoline_start + TRAMPOLINE_START
+
+.align 16
+LongModeGDTStart:
+ /* NULL segment */
+ .quad 0x0
+
+ /* Code segment */
+ .word 0xFFFF
+ .word 0x0000
+ .byte 0x00
+ .word 0xAF98
+ .byte 0x00
+
+ /* Data segment */
+ .word 0xFFFF
+ .word 0x0000
+ .byte 0x00
+ .word 0xCF92
+ .byte 0x00
+LongModeGDTEnd:
+ nop
+
+.global _trampoline_end
+_trampoline_end:
diff --git a/Architecture/amd64/cpu/SymmetricMultiprocessing.cpp b/Architecture/amd64/cpu/SymmetricMultiprocessing.cpp
index fce30d2..b1bec07 100644
--- a/Architecture/amd64/cpu/SymmetricMultiprocessing.cpp
+++ b/Architecture/amd64/cpu/SymmetricMultiprocessing.cpp
@@ -32,13 +32,13 @@ extern "C" uint64_t _trampoline_start, _trampoline_end;
/* https://wiki.osdev.org/Memory_Map_(x86) */
enum SMPTrampolineAddress
{
- PAGE_TABLE = 0x500,
- START_ADDR = 0x520,
- STACK = 0x570,
- GDT = 0x580,
- IDT = 0x590,
- CORE = 0x600,
- TRAMPOLINE_START = 0x2000
+ PAGE_TABLE = 0x500,
+ START_ADDR = 0x520,
+ STACK = 0x570,
+ GDT = 0x580,
+ IDT = 0x590,
+ CORE = 0x600,
+ TRAMPOLINE_START = 0x2000
};
std::atomic_bool CPUEnabled = false;
@@ -50,92 +50,106 @@ SafeFunction CPUData *GetCPU(long id) { return &CPUs[id]; }
SafeFunction CPUData *GetCurrentCPU()
{
- if (unlikely(!Interrupts::apic[0]))
- return &CPUs[0]; /* No APIC means we are on the BSP. */
+ if (unlikely(!Interrupts::apic[0]))
+ return &CPUs[0]; /* No APIC means we are on the BSP. */
- int CoreID = ((APIC::APIC *)Interrupts::apic[0])->Read(APIC::APIC_ID) >> 24;
+ int CoreID = ((APIC::APIC *)Interrupts::apic[0])->Read(APIC::APIC_ID) >> 24;
- if (unlikely((&CPUs[CoreID])->IsActive != true))
- {
- error("CPU %d is not active!", CoreID);
- assert((&CPUs[0])->IsActive == true); /* We can't continue without the BSP. */
- return &CPUs[0];
- }
+ if (unlikely((&CPUs[CoreID])->IsActive != true))
+ {
+ error("CPU %d is not active!", CoreID);
+ assert((&CPUs[0])->IsActive == true); /* We can't continue without the BSP. */
+ return &CPUs[0];
+ }
- assert((&CPUs[CoreID])->Checksum == CPU_DATA_CHECKSUM); /* This should never happen. */
- return &CPUs[CoreID];
+ assert((&CPUs[CoreID])->Checksum == CPU_DATA_CHECKSUM); /* This should never happen. */
+ return &CPUs[CoreID];
}
extern "C" void StartCPU()
{
- CPU::Interrupts(CPU::Disable);
- int CoreID = (int)*reinterpret_cast(CORE);
- CPU::InitializeFeatures(CoreID);
- // Initialize GDT and IDT
- Interrupts::Initialize(CoreID);
- Interrupts::Enable(CoreID);
- Interrupts::InitializeTimer(CoreID);
- asmv("mov %0, %%rsp" ::"r"((&CPUs[CoreID])->Stack));
+ CPU::Interrupts(CPU::Disable);
+ int CoreID = (int)*reinterpret_cast(CORE);
+ CPU::InitializeFeatures(CoreID);
+ // Initialize GDT and IDT
+ Interrupts::Initialize(CoreID);
+ Interrupts::Enable(CoreID);
+ Interrupts::InitializeTimer(CoreID);
+ asmv("mov %0, %%rsp" ::"r"((&CPUs[CoreID])->Stack));
- CPU::Interrupts(CPU::Enable);
- KPrint("\e058C19CPU \e8888FF%d \e058C19is online", CoreID);
- CPUEnabled.store(true, std::memory_order_release);
- CPU::Halt(true);
+ CPU::Interrupts(CPU::Enable);
+ KPrint("\e058C19CPU \e8888FF%d \e058C19is online", CoreID);
+ CPUEnabled.store(true, std::memory_order_release);
+ CPU::Halt(true);
}
namespace SMP
{
- int CPUCores = 0;
+ int CPUCores = 0;
- void Initialize(void *madt)
- {
- int Cores = ((ACPI::MADT *)madt)->CPUCores + 1;
+ void Initialize(void *_madt)
+ {
+ ACPI::MADT *madt = (ACPI::MADT *)_madt;
- if (Config.Cores > ((ACPI::MADT *)madt)->CPUCores + 1)
- KPrint("More cores requested than available. Using %d cores", ((ACPI::MADT *)madt)->CPUCores + 1);
- else if (Config.Cores != 0)
- Cores = Config.Cores;
+ int Cores = madt->CPUCores + 1;
- CPUCores = Cores;
+ if (Config.Cores > madt->CPUCores + 1)
+ KPrint("More cores requested than available. Using %d cores", madt->CPUCores + 1);
+ else if (Config.Cores != 0)
+ Cores = Config.Cores;
- uint64_t TrampolineLength = (uintptr_t)&_trampoline_end - (uintptr_t)&_trampoline_start;
- Memory::Virtual().Map(0x0, 0x0, Memory::PTFlag::RW);
- /* We reserved the TRAMPOLINE_START address inside Physical class. */
- Memory::Virtual().Map((void *)TRAMPOLINE_START, (void *)TRAMPOLINE_START, TrampolineLength, Memory::PTFlag::RW);
- memcpy((void *)TRAMPOLINE_START, &_trampoline_start, TrampolineLength);
- debug("Trampoline address: %#lx-%#lx", TRAMPOLINE_START, TRAMPOLINE_START + TrampolineLength);
+ CPUCores = Cores;
- void *CPUTmpStack = KernelAllocator.RequestPages(TO_PAGES(STACK_SIZE + 1));
- asmv("sgdt [0x580]\n"
- "sidt [0x590]\n");
- VPOKE(uintptr_t, STACK) = (uintptr_t)CPUTmpStack + STACK_SIZE;
- VPOKE(uintptr_t, PAGE_TABLE) = (uintptr_t)KernelPageTable;
- VPOKE(uint64_t, START_ADDR) = (uintptr_t)&StartCPU;
+ uint64_t TrampolineLength = (uintptr_t)&_trampoline_end - (uintptr_t)&_trampoline_start;
+ Memory::Virtual().Map(0x0, 0x0, Memory::PTFlag::RW);
+ /* We reserved the TRAMPOLINE_START address inside Physical class. */
+ Memory::Virtual().Map((void *)TRAMPOLINE_START, (void *)TRAMPOLINE_START, TrampolineLength, Memory::PTFlag::RW);
+ memcpy((void *)TRAMPOLINE_START, &_trampoline_start, TrampolineLength);
+ debug("Trampoline address: %#lx-%#lx", TRAMPOLINE_START, TRAMPOLINE_START + TrampolineLength);
- for (int i = 0; i < Cores; i++)
- {
- debug("Initializing CPU %d", i);
- if ((((APIC::APIC *)Interrupts::apic[0])->Read(APIC::APIC_ID) >> 24) != ((ACPI::MADT *)madt)->lapic[i]->ACPIProcessorId)
- {
- VPOKE(int, CORE) = i;
+ void *CPUTmpStack = KernelAllocator.RequestPages(TO_PAGES(STACK_SIZE + 1));
+ asmv("sgdt [0x580]");
+ asmv("sidt [0x590]");
+ VPOKE(uintptr_t, STACK) = (uintptr_t)CPUTmpStack + STACK_SIZE;
+ VPOKE(uintptr_t, PAGE_TABLE) = (uintptr_t)KernelPageTable;
+ VPOKE(uintptr_t, START_ADDR) = (uintptr_t)&StartCPU;
- ((APIC::APIC *)Interrupts::apic[0])->Write(APIC::APIC_ICRHI, (((ACPI::MADT *)madt)->lapic[i]->APICId << 24));
- ((APIC::APIC *)Interrupts::apic[0])->Write(APIC::APIC_ICRLO, 0x500);
+ for (int i = 0; i < Cores; i++)
+ {
+ ACPI::MADT::LocalAPIC *lapic = madt->lapic[i];
+ debug("Initializing CPU %d", lapic->APICId);
+ if ((((APIC::APIC *)Interrupts::apic[0])->Read(APIC::APIC_ID) >> 24) != lapic->APICId)
+ {
+ VPOKE(int, CORE) = i;
- ((APIC::APIC *)Interrupts::apic[0])->SendInitIPI(((ACPI::MADT *)madt)->lapic[i]->APICId);
- ((APIC::APIC *)Interrupts::apic[0])->SendStartupIPI(((ACPI::MADT *)madt)->lapic[i]->APICId, TRAMPOLINE_START);
+ ((APIC::APIC *)Interrupts::apic[0])->Write(APIC::APIC_ICRHI, (lapic->APICId << 24));
+ ((APIC::APIC *)Interrupts::apic[0])->Write(APIC::APIC_ICRLO, 0x500);
- while (!CPUEnabled.load(std::memory_order_acquire))
- CPU::Pause();
- CPUEnabled.store(false, std::memory_order_release);
- trace("CPU %d loaded.", ((ACPI::MADT *)madt)->lapic[i]->APICId);
- }
- else
- KPrint("\e058C19CPU \e8888FF%d \e058C19is the BSP", ((ACPI::MADT *)madt)->lapic[i]->APICId);
- }
+ ((APIC::APIC *)Interrupts::apic[0])->SendInitIPI(lapic->APICId);
+ TimeManager->Sleep(5, Time::Units::Milliseconds);
+ ((APIC::APIC *)Interrupts::apic[0])->SendStartupIPI(lapic->APICId, TRAMPOLINE_START);
- KernelAllocator.FreePages(CPUTmpStack, TO_PAGES(STACK_SIZE + 1));
- /* We are going to unmap the page after we are done with it. */
- Memory::Virtual().Unmap(0x0);
- }
+ debug("Waiting for CPU %d to load...", lapic->APICId);
+ uint64_t Timeout = TimeManager->CalculateTarget(2, Time::Units::Seconds);
+ while (CPUEnabled.load(std::memory_order_acquire) == false)
+ {
+ if (TimeManager->GetCounter() > Timeout)
+ {
+ error("CPU %d failed to load!", lapic->APICId);
+ KPrint("\eFF8C19CPU \e8888FF%d \eFF8C19failed to load!", lapic->APICId);
+ break;
+ }
+ CPU::Pause();
+ }
+ trace("CPU %d loaded.", lapic->APICId);
+ CPUEnabled.store(false, std::memory_order_release);
+ }
+ else
+ KPrint("\e058C19CPU \e8888FF%d \e058C19is the BSP", lapic->APICId);
+ }
+
+ KernelAllocator.FreePages(CPUTmpStack, TO_PAGES(STACK_SIZE + 1));
+ /* We are going to unmap the page after we are done with it. */
+ Memory::Virtual().Unmap(0x0);
+ }
}
diff --git a/Architecture/i386/Bootstrap/Multiboot/1/Start.asm b/Architecture/i386/Bootstrap/Multiboot/1/Start.asm
deleted file mode 100644
index 49bc2c2..0000000
--- a/Architecture/i386/Bootstrap/Multiboot/1/Start.asm
+++ /dev/null
@@ -1,22 +0,0 @@
-; This file is part of Fennix Kernel.
-;
-; Fennix Kernel 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.
-;
-; Fennix Kernel 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 Fennix Kernel. If not, see .
-
-[bits 32]
-
-section .bootstrap.text
-
-global Multiboot1_start
-Multiboot1_start:
- int3
diff --git a/Architecture/i386/Bootstrap/Multiboot/2/Multiboot_PageTable.s_fixme b/Architecture/i386/Bootstrap/Multiboot/1/Start.s
similarity index 90%
rename from Architecture/i386/Bootstrap/Multiboot/2/Multiboot_PageTable.s_fixme
rename to Architecture/i386/Bootstrap/Multiboot/1/Start.s
index 8d58c66..8efbeb2 100644
--- a/Architecture/i386/Bootstrap/Multiboot/2/Multiboot_PageTable.s_fixme
+++ b/Architecture/i386/Bootstrap/Multiboot/1/Start.s
@@ -15,6 +15,9 @@
along with Fennix Kernel. If not, see .
*/
-.intel_syntax noprefix
-
.code32
+.section .bootstrap.text
+
+.global Multiboot1_start
+Multiboot1_start:
+ jmp .
diff --git a/Architecture/i386/Bootstrap/Multiboot/2/Multiboot_PageTable.asm b/Architecture/i386/Bootstrap/Multiboot/2/Multiboot_PageTable.asm
deleted file mode 100644
index 1fefe1f..0000000
--- a/Architecture/i386/Bootstrap/Multiboot/2/Multiboot_PageTable.asm
+++ /dev/null
@@ -1,46 +0,0 @@
-; This file is part of Fennix Kernel.
-;
-; Fennix Kernel 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.
-;
-; Fennix Kernel 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 Fennix Kernel. If not, see .
-
-[bits 32]
-
-KERNEL_VIRTUAL_BASE equ 0xC0000000 ; 3GB or 0xC0000000
-KERNEL_PAGE_NUMBER equ (KERNEL_VIRTUAL_BASE >> 22) ; 768
-
-section .bootstrap.data
-align 0x1000
-global BootPageTable
-BootPageTable:
- dd 0x00000083
- dd 0x00400083
- dd 0x00800083
- dd 0x00C00083
- dd 0x01000083
- dd 0x01400083
- dd 0x01800083
- dd 0x01C00083
- dd 0x02000083
- dd 0x02400083
- times (KERNEL_PAGE_NUMBER - 10) dd 0
- dd 0x00000083
- dd 0x00400083
- dd 0x00800083
- dd 0x00C00083
- dd 0x01000083
- dd 0x01400083
- dd 0x01800083
- dd 0x01C00083
- dd 0x02000083
- dd 0x02400083
- times (1024 - KERNEL_PAGE_NUMBER - 10) dd 0
diff --git a/Architecture/i386/Bootstrap/Multiboot/2/Multiboot_PageTable.s b/Architecture/i386/Bootstrap/Multiboot/2/Multiboot_PageTable.s
new file mode 100644
index 0000000..2edfa75
--- /dev/null
+++ b/Architecture/i386/Bootstrap/Multiboot/2/Multiboot_PageTable.s
@@ -0,0 +1,51 @@
+/*
+ This file is part of Fennix Kernel.
+
+ Fennix Kernel 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.
+
+ Fennix Kernel 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 Fennix Kernel. If not, see .
+*/
+
+.code32
+KERNEL_VIRTUAL_BASE = 0xC0000000 /* 3GB */
+KERNEL_PAGE_NUMBER = 768 /* KERNEL_VIRTUAL_BASE >> 22 */
+
+.section .bootstrap.data
+.align 0x1000
+.global BootPageTable
+BootPageTable:
+ .long 0x00000083
+ .long 0x00400083
+ .long 0x00800083
+ .long 0x00C00083
+ .long 0x01000083
+ .long 0x01400083
+ .long 0x01800083
+ .long 0x01C00083
+ .long 0x02000083
+ .long 0x02400083
+ .rept (KERNEL_PAGE_NUMBER - 10)
+ .long 0
+ .endr
+ .long 0x00000083
+ .long 0x00400083
+ .long 0x00800083
+ .long 0x00C00083
+ .long 0x01000083
+ .long 0x01400083
+ .long 0x01800083
+ .long 0x01C00083
+ .long 0x02000083
+ .long 0x02400083
+ .rept (1024 - KERNEL_PAGE_NUMBER - 10)
+ .long 0
+ .endr
diff --git a/Architecture/i386/Bootstrap/Multiboot/2/Start.asm b/Architecture/i386/Bootstrap/Multiboot/2/Start.asm
deleted file mode 100644
index ae571ac..0000000
--- a/Architecture/i386/Bootstrap/Multiboot/2/Start.asm
+++ /dev/null
@@ -1,86 +0,0 @@
-; This file is part of Fennix Kernel.
-;
-; Fennix Kernel 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.
-;
-; Fennix Kernel 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 Fennix Kernel. If not, see .
-
-[bits 32]
-KERNEL_STACK_SIZE equ 0x4000 ; 16KB
-
-extern DetectCPUID
-extern Detect64Bit
-extern DetectPSE
-extern DetectPAE
-extern multiboot_main
-extern LoadGDT32
-extern BootPageTable
-
-section .bootstrap.data
-MB_HeaderMagic:
- dq 0
-
-MB_HeaderInfo:
- dq 0
-
-section .bootstrap.text
-
-global Multiboot2_start
-Multiboot2_start:
- cli
-
- mov [MB_HeaderMagic], eax
- mov [MB_HeaderInfo], ebx
-
- call DetectCPUID
- cmp eax, 0
- je $
-
- ; call Detect64Bit
- ; cmp eax, 0
- ; je $
-
- call DetectPSE
- cmp eax, 0
- je $
-
- ; call DetectPAE
- ; cmp eax, 0
- ; je $
-
- mov ecx, cr4
- or ecx, 0x00000010 ; Set PSE in CR4
- ; or ecx, 0x00000020 ; Set PAE in CR4
- mov cr4, ecx
-
- call LoadGDT32
-
- mov ecx, BootPageTable
- mov cr3, ecx
-
- mov ecx, cr0
- or ecx, 0x80000001 ; Set PG and PE in CR0
- mov cr0, ecx
-
- mov esp, KernelStack + KERNEL_STACK_SIZE
- mov eax, [MB_HeaderMagic]
- mov ebx, [MB_HeaderInfo]
- push ebx
- push eax
- call multiboot_main
-.Hang:
- hlt
- jmp .Hang
-
-section .bootstrap.bss
-align 16
-KernelStack:
- resb KERNEL_STACK_SIZE
diff --git a/Architecture/i386/Bootstrap/Multiboot/2/Start.s b/Architecture/i386/Bootstrap/Multiboot/2/Start.s
new file mode 100644
index 0000000..472fa6b
--- /dev/null
+++ b/Architecture/i386/Bootstrap/Multiboot/2/Start.s
@@ -0,0 +1,79 @@
+/*
+ This file is part of Fennix Kernel.
+
+ Fennix Kernel 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.
+
+ Fennix Kernel 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 Fennix Kernel. If not, see .
+*/
+
+.code32
+KERNEL_STACK_SIZE = 0x4000 /* 16KB */
+
+.extern DetectCPUID
+.extern DetectPSE
+.extern multiboot_main
+.extern LoadGDT32
+.extern BootPageTable
+
+.section .bootstrap.data
+MB_HeaderMagic:
+ .quad 0
+
+MB_HeaderInfo:
+ .quad 0
+
+.section .bootstrap.text
+
+.global Multiboot2_start
+Multiboot2_start:
+ cli
+
+ mov %eax, [MB_HeaderMagic]
+ mov %ebx, [MB_HeaderInfo]
+
+ call DetectCPUID
+ cmp $0, %eax
+ je .
+
+ call DetectPSE
+ cmp $0, %eax
+ je .
+
+ mov %cr4, %ecx
+ or $0x00000010, %ecx /* PSE */
+ mov %ecx, %cr4
+
+ call LoadGDT32
+
+ mov $BootPageTable, %ecx
+ mov %ecx, %cr3
+
+ mov %cr0, %ecx
+ or $0x80000000, %ecx /* PG */
+ mov %ecx, %cr0
+
+ mov $(KernelStack + KERNEL_STACK_SIZE), %esp
+ mov $0x0, %ebp
+
+ mov [MB_HeaderMagic], %eax
+ mov [MB_HeaderInfo], %ebx
+ push %ebx
+ push %eax
+ call multiboot_main
+.Hang:
+ hlt
+ jmp .Hang
+
+.section .bootstrap.bss
+.align 16
+KernelStack:
+ .space KERNEL_STACK_SIZE
diff --git a/Makefile b/Makefile
index 26e3d01..d9432cf 100644
--- a/Makefile
+++ b/Makefile
@@ -11,8 +11,6 @@ NM = ../$(COMPILER_PATH)/$(COMPILER_ARCH)nm
OBJCOPY = ../$(COMPILER_PATH)/$(COMPILER_ARCH)objcopy
OBJDUMP = ../$(COMPILER_PATH)/$(COMPILER_ARCH)objdump
GDB = ../$(COMPILER_PATH)/$(COMPILER_ARCH)gdb
-RUSTC = /usr/bin/rustc
-NASM = /usr/bin/nasm
RUST_TARGET_PATH = Architecture/$(OSARCH)/rust-target.json
@@ -22,19 +20,16 @@ GIT_COMMIT_SHORT = $(shell git rev-parse --short HEAD)
BMP_SOURCES = $(shell find ./ -type f -name '*.bmp')
PSF_SOURCES = $(shell find ./ -type f -name '*.psf')
ifeq ($(OSARCH), amd64)
-ASM_SOURCES = $(shell find ./ -type f -name '*.asm' -not -path "./Architecture/i386/*" -not -path "./Architecture/aarch64/*")
S_SOURCES = $(shell find ./ -type f -name '*.S' -not -path "./Architecture/i386/*" -not -path "./Architecture/aarch64/*")
s_SOURCES = $(shell find ./ -type f -name '*.s' -not -path "./Architecture/i386/*" -not -path "./Architecture/aarch64/*")
C_SOURCES = $(shell find ./ -type f -name '*.c' -not -path "./Architecture/i386/*" -not -path "./Architecture/aarch64/*")
CPP_SOURCES = $(shell find ./ -type f -name '*.cpp' -not -path "./Architecture/i386/*" -not -path "./Architecture/aarch64/*")
else ifeq ($(OSARCH), i386)
-ASM_SOURCES = $(shell find ./ -type f -name '*.asm' -not -path "./Architecture/amd64/*" -not -path "./Architecture/aarch64/*")
S_SOURCES = $(shell find ./ -type f -name '*.S' -not -path "./Architecture/amd64/*" -not -path "./Architecture/aarch64/*")
s_SOURCES = $(shell find ./ -type f -name '*.s' -not -path "./Architecture/amd64/*" -not -path "./Architecture/aarch64/*")
C_SOURCES = $(shell find ./ -type f -name '*.c' -not -path "./Architecture/amd64/*" -not -path "./Architecture/aarch64/*")
CPP_SOURCES = $(shell find ./ -type f -name '*.cpp' -not -path "./Architecture/amd64/*" -not -path "./Architecture/aarch64/*")
else ifeq ($(OSARCH), aarch64)
-ASM_SOURCES = $(shell find ./ -type f -name '*.asm' -not -path "./Architecture/amd64/*" -not -path "./Architecture/i386/*")
S_SOURCES = $(shell find ./ -type f -name '*.S' -not -path "./Architecture/amd64/*" -not -path "./Architecture/i386/*")
s_SOURCES = $(shell find ./ -type f -name '*.s' -not -path "./Architecture/amd64/*" -not -path "./Architecture/i386/*")
C_SOURCES = $(shell find ./ -type f -name '*.c' -not -path "./Architecture/amd64/*" -not -path "./Architecture/i386/*")
@@ -98,14 +93,6 @@ LDFLAGS += -TArchitecture/aarch64/linker.ld -fPIC -pie \
endif
-ifeq ($(OSARCH), amd64)
-NASMFLAGS := -f elf64
-else ifeq ($(OSARCH), i386)
-NASMFLAGS := -f elf32
-else ifeq ($(OSARCH), aarch64)
-NASMFLAGS :=
-endif
-
# -finstrument-functions for __cyg_profile_func_enter & __cyg_profile_func_exit. Used for profiling and debugging.
ifeq ($(DEBUG), 1)
# CFLAGS += --coverage
@@ -119,11 +106,8 @@ ifneq ($(OSARCH), aarch64)
CFLAGS += -fstack-check
endif
LDFLAGS += -ggdb3 -O0
- NASMFLAGS += -F dwarf -g
+ ASFLAGS += -g --gstabs --gdwarf-5 -D
WARNCFLAG += -Wno-unused-function -Wno-maybe-uninitialized -Wno-builtin-declaration-mismatch -Wno-unknown-pragmas -Wno-unused-parameter -Wno-unused-variable
-ifeq ($(TESTING), 1)
- CFLAGS += -DTESTING
-endif
endif
default:
@@ -156,20 +140,13 @@ $(KERNEL_FILENAME): $(OBJ)
$(info Compiling $<)
$(CPP) $(CFLAGS) $(CFLAG_STACK_PROTECTOR) $(WARNCFLAG) -std=c++20 -c $< -o $@ -fno-exceptions -fno-rtti
-%.o: %.asm
-ifeq ($(OSARCH), aarch64)
- $(error aarch64 does not support NASM)
-endif
- $(info Compiling $<)
- $(NASM) $< $(NASMFLAGS) -o $@
-
%.o: %.S
$(info Compiling $<)
- $(AS) -c $< -o $@
+ $(AS) $(ASFLAGS) -c $< -o $@
%.o: %.s
$(info Compiling $<)
- $(AS) -c $< -o $@
+ $(AS) $(ASFLAGS) -c $< -o $@
%.o: %.psf
ifeq ($(OSARCH), amd64)
diff --git a/include/cpu.hpp b/include/cpu.hpp
index fcea0ad..3a6582d 100644
--- a/include/cpu.hpp
+++ b/include/cpu.hpp
@@ -139,7 +139,7 @@ namespace CPU
/**
* @brief Pause the CPU
*/
- SafeFunction static inline void Pause(bool Loop = false)
+ SafeFunction static __always_inline inline void Pause(bool Loop = false)
{
do
{
@@ -166,15 +166,15 @@ namespace CPU
{
asmv("CPUStopLoop:\n"
"msr daifset, #2\n" // Disable IRQs (bit 1 of the DAIF register)
- "wfi\n" // Wait for Interrupt (puts the processor in low-power state until an interrupt occurs)
- "b CPUStopLoop"); // Branch to the beginning of the loop
+ "wfi\n" // Wait for Interrupt (puts the processor in low-power state until an interrupt occurs)
+ "b CPUStopLoop"); // Branch to the beginning of the loop
#endif
}
/**
* @brief Halt the CPU
*/
- SafeFunction static inline void Halt(bool Loop = false)
+ SafeFunction static __always_inline inline void Halt(bool Loop = false)
{
do
{
@@ -206,7 +206,7 @@ namespace CPU
void InitializeFeatures(long Core);
/** @brief Get CPU counter value. */
- uintptr_t Counter();
+ uint64_t Counter();
namespace x32
{
@@ -280,7 +280,7 @@ namespace CPU
uint32_t eax; // Accumulator
uint32_t InterruptNumber; // Interrupt Number
- uint32_t ErrorCode; // Error code
+ uint32_t ErrorCode; // Error code
uint32_t eip; // Instruction Pointer
uint32_t cs; // Code Segment
@@ -598,7 +598,7 @@ namespace CPU
uint64_t rax; // Accumulator
uint64_t InterruptNumber; // Interrupt Number
- uint64_t ErrorCode; // Error code
+ uint64_t ErrorCode; // Error code
uint64_t rip; // Instruction Pointer
uint64_t cs; // Code Segment
@@ -911,9 +911,9 @@ namespace CPU
uint64_t x29; // Frame pointer
uint64_t x30; // Program counter
- uint64_t sp_el0; // Stack pointer
- uint64_t elr_el1; // Exception Link Register
- uint64_t spsr_el1; // Saved Program Status Register
+ uint64_t sp_el0; // Stack pointer
+ uint64_t elr_el1; // Exception Link Register
+ uint64_t spsr_el1; // Saved Program Status Register
uint64_t ErrorCode /* esr_el1 */; // Exception Syndrome Register
uint64_t InterruptNumber /* iar_el1 */; // Interrupt Acknowledge Register