[arch][riscv][sbi] add the pmu extension, tweak boot messages, qemu-virt use reset calls
This commit is contained in:
@@ -88,19 +88,28 @@ void arch_init(void) {
|
|||||||
riscv_init_percpu();
|
riscv_init_percpu();
|
||||||
|
|
||||||
// print some arch info
|
// print some arch info
|
||||||
|
const char *mode_string;
|
||||||
#if RISCV_M_MODE
|
#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",
|
dprintf(INFO, "RISCV: mvendorid %#lx marchid %#lx mimpid %#lx mhartid %#x\n",
|
||||||
riscv_get_mvendorid(), riscv_get_marchid(),
|
riscv_get_mvendorid(), riscv_get_marchid(),
|
||||||
riscv_get_mimpid(), riscv_current_hart());
|
riscv_get_mimpid(), riscv_current_hart());
|
||||||
|
|
||||||
|
#if RISCV_M_MODE
|
||||||
dprintf(INFO, "RISCV: misa %#lx\n", riscv_csr_read(RISCV_CSR_MISA));
|
dprintf(INFO, "RISCV: misa %#lx\n", riscv_csr_read(RISCV_CSR_MISA));
|
||||||
#else
|
#elif RISCV_S_MODE
|
||||||
dprintf(INFO, "RISCV: Supervisor mode\n");
|
sbi_init();
|
||||||
#if RISCV_MMU
|
#if RISCV_MMU
|
||||||
dprintf(INFO, "RISCV: MMU enabled sv%u\n", RISCV_MMU);
|
dprintf(INFO, "RISCV: MMU enabled sv%u\n", RISCV_MMU);
|
||||||
riscv_mmu_init();
|
riscv_mmu_init();
|
||||||
#endif
|
#endif
|
||||||
sbi_init();
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if WITH_SMP
|
#if WITH_SMP
|
||||||
|
|||||||
@@ -32,6 +32,7 @@ enum sbi_return_code {
|
|||||||
SBI_ERR_INVALID_ADDRESS = -5,
|
SBI_ERR_INVALID_ADDRESS = -5,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Legacy SBI extensions (avoid using)
|
||||||
#define SBI_SET_TIMER 0x00, 0
|
#define SBI_SET_TIMER 0x00, 0
|
||||||
#define SBI_CONSOLE_PUTCHAR 0x01, 0
|
#define SBI_CONSOLE_PUTCHAR 0x01, 0
|
||||||
#define SBI_CONSOLE_GETCHAR 0x02, 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_REMOTE_SFENCE_VMA_ASID 0x07, 0
|
||||||
#define SBI_SHUTDOWN 0x08, 0
|
#define SBI_SHUTDOWN 0x08, 0
|
||||||
|
|
||||||
|
// Base extension
|
||||||
#define SBI_GET_SBI_SPEC_VERSION 0x10, 0
|
#define SBI_GET_SBI_SPEC_VERSION 0x10, 0
|
||||||
#define SBI_GET_SBI_IMPL_ID 0x10, 1
|
#define SBI_GET_SBI_IMPL_ID 0x10, 1
|
||||||
#define SBI_GET_SBI_IMPL_VERSION 0x10, 2
|
#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_MARCHID 0x10, 5
|
||||||
#define SBI_GET_MIMPID 0x10, 6
|
#define SBI_GET_MIMPID 0x10, 6
|
||||||
|
|
||||||
#define SBI_EXT_TIMER_SIG 0x54494d45
|
// Extension signatures
|
||||||
#define SBI_EXT_IPI_SIG 0x00735049
|
// use SBI_PROBE_EXTENSION to discover
|
||||||
#define SBI_EXT_RFENCE_SIG 0x52464e43
|
#define SBI_EXT_TIMER_SIG 0x54494d45 // TIME
|
||||||
#define SBI_EXT_HSM_SIG 0x0048534d
|
#define SBI_EXT_IPI_SIG 0x00735049 // sPI
|
||||||
#define SBI_EXT_SRST_SIG 0x53525354
|
#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_early_init(void);
|
||||||
void sbi_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_2(ulong extension, ulong function);
|
||||||
struct sbiret sbi_generic_call_3(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
|
#endif
|
||||||
|
|
||||||
__END_CDECLS
|
__END_CDECLS
|
||||||
|
|||||||
@@ -25,6 +25,7 @@ enum sbi_extension {
|
|||||||
SBI_EXTENSION_RFENCE,
|
SBI_EXTENSION_RFENCE,
|
||||||
SBI_EXTENSION_HSM,
|
SBI_EXTENSION_HSM,
|
||||||
SBI_EXTENSION_SRST,
|
SBI_EXTENSION_SRST,
|
||||||
|
SBI_EXTENSION_PMU,
|
||||||
};
|
};
|
||||||
|
|
||||||
static uint sbi_ext;
|
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) {
|
void sbi_early_init(void) {
|
||||||
// read the presence of some features
|
// read the presence of some features
|
||||||
sbi_ext |= sbi_probe_extension(SBI_EXT_TIMER_SIG) ? (1<<SBI_EXTENSION_TIMER) : 0;
|
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_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_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_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) {
|
void sbi_init(void) {
|
||||||
dprintf(INFO, "RISCV: SBI spec version %ld impl id %ld version %ld\n",
|
ulong version = sbi_generic_call_2(SBI_GET_SBI_SPEC_VERSION).value;
|
||||||
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_ID).value,
|
||||||
sbi_generic_call_2(SBI_GET_SBI_IMPL_VERSION).value);
|
sbi_generic_call_2(SBI_GET_SBI_IMPL_VERSION).value);
|
||||||
|
|
||||||
// print the extensions detected
|
// print the extensions detected
|
||||||
dprintf(INFO, "RISCV: SBI extension TIMER %d\n", sbi_ext_present(SBI_EXTENSION_TIMER));
|
if (LK_DEBUGLEVEL >= INFO) {
|
||||||
dprintf(INFO, "RISCV: SBI extension IPI %d\n", sbi_ext_present(SBI_EXTENSION_IPI));
|
dprintf(INFO, "RISCV: SBI extensions: ");
|
||||||
dprintf(INFO, "RISCV: SBI extension RFENCE %d\n", sbi_ext_present(SBI_EXTENSION_RFENCE));
|
if (sbi_ext_present(SBI_EXTENSION_TIMER)) dprintf(INFO, "TIMER ");
|
||||||
dprintf(INFO, "RISCV: SBI extension HSM %d\n", sbi_ext_present(SBI_EXTENSION_HSM));
|
if (sbi_ext_present(SBI_EXTENSION_IPI)) dprintf(INFO, "IPI ");
|
||||||
dprintf(INFO, "RISCV: SBI extension SRST %d\n", sbi_ext_present(SBI_EXTENSION_SRST));
|
if (sbi_ext_present(SBI_EXTENSION_RFENCE)) dprintf(INFO, "RFENCE ");
|
||||||
|
if (sbi_ext_present(SBI_EXTENSION_HSM)) dprintf(INFO, "HSM ");
|
||||||
// print a line via the console
|
if (sbi_ext_present(SBI_EXTENSION_SRST)) dprintf(INFO, "SRST ");
|
||||||
const char test[] = "SBI console test\n\r";
|
if (sbi_ext_present(SBI_EXTENSION_PMU)) dprintf(INFO, "PMU ");
|
||||||
for (const char *c = test; *c != 0; c++) {
|
dprintf(INFO, "\n");
|
||||||
sbi_call(SBI_CONSOLE_PUTCHAR, *c);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -220,10 +220,17 @@ void platform_halt(platform_halt_action suggested_action,
|
|||||||
switch (suggested_action) {
|
switch (suggested_action) {
|
||||||
case HALT_ACTION_SHUTDOWN:
|
case HALT_ACTION_SHUTDOWN:
|
||||||
dprintf(ALWAYS, "Shutting down... (reason = %d)\n", reason);
|
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;
|
*power_reset_reg = 0x5555;
|
||||||
break;
|
break;
|
||||||
case HALT_ACTION_REBOOT:
|
case HALT_ACTION_REBOOT:
|
||||||
dprintf(ALWAYS, "Rebooting... (reason = %d)\n", reason);
|
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;
|
*power_reset_reg = 0x7777;
|
||||||
break;
|
break;
|
||||||
case HALT_ACTION_HALT:
|
case HALT_ACTION_HALT:
|
||||||
|
|||||||
Reference in New Issue
Block a user