]> Pileus Git - ~andy/linux/commitdiff
ARM: KVM: VGIC control interface world switch
authorMarc Zyngier <marc.zyngier@arm.com>
Tue, 22 Jan 2013 00:36:15 +0000 (19:36 -0500)
committerMarc Zyngier <marc.zyngier@arm.com>
Mon, 11 Feb 2013 19:00:03 +0000 (19:00 +0000)
Enable the VGIC control interface to be save-restored on world switch.

Reviewed-by: Will Deacon <will.deacon@arm.com>
Signed-off-by: Christoffer Dall <c.dall@virtualopensystems.com>
Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
arch/arm/kernel/asm-offsets.c
arch/arm/kvm/interrupts_head.S

index c8b3272dfed18f8778264d5714be343ade6a88e7..17cea2e78d88a5cc9d30ebaaf4cb118e63c5d62f 100644 (file)
@@ -169,6 +169,18 @@ int main(void)
   DEFINE(VCPU_HxFAR,           offsetof(struct kvm_vcpu, arch.hxfar));
   DEFINE(VCPU_HPFAR,           offsetof(struct kvm_vcpu, arch.hpfar));
   DEFINE(VCPU_HYP_PC,          offsetof(struct kvm_vcpu, arch.hyp_pc));
+#ifdef CONFIG_KVM_ARM_VGIC
+  DEFINE(VCPU_VGIC_CPU,                offsetof(struct kvm_vcpu, arch.vgic_cpu));
+  DEFINE(VGIC_CPU_HCR,         offsetof(struct vgic_cpu, vgic_hcr));
+  DEFINE(VGIC_CPU_VMCR,                offsetof(struct vgic_cpu, vgic_vmcr));
+  DEFINE(VGIC_CPU_MISR,                offsetof(struct vgic_cpu, vgic_misr));
+  DEFINE(VGIC_CPU_EISR,                offsetof(struct vgic_cpu, vgic_eisr));
+  DEFINE(VGIC_CPU_ELRSR,       offsetof(struct vgic_cpu, vgic_elrsr));
+  DEFINE(VGIC_CPU_APR,         offsetof(struct vgic_cpu, vgic_apr));
+  DEFINE(VGIC_CPU_LR,          offsetof(struct vgic_cpu, vgic_lr));
+  DEFINE(VGIC_CPU_NR_LR,       offsetof(struct vgic_cpu, nr_lr));
+  DEFINE(KVM_VGIC_VCTRL,       offsetof(struct kvm, arch.vgic.vctrl_base));
+#endif
   DEFINE(KVM_VTTBR,            offsetof(struct kvm, arch.vttbr));
 #endif
   return 0; 
index 6a95d341e9c5d2a7faa6b97a7c0e5f88bfd720ab..8c875d54a0893bf943ed88d0a10dc3a5cb31cb2a 100644 (file)
@@ -1,3 +1,5 @@
+#include <linux/irqchip/arm-gic.h>
+
 #define VCPU_USR_REG(_reg_nr)  (VCPU_USR_REGS + (_reg_nr * 4))
 #define VCPU_USR_SP            (VCPU_USR_REG(13))
 #define VCPU_USR_LR            (VCPU_USR_REG(14))
@@ -369,6 +371,49 @@ vcpu       .req    r0              @ vcpu pointer always in r0
  * Assumes vcpu pointer in vcpu reg
  */
 .macro save_vgic_state
+#ifdef CONFIG_KVM_ARM_VGIC
+       /* Get VGIC VCTRL base into r2 */
+       ldr     r2, [vcpu, #VCPU_KVM]
+       ldr     r2, [r2, #KVM_VGIC_VCTRL]
+       cmp     r2, #0
+       beq     2f
+
+       /* Compute the address of struct vgic_cpu */
+       add     r11, vcpu, #VCPU_VGIC_CPU
+
+       /* Save all interesting registers */
+       ldr     r3, [r2, #GICH_HCR]
+       ldr     r4, [r2, #GICH_VMCR]
+       ldr     r5, [r2, #GICH_MISR]
+       ldr     r6, [r2, #GICH_EISR0]
+       ldr     r7, [r2, #GICH_EISR1]
+       ldr     r8, [r2, #GICH_ELRSR0]
+       ldr     r9, [r2, #GICH_ELRSR1]
+       ldr     r10, [r2, #GICH_APR]
+
+       str     r3, [r11, #VGIC_CPU_HCR]
+       str     r4, [r11, #VGIC_CPU_VMCR]
+       str     r5, [r11, #VGIC_CPU_MISR]
+       str     r6, [r11, #VGIC_CPU_EISR]
+       str     r7, [r11, #(VGIC_CPU_EISR + 4)]
+       str     r8, [r11, #VGIC_CPU_ELRSR]
+       str     r9, [r11, #(VGIC_CPU_ELRSR + 4)]
+       str     r10, [r11, #VGIC_CPU_APR]
+
+       /* Clear GICH_HCR */
+       mov     r5, #0
+       str     r5, [r2, #GICH_HCR]
+
+       /* Save list registers */
+       add     r2, r2, #GICH_LR0
+       add     r3, r11, #VGIC_CPU_LR
+       ldr     r4, [r11, #VGIC_CPU_NR_LR]
+1:     ldr     r6, [r2], #4
+       str     r6, [r3], #4
+       subs    r4, r4, #1
+       bne     1b
+2:
+#endif
 .endm
 
 /*
@@ -377,6 +422,35 @@ vcpu       .req    r0              @ vcpu pointer always in r0
  * Assumes vcpu pointer in vcpu reg
  */
 .macro restore_vgic_state
+#ifdef CONFIG_KVM_ARM_VGIC
+       /* Get VGIC VCTRL base into r2 */
+       ldr     r2, [vcpu, #VCPU_KVM]
+       ldr     r2, [r2, #KVM_VGIC_VCTRL]
+       cmp     r2, #0
+       beq     2f
+
+       /* Compute the address of struct vgic_cpu */
+       add     r11, vcpu, #VCPU_VGIC_CPU
+
+       /* We only restore a minimal set of registers */
+       ldr     r3, [r11, #VGIC_CPU_HCR]
+       ldr     r4, [r11, #VGIC_CPU_VMCR]
+       ldr     r8, [r11, #VGIC_CPU_APR]
+
+       str     r3, [r2, #GICH_HCR]
+       str     r4, [r2, #GICH_VMCR]
+       str     r8, [r2, #GICH_APR]
+
+       /* Restore list registers */
+       add     r2, r2, #GICH_LR0
+       add     r3, r11, #VGIC_CPU_LR
+       ldr     r4, [r11, #VGIC_CPU_NR_LR]
+1:     ldr     r6, [r3], #4
+       str     r6, [r2], #4
+       subs    r4, r4, #1
+       bne     1b
+2:
+#endif
 .endm
 
 .equ vmentry,  0