aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--virt/kvm/arm/vgic.c81
1 files changed, 73 insertions, 8 deletions
diff --git a/virt/kvm/arm/vgic.c b/virt/kvm/arm/vgic.c
index e59aaa4c64e5..be456ce264d0 100644
--- a/virt/kvm/arm/vgic.c
+++ b/virt/kvm/arm/vgic.c
@@ -71,6 +71,10 @@
71#define VGIC_ADDR_UNDEF (-1) 71#define VGIC_ADDR_UNDEF (-1)
72#define IS_VGIC_ADDR_UNDEF(_x) ((_x) == VGIC_ADDR_UNDEF) 72#define IS_VGIC_ADDR_UNDEF(_x) ((_x) == VGIC_ADDR_UNDEF)
73 73
74#define PRODUCT_ID_KVM 0x4b /* ASCII code K */
75#define IMPLEMENTER_ARM 0x43b
76#define GICC_ARCH_VERSION_V2 0x2
77
74/* Physical address of vgic virtual cpu interface */ 78/* Physical address of vgic virtual cpu interface */
75static phys_addr_t vgic_vcpu_base; 79static phys_addr_t vgic_vcpu_base;
76 80
@@ -312,7 +316,7 @@ static bool handle_mmio_misc(struct kvm_vcpu *vcpu,
312 u32 word_offset = offset & 3; 316 u32 word_offset = offset & 3;
313 317
314 switch (offset & ~3) { 318 switch (offset & ~3) {
315 case 0: /* CTLR */ 319 case 0: /* GICD_CTLR */
316 reg = vcpu->kvm->arch.vgic.enabled; 320 reg = vcpu->kvm->arch.vgic.enabled;
317 vgic_reg_access(mmio, &reg, word_offset, 321 vgic_reg_access(mmio, &reg, word_offset,
318 ACCESS_READ_VALUE | ACCESS_WRITE_VALUE); 322 ACCESS_READ_VALUE | ACCESS_WRITE_VALUE);
@@ -323,15 +327,15 @@ static bool handle_mmio_misc(struct kvm_vcpu *vcpu,
323 } 327 }
324 break; 328 break;
325 329
326 case 4: /* TYPER */ 330 case 4: /* GICD_TYPER */
327 reg = (atomic_read(&vcpu->kvm->online_vcpus) - 1) << 5; 331 reg = (atomic_read(&vcpu->kvm->online_vcpus) - 1) << 5;
328 reg |= (VGIC_NR_IRQS >> 5) - 1; 332 reg |= (VGIC_NR_IRQS >> 5) - 1;
329 vgic_reg_access(mmio, &reg, word_offset, 333 vgic_reg_access(mmio, &reg, word_offset,
330 ACCESS_READ_VALUE | ACCESS_WRITE_IGNORED); 334 ACCESS_READ_VALUE | ACCESS_WRITE_IGNORED);
331 break; 335 break;
332 336
333 case 8: /* IIDR */ 337 case 8: /* GICD_IIDR */
334 reg = 0x4B00043B; 338 reg = (PRODUCT_ID_KVM << 24) | (IMPLEMENTER_ARM << 0);
335 vgic_reg_access(mmio, &reg, word_offset, 339 vgic_reg_access(mmio, &reg, word_offset,
336 ACCESS_READ_VALUE | ACCESS_WRITE_IGNORED); 340 ACCESS_READ_VALUE | ACCESS_WRITE_IGNORED);
337 break; 341 break;
@@ -1716,9 +1720,70 @@ int kvm_vgic_addr(struct kvm *kvm, unsigned long type, u64 *addr, bool write)
1716static bool handle_cpu_mmio_misc(struct kvm_vcpu *vcpu, 1720static bool handle_cpu_mmio_misc(struct kvm_vcpu *vcpu,
1717 struct kvm_exit_mmio *mmio, phys_addr_t offset) 1721 struct kvm_exit_mmio *mmio, phys_addr_t offset)
1718{ 1722{
1719 return true; 1723 struct vgic_cpu *vgic_cpu = &vcpu->arch.vgic_cpu;
1724 u32 reg, mask = 0, shift = 0;
1725 bool updated = false;
1726
1727 switch (offset & ~0x3) {
1728 case GIC_CPU_CTRL:
1729 mask = GICH_VMCR_CTRL_MASK;
1730 shift = GICH_VMCR_CTRL_SHIFT;
1731 break;
1732 case GIC_CPU_PRIMASK:
1733 mask = GICH_VMCR_PRIMASK_MASK;
1734 shift = GICH_VMCR_PRIMASK_SHIFT;
1735 break;
1736 case GIC_CPU_BINPOINT:
1737 mask = GICH_VMCR_BINPOINT_MASK;
1738 shift = GICH_VMCR_BINPOINT_SHIFT;
1739 break;
1740 case GIC_CPU_ALIAS_BINPOINT:
1741 mask = GICH_VMCR_ALIAS_BINPOINT_MASK;
1742 shift = GICH_VMCR_ALIAS_BINPOINT_SHIFT;
1743 break;
1744 }
1745
1746 if (!mmio->is_write) {
1747 reg = (vgic_cpu->vgic_vmcr & mask) >> shift;
1748 mmio_data_write(mmio, ~0, reg);
1749 } else {
1750 reg = mmio_data_read(mmio, ~0);
1751 reg = (reg << shift) & mask;
1752 if (reg != (vgic_cpu->vgic_vmcr & mask))
1753 updated = true;
1754 vgic_cpu->vgic_vmcr &= ~mask;
1755 vgic_cpu->vgic_vmcr |= reg;
1756 }
1757 return updated;
1758}
1759
1760static bool handle_mmio_abpr(struct kvm_vcpu *vcpu,
1761 struct kvm_exit_mmio *mmio, phys_addr_t offset)
1762{
1763 return handle_cpu_mmio_misc(vcpu, mmio, GIC_CPU_ALIAS_BINPOINT);
1720} 1764}
1721 1765
1766static bool handle_cpu_mmio_ident(struct kvm_vcpu *vcpu,
1767 struct kvm_exit_mmio *mmio,
1768 phys_addr_t offset)
1769{
1770 u32 reg;
1771
1772 if (mmio->is_write)
1773 return false;
1774
1775 /* GICC_IIDR */
1776 reg = (PRODUCT_ID_KVM << 20) |
1777 (GICC_ARCH_VERSION_V2 << 16) |
1778 (IMPLEMENTER_ARM << 0);
1779 mmio_data_write(mmio, ~0, reg);
1780 return false;
1781}
1782
1783/*
1784 * CPU Interface Register accesses - these are not accessed by the VM, but by
1785 * user space for saving and restoring VGIC state.
1786 */
1722static const struct mmio_range vgic_cpu_ranges[] = { 1787static const struct mmio_range vgic_cpu_ranges[] = {
1723 { 1788 {
1724 .base = GIC_CPU_CTRL, 1789 .base = GIC_CPU_CTRL,
@@ -1728,17 +1793,17 @@ static const struct mmio_range vgic_cpu_ranges[] = {
1728 { 1793 {
1729 .base = GIC_CPU_ALIAS_BINPOINT, 1794 .base = GIC_CPU_ALIAS_BINPOINT,
1730 .len = 4, 1795 .len = 4,
1731 .handle_mmio = handle_cpu_mmio_misc, 1796 .handle_mmio = handle_mmio_abpr,
1732 }, 1797 },
1733 { 1798 {
1734 .base = GIC_CPU_ACTIVEPRIO, 1799 .base = GIC_CPU_ACTIVEPRIO,
1735 .len = 16, 1800 .len = 16,
1736 .handle_mmio = handle_cpu_mmio_misc, 1801 .handle_mmio = handle_mmio_raz_wi,
1737 }, 1802 },
1738 { 1803 {
1739 .base = GIC_CPU_IDENT, 1804 .base = GIC_CPU_IDENT,
1740 .len = 4, 1805 .len = 4,
1741 .handle_mmio = handle_cpu_mmio_misc, 1806 .handle_mmio = handle_cpu_mmio_ident,
1742 }, 1807 },
1743}; 1808};
1744 1809