aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPalmer Dabbelt <palmer@dabbelt.com>2017-11-02 18:48:38 -0700
committerGitHub <noreply@github.com>2017-11-02 18:48:38 -0700
commit3815c611158f435d36121c2c433af664ad86d8ca (patch)
tree21fd7e514596ecd126d089b5ecff255bb809d433
parent220b1bee10d9399864131cd1dbe5037714237f03 (diff)
parent27498013ad7684a5f22a99790ac29badea205a3f (diff)
downloadpk-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.c16
-rw-r--r--machine/disabled_hart_mask.h4
-rw-r--r--machine/fdt.c28
-rw-r--r--machine/fdt.h2
-rw-r--r--machine/mentry.S4
-rw-r--r--machine/minit.c26
-rw-r--r--machine/mtrap.c3
-rw-r--r--pk/pk.c1
-rw-r--r--platform/platform_interface.h4
-rw-r--r--platform/sifive-vc707-devkit.c2
-rw-r--r--platform/spike.c2
11 files changed, 64 insertions, 28 deletions
diff --git a/bbl/bbl.c b/bbl/bbl.c
index d3d6d9f..1f91ea2 100644
--- a/bbl/bbl.c
+++ b/bbl/bbl.c
@@ -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;
diff --git a/pk/pk.c b/pk/pk.c
index 11a2cdf..e7cfc3a 100644
--- a/pk/pk.c
+++ b/pk/pk.c
@@ -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;