[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-changelog] Add new feature XENFEAT_auto_translated_physmap.
# 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
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |