diff --git a/src/arch/riscv/inc/arch/csrs.h b/src/arch/riscv/inc/arch/csrs.h index b943b9911..05fafd24c 100644 --- a/src/arch/riscv/inc/arch/csrs.h +++ b/src/arch/riscv/inc/arch/csrs.h @@ -230,6 +230,9 @@ #define HSTATUS_VSXL_OFF (32) #define HSTATUS_VSXL_LEN (2) #define HSTATUS_VSXL_MSK (BIT_MASK(HSTATUS_VSXL_OFF, HSTATUS_VSXL_LEN)) +#define HSTATUS_HUPMM_OFF (48) +#define HSTATUS_HUPMM_LEN (2) +#define HSTATUS_HUPMM_MSK (BIT_MASK(HSTATUS_HUPMM_OFF, HSTATUS_HUPMM_LEN)) #if defined(RV64) #define HSTATUS_VSXL_32 (1UL << HSTATUS_VSXL_OFF) #define HSTATUS_VSXL_64 (2UL << HSTATUS_VSXL_OFF) @@ -243,16 +246,27 @@ #endif #define HENVCFG_FIOM (1ULL << 0) +#define HENVCFG_LPE (1ULL << 2) +#define HENVCFG_SSE (1ULL << 3) #define HENVCFG_CBIE_OFF (4) #define HENVCFG_CBIE_LEN (2) #define HENVCFG_CBIE_MSK (BIT_MASK(HENVCFG_CBIE_OFF, HENVCFG_CBIE_LEN)) #define HENVCFG_CBCFE (1ULL << 6) #define HENVCFG_CBZE (1ULL << 7) +#define HENVCFG_PMM_OFF (32) +#define HENVCFG_PMM_LEN (2) +#define HENVCFG_PMM_MSK (BIT_MASK(HENVCFG_PMM_OFF, HENVCFG_PMM_LEN)) +#define HENVCFG_DTE (1ULL << 59) +#define HENVCFG_ADUE (1ULL << 61) #define HENVCFG_PBMTE (1ULL << 62) #define HENVCFG_STCE (1ULL << 63) #define HENVCFG_CBIE_FLUSH (1ULL << HENVCFG_CBIE_OFF) #define HENVCFG_CBIE_INV (3ULL << HENVCFG_CBIE_OFF) +#define HENVCFG_PMM_DISABLED (0ULL) +#define HENVCFG_PMM_REV (1ULL) +#define HENVCFG_PMM_PMLEN_7 (2ULL) +#define HENVCFG_PMM_PMLEN_16 (3ULL) #define HSTATEEN_C (1ULL << 0) #define HSTATEEN_FCSR (1ULL << 1) diff --git a/src/arch/riscv/vmm.c b/src/arch/riscv/vmm.c index 79e12290d..dffd9fc74 100644 --- a/src/arch/riscv/vmm.c +++ b/src/arch/riscv/vmm.c @@ -81,6 +81,46 @@ void vmm_arch_init() } } +#if CPU_HAS_EXTENSION(CPU_EXT_SSNPM) +#if defined(RV32) +#error "Ssnpm extension is not available for RV32. Please disable CPU_EXT_SSNPM." +#elif !defined(CPU_EXT_SSNPM_PMM_MODE) +#error "Ssnpm extension PMM mode is not defined. Please define CPU_EXT_SSNPM_PMM_MODE." +#else + /** + * Program the guest-visible Ssnpm PMM mode if the hypervisor was + * configured to use it (via the CPU_EXT_SSNPM_PMM_MODE macro). + * Otherwise, henvcfg keeps the reset value written above. + */ + uint64_t pmm_val = 0; + + switch (CPU_EXT_SSNPM_PMM_MODE) { + case HENVCFG_PMM_DISABLED: + if (cpu_is_master()) { + WARNING("Ssnpm extension is enabled but PMM mode is set to disabled.\r\n"); + } + pmm_val = HENVCFG_PMM_DISABLED << HENVCFG_PMM_OFF; + break; + case HENVCFG_PMM_PMLEN_7: + pmm_val = HENVCFG_PMM_PMLEN_7 << HENVCFG_PMM_OFF; + break; + case HENVCFG_PMM_PMLEN_16: + pmm_val = HENVCFG_PMM_PMLEN_16 << HENVCFG_PMM_OFF; + break; + default: + if (cpu_is_master()) { + ERROR("Unsupported PMM mode for Ssnpm extension.\r\n"); + } + } + + csrs_henvcfg_set(pmm_val); + bool ssnpm_present = ((csrs_henvcfg_read() & pmm_val) == pmm_val); + if (cpu_is_master() && !ssnpm_present) { + ERROR("Platform configured to use Ssnpm extension, but extension not present.\r\n"); + } +#endif +#endif + /** * Configure the State Enable mechanism (Ssstateen). * diff --git a/src/platform/qemu-riscv64-virt/inc/plat/cpu_ext.h b/src/platform/qemu-riscv64-virt/inc/plat/cpu_ext.h index 00d63dc91..32770ede0 100644 --- a/src/platform/qemu-riscv64-virt/inc/plat/cpu_ext.h +++ b/src/platform/qemu-riscv64-virt/inc/plat/cpu_ext.h @@ -10,5 +10,7 @@ #if !defined(RV32) #define CPU_EXT_SVPBMT 1 #endif +#define CPU_EXT_SSNPM 0 +#define CPU_EXT_SSNPM_PMM_MODE HENVCFG_PMM_DISABLED #endif