All of lore.kernel.org
 help / color / mirror / Atom feed
From: Richard Henderson <richard.henderson@linaro.org>
To: qemu-devel@nongnu.org
Cc: peter.maydell@linaro.org
Subject: [PATCH 03/11] target/arm: Add mmu_idx for EL1 and EL2 w/ PAN enabled
Date: Tue,  3 Dec 2019 14:53:25 -0800	[thread overview]
Message-ID: <20191203225333.17055-4-richard.henderson@linaro.org> (raw)
In-Reply-To: <20191203225333.17055-1-richard.henderson@linaro.org>

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.

Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
 target/arm/cpu-param.h     |  2 +-
 target/arm/cpu.h           | 35 +++++++++++++--------
 target/arm/internals.h     |  9 ++++++
 target/arm/helper.c        | 63 +++++++++++++++++++++++++++++++-------
 target/arm/translate-a64.c |  2 ++
 target/arm/translate.c     |  2 ++
 6 files changed, 88 insertions(+), 25 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 22935e4433..22c5706835 100644
--- a/target/arm/cpu.h
+++ b/target/arm/cpu.h
@@ -2715,20 +2715,22 @@ 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 Priviledged Access
+ *     Never (PAN) bit within PSTATE.
  *
  * This gives us the following list of cases:
  *
  * NS EL0 (aka NS PL0) EL1&0 stage 1+2
- * NS EL1 (aka NS PL1) EL1&0 stage 1+2
+ * NS EL1 (aka NS PL1) 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 (aka S PL0)
- * S EL1 (not used if EL3 is 32 bit)
+ * S EL1 (not used if EL3 is 32 bit) (+PAN)
  * S EL3 (aka S PL1)
  * NS EL0&1 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
@@ -2783,19 +2785,22 @@ typedef enum ARMMMUIdx {
     /*
      * A-profile.
      */
-    ARMMMUIdx_EL10_0 = 0 | ARM_MMU_IDX_A,
-    ARMMMUIdx_EL20_0 = 1 | ARM_MMU_IDX_A,
+    ARMMMUIdx_EL10_0 =     0 | ARM_MMU_IDX_A,
+    ARMMMUIdx_EL20_0 =     1 | ARM_MMU_IDX_A,
 
-    ARMMMUIdx_EL10_1 = 2 | ARM_MMU_IDX_A,
+    ARMMMUIdx_EL10_1 =     2 | ARM_MMU_IDX_A,
+    ARMMMUIdx_EL10_1_PAN = 3 | ARM_MMU_IDX_A,
 
-    ARMMMUIdx_E2 =     3 | ARM_MMU_IDX_A,
-    ARMMMUIdx_EL20_2 = 4 | ARM_MMU_IDX_A,
+    ARMMMUIdx_E2 =         4 | ARM_MMU_IDX_A,
+    ARMMMUIdx_EL20_2 =     5 | ARM_MMU_IDX_A,
+    ARMMMUIdx_EL20_2_PAN = 6 | ARM_MMU_IDX_A,
 
-    ARMMMUIdx_SE0 =    5 | ARM_MMU_IDX_A,
-    ARMMMUIdx_SE1 =    6 | ARM_MMU_IDX_A,
-    ARMMMUIdx_SE3 =    7 | ARM_MMU_IDX_A,
+    ARMMMUIdx_SE0 =        7 | ARM_MMU_IDX_A,
+    ARMMMUIdx_SE1 =        8 | ARM_MMU_IDX_A,
+    ARMMMUIdx_SE1_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
@@ -2803,6 +2808,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.
@@ -2828,10 +2834,13 @@ typedef enum ARMMMUIdxBit {
     TO_CORE_BIT(EL10_0),
     TO_CORE_BIT(EL20_0),
     TO_CORE_BIT(EL10_1),
+    TO_CORE_BIT(EL10_1_PAN),
     TO_CORE_BIT(E2),
     TO_CORE_BIT(EL20_2),
+    TO_CORE_BIT(EL20_2_PAN),
     TO_CORE_BIT(SE0),
     TO_CORE_BIT(SE1),
+    TO_CORE_BIT(SE1_PAN),
     TO_CORE_BIT(SE3),
     TO_CORE_BIT(Stage2),
 
diff --git a/target/arm/internals.h b/target/arm/internals.h
index 850f204f14..2408953031 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_EL10_0:
     case ARMMMUIdx_EL10_1:
+    case ARMMMUIdx_EL10_1_PAN:
     case ARMMMUIdx_EL20_0:
     case ARMMMUIdx_EL20_2:
+    case ARMMMUIdx_EL20_2_PAN:
     case ARMMMUIdx_SE0:
     case ARMMMUIdx_SE1:
+    case ARMMMUIdx_SE1_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_EL10_0:
     case ARMMMUIdx_EL10_1:
+    case ARMMMUIdx_EL10_1_PAN:
     case ARMMMUIdx_EL20_0:
     case ARMMMUIdx_EL20_2:
+    case ARMMMUIdx_EL20_2_PAN:
     case ARMMMUIdx_Stage1_E0:
     case ARMMMUIdx_Stage1_E1:
+    case ARMMMUIdx_Stage1_E1_PAN:
     case ARMMMUIdx_E2:
     case ARMMMUIdx_Stage2:
     case ARMMMUIdx_MPrivNegPri:
@@ -874,6 +881,7 @@ static inline bool regime_is_secure(CPUARMState *env, ARMMMUIdx mmu_idx)
         return false;
     case ARMMMUIdx_SE0:
     case ARMMMUIdx_SE1:
+    case ARMMMUIdx_SE1_PAN:
     case ARMMMUIdx_SE3:
     case ARMMMUIdx_MSPrivNegPri:
     case ARMMMUIdx_MSUserNegPri:
@@ -1039,6 +1047,7 @@ static inline bool arm_mmu_idx_is_stage1(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 fdb86ea427..4e3fe00316 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_EL10_1 |
+                        ARMMMUIdxBit_EL10_1_PAN |
                         ARMMMUIdxBit_EL10_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_EL10_1 |
+                                        ARMMMUIdxBit_EL10_1_PAN |
                                         ARMMMUIdxBit_EL10_0 |
                                         ARMMMUIdxBit_Stage2);
 }
@@ -2660,6 +2662,7 @@ static int gt_phys_redir_timeridx(CPUARMState *env)
     switch (arm_mmu_idx(env)) {
     case ARMMMUIdx_EL20_0:
     case ARMMMUIdx_EL20_2:
+    case ARMMMUIdx_EL20_2_PAN:
         return GTIMER_HYP;
     default:
         return GTIMER_PHYS;
@@ -2671,6 +2674,7 @@ static int gt_virt_redir_timeridx(CPUARMState *env)
     switch (arm_mmu_idx(env)) {
     case ARMMMUIdx_EL20_0:
     case ARMMMUIdx_EL20_2:
+    case ARMMMUIdx_EL20_2_PAN:
         return GTIMER_HYPVIRT;
     default:
         return GTIMER_VIRT;
@@ -3288,7 +3292,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_EL10_0 || mmu_idx == ARMMMUIdx_EL10_1) {
+            if (mmu_idx == ARMMMUIdx_EL10_0 ||
+                mmu_idx == ARMMMUIdx_EL10_1 ||
+                mmu_idx == ARMMMUIdx_EL10_1_PAN) {
                 format64 |= env->cp15.hcr_el2 & (HCR_VM | HCR_DC);
             } else {
                 format64 |= arm_current_el(env) == 2;
@@ -3746,7 +3752,9 @@ static void vmsa_tcr_ttbr_el2_write(CPUARMState *env, const ARMCPRegInfo *ri,
     if ((arm_hcr_el2_eff(env) & HCR_E2H) &&
         extract64(raw_read(env, ri) ^ value, 48, 16)) {
         tlb_flush_by_mmuidx(env_cpu(env),
-                            ARMMMUIdxBit_EL20_2 | ARMMMUIdxBit_EL20_0);
+                            ARMMMUIdxBit_EL20_2 |
+                            ARMMMUIdxBit_EL20_2_PAN |
+                            ARMMMUIdxBit_EL20_0);
     }
     raw_write(env, ri, value);
 }
@@ -3764,6 +3772,7 @@ static void vttbr_write(CPUARMState *env, const ARMCPRegInfo *ri,
     if (raw_read(env, ri) != value) {
         tlb_flush_by_mmuidx(cs,
                             ARMMMUIdxBit_EL10_1 |
+                            ARMMMUIdxBit_EL10_1_PAN |
                             ARMMMUIdxBit_EL10_0 |
                             ARMMMUIdxBit_Stage2);
         raw_write(env, ri, value);
@@ -4124,12 +4133,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_SE1 | ARMMMUIdxBit_SE0;
+        return ARMMMUIdxBit_SE1 |
+               ARMMMUIdxBit_SE1_PAN |
+               ARMMMUIdxBit_SE0;
     } else if ((env->cp15.hcr_el2 & (HCR_E2H | HCR_TGE))
                == (HCR_E2H | HCR_TGE)) {
-        return ARMMMUIdxBit_EL20_2 | ARMMMUIdxBit_EL20_0;
+        return ARMMMUIdxBit_EL20_2 |
+               ARMMMUIdxBit_EL20_2_PAN |
+               ARMMMUIdxBit_EL20_0;
     } else {
-        return ARMMMUIdxBit_EL10_1 | ARMMMUIdxBit_EL10_0;
+        return ARMMMUIdxBit_EL10_1 |
+               ARMMMUIdxBit_EL10_1_PAN |
+               ARMMMUIdxBit_EL10_0;
     }
 }
 
@@ -4165,14 +4180,23 @@ static int vmalle1_tlbmask(CPUARMState *env)
      * Since we exclude secure first, we may read HCR_EL2 directly.
      */
     if (arm_is_secure_below_el3(env)) {
-        return ARMMMUIdxBit_SE1 | ARMMMUIdxBit_SE0;
+        return ARMMMUIdxBit_SE1 |
+               ARMMMUIdxBit_SE1_PAN |
+               ARMMMUIdxBit_SE0;
     } else if ((env->cp15.hcr_el2 & (HCR_E2H | HCR_TGE))
                == (HCR_E2H | HCR_TGE)) {
-        return ARMMMUIdxBit_EL20_2 | ARMMMUIdxBit_EL20_0;
+        return ARMMMUIdxBit_EL20_2 |
+               ARMMMUIdxBit_EL20_2_PAN |
+               ARMMMUIdxBit_EL20_0;
     } else if (arm_feature(env, ARM_FEATURE_EL2)) {
-        return ARMMMUIdxBit_EL10_1 | ARMMMUIdxBit_EL10_0 | ARMMMUIdxBit_Stage2;
+        return ARMMMUIdxBit_EL10_1 |
+               ARMMMUIdxBit_EL10_1_PAN |
+               ARMMMUIdxBit_EL10_0 |
+               ARMMMUIdxBit_Stage2;
     } else {
-        return ARMMMUIdxBit_EL10_1 | ARMMMUIdxBit_EL10_0;
+        return ARMMMUIdxBit_EL10_1 |
+               ARMMMUIdxBit_EL10_1_PAN |
+               ARMMMUIdxBit_EL10_0;
     }
 }
 
@@ -4188,7 +4212,9 @@ static void tlbi_aa64_alle1_write(CPUARMState *env, const ARMCPRegInfo *ri,
 static int vae2_tlbmask(CPUARMState *env)
 {
     if (arm_hcr_el2_eff(env) & HCR_E2H) {
-        return ARMMMUIdxBit_EL20_0 | ARMMMUIdxBit_EL20_2;
+        return ARMMMUIdxBit_EL20_0 |
+               ARMMMUIdxBit_EL20_2 |
+               ARMMMUIdxBit_EL20_2_PAN;
     } else {
         return ARMMMUIdxBit_E2;
     }
@@ -9080,6 +9106,7 @@ static uint32_t regime_el(CPUARMState *env, ARMMMUIdx mmu_idx)
     switch (mmu_idx) {
     case ARMMMUIdx_EL20_0:
     case ARMMMUIdx_EL20_2:
+    case ARMMMUIdx_EL20_2_PAN:
     case ARMMMUIdx_Stage2:
     case ARMMMUIdx_E2:
         return 2;
@@ -9088,10 +9115,13 @@ static uint32_t regime_el(CPUARMState *env, ARMMMUIdx mmu_idx)
     case ARMMMUIdx_SE0:
         return arm_el_is_aa64(env, 3) ? 1 : 3;
     case ARMMMUIdx_SE1:
+    case ARMMMUIdx_SE1_PAN:
     case ARMMMUIdx_Stage1_E0:
     case ARMMMUIdx_Stage1_E1:
+    case ARMMMUIdx_Stage1_E1_PAN:
     case ARMMMUIdx_EL10_0:
     case ARMMMUIdx_EL10_1:
+    case ARMMMUIdx_EL10_1_PAN:
     case ARMMMUIdx_MPrivNegPri:
     case ARMMMUIdx_MUserNegPri:
     case ARMMMUIdx_MPriv:
@@ -9207,6 +9237,8 @@ static inline ARMMMUIdx stage_1_mmu_idx(ARMMMUIdx mmu_idx)
         return ARMMMUIdx_Stage1_E0;
     case ARMMMUIdx_EL10_1:
         return ARMMMUIdx_Stage1_E1;
+    case ARMMMUIdx_EL10_1_PAN:
+        return ARMMMUIdx_Stage1_E1_PAN;
     default:
         return mmu_idx;
     }
@@ -9253,6 +9285,7 @@ static inline bool regime_is_user(CPUARMState *env, ARMMMUIdx mmu_idx)
         return false;
     case ARMMMUIdx_EL10_0:
     case ARMMMUIdx_EL10_1:
+    case ARMMMUIdx_EL10_1_PAN:
         g_assert_not_reached();
     }
 }
@@ -11145,7 +11178,9 @@ bool get_phys_addr(CPUARMState *env, target_ulong address,
                    target_ulong *page_size,
                    ARMMMUFaultInfo *fi, ARMCacheAttrs *cacheattrs)
 {
-    if (mmu_idx == ARMMMUIdx_EL10_0 || mmu_idx == ARMMMUIdx_EL10_1) {
+    if (mmu_idx == ARMMMUIdx_EL10_0 ||
+        mmu_idx == ARMMMUIdx_EL10_1 ||
+        mmu_idx == ARMMMUIdx_EL10_1_PAN) {
         /* Call ourselves recursively to do the stage 1 and then stage 2
          * translations.
          */
@@ -11672,10 +11707,13 @@ int arm_mmu_idx_to_el(ARMMMUIdx mmu_idx)
     case ARMMMUIdx_SE0:
         return 0;
     case ARMMMUIdx_EL10_1:
+    case ARMMMUIdx_EL10_1_PAN:
     case ARMMMUIdx_SE1:
+    case ARMMMUIdx_SE1_PAN:
         return 1;
     case ARMMMUIdx_E2:
     case ARMMMUIdx_EL20_2:
+    case ARMMMUIdx_EL20_2_PAN:
         return 2;
     case ARMMMUIdx_SE3:
         return 3;
@@ -11886,11 +11924,14 @@ static uint32_t rebuild_hflags_a64(CPUARMState *env, int el, int fp_el,
     /* TODO: ARMv8.2-UAO */
     switch (mmu_idx) {
     case ARMMMUIdx_EL10_1:
+    case ARMMMUIdx_EL10_1_PAN:
     case ARMMMUIdx_SE1:
+    case ARMMMUIdx_SE1_PAN:
         /* TODO: ARMv8.3-NV */
         flags = FIELD_DP32(flags, TBFLAG_A64, UNPRIV, 1);
         break;
     case ARMMMUIdx_EL20_2:
+    case ARMMMUIdx_EL20_2_PAN:
         /* TODO: ARMv8.4-SecEL2 */
         /*
          * Note that EL20_2 is gated by HCR_EL2.E2H == 1, but EL20_0 is
diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
index fe492bea90..b5c7bc2d76 100644
--- a/target/arm/translate-a64.c
+++ b/target/arm/translate-a64.c
@@ -124,9 +124,11 @@ static int get_a64_user_mem_index(DisasContext *s)
          */
         switch (useridx) {
         case ARMMMUIdx_EL10_1:
+        case ARMMMUIdx_EL10_1_PAN:
             useridx = ARMMMUIdx_EL10_0;
             break;
         case ARMMMUIdx_EL20_2:
+        case ARMMMUIdx_EL20_2_PAN:
             useridx = ARMMMUIdx_EL20_0;
             break;
         case ARMMMUIdx_SE1:
diff --git a/target/arm/translate.c b/target/arm/translate.c
index b7f726e733..47a374b53d 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_EL10_0:
     case ARMMMUIdx_EL10_1:
+    case ARMMMUIdx_EL10_1_PAN:
         return arm_to_core_mmu_idx(ARMMMUIdx_EL10_0);
     case ARMMMUIdx_SE3:
     case ARMMMUIdx_SE0:
     case ARMMMUIdx_SE1:
+    case ARMMMUIdx_SE1_PAN:
         return arm_to_core_mmu_idx(ARMMMUIdx_SE0);
     case ARMMMUIdx_MUser:
     case ARMMMUIdx_MPriv:
-- 
2.17.1



  parent reply	other threads:[~2019-12-03 23:21 UTC|newest]

Thread overview: 25+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2019-12-03 22:53 [PATCH 00/11] target/arm: Implement ARMv8.1-PAN + ARMv8.2-ATS1E1 Richard Henderson
2019-12-03 22:53 ` [PATCH 01/11] cputlb: Handle NB_MMU_MODES > TARGET_PAGE_BITS_MIN Richard Henderson
2019-12-06 18:56   ` Peter Maydell
2019-12-03 22:53 ` [PATCH 02/11] target/arm: Add arm_mmu_idx_is_stage1 Richard Henderson
2019-12-04 15:35   ` Philippe Mathieu-Daudé
2019-12-06 19:00   ` Peter Maydell
2019-12-03 22:53 ` Richard Henderson [this message]
2019-12-09 11:40   ` [PATCH 03/11] target/arm: Add mmu_idx for EL1 and EL2 w/ PAN enabled Peter Maydell
2019-12-03 22:53 ` [PATCH 04/11] target/arm: Reduce CPSR_RESERVED Richard Henderson
2019-12-06 19:06   ` Peter Maydell
2019-12-03 22:53 ` [PATCH 05/11] target/arm: Add isar_feature tests for PAN + ATS1E1 Richard Henderson
2019-12-06 19:07   ` Peter Maydell
2019-12-03 22:53 ` [PATCH 06/11] target/arm: Update MSR access for PAN Richard Henderson
2019-12-06 19:10   ` Peter Maydell
2019-12-03 22:53 ` [PATCH 07/11] target/arm: Update arm_mmu_idx_el " Richard Henderson
2019-12-06 19:10   ` Peter Maydell
2019-12-03 22:53 ` [PATCH 08/11] target/arm: Enforce PAN semantics in get_S1prot Richard Henderson
2019-12-06 19:12   ` Peter Maydell
2019-12-03 22:53 ` [PATCH 09/11] target/arm: Set PAN bit as required on exception entry Richard Henderson
2019-12-09 11:55   ` Peter Maydell
2019-12-03 22:53 ` [PATCH 10/11] target/arm: Implement ATS1E1 system registers Richard Henderson
2019-12-09 13:41   ` Peter Maydell
2020-01-31 21:38     ` Richard Henderson
2019-12-03 22:53 ` [PATCH 11/11] target/arm: Enable ARMv8.2-ATS1E1 in -cpu max Richard Henderson
2019-12-06 19:14   ` Peter Maydell

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=20191203225333.17055-4-richard.henderson@linaro.org \
    --to=richard.henderson@linaro.org \
    --cc=peter.maydell@linaro.org \
    --cc=qemu-devel@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.