diff options
| -rw-r--r-- | Documentation/virtual/kvm/api.txt | 2 | ||||
| -rw-r--r-- | arch/arm/include/uapi/asm/kvm.h | 2 | ||||
| -rw-r--r-- | arch/arm/kvm/Kconfig | 1 | ||||
| -rw-r--r-- | arch/arm/kvm/Makefile | 1 | ||||
| -rw-r--r-- | arch/arm/kvm/arm.c | 6 | ||||
| -rw-r--r-- | arch/arm64/kvm/Kconfig | 4 | ||||
| -rw-r--r-- | arch/arm64/kvm/hyp/switch.c | 8 | ||||
| -rw-r--r-- | arch/arm64/kvm/reset.c | 6 | ||||
| -rw-r--r-- | include/linux/irqchip/arm-gic-v3.h | 8 | ||||
| -rw-r--r-- | virt/kvm/arm/arch_timer.c | 17 | ||||
| -rw-r--r-- | virt/kvm/arm/vgic/vgic-its.c | 11 | ||||
| -rw-r--r-- | virt/kvm/arm/vgic/vgic-kvm-device.c | 2 | ||||
| -rw-r--r-- | virt/kvm/arm/vgic/vgic-mmio-v2.c | 3 | ||||
| -rw-r--r-- | virt/kvm/arm/vgic/vgic-mmio-v3.c | 2 | ||||
| -rw-r--r-- | virt/kvm/arm/vgic/vgic.h | 26 | 
15 files changed, 36 insertions, 63 deletions
diff --git a/Documentation/virtual/kvm/api.txt b/Documentation/virtual/kvm/api.txt index 8a5ebd118313..72a718c1176d 100644 --- a/Documentation/virtual/kvm/api.txt +++ b/Documentation/virtual/kvm/api.txt @@ -2201,7 +2201,7 @@ after pausing the vcpu, but before it is resumed.  4.71 KVM_SIGNAL_MSI  Capability: KVM_CAP_SIGNAL_MSI -Architectures: x86 arm64 +Architectures: x86 arm arm64  Type: vm ioctl  Parameters: struct kvm_msi (in)  Returns: >0 on delivery, 0 if guest blocked the MSI, and -1 on error diff --git a/arch/arm/include/uapi/asm/kvm.h b/arch/arm/include/uapi/asm/kvm.h index b38c10c73579..af05f8e0903e 100644 --- a/arch/arm/include/uapi/asm/kvm.h +++ b/arch/arm/include/uapi/asm/kvm.h @@ -87,9 +87,11 @@ struct kvm_regs {  /* Supported VGICv3 address types  */  #define KVM_VGIC_V3_ADDR_TYPE_DIST	2  #define KVM_VGIC_V3_ADDR_TYPE_REDIST	3 +#define KVM_VGIC_ITS_ADDR_TYPE		4  #define KVM_VGIC_V3_DIST_SIZE		SZ_64K  #define KVM_VGIC_V3_REDIST_SIZE		(2 * SZ_64K) +#define KVM_VGIC_V3_ITS_SIZE		(2 * SZ_64K)  #define KVM_ARM_VCPU_POWER_OFF		0 /* CPU is started in OFF state */  #define KVM_ARM_VCPU_PSCI_0_2		1 /* CPU uses PSCI v0.2 */ diff --git a/arch/arm/kvm/Kconfig b/arch/arm/kvm/Kconfig index 3e1cd0452d67..90d0176fb30d 100644 --- a/arch/arm/kvm/Kconfig +++ b/arch/arm/kvm/Kconfig @@ -34,6 +34,7 @@ config KVM  	select HAVE_KVM_IRQFD  	select HAVE_KVM_IRQCHIP  	select HAVE_KVM_IRQ_ROUTING +	select HAVE_KVM_MSI  	depends on ARM_VIRT_EXT && ARM_LPAE && ARM_ARCH_TIMER  	---help---  	  Support hosting virtualized guest machines. diff --git a/arch/arm/kvm/Makefile b/arch/arm/kvm/Makefile index f19842ea5418..d571243ab4d1 100644 --- a/arch/arm/kvm/Makefile +++ b/arch/arm/kvm/Makefile @@ -32,5 +32,6 @@ obj-y += $(KVM)/arm/vgic/vgic-mmio.o  obj-y += $(KVM)/arm/vgic/vgic-mmio-v2.o  obj-y += $(KVM)/arm/vgic/vgic-mmio-v3.o  obj-y += $(KVM)/arm/vgic/vgic-kvm-device.o +obj-y += $(KVM)/arm/vgic/vgic-its.o  obj-y += $(KVM)/irqchip.o  obj-y += $(KVM)/arm/arch_timer.o diff --git a/arch/arm/kvm/arm.c b/arch/arm/kvm/arm.c index 19b5f5c1c0ff..8f92efa8460e 100644 --- a/arch/arm/kvm/arm.c +++ b/arch/arm/kvm/arm.c @@ -221,6 +221,12 @@ int kvm_vm_ioctl_check_extension(struct kvm *kvm, long ext)  	case KVM_CAP_MAX_VCPUS:  		r = KVM_MAX_VCPUS;  		break; +	case KVM_CAP_MSI_DEVID: +		if (!kvm) +			r = -EINVAL; +		else +			r = kvm->arch.vgic.msis_require_devid; +		break;  	default:  		r = kvm_arch_dev_ioctl_check_extension(kvm, ext);  		break; diff --git a/arch/arm64/kvm/Kconfig b/arch/arm64/kvm/Kconfig index 6eaf12c1d627..52cb7ad9b2fd 100644 --- a/arch/arm64/kvm/Kconfig +++ b/arch/arm64/kvm/Kconfig @@ -16,9 +16,6 @@ menuconfig VIRTUALIZATION  if VIRTUALIZATION -config KVM_ARM_VGIC_V3_ITS -	bool -  config KVM  	bool "Kernel-based Virtual Machine (KVM) support"  	depends on OF @@ -34,7 +31,6 @@ config KVM  	select KVM_VFIO  	select HAVE_KVM_EVENTFD  	select HAVE_KVM_IRQFD -	select KVM_ARM_VGIC_V3_ITS  	select KVM_ARM_PMU if HW_PERF_EVENTS  	select HAVE_KVM_MSI  	select HAVE_KVM_IRQCHIP diff --git a/arch/arm64/kvm/hyp/switch.c b/arch/arm64/kvm/hyp/switch.c index 83037cd62d01..0c848c18ca44 100644 --- a/arch/arm64/kvm/hyp/switch.c +++ b/arch/arm64/kvm/hyp/switch.c @@ -85,7 +85,13 @@ static void __hyp_text __activate_traps(struct kvm_vcpu *vcpu)  	write_sysreg(val, hcr_el2);  	/* Trap on AArch32 cp15 c15 accesses (EL1 or EL0) */  	write_sysreg(1 << 15, hstr_el2); -	/* Make sure we trap PMU access from EL0 to EL2 */ +	/* +	 * Make sure we trap PMU access from EL0 to EL2. Also sanitize +	 * PMSELR_EL0 to make sure it never contains the cycle +	 * counter, which could make a PMXEVCNTR_EL0 access UNDEF at +	 * EL1 instead of being trapped to EL2. +	 */ +	write_sysreg(0, pmselr_el0);  	write_sysreg(ARMV8_PMU_USERENR_MASK, pmuserenr_el0);  	write_sysreg(vcpu->arch.mdcr_el2, mdcr_el2);  	__activate_traps_arch()(); diff --git a/arch/arm64/kvm/reset.c b/arch/arm64/kvm/reset.c index 5bc460884639..e95d4f68bf54 100644 --- a/arch/arm64/kvm/reset.c +++ b/arch/arm64/kvm/reset.c @@ -86,12 +86,6 @@ int kvm_arch_dev_ioctl_check_extension(struct kvm *kvm, long ext)  	case KVM_CAP_VCPU_ATTRIBUTES:  		r = 1;  		break; -	case KVM_CAP_MSI_DEVID: -		if (!kvm) -			r = -EINVAL; -		else -			r = kvm->arch.vgic.msis_require_devid; -		break;  	default:  		r = 0;  	} diff --git a/include/linux/irqchip/arm-gic-v3.h b/include/linux/irqchip/arm-gic-v3.h index b7e34313cdfe..0deea34494e7 100644 --- a/include/linux/irqchip/arm-gic-v3.h +++ b/include/linux/irqchip/arm-gic-v3.h @@ -295,10 +295,10 @@  #define GITS_BASER_InnerShareable					\  	GIC_BASER_SHAREABILITY(GITS_BASER, InnerShareable)  #define GITS_BASER_PAGE_SIZE_SHIFT	(8) -#define GITS_BASER_PAGE_SIZE_4K		(0UL << GITS_BASER_PAGE_SIZE_SHIFT) -#define GITS_BASER_PAGE_SIZE_16K	(1UL << GITS_BASER_PAGE_SIZE_SHIFT) -#define GITS_BASER_PAGE_SIZE_64K	(2UL << GITS_BASER_PAGE_SIZE_SHIFT) -#define GITS_BASER_PAGE_SIZE_MASK	(3UL << GITS_BASER_PAGE_SIZE_SHIFT) +#define GITS_BASER_PAGE_SIZE_4K		(0ULL << GITS_BASER_PAGE_SIZE_SHIFT) +#define GITS_BASER_PAGE_SIZE_16K	(1ULL << GITS_BASER_PAGE_SIZE_SHIFT) +#define GITS_BASER_PAGE_SIZE_64K	(2ULL << GITS_BASER_PAGE_SIZE_SHIFT) +#define GITS_BASER_PAGE_SIZE_MASK	(3ULL << GITS_BASER_PAGE_SIZE_SHIFT)  #define GITS_BASER_PAGES_MAX		256  #define GITS_BASER_PAGES_SHIFT		(0)  #define GITS_BASER_NR_PAGES(r)		(((r) & 0xff) + 1) diff --git a/virt/kvm/arm/arch_timer.c b/virt/kvm/arm/arch_timer.c index 27a1f6341d41..ae95fc0e3214 100644 --- a/virt/kvm/arm/arch_timer.c +++ b/virt/kvm/arm/arch_timer.c @@ -425,6 +425,11 @@ int kvm_timer_hyp_init(void)  	info = arch_timer_get_kvm_info();  	timecounter = &info->timecounter; +	if (!timecounter->cc) { +		kvm_err("kvm_arch_timer: uninitialized timecounter\n"); +		return -ENODEV; +	} +  	if (info->virtual_irq <= 0) {  		kvm_err("kvm_arch_timer: invalid virtual timer IRQ: %d\n",  			info->virtual_irq); @@ -498,17 +503,7 @@ int kvm_timer_enable(struct kvm_vcpu *vcpu)  	if (ret)  		return ret; - -	/* -	 * There is a potential race here between VCPUs starting for the first -	 * time, which may be enabling the timer multiple times.  That doesn't -	 * hurt though, because we're just setting a variable to the same -	 * variable that it already was.  The important thing is that all -	 * VCPUs have the enabled variable set, before entering the guest, if -	 * the arch timers are enabled. -	 */ -	if (timecounter) -		timer->enabled = 1; +	timer->enabled = 1;  	return 0;  } diff --git a/virt/kvm/arm/vgic/vgic-its.c b/virt/kvm/arm/vgic/vgic-its.c index 4660a7d04eea..8c2b3cdcb2c5 100644 --- a/virt/kvm/arm/vgic/vgic-its.c +++ b/virt/kvm/arm/vgic/vgic-its.c @@ -632,21 +632,22 @@ static bool vgic_its_check_id(struct vgic_its *its, u64 baser, int id)  	int index;  	u64 indirect_ptr;  	gfn_t gfn; +	int esz = GITS_BASER_ENTRY_SIZE(baser);  	if (!(baser & GITS_BASER_INDIRECT)) {  		phys_addr_t addr; -		if (id >= (l1_tbl_size / GITS_BASER_ENTRY_SIZE(baser))) +		if (id >= (l1_tbl_size / esz))  			return false; -		addr = BASER_ADDRESS(baser) + id * GITS_BASER_ENTRY_SIZE(baser); +		addr = BASER_ADDRESS(baser) + id * esz;  		gfn = addr >> PAGE_SHIFT;  		return kvm_is_visible_gfn(its->dev->kvm, gfn);  	}  	/* calculate and check the index into the 1st level */ -	index = id / (SZ_64K / GITS_BASER_ENTRY_SIZE(baser)); +	index = id / (SZ_64K / esz);  	if (index >= (l1_tbl_size / sizeof(u64)))  		return false; @@ -670,8 +671,8 @@ static bool vgic_its_check_id(struct vgic_its *its, u64 baser, int id)  	indirect_ptr &= GENMASK_ULL(51, 16);  	/* Find the address of the actual entry */ -	index = id % (SZ_64K / GITS_BASER_ENTRY_SIZE(baser)); -	indirect_ptr += index * GITS_BASER_ENTRY_SIZE(baser); +	index = id % (SZ_64K / esz); +	indirect_ptr += index * esz;  	gfn = indirect_ptr >> PAGE_SHIFT;  	return kvm_is_visible_gfn(its->dev->kvm, gfn); diff --git a/virt/kvm/arm/vgic/vgic-kvm-device.c b/virt/kvm/arm/vgic/vgic-kvm-device.c index ce1f4ed9daf4..fbe87a63d250 100644 --- a/virt/kvm/arm/vgic/vgic-kvm-device.c +++ b/virt/kvm/arm/vgic/vgic-kvm-device.c @@ -221,11 +221,9 @@ int kvm_register_vgic_device(unsigned long type)  		ret = kvm_register_device_ops(&kvm_arm_vgic_v3_ops,  					      KVM_DEV_TYPE_ARM_VGIC_V3); -#ifdef CONFIG_KVM_ARM_VGIC_V3_ITS  		if (ret)  			break;  		ret = kvm_vgic_register_its_device(); -#endif  		break;  	} diff --git a/virt/kvm/arm/vgic/vgic-mmio-v2.c b/virt/kvm/arm/vgic/vgic-mmio-v2.c index b44b359cbbad..78e34bc4d89b 100644 --- a/virt/kvm/arm/vgic/vgic-mmio-v2.c +++ b/virt/kvm/arm/vgic/vgic-mmio-v2.c @@ -129,6 +129,7 @@ static void vgic_mmio_write_target(struct kvm_vcpu *vcpu,  				   unsigned long val)  {  	u32 intid = VGIC_ADDR_TO_INTID(addr, 8); +	u8 cpu_mask = GENMASK(atomic_read(&vcpu->kvm->online_vcpus) - 1, 0);  	int i;  	/* GICD_ITARGETSR[0-7] are read-only */ @@ -141,7 +142,7 @@ static void vgic_mmio_write_target(struct kvm_vcpu *vcpu,  		spin_lock(&irq->irq_lock); -		irq->targets = (val >> (i * 8)) & 0xff; +		irq->targets = (val >> (i * 8)) & cpu_mask;  		target = irq->targets ? __ffs(irq->targets) : 0;  		irq->target_vcpu = kvm_get_vcpu(vcpu->kvm, target); diff --git a/virt/kvm/arm/vgic/vgic-mmio-v3.c b/virt/kvm/arm/vgic/vgic-mmio-v3.c index 0d3c76a4208b..50f42f0f8c4f 100644 --- a/virt/kvm/arm/vgic/vgic-mmio-v3.c +++ b/virt/kvm/arm/vgic/vgic-mmio-v3.c @@ -42,7 +42,6 @@ u64 update_64bit_reg(u64 reg, unsigned int offset, unsigned int len,  	return reg | ((u64)val << lower);  } -#ifdef CONFIG_KVM_ARM_VGIC_V3_ITS  bool vgic_has_its(struct kvm *kvm)  {  	struct vgic_dist *dist = &kvm->arch.vgic; @@ -52,7 +51,6 @@ bool vgic_has_its(struct kvm *kvm)  	return dist->has_its;  } -#endif  static unsigned long vgic_mmio_read_v3_misc(struct kvm_vcpu *vcpu,  					    gpa_t addr, unsigned int len) diff --git a/virt/kvm/arm/vgic/vgic.h b/virt/kvm/arm/vgic/vgic.h index 9d9e014765a2..859f65c6e056 100644 --- a/virt/kvm/arm/vgic/vgic.h +++ b/virt/kvm/arm/vgic/vgic.h @@ -84,37 +84,11 @@ int vgic_v3_probe(const struct gic_kvm_info *info);  int vgic_v3_map_resources(struct kvm *kvm);  int vgic_register_redist_iodevs(struct kvm *kvm, gpa_t dist_base_address); -#ifdef CONFIG_KVM_ARM_VGIC_V3_ITS  int vgic_register_its_iodevs(struct kvm *kvm);  bool vgic_has_its(struct kvm *kvm);  int kvm_vgic_register_its_device(void);  void vgic_enable_lpis(struct kvm_vcpu *vcpu);  int vgic_its_inject_msi(struct kvm *kvm, struct kvm_msi *msi); -#else -static inline int vgic_register_its_iodevs(struct kvm *kvm) -{ -	return -ENODEV; -} - -static inline bool vgic_has_its(struct kvm *kvm) -{ -	return false; -} - -static inline int kvm_vgic_register_its_device(void) -{ -	return -ENODEV; -} - -static inline void vgic_enable_lpis(struct kvm_vcpu *vcpu) -{ -} - -static inline int vgic_its_inject_msi(struct kvm *kvm, struct kvm_msi *msi) -{ -	return -ENODEV; -} -#endif  int kvm_register_vgic_device(unsigned long type);  int vgic_lazy_init(struct kvm *kvm);  | 
