From: cdall@cs.columbia.edu (Christoffer Dall)
To: linux-arm-kernel@lists.infradead.org
Subject: [PATCH v3 26/32] arm64: KVM: 32bit handling of coprocessor traps
Date: Tue, 23 Apr 2013 16:01:59 -0700 [thread overview]
Message-ID: <20130423230159.GL20569@gmail.com> (raw)
In-Reply-To: <1365437854-30214-27-git-send-email-marc.zyngier@arm.com>
On Mon, Apr 08, 2013 at 05:17:28PM +0100, Marc Zyngier wrote:
> Provide the necessary infrastructure to trap coprocessor accesses that
> occur when running 32bit guests.
>
> Also wire SMC and HVC trapped in 32bit mode while were at it.
>
> Reviewed-by: Christopher Covington <cov@codeaurora.org>
> Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
> ---
> arch/arm64/include/asm/kvm_coproc.h | 5 +
> arch/arm64/kvm/handle_exit.c | 7 ++
> arch/arm64/kvm/sys_regs.c | 178 ++++++++++++++++++++++++++++++++++--
> 3 files changed, 183 insertions(+), 7 deletions(-)
>
> diff --git a/arch/arm64/include/asm/kvm_coproc.h b/arch/arm64/include/asm/kvm_coproc.h
> index 9b4477a..9a59301 100644
> --- a/arch/arm64/include/asm/kvm_coproc.h
> +++ b/arch/arm64/include/asm/kvm_coproc.h
> @@ -32,11 +32,16 @@ struct kvm_sys_reg_table {
>
> struct kvm_sys_reg_target_table {
> struct kvm_sys_reg_table table64;
> + struct kvm_sys_reg_table table32;
> };
>
> void kvm_register_target_sys_reg_table(unsigned int target,
> struct kvm_sys_reg_target_table *table);
>
> +int kvm_handle_cp14_load_store(struct kvm_vcpu *vcpu, struct kvm_run *run);
> +int kvm_handle_cp14_access(struct kvm_vcpu *vcpu, struct kvm_run *run);
> +int kvm_handle_cp15_32(struct kvm_vcpu *vcpu, struct kvm_run *run);
> +int kvm_handle_cp15_64(struct kvm_vcpu *vcpu, struct kvm_run *run);
> int kvm_handle_sys_reg(struct kvm_vcpu *vcpu, struct kvm_run *run);
>
> #define kvm_coproc_table_init kvm_sys_reg_table_init
> diff --git a/arch/arm64/kvm/handle_exit.c b/arch/arm64/kvm/handle_exit.c
> index 4766b7f..9beaca03 100644
> --- a/arch/arm64/kvm/handle_exit.c
> +++ b/arch/arm64/kvm/handle_exit.c
> @@ -62,6 +62,13 @@ static int kvm_handle_wfi(struct kvm_vcpu *vcpu, struct kvm_run *run)
>
> static exit_handle_fn arm_exit_handlers[] = {
> [ESR_EL2_EC_WFI] = kvm_handle_wfi,
> + [ESR_EL2_EC_CP15_32] = kvm_handle_cp15_32,
> + [ESR_EL2_EC_CP15_64] = kvm_handle_cp15_64,
> + [ESR_EL2_EC_CP14_MR] = kvm_handle_cp14_access,
> + [ESR_EL2_EC_CP14_LS] = kvm_handle_cp14_load_store,
> + [ESR_EL2_EC_CP14_64] = kvm_handle_cp14_access,
> + [ESR_EL2_EC_HVC32] = handle_hvc,
> + [ESR_EL2_EC_SMC32] = handle_smc,
> [ESR_EL2_EC_HVC64] = handle_hvc,
> [ESR_EL2_EC_SMC64] = handle_smc,
> [ESR_EL2_EC_SYS64] = kvm_handle_sys_reg,
> diff --git a/arch/arm64/kvm/sys_regs.c b/arch/arm64/kvm/sys_regs.c
> index 9df3b32..0303218 100644
> --- a/arch/arm64/kvm/sys_regs.c
> +++ b/arch/arm64/kvm/sys_regs.c
> @@ -38,6 +38,10 @@
> * types are different. My gut feeling is that it should be pretty
> * easy to merge, but that would be an ABI breakage -- again. VFP
> * would also need to be abstracted.
> + *
> + * For AArch32, we only take care of what is being trapped. Anything
> + * that has to do with init and userspace access has to go via the
> + * 64bit interface.
> */
>
> /* 3 bits per cache level, as per CLIDR, but non-existent caches always 0 */
> @@ -163,6 +167,16 @@ static const struct sys_reg_desc sys_reg_descs[] = {
> { Op0(0b01), Op1(0b000), CRn(0b0111), CRm(0b1110), Op2(0b010),
> access_dcsw },
>
> + /* TEECR32_EL1 */
> + { Op0(0b10), Op1(0b010), CRn(0b0000), CRm(0b0000), Op2(0b000),
> + NULL, reset_val, TEECR32_EL1, 0 },
> + /* TEEHBR32_EL1 */
> + { Op0(0b10), Op1(0b010), CRn(0b0001), CRm(0b0000), Op2(0b000),
> + NULL, reset_val, TEEHBR32_EL1, 0 },
> + /* DBGVCR32_EL2 */
> + { Op0(0b10), Op1(0b100), CRn(0b0000), CRm(0b0111), Op2(0b000),
> + NULL, reset_val, DBGVCR32_EL2, 0 },
> +
> /* MPIDR_EL1 */
> { Op0(0b11), Op1(0b000), CRn(0b0000), CRm(0b0000), Op2(0b101),
> NULL, reset_mpidr, MPIDR_EL1 },
> @@ -273,6 +287,39 @@ static const struct sys_reg_desc sys_reg_descs[] = {
> /* TPIDRRO_EL0 */
> { Op0(0b11), Op1(0b011), CRn(0b1101), CRm(0b0000), Op2(0b011),
> NULL, reset_unknown, TPIDRRO_EL0 },
> +
> + /* DACR32_EL2 */
> + { Op0(0b11), Op1(0b100), CRn(0b0011), CRm(0b0000), Op2(0b000),
> + NULL, reset_unknown, DACR32_EL2 },
> + /* IFSR32_EL2 */
> + { Op0(0b11), Op1(0b100), CRn(0b0101), CRm(0b0000), Op2(0b001),
> + NULL, reset_unknown, IFSR32_EL2 },
> + /* FPEXC32_EL2 */
> + { Op0(0b11), Op1(0b100), CRn(0b0101), CRm(0b0011), Op2(0b000),
> + NULL, reset_val, FPEXC32_EL2, 0x70 },
> +};
> +
> +/* Trapped cp15 registers */
> +static const struct sys_reg_desc cp15_regs[] = {
> + /*
> + * DC{C,I,CI}SW operations:
> + */
> + { Op1( 0), CRn( 7), CRm( 6), Op2( 2), access_dcsw },
> + { Op1( 0), CRn( 7), CRm(10), Op2( 2), access_dcsw },
> + { Op1( 0), CRn( 7), CRm(14), Op2( 2), access_dcsw },
> + { Op1( 0), CRn( 9), CRm(12), Op2( 0), pm_fake },
> + { Op1( 0), CRn( 9), CRm(12), Op2( 1), pm_fake },
> + { Op1( 0), CRn( 9), CRm(12), Op2( 2), pm_fake },
> + { Op1( 0), CRn( 9), CRm(12), Op2( 3), pm_fake },
> + { Op1( 0), CRn( 9), CRm(12), Op2( 5), pm_fake },
> + { Op1( 0), CRn( 9), CRm(12), Op2( 6), pm_fake },
> + { Op1( 0), CRn( 9), CRm(12), Op2( 7), pm_fake },
> + { Op1( 0), CRn( 9), CRm(13), Op2( 0), pm_fake },
> + { Op1( 0), CRn( 9), CRm(13), Op2( 1), pm_fake },
> + { Op1( 0), CRn( 9), CRm(13), Op2( 2), pm_fake },
> + { Op1( 0), CRn( 9), CRm(14), Op2( 0), pm_fake },
> + { Op1( 0), CRn( 9), CRm(14), Op2( 1), pm_fake },
> + { Op1( 0), CRn( 9), CRm(14), Op2( 2), pm_fake },
> };
>
> /* Target specific emulation tables */
> @@ -285,13 +332,20 @@ void kvm_register_target_sys_reg_table(unsigned int target,
> }
>
> /* Get specific register table for this target. */
> -static const struct sys_reg_desc *get_target_table(unsigned target, size_t *num)
> +static const struct sys_reg_desc *get_target_table(unsigned target,
> + bool mode_is_64,
> + size_t *num)
> {
> struct kvm_sys_reg_target_table *table;
>
> table = target_tables[target];
> - *num = table->table64.num;
> - return table->table64.table;
> + if (mode_is_64) {
> + *num = table->table64.num;
> + return table->table64.table;
> + } else {
> + *num = table->table32.num;
> + return table->table32.table;
> + }
> }
>
> static const struct sys_reg_desc *find_reg(const struct sys_reg_params *params,
> @@ -319,13 +373,123 @@ static const struct sys_reg_desc *find_reg(const struct sys_reg_params *params,
> return NULL;
> }
>
> +int kvm_handle_cp14_load_store(struct kvm_vcpu *vcpu, struct kvm_run *run)
> +{
> + kvm_inject_undefined(vcpu);
> + return 1;
> +}
> +
> +int kvm_handle_cp14_access(struct kvm_vcpu *vcpu, struct kvm_run *run)
> +{
> + kvm_inject_undefined(vcpu);
> + return 1;
> +}
> +
> +static int emulate_cp15(struct kvm_vcpu *vcpu,
> + const struct sys_reg_params *params)
> +{
> + size_t num;
> + const struct sys_reg_desc *table, *r;
> +
> + table = get_target_table(vcpu->arch.target, false, &num);
> +
> + /* Search target-specific then generic table. */
> + r = find_reg(params, table, num);
> + if (!r)
> + r = find_reg(params, cp15_regs, ARRAY_SIZE(cp15_regs));
> +
> + if (likely(r)) {
> + /* If we don't have an accessor, we should never get here! */
> + BUG_ON(!r->access);
again not quite sure if this warrants a crash of the entire host.
> +
> + if (likely(r->access(vcpu, params, r))) {
> + /* Skip instruction, since it was emulated */
> + kvm_skip_instr(vcpu, kvm_vcpu_trap_il_is32bit(vcpu));
> + return 1;
> + }
> + /* If access function fails, it should complain. */
> + } else {
> + kvm_err("Unsupported guest CP15 access at: %08lx\n",
> + *vcpu_pc(vcpu));
> + print_sys_reg_instr(params);
> + }
> + kvm_inject_undefined(vcpu);
> + return 1;
> +}
> +
> +/**
> + * kvm_handle_cp15_64 -- handles a mrrc/mcrr trap on a guest CP15 access
> + * @vcpu: The VCPU pointer
> + * @run: The kvm_run struct
> + */
> +int kvm_handle_cp15_64(struct kvm_vcpu *vcpu, struct kvm_run *run)
> +{
> + struct sys_reg_params params;
> + u32 hsr = kvm_vcpu_get_hsr(vcpu);
> + int Rt2 = (hsr >> 10) & 0xf;
> + int ret;
> +
> + params.CRm = (hsr >> 1) & 0xf;
> + params.Rt = (hsr >> 5) & 0xf;
> + params.is_write = ((hsr & 1) == 0);
> +
> + params.Op0 = 0;
> + params.Op1 = (hsr >> 16) & 0xf;
> + params.Op2 = 0;
> + params.CRn = 0;
> +
> + /*
> + * Massive hack here. Store Rt2 in the top 32bits so we only
> + * have one register to deal with. As we use the same trap
> + * backends between AArch32 and AArch64, we get away with it.
> + */
> + if (params.is_write) {
> + u64 val = *vcpu_reg(vcpu, params.Rt);
> + val &= 0xffffffff;
> + val |= *vcpu_reg(vcpu, Rt2) << 32;
> + *vcpu_reg(vcpu, params.Rt) = val;
> + }
> +
> + ret = emulate_cp15(vcpu, ¶ms);
> +
> + /* Reverse hack here */
nit: consider changing the wording to something like 'Similar hack for
reads here', so readers don't think you are trying to reverse the hack
you did above.
> + if (ret && !params.is_write) {
> + u64 val = *vcpu_reg(vcpu, params.Rt);
> + val >>= 32;
> + *vcpu_reg(vcpu, Rt2) = val;
actually the emulate_cp15 should probably be turned into a void and the
ret check could go away, same thing on the 32-bit side.
> + }
> +
> + return ret;
> +}
> +
> +/**
> + * kvm_handle_cp15_32 -- handles a mrc/mcr trap on a guest CP15 access
> + * @vcpu: The VCPU pointer
> + * @run: The kvm_run struct
> + */
> +int kvm_handle_cp15_32(struct kvm_vcpu *vcpu, struct kvm_run *run)
> +{
> + struct sys_reg_params params;
> + u32 hsr = kvm_vcpu_get_hsr(vcpu);
> +
> + params.CRm = (hsr >> 1) & 0xf;
> + params.Rt = (hsr >> 5) & 0xf;
> + params.is_write = ((hsr & 1) == 0);
> + params.CRn = (hsr >> 10) & 0xf;
> + params.Op0 = 0;
> + params.Op1 = (hsr >> 14) & 0x7;
> + params.Op2 = (hsr >> 17) & 0x7;
> +
> + return emulate_cp15(vcpu, ¶ms);
> +}
> +
> static int emulate_sys_reg(struct kvm_vcpu *vcpu,
> const struct sys_reg_params *params)
> {
> size_t num;
> const struct sys_reg_desc *table, *r;
>
> - table = get_target_table(vcpu->arch.target, &num);
> + table = get_target_table(vcpu->arch.target, true, &num);
>
> /* Search target-specific then generic table. */
> r = find_reg(params, table, num);
> @@ -430,7 +594,7 @@ static const struct sys_reg_desc *index_to_sys_reg_desc(struct kvm_vcpu *vcpu,
> if (!index_to_params(id, ¶ms))
> return NULL;
>
> - table = get_target_table(vcpu->arch.target, &num);
> + table = get_target_table(vcpu->arch.target, true, &num);
> r = find_reg(¶ms, table, num);
> if (!r)
> r = find_reg(¶ms, sys_reg_descs, ARRAY_SIZE(sys_reg_descs));
> @@ -750,7 +914,7 @@ static int walk_sys_regs(struct kvm_vcpu *vcpu, u64 __user *uind)
> size_t num;
>
> /* We check for duplicates here, to allow arch-specific overrides. */
> - i1 = get_target_table(vcpu->arch.target, &num);
> + i1 = get_target_table(vcpu->arch.target, true, &num);
> end1 = i1 + num;
> i2 = sys_reg_descs;
> end2 = sys_reg_descs + ARRAY_SIZE(sys_reg_descs);
> @@ -862,7 +1026,7 @@ void kvm_reset_sys_regs(struct kvm_vcpu *vcpu)
> /* Generic chip reset first (so target could override). */
> reset_sys_reg_descs(vcpu, sys_reg_descs, ARRAY_SIZE(sys_reg_descs));
>
> - table = get_target_table(vcpu->arch.target, &num);
> + table = get_target_table(vcpu->arch.target, true, &num);
> reset_sys_reg_descs(vcpu, table, num);
>
> for (num = 1; num < NR_SYS_REGS; num++)
> --
> 1.8.1.4
>
>
>
> _______________________________________________
> kvmarm mailing list
> kvmarm at lists.cs.columbia.edu
> https://lists.cs.columbia.edu/cucslists/listinfo/kvmarm
next prev parent reply other threads:[~2013-04-23 23:01 UTC|newest]
Thread overview: 116+ messages / expand[flat|nested] mbox.gz Atom feed top
2013-04-08 16:17 [PATCH v3 00/32] Port of KVM to arm64 Marc Zyngier
2013-04-08 16:17 ` [PATCH v3 01/32] arm64: add explicit symbols to ESR_EL1 decoding Marc Zyngier
2013-04-08 16:17 ` [PATCH v3 02/32] arm64: KVM: define HYP and Stage-2 translation page flags Marc Zyngier
2013-04-10 14:07 ` Will Deacon
2013-04-12 15:22 ` Marc Zyngier
2013-04-26 17:01 ` Catalin Marinas
2013-04-26 17:11 ` Marc Zyngier
2013-04-08 16:17 ` [PATCH v3 03/32] arm64: KVM: HYP mode idmap support Marc Zyngier
2013-04-23 22:57 ` Christoffer Dall
2013-04-24 9:36 ` Marc Zyngier
2013-04-08 16:17 ` [PATCH v3 04/32] arm64: KVM: EL2 register definitions Marc Zyngier
2013-04-08 16:17 ` [PATCH v3 05/32] arm64: KVM: system register definitions for 64bit guests Marc Zyngier
2013-04-08 16:17 ` [PATCH v3 06/32] arm64: KVM: Basic ESR_EL2 helpers and vcpu register access Marc Zyngier
2013-04-08 16:17 ` [PATCH v3 07/32] arm64: KVM: fault injection into a guest Marc Zyngier
2013-04-10 16:40 ` Will Deacon
2013-04-12 15:29 ` Marc Zyngier
2013-04-23 22:57 ` Christoffer Dall
2013-04-24 10:04 ` Marc Zyngier
2013-04-24 16:46 ` Christoffer Dall
2013-04-29 16:26 ` Catalin Marinas
2013-05-07 16:29 ` Marc Zyngier
2013-04-08 16:17 ` [PATCH v3 08/32] arm64: KVM: architecture specific MMU backend Marc Zyngier
2013-04-23 22:58 ` Christoffer Dall
2013-04-24 11:03 ` Marc Zyngier
2013-04-24 11:10 ` Will Deacon
2013-04-24 16:50 ` Christoffer Dall
2013-04-24 16:55 ` Christoffer Dall
2013-04-25 12:59 ` Marc Zyngier
2013-04-25 15:13 ` Christoffer Dall
2013-04-29 17:35 ` Catalin Marinas
2013-04-30 10:23 ` Marc Zyngier
2013-04-08 16:17 ` [PATCH v3 09/32] arm64: KVM: user space interface Marc Zyngier
2013-04-10 16:45 ` Will Deacon
2013-04-12 15:31 ` Marc Zyngier
2013-04-08 16:17 ` [PATCH v3 10/32] arm64: KVM: system register handling Marc Zyngier
2013-04-10 17:04 ` Will Deacon
2013-04-12 15:48 ` Marc Zyngier
2013-04-23 23:01 ` Christoffer Dall
2013-04-24 13:37 ` Marc Zyngier
2013-04-08 16:17 ` [PATCH v3 11/32] arm64: KVM: CPU specific system registers handling Marc Zyngier
2013-04-10 17:06 ` Will Deacon
2013-04-12 16:04 ` Marc Zyngier
2013-04-23 22:59 ` Christoffer Dall
2013-04-24 9:33 ` Marc Zyngier
2013-04-08 16:17 ` [PATCH v3 12/32] arm64: KVM: virtual CPU reset Marc Zyngier
2013-04-10 17:07 ` Will Deacon
2013-04-12 16:04 ` Marc Zyngier
2013-04-08 16:17 ` [PATCH v3 13/32] arm64: KVM: kvm_arch and kvm_vcpu_arch definitions Marc Zyngier
2013-04-08 16:17 ` [PATCH v3 14/32] arm64: KVM: MMIO access backend Marc Zyngier
2013-04-08 16:17 ` [PATCH v3 15/32] arm64: KVM: guest one-reg interface Marc Zyngier
2013-04-10 17:13 ` Will Deacon
2013-04-12 16:35 ` Marc Zyngier
2013-04-23 22:59 ` Christoffer Dall
2013-04-24 11:27 ` Marc Zyngier
2013-04-24 17:05 ` Christoffer Dall
2013-04-08 16:17 ` [PATCH v3 16/32] arm64: KVM: hypervisor initialization code Marc Zyngier
2013-05-02 11:03 ` Catalin Marinas
2013-05-02 13:28 ` Marc Zyngier
2013-04-08 16:17 ` [PATCH v3 17/32] arm64: KVM: HYP mode world switch implementation Marc Zyngier
2013-04-23 22:59 ` Christoffer Dall
2013-04-24 11:39 ` Marc Zyngier
2013-04-24 17:08 ` Christoffer Dall
2013-04-08 16:17 ` [PATCH v3 18/32] arm64: KVM: Exit handling Marc Zyngier
2013-04-08 16:17 ` [PATCH v3 19/32] arm64: KVM: Plug the VGIC Marc Zyngier
2013-04-23 23:00 ` Christoffer Dall
2013-04-24 11:43 ` Marc Zyngier
2013-05-02 14:38 ` Catalin Marinas
2013-04-08 16:17 ` [PATCH v3 20/32] arm64: KVM: Plug the arch timer Marc Zyngier
2013-04-23 23:00 ` Christoffer Dall
2013-04-24 11:43 ` Marc Zyngier
2013-05-02 15:31 ` Catalin Marinas
2013-04-08 16:17 ` [PATCH v3 21/32] arm64: KVM: PSCI implementation Marc Zyngier
2013-04-08 16:17 ` [PATCH v3 22/32] arm64: KVM: Build system integration Marc Zyngier
2013-04-08 16:17 ` [PATCH v3 23/32] arm64: KVM: define 32bit specific registers Marc Zyngier
2013-04-08 16:17 ` [PATCH v3 24/32] arm64: KVM: 32bit GP register access Marc Zyngier
2013-04-23 23:00 ` Christoffer Dall
2013-04-24 13:06 ` Marc Zyngier
2013-04-24 17:09 ` Christoffer Dall
2013-05-02 16:09 ` Catalin Marinas
2013-05-07 16:28 ` Marc Zyngier
2013-05-07 16:33 ` Catalin Marinas
2013-05-11 0:36 ` Christoffer Dall
2013-05-11 7:51 ` Peter Maydell
2013-05-11 9:43 ` Catalin Marinas
2013-05-12 18:51 ` Christoffer Dall
2013-04-08 16:17 ` [PATCH v3 25/32] arm64: KVM: 32bit conditional execution emulation Marc Zyngier
2013-04-23 23:00 ` Christoffer Dall
2013-04-24 13:13 ` Marc Zyngier
2013-04-24 17:11 ` Christoffer Dall
2013-04-08 16:17 ` [PATCH v3 26/32] arm64: KVM: 32bit handling of coprocessor traps Marc Zyngier
2013-04-23 23:01 ` Christoffer Dall [this message]
2013-04-24 13:42 ` Marc Zyngier
2013-04-24 17:14 ` Christoffer Dall
2013-04-08 16:17 ` [PATCH v3 27/32] arm64: KVM: CPU specific 32bit coprocessor access Marc Zyngier
2013-04-08 16:17 ` [PATCH v3 28/32] arm64: KVM: 32bit specific register world switch Marc Zyngier
2013-04-08 16:17 ` [PATCH v3 29/32] arm64: KVM: 32bit guest fault injection Marc Zyngier
2013-04-23 23:02 ` Christoffer Dall
2013-04-24 13:46 ` Marc Zyngier
2013-04-24 17:15 ` Christoffer Dall
2013-04-08 16:17 ` [PATCH v3 30/32] arm64: KVM: enable initialization of a 32bit vcpu Marc Zyngier
2013-04-23 23:02 ` Christoffer Dall
2013-04-24 13:49 ` Marc Zyngier
2013-04-24 17:17 ` Christoffer Dall
2013-05-07 16:36 ` Marc Zyngier
2013-05-11 0:38 ` Christoffer Dall
2013-05-11 8:04 ` Peter Maydell
2013-05-11 16:26 ` Christoffer Dall
2013-05-11 16:31 ` Peter Maydell
2013-05-13 9:01 ` Marc Zyngier
2013-05-13 15:46 ` Christoffer Dall
2013-04-08 16:17 ` [PATCH v3 31/32] arm64: KVM: userspace API documentation Marc Zyngier
2013-04-23 23:02 ` Christoffer Dall
2013-04-24 13:52 ` Marc Zyngier
2013-04-08 16:17 ` [PATCH v3 32/32] arm64: KVM: MAINTAINERS update Marc Zyngier
2013-04-23 23:04 ` [PATCH v3 00/32] Port of KVM to arm64 Christoffer Dall
2013-05-03 13:17 ` Catalin Marinas
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=20130423230159.GL20569@gmail.com \
--to=cdall@cs.columbia.edu \
--cc=linux-arm-kernel@lists.infradead.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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).