This series is much reduced after rebasing onto V2 of the X86 PVH
patches, thanks Mukesh.
The baseline is v3.7-rc1 + "xen: build fixes and interface
tweaks" (posted this morning) and the PVH V2 patches from Mukesh.
With this series I can build a guest on Xen ARM.
The final patch requires that XENMEM_add_to_physmap_range be implemented
for x86 on the hypervisor side. For inspiration the ARM version can be
found at <[email protected]>
(and will likely be in xen-unstable soon).
Ian.
The code is no in a state where can just enable it.
Drop the *_xenballloned_pages duplicates since these are now supplied
by the balloon code.
Signed-off-by: Ian Campbell <[email protected]>
---
arch/arm/xen/enlighten.c | 23 +++++------------------
drivers/xen/Makefile | 4 ++--
2 files changed, 7 insertions(+), 20 deletions(-)
diff --git a/arch/arm/xen/enlighten.c b/arch/arm/xen/enlighten.c
index 59bcb96..ba5cc13 100644
--- a/arch/arm/xen/enlighten.c
+++ b/arch/arm/xen/enlighten.c
@@ -8,6 +8,7 @@
#include <xen/features.h>
#include <xen/platform_pci.h>
#include <xen/xenbus.h>
+#include <xen/page.h>
#include <asm/xen/hypervisor.h>
#include <asm/xen/hypercall.h>
#include <linux/interrupt.h>
@@ -29,6 +30,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);
@@ -148,21 +153,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);
diff --git a/drivers/xen/Makefile b/drivers/xen/Makefile
index 0e863703..909bb56 100644
--- a/drivers/xen/Makefile
+++ b/drivers/xen/Makefile
@@ -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)
--
1.7.2.5
The ARM platform has no concept of PVMMU and therefor no
HYPERVISOR_update_va_mapping et al. Allow this code to be compiled out
when not required.
In some similar situations (e.g. P2M) we have defined dummy functions
to avoid this, however I think we can/should draw the line at dummying
out actual hypercalls.
Signed-off-by: Ian Campbell <[email protected]>
---
arch/x86/xen/Kconfig | 1 +
drivers/xen/Kconfig | 3 +++
drivers/xen/balloon.c | 4 ++++
3 files changed, 8 insertions(+), 0 deletions(-)
diff --git a/arch/x86/xen/Kconfig b/arch/x86/xen/Kconfig
index 9323b8c..6d101a1 100644
--- a/arch/x86/xen/Kconfig
+++ b/arch/x86/xen/Kconfig
@@ -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
diff --git a/drivers/xen/Kconfig b/drivers/xen/Kconfig
index d4dffcd..9c00652 100644
--- a/drivers/xen/Kconfig
+++ b/drivers/xen/Kconfig
@@ -204,4 +204,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
diff --git a/drivers/xen/balloon.c b/drivers/xen/balloon.c
index db3aa34..92449a0 100644
--- a/drivers/xen/balloon.c
+++ b/drivers/xen/balloon.c
@@ -360,6 +360,7 @@ static enum bp_state increase_reservation(unsigned long nr_pages)
if (!xen_feature(XENFEAT_auto_translated_physmap))
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) &&
!xen_feature(XENFEAT_auto_translated_physmap)) {
@@ -371,6 +372,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);
@@ -419,6 +421,7 @@ 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)) {
if (!xen_feature(XENFEAT_auto_translated_physmap)) {
ret = HYPERVISOR_update_va_mapping(
@@ -427,6 +430,7 @@ static enum bp_state decrease_reservation(unsigned long nr_pages, gfp_t gfp)
BUG_ON(ret);
}
}
+#endif
}
/* Ensure that ballooned highmem pages don't have kmaps. */
--
1.7.2.5
Squeezing the necessary fields into the existing XENMEM_add_to_physmap
interface was proving to be a bit tricky so we have decided to go with
a new interface upstream (the XENMAPSPACE_gmfn_foreign interface using
XENMEM_add_to_physmap was never committed anywhere). This interface
also allows for batching which was impossible to support at the same
time as foreign mfns in the old interface.
This reverts the relevant parts of "PVH: basic and header changes,
elfnote changes, ..." and followups and trivially converts
pvh_add_to_xen_p2m over.
Signed-off-by: Ian Campbell <[email protected]>
---
arch/x86/xen/mmu.c | 18 ++++++++++++------
include/xen/interface/memory.h | 24 +++++++++++-------------
2 files changed, 23 insertions(+), 19 deletions(-)
diff --git a/arch/x86/xen/mmu.c b/arch/x86/xen/mmu.c
index d779e96..e7edcdd 100644
--- a/arch/x86/xen/mmu.c
+++ b/arch/x86/xen/mmu.c
@@ -2506,13 +2506,19 @@ static int pvh_add_to_xen_p2m(unsigned long lpfn, unsigned long fgmfn,
unsigned int domid)
{
int rc;
- struct xen_add_to_physmap xatp = { .u.foreign_domid = domid };
+ 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);
- xatp.gpfn = lpfn;
- xatp.idx = fgmfn;
- xatp.domid = DOMID_SELF;
- xatp.space = XENMAPSPACE_gmfn_foreign;
- rc = HYPERVISOR_memory_op(XENMEM_add_to_physmap, &xatp);
+ rc = HYPERVISOR_memory_op(XENMEM_add_to_physmap_range, &xatp);
if (rc)
pr_warn("d0: Failed to map pfn (0x%lx) to mfn (0x%lx) rc:%d\n",
lpfn, fgmfn, rc);
diff --git a/include/xen/interface/memory.h b/include/xen/interface/memory.h
index eb2d3e5..b40a431 100644
--- a/include/xen/interface/memory.h
+++ b/include/xen/interface/memory.h
@@ -153,6 +153,14 @@ struct xen_machphys_mapping {
};
DEFINE_GUEST_HANDLE_STRUCT(xen_machphys_mapping_t);
+#define XENMAPSPACE_shared_info 0 /* shared info page */
+#define XENMAPSPACE_grant_table 1 /* grant table page */
+#define XENMAPSPACE_gmfn 2 /* GMFN */
+#define XENMAPSPACE_gmfn_range 3 /* GMFN range, XENMEM_add_to_physmap only. */
+#define XENMAPSPACE_gmfn_foreign 4 /* GMFN from another dom,
+ * XENMEM_add_to_physmap_range only.
+ */
+
/*
* Sets the GPFN at which a particular page appears in the specified guest's
* pseudophysical address space.
@@ -163,22 +171,12 @@ struct xen_add_to_physmap {
/* Which domain to change the mapping for. */
domid_t domid;
- union {
- /* Number of pages to go through for gmfn_range */
- uint16_t size;
- /* IFF XENMAPSPACE_gmfn_foreign */
- domid_t foreign_domid;
- } u;
+ /* Number of pages to go through for gmfn_range */
+ uint16_t size;
+
/* Source mapping space. */
-#define XENMAPSPACE_shared_info 0 /* shared info page */
-#define XENMAPSPACE_grant_table 1 /* grant table page */
-#define XENMAPSPACE_gmfn 2 /* GMFN */
-#define XENMAPSPACE_gmfn_range 3 /* GMFN range */
-#define XENMAPSPACE_gmfn_foreign 4 /* GMFN from another guest */
unsigned int space;
-#define XENMAPIDX_grant_table_status 0x80000000
-
/* Index into source mapping space. */
xen_ulong_t idx;
--
1.7.2.5
We use XENMEM_add_to_physmap_range which is the preferred interface
for foreign mappings.
Signed-off-by: Ian Campbell <[email protected]>
---
arch/arm/include/asm/xen/interface.h | 1 +
arch/arm/xen/enlighten.c | 100 +++++++++++++++++++++++++++++++++-
arch/x86/include/asm/xen/interface.h | 1 +
include/xen/interface/memory.h | 18 ++++++
4 files changed, 117 insertions(+), 3 deletions(-)
diff --git a/arch/arm/include/asm/xen/interface.h b/arch/arm/include/asm/xen/interface.h
index 1d6ef9c..007e6da 100644
--- a/arch/arm/include/asm/xen/interface.h
+++ b/arch/arm/include/asm/xen/interface.h
@@ -43,6 +43,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
diff --git a/arch/arm/xen/enlighten.c b/arch/arm/xen/enlighten.c
index ba5cc13..6bb4630 100644
--- a/arch/arm/xen/enlighten.c
+++ b/arch/arm/xen/enlighten.c
@@ -9,6 +9,7 @@
#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>
@@ -18,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);
@@ -43,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,
+ struct page **pages, int nr)
+{
+ 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.
diff --git a/arch/x86/include/asm/xen/interface.h b/arch/x86/include/asm/xen/interface.h
index 25669c3..6246d80 100644
--- a/arch/x86/include/asm/xen/interface.h
+++ b/arch/x86/include/asm/xen/interface.h
@@ -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
diff --git a/include/xen/interface/memory.h b/include/xen/interface/memory.h
index 91bdc2a..eb2d3e5 100644
--- a/include/xen/interface/memory.h
+++ b/include/xen/interface/memory.h
@@ -190,6 +190,24 @@ DEFINE_GUEST_HANDLE_STRUCT(xen_add_to_physmap);
/*** REMOVED ***/
/*#define XENMEM_translate_gpfn_list 8*/
+#define XENMEM_add_to_physmap_range 23
+struct xen_add_to_physmap_range {
+ /* Which domain to change the mapping for. */
+ domid_t domid;
+ uint16_t space; /* => enum phys_map_space */
+
+ /* Number of pages to go through */
+ uint16_t size;
+ domid_t foreign_domid; /* IFF gmfn_foreign */
+
+ /* Indexes into space being mapped. */
+ GUEST_HANDLE(xen_ulong_t) idxs;
+
+ /* GPFN in domid where the source mapping page should appear. */
+ GUEST_HANDLE(xen_pfn_t) gpfns;
+};
+DEFINE_GUEST_HANDLE_STRUCT(xen_add_to_physmap_range);
+
/*
* Returns the pseudo-physical memory map as it was when the domain
* was started (specified by XENMEM_set_memory_map).
--
1.7.2.5
For Xen on ARM a PFN is 64 bits so we need to use the appropriate
type here.
Signed-off-by: Ian Campbell <[email protected]>
---
arch/x86/xen/mmu.c | 2 +-
include/xen/xen-ops.h | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/arch/x86/xen/mmu.c b/arch/x86/xen/mmu.c
index 1c5812b..d779e96 100644
--- a/arch/x86/xen/mmu.c
+++ b/arch/x86/xen/mmu.c
@@ -2603,7 +2603,7 @@ 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,
+ xen_pfn_t mfn, int nr,
pgprot_t prot, unsigned domid,
struct page **pages)
diff --git a/include/xen/xen-ops.h b/include/xen/xen-ops.h
index 6a40253..dc63e80 100644
--- a/include/xen/xen-ops.h
+++ b/include/xen/xen-ops.h
@@ -26,7 +26,7 @@ void xen_destroy_contiguous_region(unsigned long vstart, unsigned int order);
struct vm_area_struct;
int xen_remap_domain_mfn_range(struct vm_area_struct *vma,
unsigned long addr,
- unsigned long mfn, int nr,
+ xen_pfn_t mfn, int nr,
pgprot_t prot, unsigned domid,
struct page **pages);
int xen_unmap_domain_mfn_range(struct vm_area_struct *vma,
--
1.7.2.5
Signed-off-by: Ian Campbell <[email protected]>
---
I beleive Mukesh has something similar in his tree. Should be trivial
to resolve I think. I'm happy to do so ontop of PVH v3 when it arrives.
---
arch/x86/xen/mmu.c | 6 ++----
drivers/xen/privcmd.c | 2 +-
include/xen/xen-ops.h | 3 ++-
3 files changed, 5 insertions(+), 6 deletions(-)
diff --git a/arch/x86/xen/mmu.c b/arch/x86/xen/mmu.c
index 018cbf0..1c5812b 100644
--- a/arch/x86/xen/mmu.c
+++ b/arch/x86/xen/mmu.c
@@ -2655,11 +2655,9 @@ out:
EXPORT_SYMBOL_GPL(xen_remap_domain_mfn_range);
/* Returns: 0 success */
-int xen_unmap_domain_mfn_range(struct vm_area_struct *vma)
+int xen_unmap_domain_mfn_range(struct vm_area_struct *vma,
+ struct page **pages, int numpgs)
{
- int numpgs = (vma->vm_end - vma->vm_start) >> PAGE_SHIFT;
- struct page **pages = vma ? vma->vm_private_data : NULL;
-
if (!pages || !xen_feature(XENFEAT_auto_translated_physmap))
return 0;
diff --git a/drivers/xen/privcmd.c b/drivers/xen/privcmd.c
index 641a420..a1ca5ab 100644
--- a/drivers/xen/privcmd.c
+++ b/drivers/xen/privcmd.c
@@ -498,7 +498,7 @@ static void privcmd_close(struct vm_area_struct *vma)
if (!pages || !numpgs || !xen_feature(XENFEAT_auto_translated_physmap))
return;
- xen_unmap_domain_mfn_range(vma);
+ xen_unmap_domain_mfn_range(vma, pages, numpgs);
while (numpgs--)
free_xenballooned_pages(1, &pages[numpgs]);
kfree(pages);
diff --git a/include/xen/xen-ops.h b/include/xen/xen-ops.h
index 8b24315..6a40253 100644
--- a/include/xen/xen-ops.h
+++ b/include/xen/xen-ops.h
@@ -29,6 +29,7 @@ int xen_remap_domain_mfn_range(struct vm_area_struct *vma,
unsigned long mfn, int nr,
pgprot_t prot, unsigned domid,
struct page **pages);
-int xen_unmap_domain_mfn_range(struct vm_area_struct *vma);
+int xen_unmap_domain_mfn_range(struct vm_area_struct *vma,
+ struct page **pages, int nr);
#endif /* INCLUDE_XEN_OPS_H */
--
1.7.2.5
On Wed, 17 Oct 2012 12:32:12 +0100
Ian Campbell <[email protected]> wrote:
> Squeezing the necessary fields into the existing XENMEM_add_to_physmap
> interface was proving to be a bit tricky so we have decided to go with
> a new interface upstream (the XENMAPSPACE_gmfn_foreign interface using
> XENMEM_add_to_physmap was never committed anywhere). This interface
> also allows for batching which was impossible to support at the same
> time as foreign mfns in the old interface.
>
> This reverts the relevant parts of "PVH: basic and header changes,
> elfnote changes, ..." and followups and trivially converts
> pvh_add_to_xen_p2m over.
Hmm... I don't see xen side implementation of XENMEM_add_to_physmap_range,
and since I've already got my patches tested and cut, I'm going to send
them now. We can apply this change easily in konrad's tree.
thanks,
mukesh
On Thu, 2012-10-18 at 00:57 +0100, Mukesh Rathor wrote:
> On Wed, 17 Oct 2012 12:32:12 +0100
> Ian Campbell <[email protected]> wrote:
>
> > Squeezing the necessary fields into the existing XENMEM_add_to_physmap
> > interface was proving to be a bit tricky so we have decided to go with
> > a new interface upstream (the XENMAPSPACE_gmfn_foreign interface using
> > XENMEM_add_to_physmap was never committed anywhere). This interface
> > also allows for batching which was impossible to support at the same
> > time as foreign mfns in the old interface.
> >
> > This reverts the relevant parts of "PVH: basic and header changes,
> > elfnote changes, ..." and followups and trivially converts
> > pvh_add_to_xen_p2m over.
>
>
> Hmm... I don't see xen side implementation of XENMEM_add_to_physmap_range,
I said in the 0/6 patch, but should have repeated here:
The final patch requires that XENMEM_add_to_physmap_range be implemented
for x86 on the hypervisor side. For inspiration the ARM version can be
found at <[email protected]>
(and will likely be in xen-unstable soon).
In the end I checked it in yesterday.
> and since I've already got my patches tested and cut, I'm going to send
> them now. We can apply this change easily in konrad's tree.
Sure, no problem.
Ian.
On Wed, 17 Oct 2012, Ian Campbell wrote:
> The ARM platform has no concept of PVMMU and therefor no
> HYPERVISOR_update_va_mapping et al. Allow this code to be compiled out
> when not required.
>
> In some similar situations (e.g. P2M) we have defined dummy functions
> to avoid this, however I think we can/should draw the line at dummying
> out actual hypercalls.
>
> Signed-off-by: Ian Campbell <[email protected]>
It is OK for me
> arch/x86/xen/Kconfig | 1 +
> drivers/xen/Kconfig | 3 +++
> drivers/xen/balloon.c | 4 ++++
> 3 files changed, 8 insertions(+), 0 deletions(-)
>
> diff --git a/arch/x86/xen/Kconfig b/arch/x86/xen/Kconfig
> index 9323b8c..6d101a1 100644
> --- a/arch/x86/xen/Kconfig
> +++ b/arch/x86/xen/Kconfig
> @@ -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
> diff --git a/drivers/xen/Kconfig b/drivers/xen/Kconfig
> index d4dffcd..9c00652 100644
> --- a/drivers/xen/Kconfig
> +++ b/drivers/xen/Kconfig
> @@ -204,4 +204,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
> diff --git a/drivers/xen/balloon.c b/drivers/xen/balloon.c
> index db3aa34..92449a0 100644
> --- a/drivers/xen/balloon.c
> +++ b/drivers/xen/balloon.c
> @@ -360,6 +360,7 @@ static enum bp_state increase_reservation(unsigned long nr_pages)
> if (!xen_feature(XENFEAT_auto_translated_physmap))
> 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) &&
> !xen_feature(XENFEAT_auto_translated_physmap)) {
> @@ -371,6 +372,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);
> @@ -419,6 +421,7 @@ 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)) {
> if (!xen_feature(XENFEAT_auto_translated_physmap)) {
> ret = HYPERVISOR_update_va_mapping(
> @@ -427,6 +430,7 @@ static enum bp_state decrease_reservation(unsigned long nr_pages, gfp_t gfp)
> BUG_ON(ret);
> }
> }
> +#endif
> }
>
> /* Ensure that ballooned highmem pages don't have kmaps. */
> --
> 1.7.2.5
>
On Wed, 17 Oct 2012, Ian Campbell wrote:
> The code is no in a state where can just enable it.
>
> Drop the *_xenballloned_pages duplicates since these are now supplied
> by the balloon code.
>
> Signed-off-by: Ian Campbell <[email protected]>
Acked-by: Stefano Stabellini <[email protected]>
> arch/arm/xen/enlighten.c | 23 +++++------------------
> drivers/xen/Makefile | 4 ++--
> 2 files changed, 7 insertions(+), 20 deletions(-)
>
> diff --git a/arch/arm/xen/enlighten.c b/arch/arm/xen/enlighten.c
> index 59bcb96..ba5cc13 100644
> --- a/arch/arm/xen/enlighten.c
> +++ b/arch/arm/xen/enlighten.c
> @@ -8,6 +8,7 @@
> #include <xen/features.h>
> #include <xen/platform_pci.h>
> #include <xen/xenbus.h>
> +#include <xen/page.h>
> #include <asm/xen/hypervisor.h>
> #include <asm/xen/hypercall.h>
> #include <linux/interrupt.h>
> @@ -29,6 +30,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);
> @@ -148,21 +153,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);
> diff --git a/drivers/xen/Makefile b/drivers/xen/Makefile
> index 0e863703..909bb56 100644
> --- a/drivers/xen/Makefile
> +++ b/drivers/xen/Makefile
> @@ -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)
> --
> 1.7.2.5
>
On Wed, 17 Oct 2012, Ian Campbell wrote:
> For Xen on ARM a PFN is 64 bits so we need to use the appropriate
> type here.
>
> Signed-off-by: Ian Campbell <[email protected]>
Acked-by: Stefano Stabellini <[email protected]>
In general every mfn/pfn type should be xen_pfn_t, we might have to do a
closer audit of the code.
> arch/x86/xen/mmu.c | 2 +-
> include/xen/xen-ops.h | 2 +-
> 2 files changed, 2 insertions(+), 2 deletions(-)
>
> diff --git a/arch/x86/xen/mmu.c b/arch/x86/xen/mmu.c
> index 1c5812b..d779e96 100644
> --- a/arch/x86/xen/mmu.c
> +++ b/arch/x86/xen/mmu.c
> @@ -2603,7 +2603,7 @@ 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,
> + xen_pfn_t mfn, int nr,
> pgprot_t prot, unsigned domid,
> struct page **pages)
>
> diff --git a/include/xen/xen-ops.h b/include/xen/xen-ops.h
> index 6a40253..dc63e80 100644
> --- a/include/xen/xen-ops.h
> +++ b/include/xen/xen-ops.h
> @@ -26,7 +26,7 @@ void xen_destroy_contiguous_region(unsigned long vstart, unsigned int order);
> struct vm_area_struct;
> int xen_remap_domain_mfn_range(struct vm_area_struct *vma,
> unsigned long addr,
> - unsigned long mfn, int nr,
> + xen_pfn_t mfn, int nr,
> pgprot_t prot, unsigned domid,
> struct page **pages);
> int xen_unmap_domain_mfn_range(struct vm_area_struct *vma,
> --
> 1.7.2.5
>
On Wed, 17 Oct 2012, Ian Campbell wrote:
> We use XENMEM_add_to_physmap_range which is the preferred interface
> for foreign mappings.
>
> Signed-off-by: Ian Campbell <[email protected]>
It looks OK but there are few code style issues, please run the patch
through checkpatch.
> arch/arm/include/asm/xen/interface.h | 1 +
> arch/arm/xen/enlighten.c | 100 +++++++++++++++++++++++++++++++++-
> arch/x86/include/asm/xen/interface.h | 1 +
> include/xen/interface/memory.h | 18 ++++++
> 4 files changed, 117 insertions(+), 3 deletions(-)
>
> diff --git a/arch/arm/include/asm/xen/interface.h b/arch/arm/include/asm/xen/interface.h
> index 1d6ef9c..007e6da 100644
> --- a/arch/arm/include/asm/xen/interface.h
> +++ b/arch/arm/include/asm/xen/interface.h
> @@ -43,6 +43,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
> diff --git a/arch/arm/xen/enlighten.c b/arch/arm/xen/enlighten.c
> index ba5cc13..6bb4630 100644
> --- a/arch/arm/xen/enlighten.c
> +++ b/arch/arm/xen/enlighten.c
> @@ -9,6 +9,7 @@
> #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>
> @@ -18,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);
> @@ -43,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,
> + struct page **pages, int nr)
> +{
> + 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.
> diff --git a/arch/x86/include/asm/xen/interface.h b/arch/x86/include/asm/xen/interface.h
> index 25669c3..6246d80 100644
> --- a/arch/x86/include/asm/xen/interface.h
> +++ b/arch/x86/include/asm/xen/interface.h
> @@ -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
> diff --git a/include/xen/interface/memory.h b/include/xen/interface/memory.h
> index 91bdc2a..eb2d3e5 100644
> --- a/include/xen/interface/memory.h
> +++ b/include/xen/interface/memory.h
> @@ -190,6 +190,24 @@ DEFINE_GUEST_HANDLE_STRUCT(xen_add_to_physmap);
> /*** REMOVED ***/
> /*#define XENMEM_translate_gpfn_list 8*/
>
> +#define XENMEM_add_to_physmap_range 23
> +struct xen_add_to_physmap_range {
> + /* Which domain to change the mapping for. */
> + domid_t domid;
> + uint16_t space; /* => enum phys_map_space */
> +
> + /* Number of pages to go through */
> + uint16_t size;
> + domid_t foreign_domid; /* IFF gmfn_foreign */
> +
> + /* Indexes into space being mapped. */
> + GUEST_HANDLE(xen_ulong_t) idxs;
> +
> + /* GPFN in domid where the source mapping page should appear. */
> + GUEST_HANDLE(xen_pfn_t) gpfns;
> +};
> +DEFINE_GUEST_HANDLE_STRUCT(xen_add_to_physmap_range);
> +
> /*
> * Returns the pseudo-physical memory map as it was when the domain
> * was started (specified by XENMEM_set_memory_map).
> --
> 1.7.2.5
>
On Wed, 17 Oct 2012, Ian Campbell wrote:
> Squeezing the necessary fields into the existing XENMEM_add_to_physmap
> interface was proving to be a bit tricky so we have decided to go with
> a new interface upstream (the XENMAPSPACE_gmfn_foreign interface using
> XENMEM_add_to_physmap was never committed anywhere). This interface
> also allows for batching which was impossible to support at the same
> time as foreign mfns in the old interface.
>
> This reverts the relevant parts of "PVH: basic and header changes,
> elfnote changes, ..." and followups and trivially converts
> pvh_add_to_xen_p2m over.
>
> Signed-off-by: Ian Campbell <[email protected]>
Acked-by: Stefano Stabellini <[email protected]>
On Thu, 2012-10-18 at 14:27 +0100, Stefano Stabellini wrote:
> On Wed, 17 Oct 2012, Ian Campbell wrote:
> > We use XENMEM_add_to_physmap_range which is the preferred interface
> > for foreign mappings.
> >
> > Signed-off-by: Ian Campbell <[email protected]>
>
> It looks OK but there are few code style issues, please run the patch
> through checkpatch.
The only one I get is:
WARNING: please, no spaces at the start of a line
#83: FILE: include/xen/interface/memory.h:175:
+ uint16_t size;$
total: 0 errors, 1 warnings, 64 lines checked
The prevailing indentation in that file is 4 spaces so I think we should
ignore the warning in this case in the interests of consistency with the
surrounding code.
Ian.
On Thu, 18 Oct 2012, Ian Campbell wrote:
> On Thu, 2012-10-18 at 14:27 +0100, Stefano Stabellini wrote:
> > On Wed, 17 Oct 2012, Ian Campbell wrote:
> > > We use XENMEM_add_to_physmap_range which is the preferred interface
> > > for foreign mappings.
> > >
> > > Signed-off-by: Ian Campbell <[email protected]>
> >
> > It looks OK but there are few code style issues, please run the patch
> > through checkpatch.
>
> The only one I get is:
> WARNING: please, no spaces at the start of a line
> #83: FILE: include/xen/interface/memory.h:175:
> + uint16_t size;$
>
> total: 0 errors, 1 warnings, 64 lines checked
>
> The prevailing indentation in that file is 4 spaces so I think we should
> ignore the warning in this case in the interests of consistency with the
> surrounding code.
Strange, I get:
ERROR: spaces required around that '=' (ctx:VxV)
#140: FILE: arch/arm/xen/enlighten.c:130:
+ for (i=0; i<nr; i++) {
^
ERROR: spaces required around that '<' (ctx:VxV)
#140: FILE: arch/arm/xen/enlighten.c:130:
+ for (i=0; i<nr; i++) {
^
WARNING: please, no spaces at the start of a line
#185: FILE: include/xen/interface/memory.h:196:
+ domid_t domid;$
WARNING: please, no spaces at the start of a line
#186: FILE: include/xen/interface/memory.h:197:
+ uint16_t space; /* => enum phys_map_space */$
WARNING: please, no spaces at the start of a line
#189: FILE: include/xen/interface/memory.h:200:
+ uint16_t size;$
WARNING: please, no spaces at the start of a line
#190: FILE: include/xen/interface/memory.h:201:
+ domid_t foreign_domid; /* IFF gmfn_foreign */$
WARNING: please, no spaces at the start of a line
#193: FILE: include/xen/interface/memory.h:204:
+ GUEST_HANDLE(xen_ulong_t) idxs;$
WARNING: please, no spaces at the start of a line
#196: FILE: include/xen/interface/memory.h:207:
+ GUEST_HANDLE(xen_pfn_t) gpfns;$
total: 2 errors, 6 warnings, 162 lines checked
The ones that bother me a bit are:
+ for (i=0; i<nr; i++) {
that should be
+ for (i = 0; i < nr; i++) {
On Thu, 2012-10-18 at 14:35 +0100, Stefano Stabellini wrote:
> On Thu, 18 Oct 2012, Ian Campbell wrote:
> > On Thu, 2012-10-18 at 14:27 +0100, Stefano Stabellini wrote:
> > > On Wed, 17 Oct 2012, Ian Campbell wrote:
> > > > We use XENMEM_add_to_physmap_range which is the preferred interface
> > > > for foreign mappings.
> > > >
> > > > Signed-off-by: Ian Campbell <[email protected]>
> > >
> > > It looks OK but there are few code style issues, please run the patch
> > > through checkpatch.
> >
> > The only one I get is:
> > WARNING: please, no spaces at the start of a line
> > #83: FILE: include/xen/interface/memory.h:175:
> > + uint16_t size;$
> >
> > total: 0 errors, 1 warnings, 64 lines checked
> >
> > The prevailing indentation in that file is 4 spaces so I think we should
> > ignore the warning in this case in the interests of consistency with the
> > surrounding code.
>
> Strange, I get:
I'm running v3.7-rc1-187-g7bbf07e so it is pretty recent.
[...]
> total: 2 errors, 6 warnings, 162 lines checked
Ah, I was looking at patch 6/6...
The warnings in this one are all of the same class as before (4 space
indentation). But you are right, the other two need fixing. Done in my
tree.