[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-changelog] [xen-unstable] Add page table setup and handling, including the creation of an m2p table
# HG changeset patch # User Emmanuel Ackaouy <ack@xxxxxxxxxxxxx> # Date 1168018470 0 # Node ID f632c0c3697657c0df031820dafeb74bf0b0f5bb # Parent 4c8f157a3a471f694ccbdefa6f541ea88438b2ab Add page table setup and handling, including the creation of an m2p table meaningful to compatibility mode guests. Signed-off-by: Jan Beulich <jbeulich@xxxxxxxxxx> --- xen/arch/x86/domain.c | 78 ++++++++++-- xen/arch/x86/domain_build.c | 123 ++++++++++++++++---- xen/arch/x86/domctl.c | 7 - xen/arch/x86/e820.c | 35 +++++ xen/arch/x86/mm.c | 187 +++++++++++++++++++------------ xen/arch/x86/x86_64/mm.c | 72 +++++++++++ xen/common/compat/kernel.c | 2 xen/include/asm-x86/config.h | 30 ++++ xen/include/asm-x86/domain.h | 4 xen/include/asm-x86/mm.h | 9 + xen/include/asm-x86/page.h | 5 xen/include/asm-x86/x86_32/page-2level.h | 2 xen/include/asm-x86/x86_32/page-3level.h | 2 xen/include/asm-x86/x86_64/page.h | 7 - xen/include/asm-x86/x86_64/uaccess.h | 2 15 files changed, 451 insertions(+), 114 deletions(-) diff -r 4c8f157a3a47 -r f632c0c36976 xen/arch/x86/domain.c --- a/xen/arch/x86/domain.c Fri Jan 05 17:34:29 2007 +0000 +++ b/xen/arch/x86/domain.c Fri Jan 05 17:34:30 2007 +0000 @@ -127,6 +127,28 @@ void free_vcpu_struct(struct vcpu *v) xfree(v); } +#ifdef CONFIG_COMPAT +static int setup_compat_l4(struct vcpu *v) +{ + struct page_info *pg = alloc_domheap_page(NULL); + l4_pgentry_t *l4tab; + + if ( !pg ) + return -ENOMEM; + l4tab = copy_page(page_to_virt(pg), idle_pg_table); + l4tab[l4_table_offset(LINEAR_PT_VIRT_START)] = + l4e_from_page(pg, __PAGE_HYPERVISOR); + l4tab[l4_table_offset(PERDOMAIN_VIRT_START)] = + l4e_from_paddr(__pa(v->domain->arch.mm_perdomain_l3), __PAGE_HYPERVISOR); + v->arch.guest_table = pagetable_from_page(pg); + v->arch.guest_table_user = v->arch.guest_table; + + return 0; +} +#else +#define setup_compat_l4(v) 0 +#endif + int vcpu_initialise(struct vcpu *v) { struct domain *d = v->domain; @@ -161,11 +183,16 @@ int vcpu_initialise(struct vcpu *v) v->arch.perdomain_ptes = d->arch.mm_perdomain_pt + (v->vcpu_id << GDT_LDT_VCPU_SHIFT); + if ( IS_COMPAT(d) && (rc = setup_compat_l4(v)) != 0 ) + return rc; + return 0; } void vcpu_destroy(struct vcpu *v) { + if ( IS_COMPAT(v->domain) ) + free_domheap_page(pagetable_get_page(v->arch.guest_table)); } int arch_domain_create(struct domain *d) @@ -219,6 +246,10 @@ int arch_domain_create(struct domain *d) #endif /* __x86_64__ */ +#ifdef CONFIG_COMPAT + HYPERVISOR_COMPAT_VIRT_START(d) = __HYPERVISOR_COMPAT_VIRT_START; +#endif + shadow_domain_init(d); if ( !is_idle_domain(d) ) @@ -349,18 +380,41 @@ int arch_set_info_guest( if ( (rc = (int)set_gdt(v, c->gdt_frames, c->gdt_ents)) != 0 ) return rc; - cr3_pfn = gmfn_to_mfn(d, xen_cr3_to_pfn(c->ctrlreg[3])); - - if ( shadow_mode_refcounts(d) - ? !get_page(mfn_to_page(cr3_pfn), d) - : !get_page_and_type(mfn_to_page(cr3_pfn), d, - PGT_base_page_table) ) - { - destroy_gdt(v); - return -EINVAL; - } - - v->arch.guest_table = pagetable_from_pfn(cr3_pfn); + if ( !IS_COMPAT(d) ) + { + cr3_pfn = gmfn_to_mfn(d, xen_cr3_to_pfn(c->ctrlreg[3])); + + if ( shadow_mode_refcounts(d) + ? !get_page(mfn_to_page(cr3_pfn), d) + : !get_page_and_type(mfn_to_page(cr3_pfn), d, + PGT_base_page_table) ) + { + destroy_gdt(v); + return -EINVAL; + } + + v->arch.guest_table = pagetable_from_pfn(cr3_pfn); + } +#ifdef CONFIG_COMPAT + else + { + l4_pgentry_t *l4tab; + + cr3_pfn = gmfn_to_mfn(d, compat_cr3_to_pfn(c->ctrlreg[3])); + + if ( shadow_mode_refcounts(d) + ? !get_page(mfn_to_page(cr3_pfn), d) + : !get_page_and_type(mfn_to_page(cr3_pfn), d, + PGT_l3_page_table) ) + { + destroy_gdt(v); + return -EINVAL; + } + + l4tab = __va(pagetable_get_paddr(v->arch.guest_table)); + *l4tab = l4e_from_pfn(cr3_pfn, _PAGE_PRESENT|_PAGE_RW|_PAGE_USER|_PAGE_ACCESSED); + } +#endif } if ( v->vcpu_id == 0 ) diff -r 4c8f157a3a47 -r f632c0c36976 xen/arch/x86/domain_build.c --- a/xen/arch/x86/domain_build.c Fri Jan 05 17:34:29 2007 +0000 +++ b/xen/arch/x86/domain_build.c Fri Jan 05 17:34:30 2007 +0000 @@ -91,9 +91,11 @@ string_param("dom0_ioports_disable", opt #define L2_PROT (_PAGE_PRESENT|_PAGE_RW|_PAGE_ACCESSED|_PAGE_DIRTY|_PAGE_USER) #define L3_PROT (_PAGE_PRESENT) #elif defined(__x86_64__) -/* Allow ring-3 access in long mode as guest cannot use ring 1. */ +/* Allow ring-3 access in long mode as guest cannot use ring 1 ... */ #define BASE_PROT (_PAGE_PRESENT|_PAGE_RW|_PAGE_ACCESSED|_PAGE_USER) #define L1_PROT (BASE_PROT|_PAGE_GUEST_KERNEL) +/* ... except for compatibility mode guests. */ +#define COMPAT_L1_PROT (_PAGE_PRESENT|_PAGE_RW|_PAGE_ACCESSED) #define L2_PROT (BASE_PROT|_PAGE_DIRTY) #define L3_PROT (BASE_PROT|_PAGE_DIRTY) #define L4_PROT (BASE_PROT|_PAGE_DIRTY) @@ -262,8 +264,8 @@ int construct_dom0(struct domain *d, start_info_t *si; struct vcpu *v = d->vcpu[0]; const char *p; - unsigned long hypercall_page; - int hypercall_page_defined; + unsigned long long value; + int value_defined; #if defined(__i386__) char *image_start = (char *)_image_start; /* use lowmem mappings */ char *initrd_start = (char *)_initrd_start; /* use lowmem mappings */ @@ -323,6 +325,7 @@ int construct_dom0(struct domain *d, rc = parseelfimage(&dsi); #ifdef CONFIG_COMPAT if ( rc == -ENOSYS + && !compat_disabled && (rc = parseelf32image(&dsi)) == 0 ) { l1_pgentry_t gdt_l1e; @@ -370,10 +373,37 @@ int construct_dom0(struct domain *d, #ifdef CONFIG_COMPAT if ( IS_COMPAT(d) ) + { + value = xen_elf32note_numeric(&dsi, XEN_ELFNOTE_HV_START_LOW, &value_defined); p = xen_elf32note_string(&dsi, XEN_ELFNOTE_FEATURES); + } else #endif + { + value = xen_elfnote_numeric(&dsi, XEN_ELFNOTE_HV_START_LOW, &value_defined); p = xen_elfnote_string(&dsi, XEN_ELFNOTE_FEATURES); + } + if ( value_defined ) + { +#if CONFIG_PAGING_LEVELS < 4 + unsigned long mask = (1UL << L2_PAGETABLE_SHIFT) - 1; +#else + unsigned long mask = !IS_COMPAT(d) + ? (1UL << L4_PAGETABLE_SHIFT) - 1 + : (1UL << L2_PAGETABLE_SHIFT) - 1; +#endif + + value = (value + mask) & ~mask; +#ifdef CONFIG_COMPAT + HYPERVISOR_COMPAT_VIRT_START(d) = max_t(unsigned int, m2p_compat_vstart, value); + if ( value > (!IS_COMPAT(d) ? + HYPERVISOR_VIRT_START : + __HYPERVISOR_COMPAT_VIRT_START) ) +#else + if ( value > HYPERVISOR_VIRT_START ) +#endif + panic("Domain 0 expects too high a hypervisor start address.\n"); + } if ( p != NULL ) { parse_features(p, @@ -400,7 +430,9 @@ int construct_dom0(struct domain *d, vinitrd_start = round_pgup(dsi.v_end); vinitrd_end = vinitrd_start + initrd_len; vphysmap_start = round_pgup(vinitrd_end); - vphysmap_end = vphysmap_start + (nr_pages * sizeof(unsigned long)); + vphysmap_end = vphysmap_start + (nr_pages * (!IS_COMPAT(d) ? + sizeof(unsigned long) : + sizeof(unsigned int))); vstartinfo_start = round_pgup(vphysmap_end); vstartinfo_end = (vstartinfo_start + sizeof(struct start_info) + @@ -429,7 +461,9 @@ int construct_dom0(struct domain *d, ((_l) & ~((1UL<<(_s))-1))) >> (_s)) if ( (1 + /* # L4 */ NR(dsi.v_start, v_end, L4_PAGETABLE_SHIFT) + /* # L3 */ - NR(dsi.v_start, v_end, L3_PAGETABLE_SHIFT) + /* # L2 */ + (!IS_COMPAT(d) ? + NR(dsi.v_start, v_end, L3_PAGETABLE_SHIFT) : /* # L2 */ + 4) + /* # compat L2 */ NR(dsi.v_start, v_end, L2_PAGETABLE_SHIFT)) /* # L1 */ <= nr_pt_pages ) break; @@ -619,8 +653,10 @@ int construct_dom0(struct domain *d, #elif defined(__x86_64__) /* Overlap with Xen protected area? */ - if ( (dsi.v_start < HYPERVISOR_VIRT_END) && - (v_end > HYPERVISOR_VIRT_START) ) + if ( !IS_COMPAT(d) ? + ((dsi.v_start < HYPERVISOR_VIRT_END) && + (v_end > HYPERVISOR_VIRT_START)) : + (v_end > HYPERVISOR_COMPAT_VIRT_START(d)) ) { printk("DOM0 image overlaps with Xen private area.\n"); return -EINVAL; @@ -633,8 +669,18 @@ int construct_dom0(struct domain *d, } /* WARNING: The new domain must have its 'processor' field filled in! */ - maddr_to_page(mpt_alloc)->u.inuse.type_info = PGT_l4_page_table; - l4start = l4tab = __va(mpt_alloc); mpt_alloc += PAGE_SIZE; + if ( !IS_COMPAT(d) ) + { + maddr_to_page(mpt_alloc)->u.inuse.type_info = PGT_l4_page_table; + l4start = l4tab = __va(mpt_alloc); mpt_alloc += PAGE_SIZE; + } + else + { + page = alloc_domheap_page(NULL); + if ( !page ) + panic("Not enough RAM for domain 0 PML4.\n"); + l4start = l4tab = page_to_virt(page); + } memcpy(l4tab, idle_pg_table, PAGE_SIZE); l4tab[l4_table_offset(LINEAR_PT_VIRT_START)] = l4e_from_paddr(__pa(l4start), __PAGE_HYPERVISOR); @@ -679,7 +725,7 @@ int construct_dom0(struct domain *d, *l2tab = l2e_from_paddr(__pa(l1start), L2_PROT); l2tab++; } - *l1tab = l1e_from_pfn(mfn, L1_PROT); + *l1tab = l1e_from_pfn(mfn, !IS_COMPAT(d) ? L1_PROT : COMPAT_L1_PROT); l1tab++; page = mfn_to_page(mfn); @@ -689,6 +735,30 @@ int construct_dom0(struct domain *d, mfn++; } + +#ifdef CONFIG_COMPAT + if ( IS_COMPAT(d) ) + { + /* Ensure the first four L3 entries are all populated. */ + for ( i = 0, l3tab = l3start; i < 4; ++i, ++l3tab ) + { + if ( !l3e_get_intpte(*l3tab) ) + { + maddr_to_page(mpt_alloc)->u.inuse.type_info = PGT_l2_page_table; + l2tab = __va(mpt_alloc); mpt_alloc += PAGE_SIZE; + clear_page(l2tab); + *l3tab = l3e_from_paddr(__pa(l2tab), L3_PROT); + } + if ( i == 3 ) + l3e_get_page(*l3tab)->u.inuse.type_info |= PGT_pae_xen_l2; + } + /* Install read-only guest visible MPT mapping. */ + l2tab = l3e_to_l2e(l3start[3]); + memcpy(&l2tab[COMPAT_L2_PAGETABLE_FIRST_XEN_SLOT(d)], + &compat_idle_pg_table_l2[l2_table_offset(HIRO_COMPAT_MPT_VIRT_START)], + COMPAT_L2_PAGETABLE_XEN_SLOTS(d) * sizeof(*l2tab)); + } +#endif /* Pages that are part of page tables must be read only. */ l4tab = l4start + l4_table_offset(vpt_start); @@ -708,7 +778,8 @@ int construct_dom0(struct domain *d, page->u.inuse.type_info |= PGT_validated | 1; /* Top-level p.t. is pinned. */ - if ( (page->u.inuse.type_info & PGT_type_mask) == PGT_l4_page_table ) + if ( (page->u.inuse.type_info & PGT_type_mask) == + (!IS_COMPAT(d) ? PGT_l4_page_table : PGT_l3_page_table) ) { page->count_info += 1; page->u.inuse.type_info += 1 | PGT_pinned; @@ -761,26 +832,26 @@ int construct_dom0(struct domain *d, if ( IS_COMPAT(d) ) { (void)loadelf32image(&dsi); - hypercall_page = - xen_elf32note_numeric(&dsi, XEN_ELFNOTE_HYPERCALL_PAGE, &hypercall_page_defined); + value = + xen_elf32note_numeric(&dsi, XEN_ELFNOTE_HYPERCALL_PAGE, &value_defined); } else #endif { (void)loadelfimage(&dsi); - hypercall_page = - xen_elfnote_numeric(&dsi, XEN_ELFNOTE_HYPERCALL_PAGE, &hypercall_page_defined); - } - if ( hypercall_page_defined ) - { - if ( (hypercall_page < dsi.v_start) || (hypercall_page >= v_end) ) + value = + xen_elfnote_numeric(&dsi, XEN_ELFNOTE_HYPERCALL_PAGE, &value_defined); + } + if ( value_defined ) + { + if ( (value < dsi.v_start) || (value >= v_end) ) { write_ptbase(current); local_irq_enable(); printk("Invalid HYPERCALL_PAGE field in ELF notes.\n"); return -1; } - hypercall_page_initialise(d, (void *)hypercall_page); + hypercall_page_initialise(d, (void *)(unsigned long)value); } /* Copy the initial ramdisk. */ @@ -798,7 +869,7 @@ int construct_dom0(struct domain *d, si->shared_info = virt_to_maddr(d->shared_info); si->flags = SIF_PRIVILEGED | SIF_INITDOMAIN; - si->pt_base = vpt_start; + si->pt_base = vpt_start + 2 * PAGE_SIZE * !!IS_COMPAT(d); si->nr_pt_frames = nr_pt_pages; si->mfn_list = vphysmap_start; sprintf(si->magic, "xen-%i.%i-x86_%d%s", @@ -814,7 +885,10 @@ int construct_dom0(struct domain *d, if ( pfn > REVERSE_START ) mfn = alloc_epfn - (pfn - REVERSE_START); #endif - ((unsigned long *)vphysmap_start)[pfn] = mfn; + if ( !IS_COMPAT(d) ) + ((unsigned long *)vphysmap_start)[pfn] = mfn; + else + ((unsigned int *)vphysmap_start)[pfn] = mfn; set_gpfn_from_mfn(mfn, pfn); } while ( pfn < nr_pages ) @@ -827,7 +901,10 @@ int construct_dom0(struct domain *d, #ifndef NDEBUG #define pfn (nr_pages - 1 - (pfn - (alloc_epfn - alloc_spfn))) #endif - ((unsigned long *)vphysmap_start)[pfn] = mfn; + if ( !IS_COMPAT(d) ) + ((unsigned long *)vphysmap_start)[pfn] = mfn; + else + ((unsigned int *)vphysmap_start)[pfn] = mfn; set_gpfn_from_mfn(mfn, pfn); #undef pfn page++; pfn++; diff -r 4c8f157a3a47 -r f632c0c36976 xen/arch/x86/domctl.c --- a/xen/arch/x86/domctl.c Fri Jan 05 17:34:29 2007 +0000 +++ b/xen/arch/x86/domctl.c Fri Jan 05 17:34:30 2007 +0000 @@ -311,7 +311,12 @@ void arch_getdomaininfo_ctxt( if ( guest_kernel_mode(v, &v->arch.guest_context.user_regs) ) c->flags |= VGCF_in_kernel; - c->ctrlreg[3] = xen_pfn_to_cr3(pagetable_get_pfn(v->arch.guest_table)); + if ( !IS_COMPAT(v->domain) ) + c->ctrlreg[3] = xen_pfn_to_cr3(pagetable_get_pfn(v->arch.guest_table)); +#ifdef CONFIG_COMPAT + else + c->ctrlreg[3] = compat_pfn_to_cr3(pagetable_get_pfn(v->arch.guest_table)); +#endif c->vm_assist = v->domain->vm_assist; } diff -r 4c8f157a3a47 -r f632c0c36976 xen/arch/x86/e820.c --- a/xen/arch/x86/e820.c Fri Jan 05 17:34:29 2007 +0000 +++ b/xen/arch/x86/e820.c Fri Jan 05 17:34:30 2007 +0000 @@ -1,6 +1,7 @@ #include <xen/config.h> #include <xen/init.h> #include <xen/lib.h> +#include <xen/compat.h> #include <asm/e820.h> #include <asm/page.h> @@ -341,6 +342,39 @@ static void __init clip_4gb(void) #define clip_4gb() ((void)0) #endif +#ifdef CONFIG_COMPAT +static void __init clip_compat(void) +{ + unsigned long long limit; + unsigned int i; + + if ( compat_disabled ) + return; + /* 32-bit guests restricted to 166 GB (with current memory allocator). */ + limit = (unsigned long long)(MACH2PHYS_COMPAT_VIRT_END - + __HYPERVISOR_COMPAT_VIRT_START) << 10; + for ( i = 0; i < e820.nr_map; i++ ) + { + if ( (e820.map[i].addr + e820.map[i].size) <= limit ) + continue; + printk("WARNING: Only the first %Lu GB of the physical memory map " + "can be accessed\n" + " by compatibility mode guests. " + "Truncating the memory map...\n", + limit >> 30); + if ( e820.map[i].addr >= limit ) + e820.nr_map = i; + else + { + e820.map[i].size = limit - e820.map[i].addr; + e820.nr_map = i + 1; + } + } +} +#else +#define clip_compat() ((void)0) +#endif + static void __init clip_mem(void) { int i; @@ -374,6 +408,7 @@ static void __init machine_specific_memo *raw_nr = nr; (void)copy_e820_map(raw, nr); clip_4gb(); + clip_compat(); clip_mem(); } diff -r 4c8f157a3a47 -r f632c0c36976 xen/arch/x86/mm.c --- a/xen/arch/x86/mm.c Fri Jan 05 17:34:29 2007 +0000 +++ b/xen/arch/x86/mm.c Fri Jan 05 17:34:30 2007 +0000 @@ -126,13 +126,6 @@ */ #define MMU_UPDATE_PREEMPTED (~(~0U>>1)) -static void free_l2_table(struct page_info *page); -static void free_l1_table(struct page_info *page); - -static int mod_l2_entry(l2_pgentry_t *, l2_pgentry_t, unsigned long, - unsigned long type); -static int mod_l1_entry(l1_pgentry_t *, l1_pgentry_t, unsigned long gl1mfn); - /* Used to defer flushing of memory structures. */ struct percpu_mm_info { #define DOP_FLUSH_TLB (1<<0) /* Flush the local TLB. */ @@ -157,6 +150,15 @@ struct page_info *frame_table; struct page_info *frame_table; unsigned long max_page; unsigned long total_pages; + +#ifdef CONFIG_COMPAT +l2_pgentry_t *compat_idle_pg_table_l2 = NULL; +#define l3_disallow_mask(d) (!IS_COMPAT(d) ? \ + L3_DISALLOW_MASK : \ + COMPAT_L3_DISALLOW_MASK) +#else +#define l3_disallow_mask(d) L3_DISALLOW_MASK +#endif void __init init_frametable(void) { @@ -661,9 +663,9 @@ get_page_from_l3e( if ( !(l3e_get_flags(l3e) & _PAGE_PRESENT) ) return 1; - if ( unlikely((l3e_get_flags(l3e) & L3_DISALLOW_MASK)) ) - { - MEM_LOG("Bad L3 flags %x", l3e_get_flags(l3e) & L3_DISALLOW_MASK); + if ( unlikely((l3e_get_flags(l3e) & l3_disallow_mask(d))) ) + { + MEM_LOG("Bad L3 flags %x", l3e_get_flags(l3e) & l3_disallow_mask(d)); return 0; } @@ -700,9 +702,10 @@ get_page_from_l4e( #ifdef __x86_64__ #ifdef USER_MAPPINGS_ARE_GLOBAL -#define adjust_guest_l1e(pl1e) \ +#define adjust_guest_l1e(pl1e, d) \ do { \ - if ( likely(l1e_get_flags((pl1e)) & _PAGE_PRESENT) ) \ + if ( likely(l1e_get_flags((pl1e)) & _PAGE_PRESENT) && \ + likely(!IS_COMPAT(d)) ) \ { \ /* _PAGE_GUEST_KERNEL page cannot have the Global bit set. */ \ if ( (l1e_get_flags((pl1e)) & (_PAGE_GUEST_KERNEL|_PAGE_GLOBAL)) \ @@ -716,37 +719,53 @@ get_page_from_l4e( } \ } while ( 0 ) #else -#define adjust_guest_l1e(pl1e) \ +#define adjust_guest_l1e(pl1e, d) \ do { \ - if ( likely(l1e_get_flags((pl1e)) & _PAGE_PRESENT) ) \ + if ( likely(l1e_get_flags((pl1e)) & _PAGE_PRESENT) && \ + likely(!IS_COMPAT(d)) ) \ l1e_add_flags((pl1e), _PAGE_USER); \ } while ( 0 ) #endif -#define adjust_guest_l2e(pl2e) \ +#define adjust_guest_l2e(pl2e, d) \ do { \ - if ( likely(l2e_get_flags((pl2e)) & _PAGE_PRESENT) ) \ + if ( likely(l2e_get_flags((pl2e)) & _PAGE_PRESENT) && \ + likely(!IS_COMPAT(d)) ) \ l2e_add_flags((pl2e), _PAGE_USER); \ } while ( 0 ) -#define adjust_guest_l3e(pl3e) \ +#define adjust_guest_l3e(pl3e, d) \ do { \ if ( likely(l3e_get_flags((pl3e)) & _PAGE_PRESENT) ) \ - l3e_add_flags((pl3e), _PAGE_USER); \ + l3e_add_flags((pl3e), likely(!IS_COMPAT(d)) ? \ + _PAGE_USER : \ + _PAGE_USER|_PAGE_RW); \ } while ( 0 ) -#define adjust_guest_l4e(pl4e) \ +#define adjust_guest_l4e(pl4e, d) \ do { \ - if ( likely(l4e_get_flags((pl4e)) & _PAGE_PRESENT) ) \ + if ( likely(l4e_get_flags((pl4e)) & _PAGE_PRESENT) && \ + likely(!IS_COMPAT(d)) ) \ l4e_add_flags((pl4e), _PAGE_USER); \ } while ( 0 ) #else /* !defined(__x86_64__) */ -#define adjust_guest_l1e(_p) ((void)0) -#define adjust_guest_l2e(_p) ((void)0) -#define adjust_guest_l3e(_p) ((void)0) - +#define adjust_guest_l1e(_p, _d) ((void)(_d)) +#define adjust_guest_l2e(_p, _d) ((void)(_d)) +#define adjust_guest_l3e(_p, _d) ((void)(_d)) + +#endif + +#ifdef CONFIG_COMPAT +#define unadjust_guest_l3e(pl3e, d) \ + do { \ + if ( unlikely(IS_COMPAT(d)) && \ + likely(l3e_get_flags((pl3e)) & _PAGE_PRESENT) ) \ + l3e_remove_flags((pl3e), _PAGE_USER|_PAGE_RW|_PAGE_ACCESSED); \ + } while ( 0 ) +#else +#define unadjust_guest_l3e(_p, _d) ((void)(_d)) #endif void put_page_from_l1e(l1_pgentry_t l1e, struct domain *d) @@ -850,7 +869,7 @@ static int alloc_l1_table(struct page_in unlikely(!get_page_from_l1e(pl1e[i], d)) ) goto fail; - adjust_guest_l1e(pl1e[i]); + adjust_guest_l1e(pl1e[i], d); } unmap_domain_page(pl1e); @@ -866,13 +885,20 @@ static int alloc_l1_table(struct page_in return 0; } -#ifdef CONFIG_X86_PAE -static int create_pae_xen_mappings(l3_pgentry_t *pl3e) +#if defined(CONFIG_X86_PAE) || defined(CONFIG_COMPAT) +static int create_pae_xen_mappings(struct domain *d, l3_pgentry_t *pl3e) { struct page_info *page; - l2_pgentry_t *pl2e, l2e; + l2_pgentry_t *pl2e; l3_pgentry_t l3e3; +#ifndef CONFIG_COMPAT + l2_pgentry_t l2e; int i; +#else + + if ( !IS_COMPAT(d) ) + return 1; +#endif pl3e = (l3_pgentry_t *)((unsigned long)pl3e & PAGE_MASK); @@ -905,6 +931,7 @@ static int create_pae_xen_mappings(l3_pg /* Xen private mappings. */ pl2e = map_domain_page(l3e_get_pfn(l3e3)); +#ifndef CONFIG_COMPAT memcpy(&pl2e[L2_PAGETABLE_FIRST_XEN_SLOT & (L2_PAGETABLE_ENTRIES-1)], &idle_pg_table_l2[L2_PAGETABLE_FIRST_XEN_SLOT], L2_PAGETABLE_XEN_SLOTS * sizeof(l2_pgentry_t)); @@ -922,11 +949,20 @@ static int create_pae_xen_mappings(l3_pg l2e = l2e_from_pfn(l3e_get_pfn(pl3e[i]), __PAGE_HYPERVISOR); l2e_write(&pl2e[l2_table_offset(LINEAR_PT_VIRT_START) + i], l2e); } +#else + memcpy(&pl2e[COMPAT_L2_PAGETABLE_FIRST_XEN_SLOT(d)], + &compat_idle_pg_table_l2[l2_table_offset(HIRO_COMPAT_MPT_VIRT_START)], + COMPAT_L2_PAGETABLE_XEN_SLOTS(d) * sizeof(*pl2e)); +#endif unmap_domain_page(pl2e); return 1; } - +#else +# define create_pae_xen_mappings(d, pl3e) (1) +#endif + +#ifdef CONFIG_X86_PAE /* Flush a pgdir update into low-memory caches. */ static void pae_flush_pgd( unsigned long mfn, unsigned int idx, l3_pgentry_t nl3e) @@ -961,12 +997,8 @@ static void pae_flush_pgd( flush_tlb_mask(d->domain_dirty_cpumask); } - -#elif CONFIG_X86_64 -# define create_pae_xen_mappings(pl3e) (1) +#else # define pae_flush_pgd(mfn, idx, nl3e) ((void)0) -#else -# define create_pae_xen_mappings(pl3e) (1) #endif static int alloc_l2_table(struct page_info *page, unsigned long type) @@ -980,11 +1012,11 @@ static int alloc_l2_table(struct page_in for ( i = 0; i < L2_PAGETABLE_ENTRIES; i++ ) { - if ( is_guest_l2_slot(type, i) && + if ( is_guest_l2_slot(d, type, i) && unlikely(!get_page_from_l2e(pl2e[i], pfn, d)) ) goto fail; - adjust_guest_l2e(pl2e[i]); + adjust_guest_l2e(pl2e[i], d); } #if CONFIG_PAGING_LEVELS == 2 @@ -1007,7 +1039,7 @@ static int alloc_l2_table(struct page_in fail: MEM_LOG("Failure in alloc_l2_table: entry %d", i); while ( i-- > 0 ) - if ( is_guest_l2_slot(type, i) ) + if ( is_guest_l2_slot(d, type, i) ) put_page_from_l2e(pl2e[i], pfn); unmap_domain_page(pl2e); @@ -1039,13 +1071,24 @@ static int alloc_l3_table(struct page_in #endif pl3e = map_domain_page(pfn); + + /* + * PAE guests allocate full pages, but aren't required to initialize + * more than the first four entries; when running in compatibility + * mode, however, the full page is visible to the MMU, and hence all + * 512 entries must be valid/verified, which is most easily achieved + * by clearing them out. + */ + if ( IS_COMPAT(d) ) + memset(pl3e + 4, 0, (L3_PAGETABLE_ENTRIES - 4) * sizeof(*pl3e)); + for ( i = 0; i < L3_PAGETABLE_ENTRIES; i++ ) { -#ifdef CONFIG_X86_PAE - if ( i == 3 ) +#if defined(CONFIG_X86_PAE) || defined(CONFIG_COMPAT) + if ( (CONFIG_PAGING_LEVELS < 4 || IS_COMPAT(d)) && i == 3 ) { if ( !(l3e_get_flags(pl3e[i]) & _PAGE_PRESENT) || - (l3e_get_flags(pl3e[i]) & L3_DISALLOW_MASK) || + (l3e_get_flags(pl3e[i]) & l3_disallow_mask(d)) || !get_page_and_type_from_pagenr(l3e_get_pfn(pl3e[i]), PGT_l2_page_table | PGT_pae_xen_l2, @@ -1058,10 +1101,10 @@ static int alloc_l3_table(struct page_in unlikely(!get_page_from_l3e(pl3e[i], pfn, d)) ) goto fail; - adjust_guest_l3e(pl3e[i]); - } - - if ( !create_pae_xen_mappings(pl3e) ) + adjust_guest_l3e(pl3e[i], d); + } + + if ( !create_pae_xen_mappings(d, pl3e) ) goto fail; unmap_domain_page(pl3e); @@ -1094,7 +1137,7 @@ static int alloc_l4_table(struct page_in unlikely(!get_page_from_l4e(pl4e[i], pfn, d)) ) goto fail; - adjust_guest_l4e(pl4e[i]); + adjust_guest_l4e(pl4e[i], d); } /* Xen private mappings. */ @@ -1142,6 +1185,9 @@ static void free_l1_table(struct page_in static void free_l2_table(struct page_info *page) { +#ifdef CONFIG_COMPAT + struct domain *d = page_get_owner(page); +#endif unsigned long pfn = page_to_mfn(page); l2_pgentry_t *pl2e; int i; @@ -1149,7 +1195,7 @@ static void free_l2_table(struct page_in pl2e = map_domain_page(pfn); for ( i = 0; i < L2_PAGETABLE_ENTRIES; i++ ) - if ( is_guest_l2_slot(page->u.inuse.type_info, i) ) + if ( is_guest_l2_slot(d, page->u.inuse.type_info, i) ) put_page_from_l2e(pl2e[i], pfn); unmap_domain_page(pl2e); @@ -1162,6 +1208,7 @@ static void free_l2_table(struct page_in static void free_l3_table(struct page_info *page) { + struct domain *d = page_get_owner(page); unsigned long pfn = page_to_mfn(page); l3_pgentry_t *pl3e; int i; @@ -1170,7 +1217,10 @@ static void free_l3_table(struct page_in for ( i = 0; i < L3_PAGETABLE_ENTRIES; i++ ) if ( is_guest_l3_slot(i) ) + { put_page_from_l3e(pl3e[i], pfn); + unadjust_guest_l3e(pl3e[i], d); + } unmap_domain_page(pl3e); } @@ -1270,7 +1320,7 @@ static int mod_l1_entry(l1_pgentry_t *pl return 0; } - adjust_guest_l1e(nl1e); + adjust_guest_l1e(nl1e, d); /* Fast path for identical mapping, r/w and presence. */ if ( !l1e_has_changed(ol1e, nl1e, _PAGE_RW | _PAGE_PRESENT) ) @@ -1303,8 +1353,9 @@ static int mod_l2_entry(l2_pgentry_t *pl unsigned long type) { l2_pgentry_t ol2e; - - if ( unlikely(!is_guest_l2_slot(type,pgentry_ptr_to_slot(pl2e))) ) + struct domain *d = current->domain; + + if ( unlikely(!is_guest_l2_slot(d, type, pgentry_ptr_to_slot(pl2e))) ) { MEM_LOG("Illegal L2 update attempt in Xen-private area %p", pl2e); return 0; @@ -1322,7 +1373,7 @@ static int mod_l2_entry(l2_pgentry_t *pl return 0; } - adjust_guest_l2e(nl2e); + adjust_guest_l2e(nl2e, d); /* Fast path for identical mapping and presence. */ if ( !l2e_has_changed(ol2e, nl2e, _PAGE_PRESENT)) @@ -1354,6 +1405,7 @@ static int mod_l3_entry(l3_pgentry_t *pl unsigned long pfn) { l3_pgentry_t ol3e; + struct domain *d = current->domain; int okay; if ( unlikely(!is_guest_l3_slot(pgentry_ptr_to_slot(pl3e))) ) @@ -1362,12 +1414,13 @@ static int mod_l3_entry(l3_pgentry_t *pl return 0; } -#ifdef CONFIG_X86_PAE +#if defined(CONFIG_X86_PAE) || defined(CONFIG_COMPAT) /* * Disallow updates to final L3 slot. It contains Xen mappings, and it * would be a pain to ensure they remain continuously valid throughout. */ - if ( pgentry_ptr_to_slot(pl3e) >= 3 ) + if ( (CONFIG_PAGING_LEVELS < 4 || IS_COMPAT(d)) && + pgentry_ptr_to_slot(pl3e) >= 3 ) return 0; #endif @@ -1376,14 +1429,14 @@ static int mod_l3_entry(l3_pgentry_t *pl if ( l3e_get_flags(nl3e) & _PAGE_PRESENT ) { - if ( unlikely(l3e_get_flags(nl3e) & L3_DISALLOW_MASK) ) + if ( unlikely(l3e_get_flags(nl3e) & l3_disallow_mask(d)) ) { MEM_LOG("Bad L3 flags %x", - l3e_get_flags(nl3e) & L3_DISALLOW_MASK); + l3e_get_flags(nl3e) & l3_disallow_mask(d)); return 0; } - adjust_guest_l3e(nl3e); + adjust_guest_l3e(nl3e, d); /* Fast path for identical mapping and presence. */ if (!l3e_has_changed(ol3e, nl3e, _PAGE_PRESENT)) @@ -1403,7 +1456,7 @@ static int mod_l3_entry(l3_pgentry_t *pl return 0; } - okay = create_pae_xen_mappings(pl3e); + okay = create_pae_xen_mappings(d, pl3e); BUG_ON(!okay); pae_flush_pgd(pfn, pgentry_ptr_to_slot(pl3e), nl3e); @@ -1441,7 +1494,7 @@ static int mod_l4_entry(l4_pgentry_t *pl return 0; } - adjust_guest_l4e(nl4e); + adjust_guest_l4e(nl4e, current->domain); /* Fast path for identical mapping and presence. */ if (!l4e_has_changed(ol4e, nl4e, _PAGE_PRESENT)) @@ -2265,8 +2318,7 @@ int do_mmu_update( case PGT_l2_page_table: { l2_pgentry_t l2e = l2e_from_intpte(req.val); - okay = mod_l2_entry( - (l2_pgentry_t *)va, l2e, mfn, type_info); + okay = mod_l2_entry(va, l2e, mfn, type_info); } break; #if CONFIG_PAGING_LEVELS >= 3 @@ -2279,11 +2331,12 @@ int do_mmu_update( #endif #if CONFIG_PAGING_LEVELS >= 4 case PGT_l4_page_table: - { - l4_pgentry_t l4e = l4e_from_intpte(req.val); - okay = mod_l4_entry(va, l4e, mfn); - } - break; + if ( !IS_COMPAT(FOREIGNDOM) ) + { + l4_pgentry_t l4e = l4e_from_intpte(req.val); + okay = mod_l4_entry(va, l4e, mfn); + } + break; #endif } @@ -2387,7 +2440,7 @@ static int create_grant_pte_mapping( ASSERT(spin_is_locked(&d->big_lock)); - adjust_guest_l1e(nl1e); + adjust_guest_l1e(nl1e, d); gmfn = pte_addr >> PAGE_SHIFT; mfn = gmfn_to_mfn(d, gmfn); @@ -2508,7 +2561,7 @@ static int create_grant_va_mapping( ASSERT(spin_is_locked(&d->big_lock)); - adjust_guest_l1e(nl1e); + adjust_guest_l1e(nl1e, d); pl1e = guest_map_l1e(v, va, &gl1mfn); if ( !pl1e ) @@ -3173,7 +3226,7 @@ static int ptwr_emulated_update( } } - adjust_guest_l1e(nl1e); + adjust_guest_l1e(nl1e, d); /* Checked successfully: do the update (write or cmpxchg). */ pl1e = map_domain_page(page_to_mfn(page)); diff -r 4c8f157a3a47 -r f632c0c36976 xen/arch/x86/x86_64/mm.c --- a/xen/arch/x86/x86_64/mm.c Fri Jan 05 17:34:29 2007 +0000 +++ b/xen/arch/x86/x86_64/mm.c Fri Jan 05 17:34:30 2007 +0000 @@ -31,6 +31,10 @@ #include <asm/msr.h> #include <public/memory.h> +#ifdef CONFIG_COMPAT +unsigned int m2p_compat_vstart = __HYPERVISOR_COMPAT_VIRT_START; +#endif + struct page_info *alloc_xen_pagetable(void) { extern int early_boot; @@ -121,6 +125,47 @@ void __init paging_init(void) l2_ro_mpt++; } +#ifdef CONFIG_COMPAT + if ( !compat_disabled ) + { + /* Create user-accessible L2 directory to map the MPT for compatibility guests. */ + BUILD_BUG_ON(l4_table_offset(RDWR_MPT_VIRT_START) != + l4_table_offset(HIRO_COMPAT_MPT_VIRT_START)); + l3_ro_mpt = l4e_to_l3e(idle_pg_table[l4_table_offset(HIRO_COMPAT_MPT_VIRT_START)]); + if ( (l2_pg = alloc_domheap_page(NULL)) == NULL ) + goto nomem; + compat_idle_pg_table_l2 = l2_ro_mpt = clear_page(page_to_virt(l2_pg)); + l3e_write(&l3_ro_mpt[l3_table_offset(HIRO_COMPAT_MPT_VIRT_START)], + l3e_from_page(l2_pg, __PAGE_HYPERVISOR)); + l2_ro_mpt += l2_table_offset(HIRO_COMPAT_MPT_VIRT_START); + /* + * Allocate and map the compatibility mode machine-to-phys table. + */ + mpt_size = (mpt_size >> 1) + (1UL << (L2_PAGETABLE_SHIFT - 1)); + if ( mpt_size > RDWR_COMPAT_MPT_VIRT_END - RDWR_COMPAT_MPT_VIRT_START ) + mpt_size = RDWR_COMPAT_MPT_VIRT_END - RDWR_COMPAT_MPT_VIRT_START; + mpt_size &= ~((1UL << L2_PAGETABLE_SHIFT) - 1UL); + if ( m2p_compat_vstart + mpt_size < MACH2PHYS_COMPAT_VIRT_END ) + m2p_compat_vstart = MACH2PHYS_COMPAT_VIRT_END - mpt_size; + for ( i = 0; i < (mpt_size >> L2_PAGETABLE_SHIFT); i++ ) + { + if ( (l1_pg = alloc_domheap_pages(NULL, PAGETABLE_ORDER, 0)) == NULL ) + goto nomem; + map_pages_to_xen( + RDWR_COMPAT_MPT_VIRT_START + (i << L2_PAGETABLE_SHIFT), + page_to_mfn(l1_pg), + 1UL << PAGETABLE_ORDER, + PAGE_HYPERVISOR); + memset((void *)(RDWR_COMPAT_MPT_VIRT_START + (i << L2_PAGETABLE_SHIFT)), + 0x55, + 1UL << L2_PAGETABLE_SHIFT); + /* NB. Cannot be GLOBAL as the pt entries get copied into per-VM space. */ + l2e_write(l2_ro_mpt, l2e_from_page(l1_pg, _PAGE_PSE|_PAGE_PRESENT)); + l2_ro_mpt++; + } + } +#endif + /* Set up linear page table mapping. */ l4e_write(&idle_pg_table[l4_table_offset(LINEAR_PT_VIRT_START)], l4e_from_paddr(__pa(idle_pg_table), __PAGE_HYPERVISOR)); @@ -182,6 +227,30 @@ void subarch_init_memory(void) share_xen_page_with_privileged_guests(page, XENSHARE_readonly); } } +#ifdef CONFIG_COMPAT + if ( !compat_disabled ) + { + for ( v = RDWR_COMPAT_MPT_VIRT_START; + v != RDWR_COMPAT_MPT_VIRT_END; + v += 1 << L2_PAGETABLE_SHIFT ) + { + l3e = l4e_to_l3e(idle_pg_table[l4_table_offset(v)])[ + l3_table_offset(v)]; + if ( !(l3e_get_flags(l3e) & _PAGE_PRESENT) ) + continue; + l2e = l3e_to_l2e(l3e)[l2_table_offset(v)]; + if ( !(l2e_get_flags(l2e) & _PAGE_PRESENT) ) + continue; + m2p_start_mfn = l2e_get_pfn(l2e); + + for ( i = 0; i < L1_PAGETABLE_ENTRIES; i++ ) + { + struct page_info *page = mfn_to_page(m2p_start_mfn + i); + share_xen_page_with_privileged_guests(page, XENSHARE_readonly); + } + } + } +#endif } long subarch_memory_op(int op, XEN_GUEST_HANDLE(void) arg) @@ -189,7 +258,8 @@ long subarch_memory_op(int op, XEN_GUEST struct xen_machphys_mfn_list xmml; l3_pgentry_t l3e; l2_pgentry_t l2e; - unsigned long mfn, v; + unsigned long v; + xen_pfn_t mfn; unsigned int i; long rc = 0; diff -r 4c8f157a3a47 -r f632c0c36976 xen/common/compat/kernel.c --- a/xen/common/compat/kernel.c Fri Jan 05 17:34:29 2007 +0000 +++ b/xen/common/compat/kernel.c Fri Jan 05 17:34:30 2007 +0000 @@ -27,7 +27,7 @@ CHECK_TYPE(capabilities_info); #define xen_platform_parameters compat_platform_parameters #define xen_platform_parameters_t compat_platform_parameters_t #undef HYPERVISOR_VIRT_START -#define HYPERVISOR_VIRT_START HYPERVISOR_COMPAT_VIRT_START +#define HYPERVISOR_VIRT_START HYPERVISOR_COMPAT_VIRT_START(current->domain) #define xen_changeset_info compat_changeset_info #define xen_changeset_info_t compat_changeset_info_t diff -r 4c8f157a3a47 -r f632c0c36976 xen/include/asm-x86/config.h --- a/xen/include/asm-x86/config.h Fri Jan 05 17:34:29 2007 +0000 +++ b/xen/include/asm-x86/config.h Fri Jan 05 17:34:30 2007 +0000 @@ -129,7 +129,11 @@ * Page-frame information array. * 0xffff828800000000 - 0xffff828bffffffff [16GB, 2^34 bytes, PML4:261] * ioremap()/fixmap area. - * 0xffff828c00000000 - 0xffff82ffffffffff [464GB, PML4:261] + * 0xffff828c00000000 - 0xffff828c3fffffff [1GB, 2^30 bytes, PML4:261] + * Compatibility machine-to-phys translation table. + * 0xffff828c40000000 - 0xffff828c7fffffff [1GB, 2^30 bytes, PML4:261] + * High read-only compatibility machine-to-phys translation table. + * 0xffff828c80000000 - 0xffff82ffffffffff [462GB, PML4:261] * Reserved for future use. * 0xffff830000000000 - 0xffff83ffffffffff [1TB, 2^40 bytes, PML4:262-263] * 1:1 direct mapping of all physical memory. Xen and its heap live here. @@ -178,17 +182,33 @@ /* Slot 261: ioremap()/fixmap area (16GB). */ #define IOREMAP_VIRT_START (FRAMETABLE_VIRT_END) #define IOREMAP_VIRT_END (IOREMAP_VIRT_START + (16UL<<30)) +/* Slot 261: compatibility machine-to-phys conversion table (1GB). */ +#define RDWR_COMPAT_MPT_VIRT_START IOREMAP_VIRT_END +#define RDWR_COMPAT_MPT_VIRT_END (RDWR_COMPAT_MPT_VIRT_START + (1UL << 30)) +/* Slot 261: high read-only compatibility machine-to-phys conversion table (1GB). */ +#define HIRO_COMPAT_MPT_VIRT_START RDWR_COMPAT_MPT_VIRT_END +#define HIRO_COMPAT_MPT_VIRT_END (HIRO_COMPAT_MPT_VIRT_START + (1UL << 30)) /* Slot 262-263: A direct 1:1 mapping of all of physical memory. */ #define DIRECTMAP_VIRT_START (PML4_ADDR(262)) #define DIRECTMAP_VIRT_END (DIRECTMAP_VIRT_START + PML4_ENTRY_BYTES*2) +#ifndef __ASSEMBLY__ + +/* This is not a fixed value, just a lower limit. */ #define __HYPERVISOR_COMPAT_VIRT_START 0xF5800000 -#define HYPERVISOR_COMPAT_VIRT_START \ - mk_unsigned_long(__HYPERVISOR_COMPAT_VIRT_START) +#define HYPERVISOR_COMPAT_VIRT_START(d) ((d)->arch.hv_compat_vstart) #define MACH2PHYS_COMPAT_VIRT_START HYPERVISOR_COMPAT_VIRT_START #define MACH2PHYS_COMPAT_VIRT_END 0xFFE00000 -#define MACH2PHYS_COMPAT_NR_ENTRIES \ - ((MACH2PHYS_COMPAT_VIRT_END-MACH2PHYS_COMPAT_VIRT_START)>>2) +#define MACH2PHYS_COMPAT_NR_ENTRIES(d) \ + ((MACH2PHYS_COMPAT_VIRT_END-MACH2PHYS_COMPAT_VIRT_START(d))>>2) + +#define COMPAT_L2_PAGETABLE_FIRST_XEN_SLOT(d) \ + l2_table_offset(HYPERVISOR_COMPAT_VIRT_START(d)) +#define COMPAT_L2_PAGETABLE_LAST_XEN_SLOT l2_table_offset(~0U) +#define COMPAT_L2_PAGETABLE_XEN_SLOTS(d) \ + (COMPAT_L2_PAGETABLE_LAST_XEN_SLOT - COMPAT_L2_PAGETABLE_FIRST_XEN_SLOT(d) + 1) + +#endif #define PGT_base_page_table PGT_l4_page_table diff -r 4c8f157a3a47 -r f632c0c36976 xen/include/asm-x86/domain.h --- a/xen/include/asm-x86/domain.h Fri Jan 05 17:34:29 2007 +0000 +++ b/xen/include/asm-x86/domain.h Fri Jan 05 17:34:30 2007 +0000 @@ -98,6 +98,10 @@ struct arch_domain struct mapcache mapcache; #endif +#ifdef CONFIG_COMPAT + unsigned int hv_compat_vstart; +#endif + /* I/O-port admin-specified access capabilities. */ struct rangeset *ioport_caps; diff -r 4c8f157a3a47 -r f632c0c36976 xen/include/asm-x86/mm.h --- a/xen/include/asm-x86/mm.h Fri Jan 05 17:34:29 2007 +0000 +++ b/xen/include/asm-x86/mm.h Fri Jan 05 17:34:30 2007 +0000 @@ -257,7 +257,16 @@ int check_descriptor(const struct domain #define INVALID_M2P_ENTRY (~0UL) #define VALID_M2P(_e) (!((_e) & (1UL<<(BITS_PER_LONG-1)))) +#ifdef CONFIG_COMPAT +#define compat_machine_to_phys_mapping ((unsigned int *)RDWR_COMPAT_MPT_VIRT_START) +#define set_gpfn_from_mfn(mfn, pfn) \ + ((void)(compat_disabled || \ + (mfn) >= (RDWR_COMPAT_MPT_VIRT_END - RDWR_COMPAT_MPT_VIRT_START) / 4 || \ + (compat_machine_to_phys_mapping[(mfn)] = (unsigned int)(pfn))), \ + machine_to_phys_mapping[(mfn)] = (pfn)) +#else #define set_gpfn_from_mfn(mfn, pfn) (machine_to_phys_mapping[(mfn)] = (pfn)) +#endif #define get_gpfn_from_mfn(mfn) (machine_to_phys_mapping[(mfn)]) diff -r 4c8f157a3a47 -r f632c0c36976 xen/include/asm-x86/page.h --- a/xen/include/asm-x86/page.h Fri Jan 05 17:34:29 2007 +0000 +++ b/xen/include/asm-x86/page.h Fri Jan 05 17:34:30 2007 +0000 @@ -206,6 +206,7 @@ typedef struct { u64 pfn; } pagetable_t; typedef struct { u64 pfn; } pagetable_t; #endif #define pagetable_get_paddr(x) ((paddr_t)(x).pfn << PAGE_SHIFT) +#define pagetable_get_page(x) mfn_to_page((x).pfn) #define pagetable_get_pfn(x) ((x).pfn) #define pagetable_is_null(x) ((x).pfn == 0) #define pagetable_from_pfn(pfn) ((pagetable_t) { (pfn) }) @@ -287,6 +288,10 @@ extern l2_pgentry_t idle_pg_table_l2[R #else extern root_pgentry_t idle_pg_table[ROOT_PAGETABLE_ENTRIES]; extern l2_pgentry_t idle_pg_table_l2[ROOT_PAGETABLE_ENTRIES]; +#ifdef CONFIG_COMPAT +extern l2_pgentry_t *compat_idle_pg_table_l2; +extern unsigned int m2p_compat_vstart; +#endif #endif void paging_init(void); void setup_idle_pagetable(void); diff -r 4c8f157a3a47 -r f632c0c36976 xen/include/asm-x86/x86_32/page-2level.h --- a/xen/include/asm-x86/x86_32/page-2level.h Fri Jan 05 17:34:29 2007 +0000 +++ b/xen/include/asm-x86/x86_32/page-2level.h Fri Jan 05 17:34:30 2007 +0000 @@ -42,7 +42,7 @@ typedef l2_pgentry_t root_pgentry_t; /* misc */ #define is_guest_l1_slot(_s) (1) -#define is_guest_l2_slot(_t,_s) ((_s) < L2_PAGETABLE_FIRST_XEN_SLOT) +#define is_guest_l2_slot(_d, _t,_s) ((_s) < L2_PAGETABLE_FIRST_XEN_SLOT) /* * PTE pfn and flags: diff -r 4c8f157a3a47 -r f632c0c36976 xen/include/asm-x86/x86_32/page-3level.h --- a/xen/include/asm-x86/x86_32/page-3level.h Fri Jan 05 17:34:29 2007 +0000 +++ b/xen/include/asm-x86/x86_32/page-3level.h Fri Jan 05 17:34:30 2007 +0000 @@ -67,7 +67,7 @@ typedef l3_pgentry_t root_pgentry_t; /* misc */ #define is_guest_l1_slot(s) (1) -#define is_guest_l2_slot(t,s) \ +#define is_guest_l2_slot(d,t,s) \ ( !((t) & PGT_pae_xen_l2) || \ ((s) < (L2_PAGETABLE_FIRST_XEN_SLOT & (L2_PAGETABLE_ENTRIES - 1))) ) #define is_guest_l3_slot(s) (1) diff -r 4c8f157a3a47 -r f632c0c36976 xen/include/asm-x86/x86_64/page.h --- a/xen/include/asm-x86/x86_64/page.h Fri Jan 05 17:34:29 2007 +0000 +++ b/xen/include/asm-x86/x86_64/page.h Fri Jan 05 17:34:30 2007 +0000 @@ -54,7 +54,10 @@ typedef l4_pgentry_t root_pgentry_t; #define l4_linear_offset(_a) (((_a) & VADDR_MASK) >> L4_PAGETABLE_SHIFT) #define is_guest_l1_slot(_s) (1) -#define is_guest_l2_slot(_t, _s) (1) +#define is_guest_l2_slot(_d, _t, _s) \ + ( !IS_COMPAT(_d) || \ + !((_t) & PGT_pae_xen_l2) || \ + ((_s) < COMPAT_L2_PAGETABLE_FIRST_XEN_SLOT(_d)) ) #define is_guest_l3_slot(_s) (1) #define is_guest_l4_slot(_s) \ (((_s) < ROOT_PAGETABLE_FIRST_XEN_SLOT) || \ @@ -93,6 +96,8 @@ typedef l4_pgentry_t root_pgentry_t; #define L3_DISALLOW_MASK (BASE_DISALLOW_MASK | 0x180U /* must-be-zero */) #define L4_DISALLOW_MASK (BASE_DISALLOW_MASK | 0x180U /* must-be-zero */) +#define COMPAT_L3_DISALLOW_MASK 0xFFFFF1E6U /* must-be-zero */ + #define PAGE_HYPERVISOR (__PAGE_HYPERVISOR | _PAGE_GLOBAL) #define PAGE_HYPERVISOR_NOCACHE (__PAGE_HYPERVISOR_NOCACHE | _PAGE_GLOBAL) diff -r 4c8f157a3a47 -r f632c0c36976 xen/include/asm-x86/x86_64/uaccess.h --- a/xen/include/asm-x86/x86_64/uaccess.h Fri Jan 05 17:34:29 2007 +0000 +++ b/xen/include/asm-x86/x86_64/uaccess.h Fri Jan 05 17:34:30 2007 +0000 @@ -18,7 +18,7 @@ #ifdef CONFIG_COMPAT #define __compat_addr_ok(addr) \ - ((unsigned long)(addr) < HYPERVISOR_COMPAT_VIRT_START) + ((unsigned long)(addr) < HYPERVISOR_COMPAT_VIRT_START(current->domain)) #define compat_access_ok(addr, size) __compat_addr_ok((addr) + (size)) _______________________________________________ Xen-changelog mailing list Xen-changelog@xxxxxxxxxxxxxxxxxxx http://lists.xensource.com/xen-changelog
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |