[PATCH v10 8/8] arm/arm64: Documentation: Update arm-vgic-v3.txt

2016-11-30 Thread vijay . kilari
From: Vijaya Kumar K 

Update error code returned for Invalid CPU interface register
value and access in AArch32 mode.

Signed-off-by: Vijaya Kumar K 
---
 Documentation/virtual/kvm/devices/arm-vgic-v3.txt | 9 -
 1 file changed, 8 insertions(+), 1 deletion(-)

diff --git a/Documentation/virtual/kvm/devices/arm-vgic-v3.txt 
b/Documentation/virtual/kvm/devices/arm-vgic-v3.txt
index 9348b3c..0f29850 100644
--- a/Documentation/virtual/kvm/devices/arm-vgic-v3.txt
+++ b/Documentation/virtual/kvm/devices/arm-vgic-v3.txt
@@ -142,10 +142,12 @@ Groups:
 KVM_DEV_ARM_VGIC_CPU_SYSREGS accesses the CPU interface registers for the
 CPU specified by the mpidr field.
 
+CPU interface registers access is not implemented for AArch32 mode.
+Error -ENXIO is returned when accessed in AArch32 mode.
   Errors:
 -ENXIO: Getting or setting this register is not yet supported
 -EBUSY: VCPU is running
--EINVAL: Invalid mpidr supplied
+-EINVAL: Invalid mpidr or register value supplied
 
 
   KVM_DEV_ARM_VGIC_GRP_NR_IRQS
@@ -193,6 +195,11 @@ Groups:
 
Bit[n] indicates the status for interrupt vINTID + n.
 
+   Getting or setting the level info for an edge-triggered interrupt is
+   not guaranteed to work.  To restore the complete state of the VGIC, the
+   configuration (edge/level) of interrupts must be restored before
+   restoring the level.
+
 SGIs and any interrupt with a higher ID than the number of interrupts
 supported, will be RAZ/WI.  LPIs are always edge-triggered and are
 therefore not supported by this interface.
-- 
1.9.1

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


[PATCH v10 6/8] arm/arm64: vgic: Implement VGICv3 CPU interface access

2016-11-30 Thread vijay . kilari
From: Vijaya Kumar K 

VGICv3 CPU interface registers are accessed using
KVM_DEV_ARM_VGIC_CPU_SYSREGS ioctl. These registers are accessed
as 64-bit. The cpu MPIDR value is passed along with register id.
is used to identify the cpu for registers access.

The VM that supports SEIs expect it on destination machine to handle
guest aborts and hence checked for ICC_CTLR_EL1.SEIS compatibility.
Similarly, VM that supports Affinity Level 3 that is required for AArch64
mode, is required to be supported on destination machine. Hence checked
for ICC_CTLR_EL1.A3V compatibility.

The arch/arm64/kvm/vgic-sys-reg-v3.c handles read and write of VGIC
CPU registers for AArch64.

For AArch32 mode, arch/arm/kvm/vgic-v3-coproc.c file is created but
APIs are not implemented.

Updated arch/arm/include/uapi/asm/kvm.h with new definitions
required to compile for AArch32.

The version of VGIC v3 specification is define here
Documentation/virtual/kvm/devices/arm-vgic-v3.txt

Signed-off-by: Pavel Fedin 
Signed-off-by: Vijaya Kumar K 
---
 arch/arm/include/uapi/asm/kvm.h |   2 +
 arch/arm/kvm/Makefile   |   4 +-
 arch/arm/kvm/vgic-v3-coproc.c   |  35 
 arch/arm64/include/uapi/asm/kvm.h   |   3 +
 arch/arm64/kvm/Makefile |   3 +-
 arch/arm64/kvm/vgic-sys-reg-v3.c| 338 
 include/kvm/arm_vgic.h  |   9 +
 virt/kvm/arm/vgic/vgic-kvm-device.c |  28 +++
 virt/kvm/arm/vgic/vgic-mmio-v3.c|  18 ++
 virt/kvm/arm/vgic/vgic-v3.c |   8 +
 virt/kvm/arm/vgic/vgic.h|   4 +
 11 files changed, 449 insertions(+), 3 deletions(-)

diff --git a/arch/arm/include/uapi/asm/kvm.h b/arch/arm/include/uapi/asm/kvm.h
index 0ae6035..98658d9d 100644
--- a/arch/arm/include/uapi/asm/kvm.h
+++ b/arch/arm/include/uapi/asm/kvm.h
@@ -186,9 +186,11 @@ struct kvm_arch_memory_slot {
(0xULL << KVM_DEV_ARM_VGIC_V3_MPIDR_SHIFT)
 #define   KVM_DEV_ARM_VGIC_OFFSET_SHIFT0
 #define   KVM_DEV_ARM_VGIC_OFFSET_MASK (0xULL << 
KVM_DEV_ARM_VGIC_OFFSET_SHIFT)
+#define   KVM_DEV_ARM_VGIC_SYSREG_INSTR_MASK (0x)
 #define KVM_DEV_ARM_VGIC_GRP_NR_IRQS   3
 #define KVM_DEV_ARM_VGIC_GRP_CTRL   4
 #define KVM_DEV_ARM_VGIC_GRP_REDIST_REGS 5
+#define KVM_DEV_ARM_VGIC_CPU_SYSREGS6
 #define   KVM_DEV_ARM_VGIC_CTRL_INIT0
 
 /* KVM_IRQ_LINE irq field index values */
diff --git a/arch/arm/kvm/Makefile b/arch/arm/kvm/Makefile
index d571243..68fb023 100644
--- a/arch/arm/kvm/Makefile
+++ b/arch/arm/kvm/Makefile
@@ -7,7 +7,7 @@ ifeq ($(plus_virt),+virt)
plus_virt_def := -DREQUIRES_VIRT=1
 endif
 
-ccflags-y += -Iarch/arm/kvm
+ccflags-y += -Iarch/arm/kvm -Ivirt/kvm/arm/vgic
 CFLAGS_arm.o := -I. $(plus_virt_def)
 CFLAGS_mmu.o := -I.
 
@@ -20,7 +20,7 @@ kvm-arm-y = $(KVM)/kvm_main.o $(KVM)/coalesced_mmio.o 
$(KVM)/eventfd.o $(KVM)/vf
 obj-$(CONFIG_KVM_ARM_HOST) += hyp/
 obj-y += kvm-arm.o init.o interrupts.o
 obj-y += arm.o handle_exit.o guest.o mmu.o emulate.o reset.o
-obj-y += coproc.o coproc_a15.o coproc_a7.o mmio.o psci.o perf.o
+obj-y += coproc.o coproc_a15.o coproc_a7.o mmio.o psci.o perf.o 
vgic-v3-coproc.o
 obj-y += $(KVM)/arm/aarch32.o
 
 obj-y += $(KVM)/arm/vgic/vgic.o
diff --git a/arch/arm/kvm/vgic-v3-coproc.c b/arch/arm/kvm/vgic-v3-coproc.c
new file mode 100644
index 000..f41abf7
--- /dev/null
+++ b/arch/arm/kvm/vgic-v3-coproc.c
@@ -0,0 +1,35 @@
+/*
+ * VGIC system registers handling functions for AArch32 mode
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include 
+#include 
+#include 
+#include "vgic.h"
+
+int vgic_v3_has_cpu_sysregs_attr(struct kvm_vcpu *vcpu, bool is_write, u64 id,
+u64 *reg)
+{
+   /*
+* TODO: Implement for AArch32
+*/
+   return -ENXIO;
+}
+
+int vgic_v3_cpu_sysregs_uaccess(struct kvm_vcpu *vcpu, bool is_write, u64 id,
+   u64 *reg)
+{
+   /*
+* TODO: Implement for AArch32
+*/
+   return -ENXIO;
+}
diff --git a/arch/arm64/include/uapi/asm/kvm.h 
b/arch/arm64/include/uapi/asm/kvm.h
index 56dc08d..91c7137 100644
--- a/arch/arm64/include/uapi/asm/kvm.h
+++ b/arch/arm64/include/uapi/asm/kvm.h
@@ -206,9 +206,12 @@ struct kvm_arch_memory_slot {
(0xULL << KVM_DEV_ARM_VGIC_V3_MPIDR_SHIFT)
 #define   KVM_DEV_ARM_VGIC_OFFSET_SHIFT0
 #define   KVM_DEV_ARM_VGIC_OFFSET_MASK (0xULL << 
KVM_DEV_ARM_VGIC_OFFSET_SHIFT)
+#define   KVM_DEV_ARM_VGIC_SYSREG_INSTR_MASK (0x)
 #define 

[PATCH v10 2/8] arm/arm64: vgic: Add distributor and redistributor access

2016-11-30 Thread vijay . kilari
From: Vijaya Kumar K 

VGICv3 Distributor and Redistributor registers are accessed using
KVM_DEV_ARM_VGIC_GRP_DIST_REGS and KVM_DEV_ARM_VGIC_GRP_REDIST_REGS
with KVM_SET_DEVICE_ATTR and KVM_GET_DEVICE_ATTR ioctls.
These registers are accessed as 32-bit and cpu mpidr
value passed along with register offset is used to identify the
cpu for redistributor registers access.

The version of VGIC v3 specification is define here
Documentation/virtual/kvm/devices/arm-vgic-v3.txt

Also update arch/arm/include/uapi/asm/kvm.h to compile for
AArch32 mode.

Signed-off-by: Vijaya Kumar K 
Reviewed-by: Christoffer Dall 
---
 arch/arm/include/uapi/asm/kvm.h |   4 +
 arch/arm64/include/uapi/asm/kvm.h   |   4 +
 virt/kvm/arm/vgic/vgic-kvm-device.c | 144 ++--
 virt/kvm/arm/vgic/vgic-mmio-v2.c|  16 +---
 virt/kvm/arm/vgic/vgic-mmio-v3.c|  72 ++
 virt/kvm/arm/vgic/vgic-mmio.c   |  22 ++
 virt/kvm/arm/vgic/vgic-mmio.h   |   4 +
 virt/kvm/arm/vgic/vgic.h|  49 +++-
 8 files changed, 292 insertions(+), 23 deletions(-)

diff --git a/arch/arm/include/uapi/asm/kvm.h b/arch/arm/include/uapi/asm/kvm.h
index af05f8e..0ae6035 100644
--- a/arch/arm/include/uapi/asm/kvm.h
+++ b/arch/arm/include/uapi/asm/kvm.h
@@ -181,10 +181,14 @@ struct kvm_arch_memory_slot {
 #define KVM_DEV_ARM_VGIC_GRP_CPU_REGS  2
 #define   KVM_DEV_ARM_VGIC_CPUID_SHIFT 32
 #define   KVM_DEV_ARM_VGIC_CPUID_MASK  (0xffULL << 
KVM_DEV_ARM_VGIC_CPUID_SHIFT)
+#define   KVM_DEV_ARM_VGIC_V3_MPIDR_SHIFT 32
+#define   KVM_DEV_ARM_VGIC_V3_MPIDR_MASK \
+   (0xULL << KVM_DEV_ARM_VGIC_V3_MPIDR_SHIFT)
 #define   KVM_DEV_ARM_VGIC_OFFSET_SHIFT0
 #define   KVM_DEV_ARM_VGIC_OFFSET_MASK (0xULL << 
KVM_DEV_ARM_VGIC_OFFSET_SHIFT)
 #define KVM_DEV_ARM_VGIC_GRP_NR_IRQS   3
 #define KVM_DEV_ARM_VGIC_GRP_CTRL   4
+#define KVM_DEV_ARM_VGIC_GRP_REDIST_REGS 5
 #define   KVM_DEV_ARM_VGIC_CTRL_INIT0
 
 /* KVM_IRQ_LINE irq field index values */
diff --git a/arch/arm64/include/uapi/asm/kvm.h 
b/arch/arm64/include/uapi/asm/kvm.h
index 3051f86..56dc08d 100644
--- a/arch/arm64/include/uapi/asm/kvm.h
+++ b/arch/arm64/include/uapi/asm/kvm.h
@@ -201,10 +201,14 @@ struct kvm_arch_memory_slot {
 #define KVM_DEV_ARM_VGIC_GRP_CPU_REGS  2
 #define   KVM_DEV_ARM_VGIC_CPUID_SHIFT 32
 #define   KVM_DEV_ARM_VGIC_CPUID_MASK  (0xffULL << 
KVM_DEV_ARM_VGIC_CPUID_SHIFT)
+#define   KVM_DEV_ARM_VGIC_V3_MPIDR_SHIFT 32
+#define   KVM_DEV_ARM_VGIC_V3_MPIDR_MASK \
+   (0xULL << KVM_DEV_ARM_VGIC_V3_MPIDR_SHIFT)
 #define   KVM_DEV_ARM_VGIC_OFFSET_SHIFT0
 #define   KVM_DEV_ARM_VGIC_OFFSET_MASK (0xULL << 
KVM_DEV_ARM_VGIC_OFFSET_SHIFT)
 #define KVM_DEV_ARM_VGIC_GRP_NR_IRQS   3
 #define KVM_DEV_ARM_VGIC_GRP_CTRL  4
+#define KVM_DEV_ARM_VGIC_GRP_REDIST_REGS 5
 #define   KVM_DEV_ARM_VGIC_CTRL_INIT   0
 
 /* Device Control API on vcpu fd */
diff --git a/virt/kvm/arm/vgic/vgic-kvm-device.c 
b/virt/kvm/arm/vgic/vgic-kvm-device.c
index fbe87a6..bc7de95 100644
--- a/virt/kvm/arm/vgic/vgic-kvm-device.c
+++ b/virt/kvm/arm/vgic/vgic-kvm-device.c
@@ -235,7 +235,7 @@ struct vgic_reg_attr {
gpa_t addr;
 };
 
-static int parse_vgic_v2_attr(struct kvm_device *dev,
+static int vgic_v2_parse_attr(struct kvm_device *dev,
  struct kvm_device_attr *attr,
  struct vgic_reg_attr *reg_attr)
 {
@@ -292,14 +292,14 @@ static bool lock_all_vcpus(struct kvm *kvm)
 }
 
 /**
- * vgic_attr_regs_access_v2 - allows user space to access VGIC v2 state
+ * vgic_v2_attr_regs_access - allows user space to access VGIC v2 state
  *
  * @dev:  kvm device handle
  * @attr: kvm device attribute
  * @reg:  address the value is read or written
  * @is_write: true if userspace is writing a register
  */
-static int vgic_attr_regs_access_v2(struct kvm_device *dev,
+static int vgic_v2_attr_regs_access(struct kvm_device *dev,
struct kvm_device_attr *attr,
u32 *reg, bool is_write)
 {
@@ -308,7 +308,7 @@ static int vgic_attr_regs_access_v2(struct kvm_device *dev,
struct kvm_vcpu *vcpu;
int ret;
 
-   ret = parse_vgic_v2_attr(dev, attr, _attr);
+   ret = vgic_v2_parse_attr(dev, attr, _attr);
if (ret)
return ret;
 
@@ -362,7 +362,7 @@ static int vgic_v2_set_attr(struct kvm_device *dev,
if (get_user(reg, uaddr))
return -EFAULT;
 
-   return vgic_attr_regs_access_v2(dev, attr, , true);
+   return vgic_v2_attr_regs_access(dev, attr, , true);
}
}
 
@@ -384,7 +384,7 @@ static int vgic_v2_get_attr(struct kvm_device *dev,
u32 __user *uaddr = (u32 __user *)(long)attr->addr;
u32 reg = 0;
 
-   ret = 

[PATCH v10 3/8] arm/arm64: vgic: Introduce find_reg_by_id()

2016-11-30 Thread vijay . kilari
From: Vijaya Kumar K 

In order to implement vGICv3 CPU interface access, we will need to perform
table lookup of system registers. We would need both index_to_params() and
find_reg() exported for that purpose, but instead we export a single
function which combines them both.

Signed-off-by: Pavel Fedin 
Signed-off-by: Vijaya Kumar K 
Reviewed-by: Andre Przywara 
Acked-by: Christoffer Dall 
---
 arch/arm64/kvm/sys_regs.c | 22 +++---
 arch/arm64/kvm/sys_regs.h |  4 
 2 files changed, 19 insertions(+), 7 deletions(-)

diff --git a/arch/arm64/kvm/sys_regs.c b/arch/arm64/kvm/sys_regs.c
index f302fdb..1330d4c 100644
--- a/arch/arm64/kvm/sys_regs.c
+++ b/arch/arm64/kvm/sys_regs.c
@@ -1789,6 +1789,17 @@ static bool index_to_params(u64 id, struct 
sys_reg_params *params)
}
 }
 
+const struct sys_reg_desc *find_reg_by_id(u64 id,
+ struct sys_reg_params *params,
+ const struct sys_reg_desc table[],
+ unsigned int num)
+{
+   if (!index_to_params(id, params))
+   return NULL;
+
+   return find_reg(params, table, num);
+}
+
 /* Decode an index value, and find the sys_reg_desc entry. */
 static const struct sys_reg_desc *index_to_sys_reg_desc(struct kvm_vcpu *vcpu,
u64 id)
@@ -1912,10 +1923,8 @@ static int get_invariant_sys_reg(u64 id, void __user 
*uaddr)
struct sys_reg_params params;
const struct sys_reg_desc *r;
 
-   if (!index_to_params(id, ))
-   return -ENOENT;
-
-   r = find_reg(, invariant_sys_regs, 
ARRAY_SIZE(invariant_sys_regs));
+   r = find_reg_by_id(id, , invariant_sys_regs,
+  ARRAY_SIZE(invariant_sys_regs));
if (!r)
return -ENOENT;
 
@@ -1929,9 +1938,8 @@ static int set_invariant_sys_reg(u64 id, void __user 
*uaddr)
int err;
u64 val = 0; /* Make sure high bits are 0 for 32-bit regs */
 
-   if (!index_to_params(id, ))
-   return -ENOENT;
-   r = find_reg(, invariant_sys_regs, 
ARRAY_SIZE(invariant_sys_regs));
+   r = find_reg_by_id(id, , invariant_sys_regs,
+  ARRAY_SIZE(invariant_sys_regs));
if (!r)
return -ENOENT;
 
diff --git a/arch/arm64/kvm/sys_regs.h b/arch/arm64/kvm/sys_regs.h
index dbbb01c..9c6ffd0 100644
--- a/arch/arm64/kvm/sys_regs.h
+++ b/arch/arm64/kvm/sys_regs.h
@@ -136,6 +136,10 @@ static inline int cmp_sys_reg(const struct sys_reg_desc 
*i1,
return i1->Op2 - i2->Op2;
 }
 
+const struct sys_reg_desc *find_reg_by_id(u64 id,
+ struct sys_reg_params *params,
+ const struct sys_reg_desc table[],
+ unsigned int num);
 
 #define Op0(_x).Op0 = _x
 #define Op1(_x).Op1 = _x
-- 
1.9.1

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


[PATCH v10 5/8] arm/arm64: vgic: Introduce VENG0 and VENG1 fields to vmcr struct

2016-11-30 Thread vijay . kilari
From: Vijaya Kumar K 

ICC_VMCR_EL2 supports virtual access to ICC_IGRPEN1_EL1.Enable
and ICC_IGRPEN0_EL1.Enable fields. Add grpen0 and grpen1 member
variables to struct vmcr to support read and write of these fields.

Also refactor vgic_set_vmcr and vgic_get_vmcr() code.
Drop ICH_VMCR_CTLR_SHIFT and ICH_VMCR_CTLR_MASK macros and instead
use ICH_VMCR_EOI* and ICH_VMCR_CBPR* macros.

Signed-off-by: Vijaya Kumar K 
Reviewed-by: Christoffer Dall 
---
 include/linux/irqchip/arm-gic-v3.h |  2 --
 virt/kvm/arm/vgic/vgic-mmio-v2.c   | 16 
 virt/kvm/arm/vgic/vgic-mmio.c  | 16 
 virt/kvm/arm/vgic/vgic-v3.c| 20 ++--
 virt/kvm/arm/vgic/vgic.h   |  5 +
 5 files changed, 39 insertions(+), 20 deletions(-)

diff --git a/include/linux/irqchip/arm-gic-v3.h 
b/include/linux/irqchip/arm-gic-v3.h
index b4f8287..406fc3e 100644
--- a/include/linux/irqchip/arm-gic-v3.h
+++ b/include/linux/irqchip/arm-gic-v3.h
@@ -404,8 +404,6 @@
 #define ICH_HCR_EN (1 << 0)
 #define ICH_HCR_UIE(1 << 1)
 
-#define ICH_VMCR_CTLR_SHIFT0
-#define ICH_VMCR_CTLR_MASK (0x21f << ICH_VMCR_CTLR_SHIFT)
 #define ICH_VMCR_CBPR_SHIFT4
 #define ICH_VMCR_CBPR_MASK (1 << ICH_VMCR_CBPR_SHIFT)
 #define ICH_VMCR_EOIM_SHIFT9
diff --git a/virt/kvm/arm/vgic/vgic-mmio-v2.c b/virt/kvm/arm/vgic/vgic-mmio-v2.c
index 2cb04b7..ad353b5 100644
--- a/virt/kvm/arm/vgic/vgic-mmio-v2.c
+++ b/virt/kvm/arm/vgic/vgic-mmio-v2.c
@@ -212,22 +212,6 @@ static void vgic_mmio_write_sgipends(struct kvm_vcpu *vcpu,
}
 }
 
-static void vgic_set_vmcr(struct kvm_vcpu *vcpu, struct vgic_vmcr *vmcr)
-{
-   if (kvm_vgic_global_state.type == VGIC_V2)
-   vgic_v2_set_vmcr(vcpu, vmcr);
-   else
-   vgic_v3_set_vmcr(vcpu, vmcr);
-}
-
-static void vgic_get_vmcr(struct kvm_vcpu *vcpu, struct vgic_vmcr *vmcr)
-{
-   if (kvm_vgic_global_state.type == VGIC_V2)
-   vgic_v2_get_vmcr(vcpu, vmcr);
-   else
-   vgic_v3_get_vmcr(vcpu, vmcr);
-}
-
 #define GICC_ARCH_VERSION_V2   0x2
 
 /* These are for userland accesses only, there is no guest-facing emulation. */
diff --git a/virt/kvm/arm/vgic/vgic-mmio.c b/virt/kvm/arm/vgic/vgic-mmio.c
index 0d1bc98..f81e0e5 100644
--- a/virt/kvm/arm/vgic/vgic-mmio.c
+++ b/virt/kvm/arm/vgic/vgic-mmio.c
@@ -416,6 +416,22 @@ int vgic_validate_mmio_region_addr(struct kvm_device *dev,
return -ENXIO;
 }
 
+void vgic_set_vmcr(struct kvm_vcpu *vcpu, struct vgic_vmcr *vmcr)
+{
+   if (kvm_vgic_global_state.type == VGIC_V2)
+   vgic_v2_set_vmcr(vcpu, vmcr);
+   else
+   vgic_v3_set_vmcr(vcpu, vmcr);
+}
+
+void vgic_get_vmcr(struct kvm_vcpu *vcpu, struct vgic_vmcr *vmcr)
+{
+   if (kvm_vgic_global_state.type == VGIC_V2)
+   vgic_v2_get_vmcr(vcpu, vmcr);
+   else
+   vgic_v3_get_vmcr(vcpu, vmcr);
+}
+
 /*
  * kvm_mmio_read_buf() returns a value in a format where it can be converted
  * to a byte array and be directly observed as the guest wanted it to appear
diff --git a/virt/kvm/arm/vgic/vgic-v3.c b/virt/kvm/arm/vgic/vgic-v3.c
index 9f0dae3..c21968b 100644
--- a/virt/kvm/arm/vgic/vgic-v3.c
+++ b/virt/kvm/arm/vgic/vgic-v3.c
@@ -175,10 +175,18 @@ void vgic_v3_set_vmcr(struct kvm_vcpu *vcpu, struct 
vgic_vmcr *vmcrp)
 {
u32 vmcr;
 
-   vmcr  = (vmcrp->ctlr << ICH_VMCR_CTLR_SHIFT) & ICH_VMCR_CTLR_MASK;
+   /*
+* Ignore the FIQen bit, because GIC emulation always implies
+* SRE=1 which means the vFIQEn bit is also RES1.
+*/
+   vmcr = ((vmcrp->ctlr >> ICC_CTLR_EL1_EOImode_SHIFT) <<
+ICH_VMCR_EOIM_SHIFT) & ICH_VMCR_EOIM_MASK;
+   vmcr |= (vmcrp->ctlr << ICH_VMCR_CBPR_SHIFT) & ICH_VMCR_CBPR_MASK;
vmcr |= (vmcrp->abpr << ICH_VMCR_BPR1_SHIFT) & ICH_VMCR_BPR1_MASK;
vmcr |= (vmcrp->bpr << ICH_VMCR_BPR0_SHIFT) & ICH_VMCR_BPR0_MASK;
vmcr |= (vmcrp->pmr << ICH_VMCR_PMR_SHIFT) & ICH_VMCR_PMR_MASK;
+   vmcr |= (vmcrp->grpen0 << ICH_VMCR_ENG0_SHIFT) & ICH_VMCR_ENG0_MASK;
+   vmcr |= (vmcrp->grpen1 << ICH_VMCR_ENG1_SHIFT) & ICH_VMCR_ENG1_MASK;
 
vcpu->arch.vgic_cpu.vgic_v3.vgic_vmcr = vmcr;
 }
@@ -187,10 +195,18 @@ void vgic_v3_get_vmcr(struct kvm_vcpu *vcpu, struct 
vgic_vmcr *vmcrp)
 {
u32 vmcr = vcpu->arch.vgic_cpu.vgic_v3.vgic_vmcr;
 
-   vmcrp->ctlr = (vmcr & ICH_VMCR_CTLR_MASK) >> ICH_VMCR_CTLR_SHIFT;
+   /*
+* Ignore the FIQen bit, because GIC emulation always implies
+* SRE=1 which means the vFIQEn bit is also RES1.
+*/
+   vmcrp->ctlr = ((vmcr >> ICH_VMCR_EOIM_SHIFT) <<
+   ICC_CTLR_EL1_EOImode_SHIFT) & ICC_CTLR_EL1_EOImode_MASK;
+   vmcrp->ctlr |= (vmcr & ICH_VMCR_CBPR_MASK) >> ICH_VMCR_CBPR_SHIFT;
vmcrp->abpr = (vmcr & 

[PATCH v10 7/8] arm/arm64: vgic: Implement KVM_DEV_ARM_VGIC_GRP_LEVEL_INFO ioctl

2016-11-30 Thread vijay . kilari
From: Vijaya Kumar K 

Userspace requires to store and restore of line_level for
level triggered interrupts using ioctl KVM_DEV_ARM_VGIC_GRP_LEVEL_INFO.

Signed-off-by: Vijaya Kumar K 
---
 arch/arm/include/uapi/asm/kvm.h |  7 ++
 arch/arm64/include/uapi/asm/kvm.h   |  6 +
 virt/kvm/arm/vgic/vgic-kvm-device.c | 45 +++-
 virt/kvm/arm/vgic/vgic-mmio-v3.c| 11 +
 virt/kvm/arm/vgic/vgic-mmio.c   | 46 +
 virt/kvm/arm/vgic/vgic-mmio.h   |  5 
 virt/kvm/arm/vgic/vgic.h|  2 ++
 7 files changed, 121 insertions(+), 1 deletion(-)

diff --git a/arch/arm/include/uapi/asm/kvm.h b/arch/arm/include/uapi/asm/kvm.h
index 98658d9d..f347779 100644
--- a/arch/arm/include/uapi/asm/kvm.h
+++ b/arch/arm/include/uapi/asm/kvm.h
@@ -191,6 +191,13 @@ struct kvm_arch_memory_slot {
 #define KVM_DEV_ARM_VGIC_GRP_CTRL   4
 #define KVM_DEV_ARM_VGIC_GRP_REDIST_REGS 5
 #define KVM_DEV_ARM_VGIC_CPU_SYSREGS6
+#define KVM_DEV_ARM_VGIC_GRP_LEVEL_INFO 7
+#define KVM_DEV_ARM_VGIC_LINE_LEVEL_INFO_SHIFT 10
+#define KVM_DEV_ARM_VGIC_LINE_LEVEL_INFO_MASK \
+   (0x3fULL << KVM_DEV_ARM_VGIC_LINE_LEVEL_INFO_SHIFT)
+#define KVM_DEV_ARM_VGIC_LINE_LEVEL_INTID_MASK 0x3ff
+#define VGIC_LEVEL_INFO_LINE_LEVEL 0
+
 #define   KVM_DEV_ARM_VGIC_CTRL_INIT0
 
 /* KVM_IRQ_LINE irq field index values */
diff --git a/arch/arm64/include/uapi/asm/kvm.h 
b/arch/arm64/include/uapi/asm/kvm.h
index 91c7137..4100f8c 100644
--- a/arch/arm64/include/uapi/asm/kvm.h
+++ b/arch/arm64/include/uapi/asm/kvm.h
@@ -211,6 +211,12 @@ struct kvm_arch_memory_slot {
 #define KVM_DEV_ARM_VGIC_GRP_CTRL  4
 #define KVM_DEV_ARM_VGIC_GRP_REDIST_REGS 5
 #define KVM_DEV_ARM_VGIC_CPU_SYSREGS6
+#define KVM_DEV_ARM_VGIC_GRP_LEVEL_INFO 7
+#define KVM_DEV_ARM_VGIC_LINE_LEVEL_INFO_SHIFT 10
+#define KVM_DEV_ARM_VGIC_LINE_LEVEL_INFO_MASK \
+   (0x3fULL << KVM_DEV_ARM_VGIC_LINE_LEVEL_INFO_SHIFT)
+#define KVM_DEV_ARM_VGIC_LINE_LEVEL_INTID_MASK 0x3ff
+#define VGIC_LEVEL_INFO_LINE_LEVEL 0
 
 #define   KVM_DEV_ARM_VGIC_CTRL_INIT   0
 
diff --git a/virt/kvm/arm/vgic/vgic-kvm-device.c 
b/virt/kvm/arm/vgic/vgic-kvm-device.c
index b6266fe..d5f7197 100644
--- a/virt/kvm/arm/vgic/vgic-kvm-device.c
+++ b/virt/kvm/arm/vgic/vgic-kvm-device.c
@@ -510,6 +510,21 @@ static int vgic_v3_attr_regs_access(struct kvm_device *dev,
  regid, reg);
break;
}
+   case KVM_DEV_ARM_VGIC_GRP_LEVEL_INFO: {
+   unsigned int info, intid;
+
+   info = (attr->attr & KVM_DEV_ARM_VGIC_LINE_LEVEL_INFO_MASK) >>
+   KVM_DEV_ARM_VGIC_LINE_LEVEL_INFO_SHIFT;
+   if (info == VGIC_LEVEL_INFO_LINE_LEVEL) {
+   intid = attr->attr &
+   KVM_DEV_ARM_VGIC_LINE_LEVEL_INTID_MASK;
+   ret = vgic_v3_line_level_info_uaccess(vcpu, is_write,
+ intid, reg);
+   } else {
+   ret = -EINVAL;
+   }
+   break;
+   }
default:
ret = -EINVAL;
break;
@@ -552,6 +567,17 @@ static int vgic_v3_set_attr(struct kvm_device *dev,
 
return vgic_v3_attr_regs_access(dev, attr, , true);
}
+   case KVM_DEV_ARM_VGIC_GRP_LEVEL_INFO: {
+   u32 __user *uaddr = (u32 __user *)(long)attr->addr;
+   u64 reg;
+   u32 tmp32;
+
+   if (get_user(tmp32, uaddr))
+   return -EFAULT;
+
+   reg = tmp32;
+   return vgic_v3_attr_regs_access(dev, attr, , true);
+   }
}
return -ENXIO;
 }
@@ -587,8 +613,18 @@ static int vgic_v3_get_attr(struct kvm_device *dev,
return ret;
return put_user(reg, uaddr);
}
-   }
+   case KVM_DEV_ARM_VGIC_GRP_LEVEL_INFO: {
+   u32 __user *uaddr = (u32 __user *)(long)attr->addr;
+   u64 reg;
+   u32 tmp32;
 
+   ret = vgic_v3_attr_regs_access(dev, attr, , false);
+   if (ret)
+   return ret;
+   tmp32 = reg;
+   return put_user(tmp32, uaddr);
+   }
+   }
return -ENXIO;
 }
 
@@ -609,6 +645,13 @@ static int vgic_v3_has_attr(struct kvm_device *dev,
return vgic_v3_has_attr_regs(dev, attr);
case KVM_DEV_ARM_VGIC_GRP_NR_IRQS:
return 0;
+   case KVM_DEV_ARM_VGIC_GRP_LEVEL_INFO: {
+   if (((attr->attr & KVM_DEV_ARM_VGIC_LINE_LEVEL_INFO_MASK) >>
+ KVM_DEV_ARM_VGIC_LINE_LEVEL_INFO_SHIFT) ==
+ VGIC_LEVEL_INFO_LINE_LEVEL)
+   return 0;
+   break;
+   }

[PATCH v10 0/8] arm/arm64: vgic: Implement API for vGICv3 live migration

2016-11-30 Thread vijay . kilari
From: Vijaya Kumar K 

This patchset adds API for saving and restoring
of VGICv3 registers to support live migration with new vgic feature.
This API definition is as per version of VGICv3 specification
Documentation/virtual/kvm/devices/arm-vgic-v3.txt

The patch 3 & 4 are picked from the Pavel's previous implementation.
http://www.spinics.net/lists/kvm/msg122040.html

NOTE: Only compilation tested for AArch32. No hardware to test.

v9 => v10:
 - Dropped support for AArch32 mode.
 - Fixed line level update
 - Updated documentation
 - Moved vgic-sys-reg-v3.c to arch/arm64/kvm/ and
   added vgic-v3-coproc.c to arch/arm/kvm for AArch32
 - Fixed nits

v8 => v9:
 - Rebased to kvmarm/next branch
 - Introduce support for save and restore of CPU interface
   registers for AArch32 mode (9,10 and 11 patches).
   Only compilation tested.
 - Fixed vmcr.ctlr format
 - Updated error code for invalid CPU REG value in Documentation
 - Updated commit messages and added comments required
 - Queued IRQ when irq_line is set.
 - Compatibility check on ICC_CTLR_EL1.SEIS and A3V

v7 => v8:
 - Rebased to 4.9-rc3
 - Fixed wrong parameter to VGIC_TO_MPIDR
v6 => v7:
 - Rename all patches heading from vgic-new to vgic
 - Moved caching of priority and ID bits from vgic global struct
   to vgic_cpu struct.

v5 => v6:
 - Collated all register definitions to single patch (4)
 - Introduce macro to convert userspace MPIDR format to MPIDR reg format
 - Check on ICC_CTLR_EL1.CBPR value is made while accessing ICC_BPR1_EL1
 - Cached ich_vtr_el2 and guests priority and ID bits
 - Check on number of priority and ID bits when ICC_CTRL_EL1 write is made
 - Check is made on SRE bit for ICC_SRE_EL1 write

v4 => v5:
 - ICC_CTLR_EL1 access is updated to reflect HW values
 - Updated ICC reg access mask and shift macros
 - Introduced patch 4 for VMCR changes
 - Other minor fixes.
v3 => v4:
 - Rebased to latest code base
 - Moved vgic_uaccess() from vgic-mmio-v2.c to vgic-mmio.c
 - Dropped macro REGISTER_DESC_WITH_BITS_PER_IRQ_SHARED_UACCESS
 - Dropped LE conversion for userspace access
 - Introduced vgic_uaccess_write_pending() for ISPENDR write
 - Change macro KVM_DEV_ARM_VGIC_V3_CPUID_MASK to KVM_DEV_ARM_VGIC_V3_MIDR_MASK
 - Refactored some code as common code.
 - Changed handing of ICC_* registers
 - Allowed ICC_SRE_EL1 read by userspace
 - Fixed KVM_DEV_ARM_VGIC_LINE_LEVEL_INFO_* macros

v2 => v3:
 - Implemented separate API for ISPENDR and ICPENDR to
   read soft_pending instead of pending for level triggerred interrupts
 - Implemented ioctl KVM_DEV_ARM_VGIC_GRP_LEVEL_INFO to access line level
 - Rebased on top of Christoffer's patch set
   http://www.spinics.net/lists/kvm/msg136840.html

 NOTE: GICD_STATUSR and GICR_STATUSR are implemented as RAZ/WI.

v1 => v2:
 - The init sequence change patch is no more required.
   Fixed in patch 2 by using static vgic_io_dev regions structure instead
   of using dynamic allocation pointer.
 - Updated commit message of patch 4.
 - Dropped usage of union to manage 32-bit and 64-bit access in patch 1.
   Used local variable for 32-bit access.
 - Updated macro __ARM64_SYS_REG and ARM64_SYS_REG in
   arch/arm64/include/uapi/asm/kvm.h as per qemu requirements.

Vijaya Kumar K (8):
  arm/arm64: vgic: Implement support for userspace access
  arm/arm64: vgic: Add distributor and redistributor access
  arm/arm64: vgic: Introduce find_reg_by_id()
  irqchip/gic-v3: Add missing system register definitions
  arm/arm64: vgic: Introduce VENG0 and VENG1 fields to vmcr struct
  arm/arm64: vgic: Implement VGICv3 CPU interface access
  arm/arm64: vgic: Implement KVM_DEV_ARM_VGIC_GRP_LEVEL_INFO ioctl
  arm/arm64: Documentation: Update arm-vgic-v3.txt

 Documentation/virtual/kvm/devices/arm-vgic-v3.txt |   9 +-
 arch/arm/include/uapi/asm/kvm.h   |  13 +
 arch/arm/kvm/Makefile |   4 +-
 arch/arm/kvm/vgic-v3-coproc.c |  35 +++
 arch/arm64/include/uapi/asm/kvm.h |  13 +
 arch/arm64/kvm/Makefile   |   3 +-
 arch/arm64/kvm/sys_regs.c |  22 +-
 arch/arm64/kvm/sys_regs.h |   4 +
 arch/arm64/kvm/vgic-sys-reg-v3.c  | 338 ++
 include/kvm/arm_vgic.h|   9 +
 include/linux/irqchip/arm-gic-v3.h|  45 ++-
 virt/kvm/arm/vgic/vgic-kvm-device.c   | 215 +-
 virt/kvm/arm/vgic/vgic-mmio-v2.c  |  57 +---
 virt/kvm/arm/vgic/vgic-mmio-v3.c  | 204 +++--
 virt/kvm/arm/vgic/vgic-mmio.c | 162 ++-
 virt/kvm/arm/vgic/vgic-mmio.h |  28 ++
 virt/kvm/arm/vgic/vgic-v3.c   |  28 +-
 virt/kvm/arm/vgic/vgic.h  |  60 +++-
 18 files changed, 1144 insertions(+), 105 deletions(-)
 create mode 100644 arch/arm/kvm/vgic-v3-coproc.c
 create mode 100644 

[PATCH v10 1/8] arm/arm64: vgic: Implement support for userspace access

2016-11-30 Thread vijay . kilari
From: Vijaya Kumar K 

Read and write of some registers like ISPENDR and ICPENDR
from userspace requires special handling when compared to
guest access for these registers.

Refer to Documentation/virtual/kvm/devices/arm-vgic-v3.txt
for handling of ISPENDR, ICPENDR registers handling.

Add infrastructure to support guest and userspace read
and write for the required registers
Also moved vgic_uaccess from vgic-mmio-v2.c to vgic-mmio.c

Signed-off-by: Vijaya Kumar K 
Reviewed-by: Christoffer Dall 
---
 virt/kvm/arm/vgic/vgic-mmio-v2.c |  25 --
 virt/kvm/arm/vgic/vgic-mmio-v3.c | 103 ---
 virt/kvm/arm/vgic/vgic-mmio.c|  78 ++---
 virt/kvm/arm/vgic/vgic-mmio.h|  19 
 4 files changed, 176 insertions(+), 49 deletions(-)

diff --git a/virt/kvm/arm/vgic/vgic-mmio-v2.c b/virt/kvm/arm/vgic/vgic-mmio-v2.c
index b44b359..0b32f40 100644
--- a/virt/kvm/arm/vgic/vgic-mmio-v2.c
+++ b/virt/kvm/arm/vgic/vgic-mmio-v2.c
@@ -406,31 +406,6 @@ int vgic_v2_has_attr_regs(struct kvm_device *dev, struct 
kvm_device_attr *attr)
return -ENXIO;
 }
 
-/*
- * When userland tries to access the VGIC register handlers, we need to
- * create a usable struct vgic_io_device to be passed to the handlers and we
- * have to set up a buffer similar to what would have happened if a guest MMIO
- * access occurred, including doing endian conversions on BE systems.
- */
-static int vgic_uaccess(struct kvm_vcpu *vcpu, struct vgic_io_device *dev,
-   bool is_write, int offset, u32 *val)
-{
-   unsigned int len = 4;
-   u8 buf[4];
-   int ret;
-
-   if (is_write) {
-   vgic_data_host_to_mmio_bus(buf, len, *val);
-   ret = kvm_io_gic_ops.write(vcpu, >dev, offset, len, buf);
-   } else {
-   ret = kvm_io_gic_ops.read(vcpu, >dev, offset, len, buf);
-   if (!ret)
-   *val = vgic_data_mmio_bus_to_host(buf, len);
-   }
-
-   return ret;
-}
-
 int vgic_v2_cpuif_uaccess(struct kvm_vcpu *vcpu, bool is_write,
  int offset, u32 *val)
 {
diff --git a/virt/kvm/arm/vgic/vgic-mmio-v3.c b/virt/kvm/arm/vgic/vgic-mmio-v3.c
index 50f42f0..960e2c6 100644
--- a/virt/kvm/arm/vgic/vgic-mmio-v3.c
+++ b/virt/kvm/arm/vgic/vgic-mmio-v3.c
@@ -207,6 +207,67 @@ static unsigned long vgic_mmio_read_v3_idregs(struct 
kvm_vcpu *vcpu,
return 0;
 }
 
+static unsigned long vgic_v3_uaccess_read_pending(struct kvm_vcpu *vcpu,
+ gpa_t addr, unsigned int len)
+{
+   u32 intid = VGIC_ADDR_TO_INTID(addr, 1);
+   u32 value = 0;
+   int i;
+
+   /*
+* A level triggerred interrupt pending state is latched in both
+* "soft_pending" and "line_level" variables. Userspace will save
+* and restore soft_pending and line_level separately.
+* Refer to Documentation/virtual/kvm/devices/arm-vgic-v3.txt
+* handling of ISPENDR and ICPENDR.
+*/
+   for (i = 0; i < len * 8; i++) {
+   struct vgic_irq *irq = vgic_get_irq(vcpu->kvm, vcpu, intid + i);
+
+   if (irq->config == VGIC_CONFIG_LEVEL && irq->soft_pending)
+   value |= (1U << i);
+   if (irq->config == VGIC_CONFIG_EDGE && irq->pending)
+   value |= (1U << i);
+
+   vgic_put_irq(vcpu->kvm, irq);
+   }
+
+   return value;
+}
+
+static void vgic_v3_uaccess_write_pending(struct kvm_vcpu *vcpu,
+ gpa_t addr, unsigned int len,
+ unsigned long val)
+{
+   u32 intid = VGIC_ADDR_TO_INTID(addr, 1);
+   int i;
+
+   for (i = 0; i < len * 8; i++) {
+   struct vgic_irq *irq = vgic_get_irq(vcpu->kvm, vcpu, intid + i);
+
+   spin_lock(>irq_lock);
+   if (test_bit(i, )) {
+   /*
+* soft_pending is set irrespective of irq type
+* (level or edge) to avoid dependency that VM should
+* restore irq config before pending info.
+*/
+   irq->pending = true;
+   irq->soft_pending = true;
+   vgic_queue_irq_unlock(vcpu->kvm, irq);
+   } else {
+   irq->soft_pending = false;
+   if (irq->config == VGIC_CONFIG_EDGE ||
+   (irq->config == VGIC_CONFIG_LEVEL &&
+   !irq->line_level))
+   irq->pending = false;
+   spin_unlock(>irq_lock);
+   }
+
+   vgic_put_irq(vcpu->kvm, irq);
+   }
+}
+
 /* We want to avoid outer shareable. */
 u64 vgic_sanitise_shareability(u64 field)
 {
@@ -356,7 +417,7 @@ 

[PATCH v10 4/8] irqchip/gic-v3: Add missing system register definitions

2016-11-30 Thread vijay . kilari
From: Vijaya Kumar K 

Define register definitions for ICH_VMCR_EL2, ICC_CTLR_EL1 and
ICH_VTR_EL2, ICC_BPR0_EL1, ICC_BPR1_EL1 registers.

Signed-off-by: Vijaya Kumar K 
---
 include/linux/irqchip/arm-gic-v3.h | 43 --
 1 file changed, 41 insertions(+), 2 deletions(-)

diff --git a/include/linux/irqchip/arm-gic-v3.h 
b/include/linux/irqchip/arm-gic-v3.h
index 0deea34..b4f8287 100644
--- a/include/linux/irqchip/arm-gic-v3.h
+++ b/include/linux/irqchip/arm-gic-v3.h
@@ -352,8 +352,30 @@
 /*
  * CPU interface registers
  */
-#define ICC_CTLR_EL1_EOImode_drop_dir  (0U << 1)
-#define ICC_CTLR_EL1_EOImode_drop  (1U << 1)
+#define ICC_CTLR_EL1_EOImode_SHIFT (1)
+#define ICC_CTLR_EL1_EOImode_drop_dir  (0U << ICC_CTLR_EL1_EOImode_SHIFT)
+#define ICC_CTLR_EL1_EOImode_drop  (1U << ICC_CTLR_EL1_EOImode_SHIFT)
+#define ICC_CTLR_EL1_EOImode_MASK  (1 << ICC_CTLR_EL1_EOImode_SHIFT)
+#define ICC_CTLR_EL1_CBPR_SHIFT0
+#define ICC_CTLR_EL1_CBPR_MASK (1 << ICC_CTLR_EL1_CBPR_SHIFT)
+#define ICC_CTLR_EL1_PRI_BITS_SHIFT8
+#define ICC_CTLR_EL1_PRI_BITS_MASK (0x7 << ICC_CTLR_EL1_PRI_BITS_SHIFT)
+#define ICC_CTLR_EL1_ID_BITS_SHIFT 11
+#define ICC_CTLR_EL1_ID_BITS_MASK  (0x7 << ICC_CTLR_EL1_ID_BITS_SHIFT)
+#define ICC_CTLR_EL1_SEIS_SHIFT14
+#define ICC_CTLR_EL1_SEIS_MASK (0x1 << ICC_CTLR_EL1_SEIS_SHIFT)
+#define ICC_CTLR_EL1_A3V_SHIFT 15
+#define ICC_CTLR_EL1_A3V_MASK  (0x1 << ICC_CTLR_EL1_A3V_SHIFT)
+#define ICC_PMR_EL1_SHIFT  0
+#define ICC_PMR_EL1_MASK   (0xff << ICC_PMR_EL1_SHIFT)
+#define ICC_BPR0_EL1_SHIFT 0
+#define ICC_BPR0_EL1_MASK  (0x7 << ICC_BPR0_EL1_SHIFT)
+#define ICC_BPR1_EL1_SHIFT 0
+#define ICC_BPR1_EL1_MASK  (0x7 << ICC_BPR1_EL1_SHIFT)
+#define ICC_IGRPEN0_EL1_SHIFT  0
+#define ICC_IGRPEN0_EL1_MASK   (1 << ICC_IGRPEN0_EL1_SHIFT)
+#define ICC_IGRPEN1_EL1_SHIFT  0
+#define ICC_IGRPEN1_EL1_MASK   (1 << ICC_IGRPEN1_EL1_SHIFT)
 #define ICC_SRE_EL1_SRE(1U << 0)
 
 /*
@@ -384,12 +406,29 @@
 
 #define ICH_VMCR_CTLR_SHIFT0
 #define ICH_VMCR_CTLR_MASK (0x21f << ICH_VMCR_CTLR_SHIFT)
+#define ICH_VMCR_CBPR_SHIFT4
+#define ICH_VMCR_CBPR_MASK (1 << ICH_VMCR_CBPR_SHIFT)
+#define ICH_VMCR_EOIM_SHIFT9
+#define ICH_VMCR_EOIM_MASK (1 << ICH_VMCR_EOIM_SHIFT)
 #define ICH_VMCR_BPR1_SHIFT18
 #define ICH_VMCR_BPR1_MASK (7 << ICH_VMCR_BPR1_SHIFT)
 #define ICH_VMCR_BPR0_SHIFT21
 #define ICH_VMCR_BPR0_MASK (7 << ICH_VMCR_BPR0_SHIFT)
 #define ICH_VMCR_PMR_SHIFT 24
 #define ICH_VMCR_PMR_MASK  (0xffUL << ICH_VMCR_PMR_SHIFT)
+#define ICH_VMCR_ENG0_SHIFT0
+#define ICH_VMCR_ENG0_MASK (1 << ICH_VMCR_ENG0_SHIFT)
+#define ICH_VMCR_ENG1_SHIFT1
+#define ICH_VMCR_ENG1_MASK (1 << ICH_VMCR_ENG1_SHIFT)
+
+#define ICH_VTR_PRI_BITS_SHIFT 29
+#define ICH_VTR_PRI_BITS_MASK  (7 << ICH_VTR_PRI_BITS_SHIFT)
+#define ICH_VTR_ID_BITS_SHIFT  23
+#define ICH_VTR_ID_BITS_MASK   (7 << ICH_VTR_ID_BITS_SHIFT)
+#define ICH_VTR_SEIS_SHIFT 22
+#define ICH_VTR_SEIS_MASK  (1 << ICH_VTR_SEIS_SHIFT)
+#define ICH_VTR_A3V_SHIFT  21
+#define ICH_VTR_A3V_MASK   (1 << ICH_VTR_A3V_SHIFT)
 
 #define ICC_IAR1_EL1_SPURIOUS  0x3ff
 
-- 
1.9.1

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


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

2016-11-30 Thread Wei Huang


On 11/25/2016 08:26 AM, Andrew Jones wrote:
> On Fri, Nov 25, 2016 at 12:32:24PM +, Andre Przywara wrote:
>> Hi Drew,
>>
>> 
>>
>> On 23/11/16 17:15, Andrew Jones wrote:
> +
> +#if defined(__arm__)

 I guess you should use the arch specific header files we have in place
 for that (lib/arm{.64}/asm/processor.h). Also there are sysreg read
 wrappers (at least for arm64) in there already, can't we base this
 function on them: DEFINE_GET_SYSREG32(pmcr, el0)?
 (Requires a small change to get rid of the forced "_el1" suffix)

 We should wait for the GIC series to be merged, as this contains some
 changes in this area.
>>>
>>> As this unit test is the only consumer of PMC registers so far, then
>>> I'd prefer the defines and accessors stay here for now. Once we see
>>> a use in other unit tests then we can move some of it out.
>>
>> Well, I was more thinking of something like below.
>> I am fine with keeping the PMU sysregs private to pmu.c, but we can still
>> use the sysreg wrappers, can't we?
>> This is on top of Wei's series, so doesn't have your SYSREG32/64
>> unification, but I leave this as an exercise to the reader.
>> There is some churn in pmu.c below due to the change of _write to
>> set_, but the rest looks like simplification to me.
>>
>> Does that make sense?
> 
> Ah, now I see what you mean, and I think I like that. The question is
> whether or not I like my SYSREG macros :-) I see value in having the
> asm's easy to read (open-coded), as well as value in making sure we
> only have to review sysreg functions once. Let's ask for Wei's and
> Cov's votes. If they like the SYSREG direction, then they can vote
> with another version of this series :-)

Let us use SYSREG macros then, because it makes coding easier. V13 has
been sent. I think this PMU patcheset is a bit bloated now. So hopefully
this is the last version. After it is accepted, we can always come back
to re-factor SYSREG r/w further (if need).

Thanks,
-Wei

> 
> Thanks,
> drew
> 
>>
>> Cheers,
>> Andre.
>>
>> ---
>>  arm/pmu.c | 159 
>> +-
>>  lib/arm/asm/processor.h   |  34 --
>>  lib/arm64/asm/processor.h |  23 ++-
>>  3 files changed, 92 insertions(+), 124 deletions(-)
>>
>> diff --git a/arm/pmu.c b/arm/pmu.c
>> index f667676..f0ad02a 100644
>> --- a/arm/pmu.c
>> +++ b/arm/pmu.c
>> @@ -14,6 +14,7 @@
>>   */
>>  #include "libcflat.h"
>>  #include "asm/barrier.h"
>> +#include "asm/processor.h"
>>  
>>  #define PMU_PMCR_E (1 << 0)
>>  #define PMU_PMCR_C (1 << 2)
>> @@ -33,78 +34,42 @@
>>  #define NR_SAMPLES 10
>>  
>>  static unsigned int pmu_version;
>> -#if defined(__arm__)
>> -static inline uint32_t pmcr_read(void)
>> -{
>> -uint32_t ret;
>> -
>> -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));
>> -isb();
>> -}
>>  
>> -static inline void pmselr_write(uint32_t value)
>> -{
>> -asm volatile("mcr p15, 0, %0, c9, c12, 5" : : "r" (value));
>> -isb();
>> -}
>> -
>> -static inline void pmxevtyper_write(uint32_t value)
>> -{
>> -asm volatile("mcr p15, 0, %0, c9, c13, 1" : : "r" (value));
>> -}
>> -
>> -static inline uint64_t pmccntr_read(void)
>> +#if defined(__arm__)
>> +DEFINE_GET_SYSREG32(pmcr, 0, c9, c12, 0)
>> +DEFINE_SET_SYSREG32(pmcr, 0, c9, c12, 0)
>> +DEFINE_GET_SYSREG32(id_dfr0, 0, c0, c1, 2)
>> +DEFINE_SET_SYSREG32(pmselr, 0, c9, c12, 5)
>> +DEFINE_SET_SYSREG32(pmxevtyper, 0, c9, c13, 1)
>> +DEFINE_GET_SYSREG32(pmccntr32, 0, c9, c13, 0)
>> +DEFINE_SET_SYSREG32(pmccntr32, 0, c9, c13, 0)
>> +DEFINE_GET_SYSREG64(pmccntr64, 0, c9)
>> +DEFINE_SET_SYSREG64(pmccntr64, 0, c9)
>> +DEFINE_SET_SYSREG32(pmcntenset, 0, c9, c12, 1)
>> +
>> +static inline uint64_t get_pmccntr(void)
>>  {
>> -uint32_t lo, hi = 0;
>> -
>>  if (pmu_version == 0x3)
>> -asm volatile("mrrc p15, 0, %0, %1, c9" : "=r" (lo), "=r" (hi));
>> +return get_pmccntr32();
>>  else
>> -asm volatile("mrc p15, 0, %0, c9, c13, 0" : "=r" (lo));
>> -
>> -return ((uint64_t)hi << 32) | lo;
>> +return get_pmccntr64();
>>  }
>>  
>> -static inline void pmccntr_write(uint64_t value)
>> +static inline void set_pmccntr(uint64_t value)
>>  {
>> -uint32_t lo, hi;
>> -
>> -lo = value & 0x;
>> -hi = (value >> 32) & 0x;
>> -
>>  if (pmu_version == 0x3)
>> -asm volatile("mcrr p15, 0, %0, %1, c9" : : "r" (lo), "r" (hi));
>> +set_pmccntr64(value);
>>  else
>> -asm volatile("mcr p15, 0, %0, c9, c13, 0" : : "r" (lo));
>> +set_pmccntr64(value & 0x);
>>  }
>> -
>> -static inline void pmcntenset_write(uint32_t value)
>> -{
>> -asm volatile("mcr p15, 0, %0, c9, c12, 1" : : "r" (value));
>> -}
>> -
>>  /* PMCCFILTR is an 

[kvm-unit-tests PATCH v13 3/4] arm: pmu: Check cycle count increases

2016-11-30 Thread Wei Huang
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 
Reviewed-by: Andrew Jones 
---
 arm/pmu.c | 94 +++
 1 file changed, 94 insertions(+)

diff --git a/arm/pmu.c b/arm/pmu.c
index 1fe2b1a..3566a27 100644
--- a/arm/pmu.c
+++ b/arm/pmu.c
@@ -16,6 +16,9 @@
 #include "asm/barrier.h"
 #include "asm/processor.h"
 
+#define PMU_PMCR_E (1 << 0)
+#define PMU_PMCR_C (1 << 2)
+#define PMU_PMCR_LC(1 << 6)
 #define PMU_PMCR_N_SHIFT   11
 #define PMU_PMCR_N_MASK0x1f
 #define PMU_PMCR_ID_SHIFT  16
@@ -23,10 +26,57 @@
 #define PMU_PMCR_IMP_SHIFT 24
 #define PMU_PMCR_IMP_MASK  0xff
 
+#define ID_DFR0_PERFMON_SHIFT 24
+#define ID_DFR0_PERFMON_MASK  0xf
+
+#define PMU_CYCLE_IDX 31
+
+#define NR_SAMPLES 10
+
+static unsigned int pmu_version;
 #if defined(__arm__)
 DEFINE_GET_SYSREG32(pmcr, 0, c9, c12, 0)
+DEFINE_SET_SYSREG32(pmcr, 0, c9, c12, 0)
+DEFINE_GET_SYSREG32(id_dfr0, 0, c0, c1, 2)
+DEFINE_SET_SYSREG32(pmselr, 0, c9, c12, 5)
+DEFINE_SET_SYSREG32(pmxevtyper, 0, c9, c13, 1)
+DEFINE_GET_SYSREG32(pmccntr32, 0, c9, c13, 0)
+DEFINE_SET_SYSREG32(pmccntr32, 0, c9, c13, 0)
+DEFINE_GET_SYSREG64(pmccntr64, 0, c9)
+DEFINE_SET_SYSREG64(pmccntr64, 0, c9)
+DEFINE_SET_SYSREG32(pmcntenset, 0, c9, c12, 1)
+
+static inline uint64_t get_pmccntr(void)
+{
+   if (pmu_version == 0x3)
+   return get_pmccntr64();
+   else
+   return get_pmccntr32();
+}
+
+static inline void set_pmccntr(uint64_t value)
+{
+   if (pmu_version == 0x3)
+   set_pmccntr64(value);
+   else
+   set_pmccntr32(value & 0x);
+}
+
+/* PMCCFILTR is an obsolete name for PMXEVTYPER31 in ARMv7 */
+static inline void set_pmccfiltr(uint32_t value)
+{
+   set_pmselr(PMU_CYCLE_IDX);
+   set_pmxevtyper(value);
+   isb();
+}
 #elif defined(__aarch64__)
 DEFINE_GET_SYSREG32(pmcr, el0)
+DEFINE_SET_SYSREG32(pmcr, el0)
+DEFINE_GET_SYSREG32(id_dfr0, el1)
+DEFINE_GET_SYSREG64(pmccntr, el0);
+DEFINE_SET_SYSREG64(pmccntr, el0);
+DEFINE_SET_SYSREG32(pmcntenset, el0);
+DEFINE_SET_SYSREG32(pmccfiltr, el0);
 #endif
 
 /*
@@ -52,11 +102,55 @@ 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)
+{
+   bool success = true;
+
+   /* init before event access, this test only cares about cycle count */
+   set_pmcntenset(1 << PMU_CYCLE_IDX);
+   set_pmccfiltr(0); /* count cycles in EL0, EL1, but not EL2 */
+   set_pmccntr(0);
+
+   set_pmcr(get_pmcr() | PMU_PMCR_LC | PMU_PMCR_C | PMU_PMCR_E);
+
+   for (int i = 0; i < NR_SAMPLES; i++) {
+   uint64_t a, b;
+
+   a = get_pmccntr();
+   b = get_pmccntr();
+
+   if (a >= b) {
+   printf("Read %"PRId64" then %"PRId64".\n", a, b);
+   success = false;
+   break;
+   }
+   }
+
+   set_pmcr(get_pmcr() & ~PMU_PMCR_E);
+
+   return success;
+}
+
+void pmu_init(void)
+{
+   uint32_t dfr0;
+
+   /* probe pmu version */
+   dfr0 = get_id_dfr0();
+   pmu_version = (dfr0 >> ID_DFR0_PERFMON_SHIFT) & ID_DFR0_PERFMON_MASK;
+   report_info("PMU version: %d", pmu_version);
+}
+
 int main(void)
 {
report_prefix_push("pmu");
 
+   pmu_init();
report("Control register", check_pmcr());
+   report("Monotonically increasing cycle count", check_cycles_increase());
 
return report_summary();
 }
-- 
1.8.3.1

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


[kvm-unit-tests PATCH v13 4/4] arm: pmu: Add CPI checking

2016-11-30 Thread Wei Huang
From: Christopher Covington 

Calculate the numbers of cycles per instruction (CPI) implied by ARM
PMU cycle counter values. The code includes a strict checking facility
intended for the -icount option in TCG mode in the configuration file.

Signed-off-by: Christopher Covington 
Signed-off-by: Wei Huang 
Reviewed-by: Andrew Jones 
---
 arm/pmu.c | 123 +-
 arm/unittests.cfg |  14 +++
 2 files changed, 136 insertions(+), 1 deletion(-)

diff --git a/arm/pmu.c b/arm/pmu.c
index 3566a27..29d7c2c 100644
--- a/arm/pmu.c
+++ b/arm/pmu.c
@@ -69,6 +69,27 @@ static inline void set_pmccfiltr(uint32_t value)
set_pmxevtyper(value);
isb();
 }
+
+/*
+ * Extra instructions inserted by the compiler would be difficult to compensate
+ * for, so hand assemble everything between, and including, the PMCR accesses
+ * to start and stop counting. isb instructions were inserted to make sure
+ * pmccntr read after this function returns the exact instructions executed in
+ * the controlled block. Total instrs = isb + mcr + 2*loop = 2 + 2*loop.
+ */
+static inline void precise_instrs_loop(int loop, uint32_t pmcr)
+{
+   asm volatile(
+   "   mcr p15, 0, %[pmcr], c9, c12, 0\n"
+   "   isb\n"
+   "1: subs%[loop], %[loop], #1\n"
+   "   bgt 1b\n"
+   "   mcr p15, 0, %[z], c9, c12, 0\n"
+   "   isb\n"
+   : [loop] "+r" (loop)
+   : [pmcr] "r" (pmcr), [z] "r" (0)
+   : "cc");
+}
 #elif defined(__aarch64__)
 DEFINE_GET_SYSREG32(pmcr, el0)
 DEFINE_SET_SYSREG32(pmcr, el0)
@@ -77,6 +98,27 @@ DEFINE_GET_SYSREG64(pmccntr, el0);
 DEFINE_SET_SYSREG64(pmccntr, el0);
 DEFINE_SET_SYSREG32(pmcntenset, el0);
 DEFINE_SET_SYSREG32(pmccfiltr, el0);
+
+/*
+ * Extra instructions inserted by the compiler would be difficult to compensate
+ * for, so hand assemble everything between, and including, the PMCR accesses
+ * to start and stop counting. isb instructions are inserted to make sure
+ * pmccntr read after this function returns the exact instructions executed
+ * in the controlled block. Total instrs = isb + msr + 2*loop = 2 + 2*loop.
+ */
+static inline void precise_instrs_loop(int loop, uint32_t pmcr)
+{
+   asm volatile(
+   "   msr pmcr_el0, %[pmcr]\n"
+   "   isb\n"
+   "1: subs%[loop], %[loop], #1\n"
+   "   b.gt1b\n"
+   "   msr pmcr_el0, xzr\n"
+   "   isb\n"
+   : [loop] "+r" (loop)
+   : [pmcr] "r" (pmcr)
+   : "cc");
+}
 #endif
 
 /*
@@ -134,6 +176,79 @@ static bool check_cycles_increase(void)
return success;
 }
 
+/*
+ * Execute a known number of guest instructions. Only even instruction counts
+ * greater than or equal to 4 are supported by the in-line assembly code. The
+ * control register (PMCR_EL0) is initialized with the provided value (allowing
+ * for example for the cycle counter or event counters to be reset). At the end
+ * of the exact instruction loop, zero is written to PMCR_EL0 to disable
+ * counting, allowing the cycle counter or event counters to be read at the
+ * leisure of the calling code.
+ */
+static void measure_instrs(int num, uint32_t pmcr)
+{
+   int loop = (num - 2) / 2;
+
+   assert(num >= 4 && ((num - 2) % 2 == 0));
+   precise_instrs_loop(loop, pmcr);
+}
+
+/*
+ * Measure cycle counts for various known instruction counts. Ensure that the
+ * cycle counter progresses (similar to check_cycles_increase() but with more
+ * instructions and using reset and stop controls). If supplied a positive,
+ * nonzero CPI parameter, also strictly check that every measurement matches
+ * it. Strict CPI checking is used to test -icount mode.
+ */
+static bool check_cpi(int cpi)
+{
+   uint32_t pmcr = get_pmcr() | PMU_PMCR_LC | PMU_PMCR_C | PMU_PMCR_E;
+
+   /* init before event access, this test only cares about cycle count */
+   set_pmcntenset(1 << PMU_CYCLE_IDX);
+   set_pmccfiltr(0); /* count cycles in EL0, EL1, but not EL2 */
+
+   if (cpi > 0)
+   printf("Checking for CPI=%d.\n", cpi);
+   printf("instrs : cycles0 cycles1 ...\n");
+
+   for (unsigned int i = 4; i < 300; i += 32) {
+   uint64_t avg, sum = 0;
+
+   printf("%d :", i);
+   for (int j = 0; j < NR_SAMPLES; j++) {
+   uint64_t cycles;
+
+   set_pmccntr(0);
+   measure_instrs(i, pmcr);
+   cycles = get_pmccntr();
+   printf(" %"PRId64"", cycles);
+
+   if (!cycles) {
+   printf("\ncycles not incrementing!\n");
+   return false;
+   } else if (cpi > 0 && cycles != i * cpi) {
+   printf("\nunexpected cycle count received!\n");
+   

[kvm-unit-tests PATCH v13 0/4] ARM PMU tests

2016-11-30 Thread Wei Huang
Changes from v12:
* Define macros for system register accessors
* Re-write PMU code using the newly-defined macros
* Code tested under both AArch32 and AArch64 modes

Note:
1) Current KVM code has bugs in handling PMCCFILTR write. A fix (see
below) is required for this unit testing code to work correctly under
KVM mode.
https://lists.cs.columbia.edu/pipermail/kvmarm/2016-November/022134.html.

Thanks,
-Wei

Christopher Covington (3):
  arm: Add PMU test
  arm: pmu: Check cycle count increases
  arm: pmu: Add CPI checking

Wei Huang (1):
  arm: Define macros for accessing system registers

 arm/Makefile.common   |   3 +-
 arm/pmu.c | 277 ++
 arm/unittests.cfg |  19 
 lib/arm/asm/processor.h   |  37 ++-
 lib/arm64/asm/processor.h |  35 --
 5 files changed, 358 insertions(+), 13 deletions(-)
 create mode 100644 arm/pmu.c

-- 
1.8.3.1

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


[kvm-unit-tests PATCH v13 2/4] arm: Add PMU test

2016-11-30 Thread Wei Huang
From: Christopher Covington 

Beginning with a simple sanity check of the control register, add
a unit test for the ARM Performance Monitors Unit (PMU). PMU register
was read using the newly defined macros.

Signed-off-by: Christopher Covington 
Signed-off-by: Wei Huang 
Reviewed-by: Andrew Jones 
---
 arm/Makefile.common |  3 ++-
 arm/pmu.c   | 62 +
 arm/unittests.cfg   |  5 +
 3 files changed, 69 insertions(+), 1 deletion(-)
 create mode 100644 arm/pmu.c

diff --git a/arm/Makefile.common b/arm/Makefile.common
index f37b5c2..5da2fdd 100644
--- a/arm/Makefile.common
+++ b/arm/Makefile.common
@@ -12,7 +12,8 @@ endif
 tests-common = \
$(TEST_DIR)/selftest.flat \
$(TEST_DIR)/spinlock-test.flat \
-   $(TEST_DIR)/pci-test.flat
+   $(TEST_DIR)/pci-test.flat \
+   $(TEST_DIR)/pmu.flat
 
 all: test_cases
 
diff --git a/arm/pmu.c b/arm/pmu.c
new file mode 100644
index 000..1fe2b1a
--- /dev/null
+++ b/arm/pmu.c
@@ -0,0 +1,62 @@
+/*
+ * Test the ARM Performance Monitors Unit (PMU).
+ *
+ * Copyright (c) 2015-2016, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License version 2.1 and
+ * only version 2.1 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
+ * for more details.
+ */
+#include "libcflat.h"
+#include "asm/barrier.h"
+#include "asm/processor.h"
+
+#define PMU_PMCR_N_SHIFT   11
+#define PMU_PMCR_N_MASK0x1f
+#define PMU_PMCR_ID_SHIFT  16
+#define PMU_PMCR_ID_MASK   0xff
+#define PMU_PMCR_IMP_SHIFT 24
+#define PMU_PMCR_IMP_MASK  0xff
+
+#if defined(__arm__)
+DEFINE_GET_SYSREG32(pmcr, 0, c9, c12, 0)
+#elif defined(__aarch64__)
+DEFINE_GET_SYSREG32(pmcr, el0)
+#endif
+
+/*
+ * As a simple sanity check on the PMCR_EL0, ensure the implementer field isn't
+ * null. Also print out a couple other interesting fields for diagnostic
+ * purposes. For example, as of fall 2016, QEMU TCG mode doesn't implement
+ * event counters and therefore reports zero event counters, but hopefully
+ * support for at least the instructions event will be added in the future and
+ * the reported number of event counters will become nonzero.
+ */
+static bool check_pmcr(void)
+{
+   uint32_t pmcr;
+
+   pmcr = get_pmcr();
+
+   report_info("PMU implementer/ID code/counters: 0x%x(\"%c\")/0x%x/%d",
+   (pmcr >> PMU_PMCR_IMP_SHIFT) & PMU_PMCR_IMP_MASK,
+   ((pmcr >> PMU_PMCR_IMP_SHIFT) & PMU_PMCR_IMP_MASK) ? : ' ',
+   (pmcr >> PMU_PMCR_ID_SHIFT) & PMU_PMCR_ID_MASK,
+   (pmcr >> PMU_PMCR_N_SHIFT) & PMU_PMCR_N_MASK);
+
+   return ((pmcr >> PMU_PMCR_IMP_SHIFT) & PMU_PMCR_IMP_MASK) != 0;
+}
+
+int main(void)
+{
+   report_prefix_push("pmu");
+
+   report("Control register", check_pmcr());
+
+   return report_summary();
+}
diff --git a/arm/unittests.cfg b/arm/unittests.cfg
index ae32a42..816f494 100644
--- a/arm/unittests.cfg
+++ b/arm/unittests.cfg
@@ -58,3 +58,8 @@ groups = selftest
 [pci-test]
 file = pci-test.flat
 groups = pci
+
+# Test PMU support
+[pmu]
+file = pmu.flat
+groups = pmu
-- 
1.8.3.1

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


[kvm-unit-tests PATCH v13 1/4] arm: Define macros for accessing system registers

2016-11-30 Thread Wei Huang
This patch defines four macros to assist creating system register
accessors under both ARMv7 and AArch64:
   * DEFINE_GET_SYSREG32(name, ...)
   * DEFINE_SET_SYSREG32(name, ...)
   * DEFINE_GET_SYSREG64(name, ...)
   * DEFINE_SET_SYSREG64(name, ...)
These macros are translated to inline functions with consistent naming,
get_##name() and set_##name(), which can be used by C code directly.

Signed-off-by: Andre Przywara 
Signed-off-by: Wei Huang 
---
 lib/arm/asm/processor.h   | 37 -
 lib/arm64/asm/processor.h | 35 ---
 2 files changed, 60 insertions(+), 12 deletions(-)

diff --git a/lib/arm/asm/processor.h b/lib/arm/asm/processor.h
index f25e7ee..3ca6b42 100644
--- a/lib/arm/asm/processor.h
+++ b/lib/arm/asm/processor.h
@@ -33,13 +33,40 @@ static inline unsigned long current_cpsr(void)
 
 #define current_mode() (current_cpsr() & MODE_MASK)
 
-static inline unsigned int get_mpidr(void)
-{
-   unsigned int mpidr;
-   asm volatile("mrc p15, 0, %0, c0, c0, 5" : "=r" (mpidr));
-   return mpidr;
+#define DEFINE_GET_SYSREG32(name, opc1, crn, crm, opc2)
\
+static inline uint32_t get_##name(void)
\
+{  \
+   uint32_t reg;   \
+   asm volatile("mrc p15, " #opc1 ", %0, " #crn ", " #crm ", " \
+#opc2 : "=r" (reg));   \
+   return reg; \
+}
+
+#define DEFINE_SET_SYSREG32(name, opc1, crn, crm, opc2)
\
+static inline void set_##name(uint32_t value)  \
+{  \
+   asm volatile("mcr p15, " #opc1 ", %0, " #crn ", " #crm ", " \
+#opc2 :: "r" (value)); \
+}
+
+#define DEFINE_GET_SYSREG64(name, opc, crm)\
+static inline uint64_t get_##name(void)
\
+{  \
+   uint32_t lo, hi;\
+   asm volatile("mrrc p15, " #opc ", %0, %1, " #crm\
+: "=r" (lo), "=r" (hi));   \
+   return (uint64_t)hi << 32 | lo; \
+}
+
+#define DEFINE_SET_SYSREG64(name, opc, crm)\
+static inline void set_##name(uint64_t value)  \
+{  \
+   asm volatile("mcrr p15, " #opc ", %0, %1, " #crm\
+:: "r" (value & 0x), "r" (value >> 32));   \
 }
 
+DEFINE_GET_SYSREG32(mpidr, 0, c0, c0, 5)
+
 /* Only support Aff0 for now, up to 4 cpus */
 #define mpidr_to_cpu(mpidr) ((int)((mpidr) & 0xff))
 
diff --git a/lib/arm64/asm/processor.h b/lib/arm64/asm/processor.h
index 84d5c7c..dfa75eb 100644
--- a/lib/arm64/asm/processor.h
+++ b/lib/arm64/asm/processor.h
@@ -66,14 +66,35 @@ static inline unsigned long current_level(void)
return el & 0xc;
 }
 
-#define DEFINE_GET_SYSREG32(reg)   \
-static inline unsigned int get_##reg(void) \
-{  \
-   unsigned int reg;   \
-   asm volatile("mrs %0, " #reg "_el1" : "=r" (reg));  \
-   return reg; \
+#define DEFINE_GET_SYSREG32(reg, el)   \
+static inline uint32_t get_##reg(void) \
+{  \
+   uint32_t reg;   \
+   asm volatile("mrs %0, " #reg "_" #el : "=r" (reg)); \
+   return reg; \
 }
-DEFINE_GET_SYSREG32(mpidr)
+
+#define DEFINE_SET_SYSREG32(reg, el)   \
+static inline void set_##reg(uint32_t value)   \
+{  \
+   asm volatile("msr " #reg "_" #el ", %0" :: "r" (value));\
+}
+
+#define DEFINE_GET_SYSREG64(reg, el)   \
+static inline uint64_t get_##reg(void) \
+{  \
+   uint64_t reg;   \
+   asm volatile("mrs %0, " #reg "_" #el : "=r" (reg)); \
+   return reg; \
+}
+
+#define 

Re: Unable to use perf in VM

2016-11-30 Thread Wei Huang


On 11/30/2016 07:37 AM, Marc Zyngier wrote:
> On 30/11/16 11:48, Marc Zyngier wrote:
>> + Shannon
>>
>> On 29/11/16 22:04, Itaru Kitayama wrote:
>>> Hi,
>>>
>>> In a VM (virsh controlled, KVM acceleration enabled) on a recent
>>> kvmarm kernel host, I find I am unable to use perf to obtain
>>> performance statistics for a complex task like kernel build.
>>> (I've verified this is seen with a Fedora 25 VM and host combination
>>> as well)
>>> APM folks CC'ed think this might be caused by a bug in the core PMU 
>>> framework code, thus I'd like to have experts opinion on this issue.
>>>
>>> [root@localhost linux]# perf stat -B make
>>>CHK include/config/kernel.release
>>> [  119.617684] git[1144]: undefined instruction: pc=fc000808ff30
>>> [  119.623040] Code: 51000442 92401042 d51b9ca2 d5033fdf (d53b9d40)
>>> [  119.627607] Internal error: undefined instruction: 0 [#1] SMP
>>
>> [...]
>>
>> In a VM running mainline hosted on an AMD Seattle box:
>>
>>  Performance counter stats for 'make':
>>
>> 1526089.499304  task-clock:u (msec)   #0.932 CPUs utilized   
>>
>>  0  context-switches:u#0.000 K/sec   
>>
>>  0  cpu-migrations:u  #0.000 K/sec   
>>
>>   29527793  page-faults:u #0.019 M/sec   
>>
>>  2913174122673  cycles:u  #1.909 GHz 
>>
>>  2365040892322  instructions:u#0.81  insn per cycle  
>>
>>  branches:u   
>>
>>32049215378  branch-misses:u   #0.00% of all branches 
>>
>>
>> 1637.531444837 seconds time elapsed
>>
>> Running the same host kernel on a Mustang system, the guest explodes
>> in the way you reported. The failing instruction always seems to be
>> an access to pmxevcntr_el0 (I've seen both reads and writes).
>>
>> Funnily enough, it dies if you try any HW event other than cycles
>> ("perf stat -e cycles ls" works, and "perf stat -e instructions ls"
>> explodes). Which would tend to indicate that we're screwing up
>> the counter selection, but I have no proof of that (specially that
>> the Seattle guest is working just as expected).
> 
> It turns out that we *don't* inject an undef. It seems to be generated
> locally at EL1.
> 
> Still digging.

Just FYI: I saw it on Mustang before. My initial thought was HW related,
but without proof. I am interested to see your findings...

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


Re: [PATCH] KVM: arm/arm64: Access CNTHCTL_EL2 bit fields correctly

2016-11-30 Thread Jintack Lim
On Wed, Nov 30, 2016 at 8:31 AM, Marc Zyngier  wrote:
> On 29/11/16 21:05, Jintack Lim wrote:
>> On Tue, Nov 29, 2016 at 11:53 AM, Suzuki K Poulose
>>  wrote:
>>> On 29/11/16 09:36, Marc Zyngier wrote:

 On 29/11/16 03:28, Jintack Lim wrote:
>
> On Mon, Nov 28, 2016 at 1:39 PM, Marc Zyngier 
> wrote:
>>
>> On 28/11/16 17:43, Marc Zyngier wrote:
>
> This looks much cleaner than my patch.
> While we are at it, is it worth to consider that we just need to set
> those bits once for VHE case, not for every world switch as an
> optimization?


 Ah! That's a much better idea indeed! And we could stop messing with
 cntvoff_el2 as well, as it doesn't need to be restored to zero on exit.
 Could you try and respin something along those lines?

>>>
>>> fyi, we have a static_key based cpus_have_const_cap() for Constant cap
>>> checking (like this case) available in linux-next. May be you could make use
>>> of that instead of alternatives.
>>
>> Thanks Suzuki. This looks very useful.
>>
>> Marc, can I write a patch based on linux-next? The commit which has
>> cpus_have_const_cap() is not in master and next branch in kvm/arm
>> repo.
>
> You can. It is just that I won't be able to apply it immediately (I'll
> wait for -rc1 to be out, and send it as a fix).

Ok. Thanks!. I'll send out v2.

>
> 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: Unable to use perf in VM

2016-11-30 Thread Marc Zyngier
On 30/11/16 11:48, Marc Zyngier wrote:
> + Shannon
> 
> On 29/11/16 22:04, Itaru Kitayama wrote:
>> Hi,
>>
>> In a VM (virsh controlled, KVM acceleration enabled) on a recent
>> kvmarm kernel host, I find I am unable to use perf to obtain
>> performance statistics for a complex task like kernel build.
>> (I've verified this is seen with a Fedora 25 VM and host combination
>> as well)
>> APM folks CC'ed think this might be caused by a bug in the core PMU 
>> framework code, thus I'd like to have experts opinion on this issue.
>>
>> [root@localhost linux]# perf stat -B make
>>CHK include/config/kernel.release
>> [  119.617684] git[1144]: undefined instruction: pc=fc000808ff30
>> [  119.623040] Code: 51000442 92401042 d51b9ca2 d5033fdf (d53b9d40)
>> [  119.627607] Internal error: undefined instruction: 0 [#1] SMP
> 
> [...]
> 
> In a VM running mainline hosted on an AMD Seattle box:
> 
>  Performance counter stats for 'make':
> 
> 1526089.499304  task-clock:u (msec)   #0.932 CPUs utilized
>   
>  0  context-switches:u#0.000 K/sec
>   
>  0  cpu-migrations:u  #0.000 K/sec
>   
>   29527793  page-faults:u #0.019 M/sec
>   
>  2913174122673  cycles:u  #1.909 GHz  
>   
>  2365040892322  instructions:u#0.81  insn per cycle   
>   
>  branches:u
>   
>32049215378  branch-misses:u   #0.00% of all branches  
>   
> 
> 1637.531444837 seconds time elapsed
> 
> Running the same host kernel on a Mustang system, the guest explodes
> in the way you reported. The failing instruction always seems to be
> an access to pmxevcntr_el0 (I've seen both reads and writes).
> 
> Funnily enough, it dies if you try any HW event other than cycles
> ("perf stat -e cycles ls" works, and "perf stat -e instructions ls"
> explodes). Which would tend to indicate that we're screwing up
> the counter selection, but I have no proof of that (specially that
> the Seattle guest is working just as expected).

It turns out that we *don't* inject an undef. It seems to be generated
locally at EL1.

Still digging.

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] KVM: arm/arm64: Access CNTHCTL_EL2 bit fields correctly

2016-11-30 Thread Marc Zyngier
On 29/11/16 21:05, Jintack Lim wrote:
> On Tue, Nov 29, 2016 at 11:53 AM, Suzuki K Poulose
>  wrote:
>> On 29/11/16 09:36, Marc Zyngier wrote:
>>>
>>> On 29/11/16 03:28, Jintack Lim wrote:

 On Mon, Nov 28, 2016 at 1:39 PM, Marc Zyngier 
 wrote:
>
> On 28/11/16 17:43, Marc Zyngier wrote:

 This looks much cleaner than my patch.
 While we are at it, is it worth to consider that we just need to set
 those bits once for VHE case, not for every world switch as an
 optimization?
>>>
>>>
>>> Ah! That's a much better idea indeed! And we could stop messing with
>>> cntvoff_el2 as well, as it doesn't need to be restored to zero on exit.
>>> Could you try and respin something along those lines?
>>>
>>
>> fyi, we have a static_key based cpus_have_const_cap() for Constant cap
>> checking (like this case) available in linux-next. May be you could make use
>> of that instead of alternatives.
> 
> Thanks Suzuki. This looks very useful.
> 
> Marc, can I write a patch based on linux-next? The commit which has
> cpus_have_const_cap() is not in master and next branch in kvm/arm
> repo.

You can. It is just that I won't be able to apply it immediately (I'll
wait for -rc1 to be out, and send it as a fix).

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: Unable to use perf in VM

2016-11-30 Thread Marc Zyngier
+ Shannon

On 29/11/16 22:04, Itaru Kitayama wrote:
> Hi,
> 
> In a VM (virsh controlled, KVM acceleration enabled) on a recent
> kvmarm kernel host, I find I am unable to use perf to obtain
> performance statistics for a complex task like kernel build.
> (I've verified this is seen with a Fedora 25 VM and host combination
> as well)
> APM folks CC'ed think this might be caused by a bug in the core PMU 
> framework code, thus I'd like to have experts opinion on this issue.
> 
> [root@localhost linux]# perf stat -B make
>CHK include/config/kernel.release
> [  119.617684] git[1144]: undefined instruction: pc=fc000808ff30
> [  119.623040] Code: 51000442 92401042 d51b9ca2 d5033fdf (d53b9d40)
> [  119.627607] Internal error: undefined instruction: 0 [#1] SMP

[...]

In a VM running mainline hosted on an AMD Seattle box:

 Performance counter stats for 'make':

1526089.499304  task-clock:u (msec)   #0.932 CPUs utilized  

 0  context-switches:u#0.000 K/sec  

 0  cpu-migrations:u  #0.000 K/sec  

  29527793  page-faults:u #0.019 M/sec  

 2913174122673  cycles:u  #1.909 GHz

 2365040892322  instructions:u#0.81  insn per cycle 

 branches:u  

   32049215378  branch-misses:u   #0.00% of all branches


1637.531444837 seconds time elapsed

Running the same host kernel on a Mustang system, the guest explodes
in the way you reported. The failing instruction always seems to be
an access to pmxevcntr_el0 (I've seen both reads and writes).

Funnily enough, it dies if you try any HW event other than cycles
("perf stat -e cycles ls" works, and "perf stat -e instructions ls"
explodes). Which would tend to indicate that we're screwing up
the counter selection, but I have no proof of that (specially that
the Seattle guest is working just as expected).

Shannon, any idea?

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 v9 07/11] arm/arm64: vgic: Implement KVM_DEV_ARM_VGIC_GRP_LEVEL_INFO ioctl

2016-11-30 Thread Peter Maydell
On 30 November 2016 at 08:24, Christoffer Dall
 wrote:
> (Peter, I thought you once argued that it was important for user space
> to be able to save/restore the state without any ordering requirements,
> but I may have misunderstood.  It is still the option to add something
> like the above to the docs but also do our best to allow any ordering of
> level/config, but it becomes slightly more invasive.)

Hmm; perhaps I should think about this a bit more.

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


Re: [PATCH v9 07/11] arm/arm64: vgic: Implement KVM_DEV_ARM_VGIC_GRP_LEVEL_INFO ioctl

2016-11-30 Thread Christoffer Dall
On Wed, Nov 30, 2016 at 07:10:51AM +, Peter Maydell wrote:
> On 29 November 2016 at 21:09, Christoffer Dall
>  wrote:
> > Actually, I'm not sure what the semantics of the line level ioctl should
> > be for edge-triggered interrupts?  My inclination is that it shouldn't
> > have any effect at this point, but that would mean that at this point we
> > should only set the pending variable and try to queue the interrupt if
> > the config is level.  But that also means that when we set the config
> > later, we need to try to queue the interrupt, which we don't do
> > currently, because we rely on the guest not fiddling with the config of
> > an enabled interrupt.
> >
> > Could it be considered an error if user space tries to set the level for
> > an edge-triggered interrupt and therefore something we can just ignore
> > and assume that the corresponing interrupt will be configured as a
> > level-triggered one later?
> 
> Userspace will always read the line-level values out and write
> them back for migration, and I'd rather not make it have to
> do cross-checks against whether the interrupt is edge or level
> triggered to see whether it should write the level values into
> the kernel. Telling the kernel the level for an edge-triggered
> interrupt should be a no-op because it doesn't have any effect
> on pending status.
> 
> > In any case we probably need to clarify the ABI in terms of this
> > particular KVM_DEV_AR_VGIC_GRP_LEVEL_INFO group and how it relates to
> > the config of edge vs. level of interrupts and ordering on restore...
> 
> IIRC the QEMU code restores the config first. (There's a similar
> ordering thing for GICv2 where we have to restore GICD_ICFGRn before
> GICD_ISPENDRn.)
> 

So it sounds to me that we should add a note in the Documentation like
this:

diff --git a/Documentation/virtual/kvm/devices/arm-vgic-v3.txt 
b/Documentation/virtual/kvm/devices/arm-vgic-v3.txt
index 9348b3c..7bac20a 100644
--- a/Documentation/virtual/kvm/devices/arm-vgic-v3.txt
+++ b/Documentation/virtual/kvm/devices/arm-vgic-v3.txt
@@ -193,6 +193,11 @@ Groups:
 
Bit[n] indicates the status for interrupt vINTID + n.
 
+   Getting or setting the level info for an edge-triggered interrupt is
+   not guaranteed to work.  To restore the complete state of the VGIC, the
+   configuration (edge/level) of interrupts must be restored before
+   restoring the level.
+
 SGIs and any interrupt with a higher ID than the number of interrupts
 supported, will be RAZ/WI.  LPIs are always edge-triggered and are
 therefore not supported by this interface.

Vijay, this means that the first block in your if-statement should only
set pending and queue the interrupt if the interrupt is a level
triggered one.

(Peter, I thought you once argued that it was important for user space
to be able to save/restore the state without any ordering requirements,
but I may have misunderstood.  It is still the option to add something
like the above to the docs but also do our best to allow any ordering of
level/config, but it becomes slightly more invasive.)

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