|
@@ -71,6 +71,10 @@
|
|
|
#define VGIC_ADDR_UNDEF (-1)
|
|
|
#define IS_VGIC_ADDR_UNDEF(_x) ((_x) == VGIC_ADDR_UNDEF)
|
|
|
|
|
|
+#define PRODUCT_ID_KVM 0x4b /* ASCII code K */
|
|
|
+#define IMPLEMENTER_ARM 0x43b
|
|
|
+#define GICC_ARCH_VERSION_V2 0x2
|
|
|
+
|
|
|
/* Physical address of vgic virtual cpu interface */
|
|
|
static phys_addr_t vgic_vcpu_base;
|
|
|
|
|
@@ -312,7 +316,7 @@ static bool handle_mmio_misc(struct kvm_vcpu *vcpu,
|
|
|
u32 word_offset = offset & 3;
|
|
|
|
|
|
switch (offset & ~3) {
|
|
|
- case 0: /* CTLR */
|
|
|
+ case 0: /* GICD_CTLR */
|
|
|
reg = vcpu->kvm->arch.vgic.enabled;
|
|
|
vgic_reg_access(mmio, ®, word_offset,
|
|
|
ACCESS_READ_VALUE | ACCESS_WRITE_VALUE);
|
|
@@ -323,15 +327,15 @@ static bool handle_mmio_misc(struct kvm_vcpu *vcpu,
|
|
|
}
|
|
|
break;
|
|
|
|
|
|
- case 4: /* TYPER */
|
|
|
+ case 4: /* GICD_TYPER */
|
|
|
reg = (atomic_read(&vcpu->kvm->online_vcpus) - 1) << 5;
|
|
|
reg |= (VGIC_NR_IRQS >> 5) - 1;
|
|
|
vgic_reg_access(mmio, ®, word_offset,
|
|
|
ACCESS_READ_VALUE | ACCESS_WRITE_IGNORED);
|
|
|
break;
|
|
|
|
|
|
- case 8: /* IIDR */
|
|
|
- reg = 0x4B00043B;
|
|
|
+ case 8: /* GICD_IIDR */
|
|
|
+ reg = (PRODUCT_ID_KVM << 24) | (IMPLEMENTER_ARM << 0);
|
|
|
vgic_reg_access(mmio, ®, word_offset,
|
|
|
ACCESS_READ_VALUE | ACCESS_WRITE_IGNORED);
|
|
|
break;
|
|
@@ -1716,9 +1720,70 @@ int kvm_vgic_addr(struct kvm *kvm, unsigned long type, u64 *addr, bool write)
|
|
|
static bool handle_cpu_mmio_misc(struct kvm_vcpu *vcpu,
|
|
|
struct kvm_exit_mmio *mmio, phys_addr_t offset)
|
|
|
{
|
|
|
- return true;
|
|
|
+ struct vgic_cpu *vgic_cpu = &vcpu->arch.vgic_cpu;
|
|
|
+ u32 reg, mask = 0, shift = 0;
|
|
|
+ bool updated = false;
|
|
|
+
|
|
|
+ switch (offset & ~0x3) {
|
|
|
+ case GIC_CPU_CTRL:
|
|
|
+ mask = GICH_VMCR_CTRL_MASK;
|
|
|
+ shift = GICH_VMCR_CTRL_SHIFT;
|
|
|
+ break;
|
|
|
+ case GIC_CPU_PRIMASK:
|
|
|
+ mask = GICH_VMCR_PRIMASK_MASK;
|
|
|
+ shift = GICH_VMCR_PRIMASK_SHIFT;
|
|
|
+ break;
|
|
|
+ case GIC_CPU_BINPOINT:
|
|
|
+ mask = GICH_VMCR_BINPOINT_MASK;
|
|
|
+ shift = GICH_VMCR_BINPOINT_SHIFT;
|
|
|
+ break;
|
|
|
+ case GIC_CPU_ALIAS_BINPOINT:
|
|
|
+ mask = GICH_VMCR_ALIAS_BINPOINT_MASK;
|
|
|
+ shift = GICH_VMCR_ALIAS_BINPOINT_SHIFT;
|
|
|
+ break;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (!mmio->is_write) {
|
|
|
+ reg = (vgic_cpu->vgic_vmcr & mask) >> shift;
|
|
|
+ mmio_data_write(mmio, ~0, reg);
|
|
|
+ } else {
|
|
|
+ reg = mmio_data_read(mmio, ~0);
|
|
|
+ reg = (reg << shift) & mask;
|
|
|
+ if (reg != (vgic_cpu->vgic_vmcr & mask))
|
|
|
+ updated = true;
|
|
|
+ vgic_cpu->vgic_vmcr &= ~mask;
|
|
|
+ vgic_cpu->vgic_vmcr |= reg;
|
|
|
+ }
|
|
|
+ return updated;
|
|
|
+}
|
|
|
+
|
|
|
+static bool handle_mmio_abpr(struct kvm_vcpu *vcpu,
|
|
|
+ struct kvm_exit_mmio *mmio, phys_addr_t offset)
|
|
|
+{
|
|
|
+ return handle_cpu_mmio_misc(vcpu, mmio, GIC_CPU_ALIAS_BINPOINT);
|
|
|
}
|
|
|
|
|
|
+static bool handle_cpu_mmio_ident(struct kvm_vcpu *vcpu,
|
|
|
+ struct kvm_exit_mmio *mmio,
|
|
|
+ phys_addr_t offset)
|
|
|
+{
|
|
|
+ u32 reg;
|
|
|
+
|
|
|
+ if (mmio->is_write)
|
|
|
+ return false;
|
|
|
+
|
|
|
+ /* GICC_IIDR */
|
|
|
+ reg = (PRODUCT_ID_KVM << 20) |
|
|
|
+ (GICC_ARCH_VERSION_V2 << 16) |
|
|
|
+ (IMPLEMENTER_ARM << 0);
|
|
|
+ mmio_data_write(mmio, ~0, reg);
|
|
|
+ return false;
|
|
|
+}
|
|
|
+
|
|
|
+/*
|
|
|
+ * CPU Interface Register accesses - these are not accessed by the VM, but by
|
|
|
+ * user space for saving and restoring VGIC state.
|
|
|
+ */
|
|
|
static const struct mmio_range vgic_cpu_ranges[] = {
|
|
|
{
|
|
|
.base = GIC_CPU_CTRL,
|
|
@@ -1728,17 +1793,17 @@ static const struct mmio_range vgic_cpu_ranges[] = {
|
|
|
{
|
|
|
.base = GIC_CPU_ALIAS_BINPOINT,
|
|
|
.len = 4,
|
|
|
- .handle_mmio = handle_cpu_mmio_misc,
|
|
|
+ .handle_mmio = handle_mmio_abpr,
|
|
|
},
|
|
|
{
|
|
|
.base = GIC_CPU_ACTIVEPRIO,
|
|
|
.len = 16,
|
|
|
- .handle_mmio = handle_cpu_mmio_misc,
|
|
|
+ .handle_mmio = handle_mmio_raz_wi,
|
|
|
},
|
|
|
{
|
|
|
.base = GIC_CPU_IDENT,
|
|
|
.len = 4,
|
|
|
- .handle_mmio = handle_cpu_mmio_misc,
|
|
|
+ .handle_mmio = handle_cpu_mmio_ident,
|
|
|
},
|
|
|
};
|
|
|
|