x86_64: basic changes for supporting compatibility mode guest
RFC PATCH 6/7 x86_64: basic changes for supporting compatibility mode guest
This introduces
- a (generic) config setting to turn on compatibility mode support
- support to load a Dom0 32-bit ELF image on 64-bit
- a compatibility guest mode GDT (requires moving the ring 0 selectors to different GDT slots), and the respective selector handling changes
- some initial code path changes to address the needs of a compatibility mode guest
This changes the ABI in adding to vcpu_guest_context - does a change like this require bumping the ABI version?
config/x86_64.mk +1 -0
@@ -1,4 +1,5 @@ CONFIG_X86 := y +CONFIG_COMPAT := y CONFIG_HVM := y CONFIG_MIGRATE := y CONFIG_XCUTILS := y
xen/arch/x86/boot/x86_64.S +24 -4
@@ -223,15 +223,35 @@ 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 +# define LIMIT(d) (((d) << 16) \ + | (((MACH2PHYS_COMPAT_VIRT_END - 1) >> PAGE_SHIFT) & 0xffff) \ + | (((MACH2PHYS_COMPAT_VIRT_END - 1) << (32 - PAGE_SHIFT)) & (0xf << 48))) + .align PAGE_SIZE, 0 +ENTRY(compat_gdt_table) + .quad 0x0000000000000000 /* unused */ + .quad 0x00af9a000000ffff /* 0xe008 ring 0 code, 64-bit mode */ + .quad 0x00cf92000000ffff /* 0xe010 ring 0 data */ + .quad LIMIT(0x00cfba000000) /* 0xe019 ring 1 code, compatibility */ + .quad LIMIT(0x00cfb2000000) /* 0xe021 ring 1 data */ + .quad LIMIT(0x00c0fa000000) /* 0xe02b ring 3 code, compatibility */ + .quad LIMIT(0x00c0f2000000) /* 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)
xen/arch/x86/domain.c +93 -34
184 lines not on this page · raw message
xen/arch/x86/domain_build.c +64 -6
126 lines not on this page · raw message
xen/arch/x86/mm.c +6 -2
@@ -391,7 +391,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);
@@ -1746,6 +1746,8 @@ int new_guest_cr3(unsigned long mfn)/* Switch to idle pagetable: this VCPU has no active p.t. now. */ MEM_LOG ("New baseptr %lx: slow path via idle pagetables" , mfn); old_base_mfn =pagetable_get_pfn (v->arch.guest_table); +if ( old_base_mfn ==pagetable_get_pfn (v->arch.guest_table_user) ) + v->arch.guest_table_user =pagetable_null (); v->arch.guest_table =pagetable_null ();update_pagetables (v);write_cr3 (__pa (idle_pg_table));
@@ -1770,6 +1772,8 @@ int new_guest_cr3(unsigned long mfn) old_base_mfn =pagetable_get_pfn (v->arch.guest_table); v->arch.guest_table =pagetable_from_pfn (mfn); +if (IS_COMPAT (d) ) + v->arch.guest_table_user = v->arch.guest_table;update_pagetables (v);/* update shadow_table and monitor_table */ write_ptbase (v);
@@ -2882,7 +2886,7 @@ long do_update_descriptor(u64 pa, u64 deif ( !VALID_MFN (mfn =gmfn_to_mfn (dom, gmfn)) || (((unsigned int )pa %sizeof (struct desc_struct )) !=0 ) || !mfn_valid (mfn) || - !check_descriptor (&d) ) + !check_descriptor (dom, &d) ) {UNLOCK_BIGLOCK (dom);return -EINVAL ;
xen/arch/x86/traps.c +8 -1
@@ -1720,6 +1720,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 )
@@ -1794,7 +1801,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));
xen/arch/x86/x86_32/mm.c +6 -6
@@ -226,7 +226,7 @@ long do_stack_switch(unsigned long ss, uint 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;
@@ -237,7 +237,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;
@@ -257,8 +257,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) ) {
@@ -280,8 +280,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 );
xen/arch/x86/x86_32/traps.c +2 -2
@@ -276,7 +276,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 ;
@@ -306,7 +306,7 @@ static long register_guest_callback(strulong 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 ) {
xen/arch/x86/x86_64/asm-offsets.c +2 -2
@@ -62,8 +62,8 @@ void __dummy__(void) arch.guest_context.failsafe_callback_eip); 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);
xen/arch/x86/x86_64/mm.c +6 -6
@@ -222,7 +222,7 @@ long subarch_memory_op(int op, XEN_GUESTlong 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 ;
@@ -282,7 +282,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;
@@ -292,8 +292,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) )
@@ -309,8 +309,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 );
xen/arch/x86/x86_64/traps.c +2 -0
@@ -160,6 +160,8 @@ asmlinkage void do_double_fault(struct cvoid toggle_guest_mode (struct vcpu *v) { +if (IS_COMPAT (v->domain) ) +return ; v->arch.flags ^= TF_kernel_mode; __asm__ __volatile__ ("swapgs" );update_pagetables (v);
xen/common/Makefile +1 -0
@@ -3,6 +3,7 @@ obj-y += bitmap.o obj-y += dom0_ops.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
xen/common/elf.c +1 -1
@@ -29,7 +29,7 @@ int parseelfimage(struct domain_setup_inint h, virt_base_defined, elf_pa_off_defined;if ( !elf_sanity_check (ehdr) ) -return -EINVAL ; +return -ENOSYS ;if ( (ehdr->e_phoff + (ehdr->e_phnum*ehdr->e_phentsize)) > dsi->image_len ) {
xen/include/asm-x86/config.h +13 -3
@@ -86,6 +86,7 @@ extern unsigned long _end; /* standard E#if defined(__x86_64__)#define CONFIG_X86_64 1 +#define CONFIG_COMPAT 1#define asmlinkage
@@ -175,13 +176,22 @@ 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 __MACH2PHYS_COMPAT_VIRT_START 0xF5800000 +#define __MACH2PHYS_COMPAT_VIRT_END 0xF6800000 +#define HYPERVISOR_COMPAT_VIRT_START mk_unsigned_long(__HYPERVISOR_COMPAT_VIRT_START) +#define MACH2PHYS_COMPAT_VIRT_START mk_unsigned_long(__MACH2PHYS_COMPAT_VIRT_START) +#define MACH2PHYS_COMPAT_VIRT_END mk_unsigned_long(__MACH2PHYS_COMPAT_VIRT_END) +#define MACH2PHYS_COMPAT_NR_ENTRIES ((MACH2PHYS_COMPAT_VIRT_END-MACH2PHYS_COMPAT_VIRT_START)>>2) +#define compat_machine_to_phys_mapping ((unsigned long *)MACH2PHYS_COMPAT_VIRT_START) +#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. */
xen/include/asm-x86/desc.h +64 -24
138 lines not on this page · raw message
xen/include/asm-x86/ldt.h +2 -1
@@ -17,7 +17,8 @@ static inline void load_LDT(struct vcpuelse { 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 ) ); }
xen/include/asm-x86/mm.h +1 -1
@@ -254,7 +254,7 @@ static inline int page_is_removable(struASSERT (((_p)->count_info & PGC_count_mask) !=0 ); \ ASSERT(page_get_owner(_p) == (_d)) -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
xen/include/asm-x86/regs.h +2 -1
@@ -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 ) ||hvm_guest (current)); \/* If not a guest frame, it must be a hypervisor frame. */ \ASSERT ((diff ==0 ) || (!vm86_mode (r) && (r->cs == __HYPERVISOR_CS))); \
xen/include/asm-x86/x86_64/regs.h +3 -1
@@ -11,7 +11,9 @@#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))
xen/include/public/arch-x86_64.h +6 -1
@@ -176,7 +176,10 @@ DEFINE_XEN_GUEST_HANDLE(trap_info_t);#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
@@ -255,6 +258,8 @@ struct vcpu_guest_context {uint64_t fs_base;uint64_t gs_base_kernel;uint64_t gs_base_user; +unsigned int event_callback_cs;/* compat CS of event callback */ +unsigned int failsafe_callback_cs;/* compat CS of failsafe cb */ };typedef struct vcpu_guest_context vcpu_guest_context_t ;DEFINE_XEN_GUEST_HANDLE (vcpu_guest_context_t);
xen/include/xen/elf.h +6 -0
@@ -529,6 +529,12 @@ struct domain_setup_info;extern int loadelfimage (struct domain_setup_info *);extern int parseelfimage (struct domain_setup_info *); +#ifdef CONFIG_COMPAT +extern int loadelf32image (struct domain_setup_info *); +extern int parseelf32image (struct domain_setup_info *); +extern int elf32_sanity_check (Elf32_Ehdr *ehdr); +#endif +#ifdef Elf_Ehdrextern int elf_sanity_check (Elf_Ehdr *ehdr);#endif
xen/include/xen/sched.h +10 -0
@@ -404,6 +404,9 @@ extern struct domain *domain_list;/* Domain is paused by the hypervisor? */ #define _DOMF_paused 6#define DOMF_paused (1UL<<_DOMF_paused) +/* Domain is a compatibility one? */ +#define _DOMF_compat 7 +#define DOMF_compat (1UL<<_DOMF_compat)static inline int vcpu_runnable (struct vcpu *v) {
@@ -434,6 +437,13 @@ static inline void vcpu_unblock(struct v#define IS_PRIV (_d) \ (test_bit(_DOMF_privileged, &(_d)->domain_flags)) +#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))#endif /* __SCHED_H__ */
_______________________________________________
Xen-devel mailing list
[email protected]
http://lists.xensource.com/xen-devel
Quoted 2 lines · Jan Beulich
This changes the ABI in adding to
vcpu_guest_context- does a change like this require bumping the ABI version?
We can't do this as the struct is part of the domU ABI (used for initialising secondary VCPUs). You'll have to add the extra CS values to 64-bit arch_vcpu, I think.
-- Keir
Quoted 9 lines
Quoted 1 line
Quoted 1 line
Keir Fraser <[email protected]> 23.08.06 11:40 >>>
Quoted 2 lines · Jan Beulich
This changes the ABI in adding to
vcpu_guest_context- does a change like this require bumping the ABI version?We can't do this as the struct is part of the domU ABI (used for initialising secondary VCPUs). You'll have to add the extra CS values to 64-bit
arch_vcpu, I think.
Then libxc/xc_linux_build.c (after appropriate adjustment) wouldn't have a way to communicate these for a new domain. If extending the structure isn't possible at all, then we'll either have to make event_callback_eip and failsafe_callback_eip unions (permitting a selector:offset pair) or make syscall_callback_eip a union (permitting storing the selectors). I'd favor the second option as that field is entirely useless as long as x86_32 doesn't support syscall (which doesn't make sense as it would make things slower rather than speeding them up) - that way one doesn't have to be careful to not access the other two full 64bit *_callback_eip fields.
Jan
Quoted 10 lines · Jan Beulich
Then
libxc/xc_linux_build.c(after appropriate adjustment) wouldn't have a way to communicate these for a new domain. If extending the structure isn't possible at all, then we'll either have to makeevent_callback_eipandfailsafe_callback_eipunions (permitting a selector:offset pair) or makesyscall_callback_eipa union (permitting storing the selectors). I'd favor the second option as that field is entirely useless as long asx86_32doesn't support syscall (which doesn't make sense as it would make things slower rather than speeding them up) - that way one doesn't have to be careful to not access the other two full 64bit*_callback_eipfields.
If we do 32-bit dom0 kernel then the tools will pick up the 32-bit version of that structure. So this is only an issue for userspace if we want 64-bit dom0 to be able to build 32-bit domU's. I suppose this would be nice to have.
Obvious thing to do is suffix all the structs and defns in arch-x86_foo.h with _32 or _64 as appropriate. Then, at the end of the header, we define the non-suffixed versions only if defined(__i386__) or __defined__(x86_64) (as appropriate).
This avoids breaking the domU API unnecessarily but allows those who want to make the distinction to use the suffixed versions.
-- Keir
Quoted 13 lines
Quoted 1 line
Quoted 1 line
Keir Fraser <[email protected]> 23.08.06 12:36 >>>
Quoted 10 lines · Jan Beulich
Then
libxc/xc_linux_build.c(after appropriate adjustment) wouldn't have a way to communicate these for a new domain. If extending the structure isn't possible at all, then we'll either have to makeevent_callback_eipandfailsafe_callback_eipunions (permitting a selector:offset pair) or makesyscall_callback_eipa union (permitting storing the selectors). I'd favor the second option as that field is entirely useless as long asx86_32doesn't support syscall (which doesn't make sense as it would make things slower rather than speeding them up) - that way one doesn't have to be careful to not access the other two full 64bit*_callback_eipfields.
Quoted 4 lines
If we do 32-bit dom0 kernel then the tools will pick up the 32-bit version of that structure. So this is only an issue for userspace if we want 64-bit dom0 to be able to build 32-bit domU's. I suppose this would be nice to have.
Of course. From NetWare's perspective it is even more than just 'nice to have'.
Quoted 7 lines
Obvious thing to do is suffix all the structs and defns in
arch-x86_foo.hwith _32 or _64 as appropriate. Then, at the end of the header, we define the non-suffixed versions only ifdefined(__i386__)or__defined__(x86_64)(as appropriate).This avoids breaking the domU API unnecessarily but allows those who want to make the distinction to use the suffixed versions.
Implying that you would add an extra hypercall sub-functions that you could pass in a non-native structures? Doesn't seem too nice to me. Also, all the public headers will anyway need to be converted to compatibility ones (the next thing I intend to do actually), so converting arch-x86_32.h will come as a by-product, and handling the compatibility structure will be purely a job of the compatibility hypercalls, except for the need to add a compatibility flag to the domain creation request and to handle dual-purpose fields like the ones talked about above under IS_COMPAT() in the native hypercall.
Jan
Hi,
Quoted 4 lines
If we do 32-bit dom0 kernel then the tools will pick up the 32-bit version of that structure. So this is only an issue for userspace if we want 64-bit dom0 to be able to build 32-bit domU's. I suppose this would be nice to have.
I think we certainly want to have that. I'd suggest to have a look at my kexec bits:
http://www.suse.de/~kraxel/xen/kexec.html
http://www.suse.de/~kraxel/patches/
They include a largely rewritten domain builder, adding support for loading both 32bit and 64bit kernels with the 64bit tools should be easy.
Quoted 4 lines
Obvious thing to do is suffix all the structs and defns in
arch-x86_foo.hwith _32 or _64 as appropriate. Then, at the end of the header, we define the non-suffixed versions only ifdefined(__i386__)or__defined__(x86_64)(as appropriate).
I'd suggest to suffix them with $arch instead, so we have the option to handle even ia64 on x86 machines.
cheers,
Gerd
Signature · 2 lines
Gerd Hoffmann <[email protected]> http://www.suse.de/~kraxel/julika-dora.jpeg
There was one more issue I forgot to mention: We must disable execution of 'syscall' in some way for compatibility domains. The question is whether to add respective detection code early into the syscall path (which would affect performance-wise all 64-bit domains) or whether to {dis,en}able the use of the instruction in the context switch code by updating EFER as needed (which would have a performance effect only when switching between a native and a compatibility domain, but the performance effect would likely be significantly greater). I'd prefer the second option, not the least because its implementation is significantly easier.
Jan
Quoted 9 lines · Jan Beulich
There was one more issue I forgot to mention: We must disable execution of 'syscall' in some way for compatibility domains. The question is whether to add respective detection code early into the syscall path (which would affect performance-wise all 64-bit domains) or whether to {dis,en}able the use of the instruction in the context switch code by updating EFER as needed (which would have a performance effect only when switching between a native and a compatibility domain, but the performance effect would likely be significantly greater). I'd prefer the second option, not the least because its implementation is significantly easier.
I'm not fussed either way really. It depends how slow it is to update EFER. That'd be easy to check.
-- Keir