From: "Alex Bennée" <alex.bennee@linaro.org>
To: Richard Henderson <richard.henderson@linaro.org>
Cc: peter.maydell@linaro.org, qemu-devel@nongnu.org
Subject: Re: [PATCH v2 02/14] target/arm: Add mmu_idx for EL1 and EL2 w/ PAN enabled
Date: Mon, 03 Feb 2020 11:54:08 +0000 [thread overview]
Message-ID: <87sgjrantr.fsf@linaro.org> (raw)
In-Reply-To: <20200202010439.6410-3-richard.henderson@linaro.org>
Richard Henderson <richard.henderson@linaro.org> writes:
> To implement PAN, we will want to swap, for short periods
> of time, to a different privileged mmu_idx. In addition,
> we cannot do this with flushing alone, because the AT*
> instructions have both PAN and PAN-less versions.
>
> Add the ARMMMUIdx*_PAN constants where necessary next to
> the corresponding ARMMMUIdx* constant.
>
> Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
> ---
> target/arm/cpu-param.h | 2 +-
> target/arm/cpu.h | 33 ++++++++++++++-------
> target/arm/internals.h | 9 ++++++
> target/arm/helper.c | 60 +++++++++++++++++++++++++++++++-------
> target/arm/translate-a64.c | 3 ++
> target/arm/translate.c | 2 ++
> 6 files changed, 87 insertions(+), 22 deletions(-)
>
> diff --git a/target/arm/cpu-param.h b/target/arm/cpu-param.h
> index 18ac562346..d593b60b28 100644
> --- a/target/arm/cpu-param.h
> +++ b/target/arm/cpu-param.h
> @@ -29,6 +29,6 @@
> # define TARGET_PAGE_BITS_MIN 10
> #endif
>
> -#define NB_MMU_MODES 9
> +#define NB_MMU_MODES 12
>
> #endif
> diff --git a/target/arm/cpu.h b/target/arm/cpu.h
> index 0b3036c484..c63bceaaa5 100644
> --- a/target/arm/cpu.h
> +++ b/target/arm/cpu.h
> @@ -2751,20 +2751,24 @@ bool write_cpustate_to_list(ARMCPU *cpu, bool kvm_sync);
> * 5. we want to be able to use the TLB for accesses done as part of a
> * stage1 page table walk, rather than having to walk the stage2 page
> * table over and over.
> + * 6. we need separate EL1/EL2 mmu_idx for handling the Privileged Access
> + * Never (PAN) bit within PSTATE.
> *
> * This gives us the following list of cases:
> *
> * NS EL0 EL1&0 stage 1+2 (aka NS PL0)
> * NS EL1 EL1&0 stage 1+2 (aka NS PL1)
> + * NS EL1 EL1&0 stage 1+2 +PAN
> * NS EL0 EL2&0
> - * NS EL2 EL2&0
> + * NS EL2 EL2&0 +PAN
> * NS EL2 (aka NS PL2)
> * S EL0 EL1&0 (aka S PL0)
> * S EL1 EL1&0 (not used if EL3 is 32 bit)
> + * S EL1 EL1&0 +PAN
> * S EL3 (aka S PL1)
> * NS EL1&0 stage 2
> *
> - * for a total of 9 different mmu_idx.
> + * for a total of 12 different mmu_idx.
> *
> * R profile CPUs have an MPU, but can use the same set of MMU indexes
> * as A profile. They only need to distinguish NS EL0 and NS EL1 (and
> @@ -2819,19 +2823,22 @@ typedef enum ARMMMUIdx {
> /*
> * A-profile.
> */
> - ARMMMUIdx_E10_0 = 0 | ARM_MMU_IDX_A,
> - ARMMMUIdx_E20_0 = 1 | ARM_MMU_IDX_A,
> + ARMMMUIdx_E10_0 = 0 | ARM_MMU_IDX_A,
> + ARMMMUIdx_E20_0 = 1 | ARM_MMU_IDX_A,
>
> - ARMMMUIdx_E10_1 = 2 | ARM_MMU_IDX_A,
> + ARMMMUIdx_E10_1 = 2 | ARM_MMU_IDX_A,
> + ARMMMUIdx_E10_1_PAN = 3 | ARM_MMU_IDX_A,
>
> - ARMMMUIdx_E2 = 3 | ARM_MMU_IDX_A,
> - ARMMMUIdx_E20_2 = 4 | ARM_MMU_IDX_A,
> + ARMMMUIdx_E2 = 4 | ARM_MMU_IDX_A,
> + ARMMMUIdx_E20_2 = 5 | ARM_MMU_IDX_A,
> + ARMMMUIdx_E20_2_PAN = 6 | ARM_MMU_IDX_A,
>
> - ARMMMUIdx_SE10_0 = 5 | ARM_MMU_IDX_A,
> - ARMMMUIdx_SE10_1 = 6 | ARM_MMU_IDX_A,
> - ARMMMUIdx_SE3 = 7 | ARM_MMU_IDX_A,
> + ARMMMUIdx_SE10_0 = 7 | ARM_MMU_IDX_A,
> + ARMMMUIdx_SE10_1 = 8 | ARM_MMU_IDX_A,
> + ARMMMUIdx_SE10_1_PAN = 9 | ARM_MMU_IDX_A,
> + ARMMMUIdx_SE3 = 10 | ARM_MMU_IDX_A,
>
> - ARMMMUIdx_Stage2 = 8 | ARM_MMU_IDX_A,
> + ARMMMUIdx_Stage2 = 11 | ARM_MMU_IDX_A,
>
> /*
> * These are not allocated TLBs and are used only for AT system
> @@ -2839,6 +2846,7 @@ typedef enum ARMMMUIdx {
> */
> ARMMMUIdx_Stage1_E0 = 0 | ARM_MMU_IDX_NOTLB,
> ARMMMUIdx_Stage1_E1 = 1 | ARM_MMU_IDX_NOTLB,
> + ARMMMUIdx_Stage1_E1_PAN = 2 | ARM_MMU_IDX_NOTLB,
>
> /*
> * M-profile.
> @@ -2864,10 +2872,13 @@ typedef enum ARMMMUIdxBit {
> TO_CORE_BIT(E10_0),
> TO_CORE_BIT(E20_0),
> TO_CORE_BIT(E10_1),
> + TO_CORE_BIT(E10_1_PAN),
> TO_CORE_BIT(E2),
> TO_CORE_BIT(E20_2),
> + TO_CORE_BIT(E20_2_PAN),
> TO_CORE_BIT(SE10_0),
> TO_CORE_BIT(SE10_1),
> + TO_CORE_BIT(SE10_1_PAN),
> TO_CORE_BIT(SE3),
> TO_CORE_BIT(Stage2),
>
> diff --git a/target/arm/internals.h b/target/arm/internals.h
> index 1f8ee5f573..6be8b2d1a9 100644
> --- a/target/arm/internals.h
> +++ b/target/arm/internals.h
> @@ -843,12 +843,16 @@ static inline bool regime_has_2_ranges(ARMMMUIdx mmu_idx)
> switch (mmu_idx) {
> case ARMMMUIdx_Stage1_E0:
> case ARMMMUIdx_Stage1_E1:
> + case ARMMMUIdx_Stage1_E1_PAN:
> case ARMMMUIdx_E10_0:
> case ARMMMUIdx_E10_1:
> + case ARMMMUIdx_E10_1_PAN:
> case ARMMMUIdx_E20_0:
> case ARMMMUIdx_E20_2:
> + case ARMMMUIdx_E20_2_PAN:
> case ARMMMUIdx_SE10_0:
> case ARMMMUIdx_SE10_1:
> + case ARMMMUIdx_SE10_1_PAN:
> return true;
> default:
> return false;
> @@ -861,10 +865,13 @@ static inline bool regime_is_secure(CPUARMState *env, ARMMMUIdx mmu_idx)
> switch (mmu_idx) {
> case ARMMMUIdx_E10_0:
> case ARMMMUIdx_E10_1:
> + case ARMMMUIdx_E10_1_PAN:
> case ARMMMUIdx_E20_0:
> case ARMMMUIdx_E20_2:
> + case ARMMMUIdx_E20_2_PAN:
> case ARMMMUIdx_Stage1_E0:
> case ARMMMUIdx_Stage1_E1:
> + case ARMMMUIdx_Stage1_E1_PAN:
> case ARMMMUIdx_E2:
> case ARMMMUIdx_Stage2:
> case ARMMMUIdx_MPrivNegPri:
> @@ -875,6 +882,7 @@ static inline bool regime_is_secure(CPUARMState *env, ARMMMUIdx mmu_idx)
> case ARMMMUIdx_SE3:
> case ARMMMUIdx_SE10_0:
> case ARMMMUIdx_SE10_1:
> + case ARMMMUIdx_SE10_1_PAN:
> case ARMMMUIdx_MSPrivNegPri:
> case ARMMMUIdx_MSUserNegPri:
> case ARMMMUIdx_MSPriv:
> @@ -1046,6 +1054,7 @@ static inline bool arm_mmu_idx_is_stage1_of_2(ARMMMUIdx mmu_idx)
> switch (mmu_idx) {
> case ARMMMUIdx_Stage1_E0:
> case ARMMMUIdx_Stage1_E1:
> + case ARMMMUIdx_Stage1_E1_PAN:
> return true;
> default:
> return false;
> diff --git a/target/arm/helper.c b/target/arm/helper.c
> index 852fd71dcc..739d2d4cc5 100644
> --- a/target/arm/helper.c
> +++ b/target/arm/helper.c
> @@ -671,6 +671,7 @@ static void tlbiall_nsnh_write(CPUARMState *env, const ARMCPRegInfo *ri,
>
> tlb_flush_by_mmuidx(cs,
> ARMMMUIdxBit_E10_1 |
> + ARMMMUIdxBit_E10_1_PAN |
> ARMMMUIdxBit_E10_0 |
> ARMMMUIdxBit_Stage2);
> }
> @@ -682,6 +683,7 @@ static void tlbiall_nsnh_is_write(CPUARMState *env, const ARMCPRegInfo *ri,
>
> tlb_flush_by_mmuidx_all_cpus_synced(cs,
> ARMMMUIdxBit_E10_1 |
> + ARMMMUIdxBit_E10_1_PAN |
> ARMMMUIdxBit_E10_0 |
> ARMMMUIdxBit_Stage2);
> }
> @@ -2700,6 +2702,7 @@ static int gt_phys_redir_timeridx(CPUARMState *env)
> switch (arm_mmu_idx(env)) {
> case ARMMMUIdx_E20_0:
> case ARMMMUIdx_E20_2:
> + case ARMMMUIdx_E20_2_PAN:
> return GTIMER_HYP;
> default:
> return GTIMER_PHYS;
> @@ -2711,6 +2714,7 @@ static int gt_virt_redir_timeridx(CPUARMState *env)
> switch (arm_mmu_idx(env)) {
> case ARMMMUIdx_E20_0:
> case ARMMMUIdx_E20_2:
> + case ARMMMUIdx_E20_2_PAN:
> return GTIMER_HYPVIRT;
> default:
> return GTIMER_VIRT;
> @@ -3337,7 +3341,9 @@ static uint64_t do_ats_write(CPUARMState *env, uint64_t value,
> format64 = arm_s1_regime_using_lpae_format(env, mmu_idx);
>
> if (arm_feature(env, ARM_FEATURE_EL2)) {
> - if (mmu_idx == ARMMMUIdx_E10_0 || mmu_idx == ARMMMUIdx_E10_1) {
> + if (mmu_idx == ARMMMUIdx_E10_0 ||
> + mmu_idx == ARMMMUIdx_E10_1 ||
> + mmu_idx == ARMMMUIdx_E10_1_PAN) {
> format64 |= env->cp15.hcr_el2 & (HCR_VM | HCR_DC);
> } else {
> format64 |= arm_current_el(env) == 2;
> @@ -3797,7 +3803,9 @@ static void vmsa_tcr_ttbr_el2_write(CPUARMState *env, const ARMCPRegInfo *ri,
> if (extract64(raw_read(env, ri) ^ value, 48, 16) &&
> (arm_hcr_el2_eff(env) & HCR_E2H)) {
> tlb_flush_by_mmuidx(env_cpu(env),
> - ARMMMUIdxBit_E20_2 | ARMMMUIdxBit_E20_0);
> + ARMMMUIdxBit_E20_2 |
> + ARMMMUIdxBit_E20_2_PAN |
> + ARMMMUIdxBit_E20_0);
> }
> raw_write(env, ri, value);
> }
> @@ -3815,6 +3823,7 @@ static void vttbr_write(CPUARMState *env, const ARMCPRegInfo *ri,
> if (raw_read(env, ri) != value) {
> tlb_flush_by_mmuidx(cs,
> ARMMMUIdxBit_E10_1 |
> + ARMMMUIdxBit_E10_1_PAN |
> ARMMMUIdxBit_E10_0 |
> ARMMMUIdxBit_Stage2);
> raw_write(env, ri, value);
> @@ -4175,12 +4184,18 @@ static int vae1_tlbmask(CPUARMState *env)
> {
> /* Since we exclude secure first, we may read HCR_EL2 directly. */
> if (arm_is_secure_below_el3(env)) {
> - return ARMMMUIdxBit_SE10_1 | ARMMMUIdxBit_SE10_0;
> + return ARMMMUIdxBit_SE10_1 |
> + ARMMMUIdxBit_SE10_1_PAN |
> + ARMMMUIdxBit_SE10_0;
> } else if ((env->cp15.hcr_el2 & (HCR_E2H | HCR_TGE))
> == (HCR_E2H | HCR_TGE)) {
> - return ARMMMUIdxBit_E20_2 | ARMMMUIdxBit_E20_0;
> + return ARMMMUIdxBit_E20_2 |
> + ARMMMUIdxBit_E20_2_PAN |
> + ARMMMUIdxBit_E20_0;
> } else {
> - return ARMMMUIdxBit_E10_1 | ARMMMUIdxBit_E10_0;
> + return ARMMMUIdxBit_E10_1 |
> + ARMMMUIdxBit_E10_1_PAN |
> + ARMMMUIdxBit_E10_0;
> }
> }
>
> @@ -4214,18 +4229,28 @@ static int alle1_tlbmask(CPUARMState *env)
> * stage 1 translations.
> */
> if (arm_is_secure_below_el3(env)) {
> - return ARMMMUIdxBit_SE10_1 | ARMMMUIdxBit_SE10_0;
> + return ARMMMUIdxBit_SE10_1 |
> + ARMMMUIdxBit_SE10_1_PAN |
> + ARMMMUIdxBit_SE10_0;
> } else if (arm_feature(env, ARM_FEATURE_EL2)) {
> - return ARMMMUIdxBit_E10_1 | ARMMMUIdxBit_E10_0 | ARMMMUIdxBit_Stage2;
> + return ARMMMUIdxBit_E10_1 |
> + ARMMMUIdxBit_E10_1_PAN |
> + ARMMMUIdxBit_E10_0 |
> + ARMMMUIdxBit_Stage2;
> } else {
> - return ARMMMUIdxBit_E10_1 | ARMMMUIdxBit_E10_0;
> + return ARMMMUIdxBit_E10_1 |
> + ARMMMUIdxBit_E10_1_PAN |
> + ARMMMUIdxBit_E10_0;
> }
> }
>
> static int alle2_tlbmask(CPUARMState *env)
> {
> /* TODO: ARMv8.4-SecEL2 */
> - return ARMMMUIdxBit_E20_0 | ARMMMUIdxBit_E20_2 | ARMMMUIdxBit_E2;
> + return ARMMMUIdxBit_E20_0 |
> + ARMMMUIdxBit_E20_2 |
> + ARMMMUIdxBit_E20_2_PAN |
> + ARMMMUIdxBit_E2;
> }
>
> static void tlbi_aa64_alle1_write(CPUARMState *env, const ARMCPRegInfo *ri,
> @@ -9215,6 +9240,7 @@ static uint32_t regime_el(CPUARMState *env, ARMMMUIdx mmu_idx)
> switch (mmu_idx) {
> case ARMMMUIdx_E20_0:
> case ARMMMUIdx_E20_2:
> + case ARMMMUIdx_E20_2_PAN:
> case ARMMMUIdx_Stage2:
> case ARMMMUIdx_E2:
> return 2;
> @@ -9223,10 +9249,13 @@ static uint32_t regime_el(CPUARMState *env, ARMMMUIdx mmu_idx)
> case ARMMMUIdx_SE10_0:
> return arm_el_is_aa64(env, 3) ? 1 : 3;
> case ARMMMUIdx_SE10_1:
> + case ARMMMUIdx_SE10_1_PAN:
> case ARMMMUIdx_Stage1_E0:
> case ARMMMUIdx_Stage1_E1:
> + case ARMMMUIdx_Stage1_E1_PAN:
> case ARMMMUIdx_E10_0:
> case ARMMMUIdx_E10_1:
> + case ARMMMUIdx_E10_1_PAN:
> case ARMMMUIdx_MPrivNegPri:
> case ARMMMUIdx_MUserNegPri:
> case ARMMMUIdx_MPriv:
> @@ -9342,6 +9371,8 @@ static inline ARMMMUIdx stage_1_mmu_idx(ARMMMUIdx mmu_idx)
> return ARMMMUIdx_Stage1_E0;
> case ARMMMUIdx_E10_1:
> return ARMMMUIdx_Stage1_E1;
> + case ARMMMUIdx_E10_1_PAN:
> + return ARMMMUIdx_Stage1_E1_PAN;
> default:
> return mmu_idx;
> }
> @@ -9388,6 +9419,7 @@ static inline bool regime_is_user(CPUARMState *env, ARMMMUIdx mmu_idx)
> return false;
> case ARMMMUIdx_E10_0:
> case ARMMMUIdx_E10_1:
> + case ARMMMUIdx_E10_1_PAN:
> g_assert_not_reached();
> }
> }
> @@ -11280,7 +11312,9 @@ bool get_phys_addr(CPUARMState *env, target_ulong address,
> target_ulong *page_size,
> ARMMMUFaultInfo *fi, ARMCacheAttrs *cacheattrs)
> {
> - if (mmu_idx == ARMMMUIdx_E10_0 || mmu_idx == ARMMMUIdx_E10_1) {
> + if (mmu_idx == ARMMMUIdx_E10_0 ||
> + mmu_idx == ARMMMUIdx_E10_1 ||
> + mmu_idx == ARMMMUIdx_E10_1_PAN) {
> /* Call ourselves recursively to do the stage 1 and then stage 2
> * translations.
> */
> @@ -11807,10 +11841,13 @@ int arm_mmu_idx_to_el(ARMMMUIdx mmu_idx)
> case ARMMMUIdx_SE10_0:
> return 0;
> case ARMMMUIdx_E10_1:
> + case ARMMMUIdx_E10_1_PAN:
> case ARMMMUIdx_SE10_1:
> + case ARMMMUIdx_SE10_1_PAN:
> return 1;
> case ARMMMUIdx_E2:
> case ARMMMUIdx_E20_2:
> + case ARMMMUIdx_E20_2_PAN:
> return 2;
> case ARMMMUIdx_SE3:
> return 3;
> @@ -12027,11 +12064,14 @@ static uint32_t rebuild_hflags_a64(CPUARMState *env, int el, int fp_el,
> /* TODO: ARMv8.2-UAO */
> switch (mmu_idx) {
> case ARMMMUIdx_E10_1:
> + case ARMMMUIdx_E10_1_PAN:
> case ARMMMUIdx_SE10_1:
> + case ARMMMUIdx_SE10_1_PAN:
> /* TODO: ARMv8.3-NV */
> flags = FIELD_DP32(flags, TBFLAG_A64, UNPRIV, 1);
> break;
> case ARMMMUIdx_E20_2:
> + case ARMMMUIdx_E20_2_PAN:
> /* TODO: ARMv8.4-SecEL2 */
> /*
> * Note that E20_2 is gated by HCR_EL2.E2H == 1, but E20_0 is
> diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
> index 6e82486884..49631c2340 100644
> --- a/target/arm/translate-a64.c
> +++ b/target/arm/translate-a64.c
> @@ -124,12 +124,15 @@ static int get_a64_user_mem_index(DisasContext *s)
> */
> switch (useridx) {
> case ARMMMUIdx_E10_1:
> + case ARMMMUIdx_E10_1_PAN:
> useridx = ARMMMUIdx_E10_0;
> break;
> case ARMMMUIdx_E20_2:
> + case ARMMMUIdx_E20_2_PAN:
> useridx = ARMMMUIdx_E20_0;
> break;
> case ARMMMUIdx_SE10_1:
> + case ARMMMUIdx_SE10_1_PAN:
> useridx = ARMMMUIdx_SE10_0;
> break;
> default:
> diff --git a/target/arm/translate.c b/target/arm/translate.c
> index e11a5871d0..d58c328e08 100644
> --- a/target/arm/translate.c
> +++ b/target/arm/translate.c
> @@ -155,10 +155,12 @@ static inline int get_a32_user_mem_index(DisasContext *s)
> case ARMMMUIdx_E2: /* this one is UNPREDICTABLE */
> case ARMMMUIdx_E10_0:
> case ARMMMUIdx_E10_1:
> + case ARMMMUIdx_E10_1_PAN:
> return arm_to_core_mmu_idx(ARMMMUIdx_E10_0);
> case ARMMMUIdx_SE3:
> case ARMMMUIdx_SE10_0:
> case ARMMMUIdx_SE10_1:
> + case ARMMMUIdx_SE10_1_PAN:
> return arm_to_core_mmu_idx(ARMMMUIdx_SE10_0);
> case ARMMMUIdx_MUser:
> case ARMMMUIdx_MPriv:
--
Alex Bennée
next prev parent reply other threads:[~2020-02-03 11:55 UTC|newest]
Thread overview: 22+ messages / expand[flat|nested] mbox.gz Atom feed top
2020-02-02 1:04 [PATCH v2 00/14] target/arm: Implement PAN, ATS1E1, UAO Richard Henderson
2020-02-02 1:04 ` [PATCH v2 01/14] target/arm: Add arm_mmu_idx_is_stage1_of_2 Richard Henderson
2020-02-03 11:46 ` Alex Bennée
2020-02-02 1:04 ` [PATCH v2 02/14] target/arm: Add mmu_idx for EL1 and EL2 w/ PAN enabled Richard Henderson
2020-02-03 11:54 ` Alex Bennée [this message]
2020-02-02 1:04 ` [PATCH v2 03/14] target/arm: Add isar_feature tests for PAN + ATS1E1 Richard Henderson
2020-02-03 12:24 ` Alex Bennée
2020-02-02 1:04 ` [PATCH v2 04/14] target/arm: Move LOR regdefs to file scope Richard Henderson
2020-02-03 12:25 ` Alex Bennée
2020-02-02 1:04 ` [PATCH v2 05/14] target/arm: Update MSR access for PAN Richard Henderson
2020-02-03 13:37 ` Alex Bennée
2020-02-02 1:04 ` [PATCH v2 06/14] target/arm: Update arm_mmu_idx_el " Richard Henderson
2020-02-03 13:38 ` Alex Bennée
2020-02-02 1:04 ` [PATCH v2 07/14] target/arm: Enforce PAN semantics in get_S1prot Richard Henderson
2020-02-03 14:30 ` Alex Bennée
2020-02-02 1:04 ` [PATCH v2 08/14] target/arm: Set PAN bit as required on exception entry Richard Henderson
2020-02-02 1:04 ` [PATCH v2 09/14] target/arm: Implement ATS1E1 system registers Richard Henderson
2020-02-02 1:04 ` [PATCH v2 10/14] target/arm: Enable ARMv8.2-ATS1E1 in -cpu max Richard Henderson
2020-02-02 1:04 ` [PATCH v2 11/14] target/arm: Add ID_AA64MMFR2_EL1 Richard Henderson
2020-02-02 1:04 ` [PATCH v2 12/14] target/arm: Update MSR access to UAO Richard Henderson
2020-02-02 1:04 ` [PATCH v2 13/14] target/arm: Implement UAO semantics Richard Henderson
2020-02-02 1:04 ` [PATCH v2 14/14] target/arm: Enable ARMv8.2-UAO in -cpu max Richard Henderson
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=87sgjrantr.fsf@linaro.org \
--to=alex.bennee@linaro.org \
--cc=peter.maydell@linaro.org \
--cc=qemu-devel@nongnu.org \
--cc=richard.henderson@linaro.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.