[PATCH v3 9/9] KVM: arm-vgic: Support CPU interface reg access
Marc Zyngier
maz at misterjones.org
Mon Dec 9 12:13:41 EST 2013
On 2013-11-17 04:30, Christoffer Dall wrote:
> Implement support for the CPU interface register access driven by
> MMIO
> address offsets from the CPU interface base address. Useful for user
> space to support save/restore of the VGIC state.
>
> This commit adds support only for the same logic as the current VGIC
> support, and no more. For example, the active priority registers are
> handled as RAZ/WI, just like setting priorities on the emulated
> distributor.
>
> Signed-off-by: Christoffer Dall <christoffer.dall at linaro.org>
Acked-by: Marc Zyngier <marc.zyngier at arm.com>
> ---
> virt/kvm/arm/vgic.c | 81
> ++++++++++++++++++++++++++++++++++++++++++++++-----
> 1 file changed, 73 insertions(+), 8 deletions(-)
>
> diff --git a/virt/kvm/arm/vgic.c b/virt/kvm/arm/vgic.c
> index 16053eb..a08b89a 100644
> --- a/virt/kvm/arm/vgic.c
> +++ b/virt/kvm/arm/vgic.c
> @@ -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;
> @@ -1703,9 +1707,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,
> @@ -1715,17 +1780,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,
> },
> };
--
Who you jivin' with that Cosmik Debris?
More information about the linux-arm-kernel
mailing list