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

Commit 069915b9 authored by Linus Torvalds's avatar Linus Torvalds
Browse files

Merge tag 'stable/for-linus-3.5-rc2-tag' of...

Merge tag 'stable/for-linus-3.5-rc2-tag' of git://git.kernel.org/pub/scm/linux/kernel/git/konrad/xen

Pull five Xen bug-fixes from Konrad Rzeszutek Wilk:

 - When booting as PVHVM we would try to use PV console - but would not validate
   the parameters causing us to crash during restore b/c we re-use the wrong event
   channel.
 - When booting on machines with SR-IOV PCI bridge we didn't check for the bridge
   and tried to use it.
 - Under AMD machines would advertise the APERFMPERF resulting in needless amount
   of MSRs from the guest.
 - A global value (xen_released_pages) was not subtracted at bootup when pages
   were added back in. This resulted in the balloon worker having the wrong
   account of how many pages were truly released.
 - Fix dead-lock when xen-blkfront is run in the same domain as xen-blkback.

* tag 'stable/for-linus-3.5-rc2-tag' of git://git.kernel.org/pub/scm/linux/kernel/git/konrad/xen:
  xen: mark local pages as FOREIGN in the m2p_override
  xen/setup: filter APERFMPERF cpuid feature out
  xen/balloon: Subtract from xen_released_pages the count that is populated.
  xen/pci: Check for PCI bridge before using it.
  xen/events: Add WARN_ON when quick lookup found invalid type.
  xen/hvc: Check HVM_PARAM_CONSOLE_[EVTCHN|PFN] for correctness.
  xen/hvc: Fix error cases around HVM_PARAM_CONSOLE_PFN
  xen/hvc: Collapse error logic.
parents 41c8c535 b9e0d95c
Loading
Loading
Loading
Loading
+8 −0
Original line number Diff line number Diff line
@@ -209,6 +209,9 @@ static void __init xen_banner(void)
	       xen_feature(XENFEAT_mmu_pt_update_preserve_ad) ? " (preserve-AD)" : "");
}

#define CPUID_THERM_POWER_LEAF 6
#define APERFMPERF_PRESENT 0

static __read_mostly unsigned int cpuid_leaf1_edx_mask = ~0;
static __read_mostly unsigned int cpuid_leaf1_ecx_mask = ~0;

@@ -242,6 +245,11 @@ static void xen_cpuid(unsigned int *ax, unsigned int *bx,
		*dx = cpuid_leaf5_edx_val;
		return;

	case CPUID_THERM_POWER_LEAF:
		/* Disabling APERFMPERF for kernel usage */
		maskecx = ~(1 << APERFMPERF_PRESENT);
		break;

	case 0xb:
		/* Suppress extended topology stuff */
		maskebx = 0;
+36 −0
Original line number Diff line number Diff line
@@ -706,6 +706,7 @@ int m2p_add_override(unsigned long mfn, struct page *page,
	unsigned long uninitialized_var(address);
	unsigned level;
	pte_t *ptep = NULL;
	int ret = 0;

	pfn = page_to_pfn(page);
	if (!PageHighMem(page)) {
@@ -741,6 +742,24 @@ int m2p_add_override(unsigned long mfn, struct page *page,
	list_add(&page->lru,  &m2p_overrides[mfn_hash(mfn)]);
	spin_unlock_irqrestore(&m2p_override_lock, flags);

	/* p2m(m2p(mfn)) == mfn: the mfn is already present somewhere in
	 * this domain. Set the FOREIGN_FRAME_BIT in the p2m for the other
	 * pfn so that the following mfn_to_pfn(mfn) calls will return the
	 * pfn from the m2p_override (the backend pfn) instead.
	 * We need to do this because the pages shared by the frontend
	 * (xen-blkfront) can be already locked (lock_page, called by
	 * do_read_cache_page); when the userspace backend tries to use them
	 * with direct_IO, mfn_to_pfn returns the pfn of the frontend, so
	 * do_blockdev_direct_IO is going to try to lock the same pages
	 * again resulting in a deadlock.
	 * As a side effect get_user_pages_fast might not be safe on the
	 * frontend pages while they are being shared with the backend,
	 * because mfn_to_pfn (that ends up being called by GUPF) will
	 * return the backend pfn rather than the frontend pfn. */
	ret = __get_user(pfn, &machine_to_phys_mapping[mfn]);
	if (ret == 0 && get_phys_to_machine(pfn) == mfn)
		set_phys_to_machine(pfn, FOREIGN_FRAME(mfn));

	return 0;
}
EXPORT_SYMBOL_GPL(m2p_add_override);
@@ -752,6 +771,7 @@ int m2p_remove_override(struct page *page, bool clear_pte)
	unsigned long uninitialized_var(address);
	unsigned level;
	pte_t *ptep = NULL;
	int ret = 0;

	pfn = page_to_pfn(page);
	mfn = get_phys_to_machine(pfn);
@@ -821,6 +841,22 @@ int m2p_remove_override(struct page *page, bool clear_pte)
	} else
		set_phys_to_machine(pfn, page->index);

	/* p2m(m2p(mfn)) == FOREIGN_FRAME(mfn): the mfn is already present
	 * somewhere in this domain, even before being added to the
	 * m2p_override (see comment above in m2p_add_override).
	 * If there are no other entries in the m2p_override corresponding
	 * to this mfn, then remove the FOREIGN_FRAME_BIT from the p2m for
	 * the original pfn (the one shared by the frontend): the backend
	 * cannot do any IO on this page anymore because it has been
	 * unshared. Removing the FOREIGN_FRAME_BIT from the p2m entry of
	 * the original pfn causes mfn_to_pfn(mfn) to return the frontend
	 * pfn again. */
	mfn &= ~FOREIGN_FRAME_BIT;
	ret = __get_user(pfn, &machine_to_phys_mapping[mfn]);
	if (ret == 0 && get_phys_to_machine(pfn) == FOREIGN_FRAME(mfn) &&
			m2p_find_override(mfn) == NULL)
		set_phys_to_machine(pfn, mfn);

	return 0;
}
EXPORT_SYMBOL_GPL(m2p_remove_override);
+2 −1
Original line number Diff line number Diff line
@@ -371,7 +371,8 @@ char * __init xen_memory_setup(void)
	populated = xen_populate_chunk(map, memmap.nr_entries,
			max_pfn, &last_pfn, xen_released_pages);

	extra_pages += (xen_released_pages - populated);
	xen_released_pages -= populated;
	extra_pages += xen_released_pages;

	if (last_pfn > max_pfn) {
		max_pfn = min(MAX_DOMAIN_PAGES, last_pfn);
+17 −14
Original line number Diff line number Diff line
@@ -214,24 +214,24 @@ static int xen_hvm_console_init(void)
	/* already configured */
	if (info->intf != NULL)
		return 0;

	/*
	 * If the toolstack (or the hypervisor) hasn't set these values, the
	 * default value is 0. Even though mfn = 0 and evtchn = 0 are
	 * theoretically correct values, in practice they never are and they
	 * mean that a legacy toolstack hasn't initialized the pv console correctly.
	 */
	r = hvm_get_parameter(HVM_PARAM_CONSOLE_EVTCHN, &v);
	if (r < 0) {
		kfree(info);
		return -ENODEV;
	}
	if (r < 0 || v == 0)
		goto err;
	info->evtchn = v;
	hvm_get_parameter(HVM_PARAM_CONSOLE_PFN, &v);
	if (r < 0) {
		kfree(info);
		return -ENODEV;
	}
	v = 0;
	r = hvm_get_parameter(HVM_PARAM_CONSOLE_PFN, &v);
	if (r < 0 || v == 0)
		goto err;
	mfn = v;
	info->intf = ioremap(mfn << PAGE_SHIFT, PAGE_SIZE);
	if (info->intf == NULL) {
		kfree(info);
		return -ENODEV;
	}
	if (info->intf == NULL)
		goto err;
	info->vtermno = HVC_COOKIE;

	spin_lock(&xencons_lock);
@@ -239,6 +239,9 @@ static int xen_hvm_console_init(void)
	spin_unlock(&xencons_lock);

	return 0;
err:
	kfree(info);
	return -ENODEV;
}

static int xen_pv_console_init(void)
+9 −0
Original line number Diff line number Diff line
@@ -827,6 +827,9 @@ int bind_evtchn_to_irq(unsigned int evtchn)
					      handle_edge_irq, "event");

		xen_irq_info_evtchn_init(irq, evtchn);
	} else {
		struct irq_info *info = info_for_irq(irq);
		WARN_ON(info == NULL || info->type != IRQT_EVTCHN);
	}

out:
@@ -862,6 +865,9 @@ static int bind_ipi_to_irq(unsigned int ipi, unsigned int cpu)
		xen_irq_info_ipi_init(cpu, irq, evtchn, ipi);

		bind_evtchn_to_cpu(evtchn, cpu);
	} else {
		struct irq_info *info = info_for_irq(irq);
		WARN_ON(info == NULL || info->type != IRQT_IPI);
	}

 out:
@@ -939,6 +945,9 @@ int bind_virq_to_irq(unsigned int virq, unsigned int cpu)
		xen_irq_info_virq_init(cpu, irq, evtchn, virq);

		bind_evtchn_to_cpu(evtchn, cpu);
	} else {
		struct irq_info *info = info_for_irq(irq);
		WARN_ON(info == NULL || info->type != IRQT_VIRQ);
	}

out:
Loading