From: Weiwei Li <liweiwei@iscas.ac.cn>
To: Mayuresh Chitale <mchitale@ventanamicro.com>,
qemu-devel@nongnu.org, qemu-riscv@nongnu.org
Cc: alistair.francis@wdc.com
Subject: Re: [PATCH v7 1/4] target/riscv: Add smstateen support
Date: Wed, 3 Aug 2022 16:15:12 +0800 [thread overview]
Message-ID: <0757f313-e881-4379-0bad-31df2b41adec@iscas.ac.cn> (raw)
In-Reply-To: <20220801171843.72986-2-mchitale@ventanamicro.com>
在 2022/8/2 上午1:18, Mayuresh Chitale 写道:
> 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.h | 4 +
> target/riscv/cpu_bits.h | 37 ++++
> target/riscv/csr.c | 369 ++++++++++++++++++++++++++++++++++++++++
> target/riscv/machine.c | 21 +++
> 4 files changed, 431 insertions(+)
>
> diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h
> index 4be4b82a83..6bff935c57 100644
> --- a/target/riscv/cpu.h
> +++ b/target/riscv/cpu.h
> @@ -354,6 +354,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
> @@ -427,6 +430,7 @@ struct RISCVCPUConfig {
> bool ext_ifencei;
> bool ext_icsr;
> bool ext_zihintpause;
> + bool ext_smstateen;
> bool ext_svinval;
> bool ext_svnapot;
> bool ext_svpbmt;
> diff --git a/target/riscv/cpu_bits.h b/target/riscv/cpu_bits.h
> index 6be5a9e9f0..c773e0d310 100644
> --- a/target/riscv/cpu_bits.h
> +++ b/target/riscv/cpu_bits.h
> @@ -199,6 +199,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
> @@ -242,6 +248,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
> @@ -283,6 +299,27 @@
> #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 (1ULL << 0)
> +#define SMSTATEEN0_FCSR (1ULL << 1)
> +#define SMSTATEEN0_HSCONTXT (1ULL << 57)
> +#define SMSTATEEN0_IMSIC (1ULL << 58)
> +#define SMSTATEEN0_AIA (1ULL << 59)
> +#define SMSTATEEN0_SVSLCT (1ULL << 60)
> +#define SMSTATEEN0_HSENVCFG (1ULL << 62)
> +#define SMSTATEEN_STATEEN (1ULL << 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 0fb042b2fd..ad1642fb9b 100644
> --- a/target/riscv/csr.c
> +++ b/target/riscv/csr.c
> @@ -346,6 +346,68 @@ static RISCVException umode32(CPURISCVState *env, int csrno)
> return umode(env, 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_pred(CPURISCVState *env, int csrno, int base)
> +{
> + CPUState *cs = env_cpu(env);
> + RISCVCPU *cpu = RISCV_CPU(cs);
> +
> + if (!cpu->cfg.ext_smstateen) {
> + return RISCV_EXCP_ILLEGAL_INST;
> + }
> +
> + if (!(env->mstateen[csrno - base] & SMSTATEEN_STATEEN)) {
> + return RISCV_EXCP_ILLEGAL_INST;
> + }
> +
mstateen only control the access from less-privilege levels. If the
access is from M mode, it will always
be allowed. So I think we should add check for current priv is less
than M mode here.
Similar to sstateen.
Regards,
Weiwei Li
> + return hmode(env, csrno);
> +}
> +
> +static RISCVException hstateen(CPURISCVState *env, int csrno)
> +{
> + return hstateen_pred(env, csrno, CSR_HSTATEEN0);
> +}
> +
> +static RISCVException hstateenh(CPURISCVState *env, int csrno)
> +{
> + return hstateen_pred(env, csrno, CSR_HSTATEEN0H);
> +}
> +
> +static RISCVException sstateen(CPURISCVState *env, int csrno)
> +{
> + bool virt = riscv_cpu_virt_enabled(env);
> + int index = csrno - CSR_SSTATEEN0;
> + CPUState *cs = env_cpu(env);
> + RISCVCPU *cpu = RISCV_CPU(cs);
> +
> + if (!cpu->cfg.ext_smstateen) {
> + return RISCV_EXCP_ILLEGAL_INST;
> + }
> +
> + if (!(env->mstateen[index] & SMSTATEEN_STATEEN)) {
> + return RISCV_EXCP_ILLEGAL_INST;
> + }
> +
> + if (virt) {
> + if (!(env->hstateen[index] & SMSTATEEN_STATEEN)) {
> + return RISCV_EXCP_VIRT_INSTRUCTION_FAULT;
> + }
> + }
> +
> + return smode(env, csrno);
> +}
> +
> /* Checks if PointerMasking registers could be accessed */
> static RISCVException pointer_masking(CPURISCVState *env, int csrno)
> {
> @@ -1706,6 +1768,263 @@ 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,
> + uint64_t wr_mask, target_ulong new_val)
> +{
> + uint64_t *reg;
> +
> + reg = &env->mstateen[csrno - CSR_MSTATEEN0];
> + write_smstateen(env, reg, wr_mask, new_val);
> +
> + return RISCV_EXCP_NONE;
> +}
> +
> +static RISCVException write_mstateen0(CPURISCVState *env, int csrno,
> + target_ulong new_val)
> +{
> + uint64_t wr_mask = SMSTATEEN_STATEEN;
> +
> + return write_mstateen(env, csrno, wr_mask, new_val);
> +}
> +
> +static RISCVException write_mstateen1(CPURISCVState *env, int csrno,
> + target_ulong new_val)
> +{
> + return write_mstateen(env, csrno, SMSTATEEN_STATEEN, new_val);
> +}
> +
> +static RISCVException write_mstateen2(CPURISCVState *env, int csrno,
> + target_ulong new_val)
> +{
> + return write_mstateen(env, csrno, SMSTATEEN_STATEEN, new_val);
> +}
> +
> +static RISCVException write_mstateen3(CPURISCVState *env, int csrno,
> + target_ulong new_val)
> +{
> + return write_mstateen(env, csrno, SMSTATEEN_STATEEN, new_val);
> +}
> +
> +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,
> + uint64_t wr_mask, target_ulong new_val)
> +{
> + uint64_t *reg, val;
> +
> + 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 write_mstateen0h(CPURISCVState *env, int csrno,
> + target_ulong new_val)
> +{
> + uint64_t wr_mask = SMSTATEEN_STATEEN;
> +
> + return write_mstateenh(env, csrno, wr_mask, new_val);
> +}
> +
> +static RISCVException write_mstateen1h(CPURISCVState *env, int csrno,
> + target_ulong new_val)
> +{
> + return write_mstateenh(env, csrno, SMSTATEEN_STATEEN, new_val);
> +}
> +
> +static RISCVException write_mstateen2h(CPURISCVState *env, int csrno,
> + target_ulong new_val)
> +{
> + return write_mstateenh(env, csrno, SMSTATEEN_STATEEN, new_val);
> +}
> +
> +static RISCVException write_mstateen3h(CPURISCVState *env, int csrno,
> + target_ulong new_val)
> +{
> + return write_mstateenh(env, csrno, SMSTATEEN_STATEEN, new_val);
> +}
> +
> +static RISCVException read_hstateen(CPURISCVState *env, int csrno,
> + target_ulong *val)
> +{
> + int index = csrno - CSR_HSTATEEN0;
> +
> + *val = env->hstateen[index] & env->mstateen[index];
> +
> + return RISCV_EXCP_NONE;
> +}
> +
> +static RISCVException write_hstateen(CPURISCVState *env, int csrno,
> + uint64_t mask, target_ulong new_val)
> +{
> + int index = csrno - CSR_HSTATEEN0;
> + uint64_t *reg, wr_mask;
> +
> + reg = &env->hstateen[index];
> + wr_mask = env->mstateen[index] & mask;
> + write_smstateen(env, reg, wr_mask, new_val);
> +
> + return RISCV_EXCP_NONE;
> +}
> +
> +static RISCVException write_hstateen0(CPURISCVState *env, int csrno,
> + target_ulong new_val)
> +{
> + uint64_t wr_mask = SMSTATEEN_STATEEN;
> +
> + return write_hstateen(env, csrno, wr_mask, new_val);
> +}
> +
> +static RISCVException write_hstateen1(CPURISCVState *env, int csrno,
> + target_ulong new_val)
> +{
> + return write_hstateen(env, csrno, SMSTATEEN_STATEEN, new_val);
> +}
> +
> +static RISCVException write_hstateen2(CPURISCVState *env, int csrno,
> + target_ulong new_val)
> +{
> + return write_hstateen(env, csrno, SMSTATEEN_STATEEN, new_val);
> +}
> +
> +static RISCVException write_hstateen3(CPURISCVState *env, int csrno,
> + target_ulong new_val)
> +{
> + return write_hstateen(env, csrno, SMSTATEEN_STATEEN, new_val);
> +}
> +
> +static RISCVException read_hstateenh(CPURISCVState *env, int csrno,
> + target_ulong *val)
> +{
> + int index = csrno - CSR_HSTATEEN0H;
> +
> + *val = (env->hstateen[index] >> 32) & (env->mstateen[index] >> 32);
> +
> + return RISCV_EXCP_NONE;
> +}
> +
> +static RISCVException write_hstateenh(CPURISCVState *env, int csrno,
> + uint64_t mask, target_ulong new_val)
> +{
> + int index = csrno - CSR_HSTATEEN0H;
> + uint64_t *reg, wr_mask, val;
> +
> + reg = &env->hstateen[index];
> + val = (uint64_t)new_val << 32;
> + val |= *reg & 0xFFFFFFFF;
> + wr_mask = env->mstateen[index] & mask;
> + write_smstateen(env, reg, wr_mask, val);
> +
> + return RISCV_EXCP_NONE;
> +}
> +
> +static RISCVException write_hstateen0h(CPURISCVState *env, int csrno,
> + target_ulong new_val)
> +{
> + uint64_t wr_mask = SMSTATEEN_STATEEN;
> +
> + return write_hstateenh(env, csrno, wr_mask, new_val);
> +}
> +
> +static RISCVException write_hstateen1h(CPURISCVState *env, int csrno,
> + target_ulong new_val)
> +{
> + return write_hstateenh(env, csrno, SMSTATEEN_STATEEN, new_val);
> +}
> +
> +static RISCVException write_hstateen2h(CPURISCVState *env, int csrno,
> + target_ulong new_val)
> +{
> + return write_hstateenh(env, csrno, SMSTATEEN_STATEEN, new_val);
> +}
> +
> +static RISCVException write_hstateen3h(CPURISCVState *env, int csrno,
> + target_ulong new_val)
> +{
> + return write_hstateenh(env, csrno, SMSTATEEN_STATEEN, new_val);
> +}
> +
> +static RISCVException read_sstateen(CPURISCVState *env, int csrno,
> + target_ulong *val)
> +{
> + bool virt = riscv_cpu_virt_enabled(env);
> + int index = csrno - CSR_SSTATEEN0;
> +
> + *val = env->sstateen[index] & env->mstateen[index];
> + if (virt) {
> + *val &= env->hstateen[index];
> + }
> +
> + return RISCV_EXCP_NONE;
> +}
> +
> +static RISCVException write_sstateen(CPURISCVState *env, int csrno,
> + uint64_t mask, target_ulong new_val)
> +{
> + bool virt = riscv_cpu_virt_enabled(env);
> + int index = csrno - CSR_SSTATEEN0;
> + uint64_t wr_mask;
> + uint64_t *reg;
> +
> + wr_mask = env->mstateen[index] & mask;
> + if (virt) {
> + wr_mask &= env->hstateen[index];
> + }
> +
> + reg = &env->sstateen[index];
> + write_smstateen(env, reg, wr_mask, new_val);
> +
> + return RISCV_EXCP_NONE;
> +}
> +
> +static RISCVException write_sstateen0(CPURISCVState *env, int csrno,
> + target_ulong new_val)
> +{
> + uint64_t wr_mask = SMSTATEEN_STATEEN;
> +
> + return write_sstateen(env, csrno, wr_mask, new_val);
> +}
> +
> +static RISCVException write_sstateen1(CPURISCVState *env, int csrno,
> + target_ulong new_val)
> +{
> + return write_sstateen(env, csrno, SMSTATEEN_STATEEN, new_val);
> +}
> +
> +static RISCVException write_sstateen2(CPURISCVState *env, int csrno,
> + target_ulong new_val)
> +{
> + return write_sstateen(env, csrno, SMSTATEEN_STATEEN, new_val);
> +}
> +
> +static RISCVException write_sstateen3(CPURISCVState *env, int csrno,
> + target_ulong new_val)
> +{
> + return write_sstateen(env, csrno, SMSTATEEN_STATEEN, new_val);
> +}
> +
> static RISCVException rmw_mip64(CPURISCVState *env, int csrno,
> uint64_t *ret_val,
> uint64_t new_val, uint64_t wr_mask)
> @@ -3569,6 +3888,56 @@ 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_mstateen0,
> + .min_priv_ver = PRIV_VERSION_1_12_0 },
> + [CSR_MSTATEEN0H] = { "mstateen0h", mstateen, read_mstateenh,
> + write_mstateen0h,
> + .min_priv_ver = PRIV_VERSION_1_12_0 },
> + [CSR_MSTATEEN1] = { "mstateen1", mstateen, read_mstateen, write_mstateen1,
> + .min_priv_ver = PRIV_VERSION_1_12_0 },
> + [CSR_MSTATEEN1H] = { "mstateen1h", mstateen, read_mstateenh,
> + write_mstateen1h,
> + .min_priv_ver = PRIV_VERSION_1_12_0 },
> + [CSR_MSTATEEN2] = { "mstateen2", mstateen, read_mstateen, write_mstateen2,
> + .min_priv_ver = PRIV_VERSION_1_12_0 },
> + [CSR_MSTATEEN2H] = { "mstateen2h", mstateen, read_mstateenh,
> + write_mstateen2h,
> + .min_priv_ver = PRIV_VERSION_1_12_0 },
> + [CSR_MSTATEEN3] = { "mstateen3", mstateen, read_mstateen, write_mstateen3,
> + .min_priv_ver = PRIV_VERSION_1_12_0 },
> + [CSR_MSTATEEN3H] = { "mstateen3h", mstateen, read_mstateenh,
> + write_mstateen3h,
> + .min_priv_ver = PRIV_VERSION_1_12_0 },
> + [CSR_HSTATEEN0] = { "hstateen0", hstateen, read_hstateen, write_hstateen0,
> + .min_priv_ver = PRIV_VERSION_1_12_0 },
> + [CSR_HSTATEEN0H] = { "hstateen0h", hstateenh, read_hstateenh,
> + write_hstateen0h,
> + .min_priv_ver = PRIV_VERSION_1_12_0 },
> + [CSR_HSTATEEN1] = { "hstateen1", hstateen, read_hstateen, write_hstateen1,
> + .min_priv_ver = PRIV_VERSION_1_12_0 },
> + [CSR_HSTATEEN1H] = { "hstateen1h", hstateenh, read_hstateenh,
> + write_hstateen1h,
> + .min_priv_ver = PRIV_VERSION_1_12_0 },
> + [CSR_HSTATEEN2] = { "hstateen2", hstateen, read_hstateen, write_hstateen2,
> + .min_priv_ver = PRIV_VERSION_1_12_0 },
> + [CSR_HSTATEEN2H] = { "hstateen2h", hstateenh, read_hstateenh,
> + write_hstateen2h,
> + .min_priv_ver = PRIV_VERSION_1_12_0 },
> + [CSR_HSTATEEN3] = { "hstateen3", hstateen, read_hstateen, write_hstateen3,
> + .min_priv_ver = PRIV_VERSION_1_12_0 },
> + [CSR_HSTATEEN3H] = { "hstateen3h", hstateenh, read_hstateenh,
> + write_hstateen3h,
> + .min_priv_ver = PRIV_VERSION_1_12_0 },
> + [CSR_SSTATEEN0] = { "sstateen0", sstateen, read_sstateen, write_sstateen0,
> + .min_priv_ver = PRIV_VERSION_1_12_0 },
> + [CSR_SSTATEEN1] = { "sstateen1", sstateen, read_sstateen, write_sstateen1,
> + .min_priv_ver = PRIV_VERSION_1_12_0 },
> + [CSR_SSTATEEN2] = { "sstateen2", sstateen, read_sstateen, write_sstateen2,
> + .min_priv_ver = PRIV_VERSION_1_12_0 },
> + [CSR_SSTATEEN3] = { "sstateen3", sstateen, read_sstateen, write_sstateen3,
> + .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 dc182ca811..ef418ac19d 100644
> --- a/target/riscv/machine.c
> +++ b/target/riscv/machine.c
> @@ -262,6 +262,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;
> @@ -372,6 +392,7 @@ const VMStateDescription vmstate_riscv_cpu = {
> &vmstate_kvmtimer,
> &vmstate_envcfg,
> &vmstate_debug,
> + &vmstate_smstateen,
> NULL
> }
> };
next prev parent reply other threads:[~2022-08-03 8:19 UTC|newest]
Thread overview: 11+ messages / expand[flat|nested] mbox.gz Atom feed top
2022-08-01 17:18 [PATCH v7 0/4] RISC-V Smstateen support Mayuresh Chitale
2022-08-01 17:18 ` [PATCH v7 1/4] target/riscv: Add smstateen support Mayuresh Chitale
2022-08-03 8:15 ` Weiwei Li [this message]
2022-08-04 3:35 ` Mayuresh Chitale
2022-08-01 17:18 ` [PATCH v7 2/4] target/riscv: smstateen check for h/senvcfg Mayuresh Chitale
2022-08-03 8:24 ` Weiwei Li
2022-08-04 3:36 ` Mayuresh Chitale
2022-08-01 17:18 ` [PATCH v7 3/4] target/riscv: smstateen check for fcsr Mayuresh Chitale
2022-08-03 8:32 ` Weiwei Li
2022-08-04 3:52 ` Mayuresh Chitale
2022-08-01 17:18 ` [PATCH v7 4/4] target/riscv: smstateen knobs Mayuresh Chitale
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=0757f313-e881-4379-0bad-31df2b41adec@iscas.ac.cn \
--to=liweiwei@iscas.ac.cn \
--cc=alistair.francis@wdc.com \
--cc=mchitale@ventanamicro.com \
--cc=qemu-devel@nongnu.org \
--cc=qemu-riscv@nongnu.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.