KVM/ARM updates for 4.10:
- Support for the GICv3 ITS on 32bit platforms - A handful of timer and GIC emulation fixes - A PMU architecture fix -----BEGIN PGP SIGNATURE----- Version: GnuPG v1 iQIcBAABAgAGBQJYStI0AAoJECPQ0LrRPXpD6kcP/0J+fynLo/uhe3VAP7pZ0fH5 dFmvcgZaHQ6wpWgkHYbyuAkZ2tiQfthylErjt9Xay2qf3f0BZScsNKSkTOmVTOJH NO+4yo7YDIbRbQO3h+QX2YB3uBqdZvn6eRLCDWNLwSa/GkNmLGvhcorQer0GduCl qnsRRrNIewzSYI+U3821jVUjLgXuBuGoFt0yT/197ZBRIrowNJ4vqAvaqVaLQ4jt aOd+aCPKCaatkeewEo6Es4lX86JOytpxtVfNpRe6/gSr1mK2fHAfycQ5Txkl7oTX T/vsYUusYDSJbiz7PUMFBfNYvVijBY8QCtm6yJZHQNg6q25r3pjn//3BiuSDf4Dz o0DDMoFPjEi23myfGI91oeL9Svbtk06ERGyN7MY2vMNtORrwhmgNiSfIsqI9V0d8 Slru3REMZg+ZbY6rgyJZa9/09vlwKfqZpkwJlfQkJO9tsXn4WwwdyvwIXmaH9p5X mqnjgbIMRipBs5Teedb++pC5XQcbC8ed2KMEBXlgORDm6fC0Pz/q623tVRYhIm4B 4YKHI1A8I8XaYd0VJkZOns2Uq7/Uwc2j5wGWRIa0IwB6LXlzNw4kbD+omj0Mmo0V Fxio610jyTfrPidx/XzO0zsEzVW794Si8S4F1nFShdkk1NuzClVnQzce5TA8K3Zu cCUKISR4oi5IWVcimDQt =zxXl -----END PGP SIGNATURE----- Merge tag 'kvm-arm-for-4.10' of git://git.kernel.org/pub/scm/linux/kernel/git/kvmarm/kvmarm into HEAD KVM/ARM updates for 4.10: - Support for the GICv3 ITS on 32bit platforms - A handful of timer and GIC emulation fixes - A PMU architecture fix
This commit is contained in:
Коммит
f673b5b2a6
|
@ -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
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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()();
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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);
|
||||
|
|
Загрузка…
Ссылка в новой задаче