Re: [RFC PATCH] KVM: arm64: don't single-step for non-emulated faults

2018-11-09 Thread Mark Rutland
On Thu, Nov 08, 2018 at 02:38:43PM +, Peter Maydell wrote:
> On 8 November 2018 at 14:28, Alex Bennée  wrote:
> >
> > Mark Rutland  writes:
> >> One problem is that I couldn't spot when we advance the PC for an MMIO
> >> trap. I presume we do that in the kernel, *after* the MMIO trap, but I
> >> can't see where that happens.
> >
> > Nope it gets done before during decode_hsr in mmio.c:
> >
> > /*
> >  * The MMIO instruction is emulated and should not be re-executed
> >  * in the guest.
> >  */
> > kvm_skip_instr(vcpu, kvm_vcpu_trap_il_is32bit(vcpu));
> 
> I think that this attempt to do the PC-advance early is
> probably an underlying problem that is not helping the
> code structure here.
> 
> An enhancement that's been floated previously is that the
> MMIO emulation in userspace should be able to report back
> to KVM "nope, that access should generate a guest synchronous
> external abort (with ESR_EL1.EA = 0/1)".
> If we have that, then we definitely need to not advance the
> PC until after userspace has done the emulation and told
> us whether the memory access succeeded or not...

Yup.

I think that we absolutely want to do all the CPU state advancement (PC,
SS bit, etc) at the point we apply the effects of the instruction. Not
before we emulate the instruction, and not higher/lower in the call
stack.

We have a big problem in that guest-directed singlestep and
host-directed singlestep don't compose, and given that host-directed
singlestep doesn't work reliably today I'd be tempted to rip that out
until we've fixed guest-directed singlestep.

We should have a story for how host-directed debug is handled
transparently from the PoV of a guest using guest-directed debug.

Thanks,
Mark.
___
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm


Re: [RFC PATCH] KVM: arm64: don't single-step for non-emulated faults

2018-11-08 Thread Mark Rutland
On Thu, Nov 08, 2018 at 12:40:11PM +, Alex Bennée wrote:
> Mark Rutland  writes:
> > On Wed, Nov 07, 2018 at 06:01:20PM +0000, Mark Rutland wrote:
> >> On Wed, Nov 07, 2018 at 05:10:31PM +, Alex Bennée wrote:
> >> > Not all faults handled by handle_exit are instruction emulations. For
> >> > example a ESR_ELx_EC_IABT will result in the page tables being updated
> >> > but the instruction that triggered the fault hasn't actually executed
> >> > yet. We use the simple heuristic of checking for a changed PC before
> >> > seeing if kvm_arm_handle_step_debug wants to claim we stepped an
> >> > instruction.
> >> >
> >> > Signed-off-by: Alex Bennée 
> >> > ---
> >> >  arch/arm64/kvm/handle_exit.c | 4 +++-
> >> >  1 file changed, 3 insertions(+), 1 deletion(-)
> >> >
> >> > diff --git a/arch/arm64/kvm/handle_exit.c b/arch/arm64/kvm/handle_exit.c
> >> > index e5e741bfffe1..b8252e72f882 100644
> >> > --- a/arch/arm64/kvm/handle_exit.c
> >> > +++ b/arch/arm64/kvm/handle_exit.c
> >> > @@ -214,6 +214,7 @@ static exit_handle_fn kvm_get_exit_handler(struct 
> >> > kvm_vcpu *vcpu)
> >> >  static int handle_trap_exceptions(struct kvm_vcpu *vcpu, struct kvm_run 
> >> > *run)
> >> >  {
> >> >  int handled;
> >> > +unsigned long old_pc = *vcpu_pc(vcpu);
> >> >
> >> >  /*
> >> >   * See ARM ARM B1.14.1: "Hyp traps on instructions
> >> > @@ -233,7 +234,8 @@ static int handle_trap_exceptions(struct kvm_vcpu 
> >> > *vcpu, struct kvm_run *run)
> >> >   * kvm_arm_handle_step_debug() sets the exit_reason on the 
> >> > kvm_run
> >> >   * structure if we need to return to userspace.
> >> >   */
> >> > -if (handled > 0 && kvm_arm_handle_step_debug(vcpu, run))
> >> > +if (handled > 0 && *vcpu_pc(vcpu) != old_pc &&
> >>
> >> This doesn't work if the emulation is equivalent to a branch-to-self, so
> >> I don't think that we want to do this.
> >>
> >> When are we failing to advance the single-step state machine
> >> correctly?
> 
> When the trap is not actually an instruction emulation - e.g. setting up
> the page tables on a fault. Because we are in the act of single-stepping
> an instruction that didn't actually execute we erroneously return to
> userspace pretending we did even though we shouldn't.

I think one problem here is that we're trying to use one bit of state
(the KVM_GUESTDBG_SINGLESTEP) when we actually need two.

I had expected that we'd follow the architectural single-step state
machine, and have three states:

* inactive/disabled: not single stepping

* active-not-pending: the current instruction will be stepped, and we'll
  transition to active-pending before executing the next instruction.

* active-pending: the current instruction will raise a software step
  debug exception, before being executed.

For that to work, all we have to do is advence the state machine when we
emulate/skip an instruction, and the HW will raise the exception for us
when we enter the guest (which is the only place we have to handle the
step exception).

We need two bits of internal state for that, but KVM only gives us a
single KVM_GUESTDBG_SINGLESTEP flag, and we might exit to userspace
mid-emulation (e.g. for MMIO). To avoid that resulting in skipping two
instructions at a time, we currently add explicit
kvm_arm_handle_step_debug() checks everywhere after we've (possibly)
emulated an instruction, but these seem to hit too often.

One problem is that I couldn't spot when we advance the PC for an MMIO
trap. I presume we do that in the kernel, *after* the MMIO trap, but I
can't see where that happens.

Thanks,
Mark.
___
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm


Re: [RFC PATCH] KVM: arm64: don't single-step for non-emulated faults

2018-11-07 Thread Mark Rutland
On Wed, Nov 07, 2018 at 06:01:20PM +, Mark Rutland wrote:
> On Wed, Nov 07, 2018 at 05:10:31PM +, Alex Bennée wrote:
> > Not all faults handled by handle_exit are instruction emulations. For
> > example a ESR_ELx_EC_IABT will result in the page tables being updated
> > but the instruction that triggered the fault hasn't actually executed
> > yet. We use the simple heuristic of checking for a changed PC before
> > seeing if kvm_arm_handle_step_debug wants to claim we stepped an
> > instruction.
> > 
> > Signed-off-by: Alex Bennée 
> > ---
> >  arch/arm64/kvm/handle_exit.c | 4 +++-
> >  1 file changed, 3 insertions(+), 1 deletion(-)
> > 
> > diff --git a/arch/arm64/kvm/handle_exit.c b/arch/arm64/kvm/handle_exit.c
> > index e5e741bfffe1..b8252e72f882 100644
> > --- a/arch/arm64/kvm/handle_exit.c
> > +++ b/arch/arm64/kvm/handle_exit.c
> > @@ -214,6 +214,7 @@ static exit_handle_fn kvm_get_exit_handler(struct 
> > kvm_vcpu *vcpu)
> >  static int handle_trap_exceptions(struct kvm_vcpu *vcpu, struct kvm_run 
> > *run)
> >  {
> > int handled;
> > +unsigned long old_pc = *vcpu_pc(vcpu);
> >  
> > /*
> >  * See ARM ARM B1.14.1: "Hyp traps on instructions
> > @@ -233,7 +234,8 @@ static int handle_trap_exceptions(struct kvm_vcpu 
> > *vcpu, struct kvm_run *run)
> >  * kvm_arm_handle_step_debug() sets the exit_reason on the kvm_run
> >  * structure if we need to return to userspace.
> >  */
> > -   if (handled > 0 && kvm_arm_handle_step_debug(vcpu, run))
> > +   if (handled > 0 && *vcpu_pc(vcpu) != old_pc &&
> 
> This doesn't work if the emulation is equivalent to a branch-to-self, so
> I don't think that we want to do this.
> 
> When are we failing to advance the single-step state machine correctly?

I don't understand how this is intended to work currently.

Surely kvm_skip_instr() should advance the state machine as necessary,
so that we can rely on the HW to generate any necessary single-step
exception when we next return to the guest?

... and if userspace decides to emulate something, it's up to it to
advance the state machine consistently.

Thanks,
Mark.
___
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm


Re: [RFC PATCH] KVM: arm64: don't single-step for non-emulated faults

2018-11-07 Thread Mark Rutland
On Wed, Nov 07, 2018 at 05:10:31PM +, Alex Bennée wrote:
> Not all faults handled by handle_exit are instruction emulations. For
> example a ESR_ELx_EC_IABT will result in the page tables being updated
> but the instruction that triggered the fault hasn't actually executed
> yet. We use the simple heuristic of checking for a changed PC before
> seeing if kvm_arm_handle_step_debug wants to claim we stepped an
> instruction.
> 
> Signed-off-by: Alex Bennée 
> ---
>  arch/arm64/kvm/handle_exit.c | 4 +++-
>  1 file changed, 3 insertions(+), 1 deletion(-)
> 
> diff --git a/arch/arm64/kvm/handle_exit.c b/arch/arm64/kvm/handle_exit.c
> index e5e741bfffe1..b8252e72f882 100644
> --- a/arch/arm64/kvm/handle_exit.c
> +++ b/arch/arm64/kvm/handle_exit.c
> @@ -214,6 +214,7 @@ static exit_handle_fn kvm_get_exit_handler(struct 
> kvm_vcpu *vcpu)
>  static int handle_trap_exceptions(struct kvm_vcpu *vcpu, struct kvm_run *run)
>  {
>   int handled;
> +unsigned long old_pc = *vcpu_pc(vcpu);
>  
>   /*
>* See ARM ARM B1.14.1: "Hyp traps on instructions
> @@ -233,7 +234,8 @@ static int handle_trap_exceptions(struct kvm_vcpu *vcpu, 
> struct kvm_run *run)
>* kvm_arm_handle_step_debug() sets the exit_reason on the kvm_run
>* structure if we need to return to userspace.
>*/
> - if (handled > 0 && kvm_arm_handle_step_debug(vcpu, run))
> + if (handled > 0 && *vcpu_pc(vcpu) != old_pc &&

This doesn't work if the emulation is equivalent to a branch-to-self, so
I don't think that we want to do this.

When are we failing to advance the single-step state machine correctly?

Thanks,
Mark.

> + kvm_arm_handle_step_debug(vcpu, run))
>   handled = 0;
>  
>   return handled;
> -- 
> 2.17.1
> 
___
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm


Re: [PATCH] arm64: KVM: Don't generate UNDEF when LORegion feature is present

2018-11-05 Thread Mark Rutland
On Mon, Nov 05, 2018 at 03:30:26PM +, Marc Zyngier wrote:
> We currently hide the LORegion feature, and generate an UNDEF
> if the guest dares using the corresponding registers. This is
> a bit extreme, as ARMv8.1 guarantees the feature to be present.
> 
> The guest should check the feature register before doing anything,
> but we could also give the guest some slack (read "allow the
> guest to be a bit stupid").
> 
> So instead of unconditionnaly deliver an exception, let's
> only do it when the host doesn't support LORegion at all (or
> when the feature has been sanitized out), and treat the registers
> as RAZ/WI otherwise (with the exception of LORID_EL1 being RO).
> 
> Fixes: cc33c4e20185 ("arm64/kvm: Prohibit guest LOR accesses")
> Suggested-by: Richard Henderson 
> Signed-off-by: Marc Zyngier 
> ---
>  arch/arm64/kvm/sys_regs.c | 42 +--
>  1 file changed, 27 insertions(+), 15 deletions(-)
> 
> diff --git a/arch/arm64/kvm/sys_regs.c b/arch/arm64/kvm/sys_regs.c
> index 22fbbdbece3c..1133b74065f1 100644
> --- a/arch/arm64/kvm/sys_regs.c
> +++ b/arch/arm64/kvm/sys_regs.c
> @@ -314,12 +314,29 @@ static bool trap_raz_wi(struct kvm_vcpu *vcpu,
>   return read_zero(vcpu, p);
>  }
>  
> -static bool trap_undef(struct kvm_vcpu *vcpu,
> -struct sys_reg_params *p,
> -const struct sys_reg_desc *r)
> +/*
> + * ARMv8.1 mandates at least a trivial LORegion implementation, where all the
> + * RW registers are RES0 (which we can implement as RAZ/WI). On an ARMv8.0
> + * system, these registers should UNDEF. LORID_EL1 being a RO register, we
> + * treat it separately.
> + */
> +static bool trap_loregion(struct kvm_vcpu *vcpu,
> +   struct sys_reg_params *p,
> +   const struct sys_reg_desc *r)
>  {
> - kvm_inject_undefined(vcpu);
> - return false;
> + u64 val = read_sanitised_ftr_reg(SYS_ID_AA64MMFR1_EL1);
> + u32 sr = sys_reg((u32)r->Op0, (u32)r->Op1,
> +  (u32)r->CRn, (u32)r->CRm, (u32)r->Op2);
> +

It might be worth factoring this into a helper (e.g. param_to_reg(p)),
since there are a few other places that this would help us to use
mnemonics for.

Either way:

Acked-by: Mark Rutland 

Mark.

> + if (!(val & (0xfUL << ID_AA64MMFR1_LOR_SHIFT))) {
> + kvm_inject_undefined(vcpu);
> + return false;
> + }
> +
> + if (p->is_write && sr == SYS_LORID_EL1)
> + return write_to_read_only(vcpu, p, r);
> +
> + return trap_raz_wi(vcpu, p, r);
>  }
>  
>  static bool trap_oslsr_el1(struct kvm_vcpu *vcpu,
> @@ -1040,11 +1057,6 @@ static u64 read_id_reg(struct sys_reg_desc const *r, 
> bool raz)
>   kvm_debug("SVE unsupported for guests, suppressing\n");
>  
>   val &= ~(0xfUL << ID_AA64PFR0_SVE_SHIFT);
> - } else if (id == SYS_ID_AA64MMFR1_EL1) {
> - if (val & (0xfUL << ID_AA64MMFR1_LOR_SHIFT))
> - kvm_debug("LORegions unsupported for guests, 
> suppressing\n");
> -
> - val &= ~(0xfUL << ID_AA64MMFR1_LOR_SHIFT);
>   }
>  
>   return val;
> @@ -1330,11 +1342,11 @@ static const struct sys_reg_desc sys_reg_descs[] = {
>   { SYS_DESC(SYS_MAIR_EL1), access_vm_reg, reset_unknown, MAIR_EL1 },
>   { SYS_DESC(SYS_AMAIR_EL1), access_vm_reg, reset_amair_el1, AMAIR_EL1 },
>  
> - { SYS_DESC(SYS_LORSA_EL1), trap_undef },
> - { SYS_DESC(SYS_LOREA_EL1), trap_undef },
> - { SYS_DESC(SYS_LORN_EL1), trap_undef },
> - { SYS_DESC(SYS_LORC_EL1), trap_undef },
> - { SYS_DESC(SYS_LORID_EL1), trap_undef },
> + { SYS_DESC(SYS_LORSA_EL1), trap_loregion },
> + { SYS_DESC(SYS_LOREA_EL1), trap_loregion },
> + { SYS_DESC(SYS_LORN_EL1), trap_loregion },
> + { SYS_DESC(SYS_LORC_EL1), trap_loregion },
> + { SYS_DESC(SYS_LORID_EL1), trap_loregion },
>  
>   { SYS_DESC(SYS_VBAR_EL1), NULL, reset_val, VBAR_EL1, 0 },
>   { SYS_DESC(SYS_DISR_EL1), NULL, reset_val, DISR_EL1, 0 },
> -- 
> 2.19.1
> 
___
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm


Re: [PATCH v5 07/17] arm64: add basic pointer authentication support

2018-10-19 Thread Mark Rutland
On Fri, Oct 19, 2018 at 08:36:45AM -0700, Kees Cook wrote:
> On Fri, Oct 19, 2018 at 4:24 AM, Will Deacon  wrote:
> > Assuming we want this (Kees -- I was under the impression that everything in
> > Android would end up with the same key otherwise?), then the question is
> > do we want:
> >
> >   - prctl() get/set operations for the key, or
> >   - prctl() set_random_key operation, or
> >   - both of the above?
> >
> > Part of the answer to that may lie in the requirements of CRIU, where I
> > strongly suspect they need explicit get/set operations, although these
> > could be gated on CONFIG_CHECKPOINT_RESTORE=y.
> 
> Oh CRIU. Yikes. I'd like the get/set to be gated by the CONFIG, yes.
> No reason to allow explicit access to the key (and selected algo) if
> we don't have to.

As a minor aside, the PAC algorithm (which can be IMPLEMENTATION
DEFINED) is fixed in HW, and cannot be selected dynamically.

Thus if a process is using pointer authentication, it would not be
possible for CRIU to migrate that process to a CPU with a different PAC
algorithm.

Thanks,
Mark.
___
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm


[PATCH] kvm: arm64: fix caching of host MDCR_EL2 value

2018-10-17 Thread Mark Rutland
At boot time, KVM stashes the host MDCR_EL2 value, but only does this
when the kernel is not running in hyp mode (i.e. is non-VHE). In these
cases, the stashed value of MDCR_EL2.HPMN happens to be zero, which can
lead to CONSTRAINED UNPREDICTABLE behaviour.

Since we use this value to derive the MDCR_EL2 value when switching
to/from a guest, after a guest have been run, the performance counters
do not behave as expected. This has been observed to result in accesses
via PMXEVTYPER_EL0 and PMXEVCNTR_EL0 not affecting the relevant
counters, resulting in events not being counted. In these cases, only
the fixed-purpose cycle counter appears to work as expected.

Fix this by always stashing the host MDCR_EL2 value, regardless of VHE.

Fixes: 1e947bad0b63b351 ("arm64: KVM: Skip HYP setup when already running in 
HYP")
Signed-off-by: Mark Rutland 
Cc: Christopher Dall 
Cc: James Morse 
Cc: Marc Zyngier 
Cc: Robin Murphy 
Cc: Will Deacon 
Cc: kvmarm@lists.cs.columbia.edu
---
 virt/kvm/arm/arm.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/virt/kvm/arm/arm.c b/virt/kvm/arm/arm.c
index c92053bc3f96..8fb31a7cc22c 100644
--- a/virt/kvm/arm/arm.c
+++ b/virt/kvm/arm/arm.c
@@ -1295,8 +1295,6 @@ static void cpu_init_hyp_mode(void *dummy)
 
__cpu_init_hyp_mode(pgd_ptr, hyp_stack_ptr, vector_ptr);
__cpu_init_stage2();
-
-   kvm_arm_init_debug();
 }
 
 static void cpu_hyp_reset(void)
@@ -1320,6 +1318,8 @@ static void cpu_hyp_reinit(void)
cpu_init_hyp_mode(NULL);
}
 
+   kvm_arm_init_debug();
+
if (vgic_present)
kvm_vgic_init_cpu_hardware();
 }
-- 
2.11.0

___
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm


Re: [PATCH v5 01/17] arm64: add pointer authentication register bits

2018-10-12 Thread Mark Rutland
On Fri, Oct 12, 2018 at 09:56:05AM +0100, Will Deacon wrote:
> On Fri, Oct 12, 2018 at 09:53:54AM +0100, Mark Rutland wrote:
> > On Thu, Oct 11, 2018 at 05:28:14PM +0100, Will Deacon wrote:
> > > On Fri, Oct 05, 2018 at 09:47:38AM +0100, Kristina Martsenko wrote:
> > 
> > > > +#define ESR_ELx_EC_PAC (0x09)
> > > 
> > > Really minor nit: but shouldn't this be ESR_EL2_EC_PAC, since this trap
> > > can't occur at EL1 afaict?
> > 
> > It can also be taken to EL3 dependent on SCR_EL3.API.
> > 
> > We use ESR_ELx_EC_ for other exceptions that can't be taken to EL1
> > (e.g. ESR_ELx_EC_SMC{32,64}), so I think it would be more consistent to
> > leave this as ESR_ELx_EC_PAC rather than ESR_EL2_EC_PAC.
> 
> Fair enough, but if we grow a different EC for ESR_EL1 that uses encoding
> 0x09, this all falls apart.

We haven't had overlapping encodings so far, and if we did, we'd want to
apply some policy to all of these definitions, no?

> At the very list, maybe we should comment those that are EL2 or higher
> with /* EL2 and above */ or just fix the misnomer and drop the useless
> _ELx_ part of the names completely.

A comment sounds fine to me.

I'm not sure that s/_ELx// buys us any clarity, though; I don't think
that ESR_EC_PAC is clearly more constrained than ESR_ELx_EC_PAC.

Thanks,
Mark.
___
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm


Re: [PATCH v5 01/17] arm64: add pointer authentication register bits

2018-10-12 Thread Mark Rutland
On Thu, Oct 11, 2018 at 05:28:14PM +0100, Will Deacon wrote:
> On Fri, Oct 05, 2018 at 09:47:38AM +0100, Kristina Martsenko wrote:

> > +#define ESR_ELx_EC_PAC (0x09)
> 
> Really minor nit: but shouldn't this be ESR_EL2_EC_PAC, since this trap
> can't occur at EL1 afaict?

It can also be taken to EL3 dependent on SCR_EL3.API.

We use ESR_ELx_EC_ for other exceptions that can't be taken to EL1
(e.g. ESR_ELx_EC_SMC{32,64}), so I think it would be more consistent to
leave this as ESR_ELx_EC_PAC rather than ESR_EL2_EC_PAC.

Thanks,
Mark.
___
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm


[PATCH 0/2] arm64: spectre-v1 write fixes (CVE-2018-3693)

2018-07-10 Thread Mark Rutland
These patches inhibit spectre-v1-write gadgets found in arch/arm64, using the
same mitigation applied to existing spectre-v1-read gadgets.

This issue is also known as CVE-2018-3693, or "bounds check bypass store".
More details can be found in the Arm Cache Speculation Side-channels
whitepaper, available from the Arm security updates site [1].

Thanks,
Mark.

[1] 
https://developer.arm.com/support/arm-security-updates/speculative-processor-vulnerability

Mark Rutland (2):
  arm64: fix possible spectre-v1 write in ptrace_hbp_set_event()
  KVM: arm/arm64: vgic: fix possible spectre-v1 write in
vgic_mmio_write_apr()

 arch/arm64/kernel/ptrace.c   | 19 +++
 virt/kvm/arm/vgic/vgic-mmio-v2.c |  3 +++
 2 files changed, 14 insertions(+), 8 deletions(-)

-- 
2.11.0

___
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm


[PATCH 1/2] arm64: fix possible spectre-v1 write in ptrace_hbp_set_event()

2018-07-10 Thread Mark Rutland
It's possible for userspace to control idx. Sanitize idx when using it
as an array index, to inhibit the potential spectre-v1 write gadget.

Found by smatch.

Signed-off-by: Mark Rutland 
Cc: Catalin Marinas 
Cc: Will Deacon 
---
 arch/arm64/kernel/ptrace.c | 19 +++
 1 file changed, 11 insertions(+), 8 deletions(-)

diff --git a/arch/arm64/kernel/ptrace.c b/arch/arm64/kernel/ptrace.c
index 5c338ce5a7fa..db5440339ab3 100644
--- a/arch/arm64/kernel/ptrace.c
+++ b/arch/arm64/kernel/ptrace.c
@@ -277,19 +277,22 @@ static int ptrace_hbp_set_event(unsigned int note_type,
 
switch (note_type) {
case NT_ARM_HW_BREAK:
-   if (idx < ARM_MAX_BRP) {
-   tsk->thread.debug.hbp_break[idx] = bp;
-   err = 0;
-   }
+   if (idx >= ARM_MAX_BRP)
+   goto out;
+   idx = array_index_nospec(idx, ARM_MAX_BRP);
+   tsk->thread.debug.hbp_break[idx] = bp;
+   err = 0;
break;
case NT_ARM_HW_WATCH:
-   if (idx < ARM_MAX_WRP) {
-   tsk->thread.debug.hbp_watch[idx] = bp;
-   err = 0;
-   }
+   if (idx >= ARM_MAX_WRP)
+   goto out;
+   idx = array_index_nospec(idx, ARM_MAX_WRP);
+   tsk->thread.debug.hbp_watch[idx] = bp;
+   err = 0;
break;
}
 
+out:
return err;
 }
 
-- 
2.11.0

___
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm


[PATCH 2/2] KVM: arm/arm64: vgic: fix possible spectre-v1 write in vgic_mmio_write_apr()

2018-07-10 Thread Mark Rutland
It's possible for userspace to control n. Sanitize n when using it as an
array index, to inhibit the potential spectre-v1 write gadget.

Note that while it appears that n must be bound to the interval [0,3]
due to the way it is extracted from addr, we cannot guarantee that
compiler transformations (and/or future refactoring) will ensure this is
the case, and given this is a slow path it's better to always perform
the masking.

Found by smatch.

Signed-off-by: Mark Rutland 
Cc: Christoffer Dall 
Cc: Marc Zyngier 
Cc: kvmarm@lists.cs.columbia.edu
---
 virt/kvm/arm/vgic/vgic-mmio-v2.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/virt/kvm/arm/vgic/vgic-mmio-v2.c b/virt/kvm/arm/vgic/vgic-mmio-v2.c
index ffc587bf4742..64e571cc02df 100644
--- a/virt/kvm/arm/vgic/vgic-mmio-v2.c
+++ b/virt/kvm/arm/vgic/vgic-mmio-v2.c
@@ -352,6 +352,9 @@ static void vgic_mmio_write_apr(struct kvm_vcpu *vcpu,
 
if (n > vgic_v3_max_apr_idx(vcpu))
return;
+
+   n = array_index_nospec(n, 4);
+
/* GICv3 only uses ICH_AP1Rn for memory mapped (GICv2) guests */
vgicv3->vgic_ap1r[n] = val;
}
-- 
2.11.0

___
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm


Re: [PATCH 1/2] KVM: Enforce error in ioctl for compat tasks when !KVM_COMPAT

2018-06-19 Thread Mark Rutland
On Tue, Jun 19, 2018 at 10:42:50AM +0100, Marc Zyngier wrote:
> The current behaviour of the compat ioctls is a bit odd.
> We provide a compat_ioctl method when KVM_COMPAT is set, and NULL
> otherwise. But NULL means that the normal, non-compat ioctl should
> be used directly for compat tasks, and there is no way to actually
> prevent a compat task from issueing KVM ioctls.
> 
> This patch changes this behaviour, by always registering a compat_ioctl
> method, even if KVM_COMPAT is not selected. In that case, the callback
> will always return -EINVAL.
> 
> Reported-by: Mark Rutland 
> Signed-off-by: Marc Zyngier 

I virt/kvm/Kconfig we have:

config KVM_COMPAT
   def_bool y
   depends on KVM && COMPAT && !S390

... and in arch/s390 we have COMPAT support, so does this potentially break
anything there?

Thanks,
Mark.

> ---
>  virt/kvm/kvm_main.c | 19 +--
>  1 file changed, 9 insertions(+), 10 deletions(-)
> 
> diff --git a/virt/kvm/kvm_main.c b/virt/kvm/kvm_main.c
> index ada21f47f22b..8b47507faab5 100644
> --- a/virt/kvm/kvm_main.c
> +++ b/virt/kvm/kvm_main.c
> @@ -116,6 +116,11 @@ static long kvm_vcpu_ioctl(struct file *file, unsigned 
> int ioctl,
>  #ifdef CONFIG_KVM_COMPAT
>  static long kvm_vcpu_compat_ioctl(struct file *file, unsigned int ioctl,
> unsigned long arg);
> +#define KVM_COMPAT(c).compat_ioctl   = (c)
> +#else
> +static long kvm_no_compat_ioctl(struct file *file, unsigned int ioctl,
> + unsigned long arg) { return -EINVAL; }
> +#define KVM_COMPAT(c).compat_ioctl   = kvm_no_compat_ioctl
>  #endif
>  static int hardware_enable_all(void);
>  static void hardware_disable_all(void);
> @@ -2396,11 +2401,9 @@ static int kvm_vcpu_release(struct inode *inode, 
> struct file *filp)
>  static struct file_operations kvm_vcpu_fops = {
>   .release= kvm_vcpu_release,
>   .unlocked_ioctl = kvm_vcpu_ioctl,
> -#ifdef CONFIG_KVM_COMPAT
> - .compat_ioctl   = kvm_vcpu_compat_ioctl,
> -#endif
>   .mmap   = kvm_vcpu_mmap,
>   .llseek = noop_llseek,
> + KVM_COMPAT(kvm_vcpu_compat_ioctl),
>  };
>  
>  /*
> @@ -2824,10 +2827,8 @@ static int kvm_device_release(struct inode *inode, 
> struct file *filp)
>  
>  static const struct file_operations kvm_device_fops = {
>   .unlocked_ioctl = kvm_device_ioctl,
> -#ifdef CONFIG_KVM_COMPAT
> - .compat_ioctl = kvm_device_ioctl,
> -#endif
>   .release = kvm_device_release,
> + KVM_COMPAT(kvm_device_ioctl),
>  };
>  
>  struct kvm_device *kvm_device_from_filp(struct file *filp)
> @@ -3165,10 +3166,8 @@ static long kvm_vm_compat_ioctl(struct file *filp,
>  static struct file_operations kvm_vm_fops = {
>   .release= kvm_vm_release,
>   .unlocked_ioctl = kvm_vm_ioctl,
> -#ifdef CONFIG_KVM_COMPAT
> - .compat_ioctl   = kvm_vm_compat_ioctl,
> -#endif
>   .llseek = noop_llseek,
> + KVM_COMPAT(kvm_vm_compat_ioctl),
>  };
>  
>  static int kvm_dev_ioctl_create_vm(unsigned long type)
> @@ -3259,8 +3258,8 @@ static long kvm_dev_ioctl(struct file *filp,
>  
>  static struct file_operations kvm_chardev_ops = {
>   .unlocked_ioctl = kvm_dev_ioctl,
> - .compat_ioctl   = kvm_dev_ioctl,
>   .llseek = noop_llseek,
> + KVM_COMPAT(kvm_dev_ioctl),
>  };
>  
>  static struct miscdevice kvm_dev = {
> -- 
> 2.17.1
> 
___
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm


Re: [PATCH] KVM: arm64: VHE: Migrate _elx sysreg accessors to msr_s/mrs_s

2018-06-04 Thread Mark Rutland
Hi,

On Tue, May 29, 2018 at 03:20:47PM +0100, Dave Martin wrote:
> Currently, the {read,write}_sysreg_el*() accessors for accessing
> particular ELs' sysregs in the presence of VHE rely on some local
> hacks and define their system register encodings in a way that is
> inconsistent with the core definitions in .
> 
> As a result, it is necessary to add duplicate definitions for any
> system register that already needs a definition in sysreg.h for
> other reasons.
> 
> This is a bit of a maintenance headache, and the reasons for the
> _el*() accessors working the way they do is a bit historical.
> 
> This patch gets rid of the shadow sysreg definitions in
> , converts the _el*() accessors to use the core
> msr_s/mrs_s interface, and converts all call sites to use the
> standard sysreg #define names (i.e., upper case, with SYS_ prefix).

Nice!

[...]

>  static inline unsigned long vcpu_read_elr_el1(const struct kvm_vcpu *vcpu)
>  {
>   if (vcpu->arch.sysregs_loaded_on_cpu)
> - return read_sysreg_el1(elr);
> + return read_sysreg_el1(SYS_ELR);

Could we have the macro implicitly handle the SYS_ prefix?

A further bit of cleanup that I'd like to do is make {read,write}_sysreg() use
{mrs,msr}_s, implicitly handling the SYS_ prefix, so that we can kill off
{read,write}_sysreg_s(), and always use a {read,write}_sysreg().

A minor pain point is that we'd have to convert callers to pass the sysreg name
in upper-case, but that conversion can be scripted fairly easily.

e.g. for the above, read_sysreg() would take ELR_EL1, and read_sysreg_el1()
would take ELR.

Thanks,
Mark.
___
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm


Re: [PATCH v2 2/6] arm64: KVM: Handle Set/Way CMOs as NOPs if FWB is present

2018-05-31 Thread Mark Rutland
On Thu, May 31, 2018 at 02:00:11PM +0100, Marc Zyngier wrote:
> On 31/05/18 12:51, Mark Rutland wrote:
> > On Wed, May 30, 2018 at 01:47:02PM +0100, Marc Zyngier wrote:
> >> Set/Way handling is one of the ugliest corners of KVM. We shouldn't
> >> have to handle that, but better safe than sorry.
> >>
> >> Thankfully, FWB fixes this for us by not requiering any maintenance
> >> whatsoever, which means we don't have to emulate S/W CMOs, and don't
> >> have to track VM ops either.
> >>
> >> We still have to trap S/W though, if only to prevent the guest from
> >> doing something bad.
> > 
> > S/W ops *also* do I-cache maintenance, so we'd still need to emulate
> > that. Though it looks like we're missing that today...
> 
> This doesn't look right: CSSELR_EL1 does indeed have an InD bit, but
> that's only for the purpose of reading CSSIDR_EL1. DC CSW and co
> directly take a level *without* the InD bit, and seem to be limited to
> "data and unified cache".
> 
> Am I missing something?

No; I was mistaken.

Sorry for the noise!

Mark.
___
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm


Re: [PATCH v2 6/6] KVM: arm/arm64: Remove unnecessary CMOs when creating HYP page tables

2018-05-31 Thread Mark Rutland
On Wed, May 30, 2018 at 01:47:06PM +0100, Marc Zyngier wrote:
> There is no need to perform cache maintenance operations when
> creating the HYP page tables if we have the multiprocessing
> extensions. ARMv7 mandates them with the virtualization support,
> and ARMv8 just mandates them unconditionally.
> 
> Let's remove these operations.
> 
> Signed-off-by: Marc Zyngier 

Acked-by: Mark Rutland 

Mark.

> ---
>  virt/kvm/arm/mmu.c | 4 
>  1 file changed, 4 deletions(-)
> 
> diff --git a/virt/kvm/arm/mmu.c b/virt/kvm/arm/mmu.c
> index ad1980d2118a..ccdf544d44c0 100644
> --- a/virt/kvm/arm/mmu.c
> +++ b/virt/kvm/arm/mmu.c
> @@ -607,7 +607,6 @@ static void create_hyp_pte_mappings(pmd_t *pmd, unsigned 
> long start,
>   pte = pte_offset_kernel(pmd, addr);
>   kvm_set_pte(pte, pfn_pte(pfn, prot));
>   get_page(virt_to_page(pte));
> - kvm_flush_dcache_to_poc(pte, sizeof(*pte));
>   pfn++;
>   } while (addr += PAGE_SIZE, addr != end);
>  }
> @@ -634,7 +633,6 @@ static int create_hyp_pmd_mappings(pud_t *pud, unsigned 
> long start,
>   }
>   kvm_pmd_populate(pmd, pte);
>   get_page(virt_to_page(pmd));
> - kvm_flush_dcache_to_poc(pmd, sizeof(*pmd));
>   }
>  
>   next = pmd_addr_end(addr, end);
> @@ -667,7 +665,6 @@ static int create_hyp_pud_mappings(pgd_t *pgd, unsigned 
> long start,
>   }
>   kvm_pud_populate(pud, pmd);
>   get_page(virt_to_page(pud));
> - kvm_flush_dcache_to_poc(pud, sizeof(*pud));
>   }
>  
>   next = pud_addr_end(addr, end);
> @@ -704,7 +701,6 @@ static int __create_hyp_mappings(pgd_t *pgdp, unsigned 
> long ptrs_per_pgd,
>   }
>   kvm_pgd_populate(pgd, pud);
>   get_page(virt_to_page(pgd));
> - kvm_flush_dcache_to_poc(pgd, sizeof(*pgd));
>   }
>  
>   next = pgd_addr_end(addr, end);
> -- 
> 2.17.1
> 
___
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm


Re: [PATCH v2 5/6] KVM: arm/arm64: Stop using {pmd,pud,pgd}_populate

2018-05-31 Thread Mark Rutland
On Wed, May 30, 2018 at 01:47:05PM +0100, Marc Zyngier wrote:
> The {pmd,pud,pgd}_populate accessors usage in the kernel have always
> been a bit weird in KVM. We don't have a struct mm to pass (and
> neither does the kernel most of the time, but still...), and
> the 32bit code has all kind of cache maintenance that doesn't make
> sense on ARMv7+ when MP extensions are mandatory (which is the
> case when the VEs are present).
> 
> Let's bite the bullet and provide our own implementations. The
> only bit of architectural code left has to do with building the table
> entry itself (arm64 having up to 52bit PA, arm lacking PUD level).
> 
> Signed-off-by: Marc Zyngier 
> ---
>  arch/arm/include/asm/kvm_mmu.h   | 4 
>  arch/arm64/include/asm/kvm_mmu.h | 7 +++
>  virt/kvm/arm/mmu.c   | 8 +---
>  3 files changed, 16 insertions(+), 3 deletions(-)
> 
> diff --git a/arch/arm/include/asm/kvm_mmu.h b/arch/arm/include/asm/kvm_mmu.h
> index 468ff945efa0..a94ef9833bd3 100644
> --- a/arch/arm/include/asm/kvm_mmu.h
> +++ b/arch/arm/include/asm/kvm_mmu.h
> @@ -75,6 +75,10 @@ phys_addr_t kvm_get_idmap_vector(void);
>  int kvm_mmu_init(void);
>  void kvm_clear_hyp_idmap(void);
>  
> +#define kvm_mk_pmd(ptep) __pmd(__pa(ptep) | PMD_TYPE_TABLE)
> +#define kvm_mk_pud(pmdp) __pud(__pa(pmdp) | PMD_TYPE_TABLE)
> +#define kvm_mk_pgd(pudp) ({ BUILD_BUG(); 0; })

I can't remember how the folding logic works for ARM is a pgd entry the
entire pud table?

Assuming so:

Acked-by: Mark Rutland 

> +
>  static inline pte_t kvm_s2pte_mkwrite(pte_t pte)
>  {
>   pte_val(pte) |= L_PTE_S2_RDWR;
> diff --git a/arch/arm64/include/asm/kvm_mmu.h 
> b/arch/arm64/include/asm/kvm_mmu.h
> index 26c89b63f604..22c9f7cfdf93 100644
> --- a/arch/arm64/include/asm/kvm_mmu.h
> +++ b/arch/arm64/include/asm/kvm_mmu.h
> @@ -170,6 +170,13 @@ phys_addr_t kvm_get_idmap_vector(void);
>  int kvm_mmu_init(void);
>  void kvm_clear_hyp_idmap(void);
>  
> +#define kvm_mk_pmd(ptep) \
> + __pmd(__phys_to_pmd_val(__pa(ptep) | PMD_TYPE_TABLE))
> +#define kvm_mk_pud(pmdp) \
> + __pud(__phys_to_pud_val(__pa(pmdp) | PMD_TYPE_TABLE))
> +#define kvm_mk_pgd(pudp) \
> + __pgd(__phys_to_pgd_val(__pa(pudp) | PUD_TYPE_TABLE))
> +
>  static inline pte_t kvm_s2pte_mkwrite(pte_t pte)
>  {
>   pte_val(pte) |= PTE_S2_RDWR;
> diff --git a/virt/kvm/arm/mmu.c b/virt/kvm/arm/mmu.c
> index c9ed239c0840..ad1980d2118a 100644
> --- a/virt/kvm/arm/mmu.c
> +++ b/virt/kvm/arm/mmu.c
> @@ -191,17 +191,19 @@ static inline void kvm_set_pmd(pmd_t *pmdp, pmd_t 
> new_pmd)
>  
>  static inline void kvm_pmd_populate(pmd_t *pmdp, pte_t *ptep)
>  {
> - pmd_populate_kernel(NULL, pmdp, ptep);
> + kvm_set_pmd(pmdp, kvm_mk_pmd(ptep));
>  }
>  
>  static inline void kvm_pud_populate(pud_t *pudp, pmd_t *pmdp)
>  {
> - pud_populate(NULL, pudp, pmdp);
> + WRITE_ONCE(*pudp, kvm_mk_pud(pmdp));
> + dsb(ishst);
>  }
>  
>  static inline void kvm_pgd_populate(pgd_t *pgdp, pud_t *pudp)
>  {
> - pgd_populate(NULL, pgdp, pudp);
> + WRITE_ONCE(*pgdp, kvm_mk_pgd(pudp));
> + dsb(ishst);
>  }
>  
>  /*
> -- 
> 2.17.1
> 
___
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm


Re: [PATCH v2 4/6] KVM: arm/arm64: Consolidate page-table accessors

2018-05-31 Thread Mark Rutland
On Wed, May 30, 2018 at 01:47:04PM +0100, Marc Zyngier wrote:
> The arm and arm64 KVM page tables accessors are pointlessly different
> between the two architectures, and likely both wrong one way or another:
> arm64 lacks a dsb(), and arm doesn't use WRITE_ONCE.
> 
> Let's unify them.
> 
> Signed-off-by: Marc Zyngier 

Acked-by: Mark Rutland 

Mark.

> ---
>  arch/arm/include/asm/kvm_mmu.h   | 12 ---
>  arch/arm64/include/asm/kvm_mmu.h |  3 ---
>  virt/kvm/arm/mmu.c   | 35 
>  3 files changed, 31 insertions(+), 19 deletions(-)
> 
> diff --git a/arch/arm/include/asm/kvm_mmu.h b/arch/arm/include/asm/kvm_mmu.h
> index 707a1f06dc5d..468ff945efa0 100644
> --- a/arch/arm/include/asm/kvm_mmu.h
> +++ b/arch/arm/include/asm/kvm_mmu.h
> @@ -75,18 +75,6 @@ phys_addr_t kvm_get_idmap_vector(void);
>  int kvm_mmu_init(void);
>  void kvm_clear_hyp_idmap(void);
>  
> -static inline void kvm_set_pmd(pmd_t *pmd, pmd_t new_pmd)
> -{
> - *pmd = new_pmd;
> - dsb(ishst);
> -}
> -
> -static inline void kvm_set_pte(pte_t *pte, pte_t new_pte)
> -{
> - *pte = new_pte;
> - dsb(ishst);
> -}
> -
>  static inline pte_t kvm_s2pte_mkwrite(pte_t pte)
>  {
>   pte_val(pte) |= L_PTE_S2_RDWR;
> diff --git a/arch/arm64/include/asm/kvm_mmu.h 
> b/arch/arm64/include/asm/kvm_mmu.h
> index 9dbca5355029..26c89b63f604 100644
> --- a/arch/arm64/include/asm/kvm_mmu.h
> +++ b/arch/arm64/include/asm/kvm_mmu.h
> @@ -170,9 +170,6 @@ phys_addr_t kvm_get_idmap_vector(void);
>  int kvm_mmu_init(void);
>  void kvm_clear_hyp_idmap(void);
>  
> -#define  kvm_set_pte(ptep, pte)  set_pte(ptep, pte)
> -#define  kvm_set_pmd(pmdp, pmd)  set_pmd(pmdp, pmd)
> -
>  static inline pte_t kvm_s2pte_mkwrite(pte_t pte)
>  {
>   pte_val(pte) |= PTE_S2_RDWR;
> diff --git a/virt/kvm/arm/mmu.c b/virt/kvm/arm/mmu.c
> index ba66bf7ae299..c9ed239c0840 100644
> --- a/virt/kvm/arm/mmu.c
> +++ b/virt/kvm/arm/mmu.c
> @@ -177,6 +177,33 @@ static void clear_stage2_pmd_entry(struct kvm *kvm, 
> pmd_t *pmd, phys_addr_t addr
>   put_page(virt_to_page(pmd));
>  }
>  
> +static inline void kvm_set_pte(pte_t *ptep, pte_t new_pte)
> +{
> + WRITE_ONCE(*ptep, new_pte);
> + dsb(ishst);
> +}
> +
> +static inline void kvm_set_pmd(pmd_t *pmdp, pmd_t new_pmd)
> +{
> + WRITE_ONCE(*pmdp, new_pmd);
> + dsb(ishst);
> +}
> +
> +static inline void kvm_pmd_populate(pmd_t *pmdp, pte_t *ptep)
> +{
> + pmd_populate_kernel(NULL, pmdp, ptep);
> +}
> +
> +static inline void kvm_pud_populate(pud_t *pudp, pmd_t *pmdp)
> +{
> + pud_populate(NULL, pudp, pmdp);
> +}
> +
> +static inline void kvm_pgd_populate(pgd_t *pgdp, pud_t *pudp)
> +{
> + pgd_populate(NULL, pgdp, pudp);
> +}
> +
>  /*
>   * Unmapping vs dcache management:
>   *
> @@ -603,7 +630,7 @@ static int create_hyp_pmd_mappings(pud_t *pud, unsigned 
> long start,
>   kvm_err("Cannot allocate Hyp pte\n");
>   return -ENOMEM;
>   }
> - pmd_populate_kernel(NULL, pmd, pte);
> + kvm_pmd_populate(pmd, pte);
>   get_page(virt_to_page(pmd));
>   kvm_flush_dcache_to_poc(pmd, sizeof(*pmd));
>   }
> @@ -636,7 +663,7 @@ static int create_hyp_pud_mappings(pgd_t *pgd, unsigned 
> long start,
>   kvm_err("Cannot allocate Hyp pmd\n");
>   return -ENOMEM;
>   }
> - pud_populate(NULL, pud, pmd);
> + kvm_pud_populate(pud, pmd);
>   get_page(virt_to_page(pud));
>   kvm_flush_dcache_to_poc(pud, sizeof(*pud));
>   }
> @@ -673,7 +700,7 @@ static int __create_hyp_mappings(pgd_t *pgdp, unsigned 
> long ptrs_per_pgd,
>   err = -ENOMEM;
>   goto out;
>   }
> - pgd_populate(NULL, pgd, pud);
> + kvm_pgd_populate(pgd, pud);
>   get_page(virt_to_page(pgd));
>   kvm_flush_dcache_to_poc(pgd, sizeof(*pgd));
>   }
> @@ -1092,7 +1119,7 @@ static int stage2_set_pte(struct kvm *kvm, struct 
> kvm_mmu_memory_cache *cache,
>   if (!cache)
>   return 0; /* ignore calls from kvm_set_spte_hva */
>   pte = mmu_memory_cache_alloc(cache);
> - pmd_populate_kernel(NULL, pmd, pte);
> + kvm_pmd_populate(pmd, pte);
>   get_page(virt_to_page(pmd));
>   }
>  
> -- 
> 2.17.1
> 
___
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm


Re: [PATCH v2 3/6] arm64: KVM: Avoid marking pages as XN in Stage-2 if CTR_EL0.DIC is set

2018-05-31 Thread Mark Rutland
On Wed, May 30, 2018 at 01:47:03PM +0100, Marc Zyngier wrote:
> On systems where CTR_EL0.DIC is set, we don't need to perform
> icache invalidation to guarantee that we'll fetch the right
> instruction stream.
> 
> This also means that taking a permission fault to invalidate the
> icache is an unnecessary overhead.
> 
> On such systems, we can safely leave the page as being executable.
> 
> Acked-by: Catalin Marinas 
> Signed-off-by: Marc Zyngier 

Acked-by: Mark Rutland 

Mark.

> ---
>  arch/arm64/include/asm/pgtable-prot.h | 14 --
>  1 file changed, 12 insertions(+), 2 deletions(-)
> 
> diff --git a/arch/arm64/include/asm/pgtable-prot.h 
> b/arch/arm64/include/asm/pgtable-prot.h
> index c66c3047400e..78b942c1bea4 100644
> --- a/arch/arm64/include/asm/pgtable-prot.h
> +++ b/arch/arm64/include/asm/pgtable-prot.h
> @@ -77,8 +77,18 @@
>   __val;  \
>})
>  
> -#define PAGE_S2  __pgprot(_PROT_DEFAULT | 
> PAGE_S2_MEMATTR(NORMAL) | PTE_S2_RDONLY | PTE_S2_XN)
> -#define PAGE_S2_DEVICE   __pgprot(_PROT_DEFAULT | 
> PAGE_S2_MEMATTR(DEVICE_nGnRE) | PTE_S2_RDONLY | PTE_S2_XN)
> +#define PAGE_S2_XN   \
> + ({  \
> + u64 __val;  \
> + if (cpus_have_const_cap(ARM64_HAS_CACHE_DIC))   \
> + __val = 0;  \
> + else\
> + __val = PTE_S2_XN;  \
> + __val;  \
> + })
> +
> +#define PAGE_S2  __pgprot(_PROT_DEFAULT | 
> PAGE_S2_MEMATTR(NORMAL) | PTE_S2_RDONLY | PAGE_S2_XN)
> +#define PAGE_S2_DEVICE   __pgprot(_PROT_DEFAULT | 
> PAGE_S2_MEMATTR(DEVICE_nGnRE) | PTE_S2_RDONLY | PAGE_S2_XN)
>  
>  #define PAGE_NONE__pgprot(((_PAGE_DEFAULT) & ~PTE_VALID) | 
> PTE_PROT_NONE | PTE_RDONLY | PTE_NG | PTE_PXN | PTE_UXN)
>  #define PAGE_SHARED  __pgprot(_PAGE_DEFAULT | PTE_USER | PTE_NG | 
> PTE_PXN | PTE_UXN | PTE_WRITE)
> -- 
> 2.17.1
> 
___
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm


Re: [PATCH v2 2/6] arm64: KVM: Handle Set/Way CMOs as NOPs if FWB is present

2018-05-31 Thread Mark Rutland
On Wed, May 30, 2018 at 01:47:02PM +0100, Marc Zyngier wrote:
> Set/Way handling is one of the ugliest corners of KVM. We shouldn't
> have to handle that, but better safe than sorry.
> 
> Thankfully, FWB fixes this for us by not requiering any maintenance
> whatsoever, which means we don't have to emulate S/W CMOs, and don't
> have to track VM ops either.
> 
> We still have to trap S/W though, if only to prevent the guest from
> doing something bad.

S/W ops *also* do I-cache maintenance, so we'd still need to emulate
that. Though it looks like we're missing that today...

> 
> Signed-off-by: Marc Zyngier 
> ---
>  arch/arm64/kvm/sys_regs.c | 8 +++-
>  1 file changed, 7 insertions(+), 1 deletion(-)
> 
> diff --git a/arch/arm64/kvm/sys_regs.c b/arch/arm64/kvm/sys_regs.c
> index 6e3b969391fd..9a740f159245 100644
> --- a/arch/arm64/kvm/sys_regs.c
> +++ b/arch/arm64/kvm/sys_regs.c
> @@ -195,7 +195,13 @@ static bool access_dcsw(struct kvm_vcpu *vcpu,
>   if (!p->is_write)
>   return read_from_write_only(vcpu, p, r);
>  
> - kvm_set_way_flush(vcpu);
> + /*
> +  * Only track S/W ops if we don't have FWB. It still indicates
> +  * that the guest is a bit broken...
> +  */
> + if (!cpus_have_const_cap(ARM64_HAS_STAGE2_FWB))
> + kvm_set_way_flush(vcpu);
> +

Assuming we implement I-cache maintenance, we can have something like:

if (!cpus_have_const_cap(ARM64_HAS_STAGE2_FWB))
kvm_set_way_flush_dcache(vcpu);

kvm_set_way_flush_icache(vcpu);

Thanks,
Mark.

>   return true;
>  }
>  
> -- 
> 2.17.1
> 
___
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm


Re: [PATCH v2 1/6] arm64: KVM: Add support for Stage-2 control of memory types and cacheability

2018-05-31 Thread Mark Rutland
On Wed, May 30, 2018 at 01:47:01PM +0100, Marc Zyngier wrote:
> Up to ARMv8.3, the combinaison of Stage-1 and Stage-2 attributes
> results in the strongest attribute of the two stages.  This means
> that the hypervisor has to perform quite a lot of cache maintenance
> just in case the guest has some non-cacheable mappings around.
> 
> ARMv8.4 solves this problem by offering a different mode (FWB) where
> Stage-2 has total control over the memory attribute (this is limited
> to systems where both I/O and instruction caches are coherent with

s/caches/fetches/ -- the I-caches themselves aren't coherent with the
D-caches (or we could omit I-cache maintenance).

i.e. this implies IDC, but not DIC.

> the dcache). This is achieved by having a different set of memory
> attributes in the page tables, and a new bit set in HCR_EL2.
> 
> On such a system, we can then safely sidestep any form of dcache
> management.
> 
> Acked-by: Catalin Marinas 
> Signed-off-by: Marc Zyngier 
> ---

>  static inline bool vcpu_has_cache_enabled(struct kvm_vcpu *vcpu)
>  {
> @@ -268,7 +269,10 @@ static inline void __clean_dcache_guest_page(kvm_pfn_t 
> pfn, unsigned long size)
>  {
>   void *va = page_address(pfn_to_page(pfn));
>  
> - kvm_flush_dcache_to_poc(va, size);
> + if (!cpus_have_const_cap(ARM64_HAS_STAGE2_FWB))
> + kvm_flush_dcache_to_poc(va, size);
> + else
> + kvm_flush_dcache_to_pou(va, size);
>  }

Te commit message said instruction fetches were coherent, and that no
D-cache maintenance was necessary, so why do we need maintenance to the
PoU?

> +static void cpu_has_fwb(const struct arm64_cpu_capabilities *__unused)
> +{
> + u64 val = read_sysreg_s(SYS_CLIDR_EL1);
> +
> + /* Check that CLIDR_EL1.LOU{U,IS} are both 0 */
> + WARN_ON(val & (7 << 27 | 7 << 21));
> +}

What about CTR_EL0.IDC?

Thanks,
Mark.
___
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm


Re: [PATCH v2 08/17] arm64: ssbd: Restore mitigation status on CPU resume

2018-05-29 Thread Mark Rutland
On Tue, May 29, 2018 at 01:11:12PM +0100, Marc Zyngier wrote:
> On a system where firmware can dynamically change the state of the
> mitigation, the CPU will always come up with the mitigation enabled,
> including when coming back from suspend.
> 
> If the user has requested "no mitigation" via a command line option,
> let's enforce it by calling into the firmware again to disable it.
> 
> Similarily, for a resume from hibernate, the mitigation could have
> been disabled by the boot kernel. Let's ensure that it is set
> back on in that case.
> 
> Signed-off-by: Marc Zyngier 

With teh fixup in swsusp_arch_suspend(), this looks good to me. FWIW:

Reviewed-by: Mark Rutland 

Mark.

> ---
>  arch/arm64/include/asm/cpufeature.h |  6 ++
>  arch/arm64/kernel/cpu_errata.c  |  2 +-
>  arch/arm64/kernel/hibernate.c   | 11 +++
>  arch/arm64/kernel/suspend.c |  8 
>  4 files changed, 26 insertions(+), 1 deletion(-)
> 
> diff --git a/arch/arm64/include/asm/cpufeature.h 
> b/arch/arm64/include/asm/cpufeature.h
> index b0fc3224ce8a..55bc1f073bfb 100644
> --- a/arch/arm64/include/asm/cpufeature.h
> +++ b/arch/arm64/include/asm/cpufeature.h
> @@ -553,6 +553,12 @@ static inline int arm64_get_ssbd_state(void)
>  #endif
>  }
>  
> +#ifdef CONFIG_ARM64_SSBD
> +void arm64_set_ssbd_mitigation(bool state);
> +#else
> +static inline void arm64_set_ssbd_mitigation(bool state) {}
> +#endif
> +
>  #endif /* __ASSEMBLY__ */
>  
>  #endif
> diff --git a/arch/arm64/kernel/cpu_errata.c b/arch/arm64/kernel/cpu_errata.c
> index 2fef634e6953..2b9a31a6a16a 100644
> --- a/arch/arm64/kernel/cpu_errata.c
> +++ b/arch/arm64/kernel/cpu_errata.c
> @@ -303,7 +303,7 @@ void __init arm64_enable_wa2_handling(struct alt_instr 
> *alt,
>   *updptr = cpu_to_le32(aarch64_insn_gen_nop());
>  }
>  
> -static void arm64_set_ssbd_mitigation(bool state)
> +void arm64_set_ssbd_mitigation(bool state)
>  {
>   switch (psci_ops.conduit) {
>   case PSCI_CONDUIT_HVC:
> diff --git a/arch/arm64/kernel/hibernate.c b/arch/arm64/kernel/hibernate.c
> index 1ec5f28c39fc..6b2686d54411 100644
> --- a/arch/arm64/kernel/hibernate.c
> +++ b/arch/arm64/kernel/hibernate.c
> @@ -313,6 +313,17 @@ int swsusp_arch_suspend(void)
>  
>   sleep_cpu = -EINVAL;
>   __cpu_suspend_exit();
> +
> + /*
> +  * Just in case the boot kernel did turn the SSBD
> +  * mitigation off behind our back, let's set the state
> +  * to what we expect it to be.
> +  */
> + switch (arm64_get_ssbd_state()) {
> + case ARM64_SSBD_FORCE_ENABLE:
> + case ARM64_SSBD_KERNEL:
> + arm64_set_ssbd_mitigation(true);
> + }
>   }
>  
>   local_daif_restore(flags);
> diff --git a/arch/arm64/kernel/suspend.c b/arch/arm64/kernel/suspend.c
> index a307b9e13392..70c283368b64 100644
> --- a/arch/arm64/kernel/suspend.c
> +++ b/arch/arm64/kernel/suspend.c
> @@ -62,6 +62,14 @@ void notrace __cpu_suspend_exit(void)
>*/
>   if (hw_breakpoint_restore)
>   hw_breakpoint_restore(cpu);
> +
> + /*
> +  * On resume, firmware implementing dynamic mitigation will
> +  * have turned the mitigation on. If the user has forcefully
> +  * disabled it, make sure their wishes are obeyed.
> +  */
> + if (arm64_get_ssbd_state() == ARM64_SSBD_FORCE_DISABLE)
> + arm64_set_ssbd_mitigation(false);
>  }
>  
>  /*
> -- 
> 2.14.2
> 
___
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm


Re: [PATCHv2] ARM64: KVM: use lm_alias() for kvm_ksym_ref()

2018-05-25 Thread Mark Rutland
On Fri, May 25, 2018 at 12:08:28PM +0100, Marc Zyngier wrote:
> On 25/05/18 11:50, Mark Rutland wrote:
> > On Thu, May 10, 2018 at 12:13:47PM +0100, Mark Rutland wrote:
> >> For historical reasons, we open-code lm_alias() in kvm_ksym_ref().
> >>
> >> Let's use lm_alias() to avoid duplication and make things clearer.
> >>
> >> As we have to pull this from  (which is not safe for
> >> inclusion in assembly), we may as well move the kvm_ksym_ref()
> >> definition into the existing !__ASSEMBLY__ block.
> >>
> >> Signed-off-by: Mark Rutland <mark.rutl...@arm.com>
> >> Cc: Christoffer Dall <christoffer.d...@arm.com>
> >> Cc: Marc Zyngier <marc.zyng...@arm.com>
> >> Cc: kvmarm@lists.cs.columbia.edu
> >> ---
> >>  arch/arm64/include/asm/kvm_asm.h | 7 +--
> >>  1 file changed, 5 insertions(+), 2 deletions(-)
> > 
> > Marc, Christoffer, are you happy to pick this up?
> 
> I've queued it some time ago (see kvmarm/queue), but failed to mention
> it on the list...

Ah, cheers!

I'll drop this from my list of things to poke. :)

Thanks,
Mark.
___
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm


Re: [PATCHv4 06/10] arm64: add basic pointer authentication support

2018-05-25 Thread Mark Rutland
On Wed, May 23, 2018 at 09:42:56AM +0100, Suzuki K Poulose wrote:
> On 03/05/18 14:20, Mark Rutland wrote:
> > +#define __ptrauth_key_install(k, v)\
> > +do {   \
> > +   write_sysreg_s(v.lo, SYS_ ## k ## KEYLO_EL1);   \
> > +   write_sysreg_s(v.hi, SYS_ ## k ## KEYHI_EL1);   \
> > +} while (0)
> 
> I think it might be safer to have parentheses around v, to prevent
> something like __ptrauth_key_install(APIA, *key_val) work fine.

In case v is ever an expression with side-effects, I've made this:

#define __ptrauth_key_install(k, v) \
do {\
struct ptrauth_key __pki_v = (v);   \
write_sysreg_s(__pki_v.lo, SYS_ ## k ## KEYLO_EL1); \
write_sysreg_s(__pki_v.hi, SYS_ ## k ## KEYHI_EL1); \
} while (0)

... though I could just move the raw sysreg accesses into
ptrauth_keys_switch() for now.

[...]

> > +#ifdef CONFIG_ARM64_PNTR_AUTH
> > +   HWCAP_CAP(SYS_ID_AA64ISAR1_EL1, ID_AA64ISAR1_APA_SHIFT, FTR_UNSIGNED, 
> > 1, CAP_HWCAP, HWCAP_APIA),
> > +#endif
> 
> Did you mean CONFIG_ARM64_PTR_AUTH here ?

Yes; fixed now.

Thanks,
Mark.
___
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm


Re: [PATCHv4 05/10] arm64/cpufeature: detect pointer authentication

2018-05-25 Thread Mark Rutland
On Wed, May 23, 2018 at 09:48:28AM +0100, Suzuki K Poulose wrote:
> 
> Mark,
> 
> On 03/05/18 14:20, Mark Rutland wrote:
> > So that we can dynamically handle the presence of pointer authentication
> > functionality, wire up probing code in cpufeature.c.
> > 
> >  From ARMv8.3 onwards, ID_AA64ISAR1 is no longer entirely RES0, and now
> > has four fields describing the presence of pointer authentication
> > functionality:
> > 
> > * APA - address authentication present, using an architected algorithm
> > * API - address authentication present, using an IMP DEF algorithm
> > * GPA - generic authentication present, using an architected algorithm
> > * GPI - generic authentication present, using an IMP DEF algorithm
> > 
> > For the moment we only care about address authentication, so we only
> > need to check APA and API. It is assumed that if all CPUs support an IMP
> > DEF algorithm, the same algorithm is used across all CPUs.
> > 
> > Note that when we implement KVM support, we will also need to ensure
> > that CPUs have uniform support for GPA and GPI.
> > 
> > Signed-off-by: Mark Rutland <mark.rutl...@arm.com>
> > Cc: Catalin Marinas <catalin.mari...@arm.com>
> > Cc: Suzuki K Poulose <suzuki.poul...@arm.com>
> > Cc: Will Deacon <will.dea...@arm.com>
> > ---
> >   arch/arm64/include/asm/cpucaps.h |  5 -
> >   arch/arm64/kernel/cpufeature.c   | 47 
> > 
> >   2 files changed, 51 insertions(+), 1 deletion(-)
> > 
> > diff --git a/arch/arm64/include/asm/cpucaps.h 
> > b/arch/arm64/include/asm/cpucaps.h
> > index bc51b72fafd4..9dcb4d1b14f5 100644
> > --- a/arch/arm64/include/asm/cpucaps.h
> > +++ b/arch/arm64/include/asm/cpucaps.h
> > @@ -48,7 +48,10 @@
> >   #define ARM64_HAS_CACHE_IDC   27
> >   #define ARM64_HAS_CACHE_DIC   28
> >   #define ARM64_HW_DBM  29
> > +#define ARM64_HAS_ADDRESS_AUTH_ARCH30
> > +#define ARM64_HAS_ADDRESS_AUTH_IMP_DEF 31
> 
> Where are these caps used ? I couldn't find anything in the series
> that uses them. Otherwise looks good to me.

Those were consumed by KVM support, which needed to detect if CPUs had
mismatched support. Currently they're just placeholders as I need a
cpucap value for the separate IMP-DEF / architected probing cases.

I *could* get rid of those and just have the ARM64_HAS_ADDRESS_AUTH case
log "Address authentication", but I wanted to have separate messages for
IMP-DEF vs architected.

Thanks,
Mark.
___
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm


Re: [PATCH 3/4] KVM: arm/arm64: Remove unnecessary CMOs when creating HYP page tables

2018-05-24 Thread Mark Rutland
On Thu, May 17, 2018 at 11:35:47AM +0100, Marc Zyngier wrote:
> There is no need to perform cache maintenance operations when
> creating the HYP page tables if we have the multiprocessing
> extensions. ARMv7 mandates them with the virtualization support,
> and ARMv8 just mandates them unconditionally.
> 
> Let's remove these operations.
> 
> Signed-off-by: Marc Zyngier 
> ---
>  virt/kvm/arm/mmu.c | 5 +
>  1 file changed, 1 insertion(+), 4 deletions(-)
> 
> diff --git a/virt/kvm/arm/mmu.c b/virt/kvm/arm/mmu.c
> index ba66bf7ae299..acbfea09578c 100644
> --- a/virt/kvm/arm/mmu.c
> +++ b/virt/kvm/arm/mmu.c
> @@ -578,7 +578,6 @@ static void create_hyp_pte_mappings(pmd_t *pmd, unsigned 
> long start,
>   pte = pte_offset_kernel(pmd, addr);
>   kvm_set_pte(pte, pfn_pte(pfn, prot));
>   get_page(virt_to_page(pte));
> - kvm_flush_dcache_to_poc(pte, sizeof(*pte));
>   pfn++;
>   } while (addr += PAGE_SIZE, addr != end);
>  }
> @@ -605,7 +604,6 @@ static int create_hyp_pmd_mappings(pud_t *pud, unsigned 
> long start,
>   }
>   pmd_populate_kernel(NULL, pmd, pte);
>   get_page(virt_to_page(pmd));
> - kvm_flush_dcache_to_poc(pmd, sizeof(*pmd));
>   }
>  
>   next = pmd_addr_end(addr, end);
> @@ -638,7 +636,6 @@ static int create_hyp_pud_mappings(pgd_t *pgd, unsigned 
> long start,
>   }
>   pud_populate(NULL, pud, pmd);
>   get_page(virt_to_page(pud));
> - kvm_flush_dcache_to_poc(pud, sizeof(*pud));
>   }
>  
>   next = pud_addr_end(addr, end);
> @@ -675,7 +672,6 @@ static int __create_hyp_mappings(pgd_t *pgdp, unsigned 
> long ptrs_per_pgd,
>   }
>   pgd_populate(NULL, pgd, pud);
>   get_page(virt_to_page(pgd));
> - kvm_flush_dcache_to_poc(pgd, sizeof(*pgd));
>   }
>  
>   next = pgd_addr_end(addr, end);
> @@ -685,6 +681,7 @@ static int __create_hyp_mappings(pgd_t *pgdp, unsigned 
> long ptrs_per_pgd,
>   pfn += (next - addr) >> PAGE_SHIFT;
>   } while (addr = next, addr != end);
>  out:
> + dsb(ishst);

I think you need a dsb(ishst) wherever you had a
kvm_flush_dcache_to_poc() previously.

Otherwise, the page table walker could see stale values. e.g. after you
update a bunch of PTE entries and point a PMD entry at those, the PTW
could see the updated PMD entry, but see stale PTE entries, which could
be garbage.

That said, I think for ensuring the *order* those become visible in, you
only need a dmb(ishst), and the ensure they *are visible* you need a
DSB(ISHST) at the end.

Thanks,
Mark.
___
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm


Re: [PATCH 14/14] arm64: KVM: Add ARCH_WORKAROUND_2 discovery through ARCH_FEATURES_FUNC_ID

2018-05-24 Thread Mark Rutland
On Tue, May 22, 2018 at 04:06:48PM +0100, Marc Zyngier wrote:
> Now that all our infrastructure is in place, let's expose the
> availability of ARCH_WORKAROUND_2 to guests. We take this opportunity
> to tidy up a couple of SMCCC constants.
> 
> Acked-by: Christoffer Dall <christoffer.d...@arm.com>
> Signed-off-by: Marc Zyngier <marc.zyng...@arm.com>

Reviewed-by: Mark Rutland <mark.rutl...@arm.com>

Mark.

> ---
>  arch/arm/include/asm/kvm_host.h   | 12 
>  arch/arm64/include/asm/kvm_host.h | 23 +++
>  arch/arm64/kvm/reset.c|  4 
>  virt/kvm/arm/psci.c   | 18 --
>  4 files changed, 55 insertions(+), 2 deletions(-)
> 
> diff --git a/arch/arm/include/asm/kvm_host.h b/arch/arm/include/asm/kvm_host.h
> index c7c28c885a19..d478766b56c1 100644
> --- a/arch/arm/include/asm/kvm_host.h
> +++ b/arch/arm/include/asm/kvm_host.h
> @@ -315,6 +315,18 @@ static inline bool kvm_arm_harden_branch_predictor(void)
>   return false;
>  }
>  
> +#define KVM_SSBD_UNKNOWN -1
> +#define KVM_SSBD_FORCE_DISABLE   0
> +#define KVM_SSBD_EL1_ENTRY   1
> +#define KVM_SSBD_FORCE_ENABLE2
> +#define KVM_SSBD_MITIGATED   3
> +
> +static inline int kvm_arm_have_ssbd(void)
> +{
> + /* No way to detect it yet, pretend it is not there. */
> + return KVM_SSBD_UNKNOWN;
> +}
> +
>  static inline void kvm_vcpu_load_sysregs(struct kvm_vcpu *vcpu) {}
>  static inline void kvm_vcpu_put_sysregs(struct kvm_vcpu *vcpu) {}
>  
> diff --git a/arch/arm64/include/asm/kvm_host.h 
> b/arch/arm64/include/asm/kvm_host.h
> index 9bef3f69bdcd..082b0dbb85c6 100644
> --- a/arch/arm64/include/asm/kvm_host.h
> +++ b/arch/arm64/include/asm/kvm_host.h
> @@ -455,6 +455,29 @@ static inline bool kvm_arm_harden_branch_predictor(void)
>   return cpus_have_const_cap(ARM64_HARDEN_BRANCH_PREDICTOR);
>  }
>  
> +#define KVM_SSBD_UNKNOWN -1
> +#define KVM_SSBD_FORCE_DISABLE   0
> +#define KVM_SSBD_EL1_ENTRY   1
> +#define KVM_SSBD_FORCE_ENABLE2
> +#define KVM_SSBD_MITIGATED   3
> +
> +static inline int kvm_arm_have_ssbd(void)
> +{
> + switch (arm64_get_ssbd_state()) {
> + case ARM64_SSBD_FORCE_DISABLE:
> + return KVM_SSBD_FORCE_DISABLE;
> + case ARM64_SSBD_EL1_ENTRY:
> + return KVM_SSBD_EL1_ENTRY;
> + case ARM64_SSBD_FORCE_ENABLE:
> + return KVM_SSBD_FORCE_ENABLE;
> + case ARM64_SSBD_MITIGATED:
> + return KVM_SSBD_MITIGATED;
> + case ARM64_SSBD_UNKNOWN:
> + default:
> + return KVM_SSBD_UNKNOWN;
> + }
> +}
> +
>  void kvm_vcpu_load_sysregs(struct kvm_vcpu *vcpu);
>  void kvm_vcpu_put_sysregs(struct kvm_vcpu *vcpu);
>  
> diff --git a/arch/arm64/kvm/reset.c b/arch/arm64/kvm/reset.c
> index 3256b9228e75..20a7dfee8494 100644
> --- a/arch/arm64/kvm/reset.c
> +++ b/arch/arm64/kvm/reset.c
> @@ -122,6 +122,10 @@ int kvm_reset_vcpu(struct kvm_vcpu *vcpu)
>   /* Reset PMU */
>   kvm_pmu_vcpu_reset(vcpu);
>  
> + /* Default workaround setup is enabled (if supported) */
> + if (kvm_arm_have_ssbd() == KVM_SSBD_EL1_ENTRY)
> + vcpu->arch.workaround_flags |= VCPU_WORKAROUND_2_FLAG;
> +
>   /* Reset timer */
>   return kvm_timer_vcpu_reset(vcpu);
>  }
> diff --git a/virt/kvm/arm/psci.c b/virt/kvm/arm/psci.c
> index c4762bef13c6..4843bfa1f986 100644
> --- a/virt/kvm/arm/psci.c
> +++ b/virt/kvm/arm/psci.c
> @@ -405,7 +405,7 @@ static int kvm_psci_call(struct kvm_vcpu *vcpu)
>  int kvm_hvc_call_handler(struct kvm_vcpu *vcpu)
>  {
>   u32 func_id = smccc_get_function(vcpu);
> - u32 val = PSCI_RET_NOT_SUPPORTED;
> + u32 val = SMCCC_RET_NOT_SUPPORTED;
>   u32 feature;
>  
>   switch (func_id) {
> @@ -417,7 +417,21 @@ int kvm_hvc_call_handler(struct kvm_vcpu *vcpu)
>   switch(feature) {
>   case ARM_SMCCC_ARCH_WORKAROUND_1:
>   if (kvm_arm_harden_branch_predictor())
> - val = 0;
> + val = SMCCC_RET_SUCCESS;
> + break;
> + case ARM_SMCCC_ARCH_WORKAROUND_2:
> + switch (kvm_arm_have_ssbd()) {
> + case KVM_SSBD_FORCE_DISABLE:
> + case KVM_SSBD_UNKNOWN:
> + break;
> + case KVM_SSBD_EL1_ENTRY:
> + val = SMCCC_RET_SUCCESS;
> + break;
> + case KVM_SSBD_FORCE_ENABLE:
> +

Re: [PATCH 13/14] arm64: KVM: Handle guest's ARCH_WORKAROUND_2 requests

2018-05-24 Thread Mark Rutland
On Tue, May 22, 2018 at 04:06:47PM +0100, Marc Zyngier wrote:
> In order to forward the guest's ARCH_WORKAROUND_2 calls to EL3,
> add a small(-ish) sequence to handle it at EL2. Special care must
> be taken to track the state of the guest itself by updating the
> workaround flags. We also rely on patching to enable calls into
> the firmware.
> 
> Note that since we need to execute branches, this always executes
> after the Spectre-v2 mitigation has been applied.
> 
> Signed-off-by: Marc Zyngier <marc.zyng...@arm.com>
> ---
>  arch/arm64/kernel/asm-offsets.c |  1 +
>  arch/arm64/kvm/hyp/hyp-entry.S  | 38 +-
>  2 files changed, 38 insertions(+), 1 deletion(-)
> 
> diff --git a/arch/arm64/kernel/asm-offsets.c b/arch/arm64/kernel/asm-offsets.c
> index 5bdda651bd05..323aeb5f2fe6 100644
> --- a/arch/arm64/kernel/asm-offsets.c
> +++ b/arch/arm64/kernel/asm-offsets.c
> @@ -136,6 +136,7 @@ int main(void)
>  #ifdef CONFIG_KVM_ARM_HOST
>DEFINE(VCPU_CONTEXT,   offsetof(struct kvm_vcpu, arch.ctxt));
>DEFINE(VCPU_FAULT_DISR,offsetof(struct kvm_vcpu, arch.fault.disr_el1));
> +  DEFINE(VCPU_WORKAROUND_FLAGS,  offsetof(struct kvm_vcpu, 
> arch.workaround_flags));
>DEFINE(CPU_GP_REGS,offsetof(struct kvm_cpu_context, 
> gp_regs));
>DEFINE(CPU_USER_PT_REGS,   offsetof(struct kvm_regs, regs));
>DEFINE(CPU_FP_REGS,offsetof(struct kvm_regs, fp_regs));
> diff --git a/arch/arm64/kvm/hyp/hyp-entry.S b/arch/arm64/kvm/hyp/hyp-entry.S
> index bffece27b5c1..5b1fa37ca1f4 100644
> --- a/arch/arm64/kvm/hyp/hyp-entry.S
> +++ b/arch/arm64/kvm/hyp/hyp-entry.S
> @@ -106,8 +106,44 @@ el1_hvc_guest:
>*/
>   ldr x1, [sp]// Guest's x0
>   eor w1, w1, #ARM_SMCCC_ARCH_WORKAROUND_1
> + cbz w1, wa_epilogue
> +
> + /* ARM_SMCCC_ARCH_WORKAROUND_2 handling */
> + eor w1, w1, #(ARM_SMCCC_ARCH_WORKAROUND_1 ^ \
> +   ARM_SMCCC_ARCH_WORKAROUND_2)

... that took me a second. Lovely. :)

>   cbnzw1, el1_trap
> - mov x0, x1
> +
> +#ifdef CONFIG_ARM64_SSBD
> +alternative_cb   arm64_enable_wa2_handling
> + b   wa2_end
> +alternative_cb_end
> + get_vcpu_ptrx2, x0
> + ldr x0, [x2, #VCPU_WORKAROUND_FLAGS]
> +
> + /* Sanitize the argument and update the guest flags*/

Nit: space before the trailing '*/'. Either that or use a '//' comment.

Otherwise, this looks fine, so with that fixed:

Reviewed-by: Mark Rutland <mark.rutl...@arm.com>

Mark.

> + ldr x1, [sp, #8]// Guest's x1
> + clz w1, w1  // Murphy's device:
> + lsr w1, w1, #5  // w1 = !!w1 without using
> + eor w1, w1, #1  // the flags...
> + bfi x0, x1, #VCPU_WORKAROUND_2_FLAG_SHIFT, #1
> + str x0, [x2, #VCPU_WORKAROUND_FLAGS]
> +
> + /* Check that we actually need to perform the call */
> + hyp_ldr_this_cpu x0, arm64_ssbd_callback_required, x2
> + cbz x0, wa2_end
> +
> + mov w0, #ARM_SMCCC_ARCH_WORKAROUND_2
> + smc #0
> +
> + /* Don't leak data from the SMC call */
> + mov x3, xzr
> +wa2_end:
> + mov x2, xzr
> + mov x1, xzr
> +#endif
> +
> +wa_epilogue:
> + mov x0, xzr
>   add sp, sp, #16
>   eret
>  
> -- 
> 2.14.2
> 
___
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm


Re: [PATCH 12/14] arm64: KVM: Add ARCH_WORKAROUND_2 support for guests

2018-05-24 Thread Mark Rutland
On Tue, May 22, 2018 at 04:06:46PM +0100, Marc Zyngier wrote:
> In order to offer ARCH_WORKAROUND_2 support to guests, we need
> a bit of infrastructure.
> 
> Let's add a flag indicating whether or not the guest uses
> SSBD mitigation. Depending on the state of this flag, allow
> KVM to disable ARCH_WORKAROUND_2 before entering the guest,
> and enable it when exiting it.
> 
> Reviewed-by: Christoffer Dall <christoffer.d...@arm.com>
> Signed-off-by: Marc Zyngier <marc.zyng...@arm.com>

Reviewed-by: Mark Rutland <mark.rutl...@arm.com>

Mark.

> ---
>  arch/arm/include/asm/kvm_mmu.h|  5 +
>  arch/arm64/include/asm/kvm_asm.h  |  3 +++
>  arch/arm64/include/asm/kvm_host.h |  3 +++
>  arch/arm64/include/asm/kvm_mmu.h  | 24 ++
>  arch/arm64/kvm/hyp/switch.c   | 42 
> +++
>  virt/kvm/arm/arm.c|  4 
>  6 files changed, 81 insertions(+)
> 
> diff --git a/arch/arm/include/asm/kvm_mmu.h b/arch/arm/include/asm/kvm_mmu.h
> index 707a1f06dc5d..b0c17d88ed40 100644
> --- a/arch/arm/include/asm/kvm_mmu.h
> +++ b/arch/arm/include/asm/kvm_mmu.h
> @@ -319,6 +319,11 @@ static inline int kvm_map_vectors(void)
>   return 0;
>  }
>  
> +static inline int hyp_map_aux_data(void)
> +{
> + return 0;
> +}
> +
>  #define kvm_phys_to_vttbr(addr)  (addr)
>  
>  #endif   /* !__ASSEMBLY__ */
> diff --git a/arch/arm64/include/asm/kvm_asm.h 
> b/arch/arm64/include/asm/kvm_asm.h
> index fefd8cf42c35..d4fbb1356c4c 100644
> --- a/arch/arm64/include/asm/kvm_asm.h
> +++ b/arch/arm64/include/asm/kvm_asm.h
> @@ -33,6 +33,9 @@
>  #define KVM_ARM64_DEBUG_DIRTY_SHIFT  0
>  #define KVM_ARM64_DEBUG_DIRTY(1 << 
> KVM_ARM64_DEBUG_DIRTY_SHIFT)
>  
> +#define  VCPU_WORKAROUND_2_FLAG_SHIFT0
> +#define  VCPU_WORKAROUND_2_FLAG  (_AC(1, UL) << 
> VCPU_WORKAROUND_2_FLAG_SHIFT)
> +
>  /* Translate a kernel address of @sym into its equivalent linear mapping */
>  #define kvm_ksym_ref(sym)\
>   ({  \
> diff --git a/arch/arm64/include/asm/kvm_host.h 
> b/arch/arm64/include/asm/kvm_host.h
> index 469de8acd06f..9bef3f69bdcd 100644
> --- a/arch/arm64/include/asm/kvm_host.h
> +++ b/arch/arm64/include/asm/kvm_host.h
> @@ -216,6 +216,9 @@ struct kvm_vcpu_arch {
>   /* Exception Information */
>   struct kvm_vcpu_fault_info fault;
>  
> + /* State of various workarounds, see kvm_asm.h for bit assignment */
> + u64 workaround_flags;
> +
>   /* Guest debug state */
>   u64 debug_flags;
>  
> diff --git a/arch/arm64/include/asm/kvm_mmu.h 
> b/arch/arm64/include/asm/kvm_mmu.h
> index 082110993647..eb7a5c2a2bfb 100644
> --- a/arch/arm64/include/asm/kvm_mmu.h
> +++ b/arch/arm64/include/asm/kvm_mmu.h
> @@ -457,6 +457,30 @@ static inline int kvm_map_vectors(void)
>  }
>  #endif
>  
> +#ifdef CONFIG_ARM64_SSBD
> +DECLARE_PER_CPU_READ_MOSTLY(u64, arm64_ssbd_callback_required);
> +
> +static inline int hyp_map_aux_data(void)
> +{
> + int cpu, err;
> +
> + for_each_possible_cpu(cpu) {
> + u64 *ptr;
> +
> + ptr = per_cpu_ptr(_ssbd_callback_required, cpu);
> + err = create_hyp_mappings(ptr, ptr + 1, PAGE_HYP);
> + if (err)
> + return err;
> + }
> + return 0;
> +}
> +#else
> +static inline int hyp_map_aux_data(void)
> +{
> + return 0;
> +}
> +#endif
> +
>  #define kvm_phys_to_vttbr(addr)  phys_to_ttbr(addr)
>  
>  #endif /* __ASSEMBLY__ */
> diff --git a/arch/arm64/kvm/hyp/switch.c b/arch/arm64/kvm/hyp/switch.c
> index d9645236e474..c50cedc447f1 100644
> --- a/arch/arm64/kvm/hyp/switch.c
> +++ b/arch/arm64/kvm/hyp/switch.c
> @@ -15,6 +15,7 @@
>   * along with this program.  If not, see <http://www.gnu.org/licenses/>.
>   */
>  
> +#include 
>  #include 
>  #include 
>  #include 
> @@ -389,6 +390,39 @@ static bool __hyp_text fixup_guest_exit(struct kvm_vcpu 
> *vcpu, u64 *exit_code)
>   return false;
>  }
>  
> +static inline bool __hyp_text __needs_ssbd_off(struct kvm_vcpu *vcpu)
> +{
> + if (!cpus_have_const_cap(ARM64_SSBD))
> + return false;
> +
> + return !(vcpu->arch.workaround_flags & VCPU_WORKAROUND_2_FLAG);
> +}
> +
> +static void __hyp_text __set_guest_arch_workaround_state(struct kvm_vcpu 
> *vcpu)
> +{
> +#ifdef CONFIG_ARM64_SSBD
> + /*
> +  * The host runs with the workaround always present. If the

Re: [PATCH 11/14] arm64: KVM: Add HYP per-cpu accessors

2018-05-24 Thread Mark Rutland
On Tue, May 22, 2018 at 04:06:45PM +0100, Marc Zyngier wrote:
> As we're going to require to access per-cpu variables at EL2,
> let's craft the minimum set of accessors required to implement
> reading a per-cpu variable, relying on tpidr_el2 to contain the
> per-cpu offset.
> 
> Reviewed-by: Christoffer Dall <christoffer.d...@arm.com>
> Signed-off-by: Marc Zyngier <marc.zyng...@arm.com>

Reviewed-by: Mark Rutland <mark.rutl...@arm.com>

Mark.

> ---
>  arch/arm64/include/asm/kvm_asm.h | 27 +--
>  1 file changed, 25 insertions(+), 2 deletions(-)
> 
> diff --git a/arch/arm64/include/asm/kvm_asm.h 
> b/arch/arm64/include/asm/kvm_asm.h
> index f6648a3e4152..fefd8cf42c35 100644
> --- a/arch/arm64/include/asm/kvm_asm.h
> +++ b/arch/arm64/include/asm/kvm_asm.h
> @@ -71,14 +71,37 @@ extern u32 __kvm_get_mdcr_el2(void);
>  
>  extern u32 __init_stage2_translation(void);
>  
> +/* Home-grown __this_cpu_{ptr,read} variants that always work at HYP */
> +#define __hyp_this_cpu_ptr(sym)  
> \
> + ({  \
> + void *__ptr = hyp_symbol_addr(sym); \
> + __ptr += read_sysreg(tpidr_el2);\
> + (typeof())__ptr;\
> +  })
> +
> +#define __hyp_this_cpu_read(sym) \
> + ({  \
> + *__hyp_this_cpu_ptr(sym);   \
> +  })
> +
>  #else /* __ASSEMBLY__ */
>  
> -.macro get_host_ctxt reg, tmp
> - adr_l   \reg, kvm_host_cpu_state
> +.macro hyp_adr_this_cpu reg, sym, tmp
> + adr_l   \reg, \sym
>   mrs \tmp, tpidr_el2
>   add \reg, \reg, \tmp
>  .endm
>  
> +.macro hyp_ldr_this_cpu reg, sym, tmp
> + adr_l   \reg, \sym
> + mrs \tmp, tpidr_el2
> + ldr \reg,  [\reg, \tmp]
> +.endm
> +
> +.macro get_host_ctxt reg, tmp
> + hyp_adr_this_cpu \reg, kvm_host_cpu_state, \tmp
> +.endm
> +
>  .macro get_vcpu_ptr vcpu, ctxt
>   get_host_ctxt \ctxt, \vcpu
>   ldr \vcpu, [\ctxt, #HOST_CONTEXT_VCPU]
> -- 
> 2.14.2
> 
___
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm


Re: [PATCH 10/14] arm64: ssbd: Add prctl interface for per-thread mitigation

2018-05-24 Thread Mark Rutland
On Tue, May 22, 2018 at 04:06:44PM +0100, Marc Zyngier wrote:
> If running on a system that performs dynamic SSBD mitigation, allow
> userspace to request the mitigation for itself. This is implemented
> as a prctl call, allowing the mitigation to be enabled or disabled at
> will for this particular thread.
> 
> Signed-off-by: Marc Zyngier 
> ---
>  arch/arm64/kernel/Makefile |   1 +
>  arch/arm64/kernel/ssbd.c   | 107 
> +
>  2 files changed, 108 insertions(+)
>  create mode 100644 arch/arm64/kernel/ssbd.c
> 
> diff --git a/arch/arm64/kernel/Makefile b/arch/arm64/kernel/Makefile
> index bf825f38d206..0025f8691046 100644
> --- a/arch/arm64/kernel/Makefile
> +++ b/arch/arm64/kernel/Makefile
> @@ -54,6 +54,7 @@ arm64-obj-$(CONFIG_ARM64_RELOC_TEST)+= 
> arm64-reloc-test.o
>  arm64-reloc-test-y := reloc_test_core.o reloc_test_syms.o
>  arm64-obj-$(CONFIG_CRASH_DUMP)   += crash_dump.o
>  arm64-obj-$(CONFIG_ARM_SDE_INTERFACE)+= sdei.o
> +arm64-obj-$(CONFIG_ARM64_SSBD)   += ssbd.o
>  
>  obj-y+= $(arm64-obj-y) vdso/ probes/
>  obj-m+= $(arm64-obj-m)
> diff --git a/arch/arm64/kernel/ssbd.c b/arch/arm64/kernel/ssbd.c
> new file mode 100644
> index ..34e3c430176b
> --- /dev/null
> +++ b/arch/arm64/kernel/ssbd.c
> @@ -0,0 +1,107 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * Copyright (C) 2018 ARM Ltd, All Rights Reserved.
> + */
> +

#include 

... for the error numbers you return below.

> +#include 
> +#include 
> +
> +#include 
> +
> +/*
> + * prctl interface for SSBD
> + * FIXME: Drop the below ifdefery once the common interface has been merged.
> + */
> +#ifdef PR_SPEC_STORE_BYPASS
> +static int ssbd_prctl_set(struct task_struct *task, unsigned long ctrl)
> +{
> + int state = arm64_get_ssbd_state();
> +
> + /* Unsupported or already mitigated */
> + if (state == ARM64_SSBD_UNKNOWN)
> + return -EINVAL;
> + if (state == ARM64_SSBD_MITIGATED)
> + return -EPERM;
> +
> + /*
> +  * Things are a bit backward here: the arm64 internal API
> +  * *enables the mitigation* when the userspace API *disables
> +  * speculation*. So much fun.
> +  */
> + switch (ctrl) {
> + case PR_SPEC_ENABLE:
> + /* If speculation is force disabled, enable is not allowed */
> + if (state == ARM64_SSBD_FORCE_ENABLE ||
> + task_spec_ssb_force_disable(task))
> + return -EPERM;
> + task_clear_spec_ssb_disable(task);
> + clear_tsk_thread_flag(task, TIF_SSBD);
> + break;
> + case PR_SPEC_DISABLE:
> + if (state == ARM64_SSBD_FORCE_DISABLE)
> + return -EPERM;
> + task_set_spec_ssb_disable(task);
> + set_tsk_thread_flag(task, TIF_SSBD);
> + break;
> + case PR_SPEC_FORCE_DISABLE:
> + if (state == ARM64_SSBD_FORCE_DISABLE)
> + return -EPERM;
> + task_set_spec_ssb_disable(task);
> + task_set_spec_ssb_force_disable(task);
> + set_tsk_thread_flag(task, TIF_SSBD);
> + break;
> + default:
> + return -ERANGE;
> + }
> +
> + return 0;
> +}

I'll have to take a look at the core implementation to make sense of
the rest.

Mark.
___
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm


Re: [PATCH 09/14] arm64: ssbd: Introduce thread flag to control userspace mitigation

2018-05-24 Thread Mark Rutland
On Tue, May 22, 2018 at 04:06:43PM +0100, Marc Zyngier wrote:
> In order to allow userspace to be mitigated on demand, let's
> introduce a new thread flag that prevents the mitigation from
> being turned off when exiting to userspace, and doesn't turn
> it on on entry into the kernel (with the assumtion that the

Nit: s/assumtion/assumption/

> mitigation is always enabled in the kernel itself).
> 
> This will be used by a prctl interface introduced in a later
> patch.
> 
> Signed-off-by: Marc Zyngier <marc.zyng...@arm.com>

On the assumption that this flag cannot be flipped while a task is in
userspace:

Reviewed-by: Mark Rutland <mark.rutl...@arm.com>

Mark.

> ---
>  arch/arm64/include/asm/thread_info.h | 1 +
>  arch/arm64/kernel/entry.S| 2 ++
>  2 files changed, 3 insertions(+)
> 
> diff --git a/arch/arm64/include/asm/thread_info.h 
> b/arch/arm64/include/asm/thread_info.h
> index 740aa03c5f0d..cbcf11b5e637 100644
> --- a/arch/arm64/include/asm/thread_info.h
> +++ b/arch/arm64/include/asm/thread_info.h
> @@ -94,6 +94,7 @@ void arch_release_task_struct(struct task_struct *tsk);
>  #define TIF_32BIT22  /* 32bit process */
>  #define TIF_SVE  23  /* Scalable Vector Extension in 
> use */
>  #define TIF_SVE_VL_INHERIT   24  /* Inherit sve_vl_onexec across exec */
> +#define TIF_SSBD 25  /* Wants SSB mitigation */
>  
>  #define _TIF_SIGPENDING  (1 << TIF_SIGPENDING)
>  #define _TIF_NEED_RESCHED(1 << TIF_NEED_RESCHED)
> diff --git a/arch/arm64/kernel/entry.S b/arch/arm64/kernel/entry.S
> index e6f6e2339b22..28ad8799406f 100644
> --- a/arch/arm64/kernel/entry.S
> +++ b/arch/arm64/kernel/entry.S
> @@ -147,6 +147,8 @@ alternative_cbarm64_enable_wa2_handling
>  alternative_cb_end
>   ldr_this_cpu\tmp2, arm64_ssbd_callback_required, \tmp1
>   cbz \tmp2, \targ
> + ldr \tmp2, [tsk, #TSK_TI_FLAGS]
> + tbnz\tmp2, #TIF_SSBD, \targ
>   mov w0, #ARM_SMCCC_ARCH_WORKAROUND_2
>   mov w1, #\state
>  alternative_cb   arm64_update_smccc_conduit
> -- 
> 2.14.2
> 
> ___
> kvmarm mailing list
> kvmarm@lists.cs.columbia.edu
> https://lists.cs.columbia.edu/mailman/listinfo/kvmarm
___
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm


Re: [PATCH 07/14] arm64: ssbd: Skip apply_ssbd if not using dynamic mitigation

2018-05-24 Thread Mark Rutland
On Tue, May 22, 2018 at 04:06:41PM +0100, Marc Zyngier wrote:
> In order to avoid checking arm64_ssbd_callback_required on each
> kernel entry/exit even if no mitigation is required, let's
> add yet another alternative that by default jumps over the mitigation,
> and that gets nop'ed out if we're doing dynamic mitigation.
> 
> Think of it as a poor man's static key...

I guess in future we can magic up a more general asm static key if we
need them elsewhere.

> Signed-off-by: Marc Zyngier <marc.zyng...@arm.com>

Reviewed-by: Mark Rutland <mark.rutl...@arm.com>

Mark.

> ---
>  arch/arm64/kernel/cpu_errata.c | 14 ++
>  arch/arm64/kernel/entry.S  |  3 +++
>  2 files changed, 17 insertions(+)
> 
> diff --git a/arch/arm64/kernel/cpu_errata.c b/arch/arm64/kernel/cpu_errata.c
> index f1d4e75b0ddd..8f686f39b9c1 100644
> --- a/arch/arm64/kernel/cpu_errata.c
> +++ b/arch/arm64/kernel/cpu_errata.c
> @@ -283,6 +283,20 @@ void __init arm64_update_smccc_conduit(struct alt_instr 
> *alt,
>   *updptr = cpu_to_le32(insn);
>  }
>  
> +void __init arm64_enable_wa2_handling(struct alt_instr *alt,
> +   __le32 *origptr, __le32 *updptr,
> +   int nr_inst)
> +{
> + BUG_ON(nr_inst != 1);
> + /*
> +  * Only allow mitigation on EL1 entry/exit and guest
> +  * ARCH_WORKAROUND_2 handling if the SSBD state allows it to
> +  * be flipped.
> +  */
> + if (arm64_get_ssbd_state() == ARM64_SSBD_EL1_ENTRY)
> + *updptr = cpu_to_le32(aarch64_insn_gen_nop());
> +}
> +
>  static void do_ssbd(bool state)
>  {
>   switch (psci_ops.conduit) {
> diff --git a/arch/arm64/kernel/entry.S b/arch/arm64/kernel/entry.S
> index 29ad672a6abd..e6f6e2339b22 100644
> --- a/arch/arm64/kernel/entry.S
> +++ b/arch/arm64/kernel/entry.S
> @@ -142,6 +142,9 @@ alternative_else_nop_endif
>   // to save/restore them if required.
>   .macro  apply_ssbd, state, targ, tmp1, tmp2
>  #ifdef CONFIG_ARM64_SSBD
> +alternative_cb   arm64_enable_wa2_handling
> + b   \targ
> +alternative_cb_end
>   ldr_this_cpu\tmp2, arm64_ssbd_callback_required, \tmp1
>   cbz \tmp2, \targ
>   mov w0, #ARM_SMCCC_ARCH_WORKAROUND_2
> -- 
> 2.14.2
> 
___
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm


Re: [PATCH 05/14] arm64: Add 'ssbd' command-line option

2018-05-24 Thread Mark Rutland
On Tue, May 22, 2018 at 04:06:39PM +0100, Marc Zyngier wrote:
> On a system where the firmware implements ARCH_WORKAROUND_2,
> it may be useful to either permanently enable or disable the
> workaround for cases where the user decides that they'd rather
> not get a trap overhead, and keep the mitigation permanently
> on or off instead of switching it on exception entry/exit.
> 
> In any case, default to the mitigation being enabled.
> 
> Signed-off-by: Marc Zyngier <marc.zyng...@arm.com>
> ---
>  Documentation/admin-guide/kernel-parameters.txt |  17 
>  arch/arm64/include/asm/cpufeature.h |   6 ++
>  arch/arm64/kernel/cpu_errata.c  | 102 
> 
>  3 files changed, 109 insertions(+), 16 deletions(-)
> 
> diff --git a/Documentation/admin-guide/kernel-parameters.txt 
> b/Documentation/admin-guide/kernel-parameters.txt
> index f2040d46f095..646e112c6f63 100644
> --- a/Documentation/admin-guide/kernel-parameters.txt
> +++ b/Documentation/admin-guide/kernel-parameters.txt
> @@ -4092,6 +4092,23 @@
>   expediting.  Set to zero to disable automatic
>   expediting.
>  
> + ssbd=   [ARM64,HW]
> + Speculative Store Bypass Disable control
> +
> + On CPUs that are vulnerable to the Speculative
> + Store Bypass vulnerability and offer a
> + firmware based mitigation, this parameter
> + indicates how the mitigation should be used:
> +
> + force-on:  Unconditionnaly enable mitigation for
> +for both kernel and userspace
> + force-off: Unconditionnaly disable mitigation for
> +for both kernel and userspace
> + kernel:Always enable mitigation in the
> +kernel, and offer a prctl interface
> +to allow userspace to register its
> +interest in being mitigated too.
> +
>   stack_guard_gap=[MM]
>   override the default stack gap protection. The value
>   is in page units and it defines how many pages prior
> diff --git a/arch/arm64/include/asm/cpufeature.h 
> b/arch/arm64/include/asm/cpufeature.h
> index 09b0f2a80c8f..9bc548e22784 100644
> --- a/arch/arm64/include/asm/cpufeature.h
> +++ b/arch/arm64/include/asm/cpufeature.h
> @@ -537,6 +537,12 @@ static inline u64 read_zcr_features(void)
>   return zcr;
>  }
>  
> +#define ARM64_SSBD_UNKNOWN   -1
> +#define ARM64_SSBD_FORCE_DISABLE 0
> +#define ARM64_SSBD_EL1_ENTRY 1

The EL1_ENTRY part of the name is a bit misleading, since this doesn't
apply to EL1->EL1 exceptions (and as with many other bits of the arm64
code, it's arguably misleading in the VHE case).

Perhaps ARM64_SSBD_KERNEL, which would align with the parameter name?

Not a big deal either way, and otherwise this looks good to me.
Regardless:

Reviewed-by: Mark Rutland <mark.rutl...@arm.com>

Mark.

> +#define ARM64_SSBD_FORCE_ENABLE  2
> +#define ARM64_SSBD_MITIGATED 3
> +
>  #endif /* __ASSEMBLY__ */
>  
>  #endif
> diff --git a/arch/arm64/kernel/cpu_errata.c b/arch/arm64/kernel/cpu_errata.c
> index 7fd6d5b001f5..f1d4e75b0ddd 100644
> --- a/arch/arm64/kernel/cpu_errata.c
> +++ b/arch/arm64/kernel/cpu_errata.c
> @@ -235,6 +235,38 @@ enable_smccc_arch_workaround_1(const struct 
> arm64_cpu_capabilities *entry)
>  #ifdef CONFIG_ARM64_SSBD
>  DEFINE_PER_CPU_READ_MOSTLY(u64, arm64_ssbd_callback_required);
>  
> +int ssbd_state __read_mostly = ARM64_SSBD_EL1_ENTRY;
> +
> +static const struct ssbd_options {
> + const char  *str;
> + int state;
> +} ssbd_options[] = {
> + { "force-on",   ARM64_SSBD_FORCE_ENABLE, },
> + { "force-off",  ARM64_SSBD_FORCE_DISABLE, },
> + { "kernel", ARM64_SSBD_EL1_ENTRY, },
> +};
> +
> +static int __init ssbd_cfg(char *buf)
> +{
> + int i;
> +
> + if (!buf || !buf[0])
> + return -EINVAL;
> +
> + for (i = 0; i < ARRAY_SIZE(ssbd_options); i++) {
> + int len = strlen(ssbd_options[i].str);
> +
> + if (strncmp(buf, ssbd_options[i].str, len))
> + continue;
> +
> + ssbd_state = ssbd_options[i].state;
> + return 0;
> + }
> +
> + return -EINVAL;
> +}
> +early_param("ssbd", ssbd_cfg);
> +
>  void __init arm64_update_smccc_conduit(struct alt_instr *alt,
> 

Re: [PATCH 04/14] arm64: Add ARCH_WORKAROUND_2 probing

2018-05-24 Thread Mark Rutland
On Tue, May 22, 2018 at 04:06:38PM +0100, Marc Zyngier wrote:
> As for Spectre variant-2, we rely on SMCCC 1.1 to provide the
> discovery mechanism for detecting the SSBD mitigation.
> 
> A new capability is also allocated for that purpose, and a
> config option.
> 
> Signed-off-by: Marc Zyngier <marc.zyng...@arm.com>

Reviewed-by: Mark Rutland <mark.rutl...@arm.com>

[...]

> +static void do_ssbd(bool state)
> +{
> + switch (psci_ops.conduit) {
> + case PSCI_CONDUIT_HVC:
> + arm_smccc_1_1_hvc(ARM_SMCCC_ARCH_WORKAROUND_2, state, NULL);
> + break;
> +
> + case PSCI_CONDUIT_SMC:
> + arm_smccc_1_1_smc(ARM_SMCCC_ARCH_WORKAROUND_2, state, NULL);
> + break;
> +
> + default:
> + WARN_ON_ONCE(1);
> + break;
> + }
> +}
> +
> +static bool has_ssbd_mitigation(const struct arm64_cpu_capabilities *entry,
> + int scope)
> +{
> + struct arm_smccc_res res;
> + bool supported = true;
> +
> + WARN_ON(scope != SCOPE_LOCAL_CPU || preemptible());
> +
> + if (psci_ops.smccc_version == SMCCC_VERSION_1_0)
> + return false;
> +
> + /*
> +  * The probe function return value is either negative
> +  * (unsupported or mitigated), positive (unaffected), or zero
> +  * (requires mitigation). We only need to do anything in the
> +  * last case.
> +  */
> + switch (psci_ops.conduit) {
> + case PSCI_CONDUIT_HVC:
> + arm_smccc_1_1_hvc(ARM_SMCCC_ARCH_FEATURES_FUNC_ID,
> +   ARM_SMCCC_ARCH_WORKAROUND_2, );
> + if ((int)res.a0 != 0)
> + supported = false;
> + break;
> +
> + case PSCI_CONDUIT_SMC:
> + arm_smccc_1_1_smc(ARM_SMCCC_ARCH_FEATURES_FUNC_ID,
> +   ARM_SMCCC_ARCH_WORKAROUND_2, );
> + if ((int)res.a0 != 0)
> + supported = false;
> + break;

Once this is merged, I'll rebase my SM conduit cleanup atop.

Mark.
___
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm


Re: [PATCH 02/14] arm64: Call ARCH_WORKAROUND_2 on transitions between EL0 and EL1

2018-05-24 Thread Mark Rutland
On Thu, May 24, 2018 at 12:00:58PM +0100, Mark Rutland wrote:
> On Tue, May 22, 2018 at 04:06:36PM +0100, Marc Zyngier wrote:
> > In order for the kernel to protect itself, let's call the SSBD mitigation
> > implemented by the higher exception level (either hypervisor or firmware)
> > on each transition between userspace and kernel.
> > 
> > We must take the PSCI conduit into account in order to target the
> > right exception level, hence the introduction of a runtime patching
> > callback.
> > 
> > Signed-off-by: Marc Zyngier <marc.zyng...@arm.com>
> > ---
> >  arch/arm64/kernel/cpu_errata.c | 18 ++
> >  arch/arm64/kernel/entry.S  | 22 ++
> >  include/linux/arm-smccc.h  |  5 +
> >  3 files changed, 45 insertions(+)
> > 
> > diff --git a/arch/arm64/kernel/cpu_errata.c b/arch/arm64/kernel/cpu_errata.c
> > index a900befadfe8..46b3aafb631a 100644
> > --- a/arch/arm64/kernel/cpu_errata.c
> > +++ b/arch/arm64/kernel/cpu_errata.c
> > @@ -232,6 +232,24 @@ enable_smccc_arch_workaround_1(const struct 
> > arm64_cpu_capabilities *entry)
> >  }
> >  #endif /* CONFIG_HARDEN_BRANCH_PREDICTOR */
> >  
> > +#ifdef CONFIG_ARM64_SSBD
> > +void __init arm64_update_smccc_conduit(struct alt_instr *alt,
> > +  __le32 *origptr, __le32 *updptr,
> > +  int nr_inst)
> > +{
> > +   u32 insn;
> > +
> > +   BUG_ON(nr_inst != 1);
> > +
> > +   if (psci_ops.conduit == PSCI_CONDUIT_HVC)
> > +   insn = aarch64_insn_get_hvc_value();
> > +   else
> > +   insn = aarch64_insn_get_smc_value();
> 
> Shouldn't this also handle the case where there is no conduit?

Due to the config symbol not being defined yet, and various other fixups
in later patches, this is actually benign.

However, if you make this:

switch (psci_ops.conduit) {
case PSCI_CONDUIT_NONE:
return;
case PSCI_CONDUIT_HVC:
insn = aarch64_insn_get_hvc_value();
break;
    case PSCI_CONDUIT_SMC:
insn = aarch64_insn_get_smc_value();
break;
}

... then we won't even bother patching the nop in the default case
regardless, which is nicer, IMO.

With that:

Reviewed-by: Mark Rutland <mark.rutl...@arm.com>

Thanks,
Mark.

> 
> See below comment in apply_ssbd for rationale.
> 
> > +
> > +   *updptr = cpu_to_le32(insn);
> > +}
> > +#endif /* CONFIG_ARM64_SSBD */
> > +
> >  #define CAP_MIDR_RANGE(model, v_min, r_min, v_max, r_max)  \
> > .matches = is_affected_midr_range,  \
> > .midr_range = MIDR_RANGE(model, v_min, r_min, v_max, r_max)
> > diff --git a/arch/arm64/kernel/entry.S b/arch/arm64/kernel/entry.S
> > index ec2ee720e33e..f33e6aed3037 100644
> > --- a/arch/arm64/kernel/entry.S
> > +++ b/arch/arm64/kernel/entry.S
> > @@ -18,6 +18,7 @@
> >   * along with this program.  If not, see <http://www.gnu.org/licenses/>.
> >   */
> >  
> > +#include 
> >  #include 
> >  #include 
> >  
> > @@ -137,6 +138,18 @@ alternative_else_nop_endif
> > add \dst, \dst, #(\sym - .entry.tramp.text)
> > .endm
> >  
> > +   // This macro corrupts x0-x3. It is the caller's duty
> > +   // to save/restore them if required.
> > +   .macro  apply_ssbd, state
> > +#ifdef CONFIG_ARM64_SSBD
> > +   mov w0, #ARM_SMCCC_ARCH_WORKAROUND_2
> > +   mov w1, #\state
> > +alternative_cb arm64_update_smccc_conduit
> > +   nop // Patched to SMC/HVC #0
> > +alternative_cb_end
> > +#endif
> > +   .endm
> 
> If my system doesn't have SMCCC1.1, or the FW doesn't have an
> implementation of ARCH_WORKAROUND_2, does this stay as a NOP?
> 
> It looks like this would be patched to an SMC, which would be fatal on
> systems without EL3 FW.
> 
> > +
> > .macro  kernel_entry, el, regsize = 64
> > .if \regsize == 32
> > mov w0, w0  // zero upper 32 bits of x0
> > @@ -163,6 +176,13 @@ alternative_else_nop_endif
> > ldr x19, [tsk, #TSK_TI_FLAGS]   // since we can unmask debug
> > disable_step_tsk x19, x20   // exceptions when scheduling.
> >  
> > +   apply_ssbd 1
> 
> 
> ... and thus kernel_entry would be fatal.
> 
> Thanks,
> Mark.
___
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm


Re: [PATCH 03/14] arm64: Add per-cpu infrastructure to call ARCH_WORKAROUND_2

2018-05-24 Thread Mark Rutland
On Tue, May 22, 2018 at 04:06:37PM +0100, Marc Zyngier wrote:
> In a heterogeneous system, we can end up with both affected and
> unaffected CPUs. Let's check their status before calling into the
> firmware.
> 
> Signed-off-by: Marc Zyngier <marc.zyng...@arm.com>

Ah, I guess this may fix the issue I noted with the prior patch,
assuming we only set arm64_ssbd_callback_required for a CPU when the FW
supports the mitigation.

If so, if you fold this together with the prior patch:

Reviewed-by: Mark Rutland <mark.rutl...@arm.com>

Thanks,
Mark.

> ---
>  arch/arm64/kernel/cpu_errata.c |  2 ++
>  arch/arm64/kernel/entry.S  | 11 +++
>  2 files changed, 9 insertions(+), 4 deletions(-)
> 
> diff --git a/arch/arm64/kernel/cpu_errata.c b/arch/arm64/kernel/cpu_errata.c
> index 46b3aafb631a..0288d6cf560e 100644
> --- a/arch/arm64/kernel/cpu_errata.c
> +++ b/arch/arm64/kernel/cpu_errata.c
> @@ -233,6 +233,8 @@ enable_smccc_arch_workaround_1(const struct 
> arm64_cpu_capabilities *entry)
>  #endif   /* CONFIG_HARDEN_BRANCH_PREDICTOR */
>  
>  #ifdef CONFIG_ARM64_SSBD
> +DEFINE_PER_CPU_READ_MOSTLY(u64, arm64_ssbd_callback_required);
> +
>  void __init arm64_update_smccc_conduit(struct alt_instr *alt,
>  __le32 *origptr, __le32 *updptr,
>  int nr_inst)
> diff --git a/arch/arm64/kernel/entry.S b/arch/arm64/kernel/entry.S
> index f33e6aed3037..29ad672a6abd 100644
> --- a/arch/arm64/kernel/entry.S
> +++ b/arch/arm64/kernel/entry.S
> @@ -140,8 +140,10 @@ alternative_else_nop_endif
>  
>   // This macro corrupts x0-x3. It is the caller's duty
>   // to save/restore them if required.
> - .macro  apply_ssbd, state
> + .macro  apply_ssbd, state, targ, tmp1, tmp2
>  #ifdef CONFIG_ARM64_SSBD
> + ldr_this_cpu\tmp2, arm64_ssbd_callback_required, \tmp1
> + cbz \tmp2, \targ
>   mov w0, #ARM_SMCCC_ARCH_WORKAROUND_2
>   mov w1, #\state
>  alternative_cb   arm64_update_smccc_conduit
> @@ -176,12 +178,13 @@ alternative_cb_end
>   ldr x19, [tsk, #TSK_TI_FLAGS]   // since we can unmask debug
>   disable_step_tsk x19, x20   // exceptions when scheduling.
>  
> - apply_ssbd 1
> + apply_ssbd 1, 1f, x22, x23
>  
>  #ifdef CONFIG_ARM64_SSBD
>   ldp x0, x1, [sp, #16 * 0]
>   ldp x2, x3, [sp, #16 * 1]
>  #endif
> +1:
>  
>   mov x29, xzr// fp pointed to user-space
>   .else
> @@ -323,8 +326,8 @@ alternative_if ARM64_WORKAROUND_845719
>  alternative_else_nop_endif
>  #endif
>  3:
> - apply_ssbd 0
> -
> + apply_ssbd 0, 5f, x0, x1
> +5:
>   .endif
>  
>   msr elr_el1, x21// set up the return data
> -- 
> 2.14.2
> 
> 
> ___
> linux-arm-kernel mailing list
> linux-arm-ker...@lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
___
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm


Re: [PATCH 02/14] arm64: Call ARCH_WORKAROUND_2 on transitions between EL0 and EL1

2018-05-24 Thread Mark Rutland
On Tue, May 22, 2018 at 04:06:36PM +0100, Marc Zyngier wrote:
> In order for the kernel to protect itself, let's call the SSBD mitigation
> implemented by the higher exception level (either hypervisor or firmware)
> on each transition between userspace and kernel.
> 
> We must take the PSCI conduit into account in order to target the
> right exception level, hence the introduction of a runtime patching
> callback.
> 
> Signed-off-by: Marc Zyngier 
> ---
>  arch/arm64/kernel/cpu_errata.c | 18 ++
>  arch/arm64/kernel/entry.S  | 22 ++
>  include/linux/arm-smccc.h  |  5 +
>  3 files changed, 45 insertions(+)
> 
> diff --git a/arch/arm64/kernel/cpu_errata.c b/arch/arm64/kernel/cpu_errata.c
> index a900befadfe8..46b3aafb631a 100644
> --- a/arch/arm64/kernel/cpu_errata.c
> +++ b/arch/arm64/kernel/cpu_errata.c
> @@ -232,6 +232,24 @@ enable_smccc_arch_workaround_1(const struct 
> arm64_cpu_capabilities *entry)
>  }
>  #endif   /* CONFIG_HARDEN_BRANCH_PREDICTOR */
>  
> +#ifdef CONFIG_ARM64_SSBD
> +void __init arm64_update_smccc_conduit(struct alt_instr *alt,
> +__le32 *origptr, __le32 *updptr,
> +int nr_inst)
> +{
> + u32 insn;
> +
> + BUG_ON(nr_inst != 1);
> +
> + if (psci_ops.conduit == PSCI_CONDUIT_HVC)
> + insn = aarch64_insn_get_hvc_value();
> + else
> + insn = aarch64_insn_get_smc_value();

Shouldn't this also handle the case where there is no conduit?

See below comment in apply_ssbd for rationale.

> +
> + *updptr = cpu_to_le32(insn);
> +}
> +#endif   /* CONFIG_ARM64_SSBD */
> +
>  #define CAP_MIDR_RANGE(model, v_min, r_min, v_max, r_max)\
>   .matches = is_affected_midr_range,  \
>   .midr_range = MIDR_RANGE(model, v_min, r_min, v_max, r_max)
> diff --git a/arch/arm64/kernel/entry.S b/arch/arm64/kernel/entry.S
> index ec2ee720e33e..f33e6aed3037 100644
> --- a/arch/arm64/kernel/entry.S
> +++ b/arch/arm64/kernel/entry.S
> @@ -18,6 +18,7 @@
>   * along with this program.  If not, see .
>   */
>  
> +#include 
>  #include 
>  #include 
>  
> @@ -137,6 +138,18 @@ alternative_else_nop_endif
>   add \dst, \dst, #(\sym - .entry.tramp.text)
>   .endm
>  
> + // This macro corrupts x0-x3. It is the caller's duty
> + // to save/restore them if required.
> + .macro  apply_ssbd, state
> +#ifdef CONFIG_ARM64_SSBD
> + mov w0, #ARM_SMCCC_ARCH_WORKAROUND_2
> + mov w1, #\state
> +alternative_cb   arm64_update_smccc_conduit
> + nop // Patched to SMC/HVC #0
> +alternative_cb_end
> +#endif
> + .endm

If my system doesn't have SMCCC1.1, or the FW doesn't have an
implementation of ARCH_WORKAROUND_2, does this stay as a NOP?

It looks like this would be patched to an SMC, which would be fatal on
systems without EL3 FW.

> +
>   .macro  kernel_entry, el, regsize = 64
>   .if \regsize == 32
>   mov w0, w0  // zero upper 32 bits of x0
> @@ -163,6 +176,13 @@ alternative_else_nop_endif
>   ldr x19, [tsk, #TSK_TI_FLAGS]   // since we can unmask debug
>   disable_step_tsk x19, x20   // exceptions when scheduling.
>  
> + apply_ssbd 1


... and thus kernel_entry would be fatal.

Thanks,
Mark.
___
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm


Re: [PATCH 02/14] arm64: Call ARCH_WORKAROUND_2 on transitions between EL0 and EL1

2018-05-24 Thread Mark Rutland
On Wed, May 23, 2018 at 10:23:20AM +0100, Julien Grall wrote:
> Hi Marc,
> 
> On 05/22/2018 04:06 PM, Marc Zyngier wrote:
> > diff --git a/arch/arm64/kernel/entry.S b/arch/arm64/kernel/entry.S
> > index ec2ee720e33e..f33e6aed3037 100644
> > --- a/arch/arm64/kernel/entry.S
> > +++ b/arch/arm64/kernel/entry.S
> > @@ -18,6 +18,7 @@
> >* along with this program.  If not, see .
> >*/
> > +#include 
> >   #include 
> >   #include 
> > @@ -137,6 +138,18 @@ alternative_else_nop_endif
> > add \dst, \dst, #(\sym - .entry.tramp.text)
> > .endm
> > +   // This macro corrupts x0-x3. It is the caller's duty
> > +   // to save/restore them if required.
> 
> NIT: Shouldn't you use /* ... */ for multi-line comments?

There's no requirement to do so, and IIRC even Torvalds prefers '//'
comments for multi-line things these days.

Mark.
___
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm


[PATCHv2] ARM64: KVM: use lm_alias() for kvm_ksym_ref()

2018-05-10 Thread Mark Rutland
For historical reasons, we open-code lm_alias() in kvm_ksym_ref().

Let's use lm_alias() to avoid duplication and make things clearer.

As we have to pull this from  (which is not safe for
inclusion in assembly), we may as well move the kvm_ksym_ref()
definition into the existing !__ASSEMBLY__ block.

Signed-off-by: Mark Rutland <mark.rutl...@arm.com>
Cc: Christoffer Dall <christoffer.d...@arm.com>
Cc: Marc Zyngier <marc.zyng...@arm.com>
Cc: kvmarm@lists.cs.columbia.edu
---
 arch/arm64/include/asm/kvm_asm.h | 7 +--
 1 file changed, 5 insertions(+), 2 deletions(-)

Since v1 [1]:
* Rebase to v4.17-rc4
* Fix typo in commit message

Mark.

[1] https://lkml.kernel.org/r/20180406151909.57197-1-mark.rutl...@arm.com

diff --git a/arch/arm64/include/asm/kvm_asm.h b/arch/arm64/include/asm/kvm_asm.h
index f6648a3e4152..a9ceeec5a76f 100644
--- a/arch/arm64/include/asm/kvm_asm.h
+++ b/arch/arm64/include/asm/kvm_asm.h
@@ -33,16 +33,19 @@
 #define KVM_ARM64_DEBUG_DIRTY_SHIFT0
 #define KVM_ARM64_DEBUG_DIRTY  (1 << KVM_ARM64_DEBUG_DIRTY_SHIFT)
 
+#ifndef __ASSEMBLY__
+
+#include 
+
 /* Translate a kernel address of @sym into its equivalent linear mapping */
 #define kvm_ksym_ref(sym)  \
({  \
void *val =\
if (!is_kernel_in_hyp_mode())   \
-   val = phys_to_virt((u64) - kimage_voffset); \
+   val = lm_alias();   \
val;\
 })
 
-#ifndef __ASSEMBLY__
 struct kvm;
 struct kvm_vcpu;
 
-- 
2.11.0

___
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm


[PATCHv4 07/10] arm64: expose user PAC bit positions via ptrace

2018-05-03 Thread Mark Rutland
When pointer authentication is in use, data/instruction pointers have a
number of PAC bits inserted into them. The number and position of these
bits depends on the configured TCR_ELx.TxSZ and whether tagging is
enabled. ARMv8.3 allows tagging to differ for instruction and data
pointers.

For userspace debuggers to unwind the stack and/or to follow pointer
chains, they need to be able to remove the PAC bits before attempting to
use a pointer.

This patch adds a new structure with masks describing the location of
the PAC bits in userspace instruction and data pointers (i.e. those
addressable via TTBR0), which userspace can query via PTRACE_GETREGSET.
By clearing these bits from pointers (and replacing them with the value
of bit 55), userspace can acquire the PAC-less versions.

This new regset is exposed when the kernel is built with (user) pointer
authentication support, and the feature is enabled. Otherwise, it is
hidden.

Signed-off-by: Mark Rutland <mark.rutl...@arm.com>
Cc: Catalin Marinas <catalin.mari...@arm.com>
Cc: Ramana Radhakrishnan <ramana.radhakrish...@arm.com>
Cc: Will Deacon <will.dea...@arm.com>
---
 arch/arm64/include/asm/pointer_auth.h |  8 
 arch/arm64/include/uapi/asm/ptrace.h  |  7 +++
 arch/arm64/kernel/ptrace.c| 38 +++
 include/uapi/linux/elf.h  |  1 +
 4 files changed, 54 insertions(+)

diff --git a/arch/arm64/include/asm/pointer_auth.h 
b/arch/arm64/include/asm/pointer_auth.h
index 034877ee28bc..0263b87f95f7 100644
--- a/arch/arm64/include/asm/pointer_auth.h
+++ b/arch/arm64/include/asm/pointer_auth.h
@@ -2,9 +2,11 @@
 #ifndef __ASM_POINTER_AUTH_H
 #define __ASM_POINTER_AUTH_H
 
+#include 
 #include 
 
 #include 
+#include 
 #include 
 
 #ifdef CONFIG_ARM64_PTR_AUTH
@@ -57,6 +59,12 @@ static inline void ptrauth_keys_dup(struct ptrauth_keys *old,
*new = *old;
 }
 
+/*
+ * The EL0 pointer bits used by a pointer authentication code.
+ * This is dependent on TBI0 being enabled, or bits 63:56 would also apply.
+ */
+#define ptrauth_pac_mask() GENMASK(54, VA_BITS)
+
 #define mm_ctx_ptrauth_init(ctx) \
ptrauth_keys_init(&(ctx)->ptrauth_keys)
 
diff --git a/arch/arm64/include/uapi/asm/ptrace.h 
b/arch/arm64/include/uapi/asm/ptrace.h
index 98c4ce55d9c3..4994d718771a 100644
--- a/arch/arm64/include/uapi/asm/ptrace.h
+++ b/arch/arm64/include/uapi/asm/ptrace.h
@@ -228,6 +228,13 @@ struct user_sve_header {
  SVE_PT_SVE_OFFSET + SVE_PT_SVE_SIZE(vq, flags)\
: SVE_PT_FPSIMD_OFFSET + SVE_PT_FPSIMD_SIZE(vq, flags))
 
+/* pointer authentication masks (NT_ARM_PAC_MASK) */
+
+struct user_pac_mask {
+   __u64   data_mask;
+   __u64   insn_mask;
+};
+
 #endif /* __ASSEMBLY__ */
 
 #endif /* _UAPI__ASM_PTRACE_H */
diff --git a/arch/arm64/kernel/ptrace.c b/arch/arm64/kernel/ptrace.c
index 71d99af24ef2..f395649f755e 100644
--- a/arch/arm64/kernel/ptrace.c
+++ b/arch/arm64/kernel/ptrace.c
@@ -44,6 +44,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -951,6 +952,30 @@ static int sve_set(struct task_struct *target,
 
 #endif /* CONFIG_ARM64_SVE */
 
+#ifdef CONFIG_ARM64_PTR_AUTH
+static int pac_mask_get(struct task_struct *target,
+   const struct user_regset *regset,
+   unsigned int pos, unsigned int count,
+   void *kbuf, void __user *ubuf)
+{
+   /*
+* The PAC bits can differ across data and instruction pointers
+* depending on TCR_EL1.TBID*, which we may make use of in future, so
+* we expose separate masks.
+*/
+   unsigned long mask = ptrauth_pac_mask();
+   struct user_pac_mask uregs = {
+   .data_mask = mask,
+   .insn_mask = mask,
+   };
+
+   if (!cpus_have_cap(ARM64_HAS_ADDRESS_AUTH))
+   return -EINVAL;
+
+   return user_regset_copyout(, , , , , 0, -1);
+}
+#endif /* CONFIG_ARM64_PTR_AUTH */
+
 enum aarch64_regset {
REGSET_GPR,
REGSET_FPR,
@@ -963,6 +988,9 @@ enum aarch64_regset {
 #ifdef CONFIG_ARM64_SVE
REGSET_SVE,
 #endif
+#ifdef CONFIG_ARM64_PTR_AUTH
+   REGSET_PAC_MASK,
+#endif
 };
 
 static const struct user_regset aarch64_regsets[] = {
@@ -1032,6 +1060,16 @@ static const struct user_regset aarch64_regsets[] = {
.get_size = sve_get_size,
},
 #endif
+#ifdef CONFIG_ARM64_PTR_AUTH
+   [REGSET_PAC_MASK] = {
+   .core_note_type = NT_ARM_PAC_MASK,
+   .n = sizeof(struct user_pac_mask) / sizeof(u64),
+   .size = sizeof(u64),
+   .align = sizeof(u64),
+   .get = pac_mask_get,
+   /* this cannot be set dynamically */
+   },
+#endif
 };
 
 static const struct user_regset_view user_aarch64_view = {
diff --git a/include/uapi/linux/elf.h b/include/uapi/linux/elf.h
index e2535d6dcec7..070c28121979 100644
--- a

[PATCHv4 10/10] arm64: docs: document pointer authentication

2018-05-03 Thread Mark Rutland
Now that we've added code to support pointer authentication, add some
documentation so that people can figure out if/how to use it.

Signed-off-by: Mark Rutland <mark.rutl...@arm.com>
Cc: Andrew Jones <drjo...@redhat.com>
Cc: Catalin Marinas <catalin.mari...@arm.com>
Cc: Ramana Radhakrishnan <ramana.radhakrish...@arm.com>
Cc: Will Deacon <will.dea...@arm.com>
---
 Documentation/arm64/booting.txt|  8 +++
 Documentation/arm64/elf_hwcaps.txt |  6 ++
 Documentation/arm64/pointer-authentication.txt | 84 ++
 3 files changed, 98 insertions(+)
 create mode 100644 Documentation/arm64/pointer-authentication.txt

diff --git a/Documentation/arm64/booting.txt b/Documentation/arm64/booting.txt
index 8d0df62c3fe0..8df9f4658d6f 100644
--- a/Documentation/arm64/booting.txt
+++ b/Documentation/arm64/booting.txt
@@ -205,6 +205,14 @@ Before jumping into the kernel, the following conditions 
must be met:
 ICC_SRE_EL2.SRE (bit 0) must be initialised to 0b0.
   - The DT or ACPI tables must describe a GICv2 interrupt controller.
 
+  For CPUs with pointer authentication functionality:
+  - If EL3 is present:
+SCR_EL3.APK (bit 16) must be initialised to 0b1
+SCR_EL3.API (bit 17) must be initialised to 0b1
+  - If the kernel is entered at EL1:
+HCR_EL2.APK (bit 40) must be initialised to 0b1
+HCR_EL2.API (bit 41) must be initialised to 0b1
+
 The requirements described above for CPU mode, caches, MMUs, architected
 timers, coherency and system registers apply to all CPUs.  All CPUs must
 enter the kernel in the same exception level.
diff --git a/Documentation/arm64/elf_hwcaps.txt 
b/Documentation/arm64/elf_hwcaps.txt
index d6aff2c5e9e2..ebc8b15b45fc 100644
--- a/Documentation/arm64/elf_hwcaps.txt
+++ b/Documentation/arm64/elf_hwcaps.txt
@@ -178,3 +178,9 @@ HWCAP_ILRCPC
 HWCAP_FLAGM
 
 Functionality implied by ID_AA64ISAR0_EL1.TS == 0b0001.
+
+HWCAP_APIA
+
+EL0 AddPac and Auth functionality using APIAKey_EL1 is enabled, as
+described by Documentation/arm64/pointer-authentication.txt.
+
diff --git a/Documentation/arm64/pointer-authentication.txt 
b/Documentation/arm64/pointer-authentication.txt
new file mode 100644
index ..8a9cb5713770
--- /dev/null
+++ b/Documentation/arm64/pointer-authentication.txt
@@ -0,0 +1,84 @@
+Pointer authentication in AArch64 Linux
+=======
+
+Author: Mark Rutland <mark.rutl...@arm.com>
+Date: 2017-07-19
+
+This document briefly describes the provision of pointer authentication
+functionality in AArch64 Linux.
+
+
+Architecture overview
+-
+
+The ARMv8.3 Pointer Authentication extension adds primitives that can be
+used to mitigate certain classes of attack where an attacker can corrupt
+the contents of some memory (e.g. the stack).
+
+The extension uses a Pointer Authentication Code (PAC) to determine
+whether pointers have been modified unexpectedly. A PAC is derived from
+a pointer, another value (such as the stack pointer), and a secret key
+held in system registers.
+
+The extension adds instructions to insert a valid PAC into a pointer,
+and to verify/remove the PAC from a pointer. The PAC occupies a number
+of high-order bits of the pointer, which varies dependent on the
+configured virtual address size and whether pointer tagging is in use.
+
+A subset of these instructions have been allocated from the HINT
+encoding space. In the absence of the extension (or when disabled),
+these instructions behave as NOPs. Applications and libraries using
+these instructions operate correctly regardless of the presence of the
+extension.
+
+
+Basic support
+-
+
+When CONFIG_ARM64_PTR_AUTH is selected, and relevant HW support is
+present, the kernel will assign a random APIAKey value to each process
+at exec*() time. This key is shared by all threads within the process,
+and the key is preserved across fork(). Presence of functionality using
+APIAKey is advertised via HWCAP_APIA.
+
+Recent versions of GCC can compile code with APIAKey-based return
+address protection when passed the -msign-return-address option. This
+uses instructions in the HINT space, and such code can run on systems
+without the pointer authentication extension.
+
+The remaining instruction and data keys (APIBKey, APDAKey, APDBKey) are
+reserved for future use, and instructions using these keys must not be
+used by software until a purpose and scope for their use has been
+decided. To enable future software using these keys to function on
+contemporary kernels, where possible, instructions using these keys are
+made to behave as NOPs.
+
+The generic key (APGAKey) is currently unsupported. Instructions using
+the generic key must not be used by software.
+
+
+Debugging
+-
+
+When CONFIG_ARM64_PTR_AUTH is selected, and relevant HW support is
+present, the kernel will expose the position of TTBR0 PAC bits in the
+NT_ARM_PAC_MASK regset (struct

[PATCHv4 08/10] arm64: perf: strip PAC when unwinding userspace

2018-05-03 Thread Mark Rutland
When the kernel is unwinding userspace callchains, we can't expect that
the userspace consumer of these callchains has the data necessary to
strip the PAC from the stored LR.

This patch has the kernel strip the PAC from user stackframes when the
in-kernel unwinder is used. This only affects the LR value, and not the
FP.

This only affects the in-kernel unwinder. When userspace performs
unwinding, it is up to userspace to strip PACs as necessary (which can
be determined from DWARF information).

Signed-off-by: Mark Rutland <mark.rutl...@arm.com>
Cc: Catalin Marinas <catalin.mari...@arm.com>
Cc: Ramana Radhakrishnan <ramana.radhakrish...@arm.com>
Cc: Will Deacon <will.dea...@arm.com>
---
 arch/arm64/include/asm/pointer_auth.h | 7 +++
 arch/arm64/kernel/perf_callchain.c| 5 -
 2 files changed, 11 insertions(+), 1 deletion(-)

diff --git a/arch/arm64/include/asm/pointer_auth.h 
b/arch/arm64/include/asm/pointer_auth.h
index 0263b87f95f7..284db173ae5d 100644
--- a/arch/arm64/include/asm/pointer_auth.h
+++ b/arch/arm64/include/asm/pointer_auth.h
@@ -65,6 +65,12 @@ static inline void ptrauth_keys_dup(struct ptrauth_keys *old,
  */
 #define ptrauth_pac_mask() GENMASK(54, VA_BITS)
 
+/* Only valid for EL0 TTBR0 instruction pointers */
+static inline unsigned long ptrauth_strip_insn_pac(unsigned long ptr)
+{
+   return ptr & ~ptrauth_pac_mask();
+}
+
 #define mm_ctx_ptrauth_init(ctx) \
ptrauth_keys_init(&(ctx)->ptrauth_keys)
 
@@ -75,6 +81,7 @@ static inline void ptrauth_keys_dup(struct ptrauth_keys *old,
ptrauth_keys_dup(&(oldctx)->ptrauth_keys, &(newctx)->ptrauth_keys)
 
 #else
+#define ptrauth_strip_insn_pac(lr) (lr)
 #define mm_ctx_ptrauth_init(ctx)
 #define mm_ctx_ptrauth_switch(ctx)
 #define mm_ctx_ptrauth_dup(oldctx, newctx)
diff --git a/arch/arm64/kernel/perf_callchain.c 
b/arch/arm64/kernel/perf_callchain.c
index bcafd7dcfe8b..928204f6ab08 100644
--- a/arch/arm64/kernel/perf_callchain.c
+++ b/arch/arm64/kernel/perf_callchain.c
@@ -35,6 +35,7 @@ user_backtrace(struct frame_tail __user *tail,
 {
struct frame_tail buftail;
unsigned long err;
+   unsigned long lr;
 
/* Also check accessibility of one struct frame_tail beyond */
if (!access_ok(VERIFY_READ, tail, sizeof(buftail)))
@@ -47,7 +48,9 @@ user_backtrace(struct frame_tail __user *tail,
if (err)
return NULL;
 
-   perf_callchain_store(entry, buftail.lr);
+   lr = ptrauth_strip_insn_pac(buftail.lr);
+
+   perf_callchain_store(entry, lr);
 
/*
 * Frame pointers should strictly progress back up the stack
-- 
2.11.0

___
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm


[PATCHv4 09/10] arm64: enable pointer authentication

2018-05-03 Thread Mark Rutland
Now that all the necessary bits are in place for userspace, add the
necessary Kconfig logic to allow this to be enabled.

Signed-off-by: Mark Rutland <mark.rutl...@arm.com>
Cc: Catalin Marinas <catalin.mari...@arm.com>
Cc: Will Deacon <will.dea...@arm.com>
---
 arch/arm64/Kconfig | 23 +++
 1 file changed, 23 insertions(+)

diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
index eb2cf4938f6d..d6ce16b1ee47 100644
--- a/arch/arm64/Kconfig
+++ b/arch/arm64/Kconfig
@@ -1127,6 +1127,29 @@ config ARM64_RAS_EXTN
 
 endmenu
 
+menu "ARMv8.3 architectural features"
+
+config ARM64_PTR_AUTH
+   bool "Enable support for pointer authentication"
+   default y
+   help
+ Pointer authentication (part of the ARMv8.3 Extensions) provides
+ instructions for signing and authenticating pointers against secret
+ keys, which can be used to mitigate Return Oriented Programming (ROP)
+ and other attacks.
+
+ This option enables these instructions at EL0 (i.e. for userspace).
+
+ Choosing this option will cause the kernel to initialise secret keys
+ for each process at exec() time, with these keys being
+ context-switched along with the process.
+
+ The feature is detected at runtime. If the feature is not present in
+ hardware it will not be advertised to userspace nor will it be
+ enabled.
+
+endmenu
+
 config ARM64_SVE
bool "ARM Scalable Vector Extension support"
default y
-- 
2.11.0

___
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm


[PATCHv4 06/10] arm64: add basic pointer authentication support

2018-05-03 Thread Mark Rutland
This patch adds basic support for pointer authentication, allowing
userspace to make use of APIAKey. The kernel maintains an APIAKey value
for each process (shared by all threads within), which is initialised to
a random value at exec() time.

To describe that address authentication instructions are available, the
ID_AA64ISAR0.{APA,API} fields are exposed to userspace. A new hwcap,
APIA, is added to describe that the kernel manages APIAKey.

Instructions using other keys (APIBKey, APDAKey, APDBKey) are disabled,
and will behave as NOPs. These may be made use of in future patches.

No support is added for the generic key (APGAKey), though this cannot be
trapped or made to behave as a NOP. Its presence is not advertised with
a hwcap.

Signed-off-by: Mark Rutland <mark.rutl...@arm.com>
Cc: Catalin Marinas <catalin.mari...@arm.com>
Cc: Ramana Radhakrishnan <ramana.radhakrish...@arm.com>
Cc: Suzuki K Poulose <suzuki.poul...@arm.com>
Cc: Will Deacon <will.dea...@arm.com>
---
 arch/arm64/include/asm/mmu.h  |  5 +++
 arch/arm64/include/asm/mmu_context.h  | 11 -
 arch/arm64/include/asm/pointer_auth.h | 75 +++
 arch/arm64/include/uapi/asm/hwcap.h   |  1 +
 arch/arm64/kernel/cpufeature.c|  9 +
 arch/arm64/kernel/cpuinfo.c   |  1 +
 6 files changed, 101 insertions(+), 1 deletion(-)
 create mode 100644 arch/arm64/include/asm/pointer_auth.h

diff --git a/arch/arm64/include/asm/mmu.h b/arch/arm64/include/asm/mmu.h
index dd320df0d026..f6480ea7b0d5 100644
--- a/arch/arm64/include/asm/mmu.h
+++ b/arch/arm64/include/asm/mmu.h
@@ -25,10 +25,15 @@
 
 #ifndef __ASSEMBLY__
 
+#include 
+
 typedef struct {
atomic64_t  id;
void*vdso;
unsigned long   flags;
+#ifdef CONFIG_ARM64_PTR_AUTH
+   struct ptrauth_keys ptrauth_keys;
+#endif
 } mm_context_t;
 
 /*
diff --git a/arch/arm64/include/asm/mmu_context.h 
b/arch/arm64/include/asm/mmu_context.h
index 39ec0b8a689e..83eadbc6b946 100644
--- a/arch/arm64/include/asm/mmu_context.h
+++ b/arch/arm64/include/asm/mmu_context.h
@@ -168,7 +168,14 @@ static inline void cpu_replace_ttbr1(pgd_t *pgdp)
 #define destroy_context(mm)do { } while(0)
 void check_and_switch_context(struct mm_struct *mm, unsigned int cpu);
 
-#define init_new_context(tsk,mm)   ({ atomic64_set(&(mm)->context.id, 0); 
0; })
+static inline int init_new_context(struct task_struct *tsk,
+  struct mm_struct *mm)
+{
+   atomic64_set(>context.id, 0);
+   mm_ctx_ptrauth_init(>context);
+
+   return 0;
+}
 
 #ifdef CONFIG_ARM64_SW_TTBR0_PAN
 static inline void update_saved_ttbr0(struct task_struct *tsk,
@@ -216,6 +223,8 @@ static inline void __switch_mm(struct mm_struct *next)
return;
}
 
+   mm_ctx_ptrauth_switch(>context);
+
check_and_switch_context(next, cpu);
 }
 
diff --git a/arch/arm64/include/asm/pointer_auth.h 
b/arch/arm64/include/asm/pointer_auth.h
new file mode 100644
index ..034877ee28bc
--- /dev/null
+++ b/arch/arm64/include/asm/pointer_auth.h
@@ -0,0 +1,75 @@
+// SPDX-License-Identifier: GPL-2.0
+#ifndef __ASM_POINTER_AUTH_H
+#define __ASM_POINTER_AUTH_H
+
+#include 
+
+#include 
+#include 
+
+#ifdef CONFIG_ARM64_PTR_AUTH
+/*
+ * Each key is a 128-bit quantity which is split accross a pair of 64-bit
+ * registers (Lo and Hi).
+ */
+struct ptrauth_key {
+   unsigned long lo, hi;
+};
+
+/*
+ * We give each process its own instruction A key (APIAKey), which is shared by
+ * all threads. This is inherited upon fork(), and reinitialised upon exec*().
+ * All other keys are currently unused, with APIBKey, APDAKey, and APBAKey
+ * instructions behaving as NOPs.
+ */
+struct ptrauth_keys {
+   struct ptrauth_key apia;
+};
+
+static inline void ptrauth_keys_init(struct ptrauth_keys *keys)
+{
+   if (!cpus_have_const_cap(ARM64_HAS_ADDRESS_AUTH))
+   return;
+
+   get_random_bytes(keys, sizeof(*keys));
+}
+
+#define __ptrauth_key_install(k, v)\
+do {   \
+   write_sysreg_s(v.lo, SYS_ ## k ## KEYLO_EL1);   \
+   write_sysreg_s(v.hi, SYS_ ## k ## KEYHI_EL1);   \
+} while (0)
+
+static inline void ptrauth_keys_switch(struct ptrauth_keys *keys)
+{
+   if (!cpus_have_const_cap(ARM64_HAS_ADDRESS_AUTH))
+   return;
+
+   __ptrauth_key_install(APIA, keys->apia);
+}
+
+static inline void ptrauth_keys_dup(struct ptrauth_keys *old,
+   struct ptrauth_keys *new)
+{
+   if (!cpus_have_const_cap(ARM64_HAS_ADDRESS_AUTH))
+   return;
+
+   *new = *old;
+}
+
+#define mm_ctx_ptrauth_init(ctx) \
+   ptrauth_keys_init(&(ctx)->ptrauth_keys)
+
+#define mm_ctx_ptrauth_switch(ctx) \
+   ptrauth_keys_switch(&(ctx)->ptrauth_keys)
+
+#define mm_ctx_ptrauth_dup(oldctx, newctx) \
+   pt

[PATCHv4 05/10] arm64/cpufeature: detect pointer authentication

2018-05-03 Thread Mark Rutland
So that we can dynamically handle the presence of pointer authentication
functionality, wire up probing code in cpufeature.c.

>From ARMv8.3 onwards, ID_AA64ISAR1 is no longer entirely RES0, and now
has four fields describing the presence of pointer authentication
functionality:

* APA - address authentication present, using an architected algorithm
* API - address authentication present, using an IMP DEF algorithm
* GPA - generic authentication present, using an architected algorithm
* GPI - generic authentication present, using an IMP DEF algorithm

For the moment we only care about address authentication, so we only
need to check APA and API. It is assumed that if all CPUs support an IMP
DEF algorithm, the same algorithm is used across all CPUs.

Note that when we implement KVM support, we will also need to ensure
that CPUs have uniform support for GPA and GPI.

Signed-off-by: Mark Rutland <mark.rutl...@arm.com>
Cc: Catalin Marinas <catalin.mari...@arm.com>
Cc: Suzuki K Poulose <suzuki.poul...@arm.com>
Cc: Will Deacon <will.dea...@arm.com>
---
 arch/arm64/include/asm/cpucaps.h |  5 -
 arch/arm64/kernel/cpufeature.c   | 47 
 2 files changed, 51 insertions(+), 1 deletion(-)

diff --git a/arch/arm64/include/asm/cpucaps.h b/arch/arm64/include/asm/cpucaps.h
index bc51b72fafd4..9dcb4d1b14f5 100644
--- a/arch/arm64/include/asm/cpucaps.h
+++ b/arch/arm64/include/asm/cpucaps.h
@@ -48,7 +48,10 @@
 #define ARM64_HAS_CACHE_IDC27
 #define ARM64_HAS_CACHE_DIC28
 #define ARM64_HW_DBM   29
+#define ARM64_HAS_ADDRESS_AUTH_ARCH30
+#define ARM64_HAS_ADDRESS_AUTH_IMP_DEF 31
+#define ARM64_HAS_ADDRESS_AUTH 32
 
-#define ARM64_NCAPS30
+#define ARM64_NCAPS33
 
 #endif /* __ASM_CPUCAPS_H */
diff --git a/arch/arm64/kernel/cpufeature.c b/arch/arm64/kernel/cpufeature.c
index 536d572e5596..01b1a7e7d70f 100644
--- a/arch/arm64/kernel/cpufeature.c
+++ b/arch/arm64/kernel/cpufeature.c
@@ -142,6 +142,10 @@ static const struct arm64_ftr_bits ftr_id_aa64isar1[] = {
ARM64_FTR_BITS(FTR_VISIBLE, FTR_STRICT, FTR_LOWER_SAFE, 
ID_AA64ISAR1_LRCPC_SHIFT, 4, 0),
ARM64_FTR_BITS(FTR_VISIBLE, FTR_STRICT, FTR_LOWER_SAFE, 
ID_AA64ISAR1_FCMA_SHIFT, 4, 0),
ARM64_FTR_BITS(FTR_VISIBLE, FTR_STRICT, FTR_LOWER_SAFE, 
ID_AA64ISAR1_JSCVT_SHIFT, 4, 0),
+   ARM64_FTR_BITS(FTR_VISIBLE_IF_IS_ENABLED(CONFIG_ARM64_PTR_AUTH),
+  FTR_STRICT, FTR_LOWER_SAFE, ID_AA64ISAR1_API_SHIFT, 4, 
0),
+   ARM64_FTR_BITS(FTR_VISIBLE_IF_IS_ENABLED(CONFIG_ARM64_PTR_AUTH),
+  FTR_STRICT, FTR_LOWER_SAFE, ID_AA64ISAR1_APA_SHIFT, 4, 
0),
ARM64_FTR_BITS(FTR_VISIBLE, FTR_STRICT, FTR_LOWER_SAFE, 
ID_AA64ISAR1_DPB_SHIFT, 4, 0),
ARM64_FTR_END,
 };
@@ -1025,6 +1029,22 @@ static void cpu_copy_el2regs(const struct 
arm64_cpu_capabilities *__unused)
 }
 #endif
 
+#ifdef CONFIG_ARM64_PTR_AUTH
+static bool has_address_auth(const struct arm64_cpu_capabilities *entry,
+int __unused)
+{
+   u64 isar1 = read_sanitised_ftr_reg(SYS_ID_AA64ISAR1_EL1);
+   bool api, apa;
+
+   apa = cpuid_feature_extract_unsigned_field(isar1,
+   ID_AA64ISAR1_APA_SHIFT) > 0;
+   api = cpuid_feature_extract_unsigned_field(isar1,
+   ID_AA64ISAR1_API_SHIFT) > 0;
+
+   return apa || api;
+}
+#endif /* CONFIG_ARM64_PTR_AUTH */
+
 static const struct arm64_cpu_capabilities arm64_features[] = {
{
.desc = "GIC system register CPU interface",
@@ -1201,6 +1221,33 @@ static const struct arm64_cpu_capabilities 
arm64_features[] = {
.cpu_enable = cpu_enable_hw_dbm,
},
 #endif
+#ifdef CONFIG_ARM64_PTR_AUTH
+   {
+   .desc = "Address authentication (architected algorithm)",
+   .capability = ARM64_HAS_ADDRESS_AUTH_ARCH,
+   .type = ARM64_CPUCAP_SYSTEM_FEATURE,
+   .sys_reg = SYS_ID_AA64ISAR1_EL1,
+   .sign = FTR_UNSIGNED,
+   .field_pos = ID_AA64ISAR1_APA_SHIFT,
+   .min_field_value = ID_AA64ISAR1_APA_ARCHITECTED,
+   .matches = has_cpuid_feature,
+   },
+   {
+   .desc = "Address authentication (IMP DEF algorithm)",
+   .capability = ARM64_HAS_ADDRESS_AUTH_IMP_DEF,
+   .type = ARM64_CPUCAP_SYSTEM_FEATURE,
+   .sys_reg = SYS_ID_AA64ISAR1_EL1,
+   .sign = FTR_UNSIGNED,
+   .field_pos = ID_AA64ISAR1_API_SHIFT,
+   .min_field_value = ID_AA64ISAR1_API_IMP_DEF,
+   .matches = has_cpuid_feature,
+   },
+   {
+   .capability = ARM64_HAS_ADDRESS_AUTH,
+   .type = ARM64_CPUCAP_SYSTEM_FEATURE,

[PATCHv4 03/10] arm64/kvm: hide ptrauth from guests

2018-05-03 Thread Mark Rutland
In subsequent patches we're going to expose ptrauth to the host kernel
and userspace, but things are a bit trickier for guest kernels. For the
time being, let's hide ptrauth from KVM guests.

Regardless of how well-behaved the guest kernel is, guest userspace
could attempt to use ptrauth instructions, triggering a trap to EL2,
resulting in noise from kvm_handle_unknown_ec(). So let's write up a
handler for the PAC trap, which silently injects an UNDEF into the
guest, as if the feature were really missing.

Signed-off-by: Mark Rutland <mark.rutl...@arm.com>
Reviewed-by: Andrew Jones <drjo...@redhat.com>
Reviewed-by: Christoffer Dall <christoffer.d...@arm.com>
Cc: Marc Zyngier <marc.zyng...@arm.com>
Cc: kvmarm@lists.cs.columbia.edu
---
 arch/arm64/kvm/handle_exit.c | 18 ++
 arch/arm64/kvm/sys_regs.c|  8 
 2 files changed, 26 insertions(+)

diff --git a/arch/arm64/kvm/handle_exit.c b/arch/arm64/kvm/handle_exit.c
index e5e741bfffe1..5114ad691eae 100644
--- a/arch/arm64/kvm/handle_exit.c
+++ b/arch/arm64/kvm/handle_exit.c
@@ -173,6 +173,23 @@ static int handle_sve(struct kvm_vcpu *vcpu, struct 
kvm_run *run)
return 1;
 }
 
+/*
+ * Guest usage of a ptrauth instruction (which the guest EL1 did not turn into
+ * a NOP), or guest EL1 access to a ptrauth register.
+ */
+static int kvm_handle_ptrauth(struct kvm_vcpu *vcpu, struct kvm_run *run)
+{
+   /*
+* We don't currently suport ptrauth in a guest, and we mask the ID
+* registers to prevent well-behaved guests from trying to make use of
+* it.
+*
+* Inject an UNDEF, as if the feature really isn't present.
+*/
+   kvm_inject_undefined(vcpu);
+   return 1;
+}
+
 static exit_handle_fn arm_exit_handlers[] = {
[0 ... ESR_ELx_EC_MAX]  = kvm_handle_unknown_ec,
[ESR_ELx_EC_WFx]= kvm_handle_wfx,
@@ -195,6 +212,7 @@ static exit_handle_fn arm_exit_handlers[] = {
[ESR_ELx_EC_BKPT32] = kvm_handle_guest_debug,
[ESR_ELx_EC_BRK64]  = kvm_handle_guest_debug,
[ESR_ELx_EC_FP_ASIMD]   = handle_no_fpsimd,
+   [ESR_ELx_EC_PAC]= kvm_handle_ptrauth,
 };
 
 static exit_handle_fn kvm_get_exit_handler(struct kvm_vcpu *vcpu)
diff --git a/arch/arm64/kvm/sys_regs.c b/arch/arm64/kvm/sys_regs.c
index 806b0b126a64..8b0dfc00bf5e 100644
--- a/arch/arm64/kvm/sys_regs.c
+++ b/arch/arm64/kvm/sys_regs.c
@@ -1000,6 +1000,14 @@ static u64 read_id_reg(struct sys_reg_desc const *r, 
bool raz)
task_pid_nr(current));
 
val &= ~(0xfUL << ID_AA64PFR0_SVE_SHIFT);
+   } else if (id == SYS_ID_AA64ISAR1_EL1) {
+   const u64 ptrauth_mask = (0xfUL << ID_AA64ISAR1_APA_SHIFT) |
+(0xfUL << ID_AA64ISAR1_API_SHIFT) |
+(0xfUL << ID_AA64ISAR1_GPA_SHIFT) |
+(0xfUL << ID_AA64ISAR1_GPI_SHIFT);
+   if (val & ptrauth_mask)
+   kvm_debug("ptrauth unsupported for guests, 
suppressing\n");
+   val &= ~ptrauth_mask;
} else if (id == SYS_ID_AA64MMFR1_EL1) {
if (val & (0xfUL << ID_AA64MMFR1_LOR_SHIFT))
pr_err_once("kvm [%i]: LORegions unsupported for 
guests, suppressing\n",
-- 
2.11.0

___
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm


[PATCHv4 04/10] arm64: Don't trap host pointer auth use to EL2

2018-05-03 Thread Mark Rutland
To allow EL0 (and/or EL1) to use pointer authentication functionality,
we must ensure that pointer authentication instructions and accesses to
pointer authentication keys are not trapped to EL2.

This patch ensures that HCR_EL2 is configured appropriately when the
kernel is booted at EL2. For non-VHE kernels we set HCR_EL2.{API,APK},
ensuring that EL1 can access keys and permit EL0 use of instructions.
For VHE kernels host EL0 (TGE && E2H) is unaffected by these settings,
and it doesn't matter how we configure HCR_EL2.{API,APK}, so we don't
bother setting them.

This does not enable support for KVM guests, since KVM manages HCR_EL2
itself when running VMs.

Signed-off-by: Mark Rutland <mark.rutl...@arm.com>
Acked-by: Christoffer Dall <christoffer.d...@arm.com>
Cc: Catalin Marinas <catalin.mari...@arm.com>
Cc: Marc Zyngier <marc.zyng...@arm.com>
Cc: Will Deacon <will.dea...@arm.com>
Cc: kvmarm@lists.cs.columbia.edu
---
 arch/arm64/include/asm/kvm_arm.h | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/arch/arm64/include/asm/kvm_arm.h b/arch/arm64/include/asm/kvm_arm.h
index 89b3dda7e3cb..4d57e1e58323 100644
--- a/arch/arm64/include/asm/kvm_arm.h
+++ b/arch/arm64/include/asm/kvm_arm.h
@@ -23,6 +23,8 @@
 #include 
 
 /* Hyp Configuration Register (HCR) bits */
+#define HCR_API(UL(1) << 41)
+#define HCR_APK(UL(1) << 40)
 #define HCR_TEA(UL(1) << 37)
 #define HCR_TERR   (UL(1) << 36)
 #define HCR_TLOR   (UL(1) << 35)
@@ -86,7 +88,7 @@
 HCR_AMO | HCR_SWIO | HCR_TIDCP | HCR_RW | HCR_TLOR | \
 HCR_FMO | HCR_IMO)
 #define HCR_VIRT_EXCP_MASK (HCR_VSE | HCR_VI | HCR_VF)
-#define HCR_HOST_NVHE_FLAGS (HCR_RW)
+#define HCR_HOST_NVHE_FLAGS (HCR_RW | HCR_API | HCR_APK)
 #define HCR_HOST_VHE_FLAGS (HCR_RW | HCR_TGE | HCR_E2H)
 
 /* TCR_EL2 Registers bits */
-- 
2.11.0

___
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm


[PATCHv4 01/10] arm64: add pointer authentication register bits

2018-05-03 Thread Mark Rutland
The ARMv8.3 pointer authentication extension adds:

* New fields in ID_AA64ISAR1 to report the presence of pointer
  authentication functionality.

* New control bits in SCTLR_ELx to enable this functionality.

* New system registers to hold the keys necessary for this
  functionality.

* A new ESR_ELx.EC code used when the new instructions are affected by
  configurable traps

This patch adds the relevant definitions to  and
 for these, to be used by subsequent patches.

Signed-off-by: Mark Rutland <mark.rutl...@arm.com>
Cc: Catalin Marinas <catalin.mari...@arm.com>
Cc: Marc Zyngier <marc.zyng...@arm.com>
Cc: Suzuki K Poulose <suzuki.poul...@arm.com>
Cc: Will Deacon <will.dea...@arm.com>
---
 arch/arm64/include/asm/esr.h|  3 ++-
 arch/arm64/include/asm/sysreg.h | 30 ++
 2 files changed, 32 insertions(+), 1 deletion(-)

diff --git a/arch/arm64/include/asm/esr.h b/arch/arm64/include/asm/esr.h
index ce70c3ffb993..022785162281 100644
--- a/arch/arm64/include/asm/esr.h
+++ b/arch/arm64/include/asm/esr.h
@@ -30,7 +30,8 @@
 #define ESR_ELx_EC_CP14_LS (0x06)
 #define ESR_ELx_EC_FP_ASIMD(0x07)
 #define ESR_ELx_EC_CP10_ID (0x08)
-/* Unallocated EC: 0x09 - 0x0B */
+#define ESR_ELx_EC_PAC (0x09)
+/* Unallocated EC: 0x0A - 0x0B */
 #define ESR_ELx_EC_CP14_64 (0x0C)
 /* Unallocated EC: 0x0d */
 #define ESR_ELx_EC_ILL (0x0E)
diff --git a/arch/arm64/include/asm/sysreg.h b/arch/arm64/include/asm/sysreg.h
index 6171178075dc..426f0eb90101 100644
--- a/arch/arm64/include/asm/sysreg.h
+++ b/arch/arm64/include/asm/sysreg.h
@@ -171,6 +171,19 @@
 #define SYS_TTBR1_EL1  sys_reg(3, 0, 2, 0, 1)
 #define SYS_TCR_EL1sys_reg(3, 0, 2, 0, 2)
 
+#define SYS_APIAKEYLO_EL1  sys_reg(3, 0, 2, 1, 0)
+#define SYS_APIAKEYHI_EL1  sys_reg(3, 0, 2, 1, 1)
+#define SYS_APIBKEYLO_EL1  sys_reg(3, 0, 2, 1, 2)
+#define SYS_APIBKEYHI_EL1  sys_reg(3, 0, 2, 1, 3)
+
+#define SYS_APDAKEYLO_EL1  sys_reg(3, 0, 2, 2, 0)
+#define SYS_APDAKEYHI_EL1  sys_reg(3, 0, 2, 2, 1)
+#define SYS_APDBKEYLO_EL1  sys_reg(3, 0, 2, 2, 2)
+#define SYS_APDBKEYHI_EL1  sys_reg(3, 0, 2, 2, 3)
+
+#define SYS_APGAKEYLO_EL1  sys_reg(3, 0, 2, 3, 0)
+#define SYS_APGAKEYHI_EL1  sys_reg(3, 0, 2, 3, 1)
+
 #define SYS_ICC_PMR_EL1sys_reg(3, 0, 4, 6, 0)
 
 #define SYS_AFSR0_EL1  sys_reg(3, 0, 5, 1, 0)
@@ -417,9 +430,13 @@
 #define SYS_ICH_LR15_EL2   __SYS__LR8_EL2(7)
 
 /* Common SCTLR_ELx flags. */
+#define SCTLR_ELx_ENIA (1 << 31)
+#define SCTLR_ELx_ENIB (1 << 30)
+#define SCTLR_ELx_ENDA (1 << 27)
 #define SCTLR_ELx_EE(1 << 25)
 #define SCTLR_ELx_IESB (1 << 21)
 #define SCTLR_ELx_WXN  (1 << 19)
+#define SCTLR_ELx_ENDB (1 << 13)
 #define SCTLR_ELx_I(1 << 12)
 #define SCTLR_ELx_SA   (1 << 3)
 #define SCTLR_ELx_C(1 << 2)
@@ -510,11 +527,24 @@
 #define ID_AA64ISAR0_AES_SHIFT 4
 
 /* id_aa64isar1 */
+#define ID_AA64ISAR1_GPI_SHIFT 28
+#define ID_AA64ISAR1_GPA_SHIFT 24
 #define ID_AA64ISAR1_LRCPC_SHIFT   20
 #define ID_AA64ISAR1_FCMA_SHIFT16
 #define ID_AA64ISAR1_JSCVT_SHIFT   12
+#define ID_AA64ISAR1_API_SHIFT 8
+#define ID_AA64ISAR1_APA_SHIFT 4
 #define ID_AA64ISAR1_DPB_SHIFT 0
 
+#define ID_AA64ISAR1_APA_NI0x0
+#define ID_AA64ISAR1_APA_ARCHITECTED   0x1
+#define ID_AA64ISAR1_API_NI0x0
+#define ID_AA64ISAR1_API_IMP_DEF   0x1
+#define ID_AA64ISAR1_GPA_NI0x0
+#define ID_AA64ISAR1_GPA_ARCHITECTED   0x1
+#define ID_AA64ISAR1_GPI_NI0x0
+#define ID_AA64ISAR1_GPI_IMP_DEF   0x1
+
 /* id_aa64pfr0 */
 #define ID_AA64PFR0_CSV3_SHIFT 60
 #define ID_AA64PFR0_CSV2_SHIFT 56
-- 
2.11.0

___
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm


[PATCHv4 00/10] ARMv8.3 pointer authentication userspace support

2018-05-03 Thread Mark Rutland
This series adds support for the ARMv8.3 pointer authentication extension,
enabling userspace return address protection with recent versions of GCC.

Since RFC [1]:
* Make the KVM context switch (semi-lazy)
* Rebase to v4.13-rc1
* Improve pointer authentication documentation
* Add hwcap documentation
* Various minor cleanups

Since v1 [2]:
* Rebase to v4.15-rc1
* Settle on per-process keys
* Strip PACs when unwinding userspace
* Don't expose an XPAC hwcap (this is implied by ID registers)
* Leave APIB, ABPDA, APDB, and APGA keys unsupported for now
* Support IMP DEF algorithms
* Rely on KVM ID register emulation
* Various cleanups

Since v2 [3]:
* Unify HCR_EL2 initialization
* s/POINTER_AUTHENTICATION/PTR_AUTH/
* Drop KVM support (for now)
* Drop detection of generic authentication

Since v3 [4]:
* Drop KVM logging to kvm_debug()
* Init keys in init_new_context()
* Drop mm_hooks changes
* Commit message cleanups
* Minor formatting fixups
* Fold in acks and other tags

While there are use-cases for keys other than APIAKey, the only software that
I'm aware of with pointer authentication support is GCC, which only makes use
of APIAKey. I'm happy to add support for other keys as users appear.

I've pushed the series to the arm64/pointer-auth branch [5] of my linux tree.
The aarch64 bootwrapper [6] does the necessary EL3 setup.


Extension Overview 
==

The ARMv8.3 pointer authentication extension adds functionality to detect
modification of pointer values, mitigating certain classes of attack such as
stack smashing, and making return oriented programming attacks harder

The extension introduces the concept of a pointer authentication code (PAC),
which is stored in some upper bits of pointers. Each PAC is derived from the
original pointer, another 64-bit value (e.g. the stack pointer), and a secret
128-bit key.

New instructions are added which can be used to:

* Insert a PAC into a pointer
* Strip a PAC from a pointer
* Authenticate strip a PAC from a pointer

If authentication succeeds, the code is removed, yielding the original pointer.
If authentication fails, bits are set in the pointer such that it is guaranteed
to cause a fault if used.

These instructions can make use of four keys:

* APIAKey (A.K.A. Instruction A key)
* APIBKey (A.K.A. Instruction B key)
* APDAKey (A.K.A. Data A key)
* APDBKey (A.K.A. Data B Key)

A subset of these instruction encodings have been allocated from the HINT
space, and will operate as NOPs on any ARMv8-A parts which do not feature the
extension (or if purposefully disabled by the kernel). Software using only this
subset of the instructions should function correctly on all ARMv8-A parts.

Additionally, instructions are added to authenticate small blocks of memory in
similar fashion, using APGAKey (A.K.A. Generic key).


This Series
===

This series enables the use of instructions using APIAKey, which is initialised
and maintained per-process (shared by all threads). This series does not add
support for APIBKey, APDAKey, APDBKey, nor APGAKey.

I've given this some basic testing with a homebrew test suite. More ideally,
we'd add some tests to the kernel source tree.

For the time being, pointer authentication functionality is hidden from
guests via ID register trapping.

Thanks,
Mark.

[1] http://lists.infradead.org/pipermail/linux-arm-kernel/2017-April/498941.html
[2] 
https://lkml.kernel.org/r/1500480092-28480-1-git-send-email-mark.rutl...@arm.com
[3] https://lkml.kernel.org/r/20171127163806.31435-1-mark.rutl...@arm.com
[4] https://lkml.kernel.org/r/20180417183735.56985-1-mark.rutl...@arm.com
[5] git://git.kernel.org/pub/scm/linux/kernel/git/mark/linux.git 
arm64/pointer-auth
[6] git://git.kernel.org/pub/scm/linux/kernel/git/mark/boot-wrapper-aarch64.git

Mark Rutland (10):
  arm64: add pointer authentication register bits
  arm64/kvm: consistently handle host HCR_EL2 flags
  arm64/kvm: hide ptrauth from guests
  arm64: Don't trap host pointer auth use to EL2
  arm64/cpufeature: detect pointer authentication
  arm64: add basic pointer authentication support
  arm64: expose user PAC bit positions via ptrace
  arm64: perf: strip PAC when unwinding userspace
  arm64: enable pointer authentication
  arm64: docs: document pointer authentication

 Documentation/arm64/booting.txt|  8 +++
 Documentation/arm64/elf_hwcaps.txt |  6 ++
 Documentation/arm64/pointer-authentication.txt | 84 
 arch/arm64/Kconfig | 23 +++
 arch/arm64/include/asm/cpucaps.h   |  5 +-
 arch/arm64/include/asm/esr.h   |  3 +-
 arch/arm64/include/asm/kvm_arm.h   |  3 +
 arch/arm64/include/asm/mmu.h   |  5 ++
 arch/arm64/include/asm/mmu_context.h   | 11 +++-
 arch/arm64/include/asm/pointer_auth.h  | 90 ++
 arch/arm64/include/asm/sysreg.h| 30 +
 arch/arm64/include/uapi/asm/hwcap.h

[PATCHv4 02/10] arm64/kvm: consistently handle host HCR_EL2 flags

2018-05-03 Thread Mark Rutland
In KVM we define the configuration of HCR_EL2 for a VHE HOST in
HCR_HOST_VHE_FLAGS, but we don't have a similar definition for the
non-VHE host flags, and open-code HCR_RW. Further, in head.S we
open-code the flags for VHE and non-VHE configurations.

In future, we're going to want to configure more flags for the host, so
lets add a HCR_HOST_NVHE_FLAGS defintion, and consistently use both
HCR_HOST_VHE_FLAGS and HCR_HOST_NVHE_FLAGS in the kvm code and head.S.

We now use mov_q to generate the HCR_EL2 value, as we use when
configuring other registers in head.S.

Signed-off-by: Mark Rutland <mark.rutl...@arm.com>
Reviewed-by: Christoffer Dall <christoffer.d...@arm.com>
Cc: Catalin Marinas <catalin.mari...@arm.com>
Cc: Marc Zyngier <marc.zyng...@arm.com>
Cc: Will Deacon <will.dea...@arm.com>
Cc: kvmarm@lists.cs.columbia.edu
---
 arch/arm64/include/asm/kvm_arm.h | 1 +
 arch/arm64/kernel/head.S | 5 ++---
 arch/arm64/kvm/hyp/switch.c  | 2 +-
 3 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/arch/arm64/include/asm/kvm_arm.h b/arch/arm64/include/asm/kvm_arm.h
index 6dd285e979c9..89b3dda7e3cb 100644
--- a/arch/arm64/include/asm/kvm_arm.h
+++ b/arch/arm64/include/asm/kvm_arm.h
@@ -86,6 +86,7 @@
 HCR_AMO | HCR_SWIO | HCR_TIDCP | HCR_RW | HCR_TLOR | \
 HCR_FMO | HCR_IMO)
 #define HCR_VIRT_EXCP_MASK (HCR_VSE | HCR_VI | HCR_VF)
+#define HCR_HOST_NVHE_FLAGS (HCR_RW)
 #define HCR_HOST_VHE_FLAGS (HCR_RW | HCR_TGE | HCR_E2H)
 
 /* TCR_EL2 Registers bits */
diff --git a/arch/arm64/kernel/head.S b/arch/arm64/kernel/head.S
index b0853069702f..651a06b1980f 100644
--- a/arch/arm64/kernel/head.S
+++ b/arch/arm64/kernel/head.S
@@ -494,10 +494,9 @@ ENTRY(el2_setup)
 #endif
 
/* Hyp configuration. */
-   mov x0, #HCR_RW // 64-bit EL1
+   mov_q   x0, HCR_HOST_NVHE_FLAGS
cbz x2, set_hcr
-   orr x0, x0, #HCR_TGE// Enable Host Extensions
-   orr x0, x0, #HCR_E2H
+   mov_q   x0, HCR_HOST_VHE_FLAGS
 set_hcr:
msr hcr_el2, x0
isb
diff --git a/arch/arm64/kvm/hyp/switch.c b/arch/arm64/kvm/hyp/switch.c
index d9645236e474..cdae330e15e9 100644
--- a/arch/arm64/kvm/hyp/switch.c
+++ b/arch/arm64/kvm/hyp/switch.c
@@ -143,7 +143,7 @@ static void __hyp_text __deactivate_traps_nvhe(void)
mdcr_el2 |= MDCR_EL2_E2PB_MASK << MDCR_EL2_E2PB_SHIFT;
 
write_sysreg(mdcr_el2, mdcr_el2);
-   write_sysreg(HCR_RW, hcr_el2);
+   write_sysreg(HCR_HOST_NVHE_FLAGS, hcr_el2);
write_sysreg(CPTR_EL2_DEFAULT, cptr_el2);
 }
 
-- 
2.11.0

___
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm


Re: [PATCHv3 07/11] arm64: add basic pointer authentication support

2018-04-27 Thread Mark Rutland
On Wed, Apr 25, 2018 at 12:23:32PM +0100, Catalin Marinas wrote:
> Hi Mark,
> 
> On Tue, Apr 17, 2018 at 07:37:31PM +0100, Mark Rutland wrote:
> > diff --git a/arch/arm64/include/asm/mmu_context.h 
> > b/arch/arm64/include/asm/mmu_context.h
> > index 39ec0b8a689e..caf0d3010112 100644
> > --- a/arch/arm64/include/asm/mmu_context.h
> > +++ b/arch/arm64/include/asm/mmu_context.h
> > @@ -29,7 +29,6 @@
> >  #include 
> >  #include 
> >  #include 
> > -#include 
> >  #include 
> >  #include 
> >  #include 
> > @@ -168,7 +167,14 @@ static inline void cpu_replace_ttbr1(pgd_t *pgdp)
> >  #define destroy_context(mm)do { } while(0)
> >  void check_and_switch_context(struct mm_struct *mm, unsigned int cpu);
> >  
> > -#define init_new_context(tsk,mm)   ({ atomic64_set(&(mm)->context.id, 0); 
> > 0; })
> > +static inline int init_new_context(struct task_struct *tsk,
> > +   struct mm_struct *mm)
> > +{
> > +   atomic64_set(>context.id, 0);
> > +   mm_ctx_ptrauth_init(>context);
> > +
> > +   return 0;
> > +}
> >  
> >  #ifdef CONFIG_ARM64_SW_TTBR0_PAN
> >  static inline void update_saved_ttbr0(struct task_struct *tsk,
> > @@ -216,6 +222,8 @@ static inline void __switch_mm(struct mm_struct *next)
> > return;
> > }
> >  
> > +   mm_ctx_ptrauth_switch(>context);
> > +
> > check_and_switch_context(next, cpu);
> >  }
> >  
> > @@ -241,6 +249,19 @@ switch_mm(struct mm_struct *prev, struct mm_struct 
> > *next,
> >  void verify_cpu_asid_bits(void);
> >  void post_ttbr_update_workaround(void);
> >  
> > +static inline void arch_dup_mmap(struct mm_struct *oldmm,
> > +struct mm_struct *mm)
> > +{
> > +   mm_ctx_ptrauth_dup(>context, >context);
> > +}
> > +#define arch_dup_mmap arch_dup_mmap
> 
> IIUC, we could skip the arch_dup_mmap() and init_new_context() here for
> the fork() case since the ptrauth_keys would be copied as part of the
> dup_mm().

If we can hook into the exec*() path to init the keys, then I agree we
can do this...

> There is another situation where init_new_context() is called
> bprm_mm_init() -> mm_alloc() -> mm_init() -> init_new_context().
> However, in this case the core code also calls arch_bprm_mm_init(). So I
> think we only need to update the latter to get a new random key.

... and this seems to be the right place to do it, so I'll have a go.

> > diff --git a/arch/arm64/include/asm/pointer_auth.h 
> > b/arch/arm64/include/asm/pointer_auth.h
> > new file mode 100644
> > index ..a2e8fb91fdee
> > --- /dev/null
> > +++ b/arch/arm64/include/asm/pointer_auth.h
> > @@ -0,0 +1,89 @@
> > +/*
> > + * Copyright (C) 2016 ARM Ltd.
> > + *
> > + * This program is free software; you can redistribute it and/or modify
> > + * it under the terms of the GNU General Public License version 2 as
> > + * published by the Free Software Foundation.
> > + *
> > + * This program is distributed in the hope that it will be useful,
> > + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> > + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> > + * GNU General Public License for more details.
> > + *
> > + * You should have received a copy of the GNU General Public License
> > + * along with this program.  If not, see <http://www.gnu.org/licenses/>.
> > + */
> 
> Nitpick: 2018. You could also use the SPDX header, save some lines.

Sure, I'll replace this with a SPDX GPL-2.0 line.

Thanks,
Mark.
___
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm


Re: [PATCHv3 02/11] arm64/kvm: consistently handle host HCR_EL2 flags

2018-04-27 Thread Mark Rutland
On Fri, Apr 27, 2018 at 11:51:39AM +0200, Christoffer Dall wrote:
> On Tue, Apr 17, 2018 at 07:37:26PM +0100, Mark Rutland wrote:
> > In KVM we define the configuration of HCR_EL2 for a VHE HOST in
> > HCR_HOST_VHE_FLAGS, but we don't ahve a similar definition for the
> 
> nit: have
> 
> > non-VHE host flags, and open-code HCR_RW. Further, in head.S we
> > open-code the flags for VHE and non-VHE configurations.
> > 
> > In future, we're going to want to configure more flags for the host, so
> > lets add a HCR_HOST_NVHE_FLAGS defintion, adn consistently use both
> 
> nit: and
> 

Sorry about those; fixed up now.

[...]

> Reviewed-by: Christoffer Dall <christoffer.d...@arm.com>

Cheers!

Mark.
___
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm


[PATCH 3/3] KVM: arm/arm64: vgic: fix possible spectre-v1 in vgic_mmio_read_apr()

2018-04-25 Thread Mark Rutland
It's possible for userspace to control n. Sanitize n when using it as an
array index.

Note that while it appears that n must be bound to the interval [0,3]
due to the way it is extracted from addr, we cannot guarantee that
compiler transformations (and/or future refactoring) will ensure this is
the case, and given this is a slow path it's better to always perform
the masking.

Found by smatch.

Signed-off-by: Mark Rutland <mark.rutl...@arm.com>
Cc: Christoffer Dall <cd...@kernel.org>
Cc: Marc Zyngier <marc.zyng...@arm.com>
Cc: kvmarm@lists.cs.columbia.edu
---
 virt/kvm/arm/vgic/vgic-mmio-v2.c | 5 +
 1 file changed, 5 insertions(+)

diff --git a/virt/kvm/arm/vgic/vgic-mmio-v2.c b/virt/kvm/arm/vgic/vgic-mmio-v2.c
index e21e2f49b005..ffc587bf4742 100644
--- a/virt/kvm/arm/vgic/vgic-mmio-v2.c
+++ b/virt/kvm/arm/vgic/vgic-mmio-v2.c
@@ -14,6 +14,8 @@
 #include 
 #include 
 #include 
+#include 
+
 #include 
 #include 
 
@@ -324,6 +326,9 @@ static unsigned long vgic_mmio_read_apr(struct kvm_vcpu 
*vcpu,
 
if (n > vgic_v3_max_apr_idx(vcpu))
return 0;
+
+   n = array_index_nospec(n, 4);
+
/* GICv3 only uses ICH_AP1Rn for memory mapped (GICv2) guests */
return vgicv3->vgic_ap1r[n];
}
-- 
2.11.0

___
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm


[PATCH 0/3] arm64/kvm spectre-v1 fixes

2018-04-25 Thread Mark Rutland
These patches fix arm64-specific potential spectre-v1 gadgets found by
smatch when run over v4.17-rc2.

I'm still building up my smatch database, so it's possible that there are
further gadgets to be found.

For the moment I've ignored issues which appear to be cross-architecture.

Thanks,
Mark.

Mark Rutland (3):
  arm64: fix possible spectre-v1 in ptrace_hbp_get_event()
  KVM: arm/arm64: vgic: fix possible spectre-v1 in vgic_get_irq()
  KVM: arm/arm64: vgic: fix possible spectre-v1 in vgic_mmio_read_apr()

 arch/arm64/kernel/ptrace.c   | 14 ++
 virt/kvm/arm/vgic/vgic-mmio-v2.c |  5 +
 virt/kvm/arm/vgic/vgic.c | 14 ++
 3 files changed, 25 insertions(+), 8 deletions(-)

-- 
2.11.0

___
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm


Re: Clang arm64 build is broken

2018-04-20 Thread Mark Rutland
Hi Andrey,

On Fri, Apr 20, 2018 at 04:59:35PM +0200, Andrey Konovalov wrote:
> On Fri, Apr 20, 2018 at 10:13 AM, Marc Zyngier  wrote:
> >> The issue is that
> >> clang doesn't know about the "S" asm constraint. I reported this to
> >> clang [2], and hopefully this will get fixed. In the meantime, would
> >> it possible to work around using the "S" constraint in the kernel?
> >
> > I have no idea, I've never used clang to build the kernel. Clang isn't
> > really supported to build the arm64 kernel anyway (as you mention
> > below), and working around clang deficiencies would mean that we leave
> > with the workaround forever. I'd rather enable clang once it is at
> > feature parity with GCC.
> 
> The fact that there are some existing issues with building arm64
> kernel with clang doesn't sound like a good justification for adding
> new issues :)

I appreciate this is somewhat frustrating, but every feature where clang
is not at parity with GCC is effectively a functional regression for us.

Recently, the code that clang hasn't liked happens to be security
critical, and it is somewhat difficult to justify making that code more
complex to cater for a compiler that we know has outstanding issues with
features we rely upon.

Which is to say, I'm not sure that there's much justification either
way. We really need clang to be at feature parity with GCC for it to be
considered supported.

It would be great if some effort could be focussed on bringing clang to
feature parity with GCC before implementing new clang-specific features.

> However in this case I do believe that this is more of a bug in clang
> that should be fixed.

Just to check: does clang implement the rest of the AArch64 machine
constraints [1]?

We're liable to use more of them in future, and we should aim for parity
now so that we don't fall into the same trap in future.

> >> While we're here, regarding the other issue with kvm [3], I didn't
> >> receive any comments as to whether it makes sense to send the fix that
> >> adds -fno-jump-tables flag when building kvm with clang.
> >
> > Is that the only thing missing? Are you sure that there is no other way
> > for clang to generate absolute addresses that will then lead to a crash?
> > Again, I'd rather make sure we have the full picture.
> 
> Well, I have tried applying that patch and running kvm tests that I
> could find [1], and they passed (actually I think there was an issue
> with one of them, but I saw the same thing when I tried running them
> on a kernel built with GCC).

I think what Marc wants is a statement as to whether -fno-jump-tables is
sufficient to ensure that clang will not try to use absolute addressing,
based on an understanding of the AArch64 LLVM backend rather than test
cases.

For example, could any other pass result in the use of an absolute
address? Or are jump tables the *only* reason that clang would try to
use an absolute address.

Are there other options that we might need to pass?

Are there any options that we can pass to forbid absolute addressing?

Thanks,
Mark.

[1] https://gcc.gnu.org/onlinedocs/gccint/Machine-Constraints.html
___
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm


Re: [PATCHv3 03/11] arm64/kvm: hide ptrauth from guests

2018-04-18 Thread Mark Rutland
On Wed, Apr 18, 2018 at 03:19:26PM +0200, Andrew Jones wrote:
> On Tue, Apr 17, 2018 at 07:37:27PM +0100, Mark Rutland wrote:
> > @@ -1000,6 +1000,15 @@ static u64 read_id_reg(struct sys_reg_desc const *r, 
> > bool raz)
> > task_pid_nr(current));
> >  
> > val &= ~(0xfUL << ID_AA64PFR0_SVE_SHIFT);
> > +   } else if (id == SYS_ID_AA64ISAR1_EL1) {
> > +   const u64 ptrauth_mask = (0xfUL << ID_AA64ISAR1_APA_SHIFT) |
> > +(0xfUL << ID_AA64ISAR1_API_SHIFT) |
> > +(0xfUL << ID_AA64ISAR1_GPA_SHIFT) |
> > +(0xfUL << ID_AA64ISAR1_GPI_SHIFT);
> > +   if (val & ptrauth_mask)
> > +   pr_err_once("kvm [%i]: ptrauth unsupported for guests, 
> > suppressing\n",
> > +   task_pid_nr(current));
> 
> Marc just changed the equivalent SVE pr_err_once() to kvm_debug().
> So we probably want to do the same here.

Good point. Done.

> > +   val &= ~ptrauth_mask;
> > } else if (id == SYS_ID_AA64MMFR1_EL1) {
> > if (val & (0xfUL << ID_AA64MMFR1_LOR_SHIFT))
> > pr_err_once("kvm [%i]: LORegions unsupported for 
> > guests, suppressing\n",
> > -- 
> > 2.11.0
> >
> 
> Otherwise
>  
> Reviewed-by: Andrew Jones <drjo...@redhat.com>

Cheers!

Mark.
___
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm


Re: [PATCHv3 06/11] asm-generic: mm_hooks: allow hooks to be overridden individually

2018-04-18 Thread Mark Rutland
On Tue, Apr 17, 2018 at 09:56:02PM +0200, Arnd Bergmann wrote:
> On Tue, Apr 17, 2018 at 8:37 PM, Mark Rutland <mark.rutl...@arm.com> wrote:
> > Currently, an architecture must either implement all of the mm hooks
> > itself, or use all of those provided by the asm-generic implementation.
> > When an architecture only needs to override a single hook, it must copy
> > the stub implementations from the asm-generic version.
> >
> > To avoid this repetition, allow each hook to be overridden indiviually,
> > by placing each under an #ifndef block. As architectures providing their
> > own hooks can't include this file today, this shouldn't adversely affect
> > any existing hooks.
> >
> > Signed-off-by: Mark Rutland <mark.rutl...@arm.com>
> > Cc: Arnd Bergmann <a...@arndb.de>
> > Cc: linux-a...@vger.kernel.org
> 
> Acked-by: Arnd Bergmann <a...@arndb.de>

Cheers!

Mark.
___
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm


[PATCHv3 11/11] arm64: docs: document pointer authentication

2018-04-17 Thread Mark Rutland
Now that we've added code to support pointer authentication, add some
documentation so that people can figure out if/how to use it.

Signed-off-by: Mark Rutland <mark.rutl...@arm.com>
Cc: Andrew Jones <drjo...@redhat.com>
Cc: Catalin Marinas <catalin.mari...@arm.com>
Cc: Ramana Radhakrishnan <ramana.radhakrish...@arm.com>
Cc: Will Deacon <will.dea...@arm.com>
---
 Documentation/arm64/booting.txt|  8 +++
 Documentation/arm64/elf_hwcaps.txt |  6 ++
 Documentation/arm64/pointer-authentication.txt | 84 ++
 3 files changed, 98 insertions(+)
 create mode 100644 Documentation/arm64/pointer-authentication.txt

diff --git a/Documentation/arm64/booting.txt b/Documentation/arm64/booting.txt
index 8d0df62c3fe0..8df9f4658d6f 100644
--- a/Documentation/arm64/booting.txt
+++ b/Documentation/arm64/booting.txt
@@ -205,6 +205,14 @@ Before jumping into the kernel, the following conditions 
must be met:
 ICC_SRE_EL2.SRE (bit 0) must be initialised to 0b0.
   - The DT or ACPI tables must describe a GICv2 interrupt controller.
 
+  For CPUs with pointer authentication functionality:
+  - If EL3 is present:
+SCR_EL3.APK (bit 16) must be initialised to 0b1
+SCR_EL3.API (bit 17) must be initialised to 0b1
+  - If the kernel is entered at EL1:
+HCR_EL2.APK (bit 40) must be initialised to 0b1
+HCR_EL2.API (bit 41) must be initialised to 0b1
+
 The requirements described above for CPU mode, caches, MMUs, architected
 timers, coherency and system registers apply to all CPUs.  All CPUs must
 enter the kernel in the same exception level.
diff --git a/Documentation/arm64/elf_hwcaps.txt 
b/Documentation/arm64/elf_hwcaps.txt
index d6aff2c5e9e2..ebc8b15b45fc 100644
--- a/Documentation/arm64/elf_hwcaps.txt
+++ b/Documentation/arm64/elf_hwcaps.txt
@@ -178,3 +178,9 @@ HWCAP_ILRCPC
 HWCAP_FLAGM
 
 Functionality implied by ID_AA64ISAR0_EL1.TS == 0b0001.
+
+HWCAP_APIA
+
+EL0 AddPac and Auth functionality using APIAKey_EL1 is enabled, as
+described by Documentation/arm64/pointer-authentication.txt.
+
diff --git a/Documentation/arm64/pointer-authentication.txt 
b/Documentation/arm64/pointer-authentication.txt
new file mode 100644
index ..8a9cb5713770
--- /dev/null
+++ b/Documentation/arm64/pointer-authentication.txt
@@ -0,0 +1,84 @@
+Pointer authentication in AArch64 Linux
+=======
+
+Author: Mark Rutland <mark.rutl...@arm.com>
+Date: 2017-07-19
+
+This document briefly describes the provision of pointer authentication
+functionality in AArch64 Linux.
+
+
+Architecture overview
+-
+
+The ARMv8.3 Pointer Authentication extension adds primitives that can be
+used to mitigate certain classes of attack where an attacker can corrupt
+the contents of some memory (e.g. the stack).
+
+The extension uses a Pointer Authentication Code (PAC) to determine
+whether pointers have been modified unexpectedly. A PAC is derived from
+a pointer, another value (such as the stack pointer), and a secret key
+held in system registers.
+
+The extension adds instructions to insert a valid PAC into a pointer,
+and to verify/remove the PAC from a pointer. The PAC occupies a number
+of high-order bits of the pointer, which varies dependent on the
+configured virtual address size and whether pointer tagging is in use.
+
+A subset of these instructions have been allocated from the HINT
+encoding space. In the absence of the extension (or when disabled),
+these instructions behave as NOPs. Applications and libraries using
+these instructions operate correctly regardless of the presence of the
+extension.
+
+
+Basic support
+-
+
+When CONFIG_ARM64_PTR_AUTH is selected, and relevant HW support is
+present, the kernel will assign a random APIAKey value to each process
+at exec*() time. This key is shared by all threads within the process,
+and the key is preserved across fork(). Presence of functionality using
+APIAKey is advertised via HWCAP_APIA.
+
+Recent versions of GCC can compile code with APIAKey-based return
+address protection when passed the -msign-return-address option. This
+uses instructions in the HINT space, and such code can run on systems
+without the pointer authentication extension.
+
+The remaining instruction and data keys (APIBKey, APDAKey, APDBKey) are
+reserved for future use, and instructions using these keys must not be
+used by software until a purpose and scope for their use has been
+decided. To enable future software using these keys to function on
+contemporary kernels, where possible, instructions using these keys are
+made to behave as NOPs.
+
+The generic key (APGAKey) is currently unsupported. Instructions using
+the generic key must not be used by software.
+
+
+Debugging
+-
+
+When CONFIG_ARM64_PTR_AUTH is selected, and relevant HW support is
+present, the kernel will expose the position of TTBR0 PAC bits in the
+NT_ARM_PAC_MASK regset (struct

[PATCHv3 09/11] arm64: perf: strip PAC when unwinding userspace

2018-04-17 Thread Mark Rutland
When the kernel is unwinding userspace callchains, we can't expect that
the userspace consumer of these callchains has the data necessary to
strip the PAC from the stored LR.

This patch has the kernel strip the PAC from user stackframes when the
in-kernel unwinder is used. This only affects the LR value, and not the
FP.

This only affects the in-kernel unwinder. When userspace performs
unwinding, it is up to userspace to strip PACs as necessary (which can
be determined from DWARF information).

Signed-off-by: Mark Rutland <mark.rutl...@arm.com>
Cc: Catalin Marinas <catalin.mari...@arm.com>
Cc: Ramana Radhakrishnan <ramana.radhakrish...@arm.com>
Cc: Will Deacon <will.dea...@arm.com>
---
 arch/arm64/include/asm/pointer_auth.h | 7 +++
 arch/arm64/kernel/perf_callchain.c| 5 -
 2 files changed, 11 insertions(+), 1 deletion(-)

diff --git a/arch/arm64/include/asm/pointer_auth.h 
b/arch/arm64/include/asm/pointer_auth.h
index 5ff141245633..a9ad81791c7f 100644
--- a/arch/arm64/include/asm/pointer_auth.h
+++ b/arch/arm64/include/asm/pointer_auth.h
@@ -79,6 +79,12 @@ static inline void ptrauth_keys_dup(struct ptrauth_keys *old,
  */
 #define ptrauth_pac_mask() GENMASK(54, VA_BITS)
 
+/* Only valid for EL0 TTBR0 instruction pointers */
+static inline unsigned long ptrauth_strip_insn_pac(unsigned long ptr)
+{
+   return ptr & ~ptrauth_pac_mask();
+}
+
 #define mm_ctx_ptrauth_init(ctx) \
ptrauth_keys_init(&(ctx)->ptrauth_keys)
 
@@ -89,6 +95,7 @@ static inline void ptrauth_keys_dup(struct ptrauth_keys *old,
ptrauth_keys_dup(&(oldctx)->ptrauth_keys, &(newctx)->ptrauth_keys)
 
 #else
+#define ptrauth_strip_insn_pac(lr) (lr)
 #define mm_ctx_ptrauth_init(ctx)
 #define mm_ctx_ptrauth_switch(ctx)
 #define mm_ctx_ptrauth_dup(oldctx, newctx)
diff --git a/arch/arm64/kernel/perf_callchain.c 
b/arch/arm64/kernel/perf_callchain.c
index bcafd7dcfe8b..928204f6ab08 100644
--- a/arch/arm64/kernel/perf_callchain.c
+++ b/arch/arm64/kernel/perf_callchain.c
@@ -35,6 +35,7 @@ user_backtrace(struct frame_tail __user *tail,
 {
struct frame_tail buftail;
unsigned long err;
+   unsigned long lr;
 
/* Also check accessibility of one struct frame_tail beyond */
if (!access_ok(VERIFY_READ, tail, sizeof(buftail)))
@@ -47,7 +48,9 @@ user_backtrace(struct frame_tail __user *tail,
if (err)
return NULL;
 
-   perf_callchain_store(entry, buftail.lr);
+   lr = ptrauth_strip_insn_pac(buftail.lr);
+
+   perf_callchain_store(entry, lr);
 
/*
 * Frame pointers should strictly progress back up the stack
-- 
2.11.0

___
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm


[PATCHv3 10/11] arm64: enable pointer authentication

2018-04-17 Thread Mark Rutland
Now that all the necessary bits are in place for userspace, add the
necessary Kconfig logic to allow this to be enabled.

Signed-off-by: Mark Rutland <mark.rutl...@arm.com>
Cc: Catalin Marinas <catalin.mari...@arm.com>
Cc: Will Deacon <will.dea...@arm.com>
---
 arch/arm64/Kconfig | 23 +++
 1 file changed, 23 insertions(+)

diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
index eb2cf4938f6d..d6ce16b1ee47 100644
--- a/arch/arm64/Kconfig
+++ b/arch/arm64/Kconfig
@@ -1127,6 +1127,29 @@ config ARM64_RAS_EXTN
 
 endmenu
 
+menu "ARMv8.3 architectural features"
+
+config ARM64_PTR_AUTH
+   bool "Enable support for pointer authentication"
+   default y
+   help
+ Pointer authentication (part of the ARMv8.3 Extensions) provides
+ instructions for signing and authenticating pointers against secret
+ keys, which can be used to mitigate Return Oriented Programming (ROP)
+ and other attacks.
+
+ This option enables these instructions at EL0 (i.e. for userspace).
+
+ Choosing this option will cause the kernel to initialise secret keys
+ for each process at exec() time, with these keys being
+ context-switched along with the process.
+
+ The feature is detected at runtime. If the feature is not present in
+ hardware it will not be advertised to userspace nor will it be
+ enabled.
+
+endmenu
+
 config ARM64_SVE
bool "ARM Scalable Vector Extension support"
default y
-- 
2.11.0

___
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm


[PATCHv3 08/11] arm64: expose user PAC bit positions via ptrace

2018-04-17 Thread Mark Rutland
When pointer authentication is in use, data/instruction pointers have a
number of PAC bits inserted into them. The number and position of these
bits depends on the configured TCR_ELx.TxSZ and whether tagging is
enabled. ARMv8.3 allows tagging to differ for instruction and data
pointers.

For userspace debuggers to unwind the stack and/or to follow pointer
chains, they need to be able to remove the PAC bits before attempting to
use a pointer.

This patch adds a new structure with masks describing the location of
the PAC bits in userspace instruction and data pointers (i.e. those
addressable via TTBR0), which userspace can query via PTRACE_GETREGSET.
By clearing these bits from pointers, userspace can acquire the PAC-less
versions.

This new regset is exposed when the kernel is built with (user) pointer
authentication support, and the feature is enabled. Otherwise, it is
hidden.

Signed-off-by: Mark Rutland <mark.rutl...@arm.com>
Cc: Catalin Marinas <catalin.mari...@arm.com>
Cc: Ramana Radhakrishnan <ramana.radhakrish...@arm.com>
Cc: Will Deacon <will.dea...@arm.com>
---
 arch/arm64/include/asm/pointer_auth.h |  8 
 arch/arm64/include/uapi/asm/ptrace.h  |  7 +++
 arch/arm64/kernel/ptrace.c| 38 +++
 include/uapi/linux/elf.h  |  1 +
 4 files changed, 54 insertions(+)

diff --git a/arch/arm64/include/asm/pointer_auth.h 
b/arch/arm64/include/asm/pointer_auth.h
index a2e8fb91fdee..5ff141245633 100644
--- a/arch/arm64/include/asm/pointer_auth.h
+++ b/arch/arm64/include/asm/pointer_auth.h
@@ -16,9 +16,11 @@
 #ifndef __ASM_POINTER_AUTH_H
 #define __ASM_POINTER_AUTH_H
 
+#include 
 #include 
 
 #include 
+#include 
 #include 
 
 #ifdef CONFIG_ARM64_PTR_AUTH
@@ -71,6 +73,12 @@ static inline void ptrauth_keys_dup(struct ptrauth_keys *old,
*new = *old;
 }
 
+/*
+ * The EL0 pointer bits used by a pointer authentication code.
+ * This is dependent on TBI0 being enabled, or bits 63:56 would also apply.
+ */
+#define ptrauth_pac_mask() GENMASK(54, VA_BITS)
+
 #define mm_ctx_ptrauth_init(ctx) \
ptrauth_keys_init(&(ctx)->ptrauth_keys)
 
diff --git a/arch/arm64/include/uapi/asm/ptrace.h 
b/arch/arm64/include/uapi/asm/ptrace.h
index 98c4ce55d9c3..4994d718771a 100644
--- a/arch/arm64/include/uapi/asm/ptrace.h
+++ b/arch/arm64/include/uapi/asm/ptrace.h
@@ -228,6 +228,13 @@ struct user_sve_header {
  SVE_PT_SVE_OFFSET + SVE_PT_SVE_SIZE(vq, flags)\
: SVE_PT_FPSIMD_OFFSET + SVE_PT_FPSIMD_SIZE(vq, flags))
 
+/* pointer authentication masks (NT_ARM_PAC_MASK) */
+
+struct user_pac_mask {
+   __u64   data_mask;
+   __u64   insn_mask;
+};
+
 #endif /* __ASSEMBLY__ */
 
 #endif /* _UAPI__ASM_PTRACE_H */
diff --git a/arch/arm64/kernel/ptrace.c b/arch/arm64/kernel/ptrace.c
index 71d99af24ef2..f395649f755e 100644
--- a/arch/arm64/kernel/ptrace.c
+++ b/arch/arm64/kernel/ptrace.c
@@ -44,6 +44,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -951,6 +952,30 @@ static int sve_set(struct task_struct *target,
 
 #endif /* CONFIG_ARM64_SVE */
 
+#ifdef CONFIG_ARM64_PTR_AUTH
+static int pac_mask_get(struct task_struct *target,
+   const struct user_regset *regset,
+   unsigned int pos, unsigned int count,
+   void *kbuf, void __user *ubuf)
+{
+   /*
+* The PAC bits can differ across data and instruction pointers
+* depending on TCR_EL1.TBID*, which we may make use of in future, so
+* we expose separate masks.
+*/
+   unsigned long mask = ptrauth_pac_mask();
+   struct user_pac_mask uregs = {
+   .data_mask = mask,
+   .insn_mask = mask,
+   };
+
+   if (!cpus_have_cap(ARM64_HAS_ADDRESS_AUTH))
+   return -EINVAL;
+
+   return user_regset_copyout(, , , , , 0, -1);
+}
+#endif /* CONFIG_ARM64_PTR_AUTH */
+
 enum aarch64_regset {
REGSET_GPR,
REGSET_FPR,
@@ -963,6 +988,9 @@ enum aarch64_regset {
 #ifdef CONFIG_ARM64_SVE
REGSET_SVE,
 #endif
+#ifdef CONFIG_ARM64_PTR_AUTH
+   REGSET_PAC_MASK,
+#endif
 };
 
 static const struct user_regset aarch64_regsets[] = {
@@ -1032,6 +1060,16 @@ static const struct user_regset aarch64_regsets[] = {
.get_size = sve_get_size,
},
 #endif
+#ifdef CONFIG_ARM64_PTR_AUTH
+   [REGSET_PAC_MASK] = {
+   .core_note_type = NT_ARM_PAC_MASK,
+   .n = sizeof(struct user_pac_mask) / sizeof(u64),
+   .size = sizeof(u64),
+   .align = sizeof(u64),
+   .get = pac_mask_get,
+   /* this cannot be set dynamically */
+   },
+#endif
 };
 
 static const struct user_regset_view user_aarch64_view = {
diff --git a/include/uapi/linux/elf.h b/include/uapi/linux/elf.h
index e2535d6dcec7..070c28121979 100644
--- a/include/uapi/linux/elf.h
+++ b/include/ua

[PATCHv3 07/11] arm64: add basic pointer authentication support

2018-04-17 Thread Mark Rutland
This patch adds basic support for pointer authentication, allowing
userspace to make use of APIAKey. The kernel maintains an APIAKey value
for each process (shared by all threads within), which is initialised to
a random value at exec() time.

To describe that address authentication instructions are available, the
ID_AA64ISAR0.{APA,API} fields are exposed to userspace. A new hwcap,
APIA, is added to describe that the kernel manages APIAKey.

Instructions using other keys (APIBKey, APDAKey, APDBKey) are disabled,
and will behave as NOPs. These may be made use of in future patches.

No support is added for the generic key (APGAKey), though this cannot be
trapped or made to behave as a NOP. Its presence is not advertised with
a hwcap.

Signed-off-by: Mark Rutland <mark.rutl...@arm.com>
Cc: Catalin Marinas <catalin.mari...@arm.com>
Cc: Ramana Radhakrishnan <ramana.radhakrish...@arm.com>
Cc: Suzuki K Poulose <suzuki.poul...@arm.com>
Cc: Will Deacon <will.dea...@arm.com>
---
 arch/arm64/include/asm/mmu.h  |  5 ++
 arch/arm64/include/asm/mmu_context.h  | 25 +-
 arch/arm64/include/asm/pointer_auth.h | 89 +++
 arch/arm64/include/uapi/asm/hwcap.h   |  1 +
 arch/arm64/kernel/cpufeature.c|  9 
 arch/arm64/kernel/cpuinfo.c   |  1 +
 6 files changed, 128 insertions(+), 2 deletions(-)
 create mode 100644 arch/arm64/include/asm/pointer_auth.h

diff --git a/arch/arm64/include/asm/mmu.h b/arch/arm64/include/asm/mmu.h
index dd320df0d026..f6480ea7b0d5 100644
--- a/arch/arm64/include/asm/mmu.h
+++ b/arch/arm64/include/asm/mmu.h
@@ -25,10 +25,15 @@
 
 #ifndef __ASSEMBLY__
 
+#include 
+
 typedef struct {
atomic64_t  id;
void*vdso;
unsigned long   flags;
+#ifdef CONFIG_ARM64_PTR_AUTH
+   struct ptrauth_keys ptrauth_keys;
+#endif
 } mm_context_t;
 
 /*
diff --git a/arch/arm64/include/asm/mmu_context.h 
b/arch/arm64/include/asm/mmu_context.h
index 39ec0b8a689e..caf0d3010112 100644
--- a/arch/arm64/include/asm/mmu_context.h
+++ b/arch/arm64/include/asm/mmu_context.h
@@ -29,7 +29,6 @@
 #include 
 #include 
 #include 
-#include 
 #include 
 #include 
 #include 
@@ -168,7 +167,14 @@ static inline void cpu_replace_ttbr1(pgd_t *pgdp)
 #define destroy_context(mm)do { } while(0)
 void check_and_switch_context(struct mm_struct *mm, unsigned int cpu);
 
-#define init_new_context(tsk,mm)   ({ atomic64_set(&(mm)->context.id, 0); 
0; })
+static inline int init_new_context(struct task_struct *tsk,
+   struct mm_struct *mm)
+{
+   atomic64_set(>context.id, 0);
+   mm_ctx_ptrauth_init(>context);
+
+   return 0;
+}
 
 #ifdef CONFIG_ARM64_SW_TTBR0_PAN
 static inline void update_saved_ttbr0(struct task_struct *tsk,
@@ -216,6 +222,8 @@ static inline void __switch_mm(struct mm_struct *next)
return;
}
 
+   mm_ctx_ptrauth_switch(>context);
+
check_and_switch_context(next, cpu);
 }
 
@@ -241,6 +249,19 @@ switch_mm(struct mm_struct *prev, struct mm_struct *next,
 void verify_cpu_asid_bits(void);
 void post_ttbr_update_workaround(void);
 
+static inline void arch_dup_mmap(struct mm_struct *oldmm,
+struct mm_struct *mm)
+{
+   mm_ctx_ptrauth_dup(>context, >context);
+}
+#define arch_dup_mmap arch_dup_mmap
+
+/*
+ * We need to override arch_dup_mmap before including the generic hooks, which
+ * are otherwise sufficient for us.
+ */
+#include 
+
 #endif /* !__ASSEMBLY__ */
 
 #endif /* !__ASM_MMU_CONTEXT_H */
diff --git a/arch/arm64/include/asm/pointer_auth.h 
b/arch/arm64/include/asm/pointer_auth.h
new file mode 100644
index ..a2e8fb91fdee
--- /dev/null
+++ b/arch/arm64/include/asm/pointer_auth.h
@@ -0,0 +1,89 @@
+/*
+ * Copyright (C) 2016 ARM Ltd.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+#ifndef __ASM_POINTER_AUTH_H
+#define __ASM_POINTER_AUTH_H
+
+#include 
+
+#include 
+#include 
+
+#ifdef CONFIG_ARM64_PTR_AUTH
+/*
+ * Each key is a 128-bit quantity which is split accross a pair of 64-bit
+ * registers (Lo and Hi).
+ */
+struct ptrauth_key {
+   unsigned long lo, hi;
+};
+
+/*
+ * We give each process its own instruction A key (APIAKey), which is shared by
+ * all threads. This is inherited upon fork(), and reinitialised upon exec*().
+ * All other keys are currently unused, with APIBKey, APDAKey, a

[PATCHv3 06/11] asm-generic: mm_hooks: allow hooks to be overridden individually

2018-04-17 Thread Mark Rutland
Currently, an architecture must either implement all of the mm hooks
itself, or use all of those provided by the asm-generic implementation.
When an architecture only needs to override a single hook, it must copy
the stub implementations from the asm-generic version.

To avoid this repetition, allow each hook to be overridden indiviually,
by placing each under an #ifndef block. As architectures providing their
own hooks can't include this file today, this shouldn't adversely affect
any existing hooks.

Signed-off-by: Mark Rutland <mark.rutl...@arm.com>
Cc: Arnd Bergmann <a...@arndb.de>
Cc: linux-a...@vger.kernel.org
---
 include/asm-generic/mm_hooks.h | 11 +++
 1 file changed, 11 insertions(+)

diff --git a/include/asm-generic/mm_hooks.h b/include/asm-generic/mm_hooks.h
index 8ac4e68a12f0..2b3ee15d3702 100644
--- a/include/asm-generic/mm_hooks.h
+++ b/include/asm-generic/mm_hooks.h
@@ -7,31 +7,42 @@
 #ifndef _ASM_GENERIC_MM_HOOKS_H
 #define _ASM_GENERIC_MM_HOOKS_H
 
+#ifndef arch_dup_mmap
 static inline int arch_dup_mmap(struct mm_struct *oldmm,
struct mm_struct *mm)
 {
return 0;
 }
+#endif
 
+#ifndef arch_exit_mmap
 static inline void arch_exit_mmap(struct mm_struct *mm)
 {
 }
+#endif
 
+#ifndef arch_unmap
 static inline void arch_unmap(struct mm_struct *mm,
struct vm_area_struct *vma,
unsigned long start, unsigned long end)
 {
 }
+#endif
 
+#ifndef arch_bprm_mm_init
 static inline void arch_bprm_mm_init(struct mm_struct *mm,
 struct vm_area_struct *vma)
 {
 }
+#endif
 
+#ifndef arch_vma_access_permitted
 static inline bool arch_vma_access_permitted(struct vm_area_struct *vma,
bool write, bool execute, bool foreign)
 {
/* by default, allow everything */
return true;
 }
+#endif
+
 #endif /* _ASM_GENERIC_MM_HOOKS_H */
-- 
2.11.0

___
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm


[PATCHv3 05/11] arm64/cpufeature: detect pointer authentication

2018-04-17 Thread Mark Rutland
So that we can dynamically handle the presence of pointer authentication
functionality, wire up probing code in cpufeature.c.

>From ARMv8.3 onwards, ID_AA64ISAR1 is no longer entirely RES0, and now
has four fields describing the presence of pointer authentication
functionality:

* APA - address authentication present, using an architected algorithm
* API - address authentication present, using an IMP DEF algorithm
* GPA - generic authentication present, using an architected algorithm
* GPI - generic authentication present, using an IMP DEF algorithm

For the moment we only care about address authentication, so we only
need to check APA and API. It is assumed that if all CPUs support an IMP
DEF algorithm, the same algorithm is used across all CPUs.

Note that when we implement KVM support, we will also need to ensure
that CPUs have uniform support for GPA and GPI.

Signed-off-by: Mark Rutland <mark.rutl...@arm.com>
Cc: Catalin Marinas <catalin.mari...@arm.com>
Cc: Suzuki K Poulose <suzuki.poul...@arm.com>
Cc: Will Deacon <will.dea...@arm.com>
---
 arch/arm64/include/asm/cpucaps.h |  5 -
 arch/arm64/kernel/cpufeature.c   | 47 
 2 files changed, 51 insertions(+), 1 deletion(-)

diff --git a/arch/arm64/include/asm/cpucaps.h b/arch/arm64/include/asm/cpucaps.h
index bc51b72fafd4..9dcb4d1b14f5 100644
--- a/arch/arm64/include/asm/cpucaps.h
+++ b/arch/arm64/include/asm/cpucaps.h
@@ -48,7 +48,10 @@
 #define ARM64_HAS_CACHE_IDC27
 #define ARM64_HAS_CACHE_DIC28
 #define ARM64_HW_DBM   29
+#define ARM64_HAS_ADDRESS_AUTH_ARCH30
+#define ARM64_HAS_ADDRESS_AUTH_IMP_DEF 31
+#define ARM64_HAS_ADDRESS_AUTH 32
 
-#define ARM64_NCAPS30
+#define ARM64_NCAPS33
 
 #endif /* __ASM_CPUCAPS_H */
diff --git a/arch/arm64/kernel/cpufeature.c b/arch/arm64/kernel/cpufeature.c
index 536d572e5596..01b1a7e7d70f 100644
--- a/arch/arm64/kernel/cpufeature.c
+++ b/arch/arm64/kernel/cpufeature.c
@@ -142,6 +142,10 @@ static const struct arm64_ftr_bits ftr_id_aa64isar1[] = {
ARM64_FTR_BITS(FTR_VISIBLE, FTR_STRICT, FTR_LOWER_SAFE, 
ID_AA64ISAR1_LRCPC_SHIFT, 4, 0),
ARM64_FTR_BITS(FTR_VISIBLE, FTR_STRICT, FTR_LOWER_SAFE, 
ID_AA64ISAR1_FCMA_SHIFT, 4, 0),
ARM64_FTR_BITS(FTR_VISIBLE, FTR_STRICT, FTR_LOWER_SAFE, 
ID_AA64ISAR1_JSCVT_SHIFT, 4, 0),
+   ARM64_FTR_BITS(FTR_VISIBLE_IF_IS_ENABLED(CONFIG_ARM64_PTR_AUTH),
+  FTR_STRICT, FTR_LOWER_SAFE, ID_AA64ISAR1_API_SHIFT, 4, 
0),
+   ARM64_FTR_BITS(FTR_VISIBLE_IF_IS_ENABLED(CONFIG_ARM64_PTR_AUTH),
+  FTR_STRICT, FTR_LOWER_SAFE, ID_AA64ISAR1_APA_SHIFT, 4, 
0),
ARM64_FTR_BITS(FTR_VISIBLE, FTR_STRICT, FTR_LOWER_SAFE, 
ID_AA64ISAR1_DPB_SHIFT, 4, 0),
ARM64_FTR_END,
 };
@@ -1025,6 +1029,22 @@ static void cpu_copy_el2regs(const struct 
arm64_cpu_capabilities *__unused)
 }
 #endif
 
+#ifdef CONFIG_ARM64_PTR_AUTH
+static bool has_address_auth(const struct arm64_cpu_capabilities *entry,
+int __unused)
+{
+   u64 isar1 = read_sanitised_ftr_reg(SYS_ID_AA64ISAR1_EL1);
+   bool api, apa;
+
+   apa = cpuid_feature_extract_unsigned_field(isar1,
+   ID_AA64ISAR1_APA_SHIFT) > 0;
+   api = cpuid_feature_extract_unsigned_field(isar1,
+   ID_AA64ISAR1_API_SHIFT) > 0;
+
+   return apa || api;
+}
+#endif /* CONFIG_ARM64_PTR_AUTH */
+
 static const struct arm64_cpu_capabilities arm64_features[] = {
{
.desc = "GIC system register CPU interface",
@@ -1201,6 +1221,33 @@ static const struct arm64_cpu_capabilities 
arm64_features[] = {
.cpu_enable = cpu_enable_hw_dbm,
},
 #endif
+#ifdef CONFIG_ARM64_PTR_AUTH
+   {
+   .desc = "Address authentication (architected algorithm)",
+   .capability = ARM64_HAS_ADDRESS_AUTH_ARCH,
+   .type = ARM64_CPUCAP_SYSTEM_FEATURE,
+   .sys_reg = SYS_ID_AA64ISAR1_EL1,
+   .sign = FTR_UNSIGNED,
+   .field_pos = ID_AA64ISAR1_APA_SHIFT,
+   .min_field_value = ID_AA64ISAR1_APA_ARCHITECTED,
+   .matches = has_cpuid_feature,
+   },
+   {
+   .desc = "Address authentication (IMP DEF algorithm)",
+   .capability = ARM64_HAS_ADDRESS_AUTH_IMP_DEF,
+   .type = ARM64_CPUCAP_SYSTEM_FEATURE,
+   .sys_reg = SYS_ID_AA64ISAR1_EL1,
+   .sign = FTR_UNSIGNED,
+   .field_pos = ID_AA64ISAR1_API_SHIFT,
+   .min_field_value = ID_AA64ISAR1_API_IMP_DEF,
+   .matches = has_cpuid_feature,
+   },
+   {
+   .capability = ARM64_HAS_ADDRESS_AUTH,
+   .type = ARM64_CPUCAP_SYSTEM_FEATURE,

[PATCHv3 04/11] arm64: Don't trap host pointer auth use to EL2

2018-04-17 Thread Mark Rutland
To allow EL0 (and/or EL1) to use pointer authentication functionality,
we must ensure that pointer authentication instructions and accesses to
pointer authentication keys are not trapped to EL2.

This patch ensures that HCR_EL2 is configured appropriately when the
kernel is booted at EL2. For non-VHE kernels we set HCR_EL2.{API,APK},
ensuring that EL1 can access keys and permit EL0 use of instructions.
For VHE kernels host EL0 (TGE && E2H) is unaffected by these settings,
and it doesn't matter how we configure HCR_EL2.{API,APK}, so we don't
bother setting them.

This does not enable support for KVM guests, since KVM manages HCR_EL2
itself when running VMs.

Signed-off-by: Mark Rutland <mark.rutl...@arm.com>
Cc: Christoffer Dall <cd...@kernel.org>
Cc: Catalin Marinas <catalin.mari...@arm.com>
Cc: Marc Zyngier <marc.zyng...@arm.com>
Cc: Will Deacon <will.dea...@arm.com>
Cc: kvmarm@lists.cs.columbia.edu
---
 arch/arm64/include/asm/kvm_arm.h | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/arch/arm64/include/asm/kvm_arm.h b/arch/arm64/include/asm/kvm_arm.h
index 89b3dda7e3cb..4d57e1e58323 100644
--- a/arch/arm64/include/asm/kvm_arm.h
+++ b/arch/arm64/include/asm/kvm_arm.h
@@ -23,6 +23,8 @@
 #include 
 
 /* Hyp Configuration Register (HCR) bits */
+#define HCR_API(UL(1) << 41)
+#define HCR_APK(UL(1) << 40)
 #define HCR_TEA(UL(1) << 37)
 #define HCR_TERR   (UL(1) << 36)
 #define HCR_TLOR   (UL(1) << 35)
@@ -86,7 +88,7 @@
 HCR_AMO | HCR_SWIO | HCR_TIDCP | HCR_RW | HCR_TLOR | \
 HCR_FMO | HCR_IMO)
 #define HCR_VIRT_EXCP_MASK (HCR_VSE | HCR_VI | HCR_VF)
-#define HCR_HOST_NVHE_FLAGS (HCR_RW)
+#define HCR_HOST_NVHE_FLAGS (HCR_RW | HCR_API | HCR_APK)
 #define HCR_HOST_VHE_FLAGS (HCR_RW | HCR_TGE | HCR_E2H)
 
 /* TCR_EL2 Registers bits */
-- 
2.11.0

___
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm


[PATCHv3 03/11] arm64/kvm: hide ptrauth from guests

2018-04-17 Thread Mark Rutland
In subsequent patches we're going to expose ptrauth to the host kernel
and userspace, but things are a bit trickier for guest kernels. For the
time being, let's hide ptrauth from KVM guests.

Regardless of how well-behaved the guest kernel is, guest userspace
could attempt to use ptrauth instructions, triggering a trap to EL2,
resulting in noise from kvm_handle_unknown_ec(). So let's write up a
handler for the PAC trap, which silently injects an UNDEF into the
guest, as if the feature were really missing.

Signed-off-by: Mark Rutland <mark.rutl...@arm.com>
Cc: Christoffer Dall <cd...@kernel.org>
Cc: Marc Zyngier <marc.zyng...@arm.com>
Cc: kvmarm@lists.cs.columbia.edu
---
 arch/arm64/kvm/handle_exit.c | 18 ++
 arch/arm64/kvm/sys_regs.c|  9 +
 2 files changed, 27 insertions(+)

diff --git a/arch/arm64/kvm/handle_exit.c b/arch/arm64/kvm/handle_exit.c
index e5e741bfffe1..5114ad691eae 100644
--- a/arch/arm64/kvm/handle_exit.c
+++ b/arch/arm64/kvm/handle_exit.c
@@ -173,6 +173,23 @@ static int handle_sve(struct kvm_vcpu *vcpu, struct 
kvm_run *run)
return 1;
 }
 
+/*
+ * Guest usage of a ptrauth instruction (which the guest EL1 did not turn into
+ * a NOP), or guest EL1 access to a ptrauth register.
+ */
+static int kvm_handle_ptrauth(struct kvm_vcpu *vcpu, struct kvm_run *run)
+{
+   /*
+* We don't currently suport ptrauth in a guest, and we mask the ID
+* registers to prevent well-behaved guests from trying to make use of
+* it.
+*
+* Inject an UNDEF, as if the feature really isn't present.
+*/
+   kvm_inject_undefined(vcpu);
+   return 1;
+}
+
 static exit_handle_fn arm_exit_handlers[] = {
[0 ... ESR_ELx_EC_MAX]  = kvm_handle_unknown_ec,
[ESR_ELx_EC_WFx]= kvm_handle_wfx,
@@ -195,6 +212,7 @@ static exit_handle_fn arm_exit_handlers[] = {
[ESR_ELx_EC_BKPT32] = kvm_handle_guest_debug,
[ESR_ELx_EC_BRK64]  = kvm_handle_guest_debug,
[ESR_ELx_EC_FP_ASIMD]   = handle_no_fpsimd,
+   [ESR_ELx_EC_PAC]= kvm_handle_ptrauth,
 };
 
 static exit_handle_fn kvm_get_exit_handler(struct kvm_vcpu *vcpu)
diff --git a/arch/arm64/kvm/sys_regs.c b/arch/arm64/kvm/sys_regs.c
index 806b0b126a64..eee399c35e84 100644
--- a/arch/arm64/kvm/sys_regs.c
+++ b/arch/arm64/kvm/sys_regs.c
@@ -1000,6 +1000,15 @@ static u64 read_id_reg(struct sys_reg_desc const *r, 
bool raz)
task_pid_nr(current));
 
val &= ~(0xfUL << ID_AA64PFR0_SVE_SHIFT);
+   } else if (id == SYS_ID_AA64ISAR1_EL1) {
+   const u64 ptrauth_mask = (0xfUL << ID_AA64ISAR1_APA_SHIFT) |
+(0xfUL << ID_AA64ISAR1_API_SHIFT) |
+(0xfUL << ID_AA64ISAR1_GPA_SHIFT) |
+(0xfUL << ID_AA64ISAR1_GPI_SHIFT);
+   if (val & ptrauth_mask)
+   pr_err_once("kvm [%i]: ptrauth unsupported for guests, 
suppressing\n",
+   task_pid_nr(current));
+   val &= ~ptrauth_mask;
} else if (id == SYS_ID_AA64MMFR1_EL1) {
if (val & (0xfUL << ID_AA64MMFR1_LOR_SHIFT))
pr_err_once("kvm [%i]: LORegions unsupported for 
guests, suppressing\n",
-- 
2.11.0

___
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm


[PATCHv3 02/11] arm64/kvm: consistently handle host HCR_EL2 flags

2018-04-17 Thread Mark Rutland
In KVM we define the configuration of HCR_EL2 for a VHE HOST in
HCR_HOST_VHE_FLAGS, but we don't ahve a similar definition for the
non-VHE host flags, and open-code HCR_RW. Further, in head.S we
open-code the flags for VHE and non-VHE configurations.

In future, we're going to want to configure more flags for the host, so
lets add a HCR_HOST_NVHE_FLAGS defintion, adn consistently use both
HCR_HOST_VHE_FLAGS and HCR_HOST_NVHE_FLAGS in the kvm code and head.S.

We now use mov_q to generate the HCR_EL2 value, as we use when
configuring other registers in head.S.

Signed-off-by: Mark Rutland <mark.rutl...@arm.com>
Cc: Catalin Marinas <catalin.mari...@arm.com>
Cc: Christoffer Dall <cd...@kernel.org>
Cc: Marc Zyngier <marc.zyng...@arm.com>
Cc: Will Deacon <will.dea...@arm.com>
Cc: kvmarm@lists.cs.columbia.edu
---
 arch/arm64/include/asm/kvm_arm.h | 1 +
 arch/arm64/kernel/head.S | 5 ++---
 arch/arm64/kvm/hyp/switch.c  | 2 +-
 3 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/arch/arm64/include/asm/kvm_arm.h b/arch/arm64/include/asm/kvm_arm.h
index 6dd285e979c9..89b3dda7e3cb 100644
--- a/arch/arm64/include/asm/kvm_arm.h
+++ b/arch/arm64/include/asm/kvm_arm.h
@@ -86,6 +86,7 @@
 HCR_AMO | HCR_SWIO | HCR_TIDCP | HCR_RW | HCR_TLOR | \
 HCR_FMO | HCR_IMO)
 #define HCR_VIRT_EXCP_MASK (HCR_VSE | HCR_VI | HCR_VF)
+#define HCR_HOST_NVHE_FLAGS (HCR_RW)
 #define HCR_HOST_VHE_FLAGS (HCR_RW | HCR_TGE | HCR_E2H)
 
 /* TCR_EL2 Registers bits */
diff --git a/arch/arm64/kernel/head.S b/arch/arm64/kernel/head.S
index b0853069702f..651a06b1980f 100644
--- a/arch/arm64/kernel/head.S
+++ b/arch/arm64/kernel/head.S
@@ -494,10 +494,9 @@ ENTRY(el2_setup)
 #endif
 
/* Hyp configuration. */
-   mov x0, #HCR_RW // 64-bit EL1
+   mov_q   x0, HCR_HOST_NVHE_FLAGS
cbz x2, set_hcr
-   orr x0, x0, #HCR_TGE// Enable Host Extensions
-   orr x0, x0, #HCR_E2H
+   mov_q   x0, HCR_HOST_VHE_FLAGS
 set_hcr:
msr hcr_el2, x0
isb
diff --git a/arch/arm64/kvm/hyp/switch.c b/arch/arm64/kvm/hyp/switch.c
index d9645236e474..cdae330e15e9 100644
--- a/arch/arm64/kvm/hyp/switch.c
+++ b/arch/arm64/kvm/hyp/switch.c
@@ -143,7 +143,7 @@ static void __hyp_text __deactivate_traps_nvhe(void)
mdcr_el2 |= MDCR_EL2_E2PB_MASK << MDCR_EL2_E2PB_SHIFT;
 
write_sysreg(mdcr_el2, mdcr_el2);
-   write_sysreg(HCR_RW, hcr_el2);
+   write_sysreg(HCR_HOST_NVHE_FLAGS, hcr_el2);
write_sysreg(CPTR_EL2_DEFAULT, cptr_el2);
 }
 
-- 
2.11.0

___
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm


[PATCHv3 01/11] arm64: add pointer authentication register bits

2018-04-17 Thread Mark Rutland
The ARMv8.3 pointer authentication extension adds:

* New fields in ID_AA64ISAR1 to report the presence of pointer
  authentication functionality.

* New control bits in SCTLR_ELx to enable this functionality.

* New system registers to hold the keys necessary for this
  functionality.

* A new ESR_ELx.EC code used when the new instructions are affected by
  configurable traps

This patch adds the relevant definitions to  and
 for these, to be used by subsequent patches.

Signed-off-by: Mark Rutland <mark.rutl...@arm.com>
Cc: Catalin Marinas <catalin.mari...@arm.com>
Cc: Marc Zyngier <marc.zyng...@arm.com>
Cc: Suzuki K Poulose <suzuki.poul...@arm.com>
Cc: Will Deacon <will.dea...@arm.com>
---
 arch/arm64/include/asm/esr.h|  3 ++-
 arch/arm64/include/asm/sysreg.h | 30 ++
 2 files changed, 32 insertions(+), 1 deletion(-)

diff --git a/arch/arm64/include/asm/esr.h b/arch/arm64/include/asm/esr.h
index ce70c3ffb993..022785162281 100644
--- a/arch/arm64/include/asm/esr.h
+++ b/arch/arm64/include/asm/esr.h
@@ -30,7 +30,8 @@
 #define ESR_ELx_EC_CP14_LS (0x06)
 #define ESR_ELx_EC_FP_ASIMD(0x07)
 #define ESR_ELx_EC_CP10_ID (0x08)
-/* Unallocated EC: 0x09 - 0x0B */
+#define ESR_ELx_EC_PAC (0x09)
+/* Unallocated EC: 0x0A - 0x0B */
 #define ESR_ELx_EC_CP14_64 (0x0C)
 /* Unallocated EC: 0x0d */
 #define ESR_ELx_EC_ILL (0x0E)
diff --git a/arch/arm64/include/asm/sysreg.h b/arch/arm64/include/asm/sysreg.h
index 6171178075dc..426f0eb90101 100644
--- a/arch/arm64/include/asm/sysreg.h
+++ b/arch/arm64/include/asm/sysreg.h
@@ -171,6 +171,19 @@
 #define SYS_TTBR1_EL1  sys_reg(3, 0, 2, 0, 1)
 #define SYS_TCR_EL1sys_reg(3, 0, 2, 0, 2)
 
+#define SYS_APIAKEYLO_EL1  sys_reg(3, 0, 2, 1, 0)
+#define SYS_APIAKEYHI_EL1  sys_reg(3, 0, 2, 1, 1)
+#define SYS_APIBKEYLO_EL1  sys_reg(3, 0, 2, 1, 2)
+#define SYS_APIBKEYHI_EL1  sys_reg(3, 0, 2, 1, 3)
+
+#define SYS_APDAKEYLO_EL1  sys_reg(3, 0, 2, 2, 0)
+#define SYS_APDAKEYHI_EL1  sys_reg(3, 0, 2, 2, 1)
+#define SYS_APDBKEYLO_EL1  sys_reg(3, 0, 2, 2, 2)
+#define SYS_APDBKEYHI_EL1  sys_reg(3, 0, 2, 2, 3)
+
+#define SYS_APGAKEYLO_EL1  sys_reg(3, 0, 2, 3, 0)
+#define SYS_APGAKEYHI_EL1  sys_reg(3, 0, 2, 3, 1)
+
 #define SYS_ICC_PMR_EL1sys_reg(3, 0, 4, 6, 0)
 
 #define SYS_AFSR0_EL1  sys_reg(3, 0, 5, 1, 0)
@@ -417,9 +430,13 @@
 #define SYS_ICH_LR15_EL2   __SYS__LR8_EL2(7)
 
 /* Common SCTLR_ELx flags. */
+#define SCTLR_ELx_ENIA (1 << 31)
+#define SCTLR_ELx_ENIB (1 << 30)
+#define SCTLR_ELx_ENDA (1 << 27)
 #define SCTLR_ELx_EE(1 << 25)
 #define SCTLR_ELx_IESB (1 << 21)
 #define SCTLR_ELx_WXN  (1 << 19)
+#define SCTLR_ELx_ENDB (1 << 13)
 #define SCTLR_ELx_I(1 << 12)
 #define SCTLR_ELx_SA   (1 << 3)
 #define SCTLR_ELx_C(1 << 2)
@@ -510,11 +527,24 @@
 #define ID_AA64ISAR0_AES_SHIFT 4
 
 /* id_aa64isar1 */
+#define ID_AA64ISAR1_GPI_SHIFT 28
+#define ID_AA64ISAR1_GPA_SHIFT 24
 #define ID_AA64ISAR1_LRCPC_SHIFT   20
 #define ID_AA64ISAR1_FCMA_SHIFT16
 #define ID_AA64ISAR1_JSCVT_SHIFT   12
+#define ID_AA64ISAR1_API_SHIFT 8
+#define ID_AA64ISAR1_APA_SHIFT 4
 #define ID_AA64ISAR1_DPB_SHIFT 0
 
+#define ID_AA64ISAR1_APA_NI0x0
+#define ID_AA64ISAR1_APA_ARCHITECTED   0x1
+#define ID_AA64ISAR1_API_NI0x0
+#define ID_AA64ISAR1_API_IMP_DEF   0x1
+#define ID_AA64ISAR1_GPA_NI0x0
+#define ID_AA64ISAR1_GPA_ARCHITECTED   0x1
+#define ID_AA64ISAR1_GPI_NI0x0
+#define ID_AA64ISAR1_GPI_IMP_DEF   0x1
+
 /* id_aa64pfr0 */
 #define ID_AA64PFR0_CSV3_SHIFT 60
 #define ID_AA64PFR0_CSV2_SHIFT 56
-- 
2.11.0

___
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm


[PATCHv3 00/11] ARMv8.3 pointer authentication userspace support

2018-04-17 Thread Mark Rutland
This series adds support for the ARMv8.3 pointer authentication extension,
enabling userspace return address protection with recent versions of GCC.

Since RFC [1]:
* Make the KVM context switch (semi-lazy)
* Rebase to v4.13-rc1
* Improve pointer authentication documentation
* Add hwcap documentation
* Various minor cleanups

Since v1 [2]:
* Rebase to v4.15-rc1
* Settle on per-process keys
* Strip PACs when unwinding userspace
* Don't expose an XPAC hwcap (this is implied by ID registers)
* Leave APIB, ABPDA, APDB, and APGA keys unsupported for now
* Support IMP DEF algorithms
* Rely on KVM ID register emulation
* Various cleanups

Since v2 [3]:
* Unify HCR_EL2 initialization
* s/POINTER_AUTHENTICATION/PTR_AUTH/
* Drop KVM support (for now)
* Drop detection of generic authentication

While there are use-cases for keys other than APIAKey, the only software that
I'm aware of with pointer authentication support is GCC, which only makes use
of APIAKey. I'm happy to add support for other keys as users appear.

I've pushed the series to the arm64/pointer-auth branch [4] of my linux tree.
I've also pushed out a necessary bootwrapper patch to the pointer-auth branch
[5] of my bootwrapper repo.


Extension Overview 
==

The ARMv8.3 pointer authentication extension adds functionality to detect
modification of pointer values, mitigating certain classes of attack such as
stack smashing, and making return oriented programming attacks harder

The extension introduces the concept of a pointer authentication code (PAC),
which is stored in some upper bits of pointers. Each PAC is derived from the
original pointer, another 64-bit value (e.g. the stack pointer), and a secret
128-bit key.

New instructions are added which can be used to:

* Insert a PAC into a pointer
* Strip a PAC from a pointer
* Authenticate strip a PAC from a pointer

If authentication succeeds, the code is removed, yielding the original pointer.
If authentication fails, bits are set in the pointer such that it is guaranteed
to cause a fault if used.

These instructions can make use of four keys:

* APIAKey (A.K.A. Instruction A key)
* APIBKey (A.K.A. Instruction B key)
* APDAKey (A.K.A. Data A key)
* APDBKey (A.K.A. Data B Key)

A subset of these instruction encodings have been allocated from the HINT
space, and will operate as NOPs on any ARMv8-A parts which do not feature the
extension (or if purposefully disabled by the kernel). Software using only this
subset of the instructions should function correctly on all ARMv8-A parts.

Additionally, instructions are added to authenticate small blocks of memory in
similar fashion, using APGAKey (A.K.A. Generic key).


This Series
===

This series enables the use of instructions using APIAKey, which is initialised
and maintained per-process (shared by all threads). This series does not add
support for APIBKey, APDAKey, APDBKey, nor APGAKey.

I've given this some basic testing with a homebrew test suite. More ideally,
we'd add some tests to the kernel source tree.

For the time being, pointer authentication functionality is hidden from
guests via ID register trapping.

Thanks,
Mark.

[1] http://lists.infradead.org/pipermail/linux-arm-kernel/2017-April/498941.html
[2] 
https://lkml.kernel.org/r/1500480092-28480-1-git-send-email-mark.rutl...@arm.com
[3] https://lkml.kernel.org/r/20171127163806.31435-1-mark.rutl...@arm.com
[4] git://git.kernel.org/pub/scm/linux/kernel/git/mark/linux.git 
arm64/pointer-auth
[5] git://git.kernel.org/pub/scm/linux/kernel/git/mark/boot-wrapper-aarch64.git 
pointer-auth


Mark Rutland (11):
  arm64: add pointer authentication register bits
  arm64/kvm: consistently handle host HCR_EL2 flags
  arm64/kvm: hide ptrauth from guests
  arm64: Don't trap host pointer auth use to EL2
  arm64/cpufeature: detect pointer authentication
  asm-generic: mm_hooks: allow hooks to be overridden individually
  arm64: add basic pointer authentication support
  arm64: expose user PAC bit positions via ptrace
  arm64: perf: strip PAC when unwinding userspace
  arm64: enable pointer authentication
  arm64: docs: document pointer authentication

 Documentation/arm64/booting.txt|   8 ++
 Documentation/arm64/elf_hwcaps.txt |   6 ++
 Documentation/arm64/pointer-authentication.txt |  84 
 arch/arm64/Kconfig |  23 ++
 arch/arm64/include/asm/cpucaps.h   |   5 +-
 arch/arm64/include/asm/esr.h   |   3 +-
 arch/arm64/include/asm/kvm_arm.h   |   3 +
 arch/arm64/include/asm/mmu.h   |   5 ++
 arch/arm64/include/asm/mmu_context.h   |  25 +-
 arch/arm64/include/asm/pointer_auth.h  | 104 +
 arch/arm64/include/asm/sysreg.h|  30 +++
 arch/arm64/include/uapi/asm/hwcap.h|   1 +
 arch/arm64/include/uapi/asm/ptrace.h   |   7 ++
 arch/arm64/kernel/cpufeature.c |  56

Re: [PATCH] KVM: arm/arm64: Close VMID generation race

2018-04-10 Thread Mark Rutland
On Tue, Apr 10, 2018 at 05:05:40PM +0200, Christoffer Dall wrote:
> On Tue, Apr 10, 2018 at 11:51:19AM +0100, Mark Rutland wrote:
> > I think we also need to update kvm->arch.vttbr before updating
> > kvm->arch.vmid_gen, otherwise another CPU can come in, see that the
> > vmid_gen is up-to-date, jump to hyp, and program a stale VTTBR (with the
> > old VMID).
> > 
> > With the smp_wmb() and update of kvm->arch.vmid_gen moved to the end of
> > the critical section, I think that works, modulo using READ_ONCE() and
> > WRITE_ONCE() to ensure single-copy-atomicity of the fields we access
> > locklessly.
> 
> Indeed, you're right.  I would look something like this, then:
> 
> diff --git a/virt/kvm/arm/arm.c b/virt/kvm/arm/arm.c
> index 2e43f9d42bd5..6cb08995e7ff 100644
> --- a/virt/kvm/arm/arm.c
> +++ b/virt/kvm/arm/arm.c
> @@ -450,7 +450,9 @@ void force_vm_exit(const cpumask_t *mask)
>   */
>  static bool need_new_vmid_gen(struct kvm *kvm)
>  {
> - return unlikely(kvm->arch.vmid_gen != atomic64_read(_vmid_gen));
> + u64 current_vmid_gen = atomic64_read(_vmid_gen);
> + smp_rmb(); /* Orders read of kvm_vmid_gen and kvm->arch.vmid */
> + return unlikely(READ_ONCE(kvm->arch.vmid_gen) != current_vmid_gen);
>  }
>  
>  /**
> @@ -500,7 +502,6 @@ static void update_vttbr(struct kvm *kvm)
>   kvm_call_hyp(__kvm_flush_vm_context);
>   }
>  
> - kvm->arch.vmid_gen = atomic64_read(_vmid_gen);
>   kvm->arch.vmid = kvm_next_vmid;
>   kvm_next_vmid++;
>   kvm_next_vmid &= (1 << kvm_vmid_bits) - 1;
> @@ -509,7 +510,10 @@ static void update_vttbr(struct kvm *kvm)
>   pgd_phys = virt_to_phys(kvm->arch.pgd);
>   BUG_ON(pgd_phys & ~VTTBR_BADDR_MASK);
>   vmid = ((u64)(kvm->arch.vmid) << VTTBR_VMID_SHIFT) & 
> VTTBR_VMID_MASK(kvm_vmid_bits);
> - kvm->arch.vttbr = pgd_phys | vmid;
> + WRITE_ONCE(kvm->arch.vttbr, pgd_phys | vmid);
> +
> + smp_wmb(); /* Ensure vttbr update is observed before vmid_gen update */
> + kvm->arch.vmid_gen = atomic64_read(_vmid_gen);
>  
>   spin_unlock(_vmid_lock);
>  }

I think that's right, yes.

We could replace the smp_{r,w}mb() barriers with an acquire of the
kvm_vmid_gen and a release of kvm->arch.vmid_gen, but if we're really
trying to optimize things there are larger algorithmic changes necessary
anyhow.

> It's probably easier to convince ourselves about the correctness of
> Marc's code using a rwlock instead, though.  Thoughts?

I believe that Marc's preference was the rwlock; I have no preference
either way.

Thanks,
Mark.
___
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm


Re: [PATCH] KVM: arm/arm64: Close VMID generation race

2018-04-10 Thread Mark Rutland
On Mon, Apr 09, 2018 at 10:51:39PM +0200, Christoffer Dall wrote:
> On Mon, Apr 09, 2018 at 06:07:06PM +0100, Marc Zyngier wrote:
> > Before entering the guest, we check whether our VMID is still
> > part of the current generation. In order to avoid taking a lock,
> > we start with checking that the generation is still current, and
> > only if not current do we take the lock, recheck, and update the
> > generation and VMID.
> > 
> > This leaves open a small race: A vcpu can bump up the global
> > generation number as well as the VM's, but has not updated
> > the VMID itself yet.
> > 
> > At that point another vcpu from the same VM comes in, checks
> > the generation (and finds it not needing anything), and jumps
> > into the guest. At this point, we end-up with two vcpus belonging
> > to the same VM running with two different VMIDs. Eventually, the
> > VMID used by the second vcpu will get reassigned, and things will
> > really go wrong...
> > 
> > A simple solution would be to drop this initial check, and always take
> > the lock. This is likely to cause performance issues. A middle ground
> > is to convert the spinlock to a rwlock, and only take the read lock
> > on the fast path. If the check fails at that point, drop it and
> > acquire the write lock, rechecking the condition.
> > 
> > This ensures that the above scenario doesn't occur.
> > 
> > Reported-by: Mark Rutland <mark.rutl...@arm.com>
> > Signed-off-by: Marc Zyngier <marc.zyng...@arm.com>
> > ---
> > I haven't seen any reply from Shannon, so reposting this to
> > a slightly wider audience for feedback.
> > 
> >  virt/kvm/arm/arm.c | 15 ++-
> >  1 file changed, 10 insertions(+), 5 deletions(-)
> > 
> > diff --git a/virt/kvm/arm/arm.c b/virt/kvm/arm/arm.c
> > index dba629c5f8ac..a4c1b76240df 100644
> > --- a/virt/kvm/arm/arm.c
> > +++ b/virt/kvm/arm/arm.c
> > @@ -63,7 +63,7 @@ static DEFINE_PER_CPU(struct kvm_vcpu *, 
> > kvm_arm_running_vcpu);
> >  static atomic64_t kvm_vmid_gen = ATOMIC64_INIT(1);
> >  static u32 kvm_next_vmid;
> >  static unsigned int kvm_vmid_bits __read_mostly;
> > -static DEFINE_SPINLOCK(kvm_vmid_lock);
> > +static DEFINE_RWLOCK(kvm_vmid_lock);
> >  
> >  static bool vgic_present;
> >  
> > @@ -473,11 +473,16 @@ static void update_vttbr(struct kvm *kvm)
> >  {
> > phys_addr_t pgd_phys;
> > u64 vmid;
> > +   bool new_gen;
> >  
> > -   if (!need_new_vmid_gen(kvm))
> > +   read_lock(_vmid_lock);
> > +   new_gen = need_new_vmid_gen(kvm);
> > +   read_unlock(_vmid_lock);
> > +
> > +   if (!new_gen)
> > return;
> >  
> > -   spin_lock(_vmid_lock);
> > +   write_lock(_vmid_lock);
> >  
> > /*
> >  * We need to re-check the vmid_gen here to ensure that if another vcpu
> > @@ -485,7 +490,7 @@ static void update_vttbr(struct kvm *kvm)
> >  * use the same vmid.
> >  */
> > if (!need_new_vmid_gen(kvm)) {
> > -   spin_unlock(_vmid_lock);
> > +   write_unlock(_vmid_lock);
> > return;
> > }
> >  
> > @@ -519,7 +524,7 @@ static void update_vttbr(struct kvm *kvm)
> > vmid = ((u64)(kvm->arch.vmid) << VTTBR_VMID_SHIFT) & 
> > VTTBR_VMID_MASK(kvm_vmid_bits);
> > kvm->arch.vttbr = kvm_phys_to_vttbr(pgd_phys) | vmid;
> >  
> > -   spin_unlock(_vmid_lock);
> > +   write_unlock(_vmid_lock);
> >  }
> >  
> >  static int kvm_vcpu_first_run_init(struct kvm_vcpu *vcpu)
> > -- 
> > 2.14.2
> > 
> 
> The above looks correct to me.  I am wondering if something like the
> following would also work, which may be slightly more efficient,
> although I doubt the difference can be measured:
> 
> diff --git a/virt/kvm/arm/arm.c b/virt/kvm/arm/arm.c
> index dba629c5f8ac..7ac869bcad21 100644
> --- a/virt/kvm/arm/arm.c
> +++ b/virt/kvm/arm/arm.c
> @@ -458,7 +458,9 @@ void force_vm_exit(const cpumask_t *mask)
>   */
>  static bool need_new_vmid_gen(struct kvm *kvm)
>  {
> - return unlikely(kvm->arch.vmid_gen != atomic64_read(_vmid_gen));
> + u64 current_vmid_gen = atomic64_read(_vmid_gen);
> + smp_rmb(); /* Orders read of kvm_vmid_gen and kvm->arch.vmid */
> + return unlikely(kvm->arch.vmid_gen != current_vmid_gen);
>  }
>  
>  /**
> @@ -508,10 +510,11 @@ static void update_vttbr(struct kvm *kvm)
>   kvm_call_hyp(__kvm_flush_vm_context);
>   }
>  
> - kvm->arch.vmid_gen = atomic64_read(_vmi

Re: [PATCHv2 09/12] arm64/kvm: preserve host HCR_EL2 value

2018-04-09 Thread Mark Rutland
On Tue, Feb 06, 2018 at 01:39:15PM +0100, Christoffer Dall wrote:
> On Mon, Nov 27, 2017 at 04:38:03PM +0000, Mark Rutland wrote:
> > diff --git a/arch/arm64/kvm/hyp/switch.c b/arch/arm64/kvm/hyp/switch.c
> > index 525c01f48867..2205f0be3ced 100644
> > --- a/arch/arm64/kvm/hyp/switch.c
> > +++ b/arch/arm64/kvm/hyp/switch.c
> > @@ -71,6 +71,8 @@ static void __hyp_text __activate_traps(struct kvm_vcpu 
> > *vcpu)
> >  {
> > u64 val;
> >  
> > +   vcpu->arch.host_hcr_el2 = read_sysreg(hcr_el2);
> > +
> 
> Looking back at this, it seems excessive to switch this at every
> round-trip.  I think it should be possible to have this as a single
> global (or per-CPU) variable that gets restored directly when returning
> from the VM.

I suspect this needs to be per-cpu, to account for heterogeneous
systems.

I guess if we move hcr_el2 into kvm_cpu_context, that gives us a
per-vcpu copy for guests, and a per-cpu copy for the host (in the global
kvm_host_cpu_state).

I'll have a look at how gnarly that turns out. I'm not sure how we can
initialise that sanely for the !VHE case to match whatever el2_setup
did.

Thanks,
Mark.
___
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm


Re: [PATCHv2 10/12] arm64/kvm: context-switch ptrauth registers

2018-04-09 Thread Mark Rutland
On Mon, Apr 09, 2018 at 02:58:18PM +0200, Christoffer Dall wrote:
> Hi Mark,
> 
> [Sorry for late reply]
> 
> On Fri, Mar 09, 2018 at 02:28:38PM +0000, Mark Rutland wrote:
> > On Tue, Feb 06, 2018 at 01:38:47PM +0100, Christoffer Dall wrote:
> > > On Mon, Nov 27, 2017 at 04:38:04PM +, Mark Rutland wrote:
> > > > When pointer authentication is supported, a guest may wish to use it.
> > > > This patch adds the necessary KVM infrastructure for this to work, with
> > > > a semi-lazy context switch of the pointer auth state.
> > > > 
> > > > When we schedule a vcpu, 
> > > 
> > > That's not quite what the code does, the code only does this when we
> > > schedule back a preempted or blocked vcpu thread.
> > 
> > Does that only leave the case of the vCPU being scheduled for the first
> > time? Or am I missing something else?
> > 
> > [...]
> 
> In the current patch, you're only calling kvm_arm_vcpu_ptrauth_disable()
> from kvm_arch_sched_in() which is only called on the preempt notifier
> patch, which leaves out every time we enter the guest from userspace and
> therefore also the initial run of the vCPU (assuming there's no
> preemption in the kernel prior to running the first time).
> 
> vcpu_load() takes care of all the cases.

I see.

> > > I still find this decision to begin trapping again quite arbitrary, and
> > > would at least prefer this to be in vcpu_load (which would make the
> > > behavior match the commit text as well).
> > 
> > Sure, done.
> > 
> > > My expectation would be that if a guest is running software with pointer
> > > authentication enabled, then it's likely to either keep using the
> > > feature, or not use it at all, so I would make this a one-time flag.
> > 
> > I think it's likely that some applications will use ptrauth while others
> > do not. Even if the gust OS supports ptrauth, KVM may repeatedly preempt
> > an application that doesn't use it, and we'd win in that case.
> > 
> > There are also some rarer cases, like kexec in a guest from a
> > ptrauth-aware kernel to a ptrauth-oblivious one.
> > 
> > I don't have strong feelings either way, and I have no data.
> 
> I think your intuition sounds sane, and let's reset the flag on every
> vcpu_load, and we can always revisit when we have hardware and data if
> someone reports a performance issue.

Cool. I've switched to vcpu_load() locally, and will use that in v3.

Thanks,
Mark.
___
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm


[PATCH] ARM64: KVM: use lm_alias() for kvm_ksym_ref()

2018-04-06 Thread Mark Rutland
For historical reasons, we open-code lm_alias() in kvm_ksym_ref().

Let's use lm_alias() to avoid duplication and make things clearer.

As we have to pull this from  (which is not safe for
includion in assembly), we may as well move the kvm_ksym_ref()
definition into the existing !__ASSEMBLY__ block.

Signed-off-by: Mark Rutland <mark.rutl...@arm.com>
Cc: Marc Zyngier <marc.zyng...@arm.com>
Cc: kvmarm@lists.cs.columbia.edu
---
 arch/arm64/include/asm/kvm_asm.h | 7 +--
 1 file changed, 5 insertions(+), 2 deletions(-)

diff --git a/arch/arm64/include/asm/kvm_asm.h b/arch/arm64/include/asm/kvm_asm.h
index 24961b732e65..306aaead8204 100644
--- a/arch/arm64/include/asm/kvm_asm.h
+++ b/arch/arm64/include/asm/kvm_asm.h
@@ -33,15 +33,18 @@
 #define KVM_ARM64_DEBUG_DIRTY_SHIFT0
 #define KVM_ARM64_DEBUG_DIRTY  (1 << KVM_ARM64_DEBUG_DIRTY_SHIFT)
 
+#ifndef __ASSEMBLY__
+
+#include 
+
 #define kvm_ksym_ref(sym)  \
({  \
void *val =\
if (!is_kernel_in_hyp_mode())   \
-   val = phys_to_virt((u64) - kimage_voffset); \
+   val = lm_alias();   \
val;\
 })
 
-#ifndef __ASSEMBLY__
 struct kvm;
 struct kvm_vcpu;
 
-- 
2.11.0

___
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm


Re: [PATCH] KVM: ARM: updtae the VMID generation logic

2018-04-03 Thread Mark Rutland
On Thu, Mar 29, 2018 at 04:27:58PM +0100, Mark Rutland wrote:
> On Thu, Mar 29, 2018 at 11:00:24PM +0800, Shannon Zhao wrote:
> > From: zhaoshenglong <zhaoshengl...@huawei.com>
> > 
> > Currently the VMID for some VM is allocated during VCPU entry/exit
> > context and will be updated when kvm_next_vmid inversion. So this will
> > cause the existing VMs exiting from guest and flush the tlb and icache.
> > 
> > Also, while a platform with 8 bit VMID supports 255 VMs, it can create
> > more than 255 VMs and if we create e.g. 256 VMs, some VMs will occur
> > page fault since at some moment two VMs have same VMID.
> 
> Have you seen this happen?
> 
> I beleive that update_vttbr() should prevent this. We intialize
> kvm_vmid_gen to 1, and when we init a VM, we set its vmid_gen to 0. So
> the first time a VM is scheduled, update_vttbr() will allocate a VMID,
> and by construction we shouldn't be able to allocate the same VMID to
> multiple active VMs, regardless of whether we overflow several times.

Having delved a bit deeper, I think there is a case where a vcpu could
end up using a stale VMID.

Say we have two physical CPUs, and we're running a VM with two VCPUs. 

We start one vCPU, and in update_vttbr() we find the VM's vmid_gen is
stale. So we:

1) Take the vmid lock
2) Increment kvm_vmid_gen
3) force_vm_exit(cpu_all_mask)
4) kvm_call_hyp(__kvm_flush_vm_context)
5) Update kvm->arch.vmid_gen
6) Update kvm->arch.vmid
7) Update kvm->arch.vttbr

... but between steps 5 and 6/7, another CPU can enter update_vttbr(), see that
kvm->arch.vmid_gen == kvm_vmid_gen, and carry on into hyp. In hyp, it reads the
stale kvm->arch.vmid or kvm->arch.vttbr, and programs a stale VMID into the
hardware.

There's a very small window for that to happen, but we might be able to
exacerbate it with something like the below (untested) hack.

This is a classing TOCTTOU bug, and the best way I'm aware of to sovle this is
something like the arm64 ASID allocator, where we reserve the active ASID on
each CPU.

Thanks,
Mark.

>8
diff --git a/virt/kvm/arm/arm.c b/virt/kvm/arm/arm.c
index 53572304843b..69d55aa12350 100644
--- a/virt/kvm/arm/arm.c
+++ b/virt/kvm/arm/arm.c
@@ -506,6 +506,7 @@ static void update_vttbr(struct kvm *kvm)
}
 
kvm->arch.vmid_gen = atomic64_read(_vmid_gen);
+   udelay(10);
kvm->arch.vmid = kvm_next_vmid;
kvm_next_vmid++;
kvm_next_vmid &= (1 << kvm_vmid_bits) - 1;

___
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm


Re: arm64 kvm built with clang doesn't boot

2018-03-16 Thread Mark Rutland
On Fri, Mar 16, 2018 at 04:52:08PM +, Nick Desaulniers wrote:
> + Sami (Google), Takahiro (Linaro)
> 
> Just so I fully understand the problem enough to articulate it, we'd be
> looking for the compiler to keep the jump tables for speed (I would guess
> -fno-jump-tables would emit an if-else chain) but only emit relative jumps
> (not absolute jumps)?

Our main concern is that there is no absolute addressing. If that rules
out using a relative jump table, that's ok.

We want to avoid the fragility of collecting -f-no-* options as future
compiler transformations end up introducing absolute addressing.

Thanks,
Mark.
___
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm


Re: arm64 kvm built with clang doesn't boot

2018-03-16 Thread Mark Rutland
On Fri, Mar 16, 2018 at 02:13:14PM +, Mark Rutland wrote:
> On Fri, Mar 16, 2018 at 02:49:00PM +0100, Andrey Konovalov wrote:
> > Hi!
> 
> Hi,
>  
> > I've recently tried to boot clang built kernel on real hardware
> > (Odroid C2 board) instead of using a VM. The issue that I stumbled
> > upon is that arm64 kvm built with clang doesn't boot.
> > 
> > Adding -fno-jump-tables compiler flag to arch/arm64/kvm/* helps. There
> > was a patch some time ago that did exactly that
> > (https://patchwork.kernel.org/patch/10060381/), but it wasn't accepted
> > AFAICT (see the discussion on that thread).
> > 
> > What would be the best way to get this fixed?
> 
> I think that patch is our best bet currently, but to save ourselves pain
> in future it would be *really* nice if GCC and clang could provide an
> option line -fno-absolute-addressing that would implicitly disable any
> feature that would generate an absolute address as jump tables do.
> 
> > I've also had to disable CONFIG_JUMP_LABEL to get the kernel boot
> > (even without kvm enabled), but that might be a different (though
> > related) issue.
> 
> With v4.15 (and clang 5.0.0), I did not have to disable jump labels to
> get a kernel booting on a Juno platform, though I did have to pass
> -fno-jump-tables to the hyp code.

FWIW, with that same compiler and patch applied atop of v4.16-rc4, and
some bodges around clang not liking the rX register naming in the SMCCC
code, I get a kernel that boots on my Juno, though I immediately hit a
KASAN splat:

[8.476766] 
==
[8.483990] BUG: KASAN: slab-out-of-bounds in __d_lookup_rcu+0x350/0x400
[8.490664] Read of size 8 at addr 8009336e2a30 by task init/1
[8.496808] 
[8.498313] CPU: 2 PID: 1 Comm: init Not tainted 
4.16.0-rc4-1-g1e3a801c4e30-dirty #1
[8.506361] Hardware name: ARM Juno development board (r1) (DT)
[8.512248] Call trace:
[8.514699]  dump_backtrace+0x0/0x29c
[8.518356]  show_stack+0x20/0x2c
[8.521667]  dump_stack+0x118/0x15c
[8.525151]  print_address_description+0x80/0x2d0
[8.529839]  kasan_report+0x208/0x278
[8.533492]  __asan_load8+0x1b0/0x1b8
[8.537148]  __d_lookup_rcu+0x350/0x400
[8.540974]  lookup_fast+0x19c/0x780
[8.544541]  walk_component+0x108/0x121c
[8.548452]  path_lookupat+0x1a4/0x620
[8.552197]  filename_lookup+0x1d8/0x440
[8.556113]  user_path_at_empty+0x54/0x68
[8.560112]  vfs_statx+0x108/0x1f0
[8.563507]  SyS_newfstatat+0x118/0x19c
[8.567333]  el0_svc_naked+0x30/0x34
[8.570889] 
[8.572380] Allocated by task 1:
[8.575603]  kasan_kmalloc+0xe0/0x1ac
[8.579259]  __kmalloc+0x1e4/0x278
[8.582656]  __d_alloc+0x8c/0x370
[8.585968]  d_alloc_parallel+0xdc/0xca0
[8.589883]  nfs_readdir_xdr_to_array+0xe44/0x1694
[8.594658]  nfs_readdir_filler+0x44/0xe8
[8.598662]  do_read_cache_page+0x450/0x6f4
[8.602836]  read_cache_page+0x44/0x54
[8.606575]  nfs_readdir+0xd58/0xef4
[8.610143]  iterate_dir+0x15c/0x26c
[8.613711]  SyS_getdents64+0x180/0x30c
[8.617538]  el0_svc_naked+0x30/0x34
[8.621093] 
[8.622584] Freed by task 0:
[8.625451] (stack is not available)
[8.629007] 
[8.630505] The buggy address belongs to the object at 8009336e2a00
[8.630505]  which belongs to the cache kmalloc-128 of size 128
[8.642969] The buggy address is located 48 bytes inside of
[8.642969]  128-byte region [8009336e2a00, 8009336e2a80)
[8.654558] The buggy address belongs to the page:
[8.659335] page:7e0024cdb880 count:1 mapcount:0 
mapping: index:0x0
[8.667304] flags: 0x1fffc100(slab)
[8.671487] raw: 1fffc100   
000100100010
[8.679206] raw: dead0100 dead0200 800937403c00 

[8.686907] page dumped because: kasan: bad access detected
[8.692447] 
[8.693935] Memory state around the buggy address:
[8.698710]  8009336e2900: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
00
[8.705902]  8009336e2980: fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc 
fc
[8.713093] >8009336e2a00: 00 00 00 00 00 00 06 fc fc fc fc fc fc fc fc 
fc
[8.720277]  ^
[8.725051]  8009336e2a80: fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc 
fc
[8.732242]  8009336e2b00: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
00
[8.739426] 
==

Thanks,
Mark.
___
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm


Re: arm64 kvm built with clang doesn't boot

2018-03-16 Thread Mark Rutland
On Fri, Mar 16, 2018 at 02:49:00PM +0100, Andrey Konovalov wrote:
> Hi!

Hi,
 
> I've recently tried to boot clang built kernel on real hardware
> (Odroid C2 board) instead of using a VM. The issue that I stumbled
> upon is that arm64 kvm built with clang doesn't boot.
> 
> Adding -fno-jump-tables compiler flag to arch/arm64/kvm/* helps. There
> was a patch some time ago that did exactly that
> (https://patchwork.kernel.org/patch/10060381/), but it wasn't accepted
> AFAICT (see the discussion on that thread).
> 
> What would be the best way to get this fixed?

I think that patch is our best bet currently, but to save ourselves pain
in future it would be *really* nice if GCC and clang could provide an
option line -fno-absolute-addressing that would implicitly disable any
feature that would generate an absolute address as jump tables do.

> I've also had to disable CONFIG_JUMP_LABEL to get the kernel boot
> (even without kvm enabled), but that might be a different (though
> related) issue.

With v4.15 (and clang 5.0.0), I did not have to disable jump labels to
get a kernel booting on a Juno platform, though I did have to pass
-fno-jump-tables to the hyp code.

Which kernel version and clang version are you using?

Thanks,
Mark.
___
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm


Re: [PATCHv2 10/12] arm64/kvm: context-switch ptrauth registers

2018-03-09 Thread Mark Rutland
On Tue, Feb 06, 2018 at 01:38:47PM +0100, Christoffer Dall wrote:
> On Mon, Nov 27, 2017 at 04:38:04PM +0000, Mark Rutland wrote:
> > When pointer authentication is supported, a guest may wish to use it.
> > This patch adds the necessary KVM infrastructure for this to work, with
> > a semi-lazy context switch of the pointer auth state.
> > 
> > When we schedule a vcpu, 
> 
> That's not quite what the code does, the code only does this when we
> schedule back a preempted or blocked vcpu thread.

Does that only leave the case of the vCPU being scheduled for the first
time? Or am I missing something else?

[...]

> > we disable guest usage of pointer
> > authentication instructions and accesses to the keys. While these are
> > disabled, we avoid context-switching the keys. When we trap the guest
> > trying to use pointer authentication functionality, we change to eagerly
> > context-switching the keys, and enable the feature. The next time the
> > vcpu is scheduled out/in, we start again.
> > 
> > Pointer authentication consists of address authentication and generic
> > authentication, and CPUs in a system might have varied support for
> > either. Where support for either feature is not uniform, it is hidden
> > from guests via ID register emulation, as a result of the cpufeature
> > framework in the host.
> > 
> > Unfortunately, address authentication and generic authentication cannot
> > be trapped separately, as the architecture provides a single EL2 trap
> > covering both. If we wish to expose one without the other, we cannot
> > prevent a (badly-written) guest from intermittently using a feature
> > which is not uniformly supported (when scheduled on a physical CPU which
> > supports the relevant feature). 
> 
> We could choose to always trap and emulate in software in this case,
> couldn't we?  (not saying we should though).

Practically speaking, we cannot. Emulating the feature would be so
detrimental to performance as to render the feature useless --  every
function prologue/epilogue in a guest would end up trapping to hyp.

Additionally, if the algorithm is IMP DEF, we simply don't know how to
emulate it.

[...]

> Also, this patch doesn't let userspace decide if we should hide or
> expose the feature to guests, and will expose new system registers to
> userspace.  That means that on hardware supporting pointer
> authentication, with this patch, it's not possible to migrate to a
> machine which doesn't have the support.  That's probably a good thing
> (false sense of security etc.), but I wonder if we should have a
> mechanism for userspace to ask for pointer authentication in the guest
> and only if that's enabled, do we expose the feature to the guest and in
> the system register list to user space as well?

Making this an opt-in makes sense to me, given it affects migration.
I'll take a look at what we do for SVE.

[...]

> > When the guest is scheduled on a
> > physical CPU lacking the feature, these atetmps will result in an UNDEF
> 
> attempts

Whoops. Fixed.

[...]

> > +static inline void kvm_arch_sched_in(struct kvm_vcpu *vcpu, int cpu)
> > +{
> > +   kvm_arm_vcpu_ptrauth_disable(vcpu);
> > +}
> > +
> 
> I still find this decision to begin trapping again quite arbitrary, and
> would at least prefer this to be in vcpu_load (which would make the
> behavior match the commit text as well).

Sure, done.

> My expectation would be that if a guest is running software with pointer
> authentication enabled, then it's likely to either keep using the
> feature, or not use it at all, so I would make this a one-time flag.

I think it's likely that some applications will use ptrauth while others
do not. Even if the gust OS supports ptrauth, KVM may repeatedly preempt
an application that doesn't use it, and we'd win in that case.

There are also some rarer cases, like kexec in a guest from a
ptrauth-aware kernel to a ptrauth-oblivious one.

I don't have strong feelings either way, and I have no data.

Thanks,
Mark.
___
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm


Re: [PATCH v7] arm64: Add support for new control bits CTR_EL0.DIC and CTR_EL0.IDC

2018-03-09 Thread Mark Rutland
On Wed, Mar 07, 2018 at 09:00:08AM -0600, Shanker Donthineni wrote:
>  static inline void __flush_icache_all(void)
>  {
> - asm("ic ialluis");
> - dsb(ish);
> + /* Instruction cache invalidation is not required for I/D coherence? */
> + if (!cpus_have_const_cap(ARM64_HAS_CACHE_DIC)) {
> + asm("ic ialluis");
> + dsb(ish);
> + }
>  }

I don't think we need the comment here. We don't have this in the other
cases we look at the ARM64_HAS_CACHE_{IDC,DIC} caps.

This would also be slightly nicer as an early return:

static inline void __flush_icache_all(void)
{
if (cpus_have_const_cap(ARM64_HAS_CACHE_DIC))
return;

asm("ic ialluis");
dsb(ish);
}

... which minimizes indentation, and the diffstat.

The rest looks fine to me, so with the above changes:

Reviewed-by: Mark Rutland <mark.rutl...@arm.com>

Thanks,
Mark.
___
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm


Re: [PATCH v5] arm64: Add support for new control bits CTR_EL0.DIC and CTR_EL0.IDC

2018-02-28 Thread Mark Rutland
Hi,

On Sat, Feb 24, 2018 at 06:09:53AM -0600, Shanker Donthineni wrote:
> +config ARM64_SKIP_CACHE_POU
> + bool "Enable support to skip cache POU operations"

Nit: s/POU/PoU/ in text

> + default y
> + help
> +   Explicit point of unification cache operations can be eliminated
> +   in software if the hardware handles transparently. The new bits in
> +   CTR_EL0, CTR_EL0.DIC and CTR_EL0.IDC indicates the hardware
> +   capabilities of ICache and DCache POU requirements.

Likewise, s/POU/PoU/.

> +
> +   Selecting this feature will allow the kernel to optimize the POU
> +   cache maintaince operations where it requires 'D{I}C C{I}VAU'

The instruction expansion here is a bit odd. It'd probably be best to
just say:

  Selecting this feature will allow the kernel to optimize cache
  maintenance to the PoU.

[...]

> diff --git a/arch/arm64/include/asm/cache.h b/arch/arm64/include/asm/cache.h
> index ea9bb4e..e22178b 100644
> --- a/arch/arm64/include/asm/cache.h
> +++ b/arch/arm64/include/asm/cache.h
> @@ -20,8 +20,13 @@
>  
>  #define CTR_L1IP_SHIFT   14
>  #define CTR_L1IP_MASK3
> +#define CTR_DMLINE_SHIFT 16
> +#define CTR_ERG_SHIFT20
>  #define CTR_CWG_SHIFT24
>  #define CTR_CWG_MASK 15
> +#define CTR_IDC_SHIFT28
> +#define CTR_DIC_SHIFT29
> +#define CTR_B31_SHIFT31

I think the CTR_B31_SHIFT define is gratuitous...

[...]

>  static const struct arm64_ftr_bits ftr_ctr[] = {
> - ARM64_FTR_BITS(FTR_VISIBLE, FTR_STRICT, FTR_EXACT, 31, 1, 1),   
> /* RES1 */

... and we can/should leave this line as-is.

> - ARM64_FTR_BITS(FTR_VISIBLE, FTR_STRICT, FTR_LOWER_SAFE, 29, 1, 1),  
> /* DIC */
> - ARM64_FTR_BITS(FTR_VISIBLE, FTR_STRICT, FTR_LOWER_SAFE, 28, 1, 1),  
> /* IDC */
> - ARM64_FTR_BITS(FTR_VISIBLE, FTR_STRICT, FTR_HIGHER_SAFE, 24, 4, 0), 
> /* CWG */
> - ARM64_FTR_BITS(FTR_VISIBLE, FTR_STRICT, FTR_HIGHER_SAFE, 20, 4, 0), 
> /* ERG */
> - ARM64_FTR_BITS(FTR_VISIBLE, FTR_STRICT, FTR_LOWER_SAFE, 16, 4, 1),  
> /* DminLine */
> + ARM64_FTR_BITS(FTR_VISIBLE, FTR_STRICT, FTR_EXACT, CTR_B31_SHIFT, 1, 
> 1), /* RES1 */
> + ARM64_FTR_BITS(FTR_VISIBLE, FTR_STRICT, FTR_LOWER_SAFE, CTR_DIC_SHIFT, 
> 1, 1),/* DIC */
> + ARM64_FTR_BITS(FTR_VISIBLE, FTR_STRICT, FTR_LOWER_SAFE, CTR_IDC_SHIFT, 
> 1, 1),/* IDC */
> + ARM64_FTR_BITS(FTR_VISIBLE, FTR_STRICT, FTR_HIGHER_SAFE, CTR_CWG_SHIFT, 
> 4, 0),   /* CWG */
> + ARM64_FTR_BITS(FTR_VISIBLE, FTR_STRICT, FTR_HIGHER_SAFE, CTR_ERG_SHIFT, 
> 4, 0),   /* ERG */
> + ARM64_FTR_BITS(FTR_VISIBLE, FTR_STRICT, FTR_LOWER_SAFE, 
> CTR_DMLINE_SHIFT, 4, 1), /* DminLine */

... though the other changes are fine by me.

[...]


> +static bool has_cache_idc(const struct arm64_cpu_capabilities *entry,
> +   int __unused)
> +{
> + return (read_sanitised_ftr_reg(SYS_CTR_EL0) & (1UL << CTR_IDC_SHIFT));
> +}

This can be:

return read_sanitised_ftr_reg(SYS_CTR_EL0) & BIT(CTR_IDC_SHIFT);

> +static bool has_cache_dic(const struct arm64_cpu_capabilities *entry,
> +   int __unused)
> +{
> + return (read_sanitised_ftr_reg(SYS_CTR_EL0) & (1UL << CTR_DIC_SHIFT));
> +}

Likewise:

return read_sanitised_ftr_reg(SYS_CTR_EL0) & BIT(CTR_DIC_SHIFT);

Otherwise, this looks good to me.

Thanks,
Mark.
___
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm


Re: [PATCH v4] arm64: Add support for new control bits CTR_EL0.DIC and CTR_EL0.IDC

2018-02-22 Thread Mark Rutland
On Thu, Feb 22, 2018 at 04:28:03PM +, Robin Murphy wrote:
> [Apologies to keep elbowing in, and if I'm being thick here...]
> 
> On 22/02/18 15:22, Mark Rutland wrote:
> > On Thu, Feb 22, 2018 at 08:51:30AM -0600, Shanker Donthineni wrote:
> > > +#define CTR_B31_SHIFT31
> > 
> > Since this is just a RES1 bit, I think we don't need a mnemonic for it,
> > but I'll defer to Will and Catalin on that.
> > 
> > >   ENTRY(invalidate_icache_range)
> > > +#ifdef CONFIG_ARM64_SKIP_CACHE_POU
> > > +alternative_if ARM64_HAS_CACHE_DIC
> > > + mov x0, xzr
> > > + dsb ishst
> > > + isb
> > > + ret
> > > +alternative_else_nop_endif
> > > +#endif
> > 
> > As commented on v3, I don't believe you need the DSB here. If prior
> > stores haven't been completed at this point, the existing implementation
> > would not work correctly here.
> 
> True in terms of ordering between stores prior to entry and the IC IVAU
> itself, but what about the DSH ISH currently issued *after* the IC IVAU
> before returning? Is provably impossible that existing callers might be
> relying on that ordering *anything*, or would we risk losing something
> subtle by effectively removing it?

AFAIK, the only caller of this is KVM, before page table updates occur
to add execute permissions to the page this is applied to.

At least in that case, I do not beleive there would be breakage.

If we're worried about subtleties in callers, then we'd need to stick
with DSB ISH rather than optimising to DSH ISHST.

Thanks,
Mark.
___
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm


Re: [PATCH v4] arm64: Add support for new control bits CTR_EL0.DIC and CTR_EL0.IDC

2018-02-22 Thread Mark Rutland
On Thu, Feb 22, 2018 at 08:51:30AM -0600, Shanker Donthineni wrote:
> +#define CTR_B31_SHIFT31

Since this is just a RES1 bit, I think we don't need a mnemonic for it,
but I'll defer to Will and Catalin on that.

>  ENTRY(invalidate_icache_range)
> +#ifdef CONFIG_ARM64_SKIP_CACHE_POU
> +alternative_if ARM64_HAS_CACHE_DIC
> + mov x0, xzr
> + dsb ishst
> + isb
> + ret
> +alternative_else_nop_endif
> +#endif

As commented on v3, I don't believe you need the DSB here. If prior
stores haven't been completed at this point, the existing implementation
would not work correctly here.

Otherwise, this looks ok to me.

Thanks,
Mark.
___
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm


Re: [PATCH v3] arm64: Add support for new control bits CTR_EL0.DIC and CTR_EL0.IDC

2018-02-22 Thread Mark Rutland
On Wed, Feb 21, 2018 at 04:51:40PM +, Robin Murphy wrote:
> On 21/02/18 16:14, Shanker Donthineni wrote:
> [...]
> > > > @@ -1100,6 +1114,20 @@ static int cpu_copy_el2regs(void *__unused)
> > > > .enable = cpu_clear_disr,
> > > > },
> > > >   #endif /* CONFIG_ARM64_RAS_EXTN */
> > > > +#ifdef CONFIG_ARM64_SKIP_CACHE_POU
> > > > +   {
> > > > +   .desc = "DCache clean to POU",
> > > 
> > > This description is confusing, and sounds like it's describing DC CVAU, 
> > > rather
> > > than the ability to ellide it. How about:
> > 
> > Sure, I'll take your suggestion.
> 
> Can we at least spell "elision" correctly please? ;)

Argh. Yes.

> Personally I read DIC and IDC as "D-cache to I-cache coherency" and "I-cache
> to D-cache coherency" respectively (just my interpretation, I've not looked
> into the spec work for any hints of rationale), but out loud those do sound
> so poorly-defined that keeping things in terms of the required maintenance
> probably is better.

So long as we have (IDC) and (DIC) in the text to avoid ambiguity, I'm
not that worried either way.

Thanks,
Mark.
___
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm


Re: [PATCH v3] arm64: Add support for new control bits CTR_EL0.DIC and CTR_EL0.IDC

2018-02-21 Thread Mark Rutland
On Wed, Feb 21, 2018 at 07:49:06AM -0600, Shanker Donthineni wrote:
> The DCache clean & ICache invalidation requirements for instructions
> to be data coherence are discoverable through new fields in CTR_EL0.
> The following two control bits DIC and IDC were defined for this
> purpose. No need to perform point of unification cache maintenance
> operations from software on systems where CPU caches are transparent.
> 
> This patch optimize the three functions __flush_cache_user_range(),
> clean_dcache_area_pou() and invalidate_icache_range() if the hardware
> reports CTR_EL0.IDC and/or CTR_EL0.IDC. Basically it skips the two
> instructions 'DC CVAU' and 'IC IVAU', and the associated loop logic
> in order to avoid the unnecessary overhead.
> 
> CTR_EL0.DIC: Instruction cache invalidation requirements for
>  instruction to data coherence. The meaning of this bit[29].
>   0: Instruction cache invalidation to the point of unification
>  is required for instruction to data coherence.
>   1: Instruction cache cleaning to the point of unification is
>   not required for instruction to data coherence.
> 
> CTR_EL0.IDC: Data cache clean requirements for instruction to data
>  coherence. The meaning of this bit[28].
>   0: Data cache clean to the point of unification is required for
>  instruction to data coherence, unless CLIDR_EL1.LoC == 0b000
>  or (CLIDR_EL1.LoUIS == 0b000 && CLIDR_EL1.LoUU == 0b000).
>   1: Data cache clean to the point of unification is not required
>  for instruction to data coherence.
> 
> Signed-off-by: Philip Elcan 
> Signed-off-by: Shanker Donthineni 
> ---
> Changes since v2:
>   -Included barriers, DSB/ISB with DIC set, and DSB with IDC set.
>   -Single Kconfig option.
> 
> Changes since v1:
>   -Reworded commit text.
>   -Used the alternatives framework as Catalin suggested.
>   -Rebased on top of https://patchwork.kernel.org/patch/10227927/
> 
>  arch/arm64/Kconfig   | 12 
>  arch/arm64/include/asm/cache.h   |  5 +
>  arch/arm64/include/asm/cpucaps.h |  4 +++-
>  arch/arm64/kernel/cpufeature.c   | 40 
> ++--
>  arch/arm64/mm/cache.S| 21 +++--
>  5 files changed, 73 insertions(+), 9 deletions(-)
> 
> diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
> index f55fe5b..82b8053 100644
> --- a/arch/arm64/Kconfig
> +++ b/arch/arm64/Kconfig
> @@ -1095,6 +1095,18 @@ config ARM64_RAS_EXTN
> and access the new registers if the system supports the extension.
> Platform RAS features may additionally depend on firmware support.
>  
> +config ARM64_SKIP_CACHE_POU
> + bool "Enable support to skip cache POU operations"
> + default y
> + help
> +   Explicit point of unification cache operations can be eliminated
> +   in software if the hardware handles transparently. The new bits in
> +   CTR_EL0, CTR_EL0.DIC and CTR_EL0.IDC indicates the hardware
> +   capabilities of ICache and DCache POU requirements.
> +
> +   Selecting this feature will allow the kernel to optimize the POU
> +   cache maintaince operations where it requires 'D{I}C C{I}VAU'
> +
>  endmenu

Is it worth having a config option for this at all? The savings from turning
this off seem trivial.

>  
>  config ARM64_SVE
> diff --git a/arch/arm64/include/asm/cache.h b/arch/arm64/include/asm/cache.h
> index ea9bb4e..e22178b 100644
> --- a/arch/arm64/include/asm/cache.h
> +++ b/arch/arm64/include/asm/cache.h
> @@ -20,8 +20,13 @@
>  
>  #define CTR_L1IP_SHIFT   14
>  #define CTR_L1IP_MASK3
> +#define CTR_DMLINE_SHIFT 16
> +#define CTR_ERG_SHIFT20
>  #define CTR_CWG_SHIFT24
>  #define CTR_CWG_MASK 15
> +#define CTR_IDC_SHIFT28
> +#define CTR_DIC_SHIFT29
> +#define CTR_B31_SHIFT31
>  
>  #define CTR_L1IP(ctr)(((ctr) >> CTR_L1IP_SHIFT) & 
> CTR_L1IP_MASK)
>  
> diff --git a/arch/arm64/include/asm/cpucaps.h 
> b/arch/arm64/include/asm/cpucaps.h
> index bb26382..8dd42ae 100644
> --- a/arch/arm64/include/asm/cpucaps.h
> +++ b/arch/arm64/include/asm/cpucaps.h
> @@ -45,7 +45,9 @@
>  #define ARM64_HARDEN_BRANCH_PREDICTOR24
>  #define ARM64_HARDEN_BP_POST_GUEST_EXIT  25
>  #define ARM64_HAS_RAS_EXTN   26
> +#define ARM64_HAS_CACHE_IDC  27
> +#define ARM64_HAS_CACHE_DIC  28
>  
> -#define ARM64_NCAPS  27
> +#define ARM64_NCAPS  29
>  
>  #endif /* __ASM_CPUCAPS_H */
> diff --git a/arch/arm64/kernel/cpufeature.c b/arch/arm64/kernel/cpufeature.c
> index ff8a6e9..12e100a 100644
> --- a/arch/arm64/kernel/cpufeature.c
> +++ b/arch/arm64/kernel/cpufeature.c
> @@ -199,12 +199,12 @@ static int __init register_cpu_hwcaps_dumper(void)
>  };
>  
>  static const struct arm64_ftr_bits ftr_ctr[] = {
> 

[PATCHv2] arm64/kvm: Prohibit guest LOR accesses

2018-02-13 Thread Mark Rutland
We don't currently limit guest accesses to the LOR registers, which we
neither virtualize nor context-switch. As such, guests are provided with
unusable information/controls, and are not isolated from each other (or
the host).

To prevent these issues, we can trap register accesses and present the
illusion LORegions are unssupported by the CPU. To do this, we mask
ID_AA64MMFR1.LO, and set HCR_EL2.TLOR to trap accesses to the following
registers:

* LORC_EL1
* LOREA_EL1
* LORID_EL1
* LORN_EL1
* LORSA_EL1

... when trapped, we inject an UNDEFINED exception to EL1, simulating
their non-existence.

As noted in D7.2.67, when no LORegions are implemented, LoadLOAcquire
and StoreLORelease must behave as LoadAcquire and StoreRelease
respectively. We can ensure this by clearing LORC_EL1.EN when a CPU's
EL2 is first initialized, as the host kernel will not modify this.

Signed-off-by: Mark Rutland <mark.rutl...@arm.com>
Cc: Vladimir Murzin <vladimir.mur...@arm.com>
Cc: Catalin Marinas <catalin.mari...@arm.com>
Cc: Christoffer Dall <christoffer.d...@linaro.org>
Cc: Marc Zyngier <marc.zyng...@arm.com>
Cc: Will Deacon <will.dea...@arm.com>
Cc: kvmarm@lists.cs.columbia.edu
---
 arch/arm64/include/asm/kvm_arm.h |  4 +++-
 arch/arm64/include/asm/sysreg.h  |  6 ++
 arch/arm64/kernel/head.S |  7 +++
 arch/arm64/kvm/sys_regs.c| 20 
 4 files changed, 36 insertions(+), 1 deletion(-)

Since v1 [1]:
* Mask ID_AA64MMFR1.LO
* Always inject an UNDEF for SYS_LOR* accesses

[1] 
http://lists.infradead.org/pipermail/linux-arm-kernel/2018-February/558987.html

diff --git a/arch/arm64/include/asm/kvm_arm.h b/arch/arm64/include/asm/kvm_arm.h
index b0c84171e6a3..1b438c334463 100644
--- a/arch/arm64/include/asm/kvm_arm.h
+++ b/arch/arm64/include/asm/kvm_arm.h
@@ -25,6 +25,7 @@
 /* Hyp Configuration Register (HCR) bits */
 #define HCR_TEA(UL(1) << 37)
 #define HCR_TERR   (UL(1) << 36)
+#define HCR_TLOR   (UL(1) << 35)
 #define HCR_E2H(UL(1) << 34)
 #define HCR_ID (UL(1) << 33)
 #define HCR_CD (UL(1) << 32)
@@ -64,6 +65,7 @@
 
 /*
  * The bits we set in HCR:
+ * TLOR:   Trap LORegion register accesses
  * RW: 64bit by default, can be overridden for 32bit VMs
  * TAC:Trap ACTLR
  * TSC:Trap SMC
@@ -81,7 +83,7 @@
  */
 #define HCR_GUEST_FLAGS (HCR_TSC | HCR_TSW | HCR_TWE | HCR_TWI | HCR_VM | \
 HCR_TVM | HCR_BSU_IS | HCR_FB | HCR_TAC | \
-HCR_AMO | HCR_SWIO | HCR_TIDCP | HCR_RW)
+HCR_AMO | HCR_SWIO | HCR_TIDCP | HCR_RW | HCR_TLOR)
 #define HCR_VIRT_EXCP_MASK (HCR_VSE | HCR_VI | HCR_VF)
 #define HCR_INT_OVERRIDE   (HCR_FMO | HCR_IMO)
 #define HCR_HOST_VHE_FLAGS (HCR_RW | HCR_TGE | HCR_E2H)
diff --git a/arch/arm64/include/asm/sysreg.h b/arch/arm64/include/asm/sysreg.h
index 0e1960c59197..69a99856461c 100644
--- a/arch/arm64/include/asm/sysreg.h
+++ b/arch/arm64/include/asm/sysreg.h
@@ -288,6 +288,12 @@
 #define SYS_MAIR_EL1   sys_reg(3, 0, 10, 2, 0)
 #define SYS_AMAIR_EL1  sys_reg(3, 0, 10, 3, 0)
 
+#define SYS_LORSA_EL1  sys_reg(3, 0, 10, 4, 0)
+#define SYS_LOREA_EL1  sys_reg(3, 0, 10, 4, 1)
+#define SYS_LORN_EL1   sys_reg(3, 0, 10, 4, 2)
+#define SYS_LORC_EL1   sys_reg(3, 0, 10, 4, 3)
+#define SYS_LORID_EL1  sys_reg(3, 0, 10, 4, 7)
+
 #define SYS_VBAR_EL1   sys_reg(3, 0, 12, 0, 0)
 #define SYS_DISR_EL1   sys_reg(3, 0, 12, 1, 1)
 
diff --git a/arch/arm64/kernel/head.S b/arch/arm64/kernel/head.S
index 2b6b8b24e5ab..b0853069702f 100644
--- a/arch/arm64/kernel/head.S
+++ b/arch/arm64/kernel/head.S
@@ -577,6 +577,13 @@ set_hcr:
 7:
msr mdcr_el2, x3// Configure debug traps
 
+   /* LORegions */
+   mrs x1, id_aa64mmfr1_el1
+   ubfxx0, x1, #ID_AA64MMFR1_LOR_SHIFT, 4
+   cbz x0, 1f
+   msr_s   SYS_LORC_EL1, xzr
+1:
+
/* Stage-2 translation */
msr vttbr_el2, xzr
 
diff --git a/arch/arm64/kvm/sys_regs.c b/arch/arm64/kvm/sys_regs.c
index 50a43c7b97ca..55982b565eb2 100644
--- a/arch/arm64/kvm/sys_regs.c
+++ b/arch/arm64/kvm/sys_regs.c
@@ -175,6 +175,14 @@ static bool trap_raz_wi(struct kvm_vcpu *vcpu,
return read_zero(vcpu, p);
 }
 
+static bool trap_undef(struct kvm_vcpu *vcpu,
+  struct sys_reg_params *p,
+  const struct sys_reg_desc *r)
+{
+   kvm_inject_undefined(vcpu);
+   return false;
+}
+
 static bool trap_oslsr_el1(struct kvm_vcpu *vcpu,
   struct sys_reg_params *p,
   const struct sys_reg_desc *r)
@@ -893,6 +901,12 @@ static u64 read_id_reg(struct sys_reg_desc const *r, bool 
raz)
task_pid

Re: [PATCH] arm64/kvm: Prohibit guest LOR accesses

2018-02-13 Thread Mark Rutland
On Tue, Feb 13, 2018 at 11:27:42AM +0100, Christoffer Dall wrote:
> Hi Mark,

Hi Christoffer,

> On Mon, Feb 12, 2018 at 11:14:24AM +, Mark Rutland wrote:
> > We don't currently limit guest accesses to the LOR registers, which we
> > neither virtualize nor context-switch. As such, guests are provided with
> > unusable information/controls, and are not isolated from each other (or
> > the host).
> > 
> > To prevent these issues, we can trap register accesses and present the
> > illusion that no LORegions are implemented.
> 
> Shouldn't we then also hide this from the ID register similar to what we
> do for SVE at the moment, using something like this (untested):
> 
> diff --git a/arch/arm64/kvm/sys_regs.c b/arch/arm64/kvm/sys_regs.c
> index a828a209716f..b7ee414aee67 100644
> --- a/arch/arm64/kvm/sys_regs.c
> +++ b/arch/arm64/kvm/sys_regs.c
> @@ -1064,6 +1064,12 @@ static u64 read_id_reg(struct sys_reg_desc const *r, 
> bool raz)
>   task_pid_nr(current));
>  
>   val &= ~(0xfUL << ID_AA64PFR0_SVE_SHIFT);
> + } else if (id == SYS_ID_AA64MMFR1_EL) {
> + if (val & (0xfUL << ID_AA64MMFR1_LOR_SHIFT))
> + pr_err_once("kvm [%i]: LORegions unsupported for 
> guests, suppressing\n",
> + task_pid_nr(current));
> +
> + val &= ~(0xfUL << ID_AA64MMFR1_LOR_SHIFT);
>   }
>  
>   return val;

Sure. With that, it would make sense for the trapped LOR* register
accesses to UNDEF, as they logically shouldn't exist.

[...]

> > diff --git a/arch/arm64/kvm/sys_regs.c b/arch/arm64/kvm/sys_regs.c
> > index 50a43c7b97ca..67b10b7a07bf 100644
> > --- a/arch/arm64/kvm/sys_regs.c
> > +++ b/arch/arm64/kvm/sys_regs.c
> > @@ -175,6 +175,17 @@ static bool trap_raz_wi(struct kvm_vcpu *vcpu,
> > return read_zero(vcpu, p);
> >  }
> >  
> > +static bool trap_raz_ro(struct kvm_vcpu *vcpu,
> > +   struct sys_reg_params *p,
> > +   const struct sys_reg_desc *r)
> > +{
> > +   if (!p->is_write)
> > +   return read_zero(vcpu, p);
> > +
> > +   kvm_inject_undefined(vcpu);
> > +   return false;
> > +}
> > +
> 
> I'm a little unclear if this is stricly the right thing to do.  I can't
> seem to find anything specific about writes to this register (which has
> some text about RW fields but only specifies it can be *read* with an
> MRS instruction), so it seems to me that this should either be
> trap_raz_wi(), or call write_to_read_only() if we expect a write to
> undef at EL1 rather than trap to EL2.  On the other hand, if the
> architecture is unclear, then we're at least enforcing one
> interpretation here I suppose.

Having looked at the ARM ARM, I think write_to_read_only() is the right
thing to do.

It's not clear to me whether HCR_EL2.TLOR traps writes to LORID_EL1, or
leaves these UNDEFINED at EL1. In the description of traps and enables
it's stated that HCR_EL2.TLOR traps "Non-secure accesses to this
register from EL1", which could be read to mean either. I'll see if I
can get to the bottom of that.

I don't think trap_raz_wi(), as LORID_EL1 is never RW at EL1, and a
write wound UNDEF were HCR_EL2.TLOR clear.

Thanks,
Mark.
___
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm


Re: [PATCHv2 05/12] arm64: Don't trap host pointer auth use to EL2

2018-02-12 Thread Mark Rutland
On Tue, Feb 06, 2018 at 01:39:06PM +0100, Christoffer Dall wrote:
> Hi Mark,
> 
> On Mon, Nov 27, 2017 at 04:37:59PM +0000, Mark Rutland wrote:
> > To allow EL0 (and/or EL1) to use pointer authentication functionality,
> > we must ensure that pointer authentication instructions and accesses to
> > pointer authentication keys are not trapped to EL2 (where we will not be
> > able to handle them).
> 
> ...on non-VHE systems, presumably?

For EL0 usage, we don't want to trap even in the absence of VHE, so I'll
drop the bit in brackets entirely.

> > This patch ensures that HCR_EL2 is configured appropriately when the
> > kernel is booted at EL2. For non-VHE kernels we set HCR_EL2.{API,APK},
> > ensuring that EL1 can access keys and permit EL0 use of instructions.
> > For VHE kernels, EL2 access is controlled by EL3, and we need not set
> > anything.
> 
> 
> for VHE kernels host EL0 (TGE && E2H) is unaffected by these settings,
> and it doesn't matter how we configure HCR_EL2.{API,APK}.
> 
> (Because you do actually set these bits when the features are present if
> I read the code correctly).

Ah, true. I've taken your proposed wording.

> > This does not enable support for KVM guests, since KVM manages HCR_EL2
> > itself.
> 
> (...when running VMs.)
> 
> 
> Besides the nits:
> 
> Acked-by: Christoffer Dall <christoffer.d...@linaro.org>

Cheers!

Mark.
___
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm


[PATCH] arm64/kvm: Prohibit guest LOR accesses

2018-02-12 Thread Mark Rutland
We don't currently limit guest accesses to the LOR registers, which we
neither virtualize nor context-switch. As such, guests are provided with
unusable information/controls, and are not isolated from each other (or
the host).

To prevent these issues, we can trap register accesses and present the
illusion that no LORegions are implemented. Per ARM DDI 0487B.a, in this
case all fields in LORID_EL1 will contain zero, and:

* LORC_EL1  is RW, RES0 (D7.2.65 "Configurations" & "Accessibility")
* LOREA_EL1 is RW, RES0 (D7.2.66 "Configurations" & "Accessibility")
* LORN_EL1  is RW, RES0 (D7.2.68 "Configurations" & "Accessibility")
* LORSA_EL1 is RW, RES0 (D7.2.69 "Configurations" & "Accessibility")

Note that LORID_EL1 itself is RO per D7.2.67.

As noted in D7.2.67, when no LORegions are implemented, LoadLOAcquire
and StoreLORelease must behave as LoadAcquire and StoreRelease
respectively. We can ensure this by clearing LORC_EL1.EN when a CPU's
EL2 is first initialized, as the host kernel will not modify this.

Signed-off-by: Mark Rutland <mark.rutl...@arm.com>
Reviewed-by: Vladimir Murzin <vladimir.mur...@arm.com>
Cc: Catalin Marinas <catalin.mari...@arm.com>
Cc: Christoffer Dall <christoffer.d...@linaro.org>
Cc: Marc Zyngier <marc.zyng...@arm.com>
Cc: Will Deacon <will.dea...@arm.com>
Cc: kvmarm@lists.cs.columbia.edu
---
 arch/arm64/include/asm/kvm_arm.h |  4 +++-
 arch/arm64/include/asm/sysreg.h  |  6 ++
 arch/arm64/kernel/head.S |  7 +++
 arch/arm64/kvm/sys_regs.c| 17 +
 4 files changed, 33 insertions(+), 1 deletion(-)

diff --git a/arch/arm64/include/asm/kvm_arm.h b/arch/arm64/include/asm/kvm_arm.h
index b0c84171e6a3..1b438c334463 100644
--- a/arch/arm64/include/asm/kvm_arm.h
+++ b/arch/arm64/include/asm/kvm_arm.h
@@ -25,6 +25,7 @@
 /* Hyp Configuration Register (HCR) bits */
 #define HCR_TEA(UL(1) << 37)
 #define HCR_TERR   (UL(1) << 36)
+#define HCR_TLOR   (UL(1) << 35)
 #define HCR_E2H(UL(1) << 34)
 #define HCR_ID (UL(1) << 33)
 #define HCR_CD (UL(1) << 32)
@@ -64,6 +65,7 @@
 
 /*
  * The bits we set in HCR:
+ * TLOR:   Trap LORegion register accesses
  * RW: 64bit by default, can be overridden for 32bit VMs
  * TAC:Trap ACTLR
  * TSC:Trap SMC
@@ -81,7 +83,7 @@
  */
 #define HCR_GUEST_FLAGS (HCR_TSC | HCR_TSW | HCR_TWE | HCR_TWI | HCR_VM | \
 HCR_TVM | HCR_BSU_IS | HCR_FB | HCR_TAC | \
-HCR_AMO | HCR_SWIO | HCR_TIDCP | HCR_RW)
+HCR_AMO | HCR_SWIO | HCR_TIDCP | HCR_RW | HCR_TLOR)
 #define HCR_VIRT_EXCP_MASK (HCR_VSE | HCR_VI | HCR_VF)
 #define HCR_INT_OVERRIDE   (HCR_FMO | HCR_IMO)
 #define HCR_HOST_VHE_FLAGS (HCR_RW | HCR_TGE | HCR_E2H)
diff --git a/arch/arm64/include/asm/sysreg.h b/arch/arm64/include/asm/sysreg.h
index 0e1960c59197..69a99856461c 100644
--- a/arch/arm64/include/asm/sysreg.h
+++ b/arch/arm64/include/asm/sysreg.h
@@ -288,6 +288,12 @@
 #define SYS_MAIR_EL1   sys_reg(3, 0, 10, 2, 0)
 #define SYS_AMAIR_EL1  sys_reg(3, 0, 10, 3, 0)
 
+#define SYS_LORSA_EL1  sys_reg(3, 0, 10, 4, 0)
+#define SYS_LOREA_EL1  sys_reg(3, 0, 10, 4, 1)
+#define SYS_LORN_EL1   sys_reg(3, 0, 10, 4, 2)
+#define SYS_LORC_EL1   sys_reg(3, 0, 10, 4, 3)
+#define SYS_LORID_EL1  sys_reg(3, 0, 10, 4, 7)
+
 #define SYS_VBAR_EL1   sys_reg(3, 0, 12, 0, 0)
 #define SYS_DISR_EL1   sys_reg(3, 0, 12, 1, 1)
 
diff --git a/arch/arm64/kernel/head.S b/arch/arm64/kernel/head.S
index 2b6b8b24e5ab..b0853069702f 100644
--- a/arch/arm64/kernel/head.S
+++ b/arch/arm64/kernel/head.S
@@ -577,6 +577,13 @@ set_hcr:
 7:
msr mdcr_el2, x3// Configure debug traps
 
+   /* LORegions */
+   mrs x1, id_aa64mmfr1_el1
+   ubfxx0, x1, #ID_AA64MMFR1_LOR_SHIFT, 4
+   cbz x0, 1f
+   msr_s   SYS_LORC_EL1, xzr
+1:
+
/* Stage-2 translation */
msr vttbr_el2, xzr
 
diff --git a/arch/arm64/kvm/sys_regs.c b/arch/arm64/kvm/sys_regs.c
index 50a43c7b97ca..67b10b7a07bf 100644
--- a/arch/arm64/kvm/sys_regs.c
+++ b/arch/arm64/kvm/sys_regs.c
@@ -175,6 +175,17 @@ static bool trap_raz_wi(struct kvm_vcpu *vcpu,
return read_zero(vcpu, p);
 }
 
+static bool trap_raz_ro(struct kvm_vcpu *vcpu,
+   struct sys_reg_params *p,
+   const struct sys_reg_desc *r)
+{
+   if (!p->is_write)
+   return read_zero(vcpu, p);
+
+   kvm_inject_undefined(vcpu);
+   return false;
+}
+
 static bool trap_oslsr_el1(struct kvm_vcpu *vcpu,
   struct sys_reg_params *p,
   const s

Re: [RESEND PATCH v4 2/2] arm64: Add software workaround for Falkor erratum 1041

2017-12-11 Thread Mark Rutland
Hi,

On Sun, Dec 10, 2017 at 08:03:43PM -0600, Shanker Donthineni wrote:
> +/**
> + * Errata workaround prior to disable MMU. Insert an ISB immediately prior
> + * to executing the MSR that will change SCTLR_ELn[M] from a value of 1 to 0.
> + */
> + .macro pre_disable_mmu_workaround
> +#ifdef CONFIG_QCOM_FALKOR_ERRATUM_E1041
> +alternative_if ARM64_WORKAROUND_QCOM_FALKOR_E1041
> + isb
> +alternative_else_nop_endif
> +#endif
> + .endm

There's really no need for this to be an alternative. It makes the
kernel larger and more complex due to all the altinstr data and probing
code.

As Will suggested last time [1], please just use the ifdef, and always
compile-in the extra ISB if CONFIG_QCOM_FALKOR_ERRATUM_E1041 is
selected. Get rid of the alternatives and probing code.

All you need here is:

/*
 * Some Falkor parts make errant speculative instruction fetches
 * when SCTLR_ELx.M is cleared. An ISB before the write to
 * SCTLR_ELx prevents this.
 */
.macro pre_disable_mmu_workaround
#ifdef
isb
#endif
.endm

> +
> + .macro pre_disable_mmu_early_workaround
> +#ifdef CONFIG_QCOM_FALKOR_ERRATUM_E1041
> + isb
> +#endif
> + .endm
> +

... and we don't need a special early variant.

Thanks,
Mark.

[1] https://lkml.kernel.org/r/20171201112457.ge18...@arm.com
___
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm


Re: [PATCH v5 08/16] arm64: Add vmap_stack header file

2017-12-07 Thread Mark Rutland
Hi James,

On Wed, Dec 06, 2017 at 07:01:34PM +, James Morse wrote:
> Today the arm64 arch code allocates an extra IRQ stack per-cpu. If we
> also have SDEI and VMAP stacks we need two extra per-cpu VMAP stacks.
> 
> Move the VMAP stack allocation out to a helper in a new header file.
> This avoids missing THREADINFO_GFP, or getting the all-important alignment
> wrong.
> 
> Signed-off-by: James Morse <james.mo...@arm.com>
> Reviewed-by: Catalin Marinas <catalin.mari...@arm.com>
> ---
> Changes since v4:
>  * Added gfp.h include
> 
> Changes since v3:
>  * Added BUILD_BUG() instead of a spooky link error
> 
>  arch/arm64/include/asm/vmap_stack.h | 26 ++
>  arch/arm64/kernel/irq.c | 13 ++---
>  2 files changed, 28 insertions(+), 11 deletions(-)
>  create mode 100644 arch/arm64/include/asm/vmap_stack.h
> 
> diff --git a/arch/arm64/include/asm/vmap_stack.h 
> b/arch/arm64/include/asm/vmap_stack.h
> new file mode 100644
> index ..5465e4e65987
> --- /dev/null
> +++ b/arch/arm64/include/asm/vmap_stack.h
> @@ -0,0 +1,26 @@
> +// SPDX-License-Identifier: GPL-2.0
> +// Copyright (C) 2017 Arm Ltd.
> +#ifndef __ASM_VMAP_STACK_H
> +#define __ASM_VMAP_STACK_H
> +
> +#include 
> +#include 
> +#include 
> +#include 
> +#include 

I think we also need:

#include   // for BUILD_BUG_ON()
#incldue   // for IS_ENABLED()

Otherwise, this looks good to me. With those includes folded in:

Reviewed-by: Mark Rutland <mark.rutl...@arm.com>

Thanks,
Mark.

> +
> +/*
> + * To ensure that VMAP'd stack overflow detection works correctly, all VMAP'd
> + * stacks need to have the same alignment.
> + */
> +static inline unsigned long *arch_alloc_vmap_stack(size_t stack_size, int 
> node)
> +{
> + BUILD_BUG_ON(!IS_ENABLED(CONFIG_VMAP_STACK));
> +
> + return __vmalloc_node_range(stack_size, THREAD_ALIGN,
> + VMALLOC_START, VMALLOC_END,
> + THREADINFO_GFP, PAGE_KERNEL, 0, node,
> + __builtin_return_address(0));
> +}
> +
> +#endif /* __ASM_VMAP_STACK_H */
> diff --git a/arch/arm64/kernel/irq.c b/arch/arm64/kernel/irq.c
> index 713561e5bcab..60e5fc661f74 100644
> --- a/arch/arm64/kernel/irq.c
> +++ b/arch/arm64/kernel/irq.c
> @@ -29,6 +29,7 @@
>  #include 
>  #include 
>  #include 
> +#include 
>  
>  unsigned long irq_err_count;
>  
> @@ -58,17 +59,7 @@ static void init_irq_stacks(void)
>   unsigned long *p;
>  
>   for_each_possible_cpu(cpu) {
> - /*
> - * To ensure that VMAP'd stack overflow detection works
> - * correctly, the IRQ stacks need to have the same
> - * alignment as other stacks.
> - */
> - p = __vmalloc_node_range(IRQ_STACK_SIZE, THREAD_ALIGN,
> -  VMALLOC_START, VMALLOC_END,
> -  THREADINFO_GFP, PAGE_KERNEL,
> -  0, cpu_to_node(cpu),
> -  __builtin_return_address(0));
> -
> + p = arch_alloc_vmap_stack(IRQ_STACK_SIZE, cpu_to_node(cpu));
>   per_cpu(irq_stack_ptr, cpu) = p;
>   }
>  }
> -- 
> 2.15.0
> 
> --
> To unsubscribe from this list: send the line "unsubscribe devicetree" in
> the body of a message to majord...@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
___
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm


[PATCHv2 12/12] arm64: docs: document pointer authentication

2017-11-27 Thread Mark Rutland
Now that we've added code to support pointer authentication, add some
documentation so that people can figure out if/how to use it.

Signed-off-by: Mark Rutland <mark.rutl...@arm.com>
Cc: Catalin Marinas <catalin.mari...@arm.com>
Cc: Will Deacon <will.dea...@arm.com>
Cc: Yao Qi <yao...@arm.com>
---
 Documentation/arm64/booting.txt|  8 +++
 Documentation/arm64/elf_hwcaps.txt |  6 ++
 Documentation/arm64/pointer-authentication.txt | 85 ++
 3 files changed, 99 insertions(+)
 create mode 100644 Documentation/arm64/pointer-authentication.txt

diff --git a/Documentation/arm64/booting.txt b/Documentation/arm64/booting.txt
index 8d0df62c3fe0..8df9f4658d6f 100644
--- a/Documentation/arm64/booting.txt
+++ b/Documentation/arm64/booting.txt
@@ -205,6 +205,14 @@ Before jumping into the kernel, the following conditions 
must be met:
 ICC_SRE_EL2.SRE (bit 0) must be initialised to 0b0.
   - The DT or ACPI tables must describe a GICv2 interrupt controller.
 
+  For CPUs with pointer authentication functionality:
+  - If EL3 is present:
+SCR_EL3.APK (bit 16) must be initialised to 0b1
+SCR_EL3.API (bit 17) must be initialised to 0b1
+  - If the kernel is entered at EL1:
+HCR_EL2.APK (bit 40) must be initialised to 0b1
+HCR_EL2.API (bit 41) must be initialised to 0b1
+
 The requirements described above for CPU mode, caches, MMUs, architected
 timers, coherency and system registers apply to all CPUs.  All CPUs must
 enter the kernel in the same exception level.
diff --git a/Documentation/arm64/elf_hwcaps.txt 
b/Documentation/arm64/elf_hwcaps.txt
index 89edba12a9e0..6cf40e419a9d 100644
--- a/Documentation/arm64/elf_hwcaps.txt
+++ b/Documentation/arm64/elf_hwcaps.txt
@@ -158,3 +158,9 @@ HWCAP_SHA512
 HWCAP_SVE
 
 Functionality implied by ID_AA64PFR0_EL1.SVE == 0b0001.
+
+HWCAP_APIA
+
+EL0 AddPac and Auth functionality using APIAKey_EL1 is enabled, as
+described by Documentation/arm64/pointer-authentication.txt.
+
diff --git a/Documentation/arm64/pointer-authentication.txt 
b/Documentation/arm64/pointer-authentication.txt
new file mode 100644
index ..e9b5c6bdb84f
--- /dev/null
+++ b/Documentation/arm64/pointer-authentication.txt
@@ -0,0 +1,85 @@
+Pointer authentication in AArch64 Linux
+=======
+
+Author: Mark Rutland <mark.rutl...@arm.com>
+Date: 2017-07-19
+
+This document briefly describes the provision of pointer authentication
+functionality in AArch64 Linux.
+
+
+Architecture overview
+-
+
+The ARMv8.3 Pointer Authentication extension adds primitives that can be
+used to mitigate certain classes of attack where an attacker can corrupt
+the contents of some memory (e.g. the stack).
+
+The extension uses a Pointer Authentication Code (PAC) to determine
+whether pointers have been modified unexpectedly. A PAC is derived from
+a pointer, another value (such as the stack pointer), and a secret key
+held in system registers.
+
+The extension adds instructions to insert a valid PAC into a pointer,
+and to verify/remove the PAC from a pointer. The PAC occupies a number
+of high-order bits of the pointer, which varies dependent on the
+configured virtual address size and whether pointer tagging is in use.
+
+A subset of these instructions have been allocated from the HINT
+encoding space. In the absence of the extension (or when disabled),
+these instructions behave as NOPs. Applications and libraries using
+these instructions operate correctly regardless of the presence of the
+extension.
+
+
+Basic support
+-
+
+When CONFIG_ARM64_POINTER_AUTHENTICATION is selected, and relevant HW
+support is present, the kernel will assign a random APIAKey value to
+each process at exec*() time. This key is shared by all threads within
+the process, and the key is preserved across fork(). Presence of
+functionality using APIAKey is advertised via HWCAP_APIA.
+
+Recent versions of GCC can compile code with APIAKey-based return
+address protection when passed the -msign-return-address option. This
+uses instructions in the HINT space, and such code can run on systems
+without the pointer authentication extension.
+
+The remaining instruction and data keys (APIBKey, APDAKey, APDBKey) are
+reserved for future use, and instructions using these keys must not be
+used by software until a purpose and scope for their use has been
+decided. To enable future software using these keys to function on
+contemporary kernels, where possible, instructions using these keys are
+made to behave as NOPs.
+
+The generic key (APGAKey) is currently unsupported. Instructions using
+the generic key must not be used by software.
+
+
+Debugging
+-
+
+When CONFIG_ARM64_POINTER_AUTHENTICATION is selected, and relevant HW
+support is present, the kernel will expose the position of TTBR0 PAC
+bits in the NT_ARM_PAC_MASK regset (struct user_pac_mask), which
+userspace c

[PATCHv2 09/12] arm64/kvm: preserve host HCR_EL2 value

2017-11-27 Thread Mark Rutland
When restoring HCR_EL2 for the host, KVM uses HCR_HOST_VHE_FLAGS, which
is a constant value. This works today, as the host HCR_EL2 value is
always the same, but this will get in the way of supporting extensions
that require HCR_EL2 bits to be set conditionally for the host.

To allow such features to work without KVM having to explicitly handle
every possible host feature combination, this patch has KVM save/restore
the host HCR when switching to/from a guest HCR.

For __{activate,deactivate}_traps(), the HCR save/restore is made common
across the !VHE and VHE paths. As the host and guest HCR values must
have E2H set when VHE is in use, register redirection should always be
in effect at EL2, and this change should not adversely affect the VHE
code.

For the hyp TLB maintenance code, __tlb_switch_to_host_vhe() is updated
to toggle the TGE bit with a RMW sequence, as we already do in
__tlb_switch_to_guest_vhe().

The now unused HCR_HOST_VHE_FLAGS definition is removed.

Signed-off-by: Mark Rutland <mark.rutl...@arm.com>
Reviewed-by: Christoffer Dall <cd...@linaro.org>
Cc: Marc Zyngier <marc.zyng...@arm.com>
Cc: kvmarm@lists.cs.columbia.edu
---
 arch/arm64/include/asm/kvm_arm.h  | 1 -
 arch/arm64/include/asm/kvm_host.h | 5 -
 arch/arm64/kvm/hyp/switch.c   | 5 +++--
 arch/arm64/kvm/hyp/tlb.c  | 6 +-
 4 files changed, 12 insertions(+), 5 deletions(-)

diff --git a/arch/arm64/include/asm/kvm_arm.h b/arch/arm64/include/asm/kvm_arm.h
index 62854d5d1d3b..aa02b05430e8 100644
--- a/arch/arm64/include/asm/kvm_arm.h
+++ b/arch/arm64/include/asm/kvm_arm.h
@@ -84,7 +84,6 @@
 HCR_AMO | HCR_SWIO | HCR_TIDCP | HCR_RW)
 #define HCR_VIRT_EXCP_MASK (HCR_VSE | HCR_VI | HCR_VF)
 #define HCR_INT_OVERRIDE   (HCR_FMO | HCR_IMO)
-#define HCR_HOST_VHE_FLAGS (HCR_RW | HCR_TGE | HCR_E2H)
 
 /* TCR_EL2 Registers bits */
 #define TCR_EL2_RES1   ((1 << 31) | (1 << 23))
diff --git a/arch/arm64/include/asm/kvm_host.h 
b/arch/arm64/include/asm/kvm_host.h
index 674912d7a571..39184aa3e2f2 100644
--- a/arch/arm64/include/asm/kvm_host.h
+++ b/arch/arm64/include/asm/kvm_host.h
@@ -199,10 +199,13 @@ typedef struct kvm_cpu_context kvm_cpu_context_t;
 struct kvm_vcpu_arch {
struct kvm_cpu_context ctxt;
 
-   /* HYP configuration */
+   /* Guest HYP configuration */
u64 hcr_el2;
u32 mdcr_el2;
 
+   /* Host HYP configuration */
+   u64 host_hcr_el2;
+
/* Exception Information */
struct kvm_vcpu_fault_info fault;
 
diff --git a/arch/arm64/kvm/hyp/switch.c b/arch/arm64/kvm/hyp/switch.c
index 525c01f48867..2205f0be3ced 100644
--- a/arch/arm64/kvm/hyp/switch.c
+++ b/arch/arm64/kvm/hyp/switch.c
@@ -71,6 +71,8 @@ static void __hyp_text __activate_traps(struct kvm_vcpu *vcpu)
 {
u64 val;
 
+   vcpu->arch.host_hcr_el2 = read_sysreg(hcr_el2);
+
/*
 * We are about to set CPTR_EL2.TFP to trap all floating point
 * register accesses to EL2, however, the ARM ARM clearly states that
@@ -116,7 +118,6 @@ static void __hyp_text __deactivate_traps_vhe(void)
MDCR_EL2_TPMS;
 
write_sysreg(mdcr_el2, mdcr_el2);
-   write_sysreg(HCR_HOST_VHE_FLAGS, hcr_el2);
write_sysreg(CPACR_EL1_DEFAULT, cpacr_el1);
write_sysreg(vectors, vbar_el1);
 }
@@ -129,7 +130,6 @@ static void __hyp_text __deactivate_traps_nvhe(void)
mdcr_el2 |= MDCR_EL2_E2PB_MASK << MDCR_EL2_E2PB_SHIFT;
 
write_sysreg(mdcr_el2, mdcr_el2);
-   write_sysreg(HCR_RW, hcr_el2);
write_sysreg(CPTR_EL2_DEFAULT, cptr_el2);
 }
 
@@ -151,6 +151,7 @@ static void __hyp_text __deactivate_traps(struct kvm_vcpu 
*vcpu)
__deactivate_traps_arch()();
write_sysreg(0, hstr_el2);
write_sysreg(0, pmuserenr_el0);
+   write_sysreg(vcpu->arch.host_hcr_el2, hcr_el2);
 }
 
 static void __hyp_text __activate_vm(struct kvm_vcpu *vcpu)
diff --git a/arch/arm64/kvm/hyp/tlb.c b/arch/arm64/kvm/hyp/tlb.c
index 73464a96c365..c2b0680efa2c 100644
--- a/arch/arm64/kvm/hyp/tlb.c
+++ b/arch/arm64/kvm/hyp/tlb.c
@@ -49,12 +49,16 @@ static hyp_alternate_select(__tlb_switch_to_guest,
 
 static void __hyp_text __tlb_switch_to_host_vhe(struct kvm *kvm)
 {
+   u64 val;
+
/*
 * We're done with the TLB operation, let's restore the host's
 * view of HCR_EL2.
 */
write_sysreg(0, vttbr_el2);
-   write_sysreg(HCR_HOST_VHE_FLAGS, hcr_el2);
+   val = read_sysreg(hcr_el2);
+   val |= HCR_TGE;
+   write_sysreg(val, hcr_el2);
 }
 
 static void __hyp_text __tlb_switch_to_host_nvhe(struct kvm *kvm)
-- 
2.11.0

___
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm


[PATCHv2 10/12] arm64/kvm: context-switch ptrauth registers

2017-11-27 Thread Mark Rutland
When pointer authentication is supported, a guest may wish to use it.
This patch adds the necessary KVM infrastructure for this to work, with
a semi-lazy context switch of the pointer auth state.

When we schedule a vcpu, we disable guest usage of pointer
authentication instructions and accesses to the keys. While these are
disabled, we avoid context-switching the keys. When we trap the guest
trying to use pointer authentication functionality, we change to eagerly
context-switching the keys, and enable the feature. The next time the
vcpu is scheduled out/in, we start again.

Pointer authentication consists of address authentication and generic
authentication, and CPUs in a system might have varied support for
either. Where support for either feature is not uniform, it is hidden
from guests via ID register emulation, as a result of the cpufeature
framework in the host.

Unfortunately, address authentication and generic authentication cannot
be trapped separately, as the architecture provides a single EL2 trap
covering both. If we wish to expose one without the other, we cannot
prevent a (badly-written) guest from intermittently using a feature
which is not uniformly supported (when scheduled on a physical CPU which
supports the relevant feature). When the guest is scheduled on a
physical CPU lacking the feature, these atetmps will result in an UNDEF
being taken by the guest.

Signed-off-by: Mark Rutland <mark.rutl...@arm.com>
Cc: Christoffer Dall <cd...@linaro.org>
Cc: Marc Zyngier <marc.zyng...@arm.com>
Cc: kvmarm@lists.cs.columbia.edu
---
 arch/arm64/include/asm/kvm_host.h | 23 +-
 arch/arm64/include/asm/kvm_hyp.h  |  7 +++
 arch/arm64/kvm/handle_exit.c  | 21 +
 arch/arm64/kvm/hyp/Makefile   |  1 +
 arch/arm64/kvm/hyp/ptrauth-sr.c   | 91 +++
 arch/arm64/kvm/hyp/switch.c   |  4 ++
 arch/arm64/kvm/sys_regs.c | 32 ++
 7 files changed, 178 insertions(+), 1 deletion(-)
 create mode 100644 arch/arm64/kvm/hyp/ptrauth-sr.c

diff --git a/arch/arm64/include/asm/kvm_host.h 
b/arch/arm64/include/asm/kvm_host.h
index 39184aa3e2f2..2fc21a2a75a7 100644
--- a/arch/arm64/include/asm/kvm_host.h
+++ b/arch/arm64/include/asm/kvm_host.h
@@ -136,6 +136,18 @@ enum vcpu_sysreg {
PMSWINC_EL0,/* Software Increment Register */
PMUSERENR_EL0,  /* User Enable Register */
 
+   /* Pointer Authentication Registers */
+   APIAKEYLO_EL1,
+   APIAKEYHI_EL1,
+   APIBKEYLO_EL1,
+   APIBKEYHI_EL1,
+   APDAKEYLO_EL1,
+   APDAKEYHI_EL1,
+   APDBKEYLO_EL1,
+   APDBKEYHI_EL1,
+   APGAKEYLO_EL1,
+   APGAKEYHI_EL1,
+
/* 32bit specific registers. Keep them at the end of the range */
DACR32_EL2, /* Domain Access Control Register */
IFSR32_EL2, /* Instruction Fault Status Register */
@@ -363,10 +375,19 @@ static inline void __cpu_init_hyp_mode(phys_addr_t 
pgd_ptr,
__kvm_call_hyp((void *)pgd_ptr, hyp_stack_ptr, vector_ptr);
 }
 
+void kvm_arm_vcpu_ptrauth_enable(struct kvm_vcpu *vcpu);
+void kvm_arm_vcpu_ptrauth_disable(struct kvm_vcpu *vcpu);
+void kvm_arm_vcpu_ptrauth_trap(struct kvm_vcpu *vcpu);
+
 static inline void kvm_arch_hardware_unsetup(void) {}
 static inline void kvm_arch_sync_events(struct kvm *kvm) {}
 static inline void kvm_arch_vcpu_uninit(struct kvm_vcpu *vcpu) {}
-static inline void kvm_arch_sched_in(struct kvm_vcpu *vcpu, int cpu) {}
+
+static inline void kvm_arch_sched_in(struct kvm_vcpu *vcpu, int cpu)
+{
+   kvm_arm_vcpu_ptrauth_disable(vcpu);
+}
+
 static inline void kvm_arch_vcpu_block_finish(struct kvm_vcpu *vcpu) {}
 
 void kvm_arm_init_debug(void);
diff --git a/arch/arm64/include/asm/kvm_hyp.h b/arch/arm64/include/asm/kvm_hyp.h
index 08d3bb66c8b7..d0dd924cb175 100644
--- a/arch/arm64/include/asm/kvm_hyp.h
+++ b/arch/arm64/include/asm/kvm_hyp.h
@@ -152,6 +152,13 @@ void __fpsimd_save_state(struct user_fpsimd_state 
*fp_regs);
 void __fpsimd_restore_state(struct user_fpsimd_state *fp_regs);
 bool __fpsimd_enabled(void);
 
+void __ptrauth_switch_to_guest(struct kvm_vcpu *vcpu,
+  struct kvm_cpu_context *host_ctxt,
+  struct kvm_cpu_context *guest_ctxt);
+void __ptrauth_switch_to_host(struct kvm_vcpu *vcpu,
+ struct kvm_cpu_context *host_ctxt,
+ struct kvm_cpu_context *guest_ctxt);
+
 u64 __guest_enter(struct kvm_vcpu *vcpu, struct kvm_cpu_context *host_ctxt);
 void __noreturn __hyp_do_panic(unsigned long, ...);
 
diff --git a/arch/arm64/kvm/handle_exit.c b/arch/arm64/kvm/handle_exit.c
index b71247995469..d9aff3c86551 100644
--- a/arch/arm64/kvm/handle_exit.c
+++ b/arch/arm64/kvm/handle_exit.c
@@ -136,6 +136,26 @@ static int kvm_handle_guest_debug(struct kvm_vcpu *vcpu, 
struct kvm_run *run)
return ret;
 }
 
+/*
+ * Handle the guest trying to use a ptrauth instruction, or trying to access a
+ 

[PATCHv2 08/12] arm64: perf: strip PAC when unwinding userspace

2017-11-27 Thread Mark Rutland
When the kernel is unwinding userspace callchains, we can't expect that
the userspace consumer of these callchains has the data necessary to
strip the PAC from the stored LR.

This patch has the kernel strip the PAC from user stackframes when the
in-kernel unwinder is used. This only affects the LR value, and not the
FP.

This only affects the in-kernel unwinder. When userspace performs
unwinding, it is up to userspace to strip PACs as necessary (which can
be determined from DWARF information).

Signed-off-by: Mark Rutland <mark.rutl...@arm.com>
Cc: Catalin Marinas <catalin.mari...@arm.com>
Cc: Will Deacon <will.dea...@arm.com>
Cc: Yao Qi <yao...@arm.com>
---
 arch/arm64/include/asm/pointer_auth.h | 7 +++
 arch/arm64/kernel/perf_callchain.c| 5 -
 2 files changed, 11 insertions(+), 1 deletion(-)

diff --git a/arch/arm64/include/asm/pointer_auth.h 
b/arch/arm64/include/asm/pointer_auth.h
index b08ebec4b806..07788ce755bc 100644
--- a/arch/arm64/include/asm/pointer_auth.h
+++ b/arch/arm64/include/asm/pointer_auth.h
@@ -79,6 +79,12 @@ static inline void ptrauth_keys_dup(struct ptrauth_keys *old,
  */
 #define ptrauth_pac_mask() GENMASK(54, VA_BITS)
 
+/* Only valid for EL0 TTBR0 instruction pointers */
+static inline unsigned long ptrauth_strip_insn_pac(unsigned long ptr)
+{
+   return ptr & ~ptrauth_pac_mask();
+}
+
 #define mm_ctx_ptrauth_init(ctx) \
ptrauth_keys_init(&(ctx)->ptrauth_keys)
 
@@ -89,6 +95,7 @@ static inline void ptrauth_keys_dup(struct ptrauth_keys *old,
ptrauth_keys_dup(&(oldctx)->ptrauth_keys, &(newctx)->ptrauth_keys)
 
 #else
+#define ptrauth_strip_insn_pac(lr) (lr)
 #define mm_ctx_ptrauth_init(ctx)
 #define mm_ctx_ptrauth_switch(ctx)
 #define mm_ctx_ptrauth_dup(oldctx, newctx)
diff --git a/arch/arm64/kernel/perf_callchain.c 
b/arch/arm64/kernel/perf_callchain.c
index bcafd7dcfe8b..928204f6ab08 100644
--- a/arch/arm64/kernel/perf_callchain.c
+++ b/arch/arm64/kernel/perf_callchain.c
@@ -35,6 +35,7 @@ user_backtrace(struct frame_tail __user *tail,
 {
struct frame_tail buftail;
unsigned long err;
+   unsigned long lr;
 
/* Also check accessibility of one struct frame_tail beyond */
if (!access_ok(VERIFY_READ, tail, sizeof(buftail)))
@@ -47,7 +48,9 @@ user_backtrace(struct frame_tail __user *tail,
if (err)
return NULL;
 
-   perf_callchain_store(entry, buftail.lr);
+   lr = ptrauth_strip_insn_pac(buftail.lr);
+
+   perf_callchain_store(entry, lr);
 
/*
 * Frame pointers should strictly progress back up the stack
-- 
2.11.0

___
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm


[PATCHv2 06/12] arm64: add basic pointer authentication support

2017-11-27 Thread Mark Rutland
This patch adds basic support for pointer authentication, allowing
userspace to make use of APIAKey. The kernel maintains an APIAKey value
for each process (shared by all threads within), which is initialised to
a random value at exec() time.

To describe that address authentication instructions are available, the
ID_AA64ISAR0.{APA,API} fields are exposed to userspace. A new hwcap,
APIA, is added to describe that the kernel manages APIAKey.

Instructions using other keys (APIBKey, APDAKey, APDBKey) are disabled,
and will behave as NOPs. These may be made use of in future patches.

No support is added for the generic key (APGAKey), though this cannot be
trapped or made to behave as a NOP. Its presence is not advertised with
a hwcap.

Signed-off-by: Mark Rutland <mark.rutl...@arm.com>
Cc: Catalin Marinas <catalin.mari...@arm.com>
Cc: Suzuki K Poulose <suzuki.poul...@arm.com>
Cc: Will Deacon <will.dea...@arm.com>
---
 arch/arm64/include/asm/mmu.h  |  5 ++
 arch/arm64/include/asm/mmu_context.h  | 25 +-
 arch/arm64/include/asm/pointer_auth.h | 89 +++
 arch/arm64/include/uapi/asm/hwcap.h   |  1 +
 arch/arm64/kernel/cpufeature.c| 17 ++-
 arch/arm64/kernel/cpuinfo.c   |  1 +
 6 files changed, 134 insertions(+), 4 deletions(-)
 create mode 100644 arch/arm64/include/asm/pointer_auth.h

diff --git a/arch/arm64/include/asm/mmu.h b/arch/arm64/include/asm/mmu.h
index 0d34bf0a89c7..2bcdf7f923ba 100644
--- a/arch/arm64/include/asm/mmu.h
+++ b/arch/arm64/include/asm/mmu.h
@@ -16,12 +16,17 @@
 #ifndef __ASM_MMU_H
 #define __ASM_MMU_H
 
+#include 
+
 #define MMCF_AARCH32   0x1 /* mm context flag for AArch32 executables */
 
 typedef struct {
atomic64_t  id;
void*vdso;
unsigned long   flags;
+#ifdef CONFIG_ARM64_POINTER_AUTHENTICATION
+   struct ptrauth_keys ptrauth_keys;
+#endif
 } mm_context_t;
 
 /*
diff --git a/arch/arm64/include/asm/mmu_context.h 
b/arch/arm64/include/asm/mmu_context.h
index 3257895a9b5e..06757a537bd7 100644
--- a/arch/arm64/include/asm/mmu_context.h
+++ b/arch/arm64/include/asm/mmu_context.h
@@ -31,7 +31,6 @@
 #include 
 #include 
 #include 
-#include 
 #include 
 #include 
 #include 
@@ -154,7 +153,14 @@ static inline void cpu_replace_ttbr1(pgd_t *pgd)
 #define destroy_context(mm)do { } while(0)
 void check_and_switch_context(struct mm_struct *mm, unsigned int cpu);
 
-#define init_new_context(tsk,mm)   ({ atomic64_set(&(mm)->context.id, 0); 
0; })
+static inline int init_new_context(struct task_struct *tsk,
+   struct mm_struct *mm)
+{
+   atomic64_set(>context.id, 0);
+   mm_ctx_ptrauth_init(>context);
+
+   return 0;
+}
 
 /*
  * This is called when "tsk" is about to enter lazy TLB mode.
@@ -200,6 +206,8 @@ static inline void __switch_mm(struct mm_struct *next)
return;
}
 
+   mm_ctx_ptrauth_switch(>context);
+
check_and_switch_context(next, cpu);
 }
 
@@ -226,6 +234,19 @@ switch_mm(struct mm_struct *prev, struct mm_struct *next,
 
 void verify_cpu_asid_bits(void);
 
+static inline void arch_dup_mmap(struct mm_struct *oldmm,
+struct mm_struct *mm)
+{
+   mm_ctx_ptrauth_dup(>context, >context);
+}
+#define arch_dup_mmap arch_dup_mmap
+
+/*
+ * We need to override arch_dup_mmap before including the generic hooks, which
+ * are otherwise sufficient for us.
+ */
+#include 
+
 #endif /* !__ASSEMBLY__ */
 
 #endif /* !__ASM_MMU_CONTEXT_H */
diff --git a/arch/arm64/include/asm/pointer_auth.h 
b/arch/arm64/include/asm/pointer_auth.h
new file mode 100644
index ..964da0c3dc48
--- /dev/null
+++ b/arch/arm64/include/asm/pointer_auth.h
@@ -0,0 +1,89 @@
+/*
+ * Copyright (C) 2016 ARM Ltd.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+#ifndef __ASM_POINTER_AUTH_H
+#define __ASM_POINTER_AUTH_H
+
+#include 
+
+#include 
+#include 
+
+#ifdef CONFIG_ARM64_POINTER_AUTHENTICATION
+/*
+ * Each key is a 128-bit quantity which is split accross a pair of 64-bit
+ * registers (Lo and Hi).
+ */
+struct ptrauth_key {
+   unsigned long lo, hi;
+};
+
+/*
+ * We give each process its own instruction A key (APIAKey), which is shared by
+ * all threads. This is inherited upon fork(), and reinitialised upon exec*().
+ * All other keys are currently unused, with A

[PATCHv2 05/12] arm64: Don't trap host pointer auth use to EL2

2017-11-27 Thread Mark Rutland
To allow EL0 (and/or EL1) to use pointer authentication functionality,
we must ensure that pointer authentication instructions and accesses to
pointer authentication keys are not trapped to EL2 (where we will not be
able to handle them).

This patch ensures that HCR_EL2 is configured appropriately when the
kernel is booted at EL2. For non-VHE kernels we set HCR_EL2.{API,APK},
ensuring that EL1 can access keys and permit EL0 use of instructions.
For VHE kernels, EL2 access is controlled by EL3, and we need not set
anything.

This does not enable support for KVM guests, since KVM manages HCR_EL2
itself.

Signed-off-by: Mark Rutland <mark.rutl...@arm.com>
Cc: Catalin Marinas <catalin.mari...@arm.com>
Cc: Christoffer Dall <cd...@linaro.org>
Cc: Marc Zyngier <marc.zyng...@arm.com>
Cc: Will Deacon <will.dea...@arm.com>
Cc: kvmarm@lists.cs.columbia.edu
---
 arch/arm64/include/asm/kvm_arm.h |  2 ++
 arch/arm64/kernel/head.S | 19 +--
 2 files changed, 19 insertions(+), 2 deletions(-)

diff --git a/arch/arm64/include/asm/kvm_arm.h b/arch/arm64/include/asm/kvm_arm.h
index 7f069ff37f06..62854d5d1d3b 100644
--- a/arch/arm64/include/asm/kvm_arm.h
+++ b/arch/arm64/include/asm/kvm_arm.h
@@ -23,6 +23,8 @@
 #include 
 
 /* Hyp Configuration Register (HCR) bits */
+#define HCR_API(UL(1) << 41)
+#define HCR_APK(UL(1) << 40)
 #define HCR_E2H(UL(1) << 34)
 #define HCR_ID (UL(1) << 33)
 #define HCR_CD (UL(1) << 32)
diff --git a/arch/arm64/kernel/head.S b/arch/arm64/kernel/head.S
index 67e86a0f57ac..06a96e9af26b 100644
--- a/arch/arm64/kernel/head.S
+++ b/arch/arm64/kernel/head.S
@@ -415,10 +415,25 @@ CPU_LE(   bic x0, x0, #(1 << 25)  )   // 
Clear the EE bit for EL2
 
/* Hyp configuration. */
mov x0, #HCR_RW // 64-bit EL1
-   cbz x2, set_hcr
+   cbz x2, 1f
orr x0, x0, #HCR_TGE// Enable Host Extensions
orr x0, x0, #HCR_E2H
-set_hcr:
+1:
+#ifdef CONFIG_ARM64_POINTER_AUTHENTICATION
+   /*
+* Disable pointer authentication traps to EL2. The HCR_EL2.{APK,API}
+* bits exist iff at least one authentication mechanism is implemented.
+*/
+   mrs x1, id_aa64isar1_el1
+   mov_q   x3, ((0xf << ID_AA64ISAR1_GPI_SHIFT) | \
+(0xf << ID_AA64ISAR1_GPA_SHIFT) | \
+(0xf << ID_AA64ISAR1_API_SHIFT) | \
+(0xf << ID_AA64ISAR1_APA_SHIFT))
+   and x1, x1, x3
+   cbz x1, 1f
+   orr x0, x0, #(HCR_APK | HCR_API)
+1:
+#endif
msr hcr_el2, x0
isb
 
-- 
2.11.0

___
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm


[PATCHv2 04/12] arm64/cpufeature: detect pointer authentication

2017-11-27 Thread Mark Rutland
So that we can dynamically handle the presence of pointer authentication
functionality, wire up probing code in cpufeature.c.

It is assumed that if all CPUs support an IMP DEF algorithm, the same
algorithm is used across all CPUs.

Signed-off-by: Mark Rutland <mark.rutl...@arm.com>
Cc: Catalin Marinas <catalin.mari...@arm.com>
Cc: Suzuki K Poulose <suzuki.poul...@arm.com>
Cc: Will Deacon <will.dea...@arm.com>
---
 arch/arm64/include/asm/cpucaps.h |  8 +++-
 arch/arm64/kernel/cpufeature.c   | 82 
 2 files changed, 89 insertions(+), 1 deletion(-)

diff --git a/arch/arm64/include/asm/cpucaps.h b/arch/arm64/include/asm/cpucaps.h
index 2ff7c5e8efab..d2830ce5c1c7 100644
--- a/arch/arm64/include/asm/cpucaps.h
+++ b/arch/arm64/include/asm/cpucaps.h
@@ -41,7 +41,13 @@
 #define ARM64_WORKAROUND_CAVIUM_30115  20
 #define ARM64_HAS_DCPOP21
 #define ARM64_SVE  22
+#define ARM64_HAS_ADDRESS_AUTH_ARCH23
+#define ARM64_HAS_ADDRESS_AUTH_IMP_DEF 24
+#define ARM64_HAS_ADDRESS_AUTH 25
+#define ARM64_HAS_GENERIC_AUTH_ARCH26
+#define ARM64_HAS_GENERIC_AUTH_IMP_DEF 27
+#define ARM64_HAS_GENERIC_AUTH 28
 
-#define ARM64_NCAPS23
+#define ARM64_NCAPS29
 
 #endif /* __ASM_CPUCAPS_H */
diff --git a/arch/arm64/kernel/cpufeature.c b/arch/arm64/kernel/cpufeature.c
index 1883cdffcdf7..babd4c173092 100644
--- a/arch/arm64/kernel/cpufeature.c
+++ b/arch/arm64/kernel/cpufeature.c
@@ -853,6 +853,36 @@ static bool has_no_fpsimd(const struct 
arm64_cpu_capabilities *entry, int __unus
ID_AA64PFR0_FP_SHIFT) < 0;
 }
 
+#ifdef CONFIG_ARM64_POINTER_AUTHENTICATION
+static bool has_address_auth(const struct arm64_cpu_capabilities *entry,
+int __unused)
+{
+   u64 isar1 = read_sanitised_ftr_reg(SYS_ID_AA64ISAR1_EL1);
+   bool api, apa;
+
+   apa = cpuid_feature_extract_unsigned_field(isar1,
+   ID_AA64ISAR1_APA_SHIFT) > 0;
+   api = cpuid_feature_extract_unsigned_field(isar1,
+   ID_AA64ISAR1_API_SHIFT) > 0;
+
+   return apa || api;
+}
+
+static bool has_generic_auth(const struct arm64_cpu_capabilities *entry,
+int __unused)
+{
+   u64 isar1 = read_sanitised_ftr_reg(SYS_ID_AA64ISAR1_EL1);
+   bool gpi, gpa;
+
+   gpa = cpuid_feature_extract_unsigned_field(isar1,
+   ID_AA64ISAR1_GPA_SHIFT) > 0;
+   gpi = cpuid_feature_extract_unsigned_field(isar1,
+   ID_AA64ISAR1_GPI_SHIFT) > 0;
+
+   return gpa || gpi;
+}
+#endif /* CONFIG_ARM64_POINTER_AUTHENTICATION */
+
 static const struct arm64_cpu_capabilities arm64_features[] = {
{
.desc = "GIC system register CPU interface",
@@ -970,6 +1000,58 @@ static const struct arm64_cpu_capabilities 
arm64_features[] = {
.enable = sve_kernel_enable,
},
 #endif /* CONFIG_ARM64_SVE */
+#ifdef CONFIG_ARM64_POINTER_AUTHENTICATION
+   {
+   .desc = "Address authentication (architected algorithm)",
+   .capability = ARM64_HAS_ADDRESS_AUTH_ARCH,
+   .def_scope = SCOPE_SYSTEM,
+   .sys_reg = SYS_ID_AA64ISAR1_EL1,
+   .sign = FTR_UNSIGNED,
+   .field_pos = ID_AA64ISAR1_APA_SHIFT,
+   .min_field_value = ID_AA64ISAR1_APA_ARCHITECTED,
+   .matches = has_cpuid_feature,
+   },
+   {
+   .desc = "Address authentication (IMP DEF algorithm)",
+   .capability = ARM64_HAS_ADDRESS_AUTH_IMP_DEF,
+   .def_scope = SCOPE_SYSTEM,
+   .sys_reg = SYS_ID_AA64ISAR1_EL1,
+   .sign = FTR_UNSIGNED,
+   .field_pos = ID_AA64ISAR1_API_SHIFT,
+   .min_field_value = ID_AA64ISAR1_API_IMP_DEF,
+   .matches = has_cpuid_feature,
+   },
+   {
+   .capability = ARM64_HAS_ADDRESS_AUTH,
+   .def_scope = SCOPE_SYSTEM,
+   .matches = has_address_auth,
+   },
+   {
+   .desc = "Generic authentication (architected algorithm)",
+   .capability = ARM64_HAS_GENERIC_AUTH_ARCH,
+   .def_scope = SCOPE_SYSTEM,
+   .sys_reg = SYS_ID_AA64ISAR1_EL1,
+   .sign = FTR_UNSIGNED,
+   .field_pos = ID_AA64ISAR1_GPA_SHIFT,
+   .min_field_value = ID_AA64ISAR1_GPA_ARCHITECTED,
+   .matches = has_cpuid_feature
+   },
+   {
+   .desc = "Generic authentication (IMP DEF algorithm)",
+   .capability = ARM64_HAS_GENERIC_AUTH_IMP_DEF,
+   .def_scope = SCOPE_SYST

[PATCHv2 03/12] arm64/cpufeature: add ARMv8.3 id_aa64isar1 bits

2017-11-27 Thread Mark Rutland
>From ARMv8.3 onwards, ID_AA64ISAR1 is no longer entirely RES0, and now
has four fields describing the presence of pointer authentication
functionality:

* APA - address authentication present, using an architected algorithm
* API - address authentication present, using an IMP DEF algorithm
* GPA - generic authentication present, using an architected algorithm
* GPI - generic authentication present, using an IMP DEF algorithm

This patch adds the requisite definitions so that we can identify the
presence of this functionality.

For the timebeing, the features are hidden from both KVM guests and
userspace. As marking them with FTR_HIDDEN only hides them from
userspace, they are also protected with ifdeffery on
CONFIG_ARM64_POINTER_AUTHENTICATION.

Signed-off-by: Mark Rutland <mark.rutl...@arm.com>
Cc: Suzuki K Poulose <suzuki.poul...@arm.com>
Cc: Catalin Marinas <catalin.mari...@arm.com>
Cc: Will Deacon <will.dea...@arm.com>
Cc: Suzuki K Poulose <suzuki.poul...@arm.com>
---
 arch/arm64/kernel/cpufeature.c | 8 
 1 file changed, 8 insertions(+)

diff --git a/arch/arm64/kernel/cpufeature.c b/arch/arm64/kernel/cpufeature.c
index c5ba0097887f..1883cdffcdf7 100644
--- a/arch/arm64/kernel/cpufeature.c
+++ b/arch/arm64/kernel/cpufeature.c
@@ -137,9 +137,17 @@ static const struct arm64_ftr_bits ftr_id_aa64isar0[] = {
 };
 
 static const struct arm64_ftr_bits ftr_id_aa64isar1[] = {
+#ifdef CONFIG_ARM64_POINTER_AUTHENTICATION
+   ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, 
ID_AA64ISAR1_GPI_SHIFT, 4, 0),
+   ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, 
ID_AA64ISAR1_GPA_SHIFT, 4, 0),
+#endif
ARM64_FTR_BITS(FTR_VISIBLE, FTR_STRICT, FTR_LOWER_SAFE, 
ID_AA64ISAR1_LRCPC_SHIFT, 4, 0),
ARM64_FTR_BITS(FTR_VISIBLE, FTR_STRICT, FTR_LOWER_SAFE, 
ID_AA64ISAR1_FCMA_SHIFT, 4, 0),
ARM64_FTR_BITS(FTR_VISIBLE, FTR_STRICT, FTR_LOWER_SAFE, 
ID_AA64ISAR1_JSCVT_SHIFT, 4, 0),
+#ifdef CONFIG_ARM64_POINTER_AUTHENTICATION
+   ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, 
ID_AA64ISAR1_API_SHIFT, 4, 0),
+   ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, 
ID_AA64ISAR1_APA_SHIFT, 4, 0),
+#endif
ARM64_FTR_BITS(FTR_VISIBLE, FTR_STRICT, FTR_LOWER_SAFE, 
ID_AA64ISAR1_DPB_SHIFT, 4, 0),
ARM64_FTR_END,
 };
-- 
2.11.0

___
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm


<    1   2   3   4   5   >