summaryrefslogtreecommitdiffstats
path: root/sys/i386
diff options
context:
space:
mode:
authorpeter <peter@FreeBSD.org>2005-04-13 22:57:17 +0000
committerpeter <peter@FreeBSD.org>2005-04-13 22:57:17 +0000
commit7bc6e7456ed8293645768a1f7523c733ff0c00d7 (patch)
treeaf5fd1903b9a4515ee70a0ddf85c5cd059996ab4 /sys/i386
parent47cf7426fa7b813ccf8268451588946defa747c2 (diff)
downloadFreeBSD-src-7bc6e7456ed8293645768a1f7523c733ff0c00d7.zip
FreeBSD-src-7bc6e7456ed8293645768a1f7523c733ff0c00d7.tar.gz
Change the segment limits to 4GB, we set the user accessible bit on all
of the kernel address space already. Intel recommend this anyway, because using a non-4GB limit adds an additional clock cycle to address generation. We were able to install 4GB segments into the LDT, so any limits we imposed on %cs and %ds were academic anyway. More importantly, this allows us to make a page in the kernel readable to user applications, for holding things like the signal trampoline and other fun things. Move the user %cs/%ds segments from the LDT to the GDT. There was no good reason for them to be there anyway. The old LDT entries are still there but we can now relax the restriction that prevented users from emptying the default LDT entries. Putting user and kernel %cs and %ds together allows us to access the fast sysenter/sysexit/syscall/sysret instructions. syscall/sysret in particular require that the user/kernel segments be laid out this way. Reserve a slot specifically for NDIS while here. Create two user controllable slots in the GDT that are context switched with the (kernel) thread. This allows user applications to set two user privilige selectors to arbitary values. Create i386_set_fsbase(void *base) and friends. (get/set, fs/gs). For i386, %gs is used by tls and the thread libraries and this means that user processes no longer have to have the cost of having a custom LDT, and we will no longer to do a ldt switch when activating a kthread/ithread in the usual case any more. In other words, we can now set the base address for %fs and %gs to arbitary addresses without the pain of messing with ldt segments.
Diffstat (limited to 'sys/i386')
-rw-r--r--sys/i386/i386/genassym.c2
-rw-r--r--sys/i386/i386/machdep.c138
-rw-r--r--sys/i386/i386/mp_machdep.c2
-rw-r--r--sys/i386/i386/swtch.s16
-rw-r--r--sys/i386/i386/sys_machdep.c63
-rw-r--r--sys/i386/include/pcb.h2
-rw-r--r--sys/i386/include/pcpu.h1
-rw-r--r--sys/i386/include/segments.h36
-rw-r--r--sys/i386/include/sysarch.h8
9 files changed, 201 insertions, 67 deletions
diff --git a/sys/i386/i386/genassym.c b/sys/i386/i386/genassym.c
index 9436237..0cb371c 100644
--- a/sys/i386/i386/genassym.c
+++ b/sys/i386/i386/genassym.c
@@ -134,6 +134,7 @@ ASSYM(PCB_PSL, offsetof(struct pcb, pcb_psl));
ASSYM(PCB_DBREGS, PCB_DBREGS);
ASSYM(PCB_EXT, offsetof(struct pcb, pcb_ext));
+ASSYM(PCB_FSD, offsetof(struct pcb, pcb_fsd));
ASSYM(PCB_VM86, offsetof(struct pcb, pcb_vm86));
ASSYM(PCB_FLAGS, offsetof(struct pcb, pcb_flags));
ASSYM(PCB_SAVEFPU, offsetof(struct pcb, pcb_save));
@@ -193,6 +194,7 @@ ASSYM(PC_CURPCB, offsetof(struct pcpu, pc_curpcb));
ASSYM(PC_COMMON_TSS, offsetof(struct pcpu, pc_common_tss));
ASSYM(PC_COMMON_TSSD, offsetof(struct pcpu, pc_common_tssd));
ASSYM(PC_TSS_GDT, offsetof(struct pcpu, pc_tss_gdt));
+ASSYM(PC_FSGS_GDT, offsetof(struct pcpu, pc_fsgs_gdt));
ASSYM(PC_CURRENTLDT, offsetof(struct pcpu, pc_currentldt));
ASSYM(PC_CPUID, offsetof(struct pcpu, pc_cpuid));
ASSYM(PC_CURPMAP, offsetof(struct pcpu, pc_curpmap));
diff --git a/sys/i386/i386/machdep.c b/sys/i386/i386/machdep.c
index bbd3fc1..40d88b4 100644
--- a/sys/i386/i386/machdep.c
+++ b/sys/i386/i386/machdep.c
@@ -1286,7 +1286,12 @@ static char dblfault_stack[PAGE_SIZE];
extern vm_offset_t proc0kstack;
-/* software prototypes -- in more palatable form */
+/*
+ * software prototypes -- in more palatable form.
+ *
+ * GCODE_SEL through GUDATA_SEL must be in this order for syscall/sysret
+ * GUFS_SEL and GUGS_SEL must be in this order (swtch.s knows it)
+ */
struct soft_segment_descriptor gdt_segs[] = {
/* GNULL_SEL 0 Null Descriptor */
{ 0x0, /* segment base address */
@@ -1297,7 +1302,34 @@ struct soft_segment_descriptor gdt_segs[] = {
0, 0,
0, /* default 32 vs 16 bit size */
0 /* limit granularity (byte/page units)*/ },
-/* GCODE_SEL 1 Code Descriptor for kernel */
+/* GPRIV_SEL 1 SMP Per-Processor Private Data Descriptor */
+{ 0x0, /* segment base address */
+ 0xfffff, /* length - all address space */
+ SDT_MEMRWA, /* segment type */
+ 0, /* segment descriptor priority level */
+ 1, /* segment descriptor present */
+ 0, 0,
+ 1, /* default 32 vs 16 bit size */
+ 1 /* limit granularity (byte/page units)*/ },
+/* GUFS_SEL 2 %fs Descriptor for user */
+{ 0x0, /* segment base address */
+ 0xfffff, /* length - all address space */
+ SDT_MEMRWA, /* segment type */
+ SEL_UPL, /* segment descriptor priority level */
+ 1, /* segment descriptor present */
+ 0, 0,
+ 1, /* default 32 vs 16 bit size */
+ 1 /* limit granularity (byte/page units)*/ },
+/* GUGS_SEL 3 %gs Descriptor for user */
+{ 0x0, /* segment base address */
+ 0xfffff, /* length - all address space */
+ SDT_MEMRWA, /* segment type */
+ SEL_UPL, /* segment descriptor priority level */
+ 1, /* segment descriptor present */
+ 0, 0,
+ 1, /* default 32 vs 16 bit size */
+ 1 /* limit granularity (byte/page units)*/ },
+/* GCODE_SEL 4 Code Descriptor for kernel */
{ 0x0, /* segment base address */
0xfffff, /* length - all address space */
SDT_MEMERA, /* segment type */
@@ -1306,7 +1338,7 @@ struct soft_segment_descriptor gdt_segs[] = {
0, 0,
1, /* default 32 vs 16 bit size */
1 /* limit granularity (byte/page units)*/ },
-/* GDATA_SEL 2 Data Descriptor for kernel */
+/* GDATA_SEL 5 Data Descriptor for kernel */
{ 0x0, /* segment base address */
0xfffff, /* length - all address space */
SDT_MEMRWA, /* segment type */
@@ -1315,16 +1347,34 @@ struct soft_segment_descriptor gdt_segs[] = {
0, 0,
1, /* default 32 vs 16 bit size */
1 /* limit granularity (byte/page units)*/ },
-/* GPRIV_SEL 3 SMP Per-Processor Private Data Descriptor */
+/* GUCODE_SEL 6 Code Descriptor for user */
+{ 0x0, /* segment base address */
+ 0xfffff, /* length - all address space */
+ SDT_MEMERA, /* segment type */
+ SEL_UPL, /* segment descriptor priority level */
+ 1, /* segment descriptor present */
+ 0, 0,
+ 1, /* default 32 vs 16 bit size */
+ 1 /* limit granularity (byte/page units)*/ },
+/* GUDATA_SEL 7 Data Descriptor for user */
{ 0x0, /* segment base address */
0xfffff, /* length - all address space */
SDT_MEMRWA, /* segment type */
+ SEL_UPL, /* segment descriptor priority level */
+ 1, /* segment descriptor present */
+ 0, 0,
+ 1, /* default 32 vs 16 bit size */
+ 1 /* limit granularity (byte/page units)*/ },
+/* GBIOSLOWMEM_SEL 8 BIOS access to realmode segment 0x40, must be #8 in GDT */
+{ 0x400, /* segment base address */
+ 0xfffff, /* length */
+ SDT_MEMRWA, /* segment type */
0, /* segment descriptor priority level */
1, /* segment descriptor present */
0, 0,
1, /* default 32 vs 16 bit size */
1 /* limit granularity (byte/page units)*/ },
-/* GPROC0_SEL 4 Proc 0 Tss Descriptor */
+/* GPROC0_SEL 9 Proc 0 Tss Descriptor */
{
0x0, /* segment base address */
sizeof(struct i386tss)-1,/* length */
@@ -1334,7 +1384,7 @@ struct soft_segment_descriptor gdt_segs[] = {
0, 0,
0, /* unused - default 32 vs 16 bit size */
0 /* limit granularity (byte/page units)*/ },
-/* GLDT_SEL 5 LDT Descriptor */
+/* GLDT_SEL 10 LDT Descriptor */
{ (int) ldt, /* segment base address */
sizeof(ldt)-1, /* length - all address space */
SDT_SYSLDT, /* segment type */
@@ -1343,7 +1393,7 @@ struct soft_segment_descriptor gdt_segs[] = {
0, 0,
0, /* unused - default 32 vs 16 bit size */
0 /* limit granularity (byte/page units)*/ },
-/* GUSERLDT_SEL 6 User LDT Descriptor per process */
+/* GUSERLDT_SEL 11 User LDT Descriptor per process */
{ (int) ldt, /* segment base address */
(512 * sizeof(union descriptor)-1), /* length */
SDT_SYSLDT, /* segment type */
@@ -1352,25 +1402,7 @@ struct soft_segment_descriptor gdt_segs[] = {
0, 0,
0, /* unused - default 32 vs 16 bit size */
0 /* limit granularity (byte/page units)*/ },
-/* GTGATE_SEL 7 Null Descriptor - Placeholder */
-{ 0x0, /* segment base address */
- 0x0, /* length - all address space */
- 0, /* segment type */
- 0, /* segment descriptor priority level */
- 0, /* segment descriptor present */
- 0, 0,
- 0, /* default 32 vs 16 bit size */
- 0 /* limit granularity (byte/page units)*/ },
-/* GBIOSLOWMEM_SEL 8 BIOS access to realmode segment 0x40, must be #8 in GDT */
-{ 0x400, /* segment base address */
- 0xfffff, /* length */
- SDT_MEMRWA, /* segment type */
- 0, /* segment descriptor priority level */
- 1, /* segment descriptor present */
- 0, 0,
- 1, /* default 32 vs 16 bit size */
- 1 /* limit granularity (byte/page units)*/ },
-/* GPANIC_SEL 9 Panic Tss Descriptor */
+/* GPANIC_SEL 12 Panic Tss Descriptor */
{ (int) &dblfault_tss, /* segment base address */
sizeof(struct i386tss)-1,/* length - all address space */
SDT_SYS386TSS, /* segment type */
@@ -1379,7 +1411,7 @@ struct soft_segment_descriptor gdt_segs[] = {
0, 0,
0, /* unused - default 32 vs 16 bit size */
0 /* limit granularity (byte/page units)*/ },
-/* GBIOSCODE32_SEL 10 BIOS 32-bit interface (32bit Code) */
+/* GBIOSCODE32_SEL 13 BIOS 32-bit interface (32bit Code) */
{ 0, /* segment base address (overwritten) */
0xfffff, /* length */
SDT_MEMERA, /* segment type */
@@ -1388,7 +1420,7 @@ struct soft_segment_descriptor gdt_segs[] = {
0, 0,
0, /* default 32 vs 16 bit size */
1 /* limit granularity (byte/page units)*/ },
-/* GBIOSCODE16_SEL 11 BIOS 32-bit interface (16bit Code) */
+/* GBIOSCODE16_SEL 14 BIOS 32-bit interface (16bit Code) */
{ 0, /* segment base address (overwritten) */
0xfffff, /* length */
SDT_MEMERA, /* segment type */
@@ -1397,7 +1429,7 @@ struct soft_segment_descriptor gdt_segs[] = {
0, 0,
0, /* default 32 vs 16 bit size */
1 /* limit granularity (byte/page units)*/ },
-/* GBIOSDATA_SEL 12 BIOS 32-bit interface (Data) */
+/* GBIOSDATA_SEL 15 BIOS 32-bit interface (Data) */
{ 0, /* segment base address (overwritten) */
0xfffff, /* length */
SDT_MEMRWA, /* segment type */
@@ -1406,7 +1438,7 @@ struct soft_segment_descriptor gdt_segs[] = {
0, 0,
1, /* default 32 vs 16 bit size */
1 /* limit granularity (byte/page units)*/ },
-/* GBIOSUTIL_SEL 13 BIOS 16-bit interface (Utility) */
+/* GBIOSUTIL_SEL 16 BIOS 16-bit interface (Utility) */
{ 0, /* segment base address (overwritten) */
0xfffff, /* length */
SDT_MEMRWA, /* segment type */
@@ -1415,7 +1447,7 @@ struct soft_segment_descriptor gdt_segs[] = {
0, 0,
0, /* default 32 vs 16 bit size */
1 /* limit granularity (byte/page units)*/ },
-/* GBIOSARGS_SEL 14 BIOS 16-bit interface (Arguments) */
+/* GBIOSARGS_SEL 17 BIOS 16-bit interface (Arguments) */
{ 0, /* segment base address (overwritten) */
0xfffff, /* length */
SDT_MEMRWA, /* segment type */
@@ -1424,6 +1456,15 @@ struct soft_segment_descriptor gdt_segs[] = {
0, 0,
0, /* default 32 vs 16 bit size */
1 /* limit granularity (byte/page units)*/ },
+/* GNDIS_SEL 18 NDIS Descriptor */
+{ 0x0, /* segment base address */
+ 0x0, /* length */
+ 0, /* segment type */
+ 0, /* segment descriptor priority level */
+ 0, /* segment descriptor present */
+ 0, 0,
+ 0, /* default 32 vs 16 bit size */
+ 0 /* limit granularity (byte/page units)*/ },
};
static struct soft_segment_descriptor ldt_segs[] = {
@@ -1999,25 +2040,22 @@ init386(first)
init_param1();
/*
- * make gdt memory segments, the code segment goes up to end of the
- * page with etext in it, the data segment goes to the end of
- * the address space
- */
- /*
- * XXX text protection is temporarily (?) disabled. The limit was
- * i386_btop(round_page(etext)) - 1.
+ * Make gdt memory segments. All segments cover the full 4GB
+ * of address space and permissions are enforced at page level.
*/
gdt_segs[GCODE_SEL].ssd_limit = atop(0 - 1);
gdt_segs[GDATA_SEL].ssd_limit = atop(0 - 1);
+ gdt_segs[GUCODE_SEL].ssd_limit = atop(0 - 1);
+ gdt_segs[GUDATA_SEL].ssd_limit = atop(0 - 1);
+ gdt_segs[GUFS_SEL].ssd_limit = atop(0 - 1);
+ gdt_segs[GUGS_SEL].ssd_limit = atop(0 - 1);
+
#ifdef SMP
pc = &SMP_prvspace[0].pcpu;
- gdt_segs[GPRIV_SEL].ssd_limit =
- atop(sizeof(struct privatespace) - 1);
#else
pc = &__pcpu;
- gdt_segs[GPRIV_SEL].ssd_limit =
- atop(sizeof(struct pcpu) - 1);
#endif
+ gdt_segs[GPRIV_SEL].ssd_limit = atop(0 - 1);
gdt_segs[GPRIV_SEL].ssd_base = (int) pc;
gdt_segs[GPROC0_SEL].ssd_base = (int) &pc->pc_common_tss;
@@ -2046,12 +2084,8 @@ init386(first)
mtx_init(&icu_lock, "icu", NULL, MTX_SPIN | MTX_NOWITNESS);
/* make ldt memory segments */
- /*
- * XXX - VM_MAXUSER_ADDRESS is an end address, not a max. And it
- * should be spelled ...MAX_USER...
- */
- ldt_segs[LUCODE_SEL].ssd_limit = atop(VM_MAXUSER_ADDRESS - 1);
- ldt_segs[LUDATA_SEL].ssd_limit = atop(VM_MAXUSER_ADDRESS - 1);
+ ldt_segs[LUCODE_SEL].ssd_limit = atop(0 - 1);
+ ldt_segs[LUDATA_SEL].ssd_limit = atop(0 - 1);
for (x = 0; x < sizeof ldt_segs / sizeof ldt_segs[0]; x++)
ssdtosd(&ldt_segs[x], &ldt[x].sd);
@@ -2151,6 +2185,9 @@ init386(first)
PCPU_SET(common_tss.tss_ioopt, (sizeof (struct i386tss)) << 16);
ltr(gsel_tss);
+ /* pointer to selector slot for %fs/%gs */
+ PCPU_SET(fsgs_gdt, &gdt[GUFS_SEL].sd);
+
dblfault_tss.tss_esp = dblfault_tss.tss_esp0 = dblfault_tss.tss_esp1 =
dblfault_tss.tss_esp2 = (int)&dblfault_stack[sizeof(dblfault_stack)];
dblfault_tss.tss_ss = dblfault_tss.tss_ss0 = dblfault_tss.tss_ss1 =
@@ -2193,13 +2230,14 @@ init386(first)
gdp->gd_hioffset = x >> 16;
/* XXX does this work? */
+ /* XXX yes! */
ldt[LBSDICALLS_SEL] = ldt[LSYS5CALLS_SEL];
ldt[LSOL26CALLS_SEL] = ldt[LSYS5CALLS_SEL];
/* transfer to user mode */
- _ucodesel = LSEL(LUCODE_SEL, SEL_UPL);
- _udatasel = LSEL(LUDATA_SEL, SEL_UPL);
+ _ucodesel = GSEL(GUCODE_SEL, SEL_UPL);
+ _udatasel = GSEL(GUDATA_SEL, SEL_UPL);
/* setup proc 0's pcb */
thread0.td_pcb->pcb_flags = 0; /* XXXKSE */
diff --git a/sys/i386/i386/mp_machdep.c b/sys/i386/i386/mp_machdep.c
index bb316e8..d601f6d 100644
--- a/sys/i386/i386/mp_machdep.c
+++ b/sys/i386/i386/mp_machdep.c
@@ -467,6 +467,8 @@ init_secondary(void)
PCPU_SET(common_tssd, *PCPU_GET(tss_gdt));
ltr(gsel_tss);
+ PCPU_SET(fsgs_gdt, &gdt[myid * NGDT + GUFS_SEL].sd);
+
/*
* Set to a known state:
* Set by mpboot.s: CR0_PG, CR0_PE
diff --git a/sys/i386/i386/swtch.s b/sys/i386/i386/swtch.s
index 96e2b25..f1404c3 100644
--- a/sys/i386/i386/swtch.s
+++ b/sys/i386/i386/swtch.s
@@ -220,13 +220,25 @@ sw1:
/* Move correct tss descriptor into GDT slot, then reload tr. */
movl PCPU(TSS_GDT), %ebx /* entry in GDT */
movl 0(%edi), %eax
+ movl 4(%edi), %esi
movl %eax, 0(%ebx)
- movl 4(%edi), %eax
- movl %eax, 4(%ebx)
+ movl %esi, 4(%ebx)
movl $GPROC0_SEL*8, %esi /* GSEL(entry, SEL_KPL) */
ltr %si
3:
+ /* Copy the %fs and %gs selectors into this pcpu gdt */
+ leal PCB_FSD(%edx), %esi
+ movl PCPU(FSGS_GDT), %edi
+ movl 0(%esi), %eax /* %fs selector */
+ movl 4(%esi), %ebx
+ movl %eax, 0(%edi)
+ movl %ebx, 4(%edi)
+ movl 8(%esi), %eax /* %gs selector, comes straight after */
+ movl 12(%esi), %ebx
+ movl %eax, 8(%edi)
+ movl %ebx, 12(%edi)
+
/* Restore context. */
movl PCB_EBX(%edx),%ebx
movl PCB_ESP(%edx),%esp
diff --git a/sys/i386/i386/sys_machdep.c b/sys/i386/i386/sys_machdep.c
index 5738e1f..129de2b 100644
--- a/sys/i386/i386/sys_machdep.c
+++ b/sys/i386/i386/sys_machdep.c
@@ -90,6 +90,8 @@ sysarch(td, uap)
struct i386_ldt_args largs;
struct i386_ioperm_args iargs;
} kargs;
+ uint32_t base;
+ struct segment_descriptor sd, *sdp;
switch (uap->op) {
case I386_GET_IOPERM:
@@ -145,6 +147,67 @@ sysarch(td, uap)
case I386_VM86:
error = vm86_sysarch(td, uap->parms);
break;
+ case I386_GET_FSBASE:
+ sdp = &td->td_pcb->pcb_fsd;
+ base = sdp->sd_hibase << 24 | sdp->sd_lobase;
+ error = copyout(&base, uap->parms, sizeof(base));
+ break;
+ case I386_SET_FSBASE:
+ error = copyin(uap->parms, &base, sizeof(base));
+ if (!error) {
+ /*
+ * Construct a descriptor and store it in the pcb for
+ * the next context switch. Also store it in the gdt
+ * so that the load of tf_fs into %fs will activate it
+ * at return to userland.
+ */
+ sd.sd_lobase = base & 0xffffff;
+ sd.sd_hibase = (base >> 24) & 0xff;
+ sd.sd_lolimit = 0xffff; /* 4GB limit, wraps around */
+ sd.sd_hilimit = 0xf;
+ sd.sd_type = SDT_MEMRWA;
+ sd.sd_dpl = SEL_UPL;
+ sd.sd_p = 1;
+ sd.sd_xx = 0;
+ sd.sd_def32 = 1;
+ sd.sd_gran = 1;
+ mtx_lock_spin(&sched_lock);
+ td->td_pcb->pcb_fsd = sd;
+ PCPU_GET(fsgs_gdt)[0] = sd;
+ td->td_frame->tf_fs = GSEL(GUFS_SEL, SEL_UPL);
+ mtx_unlock_spin(&sched_lock);
+ }
+ break;
+ case I386_GET_GSBASE:
+ sdp = &td->td_pcb->pcb_gsd;
+ base = sdp->sd_hibase << 24 | sdp->sd_lobase;
+ error = copyout(&base, uap->parms, sizeof(base));
+ break;
+ case I386_SET_GSBASE:
+ error = copyin(uap->parms, &base, sizeof(base));
+ if (!error) {
+ /*
+ * Construct a descriptor and store it in the pcb for
+ * the next context switch. Also store it in the gdt
+ * because we have to do a load_gs() right now.
+ */
+ sd.sd_lobase = base & 0xffffff;
+ sd.sd_hibase = (base >> 24) & 0xff;
+ sd.sd_lolimit = 0xffff; /* 4GB limit, wraps around */
+ sd.sd_hilimit = 0xf;
+ sd.sd_type = SDT_MEMRWA;
+ sd.sd_dpl = SEL_UPL;
+ sd.sd_p = 1;
+ sd.sd_xx = 0;
+ sd.sd_def32 = 1;
+ sd.sd_gran = 1;
+ mtx_lock_spin(&sched_lock);
+ td->td_pcb->pcb_gsd = sd;
+ PCPU_GET(fsgs_gdt)[1] = sd;
+ load_gs(GSEL(GUGS_SEL, SEL_UPL));
+ mtx_unlock_spin(&sched_lock);
+ }
+ break;
default:
error = EINVAL;
break;
diff --git a/sys/i386/include/pcb.h b/sys/i386/include/pcb.h
index c6ae09f..be415c2 100644
--- a/sys/i386/include/pcb.h
+++ b/sys/i386/include/pcb.h
@@ -67,6 +67,8 @@ struct pcb {
caddr_t pcb_onfault; /* copyin/out fault recovery */
int pcb_gs;
+ struct segment_descriptor pcb_fsd;
+ struct segment_descriptor pcb_gsd;
struct pcb_ext *pcb_ext; /* optional pcb extension */
int pcb_psl; /* process status long */
void (*pcb_switchout)(void); /* Special switchout function. */
diff --git a/sys/i386/include/pcpu.h b/sys/i386/include/pcpu.h
index f371e39..6312b97 100644
--- a/sys/i386/include/pcpu.h
+++ b/sys/i386/include/pcpu.h
@@ -51,6 +51,7 @@
struct i386tss pc_common_tss; \
struct segment_descriptor pc_common_tssd; \
struct segment_descriptor *pc_tss_gdt; \
+ struct segment_descriptor *pc_fsgs_gdt; \
int pc_currentldt; \
u_int pc_acpi_id; \
u_int pc_apic_id
diff --git a/sys/i386/include/segments.h b/sys/i386/include/segments.h
index 569c5c8..351ff5d 100644
--- a/sys/i386/include/segments.h
+++ b/sys/i386/include/segments.h
@@ -199,24 +199,30 @@ struct region_descriptor {
/*
* Entries in the Global Descriptor Table (GDT)
+ * Note that each 4 entries share a single 32 byte L1 cache line.
+ * Some of the fast syscall instructions require a specific order here.
*/
#define GNULL_SEL 0 /* Null Descriptor */
-#define GCODE_SEL 1 /* Kernel Code Descriptor */
-#define GDATA_SEL 2 /* Kernel Data Descriptor */
-#define GPRIV_SEL 3 /* SMP Per-Processor Private Data */
-#define GPROC0_SEL 4 /* Task state process slot zero and up */
-#define GLDT_SEL 5 /* LDT - eventually one per process */
-#define GUSERLDT_SEL 6 /* User LDT */
-#define GTGATE_SEL 7 /* Process task switch gate */
+#define GPRIV_SEL 1 /* SMP Per-Processor Private Data */
+#define GUFS_SEL 2 /* User %fs Descriptor (order critical: 1) */
+#define GUGS_SEL 3 /* User %gs Descriptor (order critical: 2) */
+#define GCODE_SEL 4 /* Kernel Code Descriptor (order critical: 1) */
+#define GDATA_SEL 5 /* Kernel Data Descriptor (order critical: 2) */
+#define GUCODE_SEL 6 /* User Code Descriptor (order critical: 3) */
+#define GUDATA_SEL 7 /* User Data Descriptor (order critical: 4) */
#define GBIOSLOWMEM_SEL 8 /* BIOS low memory access (must be entry 8) */
-#define GPANIC_SEL 9 /* Task state to consider panic from */
-#define GBIOSCODE32_SEL 10 /* BIOS interface (32bit Code) */
-#define GBIOSCODE16_SEL 11 /* BIOS interface (16bit Code) */
-#define GBIOSDATA_SEL 12 /* BIOS interface (Data) */
-#define GBIOSUTIL_SEL 13 /* BIOS interface (Utility) */
-#define GBIOSARGS_SEL 14 /* BIOS interface (Arguments) */
-
-#define NGDT 15
+#define GPROC0_SEL 9 /* Task state process slot zero and up */
+#define GLDT_SEL 10 /* Default User LDT */
+#define GUSERLDT_SEL 11 /* User LDT */
+#define GPANIC_SEL 12 /* Task state to consider panic from */
+#define GBIOSCODE32_SEL 13 /* BIOS interface (32bit Code) */
+#define GBIOSCODE16_SEL 14 /* BIOS interface (16bit Code) */
+#define GBIOSDATA_SEL 15 /* BIOS interface (Data) */
+#define GBIOSUTIL_SEL 16 /* BIOS interface (Utility) */
+#define GBIOSARGS_SEL 17 /* BIOS interface (Arguments) */
+#define GNDIS_SEL 18 /* For the NDIS layer */
+
+#define NGDT 19
/*
* Entries in the Local Descriptor Table (LDT)
diff --git a/sys/i386/include/sysarch.h b/sys/i386/include/sysarch.h
index 899ebd8..454d64c 100644
--- a/sys/i386/include/sysarch.h
+++ b/sys/i386/include/sysarch.h
@@ -43,6 +43,10 @@
#define I386_SET_IOPERM 4
/* xxxxx */
#define I386_VM86 6
+#define I386_GET_FSBASE 7
+#define I386_SET_FSBASE 8
+#define I386_GET_GSBASE 9
+#define I386_SET_GSBASE 10
/* These four only exist when running an i386 binary on amd64 */
#define _AMD64_GET_FSBASE 128
@@ -84,6 +88,10 @@ int i386_set_ldt(int, union descriptor *, int);
int i386_get_ioperm(unsigned int, unsigned int *, int *);
int i386_set_ioperm(unsigned int, unsigned int, int);
int i386_vm86(int, void *);
+int i386_get_fsbase(void **);
+int i386_get_gsbase(void **);
+int i386_set_fsbase(void *);
+int i386_set_gsbase(void *);
int i386_set_watch(int, unsigned int, int, int, struct dbreg *);
int i386_clr_watch(int, struct dbreg *);
int sysarch(int, void *);
OpenPOWER on IntegriCloud