Skip to content

Commit

Permalink
Merge branch 'arm-privcmd-for-3.8' of git://xenbits.xen.org/people/ia…
Browse files Browse the repository at this point in the history
…nc/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: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
  • Loading branch information
Konrad Rzeszutek Wilk committed Nov 30, 2012
2 parents a7be94a + f832da0 commit 6a7ed40
Show file tree
Hide file tree
Showing 11 changed files with 246 additions and 33 deletions.
1 change: 1 addition & 0 deletions arch/arm/include/asm/xen/interface.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
123 changes: 102 additions & 21 deletions arch/arm/xen/enlighten.c
Original file line number Diff line number Diff line change
Expand Up @@ -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>
Expand All @@ -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);
Expand All @@ -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);
Expand All @@ -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.
Expand Down Expand Up @@ -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 change: 1 addition & 0 deletions arch/x86/include/asm/xen/interface.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
1 change: 1 addition & 0 deletions arch/x86/xen/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
17 changes: 15 additions & 2 deletions arch/x86/xen/mmu.c
Original file line number Diff line number Diff line change
Expand Up @@ -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];
Expand Down Expand Up @@ -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);
3 changes: 3 additions & 0 deletions drivers/xen/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -206,4 +206,7 @@ config XEN_MCE_LOG
Allow kernel fetching MCE error from Xen platform and
converting it into Linux mcelog format for mcelog tools

config XEN_HAVE_PVMMU
bool

endmenu
4 changes: 2 additions & 2 deletions drivers/xen/Makefile
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
ifneq ($(CONFIG_ARM),y)
obj-y += manage.o balloon.o
obj-y += manage.o
obj-$(CONFIG_HOTPLUG_CPU) += cpu_hotplug.o
endif
obj-y += grant-table.o features.o events.o
obj-y += grant-table.o features.o events.o balloon.o
obj-y += xenbus/

nostackp := $(call cc-option, -fno-stack-protector)
Expand Down
5 changes: 4 additions & 1 deletion drivers/xen/balloon.c
Original file line number Diff line number Diff line change
Expand Up @@ -359,6 +359,7 @@ static enum bp_state increase_reservation(unsigned long nr_pages)

set_phys_to_machine(pfn, frame_list[i]);

#ifdef CONFIG_XEN_HAVE_PVMMU
/* Link back into the page tables if not highmem. */
if (xen_pv_domain() && !PageHighMem(page)) {
int ret;
Expand All @@ -368,6 +369,7 @@ static enum bp_state increase_reservation(unsigned long nr_pages)
0);
BUG_ON(ret);
}
#endif

/* Relinquish the page back to the allocator. */
ClearPageReserved(page);
Expand Down Expand Up @@ -416,13 +418,14 @@ static enum bp_state decrease_reservation(unsigned long nr_pages, gfp_t gfp)

scrub_page(page);

#ifdef CONFIG_XEN_HAVE_PVMMU
if (xen_pv_domain() && !PageHighMem(page)) {
ret = HYPERVISOR_update_va_mapping(
(unsigned long)__va(pfn << PAGE_SHIFT),
__pte_ma(0), 0);
BUG_ON(ret);
}

#endif
}

/* Ensure that ballooned highmem pages don't have kmaps. */
Expand Down
Loading

0 comments on commit 6a7ed40

Please sign in to comment.