2007-12-06 19:00:59

by Glauber Costa

[permalink] [raw]
Subject: [PATCH 0/19] desc_struct integration

Hi,

this is a series of patches that unify the struct desc_struct and friends
across x86_64 and i386. As usual, it provides paravirt capabilities as a
side-effect for x86_64.

I consider the main goal, namely, of unifying the desc_struct, an ongoing
effort, being this the beginning. A lot of old code has to be touched to
accomplish that.

I don't consider this patch ready for inclusion. Basically, the main reason
is that I change the signatures of write_idt_entry(), write_gdt_entry(), and
write_ldt_entry(). This is needed to account for the differences between the
two architectures. (For example, gate descriptors in x86_64 are 16-byte long
and can't be represented by low and high entries). As my patch series were
64-bit only, I hadn't come across the problem before.

I think this interface is sane, but I'd like to hear opinions. Specially
from Jeremy and Zach, since it would touch xen and vmi code. The later, by
the way, is _not_ included in this series. Being the interface acked, we
still have to write it.

Thanks in advance for the review in opinions to come.


2007-12-06 19:01:21

by Glauber Costa

[permalink] [raw]
Subject: [PATCH 1/19] unify desc_struct

This patch aims to make the access of struct desc_struct variables
equal across architectures. In this patch, I unify the i386 and x86_64
versions under an anonymous union, keeping the way they are accessed
untouched (a and b for 32-bit code, individual bit-fields for 64-bit).

This solution is not beautiful, but will allow us to integrate common
code that differed by the way descriptors were used. This is to be viewed
incrementally. There's simply too much code to be fixed at once.

In the future, goal is to set up in a single way of acessing
the desc_struct fields.

Signed-off-by: Glauber de Oliveira Costa <[email protected]>
---
arch/x86/kernel/apm_32.c | 2 +-
arch/x86/kernel/cpu/common.c | 28 ++++++++++++++--------------
arch/x86/kernel/process_64.c | 2 +-
arch/x86/kernel/traps_32.c | 2 +-
include/asm-x86/desc_defs.h | 28 ++++++++++++++++++++--------
include/asm-x86/processor_32.h | 5 +----
6 files changed, 38 insertions(+), 29 deletions(-)

diff --git a/arch/x86/kernel/apm_32.c b/arch/x86/kernel/apm_32.c
index 8cd9778..b8b9339 100644
--- a/arch/x86/kernel/apm_32.c
+++ b/arch/x86/kernel/apm_32.c
@@ -405,7 +405,7 @@ static DECLARE_WAIT_QUEUE_HEAD(apm_waitqueue);
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 = {{{ 0, 0x00409200 }}};

static const char driver_version[] = "1.16ac"; /* no spaces */

diff --git a/arch/x86/kernel/cpu/common.c b/arch/x86/kernel/cpu/common.c
index 235cd61..0fe1c1d 100644
--- a/arch/x86/kernel/cpu/common.c
+++ b/arch/x86/kernel/cpu/common.c
@@ -22,31 +22,31 @@
#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] = {{{ 0x0000ffff, 0x00cf9a00 }}},
+ [GDT_ENTRY_KERNEL_DS] = {{{ 0x0000ffff, 0x00cf9200 }}},
+ [GDT_ENTRY_DEFAULT_USER_CS] = {{{ 0x0000ffff, 0x00cffa00 }}},
+ [GDT_ENTRY_DEFAULT_USER_DS] = {{{ 0x0000ffff, 0x00cff200 }}},
/*
* 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 */
+ [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 */
/*
* 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 */
+ [GDT_ENTRY_APMBIOS_BASE] = {{{ 0x0000ffff, 0x00409a00 }}},/* 32-bit code */
/* 16-bit code */
- [GDT_ENTRY_APMBIOS_BASE+1] = { 0x0000ffff, 0x00009a00 },
- [GDT_ENTRY_APMBIOS_BASE+2] = { 0x0000ffff, 0x00409200 }, /* data */
+ [GDT_ENTRY_APMBIOS_BASE+1] = {{{ 0x0000ffff, 0x00009a00 }}},
+ [GDT_ENTRY_APMBIOS_BASE+2] = {{{ 0x0000ffff, 0x00409200 }}}, /* data */

- [GDT_ENTRY_ESPFIX_SS] = { 0x00000000, 0x00c09200 },
- [GDT_ENTRY_PERCPU] = { 0x00000000, 0x00000000 },
+ [GDT_ENTRY_ESPFIX_SS] = {{{ 0x00000000, 0x00c09200 }}},
+ [GDT_ENTRY_PERCPU] = {{{ 0x00000000, 0x00000000 }}},
} };
EXPORT_PER_CPU_SYMBOL_GPL(gdt_page);

diff --git a/arch/x86/kernel/process_64.c b/arch/x86/kernel/process_64.c
index 6724840..9e99cb7 100644
--- a/arch/x86/kernel/process_64.c
+++ b/arch/x86/kernel/process_64.c
@@ -437,7 +437,7 @@ static inline void set_32bit_tls(struct task_struct *t, int tls, u32 addr)
.limit_in_pages = 1,
.useable = 1,
};
- struct n_desc_struct *desc = (void *)t->thread.tls_array;
+ struct desc_struct *desc = (void *)t->thread.tls_array;
desc += tls;
desc->a = LDT_entry_a(&ud);
desc->b = LDT_entry_b(&ud);
diff --git a/arch/x86/kernel/traps_32.c b/arch/x86/kernel/traps_32.c
index e15014e..94c5aea 100644
--- a/arch/x86/kernel/traps_32.c
+++ b/arch/x86/kernel/traps_32.c
@@ -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"))) = { {{{ 0, 0 }}}, };

asmlinkage void divide_error(void);
asmlinkage void debug(void);
diff --git a/include/asm-x86/desc_defs.h b/include/asm-x86/desc_defs.h
index 0890040..b3db064 100644
--- a/include/asm-x86/desc_defs.h
+++ b/include/asm-x86/desc_defs.h
@@ -11,18 +11,30 @@

#include <linux/types.h>

+/*
+ * FIXME: Acessing the desc_struct through its fields is more elegant,
+ * and should be the one valid thing to do. However, a lot of open code
+ * still touches the a and b acessors, and doing this allow us to do it
+ * incrementally. We keep the signature as a struct, rather than an union,
+ * so we can get rid of it transparently in the future -- glommer
+ */
+#define raw_desc_struct struct { unsigned int a, b; }
+#define detailed_desc_struct \
+ struct { \
+ 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;\
+ }
+
// 8 byte segment descriptor
struct desc_struct {
- 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;
+ union {
+ raw_desc_struct;
+ detailed_desc_struct;
+ };
} __attribute__((packed));

-struct n_desc_struct {
- unsigned int a,b;
-};
-
enum {
GATE_INTERRUPT = 0xE,
GATE_TRAP = 0xF,
diff --git a/include/asm-x86/processor_32.h b/include/asm-x86/processor_32.h
index 0d83da1..f1fc049 100644
--- a/include/asm-x86/processor_32.h
+++ b/include/asm-x86/processor_32.h
@@ -20,14 +20,11 @@
#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 int desc_empty(const void *ptr)
{
const u32 *desc = ptr;
--
1.4.4.2

2007-12-06 19:01:36

by Glauber Costa

[permalink] [raw]
Subject: [PATCH 4/19] removed unused variable

This variable is not used anywere, and is then removed

Signed-off-by: Glauber de Oliveira Costa <[email protected]>
---
include/asm-x86/desc_64.h | 5 -----
1 files changed, 0 insertions(+), 5 deletions(-)

diff --git a/include/asm-x86/desc_64.h b/include/asm-x86/desc_64.h
index 1c26dbb..660cc84 100644
--- a/include/asm-x86/desc_64.h
+++ b/include/asm-x86/desc_64.h
@@ -30,11 +30,6 @@ static inline unsigned long __store_tr(void)

#define store_tr(tr) (tr) = __store_tr()

-/*
- * This is the ldt that every process will get unless we need
- * something other than this.
- */
-extern struct desc_struct default_ldt[];
extern struct gate_struct idt_table[];
extern struct desc_ptr cpu_gdt_descr[];

--
1.4.4.2

2007-12-06 19:01:53

by Glauber Costa

[permalink] [raw]
Subject: [PATCH 3/19] change gdt acessor macro name

This patch changes the name of x86_64 macro used to access the per-cpu
gdt. It is now equal to the i386 version, which will allow code to be shared.

Signed-off-by: Glauber de Oliveira Costa <[email protected]>
---
arch/x86/kernel/setup64.c | 2 +-
arch/x86/kernel/suspend_64.c | 2 +-
arch/x86/kernel/vsyscall_64.c | 2 +-
include/asm-x86/desc_64.h | 10 +++++-----
4 files changed, 8 insertions(+), 8 deletions(-)

diff --git a/arch/x86/kernel/setup64.c b/arch/x86/kernel/setup64.c
index 51297cc..05cafcb 100644
--- a/arch/x86/kernel/setup64.c
+++ b/arch/x86/kernel/setup64.c
@@ -228,7 +228,7 @@ void __cpuinit cpu_init (void)
* and set up the GDT descriptor:
*/
if (cpu)
- memcpy(cpu_gdt(cpu), cpu_gdt_table, GDT_SIZE);
+ memcpy(get_cpu_gdt_table(cpu), cpu_gdt_table, GDT_SIZE);

cpu_gdt_descr[cpu].size = GDT_SIZE;
load_gdt((const struct desc_ptr *)&cpu_gdt_descr[cpu]);
diff --git a/arch/x86/kernel/suspend_64.c b/arch/x86/kernel/suspend_64.c
index c58ca08..54eca46 100644
--- a/arch/x86/kernel/suspend_64.c
+++ b/arch/x86/kernel/suspend_64.c
@@ -118,7 +118,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;
+ get_cpu_gdt_table(cpu)[GDT_ENTRY_TSS].type = 9;

syscall_init(); /* This sets MSR_*STAR and related */
load_TR_desc(); /* This does ltr */
diff --git a/arch/x86/kernel/vsyscall_64.c b/arch/x86/kernel/vsyscall_64.c
index c4c5e76..e5c1118 100644
--- a/arch/x86/kernel/vsyscall_64.c
+++ b/arch/x86/kernel/vsyscall_64.c
@@ -297,7 +297,7 @@ static void __cpuinit vsyscall_set_cpu(int cpu)
/* Store cpu number in limit so that it can be loaded quickly
in user space in vgetcpu.
12 bits for the CPU and 8 bits for the node. */
- d = (unsigned long *)(cpu_gdt(cpu) + GDT_ENTRY_PER_CPU);
+ d = (unsigned long *)(get_cpu_gdt_table(cpu) + GDT_ENTRY_PER_CPU);
*d = 0x0f40000000000ULL;
*d |= cpu;
*d |= (node & 0xf) << 12;
diff --git a/include/asm-x86/desc_64.h b/include/asm-x86/desc_64.h
index 230ac6e..1c26dbb 100644
--- a/include/asm-x86/desc_64.h
+++ b/include/asm-x86/desc_64.h
@@ -48,7 +48,7 @@ static inline void write_ldt_entry(struct desc_struct *ldt,
}

/* the cpu gdt accessor */
-#define cpu_gdt(_cpu) ((struct desc_struct *)cpu_gdt_descr[_cpu].address)
+#define get_cpu_gdt_table(_cpu) ((struct desc_struct *)cpu_gdt_descr[_cpu].address)

static inline void load_gdt(const struct desc_ptr *ptr)
{
@@ -141,15 +141,15 @@ static inline void set_tss_desc(unsigned cpu, void *addr)
* -1? seg base+limit should be pointing to the address of the
* last valid byte
*/
- set_tssldt_descriptor(&cpu_gdt(cpu)[GDT_ENTRY_TSS],
+ set_tssldt_descriptor(&get_cpu_gdt_table(cpu)[GDT_ENTRY_TSS],
(unsigned long)addr, DESC_TSS,
IO_BITMAP_OFFSET + IO_BITMAP_BYTES + sizeof(unsigned long) - 1);
}

static inline void set_ldt_desc(unsigned cpu, void *addr, int size)
{
- set_tssldt_descriptor(&cpu_gdt(cpu)[GDT_ENTRY_LDT], (unsigned long)addr,
- DESC_LDT, size * 8 - 1);
+ set_tssldt_descriptor(&get_cpu_gdt_table(cpu)[GDT_ENTRY_LDT],
+ (unsigned long)addr, DESC_LDT, size * 8 - 1);
}

#define LDT_entry_a(info) \
@@ -183,7 +183,7 @@ static inline void set_ldt_desc(unsigned cpu, void *addr, int size)
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);
+ u64 *gdt = (u64 *)(get_cpu_gdt_table(cpu) + GDT_ENTRY_TLS_MIN);

for (i = 0; i < GDT_ENTRY_TLS_ENTRIES; i++)
gdt[i] = t->tls_array[i];
--
1.4.4.2

2007-12-06 19:02:13

by Glauber Costa

[permalink] [raw]
Subject: [PATCH 6/19] change write_idt_entry signature

this patch changes write_idt_entry signature. It now takes a gate_desc
instead of the a and b parameters. It will allow it to be later unified
between i386 and x86_64.

Signed-off-by: Glauber de Oliveira Costa <[email protected]>
---
arch/x86/kernel/paravirt_32.c | 2 +-
arch/x86/xen/enlighten.c | 5 ++---
include/asm-x86/desc_32.h | 9 +++++++--
include/asm-x86/paravirt.h | 9 +++++----
4 files changed, 15 insertions(+), 10 deletions(-)

diff --git a/arch/x86/kernel/paravirt_32.c b/arch/x86/kernel/paravirt_32.c
index f4e3a8e..9ed46da 100644
--- a/arch/x86/kernel/paravirt_32.c
+++ b/arch/x86/kernel/paravirt_32.c
@@ -381,7 +381,7 @@ struct pv_cpu_ops pv_cpu_ops = {
.load_tls = native_load_tls,
.write_ldt_entry = write_dt_entry,
.write_gdt_entry = write_dt_entry,
- .write_idt_entry = write_dt_entry,
+ .write_idt_entry = write_idt_entry,
.load_sp0 = native_load_sp0,

.irq_enable_syscall_ret = native_irq_enable_syscall_ret,
diff --git a/arch/x86/xen/enlighten.c b/arch/x86/xen/enlighten.c
index 53b097a..829a450 100644
--- a/arch/x86/xen/enlighten.c
+++ b/arch/x86/xen/enlighten.c
@@ -399,8 +399,7 @@ static DEFINE_PER_CPU(struct desc_ptr, idt_desc);

/* Set an IDT entry. If the entry is part of the current IDT, then
also update Xen. */
-static void xen_write_idt_entry(struct desc_struct *dt, int entrynum,
- u32 low, u32 high)
+static void xen_write_idt_entry(gate_desc *dt, int entrynum, gate_desc *g)
{
unsigned long p = (unsigned long)&dt[entrynum];
unsigned long start, end;
@@ -412,7 +411,7 @@ static void xen_write_idt_entry(struct desc_struct *dt, int entrynum,

xen_mc_flush();

- write_dt_entry(dt, entrynum, low, high);
+ native_write_idt_entry(dt, entrynum, g);

if (p >= start && (p + 8) <= end) {
struct trap_info info[2];
diff --git a/include/asm-x86/desc_32.h b/include/asm-x86/desc_32.h
index 77f1e5a..e77ed8c 100644
--- a/include/asm-x86/desc_32.h
+++ b/include/asm-x86/desc_32.h
@@ -70,9 +70,14 @@ static inline void pack_gate(gate_desc *gate,

#define write_ldt_entry(dt, entry, a, b) write_dt_entry(dt, entry, a, b)
#define write_gdt_entry(dt, entry, a, b) write_dt_entry(dt, entry, a, b)
-#define write_idt_entry(dt, entry, a, b) write_dt_entry(dt, entry, a, b)
+#define write_idt_entry(dt, entry, g) native_write_idt_entry(dt, entry, g)
#endif

+static inline void native_write_idt_entry(gate_desc *idt, int entry, gate_desc *gate)
+{
+ memcpy(&idt[entry], gate, sizeof(*gate));
+}
+
static inline void write_dt_entry(struct desc_struct *dt,
int entry, u32 entry_low, u32 entry_high)
{
@@ -142,7 +147,7 @@ static inline void _set_gate(int gate, unsigned int type, void *addr, unsigned s
{
gate_desc g;
pack_gate(&g, (unsigned long)addr, seg, type, 0);
- write_idt_entry(idt_table, gate, g.a, g.b);
+ write_idt_entry(idt_table, gate, &g);
}

static inline void __set_tss_desc(unsigned int cpu, unsigned int entry, const void *addr)
diff --git a/include/asm-x86/paravirt.h b/include/asm-x86/paravirt.h
index 0333fb6..d369b85 100644
--- a/include/asm-x86/paravirt.h
+++ b/include/asm-x86/paravirt.h
@@ -24,6 +24,7 @@ struct desc_ptr;
struct tss_struct;
struct mm_struct;
struct desc_struct;
+gate_desc;

/* general info */
struct pv_info {
@@ -99,8 +100,8 @@ struct pv_cpu_ops {
int entrynum, u32 low, u32 high);
void (*write_gdt_entry)(struct desc_struct *,
int entrynum, u32 low, u32 high);
- void (*write_idt_entry)(struct desc_struct *,
- int entrynum, u32 low, u32 high);
+ void (*write_idt_entry)(gate_desc *,
+ int entrynum, gate_desc *gate);
void (*load_sp0)(struct tss_struct *tss, struct thread_struct *t);

void (*set_iopl_mask)(unsigned mask);
@@ -667,9 +668,9 @@ static inline void write_gdt_entry(void *dt, int entry, u32 low, u32 high)
{
PVOP_VCALL4(pv_cpu_ops.write_gdt_entry, dt, entry, low, high);
}
-static inline void write_idt_entry(void *dt, int entry, u32 low, u32 high)
+static inline void write_idt_entry(gate_desc *dt, int entry, gate_desc *g)
{
- PVOP_VCALL4(pv_cpu_ops.write_idt_entry, dt, entry, low, high);
+ PVOP_VCALL4(pv_cpu_ops.write_idt_entry, dt, entry, g);
}
static inline void set_iopl_mask(unsigned mask)
{
--
1.4.4.2

2007-12-06 19:02:30

by Glauber Costa

[permalink] [raw]
Subject: [PATCH 2/19] unify struct desc_ptr

This patch unifies struct desc_ptr between i386 and x86_64.
They can be expressed in the exact same way in C code, only
having to change the name of one of them. As Xgt_desc_struct
is ugly and big, this is the one that goes away.

There's also a padding field in i386, but it is not really
needed in the C structure definition.

Signed-off-by: Glauber de Oliveira Costa <[email protected]>
---
arch/x86/kernel/asm-offsets_32.c | 5 ++---
arch/x86/kernel/cpu/common.c | 2 +-
arch/x86/kernel/doublefault_32.c | 2 +-
arch/x86/kernel/efi_32.c | 4 ++--
arch/x86/kernel/machine_kexec_32.c | 4 ++--
arch/x86/kernel/reboot_32.c | 2 +-
arch/x86/lguest/boot.c | 4 ++--
arch/x86/xen/enlighten.c | 10 +++++-----
drivers/kvm/svm.c | 2 +-
include/asm-x86/desc_32.h | 16 +++++-----------
include/asm-x86/lguest.h | 8 ++++----
include/asm-x86/paravirt.h | 18 +++++++++---------
include/asm-x86/processor_32.h | 2 +-
include/asm-x86/suspend_32.h | 4 ++--
14 files changed, 38 insertions(+), 45 deletions(-)

diff --git a/arch/x86/kernel/asm-offsets_32.c b/arch/x86/kernel/asm-offsets_32.c
index 4153135..afd8446 100644
--- a/arch/x86/kernel/asm-offsets_32.c
+++ b/arch/x86/kernel/asm-offsets_32.c
@@ -70,9 +70,8 @@ void foo(void)
OFFSET(TI_cpu, thread_info, cpu);
BLANK();

- OFFSET(GDS_size, Xgt_desc_struct, size);
- OFFSET(GDS_address, Xgt_desc_struct, address);
- OFFSET(GDS_pad, Xgt_desc_struct, pad);
+ OFFSET(GDS_size, desc_ptr, size);
+ OFFSET(GDS_address, desc_ptr, address);
BLANK();

OFFSET(PT_EBX, pt_regs, bx);
diff --git a/arch/x86/kernel/cpu/common.c b/arch/x86/kernel/cpu/common.c
index 0fe1c1d..a80847f 100644
--- a/arch/x86/kernel/cpu/common.c
+++ b/arch/x86/kernel/cpu/common.c
@@ -642,7 +642,7 @@ struct pt_regs * __devinit idle_regs(struct pt_regs *regs)
* it's on the real one. */
void switch_to_new_gdt(void)
{
- struct Xgt_desc_struct gdt_descr;
+ struct desc_ptr gdt_descr;

gdt_descr.address = (long)get_cpu_gdt_table(smp_processor_id());
gdt_descr.size = GDT_SIZE - 1;
diff --git a/arch/x86/kernel/doublefault_32.c b/arch/x86/kernel/doublefault_32.c
index cc19a3e..d16122a 100644
--- a/arch/x86/kernel/doublefault_32.c
+++ b/arch/x86/kernel/doublefault_32.c
@@ -17,7 +17,7 @@ static unsigned long doublefault_stack[DOUBLEFAULT_STACKSIZE];

static void doublefault_fn(void)
{
- struct Xgt_desc_struct gdt_desc = {0, 0};
+ struct desc_ptr gdt_desc = {0, 0};
unsigned long gdt, tss;

store_gdt(&gdt_desc);
diff --git a/arch/x86/kernel/efi_32.c b/arch/x86/kernel/efi_32.c
index e2be78f..863e892 100644
--- a/arch/x86/kernel/efi_32.c
+++ b/arch/x86/kernel/efi_32.c
@@ -69,7 +69,7 @@ static void efi_call_phys_prelog(void) __acquires(efi_rt_lock)
{
unsigned long cr4;
unsigned long temp;
- struct Xgt_desc_struct gdt_descr;
+ struct desc_ptr gdt_descr;

spin_lock(&efi_rt_lock);
local_irq_save(efi_rt_eflags);
@@ -111,7 +111,7 @@ static void efi_call_phys_prelog(void) __acquires(efi_rt_lock)
static void efi_call_phys_epilog(void) __releases(efi_rt_lock)
{
unsigned long cr4;
- struct Xgt_desc_struct gdt_descr;
+ struct desc_ptr gdt_descr;

gdt_descr.address = (unsigned long)get_cpu_gdt_table(0);
gdt_descr.size = GDT_SIZE - 1;
diff --git a/arch/x86/kernel/machine_kexec_32.c b/arch/x86/kernel/machine_kexec_32.c
index 11b935f..c1cfd60 100644
--- a/arch/x86/kernel/machine_kexec_32.c
+++ b/arch/x86/kernel/machine_kexec_32.c
@@ -32,7 +32,7 @@ static u32 kexec_pte1[1024] PAGE_ALIGNED;

static void set_idt(void *newidt, __u16 limit)
{
- struct Xgt_desc_struct curidt;
+ struct desc_ptr curidt;

/* ia32 supports unaliged loads & stores */
curidt.size = limit;
@@ -44,7 +44,7 @@ static void set_idt(void *newidt, __u16 limit)

static void set_gdt(void *newgdt, __u16 limit)
{
- struct Xgt_desc_struct curgdt;
+ struct desc_ptr curgdt;

/* ia32 supports unaligned loads & stores */
curgdt.size = limit;
diff --git a/arch/x86/kernel/reboot_32.c b/arch/x86/kernel/reboot_32.c
index bb1a0f8..c3376fa 100644
--- a/arch/x86/kernel/reboot_32.c
+++ b/arch/x86/kernel/reboot_32.c
@@ -161,7 +161,7 @@ real_mode_gdt_entries [3] =
0x000092000100ffffULL /* 16-bit real-mode 64k data at 0x00000100 */
};

-static struct Xgt_desc_struct
+static struct desc_ptr
real_mode_gdt = { sizeof (real_mode_gdt_entries) - 1, (long)real_mode_gdt_entries },
real_mode_idt = { 0x3ff, 0 },
no_idt = { 0, 0 };
diff --git a/arch/x86/lguest/boot.c b/arch/x86/lguest/boot.c
index c751e3c..aa0bdd5 100644
--- a/arch/x86/lguest/boot.c
+++ b/arch/x86/lguest/boot.c
@@ -229,7 +229,7 @@ static void lguest_write_idt_entry(struct desc_struct *dt,
/* Changing to a different IDT is very rare: we keep the IDT up-to-date every
* time it is written, so we can simply loop through all entries and tell the
* Host about them. */
-static void lguest_load_idt(const struct Xgt_desc_struct *desc)
+static void lguest_load_idt(const struct desc_ptr *desc)
{
unsigned int i;
struct desc_struct *idt = (void *)desc->address;
@@ -252,7 +252,7 @@ static void lguest_load_idt(const struct Xgt_desc_struct *desc)
* hypercall and use that repeatedly to load a new IDT. I don't think it
* really matters, but wouldn't it be nice if they were the same?
*/
-static void lguest_load_gdt(const struct Xgt_desc_struct *desc)
+static void lguest_load_gdt(const struct desc_ptr *desc)
{
BUG_ON((desc->size+1)/8 != GDT_ENTRIES);
hcall(LHCALL_LOAD_GDT, __pa(desc->address), GDT_ENTRIES, 0);
diff --git a/arch/x86/xen/enlighten.c b/arch/x86/xen/enlighten.c
index 7b16f2c..53b097a 100644
--- a/arch/x86/xen/enlighten.c
+++ b/arch/x86/xen/enlighten.c
@@ -295,7 +295,7 @@ static void xen_set_ldt(const void *addr, unsigned entries)
xen_mc_issue(PARAVIRT_LAZY_CPU);
}

-static void xen_load_gdt(const struct Xgt_desc_struct *dtr)
+static void xen_load_gdt(const struct desc_ptr *dtr)
{
unsigned long *frames;
unsigned long va = dtr->address;
@@ -395,7 +395,7 @@ static int cvt_gate_to_trap(int vector, u32 low, u32 high,
}

/* Locations of each CPU's IDT */
-static DEFINE_PER_CPU(struct Xgt_desc_struct, idt_desc);
+static DEFINE_PER_CPU(struct desc_ptr, idt_desc);

/* Set an IDT entry. If the entry is part of the current IDT, then
also update Xen. */
@@ -427,7 +427,7 @@ static void xen_write_idt_entry(struct desc_struct *dt, int entrynum,
preempt_enable();
}

-static void xen_convert_trap_info(const struct Xgt_desc_struct *desc,
+static void xen_convert_trap_info(const struct desc_ptr *desc,
struct trap_info *traps)
{
unsigned in, out, count;
@@ -446,7 +446,7 @@ static void xen_convert_trap_info(const struct Xgt_desc_struct *desc,

void xen_copy_trap_info(struct trap_info *traps)
{
- const struct Xgt_desc_struct *desc = &__get_cpu_var(idt_desc);
+ const struct desc_ptr *desc = &__get_cpu_var(idt_desc);

xen_convert_trap_info(desc, traps);
}
@@ -454,7 +454,7 @@ void xen_copy_trap_info(struct trap_info *traps)
/* Load a new IDT into Xen. In principle this can be per-CPU, so we
hold a spinlock to protect the static traps[] array (static because
it avoids allocation, and saves stack space). */
-static void xen_load_idt(const struct Xgt_desc_struct *desc)
+static void xen_load_idt(const struct desc_ptr *desc)
{
static DEFINE_SPINLOCK(lock);
static struct trap_info traps[257];
diff --git a/drivers/kvm/svm.c b/drivers/kvm/svm.c
index 4e04e49..ced4ac1 100644
--- a/drivers/kvm/svm.c
+++ b/drivers/kvm/svm.c
@@ -290,7 +290,7 @@ static void svm_hardware_enable(void *garbage)
#ifdef CONFIG_X86_64
struct desc_ptr gdt_descr;
#else
- struct Xgt_desc_struct gdt_descr;
+ struct desc_ptr gdt_descr;
#endif
struct desc_struct *gdt;
int me = raw_smp_processor_id();
diff --git a/include/asm-x86/desc_32.h b/include/asm-x86/desc_32.h
index c547403..bc5ca34 100644
--- a/include/asm-x86/desc_32.h
+++ b/include/asm-x86/desc_32.h
@@ -12,12 +12,6 @@

#include <asm/mmu.h>

-struct Xgt_desc_struct {
- unsigned short size;
- unsigned long address __attribute__((packed));
- unsigned short pad;
-} __attribute__ ((packed));
-
struct gdt_page
{
struct desc_struct gdt[GDT_ENTRIES];
@@ -29,7 +23,7 @@ static inline struct desc_struct *get_cpu_gdt_table(unsigned int cpu)
return per_cpu(gdt_page, cpu).gdt;
}

-extern struct Xgt_desc_struct idt_descr;
+extern struct desc_ptr idt_descr;
extern struct desc_struct idt_table[];
extern void set_intr_gate(unsigned int irq, void * addr);

@@ -107,22 +101,22 @@ static inline void native_load_tr_desc(void)
asm volatile("ltr %w0"::"q" (GDT_ENTRY_TSS*8));
}

-static inline void native_load_gdt(const struct Xgt_desc_struct *dtr)
+static inline void native_load_gdt(const struct desc_ptr *dtr)
{
asm volatile("lgdt %0"::"m" (*dtr));
}

-static inline void native_load_idt(const struct Xgt_desc_struct *dtr)
+static inline void native_load_idt(const struct desc_ptr *dtr)
{
asm volatile("lidt %0"::"m" (*dtr));
}

-static inline void native_store_gdt(struct Xgt_desc_struct *dtr)
+static inline void native_store_gdt(struct desc_ptr *dtr)
{
asm ("sgdt %0":"=m" (*dtr));
}

-static inline void native_store_idt(struct Xgt_desc_struct *dtr)
+static inline void native_store_idt(struct desc_ptr *dtr)
{
asm ("sidt %0":"=m" (*dtr));
}
diff --git a/include/asm-x86/lguest.h b/include/asm-x86/lguest.h
index ccd3384..d39f881 100644
--- a/include/asm-x86/lguest.h
+++ b/include/asm-x86/lguest.h
@@ -44,13 +44,13 @@ struct lguest_ro_state
{
/* Host information we need to restore when we switch back. */
u32 host_cr3;
- struct Xgt_desc_struct host_idt_desc;
- struct Xgt_desc_struct host_gdt_desc;
+ struct desc_ptr host_idt_desc;
+ struct desc_ptr host_gdt_desc;
u32 host_sp;

/* Fields which are used when guest is running. */
- struct Xgt_desc_struct guest_idt_desc;
- struct Xgt_desc_struct guest_gdt_desc;
+ struct desc_ptr guest_idt_desc;
+ struct desc_ptr guest_gdt_desc;
struct i386_hw_tss guest_tss;
struct desc_struct guest_idt[IDT_ENTRIES];
struct desc_struct guest_gdt[GDT_ENTRIES];
diff --git a/include/asm-x86/paravirt.h b/include/asm-x86/paravirt.h
index e95c2a6..0333fb6 100644
--- a/include/asm-x86/paravirt.h
+++ b/include/asm-x86/paravirt.h
@@ -20,7 +20,7 @@

struct page;
struct thread_struct;
-struct Xgt_desc_struct;
+struct desc_ptr;
struct tss_struct;
struct mm_struct;
struct desc_struct;
@@ -88,10 +88,10 @@ struct pv_cpu_ops {

/* Segment descriptor handling */
void (*load_tr_desc)(void);
- void (*load_gdt)(const struct Xgt_desc_struct *);
- void (*load_idt)(const struct Xgt_desc_struct *);
- void (*store_gdt)(struct Xgt_desc_struct *);
- void (*store_idt)(struct Xgt_desc_struct *);
+ void (*load_gdt)(const struct desc_ptr *);
+ void (*load_idt)(const struct desc_ptr *);
+ void (*store_gdt)(struct desc_ptr *);
+ void (*store_idt)(struct desc_ptr *);
void (*set_ldt)(const void *desc, unsigned entries);
unsigned long (*store_tr)(void);
void (*load_tls)(struct thread_struct *t, unsigned int cpu);
@@ -630,11 +630,11 @@ static inline void load_TR_desc(void)
{
PVOP_VCALL0(pv_cpu_ops.load_tr_desc);
}
-static inline void load_gdt(const struct Xgt_desc_struct *dtr)
+static inline void load_gdt(const struct desc_ptr *dtr)
{
PVOP_VCALL1(pv_cpu_ops.load_gdt, dtr);
}
-static inline void load_idt(const struct Xgt_desc_struct *dtr)
+static inline void load_idt(const struct desc_ptr *dtr)
{
PVOP_VCALL1(pv_cpu_ops.load_idt, dtr);
}
@@ -642,11 +642,11 @@ static inline void set_ldt(const void *addr, unsigned entries)
{
PVOP_VCALL2(pv_cpu_ops.set_ldt, addr, entries);
}
-static inline void store_gdt(struct Xgt_desc_struct *dtr)
+static inline void store_gdt(struct desc_ptr *dtr)
{
PVOP_VCALL1(pv_cpu_ops.store_gdt, dtr);
}
-static inline void store_idt(struct Xgt_desc_struct *dtr)
+static inline void store_idt(struct desc_ptr *dtr)
{
PVOP_VCALL1(pv_cpu_ops.store_idt, dtr);
}
diff --git a/include/asm-x86/processor_32.h b/include/asm-x86/processor_32.h
index f1fc049..a8aedb2 100644
--- a/include/asm-x86/processor_32.h
+++ b/include/asm-x86/processor_32.h
@@ -704,7 +704,7 @@ extern void enable_sep_cpu(void);
extern int sysenter_setup(void);

/* Defined in head.S */
-extern struct Xgt_desc_struct early_gdt_descr;
+extern struct desc_ptr early_gdt_descr;

extern void cpu_set_gdt(int);
extern void switch_to_new_gdt(void);
diff --git a/include/asm-x86/suspend_32.h b/include/asm-x86/suspend_32.h
index a252073..1bbda3a 100644
--- a/include/asm-x86/suspend_32.h
+++ b/include/asm-x86/suspend_32.h
@@ -12,8 +12,8 @@ static inline int arch_prepare_suspend(void) { return 0; }
struct saved_context {
u16 es, fs, gs, ss;
unsigned long cr0, cr2, cr3, cr4;
- struct Xgt_desc_struct gdt;
- struct Xgt_desc_struct idt;
+ struct desc_ptr gdt;
+ struct desc_ptr idt;
u16 ldt;
u16 tss;
unsigned long tr;
--
1.4.4.2

2007-12-06 19:02:48

by Glauber Costa

[permalink] [raw]
Subject: [PATCH 5/19] introduce gate_desc type.

To account for the differences in gate descriptor in i386 and x86_64
a gate_desc type is introduced.

Signed-off-by: Glauber de Oliveira Costa <[email protected]>
---
arch/x86/kernel/traps_32.c | 3 ++-
include/asm-x86/desc_32.h | 15 ++++++++-------
include/asm-x86/desc_64.h | 4 ++--
include/asm-x86/desc_defs.h | 8 +++++++-
4 files changed, 19 insertions(+), 11 deletions(-)

diff --git a/arch/x86/kernel/traps_32.c b/arch/x86/kernel/traps_32.c
index 94c5aea..6b03d88 100644
--- a/arch/x86/kernel/traps_32.c
+++ b/arch/x86/kernel/traps_32.c
@@ -76,7 +76,8 @@ 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 }}}, };
+gate_desc idt_table[256]
+ __attribute__((__section__(".data.idt"))) = { {{{ 0, 0 }}}, };

asmlinkage void divide_error(void);
asmlinkage void debug(void);
diff --git a/include/asm-x86/desc_32.h b/include/asm-x86/desc_32.h
index bc5ca34..77f1e5a 100644
--- a/include/asm-x86/desc_32.h
+++ b/include/asm-x86/desc_32.h
@@ -3,6 +3,7 @@

#include <asm/ldt.h>
#include <asm/segment.h>
+#include <asm/desc_defs.h>

#ifndef __ASSEMBLY__

@@ -24,7 +25,7 @@ static inline struct desc_struct *get_cpu_gdt_table(unsigned int cpu)
}

extern struct desc_ptr idt_descr;
-extern struct desc_struct idt_table[];
+extern gate_desc idt_table[];
extern void set_intr_gate(unsigned int irq, void * addr);

static inline void pack_descriptor(__u32 *a, __u32 *b,
@@ -35,11 +36,11 @@ static inline void pack_descriptor(__u32 *a, __u32 *b,
(limit & 0x000f0000) | ((type & 0xff) << 8) | ((flags & 0xf) << 20);
}

-static inline void pack_gate(__u32 *a, __u32 *b,
+static inline void pack_gate(gate_desc *gate,
unsigned long base, unsigned short seg, unsigned char type, unsigned char flags)
{
- *a = (seg << 16) | (base & 0xffff);
- *b = (base & 0xffff0000) | ((type & 0xff) << 8) | (flags & 0xff);
+ gate->a = (seg << 16) | (base & 0xffff);
+ gate->b = (base & 0xffff0000) | ((type & 0xff) << 8) | (flags & 0xff);
}

#define DESCTYPE_LDT 0x82 /* present, system, DPL-0, LDT */
@@ -139,9 +140,9 @@ static inline void native_load_tls(struct thread_struct *t, unsigned int cpu)

static inline void _set_gate(int gate, unsigned int type, void *addr, unsigned short seg)
{
- __u32 a, b;
- pack_gate(&a, &b, (unsigned long)addr, seg, type, 0);
- write_idt_entry(idt_table, gate, a, b);
+ gate_desc g;
+ pack_gate(&g, (unsigned long)addr, seg, type, 0);
+ write_idt_entry(idt_table, gate, g.a, g.b);
}

static inline void __set_tss_desc(unsigned int cpu, unsigned int entry, const void *addr)
diff --git a/include/asm-x86/desc_64.h b/include/asm-x86/desc_64.h
index 660cc84..ffc6c06 100644
--- a/include/asm-x86/desc_64.h
+++ b/include/asm-x86/desc_64.h
@@ -30,7 +30,7 @@ static inline unsigned long __store_tr(void)

#define store_tr(tr) (tr) = __store_tr()

-extern struct gate_struct idt_table[];
+extern gate_desc idt_table[];
extern struct desc_ptr cpu_gdt_descr[];

static inline void write_ldt_entry(struct desc_struct *ldt,
@@ -58,7 +58,7 @@ static inline void store_gdt(struct desc_ptr *ptr)
static inline void _set_gate(void *adr, unsigned type, unsigned long func,
unsigned dpl, unsigned ist)
{
- struct gate_struct s;
+ gate_desc s;

s.offset_low = PTR_LOW(func);
s.segment = __KERNEL_CS;
diff --git a/include/asm-x86/desc_defs.h b/include/asm-x86/desc_defs.h
index b3db064..e502549 100644
--- a/include/asm-x86/desc_defs.h
+++ b/include/asm-x86/desc_defs.h
@@ -42,7 +42,7 @@ enum {
};

// 16byte gate
-struct gate_struct {
+struct gate_struct64 {
u16 offset_low;
u16 segment;
unsigned ist : 3, zero0 : 5, type : 5, dpl : 2, p : 1;
@@ -70,6 +70,12 @@ struct ldttss_desc {
u32 zero1;
} __attribute__((packed));

+#ifdef CONFIG_X86_64
+typedef struct gate_struct64 gate_desc;
+#else
+typedef struct desc_struct gate_desc;
+#endif
+
struct desc_ptr {
unsigned short size;
unsigned long address;
--
1.4.4.2

2007-12-06 19:03:08

by Glauber Costa

[permalink] [raw]
Subject: [PATCH 7/19] introduce ldt_desc type.

this patch introduces ldt_desc type to account for the differences
in the ldt descriptor in x86_64 and i386

Signed-off-by: Glauber de Oliveira Costa <[email protected]>
---
include/asm-x86/desc_64.h | 2 +-
include/asm-x86/desc_defs.h | 4 +++-
2 files changed, 4 insertions(+), 2 deletions(-)

diff --git a/include/asm-x86/desc_64.h b/include/asm-x86/desc_64.h
index ffc6c06..8fe1b4c 100644
--- a/include/asm-x86/desc_64.h
+++ b/include/asm-x86/desc_64.h
@@ -113,7 +113,7 @@ static inline void store_idt(struct desc_ptr *dtr)
static inline void set_tssldt_descriptor(void *ptr, unsigned long tss,
unsigned type, unsigned size)
{
- struct ldttss_desc d;
+ struct ldttss_desc64 d;

memset(&d, 0, sizeof(d));
d.limit0 = size & 0xFFFF;
diff --git a/include/asm-x86/desc_defs.h b/include/asm-x86/desc_defs.h
index e502549..3a562d1 100644
--- a/include/asm-x86/desc_defs.h
+++ b/include/asm-x86/desc_defs.h
@@ -61,7 +61,7 @@ enum {
};

// LDT or TSS descriptor in the GDT. 16 bytes.
-struct ldttss_desc {
+struct ldttss_desc64 {
u16 limit0;
u16 base0;
unsigned base1 : 8, type : 5, dpl : 2, p : 1;
@@ -72,8 +72,10 @@ struct ldttss_desc {

#ifdef CONFIG_X86_64
typedef struct gate_struct64 gate_desc;
+typedef struct ldttss_desc64 ldt_desc;
#else
typedef struct desc_struct gate_desc;
+typedef struct desc_struct ldt_desc;
#endif

struct desc_ptr {
--
1.4.4.2

2007-12-06 19:03:28

by Glauber Costa

[permalink] [raw]
Subject: [PATCH 9/19] introduce fill_ldt

This patch introduces fill_ldt(), which populates a ldt descriptor
from a user_desc in once, instead of relying in the LDT_entry_a and
LDT_entry_b macros

Signed-off-by: Glauber de Oliveira Costa <[email protected]>
---
arch/x86/kernel/ldt.c | 3 +--
arch/x86/kernel/process_64.c | 3 +--
arch/x86/kernel/tls.c | 7 +++----
include/asm-x86/desc_32.h | 15 ---------------
include/asm-x86/desc_64.h | 17 -----------------
include/asm-x86/ldt.h | 19 +++++++++++++++++++
6 files changed, 24 insertions(+), 40 deletions(-)

diff --git a/arch/x86/kernel/ldt.c b/arch/x86/kernel/ldt.c
index 7eb0c8a..3e872b4 100644
--- a/arch/x86/kernel/ldt.c
+++ b/arch/x86/kernel/ldt.c
@@ -223,8 +223,7 @@ static int write_ldt(void __user *ptr, unsigned long bytecount, int oldmode)
}
}

- ldt.a = LDT_entry_a(&ldt_info);
- ldt.b = LDT_entry_b(&ldt_info);
+ fill_ldt(&ldt, &ldt_info);
if (oldmode)
ldt.avl = 0;

diff --git a/arch/x86/kernel/process_64.c b/arch/x86/kernel/process_64.c
index 9e99cb7..8b6d492 100644
--- a/arch/x86/kernel/process_64.c
+++ b/arch/x86/kernel/process_64.c
@@ -439,8 +439,7 @@ static inline void set_32bit_tls(struct task_struct *t, int tls, u32 addr)
};
struct desc_struct *desc = (void *)t->thread.tls_array;
desc += tls;
- desc->a = LDT_entry_a(&ud);
- desc->b = LDT_entry_b(&ud);
+ fill_ldt(desc, &ud);
}

static inline u32 read_32bit_tls(struct task_struct *t, int tls)
diff --git a/arch/x86/kernel/tls.c b/arch/x86/kernel/tls.c
index 67a3776..74d2b65 100644
--- a/arch/x86/kernel/tls.c
+++ b/arch/x86/kernel/tls.c
@@ -67,10 +67,9 @@ int do_set_thread_area(struct task_struct *p, int idx,
if (LDT_empty(&info)) {
desc[0] = 0;
desc[1] = 0;
- } else {
- desc[0] = LDT_entry_a(&info);
- desc[1] = LDT_entry_b(&info);
- }
+ } else
+ fill_ldt((struct desc_struct *)desc, &info);
+
if (t == &current->thread)
load_TLS(t, cpu);

diff --git a/include/asm-x86/desc_32.h b/include/asm-x86/desc_32.h
index e77ed8c..3653c9f 100644
--- a/include/asm-x86/desc_32.h
+++ b/include/asm-x86/desc_32.h
@@ -162,21 +162,6 @@ static inline void __set_tss_desc(unsigned int cpu, unsigned int entry, const vo

#define set_tss_desc(cpu,addr) __set_tss_desc(cpu, GDT_ENTRY_TSS, addr)

-#define LDT_entry_a(info) \
- ((((info)->base_addr & 0x0000ffff) << 16) | ((info)->limit & 0x0ffff))
-
-#define LDT_entry_b(info) \
- (((info)->base_addr & 0xff000000) | \
- (((info)->base_addr & 0x00ff0000) >> 16) | \
- ((info)->limit & 0xf0000) | \
- (((info)->read_exec_only ^ 1) << 9) | \
- ((info)->contents << 10) | \
- (((info)->seg_not_present ^ 1) << 15) | \
- ((info)->seg_32bit << 22) | \
- ((info)->limit_in_pages << 23) | \
- ((info)->useable << 20) | \
- 0x7000)
-
#define LDT_empty(info) (\
(info)->base_addr == 0 && \
(info)->limit == 0 && \
diff --git a/include/asm-x86/desc_64.h b/include/asm-x86/desc_64.h
index 8fe1b4c..e0aa4bc 100644
--- a/include/asm-x86/desc_64.h
+++ b/include/asm-x86/desc_64.h
@@ -147,23 +147,6 @@ static inline void set_ldt_desc(unsigned cpu, void *addr, int size)
(unsigned long)addr, DESC_LDT, size * 8 - 1);
}

-#define LDT_entry_a(info) \
- ((((info)->base_addr & 0x0000ffff) << 16) | ((info)->limit & 0x0ffff))
-/* Don't allow setting of the lm bit. It is useless anyways because
- 64bit system calls require __USER_CS. */
-#define LDT_entry_b(info) \
- (((info)->base_addr & 0xff000000) | \
- (((info)->base_addr & 0x00ff0000) >> 16) | \
- ((info)->limit & 0xf0000) | \
- (((info)->read_exec_only ^ 1) << 9) | \
- ((info)->contents << 10) | \
- (((info)->seg_not_present ^ 1) << 15) | \
- ((info)->seg_32bit << 22) | \
- ((info)->limit_in_pages << 23) | \
- ((info)->useable << 20) | \
- /* ((info)->lm << 21) | */ \
- 0x7000)
-
#define LDT_empty(info) (\
(info)->base_addr == 0 && \
(info)->limit == 0 && \
diff --git a/include/asm-x86/ldt.h b/include/asm-x86/ldt.h
index 20c5972..5f00d02 100644
--- a/include/asm-x86/ldt.h
+++ b/include/asm-x86/ldt.h
@@ -5,6 +5,7 @@
*/
#ifndef _ASM_X86_LDT_H
#define _ASM_X86_LDT_H
+#include <asm/desc_defs.h>

/* Maximum number of LDT entries supported. */
#define LDT_ENTRIES 8192
@@ -32,6 +33,24 @@ struct user_desc {
#endif
};

+static inline void fill_ldt(struct desc_struct *desc, struct user_desc *info)
+{
+ desc->limit0 = info->limit & 0x0ffff;
+ desc->base0 = info->base_addr & 0x0000ffff;
+
+ desc->base1 = info->base_addr & 0x00ff0000;
+ desc->type = (info->read_exec_only ^ 1) << 1;
+ desc->type |= info->contents << 2;
+ desc->s = 1;
+ desc->dpl = 0x3;
+ desc->p = info->seg_not_present ^ 1;
+ desc->limit = info->limit & 0xf0000;
+ desc->avl = info->useable;
+ desc->d = info->seg_32bit;
+ desc->g = info->limit_in_pages;
+ desc->base2 = info->base_addr & 0xff000000;
+}
+
#define MODIFY_LDT_CONTENTS_DATA 0
#define MODIFY_LDT_CONTENTS_STACK 1
#define MODIFY_LDT_CONTENTS_CODE 2
--
1.4.4.2

2007-12-06 19:03:43

by Glauber Costa

[permalink] [raw]
Subject: [PATCH 8/19] modify write_ldt function

This patch modifies the write_ldt() function to make use
of the new struct desc_struct instead of entry_1 and entry_2
entries

Signed-off-by: Glauber de Oliveira Costa <[email protected]>
---
arch/x86/kernel/ldt.c | 15 +++++++--------
1 files changed, 7 insertions(+), 8 deletions(-)

diff --git a/arch/x86/kernel/ldt.c b/arch/x86/kernel/ldt.c
index a8cdca3..7eb0c8a 100644
--- a/arch/x86/kernel/ldt.c
+++ b/arch/x86/kernel/ldt.c
@@ -186,7 +186,7 @@ static int read_default_ldt(void __user *ptr, unsigned long bytecount)
static int write_ldt(void __user *ptr, unsigned long bytecount, int oldmode)
{
struct mm_struct *mm = current->mm;
- __u32 entry_1, entry_2;
+ struct desc_struct ldt;
int error;
struct user_desc ldt_info;

@@ -218,21 +218,20 @@ static int write_ldt(void __user *ptr, unsigned long bytecount, int oldmode)
/* Allow LDTs to be cleared by the user. */
if (ldt_info.base_addr == 0 && ldt_info.limit == 0) {
if (oldmode || LDT_empty(&ldt_info)) {
- entry_1 = 0;
- entry_2 = 0;
+ memset(&ldt, 0, sizeof(ldt));
goto install;
}
}

- entry_1 = LDT_entry_a(&ldt_info);
- entry_2 = LDT_entry_b(&ldt_info);
+ ldt.a = LDT_entry_a(&ldt_info);
+ ldt.b = LDT_entry_b(&ldt_info);
if (oldmode)
- entry_2 &= ~(1 << 20);
+ ldt.avl = 0;

/* Install the new entry ... */
install:
- write_ldt_entry(mm->context.ldt, ldt_info.entry_number, entry_1,
- entry_2);
+ write_ldt_entry(mm->context.ldt, ldt_info.entry_number,
+ ldt.a, ldt.b);
error = 0;

out_unlock:
--
1.4.4.2

2007-12-06 19:04:03

by Glauber Costa

[permalink] [raw]
Subject: [PATCH 10/19] change write_gdt_entry signature.

This patch changes the write_gdt_entry function signature.
Instead of the old "a" and "b" parameters, it now receives
a pointer to a desc_struct, and the size of the entry being
handled. This is because x86_64 can have some 16-byte entries
as well as 8-byte ones.

Signed-off-by: Glauber de Oliveira Costa <[email protected]>
---
arch/x86/kernel/paravirt_32.c | 4 ++--
arch/x86/kernel/smpcommon_32.c | 7 ++++---
arch/x86/xen/enlighten.c | 5 ++---
include/asm-x86/desc_32.h | 29 +++++++++++++++--------------
include/asm-x86/paravirt.h | 9 ++++++---
5 files changed, 29 insertions(+), 25 deletions(-)

diff --git a/arch/x86/kernel/paravirt_32.c b/arch/x86/kernel/paravirt_32.c
index 9ed46da..edff853 100644
--- a/arch/x86/kernel/paravirt_32.c
+++ b/arch/x86/kernel/paravirt_32.c
@@ -379,8 +379,8 @@ struct pv_cpu_ops pv_cpu_ops = {
.store_idt = native_store_idt,
.store_tr = native_store_tr,
.load_tls = native_load_tls,
- .write_ldt_entry = write_dt_entry,
- .write_gdt_entry = write_dt_entry,
+ .write_ldt_entry = write_ldt_entry,
+ .write_gdt_entry = write_gdt_entry,
.write_idt_entry = write_idt_entry,
.load_sp0 = native_load_sp0,

diff --git a/arch/x86/kernel/smpcommon_32.c b/arch/x86/kernel/smpcommon_32.c
index bbfe85a..a6f9b41 100644
--- a/arch/x86/kernel/smpcommon_32.c
+++ b/arch/x86/kernel/smpcommon_32.c
@@ -14,10 +14,11 @@ __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(&gdt[GDT_ENTRY_PERCPU],
__per_cpu_offset[cpu], 0xFFFFF,
- 0x80 | DESCTYPE_S | 0x2, 0x8);
+ 0x80 | 0x2, 0x8);
+
+ gdt[GDT_ENTRY_PERCPU].s = 1;

per_cpu(this_cpu_off, cpu) = __per_cpu_offset[cpu];
per_cpu(cpu_number, cpu) = cpu;
diff --git a/arch/x86/xen/enlighten.c b/arch/x86/xen/enlighten.c
index 829a450..a552103 100644
--- a/arch/x86/xen/enlighten.c
+++ b/arch/x86/xen/enlighten.c
@@ -474,7 +474,7 @@ static void xen_load_idt(const struct desc_ptr *desc)
/* Write a GDT descriptor entry. Ignore LDT descriptors, since
they're handled differently. */
static void xen_write_gdt_entry(struct desc_struct *dt, int entry,
- u32 low, u32 high)
+ void *desc, int size)
{
preempt_disable();

@@ -486,10 +486,9 @@ static void xen_write_gdt_entry(struct desc_struct *dt, int entry,

default: {
xmaddr_t maddr = virt_to_machine(&dt[entry]);
- u64 desc = (u64)high << 32 | low;

xen_mc_flush();
- if (HYPERVISOR_update_descriptor(maddr.maddr, desc))
+ if (HYPERVISOR_update_descriptor(maddr.maddr, *(u64 *)desc))
BUG();
}

diff --git a/include/asm-x86/desc_32.h b/include/asm-x86/desc_32.h
index 3653c9f..622b0e7 100644
--- a/include/asm-x86/desc_32.h
+++ b/include/asm-x86/desc_32.h
@@ -28,11 +28,11 @@ extern struct desc_ptr idt_descr;
extern gate_desc idt_table[];
extern void set_intr_gate(unsigned int irq, void * addr);

-static inline void pack_descriptor(__u32 *a, __u32 *b,
+static inline void pack_descriptor(struct desc_struct *desc,
unsigned long base, unsigned long limit, unsigned char type, unsigned char flags)
{
- *a = ((base & 0xffff) << 16) | (limit & 0xffff);
- *b = (base & 0xff000000) | ((base & 0xff0000) >> 16) |
+ desc->a = ((base & 0xffff) << 16) | (limit & 0xffff);
+ desc->b = (base & 0xff000000) | ((base & 0xff0000) >> 16) |
(limit & 0x000f0000) | ((type & 0xff) << 8) | ((flags & 0xf) << 20);
}

@@ -69,7 +69,8 @@ static inline void pack_gate(gate_desc *gate,
#define set_ldt native_set_ldt

#define write_ldt_entry(dt, entry, a, b) write_dt_entry(dt, entry, a, b)
-#define write_gdt_entry(dt, entry, a, b) write_dt_entry(dt, entry, a, b)
+#define write_gdt_entry(dt, entry, desc, size) \
+ native_write_gdt_entry(dt, entry, desc, size)
#define write_idt_entry(dt, entry, g) native_write_idt_entry(dt, entry, g)
#endif

@@ -78,11 +79,10 @@ static inline void native_write_idt_entry(gate_desc *idt, int entry, gate_desc *
memcpy(&idt[entry], gate, sizeof(*gate));
}

-static inline void write_dt_entry(struct desc_struct *dt,
- int entry, u32 entry_low, u32 entry_high)
+static inline void native_write_gdt_entry(struct desc_struct *gdt, int entry,
+ void *desc, int size)
{
- dt[entry].a = entry_low;
- dt[entry].b = entry_high;
+ memcpy(&gdt[entry], desc, size);
}

static inline void native_set_ldt(const void *addr, unsigned int entries)
@@ -91,12 +91,13 @@ static inline void native_set_ldt(const void *addr, unsigned int entries)
__asm__ __volatile__("lldt %w0"::"q" (0));
else {
unsigned cpu = smp_processor_id();
- __u32 a, b;
+ ldt_desc ldt;

- pack_descriptor(&a, &b, (unsigned long)addr,
+ pack_descriptor(&ldt, (unsigned long)addr,
entries * sizeof(struct desc_struct) - 1,
DESCTYPE_LDT, 0);
- write_gdt_entry(get_cpu_gdt_table(cpu), GDT_ENTRY_LDT, a, b);
+ write_gdt_entry(get_cpu_gdt_table(cpu), GDT_ENTRY_LDT,
+ &ldt, sizeof(ldt));
__asm__ __volatile__("lldt %w0"::"q" (GDT_ENTRY_LDT*8));
}
}
@@ -152,11 +153,11 @@ static inline void _set_gate(int gate, unsigned int type, void *addr, unsigned s

static inline void __set_tss_desc(unsigned int cpu, unsigned int entry, const void *addr)
{
- __u32 a, b;
- pack_descriptor(&a, &b, (unsigned long)addr,
+ tss_desc tss;
+ pack_descriptor(&tss, (unsigned long)addr,
offsetof(struct tss_struct, __cacheline_filler) - 1,
DESCTYPE_TSS, 0);
- write_gdt_entry(get_cpu_gdt_table(cpu), entry, a, b);
+ write_gdt_entry(get_cpu_gdt_table(cpu), entry, &tss, sizeof(tss));
}


diff --git a/include/asm-x86/paravirt.h b/include/asm-x86/paravirt.h
index d369b85..a3e22b7 100644
--- a/include/asm-x86/paravirt.h
+++ b/include/asm-x86/paravirt.h
@@ -99,7 +99,7 @@ struct pv_cpu_ops {
void (*write_ldt_entry)(struct desc_struct *,
int entrynum, u32 low, u32 high);
void (*write_gdt_entry)(struct desc_struct *,
- int entrynum, u32 low, u32 high);
+ int entrynum, void *desc, int size);
void (*write_idt_entry)(gate_desc *,
int entrynum, gate_desc *gate);
void (*load_sp0)(struct tss_struct *tss, struct thread_struct *t);
@@ -664,10 +664,13 @@ static inline void write_ldt_entry(void *dt, int entry, u32 low, u32 high)
{
PVOP_VCALL4(pv_cpu_ops.write_ldt_entry, dt, entry, low, high);
}
-static inline void write_gdt_entry(void *dt, int entry, u32 low, u32 high)
+
+static inline void write_gdt_entry(struct desc_struct *dt, int entry,
+ void *desc, int size)
{
- PVOP_VCALL4(pv_cpu_ops.write_gdt_entry, dt, entry, low, high);
+ PVOP_VCALL4(pv_cpu_ops.write_gdt_entry, dt, entry, desc, size);
}
+
static inline void write_idt_entry(gate_desc *dt, int entry, gate_desc *g)
{
PVOP_VCALL4(pv_cpu_ops.write_idt_entry, dt, entry, g);
--
1.4.4.2

2007-12-06 19:04:29

by Glauber Costa

[permalink] [raw]
Subject: [PATCH 11/19] change write_ldt_entry signature

this patch changes the signature of write_ldt_entry.

Signed-off-by: Glauber de Oliveira Costa <[email protected]>
---
arch/x86/kernel/ldt.c | 3 +--
arch/x86/xen/enlighten.c | 4 ++--
include/asm-x86/desc_32.h | 9 ++++++++-
include/asm-x86/desc_64.h | 7 ++-----
include/asm-x86/paravirt.h | 10 ++++++----
5 files changed, 19 insertions(+), 14 deletions(-)

diff --git a/arch/x86/kernel/ldt.c b/arch/x86/kernel/ldt.c
index 3e872b4..b8ef462 100644
--- a/arch/x86/kernel/ldt.c
+++ b/arch/x86/kernel/ldt.c
@@ -229,8 +229,7 @@ static int write_ldt(void __user *ptr, unsigned long bytecount, int oldmode)

/* Install the new entry ... */
install:
- write_ldt_entry(mm->context.ldt, ldt_info.entry_number,
- ldt.a, ldt.b);
+ write_ldt_entry(mm->context.ldt, ldt_info.entry_number, &ldt);
error = 0;

out_unlock:
diff --git a/arch/x86/xen/enlighten.c b/arch/x86/xen/enlighten.c
index a552103..16223b6 100644
--- a/arch/x86/xen/enlighten.c
+++ b/arch/x86/xen/enlighten.c
@@ -357,11 +357,11 @@ static void xen_load_tls(struct thread_struct *t, unsigned int cpu)
}

static void xen_write_ldt_entry(struct desc_struct *dt, int entrynum,
- u32 low, u32 high)
+ void *ptr)
{
unsigned long lp = (unsigned long)&dt[entrynum];
xmaddr_t mach_lp = virt_to_machine(lp);
- u64 entry = (u64)high << 32 | low;
+ u64 entry = *(u64 *)ptr;

preempt_disable();

diff --git a/include/asm-x86/desc_32.h b/include/asm-x86/desc_32.h
index 622b0e7..46fe80a 100644
--- a/include/asm-x86/desc_32.h
+++ b/include/asm-x86/desc_32.h
@@ -68,12 +68,19 @@ static inline void pack_gate(gate_desc *gate,
#define load_TLS(t, cpu) native_load_tls(t, cpu)
#define set_ldt native_set_ldt

-#define write_ldt_entry(dt, entry, a, b) write_dt_entry(dt, entry, a, b)
+#define write_ldt_entry(dt, entry, desc) \
+ native_write_ldt_entry(dt, entry, desc)
#define write_gdt_entry(dt, entry, desc, size) \
native_write_gdt_entry(dt, entry, desc, size)
#define write_idt_entry(dt, entry, g) native_write_idt_entry(dt, entry, g)
#endif

+static inline void native_write_ldt_entry(struct desc_struct *ldt, int entry,
+ void *desc)
+{
+ memcpy(&ldt[entry], desc, size);
+}
+
static inline void native_write_idt_entry(gate_desc *idt, int entry, gate_desc *gate)
{
memcpy(&idt[entry], gate, sizeof(*gate));
diff --git a/include/asm-x86/desc_64.h b/include/asm-x86/desc_64.h
index e0aa4bc..3cd5f10 100644
--- a/include/asm-x86/desc_64.h
+++ b/include/asm-x86/desc_64.h
@@ -34,12 +34,9 @@ extern gate_desc idt_table[];
extern struct desc_ptr cpu_gdt_descr[];

static inline void write_ldt_entry(struct desc_struct *ldt,
- int entry, u32 entry_low, u32 entry_high)
+ int entry, void *ptr)
{
- __u32 *lp = (__u32 *)((entry << 3) + (char *)ldt);
-
- lp[0] = entry_low;
- lp[1] = entry_high;
+ memcpy(&ldt[entry], ptr, 8);
}

/* the cpu gdt accessor */
diff --git a/include/asm-x86/paravirt.h b/include/asm-x86/paravirt.h
index a3e22b7..b855264 100644
--- a/include/asm-x86/paravirt.h
+++ b/include/asm-x86/paravirt.h
@@ -96,8 +96,8 @@ struct pv_cpu_ops {
void (*set_ldt)(const void *desc, unsigned entries);
unsigned long (*store_tr)(void);
void (*load_tls)(struct thread_struct *t, unsigned int cpu);
- void (*write_ldt_entry)(struct desc_struct *,
- int entrynum, u32 low, u32 high);
+ void (*write_ldt_entry)(struct desc_struct *ldt, int entrynum,
+ void *desc);
void (*write_gdt_entry)(struct desc_struct *,
int entrynum, void *desc, int size);
void (*write_idt_entry)(gate_desc *,
@@ -660,9 +660,11 @@ static inline void load_TLS(struct thread_struct *t, unsigned cpu)
{
PVOP_VCALL2(pv_cpu_ops.load_tls, t, cpu);
}
-static inline void write_ldt_entry(void *dt, int entry, u32 low, u32 high)
+
+static inline void write_ldt_entry(struct desc_struct *dt, int entry,
+ void *desc)
{
- PVOP_VCALL4(pv_cpu_ops.write_ldt_entry, dt, entry, low, high);
+ PVOP_VCALL3(pv_cpu_ops.write_ldt_entry, dt, entry, desc);
}

static inline void write_gdt_entry(struct desc_struct *dt, int entry,
--
1.4.4.2

2007-12-06 19:04:44

by Glauber Costa

[permalink] [raw]
Subject: [PATCH 12/19] move constants to desc_defs.h

this patch moves constant definitions regarding descriptor types
from desc_32.h to desc_defs.h. The change from defines to enum
to comply with previous versions in desc_defs.h

Signed-off-by: Glauber de Oliveira Costa <[email protected]>
---
include/asm-x86/desc_32.h | 8 --------
include/asm-x86/desc_defs.h | 7 +++++++
2 files changed, 7 insertions(+), 8 deletions(-)

diff --git a/include/asm-x86/desc_32.h b/include/asm-x86/desc_32.h
index 46fe80a..5d1e848 100644
--- a/include/asm-x86/desc_32.h
+++ b/include/asm-x86/desc_32.h
@@ -43,14 +43,6 @@ static inline void pack_gate(gate_desc *gate,
gate->b = (base & 0xffff0000) | ((type & 0xff) << 8) | (flags & 0xff);
}

-#define DESCTYPE_LDT 0x82 /* present, system, DPL-0, LDT */
-#define DESCTYPE_TSS 0x89 /* present, system, DPL-0, 32-bit TSS */
-#define DESCTYPE_TASK 0x85 /* present, system, DPL-0, task gate */
-#define DESCTYPE_INT 0x8e /* present, system, DPL-0, interrupt gate */
-#define DESCTYPE_TRAP 0x8f /* present, system, DPL-0, trap gate */
-#define DESCTYPE_DPL3 0x60 /* DPL-3 */
-#define DESCTYPE_S 0x10 /* !system */
-
#ifdef CONFIG_PARAVIRT
#include <asm/paravirt.h>
#else
diff --git a/include/asm-x86/desc_defs.h b/include/asm-x86/desc_defs.h
index 3a562d1..3bfb7d9 100644
--- a/include/asm-x86/desc_defs.h
+++ b/include/asm-x86/desc_defs.h
@@ -58,6 +58,13 @@ struct gate_struct64 {
enum {
DESC_TSS = 0x9,
DESC_LDT = 0x2,
+ DESCTYPE_LDT = 0x82, /* present, system, DPL-0, LDT */
+ DESCTYPE_TSS = 0x89, /* present, system, DPL-0, 32-bit TSS */
+ DESCTYPE_TASK = 0x85, /* present, system, DPL-0, task gate */
+ DESCTYPE_INT = 0x8e, /* present, system, DPL-0, interrupt gate */
+ DESCTYPE_TRAP = 0x8f, /* present, system, DPL-0, trap gate */
+ DESCTYPE_DPL3 = 0x60, /* DPL-3 */
+ DESCTYPE_S = 0x10, /* !system */
};

// LDT or TSS descriptor in the GDT. 16 bytes.
--
1.4.4.2

2007-12-06 19:05:00

by Glauber Costa

[permalink] [raw]
Subject: [PATCH 13/19] unify non-paravirt parts of desc.h

This patch unifies the non-paravirt part of desc_{32,64}.h into
desc.h. Most of it, is simply common code, that is moved to
the shared header. The only exception is the set_ldt_desc in desc_64.h,
which is changed - included its name - to accomodate for the way
the ldt is set up in i386.

Also, constant definitions used in desc_32.h are moved to desc_defs.h

Signed-off-by: Glauber de Oliveira Costa <[email protected]>
---
include/asm-x86/desc.h | 87 ++++++++++++++++++++++++++++++++++++++
include/asm-x86/desc_32.h | 66 ----------------------------
include/asm-x86/desc_64.h | 64 ++++-----------------------
include/asm-x86/mmu_context_64.h | 4 +-
4 files changed, 99 insertions(+), 122 deletions(-)

diff --git a/include/asm-x86/desc.h b/include/asm-x86/desc.h
index 6065c50..926d6f8 100644
--- a/include/asm-x86/desc.h
+++ b/include/asm-x86/desc.h
@@ -1,5 +1,92 @@
+#ifndef _ASM_DESC_H_
+#define _ASM_DESC_H_
+
+#include <asm/desc_defs.h>
+
+#ifndef __ASSEMBLY__
+#include <asm/mmu.h>
+
+extern struct desc_ptr idt_descr;
+extern gate_desc idt_table[];
+
+#endif
+
#ifdef CONFIG_X86_32
# include "desc_32.h"
#else
# include "desc_64.h"
#endif
+
+#ifndef __ASSEMBLY__
+
+#define _LDT_empty(info) (\
+ (info)->base_addr == 0 && \
+ (info)->limit == 0 && \
+ (info)->contents == 0 && \
+ (info)->read_exec_only == 1 && \
+ (info)->seg_32bit == 0 && \
+ (info)->limit_in_pages == 0 && \
+ (info)->seg_not_present == 1 && \
+ (info)->useable == 0 )
+
+#ifdef CONFIG_X86_64
+#define LDT_empty(info) (_LDT_empty(info) && ((info)->lm == 0))
+#else
+#define LDT_empty(info) (_LDT_empty(info))
+#endif
+
+static inline void clear_LDT(void)
+{
+ set_ldt(NULL, 0);
+}
+
+/*
+ * load one particular LDT into the current CPU
+ */
+static inline void load_LDT_nolock(mm_context_t *pc)
+{
+ set_ldt(pc->ldt, pc->size);
+}
+
+static inline void load_LDT(mm_context_t *pc)
+{
+ preempt_disable();
+ load_LDT_nolock(pc);
+ preempt_enable();
+}
+
+static inline unsigned long get_desc_base(unsigned long *desc)
+{
+ unsigned long base;
+ base = ((desc[0] >> 16) & 0x0000ffff) |
+ ((desc[1] << 16) & 0x00ff0000) |
+ (desc[1] & 0xff000000);
+ return base;
+}
+
+#else
+/*
+ * GET_DESC_BASE reads the descriptor base of the specified segment.
+ *
+ * Args:
+ * idx - descriptor index
+ * gdt - GDT pointer
+ * base - 32bit register to which the base will be written
+ * lo_w - lo word of the "base" register
+ * lo_b - lo byte of the "base" register
+ * hi_b - hi byte of the low word of the "base" register
+ *
+ * Example:
+ * GET_DESC_BASE(GDT_ENTRY_ESPFIX_SS, %ebx, %eax, %ax, %al, %ah)
+ * Will read the base address of GDT_ENTRY_ESPFIX_SS and put it into %eax.
+ */
+#define GET_DESC_BASE(idx, gdt, base, lo_w, lo_b, hi_b) \
+ movb idx*8+4(gdt), lo_b; \
+ movb idx*8+7(gdt), hi_b; \
+ shll $16, base; \
+ movw idx*8+2(gdt), lo_w;
+
+
+#endif /* __ASSEMBLY__ */
+
+#endif
diff --git a/include/asm-x86/desc_32.h b/include/asm-x86/desc_32.h
index 5d1e848..960ec77 100644
--- a/include/asm-x86/desc_32.h
+++ b/include/asm-x86/desc_32.h
@@ -11,8 +11,6 @@
#include <linux/smp.h>
#include <linux/percpu.h>

-#include <asm/mmu.h>
-
struct gdt_page
{
struct desc_struct gdt[GDT_ENTRIES];
@@ -24,8 +22,6 @@ static inline struct desc_struct *get_cpu_gdt_table(unsigned int cpu)
return per_cpu(gdt_page, cpu).gdt;
}

-extern struct desc_ptr idt_descr;
-extern gate_desc idt_table[];
extern void set_intr_gate(unsigned int irq, void * addr);

static inline void pack_descriptor(struct desc_struct *desc,
@@ -162,68 +158,6 @@ static inline void __set_tss_desc(unsigned int cpu, unsigned int entry, const vo

#define set_tss_desc(cpu,addr) __set_tss_desc(cpu, GDT_ENTRY_TSS, addr)

-#define LDT_empty(info) (\
- (info)->base_addr == 0 && \
- (info)->limit == 0 && \
- (info)->contents == 0 && \
- (info)->read_exec_only == 1 && \
- (info)->seg_32bit == 0 && \
- (info)->limit_in_pages == 0 && \
- (info)->seg_not_present == 1 && \
- (info)->useable == 0 )
-
-static inline void clear_LDT(void)
-{
- set_ldt(NULL, 0);
-}
-
-/*
- * load one particular LDT into the current CPU
- */
-static inline void load_LDT_nolock(mm_context_t *pc)
-{
- set_ldt(pc->ldt, pc->size);
-}
-
-static inline void load_LDT(mm_context_t *pc)
-{
- preempt_disable();
- load_LDT_nolock(pc);
- preempt_enable();
-}
-
-static inline unsigned long get_desc_base(unsigned long *desc)
-{
- unsigned long base;
- base = ((desc[0] >> 16) & 0x0000ffff) |
- ((desc[1] << 16) & 0x00ff0000) |
- (desc[1] & 0xff000000);
- return base;
-}
-
-#else /* __ASSEMBLY__ */
-
-/*
- * GET_DESC_BASE reads the descriptor base of the specified segment.
- *
- * Args:
- * idx - descriptor index
- * gdt - GDT pointer
- * base - 32bit register to which the base will be written
- * lo_w - lo word of the "base" register
- * lo_b - lo byte of the "base" register
- * hi_b - hi byte of the low word of the "base" register
- *
- * Example:
- * GET_DESC_BASE(GDT_ENTRY_ESPFIX_SS, %ebx, %eax, %ax, %al, %ah)
- * Will read the base address of GDT_ENTRY_ESPFIX_SS and put it into %eax.
- */
-#define GET_DESC_BASE(idx, gdt, base, lo_w, lo_b, hi_b) \
- movb idx*8+4(gdt), lo_b; \
- movb idx*8+7(gdt), hi_b; \
- shll $16, base; \
- movw idx*8+2(gdt), lo_w;
-
#endif /* !__ASSEMBLY__ */

#endif
diff --git a/include/asm-x86/desc_64.h b/include/asm-x86/desc_64.h
index 3cd5f10..2dc19e2 100644
--- a/include/asm-x86/desc_64.h
+++ b/include/asm-x86/desc_64.h
@@ -9,16 +9,13 @@

#include <linux/string.h>
#include <linux/smp.h>
-#include <asm/desc_defs.h>

#include <asm/segment.h>
-#include <asm/mmu.h>

extern struct desc_struct cpu_gdt_table[GDT_ENTRIES];

#define load_TR_desc() asm volatile("ltr %w0"::"r" (GDT_ENTRY_TSS*8))
#define load_LDT_desc() asm volatile("lldt %w0"::"r" (GDT_ENTRY_LDT*8))
-#define clear_LDT() asm volatile("lldt %w0"::"r" (0))

static inline unsigned long __store_tr(void)
{
@@ -30,7 +27,6 @@ static inline unsigned long __store_tr(void)

#define store_tr(tr) (tr) = __store_tr()

-extern gate_desc idt_table[];
extern struct desc_ptr cpu_gdt_descr[];

static inline void write_ldt_entry(struct desc_struct *ldt,
@@ -138,22 +134,18 @@ static inline void set_tss_desc(unsigned cpu, void *addr)
IO_BITMAP_OFFSET + IO_BITMAP_BYTES + sizeof(unsigned long) - 1);
}

-static inline void set_ldt_desc(unsigned cpu, void *addr, int size)
+static inline void set_ldt(void *addr, int entries)
{
- set_tssldt_descriptor(&get_cpu_gdt_table(cpu)[GDT_ENTRY_LDT],
- (unsigned long)addr, DESC_LDT, size * 8 - 1);
-}
+ if (likely(entries == 0))
+ __asm__ __volatile__("lldt %w0"::"q" (0));
+ else {
+ unsigned cpu = smp_processor_id();

-#define LDT_empty(info) (\
- (info)->base_addr == 0 && \
- (info)->limit == 0 && \
- (info)->contents == 0 && \
- (info)->read_exec_only == 1 && \
- (info)->seg_32bit == 0 && \
- (info)->limit_in_pages == 0 && \
- (info)->seg_not_present == 1 && \
- (info)->useable == 0 && \
- (info)->lm == 0)
+ set_tssldt_descriptor(&get_cpu_gdt_table(cpu)[GDT_ENTRY_LDT],
+ (unsigned long)addr, DESC_LDT, entries * 8 - 1);
+ __asm__ __volatile__("lldt %w0"::"q" (GDT_ENTRY_LDT*8));
+ }
+}

static inline void load_TLS(struct thread_struct *t, unsigned int cpu)
{
@@ -164,42 +156,6 @@ static inline void load_TLS(struct thread_struct *t, unsigned int cpu)
gdt[i] = t->tls_array[i];
}

-/*
- * load one particular LDT into the current CPU
- */
-static inline void load_LDT_nolock(mm_context_t *pc, int cpu)
-{
- int count = pc->size;
-
- if (likely(!count)) {
- clear_LDT();
- return;
- }
-
- set_ldt_desc(cpu, pc->ldt, count);
- load_LDT_desc();
-}
-
-static inline void load_LDT(mm_context_t *pc)
-{
- int cpu = get_cpu();
-
- load_LDT_nolock(pc, cpu);
- put_cpu();
-}
-
-extern struct desc_ptr idt_descr;
-
-static inline unsigned long get_desc_base(const void *ptr)
-{
- const u32 *desc = ptr;
- unsigned long base;
- base = ((desc[0] >> 16) & 0x0000ffff) |
- ((desc[1] << 16) & 0x00ff0000) |
- (desc[1] & 0xff000000);
- return base;
-}
-
#endif /* !__ASSEMBLY__ */

#endif
diff --git a/include/asm-x86/mmu_context_64.h b/include/asm-x86/mmu_context_64.h
index 29f95c3..98bfe43 100644
--- a/include/asm-x86/mmu_context_64.h
+++ b/include/asm-x86/mmu_context_64.h
@@ -43,7 +43,7 @@ static inline void switch_mm(struct mm_struct *prev, struct mm_struct *next,
load_cr3(next->pgd);

if (unlikely(next->context.ldt != prev->context.ldt))
- load_LDT_nolock(&next->context, cpu);
+ load_LDT_nolock(&next->context);
}
#ifdef CONFIG_SMP
else {
@@ -56,7 +56,7 @@ static inline void switch_mm(struct mm_struct *prev, struct mm_struct *next,
* to make sure to use no freed page tables.
*/
load_cr3(next->pgd);
- load_LDT_nolock(&next->context, cpu);
+ load_LDT_nolock(&next->context);
}
}
#endif
--
1.4.4.2

2007-12-06 19:05:27

by Glauber Costa

[permalink] [raw]
Subject: [PATCH 15/19] modify get_desc_base

This patch makes get_desc_base() receive a struct desc_struct,
and then uses its internal fields to compute the base address.

Signed-off-by: Glauber de Oliveira Costa <[email protected]>
---
arch/x86/kernel/tls.c | 2 +-
arch/x86/mm/fault_32.c | 2 +-
include/asm-x86/desc.h | 8 ++------
3 files changed, 4 insertions(+), 8 deletions(-)

diff --git a/arch/x86/kernel/tls.c b/arch/x86/kernel/tls.c
index 74d2b65..98f428b 100644
--- a/arch/x86/kernel/tls.c
+++ b/arch/x86/kernel/tls.c
@@ -112,7 +112,7 @@ int do_get_thread_area(struct task_struct *p, int idx,

memset(&info, 0, sizeof(struct user_desc));
info.entry_number = idx;
- info.base_addr = get_desc_base((void *)desc);
+ info.base_addr = get_desc_base((struct desc_struct *)desc);
info.limit = GET_LIMIT(desc);
info.seg_32bit = GET_32BIT(desc);
info.contents = GET_CONTENTS(desc);
diff --git a/arch/x86/mm/fault_32.c b/arch/x86/mm/fault_32.c
index 6056c6d..ef5ab2b 100644
--- a/arch/x86/mm/fault_32.c
+++ b/arch/x86/mm/fault_32.c
@@ -115,7 +115,7 @@ static inline unsigned long get_segment_eip(struct pt_regs *regs,
}

/* Decode the code segment base from the descriptor */
- base = get_desc_base((unsigned long *)desc);
+ base = get_desc_base((struct desc_struct *)desc);

if (seg & (1<<2)) {
mutex_unlock(&current->mm->context.lock);
diff --git a/include/asm-x86/desc.h b/include/asm-x86/desc.h
index 926d6f8..3480cb1 100644
--- a/include/asm-x86/desc.h
+++ b/include/asm-x86/desc.h
@@ -55,13 +55,9 @@ static inline void load_LDT(mm_context_t *pc)
preempt_enable();
}

-static inline unsigned long get_desc_base(unsigned long *desc)
+static inline unsigned long get_desc_base(struct desc_struct *desc)
{
- unsigned long base;
- base = ((desc[0] >> 16) & 0x0000ffff) |
- ((desc[1] << 16) & 0x00ff0000) |
- (desc[1] & 0xff000000);
- return base;
+ return desc->base0 | ((desc->base1) << 16) | ((desc->base2) << 24);
}

#else
--
1.4.4.2

2007-12-06 19:05:46

by Glauber Costa

[permalink] [raw]
Subject: [PATCH 14/19] use the same data type for tls_array.

This patch changes the type of tls_array in x86_64 to
a desc_struct. Now, both i386 and x86_64 tls_array have
the same type, and code accessing it can be shared.

Signed-off-by: Glauber de Oliveira Costa <[email protected]>
---
include/asm-x86/desc_64.h | 2 +-
include/asm-x86/processor_64.h | 3 ++-
2 files changed, 3 insertions(+), 2 deletions(-)

diff --git a/include/asm-x86/desc_64.h b/include/asm-x86/desc_64.h
index 2dc19e2..7fd9876 100644
--- a/include/asm-x86/desc_64.h
+++ b/include/asm-x86/desc_64.h
@@ -150,7 +150,7 @@ static inline void set_ldt(void *addr, int entries)
static inline void load_TLS(struct thread_struct *t, unsigned int cpu)
{
unsigned int i;
- u64 *gdt = (u64 *)(get_cpu_gdt_table(cpu) + GDT_ENTRY_TLS_MIN);
+ struct desc_struct *gdt = (get_cpu_gdt_table(cpu) + GDT_ENTRY_TLS_MIN);

for (i = 0; i < GDT_ENTRY_TLS_ENTRIES; i++)
gdt[i] = t->tls_array[i];
diff --git a/include/asm-x86/processor_64.h b/include/asm-x86/processor_64.h
index 5689a8a..742090f 100644
--- a/include/asm-x86/processor_64.h
+++ b/include/asm-x86/processor_64.h
@@ -19,6 +19,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
@@ -241,7 +242,7 @@ struct thread_struct {
/* MSR_IA32_DEBUGCTLMSR value to switch in if TIF_DEBUGCTLMSR is set. */
unsigned long debugctlmsr;
/* 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 { \
--
1.4.4.2

2007-12-06 19:06:01

by Glauber Costa

[permalink] [raw]
Subject: [PATCH 16/19] provide tss_desc

Provide a new type, tss_desc, to represent the tss descriptor
in a unified way accross x86_64 and i386

Signed-off-by: Glauber de Oliveira Costa <[email protected]>
---
include/asm-x86/desc_defs.h | 2 ++
1 files changed, 2 insertions(+), 0 deletions(-)

diff --git a/include/asm-x86/desc_defs.h b/include/asm-x86/desc_defs.h
index 3bfb7d9..d4ae70d 100644
--- a/include/asm-x86/desc_defs.h
+++ b/include/asm-x86/desc_defs.h
@@ -80,9 +80,11 @@ struct ldttss_desc64 {
#ifdef CONFIG_X86_64
typedef struct gate_struct64 gate_desc;
typedef struct ldttss_desc64 ldt_desc;
+typedef struct ldttss_desc64 tss_desc;
#else
typedef struct desc_struct gate_desc;
typedef struct desc_struct ldt_desc;
+typedef struct desc_struct tss_desc;
#endif

struct desc_ptr {
--
1.4.4.2

2007-12-06 19:06:28

by Glauber Costa

[permalink] [raw]
Subject: [PATCH 17/19] unify paravirt pieces of descriptor handling

With the types used to access descriptors in x86_64 and i386
now being the same, the code that effectively handles them can
now be easily shared. This patch moves the paravirt part of
desc_32.h into desc.h, and then, we get paravirt support in x86_64
for free.

Signed-off-by: Glauber de Oliveira Costa <[email protected]>
---
include/asm-x86/desc.h | 155 +++++++++++++++++++++++++++++++++++++++++++
include/asm-x86/desc_32.h | 120 ---------------------------------
include/asm-x86/desc_64.h | 104 +++--------------------------
include/asm-x86/desc_defs.h | 6 +-
4 files changed, 169 insertions(+), 216 deletions(-)

diff --git a/include/asm-x86/desc.h b/include/asm-x86/desc.h
index 3480cb1..1773dd2 100644
--- a/include/asm-x86/desc.h
+++ b/include/asm-x86/desc.h
@@ -5,11 +5,166 @@

#ifndef __ASSEMBLY__
#include <asm/mmu.h>
+#include <linux/smp.h>

extern struct desc_ptr idt_descr;
extern gate_desc idt_table[];

+#ifdef CONFIG_X86_64
+extern struct desc_struct cpu_gdt_table[GDT_ENTRIES];
+extern struct desc_ptr cpu_gdt_descr[];
+/* the cpu gdt accessor */
+#define get_cpu_gdt_table(_cpu) ((struct desc_struct *)cpu_gdt_descr[_cpu].address)
+#else
+struct gdt_page
+{
+ struct desc_struct gdt[GDT_ENTRIES];
+} __attribute__((aligned(PAGE_SIZE)));
+DECLARE_PER_CPU(struct gdt_page, gdt_page);
+
+static inline struct desc_struct *get_cpu_gdt_table(unsigned int cpu)
+{
+ return per_cpu(gdt_page, cpu).gdt;
+}
+#endif
+
+#ifdef CONFIG_PARAVIRT
+#include <asm/paravirt.h>
+#else
+#define load_TR_desc() native_load_tr_desc()
+#define load_gdt(dtr) native_load_gdt(dtr)
+#define load_idt(dtr) native_load_idt(dtr)
+#define load_tr(tr) __asm__ __volatile("ltr %0"::"m" (tr))
+#define load_ldt(ldt) __asm__ __volatile("lldt %0"::"m" (ldt))
+
+#define store_gdt(dtr) native_store_gdt(dtr)
+#define store_idt(dtr) native_store_idt(dtr)
+#define store_tr(tr) (tr = native_store_tr())
+#define store_ldt(ldt) __asm__ ("sldt %0":"=m" (ldt))
+
+#define load_TLS(t, cpu) native_load_tls(t, cpu)
+#define set_ldt native_set_ldt
+
+#define write_ldt_entry(dt, entry, desc) \
+ native_write_ldt_entry(dt, entry, desc)
+#define write_gdt_entry(dt, entry, desc, size) \
+ native_write_gdt_entry(dt, entry, desc, size)
+#define write_idt_entry(dt, entry, g) native_write_idt_entry(dt, entry, g)
+#endif
+
+static inline void native_write_idt_entry(gate_desc *idt, int entry, gate_desc *gate)
+{
+ memcpy(&idt[entry], gate, sizeof(*gate));
+}
+
+static inline void native_write_ldt_entry(struct desc_struct *ldt, int entry,
+ void *desc)
+{
+ memcpy(&ldt[entry], desc, 8);
+}
+
+static inline void native_write_gdt_entry(struct desc_struct *gdt, int entry,
+ void *desc, int size)
+{
+ memcpy(&gdt[entry], desc, size);
+}
+
+static inline void set_tssldt_descriptor(struct ldttss_desc64 *d, unsigned long tss,
+ unsigned type, unsigned size)
+{
+ memset(d, 0, sizeof(*d));
+ d->limit0 = size & 0xFFFF;
+ d->base0 = PTR_LOW(tss);
+ d->base1 = PTR_MIDDLE(tss) & 0xFF;
+ d->type = type;
+ d->p = 1;
+ d->limit1 = (size >> 16) & 0xF;
+ d->base2 = (PTR_MIDDLE(tss) >> 8) & 0xFF;
+ d->base3 = PTR_HIGH(tss);
+}
+
+static inline void pack_descriptor(struct desc_struct *desc, unsigned long base,
+ unsigned long limit, unsigned char type,
+ unsigned char flags)
+{
+ desc->a = ((base & 0xffff) << 16) | (limit & 0xffff);
+ desc->b = (base & 0xff000000) | ((base & 0xff0000) >> 16) |
+ (limit & 0x000f0000) | ((type & 0xff) << 8) |
+ ((flags & 0xf) << 20);
+}
+
+static inline void pack_ldt(ldt_desc *ldt, unsigned long addr,
+ unsigned size)
+{
+
+#ifdef CONFIG_X86_64
+ set_tssldt_descriptor(ldt,
+ addr, DESC_LDT, size);
+#else
+ pack_descriptor(ldt, (unsigned long)addr,
+ size,
+ 0x80 | DESC_LDT, 0);
#endif
+}
+
+static inline void native_set_ldt(const void *addr, unsigned int entries)
+{
+ if (likely(entries == 0))
+ __asm__ __volatile__("lldt %w0"::"q" (0));
+ else {
+ unsigned cpu = smp_processor_id();
+ ldt_desc ldt;
+
+ pack_ldt(&ldt, (unsigned long)addr,
+ entries * sizeof(ldt) - 1);
+ write_gdt_entry(get_cpu_gdt_table(cpu), GDT_ENTRY_LDT,
+ &ldt, sizeof(ldt));
+ __asm__ __volatile__("lldt %w0"::"q" (GDT_ENTRY_LDT*8));
+ }
+}
+
+static inline void native_load_tr_desc(void)
+{
+ asm volatile("ltr %w0"::"q" (GDT_ENTRY_TSS*8));
+}
+
+static inline void native_load_gdt(const struct desc_ptr *dtr)
+{
+ asm volatile("lgdt %0"::"m" (*dtr));
+}
+
+static inline void native_load_idt(const struct desc_ptr *dtr)
+{
+ asm volatile("lidt %0"::"m" (*dtr));
+}
+
+static inline void native_store_gdt(struct desc_ptr *dtr)
+{
+ asm ("sgdt %0":"=m" (*dtr));
+}
+
+static inline void native_store_idt(struct desc_ptr *dtr)
+{
+ asm ("sidt %0":"=m" (*dtr));
+}
+
+static inline unsigned long native_store_tr(void)
+{
+ unsigned long tr;
+ asm ("str %0":"=r" (tr));
+ return tr;
+}
+
+static inline void native_load_tls(struct thread_struct *t, unsigned int cpu)
+{
+ unsigned int i;
+ struct desc_struct *gdt = get_cpu_gdt_table(cpu);
+
+ for (i = 0; i < GDT_ENTRY_TLS_ENTRIES; i++)
+ gdt[GDT_ENTRY_TLS_MIN + i] = t->tls_array[i];
+}
+#endif /* __ASSEMBLY__ */
+

#ifdef CONFIG_X86_32
# include "desc_32.h"
diff --git a/include/asm-x86/desc_32.h b/include/asm-x86/desc_32.h
index 960ec77..e8f2bc2 100644
--- a/include/asm-x86/desc_32.h
+++ b/include/asm-x86/desc_32.h
@@ -8,30 +8,10 @@
#ifndef __ASSEMBLY__

#include <linux/preempt.h>
-#include <linux/smp.h>
#include <linux/percpu.h>

-struct gdt_page
-{
- struct desc_struct gdt[GDT_ENTRIES];
-} __attribute__((aligned(PAGE_SIZE)));
-DECLARE_PER_CPU(struct gdt_page, gdt_page);
-
-static inline struct desc_struct *get_cpu_gdt_table(unsigned int cpu)
-{
- return per_cpu(gdt_page, cpu).gdt;
-}
-
extern void set_intr_gate(unsigned int irq, void * addr);

-static inline void pack_descriptor(struct desc_struct *desc,
- unsigned long base, unsigned long limit, unsigned char type, unsigned char flags)
-{
- desc->a = ((base & 0xffff) << 16) | (limit & 0xffff);
- desc->b = (base & 0xff000000) | ((base & 0xff0000) >> 16) |
- (limit & 0x000f0000) | ((type & 0xff) << 8) | ((flags & 0xf) << 20);
-}
-
static inline void pack_gate(gate_desc *gate,
unsigned long base, unsigned short seg, unsigned char type, unsigned char flags)
{
@@ -39,106 +19,6 @@ static inline void pack_gate(gate_desc *gate,
gate->b = (base & 0xffff0000) | ((type & 0xff) << 8) | (flags & 0xff);
}

-#ifdef CONFIG_PARAVIRT
-#include <asm/paravirt.h>
-#else
-#define load_TR_desc() native_load_tr_desc()
-#define load_gdt(dtr) native_load_gdt(dtr)
-#define load_idt(dtr) native_load_idt(dtr)
-#define load_tr(tr) __asm__ __volatile("ltr %0"::"m" (tr))
-#define load_ldt(ldt) __asm__ __volatile("lldt %0"::"m" (ldt))
-
-#define store_gdt(dtr) native_store_gdt(dtr)
-#define store_idt(dtr) native_store_idt(dtr)
-#define store_tr(tr) (tr = native_store_tr())
-#define store_ldt(ldt) __asm__ ("sldt %0":"=m" (ldt))
-
-#define load_TLS(t, cpu) native_load_tls(t, cpu)
-#define set_ldt native_set_ldt
-
-#define write_ldt_entry(dt, entry, desc) \
- native_write_ldt_entry(dt, entry, desc)
-#define write_gdt_entry(dt, entry, desc, size) \
- native_write_gdt_entry(dt, entry, desc, size)
-#define write_idt_entry(dt, entry, g) native_write_idt_entry(dt, entry, g)
-#endif
-
-static inline void native_write_ldt_entry(struct desc_struct *ldt, int entry,
- void *desc)
-{
- memcpy(&ldt[entry], desc, size);
-}
-
-static inline void native_write_idt_entry(gate_desc *idt, int entry, gate_desc *gate)
-{
- memcpy(&idt[entry], gate, sizeof(*gate));
-}
-
-static inline void native_write_gdt_entry(struct desc_struct *gdt, int entry,
- void *desc, int size)
-{
- memcpy(&gdt[entry], desc, size);
-}
-
-static inline void native_set_ldt(const void *addr, unsigned int entries)
-{
- if (likely(entries == 0))
- __asm__ __volatile__("lldt %w0"::"q" (0));
- else {
- unsigned cpu = smp_processor_id();
- ldt_desc ldt;
-
- pack_descriptor(&ldt, (unsigned long)addr,
- entries * sizeof(struct desc_struct) - 1,
- DESCTYPE_LDT, 0);
- write_gdt_entry(get_cpu_gdt_table(cpu), GDT_ENTRY_LDT,
- &ldt, sizeof(ldt));
- __asm__ __volatile__("lldt %w0"::"q" (GDT_ENTRY_LDT*8));
- }
-}
-
-
-static inline void native_load_tr_desc(void)
-{
- asm volatile("ltr %w0"::"q" (GDT_ENTRY_TSS*8));
-}
-
-static inline void native_load_gdt(const struct desc_ptr *dtr)
-{
- asm volatile("lgdt %0"::"m" (*dtr));
-}
-
-static inline void native_load_idt(const struct desc_ptr *dtr)
-{
- asm volatile("lidt %0"::"m" (*dtr));
-}
-
-static inline void native_store_gdt(struct desc_ptr *dtr)
-{
- asm ("sgdt %0":"=m" (*dtr));
-}
-
-static inline void native_store_idt(struct desc_ptr *dtr)
-{
- asm ("sidt %0":"=m" (*dtr));
-}
-
-static inline unsigned long native_store_tr(void)
-{
- unsigned long tr;
- asm ("str %0":"=r" (tr));
- return tr;
-}
-
-static inline void native_load_tls(struct thread_struct *t, unsigned int cpu)
-{
- unsigned int i;
- struct desc_struct *gdt = get_cpu_gdt_table(cpu);
-
- for (i = 0; i < GDT_ENTRY_TLS_ENTRIES; i++)
- gdt[GDT_ENTRY_TLS_MIN + i] = t->tls_array[i];
-}
-
static inline void _set_gate(int gate, unsigned int type, void *addr, unsigned short seg)
{
gate_desc g;
diff --git a/include/asm-x86/desc_64.h b/include/asm-x86/desc_64.h
index 7fd9876..fd907da 100644
--- a/include/asm-x86/desc_64.h
+++ b/include/asm-x86/desc_64.h
@@ -8,47 +8,10 @@
#ifndef __ASSEMBLY__

#include <linux/string.h>
-#include <linux/smp.h>

#include <asm/segment.h>

-extern struct desc_struct cpu_gdt_table[GDT_ENTRIES];
-
-#define load_TR_desc() asm volatile("ltr %w0"::"r" (GDT_ENTRY_TSS*8))
-#define load_LDT_desc() asm volatile("lldt %w0"::"r" (GDT_ENTRY_LDT*8))
-
-static inline unsigned long __store_tr(void)
-{
- unsigned long tr;
-
- asm volatile ("str %w0":"=r" (tr));
- return tr;
-}
-
-#define store_tr(tr) (tr) = __store_tr()
-
-extern struct desc_ptr cpu_gdt_descr[];
-
-static inline void write_ldt_entry(struct desc_struct *ldt,
- int entry, void *ptr)
-{
- memcpy(&ldt[entry], ptr, 8);
-}
-
-/* the cpu gdt accessor */
-#define get_cpu_gdt_table(_cpu) ((struct desc_struct *)cpu_gdt_descr[_cpu].address)
-
-static inline void load_gdt(const struct desc_ptr *ptr)
-{
- asm volatile("lgdt %w0"::"m" (*ptr));
-}
-
-static inline void store_gdt(struct desc_ptr *ptr)
-{
- asm("sgdt %w0":"=m" (*ptr));
-}
-
-static inline void _set_gate(void *adr, unsigned type, unsigned long func,
+static inline void _set_gate(int gate, unsigned type, unsigned long func,
unsigned dpl, unsigned ist)
{
gate_desc s;
@@ -67,61 +30,37 @@ static inline void _set_gate(void *adr, unsigned type, unsigned long func,
* does not need to be atomic because it is only done once at
* setup time
*/
- memcpy(adr, &s, 16);
+ write_idt_entry(idt_table, gate, &s);
}

static inline void set_intr_gate(int nr, void *func)
{
BUG_ON((unsigned)nr > 0xFF);
- _set_gate(&idt_table[nr], GATE_INTERRUPT, (unsigned long) func, 0, 0);
+ _set_gate(nr, GATE_INTERRUPT, (unsigned long) func, 0, 0);
}

static inline void set_intr_gate_ist(int nr, void *func, unsigned ist)
{
BUG_ON((unsigned)nr > 0xFF);
- _set_gate(&idt_table[nr], GATE_INTERRUPT, (unsigned long) func, 0, ist);
+ _set_gate(nr, GATE_INTERRUPT, (unsigned long) func, 0, ist);
}

static inline void set_system_gate(int nr, void *func)
{
BUG_ON((unsigned)nr > 0xFF);
- _set_gate(&idt_table[nr], GATE_INTERRUPT, (unsigned long) func, 3, 0);
+ _set_gate(nr, GATE_INTERRUPT, (unsigned long) func, 3, 0);
}

static inline void set_system_gate_ist(int nr, void *func, unsigned ist)
{
- _set_gate(&idt_table[nr], GATE_INTERRUPT, (unsigned long) func, 3, ist);
-}
-
-static inline void load_idt(const struct desc_ptr *ptr)
-{
- asm volatile("lidt %w0"::"m" (*ptr));
-}
-
-static inline void store_idt(struct desc_ptr *dtr)
-{
- asm("sidt %w0":"=m" (*dtr));
-}
-
-static inline void set_tssldt_descriptor(void *ptr, unsigned long tss,
- unsigned type, unsigned size)
-{
- struct ldttss_desc64 d;
-
- memset(&d, 0, sizeof(d));
- d.limit0 = size & 0xFFFF;
- d.base0 = PTR_LOW(tss);
- d.base1 = PTR_MIDDLE(tss) & 0xFF;
- d.type = type;
- d.p = 1;
- d.limit1 = (size >> 16) & 0xF;
- d.base2 = (PTR_MIDDLE(tss) >> 8) & 0xFF;
- d.base3 = PTR_HIGH(tss);
- memcpy(ptr, &d, 16);
+ _set_gate(nr, GATE_INTERRUPT, (unsigned long) func, 3, ist);
}

static inline void set_tss_desc(unsigned cpu, void *addr)
{
+ struct desc_struct *d = get_cpu_gdt_table(cpu);
+ tss_desc tss;
+
/*
* sizeof(unsigned long) coming from an extra "long" at the end
* of the iobitmap. See tss_struct definition in processor.h
@@ -129,31 +68,10 @@ static inline void set_tss_desc(unsigned cpu, void *addr)
* -1? seg base+limit should be pointing to the address of the
* last valid byte
*/
- set_tssldt_descriptor(&get_cpu_gdt_table(cpu)[GDT_ENTRY_TSS],
+ set_tssldt_descriptor(&tss,
(unsigned long)addr, DESC_TSS,
IO_BITMAP_OFFSET + IO_BITMAP_BYTES + sizeof(unsigned long) - 1);
-}
-
-static inline void set_ldt(void *addr, int entries)
-{
- if (likely(entries == 0))
- __asm__ __volatile__("lldt %w0"::"q" (0));
- else {
- unsigned cpu = smp_processor_id();
-
- set_tssldt_descriptor(&get_cpu_gdt_table(cpu)[GDT_ENTRY_LDT],
- (unsigned long)addr, DESC_LDT, entries * 8 - 1);
- __asm__ __volatile__("lldt %w0"::"q" (GDT_ENTRY_LDT*8));
- }
-}
-
-static inline void load_TLS(struct thread_struct *t, unsigned int cpu)
-{
- unsigned int i;
- struct desc_struct *gdt = (get_cpu_gdt_table(cpu) + GDT_ENTRY_TLS_MIN);
-
- for (i = 0; i < GDT_ENTRY_TLS_ENTRIES; i++)
- gdt[i] = t->tls_array[i];
+ write_gdt_entry(d, GDT_ENTRY_TSS, &tss, sizeof(tss_desc));
}

#endif /* !__ASSEMBLY__ */
diff --git a/include/asm-x86/desc_defs.h b/include/asm-x86/desc_defs.h
index d4ae70d..69597f3 100644
--- a/include/asm-x86/desc_defs.h
+++ b/include/asm-x86/desc_defs.h
@@ -51,9 +51,9 @@ struct gate_struct64 {
u32 zero1;
} __attribute__((packed));

-#define PTR_LOW(x) ((unsigned long)(x) & 0xFFFF)
-#define PTR_MIDDLE(x) (((unsigned long)(x) >> 16) & 0xFFFF)
-#define PTR_HIGH(x) ((unsigned long)(x) >> 32)
+#define PTR_LOW(x) ((unsigned long long)(x) & 0xFFFF)
+#define PTR_MIDDLE(x) (((unsigned long long)(x) >> 16) & 0xFFFF)
+#define PTR_HIGH(x) ((unsigned long long)(x) >> 32)

enum {
DESC_TSS = 0x9,
--
1.4.4.2

2007-12-06 19:06:44

by Glauber Costa

[permalink] [raw]
Subject: [PATCH 19/19] unify set_tss_desc

This patch unifies the set_tss_desc between i386 and x86_64,
which can now have a common implementation. After the old
functions are removed from desc_{32,64}.h, nothing important is
left, and the files can be removed.

Signed-off-by: Glauber de Oliveira Costa <[email protected]>
---
include/asm-x86/desc.h | 40 +++++++++++++++++++++++++++++++++-------
include/asm-x86/desc_64.h | 34 ----------------------------------
2 files changed, 33 insertions(+), 41 deletions(-)

diff --git a/include/asm-x86/desc.h b/include/asm-x86/desc.h
index 1290757..4aab1fd 100644
--- a/include/asm-x86/desc.h
+++ b/include/asm-x86/desc.h
@@ -133,6 +133,39 @@ static inline void pack_ldt(ldt_desc *ldt, unsigned long addr,
#endif
}

+static inline void pack_tss(tss_desc *tss, unsigned long addr,
+ unsigned size, unsigned entry)
+{
+#ifdef CONFIG_X86_64
+ set_tssldt_descriptor(tss,
+ addr, entry, size);
+#else
+ pack_descriptor(tss, (unsigned long)addr,
+ size,
+ 0x80 | entry, 0);
+#endif
+}
+
+static inline void __set_tss_desc(unsigned cpu, unsigned int entry, void *addr)
+{
+ struct desc_struct *d = get_cpu_gdt_table(cpu);
+ tss_desc tss;
+
+ /*
+ * sizeof(unsigned long) coming from an extra "long" at the end
+ * of the iobitmap. See tss_struct definition in processor.h
+ *
+ * -1? seg base+limit should be pointing to the address of the
+ * last valid byte
+ */
+ pack_tss(&tss, (unsigned long)addr,
+ IO_BITMAP_OFFSET + IO_BITMAP_BYTES + sizeof(unsigned long) - 1,
+ DESC_TSS);
+ write_gdt_entry(d, entry, &tss, sizeof(tss));
+}
+
+#define set_tss_desc(cpu,addr) __set_tss_desc(cpu, GDT_ENTRY_TSS, addr)
+
static inline void native_set_ldt(const void *addr, unsigned int entries)
{
if (likely(entries == 0))
@@ -191,13 +224,6 @@ static inline void native_load_tls(struct thread_struct *t, unsigned int cpu)
}
#endif /* __ASSEMBLY__ */

-
-#ifdef CONFIG_X86_32
-# include "desc_32.h"
-#else
-# include "desc_64.h"
-#endif
-
#ifndef __ASSEMBLY__

#define _LDT_empty(info) (\
diff --git a/include/asm-x86/desc_64.h b/include/asm-x86/desc_64.h
deleted file mode 100644
index de37b9b..0000000
--- a/include/asm-x86/desc_64.h
+++ /dev/null
@@ -1,34 +0,0 @@
-/* Written 2000 by Andi Kleen */
-#ifndef __ARCH_DESC_H
-#define __ARCH_DESC_H
-
-#include <linux/threads.h>
-#include <asm/ldt.h>
-
-#ifndef __ASSEMBLY__
-
-#include <linux/string.h>
-
-#include <asm/segment.h>
-
-static inline void set_tss_desc(unsigned cpu, void *addr)
-{
- struct desc_struct *d = get_cpu_gdt_table(cpu);
- tss_desc tss;
-
- /*
- * sizeof(unsigned long) coming from an extra "long" at the end
- * of the iobitmap. See tss_struct definition in processor.h
- *
- * -1? seg base+limit should be pointing to the address of the
- * last valid byte
- */
- set_tssldt_descriptor(&tss,
- (unsigned long)addr, DESC_TSS,
- IO_BITMAP_OFFSET + IO_BITMAP_BYTES + sizeof(unsigned long) - 1);
- write_gdt_entry(d, GDT_ENTRY_TSS, &tss, sizeof(tss_desc));
-}
-
-#endif /* !__ASSEMBLY__ */
-
-#endif
--
1.4.4.2

2007-12-06 19:07:01

by Glauber Costa

[permalink] [raw]
Subject: [PATCH 18/19] move _set_gate and its users to a common location

This patch moves _set_gate and its users to desc.h. We can now
use common code for x86_64 and i386.

Signed-off-by: Glauber de Oliveira Costa <[email protected]>
---
arch/x86/kernel/traps_32.c | 34 ----------------
include/asm-x86/desc.h | 88 +++++++++++++++++++++++++++++++++++++++++++
include/asm-x86/desc_32.h | 43 ---------------------
include/asm-x86/desc_64.h | 45 ----------------------
include/asm-x86/desc_defs.h | 5 +--
5 files changed, 89 insertions(+), 126 deletions(-)

diff --git a/arch/x86/kernel/traps_32.c b/arch/x86/kernel/traps_32.c
index 6b03d88..776e19b 100644
--- a/arch/x86/kernel/traps_32.c
+++ b/arch/x86/kernel/traps_32.c
@@ -1102,40 +1102,6 @@ asmlinkage void math_emulate(long arg)

#endif /* CONFIG_MATH_EMULATION */

-/*
- * This needs to use 'idt_table' rather than 'idt', and
- * thus use the _nonmapped_ version of the IDT, as the
- * Pentium F0 0F bugfix can have resulted in the mapped
- * IDT being write-protected.
- */
-void set_intr_gate(unsigned int n, void *addr)
-{
- _set_gate(n, DESCTYPE_INT, addr, __KERNEL_CS);
-}
-
-/*
- * This routine sets up an interrupt gate at directory privilege level 3.
- */
-static inline void set_system_intr_gate(unsigned int n, void *addr)
-{
- _set_gate(n, DESCTYPE_INT | DESCTYPE_DPL3, addr, __KERNEL_CS);
-}
-
-static void __init set_trap_gate(unsigned int n, void *addr)
-{
- _set_gate(n, DESCTYPE_TRAP, addr, __KERNEL_CS);
-}
-
-static void __init set_system_gate(unsigned int n, void *addr)
-{
- _set_gate(n, DESCTYPE_TRAP | DESCTYPE_DPL3, addr, __KERNEL_CS);
-}
-
-static void __init set_task_gate(unsigned int n, unsigned int gdt_entry)
-{
- _set_gate(n, DESCTYPE_TASK, (void *)0, (gdt_entry<<3));
-}
-

void __init trap_init(void)
{
diff --git a/include/asm-x86/desc.h b/include/asm-x86/desc.h
index 1773dd2..1290757 100644
--- a/include/asm-x86/desc.h
+++ b/include/asm-x86/desc.h
@@ -15,6 +15,22 @@ extern struct desc_struct cpu_gdt_table[GDT_ENTRIES];
extern struct desc_ptr cpu_gdt_descr[];
/* the cpu gdt accessor */
#define get_cpu_gdt_table(_cpu) ((struct desc_struct *)cpu_gdt_descr[_cpu].address)
+
+static inline void pack_gate(gate_desc *gate, unsigned type, unsigned long func,
+ unsigned dpl, unsigned ist, unsigned seg)
+{
+ gate->offset_low = PTR_LOW(func);
+ gate->segment = __KERNEL_CS;
+ gate->ist = ist;
+ gate->p = 1;
+ gate->dpl = dpl;
+ gate->zero0 = 0;
+ gate->zero1 = 0;
+ gate->type = type;
+ gate->offset_middle = PTR_MIDDLE(func);
+ gate->offset_high = PTR_HIGH(func);
+}
+
#else
struct gdt_page
{
@@ -26,6 +42,16 @@ static inline struct desc_struct *get_cpu_gdt_table(unsigned int cpu)
{
return per_cpu(gdt_page, cpu).gdt;
}
+
+static inline void pack_gate(gate_desc *gate,unsigned char type,
+ unsigned long base, unsigned dpl, unsigned flags, unsigned short seg)
+
+{
+ gate->a = (seg << 16) | (base & 0xffff);
+ gate->b = (base & 0xffff0000) |
+ ((( 0x80 | type | (dpl << 5)) & 0xff) << 8);
+}
+
#endif

#ifdef CONFIG_PARAVIRT
@@ -214,6 +240,68 @@ static inline unsigned long get_desc_base(struct desc_struct *desc)
{
return desc->base0 | ((desc->base1) << 16) | ((desc->base2) << 24);
}
+static inline void _set_gate(int gate, unsigned type, void *addr,
+ unsigned dpl, unsigned ist, unsigned seg)
+{
+ gate_desc s;
+ pack_gate(&s, type, (unsigned long)addr, dpl, ist, seg);
+ /*
+ * does not need to be atomic because it is only done once at
+ * setup time
+ */
+ write_idt_entry(idt_table, gate, &s);
+}
+
+/*
+ * This needs to use 'idt_table' rather than 'idt', and
+ * thus use the _nonmapped_ version of the IDT, as the
+ * Pentium F0 0F bugfix can have resulted in the mapped
+ * IDT being write-protected.
+ */
+static inline void set_intr_gate(unsigned int n, void *addr)
+{
+ BUG_ON((unsigned)n > 0xFF);
+ _set_gate(n, GATE_INTERRUPT, addr, 0, 0, __KERNEL_CS);
+}
+
+/*
+ * This routine sets up an interrupt gate at directory privilege level 3.
+ */
+static inline void set_system_intr_gate(unsigned int n, void *addr)
+{
+ BUG_ON((unsigned)n > 0xFF);
+ _set_gate(n, GATE_INTERRUPT, addr, 0x3, 0, __KERNEL_CS);
+}
+
+static inline void set_trap_gate(unsigned int n, void *addr)
+{
+ BUG_ON((unsigned)n > 0xFF);
+ _set_gate(n, GATE_TRAP, addr, 0, 0, __KERNEL_CS);
+}
+
+static inline void set_system_gate(unsigned int n, void *addr)
+{
+ BUG_ON((unsigned)n > 0xFF);
+ _set_gate(n, GATE_TRAP, addr, 0x3, 0, __KERNEL_CS);
+}
+
+static inline void set_task_gate(unsigned int n, unsigned int gdt_entry)
+{
+ BUG_ON((unsigned)n > 0xFF);
+ _set_gate(n, GATE_TASK, (void *)0, 0, 0, (gdt_entry<<3));
+}
+
+static inline void set_intr_gate_ist(int n, void *addr, unsigned ist)
+{
+ BUG_ON((unsigned)n > 0xFF);
+ _set_gate(n, GATE_INTERRUPT, addr, 0, ist, __KERNEL_CS);
+}
+
+static inline void set_system_gate_ist(int n, void *addr, unsigned ist)
+{
+ BUG_ON((unsigned)n > 0xFF);
+ _set_gate(n, GATE_INTERRUPT, addr, 0x3, ist, __KERNEL_CS);
+}

#else
/*
diff --git a/include/asm-x86/desc_32.h b/include/asm-x86/desc_32.h
deleted file mode 100644
index e8f2bc2..0000000
--- a/include/asm-x86/desc_32.h
+++ /dev/null
@@ -1,43 +0,0 @@
-#ifndef __ARCH_DESC_H
-#define __ARCH_DESC_H
-
-#include <asm/ldt.h>
-#include <asm/segment.h>
-#include <asm/desc_defs.h>
-
-#ifndef __ASSEMBLY__
-
-#include <linux/preempt.h>
-#include <linux/percpu.h>
-
-extern void set_intr_gate(unsigned int irq, void * addr);
-
-static inline void pack_gate(gate_desc *gate,
- unsigned long base, unsigned short seg, unsigned char type, unsigned char flags)
-{
- gate->a = (seg << 16) | (base & 0xffff);
- gate->b = (base & 0xffff0000) | ((type & 0xff) << 8) | (flags & 0xff);
-}
-
-static inline void _set_gate(int gate, unsigned int type, void *addr, unsigned short seg)
-{
- gate_desc g;
- pack_gate(&g, (unsigned long)addr, seg, type, 0);
- write_idt_entry(idt_table, gate, &g);
-}
-
-static inline void __set_tss_desc(unsigned int cpu, unsigned int entry, const void *addr)
-{
- tss_desc tss;
- pack_descriptor(&tss, (unsigned long)addr,
- offsetof(struct tss_struct, __cacheline_filler) - 1,
- DESCTYPE_TSS, 0);
- write_gdt_entry(get_cpu_gdt_table(cpu), entry, &tss, sizeof(tss));
-}
-
-
-#define set_tss_desc(cpu,addr) __set_tss_desc(cpu, GDT_ENTRY_TSS, addr)
-
-#endif /* !__ASSEMBLY__ */
-
-#endif
diff --git a/include/asm-x86/desc_64.h b/include/asm-x86/desc_64.h
index fd907da..de37b9b 100644
--- a/include/asm-x86/desc_64.h
+++ b/include/asm-x86/desc_64.h
@@ -11,51 +11,6 @@

#include <asm/segment.h>

-static inline void _set_gate(int gate, unsigned type, unsigned long func,
- unsigned dpl, unsigned ist)
-{
- gate_desc s;
-
- s.offset_low = PTR_LOW(func);
- s.segment = __KERNEL_CS;
- s.ist = ist;
- s.p = 1;
- s.dpl = dpl;
- s.zero0 = 0;
- s.zero1 = 0;
- s.type = type;
- s.offset_middle = PTR_MIDDLE(func);
- s.offset_high = PTR_HIGH(func);
- /*
- * does not need to be atomic because it is only done once at
- * setup time
- */
- write_idt_entry(idt_table, gate, &s);
-}
-
-static inline void set_intr_gate(int nr, void *func)
-{
- BUG_ON((unsigned)nr > 0xFF);
- _set_gate(nr, GATE_INTERRUPT, (unsigned long) func, 0, 0);
-}
-
-static inline void set_intr_gate_ist(int nr, void *func, unsigned ist)
-{
- BUG_ON((unsigned)nr > 0xFF);
- _set_gate(nr, GATE_INTERRUPT, (unsigned long) func, 0, ist);
-}
-
-static inline void set_system_gate(int nr, void *func)
-{
- BUG_ON((unsigned)nr > 0xFF);
- _set_gate(nr, GATE_INTERRUPT, (unsigned long) func, 3, 0);
-}
-
-static inline void set_system_gate_ist(int nr, void *func, unsigned ist)
-{
- _set_gate(nr, GATE_INTERRUPT, (unsigned long) func, 3, ist);
-}
-
static inline void set_tss_desc(unsigned cpu, void *addr)
{
struct desc_struct *d = get_cpu_gdt_table(cpu);
diff --git a/include/asm-x86/desc_defs.h b/include/asm-x86/desc_defs.h
index 69597f3..7759d8a 100644
--- a/include/asm-x86/desc_defs.h
+++ b/include/asm-x86/desc_defs.h
@@ -39,6 +39,7 @@ enum {
GATE_INTERRUPT = 0xE,
GATE_TRAP = 0xF,
GATE_CALL = 0xC,
+ GATE_TASK = 0x5,
};

// 16byte gate
@@ -60,10 +61,6 @@ enum {
DESC_LDT = 0x2,
DESCTYPE_LDT = 0x82, /* present, system, DPL-0, LDT */
DESCTYPE_TSS = 0x89, /* present, system, DPL-0, 32-bit TSS */
- DESCTYPE_TASK = 0x85, /* present, system, DPL-0, task gate */
- DESCTYPE_INT = 0x8e, /* present, system, DPL-0, interrupt gate */
- DESCTYPE_TRAP = 0x8f, /* present, system, DPL-0, trap gate */
- DESCTYPE_DPL3 = 0x60, /* DPL-3 */
DESCTYPE_S = 0x10, /* !system */
};

--
1.4.4.2

2007-12-06 19:24:30

by Jeremy Fitzhardinge

[permalink] [raw]
Subject: Re: [PATCH 1/19] unify desc_struct

Glauber de Oliveira Costa wrote:
> This patch aims to make the access of struct desc_struct variables
> equal across architectures. In this patch, I unify the i386 and x86_64
> versions under an anonymous union, keeping the way they are accessed
> untouched (a and b for 32-bit code, individual bit-fields for 64-bit).
>
> This solution is not beautiful, but will allow us to integrate common
> code that differed by the way descriptors were used. This is to be viewed
> incrementally. There's simply too much code to be fixed at once.
>
> In the future, goal is to set up in a single way of acessing
> the desc_struct fields.
>
> Signed-off-by: Glauber de Oliveira Costa <[email protected]>
> ---
> arch/x86/kernel/apm_32.c | 2 +-
> arch/x86/kernel/cpu/common.c | 28 ++++++++++++++--------------
> arch/x86/kernel/process_64.c | 2 +-
> arch/x86/kernel/traps_32.c | 2 +-
> include/asm-x86/desc_defs.h | 28 ++++++++++++++++++++--------
> include/asm-x86/processor_32.h | 5 +----
> 6 files changed, 38 insertions(+), 29 deletions(-)
>
> diff --git a/arch/x86/kernel/apm_32.c b/arch/x86/kernel/apm_32.c
> index 8cd9778..b8b9339 100644
> --- a/arch/x86/kernel/apm_32.c
> +++ b/arch/x86/kernel/apm_32.c
> @@ -405,7 +405,7 @@ static DECLARE_WAIT_QUEUE_HEAD(apm_waitqueue);
> 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 = {{{ 0, 0x00409200 }}};
>
> static const char driver_version[] = "1.16ac"; /* no spaces */
>
> diff --git a/arch/x86/kernel/cpu/common.c b/arch/x86/kernel/cpu/common.c
> index 235cd61..0fe1c1d 100644
> --- a/arch/x86/kernel/cpu/common.c
> +++ b/arch/x86/kernel/cpu/common.c
> @@ -22,31 +22,31 @@
> #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] = {{{ 0x0000ffff, 0x00cf9a00 }}},
> + [GDT_ENTRY_KERNEL_DS] = {{{ 0x0000ffff, 0x00cf9200 }}},
> + [GDT_ENTRY_DEFAULT_USER_CS] = {{{ 0x0000ffff, 0x00cffa00 }}},
> + [GDT_ENTRY_DEFAULT_USER_DS] = {{{ 0x0000ffff, 0x00cff200 }}},
>

I don't suppose there's some way to make all this more symbolic?

> /*
> * 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 */
> + [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 */
> /*
> * 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 */
> + [GDT_ENTRY_APMBIOS_BASE] = {{{ 0x0000ffff, 0x00409a00 }}},/* 32-bit code */
> /* 16-bit code */
> - [GDT_ENTRY_APMBIOS_BASE+1] = { 0x0000ffff, 0x00009a00 },
> - [GDT_ENTRY_APMBIOS_BASE+2] = { 0x0000ffff, 0x00409200 }, /* data */
> + [GDT_ENTRY_APMBIOS_BASE+1] = {{{ 0x0000ffff, 0x00009a00 }}},
> + [GDT_ENTRY_APMBIOS_BASE+2] = {{{ 0x0000ffff, 0x00409200 }}}, /* data */
>
> - [GDT_ENTRY_ESPFIX_SS] = { 0x00000000, 0x00c09200 },
> - [GDT_ENTRY_PERCPU] = { 0x00000000, 0x00000000 },
> + [GDT_ENTRY_ESPFIX_SS] = {{{ 0x00000000, 0x00c09200 }}},
> + [GDT_ENTRY_PERCPU] = {{{ 0x00000000, 0x00000000 }}},
> } };
> EXPORT_PER_CPU_SYMBOL_GPL(gdt_page);
>
> diff --git a/arch/x86/kernel/process_64.c b/arch/x86/kernel/process_64.c
> index 6724840..9e99cb7 100644
> --- a/arch/x86/kernel/process_64.c
> +++ b/arch/x86/kernel/process_64.c
> @@ -437,7 +437,7 @@ static inline void set_32bit_tls(struct task_struct *t, int tls, u32 addr)
> .limit_in_pages = 1,
> .useable = 1,
> };
> - struct n_desc_struct *desc = (void *)t->thread.tls_array;
> + struct desc_struct *desc = (void *)t->thread.tls_array;
> desc += tls;
> desc->a = LDT_entry_a(&ud);
> desc->b = LDT_entry_b(&ud);
> diff --git a/arch/x86/kernel/traps_32.c b/arch/x86/kernel/traps_32.c
> index e15014e..94c5aea 100644
> --- a/arch/x86/kernel/traps_32.c
> +++ b/arch/x86/kernel/traps_32.c
> @@ -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"))) = { {{{ 0, 0 }}}, };
>
> asmlinkage void divide_error(void);
> asmlinkage void debug(void);
> diff --git a/include/asm-x86/desc_defs.h b/include/asm-x86/desc_defs.h
> index 0890040..b3db064 100644
> --- a/include/asm-x86/desc_defs.h
> +++ b/include/asm-x86/desc_defs.h
> @@ -11,18 +11,30 @@
>
> #include <linux/types.h>
>
> +/*
> + * FIXME: Acessing the desc_struct through its fields is more elegant,
> + * and should be the one valid thing to do. However, a lot of open code
> + * still touches the a and b acessors, and doing this allow us to do it
> + * incrementally. We keep the signature as a struct, rather than an union,
> + * so we can get rid of it transparently in the future -- glommer
> + */
> +#define raw_desc_struct struct { unsigned int a, b; }
> +#define detailed_desc_struct \
> + struct { \
> + 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;\
> + }
> +
> // 8 byte segment descriptor
> struct desc_struct {
> - 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;
> + union {
> + raw_desc_struct;
> + detailed_desc_struct;
> + };
> } __attribute__((packed));
>

Is it really necessary to use #defines? Couldn't you just define the
structures inline, or give them names?

J

2007-12-06 19:37:37

by Glauber Costa

[permalink] [raw]
Subject: Re: [PATCH 1/19] unify desc_struct

On Dec 6, 2007 5:24 PM, Jeremy Fitzhardinge <[email protected]> wrote:
>
> Glauber de Oliveira Costa wrote:
> > This patch aims to make the access of struct desc_struct variables
> > equal across architectures. In this patch, I unify the i386 and x86_64
> > versions under an anonymous union, keeping the way they are accessed
> > untouched (a and b for 32-bit code, individual bit-fields for 64-bit).
> >
> > This solution is not beautiful, but will allow us to integrate common
> > code that differed by the way descriptors were used. This is to be viewed
> > incrementally. There's simply too much code to be fixed at once.
> >
> > In the future, goal is to set up in a single way of acessing
> > the desc_struct fields.
> >
> > Signed-off-by: Glauber de Oliveira Costa <[email protected]>
> > ---
> > arch/x86/kernel/apm_32.c | 2 +-
> > arch/x86/kernel/cpu/common.c | 28 ++++++++++++++--------------
> > arch/x86/kernel/process_64.c | 2 +-
> > arch/x86/kernel/traps_32.c | 2 +-
> > include/asm-x86/desc_defs.h | 28 ++++++++++++++++++++--------
> > include/asm-x86/processor_32.h | 5 +----
> > 6 files changed, 38 insertions(+), 29 deletions(-)
> >
> > diff --git a/arch/x86/kernel/apm_32.c b/arch/x86/kernel/apm_32.c
> > index 8cd9778..b8b9339 100644
> > --- a/arch/x86/kernel/apm_32.c
> > +++ b/arch/x86/kernel/apm_32.c
> > @@ -405,7 +405,7 @@ static DECLARE_WAIT_QUEUE_HEAD(apm_waitqueue);
> > 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 = {{{ 0, 0x00409200 }}};
> >
> > static const char driver_version[] = "1.16ac"; /* no spaces */
> >
> > diff --git a/arch/x86/kernel/cpu/common.c b/arch/x86/kernel/cpu/common.c
> > index 235cd61..0fe1c1d 100644
> > --- a/arch/x86/kernel/cpu/common.c
> > +++ b/arch/x86/kernel/cpu/common.c
> > @@ -22,31 +22,31 @@
> > #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] = {{{ 0x0000ffff, 0x00cf9a00 }}},
> > + [GDT_ENTRY_KERNEL_DS] = {{{ 0x0000ffff, 0x00cf9200 }}},
> > + [GDT_ENTRY_DEFAULT_USER_CS] = {{{ 0x0000ffff, 0x00cffa00 }}},
> > + [GDT_ENTRY_DEFAULT_USER_DS] = {{{ 0x0000ffff, 0x00cff200 }}},
> >
>
> I don't suppose there's some way to make all this more symbolic?

There may be, but it's not the problem I'm trying to address in this
series. It's probably not too hard
to come up with a macro that receives the relevant parts of the
descriptors and create the initializers.

but it's deferred work.

>
>
> > /*
> > * 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 */
> > + [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 */
> > /*
> > * 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 */
> > + [GDT_ENTRY_APMBIOS_BASE] = {{{ 0x0000ffff, 0x00409a00 }}},/* 32-bit code */
> > /* 16-bit code */
> > - [GDT_ENTRY_APMBIOS_BASE+1] = { 0x0000ffff, 0x00009a00 },
> > - [GDT_ENTRY_APMBIOS_BASE+2] = { 0x0000ffff, 0x00409200 }, /* data */
> > + [GDT_ENTRY_APMBIOS_BASE+1] = {{{ 0x0000ffff, 0x00009a00 }}},
> > + [GDT_ENTRY_APMBIOS_BASE+2] = {{{ 0x0000ffff, 0x00409200 }}}, /* data */
> >
> > - [GDT_ENTRY_ESPFIX_SS] = { 0x00000000, 0x00c09200 },
> > - [GDT_ENTRY_PERCPU] = { 0x00000000, 0x00000000 },
> > + [GDT_ENTRY_ESPFIX_SS] = {{{ 0x00000000, 0x00c09200 }}},
> > + [GDT_ENTRY_PERCPU] = {{{ 0x00000000, 0x00000000 }}},
> > } };
> > EXPORT_PER_CPU_SYMBOL_GPL(gdt_page);
> >
> > diff --git a/arch/x86/kernel/process_64.c b/arch/x86/kernel/process_64.c
> > index 6724840..9e99cb7 100644
> > --- a/arch/x86/kernel/process_64.c
> > +++ b/arch/x86/kernel/process_64.c
> > @@ -437,7 +437,7 @@ static inline void set_32bit_tls(struct task_struct *t, int tls, u32 addr)
> > .limit_in_pages = 1,
> > .useable = 1,
> > };
> > - struct n_desc_struct *desc = (void *)t->thread.tls_array;
> > + struct desc_struct *desc = (void *)t->thread.tls_array;
> > desc += tls;
> > desc->a = LDT_entry_a(&ud);
> > desc->b = LDT_entry_b(&ud);
> > diff --git a/arch/x86/kernel/traps_32.c b/arch/x86/kernel/traps_32.c
> > index e15014e..94c5aea 100644
> > --- a/arch/x86/kernel/traps_32.c
> > +++ b/arch/x86/kernel/traps_32.c
> > @@ -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"))) = { {{{ 0, 0 }}}, };
> >
> > asmlinkage void divide_error(void);
> > asmlinkage void debug(void);
> > diff --git a/include/asm-x86/desc_defs.h b/include/asm-x86/desc_defs.h
> > index 0890040..b3db064 100644
> > --- a/include/asm-x86/desc_defs.h
> > +++ b/include/asm-x86/desc_defs.h
> > @@ -11,18 +11,30 @@
> >
> > #include <linux/types.h>
> >
> > +/*
> > + * FIXME: Acessing the desc_struct through its fields is more elegant,
> > + * and should be the one valid thing to do. However, a lot of open code
> > + * still touches the a and b acessors, and doing this allow us to do it
> > + * incrementally. We keep the signature as a struct, rather than an union,
> > + * so we can get rid of it transparently in the future -- glommer
> > + */
> > +#define raw_desc_struct struct { unsigned int a, b; }
> > +#define detailed_desc_struct \
> > + struct { \
> > + 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;\
> > + }
> > +
> > // 8 byte segment descriptor
> > struct desc_struct {
> > - 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;
> > + union {
> > + raw_desc_struct;
> > + detailed_desc_struct;
> > + };
> > } __attribute__((packed));
> >
>
> Is it really necessary to use #defines? Couldn't you just define the
> structures inline, or give them names?

No, it's not necessary. It's just the less ugly way I found.
As I intend to switch all uses to the field accesses, instead of a and
b, I don't think it's a big deal. When it's done, the struct will be
clean and simple, with no need for
these defines.



--
Glauber de Oliveira Costa.
"Free as in Freedom"
http://glommer.net

"The less confident you are, the more serious you have to act."

2007-12-06 20:54:56

by Andi Kleen

[permalink] [raw]
Subject: Re: [PATCH 1/19] unify desc_struct


> +/*
> + * FIXME: Acessing the desc_struct through its fields is more elegant,
> + * and should be the one valid thing to do. However, a lot of open code
> + * still touches the a and b acessors, and doing this allow us to do it
> + * incrementally. We keep the signature as a struct, rather than an union,
> + * so we can get rid of it transparently in the future -- glommer
> + */
> +#define raw_desc_struct struct { unsigned int a, b; }
> +#define detailed_desc_struct \
> + struct { \
> + 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;\
> + }

The standard clean way to do this is with a anonymous union.

-Andi

2007-12-06 21:20:53

by Glauber Costa

[permalink] [raw]
Subject: Re: [PATCH 1/19] unify desc_struct

On Dec 6, 2007 6:54 PM, Andi Kleen <[email protected]> wrote:
>
> > +/*
> > + * FIXME: Acessing the desc_struct through its fields is more elegant,
> > + * and should be the one valid thing to do. However, a lot of open code
> > + * still touches the a and b acessors, and doing this allow us to do it
> > + * incrementally. We keep the signature as a struct, rather than an union,
> > + * so we can get rid of it transparently in the future -- glommer
> > + */
> > +#define raw_desc_struct struct { unsigned int a, b; }
> > +#define detailed_desc_struct \
> > + struct { \
> > + 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;\
> > + }
>
> The standard clean way to do this is with a anonymous union.
It is an anonymous union.

However:

* It's an union of structs
* I wished to keep the toplevel type as a struct
The alternative would be to write:

struct desc_struct {
union {
struct { unsigned int a, b; };
struct {
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;
};
};
};

Which is fine, it's all the same in the end. Just with more shift
rights, and more visual pollution.


--
Glauber de Oliveira Costa.
"Free as in Freedom"
http://glommer.net

"The less confident you are, the more serious you have to act."

2007-12-06 22:03:34

by Jeremy Fitzhardinge

[permalink] [raw]
Subject: Re: [PATCH 1/19] unify desc_struct

Glauber de Oliveira Costa wrote:
> On Dec 6, 2007 6:54 PM, Andi Kleen <[email protected]> wrote:
>
>>> +/*
>>> + * FIXME: Acessing the desc_struct through its fields is more elegant,
>>> + * and should be the one valid thing to do. However, a lot of open code
>>> + * still touches the a and b acessors, and doing this allow us to do it
>>> + * incrementally. We keep the signature as a struct, rather than an union,
>>> + * so we can get rid of it transparently in the future -- glommer
>>> + */
>>> +#define raw_desc_struct struct { unsigned int a, b; }
>>> +#define detailed_desc_struct \
>>> + struct { \
>>> + 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;\
>>> + }
>>>
>> The standard clean way to do this is with a anonymous union.
>>
> It is an anonymous union.
>
> However:
>
> * It's an union of structs
> * I wished to keep the toplevel type as a struct
> The alternative would be to write:
>
> struct desc_struct {
> union {
> struct { unsigned int a, b; };
> struct {
> 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;
> };
> };
> };
>
> Which is fine, it's all the same in the end. Just with more shift
> rights, and more visual pollution.
>

No, that's much clearer. It's a pity that the anonymous struct/union
syntax isn't general enough to allow:

struct desc_packed {
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;
};

struct desc {
struct desc_packed;
};

J

2007-12-12 15:38:41

by Glauber Costa

[permalink] [raw]
Subject: [PATCH 0/19] desc_struct integration

Since the last version of it received no comments on the interfaces, here
it goes a version, that I feel ready for inclusion.

The comments regarding style, specially the elimination of the #defines in
the desc_struct definition were merged. I also implemented the vmi
functions,
missing last time.

Ingo, in the absense of further complaints, could you please push to the
x86 tree?

2007-12-12 15:38:59

by Glauber Costa

[permalink] [raw]
Subject: [PATCH 01/19] unify desc_struct

This patch aims to make the access of struct desc_struct variables
equal across architectures. In this patch, I unify the i386 and x86_64
versions under an anonymous union, keeping the way they are accessed
untouched (a and b for 32-bit code, individual bit-fields for 64-bit).

This solution is not beautiful, but will allow us to integrate common
code that differed by the way descriptors were used. This is to be viewed
incrementally. There's simply too much code to be fixed at once.

In the future, goal is to set up in a single way of acessing
the desc_struct fields.

Signed-off-by: Glauber de Oliveira Costa <[email protected]>
---
arch/x86/kernel/apm_32.c | 2 +-
arch/x86/kernel/cpu/common.c | 28 ++++++++++++++--------------
arch/x86/kernel/process_64.c | 2 +-
arch/x86/kernel/traps_32.c | 2 +-
include/asm-x86/desc_defs.h | 25 +++++++++++++++++--------
include/asm-x86/lguest.h | 4 ++--
include/asm-x86/processor_32.h | 5 +----
7 files changed, 37 insertions(+), 31 deletions(-)

Index: linux-2.6-x86/arch/x86/kernel/apm_32.c
===================================================================
--- linux-2.6-x86.orig/arch/x86/kernel/apm_32.c
+++ linux-2.6-x86/arch/x86/kernel/apm_32.c
@@ -405,7 +405,7 @@ static DECLARE_WAIT_QUEUE_HEAD(apm_waitq
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 = { { { 0, 0x00409200 } } };

static const char driver_version[] = "1.16ac"; /* no spaces */

Index: linux-2.6-x86/arch/x86/kernel/cpu/common.c
===================================================================
--- linux-2.6-x86.orig/arch/x86/kernel/cpu/common.c
+++ linux-2.6-x86/arch/x86/kernel/cpu/common.c
@@ -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] = { { { 0x0000ffff, 0x00cf9a00 } } },
+ [GDT_ENTRY_KERNEL_DS] = { { { 0x0000ffff, 0x00cf9200 } } },
+ [GDT_ENTRY_DEFAULT_USER_CS] = { { { 0x0000ffff, 0x00cffa00 } } },
+ [GDT_ENTRY_DEFAULT_USER_DS] = { { { 0x0000ffff, 0x00cff200 } } },
/*
* 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] = { { { 0x0000ffff, 0x00409a00 } } },
+ /* 16-bit code */
+ [GDT_ENTRY_PNPBIOS_CS16] = { { { 0x0000ffff, 0x00009a00 } } },
+ /* 16-bit data */
+ [GDT_ENTRY_PNPBIOS_DS] = { { { 0x0000ffff, 0x00009200 } } },
+ /* 16-bit data */
+ [GDT_ENTRY_PNPBIOS_TS1] = { { { 0x00000000, 0x00009200 } } },
+ /* 16-bit data */
+ [GDT_ENTRY_PNPBIOS_TS2] = { { { 0x00000000, 0x00009200 } } },
/*
* 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] = { { { 0x0000ffff, 0x00409a00 } } },
/* 16-bit code */
- [GDT_ENTRY_APMBIOS_BASE+1] = { 0x0000ffff, 0x00009a00 },
- [GDT_ENTRY_APMBIOS_BASE+2] = { 0x0000ffff, 0x00409200 }, /* data */
+ [GDT_ENTRY_APMBIOS_BASE+1] = { { { 0x0000ffff, 0x00009a00 } } },
+ /* data */
+ [GDT_ENTRY_APMBIOS_BASE+2] = { { { 0x0000ffff, 0x00409200 } } },

- [GDT_ENTRY_ESPFIX_SS] = { 0x00000000, 0x00c09200 },
- [GDT_ENTRY_PERCPU] = { 0x00000000, 0x00000000 },
+ [GDT_ENTRY_ESPFIX_SS] = { { { 0x00000000, 0x00c09200 } } },
+ [GDT_ENTRY_PERCPU] = { { { 0x00000000, 0x00000000 } } },
} };
EXPORT_PER_CPU_SYMBOL_GPL(gdt_page);

Index: linux-2.6-x86/arch/x86/kernel/process_64.c
===================================================================
--- linux-2.6-x86.orig/arch/x86/kernel/process_64.c
+++ linux-2.6-x86/arch/x86/kernel/process_64.c
@@ -444,7 +444,7 @@ static inline void set_32bit_tls(struct
.limit_in_pages = 1,
.useable = 1,
};
- struct n_desc_struct *desc = (void *)t->thread.tls_array;
+ struct desc_struct *desc = (void *)t->thread.tls_array;
desc += tls;
desc->a = LDT_entry_a(&ud);
desc->b = LDT_entry_b(&ud);
Index: linux-2.6-x86/arch/x86/kernel/traps_32.c
===================================================================
--- linux-2.6-x86.orig/arch/x86/kernel/traps_32.c
+++ linux-2.6-x86/arch/x86/kernel/traps_32.c
@@ -76,7 +76,8 @@ 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"))) = { { { { 0, 0 } } }, };

asmlinkage void divide_error(void);
asmlinkage void debug(void);
Index: linux-2.6-x86/include/asm-x86/desc_defs.h
===================================================================
--- linux-2.6-x86.orig/include/asm-x86/desc_defs.h
+++ linux-2.6-x86/include/asm-x86/desc_defs.h
@@ -11,17 +11,26 @@

#include <linux/types.h>

+/*
+ * FIXME: Acessing the desc_struct through its fields is more elegant,
+ * and should be the one valid thing to do. However, a lot of open code
+ * still touches the a and b acessors, and doing this allow us to do it
+ * incrementally. We keep the signature as a struct, rather than an union,
+ * so we can get rid of it transparently in the future -- glommer
+ */
// 8 byte segment descriptor
struct desc_struct {
- 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));
+ union {
+ struct { unsigned int a, b; };
+ struct {
+ 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;
+ };

-struct n_desc_struct {
- unsigned int a,b;
-};
+ };
+} __attribute__((packed));

enum {
GATE_INTERRUPT = 0xE,
Index: linux-2.6-x86/include/asm-x86/lguest.h
===================================================================
--- linux-2.6-x86.orig/include/asm-x86/lguest.h
+++ linux-2.6-x86/include/asm-x86/lguest.h
@@ -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 desc_struct){ { {0x0000ffff, 0x00cf9b00} } })
+#define FULL_SEGMENT ((struct desc_struct){ { {0x0000ffff, 0x00cf9300} } })

#endif /* __ASSEMBLY__ */

Index: linux-2.6-x86/include/asm-x86/processor_32.h
===================================================================
--- linux-2.6-x86.orig/include/asm-x86/processor_32.h
+++ linux-2.6-x86/include/asm-x86/processor_32.h
@@ -20,14 +20,11 @@
#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 int desc_empty(const void *ptr)
{
const u32 *desc = ptr;

2007-12-12 15:39:22

by Glauber Costa

[permalink] [raw]
Subject: [PATCH 02/19] unify struct desc_ptr

This patch unifies struct desc_ptr between i386 and x86_64.
They can be expressed in the exact same way in C code, only
having to change the name of one of them. As Xgt_desc_struct
is ugly and big, this is the one that goes away.

There's also a padding field in i386, but it is not really
needed in the C structure definition.

Signed-off-by: Glauber de Oliveira Costa <[email protected]>
---
arch/x86/kernel/asm-offsets_32.c | 5 ++---
arch/x86/kernel/cpu/common.c | 2 +-
arch/x86/kernel/doublefault_32.c | 2 +-
arch/x86/kernel/efi_32.c | 4 ++--
arch/x86/kernel/machine_kexec_32.c | 4 ++--
arch/x86/kernel/reboot_32.c | 2 +-
arch/x86/lguest/boot.c | 4 ++--
arch/x86/xen/enlighten.c | 10 +++++-----
drivers/kvm/svm.c | 2 +-
include/asm-x86/desc_32.h | 16 +++++-----------
include/asm-x86/lguest.h | 8 ++++----
include/asm-x86/paravirt.h | 18 +++++++++---------
include/asm-x86/processor_32.h | 2 +-
include/asm-x86/suspend_32.h | 4 ++--
14 files changed, 38 insertions(+), 45 deletions(-)

Index: linux-2.6-x86/arch/x86/kernel/asm-offsets_32.c
===================================================================
--- linux-2.6-x86.orig/arch/x86/kernel/asm-offsets_32.c
+++ linux-2.6-x86/arch/x86/kernel/asm-offsets_32.c
@@ -70,9 +70,8 @@ void foo(void)
OFFSET(TI_cpu, thread_info, cpu);
BLANK();

- OFFSET(GDS_size, Xgt_desc_struct, size);
- OFFSET(GDS_address, Xgt_desc_struct, address);
- OFFSET(GDS_pad, Xgt_desc_struct, pad);
+ OFFSET(GDS_size, desc_ptr, size);
+ OFFSET(GDS_address, desc_ptr, address);
BLANK();

OFFSET(PT_EBX, pt_regs, bx);
Index: linux-2.6-x86/arch/x86/kernel/cpu/common.c
===================================================================
--- linux-2.6-x86.orig/arch/x86/kernel/cpu/common.c
+++ linux-2.6-x86/arch/x86/kernel/cpu/common.c
@@ -649,7 +649,7 @@ struct pt_regs * __devinit idle_regs(str
* it's on the real one. */
void switch_to_new_gdt(void)
{
- struct Xgt_desc_struct gdt_descr;
+ struct desc_ptr gdt_descr;

gdt_descr.address = (long)get_cpu_gdt_table(smp_processor_id());
gdt_descr.size = GDT_SIZE - 1;
Index: linux-2.6-x86/arch/x86/kernel/doublefault_32.c
===================================================================
--- linux-2.6-x86.orig/arch/x86/kernel/doublefault_32.c
+++ linux-2.6-x86/arch/x86/kernel/doublefault_32.c
@@ -17,7 +17,7 @@ static unsigned long doublefault_stack[D

static void doublefault_fn(void)
{
- struct Xgt_desc_struct gdt_desc = {0, 0};
+ struct desc_ptr gdt_desc = {0, 0};
unsigned long gdt, tss;

store_gdt(&gdt_desc);
Index: linux-2.6-x86/arch/x86/kernel/efi_32.c
===================================================================
--- linux-2.6-x86.orig/arch/x86/kernel/efi_32.c
+++ linux-2.6-x86/arch/x86/kernel/efi_32.c
@@ -69,7 +69,7 @@ static void efi_call_phys_prelog(void) _
{
unsigned long cr4;
unsigned long temp;
- struct Xgt_desc_struct gdt_descr;
+ struct desc_ptr gdt_descr;

spin_lock(&efi_rt_lock);
local_irq_save(efi_rt_eflags);
@@ -111,7 +111,7 @@ static void efi_call_phys_prelog(void) _
static void efi_call_phys_epilog(void) __releases(efi_rt_lock)
{
unsigned long cr4;
- struct Xgt_desc_struct gdt_descr;
+ struct desc_ptr gdt_descr;

gdt_descr.address = (unsigned long)get_cpu_gdt_table(0);
gdt_descr.size = GDT_SIZE - 1;
Index: linux-2.6-x86/arch/x86/kernel/machine_kexec_32.c
===================================================================
--- linux-2.6-x86.orig/arch/x86/kernel/machine_kexec_32.c
+++ linux-2.6-x86/arch/x86/kernel/machine_kexec_32.c
@@ -32,7 +32,7 @@ static u32 kexec_pte1[1024] PAGE_ALIGNED

static void set_idt(void *newidt, __u16 limit)
{
- struct Xgt_desc_struct curidt;
+ struct desc_ptr curidt;

/* ia32 supports unaliged loads & stores */
curidt.size = limit;
@@ -44,7 +44,7 @@ static void set_idt(void *newidt, __u16

static void set_gdt(void *newgdt, __u16 limit)
{
- struct Xgt_desc_struct curgdt;
+ struct desc_ptr curgdt;

/* ia32 supports unaligned loads & stores */
curgdt.size = limit;
Index: linux-2.6-x86/arch/x86/kernel/reboot_32.c
===================================================================
--- linux-2.6-x86.orig/arch/x86/kernel/reboot_32.c
+++ linux-2.6-x86/arch/x86/kernel/reboot_32.c
@@ -161,7 +161,7 @@ real_mode_gdt_entries [3] =
0x000092000100ffffULL /* 16-bit real-mode 64k data at 0x00000100 */
};

-static struct Xgt_desc_struct
+static struct desc_ptr
real_mode_gdt = { sizeof (real_mode_gdt_entries) - 1, (long)real_mode_gdt_entries },
real_mode_idt = { 0x3ff, 0 },
no_idt = { 0, 0 };
Index: linux-2.6-x86/arch/x86/lguest/boot.c
===================================================================
--- linux-2.6-x86.orig/arch/x86/lguest/boot.c
+++ linux-2.6-x86/arch/x86/lguest/boot.c
@@ -229,7 +229,7 @@ static void lguest_write_idt_entry(struc
/* Changing to a different IDT is very rare: we keep the IDT up-to-date every
* time it is written, so we can simply loop through all entries and tell the
* Host about them. */
-static void lguest_load_idt(const struct Xgt_desc_struct *desc)
+static void lguest_load_idt(const struct desc_ptr *desc)
{
unsigned int i;
struct desc_struct *idt = (void *)desc->address;
@@ -252,7 +252,7 @@ static void lguest_load_idt(const struct
* hypercall and use that repeatedly to load a new IDT. I don't think it
* really matters, but wouldn't it be nice if they were the same?
*/
-static void lguest_load_gdt(const struct Xgt_desc_struct *desc)
+static void lguest_load_gdt(const struct desc_ptr *desc)
{
BUG_ON((desc->size+1)/8 != GDT_ENTRIES);
hcall(LHCALL_LOAD_GDT, __pa(desc->address), GDT_ENTRIES, 0);
Index: linux-2.6-x86/arch/x86/xen/enlighten.c
===================================================================
--- linux-2.6-x86.orig/arch/x86/xen/enlighten.c
+++ linux-2.6-x86/arch/x86/xen/enlighten.c
@@ -295,7 +295,7 @@ static void xen_set_ldt(const void *addr
xen_mc_issue(PARAVIRT_LAZY_CPU);
}

-static void xen_load_gdt(const struct Xgt_desc_struct *dtr)
+static void xen_load_gdt(const struct desc_ptr *dtr)
{
unsigned long *frames;
unsigned long va = dtr->address;
@@ -395,7 +395,7 @@ static int cvt_gate_to_trap(int vector,
}

/* Locations of each CPU's IDT */
-static DEFINE_PER_CPU(struct Xgt_desc_struct, idt_desc);
+static DEFINE_PER_CPU(struct desc_ptr, idt_desc);

/* Set an IDT entry. If the entry is part of the current IDT, then
also update Xen. */
@@ -427,7 +427,7 @@ static void xen_write_idt_entry(struct d
preempt_enable();
}

-static void xen_convert_trap_info(const struct Xgt_desc_struct *desc,
+static void xen_convert_trap_info(const struct desc_ptr *desc,
struct trap_info *traps)
{
unsigned in, out, count;
@@ -446,7 +446,7 @@ static void xen_convert_trap_info(const

void xen_copy_trap_info(struct trap_info *traps)
{
- const struct Xgt_desc_struct *desc = &__get_cpu_var(idt_desc);
+ const struct desc_ptr *desc = &__get_cpu_var(idt_desc);

xen_convert_trap_info(desc, traps);
}
@@ -454,7 +454,7 @@ void xen_copy_trap_info(struct trap_info
/* Load a new IDT into Xen. In principle this can be per-CPU, so we
hold a spinlock to protect the static traps[] array (static because
it avoids allocation, and saves stack space). */
-static void xen_load_idt(const struct Xgt_desc_struct *desc)
+static void xen_load_idt(const struct desc_ptr *desc)
{
static DEFINE_SPINLOCK(lock);
static struct trap_info traps[257];
Index: linux-2.6-x86/drivers/kvm/svm.c
===================================================================
--- linux-2.6-x86.orig/drivers/kvm/svm.c
+++ linux-2.6-x86/drivers/kvm/svm.c
@@ -290,7 +290,7 @@ static void svm_hardware_enable(void *ga
#ifdef CONFIG_X86_64
struct desc_ptr gdt_descr;
#else
- struct Xgt_desc_struct gdt_descr;
+ struct desc_ptr gdt_descr;
#endif
struct desc_struct *gdt;
int me = raw_smp_processor_id();
Index: linux-2.6-x86/include/asm-x86/desc_32.h
===================================================================
--- linux-2.6-x86.orig/include/asm-x86/desc_32.h
+++ linux-2.6-x86/include/asm-x86/desc_32.h
@@ -12,12 +12,6 @@

#include <asm/mmu.h>

-struct Xgt_desc_struct {
- unsigned short size;
- unsigned long address __attribute__((packed));
- unsigned short pad;
-} __attribute__ ((packed));
-
struct gdt_page
{
struct desc_struct gdt[GDT_ENTRIES];
@@ -29,7 +23,7 @@ static inline struct desc_struct *get_cp
return per_cpu(gdt_page, cpu).gdt;
}

-extern struct Xgt_desc_struct idt_descr;
+extern struct desc_ptr idt_descr;
extern struct desc_struct idt_table[];
extern void set_intr_gate(unsigned int irq, void * addr);

@@ -107,22 +101,22 @@ static inline void native_load_tr_desc(v
asm volatile("ltr %w0"::"q" (GDT_ENTRY_TSS*8));
}

-static inline void native_load_gdt(const struct Xgt_desc_struct *dtr)
+static inline void native_load_gdt(const struct desc_ptr *dtr)
{
asm volatile("lgdt %0"::"m" (*dtr));
}

-static inline void native_load_idt(const struct Xgt_desc_struct *dtr)
+static inline void native_load_idt(const struct desc_ptr *dtr)
{
asm volatile("lidt %0"::"m" (*dtr));
}

-static inline void native_store_gdt(struct Xgt_desc_struct *dtr)
+static inline void native_store_gdt(struct desc_ptr *dtr)
{
asm ("sgdt %0":"=m" (*dtr));
}

-static inline void native_store_idt(struct Xgt_desc_struct *dtr)
+static inline void native_store_idt(struct desc_ptr *dtr)
{
asm ("sidt %0":"=m" (*dtr));
}
Index: linux-2.6-x86/include/asm-x86/lguest.h
===================================================================
--- linux-2.6-x86.orig/include/asm-x86/lguest.h
+++ linux-2.6-x86/include/asm-x86/lguest.h
@@ -44,13 +44,13 @@ struct lguest_ro_state
{
/* Host information we need to restore when we switch back. */
u32 host_cr3;
- struct Xgt_desc_struct host_idt_desc;
- struct Xgt_desc_struct host_gdt_desc;
+ struct desc_ptr host_idt_desc;
+ struct desc_ptr host_gdt_desc;
u32 host_sp;

/* Fields which are used when guest is running. */
- struct Xgt_desc_struct guest_idt_desc;
- struct Xgt_desc_struct guest_gdt_desc;
+ struct desc_ptr guest_idt_desc;
+ struct desc_ptr guest_gdt_desc;
struct i386_hw_tss guest_tss;
struct desc_struct guest_idt[IDT_ENTRIES];
struct desc_struct guest_gdt[GDT_ENTRIES];
Index: linux-2.6-x86/include/asm-x86/paravirt.h
===================================================================
--- linux-2.6-x86.orig/include/asm-x86/paravirt.h
+++ linux-2.6-x86/include/asm-x86/paravirt.h
@@ -20,7 +20,7 @@

struct page;
struct thread_struct;
-struct Xgt_desc_struct;
+struct desc_ptr;
struct tss_struct;
struct mm_struct;
struct desc_struct;
@@ -88,10 +88,10 @@ struct pv_cpu_ops {

/* Segment descriptor handling */
void (*load_tr_desc)(void);
- void (*load_gdt)(const struct Xgt_desc_struct *);
- void (*load_idt)(const struct Xgt_desc_struct *);
- void (*store_gdt)(struct Xgt_desc_struct *);
- void (*store_idt)(struct Xgt_desc_struct *);
+ void (*load_gdt)(const struct desc_ptr *);
+ void (*load_idt)(const struct desc_ptr *);
+ void (*store_gdt)(struct desc_ptr *);
+ void (*store_idt)(struct desc_ptr *);
void (*set_ldt)(const void *desc, unsigned entries);
unsigned long (*store_tr)(void);
void (*load_tls)(struct thread_struct *t, unsigned int cpu);
@@ -630,11 +630,11 @@ static inline void load_TR_desc(void)
{
PVOP_VCALL0(pv_cpu_ops.load_tr_desc);
}
-static inline void load_gdt(const struct Xgt_desc_struct *dtr)
+static inline void load_gdt(const struct desc_ptr *dtr)
{
PVOP_VCALL1(pv_cpu_ops.load_gdt, dtr);
}
-static inline void load_idt(const struct Xgt_desc_struct *dtr)
+static inline void load_idt(const struct desc_ptr *dtr)
{
PVOP_VCALL1(pv_cpu_ops.load_idt, dtr);
}
@@ -642,11 +642,11 @@ static inline void set_ldt(const void *a
{
PVOP_VCALL2(pv_cpu_ops.set_ldt, addr, entries);
}
-static inline void store_gdt(struct Xgt_desc_struct *dtr)
+static inline void store_gdt(struct desc_ptr *dtr)
{
PVOP_VCALL1(pv_cpu_ops.store_gdt, dtr);
}
-static inline void store_idt(struct Xgt_desc_struct *dtr)
+static inline void store_idt(struct desc_ptr *dtr)
{
PVOP_VCALL1(pv_cpu_ops.store_idt, dtr);
}
Index: linux-2.6-x86/include/asm-x86/processor_32.h
===================================================================
--- linux-2.6-x86.orig/include/asm-x86/processor_32.h
+++ linux-2.6-x86/include/asm-x86/processor_32.h
@@ -707,7 +707,7 @@ extern void enable_sep_cpu(void);
extern int sysenter_setup(void);

/* Defined in head.S */
-extern struct Xgt_desc_struct early_gdt_descr;
+extern struct desc_ptr early_gdt_descr;

extern void cpu_set_gdt(int);
extern void switch_to_new_gdt(void);
Index: linux-2.6-x86/include/asm-x86/suspend_32.h
===================================================================
--- linux-2.6-x86.orig/include/asm-x86/suspend_32.h
+++ linux-2.6-x86/include/asm-x86/suspend_32.h
@@ -12,8 +12,8 @@ static inline int arch_prepare_suspend(v
struct saved_context {
u16 es, fs, gs, ss;
unsigned long cr0, cr2, cr3, cr4;
- struct Xgt_desc_struct gdt;
- struct Xgt_desc_struct idt;
+ struct desc_ptr gdt;
+ struct desc_ptr idt;
u16 ldt;
u16 tss;
unsigned long tr;

2007-12-12 15:39:37

by Glauber Costa

[permalink] [raw]
Subject: [PATCH 03/19] change gdt acessor macro name

This patch changes the name of x86_64 macro used to access the per-cpu
gdt. It is now equal to the i386 version, which will allow code to be shared.

Signed-off-by: Glauber de Oliveira Costa <[email protected]>
---
arch/x86/kernel/setup64.c | 2 +-
arch/x86/kernel/suspend_64.c | 2 +-
arch/x86/kernel/vsyscall_64.c | 2 +-
include/asm-x86/desc_64.h | 10 +++++-----
4 files changed, 8 insertions(+), 8 deletions(-)

Index: linux-2.6-x86/arch/x86/kernel/setup64.c
===================================================================
--- linux-2.6-x86.orig/arch/x86/kernel/setup64.c
+++ linux-2.6-x86/arch/x86/kernel/setup64.c
@@ -228,7 +228,7 @@ void __cpuinit cpu_init (void)
* and set up the GDT descriptor:
*/
if (cpu)
- memcpy(cpu_gdt(cpu), cpu_gdt_table, GDT_SIZE);
+ memcpy(get_cpu_gdt_table(cpu), cpu_gdt_table, GDT_SIZE);

cpu_gdt_descr[cpu].size = GDT_SIZE;
load_gdt((const struct desc_ptr *)&cpu_gdt_descr[cpu]);
Index: linux-2.6-x86/arch/x86/kernel/suspend_64.c
===================================================================
--- linux-2.6-x86.orig/arch/x86/kernel/suspend_64.c
+++ linux-2.6-x86/arch/x86/kernel/suspend_64.c
@@ -118,7 +118,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;
+ get_cpu_gdt_table(cpu)[GDT_ENTRY_TSS].type = 9;

syscall_init(); /* This sets MSR_*STAR and related */
load_TR_desc(); /* This does ltr */
Index: linux-2.6-x86/arch/x86/kernel/vsyscall_64.c
===================================================================
--- linux-2.6-x86.orig/arch/x86/kernel/vsyscall_64.c
+++ linux-2.6-x86/arch/x86/kernel/vsyscall_64.c
@@ -297,7 +297,7 @@ static void __cpuinit vsyscall_set_cpu(i
/* Store cpu number in limit so that it can be loaded quickly
in user space in vgetcpu.
12 bits for the CPU and 8 bits for the node. */
- d = (unsigned long *)(cpu_gdt(cpu) + GDT_ENTRY_PER_CPU);
+ d = (unsigned long *)(get_cpu_gdt_table(cpu) + GDT_ENTRY_PER_CPU);
*d = 0x0f40000000000ULL;
*d |= cpu;
*d |= (node & 0xf) << 12;
Index: linux-2.6-x86/include/asm-x86/desc_64.h
===================================================================
--- linux-2.6-x86.orig/include/asm-x86/desc_64.h
+++ linux-2.6-x86/include/asm-x86/desc_64.h
@@ -48,7 +48,7 @@ static inline void write_ldt_entry(struc
}

/* the cpu gdt accessor */
-#define cpu_gdt(_cpu) ((struct desc_struct *)cpu_gdt_descr[_cpu].address)
+#define get_cpu_gdt_table(x) ((struct desc_struct *)cpu_gdt_descr[x].address)

static inline void load_gdt(const struct desc_ptr *ptr)
{
@@ -141,15 +141,15 @@ static inline void set_tss_desc(unsigned
* -1? seg base+limit should be pointing to the address of the
* last valid byte
*/
- set_tssldt_descriptor(&cpu_gdt(cpu)[GDT_ENTRY_TSS],
+ set_tssldt_descriptor(&get_cpu_gdt_table(cpu)[GDT_ENTRY_TSS],
(unsigned long)addr, DESC_TSS,
IO_BITMAP_OFFSET + IO_BITMAP_BYTES + sizeof(unsigned long) - 1);
}

static inline void set_ldt_desc(unsigned cpu, void *addr, int size)
{
- set_tssldt_descriptor(&cpu_gdt(cpu)[GDT_ENTRY_LDT], (unsigned long)addr,
- DESC_LDT, size * 8 - 1);
+ set_tssldt_descriptor(&get_cpu_gdt_table(cpu)[GDT_ENTRY_LDT],
+ (unsigned long)addr, DESC_LDT, size * 8 - 1);
}

#define LDT_entry_a(info) \
@@ -183,7 +183,7 @@ static inline void set_ldt_desc(unsigned
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);
+ u64 *gdt = (u64 *)(get_cpu_gdt_table(cpu) + GDT_ENTRY_TLS_MIN);

for (i = 0; i < GDT_ENTRY_TLS_ENTRIES; i++)
gdt[i] = t->tls_array[i];

2007-12-12 15:39:53

by Glauber Costa

[permalink] [raw]
Subject: [PATCH 07/19] introduce ldt_desc type.

this patch introduces ldt_desc type to account for the differences
in the ldt descriptor in x86_64 and i386

Signed-off-by: Glauber de Oliveira Costa <[email protected]>
---
include/asm-x86/desc_64.h | 2 +-
include/asm-x86/desc_defs.h | 4 +++-
2 files changed, 4 insertions(+), 2 deletions(-)

diff --git a/include/asm-x86/desc_64.h b/include/asm-x86/desc_64.h
index ffc6c06..8fe1b4c 100644
--- a/include/asm-x86/desc_64.h
+++ b/include/asm-x86/desc_64.h
@@ -113,7 +113,7 @@ static inline void store_idt(struct desc_ptr *dtr)
static inline void set_tssldt_descriptor(void *ptr, unsigned long tss,
unsigned type, unsigned size)
{
- struct ldttss_desc d;
+ struct ldttss_desc64 d;

memset(&d, 0, sizeof(d));
d.limit0 = size & 0xFFFF;
diff --git a/include/asm-x86/desc_defs.h b/include/asm-x86/desc_defs.h
index 05eff93..5a58fc1 100644
--- a/include/asm-x86/desc_defs.h
+++ b/include/asm-x86/desc_defs.h
@@ -58,7 +58,7 @@ enum {
};

// LDT or TSS descriptor in the GDT. 16 bytes.
-struct ldttss_desc {
+struct ldttss_desc64 {
u16 limit0;
u16 base0;
unsigned base1 : 8, type : 5, dpl : 2, p : 1;
@@ -69,8 +69,10 @@ struct ldttss_desc {

#ifdef CONFIG_X86_64
typedef struct gate_struct64 gate_desc;
+typedef struct ldttss_desc64 ldt_desc;
#else
typedef struct desc_struct gate_desc;
+typedef struct desc_struct ldt_desc;
#endif

struct desc_ptr {
--
1.5.0.6

2007-12-12 15:40:25

by Glauber Costa

[permalink] [raw]
Subject: [PATCH 04/19] removed unused variable

This variable is not used anywere, and is then removed

Signed-off-by: Glauber de Oliveira Costa <[email protected]>
---
include/asm-x86/desc_64.h | 5 -----
1 files changed, 0 insertions(+), 5 deletions(-)

diff --git a/include/asm-x86/desc_64.h b/include/asm-x86/desc_64.h
index 1c26dbb..660cc84 100644
--- a/include/asm-x86/desc_64.h
+++ b/include/asm-x86/desc_64.h
@@ -30,11 +30,6 @@ static inline unsigned long __store_tr(void)

#define store_tr(tr) (tr) = __store_tr()

-/*
- * This is the ldt that every process will get unless we need
- * something other than this.
- */
-extern struct desc_struct default_ldt[];
extern struct gate_struct idt_table[];
extern struct desc_ptr cpu_gdt_descr[];

--
1.5.0.6

2007-12-12 15:40:46

by Glauber Costa

[permalink] [raw]
Subject: [PATCH 05/19] introduce gate_desc type.

To account for the differences in gate descriptor in i386 and x86_64
a gate_desc type is introduced.

Signed-off-by: Glauber de Oliveira Costa <[email protected]>
---
arch/x86/kernel/traps_32.c | 3 ++-
include/asm-x86/desc_32.h | 15 ++++++++-------
include/asm-x86/desc_64.h | 4 ++--
include/asm-x86/desc_defs.h | 8 +++++++-
4 files changed, 19 insertions(+), 11 deletions(-)

diff --git a/arch/x86/kernel/traps_32.c b/arch/x86/kernel/traps_32.c
index 94c5aea..6b03d88 100644
--- a/arch/x86/kernel/traps_32.c
+++ b/arch/x86/kernel/traps_32.c
@@ -76,8 +76,8 @@ 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 } } }, };
+gate_desc idt_table[256]
+ __attribute__((__section__(".data.idt"))) = { { { { 0, 0 } } }, };

asmlinkage void divide_error(void);
asmlinkage void debug(void);
diff --git a/include/asm-x86/desc_32.h b/include/asm-x86/desc_32.h
index bc5ca34..77f1e5a 100644
--- a/include/asm-x86/desc_32.h
+++ b/include/asm-x86/desc_32.h
@@ -3,6 +3,7 @@

#include <asm/ldt.h>
#include <asm/segment.h>
+#include <asm/desc_defs.h>

#ifndef __ASSEMBLY__

@@ -24,7 +25,7 @@ static inline struct desc_struct *get_cpu_gdt_table(unsigned int cpu)
}

extern struct desc_ptr idt_descr;
-extern struct desc_struct idt_table[];
+extern gate_desc idt_table[];
extern void set_intr_gate(unsigned int irq, void * addr);

static inline void pack_descriptor(__u32 *a, __u32 *b,
@@ -35,11 +36,11 @@ static inline void pack_descriptor(__u32 *a, __u32 *b,
(limit & 0x000f0000) | ((type & 0xff) << 8) | ((flags & 0xf) << 20);
}

-static inline void pack_gate(__u32 *a, __u32 *b,
+static inline void pack_gate(gate_desc *gate,
unsigned long base, unsigned short seg, unsigned char type, unsigned char flags)
{
- *a = (seg << 16) | (base & 0xffff);
- *b = (base & 0xffff0000) | ((type & 0xff) << 8) | (flags & 0xff);
+ gate->a = (seg << 16) | (base & 0xffff);
+ gate->b = (base & 0xffff0000) | ((type & 0xff) << 8) | (flags & 0xff);
}

#define DESCTYPE_LDT 0x82 /* present, system, DPL-0, LDT */
@@ -139,9 +140,9 @@ static inline void native_load_tls(struct thread_struct *t, unsigned int cpu)

static inline void _set_gate(int gate, unsigned int type, void *addr, unsigned short seg)
{
- __u32 a, b;
- pack_gate(&a, &b, (unsigned long)addr, seg, type, 0);
- write_idt_entry(idt_table, gate, a, b);
+ gate_desc g;
+ pack_gate(&g, (unsigned long)addr, seg, type, 0);
+ write_idt_entry(idt_table, gate, g.a, g.b);
}

static inline void __set_tss_desc(unsigned int cpu, unsigned int entry, const void *addr)
diff --git a/include/asm-x86/desc_64.h b/include/asm-x86/desc_64.h
index 660cc84..ffc6c06 100644
--- a/include/asm-x86/desc_64.h
+++ b/include/asm-x86/desc_64.h
@@ -30,7 +30,7 @@ static inline unsigned long __store_tr(void)

#define store_tr(tr) (tr) = __store_tr()

-extern struct gate_struct idt_table[];
+extern gate_desc idt_table[];
extern struct desc_ptr cpu_gdt_descr[];

static inline void write_ldt_entry(struct desc_struct *ldt,
@@ -58,7 +58,7 @@ static inline void store_gdt(struct desc_ptr *ptr)
static inline void _set_gate(void *adr, unsigned type, unsigned long func,
unsigned dpl, unsigned ist)
{
- struct gate_struct s;
+ gate_desc s;

s.offset_low = PTR_LOW(func);
s.segment = __KERNEL_CS;
diff --git a/include/asm-x86/desc_defs.h b/include/asm-x86/desc_defs.h
index f37b44c..05eff93 100644
--- a/include/asm-x86/desc_defs.h
+++ b/include/asm-x86/desc_defs.h
@@ -39,7 +39,7 @@ enum {
};

// 16byte gate
-struct gate_struct {
+struct gate_struct64 {
u16 offset_low;
u16 segment;
unsigned ist : 3, zero0 : 5, type : 5, dpl : 2, p : 1;
@@ -67,6 +67,12 @@ struct ldttss_desc {
u32 zero1;
} __attribute__((packed));

+#ifdef CONFIG_X86_64
+typedef struct gate_struct64 gate_desc;
+#else
+typedef struct desc_struct gate_desc;
+#endif
+
struct desc_ptr {
unsigned short size;
unsigned long address;
--
1.5.0.6

2007-12-12 15:41:00

by Glauber Costa

[permalink] [raw]
Subject: [PATCH 06/19] change write_idt_entry signature

this patch changes write_idt_entry signature. It now takes a gate_desc
instead of the a and b parameters. It will allow it to be later unified
between i386 and x86_64.

Signed-off-by: Glauber de Oliveira Costa <[email protected]>
CC: Zachary Amsden <[email protected]>
CC: Jeremy Fitzhardinge <Jeremy.Fitzhardinge.citrix.com>
---
arch/x86/kernel/paravirt_32.c | 2 +-
arch/x86/kernel/vmi_32.c | 10 +++++++++-
arch/x86/lguest/boot.c | 9 +++++----
arch/x86/xen/enlighten.c | 8 ++++----
include/asm-x86/desc_32.h | 10 ++++++++--
include/asm-x86/paravirt.h | 9 +++++----
6 files changed, 32 insertions(+), 16 deletions(-)

diff --git a/arch/x86/kernel/paravirt_32.c b/arch/x86/kernel/paravirt_32.c
index f4e3a8e..13bbc99 100644
--- a/arch/x86/kernel/paravirt_32.c
+++ b/arch/x86/kernel/paravirt_32.c
@@ -381,7 +381,7 @@ struct pv_cpu_ops pv_cpu_ops = {
.load_tls = native_load_tls,
.write_ldt_entry = write_dt_entry,
.write_gdt_entry = write_dt_entry,
- .write_idt_entry = write_dt_entry,
+ .write_idt_entry = native_write_idt_entry,
.load_sp0 = native_load_sp0,

.irq_enable_syscall_ret = native_irq_enable_syscall_ret,
diff --git a/arch/x86/kernel/vmi_32.c b/arch/x86/kernel/vmi_32.c
index 4cfda7d..a635b22 100644
--- a/arch/x86/kernel/vmi_32.c
+++ b/arch/x86/kernel/vmi_32.c
@@ -62,6 +62,7 @@ static struct {
void (*cpuid)(void /* non-c */);
void (*_set_ldt)(u32 selector);
void (*set_tr)(u32 selector);
+ void (*write_idt_entry)(struct desc_struct *, int, u32, u32);
void (*set_kernel_stack)(u32 selector, u32 sp0);
void (*allocate_page)(u32, u32, u32, u32, u32);
void (*release_page)(u32, u32);
@@ -214,6 +215,12 @@ static void vmi_set_tr(void)
vmi_ops.set_tr(GDT_ENTRY_TSS*sizeof(struct desc_struct));
}

+static void vmi_write_idt_entry(gate_desc *dt, int entry, const gate_desc *g)
+{
+ u32 *idt_entry = (u32 *)g;
+ vmi_ops.write_idt_entry(dt, entry, idt_entry[0], idt_entry[2]);
+}
+
static void vmi_load_sp0(struct tss_struct *tss,
struct thread_struct *thread)
{
@@ -792,7 +799,8 @@ static inline int __init activate_vmi(void)
pv_cpu_ops.load_tls = vmi_load_tls;
para_fill(pv_cpu_ops.write_ldt_entry, WriteLDTEntry);
para_fill(pv_cpu_ops.write_gdt_entry, WriteGDTEntry);
- para_fill(pv_cpu_ops.write_idt_entry, WriteIDTEntry);
+ para_wrap(pv_cpu_ops.write_idt_entry, vmi_write_idt_entry,
+ write_idt_entry, WriteIDTEntry);
para_wrap(pv_cpu_ops.load_sp0, vmi_load_sp0, set_kernel_stack, UpdateKernelStack);
para_fill(pv_cpu_ops.set_iopl_mask, SetIOPLMask);
para_fill(pv_cpu_ops.io_delay, IODelay);
diff --git a/arch/x86/lguest/boot.c b/arch/x86/lguest/boot.c
index aa0bdd5..b50c8ad 100644
--- a/arch/x86/lguest/boot.c
+++ b/arch/x86/lguest/boot.c
@@ -217,13 +217,14 @@ static void irq_enable(void)
* address of the handler, and... well, who cares? The Guest just asks the
* Host to make the change anyway, because the Host controls the real IDT.
*/
-static void lguest_write_idt_entry(struct desc_struct *dt,
- int entrynum, u32 low, u32 high)
+static void lguest_write_idt_entry(gate_desc *dt,
+ int entrynum, const gate_desc *g)
{
+ u32 *desc = (u32 *)g;
/* Keep the local copy up to date. */
- write_dt_entry(dt, entrynum, low, high);
+ native_write_idt_entry(dt, entrynum, g);
/* Tell Host about this new entry. */
- hcall(LHCALL_LOAD_IDT_ENTRY, entrynum, low, high);
+ hcall(LHCALL_LOAD_IDT_ENTRY, entrynum, desc[0], desc[1]);
}

/* Changing to a different IDT is very rare: we keep the IDT up-to-date every
diff --git a/arch/x86/xen/enlighten.c b/arch/x86/xen/enlighten.c
index 8215ea6..6dd349e 100644
--- a/arch/x86/xen/enlighten.c
+++ b/arch/x86/xen/enlighten.c
@@ -399,8 +399,7 @@ static DEFINE_PER_CPU(struct desc_ptr, idt_desc);

/* Set an IDT entry. If the entry is part of the current IDT, then
also update Xen. */
-static void xen_write_idt_entry(struct desc_struct *dt, int entrynum,
- u32 low, u32 high)
+static void xen_write_idt_entry(gate_desc *dt, int entrynum, const gate_desc *g)
{
unsigned long p = (unsigned long)&dt[entrynum];
unsigned long start, end;
@@ -412,14 +411,15 @@ static void xen_write_idt_entry(struct desc_struct *dt, int entrynum,

xen_mc_flush();

- write_dt_entry(dt, entrynum, low, high);
+ native_write_idt_entry(dt, entrynum, g);

if (p >= start && (p + 8) <= end) {
struct trap_info info[2];
+ u32 *desc = (u32 *)g;

info[1].address = 0;

- if (cvt_gate_to_trap(entrynum, low, high, &info[0]))
+ if (cvt_gate_to_trap(entrynum, desc[0], desc[1], &info[0]))
if (HYPERVISOR_set_trap_table(info))
BUG();
}
diff --git a/include/asm-x86/desc_32.h b/include/asm-x86/desc_32.h
index 77f1e5a..54b2314 100644
--- a/include/asm-x86/desc_32.h
+++ b/include/asm-x86/desc_32.h
@@ -70,9 +70,15 @@ static inline void pack_gate(gate_desc *gate,

#define write_ldt_entry(dt, entry, a, b) write_dt_entry(dt, entry, a, b)
#define write_gdt_entry(dt, entry, a, b) write_dt_entry(dt, entry, a, b)
-#define write_idt_entry(dt, entry, a, b) write_dt_entry(dt, entry, a, b)
+#define write_idt_entry(dt, entry, g) native_write_idt_entry(dt, entry, g)
#endif

+static inline void native_write_idt_entry(gate_desc *idt, int entry,
+ const gate_desc *gate)
+{
+ memcpy(&idt[entry], gate, sizeof(*gate));
+}
+
static inline void write_dt_entry(struct desc_struct *dt,
int entry, u32 entry_low, u32 entry_high)
{
@@ -142,7 +148,7 @@ static inline void _set_gate(int gate, unsigned int type, void *addr, unsigned s
{
gate_desc g;
pack_gate(&g, (unsigned long)addr, seg, type, 0);
- write_idt_entry(idt_table, gate, g.a, g.b);
+ write_idt_entry(idt_table, gate, &g);
}

static inline void __set_tss_desc(unsigned int cpu, unsigned int entry, const void *addr)
diff --git a/include/asm-x86/paravirt.h b/include/asm-x86/paravirt.h
index 0333fb6..86a9d7b 100644
--- a/include/asm-x86/paravirt.h
+++ b/include/asm-x86/paravirt.h
@@ -17,6 +17,7 @@
#include <linux/types.h>
#include <linux/cpumask.h>
#include <asm/kmap_types.h>
+#include <asm/desc_defs.h>

struct page;
struct thread_struct;
@@ -99,8 +100,8 @@ struct pv_cpu_ops {
int entrynum, u32 low, u32 high);
void (*write_gdt_entry)(struct desc_struct *,
int entrynum, u32 low, u32 high);
- void (*write_idt_entry)(struct desc_struct *,
- int entrynum, u32 low, u32 high);
+ void (*write_idt_entry)(gate_desc *,
+ int entrynum, const gate_desc *gate);
void (*load_sp0)(struct tss_struct *tss, struct thread_struct *t);

void (*set_iopl_mask)(unsigned mask);
@@ -667,9 +668,9 @@ static inline void write_gdt_entry(void *dt, int entry, u32 low, u32 high)
{
PVOP_VCALL4(pv_cpu_ops.write_gdt_entry, dt, entry, low, high);
}
-static inline void write_idt_entry(void *dt, int entry, u32 low, u32 high)
+static inline void write_idt_entry(gate_desc *dt, int entry, const gate_desc *g)
{
- PVOP_VCALL4(pv_cpu_ops.write_idt_entry, dt, entry, low, high);
+ PVOP_VCALL3(pv_cpu_ops.write_idt_entry, dt, entry, g);
}
static inline void set_iopl_mask(unsigned mask)
{
--
1.5.0.6

2007-12-12 15:41:22

by Glauber Costa

[permalink] [raw]
Subject: [PATCH 08/19] modify write_ldt function

This patch modifies the write_ldt() function to make use
of the new struct desc_struct instead of entry_1 and entry_2
entries

Signed-off-by: Glauber de Oliveira Costa <[email protected]>
---
arch/x86/kernel/ldt.c | 15 +++++++--------
1 files changed, 7 insertions(+), 8 deletions(-)

diff --git a/arch/x86/kernel/ldt.c b/arch/x86/kernel/ldt.c
index a8cdca3..7eb0c8a 100644
--- a/arch/x86/kernel/ldt.c
+++ b/arch/x86/kernel/ldt.c
@@ -186,7 +186,7 @@ static int read_default_ldt(void __user *ptr, unsigned long bytecount)
static int write_ldt(void __user *ptr, unsigned long bytecount, int oldmode)
{
struct mm_struct *mm = current->mm;
- __u32 entry_1, entry_2;
+ struct desc_struct ldt;
int error;
struct user_desc ldt_info;

@@ -218,21 +218,20 @@ static int write_ldt(void __user *ptr, unsigned long bytecount, int oldmode)
/* Allow LDTs to be cleared by the user. */
if (ldt_info.base_addr == 0 && ldt_info.limit == 0) {
if (oldmode || LDT_empty(&ldt_info)) {
- entry_1 = 0;
- entry_2 = 0;
+ memset(&ldt, 0, sizeof(ldt));
goto install;
}
}

- entry_1 = LDT_entry_a(&ldt_info);
- entry_2 = LDT_entry_b(&ldt_info);
+ ldt.a = LDT_entry_a(&ldt_info);
+ ldt.b = LDT_entry_b(&ldt_info);
if (oldmode)
- entry_2 &= ~(1 << 20);
+ ldt.avl = 0;

/* Install the new entry ... */
install:
- write_ldt_entry(mm->context.ldt, ldt_info.entry_number, entry_1,
- entry_2);
+ write_ldt_entry(mm->context.ldt, ldt_info.entry_number,
+ ldt.a, ldt.b);
error = 0;

out_unlock:
--
1.5.0.6

2007-12-12 15:41:38

by Glauber Costa

[permalink] [raw]
Subject: [PATCH 09/19] introduce fill_ldt

This patch introduces fill_ldt(), which populates a ldt descriptor
from a user_desc in once, instead of relying in the LDT_entry_a and
LDT_entry_b macros

Signed-off-by: Glauber de Oliveira Costa <[email protected]>
---
arch/x86/kernel/ldt.c | 3 +--
arch/x86/kernel/process_64.c | 3 +--
arch/x86/kernel/tls.c | 7 +++----
include/asm-x86/desc_32.h | 15 ---------------
include/asm-x86/desc_64.h | 17 -----------------
include/asm-x86/ldt.h | 19 +++++++++++++++++++
6 files changed, 24 insertions(+), 40 deletions(-)

diff --git a/arch/x86/kernel/ldt.c b/arch/x86/kernel/ldt.c
index 7eb0c8a..3e872b4 100644
--- a/arch/x86/kernel/ldt.c
+++ b/arch/x86/kernel/ldt.c
@@ -223,8 +223,7 @@ static int write_ldt(void __user *ptr, unsigned long bytecount, int oldmode)
}
}

- ldt.a = LDT_entry_a(&ldt_info);
- ldt.b = LDT_entry_b(&ldt_info);
+ fill_ldt(&ldt, &ldt_info);
if (oldmode)
ldt.avl = 0;

diff --git a/arch/x86/kernel/process_64.c b/arch/x86/kernel/process_64.c
index e09d9f1..abf32e3 100644
--- a/arch/x86/kernel/process_64.c
+++ b/arch/x86/kernel/process_64.c
@@ -446,8 +446,7 @@ static inline void set_32bit_tls(struct task_struct *t, int tls, u32 addr)
};
struct desc_struct *desc = (void *)t->thread.tls_array;
desc += tls;
- desc->a = LDT_entry_a(&ud);
- desc->b = LDT_entry_b(&ud);
+ fill_ldt(desc, &ud);
}

static inline u32 read_32bit_tls(struct task_struct *t, int tls)
diff --git a/arch/x86/kernel/tls.c b/arch/x86/kernel/tls.c
index 67a3776..74d2b65 100644
--- a/arch/x86/kernel/tls.c
+++ b/arch/x86/kernel/tls.c
@@ -67,10 +67,9 @@ int do_set_thread_area(struct task_struct *p, int idx,
if (LDT_empty(&info)) {
desc[0] = 0;
desc[1] = 0;
- } else {
- desc[0] = LDT_entry_a(&info);
- desc[1] = LDT_entry_b(&info);
- }
+ } else
+ fill_ldt((struct desc_struct *)desc, &info);
+
if (t == &current->thread)
load_TLS(t, cpu);

diff --git a/include/asm-x86/desc_32.h b/include/asm-x86/desc_32.h
index 54b2314..0370099 100644
--- a/include/asm-x86/desc_32.h
+++ b/include/asm-x86/desc_32.h
@@ -163,21 +163,6 @@ static inline void __set_tss_desc(unsigned int cpu, unsigned int entry, const vo

#define set_tss_desc(cpu,addr) __set_tss_desc(cpu, GDT_ENTRY_TSS, addr)

-#define LDT_entry_a(info) \
- ((((info)->base_addr & 0x0000ffff) << 16) | ((info)->limit & 0x0ffff))
-
-#define LDT_entry_b(info) \
- (((info)->base_addr & 0xff000000) | \
- (((info)->base_addr & 0x00ff0000) >> 16) | \
- ((info)->limit & 0xf0000) | \
- (((info)->read_exec_only ^ 1) << 9) | \
- ((info)->contents << 10) | \
- (((info)->seg_not_present ^ 1) << 15) | \
- ((info)->seg_32bit << 22) | \
- ((info)->limit_in_pages << 23) | \
- ((info)->useable << 20) | \
- 0x7000)
-
#define LDT_empty(info) (\
(info)->base_addr == 0 && \
(info)->limit == 0 && \
diff --git a/include/asm-x86/desc_64.h b/include/asm-x86/desc_64.h
index 8fe1b4c..e0aa4bc 100644
--- a/include/asm-x86/desc_64.h
+++ b/include/asm-x86/desc_64.h
@@ -147,23 +147,6 @@ static inline void set_ldt_desc(unsigned cpu, void *addr, int size)
(unsigned long)addr, DESC_LDT, size * 8 - 1);
}

-#define LDT_entry_a(info) \
- ((((info)->base_addr & 0x0000ffff) << 16) | ((info)->limit & 0x0ffff))
-/* Don't allow setting of the lm bit. It is useless anyways because
- 64bit system calls require __USER_CS. */
-#define LDT_entry_b(info) \
- (((info)->base_addr & 0xff000000) | \
- (((info)->base_addr & 0x00ff0000) >> 16) | \
- ((info)->limit & 0xf0000) | \
- (((info)->read_exec_only ^ 1) << 9) | \
- ((info)->contents << 10) | \
- (((info)->seg_not_present ^ 1) << 15) | \
- ((info)->seg_32bit << 22) | \
- ((info)->limit_in_pages << 23) | \
- ((info)->useable << 20) | \
- /* ((info)->lm << 21) | */ \
- 0x7000)
-
#define LDT_empty(info) (\
(info)->base_addr == 0 && \
(info)->limit == 0 && \
diff --git a/include/asm-x86/ldt.h b/include/asm-x86/ldt.h
index 20c5972..49013fd 100644
--- a/include/asm-x86/ldt.h
+++ b/include/asm-x86/ldt.h
@@ -5,6 +5,7 @@
*/
#ifndef _ASM_X86_LDT_H
#define _ASM_X86_LDT_H
+#include <asm/desc_defs.h>

/* Maximum number of LDT entries supported. */
#define LDT_ENTRIES 8192
@@ -32,6 +33,24 @@ struct user_desc {
#endif
};

+static inline void fill_ldt(struct desc_struct *desc, struct user_desc *info)
+{
+ desc->limit0 = info->limit & 0x0ffff;
+ desc->base0 = info->base_addr & 0x0000ffff;
+
+ desc->base1 = (info->base_addr & 0x00ff0000) >> 16;
+ desc->type = (info->read_exec_only ^ 1) << 1;
+ desc->type |= info->contents << 2;
+ desc->s = 1;
+ desc->dpl = 0x3;
+ desc->p = info->seg_not_present ^ 1;
+ desc->limit = (info->limit & 0xf0000) >> 16;
+ desc->avl = info->useable;
+ desc->d = info->seg_32bit;
+ desc->g = info->limit_in_pages;
+ desc->base2 = (info->base_addr & 0xff000000) >> 24;
+}
+
#define MODIFY_LDT_CONTENTS_DATA 0
#define MODIFY_LDT_CONTENTS_STACK 1
#define MODIFY_LDT_CONTENTS_CODE 2
--
1.5.0.6

2007-12-12 15:41:52

by Glauber Costa

[permalink] [raw]
Subject: [PATCH 10/19] provide tss_desc

Provide a new type, tss_desc, to represent the tss descriptor
in a unified way accross x86_64 and i386

Signed-off-by: Glauber de Oliveira Costa <[email protected]>
---
include/asm-x86/desc_defs.h | 2 ++
1 files changed, 2 insertions(+), 0 deletions(-)

diff --git a/include/asm-x86/desc_defs.h b/include/asm-x86/desc_defs.h
index 5a58fc1..c4d7874 100644
--- a/include/asm-x86/desc_defs.h
+++ b/include/asm-x86/desc_defs.h
@@ -70,9 +70,11 @@ struct ldttss_desc64 {
#ifdef CONFIG_X86_64
typedef struct gate_struct64 gate_desc;
typedef struct ldttss_desc64 ldt_desc;
+typedef struct ldttss_desc64 tss_desc;
#else
typedef struct desc_struct gate_desc;
typedef struct desc_struct ldt_desc;
+typedef struct desc_struct tss_desc;
#endif

struct desc_ptr {
--
1.5.0.6

2007-12-12 15:42:18

by Glauber Costa

[permalink] [raw]
Subject: [PATCH 11/19] change write_gdt_entry signature.

This patch changes the write_gdt_entry function signature.
Instead of the old "a" and "b" parameters, it now receives
a pointer to a desc_struct, and the size of the entry being
handled. This is because x86_64 can have some 16-byte entries
as well as 8-byte ones.

Signed-off-by: Glauber de Oliveira Costa <[email protected]>
CC: Zachary Amsden <[email protected]>
CC: Jeremy Fitzhardinge <Jeremy.Fitzhardinge.citrix.com>
---
arch/x86/kernel/paravirt_32.c | 2 +-
arch/x86/kernel/smpcommon_32.c | 7 ++++---
arch/x86/kernel/vmi_32.c | 21 +++++++++++++++------
arch/x86/lguest/boot.c | 6 +++---
arch/x86/xen/enlighten.c | 11 +++++------
include/asm-x86/desc_32.h | 34 ++++++++++++++++++++++------------
include/asm-x86/paravirt.h | 9 ++++++---
7 files changed, 56 insertions(+), 34 deletions(-)

diff --git a/arch/x86/kernel/paravirt_32.c b/arch/x86/kernel/paravirt_32.c
index 13bbc99..77602c1 100644
--- a/arch/x86/kernel/paravirt_32.c
+++ b/arch/x86/kernel/paravirt_32.c
@@ -380,7 +380,7 @@ struct pv_cpu_ops pv_cpu_ops = {
.store_tr = native_store_tr,
.load_tls = native_load_tls,
.write_ldt_entry = write_dt_entry,
- .write_gdt_entry = write_dt_entry,
+ .write_gdt_entry = native_write_gdt_entry,
.write_idt_entry = native_write_idt_entry,
.load_sp0 = native_load_sp0,

diff --git a/arch/x86/kernel/smpcommon_32.c b/arch/x86/kernel/smpcommon_32.c
index bbfe85a..8bc38af 100644
--- a/arch/x86/kernel/smpcommon_32.c
+++ b/arch/x86/kernel/smpcommon_32.c
@@ -14,10 +14,11 @@ __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(&gdt[GDT_ENTRY_PERCPU],
__per_cpu_offset[cpu], 0xFFFFF,
- 0x80 | DESCTYPE_S | 0x2, 0x8);
+ 0x2 | DESCTYPE_S, 0x8);
+
+ gdt[GDT_ENTRY_PERCPU].s = 1;

per_cpu(this_cpu_off, cpu) = __per_cpu_offset[cpu];
per_cpu(cpu_number, cpu) = cpu;
diff --git a/arch/x86/kernel/vmi_32.c b/arch/x86/kernel/vmi_32.c
index a635b22..21edd0d 100644
--- a/arch/x86/kernel/vmi_32.c
+++ b/arch/x86/kernel/vmi_32.c
@@ -63,6 +63,7 @@ static struct {
void (*_set_ldt)(u32 selector);
void (*set_tr)(u32 selector);
void (*write_idt_entry)(struct desc_struct *, int, u32, u32);
+ void (*write_gdt_entry)(struct desc_struct *, int, u32, u32);
void (*set_kernel_stack)(u32 selector, u32 sp0);
void (*allocate_page)(u32, u32, u32, u32, u32);
void (*release_page)(u32, u32);
@@ -187,7 +188,7 @@ static void vmi_cpuid(unsigned int *ax, unsigned int *bx,
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);
+ write_gdt_entry(gdt, nr, new, 0);
}

static void vmi_load_tls(struct thread_struct *t, unsigned int cpu)
@@ -201,12 +202,12 @@ static void vmi_load_tls(struct thread_struct *t, unsigned int cpu)
static void vmi_set_ldt(const void *addr, unsigned entries)
{
unsigned cpu = smp_processor_id();
- u32 low, high;
+ struct desc_struct desc;

- pack_descriptor(&low, &high, (unsigned long)addr,
+ pack_descriptor(&desc, (unsigned long)addr,
entries * sizeof(struct desc_struct) - 1,
- DESCTYPE_LDT, 0);
- write_gdt_entry(get_cpu_gdt_table(cpu), GDT_ENTRY_LDT, low, high);
+ DESC_LDT, 0);
+ write_gdt_entry(get_cpu_gdt_table(cpu), GDT_ENTRY_LDT, &desc, DESC_LDT);
vmi_ops._set_ldt(entries ? GDT_ENTRY_LDT*sizeof(struct desc_struct) : 0);
}

@@ -221,6 +222,13 @@ static void vmi_write_idt_entry(gate_desc *dt, int entry, const gate_desc *g)
vmi_ops.write_idt_entry(dt, entry, idt_entry[0], idt_entry[2]);
}

+static void vmi_write_gdt_entry(struct desc_struct *dt, int entry,
+ const void *desc, int type)
+{
+ u32 *gdt_entry = (u32 *)desc;
+ vmi_ops.write_gdt_entry(dt, entry, gdt_entry[0], gdt_entry[2]);
+}
+
static void vmi_load_sp0(struct tss_struct *tss,
struct thread_struct *thread)
{
@@ -798,7 +806,8 @@ static inline int __init activate_vmi(void)
para_fill(pv_cpu_ops.store_tr, GetTR);
pv_cpu_ops.load_tls = vmi_load_tls;
para_fill(pv_cpu_ops.write_ldt_entry, WriteLDTEntry);
- para_fill(pv_cpu_ops.write_gdt_entry, WriteGDTEntry);
+ para_wrap(pv_cpu_ops.write_gdt_entry, vmi_write_gdt_entry,
+ write_gdt_entry, WriteGDTEntry);
para_wrap(pv_cpu_ops.write_idt_entry, vmi_write_idt_entry,
write_idt_entry, WriteIDTEntry);
para_wrap(pv_cpu_ops.load_sp0, vmi_load_sp0, set_kernel_stack, UpdateKernelStack);
diff --git a/arch/x86/lguest/boot.c b/arch/x86/lguest/boot.c
index b50c8ad..a633737 100644
--- a/arch/x86/lguest/boot.c
+++ b/arch/x86/lguest/boot.c
@@ -262,10 +262,10 @@ static void lguest_load_gdt(const struct desc_ptr *desc)
/* For a single GDT entry which changes, we do the lazy thing: alter our GDT,
* then tell the Host to reload the entire thing. This operation is so rare
* that this naive implementation is reasonable. */
-static void lguest_write_gdt_entry(struct desc_struct *dt,
- int entrynum, u32 low, u32 high)
+static void lguest_write_gdt_entry(struct desc_struct *dt, int entrynum,
+ const void *desc, int type)
{
- write_dt_entry(dt, entrynum, low, high);
+ native_write_gdt_entry(dt, entrynum, desc, type);
hcall(LHCALL_LOAD_GDT, __pa(dt), GDT_ENTRIES, 0);
}

diff --git a/arch/x86/xen/enlighten.c b/arch/x86/xen/enlighten.c
index 6dd349e..c38240c 100644
--- a/arch/x86/xen/enlighten.c
+++ b/arch/x86/xen/enlighten.c
@@ -475,22 +475,21 @@ static void xen_load_idt(const struct desc_ptr *desc)
/* Write a GDT descriptor entry. Ignore LDT descriptors, since
they're handled differently. */
static void xen_write_gdt_entry(struct desc_struct *dt, int entry,
- u32 low, u32 high)
+ const void *desc, int type)
{
preempt_disable();

- switch ((high >> 8) & 0xff) {
- case DESCTYPE_LDT:
- case DESCTYPE_TSS:
+ switch (type) {
+ case DESC_LDT:
+ case DESC_TSS:
/* ignore */
break;

default: {
xmaddr_t maddr = virt_to_machine(&dt[entry]);
- u64 desc = (u64)high << 32 | low;

xen_mc_flush();
- if (HYPERVISOR_update_descriptor(maddr.maddr, desc))
+ if (HYPERVISOR_update_descriptor(maddr.maddr, *(u64 *)desc))
BUG();
}

diff --git a/include/asm-x86/desc_32.h b/include/asm-x86/desc_32.h
index 0370099..41d8214 100644
--- a/include/asm-x86/desc_32.h
+++ b/include/asm-x86/desc_32.h
@@ -28,12 +28,13 @@ extern struct desc_ptr idt_descr;
extern gate_desc idt_table[];
extern void set_intr_gate(unsigned int irq, void * addr);

-static inline void pack_descriptor(__u32 *a, __u32 *b,
+static inline void pack_descriptor(struct desc_struct *desc,
unsigned long base, unsigned long limit, unsigned char type, unsigned char flags)
{
- *a = ((base & 0xffff) << 16) | (limit & 0xffff);
- *b = (base & 0xff000000) | ((base & 0xff0000) >> 16) |
+ desc->a = ((base & 0xffff) << 16) | (limit & 0xffff);
+ desc->b = (base & 0xff000000) | ((base & 0xff0000) >> 16) |
(limit & 0x000f0000) | ((type & 0xff) << 8) | ((flags & 0xf) << 20);
+ desc->p = 1;
}

static inline void pack_gate(gate_desc *gate,
@@ -69,7 +70,8 @@ static inline void pack_gate(gate_desc *gate,
#define set_ldt native_set_ldt

#define write_ldt_entry(dt, entry, a, b) write_dt_entry(dt, entry, a, b)
-#define write_gdt_entry(dt, entry, a, b) write_dt_entry(dt, entry, a, b)
+#define write_gdt_entry(dt, entry, desc, type) \
+ native_write_gdt_entry(dt, entry, desc, type)
#define write_idt_entry(dt, entry, g) native_write_idt_entry(dt, entry, g)
#endif

@@ -79,6 +81,12 @@ static inline void native_write_idt_entry(gate_desc *idt, int entry,
memcpy(&idt[entry], gate, sizeof(*gate));
}

+static inline void native_write_gdt_entry(struct desc_struct *gdt, int entry,
+ const void *desc, int type)
+{
+ memcpy(&gdt[entry], desc, sizeof(struct desc_struct));
+}
+
static inline void write_dt_entry(struct desc_struct *dt,
int entry, u32 entry_low, u32 entry_high)
{
@@ -86,18 +94,20 @@ static inline void write_dt_entry(struct desc_struct *dt,
dt[entry].b = entry_high;
}

+
static inline void native_set_ldt(const void *addr, unsigned int entries)
{
if (likely(entries == 0))
__asm__ __volatile__("lldt %w0"::"q" (0));
else {
unsigned cpu = smp_processor_id();
- __u32 a, b;
+ ldt_desc ldt;

- pack_descriptor(&a, &b, (unsigned long)addr,
+ pack_descriptor(&ldt, (unsigned long)addr,
entries * sizeof(struct desc_struct) - 1,
- DESCTYPE_LDT, 0);
- write_gdt_entry(get_cpu_gdt_table(cpu), GDT_ENTRY_LDT, a, b);
+ DESC_LDT, 0);
+ write_gdt_entry(get_cpu_gdt_table(cpu), GDT_ENTRY_LDT,
+ &ldt, DESC_LDT);
__asm__ __volatile__("lldt %w0"::"q" (GDT_ENTRY_LDT*8));
}
}
@@ -153,11 +163,11 @@ static inline void _set_gate(int gate, unsigned int type, void *addr, unsigned s

static inline void __set_tss_desc(unsigned int cpu, unsigned int entry, const void *addr)
{
- __u32 a, b;
- pack_descriptor(&a, &b, (unsigned long)addr,
+ tss_desc tss;
+ pack_descriptor(&tss, (unsigned long)addr,
offsetof(struct tss_struct, __cacheline_filler) - 1,
- DESCTYPE_TSS, 0);
- write_gdt_entry(get_cpu_gdt_table(cpu), entry, a, b);
+ DESC_TSS, 0);
+ write_gdt_entry(get_cpu_gdt_table(cpu), entry, &tss, DESC_TSS);
}


diff --git a/include/asm-x86/paravirt.h b/include/asm-x86/paravirt.h
index 86a9d7b..3f2abf2 100644
--- a/include/asm-x86/paravirt.h
+++ b/include/asm-x86/paravirt.h
@@ -99,7 +99,7 @@ struct pv_cpu_ops {
void (*write_ldt_entry)(struct desc_struct *,
int entrynum, u32 low, u32 high);
void (*write_gdt_entry)(struct desc_struct *,
- int entrynum, u32 low, u32 high);
+ int entrynum, const void *desc, int size);
void (*write_idt_entry)(gate_desc *,
int entrynum, const gate_desc *gate);
void (*load_sp0)(struct tss_struct *tss, struct thread_struct *t);
@@ -664,10 +664,13 @@ static inline void write_ldt_entry(void *dt, int entry, u32 low, u32 high)
{
PVOP_VCALL4(pv_cpu_ops.write_ldt_entry, dt, entry, low, high);
}
-static inline void write_gdt_entry(void *dt, int entry, u32 low, u32 high)
+
+static inline void write_gdt_entry(struct desc_struct *dt, int entry,
+ void *desc, int type)
{
- PVOP_VCALL4(pv_cpu_ops.write_gdt_entry, dt, entry, low, high);
+ PVOP_VCALL4(pv_cpu_ops.write_gdt_entry, dt, entry, desc, type);
}
+
static inline void write_idt_entry(gate_desc *dt, int entry, const gate_desc *g)
{
PVOP_VCALL3(pv_cpu_ops.write_idt_entry, dt, entry, g);
--
1.5.0.6

2007-12-12 15:42:34

by Glauber Costa

[permalink] [raw]
Subject: [PATCH 12/19] change write_ldt_entry signature

this patch changes the signature of write_ldt_entry.

Signed-off-by: Glauber de Oliveira Costa <[email protected]>
CC: Zachary Amsden <[email protected]>
CC: Jeremy Fitzhardinge <Jeremy.Fitzhardinge.citrix.com>
---
arch/x86/kernel/ldt.c | 3 +--
arch/x86/kernel/paravirt_32.c | 2 +-
arch/x86/kernel/vmi_32.c | 11 ++++++++++-
arch/x86/xen/enlighten.c | 4 ++--
include/asm-x86/desc_32.h | 9 ++++++++-
include/asm-x86/desc_64.h | 7 ++-----
include/asm-x86/paravirt.h | 10 ++++++----
7 files changed, 30 insertions(+), 16 deletions(-)

diff --git a/arch/x86/kernel/ldt.c b/arch/x86/kernel/ldt.c
index 3e872b4..b8ef462 100644
--- a/arch/x86/kernel/ldt.c
+++ b/arch/x86/kernel/ldt.c
@@ -229,8 +229,7 @@ static int write_ldt(void __user *ptr, unsigned long bytecount, int oldmode)

/* Install the new entry ... */
install:
- write_ldt_entry(mm->context.ldt, ldt_info.entry_number,
- ldt.a, ldt.b);
+ write_ldt_entry(mm->context.ldt, ldt_info.entry_number, &ldt);
error = 0;

out_unlock:
diff --git a/arch/x86/kernel/paravirt_32.c b/arch/x86/kernel/paravirt_32.c
index 77602c1..dd063fb 100644
--- a/arch/x86/kernel/paravirt_32.c
+++ b/arch/x86/kernel/paravirt_32.c
@@ -379,7 +379,7 @@ struct pv_cpu_ops pv_cpu_ops = {
.store_idt = native_store_idt,
.store_tr = native_store_tr,
.load_tls = native_load_tls,
- .write_ldt_entry = write_dt_entry,
+ .write_ldt_entry = native_write_ldt_entry,
.write_gdt_entry = native_write_gdt_entry,
.write_idt_entry = native_write_idt_entry,
.load_sp0 = native_load_sp0,
diff --git a/arch/x86/kernel/vmi_32.c b/arch/x86/kernel/vmi_32.c
index 21edd0d..10c4641 100644
--- a/arch/x86/kernel/vmi_32.c
+++ b/arch/x86/kernel/vmi_32.c
@@ -64,6 +64,7 @@ static struct {
void (*set_tr)(u32 selector);
void (*write_idt_entry)(struct desc_struct *, int, u32, u32);
void (*write_gdt_entry)(struct desc_struct *, int, u32, u32);
+ void (*write_ldt_entry)(struct desc_struct *, int, u32, u32);
void (*set_kernel_stack)(u32 selector, u32 sp0);
void (*allocate_page)(u32, u32, u32, u32, u32);
void (*release_page)(u32, u32);
@@ -229,6 +230,13 @@ static void vmi_write_gdt_entry(struct desc_struct *dt, int entry,
vmi_ops.write_gdt_entry(dt, entry, gdt_entry[0], gdt_entry[2]);
}

+static void vmi_write_ldt_entry(struct desc_struct *dt, int entry,
+ const void *desc)
+{
+ u32 *ldt_entry = (u32 *)desc;
+ vmi_ops.write_idt_entry(dt, entry, ldt_entry[0], ldt_entry[2]);
+}
+
static void vmi_load_sp0(struct tss_struct *tss,
struct thread_struct *thread)
{
@@ -805,7 +813,8 @@ static inline int __init activate_vmi(void)
para_fill(pv_cpu_ops.store_idt, GetIDT);
para_fill(pv_cpu_ops.store_tr, GetTR);
pv_cpu_ops.load_tls = vmi_load_tls;
- para_fill(pv_cpu_ops.write_ldt_entry, WriteLDTEntry);
+ para_wrap(pv_cpu_ops.write_ldt_entry, vmi_write_ldt_entry,
+ write_ldt_entry, WriteLDTEntry);
para_wrap(pv_cpu_ops.write_gdt_entry, vmi_write_gdt_entry,
write_gdt_entry, WriteGDTEntry);
para_wrap(pv_cpu_ops.write_idt_entry, vmi_write_idt_entry,
diff --git a/arch/x86/xen/enlighten.c b/arch/x86/xen/enlighten.c
index c38240c..c904686 100644
--- a/arch/x86/xen/enlighten.c
+++ b/arch/x86/xen/enlighten.c
@@ -357,11 +357,11 @@ static void xen_load_tls(struct thread_struct *t, unsigned int cpu)
}

static void xen_write_ldt_entry(struct desc_struct *dt, int entrynum,
- u32 low, u32 high)
+ const void *ptr)
{
unsigned long lp = (unsigned long)&dt[entrynum];
xmaddr_t mach_lp = virt_to_machine(lp);
- u64 entry = (u64)high << 32 | low;
+ u64 entry = *(u64 *)ptr;

preempt_disable();

diff --git a/include/asm-x86/desc_32.h b/include/asm-x86/desc_32.h
index 41d8214..92a72b0 100644
--- a/include/asm-x86/desc_32.h
+++ b/include/asm-x86/desc_32.h
@@ -69,12 +69,19 @@ static inline void pack_gate(gate_desc *gate,
#define load_TLS(t, cpu) native_load_tls(t, cpu)
#define set_ldt native_set_ldt

-#define write_ldt_entry(dt, entry, a, b) write_dt_entry(dt, entry, a, b)
+#define write_ldt_entry(dt, entry, desc) \
+ native_write_ldt_entry(dt, entry, desc)
#define write_gdt_entry(dt, entry, desc, type) \
native_write_gdt_entry(dt, entry, desc, type)
#define write_idt_entry(dt, entry, g) native_write_idt_entry(dt, entry, g)
#endif

+static inline void native_write_ldt_entry(struct desc_struct *ldt, int entry,
+ const void *desc)
+{
+ memcpy(&ldt[entry], desc, sizeof(struct desc_struct));
+}
+
static inline void native_write_idt_entry(gate_desc *idt, int entry,
const gate_desc *gate)
{
diff --git a/include/asm-x86/desc_64.h b/include/asm-x86/desc_64.h
index e0aa4bc..3cd5f10 100644
--- a/include/asm-x86/desc_64.h
+++ b/include/asm-x86/desc_64.h
@@ -34,12 +34,9 @@ extern gate_desc idt_table[];
extern struct desc_ptr cpu_gdt_descr[];

static inline void write_ldt_entry(struct desc_struct *ldt,
- int entry, u32 entry_low, u32 entry_high)
+ int entry, void *ptr)
{
- __u32 *lp = (__u32 *)((entry << 3) + (char *)ldt);
-
- lp[0] = entry_low;
- lp[1] = entry_high;
+ memcpy(&ldt[entry], ptr, 8);
}

/* the cpu gdt accessor */
diff --git a/include/asm-x86/paravirt.h b/include/asm-x86/paravirt.h
index 3f2abf2..4f23f43 100644
--- a/include/asm-x86/paravirt.h
+++ b/include/asm-x86/paravirt.h
@@ -96,8 +96,8 @@ struct pv_cpu_ops {
void (*set_ldt)(const void *desc, unsigned entries);
unsigned long (*store_tr)(void);
void (*load_tls)(struct thread_struct *t, unsigned int cpu);
- void (*write_ldt_entry)(struct desc_struct *,
- int entrynum, u32 low, u32 high);
+ void (*write_ldt_entry)(struct desc_struct *ldt, int entrynum,
+ const void *desc);
void (*write_gdt_entry)(struct desc_struct *,
int entrynum, const void *desc, int size);
void (*write_idt_entry)(gate_desc *,
@@ -660,9 +660,11 @@ static inline void load_TLS(struct thread_struct *t, unsigned cpu)
{
PVOP_VCALL2(pv_cpu_ops.load_tls, t, cpu);
}
-static inline void write_ldt_entry(void *dt, int entry, u32 low, u32 high)
+
+static inline void write_ldt_entry(struct desc_struct *dt, int entry,
+ const void *desc)
{
- PVOP_VCALL4(pv_cpu_ops.write_ldt_entry, dt, entry, low, high);
+ PVOP_VCALL3(pv_cpu_ops.write_ldt_entry, dt, entry, desc);
}

static inline void write_gdt_entry(struct desc_struct *dt, int entry,
--
1.5.0.6

2007-12-12 15:42:51

by Glauber Costa

[permalink] [raw]
Subject: [PATCH 13/19] move constants to desc_defs.h

this patch moves constant definitions regarding descriptor types
from desc_32.h to desc_defs.h. The change from defines to enum
to comply with previous versions in desc_defs.h

Signed-off-by: Glauber de Oliveira Costa <[email protected]>
---
include/asm-x86/desc_32.h | 8 --------
include/asm-x86/desc_defs.h | 5 +++++
2 files changed, 5 insertions(+), 8 deletions(-)

diff --git a/include/asm-x86/desc_32.h b/include/asm-x86/desc_32.h
index 92a72b0..14238df 100644
--- a/include/asm-x86/desc_32.h
+++ b/include/asm-x86/desc_32.h
@@ -44,14 +44,6 @@ static inline void pack_gate(gate_desc *gate,
gate->b = (base & 0xffff0000) | ((type & 0xff) << 8) | (flags & 0xff);
}

-#define DESCTYPE_LDT 0x82 /* present, system, DPL-0, LDT */
-#define DESCTYPE_TSS 0x89 /* present, system, DPL-0, 32-bit TSS */
-#define DESCTYPE_TASK 0x85 /* present, system, DPL-0, task gate */
-#define DESCTYPE_INT 0x8e /* present, system, DPL-0, interrupt gate */
-#define DESCTYPE_TRAP 0x8f /* present, system, DPL-0, trap gate */
-#define DESCTYPE_DPL3 0x60 /* DPL-3 */
-#define DESCTYPE_S 0x10 /* !system */
-
#ifdef CONFIG_PARAVIRT
#include <asm/paravirt.h>
#else
diff --git a/include/asm-x86/desc_defs.h b/include/asm-x86/desc_defs.h
index c4d7874..5ca416d 100644
--- a/include/asm-x86/desc_defs.h
+++ b/include/asm-x86/desc_defs.h
@@ -55,6 +55,11 @@ struct gate_struct64 {
enum {
DESC_TSS = 0x9,
DESC_LDT = 0x2,
+ DESCTYPE_TASK = 0x85, /* present, system, DPL-0, task gate */
+ DESCTYPE_INT = 0x8e, /* present, system, DPL-0, interrupt gate */
+ DESCTYPE_TRAP = 0x8f, /* present, system, DPL-0, trap gate */
+ DESCTYPE_DPL3 = 0x60, /* DPL-3 */
+ DESCTYPE_S = 0x10, /* !system */
};

// LDT or TSS descriptor in the GDT. 16 bytes.
--
1.5.0.6

2007-12-12 15:43:13

by Glauber Costa

[permalink] [raw]
Subject: [PATCH 15/19] use the same data type for tls_array.

This patch changes the type of tls_array in x86_64 to
a desc_struct. Now, both i386 and x86_64 tls_array have
the same type, and code accessing it can be shared.

Signed-off-by: Glauber de Oliveira Costa <[email protected]>
---
include/asm-x86/desc_64.h | 2 +-
include/asm-x86/processor_64.h | 3 ++-
2 files changed, 3 insertions(+), 2 deletions(-)

diff --git a/include/asm-x86/desc_64.h b/include/asm-x86/desc_64.h
index 2dc19e2..7fd9876 100644
--- a/include/asm-x86/desc_64.h
+++ b/include/asm-x86/desc_64.h
@@ -150,7 +150,7 @@ static inline void set_ldt(void *addr, int entries)
static inline void load_TLS(struct thread_struct *t, unsigned int cpu)
{
unsigned int i;
- u64 *gdt = (u64 *)(get_cpu_gdt_table(cpu) + GDT_ENTRY_TLS_MIN);
+ struct desc_struct *gdt = (get_cpu_gdt_table(cpu) + GDT_ENTRY_TLS_MIN);

for (i = 0; i < GDT_ENTRY_TLS_ENTRIES; i++)
gdt[i] = t->tls_array[i];
diff --git a/include/asm-x86/processor_64.h b/include/asm-x86/processor_64.h
index 8efdf99..51f1970 100644
--- a/include/asm-x86/processor_64.h
+++ b/include/asm-x86/processor_64.h
@@ -19,6 +19,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
@@ -244,7 +245,7 @@ struct thread_struct {
* goes into MSR_IA32_DS_AREA */
unsigned long ds_area_msr;
/* 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 { \
--
1.5.0.6

2007-12-12 15:43:35

by Glauber Costa

[permalink] [raw]
Subject: [PATCH 14/19] unify non-paravirt parts of desc.h

This patch unifies the non-paravirt part of desc_{32,64}.h into
desc.h. Most of it, is simply common code, that is moved to
the shared header. The only exception is the set_ldt_desc in desc_64.h,
which is changed - included its name - to accomodate for the way
the ldt is set up in i386.

Also, constant definitions used in desc_32.h are moved to desc_defs.h

Signed-off-by: Glauber de Oliveira Costa <[email protected]>
---
include/asm-x86/desc.h | 87 ++++++++++++++++++++++++++++++++++++++
include/asm-x86/desc_32.h | 66 ----------------------------
include/asm-x86/desc_64.h | 64 ++++-----------------------
include/asm-x86/mmu_context_64.h | 4 +-
4 files changed, 99 insertions(+), 122 deletions(-)

Index: linux-2.6-x86/include/asm-x86/desc.h
===================================================================
--- linux-2.6-x86.orig/include/asm-x86/desc.h
+++ linux-2.6-x86/include/asm-x86/desc.h
@@ -1,5 +1,92 @@
+#ifndef _ASM_DESC_H_
+#define _ASM_DESC_H_
+
+#include <asm/desc_defs.h>
+
+#ifndef __ASSEMBLY__
+#include <asm/mmu.h>
+
+extern struct desc_ptr idt_descr;
+extern gate_desc idt_table[];
+
+#endif
+
#ifdef CONFIG_X86_32
# include "desc_32.h"
#else
# include "desc_64.h"
#endif
+
+#ifndef __ASSEMBLY__
+
+#define _LDT_empty(info) (\
+ (info)->base_addr == 0 && \
+ (info)->limit == 0 && \
+ (info)->contents == 0 && \
+ (info)->read_exec_only == 1 && \
+ (info)->seg_32bit == 0 && \
+ (info)->limit_in_pages == 0 && \
+ (info)->seg_not_present == 1 && \
+ (info)->useable == 0)
+
+#ifdef CONFIG_X86_64
+#define LDT_empty(info) (_LDT_empty(info) && ((info)->lm == 0))
+#else
+#define LDT_empty(info) (_LDT_empty(info))
+#endif
+
+static inline void clear_LDT(void)
+{
+ set_ldt(NULL, 0);
+}
+
+/*
+ * load one particular LDT into the current CPU
+ */
+static inline void load_LDT_nolock(mm_context_t *pc)
+{
+ set_ldt(pc->ldt, pc->size);
+}
+
+static inline void load_LDT(mm_context_t *pc)
+{
+ preempt_disable();
+ load_LDT_nolock(pc);
+ preempt_enable();
+}
+
+static inline unsigned long get_desc_base(unsigned long *desc)
+{
+ unsigned long base;
+ base = ((desc[0] >> 16) & 0x0000ffff) |
+ ((desc[1] << 16) & 0x00ff0000) |
+ (desc[1] & 0xff000000);
+ return base;
+}
+
+#else
+/*
+ * GET_DESC_BASE reads the descriptor base of the specified segment.
+ *
+ * Args:
+ * idx - descriptor index
+ * gdt - GDT pointer
+ * base - 32bit register to which the base will be written
+ * lo_w - lo word of the "base" register
+ * lo_b - lo byte of the "base" register
+ * hi_b - hi byte of the low word of the "base" register
+ *
+ * Example:
+ * GET_DESC_BASE(GDT_ENTRY_ESPFIX_SS, %ebx, %eax, %ax, %al, %ah)
+ * Will read the base address of GDT_ENTRY_ESPFIX_SS and put it into %eax.
+ */
+#define GET_DESC_BASE(idx, gdt, base, lo_w, lo_b, hi_b) \
+ movb idx*8+4(gdt), lo_b; \
+ movb idx*8+7(gdt), hi_b; \
+ shll $16, base; \
+ movw idx*8+2(gdt), lo_w;
+
+
+#endif /* __ASSEMBLY__ */
+
+#endif
Index: linux-2.6-x86/include/asm-x86/desc_32.h
===================================================================
--- linux-2.6-x86.orig/include/asm-x86/desc_32.h
+++ linux-2.6-x86/include/asm-x86/desc_32.h
@@ -11,8 +11,6 @@
#include <linux/smp.h>
#include <linux/percpu.h>

-#include <asm/mmu.h>
-
struct gdt_page
{
struct desc_struct gdt[GDT_ENTRIES];
@@ -24,8 +22,6 @@ static inline struct desc_struct *get_cp
return per_cpu(gdt_page, cpu).gdt;
}

-extern struct desc_ptr idt_descr;
-extern gate_desc idt_table[];
extern void set_intr_gate(unsigned int irq, void * addr);

static inline void pack_descriptor(struct desc_struct *desc,
@@ -172,68 +168,6 @@ static inline void __set_tss_desc(unsign

#define set_tss_desc(cpu,addr) __set_tss_desc(cpu, GDT_ENTRY_TSS, addr)

-#define LDT_empty(info) (\
- (info)->base_addr == 0 && \
- (info)->limit == 0 && \
- (info)->contents == 0 && \
- (info)->read_exec_only == 1 && \
- (info)->seg_32bit == 0 && \
- (info)->limit_in_pages == 0 && \
- (info)->seg_not_present == 1 && \
- (info)->useable == 0 )
-
-static inline void clear_LDT(void)
-{
- set_ldt(NULL, 0);
-}
-
-/*
- * load one particular LDT into the current CPU
- */
-static inline void load_LDT_nolock(mm_context_t *pc)
-{
- set_ldt(pc->ldt, pc->size);
-}
-
-static inline void load_LDT(mm_context_t *pc)
-{
- preempt_disable();
- load_LDT_nolock(pc);
- preempt_enable();
-}
-
-static inline unsigned long get_desc_base(unsigned long *desc)
-{
- unsigned long base;
- base = ((desc[0] >> 16) & 0x0000ffff) |
- ((desc[1] << 16) & 0x00ff0000) |
- (desc[1] & 0xff000000);
- return base;
-}
-
-#else /* __ASSEMBLY__ */
-
-/*
- * GET_DESC_BASE reads the descriptor base of the specified segment.
- *
- * Args:
- * idx - descriptor index
- * gdt - GDT pointer
- * base - 32bit register to which the base will be written
- * lo_w - lo word of the "base" register
- * lo_b - lo byte of the "base" register
- * hi_b - hi byte of the low word of the "base" register
- *
- * Example:
- * GET_DESC_BASE(GDT_ENTRY_ESPFIX_SS, %ebx, %eax, %ax, %al, %ah)
- * Will read the base address of GDT_ENTRY_ESPFIX_SS and put it into %eax.
- */
-#define GET_DESC_BASE(idx, gdt, base, lo_w, lo_b, hi_b) \
- movb idx*8+4(gdt), lo_b; \
- movb idx*8+7(gdt), hi_b; \
- shll $16, base; \
- movw idx*8+2(gdt), lo_w;
-
#endif /* !__ASSEMBLY__ */

#endif
Index: linux-2.6-x86/include/asm-x86/desc_64.h
===================================================================
--- linux-2.6-x86.orig/include/asm-x86/desc_64.h
+++ linux-2.6-x86/include/asm-x86/desc_64.h
@@ -9,16 +9,13 @@

#include <linux/string.h>
#include <linux/smp.h>
-#include <asm/desc_defs.h>

#include <asm/segment.h>
-#include <asm/mmu.h>

extern struct desc_struct cpu_gdt_table[GDT_ENTRIES];

#define load_TR_desc() asm volatile("ltr %w0"::"r" (GDT_ENTRY_TSS*8))
#define load_LDT_desc() asm volatile("lldt %w0"::"r" (GDT_ENTRY_LDT*8))
-#define clear_LDT() asm volatile("lldt %w0"::"r" (0))

static inline unsigned long __store_tr(void)
{
@@ -30,7 +27,6 @@ static inline unsigned long __store_tr(v

#define store_tr(tr) (tr) = __store_tr()

-extern gate_desc idt_table[];
extern struct desc_ptr cpu_gdt_descr[];

static inline void write_ldt_entry(struct desc_struct *ldt,
@@ -138,23 +134,19 @@ static inline void set_tss_desc(unsigned
IO_BITMAP_OFFSET + IO_BITMAP_BYTES + sizeof(unsigned long) - 1);
}

-static inline void set_ldt_desc(unsigned cpu, void *addr, int size)
+static inline void set_ldt(void *addr, int entries)
{
- set_tssldt_descriptor(&get_cpu_gdt_table(cpu)[GDT_ENTRY_LDT],
- (unsigned long)addr, DESC_LDT, size * 8 - 1);
+ if (likely(entries == 0))
+ __asm__ __volatile__("lldt %w0"::"q" (0));
+ else {
+ unsigned cpu = smp_processor_id();
+
+ set_tssldt_descriptor(&get_cpu_gdt_table(cpu)[GDT_ENTRY_LDT],
+ (unsigned long)addr, DESC_LDT, entries * 8 - 1);
+ __asm__ __volatile__("lldt %w0"::"q" (GDT_ENTRY_LDT*8));
+ }
}

-#define LDT_empty(info) (\
- (info)->base_addr == 0 && \
- (info)->limit == 0 && \
- (info)->contents == 0 && \
- (info)->read_exec_only == 1 && \
- (info)->seg_32bit == 0 && \
- (info)->limit_in_pages == 0 && \
- (info)->seg_not_present == 1 && \
- (info)->useable == 0 && \
- (info)->lm == 0)
-
static inline void load_TLS(struct thread_struct *t, unsigned int cpu)
{
unsigned int i;
@@ -164,42 +156,6 @@ static inline void load_TLS(struct threa
gdt[i] = t->tls_array[i];
}

-/*
- * load one particular LDT into the current CPU
- */
-static inline void load_LDT_nolock(mm_context_t *pc, int cpu)
-{
- int count = pc->size;
-
- if (likely(!count)) {
- clear_LDT();
- return;
- }
-
- set_ldt_desc(cpu, pc->ldt, count);
- load_LDT_desc();
-}
-
-static inline void load_LDT(mm_context_t *pc)
-{
- int cpu = get_cpu();
-
- load_LDT_nolock(pc, cpu);
- put_cpu();
-}
-
-extern struct desc_ptr idt_descr;
-
-static inline unsigned long get_desc_base(const void *ptr)
-{
- const u32 *desc = ptr;
- unsigned long base;
- base = ((desc[0] >> 16) & 0x0000ffff) |
- ((desc[1] << 16) & 0x00ff0000) |
- (desc[1] & 0xff000000);
- return base;
-}
-
#endif /* !__ASSEMBLY__ */

#endif
Index: linux-2.6-x86/include/asm-x86/mmu_context_64.h
===================================================================
--- linux-2.6-x86.orig/include/asm-x86/mmu_context_64.h
+++ linux-2.6-x86/include/asm-x86/mmu_context_64.h
@@ -43,7 +43,7 @@ static inline void switch_mm(struct mm_s
load_cr3(next->pgd);

if (unlikely(next->context.ldt != prev->context.ldt))
- load_LDT_nolock(&next->context, cpu);
+ load_LDT_nolock(&next->context);
}
#ifdef CONFIG_SMP
else {
@@ -56,7 +56,7 @@ static inline void switch_mm(struct mm_s
* to make sure to use no freed page tables.
*/
load_cr3(next->pgd);
- load_LDT_nolock(&next->context, cpu);
+ load_LDT_nolock(&next->context);
}
}
#endif

2007-12-12 15:43:50

by Glauber Costa

[permalink] [raw]
Subject: [PATCH 17/19] unify paravirt pieces of descriptor handling

With the types used to access descriptors in x86_64 and i386
now being the same, the code that effectively handles them can
now be easily shared. This patch moves the paravirt part of
desc_32.h into desc.h, and then, we get paravirt support in x86_64
for free.

Signed-off-by: Glauber de Oliveira Costa <[email protected]>
---
include/asm-x86/desc.h | 169 +++++++++++++++++++++++++++++++++++++++++++
include/asm-x86/desc_32.h | 130 ---------------------------------
include/asm-x86/desc_64.h | 104 +++------------------------
include/asm-x86/desc_defs.h | 6 +-
4 files changed, 183 insertions(+), 226 deletions(-)

Index: linux-2.6-x86/include/asm-x86/desc.h
===================================================================
--- linux-2.6-x86.orig/include/asm-x86/desc.h
+++ linux-2.6-x86/include/asm-x86/desc.h
@@ -5,11 +5,180 @@

#ifndef __ASSEMBLY__
#include <asm/mmu.h>
+#include <linux/smp.h>

extern struct desc_ptr idt_descr;
extern gate_desc idt_table[];

+#ifdef CONFIG_X86_64
+extern struct desc_struct cpu_gdt_table[GDT_ENTRIES];
+extern struct desc_ptr cpu_gdt_descr[];
+/* the cpu gdt accessor */
+#define get_cpu_gdt_table(x) ((struct desc_struct *)cpu_gdt_descr[x].address)
+#else
+struct gdt_page {
+ struct desc_struct gdt[GDT_ENTRIES];
+} __attribute__((aligned(PAGE_SIZE)));
+DECLARE_PER_CPU(struct gdt_page, gdt_page);
+
+static inline struct desc_struct *get_cpu_gdt_table(unsigned int cpu)
+{
+ return per_cpu(gdt_page, cpu).gdt;
+}
+#endif
+
+#ifdef CONFIG_PARAVIRT
+#include <asm/paravirt.h>
+#else
+#define load_TR_desc() native_load_tr_desc()
+#define load_gdt(dtr) native_load_gdt(dtr)
+#define load_idt(dtr) native_load_idt(dtr)
+#define load_tr(tr) __asm__ __volatile("ltr %0"::"m" (tr))
+#define load_ldt(ldt) __asm__ __volatile("lldt %0"::"m" (ldt))
+
+#define store_gdt(dtr) native_store_gdt(dtr)
+#define store_idt(dtr) native_store_idt(dtr)
+#define store_tr(tr) (tr = native_store_tr())
+#define store_ldt(ldt) __asm__ ("sldt %0":"=m" (ldt))
+
+#define load_TLS(t, cpu) native_load_tls(t, cpu)
+#define set_ldt native_set_ldt
+
+#define write_ldt_entry(dt, entry, desc) \
+ native_write_ldt_entry(dt, entry, desc)
+#define write_gdt_entry(dt, entry, desc, type) \
+ native_write_gdt_entry(dt, entry, desc, type)
+#define write_idt_entry(dt, entry, g) native_write_idt_entry(dt, entry, g)
+#endif
+
+static inline void native_write_idt_entry(gate_desc *idt, int entry,
+ const gate_desc *gate)
+{
+ memcpy(&idt[entry], gate, sizeof(*gate));
+}
+
+static inline void native_write_ldt_entry(struct desc_struct *ldt, int entry,
+ const void *desc)
+{
+ memcpy(&ldt[entry], desc, 8);
+}
+
+static inline void native_write_gdt_entry(struct desc_struct *gdt, int entry,
+ const void *desc, int type)
+{
+ unsigned int size;
+ switch (type) {
+ case DESC_TSS:
+ size = sizeof(tss_desc);
+ break;
+ case DESC_LDT:
+ size = sizeof(ldt_desc);
+ break;
+ default:
+ size = sizeof(struct desc_struct);
+ break;
+ }
+ memcpy(&gdt[entry], desc, size);
+}
+
+static inline void set_tssldt_descriptor(struct ldttss_desc64 *d,
+ unsigned long tss, unsigned type,
+ unsigned size)
+{
+ memset(d, 0, sizeof(*d));
+ d->limit0 = size & 0xFFFF;
+ d->base0 = PTR_LOW(tss);
+ d->base1 = PTR_MIDDLE(tss) & 0xFF;
+ d->type = type;
+ d->p = 1;
+ d->limit1 = (size >> 16) & 0xF;
+ d->base2 = (PTR_MIDDLE(tss) >> 8) & 0xFF;
+ d->base3 = PTR_HIGH(tss);
+}
+
+static inline void pack_descriptor(struct desc_struct *desc, unsigned long base,
+ unsigned long limit, unsigned char type,
+ unsigned char flags)
+{
+ desc->a = ((base & 0xffff) << 16) | (limit & 0xffff);
+ desc->b = (base & 0xff000000) | ((base & 0xff0000) >> 16) |
+ (limit & 0x000f0000) | ((type & 0xff) << 8) |
+ ((flags & 0xf) << 20);
+ desc->p = 1;
+}
+
+static inline void pack_ldt(ldt_desc *ldt, unsigned long addr,
+ unsigned size)
+{
+
+#ifdef CONFIG_X86_64
+ set_tssldt_descriptor(ldt,
+ addr, DESC_LDT, size);
+#else
+ pack_descriptor(ldt, (unsigned long)addr,
+ size,
+ 0x80 | DESC_LDT, 0);
#endif
+}
+
+static inline void native_set_ldt(const void *addr, unsigned int entries)
+{
+ if (likely(entries == 0))
+ __asm__ __volatile__("lldt %w0"::"q" (0));
+ else {
+ unsigned cpu = smp_processor_id();
+ ldt_desc ldt;
+
+ pack_ldt(&ldt, (unsigned long)addr,
+ entries * sizeof(ldt) - 1);
+ write_gdt_entry(get_cpu_gdt_table(cpu), GDT_ENTRY_LDT,
+ &ldt, sizeof(ldt));
+ __asm__ __volatile__("lldt %w0"::"q" (GDT_ENTRY_LDT*8));
+ }
+}
+
+static inline void native_load_tr_desc(void)
+{
+ asm volatile("ltr %w0"::"q" (GDT_ENTRY_TSS*8));
+}
+
+static inline void native_load_gdt(const struct desc_ptr *dtr)
+{
+ asm volatile("lgdt %0"::"m" (*dtr));
+}
+
+static inline void native_load_idt(const struct desc_ptr *dtr)
+{
+ asm volatile("lidt %0"::"m" (*dtr));
+}
+
+static inline void native_store_gdt(struct desc_ptr *dtr)
+{
+ asm volatile("sgdt %0":"=m" (*dtr));
+}
+
+static inline void native_store_idt(struct desc_ptr *dtr)
+{
+ asm volatile("sidt %0":"=m" (*dtr));
+}
+
+static inline unsigned long native_store_tr(void)
+{
+ unsigned long tr;
+ asm volatile("str %0":"=r" (tr));
+ return tr;
+}
+
+static inline void native_load_tls(struct thread_struct *t, unsigned int cpu)
+{
+ unsigned int i;
+ struct desc_struct *gdt = get_cpu_gdt_table(cpu);
+
+ for (i = 0; i < GDT_ENTRY_TLS_ENTRIES; i++)
+ gdt[GDT_ENTRY_TLS_MIN + i] = t->tls_array[i];
+}
+#endif /* __ASSEMBLY__ */
+

#ifdef CONFIG_X86_32
# include "desc_32.h"
Index: linux-2.6-x86/include/asm-x86/desc_32.h
===================================================================
--- linux-2.6-x86.orig/include/asm-x86/desc_32.h
+++ linux-2.6-x86/include/asm-x86/desc_32.h
@@ -8,31 +8,10 @@
#ifndef __ASSEMBLY__

#include <linux/preempt.h>
-#include <linux/smp.h>
#include <linux/percpu.h>

-struct gdt_page
-{
- struct desc_struct gdt[GDT_ENTRIES];
-} __attribute__((aligned(PAGE_SIZE)));
-DECLARE_PER_CPU(struct gdt_page, gdt_page);
-
-static inline struct desc_struct *get_cpu_gdt_table(unsigned int cpu)
-{
- return per_cpu(gdt_page, cpu).gdt;
-}
-
extern void set_intr_gate(unsigned int irq, void * addr);

-static inline void pack_descriptor(struct desc_struct *desc,
- unsigned long base, unsigned long limit, unsigned char type, unsigned char flags)
-{
- desc->a = ((base & 0xffff) << 16) | (limit & 0xffff);
- desc->b = (base & 0xff000000) | ((base & 0xff0000) >> 16) |
- (limit & 0x000f0000) | ((type & 0xff) << 8) | ((flags & 0xf) << 20);
- desc->p = 1;
-}
-
static inline void pack_gate(gate_desc *gate,
unsigned long base, unsigned short seg, unsigned char type, unsigned char flags)
{
@@ -40,115 +19,6 @@ static inline void pack_gate(gate_desc *
gate->b = (base & 0xffff0000) | ((type & 0xff) << 8) | (flags & 0xff);
}

-#ifdef CONFIG_PARAVIRT
-#include <asm/paravirt.h>
-#else
-#define load_TR_desc() native_load_tr_desc()
-#define load_gdt(dtr) native_load_gdt(dtr)
-#define load_idt(dtr) native_load_idt(dtr)
-#define load_tr(tr) __asm__ __volatile("ltr %0"::"m" (tr))
-#define load_ldt(ldt) __asm__ __volatile("lldt %0"::"m" (ldt))
-
-#define store_gdt(dtr) native_store_gdt(dtr)
-#define store_idt(dtr) native_store_idt(dtr)
-#define store_tr(tr) (tr = native_store_tr())
-#define store_ldt(ldt) __asm__ ("sldt %0":"=m" (ldt))
-
-#define load_TLS(t, cpu) native_load_tls(t, cpu)
-#define set_ldt native_set_ldt
-
-#define write_ldt_entry(dt, entry, desc) \
- native_write_ldt_entry(dt, entry, desc)
-#define write_gdt_entry(dt, entry, desc, type) \
- native_write_gdt_entry(dt, entry, desc, type)
-#define write_idt_entry(dt, entry, g) native_write_idt_entry(dt, entry, g)
-#endif
-
-static inline void native_write_ldt_entry(struct desc_struct *ldt, int entry,
- const void *desc)
-{
- memcpy(&ldt[entry], desc, sizeof(struct desc_struct));
-}
-
-static inline void native_write_idt_entry(gate_desc *idt, int entry,
- const gate_desc *gate)
-{
- memcpy(&idt[entry], gate, sizeof(*gate));
-}
-
-static inline void native_write_gdt_entry(struct desc_struct *gdt, int entry,
- const void *desc, int type)
-{
- memcpy(&gdt[entry], desc, sizeof(struct desc_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;
-}
-
-
-static inline void native_set_ldt(const void *addr, unsigned int entries)
-{
- if (likely(entries == 0))
- __asm__ __volatile__("lldt %w0"::"q" (0));
- else {
- unsigned cpu = smp_processor_id();
- ldt_desc ldt;
-
- pack_descriptor(&ldt, (unsigned long)addr,
- entries * sizeof(struct desc_struct) - 1,
- DESC_LDT, 0);
- write_gdt_entry(get_cpu_gdt_table(cpu), GDT_ENTRY_LDT,
- &ldt, DESC_LDT);
- __asm__ __volatile__("lldt %w0"::"q" (GDT_ENTRY_LDT*8));
- }
-}
-
-
-static inline void native_load_tr_desc(void)
-{
- asm volatile("ltr %w0"::"q" (GDT_ENTRY_TSS*8));
-}
-
-static inline void native_load_gdt(const struct desc_ptr *dtr)
-{
- asm volatile("lgdt %0"::"m" (*dtr));
-}
-
-static inline void native_load_idt(const struct desc_ptr *dtr)
-{
- asm volatile("lidt %0"::"m" (*dtr));
-}
-
-static inline void native_store_gdt(struct desc_ptr *dtr)
-{
- asm ("sgdt %0":"=m" (*dtr));
-}
-
-static inline void native_store_idt(struct desc_ptr *dtr)
-{
- asm ("sidt %0":"=m" (*dtr));
-}
-
-static inline unsigned long native_store_tr(void)
-{
- unsigned long tr;
- asm ("str %0":"=r" (tr));
- return tr;
-}
-
-static inline void native_load_tls(struct thread_struct *t, unsigned int cpu)
-{
- unsigned int i;
- struct desc_struct *gdt = get_cpu_gdt_table(cpu);
-
- for (i = 0; i < GDT_ENTRY_TLS_ENTRIES; i++)
- gdt[GDT_ENTRY_TLS_MIN + i] = t->tls_array[i];
-}
-
static inline void _set_gate(int gate, unsigned int type, void *addr, unsigned short seg)
{
gate_desc g;
Index: linux-2.6-x86/include/asm-x86/desc_64.h
===================================================================
--- linux-2.6-x86.orig/include/asm-x86/desc_64.h
+++ linux-2.6-x86/include/asm-x86/desc_64.h
@@ -8,47 +8,10 @@
#ifndef __ASSEMBLY__

#include <linux/string.h>
-#include <linux/smp.h>

#include <asm/segment.h>

-extern struct desc_struct cpu_gdt_table[GDT_ENTRIES];
-
-#define load_TR_desc() asm volatile("ltr %w0"::"r" (GDT_ENTRY_TSS*8))
-#define load_LDT_desc() asm volatile("lldt %w0"::"r" (GDT_ENTRY_LDT*8))
-
-static inline unsigned long __store_tr(void)
-{
- unsigned long tr;
-
- asm volatile ("str %w0":"=r" (tr));
- return tr;
-}
-
-#define store_tr(tr) (tr) = __store_tr()
-
-extern struct desc_ptr cpu_gdt_descr[];
-
-static inline void write_ldt_entry(struct desc_struct *ldt,
- int entry, void *ptr)
-{
- memcpy(&ldt[entry], ptr, 8);
-}
-
-/* the cpu gdt accessor */
-#define get_cpu_gdt_table(x) ((struct desc_struct *)cpu_gdt_descr[x].address)
-
-static inline void load_gdt(const struct desc_ptr *ptr)
-{
- asm volatile("lgdt %w0"::"m" (*ptr));
-}
-
-static inline void store_gdt(struct desc_ptr *ptr)
-{
- asm("sgdt %w0":"=m" (*ptr));
-}
-
-static inline void _set_gate(void *adr, unsigned type, unsigned long func,
+static inline void _set_gate(int gate, unsigned type, unsigned long func,
unsigned dpl, unsigned ist)
{
gate_desc s;
@@ -67,61 +30,37 @@ static inline void _set_gate(void *adr,
* does not need to be atomic because it is only done once at
* setup time
*/
- memcpy(adr, &s, 16);
+ write_idt_entry(idt_table, gate, &s);
}

static inline void set_intr_gate(int nr, void *func)
{
BUG_ON((unsigned)nr > 0xFF);
- _set_gate(&idt_table[nr], GATE_INTERRUPT, (unsigned long) func, 0, 0);
+ _set_gate(nr, GATE_INTERRUPT, (unsigned long) func, 0, 0);
}

static inline void set_intr_gate_ist(int nr, void *func, unsigned ist)
{
BUG_ON((unsigned)nr > 0xFF);
- _set_gate(&idt_table[nr], GATE_INTERRUPT, (unsigned long) func, 0, ist);
+ _set_gate(nr, GATE_INTERRUPT, (unsigned long) func, 0, ist);
}

static inline void set_system_gate(int nr, void *func)
{
BUG_ON((unsigned)nr > 0xFF);
- _set_gate(&idt_table[nr], GATE_INTERRUPT, (unsigned long) func, 3, 0);
+ _set_gate(nr, GATE_INTERRUPT, (unsigned long) func, 3, 0);
}

static inline void set_system_gate_ist(int nr, void *func, unsigned ist)
{
- _set_gate(&idt_table[nr], GATE_INTERRUPT, (unsigned long) func, 3, ist);
-}
-
-static inline void load_idt(const struct desc_ptr *ptr)
-{
- asm volatile("lidt %w0"::"m" (*ptr));
-}
-
-static inline void store_idt(struct desc_ptr *dtr)
-{
- asm("sidt %w0":"=m" (*dtr));
-}
-
-static inline void set_tssldt_descriptor(void *ptr, unsigned long tss,
- unsigned type, unsigned size)
-{
- struct ldttss_desc64 d;
-
- memset(&d, 0, sizeof(d));
- d.limit0 = size & 0xFFFF;
- d.base0 = PTR_LOW(tss);
- d.base1 = PTR_MIDDLE(tss) & 0xFF;
- d.type = type;
- d.p = 1;
- d.limit1 = (size >> 16) & 0xF;
- d.base2 = (PTR_MIDDLE(tss) >> 8) & 0xFF;
- d.base3 = PTR_HIGH(tss);
- memcpy(ptr, &d, 16);
+ _set_gate(nr, GATE_INTERRUPT, (unsigned long) func, 3, ist);
}

static inline void set_tss_desc(unsigned cpu, void *addr)
{
+ struct desc_struct *d = get_cpu_gdt_table(cpu);
+ tss_desc tss;
+
/*
* sizeof(unsigned long) coming from an extra "long" at the end
* of the iobitmap. See tss_struct definition in processor.h
@@ -129,31 +68,10 @@ static inline void set_tss_desc(unsigned
* -1? seg base+limit should be pointing to the address of the
* last valid byte
*/
- set_tssldt_descriptor(&get_cpu_gdt_table(cpu)[GDT_ENTRY_TSS],
+ set_tssldt_descriptor(&tss,
(unsigned long)addr, DESC_TSS,
IO_BITMAP_OFFSET + IO_BITMAP_BYTES + sizeof(unsigned long) - 1);
-}
-
-static inline void set_ldt(void *addr, int entries)
-{
- if (likely(entries == 0))
- __asm__ __volatile__("lldt %w0"::"q" (0));
- else {
- unsigned cpu = smp_processor_id();
-
- set_tssldt_descriptor(&get_cpu_gdt_table(cpu)[GDT_ENTRY_LDT],
- (unsigned long)addr, DESC_LDT, entries * 8 - 1);
- __asm__ __volatile__("lldt %w0"::"q" (GDT_ENTRY_LDT*8));
- }
-}
-
-static inline void load_TLS(struct thread_struct *t, unsigned int cpu)
-{
- unsigned int i;
- struct desc_struct *gdt = (get_cpu_gdt_table(cpu) + GDT_ENTRY_TLS_MIN);
-
- for (i = 0; i < GDT_ENTRY_TLS_ENTRIES; i++)
- gdt[i] = t->tls_array[i];
+ write_gdt_entry(d, GDT_ENTRY_TSS, &tss, sizeof(tss_desc));
}

#endif /* !__ASSEMBLY__ */
Index: linux-2.6-x86/include/asm-x86/desc_defs.h
===================================================================
--- linux-2.6-x86.orig/include/asm-x86/desc_defs.h
+++ linux-2.6-x86/include/asm-x86/desc_defs.h
@@ -48,9 +48,9 @@ struct gate_struct64 {
u32 zero1;
} __attribute__((packed));

-#define PTR_LOW(x) ((unsigned long)(x) & 0xFFFF)
-#define PTR_MIDDLE(x) (((unsigned long)(x) >> 16) & 0xFFFF)
-#define PTR_HIGH(x) ((unsigned long)(x) >> 32)
+#define PTR_LOW(x) ((unsigned long long)(x) & 0xFFFF)
+#define PTR_MIDDLE(x) (((unsigned long long)(x) >> 16) & 0xFFFF)
+#define PTR_HIGH(x) ((unsigned long long)(x) >> 32)

enum {
DESC_TSS = 0x9,

2007-12-12 15:44:16

by Glauber Costa

[permalink] [raw]
Subject: [PATCH 16/19] modify get_desc_base

This patch makes get_desc_base() receive a struct desc_struct,
and then uses its internal fields to compute the base address.

Signed-off-by: Glauber de Oliveira Costa <[email protected]>
---
arch/x86/kernel/tls.c | 2 +-
arch/x86/mm/fault_32.c | 2 +-
include/asm-x86/desc.h | 8 ++------
3 files changed, 4 insertions(+), 8 deletions(-)

diff --git a/arch/x86/kernel/tls.c b/arch/x86/kernel/tls.c
index 74d2b65..98f428b 100644
--- a/arch/x86/kernel/tls.c
+++ b/arch/x86/kernel/tls.c
@@ -112,7 +112,7 @@ int do_get_thread_area(struct task_struct *p, int idx,

memset(&info, 0, sizeof(struct user_desc));
info.entry_number = idx;
- info.base_addr = get_desc_base((void *)desc);
+ info.base_addr = get_desc_base((struct desc_struct *)desc);
info.limit = GET_LIMIT(desc);
info.seg_32bit = GET_32BIT(desc);
info.contents = GET_CONTENTS(desc);
diff --git a/arch/x86/mm/fault_32.c b/arch/x86/mm/fault_32.c
index 6056c6d..ef5ab2b 100644
--- a/arch/x86/mm/fault_32.c
+++ b/arch/x86/mm/fault_32.c
@@ -115,7 +115,7 @@ static inline unsigned long get_segment_eip(struct pt_regs *regs,
}

/* Decode the code segment base from the descriptor */
- base = get_desc_base((unsigned long *)desc);
+ base = get_desc_base((struct desc_struct *)desc);

if (seg & (1<<2)) {
mutex_unlock(&current->mm->context.lock);
diff --git a/include/asm-x86/desc.h b/include/asm-x86/desc.h
index 926d6f8..3480cb1 100644
--- a/include/asm-x86/desc.h
+++ b/include/asm-x86/desc.h
@@ -55,13 +55,9 @@ static inline void load_LDT(mm_context_t *pc)
preempt_enable();
}

-static inline unsigned long get_desc_base(unsigned long *desc)
+static inline unsigned long get_desc_base(struct desc_struct *desc)
{
- unsigned long base;
- base = ((desc[0] >> 16) & 0x0000ffff) |
- ((desc[1] << 16) & 0x00ff0000) |
- (desc[1] & 0xff000000);
- return base;
+ return desc->base0 | ((desc->base1) << 16) | ((desc->base2) << 24);
}

#else
--
1.5.0.6

2007-12-12 15:44:48

by Glauber Costa

[permalink] [raw]
Subject: [PATCH 19/19] unify set_tss_desc

This patch unifies the set_tss_desc between i386 and x86_64,
which can now have a common implementation. After the old
functions are removed from desc_{32,64}.h, nothing important is
left, and the files can be removed.

Signed-off-by: Glauber de Oliveira Costa <[email protected]>
---
include/asm-x86/desc.h | 40 +++++++++++++++++++++++++++++++++-------
include/asm-x86/desc_32.h | 27 ---------------------------
include/asm-x86/desc_64.h | 34 ----------------------------------
3 files changed, 33 insertions(+), 68 deletions(-)
delete mode 100644 include/asm-x86/desc_32.h
delete mode 100644 include/asm-x86/desc_64.h

Index: linux-2.6-x86/include/asm-x86/desc.h
===================================================================
--- linux-2.6-x86.orig/include/asm-x86/desc.h
+++ linux-2.6-x86/include/asm-x86/desc.h
@@ -147,6 +147,39 @@ static inline void pack_ldt(ldt_desc *ld
#endif
}

+static inline void pack_tss(tss_desc *tss, unsigned long addr,
+ unsigned size, unsigned entry)
+{
+#ifdef CONFIG_X86_64
+ set_tssldt_descriptor(tss,
+ addr, entry, size);
+#else
+ pack_descriptor(tss, (unsigned long)addr,
+ size,
+ 0x80 | entry, 0);
+#endif
+}
+
+static inline void __set_tss_desc(unsigned cpu, unsigned int entry, void *addr)
+{
+ struct desc_struct *d = get_cpu_gdt_table(cpu);
+ tss_desc tss;
+
+ /*
+ * sizeof(unsigned long) coming from an extra "long" at the end
+ * of the iobitmap. See tss_struct definition in processor.h
+ *
+ * -1? seg base+limit should be pointing to the address of the
+ * last valid byte
+ */
+ pack_tss(&tss, (unsigned long)addr,
+ IO_BITMAP_OFFSET + IO_BITMAP_BYTES + sizeof(unsigned long) - 1,
+ DESC_TSS);
+ write_gdt_entry(d, entry, &tss, sizeof(tss));
+}
+
+#define set_tss_desc(cpu, addr) __set_tss_desc(cpu, GDT_ENTRY_TSS, addr)
+
static inline void native_set_ldt(const void *addr, unsigned int entries)
{
if (likely(entries == 0))
@@ -205,13 +238,6 @@ static inline void native_load_tls(struc
}
#endif /* __ASSEMBLY__ */

-
-#ifdef CONFIG_X86_32
-# include "desc_32.h"
-#else
-# include "desc_64.h"
-#endif
-
#ifndef __ASSEMBLY__

#define _LDT_empty(info) (\
Index: linux-2.6-x86/include/asm-x86/desc_32.h
===================================================================
--- linux-2.6-x86.orig/include/asm-x86/desc_32.h
+++ /dev/null
@@ -1,27 +0,0 @@
-#ifndef __ARCH_DESC_H
-#define __ARCH_DESC_H
-
-#include <asm/ldt.h>
-#include <asm/segment.h>
-#include <asm/desc_defs.h>
-
-#ifndef __ASSEMBLY__
-
-#include <linux/preempt.h>
-#include <linux/percpu.h>
-
-static inline void __set_tss_desc(unsigned int cpu, unsigned int entry, const void *addr)
-{
- tss_desc tss;
- pack_descriptor(&tss, (unsigned long)addr,
- offsetof(struct tss_struct, __cacheline_filler) - 1,
- DESC_TSS, 0);
- write_gdt_entry(get_cpu_gdt_table(cpu), entry, &tss, DESC_TSS);
-}
-
-
-#define set_tss_desc(cpu,addr) __set_tss_desc(cpu, GDT_ENTRY_TSS, addr)
-
-#endif /* !__ASSEMBLY__ */
-
-#endif
Index: linux-2.6-x86/include/asm-x86/desc_64.h
===================================================================
--- linux-2.6-x86.orig/include/asm-x86/desc_64.h
+++ /dev/null
@@ -1,34 +0,0 @@
-/* Written 2000 by Andi Kleen */
-#ifndef __ARCH_DESC_H
-#define __ARCH_DESC_H
-
-#include <linux/threads.h>
-#include <asm/ldt.h>
-
-#ifndef __ASSEMBLY__
-
-#include <linux/string.h>
-
-#include <asm/segment.h>
-
-static inline void set_tss_desc(unsigned cpu, void *addr)
-{
- struct desc_struct *d = get_cpu_gdt_table(cpu);
- tss_desc tss;
-
- /*
- * sizeof(unsigned long) coming from an extra "long" at the end
- * of the iobitmap. See tss_struct definition in processor.h
- *
- * -1? seg base+limit should be pointing to the address of the
- * last valid byte
- */
- set_tssldt_descriptor(&tss,
- (unsigned long)addr, DESC_TSS,
- IO_BITMAP_OFFSET + IO_BITMAP_BYTES + sizeof(unsigned long) - 1);
- write_gdt_entry(d, GDT_ENTRY_TSS, &tss, sizeof(tss_desc));
-}
-
-#endif /* !__ASSEMBLY__ */
-
-#endif

2007-12-12 15:45:05

by Glauber Costa

[permalink] [raw]
Subject: [PATCH 18/19] move _set_gate and its users to a common location

This patch moves _set_gate and its users to desc.h. We can now
use common code for x86_64 and i386.

Signed-off-by: Glauber de Oliveira Costa <[email protected]>
---
arch/x86/kernel/traps_32.c | 34 ----------------
include/asm-x86/desc.h | 88 +++++++++++++++++++++++++++++++++++++++++++
include/asm-x86/desc_32.h | 16 --------
include/asm-x86/desc_64.h | 45 ----------------------
include/asm-x86/desc_defs.h | 5 +--
5 files changed, 89 insertions(+), 99 deletions(-)

Index: linux-2.6-x86/arch/x86/kernel/traps_32.c
===================================================================
--- linux-2.6-x86.orig/arch/x86/kernel/traps_32.c
+++ linux-2.6-x86/arch/x86/kernel/traps_32.c
@@ -1102,40 +1102,6 @@ asmlinkage void math_emulate(long arg)

#endif /* CONFIG_MATH_EMULATION */

-/*
- * This needs to use 'idt_table' rather than 'idt', and
- * thus use the _nonmapped_ version of the IDT, as the
- * Pentium F0 0F bugfix can have resulted in the mapped
- * IDT being write-protected.
- */
-void set_intr_gate(unsigned int n, void *addr)
-{
- _set_gate(n, DESCTYPE_INT, addr, __KERNEL_CS);
-}
-
-/*
- * This routine sets up an interrupt gate at directory privilege level 3.
- */
-static inline void set_system_intr_gate(unsigned int n, void *addr)
-{
- _set_gate(n, DESCTYPE_INT | DESCTYPE_DPL3, addr, __KERNEL_CS);
-}
-
-static void __init set_trap_gate(unsigned int n, void *addr)
-{
- _set_gate(n, DESCTYPE_TRAP, addr, __KERNEL_CS);
-}
-
-static void __init set_system_gate(unsigned int n, void *addr)
-{
- _set_gate(n, DESCTYPE_TRAP | DESCTYPE_DPL3, addr, __KERNEL_CS);
-}
-
-static void __init set_task_gate(unsigned int n, unsigned int gdt_entry)
-{
- _set_gate(n, DESCTYPE_TASK, (void *)0, (gdt_entry<<3));
-}
-

void __init trap_init(void)
{
Index: linux-2.6-x86/include/asm-x86/desc.h
===================================================================
--- linux-2.6-x86.orig/include/asm-x86/desc.h
+++ linux-2.6-x86/include/asm-x86/desc.h
@@ -15,6 +15,22 @@ extern struct desc_struct cpu_gdt_table[
extern struct desc_ptr cpu_gdt_descr[];
/* the cpu gdt accessor */
#define get_cpu_gdt_table(x) ((struct desc_struct *)cpu_gdt_descr[x].address)
+
+static inline void pack_gate(gate_desc *gate, unsigned type, unsigned long func,
+ unsigned dpl, unsigned ist, unsigned seg)
+{
+ gate->offset_low = PTR_LOW(func);
+ gate->segment = __KERNEL_CS;
+ gate->ist = ist;
+ gate->p = 1;
+ gate->dpl = dpl;
+ gate->zero0 = 0;
+ gate->zero1 = 0;
+ gate->type = type;
+ gate->offset_middle = PTR_MIDDLE(func);
+ gate->offset_high = PTR_HIGH(func);
+}
+
#else
struct gdt_page {
struct desc_struct gdt[GDT_ENTRIES];
@@ -25,6 +41,16 @@ static inline struct desc_struct *get_cp
{
return per_cpu(gdt_page, cpu).gdt;
}
+
+static inline void pack_gate(gate_desc *gate, unsigned char type,
+ unsigned long base, unsigned dpl, unsigned flags, unsigned short seg)
+
+{
+ gate->a = (seg << 16) | (base & 0xffff);
+ gate->b = (base & 0xffff0000) |
+ (((0x80 | type | (dpl << 5)) & 0xff) << 8);
+}
+
#endif

#ifdef CONFIG_PARAVIRT
@@ -228,6 +254,68 @@ static inline unsigned long get_desc_bas
{
return desc->base0 | ((desc->base1) << 16) | ((desc->base2) << 24);
}
+static inline void _set_gate(int gate, unsigned type, void *addr,
+ unsigned dpl, unsigned ist, unsigned seg)
+{
+ gate_desc s;
+ pack_gate(&s, type, (unsigned long)addr, dpl, ist, seg);
+ /*
+ * does not need to be atomic because it is only done once at
+ * setup time
+ */
+ write_idt_entry(idt_table, gate, &s);
+}
+
+/*
+ * This needs to use 'idt_table' rather than 'idt', and
+ * thus use the _nonmapped_ version of the IDT, as the
+ * Pentium F0 0F bugfix can have resulted in the mapped
+ * IDT being write-protected.
+ */
+static inline void set_intr_gate(unsigned int n, void *addr)
+{
+ BUG_ON((unsigned)n > 0xFF);
+ _set_gate(n, GATE_INTERRUPT, addr, 0, 0, __KERNEL_CS);
+}
+
+/*
+ * This routine sets up an interrupt gate at directory privilege level 3.
+ */
+static inline void set_system_intr_gate(unsigned int n, void *addr)
+{
+ BUG_ON((unsigned)n > 0xFF);
+ _set_gate(n, GATE_INTERRUPT, addr, 0x3, 0, __KERNEL_CS);
+}
+
+static inline void set_trap_gate(unsigned int n, void *addr)
+{
+ BUG_ON((unsigned)n > 0xFF);
+ _set_gate(n, GATE_TRAP, addr, 0, 0, __KERNEL_CS);
+}
+
+static inline void set_system_gate(unsigned int n, void *addr)
+{
+ BUG_ON((unsigned)n > 0xFF);
+ _set_gate(n, GATE_TRAP, addr, 0x3, 0, __KERNEL_CS);
+}
+
+static inline void set_task_gate(unsigned int n, unsigned int gdt_entry)
+{
+ BUG_ON((unsigned)n > 0xFF);
+ _set_gate(n, GATE_TASK, (void *)0, 0, 0, (gdt_entry<<3));
+}
+
+static inline void set_intr_gate_ist(int n, void *addr, unsigned ist)
+{
+ BUG_ON((unsigned)n > 0xFF);
+ _set_gate(n, GATE_INTERRUPT, addr, 0, ist, __KERNEL_CS);
+}
+
+static inline void set_system_gate_ist(int n, void *addr, unsigned ist)
+{
+ BUG_ON((unsigned)n > 0xFF);
+ _set_gate(n, GATE_INTERRUPT, addr, 0x3, ist, __KERNEL_CS);
+}

#else
/*
Index: linux-2.6-x86/include/asm-x86/desc_32.h
===================================================================
--- linux-2.6-x86.orig/include/asm-x86/desc_32.h
+++ linux-2.6-x86/include/asm-x86/desc_32.h
@@ -10,22 +10,6 @@
#include <linux/preempt.h>
#include <linux/percpu.h>

-extern void set_intr_gate(unsigned int irq, void * addr);
-
-static inline void pack_gate(gate_desc *gate,
- unsigned long base, unsigned short seg, unsigned char type, unsigned char flags)
-{
- gate->a = (seg << 16) | (base & 0xffff);
- gate->b = (base & 0xffff0000) | ((type & 0xff) << 8) | (flags & 0xff);
-}
-
-static inline void _set_gate(int gate, unsigned int type, void *addr, unsigned short seg)
-{
- gate_desc g;
- pack_gate(&g, (unsigned long)addr, seg, type, 0);
- write_idt_entry(idt_table, gate, &g);
-}
-
static inline void __set_tss_desc(unsigned int cpu, unsigned int entry, const void *addr)
{
tss_desc tss;
Index: linux-2.6-x86/include/asm-x86/desc_64.h
===================================================================
--- linux-2.6-x86.orig/include/asm-x86/desc_64.h
+++ linux-2.6-x86/include/asm-x86/desc_64.h
@@ -11,51 +11,6 @@

#include <asm/segment.h>

-static inline void _set_gate(int gate, unsigned type, unsigned long func,
- unsigned dpl, unsigned ist)
-{
- gate_desc s;
-
- s.offset_low = PTR_LOW(func);
- s.segment = __KERNEL_CS;
- s.ist = ist;
- s.p = 1;
- s.dpl = dpl;
- s.zero0 = 0;
- s.zero1 = 0;
- s.type = type;
- s.offset_middle = PTR_MIDDLE(func);
- s.offset_high = PTR_HIGH(func);
- /*
- * does not need to be atomic because it is only done once at
- * setup time
- */
- write_idt_entry(idt_table, gate, &s);
-}
-
-static inline void set_intr_gate(int nr, void *func)
-{
- BUG_ON((unsigned)nr > 0xFF);
- _set_gate(nr, GATE_INTERRUPT, (unsigned long) func, 0, 0);
-}
-
-static inline void set_intr_gate_ist(int nr, void *func, unsigned ist)
-{
- BUG_ON((unsigned)nr > 0xFF);
- _set_gate(nr, GATE_INTERRUPT, (unsigned long) func, 0, ist);
-}
-
-static inline void set_system_gate(int nr, void *func)
-{
- BUG_ON((unsigned)nr > 0xFF);
- _set_gate(nr, GATE_INTERRUPT, (unsigned long) func, 3, 0);
-}
-
-static inline void set_system_gate_ist(int nr, void *func, unsigned ist)
-{
- _set_gate(nr, GATE_INTERRUPT, (unsigned long) func, 3, ist);
-}
-
static inline void set_tss_desc(unsigned cpu, void *addr)
{
struct desc_struct *d = get_cpu_gdt_table(cpu);
Index: linux-2.6-x86/include/asm-x86/desc_defs.h
===================================================================
--- linux-2.6-x86.orig/include/asm-x86/desc_defs.h
+++ linux-2.6-x86/include/asm-x86/desc_defs.h
@@ -36,6 +36,7 @@ enum {
GATE_INTERRUPT = 0xE,
GATE_TRAP = 0xF,
GATE_CALL = 0xC,
+ GATE_TASK = 0x5,
};

// 16byte gate
@@ -55,10 +56,6 @@ struct gate_struct64 {
enum {
DESC_TSS = 0x9,
DESC_LDT = 0x2,
- DESCTYPE_TASK = 0x85, /* present, system, DPL-0, task gate */
- DESCTYPE_INT = 0x8e, /* present, system, DPL-0, interrupt gate */
- DESCTYPE_TRAP = 0x8f, /* present, system, DPL-0, trap gate */
- DESCTYPE_DPL3 = 0x60, /* DPL-3 */
DESCTYPE_S = 0x10, /* !system */
};

2007-12-12 17:21:18

by Ingo Molnar

[permalink] [raw]
Subject: Re: [PATCH 0/19] desc_struct integration


* Glauber de Oliveira Costa <[email protected]> wrote:

> Since the last version of it received no comments on the interfaces,
> here it goes a version, that I feel ready for inclusion.
>
> The comments regarding style, specially the elimination of the
> #defines in the desc_struct definition were merged. I also implemented
> the vmi functions, missing last time.
>
> Ingo, in the absense of further complaints, could you please push to
> the x86 tree?

yeah, i've added them.

Ingo

2007-12-12 18:07:07

by Ingo Molnar

[permalink] [raw]
Subject: Re: [PATCH 09/19] introduce fill_ldt


* Glauber de Oliveira Costa <[email protected]> wrote:

> diff --git a/include/asm-x86/ldt.h b/include/asm-x86/ldt.h
> index 20c5972..49013fd 100644
> --- a/include/asm-x86/ldt.h
> +++ b/include/asm-x86/ldt.h
> @@ -5,6 +5,7 @@
> */
> #ifndef _ASM_X86_LDT_H
> #define _ASM_X86_LDT_H
> +#include <asm/desc_defs.h>

this breaks CONFIG_HEADERS_CHECK=y, because asm/desc_defs.h is not an
exported header.

Ingo

2007-12-12 18:15:17

by Ingo Molnar

[permalink] [raw]
Subject: Re: [PATCH 0/19] desc_struct integration


* Ingo Molnar <[email protected]> wrote:

> > Since the last version of it received no comments on the interfaces,
> > here it goes a version, that I feel ready for inclusion.
> >
> > The comments regarding style, specially the elimination of the
> > #defines in the desc_struct definition were merged. I also
> > #implemented
> > the vmi functions, missing last time.
> >
> > Ingo, in the absense of further complaints, could you please push to
> > the x86 tree?
>
> yeah, i've added them.

the patches cause a spontaneous reboot on x86 64-bit, around the time
when bootup hits user-space. It's due to one of the 25 patches from you
today. Config attached.

Ingo


Attachments:
(No filename) (669.00 B)
config (48.26 kB)
Download all attachments

2007-12-12 18:21:36

by Ingo Molnar

[permalink] [raw]
Subject: Re: [PATCH 0/19] desc_struct integration


* Ingo Molnar <[email protected]> wrote:

> > > Ingo, in the absense of further complaints, could you please push
> > > to the x86 tree?
> >
> > yeah, i've added them.
>
> the patches cause a spontaneous reboot on x86 64-bit, around the time
> when bootup hits user-space. It's due to one of the 25 patches from
> you today. Config attached.

likely caused by this patch:

Subject: unify non-paravirt parts of desc.h

_please_ be more careful when unifying. Do check the before/after
vmlinux - the binary size at least. And watch out for compiler warnings
as well:

arch/x86/kernel/process_64.c: In function 'read_32bit_tls':
arch/x86/kernel/process_64.c:454: warning: passing argument 1 of 'get_desc_base' from incompatible pointer type

i've pulled the patches from the tree for now.

Ingo

2007-12-12 18:28:18

by Glauber Costa

[permalink] [raw]
Subject: Re: [PATCH 0/19] desc_struct integration

Ingo Molnar wrote:
> * Ingo Molnar <[email protected]> wrote:
>
>>>> Ingo, in the absense of further complaints, could you please push
>>>> to the x86 tree?
>>> yeah, i've added them.
>> the patches cause a spontaneous reboot on x86 64-bit, around the time
>> when bootup hits user-space. It's due to one of the 25 patches from
>> you today. Config attached.
>
> likely caused by this patch:
>
> Subject: unify non-paravirt parts of desc.h
>
> _please_ be more careful when unifying. Do check the before/after
> vmlinux - the binary size at least. And watch out for compiler warnings
> as well:
>
> arch/x86/kernel/process_64.c: In function 'read_32bit_tls':
> arch/x86/kernel/process_64.c:454: warning: passing argument 1 of 'get_desc_base' from incompatible pointer type
I saw this warning, and this was fixed in the patch that follows. But
yeah, I could have done a separate one, to avoid it. Do you have any
other reason to believe this is the cause?

My box booted fine with the changes, but I'm re-verifying, and will send
and update soon.

> i've pulled the patches from the tree for now.
Ok, I'll investigate it, meanwhile.

2007-12-12 18:35:17

by Ingo Molnar

[permalink] [raw]
Subject: Re: [PATCH 0/19] desc_struct integration


* Glauber de Oliveira Costa <[email protected]> wrote:

> Ingo Molnar wrote:
>> * Ingo Molnar <[email protected]> wrote:
>>
>>>>> Ingo, in the absense of further complaints, could you please push to
>>>>> the x86 tree?
>>>> yeah, i've added them.
>>> the patches cause a spontaneous reboot on x86 64-bit, around the time
>>> when bootup hits user-space. It's due to one of the 25 patches from you
>>> today. Config attached.
>>
>> likely caused by this patch:
>>
>> Subject: unify non-paravirt parts of desc.h
>>
>> _please_ be more careful when unifying. Do check the before/after vmlinux
>> - the binary size at least. And watch out for compiler warnings as well:
>>
>> arch/x86/kernel/process_64.c: In function 'read_32bit_tls':
>> arch/x86/kernel/process_64.c:454: warning: passing argument 1 of 'get_desc_base' from incompatible pointer type

> I saw this warning, and this was fixed in the patch that follows. But
> yeah, I could have done a separate one, to avoid it. Do you have any
> other reason to believe this is the cause?

that is bisection-unfriendly - every patch has to work.

> My box booted fine with the changes, but I'm re-verifying, and will
> send and update soon.

please try the config i sent - does that boot fine on your box?

Ingo

2007-12-12 18:35:52

by Ingo Molnar

[permalink] [raw]
Subject: Re: [PATCH 0/19] desc_struct integration


before i pulled the patches i narrowed the problem down to one of the
last ~6 patches in your 25-patch series. I couldnt continue bisecting it
when i saw that process_64.c warning.

Ingo

2007-12-12 19:07:18

by Glauber Costa

[permalink] [raw]
Subject: Re: [PATCH 0/19] desc_struct integration

Ingo Molnar wrote:
> * Glauber de Oliveira Costa <[email protected]> wrote:
>
>> Ingo Molnar wrote:
>>> * Ingo Molnar <[email protected]> wrote:
>>>
>>>>>> Ingo, in the absense of further complaints, could you please push to
>>>>>> the x86 tree?
>>>>> yeah, i've added them.
>>>> the patches cause a spontaneous reboot on x86 64-bit, around the time
>>>> when bootup hits user-space. It's due to one of the 25 patches from you
>>>> today. Config attached.
>>> likely caused by this patch:
>>>
>>> Subject: unify non-paravirt parts of desc.h
>>>
>>> _please_ be more careful when unifying. Do check the before/after vmlinux
>>> - the binary size at least. And watch out for compiler warnings as well:
>>>
>>> arch/x86/kernel/process_64.c: In function 'read_32bit_tls':
>>> arch/x86/kernel/process_64.c:454: warning: passing argument 1 of 'get_desc_base' from incompatible pointer type
>
>> I saw this warning, and this was fixed in the patch that follows. But
>> yeah, I could have done a separate one, to avoid it. Do you have any
>> other reason to believe this is the cause?
>
> that is bisection-unfriendly - every patch has to work.
I know, and I'm sorry. I thought it was not that bad, by being just a
warning due to a type cast. ;-)
(famous last words, I know)

>> My box booted fine with the changes, but I'm re-verifying, and will
>> send and update soon.
>
> please try the config i sent - does that boot fine on your box?
No, it doesn't. I'll bisect it, and send an updated series, with your 3
concerns addressed.

2007-12-12 23:41:33

by H. Peter Anvin

[permalink] [raw]
Subject: Re: [PATCH 0/19] desc_struct integration

Glauber de Oliveira Costa wrote:
> Since the last version of it received no comments on the interfaces, here
> it goes a version, that I feel ready for inclusion.
>
> The comments regarding style, specially the elimination of the #defines in
> the desc_struct definition were merged. I also implemented the vmi
> functions,
> missing last time.
>
> Ingo, in the absense of further complaints, could you please push to the
> x86 tree?
>

Looks fine to me...

-hpa

2007-12-13 04:46:20

by Glauber Costa

[permalink] [raw]
Subject: [PATCH 0/19 - v3] desc_struct integration

Here it goes a new version of the patchset.

It addresses the problems raised, namely:
* it does not harm make headers_check anymore. (fill_ldt is moved to desc.h)
* it fixes the x86_64 spontaneous boot problem
* it does not have a warning at get_desc_base() anymore.


2007-12-13 04:46:36

by Glauber Costa

[permalink] [raw]
Subject: [PATCH 01/19] unify desc_struct

This patch aims to make the access of struct desc_struct variables
equal across architectures. In this patch, I unify the i386 and x86_64
versions under an anonymous union, keeping the way they are accessed
untouched (a and b for 32-bit code, individual bit-fields for 64-bit).

This solution is not beautiful, but will allow us to integrate common
code that differed by the way descriptors were used. This is to be viewed
incrementally. There's simply too much code to be fixed at once.

In the future, goal is to set up in a single way of acessing
the desc_struct fields.

Signed-off-by: Glauber de Oliveira Costa <[email protected]>
---
arch/x86/kernel/apm_32.c | 2 +-
arch/x86/kernel/cpu/common.c | 28 ++++++++++++++--------------
arch/x86/kernel/process_64.c | 2 +-
arch/x86/kernel/traps_32.c | 2 +-
include/asm-x86/desc_defs.h | 25 +++++++++++++++++--------
include/asm-x86/lguest.h | 4 ++--
include/asm-x86/processor_32.h | 5 +----
7 files changed, 37 insertions(+), 31 deletions(-)

Index: linux-2.6-x86/arch/x86/kernel/apm_32.c
===================================================================
--- linux-2.6-x86.orig/arch/x86/kernel/apm_32.c
+++ linux-2.6-x86/arch/x86/kernel/apm_32.c
@@ -405,7 +405,7 @@ static DECLARE_WAIT_QUEUE_HEAD(apm_waitq
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 = { { { 0, 0x00409200 } } };

static const char driver_version[] = "1.16ac"; /* no spaces */

Index: linux-2.6-x86/arch/x86/kernel/cpu/common.c
===================================================================
--- linux-2.6-x86.orig/arch/x86/kernel/cpu/common.c
+++ linux-2.6-x86/arch/x86/kernel/cpu/common.c
@@ -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] = { { { 0x0000ffff, 0x00cf9a00 } } },
+ [GDT_ENTRY_KERNEL_DS] = { { { 0x0000ffff, 0x00cf9200 } } },
+ [GDT_ENTRY_DEFAULT_USER_CS] = { { { 0x0000ffff, 0x00cffa00 } } },
+ [GDT_ENTRY_DEFAULT_USER_DS] = { { { 0x0000ffff, 0x00cff200 } } },
/*
* 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] = { { { 0x0000ffff, 0x00409a00 } } },
+ /* 16-bit code */
+ [GDT_ENTRY_PNPBIOS_CS16] = { { { 0x0000ffff, 0x00009a00 } } },
+ /* 16-bit data */
+ [GDT_ENTRY_PNPBIOS_DS] = { { { 0x0000ffff, 0x00009200 } } },
+ /* 16-bit data */
+ [GDT_ENTRY_PNPBIOS_TS1] = { { { 0x00000000, 0x00009200 } } },
+ /* 16-bit data */
+ [GDT_ENTRY_PNPBIOS_TS2] = { { { 0x00000000, 0x00009200 } } },
/*
* 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] = { { { 0x0000ffff, 0x00409a00 } } },
/* 16-bit code */
- [GDT_ENTRY_APMBIOS_BASE+1] = { 0x0000ffff, 0x00009a00 },
- [GDT_ENTRY_APMBIOS_BASE+2] = { 0x0000ffff, 0x00409200 }, /* data */
+ [GDT_ENTRY_APMBIOS_BASE+1] = { { { 0x0000ffff, 0x00009a00 } } },
+ /* data */
+ [GDT_ENTRY_APMBIOS_BASE+2] = { { { 0x0000ffff, 0x00409200 } } },

- [GDT_ENTRY_ESPFIX_SS] = { 0x00000000, 0x00c09200 },
- [GDT_ENTRY_PERCPU] = { 0x00000000, 0x00000000 },
+ [GDT_ENTRY_ESPFIX_SS] = { { { 0x00000000, 0x00c09200 } } },
+ [GDT_ENTRY_PERCPU] = { { { 0x00000000, 0x00000000 } } },
} };
EXPORT_PER_CPU_SYMBOL_GPL(gdt_page);

Index: linux-2.6-x86/arch/x86/kernel/process_64.c
===================================================================
--- linux-2.6-x86.orig/arch/x86/kernel/process_64.c
+++ linux-2.6-x86/arch/x86/kernel/process_64.c
@@ -444,7 +444,7 @@ static inline void set_32bit_tls(struct
.limit_in_pages = 1,
.useable = 1,
};
- struct n_desc_struct *desc = (void *)t->thread.tls_array;
+ struct desc_struct *desc = (void *)t->thread.tls_array;
desc += tls;
desc->a = LDT_entry_a(&ud);
desc->b = LDT_entry_b(&ud);
Index: linux-2.6-x86/arch/x86/kernel/traps_32.c
===================================================================
--- linux-2.6-x86.orig/arch/x86/kernel/traps_32.c
+++ linux-2.6-x86/arch/x86/kernel/traps_32.c
@@ -76,7 +76,8 @@ 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"))) = { { { { 0, 0 } } }, };

asmlinkage void divide_error(void);
asmlinkage void debug(void);
Index: linux-2.6-x86/include/asm-x86/desc_defs.h
===================================================================
--- linux-2.6-x86.orig/include/asm-x86/desc_defs.h
+++ linux-2.6-x86/include/asm-x86/desc_defs.h
@@ -11,17 +11,26 @@

#include <linux/types.h>

+/*
+ * FIXME: Acessing the desc_struct through its fields is more elegant,
+ * and should be the one valid thing to do. However, a lot of open code
+ * still touches the a and b acessors, and doing this allow us to do it
+ * incrementally. We keep the signature as a struct, rather than an union,
+ * so we can get rid of it transparently in the future -- glommer
+ */
// 8 byte segment descriptor
struct desc_struct {
- 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));
+ union {
+ struct { unsigned int a, b; };
+ struct {
+ 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;
+ };

-struct n_desc_struct {
- unsigned int a,b;
-};
+ };
+} __attribute__((packed));

enum {
GATE_INTERRUPT = 0xE,
Index: linux-2.6-x86/include/asm-x86/lguest.h
===================================================================
--- linux-2.6-x86.orig/include/asm-x86/lguest.h
+++ linux-2.6-x86/include/asm-x86/lguest.h
@@ -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 desc_struct){ { {0x0000ffff, 0x00cf9b00} } })
+#define FULL_SEGMENT ((struct desc_struct){ { {0x0000ffff, 0x00cf9300} } })

#endif /* __ASSEMBLY__ */

Index: linux-2.6-x86/include/asm-x86/processor_32.h
===================================================================
--- linux-2.6-x86.orig/include/asm-x86/processor_32.h
+++ linux-2.6-x86/include/asm-x86/processor_32.h
@@ -20,14 +20,11 @@
#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 int desc_empty(const void *ptr)
{
const u32 *desc = ptr;

2007-12-13 04:46:51

by Glauber Costa

[permalink] [raw]
Subject: [PATCH 03/19] change gdt acessor macro name

This patch changes the name of x86_64 macro used to access the per-cpu
gdt. It is now equal to the i386 version, which will allow code to be shared.

Signed-off-by: Glauber de Oliveira Costa <[email protected]>
---
arch/x86/kernel/setup64.c | 2 +-
arch/x86/kernel/suspend_64.c | 2 +-
arch/x86/kernel/vsyscall_64.c | 2 +-
include/asm-x86/desc_64.h | 10 +++++-----
4 files changed, 8 insertions(+), 8 deletions(-)

Index: linux-2.6-x86/arch/x86/kernel/setup64.c
===================================================================
--- linux-2.6-x86.orig/arch/x86/kernel/setup64.c
+++ linux-2.6-x86/arch/x86/kernel/setup64.c
@@ -228,7 +228,7 @@ void __cpuinit cpu_init (void)
* and set up the GDT descriptor:
*/
if (cpu)
- memcpy(cpu_gdt(cpu), cpu_gdt_table, GDT_SIZE);
+ memcpy(get_cpu_gdt_table(cpu), cpu_gdt_table, GDT_SIZE);

cpu_gdt_descr[cpu].size = GDT_SIZE;
load_gdt((const struct desc_ptr *)&cpu_gdt_descr[cpu]);
Index: linux-2.6-x86/arch/x86/kernel/suspend_64.c
===================================================================
--- linux-2.6-x86.orig/arch/x86/kernel/suspend_64.c
+++ linux-2.6-x86/arch/x86/kernel/suspend_64.c
@@ -118,7 +118,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;
+ get_cpu_gdt_table(cpu)[GDT_ENTRY_TSS].type = 9;

syscall_init(); /* This sets MSR_*STAR and related */
load_TR_desc(); /* This does ltr */
Index: linux-2.6-x86/arch/x86/kernel/vsyscall_64.c
===================================================================
--- linux-2.6-x86.orig/arch/x86/kernel/vsyscall_64.c
+++ linux-2.6-x86/arch/x86/kernel/vsyscall_64.c
@@ -297,7 +297,7 @@ static void __cpuinit vsyscall_set_cpu(i
/* Store cpu number in limit so that it can be loaded quickly
in user space in vgetcpu.
12 bits for the CPU and 8 bits for the node. */
- d = (unsigned long *)(cpu_gdt(cpu) + GDT_ENTRY_PER_CPU);
+ d = (unsigned long *)(get_cpu_gdt_table(cpu) + GDT_ENTRY_PER_CPU);
*d = 0x0f40000000000ULL;
*d |= cpu;
*d |= (node & 0xf) << 12;
Index: linux-2.6-x86/include/asm-x86/desc_64.h
===================================================================
--- linux-2.6-x86.orig/include/asm-x86/desc_64.h
+++ linux-2.6-x86/include/asm-x86/desc_64.h
@@ -48,7 +48,7 @@ static inline void write_ldt_entry(struc
}

/* the cpu gdt accessor */
-#define cpu_gdt(_cpu) ((struct desc_struct *)cpu_gdt_descr[_cpu].address)
+#define get_cpu_gdt_table(x) ((struct desc_struct *)cpu_gdt_descr[x].address)

static inline void load_gdt(const struct desc_ptr *ptr)
{
@@ -141,15 +141,15 @@ static inline void set_tss_desc(unsigned
* -1? seg base+limit should be pointing to the address of the
* last valid byte
*/
- set_tssldt_descriptor(&cpu_gdt(cpu)[GDT_ENTRY_TSS],
+ set_tssldt_descriptor(&get_cpu_gdt_table(cpu)[GDT_ENTRY_TSS],
(unsigned long)addr, DESC_TSS,
IO_BITMAP_OFFSET + IO_BITMAP_BYTES + sizeof(unsigned long) - 1);
}

static inline void set_ldt_desc(unsigned cpu, void *addr, int size)
{
- set_tssldt_descriptor(&cpu_gdt(cpu)[GDT_ENTRY_LDT], (unsigned long)addr,
- DESC_LDT, size * 8 - 1);
+ set_tssldt_descriptor(&get_cpu_gdt_table(cpu)[GDT_ENTRY_LDT],
+ (unsigned long)addr, DESC_LDT, size * 8 - 1);
}

#define LDT_entry_a(info) \
@@ -183,7 +183,7 @@ static inline void set_ldt_desc(unsigned
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);
+ u64 *gdt = (u64 *)(get_cpu_gdt_table(cpu) + GDT_ENTRY_TLS_MIN);

for (i = 0; i < GDT_ENTRY_TLS_ENTRIES; i++)
gdt[i] = t->tls_array[i];

2007-12-13 04:47:22

by Glauber Costa

[permalink] [raw]
Subject: [PATCH 02/19] unify struct desc_ptr

This patch unifies struct desc_ptr between i386 and x86_64.
They can be expressed in the exact same way in C code, only
having to change the name of one of them. As Xgt_desc_struct
is ugly and big, this is the one that goes away.

There's also a padding field in i386, but it is not really
needed in the C structure definition.

Signed-off-by: Glauber de Oliveira Costa <[email protected]>
---
arch/x86/kernel/asm-offsets_32.c | 5 ++---
arch/x86/kernel/cpu/common.c | 2 +-
arch/x86/kernel/doublefault_32.c | 2 +-
arch/x86/kernel/efi_32.c | 4 ++--
arch/x86/kernel/machine_kexec_32.c | 4 ++--
arch/x86/kernel/reboot_32.c | 2 +-
arch/x86/lguest/boot.c | 4 ++--
arch/x86/xen/enlighten.c | 10 +++++-----
drivers/kvm/svm.c | 2 +-
include/asm-x86/desc_32.h | 16 +++++-----------
include/asm-x86/lguest.h | 8 ++++----
include/asm-x86/paravirt.h | 18 +++++++++---------
include/asm-x86/processor_32.h | 2 +-
include/asm-x86/suspend_32.h | 4 ++--
14 files changed, 38 insertions(+), 45 deletions(-)

Index: linux-2.6-x86/arch/x86/kernel/asm-offsets_32.c
===================================================================
--- linux-2.6-x86.orig/arch/x86/kernel/asm-offsets_32.c
+++ linux-2.6-x86/arch/x86/kernel/asm-offsets_32.c
@@ -70,9 +70,8 @@ void foo(void)
OFFSET(TI_cpu, thread_info, cpu);
BLANK();

- OFFSET(GDS_size, Xgt_desc_struct, size);
- OFFSET(GDS_address, Xgt_desc_struct, address);
- OFFSET(GDS_pad, Xgt_desc_struct, pad);
+ OFFSET(GDS_size, desc_ptr, size);
+ OFFSET(GDS_address, desc_ptr, address);
BLANK();

OFFSET(PT_EBX, pt_regs, bx);
Index: linux-2.6-x86/arch/x86/kernel/cpu/common.c
===================================================================
--- linux-2.6-x86.orig/arch/x86/kernel/cpu/common.c
+++ linux-2.6-x86/arch/x86/kernel/cpu/common.c
@@ -649,7 +649,7 @@ struct pt_regs * __devinit idle_regs(str
* it's on the real one. */
void switch_to_new_gdt(void)
{
- struct Xgt_desc_struct gdt_descr;
+ struct desc_ptr gdt_descr;

gdt_descr.address = (long)get_cpu_gdt_table(smp_processor_id());
gdt_descr.size = GDT_SIZE - 1;
Index: linux-2.6-x86/arch/x86/kernel/doublefault_32.c
===================================================================
--- linux-2.6-x86.orig/arch/x86/kernel/doublefault_32.c
+++ linux-2.6-x86/arch/x86/kernel/doublefault_32.c
@@ -17,7 +17,7 @@ static unsigned long doublefault_stack[D

static void doublefault_fn(void)
{
- struct Xgt_desc_struct gdt_desc = {0, 0};
+ struct desc_ptr gdt_desc = {0, 0};
unsigned long gdt, tss;

store_gdt(&gdt_desc);
Index: linux-2.6-x86/arch/x86/kernel/efi_32.c
===================================================================
--- linux-2.6-x86.orig/arch/x86/kernel/efi_32.c
+++ linux-2.6-x86/arch/x86/kernel/efi_32.c
@@ -69,7 +69,7 @@ static void efi_call_phys_prelog(void) _
{
unsigned long cr4;
unsigned long temp;
- struct Xgt_desc_struct gdt_descr;
+ struct desc_ptr gdt_descr;

spin_lock(&efi_rt_lock);
local_irq_save(efi_rt_eflags);
@@ -111,7 +111,7 @@ static void efi_call_phys_prelog(void) _
static void efi_call_phys_epilog(void) __releases(efi_rt_lock)
{
unsigned long cr4;
- struct Xgt_desc_struct gdt_descr;
+ struct desc_ptr gdt_descr;

gdt_descr.address = (unsigned long)get_cpu_gdt_table(0);
gdt_descr.size = GDT_SIZE - 1;
Index: linux-2.6-x86/arch/x86/kernel/machine_kexec_32.c
===================================================================
--- linux-2.6-x86.orig/arch/x86/kernel/machine_kexec_32.c
+++ linux-2.6-x86/arch/x86/kernel/machine_kexec_32.c
@@ -32,7 +32,7 @@ static u32 kexec_pte1[1024] PAGE_ALIGNED

static void set_idt(void *newidt, __u16 limit)
{
- struct Xgt_desc_struct curidt;
+ struct desc_ptr curidt;

/* ia32 supports unaliged loads & stores */
curidt.size = limit;
@@ -44,7 +44,7 @@ static void set_idt(void *newidt, __u16

static void set_gdt(void *newgdt, __u16 limit)
{
- struct Xgt_desc_struct curgdt;
+ struct desc_ptr curgdt;

/* ia32 supports unaligned loads & stores */
curgdt.size = limit;
Index: linux-2.6-x86/arch/x86/kernel/reboot_32.c
===================================================================
--- linux-2.6-x86.orig/arch/x86/kernel/reboot_32.c
+++ linux-2.6-x86/arch/x86/kernel/reboot_32.c
@@ -161,7 +161,7 @@ real_mode_gdt_entries [3] =
0x000092000100ffffULL /* 16-bit real-mode 64k data at 0x00000100 */
};

-static struct Xgt_desc_struct
+static struct desc_ptr
real_mode_gdt = { sizeof (real_mode_gdt_entries) - 1, (long)real_mode_gdt_entries },
real_mode_idt = { 0x3ff, 0 },
no_idt = { 0, 0 };
Index: linux-2.6-x86/arch/x86/lguest/boot.c
===================================================================
--- linux-2.6-x86.orig/arch/x86/lguest/boot.c
+++ linux-2.6-x86/arch/x86/lguest/boot.c
@@ -229,7 +229,7 @@ static void lguest_write_idt_entry(struc
/* Changing to a different IDT is very rare: we keep the IDT up-to-date every
* time it is written, so we can simply loop through all entries and tell the
* Host about them. */
-static void lguest_load_idt(const struct Xgt_desc_struct *desc)
+static void lguest_load_idt(const struct desc_ptr *desc)
{
unsigned int i;
struct desc_struct *idt = (void *)desc->address;
@@ -252,7 +252,7 @@ static void lguest_load_idt(const struct
* hypercall and use that repeatedly to load a new IDT. I don't think it
* really matters, but wouldn't it be nice if they were the same?
*/
-static void lguest_load_gdt(const struct Xgt_desc_struct *desc)
+static void lguest_load_gdt(const struct desc_ptr *desc)
{
BUG_ON((desc->size+1)/8 != GDT_ENTRIES);
hcall(LHCALL_LOAD_GDT, __pa(desc->address), GDT_ENTRIES, 0);
Index: linux-2.6-x86/arch/x86/xen/enlighten.c
===================================================================
--- linux-2.6-x86.orig/arch/x86/xen/enlighten.c
+++ linux-2.6-x86/arch/x86/xen/enlighten.c
@@ -295,7 +295,7 @@ static void xen_set_ldt(const void *addr
xen_mc_issue(PARAVIRT_LAZY_CPU);
}

-static void xen_load_gdt(const struct Xgt_desc_struct *dtr)
+static void xen_load_gdt(const struct desc_ptr *dtr)
{
unsigned long *frames;
unsigned long va = dtr->address;
@@ -395,7 +395,7 @@ static int cvt_gate_to_trap(int vector,
}

/* Locations of each CPU's IDT */
-static DEFINE_PER_CPU(struct Xgt_desc_struct, idt_desc);
+static DEFINE_PER_CPU(struct desc_ptr, idt_desc);

/* Set an IDT entry. If the entry is part of the current IDT, then
also update Xen. */
@@ -427,7 +427,7 @@ static void xen_write_idt_entry(struct d
preempt_enable();
}

-static void xen_convert_trap_info(const struct Xgt_desc_struct *desc,
+static void xen_convert_trap_info(const struct desc_ptr *desc,
struct trap_info *traps)
{
unsigned in, out, count;
@@ -446,7 +446,7 @@ static void xen_convert_trap_info(const

void xen_copy_trap_info(struct trap_info *traps)
{
- const struct Xgt_desc_struct *desc = &__get_cpu_var(idt_desc);
+ const struct desc_ptr *desc = &__get_cpu_var(idt_desc);

xen_convert_trap_info(desc, traps);
}
@@ -454,7 +454,7 @@ void xen_copy_trap_info(struct trap_info
/* Load a new IDT into Xen. In principle this can be per-CPU, so we
hold a spinlock to protect the static traps[] array (static because
it avoids allocation, and saves stack space). */
-static void xen_load_idt(const struct Xgt_desc_struct *desc)
+static void xen_load_idt(const struct desc_ptr *desc)
{
static DEFINE_SPINLOCK(lock);
static struct trap_info traps[257];
Index: linux-2.6-x86/drivers/kvm/svm.c
===================================================================
--- linux-2.6-x86.orig/drivers/kvm/svm.c
+++ linux-2.6-x86/drivers/kvm/svm.c
@@ -290,7 +290,7 @@ static void svm_hardware_enable(void *ga
#ifdef CONFIG_X86_64
struct desc_ptr gdt_descr;
#else
- struct Xgt_desc_struct gdt_descr;
+ struct desc_ptr gdt_descr;
#endif
struct desc_struct *gdt;
int me = raw_smp_processor_id();
Index: linux-2.6-x86/include/asm-x86/desc_32.h
===================================================================
--- linux-2.6-x86.orig/include/asm-x86/desc_32.h
+++ linux-2.6-x86/include/asm-x86/desc_32.h
@@ -12,12 +12,6 @@

#include <asm/mmu.h>

-struct Xgt_desc_struct {
- unsigned short size;
- unsigned long address __attribute__((packed));
- unsigned short pad;
-} __attribute__ ((packed));
-
struct gdt_page
{
struct desc_struct gdt[GDT_ENTRIES];
@@ -29,7 +23,7 @@ static inline struct desc_struct *get_cp
return per_cpu(gdt_page, cpu).gdt;
}

-extern struct Xgt_desc_struct idt_descr;
+extern struct desc_ptr idt_descr;
extern struct desc_struct idt_table[];
extern void set_intr_gate(unsigned int irq, void * addr);

@@ -107,22 +101,22 @@ static inline void native_load_tr_desc(v
asm volatile("ltr %w0"::"q" (GDT_ENTRY_TSS*8));
}

-static inline void native_load_gdt(const struct Xgt_desc_struct *dtr)
+static inline void native_load_gdt(const struct desc_ptr *dtr)
{
asm volatile("lgdt %0"::"m" (*dtr));
}

-static inline void native_load_idt(const struct Xgt_desc_struct *dtr)
+static inline void native_load_idt(const struct desc_ptr *dtr)
{
asm volatile("lidt %0"::"m" (*dtr));
}

-static inline void native_store_gdt(struct Xgt_desc_struct *dtr)
+static inline void native_store_gdt(struct desc_ptr *dtr)
{
asm ("sgdt %0":"=m" (*dtr));
}

-static inline void native_store_idt(struct Xgt_desc_struct *dtr)
+static inline void native_store_idt(struct desc_ptr *dtr)
{
asm ("sidt %0":"=m" (*dtr));
}
Index: linux-2.6-x86/include/asm-x86/lguest.h
===================================================================
--- linux-2.6-x86.orig/include/asm-x86/lguest.h
+++ linux-2.6-x86/include/asm-x86/lguest.h
@@ -44,13 +44,13 @@ struct lguest_ro_state
{
/* Host information we need to restore when we switch back. */
u32 host_cr3;
- struct Xgt_desc_struct host_idt_desc;
- struct Xgt_desc_struct host_gdt_desc;
+ struct desc_ptr host_idt_desc;
+ struct desc_ptr host_gdt_desc;
u32 host_sp;

/* Fields which are used when guest is running. */
- struct Xgt_desc_struct guest_idt_desc;
- struct Xgt_desc_struct guest_gdt_desc;
+ struct desc_ptr guest_idt_desc;
+ struct desc_ptr guest_gdt_desc;
struct i386_hw_tss guest_tss;
struct desc_struct guest_idt[IDT_ENTRIES];
struct desc_struct guest_gdt[GDT_ENTRIES];
Index: linux-2.6-x86/include/asm-x86/paravirt.h
===================================================================
--- linux-2.6-x86.orig/include/asm-x86/paravirt.h
+++ linux-2.6-x86/include/asm-x86/paravirt.h
@@ -20,7 +20,7 @@

struct page;
struct thread_struct;
-struct Xgt_desc_struct;
+struct desc_ptr;
struct tss_struct;
struct mm_struct;
struct desc_struct;
@@ -88,10 +88,10 @@ struct pv_cpu_ops {

/* Segment descriptor handling */
void (*load_tr_desc)(void);
- void (*load_gdt)(const struct Xgt_desc_struct *);
- void (*load_idt)(const struct Xgt_desc_struct *);
- void (*store_gdt)(struct Xgt_desc_struct *);
- void (*store_idt)(struct Xgt_desc_struct *);
+ void (*load_gdt)(const struct desc_ptr *);
+ void (*load_idt)(const struct desc_ptr *);
+ void (*store_gdt)(struct desc_ptr *);
+ void (*store_idt)(struct desc_ptr *);
void (*set_ldt)(const void *desc, unsigned entries);
unsigned long (*store_tr)(void);
void (*load_tls)(struct thread_struct *t, unsigned int cpu);
@@ -630,11 +630,11 @@ static inline void load_TR_desc(void)
{
PVOP_VCALL0(pv_cpu_ops.load_tr_desc);
}
-static inline void load_gdt(const struct Xgt_desc_struct *dtr)
+static inline void load_gdt(const struct desc_ptr *dtr)
{
PVOP_VCALL1(pv_cpu_ops.load_gdt, dtr);
}
-static inline void load_idt(const struct Xgt_desc_struct *dtr)
+static inline void load_idt(const struct desc_ptr *dtr)
{
PVOP_VCALL1(pv_cpu_ops.load_idt, dtr);
}
@@ -642,11 +642,11 @@ static inline void set_ldt(const void *a
{
PVOP_VCALL2(pv_cpu_ops.set_ldt, addr, entries);
}
-static inline void store_gdt(struct Xgt_desc_struct *dtr)
+static inline void store_gdt(struct desc_ptr *dtr)
{
PVOP_VCALL1(pv_cpu_ops.store_gdt, dtr);
}
-static inline void store_idt(struct Xgt_desc_struct *dtr)
+static inline void store_idt(struct desc_ptr *dtr)
{
PVOP_VCALL1(pv_cpu_ops.store_idt, dtr);
}
Index: linux-2.6-x86/include/asm-x86/processor_32.h
===================================================================
--- linux-2.6-x86.orig/include/asm-x86/processor_32.h
+++ linux-2.6-x86/include/asm-x86/processor_32.h
@@ -707,7 +707,7 @@ extern void enable_sep_cpu(void);
extern int sysenter_setup(void);

/* Defined in head.S */
-extern struct Xgt_desc_struct early_gdt_descr;
+extern struct desc_ptr early_gdt_descr;

extern void cpu_set_gdt(int);
extern void switch_to_new_gdt(void);
Index: linux-2.6-x86/include/asm-x86/suspend_32.h
===================================================================
--- linux-2.6-x86.orig/include/asm-x86/suspend_32.h
+++ linux-2.6-x86/include/asm-x86/suspend_32.h
@@ -12,8 +12,8 @@ static inline int arch_prepare_suspend(v
struct saved_context {
u16 es, fs, gs, ss;
unsigned long cr0, cr2, cr3, cr4;
- struct Xgt_desc_struct gdt;
- struct Xgt_desc_struct idt;
+ struct desc_ptr gdt;
+ struct desc_ptr idt;
u16 ldt;
u16 tss;
unsigned long tr;

2007-12-13 04:47:44

by Glauber Costa

[permalink] [raw]
Subject: [PATCH 04/19] removed unused variable

This variable is not used anywere, and is then removed

Signed-off-by: Glauber de Oliveira Costa <[email protected]>
---
include/asm-x86/desc_64.h | 5 -----
1 files changed, 0 insertions(+), 5 deletions(-)

diff --git a/include/asm-x86/desc_64.h b/include/asm-x86/desc_64.h
index 1c26dbb..660cc84 100644
--- a/include/asm-x86/desc_64.h
+++ b/include/asm-x86/desc_64.h
@@ -30,11 +30,6 @@ static inline unsigned long __store_tr(void)

#define store_tr(tr) (tr) = __store_tr()

-/*
- * This is the ldt that every process will get unless we need
- * something other than this.
- */
-extern struct desc_struct default_ldt[];
extern struct gate_struct idt_table[];
extern struct desc_ptr cpu_gdt_descr[];

--
1.5.0.6

2007-12-13 04:48:01

by Glauber Costa

[permalink] [raw]
Subject: [PATCH 05/19] introduce gate_desc type.

To account for the differences in gate descriptor in i386 and x86_64
a gate_desc type is introduced.

Signed-off-by: Glauber de Oliveira Costa <[email protected]>
---
arch/x86/kernel/traps_32.c | 3 ++-
include/asm-x86/desc_32.h | 15 ++++++++-------
include/asm-x86/desc_64.h | 4 ++--
include/asm-x86/desc_defs.h | 8 +++++++-
4 files changed, 19 insertions(+), 11 deletions(-)

diff --git a/arch/x86/kernel/traps_32.c b/arch/x86/kernel/traps_32.c
index 94c5aea..6b03d88 100644
--- a/arch/x86/kernel/traps_32.c
+++ b/arch/x86/kernel/traps_32.c
@@ -76,8 +76,8 @@ 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 } } }, };
+gate_desc idt_table[256]
+ __attribute__((__section__(".data.idt"))) = { { { { 0, 0 } } }, };

asmlinkage void divide_error(void);
asmlinkage void debug(void);
diff --git a/include/asm-x86/desc_32.h b/include/asm-x86/desc_32.h
index bc5ca34..77f1e5a 100644
--- a/include/asm-x86/desc_32.h
+++ b/include/asm-x86/desc_32.h
@@ -3,6 +3,7 @@

#include <asm/ldt.h>
#include <asm/segment.h>
+#include <asm/desc_defs.h>

#ifndef __ASSEMBLY__

@@ -24,7 +25,7 @@ static inline struct desc_struct *get_cpu_gdt_table(unsigned int cpu)
}

extern struct desc_ptr idt_descr;
-extern struct desc_struct idt_table[];
+extern gate_desc idt_table[];
extern void set_intr_gate(unsigned int irq, void * addr);

static inline void pack_descriptor(__u32 *a, __u32 *b,
@@ -35,11 +36,11 @@ static inline void pack_descriptor(__u32 *a, __u32 *b,
(limit & 0x000f0000) | ((type & 0xff) << 8) | ((flags & 0xf) << 20);
}

-static inline void pack_gate(__u32 *a, __u32 *b,
+static inline void pack_gate(gate_desc *gate,
unsigned long base, unsigned short seg, unsigned char type, unsigned char flags)
{
- *a = (seg << 16) | (base & 0xffff);
- *b = (base & 0xffff0000) | ((type & 0xff) << 8) | (flags & 0xff);
+ gate->a = (seg << 16) | (base & 0xffff);
+ gate->b = (base & 0xffff0000) | ((type & 0xff) << 8) | (flags & 0xff);
}

#define DESCTYPE_LDT 0x82 /* present, system, DPL-0, LDT */
@@ -139,9 +140,9 @@ static inline void native_load_tls(struct thread_struct *t, unsigned int cpu)

static inline void _set_gate(int gate, unsigned int type, void *addr, unsigned short seg)
{
- __u32 a, b;
- pack_gate(&a, &b, (unsigned long)addr, seg, type, 0);
- write_idt_entry(idt_table, gate, a, b);
+ gate_desc g;
+ pack_gate(&g, (unsigned long)addr, seg, type, 0);
+ write_idt_entry(idt_table, gate, g.a, g.b);
}

static inline void __set_tss_desc(unsigned int cpu, unsigned int entry, const void *addr)
diff --git a/include/asm-x86/desc_64.h b/include/asm-x86/desc_64.h
index 660cc84..ffc6c06 100644
--- a/include/asm-x86/desc_64.h
+++ b/include/asm-x86/desc_64.h
@@ -30,7 +30,7 @@ static inline unsigned long __store_tr(void)

#define store_tr(tr) (tr) = __store_tr()

-extern struct gate_struct idt_table[];
+extern gate_desc idt_table[];
extern struct desc_ptr cpu_gdt_descr[];

static inline void write_ldt_entry(struct desc_struct *ldt,
@@ -58,7 +58,7 @@ static inline void store_gdt(struct desc_ptr *ptr)
static inline void _set_gate(void *adr, unsigned type, unsigned long func,
unsigned dpl, unsigned ist)
{
- struct gate_struct s;
+ gate_desc s;

s.offset_low = PTR_LOW(func);
s.segment = __KERNEL_CS;
diff --git a/include/asm-x86/desc_defs.h b/include/asm-x86/desc_defs.h
index f37b44c..05eff93 100644
--- a/include/asm-x86/desc_defs.h
+++ b/include/asm-x86/desc_defs.h
@@ -39,7 +39,7 @@ enum {
};

// 16byte gate
-struct gate_struct {
+struct gate_struct64 {
u16 offset_low;
u16 segment;
unsigned ist : 3, zero0 : 5, type : 5, dpl : 2, p : 1;
@@ -67,6 +67,12 @@ struct ldttss_desc {
u32 zero1;
} __attribute__((packed));

+#ifdef CONFIG_X86_64
+typedef struct gate_struct64 gate_desc;
+#else
+typedef struct desc_struct gate_desc;
+#endif
+
struct desc_ptr {
unsigned short size;
unsigned long address;
--
1.5.0.6

2007-12-13 04:48:26

by Glauber Costa

[permalink] [raw]
Subject: [PATCH 15/19] use the same data type for tls_array.

This patch changes the type of tls_array in x86_64 to
a desc_struct. Now, both i386 and x86_64 tls_array have
the same type, and code accessing it can be shared.

Signed-off-by: Glauber de Oliveira Costa <[email protected]>
---
include/asm-x86/desc_64.h | 2 +-
include/asm-x86/processor_64.h | 3 ++-
2 files changed, 3 insertions(+), 2 deletions(-)

diff --git a/include/asm-x86/desc_64.h b/include/asm-x86/desc_64.h
index 2dc19e2..7fd9876 100644
--- a/include/asm-x86/desc_64.h
+++ b/include/asm-x86/desc_64.h
@@ -150,7 +150,7 @@ static inline void set_ldt(void *addr, int entries)
static inline void load_TLS(struct thread_struct *t, unsigned int cpu)
{
unsigned int i;
- u64 *gdt = (u64 *)(get_cpu_gdt_table(cpu) + GDT_ENTRY_TLS_MIN);
+ struct desc_struct *gdt = (get_cpu_gdt_table(cpu) + GDT_ENTRY_TLS_MIN);

for (i = 0; i < GDT_ENTRY_TLS_ENTRIES; i++)
gdt[i] = t->tls_array[i];
diff --git a/include/asm-x86/processor_64.h b/include/asm-x86/processor_64.h
index 8efdf99..51f1970 100644
--- a/include/asm-x86/processor_64.h
+++ b/include/asm-x86/processor_64.h
@@ -19,6 +19,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
@@ -244,7 +245,7 @@ struct thread_struct {
* goes into MSR_IA32_DS_AREA */
unsigned long ds_area_msr;
/* 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 { \
--
1.5.0.6

2007-12-13 04:48:42

by Glauber Costa

[permalink] [raw]
Subject: [PATCH 08/19] modify write_ldt function

This patch modifies the write_ldt() function to make use
of the new struct desc_struct instead of entry_1 and entry_2
entries

Signed-off-by: Glauber de Oliveira Costa <[email protected]>
---
arch/x86/kernel/ldt.c | 15 +++++++--------
1 files changed, 7 insertions(+), 8 deletions(-)

diff --git a/arch/x86/kernel/ldt.c b/arch/x86/kernel/ldt.c
index a8cdca3..7eb0c8a 100644
--- a/arch/x86/kernel/ldt.c
+++ b/arch/x86/kernel/ldt.c
@@ -186,7 +186,7 @@ static int read_default_ldt(void __user *ptr, unsigned long bytecount)
static int write_ldt(void __user *ptr, unsigned long bytecount, int oldmode)
{
struct mm_struct *mm = current->mm;
- __u32 entry_1, entry_2;
+ struct desc_struct ldt;
int error;
struct user_desc ldt_info;

@@ -218,21 +218,20 @@ static int write_ldt(void __user *ptr, unsigned long bytecount, int oldmode)
/* Allow LDTs to be cleared by the user. */
if (ldt_info.base_addr == 0 && ldt_info.limit == 0) {
if (oldmode || LDT_empty(&ldt_info)) {
- entry_1 = 0;
- entry_2 = 0;
+ memset(&ldt, 0, sizeof(ldt));
goto install;
}
}

- entry_1 = LDT_entry_a(&ldt_info);
- entry_2 = LDT_entry_b(&ldt_info);
+ ldt.a = LDT_entry_a(&ldt_info);
+ ldt.b = LDT_entry_b(&ldt_info);
if (oldmode)
- entry_2 &= ~(1 << 20);
+ ldt.avl = 0;

/* Install the new entry ... */
install:
- write_ldt_entry(mm->context.ldt, ldt_info.entry_number, entry_1,
- entry_2);
+ write_ldt_entry(mm->context.ldt, ldt_info.entry_number,
+ ldt.a, ldt.b);
error = 0;

out_unlock:
--
1.5.0.6

2007-12-13 04:48:58

by Glauber Costa

[permalink] [raw]
Subject: [PATCH 18/19] move _set_gate and its users to a common location

This patch moves _set_gate and its users to desc.h. We can now
use common code for x86_64 and i386.

Signed-off-by: Glauber de Oliveira Costa <[email protected]>
---
arch/x86/kernel/traps_32.c | 34 ----------------
include/asm-x86/desc.h | 88 +++++++++++++++++++++++++++++++++++++++++++
include/asm-x86/desc_32.h | 16 --------
include/asm-x86/desc_64.h | 45 ----------------------
include/asm-x86/desc_defs.h | 5 +--
5 files changed, 89 insertions(+), 99 deletions(-)

Index: linux-2.6-x86/arch/x86/kernel/traps_32.c
===================================================================
--- linux-2.6-x86.orig/arch/x86/kernel/traps_32.c
+++ linux-2.6-x86/arch/x86/kernel/traps_32.c
@@ -1102,40 +1102,6 @@ asmlinkage void math_emulate(long arg)

#endif /* CONFIG_MATH_EMULATION */

-/*
- * This needs to use 'idt_table' rather than 'idt', and
- * thus use the _nonmapped_ version of the IDT, as the
- * Pentium F0 0F bugfix can have resulted in the mapped
- * IDT being write-protected.
- */
-void set_intr_gate(unsigned int n, void *addr)
-{
- _set_gate(n, DESCTYPE_INT, addr, __KERNEL_CS);
-}
-
-/*
- * This routine sets up an interrupt gate at directory privilege level 3.
- */
-static inline void set_system_intr_gate(unsigned int n, void *addr)
-{
- _set_gate(n, DESCTYPE_INT | DESCTYPE_DPL3, addr, __KERNEL_CS);
-}
-
-static void __init set_trap_gate(unsigned int n, void *addr)
-{
- _set_gate(n, DESCTYPE_TRAP, addr, __KERNEL_CS);
-}
-
-static void __init set_system_gate(unsigned int n, void *addr)
-{
- _set_gate(n, DESCTYPE_TRAP | DESCTYPE_DPL3, addr, __KERNEL_CS);
-}
-
-static void __init set_task_gate(unsigned int n, unsigned int gdt_entry)
-{
- _set_gate(n, DESCTYPE_TASK, (void *)0, (gdt_entry<<3));
-}
-

void __init trap_init(void)
{
Index: linux-2.6-x86/include/asm-x86/desc.h
===================================================================
--- linux-2.6-x86.orig/include/asm-x86/desc.h
+++ linux-2.6-x86/include/asm-x86/desc.h
@@ -33,6 +33,22 @@ extern struct desc_struct cpu_gdt_table[
extern struct desc_ptr cpu_gdt_descr[];
/* the cpu gdt accessor */
#define get_cpu_gdt_table(x) ((struct desc_struct *)cpu_gdt_descr[x].address)
+
+static inline void pack_gate(gate_desc *gate, unsigned type, unsigned long func,
+ unsigned dpl, unsigned ist, unsigned seg)
+{
+ gate->offset_low = PTR_LOW(func);
+ gate->segment = __KERNEL_CS;
+ gate->ist = ist;
+ gate->p = 1;
+ gate->dpl = dpl;
+ gate->zero0 = 0;
+ gate->zero1 = 0;
+ gate->type = type;
+ gate->offset_middle = PTR_MIDDLE(func);
+ gate->offset_high = PTR_HIGH(func);
+}
+
#else
struct gdt_page {
struct desc_struct gdt[GDT_ENTRIES];
@@ -43,6 +59,16 @@ static inline struct desc_struct *get_cp
{
return per_cpu(gdt_page, cpu).gdt;
}
+
+static inline void pack_gate(gate_desc *gate, unsigned char type,
+ unsigned long base, unsigned dpl, unsigned flags, unsigned short seg)
+
+{
+ gate->a = (seg << 16) | (base & 0xffff);
+ gate->b = (base & 0xffff0000) |
+ (((0x80 | type | (dpl << 5)) & 0xff) << 8);
+}
+
#endif

#ifdef CONFIG_PARAVIRT
@@ -242,6 +268,68 @@ static inline unsigned long get_desc_bas
{
return desc->base0 | ((desc->base1) << 16) | ((desc->base2) << 24);
}
+static inline void _set_gate(int gate, unsigned type, void *addr,
+ unsigned dpl, unsigned ist, unsigned seg)
+{
+ gate_desc s;
+ pack_gate(&s, type, (unsigned long)addr, dpl, ist, seg);
+ /*
+ * does not need to be atomic because it is only done once at
+ * setup time
+ */
+ write_idt_entry(idt_table, gate, &s);
+}
+
+/*
+ * This needs to use 'idt_table' rather than 'idt', and
+ * thus use the _nonmapped_ version of the IDT, as the
+ * Pentium F0 0F bugfix can have resulted in the mapped
+ * IDT being write-protected.
+ */
+static inline void set_intr_gate(unsigned int n, void *addr)
+{
+ BUG_ON((unsigned)n > 0xFF);
+ _set_gate(n, GATE_INTERRUPT, addr, 0, 0, __KERNEL_CS);
+}
+
+/*
+ * This routine sets up an interrupt gate at directory privilege level 3.
+ */
+static inline void set_system_intr_gate(unsigned int n, void *addr)
+{
+ BUG_ON((unsigned)n > 0xFF);
+ _set_gate(n, GATE_INTERRUPT, addr, 0x3, 0, __KERNEL_CS);
+}
+
+static inline void set_trap_gate(unsigned int n, void *addr)
+{
+ BUG_ON((unsigned)n > 0xFF);
+ _set_gate(n, GATE_TRAP, addr, 0, 0, __KERNEL_CS);
+}
+
+static inline void set_system_gate(unsigned int n, void *addr)
+{
+ BUG_ON((unsigned)n > 0xFF);
+ _set_gate(n, GATE_TRAP, addr, 0x3, 0, __KERNEL_CS);
+}
+
+static inline void set_task_gate(unsigned int n, unsigned int gdt_entry)
+{
+ BUG_ON((unsigned)n > 0xFF);
+ _set_gate(n, GATE_TASK, (void *)0, 0, 0, (gdt_entry<<3));
+}
+
+static inline void set_intr_gate_ist(int n, void *addr, unsigned ist)
+{
+ BUG_ON((unsigned)n > 0xFF);
+ _set_gate(n, GATE_INTERRUPT, addr, 0, ist, __KERNEL_CS);
+}
+
+static inline void set_system_gate_ist(int n, void *addr, unsigned ist)
+{
+ BUG_ON((unsigned)n > 0xFF);
+ _set_gate(n, GATE_INTERRUPT, addr, 0x3, ist, __KERNEL_CS);
+}

#else
/*
Index: linux-2.6-x86/include/asm-x86/desc_32.h
===================================================================
--- linux-2.6-x86.orig/include/asm-x86/desc_32.h
+++ linux-2.6-x86/include/asm-x86/desc_32.h
@@ -10,22 +10,6 @@
#include <linux/preempt.h>
#include <linux/percpu.h>

-extern void set_intr_gate(unsigned int irq, void * addr);
-
-static inline void pack_gate(gate_desc *gate,
- unsigned long base, unsigned short seg, unsigned char type, unsigned char flags)
-{
- gate->a = (seg << 16) | (base & 0xffff);
- gate->b = (base & 0xffff0000) | ((type & 0xff) << 8) | (flags & 0xff);
-}
-
-static inline void _set_gate(int gate, unsigned int type, void *addr, unsigned short seg)
-{
- gate_desc g;
- pack_gate(&g, (unsigned long)addr, seg, type, 0);
- write_idt_entry(idt_table, gate, &g);
-}
-
static inline void __set_tss_desc(unsigned int cpu, unsigned int entry, const void *addr)
{
tss_desc tss;
Index: linux-2.6-x86/include/asm-x86/desc_64.h
===================================================================
--- linux-2.6-x86.orig/include/asm-x86/desc_64.h
+++ linux-2.6-x86/include/asm-x86/desc_64.h
@@ -11,51 +11,6 @@

#include <asm/segment.h>

-static inline void _set_gate(int gate, unsigned type, unsigned long func,
- unsigned dpl, unsigned ist)
-{
- gate_desc s;
-
- s.offset_low = PTR_LOW(func);
- s.segment = __KERNEL_CS;
- s.ist = ist;
- s.p = 1;
- s.dpl = dpl;
- s.zero0 = 0;
- s.zero1 = 0;
- s.type = type;
- s.offset_middle = PTR_MIDDLE(func);
- s.offset_high = PTR_HIGH(func);
- /*
- * does not need to be atomic because it is only done once at
- * setup time
- */
- write_idt_entry(idt_table, gate, &s);
-}
-
-static inline void set_intr_gate(int nr, void *func)
-{
- BUG_ON((unsigned)nr > 0xFF);
- _set_gate(nr, GATE_INTERRUPT, (unsigned long) func, 0, 0);
-}
-
-static inline void set_intr_gate_ist(int nr, void *func, unsigned ist)
-{
- BUG_ON((unsigned)nr > 0xFF);
- _set_gate(nr, GATE_INTERRUPT, (unsigned long) func, 0, ist);
-}
-
-static inline void set_system_gate(int nr, void *func)
-{
- BUG_ON((unsigned)nr > 0xFF);
- _set_gate(nr, GATE_INTERRUPT, (unsigned long) func, 3, 0);
-}
-
-static inline void set_system_gate_ist(int nr, void *func, unsigned ist)
-{
- _set_gate(nr, GATE_INTERRUPT, (unsigned long) func, 3, ist);
-}
-
static inline void set_tss_desc(unsigned cpu, void *addr)
{
struct desc_struct *d = get_cpu_gdt_table(cpu);
Index: linux-2.6-x86/include/asm-x86/desc_defs.h
===================================================================
--- linux-2.6-x86.orig/include/asm-x86/desc_defs.h
+++ linux-2.6-x86/include/asm-x86/desc_defs.h
@@ -36,6 +36,7 @@ enum {
GATE_INTERRUPT = 0xE,
GATE_TRAP = 0xF,
GATE_CALL = 0xC,
+ GATE_TASK = 0x5,
};

// 16byte gate
@@ -55,10 +56,6 @@ struct gate_struct64 {
enum {
DESC_TSS = 0x9,
DESC_LDT = 0x2,
- DESCTYPE_TASK = 0x85, /* present, system, DPL-0, task gate */
- DESCTYPE_INT = 0x8e, /* present, system, DPL-0, interrupt gate */
- DESCTYPE_TRAP = 0x8f, /* present, system, DPL-0, trap gate */
- DESCTYPE_DPL3 = 0x60, /* DPL-3 */
DESCTYPE_S = 0x10, /* !system */
};

2007-12-13 04:49:33

by Glauber Costa

[permalink] [raw]
Subject: [PATCH 16/19] modify get_desc_base

This patch makes get_desc_base() receive a struct desc_struct,
and then uses its internal fields to compute the base address.
This is done at both i386 and x86_64, and then it is moved
to common header

Signed-off-by: Glauber de Oliveira Costa <[email protected]>
---
arch/x86/kernel/tls.c | 2 +-
arch/x86/mm/fault_32.c | 2 +-
include/asm-x86/desc.h | 8 ++------
3 files changed, 4 insertions(+), 8 deletions(-)

Index: linux-2.6-x86/arch/x86/kernel/tls.c
===================================================================
--- linux-2.6-x86.orig/arch/x86/kernel/tls.c
+++ linux-2.6-x86/arch/x86/kernel/tls.c
@@ -112,7 +112,7 @@ int do_get_thread_area(struct task_struc

memset(&info, 0, sizeof(struct user_desc));
info.entry_number = idx;
- info.base_addr = get_desc_base((void *)desc);
+ info.base_addr = get_desc_base((struct desc_struct *)desc);
info.limit = GET_LIMIT(desc);
info.seg_32bit = GET_32BIT(desc);
info.contents = GET_CONTENTS(desc);
Index: linux-2.6-x86/arch/x86/mm/fault_32.c
===================================================================
--- linux-2.6-x86.orig/arch/x86/mm/fault_32.c
+++ linux-2.6-x86/arch/x86/mm/fault_32.c
@@ -115,7 +115,7 @@ static inline unsigned long get_segment_
}

/* Decode the code segment base from the descriptor */
- base = get_desc_base((unsigned long *)desc);
+ base = get_desc_base((struct desc_struct *)desc);

if (seg & (1<<2)) {
mutex_unlock(&current->mm->context.lock);
Index: linux-2.6-x86/include/asm-x86/desc.h
===================================================================
--- linux-2.6-x86.orig/include/asm-x86/desc.h
+++ linux-2.6-x86/include/asm-x86/desc.h
@@ -69,6 +69,11 @@ static inline void load_LDT(mm_context_t
preempt_enable();
}

+static inline unsigned long get_desc_base(struct desc_struct *desc)
+{
+ return desc->base0 | ((desc->base1) << 16) | ((desc->base2) << 24);
+}
+
#else
/*
* GET_DESC_BASE reads the descriptor base of the specified segment.
Index: linux-2.6-x86/include/asm-x86/desc_32.h
===================================================================
--- linux-2.6-x86.orig/include/asm-x86/desc_32.h
+++ linux-2.6-x86/include/asm-x86/desc_32.h
@@ -168,14 +168,6 @@ static inline void __set_tss_desc(unsign

#define set_tss_desc(cpu,addr) __set_tss_desc(cpu, GDT_ENTRY_TSS, addr)

-static inline unsigned long get_desc_base(unsigned long *desc)
-{
- unsigned long base;
- base = ((desc[0] >> 16) & 0x0000ffff) |
- ((desc[1] << 16) & 0x00ff0000) |
- (desc[1] & 0xff000000);
- return base;
-}
#endif /* !__ASSEMBLY__ */

#endif
Index: linux-2.6-x86/include/asm-x86/desc_64.h
===================================================================
--- linux-2.6-x86.orig/include/asm-x86/desc_64.h
+++ linux-2.6-x86/include/asm-x86/desc_64.h
@@ -156,15 +156,6 @@ static inline void load_TLS(struct threa
gdt[i] = t->tls_array[i];
}

-static inline unsigned long get_desc_base(const void *ptr)
-{
- const u32 *desc = ptr;
- unsigned long base;
- base = ((desc[0] >> 16) & 0x0000ffff) |
- ((desc[1] << 16) & 0x00ff0000) |
- (desc[1] & 0xff000000);
- return base;
-}
#endif /* !__ASSEMBLY__ */

#endif

2007-12-13 04:49:50

by Glauber Costa

[permalink] [raw]
Subject: [PATCH 06/19] change write_idt_entry signature

this patch changes write_idt_entry signature. It now takes a gate_desc
instead of the a and b parameters. It will allow it to be later unified
between i386 and x86_64.

Signed-off-by: Glauber de Oliveira Costa <[email protected]>
CC: Zachary Amsden <[email protected]>
CC: Jeremy Fitzhardinge <Jeremy.Fitzhardinge.citrix.com>
---
arch/x86/kernel/paravirt_32.c | 2 +-
arch/x86/kernel/vmi_32.c | 10 +++++++++-
arch/x86/lguest/boot.c | 9 +++++----
arch/x86/xen/enlighten.c | 8 ++++----
include/asm-x86/desc_32.h | 10 ++++++++--
include/asm-x86/paravirt.h | 9 +++++----
6 files changed, 32 insertions(+), 16 deletions(-)

diff --git a/arch/x86/kernel/paravirt_32.c b/arch/x86/kernel/paravirt_32.c
index f4e3a8e..13bbc99 100644
--- a/arch/x86/kernel/paravirt_32.c
+++ b/arch/x86/kernel/paravirt_32.c
@@ -381,7 +381,7 @@ struct pv_cpu_ops pv_cpu_ops = {
.load_tls = native_load_tls,
.write_ldt_entry = write_dt_entry,
.write_gdt_entry = write_dt_entry,
- .write_idt_entry = write_dt_entry,
+ .write_idt_entry = native_write_idt_entry,
.load_sp0 = native_load_sp0,

.irq_enable_syscall_ret = native_irq_enable_syscall_ret,
diff --git a/arch/x86/kernel/vmi_32.c b/arch/x86/kernel/vmi_32.c
index 4cfda7d..a635b22 100644
--- a/arch/x86/kernel/vmi_32.c
+++ b/arch/x86/kernel/vmi_32.c
@@ -62,6 +62,7 @@ static struct {
void (*cpuid)(void /* non-c */);
void (*_set_ldt)(u32 selector);
void (*set_tr)(u32 selector);
+ void (*write_idt_entry)(struct desc_struct *, int, u32, u32);
void (*set_kernel_stack)(u32 selector, u32 sp0);
void (*allocate_page)(u32, u32, u32, u32, u32);
void (*release_page)(u32, u32);
@@ -214,6 +215,12 @@ static void vmi_set_tr(void)
vmi_ops.set_tr(GDT_ENTRY_TSS*sizeof(struct desc_struct));
}

+static void vmi_write_idt_entry(gate_desc *dt, int entry, const gate_desc *g)
+{
+ u32 *idt_entry = (u32 *)g;
+ vmi_ops.write_idt_entry(dt, entry, idt_entry[0], idt_entry[2]);
+}
+
static void vmi_load_sp0(struct tss_struct *tss,
struct thread_struct *thread)
{
@@ -792,7 +799,8 @@ static inline int __init activate_vmi(void)
pv_cpu_ops.load_tls = vmi_load_tls;
para_fill(pv_cpu_ops.write_ldt_entry, WriteLDTEntry);
para_fill(pv_cpu_ops.write_gdt_entry, WriteGDTEntry);
- para_fill(pv_cpu_ops.write_idt_entry, WriteIDTEntry);
+ para_wrap(pv_cpu_ops.write_idt_entry, vmi_write_idt_entry,
+ write_idt_entry, WriteIDTEntry);
para_wrap(pv_cpu_ops.load_sp0, vmi_load_sp0, set_kernel_stack, UpdateKernelStack);
para_fill(pv_cpu_ops.set_iopl_mask, SetIOPLMask);
para_fill(pv_cpu_ops.io_delay, IODelay);
diff --git a/arch/x86/lguest/boot.c b/arch/x86/lguest/boot.c
index aa0bdd5..b50c8ad 100644
--- a/arch/x86/lguest/boot.c
+++ b/arch/x86/lguest/boot.c
@@ -217,13 +217,14 @@ static void irq_enable(void)
* address of the handler, and... well, who cares? The Guest just asks the
* Host to make the change anyway, because the Host controls the real IDT.
*/
-static void lguest_write_idt_entry(struct desc_struct *dt,
- int entrynum, u32 low, u32 high)
+static void lguest_write_idt_entry(gate_desc *dt,
+ int entrynum, const gate_desc *g)
{
+ u32 *desc = (u32 *)g;
/* Keep the local copy up to date. */
- write_dt_entry(dt, entrynum, low, high);
+ native_write_idt_entry(dt, entrynum, g);
/* Tell Host about this new entry. */
- hcall(LHCALL_LOAD_IDT_ENTRY, entrynum, low, high);
+ hcall(LHCALL_LOAD_IDT_ENTRY, entrynum, desc[0], desc[1]);
}

/* Changing to a different IDT is very rare: we keep the IDT up-to-date every
diff --git a/arch/x86/xen/enlighten.c b/arch/x86/xen/enlighten.c
index 8215ea6..6dd349e 100644
--- a/arch/x86/xen/enlighten.c
+++ b/arch/x86/xen/enlighten.c
@@ -399,8 +399,7 @@ static DEFINE_PER_CPU(struct desc_ptr, idt_desc);

/* Set an IDT entry. If the entry is part of the current IDT, then
also update Xen. */
-static void xen_write_idt_entry(struct desc_struct *dt, int entrynum,
- u32 low, u32 high)
+static void xen_write_idt_entry(gate_desc *dt, int entrynum, const gate_desc *g)
{
unsigned long p = (unsigned long)&dt[entrynum];
unsigned long start, end;
@@ -412,14 +411,15 @@ static void xen_write_idt_entry(struct desc_struct *dt, int entrynum,

xen_mc_flush();

- write_dt_entry(dt, entrynum, low, high);
+ native_write_idt_entry(dt, entrynum, g);

if (p >= start && (p + 8) <= end) {
struct trap_info info[2];
+ u32 *desc = (u32 *)g;

info[1].address = 0;

- if (cvt_gate_to_trap(entrynum, low, high, &info[0]))
+ if (cvt_gate_to_trap(entrynum, desc[0], desc[1], &info[0]))
if (HYPERVISOR_set_trap_table(info))
BUG();
}
diff --git a/include/asm-x86/desc_32.h b/include/asm-x86/desc_32.h
index 77f1e5a..54b2314 100644
--- a/include/asm-x86/desc_32.h
+++ b/include/asm-x86/desc_32.h
@@ -70,9 +70,15 @@ static inline void pack_gate(gate_desc *gate,

#define write_ldt_entry(dt, entry, a, b) write_dt_entry(dt, entry, a, b)
#define write_gdt_entry(dt, entry, a, b) write_dt_entry(dt, entry, a, b)
-#define write_idt_entry(dt, entry, a, b) write_dt_entry(dt, entry, a, b)
+#define write_idt_entry(dt, entry, g) native_write_idt_entry(dt, entry, g)
#endif

+static inline void native_write_idt_entry(gate_desc *idt, int entry,
+ const gate_desc *gate)
+{
+ memcpy(&idt[entry], gate, sizeof(*gate));
+}
+
static inline void write_dt_entry(struct desc_struct *dt,
int entry, u32 entry_low, u32 entry_high)
{
@@ -142,7 +148,7 @@ static inline void _set_gate(int gate, unsigned int type, void *addr, unsigned s
{
gate_desc g;
pack_gate(&g, (unsigned long)addr, seg, type, 0);
- write_idt_entry(idt_table, gate, g.a, g.b);
+ write_idt_entry(idt_table, gate, &g);
}

static inline void __set_tss_desc(unsigned int cpu, unsigned int entry, const void *addr)
diff --git a/include/asm-x86/paravirt.h b/include/asm-x86/paravirt.h
index 0333fb6..86a9d7b 100644
--- a/include/asm-x86/paravirt.h
+++ b/include/asm-x86/paravirt.h
@@ -17,6 +17,7 @@
#include <linux/types.h>
#include <linux/cpumask.h>
#include <asm/kmap_types.h>
+#include <asm/desc_defs.h>

struct page;
struct thread_struct;
@@ -99,8 +100,8 @@ struct pv_cpu_ops {
int entrynum, u32 low, u32 high);
void (*write_gdt_entry)(struct desc_struct *,
int entrynum, u32 low, u32 high);
- void (*write_idt_entry)(struct desc_struct *,
- int entrynum, u32 low, u32 high);
+ void (*write_idt_entry)(gate_desc *,
+ int entrynum, const gate_desc *gate);
void (*load_sp0)(struct tss_struct *tss, struct thread_struct *t);

void (*set_iopl_mask)(unsigned mask);
@@ -667,9 +668,9 @@ static inline void write_gdt_entry(void *dt, int entry, u32 low, u32 high)
{
PVOP_VCALL4(pv_cpu_ops.write_gdt_entry, dt, entry, low, high);
}
-static inline void write_idt_entry(void *dt, int entry, u32 low, u32 high)
+static inline void write_idt_entry(gate_desc *dt, int entry, const gate_desc *g)
{
- PVOP_VCALL4(pv_cpu_ops.write_idt_entry, dt, entry, low, high);
+ PVOP_VCALL3(pv_cpu_ops.write_idt_entry, dt, entry, g);
}
static inline void set_iopl_mask(unsigned mask)
{
--
1.5.0.6

2007-12-13 04:50:19

by Glauber Costa

[permalink] [raw]
Subject: [PATCH 07/19] introduce ldt_desc type.

this patch introduces ldt_desc type to account for the differences
in the ldt descriptor in x86_64 and i386

Signed-off-by: Glauber de Oliveira Costa <[email protected]>
---
include/asm-x86/desc_64.h | 2 +-
include/asm-x86/desc_defs.h | 4 +++-
2 files changed, 4 insertions(+), 2 deletions(-)

diff --git a/include/asm-x86/desc_64.h b/include/asm-x86/desc_64.h
index ffc6c06..8fe1b4c 100644
--- a/include/asm-x86/desc_64.h
+++ b/include/asm-x86/desc_64.h
@@ -113,7 +113,7 @@ static inline void store_idt(struct desc_ptr *dtr)
static inline void set_tssldt_descriptor(void *ptr, unsigned long tss,
unsigned type, unsigned size)
{
- struct ldttss_desc d;
+ struct ldttss_desc64 d;

memset(&d, 0, sizeof(d));
d.limit0 = size & 0xFFFF;
diff --git a/include/asm-x86/desc_defs.h b/include/asm-x86/desc_defs.h
index 05eff93..5a58fc1 100644
--- a/include/asm-x86/desc_defs.h
+++ b/include/asm-x86/desc_defs.h
@@ -58,7 +58,7 @@ enum {
};

// LDT or TSS descriptor in the GDT. 16 bytes.
-struct ldttss_desc {
+struct ldttss_desc64 {
u16 limit0;
u16 base0;
unsigned base1 : 8, type : 5, dpl : 2, p : 1;
@@ -69,8 +69,10 @@ struct ldttss_desc {

#ifdef CONFIG_X86_64
typedef struct gate_struct64 gate_desc;
+typedef struct ldttss_desc64 ldt_desc;
#else
typedef struct desc_struct gate_desc;
+typedef struct desc_struct ldt_desc;
#endif

struct desc_ptr {
--
1.5.0.6

2007-12-13 04:50:42

by Glauber Costa

[permalink] [raw]
Subject: [PATCH 17/19] unify paravirt pieces of descriptor handling

With the types used to access descriptors in x86_64 and i386
now being the same, the code that effectively handles them can
now be easily shared. This patch moves the paravirt part of
desc_32.h into desc.h, and then, we get paravirt support in x86_64
for free.

Signed-off-by: Glauber de Oliveira Costa <[email protected]>
---
include/asm-x86/desc.h | 169 +++++++++++++++++++++++++++++++++++++++++++
include/asm-x86/desc_32.h | 130 ---------------------------------
include/asm-x86/desc_64.h | 104 +++------------------------
include/asm-x86/desc_defs.h | 6 +-
4 files changed, 183 insertions(+), 226 deletions(-)

Index: linux-2.6-x86/include/asm-x86/desc_32.h
===================================================================
--- linux-2.6-x86.orig/include/asm-x86/desc_32.h
+++ linux-2.6-x86/include/asm-x86/desc_32.h
@@ -8,31 +8,10 @@
#ifndef __ASSEMBLY__

#include <linux/preempt.h>
-#include <linux/smp.h>
#include <linux/percpu.h>

-struct gdt_page
-{
- struct desc_struct gdt[GDT_ENTRIES];
-} __attribute__((aligned(PAGE_SIZE)));
-DECLARE_PER_CPU(struct gdt_page, gdt_page);
-
-static inline struct desc_struct *get_cpu_gdt_table(unsigned int cpu)
-{
- return per_cpu(gdt_page, cpu).gdt;
-}
-
extern void set_intr_gate(unsigned int irq, void * addr);

-static inline void pack_descriptor(struct desc_struct *desc,
- unsigned long base, unsigned long limit, unsigned char type, unsigned char flags)
-{
- desc->a = ((base & 0xffff) << 16) | (limit & 0xffff);
- desc->b = (base & 0xff000000) | ((base & 0xff0000) >> 16) |
- (limit & 0x000f0000) | ((type & 0xff) << 8) | ((flags & 0xf) << 20);
- desc->p = 1;
-}
-
static inline void pack_gate(gate_desc *gate,
unsigned long base, unsigned short seg, unsigned char type, unsigned char flags)
{
@@ -40,115 +19,6 @@ static inline void pack_gate(gate_desc *
gate->b = (base & 0xffff0000) | ((type & 0xff) << 8) | (flags & 0xff);
}

-#ifdef CONFIG_PARAVIRT
-#include <asm/paravirt.h>
-#else
-#define load_TR_desc() native_load_tr_desc()
-#define load_gdt(dtr) native_load_gdt(dtr)
-#define load_idt(dtr) native_load_idt(dtr)
-#define load_tr(tr) __asm__ __volatile("ltr %0"::"m" (tr))
-#define load_ldt(ldt) __asm__ __volatile("lldt %0"::"m" (ldt))
-
-#define store_gdt(dtr) native_store_gdt(dtr)
-#define store_idt(dtr) native_store_idt(dtr)
-#define store_tr(tr) (tr = native_store_tr())
-#define store_ldt(ldt) __asm__ ("sldt %0":"=m" (ldt))
-
-#define load_TLS(t, cpu) native_load_tls(t, cpu)
-#define set_ldt native_set_ldt
-
-#define write_ldt_entry(dt, entry, desc) \
- native_write_ldt_entry(dt, entry, desc)
-#define write_gdt_entry(dt, entry, desc, type) \
- native_write_gdt_entry(dt, entry, desc, type)
-#define write_idt_entry(dt, entry, g) native_write_idt_entry(dt, entry, g)
-#endif
-
-static inline void native_write_ldt_entry(struct desc_struct *ldt, int entry,
- const void *desc)
-{
- memcpy(&ldt[entry], desc, sizeof(struct desc_struct));
-}
-
-static inline void native_write_idt_entry(gate_desc *idt, int entry,
- const gate_desc *gate)
-{
- memcpy(&idt[entry], gate, sizeof(*gate));
-}
-
-static inline void native_write_gdt_entry(struct desc_struct *gdt, int entry,
- const void *desc, int type)
-{
- memcpy(&gdt[entry], desc, sizeof(struct desc_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;
-}
-
-
-static inline void native_set_ldt(const void *addr, unsigned int entries)
-{
- if (likely(entries == 0))
- __asm__ __volatile__("lldt %w0"::"q" (0));
- else {
- unsigned cpu = smp_processor_id();
- ldt_desc ldt;
-
- pack_descriptor(&ldt, (unsigned long)addr,
- entries * sizeof(struct desc_struct) - 1,
- DESC_LDT, 0);
- write_gdt_entry(get_cpu_gdt_table(cpu), GDT_ENTRY_LDT,
- &ldt, DESC_LDT);
- __asm__ __volatile__("lldt %w0"::"q" (GDT_ENTRY_LDT*8));
- }
-}
-
-
-static inline void native_load_tr_desc(void)
-{
- asm volatile("ltr %w0"::"q" (GDT_ENTRY_TSS*8));
-}
-
-static inline void native_load_gdt(const struct desc_ptr *dtr)
-{
- asm volatile("lgdt %0"::"m" (*dtr));
-}
-
-static inline void native_load_idt(const struct desc_ptr *dtr)
-{
- asm volatile("lidt %0"::"m" (*dtr));
-}
-
-static inline void native_store_gdt(struct desc_ptr *dtr)
-{
- asm ("sgdt %0":"=m" (*dtr));
-}
-
-static inline void native_store_idt(struct desc_ptr *dtr)
-{
- asm ("sidt %0":"=m" (*dtr));
-}
-
-static inline unsigned long native_store_tr(void)
-{
- unsigned long tr;
- asm ("str %0":"=r" (tr));
- return tr;
-}
-
-static inline void native_load_tls(struct thread_struct *t, unsigned int cpu)
-{
- unsigned int i;
- struct desc_struct *gdt = get_cpu_gdt_table(cpu);
-
- for (i = 0; i < GDT_ENTRY_TLS_ENTRIES; i++)
- gdt[GDT_ENTRY_TLS_MIN + i] = t->tls_array[i];
-}
-
static inline void _set_gate(int gate, unsigned int type, void *addr, unsigned short seg)
{
gate_desc g;
Index: linux-2.6-x86/include/asm-x86/desc_64.h
===================================================================
--- linux-2.6-x86.orig/include/asm-x86/desc_64.h
+++ linux-2.6-x86/include/asm-x86/desc_64.h
@@ -8,47 +8,10 @@
#ifndef __ASSEMBLY__

#include <linux/string.h>
-#include <linux/smp.h>

#include <asm/segment.h>

-extern struct desc_struct cpu_gdt_table[GDT_ENTRIES];
-
-#define load_TR_desc() asm volatile("ltr %w0"::"r" (GDT_ENTRY_TSS*8))
-#define load_LDT_desc() asm volatile("lldt %w0"::"r" (GDT_ENTRY_LDT*8))
-
-static inline unsigned long __store_tr(void)
-{
- unsigned long tr;
-
- asm volatile ("str %w0":"=r" (tr));
- return tr;
-}
-
-#define store_tr(tr) (tr) = __store_tr()
-
-extern struct desc_ptr cpu_gdt_descr[];
-
-static inline void write_ldt_entry(struct desc_struct *ldt,
- int entry, void *ptr)
-{
- memcpy(&ldt[entry], ptr, 8);
-}
-
-/* the cpu gdt accessor */
-#define get_cpu_gdt_table(x) ((struct desc_struct *)cpu_gdt_descr[x].address)
-
-static inline void load_gdt(const struct desc_ptr *ptr)
-{
- asm volatile("lgdt %w0"::"m" (*ptr));
-}
-
-static inline void store_gdt(struct desc_ptr *ptr)
-{
- asm("sgdt %w0":"=m" (*ptr));
-}
-
-static inline void _set_gate(void *adr, unsigned type, unsigned long func,
+static inline void _set_gate(int gate, unsigned type, unsigned long func,
unsigned dpl, unsigned ist)
{
gate_desc s;
@@ -67,61 +30,37 @@ static inline void _set_gate(void *adr,
* does not need to be atomic because it is only done once at
* setup time
*/
- memcpy(adr, &s, 16);
+ write_idt_entry(idt_table, gate, &s);
}

static inline void set_intr_gate(int nr, void *func)
{
BUG_ON((unsigned)nr > 0xFF);
- _set_gate(&idt_table[nr], GATE_INTERRUPT, (unsigned long) func, 0, 0);
+ _set_gate(nr, GATE_INTERRUPT, (unsigned long) func, 0, 0);
}

static inline void set_intr_gate_ist(int nr, void *func, unsigned ist)
{
BUG_ON((unsigned)nr > 0xFF);
- _set_gate(&idt_table[nr], GATE_INTERRUPT, (unsigned long) func, 0, ist);
+ _set_gate(nr, GATE_INTERRUPT, (unsigned long) func, 0, ist);
}

static inline void set_system_gate(int nr, void *func)
{
BUG_ON((unsigned)nr > 0xFF);
- _set_gate(&idt_table[nr], GATE_INTERRUPT, (unsigned long) func, 3, 0);
+ _set_gate(nr, GATE_INTERRUPT, (unsigned long) func, 3, 0);
}

static inline void set_system_gate_ist(int nr, void *func, unsigned ist)
{
- _set_gate(&idt_table[nr], GATE_INTERRUPT, (unsigned long) func, 3, ist);
-}
-
-static inline void load_idt(const struct desc_ptr *ptr)
-{
- asm volatile("lidt %w0"::"m" (*ptr));
-}
-
-static inline void store_idt(struct desc_ptr *dtr)
-{
- asm("sidt %w0":"=m" (*dtr));
-}
-
-static inline void set_tssldt_descriptor(void *ptr, unsigned long tss,
- unsigned type, unsigned size)
-{
- struct ldttss_desc64 d;
-
- memset(&d, 0, sizeof(d));
- d.limit0 = size & 0xFFFF;
- d.base0 = PTR_LOW(tss);
- d.base1 = PTR_MIDDLE(tss) & 0xFF;
- d.type = type;
- d.p = 1;
- d.limit1 = (size >> 16) & 0xF;
- d.base2 = (PTR_MIDDLE(tss) >> 8) & 0xFF;
- d.base3 = PTR_HIGH(tss);
- memcpy(ptr, &d, 16);
+ _set_gate(nr, GATE_INTERRUPT, (unsigned long) func, 3, ist);
}

static inline void set_tss_desc(unsigned cpu, void *addr)
{
+ struct desc_struct *d = get_cpu_gdt_table(cpu);
+ tss_desc tss;
+
/*
* sizeof(unsigned long) coming from an extra "long" at the end
* of the iobitmap. See tss_struct definition in processor.h
@@ -129,31 +68,10 @@ static inline void set_tss_desc(unsigned
* -1? seg base+limit should be pointing to the address of the
* last valid byte
*/
- set_tssldt_descriptor(&get_cpu_gdt_table(cpu)[GDT_ENTRY_TSS],
+ set_tssldt_descriptor(&tss,
(unsigned long)addr, DESC_TSS,
IO_BITMAP_OFFSET + IO_BITMAP_BYTES + sizeof(unsigned long) - 1);
-}
-
-static inline void set_ldt(void *addr, int entries)
-{
- if (likely(entries == 0))
- __asm__ __volatile__("lldt %w0"::"q" (0));
- else {
- unsigned cpu = smp_processor_id();
-
- set_tssldt_descriptor(&get_cpu_gdt_table(cpu)[GDT_ENTRY_LDT],
- (unsigned long)addr, DESC_LDT, entries * 8 - 1);
- __asm__ __volatile__("lldt %w0"::"q" (GDT_ENTRY_LDT*8));
- }
-}
-
-static inline void load_TLS(struct thread_struct *t, unsigned int cpu)
-{
- unsigned int i;
- struct desc_struct *gdt = (get_cpu_gdt_table(cpu) + GDT_ENTRY_TLS_MIN);
-
- for (i = 0; i < GDT_ENTRY_TLS_ENTRIES; i++)
- gdt[i] = t->tls_array[i];
+ write_gdt_entry(d, GDT_ENTRY_TSS, &tss, DESC_TSS);
}

#endif /* !__ASSEMBLY__ */
Index: linux-2.6-x86/include/asm-x86/desc_defs.h
===================================================================
--- linux-2.6-x86.orig/include/asm-x86/desc_defs.h
+++ linux-2.6-x86/include/asm-x86/desc_defs.h
@@ -48,9 +48,9 @@ struct gate_struct64 {
u32 zero1;
} __attribute__((packed));

-#define PTR_LOW(x) ((unsigned long)(x) & 0xFFFF)
-#define PTR_MIDDLE(x) (((unsigned long)(x) >> 16) & 0xFFFF)
-#define PTR_HIGH(x) ((unsigned long)(x) >> 32)
+#define PTR_LOW(x) ((unsigned long long)(x) & 0xFFFF)
+#define PTR_MIDDLE(x) (((unsigned long long)(x) >> 16) & 0xFFFF)
+#define PTR_HIGH(x) ((unsigned long long)(x) >> 32)

enum {
DESC_TSS = 0x9,
Index: linux-2.6-x86/include/asm-x86/desc.h
===================================================================
--- linux-2.6-x86.orig/include/asm-x86/desc.h
+++ linux-2.6-x86/include/asm-x86/desc.h
@@ -5,6 +5,7 @@
#include <asm/desc_defs.h>
#include <asm/ldt.h>
#include <asm/mmu.h>
+#include <linux/smp.h>

static inline void fill_ldt(struct desc_struct *desc, struct user_desc *info)
{
@@ -27,6 +28,174 @@ static inline void fill_ldt(struct desc_
extern struct desc_ptr idt_descr;
extern gate_desc idt_table[];

+#ifdef CONFIG_X86_64
+extern struct desc_struct cpu_gdt_table[GDT_ENTRIES];
+extern struct desc_ptr cpu_gdt_descr[];
+/* the cpu gdt accessor */
+#define get_cpu_gdt_table(x) ((struct desc_struct *)cpu_gdt_descr[x].address)
+#else
+struct gdt_page {
+ struct desc_struct gdt[GDT_ENTRIES];
+} __attribute__((aligned(PAGE_SIZE)));
+DECLARE_PER_CPU(struct gdt_page, gdt_page);
+
+static inline struct desc_struct *get_cpu_gdt_table(unsigned int cpu)
+{
+ return per_cpu(gdt_page, cpu).gdt;
+}
+#endif
+
+#ifdef CONFIG_PARAVIRT
+#include <asm/paravirt.h>
+#else
+#define load_TR_desc() native_load_tr_desc()
+#define load_gdt(dtr) native_load_gdt(dtr)
+#define load_idt(dtr) native_load_idt(dtr)
+#define load_tr(tr) __asm__ __volatile("ltr %0"::"m" (tr))
+#define load_ldt(ldt) __asm__ __volatile("lldt %0"::"m" (ldt))
+
+#define store_gdt(dtr) native_store_gdt(dtr)
+#define store_idt(dtr) native_store_idt(dtr)
+#define store_tr(tr) (tr = native_store_tr())
+#define store_ldt(ldt) __asm__ ("sldt %0":"=m" (ldt))
+
+#define load_TLS(t, cpu) native_load_tls(t, cpu)
+#define set_ldt native_set_ldt
+
+#define write_ldt_entry(dt, entry, desc) \
+ native_write_ldt_entry(dt, entry, desc)
+#define write_gdt_entry(dt, entry, desc, type) \
+ native_write_gdt_entry(dt, entry, desc, type)
+#define write_idt_entry(dt, entry, g) native_write_idt_entry(dt, entry, g)
+#endif
+
+static inline void native_write_idt_entry(gate_desc *idt, int entry,
+ const gate_desc *gate)
+{
+ memcpy(&idt[entry], gate, sizeof(*gate));
+}
+
+static inline void native_write_ldt_entry(struct desc_struct *ldt, int entry,
+ const void *desc)
+{
+ memcpy(&ldt[entry], desc, 8);
+}
+
+static inline void native_write_gdt_entry(struct desc_struct *gdt, int entry,
+ const void *desc, int type)
+{
+ unsigned int size;
+ switch (type) {
+ case DESC_TSS:
+ size = sizeof(tss_desc);
+ break;
+ case DESC_LDT:
+ size = sizeof(ldt_desc);
+ break;
+ default:
+ size = sizeof(struct desc_struct);
+ break;
+ }
+ memcpy(&gdt[entry], desc, size);
+}
+
+static inline void set_tssldt_descriptor(struct ldttss_desc64 *d,
+ unsigned long tss, unsigned type,
+ unsigned size)
+{
+ memset(d, 0, sizeof(*d));
+ d->limit0 = size & 0xFFFF;
+ d->base0 = PTR_LOW(tss);
+ d->base1 = PTR_MIDDLE(tss) & 0xFF;
+ d->type = type;
+ d->p = 1;
+ d->limit1 = (size >> 16) & 0xF;
+ d->base2 = (PTR_MIDDLE(tss) >> 8) & 0xFF;
+ d->base3 = PTR_HIGH(tss);
+}
+
+static inline void pack_descriptor(struct desc_struct *desc, unsigned long base,
+ unsigned long limit, unsigned char type,
+ unsigned char flags)
+{
+ desc->a = ((base & 0xffff) << 16) | (limit & 0xffff);
+ desc->b = (base & 0xff000000) | ((base & 0xff0000) >> 16) |
+ (limit & 0x000f0000) | ((type & 0xff) << 8) |
+ ((flags & 0xf) << 20);
+ desc->p = 1;
+}
+
+static inline void pack_ldt(ldt_desc *ldt, unsigned long addr,
+ unsigned size)
+{
+
+#ifdef CONFIG_X86_64
+ set_tssldt_descriptor(ldt,
+ addr, DESC_LDT, size);
+#else
+ pack_descriptor(ldt, (unsigned long)addr,
+ size,
+ 0x80 | DESC_LDT, 0);
+#endif
+}
+
+static inline void native_set_ldt(const void *addr, unsigned int entries)
+{
+ if (likely(entries == 0))
+ __asm__ __volatile__("lldt %w0"::"q" (0));
+ else {
+ unsigned cpu = smp_processor_id();
+ ldt_desc ldt;
+
+ pack_ldt(&ldt, (unsigned long)addr,
+ entries * sizeof(ldt) - 1);
+ write_gdt_entry(get_cpu_gdt_table(cpu), GDT_ENTRY_LDT,
+ &ldt, DESC_LDT);
+ __asm__ __volatile__("lldt %w0"::"q" (GDT_ENTRY_LDT*8));
+ }
+}
+
+static inline void native_load_tr_desc(void)
+{
+ asm volatile("ltr %w0"::"q" (GDT_ENTRY_TSS*8));
+}
+
+static inline void native_load_gdt(const struct desc_ptr *dtr)
+{
+ asm volatile("lgdt %0"::"m" (*dtr));
+}
+
+static inline void native_load_idt(const struct desc_ptr *dtr)
+{
+ asm volatile("lidt %0"::"m" (*dtr));
+}
+
+static inline void native_store_gdt(struct desc_ptr *dtr)
+{
+ asm volatile("sgdt %0":"=m" (*dtr));
+}
+
+static inline void native_store_idt(struct desc_ptr *dtr)
+{
+ asm volatile("sidt %0":"=m" (*dtr));
+}
+
+static inline unsigned long native_store_tr(void)
+{
+ unsigned long tr;
+ asm volatile("str %0":"=r" (tr));
+ return tr;
+}
+
+static inline void native_load_tls(struct thread_struct *t, unsigned int cpu)
+{
+ unsigned int i;
+ struct desc_struct *gdt = get_cpu_gdt_table(cpu);
+
+ for (i = 0; i < GDT_ENTRY_TLS_ENTRIES; i++)
+ gdt[GDT_ENTRY_TLS_MIN + i] = t->tls_array[i];
+}
+
#ifdef CONFIG_X86_32
# include "desc_32.h"
#else

2007-12-13 04:50:59

by Glauber Costa

[permalink] [raw]
Subject: [PATCH 10/19] provide tss_desc

Provide a new type, tss_desc, to represent the tss descriptor
in a unified way accross x86_64 and i386

Signed-off-by: Glauber de Oliveira Costa <[email protected]>
---
include/asm-x86/desc_defs.h | 2 ++
1 files changed, 2 insertions(+), 0 deletions(-)

diff --git a/include/asm-x86/desc_defs.h b/include/asm-x86/desc_defs.h
index 5a58fc1..c4d7874 100644
--- a/include/asm-x86/desc_defs.h
+++ b/include/asm-x86/desc_defs.h
@@ -70,9 +70,11 @@ struct ldttss_desc64 {
#ifdef CONFIG_X86_64
typedef struct gate_struct64 gate_desc;
typedef struct ldttss_desc64 ldt_desc;
+typedef struct ldttss_desc64 tss_desc;
#else
typedef struct desc_struct gate_desc;
typedef struct desc_struct ldt_desc;
+typedef struct desc_struct tss_desc;
#endif

struct desc_ptr {
--
1.5.0.6

2007-12-13 04:51:22

by Glauber Costa

[permalink] [raw]
Subject: [PATCH 12/19] change write_ldt_entry signature

this patch changes the signature of write_ldt_entry.

Signed-off-by: Glauber de Oliveira Costa <[email protected]>
CC: Zachary Amsden <[email protected]>
CC: Jeremy Fitzhardinge <Jeremy.Fitzhardinge.citrix.com>
---
arch/x86/kernel/ldt.c | 3 +--
arch/x86/kernel/paravirt_32.c | 2 +-
arch/x86/kernel/vmi_32.c | 11 ++++++++++-
arch/x86/xen/enlighten.c | 4 ++--
include/asm-x86/desc_32.h | 9 ++++++++-
include/asm-x86/desc_64.h | 7 ++-----
include/asm-x86/paravirt.h | 10 ++++++----
7 files changed, 30 insertions(+), 16 deletions(-)

diff --git a/arch/x86/kernel/ldt.c b/arch/x86/kernel/ldt.c
index 3e872b4..b8ef462 100644
--- a/arch/x86/kernel/ldt.c
+++ b/arch/x86/kernel/ldt.c
@@ -229,8 +229,7 @@ static int write_ldt(void __user *ptr, unsigned long bytecount, int oldmode)

/* Install the new entry ... */
install:
- write_ldt_entry(mm->context.ldt, ldt_info.entry_number,
- ldt.a, ldt.b);
+ write_ldt_entry(mm->context.ldt, ldt_info.entry_number, &ldt);
error = 0;

out_unlock:
diff --git a/arch/x86/kernel/paravirt_32.c b/arch/x86/kernel/paravirt_32.c
index 77602c1..dd063fb 100644
--- a/arch/x86/kernel/paravirt_32.c
+++ b/arch/x86/kernel/paravirt_32.c
@@ -379,7 +379,7 @@ struct pv_cpu_ops pv_cpu_ops = {
.store_idt = native_store_idt,
.store_tr = native_store_tr,
.load_tls = native_load_tls,
- .write_ldt_entry = write_dt_entry,
+ .write_ldt_entry = native_write_ldt_entry,
.write_gdt_entry = native_write_gdt_entry,
.write_idt_entry = native_write_idt_entry,
.load_sp0 = native_load_sp0,
diff --git a/arch/x86/kernel/vmi_32.c b/arch/x86/kernel/vmi_32.c
index 21edd0d..10c4641 100644
--- a/arch/x86/kernel/vmi_32.c
+++ b/arch/x86/kernel/vmi_32.c
@@ -64,6 +64,7 @@ static struct {
void (*set_tr)(u32 selector);
void (*write_idt_entry)(struct desc_struct *, int, u32, u32);
void (*write_gdt_entry)(struct desc_struct *, int, u32, u32);
+ void (*write_ldt_entry)(struct desc_struct *, int, u32, u32);
void (*set_kernel_stack)(u32 selector, u32 sp0);
void (*allocate_page)(u32, u32, u32, u32, u32);
void (*release_page)(u32, u32);
@@ -229,6 +230,13 @@ static void vmi_write_gdt_entry(struct desc_struct *dt, int entry,
vmi_ops.write_gdt_entry(dt, entry, gdt_entry[0], gdt_entry[2]);
}

+static void vmi_write_ldt_entry(struct desc_struct *dt, int entry,
+ const void *desc)
+{
+ u32 *ldt_entry = (u32 *)desc;
+ vmi_ops.write_idt_entry(dt, entry, ldt_entry[0], ldt_entry[2]);
+}
+
static void vmi_load_sp0(struct tss_struct *tss,
struct thread_struct *thread)
{
@@ -805,7 +813,8 @@ static inline int __init activate_vmi(void)
para_fill(pv_cpu_ops.store_idt, GetIDT);
para_fill(pv_cpu_ops.store_tr, GetTR);
pv_cpu_ops.load_tls = vmi_load_tls;
- para_fill(pv_cpu_ops.write_ldt_entry, WriteLDTEntry);
+ para_wrap(pv_cpu_ops.write_ldt_entry, vmi_write_ldt_entry,
+ write_ldt_entry, WriteLDTEntry);
para_wrap(pv_cpu_ops.write_gdt_entry, vmi_write_gdt_entry,
write_gdt_entry, WriteGDTEntry);
para_wrap(pv_cpu_ops.write_idt_entry, vmi_write_idt_entry,
diff --git a/arch/x86/xen/enlighten.c b/arch/x86/xen/enlighten.c
index c38240c..c904686 100644
--- a/arch/x86/xen/enlighten.c
+++ b/arch/x86/xen/enlighten.c
@@ -357,11 +357,11 @@ static void xen_load_tls(struct thread_struct *t, unsigned int cpu)
}

static void xen_write_ldt_entry(struct desc_struct *dt, int entrynum,
- u32 low, u32 high)
+ const void *ptr)
{
unsigned long lp = (unsigned long)&dt[entrynum];
xmaddr_t mach_lp = virt_to_machine(lp);
- u64 entry = (u64)high << 32 | low;
+ u64 entry = *(u64 *)ptr;

preempt_disable();

diff --git a/include/asm-x86/desc_32.h b/include/asm-x86/desc_32.h
index 41d8214..92a72b0 100644
--- a/include/asm-x86/desc_32.h
+++ b/include/asm-x86/desc_32.h
@@ -69,12 +69,19 @@ static inline void pack_gate(gate_desc *gate,
#define load_TLS(t, cpu) native_load_tls(t, cpu)
#define set_ldt native_set_ldt

-#define write_ldt_entry(dt, entry, a, b) write_dt_entry(dt, entry, a, b)
+#define write_ldt_entry(dt, entry, desc) \
+ native_write_ldt_entry(dt, entry, desc)
#define write_gdt_entry(dt, entry, desc, type) \
native_write_gdt_entry(dt, entry, desc, type)
#define write_idt_entry(dt, entry, g) native_write_idt_entry(dt, entry, g)
#endif

+static inline void native_write_ldt_entry(struct desc_struct *ldt, int entry,
+ const void *desc)
+{
+ memcpy(&ldt[entry], desc, sizeof(struct desc_struct));
+}
+
static inline void native_write_idt_entry(gate_desc *idt, int entry,
const gate_desc *gate)
{
diff --git a/include/asm-x86/desc_64.h b/include/asm-x86/desc_64.h
index e0aa4bc..3cd5f10 100644
--- a/include/asm-x86/desc_64.h
+++ b/include/asm-x86/desc_64.h
@@ -34,12 +34,9 @@ extern gate_desc idt_table[];
extern struct desc_ptr cpu_gdt_descr[];

static inline void write_ldt_entry(struct desc_struct *ldt,
- int entry, u32 entry_low, u32 entry_high)
+ int entry, void *ptr)
{
- __u32 *lp = (__u32 *)((entry << 3) + (char *)ldt);
-
- lp[0] = entry_low;
- lp[1] = entry_high;
+ memcpy(&ldt[entry], ptr, 8);
}

/* the cpu gdt accessor */
diff --git a/include/asm-x86/paravirt.h b/include/asm-x86/paravirt.h
index 3f2abf2..4f23f43 100644
--- a/include/asm-x86/paravirt.h
+++ b/include/asm-x86/paravirt.h
@@ -96,8 +96,8 @@ struct pv_cpu_ops {
void (*set_ldt)(const void *desc, unsigned entries);
unsigned long (*store_tr)(void);
void (*load_tls)(struct thread_struct *t, unsigned int cpu);
- void (*write_ldt_entry)(struct desc_struct *,
- int entrynum, u32 low, u32 high);
+ void (*write_ldt_entry)(struct desc_struct *ldt, int entrynum,
+ const void *desc);
void (*write_gdt_entry)(struct desc_struct *,
int entrynum, const void *desc, int size);
void (*write_idt_entry)(gate_desc *,
@@ -660,9 +660,11 @@ static inline void load_TLS(struct thread_struct *t, unsigned cpu)
{
PVOP_VCALL2(pv_cpu_ops.load_tls, t, cpu);
}
-static inline void write_ldt_entry(void *dt, int entry, u32 low, u32 high)
+
+static inline void write_ldt_entry(struct desc_struct *dt, int entry,
+ const void *desc)
{
- PVOP_VCALL4(pv_cpu_ops.write_ldt_entry, dt, entry, low, high);
+ PVOP_VCALL3(pv_cpu_ops.write_ldt_entry, dt, entry, desc);
}

static inline void write_gdt_entry(struct desc_struct *dt, int entry,
--
1.5.0.6

2007-12-13 04:51:39

by Glauber Costa

[permalink] [raw]
Subject: [PATCH 09/19] introduce fill_ldt

This patch introduces fill_ldt(), which populates a ldt descriptor
from a user_desc in once, instead of relying in the LDT_entry_a and
LDT_entry_b macros

Signed-off-by: Glauber de Oliveira Costa <[email protected]>
---
arch/x86/kernel/ldt.c | 3 +--
arch/x86/kernel/process_64.c | 3 +--
arch/x86/kernel/tls.c | 7 +++----
include/asm-x86/desc_32.h | 15 ---------------
include/asm-x86/desc_64.h | 17 -----------------
include/asm-x86/ldt.h | 19 +++++++++++++++++++
6 files changed, 24 insertions(+), 40 deletions(-)

Index: linux-2.6-x86/arch/x86/kernel/ldt.c
===================================================================
--- linux-2.6-x86.orig/arch/x86/kernel/ldt.c
+++ linux-2.6-x86/arch/x86/kernel/ldt.c
@@ -223,8 +223,7 @@ static int write_ldt(void __user *ptr, u
}
}

- ldt.a = LDT_entry_a(&ldt_info);
- ldt.b = LDT_entry_b(&ldt_info);
+ fill_ldt(&ldt, &ldt_info);
if (oldmode)
ldt.avl = 0;

Index: linux-2.6-x86/arch/x86/kernel/process_64.c
===================================================================
--- linux-2.6-x86.orig/arch/x86/kernel/process_64.c
+++ linux-2.6-x86/arch/x86/kernel/process_64.c
@@ -446,8 +446,7 @@ static inline void set_32bit_tls(struct
};
struct desc_struct *desc = (void *)t->thread.tls_array;
desc += tls;
- desc->a = LDT_entry_a(&ud);
- desc->b = LDT_entry_b(&ud);
+ fill_ldt(desc, &ud);
}

static inline u32 read_32bit_tls(struct task_struct *t, int tls)
Index: linux-2.6-x86/arch/x86/kernel/tls.c
===================================================================
--- linux-2.6-x86.orig/arch/x86/kernel/tls.c
+++ linux-2.6-x86/arch/x86/kernel/tls.c
@@ -67,10 +67,9 @@ int do_set_thread_area(struct task_struc
if (LDT_empty(&info)) {
desc[0] = 0;
desc[1] = 0;
- } else {
- desc[0] = LDT_entry_a(&info);
- desc[1] = LDT_entry_b(&info);
- }
+ } else
+ fill_ldt((struct desc_struct *)desc, &info);
+
if (t == &current->thread)
load_TLS(t, cpu);

Index: linux-2.6-x86/include/asm-x86/desc_32.h
===================================================================
--- linux-2.6-x86.orig/include/asm-x86/desc_32.h
+++ linux-2.6-x86/include/asm-x86/desc_32.h
@@ -163,21 +163,6 @@ static inline void __set_tss_desc(unsign

#define set_tss_desc(cpu,addr) __set_tss_desc(cpu, GDT_ENTRY_TSS, addr)

-#define LDT_entry_a(info) \
- ((((info)->base_addr & 0x0000ffff) << 16) | ((info)->limit & 0x0ffff))
-
-#define LDT_entry_b(info) \
- (((info)->base_addr & 0xff000000) | \
- (((info)->base_addr & 0x00ff0000) >> 16) | \
- ((info)->limit & 0xf0000) | \
- (((info)->read_exec_only ^ 1) << 9) | \
- ((info)->contents << 10) | \
- (((info)->seg_not_present ^ 1) << 15) | \
- ((info)->seg_32bit << 22) | \
- ((info)->limit_in_pages << 23) | \
- ((info)->useable << 20) | \
- 0x7000)
-
#define LDT_empty(info) (\
(info)->base_addr == 0 && \
(info)->limit == 0 && \
Index: linux-2.6-x86/include/asm-x86/desc_64.h
===================================================================
--- linux-2.6-x86.orig/include/asm-x86/desc_64.h
+++ linux-2.6-x86/include/asm-x86/desc_64.h
@@ -147,23 +147,6 @@ static inline void set_ldt_desc(unsigned
(unsigned long)addr, DESC_LDT, size * 8 - 1);
}

-#define LDT_entry_a(info) \
- ((((info)->base_addr & 0x0000ffff) << 16) | ((info)->limit & 0x0ffff))
-/* Don't allow setting of the lm bit. It is useless anyways because
- 64bit system calls require __USER_CS. */
-#define LDT_entry_b(info) \
- (((info)->base_addr & 0xff000000) | \
- (((info)->base_addr & 0x00ff0000) >> 16) | \
- ((info)->limit & 0xf0000) | \
- (((info)->read_exec_only ^ 1) << 9) | \
- ((info)->contents << 10) | \
- (((info)->seg_not_present ^ 1) << 15) | \
- ((info)->seg_32bit << 22) | \
- ((info)->limit_in_pages << 23) | \
- ((info)->useable << 20) | \
- /* ((info)->lm << 21) | */ \
- 0x7000)
-
#define LDT_empty(info) (\
(info)->base_addr == 0 && \
(info)->limit == 0 && \
Index: linux-2.6-x86/include/asm-x86/desc.h
===================================================================
--- linux-2.6-x86.orig/include/asm-x86/desc.h
+++ linux-2.6-x86/include/asm-x86/desc.h
@@ -1,5 +1,34 @@
+#ifndef _ASM_DESC_H_
+#define _ASM_DESC_H_
+
+#ifndef __ASSEMBLY__
+#include <asm/desc_defs.h>
+#include <asm/ldt.h>
+
+static inline void fill_ldt(struct desc_struct *desc, struct user_desc *info)
+{
+ desc->limit0 = info->limit & 0x0ffff;
+ desc->base0 = info->base_addr & 0x0000ffff;
+
+ desc->base1 = (info->base_addr & 0x00ff0000) >> 16;
+ desc->type = (info->read_exec_only ^ 1) << 1;
+ desc->type |= info->contents << 2;
+ desc->s = 1;
+ desc->dpl = 0x3;
+ desc->p = info->seg_not_present ^ 1;
+ desc->limit = (info->limit & 0xf0000) >> 16;
+ desc->avl = info->useable;
+ desc->d = info->seg_32bit;
+ desc->g = info->limit_in_pages;
+ desc->base2 = (info->base_addr & 0xff000000) >> 24;
+}
+
+#endif
+
#ifdef CONFIG_X86_32
# include "desc_32.h"
#else
# include "desc_64.h"
#endif
+
+#endif

2007-12-13 04:51:55

by Glauber Costa

[permalink] [raw]
Subject: [PATCH 11/19] change write_gdt_entry signature.

This patch changes the write_gdt_entry function signature.
Instead of the old "a" and "b" parameters, it now receives
a pointer to a desc_struct, and the size of the entry being
handled. This is because x86_64 can have some 16-byte entries
as well as 8-byte ones.

Signed-off-by: Glauber de Oliveira Costa <[email protected]>
CC: Zachary Amsden <[email protected]>
CC: Jeremy Fitzhardinge <Jeremy.Fitzhardinge.citrix.com>
---
arch/x86/kernel/paravirt_32.c | 2 +-
arch/x86/kernel/smpcommon_32.c | 7 ++++---
arch/x86/kernel/vmi_32.c | 21 +++++++++++++++------
arch/x86/lguest/boot.c | 6 +++---
arch/x86/xen/enlighten.c | 11 +++++------
include/asm-x86/desc_32.h | 34 ++++++++++++++++++++++------------
include/asm-x86/paravirt.h | 9 ++++++---
7 files changed, 56 insertions(+), 34 deletions(-)

diff --git a/arch/x86/kernel/paravirt_32.c b/arch/x86/kernel/paravirt_32.c
index 13bbc99..77602c1 100644
--- a/arch/x86/kernel/paravirt_32.c
+++ b/arch/x86/kernel/paravirt_32.c
@@ -380,7 +380,7 @@ struct pv_cpu_ops pv_cpu_ops = {
.store_tr = native_store_tr,
.load_tls = native_load_tls,
.write_ldt_entry = write_dt_entry,
- .write_gdt_entry = write_dt_entry,
+ .write_gdt_entry = native_write_gdt_entry,
.write_idt_entry = native_write_idt_entry,
.load_sp0 = native_load_sp0,

diff --git a/arch/x86/kernel/smpcommon_32.c b/arch/x86/kernel/smpcommon_32.c
index bbfe85a..8bc38af 100644
--- a/arch/x86/kernel/smpcommon_32.c
+++ b/arch/x86/kernel/smpcommon_32.c
@@ -14,10 +14,11 @@ __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(&gdt[GDT_ENTRY_PERCPU],
__per_cpu_offset[cpu], 0xFFFFF,
- 0x80 | DESCTYPE_S | 0x2, 0x8);
+ 0x2 | DESCTYPE_S, 0x8);
+
+ gdt[GDT_ENTRY_PERCPU].s = 1;

per_cpu(this_cpu_off, cpu) = __per_cpu_offset[cpu];
per_cpu(cpu_number, cpu) = cpu;
diff --git a/arch/x86/kernel/vmi_32.c b/arch/x86/kernel/vmi_32.c
index a635b22..21edd0d 100644
--- a/arch/x86/kernel/vmi_32.c
+++ b/arch/x86/kernel/vmi_32.c
@@ -63,6 +63,7 @@ static struct {
void (*_set_ldt)(u32 selector);
void (*set_tr)(u32 selector);
void (*write_idt_entry)(struct desc_struct *, int, u32, u32);
+ void (*write_gdt_entry)(struct desc_struct *, int, u32, u32);
void (*set_kernel_stack)(u32 selector, u32 sp0);
void (*allocate_page)(u32, u32, u32, u32, u32);
void (*release_page)(u32, u32);
@@ -187,7 +188,7 @@ static void vmi_cpuid(unsigned int *ax, unsigned int *bx,
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);
+ write_gdt_entry(gdt, nr, new, 0);
}

static void vmi_load_tls(struct thread_struct *t, unsigned int cpu)
@@ -201,12 +202,12 @@ static void vmi_load_tls(struct thread_struct *t, unsigned int cpu)
static void vmi_set_ldt(const void *addr, unsigned entries)
{
unsigned cpu = smp_processor_id();
- u32 low, high;
+ struct desc_struct desc;

- pack_descriptor(&low, &high, (unsigned long)addr,
+ pack_descriptor(&desc, (unsigned long)addr,
entries * sizeof(struct desc_struct) - 1,
- DESCTYPE_LDT, 0);
- write_gdt_entry(get_cpu_gdt_table(cpu), GDT_ENTRY_LDT, low, high);
+ DESC_LDT, 0);
+ write_gdt_entry(get_cpu_gdt_table(cpu), GDT_ENTRY_LDT, &desc, DESC_LDT);
vmi_ops._set_ldt(entries ? GDT_ENTRY_LDT*sizeof(struct desc_struct) : 0);
}

@@ -221,6 +222,13 @@ static void vmi_write_idt_entry(gate_desc *dt, int entry, const gate_desc *g)
vmi_ops.write_idt_entry(dt, entry, idt_entry[0], idt_entry[2]);
}

+static void vmi_write_gdt_entry(struct desc_struct *dt, int entry,
+ const void *desc, int type)
+{
+ u32 *gdt_entry = (u32 *)desc;
+ vmi_ops.write_gdt_entry(dt, entry, gdt_entry[0], gdt_entry[2]);
+}
+
static void vmi_load_sp0(struct tss_struct *tss,
struct thread_struct *thread)
{
@@ -798,7 +806,8 @@ static inline int __init activate_vmi(void)
para_fill(pv_cpu_ops.store_tr, GetTR);
pv_cpu_ops.load_tls = vmi_load_tls;
para_fill(pv_cpu_ops.write_ldt_entry, WriteLDTEntry);
- para_fill(pv_cpu_ops.write_gdt_entry, WriteGDTEntry);
+ para_wrap(pv_cpu_ops.write_gdt_entry, vmi_write_gdt_entry,
+ write_gdt_entry, WriteGDTEntry);
para_wrap(pv_cpu_ops.write_idt_entry, vmi_write_idt_entry,
write_idt_entry, WriteIDTEntry);
para_wrap(pv_cpu_ops.load_sp0, vmi_load_sp0, set_kernel_stack, UpdateKernelStack);
diff --git a/arch/x86/lguest/boot.c b/arch/x86/lguest/boot.c
index b50c8ad..a633737 100644
--- a/arch/x86/lguest/boot.c
+++ b/arch/x86/lguest/boot.c
@@ -262,10 +262,10 @@ static void lguest_load_gdt(const struct desc_ptr *desc)
/* For a single GDT entry which changes, we do the lazy thing: alter our GDT,
* then tell the Host to reload the entire thing. This operation is so rare
* that this naive implementation is reasonable. */
-static void lguest_write_gdt_entry(struct desc_struct *dt,
- int entrynum, u32 low, u32 high)
+static void lguest_write_gdt_entry(struct desc_struct *dt, int entrynum,
+ const void *desc, int type)
{
- write_dt_entry(dt, entrynum, low, high);
+ native_write_gdt_entry(dt, entrynum, desc, type);
hcall(LHCALL_LOAD_GDT, __pa(dt), GDT_ENTRIES, 0);
}

diff --git a/arch/x86/xen/enlighten.c b/arch/x86/xen/enlighten.c
index 6dd349e..c38240c 100644
--- a/arch/x86/xen/enlighten.c
+++ b/arch/x86/xen/enlighten.c
@@ -475,22 +475,21 @@ static void xen_load_idt(const struct desc_ptr *desc)
/* Write a GDT descriptor entry. Ignore LDT descriptors, since
they're handled differently. */
static void xen_write_gdt_entry(struct desc_struct *dt, int entry,
- u32 low, u32 high)
+ const void *desc, int type)
{
preempt_disable();

- switch ((high >> 8) & 0xff) {
- case DESCTYPE_LDT:
- case DESCTYPE_TSS:
+ switch (type) {
+ case DESC_LDT:
+ case DESC_TSS:
/* ignore */
break;

default: {
xmaddr_t maddr = virt_to_machine(&dt[entry]);
- u64 desc = (u64)high << 32 | low;

xen_mc_flush();
- if (HYPERVISOR_update_descriptor(maddr.maddr, desc))
+ if (HYPERVISOR_update_descriptor(maddr.maddr, *(u64 *)desc))
BUG();
}

diff --git a/include/asm-x86/desc_32.h b/include/asm-x86/desc_32.h
index 0370099..41d8214 100644
--- a/include/asm-x86/desc_32.h
+++ b/include/asm-x86/desc_32.h
@@ -28,12 +28,13 @@ extern struct desc_ptr idt_descr;
extern gate_desc idt_table[];
extern void set_intr_gate(unsigned int irq, void * addr);

-static inline void pack_descriptor(__u32 *a, __u32 *b,
+static inline void pack_descriptor(struct desc_struct *desc,
unsigned long base, unsigned long limit, unsigned char type, unsigned char flags)
{
- *a = ((base & 0xffff) << 16) | (limit & 0xffff);
- *b = (base & 0xff000000) | ((base & 0xff0000) >> 16) |
+ desc->a = ((base & 0xffff) << 16) | (limit & 0xffff);
+ desc->b = (base & 0xff000000) | ((base & 0xff0000) >> 16) |
(limit & 0x000f0000) | ((type & 0xff) << 8) | ((flags & 0xf) << 20);
+ desc->p = 1;
}

static inline void pack_gate(gate_desc *gate,
@@ -69,7 +70,8 @@ static inline void pack_gate(gate_desc *gate,
#define set_ldt native_set_ldt

#define write_ldt_entry(dt, entry, a, b) write_dt_entry(dt, entry, a, b)
-#define write_gdt_entry(dt, entry, a, b) write_dt_entry(dt, entry, a, b)
+#define write_gdt_entry(dt, entry, desc, type) \
+ native_write_gdt_entry(dt, entry, desc, type)
#define write_idt_entry(dt, entry, g) native_write_idt_entry(dt, entry, g)
#endif

@@ -79,6 +81,12 @@ static inline void native_write_idt_entry(gate_desc *idt, int entry,
memcpy(&idt[entry], gate, sizeof(*gate));
}

+static inline void native_write_gdt_entry(struct desc_struct *gdt, int entry,
+ const void *desc, int type)
+{
+ memcpy(&gdt[entry], desc, sizeof(struct desc_struct));
+}
+
static inline void write_dt_entry(struct desc_struct *dt,
int entry, u32 entry_low, u32 entry_high)
{
@@ -86,18 +94,20 @@ static inline void write_dt_entry(struct desc_struct *dt,
dt[entry].b = entry_high;
}

+
static inline void native_set_ldt(const void *addr, unsigned int entries)
{
if (likely(entries == 0))
__asm__ __volatile__("lldt %w0"::"q" (0));
else {
unsigned cpu = smp_processor_id();
- __u32 a, b;
+ ldt_desc ldt;

- pack_descriptor(&a, &b, (unsigned long)addr,
+ pack_descriptor(&ldt, (unsigned long)addr,
entries * sizeof(struct desc_struct) - 1,
- DESCTYPE_LDT, 0);
- write_gdt_entry(get_cpu_gdt_table(cpu), GDT_ENTRY_LDT, a, b);
+ DESC_LDT, 0);
+ write_gdt_entry(get_cpu_gdt_table(cpu), GDT_ENTRY_LDT,
+ &ldt, DESC_LDT);
__asm__ __volatile__("lldt %w0"::"q" (GDT_ENTRY_LDT*8));
}
}
@@ -153,11 +163,11 @@ static inline void _set_gate(int gate, unsigned int type, void *addr, unsigned s

static inline void __set_tss_desc(unsigned int cpu, unsigned int entry, const void *addr)
{
- __u32 a, b;
- pack_descriptor(&a, &b, (unsigned long)addr,
+ tss_desc tss;
+ pack_descriptor(&tss, (unsigned long)addr,
offsetof(struct tss_struct, __cacheline_filler) - 1,
- DESCTYPE_TSS, 0);
- write_gdt_entry(get_cpu_gdt_table(cpu), entry, a, b);
+ DESC_TSS, 0);
+ write_gdt_entry(get_cpu_gdt_table(cpu), entry, &tss, DESC_TSS);
}


diff --git a/include/asm-x86/paravirt.h b/include/asm-x86/paravirt.h
index 86a9d7b..3f2abf2 100644
--- a/include/asm-x86/paravirt.h
+++ b/include/asm-x86/paravirt.h
@@ -99,7 +99,7 @@ struct pv_cpu_ops {
void (*write_ldt_entry)(struct desc_struct *,
int entrynum, u32 low, u32 high);
void (*write_gdt_entry)(struct desc_struct *,
- int entrynum, u32 low, u32 high);
+ int entrynum, const void *desc, int size);
void (*write_idt_entry)(gate_desc *,
int entrynum, const gate_desc *gate);
void (*load_sp0)(struct tss_struct *tss, struct thread_struct *t);
@@ -664,10 +664,13 @@ static inline void write_ldt_entry(void *dt, int entry, u32 low, u32 high)
{
PVOP_VCALL4(pv_cpu_ops.write_ldt_entry, dt, entry, low, high);
}
-static inline void write_gdt_entry(void *dt, int entry, u32 low, u32 high)
+
+static inline void write_gdt_entry(struct desc_struct *dt, int entry,
+ void *desc, int type)
{
- PVOP_VCALL4(pv_cpu_ops.write_gdt_entry, dt, entry, low, high);
+ PVOP_VCALL4(pv_cpu_ops.write_gdt_entry, dt, entry, desc, type);
}
+
static inline void write_idt_entry(gate_desc *dt, int entry, const gate_desc *g)
{
PVOP_VCALL3(pv_cpu_ops.write_idt_entry, dt, entry, g);
--
1.5.0.6

2007-12-13 04:52:28

by Glauber Costa

[permalink] [raw]
Subject: [PATCH 14/19] unify non-paravirt parts of desc.h

This patch unifies the non-paravirt part of desc_{32,64}.h into
desc.h. Most of it, is simply common code, that is moved to
the shared header. The only exception is the set_ldt_desc in desc_64.h,
which is changed - included its name - to accomodate for the way
the ldt is set up in i386.

Also, constant definitions used in desc_32.h are moved to desc_defs.h

Signed-off-by: Glauber de Oliveira Costa <[email protected]>
---
include/asm-x86/desc.h | 87 ++++++++++++++++++++++++++++++++++++++
include/asm-x86/desc_32.h | 66 ----------------------------
include/asm-x86/desc_64.h | 64 ++++-----------------------
include/asm-x86/mmu_context_64.h | 4 +-
4 files changed, 99 insertions(+), 122 deletions(-)

Index: linux-2.6-x86/include/asm-x86/desc.h
===================================================================
--- linux-2.6-x86.orig/include/asm-x86/desc.h
+++ linux-2.6-x86/include/asm-x86/desc.h
@@ -4,6 +4,7 @@
#ifndef __ASSEMBLY__
#include <asm/desc_defs.h>
#include <asm/ldt.h>
+#include <asm/mmu.h>

static inline void fill_ldt(struct desc_struct *desc, struct user_desc *info)
{
@@ -23,7 +24,8 @@ static inline void fill_ldt(struct desc_
desc->base2 = (info->base_addr & 0xff000000) >> 24;
}

-#endif
+extern struct desc_ptr idt_descr;
+extern gate_desc idt_table[];

#ifdef CONFIG_X86_32
# include "desc_32.h"
@@ -31,4 +33,65 @@ static inline void fill_ldt(struct desc_
# include "desc_64.h"
#endif

+#define _LDT_empty(info) (\
+ (info)->base_addr == 0 && \
+ (info)->limit == 0 && \
+ (info)->contents == 0 && \
+ (info)->read_exec_only == 1 && \
+ (info)->seg_32bit == 0 && \
+ (info)->limit_in_pages == 0 && \
+ (info)->seg_not_present == 1 && \
+ (info)->useable == 0)
+
+#ifdef CONFIG_X86_64
+#define LDT_empty(info) (_LDT_empty(info) && ((info)->lm == 0))
+#else
+#define LDT_empty(info) (_LDT_empty(info))
+#endif
+
+static inline void clear_LDT(void)
+{
+ set_ldt(NULL, 0);
+}
+
+/*
+ * load one particular LDT into the current CPU
+ */
+static inline void load_LDT_nolock(mm_context_t *pc)
+{
+ set_ldt(pc->ldt, pc->size);
+}
+
+static inline void load_LDT(mm_context_t *pc)
+{
+ preempt_disable();
+ load_LDT_nolock(pc);
+ preempt_enable();
+}
+
+#else
+/*
+ * GET_DESC_BASE reads the descriptor base of the specified segment.
+ *
+ * Args:
+ * idx - descriptor index
+ * gdt - GDT pointer
+ * base - 32bit register to which the base will be written
+ * lo_w - lo word of the "base" register
+ * lo_b - lo byte of the "base" register
+ * hi_b - hi byte of the low word of the "base" register
+ *
+ * Example:
+ * GET_DESC_BASE(GDT_ENTRY_ESPFIX_SS, %ebx, %eax, %ax, %al, %ah)
+ * Will read the base address of GDT_ENTRY_ESPFIX_SS and put it into %eax.
+ */
+#define GET_DESC_BASE(idx, gdt, base, lo_w, lo_b, hi_b) \
+ movb idx*8+4(gdt), lo_b; \
+ movb idx*8+7(gdt), hi_b; \
+ shll $16, base; \
+ movw idx*8+2(gdt), lo_w;
+
+
+#endif /* __ASSEMBLY__ */
+
#endif
Index: linux-2.6-x86/include/asm-x86/desc_32.h
===================================================================
--- linux-2.6-x86.orig/include/asm-x86/desc_32.h
+++ linux-2.6-x86/include/asm-x86/desc_32.h
@@ -11,8 +11,6 @@
#include <linux/smp.h>
#include <linux/percpu.h>

-#include <asm/mmu.h>
-
struct gdt_page
{
struct desc_struct gdt[GDT_ENTRIES];
@@ -24,8 +22,6 @@ static inline struct desc_struct *get_cp
return per_cpu(gdt_page, cpu).gdt;
}

-extern struct desc_ptr idt_descr;
-extern gate_desc idt_table[];
extern void set_intr_gate(unsigned int irq, void * addr);

static inline void pack_descriptor(struct desc_struct *desc,
@@ -172,36 +168,6 @@ static inline void __set_tss_desc(unsign

#define set_tss_desc(cpu,addr) __set_tss_desc(cpu, GDT_ENTRY_TSS, addr)

-#define LDT_empty(info) (\
- (info)->base_addr == 0 && \
- (info)->limit == 0 && \
- (info)->contents == 0 && \
- (info)->read_exec_only == 1 && \
- (info)->seg_32bit == 0 && \
- (info)->limit_in_pages == 0 && \
- (info)->seg_not_present == 1 && \
- (info)->useable == 0 )
-
-static inline void clear_LDT(void)
-{
- set_ldt(NULL, 0);
-}
-
-/*
- * load one particular LDT into the current CPU
- */
-static inline void load_LDT_nolock(mm_context_t *pc)
-{
- set_ldt(pc->ldt, pc->size);
-}
-
-static inline void load_LDT(mm_context_t *pc)
-{
- preempt_disable();
- load_LDT_nolock(pc);
- preempt_enable();
-}
-
static inline unsigned long get_desc_base(unsigned long *desc)
{
unsigned long base;
@@ -210,30 +176,6 @@ static inline unsigned long get_desc_bas
(desc[1] & 0xff000000);
return base;
}
-
-#else /* __ASSEMBLY__ */
-
-/*
- * GET_DESC_BASE reads the descriptor base of the specified segment.
- *
- * Args:
- * idx - descriptor index
- * gdt - GDT pointer
- * base - 32bit register to which the base will be written
- * lo_w - lo word of the "base" register
- * lo_b - lo byte of the "base" register
- * hi_b - hi byte of the low word of the "base" register
- *
- * Example:
- * GET_DESC_BASE(GDT_ENTRY_ESPFIX_SS, %ebx, %eax, %ax, %al, %ah)
- * Will read the base address of GDT_ENTRY_ESPFIX_SS and put it into %eax.
- */
-#define GET_DESC_BASE(idx, gdt, base, lo_w, lo_b, hi_b) \
- movb idx*8+4(gdt), lo_b; \
- movb idx*8+7(gdt), hi_b; \
- shll $16, base; \
- movw idx*8+2(gdt), lo_w;
-
#endif /* !__ASSEMBLY__ */

#endif
Index: linux-2.6-x86/include/asm-x86/desc_64.h
===================================================================
--- linux-2.6-x86.orig/include/asm-x86/desc_64.h
+++ linux-2.6-x86/include/asm-x86/desc_64.h
@@ -9,16 +9,13 @@

#include <linux/string.h>
#include <linux/smp.h>
-#include <asm/desc_defs.h>

#include <asm/segment.h>
-#include <asm/mmu.h>

extern struct desc_struct cpu_gdt_table[GDT_ENTRIES];

#define load_TR_desc() asm volatile("ltr %w0"::"r" (GDT_ENTRY_TSS*8))
#define load_LDT_desc() asm volatile("lldt %w0"::"r" (GDT_ENTRY_LDT*8))
-#define clear_LDT() asm volatile("lldt %w0"::"r" (0))

static inline unsigned long __store_tr(void)
{
@@ -30,7 +27,6 @@ static inline unsigned long __store_tr(v

#define store_tr(tr) (tr) = __store_tr()

-extern gate_desc idt_table[];
extern struct desc_ptr cpu_gdt_descr[];

static inline void write_ldt_entry(struct desc_struct *ldt,
@@ -138,23 +134,19 @@ static inline void set_tss_desc(unsigned
IO_BITMAP_OFFSET + IO_BITMAP_BYTES + sizeof(unsigned long) - 1);
}

-static inline void set_ldt_desc(unsigned cpu, void *addr, int size)
+static inline void set_ldt(void *addr, int entries)
{
- set_tssldt_descriptor(&get_cpu_gdt_table(cpu)[GDT_ENTRY_LDT],
- (unsigned long)addr, DESC_LDT, size * 8 - 1);
+ if (likely(entries == 0))
+ __asm__ __volatile__("lldt %w0"::"q" (0));
+ else {
+ unsigned cpu = smp_processor_id();
+
+ set_tssldt_descriptor(&get_cpu_gdt_table(cpu)[GDT_ENTRY_LDT],
+ (unsigned long)addr, DESC_LDT, entries * 8 - 1);
+ __asm__ __volatile__("lldt %w0"::"q" (GDT_ENTRY_LDT*8));
+ }
}

-#define LDT_empty(info) (\
- (info)->base_addr == 0 && \
- (info)->limit == 0 && \
- (info)->contents == 0 && \
- (info)->read_exec_only == 1 && \
- (info)->seg_32bit == 0 && \
- (info)->limit_in_pages == 0 && \
- (info)->seg_not_present == 1 && \
- (info)->useable == 0 && \
- (info)->lm == 0)
-
static inline void load_TLS(struct thread_struct *t, unsigned int cpu)
{
unsigned int i;
@@ -164,32 +156,6 @@ static inline void load_TLS(struct threa
gdt[i] = t->tls_array[i];
}

-/*
- * load one particular LDT into the current CPU
- */
-static inline void load_LDT_nolock(mm_context_t *pc, int cpu)
-{
- int count = pc->size;
-
- if (likely(!count)) {
- clear_LDT();
- return;
- }
-
- set_ldt_desc(cpu, pc->ldt, count);
- load_LDT_desc();
-}
-
-static inline void load_LDT(mm_context_t *pc)
-{
- int cpu = get_cpu();
-
- load_LDT_nolock(pc, cpu);
- put_cpu();
-}
-
-extern struct desc_ptr idt_descr;
-
static inline unsigned long get_desc_base(const void *ptr)
{
const u32 *desc = ptr;
@@ -199,7 +165,6 @@ static inline unsigned long get_desc_bas
(desc[1] & 0xff000000);
return base;
}
-
#endif /* !__ASSEMBLY__ */

#endif
Index: linux-2.6-x86/include/asm-x86/mmu_context_64.h
===================================================================
--- linux-2.6-x86.orig/include/asm-x86/mmu_context_64.h
+++ linux-2.6-x86/include/asm-x86/mmu_context_64.h
@@ -43,7 +43,7 @@ static inline void switch_mm(struct mm_s
load_cr3(next->pgd);

if (unlikely(next->context.ldt != prev->context.ldt))
- load_LDT_nolock(&next->context, cpu);
+ load_LDT_nolock(&next->context);
}
#ifdef CONFIG_SMP
else {
@@ -56,7 +56,7 @@ static inline void switch_mm(struct mm_s
* to make sure to use no freed page tables.
*/
load_cr3(next->pgd);
- load_LDT_nolock(&next->context, cpu);
+ load_LDT_nolock(&next->context);
}
}
#endif

2007-12-13 04:52:46

by Glauber Costa

[permalink] [raw]
Subject: [PATCH 13/19] move constants to desc_defs.h

this patch moves constant definitions regarding descriptor types
from desc_32.h to desc_defs.h. The change from defines to enum
to comply with previous versions in desc_defs.h

Signed-off-by: Glauber de Oliveira Costa <[email protected]>
---
include/asm-x86/desc_32.h | 8 --------
include/asm-x86/desc_defs.h | 5 +++++
2 files changed, 5 insertions(+), 8 deletions(-)

diff --git a/include/asm-x86/desc_32.h b/include/asm-x86/desc_32.h
index 92a72b0..14238df 100644
--- a/include/asm-x86/desc_32.h
+++ b/include/asm-x86/desc_32.h
@@ -44,14 +44,6 @@ static inline void pack_gate(gate_desc *gate,
gate->b = (base & 0xffff0000) | ((type & 0xff) << 8) | (flags & 0xff);
}

-#define DESCTYPE_LDT 0x82 /* present, system, DPL-0, LDT */
-#define DESCTYPE_TSS 0x89 /* present, system, DPL-0, 32-bit TSS */
-#define DESCTYPE_TASK 0x85 /* present, system, DPL-0, task gate */
-#define DESCTYPE_INT 0x8e /* present, system, DPL-0, interrupt gate */
-#define DESCTYPE_TRAP 0x8f /* present, system, DPL-0, trap gate */
-#define DESCTYPE_DPL3 0x60 /* DPL-3 */
-#define DESCTYPE_S 0x10 /* !system */
-
#ifdef CONFIG_PARAVIRT
#include <asm/paravirt.h>
#else
diff --git a/include/asm-x86/desc_defs.h b/include/asm-x86/desc_defs.h
index c4d7874..5ca416d 100644
--- a/include/asm-x86/desc_defs.h
+++ b/include/asm-x86/desc_defs.h
@@ -55,6 +55,11 @@ struct gate_struct64 {
enum {
DESC_TSS = 0x9,
DESC_LDT = 0x2,
+ DESCTYPE_TASK = 0x85, /* present, system, DPL-0, task gate */
+ DESCTYPE_INT = 0x8e, /* present, system, DPL-0, interrupt gate */
+ DESCTYPE_TRAP = 0x8f, /* present, system, DPL-0, trap gate */
+ DESCTYPE_DPL3 = 0x60, /* DPL-3 */
+ DESCTYPE_S = 0x10, /* !system */
};

// LDT or TSS descriptor in the GDT. 16 bytes.
--
1.5.0.6

2007-12-13 04:53:08

by Glauber Costa

[permalink] [raw]
Subject: [PATCH 19/19] unify set_tss_desc

This patch unifies the set_tss_desc between i386 and x86_64,
which can now have a common implementation. After the old
functions are removed from desc_{32,64}.h, nothing important is
left, and the files can be removed.

Signed-off-by: Glauber de Oliveira Costa <[email protected]>
---
include/asm-x86/desc.h | 40 +++++++++++++++++++++++++++++++++-------
include/asm-x86/desc_32.h | 27 ---------------------------
include/asm-x86/desc_64.h | 34 ----------------------------------
3 files changed, 33 insertions(+), 68 deletions(-)
delete mode 100644 include/asm-x86/desc_32.h
delete mode 100644 include/asm-x86/desc_64.h

Index: linux-2.6-x86/include/asm-x86/desc.h
===================================================================
--- linux-2.6-x86.orig/include/asm-x86/desc.h
+++ linux-2.6-x86/include/asm-x86/desc.h
@@ -165,6 +165,39 @@ static inline void pack_ldt(ldt_desc *ld
#endif
}

+static inline void pack_tss(tss_desc *tss, unsigned long addr,
+ unsigned size, unsigned entry)
+{
+#ifdef CONFIG_X86_64
+ set_tssldt_descriptor(tss,
+ addr, entry, size);
+#else
+ pack_descriptor(tss, (unsigned long)addr,
+ size,
+ 0x80 | entry, 0);
+#endif
+}
+
+static inline void __set_tss_desc(unsigned cpu, unsigned int entry, void *addr)
+{
+ struct desc_struct *d = get_cpu_gdt_table(cpu);
+ tss_desc tss;
+
+ /*
+ * sizeof(unsigned long) coming from an extra "long" at the end
+ * of the iobitmap. See tss_struct definition in processor.h
+ *
+ * -1? seg base+limit should be pointing to the address of the
+ * last valid byte
+ */
+ pack_tss(&tss, (unsigned long)addr,
+ IO_BITMAP_OFFSET + IO_BITMAP_BYTES + sizeof(unsigned long) - 1,
+ DESC_TSS);
+ write_gdt_entry(d, entry, &tss, DESC_TSS);
+}
+
+#define set_tss_desc(cpu, addr) __set_tss_desc(cpu, GDT_ENTRY_TSS, addr)
+
static inline void native_set_ldt(const void *addr, unsigned int entries)
{
if (likely(entries == 0))
@@ -222,12 +255,6 @@ static inline void native_load_tls(struc
gdt[GDT_ENTRY_TLS_MIN + i] = t->tls_array[i];
}

-#ifdef CONFIG_X86_32
-# include "desc_32.h"
-#else
-# include "desc_64.h"
-#endif
-
#define _LDT_empty(info) (\
(info)->base_addr == 0 && \
(info)->limit == 0 && \
Index: linux-2.6-x86/include/asm-x86/desc_32.h
===================================================================
--- linux-2.6-x86.orig/include/asm-x86/desc_32.h
+++ /dev/null
@@ -1,27 +0,0 @@
-#ifndef __ARCH_DESC_H
-#define __ARCH_DESC_H
-
-#include <asm/ldt.h>
-#include <asm/segment.h>
-#include <asm/desc_defs.h>
-
-#ifndef __ASSEMBLY__
-
-#include <linux/preempt.h>
-#include <linux/percpu.h>
-
-static inline void __set_tss_desc(unsigned int cpu, unsigned int entry, const void *addr)
-{
- tss_desc tss;
- pack_descriptor(&tss, (unsigned long)addr,
- offsetof(struct tss_struct, __cacheline_filler) - 1,
- DESC_TSS, 0);
- write_gdt_entry(get_cpu_gdt_table(cpu), entry, &tss, DESC_TSS);
-}
-
-
-#define set_tss_desc(cpu,addr) __set_tss_desc(cpu, GDT_ENTRY_TSS, addr)
-
-#endif /* !__ASSEMBLY__ */
-
-#endif
Index: linux-2.6-x86/include/asm-x86/desc_64.h
===================================================================
--- linux-2.6-x86.orig/include/asm-x86/desc_64.h
+++ linux-2.6-x86/include/asm-x86/desc_64.h
@@ -1,34 +1 @@
-/* Written 2000 by Andi Kleen */
-#ifndef __ARCH_DESC_H
-#define __ARCH_DESC_H

-#include <linux/threads.h>
-#include <asm/ldt.h>
-
-#ifndef __ASSEMBLY__
-
-#include <linux/string.h>
-
-#include <asm/segment.h>
-
-static inline void set_tss_desc(unsigned cpu, void *addr)
-{
- struct desc_struct *d = get_cpu_gdt_table(cpu);
- tss_desc tss;
-
- /*
- * sizeof(unsigned long) coming from an extra "long" at the end
- * of the iobitmap. See tss_struct definition in processor.h
- *
- * -1? seg base+limit should be pointing to the address of the
- * last valid byte
- */
- set_tssldt_descriptor(&tss,
- (unsigned long)addr, DESC_TSS,
- IO_BITMAP_OFFSET + IO_BITMAP_BYTES + sizeof(unsigned long) - 1);
- write_gdt_entry(d, GDT_ENTRY_TSS, &tss, DESC_TSS);
-}
-
-#endif /* !__ASSEMBLY__ */
-
-#endif

2007-12-13 12:46:50

by Andi Kleen

[permalink] [raw]
Subject: Re: [PATCH 19/19] unify set_tss_desc

> +static inline void pack_tss(tss_desc *tss, unsigned long addr,
> + unsigned size, unsigned entry)
> +{
> +#ifdef CONFIG_X86_64
> + set_tssldt_descriptor(tss,
> + addr, entry, size);
> +#else
> + pack_descriptor(tss, (unsigned long)addr,
> + size,
> + 0x80 | entry, 0);

It would be better if you just unified that first instead of ifdef'ing.
I guess i386 could get a set_tssldt_descriptor() like wrapper
around pack_descriptor().

-Andi

2007-12-13 14:52:23

by Glauber Costa

[permalink] [raw]
Subject: Re: [PATCH 19/19] unify set_tss_desc

Andi Kleen wrote:
>> +static inline void pack_tss(tss_desc *tss, unsigned long addr,
>> + unsigned size, unsigned entry)
>> +{
>> +#ifdef CONFIG_X86_64
>> + set_tssldt_descriptor(tss,
>> + addr, entry, size);
>> +#else
>> + pack_descriptor(tss, (unsigned long)addr,
>> + size,
>> + 0x80 | entry, 0);
>
> It would be better if you just unified that first instead of ifdef'ing.
> I guess i386 could get a set_tssldt_descriptor() like wrapper
> around pack_descriptor().
Good point.

Thanks, Andi.

2007-12-13 16:42:18

by Glauber Costa

[permalink] [raw]
Subject: [PATCH 0/19 -v4] desc_struct integration

Since the last version of it received no comments on the interfaces, here
it goes a version, that I feel ready for inclusion.

The comments regarding style, specially the elimination of the #defines in
the desc_struct definition were merged. I also implemented the vmi
functions,
missing last time.

Ingo, in the absense of further complaints, could you please push to the
x86 tree?

2007-12-13 16:43:25

by Glauber Costa

[permalink] [raw]
Subject: [PATCH 02/19] unify struct desc_ptr

This patch unifies struct desc_ptr between i386 and x86_64.
They can be expressed in the exact same way in C code, only
having to change the name of one of them. As Xgt_desc_struct
is ugly and big, this is the one that goes away.

There's also a padding field in i386, but it is not really
needed in the C structure definition.

Signed-off-by: Glauber de Oliveira Costa <[email protected]>
---
arch/x86/kernel/asm-offsets_32.c | 5 ++---
arch/x86/kernel/cpu/common.c | 2 +-
arch/x86/kernel/doublefault_32.c | 2 +-
arch/x86/kernel/efi_32.c | 4 ++--
arch/x86/kernel/machine_kexec_32.c | 4 ++--
arch/x86/kernel/reboot_32.c | 2 +-
arch/x86/lguest/boot.c | 4 ++--
arch/x86/xen/enlighten.c | 10 +++++-----
drivers/kvm/svm.c | 2 +-
include/asm-x86/desc_32.h | 16 +++++-----------
include/asm-x86/lguest.h | 8 ++++----
include/asm-x86/paravirt.h | 18 +++++++++---------
include/asm-x86/processor_32.h | 2 +-
include/asm-x86/suspend_32.h | 4 ++--
14 files changed, 38 insertions(+), 45 deletions(-)

Index: linux-2.6-x86/arch/x86/kernel/asm-offsets_32.c
===================================================================
--- linux-2.6-x86.orig/arch/x86/kernel/asm-offsets_32.c
+++ linux-2.6-x86/arch/x86/kernel/asm-offsets_32.c
@@ -70,9 +70,8 @@ void foo(void)
OFFSET(TI_cpu, thread_info, cpu);
BLANK();

- OFFSET(GDS_size, Xgt_desc_struct, size);
- OFFSET(GDS_address, Xgt_desc_struct, address);
- OFFSET(GDS_pad, Xgt_desc_struct, pad);
+ OFFSET(GDS_size, desc_ptr, size);
+ OFFSET(GDS_address, desc_ptr, address);
BLANK();

OFFSET(PT_EBX, pt_regs, bx);
Index: linux-2.6-x86/arch/x86/kernel/cpu/common.c
===================================================================
--- linux-2.6-x86.orig/arch/x86/kernel/cpu/common.c
+++ linux-2.6-x86/arch/x86/kernel/cpu/common.c
@@ -649,7 +649,7 @@ struct pt_regs * __devinit idle_regs(str
* it's on the real one. */
void switch_to_new_gdt(void)
{
- struct Xgt_desc_struct gdt_descr;
+ struct desc_ptr gdt_descr;

gdt_descr.address = (long)get_cpu_gdt_table(smp_processor_id());
gdt_descr.size = GDT_SIZE - 1;
Index: linux-2.6-x86/arch/x86/kernel/doublefault_32.c
===================================================================
--- linux-2.6-x86.orig/arch/x86/kernel/doublefault_32.c
+++ linux-2.6-x86/arch/x86/kernel/doublefault_32.c
@@ -17,7 +17,7 @@ static unsigned long doublefault_stack[D

static void doublefault_fn(void)
{
- struct Xgt_desc_struct gdt_desc = {0, 0};
+ struct desc_ptr gdt_desc = {0, 0};
unsigned long gdt, tss;

store_gdt(&gdt_desc);
Index: linux-2.6-x86/arch/x86/kernel/efi_32.c
===================================================================
--- linux-2.6-x86.orig/arch/x86/kernel/efi_32.c
+++ linux-2.6-x86/arch/x86/kernel/efi_32.c
@@ -69,7 +69,7 @@ static void efi_call_phys_prelog(void) _
{
unsigned long cr4;
unsigned long temp;
- struct Xgt_desc_struct gdt_descr;
+ struct desc_ptr gdt_descr;

spin_lock(&efi_rt_lock);
local_irq_save(efi_rt_eflags);
@@ -111,7 +111,7 @@ static void efi_call_phys_prelog(void) _
static void efi_call_phys_epilog(void) __releases(efi_rt_lock)
{
unsigned long cr4;
- struct Xgt_desc_struct gdt_descr;
+ struct desc_ptr gdt_descr;

gdt_descr.address = (unsigned long)get_cpu_gdt_table(0);
gdt_descr.size = GDT_SIZE - 1;
Index: linux-2.6-x86/arch/x86/kernel/machine_kexec_32.c
===================================================================
--- linux-2.6-x86.orig/arch/x86/kernel/machine_kexec_32.c
+++ linux-2.6-x86/arch/x86/kernel/machine_kexec_32.c
@@ -32,7 +32,7 @@ static u32 kexec_pte1[1024] PAGE_ALIGNED

static void set_idt(void *newidt, __u16 limit)
{
- struct Xgt_desc_struct curidt;
+ struct desc_ptr curidt;

/* ia32 supports unaliged loads & stores */
curidt.size = limit;
@@ -44,7 +44,7 @@ static void set_idt(void *newidt, __u16

static void set_gdt(void *newgdt, __u16 limit)
{
- struct Xgt_desc_struct curgdt;
+ struct desc_ptr curgdt;

/* ia32 supports unaligned loads & stores */
curgdt.size = limit;
Index: linux-2.6-x86/arch/x86/kernel/reboot_32.c
===================================================================
--- linux-2.6-x86.orig/arch/x86/kernel/reboot_32.c
+++ linux-2.6-x86/arch/x86/kernel/reboot_32.c
@@ -161,7 +161,7 @@ real_mode_gdt_entries [3] =
0x000092000100ffffULL /* 16-bit real-mode 64k data at 0x00000100 */
};

-static struct Xgt_desc_struct
+static struct desc_ptr
real_mode_gdt = { sizeof (real_mode_gdt_entries) - 1, (long)real_mode_gdt_entries },
real_mode_idt = { 0x3ff, 0 },
no_idt = { 0, 0 };
Index: linux-2.6-x86/arch/x86/lguest/boot.c
===================================================================
--- linux-2.6-x86.orig/arch/x86/lguest/boot.c
+++ linux-2.6-x86/arch/x86/lguest/boot.c
@@ -229,7 +229,7 @@ static void lguest_write_idt_entry(struc
/* Changing to a different IDT is very rare: we keep the IDT up-to-date every
* time it is written, so we can simply loop through all entries and tell the
* Host about them. */
-static void lguest_load_idt(const struct Xgt_desc_struct *desc)
+static void lguest_load_idt(const struct desc_ptr *desc)
{
unsigned int i;
struct desc_struct *idt = (void *)desc->address;
@@ -252,7 +252,7 @@ static void lguest_load_idt(const struct
* hypercall and use that repeatedly to load a new IDT. I don't think it
* really matters, but wouldn't it be nice if they were the same?
*/
-static void lguest_load_gdt(const struct Xgt_desc_struct *desc)
+static void lguest_load_gdt(const struct desc_ptr *desc)
{
BUG_ON((desc->size+1)/8 != GDT_ENTRIES);
hcall(LHCALL_LOAD_GDT, __pa(desc->address), GDT_ENTRIES, 0);
Index: linux-2.6-x86/arch/x86/xen/enlighten.c
===================================================================
--- linux-2.6-x86.orig/arch/x86/xen/enlighten.c
+++ linux-2.6-x86/arch/x86/xen/enlighten.c
@@ -295,7 +295,7 @@ static void xen_set_ldt(const void *addr
xen_mc_issue(PARAVIRT_LAZY_CPU);
}

-static void xen_load_gdt(const struct Xgt_desc_struct *dtr)
+static void xen_load_gdt(const struct desc_ptr *dtr)
{
unsigned long *frames;
unsigned long va = dtr->address;
@@ -395,7 +395,7 @@ static int cvt_gate_to_trap(int vector,
}

/* Locations of each CPU's IDT */
-static DEFINE_PER_CPU(struct Xgt_desc_struct, idt_desc);
+static DEFINE_PER_CPU(struct desc_ptr, idt_desc);

/* Set an IDT entry. If the entry is part of the current IDT, then
also update Xen. */
@@ -427,7 +427,7 @@ static void xen_write_idt_entry(struct d
preempt_enable();
}

-static void xen_convert_trap_info(const struct Xgt_desc_struct *desc,
+static void xen_convert_trap_info(const struct desc_ptr *desc,
struct trap_info *traps)
{
unsigned in, out, count;
@@ -446,7 +446,7 @@ static void xen_convert_trap_info(const

void xen_copy_trap_info(struct trap_info *traps)
{
- const struct Xgt_desc_struct *desc = &__get_cpu_var(idt_desc);
+ const struct desc_ptr *desc = &__get_cpu_var(idt_desc);

xen_convert_trap_info(desc, traps);
}
@@ -454,7 +454,7 @@ void xen_copy_trap_info(struct trap_info
/* Load a new IDT into Xen. In principle this can be per-CPU, so we
hold a spinlock to protect the static traps[] array (static because
it avoids allocation, and saves stack space). */
-static void xen_load_idt(const struct Xgt_desc_struct *desc)
+static void xen_load_idt(const struct desc_ptr *desc)
{
static DEFINE_SPINLOCK(lock);
static struct trap_info traps[257];
Index: linux-2.6-x86/drivers/kvm/svm.c
===================================================================
--- linux-2.6-x86.orig/drivers/kvm/svm.c
+++ linux-2.6-x86/drivers/kvm/svm.c
@@ -290,7 +290,7 @@ static void svm_hardware_enable(void *ga
#ifdef CONFIG_X86_64
struct desc_ptr gdt_descr;
#else
- struct Xgt_desc_struct gdt_descr;
+ struct desc_ptr gdt_descr;
#endif
struct desc_struct *gdt;
int me = raw_smp_processor_id();
Index: linux-2.6-x86/include/asm-x86/desc_32.h
===================================================================
--- linux-2.6-x86.orig/include/asm-x86/desc_32.h
+++ linux-2.6-x86/include/asm-x86/desc_32.h
@@ -12,12 +12,6 @@

#include <asm/mmu.h>

-struct Xgt_desc_struct {
- unsigned short size;
- unsigned long address __attribute__((packed));
- unsigned short pad;
-} __attribute__ ((packed));
-
struct gdt_page
{
struct desc_struct gdt[GDT_ENTRIES];
@@ -29,7 +23,7 @@ static inline struct desc_struct *get_cp
return per_cpu(gdt_page, cpu).gdt;
}

-extern struct Xgt_desc_struct idt_descr;
+extern struct desc_ptr idt_descr;
extern struct desc_struct idt_table[];
extern void set_intr_gate(unsigned int irq, void * addr);

@@ -107,22 +101,22 @@ static inline void native_load_tr_desc(v
asm volatile("ltr %w0"::"q" (GDT_ENTRY_TSS*8));
}

-static inline void native_load_gdt(const struct Xgt_desc_struct *dtr)
+static inline void native_load_gdt(const struct desc_ptr *dtr)
{
asm volatile("lgdt %0"::"m" (*dtr));
}

-static inline void native_load_idt(const struct Xgt_desc_struct *dtr)
+static inline void native_load_idt(const struct desc_ptr *dtr)
{
asm volatile("lidt %0"::"m" (*dtr));
}

-static inline void native_store_gdt(struct Xgt_desc_struct *dtr)
+static inline void native_store_gdt(struct desc_ptr *dtr)
{
asm ("sgdt %0":"=m" (*dtr));
}

-static inline void native_store_idt(struct Xgt_desc_struct *dtr)
+static inline void native_store_idt(struct desc_ptr *dtr)
{
asm ("sidt %0":"=m" (*dtr));
}
Index: linux-2.6-x86/include/asm-x86/lguest.h
===================================================================
--- linux-2.6-x86.orig/include/asm-x86/lguest.h
+++ linux-2.6-x86/include/asm-x86/lguest.h
@@ -44,13 +44,13 @@ struct lguest_ro_state
{
/* Host information we need to restore when we switch back. */
u32 host_cr3;
- struct Xgt_desc_struct host_idt_desc;
- struct Xgt_desc_struct host_gdt_desc;
+ struct desc_ptr host_idt_desc;
+ struct desc_ptr host_gdt_desc;
u32 host_sp;

/* Fields which are used when guest is running. */
- struct Xgt_desc_struct guest_idt_desc;
- struct Xgt_desc_struct guest_gdt_desc;
+ struct desc_ptr guest_idt_desc;
+ struct desc_ptr guest_gdt_desc;
struct i386_hw_tss guest_tss;
struct desc_struct guest_idt[IDT_ENTRIES];
struct desc_struct guest_gdt[GDT_ENTRIES];
Index: linux-2.6-x86/include/asm-x86/paravirt.h
===================================================================
--- linux-2.6-x86.orig/include/asm-x86/paravirt.h
+++ linux-2.6-x86/include/asm-x86/paravirt.h
@@ -20,7 +20,7 @@

struct page;
struct thread_struct;
-struct Xgt_desc_struct;
+struct desc_ptr;
struct tss_struct;
struct mm_struct;
struct desc_struct;
@@ -88,10 +88,10 @@ struct pv_cpu_ops {

/* Segment descriptor handling */
void (*load_tr_desc)(void);
- void (*load_gdt)(const struct Xgt_desc_struct *);
- void (*load_idt)(const struct Xgt_desc_struct *);
- void (*store_gdt)(struct Xgt_desc_struct *);
- void (*store_idt)(struct Xgt_desc_struct *);
+ void (*load_gdt)(const struct desc_ptr *);
+ void (*load_idt)(const struct desc_ptr *);
+ void (*store_gdt)(struct desc_ptr *);
+ void (*store_idt)(struct desc_ptr *);
void (*set_ldt)(const void *desc, unsigned entries);
unsigned long (*store_tr)(void);
void (*load_tls)(struct thread_struct *t, unsigned int cpu);
@@ -630,11 +630,11 @@ static inline void load_TR_desc(void)
{
PVOP_VCALL0(pv_cpu_ops.load_tr_desc);
}
-static inline void load_gdt(const struct Xgt_desc_struct *dtr)
+static inline void load_gdt(const struct desc_ptr *dtr)
{
PVOP_VCALL1(pv_cpu_ops.load_gdt, dtr);
}
-static inline void load_idt(const struct Xgt_desc_struct *dtr)
+static inline void load_idt(const struct desc_ptr *dtr)
{
PVOP_VCALL1(pv_cpu_ops.load_idt, dtr);
}
@@ -642,11 +642,11 @@ static inline void set_ldt(const void *a
{
PVOP_VCALL2(pv_cpu_ops.set_ldt, addr, entries);
}
-static inline void store_gdt(struct Xgt_desc_struct *dtr)
+static inline void store_gdt(struct desc_ptr *dtr)
{
PVOP_VCALL1(pv_cpu_ops.store_gdt, dtr);
}
-static inline void store_idt(struct Xgt_desc_struct *dtr)
+static inline void store_idt(struct desc_ptr *dtr)
{
PVOP_VCALL1(pv_cpu_ops.store_idt, dtr);
}
Index: linux-2.6-x86/include/asm-x86/processor_32.h
===================================================================
--- linux-2.6-x86.orig/include/asm-x86/processor_32.h
+++ linux-2.6-x86/include/asm-x86/processor_32.h
@@ -707,7 +707,7 @@ extern void enable_sep_cpu(void);
extern int sysenter_setup(void);

/* Defined in head.S */
-extern struct Xgt_desc_struct early_gdt_descr;
+extern struct desc_ptr early_gdt_descr;

extern void cpu_set_gdt(int);
extern void switch_to_new_gdt(void);
Index: linux-2.6-x86/include/asm-x86/suspend_32.h
===================================================================
--- linux-2.6-x86.orig/include/asm-x86/suspend_32.h
+++ linux-2.6-x86/include/asm-x86/suspend_32.h
@@ -12,8 +12,8 @@ static inline int arch_prepare_suspend(v
struct saved_context {
u16 es, fs, gs, ss;
unsigned long cr0, cr2, cr3, cr4;
- struct Xgt_desc_struct gdt;
- struct Xgt_desc_struct idt;
+ struct desc_ptr gdt;
+ struct desc_ptr idt;
u16 ldt;
u16 tss;
unsigned long tr;

2007-12-13 16:43:58

by Glauber Costa

[permalink] [raw]
Subject: [PATCH 03/19] change gdt acessor macro name

This patch changes the name of x86_64 macro used to access the per-cpu
gdt. It is now equal to the i386 version, which will allow code to be shared.

Signed-off-by: Glauber de Oliveira Costa <[email protected]>
---
arch/x86/kernel/setup64.c | 2 +-
arch/x86/kernel/suspend_64.c | 2 +-
arch/x86/kernel/vsyscall_64.c | 2 +-
include/asm-x86/desc_64.h | 10 +++++-----
4 files changed, 8 insertions(+), 8 deletions(-)

Index: linux-2.6-x86/arch/x86/kernel/setup64.c
===================================================================
--- linux-2.6-x86.orig/arch/x86/kernel/setup64.c
+++ linux-2.6-x86/arch/x86/kernel/setup64.c
@@ -228,7 +228,7 @@ void __cpuinit cpu_init (void)
* and set up the GDT descriptor:
*/
if (cpu)
- memcpy(cpu_gdt(cpu), cpu_gdt_table, GDT_SIZE);
+ memcpy(get_cpu_gdt_table(cpu), cpu_gdt_table, GDT_SIZE);

cpu_gdt_descr[cpu].size = GDT_SIZE;
load_gdt((const struct desc_ptr *)&cpu_gdt_descr[cpu]);
Index: linux-2.6-x86/arch/x86/kernel/suspend_64.c
===================================================================
--- linux-2.6-x86.orig/arch/x86/kernel/suspend_64.c
+++ linux-2.6-x86/arch/x86/kernel/suspend_64.c
@@ -118,7 +118,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;
+ get_cpu_gdt_table(cpu)[GDT_ENTRY_TSS].type = 9;

syscall_init(); /* This sets MSR_*STAR and related */
load_TR_desc(); /* This does ltr */
Index: linux-2.6-x86/arch/x86/kernel/vsyscall_64.c
===================================================================
--- linux-2.6-x86.orig/arch/x86/kernel/vsyscall_64.c
+++ linux-2.6-x86/arch/x86/kernel/vsyscall_64.c
@@ -297,7 +297,7 @@ static void __cpuinit vsyscall_set_cpu(i
/* Store cpu number in limit so that it can be loaded quickly
in user space in vgetcpu.
12 bits for the CPU and 8 bits for the node. */
- d = (unsigned long *)(cpu_gdt(cpu) + GDT_ENTRY_PER_CPU);
+ d = (unsigned long *)(get_cpu_gdt_table(cpu) + GDT_ENTRY_PER_CPU);
*d = 0x0f40000000000ULL;
*d |= cpu;
*d |= (node & 0xf) << 12;
Index: linux-2.6-x86/include/asm-x86/desc_64.h
===================================================================
--- linux-2.6-x86.orig/include/asm-x86/desc_64.h
+++ linux-2.6-x86/include/asm-x86/desc_64.h
@@ -48,7 +48,7 @@ static inline void write_ldt_entry(struc
}

/* the cpu gdt accessor */
-#define cpu_gdt(_cpu) ((struct desc_struct *)cpu_gdt_descr[_cpu].address)
+#define get_cpu_gdt_table(x) ((struct desc_struct *)cpu_gdt_descr[x].address)

static inline void load_gdt(const struct desc_ptr *ptr)
{
@@ -141,15 +141,15 @@ static inline void set_tss_desc(unsigned
* -1? seg base+limit should be pointing to the address of the
* last valid byte
*/
- set_tssldt_descriptor(&cpu_gdt(cpu)[GDT_ENTRY_TSS],
+ set_tssldt_descriptor(&get_cpu_gdt_table(cpu)[GDT_ENTRY_TSS],
(unsigned long)addr, DESC_TSS,
IO_BITMAP_OFFSET + IO_BITMAP_BYTES + sizeof(unsigned long) - 1);
}

static inline void set_ldt_desc(unsigned cpu, void *addr, int size)
{
- set_tssldt_descriptor(&cpu_gdt(cpu)[GDT_ENTRY_LDT], (unsigned long)addr,
- DESC_LDT, size * 8 - 1);
+ set_tssldt_descriptor(&get_cpu_gdt_table(cpu)[GDT_ENTRY_LDT],
+ (unsigned long)addr, DESC_LDT, size * 8 - 1);
}

#define LDT_entry_a(info) \
@@ -183,7 +183,7 @@ static inline void set_ldt_desc(unsigned
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);
+ u64 *gdt = (u64 *)(get_cpu_gdt_table(cpu) + GDT_ENTRY_TLS_MIN);

for (i = 0; i < GDT_ENTRY_TLS_ENTRIES; i++)
gdt[i] = t->tls_array[i];

2007-12-13 16:44:27

by Glauber Costa

[permalink] [raw]
Subject: [PATCH 01/19] unify desc_struct

This patch aims to make the access of struct desc_struct variables
equal across architectures. In this patch, I unify the i386 and x86_64
versions under an anonymous union, keeping the way they are accessed
untouched (a and b for 32-bit code, individual bit-fields for 64-bit).

This solution is not beautiful, but will allow us to integrate common
code that differed by the way descriptors were used. This is to be viewed
incrementally. There's simply too much code to be fixed at once.

In the future, goal is to set up in a single way of acessing
the desc_struct fields.

Signed-off-by: Glauber de Oliveira Costa <[email protected]>
---
arch/x86/kernel/apm_32.c | 2 +-
arch/x86/kernel/cpu/common.c | 28 ++++++++++++++--------------
arch/x86/kernel/process_64.c | 2 +-
arch/x86/kernel/traps_32.c | 2 +-
include/asm-x86/desc_defs.h | 25 +++++++++++++++++--------
include/asm-x86/lguest.h | 4 ++--
include/asm-x86/processor_32.h | 5 +----
7 files changed, 37 insertions(+), 31 deletions(-)

Index: linux-2.6-x86/arch/x86/kernel/apm_32.c
===================================================================
--- linux-2.6-x86.orig/arch/x86/kernel/apm_32.c
+++ linux-2.6-x86/arch/x86/kernel/apm_32.c
@@ -405,7 +405,7 @@ static DECLARE_WAIT_QUEUE_HEAD(apm_waitq
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 = { { { 0, 0x00409200 } } };

static const char driver_version[] = "1.16ac"; /* no spaces */

Index: linux-2.6-x86/arch/x86/kernel/cpu/common.c
===================================================================
--- linux-2.6-x86.orig/arch/x86/kernel/cpu/common.c
+++ linux-2.6-x86/arch/x86/kernel/cpu/common.c
@@ -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] = { { { 0x0000ffff, 0x00cf9a00 } } },
+ [GDT_ENTRY_KERNEL_DS] = { { { 0x0000ffff, 0x00cf9200 } } },
+ [GDT_ENTRY_DEFAULT_USER_CS] = { { { 0x0000ffff, 0x00cffa00 } } },
+ [GDT_ENTRY_DEFAULT_USER_DS] = { { { 0x0000ffff, 0x00cff200 } } },
/*
* 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] = { { { 0x0000ffff, 0x00409a00 } } },
+ /* 16-bit code */
+ [GDT_ENTRY_PNPBIOS_CS16] = { { { 0x0000ffff, 0x00009a00 } } },
+ /* 16-bit data */
+ [GDT_ENTRY_PNPBIOS_DS] = { { { 0x0000ffff, 0x00009200 } } },
+ /* 16-bit data */
+ [GDT_ENTRY_PNPBIOS_TS1] = { { { 0x00000000, 0x00009200 } } },
+ /* 16-bit data */
+ [GDT_ENTRY_PNPBIOS_TS2] = { { { 0x00000000, 0x00009200 } } },
/*
* 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] = { { { 0x0000ffff, 0x00409a00 } } },
/* 16-bit code */
- [GDT_ENTRY_APMBIOS_BASE+1] = { 0x0000ffff, 0x00009a00 },
- [GDT_ENTRY_APMBIOS_BASE+2] = { 0x0000ffff, 0x00409200 }, /* data */
+ [GDT_ENTRY_APMBIOS_BASE+1] = { { { 0x0000ffff, 0x00009a00 } } },
+ /* data */
+ [GDT_ENTRY_APMBIOS_BASE+2] = { { { 0x0000ffff, 0x00409200 } } },

- [GDT_ENTRY_ESPFIX_SS] = { 0x00000000, 0x00c09200 },
- [GDT_ENTRY_PERCPU] = { 0x00000000, 0x00000000 },
+ [GDT_ENTRY_ESPFIX_SS] = { { { 0x00000000, 0x00c09200 } } },
+ [GDT_ENTRY_PERCPU] = { { { 0x00000000, 0x00000000 } } },
} };
EXPORT_PER_CPU_SYMBOL_GPL(gdt_page);

Index: linux-2.6-x86/arch/x86/kernel/process_64.c
===================================================================
--- linux-2.6-x86.orig/arch/x86/kernel/process_64.c
+++ linux-2.6-x86/arch/x86/kernel/process_64.c
@@ -444,7 +444,7 @@ static inline void set_32bit_tls(struct
.limit_in_pages = 1,
.useable = 1,
};
- struct n_desc_struct *desc = (void *)t->thread.tls_array;
+ struct desc_struct *desc = (void *)t->thread.tls_array;
desc += tls;
desc->a = LDT_entry_a(&ud);
desc->b = LDT_entry_b(&ud);
Index: linux-2.6-x86/arch/x86/kernel/traps_32.c
===================================================================
--- linux-2.6-x86.orig/arch/x86/kernel/traps_32.c
+++ linux-2.6-x86/arch/x86/kernel/traps_32.c
@@ -76,7 +76,8 @@ 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"))) = { { { { 0, 0 } } }, };

asmlinkage void divide_error(void);
asmlinkage void debug(void);
Index: linux-2.6-x86/include/asm-x86/desc_defs.h
===================================================================
--- linux-2.6-x86.orig/include/asm-x86/desc_defs.h
+++ linux-2.6-x86/include/asm-x86/desc_defs.h
@@ -11,17 +11,26 @@

#include <linux/types.h>

+/*
+ * FIXME: Acessing the desc_struct through its fields is more elegant,
+ * and should be the one valid thing to do. However, a lot of open code
+ * still touches the a and b acessors, and doing this allow us to do it
+ * incrementally. We keep the signature as a struct, rather than an union,
+ * so we can get rid of it transparently in the future -- glommer
+ */
// 8 byte segment descriptor
struct desc_struct {
- 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));
+ union {
+ struct { unsigned int a, b; };
+ struct {
+ 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;
+ };

-struct n_desc_struct {
- unsigned int a,b;
-};
+ };
+} __attribute__((packed));

enum {
GATE_INTERRUPT = 0xE,
Index: linux-2.6-x86/include/asm-x86/lguest.h
===================================================================
--- linux-2.6-x86.orig/include/asm-x86/lguest.h
+++ linux-2.6-x86/include/asm-x86/lguest.h
@@ -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 desc_struct){ { {0x0000ffff, 0x00cf9b00} } })
+#define FULL_SEGMENT ((struct desc_struct){ { {0x0000ffff, 0x00cf9300} } })

#endif /* __ASSEMBLY__ */

Index: linux-2.6-x86/include/asm-x86/processor_32.h
===================================================================
--- linux-2.6-x86.orig/include/asm-x86/processor_32.h
+++ linux-2.6-x86/include/asm-x86/processor_32.h
@@ -20,14 +20,11 @@
#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 int desc_empty(const void *ptr)
{
const u32 *desc = ptr;

2007-12-13 16:44:41

by Glauber Costa

[permalink] [raw]
Subject: [PATCH 15/19] use the same data type for tls_array.

This patch changes the type of tls_array in x86_64 to
a desc_struct. Now, both i386 and x86_64 tls_array have
the same type, and code accessing it can be shared.

Signed-off-by: Glauber de Oliveira Costa <[email protected]>
---
include/asm-x86/desc_64.h | 2 +-
include/asm-x86/processor_64.h | 3 ++-
2 files changed, 3 insertions(+), 2 deletions(-)

diff --git a/include/asm-x86/desc_64.h b/include/asm-x86/desc_64.h
index 2dc19e2..7fd9876 100644
--- a/include/asm-x86/desc_64.h
+++ b/include/asm-x86/desc_64.h
@@ -150,7 +150,7 @@ static inline void set_ldt(void *addr, int entries)
static inline void load_TLS(struct thread_struct *t, unsigned int cpu)
{
unsigned int i;
- u64 *gdt = (u64 *)(get_cpu_gdt_table(cpu) + GDT_ENTRY_TLS_MIN);
+ struct desc_struct *gdt = (get_cpu_gdt_table(cpu) + GDT_ENTRY_TLS_MIN);

for (i = 0; i < GDT_ENTRY_TLS_ENTRIES; i++)
gdt[i] = t->tls_array[i];
diff --git a/include/asm-x86/processor_64.h b/include/asm-x86/processor_64.h
index 8efdf99..51f1970 100644
--- a/include/asm-x86/processor_64.h
+++ b/include/asm-x86/processor_64.h
@@ -19,6 +19,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
@@ -244,7 +245,7 @@ struct thread_struct {
* goes into MSR_IA32_DS_AREA */
unsigned long ds_area_msr;
/* 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 { \
--
1.5.0.6

2007-12-13 16:45:00

by Glauber Costa

[permalink] [raw]
Subject: [PATCH 14/19] unify non-paravirt parts of desc.h

This patch unifies the non-paravirt part of desc_{32,64}.h into
desc.h. Most of it, is simply common code, that is moved to
the shared header. The only exception is the set_ldt_desc in desc_64.h,
which is changed - included its name - to accomodate for the way
the ldt is set up in i386.

Also, constant definitions used in desc_32.h are moved to desc_defs.h

Signed-off-by: Glauber de Oliveira Costa <[email protected]>
---
include/asm-x86/desc.h | 87 ++++++++++++++++++++++++++++++++++++++
include/asm-x86/desc_32.h | 66 ----------------------------
include/asm-x86/desc_64.h | 64 ++++-----------------------
include/asm-x86/mmu_context_64.h | 4 +-
4 files changed, 99 insertions(+), 122 deletions(-)

Index: linux-2.6-x86/include/asm-x86/desc.h
===================================================================
--- linux-2.6-x86.orig/include/asm-x86/desc.h
+++ linux-2.6-x86/include/asm-x86/desc.h
@@ -4,6 +4,7 @@
#ifndef __ASSEMBLY__
#include <asm/desc_defs.h>
#include <asm/ldt.h>
+#include <asm/mmu.h>

static inline void fill_ldt(struct desc_struct *desc, struct user_desc *info)
{
@@ -23,7 +24,8 @@ static inline void fill_ldt(struct desc_
desc->base2 = (info->base_addr & 0xff000000) >> 24;
}

-#endif
+extern struct desc_ptr idt_descr;
+extern gate_desc idt_table[];

#ifdef CONFIG_X86_32
# include "desc_32.h"
@@ -31,4 +33,65 @@ static inline void fill_ldt(struct desc_
# include "desc_64.h"
#endif

+#define _LDT_empty(info) (\
+ (info)->base_addr == 0 && \
+ (info)->limit == 0 && \
+ (info)->contents == 0 && \
+ (info)->read_exec_only == 1 && \
+ (info)->seg_32bit == 0 && \
+ (info)->limit_in_pages == 0 && \
+ (info)->seg_not_present == 1 && \
+ (info)->useable == 0)
+
+#ifdef CONFIG_X86_64
+#define LDT_empty(info) (_LDT_empty(info) && ((info)->lm == 0))
+#else
+#define LDT_empty(info) (_LDT_empty(info))
+#endif
+
+static inline void clear_LDT(void)
+{
+ set_ldt(NULL, 0);
+}
+
+/*
+ * load one particular LDT into the current CPU
+ */
+static inline void load_LDT_nolock(mm_context_t *pc)
+{
+ set_ldt(pc->ldt, pc->size);
+}
+
+static inline void load_LDT(mm_context_t *pc)
+{
+ preempt_disable();
+ load_LDT_nolock(pc);
+ preempt_enable();
+}
+
+#else
+/*
+ * GET_DESC_BASE reads the descriptor base of the specified segment.
+ *
+ * Args:
+ * idx - descriptor index
+ * gdt - GDT pointer
+ * base - 32bit register to which the base will be written
+ * lo_w - lo word of the "base" register
+ * lo_b - lo byte of the "base" register
+ * hi_b - hi byte of the low word of the "base" register
+ *
+ * Example:
+ * GET_DESC_BASE(GDT_ENTRY_ESPFIX_SS, %ebx, %eax, %ax, %al, %ah)
+ * Will read the base address of GDT_ENTRY_ESPFIX_SS and put it into %eax.
+ */
+#define GET_DESC_BASE(idx, gdt, base, lo_w, lo_b, hi_b) \
+ movb idx*8+4(gdt), lo_b; \
+ movb idx*8+7(gdt), hi_b; \
+ shll $16, base; \
+ movw idx*8+2(gdt), lo_w;
+
+
+#endif /* __ASSEMBLY__ */
+
#endif
Index: linux-2.6-x86/include/asm-x86/desc_32.h
===================================================================
--- linux-2.6-x86.orig/include/asm-x86/desc_32.h
+++ linux-2.6-x86/include/asm-x86/desc_32.h
@@ -11,8 +11,6 @@
#include <linux/smp.h>
#include <linux/percpu.h>

-#include <asm/mmu.h>
-
struct gdt_page
{
struct desc_struct gdt[GDT_ENTRIES];
@@ -24,8 +22,6 @@ static inline struct desc_struct *get_cp
return per_cpu(gdt_page, cpu).gdt;
}

-extern struct desc_ptr idt_descr;
-extern gate_desc idt_table[];
extern void set_intr_gate(unsigned int irq, void * addr);

static inline void pack_descriptor(struct desc_struct *desc,
@@ -172,36 +168,6 @@ static inline void __set_tss_desc(unsign

#define set_tss_desc(cpu,addr) __set_tss_desc(cpu, GDT_ENTRY_TSS, addr)

-#define LDT_empty(info) (\
- (info)->base_addr == 0 && \
- (info)->limit == 0 && \
- (info)->contents == 0 && \
- (info)->read_exec_only == 1 && \
- (info)->seg_32bit == 0 && \
- (info)->limit_in_pages == 0 && \
- (info)->seg_not_present == 1 && \
- (info)->useable == 0 )
-
-static inline void clear_LDT(void)
-{
- set_ldt(NULL, 0);
-}
-
-/*
- * load one particular LDT into the current CPU
- */
-static inline void load_LDT_nolock(mm_context_t *pc)
-{
- set_ldt(pc->ldt, pc->size);
-}
-
-static inline void load_LDT(mm_context_t *pc)
-{
- preempt_disable();
- load_LDT_nolock(pc);
- preempt_enable();
-}
-
static inline unsigned long get_desc_base(unsigned long *desc)
{
unsigned long base;
@@ -210,30 +176,6 @@ static inline unsigned long get_desc_bas
(desc[1] & 0xff000000);
return base;
}
-
-#else /* __ASSEMBLY__ */
-
-/*
- * GET_DESC_BASE reads the descriptor base of the specified segment.
- *
- * Args:
- * idx - descriptor index
- * gdt - GDT pointer
- * base - 32bit register to which the base will be written
- * lo_w - lo word of the "base" register
- * lo_b - lo byte of the "base" register
- * hi_b - hi byte of the low word of the "base" register
- *
- * Example:
- * GET_DESC_BASE(GDT_ENTRY_ESPFIX_SS, %ebx, %eax, %ax, %al, %ah)
- * Will read the base address of GDT_ENTRY_ESPFIX_SS and put it into %eax.
- */
-#define GET_DESC_BASE(idx, gdt, base, lo_w, lo_b, hi_b) \
- movb idx*8+4(gdt), lo_b; \
- movb idx*8+7(gdt), hi_b; \
- shll $16, base; \
- movw idx*8+2(gdt), lo_w;
-
#endif /* !__ASSEMBLY__ */

#endif
Index: linux-2.6-x86/include/asm-x86/desc_64.h
===================================================================
--- linux-2.6-x86.orig/include/asm-x86/desc_64.h
+++ linux-2.6-x86/include/asm-x86/desc_64.h
@@ -9,16 +9,13 @@

#include <linux/string.h>
#include <linux/smp.h>
-#include <asm/desc_defs.h>

#include <asm/segment.h>
-#include <asm/mmu.h>

extern struct desc_struct cpu_gdt_table[GDT_ENTRIES];

#define load_TR_desc() asm volatile("ltr %w0"::"r" (GDT_ENTRY_TSS*8))
#define load_LDT_desc() asm volatile("lldt %w0"::"r" (GDT_ENTRY_LDT*8))
-#define clear_LDT() asm volatile("lldt %w0"::"r" (0))

static inline unsigned long __store_tr(void)
{
@@ -30,7 +27,6 @@ static inline unsigned long __store_tr(v

#define store_tr(tr) (tr) = __store_tr()

-extern gate_desc idt_table[];
extern struct desc_ptr cpu_gdt_descr[];

static inline void write_ldt_entry(struct desc_struct *ldt,
@@ -138,23 +134,19 @@ static inline void set_tss_desc(unsigned
IO_BITMAP_OFFSET + IO_BITMAP_BYTES + sizeof(unsigned long) - 1);
}

-static inline void set_ldt_desc(unsigned cpu, void *addr, int size)
+static inline void set_ldt(void *addr, int entries)
{
- set_tssldt_descriptor(&get_cpu_gdt_table(cpu)[GDT_ENTRY_LDT],
- (unsigned long)addr, DESC_LDT, size * 8 - 1);
+ if (likely(entries == 0))
+ __asm__ __volatile__("lldt %w0"::"q" (0));
+ else {
+ unsigned cpu = smp_processor_id();
+
+ set_tssldt_descriptor(&get_cpu_gdt_table(cpu)[GDT_ENTRY_LDT],
+ (unsigned long)addr, DESC_LDT, entries * 8 - 1);
+ __asm__ __volatile__("lldt %w0"::"q" (GDT_ENTRY_LDT*8));
+ }
}

-#define LDT_empty(info) (\
- (info)->base_addr == 0 && \
- (info)->limit == 0 && \
- (info)->contents == 0 && \
- (info)->read_exec_only == 1 && \
- (info)->seg_32bit == 0 && \
- (info)->limit_in_pages == 0 && \
- (info)->seg_not_present == 1 && \
- (info)->useable == 0 && \
- (info)->lm == 0)
-
static inline void load_TLS(struct thread_struct *t, unsigned int cpu)
{
unsigned int i;
@@ -164,32 +156,6 @@ static inline void load_TLS(struct threa
gdt[i] = t->tls_array[i];
}

-/*
- * load one particular LDT into the current CPU
- */
-static inline void load_LDT_nolock(mm_context_t *pc, int cpu)
-{
- int count = pc->size;
-
- if (likely(!count)) {
- clear_LDT();
- return;
- }
-
- set_ldt_desc(cpu, pc->ldt, count);
- load_LDT_desc();
-}
-
-static inline void load_LDT(mm_context_t *pc)
-{
- int cpu = get_cpu();
-
- load_LDT_nolock(pc, cpu);
- put_cpu();
-}
-
-extern struct desc_ptr idt_descr;
-
static inline unsigned long get_desc_base(const void *ptr)
{
const u32 *desc = ptr;
@@ -199,7 +165,6 @@ static inline unsigned long get_desc_bas
(desc[1] & 0xff000000);
return base;
}
-
#endif /* !__ASSEMBLY__ */

#endif
Index: linux-2.6-x86/include/asm-x86/mmu_context_64.h
===================================================================
--- linux-2.6-x86.orig/include/asm-x86/mmu_context_64.h
+++ linux-2.6-x86/include/asm-x86/mmu_context_64.h
@@ -43,7 +43,7 @@ static inline void switch_mm(struct mm_s
load_cr3(next->pgd);

if (unlikely(next->context.ldt != prev->context.ldt))
- load_LDT_nolock(&next->context, cpu);
+ load_LDT_nolock(&next->context);
}
#ifdef CONFIG_SMP
else {
@@ -56,7 +56,7 @@ static inline void switch_mm(struct mm_s
* to make sure to use no freed page tables.
*/
load_cr3(next->pgd);
- load_LDT_nolock(&next->context, cpu);
+ load_LDT_nolock(&next->context);
}
}
#endif

2007-12-13 16:45:30

by Glauber Costa

[permalink] [raw]
Subject: [PATCH 16/19] modify get_desc_base

This patch makes get_desc_base() receive a struct desc_struct,
and then uses its internal fields to compute the base address.
This is done at both i386 and x86_64, and then it is moved
to common header

Signed-off-by: Glauber de Oliveira Costa <[email protected]>
---
arch/x86/kernel/tls.c | 2 +-
arch/x86/mm/fault_32.c | 2 +-
include/asm-x86/desc.h | 8 ++------
3 files changed, 4 insertions(+), 8 deletions(-)

Index: linux-2.6-x86/arch/x86/kernel/tls.c
===================================================================
--- linux-2.6-x86.orig/arch/x86/kernel/tls.c
+++ linux-2.6-x86/arch/x86/kernel/tls.c
@@ -112,7 +112,7 @@ int do_get_thread_area(struct task_struc

memset(&info, 0, sizeof(struct user_desc));
info.entry_number = idx;
- info.base_addr = get_desc_base((void *)desc);
+ info.base_addr = get_desc_base((struct desc_struct *)desc);
info.limit = GET_LIMIT(desc);
info.seg_32bit = GET_32BIT(desc);
info.contents = GET_CONTENTS(desc);
Index: linux-2.6-x86/arch/x86/mm/fault_32.c
===================================================================
--- linux-2.6-x86.orig/arch/x86/mm/fault_32.c
+++ linux-2.6-x86/arch/x86/mm/fault_32.c
@@ -115,7 +115,7 @@ static inline unsigned long get_segment_
}

/* Decode the code segment base from the descriptor */
- base = get_desc_base((unsigned long *)desc);
+ base = get_desc_base((struct desc_struct *)desc);

if (seg & (1<<2)) {
mutex_unlock(&current->mm->context.lock);
Index: linux-2.6-x86/include/asm-x86/desc.h
===================================================================
--- linux-2.6-x86.orig/include/asm-x86/desc.h
+++ linux-2.6-x86/include/asm-x86/desc.h
@@ -69,6 +69,11 @@ static inline void load_LDT(mm_context_t
preempt_enable();
}

+static inline unsigned long get_desc_base(struct desc_struct *desc)
+{
+ return desc->base0 | ((desc->base1) << 16) | ((desc->base2) << 24);
+}
+
#else
/*
* GET_DESC_BASE reads the descriptor base of the specified segment.
Index: linux-2.6-x86/include/asm-x86/desc_32.h
===================================================================
--- linux-2.6-x86.orig/include/asm-x86/desc_32.h
+++ linux-2.6-x86/include/asm-x86/desc_32.h
@@ -168,14 +168,6 @@ static inline void __set_tss_desc(unsign

#define set_tss_desc(cpu,addr) __set_tss_desc(cpu, GDT_ENTRY_TSS, addr)

-static inline unsigned long get_desc_base(unsigned long *desc)
-{
- unsigned long base;
- base = ((desc[0] >> 16) & 0x0000ffff) |
- ((desc[1] << 16) & 0x00ff0000) |
- (desc[1] & 0xff000000);
- return base;
-}
#endif /* !__ASSEMBLY__ */

#endif
Index: linux-2.6-x86/include/asm-x86/desc_64.h
===================================================================
--- linux-2.6-x86.orig/include/asm-x86/desc_64.h
+++ linux-2.6-x86/include/asm-x86/desc_64.h
@@ -156,15 +156,6 @@ static inline void load_TLS(struct threa
gdt[i] = t->tls_array[i];
}

-static inline unsigned long get_desc_base(const void *ptr)
-{
- const u32 *desc = ptr;
- unsigned long base;
- base = ((desc[0] >> 16) & 0x0000ffff) |
- ((desc[1] << 16) & 0x00ff0000) |
- (desc[1] & 0xff000000);
- return base;
-}
#endif /* !__ASSEMBLY__ */

#endif

2007-12-13 16:45:51

by Glauber Costa

[permalink] [raw]
Subject: [PATCH 13/19] move constants to desc_defs.h

this patch moves constant definitions regarding descriptor types
from desc_32.h to desc_defs.h. The change from defines to enum
to comply with previous versions in desc_defs.h

Signed-off-by: Glauber de Oliveira Costa <[email protected]>
---
include/asm-x86/desc_32.h | 8 --------
include/asm-x86/desc_defs.h | 5 +++++
2 files changed, 5 insertions(+), 8 deletions(-)

diff --git a/include/asm-x86/desc_32.h b/include/asm-x86/desc_32.h
index 92a72b0..14238df 100644
--- a/include/asm-x86/desc_32.h
+++ b/include/asm-x86/desc_32.h
@@ -44,14 +44,6 @@ static inline void pack_gate(gate_desc *gate,
gate->b = (base & 0xffff0000) | ((type & 0xff) << 8) | (flags & 0xff);
}

-#define DESCTYPE_LDT 0x82 /* present, system, DPL-0, LDT */
-#define DESCTYPE_TSS 0x89 /* present, system, DPL-0, 32-bit TSS */
-#define DESCTYPE_TASK 0x85 /* present, system, DPL-0, task gate */
-#define DESCTYPE_INT 0x8e /* present, system, DPL-0, interrupt gate */
-#define DESCTYPE_TRAP 0x8f /* present, system, DPL-0, trap gate */
-#define DESCTYPE_DPL3 0x60 /* DPL-3 */
-#define DESCTYPE_S 0x10 /* !system */
-
#ifdef CONFIG_PARAVIRT
#include <asm/paravirt.h>
#else
diff --git a/include/asm-x86/desc_defs.h b/include/asm-x86/desc_defs.h
index c4d7874..5ca416d 100644
--- a/include/asm-x86/desc_defs.h
+++ b/include/asm-x86/desc_defs.h
@@ -55,6 +55,11 @@ struct gate_struct64 {
enum {
DESC_TSS = 0x9,
DESC_LDT = 0x2,
+ DESCTYPE_TASK = 0x85, /* present, system, DPL-0, task gate */
+ DESCTYPE_INT = 0x8e, /* present, system, DPL-0, interrupt gate */
+ DESCTYPE_TRAP = 0x8f, /* present, system, DPL-0, trap gate */
+ DESCTYPE_DPL3 = 0x60, /* DPL-3 */
+ DESCTYPE_S = 0x10, /* !system */
};

// LDT or TSS descriptor in the GDT. 16 bytes.
--
1.5.0.6

2007-12-13 16:46:25

by Glauber Costa

[permalink] [raw]
Subject: [PATCH 18/19] move _set_gate and its users to a common location

This patch moves _set_gate and its users to desc.h. We can now
use common code for x86_64 and i386.

Signed-off-by: Glauber de Oliveira Costa <[email protected]>
---
arch/x86/kernel/traps_32.c | 34 ----------------
include/asm-x86/desc.h | 88 +++++++++++++++++++++++++++++++++++++++++++
include/asm-x86/desc_32.h | 16 --------
include/asm-x86/desc_64.h | 45 ----------------------
include/asm-x86/desc_defs.h | 5 +--
5 files changed, 89 insertions(+), 99 deletions(-)

Index: linux-2.6-x86/arch/x86/kernel/traps_32.c
===================================================================
--- linux-2.6-x86.orig/arch/x86/kernel/traps_32.c
+++ linux-2.6-x86/arch/x86/kernel/traps_32.c
@@ -1102,40 +1102,6 @@ asmlinkage void math_emulate(long arg)

#endif /* CONFIG_MATH_EMULATION */

-/*
- * This needs to use 'idt_table' rather than 'idt', and
- * thus use the _nonmapped_ version of the IDT, as the
- * Pentium F0 0F bugfix can have resulted in the mapped
- * IDT being write-protected.
- */
-void set_intr_gate(unsigned int n, void *addr)
-{
- _set_gate(n, DESCTYPE_INT, addr, __KERNEL_CS);
-}
-
-/*
- * This routine sets up an interrupt gate at directory privilege level 3.
- */
-static inline void set_system_intr_gate(unsigned int n, void *addr)
-{
- _set_gate(n, DESCTYPE_INT | DESCTYPE_DPL3, addr, __KERNEL_CS);
-}
-
-static void __init set_trap_gate(unsigned int n, void *addr)
-{
- _set_gate(n, DESCTYPE_TRAP, addr, __KERNEL_CS);
-}
-
-static void __init set_system_gate(unsigned int n, void *addr)
-{
- _set_gate(n, DESCTYPE_TRAP | DESCTYPE_DPL3, addr, __KERNEL_CS);
-}
-
-static void __init set_task_gate(unsigned int n, unsigned int gdt_entry)
-{
- _set_gate(n, DESCTYPE_TASK, (void *)0, (gdt_entry<<3));
-}
-

void __init trap_init(void)
{
Index: linux-2.6-x86/include/asm-x86/desc.h
===================================================================
--- linux-2.6-x86.orig/include/asm-x86/desc.h
+++ linux-2.6-x86/include/asm-x86/desc.h
@@ -33,6 +33,22 @@ extern struct desc_struct cpu_gdt_table[
extern struct desc_ptr cpu_gdt_descr[];
/* the cpu gdt accessor */
#define get_cpu_gdt_table(x) ((struct desc_struct *)cpu_gdt_descr[x].address)
+
+static inline void pack_gate(gate_desc *gate, unsigned type, unsigned long func,
+ unsigned dpl, unsigned ist, unsigned seg)
+{
+ gate->offset_low = PTR_LOW(func);
+ gate->segment = __KERNEL_CS;
+ gate->ist = ist;
+ gate->p = 1;
+ gate->dpl = dpl;
+ gate->zero0 = 0;
+ gate->zero1 = 0;
+ gate->type = type;
+ gate->offset_middle = PTR_MIDDLE(func);
+ gate->offset_high = PTR_HIGH(func);
+}
+
#else
struct gdt_page {
struct desc_struct gdt[GDT_ENTRIES];
@@ -43,6 +59,16 @@ static inline struct desc_struct *get_cp
{
return per_cpu(gdt_page, cpu).gdt;
}
+
+static inline void pack_gate(gate_desc *gate, unsigned char type,
+ unsigned long base, unsigned dpl, unsigned flags, unsigned short seg)
+
+{
+ gate->a = (seg << 16) | (base & 0xffff);
+ gate->b = (base & 0xffff0000) |
+ (((0x80 | type | (dpl << 5)) & 0xff) << 8);
+}
+
#endif

#ifdef CONFIG_PARAVIRT
@@ -234,6 +260,68 @@ static inline unsigned long get_desc_bas
{
return desc->base0 | ((desc->base1) << 16) | ((desc->base2) << 24);
}
+static inline void _set_gate(int gate, unsigned type, void *addr,
+ unsigned dpl, unsigned ist, unsigned seg)
+{
+ gate_desc s;
+ pack_gate(&s, type, (unsigned long)addr, dpl, ist, seg);
+ /*
+ * does not need to be atomic because it is only done once at
+ * setup time
+ */
+ write_idt_entry(idt_table, gate, &s);
+}
+
+/*
+ * This needs to use 'idt_table' rather than 'idt', and
+ * thus use the _nonmapped_ version of the IDT, as the
+ * Pentium F0 0F bugfix can have resulted in the mapped
+ * IDT being write-protected.
+ */
+static inline void set_intr_gate(unsigned int n, void *addr)
+{
+ BUG_ON((unsigned)n > 0xFF);
+ _set_gate(n, GATE_INTERRUPT, addr, 0, 0, __KERNEL_CS);
+}
+
+/*
+ * This routine sets up an interrupt gate at directory privilege level 3.
+ */
+static inline void set_system_intr_gate(unsigned int n, void *addr)
+{
+ BUG_ON((unsigned)n > 0xFF);
+ _set_gate(n, GATE_INTERRUPT, addr, 0x3, 0, __KERNEL_CS);
+}
+
+static inline void set_trap_gate(unsigned int n, void *addr)
+{
+ BUG_ON((unsigned)n > 0xFF);
+ _set_gate(n, GATE_TRAP, addr, 0, 0, __KERNEL_CS);
+}
+
+static inline void set_system_gate(unsigned int n, void *addr)
+{
+ BUG_ON((unsigned)n > 0xFF);
+ _set_gate(n, GATE_TRAP, addr, 0x3, 0, __KERNEL_CS);
+}
+
+static inline void set_task_gate(unsigned int n, unsigned int gdt_entry)
+{
+ BUG_ON((unsigned)n > 0xFF);
+ _set_gate(n, GATE_TASK, (void *)0, 0, 0, (gdt_entry<<3));
+}
+
+static inline void set_intr_gate_ist(int n, void *addr, unsigned ist)
+{
+ BUG_ON((unsigned)n > 0xFF);
+ _set_gate(n, GATE_INTERRUPT, addr, 0, ist, __KERNEL_CS);
+}
+
+static inline void set_system_gate_ist(int n, void *addr, unsigned ist)
+{
+ BUG_ON((unsigned)n > 0xFF);
+ _set_gate(n, GATE_INTERRUPT, addr, 0x3, ist, __KERNEL_CS);
+}

#else
/*
Index: linux-2.6-x86/include/asm-x86/desc_32.h
===================================================================
--- linux-2.6-x86.orig/include/asm-x86/desc_32.h
+++ linux-2.6-x86/include/asm-x86/desc_32.h
@@ -10,22 +10,6 @@
#include <linux/preempt.h>
#include <linux/percpu.h>

-extern void set_intr_gate(unsigned int irq, void * addr);
-
-static inline void pack_gate(gate_desc *gate,
- unsigned long base, unsigned short seg, unsigned char type, unsigned char flags)
-{
- gate->a = (seg << 16) | (base & 0xffff);
- gate->b = (base & 0xffff0000) | ((type & 0xff) << 8) | (flags & 0xff);
-}
-
-static inline void _set_gate(int gate, unsigned int type, void *addr, unsigned short seg)
-{
- gate_desc g;
- pack_gate(&g, (unsigned long)addr, seg, type, 0);
- write_idt_entry(idt_table, gate, &g);
-}
-
static inline void __set_tss_desc(unsigned int cpu, unsigned int entry, const void *addr)
{
tss_desc tss;
Index: linux-2.6-x86/include/asm-x86/desc_64.h
===================================================================
--- linux-2.6-x86.orig/include/asm-x86/desc_64.h
+++ linux-2.6-x86/include/asm-x86/desc_64.h
@@ -11,51 +11,6 @@

#include <asm/segment.h>

-static inline void _set_gate(int gate, unsigned type, unsigned long func,
- unsigned dpl, unsigned ist)
-{
- gate_desc s;
-
- s.offset_low = PTR_LOW(func);
- s.segment = __KERNEL_CS;
- s.ist = ist;
- s.p = 1;
- s.dpl = dpl;
- s.zero0 = 0;
- s.zero1 = 0;
- s.type = type;
- s.offset_middle = PTR_MIDDLE(func);
- s.offset_high = PTR_HIGH(func);
- /*
- * does not need to be atomic because it is only done once at
- * setup time
- */
- write_idt_entry(idt_table, gate, &s);
-}
-
-static inline void set_intr_gate(int nr, void *func)
-{
- BUG_ON((unsigned)nr > 0xFF);
- _set_gate(nr, GATE_INTERRUPT, (unsigned long) func, 0, 0);
-}
-
-static inline void set_intr_gate_ist(int nr, void *func, unsigned ist)
-{
- BUG_ON((unsigned)nr > 0xFF);
- _set_gate(nr, GATE_INTERRUPT, (unsigned long) func, 0, ist);
-}
-
-static inline void set_system_gate(int nr, void *func)
-{
- BUG_ON((unsigned)nr > 0xFF);
- _set_gate(nr, GATE_INTERRUPT, (unsigned long) func, 3, 0);
-}
-
-static inline void set_system_gate_ist(int nr, void *func, unsigned ist)
-{
- _set_gate(nr, GATE_INTERRUPT, (unsigned long) func, 3, ist);
-}
-
static inline void set_tss_desc(unsigned cpu, void *addr)
{
struct desc_struct *d = get_cpu_gdt_table(cpu);
Index: linux-2.6-x86/include/asm-x86/desc_defs.h
===================================================================
--- linux-2.6-x86.orig/include/asm-x86/desc_defs.h
+++ linux-2.6-x86/include/asm-x86/desc_defs.h
@@ -36,6 +36,7 @@ enum {
GATE_INTERRUPT = 0xE,
GATE_TRAP = 0xF,
GATE_CALL = 0xC,
+ GATE_TASK = 0x5,
};

// 16byte gate
@@ -55,10 +56,6 @@ struct gate_struct64 {
enum {
DESC_TSS = 0x9,
DESC_LDT = 0x2,
- DESCTYPE_TASK = 0x85, /* present, system, DPL-0, task gate */
- DESCTYPE_INT = 0x8e, /* present, system, DPL-0, interrupt gate */
- DESCTYPE_TRAP = 0x8f, /* present, system, DPL-0, trap gate */
- DESCTYPE_DPL3 = 0x60, /* DPL-3 */
DESCTYPE_S = 0x10, /* !system */
};

2007-12-13 16:46:43

by Glauber Costa

[permalink] [raw]
Subject: [PATCH 17/19] unify paravirt pieces of descriptor handling

With the types used to access descriptors in x86_64 and i386
now being the same, the code that effectively handles them can
now be easily shared. This patch moves the paravirt part of
desc_32.h into desc.h, and then, we get paravirt support in x86_64
for free.

Signed-off-by: Glauber de Oliveira Costa <[email protected]>
---
include/asm-x86/desc.h | 169 +++++++++++++++++++++++++++++++++++++++++++
include/asm-x86/desc_32.h | 130 ---------------------------------
include/asm-x86/desc_64.h | 104 +++------------------------
include/asm-x86/desc_defs.h | 6 +-
4 files changed, 183 insertions(+), 226 deletions(-)

Index: linux-2.6-x86/include/asm-x86/desc_32.h
===================================================================
--- linux-2.6-x86.orig/include/asm-x86/desc_32.h
+++ linux-2.6-x86/include/asm-x86/desc_32.h
@@ -8,31 +8,10 @@
#ifndef __ASSEMBLY__

#include <linux/preempt.h>
-#include <linux/smp.h>
#include <linux/percpu.h>

-struct gdt_page
-{
- struct desc_struct gdt[GDT_ENTRIES];
-} __attribute__((aligned(PAGE_SIZE)));
-DECLARE_PER_CPU(struct gdt_page, gdt_page);
-
-static inline struct desc_struct *get_cpu_gdt_table(unsigned int cpu)
-{
- return per_cpu(gdt_page, cpu).gdt;
-}
-
extern void set_intr_gate(unsigned int irq, void * addr);

-static inline void pack_descriptor(struct desc_struct *desc,
- unsigned long base, unsigned long limit, unsigned char type, unsigned char flags)
-{
- desc->a = ((base & 0xffff) << 16) | (limit & 0xffff);
- desc->b = (base & 0xff000000) | ((base & 0xff0000) >> 16) |
- (limit & 0x000f0000) | ((type & 0xff) << 8) | ((flags & 0xf) << 20);
- desc->p = 1;
-}
-
static inline void pack_gate(gate_desc *gate,
unsigned long base, unsigned short seg, unsigned char type, unsigned char flags)
{
@@ -40,115 +19,6 @@ static inline void pack_gate(gate_desc *
gate->b = (base & 0xffff0000) | ((type & 0xff) << 8) | (flags & 0xff);
}

-#ifdef CONFIG_PARAVIRT
-#include <asm/paravirt.h>
-#else
-#define load_TR_desc() native_load_tr_desc()
-#define load_gdt(dtr) native_load_gdt(dtr)
-#define load_idt(dtr) native_load_idt(dtr)
-#define load_tr(tr) __asm__ __volatile("ltr %0"::"m" (tr))
-#define load_ldt(ldt) __asm__ __volatile("lldt %0"::"m" (ldt))
-
-#define store_gdt(dtr) native_store_gdt(dtr)
-#define store_idt(dtr) native_store_idt(dtr)
-#define store_tr(tr) (tr = native_store_tr())
-#define store_ldt(ldt) __asm__ ("sldt %0":"=m" (ldt))
-
-#define load_TLS(t, cpu) native_load_tls(t, cpu)
-#define set_ldt native_set_ldt
-
-#define write_ldt_entry(dt, entry, desc) \
- native_write_ldt_entry(dt, entry, desc)
-#define write_gdt_entry(dt, entry, desc, type) \
- native_write_gdt_entry(dt, entry, desc, type)
-#define write_idt_entry(dt, entry, g) native_write_idt_entry(dt, entry, g)
-#endif
-
-static inline void native_write_ldt_entry(struct desc_struct *ldt, int entry,
- const void *desc)
-{
- memcpy(&ldt[entry], desc, sizeof(struct desc_struct));
-}
-
-static inline void native_write_idt_entry(gate_desc *idt, int entry,
- const gate_desc *gate)
-{
- memcpy(&idt[entry], gate, sizeof(*gate));
-}
-
-static inline void native_write_gdt_entry(struct desc_struct *gdt, int entry,
- const void *desc, int type)
-{
- memcpy(&gdt[entry], desc, sizeof(struct desc_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;
-}
-
-
-static inline void native_set_ldt(const void *addr, unsigned int entries)
-{
- if (likely(entries == 0))
- __asm__ __volatile__("lldt %w0"::"q" (0));
- else {
- unsigned cpu = smp_processor_id();
- ldt_desc ldt;
-
- pack_descriptor(&ldt, (unsigned long)addr,
- entries * sizeof(struct desc_struct) - 1,
- DESC_LDT, 0);
- write_gdt_entry(get_cpu_gdt_table(cpu), GDT_ENTRY_LDT,
- &ldt, DESC_LDT);
- __asm__ __volatile__("lldt %w0"::"q" (GDT_ENTRY_LDT*8));
- }
-}
-
-
-static inline void native_load_tr_desc(void)
-{
- asm volatile("ltr %w0"::"q" (GDT_ENTRY_TSS*8));
-}
-
-static inline void native_load_gdt(const struct desc_ptr *dtr)
-{
- asm volatile("lgdt %0"::"m" (*dtr));
-}
-
-static inline void native_load_idt(const struct desc_ptr *dtr)
-{
- asm volatile("lidt %0"::"m" (*dtr));
-}
-
-static inline void native_store_gdt(struct desc_ptr *dtr)
-{
- asm ("sgdt %0":"=m" (*dtr));
-}
-
-static inline void native_store_idt(struct desc_ptr *dtr)
-{
- asm ("sidt %0":"=m" (*dtr));
-}
-
-static inline unsigned long native_store_tr(void)
-{
- unsigned long tr;
- asm ("str %0":"=r" (tr));
- return tr;
-}
-
-static inline void native_load_tls(struct thread_struct *t, unsigned int cpu)
-{
- unsigned int i;
- struct desc_struct *gdt = get_cpu_gdt_table(cpu);
-
- for (i = 0; i < GDT_ENTRY_TLS_ENTRIES; i++)
- gdt[GDT_ENTRY_TLS_MIN + i] = t->tls_array[i];
-}
-
static inline void _set_gate(int gate, unsigned int type, void *addr, unsigned short seg)
{
gate_desc g;
Index: linux-2.6-x86/include/asm-x86/desc_64.h
===================================================================
--- linux-2.6-x86.orig/include/asm-x86/desc_64.h
+++ linux-2.6-x86/include/asm-x86/desc_64.h
@@ -8,47 +8,10 @@
#ifndef __ASSEMBLY__

#include <linux/string.h>
-#include <linux/smp.h>

#include <asm/segment.h>

-extern struct desc_struct cpu_gdt_table[GDT_ENTRIES];
-
-#define load_TR_desc() asm volatile("ltr %w0"::"r" (GDT_ENTRY_TSS*8))
-#define load_LDT_desc() asm volatile("lldt %w0"::"r" (GDT_ENTRY_LDT*8))
-
-static inline unsigned long __store_tr(void)
-{
- unsigned long tr;
-
- asm volatile ("str %w0":"=r" (tr));
- return tr;
-}
-
-#define store_tr(tr) (tr) = __store_tr()
-
-extern struct desc_ptr cpu_gdt_descr[];
-
-static inline void write_ldt_entry(struct desc_struct *ldt,
- int entry, void *ptr)
-{
- memcpy(&ldt[entry], ptr, 8);
-}
-
-/* the cpu gdt accessor */
-#define get_cpu_gdt_table(x) ((struct desc_struct *)cpu_gdt_descr[x].address)
-
-static inline void load_gdt(const struct desc_ptr *ptr)
-{
- asm volatile("lgdt %w0"::"m" (*ptr));
-}
-
-static inline void store_gdt(struct desc_ptr *ptr)
-{
- asm("sgdt %w0":"=m" (*ptr));
-}
-
-static inline void _set_gate(void *adr, unsigned type, unsigned long func,
+static inline void _set_gate(int gate, unsigned type, unsigned long func,
unsigned dpl, unsigned ist)
{
gate_desc s;
@@ -67,61 +30,37 @@ static inline void _set_gate(void *adr,
* does not need to be atomic because it is only done once at
* setup time
*/
- memcpy(adr, &s, 16);
+ write_idt_entry(idt_table, gate, &s);
}

static inline void set_intr_gate(int nr, void *func)
{
BUG_ON((unsigned)nr > 0xFF);
- _set_gate(&idt_table[nr], GATE_INTERRUPT, (unsigned long) func, 0, 0);
+ _set_gate(nr, GATE_INTERRUPT, (unsigned long) func, 0, 0);
}

static inline void set_intr_gate_ist(int nr, void *func, unsigned ist)
{
BUG_ON((unsigned)nr > 0xFF);
- _set_gate(&idt_table[nr], GATE_INTERRUPT, (unsigned long) func, 0, ist);
+ _set_gate(nr, GATE_INTERRUPT, (unsigned long) func, 0, ist);
}

static inline void set_system_gate(int nr, void *func)
{
BUG_ON((unsigned)nr > 0xFF);
- _set_gate(&idt_table[nr], GATE_INTERRUPT, (unsigned long) func, 3, 0);
+ _set_gate(nr, GATE_INTERRUPT, (unsigned long) func, 3, 0);
}

static inline void set_system_gate_ist(int nr, void *func, unsigned ist)
{
- _set_gate(&idt_table[nr], GATE_INTERRUPT, (unsigned long) func, 3, ist);
-}
-
-static inline void load_idt(const struct desc_ptr *ptr)
-{
- asm volatile("lidt %w0"::"m" (*ptr));
-}
-
-static inline void store_idt(struct desc_ptr *dtr)
-{
- asm("sidt %w0":"=m" (*dtr));
-}
-
-static inline void set_tssldt_descriptor(void *ptr, unsigned long tss,
- unsigned type, unsigned size)
-{
- struct ldttss_desc64 d;
-
- memset(&d, 0, sizeof(d));
- d.limit0 = size & 0xFFFF;
- d.base0 = PTR_LOW(tss);
- d.base1 = PTR_MIDDLE(tss) & 0xFF;
- d.type = type;
- d.p = 1;
- d.limit1 = (size >> 16) & 0xF;
- d.base2 = (PTR_MIDDLE(tss) >> 8) & 0xFF;
- d.base3 = PTR_HIGH(tss);
- memcpy(ptr, &d, 16);
+ _set_gate(nr, GATE_INTERRUPT, (unsigned long) func, 3, ist);
}

static inline void set_tss_desc(unsigned cpu, void *addr)
{
+ struct desc_struct *d = get_cpu_gdt_table(cpu);
+ tss_desc tss;
+
/*
* sizeof(unsigned long) coming from an extra "long" at the end
* of the iobitmap. See tss_struct definition in processor.h
@@ -129,31 +68,10 @@ static inline void set_tss_desc(unsigned
* -1? seg base+limit should be pointing to the address of the
* last valid byte
*/
- set_tssldt_descriptor(&get_cpu_gdt_table(cpu)[GDT_ENTRY_TSS],
+ set_tssldt_descriptor(&tss,
(unsigned long)addr, DESC_TSS,
IO_BITMAP_OFFSET + IO_BITMAP_BYTES + sizeof(unsigned long) - 1);
-}
-
-static inline void set_ldt(void *addr, int entries)
-{
- if (likely(entries == 0))
- __asm__ __volatile__("lldt %w0"::"q" (0));
- else {
- unsigned cpu = smp_processor_id();
-
- set_tssldt_descriptor(&get_cpu_gdt_table(cpu)[GDT_ENTRY_LDT],
- (unsigned long)addr, DESC_LDT, entries * 8 - 1);
- __asm__ __volatile__("lldt %w0"::"q" (GDT_ENTRY_LDT*8));
- }
-}
-
-static inline void load_TLS(struct thread_struct *t, unsigned int cpu)
-{
- unsigned int i;
- struct desc_struct *gdt = (get_cpu_gdt_table(cpu) + GDT_ENTRY_TLS_MIN);
-
- for (i = 0; i < GDT_ENTRY_TLS_ENTRIES; i++)
- gdt[i] = t->tls_array[i];
+ write_gdt_entry(d, GDT_ENTRY_TSS, &tss, DESC_TSS);
}

#endif /* !__ASSEMBLY__ */
Index: linux-2.6-x86/include/asm-x86/desc_defs.h
===================================================================
--- linux-2.6-x86.orig/include/asm-x86/desc_defs.h
+++ linux-2.6-x86/include/asm-x86/desc_defs.h
@@ -48,9 +48,9 @@ struct gate_struct64 {
u32 zero1;
} __attribute__((packed));

-#define PTR_LOW(x) ((unsigned long)(x) & 0xFFFF)
-#define PTR_MIDDLE(x) (((unsigned long)(x) >> 16) & 0xFFFF)
-#define PTR_HIGH(x) ((unsigned long)(x) >> 32)
+#define PTR_LOW(x) ((unsigned long long)(x) & 0xFFFF)
+#define PTR_MIDDLE(x) (((unsigned long long)(x) >> 16) & 0xFFFF)
+#define PTR_HIGH(x) ((unsigned long long)(x) >> 32)

enum {
DESC_TSS = 0x9,
Index: linux-2.6-x86/include/asm-x86/desc.h
===================================================================
--- linux-2.6-x86.orig/include/asm-x86/desc.h
+++ linux-2.6-x86/include/asm-x86/desc.h
@@ -5,6 +5,7 @@
#include <asm/desc_defs.h>
#include <asm/ldt.h>
#include <asm/mmu.h>
+#include <linux/smp.h>

static inline void fill_ldt(struct desc_struct *desc, struct user_desc *info)
{
@@ -27,6 +28,166 @@ static inline void fill_ldt(struct desc_
extern struct desc_ptr idt_descr;
extern gate_desc idt_table[];

+#ifdef CONFIG_X86_64
+extern struct desc_struct cpu_gdt_table[GDT_ENTRIES];
+extern struct desc_ptr cpu_gdt_descr[];
+/* the cpu gdt accessor */
+#define get_cpu_gdt_table(x) ((struct desc_struct *)cpu_gdt_descr[x].address)
+#else
+struct gdt_page {
+ struct desc_struct gdt[GDT_ENTRIES];
+} __attribute__((aligned(PAGE_SIZE)));
+DECLARE_PER_CPU(struct gdt_page, gdt_page);
+
+static inline struct desc_struct *get_cpu_gdt_table(unsigned int cpu)
+{
+ return per_cpu(gdt_page, cpu).gdt;
+}
+#endif
+
+#ifdef CONFIG_PARAVIRT
+#include <asm/paravirt.h>
+#else
+#define load_TR_desc() native_load_tr_desc()
+#define load_gdt(dtr) native_load_gdt(dtr)
+#define load_idt(dtr) native_load_idt(dtr)
+#define load_tr(tr) __asm__ __volatile("ltr %0"::"m" (tr))
+#define load_ldt(ldt) __asm__ __volatile("lldt %0"::"m" (ldt))
+
+#define store_gdt(dtr) native_store_gdt(dtr)
+#define store_idt(dtr) native_store_idt(dtr)
+#define store_tr(tr) (tr = native_store_tr())
+#define store_ldt(ldt) __asm__ ("sldt %0":"=m" (ldt))
+
+#define load_TLS(t, cpu) native_load_tls(t, cpu)
+#define set_ldt native_set_ldt
+
+#define write_ldt_entry(dt, entry, desc) \
+ native_write_ldt_entry(dt, entry, desc)
+#define write_gdt_entry(dt, entry, desc, type) \
+ native_write_gdt_entry(dt, entry, desc, type)
+#define write_idt_entry(dt, entry, g) native_write_idt_entry(dt, entry, g)
+#endif
+
+static inline void native_write_idt_entry(gate_desc *idt, int entry,
+ const gate_desc *gate)
+{
+ memcpy(&idt[entry], gate, sizeof(*gate));
+}
+
+static inline void native_write_ldt_entry(struct desc_struct *ldt, int entry,
+ const void *desc)
+{
+ memcpy(&ldt[entry], desc, 8);
+}
+
+static inline void native_write_gdt_entry(struct desc_struct *gdt, int entry,
+ const void *desc, int type)
+{
+ unsigned int size;
+ switch (type) {
+ case DESC_TSS:
+ size = sizeof(tss_desc);
+ break;
+ case DESC_LDT:
+ size = sizeof(ldt_desc);
+ break;
+ default:
+ size = sizeof(struct desc_struct);
+ break;
+ }
+ memcpy(&gdt[entry], desc, size);
+}
+
+static inline void pack_descriptor(struct desc_struct *desc, unsigned long base,
+ unsigned long limit, unsigned char type,
+ unsigned char flags)
+{
+ desc->a = ((base & 0xffff) << 16) | (limit & 0xffff);
+ desc->b = (base & 0xff000000) | ((base & 0xff0000) >> 16) |
+ (limit & 0x000f0000) | ((type & 0xff) << 8) |
+ ((flags & 0xf) << 20);
+ desc->p = 1;
+}
+
+
+static inline void set_tssldt_descriptor(void *d, unsigned long addr,
+ unsigned type, unsigned size)
+{
+#ifdef CONFIG_X86_64
+ struct ldttss_desc64 *desc = d;
+ memset(desc, 0, sizeof(*desc));
+ desc->limit0 = size & 0xFFFF;
+ desc->base0 = PTR_LOW(addr);
+ desc->base1 = PTR_MIDDLE(addr) & 0xFF;
+ desc->type = type;
+ desc->p = 1;
+ desc->limit1 = (size >> 16) & 0xF;
+ desc->base2 = (PTR_MIDDLE(addr) >> 8) & 0xFF;
+ desc->base3 = PTR_HIGH(addr);
+#else
+
+ pack_descriptor((struct desc_struct *)d, addr, size, 0x80 | type, 0);
+#endif
+}
+
+static inline void native_set_ldt(const void *addr, unsigned int entries)
+{
+ if (likely(entries == 0))
+ __asm__ __volatile__("lldt %w0"::"q" (0));
+ else {
+ unsigned cpu = smp_processor_id();
+ ldt_desc ldt;
+
+ set_tssldt_descriptor(&ldt, (unsigned long)addr,
+ DESC_LDT, entries * sizeof(ldt) - 1);
+ write_gdt_entry(get_cpu_gdt_table(cpu), GDT_ENTRY_LDT,
+ &ldt, DESC_LDT);
+ __asm__ __volatile__("lldt %w0"::"q" (GDT_ENTRY_LDT*8));
+ }
+}
+
+static inline void native_load_tr_desc(void)
+{
+ asm volatile("ltr %w0"::"q" (GDT_ENTRY_TSS*8));
+}
+
+static inline void native_load_gdt(const struct desc_ptr *dtr)
+{
+ asm volatile("lgdt %0"::"m" (*dtr));
+}
+
+static inline void native_load_idt(const struct desc_ptr *dtr)
+{
+ asm volatile("lidt %0"::"m" (*dtr));
+}
+
+static inline void native_store_gdt(struct desc_ptr *dtr)
+{
+ asm volatile("sgdt %0":"=m" (*dtr));
+}
+
+static inline void native_store_idt(struct desc_ptr *dtr)
+{
+ asm volatile("sidt %0":"=m" (*dtr));
+}
+
+static inline unsigned long native_store_tr(void)
+{
+ unsigned long tr;
+ asm volatile("str %0":"=r" (tr));
+ return tr;
+}
+
+static inline void native_load_tls(struct thread_struct *t, unsigned int cpu)
+{
+ unsigned int i;
+ struct desc_struct *gdt = get_cpu_gdt_table(cpu);
+
+ for (i = 0; i < GDT_ENTRY_TLS_ENTRIES; i++)
+ gdt[GDT_ENTRY_TLS_MIN + i] = t->tls_array[i];
+}
+
#ifdef CONFIG_X86_32
# include "desc_32.h"
#else

2007-12-13 16:47:03

by Glauber Costa

[permalink] [raw]
Subject: [PATCH 19/19] unify set_tss_desc

This patch unifies the set_tss_desc between i386 and x86_64,
which can now have a common implementation. After the old
functions are removed from desc_{32,64}.h, nothing important is
left, and the files can be removed.

Signed-off-by: Glauber de Oliveira Costa <[email protected]>
---
include/asm-x86/desc.h | 40 +++++++++++++++++++++++++++++++++-------
include/asm-x86/desc_32.h | 27 ---------------------------
include/asm-x86/desc_64.h | 34 ----------------------------------
3 files changed, 33 insertions(+), 68 deletions(-)
delete mode 100644 include/asm-x86/desc_32.h
delete mode 100644 include/asm-x86/desc_64.h

Index: linux-2.6-x86/include/asm-x86/desc.h
===================================================================
--- linux-2.6-x86.orig/include/asm-x86/desc.h
+++ linux-2.6-x86/include/asm-x86/desc.h
@@ -157,6 +157,26 @@ static inline void set_tssldt_descriptor
#endif
}

+static inline void __set_tss_desc(unsigned cpu, unsigned int entry, void *addr)
+{
+ struct desc_struct *d = get_cpu_gdt_table(cpu);
+ tss_desc tss;
+
+ /*
+ * sizeof(unsigned long) coming from an extra "long" at the end
+ * of the iobitmap. See tss_struct definition in processor.h
+ *
+ * -1? seg base+limit should be pointing to the address of the
+ * last valid byte
+ */
+ set_tssldt_descriptor(&tss, (unsigned long)addr,
+ IO_BITMAP_OFFSET + IO_BITMAP_BYTES + sizeof(unsigned long) - 1,
+ DESC_TSS);
+ write_gdt_entry(d, entry, &tss, DESC_TSS);
+}
+
+#define set_tss_desc(cpu, addr) __set_tss_desc(cpu, GDT_ENTRY_TSS, addr)
+
static inline void native_set_ldt(const void *addr, unsigned int entries)
{
if (likely(entries == 0))
@@ -214,12 +234,6 @@ static inline void native_load_tls(struc
gdt[GDT_ENTRY_TLS_MIN + i] = t->tls_array[i];
}

-#ifdef CONFIG_X86_32
-# include "desc_32.h"
-#else
-# include "desc_64.h"
-#endif
-
#define _LDT_empty(info) (\
(info)->base_addr == 0 && \
(info)->limit == 0 && \
Index: linux-2.6-x86/include/asm-x86/desc_32.h
===================================================================
--- linux-2.6-x86.orig/include/asm-x86/desc_32.h
+++ /dev/null
@@ -1,27 +0,0 @@
-#ifndef __ARCH_DESC_H
-#define __ARCH_DESC_H
-
-#include <asm/ldt.h>
-#include <asm/segment.h>
-#include <asm/desc_defs.h>
-
-#ifndef __ASSEMBLY__
-
-#include <linux/preempt.h>
-#include <linux/percpu.h>
-
-static inline void __set_tss_desc(unsigned int cpu, unsigned int entry, const void *addr)
-{
- tss_desc tss;
- pack_descriptor(&tss, (unsigned long)addr,
- offsetof(struct tss_struct, __cacheline_filler) - 1,
- DESC_TSS, 0);
- write_gdt_entry(get_cpu_gdt_table(cpu), entry, &tss, DESC_TSS);
-}
-
-
-#define set_tss_desc(cpu,addr) __set_tss_desc(cpu, GDT_ENTRY_TSS, addr)
-
-#endif /* !__ASSEMBLY__ */
-
-#endif
Index: linux-2.6-x86/include/asm-x86/desc_64.h
===================================================================
--- linux-2.6-x86.orig/include/asm-x86/desc_64.h
+++ linux-2.6-x86/include/asm-x86/desc_64.h
@@ -1,34 +1 @@
-/* Written 2000 by Andi Kleen */
-#ifndef __ARCH_DESC_H
-#define __ARCH_DESC_H

-#include <linux/threads.h>
-#include <asm/ldt.h>
-
-#ifndef __ASSEMBLY__
-
-#include <linux/string.h>
-
-#include <asm/segment.h>
-
-static inline void set_tss_desc(unsigned cpu, void *addr)
-{
- struct desc_struct *d = get_cpu_gdt_table(cpu);
- tss_desc tss;
-
- /*
- * sizeof(unsigned long) coming from an extra "long" at the end
- * of the iobitmap. See tss_struct definition in processor.h
- *
- * -1? seg base+limit should be pointing to the address of the
- * last valid byte
- */
- set_tssldt_descriptor(&tss,
- (unsigned long)addr, DESC_TSS,
- IO_BITMAP_OFFSET + IO_BITMAP_BYTES + sizeof(unsigned long) - 1);
- write_gdt_entry(d, GDT_ENTRY_TSS, &tss, DESC_TSS);
-}
-
-#endif /* !__ASSEMBLY__ */
-
-#endif

2007-12-13 16:48:53

by Ingo Molnar

[permalink] [raw]
Subject: Re: [PATCH 0/19 -v4] desc_struct integration


* Glauber de Oliveira Costa <[email protected]> wrote:

> Since the last version of it received no comments on the interfaces,
> here it goes a version, that I feel ready for inclusion.
>
> The comments regarding style, specially the elimination of the
> #defines in the desc_struct definition were merged. I also implemented
> the vmi functions, missing last time.
>
> Ingo, in the absense of further complaints, could you please push to
> the x86 tree?

well i've already included v3 in x86.git (and it's pushed out), and that
was looking good already in review and in testing - could you send a
v3->v4 delta too?

Ingo

2007-12-13 16:57:45

by Glauber Costa

[permalink] [raw]
Subject: [PATCH 04/19] removed unused variable

This variable is not used anywere, and is then removed

Signed-off-by: Glauber de Oliveira Costa <[email protected]>
---
include/asm-x86/desc_64.h | 5 -----
1 files changed, 0 insertions(+), 5 deletions(-)

diff --git a/include/asm-x86/desc_64.h b/include/asm-x86/desc_64.h
index 1c26dbb..660cc84 100644
--- a/include/asm-x86/desc_64.h
+++ b/include/asm-x86/desc_64.h
@@ -30,11 +30,6 @@ static inline unsigned long __store_tr(void)

#define store_tr(tr) (tr) = __store_tr()

-/*
- * This is the ldt that every process will get unless we need
- * something other than this.
- */
-extern struct desc_struct default_ldt[];
extern struct gate_struct idt_table[];
extern struct desc_ptr cpu_gdt_descr[];

--
1.5.0.6

2007-12-13 16:58:00

by Glauber Costa

[permalink] [raw]
Subject: [PATCH 07/19] introduce ldt_desc type.

this patch introduces ldt_desc type to account for the differences
in the ldt descriptor in x86_64 and i386

Signed-off-by: Glauber de Oliveira Costa <[email protected]>
---
include/asm-x86/desc_64.h | 2 +-
include/asm-x86/desc_defs.h | 4 +++-
2 files changed, 4 insertions(+), 2 deletions(-)

diff --git a/include/asm-x86/desc_64.h b/include/asm-x86/desc_64.h
index ffc6c06..8fe1b4c 100644
--- a/include/asm-x86/desc_64.h
+++ b/include/asm-x86/desc_64.h
@@ -113,7 +113,7 @@ static inline void store_idt(struct desc_ptr *dtr)
static inline void set_tssldt_descriptor(void *ptr, unsigned long tss,
unsigned type, unsigned size)
{
- struct ldttss_desc d;
+ struct ldttss_desc64 d;

memset(&d, 0, sizeof(d));
d.limit0 = size & 0xFFFF;
diff --git a/include/asm-x86/desc_defs.h b/include/asm-x86/desc_defs.h
index 05eff93..5a58fc1 100644
--- a/include/asm-x86/desc_defs.h
+++ b/include/asm-x86/desc_defs.h
@@ -58,7 +58,7 @@ enum {
};

// LDT or TSS descriptor in the GDT. 16 bytes.
-struct ldttss_desc {
+struct ldttss_desc64 {
u16 limit0;
u16 base0;
unsigned base1 : 8, type : 5, dpl : 2, p : 1;
@@ -69,8 +69,10 @@ struct ldttss_desc {

#ifdef CONFIG_X86_64
typedef struct gate_struct64 gate_desc;
+typedef struct ldttss_desc64 ldt_desc;
#else
typedef struct desc_struct gate_desc;
+typedef struct desc_struct ldt_desc;
#endif

struct desc_ptr {
--
1.5.0.6

2007-12-13 16:58:27

by Glauber Costa

[permalink] [raw]
Subject: [PATCH 10/19] provide tss_desc

Provide a new type, tss_desc, to represent the tss descriptor
in a unified way accross x86_64 and i386

Signed-off-by: Glauber de Oliveira Costa <[email protected]>
---
include/asm-x86/desc_defs.h | 2 ++
1 files changed, 2 insertions(+), 0 deletions(-)

diff --git a/include/asm-x86/desc_defs.h b/include/asm-x86/desc_defs.h
index 5a58fc1..c4d7874 100644
--- a/include/asm-x86/desc_defs.h
+++ b/include/asm-x86/desc_defs.h
@@ -70,9 +70,11 @@ struct ldttss_desc64 {
#ifdef CONFIG_X86_64
typedef struct gate_struct64 gate_desc;
typedef struct ldttss_desc64 ldt_desc;
+typedef struct ldttss_desc64 tss_desc;
#else
typedef struct desc_struct gate_desc;
typedef struct desc_struct ldt_desc;
+typedef struct desc_struct tss_desc;
#endif

struct desc_ptr {
--
1.5.0.6

2007-12-13 16:58:43

by Glauber Costa

[permalink] [raw]
Subject: [PATCH 08/19] modify write_ldt function

This patch modifies the write_ldt() function to make use
of the new struct desc_struct instead of entry_1 and entry_2
entries

Signed-off-by: Glauber de Oliveira Costa <[email protected]>
---
arch/x86/kernel/ldt.c | 15 +++++++--------
1 files changed, 7 insertions(+), 8 deletions(-)

diff --git a/arch/x86/kernel/ldt.c b/arch/x86/kernel/ldt.c
index a8cdca3..7eb0c8a 100644
--- a/arch/x86/kernel/ldt.c
+++ b/arch/x86/kernel/ldt.c
@@ -186,7 +186,7 @@ static int read_default_ldt(void __user *ptr, unsigned long bytecount)
static int write_ldt(void __user *ptr, unsigned long bytecount, int oldmode)
{
struct mm_struct *mm = current->mm;
- __u32 entry_1, entry_2;
+ struct desc_struct ldt;
int error;
struct user_desc ldt_info;

@@ -218,21 +218,20 @@ static int write_ldt(void __user *ptr, unsigned long bytecount, int oldmode)
/* Allow LDTs to be cleared by the user. */
if (ldt_info.base_addr == 0 && ldt_info.limit == 0) {
if (oldmode || LDT_empty(&ldt_info)) {
- entry_1 = 0;
- entry_2 = 0;
+ memset(&ldt, 0, sizeof(ldt));
goto install;
}
}

- entry_1 = LDT_entry_a(&ldt_info);
- entry_2 = LDT_entry_b(&ldt_info);
+ ldt.a = LDT_entry_a(&ldt_info);
+ ldt.b = LDT_entry_b(&ldt_info);
if (oldmode)
- entry_2 &= ~(1 << 20);
+ ldt.avl = 0;

/* Install the new entry ... */
install:
- write_ldt_entry(mm->context.ldt, ldt_info.entry_number, entry_1,
- entry_2);
+ write_ldt_entry(mm->context.ldt, ldt_info.entry_number,
+ ldt.a, ldt.b);
error = 0;

out_unlock:
--
1.5.0.6

2007-12-13 16:58:58

by Glauber Costa

[permalink] [raw]
Subject: [PATCH 12/19] change write_ldt_entry signature

this patch changes the signature of write_ldt_entry.

Signed-off-by: Glauber de Oliveira Costa <[email protected]>
CC: Zachary Amsden <[email protected]>
CC: Jeremy Fitzhardinge <Jeremy.Fitzhardinge.citrix.com>
---
arch/x86/kernel/ldt.c | 3 +--
arch/x86/kernel/paravirt_32.c | 2 +-
arch/x86/kernel/vmi_32.c | 11 ++++++++++-
arch/x86/xen/enlighten.c | 4 ++--
include/asm-x86/desc_32.h | 9 ++++++++-
include/asm-x86/desc_64.h | 7 ++-----
include/asm-x86/paravirt.h | 10 ++++++----
7 files changed, 30 insertions(+), 16 deletions(-)

diff --git a/arch/x86/kernel/ldt.c b/arch/x86/kernel/ldt.c
index 3e872b4..b8ef462 100644
--- a/arch/x86/kernel/ldt.c
+++ b/arch/x86/kernel/ldt.c
@@ -229,8 +229,7 @@ static int write_ldt(void __user *ptr, unsigned long bytecount, int oldmode)

/* Install the new entry ... */
install:
- write_ldt_entry(mm->context.ldt, ldt_info.entry_number,
- ldt.a, ldt.b);
+ write_ldt_entry(mm->context.ldt, ldt_info.entry_number, &ldt);
error = 0;

out_unlock:
diff --git a/arch/x86/kernel/paravirt_32.c b/arch/x86/kernel/paravirt_32.c
index 77602c1..dd063fb 100644
--- a/arch/x86/kernel/paravirt_32.c
+++ b/arch/x86/kernel/paravirt_32.c
@@ -379,7 +379,7 @@ struct pv_cpu_ops pv_cpu_ops = {
.store_idt = native_store_idt,
.store_tr = native_store_tr,
.load_tls = native_load_tls,
- .write_ldt_entry = write_dt_entry,
+ .write_ldt_entry = native_write_ldt_entry,
.write_gdt_entry = native_write_gdt_entry,
.write_idt_entry = native_write_idt_entry,
.load_sp0 = native_load_sp0,
diff --git a/arch/x86/kernel/vmi_32.c b/arch/x86/kernel/vmi_32.c
index 21edd0d..10c4641 100644
--- a/arch/x86/kernel/vmi_32.c
+++ b/arch/x86/kernel/vmi_32.c
@@ -64,6 +64,7 @@ static struct {
void (*set_tr)(u32 selector);
void (*write_idt_entry)(struct desc_struct *, int, u32, u32);
void (*write_gdt_entry)(struct desc_struct *, int, u32, u32);
+ void (*write_ldt_entry)(struct desc_struct *, int, u32, u32);
void (*set_kernel_stack)(u32 selector, u32 sp0);
void (*allocate_page)(u32, u32, u32, u32, u32);
void (*release_page)(u32, u32);
@@ -229,6 +230,13 @@ static void vmi_write_gdt_entry(struct desc_struct *dt, int entry,
vmi_ops.write_gdt_entry(dt, entry, gdt_entry[0], gdt_entry[2]);
}

+static void vmi_write_ldt_entry(struct desc_struct *dt, int entry,
+ const void *desc)
+{
+ u32 *ldt_entry = (u32 *)desc;
+ vmi_ops.write_idt_entry(dt, entry, ldt_entry[0], ldt_entry[2]);
+}
+
static void vmi_load_sp0(struct tss_struct *tss,
struct thread_struct *thread)
{
@@ -805,7 +813,8 @@ static inline int __init activate_vmi(void)
para_fill(pv_cpu_ops.store_idt, GetIDT);
para_fill(pv_cpu_ops.store_tr, GetTR);
pv_cpu_ops.load_tls = vmi_load_tls;
- para_fill(pv_cpu_ops.write_ldt_entry, WriteLDTEntry);
+ para_wrap(pv_cpu_ops.write_ldt_entry, vmi_write_ldt_entry,
+ write_ldt_entry, WriteLDTEntry);
para_wrap(pv_cpu_ops.write_gdt_entry, vmi_write_gdt_entry,
write_gdt_entry, WriteGDTEntry);
para_wrap(pv_cpu_ops.write_idt_entry, vmi_write_idt_entry,
diff --git a/arch/x86/xen/enlighten.c b/arch/x86/xen/enlighten.c
index c38240c..c904686 100644
--- a/arch/x86/xen/enlighten.c
+++ b/arch/x86/xen/enlighten.c
@@ -357,11 +357,11 @@ static void xen_load_tls(struct thread_struct *t, unsigned int cpu)
}

static void xen_write_ldt_entry(struct desc_struct *dt, int entrynum,
- u32 low, u32 high)
+ const void *ptr)
{
unsigned long lp = (unsigned long)&dt[entrynum];
xmaddr_t mach_lp = virt_to_machine(lp);
- u64 entry = (u64)high << 32 | low;
+ u64 entry = *(u64 *)ptr;

preempt_disable();

diff --git a/include/asm-x86/desc_32.h b/include/asm-x86/desc_32.h
index 41d8214..92a72b0 100644
--- a/include/asm-x86/desc_32.h
+++ b/include/asm-x86/desc_32.h
@@ -69,12 +69,19 @@ static inline void pack_gate(gate_desc *gate,
#define load_TLS(t, cpu) native_load_tls(t, cpu)
#define set_ldt native_set_ldt

-#define write_ldt_entry(dt, entry, a, b) write_dt_entry(dt, entry, a, b)
+#define write_ldt_entry(dt, entry, desc) \
+ native_write_ldt_entry(dt, entry, desc)
#define write_gdt_entry(dt, entry, desc, type) \
native_write_gdt_entry(dt, entry, desc, type)
#define write_idt_entry(dt, entry, g) native_write_idt_entry(dt, entry, g)
#endif

+static inline void native_write_ldt_entry(struct desc_struct *ldt, int entry,
+ const void *desc)
+{
+ memcpy(&ldt[entry], desc, sizeof(struct desc_struct));
+}
+
static inline void native_write_idt_entry(gate_desc *idt, int entry,
const gate_desc *gate)
{
diff --git a/include/asm-x86/desc_64.h b/include/asm-x86/desc_64.h
index e0aa4bc..3cd5f10 100644
--- a/include/asm-x86/desc_64.h
+++ b/include/asm-x86/desc_64.h
@@ -34,12 +34,9 @@ extern gate_desc idt_table[];
extern struct desc_ptr cpu_gdt_descr[];

static inline void write_ldt_entry(struct desc_struct *ldt,
- int entry, u32 entry_low, u32 entry_high)
+ int entry, void *ptr)
{
- __u32 *lp = (__u32 *)((entry << 3) + (char *)ldt);
-
- lp[0] = entry_low;
- lp[1] = entry_high;
+ memcpy(&ldt[entry], ptr, 8);
}

/* the cpu gdt accessor */
diff --git a/include/asm-x86/paravirt.h b/include/asm-x86/paravirt.h
index 3f2abf2..4f23f43 100644
--- a/include/asm-x86/paravirt.h
+++ b/include/asm-x86/paravirt.h
@@ -96,8 +96,8 @@ struct pv_cpu_ops {
void (*set_ldt)(const void *desc, unsigned entries);
unsigned long (*store_tr)(void);
void (*load_tls)(struct thread_struct *t, unsigned int cpu);
- void (*write_ldt_entry)(struct desc_struct *,
- int entrynum, u32 low, u32 high);
+ void (*write_ldt_entry)(struct desc_struct *ldt, int entrynum,
+ const void *desc);
void (*write_gdt_entry)(struct desc_struct *,
int entrynum, const void *desc, int size);
void (*write_idt_entry)(gate_desc *,
@@ -660,9 +660,11 @@ static inline void load_TLS(struct thread_struct *t, unsigned cpu)
{
PVOP_VCALL2(pv_cpu_ops.load_tls, t, cpu);
}
-static inline void write_ldt_entry(void *dt, int entry, u32 low, u32 high)
+
+static inline void write_ldt_entry(struct desc_struct *dt, int entry,
+ const void *desc)
{
- PVOP_VCALL4(pv_cpu_ops.write_ldt_entry, dt, entry, low, high);
+ PVOP_VCALL3(pv_cpu_ops.write_ldt_entry, dt, entry, desc);
}

static inline void write_gdt_entry(struct desc_struct *dt, int entry,
--
1.5.0.6

2007-12-13 16:59:34

by Glauber Costa

[permalink] [raw]
Subject: [PATCH 05/19] introduce gate_desc type.

To account for the differences in gate descriptor in i386 and x86_64
a gate_desc type is introduced.

Signed-off-by: Glauber de Oliveira Costa <[email protected]>
---
arch/x86/kernel/traps_32.c | 3 ++-
include/asm-x86/desc_32.h | 15 ++++++++-------
include/asm-x86/desc_64.h | 4 ++--
include/asm-x86/desc_defs.h | 8 +++++++-
4 files changed, 19 insertions(+), 11 deletions(-)

diff --git a/arch/x86/kernel/traps_32.c b/arch/x86/kernel/traps_32.c
index 94c5aea..6b03d88 100644
--- a/arch/x86/kernel/traps_32.c
+++ b/arch/x86/kernel/traps_32.c
@@ -76,8 +76,8 @@ 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 } } }, };
+gate_desc idt_table[256]
+ __attribute__((__section__(".data.idt"))) = { { { { 0, 0 } } }, };

asmlinkage void divide_error(void);
asmlinkage void debug(void);
diff --git a/include/asm-x86/desc_32.h b/include/asm-x86/desc_32.h
index bc5ca34..77f1e5a 100644
--- a/include/asm-x86/desc_32.h
+++ b/include/asm-x86/desc_32.h
@@ -3,6 +3,7 @@

#include <asm/ldt.h>
#include <asm/segment.h>
+#include <asm/desc_defs.h>

#ifndef __ASSEMBLY__

@@ -24,7 +25,7 @@ static inline struct desc_struct *get_cpu_gdt_table(unsigned int cpu)
}

extern struct desc_ptr idt_descr;
-extern struct desc_struct idt_table[];
+extern gate_desc idt_table[];
extern void set_intr_gate(unsigned int irq, void * addr);

static inline void pack_descriptor(__u32 *a, __u32 *b,
@@ -35,11 +36,11 @@ static inline void pack_descriptor(__u32 *a, __u32 *b,
(limit & 0x000f0000) | ((type & 0xff) << 8) | ((flags & 0xf) << 20);
}

-static inline void pack_gate(__u32 *a, __u32 *b,
+static inline void pack_gate(gate_desc *gate,
unsigned long base, unsigned short seg, unsigned char type, unsigned char flags)
{
- *a = (seg << 16) | (base & 0xffff);
- *b = (base & 0xffff0000) | ((type & 0xff) << 8) | (flags & 0xff);
+ gate->a = (seg << 16) | (base & 0xffff);
+ gate->b = (base & 0xffff0000) | ((type & 0xff) << 8) | (flags & 0xff);
}

#define DESCTYPE_LDT 0x82 /* present, system, DPL-0, LDT */
@@ -139,9 +140,9 @@ static inline void native_load_tls(struct thread_struct *t, unsigned int cpu)

static inline void _set_gate(int gate, unsigned int type, void *addr, unsigned short seg)
{
- __u32 a, b;
- pack_gate(&a, &b, (unsigned long)addr, seg, type, 0);
- write_idt_entry(idt_table, gate, a, b);
+ gate_desc g;
+ pack_gate(&g, (unsigned long)addr, seg, type, 0);
+ write_idt_entry(idt_table, gate, g.a, g.b);
}

static inline void __set_tss_desc(unsigned int cpu, unsigned int entry, const void *addr)
diff --git a/include/asm-x86/desc_64.h b/include/asm-x86/desc_64.h
index 660cc84..ffc6c06 100644
--- a/include/asm-x86/desc_64.h
+++ b/include/asm-x86/desc_64.h
@@ -30,7 +30,7 @@ static inline unsigned long __store_tr(void)

#define store_tr(tr) (tr) = __store_tr()

-extern struct gate_struct idt_table[];
+extern gate_desc idt_table[];
extern struct desc_ptr cpu_gdt_descr[];

static inline void write_ldt_entry(struct desc_struct *ldt,
@@ -58,7 +58,7 @@ static inline void store_gdt(struct desc_ptr *ptr)
static inline void _set_gate(void *adr, unsigned type, unsigned long func,
unsigned dpl, unsigned ist)
{
- struct gate_struct s;
+ gate_desc s;

s.offset_low = PTR_LOW(func);
s.segment = __KERNEL_CS;
diff --git a/include/asm-x86/desc_defs.h b/include/asm-x86/desc_defs.h
index f37b44c..05eff93 100644
--- a/include/asm-x86/desc_defs.h
+++ b/include/asm-x86/desc_defs.h
@@ -39,7 +39,7 @@ enum {
};

// 16byte gate
-struct gate_struct {
+struct gate_struct64 {
u16 offset_low;
u16 segment;
unsigned ist : 3, zero0 : 5, type : 5, dpl : 2, p : 1;
@@ -67,6 +67,12 @@ struct ldttss_desc {
u32 zero1;
} __attribute__((packed));

+#ifdef CONFIG_X86_64
+typedef struct gate_struct64 gate_desc;
+#else
+typedef struct desc_struct gate_desc;
+#endif
+
struct desc_ptr {
unsigned short size;
unsigned long address;
--
1.5.0.6

2007-12-13 16:59:58

by Glauber Costa

[permalink] [raw]
Subject: [PATCH 09/19] introduce fill_ldt

This patch introduces fill_ldt(), which populates a ldt descriptor
from a user_desc in once, instead of relying in the LDT_entry_a and
LDT_entry_b macros

Signed-off-by: Glauber de Oliveira Costa <[email protected]>
---
arch/x86/kernel/ldt.c | 3 +--
arch/x86/kernel/process_64.c | 3 +--
arch/x86/kernel/tls.c | 7 +++----
include/asm-x86/desc_32.h | 15 ---------------
include/asm-x86/desc_64.h | 17 -----------------
include/asm-x86/ldt.h | 19 +++++++++++++++++++
6 files changed, 24 insertions(+), 40 deletions(-)

Index: linux-2.6-x86/arch/x86/kernel/ldt.c
===================================================================
--- linux-2.6-x86.orig/arch/x86/kernel/ldt.c
+++ linux-2.6-x86/arch/x86/kernel/ldt.c
@@ -223,8 +223,7 @@ static int write_ldt(void __user *ptr, u
}
}

- ldt.a = LDT_entry_a(&ldt_info);
- ldt.b = LDT_entry_b(&ldt_info);
+ fill_ldt(&ldt, &ldt_info);
if (oldmode)
ldt.avl = 0;

Index: linux-2.6-x86/arch/x86/kernel/process_64.c
===================================================================
--- linux-2.6-x86.orig/arch/x86/kernel/process_64.c
+++ linux-2.6-x86/arch/x86/kernel/process_64.c
@@ -446,8 +446,7 @@ static inline void set_32bit_tls(struct
};
struct desc_struct *desc = (void *)t->thread.tls_array;
desc += tls;
- desc->a = LDT_entry_a(&ud);
- desc->b = LDT_entry_b(&ud);
+ fill_ldt(desc, &ud);
}

static inline u32 read_32bit_tls(struct task_struct *t, int tls)
Index: linux-2.6-x86/arch/x86/kernel/tls.c
===================================================================
--- linux-2.6-x86.orig/arch/x86/kernel/tls.c
+++ linux-2.6-x86/arch/x86/kernel/tls.c
@@ -67,10 +67,9 @@ int do_set_thread_area(struct task_struc
if (LDT_empty(&info)) {
desc[0] = 0;
desc[1] = 0;
- } else {
- desc[0] = LDT_entry_a(&info);
- desc[1] = LDT_entry_b(&info);
- }
+ } else
+ fill_ldt((struct desc_struct *)desc, &info);
+
if (t == &current->thread)
load_TLS(t, cpu);

Index: linux-2.6-x86/include/asm-x86/desc_32.h
===================================================================
--- linux-2.6-x86.orig/include/asm-x86/desc_32.h
+++ linux-2.6-x86/include/asm-x86/desc_32.h
@@ -163,21 +163,6 @@ static inline void __set_tss_desc(unsign

#define set_tss_desc(cpu,addr) __set_tss_desc(cpu, GDT_ENTRY_TSS, addr)

-#define LDT_entry_a(info) \
- ((((info)->base_addr & 0x0000ffff) << 16) | ((info)->limit & 0x0ffff))
-
-#define LDT_entry_b(info) \
- (((info)->base_addr & 0xff000000) | \
- (((info)->base_addr & 0x00ff0000) >> 16) | \
- ((info)->limit & 0xf0000) | \
- (((info)->read_exec_only ^ 1) << 9) | \
- ((info)->contents << 10) | \
- (((info)->seg_not_present ^ 1) << 15) | \
- ((info)->seg_32bit << 22) | \
- ((info)->limit_in_pages << 23) | \
- ((info)->useable << 20) | \
- 0x7000)
-
#define LDT_empty(info) (\
(info)->base_addr == 0 && \
(info)->limit == 0 && \
Index: linux-2.6-x86/include/asm-x86/desc_64.h
===================================================================
--- linux-2.6-x86.orig/include/asm-x86/desc_64.h
+++ linux-2.6-x86/include/asm-x86/desc_64.h
@@ -147,23 +147,6 @@ static inline void set_ldt_desc(unsigned
(unsigned long)addr, DESC_LDT, size * 8 - 1);
}

-#define LDT_entry_a(info) \
- ((((info)->base_addr & 0x0000ffff) << 16) | ((info)->limit & 0x0ffff))
-/* Don't allow setting of the lm bit. It is useless anyways because
- 64bit system calls require __USER_CS. */
-#define LDT_entry_b(info) \
- (((info)->base_addr & 0xff000000) | \
- (((info)->base_addr & 0x00ff0000) >> 16) | \
- ((info)->limit & 0xf0000) | \
- (((info)->read_exec_only ^ 1) << 9) | \
- ((info)->contents << 10) | \
- (((info)->seg_not_present ^ 1) << 15) | \
- ((info)->seg_32bit << 22) | \
- ((info)->limit_in_pages << 23) | \
- ((info)->useable << 20) | \
- /* ((info)->lm << 21) | */ \
- 0x7000)
-
#define LDT_empty(info) (\
(info)->base_addr == 0 && \
(info)->limit == 0 && \
Index: linux-2.6-x86/include/asm-x86/desc.h
===================================================================
--- linux-2.6-x86.orig/include/asm-x86/desc.h
+++ linux-2.6-x86/include/asm-x86/desc.h
@@ -1,5 +1,34 @@
+#ifndef _ASM_DESC_H_
+#define _ASM_DESC_H_
+
+#ifndef __ASSEMBLY__
+#include <asm/desc_defs.h>
+#include <asm/ldt.h>
+
+static inline void fill_ldt(struct desc_struct *desc, struct user_desc *info)
+{
+ desc->limit0 = info->limit & 0x0ffff;
+ desc->base0 = info->base_addr & 0x0000ffff;
+
+ desc->base1 = (info->base_addr & 0x00ff0000) >> 16;
+ desc->type = (info->read_exec_only ^ 1) << 1;
+ desc->type |= info->contents << 2;
+ desc->s = 1;
+ desc->dpl = 0x3;
+ desc->p = info->seg_not_present ^ 1;
+ desc->limit = (info->limit & 0xf0000) >> 16;
+ desc->avl = info->useable;
+ desc->d = info->seg_32bit;
+ desc->g = info->limit_in_pages;
+ desc->base2 = (info->base_addr & 0xff000000) >> 24;
+}
+
+#endif
+
#ifdef CONFIG_X86_32
# include "desc_32.h"
#else
# include "desc_64.h"
#endif
+
+#endif

2007-12-13 17:00:38

by Glauber Costa

[permalink] [raw]
Subject: [PATCH 06/19] change write_idt_entry signature

this patch changes write_idt_entry signature. It now takes a gate_desc
instead of the a and b parameters. It will allow it to be later unified
between i386 and x86_64.

Signed-off-by: Glauber de Oliveira Costa <[email protected]>
CC: Zachary Amsden <[email protected]>
CC: Jeremy Fitzhardinge <Jeremy.Fitzhardinge.citrix.com>
---
arch/x86/kernel/paravirt_32.c | 2 +-
arch/x86/kernel/vmi_32.c | 10 +++++++++-
arch/x86/lguest/boot.c | 9 +++++----
arch/x86/xen/enlighten.c | 8 ++++----
include/asm-x86/desc_32.h | 10 ++++++++--
include/asm-x86/paravirt.h | 9 +++++----
6 files changed, 32 insertions(+), 16 deletions(-)

diff --git a/arch/x86/kernel/paravirt_32.c b/arch/x86/kernel/paravirt_32.c
index f4e3a8e..13bbc99 100644
--- a/arch/x86/kernel/paravirt_32.c
+++ b/arch/x86/kernel/paravirt_32.c
@@ -381,7 +381,7 @@ struct pv_cpu_ops pv_cpu_ops = {
.load_tls = native_load_tls,
.write_ldt_entry = write_dt_entry,
.write_gdt_entry = write_dt_entry,
- .write_idt_entry = write_dt_entry,
+ .write_idt_entry = native_write_idt_entry,
.load_sp0 = native_load_sp0,

.irq_enable_syscall_ret = native_irq_enable_syscall_ret,
diff --git a/arch/x86/kernel/vmi_32.c b/arch/x86/kernel/vmi_32.c
index 4cfda7d..a635b22 100644
--- a/arch/x86/kernel/vmi_32.c
+++ b/arch/x86/kernel/vmi_32.c
@@ -62,6 +62,7 @@ static struct {
void (*cpuid)(void /* non-c */);
void (*_set_ldt)(u32 selector);
void (*set_tr)(u32 selector);
+ void (*write_idt_entry)(struct desc_struct *, int, u32, u32);
void (*set_kernel_stack)(u32 selector, u32 sp0);
void (*allocate_page)(u32, u32, u32, u32, u32);
void (*release_page)(u32, u32);
@@ -214,6 +215,12 @@ static void vmi_set_tr(void)
vmi_ops.set_tr(GDT_ENTRY_TSS*sizeof(struct desc_struct));
}

+static void vmi_write_idt_entry(gate_desc *dt, int entry, const gate_desc *g)
+{
+ u32 *idt_entry = (u32 *)g;
+ vmi_ops.write_idt_entry(dt, entry, idt_entry[0], idt_entry[2]);
+}
+
static void vmi_load_sp0(struct tss_struct *tss,
struct thread_struct *thread)
{
@@ -792,7 +799,8 @@ static inline int __init activate_vmi(void)
pv_cpu_ops.load_tls = vmi_load_tls;
para_fill(pv_cpu_ops.write_ldt_entry, WriteLDTEntry);
para_fill(pv_cpu_ops.write_gdt_entry, WriteGDTEntry);
- para_fill(pv_cpu_ops.write_idt_entry, WriteIDTEntry);
+ para_wrap(pv_cpu_ops.write_idt_entry, vmi_write_idt_entry,
+ write_idt_entry, WriteIDTEntry);
para_wrap(pv_cpu_ops.load_sp0, vmi_load_sp0, set_kernel_stack, UpdateKernelStack);
para_fill(pv_cpu_ops.set_iopl_mask, SetIOPLMask);
para_fill(pv_cpu_ops.io_delay, IODelay);
diff --git a/arch/x86/lguest/boot.c b/arch/x86/lguest/boot.c
index aa0bdd5..b50c8ad 100644
--- a/arch/x86/lguest/boot.c
+++ b/arch/x86/lguest/boot.c
@@ -217,13 +217,14 @@ static void irq_enable(void)
* address of the handler, and... well, who cares? The Guest just asks the
* Host to make the change anyway, because the Host controls the real IDT.
*/
-static void lguest_write_idt_entry(struct desc_struct *dt,
- int entrynum, u32 low, u32 high)
+static void lguest_write_idt_entry(gate_desc *dt,
+ int entrynum, const gate_desc *g)
{
+ u32 *desc = (u32 *)g;
/* Keep the local copy up to date. */
- write_dt_entry(dt, entrynum, low, high);
+ native_write_idt_entry(dt, entrynum, g);
/* Tell Host about this new entry. */
- hcall(LHCALL_LOAD_IDT_ENTRY, entrynum, low, high);
+ hcall(LHCALL_LOAD_IDT_ENTRY, entrynum, desc[0], desc[1]);
}

/* Changing to a different IDT is very rare: we keep the IDT up-to-date every
diff --git a/arch/x86/xen/enlighten.c b/arch/x86/xen/enlighten.c
index 8215ea6..6dd349e 100644
--- a/arch/x86/xen/enlighten.c
+++ b/arch/x86/xen/enlighten.c
@@ -399,8 +399,7 @@ static DEFINE_PER_CPU(struct desc_ptr, idt_desc);

/* Set an IDT entry. If the entry is part of the current IDT, then
also update Xen. */
-static void xen_write_idt_entry(struct desc_struct *dt, int entrynum,
- u32 low, u32 high)
+static void xen_write_idt_entry(gate_desc *dt, int entrynum, const gate_desc *g)
{
unsigned long p = (unsigned long)&dt[entrynum];
unsigned long start, end;
@@ -412,14 +411,15 @@ static void xen_write_idt_entry(struct desc_struct *dt, int entrynum,

xen_mc_flush();

- write_dt_entry(dt, entrynum, low, high);
+ native_write_idt_entry(dt, entrynum, g);

if (p >= start && (p + 8) <= end) {
struct trap_info info[2];
+ u32 *desc = (u32 *)g;

info[1].address = 0;

- if (cvt_gate_to_trap(entrynum, low, high, &info[0]))
+ if (cvt_gate_to_trap(entrynum, desc[0], desc[1], &info[0]))
if (HYPERVISOR_set_trap_table(info))
BUG();
}
diff --git a/include/asm-x86/desc_32.h b/include/asm-x86/desc_32.h
index 77f1e5a..54b2314 100644
--- a/include/asm-x86/desc_32.h
+++ b/include/asm-x86/desc_32.h
@@ -70,9 +70,15 @@ static inline void pack_gate(gate_desc *gate,

#define write_ldt_entry(dt, entry, a, b) write_dt_entry(dt, entry, a, b)
#define write_gdt_entry(dt, entry, a, b) write_dt_entry(dt, entry, a, b)
-#define write_idt_entry(dt, entry, a, b) write_dt_entry(dt, entry, a, b)
+#define write_idt_entry(dt, entry, g) native_write_idt_entry(dt, entry, g)
#endif

+static inline void native_write_idt_entry(gate_desc *idt, int entry,
+ const gate_desc *gate)
+{
+ memcpy(&idt[entry], gate, sizeof(*gate));
+}
+
static inline void write_dt_entry(struct desc_struct *dt,
int entry, u32 entry_low, u32 entry_high)
{
@@ -142,7 +148,7 @@ static inline void _set_gate(int gate, unsigned int type, void *addr, unsigned s
{
gate_desc g;
pack_gate(&g, (unsigned long)addr, seg, type, 0);
- write_idt_entry(idt_table, gate, g.a, g.b);
+ write_idt_entry(idt_table, gate, &g);
}

static inline void __set_tss_desc(unsigned int cpu, unsigned int entry, const void *addr)
diff --git a/include/asm-x86/paravirt.h b/include/asm-x86/paravirt.h
index 0333fb6..86a9d7b 100644
--- a/include/asm-x86/paravirt.h
+++ b/include/asm-x86/paravirt.h
@@ -17,6 +17,7 @@
#include <linux/types.h>
#include <linux/cpumask.h>
#include <asm/kmap_types.h>
+#include <asm/desc_defs.h>

struct page;
struct thread_struct;
@@ -99,8 +100,8 @@ struct pv_cpu_ops {
int entrynum, u32 low, u32 high);
void (*write_gdt_entry)(struct desc_struct *,
int entrynum, u32 low, u32 high);
- void (*write_idt_entry)(struct desc_struct *,
- int entrynum, u32 low, u32 high);
+ void (*write_idt_entry)(gate_desc *,
+ int entrynum, const gate_desc *gate);
void (*load_sp0)(struct tss_struct *tss, struct thread_struct *t);

void (*set_iopl_mask)(unsigned mask);
@@ -667,9 +668,9 @@ static inline void write_gdt_entry(void *dt, int entry, u32 low, u32 high)
{
PVOP_VCALL4(pv_cpu_ops.write_gdt_entry, dt, entry, low, high);
}
-static inline void write_idt_entry(void *dt, int entry, u32 low, u32 high)
+static inline void write_idt_entry(gate_desc *dt, int entry, const gate_desc *g)
{
- PVOP_VCALL4(pv_cpu_ops.write_idt_entry, dt, entry, low, high);
+ PVOP_VCALL3(pv_cpu_ops.write_idt_entry, dt, entry, g);
}
static inline void set_iopl_mask(unsigned mask)
{
--
1.5.0.6

2007-12-13 17:00:54

by Glauber Costa

[permalink] [raw]
Subject: [PATCH 11/19] change write_gdt_entry signature.

This patch changes the write_gdt_entry function signature.
Instead of the old "a" and "b" parameters, it now receives
a pointer to a desc_struct, and the size of the entry being
handled. This is because x86_64 can have some 16-byte entries
as well as 8-byte ones.

Signed-off-by: Glauber de Oliveira Costa <[email protected]>
CC: Zachary Amsden <[email protected]>
CC: Jeremy Fitzhardinge <Jeremy.Fitzhardinge.citrix.com>
---
arch/x86/kernel/paravirt_32.c | 2 +-
arch/x86/kernel/smpcommon_32.c | 7 ++++---
arch/x86/kernel/vmi_32.c | 21 +++++++++++++++------
arch/x86/lguest/boot.c | 6 +++---
arch/x86/xen/enlighten.c | 11 +++++------
include/asm-x86/desc_32.h | 34 ++++++++++++++++++++++------------
include/asm-x86/paravirt.h | 9 ++++++---
7 files changed, 56 insertions(+), 34 deletions(-)

diff --git a/arch/x86/kernel/paravirt_32.c b/arch/x86/kernel/paravirt_32.c
index 13bbc99..77602c1 100644
--- a/arch/x86/kernel/paravirt_32.c
+++ b/arch/x86/kernel/paravirt_32.c
@@ -380,7 +380,7 @@ struct pv_cpu_ops pv_cpu_ops = {
.store_tr = native_store_tr,
.load_tls = native_load_tls,
.write_ldt_entry = write_dt_entry,
- .write_gdt_entry = write_dt_entry,
+ .write_gdt_entry = native_write_gdt_entry,
.write_idt_entry = native_write_idt_entry,
.load_sp0 = native_load_sp0,

diff --git a/arch/x86/kernel/smpcommon_32.c b/arch/x86/kernel/smpcommon_32.c
index bbfe85a..8bc38af 100644
--- a/arch/x86/kernel/smpcommon_32.c
+++ b/arch/x86/kernel/smpcommon_32.c
@@ -14,10 +14,11 @@ __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(&gdt[GDT_ENTRY_PERCPU],
__per_cpu_offset[cpu], 0xFFFFF,
- 0x80 | DESCTYPE_S | 0x2, 0x8);
+ 0x2 | DESCTYPE_S, 0x8);
+
+ gdt[GDT_ENTRY_PERCPU].s = 1;

per_cpu(this_cpu_off, cpu) = __per_cpu_offset[cpu];
per_cpu(cpu_number, cpu) = cpu;
diff --git a/arch/x86/kernel/vmi_32.c b/arch/x86/kernel/vmi_32.c
index a635b22..21edd0d 100644
--- a/arch/x86/kernel/vmi_32.c
+++ b/arch/x86/kernel/vmi_32.c
@@ -63,6 +63,7 @@ static struct {
void (*_set_ldt)(u32 selector);
void (*set_tr)(u32 selector);
void (*write_idt_entry)(struct desc_struct *, int, u32, u32);
+ void (*write_gdt_entry)(struct desc_struct *, int, u32, u32);
void (*set_kernel_stack)(u32 selector, u32 sp0);
void (*allocate_page)(u32, u32, u32, u32, u32);
void (*release_page)(u32, u32);
@@ -187,7 +188,7 @@ static void vmi_cpuid(unsigned int *ax, unsigned int *bx,
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);
+ write_gdt_entry(gdt, nr, new, 0);
}

static void vmi_load_tls(struct thread_struct *t, unsigned int cpu)
@@ -201,12 +202,12 @@ static void vmi_load_tls(struct thread_struct *t, unsigned int cpu)
static void vmi_set_ldt(const void *addr, unsigned entries)
{
unsigned cpu = smp_processor_id();
- u32 low, high;
+ struct desc_struct desc;

- pack_descriptor(&low, &high, (unsigned long)addr,
+ pack_descriptor(&desc, (unsigned long)addr,
entries * sizeof(struct desc_struct) - 1,
- DESCTYPE_LDT, 0);
- write_gdt_entry(get_cpu_gdt_table(cpu), GDT_ENTRY_LDT, low, high);
+ DESC_LDT, 0);
+ write_gdt_entry(get_cpu_gdt_table(cpu), GDT_ENTRY_LDT, &desc, DESC_LDT);
vmi_ops._set_ldt(entries ? GDT_ENTRY_LDT*sizeof(struct desc_struct) : 0);
}

@@ -221,6 +222,13 @@ static void vmi_write_idt_entry(gate_desc *dt, int entry, const gate_desc *g)
vmi_ops.write_idt_entry(dt, entry, idt_entry[0], idt_entry[2]);
}

+static void vmi_write_gdt_entry(struct desc_struct *dt, int entry,
+ const void *desc, int type)
+{
+ u32 *gdt_entry = (u32 *)desc;
+ vmi_ops.write_gdt_entry(dt, entry, gdt_entry[0], gdt_entry[2]);
+}
+
static void vmi_load_sp0(struct tss_struct *tss,
struct thread_struct *thread)
{
@@ -798,7 +806,8 @@ static inline int __init activate_vmi(void)
para_fill(pv_cpu_ops.store_tr, GetTR);
pv_cpu_ops.load_tls = vmi_load_tls;
para_fill(pv_cpu_ops.write_ldt_entry, WriteLDTEntry);
- para_fill(pv_cpu_ops.write_gdt_entry, WriteGDTEntry);
+ para_wrap(pv_cpu_ops.write_gdt_entry, vmi_write_gdt_entry,
+ write_gdt_entry, WriteGDTEntry);
para_wrap(pv_cpu_ops.write_idt_entry, vmi_write_idt_entry,
write_idt_entry, WriteIDTEntry);
para_wrap(pv_cpu_ops.load_sp0, vmi_load_sp0, set_kernel_stack, UpdateKernelStack);
diff --git a/arch/x86/lguest/boot.c b/arch/x86/lguest/boot.c
index b50c8ad..a633737 100644
--- a/arch/x86/lguest/boot.c
+++ b/arch/x86/lguest/boot.c
@@ -262,10 +262,10 @@ static void lguest_load_gdt(const struct desc_ptr *desc)
/* For a single GDT entry which changes, we do the lazy thing: alter our GDT,
* then tell the Host to reload the entire thing. This operation is so rare
* that this naive implementation is reasonable. */
-static void lguest_write_gdt_entry(struct desc_struct *dt,
- int entrynum, u32 low, u32 high)
+static void lguest_write_gdt_entry(struct desc_struct *dt, int entrynum,
+ const void *desc, int type)
{
- write_dt_entry(dt, entrynum, low, high);
+ native_write_gdt_entry(dt, entrynum, desc, type);
hcall(LHCALL_LOAD_GDT, __pa(dt), GDT_ENTRIES, 0);
}

diff --git a/arch/x86/xen/enlighten.c b/arch/x86/xen/enlighten.c
index 6dd349e..c38240c 100644
--- a/arch/x86/xen/enlighten.c
+++ b/arch/x86/xen/enlighten.c
@@ -475,22 +475,21 @@ static void xen_load_idt(const struct desc_ptr *desc)
/* Write a GDT descriptor entry. Ignore LDT descriptors, since
they're handled differently. */
static void xen_write_gdt_entry(struct desc_struct *dt, int entry,
- u32 low, u32 high)
+ const void *desc, int type)
{
preempt_disable();

- switch ((high >> 8) & 0xff) {
- case DESCTYPE_LDT:
- case DESCTYPE_TSS:
+ switch (type) {
+ case DESC_LDT:
+ case DESC_TSS:
/* ignore */
break;

default: {
xmaddr_t maddr = virt_to_machine(&dt[entry]);
- u64 desc = (u64)high << 32 | low;

xen_mc_flush();
- if (HYPERVISOR_update_descriptor(maddr.maddr, desc))
+ if (HYPERVISOR_update_descriptor(maddr.maddr, *(u64 *)desc))
BUG();
}

diff --git a/include/asm-x86/desc_32.h b/include/asm-x86/desc_32.h
index 0370099..41d8214 100644
--- a/include/asm-x86/desc_32.h
+++ b/include/asm-x86/desc_32.h
@@ -28,12 +28,13 @@ extern struct desc_ptr idt_descr;
extern gate_desc idt_table[];
extern void set_intr_gate(unsigned int irq, void * addr);

-static inline void pack_descriptor(__u32 *a, __u32 *b,
+static inline void pack_descriptor(struct desc_struct *desc,
unsigned long base, unsigned long limit, unsigned char type, unsigned char flags)
{
- *a = ((base & 0xffff) << 16) | (limit & 0xffff);
- *b = (base & 0xff000000) | ((base & 0xff0000) >> 16) |
+ desc->a = ((base & 0xffff) << 16) | (limit & 0xffff);
+ desc->b = (base & 0xff000000) | ((base & 0xff0000) >> 16) |
(limit & 0x000f0000) | ((type & 0xff) << 8) | ((flags & 0xf) << 20);
+ desc->p = 1;
}

static inline void pack_gate(gate_desc *gate,
@@ -69,7 +70,8 @@ static inline void pack_gate(gate_desc *gate,
#define set_ldt native_set_ldt

#define write_ldt_entry(dt, entry, a, b) write_dt_entry(dt, entry, a, b)
-#define write_gdt_entry(dt, entry, a, b) write_dt_entry(dt, entry, a, b)
+#define write_gdt_entry(dt, entry, desc, type) \
+ native_write_gdt_entry(dt, entry, desc, type)
#define write_idt_entry(dt, entry, g) native_write_idt_entry(dt, entry, g)
#endif

@@ -79,6 +81,12 @@ static inline void native_write_idt_entry(gate_desc *idt, int entry,
memcpy(&idt[entry], gate, sizeof(*gate));
}

+static inline void native_write_gdt_entry(struct desc_struct *gdt, int entry,
+ const void *desc, int type)
+{
+ memcpy(&gdt[entry], desc, sizeof(struct desc_struct));
+}
+
static inline void write_dt_entry(struct desc_struct *dt,
int entry, u32 entry_low, u32 entry_high)
{
@@ -86,18 +94,20 @@ static inline void write_dt_entry(struct desc_struct *dt,
dt[entry].b = entry_high;
}

+
static inline void native_set_ldt(const void *addr, unsigned int entries)
{
if (likely(entries == 0))
__asm__ __volatile__("lldt %w0"::"q" (0));
else {
unsigned cpu = smp_processor_id();
- __u32 a, b;
+ ldt_desc ldt;

- pack_descriptor(&a, &b, (unsigned long)addr,
+ pack_descriptor(&ldt, (unsigned long)addr,
entries * sizeof(struct desc_struct) - 1,
- DESCTYPE_LDT, 0);
- write_gdt_entry(get_cpu_gdt_table(cpu), GDT_ENTRY_LDT, a, b);
+ DESC_LDT, 0);
+ write_gdt_entry(get_cpu_gdt_table(cpu), GDT_ENTRY_LDT,
+ &ldt, DESC_LDT);
__asm__ __volatile__("lldt %w0"::"q" (GDT_ENTRY_LDT*8));
}
}
@@ -153,11 +163,11 @@ static inline void _set_gate(int gate, unsigned int type, void *addr, unsigned s

static inline void __set_tss_desc(unsigned int cpu, unsigned int entry, const void *addr)
{
- __u32 a, b;
- pack_descriptor(&a, &b, (unsigned long)addr,
+ tss_desc tss;
+ pack_descriptor(&tss, (unsigned long)addr,
offsetof(struct tss_struct, __cacheline_filler) - 1,
- DESCTYPE_TSS, 0);
- write_gdt_entry(get_cpu_gdt_table(cpu), entry, a, b);
+ DESC_TSS, 0);
+ write_gdt_entry(get_cpu_gdt_table(cpu), entry, &tss, DESC_TSS);
}


diff --git a/include/asm-x86/paravirt.h b/include/asm-x86/paravirt.h
index 86a9d7b..3f2abf2 100644
--- a/include/asm-x86/paravirt.h
+++ b/include/asm-x86/paravirt.h
@@ -99,7 +99,7 @@ struct pv_cpu_ops {
void (*write_ldt_entry)(struct desc_struct *,
int entrynum, u32 low, u32 high);
void (*write_gdt_entry)(struct desc_struct *,
- int entrynum, u32 low, u32 high);
+ int entrynum, const void *desc, int size);
void (*write_idt_entry)(gate_desc *,
int entrynum, const gate_desc *gate);
void (*load_sp0)(struct tss_struct *tss, struct thread_struct *t);
@@ -664,10 +664,13 @@ static inline void write_ldt_entry(void *dt, int entry, u32 low, u32 high)
{
PVOP_VCALL4(pv_cpu_ops.write_ldt_entry, dt, entry, low, high);
}
-static inline void write_gdt_entry(void *dt, int entry, u32 low, u32 high)
+
+static inline void write_gdt_entry(struct desc_struct *dt, int entry,
+ void *desc, int type)
{
- PVOP_VCALL4(pv_cpu_ops.write_gdt_entry, dt, entry, low, high);
+ PVOP_VCALL4(pv_cpu_ops.write_gdt_entry, dt, entry, desc, type);
}
+
static inline void write_idt_entry(gate_desc *dt, int entry, const gate_desc *g)
{
PVOP_VCALL3(pv_cpu_ops.write_idt_entry, dt, entry, g);
--
1.5.0.6

2007-12-13 17:08:00

by Glauber Costa

[permalink] [raw]
Subject: Re: [PATCH 0/19 -v4] desc_struct integration

Ingo Molnar wrote:
> * Glauber de Oliveira Costa <[email protected]> wrote:
>
>> Since the last version of it received no comments on the interfaces,
>> here it goes a version, that I feel ready for inclusion.
>>
>> The comments regarding style, specially the elimination of the
>> #defines in the desc_struct definition were merged. I also implemented
>> the vmi functions, missing last time.
>>
>> Ingo, in the absense of further complaints, could you please push to
>> the x86 tree?
>
> well i've already included v3 in x86.git (and it's pushed out), and that
> was looking good already in review and in testing - could you send a
> v3->v4 delta too?
Sure. The only real difference was Andi suggestion, but it was more
stylish. Will do soon.

2007-12-22 02:13:43

by Ingo Molnar

[permalink] [raw]
Subject: Re: [PATCH 18/19] move _set_gate and its users to a common location


* Glauber de Oliveira Costa <[email protected]> wrote:

> This patch moves _set_gate and its users to desc.h. We can now use
> common code for x86_64 and i386.

a few days ago i started seeing weird crashes on 64-bit x86 in the
random-kernel-bootup tests. Nothing truly reproducable to be bisectable,
but quality of x86.git went down drastically. Double faults, triple
faults, crashes all around the place, with every few dozen kernel
bootups.

Today i found a config and a workload that triggered the crashes a bit
more reliably. I still needed a 6 hours bisection marathon to pinpoint
the patch - the one in this thread. A review of it with H. Peter Anvin
pinpointed the breakage:

> +static inline void set_system_gate(unsigned int n, void *addr)
> +{
> + BUG_ON((unsigned)n > 0xFF);
> + _set_gate(n, GATE_TRAP, addr, 0x3, 0, __KERNEL_CS);
> +}

> -static inline void set_system_gate(int nr, void *func)
> -{
> - BUG_ON((unsigned)nr > 0xFF);
> - _set_gate(nr, GATE_INTERRUPT, (unsigned long) func, 3, 0);
> -}

you changed the type of system gates on 64-bit from GATE_INTERRUPT to
GATE_TRAP. The effect of this is that these gates enter with interrupts
enabled - instead of interrupts disabled. This, amongst others, affects
the following key gate:

set_system_gate(IA32_SYSCALL_VECTOR, ia32_syscall);

which relies on disabled interrupts to fix up its stack. If an interrupt
comes in the wrong moment then we get a kernel stack corruption that is
not survivable.

the reason for this bug was that you tried to do too many changes in a
single patch. You did a cleanup, you did unification and you moved code
around. It was totally non-obvious what you did and the resulting patch
was not reviewable at all - even after the bisection poinpointed the
patch, it took us almost 30 minutes to figure out where the bug was. If
this unstructured, careless mess of patches continues then we are not
going to be able to accept any more 64-bit paravirt patches into
x86.git.

Ingo