[arch][riscv][sbi] add the pmu extension, tweak boot messages, qemu-virt use reset calls

This commit is contained in:
Travis Geiselbrecht
2022-05-29 14:48:04 -07:00
parent b3dd72ab1d
commit 095aca80f1
4 changed files with 68 additions and 21 deletions

View File

@@ -88,19 +88,28 @@ void arch_init(void) {
riscv_init_percpu();
// print some arch info
const char *mode_string;
#if RISCV_M_MODE
dprintf(INFO, "RISCV: Machine mode\n");
mode_string = "Machine";
#elif RISCV_S_MODE
mode_string = "Supervisor";
#else
#error need to define M or S mode
#endif
dprintf(INFO, "RISCV: %s mode\n", mode_string);
dprintf(INFO, "RISCV: mvendorid %#lx marchid %#lx mimpid %#lx mhartid %#x\n",
riscv_get_mvendorid(), riscv_get_marchid(),
riscv_get_mimpid(), riscv_current_hart());
#if RISCV_M_MODE
dprintf(INFO, "RISCV: misa %#lx\n", riscv_csr_read(RISCV_CSR_MISA));
#else
dprintf(INFO, "RISCV: Supervisor mode\n");
#elif RISCV_S_MODE
sbi_init();
#if RISCV_MMU
dprintf(INFO, "RISCV: MMU enabled sv%u\n", RISCV_MMU);
riscv_mmu_init();
#endif
sbi_init();
#endif
#if WITH_SMP

View File

@@ -32,6 +32,7 @@ enum sbi_return_code {
SBI_ERR_INVALID_ADDRESS = -5,
};
// Legacy SBI extensions (avoid using)
#define SBI_SET_TIMER 0x00, 0
#define SBI_CONSOLE_PUTCHAR 0x01, 0
#define SBI_CONSOLE_GETCHAR 0x02, 0
@@ -42,6 +43,7 @@ enum sbi_return_code {
#define SBI_REMOTE_SFENCE_VMA_ASID 0x07, 0
#define SBI_SHUTDOWN 0x08, 0
// Base extension
#define SBI_GET_SBI_SPEC_VERSION 0x10, 0
#define SBI_GET_SBI_IMPL_ID 0x10, 1
#define SBI_GET_SBI_IMPL_VERSION 0x10, 2
@@ -50,11 +52,14 @@ enum sbi_return_code {
#define SBI_GET_MARCHID 0x10, 5
#define SBI_GET_MIMPID 0x10, 6
#define SBI_EXT_TIMER_SIG 0x54494d45
#define SBI_EXT_IPI_SIG 0x00735049
#define SBI_EXT_RFENCE_SIG 0x52464e43
#define SBI_EXT_HSM_SIG 0x0048534d
#define SBI_EXT_SRST_SIG 0x53525354
// Extension signatures
// use SBI_PROBE_EXTENSION to discover
#define SBI_EXT_TIMER_SIG 0x54494d45 // TIME
#define SBI_EXT_IPI_SIG 0x00735049 // sPI
#define SBI_EXT_RFENCE_SIG 0x52464e43 // RFNC
#define SBI_EXT_HSM_SIG 0x0048534d // HSM
#define SBI_EXT_SRST_SIG 0x53525354 // SRST
#define SBI_EXT_PMU_SIG 0x00504d55 // PMU
void sbi_early_init(void);
void sbi_init(void);
@@ -71,6 +76,17 @@ bool sbi_probe_extension(ulong extension);
struct sbiret sbi_generic_call_2(ulong extension, ulong function);
struct sbiret sbi_generic_call_3(ulong extension, ulong function);
#define SBI_RESET_TYPE_SHUTDOWN 0
#define SBI_RESET_TYPE_COLD_REBOOT 1
#define SBI_RESET_TYPE_WARM_REBOOT 2
#define SBI_RESET_TYPE_VENDOR_BASE (0xf0000000)
#define SBI_RESET_REASON_NONE 0
#define SBI_RESET_REASON_SYSTEM_FAILURE 1
#define SBI_RESET_REASON_SBI_BASE (0xe0000000)
#define SBI_RESET_REASON_VENDOR_BASE (0xf0000000)
status_t sbi_system_reset(uint32_t type, uint32_t reason);
#endif
__END_CDECLS

View File

@@ -25,6 +25,7 @@ enum sbi_extension {
SBI_EXTENSION_RFENCE,
SBI_EXTENSION_HSM,
SBI_EXTENSION_SRST,
SBI_EXTENSION_PMU,
};
static uint sbi_ext;
@@ -110,6 +111,19 @@ void sbi_rfence_vma(const unsigned long *hart_mask, vaddr_t vma, size_t size) {
}
}
status_t sbi_system_reset(uint32_t type, uint32_t reason) {
if (likely(sbi_ext_present(SBI_EXTENSION_SRST))) {
ulong error = sbi_call(SBI_EXT_SRST_SIG, 0, type, reason).error;
if (error != 0) {
return ERR_GENERIC;
}
// we really shouldn't get here
return NO_ERROR;
} else {
return ERR_NOT_IMPLEMENTED;
}
}
void sbi_early_init(void) {
// read the presence of some features
sbi_ext |= sbi_probe_extension(SBI_EXT_TIMER_SIG) ? (1<<SBI_EXTENSION_TIMER) : 0;
@@ -117,25 +131,26 @@ void sbi_early_init(void) {
sbi_ext |= sbi_probe_extension(SBI_EXT_RFENCE_SIG) ? (1<<SBI_EXTENSION_RFENCE) : 0;
sbi_ext |= sbi_probe_extension(SBI_EXT_HSM_SIG) ? (1<<SBI_EXTENSION_HSM) : 0;
sbi_ext |= sbi_probe_extension(SBI_EXT_SRST_SIG) ? (1<<SBI_EXTENSION_SRST) : 0;
sbi_ext |= sbi_probe_extension(SBI_EXT_PMU_SIG) ? (1<<SBI_EXTENSION_PMU) : 0;
}
void sbi_init(void) {
dprintf(INFO, "RISCV: SBI spec version %ld impl id %ld version %ld\n",
sbi_generic_call_2(SBI_GET_SBI_SPEC_VERSION).value,
ulong version = sbi_generic_call_2(SBI_GET_SBI_SPEC_VERSION).value;
dprintf(INFO, "RISCV: SBI spec version %lu.%lu impl id %lu version %lu\n",
(version >> 24) & 0x7f, version & ((1UL<<24)-1),
sbi_generic_call_2(SBI_GET_SBI_IMPL_ID).value,
sbi_generic_call_2(SBI_GET_SBI_IMPL_VERSION).value);
// print the extensions detected
dprintf(INFO, "RISCV: SBI extension TIMER %d\n", sbi_ext_present(SBI_EXTENSION_TIMER));
dprintf(INFO, "RISCV: SBI extension IPI %d\n", sbi_ext_present(SBI_EXTENSION_IPI));
dprintf(INFO, "RISCV: SBI extension RFENCE %d\n", sbi_ext_present(SBI_EXTENSION_RFENCE));
dprintf(INFO, "RISCV: SBI extension HSM %d\n", sbi_ext_present(SBI_EXTENSION_HSM));
dprintf(INFO, "RISCV: SBI extension SRST %d\n", sbi_ext_present(SBI_EXTENSION_SRST));
// print a line via the console
const char test[] = "SBI console test\n\r";
for (const char *c = test; *c != 0; c++) {
sbi_call(SBI_CONSOLE_PUTCHAR, *c);
if (LK_DEBUGLEVEL >= INFO) {
dprintf(INFO, "RISCV: SBI extensions: ");
if (sbi_ext_present(SBI_EXTENSION_TIMER)) dprintf(INFO, "TIMER ");
if (sbi_ext_present(SBI_EXTENSION_IPI)) dprintf(INFO, "IPI ");
if (sbi_ext_present(SBI_EXTENSION_RFENCE)) dprintf(INFO, "RFENCE ");
if (sbi_ext_present(SBI_EXTENSION_HSM)) dprintf(INFO, "HSM ");
if (sbi_ext_present(SBI_EXTENSION_SRST)) dprintf(INFO, "SRST ");
if (sbi_ext_present(SBI_EXTENSION_PMU)) dprintf(INFO, "PMU ");
dprintf(INFO, "\n");
}
}

View File

@@ -220,10 +220,17 @@ void platform_halt(platform_halt_action suggested_action,
switch (suggested_action) {
case HALT_ACTION_SHUTDOWN:
dprintf(ALWAYS, "Shutting down... (reason = %d)\n", reason);
#if RISCV_S_MODE
// try to use SBI as a cleaner way to stop
sbi_system_reset(SBI_RESET_TYPE_SHUTDOWN, SBI_RESET_REASON_NONE);
#endif
*power_reset_reg = 0x5555;
break;
case HALT_ACTION_REBOOT:
dprintf(ALWAYS, "Rebooting... (reason = %d)\n", reason);
#if RISCV_S_MODE
sbi_system_reset(SBI_RESET_TYPE_COLD_REBOOT, SBI_RESET_REASON_NONE);
#endif
*power_reset_reg = 0x7777;
break;
case HALT_ACTION_HALT: