Re: [Qemu-devel] [kvm-unit-tests PATCH v8 2/3] arm: pmu: Check cycle count increases

2016-11-10 Thread Andrew Jones
On Tue, Nov 08, 2016 at 12:17:14PM -0600, Wei Huang wrote:
> From: Christopher Covington 
> 
> Ensure that reads of the PMCCNTR_EL0 are monotonically increasing,
> even for the smallest delta of two subsequent reads.
> 
> Signed-off-by: Christopher Covington 
> Signed-off-by: Wei Huang 
> ---
>  arm/pmu.c | 98 
> +++
>  1 file changed, 98 insertions(+)
> 
> diff --git a/arm/pmu.c b/arm/pmu.c
> index 0b29088..d5e3ac3 100644
> --- a/arm/pmu.c
> +++ b/arm/pmu.c
> @@ -14,6 +14,7 @@
>   */
>  #include "libcflat.h"
>  
> +#define PMU_PMCR_E (1 << 0)
>  #define PMU_PMCR_N_SHIFT   11
>  #define PMU_PMCR_N_MASK0x1f
>  #define PMU_PMCR_ID_SHIFT  16
> @@ -21,6 +22,10 @@
>  #define PMU_PMCR_IMP_SHIFT 24
>  #define PMU_PMCR_IMP_MASK  0xff
>  
> +#define PMU_CYCLE_IDX  31
> +
> +#define NR_SAMPLES 10
> +
>  #if defined(__arm__)
>  static inline uint32_t pmcr_read(void)
>  {
> @@ -29,6 +34,47 @@ static inline uint32_t pmcr_read(void)
>   asm volatile("mrc p15, 0, %0, c9, c12, 0" : "=r" (ret));
>   return ret;
>  }
> +
> +static inline void pmcr_write(uint32_t value)
> +{
> + asm volatile("mcr p15, 0, %0, c9, c12, 0" : : "r" (value));
> +}
> +
> +static inline void pmselr_write(uint32_t value)
> +{
> + asm volatile("mcr p15, 0, %0, c9, c12, 5" : : "r" (value));
> +}
> +
> +static inline void pmxevtyper_write(uint32_t value)
> +{
> + asm volatile("mcr p15, 0, %0, c9, c13, 1" : : "r" (value));
> +}
> +
> +/*
> + * While PMCCNTR can be accessed as a 64 bit coprocessor register, returning 
> 64
> + * bits doesn't seem worth the trouble when differential usage of the result 
> is
> + * expected (with differences that can easily fit in 32 bits). So just return
> + * the lower 32 bits of the cycle count in AArch32.

Like I said in the last review, I'd rather we not do this. We should
return the full value and then the test case should confirm the upper
32 bits are zero.

> + */
> +static inline uint32_t pmccntr_read(void)
> +{
> + uint32_t cycles;
> +
> + asm volatile("mrc p15, 0, %0, c9, c13, 0" : "=r" (cycles));
> + return cycles;
> +}
> +
> +static inline void pmcntenset_write(uint32_t value)
> +{
> + asm volatile("mcr p15, 0, %0, c9, c12, 1" : : "r" (value));
> +}
> +
> +/* PMCCFILTR is an obsolete name for PMXEVTYPER31 in ARMv7 */
> +static inline void pmccfiltr_write(uint32_t value)
> +{
> + pmselr_write(PMU_CYCLE_IDX);
> + pmxevtyper_write(value);
> +}
>  #elif defined(__aarch64__)
>  static inline uint32_t pmcr_read(void)
>  {
> @@ -37,6 +83,29 @@ static inline uint32_t pmcr_read(void)
>   asm volatile("mrs %0, pmcr_el0" : "=r" (ret));
>   return ret;
>  }
> +
> +static inline void pmcr_write(uint32_t value)
> +{
> + asm volatile("msr pmcr_el0, %0" : : "r" (value));
> +}
> +
> +static inline uint32_t pmccntr_read(void)
> +{
> + uint32_t cycles;
> +
> + asm volatile("mrs %0, pmccntr_el0" : "=r" (cycles));
> + return cycles;
> +}
> +
> +static inline void pmcntenset_write(uint32_t value)
> +{
> + asm volatile("msr pmcntenset_el0, %0" : : "r" (value));
> +}
> +
> +static inline void pmccfiltr_write(uint32_t value)
> +{
> + asm volatile("msr pmccfiltr_el0, %0" : : "r" (value));
> +}
>  #endif
>  
>  /*
> @@ -63,11 +132,40 @@ static bool check_pmcr(void)
>   return ((pmcr >> PMU_PMCR_IMP_SHIFT) & PMU_PMCR_IMP_MASK) != 0;
>  }
>  
> +/*
> + * Ensure that the cycle counter progresses between back-to-back reads.
> + */
> +static bool check_cycles_increase(void)
> +{
> + pmcr_write(pmcr_read() | PMU_PMCR_E);
> +
> + for (int i = 0; i < NR_SAMPLES; i++) {
> + unsigned long a, b;
> +
> + a = pmccntr_read();
> + b = pmccntr_read();
> +
> + if (a >= b) {
> + printf("Read %ld then %ld.\n", a, b);
> + return false;
> + }
> + }
> +
> + pmcr_write(pmcr_read() & ~PMU_PMCR_E);
> +
> + return true;
> +}
> +
>  int main(void)
>  {
>   report_prefix_push("pmu");
>  
> + /* init for PMU event access, right now only care about cycle count */
> + pmcntenset_write(1 << PMU_CYCLE_IDX);
> + pmccfiltr_write(0); /* count cycles in EL0, EL1, but not EL2 */
> +
>   report("Control register", check_pmcr());
> + report("Monotonically increasing cycle count", check_cycles_increase());
>  
>   return report_summary();
>  }
> -- 
> 1.8.3.1

Besides needing to use u64's for registers that return u64's, it
looks good to me.

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


Re: [Qemu-devel] [kvm-unit-tests PATCH v8 1/3] arm: Add PMU test

2016-11-10 Thread Andrew Jones
On Tue, Nov 08, 2016 at 12:17:13PM -0600, Wei Huang wrote:
> From: Christopher Covington 
> 
> Beginning with a simple sanity check of the control register, add
> a unit test for the ARM Performance Monitors Unit (PMU).
> 
> Signed-off-by: Christopher Covington 
> Signed-off-by: Wei Huang 
> ---
>  arm/Makefile.common |  3 ++-
>  arm/pmu.c   | 73 
> +
>  arm/unittests.cfg   |  5 
>  3 files changed, 80 insertions(+), 1 deletion(-)
>  create mode 100644 arm/pmu.c

Reviewed-by: Andrew Jones 
___
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm


Re: [Qemu-devel] [kvm-unit-tests PATCH v5 10/11] arm/arm64: gicv3: add an IPI test

2016-11-10 Thread Andrew Jones
On Thu, Nov 10, 2016 at 07:53:58PM +, Alex Bennée wrote:
[...]
> > +struct gic gicv2 = {
> > +   .ipi = {
> > +   .enable = gicv2_enable_defaults,
> > +   .send_self = gicv2_ipi_send_self,
> > +   .send_tlist = gicv2_ipi_send_tlist,
> > +   .send_broadcast = gicv2_ipi_send_broadcast,
> > +   },
> > +   .read_iar = gicv2_read_iar,
> > +   .irqnr = gicv2_irqnr,
> > +   .write_eoi = gicv2_write_eoi,
> > +};
> > +
> > +struct gic gicv3 = {
> > +   .ipi = {
> > +   .enable = gicv3_enable_defaults,
> > +   .send_self = gicv3_ipi_send_self,
> > +   .send_tlist = gicv3_ipi_send_tlist,
> > +   .send_broadcast = gicv3_ipi_send_broadcast,
> > +   },
> > +   .read_iar = gicv3_read_iar,
> > +   .irqnr = gicv3_irqnr,
> > +   .write_eoi = gicv3_write_eoir,
> > +};
> > +
> 
> So I was re-basing my kvm-unit-tests against your GIC rework and found
> myself copy and pasting a bunch of this into my tests that fire IRQs.
> That makes me think the abstraction should be in the library code so
> other tests can fiddle with sending IRQs.
> 
> What do you think?
>

I guess you mean moving the above two structs and their corresponding
functions (all which aren't already common) to lib/arm/ ? Or do you
just mean the one non-trivial function gicv3_ipi_send_tlist? I think
agree with gicv3_ipi_send_tlist getting shared, but the others are
mostly one-liners, so I'm not sure. I guess I'd have to see how you're
using them first.

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


Re: [kvm-unit-tests PATCH v5 10/11] arm/arm64: gicv3: add an IPI test

2016-11-10 Thread Alex Bennée

Andrew Jones  writes:

> Signed-off-by: Andrew Jones 
>
> ---
> v5:
>  - fix copy+paste error in gicv3_write_eoir [drew]
>  - use modern register names [Andre]
> v4:
>  - heavily comment gicv3_ipi_send_tlist() [Eric]
>  - changes needed for gicv2 iar/irqstat fix to other patch
> v2:
>  - use IRM for gicv3 broadcast
> ---
>  arm/gic.c  | 195 
> ++---
>  arm/unittests.cfg  |   6 ++
>  lib/arm/asm/arch_gicv3.h   |  23 ++
>  lib/arm64/asm/arch_gicv3.h |  22 +
>  4 files changed, 236 insertions(+), 10 deletions(-)
>
> diff --git a/arm/gic.c b/arm/gic.c
> index 06092aec7c08..ca68f8ad1cb9 100644
> --- a/arm/gic.c
> +++ b/arm/gic.c
> @@ -3,6 +3,8 @@
>   *
>   * GICv2
>   *   + test sending/receiving IPIs
> + * GICv3
> + *   + test sending/receiving IPIs
>   *
>   * Copyright (C) 2016, Red Hat Inc, Andrew Jones 
>   *
> @@ -16,6 +18,19 @@
>  #include 
>  #include 
>
> +struct gic {
> + struct {
> + void (*enable)(void);
> + void (*send_self)(void);
> + void (*send_tlist)(cpumask_t *);
> + void (*send_broadcast)(void);
> + } ipi;
> + u32 (*read_iar)(void);
> + u32 (*irqnr)(u32 iar);
> + void (*write_eoi)(u32);
> +};
> +
> +static struct gic *gic;
>  static int gic_version;
>  static int acked[NR_CPUS], spurious[NR_CPUS];
>  static cpumask_t ready;
> @@ -69,13 +84,33 @@ static void check_acked(cpumask_t *mask)
>  false, missing, extra, unexpected);
>  }
>
> +static u32 gicv2_read_iar(void)
> +{
> + return readl(gicv2_cpu_base() + GICC_IAR);
> +}
> +
> +static u32 gicv2_irqnr(u32 iar)
> +{
> + return iar & GICC_IAR_INT_ID_MASK;
> +}
> +
> +static void gicv2_write_eoi(u32 irqstat)
> +{
> + writel(irqstat, gicv2_cpu_base() + GICC_EOIR);
> +}
> +
> +static u32 gicv3_irqnr(u32 iar)
> +{
> + return iar;
> +}
> +
>  static void ipi_handler(struct pt_regs *regs __unused)
>  {
> - u32 irqstat = readl(gicv2_cpu_base() + GICC_IAR);
> - u32 irqnr = irqstat & GICC_IAR_INT_ID_MASK;
> + u32 irqstat = gic->read_iar();
> + u32 irqnr = gic->irqnr(irqstat);
>
>   if (irqnr != GICC_INT_SPURIOUS) {
> - writel(irqstat, gicv2_cpu_base() + GICC_EOIR);
> + gic->write_eoi(irqstat);
>   smp_rmb(); /* pairs with wmb in ipi_test functions */
>   ++acked[smp_processor_id()];
>   smp_wmb(); /* pairs with rmb in check_acked */
> @@ -85,6 +120,112 @@ static void ipi_handler(struct pt_regs *regs __unused)
>   }
>  }
>
> +static void gicv2_ipi_send_self(void)
> +{
> + writel(2 << 24, gicv2_dist_base() + GICD_SGIR);
> +}
> +
> +static void gicv2_ipi_send_tlist(cpumask_t *mask)
> +{
> + u8 tlist = (u8)cpumask_bits(mask)[0];
> +
> + writel(tlist << 16, gicv2_dist_base() + GICD_SGIR);
> +}
> +
> +static void gicv2_ipi_send_broadcast(void)
> +{
> + writel(1 << 24, gicv2_dist_base() + GICD_SGIR);
> +}
> +
> +#define ICC_SGI1R_AFFINITY_1_SHIFT   16
> +#define ICC_SGI1R_AFFINITY_2_SHIFT   32
> +#define ICC_SGI1R_AFFINITY_3_SHIFT   48
> +#define MPIDR_TO_SGI_AFFINITY(cluster_id, level) \
> + (MPIDR_AFFINITY_LEVEL(cluster_id, level) << ICC_SGI1R_AFFINITY_## level 
> ## _SHIFT)
> +
> +static void gicv3_ipi_send_tlist(cpumask_t *mask)
> +{
> + u16 tlist;
> + int cpu;
> +
> + /*
> +  * For each cpu in the mask collect its peers, which are also in
> +  * the mask, in order to form target lists.
> +  */
> + for_each_cpu(cpu, mask) {
> + u64 mpidr = cpus[cpu], sgi1r;
> + u64 cluster_id;
> +
> + /*
> +  * GICv3 can send IPIs to up 16 peer cpus with a single
> +  * write to ICC_SGI1R_EL1 (using the target list). Peers
> +  * are cpus that have nearly identical MPIDRs, the only
> +  * difference being Aff0. The matching upper affinity
> +  * levels form the cluster ID.
> +  */
> + cluster_id = mpidr & ~0xffUL;
> + tlist = 0;
> +
> + /*
> +  * Sort of open code for_each_cpu in order to have a
> +  * nested for_each_cpu loop.
> +  */
> + while (cpu < nr_cpus) {
> + if ((mpidr & 0xff) >= 16) {
> + printf("cpu%d MPIDR:aff0 is %d (>= 16)!\n",
> + cpu, (int)(mpidr & 0xff));
> + break;
> + }
> +
> + tlist |= 1 << (mpidr & 0xf);
> +
> + cpu = cpumask_next(cpu, mask);
> + if (cpu >= nr_cpus)
> + break;
> +
> + mpidr = cpus[cpu];
> +
> + if (cluster_id != (mpidr & ~0xffUL)) {
> + /*
> +  * The next cpu isn't in our cluster. 

Re: [PATCH 1/2] arm64: perf: Move ARMv8 PMU perf event definitions to asm/perf_event.h

2016-11-10 Thread Wei Huang


On 11/10/2016 11:17 AM, Will Deacon wrote:
> On Thu, Nov 10, 2016 at 03:32:12PM +, Marc Zyngier wrote:
>> On 10/11/16 15:12, Wei Huang wrote:
>>>
>>>
>>> On 11/10/2016 03:10 AM, Marc Zyngier wrote:
 Hi Wei,

 On 09/11/16 19:57, Wei Huang wrote:
> This patch moves ARMv8-related perf event definitions from perf_event.c
> to asm/perf_event.h; so KVM code can use them directly. This also help
> remove a duplicated definition of SW_INCR in perf_event.h.
>
> Signed-off-by: Wei Huang 
> ---
>  arch/arm64/include/asm/perf_event.h | 161 
> +++-
>  arch/arm64/kernel/perf_event.c  | 161 
> 
>  2 files changed, 160 insertions(+), 162 deletions(-)
>
> diff --git a/arch/arm64/include/asm/perf_event.h 
> b/arch/arm64/include/asm/perf_event.h
> index 2065f46..6c7b18b 100644
> --- a/arch/arm64/include/asm/perf_event.h
> +++ b/arch/arm64/include/asm/perf_event.h
> @@ -46,7 +46,166 @@
>  #define  ARMV8_PMU_EVTYPE_MASK   0xc800  /* Mask for writable 
> bits */
>  #define  ARMV8_PMU_EVTYPE_EVENT  0x  /* Mask for EVENT bits 
> */
>  
> -#define ARMV8_PMU_EVTYPE_EVENT_SW_INCR   0   /* Software increment 
> event */
> +/*
> + * ARMv8 PMUv3 Performance Events handling code.
> + * Common event types.
> + */
> +
> +/* Required events. */
> +#define ARMV8_PMUV3_PERFCTR_SW_INCR  0x00
> +#define ARMV8_PMUV3_PERFCTR_L1D_CACHE_REFILL 0x03
> +#define ARMV8_PMUV3_PERFCTR_L1D_CACHE0x04
> +#define ARMV8_PMUV3_PERFCTR_BR_MIS_PRED  0x10
> +#define ARMV8_PMUV3_PERFCTR_CPU_CYCLES   0x11
> +#define ARMV8_PMUV3_PERFCTR_BR_PRED  0x12

 In my initial review, I asked for the "required" events to be moved to a
 shared location. What's the rational for moving absolutely everything?
>>>
>>> I did notice the phrase "required" in the original email. However I
>>> think it is weird to have two places for a same set of PMU definitions.
>>> Other developers might think these two are missing if they don't search
>>> kernel files carefully.
>>>
>>> If Will Deacon and you insist, I can move only two defs to perf_event.h,
>>> consolidated with the 2nd patch into a single one.
>>
>> My personal feeling is that only architected events should be in a
>> public header. The CPU-specific ones are probably better kept private,
>> as it is doubtful that other users would appear).
>>
>> I'll leave it up to Will to decide, as all I want to avoid is the
>> duplication of constants between the PMU and KVM code bases.
> 
> Yeah, just take the sets that you need (i.e. the architected events).

Hi Will,

Just to clarify what "architected" means:

We need two for KVM: SW_INCR (architectural) and CPU_CYCLES
(micro-architectural). Looking at perf_event.c file, I can either
relocate the  "Required events" (6 events) or the whole set of
ARMV8_PMUV3_PERFCTR_* (~50 events) to perf_event.h. Which way you prefer?

Thanks,
-Wei

> 
> Also, check that it builds.
> 
> Will
> --
> To unsubscribe from this list: send the line "unsubscribe kvm" 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


[kvm-unit-tests PATCH v5 10/11] arm/arm64: gicv3: add an IPI test

2016-11-10 Thread Andrew Jones
Signed-off-by: Andrew Jones 

---
v5:
 - fix copy+paste error in gicv3_write_eoir [drew]
 - use modern register names [Andre]
v4:
 - heavily comment gicv3_ipi_send_tlist() [Eric]
 - changes needed for gicv2 iar/irqstat fix to other patch
v2:
 - use IRM for gicv3 broadcast
---
 arm/gic.c  | 195 ++---
 arm/unittests.cfg  |   6 ++
 lib/arm/asm/arch_gicv3.h   |  23 ++
 lib/arm64/asm/arch_gicv3.h |  22 +
 4 files changed, 236 insertions(+), 10 deletions(-)

diff --git a/arm/gic.c b/arm/gic.c
index 06092aec7c08..ca68f8ad1cb9 100644
--- a/arm/gic.c
+++ b/arm/gic.c
@@ -3,6 +3,8 @@
  *
  * GICv2
  *   + test sending/receiving IPIs
+ * GICv3
+ *   + test sending/receiving IPIs
  *
  * Copyright (C) 2016, Red Hat Inc, Andrew Jones 
  *
@@ -16,6 +18,19 @@
 #include 
 #include 
 
+struct gic {
+   struct {
+   void (*enable)(void);
+   void (*send_self)(void);
+   void (*send_tlist)(cpumask_t *);
+   void (*send_broadcast)(void);
+   } ipi;
+   u32 (*read_iar)(void);
+   u32 (*irqnr)(u32 iar);
+   void (*write_eoi)(u32);
+};
+
+static struct gic *gic;
 static int gic_version;
 static int acked[NR_CPUS], spurious[NR_CPUS];
 static cpumask_t ready;
@@ -69,13 +84,33 @@ static void check_acked(cpumask_t *mask)
   false, missing, extra, unexpected);
 }
 
+static u32 gicv2_read_iar(void)
+{
+   return readl(gicv2_cpu_base() + GICC_IAR);
+}
+
+static u32 gicv2_irqnr(u32 iar)
+{
+   return iar & GICC_IAR_INT_ID_MASK;
+}
+
+static void gicv2_write_eoi(u32 irqstat)
+{
+   writel(irqstat, gicv2_cpu_base() + GICC_EOIR);
+}
+
+static u32 gicv3_irqnr(u32 iar)
+{
+   return iar;
+}
+
 static void ipi_handler(struct pt_regs *regs __unused)
 {
-   u32 irqstat = readl(gicv2_cpu_base() + GICC_IAR);
-   u32 irqnr = irqstat & GICC_IAR_INT_ID_MASK;
+   u32 irqstat = gic->read_iar();
+   u32 irqnr = gic->irqnr(irqstat);
 
if (irqnr != GICC_INT_SPURIOUS) {
-   writel(irqstat, gicv2_cpu_base() + GICC_EOIR);
+   gic->write_eoi(irqstat);
smp_rmb(); /* pairs with wmb in ipi_test functions */
++acked[smp_processor_id()];
smp_wmb(); /* pairs with rmb in check_acked */
@@ -85,6 +120,112 @@ static void ipi_handler(struct pt_regs *regs __unused)
}
 }
 
+static void gicv2_ipi_send_self(void)
+{
+   writel(2 << 24, gicv2_dist_base() + GICD_SGIR);
+}
+
+static void gicv2_ipi_send_tlist(cpumask_t *mask)
+{
+   u8 tlist = (u8)cpumask_bits(mask)[0];
+
+   writel(tlist << 16, gicv2_dist_base() + GICD_SGIR);
+}
+
+static void gicv2_ipi_send_broadcast(void)
+{
+   writel(1 << 24, gicv2_dist_base() + GICD_SGIR);
+}
+
+#define ICC_SGI1R_AFFINITY_1_SHIFT 16
+#define ICC_SGI1R_AFFINITY_2_SHIFT 32
+#define ICC_SGI1R_AFFINITY_3_SHIFT 48
+#define MPIDR_TO_SGI_AFFINITY(cluster_id, level) \
+   (MPIDR_AFFINITY_LEVEL(cluster_id, level) << ICC_SGI1R_AFFINITY_## level 
## _SHIFT)
+
+static void gicv3_ipi_send_tlist(cpumask_t *mask)
+{
+   u16 tlist;
+   int cpu;
+
+   /*
+* For each cpu in the mask collect its peers, which are also in
+* the mask, in order to form target lists.
+*/
+   for_each_cpu(cpu, mask) {
+   u64 mpidr = cpus[cpu], sgi1r;
+   u64 cluster_id;
+
+   /*
+* GICv3 can send IPIs to up 16 peer cpus with a single
+* write to ICC_SGI1R_EL1 (using the target list). Peers
+* are cpus that have nearly identical MPIDRs, the only
+* difference being Aff0. The matching upper affinity
+* levels form the cluster ID.
+*/
+   cluster_id = mpidr & ~0xffUL;
+   tlist = 0;
+
+   /*
+* Sort of open code for_each_cpu in order to have a
+* nested for_each_cpu loop.
+*/
+   while (cpu < nr_cpus) {
+   if ((mpidr & 0xff) >= 16) {
+   printf("cpu%d MPIDR:aff0 is %d (>= 16)!\n",
+   cpu, (int)(mpidr & 0xff));
+   break;
+   }
+
+   tlist |= 1 << (mpidr & 0xf);
+
+   cpu = cpumask_next(cpu, mask);
+   if (cpu >= nr_cpus)
+   break;
+
+   mpidr = cpus[cpu];
+
+   if (cluster_id != (mpidr & ~0xffUL)) {
+   /*
+* The next cpu isn't in our cluster. Roll
+* back the cpu index allowing the outer
+* for_each_cpu to find it again with
+* cpumask_next
+   

[kvm-unit-tests PATCH v5 07/11] arm/arm64: gicv2: add an IPI test

2016-11-10 Thread Andrew Jones
Reviewed-by: Eric Auger 
Signed-off-by: Andrew Jones 
---
v5: use modern registers [Andre]
v4: properly mask irqnr in ipi_handler
v2: add more details in the output if a test fails,
report spurious interrupts if we get them
---
 arm/Makefile.common  |   6 +-
 arm/gic.c| 195 +++
 arm/unittests.cfg|   7 ++
 lib/arm/asm/gic-v2.h |   2 +
 lib/arm/asm/gic.h|   4 ++
 5 files changed, 211 insertions(+), 3 deletions(-)
 create mode 100644 arm/gic.c

diff --git a/arm/Makefile.common b/arm/Makefile.common
index 41239c37e092..bc38183ab86e 100644
--- a/arm/Makefile.common
+++ b/arm/Makefile.common
@@ -9,9 +9,9 @@ ifeq ($(LOADADDR),)
LOADADDR = 0x4000
 endif
 
-tests-common = \
-   $(TEST_DIR)/selftest.flat \
-   $(TEST_DIR)/spinlock-test.flat
+tests-common  = $(TEST_DIR)/selftest.flat
+tests-common += $(TEST_DIR)/spinlock-test.flat
+tests-common += $(TEST_DIR)/gic.flat
 
 all: test_cases
 
diff --git a/arm/gic.c b/arm/gic.c
new file mode 100644
index ..06092aec7c08
--- /dev/null
+++ b/arm/gic.c
@@ -0,0 +1,195 @@
+/*
+ * GIC tests
+ *
+ * GICv2
+ *   + test sending/receiving IPIs
+ *
+ * Copyright (C) 2016, Red Hat Inc, Andrew Jones 
+ *
+ * This work is licensed under the terms of the GNU LGPL, version 2.
+ */
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+static int gic_version;
+static int acked[NR_CPUS], spurious[NR_CPUS];
+static cpumask_t ready;
+
+static void nr_cpu_check(int nr)
+{
+   if (nr_cpus < nr)
+   report_abort("At least %d cpus required", nr);
+}
+
+static void wait_on_ready(void)
+{
+   cpumask_set_cpu(smp_processor_id(), );
+   while (!cpumask_full())
+   cpu_relax();
+}
+
+static void check_acked(cpumask_t *mask)
+{
+   int missing = 0, extra = 0, unexpected = 0;
+   int nr_pass, cpu, i;
+
+   /* Wait up to 5s for all interrupts to be delivered */
+   for (i = 0; i < 50; ++i) {
+   mdelay(100);
+   nr_pass = 0;
+   for_each_present_cpu(cpu) {
+   smp_rmb();
+   nr_pass += cpumask_test_cpu(cpu, mask) ?
+   acked[cpu] == 1 : acked[cpu] == 0;
+   }
+   if (nr_pass == nr_cpus) {
+   report("Completed in %d ms", true, ++i * 100);
+   return;
+   }
+   }
+
+   for_each_present_cpu(cpu) {
+   if (cpumask_test_cpu(cpu, mask)) {
+   if (!acked[cpu])
+   ++missing;
+   else if (acked[cpu] > 1)
+   ++extra;
+   } else {
+   if (acked[cpu])
+   ++unexpected;
+   }
+   }
+
+   report("Timed-out (5s). ACKS: missing=%d extra=%d unexpected=%d",
+  false, missing, extra, unexpected);
+}
+
+static void ipi_handler(struct pt_regs *regs __unused)
+{
+   u32 irqstat = readl(gicv2_cpu_base() + GICC_IAR);
+   u32 irqnr = irqstat & GICC_IAR_INT_ID_MASK;
+
+   if (irqnr != GICC_INT_SPURIOUS) {
+   writel(irqstat, gicv2_cpu_base() + GICC_EOIR);
+   smp_rmb(); /* pairs with wmb in ipi_test functions */
+   ++acked[smp_processor_id()];
+   smp_wmb(); /* pairs with rmb in check_acked */
+   } else {
+   ++spurious[smp_processor_id()];
+   smp_wmb();
+   }
+}
+
+static void ipi_test_self(void)
+{
+   cpumask_t mask;
+
+   report_prefix_push("self");
+   memset(acked, 0, sizeof(acked));
+   smp_wmb();
+   cpumask_clear();
+   cpumask_set_cpu(0, );
+   writel(2 << 24, gicv2_dist_base() + GICD_SGIR);
+   check_acked();
+   report_prefix_pop();
+}
+
+static void ipi_test_smp(void)
+{
+   cpumask_t mask;
+   unsigned long tlist;
+
+   report_prefix_push("target-list");
+   memset(acked, 0, sizeof(acked));
+   smp_wmb();
+   tlist = cpumask_bits(_present_mask)[0] & 0xaa;
+   cpumask_bits()[0] = tlist;
+   writel((u8)tlist << 16, gicv2_dist_base() + GICD_SGIR);
+   check_acked();
+   report_prefix_pop();
+
+   report_prefix_push("broadcast");
+   memset(acked, 0, sizeof(acked));
+   smp_wmb();
+   cpumask_copy(, _present_mask);
+   cpumask_clear_cpu(0, );
+   writel(1 << 24, gicv2_dist_base() + GICD_SGIR);
+   check_acked();
+   report_prefix_pop();
+}
+
+static void ipi_enable(void)
+{
+   gicv2_enable_defaults();
+#ifdef __arm__
+   install_exception_handler(EXCPTN_IRQ, ipi_handler);
+#else
+   install_irq_handler(EL1H_IRQ, ipi_handler);
+#endif
+   local_irq_enable();
+}
+
+static void ipi_recv(void)
+{
+   ipi_enable();
+   cpumask_set_cpu(smp_processor_id(), );
+   while (1)
+  

[kvm-unit-tests PATCH v5 11/11] arm/arm64: gic: don't just use zero

2016-11-10 Thread Andrew Jones
Allow user to select who sends ipis and with which irq,
rather than just always sending irq=0 from cpu0.

Signed-off-by: Andrew Jones 

---
v4: improve structure and make sure spurious checking is
done even when the sender isn't cpu0
v2: actually check that the irq received was the irq sent,
and (for gicv2) that the sender is the expected one.
---
 arm/gic.c | 99 ++-
 1 file changed, 73 insertions(+), 26 deletions(-)

diff --git a/arm/gic.c b/arm/gic.c
index ca68f8ad1cb9..af9e745e2e5c 100644
--- a/arm/gic.c
+++ b/arm/gic.c
@@ -11,6 +11,7 @@
  * This work is licensed under the terms of the GNU LGPL, version 2.
  */
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -34,6 +35,8 @@ static struct gic *gic;
 static int gic_version;
 static int acked[NR_CPUS], spurious[NR_CPUS];
 static cpumask_t ready;
+static int sender;
+static u32 irq;
 
 static void nr_cpu_check(int nr)
 {
@@ -86,7 +89,16 @@ static void check_acked(cpumask_t *mask)
 
 static u32 gicv2_read_iar(void)
 {
-   return readl(gicv2_cpu_base() + GICC_IAR);
+   u32 iar = readl(gicv2_cpu_base() + GICC_IAR);
+   int src = (iar >> 10) & 7;
+
+   if (src != sender) {
+   report("cpu%d received IPI from unexpected source cpu%d "
+  "(expected cpu%d)",
+  false, smp_processor_id(), src, sender);
+   }
+
+   return iar;
 }
 
 static u32 gicv2_irqnr(u32 iar)
@@ -111,9 +123,15 @@ static void ipi_handler(struct pt_regs *regs __unused)
 
if (irqnr != GICC_INT_SPURIOUS) {
gic->write_eoi(irqstat);
-   smp_rmb(); /* pairs with wmb in ipi_test functions */
-   ++acked[smp_processor_id()];
-   smp_wmb(); /* pairs with rmb in check_acked */
+   if (irqnr == irq) {
+   smp_rmb(); /* pairs with wmb in ipi_test functions */
+   ++acked[smp_processor_id()];
+   smp_wmb(); /* pairs with rmb in check_acked */
+   } else {
+   report("cpu%d received unexpected irq %u "
+  "(expected %u)",
+  false, smp_processor_id(), irqnr, irq);
+   }
} else {
++spurious[smp_processor_id()];
smp_wmb();
@@ -122,19 +140,19 @@ static void ipi_handler(struct pt_regs *regs __unused)
 
 static void gicv2_ipi_send_self(void)
 {
-   writel(2 << 24, gicv2_dist_base() + GICD_SGIR);
+   writel(2 << 24 | irq, gicv2_dist_base() + GICD_SGIR);
 }
 
 static void gicv2_ipi_send_tlist(cpumask_t *mask)
 {
u8 tlist = (u8)cpumask_bits(mask)[0];
 
-   writel(tlist << 16, gicv2_dist_base() + GICD_SGIR);
+   writel(tlist << 16 | irq, gicv2_dist_base() + GICD_SGIR);
 }
 
 static void gicv2_ipi_send_broadcast(void)
 {
-   writel(1 << 24, gicv2_dist_base() + GICD_SGIR);
+   writel(1 << 24 | irq, gicv2_dist_base() + GICD_SGIR);
 }
 
 #define ICC_SGI1R_AFFINITY_1_SHIFT 16
@@ -200,7 +218,7 @@ static void gicv3_ipi_send_tlist(cpumask_t *mask)
/* Send the IPIs for the target list of this cluster */
sgi1r = (MPIDR_TO_SGI_AFFINITY(cluster_id, 3)   |
 MPIDR_TO_SGI_AFFINITY(cluster_id, 2)   |
-/* irq << 24   | */
+irq << 24  |
 MPIDR_TO_SGI_AFFINITY(cluster_id, 1)   |
 tlist);
 
@@ -222,7 +240,7 @@ static void gicv3_ipi_send_self(void)
 
 static void gicv3_ipi_send_broadcast(void)
 {
-   gicv3_write_sgi1r(1ULL << 40);
+   gicv3_write_sgi1r(1ULL << 40 | irq << 24);
isb();
 }
 
@@ -234,7 +252,7 @@ static void ipi_test_self(void)
memset(acked, 0, sizeof(acked));
smp_wmb();
cpumask_clear();
-   cpumask_set_cpu(0, );
+   cpumask_set_cpu(smp_processor_id(), );
gic->ipi.send_self();
check_acked();
report_prefix_pop();
@@ -249,7 +267,7 @@ static void ipi_test_smp(void)
memset(acked, 0, sizeof(acked));
smp_wmb();
cpumask_copy(, _present_mask);
-   for (i = 0; i < nr_cpus; i += 2)
+   for (i = smp_processor_id() & 1; i < nr_cpus; i += 2)
cpumask_clear_cpu(i, );
gic->ipi.send_tlist();
check_acked();
@@ -259,7 +277,7 @@ static void ipi_test_smp(void)
memset(acked, 0, sizeof(acked));
smp_wmb();
cpumask_copy(, _present_mask);
-   cpumask_clear_cpu(0, );
+   cpumask_clear_cpu(smp_processor_id(), );
gic->ipi.send_broadcast();
check_acked();
report_prefix_pop();
@@ -276,6 +294,27 @@ static void ipi_enable(void)
local_irq_enable();
 }
 
+static void ipi_send(void)
+{
+   int cpu;
+
+   ipi_enable();
+   wait_on_ready();
+   ipi_test_self();
+   

[kvm-unit-tests PATCH v5 03/11] arm/arm64: smp: support more than 8 cpus

2016-11-10 Thread Andrew Jones
By adding support for launching with gicv3 we can break the 8 vcpu
limit. This patch adds support to smp code and also selects the
vgic model corresponding to the host. The vgic model may also be
manually selected by adding e.g. -machine gic-version=3 to
extra_params.

Reviewed-by: Alex Bennée 
Signed-off-by: Andrew Jones 

---
v5: left cpus a u32 for now. Changing to u64 requires a change to
devicetree. Will do it later. [Andre]
v4: improved commit message
---
 arm/run   | 19 ---
 arm/selftest.c|  5 -
 lib/arm/asm/processor.h   |  9 +++--
 lib/arm/asm/setup.h   |  4 ++--
 lib/arm/setup.c   | 10 ++
 lib/arm64/asm/processor.h |  9 +++--
 6 files changed, 42 insertions(+), 14 deletions(-)

diff --git a/arm/run b/arm/run
index a2f35ef6a7e6..2d0698619606 100755
--- a/arm/run
+++ b/arm/run
@@ -31,13 +31,6 @@ if [ -z "$ACCEL" ]; then
fi
 fi
 
-if [ "$HOST" = "aarch64" ] && [ "$ACCEL" = "kvm" ]; then
-   processor="host"
-   if [ "$ARCH" = "arm" ]; then
-   processor+=",aarch64=off"
-   fi
-fi
-
 qemu="${QEMU:-qemu-system-$ARCH_NAME}"
 qpath=$(which $qemu 2>/dev/null)
 
@@ -53,6 +46,18 @@ fi
 
 M='-machine virt'
 
+if [ "$ACCEL" = "kvm" ]; then
+   if $qemu $M,\? 2>&1 | grep gic-version > /dev/null; then
+   M+=',gic-version=host'
+   fi
+   if [ "$HOST" = "aarch64" ]; then
+   processor="host"
+   if [ "$ARCH" = "arm" ]; then
+   processor+=",aarch64=off"
+   fi
+   fi
+fi
+
 if ! $qemu $M -device '?' 2>&1 | grep virtconsole > /dev/null; then
echo "$qpath doesn't support virtio-console for chr-testdev. Exiting."
exit 2
diff --git a/arm/selftest.c b/arm/selftest.c
index 196164f5313d..2f117f795d2d 100644
--- a/arm/selftest.c
+++ b/arm/selftest.c
@@ -312,9 +312,10 @@ static bool psci_check(void)
 static cpumask_t smp_reported;
 static void cpu_report(void)
 {
+   unsigned long mpidr = get_mpidr();
int cpu = smp_processor_id();
 
-   report("CPU%d online", true, cpu);
+   report("CPU(%3d) mpidr=%lx", mpidr_to_cpu(mpidr) == cpu, cpu, mpidr);
cpumask_set_cpu(cpu, _reported);
halt();
 }
@@ -343,6 +344,7 @@ int main(int argc, char **argv)
 
} else if (strcmp(argv[1], "smp") == 0) {
 
+   unsigned long mpidr = get_mpidr();
int cpu;
 
report("PSCI version", psci_check());
@@ -353,6 +355,7 @@ int main(int argc, char **argv)
smp_boot_secondary(cpu, cpu_report);
}
 
+   report("CPU(%3d) mpidr=%lx", mpidr_to_cpu(mpidr) == 0, 0, 
mpidr);
cpumask_set_cpu(0, _reported);
while (!cpumask_full(_reported))
cpu_relax();
diff --git a/lib/arm/asm/processor.h b/lib/arm/asm/processor.h
index 02f912f99974..ecf5bbe1824a 100644
--- a/lib/arm/asm/processor.h
+++ b/lib/arm/asm/processor.h
@@ -40,8 +40,13 @@ static inline unsigned long get_mpidr(void)
return mpidr;
 }
 
-/* Only support Aff0 for now, up to 4 cpus */
-#define mpidr_to_cpu(mpidr) ((int)((mpidr) & 0xff))
+#define MPIDR_HWID_BITMASK 0xff
+extern int mpidr_to_cpu(unsigned long mpidr);
+
+#define MPIDR_LEVEL_SHIFT(level) \
+   (((1 << level) >> 1) << 3)
+#define MPIDR_AFFINITY_LEVEL(mpidr, level) \
+   ((mpidr >> MPIDR_LEVEL_SHIFT(level)) & 0xff)
 
 extern void start_usr(void (*func)(void *arg), void *arg, unsigned long 
sp_usr);
 extern bool is_user(void);
diff --git a/lib/arm/asm/setup.h b/lib/arm/asm/setup.h
index cb8fdbd38dd5..1de99dd184d1 100644
--- a/lib/arm/asm/setup.h
+++ b/lib/arm/asm/setup.h
@@ -10,8 +10,8 @@
 #include 
 #include 
 
-#define NR_CPUS8
-extern u32 cpus[NR_CPUS];
+#define NR_CPUS255
+extern u32 cpus[NR_CPUS];  /* per-cpu IDs (MPIDRs) */
 extern int nr_cpus;
 
 #define NR_MEM_REGIONS 8
diff --git a/lib/arm/setup.c b/lib/arm/setup.c
index 7e7b39f11dde..241bf9410447 100644
--- a/lib/arm/setup.c
+++ b/lib/arm/setup.c
@@ -30,6 +30,16 @@ int nr_cpus;
 struct mem_region mem_regions[NR_MEM_REGIONS];
 phys_addr_t __phys_offset, __phys_end;
 
+int mpidr_to_cpu(unsigned long mpidr)
+{
+   int i;
+
+   for (i = 0; i < nr_cpus; ++i)
+   if (cpus[i] == (mpidr & MPIDR_HWID_BITMASK))
+   return i;
+   return -1;
+}
+
 static void cpu_set(int fdtnode __unused, u32 regval, void *info __unused)
 {
int cpu = nr_cpus++;
diff --git a/lib/arm64/asm/processor.h b/lib/arm64/asm/processor.h
index 9a208ff729b7..7e448dc81a6a 100644
--- a/lib/arm64/asm/processor.h
+++ b/lib/arm64/asm/processor.h
@@ -78,8 +78,13 @@ static inline type get_##reg(void)   
\
 
 DEFINE_GET_SYSREG64(mpidr)
 
-/* Only support Aff0 for now, gicv2 only */
-#define mpidr_to_cpu(mpidr) ((int)((mpidr) & 0xff))
+#define 

[kvm-unit-tests PATCH v5 09/11] arm/arm64: add initial gicv3 support

2016-11-10 Thread Andrew Jones
Signed-off-by: Andrew Jones 

---
v5: use modern register names [Andre]
v4:
 - only take defines from kernel we need now [Andre]
 - simplify enable by not caring if we reinit the distributor [drew]
v2:
 - configure irqs as NS GRP1
---
 lib/arm/asm/arch_gicv3.h   | 42 +
 lib/arm/asm/gic-v3.h   | 94 ++
 lib/arm/asm/gic.h  |  6 ++-
 lib/arm/gic.c  | 65 
 lib/arm64/asm/arch_gicv3.h | 44 ++
 lib/arm64/asm/gic-v3.h |  1 +
 lib/arm64/asm/sysreg.h | 44 ++
 7 files changed, 294 insertions(+), 2 deletions(-)
 create mode 100644 lib/arm/asm/arch_gicv3.h
 create mode 100644 lib/arm/asm/gic-v3.h
 create mode 100644 lib/arm64/asm/arch_gicv3.h
 create mode 100644 lib/arm64/asm/gic-v3.h
 create mode 100644 lib/arm64/asm/sysreg.h

diff --git a/lib/arm/asm/arch_gicv3.h b/lib/arm/asm/arch_gicv3.h
new file mode 100644
index ..81a1e5f6c29c
--- /dev/null
+++ b/lib/arm/asm/arch_gicv3.h
@@ -0,0 +1,42 @@
+/*
+ * All ripped off from arch/arm/include/asm/arch_gicv3.h
+ *
+ * Copyright (C) 2016, Red Hat Inc, Andrew Jones 
+ *
+ * This work is licensed under the terms of the GNU LGPL, version 2.
+ */
+#ifndef _ASMARM_ARCH_GICV3_H_
+#define _ASMARM_ARCH_GICV3_H_
+
+#ifndef __ASSEMBLY__
+#include 
+#include 
+#include 
+
+#define __stringify xstr
+
+#define __ACCESS_CP15(CRn, Op1, CRm, Op2)  p15, Op1, %0, CRn, CRm, Op2
+
+#define ICC_PMR__ACCESS_CP15(c4, 0, c6, 0)
+#define ICC_IGRPEN1__ACCESS_CP15(c12, 0, c12, 7)
+
+static inline void gicv3_write_pmr(u32 val)
+{
+   asm volatile("mcr " __stringify(ICC_PMR) : : "r" (val));
+}
+
+static inline void gicv3_write_grpen1(u32 val)
+{
+   asm volatile("mcr " __stringify(ICC_IGRPEN1) : : "r" (val));
+   isb();
+}
+
+static inline u64 gicv3_read_typer(const volatile void __iomem *addr)
+{
+   u64 val = readl(addr);
+   val |= (u64)readl(addr + 4) << 32;
+   return val;
+}
+
+#endif /* !__ASSEMBLY__ */
+#endif /* _ASMARM_ARCH_GICV3_H_ */
diff --git a/lib/arm/asm/gic-v3.h b/lib/arm/asm/gic-v3.h
new file mode 100644
index ..e0f303d82508
--- /dev/null
+++ b/lib/arm/asm/gic-v3.h
@@ -0,0 +1,94 @@
+/*
+ * All GIC* defines are lifted from include/linux/irqchip/arm-gic-v3.h
+ *
+ * Copyright (C) 2016, Red Hat Inc, Andrew Jones 
+ *
+ * This work is licensed under the terms of the GNU LGPL, version 2.
+ */
+#ifndef _ASMARM_GIC_V3_H_
+#define _ASMARM_GIC_V3_H_
+
+#ifndef _ASMARM_GIC_H_
+#error Do not directly include . Include 
+#endif
+
+#define GICD_CTLR_RWP  (1U << 31)
+#define GICD_CTLR_ARE_NS   (1U << 4)
+#define GICD_CTLR_ENABLE_G1A   (1U << 1)
+#define GICD_CTLR_ENABLE_G1(1U << 0)
+
+/* Re-Distributor registers, offsets from RD_base */
+#define GICR_TYPER 0x0008
+
+#define GICR_TYPER_LAST(1U << 4)
+
+/* Re-Distributor registers, offsets from SGI_base */
+#define GICR_IGROUPR0  GICD_IGROUPR
+#define GICR_ISENABLER0GICD_ISENABLER
+#define GICR_IPRIORITYR0   GICD_IPRIORITYR
+
+#include 
+
+#ifndef __ASSEMBLY__
+#include 
+#include 
+#include 
+#include 
+
+struct gicv3_data {
+   void *dist_base;
+   void *redist_base[NR_CPUS];
+   unsigned int irq_nr;
+};
+extern struct gicv3_data gicv3_data;
+
+#define gicv3_dist_base()  (gicv3_data.dist_base)
+#define gicv3_redist_base()
(gicv3_data.redist_base[smp_processor_id()])
+#define gicv3_sgi_base()   
(gicv3_data.redist_base[smp_processor_id()] + SZ_64K)
+
+extern int gicv3_init(void);
+extern void gicv3_enable_defaults(void);
+extern void gicv3_set_redist_base(void);
+
+static inline void gicv3_do_wait_for_rwp(void *base)
+{
+   int count = 10; /* 1s */
+
+   while (readl(base + GICD_CTLR) & GICD_CTLR_RWP) {
+   if (!--count) {
+   printf("GICv3: RWP timeout!\n");
+   abort();
+   }
+   cpu_relax();
+   udelay(10);
+   };
+}
+
+static inline void gicv3_dist_wait_for_rwp(void)
+{
+   gicv3_do_wait_for_rwp(gicv3_dist_base());
+}
+
+static inline void gicv3_redist_wait_for_rwp(void)
+{
+   gicv3_do_wait_for_rwp(gicv3_redist_base());
+}
+
+static inline u32 mpidr_compress(u64 mpidr)
+{
+   u64 compressed = mpidr & MPIDR_HWID_BITMASK;
+
+   compressed = (((compressed >> 32) & 0xff) << 24) | compressed;
+   return compressed;
+}
+
+static inline u64 mpidr_uncompress(u32 compressed)
+{
+   u64 mpidr = ((u64)compressed >> 24) << 32;
+
+   mpidr |= compressed & MPIDR_HWID_BITMASK;
+   return mpidr;
+}
+
+#endif /* !__ASSEMBLY__ */
+#endif /* _ASMARM_GIC_V3_H_ */
diff --git a/lib/arm/asm/gic.h b/lib/arm/asm/gic.h

[kvm-unit-tests PATCH v5 04/11] arm/arm64: add some delay routines

2016-11-10 Thread Andrew Jones
Allow a thread to wait some specified amount of time. Can
specify in cycles, usecs, and msecs.

Reviewed-by: Alex Bennée 
Reviewed-by: Eric Auger 
Signed-off-by: Andrew Jones 
---
 lib/arm/asm/processor.h   | 19 +++
 lib/arm/processor.c   | 15 +++
 lib/arm64/asm/processor.h | 19 +++
 lib/arm64/processor.c | 15 +++
 4 files changed, 68 insertions(+)

diff --git a/lib/arm/asm/processor.h b/lib/arm/asm/processor.h
index ecf5bbe1824a..bc46d1f980ee 100644
--- a/lib/arm/asm/processor.h
+++ b/lib/arm/asm/processor.h
@@ -5,7 +5,9 @@
  *
  * This work is licensed under the terms of the GNU LGPL, version 2.
  */
+#include 
 #include 
+#include 
 
 enum vector {
EXCPTN_RST,
@@ -51,4 +53,21 @@ extern int mpidr_to_cpu(unsigned long mpidr);
 extern void start_usr(void (*func)(void *arg), void *arg, unsigned long 
sp_usr);
 extern bool is_user(void);
 
+static inline u64 get_cntvct(void)
+{
+   u64 vct;
+   isb();
+   asm volatile("mrrc p15, 1, %Q0, %R0, c14" : "=r" (vct));
+   return vct;
+}
+
+extern void delay(u64 cycles);
+extern void udelay(unsigned long usecs);
+
+static inline void mdelay(unsigned long msecs)
+{
+   while (msecs--)
+   udelay(1000);
+}
+
 #endif /* _ASMARM_PROCESSOR_H_ */
diff --git a/lib/arm/processor.c b/lib/arm/processor.c
index 54fdb87ef019..c2ee360df688 100644
--- a/lib/arm/processor.c
+++ b/lib/arm/processor.c
@@ -9,6 +9,7 @@
 #include 
 #include 
 #include 
+#include 
 
 static const char *processor_modes[] = {
"USER_26", "FIQ_26" , "IRQ_26" , "SVC_26" ,
@@ -141,3 +142,17 @@ bool is_user(void)
 {
return current_thread_info()->flags & TIF_USER_MODE;
 }
+
+void delay(u64 cycles)
+{
+   u64 start = get_cntvct();
+   while ((get_cntvct() - start) < cycles)
+   cpu_relax();
+}
+
+void udelay(unsigned long usec)
+{
+   unsigned int frq;
+   asm volatile("mrc p15, 0, %0, c14, c0, 0" : "=r" (frq));
+   delay((u64)usec * frq / 100);
+}
diff --git a/lib/arm64/asm/processor.h b/lib/arm64/asm/processor.h
index 7e448dc81a6a..94f7ce35b65c 100644
--- a/lib/arm64/asm/processor.h
+++ b/lib/arm64/asm/processor.h
@@ -17,8 +17,10 @@
 #define SCTLR_EL1_M(1 << 0)
 
 #ifndef __ASSEMBLY__
+#include 
 #include 
 #include 
+#include 
 
 enum vector {
EL1T_SYNC,
@@ -89,5 +91,22 @@ extern int mpidr_to_cpu(unsigned long mpidr);
 extern void start_usr(void (*func)(void *arg), void *arg, unsigned long 
sp_usr);
 extern bool is_user(void);
 
+static inline u64 get_cntvct(void)
+{
+   u64 vct;
+   isb();
+   asm volatile("mrs %0, cntvct_el0" : "=r" (vct));
+   return vct;
+}
+
+extern void delay(u64 cycles);
+extern void udelay(unsigned long usecs);
+
+static inline void mdelay(unsigned long msecs)
+{
+   while (msecs--)
+   udelay(1000);
+}
+
 #endif /* !__ASSEMBLY__ */
 #endif /* _ASMARM64_PROCESSOR_H_ */
diff --git a/lib/arm64/processor.c b/lib/arm64/processor.c
index deeab4ec9c8a..50fa835c6f1e 100644
--- a/lib/arm64/processor.c
+++ b/lib/arm64/processor.c
@@ -9,6 +9,7 @@
 #include 
 #include 
 #include 
+#include 
 
 static const char *vector_names[] = {
"el1t_sync",
@@ -253,3 +254,17 @@ bool is_user(void)
 {
return current_thread_info()->flags & TIF_USER_MODE;
 }
+
+void delay(u64 cycles)
+{
+   u64 start = get_cntvct();
+   while ((get_cntvct() - start) < cycles)
+   cpu_relax();
+}
+
+void udelay(unsigned long usec)
+{
+   unsigned int frq;
+   asm volatile("mrs %0, cntfrq_el0" : "=r" (frq));
+   delay((u64)usec * frq / 100);
+}
-- 
2.7.4

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


[kvm-unit-tests PATCH v5 06/11] arm/arm64: add initial gicv2 support

2016-11-10 Thread Andrew Jones
Add some gicv2 support. This just adds init and enable
functions, allowing unit tests to start messing with it.

Signed-off-by: Andrew Jones 

---
v5: share/use only the modern register names [Andre]
v4:
 - only take defines from kernel we need now [Andre]
 - moved defines to asm/gic.h so they'll be shared with v3 [drew]
 - simplify enable by not caring if we reinit the distributor [drew]
 - init all GICD_INT_DEF_PRI_X4 registers [Eric]
---
 arm/Makefile.common|  1 +
 lib/arm/asm/gic-v2.h   | 34 ++
 lib/arm/asm/gic.h  | 37 
 lib/arm/gic.c  | 76 ++
 lib/arm64/asm/gic-v2.h |  1 +
 lib/arm64/asm/gic.h|  1 +
 6 files changed, 150 insertions(+)
 create mode 100644 lib/arm/asm/gic-v2.h
 create mode 100644 lib/arm/asm/gic.h
 create mode 100644 lib/arm/gic.c
 create mode 100644 lib/arm64/asm/gic-v2.h
 create mode 100644 lib/arm64/asm/gic.h

diff --git a/arm/Makefile.common b/arm/Makefile.common
index ccb554d9251a..41239c37e092 100644
--- a/arm/Makefile.common
+++ b/arm/Makefile.common
@@ -42,6 +42,7 @@ cflatobjs += lib/arm/mmu.o
 cflatobjs += lib/arm/bitops.o
 cflatobjs += lib/arm/psci.o
 cflatobjs += lib/arm/smp.o
+cflatobjs += lib/arm/gic.o
 
 libeabi = lib/arm/libeabi.a
 eabiobjs = lib/arm/eabi_compat.o
diff --git a/lib/arm/asm/gic-v2.h b/lib/arm/asm/gic-v2.h
new file mode 100644
index ..c2d5fecd4886
--- /dev/null
+++ b/lib/arm/asm/gic-v2.h
@@ -0,0 +1,34 @@
+/*
+ * All GIC* defines are lifted from include/linux/irqchip/arm-gic.h
+ *
+ * Copyright (C) 2016, Red Hat Inc, Andrew Jones 
+ *
+ * This work is licensed under the terms of the GNU LGPL, version 2.
+ */
+#ifndef _ASMARM_GIC_V2_H_
+#define _ASMARM_GIC_V2_H_
+
+#ifndef _ASMARM_GIC_H_
+#error Do not directly include . Include 
+#endif
+
+#define GICD_ENABLE0x1
+#define GICC_ENABLE0x1
+
+#ifndef __ASSEMBLY__
+
+struct gicv2_data {
+   void *dist_base;
+   void *cpu_base;
+   unsigned int irq_nr;
+};
+extern struct gicv2_data gicv2_data;
+
+#define gicv2_dist_base()  (gicv2_data.dist_base)
+#define gicv2_cpu_base()   (gicv2_data.cpu_base)
+
+extern int gicv2_init(void);
+extern void gicv2_enable_defaults(void);
+
+#endif /* !__ASSEMBLY__ */
+#endif /* _ASMARM_GIC_V2_H_ */
diff --git a/lib/arm/asm/gic.h b/lib/arm/asm/gic.h
new file mode 100644
index ..d44e47bcf404
--- /dev/null
+++ b/lib/arm/asm/gic.h
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2016, Red Hat Inc, Andrew Jones 
+ *
+ * This work is licensed under the terms of the GNU LGPL, version 2.
+ */
+#ifndef _ASMARM_GIC_H_
+#define _ASMARM_GIC_H_
+
+#include 
+
+#define GICD_CTLR  0x
+#define GICD_TYPER 0x0004
+#define GICD_ISENABLER 0x0100
+#define GICD_IPRIORITYR0x0400
+
+#define GICD_TYPER_IRQS(typer) typer) & 0x1f) + 1) * 32)
+#define GICD_INT_EN_SET_SGI0x
+#define GICD_INT_DEF_PRI_X40xa0a0a0a0
+
+#define GICC_CTLR  0x
+#define GICC_PMR   0x0004
+
+#define GICC_INT_PRI_THRESHOLD 0xf0
+
+#ifndef __ASSEMBLY__
+
+/*
+ * gic_init will try to find all known gics, and then
+ * initialize the gic data for the one found.
+ * returns
+ *  0   : no gic was found
+ *  > 0 : the gic version of the gic found
+ */
+extern int gic_init(void);
+
+#endif /* !__ASSEMBLY__ */
+#endif /* _ASMARM_GIC_H_ */
diff --git a/lib/arm/gic.c b/lib/arm/gic.c
new file mode 100644
index ..d655105e058b
--- /dev/null
+++ b/lib/arm/gic.c
@@ -0,0 +1,76 @@
+/*
+ * Copyright (C) 2016, Red Hat Inc, Andrew Jones 
+ *
+ * This work is licensed under the terms of the GNU LGPL, version 2.
+ */
+#include 
+#include 
+#include 
+
+struct gicv2_data gicv2_data;
+
+/*
+ * Documentation/devicetree/bindings/interrupt-controller/arm,gic.txt
+ */
+static bool
+gic_get_dt_bases(const char *compatible, void **base1, void **base2)
+{
+   struct dt_pbus_reg reg;
+   struct dt_device gic;
+   struct dt_bus bus;
+   int node, ret;
+
+   dt_bus_init_defaults();
+   dt_device_init(, , NULL);
+
+   node = dt_device_find_compatible(, compatible);
+   assert(node >= 0 || node == -FDT_ERR_NOTFOUND);
+
+   if (node == -FDT_ERR_NOTFOUND)
+   return false;
+
+   dt_device_bind_node(, node);
+
+   ret = dt_pbus_translate(, 0, );
+   assert(ret == 0);
+   *base1 = ioremap(reg.addr, reg.size);
+
+   ret = dt_pbus_translate(, 1, );
+   assert(ret == 0);
+   *base2 = ioremap(reg.addr, reg.size);
+
+   return true;
+}
+
+int gicv2_init(void)
+{
+   return gic_get_dt_bases("arm,cortex-a15-gic",
+   _data.dist_base, _data.cpu_base);
+}
+
+int gic_init(void)
+{
+   if (gicv2_init())
+   

[kvm-unit-tests PATCH v5 05/11] arm/arm64: irq enable/disable

2016-11-10 Thread Andrew Jones
Reviewed-by: Alex Bennée 
Reviewed-by: Eric Auger 
Signed-off-by: Andrew Jones 
---
 lib/arm/asm/processor.h   | 10 ++
 lib/arm64/asm/processor.h | 10 ++
 2 files changed, 20 insertions(+)

diff --git a/lib/arm/asm/processor.h b/lib/arm/asm/processor.h
index bc46d1f980ee..959ecda5dced 100644
--- a/lib/arm/asm/processor.h
+++ b/lib/arm/asm/processor.h
@@ -35,6 +35,16 @@ static inline unsigned long current_cpsr(void)
 
 #define current_mode() (current_cpsr() & MODE_MASK)
 
+static inline void local_irq_enable(void)
+{
+   asm volatile("cpsie i" : : : "memory", "cc");
+}
+
+static inline void local_irq_disable(void)
+{
+   asm volatile("cpsid i" : : : "memory", "cc");
+}
+
 static inline unsigned long get_mpidr(void)
 {
unsigned long mpidr;
diff --git a/lib/arm64/asm/processor.h b/lib/arm64/asm/processor.h
index 94f7ce35b65c..d54a4ed1c187 100644
--- a/lib/arm64/asm/processor.h
+++ b/lib/arm64/asm/processor.h
@@ -68,6 +68,16 @@ static inline unsigned long current_level(void)
return el & 0xc;
 }
 
+static inline void local_irq_enable(void)
+{
+   asm volatile("msr daifclr, #2" : : : "memory");
+}
+
+static inline void local_irq_disable(void)
+{
+   asm volatile("msr daifset, #2" : : : "memory");
+}
+
 #define DEFINE_GET_SYSREG(reg, type)   \
 static inline type get_##reg(void) \
 {  \
-- 
2.7.4

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


[kvm-unit-tests PATCH v5 08/11] libcflat: add IS_ALIGNED() macro, and page sizes

2016-11-10 Thread Andrew Jones
From: Peter Xu 

These macros will be useful to do page alignment checks.

Reviewed-by: Andre Przywara 
Signed-off-by: Peter Xu 
[drew: also added SZ_64K]
Signed-off-by: Andrew Jones 
---
 lib/libcflat.h | 6 ++
 1 file changed, 6 insertions(+)

diff --git a/lib/libcflat.h b/lib/libcflat.h
index 82005f5d014f..143fc53061fe 100644
--- a/lib/libcflat.h
+++ b/lib/libcflat.h
@@ -33,6 +33,12 @@
 #define __ALIGN_MASK(x, mask)  (((x) + (mask)) & ~(mask))
 #define __ALIGN(x, a)  __ALIGN_MASK(x, (typeof(x))(a) - 1)
 #define ALIGN(x, a)__ALIGN((x), (a))
+#define IS_ALIGNED(x, a)   (((x) & ((typeof(x))(a) - 1)) == 0)
+
+#define SZ_4K  (0x1000)
+#define SZ_64K (0x1)
+#define SZ_2M  (0x20)
+#define SZ_1G  (0x4000)
 
 typedef uint8_tu8;
 typedef int8_t s8;
-- 
2.7.4

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


[kvm-unit-tests PATCH v5 02/11] arm64: fix get_"sysreg32" and make MPIDR 64bit

2016-11-10 Thread Andrew Jones
mrs is always 64bit, so we should always use a 64bit register.
Sometimes we'll only want to return the lower 32, but not for
MPIDR, as that does define fields in the upper 32.

Reviewed-by: Alex Bennée 
Reviewed-by: Eric Auger 
Signed-off-by: Andrew Jones 

---
v5: switch arm32's get_mpidr to 'unsigned long' too, to be
consistent with arm64 [Andre]
---
 lib/arm/asm/processor.h   |  4 ++--
 lib/arm64/asm/processor.h | 15 +--
 2 files changed, 11 insertions(+), 8 deletions(-)

diff --git a/lib/arm/asm/processor.h b/lib/arm/asm/processor.h
index f25e7eee3666..02f912f99974 100644
--- a/lib/arm/asm/processor.h
+++ b/lib/arm/asm/processor.h
@@ -33,9 +33,9 @@ static inline unsigned long current_cpsr(void)
 
 #define current_mode() (current_cpsr() & MODE_MASK)
 
-static inline unsigned int get_mpidr(void)
+static inline unsigned long get_mpidr(void)
 {
-   unsigned int mpidr;
+   unsigned long mpidr;
asm volatile("mrc p15, 0, %0, c0, c0, 5" : "=r" (mpidr));
return mpidr;
 }
diff --git a/lib/arm64/asm/processor.h b/lib/arm64/asm/processor.h
index 84d5c7ce752b..9a208ff729b7 100644
--- a/lib/arm64/asm/processor.h
+++ b/lib/arm64/asm/processor.h
@@ -66,14 +66,17 @@ static inline unsigned long current_level(void)
return el & 0xc;
 }
 
-#define DEFINE_GET_SYSREG32(reg)   \
-static inline unsigned int get_##reg(void) \
+#define DEFINE_GET_SYSREG(reg, type)   \
+static inline type get_##reg(void) \
 {  \
-   unsigned int reg;   \
-   asm volatile("mrs %0, " #reg "_el1" : "=r" (reg));  \
-   return reg; \
+   unsigned long r;\
+   asm volatile("mrs %0, " #reg "_el1" : "=r" (r));\
+   return (type)r; \
 }
-DEFINE_GET_SYSREG32(mpidr)
+#define DEFINE_GET_SYSREG32(reg) DEFINE_GET_SYSREG(reg, unsigned int)
+#define DEFINE_GET_SYSREG64(reg) DEFINE_GET_SYSREG(reg, unsigned long)
+
+DEFINE_GET_SYSREG64(mpidr)
 
 /* Only support Aff0 for now, gicv2 only */
 #define mpidr_to_cpu(mpidr) ((int)((mpidr) & 0xff))
-- 
2.7.4

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


[kvm-unit-tests PATCH v5 00/11] arm/arm64: add gic framework

2016-11-10 Thread Andrew Jones
v5:
 - fix arm32/gicv3 compile [drew]
 - use modern register names [Andre]
 - one Andre r-b

v4:
 - Eric's r-b's
 - Andre's suggestion to only take defines we need
 - several other changes listed in individual patches

v3:
 - Rebased on latest master
 - Added Alex's r-b's

v2:
 Rebased on latest master + my "populate argv[0]" series (will
 send a REPOST for that shortly. Additionally a few patches got
 fixes/features;
 07/10 got same fix as kernel 7c9b973061 "irqchip/gic-v3: Configure
   all interrupts as non-secure Group-1" in order to continue
   working over TCG, as the gicv3 code for TCG removed a hack
   it had there to make Linux happy.
 08/10 added more output for when things fail (if they fail)
 09/10 switched gicv3 broadcast implementation to using IRM. This
   found a bug in a recent (but not tip) kernel, which I was
   about to fix, but then I saw MarcZ beat me to it.
 10/10 actually check that the input irq is the received irq


Import defines, and steal enough helper functions, from Linux to
enable programming of the gic (v2 and v3). Then use the framework
to add an initial test (an ipi test; self, target-list, broadcast).

It's my hope that this framework will be a suitable base on which
more tests may be easily added, particularly because we have
vgic-new and tcg gicv3 emulation getting close to merge. (v3 UPDATE:
vgic-new and tcg gicv3 are merged now)

To run it, along with other tests, just do

 ./configure [ --arch=[arm|arm64] --cross-prefix=$PREFIX ]
 make
 export QEMU=$PATH_TO_QEMU
 ./run_tests.sh

To run it separately do, e.g.

$QEMU -machine virt,accel=tcg -cpu cortex-a57 \
 -device virtio-serial-device \
 -device virtconsole,chardev=ctd -chardev testdev,id=ctd \
 -display none -serial stdio \
 -kernel arm/gic.flat \
 -smp 123 -machine gic-version=3 -append ipi
  ^^ note, we can go nuts with nr-cpus on TCG :-)

Or, a KVM example using a different "sender" cpu and irq (other than zero)

$QEMU -machine virt,accel=kvm -cpu host \
 -device virtio-serial-device \
 -device virtconsole,chardev=ctd -chardev testdev,id=ctd \
 -display none -serial stdio \
 -kernel arm/gic.flat \
 -smp 48 -machine gic-version=3 -append 'ipi sender=42 irq=1'


Patches:
01-05: fixes and functionality needed by the later gic patches
06-07: enable gicv2 and gicv2 IPI test
08-10: enable gicv3 and gicv3 IPI test
   11: extend the IPI tests to take variable sender and irq

Available here: https://github.com/rhdrjones/kvm-unit-tests/commits/arm/gic-v5


Andrew Jones (10):
  lib: xstr: allow multiple args
  arm64: fix get_"sysreg32" and make MPIDR 64bit
  arm/arm64: smp: support more than 8 cpus
  arm/arm64: add some delay routines
  arm/arm64: irq enable/disable
  arm/arm64: add initial gicv2 support
  arm/arm64: gicv2: add an IPI test
  arm/arm64: add initial gicv3 support
  arm/arm64: gicv3: add an IPI test
  arm/arm64: gic: don't just use zero

Peter Xu (1):
  libcflat: add IS_ALIGNED() macro, and page sizes

 arm/Makefile.common|   7 +-
 arm/gic.c  | 417 +
 arm/run|  19 ++-
 arm/selftest.c |   5 +-
 arm/unittests.cfg  |  13 ++
 lib/arm/asm/arch_gicv3.h   |  65 +++
 lib/arm/asm/gic-v2.h   |  36 
 lib/arm/asm/gic-v3.h   |  94 ++
 lib/arm/asm/gic.h  |  43 +
 lib/arm/asm/processor.h|  42 -
 lib/arm/asm/setup.h|   4 +-
 lib/arm/gic.c  | 141 +++
 lib/arm/processor.c|  15 ++
 lib/arm/setup.c|  10 ++
 lib/arm64/asm/arch_gicv3.h |  66 +++
 lib/arm64/asm/gic-v2.h |   1 +
 lib/arm64/asm/gic-v3.h |   1 +
 lib/arm64/asm/gic.h|   1 +
 lib/arm64/asm/processor.h  |  53 +-
 lib/arm64/asm/sysreg.h |  44 +
 lib/arm64/processor.c  |  15 ++
 lib/libcflat.h |  10 +-
 22 files changed, 1075 insertions(+), 27 deletions(-)
 create mode 100644 arm/gic.c
 create mode 100644 lib/arm/asm/arch_gicv3.h
 create mode 100644 lib/arm/asm/gic-v2.h
 create mode 100644 lib/arm/asm/gic-v3.h
 create mode 100644 lib/arm/asm/gic.h
 create mode 100644 lib/arm/gic.c
 create mode 100644 lib/arm64/asm/arch_gicv3.h
 create mode 100644 lib/arm64/asm/gic-v2.h
 create mode 100644 lib/arm64/asm/gic-v3.h
 create mode 100644 lib/arm64/asm/gic.h
 create mode 100644 lib/arm64/asm/sysreg.h

-- 
2.7.4

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


[kvm-unit-tests PATCH v5 01/11] lib: xstr: allow multiple args

2016-11-10 Thread Andrew Jones
Make implementation equivalent to Linux's include/linux/stringify.h

Reviewed-by: Eric Auger 
Signed-off-by: Andrew Jones 
---
 lib/libcflat.h | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/lib/libcflat.h b/lib/libcflat.h
index 72b1bf9668ef..82005f5d014f 100644
--- a/lib/libcflat.h
+++ b/lib/libcflat.h
@@ -27,8 +27,8 @@
 
 #define __unused __attribute__((__unused__))
 
-#define xstr(s) xxstr(s)
-#define xxstr(s) #s
+#define xstr(s...) xxstr(s)
+#define xxstr(s...) #s
 
 #define __ALIGN_MASK(x, mask)  (((x) + (mask)) & ~(mask))
 #define __ALIGN(x, a)  __ALIGN_MASK(x, (typeof(x))(a) - 1)
-- 
2.7.4

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


Re: [kvm-unit-tests PATCH v4 00/11] arm/arm64: add gic framework

2016-11-10 Thread Andrew Jones
On Thu, Nov 10, 2016 at 04:52:30PM +, Andre Przywara wrote:
> Hi,
> 
> so is this actually v4 just resent?
> Or is this is a new version with s/5/4/?
> I can't spot any of the key changes quickly ...

Argh... Forgot to edit my bash history after pulling it up to send.
OK, the real v5 is coming...

Thanks,
Your Friendly Spammer

> 
> Cheers,
> Andre.
> 
> On 10/11/16 16:07, Andrew Jones wrote:
> > v4:
> >  - Eric's r-b's
> >  - Andre's suggestion to only take defines we need
> >  - several other changes listed in individual patches
> > 
> > v3:
> >  - Rebased on latest master
> >  - Added Alex's r-b's
> > 
> > v2:
> >  Rebased on latest master + my "populate argv[0]" series (will
> >  send a REPOST for that shortly. Additionally a few patches got
> >  fixes/features;
> >  07/10 got same fix as kernel 7c9b973061 "irqchip/gic-v3: Configure
> >all interrupts as non-secure Group-1" in order to continue
> >working over TCG, as the gicv3 code for TCG removed a hack
> >it had there to make Linux happy.
> >  08/10 added more output for when things fail (if they fail)
> >  09/10 switched gicv3 broadcast implementation to using IRM. This
> >found a bug in a recent (but not tip) kernel, which I was
> >about to fix, but then I saw MarcZ beat me to it.
> >  10/10 actually check that the input irq is the received irq
> > 
> > 
> > Import defines, and steal enough helper functions, from Linux to
> > enable programming of the gic (v2 and v3). Then use the framework
> > to add an initial test (an ipi test; self, target-list, broadcast).
> > 
> > It's my hope that this framework will be a suitable base on which
> > more tests may be easily added, particularly because we have
> > vgic-new and tcg gicv3 emulation getting close to merge. (v3 UPDATE:
> > vgic-new and tcg gicv3 are merged now)
> > 
> > To run it, along with other tests, just do
> > 
> >  ./configure [ --arch=[arm|arm64] --cross-prefix=$PREFIX ]
> >  make
> >  export QEMU=$PATH_TO_QEMU
> >  ./run_tests.sh
> > 
> > To run it separately do, e.g.
> > 
> > $QEMU -machine virt,accel=tcg -cpu cortex-a57 \
> >  -device virtio-serial-device \
> >  -device virtconsole,chardev=ctd -chardev testdev,id=ctd \
> >  -display none -serial stdio \
> >  -kernel arm/gic.flat \
> >  -smp 123 -machine gic-version=3 -append ipi
> >   ^^ note, we can go nuts with nr-cpus on TCG :-)
> > 
> > Or, a KVM example using a different "sender" cpu and irq (other than zero)
> > 
> > $QEMU -machine virt,accel=kvm -cpu host \
> >  -device virtio-serial-device \
> >  -device virtconsole,chardev=ctd -chardev testdev,id=ctd \
> >  -display none -serial stdio \
> >  -kernel arm/gic.flat \
> >  -smp 48 -machine gic-version=3 -append 'ipi sender=42 irq=1'
> > 
> > 
> > Patches:
> > 01-05: fixes and functionality needed by the later gic patches
> > 06-07: enable gicv2 and gicv2 IPI test
> > 08-10: enable gicv3 and gicv3 IPI test
> >11: extend the IPI tests to take variable sender and irq
> > 
> > Available here: 
> > https://github.com/rhdrjones/kvm-unit-tests/commits/arm/gic-v4
> > 
> > 
> > Andrew Jones (10):
> >   lib: xstr: allow multiple args
> >   arm64: fix get_"sysreg32" and make MPIDR 64bit
> >   arm/arm64: smp: support more than 8 cpus
> >   arm/arm64: add some delay routines
> >   arm/arm64: irq enable/disable
> >   arm/arm64: add initial gicv2 support
> >   arm/arm64: gicv2: add an IPI test
> >   arm/arm64: add initial gicv3 support
> >   arm/arm64: gicv3: add an IPI test
> >   arm/arm64: gic: don't just use zero
> > 
> > Peter Xu (1):
> >   libcflat: add IS_ALIGNED() macro, and page sizes
> > 
> >  arm/Makefile.common|   7 +-
> >  arm/gic.c  | 417 
> > +
> >  arm/run|  19 ++-
> >  arm/selftest.c |   5 +-
> >  arm/unittests.cfg  |  13 ++
> >  lib/arm/asm/arch_gicv3.h   |  65 +++
> >  lib/arm/asm/gic-v2.h   |  28 +++
> >  lib/arm/asm/gic-v3.h   |  92 ++
> >  lib/arm/asm/gic.h  |  51 ++
> >  lib/arm/asm/processor.h|  38 -
> >  lib/arm/asm/setup.h|   4 +-
> >  lib/arm/gic.c  | 131 ++
> >  lib/arm/processor.c|  15 ++
> >  lib/arm/setup.c|  12 +-
> >  lib/arm64/asm/arch_gicv3.h |  66 +++
> >  lib/arm64/asm/gic-v2.h |   1 +
> >  lib/arm64/asm/gic-v3.h |   1 +
> >  lib/arm64/asm/gic.h|   1 +
> >  lib/arm64/asm/processor.h  |  53 +-
> >  lib/arm64/asm/sysreg.h |  44 +
> >  lib/arm64/processor.c  |  15 ++
> >  lib/libcflat.h |  10 +-
> >  22 files changed, 1062 insertions(+), 26 deletions(-)
> >  create mode 100644 arm/gic.c
> >  create mode 100644 lib/arm/asm/arch_gicv3.h
> >  create mode 100644 lib/arm/asm/gic-v2.h
> >  create mode 100644 lib/arm/asm/gic-v3.h
> >  create mode 100644 lib/arm/asm/gic.h
> >  create mode 100644 lib/arm/gic.c
> >  create mode 100644 lib/arm64/asm/arch_gicv3.h
> >  create mode 

Re: [PATCH 1/2] arm64: perf: Move ARMv8 PMU perf event definitions to asm/perf_event.h

2016-11-10 Thread Will Deacon
On Thu, Nov 10, 2016 at 03:32:12PM +, Marc Zyngier wrote:
> On 10/11/16 15:12, Wei Huang wrote:
> > 
> > 
> > On 11/10/2016 03:10 AM, Marc Zyngier wrote:
> >> Hi Wei,
> >>
> >> On 09/11/16 19:57, Wei Huang wrote:
> >>> This patch moves ARMv8-related perf event definitions from perf_event.c
> >>> to asm/perf_event.h; so KVM code can use them directly. This also help
> >>> remove a duplicated definition of SW_INCR in perf_event.h.
> >>>
> >>> Signed-off-by: Wei Huang 
> >>> ---
> >>>  arch/arm64/include/asm/perf_event.h | 161 
> >>> +++-
> >>>  arch/arm64/kernel/perf_event.c  | 161 
> >>> 
> >>>  2 files changed, 160 insertions(+), 162 deletions(-)
> >>>
> >>> diff --git a/arch/arm64/include/asm/perf_event.h 
> >>> b/arch/arm64/include/asm/perf_event.h
> >>> index 2065f46..6c7b18b 100644
> >>> --- a/arch/arm64/include/asm/perf_event.h
> >>> +++ b/arch/arm64/include/asm/perf_event.h
> >>> @@ -46,7 +46,166 @@
> >>>  #define  ARMV8_PMU_EVTYPE_MASK   0xc800  /* Mask for writable 
> >>> bits */
> >>>  #define  ARMV8_PMU_EVTYPE_EVENT  0x  /* Mask for EVENT bits 
> >>> */
> >>>  
> >>> -#define ARMV8_PMU_EVTYPE_EVENT_SW_INCR   0   /* Software increment 
> >>> event */
> >>> +/*
> >>> + * ARMv8 PMUv3 Performance Events handling code.
> >>> + * Common event types.
> >>> + */
> >>> +
> >>> +/* Required events. */
> >>> +#define ARMV8_PMUV3_PERFCTR_SW_INCR  0x00
> >>> +#define ARMV8_PMUV3_PERFCTR_L1D_CACHE_REFILL 0x03
> >>> +#define ARMV8_PMUV3_PERFCTR_L1D_CACHE0x04
> >>> +#define ARMV8_PMUV3_PERFCTR_BR_MIS_PRED  0x10
> >>> +#define ARMV8_PMUV3_PERFCTR_CPU_CYCLES   0x11
> >>> +#define ARMV8_PMUV3_PERFCTR_BR_PRED  0x12
> >>
> >> In my initial review, I asked for the "required" events to be moved to a
> >> shared location. What's the rational for moving absolutely everything?
> > 
> > I did notice the phrase "required" in the original email. However I
> > think it is weird to have two places for a same set of PMU definitions.
> > Other developers might think these two are missing if they don't search
> > kernel files carefully.
> > 
> > If Will Deacon and you insist, I can move only two defs to perf_event.h,
> > consolidated with the 2nd patch into a single one.
> 
> My personal feeling is that only architected events should be in a
> public header. The CPU-specific ones are probably better kept private,
> as it is doubtful that other users would appear).
> 
> I'll leave it up to Will to decide, as all I want to avoid is the
> duplication of constants between the PMU and KVM code bases.

Yeah, just take the sets that you need (i.e. the architected events).

Also, check that it builds.

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


Re: [kvm-unit-tests PATCH v4 00/11] arm/arm64: add gic framework

2016-11-10 Thread Andre Przywara
Hi,

so is this actually v4 just resent?
Or is this is a new version with s/5/4/?
I can't spot any of the key changes quickly ...

Cheers,
Andre.

On 10/11/16 16:07, Andrew Jones wrote:
> v4:
>  - Eric's r-b's
>  - Andre's suggestion to only take defines we need
>  - several other changes listed in individual patches
> 
> v3:
>  - Rebased on latest master
>  - Added Alex's r-b's
> 
> v2:
>  Rebased on latest master + my "populate argv[0]" series (will
>  send a REPOST for that shortly. Additionally a few patches got
>  fixes/features;
>  07/10 got same fix as kernel 7c9b973061 "irqchip/gic-v3: Configure
>all interrupts as non-secure Group-1" in order to continue
>working over TCG, as the gicv3 code for TCG removed a hack
>it had there to make Linux happy.
>  08/10 added more output for when things fail (if they fail)
>  09/10 switched gicv3 broadcast implementation to using IRM. This
>found a bug in a recent (but not tip) kernel, which I was
>about to fix, but then I saw MarcZ beat me to it.
>  10/10 actually check that the input irq is the received irq
> 
> 
> Import defines, and steal enough helper functions, from Linux to
> enable programming of the gic (v2 and v3). Then use the framework
> to add an initial test (an ipi test; self, target-list, broadcast).
> 
> It's my hope that this framework will be a suitable base on which
> more tests may be easily added, particularly because we have
> vgic-new and tcg gicv3 emulation getting close to merge. (v3 UPDATE:
> vgic-new and tcg gicv3 are merged now)
> 
> To run it, along with other tests, just do
> 
>  ./configure [ --arch=[arm|arm64] --cross-prefix=$PREFIX ]
>  make
>  export QEMU=$PATH_TO_QEMU
>  ./run_tests.sh
> 
> To run it separately do, e.g.
> 
> $QEMU -machine virt,accel=tcg -cpu cortex-a57 \
>  -device virtio-serial-device \
>  -device virtconsole,chardev=ctd -chardev testdev,id=ctd \
>  -display none -serial stdio \
>  -kernel arm/gic.flat \
>  -smp 123 -machine gic-version=3 -append ipi
>   ^^ note, we can go nuts with nr-cpus on TCG :-)
> 
> Or, a KVM example using a different "sender" cpu and irq (other than zero)
> 
> $QEMU -machine virt,accel=kvm -cpu host \
>  -device virtio-serial-device \
>  -device virtconsole,chardev=ctd -chardev testdev,id=ctd \
>  -display none -serial stdio \
>  -kernel arm/gic.flat \
>  -smp 48 -machine gic-version=3 -append 'ipi sender=42 irq=1'
> 
> 
> Patches:
> 01-05: fixes and functionality needed by the later gic patches
> 06-07: enable gicv2 and gicv2 IPI test
> 08-10: enable gicv3 and gicv3 IPI test
>11: extend the IPI tests to take variable sender and irq
> 
> Available here: https://github.com/rhdrjones/kvm-unit-tests/commits/arm/gic-v4
> 
> 
> Andrew Jones (10):
>   lib: xstr: allow multiple args
>   arm64: fix get_"sysreg32" and make MPIDR 64bit
>   arm/arm64: smp: support more than 8 cpus
>   arm/arm64: add some delay routines
>   arm/arm64: irq enable/disable
>   arm/arm64: add initial gicv2 support
>   arm/arm64: gicv2: add an IPI test
>   arm/arm64: add initial gicv3 support
>   arm/arm64: gicv3: add an IPI test
>   arm/arm64: gic: don't just use zero
> 
> Peter Xu (1):
>   libcflat: add IS_ALIGNED() macro, and page sizes
> 
>  arm/Makefile.common|   7 +-
>  arm/gic.c  | 417 
> +
>  arm/run|  19 ++-
>  arm/selftest.c |   5 +-
>  arm/unittests.cfg  |  13 ++
>  lib/arm/asm/arch_gicv3.h   |  65 +++
>  lib/arm/asm/gic-v2.h   |  28 +++
>  lib/arm/asm/gic-v3.h   |  92 ++
>  lib/arm/asm/gic.h  |  51 ++
>  lib/arm/asm/processor.h|  38 -
>  lib/arm/asm/setup.h|   4 +-
>  lib/arm/gic.c  | 131 ++
>  lib/arm/processor.c|  15 ++
>  lib/arm/setup.c|  12 +-
>  lib/arm64/asm/arch_gicv3.h |  66 +++
>  lib/arm64/asm/gic-v2.h |   1 +
>  lib/arm64/asm/gic-v3.h |   1 +
>  lib/arm64/asm/gic.h|   1 +
>  lib/arm64/asm/processor.h  |  53 +-
>  lib/arm64/asm/sysreg.h |  44 +
>  lib/arm64/processor.c  |  15 ++
>  lib/libcflat.h |  10 +-
>  22 files changed, 1062 insertions(+), 26 deletions(-)
>  create mode 100644 arm/gic.c
>  create mode 100644 lib/arm/asm/arch_gicv3.h
>  create mode 100644 lib/arm/asm/gic-v2.h
>  create mode 100644 lib/arm/asm/gic-v3.h
>  create mode 100644 lib/arm/asm/gic.h
>  create mode 100644 lib/arm/gic.c
>  create mode 100644 lib/arm64/asm/arch_gicv3.h
>  create mode 100644 lib/arm64/asm/gic-v2.h
>  create mode 100644 lib/arm64/asm/gic-v3.h
>  create mode 100644 lib/arm64/asm/gic.h
>  create mode 100644 lib/arm64/asm/sysreg.h
> 
___
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm


[kvm-unit-tests PATCH v4 10/11] arm/arm64: gicv3: add an IPI test

2016-11-10 Thread Andrew Jones
Signed-off-by: Andrew Jones 

---
v4:
 - heavily comment gicv3_ipi_send_tlist() [Eric]
 - changes needed for gicv2 iar/irqstat fix to other patch
v2:
 - use IRM for gicv3 broadcast
---
 arm/gic.c  | 195 ++---
 arm/unittests.cfg  |   6 ++
 lib/arm/asm/arch_gicv3.h   |  23 ++
 lib/arm64/asm/arch_gicv3.h |  22 +
 4 files changed, 236 insertions(+), 10 deletions(-)

diff --git a/arm/gic.c b/arm/gic.c
index efefab7296d4..d98ca6b9efd5 100644
--- a/arm/gic.c
+++ b/arm/gic.c
@@ -3,6 +3,8 @@
  *
  * GICv2
  *   + test sending/receiving IPIs
+ * GICv3
+ *   + test sending/receiving IPIs
  *
  * Copyright (C) 2016, Red Hat Inc, Andrew Jones 
  *
@@ -16,6 +18,19 @@
 #include 
 #include 
 
+struct gic {
+   struct {
+   void (*enable)(void);
+   void (*send_self)(void);
+   void (*send_tlist)(cpumask_t *);
+   void (*send_broadcast)(void);
+   } ipi;
+   u32 (*read_iar)(void);
+   u32 (*irqnr)(u32 iar);
+   void (*write_eoi)(u32);
+};
+
+static struct gic *gic;
 static int gic_version;
 static int acked[NR_CPUS], spurious[NR_CPUS];
 static cpumask_t ready;
@@ -69,13 +84,33 @@ static void check_acked(cpumask_t *mask)
   false, missing, extra, unexpected);
 }
 
+static u32 gicv2_read_iar(void)
+{
+   return readl(gicv2_cpu_base() + GIC_CPU_INTACK);
+}
+
+static u32 gicv2_irqnr(u32 iar)
+{
+   return iar & GICC_IAR_INT_ID_MASK;
+}
+
+static void gicv2_write_eoi(u32 irqstat)
+{
+   writel(irqstat, gicv2_cpu_base() + GIC_CPU_EOI);
+}
+
+static u32 gicv3_irqnr(u32 iar)
+{
+   return iar;
+}
+
 static void ipi_handler(struct pt_regs *regs __unused)
 {
-   u32 irqstat = readl(gicv2_cpu_base() + GIC_CPU_INTACK);
-   u32 irqnr = irqstat & GICC_IAR_INT_ID_MASK;
+   u32 irqstat = gic->read_iar();
+   u32 irqnr = gic->irqnr(irqstat);
 
if (irqnr != GICC_INT_SPURIOUS) {
-   writel(irqstat, gicv2_cpu_base() + GIC_CPU_EOI);
+   gic->write_eoi(irqstat);
smp_rmb(); /* pairs with wmb in ipi_test functions */
++acked[smp_processor_id()];
smp_wmb(); /* pairs with rmb in check_acked */
@@ -85,6 +120,112 @@ static void ipi_handler(struct pt_regs *regs __unused)
}
 }
 
+static void gicv2_ipi_send_self(void)
+{
+   writel(2 << 24, gicv2_dist_base() + GIC_DIST_SOFTINT);
+}
+
+static void gicv2_ipi_send_tlist(cpumask_t *mask)
+{
+   u8 tlist = (u8)cpumask_bits(mask)[0];
+
+   writel(tlist << 16, gicv2_dist_base() + GIC_DIST_SOFTINT);
+}
+
+static void gicv2_ipi_send_broadcast(void)
+{
+   writel(1 << 24, gicv2_dist_base() + GIC_DIST_SOFTINT);
+}
+
+#define ICC_SGI1R_AFFINITY_1_SHIFT 16
+#define ICC_SGI1R_AFFINITY_2_SHIFT 32
+#define ICC_SGI1R_AFFINITY_3_SHIFT 48
+#define MPIDR_TO_SGI_AFFINITY(cluster_id, level) \
+   (MPIDR_AFFINITY_LEVEL(cluster_id, level) << ICC_SGI1R_AFFINITY_## level 
## _SHIFT)
+
+static void gicv3_ipi_send_tlist(cpumask_t *mask)
+{
+   u16 tlist;
+   int cpu;
+
+   /*
+* For each cpu in the mask collect its peers, which are also in
+* the mask, in order to form target lists.
+*/
+   for_each_cpu(cpu, mask) {
+   u64 mpidr = cpus[cpu], sgi1r;
+   u64 cluster_id;
+
+   /*
+* GICv3 can send IPIs to up 16 peer cpus with a single
+* write to ICC_SGI1R_EL1 (using the target list). Peers
+* are cpus that have nearly identical MPIDRs, the only
+* difference being Aff0. The matching upper affinity
+* levels form the cluster ID.
+*/
+   cluster_id = mpidr & ~0xffUL;
+   tlist = 0;
+
+   /*
+* Sort of open code for_each_cpu in order to have a
+* nested for_each_cpu loop.
+*/
+   while (cpu < nr_cpus) {
+   if ((mpidr & 0xff) >= 16) {
+   printf("cpu%d MPIDR:aff0 is %d (>= 16)!\n",
+   cpu, (int)(mpidr & 0xff));
+   break;
+   }
+
+   tlist |= 1 << (mpidr & 0xf);
+
+   cpu = cpumask_next(cpu, mask);
+   if (cpu >= nr_cpus)
+   break;
+
+   mpidr = cpus[cpu];
+
+   if (cluster_id != (mpidr & ~0xffUL)) {
+   /*
+* The next cpu isn't in our cluster. Roll
+* back the cpu index allowing the outer
+* for_each_cpu to find it again with
+* cpumask_next
+*/
+   --cpu;
+   

[kvm-unit-tests PATCH v4 09/11] arm/arm64: add initial gicv3 support

2016-11-10 Thread Andrew Jones
Signed-off-by: Andrew Jones 

---
v4:
 - only take defines from kernel we need now [Andre]
 - simplify enable by not caring if we reinit the distributor [drew]
v2:
 - configure irqs as NS GRP1
---
 lib/arm/asm/arch_gicv3.h   | 42 +
 lib/arm/asm/gic-v3.h   | 92 ++
 lib/arm/asm/gic.h  |  1 +
 lib/arm/gic.c  | 56 
 lib/arm64/asm/arch_gicv3.h | 44 ++
 lib/arm64/asm/gic-v3.h |  1 +
 lib/arm64/asm/sysreg.h | 44 ++
 7 files changed, 280 insertions(+)
 create mode 100644 lib/arm/asm/arch_gicv3.h
 create mode 100644 lib/arm/asm/gic-v3.h
 create mode 100644 lib/arm64/asm/arch_gicv3.h
 create mode 100644 lib/arm64/asm/gic-v3.h
 create mode 100644 lib/arm64/asm/sysreg.h

diff --git a/lib/arm/asm/arch_gicv3.h b/lib/arm/asm/arch_gicv3.h
new file mode 100644
index ..81a1e5f6c29c
--- /dev/null
+++ b/lib/arm/asm/arch_gicv3.h
@@ -0,0 +1,42 @@
+/*
+ * All ripped off from arch/arm/include/asm/arch_gicv3.h
+ *
+ * Copyright (C) 2016, Red Hat Inc, Andrew Jones 
+ *
+ * This work is licensed under the terms of the GNU LGPL, version 2.
+ */
+#ifndef _ASMARM_ARCH_GICV3_H_
+#define _ASMARM_ARCH_GICV3_H_
+
+#ifndef __ASSEMBLY__
+#include 
+#include 
+#include 
+
+#define __stringify xstr
+
+#define __ACCESS_CP15(CRn, Op1, CRm, Op2)  p15, Op1, %0, CRn, CRm, Op2
+
+#define ICC_PMR__ACCESS_CP15(c4, 0, c6, 0)
+#define ICC_IGRPEN1__ACCESS_CP15(c12, 0, c12, 7)
+
+static inline void gicv3_write_pmr(u32 val)
+{
+   asm volatile("mcr " __stringify(ICC_PMR) : : "r" (val));
+}
+
+static inline void gicv3_write_grpen1(u32 val)
+{
+   asm volatile("mcr " __stringify(ICC_IGRPEN1) : : "r" (val));
+   isb();
+}
+
+static inline u64 gicv3_read_typer(const volatile void __iomem *addr)
+{
+   u64 val = readl(addr);
+   val |= (u64)readl(addr + 4) << 32;
+   return val;
+}
+
+#endif /* !__ASSEMBLY__ */
+#endif /* _ASMARM_ARCH_GICV3_H_ */
diff --git a/lib/arm/asm/gic-v3.h b/lib/arm/asm/gic-v3.h
new file mode 100644
index ..03321f8c860f
--- /dev/null
+++ b/lib/arm/asm/gic-v3.h
@@ -0,0 +1,92 @@
+/*
+ * All GIC* defines are lifted from include/linux/irqchip/arm-gic-v3.h
+ *
+ * Copyright (C) 2016, Red Hat Inc, Andrew Jones 
+ *
+ * This work is licensed under the terms of the GNU LGPL, version 2.
+ */
+#ifndef _ASMARM_GIC_V3_H_
+#define _ASMARM_GIC_V3_H_
+
+#ifndef _ASMARM_GIC_H_
+#error Do not directly include . Include 
+#endif
+
+#define GICD_CTLR  0x
+#define GICD_TYPER 0x0004
+#define GICD_IGROUPR   0x0080
+
+#define GICD_CTLR_RWP  (1U << 31)
+#define GICD_CTLR_ARE_NS   (1U << 4)
+#define GICD_CTLR_ENABLE_G1A   (1U << 1)
+#define GICD_CTLR_ENABLE_G1(1U << 0)
+
+#define GICR_TYPER 0x0008
+#define GICR_IGROUPR0  GICD_IGROUPR
+#define GICR_TYPER_LAST(1U << 4)
+
+
+#include 
+
+#ifndef __ASSEMBLY__
+#include 
+#include 
+#include 
+#include 
+
+struct gicv3_data {
+   void *dist_base;
+   void *redist_base[NR_CPUS];
+   unsigned int irq_nr;
+};
+extern struct gicv3_data gicv3_data;
+
+#define gicv3_dist_base()  (gicv3_data.dist_base)
+#define gicv3_redist_base()
(gicv3_data.redist_base[smp_processor_id()])
+#define gicv3_sgi_base()   
(gicv3_data.redist_base[smp_processor_id()] + SZ_64K)
+
+extern int gicv3_init(void);
+extern void gicv3_enable_defaults(void);
+
+static inline void gicv3_do_wait_for_rwp(void *base)
+{
+   int count = 10; /* 1s */
+
+   while (readl(base + GICD_CTLR) & GICD_CTLR_RWP) {
+   if (!--count) {
+   printf("GICv3: RWP timeout!\n");
+   abort();
+   }
+   cpu_relax();
+   udelay(10);
+   };
+}
+
+static inline void gicv3_dist_wait_for_rwp(void)
+{
+   gicv3_do_wait_for_rwp(gicv3_dist_base());
+}
+
+static inline void gicv3_redist_wait_for_rwp(void)
+{
+   gicv3_do_wait_for_rwp(gicv3_redist_base());
+}
+
+static inline u32 mpidr_compress(u64 mpidr)
+{
+   u64 compressed = mpidr & MPIDR_HWID_BITMASK;
+
+   compressed = (((compressed >> 32) & 0xff) << 24) | compressed;
+   return compressed;
+}
+
+static inline u64 mpidr_uncompress(u32 compressed)
+{
+   u64 mpidr = ((u64)compressed >> 24) << 32;
+
+   mpidr |= compressed & MPIDR_HWID_BITMASK;
+   return mpidr;
+}
+
+#endif /* !__ASSEMBLY__ */
+#endif /* _ASMARM_GIC_V3_H_ */
diff --git a/lib/arm/asm/gic.h b/lib/arm/asm/gic.h
index 328e078a9ae1..4897bc592cdd 100644
--- a/lib/arm/asm/gic.h
+++ b/lib/arm/asm/gic.h
@@ -7,6 +7,7 @@
 #define _ASMARM_GIC_H_
 
 #include 
+#include 
 
 #define GIC_CPU_CTRL

[kvm-unit-tests PATCH v4 04/11] arm/arm64: add some delay routines

2016-11-10 Thread Andrew Jones
Allow a thread to wait some specified amount of time. Can
specify in cycles, usecs, and msecs.

Reviewed-by: Alex Bennée 
Reviewed-by: Eric Auger 
Signed-off-by: Andrew Jones 
---
 lib/arm/asm/processor.h   | 19 +++
 lib/arm/processor.c   | 15 +++
 lib/arm64/asm/processor.h | 19 +++
 lib/arm64/processor.c | 15 +++
 4 files changed, 68 insertions(+)

diff --git a/lib/arm/asm/processor.h b/lib/arm/asm/processor.h
index d2048f5f5f7e..afc903ca7d4a 100644
--- a/lib/arm/asm/processor.h
+++ b/lib/arm/asm/processor.h
@@ -5,7 +5,9 @@
  *
  * This work is licensed under the terms of the GNU LGPL, version 2.
  */
+#include 
 #include 
+#include 
 
 enum vector {
EXCPTN_RST,
@@ -51,4 +53,21 @@ extern int mpidr_to_cpu(unsigned long mpidr);
 extern void start_usr(void (*func)(void *arg), void *arg, unsigned long 
sp_usr);
 extern bool is_user(void);
 
+static inline u64 get_cntvct(void)
+{
+   u64 vct;
+   isb();
+   asm volatile("mrrc p15, 1, %Q0, %R0, c14" : "=r" (vct));
+   return vct;
+}
+
+extern void delay(u64 cycles);
+extern void udelay(unsigned long usecs);
+
+static inline void mdelay(unsigned long msecs)
+{
+   while (msecs--)
+   udelay(1000);
+}
+
 #endif /* _ASMARM_PROCESSOR_H_ */
diff --git a/lib/arm/processor.c b/lib/arm/processor.c
index 54fdb87ef019..c2ee360df688 100644
--- a/lib/arm/processor.c
+++ b/lib/arm/processor.c
@@ -9,6 +9,7 @@
 #include 
 #include 
 #include 
+#include 
 
 static const char *processor_modes[] = {
"USER_26", "FIQ_26" , "IRQ_26" , "SVC_26" ,
@@ -141,3 +142,17 @@ bool is_user(void)
 {
return current_thread_info()->flags & TIF_USER_MODE;
 }
+
+void delay(u64 cycles)
+{
+   u64 start = get_cntvct();
+   while ((get_cntvct() - start) < cycles)
+   cpu_relax();
+}
+
+void udelay(unsigned long usec)
+{
+   unsigned int frq;
+   asm volatile("mrc p15, 0, %0, c14, c0, 0" : "=r" (frq));
+   delay((u64)usec * frq / 100);
+}
diff --git a/lib/arm64/asm/processor.h b/lib/arm64/asm/processor.h
index 7e448dc81a6a..94f7ce35b65c 100644
--- a/lib/arm64/asm/processor.h
+++ b/lib/arm64/asm/processor.h
@@ -17,8 +17,10 @@
 #define SCTLR_EL1_M(1 << 0)
 
 #ifndef __ASSEMBLY__
+#include 
 #include 
 #include 
+#include 
 
 enum vector {
EL1T_SYNC,
@@ -89,5 +91,22 @@ extern int mpidr_to_cpu(unsigned long mpidr);
 extern void start_usr(void (*func)(void *arg), void *arg, unsigned long 
sp_usr);
 extern bool is_user(void);
 
+static inline u64 get_cntvct(void)
+{
+   u64 vct;
+   isb();
+   asm volatile("mrs %0, cntvct_el0" : "=r" (vct));
+   return vct;
+}
+
+extern void delay(u64 cycles);
+extern void udelay(unsigned long usecs);
+
+static inline void mdelay(unsigned long msecs)
+{
+   while (msecs--)
+   udelay(1000);
+}
+
 #endif /* !__ASSEMBLY__ */
 #endif /* _ASMARM64_PROCESSOR_H_ */
diff --git a/lib/arm64/processor.c b/lib/arm64/processor.c
index deeab4ec9c8a..50fa835c6f1e 100644
--- a/lib/arm64/processor.c
+++ b/lib/arm64/processor.c
@@ -9,6 +9,7 @@
 #include 
 #include 
 #include 
+#include 
 
 static const char *vector_names[] = {
"el1t_sync",
@@ -253,3 +254,17 @@ bool is_user(void)
 {
return current_thread_info()->flags & TIF_USER_MODE;
 }
+
+void delay(u64 cycles)
+{
+   u64 start = get_cntvct();
+   while ((get_cntvct() - start) < cycles)
+   cpu_relax();
+}
+
+void udelay(unsigned long usec)
+{
+   unsigned int frq;
+   asm volatile("mrs %0, cntfrq_el0" : "=r" (frq));
+   delay((u64)usec * frq / 100);
+}
-- 
2.7.4

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


[kvm-unit-tests PATCH v4 08/11] libcflat: add IS_ALIGNED() macro, and page sizes

2016-11-10 Thread Andrew Jones
From: Peter Xu 

These macros will be useful to do page alignment checks.

Signed-off-by: Peter Xu 
[drew: also added SZ_64K]
Signed-off-by: Andrew Jones 
---
 lib/libcflat.h | 6 ++
 1 file changed, 6 insertions(+)

diff --git a/lib/libcflat.h b/lib/libcflat.h
index 82005f5d014f..143fc53061fe 100644
--- a/lib/libcflat.h
+++ b/lib/libcflat.h
@@ -33,6 +33,12 @@
 #define __ALIGN_MASK(x, mask)  (((x) + (mask)) & ~(mask))
 #define __ALIGN(x, a)  __ALIGN_MASK(x, (typeof(x))(a) - 1)
 #define ALIGN(x, a)__ALIGN((x), (a))
+#define IS_ALIGNED(x, a)   (((x) & ((typeof(x))(a) - 1)) == 0)
+
+#define SZ_4K  (0x1000)
+#define SZ_64K (0x1)
+#define SZ_2M  (0x20)
+#define SZ_1G  (0x4000)
 
 typedef uint8_tu8;
 typedef int8_t s8;
-- 
2.7.4

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


[kvm-unit-tests PATCH v4 02/11] arm64: fix get_"sysreg32" and make MPIDR 64bit

2016-11-10 Thread Andrew Jones
mrs is always 64bit, so we should always use a 64bit register.
Sometimes we'll only want to return the lower 32, but not for
MPIDR, as that does define fields in the upper 32.

Reviewed-by: Alex Bennée 
Reviewed-by: Eric Auger 
Signed-off-by: Andrew Jones 
---
 lib/arm64/asm/processor.h | 15 +--
 1 file changed, 9 insertions(+), 6 deletions(-)

diff --git a/lib/arm64/asm/processor.h b/lib/arm64/asm/processor.h
index 84d5c7ce752b..9a208ff729b7 100644
--- a/lib/arm64/asm/processor.h
+++ b/lib/arm64/asm/processor.h
@@ -66,14 +66,17 @@ static inline unsigned long current_level(void)
return el & 0xc;
 }
 
-#define DEFINE_GET_SYSREG32(reg)   \
-static inline unsigned int get_##reg(void) \
+#define DEFINE_GET_SYSREG(reg, type)   \
+static inline type get_##reg(void) \
 {  \
-   unsigned int reg;   \
-   asm volatile("mrs %0, " #reg "_el1" : "=r" (reg));  \
-   return reg; \
+   unsigned long r;\
+   asm volatile("mrs %0, " #reg "_el1" : "=r" (r));\
+   return (type)r; \
 }
-DEFINE_GET_SYSREG32(mpidr)
+#define DEFINE_GET_SYSREG32(reg) DEFINE_GET_SYSREG(reg, unsigned int)
+#define DEFINE_GET_SYSREG64(reg) DEFINE_GET_SYSREG(reg, unsigned long)
+
+DEFINE_GET_SYSREG64(mpidr)
 
 /* Only support Aff0 for now, gicv2 only */
 #define mpidr_to_cpu(mpidr) ((int)((mpidr) & 0xff))
-- 
2.7.4

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


[kvm-unit-tests PATCH v4 01/11] lib: xstr: allow multiple args

2016-11-10 Thread Andrew Jones
Make implementation equivalent to Linux's include/linux/stringify.h

Reviewed-by: Eric Auger 
Signed-off-by: Andrew Jones 
---
 lib/libcflat.h | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/lib/libcflat.h b/lib/libcflat.h
index 72b1bf9668ef..82005f5d014f 100644
--- a/lib/libcflat.h
+++ b/lib/libcflat.h
@@ -27,8 +27,8 @@
 
 #define __unused __attribute__((__unused__))
 
-#define xstr(s) xxstr(s)
-#define xxstr(s) #s
+#define xstr(s...) xxstr(s)
+#define xxstr(s...) #s
 
 #define __ALIGN_MASK(x, mask)  (((x) + (mask)) & ~(mask))
 #define __ALIGN(x, a)  __ALIGN_MASK(x, (typeof(x))(a) - 1)
-- 
2.7.4

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


[kvm-unit-tests PATCH v4 07/11] arm/arm64: gicv2: add an IPI test

2016-11-10 Thread Andrew Jones
Reviewed-by: Eric Auger 
Signed-off-by: Andrew Jones 
---
v4: properly mask irqnr in ipi_handler
v2: add more details in the output if a test fails,
report spurious interrupts if we get them
---
 arm/Makefile.common |   6 +-
 arm/gic.c   | 195 
 arm/unittests.cfg   |   7 ++
 lib/arm/asm/gic.h   |   6 ++
 4 files changed, 211 insertions(+), 3 deletions(-)
 create mode 100644 arm/gic.c

diff --git a/arm/Makefile.common b/arm/Makefile.common
index 41239c37e092..bc38183ab86e 100644
--- a/arm/Makefile.common
+++ b/arm/Makefile.common
@@ -9,9 +9,9 @@ ifeq ($(LOADADDR),)
LOADADDR = 0x4000
 endif
 
-tests-common = \
-   $(TEST_DIR)/selftest.flat \
-   $(TEST_DIR)/spinlock-test.flat
+tests-common  = $(TEST_DIR)/selftest.flat
+tests-common += $(TEST_DIR)/spinlock-test.flat
+tests-common += $(TEST_DIR)/gic.flat
 
 all: test_cases
 
diff --git a/arm/gic.c b/arm/gic.c
new file mode 100644
index ..efefab7296d4
--- /dev/null
+++ b/arm/gic.c
@@ -0,0 +1,195 @@
+/*
+ * GIC tests
+ *
+ * GICv2
+ *   + test sending/receiving IPIs
+ *
+ * Copyright (C) 2016, Red Hat Inc, Andrew Jones 
+ *
+ * This work is licensed under the terms of the GNU LGPL, version 2.
+ */
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+static int gic_version;
+static int acked[NR_CPUS], spurious[NR_CPUS];
+static cpumask_t ready;
+
+static void nr_cpu_check(int nr)
+{
+   if (nr_cpus < nr)
+   report_abort("At least %d cpus required", nr);
+}
+
+static void wait_on_ready(void)
+{
+   cpumask_set_cpu(smp_processor_id(), );
+   while (!cpumask_full())
+   cpu_relax();
+}
+
+static void check_acked(cpumask_t *mask)
+{
+   int missing = 0, extra = 0, unexpected = 0;
+   int nr_pass, cpu, i;
+
+   /* Wait up to 5s for all interrupts to be delivered */
+   for (i = 0; i < 50; ++i) {
+   mdelay(100);
+   nr_pass = 0;
+   for_each_present_cpu(cpu) {
+   smp_rmb();
+   nr_pass += cpumask_test_cpu(cpu, mask) ?
+   acked[cpu] == 1 : acked[cpu] == 0;
+   }
+   if (nr_pass == nr_cpus) {
+   report("Completed in %d ms", true, ++i * 100);
+   return;
+   }
+   }
+
+   for_each_present_cpu(cpu) {
+   if (cpumask_test_cpu(cpu, mask)) {
+   if (!acked[cpu])
+   ++missing;
+   else if (acked[cpu] > 1)
+   ++extra;
+   } else {
+   if (acked[cpu])
+   ++unexpected;
+   }
+   }
+
+   report("Timed-out (5s). ACKS: missing=%d extra=%d unexpected=%d",
+  false, missing, extra, unexpected);
+}
+
+static void ipi_handler(struct pt_regs *regs __unused)
+{
+   u32 irqstat = readl(gicv2_cpu_base() + GIC_CPU_INTACK);
+   u32 irqnr = irqstat & GICC_IAR_INT_ID_MASK;
+
+   if (irqnr != GICC_INT_SPURIOUS) {
+   writel(irqstat, gicv2_cpu_base() + GIC_CPU_EOI);
+   smp_rmb(); /* pairs with wmb in ipi_test functions */
+   ++acked[smp_processor_id()];
+   smp_wmb(); /* pairs with rmb in check_acked */
+   } else {
+   ++spurious[smp_processor_id()];
+   smp_wmb();
+   }
+}
+
+static void ipi_test_self(void)
+{
+   cpumask_t mask;
+
+   report_prefix_push("self");
+   memset(acked, 0, sizeof(acked));
+   smp_wmb();
+   cpumask_clear();
+   cpumask_set_cpu(0, );
+   writel(2 << 24, gicv2_dist_base() + GIC_DIST_SOFTINT);
+   check_acked();
+   report_prefix_pop();
+}
+
+static void ipi_test_smp(void)
+{
+   cpumask_t mask;
+   unsigned long tlist;
+
+   report_prefix_push("target-list");
+   memset(acked, 0, sizeof(acked));
+   smp_wmb();
+   tlist = cpumask_bits(_present_mask)[0] & 0xaa;
+   cpumask_bits()[0] = tlist;
+   writel((u8)tlist << 16, gicv2_dist_base() + GIC_DIST_SOFTINT);
+   check_acked();
+   report_prefix_pop();
+
+   report_prefix_push("broadcast");
+   memset(acked, 0, sizeof(acked));
+   smp_wmb();
+   cpumask_copy(, _present_mask);
+   cpumask_clear_cpu(0, );
+   writel(1 << 24, gicv2_dist_base() + GIC_DIST_SOFTINT);
+   check_acked();
+   report_prefix_pop();
+}
+
+static void ipi_enable(void)
+{
+   gicv2_enable_defaults();
+#ifdef __arm__
+   install_exception_handler(EXCPTN_IRQ, ipi_handler);
+#else
+   install_irq_handler(EL1H_IRQ, ipi_handler);
+#endif
+   local_irq_enable();
+}
+
+static void ipi_recv(void)
+{
+   ipi_enable();
+   cpumask_set_cpu(smp_processor_id(), );
+   while (1)
+   wfi();
+}
+
+int 

[kvm-unit-tests PATCH v4 11/11] arm/arm64: gic: don't just use zero

2016-11-10 Thread Andrew Jones
Allow user to select who sends ipis and with which irq,
rather than just always sending irq=0 from cpu0.

Signed-off-by: Andrew Jones 

---
v4: improve structure and make sure spurious checking is
done even when the sender isn't cpu0
v2: actually check that the irq received was the irq sent,
and (for gicv2) that the sender is the expected one.
---
 arm/gic.c | 99 ++-
 1 file changed, 73 insertions(+), 26 deletions(-)

diff --git a/arm/gic.c b/arm/gic.c
index d98ca6b9efd5..8e50bc1b35e0 100644
--- a/arm/gic.c
+++ b/arm/gic.c
@@ -11,6 +11,7 @@
  * This work is licensed under the terms of the GNU LGPL, version 2.
  */
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -34,6 +35,8 @@ static struct gic *gic;
 static int gic_version;
 static int acked[NR_CPUS], spurious[NR_CPUS];
 static cpumask_t ready;
+static int sender;
+static u32 irq;
 
 static void nr_cpu_check(int nr)
 {
@@ -86,7 +89,16 @@ static void check_acked(cpumask_t *mask)
 
 static u32 gicv2_read_iar(void)
 {
-   return readl(gicv2_cpu_base() + GIC_CPU_INTACK);
+   u32 iar = readl(gicv2_cpu_base() + GIC_CPU_INTACK);
+   int src = (iar >> 10) & 7;
+
+   if (src != sender) {
+   report("cpu%d received IPI from unexpected source cpu%d "
+  "(expected cpu%d)",
+  false, smp_processor_id(), src, sender);
+   }
+
+   return iar;
 }
 
 static u32 gicv2_irqnr(u32 iar)
@@ -111,9 +123,15 @@ static void ipi_handler(struct pt_regs *regs __unused)
 
if (irqnr != GICC_INT_SPURIOUS) {
gic->write_eoi(irqstat);
-   smp_rmb(); /* pairs with wmb in ipi_test functions */
-   ++acked[smp_processor_id()];
-   smp_wmb(); /* pairs with rmb in check_acked */
+   if (irqnr == irq) {
+   smp_rmb(); /* pairs with wmb in ipi_test functions */
+   ++acked[smp_processor_id()];
+   smp_wmb(); /* pairs with rmb in check_acked */
+   } else {
+   report("cpu%d received unexpected irq %u "
+  "(expected %u)",
+  false, smp_processor_id(), irqnr, irq);
+   }
} else {
++spurious[smp_processor_id()];
smp_wmb();
@@ -122,19 +140,19 @@ static void ipi_handler(struct pt_regs *regs __unused)
 
 static void gicv2_ipi_send_self(void)
 {
-   writel(2 << 24, gicv2_dist_base() + GIC_DIST_SOFTINT);
+   writel(2 << 24 | irq, gicv2_dist_base() + GIC_DIST_SOFTINT);
 }
 
 static void gicv2_ipi_send_tlist(cpumask_t *mask)
 {
u8 tlist = (u8)cpumask_bits(mask)[0];
 
-   writel(tlist << 16, gicv2_dist_base() + GIC_DIST_SOFTINT);
+   writel(tlist << 16 | irq, gicv2_dist_base() + GIC_DIST_SOFTINT);
 }
 
 static void gicv2_ipi_send_broadcast(void)
 {
-   writel(1 << 24, gicv2_dist_base() + GIC_DIST_SOFTINT);
+   writel(1 << 24 | irq, gicv2_dist_base() + GIC_DIST_SOFTINT);
 }
 
 #define ICC_SGI1R_AFFINITY_1_SHIFT 16
@@ -200,7 +218,7 @@ static void gicv3_ipi_send_tlist(cpumask_t *mask)
/* Send the IPIs for the target list of this cluster */
sgi1r = (MPIDR_TO_SGI_AFFINITY(cluster_id, 3)   |
 MPIDR_TO_SGI_AFFINITY(cluster_id, 2)   |
-/* irq << 24   | */
+irq << 24  |
 MPIDR_TO_SGI_AFFINITY(cluster_id, 1)   |
 tlist);
 
@@ -222,7 +240,7 @@ static void gicv3_ipi_send_self(void)
 
 static void gicv3_ipi_send_broadcast(void)
 {
-   gicv3_write_sgi1r(1ULL << 40);
+   gicv3_write_sgi1r(1ULL << 40 | irq << 24);
isb();
 }
 
@@ -234,7 +252,7 @@ static void ipi_test_self(void)
memset(acked, 0, sizeof(acked));
smp_wmb();
cpumask_clear();
-   cpumask_set_cpu(0, );
+   cpumask_set_cpu(smp_processor_id(), );
gic->ipi.send_self();
check_acked();
report_prefix_pop();
@@ -249,7 +267,7 @@ static void ipi_test_smp(void)
memset(acked, 0, sizeof(acked));
smp_wmb();
cpumask_copy(, _present_mask);
-   for (i = 0; i < nr_cpus; i += 2)
+   for (i = smp_processor_id() & 1; i < nr_cpus; i += 2)
cpumask_clear_cpu(i, );
gic->ipi.send_tlist();
check_acked();
@@ -259,7 +277,7 @@ static void ipi_test_smp(void)
memset(acked, 0, sizeof(acked));
smp_wmb();
cpumask_copy(, _present_mask);
-   cpumask_clear_cpu(0, );
+   cpumask_clear_cpu(smp_processor_id(), );
gic->ipi.send_broadcast();
check_acked();
report_prefix_pop();
@@ -276,6 +294,27 @@ static void ipi_enable(void)
local_irq_enable();
 }
 
+static void ipi_send(void)
+{
+   int cpu;
+
+   ipi_enable();
+   

[kvm-unit-tests PATCH v4 03/11] arm/arm64: smp: support more than 8 cpus

2016-11-10 Thread Andrew Jones
By adding support for launching with gicv3 we can break the 8 vcpu
limit. This patch adds support to smp code and also selects the
vgic model corresponding to the host. The vgic model may also be
manually selected by adding e.g. -machine gic-version=3 to
extra_params.

Reviewed-by: Alex Bennée 
Signed-off-by: Andrew Jones 

---
v4: improved commit message
---
 arm/run   | 19 ---
 arm/selftest.c|  5 -
 lib/arm/asm/processor.h   |  9 +++--
 lib/arm/asm/setup.h   |  4 ++--
 lib/arm/setup.c   | 12 +++-
 lib/arm64/asm/processor.h |  9 +++--
 6 files changed, 43 insertions(+), 15 deletions(-)

diff --git a/arm/run b/arm/run
index a2f35ef6a7e6..2d0698619606 100755
--- a/arm/run
+++ b/arm/run
@@ -31,13 +31,6 @@ if [ -z "$ACCEL" ]; then
fi
 fi
 
-if [ "$HOST" = "aarch64" ] && [ "$ACCEL" = "kvm" ]; then
-   processor="host"
-   if [ "$ARCH" = "arm" ]; then
-   processor+=",aarch64=off"
-   fi
-fi
-
 qemu="${QEMU:-qemu-system-$ARCH_NAME}"
 qpath=$(which $qemu 2>/dev/null)
 
@@ -53,6 +46,18 @@ fi
 
 M='-machine virt'
 
+if [ "$ACCEL" = "kvm" ]; then
+   if $qemu $M,\? 2>&1 | grep gic-version > /dev/null; then
+   M+=',gic-version=host'
+   fi
+   if [ "$HOST" = "aarch64" ]; then
+   processor="host"
+   if [ "$ARCH" = "arm" ]; then
+   processor+=",aarch64=off"
+   fi
+   fi
+fi
+
 if ! $qemu $M -device '?' 2>&1 | grep virtconsole > /dev/null; then
echo "$qpath doesn't support virtio-console for chr-testdev. Exiting."
exit 2
diff --git a/arm/selftest.c b/arm/selftest.c
index 196164f5313d..2f117f795d2d 100644
--- a/arm/selftest.c
+++ b/arm/selftest.c
@@ -312,9 +312,10 @@ static bool psci_check(void)
 static cpumask_t smp_reported;
 static void cpu_report(void)
 {
+   unsigned long mpidr = get_mpidr();
int cpu = smp_processor_id();
 
-   report("CPU%d online", true, cpu);
+   report("CPU(%3d) mpidr=%lx", mpidr_to_cpu(mpidr) == cpu, cpu, mpidr);
cpumask_set_cpu(cpu, _reported);
halt();
 }
@@ -343,6 +344,7 @@ int main(int argc, char **argv)
 
} else if (strcmp(argv[1], "smp") == 0) {
 
+   unsigned long mpidr = get_mpidr();
int cpu;
 
report("PSCI version", psci_check());
@@ -353,6 +355,7 @@ int main(int argc, char **argv)
smp_boot_secondary(cpu, cpu_report);
}
 
+   report("CPU(%3d) mpidr=%lx", mpidr_to_cpu(mpidr) == 0, 0, 
mpidr);
cpumask_set_cpu(0, _reported);
while (!cpumask_full(_reported))
cpu_relax();
diff --git a/lib/arm/asm/processor.h b/lib/arm/asm/processor.h
index f25e7eee3666..d2048f5f5f7e 100644
--- a/lib/arm/asm/processor.h
+++ b/lib/arm/asm/processor.h
@@ -40,8 +40,13 @@ static inline unsigned int get_mpidr(void)
return mpidr;
 }
 
-/* Only support Aff0 for now, up to 4 cpus */
-#define mpidr_to_cpu(mpidr) ((int)((mpidr) & 0xff))
+#define MPIDR_HWID_BITMASK 0xff
+extern int mpidr_to_cpu(unsigned long mpidr);
+
+#define MPIDR_LEVEL_SHIFT(level) \
+   (((1 << level) >> 1) << 3)
+#define MPIDR_AFFINITY_LEVEL(mpidr, level) \
+   ((mpidr >> MPIDR_LEVEL_SHIFT(level)) & 0xff)
 
 extern void start_usr(void (*func)(void *arg), void *arg, unsigned long 
sp_usr);
 extern bool is_user(void);
diff --git a/lib/arm/asm/setup.h b/lib/arm/asm/setup.h
index cb8fdbd38dd5..b0d51f5f0721 100644
--- a/lib/arm/asm/setup.h
+++ b/lib/arm/asm/setup.h
@@ -10,8 +10,8 @@
 #include 
 #include 
 
-#define NR_CPUS8
-extern u32 cpus[NR_CPUS];
+#define NR_CPUS255
+extern u64 cpus[NR_CPUS];  /* per-cpu IDs (MPIDRs) */
 extern int nr_cpus;
 
 #define NR_MEM_REGIONS 8
diff --git a/lib/arm/setup.c b/lib/arm/setup.c
index 7e7b39f11dde..b6e2d5815e72 100644
--- a/lib/arm/setup.c
+++ b/lib/arm/setup.c
@@ -24,12 +24,22 @@ extern unsigned long stacktop;
 extern void io_init(void);
 extern void setup_args_progname(const char *args);
 
-u32 cpus[NR_CPUS] = { [0 ... NR_CPUS-1] = (~0U) };
+u64 cpus[NR_CPUS] = { [0 ... NR_CPUS-1] = (~0U) };
 int nr_cpus;
 
 struct mem_region mem_regions[NR_MEM_REGIONS];
 phys_addr_t __phys_offset, __phys_end;
 
+int mpidr_to_cpu(unsigned long mpidr)
+{
+   int i;
+
+   for (i = 0; i < nr_cpus; ++i)
+   if (cpus[i] == (mpidr & MPIDR_HWID_BITMASK))
+   return i;
+   return -1;
+}
+
 static void cpu_set(int fdtnode __unused, u32 regval, void *info __unused)
 {
int cpu = nr_cpus++;
diff --git a/lib/arm64/asm/processor.h b/lib/arm64/asm/processor.h
index 9a208ff729b7..7e448dc81a6a 100644
--- a/lib/arm64/asm/processor.h
+++ b/lib/arm64/asm/processor.h
@@ -78,8 +78,13 @@ static inline type get_##reg(void)   
\
 
 

[kvm-unit-tests PATCH v4 06/11] arm/arm64: add initial gicv2 support

2016-11-10 Thread Andrew Jones
Add some gicv2 support. This just adds init and enable
functions, allowing unit tests to start messing with it.

Signed-off-by: Andrew Jones 

---
v4:
 - only take defines from kernel we need now [Andre]
 - moved defines to asm/gic.h so they'll be shared with v3 [drew]
 - simplify enable by not caring if we reinit the distributor [drew]
 - init all GICD_INT_DEF_PRI_X4 registers [Eric]
---
 arm/Makefile.common|  1 +
 lib/arm/asm/gic-v2.h   | 28 +++
 lib/arm/asm/gic.h  | 44 +
 lib/arm/gic.c  | 75 ++
 lib/arm64/asm/gic-v2.h |  1 +
 lib/arm64/asm/gic.h|  1 +
 6 files changed, 150 insertions(+)
 create mode 100644 lib/arm/asm/gic-v2.h
 create mode 100644 lib/arm/asm/gic.h
 create mode 100644 lib/arm/gic.c
 create mode 100644 lib/arm64/asm/gic-v2.h
 create mode 100644 lib/arm64/asm/gic.h

diff --git a/arm/Makefile.common b/arm/Makefile.common
index ccb554d9251a..41239c37e092 100644
--- a/arm/Makefile.common
+++ b/arm/Makefile.common
@@ -42,6 +42,7 @@ cflatobjs += lib/arm/mmu.o
 cflatobjs += lib/arm/bitops.o
 cflatobjs += lib/arm/psci.o
 cflatobjs += lib/arm/smp.o
+cflatobjs += lib/arm/gic.o
 
 libeabi = lib/arm/libeabi.a
 eabiobjs = lib/arm/eabi_compat.o
diff --git a/lib/arm/asm/gic-v2.h b/lib/arm/asm/gic-v2.h
new file mode 100644
index ..f91530f88355
--- /dev/null
+++ b/lib/arm/asm/gic-v2.h
@@ -0,0 +1,28 @@
+/*
+ * All GIC* defines are lifted from include/linux/irqchip/arm-gic.h
+ *
+ * Copyright (C) 2016, Red Hat Inc, Andrew Jones 
+ *
+ * This work is licensed under the terms of the GNU LGPL, version 2.
+ */
+#ifndef _ASMARM_GIC_V2_H_
+#define _ASMARM_GIC_V2_H_
+
+#ifndef _ASMARM_GIC_H_
+#error Do not directly include . Include 
+#endif
+
+struct gicv2_data {
+   void *dist_base;
+   void *cpu_base;
+   unsigned int irq_nr;
+};
+extern struct gicv2_data gicv2_data;
+
+#define gicv2_dist_base()  (gicv2_data.dist_base)
+#define gicv2_cpu_base()   (gicv2_data.cpu_base)
+
+extern int gicv2_init(void);
+extern void gicv2_enable_defaults(void);
+
+#endif /* _ASMARM_GIC_V2_H_ */
diff --git a/lib/arm/asm/gic.h b/lib/arm/asm/gic.h
new file mode 100644
index ..ec92f1064dc0
--- /dev/null
+++ b/lib/arm/asm/gic.h
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2016, Red Hat Inc, Andrew Jones 
+ *
+ * This work is licensed under the terms of the GNU LGPL, version 2.
+ */
+#ifndef _ASMARM_GIC_H_
+#define _ASMARM_GIC_H_
+
+#include 
+
+#define GIC_CPU_CTRL   0x00
+#define GIC_CPU_PRIMASK0x04
+
+#define GICC_ENABLE0x1
+#define GICC_INT_PRI_THRESHOLD 0xf0
+
+#define GIC_DIST_CTRL  0x000
+#define GIC_DIST_CTR   0x004
+#define GIC_DIST_ENABLE_SET0x100
+#define GIC_DIST_PRI   0x400
+
+#define GICD_ENABLE0x1
+#define GICD_INT_EN_SET_SGI0x
+#define GICD_INT_DEF_PRI   0xa0
+#define GICD_INT_DEF_PRI_X4((GICD_INT_DEF_PRI << 24) |\
+   (GICD_INT_DEF_PRI << 16) |\
+   (GICD_INT_DEF_PRI << 8) |\
+   GICD_INT_DEF_PRI)
+
+#define GICD_TYPER_IRQS(typer) typer) & 0x1f) + 1) * 32)
+
+#ifndef __ASSEMBLY__
+
+/*
+ * gic_init will try to find all known gics, and then
+ * initialize the gic data for the one found.
+ * returns
+ *  0   : no gic was found
+ *  > 0 : the gic version of the gic found
+ */
+extern int gic_init(void);
+
+#endif /* !__ASSEMBLY__ */
+#endif /* _ASMARM_GIC_H_ */
diff --git a/lib/arm/gic.c b/lib/arm/gic.c
new file mode 100644
index ..91d78c9a0cc2
--- /dev/null
+++ b/lib/arm/gic.c
@@ -0,0 +1,75 @@
+/*
+ * Copyright (C) 2016, Red Hat Inc, Andrew Jones 
+ *
+ * This work is licensed under the terms of the GNU LGPL, version 2.
+ */
+#include 
+#include 
+#include 
+
+struct gicv2_data gicv2_data;
+
+/*
+ * Documentation/devicetree/bindings/interrupt-controller/arm,gic.txt
+ */
+static bool
+gic_get_dt_bases(const char *compatible, void **base1, void **base2)
+{
+   struct dt_pbus_reg reg;
+   struct dt_device gic;
+   struct dt_bus bus;
+   int node, ret;
+
+   dt_bus_init_defaults();
+   dt_device_init(, , NULL);
+
+   node = dt_device_find_compatible(, compatible);
+   assert(node >= 0 || node == -FDT_ERR_NOTFOUND);
+
+   if (node == -FDT_ERR_NOTFOUND)
+   return false;
+
+   dt_device_bind_node(, node);
+
+   ret = dt_pbus_translate(, 0, );
+   assert(ret == 0);
+   *base1 = ioremap(reg.addr, reg.size);
+
+   ret = dt_pbus_translate(, 1, );
+   assert(ret == 0);
+   *base2 = ioremap(reg.addr, reg.size);
+
+   return true;
+}
+
+int gicv2_init(void)
+{
+   return 

[kvm-unit-tests PATCH v4 00/11] arm/arm64: add gic framework

2016-11-10 Thread Andrew Jones
v4:
 - Eric's r-b's
 - Andre's suggestion to only take defines we need
 - several other changes listed in individual patches

v3:
 - Rebased on latest master
 - Added Alex's r-b's

v2:
 Rebased on latest master + my "populate argv[0]" series (will
 send a REPOST for that shortly. Additionally a few patches got
 fixes/features;
 07/10 got same fix as kernel 7c9b973061 "irqchip/gic-v3: Configure
   all interrupts as non-secure Group-1" in order to continue
   working over TCG, as the gicv3 code for TCG removed a hack
   it had there to make Linux happy.
 08/10 added more output for when things fail (if they fail)
 09/10 switched gicv3 broadcast implementation to using IRM. This
   found a bug in a recent (but not tip) kernel, which I was
   about to fix, but then I saw MarcZ beat me to it.
 10/10 actually check that the input irq is the received irq


Import defines, and steal enough helper functions, from Linux to
enable programming of the gic (v2 and v3). Then use the framework
to add an initial test (an ipi test; self, target-list, broadcast).

It's my hope that this framework will be a suitable base on which
more tests may be easily added, particularly because we have
vgic-new and tcg gicv3 emulation getting close to merge. (v3 UPDATE:
vgic-new and tcg gicv3 are merged now)

To run it, along with other tests, just do

 ./configure [ --arch=[arm|arm64] --cross-prefix=$PREFIX ]
 make
 export QEMU=$PATH_TO_QEMU
 ./run_tests.sh

To run it separately do, e.g.

$QEMU -machine virt,accel=tcg -cpu cortex-a57 \
 -device virtio-serial-device \
 -device virtconsole,chardev=ctd -chardev testdev,id=ctd \
 -display none -serial stdio \
 -kernel arm/gic.flat \
 -smp 123 -machine gic-version=3 -append ipi
  ^^ note, we can go nuts with nr-cpus on TCG :-)

Or, a KVM example using a different "sender" cpu and irq (other than zero)

$QEMU -machine virt,accel=kvm -cpu host \
 -device virtio-serial-device \
 -device virtconsole,chardev=ctd -chardev testdev,id=ctd \
 -display none -serial stdio \
 -kernel arm/gic.flat \
 -smp 48 -machine gic-version=3 -append 'ipi sender=42 irq=1'


Patches:
01-05: fixes and functionality needed by the later gic patches
06-07: enable gicv2 and gicv2 IPI test
08-10: enable gicv3 and gicv3 IPI test
   11: extend the IPI tests to take variable sender and irq

Available here: https://github.com/rhdrjones/kvm-unit-tests/commits/arm/gic-v4


Andrew Jones (10):
  lib: xstr: allow multiple args
  arm64: fix get_"sysreg32" and make MPIDR 64bit
  arm/arm64: smp: support more than 8 cpus
  arm/arm64: add some delay routines
  arm/arm64: irq enable/disable
  arm/arm64: add initial gicv2 support
  arm/arm64: gicv2: add an IPI test
  arm/arm64: add initial gicv3 support
  arm/arm64: gicv3: add an IPI test
  arm/arm64: gic: don't just use zero

Peter Xu (1):
  libcflat: add IS_ALIGNED() macro, and page sizes

 arm/Makefile.common|   7 +-
 arm/gic.c  | 417 +
 arm/run|  19 ++-
 arm/selftest.c |   5 +-
 arm/unittests.cfg  |  13 ++
 lib/arm/asm/arch_gicv3.h   |  65 +++
 lib/arm/asm/gic-v2.h   |  28 +++
 lib/arm/asm/gic-v3.h   |  92 ++
 lib/arm/asm/gic.h  |  51 ++
 lib/arm/asm/processor.h|  38 -
 lib/arm/asm/setup.h|   4 +-
 lib/arm/gic.c  | 131 ++
 lib/arm/processor.c|  15 ++
 lib/arm/setup.c|  12 +-
 lib/arm64/asm/arch_gicv3.h |  66 +++
 lib/arm64/asm/gic-v2.h |   1 +
 lib/arm64/asm/gic-v3.h |   1 +
 lib/arm64/asm/gic.h|   1 +
 lib/arm64/asm/processor.h  |  53 +-
 lib/arm64/asm/sysreg.h |  44 +
 lib/arm64/processor.c  |  15 ++
 lib/libcflat.h |  10 +-
 22 files changed, 1062 insertions(+), 26 deletions(-)
 create mode 100644 arm/gic.c
 create mode 100644 lib/arm/asm/arch_gicv3.h
 create mode 100644 lib/arm/asm/gic-v2.h
 create mode 100644 lib/arm/asm/gic-v3.h
 create mode 100644 lib/arm/asm/gic.h
 create mode 100644 lib/arm/gic.c
 create mode 100644 lib/arm64/asm/arch_gicv3.h
 create mode 100644 lib/arm64/asm/gic-v2.h
 create mode 100644 lib/arm64/asm/gic-v3.h
 create mode 100644 lib/arm64/asm/gic.h
 create mode 100644 lib/arm64/asm/sysreg.h

-- 
2.7.4

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


Re: [PATCH 1/2] arm64: perf: Move ARMv8 PMU perf event definitions to asm/perf_event.h

2016-11-10 Thread Marc Zyngier
On 10/11/16 15:12, Wei Huang wrote:
> 
> 
> On 11/10/2016 03:10 AM, Marc Zyngier wrote:
>> Hi Wei,
>>
>> On 09/11/16 19:57, Wei Huang wrote:
>>> This patch moves ARMv8-related perf event definitions from perf_event.c
>>> to asm/perf_event.h; so KVM code can use them directly. This also help
>>> remove a duplicated definition of SW_INCR in perf_event.h.
>>>
>>> Signed-off-by: Wei Huang 
>>> ---
>>>  arch/arm64/include/asm/perf_event.h | 161 
>>> +++-
>>>  arch/arm64/kernel/perf_event.c  | 161 
>>> 
>>>  2 files changed, 160 insertions(+), 162 deletions(-)
>>>
>>> diff --git a/arch/arm64/include/asm/perf_event.h 
>>> b/arch/arm64/include/asm/perf_event.h
>>> index 2065f46..6c7b18b 100644
>>> --- a/arch/arm64/include/asm/perf_event.h
>>> +++ b/arch/arm64/include/asm/perf_event.h
>>> @@ -46,7 +46,166 @@
>>>  #defineARMV8_PMU_EVTYPE_MASK   0xc800  /* Mask for writable 
>>> bits */
>>>  #defineARMV8_PMU_EVTYPE_EVENT  0x  /* Mask for EVENT bits 
>>> */
>>>  
>>> -#define ARMV8_PMU_EVTYPE_EVENT_SW_INCR 0   /* Software increment 
>>> event */
>>> +/*
>>> + * ARMv8 PMUv3 Performance Events handling code.
>>> + * Common event types.
>>> + */
>>> +
>>> +/* Required events. */
>>> +#define ARMV8_PMUV3_PERFCTR_SW_INCR0x00
>>> +#define ARMV8_PMUV3_PERFCTR_L1D_CACHE_REFILL   0x03
>>> +#define ARMV8_PMUV3_PERFCTR_L1D_CACHE  0x04
>>> +#define ARMV8_PMUV3_PERFCTR_BR_MIS_PRED0x10
>>> +#define ARMV8_PMUV3_PERFCTR_CPU_CYCLES 0x11
>>> +#define ARMV8_PMUV3_PERFCTR_BR_PRED0x12
>>
>> In my initial review, I asked for the "required" events to be moved to a
>> shared location. What's the rational for moving absolutely everything?
> 
> I did notice the phrase "required" in the original email. However I
> think it is weird to have two places for a same set of PMU definitions.
> Other developers might think these two are missing if they don't search
> kernel files carefully.
> 
> If Will Deacon and you insist, I can move only two defs to perf_event.h,
> consolidated with the 2nd patch into a single one.

My personal feeling is that only architected events should be in a
public header. The CPU-specific ones are probably better kept private,
as it is doubtful that other users would appear).

I'll leave it up to Will to decide, as all I want to avoid is the
duplication of constants between the PMU and KVM code bases.

Thanks,

M.
-- 
Jazz is not dead. It just smells funny...
___
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm


Re: [PATCH 1/2] arm64: perf: Move ARMv8 PMU perf event definitions to asm/perf_event.h

2016-11-10 Thread Mark Rutland
On Thu, Nov 10, 2016 at 09:12:35AM -0600, Wei Huang wrote:
> On 11/10/2016 03:10 AM, Marc Zyngier wrote:
> > On 09/11/16 19:57, Wei Huang wrote:
> >> diff --git a/arch/arm64/include/asm/perf_event.h 
> >> b/arch/arm64/include/asm/perf_event.h

> >> +/*
> >> + * ARMv8 PMUv3 Performance Events handling code.
> >> + * Common event types.
> >> + */
> >> +
> >> +/* Required events. */
> >> +#define ARMV8_PMUV3_PERFCTR_SW_INCR   0x00
> >> +#define ARMV8_PMUV3_PERFCTR_L1D_CACHE_REFILL  0x03
> >> +#define ARMV8_PMUV3_PERFCTR_L1D_CACHE 0x04
> >> +#define ARMV8_PMUV3_PERFCTR_BR_MIS_PRED   0x10
> >> +#define ARMV8_PMUV3_PERFCTR_CPU_CYCLES0x11
> >> +#define ARMV8_PMUV3_PERFCTR_BR_PRED   0x12
> > 
> > In my initial review, I asked for the "required" events to be moved to a
> > shared location. What's the rational for moving absolutely everything?
> 
> I did notice the phrase "required" in the original email. However I
> think it is weird to have two places for a same set of PMU definitions.
> Other developers might think these two are missing if they don't search
> kernel files carefully.
> 
> If Will Deacon and you insist, I can move only two defs to perf_event.h,
> consolidated with the 2nd patch into a single one.

FWIW, my personal preference would be for all the definitions (or at
least all of the ARMV8_PMUV3_* ones) to be in one place.

That said, I don't feel particularly strongly either way, and I'll defer
to Will.

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


Re: [PATCH 1/2] arm64: perf: Move ARMv8 PMU perf event definitions to asm/perf_event.h

2016-11-10 Thread Wei Huang


On 11/10/2016 03:10 AM, Marc Zyngier wrote:
> Hi Wei,
> 
> On 09/11/16 19:57, Wei Huang wrote:
>> This patch moves ARMv8-related perf event definitions from perf_event.c
>> to asm/perf_event.h; so KVM code can use them directly. This also help
>> remove a duplicated definition of SW_INCR in perf_event.h.
>>
>> Signed-off-by: Wei Huang 
>> ---
>>  arch/arm64/include/asm/perf_event.h | 161 
>> +++-
>>  arch/arm64/kernel/perf_event.c  | 161 
>> 
>>  2 files changed, 160 insertions(+), 162 deletions(-)
>>
>> diff --git a/arch/arm64/include/asm/perf_event.h 
>> b/arch/arm64/include/asm/perf_event.h
>> index 2065f46..6c7b18b 100644
>> --- a/arch/arm64/include/asm/perf_event.h
>> +++ b/arch/arm64/include/asm/perf_event.h
>> @@ -46,7 +46,166 @@
>>  #define ARMV8_PMU_EVTYPE_MASK   0xc800  /* Mask for writable 
>> bits */
>>  #define ARMV8_PMU_EVTYPE_EVENT  0x  /* Mask for EVENT bits 
>> */
>>  
>> -#define ARMV8_PMU_EVTYPE_EVENT_SW_INCR  0   /* Software increment 
>> event */
>> +/*
>> + * ARMv8 PMUv3 Performance Events handling code.
>> + * Common event types.
>> + */
>> +
>> +/* Required events. */
>> +#define ARMV8_PMUV3_PERFCTR_SW_INCR 0x00
>> +#define ARMV8_PMUV3_PERFCTR_L1D_CACHE_REFILL0x03
>> +#define ARMV8_PMUV3_PERFCTR_L1D_CACHE   0x04
>> +#define ARMV8_PMUV3_PERFCTR_BR_MIS_PRED 0x10
>> +#define ARMV8_PMUV3_PERFCTR_CPU_CYCLES  0x11
>> +#define ARMV8_PMUV3_PERFCTR_BR_PRED 0x12
> 
> In my initial review, I asked for the "required" events to be moved to a
> shared location. What's the rational for moving absolutely everything?

I did notice the phrase "required" in the original email. However I
think it is weird to have two places for a same set of PMU definitions.
Other developers might think these two are missing if they don't search
kernel files carefully.

If Will Deacon and you insist, I can move only two defs to perf_event.h,
consolidated with the 2nd patch into a single one.

> KVM only needs to know about ARMV8_PMUV3_PERFCTR_SW_INCR and
> ARMV8_PMUV3_PERFCTR_CPU_CYCLES, so I thought that moving the above six
> events (and maybe the following two) would be enough.
> 
> Also, you've now broken the build by dropping
> ARMV8_PMU_EVTYPE_EVENT_SW_INCR without amending it use in the KVM PMU
> code (see the kbuild report).
> 

My bad. I tested compilation only after two patches applied. Will fix it.



>> +
>>  /* PMUv3 HW events mapping. */
>>  
>>  /*
>>
> 
> Thanks,
> 
>   M.
> 
___
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm


Re: [PATCH 1/2] arm64: perf: Move ARMv8 PMU perf event definitions to asm/perf_event.h

2016-11-10 Thread Marc Zyngier
Hi Wei,

On 09/11/16 19:57, Wei Huang wrote:
> This patch moves ARMv8-related perf event definitions from perf_event.c
> to asm/perf_event.h; so KVM code can use them directly. This also help
> remove a duplicated definition of SW_INCR in perf_event.h.
> 
> Signed-off-by: Wei Huang 
> ---
>  arch/arm64/include/asm/perf_event.h | 161 
> +++-
>  arch/arm64/kernel/perf_event.c  | 161 
> 
>  2 files changed, 160 insertions(+), 162 deletions(-)
> 
> diff --git a/arch/arm64/include/asm/perf_event.h 
> b/arch/arm64/include/asm/perf_event.h
> index 2065f46..6c7b18b 100644
> --- a/arch/arm64/include/asm/perf_event.h
> +++ b/arch/arm64/include/asm/perf_event.h
> @@ -46,7 +46,166 @@
>  #define  ARMV8_PMU_EVTYPE_MASK   0xc800  /* Mask for writable 
> bits */
>  #define  ARMV8_PMU_EVTYPE_EVENT  0x  /* Mask for EVENT bits 
> */
>  
> -#define ARMV8_PMU_EVTYPE_EVENT_SW_INCR   0   /* Software increment 
> event */
> +/*
> + * ARMv8 PMUv3 Performance Events handling code.
> + * Common event types.
> + */
> +
> +/* Required events. */
> +#define ARMV8_PMUV3_PERFCTR_SW_INCR  0x00
> +#define ARMV8_PMUV3_PERFCTR_L1D_CACHE_REFILL 0x03
> +#define ARMV8_PMUV3_PERFCTR_L1D_CACHE0x04
> +#define ARMV8_PMUV3_PERFCTR_BR_MIS_PRED  0x10
> +#define ARMV8_PMUV3_PERFCTR_CPU_CYCLES   0x11
> +#define ARMV8_PMUV3_PERFCTR_BR_PRED  0x12

In my initial review, I asked for the "required" events to be moved to a
shared location. What's the rational for moving absolutely everything?
KVM only needs to know about ARMV8_PMUV3_PERFCTR_SW_INCR and
ARMV8_PMUV3_PERFCTR_CPU_CYCLES, so I thought that moving the above six
events (and maybe the following two) would be enough.

Also, you've now broken the build by dropping
ARMV8_PMU_EVTYPE_EVENT_SW_INCR without amending it use in the KVM PMU
code (see the kbuild report).

> +
> +/* At least one of the following is required. */
> +#define ARMV8_PMUV3_PERFCTR_INST_RETIRED 0x08
> +#define ARMV8_PMUV3_PERFCTR_INST_SPEC0x1B
> +
> +/* Common architectural events. */
> +#define ARMV8_PMUV3_PERFCTR_LD_RETIRED   0x06
> +#define ARMV8_PMUV3_PERFCTR_ST_RETIRED   0x07
> +#define ARMV8_PMUV3_PERFCTR_EXC_TAKEN0x09
> +#define ARMV8_PMUV3_PERFCTR_EXC_RETURN   0x0A
> +#define ARMV8_PMUV3_PERFCTR_CID_WRITE_RETIRED0x0B
> +#define ARMV8_PMUV3_PERFCTR_PC_WRITE_RETIRED 0x0C
> +#define ARMV8_PMUV3_PERFCTR_BR_IMMED_RETIRED 0x0D
> +#define ARMV8_PMUV3_PERFCTR_BR_RETURN_RETIRED0x0E
> +#define ARMV8_PMUV3_PERFCTR_UNALIGNED_LDST_RETIRED   0x0F
> +#define ARMV8_PMUV3_PERFCTR_TTBR_WRITE_RETIRED   0x1C
> +#define ARMV8_PMUV3_PERFCTR_CHAIN0x1E
> +#define ARMV8_PMUV3_PERFCTR_BR_RETIRED   0x21
> +
> +/* Common microarchitectural events. */
> +#define ARMV8_PMUV3_PERFCTR_L1I_CACHE_REFILL 0x01
> +#define ARMV8_PMUV3_PERFCTR_L1I_TLB_REFILL   0x02
> +#define ARMV8_PMUV3_PERFCTR_L1D_TLB_REFILL   0x05
> +#define ARMV8_PMUV3_PERFCTR_MEM_ACCESS   0x13
> +#define ARMV8_PMUV3_PERFCTR_L1I_CACHE0x14
> +#define ARMV8_PMUV3_PERFCTR_L1D_CACHE_WB 0x15
> +#define ARMV8_PMUV3_PERFCTR_L2D_CACHE0x16
> +#define ARMV8_PMUV3_PERFCTR_L2D_CACHE_REFILL 0x17
> +#define ARMV8_PMUV3_PERFCTR_L2D_CACHE_WB 0x18
> +#define ARMV8_PMUV3_PERFCTR_BUS_ACCESS   0x19
> +#define ARMV8_PMUV3_PERFCTR_MEMORY_ERROR 0x1A
> +#define ARMV8_PMUV3_PERFCTR_BUS_CYCLES   0x1D
> +#define ARMV8_PMUV3_PERFCTR_L1D_CACHE_ALLOCATE   0x1F
> +#define ARMV8_PMUV3_PERFCTR_L2D_CACHE_ALLOCATE   0x20
> +#define ARMV8_PMUV3_PERFCTR_BR_MIS_PRED_RETIRED  0x22
> +#define ARMV8_PMUV3_PERFCTR_STALL_FRONTEND   0x23
> +#define ARMV8_PMUV3_PERFCTR_STALL_BACKEND0x24
> +#define ARMV8_PMUV3_PERFCTR_L1D_TLB  0x25
> +#define ARMV8_PMUV3_PERFCTR_L1I_TLB  0x26
> +#define ARMV8_PMUV3_PERFCTR_L2I_CACHE0x27
> +#define ARMV8_PMUV3_PERFCTR_L2I_CACHE_REFILL 0x28
> +#define ARMV8_PMUV3_PERFCTR_L3D_CACHE_ALLOCATE   0x29
> +#define ARMV8_PMUV3_PERFCTR_L3D_CACHE_REFILL 0x2A
> +#define ARMV8_PMUV3_PERFCTR_L3D_CACHE