[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: [RFC PATCH v3 1/4] target/riscv: Add smstateen support
From: |
Alistair Francis |
Subject: |
Re: [RFC PATCH v3 1/4] target/riscv: Add smstateen support |
Date: |
Thu, 31 Mar 2022 12:42:11 +1000 |
On Tue, Mar 29, 2022 at 3:24 AM Mayuresh Chitale
<mchitale@ventanamicro.com> wrote:
>
> Smstateen extension specifies a mechanism to close
> the potential covert channels that could cause security issues.
>
> This patch adds the CSRs defined in the specification and
> the corresponding predicates and read/write functions.
>
> Signed-off-by: Mayuresh Chitale <mchitale@ventanamicro.com>
> ---
> target/riscv/cpu.c | 2 +
> target/riscv/cpu.h | 4 +
> target/riscv/cpu_bits.h | 36 +++++++
> target/riscv/csr.c | 210 ++++++++++++++++++++++++++++++++++++++++
> target/riscv/machine.c | 21 ++++
> 5 files changed, 273 insertions(+)
>
> diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
> index 3aa2ef5cce..dc5472834d 100644
> --- a/target/riscv/cpu.c
> +++ b/target/riscv/cpu.c
> @@ -788,6 +788,7 @@ static Property riscv_cpu_properties[] = {
> DEFINE_PROP_BOOL("Zve64f", RISCVCPU, cfg.ext_zve64f, false),
> DEFINE_PROP_BOOL("mmu", RISCVCPU, cfg.mmu, true),
> DEFINE_PROP_BOOL("pmp", RISCVCPU, cfg.pmp, true),
> + DEFINE_PROP_BOOL("smstateen", RISCVCPU, cfg.ext_smstateen, true),
I'm not convinced this should be enabled by default. Does OpenSBI and
other M-mode firmware currently handle support enabling this?
Also, if you do think it should be enabled by default, it should be
enabled in a separate patch at the end of the series. The idea is to
add the feature first, then enable it.
>
> DEFINE_PROP_STRING("priv_spec", RISCVCPU, cfg.priv_spec),
> DEFINE_PROP_STRING("vext_spec", RISCVCPU, cfg.vext_spec),
> @@ -929,6 +930,7 @@ static void riscv_isa_string_ext(RISCVCPU *cpu, char
> **isa_str, int max_str_len)
> ISA_EDATA_ENTRY(zhinxmin, ext_zhinxmin),
> ISA_EDATA_ENTRY(zve32f, ext_zve32f),
> ISA_EDATA_ENTRY(zve64f, ext_zve64f),
> + ISA_EDATA_ENTRY(smstateen, ext_smstateen),
> };
>
> for (i = 0; i < ARRAY_SIZE(isa_edata_arr); i++) {
> diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h
> index c9956513bc..4a3b5a6c23 100644
> --- a/target/riscv/cpu.h
> +++ b/target/riscv/cpu.h
> @@ -307,6 +307,9 @@ struct CPUArchState {
>
> /* CSRs for execution enviornment configuration */
> uint64_t menvcfg;
> + uint64_t mstateen[SMSTATEEN_MAX_COUNT];
> + uint64_t hstateen[SMSTATEEN_MAX_COUNT];
> + uint64_t sstateen[SMSTATEEN_MAX_COUNT];
> target_ulong senvcfg;
> uint64_t henvcfg;
> #endif
> @@ -378,6 +381,7 @@ struct RISCVCPUConfig {
> bool ext_zhinxmin;
> bool ext_zve32f;
> bool ext_zve64f;
> + bool ext_smstateen;
>
> /* Vendor-specific custom extensions */
> bool ext_XVentanaCondOps;
> diff --git a/target/riscv/cpu_bits.h b/target/riscv/cpu_bits.h
> index bb47cf7e77..b2b0bcb929 100644
> --- a/target/riscv/cpu_bits.h
> +++ b/target/riscv/cpu_bits.h
> @@ -205,6 +205,12 @@
> /* Supervisor Configuration CSRs */
> #define CSR_SENVCFG 0x10A
>
> +/* Supervisor state CSRs */
> +#define CSR_SSTATEEN0 0x10C
> +#define CSR_SSTATEEN1 0x10D
> +#define CSR_SSTATEEN2 0x10E
> +#define CSR_SSTATEEN3 0x10F
> +
> /* Supervisor Trap Handling */
> #define CSR_SSCRATCH 0x140
> #define CSR_SEPC 0x141
> @@ -254,6 +260,16 @@
> #define CSR_HENVCFG 0x60A
> #define CSR_HENVCFGH 0x61A
>
> +/* Hypervisor state CSRs */
> +#define CSR_HSTATEEN0 0x60C
> +#define CSR_HSTATEEN0H 0x61C
> +#define CSR_HSTATEEN1 0x60D
> +#define CSR_HSTATEEN1H 0x61D
> +#define CSR_HSTATEEN2 0x60E
> +#define CSR_HSTATEEN2H 0x61E
> +#define CSR_HSTATEEN3 0x60F
> +#define CSR_HSTATEEN3H 0x61F
> +
> /* Virtual CSRs */
> #define CSR_VSSTATUS 0x200
> #define CSR_VSIE 0x204
> @@ -301,6 +317,26 @@
> #define CSR_MENVCFG 0x30A
> #define CSR_MENVCFGH 0x31A
>
> +/* Machine state CSRs */
> +#define CSR_MSTATEEN0 0x30C
> +#define CSR_MSTATEEN0H 0x31C
> +#define CSR_MSTATEEN1 0x30D
> +#define CSR_MSTATEEN1H 0x31D
> +#define CSR_MSTATEEN2 0x30E
> +#define CSR_MSTATEEN2H 0x31E
> +#define CSR_MSTATEEN3 0x30F
> +#define CSR_MSTATEEN3H 0x31F
> +
> +/* Common defines for all smstateen */
> +#define SMSTATEEN_MAX_COUNT 4
> +#define SMSTATEEN0_CS 0
> +#define SMSTATEEN0_FCSR 0
Should this be 1?
Alistair
> +#define SMSTATEEN0_IMSIC 58
> +#define SMSTATEEN0_AIA 59
> +#define SMSTATEEN0_SVSLCT 60
> +#define SMSTATEEN0_HSENVCFG 62
> +#define SMSTATEEN_STATEN 63
> +
> /* Enhanced Physical Memory Protection (ePMP) */
> #define CSR_MSECCFG 0x747
> #define CSR_MSECCFGH 0x757
> diff --git a/target/riscv/csr.c b/target/riscv/csr.c
> index 2c0319ad12..e3dafc37ef 100644
> --- a/target/riscv/csr.c
> +++ b/target/riscv/csr.c
> @@ -245,6 +245,42 @@ static RISCVException hmode32(CPURISCVState *env, int
> csrno)
>
> }
>
> +static RISCVException mstateen(CPURISCVState *env, int csrno)
> +{
> + CPUState *cs = env_cpu(env);
> + RISCVCPU *cpu = RISCV_CPU(cs);
> +
> + if (!cpu->cfg.ext_smstateen) {
> + return RISCV_EXCP_ILLEGAL_INST;
> + }
> +
> + return any(env, csrno);
> +}
> +
> +static RISCVException hstateen(CPURISCVState *env, int csrno)
> +{
> + CPUState *cs = env_cpu(env);
> + RISCVCPU *cpu = RISCV_CPU(cs);
> +
> + if (!cpu->cfg.ext_smstateen) {
> + return RISCV_EXCP_ILLEGAL_INST;
> + }
> +
> + return hmode(env, csrno);
> +}
> +
> +static RISCVException sstateen(CPURISCVState *env, int csrno)
> +{
> + CPUState *cs = env_cpu(env);
> + RISCVCPU *cpu = RISCV_CPU(cs);
> +
> + if (!cpu->cfg.ext_smstateen) {
> + return RISCV_EXCP_ILLEGAL_INST;
> + }
> +
> + return smode(env, csrno);
> +}
> +
> /* Checks if PointerMasking registers could be accessed */
> static RISCVException pointer_masking(CPURISCVState *env, int csrno)
> {
> @@ -1493,6 +1529,129 @@ static RISCVException write_henvcfgh(CPURISCVState
> *env, int csrno,
> return RISCV_EXCP_NONE;
> }
>
> +static inline void write_smstateen(CPURISCVState *env, uint64_t *reg,
> + uint64_t wr_mask, uint64_t new_val)
> +{
> + *reg = (*reg & ~wr_mask) | (new_val & wr_mask);
> +}
> +
> +static RISCVException read_mstateen(CPURISCVState *env, int csrno,
> + target_ulong *val)
> +{
> + *val = env->mstateen[csrno - CSR_MSTATEEN0];
> +
> + return RISCV_EXCP_NONE;
> +}
> +
> +static RISCVException write_mstateen(CPURISCVState *env, int csrno,
> + target_ulong new_val)
> +{
> + uint64_t *reg;
> + uint64_t wr_mask = 1UL << SMSTATEEN_STATEN;
> +
> + reg = &env->mstateen[csrno - CSR_MSTATEEN0];
> + write_smstateen(env, reg, wr_mask, new_val);
> +
> + return RISCV_EXCP_NONE;
> +}
> +
> +static RISCVException read_mstateenh(CPURISCVState *env, int csrno,
> + target_ulong *val)
> +{
> + *val = env->mstateen[csrno - CSR_MSTATEEN0H] >> 32;
> +
> + return RISCV_EXCP_NONE;
> +}
> +
> +static RISCVException write_mstateenh(CPURISCVState *env, int csrno,
> + target_ulong new_val)
> +{
> + uint64_t *reg;
> + uint64_t val;
> + uint64_t wr_mask = 1UL << SMSTATEEN_STATEN;
> +
> + reg = &env->mstateen[csrno - CSR_MSTATEEN0H];
> + val = (uint64_t)new_val << 32;
> + val |= *reg & 0xFFFFFFFF;
> + write_smstateen(env, reg, wr_mask, val);
> +
> + return RISCV_EXCP_NONE;
> +}
> +
> +static RISCVException read_hstateen(CPURISCVState *env, int csrno,
> + target_ulong *val)
> +{
> + *val = env->hstateen[csrno - CSR_HSTATEEN0];
> +
> + return RISCV_EXCP_NONE;
> +}
> +
> +static RISCVException write_hstateen(CPURISCVState *env, int csrno,
> + target_ulong new_val)
> +{
> + uint64_t *reg;
> + uint64_t wr_mask = 1UL << SMSTATEEN_STATEN;
> + int index = csrno - CSR_HSTATEEN0;
> +
> + reg = &env->hstateen[index];
> + wr_mask &= env->mstateen[index];
> + write_smstateen(env, reg, wr_mask, new_val);
> +
> + return RISCV_EXCP_NONE;
> +}
> +
> +static RISCVException read_hstateenh(CPURISCVState *env, int csrno,
> + target_ulong *val)
> +{
> + *val = env->hstateen[csrno - CSR_HSTATEEN0H] >> 32;
> +
> + return RISCV_EXCP_NONE;
> +}
> +
> +static RISCVException write_hstateenh(CPURISCVState *env, int csrno,
> + target_ulong new_val)
> +{
> + uint64_t *reg;
> + uint64_t val;
> + uint64_t wr_mask = 1UL << SMSTATEEN_STATEN;
> + int index = csrno - CSR_HSTATEEN0H;
> +
> + reg = &env->hstateen[index];
> + val = (uint64_t)new_val << 32;
> + val |= *reg & 0xFFFFFFFF;
> + wr_mask &= env->mstateen[index];
> +
> + write_smstateen(env, reg, wr_mask, val);
> + return RISCV_EXCP_NONE;
> +}
> +
> +static RISCVException read_sstateen(CPURISCVState *env, int csrno,
> + target_ulong *val)
> +{
> + *val = env->sstateen[csrno - CSR_SSTATEEN0];
> +
> + return RISCV_EXCP_NONE;
> +}
> +
> +static RISCVException write_sstateen(CPURISCVState *env, int csrno,
> + target_ulong new_val)
> +{
> + uint64_t *reg;
> + uint64_t wr_mask = 0;
> + int index = csrno - CSR_SSTATEEN0;
> + bool virt = riscv_cpu_virt_enabled(env);
> +
> + reg = &env->sstateen[index];
> + if (virt) {
> + wr_mask &= env->mstateen[index];
> + } else {
> + wr_mask &= env->hstateen[index];
> + }
> + write_smstateen(env, reg, wr_mask, new_val);
> +
> + return RISCV_EXCP_NONE;
> +}
> +
> static RISCVException rmw_mip64(CPURISCVState *env, int csrno,
> uint64_t *ret_val,
> uint64_t new_val, uint64_t wr_mask)
> @@ -3268,6 +3427,57 @@ riscv_csr_operations csr_ops[CSR_TABLE_SIZE] = {
> [CSR_HENVCFGH] = { "henvcfgh", hmode32, read_henvcfgh, write_henvcfgh,
> .min_priv_ver =
> PRIV_VERSION_1_12_0 },
>
> + /* Smstateen extension CSRs */
> + [CSR_MSTATEEN0] = { "mstateen0", mstateen, read_mstateen, write_mstateen,
> + .min_priv_ver = PRIV_VERSION_1_12_0 },
> + [CSR_MSTATEEN0H] = { "mstateen0h", mstateen, read_mstateenh,
> + write_mstateenh,
> + .min_priv_ver = PRIV_VERSION_1_12_0 },
> + [CSR_MSTATEEN1] = { "mstateen1", mstateen, read_mstateen, write_mstateen,
> + .min_priv_ver = PRIV_VERSION_1_12_0 },
> + [CSR_MSTATEEN1H] = { "mstateen1h", mstateen, read_mstateenh,
> + write_mstateenh,
> + .min_priv_ver = PRIV_VERSION_1_12_0 },
> + [CSR_MSTATEEN2] = { "mstateen2", mstateen, read_mstateen, write_mstateen,
> + .min_priv_ver = PRIV_VERSION_1_12_0 },
> + [CSR_MSTATEEN2H] = { "mstateen2h", mstateen, read_mstateenh,
> + write_mstateenh,
> + .min_priv_ver = PRIV_VERSION_1_12_0 },
> + [CSR_MSTATEEN3] = { "mstateen3", mstateen, read_mstateen, write_mstateen,
> + .min_priv_ver = PRIV_VERSION_1_12_0 },
> + [CSR_MSTATEEN3H] = { "mstateen3h", mstateen, read_mstateenh,
> + write_mstateenh,
> + .min_priv_ver = PRIV_VERSION_1_12_0 },
> +
> + [CSR_HSTATEEN0] = { "hstateen0", hstateen, read_hstateen, write_hstateen,
> + .min_priv_ver = PRIV_VERSION_1_12_0 },
> + [CSR_HSTATEEN0H] = { "hstateen0h", hstateen, read_hstateenh,
> + write_hstateenh,
> + .min_priv_ver = PRIV_VERSION_1_12_0 },
> + [CSR_HSTATEEN1] = { "hstateen1", hstateen, read_hstateen, write_hstateen,
> + .min_priv_ver = PRIV_VERSION_1_12_0 },
> + [CSR_HSTATEEN1H] = { "hstateen1h", hstateen, read_hstateenh,
> + write_hstateenh,
> + .min_priv_ver = PRIV_VERSION_1_12_0 },
> + [CSR_HSTATEEN2] = { "hstateen2", hstateen, read_hstateen, write_hstateen,
> + .min_priv_ver = PRIV_VERSION_1_12_0 },
> + [CSR_HSTATEEN2H] = { "hstateen2h", hstateen, read_hstateenh,
> + write_hstateenh,
> + .min_priv_ver = PRIV_VERSION_1_12_0 },
> + [CSR_HSTATEEN3] = { "hstateen3", hstateen, read_hstateen, write_hstateen,
> + .min_priv_ver = PRIV_VERSION_1_12_0 },
> + [CSR_HSTATEEN3H] = { "hstateen3h", hstateen, read_hstateenh,
> + write_hstateenh,
> + .min_priv_ver = PRIV_VERSION_1_12_0 },
> +
> + [CSR_SSTATEEN0] = { "sstateen0", sstateen, read_sstateen, write_sstateen,
> + .min_priv_ver = PRIV_VERSION_1_12_0 },
> + [CSR_SSTATEEN1] = { "sstateen1", sstateen, read_sstateen, write_sstateen,
> + .min_priv_ver = PRIV_VERSION_1_12_0 },
> + [CSR_SSTATEEN2] = { "sstateen2", sstateen, read_sstateen, write_sstateen,
> + .min_priv_ver = PRIV_VERSION_1_12_0 },
> + [CSR_SSTATEEN3] = { "sstateen3", sstateen, read_sstateen, write_sstateen,
> + .min_priv_ver = PRIV_VERSION_1_12_0 },
> /* Supervisor Trap Setup */
> [CSR_SSTATUS] = { "sstatus", smode, read_sstatus,
> write_sstatus, NULL,
> read_sstatus_i128
> },
> diff --git a/target/riscv/machine.c b/target/riscv/machine.c
> index 243f567949..40e146c578 100644
> --- a/target/riscv/machine.c
> +++ b/target/riscv/machine.c
> @@ -231,6 +231,26 @@ static int riscv_cpu_post_load(void *opaque, int
> version_id)
> return 0;
> }
>
> +static bool smstateen_needed(void *opaque)
> +{
> + RISCVCPU *cpu = opaque;
> +
> + return cpu->cfg.ext_smstateen;
> +}
> +
> +static const VMStateDescription vmstate_smstateen = {
> + .name = "cpu/smtateen",
> + .version_id = 1,
> + .minimum_version_id = 1,
> + .needed = smstateen_needed,
> + .fields = (VMStateField[]) {
> + VMSTATE_UINT64_ARRAY(env.mstateen, RISCVCPU, 4),
> + VMSTATE_UINT64_ARRAY(env.hstateen, RISCVCPU, 4),
> + VMSTATE_UINT64_ARRAY(env.sstateen, RISCVCPU, 4),
> + VMSTATE_END_OF_LIST()
> + }
> +};
> +
> static bool envcfg_needed(void *opaque)
> {
> RISCVCPU *cpu = opaque;
> @@ -315,6 +335,7 @@ const VMStateDescription vmstate_riscv_cpu = {
> &vmstate_rv128,
> &vmstate_kvmtimer,
> &vmstate_envcfg,
> + &vmstate_smstateen,
> NULL
> }
> };
> --
> 2.17.1
>
>