misc: Converge with 5.x

This commit is contained in:
mintsuki 2023-09-22 17:51:07 -05:00
parent d9f8ce2b6f
commit f9682543fd
12 changed files with 90 additions and 215 deletions

View File

@ -21,10 +21,6 @@ way to modify its own EFI executable to bake in the BLAKE2B checksum of the conf
a key added to the firmware's keychain. This prevents modifications to the config file (and in turn the checksums contained there) a key added to the firmware's keychain. This prevents modifications to the config file (and in turn the checksums contained there)
from going unnoticed. from going unnoticed.
### What about ext2/3/4? Why is that supported then?
Simply put, legacy. And because a lot of Linux users expect it to "work that way". ext2/3/4 support has been dropped as of Limine 6.x.
### But I don't want to have a separate FAT boot partition! I don't want it!!! ### But I don't want to have a separate FAT boot partition! I don't want it!!!
Well tough luck. It is `$year_following_2012` now and most PCs are equipped with UEFI and simply won't boot without a FAT EFI system partition Well tough luck. It is `$year_following_2012` now and most PCs are equipped with UEFI and simply won't boot without a FAT EFI system partition

View File

@ -87,7 +87,7 @@ The protocol mandates kernels to load themselves at or above
`0xffffffff80000000`. Lower half kernels are *not supported*. `0xffffffff80000000`. Lower half kernels are *not supported*.
At handoff, the kernel will be properly loaded and mapped with appropriate At handoff, the kernel will be properly loaded and mapped with appropriate
MMU permissions at the requested virtual memory address (provided it is at MMU permissions, as supervisor, at the requested virtual memory address (provided it is at
or above `0xffffffff80000000`). or above `0xffffffff80000000`).
No specific physical memory placement is guaranteed, except that the kernel No specific physical memory placement is guaranteed, except that the kernel
@ -95,12 +95,14 @@ is guaranteed to be physically contiguous. In order to determine
where the kernel is loaded in physical memory, see the Kernel Address feature where the kernel is loaded in physical memory, see the Kernel Address feature
below. below.
Alongside the loaded kernel, the bootloader will set up memory mappings such Alongside the loaded kernel, the bootloader will set up memory mappings as such:
that every usable, bootloader reclaimable, framebuffer, or kernel/modules ```
memory map region is mapped at HHDM offset + its physical address. Base Physical Address | | Base Virtual Address
Additionally, the whole 0->4GiB physical memory region will also be mapped 0x0000000000001000 | (4 GiB - 0x1000) and any additional memory map region | 0x0000000000001000
at HHDM offset + physical address, regardless of the contents of the 0x0000000000000000 | 4 GiB and any additional memory map region | HHDM start
memory map. These mappings are supervisor, read, write, execute (-rwx). ```
Where "HHDM start" is returned by the Higher Half Direct Map feature (see below).
These mappings are supervisor, read, write, execute (-rwx).
The bootloader page tables are in bootloader-reclaimable memory (see Memory Map The bootloader page tables are in bootloader-reclaimable memory (see Memory Map
feature below), and their specific layout is undefined as long as they provide feature below), and their specific layout is undefined as long as they provide
@ -117,7 +119,7 @@ config).
The kernel executable, loaded at or above `0xffffffff80000000`, sees all of its The kernel executable, loaded at or above `0xffffffff80000000`, sees all of its
segments mapped using write-back (WB) caching at the page tables level. segments mapped using write-back (WB) caching at the page tables level.
All HHDM memory regions are mapped using write-back (WB) caching at the page All HHDM and identity map memory regions are mapped using write-back (WB) caching at the page
tables level, except framebuffer regions which are mapped using write-combining tables level, except framebuffer regions which are mapped using write-combining
(WC) caching at the page tables level. (WC) caching at the page tables level.
@ -140,7 +142,7 @@ The MTRRs are left as the firmware set them up.
The kernel executable, loaded at or above `0xffffffff80000000`, sees all of its The kernel executable, loaded at or above `0xffffffff80000000`, sees all of its
segments mapped using Normal Write-Back RW-Allocate non-transient caching mode. segments mapped using Normal Write-Back RW-Allocate non-transient caching mode.
All HHDM memory regions are mapped using the Normal Write-Back RW-Allocate All HHDM and identity map memory regions are mapped using the Normal Write-Back RW-Allocate
non-transient caching mode, except for the framebuffer regions, which are non-transient caching mode, except for the framebuffer regions, which are
mapped in using an unspecified caching mode, correct for use with the mapped in using an unspecified caching mode, correct for use with the
framebuffer on the platform. framebuffer on the platform.
@ -155,7 +157,7 @@ is used on its own.
If the `Svpbmt` extension is available, all framebuffer memory regions are mapped If the `Svpbmt` extension is available, all framebuffer memory regions are mapped
with `PBMT=NC` to enable write-combining optimizations. The kernel executable, with `PBMT=NC` to enable write-combining optimizations. The kernel executable,
loaded at or above `0xffffffff80000000`, and all HHDM memory regions are mapped loaded at or above `0xffffffff80000000`, and all HHDM and identity map memory regions are mapped
with the default `PBMT=PMA`. with the default `PBMT=PMA`.
If the `Svpbmt` extension is not available, no PMAs can be overridden (effectively, If the `Svpbmt` extension is not available, no PMAs can be overridden (effectively,

View File

@ -99,7 +99,7 @@ noreturn void enter_in_el1(uint64_t entry, uint64_t sp, uint64_t sctlr,
uint64_t mair, uint64_t tcr, uint64_t ttbr0, uint64_t mair, uint64_t tcr, uint64_t ttbr0,
uint64_t ttbr1, uint64_t target_x0); uint64_t ttbr1, uint64_t target_x0);
#elif defined (__riscv64) #elif defined (__riscv64)
noreturn void riscv_spinup(uint64_t entry, uint64_t sp, uint64_t satp, uint64_t direct_map_offset); noreturn void riscv_spinup(uint64_t entry, uint64_t sp, uint64_t satp);
#if defined (UEFI) #if defined (UEFI)
RISCV_EFI_BOOT_PROTOCOL *get_riscv_boot_protocol(void); RISCV_EFI_BOOT_PROTOCOL *get_riscv_boot_protocol(void);
#endif #endif

View File

@ -4,7 +4,7 @@
// noreturn void enter_in_el1(uint64_t entry, uint64_t sp, uint64_t sctlr, // noreturn void enter_in_el1(uint64_t entry, uint64_t sp, uint64_t sctlr,
// uint64_t mair, uint64_t tcr, uint64_t ttbr0, // uint64_t mair, uint64_t tcr, uint64_t ttbr0,
// uint64_t ttbr1, uint64_t direct_map_offset) // uint64_t ttbr1, uint64_t target_x0)
// Potentially drop to EL1 from EL2 (and also disable trapping to EL2), then // Potentially drop to EL1 from EL2 (and also disable trapping to EL2), then
// configure EL1 state and jump to kernel. // configure EL1 state and jump to kernel.
@ -13,50 +13,6 @@ enter_in_el1:
msr spsel, #0 msr spsel, #0
mov sp, x1 mov sp, x1
PICK_EL x8, 0f, 2f
0:
// Switch to the new page tables
// Point the EL1t handler to the continuation, such that after we page fault,
// execution continues and the kernel is entered.
adrp x8, 1f
add x8, x8, #:lo12:1f
add x8, x8, x7
msr vbar_el1, x8
isb
dsb sy
isb
// Switch the page table registers
msr mair_el1, x3
msr tcr_el1, x4
msr ttbr0_el1, x5
msr ttbr1_el1, x6
msr sctlr_el1, x2
isb
dsb sy
isb
// Jump to the higher half mapping in case we didn't immediately crash
br x8
// Alignment required by VBAR register
.align 11
1:
// Zero out VBAR to avoid confusion
msr vbar_el1, xzr
// Enter kernel in EL1
mov x8, #0x3c4
msr spsr_el1, x8
msr elr_el1, x0
mov x0, xzr
ZERO_REGS_EXCEPT_X0
eret
2:
// Configure EL1 state // Configure EL1 state
msr mair_el1, x3 msr mair_el1, x3
msr tcr_el1, x4 msr tcr_el1, x4
@ -66,6 +22,19 @@ enter_in_el1:
dsb sy dsb sy
isb isb
PICK_EL x8, 0f, 1f
0:
// Enter kernel in EL1
mov x8, #0x3c4
msr spsr_el1, x8
msr elr_el1, x0
mov x0, x7
ZERO_REGS_EXCEPT_X0
eret
1:
// Configure EL2-specific state for EL1 // Configure EL2-specific state for EL1
// Don't trap counters to EL2 // Don't trap counters to EL2
@ -88,7 +57,7 @@ enter_in_el1:
msr spsr_el2, x8 msr spsr_el2, x8
msr elr_el2, x0 msr elr_el2, x0
mov x0, xzr mov x0, x7
ZERO_REGS_EXCEPT_X0 ZERO_REGS_EXCEPT_X0
eret eret

View File

@ -6,19 +6,11 @@ riscv_spinup:
.option norelax .option norelax
csrci sstatus, 0x2 csrci sstatus, 0x2
csrw sie, zero csrw sie, zero
lla t0, 0f
add t0, t0, a3
csrw stvec, t0
csrw satp, a2
sfence.vma
unimp
.align 4
0:
csrw stvec, zero csrw stvec, zero
mv t0, a0 mv t0, a0
mv sp, a1 mv sp, a1
csrw satp, a2
mv a0, zero mv a0, zero
mv a1, zero mv a1, zero

View File

@ -63,8 +63,33 @@ static pagemap_t build_pagemap(int paging_mode, bool nx, struct elf_range *range
} }
} }
// Map 0->4GiB range to HHDM // Sub 2MiB mappings
for (uint64_t i = 0; i < 0x100000000; i += 0x40000000) { for (uint64_t i = 0; i < 0x200000; i += 0x1000) {
if (i != 0) {
map_page(pagemap, i, i, VMM_FLAG_WRITE, Size4KiB);
}
map_page(pagemap, direct_map_offset + i, i, VMM_FLAG_WRITE, Size4KiB);
}
// Map 2MiB to 4GiB at higher half base and 0
//
// NOTE: We cannot just directly map from 2MiB to 4GiB with 1GiB
// pages because if you do the math.
//
// start = 0x200000
// end = 0x40000000
//
// pages_required = (end - start) / (4096 * 512 * 512)
//
// So we map 2MiB to 1GiB with 2MiB pages and then map the rest
// with 1GiB pages :^)
for (uint64_t i = 0x200000; i < 0x40000000; i += 0x200000) {
map_page(pagemap, i, i, VMM_FLAG_WRITE, Size2MiB);
map_page(pagemap, direct_map_offset + i, i, VMM_FLAG_WRITE, Size2MiB);
}
for (uint64_t i = 0x40000000; i < 0x100000000; i += 0x40000000) {
map_page(pagemap, i, i, VMM_FLAG_WRITE, Size1GiB);
map_page(pagemap, direct_map_offset + i, i, VMM_FLAG_WRITE, Size1GiB); map_page(pagemap, direct_map_offset + i, i, VMM_FLAG_WRITE, Size1GiB);
} }
@ -74,14 +99,8 @@ static pagemap_t build_pagemap(int paging_mode, bool nx, struct elf_range *range
for (size_t i = 0; i < _memmap_entries; i++) for (size_t i = 0; i < _memmap_entries; i++)
_memmap[i] = memmap[i]; _memmap[i] = memmap[i];
// Map all free memory regions to the higher half direct map offset // Map any other region of memory from the memmap
for (size_t i = 0; i < _memmap_entries; i++) { for (size_t i = 0; i < _memmap_entries; i++) {
if (_memmap[i].type != MEMMAP_USABLE
&& _memmap[i].type != MEMMAP_BOOTLOADER_RECLAIMABLE
&& _memmap[i].type != MEMMAP_KERNEL_AND_MODULES) {
continue;
}
uint64_t base = _memmap[i].base; uint64_t base = _memmap[i].base;
uint64_t length = _memmap[i].length; uint64_t length = _memmap[i].length;
uint64_t top = base + length; uint64_t top = base + length;
@ -100,6 +119,7 @@ static pagemap_t build_pagemap(int paging_mode, bool nx, struct elf_range *range
for (uint64_t j = 0; j < aligned_length; j += 0x40000000) { for (uint64_t j = 0; j < aligned_length; j += 0x40000000) {
uint64_t page = aligned_base + j; uint64_t page = aligned_base + j;
map_page(pagemap, page, page, VMM_FLAG_WRITE, Size1GiB);
map_page(pagemap, direct_map_offset + page, page, VMM_FLAG_WRITE, Size1GiB); map_page(pagemap, direct_map_offset + page, page, VMM_FLAG_WRITE, Size1GiB);
} }
} }
@ -120,17 +140,11 @@ static pagemap_t build_pagemap(int paging_mode, bool nx, struct elf_range *range
for (uint64_t j = 0; j < aligned_length; j += 0x1000) { for (uint64_t j = 0; j < aligned_length; j += 0x1000) {
uint64_t page = aligned_base + j; uint64_t page = aligned_base + j;
map_page(pagemap, page, page, VMM_FLAG_WRITE | VMM_FLAG_FB, Size4KiB);
map_page(pagemap, direct_map_offset + page, page, VMM_FLAG_WRITE | VMM_FLAG_FB, Size4KiB); map_page(pagemap, direct_map_offset + page, page, VMM_FLAG_WRITE | VMM_FLAG_FB, Size4KiB);
} }
} }
// XXX we do this as a quick and dirty way to switch to the higher half
#if defined (__x86_64__) || defined (__i386__)
for (uint64_t i = 0; i < 0x100000000; i += 0x40000000) {
map_page(pagemap, i, i, VMM_FLAG_WRITE, Size1GiB);
}
#endif
return pagemap; return pagemap;
} }
@ -944,10 +958,9 @@ FEAT_START
uint64_t bsp_mpidr; uint64_t bsp_mpidr;
smp_info = init_smp(&cpu_count, &bsp_mpidr, smp_info = init_smp(&cpu_count, &bsp_mpidr,
pagemap, LIMINE_MAIR(fb_attr), LIMINE_TCR(tsz, pa), LIMINE_SCTLR, pagemap, LIMINE_MAIR(fb_attr), LIMINE_TCR(tsz, pa), LIMINE_SCTLR);
direct_map_offset);
#elif defined (__riscv64) #elif defined (__riscv64)
smp_info = init_smp(&cpu_count, pagemap, direct_map_offset); smp_info = init_smp(&cpu_count, pagemap);
#else #else
#error Unknown architecture #error Unknown architecture
#endif #endif
@ -1081,12 +1094,11 @@ FEAT_END
uint64_t reported_stack = reported_addr(stack); uint64_t reported_stack = reported_addr(stack);
common_spinup(limine_spinup_32, 10, common_spinup(limine_spinup_32, 8,
paging_mode, (uint32_t)(uintptr_t)pagemap.top_level, paging_mode, (uint32_t)(uintptr_t)pagemap.top_level,
(uint32_t)entry_point, (uint32_t)(entry_point >> 32), (uint32_t)entry_point, (uint32_t)(entry_point >> 32),
(uint32_t)reported_stack, (uint32_t)(reported_stack >> 32), (uint32_t)reported_stack, (uint32_t)(reported_stack >> 32),
(uint32_t)(uintptr_t)local_gdt, nx_available, (uint32_t)(uintptr_t)local_gdt, nx_available);
(uint32_t)direct_map_offset, (uint32_t)(direct_map_offset >> 32));
#elif defined (__aarch64__) #elif defined (__aarch64__)
vmm_assert_4k_pages(); vmm_assert_4k_pages();
@ -1094,13 +1106,12 @@ FEAT_END
enter_in_el1(entry_point, reported_stack, LIMINE_SCTLR, LIMINE_MAIR(fb_attr), LIMINE_TCR(tsz, pa), enter_in_el1(entry_point, reported_stack, LIMINE_SCTLR, LIMINE_MAIR(fb_attr), LIMINE_TCR(tsz, pa),
(uint64_t)pagemap.top_level[0], (uint64_t)pagemap.top_level[0],
(uint64_t)pagemap.top_level[1], (uint64_t)pagemap.top_level[1], 0);
direct_map_offset);
#elif defined (__riscv64) #elif defined (__riscv64)
uint64_t reported_stack = reported_addr(stack); uint64_t reported_stack = reported_addr(stack);
uint64_t satp = make_satp(pagemap.paging_mode, pagemap.top_level); uint64_t satp = make_satp(pagemap.paging_mode, pagemap.top_level);
riscv_spinup(entry_point, reported_stack, satp, direct_map_offset); riscv_spinup(entry_point, reported_stack, satp);
#else #else
#error Unknown architecture #error Unknown architecture
#endif #endif

View File

@ -67,24 +67,6 @@ bits 64
mov eax, [rsp+28] ; local_gdt mov eax, [rsp+28] ; local_gdt
lgdt [rax] lgdt [rax]
; Jump to higher half
mov rax, qword [rsp+36]
add rsp, rax
call .p2
.p2:
add qword [rsp], .hh - .p2
add qword [rsp], rax
retq
.hh:
; Unmap lower half entirely
mov rsi, cr3
lea rdi, [rsi + rax]
mov rcx, 256
xor rax, rax
rep stosq
mov cr3, rsi
; Push fake return address ; Push fake return address
mov rsi, [rsp+20] ; stack mov rsi, [rsp+20] ; stack
sub rsi, 8 sub rsi, 8

View File

@ -259,8 +259,6 @@ struct limine_smp_info *init_smp(size_t *cpu_count,
struct trampoline_passed_info { struct trampoline_passed_info {
uint64_t smp_tpl_booted_flag; uint64_t smp_tpl_booted_flag;
uint64_t smp_tpl_hhdm_offset;
uint64_t smp_tpl_ttbr0; uint64_t smp_tpl_ttbr0;
uint64_t smp_tpl_ttbr1; uint64_t smp_tpl_ttbr1;
@ -283,8 +281,7 @@ static uint32_t psci_cpu_on = 0xC4000003;
static bool try_start_ap(int boot_method, uint64_t method_ptr, static bool try_start_ap(int boot_method, uint64_t method_ptr,
struct limine_smp_info *info_struct, struct limine_smp_info *info_struct,
uint64_t ttbr0, uint64_t ttbr1, uint64_t mair, uint64_t ttbr0, uint64_t ttbr1, uint64_t mair,
uint64_t tcr, uint64_t sctlr, uint64_t tcr, uint64_t sctlr) {
uint64_t hhdm_offset) {
// Prepare the trampoline // Prepare the trampoline
static void *trampoline = NULL; static void *trampoline = NULL;
if (trampoline == NULL) { if (trampoline == NULL) {
@ -306,7 +303,6 @@ static bool try_start_ap(int boot_method, uint64_t method_ptr,
passed_info->smp_tpl_mair = mair; passed_info->smp_tpl_mair = mair;
passed_info->smp_tpl_tcr = tcr; passed_info->smp_tpl_tcr = tcr;
passed_info->smp_tpl_sctlr = sctlr; passed_info->smp_tpl_sctlr = sctlr;
passed_info->smp_tpl_hhdm_offset = hhdm_offset;
// Cache coherency between the I-Cache and D-Cache is not guaranteed by the // Cache coherency between the I-Cache and D-Cache is not guaranteed by the
// architecture and as such we must perform I-Cache invalidation. // architecture and as such we must perform I-Cache invalidation.
@ -390,8 +386,7 @@ static struct limine_smp_info *try_acpi_smp(size_t *cpu_count,
pagemap_t pagemap, pagemap_t pagemap,
uint64_t mair, uint64_t mair,
uint64_t tcr, uint64_t tcr,
uint64_t sctlr, uint64_t sctlr) {
uint64_t hhdm_offset) {
int boot_method = BOOT_WITH_ACPI_PARK; int boot_method = BOOT_WITH_ACPI_PARK;
// Search for FADT table // Search for FADT table
@ -479,7 +474,7 @@ static struct limine_smp_info *try_acpi_smp(size_t *cpu_count,
if (!try_start_ap(boot_method, gicc->parking_addr, info_struct, if (!try_start_ap(boot_method, gicc->parking_addr, info_struct,
(uint64_t)(uintptr_t)pagemap.top_level[0], (uint64_t)(uintptr_t)pagemap.top_level[0],
(uint64_t)(uintptr_t)pagemap.top_level[1], (uint64_t)(uintptr_t)pagemap.top_level[1],
mair, tcr, sctlr, hhdm_offset)) { mair, tcr, sctlr)) {
print("smp: FAILED to bring-up AP\n"); print("smp: FAILED to bring-up AP\n");
continue; continue;
} }
@ -500,18 +495,16 @@ struct limine_smp_info *init_smp(size_t *cpu_count,
pagemap_t pagemap, pagemap_t pagemap,
uint64_t mair, uint64_t mair,
uint64_t tcr, uint64_t tcr,
uint64_t sctlr, uint64_t sctlr) {
uint64_t hhdm_offset) {
struct limine_smp_info *info = NULL; struct limine_smp_info *info = NULL;
//if (dtb_is_present() && (info = try_dtb_smp(cpu_count, //if (dtb_is_present() && (info = try_dtb_smp(cpu_count,
// _bsp_iface_no, pagemap, mair, tcr, sctlr, hhdm_offset))) // _bsp_iface_no, pagemap, mair, tcr, sctlr)))
// return info; // return info;
// No RSDP means no ACPI // No RSDP means no ACPI
if (acpi_get_rsdp() && (info = try_acpi_smp( if (acpi_get_rsdp() && (info = try_acpi_smp(cpu_count,
cpu_count, bsp_mpidr, pagemap, bsp_mpidr, pagemap, mair, tcr, sctlr)))
mair, tcr, sctlr, hhdm_offset)))
return info; return info;
printv("Failed to figure out how to start APs."); printv("Failed to figure out how to start APs.");
@ -525,17 +518,14 @@ struct trampoline_passed_info {
uint64_t smp_tpl_booted_flag; uint64_t smp_tpl_booted_flag;
uint64_t smp_tpl_satp; uint64_t smp_tpl_satp;
uint64_t smp_tpl_info_struct; uint64_t smp_tpl_info_struct;
uint64_t smp_tpl_hhdm_offset;
}; };
static bool smp_start_ap(size_t hartid, size_t satp, struct limine_smp_info *info_struct, static bool smp_start_ap(size_t hartid, size_t satp, struct limine_smp_info *info_struct) {
uint64_t hhdm_offset) {
static struct trampoline_passed_info passed_info; static struct trampoline_passed_info passed_info;
passed_info.smp_tpl_booted_flag = 0; passed_info.smp_tpl_booted_flag = 0;
passed_info.smp_tpl_satp = satp; passed_info.smp_tpl_satp = satp;
passed_info.smp_tpl_info_struct = (uint64_t)info_struct; passed_info.smp_tpl_info_struct = (uint64_t)info_struct;
passed_info.smp_tpl_hhdm_offset = hhdm_offset;
asm volatile ("" ::: "memory"); asm volatile ("" ::: "memory");
@ -551,7 +541,7 @@ static bool smp_start_ap(size_t hartid, size_t satp, struct limine_smp_info *inf
return false; return false;
} }
struct limine_smp_info *init_smp(size_t *cpu_count, pagemap_t pagemap, uint64_t hhdm_offset) { struct limine_smp_info *init_smp(size_t *cpu_count, pagemap_t pagemap) {
size_t num_cpus = 0; size_t num_cpus = 0;
for (struct riscv_hart *hart = hart_list; hart != NULL; hart = hart->next) { for (struct riscv_hart *hart = hart_list; hart != NULL; hart = hart->next) {
if (!(hart->flags & RISCV_HART_COPROC)) { if (!(hart->flags & RISCV_HART_COPROC)) {
@ -584,7 +574,7 @@ struct limine_smp_info *init_smp(size_t *cpu_count, pagemap_t pagemap, uint64_t
// Try to start the AP. // Try to start the AP.
size_t satp = make_satp(pagemap.paging_mode, pagemap.top_level); size_t satp = make_satp(pagemap.paging_mode, pagemap.top_level);
if (!smp_start_ap(hart->hartid, satp, info_struct, hhdm_offset)) { if (!smp_start_ap(hart->hartid, satp, info_struct)) {
print("smp: FAILED to bring-up AP\n"); print("smp: FAILED to bring-up AP\n");
continue; continue;
} }

View File

@ -27,14 +27,12 @@ struct limine_smp_info *init_smp(size_t *cpu_count,
pagemap_t pagemap, pagemap_t pagemap,
uint64_t mair, uint64_t mair,
uint64_t tcr, uint64_t tcr,
uint64_t sctlr, uint64_t sctlr);
uint64_t hhdm_offset);
#elif defined (__riscv64) #elif defined (__riscv64)
struct limine_smp_info *init_smp(size_t *cpu_count, struct limine_smp_info *init_smp(size_t *cpu_count,
pagemap_t pagemap, pagemap_t pagemap);
uint64_t hhdm_offset);
#else #else
#error Unknown architecture #error Unknown architecture

View File

@ -1,7 +1,6 @@
#include <lib/macros.aarch64_asm.h> #include <lib/macros.aarch64_asm.h>
.set tpl_booted_flag, -64 .set tpl_booted_flag, -56
.set tpl_hhdm_offset, -56
.set tpl_ttbr0, -48 .set tpl_ttbr0, -48
.set tpl_ttbr1, -40 .set tpl_ttbr1, -40
.set tpl_mair, -32 .set tpl_mair, -32
@ -27,22 +26,20 @@ smp_trampoline_start:
ldr x4, [x1, tpl_tcr] ldr x4, [x1, tpl_tcr]
ldr x5, [x1, tpl_ttbr0] ldr x5, [x1, tpl_ttbr0]
ldr x6, [x1, tpl_ttbr1] ldr x6, [x1, tpl_ttbr1]
ldr x7, [x1, tpl_hhdm_offset]
PICK_EL x8, 1f, 0f // Configure EL1 state
0:
// Configure EL2-specific state for EL1
// Configure EL1 page tables
msr mair_el1, x3 msr mair_el1, x3
msr tcr_el1, x4 msr tcr_el1, x4
msr ttbr0_el1, x5 msr ttbr0_el1, x5
msr ttbr1_el1, x6 msr ttbr1_el1, x6
msr sctlr_el1, x2 msr sctlr_el1, x2
isb
dsb sy dsb sy
isb isb
PICK_EL x8, 1f, 0f
0:
// Configure EL2-specific state for EL1
// Don't trap counters to EL2 // Don't trap counters to EL2
mrs x8, cnthctl_el2 mrs x8, cnthctl_el2
orr x8, x8, #3 orr x8, x8, #3
@ -63,67 +60,26 @@ smp_trampoline_start:
// Run rest of trampoline in EL1 // Run rest of trampoline in EL1
mov x8, #0x3c4 mov x8, #0x3c4
msr spsr_el2, x8 msr spsr_el2, x8
adrp x8, 3f adr x8, 1f
add x8, x8, :lo12:2f
add x8, x8, x7 // Add HHDM offset
msr elr_el2, x8 msr elr_el2, x8
eret eret
1: 1:
msr spsel, #0
// Switch to the new page tables
// Point the EL1t handler to the continuation, such that after we page fault,
// execution continues as expected.
adrp x8, 2f
add x8, x8, #:lo12:2f
add x8, x8, x7
msr vbar_el1, x8
isb
dsb sy
isb
// Switch the page table registers
msr mair_el1, x3
msr tcr_el1, x4
msr ttbr0_el1, x5
msr ttbr1_el1, x6
msr sctlr_el1, x2
isb
dsb sy
isb
// Jump to the higher half mapping in case we didn't immediately crash
br x8
// Alignment required by VBAR register
.align 11
2:
// Zero out VBAR to avoid confusion
msr vbar_el1, xzr
3:
// Add HHDM offset to data pointer
add x1, x1, x7
// Notify BSP we are alive // Notify BSP we are alive
mov x8, #1 mov x8, #1
add x9, x1, tpl_booted_flag add x9, x1, tpl_booted_flag
stlr x8, [x9] stlr x8, [x9]
// Wait for BSP to tell us where to go // Wait for BSP to tell us where to go
// Add HHDM offset to our info struct pointer
add x0, x0, x7
add x9, x0, #24 add x9, x0, #24
4: 2:
ldar x8, [x9] ldar x8, [x9]
cbnz x8, 5f cbnz x8, 3f
yield yield
b 4b b 2b
5: 3:
msr elr_el1, x8 msr elr_el1, x8
msr spsel, #0 msr spsel, #0

View File

@ -11,26 +11,9 @@ smp_trampoline_start:
// //
// All other registers are undefined. // All other registers are undefined.
#define smp_tpl_booted_flag 0 ld a0, 16(a1)
#define smp_tpl_satp 8 ld t0, 8(a1)
#define smp_tpl_info_struct 16
#define smp_tpl_hhdm_offset 24
ld a0, smp_tpl_info_struct(a1)
ld t1, smp_tpl_hhdm_offset(a1)
// Set `stvec` so we page fault into the higher half after loading `satp`.
lla t0, 0f
add t0, t1, t0
csrw stvec, t0
ld t0, smp_tpl_satp(a1)
csrw satp, t0 csrw satp, t0
sfence.vma
unimp
0:
// Relocate the smp_info and passed_info pointers to the higher half.
add a0, t1, a0
add a1, t1, a1
// Tell the BSP we've started. // Tell the BSP we've started.
li t0, 1 li t0, 1

View File

@ -168,10 +168,6 @@ parking64:
jmp .loop jmp .loop
.out: .out:
; Clear TLB
mov rbx, cr3
mov cr3, rbx
mov rsp, qword [rdi + 8] mov rsp, qword [rdi + 8]
push 0 push 0
push rax push rax