summaryrefslogtreecommitdiffstats
path: root/virt
diff options
context:
space:
mode:
authorVijaya Kumar K <Vijaya.Kumar@cavium.com>2017-01-26 09:20:51 -0500
committerMarc Zyngier <marc.zyngier@arm.com>2017-01-30 08:47:25 -0500
commitd017d7b0bd7ab32644d35666a6c4412daa0b0a1d (patch)
tree2e21087dde0969512442e0b70aa2ec318bef5aa2 /virt
parent5fb247d79c04240dce86c842976cde1edde7f7ed (diff)
KVM: arm/arm64: vgic: Implement VGICv3 CPU interface access
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. It 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 defined here Documentation/virtual/kvm/devices/arm-vgic-v3.txt Acked-by: Christoffer Dall <christoffer.dall@linaro.org> Reviewed-by: Eric Auger <eric.auger@redhat.com> Signed-off-by: Pavel Fedin <p.fedin@samsung.com> Signed-off-by: Vijaya Kumar K <Vijaya.Kumar@cavium.com> Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
Diffstat (limited to 'virt')
-rw-r--r--virt/kvm/arm/vgic/vgic-kvm-device.c27
-rw-r--r--virt/kvm/arm/vgic/vgic-mmio-v3.c6
-rw-r--r--virt/kvm/arm/vgic/vgic-v3.c8
-rw-r--r--virt/kvm/arm/vgic/vgic.h25
4 files changed, 66 insertions, 0 deletions
diff --git a/virt/kvm/arm/vgic/vgic-kvm-device.c b/virt/kvm/arm/vgic/vgic-kvm-device.c
index 227337fd5156..b30372b59dc2 100644
--- a/virt/kvm/arm/vgic/vgic-kvm-device.c
+++ b/virt/kvm/arm/vgic/vgic-kvm-device.c
@@ -504,6 +504,14 @@ static int vgic_v3_attr_regs_access(struct kvm_device *dev,
504 if (!is_write) 504 if (!is_write)
505 *reg = tmp32; 505 *reg = tmp32;
506 break; 506 break;
507 case KVM_DEV_ARM_VGIC_GRP_CPU_SYSREGS: {
508 u64 regid;
509
510 regid = (attr->attr & KVM_DEV_ARM_VGIC_SYSREG_INSTR_MASK);
511 ret = vgic_v3_cpu_sysregs_uaccess(vcpu, is_write,
512 regid, reg);
513 break;
514 }
507 default: 515 default:
508 ret = -EINVAL; 516 ret = -EINVAL;
509 break; 517 break;
@@ -537,6 +545,15 @@ static int vgic_v3_set_attr(struct kvm_device *dev,
537 reg = tmp32; 545 reg = tmp32;
538 return vgic_v3_attr_regs_access(dev, attr, &reg, true); 546 return vgic_v3_attr_regs_access(dev, attr, &reg, true);
539 } 547 }
548 case KVM_DEV_ARM_VGIC_GRP_CPU_SYSREGS: {
549 u64 __user *uaddr = (u64 __user *)(long)attr->addr;
550 u64 reg;
551
552 if (get_user(reg, uaddr))
553 return -EFAULT;
554
555 return vgic_v3_attr_regs_access(dev, attr, &reg, true);
556 }
540 } 557 }
541 return -ENXIO; 558 return -ENXIO;
542} 559}
@@ -563,6 +580,15 @@ static int vgic_v3_get_attr(struct kvm_device *dev,
563 tmp32 = reg; 580 tmp32 = reg;
564 return put_user(tmp32, uaddr); 581 return put_user(tmp32, uaddr);
565 } 582 }
583 case KVM_DEV_ARM_VGIC_GRP_CPU_SYSREGS: {
584 u64 __user *uaddr = (u64 __user *)(long)attr->addr;
585 u64 reg;
586
587 ret = vgic_v3_attr_regs_access(dev, attr, &reg, false);
588 if (ret)
589 return ret;
590 return put_user(reg, uaddr);
591 }
566 } 592 }
567 593
568 return -ENXIO; 594 return -ENXIO;
@@ -581,6 +607,7 @@ static int vgic_v3_has_attr(struct kvm_device *dev,
581 break; 607 break;
582 case KVM_DEV_ARM_VGIC_GRP_DIST_REGS: 608 case KVM_DEV_ARM_VGIC_GRP_DIST_REGS:
583 case KVM_DEV_ARM_VGIC_GRP_REDIST_REGS: 609 case KVM_DEV_ARM_VGIC_GRP_REDIST_REGS:
610 case KVM_DEV_ARM_VGIC_GRP_CPU_SYSREGS:
584 return vgic_v3_has_attr_regs(dev, attr); 611 return vgic_v3_has_attr_regs(dev, attr);
585 case KVM_DEV_ARM_VGIC_GRP_NR_IRQS: 612 case KVM_DEV_ARM_VGIC_GRP_NR_IRQS:
586 return 0; 613 return 0;
diff --git a/virt/kvm/arm/vgic/vgic-mmio-v3.c b/virt/kvm/arm/vgic/vgic-mmio-v3.c
index 2031138cfcf4..549ae459ca0e 100644
--- a/virt/kvm/arm/vgic/vgic-mmio-v3.c
+++ b/virt/kvm/arm/vgic/vgic-mmio-v3.c
@@ -645,6 +645,12 @@ int vgic_v3_has_attr_regs(struct kvm_device *dev, struct kvm_device_attr *attr)
645 iodev.base_addr = 0; 645 iodev.base_addr = 0;
646 break; 646 break;
647 } 647 }
648 case KVM_DEV_ARM_VGIC_GRP_CPU_SYSREGS: {
649 u64 reg, id;
650
651 id = (attr->attr & KVM_DEV_ARM_VGIC_SYSREG_INSTR_MASK);
652 return vgic_v3_has_cpu_sysregs_attr(vcpu, 0, id, &reg);
653 }
648 default: 654 default:
649 return -ENXIO; 655 return -ENXIO;
650 } 656 }
diff --git a/virt/kvm/arm/vgic/vgic-v3.c b/virt/kvm/arm/vgic/vgic-v3.c
index 42ff9c9826d3..edc6ee2dc852 100644
--- a/virt/kvm/arm/vgic/vgic-v3.c
+++ b/virt/kvm/arm/vgic/vgic-v3.c
@@ -238,6 +238,13 @@ void vgic_v3_enable(struct kvm_vcpu *vcpu)
238 vgic_v3->vgic_sre = 0; 238 vgic_v3->vgic_sre = 0;
239 } 239 }
240 240
241 vcpu->arch.vgic_cpu.num_id_bits = (kvm_vgic_global_state.ich_vtr_el2 &
242 ICH_VTR_ID_BITS_MASK) >>
243 ICH_VTR_ID_BITS_SHIFT;
244 vcpu->arch.vgic_cpu.num_pri_bits = ((kvm_vgic_global_state.ich_vtr_el2 &
245 ICH_VTR_PRI_BITS_MASK) >>
246 ICH_VTR_PRI_BITS_SHIFT) + 1;
247
241 /* Get the show on the road... */ 248 /* Get the show on the road... */
242 vgic_v3->vgic_hcr = ICH_HCR_EN; 249 vgic_v3->vgic_hcr = ICH_HCR_EN;
243} 250}
@@ -336,6 +343,7 @@ int vgic_v3_probe(const struct gic_kvm_info *info)
336 */ 343 */
337 kvm_vgic_global_state.nr_lr = (ich_vtr_el2 & 0xf) + 1; 344 kvm_vgic_global_state.nr_lr = (ich_vtr_el2 & 0xf) + 1;
338 kvm_vgic_global_state.can_emulate_gicv2 = false; 345 kvm_vgic_global_state.can_emulate_gicv2 = false;
346 kvm_vgic_global_state.ich_vtr_el2 = ich_vtr_el2;
339 347
340 if (!info->vcpu.start) { 348 if (!info->vcpu.start) {
341 kvm_info("GICv3: no GICV resource entry\n"); 349 kvm_info("GICv3: no GICV resource entry\n");
diff --git a/virt/kvm/arm/vgic/vgic.h b/virt/kvm/arm/vgic/vgic.h
index ecfe1a6c841a..a5a45f66c058 100644
--- a/virt/kvm/arm/vgic/vgic.h
+++ b/virt/kvm/arm/vgic/vgic.h
@@ -52,6 +52,27 @@
52 VGIC_AFFINITY_LEVEL(val, 2) | \ 52 VGIC_AFFINITY_LEVEL(val, 2) | \
53 VGIC_AFFINITY_LEVEL(val, 3)) 53 VGIC_AFFINITY_LEVEL(val, 3))
54 54
55/*
56 * As per Documentation/virtual/kvm/devices/arm-vgic-v3.txt,
57 * below macros are defined for CPUREG encoding.
58 */
59#define KVM_REG_ARM_VGIC_SYSREG_OP0_MASK 0x000000000000c000
60#define KVM_REG_ARM_VGIC_SYSREG_OP0_SHIFT 14
61#define KVM_REG_ARM_VGIC_SYSREG_OP1_MASK 0x0000000000003800
62#define KVM_REG_ARM_VGIC_SYSREG_OP1_SHIFT 11
63#define KVM_REG_ARM_VGIC_SYSREG_CRN_MASK 0x0000000000000780
64#define KVM_REG_ARM_VGIC_SYSREG_CRN_SHIFT 7
65#define KVM_REG_ARM_VGIC_SYSREG_CRM_MASK 0x0000000000000078
66#define KVM_REG_ARM_VGIC_SYSREG_CRM_SHIFT 3
67#define KVM_REG_ARM_VGIC_SYSREG_OP2_MASK 0x0000000000000007
68#define KVM_REG_ARM_VGIC_SYSREG_OP2_SHIFT 0
69
70#define KVM_DEV_ARM_VGIC_SYSREG_MASK (KVM_REG_ARM_VGIC_SYSREG_OP0_MASK | \
71 KVM_REG_ARM_VGIC_SYSREG_OP1_MASK | \
72 KVM_REG_ARM_VGIC_SYSREG_CRN_MASK | \
73 KVM_REG_ARM_VGIC_SYSREG_CRM_MASK | \
74 KVM_REG_ARM_VGIC_SYSREG_OP2_MASK)
75
55static inline bool irq_is_pending(struct vgic_irq *irq) 76static inline bool irq_is_pending(struct vgic_irq *irq)
56{ 77{
57 if (irq->config == VGIC_CONFIG_EDGE) 78 if (irq->config == VGIC_CONFIG_EDGE)
@@ -139,6 +160,10 @@ int vgic_v3_dist_uaccess(struct kvm_vcpu *vcpu, bool is_write,
139 int offset, u32 *val); 160 int offset, u32 *val);
140int vgic_v3_redist_uaccess(struct kvm_vcpu *vcpu, bool is_write, 161int vgic_v3_redist_uaccess(struct kvm_vcpu *vcpu, bool is_write,
141 int offset, u32 *val); 162 int offset, u32 *val);
163int vgic_v3_cpu_sysregs_uaccess(struct kvm_vcpu *vcpu, bool is_write,
164 u64 id, u64 *val);
165int vgic_v3_has_cpu_sysregs_attr(struct kvm_vcpu *vcpu, bool is_write, u64 id,
166 u64 *reg);
142int kvm_register_vgic_device(unsigned long type); 167int kvm_register_vgic_device(unsigned long type);
143void vgic_set_vmcr(struct kvm_vcpu *vcpu, struct vgic_vmcr *vmcr); 168void vgic_set_vmcr(struct kvm_vcpu *vcpu, struct vgic_vmcr *vmcr);
144void vgic_get_vmcr(struct kvm_vcpu *vcpu, struct vgic_vmcr *vmcr); 169void vgic_get_vmcr(struct kvm_vcpu *vcpu, struct vgic_vmcr *vmcr);