On Thu, Jul 5, 2012 at 11:28 AM, Marc Zyngier <marc.zyngier@xxxxxxx> wrote: > Wire the basic framework code for VGIC support. Nothing to enable > yet. > > Signed-off-by: Marc Zyngier <marc.zyngier@xxxxxxx> > --- > arch/arm/include/asm/kvm_emulate.h | 9 +++++++ > arch/arm/include/asm/kvm_host.h | 8 ++++++ > arch/arm/include/asm/kvm_vgic.h | 47 ++++++++++++++++++++++++++++++++++++ > arch/arm/kvm/arm.c | 18 ++++++++++++++ > arch/arm/kvm/emulate.c | 2 +- > arch/arm/kvm/interrupts.S | 18 ++++++++++++++ > arch/arm/kvm/mmu.c | 3 +++ > virt/kvm/kvm_main.c | 5 ++-- > 8 files changed, 107 insertions(+), 3 deletions(-) > create mode 100644 arch/arm/include/asm/kvm_vgic.h > > diff --git a/arch/arm/include/asm/kvm_emulate.h b/arch/arm/include/asm/kvm_emulate.h > index c41537b..7774ec4 100644 > --- a/arch/arm/include/asm/kvm_emulate.h > +++ b/arch/arm/include/asm/kvm_emulate.h > @@ -22,6 +22,15 @@ > #include <linux/kvm_host.h> > #include <asm/kvm_asm.h> > > +/* > + * The in-kernel MMIO emulation code wants to use a copy of run->mmio, > + * which is an anonymous type. In order to avoid keeping the two types > + * in sync, use the below horror. Yes, this is beyond ugly. > + */ I don't know to laugh or cry. Probably changing the in-kernel mmio emulation code is a better way to go. > +struct kvm_exit_mmio { > + typeof(((struct kvm_run *)0)->mmio) mmio; > +}; > + > u32 *vcpu_reg_mode(struct kvm_vcpu *vcpu, u8 reg_num, enum vcpu_mode mode); > > static inline u8 __vcpu_mode(u32 cpsr) > diff --git a/arch/arm/include/asm/kvm_host.h b/arch/arm/include/asm/kvm_host.h > index 91be029..3b289b8 100644 > --- a/arch/arm/include/asm/kvm_host.h > +++ b/arch/arm/include/asm/kvm_host.h > @@ -24,6 +24,8 @@ > #define KVM_PRIVATE_MEM_SLOTS 4 > #define KVM_COALESCED_MMIO_PAGE_OFFSET 1 > > +#include <asm/kvm_vgic.h> > + > /* We don't currently support large pages. */ > #define KVM_HPAGE_GFN_SHIFT(x) 0 > #define KVM_NR_PAGE_SIZES 1 > @@ -45,6 +47,9 @@ struct kvm_arch { > > /* VTTBR value associated with above pgd and vmid */ > u64 vttbr; > + > + /* Interrupt controller */ > + struct vgic_dist vgic; > }; > > #define EXCEPTION_NONE 0 > @@ -125,6 +130,9 @@ struct kvm_vcpu_arch { > > /* Hyp exception information */ > u32 hyp_pc; /* PC when exception was taken from Hyp mode */ > + > + /* VGIC state */ > + struct vgic_cpu vgic_cpu; > }; > > struct kvm_vm_stat { > diff --git a/arch/arm/include/asm/kvm_vgic.h b/arch/arm/include/asm/kvm_vgic.h > new file mode 100644 > index 0000000..8e8bd6d > --- /dev/null > +++ b/arch/arm/include/asm/kvm_vgic.h > @@ -0,0 +1,47 @@ > +#ifndef __ASM_ARM_KVM_VGIC_H > +#define __ASM_ARM_KVM_VGIC_H > + > +struct vgic_dist { > +}; > + > +struct vgic_cpu { > +}; > + > +struct kvm; > +struct kvm_vcpu; > +struct kvm_run; > +struct kvm_exit_mmio; > + > +#ifndef CONFIG_KVM_ARM_VGIC > +static inline int kvm_vgic_hyp_init(void) > +{ > + return 0; > +} > + > +static inline int kvm_vgic_init(struct kvm *kvm) > +{ > + return 0; > +} > + > +static inline void kvm_vgic_vcpu_init(struct kvm_vcpu *vcpu) {} > +static inline void kvm_vgic_sync_to_cpu(struct kvm_vcpu *vcpu) {} > +static inline void kvm_vgic_sync_from_cpu(struct kvm_vcpu *vcpu) {} > + > +static inline int kvm_vgic_vcpu_pending_irq(struct kvm_vcpu *vcpu) > +{ > + return 0; > +} > + > +static inline int vgic_handle_mmio(struct kvm_vcpu *vcpu, struct kvm_run *run, > + struct kvm_exit_mmio *mmio) > +{ > + return KVM_EXIT_MMIO; > +} > + > +static inline int irqchip_in_kernel(struct kvm *kvm) > +{ > + return 0; > +} > +#endif > + > +#endif > diff --git a/arch/arm/kvm/arm.c b/arch/arm/kvm/arm.c > index 8bb53cb..bdf0f86 100644 > --- a/arch/arm/kvm/arm.c > +++ b/arch/arm/kvm/arm.c > @@ -177,6 +177,9 @@ int kvm_dev_ioctl_check_extension(long ext) > { > int r; > switch (ext) { > +#ifdef CONFIG_KVM_ARM_VGIC > + case KVM_CAP_IRQCHIP: > +#endif > case KVM_CAP_USER_MEMORY: > case KVM_CAP_DESTROY_MEMORY_REGION_WORKS: > r = 1; > @@ -289,6 +292,9 @@ int kvm_arch_vcpu_init(struct kvm_vcpu *vcpu) > if (ret < 0) > return ret; > > + /* Set up VGIC */ > + kvm_vgic_vcpu_init(vcpu); > + > return 0; > } > > @@ -343,6 +349,7 @@ int kvm_arch_vcpu_ioctl_set_mpstate(struct kvm_vcpu *vcpu, > int kvm_arch_vcpu_runnable(struct kvm_vcpu *v) > { > return !!v->arch.irq_lines || > + kvm_vgic_vcpu_pending_irq(v) || > !v->arch.wait_for_interrupts; > } > > @@ -578,6 +585,8 @@ int kvm_arch_vcpu_ioctl_run(struct kvm_vcpu *vcpu, struct kvm_run *run) > > update_vttbr(vcpu->kvm); > > + kvm_vgic_sync_to_cpu(vcpu); > + > /* > * Make sure preemption is disabled while calling handle_exit > * as exit handling touches CPU-specific resources, such as > @@ -626,6 +635,8 @@ int kvm_arch_vcpu_ioctl_run(struct kvm_vcpu *vcpu, struct kvm_run *run) > } else { > exit_reason = ret; /* 0 == KVM_EXIT_UNKNOWN */ > } > + > + kvm_vgic_sync_from_cpu(vcpu); > } > > if (vcpu->sigset_active) > @@ -808,6 +819,13 @@ static int init_hyp_mode(void) > } > > /* > + * Init HYP view of VGIC > + */ > + err = kvm_vgic_hyp_init(); > + if (err) > + goto out_free_mappings; > + > + /* > * Set the HVBAR to the virtual kernel address > */ > for_each_online_cpu(cpu) > diff --git a/arch/arm/kvm/emulate.c b/arch/arm/kvm/emulate.c > index 564add2..4580c1f4 100644 > --- a/arch/arm/kvm/emulate.c > +++ b/arch/arm/kvm/emulate.c > @@ -518,7 +518,7 @@ int kvm_handle_wfi(struct kvm_vcpu *vcpu, struct kvm_run *run) > { > trace_kvm_wfi(vcpu->arch.regs.pc); > vcpu->stat.wfi_exits++; > - if (!vcpu->arch.irq_lines) > + if (!vcpu->arch.irq_lines && !kvm_vgic_vcpu_pending_irq(vcpu)) > vcpu->arch.wait_for_interrupts = 1; > return 0; > } > diff --git a/arch/arm/kvm/interrupts.S b/arch/arm/kvm/interrupts.S > index fd7331c..f3e4c3c 100644 > --- a/arch/arm/kvm/interrupts.S > +++ b/arch/arm/kvm/interrupts.S > @@ -267,6 +267,20 @@ ENDPROC(__kvm_flush_vm_context) > mcr p15, 0, r11, c10, c2, 1 @ NMRR > .endm > > +/* > + * Save the VGIC CPU state into memory > + * @vcpup: Register pointing to VCPU struct > + */ > +.macro save_vgic_state vcpup > +.endm > + > +/* > + * Restore the VGIC CPU state from memory > + * @vcpup: Register pointing to VCPU struct > + */ > +.macro restore_vgic_state vcpup > +.endm > + > /* Configures the HSTR (Hyp System Trap Register) on entry/return > * (hardware reset value is 0) */ > .macro set_hstr entry > @@ -324,6 +338,8 @@ ENTRY(__kvm_vcpu_run) > store_mode_state sp, irq > store_mode_state sp, fiq > > + restore_vgic_state r0 > + > @ Store hardware CP15 state and load guest state > read_cp15_state > write_cp15_state 1, r0 > @@ -412,6 +428,8 @@ __kvm_vcpu_return: > read_cp15_state 1, r1 > write_cp15_state > > + save_vgic_state r1 > + > load_mode_state sp, fiq > load_mode_state sp, irq > load_mode_state sp, und > diff --git a/arch/arm/kvm/mmu.c b/arch/arm/kvm/mmu.c > index ca76be0..4955a51 100644 > --- a/arch/arm/kvm/mmu.c > +++ b/arch/arm/kvm/mmu.c > @@ -598,6 +598,7 @@ static int io_mem_abort(struct kvm_vcpu *vcpu, struct kvm_run *run, > { > unsigned long rd, len, instr_len; > bool is_write, sign_extend; > + struct kvm_exit_mmio mmio; > > if (!(vcpu->arch.hsr & HSR_ISV)) > return invalid_io_mem_abort(vcpu, fault_ipa); > @@ -654,6 +655,8 @@ static int io_mem_abort(struct kvm_vcpu *vcpu, struct kvm_run *run, > if (is_write) > memcpy(run->mmio.data, vcpu_reg(vcpu, rd), len); > > + run->exit_reason = vgic_handle_mmio(vcpu, run); > + > /* > * The MMIO instruction is emulated and should not be re-executed > * in the guest. > diff --git a/virt/kvm/kvm_main.c b/virt/kvm/kvm_main.c > index 1d33877..d19c0f0 100644 > --- a/virt/kvm/kvm_main.c > +++ b/virt/kvm/kvm_main.c > @@ -1756,12 +1756,13 @@ static long kvm_vcpu_ioctl(struct file *filp, > if (vcpu->kvm->mm != current->mm) > return -EIO; > > -#if defined(CONFIG_S390) || defined(CONFIG_PPC) > +#if defined(CONFIG_S390) || defined(CONFIG_PPC) || defined(CONFIG_ARM) > /* > * Special cases: vcpu ioctls that are asynchronous to vcpu execution, > * so vcpu_load() would break it. > */ > - if (ioctl == KVM_S390_INTERRUPT || ioctl == KVM_INTERRUPT) > + if (ioctl == KVM_S390_INTERRUPT || ioctl == KVM_INTERRUPT || > + ioctl == KVM_IRQ_LINE) > return kvm_arch_vcpu_ioctl(filp, ioctl, arg); > #endif > > -- > 1.7.10.3 > > otherwise looks good _______________________________________________ kvmarm mailing list kvmarm@xxxxxxxxxxxxxxxxxxxxx https://lists.cs.columbia.edu/cucslists/listinfo/kvmarm