# HG changeset patch
# User Ian.Campbell@xxxxxxxxxxxxx
# Node ID c84a051d89670408e696cad2528ad14d062f9345
# Parent 0e87a5bd6e8bbfe5e6921e32e0d6cc91d14bded8
Add new feature XENFEAT_auto_translated_physmap.
This feature causes the guest OS to ignore the P2M and M2P tables and
to assume that P==M.
Signed-off-by: Ian Campbell <Ian.Campbell@xxxxxxxxxxxxx>
diff -r 0e87a5bd6e8b -r c84a051d8967
linux-2.6-xen-sparse/arch/i386/kernel/setup-xen.c
--- a/linux-2.6-xen-sparse/arch/i386/kernel/setup-xen.c Wed Feb 1 20:11:18 2006
+++ b/linux-2.6-xen-sparse/arch/i386/kernel/setup-xen.c Wed Feb 1 20:12:51 2006
@@ -1310,7 +1310,9 @@
}
#endif
- phys_to_machine_mapping = (unsigned long *)xen_start_info->mfn_list;
+ if (!xen_feature(XENFEAT_auto_translated_physmap))
+ phys_to_machine_mapping =
+ (unsigned long *)xen_start_info->mfn_list;
}
/*
@@ -1746,42 +1748,43 @@
#endif
/* Make sure we have a correctly sized P->M table. */
- phys_to_machine_mapping = alloc_bootmem_low_pages(
- max_pfn * sizeof(unsigned long));
- memset(phys_to_machine_mapping, ~0,
- max_pfn * sizeof(unsigned long));
- memcpy(phys_to_machine_mapping,
- (unsigned long *)xen_start_info->mfn_list,
- xen_start_info->nr_pages * sizeof(unsigned long));
- free_bootmem(
- __pa(xen_start_info->mfn_list),
- PFN_PHYS(PFN_UP(xen_start_info->nr_pages *
- sizeof(unsigned long))));
-
- /*
- * Initialise the list of the frames that specify the list of
- * frames that make up the p2m table. Used by save/restore
- */
- pfn_to_mfn_frame_list_list = alloc_bootmem_low_pages(PAGE_SIZE);
- HYPERVISOR_shared_info->arch.pfn_to_mfn_frame_list_list =
- virt_to_mfn(pfn_to_mfn_frame_list_list);
-
- fpp = PAGE_SIZE/sizeof(unsigned long);
- for ( i=0, j=0, k=-1; i< max_pfn; i+=fpp, j++ )
- {
- if ( (j % fpp) == 0 )
- {
- k++;
- BUG_ON(k>=16);
- pfn_to_mfn_frame_list[k] = alloc_bootmem_low_pages(PAGE_SIZE);
- pfn_to_mfn_frame_list_list[k] =
- virt_to_mfn(pfn_to_mfn_frame_list[k]);
- j=0;
- }
- pfn_to_mfn_frame_list[k][j] =
- virt_to_mfn(&phys_to_machine_mapping[i]);
- }
- HYPERVISOR_shared_info->arch.max_pfn = max_pfn;
+ if (!xen_feature(XENFEAT_auto_translated_physmap)) {
+ phys_to_machine_mapping = alloc_bootmem_low_pages(
+ max_pfn * sizeof(unsigned long));
+ memset(phys_to_machine_mapping, ~0,
+ max_pfn * sizeof(unsigned long));
+ memcpy(phys_to_machine_mapping,
+ (unsigned long *)xen_start_info->mfn_list,
+ xen_start_info->nr_pages * sizeof(unsigned long));
+ free_bootmem(
+ __pa(xen_start_info->mfn_list),
+ PFN_PHYS(PFN_UP(xen_start_info->nr_pages *
+ sizeof(unsigned long))));
+
+ /*
+ * Initialise the list of the frames that specify the list of
+ * frames that make up the p2m table. Used by save/restore
+ */
+ pfn_to_mfn_frame_list_list = alloc_bootmem_low_pages(PAGE_SIZE);
+ HYPERVISOR_shared_info->arch.pfn_to_mfn_frame_list_list =
+ virt_to_mfn(pfn_to_mfn_frame_list_list);
+
+ fpp = PAGE_SIZE/sizeof(unsigned long);
+ for (i=0, j=0, k=-1; i< max_pfn; i+=fpp, j++) {
+ if ((j % fpp) == 0) {
+ k++;
+ BUG_ON(k>=16);
+ pfn_to_mfn_frame_list[k] =
+ alloc_bootmem_low_pages(PAGE_SIZE);
+ pfn_to_mfn_frame_list_list[k] =
+ virt_to_mfn(pfn_to_mfn_frame_list[k]);
+ j=0;
+ }
+ pfn_to_mfn_frame_list[k][j] =
+ virt_to_mfn(&phys_to_machine_mapping[i]);
+ }
+ HYPERVISOR_shared_info->arch.max_pfn = max_pfn;
+ }
/*
* NOTE: at this point the bootmem allocator is fully available.
diff -r 0e87a5bd6e8b -r c84a051d8967
linux-2.6-xen-sparse/arch/i386/mm/hypervisor.c
--- a/linux-2.6-xen-sparse/arch/i386/mm/hypervisor.c Wed Feb 1 20:11:18 2006
+++ b/linux-2.6-xen-sparse/arch/i386/mm/hypervisor.c Wed Feb 1 20:12:51 2006
@@ -35,6 +35,7 @@
#include <asm/pgtable.h>
#include <asm/hypervisor.h>
#include <xen/balloon.h>
+#include <xen/features.h>
#include <xen/interface/memory.h>
#include <linux/module.h>
#include <linux/percpu.h>
@@ -100,6 +101,10 @@
void xen_machphys_update(unsigned long mfn, unsigned long pfn)
{
mmu_update_t u;
+ if (xen_feature(XENFEAT_auto_translated_physmap)) {
+ BUG_ON(pfn != mfn);
+ return;
+ }
u.ptr = ((unsigned long long)mfn << PAGE_SHIFT) | MMU_MACHPHYS_UPDATE;
u.val = pfn;
BUG_ON(HYPERVISOR_mmu_update(&u, 1, NULL, DOMID_SELF) < 0);
@@ -322,6 +327,11 @@
.extent_order = 0,
.domid = DOMID_SELF
};
+
+ if (xen_feature(XENFEAT_auto_translated_physmap)) {
+ BUG_ON(order >= 1);
+ return 0;
+ }
scrub_pages(vstart, 1 << order);
@@ -401,6 +411,9 @@
.domid = DOMID_SELF
};
+ if (xen_feature(XENFEAT_auto_translated_physmap))
+ return;
+
scrub_pages(vstart, 1 << order);
balloon_lock(flags);
diff -r 0e87a5bd6e8b -r c84a051d8967
linux-2.6-xen-sparse/arch/i386/mm/ioremap-xen.c
--- a/linux-2.6-xen-sparse/arch/i386/mm/ioremap-xen.c Wed Feb 1 20:11:18 2006
+++ b/linux-2.6-xen-sparse/arch/i386/mm/ioremap-xen.c Wed Feb 1 20:12:51 2006
@@ -177,15 +177,13 @@
/*
* Does @address reside within a non-highmem page that is local to this virtual
* machine (i.e., not an I/O page, nor a memory page belonging to another VM).
- * See the comment that accompanies pte_pfn() in pgtable-2level.h to understand
+ * See the comment that accompanies mfn_to_local_pfn() in page.h to understand
* why this works.
*/
static inline int is_local_lowmem(unsigned long address)
{
extern unsigned long max_low_pfn;
- unsigned long mfn = address >> PAGE_SHIFT;
- unsigned long pfn = mfn_to_pfn(mfn);
- return ((pfn < max_low_pfn) && (phys_to_machine_mapping[pfn] == mfn));
+ return (mfn_to_local_pfn(address >> PAGE_SHIFT) < max_low_pfn);
}
/*
diff -r 0e87a5bd6e8b -r c84a051d8967
linux-2.6-xen-sparse/arch/i386/mm/pgtable-xen.c
--- a/linux-2.6-xen-sparse/arch/i386/mm/pgtable-xen.c Wed Feb 1 20:11:18 2006
+++ b/linux-2.6-xen-sparse/arch/i386/mm/pgtable-xen.c Wed Feb 1 20:12:51 2006
@@ -522,6 +522,9 @@
pte_t *pte;
int g, u, m;
+ if (xen_feature(XENFEAT_auto_translated_physmap))
+ return;
+
for (g = 0; g < USER_PTRS_PER_PGD; g++, pgd++) {
if (pgd_none(*pgd))
continue;
diff -r 0e87a5bd6e8b -r c84a051d8967
linux-2.6-xen-sparse/arch/x86_64/kernel/head64-xen.c
--- a/linux-2.6-xen-sparse/arch/x86_64/kernel/head64-xen.c Wed Feb 1
20:11:18 2006
+++ b/linux-2.6-xen-sparse/arch/x86_64/kernel/head64-xen.c Wed Feb 1
20:12:51 2006
@@ -89,9 +89,12 @@
{
int i;
- phys_to_machine_mapping = (unsigned long *)xen_start_info->mfn_list;
- start_pfn = (__pa(xen_start_info->pt_base) >> PAGE_SHIFT) +
- xen_start_info->nr_pt_frames;
+ if (!xen_feature(XENFEAT_auto_translated_physmap)) {
+ phys_to_machine_mapping =
+ (unsigned long *)xen_start_info->mfn_list;
+ start_pfn = (__pa(xen_start_info->pt_base) >> PAGE_SHIFT) +
+ xen_start_info->nr_pt_frames;
+ }
for (i = 0; i < 256; i++)
set_intr_gate(i, early_idt_handler);
diff -r 0e87a5bd6e8b -r c84a051d8967
linux-2.6-xen-sparse/arch/x86_64/kernel/setup-xen.c
--- a/linux-2.6-xen-sparse/arch/x86_64/kernel/setup-xen.c Wed Feb 1
20:11:18 2006
+++ b/linux-2.6-xen-sparse/arch/x86_64/kernel/setup-xen.c Wed Feb 1
20:12:51 2006
@@ -784,27 +784,6 @@
int i, j, k, fpp;
unsigned long va;
- /* Make sure we have a large enough P->M table. */
- phys_to_machine_mapping = alloc_bootmem(
- end_pfn * sizeof(unsigned long));
- memset(phys_to_machine_mapping, ~0,
- end_pfn * sizeof(unsigned long));
- memcpy(phys_to_machine_mapping,
- (unsigned long *)xen_start_info->mfn_list,
- xen_start_info->nr_pages * sizeof(unsigned long));
- free_bootmem(
- __pa(xen_start_info->mfn_list),
- PFN_PHYS(PFN_UP(xen_start_info->nr_pages *
- sizeof(unsigned long))));
-
- /* 'Initial mapping' of old p2m table must be destroyed. */
- for (va = xen_start_info->mfn_list;
- va < (xen_start_info->mfn_list +
- (xen_start_info->nr_pages*sizeof(unsigned long)));
- va += PAGE_SIZE) {
- HYPERVISOR_update_va_mapping(va, __pte_ma(0), 0);
- }
-
/* 'Initial mapping' of initrd must be destroyed. */
for (va = xen_start_info->mod_start;
va < (xen_start_info->mod_start+xen_start_info->mod_len);
@@ -812,30 +791,53 @@
HYPERVISOR_update_va_mapping(va, __pte_ma(0), 0);
}
- /*
- * Initialise the list of the frames that specify the list of
- * frames that make up the p2m table. Used by save/restore
- */
- pfn_to_mfn_frame_list_list = alloc_bootmem(PAGE_SIZE);
- HYPERVISOR_shared_info->arch.pfn_to_mfn_frame_list_list =
- virt_to_mfn(pfn_to_mfn_frame_list_list);
-
- fpp = PAGE_SIZE/sizeof(unsigned long);
- for ( i=0, j=0, k=-1; i< end_pfn; i+=fpp, j++ )
- {
- if ( (j % fpp) == 0 )
- {
- k++;
- BUG_ON(k>=fpp);
- pfn_to_mfn_frame_list[k] =
alloc_bootmem(PAGE_SIZE);
- pfn_to_mfn_frame_list_list[k] =
- virt_to_mfn(pfn_to_mfn_frame_list[k]);
- j=0;
+ if (!xen_feature(XENFEAT_auto_translated_physmap)) {
+ /* Make sure we have a large enough P->M table. */
+ phys_to_machine_mapping = alloc_bootmem(
+ end_pfn * sizeof(unsigned long));
+ memset(phys_to_machine_mapping, ~0,
+ end_pfn * sizeof(unsigned long));
+ memcpy(phys_to_machine_mapping,
+ (unsigned long *)xen_start_info->mfn_list,
+ xen_start_info->nr_pages * sizeof(unsigned
long));
+ free_bootmem(
+ __pa(xen_start_info->mfn_list),
+ PFN_PHYS(PFN_UP(xen_start_info->nr_pages *
+ sizeof(unsigned long))));
+
+ /* Destroyed 'initial mapping' of old p2m table. */
+ for (va = xen_start_info->mfn_list;
+ va < (xen_start_info->mfn_list +
+ (xen_start_info->nr_pages*sizeof(unsigned
long)));
+ va += PAGE_SIZE) {
+ HYPERVISOR_update_va_mapping(va, __pte_ma(0),
0);
}
- pfn_to_mfn_frame_list[k][j] =
- virt_to_mfn(&phys_to_machine_mapping[i]);
+
+ /*
+ * Initialise the list of the frames that specify the
+ * list of frames that make up the p2m table. Used by
+ * save/restore.
+ */
+ pfn_to_mfn_frame_list_list = alloc_bootmem(PAGE_SIZE);
+ HYPERVISOR_shared_info->arch.pfn_to_mfn_frame_list_list
=
+ virt_to_mfn(pfn_to_mfn_frame_list_list);
+
+ fpp = PAGE_SIZE/sizeof(unsigned long);
+ for (i=0, j=0, k=-1; i< end_pfn; i+=fpp, j++) {
+ if ((j % fpp) == 0) {
+ k++;
+ BUG_ON(k>=fpp);
+ pfn_to_mfn_frame_list[k] =
+ alloc_bootmem(PAGE_SIZE);
+ pfn_to_mfn_frame_list_list[k] =
+
virt_to_mfn(pfn_to_mfn_frame_list[k]);
+ j=0;
+ }
+ pfn_to_mfn_frame_list[k][j] =
+
virt_to_mfn(&phys_to_machine_mapping[i]);
+ }
+ HYPERVISOR_shared_info->arch.max_pfn = end_pfn;
}
- HYPERVISOR_shared_info->arch.max_pfn = end_pfn;
}
diff -r 0e87a5bd6e8b -r c84a051d8967
linux-2.6-xen-sparse/drivers/xen/core/reboot.c
--- a/linux-2.6-xen-sparse/drivers/xen/core/reboot.c Wed Feb 1 20:11:18 2006
+++ b/linux-2.6-xen-sparse/drivers/xen/core/reboot.c Wed Feb 1 20:12:51 2006
@@ -101,6 +101,12 @@
BUG_ON(smp_processor_id() != 0);
BUG_ON(in_interrupt());
+
+ if (xen_feature(XENFEAT_auto_translated_physmap)) {
+ printk(KERN_WARNING "Cannot suspend in "
+ "auto_translated_physmap mode.\n");
+ return -EOPNOTSUPP;
+ }
#if defined(CONFIG_SMP) && !defined(CONFIG_HOTPLUG_CPU)
if (num_online_cpus() > 1) {
diff -r 0e87a5bd6e8b -r c84a051d8967
linux-2.6-xen-sparse/drivers/xen/netback/netback.c
--- a/linux-2.6-xen-sparse/drivers/xen/netback/netback.c Wed Feb 1
20:11:18 2006
+++ b/linux-2.6-xen-sparse/drivers/xen/netback/netback.c Wed Feb 1
20:12:51 2006
@@ -236,10 +236,12 @@
netif->rx.req_cons++;
gop++;
- mmu->ptr = ((maddr_t)new_mfn << PAGE_SHIFT) |
- MMU_MACHPHYS_UPDATE;
- mmu->val = __pa(vdata) >> PAGE_SHIFT;
- mmu++;
+ if (!xen_feature(XENFEAT_auto_translated_physmap)) {
+ mmu->ptr = ((maddr_t)new_mfn << PAGE_SHIFT) |
+ MMU_MACHPHYS_UPDATE;
+ mmu->val = __pa(vdata) >> PAGE_SHIFT;
+ mmu++;
+ }
__skb_queue_tail(&rxq, skb);
@@ -251,14 +253,17 @@
if (mcl == rx_mcl)
return;
- mcl->op = __HYPERVISOR_mmu_update;
- mcl->args[0] = (unsigned long)rx_mmu;
- mcl->args[1] = mmu - rx_mmu;
- mcl->args[2] = 0;
- mcl->args[3] = DOMID_SELF;
- mcl++;
-
- mcl[-2].args[MULTI_UVMFLAGS_INDEX] = UVMF_TLB_FLUSH|UVMF_ALL;
+ mcl[-1].args[MULTI_UVMFLAGS_INDEX] = UVMF_TLB_FLUSH|UVMF_ALL;
+
+ if (mmu - rx_mmu) {
+ mcl->op = __HYPERVISOR_mmu_update;
+ mcl->args[0] = (unsigned long)rx_mmu;
+ mcl->args[1] = mmu - rx_mmu;
+ mcl->args[2] = 0;
+ mcl->args[3] = DOMID_SELF;
+ mcl++;
+ }
+
ret = HYPERVISOR_multicall(rx_mcl, mcl - rx_mcl);
BUG_ON(ret != 0);
diff -r 0e87a5bd6e8b -r c84a051d8967
linux-2.6-xen-sparse/drivers/xen/netfront/netfront.c
--- a/linux-2.6-xen-sparse/drivers/xen/netfront/netfront.c Wed Feb 1
20:11:18 2006
+++ b/linux-2.6-xen-sparse/drivers/xen/netfront/netfront.c Wed Feb 1
20:12:51 2006
@@ -802,14 +802,17 @@
np->stats.rx_bytes += rx->status;
/* Remap the page. */
- mmu->ptr = ((maddr_t)mfn << PAGE_SHIFT) | MMU_MACHPHYS_UPDATE;
- mmu->val = __pa(skb->head) >> PAGE_SHIFT;
- mmu++;
MULTI_update_va_mapping(mcl, (unsigned long)skb->head,
pfn_pte_ma(mfn, PAGE_KERNEL), 0);
mcl++;
-
- set_phys_to_machine(__pa(skb->head) >> PAGE_SHIFT, mfn);
+ if (!xen_feature(XENFEAT_auto_translated_physmap)) {
+ mmu->ptr = ((maddr_t)mfn << PAGE_SHIFT)
+ | MMU_MACHPHYS_UPDATE;
+ mmu->val = __pa(skb->head) >> PAGE_SHIFT;
+ mmu++;
+
+ set_phys_to_machine(__pa(skb->head) >> PAGE_SHIFT, mfn);
+ }
__skb_queue_tail(&rxq, skb);
}
diff -r 0e87a5bd6e8b -r c84a051d8967
linux-2.6-xen-sparse/include/asm-i386/mach-xen/asm/page.h
--- a/linux-2.6-xen-sparse/include/asm-i386/mach-xen/asm/page.h Wed Feb 1
20:11:18 2006
+++ b/linux-2.6-xen-sparse/include/asm-i386/mach-xen/asm/page.h Wed Feb 1
20:12:51 2006
@@ -18,6 +18,7 @@
#include <linux/kernel.h>
#include <asm/bug.h>
#include <xen/interface/xen.h>
+#include <xen/features.h>
#include <xen/foreign_page.h>
#define arch_free_page(_page,_order) \
@@ -61,15 +62,31 @@
/**** MACHINE <-> PHYSICAL CONVERSION MACROS ****/
#define INVALID_P2M_ENTRY (~0UL)
-#define FOREIGN_FRAME(m) ((m) | (1UL<<31))
+#define FOREIGN_FRAME_BIT (1UL<<31)
+#define FOREIGN_FRAME(m) ((m) | FOREIGN_FRAME_BIT)
+
extern unsigned long *phys_to_machine_mapping;
-#define pfn_to_mfn(pfn) \
-(phys_to_machine_mapping[(unsigned int)(pfn)] & ~(1UL<<31))
-#define phys_to_machine_mapping_valid(pfn) \
- (phys_to_machine_mapping[pfn] != INVALID_P2M_ENTRY)
+
+static inline unsigned long pfn_to_mfn(unsigned long pfn)
+{
+ if (xen_feature(XENFEAT_auto_translated_physmap))
+ return pfn;
+ return phys_to_machine_mapping[(unsigned int)(pfn)] &
~FOREIGN_FRAME_BIT;
+}
+
+static inline int phys_to_machine_mapping_valid(unsigned long pfn)
+{
+ if (xen_feature(XENFEAT_auto_translated_physmap))
+ return 1;
+ return (phys_to_machine_mapping[pfn] != INVALID_P2M_ENTRY);
+}
+
static inline unsigned long mfn_to_pfn(unsigned long mfn)
{
unsigned long pfn;
+
+ if (xen_feature(XENFEAT_auto_translated_physmap))
+ return mfn;
/*
* The array access can fail (e.g., device space beyond end of RAM).
@@ -88,8 +105,43 @@
return pfn;
}
+/*
+ * We detect special mappings in one of two ways:
+ * 1. If the MFN is an I/O page then Xen will set the m2p entry
+ * to be outside our maximum possible pseudophys range.
+ * 2. If the MFN belongs to a different domain then we will certainly
+ * not have MFN in our p2m table. Conversely, if the page is ours,
+ * then we'll have p2m(m2p(MFN))==MFN.
+ * If we detect a special mapping then it doesn't have a 'struct page'.
+ * We force !pfn_valid() by returning an out-of-range pointer.
+ *
+ * NB. These checks require that, for any MFN that is not in our reservation,
+ * there is no PFN such that p2m(PFN) == MFN. Otherwise we can get confused if
+ * we are foreign-mapping the MFN, and the other domain as m2p(MFN) == PFN.
+ * Yikes! Various places must poke in INVALID_P2M_ENTRY for safety.
+ *
+ * NB2. When deliberately mapping foreign pages into the p2m table, you *must*
+ * use FOREIGN_FRAME(). This will cause pte_pfn() to choke on it, as we
+ * require. In all the cases we care about, the FOREIGN_FRAME bit is
+ * masked (e.g., pfn_to_mfn()) so behaviour there is correct.
+ */
+static inline unsigned long mfn_to_local_pfn(unsigned long mfn)
+{
+ extern unsigned long max_mapnr;
+ unsigned long pfn = mfn_to_pfn(mfn);
+ if ((pfn < max_mapnr)
+ && !xen_feature(XENFEAT_auto_translated_physmap)
+ && (phys_to_machine_mapping[pfn] != mfn))
+ return max_mapnr; /* force !pfn_valid() */
+ return pfn;
+}
+
static inline void set_phys_to_machine(unsigned long pfn, unsigned long mfn)
{
+ if (xen_feature(XENFEAT_auto_translated_physmap)) {
+ BUG_ON(pfn != mfn && mfn != INVALID_P2M_ENTRY);
+ return;
+ }
phys_to_machine_mapping[pfn] = mfn;
}
diff -r 0e87a5bd6e8b -r c84a051d8967
linux-2.6-xen-sparse/include/asm-i386/mach-xen/asm/pgtable-2level.h
--- a/linux-2.6-xen-sparse/include/asm-i386/mach-xen/asm/pgtable-2level.h
Wed Feb 1 20:11:18 2006
+++ b/linux-2.6-xen-sparse/include/asm-i386/mach-xen/asm/pgtable-2level.h
Wed Feb 1 20:12:51 2006
@@ -39,35 +39,8 @@
#define ptep_get_and_clear(mm,addr,xp) __pte_ma(xchg(&(xp)->pte_low, 0))
#define pte_same(a, b) ((a).pte_low == (b).pte_low)
-/*
- * We detect special mappings in one of two ways:
- * 1. If the MFN is an I/O page then Xen will set the m2p entry
- * to be outside our maximum possible pseudophys range.
- * 2. If the MFN belongs to a different domain then we will certainly
- * not have MFN in our p2m table. Conversely, if the page is ours,
- * then we'll have p2m(m2p(MFN))==MFN.
- * If we detect a special mapping then it doesn't have a 'struct page'.
- * We force !pfn_valid() by returning an out-of-range pointer.
- *
- * NB. These checks require that, for any MFN that is not in our reservation,
- * there is no PFN such that p2m(PFN) == MFN. Otherwise we can get confused if
- * we are foreign-mapping the MFN, and the other domain as m2p(MFN) == PFN.
- * Yikes! Various places must poke in INVALID_P2M_ENTRY for safety.
- *
- * NB2. When deliberately mapping foreign pages into the p2m table, you *must*
- * use FOREIGN_FRAME(). This will cause pte_pfn() to choke on it, as we
- * require. In all the cases we care about, the FOREIGN_FRAME bit is
- * masked (e.g., pfn_to_mfn()) so behaviour there is correct.
- */
#define pte_mfn(_pte) ((_pte).pte_low >> PAGE_SHIFT)
-#define pte_pfn(_pte) \
-({ \
- unsigned long mfn = pte_mfn(_pte); \
- unsigned long pfn = mfn_to_pfn(mfn); \
- if ((pfn >= max_mapnr) || (phys_to_machine_mapping[pfn] != mfn))\
- pfn = max_mapnr; /* special: force !pfn_valid() */ \
- pfn; \
-})
+#define pte_pfn(_pte) mfn_to_local_pfn(pte_mfn(_pte))
#define pte_page(_pte) pfn_to_page(pte_pfn(_pte))
diff -r 0e87a5bd6e8b -r c84a051d8967
linux-2.6-xen-sparse/include/asm-i386/mach-xen/asm/pgtable-3level.h
--- a/linux-2.6-xen-sparse/include/asm-i386/mach-xen/asm/pgtable-3level.h
Wed Feb 1 20:11:18 2006
+++ b/linux-2.6-xen-sparse/include/asm-i386/mach-xen/asm/pgtable-3level.h
Wed Feb 1 20:12:51 2006
@@ -140,14 +140,7 @@
#define pte_mfn(_pte) ( ((_pte).pte_low >> PAGE_SHIFT) |\
(((_pte).pte_high & 0xfff) << (32-PAGE_SHIFT)) )
-#define pte_pfn(_pte) \
-({ \
- unsigned long mfn = pte_mfn(_pte); \
- unsigned long pfn = mfn_to_pfn(mfn); \
- if ((pfn >= max_mapnr) || (phys_to_machine_mapping[pfn] != mfn))\
- pfn = max_mapnr; /* special: force !pfn_valid() */ \
- pfn; \
-})
+#define pte_pfn(_pte) mfn_to_local_pfn(pte_mfn(_pte))
extern unsigned long long __supported_pte_mask;
diff -r 0e87a5bd6e8b -r c84a051d8967
linux-2.6-xen-sparse/include/asm-x86_64/mach-xen/asm/page.h
--- a/linux-2.6-xen-sparse/include/asm-x86_64/mach-xen/asm/page.h Wed Feb
1 20:11:18 2006
+++ b/linux-2.6-xen-sparse/include/asm-x86_64/mach-xen/asm/page.h Wed Feb
1 20:12:51 2006
@@ -4,7 +4,10 @@
#include <linux/config.h>
/* #include <linux/string.h> */
#ifndef __ASSEMBLY__
+#include <linux/kernel.h>
#include <linux/types.h>
+#include <asm/bug.h>
+#include <xen/features.h>
#endif
#include <xen/interface/xen.h>
#include <xen/foreign_page.h>
@@ -65,15 +68,31 @@
/**** MACHINE <-> PHYSICAL CONVERSION MACROS ****/
#define INVALID_P2M_ENTRY (~0UL)
-#define FOREIGN_FRAME(m) ((m) | (1UL<<63))
+#define FOREIGN_FRAME_BIT (1UL<<63)
+#define FOREIGN_FRAME(m) ((m) | FOREIGN_FRAME_BIT)
+
extern unsigned long *phys_to_machine_mapping;
-#define pfn_to_mfn(pfn) \
-(phys_to_machine_mapping[(unsigned int)(pfn)] & ~(1UL << 63))
-#define phys_to_machine_mapping_valid(pfn) \
- (phys_to_machine_mapping[pfn] != INVALID_P2M_ENTRY)
+
+static inline unsigned long pfn_to_mfn(unsigned long pfn)
+{
+ if (xen_feature(XENFEAT_auto_translated_physmap))
+ return pfn;
+ return phys_to_machine_mapping[(unsigned int)(pfn)] &
~FOREIGN_FRAME_BIT;
+}
+
+static inline int phys_to_machine_mapping_valid(unsigned long pfn)
+{
+ if (xen_feature(XENFEAT_auto_translated_physmap))
+ return 1;
+ return (phys_to_machine_mapping[pfn] != INVALID_P2M_ENTRY);
+}
+
static inline unsigned long mfn_to_pfn(unsigned long mfn)
{
unsigned long pfn;
+
+ if (xen_feature(XENFEAT_auto_translated_physmap))
+ return mfn;
/*
* The array access can fail (e.g., device space beyond end of RAM).
@@ -92,8 +111,43 @@
return pfn;
}
+/*
+ * We detect special mappings in one of two ways:
+ * 1. If the MFN is an I/O page then Xen will set the m2p entry
+ * to be outside our maximum possible pseudophys range.
+ * 2. If the MFN belongs to a different domain then we will certainly
+ * not have MFN in our p2m table. Conversely, if the page is ours,
+ * then we'll have p2m(m2p(MFN))==MFN.
+ * If we detect a special mapping then it doesn't have a 'struct page'.
+ * We force !pfn_valid() by returning an out-of-range pointer.
+ *
+ * NB. These checks require that, for any MFN that is not in our reservation,
+ * there is no PFN such that p2m(PFN) == MFN. Otherwise we can get confused if
+ * we are foreign-mapping the MFN, and the other domain as m2p(MFN) == PFN.
+ * Yikes! Various places must poke in INVALID_P2M_ENTRY for safety.
+ *
+ * NB2. When deliberately mapping foreign pages into the p2m table, you *must*
+ * use FOREIGN_FRAME(). This will cause pte_pfn() to choke on it, as we
+ * require. In all the cases we care about, the FOREIGN_FRAME bit is
+ * masked (e.g., pfn_to_mfn()) so behaviour there is correct.
+ */
+static inline unsigned long mfn_to_local_pfn(unsigned long mfn)
+{
+ unsigned long pfn = mfn_to_pfn(mfn);
+ if ((pfn < end_pfn)
+ && !xen_feature(XENFEAT_auto_translated_physmap)
+ && (phys_to_machine_mapping[pfn] != mfn))
+ return end_pfn; /* force !pfn_valid() */
+ return pfn;
+}
+
+
static inline void set_phys_to_machine(unsigned long pfn, unsigned long mfn)
{
+ if (xen_feature(XENFEAT_auto_translated_physmap)) {
+ BUG_ON(pfn != mfn && mfn != INVALID_P2M_ENTRY);
+ return;
+ }
phys_to_machine_mapping[pfn] = mfn;
}
@@ -207,12 +261,6 @@
#define KERNEL_TEXT_SIZE (40UL*1024*1024)
#define KERNEL_TEXT_START 0xffffffff80000000UL
-
-#ifndef __ASSEMBLY__
-
-#include <asm/bug.h>
-
-#endif /* __ASSEMBLY__ */
#define PAGE_OFFSET ((unsigned long)__PAGE_OFFSET)
diff -r 0e87a5bd6e8b -r c84a051d8967
linux-2.6-xen-sparse/include/asm-x86_64/mach-xen/asm/pgtable.h
--- a/linux-2.6-xen-sparse/include/asm-x86_64/mach-xen/asm/pgtable.h Wed Feb
1 20:11:18 2006
+++ b/linux-2.6-xen-sparse/include/asm-x86_64/mach-xen/asm/pgtable.h Wed Feb
1 20:12:51 2006
@@ -295,35 +295,8 @@
#define pages_to_mb(x) ((x) >> (20-PAGE_SHIFT))
-/*
- * We detect special mappings in one of two ways:
- * 1. If the MFN is an I/O page then Xen will set the m2p entry
- * to be outside our maximum possible pseudophys range.
- * 2. If the MFN belongs to a different domain then we will certainly
- * not have MFN in our p2m table. Conversely, if the page is ours,
- * then we'll have p2m(m2p(MFN))==MFN.
- * If we detect a special mapping then it doesn't have a 'struct page'.
- * We force !pfn_valid() by returning an out-of-range pointer.
- *
- * NB. These checks require that, for any MFN that is not in our reservation,
- * there is no PFN such that p2m(PFN) == MFN. Otherwise we can get confused if
- * we are foreign-mapping the MFN, and the other domain as m2p(MFN) == PFN.
- * Yikes! Various places must poke in INVALID_P2M_ENTRY for safety.
- *
- * NB2. When deliberately mapping foreign pages into the p2m table, you *must*
- * use FOREIGN_FRAME(). This will cause pte_pfn() to choke on it, as we
- * require. In all the cases we care about, the FOREIGN_FRAME bit is
- * masked (e.g., pfn_to_mfn()) so behaviour there is correct.
- */
#define pte_mfn(_pte) (((_pte).pte & PTE_MASK) >> PAGE_SHIFT)
-#define pte_pfn(_pte) \
-({ \
- unsigned long mfn = pte_mfn(_pte); \
- unsigned long pfn = mfn_to_pfn(mfn); \
- if ((pfn >= end_pfn) || (phys_to_machine_mapping[pfn] != mfn))\
- pfn = end_pfn; /* special: force !pfn_valid() */ \
- pfn; \
-})
+#define pte_pfn(_pte) mfn_to_local_pfn(pte_mfn(_pte))
#define pte_page(x) pfn_to_page(pte_pfn(x))
diff -r 0e87a5bd6e8b -r c84a051d8967 xen/include/public/version.h
--- a/xen/include/public/version.h Wed Feb 1 20:11:18 2006
+++ b/xen/include/public/version.h Wed Feb 1 20:12:51 2006
@@ -47,6 +47,7 @@
#define XENFEAT_writable_page_tables 0
#define XENFEAT_writable_descriptor_tables 1
+#define XENFEAT_auto_translated_physmap 2
#define XENFEAT_NR_SUBMAPS 1
_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-changelog
|