forked from Bananymous/banan-os
Kernel: Don't load AP init code to 0xF000, but relocate it later
This cleans up the kernel executable as bootloaders don't have to load AP init code straight to 0xF000, but it will be moved there once kernel is doing the AP initialization.
This commit is contained in:
parent
066e8e1cc2
commit
969563c06a
|
@ -1,4 +1,4 @@
|
||||||
.section .userspace, "aw"
|
.section .userspace, "ax"
|
||||||
|
|
||||||
// stack contains
|
// stack contains
|
||||||
// return address
|
// return address
|
||||||
|
|
|
@ -235,26 +235,31 @@ system_halt:
|
||||||
jmp 1b
|
jmp 1b
|
||||||
|
|
||||||
|
|
||||||
|
#define AP_V2P(vaddr) ((vaddr) - ap_trampoline + 0xF000)
|
||||||
|
|
||||||
.section .ap_init, "ax"
|
.section .ap_init, "ax"
|
||||||
|
|
||||||
.code16
|
.code16
|
||||||
.global ap_trampoline
|
.global ap_trampoline
|
||||||
ap_trampoline:
|
ap_trampoline:
|
||||||
jmp 1f
|
jmp 1f
|
||||||
|
|
||||||
.align 8
|
.align 8
|
||||||
ap_stack_ptr:
|
ap_stack_ptr:
|
||||||
.skip 4
|
.skip 4
|
||||||
1:
|
ap_stack_loaded:
|
||||||
cli; cld
|
.skip 1
|
||||||
ljmpl $0x00, $ap_cs_clear
|
|
||||||
ap_cs_clear:
|
|
||||||
|
|
||||||
|
1: cli; cld
|
||||||
|
ljmpl $0x00, $AP_V2P(ap_cs_clear)
|
||||||
|
|
||||||
|
ap_cs_clear:
|
||||||
# load ap gdt and enter protected mode
|
# load ap gdt and enter protected mode
|
||||||
lgdt ap_gdtr
|
lgdt AP_V2P(ap_gdtr)
|
||||||
movl %cr0, %eax
|
movl %cr0, %eax
|
||||||
orb $1, %al
|
orb $1, %al
|
||||||
movl %eax, %cr0
|
movl %eax, %cr0
|
||||||
ljmpl $0x08, $ap_protected_mode
|
ljmpl $0x08, $AP_V2P(ap_protected_mode)
|
||||||
|
|
||||||
.code32
|
.code32
|
||||||
ap_protected_mode:
|
ap_protected_mode:
|
||||||
|
@ -263,16 +268,15 @@ ap_protected_mode:
|
||||||
movw %ax, %ss
|
movw %ax, %ss
|
||||||
movw %ax, %es
|
movw %ax, %es
|
||||||
|
|
||||||
movl ap_stack_ptr, %esp
|
movl AP_V2P(ap_stack_ptr), %esp
|
||||||
movb $1, V2P(g_ap_stack_loaded)
|
movb $1, AP_V2P(ap_stack_loaded)
|
||||||
|
|
||||||
call V2P(enable_sse)
|
leal V2P(enable_sse), %ecx; call *%ecx
|
||||||
|
leal V2P(initialize_paging), %ecx; call *%ecx
|
||||||
call V2P(initialize_paging)
|
|
||||||
|
|
||||||
# load boot gdt and enter long mode
|
# load boot gdt and enter long mode
|
||||||
lgdt V2P(boot_gdtr)
|
lgdt V2P(boot_gdtr)
|
||||||
ljmpl $0x08, $ap_flush_gdt
|
ljmpl $0x08, $AP_V2P(ap_flush_gdt)
|
||||||
|
|
||||||
ap_flush_gdt:
|
ap_flush_gdt:
|
||||||
# move stack pointer to higher half
|
# move stack pointer to higher half
|
||||||
|
|
|
@ -4,13 +4,6 @@ KERNEL_OFFSET = 0xC0000000;
|
||||||
|
|
||||||
SECTIONS
|
SECTIONS
|
||||||
{
|
{
|
||||||
. = 0xF000;
|
|
||||||
.ap_init ALIGN(4K) : AT(ADDR(.ap_init))
|
|
||||||
{
|
|
||||||
g_ap_init_addr = .;
|
|
||||||
*(.ap_init)
|
|
||||||
}
|
|
||||||
|
|
||||||
. = 0x00100000 + KERNEL_OFFSET;
|
. = 0x00100000 + KERNEL_OFFSET;
|
||||||
|
|
||||||
g_kernel_start = .;
|
g_kernel_start = .;
|
||||||
|
@ -28,15 +21,20 @@ SECTIONS
|
||||||
g_userspace_end = .;
|
g_userspace_end = .;
|
||||||
g_kernel_execute_end = .;
|
g_kernel_execute_end = .;
|
||||||
}
|
}
|
||||||
.rodata ALIGN(4K) : AT(ADDR(.rodata) - KERNEL_OFFSET)
|
.ap_init ALIGN(4K) : AT(ADDR(.ap_init))
|
||||||
{
|
{
|
||||||
*(.rodata.*)
|
g_ap_init_addr = .;
|
||||||
|
*(.ap_init)
|
||||||
}
|
}
|
||||||
.data ALIGN(4K) : AT(ADDR(.data) - KERNEL_OFFSET)
|
.data ALIGN(4K) : AT(ADDR(.data) - KERNEL_OFFSET)
|
||||||
{
|
{
|
||||||
g_kernel_writable_start = .;
|
g_kernel_writable_start = .;
|
||||||
*(.data)
|
*(.data)
|
||||||
}
|
}
|
||||||
|
.rodata ALIGN(4K) : AT(ADDR(.rodata) - KERNEL_OFFSET)
|
||||||
|
{
|
||||||
|
*(.rodata.*)
|
||||||
|
}
|
||||||
.bss ALIGN(4K) : AT(ADDR(.bss) - KERNEL_OFFSET)
|
.bss ALIGN(4K) : AT(ADDR(.bss) - KERNEL_OFFSET)
|
||||||
{
|
{
|
||||||
*(COMMON)
|
*(COMMON)
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
.section .userspace, "aw"
|
.section .userspace, "ax"
|
||||||
|
|
||||||
// stack contains
|
// stack contains
|
||||||
// return address
|
// return address
|
||||||
|
|
|
@ -108,9 +108,6 @@ g_ap_startup_done:
|
||||||
.global g_ap_running_count
|
.global g_ap_running_count
|
||||||
g_ap_running_count:
|
g_ap_running_count:
|
||||||
.byte 0
|
.byte 0
|
||||||
.global g_ap_stack_loaded
|
|
||||||
g_ap_stack_loaded:
|
|
||||||
.byte 0
|
|
||||||
|
|
||||||
.section .text
|
.section .text
|
||||||
|
|
||||||
|
@ -194,7 +191,6 @@ _start:
|
||||||
|
|
||||||
call check_requirements
|
call check_requirements
|
||||||
call enable_sse
|
call enable_sse
|
||||||
|
|
||||||
call initialize_paging
|
call initialize_paging
|
||||||
|
|
||||||
# flush gdt and jump to 64 bit
|
# flush gdt and jump to 64 bit
|
||||||
|
@ -237,26 +233,31 @@ system_halt:
|
||||||
jmp 1b
|
jmp 1b
|
||||||
|
|
||||||
|
|
||||||
|
#define AP_V2P(vaddr) ((vaddr) - ap_trampoline + 0xF000)
|
||||||
|
|
||||||
.section .ap_init, "ax"
|
.section .ap_init, "ax"
|
||||||
|
|
||||||
.code16
|
.code16
|
||||||
.global ap_trampoline
|
.global ap_trampoline
|
||||||
ap_trampoline:
|
ap_trampoline:
|
||||||
jmp 1f
|
jmp 1f
|
||||||
|
|
||||||
.align 8
|
.align 8
|
||||||
ap_stack_ptr:
|
ap_stack_ptr:
|
||||||
.skip 4
|
.skip 4
|
||||||
1:
|
ap_stack_loaded:
|
||||||
cli; cld
|
.skip 1
|
||||||
ljmpl $0x00, $ap_cs_clear
|
|
||||||
ap_cs_clear:
|
|
||||||
|
|
||||||
|
1: cli; cld
|
||||||
|
ljmpl $0x00, $AP_V2P(ap_cs_clear)
|
||||||
|
|
||||||
|
ap_cs_clear:
|
||||||
# load ap gdt and enter protected mode
|
# load ap gdt and enter protected mode
|
||||||
lgdt ap_gdtr
|
lgdt AP_V2P(ap_gdtr)
|
||||||
movl %cr0, %eax
|
movl %cr0, %eax
|
||||||
orb $1, %al
|
orb $1, %al
|
||||||
movl %eax, %cr0
|
movl %eax, %cr0
|
||||||
ljmpl $0x08, $ap_protected_mode
|
ljmpl $0x08, $AP_V2P(ap_protected_mode)
|
||||||
|
|
||||||
.code32
|
.code32
|
||||||
ap_protected_mode:
|
ap_protected_mode:
|
||||||
|
@ -265,16 +266,15 @@ ap_protected_mode:
|
||||||
movw %ax, %ss
|
movw %ax, %ss
|
||||||
movw %ax, %es
|
movw %ax, %es
|
||||||
|
|
||||||
movl ap_stack_ptr, %esp
|
movl AP_V2P(ap_stack_ptr), %esp
|
||||||
movb $1, V2P(g_ap_stack_loaded)
|
movb $1, AP_V2P(ap_stack_loaded)
|
||||||
|
|
||||||
call V2P(enable_sse)
|
leal V2P(enable_sse), %ecx; call *%ecx
|
||||||
|
leal V2P(initialize_paging), %ecx; call *%ecx
|
||||||
call V2P(initialize_paging)
|
|
||||||
|
|
||||||
# load boot gdt and enter long mode
|
# load boot gdt and enter long mode
|
||||||
lgdt V2P(boot_gdtr)
|
lgdt V2P(boot_gdtr)
|
||||||
ljmpl $0x08, $ap_long_mode
|
ljmpl $0x08, $AP_V2P(ap_long_mode)
|
||||||
|
|
||||||
.code64
|
.code64
|
||||||
ap_long_mode:
|
ap_long_mode:
|
||||||
|
@ -282,22 +282,20 @@ ap_long_mode:
|
||||||
movl %esp, %esp
|
movl %esp, %esp
|
||||||
addq $KERNEL_OFFSET, %rsp
|
addq $KERNEL_OFFSET, %rsp
|
||||||
|
|
||||||
# jump to higher half
|
|
||||||
movabsq $ap_higher_half, %rcx
|
|
||||||
jmp *%rcx
|
|
||||||
|
|
||||||
ap_higher_half:
|
|
||||||
# clear rbp for stacktrace
|
# clear rbp for stacktrace
|
||||||
xorq %rbp, %rbp
|
xorq %rbp, %rbp
|
||||||
|
|
||||||
|
xorb %al, %al
|
||||||
1: pause
|
1: pause
|
||||||
cmpb $0, g_ap_startup_done
|
cmpb %al, g_ap_startup_done
|
||||||
jz 1b
|
jz 1b
|
||||||
|
|
||||||
lock incb g_ap_running_count
|
lock incb g_ap_running_count
|
||||||
|
|
||||||
call ap_main
|
# jump to ap_main in higher half
|
||||||
jmp system_halt
|
movabsq $ap_main, %rcx
|
||||||
|
call *%rcx
|
||||||
|
jmp V2P(system_halt)
|
||||||
|
|
||||||
ap_gdt:
|
ap_gdt:
|
||||||
.quad 0x0000000000000000 # null descriptor
|
.quad 0x0000000000000000 # null descriptor
|
||||||
|
|
|
@ -4,13 +4,6 @@ KERNEL_OFFSET = 0xFFFFFFFF80000000;
|
||||||
|
|
||||||
SECTIONS
|
SECTIONS
|
||||||
{
|
{
|
||||||
. = 0xF000;
|
|
||||||
.ap_init ALIGN(4K) : AT(ADDR(.ap_init))
|
|
||||||
{
|
|
||||||
g_ap_init_addr = .;
|
|
||||||
*(.ap_init)
|
|
||||||
}
|
|
||||||
|
|
||||||
. = 0x00100000 + KERNEL_OFFSET;
|
. = 0x00100000 + KERNEL_OFFSET;
|
||||||
|
|
||||||
g_kernel_start = .;
|
g_kernel_start = .;
|
||||||
|
@ -28,15 +21,20 @@ SECTIONS
|
||||||
g_userspace_end = .;
|
g_userspace_end = .;
|
||||||
g_kernel_execute_end = .;
|
g_kernel_execute_end = .;
|
||||||
}
|
}
|
||||||
.rodata ALIGN(4K) : AT(ADDR(.rodata) - KERNEL_OFFSET)
|
.ap_init ALIGN(4K) : AT(ADDR(.ap_init))
|
||||||
{
|
{
|
||||||
*(.rodata.*)
|
g_ap_init_addr = .;
|
||||||
|
*(.ap_init)
|
||||||
}
|
}
|
||||||
.data ALIGN(4K) : AT(ADDR(.data) - KERNEL_OFFSET)
|
.data ALIGN(4K) : AT(ADDR(.data) - KERNEL_OFFSET)
|
||||||
{
|
{
|
||||||
g_kernel_writable_start = .;
|
g_kernel_writable_start = .;
|
||||||
*(.data)
|
*(.data)
|
||||||
}
|
}
|
||||||
|
.rodata ALIGN(4K) : AT(ADDR(.rodata) - KERNEL_OFFSET)
|
||||||
|
{
|
||||||
|
*(.rodata.*)
|
||||||
|
}
|
||||||
.bss ALIGN(4K) : AT(ADDR(.bss) - KERNEL_OFFSET)
|
.bss ALIGN(4K) : AT(ADDR(.bss) - KERNEL_OFFSET)
|
||||||
{
|
{
|
||||||
*(COMMON)
|
*(COMMON)
|
||||||
|
|
|
@ -31,7 +31,6 @@ extern uint8_t g_ap_init_addr[];
|
||||||
|
|
||||||
extern volatile uint8_t g_ap_startup_done[];
|
extern volatile uint8_t g_ap_startup_done[];
|
||||||
extern volatile uint8_t g_ap_running_count[];
|
extern volatile uint8_t g_ap_running_count[];
|
||||||
extern volatile uint8_t g_ap_stack_loaded[];
|
|
||||||
|
|
||||||
namespace Kernel
|
namespace Kernel
|
||||||
{
|
{
|
||||||
|
@ -261,8 +260,6 @@ namespace Kernel
|
||||||
__builtin_ia32_pause();
|
__builtin_ia32_pause();
|
||||||
};
|
};
|
||||||
|
|
||||||
const size_t ap_init_page = reinterpret_cast<vaddr_t>(g_ap_init_addr) / PAGE_SIZE;
|
|
||||||
|
|
||||||
dprintln("System has {} processors", m_processors.size());
|
dprintln("System has {} processors", m_processors.size());
|
||||||
|
|
||||||
uint8_t bsp_id = Kernel::Processor::current_id().as_u32();
|
uint8_t bsp_id = Kernel::Processor::current_id().as_u32();
|
||||||
|
@ -275,6 +272,11 @@ namespace Kernel
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
constexpr paddr_t ap_init_paddr = 0xF000;
|
||||||
|
PageTable::with_fast_page(ap_init_paddr, [&] {
|
||||||
|
memcpy(PageTable::fast_page_as_ptr(), g_ap_init_addr, PAGE_SIZE);
|
||||||
|
});
|
||||||
|
|
||||||
for (auto& processor : m_processors)
|
for (auto& processor : m_processors)
|
||||||
{
|
{
|
||||||
if (processor.apic_id == bsp_id)
|
if (processor.apic_id == bsp_id)
|
||||||
|
@ -289,10 +291,10 @@ namespace Kernel
|
||||||
dprintln("Trying to enable processor (lapic id {})", processor.apic_id);
|
dprintln("Trying to enable processor (lapic id {})", processor.apic_id);
|
||||||
|
|
||||||
auto& proc = Kernel::Processor::create(ProcessorID(processor.apic_id));
|
auto& proc = Kernel::Processor::create(ProcessorID(processor.apic_id));
|
||||||
PageTable::with_fast_page((paddr_t)g_ap_init_addr, [&] {
|
PageTable::with_fast_page(ap_init_paddr, [&] {
|
||||||
PageTable::fast_page_as_sized<uint32_t>(2) = V2P(proc.stack_top());
|
PageTable::fast_page_as_sized<uint32_t>(2) = kmalloc_paddr_of(proc.stack_top()).value();
|
||||||
|
PageTable::fast_page_as_sized<uint8_t>(13) = 0;
|
||||||
});
|
});
|
||||||
*g_ap_stack_loaded = 0;
|
|
||||||
|
|
||||||
write_to_local_apic(LAPIC_ERROR_REG, 0x00);
|
write_to_local_apic(LAPIC_ERROR_REG, 0x00);
|
||||||
|
|
||||||
|
@ -323,18 +325,20 @@ namespace Kernel
|
||||||
| ICR_LO_level_assert
|
| ICR_LO_level_assert
|
||||||
| ICR_LO_trigger_mode_edge
|
| ICR_LO_trigger_mode_edge
|
||||||
| ICR_LO_destination_shorthand_none
|
| ICR_LO_destination_shorthand_none
|
||||||
| ap_init_page
|
| (ap_init_paddr / PAGE_SIZE)
|
||||||
, 200
|
, 200
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// give processor upto 100 * 100 us + 200 us to boot
|
// give processor upto 100 * 100 us + 200 us to boot
|
||||||
for (int i = 0; i < 100; i++)
|
PageTable::with_fast_page(ap_init_paddr, [&] {
|
||||||
{
|
for (int i = 0; i < 100; i++)
|
||||||
if (__atomic_load_n(&g_ap_stack_loaded[0], __ATOMIC_SEQ_CST))
|
{
|
||||||
break;
|
if (__atomic_load_n(&PageTable::fast_page_as_sized<uint8_t>(13), __ATOMIC_SEQ_CST))
|
||||||
udelay(100);
|
break;
|
||||||
}
|
udelay(100);
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
__atomic_store_n(&g_ap_startup_done[0], 1, __ATOMIC_SEQ_CST);
|
__atomic_store_n(&g_ap_startup_done[0], 1, __ATOMIC_SEQ_CST);
|
||||||
|
|
Loading…
Reference in New Issue