Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit e7e6d2a4 authored by Linus Torvalds's avatar Linus Torvalds
Browse files
Pull KVM fixes from Paolo Bonzini:
 - Fix for a Haswell regression in nested virtualization, introduced
   during the merge window.
 - A fix from Oleg to async page faults.
 - A bunch of small ARM changes.
 - A trivial patch to use the new MSI-X API introduced during the merge
   window.

* tag 'for-linus' of git://git.kernel.org/pub/scm/virt/kvm/kvm:
  KVM: ARM: vgic: Fix the overlap check action about setting the GICD & GICC base address.
  KVM: arm/arm64: vgic: fix GICD_ICFGR register accesses
  KVM: async_pf: mm->mm_users can not pin apf->mm
  KVM: ARM: vgic: Fix sgi dispatch problem
  MAINTAINERS: co-maintainance of KVM/{arm,arm64}
  arm: KVM: fix possible misalignment of PGDs and bounce page
  KVM: x86: Check for host supported fields in shadow vmcs
  kvm: Use pci_enable_msix_exact() instead of pci_enable_msix()
  ARM: KVM: disable KVM in Kconfig on big-endian systems
parents b28e4f08 a5a5aef4
Loading
Loading
Loading
Loading
+5 −0
Original line number Diff line number Diff line
@@ -5114,14 +5114,19 @@ F: drivers/s390/kvm/

KERNEL VIRTUAL MACHINE (KVM) FOR ARM
M:	Christoffer Dall <christoffer.dall@linaro.org>
M:	Marc Zyngier <marc.zyngier@arm.com>
L:	linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
L:	kvmarm@lists.cs.columbia.edu
W:	http://systems.cs.columbia.edu/projects/kvm-arm
S:	Supported
F:	arch/arm/include/uapi/asm/kvm*
F:	arch/arm/include/asm/kvm*
F:	arch/arm/kvm/
F:	virt/kvm/arm/
F:	include/kvm/arm_*

KERNEL VIRTUAL MACHINE FOR ARM64 (KVM/arm64)
M:	Christoffer Dall <christoffer.dall@linaro.org>
M:	Marc Zyngier <marc.zyngier@arm.com>
L:	linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
L:	kvmarm@lists.cs.columbia.edu
+1 −1
Original line number Diff line number Diff line
@@ -23,7 +23,7 @@ config KVM
	select HAVE_KVM_CPU_RELAX_INTERCEPT
	select KVM_MMIO
	select KVM_ARM_HOST
	depends on ARM_VIRT_EXT && ARM_LPAE
	depends on ARM_VIRT_EXT && ARM_LPAE && !CPU_BIG_ENDIAN
	---help---
	  Support hosting virtualized guest machines. You will also
	  need to select one or more of the processor modules below.
+9 −6
Original line number Diff line number Diff line
@@ -42,6 +42,8 @@ static unsigned long hyp_idmap_start;
static unsigned long hyp_idmap_end;
static phys_addr_t hyp_idmap_vector;

#define pgd_order get_order(PTRS_PER_PGD * sizeof(pgd_t))

#define kvm_pmd_huge(_x)	(pmd_huge(_x) || pmd_trans_huge(_x))

static void kvm_tlb_flush_vmid_ipa(struct kvm *kvm, phys_addr_t ipa)
@@ -293,14 +295,14 @@ void free_boot_hyp_pgd(void)
	if (boot_hyp_pgd) {
		unmap_range(NULL, boot_hyp_pgd, hyp_idmap_start, PAGE_SIZE);
		unmap_range(NULL, boot_hyp_pgd, TRAMPOLINE_VA, PAGE_SIZE);
		kfree(boot_hyp_pgd);
		free_pages((unsigned long)boot_hyp_pgd, pgd_order);
		boot_hyp_pgd = NULL;
	}

	if (hyp_pgd)
		unmap_range(NULL, hyp_pgd, TRAMPOLINE_VA, PAGE_SIZE);

	kfree(init_bounce_page);
	free_page((unsigned long)init_bounce_page);
	init_bounce_page = NULL;

	mutex_unlock(&kvm_hyp_pgd_mutex);
@@ -330,7 +332,7 @@ void free_hyp_pgds(void)
		for (addr = VMALLOC_START; is_vmalloc_addr((void*)addr); addr += PGDIR_SIZE)
			unmap_range(NULL, hyp_pgd, KERN_TO_HYP(addr), PGDIR_SIZE);

		kfree(hyp_pgd);
		free_pages((unsigned long)hyp_pgd, pgd_order);
		hyp_pgd = NULL;
	}

@@ -1024,7 +1026,7 @@ int kvm_mmu_init(void)
		size_t len = __hyp_idmap_text_end - __hyp_idmap_text_start;
		phys_addr_t phys_base;

		init_bounce_page = kmalloc(PAGE_SIZE, GFP_KERNEL);
		init_bounce_page = (void *)__get_free_page(GFP_KERNEL);
		if (!init_bounce_page) {
			kvm_err("Couldn't allocate HYP init bounce page\n");
			err = -ENOMEM;
@@ -1050,8 +1052,9 @@ int kvm_mmu_init(void)
			 (unsigned long)phys_base);
	}

	hyp_pgd = kzalloc(PTRS_PER_PGD * sizeof(pgd_t), GFP_KERNEL);
	boot_hyp_pgd = kzalloc(PTRS_PER_PGD * sizeof(pgd_t), GFP_KERNEL);
	hyp_pgd = (pgd_t *)__get_free_pages(GFP_KERNEL | __GFP_ZERO, pgd_order);
	boot_hyp_pgd = (pgd_t *)__get_free_pages(GFP_KERNEL | __GFP_ZERO, pgd_order);

	if (!hyp_pgd || !boot_hyp_pgd) {
		kvm_err("Hyp mode PGD not allocated\n");
		err = -ENOMEM;
+41 −12
Original line number Diff line number Diff line
@@ -503,7 +503,7 @@ static inline struct vcpu_vmx *to_vmx(struct kvm_vcpu *vcpu)
				[number##_HIGH] = VMCS12_OFFSET(name)+4


static const unsigned long shadow_read_only_fields[] = {
static unsigned long shadow_read_only_fields[] = {
	/*
	 * We do NOT shadow fields that are modified when L0
	 * traps and emulates any vmx instruction (e.g. VMPTRLD,
@@ -526,10 +526,10 @@ static const unsigned long shadow_read_only_fields[] = {
	GUEST_LINEAR_ADDRESS,
	GUEST_PHYSICAL_ADDRESS
};
static const int max_shadow_read_only_fields =
static int max_shadow_read_only_fields =
	ARRAY_SIZE(shadow_read_only_fields);

static const unsigned long shadow_read_write_fields[] = {
static unsigned long shadow_read_write_fields[] = {
	GUEST_RIP,
	GUEST_RSP,
	GUEST_CR0,
@@ -558,7 +558,7 @@ static const unsigned long shadow_read_write_fields[] = {
	HOST_FS_SELECTOR,
	HOST_GS_SELECTOR
};
static const int max_shadow_read_write_fields =
static int max_shadow_read_write_fields =
	ARRAY_SIZE(shadow_read_write_fields);

static const unsigned short vmcs_field_to_offset_table[] = {
@@ -3009,6 +3009,41 @@ static void free_kvm_area(void)
	}
}

static void init_vmcs_shadow_fields(void)
{
	int i, j;

	/* No checks for read only fields yet */

	for (i = j = 0; i < max_shadow_read_write_fields; i++) {
		switch (shadow_read_write_fields[i]) {
		case GUEST_BNDCFGS:
			if (!vmx_mpx_supported())
				continue;
			break;
		default:
			break;
		}

		if (j < i)
			shadow_read_write_fields[j] =
				shadow_read_write_fields[i];
		j++;
	}
	max_shadow_read_write_fields = j;

	/* shadowed fields guest access without vmexit */
	for (i = 0; i < max_shadow_read_write_fields; i++) {
		clear_bit(shadow_read_write_fields[i],
			  vmx_vmwrite_bitmap);
		clear_bit(shadow_read_write_fields[i],
			  vmx_vmread_bitmap);
	}
	for (i = 0; i < max_shadow_read_only_fields; i++)
		clear_bit(shadow_read_only_fields[i],
			  vmx_vmread_bitmap);
}

static __init int alloc_kvm_area(void)
{
	int cpu;
@@ -3039,6 +3074,8 @@ static __init int hardware_setup(void)
		enable_vpid = 0;
	if (!cpu_has_vmx_shadow_vmcs())
		enable_shadow_vmcs = 0;
	if (enable_shadow_vmcs)
		init_vmcs_shadow_fields();

	if (!cpu_has_vmx_ept() ||
	    !cpu_has_vmx_ept_4levels()) {
@@ -8803,14 +8840,6 @@ static int __init vmx_init(void)

	memset(vmx_vmread_bitmap, 0xff, PAGE_SIZE);
	memset(vmx_vmwrite_bitmap, 0xff, PAGE_SIZE);
	/* shadowed read/write fields */
	for (i = 0; i < max_shadow_read_write_fields; i++) {
		clear_bit(shadow_read_write_fields[i], vmx_vmwrite_bitmap);
		clear_bit(shadow_read_write_fields[i], vmx_vmread_bitmap);
	}
	/* shadowed read only fields */
	for (i = 0; i < max_shadow_read_only_fields; i++)
		clear_bit(shadow_read_only_fields[i], vmx_vmread_bitmap);

	/*
	 * Allow direct access to the PC debug port (it is often used for I/O
+8 −7
Original line number Diff line number Diff line
@@ -548,11 +548,10 @@ static bool handle_mmio_cfg_reg(struct kvm_vcpu *vcpu,
	u32 val;
	u32 *reg;

	offset >>= 1;
	reg = vgic_bitmap_get_reg(&vcpu->kvm->arch.vgic.irq_cfg,
				  vcpu->vcpu_id, offset);
				  vcpu->vcpu_id, offset >> 1);

	if (offset & 2)
	if (offset & 4)
		val = *reg >> 16;
	else
		val = *reg & 0xffff;
@@ -561,13 +560,13 @@ static bool handle_mmio_cfg_reg(struct kvm_vcpu *vcpu,
	vgic_reg_access(mmio, &val, offset,
			ACCESS_READ_VALUE | ACCESS_WRITE_VALUE);
	if (mmio->is_write) {
		if (offset < 4) {
		if (offset < 8) {
			*reg = ~0U; /* Force PPIs/SGIs to 1 */
			return false;
		}

		val = vgic_cfg_compress(val);
		if (offset & 2) {
		if (offset & 4) {
			*reg &= 0xffff;
			*reg |= val << 16;
		} else {
@@ -916,6 +915,7 @@ static void vgic_dispatch_sgi(struct kvm_vcpu *vcpu, u32 reg)
	case 0:
		if (!target_cpus)
			return;
		break;

	case 1:
		target_cpus = ((1 << nrcpus) - 1) & ~(1 << vcpu_id) & 0xff;
@@ -1667,10 +1667,11 @@ static int vgic_ioaddr_assign(struct kvm *kvm, phys_addr_t *ioaddr,
	if (addr + size < addr)
		return -EINVAL;

	*ioaddr = addr;
	ret = vgic_ioaddr_overlap(kvm);
	if (ret)
		return ret;
	*ioaddr = addr;
		*ioaddr = VGIC_ADDR_UNDEF;

	return ret;
}

Loading