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

Commit 6a7ed405 authored by Konrad Rzeszutek Wilk's avatar Konrad Rzeszutek Wilk
Browse files

Merge branch 'arm-privcmd-for-3.8' of git://xenbits.xen.org/people/ianc/linux...

Merge branch 'arm-privcmd-for-3.8' of git://xenbits.xen.org/people/ianc/linux into stable/for-linus-3.8

* 'arm-privcmd-for-3.8' of git://xenbits.xen.org/people/ianc/linux

:
  xen: arm: implement remap interfaces needed for privcmd mappings.
  xen: correctly use xen_pfn_t in remap_domain_mfn_range.
  xen: arm: enable balloon driver
  xen: balloon: allow PVMMU interfaces to be compiled out
  xen: privcmd: support autotranslated physmap guests.
  xen: add pages parameter to xen_remap_domain_mfn_range

Signed-off-by: default avatarKonrad Rzeszutek Wilk <konrad.wilk@oracle.com>
parents a7be94ac f832da06
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -49,6 +49,7 @@ DEFINE_GUEST_HANDLE(void);
DEFINE_GUEST_HANDLE(uint64_t);
DEFINE_GUEST_HANDLE(uint32_t);
DEFINE_GUEST_HANDLE(xen_pfn_t);
DEFINE_GUEST_HANDLE(xen_ulong_t);

/* Maximum number of virtual CPUs in multi-processor guests. */
#define MAX_VIRT_CPUS 1
+102 −21
Original line number Diff line number Diff line
@@ -8,6 +8,8 @@
#include <xen/features.h>
#include <xen/platform_pci.h>
#include <xen/xenbus.h>
#include <xen/page.h>
#include <xen/xen-ops.h>
#include <asm/xen/hypervisor.h>
#include <asm/xen/hypercall.h>
#include <linux/interrupt.h>
@@ -17,6 +19,8 @@
#include <linux/of_irq.h>
#include <linux/of_address.h>

#include <linux/mm.h>

struct start_info _xen_start_info;
struct start_info *xen_start_info = &_xen_start_info;
EXPORT_SYMBOL_GPL(xen_start_info);
@@ -29,6 +33,10 @@ struct shared_info *HYPERVISOR_shared_info = (void *)&xen_dummy_shared_info;

DEFINE_PER_CPU(struct vcpu_info *, xen_vcpu);

/* These are unused until we support booting "pre-ballooned" */
unsigned long xen_released_pages;
struct xen_memory_region xen_extra_mem[XEN_EXTRA_MEM_MAX_REGIONS] __initdata;

/* TODO: to be removed */
__read_mostly int xen_have_vector_callback;
EXPORT_SYMBOL_GPL(xen_have_vector_callback);
@@ -38,15 +46,106 @@ EXPORT_SYMBOL_GPL(xen_platform_pci_unplug);

static __read_mostly int xen_events_irq = -1;

/* map fgmfn of domid to lpfn in the current domain */
static int map_foreign_page(unsigned long lpfn, unsigned long fgmfn,
			    unsigned int domid)
{
	int rc;
	struct xen_add_to_physmap_range xatp = {
		.domid = DOMID_SELF,
		.foreign_domid = domid,
		.size = 1,
		.space = XENMAPSPACE_gmfn_foreign,
	};
	xen_ulong_t idx = fgmfn;
	xen_pfn_t gpfn = lpfn;

	set_xen_guest_handle(xatp.idxs, &idx);
	set_xen_guest_handle(xatp.gpfns, &gpfn);

	rc = HYPERVISOR_memory_op(XENMEM_add_to_physmap_range, &xatp);
	if (rc) {
		pr_warn("Failed to map pfn to mfn rc:%d pfn:%lx mfn:%lx\n",
			rc, lpfn, fgmfn);
		return 1;
	}
	return 0;
}

struct remap_data {
	xen_pfn_t fgmfn; /* foreign domain's gmfn */
	pgprot_t prot;
	domid_t  domid;
	struct vm_area_struct *vma;
	int index;
	struct page **pages;
	struct xen_remap_mfn_info *info;
};

static int remap_pte_fn(pte_t *ptep, pgtable_t token, unsigned long addr,
			void *data)
{
	struct remap_data *info = data;
	struct page *page = info->pages[info->index++];
	unsigned long pfn = page_to_pfn(page);
	pte_t pte = pfn_pte(pfn, info->prot);

	if (map_foreign_page(pfn, info->fgmfn, info->domid))
		return -EFAULT;
	set_pte_at(info->vma->vm_mm, addr, ptep, pte);

	return 0;
}

int xen_remap_domain_mfn_range(struct vm_area_struct *vma,
			       unsigned long addr,
			       unsigned long mfn, int nr,
			       pgprot_t prot, unsigned domid)
			       xen_pfn_t mfn, int nr,
			       pgprot_t prot, unsigned domid,
			       struct page **pages)
{
	return -ENOSYS;
	int err;
	struct remap_data data;

	/* TBD: Batching, current sole caller only does page at a time */
	if (nr > 1)
		return -EINVAL;

	data.fgmfn = mfn;
	data.prot = prot;
	data.domid = domid;
	data.vma = vma;
	data.index = 0;
	data.pages = pages;
	err = apply_to_page_range(vma->vm_mm, addr, nr << PAGE_SHIFT,
				  remap_pte_fn, &data);
	return err;
}
EXPORT_SYMBOL_GPL(xen_remap_domain_mfn_range);

int xen_unmap_domain_mfn_range(struct vm_area_struct *vma,
			       int nr, struct page **pages)
{
	int i;

	for (i = 0; i < nr; i++) {
		struct xen_remove_from_physmap xrp;
		unsigned long rc, pfn;

		pfn = page_to_pfn(pages[i]);

		xrp.domid = DOMID_SELF;
		xrp.gpfn = pfn;
		rc = HYPERVISOR_memory_op(XENMEM_remove_from_physmap, &xrp);
		if (rc) {
			pr_warn("Failed to unmap pfn:%lx rc:%ld\n",
				pfn, rc);
			return rc;
		}
	}
	return 0;
}
EXPORT_SYMBOL_GPL(xen_unmap_domain_mfn_range);

/*
 * see Documentation/devicetree/bindings/arm/xen.txt for the
 * documentation of the Xen Device Tree format.
@@ -148,21 +247,3 @@ static int __init xen_init_events(void)
	return 0;
}
postcore_initcall(xen_init_events);

/* XXX: only until balloon is properly working */
int alloc_xenballooned_pages(int nr_pages, struct page **pages, bool highmem)
{
	*pages = alloc_pages(highmem ? GFP_HIGHUSER : GFP_KERNEL,
			get_order(nr_pages));
	if (*pages == NULL)
		return -ENOMEM;
	return 0;
}
EXPORT_SYMBOL_GPL(alloc_xenballooned_pages);

void free_xenballooned_pages(int nr_pages, struct page **pages)
{
	kfree(*pages);
	*pages = NULL;
}
EXPORT_SYMBOL_GPL(free_xenballooned_pages);
+1 −0
Original line number Diff line number Diff line
@@ -63,6 +63,7 @@ DEFINE_GUEST_HANDLE(void);
DEFINE_GUEST_HANDLE(uint64_t);
DEFINE_GUEST_HANDLE(uint32_t);
DEFINE_GUEST_HANDLE(xen_pfn_t);
DEFINE_GUEST_HANDLE(xen_ulong_t);
#endif

#ifndef HYPERVISOR_VIRT_START
+1 −0
Original line number Diff line number Diff line
@@ -6,6 +6,7 @@ config XEN
	bool "Xen guest support"
	select PARAVIRT
	select PARAVIRT_CLOCK
	select XEN_HAVE_PVMMU
	depends on X86_64 || (X86_32 && X86_PAE && !X86_VISWS)
	depends on X86_CMPXCHG && X86_TSC
	help
+15 −2
Original line number Diff line number Diff line
@@ -2478,8 +2478,10 @@ static int remap_area_mfn_pte_fn(pte_t *ptep, pgtable_t token,

int xen_remap_domain_mfn_range(struct vm_area_struct *vma,
			       unsigned long addr,
			       unsigned long mfn, int nr,
			       pgprot_t prot, unsigned domid)
			       xen_pfn_t mfn, int nr,
			       pgprot_t prot, unsigned domid,
			       struct page **pages)

{
	struct remap_data rmd;
	struct mmu_update mmu_update[REMAP_BATCH_SIZE];
@@ -2523,3 +2525,14 @@ int xen_remap_domain_mfn_range(struct vm_area_struct *vma,
	return err;
}
EXPORT_SYMBOL_GPL(xen_remap_domain_mfn_range);

/* Returns: 0 success */
int xen_unmap_domain_mfn_range(struct vm_area_struct *vma,
			       int numpgs, struct page **pages)
{
	if (!pages || !xen_feature(XENFEAT_auto_translated_physmap))
		return 0;

	return -EINVAL;
}
EXPORT_SYMBOL_GPL(xen_unmap_domain_mfn_range);
Loading