Re: [PATCH v2 02/11] ARM: KVM: Initial VGIC infrastructure support

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



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


[Index of Archives]     [Linux KVM]     [Spice Development]     [Libvirt]     [Libvirt Users]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux