:: commit 56cdc669bf6ef8eff4bd3d0f8be23d8158bb602e

xvanc <xvancm@gmail.com> — 2023-08-02 20:20

parents: 46d3dcd600

limine/riscv: remove dependency on lower half identity map

diff --git a/common/lib/misc.h b/common/lib/misc.h
index ae0ccb51..57df7071 100644
--- a/common/lib/misc.h
+++ b/common/lib/misc.h
@@ -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 ttbr1, uint64_t target_x0);
 #elif defined (__riscv64)
-noreturn void riscv_spinup(uint64_t entry, uint64_t sp, uint64_t satp);
+noreturn void riscv_spinup(uint64_t entry, uint64_t sp, uint64_t satp, uint64_t direct_map_offset);
 #if defined (UEFI)
 RISCV_EFI_BOOT_PROTOCOL *get_riscv_boot_protocol(void);
 #endif
diff --git a/common/lib/spinup.asm_riscv64 b/common/lib/spinup.asm_riscv64
index e0e69c6a..7c27ba82 100644
--- a/common/lib/spinup.asm_riscv64
+++ b/common/lib/spinup.asm_riscv64
@@ -6,11 +6,18 @@ riscv_spinup:
 .option norelax
         csrci   sstatus, 0x2
         csrw    sie, zero
+
+        lla     t0, 0f
+        add     t0, t0, a3
+        csrw    stvec, t0
+        csrw    satp, a2
+        unimp
+.align 4
+0:
         csrw    stvec, zero
 
         mv      t0, a0
         mv      sp, a1
-        csrw    satp, a2
 
         mv      a0, zero
         mv      a1, zero
diff --git a/common/protos/limine.c b/common/protos/limine.c
index 6d046430..dd8ec18b 100644
--- a/common/protos/limine.c
+++ b/common/protos/limine.c
@@ -963,7 +963,7 @@ FEAT_START
         break;
     }
 
-    smp_info = init_smp(&cpu_count, bsp_hartid, pagemap);
+    smp_info = init_smp(&cpu_count, bsp_hartid, pagemap, direct_map_offset);
 #else
 #error Unknown architecture
 #endif
@@ -1106,7 +1106,7 @@ FEAT_END
     uint64_t reported_stack = reported_addr(stack);
     uint64_t satp = make_satp(pagemap.paging_mode, pagemap.top_level);
 
-    riscv_spinup(entry_point, reported_stack, satp);
+    riscv_spinup(entry_point, reported_stack, satp, direct_map_offset);
 #else
 #error Unknown architecture
 #endif
diff --git a/common/sys/smp.c b/common/sys/smp.c
index cbc8f9c7..98f9a620 100644
--- a/common/sys/smp.c
+++ b/common/sys/smp.c
@@ -582,14 +582,17 @@ struct trampoline_passed_info {
     uint64_t smp_tpl_booted_flag;
     uint64_t smp_tpl_satp;
     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;
 
     passed_info.smp_tpl_booted_flag = 0;
     passed_info.smp_tpl_satp        = satp;
     passed_info.smp_tpl_info_struct = (uint64_t)info_struct;
+    passed_info.smp_tpl_hhdm_offset = hhdm_offset;
 
     asm volatile ("" ::: "memory");
 
@@ -606,8 +609,9 @@ static bool smp_start_ap(size_t hartid, size_t satp, struct limine_smp_info *inf
 }
 
 struct limine_smp_info *init_smp(size_t   *cpu_count,
-                                 size_t   bsp_hartid,
-                                 pagemap_t pagemap) {
+                                 size_t    bsp_hartid,
+                                 pagemap_t pagemap,
+                                 uint64_t  hhdm_offset) {
     // No RSDP means no ACPI.
     // Parsing the Device Tree is the only other method for detecting APs.
     if (acpi_get_rsdp() == NULL) {
@@ -666,7 +670,7 @@ struct limine_smp_info *init_smp(size_t   *cpu_count,
 
                 // Try to start the AP.
                 size_t satp = make_satp(pagemap.paging_mode, pagemap.top_level);
-                if (!smp_start_ap(intc->hartid, satp, info_struct)) {
+                if (!smp_start_ap(intc->hartid, satp, info_struct, hhdm_offset)) {
                     print("smp: FAILED to bring-up AP\n");
                     continue;
                 }
diff --git a/common/sys/smp.h b/common/sys/smp.h
index a9eb6cac..bc82d6cd 100644
--- a/common/sys/smp.h
+++ b/common/sys/smp.h
@@ -33,8 +33,9 @@ struct limine_smp_info *init_smp(size_t   *cpu_count,
 #elif defined (__riscv64)
 
 struct limine_smp_info *init_smp(size_t   *cpu_count,
-                                 uint64_t bsp_hartid,
-                                 pagemap_t pagemap);
+                                 uint64_t  bsp_hartid,
+                                 pagemap_t pagemap,
+                                 uint64_t  hhdm_offset);
 
 #else
 #error Unknown architecture
diff --git a/common/sys/smp_trampoline.asm_riscv64 b/common/sys/smp_trampoline.asm_riscv64
index e9e886f8..6bdb1f92 100644
--- a/common/sys/smp_trampoline.asm_riscv64
+++ b/common/sys/smp_trampoline.asm_riscv64
@@ -11,15 +11,29 @@ smp_trampoline_start:
         //
         // All other registers are undefined.
 
-        ld      a0, 16(a1)
-        ld      t0, 8(a1)
-        csrw    satp, t0
+#define smp_tpl_booted_flag     0
+#define smp_tpl_satp            8
+#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)
 
         // Tell the BSP we've started.
         li      t0, 1
         fence   rw, w
         sd      t0, (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
+0:
+        // Relocate the info struct to the higher half.
+        add     a0, t1, a0
+
         // Zero all the things.
         // Preserve a0
         mv      a1, zero
tab: 248 wrap: offon