x86: Unify desc_struct definition

desc_struct is various things, depending on context.  This patch unifies the
32 and 64-bit definitions into a union, and cleans up the callers.

Some callers could probably be neatened further, now correct types are
available.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>

 arch/x86/ia32/tls32.c                 |   58 ++++++++++++----------------------
 arch/x86/kernel/apm_32.c              |    2 -
 arch/x86/kernel/cpu/common.c          |   35 ++++++++++++--------
 arch/x86/kernel/process_32.c          |   43 ++++++++-----------------
 arch/x86/kernel/process_64.c          |   12 +------
 arch/x86/kernel/ptrace_32.c           |   37 +++++++--------------
 arch/x86/kernel/smpcommon_32.c        |    4 +-
 arch/x86/kernel/suspend_64.c          |    2 -
 arch/x86/kernel/traps_32.c            |    2 -
 arch/x86/kernel/vmi_32.c              |    4 +-
 arch/x86/lguest/boot.c                |    2 -
 arch/x86/math-emu/fpu_entry.c         |    4 +-
 arch/x86/math-emu/fpu_system.h        |   17 ++++-----
 arch/x86/math-emu/get_address.c       |    4 +-
 drivers/kvm/kvm_main.c                |   12 ++++---
 drivers/lguest/interrupts_and_traps.c |   22 ++++++------
 drivers/lguest/segments.c             |   22 ++++++------
 drivers/lguest/x86/core.c             |    4 +-
 drivers/pnp/pnpbios/bioscalls.c       |    2 -
 include/asm-x86/desc_32.h             |    5 +-
 include/asm-x86/desc_64.h             |    8 ++--
 include/asm-x86/desc_defs.h           |   42 +++++++++++++++++++-----
 include/asm-x86/lguest.h              |    4 +-
 include/asm-x86/processor_32.h        |   17 +++++----
 include/asm-x86/processor_64.h        |   16 ++++++---
 include/asm-x86/xen/hypercall.h       |    4 +-
 26 files changed, 190 insertions(+), 194 deletions(-)
diff -r ca43743e0c27 arch/x86/ia32/tls32.c
--- a/arch/x86/ia32/tls32.c	Fri Nov 23 11:44:20 2007 +1100
+++ b/arch/x86/ia32/tls32.c	Sat Nov 24 14:54:16 2007 +1100
@@ -19,7 +19,7 @@ static int get_free_idx(void)
 	int idx;
 
 	for (idx = 0; idx < GDT_ENTRY_TLS_ENTRIES; idx++)
-		if (desc_empty((struct n_desc_struct *)(t->tls_array) + idx))
+		if (desc_empty(t->tls_array + idx))
 			return idx + GDT_ENTRY_TLS_MIN;
 	return -ESRCH;
 }
@@ -31,7 +31,7 @@ int do_set_thread_area(struct thread_str
 int do_set_thread_area(struct thread_struct *t, struct user_desc __user *u_info)
 {
 	struct user_desc info;
-	struct n_desc_struct *desc;
+	struct desc_struct *desc;
 	int cpu, idx;
 
 	if (copy_from_user(&info, u_info, sizeof(info)))
@@ -54,7 +54,7 @@ int do_set_thread_area(struct thread_str
 	if (idx < GDT_ENTRY_TLS_MIN || idx > GDT_ENTRY_TLS_MAX)
 		return -EINVAL;
 
-	desc = ((struct n_desc_struct *)t->tls_array) + idx - GDT_ENTRY_TLS_MIN;
+	desc = t->tls_array + idx - GDT_ENTRY_TLS_MIN;
 
 	/*
 	 * We must not get preempted while modifying the TLS.
@@ -62,11 +62,11 @@ int do_set_thread_area(struct thread_str
 	cpu = get_cpu();
 
 	if (LDT_empty(&info)) {
-		desc->a = 0;
-		desc->b = 0;
+		desc->raw.a = 0;
+		desc->raw.b = 0;
 	} else {
-		desc->a = LDT_entry_a(&info);
-		desc->b = LDT_entry_b(&info);
+		desc->raw.a = LDT_entry_a(&info);
+		desc->raw.b = LDT_entry_b(&info);
 	}
 	if (t == &current->thread)
 		load_TLS(t, cpu);
@@ -85,27 +85,13 @@ asmlinkage long sys32_set_thread_area(st
  * Get the current Thread-Local Storage area:
  */
 
-#define GET_BASE(desc) ( \
-	(((desc)->a >> 16) & 0x0000ffff) | \
-	(((desc)->b << 16) & 0x00ff0000) | \
-	( (desc)->b        & 0xff000000)   )
-
-#define GET_LIMIT(desc) ( \
-	((desc)->a & 0x0ffff) | \
-	 ((desc)->b & 0xf0000) )
-	
-#define GET_32BIT(desc)		(((desc)->b >> 22) & 1)
-#define GET_CONTENTS(desc)	(((desc)->b >> 10) & 3)
-#define GET_WRITABLE(desc)	(((desc)->b >>  9) & 1)
-#define GET_LIMIT_PAGES(desc)	(((desc)->b >> 23) & 1)
-#define GET_PRESENT(desc)	(((desc)->b >> 15) & 1)
-#define GET_USEABLE(desc)	(((desc)->b >> 20) & 1)
-#define GET_LONGMODE(desc)	(((desc)->b >> 21) & 1)
+#define GET_CONTENTS(desc)	(((desc)->raw.b >> 10) & 3)
+#define GET_WRITABLE(desc)	(((desc)->raw.b >>  9) & 1)
 
 int do_get_thread_area(struct thread_struct *t, struct user_desc __user *u_info)
 {
 	struct user_desc info;
-	struct n_desc_struct *desc;
+	struct desc_struct *desc;
 	int idx;
 
 	if (get_user(idx, &u_info->entry_number))
@@ -113,19 +99,19 @@ int do_get_thread_area(struct thread_str
 	if (idx < GDT_ENTRY_TLS_MIN || idx > GDT_ENTRY_TLS_MAX)
 		return -EINVAL;
 
-	desc = ((struct n_desc_struct *)t->tls_array) + idx - GDT_ENTRY_TLS_MIN;
+	desc = t->tls_array + idx - GDT_ENTRY_TLS_MIN;
 
 	memset(&info, 0, sizeof(struct user_desc));
 	info.entry_number = idx;
-	info.base_addr = GET_BASE(desc);
-	info.limit = GET_LIMIT(desc);
-	info.seg_32bit = GET_32BIT(desc);
+	info.base_addr = get_seg_desc_base(&desc->seg);
+	info.limit = get_seg_desc_limit(&desc->seg);
+	info.seg_32bit = desc->seg.d;
 	info.contents = GET_CONTENTS(desc);
 	info.read_exec_only = !GET_WRITABLE(desc);
-	info.limit_in_pages = GET_LIMIT_PAGES(desc);
-	info.seg_not_present = !GET_PRESENT(desc);
-	info.useable = GET_USEABLE(desc);
-	info.lm = GET_LONGMODE(desc);
+	info.limit_in_pages = desc->seg.g;
+	info.seg_not_present = !desc->seg.p;
+	info.useable = desc->seg.avl;
+	info.lm = desc->seg.l;
 
 	if (copy_to_user(u_info, &info, sizeof(info)))
 		return -EFAULT;
@@ -140,7 +126,7 @@ asmlinkage long sys32_get_thread_area(st
 
 int ia32_child_tls(struct task_struct *p, struct pt_regs *childregs)
 {
-	struct n_desc_struct *desc;
+	struct desc_struct *desc;
 	struct user_desc info;
 	struct user_desc __user *cp;
 	int idx;
@@ -155,9 +141,9 @@ int ia32_child_tls(struct task_struct *p
 	if (idx < GDT_ENTRY_TLS_MIN || idx > GDT_ENTRY_TLS_MAX)
 		return -EINVAL;
 	
-	desc = (struct n_desc_struct *)(p->thread.tls_array) + idx - GDT_ENTRY_TLS_MIN;
-	desc->a = LDT_entry_a(&info);
-	desc->b = LDT_entry_b(&info);
+	desc = p->thread.tls_array + idx - GDT_ENTRY_TLS_MIN;
+	desc->raw.a = LDT_entry_a(&info);
+	desc->raw.b = LDT_entry_b(&info);
 
 	return 0;
 }
diff -r ca43743e0c27 arch/x86/kernel/apm_32.c
--- a/arch/x86/kernel/apm_32.c	Fri Nov 23 11:44:20 2007 +1100
+++ b/arch/x86/kernel/apm_32.c	Sat Nov 24 14:54:16 2007 +1100
@@ -407,7 +407,7 @@ static DECLARE_WAIT_QUEUE_HEAD(apm_suspe
 static DECLARE_WAIT_QUEUE_HEAD(apm_suspend_waitqueue);
 static struct apm_user *	user_list;
 static DEFINE_SPINLOCK(user_list_lock);
-static const struct desc_struct	bad_bios_desc = { 0, 0x00409200 };
+static const struct desc_struct	bad_bios_desc = { { .raw = { 0,0x00409200 } } };
 
 static const char		driver_version[] = "1.16ac";	/* no spaces */
 
diff -r ca43743e0c27 arch/x86/kernel/cpu/common.c
--- a/arch/x86/kernel/cpu/common.c	Fri Nov 23 11:44:20 2007 +1100
+++ b/arch/x86/kernel/cpu/common.c	Sat Nov 24 14:54:16 2007 +1100
@@ -22,31 +22,38 @@
 #include "cpu.h"
 
 DEFINE_PER_CPU(struct gdt_page, gdt_page) = { .gdt = {
-	[GDT_ENTRY_KERNEL_CS] = { 0x0000ffff, 0x00cf9a00 },
-	[GDT_ENTRY_KERNEL_DS] = { 0x0000ffff, 0x00cf9200 },
-	[GDT_ENTRY_DEFAULT_USER_CS] = { 0x0000ffff, 0x00cffa00 },
-	[GDT_ENTRY_DEFAULT_USER_DS] = { 0x0000ffff, 0x00cff200 },
+	[GDT_ENTRY_KERNEL_CS] = { { 0x00cf9a000000ffffULL } },
+	[GDT_ENTRY_KERNEL_DS] = { { 0x00cf92000000ffffULL } },
+	[GDT_ENTRY_DEFAULT_USER_CS] = { { 0x00cffa000000ffffULL } },
+	[GDT_ENTRY_DEFAULT_USER_DS] = { { 0x00cff2000000ffffULL } },
 	/*
 	 * Segments used for calling PnP BIOS have byte granularity.
 	 * They code segments and data segments have fixed 64k limits,
 	 * the transfer segment sizes are set at run time.
 	 */
-	[GDT_ENTRY_PNPBIOS_CS32] = { 0x0000ffff, 0x00409a00 },/* 32-bit code */
-	[GDT_ENTRY_PNPBIOS_CS16] = { 0x0000ffff, 0x00009a00 },/* 16-bit code */
-	[GDT_ENTRY_PNPBIOS_DS] = { 0x0000ffff, 0x00009200 }, /* 16-bit data */
-	[GDT_ENTRY_PNPBIOS_TS1] = { 0x00000000, 0x00009200 },/* 16-bit data */
-	[GDT_ENTRY_PNPBIOS_TS2] = { 0x00000000, 0x00009200 },/* 16-bit data */
+	/* 32-bit code */
+	[GDT_ENTRY_PNPBIOS_CS32] = { { 0x00409a000000ffffULL } },
+	/* 16-bit code */
+	[GDT_ENTRY_PNPBIOS_CS16] = { { 0x00009a000000ffffULL } },
+	/* 16-bit data */
+	[GDT_ENTRY_PNPBIOS_DS] = { { 0x000092000000ffffULL } },
+	/* 16-bit data */
+	[GDT_ENTRY_PNPBIOS_TS1] = { { 0x0000920000000000ULL } },
+	/* 16-bit data */
+	[GDT_ENTRY_PNPBIOS_TS2] = { { 0x0000920000000000ULL } },
 	/*
 	 * The APM segments have byte granularity and their bases
 	 * are set at run time.  All have 64k limits.
 	 */
-	[GDT_ENTRY_APMBIOS_BASE] = { 0x0000ffff, 0x00409a00 },/* 32-bit code */
+	/* 32-bit code */
+	[GDT_ENTRY_APMBIOS_BASE] = { { 0x00409a000000ffffULL } },
 	/* 16-bit code */
-	[GDT_ENTRY_APMBIOS_BASE+1] = { 0x0000ffff, 0x00009a00 },
-	[GDT_ENTRY_APMBIOS_BASE+2] = { 0x0000ffff, 0x00409200 }, /* data */
+	[GDT_ENTRY_APMBIOS_BASE+1] = { { 0x00009a000000ffffULL } },
+	/* data */
+	[GDT_ENTRY_APMBIOS_BASE+2] = { { 0x004092000000ffffULL } },
 
-	[GDT_ENTRY_ESPFIX_SS] = { 0x00000000, 0x00c09200 },
-	[GDT_ENTRY_PERCPU] = { 0x00000000, 0x00000000 },
+	[GDT_ENTRY_ESPFIX_SS] = { { 0x00c0920000000000ULL } },
+	[GDT_ENTRY_PERCPU] = { { 0x0000000000000000ULL } },
 } };
 EXPORT_PER_CPU_SYMBOL_GPL(gdt_page);
 
diff -r ca43743e0c27 arch/x86/kernel/process_32.c
--- a/arch/x86/kernel/process_32.c	Fri Nov 23 11:44:20 2007 +1100
+++ b/arch/x86/kernel/process_32.c	Sat Nov 24 14:54:16 2007 +1100
@@ -499,9 +499,9 @@ int copy_thread(int nr, unsigned long cl
 		if (idx < GDT_ENTRY_TLS_MIN || idx > GDT_ENTRY_TLS_MAX)
 			goto out;
 
-		desc = p->thread.tls_array + idx - GDT_ENTRY_TLS_MIN;
-		desc->a = LDT_entry_a(&info);
-		desc->b = LDT_entry_b(&info);
+		desc = &p->thread.tls_array[idx - GDT_ENTRY_TLS_MIN];
+		desc->raw.a = LDT_entry_a(&info);
+		desc->raw.b = LDT_entry_b(&info);
 	}
 
 	err = 0;
@@ -902,11 +902,11 @@ asmlinkage int sys_set_thread_area(struc
 	cpu = get_cpu();
 
 	if (LDT_empty(&info)) {
-		desc->a = 0;
-		desc->b = 0;
+		desc->raw.a = 0;
+		desc->raw.b = 0;
 	} else {
-		desc->a = LDT_entry_a(&info);
-		desc->b = LDT_entry_b(&info);
+		desc->raw.a = LDT_entry_a(&info);
+		desc->raw.b = LDT_entry_b(&info);
 	}
 	load_TLS(t, cpu);
 
@@ -919,21 +919,8 @@ asmlinkage int sys_set_thread_area(struc
  * Get the current Thread-Local Storage area:
  */
 
-#define GET_BASE(desc) ( \
-	(((desc)->a >> 16) & 0x0000ffff) | \
-	(((desc)->b << 16) & 0x00ff0000) | \
-	( (desc)->b        & 0xff000000)   )
-
-#define GET_LIMIT(desc) ( \
-	((desc)->a & 0x0ffff) | \
-	 ((desc)->b & 0xf0000) )
-	
-#define GET_32BIT(desc)		(((desc)->b >> 22) & 1)
-#define GET_CONTENTS(desc)	(((desc)->b >> 10) & 3)
-#define GET_WRITABLE(desc)	(((desc)->b >>  9) & 1)
-#define GET_LIMIT_PAGES(desc)	(((desc)->b >> 23) & 1)
-#define GET_PRESENT(desc)	(((desc)->b >> 15) & 1)
-#define GET_USEABLE(desc)	(((desc)->b >> 20) & 1)
+#define GET_CONTENTS(desc)	(((desc)->raw.b >> 10) & 3)
+#define GET_WRITABLE(desc)	(((desc)->raw.b >>  9) & 1)
 
 asmlinkage int sys_get_thread_area(struct user_desc __user *u_info)
 {
@@ -951,14 +938,14 @@ asmlinkage int sys_get_thread_area(struc
 	desc = current->thread.tls_array + idx - GDT_ENTRY_TLS_MIN;
 
 	info.entry_number = idx;
-	info.base_addr = GET_BASE(desc);
-	info.limit = GET_LIMIT(desc);
-	info.seg_32bit = GET_32BIT(desc);
+	info.base_addr = get_seg_desc_base(&desc->seg);
+	info.limit = get_seg_desc_limit(&desc->seg);
+	info.seg_32bit = desc->seg.d;
 	info.contents = GET_CONTENTS(desc);
 	info.read_exec_only = !GET_WRITABLE(desc);
-	info.limit_in_pages = GET_LIMIT_PAGES(desc);
-	info.seg_not_present = !GET_PRESENT(desc);
-	info.useable = GET_USEABLE(desc);
+	info.limit_in_pages = desc->seg.g;
+	info.seg_not_present = !desc->seg.p;
+	info.useable = desc->seg.avl;
 
 	if (copy_to_user(u_info, &info, sizeof(info)))
 		return -EFAULT;
diff -r ca43743e0c27 arch/x86/kernel/process_64.c
--- a/arch/x86/kernel/process_64.c	Fri Nov 23 11:44:20 2007 +1100
+++ b/arch/x86/kernel/process_64.c	Sat Nov 24 14:54:16 2007 +1100
@@ -445,19 +445,13 @@ static inline void set_32bit_tls(struct 
 		.limit_in_pages = 1,
 		.useable = 1,
 	};
-	struct n_desc_struct *desc = (void *)t->thread.tls_array;
-	desc += tls;
-	desc->a = LDT_entry_a(&ud); 
-	desc->b = LDT_entry_b(&ud); 
+	t->thread.tls_array[tls].raw.a = LDT_entry_a(&ud);
+	t->thread.tls_array[tls].raw.b = LDT_entry_b(&ud);
 }
 
 static inline u32 read_32bit_tls(struct task_struct *t, int tls)
 {
-	struct desc_struct *desc = (void *)t->thread.tls_array;
-	desc += tls;
-	return desc->base0 | 
-		(((u32)desc->base1) << 16) | 
-		(((u32)desc->base2) << 24);
+	return get_seg_desc_base(&t->thread.tls_array[tls].seg);
 }
 
 /*
diff -r ca43743e0c27 arch/x86/kernel/ptrace_32.c
--- a/arch/x86/kernel/ptrace_32.c	Fri Nov 23 11:44:20 2007 +1100
+++ b/arch/x86/kernel/ptrace_32.c	Sat Nov 24 14:54:16 2007 +1100
@@ -290,21 +290,8 @@ ptrace_get_thread_area(struct task_struc
  * Get the current Thread-Local Storage area:
  */
 
-#define GET_BASE(desc) ( \
-	(((desc)->a >> 16) & 0x0000ffff) | \
-	(((desc)->b << 16) & 0x00ff0000) | \
-	( (desc)->b        & 0xff000000)   )
-
-#define GET_LIMIT(desc) ( \
-	((desc)->a & 0x0ffff) | \
-	 ((desc)->b & 0xf0000) )
-
-#define GET_32BIT(desc)		(((desc)->b >> 22) & 1)
-#define GET_CONTENTS(desc)	(((desc)->b >> 10) & 3)
-#define GET_WRITABLE(desc)	(((desc)->b >>  9) & 1)
-#define GET_LIMIT_PAGES(desc)	(((desc)->b >> 23) & 1)
-#define GET_PRESENT(desc)	(((desc)->b >> 15) & 1)
-#define GET_USEABLE(desc)	(((desc)->b >> 20) & 1)
+#define GET_CONTENTS(desc)	(((desc)->raw.b >> 10) & 3)
+#define GET_WRITABLE(desc)	(((desc)->raw.b >>  9) & 1)
 
 	if (idx < GDT_ENTRY_TLS_MIN || idx > GDT_ENTRY_TLS_MAX)
 		return -EINVAL;
@@ -312,14 +299,14 @@ ptrace_get_thread_area(struct task_struc
 	desc = child->thread.tls_array + idx - GDT_ENTRY_TLS_MIN;
 
 	info.entry_number = idx;
-	info.base_addr = GET_BASE(desc);
-	info.limit = GET_LIMIT(desc);
-	info.seg_32bit = GET_32BIT(desc);
+	info.base_addr = get_seg_desc_base(&desc->seg);
+	info.limit = get_seg_desc_limit(&desc->seg);
+	info.seg_32bit = desc->seg.d;
 	info.contents = GET_CONTENTS(desc);
 	info.read_exec_only = !GET_WRITABLE(desc);
-	info.limit_in_pages = GET_LIMIT_PAGES(desc);
-	info.seg_not_present = !GET_PRESENT(desc);
-	info.useable = GET_USEABLE(desc);
+	info.limit_in_pages = desc->seg.g;
+	info.seg_not_present = !desc->seg.p;
+	info.useable = desc->seg.avl;
 
 	if (copy_to_user(user_desc, &info, sizeof(info)))
 		return -EFAULT;
@@ -345,11 +332,11 @@ ptrace_set_thread_area(struct task_struc
 
 	desc = child->thread.tls_array + idx - GDT_ENTRY_TLS_MIN;
 	if (LDT_empty(&info)) {
-		desc->a = 0;
-		desc->b = 0;
+		desc->raw.a = 0;
+		desc->raw.b = 0;
 	} else {
-		desc->a = LDT_entry_a(&info);
-		desc->b = LDT_entry_b(&info);
+		desc->raw.a = LDT_entry_a(&info);
+		desc->raw.b = LDT_entry_b(&info);
 	}
 
 	return 0;
diff -r ca43743e0c27 arch/x86/kernel/smpcommon_32.c
--- a/arch/x86/kernel/smpcommon_32.c	Fri Nov 23 11:44:20 2007 +1100
+++ b/arch/x86/kernel/smpcommon_32.c	Sat Nov 24 14:54:16 2007 +1100
@@ -14,8 +14,8 @@ __cpuinit void init_gdt(int cpu)
 {
 	struct desc_struct *gdt = get_cpu_gdt_table(cpu);
 
-	pack_descriptor((u32 *)&gdt[GDT_ENTRY_PERCPU].a,
-			(u32 *)&gdt[GDT_ENTRY_PERCPU].b,
+	pack_descriptor((u32 *)&gdt[GDT_ENTRY_PERCPU].raw.a,
+			(u32 *)&gdt[GDT_ENTRY_PERCPU].raw.b,
 			__per_cpu_offset[cpu], 0xFFFFF,
 			0x80 | DESCTYPE_S | 0x2, 0x8);
 
diff -r ca43743e0c27 arch/x86/kernel/suspend_64.c
--- a/arch/x86/kernel/suspend_64.c	Fri Nov 23 11:44:20 2007 +1100
+++ b/arch/x86/kernel/suspend_64.c	Sat Nov 24 14:54:16 2007 +1100
@@ -120,7 +120,7 @@ void fix_processor_context(void)
 
 	set_tss_desc(cpu,t);	/* This just modifies memory; should not be necessary. But... This is necessary, because 386 hardware has concept of busy TSS or some similar stupidity. */
 
-	cpu_gdt(cpu)[GDT_ENTRY_TSS].type = 9;
+	cpu_gdt(cpu)[GDT_ENTRY_TSS].seg.type = DESC_TSS;
 
 	syscall_init();                         /* This sets MSR_*STAR and related */
 	load_TR_desc();				/* This does ltr */
diff -r ca43743e0c27 arch/x86/kernel/traps_32.c
--- a/arch/x86/kernel/traps_32.c	Fri Nov 23 11:44:20 2007 +1100
+++ b/arch/x86/kernel/traps_32.c	Sat Nov 24 14:54:16 2007 +1100
@@ -76,7 +76,7 @@ char ignore_fpu_irq = 0;
  * F0 0F bug workaround.. We have a special link segment
  * for this.
  */
-struct desc_struct idt_table[256] __attribute__((__section__(".data.idt"))) = { {0, 0}, };
+struct desc_struct idt_table[256] __attribute__((__section__(".data.idt")));
 
 asmlinkage void divide_error(void);
 asmlinkage void debug(void);
diff -r ca43743e0c27 arch/x86/kernel/vmi_32.c
--- a/arch/x86/kernel/vmi_32.c	Fri Nov 23 11:44:20 2007 +1100
+++ b/arch/x86/kernel/vmi_32.c	Sat Nov 24 14:54:16 2007 +1100
@@ -185,8 +185,8 @@ static void vmi_cpuid(unsigned int *eax,
 
 static inline void vmi_maybe_load_tls(struct desc_struct *gdt, int nr, struct desc_struct *new)
 {
-	if (gdt[nr].a != new->a || gdt[nr].b != new->b)
-		write_gdt_entry(gdt, nr, new->a, new->b);
+	if (!desc_equal(&gdt[nr], new))
+		write_gdt_entry(gdt, nr, new->raw.a, new->raw.b);
 }
 
 static void vmi_load_tls(struct thread_struct *t, unsigned int cpu)
diff -r ca43743e0c27 arch/x86/lguest/boot.c
--- a/arch/x86/lguest/boot.c	Fri Nov 23 11:44:20 2007 +1100
+++ b/arch/x86/lguest/boot.c	Sat Nov 24 14:54:16 2007 +1100
@@ -235,7 +235,7 @@ static void lguest_load_idt(const struct
 	struct desc_struct *idt = (void *)desc->address;
 
 	for (i = 0; i < (desc->size+1)/8; i++)
-		hcall(LHCALL_LOAD_IDT_ENTRY, i, idt[i].a, idt[i].b);
+		hcall(LHCALL_LOAD_IDT_ENTRY, i, idt[i].raw.a, idt[i].raw.b);
 }
 
 /*
diff -r ca43743e0c27 arch/x86/math-emu/fpu_entry.c
--- a/arch/x86/math-emu/fpu_entry.c	Fri Nov 23 11:44:20 2007 +1100
+++ b/arch/x86/math-emu/fpu_entry.c	Sat Nov 24 14:54:16 2007 +1100
@@ -204,9 +204,9 @@ asmlinkage void math_emulate(long arg)
 	  /* 16 bit protected mode */
 	  addr_modes.default_mode = PM16;
 	}
-      FPU_EIP += code_base = SEG_BASE_ADDR(code_descriptor);
+      FPU_EIP += code_base = get_seg_desc_base(&code_descriptor.seg);
       code_limit = code_base
-	+ (SEG_LIMIT(code_descriptor)+1) * SEG_GRANULARITY(code_descriptor)
+	+ (get_seg_desc_limit(&code_descriptor.seg)+1) * SEG_GRANULARITY(code_descriptor)
 	  - 1;
       if ( code_limit < code_base ) code_limit = 0xffffffff;
     }
diff -r ca43743e0c27 arch/x86/math-emu/fpu_system.h
--- a/arch/x86/math-emu/fpu_system.h	Fri Nov 23 11:44:20 2007 +1100
+++ b/arch/x86/math-emu/fpu_system.h	Sat Nov 24 14:54:16 2007 +1100
@@ -23,16 +23,13 @@
 /* s is always from a cpu register, and the cpu does bounds checking
  * during register load --> no further bounds checks needed */
 #define LDT_DESCRIPTOR(s)	(((struct desc_struct *)current->mm->context.ldt)[(s) >> 3])
-#define SEG_D_SIZE(x)		((x).b & (3 << 21))
-#define SEG_G_BIT(x)		((x).b & (1 << 23))
-#define SEG_GRANULARITY(x)	(((x).b & (1 << 23)) ? 4096 : 1)
-#define SEG_286_MODE(x)		((x).b & ( 0xff000000 | 0xf0000 | (1 << 23)))
-#define SEG_BASE_ADDR(s)	(((s).b & 0xff000000) \
-				 | (((s).b & 0xff) << 16) | ((s).a >> 16))
-#define SEG_LIMIT(s)		(((s).b & 0xff0000) | ((s).a & 0xffff))
-#define SEG_EXECUTE_ONLY(s)	(((s).b & ((1 << 11) | (1 << 9))) == (1 << 11))
-#define SEG_WRITE_PERM(s)	(((s).b & ((1 << 11) | (1 << 9))) == (1 << 9))
-#define SEG_EXPAND_DOWN(s)	(((s).b & ((1 << 11) | (1 << 10))) \
+#define SEG_D_SIZE(x)		((x).raw.b & (3 << 21))
+#define SEG_G_BIT(x)		((x).seg.g)
+#define SEG_GRANULARITY(x)	((x).seg.g ? 4096 : 1)
+#define SEG_286_MODE(x)		((x).raw.b & ( 0xff000000 | 0xf0000 | (1 << 23)))
+#define SEG_EXECUTE_ONLY(s)	(((s).raw.b & ((1 << 11) | (1 << 9))) == (1 << 11))
+#define SEG_WRITE_PERM(s)	(((s).raw.b & ((1 << 11) | (1 << 9))) == (1 << 9))
+#define SEG_EXPAND_DOWN(s)	(((s).raw.b & ((1 << 11) | (1 << 10))) \
 				 == (1 << 10))
 
 #define I387			(current->thread.i387)
diff -r ca43743e0c27 arch/x86/math-emu/get_address.c
--- a/arch/x86/math-emu/get_address.c	Fri Nov 23 11:44:20 2007 +1100
+++ b/arch/x86/math-emu/get_address.c	Sat Nov 24 14:54:16 2007 +1100
@@ -179,10 +179,10 @@ static long pm_address(u_char FPU_modrm,
     }
 
   descriptor = LDT_DESCRIPTOR(PM_REG_(segment));
-  base_address = SEG_BASE_ADDR(descriptor);
+  base_address = get_seg_desc_base(&descriptor.seg);
   address = base_address + offset;
   limit = base_address
-	+ (SEG_LIMIT(descriptor)+1) * SEG_GRANULARITY(descriptor) - 1;
+	+ (get_seg_desc_limit(&descriptor.seg)+1) * SEG_GRANULARITY(descriptor) - 1;
   if ( limit < base_address ) limit = 0xffffffff;
 
   if ( SEG_EXPAND_DOWN(descriptor) )
diff -r ca43743e0c27 drivers/kvm/kvm_main.c
--- a/drivers/kvm/kvm_main.c	Fri Nov 23 11:44:20 2007 +1100
+++ b/drivers/kvm/kvm_main.c	Sat Nov 24 14:54:16 2007 +1100
@@ -117,7 +117,7 @@ static long kvm_vcpu_ioctl(struct file *
 
 unsigned long segment_base(u16 selector)
 {
-	struct descriptor_table gdt;
+	struct Xgt_desc_struct gdt;
 	struct segment_descriptor *d;
 	unsigned long table_base;
 	typedef unsigned long ul;
@@ -126,15 +126,17 @@ unsigned long segment_base(u16 selector)
 	if (selector == 0)
 		return 0;
 
-	asm ("sgdt %0" : "=m"(gdt));
-	table_base = gdt.base;
-
-	if (selector & 4) {           /* from ldt */
+	if ((selector & SEGMENT_TI_MASK) == SEGMENT_LDT) {
 		u16 ldt_selector;
 
+		/* FIXME: paravirt_ops doesn't have a store_ldt */
 		asm ("sldt %0" : "=g"(ldt_selector));
 		table_base = segment_base(ldt_selector);
+	} else {
+		store_gdt(&gdt);
+		table_base = gdt.address;
 	}
+
 	d = (struct segment_descriptor *)(table_base + (selector & ~7));
 	v = d->base_low | ((ul)d->base_mid << 16) | ((ul)d->base_high << 24);
 #ifdef CONFIG_X86_64
diff -r ca43743e0c27 drivers/lguest/interrupts_and_traps.c
--- a/drivers/lguest/interrupts_and_traps.c	Fri Nov 23 11:44:20 2007 +1100
+++ b/drivers/lguest/interrupts_and_traps.c	Sat Nov 24 14:54:16 2007 +1100
@@ -178,13 +178,13 @@ void maybe_do_interrupt(struct lguest *l
 	 * over them. */
 	idt = &lg->arch.idt[FIRST_EXTERNAL_VECTOR+irq];
 	/* If they don't have a handler (yet?), we just ignore it */
-	if (idt_present(idt->a, idt->b)) {
+	if (idt_present(idt->raw.a, idt->raw.b)) {
 		/* OK, mark it no longer pending and deliver it. */
 		clear_bit(irq, lg->irqs_pending);
 		/* set_guest_interrupt() takes the interrupt descriptor and a
 		 * flag to say whether this interrupt pushes an error code onto
 		 * the stack as well: virtual interrupts never do. */
-		set_guest_interrupt(lg, idt->a, idt->b, 0);
+		set_guest_interrupt(lg, idt->raw.a, idt->raw.b, 0);
 	}
 
 	/* Every time we deliver an interrupt, we update the timestamp in the
@@ -254,10 +254,10 @@ int deliver_trap(struct lguest *lg, unsi
 
 	/* Early on the Guest hasn't set the IDT entries (or maybe it put a
 	 * bogus one in): if we fail here, the Guest will be killed. */
-	if (!idt_present(lg->arch.idt[num].a, lg->arch.idt[num].b))
+	if (!idt_present(lg->arch.idt[num].raw.a, lg->arch.idt[num].raw.b))
 		return 0;
-	set_guest_interrupt(lg, lg->arch.idt[num].a, lg->arch.idt[num].b,
-			    has_err(num));
+	set_guest_interrupt(lg, lg->arch.idt[num].raw.a,
+			    lg->arch.idt[num].raw.b, has_err(num));
 	return 1;
 }
 
@@ -360,7 +360,7 @@ static void set_trap(struct lguest *lg, 
 
 	/* We zero-out a not-present entry */
 	if (!idt_present(lo, hi)) {
-		trap->a = trap->b = 0;
+		trap->raw.a = trap->raw.b = 0;
 		return;
 	}
 
@@ -372,8 +372,8 @@ static void set_trap(struct lguest *lg, 
 	 * type.  The privilege level controls where the trap can be triggered
 	 * manually with an "int" instruction.  This is usually GUEST_PL,
 	 * except for system calls which userspace can use. */
-	trap->a = ((__KERNEL_CS|GUEST_PL)<<16) | (lo&0x0000FFFF);
-	trap->b = (hi&0xFFFFEF00);
+	trap->raw.a = ((__KERNEL_CS|GUEST_PL)<<16) | (lo&0x0000FFFF);
+	trap->raw.b = (hi&0xFFFFEF00);
 }
 
 /*H:230 While we're here, dealing with delivering traps and interrupts to the
@@ -417,8 +417,8 @@ static void default_idt_entry(struct des
 		flags |= (GUEST_PL << 13);
 
 	/* Now pack it into the IDT entry in its weird format. */
-	idt->a = (LGUEST_CS<<16) | (handler&0x0000FFFF);
-	idt->b = (handler&0xFFFF0000) | flags;
+	idt->raw.a = (LGUEST_CS<<16) | (handler&0x0000FFFF);
+	idt->raw.b = (handler&0xFFFF0000) | flags;
 }
 
 /* When the Guest first starts, we put default entries into the IDT. */
@@ -450,7 +450,7 @@ void copy_traps(const struct lguest *lg,
 		 * Interrupt gates (type 14) disable interrupts as they are
 		 * entered, which we never let the Guest do.  Not present
 		 * entries (type 0x0) also can't go direct, of course. */
-		if (idt_type(lg->arch.idt[i].a, lg->arch.idt[i].b) == 0xF)
+		if (idt_type(lg->arch.idt[i].raw.a, lg->arch.idt[i].raw.b)==0xF)
 			idt[i] = lg->arch.idt[i];
 		else
 			/* Reset it to the default. */
diff -r ca43743e0c27 drivers/lguest/segments.c
--- a/drivers/lguest/segments.c	Fri Nov 23 11:44:20 2007 +1100
+++ b/drivers/lguest/segments.c	Sat Nov 24 14:54:16 2007 +1100
@@ -71,14 +71,14 @@ static void fixup_gdt_table(struct lgues
 		/* Segment descriptors contain a privilege level: the Guest is
 		 * sometimes careless and leaves this as 0, even though it's
 		 * running at privilege level 1.  If so, we fix it here. */
-		if ((lg->arch.gdt[i].b & 0x00006000) == 0)
-			lg->arch.gdt[i].b |= (GUEST_PL << 13);
+		if ((lg->arch.gdt[i].raw.b & 0x00006000) == 0)
+			lg->arch.gdt[i].raw.b |= (GUEST_PL << 13);
 
 		/* Each descriptor has an "accessed" bit.  If we don't set it
 		 * now, the CPU will try to set it when the Guest first loads
 		 * that entry into a segment register.  But the GDT isn't
 		 * writable by the Guest, so bad things can happen. */
-		lg->arch.gdt[i].b |= 0x00000100;
+		lg->arch.gdt[i].raw.b |= 0x00000100;
 	}
 }
 
@@ -95,15 +95,15 @@ void setup_default_gdt_entries(struct lg
 	unsigned long tss = (unsigned long)&state->guest_tss;
 
 	/* The Switcher segments are full 0-4G segments, privilege level 0 */
-	gdt[GDT_ENTRY_LGUEST_CS] = FULL_EXEC_SEGMENT;
-	gdt[GDT_ENTRY_LGUEST_DS] = FULL_SEGMENT;
+	gdt[GDT_ENTRY_LGUEST_CS].raw = FULL_EXEC_SEGMENT;
+	gdt[GDT_ENTRY_LGUEST_DS].raw = FULL_SEGMENT;
 
 	/* The TSS segment refers to the TSS entry for this particular CPU.
 	 * Forgive the magic flags: the 0x8900 means the entry is Present, it's
 	 * privilege level 0 Available 386 TSS system segment, and the 0x67
 	 * means Saturn is eclipsed by Mercury in the twelfth house. */
-	gdt[GDT_ENTRY_TSS].a = 0x00000067 | (tss << 16);
-	gdt[GDT_ENTRY_TSS].b = 0x00008900 | (tss & 0xFF000000)
+	gdt[GDT_ENTRY_TSS].raw.a = 0x00000067 | (tss << 16);
+	gdt[GDT_ENTRY_TSS].raw.b = 0x00008900 | (tss & 0xFF000000)
 		| ((tss >> 16) & 0x000000FF);
 }
 
@@ -112,12 +112,12 @@ void setup_guest_gdt(struct lguest *lg)
 void setup_guest_gdt(struct lguest *lg)
 {
 	/* Start with full 0-4G segments... */
-	lg->arch.gdt[GDT_ENTRY_KERNEL_CS] = FULL_EXEC_SEGMENT;
-	lg->arch.gdt[GDT_ENTRY_KERNEL_DS] = FULL_SEGMENT;
+	lg->arch.gdt[GDT_ENTRY_KERNEL_CS].raw = FULL_EXEC_SEGMENT;
+	lg->arch.gdt[GDT_ENTRY_KERNEL_DS].raw = FULL_SEGMENT;
 	/* ...except the Guest is allowed to use them, so set the privilege
 	 * level appropriately in the flags. */
-	lg->arch.gdt[GDT_ENTRY_KERNEL_CS].b |= (GUEST_PL << 13);
-	lg->arch.gdt[GDT_ENTRY_KERNEL_DS].b |= (GUEST_PL << 13);
+	lg->arch.gdt[GDT_ENTRY_KERNEL_CS].raw.b |= (GUEST_PL << 13);
+	lg->arch.gdt[GDT_ENTRY_KERNEL_DS].raw.b |= (GUEST_PL << 13);
 }
 
 /*H:650 An optimization of copy_gdt(), for just the three "thead-local storage"
diff -r ca43743e0c27 drivers/lguest/x86/core.c
--- a/drivers/lguest/x86/core.c	Fri Nov 23 11:44:20 2007 +1100
+++ b/drivers/lguest/x86/core.c	Sat Nov 24 14:54:16 2007 +1100
@@ -434,8 +434,8 @@ void __init lguest_arch_host_init(void)
 
 		/* The Host needs to be able to use the LGUEST segments on this
 		 * CPU, too, so put them in the Host GDT. */
-		get_cpu_gdt_table(i)[GDT_ENTRY_LGUEST_CS] = FULL_EXEC_SEGMENT;
-		get_cpu_gdt_table(i)[GDT_ENTRY_LGUEST_DS] = FULL_SEGMENT;
+		get_cpu_gdt_table(i)[GDT_ENTRY_LGUEST_CS].raw=FULL_EXEC_SEGMENT;
+		get_cpu_gdt_table(i)[GDT_ENTRY_LGUEST_DS].raw = FULL_SEGMENT;
 	}
 
 	/* In the Switcher, we want the %cs segment register to use the
diff -r ca43743e0c27 drivers/pnp/pnpbios/bioscalls.c
--- a/drivers/pnp/pnpbios/bioscalls.c	Fri Nov 23 11:44:20 2007 +1100
+++ b/drivers/pnp/pnpbios/bioscalls.c	Sat Nov 24 14:54:16 2007 +1100
@@ -61,7 +61,7 @@ set_limit(gdt[(selname) >> 3], size); \
 set_limit(gdt[(selname) >> 3], size); \
 } while(0)
 
-static struct desc_struct bad_bios_desc = { 0, 0x00409200 };
+static struct desc_struct bad_bios_desc = { { 0, 0x00409200 } };
 
 /*
  * At some point we want to use this stack frame pointer to unwind
diff -r ca43743e0c27 include/asm-x86/desc_32.h
--- a/include/asm-x86/desc_32.h	Fri Nov 23 11:44:20 2007 +1100
+++ b/include/asm-x86/desc_32.h	Sat Nov 24 14:54:16 2007 +1100
@@ -11,6 +11,7 @@
 #include <linux/percpu.h>
 
 #include <asm/mmu.h>
+#include <asm/desc_defs.h>
 
 struct Xgt_desc_struct {
 	unsigned short size;
@@ -81,8 +82,8 @@ static inline void write_dt_entry(struct
 static inline void write_dt_entry(struct desc_struct *dt,
 				  int entry, u32 entry_low, u32 entry_high)
 {
-	dt[entry].a = entry_low;
-	dt[entry].b = entry_high;
+	dt[entry].raw.a = entry_low;
+	dt[entry].raw.b = entry_high;
 }
 
 static inline void native_set_ldt(const void *addr, unsigned int entries)
diff -r ca43743e0c27 include/asm-x86/desc_64.h
--- a/include/asm-x86/desc_64.h	Fri Nov 23 11:44:20 2007 +1100
+++ b/include/asm-x86/desc_64.h	Sat Nov 24 14:54:16 2007 +1100
@@ -35,7 +35,7 @@ static inline unsigned long __store_tr(v
  * something other than this.
  */
 extern struct desc_struct default_ldt[];
-extern struct gate_struct idt_table[]; 
+extern struct gate_struct_64 idt_table[]; 
 extern struct desc_ptr cpu_gdt_descr[];
 
 /* the cpu gdt accessor */
@@ -53,7 +53,7 @@ static inline void store_gdt(struct desc
 
 static inline void _set_gate(void *adr, unsigned type, unsigned long func, unsigned dpl, unsigned ist)  
 {
-	struct gate_struct s; 	
+	struct gate_struct_64 s; 	
 	s.offset_low = PTR_LOW(func); 
 	s.segment = __KERNEL_CS;
 	s.ist = ist; 
@@ -104,7 +104,7 @@ static inline void set_tssldt_descriptor
 static inline void set_tssldt_descriptor(void *ptr, unsigned long tss, unsigned type, 
 					 unsigned size) 
 { 
-	struct ldttss_desc d;
+	struct ldttss_desc_64 d;
 	memset(&d,0,sizeof(d)); 
 	d.limit0 = size & 0xFFFF;
 	d.base0 = PTR_LOW(tss); 
@@ -168,7 +168,7 @@ static inline void load_TLS(struct threa
 static inline void load_TLS(struct thread_struct *t, unsigned int cpu)
 {
 	unsigned int i;
-	u64 *gdt = (u64 *)(cpu_gdt(cpu) + GDT_ENTRY_TLS_MIN);
+	struct desc_struct *gdt = cpu_gdt(cpu) + GDT_ENTRY_TLS_MIN;
 
 	for (i = 0; i < GDT_ENTRY_TLS_ENTRIES; i++)
 		gdt[i] = t->tls_array[i];
diff -r ca43743e0c27 include/asm-x86/desc_defs.h
--- a/include/asm-x86/desc_defs.h	Fri Nov 23 11:44:20 2007 +1100
+++ b/include/asm-x86/desc_defs.h	Sat Nov 24 14:54:16 2007 +1100
@@ -11,16 +11,43 @@
 
 #include <linux/types.h>
 
-// 8 byte segment descriptor
-struct desc_struct {
+// 8 byte segment descriptor (GDT/LDT)
+struct segment_desc {
 	u16 limit0;
 	u16 base0;
 	unsigned base1 : 8, type : 4, s : 1, dpl : 2, p : 1;
 	unsigned limit : 4, avl : 1, l : 1, d : 1, g : 1, base2 : 8;
 } __attribute__((packed));
 
-struct n_desc_struct {
+static inline u32 get_seg_desc_base(const struct segment_desc *seg)
+{
+	return seg->base0 | ((u32)seg->base1 << 16) | ((u32)seg->base2 << 24);
+}
+
+static inline u32 get_seg_desc_limit(const struct segment_desc *seg)
+{
+	return seg->limit0 | ((u32)seg->limit << 16);
+}
+
+// 8 byte interrupt/trap descriptor (i386 IDT)
+struct gate_struct_32 {
+	u16 offset_low;
+	u16 segment;
+	unsigned zero0 : 8, type : 5, dpl : 2, p : 1;
+	u16 offset_middle;
+};
+
+struct raw_desc {
 	unsigned int a,b;
+};
+
+struct desc_struct {
+	union {
+		u64 raw64;
+		struct segment_desc seg;
+		struct gate_struct_32 gate;
+		struct raw_desc raw;
+	};
 };
 
 enum {
@@ -29,8 +56,8 @@ enum {
 	GATE_CALL = 0xC,
 };
 
-// 16byte gate
-struct gate_struct {
+// 16byte gate (x86_64 only)
+struct gate_struct_64 {
 	u16 offset_low;
 	u16 segment;
 	unsigned ist : 3, zero0 : 5, type : 5, dpl : 2, p : 1;
@@ -48,8 +75,8 @@ enum {
 	DESC_LDT = 0x2,
 };
 
-// LDT or TSS descriptor in the GDT. 16 bytes.
-struct ldttss_desc {
+// LDT or TSS descriptor in the GDT (x86_64 only). 16 bytes.
+struct ldttss_desc_64 {
 	u16 limit0;
 	u16 base0;
 	unsigned base1 : 8, type : 5, dpl : 2, p : 1;
@@ -63,7 +90,6 @@ struct desc_ptr {
 	unsigned long address;
 } __attribute__((packed)) ;
 
-
 #endif /* !__ASSEMBLY__ */
 
 #endif
diff -r ca43743e0c27 include/asm-x86/lguest.h
--- a/include/asm-x86/lguest.h	Fri Nov 23 11:44:20 2007 +1100
+++ b/include/asm-x86/lguest.h	Sat Nov 24 14:54:16 2007 +1100
@@ -78,8 +78,8 @@ static inline void lguest_set_ts(void)
 }
 
 /* Full 4G segment descriptors, suitable for CS and DS. */
-#define FULL_EXEC_SEGMENT ((struct desc_struct){0x0000ffff, 0x00cf9b00})
-#define FULL_SEGMENT ((struct desc_struct){0x0000ffff, 0x00cf9300})
+#define FULL_EXEC_SEGMENT ((struct raw_desc){0x0000ffff, 0x00cf9b00})
+#define FULL_SEGMENT ((struct raw_desc){0x0000ffff, 0x00cf9300})
 
 #endif /* __ASSEMBLY__ */
 
diff -r ca43743e0c27 include/asm-x86/processor_32.h
--- a/include/asm-x86/processor_32.h	Fri Nov 23 11:44:20 2007 +1100
+++ b/include/asm-x86/processor_32.h	Sat Nov 24 14:54:16 2007 +1100
@@ -22,19 +22,22 @@
 #include <linux/cpumask.h>
 #include <linux/init.h>
 #include <asm/processor-flags.h>
+#include <asm/desc_defs.h>
 
 /* flag for disabling the tsc */
 extern int tsc_disable;
 
-struct desc_struct {
-	unsigned long a,b;
-};
+static inline bool desc_empty(const struct desc_struct *desc)
+{
+	return !(desc->raw.a | desc->raw.b);
+}
 
-#define desc_empty(desc) \
-		(!((desc)->a | (desc)->b))
+static inline bool desc_equal(const struct desc_struct *d1,
+			      const struct desc_struct *d2)
+{
+	return d1->raw.a == d2->raw.a && d1->raw.b == d2->raw.b;
+}
 
-#define desc_equal(desc1, desc2) \
-		(((desc1)->a == (desc2)->a) && ((desc1)->b == (desc2)->b))
 /*
  * Default implementation of macro that returns current
  * instruction pointer ("program counter").
diff -r ca43743e0c27 include/asm-x86/processor_64.h
--- a/include/asm-x86/processor_64.h	Fri Nov 23 11:44:20 2007 +1100
+++ b/include/asm-x86/processor_64.h	Sat Nov 24 14:54:16 2007 +1100
@@ -21,6 +21,7 @@
 #include <linux/personality.h>
 #include <linux/cpumask.h>
 #include <asm/processor-flags.h>
+#include <asm/desc_defs.h>
 
 #define TF_MASK		0x00000100
 #define IF_MASK		0x00000200
@@ -32,11 +33,16 @@
 #define VIP_MASK	0x00100000	/* virtual interrupt pending */
 #define ID_MASK		0x00200000
 
-#define desc_empty(desc) \
-               (!((desc)->a | (desc)->b))
+static inline bool desc_empty(const struct desc_struct *desc)
+{
+	return !desc->raw64;
+}
 
-#define desc_equal(desc1, desc2) \
-               (((desc1)->a == (desc2)->a) && ((desc1)->b == (desc2)->b))
+static inline bool desc_equal(const struct desc_struct *d1,
+			      const struct desc_struct *d2)
+{
+	return d1->raw64 == d2->raw64;
+}
 
 /*
  * Default implementation of macro that returns current
@@ -240,7 +246,7 @@ struct thread_struct {
 	unsigned long	*io_bitmap_ptr;
 	unsigned io_bitmap_max;
 /* cached TLS descriptors. */
-	u64 tls_array[GDT_ENTRY_TLS_ENTRIES];
+	struct desc_struct tls_array[GDT_ENTRY_TLS_ENTRIES];
 } __attribute__((aligned(16)));
 
 #define INIT_THREAD  { \
diff -r ca43743e0c27 include/asm-x86/xen/hypercall.h
--- a/include/asm-x86/xen/hypercall.h	Fri Nov 23 11:44:20 2007 +1100
+++ b/include/asm-x86/xen/hypercall.h	Sat Nov 24 14:54:16 2007 +1100
@@ -359,8 +359,8 @@ MULTI_update_descriptor(struct multicall
 	mcl->op = __HYPERVISOR_update_descriptor;
 	mcl->args[0] = maddr;
 	mcl->args[1] = maddr >> 32;
-	mcl->args[2] = desc.a;
-	mcl->args[3] = desc.b;
+	mcl->args[2] = desc.raw.a;
+	mcl->args[3] = desc.raw.b;
 }
 
 static inline void
