1059 lines
42 KiB
Diff
1059 lines
42 KiB
Diff
|
Introduce _DOMF_compat and infrastructure as well as several conditionals
|
||
|
dealing with operations that need to distinguish between native and
|
||
|
compatibility mode guests.
|
||
|
|
||
|
Index: 2007-01-08/config/x86_64.mk
|
||
|
===================================================================
|
||
|
--- 2007-01-08.orig/config/x86_64.mk 2007-01-08 15:34:30.000000000 +0100
|
||
|
+++ 2007-01-08/config/x86_64.mk 2007-01-08 14:45:40.000000000 +0100
|
||
|
@@ -2,6 +2,7 @@ CONFIG_X86 := y
|
||
|
CONFIG_X86_64 := y
|
||
|
CONFIG_X86_$(XEN_OS) := y
|
||
|
|
||
|
+CONFIG_COMPAT := y
|
||
|
CONFIG_HVM := y
|
||
|
CONFIG_MIGRATE := y
|
||
|
CONFIG_XCUTILS := y
|
||
|
Index: 2007-01-08/tools/libxc/xc_linux_build.c
|
||
|
===================================================================
|
||
|
--- 2007-01-08.orig/tools/libxc/xc_linux_build.c 2007-01-08 15:34:30.000000000 +0100
|
||
|
+++ 2007-01-08/tools/libxc/xc_linux_build.c 2007-01-08 14:45:40.000000000 +0100
|
||
|
@@ -595,6 +595,7 @@ static int compat_check(int xc_handle, s
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
+#ifndef __x86_64__//temp
|
||
|
if (strstr(xen_caps, "xen-3.0-x86_32p")) {
|
||
|
if (dsi->pae_kernel == PAEKERN_bimodal) {
|
||
|
dsi->pae_kernel = PAEKERN_extended_cr3;
|
||
|
@@ -612,6 +613,7 @@ static int compat_check(int xc_handle, s
|
||
|
return 0;
|
||
|
}
|
||
|
}
|
||
|
+#endif
|
||
|
|
||
|
return 1;
|
||
|
}
|
||
|
Index: 2007-01-08/xen/arch/x86/boot/x86_64.S
|
||
|
===================================================================
|
||
|
--- 2007-01-08.orig/xen/arch/x86/boot/x86_64.S 2007-01-08 15:34:30.000000000 +0100
|
||
|
+++ 2007-01-08/xen/arch/x86/boot/x86_64.S 2007-01-08 14:45:40.000000000 +0100
|
||
|
@@ -226,15 +226,34 @@ high_start:
|
||
|
.align PAGE_SIZE, 0
|
||
|
ENTRY(gdt_table)
|
||
|
.quad 0x0000000000000000 /* unused */
|
||
|
- .quad 0x00cf9a000000ffff /* 0xe008 ring 0 code, compatibility */
|
||
|
- .quad 0x00af9a000000ffff /* 0xe010 ring 0 code, 64-bit mode */
|
||
|
- .quad 0x00cf92000000ffff /* 0xe018 ring 0 data */
|
||
|
+ .quad 0x00af9a000000ffff /* 0xe008 ring 0 code, 64-bit mode */
|
||
|
+ .quad 0x00cf92000000ffff /* 0xe010 ring 0 data */
|
||
|
+ .quad 0x0000000000000000 /* reserved */
|
||
|
.quad 0x00cffa000000ffff /* 0xe023 ring 3 code, compatibility */
|
||
|
.quad 0x00cff2000000ffff /* 0xe02b ring 3 data */
|
||
|
.quad 0x00affa000000ffff /* 0xe033 ring 3 code, 64-bit mode */
|
||
|
- .quad 0x0000000000000000 /* unused */
|
||
|
+ .quad 0x00cf9a000000ffff /* 0xe038 ring 0 code, compatibility */
|
||
|
+ .org gdt_table - FIRST_RESERVED_GDT_BYTE + __TSS(0) * 8
|
||
|
.fill 4*NR_CPUS,8,0 /* space for TSS and LDT per CPU */
|
||
|
|
||
|
+#ifdef CONFIG_COMPAT
|
||
|
+ .align PAGE_SIZE, 0
|
||
|
+/* NB. Even rings != 0 get access to the full 4Gb, as only the */
|
||
|
+/* (compatibility) machine->physical mapping table lives there. */
|
||
|
+ENTRY(compat_gdt_table)
|
||
|
+ .quad 0x0000000000000000 /* unused */
|
||
|
+ .quad 0x00af9a000000ffff /* 0xe008 ring 0 code, 64-bit mode */
|
||
|
+ .quad 0x00cf92000000ffff /* 0xe010 ring 0 data */
|
||
|
+ .quad 0x00cfba000000ffff /* 0xe019 ring 1 code, compatibility */
|
||
|
+ .quad 0x00cfb2000000ffff /* 0xe021 ring 1 data */
|
||
|
+ .quad 0x00cffa000000ffff /* 0xe02b ring 3 code, compatibility */
|
||
|
+ .quad 0x00cff2000000ffff /* 0xe033 ring 3 data */
|
||
|
+ .quad 0x00cf9a000000ffff /* 0xe038 ring 0 code, compatibility */
|
||
|
+ .org compat_gdt_table - FIRST_RESERVED_GDT_BYTE + __TSS(0) * 8
|
||
|
+ .fill 4*NR_CPUS,8,0 /* space for TSS and LDT per CPU */
|
||
|
+# undef LIMIT
|
||
|
+#endif
|
||
|
+
|
||
|
/* Initial PML4 -- level-4 page table. */
|
||
|
.align PAGE_SIZE, 0
|
||
|
ENTRY(idle_pg_table)
|
||
|
Index: 2007-01-08/xen/arch/x86/domain.c
|
||
|
===================================================================
|
||
|
--- 2007-01-08.orig/xen/arch/x86/domain.c 2007-01-08 15:34:30.000000000 +0100
|
||
|
+++ 2007-01-08/xen/arch/x86/domain.c 2007-01-08 14:45:40.000000000 +0100
|
||
|
@@ -287,17 +287,18 @@ int arch_set_info_guest(
|
||
|
|
||
|
if ( !is_hvm_vcpu(v) )
|
||
|
{
|
||
|
- fixup_guest_stack_selector(c->user_regs.ss);
|
||
|
- fixup_guest_stack_selector(c->kernel_ss);
|
||
|
- fixup_guest_code_selector(c->user_regs.cs);
|
||
|
-
|
||
|
-#ifdef __i386__
|
||
|
- fixup_guest_code_selector(c->event_callback_cs);
|
||
|
- fixup_guest_code_selector(c->failsafe_callback_cs);
|
||
|
-#endif
|
||
|
+ fixup_guest_stack_selector(d, c->user_regs.ss);
|
||
|
+ fixup_guest_stack_selector(d, c->kernel_ss);
|
||
|
+ fixup_guest_code_selector(d, c->user_regs.cs);
|
||
|
+
|
||
|
+ if ( CONFIG_PAGING_LEVELS < 4 || IS_COMPAT(d) )
|
||
|
+ {
|
||
|
+ fixup_guest_code_selector(d, c->event_callback_cs);
|
||
|
+ fixup_guest_code_selector(d, c->failsafe_callback_cs);
|
||
|
+ }
|
||
|
|
||
|
for ( i = 0; i < 256; i++ )
|
||
|
- fixup_guest_code_selector(c->trap_ctxt[i].cs);
|
||
|
+ fixup_guest_code_selector(d, c->trap_ctxt[i].cs);
|
||
|
|
||
|
/* LDT safety checks. */
|
||
|
if ( ((c->ldt_base & (PAGE_SIZE-1)) != 0) ||
|
||
|
@@ -502,27 +503,30 @@ static void load_segments(struct vcpu *n
|
||
|
all_segs_okay &= loadsegment(gs, nctxt->user_regs.gs);
|
||
|
}
|
||
|
|
||
|
- /* This can only be non-zero if selector is NULL. */
|
||
|
- if ( nctxt->fs_base )
|
||
|
- wrmsr(MSR_FS_BASE,
|
||
|
- nctxt->fs_base,
|
||
|
- nctxt->fs_base>>32);
|
||
|
-
|
||
|
- /* Most kernels have non-zero GS base, so don't bother testing. */
|
||
|
- /* (This is also a serialising instruction, avoiding AMD erratum #88.) */
|
||
|
- wrmsr(MSR_SHADOW_GS_BASE,
|
||
|
- nctxt->gs_base_kernel,
|
||
|
- nctxt->gs_base_kernel>>32);
|
||
|
-
|
||
|
- /* This can only be non-zero if selector is NULL. */
|
||
|
- if ( nctxt->gs_base_user )
|
||
|
- wrmsr(MSR_GS_BASE,
|
||
|
- nctxt->gs_base_user,
|
||
|
- nctxt->gs_base_user>>32);
|
||
|
-
|
||
|
- /* If in kernel mode then switch the GS bases around. */
|
||
|
- if ( n->arch.flags & TF_kernel_mode )
|
||
|
- __asm__ __volatile__ ( "swapgs" );
|
||
|
+ if ( !IS_COMPAT(n->domain) )
|
||
|
+ {
|
||
|
+ /* This can only be non-zero if selector is NULL. */
|
||
|
+ if ( nctxt->fs_base )
|
||
|
+ wrmsr(MSR_FS_BASE,
|
||
|
+ nctxt->fs_base,
|
||
|
+ nctxt->fs_base>>32);
|
||
|
+
|
||
|
+ /* Most kernels have non-zero GS base, so don't bother testing. */
|
||
|
+ /* (This is also a serialising instruction, avoiding AMD erratum #88.) */
|
||
|
+ wrmsr(MSR_SHADOW_GS_BASE,
|
||
|
+ nctxt->gs_base_kernel,
|
||
|
+ nctxt->gs_base_kernel>>32);
|
||
|
+
|
||
|
+ /* This can only be non-zero if selector is NULL. */
|
||
|
+ if ( nctxt->gs_base_user )
|
||
|
+ wrmsr(MSR_GS_BASE,
|
||
|
+ nctxt->gs_base_user,
|
||
|
+ nctxt->gs_base_user>>32);
|
||
|
+
|
||
|
+ /* If in kernel mode then switch the GS bases around. */
|
||
|
+ if ( (n->arch.flags & TF_kernel_mode) )
|
||
|
+ __asm__ __volatile__ ( "swapgs" );
|
||
|
+ }
|
||
|
|
||
|
if ( unlikely(!all_segs_okay) )
|
||
|
{
|
||
|
@@ -533,6 +537,55 @@ static void load_segments(struct vcpu *n
|
||
|
(unsigned long *)nctxt->kernel_sp;
|
||
|
unsigned long cs_and_mask, rflags;
|
||
|
|
||
|
+ if ( IS_COMPAT(n->domain) )
|
||
|
+ {
|
||
|
+ unsigned int *esp = ring_1(regs) ?
|
||
|
+ (unsigned int *)regs->rsp :
|
||
|
+ (unsigned int *)nctxt->kernel_sp;
|
||
|
+ unsigned int cs_and_mask, eflags;
|
||
|
+ int ret = 0;
|
||
|
+
|
||
|
+ /* CS longword also contains full evtchn_upcall_mask. */
|
||
|
+ cs_and_mask = (unsigned short)regs->cs |
|
||
|
+ ((unsigned int)n->vcpu_info->evtchn_upcall_mask << 16);
|
||
|
+ /* Fold upcall mask into RFLAGS.IF. */
|
||
|
+ eflags = regs->_eflags & ~X86_EFLAGS_IF;
|
||
|
+ eflags |= !n->vcpu_info->evtchn_upcall_mask << 9;
|
||
|
+
|
||
|
+ if ( !ring_1(regs) )
|
||
|
+ {
|
||
|
+ ret = put_user(regs->ss, esp-1);
|
||
|
+ ret |= put_user(regs->_esp, esp-2);
|
||
|
+ esp -= 2;
|
||
|
+ }
|
||
|
+
|
||
|
+ if ( ret |
|
||
|
+ put_user(eflags, esp-1) |
|
||
|
+ put_user(cs_and_mask, esp-2) |
|
||
|
+ put_user(regs->_eip, esp-3) |
|
||
|
+ put_user(nctxt->user_regs.gs, esp-4) |
|
||
|
+ put_user(nctxt->user_regs.fs, esp-5) |
|
||
|
+ put_user(nctxt->user_regs.es, esp-6) |
|
||
|
+ put_user(nctxt->user_regs.ds, esp-7) )
|
||
|
+ {
|
||
|
+ gdprintk(XENLOG_ERR, "Error while creating compat "
|
||
|
+ "failsafe callback frame.\n");
|
||
|
+ domain_crash(n->domain);
|
||
|
+ }
|
||
|
+
|
||
|
+ if ( test_bit(_VGCF_failsafe_disables_events,
|
||
|
+ &n->arch.guest_context.flags) )
|
||
|
+ n->vcpu_info->evtchn_upcall_mask = 1;
|
||
|
+
|
||
|
+ regs->entry_vector = TRAP_syscall;
|
||
|
+ regs->_eflags &= 0xFFFCBEFFUL;
|
||
|
+ regs->ss = FLAT_COMPAT_KERNEL_SS;
|
||
|
+ regs->_esp = (unsigned long)(esp-7);
|
||
|
+ regs->cs = FLAT_COMPAT_KERNEL_CS;
|
||
|
+ regs->_eip = nctxt->failsafe_callback_eip;
|
||
|
+ return;
|
||
|
+ }
|
||
|
+
|
||
|
if ( !(n->arch.flags & TF_kernel_mode) )
|
||
|
toggle_guest_mode(n);
|
||
|
else
|
||
|
@@ -594,7 +647,7 @@ static void save_segments(struct vcpu *v
|
||
|
if ( regs->es )
|
||
|
dirty_segment_mask |= DIRTY_ES;
|
||
|
|
||
|
- if ( regs->fs )
|
||
|
+ if ( regs->fs || IS_COMPAT(v->domain) )
|
||
|
{
|
||
|
dirty_segment_mask |= DIRTY_FS;
|
||
|
ctxt->fs_base = 0; /* != 0 selector kills fs_base */
|
||
|
@@ -604,7 +657,7 @@ static void save_segments(struct vcpu *v
|
||
|
dirty_segment_mask |= DIRTY_FS_BASE;
|
||
|
}
|
||
|
|
||
|
- if ( regs->gs )
|
||
|
+ if ( regs->gs || IS_COMPAT(v->domain) )
|
||
|
{
|
||
|
dirty_segment_mask |= DIRTY_GS;
|
||
|
ctxt->gs_base_user = 0; /* != 0 selector kills gs_base_user */
|
||
|
@@ -736,6 +789,23 @@ void context_switch(struct vcpu *prev, s
|
||
|
{
|
||
|
__context_switch();
|
||
|
|
||
|
+#ifdef CONFIG_COMPAT
|
||
|
+ if ( is_idle_vcpu(prev)
|
||
|
+ || IS_COMPAT(prev->domain) != IS_COMPAT(next->domain) )
|
||
|
+ {
|
||
|
+ uint32_t efer_lo, efer_hi;
|
||
|
+
|
||
|
+ local_flush_tlb_one(GDT_VIRT_START(next) + FIRST_RESERVED_GDT_BYTE);
|
||
|
+
|
||
|
+ rdmsr(MSR_EFER, efer_lo, efer_hi);
|
||
|
+ if ( !IS_COMPAT(next->domain) == !(efer_lo & EFER_SCE) )
|
||
|
+ {
|
||
|
+ efer_lo ^= EFER_SCE;
|
||
|
+ wrmsr(MSR_EFER, efer_lo, efer_hi);
|
||
|
+ }
|
||
|
+ }
|
||
|
+#endif
|
||
|
+
|
||
|
/* Re-enable interrupts before restoring state which may fault. */
|
||
|
local_irq_enable();
|
||
|
|
||
|
@@ -948,6 +1018,10 @@ void domain_relinquish_resources(struct
|
||
|
put_page(mfn_to_page(pfn));
|
||
|
else
|
||
|
put_page_and_type(mfn_to_page(pfn));
|
||
|
+#ifdef __x86_64__
|
||
|
+ if ( pfn == pagetable_get_pfn(v->arch.guest_table_user) )
|
||
|
+ v->arch.guest_table_user = pagetable_null();
|
||
|
+#endif
|
||
|
v->arch.guest_table = pagetable_null();
|
||
|
}
|
||
|
|
||
|
Index: 2007-01-08/xen/arch/x86/domain_build.c
|
||
|
===================================================================
|
||
|
--- 2007-01-08.orig/xen/arch/x86/domain_build.c 2007-01-08 15:34:30.000000000 +0100
|
||
|
+++ 2007-01-08/xen/arch/x86/domain_build.c 2007-01-08 15:34:55.000000000 +0100
|
||
|
@@ -319,10 +319,38 @@ int construct_dom0(struct domain *d,
|
||
|
|
||
|
nr_pages = compute_dom0_nr_pages();
|
||
|
|
||
|
- if ( (rc = parseelfimage(&dsi)) != 0 )
|
||
|
- return rc;
|
||
|
+ rc = parseelfimage(&dsi);
|
||
|
+#ifdef CONFIG_COMPAT
|
||
|
+ if ( rc == -ENOSYS
|
||
|
+ && (rc = parseelf32image(&dsi)) == 0 )
|
||
|
+ {
|
||
|
+ l1_pgentry_t gdt_l1e;
|
||
|
+
|
||
|
+ set_bit(_DOMF_compat, &d->domain_flags);
|
||
|
+
|
||
|
+ if ( nr_pages != (unsigned int)nr_pages )
|
||
|
+ nr_pages = UINT_MAX;
|
||
|
+
|
||
|
+ /*
|
||
|
+ * Map compatibility Xen segments into every VCPU's GDT. See
|
||
|
+ * arch_domain_create() for further comments.
|
||
|
+ */
|
||
|
+ gdt_l1e = l1e_from_page(virt_to_page(compat_gdt_table),
|
||
|
+ PAGE_HYPERVISOR);
|
||
|
+ for ( i = 0; i < MAX_VIRT_CPUS; i++ )
|
||
|
+ d->arch.mm_perdomain_pt[((i << GDT_LDT_VCPU_SHIFT) +
|
||
|
+ FIRST_RESERVED_GDT_PAGE)] = gdt_l1e;
|
||
|
+ local_flush_tlb_one(GDT_LDT_VIRT_START + FIRST_RESERVED_GDT_BYTE);
|
||
|
+ }
|
||
|
+#endif
|
||
|
+ if ( rc != 0)
|
||
|
+ {
|
||
|
+ if ( rc == -ENOSYS )
|
||
|
+ printk("DOM0 image is not a Xen-compatible Elf image.\n");
|
||
|
+ return rc;
|
||
|
+ }
|
||
|
|
||
|
- xen_pae = (CONFIG_PAGING_LEVELS == 3);
|
||
|
+ xen_pae = (CONFIG_PAGING_LEVELS == 3) || IS_COMPAT(d);
|
||
|
if (dsi.pae_kernel == PAEKERN_bimodal)
|
||
|
dom0_pae = xen_pae;
|
||
|
else
|
||
|
@@ -338,7 +366,13 @@ int construct_dom0(struct domain *d,
|
||
|
dsi.pae_kernel == PAEKERN_bimodal) )
|
||
|
set_bit(VMASST_TYPE_pae_extended_cr3, &d->vm_assist);
|
||
|
|
||
|
- if ( (p = xen_elfnote_string(&dsi, XEN_ELFNOTE_FEATURES)) != NULL )
|
||
|
+#ifdef CONFIG_COMPAT
|
||
|
+ if ( IS_COMPAT(d) )
|
||
|
+ p = xen_elf32note_string(&dsi, XEN_ELFNOTE_FEATURES);
|
||
|
+ else
|
||
|
+#endif
|
||
|
+ p = xen_elfnote_string(&dsi, XEN_ELFNOTE_FEATURES);
|
||
|
+ if ( p != NULL )
|
||
|
{
|
||
|
parse_features(p,
|
||
|
dom0_features_supported,
|
||
|
@@ -590,6 +624,12 @@ int construct_dom0(struct domain *d,
|
||
|
return -EINVAL;
|
||
|
}
|
||
|
|
||
|
+ if ( IS_COMPAT(d) )
|
||
|
+ {
|
||
|
+ v->arch.guest_context.failsafe_callback_cs = FLAT_COMPAT_KERNEL_CS;
|
||
|
+ v->arch.guest_context.event_callback_cs = FLAT_COMPAT_KERNEL_CS;
|
||
|
+ }
|
||
|
+
|
||
|
/* 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;
|
||
|
@@ -599,6 +639,8 @@ int construct_dom0(struct domain *d,
|
||
|
l4tab[l4_table_offset(PERDOMAIN_VIRT_START)] =
|
||
|
l4e_from_paddr(__pa(d->arch.mm_perdomain_l3), __PAGE_HYPERVISOR);
|
||
|
v->arch.guest_table = pagetable_from_paddr(__pa(l4start));
|
||
|
+ if ( IS_COMPAT(d) )
|
||
|
+ v->arch.guest_table_user = v->arch.guest_table;
|
||
|
|
||
|
l4tab += l4_table_offset(dsi.v_start);
|
||
|
mfn = alloc_spfn;
|
||
|
@@ -711,10 +753,20 @@ int construct_dom0(struct domain *d,
|
||
|
write_ptbase(v);
|
||
|
|
||
|
/* Copy the OS image and free temporary buffer. */
|
||
|
- (void)loadelfimage(&dsi);
|
||
|
-
|
||
|
- hypercall_page =
|
||
|
- xen_elfnote_numeric(&dsi, XEN_ELFNOTE_HYPERCALL_PAGE, &hypercall_page_defined);
|
||
|
+#ifdef CONFIG_COMPAT
|
||
|
+ if ( IS_COMPAT(d) )
|
||
|
+ {
|
||
|
+ (void)loadelf32image(&dsi);
|
||
|
+ hypercall_page =
|
||
|
+ xen_elf32note_numeric(&dsi, XEN_ELFNOTE_HYPERCALL_PAGE, &hypercall_page_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) )
|
||
|
@@ -747,7 +799,7 @@ int construct_dom0(struct domain *d,
|
||
|
si->mfn_list = vphysmap_start;
|
||
|
sprintf(si->magic, "xen-%i.%i-x86_%d%s",
|
||
|
xen_major_version(), xen_minor_version(),
|
||
|
- BITS_PER_LONG, xen_pae ? "p" : "");
|
||
|
+ !IS_COMPAT(d) ? BITS_PER_LONG : 32, xen_pae ? "p" : "");
|
||
|
|
||
|
/* Write the phys->machine and machine->phys table entries. */
|
||
|
for ( pfn = 0; pfn < d->tot_pages; pfn++ )
|
||
|
@@ -819,9 +871,11 @@ int construct_dom0(struct domain *d,
|
||
|
* [EAX,EBX,ECX,EDX,EDI,EBP are zero]
|
||
|
*/
|
||
|
regs = &v->arch.guest_context.user_regs;
|
||
|
- regs->ds = regs->es = regs->fs = regs->gs = FLAT_KERNEL_DS;
|
||
|
- regs->ss = FLAT_KERNEL_SS;
|
||
|
- regs->cs = FLAT_KERNEL_CS;
|
||
|
+ regs->ds = regs->es = regs->fs = regs->gs = !IS_COMPAT(d)
|
||
|
+ ? FLAT_KERNEL_DS
|
||
|
+ : FLAT_COMPAT_KERNEL_DS;
|
||
|
+ regs->ss = !IS_COMPAT(d) ? FLAT_KERNEL_SS : FLAT_COMPAT_KERNEL_SS;
|
||
|
+ regs->cs = !IS_COMPAT(d) ? FLAT_KERNEL_CS : FLAT_COMPAT_KERNEL_CS;
|
||
|
regs->eip = dsi.v_kernentry;
|
||
|
regs->esp = vstack_end;
|
||
|
regs->esi = vstartinfo_start;
|
||
|
@@ -906,13 +960,28 @@ int elf_sanity_check(const Elf_Ehdr *ehd
|
||
|
(ehdr->e_ident[EI_DATA] != ELFDATA2LSB) ||
|
||
|
(ehdr->e_type != ET_EXEC) )
|
||
|
{
|
||
|
- printk("DOM0 image is not a Xen-compatible Elf image.\n");
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
return 1;
|
||
|
}
|
||
|
|
||
|
+#ifdef CONFIG_COMPAT
|
||
|
+int elf32_sanity_check(const Elf32_Ehdr *ehdr)
|
||
|
+{
|
||
|
+ if ( !IS_ELF(*ehdr) ||
|
||
|
+ (ehdr->e_ident[EI_CLASS] != ELFCLASS32) ||
|
||
|
+ (ehdr->e_machine != EM_386) ||
|
||
|
+ (ehdr->e_ident[EI_DATA] != ELFDATA2LSB) ||
|
||
|
+ (ehdr->e_type != ET_EXEC) )
|
||
|
+ {
|
||
|
+ return 0;
|
||
|
+ }
|
||
|
+
|
||
|
+ return 1;
|
||
|
+}
|
||
|
+#endif
|
||
|
+
|
||
|
/*
|
||
|
* Local variables:
|
||
|
* mode: C
|
||
|
Index: 2007-01-08/xen/arch/x86/mm.c
|
||
|
===================================================================
|
||
|
--- 2007-01-08.orig/xen/arch/x86/mm.c 2007-01-08 15:34:30.000000000 +0100
|
||
|
+++ 2007-01-08/xen/arch/x86/mm.c 2007-01-08 14:45:40.000000000 +0100
|
||
|
@@ -401,7 +401,7 @@ static int alloc_segdesc_page(struct pag
|
||
|
descs = map_domain_page(page_to_mfn(page));
|
||
|
|
||
|
for ( i = 0; i < 512; i++ )
|
||
|
- if ( unlikely(!check_descriptor(&descs[i])) )
|
||
|
+ if ( unlikely(!check_descriptor(page_get_owner(page), &descs[i])) )
|
||
|
goto fail;
|
||
|
|
||
|
unmap_domain_page(descs);
|
||
|
@@ -2833,7 +2833,7 @@ long do_update_descriptor(u64 pa, u64 de
|
||
|
mfn = gmfn_to_mfn(dom, gmfn);
|
||
|
if ( (((unsigned int)pa % sizeof(struct desc_struct)) != 0) ||
|
||
|
!mfn_valid(mfn) ||
|
||
|
- !check_descriptor(&d) )
|
||
|
+ !check_descriptor(dom, &d) )
|
||
|
{
|
||
|
UNLOCK_BIGLOCK(dom);
|
||
|
return -EINVAL;
|
||
|
Index: 2007-01-08/xen/arch/x86/setup.c
|
||
|
===================================================================
|
||
|
--- 2007-01-08.orig/xen/arch/x86/setup.c 2007-01-08 15:34:30.000000000 +0100
|
||
|
+++ 2007-01-08/xen/arch/x86/setup.c 2007-01-08 14:45:40.000000000 +0100
|
||
|
@@ -791,6 +791,9 @@ void arch_get_xen_caps(xen_capabilities_
|
||
|
#elif defined(CONFIG_X86_64)
|
||
|
|
||
|
p += sprintf(p, "xen-%d.%d-x86_64 ", major, minor);
|
||
|
+#ifdef CONFIG_COMPAT
|
||
|
+ p += sprintf(p, "xen-%d.%d-x86_32p ", major, minor);
|
||
|
+#endif
|
||
|
if ( hvm_enabled )
|
||
|
{
|
||
|
p += sprintf(p, "hvm-%d.%d-x86_32 ", major, minor);
|
||
|
Index: 2007-01-08/xen/arch/x86/traps.c
|
||
|
===================================================================
|
||
|
--- 2007-01-08.orig/xen/arch/x86/traps.c 2007-01-08 15:34:30.000000000 +0100
|
||
|
+++ 2007-01-08/xen/arch/x86/traps.c 2007-01-08 14:45:40.000000000 +0100
|
||
|
@@ -398,7 +398,7 @@ static int do_guest_trap(
|
||
|
if ( TI_GET_IF(ti) )
|
||
|
tb->flags |= TBF_INTERRUPT;
|
||
|
|
||
|
- if ( unlikely(null_trap_bounce(tb)) )
|
||
|
+ if ( unlikely(null_trap_bounce(v, tb)) )
|
||
|
gdprintk(XENLOG_WARNING, "Unhandled %s fault/trap [#%d] in "
|
||
|
"domain %d on VCPU %d [ec=%04x]\n",
|
||
|
trapstr(trapnr), trapnr, v->domain->domain_id, v->vcpu_id,
|
||
|
@@ -689,7 +689,7 @@ void propagate_page_fault(unsigned long
|
||
|
tb->eip = ti->address;
|
||
|
if ( TI_GET_IF(ti) )
|
||
|
tb->flags |= TBF_INTERRUPT;
|
||
|
- if ( unlikely(null_trap_bounce(tb)) )
|
||
|
+ if ( unlikely(null_trap_bounce(v, tb)) )
|
||
|
{
|
||
|
printk("Unhandled page fault in domain %d on VCPU %d (ec=%04X)\n",
|
||
|
v->domain->domain_id, v->vcpu_id, error_code);
|
||
|
@@ -1801,6 +1801,13 @@ void set_tss_desc(unsigned int n, void *
|
||
|
(unsigned long)addr,
|
||
|
offsetof(struct tss_struct, __cacheline_filler) - 1,
|
||
|
9);
|
||
|
+#ifdef CONFIG_COMPAT
|
||
|
+ _set_tssldt_desc(
|
||
|
+ compat_gdt_table + __TSS(n) - FIRST_RESERVED_GDT_ENTRY,
|
||
|
+ (unsigned long)addr,
|
||
|
+ offsetof(struct tss_struct, __cacheline_filler) - 1,
|
||
|
+ 11);
|
||
|
+#endif
|
||
|
}
|
||
|
|
||
|
void __init trap_init(void)
|
||
|
@@ -1875,7 +1882,7 @@ long do_set_trap_table(XEN_GUEST_HANDLE(
|
||
|
if ( cur.address == 0 )
|
||
|
break;
|
||
|
|
||
|
- fixup_guest_code_selector(cur.cs);
|
||
|
+ fixup_guest_code_selector(current->domain, cur.cs);
|
||
|
|
||
|
memcpy(&dst[cur.vector], &cur, sizeof(cur));
|
||
|
|
||
|
Index: 2007-01-08/xen/arch/x86/x86_32/mm.c
|
||
|
===================================================================
|
||
|
--- 2007-01-08.orig/xen/arch/x86/x86_32/mm.c 2007-01-08 15:34:30.000000000 +0100
|
||
|
+++ 2007-01-08/xen/arch/x86/x86_32/mm.c 2007-01-08 14:45:40.000000000 +0100
|
||
|
@@ -230,7 +230,7 @@ long do_stack_switch(unsigned long ss, u
|
||
|
int nr = smp_processor_id();
|
||
|
struct tss_struct *t = &init_tss[nr];
|
||
|
|
||
|
- fixup_guest_stack_selector(ss);
|
||
|
+ fixup_guest_stack_selector(current->domain, ss);
|
||
|
|
||
|
current->arch.guest_context.kernel_ss = ss;
|
||
|
current->arch.guest_context.kernel_sp = esp;
|
||
|
@@ -241,7 +241,7 @@ long do_stack_switch(unsigned long ss, u
|
||
|
}
|
||
|
|
||
|
/* Returns TRUE if given descriptor is valid for GDT or LDT. */
|
||
|
-int check_descriptor(struct desc_struct *d)
|
||
|
+int check_descriptor(const struct domain *dom, struct desc_struct *d)
|
||
|
{
|
||
|
unsigned long base, limit;
|
||
|
u32 a = d->a, b = d->b;
|
||
|
@@ -261,8 +261,8 @@ int check_descriptor(struct desc_struct
|
||
|
* gates (consider a call gate pointing at another kernel descriptor with
|
||
|
* DPL 0 -- this would get the OS ring-0 privileges).
|
||
|
*/
|
||
|
- if ( (b & _SEGMENT_DPL) < (GUEST_KERNEL_RPL << 13) )
|
||
|
- d->b = b = (b & ~_SEGMENT_DPL) | (GUEST_KERNEL_RPL << 13);
|
||
|
+ if ( (b & _SEGMENT_DPL) < (GUEST_KERNEL_RPL(dom) << 13) )
|
||
|
+ d->b = b = (b & ~_SEGMENT_DPL) | (GUEST_KERNEL_RPL(dom) << 13);
|
||
|
|
||
|
if ( !(b & _SEGMENT_S) )
|
||
|
{
|
||
|
@@ -284,8 +284,8 @@ int check_descriptor(struct desc_struct
|
||
|
|
||
|
/* Validate and fix up the target code selector. */
|
||
|
cs = a >> 16;
|
||
|
- fixup_guest_code_selector(cs);
|
||
|
- if ( !guest_gate_selector_okay(cs) )
|
||
|
+ fixup_guest_code_selector(dom, cs);
|
||
|
+ if ( !guest_gate_selector_okay(dom, cs) )
|
||
|
goto bad;
|
||
|
a = d->a = (d->a & 0xffffU) | (cs << 16);
|
||
|
|
||
|
Index: 2007-01-08/xen/arch/x86/x86_32/traps.c
|
||
|
===================================================================
|
||
|
--- 2007-01-08.orig/xen/arch/x86/x86_32/traps.c 2007-01-08 15:34:30.000000000 +0100
|
||
|
+++ 2007-01-08/xen/arch/x86/x86_32/traps.c 2007-01-08 14:45:40.000000000 +0100
|
||
|
@@ -296,7 +296,7 @@ void init_int80_direct_trap(struct vcpu
|
||
|
* switch to the Xen stack and we need to swap back to the guest
|
||
|
* kernel stack before passing control to the system call entry point.
|
||
|
*/
|
||
|
- if ( TI_GET_IF(ti) || !guest_gate_selector_okay(ti->cs) ||
|
||
|
+ if ( TI_GET_IF(ti) || !guest_gate_selector_okay(v->domain, ti->cs) ||
|
||
|
supervisor_mode_kernel )
|
||
|
{
|
||
|
v->arch.int80_desc.a = v->arch.int80_desc.b = 0;
|
||
|
@@ -326,7 +326,7 @@ static long register_guest_callback(stru
|
||
|
long ret = 0;
|
||
|
struct vcpu *v = current;
|
||
|
|
||
|
- fixup_guest_code_selector(reg->address.cs);
|
||
|
+ fixup_guest_code_selector(v->domain, reg->address.cs);
|
||
|
|
||
|
switch ( reg->type )
|
||
|
{
|
||
|
Index: 2007-01-08/xen/arch/x86/x86_64/asm-offsets.c
|
||
|
===================================================================
|
||
|
--- 2007-01-08.orig/xen/arch/x86/x86_64/asm-offsets.c 2007-01-08 15:34:30.000000000 +0100
|
||
|
+++ 2007-01-08/xen/arch/x86/x86_64/asm-offsets.c 2007-01-08 14:45:40.000000000 +0100
|
||
|
@@ -58,12 +58,16 @@ void __dummy__(void)
|
||
|
OFFSET(VCPU_thread_flags, struct vcpu, arch.flags);
|
||
|
OFFSET(VCPU_event_addr, struct vcpu,
|
||
|
arch.guest_context.event_callback_eip);
|
||
|
+ OFFSET(VCPU_event_sel, struct vcpu,
|
||
|
+ arch.guest_context.event_callback_cs);
|
||
|
OFFSET(VCPU_failsafe_addr, struct vcpu,
|
||
|
arch.guest_context.failsafe_callback_eip);
|
||
|
+ OFFSET(VCPU_failsafe_sel, struct vcpu,
|
||
|
+ arch.guest_context.failsafe_callback_cs);
|
||
|
OFFSET(VCPU_syscall_addr, struct vcpu,
|
||
|
arch.guest_context.syscall_callback_eip);
|
||
|
- OFFSET(VCPU_kernel_sp, struct vcpu,
|
||
|
- arch.guest_context.kernel_sp);
|
||
|
+ OFFSET(VCPU_kernel_sp, struct vcpu, arch.guest_context.kernel_sp);
|
||
|
+ OFFSET(VCPU_kernel_ss, struct vcpu, arch.guest_context.kernel_ss);
|
||
|
OFFSET(VCPU_guest_context_flags, struct vcpu, arch.guest_context.flags);
|
||
|
OFFSET(VCPU_arch_guest_fpu_ctxt, struct vcpu, arch.guest_context.fpu_ctxt);
|
||
|
OFFSET(VCPU_flags, struct vcpu, vcpu_flags);
|
||
|
Index: 2007-01-08/xen/arch/x86/x86_64/mm.c
|
||
|
===================================================================
|
||
|
--- 2007-01-08.orig/xen/arch/x86/x86_64/mm.c 2007-01-08 15:34:30.000000000 +0100
|
||
|
+++ 2007-01-08/xen/arch/x86/x86_64/mm.c 2007-01-08 14:45:40.000000000 +0100
|
||
|
@@ -231,7 +231,7 @@ long subarch_memory_op(int op, XEN_GUEST
|
||
|
|
||
|
long do_stack_switch(unsigned long ss, unsigned long esp)
|
||
|
{
|
||
|
- fixup_guest_stack_selector(ss);
|
||
|
+ fixup_guest_stack_selector(current->domain, ss);
|
||
|
current->arch.guest_context.kernel_ss = ss;
|
||
|
current->arch.guest_context.kernel_sp = esp;
|
||
|
return 0;
|
||
|
@@ -291,7 +291,7 @@ long do_set_segment_base(unsigned int wh
|
||
|
|
||
|
|
||
|
/* Returns TRUE if given descriptor is valid for GDT or LDT. */
|
||
|
-int check_descriptor(struct desc_struct *d)
|
||
|
+int check_descriptor(const struct domain *dom, struct desc_struct *d)
|
||
|
{
|
||
|
u32 a = d->a, b = d->b;
|
||
|
u16 cs;
|
||
|
@@ -301,8 +301,8 @@ int check_descriptor(struct desc_struct
|
||
|
goto good;
|
||
|
|
||
|
/* Check and fix up the DPL. */
|
||
|
- if ( (b & _SEGMENT_DPL) < (GUEST_KERNEL_RPL << 13) )
|
||
|
- d->b = b = (b & ~_SEGMENT_DPL) | (GUEST_KERNEL_RPL << 13);
|
||
|
+ if ( (b & _SEGMENT_DPL) < (GUEST_KERNEL_RPL(dom) << 13) )
|
||
|
+ d->b = b = (b & ~_SEGMENT_DPL) | (GUEST_KERNEL_RPL(dom) << 13);
|
||
|
|
||
|
/* All code and data segments are okay. No base/limit checking. */
|
||
|
if ( (b & _SEGMENT_S) )
|
||
|
@@ -318,8 +318,8 @@ int check_descriptor(struct desc_struct
|
||
|
|
||
|
/* Validate and fix up the target code selector. */
|
||
|
cs = a >> 16;
|
||
|
- fixup_guest_code_selector(cs);
|
||
|
- if ( !guest_gate_selector_okay(cs) )
|
||
|
+ fixup_guest_code_selector(dom, cs);
|
||
|
+ if ( !guest_gate_selector_okay(dom, cs) )
|
||
|
goto bad;
|
||
|
a = d->a = (d->a & 0xffffU) | (cs << 16);
|
||
|
|
||
|
Index: 2007-01-08/xen/arch/x86/x86_64/traps.c
|
||
|
===================================================================
|
||
|
--- 2007-01-08.orig/xen/arch/x86/x86_64/traps.c 2007-01-08 15:34:30.000000000 +0100
|
||
|
+++ 2007-01-08/xen/arch/x86/x86_64/traps.c 2007-01-08 14:45:40.000000000 +0100
|
||
|
@@ -178,6 +178,8 @@ asmlinkage void do_double_fault(struct c
|
||
|
|
||
|
void toggle_guest_mode(struct vcpu *v)
|
||
|
{
|
||
|
+ if ( IS_COMPAT(v->domain) )
|
||
|
+ return;
|
||
|
v->arch.flags ^= TF_kernel_mode;
|
||
|
__asm__ __volatile__ ( "swapgs" );
|
||
|
update_cr3(v);
|
||
|
Index: 2007-01-08/xen/common/Makefile
|
||
|
===================================================================
|
||
|
--- 2007-01-08.orig/xen/common/Makefile 2007-01-08 15:34:30.000000000 +0100
|
||
|
+++ 2007-01-08/xen/common/Makefile 2007-01-08 14:45:40.000000000 +0100
|
||
|
@@ -3,6 +3,7 @@ obj-y += bitmap.o
|
||
|
obj-y += domctl.o
|
||
|
obj-y += domain.o
|
||
|
obj-y += elf.o
|
||
|
+obj-$(CONFIG_COMPAT) += elf32.o
|
||
|
obj-y += event_channel.o
|
||
|
obj-y += grant_table.o
|
||
|
obj-y += kernel.o
|
||
|
Index: 2007-01-08/xen/common/elf.c
|
||
|
===================================================================
|
||
|
--- 2007-01-08.orig/xen/common/elf.c 2007-01-08 15:34:30.000000000 +0100
|
||
|
+++ 2007-01-08/xen/common/elf.c 2007-01-08 14:45:40.000000000 +0100
|
||
|
@@ -203,7 +203,7 @@ int parseelfimage(struct domain_setup_in
|
||
|
int h, virt_base_defined, elf_pa_off_defined, virt_entry_defined;
|
||
|
|
||
|
if ( !elf_sanity_check(ehdr) )
|
||
|
- return -EINVAL;
|
||
|
+ return -ENOSYS;
|
||
|
|
||
|
if ( (ehdr->e_phoff + (ehdr->e_phnum*ehdr->e_phentsize)) > image_len )
|
||
|
{
|
||
|
Index: 2007-01-08/xen/common/elf32.c
|
||
|
===================================================================
|
||
|
--- /dev/null 1970-01-01 00:00:00.000000000 +0000
|
||
|
+++ 2007-01-08/xen/common/elf32.c 2007-01-08 14:45:40.000000000 +0100
|
||
|
@@ -0,0 +1,19 @@
|
||
|
+/******************************************************************************
|
||
|
+ * elf32.c
|
||
|
+ *
|
||
|
+ * Stub to support 32-bit ELF images on 64-bit platforms.
|
||
|
+ */
|
||
|
+
|
||
|
+#include <xen/config.h>
|
||
|
+#undef ELFSIZE
|
||
|
+#define ELFSIZE 32
|
||
|
+#include <xen/types.h>
|
||
|
+#include <xen/elf.h>
|
||
|
+
|
||
|
+#define xen_elfnote_string xen_elf32note_string
|
||
|
+#define xen_elfnote_numeric xen_elf32note_numeric
|
||
|
+#define parseelfimage parseelf32image
|
||
|
+#define loadelfimage loadelf32image
|
||
|
+#define elf_sanity_check elf32_sanity_check
|
||
|
+
|
||
|
+#include "elf.c"
|
||
|
Index: 2007-01-08/xen/include/asm-x86/config.h
|
||
|
===================================================================
|
||
|
--- 2007-01-08.orig/xen/include/asm-x86/config.h 2007-01-08 15:34:30.000000000 +0100
|
||
|
+++ 2007-01-08/xen/include/asm-x86/config.h 2007-01-08 14:45:40.000000000 +0100
|
||
|
@@ -91,6 +91,7 @@ extern unsigned long _end; /* standard E
|
||
|
#if defined(__x86_64__)
|
||
|
|
||
|
#define CONFIG_X86_64 1
|
||
|
+#define CONFIG_COMPAT 1
|
||
|
|
||
|
#define asmlinkage
|
||
|
|
||
|
@@ -185,13 +186,21 @@ extern unsigned long _end; /* standard E
|
||
|
#define DIRECTMAP_VIRT_START (PML4_ADDR(262))
|
||
|
#define DIRECTMAP_VIRT_END (DIRECTMAP_VIRT_START + PML4_ENTRY_BYTES*2)
|
||
|
|
||
|
+#define __HYPERVISOR_COMPAT_VIRT_START 0xF5800000
|
||
|
+#define HYPERVISOR_COMPAT_VIRT_START \
|
||
|
+ mk_unsigned_long(__HYPERVISOR_COMPAT_VIRT_START)
|
||
|
+#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 PGT_base_page_table PGT_l4_page_table
|
||
|
|
||
|
-#define __HYPERVISOR_CS64 0xe010
|
||
|
-#define __HYPERVISOR_CS32 0xe008
|
||
|
+#define __HYPERVISOR_CS64 0xe008
|
||
|
+#define __HYPERVISOR_CS32 0xe038
|
||
|
#define __HYPERVISOR_CS __HYPERVISOR_CS64
|
||
|
#define __HYPERVISOR_DS64 0x0000
|
||
|
-#define __HYPERVISOR_DS32 0xe018
|
||
|
+#define __HYPERVISOR_DS32 0xe010
|
||
|
#define __HYPERVISOR_DS __HYPERVISOR_DS64
|
||
|
|
||
|
/* For generic assembly code: use macros to define operation/operand sizes. */
|
||
|
Index: 2007-01-08/xen/include/asm-x86/desc.h
|
||
|
===================================================================
|
||
|
--- 2007-01-08.orig/xen/include/asm-x86/desc.h 2007-01-08 15:34:30.000000000 +0100
|
||
|
+++ 2007-01-08/xen/include/asm-x86/desc.h 2007-01-08 14:45:40.000000000 +0100
|
||
|
@@ -18,31 +18,76 @@
|
||
|
|
||
|
#define LDT_ENTRY_SIZE 8
|
||
|
|
||
|
+#if defined(__x86_64__)
|
||
|
+
|
||
|
+#define FLAT_COMPAT_RING1_CS 0xe019 /* GDT index 259 */
|
||
|
+#define FLAT_COMPAT_RING1_DS 0xe021 /* GDT index 260 */
|
||
|
+#define FLAT_COMPAT_RING1_SS 0xe021 /* GDT index 260 */
|
||
|
+#define FLAT_COMPAT_RING3_CS 0xe02b /* GDT index 261 */
|
||
|
+#define FLAT_COMPAT_RING3_DS 0xe033 /* GDT index 262 */
|
||
|
+#define FLAT_COMPAT_RING3_SS 0xe033 /* GDT index 262 */
|
||
|
+
|
||
|
+#define FLAT_COMPAT_KERNEL_DS FLAT_COMPAT_RING1_DS
|
||
|
+#define FLAT_COMPAT_KERNEL_CS FLAT_COMPAT_RING1_CS
|
||
|
+#define FLAT_COMPAT_KERNEL_SS FLAT_COMPAT_RING1_SS
|
||
|
+#define FLAT_COMPAT_USER_DS FLAT_COMPAT_RING3_DS
|
||
|
+#define FLAT_COMPAT_USER_CS FLAT_COMPAT_RING3_CS
|
||
|
+#define FLAT_COMPAT_USER_SS FLAT_COMPAT_RING3_SS
|
||
|
+
|
||
|
+#define __FIRST_TSS_ENTRY (FIRST_RESERVED_GDT_ENTRY + 8)
|
||
|
+#define __FIRST_LDT_ENTRY (__FIRST_TSS_ENTRY + 2)
|
||
|
+
|
||
|
+#define __TSS(n) (((n)<<2) + __FIRST_TSS_ENTRY)
|
||
|
+#define __LDT(n) (((n)<<2) + __FIRST_LDT_ENTRY)
|
||
|
+
|
||
|
+#elif defined(__i386__)
|
||
|
+
|
||
|
+#define FLAT_COMPAT_KERNEL_CS FLAT_KERNEL_CS
|
||
|
+#define FLAT_COMPAT_KERNEL_DS FLAT_KERNEL_DS
|
||
|
+#define FLAT_COMPAT_KERNEL_SS FLAT_KERNEL_SS
|
||
|
+#define FLAT_COMPAT_USER_CS FLAT_USER_CS
|
||
|
+#define FLAT_COMPAT_USER_DS FLAT_USER_DS
|
||
|
+#define FLAT_COMPAT_USER_SS FLAT_USER_SS
|
||
|
+
|
||
|
+#define __DOUBLEFAULT_TSS_ENTRY FIRST_RESERVED_GDT_ENTRY
|
||
|
+
|
||
|
+#define __FIRST_TSS_ENTRY (FIRST_RESERVED_GDT_ENTRY + 8)
|
||
|
+#define __FIRST_LDT_ENTRY (__FIRST_TSS_ENTRY + 1)
|
||
|
+
|
||
|
+#define __TSS(n) (((n)<<1) + __FIRST_TSS_ENTRY)
|
||
|
+#define __LDT(n) (((n)<<1) + __FIRST_LDT_ENTRY)
|
||
|
+
|
||
|
+#endif
|
||
|
+
|
||
|
+#ifndef __ASSEMBLY__
|
||
|
+
|
||
|
#define load_TR(n) __asm__ __volatile__ ("ltr %%ax" : : "a" (__TSS(n)<<3) )
|
||
|
|
||
|
#if defined(__x86_64__)
|
||
|
-#define GUEST_KERNEL_RPL 3
|
||
|
+#define GUEST_KERNEL_RPL(d) (!IS_COMPAT(d) ? 3 : 1)
|
||
|
#elif defined(__i386__)
|
||
|
-#define GUEST_KERNEL_RPL 1
|
||
|
+#define GUEST_KERNEL_RPL(d) ((void)(d), 1)
|
||
|
#endif
|
||
|
|
||
|
/* Fix up the RPL of a guest segment selector. */
|
||
|
-#define __fixup_guest_selector(sel) \
|
||
|
- ((sel) = (((sel) & 3) >= GUEST_KERNEL_RPL) ? (sel) : \
|
||
|
- (((sel) & ~3) | GUEST_KERNEL_RPL))
|
||
|
+#define __fixup_guest_selector(d, sel) \
|
||
|
+({ \
|
||
|
+ uint16_t _rpl = GUEST_KERNEL_RPL(d); \
|
||
|
+ (sel) = (((sel) & 3) >= _rpl) ? (sel) : (((sel) & ~3) | _rpl); \
|
||
|
+})
|
||
|
|
||
|
/* Stack selectors don't need fixing up if the kernel runs in ring 0. */
|
||
|
#ifdef CONFIG_X86_SUPERVISOR_MODE_KERNEL
|
||
|
-#define fixup_guest_stack_selector(ss) ((void)0)
|
||
|
+#define fixup_guest_stack_selector(d, ss) ((void)0)
|
||
|
#else
|
||
|
-#define fixup_guest_stack_selector(ss) __fixup_guest_selector(ss)
|
||
|
+#define fixup_guest_stack_selector(d, ss) __fixup_guest_selector(d, ss)
|
||
|
#endif
|
||
|
|
||
|
/*
|
||
|
* Code selectors are always fixed up. It allows the Xen exit stub to detect
|
||
|
* return to guest context, even when the guest kernel runs in ring 0.
|
||
|
*/
|
||
|
-#define fixup_guest_code_selector(cs) __fixup_guest_selector(cs)
|
||
|
+#define fixup_guest_code_selector(d, cs) __fixup_guest_selector(d, cs)
|
||
|
|
||
|
/*
|
||
|
* We need this function because enforcing the correct guest kernel RPL is
|
||
|
@@ -57,11 +102,15 @@
|
||
|
* DPL < CPL then they'll be cleared automatically. If SS RPL or DPL differs
|
||
|
* from CS RPL then we'll #GP.
|
||
|
*/
|
||
|
-#define guest_gate_selector_okay(sel) \
|
||
|
+#define guest_gate_selector_okay(d, sel) \
|
||
|
((((sel)>>3) < FIRST_RESERVED_GDT_ENTRY) || /* Guest seg? */ \
|
||
|
- ((sel) == FLAT_KERNEL_CS) || /* Xen default seg? */ \
|
||
|
+ ((sel) == (!IS_COMPAT(d) ? \
|
||
|
+ FLAT_KERNEL_CS : /* Xen default seg? */ \
|
||
|
+ FLAT_COMPAT_KERNEL_CS)) || /* Xen default compat seg? */ \
|
||
|
((sel) & 4)) /* LDT seg? */
|
||
|
|
||
|
+#endif /* __ASSEMBLY__ */
|
||
|
+
|
||
|
/* These are bitmasks for the high 32 bits of a descriptor table entry. */
|
||
|
#define _SEGMENT_TYPE (15<< 8)
|
||
|
#define _SEGMENT_EC ( 1<<10) /* Expand-down or Conforming segment */
|
||
|
@@ -81,12 +130,6 @@ struct desc_struct {
|
||
|
|
||
|
#if defined(__x86_64__)
|
||
|
|
||
|
-#define __FIRST_TSS_ENTRY (FIRST_RESERVED_GDT_ENTRY + 8)
|
||
|
-#define __FIRST_LDT_ENTRY (__FIRST_TSS_ENTRY + 2)
|
||
|
-
|
||
|
-#define __TSS(n) (((n)<<2) + __FIRST_TSS_ENTRY)
|
||
|
-#define __LDT(n) (((n)<<2) + __FIRST_LDT_ENTRY)
|
||
|
-
|
||
|
typedef struct {
|
||
|
u64 a, b;
|
||
|
} idt_entry_t;
|
||
|
@@ -118,14 +161,6 @@ do {
|
||
|
|
||
|
#elif defined(__i386__)
|
||
|
|
||
|
-#define __DOUBLEFAULT_TSS_ENTRY FIRST_RESERVED_GDT_ENTRY
|
||
|
-
|
||
|
-#define __FIRST_TSS_ENTRY (FIRST_RESERVED_GDT_ENTRY + 8)
|
||
|
-#define __FIRST_LDT_ENTRY (__FIRST_TSS_ENTRY + 1)
|
||
|
-
|
||
|
-#define __TSS(n) (((n)<<1) + __FIRST_TSS_ENTRY)
|
||
|
-#define __LDT(n) (((n)<<1) + __FIRST_LDT_ENTRY)
|
||
|
-
|
||
|
typedef struct desc_struct idt_entry_t;
|
||
|
|
||
|
#define _set_gate(gate_addr,type,dpl,addr) \
|
||
|
@@ -155,6 +190,11 @@ __asm__ __volatile__ ("movw %w3,0(%2)\n\
|
||
|
#endif
|
||
|
|
||
|
extern struct desc_struct gdt_table[];
|
||
|
+#ifdef CONFIG_COMPAT
|
||
|
+extern struct desc_struct compat_gdt_table[];
|
||
|
+#else
|
||
|
+# define compat_gdt_table gdt_table
|
||
|
+#endif
|
||
|
|
||
|
struct Xgt_desc_struct {
|
||
|
unsigned short size;
|
||
|
Index: 2007-01-08/xen/include/asm-x86/ldt.h
|
||
|
===================================================================
|
||
|
--- 2007-01-08.orig/xen/include/asm-x86/ldt.h 2007-01-08 15:34:30.000000000 +0100
|
||
|
+++ 2007-01-08/xen/include/asm-x86/ldt.h 2007-01-08 14:45:40.000000000 +0100
|
||
|
@@ -17,7 +17,8 @@ static inline void load_LDT(struct vcpu
|
||
|
else
|
||
|
{
|
||
|
cpu = smp_processor_id();
|
||
|
- desc = gdt_table + __LDT(cpu) - FIRST_RESERVED_GDT_ENTRY;
|
||
|
+ desc = (!IS_COMPAT(v->domain) ? gdt_table : compat_gdt_table)
|
||
|
+ + __LDT(cpu) - FIRST_RESERVED_GDT_ENTRY;
|
||
|
_set_tssldt_desc(desc, LDT_VIRT_START(v), ents*8-1, 2);
|
||
|
__asm__ __volatile__ ( "lldt %%ax" : : "a" (__LDT(cpu)<<3) );
|
||
|
}
|
||
|
Index: 2007-01-08/xen/include/asm-x86/mm.h
|
||
|
===================================================================
|
||
|
--- 2007-01-08.orig/xen/include/asm-x86/mm.h 2007-01-08 15:34:30.000000000 +0100
|
||
|
+++ 2007-01-08/xen/include/asm-x86/mm.h 2007-01-08 14:45:40.000000000 +0100
|
||
|
@@ -244,7 +244,7 @@ unsigned long
|
||
|
pae_copy_root(struct vcpu *v, l3_pgentry_t *l3tab);
|
||
|
#endif /* CONFIG_PAGING_LEVELS == 3 */
|
||
|
|
||
|
-int check_descriptor(struct desc_struct *d);
|
||
|
+int check_descriptor(const struct domain *, struct desc_struct *d);
|
||
|
|
||
|
/*
|
||
|
* The MPT (machine->physical mapping table) is an array of word-sized
|
||
|
Index: 2007-01-08/xen/include/asm-x86/regs.h
|
||
|
===================================================================
|
||
|
--- 2007-01-08.orig/xen/include/asm-x86/regs.h 2007-01-08 15:34:30.000000000 +0100
|
||
|
+++ 2007-01-08/xen/include/asm-x86/regs.h 2007-01-08 14:45:40.000000000 +0100
|
||
|
@@ -38,7 +38,8 @@ enum EFLAGS {
|
||
|
ASSERT(diff < STACK_SIZE); \
|
||
|
/* If a guest frame, it must be have guest privs (unless HVM guest). */ \
|
||
|
/* We permit CS==0 which can come from an uninitialised trap entry. */ \
|
||
|
- ASSERT((diff != 0) || vm86_mode(r) || ((r->cs&3) >= GUEST_KERNEL_RPL) || \
|
||
|
+ ASSERT((diff != 0) || vm86_mode(r) || \
|
||
|
+ ((r->cs&3) >= GUEST_KERNEL_RPL(current->domain)) || \
|
||
|
(r->cs == 0) || is_hvm_vcpu(current)); \
|
||
|
/* If not a guest frame, it must be a hypervisor frame. */ \
|
||
|
ASSERT((diff == 0) || (!vm86_mode(r) && (r->cs == __HYPERVISOR_CS))); \
|
||
|
Index: 2007-01-08/xen/include/asm-x86/x86_32/regs.h
|
||
|
===================================================================
|
||
|
--- 2007-01-08.orig/xen/include/asm-x86/x86_32/regs.h 2007-01-08 15:34:30.000000000 +0100
|
||
|
+++ 2007-01-08/xen/include/asm-x86/x86_32/regs.h 2007-01-08 14:45:40.000000000 +0100
|
||
|
@@ -17,7 +17,7 @@
|
||
|
((dpl) >= (vm86_mode(r) ? 3 : ((r)->cs & 3)))
|
||
|
|
||
|
/* Check for null trap callback handler: Is the selector null (0-3)? */
|
||
|
-#define null_trap_bounce(tb) (((tb)->cs & ~3) == 0)
|
||
|
+#define null_trap_bounce(v, tb) (((tb)->cs & ~3) == 0)
|
||
|
|
||
|
/* Number of bytes of on-stack execution state to be context-switched. */
|
||
|
#define CTXT_SWITCH_STACK_BYTES (sizeof(struct cpu_user_regs))
|
||
|
Index: 2007-01-08/xen/include/asm-x86/x86_64/regs.h
|
||
|
===================================================================
|
||
|
--- 2007-01-08.orig/xen/include/asm-x86/x86_64/regs.h 2007-01-08 15:34:30.000000000 +0100
|
||
|
+++ 2007-01-08/xen/include/asm-x86/x86_64/regs.h 2007-01-08 14:45:40.000000000 +0100
|
||
|
@@ -11,13 +11,16 @@
|
||
|
#define ring_3(r) (((r)->cs & 3) == 3)
|
||
|
|
||
|
#define guest_kernel_mode(v, r) \
|
||
|
- (ring_3(r) && ((v)->arch.flags & TF_kernel_mode))
|
||
|
+ (!IS_COMPAT((v)->domain) ? \
|
||
|
+ ring_3(r) && ((v)->arch.flags & TF_kernel_mode) : \
|
||
|
+ ring_1(r))
|
||
|
|
||
|
#define permit_softint(dpl, v, r) \
|
||
|
((dpl) >= (guest_kernel_mode(v, r) ? 1 : 3))
|
||
|
|
||
|
/* Check for null trap callback handler: Is the EIP null? */
|
||
|
-#define null_trap_bounce(tb) ((tb)->eip == 0)
|
||
|
+#define null_trap_bounce(v, tb) \
|
||
|
+ (!IS_COMPAT((v)->domain) ? (tb)->eip == 0 : ((tb)->cs & ~3) == 0)
|
||
|
|
||
|
/* Number of bytes of on-stack execution state to be context-switched. */
|
||
|
/* NB. Segment registers and bases are not saved/restored on x86/64 stack. */
|
||
|
Index: 2007-01-08/xen/include/public/arch-x86/xen.h
|
||
|
===================================================================
|
||
|
--- 2007-01-08.orig/xen/include/public/arch-x86/xen.h 2007-01-08 15:34:30.000000000 +0100
|
||
|
+++ 2007-01-08/xen/include/public/arch-x86/xen.h 2007-01-08 14:52:24.000000000 +0100
|
||
|
@@ -141,8 +141,18 @@ struct vcpu_guest_context {
|
||
|
#else
|
||
|
unsigned long event_callback_eip;
|
||
|
unsigned long failsafe_callback_eip;
|
||
|
+#ifdef __XEN__
|
||
|
+ union {
|
||
|
+ unsigned long syscall_callback_eip;
|
||
|
+ struct {
|
||
|
+ unsigned int event_callback_cs; /* compat CS of event cb */
|
||
|
+ unsigned int failsafe_callback_cs; /* compat CS of failsafe cb */
|
||
|
+ };
|
||
|
+ };
|
||
|
+#else
|
||
|
unsigned long syscall_callback_eip;
|
||
|
#endif
|
||
|
+#endif
|
||
|
unsigned long vm_assist; /* VMASST_TYPE_* bitmap */
|
||
|
#ifdef __x86_64__
|
||
|
/* Segment base addresses. */
|
||
|
Index: 2007-01-08/xen/include/public/arch-x86/xen-x86_64.h
|
||
|
===================================================================
|
||
|
--- 2007-01-08.orig/xen/include/public/arch-x86/xen-x86_64.h 2007-01-08 15:34:30.000000000 +0100
|
||
|
+++ 2007-01-08/xen/include/public/arch-x86/xen-x86_64.h 2007-01-08 14:52:13.000000000 +0100
|
||
|
@@ -141,7 +141,10 @@ struct iret_context {
|
||
|
|
||
|
#ifdef __GNUC__
|
||
|
/* Anonymous union includes both 32- and 64-bit names (e.g., eax/rax). */
|
||
|
-#define __DECL_REG(name) union { uint64_t r ## name, e ## name; }
|
||
|
+#define __DECL_REG(name) union { \
|
||
|
+ uint64_t r ## name, e ## name; \
|
||
|
+ uint32_t _e ## name; \
|
||
|
+}
|
||
|
#else
|
||
|
/* Non-gcc sources must always use the proper 64-bit name (e.g., rax). */
|
||
|
#define __DECL_REG(name) uint64_t r ## name
|
||
|
Index: 2007-01-08/xen/include/xen/elf.h
|
||
|
===================================================================
|
||
|
--- 2007-01-08.orig/xen/include/xen/elf.h 2007-01-08 15:34:30.000000000 +0100
|
||
|
+++ 2007-01-08/xen/include/xen/elf.h 2007-01-08 14:47:11.000000000 +0100
|
||
|
@@ -525,6 +525,15 @@ extern unsigned long long xen_elfnote_nu
|
||
|
int type, int *defined);
|
||
|
extern const char *xen_elfnote_string(struct domain_setup_info *dsi, int type);
|
||
|
|
||
|
+#ifdef CONFIG_COMPAT
|
||
|
+extern int elf32_sanity_check(const Elf32_Ehdr *ehdr);
|
||
|
+extern int loadelf32image(struct domain_setup_info *);
|
||
|
+extern int parseelf32image(struct domain_setup_info *);
|
||
|
+extern unsigned long long xen_elf32note_numeric(struct domain_setup_info *,
|
||
|
+ int type, int *defined);
|
||
|
+extern const char *xen_elf32note_string(struct domain_setup_info *, int type);
|
||
|
+#endif
|
||
|
+
|
||
|
#ifdef Elf_Ehdr
|
||
|
extern int elf_sanity_check(const Elf_Ehdr *ehdr);
|
||
|
#endif
|
||
|
Index: 2007-01-08/xen/include/xen/sched.h
|
||
|
===================================================================
|
||
|
--- 2007-01-08.orig/xen/include/xen/sched.h 2007-01-08 15:34:30.000000000 +0100
|
||
|
+++ 2007-01-08/xen/include/xen/sched.h 2007-01-08 14:45:40.000000000 +0100
|
||
|
@@ -422,6 +422,9 @@ extern struct domain *domain_list;
|
||
|
/* Domain is paused by the hypervisor? */
|
||
|
#define _DOMF_paused 5
|
||
|
#define DOMF_paused (1UL<<_DOMF_paused)
|
||
|
+ /* Domain is a compatibility one? */
|
||
|
+#define _DOMF_compat 6
|
||
|
+#define DOMF_compat (1UL<<_DOMF_compat)
|
||
|
|
||
|
static inline int vcpu_runnable(struct vcpu *v)
|
||
|
{
|
||
|
@@ -458,6 +461,13 @@ static inline void vcpu_unblock(struct v
|
||
|
|
||
|
#define IS_PRIV(_d) ((_d)->is_privileged)
|
||
|
|
||
|
+#ifdef CONFIG_COMPAT
|
||
|
+#define IS_COMPAT(_d) \
|
||
|
+ (test_bit(_DOMF_compat, &(_d)->domain_flags))
|
||
|
+#else
|
||
|
+#define IS_COMPAT(_d) 0
|
||
|
+#endif
|
||
|
+
|
||
|
#define VM_ASSIST(_d,_t) (test_bit((_t), &(_d)->vm_assist))
|
||
|
|
||
|
#define is_hvm_domain(d) ((d)->is_hvm)
|