metal-cos/sys/amd64/mpboot.S
2023-09-09 20:18:08 -04:00

186 lines
3.4 KiB
ArmAsm

/**
* Low level multiprocessor boot code
*/
#define KERNEL_BASE 0xFFFF800000000000
#define LOWMEM(_x) (_x - KERNEL_BASE)
#define MPLOWMEM(_x) (_x - KERNEL_BASE + 0x7000)
.extern bootpgtbl1
.extern stack
.extern Machine_InitAP
.text
/**
* mpstart_begin --
*
* Support processors start executing here in 16-bit compat mode.
*/
.code16
.globl mpstart_begin
mpstart_begin:
// Disable interrupts
cli
// Initialize the segment registers to 0, which is an offset in 16-bit mode
xorw %ax, %ax
movw %ax, %ds
movw %ax, %es
movw %ax, %fs
movw %ax, %gs
// Load 32-bit GDT
lgdt (mpstartgdtdesc32 - mpstart_begin + 0x7000)
movl %cr0, %eax
orl 0x00000011, %eax
movl %eax, %cr0
// Long jump to reload the code segment switching us into 32-bit mode
ljmp $0x08, $(mpstart_enter32 - mpstart_begin + 0x7000)
nop
nop
// Now we're in 32-bit mode
.code32
mpstart_enter32:
nop
nop
// Initialize segment registers
movw $0x10, %ax
movw %ax, %ds
movw %ax, %es
movw %ax, %fs
movw %ax, %gs
// Setup stack
movw %ax,%ss
movl $0x7000, %esp
// Reset EFLAGS
pushl $0x0
popf
// Set CR4
movl %cr4, %eax
orl $0x0000006A0, %eax
movl %eax, %cr4
// Temporary Page Table
movl $LOWMEM(bootpgtbl1), %eax
movl %eax, %cr3
// Set EFER
movl $0xC0000080, %ecx
rdmsr
orl $0x0900, %eax
wrmsr
// Load 64-bit GDT
movl $LOWMEM(mpstartgdtdesc), %eax
lgdt (%eax)
// Set CR0
movl %cr0, %eax
// QEMU seems to set cr0 with garbage
andl $0x1FF5FFC0, %eax
orl $0x8005002B, %eax
movl %eax, %cr0
// Long jump again to swithc us into 64-bit mode
movl $LOWMEM(mpstart_enter64ptr), %edi
ljmp *(%edi)
nop
nop
// Now we're playing with power
.code64
mpstart_enter64:
nop
nop
// Jump into the high memory address where the kernel should execute
movq $LOWMEM(mpstart_high64ptr), %rdi
jmp *(%rdi)
nop
nop
mpstart_high64:
nop
nop
// Load Initial CPU State
movq (0x6F00), %rax
movq (0x6F08), %rbx
movq %rax, %cr3
movq %rbx, %rsp
call Machine_InitAP
// If we get here something went wrong so we write HALT to the display
1:
movw $(0x5000 + 'H'), (0xB8098)
movw $(0x5000 + 'A'), (0xB809A)
movw $(0x5000 + 'L'), (0xB809C)
movw $(0x5000 + 'T'), (0xB809E)
jmp 1b
.p2align 4
mpstart_enter64ptr:
.long LOWMEM(mpstart_enter64)
.word 0x08
.p2align 4
mpstart_high64ptr:
.quad mpstart_high64
/**
* 32-bit GDT Table
*/
.p2align 12
mpstartgdt32:
.quad 0x0000000000000000 /* Null */
.quad 0x00CF9A000000FFFF /* Temporary CS */
.quad 0x00CF92000000FFFF /* Temporary DS */
.quad 0x0000000000000000
.quad 0x0000000000000000
.quad 0x0000000000000000
.quad 0x0000000000000000
.quad 0x0000000000000000
.p2align 4
mpstartgdtdesc32:
.word 0x003F
.long LOWMEM(mpstartgdt32)
.p2align 12
mpstartgdt:
.quad 0x0000000000000000 /* Null */
.quad 0x00AF9C000000FFFF /* Kernel CS */
.quad 0x00CF92000000FFFF /* Kernel DS */
.quad 0x0000000000000000
.quad 0x0000000000000000
.quad 0x0000000000000000
.quad 0x0000000000000000
.quad 0x0000000000000000
.p2align 4
.quad 0x0
mpstartgdtdesc:
.word 0x003F
.quad LOWMEM(mpstartgdt)
.globl mpstart_end
mpstart_end:
// Boot stack
//.globl mpstack
//.comm mpstack, STACK_SIZE