[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Xen-changelog] Merge up and generally make shadow mode be nice.



# HG changeset patch
# User sos22@xxxxxxxxxxxxxxxxxxxx
# Node ID 990c009015e8582eebf04698d845ca2b926ea6bf
# Parent  05a1340bc1e7d47d38520fffc571d17399a0cf8c
# Parent  60beade30a0c01c998f8fdea4a280d329228ce74
Merge up and generally make shadow mode be nice.

Signed-off-by: Steven Smith, sos22@xxxxxxxxx

diff -r 05a1340bc1e7 -r 990c009015e8 
linux-2.6-xen-sparse/arch/xen/i386/kernel/cpu/common.c
--- a/linux-2.6-xen-sparse/arch/xen/i386/kernel/cpu/common.c    Thu Jan 26 
18:52:18 2006
+++ b/linux-2.6-xen-sparse/arch/xen/i386/kernel/cpu/common.c    Fri Jan 27 
20:23:06 2006
@@ -572,7 +572,7 @@
             va < gdt_descr->address + gdt_descr->size;
             va += PAGE_SIZE, f++) {
                frames[f] = virt_to_mfn(va);
-               make_lowmem_page_readonly((void *)va);
+               make_lowmem_mmu_page_readonly((void *)va);
        }
        if (HYPERVISOR_set_gdt(frames, gdt_descr->size / 8))
                BUG();
diff -r 05a1340bc1e7 -r 990c009015e8 
linux-2.6-xen-sparse/arch/xen/i386/kernel/ldt.c
--- a/linux-2.6-xen-sparse/arch/xen/i386/kernel/ldt.c   Thu Jan 26 18:52:18 2006
+++ b/linux-2.6-xen-sparse/arch/xen/i386/kernel/ldt.c   Fri Jan 27 20:23:06 2006
@@ -119,7 +119,7 @@
        if (mm->context.size) {
                if (mm == current->active_mm)
                        clear_LDT();
-               make_pages_writable(mm->context.ldt, 
+               make_pages_writable(mm->context.ldt,
                                    (mm->context.size * LDT_ENTRY_SIZE) /
                                    PAGE_SIZE);
                if (mm->context.size*LDT_ENTRY_SIZE > PAGE_SIZE)
diff -r 05a1340bc1e7 -r 990c009015e8 
linux-2.6-xen-sparse/arch/xen/i386/kernel/setup.c
--- a/linux-2.6-xen-sparse/arch/xen/i386/kernel/setup.c Thu Jan 26 18:52:18 2006
+++ b/linux-2.6-xen-sparse/arch/xen/i386/kernel/setup.c Fri Jan 27 20:23:06 2006
@@ -56,6 +56,7 @@
 #include <asm/hypervisor.h>
 #include <asm-xen/xen-public/physdev.h>
 #include <asm-xen/xen-public/memory.h>
+#include <asm-xen/features.h>
 #include "setup_arch_pre.h"
 #include <bios_ebda.h>
 
@@ -1591,6 +1592,9 @@
        rd_prompt = ((RAMDISK_FLAGS & RAMDISK_PROMPT_FLAG) != 0);
        rd_doload = ((RAMDISK_FLAGS & RAMDISK_LOAD_FLAG) != 0);
 #endif
+
+       setup_xen_features();
+
        ARCH_SETUP
        if (efi_enabled)
                efi_init();
@@ -1601,6 +1605,7 @@
 
        copy_edd();
 
+       /* Make the PFNs in the Xen hole reserved. */
        if (!MOUNT_ROOT_RDONLY)
                root_mountflags &= ~MS_RDONLY;
        init_mm.start_code = (unsigned long) _text;
@@ -1763,6 +1768,8 @@
                console_use_vt = 0;
 #endif
        }
+
+
 }
 
 static int
diff -r 05a1340bc1e7 -r 990c009015e8 
linux-2.6-xen-sparse/arch/xen/i386/mm/hypervisor.c
--- a/linux-2.6-xen-sparse/arch/xen/i386/mm/hypervisor.c        Thu Jan 26 
18:52:18 2006
+++ b/linux-2.6-xen-sparse/arch/xen/i386/mm/hypervisor.c        Fri Jan 27 
20:23:06 2006
@@ -113,6 +113,20 @@
        BUG_ON(HYPERVISOR_mmuext_op(&op, 1, NULL, DOMID_SELF) < 0);
 }
 
+unsigned long xen_pfn_hole_start(void)
+{
+       struct mmuext_op op;
+       op.cmd = MMUEXT_PFN_HOLE_BASE;
+       return HYPERVISOR_mmuext_op(&op, 1, NULL, DOMID_SELF);
+}
+
+unsigned long xen_pfn_hole_size(void)
+{
+       struct mmuext_op op;
+       op.cmd = MMUEXT_PFN_HOLE_SIZE;
+       return HYPERVISOR_mmuext_op(&op, 1, NULL, DOMID_SELF);
+}
+
 void xen_new_user_pt(unsigned long ptr)
 {
        struct mmuext_op op;
@@ -265,6 +279,7 @@
  */
 unsigned long *contiguous_bitmap;
 
+#ifndef CONFIG_XEN_SHADOW_MODE
 static void contiguous_bitmap_set(
        unsigned long first_page, unsigned long nr_pages)
 {
@@ -315,9 +330,9 @@
        pud_t         *pud; 
        pmd_t         *pmd;
        pte_t         *pte;
-       unsigned long  mfn, i, flags;
+       unsigned long  frame, i, flags;
        struct xen_memory_reservation reservation = {
-               .extent_start = &mfn,
+               .extent_start = &frame,
                .nr_extents   = 1,
                .extent_order = 0,
                .domid        = DOMID_SELF
@@ -333,7 +348,7 @@
                pud = pud_offset(pgd, (vstart + (i*PAGE_SIZE)));
                pmd = pmd_offset(pud, (vstart + (i*PAGE_SIZE)));
                pte = pte_offset_kernel(pmd, (vstart + (i*PAGE_SIZE)));
-               mfn = pte_mfn(*pte);
+               frame = pte_mfn(*pte);
                BUG_ON(HYPERVISOR_update_va_mapping(
                        vstart + (i*PAGE_SIZE), __pte_ma(0), 0));
                set_phys_to_machine((__pa(vstart)>>PAGE_SHIFT)+i,
@@ -345,7 +360,8 @@
        /* 2. Get a new contiguous memory extent. */
        reservation.extent_order = order;
        reservation.address_bits = address_bits;
-       if (HYPERVISOR_memory_op(XENMEM_increase_reservation,
+       frame = __pa(vstart) >> PAGE_SHIFT;
+       if (HYPERVISOR_memory_op(XENMEM_populate_physmap,
                                 &reservation) != 1)
                goto fail;
 
@@ -353,9 +369,8 @@
        for (i = 0; i < (1<<order); i++) {
                BUG_ON(HYPERVISOR_update_va_mapping(
                        vstart + (i*PAGE_SIZE),
-                       pfn_pte_ma(mfn+i, PAGE_KERNEL), 0));
-               xen_machphys_update(mfn+i, (__pa(vstart)>>PAGE_SHIFT)+i);
-               set_phys_to_machine((__pa(vstart)>>PAGE_SHIFT)+i, mfn+i);
+                       pfn_pte_ma(frame+i, PAGE_KERNEL), 0));
+               set_phys_to_machine((__pa(vstart)>>PAGE_SHIFT)+i, frame+i);
        }
 
        flush_tlb_all();
@@ -371,13 +386,13 @@
        reservation.address_bits = 0;
 
        for (i = 0; i < (1<<order); i++) {
+               frame = (__pa(vstart) >> PAGE_SHIFT) + i;
                BUG_ON(HYPERVISOR_memory_op(
-                       XENMEM_increase_reservation, &reservation) != 1);
+                       XENMEM_populate_physmap, &reservation) != 1);
                BUG_ON(HYPERVISOR_update_va_mapping(
                        vstart + (i*PAGE_SIZE),
-                       pfn_pte_ma(mfn, PAGE_KERNEL), 0));
-               xen_machphys_update(mfn, (__pa(vstart)>>PAGE_SHIFT)+i);
-               set_phys_to_machine((__pa(vstart)>>PAGE_SHIFT)+i, mfn);
+                       pfn_pte_ma(frame, PAGE_KERNEL), 0));
+               set_phys_to_machine((__pa(vstart)>>PAGE_SHIFT)+i, frame);
        }
 
        flush_tlb_all();
@@ -393,9 +408,9 @@
        pud_t         *pud; 
        pmd_t         *pmd;
        pte_t         *pte;
-       unsigned long  mfn, i, flags;
+       unsigned long  frame, i, flags;
        struct xen_memory_reservation reservation = {
-               .extent_start = &mfn,
+               .extent_start = &frame,
                .nr_extents   = 1,
                .extent_order = 0,
                .domid        = DOMID_SELF
@@ -413,7 +428,7 @@
                pud = pud_offset(pgd, (vstart + (i*PAGE_SIZE)));
                pmd = pmd_offset(pud, (vstart + (i*PAGE_SIZE)));
                pte = pte_offset_kernel(pmd, (vstart + (i*PAGE_SIZE)));
-               mfn = pte_mfn(*pte);
+               frame = pte_mfn(*pte);
                BUG_ON(HYPERVISOR_update_va_mapping(
                        vstart + (i*PAGE_SIZE), __pte_ma(0), 0));
                set_phys_to_machine((__pa(vstart)>>PAGE_SHIFT)+i,
@@ -424,19 +439,32 @@
 
        /* 2. Map new pages in place of old pages. */
        for (i = 0; i < (1<<order); i++) {
+               frame = (__pa(vstart) >> PAGE_SHIFT) + i;
                BUG_ON(HYPERVISOR_memory_op(
-                       XENMEM_increase_reservation, &reservation) != 1);
+                       XENMEM_populate_physmap, &reservation) != 1);
                BUG_ON(HYPERVISOR_update_va_mapping(
                        vstart + (i*PAGE_SIZE),
-                       pfn_pte_ma(mfn, PAGE_KERNEL), 0));
-               xen_machphys_update(mfn, (__pa(vstart)>>PAGE_SHIFT)+i);
-               set_phys_to_machine((__pa(vstart)>>PAGE_SHIFT)+i, mfn);
+                       pfn_pte_ma(frame, PAGE_KERNEL), 0));
+               set_phys_to_machine((__pa(vstart)>>PAGE_SHIFT)+i, frame);
        }
 
        flush_tlb_all();
 
        balloon_unlock(flags);
 }
+#else
+int xen_create_contiguous_region(
+       unsigned long vstat, unsigned int order, unsigned int address_bits)
+{
+       if (order >= 1)
+               BUG();
+       return 0;
+}
+
+void xen_destroy_contiguous_region(unsigned long vstart, unsigned int order)
+{
+}
+#endif
 
 #ifdef __i386__
 int write_ldt_entry(void *ldt, int entry, __u32 entry_a, __u32 entry_b)
diff -r 05a1340bc1e7 -r 990c009015e8 
linux-2.6-xen-sparse/arch/xen/i386/mm/init.c
--- a/linux-2.6-xen-sparse/arch/xen/i386/mm/init.c      Thu Jan 26 18:52:18 2006
+++ b/linux-2.6-xen-sparse/arch/xen/i386/mm/init.c      Fri Jan 27 20:23:06 2006
@@ -68,7 +68,7 @@
                
 #ifdef CONFIG_X86_PAE
        pmd_table = (pmd_t *) alloc_bootmem_low_pages(PAGE_SIZE);
-       make_lowmem_page_readonly(pmd_table);
+       make_lowmem_mmu_page_readonly(pmd_table);
        set_pgd(pgd, __pgd(__pa(pmd_table) | _PAGE_PRESENT));
        pud = pud_offset(pgd, 0);
        if (pmd_table != pmd_offset(pud, 0)) 
@@ -89,7 +89,7 @@
 {
        if (pmd_none(*pmd)) {
                pte_t *page_table = (pte_t *) 
alloc_bootmem_low_pages(PAGE_SIZE);
-               make_lowmem_page_readonly(page_table);
+               make_lowmem_mmu_page_readonly(page_table);
                set_pmd(pmd, __pmd(__pa(page_table) | _PAGE_TABLE));
                if (page_table != pte_offset_kernel(pmd, 0))
                        BUG();  
@@ -643,6 +643,17 @@
                set_page_count(&mem_map[pfn], 1);
                totalram_pages++;
        }
+
+        /* Make the Xen hole reserved. */
+        unsigned long hole_start, hole_size;
+        hole_size = xen_pfn_hole_size();
+        hole_start = xen_pfn_hole_start();
+        for (pfn = hole_start; pfn < hole_start + hole_size; pfn++) {
+                printk("<0>Reserve %lx for hole.\n",
+                       pfn);
+                SetPageReserved(pfn_to_page(pfn));
+                BUG_ON(!PageReserved(pfn_to_page(pfn)));
+        }
 
        reservedpages = 0;
        for (tmp = 0; tmp < max_low_pfn; tmp++)
diff -r 05a1340bc1e7 -r 990c009015e8 
linux-2.6-xen-sparse/arch/xen/i386/mm/pgtable.c
--- a/linux-2.6-xen-sparse/arch/xen/i386/mm/pgtable.c   Thu Jan 26 18:52:18 2006
+++ b/linux-2.6-xen-sparse/arch/xen/i386/mm/pgtable.c   Fri Jan 27 20:23:06 2006
@@ -24,6 +24,7 @@
 #include <asm/io.h>
 #include <asm/mmu_context.h>
 
+#include <asm-xen/features.h>
 #include <asm-xen/foreign_page.h>
 #include <asm/hypervisor.h>
 
@@ -198,7 +199,7 @@
 {
        pte_t *pte = (pte_t 
*)__get_free_page(GFP_KERNEL|__GFP_REPEAT|__GFP_ZERO);
        if (pte)
-               make_lowmem_page_readonly(pte);
+               make_lowmem_mmu_page_readonly(pte);
        return pte;
 }
 
@@ -316,6 +317,7 @@
 
        pgd_test_and_unpin(pgd);
 
+       memset(pgd, 0, 10);
        if (PTRS_PER_PMD == 1 || !pgd)
                return pgd;
 
@@ -344,7 +346,7 @@
                        pmd_t *kpmd = pmd_offset(kpud, v);
                        pmd_t *pmd = (void *)__va(pgd_val(pgd[i])-1);
                        memcpy(pmd, kpmd, PAGE_SIZE);
-                       make_lowmem_page_readonly(pmd);
+                       make_lowmem_mmu_page_readonly(pmd);
                }
                pgd_list_add(pgd);
                spin_unlock_irqrestore(&pgd_lock, flags);
@@ -378,7 +380,7 @@
                        spin_unlock_irqrestore(&pgd_lock, flags);
                        for (i = USER_PTRS_PER_PGD; i < PTRS_PER_PGD; i++) {
                                pmd_t *pmd = (void *)__va(pgd_val(pgd[i])-1);
-                               make_lowmem_page_writable(pmd);
+                               make_lowmem_mmu_page_writable(pmd);
                                memset(pmd, 0, PTRS_PER_PMD*sizeof(pmd_t));
                                kmem_cache_free(pmd_cache, pmd);
                        }
@@ -388,27 +390,37 @@
        kmem_cache_free(pgd_cache, pgd);
 }
 
-#ifndef CONFIG_XEN_SHADOW_MODE
+
 void make_lowmem_page_readonly(void *va)
 {
-       pte_t *pte = virt_to_ptep(va);
-       int rc = HYPERVISOR_update_va_mapping(
+       pte_t *pte;
+       int rc;
+
+       pte = virt_to_ptep(va);
+       rc = HYPERVISOR_update_va_mapping(
                (unsigned long)va, pte_wrprotect(*pte), 0);
        BUG_ON(rc);
 }
 
 void make_lowmem_page_writable(void *va)
 {
-       pte_t *pte = virt_to_ptep(va);
-       int rc = HYPERVISOR_update_va_mapping(
+       pte_t *pte;
+       int rc;
+
+       pte = virt_to_ptep(va);
+       rc = HYPERVISOR_update_va_mapping(
                (unsigned long)va, pte_mkwrite(*pte), 0);
        BUG_ON(rc);
 }
 
+
 void make_page_readonly(void *va)
 {
-       pte_t *pte = virt_to_ptep(va);
-       int rc = HYPERVISOR_update_va_mapping(
+       pte_t *pte;
+       int rc;
+
+       pte = virt_to_ptep(va);
+       rc = HYPERVISOR_update_va_mapping(
                (unsigned long)va, pte_wrprotect(*pte), 0);
        if (rc) /* fallback? */
                xen_l1_entry_update(pte, pte_wrprotect(*pte));
@@ -426,8 +438,11 @@
 
 void make_page_writable(void *va)
 {
-       pte_t *pte = virt_to_ptep(va);
-       int rc = HYPERVISOR_update_va_mapping(
+       pte_t *pte;
+       int rc;
+
+       pte = virt_to_ptep(va);
+       rc = HYPERVISOR_update_va_mapping(
                (unsigned long)va, pte_mkwrite(*pte), 0);
        if (rc) /* fallback? */
                xen_l1_entry_update(pte, pte_mkwrite(*pte));
@@ -441,7 +456,7 @@
        }
 }
 
-void make_pages_readonly(void *va, unsigned int nr)
+void make_pages_readonly(void *va, unsigned nr)
 {
        while (nr-- != 0) {
                make_page_readonly(va);
@@ -449,14 +464,57 @@
        }
 }
 
-void make_pages_writable(void *va, unsigned int nr)
+void make_pages_writable(void *va, unsigned nr)
 {
        while (nr-- != 0) {
                make_page_writable(va);
                va = (void *)((unsigned long)va + PAGE_SIZE);
        }
 }
-#endif /* CONFIG_XEN_SHADOW_MODE */
+
+#ifndef CONFIG_XEN_SHADOW_MODE
+void make_lowmem_mmu_page_readonly(void *va)
+{
+       if (xen_feature(writable_mmu_structures))
+               return;
+       make_lowmem_page_readonly(va);
+}
+
+void make_lowmem_mmu_page_writable(void *va)
+{
+       if (xen_feature(writable_mmu_structures))
+               return;
+       make_lowmem_page_writable(va);
+}
+
+void make_mmu_page_readonly(void *va)
+{
+       if (xen_feature(writable_mmu_structures))
+               return;
+       make_page_readonly(va);
+}
+
+void make_mmu_page_writable(void *va)
+{
+       if (xen_feature(writable_mmu_structures))
+               return;
+       make_page_writable(va);
+}
+
+void make_mmu_pages_readonly(void *va, unsigned int nr)
+{
+       if (xen_feature(writable_mmu_structures))
+               return;
+       make_pages_readonly(va, nr);
+}
+
+void make_mmu_pages_writable(void *va, unsigned int nr)
+{
+       if (xen_feature(writable_mmu_structures))
+               return;
+       make_pages_writable(va, nr);
+}
+#endif
 
 static inline void pgd_walk_set_prot(void *pt, pgprot_t flags)
 {
@@ -507,7 +565,8 @@
 
 static void __pgd_pin(pgd_t *pgd)
 {
-       pgd_walk(pgd, PAGE_KERNEL_RO);
+       if (!xen_feature(writable_mmu_structures))
+               pgd_walk(pgd, PAGE_KERNEL_RO);
        xen_pgd_pin(__pa(pgd));
        set_bit(PG_pinned, &virt_to_page(pgd)->flags);
 }
@@ -515,7 +574,8 @@
 static void __pgd_unpin(pgd_t *pgd)
 {
        xen_pgd_unpin(__pa(pgd));
-       pgd_walk(pgd, PAGE_KERNEL);
+       if (!xen_feature(writable_mmu_structures))
+               pgd_walk(pgd, PAGE_KERNEL);
        clear_bit(PG_pinned, &virt_to_page(pgd)->flags);
 }
 
diff -r 05a1340bc1e7 -r 990c009015e8 
linux-2.6-xen-sparse/arch/xen/kernel/Makefile
--- a/linux-2.6-xen-sparse/arch/xen/kernel/Makefile     Thu Jan 26 18:52:18 2006
+++ b/linux-2.6-xen-sparse/arch/xen/kernel/Makefile     Fri Jan 27 20:23:06 2006
@@ -11,7 +11,7 @@
 
 extra-y += vmlinux.lds
 
-obj-y   := evtchn.o reboot.o gnttab.o
+obj-y   := evtchn.o reboot.o gnttab.o features.o
 
 obj-$(CONFIG_PROC_FS) += xen_proc.o
 obj-$(CONFIG_NET)     += skbuff.o
diff -r 05a1340bc1e7 -r 990c009015e8 
linux-2.6-xen-sparse/arch/xen/kernel/gnttab.c
--- a/linux-2.6-xen-sparse/arch/xen/kernel/gnttab.c     Thu Jan 26 18:52:18 2006
+++ b/linux-2.6-xen-sparse/arch/xen/kernel/gnttab.c     Fri Jan 27 20:23:06 2006
@@ -201,25 +201,22 @@
 }
 
 int
-gnttab_grant_foreign_transfer(domid_t domid)
+gnttab_grant_foreign_transfer(domid_t domid, unsigned long pfn)
 {
        int ref;
 
        if (unlikely((ref = get_free_entry()) == -1))
                return -ENOSPC;
-
-       shared[ref].frame = 0;
-       shared[ref].domid = domid;
-       wmb();
-       shared[ref].flags = GTF_accept_transfer;
+       gnttab_grant_foreign_transfer_ref(ref, domid, pfn);
 
        return ref;
 }
 
 void
-gnttab_grant_foreign_transfer_ref(grant_ref_t ref, domid_t domid)
-{
-       shared[ref].frame = 0;
+gnttab_grant_foreign_transfer_ref(grant_ref_t ref, domid_t domid,
+                                 unsigned long pfn)
+{
+       shared[ref].frame = pfn;
        shared[ref].domid = domid;
        wmb();
        shared[ref].flags = GTF_accept_transfer;
diff -r 05a1340bc1e7 -r 990c009015e8 
linux-2.6-xen-sparse/arch/xen/kernel/reboot.c
--- a/linux-2.6-xen-sparse/arch/xen/kernel/reboot.c     Thu Jan 26 18:52:18 2006
+++ b/linux-2.6-xen-sparse/arch/xen/kernel/reboot.c     Fri Jan 27 20:23:06 2006
@@ -74,6 +74,7 @@
 #endif
 
 
+#ifndef CONFIG_XEN_SHADOW_MODE
 static int __do_suspend(void *ignore)
 {
        int i, j, k, fpp;
@@ -216,6 +217,13 @@
 
        return err;
 }
+#else
+static int __do_suspend(void *ignore)
+{
+       printk(KERN_WARNING "Don't do suspend in shadow mode\n");
+       return -EOPNOTSUPP;
+}
+#endif
 
 static int shutdown_process(void *__unused)
 {
diff -r 05a1340bc1e7 -r 990c009015e8 
linux-2.6-xen-sparse/arch/xen/x86_64/kernel/ldt.c
--- a/linux-2.6-xen-sparse/arch/xen/x86_64/kernel/ldt.c Thu Jan 26 18:52:18 2006
+++ b/linux-2.6-xen-sparse/arch/xen/x86_64/kernel/ldt.c Fri Jan 27 20:23:06 2006
@@ -65,8 +65,8 @@
 
                preempt_disable();
 #endif
-               make_pages_readonly(pc->ldt, (pc->size * LDT_ENTRY_SIZE) /
-                                   PAGE_SIZE);
+               make_mmu_pages_readonly(pc->ldt, (pc->size * LDT_ENTRY_SIZE) /
+                                       PAGE_SIZE);
                load_LDT(pc);
 #ifdef CONFIG_SMP
                mask = cpumask_of_cpu(smp_processor_id());
@@ -76,7 +76,7 @@
 #endif
        }
        if (oldsize) {
-               make_pages_writable(oldldt, (oldsize * LDT_ENTRY_SIZE) /
+               make_mmu_pages_writable(oldldt, (oldsize * LDT_ENTRY_SIZE) /
                        PAGE_SIZE);
                if (oldsize*LDT_ENTRY_SIZE > PAGE_SIZE)
                        vfree(oldldt);
@@ -92,8 +92,8 @@
        if (err < 0)
                return err;
        memcpy(new->ldt, old->ldt, old->size*LDT_ENTRY_SIZE);
-       make_pages_readonly(new->ldt, (new->size * LDT_ENTRY_SIZE) /
-                           PAGE_SIZE);
+       make_mmu_pages_readonly(new->ldt, (new->size * LDT_ENTRY_SIZE) /
+                               PAGE_SIZE);
        return 0;
 }
 
@@ -131,9 +131,9 @@
        if (mm->context.size) {
                if (mm == current->active_mm)
                        clear_LDT();
-               make_pages_writable(mm->context.ldt, 
-                                   (mm->context.size * LDT_ENTRY_SIZE) /
-                                   PAGE_SIZE);
+               make_mmu_pages_writable(mm->context.ldt,
+                                       (mm->context.size * LDT_ENTRY_SIZE) /
+                                       PAGE_SIZE);
                if (mm->context.size*LDT_ENTRY_SIZE > PAGE_SIZE)
                        vfree(mm->context.ldt);
                else
diff -r 05a1340bc1e7 -r 990c009015e8 
linux-2.6-xen-sparse/arch/xen/x86_64/kernel/setup.c
--- a/linux-2.6-xen-sparse/arch/xen/x86_64/kernel/setup.c       Thu Jan 26 
18:52:18 2006
+++ b/linux-2.6-xen-sparse/arch/xen/x86_64/kernel/setup.c       Fri Jan 27 
20:23:06 2006
@@ -63,6 +63,7 @@
 #include "setup_arch_pre.h"
 #include <asm/hypervisor.h>
 #include <asm-xen/xen-public/nmi.h>
+#include <asm-xen/features.h>
 #define PFN_UP(x)       (((x) + PAGE_SIZE-1) >> PAGE_SHIFT)
 #define PFN_PHYS(x)     ((x) << PAGE_SHIFT)
 #define end_pfn_map end_pfn
@@ -587,6 +588,8 @@
 
 #endif
 
+       setup_xen_features();
+
        HYPERVISOR_vm_assist(VMASST_CMD_enable,
                             VMASST_TYPE_writable_pagetables);
 
diff -r 05a1340bc1e7 -r 990c009015e8 
linux-2.6-xen-sparse/arch/xen/x86_64/kernel/setup64.c
--- a/linux-2.6-xen-sparse/arch/xen/x86_64/kernel/setup64.c     Thu Jan 26 
18:52:18 2006
+++ b/linux-2.6-xen-sparse/arch/xen/x86_64/kernel/setup64.c     Fri Jan 27 
20:23:06 2006
@@ -141,7 +141,7 @@
             va < gdt_descr->address + gdt_descr->size;
             va += PAGE_SIZE, f++) {
                frames[f] = virt_to_mfn(va);
-               make_page_readonly((void *)va);
+               make_mmu_page_readonly((void *)va);
        }
        if (HYPERVISOR_set_gdt(frames, gdt_descr->size /
                                sizeof (struct desc_struct)))
diff -r 05a1340bc1e7 -r 990c009015e8 
linux-2.6-xen-sparse/arch/xen/x86_64/mm/init.c
--- a/linux-2.6-xen-sparse/arch/xen/x86_64/mm/init.c    Thu Jan 26 18:52:18 2006
+++ b/linux-2.6-xen-sparse/arch/xen/x86_64/mm/init.c    Fri Jan 27 20:23:06 2006
@@ -40,6 +40,8 @@
 #include <asm/proto.h>
 #include <asm/smp.h>
 
+#include <asm-xen/features.h>
+
 #ifndef Dprintk
 #define Dprintk(x...)
 #endif
@@ -66,12 +68,15 @@
        (((mfn_to_pfn((addr) >> PAGE_SHIFT)) << PAGE_SHIFT) +   \
        __START_KERNEL_map)))
 
-static void early_make_page_readonly(void *va)
+static void early_make_mmu_page_readonly(void *va)
 {
        unsigned long addr, _va = (unsigned long)va;
        pte_t pte, *ptep;
        unsigned long *page = (unsigned long *) init_level4_pgt;
 
+       if (xen_feature(writable_mmu_structures))
+               return;
+
        addr = (unsigned long) page[pgd_index(_va)];
        addr_to_page(addr, page);
 
@@ -88,10 +93,13 @@
                BUG();
 }
 
-void make_page_readonly(void *va)
+void make_mmu_page_readonly(void *va)
 {
        pgd_t *pgd; pud_t *pud; pmd_t *pmd; pte_t pte, *ptep;
        unsigned long addr = (unsigned long) va;
+
+       if (xen_feature(writable_mmu_structures))
+               return;
 
        pgd = pgd_offset_k(addr);
        pud = pud_offset(pgd, addr);
@@ -103,13 +111,16 @@
                xen_l1_entry_update(ptep, pte); /* fallback */
 
        if ((addr >= VMALLOC_START) && (addr < VMALLOC_END))
-               make_page_readonly(__va(pte_pfn(pte) << PAGE_SHIFT));
-}
-
-void make_page_writable(void *va)
+               make_mmu_page_readonly(__va(pte_pfn(pte) << PAGE_SHIFT));
+}
+
+void make_mmu_page_writable(void *va)
 {
        pgd_t *pgd; pud_t *pud; pmd_t *pmd; pte_t pte, *ptep;
        unsigned long addr = (unsigned long) va;
+
+       if (xen_feature(writable_mmu_structures))
+               return;
 
        pgd = pgd_offset_k(addr);
        pud = pud_offset(pgd, addr);
@@ -121,21 +132,26 @@
                xen_l1_entry_update(ptep, pte); /* fallback */
 
        if ((addr >= VMALLOC_START) && (addr < VMALLOC_END))
-               make_page_writable(__va(pte_pfn(pte) << PAGE_SHIFT));
-}
-
-void make_pages_readonly(void *va, unsigned nr)
-{
+               make_mmu_page_writable(__va(pte_pfn(pte) << PAGE_SHIFT));
+}
+
+void make_mmu_pages_readonly(void *va, unsigned nr)
+{
+       if (xen_feature(writable_mmu_structures))
+               return;
+
        while (nr-- != 0) {
-               make_page_readonly(va);
+               make_mmu_page_readonly(va);
                va = (void*)((unsigned long)va + PAGE_SIZE);
        }
 }
 
-void make_pages_writable(void *va, unsigned nr)
-{
+void make_mmu_pages_writable(void *va, unsigned nr)
+{
+       if (xen_feature(writable_mmu_structures))
+               return;
        while (nr-- != 0) {
-               make_page_writable(va);
+               make_mmu_page_writable(va);
                va = (void*)((unsigned long)va + PAGE_SIZE);
        }
 }
@@ -223,7 +239,7 @@
        pud = (user_mode ? pud_offset_u(vaddr) : pud_offset(pgd, vaddr));
        if (pud_none(*pud)) {
                pmd = (pmd_t *) spp_getpage(); 
-               make_page_readonly(pmd);
+               make_mmu_page_readonly(pmd);
                xen_pmd_pin(__pa(pmd));
                set_pud(pud, __pud(__pa(pmd) | _KERNPG_TABLE | _PAGE_USER));
                if (pmd != pmd_offset(pud, 0)) {
@@ -234,7 +250,7 @@
        pmd = pmd_offset(pud, vaddr);
        if (pmd_none(*pmd)) {
                pte = (pte_t *) spp_getpage();
-               make_page_readonly(pte);
+               make_mmu_page_readonly(pte);
                xen_pte_pin(__pa(pte));
                set_pmd(pmd, __pmd(__pa(pte) | _KERNPG_TABLE | _PAGE_USER));
                if (pte != pte_offset_kernel(pmd, 0)) {
@@ -276,7 +292,7 @@
        if (pud_none(*pud)) {
 
                pmd = (pmd_t *) spp_getpage(); 
-               make_page_readonly(pmd);
+               make_mmu_page_readonly(pmd);
                xen_pmd_pin(__pa(pmd));
 
                set_pud(pud, __pud(__pa(pmd) | _KERNPG_TABLE | _PAGE_USER));
@@ -290,7 +306,7 @@
 
        if (pmd_none(*pmd)) {
                pte = (pte_t *) spp_getpage();
-               make_page_readonly(pte);  
+               make_mmu_page_readonly(pte);
                xen_pte_pin(__pa(pte));
 
                set_pmd(pmd, __pmd(__pa(pte) | _KERNPG_TABLE | _PAGE_USER));
@@ -384,6 +400,9 @@
 static inline int make_readonly(unsigned long paddr)
 {
        int readonly = 0;
+
+       if (xen_feature(writable_mmu_structures))
+               return 0;
 
        /* Make old and new page tables read-only. */
        if ((paddr >= (xen_start_info->pt_base - __START_KERNEL_map))
@@ -419,7 +438,7 @@
                } 
 
                pmd = alloc_static_page(&pmd_phys);
-               early_make_page_readonly(pmd);
+               early_make_mmu_page_readonly(pmd);
                xen_pmd_pin(pmd_phys);
                set_pud(pud, __pud(pmd_phys | _KERNPG_TABLE));
                for (j = 0; j < PTRS_PER_PMD; pmd++, j++) {
@@ -448,7 +467,7 @@
                                __set_pte(pte, __pte(paddr | _KERNPG_TABLE));
                        }
                        pte = pte_save;
-                       early_make_page_readonly(pte);  
+                       early_make_mmu_page_readonly(pte);
                        xen_pte_pin(pte_phys);
                        set_pmd(pmd, __pmd(pte_phys | _KERNPG_TABLE));
                }
@@ -497,11 +516,11 @@
                      _KERNPG_TABLE | _PAGE_USER);
        memcpy((void *)level2_kernel_pgt, page, PAGE_SIZE);
 
-       early_make_page_readonly(init_level4_pgt);
-       early_make_page_readonly(init_level4_user_pgt);
-       early_make_page_readonly(level3_kernel_pgt);
-       early_make_page_readonly(level3_user_pgt);
-       early_make_page_readonly(level2_kernel_pgt);
+       early_make_mmu_page_readonly(init_level4_pgt);
+       early_make_mmu_page_readonly(init_level4_user_pgt);
+       early_make_mmu_page_readonly(level3_kernel_pgt);
+       early_make_mmu_page_readonly(level3_user_pgt);
+       early_make_mmu_page_readonly(level2_kernel_pgt);
 
        xen_pgd_pin(__pa_symbol(init_level4_pgt));
        xen_pgd_pin(__pa_symbol(init_level4_user_pgt));
@@ -539,7 +558,7 @@
                pmd = (pmd_t *)&page[pmd_index(va)];
                if (pmd_none(*pmd)) {
                        pte_page = alloc_static_page(&phys);
-                       early_make_page_readonly(pte_page);
+                       early_make_mmu_page_readonly(pte_page);
                        xen_pte_pin(phys);
                        set_pmd(pmd, __pmd(phys | _KERNPG_TABLE | _PAGE_USER));
                } else {
@@ -586,7 +605,7 @@
        for (; start < end; start = next) {
                unsigned long pud_phys; 
                pud_t *pud = alloc_static_page(&pud_phys);
-               early_make_page_readonly(pud);
+               early_make_mmu_page_readonly(pud);
                xen_pud_pin(pud_phys);
                next = start + PGDIR_SIZE;
                if (next > end) 
@@ -791,11 +810,11 @@
                set_page_count(virt_to_page(addr), 1);
                memset((void *)(addr & ~(PAGE_SIZE-1)), 0xcc, PAGE_SIZE); 
                xen_pte_unpin(__pa(addr));
-               make_page_writable(__va(__pa(addr)));
+               make_mmu_page_writable(__va(__pa(addr)));
                /*
                 * Make pages from __PAGE_OFFSET address as well
                 */
-               make_page_writable((void *)addr);
+               make_mmu_page_writable((void *)addr);
                free_page(addr);
                totalram_pages++;
        }
diff -r 05a1340bc1e7 -r 990c009015e8 
linux-2.6-xen-sparse/drivers/xen/balloon/balloon.c
--- a/linux-2.6-xen-sparse/drivers/xen/balloon/balloon.c        Thu Jan 26 
18:52:18 2006
+++ b/linux-2.6-xen-sparse/drivers/xen/balloon/balloon.c        Fri Jan 27 
20:23:06 2006
@@ -107,9 +107,27 @@
 #define WPRINTK(fmt, args...) \
        printk(KERN_WARNING "xen_mem: " fmt, ##args)
 
+static int page_is_xen_hole(unsigned long pfn)
+{
+       static unsigned long hole_start, hole_len = -1;
+       if (hole_len == -1) {
+               hole_start = xen_pfn_hole_start();
+               hole_len = xen_pfn_hole_size();
+               printk("<0>Xen hole at [%lx,%lx).\n", hole_start,
+                      hole_start + hole_len);
+       }
+       return pfn >= hole_start && pfn < hole_start + hole_len;
+}
+
 /* balloon_append: add the given page to the balloon. */
 static void balloon_append(struct page *page)
 {
+       BUG_ON(PageReserved(page));
+       if (page_is_xen_hole(page_to_pfn(page))) {
+               printk("<0>Attempt to add reserved pfn %lx to balloon.\n",
+                      page_to_pfn(page));
+               BUG();
+       }
        /* Lowmem is re-populated first, so highmem pages go at list tail. */
        if (PageHighMem(page)) {
                list_add_tail(PAGE_TO_LIST(page), &ballooned_pages);
@@ -139,6 +157,21 @@
        return page;
 }
 
+static struct page *balloon_first_page(void)
+{
+       if (list_empty(&ballooned_pages))
+               return NULL;
+       return LIST_TO_PAGE(ballooned_pages.next);
+}
+
+static struct page *balloon_next_page(struct page *page)
+{
+       struct list_head *next = PAGE_TO_LIST(page)->next;
+       if (next == &ballooned_pages)
+               return NULL;
+       return LIST_TO_PAGE(next);
+}
+
 static void balloon_alarm(unsigned long unused)
 {
        schedule_work(&balloon_worker);
@@ -154,7 +187,7 @@
 
 static int increase_reservation(unsigned long nr_pages)
 {
-       unsigned long *mfn_list, pfn, i, flags;
+       unsigned long *frame_list, pfn, i, flags;
        struct page   *page;
        long           rc;
        struct xen_memory_reservation reservation = {
@@ -166,20 +199,28 @@
        if (nr_pages > (PAGE_SIZE / sizeof(unsigned long)))
                nr_pages = PAGE_SIZE / sizeof(unsigned long);
 
-       mfn_list = (unsigned long *)__get_free_page(GFP_KERNEL);
-       if (mfn_list == NULL)
+       frame_list = (unsigned long *)__get_free_page(GFP_KERNEL);
+       if (frame_list == NULL)
                return -ENOMEM;
 
        balloon_lock(flags);
 
-       reservation.extent_start = mfn_list;
+       page = balloon_first_page();
+       for (i = 0; i < nr_pages; i++) {
+               BUG_ON(page == NULL);
+               frame_list[i] = page_to_pfn(page);;
+               BUG_ON(page_is_xen_hole(frame_list[i]));
+               page = balloon_next_page(page);
+       }
+
+       reservation.extent_start = frame_list;
        reservation.nr_extents   = nr_pages;
        rc = HYPERVISOR_memory_op(
-               XENMEM_increase_reservation, &reservation);
+               XENMEM_populate_physmap, &reservation);
        if (rc < nr_pages) {
                int ret;
                /* We hit the Xen hard limit: reprobe. */
-               reservation.extent_start = mfn_list;
+               reservation.extent_start = frame_list;
                reservation.nr_extents   = rc;
                ret = HYPERVISOR_memory_op(XENMEM_decrease_reservation,
                                &reservation);
@@ -193,20 +234,34 @@
                BUG_ON(page == NULL);
 
                pfn = page_to_pfn(page);
+#ifndef CONFIG_XEN_SHADOW_MODE
+               /* In shadow mode, Xen handles this part for us. */
                BUG_ON(phys_to_machine_mapping_valid(pfn));
 
                /* Update P->M and M->P tables. */
-               set_phys_to_machine(pfn, mfn_list[i]);
-               xen_machphys_update(mfn_list[i], pfn);
-            
+               set_phys_to_machine(pfn, frame_list[i]);
+               xen_machphys_update(frame_list[i], pfn);
+#endif
+
+               printk("<0>Balloon allocated %lx.\n", pfn);
                /* Link back into the page tables if not highmem. */
                if (pfn < max_low_pfn) {
                        int ret;
+                       pgd_t *pgd = pgd_offset_k((unsigned long)__va(pfn << 
PAGE_SHIFT));
+                       printk("pgd is %lx.\n", *(unsigned long *)pgd);
+                       (void)copy_from_user(&ret,
+                                            (unsigned long *)__va(pfn << 
PAGE_SHIFT),
+                                            4);
                        ret = HYPERVISOR_update_va_mapping(
                                (unsigned long)__va(pfn << PAGE_SHIFT),
-                               pfn_pte_ma(mfn_list[i], PAGE_KERNEL),
+                               pfn_pte_ma(frame_list[i], PAGE_KERNEL),
                                0);
                        BUG_ON(ret);
+                       printk("<0>Rehooked va; pte now %lx.\n",
+                              *(unsigned long *)virt_to_ptep(__va(pfn << 
PAGE_SHIFT)));
+                       *(unsigned long *)__va(pfn << PAGE_SHIFT) =
+                               0xf001;
+                       printk("<0>Touched va.\n");
                }
 
                /* Relinquish the page back to the allocator. */
@@ -221,14 +276,14 @@
  out:
        balloon_unlock(flags);
 
-       free_page((unsigned long)mfn_list);
+       free_page((unsigned long)frame_list);
 
        return 0;
 }
 
 static int decrease_reservation(unsigned long nr_pages)
 {
-       unsigned long *mfn_list, pfn, i, flags;
+       unsigned long *frame_list, pfn, i, flags;
        struct page   *page;
        void          *v;
        int            need_sleep = 0;
@@ -242,8 +297,8 @@
        if (nr_pages > (PAGE_SIZE / sizeof(unsigned long)))
                nr_pages = PAGE_SIZE / sizeof(unsigned long);
 
-       mfn_list = (unsigned long *)__get_free_page(GFP_KERNEL);
-       if (mfn_list == NULL)
+       frame_list = (unsigned long *)__get_free_page(GFP_KERNEL);
+       if (frame_list == NULL)
                return -ENOMEM;
 
        for (i = 0; i < nr_pages; i++) {
@@ -254,7 +309,7 @@
                }
 
                pfn = page_to_pfn(page);
-               mfn_list[i] = pfn_to_mfn(pfn);
+               frame_list[i] = pfn_to_mfn(pfn);
 
                if (!PageHighMem(page)) {
                        v = phys_to_virt(pfn << PAGE_SHIFT);
@@ -280,12 +335,12 @@
 
        /* No more mappings: invalidate P2M and add to balloon. */
        for (i = 0; i < nr_pages; i++) {
-               pfn = mfn_to_pfn(mfn_list[i]);
+               pfn = mfn_to_pfn(frame_list[i]);
                set_phys_to_machine(pfn, INVALID_P2M_ENTRY);
                balloon_append(pfn_to_page(pfn));
        }
 
-       reservation.extent_start = mfn_list;
+       reservation.extent_start = frame_list;
        reservation.nr_extents   = nr_pages;
        ret = HYPERVISOR_memory_op(XENMEM_decrease_reservation, &reservation);
        BUG_ON(ret != nr_pages);
@@ -295,7 +350,7 @@
 
        balloon_unlock(flags);
 
-       free_page((unsigned long)mfn_list);
+       free_page((unsigned long)frame_list);
 
        return need_sleep;
 }
diff -r 05a1340bc1e7 -r 990c009015e8 
linux-2.6-xen-sparse/drivers/xen/netfront/netfront.c
--- a/linux-2.6-xen-sparse/drivers/xen/netfront/netfront.c      Thu Jan 26 
18:52:18 2006
+++ b/linux-2.6-xen-sparse/drivers/xen/netfront/netfront.c      Fri Jan 27 
20:23:06 2006
@@ -586,7 +586,8 @@
                BUG_ON((signed short)ref < 0);
                np->grant_rx_ref[id] = ref;
                gnttab_grant_foreign_transfer_ref(ref,
-                                                 np->xbdev->otherend_id);
+                                                 np->xbdev->otherend_id,
+                                                 __pa(skb->head) >> 
PAGE_SHIFT);
                RING_GET_REQUEST(&np->rx, req_prod + i)->gref = ref;
                rx_pfn_array[i] = virt_to_mfn(skb->head);
 
@@ -613,7 +614,7 @@
        reservation.domid        = DOMID_SELF;
 
        /* Tell the ballon driver what is going on. */
-       balloon_update_driver_allowance(i);
+//SOS22        balloon_update_driver_allowance(i);
 
        /* Zap PTEs and give away pages in one big multicall. */
        (void)HYPERVISOR_multicall(rx_mcl, i+1);
@@ -802,9 +803,11 @@
                np->stats.rx_bytes += rx->status;
 
                /* Remap the page. */
+#ifndef CONFIG_XEN_SHADOW_MODE
                mmu->ptr = ((maddr_t)mfn << PAGE_SHIFT) | MMU_MACHPHYS_UPDATE;
                mmu->val  = __pa(skb->head) >> PAGE_SHIFT;
                mmu++;
+#endif
                MULTI_update_va_mapping(mcl, (unsigned long)skb->head,
                                        pfn_pte_ma(mfn, PAGE_KERNEL), 0);
                mcl++;
@@ -815,7 +818,7 @@
        }
 
        /* Some pages are no longer absent... */
-       balloon_update_driver_allowance(-work_done);
+//SOS22        balloon_update_driver_allowance(-work_done);
 
        /* Do all the remapping work, and M2P updates, in one big hypercall. */
        if (likely((mcl - rx_mcl) != 0)) {
@@ -999,7 +1002,8 @@
                if ((unsigned long)np->rx_skbs[i] < __PAGE_OFFSET)
                        continue;
                gnttab_grant_foreign_transfer_ref(
-                       np->grant_rx_ref[i], np->xbdev->otherend_id);
+                       np->grant_rx_ref[i], np->xbdev->otherend_id,
+                       __pa(np->rx_skbs[i]->data) >> PAGE_SHIFT);
                RING_GET_REQUEST(&np->rx, requeue_idx)->gref =
                        np->grant_rx_ref[i];
                RING_GET_REQUEST(&np->rx, requeue_idx)->id = i;
diff -r 05a1340bc1e7 -r 990c009015e8 linux-2.6-xen-sparse/drivers/xen/util.c
--- a/linux-2.6-xen-sparse/drivers/xen/util.c   Thu Jan 26 18:52:18 2006
+++ b/linux-2.6-xen-sparse/drivers/xen/util.c   Fri Jan 27 20:23:06 2006
@@ -1,5 +1,6 @@
 #include <linux/config.h>
 #include <linux/mm.h>
+#include <linux/module.h>
 #include <linux/slab.h>
 #include <linux/vmalloc.h>
 #include <asm/uaccess.h>
@@ -31,7 +32,7 @@
 
        return area;
 }
-EXPORT_SYMBOL(alloc_vm_area);
+EXPORT_SYMBOL_GPL(alloc_vm_area);
 
 void free_vm_area(struct vm_struct *area)
 {
@@ -40,7 +41,7 @@
        BUG_ON(ret != area);
        kfree(area);
 }
-EXPORT_SYMBOL(free_vm_area);
+EXPORT_SYMBOL_GPL(free_vm_area);
 
 void lock_vm_area(struct vm_struct *area)
 {
@@ -60,13 +61,13 @@
        for (i = 0; i < area->size; i += PAGE_SIZE)
                (void)__get_user(c, (char __user *)area->addr + i);
 }
-EXPORT_SYMBOL(lock_vm_area);
+EXPORT_SYMBOL_GPL(lock_vm_area);
 
 void unlock_vm_area(struct vm_struct *area)
 {
        preempt_enable();
 }
-EXPORT_SYMBOL(unlock_vm_area);
+EXPORT_SYMBOL_GPL(unlock_vm_area);
 
 /*
  * Local variables:
diff -r 05a1340bc1e7 -r 990c009015e8 
linux-2.6-xen-sparse/include/asm-xen/asm-i386/hypervisor.h
--- a/linux-2.6-xen-sparse/include/asm-xen/asm-i386/hypervisor.h        Thu Jan 
26 18:52:18 2006
+++ b/linux-2.6-xen-sparse/include/asm-xen/asm-i386/hypervisor.h        Fri Jan 
27 20:23:06 2006
@@ -101,6 +101,9 @@
 void xen_set_ldt(unsigned long ptr, unsigned long bytes);
 void xen_machphys_update(unsigned long mfn, unsigned long pfn);
 
+unsigned long xen_pfn_hole_start(void);
+unsigned long xen_pfn_hole_size(void);
+
 #ifdef CONFIG_SMP
 #include <linux/cpumask.h>
 void xen_tlb_flush_all(void);
diff -r 05a1340bc1e7 -r 990c009015e8 
linux-2.6-xen-sparse/include/asm-xen/asm-i386/page.h
--- a/linux-2.6-xen-sparse/include/asm-xen/asm-i386/page.h      Thu Jan 26 
18:52:18 2006
+++ b/linux-2.6-xen-sparse/include/asm-xen/asm-i386/page.h      Fri Jan 27 
20:23:06 2006
@@ -59,8 +59,18 @@
 #define clear_user_page(page, vaddr, pg)       clear_page(page)
 #define copy_user_page(to, from, vaddr, pg)    copy_page(to, from)
 
+/* Definitions for machine and pseudophysical addresses. */
+#ifdef CONFIG_X86_PAE
+typedef unsigned long long paddr_t;
+typedef unsigned long long maddr_t;
+#else
+typedef unsigned long paddr_t;
+typedef unsigned long maddr_t;
+#endif
+
 /**** MACHINE <-> PHYSICAL CONVERSION MACROS ****/
 #define INVALID_P2M_ENTRY      (~0UL)
+#ifndef CONFIG_XEN_SHADOW_MODE
 #define FOREIGN_FRAME(m)       ((m) | (1UL<<31))
 extern unsigned long *phys_to_machine_mapping;
 #define pfn_to_mfn(pfn)        \
@@ -93,15 +103,6 @@
        phys_to_machine_mapping[pfn] = mfn;
 }
 
-/* Definitions for machine and pseudophysical addresses. */
-#ifdef CONFIG_X86_PAE
-typedef unsigned long long paddr_t;
-typedef unsigned long long maddr_t;
-#else
-typedef unsigned long paddr_t;
-typedef unsigned long maddr_t;
-#endif
-
 static inline maddr_t phys_to_machine(paddr_t phys)
 {
        maddr_t machine = pfn_to_mfn(phys >> PAGE_SHIFT);
@@ -114,7 +115,16 @@
        phys = (phys << PAGE_SHIFT) | (machine & ~PAGE_MASK);
        return phys;
 }
-
+#else
+#define pfn_to_mfn(p) (p)
+#define mfn_to_pfn(m) (m)
+#define phys_to_machine(p) (p)
+#define machine_to_phys(m) (m)
+static inline void set_phys_to_machine(unsigned long pfn, unsigned long mfn)
+{
+       BUG_ON(pfn != mfn && mfn != INVALID_P2M_ENTRY);
+}
+#endif
 /*
  * These are used to make use of C type-checking..
  */
diff -r 05a1340bc1e7 -r 990c009015e8 
linux-2.6-xen-sparse/include/asm-xen/asm-i386/pgalloc.h
--- a/linux-2.6-xen-sparse/include/asm-xen/asm-i386/pgalloc.h   Thu Jan 26 
18:52:18 2006
+++ b/linux-2.6-xen-sparse/include/asm-xen/asm-i386/pgalloc.h   Fri Jan 27 
20:23:06 2006
@@ -42,7 +42,7 @@
 static inline void pte_free_kernel(pte_t *pte)
 {
        free_page((unsigned long)pte);
-       make_page_writable(pte);
+       make_mmu_page_writable(pte);
 }
 
 extern void pte_free(struct page *pte);
diff -r 05a1340bc1e7 -r 990c009015e8 
linux-2.6-xen-sparse/include/asm-xen/asm-i386/pgtable-2level.h
--- a/linux-2.6-xen-sparse/include/asm-xen/asm-i386/pgtable-2level.h    Thu Jan 
26 18:52:18 2006
+++ b/linux-2.6-xen-sparse/include/asm-xen/asm-i386/pgtable-2level.h    Fri Jan 
27 20:23:06 2006
@@ -64,7 +64,7 @@
 ({                                                                     \
        unsigned long mfn = pte_mfn(_pte);                              \
        unsigned long pfn = mfn_to_pfn(mfn);                            \
-       if ((pfn >= max_mapnr) || (phys_to_machine_mapping[pfn] != mfn))\
+       if ((pfn >= max_mapnr) || (pfn_to_mfn(pfn) != mfn))             \
                pfn = max_mapnr; /* special: force !pfn_valid() */      \
        pfn;                                                            \
 })
diff -r 05a1340bc1e7 -r 990c009015e8 
linux-2.6-xen-sparse/include/asm-xen/asm-i386/pgtable-3level.h
--- a/linux-2.6-xen-sparse/include/asm-xen/asm-i386/pgtable-3level.h    Thu Jan 
26 18:52:18 2006
+++ b/linux-2.6-xen-sparse/include/asm-xen/asm-i386/pgtable-3level.h    Fri Jan 
27 20:23:06 2006
@@ -149,7 +149,7 @@
 ({                                                                     \
        unsigned long mfn = pte_mfn(_pte);                              \
        unsigned long pfn = mfn_to_pfn(mfn);                            \
-       if ((pfn >= max_mapnr) || (phys_to_machine_mapping[pfn] != mfn))\
+       if ((pfn >= max_mapnr) || (pfn_to_mfn(pfn) != mfn))             \
                pfn = max_mapnr; /* special: force !pfn_valid() */      \
        pfn;                                                            \
 })
diff -r 05a1340bc1e7 -r 990c009015e8 
linux-2.6-xen-sparse/include/asm-xen/asm-i386/pgtable.h
--- a/linux-2.6-xen-sparse/include/asm-xen/asm-i386/pgtable.h   Thu Jan 26 
18:52:18 2006
+++ b/linux-2.6-xen-sparse/include/asm-xen/asm-i386/pgtable.h   Fri Jan 27 
20:23:06 2006
@@ -412,20 +412,26 @@
        ptep_set_access_flags(__vma, __address, __ptep, __entry, 1);    \
 } while (0)
 
-#ifndef CONFIG_XEN_SHADOW_MODE
 void make_lowmem_page_readonly(void *va);
 void make_lowmem_page_writable(void *va);
 void make_page_readonly(void *va);
 void make_page_writable(void *va);
 void make_pages_readonly(void *va, unsigned int nr);
 void make_pages_writable(void *va, unsigned int nr);
-#else
-#define make_lowmem_page_readonly(_va) ((void)0)
-#define make_lowmem_page_writable(_va) ((void)0)
-#define make_page_readonly(_va)        ((void)0)
-#define make_page_writable(_va)        ((void)0)
-#define make_pages_readonly(_va, _nr)  ((void)0)
-#define make_pages_writable(_va, _nr)  ((void)0)
+#ifndef CONFIG_XEN_SHADOW_MODE
+void make_lowmem_mmu_page_readonly(void *va);
+void make_lowmem_mmu_page_writable(void *va);
+void make_mmu_page_readonly(void *va);
+void make_mmu_page_writable(void *va);
+void make_mmu_pages_readonly(void *va, unsigned int nr);
+void make_mmu_pages_writable(void *va, unsigned int nr);
+#else
+#define make_lowmem_mmu_page_readonly(_va) ((void)0)
+#define make_lowmem_mmu_page_writable(_va)     ((void)0)
+#define make_mmu_page_readonly(_va)        ((void)0)
+#define make_mmu_page_writable(_va)            ((void)0)
+#define make_mmu_pages_readonly(_va, _nr)  ((void)0)
+#define make_mmu_pages_writable(_va, _nr)      ((void)0)
 #endif
 
 #define virt_to_ptep(__va)                                             \
diff -r 05a1340bc1e7 -r 990c009015e8 
linux-2.6-xen-sparse/include/asm-xen/asm-x86_64/pgalloc.h
--- a/linux-2.6-xen-sparse/include/asm-xen/asm-x86_64/pgalloc.h Thu Jan 26 
18:52:18 2006
+++ b/linux-2.6-xen-sparse/include/asm-xen/asm-x86_64/pgalloc.h Fri Jan 27 
20:23:06 2006
@@ -7,10 +7,10 @@
 #include <linux/mm.h>
 #include <asm/io.h>            /* for phys_to_virt and page_to_pseudophys */
 
-void make_page_readonly(void *va);
-void make_page_writable(void *va);
-void make_pages_readonly(void *va, unsigned int nr);
-void make_pages_writable(void *va, unsigned int nr);
+void make_mmu_page_readonly(void *va);
+void make_mmu_page_writable(void *va);
+void make_mmu_pages_readonly(void *va, unsigned int nr);
+void make_mmu_pages_writable(void *va, unsigned int nr);
 
 #define __user_pgd(pgd) ((pgd) + PTRS_PER_PGD)
 
@@ -161,7 +161,7 @@
 {
         pte_t *pte = (pte_t *)get_zeroed_page(GFP_KERNEL|__GFP_REPEAT);
         if (pte)
-               make_page_readonly(pte);
+               make_mmu_page_readonly(pte);
 
        return pte;
 }
@@ -181,7 +181,7 @@
 {
        BUG_ON((unsigned long)pte & (PAGE_SIZE-1));
         xen_pte_unpin(__pa(pte));
-        make_page_writable(pte);
+        make_mmu_page_writable(pte);
        free_page((unsigned long)pte); 
 }
 
diff -r 05a1340bc1e7 -r 990c009015e8 
linux-2.6-xen-sparse/include/asm-xen/gnttab.h
--- a/linux-2.6-xen-sparse/include/asm-xen/gnttab.h     Thu Jan 26 18:52:18 2006
+++ b/linux-2.6-xen-sparse/include/asm-xen/gnttab.h     Fri Jan 27 20:23:06 2006
@@ -50,7 +50,7 @@
 void gnttab_end_foreign_access(grant_ref_t ref, int readonly,
                               unsigned long page);
 
-int gnttab_grant_foreign_transfer(domid_t domid);
+int gnttab_grant_foreign_transfer(domid_t domid, unsigned long pfn);
 
 unsigned long gnttab_end_foreign_transfer_ref(grant_ref_t ref);
 unsigned long gnttab_end_foreign_transfer(grant_ref_t ref);
@@ -77,7 +77,8 @@
 void gnttab_grant_foreign_access_ref(grant_ref_t ref, domid_t domid,
                                     unsigned long frame, int readonly);
 
-void gnttab_grant_foreign_transfer_ref(grant_ref_t, domid_t domid);
+void gnttab_grant_foreign_transfer_ref(grant_ref_t, domid_t domid,
+                                      unsigned long pfn);
 
 #ifdef __ia64__
 #define gnttab_map_vaddr(map) __va(map.dev_bus_addr)
diff -r 05a1340bc1e7 -r 990c009015e8 linux-2.6-xen-sparse/mm/memory.c
--- a/linux-2.6-xen-sparse/mm/memory.c  Thu Jan 26 18:52:18 2006
+++ b/linux-2.6-xen-sparse/mm/memory.c  Fri Jan 27 20:23:06 2006
@@ -291,6 +291,7 @@
                spin_lock(&mm->page_table_lock);
                if (!new)
                        return NULL;
+
                /*
                 * Because we dropped the lock, we should re-check the
                 * entry, as somebody else could have populated it..
diff -r 05a1340bc1e7 -r 990c009015e8 xen/arch/x86/mm.c
--- a/xen/arch/x86/mm.c Thu Jan 26 18:52:18 2006
+++ b/xen/arch/x86/mm.c Fri Jan 27 20:23:06 2006
@@ -1041,7 +1041,7 @@
     if ( unlikely(cmpxchg_user(pl1e, o, n) != 0) ||
          unlikely(o != l1e_get_intpte(ol1e)) )
     {
-        MEM_LOG("Failed to update %" PRIpte " -> %" PRIpte
+        printf("Failed to update %" PRIpte " -> %" PRIpte
                 ": saw %" PRIpte,
                 l1e_get_intpte(ol1e),
                 l1e_get_intpte(nl1e),
@@ -1058,11 +1058,16 @@
     l1_pgentry_t ol1e;
     struct domain *d = current->domain;
 
-    if ( unlikely(__copy_from_user(&ol1e, pl1e, sizeof(ol1e)) != 0) )
+    shadow_sync_all(d);
+    if ( unlikely(__copy_from_user(&ol1e, pl1e, sizeof(ol1e)) != 0) ) {
+        printf("copy_from_user1 failed %p, l2 %lx.\n", pl1e,
+               *(unsigned long *)&__linear_l2_table[l2_table_offset((unsigned 
long)pl1e)]);
         return 0;
-
-    if ( unlikely(shadow_mode_refcounts(d)) )
+    }
+
+    if ( unlikely(shadow_mode_refcounts(d)) ) {
         return update_l1e(pl1e, ol1e, nl1e);
+    }
 
     if ( l1e_get_flags(nl1e) & _PAGE_PRESENT )
     {
@@ -2540,8 +2545,10 @@
 
     perfc_incrc(calls_to_update_va);
 
-    if ( unlikely(!__addr_ok(va) && !shadow_mode_external(d)) )
+    if ( unlikely(!__addr_ok(va) && !shadow_mode_external(d)) ) {
+        printf("Bad update_va_mapping.\n");
         return -EINVAL;
+    }
 
     LOCK_BIGLOCK(d);
 
@@ -2550,9 +2557,13 @@
     if ( unlikely(shadow_mode_enabled(d)) )
         check_pagetable(v, "pre-va"); /* debug */
 
+    shadow_sync_all(d);
+
     if ( unlikely(!mod_l1_entry(&linear_pg_table[l1_linear_offset(va)],
-                                val)) )
+                                val)) ) {
+        printf("mod_l1_entry failed.\n");
         rc = -EINVAL;
+    }
 
     if ( likely(rc == 0) && unlikely(shadow_mode_enabled(d)) )
     {
@@ -2569,7 +2580,8 @@
         }
     
         rc = shadow_do_update_va_mapping(va, val, v);
-
+        if (rc)
+            printf("shadow_do_update_va_mapping says %d.\n", rc);
         check_pagetable(v, "post-va"); /* debug */
     }
 
diff -r 05a1340bc1e7 -r 990c009015e8 xen/arch/x86/shadow32.c
--- a/xen/arch/x86/shadow32.c   Thu Jan 26 18:52:18 2006
+++ b/xen/arch/x86/shadow32.c   Fri Jan 27 20:23:06 2006
@@ -2494,7 +2494,9 @@
             l2_pgentry_t *guest2 = guest;
             l2_pgentry_t *snapshot2 = snapshot;
             l1_pgentry_t *shadow2 = shadow;
-            
+
+            printf("Update hl2 shadow.\n");
+
             ASSERT(shadow_mode_write_all(d) || shadow_mode_wr_pt_pte(d));
             BUG_ON(!shadow_mode_refcounts(d)); // not yet implemented
 
diff -r 05a1340bc1e7 -r 990c009015e8 xen/common/kernel.c
--- a/xen/common/kernel.c       Thu Jan 26 18:52:18 2006
+++ b/xen/common/kernel.c       Fri Jan 27 20:23:06 2006
@@ -13,6 +13,7 @@
 #include <asm/current.h>
 #include <public/nmi.h>
 #include <public/version.h>
+#include <asm/shadow.h>
 
 void cmdline_parse(char *cmdline)
 {
@@ -144,6 +145,31 @@
             return -EFAULT;
         return 0;
     }
+
+    case XENVER_get_features:
+    {
+        xen_feature_info_t fi;
+
+        if ( copy_from_user(&fi, arg, sizeof(fi)) )
+            return -EFAULT;
+
+        switch ( fi.submap_idx )
+        {
+        case 0:
+            if (shadow_mode_wr_pt_pte(current->domain))
+                fi.submap = XENFEAT_writable_mmu_structures;
+            else
+                fi.submap = 0;
+            break;
+        default:
+            return -EINVAL;
+        }
+
+        if ( copy_to_user(arg, &fi, sizeof(fi)) )
+            return -EFAULT;
+        return 0;
+    }
+
     }
 
     return -ENOSYS;
diff -r 05a1340bc1e7 -r 990c009015e8 xen/common/memory.c
--- a/xen/common/memory.c       Thu Jan 26 18:52:18 2006
+++ b/xen/common/memory.c       Fri Jan 27 20:23:06 2006
@@ -30,7 +30,7 @@
     int           *preempted)
 {
     struct pfn_info *page;
-    unsigned int     i;
+    unsigned long    i;
 
     if ( (extent_list != NULL) &&
          !array_access_ok(extent_list, nr_extents, sizeof(*extent_list)) )
@@ -52,7 +52,7 @@
             d, extent_order, flags)) == NULL) )
         {
             DPRINTK("Could not allocate order=%d extent: "
-                    "id=%d flags=%x (%d of %d)\n",
+                    "id=%d flags=%x (%ld of %d)\n",
                     extent_order, d->domain_id, flags, i, nr_extents);
             return i;
         }
@@ -64,6 +64,79 @@
     }
 
     return nr_extents;
+}
+
+static long
+populate_physmap(
+    struct domain *d, 
+    unsigned long *extent_list, 
+    unsigned int   nr_extents,
+    unsigned int   extent_order,
+    unsigned int   flags,
+    int           *preempted)
+{
+    struct pfn_info         *page;
+    unsigned long            i, j, pfn, mfn;
+    struct domain_mmap_cache cache1, cache2;
+
+    if ( !array_access_ok(extent_list, nr_extents, sizeof(*extent_list)) )
+        return 0;
+
+    if ( (extent_order != 0) &&
+         !multipage_allocation_permitted(current->domain) )
+        return 0;
+
+    if (shadow_mode_translate(d)) {
+        domain_mmap_cache_init(&cache1);
+        domain_mmap_cache_init(&cache2);
+        shadow_lock(d);
+    }
+
+    for ( i = 0; i < nr_extents; i++ )
+    {
+        if ( hypercall_preempt_check() )
+        {
+            *preempted = 1;
+            goto out;
+        }
+
+        if ( unlikely((page = alloc_domheap_pages(
+            d, extent_order, flags)) == NULL) )
+        {
+            DPRINTK("Could not allocate order=%d extent: "
+                    "id=%d flags=%x (%ld of %d)\n",
+                    extent_order, d->domain_id, flags, i, nr_extents);
+            goto out;
+        }
+
+        mfn = page_to_pfn(page);
+
+        if ( unlikely(__get_user(pfn, &extent_list[i]) != 0) )
+            goto out;
+
+        for ( j = 0; j < (1 << extent_order); j++ ) {
+            printf("Populating %lx with %lx.\n",
+                   pfn + j, mfn + j);
+            if (shadow_mode_translate(d))
+                set_p2m_entry(d, pfn + j, mfn + j, &cache1, &cache2);
+            set_pfn_from_mfn(mfn + j, pfn + j);
+        }
+
+        if (!shadow_mode_translate(d)) {
+            /* Inform the domain of the new page's machine address. */ 
+            if ( __put_user(mfn, &extent_list[i]) != 0 )
+                goto out;
+        }
+    }
+
+ out:
+    if (shadow_mode_translate(d)) {
+        shadow_unlock(d);
+        domain_mmap_cache_destroy(&cache1);
+        domain_mmap_cache_destroy(&cache2);
+    }
+
+    return i;
 }
     
 static long
@@ -76,7 +149,7 @@
     int           *preempted)
 {
     struct pfn_info *page;
-    unsigned long    i, j, mpfn, mfn;
+    unsigned long    i, j, gpfn, mfn;
 
     if ( !array_access_ok(extent_list, nr_extents, sizeof(*extent_list)) )
         return 0;
@@ -89,16 +162,16 @@
             return i;
         }
 
-        if ( unlikely(__get_user(mpfn, &extent_list[i]) != 0) )
+        if ( unlikely(__get_user(gpfn, &extent_list[i]) != 0) )
             return i;
 
         for ( j = 0; j < (1 << extent_order); j++ )
         {
-            mfn = __gpfn_to_mfn(d, mpfn + j);
+            mfn = __gpfn_to_mfn(d, gpfn + j);
             if ( unlikely(mfn >= max_page) )
             {
-                DPRINTK("Domain %u page number out of range (%lx >= %lx)\n", 
-                        d->domain_id, mfn, max_page);
+                DPRINTK("Domain %u page number out of range (%lx(%lx) >= 
%lx)\n", 
+                        d->domain_id, mfn, gpfn, max_page);
                 return i;
             }
             
@@ -115,8 +188,18 @@
             if ( test_and_clear_bit(_PGC_allocated, &page->count_info) )
                 put_page(page);
 
-            shadow_sync_and_drop_references(d, page);
-
+            if (shadow_mode_translate(d)) {
+                struct domain_mmap_cache c1, c2;
+                domain_mmap_cache_init(&c1);
+                domain_mmap_cache_init(&c2);
+                shadow_lock(d);
+                shadow_sync_and_drop_references(d, page);
+                set_p2m_entry(d, gpfn + j, -1, &c1, &c2);
+                set_pfn_from_mfn(mfn + j, INVALID_M2P_ENTRY);
+                shadow_unlock(d);
+                domain_mmap_cache_destroy(&c1);
+                domain_mmap_cache_destroy(&c2);
+            }
             put_page(page);
         }
     }
@@ -144,6 +227,7 @@
     {
     case XENMEM_increase_reservation:
     case XENMEM_decrease_reservation:
+    case XENMEM_populate_physmap:
         if ( copy_from_user(&reservation, arg, sizeof(reservation)) )
             return -EFAULT;
 
@@ -171,14 +255,37 @@
         else if ( (d = find_domain_by_id(reservation.domid)) == NULL )
             return -ESRCH;
 
-        rc = ((op == XENMEM_increase_reservation) ?
-              increase_reservation : decrease_reservation)(
-                  d,
-                  reservation.extent_start,
-                  reservation.nr_extents,
-                  reservation.extent_order,
-                  flags,
-                  &preempted);
+        switch ( op )
+        {
+        case XENMEM_increase_reservation:
+            rc = increase_reservation(
+                d,
+                reservation.extent_start,
+                reservation.nr_extents,
+                reservation.extent_order,
+                flags,
+                &preempted);
+            break;
+        case XENMEM_decrease_reservation:
+            rc = decrease_reservation(
+                d,
+                reservation.extent_start,
+                reservation.nr_extents,
+                reservation.extent_order,
+                flags,
+                &preempted);
+            break;
+        case XENMEM_populate_physmap:
+        default:
+            rc = populate_physmap(
+                d,
+                reservation.extent_start,
+                reservation.nr_extents,
+                reservation.extent_order,
+                flags,
+                &preempted);
+            break;
+        }
 
         if ( unlikely(reservation.domid != DOMID_SELF) )
             put_domain(d);
diff -r 05a1340bc1e7 -r 990c009015e8 xen/include/asm-x86/shadow.h
--- a/xen/include/asm-x86/shadow.h      Thu Jan 26 18:52:18 2006
+++ b/xen/include/asm-x86/shadow.h      Fri Jan 27 20:23:06 2006
@@ -326,7 +326,7 @@
 #define SHADOW_SNAPSHOT_ELSEWHERE (-1L)
 
 /************************************************************************/
-#define SHADOW_DEBUG 0
+#define SHADOW_DEBUG 1
 #define SHADOW_VERBOSE_DEBUG 0
 #define SHADOW_VVERBOSE_DEBUG 0
 #define SHADOW_VVVERBOSE_DEBUG 0
diff -r 05a1340bc1e7 -r 990c009015e8 xen/include/public/memory.h
--- a/xen/include/public/memory.h       Thu Jan 26 18:52:18 2006
+++ b/xen/include/public/memory.h       Fri Jan 27 20:23:06 2006
@@ -16,11 +16,18 @@
  */
 #define XENMEM_increase_reservation 0
 #define XENMEM_decrease_reservation 1
+#define XENMEM_populate_physmap     6
 typedef struct xen_memory_reservation {
 
     /*
-     * MFN bases of extents to free (XENMEM_decrease_reservation).
-     * MFN bases of extents that were allocated (XENMEM_increase_reservation).
+     * XENMEM_increase_reservation:
+     *   OUT: MFN bases of extents that were allocated
+     * XENMEM_decrease_reservation:
+     *   IN:  MFN bases of extents to free
+     * XENMEM_populate_physmap:
+     *   IN:  PFN bases of extents to populate with memory
+     *   OUT: MFN bases of extents that were allocated
+     *   (NB. This command also updates the mach_to_phys translation table)
      */
     unsigned long *extent_start;
 
@@ -29,11 +36,10 @@
     unsigned int   extent_order;
 
     /*
-     * XENMEM_increase_reservation: maximum # bits addressable by the user
-     * of the allocated region (e.g., I/O devices often have a 32-bit
-     * limitation even in 64-bit systems). If zero then the user has no
-     * addressing restriction.
-     * XENMEM_decrease_reservation: unused.
+     * Mmaximum # bits addressable by the user of the allocated region (e.g., 
+     * I/O devices often have a 32-bit limitation even in 64-bit systems). If 
+     * zero then the user has no addressing restriction.
+     * This field is not used by XENMEM_decrease_reservation.
      */
     unsigned int   address_bits;
 
diff -r 05a1340bc1e7 -r 990c009015e8 xen/include/public/version.h
--- a/xen/include/public/version.h      Thu Jan 26 18:52:18 2006
+++ b/xen/include/public/version.h      Fri Jan 27 20:23:06 2006
@@ -39,6 +39,17 @@
     unsigned long virt_start;
 } xen_platform_parameters_t;
 
+#define XENVER_get_features 6
+typedef struct xen_feature_info {
+    unsigned int submap_idx;    /* IN: which 32-bit submap to return */
+    uint32_t     submap;        /* OUT: 32-bit submap */
+} xen_feature_info_t;
+
+#define _XENFEAT_writable_mmu_structures 0
+#define XENFEAT_writable_mmu_structures (1UL<<_XENFEAT_writable_mmu_structures)
+
+#define XENFEAT_NR_SUBMAPS 1
+
 #endif /* __XEN_PUBLIC_VERSION_H__ */
 
 /*
diff -r 05a1340bc1e7 -r 990c009015e8 
linux-2.6-xen-sparse/arch/xen/kernel/features.c
--- /dev/null   Thu Jan 26 18:52:18 2006
+++ b/linux-2.6-xen-sparse/arch/xen/kernel/features.c   Fri Jan 27 20:23:06 2006
@@ -0,0 +1,29 @@
+/******************************************************************************
+ * features.c
+ *
+ * Xen feature flags.
+ *
+ * Copyright (c) 2006, Ian Campbell
+ */
+#include <linux/types.h>
+#include <linux/cache.h>
+#include <asm/hypervisor.h>
+#include <asm-xen/features.h>
+
+/* When we rebase to a more recent version of Linux we can use __read_mostly 
here. */
+unsigned long xen_features[XENFEAT_NR_SUBMAPS] __cacheline_aligned;
+
+void setup_xen_features(void)
+{
+     uint32_t *flags = (uint32_t *)&xen_features[0];
+     xen_feature_info_t fi;
+     int i;
+
+     for (i=0; i<XENFEAT_NR_SUBMAPS; i++) {
+         fi.submap_idx = i;
+         if (HYPERVISOR_xen_version(XENVER_get_features, &fi) < 0)
+              break;
+         flags[i] = fi.submap;
+     }
+}
+
diff -r 05a1340bc1e7 -r 990c009015e8 
linux-2.6-xen-sparse/include/asm-xen/features.h
--- /dev/null   Thu Jan 26 18:52:18 2006
+++ b/linux-2.6-xen-sparse/include/asm-xen/features.h   Fri Jan 27 20:23:06 2006
@@ -0,0 +1,20 @@
+/******************************************************************************
+ * features.h
+ *
+ * Query the features reported by Xen.
+ *
+ * Copyright (c) 2006, Ian Campbell
+ */
+
+#ifndef __ASM_XEN_FEATURES_H__
+#define __ASM_XEN_FEATURES_H__
+
+#include <asm-xen/xen-public/version.h>
+
+extern void setup_xen_features(void);
+
+extern unsigned long xen_features[XENFEAT_NR_SUBMAPS];
+
+#define xen_feature(flag)      (test_bit(_XENFEAT_ ## flag, xen_features))
+
+#endif

_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-changelog


 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.