diff options
author | Palmer Dabbelt <palmer@dabbelt.com> | 2017-11-02 18:48:38 -0700 |
---|---|---|
committer | GitHub <noreply@github.com> | 2017-11-02 18:48:38 -0700 |
commit | 3815c611158f435d36121c2c433af664ad86d8ca (patch) | |
tree | 21fd7e514596ecd126d089b5ecff255bb809d433 | |
parent | 220b1bee10d9399864131cd1dbe5037714237f03 (diff) | |
parent | 27498013ad7684a5f22a99790ac29badea205a3f (diff) | |
download | pk-3815c611158f435d36121c2c433af664ad86d8ca.zip pk-3815c611158f435d36121c2c433af664ad86d8ca.tar.gz pk-3815c611158f435d36121c2c433af664ad86d8ca.tar.bz2 |
Merge pull request #67 from riscv/dts2
Detect harts that can't boot Linux instead of hard-coding them
-rw-r--r-- | bbl/bbl.c | 16 | ||||
-rw-r--r-- | machine/disabled_hart_mask.h | 4 | ||||
-rw-r--r-- | machine/fdt.c | 28 | ||||
-rw-r--r-- | machine/fdt.h | 2 | ||||
-rw-r--r-- | machine/mentry.S | 4 | ||||
-rw-r--r-- | machine/minit.c | 26 | ||||
-rw-r--r-- | machine/mtrap.c | 3 | ||||
-rw-r--r-- | pk/pk.c | 1 | ||||
-rw-r--r-- | platform/platform_interface.h | 4 | ||||
-rw-r--r-- | platform/sifive-vc707-devkit.c | 2 | ||||
-rw-r--r-- | platform/spike.c | 2 |
11 files changed, 64 insertions, 28 deletions
@@ -9,6 +9,7 @@ #include <string.h> static const void* entry_point; +long disabled_hart_mask; static uintptr_t dtb_output() { @@ -24,7 +25,7 @@ static void filter_dtb(uintptr_t source) memcpy((void*)dest, (void*)source, size); // Remove information from the chained FDT - filter_harts(dest, platform__disabled_hart_mask); + filter_harts(dest, &disabled_hart_mask); filter_plic(dest); filter_compat(dest, "riscv,clint0"); filter_compat(dest, "riscv,debug-013"); @@ -37,7 +38,18 @@ void boot_other_hart(uintptr_t unused __attribute__((unused))) entry = entry_point; mb(); } while (!entry); - enter_supervisor_mode(entry, read_csr(mhartid), dtb_output()); + + long hartid = read_csr(mhartid); + if ((1 << hartid) & disabled_hart_mask) { + while (1) { + __asm__ volatile("wfi"); +#ifdef __riscv_div + __asm__ volatile("div x0, x0, x0"); +#endif + } + } + + enter_supervisor_mode(entry, hartid, dtb_output()); } void boot_loader(uintptr_t dtb) diff --git a/machine/disabled_hart_mask.h b/machine/disabled_hart_mask.h new file mode 100644 index 0000000..2a3a73c --- /dev/null +++ b/machine/disabled_hart_mask.h @@ -0,0 +1,4 @@ +#ifndef DISABLED_HART_MASK_H +#define DISABLED_HART_MASK_H +extern long disabled_hart_mask; +#endif diff --git a/machine/fdt.c b/machine/fdt.c index 35681f8..061b19e 100644 --- a/machine/fdt.c +++ b/machine/fdt.c @@ -1,3 +1,4 @@ +#include <stdbool.h> #include <stdint.h> #include <string.h> #include "config.h" @@ -553,13 +554,15 @@ struct hart_filter { int compat; int hart; char *status; - unsigned long mask; + char *mmu_type; + long *disabled_hart_mask; }; static void hart_filter_open(const struct fdt_scan_node *node, void *extra) { struct hart_filter *filter = (struct hart_filter *)extra; - filter->status = 0; + filter->status = NULL; + filter->mmu_type = NULL; filter->compat = 0; filter->hart = -1; } @@ -575,9 +578,22 @@ static void hart_filter_prop(const struct fdt_scan_prop *prop, void *extra) filter->hart = reg; } else if (!strcmp(prop->name, "status")) { filter->status = (char*)prop->value; + } else if (!strcmp(prop->name, "mmu-type")) { + filter->mmu_type = (char*)prop->value; } } +static bool hart_filter_mask(const struct hart_filter *filter) +{ + if (filter->mmu_type == NULL) return true; + if (strcmp(filter->status, "okay")) return true; + if (!strcmp(filter->mmu_type, "riscv,sv39")) return false; + if (!strcmp(filter->mmu_type, "riscv,sv48")) return false; + printm("hart_filter_mask saw unknown hart type: status=\"%s\", mmu_type=\"%s\"\n", + filter->status, filter->mmu_type); + return true; +} + static void hart_filter_done(const struct fdt_scan_node *node, void *extra) { struct hart_filter *filter = (struct hart_filter *)extra; @@ -586,14 +602,15 @@ static void hart_filter_done(const struct fdt_scan_node *node, void *extra) assert (filter->status); assert (filter->hart >= 0); - if (((filter->mask >> filter->hart) & 1) && !strcmp(filter->status, "okay")) { + if (hart_filter_mask(filter)) { strcpy(filter->status, "masked"); uint32_t *len = (uint32_t*)filter->status; len[-2] = bswap(strlen("masked")+1); + *filter->disabled_hart_mask |= (1 << filter->hart); } } -void filter_harts(uintptr_t fdt, unsigned long hart_mask) +void filter_harts(uintptr_t fdt, long *disabled_hart_mask) { struct fdt_cb cb; struct hart_filter filter; @@ -604,7 +621,8 @@ void filter_harts(uintptr_t fdt, unsigned long hart_mask) cb.done = hart_filter_done; cb.extra = &filter; - filter.mask = hart_mask; + filter.disabled_hart_mask = disabled_hart_mask; + *disabled_hart_mask = 0; fdt_scan(fdt, &cb); } diff --git a/machine/fdt.h b/machine/fdt.h index 5932e17..d436778 100644 --- a/machine/fdt.h +++ b/machine/fdt.h @@ -61,7 +61,7 @@ void query_plic(uintptr_t fdt); void query_clint(uintptr_t fdt); // Remove information from FDT -void filter_harts(uintptr_t fdt, unsigned long hart_mask); +void filter_harts(uintptr_t fdt, long *disabled_hart_mask); void filter_plic(uintptr_t fdt); void filter_compat(uintptr_t fdt, const char *compat); diff --git a/machine/mentry.S b/machine/mentry.S index 33d7be4..11c053c 100644 --- a/machine/mentry.S +++ b/machine/mentry.S @@ -258,7 +258,7 @@ do_reset: add sp, sp, a2 # Boot on the first unmasked hart - la a4, platform__disabled_hart_mask + la a4, disabled_hart_mask LOAD a4, 0(a4) addi a5, a4, 1 not a4, a4 @@ -277,7 +277,7 @@ do_reset: wfi # masked harts never start - la a4, platform__disabled_hart_mask + la a4, disabled_hart_mask LOAD a4, 0(a4) srl a4, a4, a3 andi a4, a4, 1 diff --git a/machine/minit.c b/machine/minit.c index 187bef7..5f98501 100644 --- a/machine/minit.c +++ b/machine/minit.c @@ -6,6 +6,7 @@ #include "uart.h" #include "finisher.h" #include "platform_interface.h" +#include "disabled_hart_mask.h" #include <string.h> #include <limits.h> @@ -18,22 +19,28 @@ size_t plic_ndevs; static void mstatus_init() { // Enable FPU - write_csr(mstatus, MSTATUS_FS); + if (supports_extension('D') || supports_extension('F')) + write_csr(mstatus, MSTATUS_FS); // Enable user/supervisor use of perf counters - write_csr(scounteren, -1); + if (supports_extension('S')) + write_csr(scounteren, -1); write_csr(mcounteren, -1); // Enable software interrupts write_csr(mie, MIP_MSIP); // Disable paging - write_csr(sptbr, 0); + if (supports_extension('S')) + write_csr(sptbr, 0); } // send S-mode interrupts and most exceptions straight to S-mode static void delegate_traps() { + if (!supports_extension('S')) + return; + uintptr_t interrupts = MIP_SSIP | MIP_STIP | MIP_SEIP; uintptr_t exceptions = (1U << CAUSE_MISALIGNED_FETCH) | @@ -52,11 +59,12 @@ static void delegate_traps() static void fp_init() { + if (!supports_extension('D') && !supports_extension('F')) + return; + assert(read_csr(mstatus) & MSTATUS_FS); #ifdef __riscv_flen - if (!supports_extension('D')) - die("FPU not found; recompile pk with -msoft-float"); for (int i = 0; i < 32; i++) init_fp_reg(i); write_csr(fcsr, 0); @@ -125,18 +133,18 @@ static void hart_plic_init() static void wake_harts() { for (int hart = 0; hart < MAX_HARTS; ++hart) - if ((((~platform__disabled_hart_mask & hart_mask) >> hart) & 1)) + if ((((~disabled_hart_mask & hart_mask) >> hart) & 1)) *OTHER_HLS(hart)->ipi = 1; // wakeup the hart } void init_first_hart(uintptr_t hartid, uintptr_t dtb) { - hart_init(); - hls_init(0); // this might get called again from parse_config_string - // Confirm console as early as possible query_uart(dtb); + hart_init(); + hls_init(0); // this might get called again from parse_config_string + // Find the power button early as well so die() works query_finisher(dtb); diff --git a/machine/mtrap.c b/machine/mtrap.c index e5faae3..dba3613 100644 --- a/machine/mtrap.c +++ b/machine/mtrap.c @@ -9,6 +9,7 @@ #include "fdt.h" #include "unprivileged_memory.h" #include "platform_interface.h" +#include "disabled_hart_mask.h" #include <errno.h> #include <stdarg.h> #include <stdio.h> @@ -63,7 +64,7 @@ void printm(const char* s, ...) static void send_ipi(uintptr_t recipient, int event) { - if (((platform__disabled_hart_mask >> recipient) & 1)) return; + if (((disabled_hart_mask >> recipient) & 1)) return; atomic_or(&OTHER_HLS(recipient)->mipi_pending, event); mb(); *OTHER_HLS(recipient)->ipi = 1; @@ -7,6 +7,7 @@ #include <stdbool.h> elf_info current; +long disabled_hart_mask; static void handle_option(const char* s) { diff --git a/platform/platform_interface.h b/platform/platform_interface.h index f083085..203457d 100644 --- a/platform/platform_interface.h +++ b/platform/platform_interface.h @@ -20,10 +20,6 @@ const char *platform__get_logo(void); /* Returns TRUE if it's valid to use the HTIF */ int platform__use_htif(void); -/* The harts that should be excluded from booting to the target program and - * should intsead be held in a loop. */ -extern long platform__disabled_hart_mask; - #endif #endif diff --git a/platform/sifive-vc707-devkit.c b/platform/sifive-vc707-devkit.c index cc0e0f1..bd27861 100644 --- a/platform/sifive-vc707-devkit.c +++ b/platform/sifive-vc707-devkit.c @@ -28,8 +28,6 @@ static const char logo[] = "\r\n" " SiFive RISC-V Coreplex\r\n"; -long platform__disabled_hart_mask = 0x1; - const char *platform__get_logo(void) { return logo; diff --git a/platform/spike.c b/platform/spike.c index 4d9d397..159255f 100644 --- a/platform/spike.c +++ b/platform/spike.c @@ -25,8 +25,6 @@ static const char logo[] = "\n" " INSTRUCTION SETS WANT TO BE FREE\n"; -long platform__disabled_hart_mask = 0; - const char *platform__get_logo(void) { return logo; |