186 lines
3.4 KiB
ArmAsm
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
|
|
|