Merge branch 'x86/cpufeature' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip into kvm/next
Topic branch for AVX512_4VNNIW and AVX512_4FMAPS support in KVM.
此提交包含在:
@@ -453,17 +453,33 @@ struct vgic_io_device *kvm_to_vgic_iodev(const struct kvm_io_device *dev)
|
||||
return container_of(dev, struct vgic_io_device, dev);
|
||||
}
|
||||
|
||||
static bool check_region(const struct vgic_register_region *region,
|
||||
static bool check_region(const struct kvm *kvm,
|
||||
const struct vgic_register_region *region,
|
||||
gpa_t addr, int len)
|
||||
{
|
||||
if ((region->access_flags & VGIC_ACCESS_8bit) && len == 1)
|
||||
return true;
|
||||
if ((region->access_flags & VGIC_ACCESS_32bit) &&
|
||||
len == sizeof(u32) && !(addr & 3))
|
||||
return true;
|
||||
if ((region->access_flags & VGIC_ACCESS_64bit) &&
|
||||
len == sizeof(u64) && !(addr & 7))
|
||||
return true;
|
||||
int flags, nr_irqs = kvm->arch.vgic.nr_spis + VGIC_NR_PRIVATE_IRQS;
|
||||
|
||||
switch (len) {
|
||||
case sizeof(u8):
|
||||
flags = VGIC_ACCESS_8bit;
|
||||
break;
|
||||
case sizeof(u32):
|
||||
flags = VGIC_ACCESS_32bit;
|
||||
break;
|
||||
case sizeof(u64):
|
||||
flags = VGIC_ACCESS_64bit;
|
||||
break;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
|
||||
if ((region->access_flags & flags) && IS_ALIGNED(addr, len)) {
|
||||
if (!region->bits_per_irq)
|
||||
return true;
|
||||
|
||||
/* Do we access a non-allocated IRQ? */
|
||||
return VGIC_ADDR_TO_INTID(addr, region->bits_per_irq) < nr_irqs;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
@@ -477,7 +493,7 @@ static int dispatch_mmio_read(struct kvm_vcpu *vcpu, struct kvm_io_device *dev,
|
||||
|
||||
region = vgic_find_mmio_region(iodev->regions, iodev->nr_regions,
|
||||
addr - iodev->base_addr);
|
||||
if (!region || !check_region(region, addr, len)) {
|
||||
if (!region || !check_region(vcpu->kvm, region, addr, len)) {
|
||||
memset(val, 0, len);
|
||||
return 0;
|
||||
}
|
||||
@@ -510,10 +526,7 @@ static int dispatch_mmio_write(struct kvm_vcpu *vcpu, struct kvm_io_device *dev,
|
||||
|
||||
region = vgic_find_mmio_region(iodev->regions, iodev->nr_regions,
|
||||
addr - iodev->base_addr);
|
||||
if (!region)
|
||||
return 0;
|
||||
|
||||
if (!check_region(region, addr, len))
|
||||
if (!region || !check_region(vcpu->kvm, region, addr, len))
|
||||
return 0;
|
||||
|
||||
switch (iodev->iodev_type) {
|
||||
|
@@ -50,15 +50,15 @@ extern struct kvm_io_device_ops kvm_io_gic_ops;
|
||||
#define VGIC_ADDR_IRQ_MASK(bits) (((bits) * 1024 / 8) - 1)
|
||||
|
||||
/*
|
||||
* (addr & mask) gives us the byte offset for the INT ID, so we want to
|
||||
* divide this with 'bytes per irq' to get the INT ID, which is given
|
||||
* by '(bits) / 8'. But we do this with fixed-point-arithmetic and
|
||||
* take advantage of the fact that division by a fraction equals
|
||||
* multiplication with the inverted fraction, and scale up both the
|
||||
* numerator and denominator with 8 to support at most 64 bits per IRQ:
|
||||
* (addr & mask) gives us the _byte_ offset for the INT ID.
|
||||
* We multiply this by 8 the get the _bit_ offset, then divide this by
|
||||
* the number of bits to learn the actual INT ID.
|
||||
* But instead of a division (which requires a "long long div" implementation),
|
||||
* we shift by the binary logarithm of <bits>.
|
||||
* This assumes that <bits> is a power of two.
|
||||
*/
|
||||
#define VGIC_ADDR_TO_INTID(addr, bits) (((addr) & VGIC_ADDR_IRQ_MASK(bits)) * \
|
||||
64 / (bits) / 8)
|
||||
8 >> ilog2(bits))
|
||||
|
||||
/*
|
||||
* Some VGIC registers store per-IRQ information, with a different number
|
||||
|
@@ -273,6 +273,18 @@ retry:
|
||||
* no more work for us to do.
|
||||
*/
|
||||
spin_unlock(&irq->irq_lock);
|
||||
|
||||
/*
|
||||
* We have to kick the VCPU here, because we could be
|
||||
* queueing an edge-triggered interrupt for which we
|
||||
* get no EOI maintenance interrupt. In that case,
|
||||
* while the IRQ is already on the VCPU's AP list, the
|
||||
* VCPU could have EOI'ed the original interrupt and
|
||||
* won't see this one until it exits for some other
|
||||
* reason.
|
||||
*/
|
||||
if (vcpu)
|
||||
kvm_vcpu_kick(vcpu);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@@ -1346,21 +1346,19 @@ unsigned long kvm_vcpu_gfn_to_hva_prot(struct kvm_vcpu *vcpu, gfn_t gfn, bool *w
|
||||
static int get_user_page_nowait(unsigned long start, int write,
|
||||
struct page **page)
|
||||
{
|
||||
int flags = FOLL_TOUCH | FOLL_NOWAIT | FOLL_HWPOISON | FOLL_GET;
|
||||
int flags = FOLL_NOWAIT | FOLL_HWPOISON;
|
||||
|
||||
if (write)
|
||||
flags |= FOLL_WRITE;
|
||||
|
||||
return __get_user_pages(current, current->mm, start, 1, flags, page,
|
||||
NULL, NULL);
|
||||
return get_user_pages(start, 1, flags, page, NULL);
|
||||
}
|
||||
|
||||
static inline int check_user_page_hwpoison(unsigned long addr)
|
||||
{
|
||||
int rc, flags = FOLL_TOUCH | FOLL_HWPOISON | FOLL_WRITE;
|
||||
int rc, flags = FOLL_HWPOISON | FOLL_WRITE;
|
||||
|
||||
rc = __get_user_pages(current, current->mm, addr, 1,
|
||||
flags, NULL, NULL, NULL);
|
||||
rc = get_user_pages(addr, 1, flags, NULL, NULL);
|
||||
return rc == -EHWPOISON;
|
||||
}
|
||||
|
||||
|
新增問題並參考
封鎖使用者