summaryrefslogtreecommitdiffstats
path: root/sys/amd64/amd64/mp_machdep.c
diff options
context:
space:
mode:
authorkib <kib@FreeBSD.org>2009-04-01 13:09:26 +0000
committerkib <kib@FreeBSD.org>2009-04-01 13:09:26 +0000
commit253f7779bc4142bb2814f0f44999bc0e48e9bbe5 (patch)
treeb58cda2045e48f43c2d8ff644f3d5c3a859f6e99 /sys/amd64/amd64/mp_machdep.c
parentd2c67f9684a76233c58b569abc3a56c24f6a64db (diff)
downloadFreeBSD-src-253f7779bc4142bb2814f0f44999bc0e48e9bbe5.zip
FreeBSD-src-253f7779bc4142bb2814f0f44999bc0e48e9bbe5.tar.gz
Save and restore segment registers on amd64 when entering and leaving
the kernel on amd64. Fill and read segment registers for mcontext and signals. Handle traps caused by restoration of the invalidated selectors. Implement user-mode creation and manipulation of the process-specific LDT descriptors for amd64, see sysarch(2). Implement support for TSS i/o port access permission bitmap for amd64. Context-switch LDT and TSS. Do not save and restore segment registers on the context switch, that is handled by kernel enter/leave trampolines now. Remove segment restore code from the signal trampolines for freebsd/amd64, freebsd/ia32 and linux/i386 for the same reason. Implement amd64-specific compat shims for sysarch. Linuxolator (temporary ?) switched to use gsbase for thread_area pointer. TODO: Currently, gdb is not adapted to show segment registers from struct reg. Also, no machine-depended ptrace command is added to set segment registers for debugged process. In collaboration with: pho Discussed with: peter Reviewed by: jhb Linuxolator tested by: dchagin
Diffstat (limited to 'sys/amd64/amd64/mp_machdep.c')
-rw-r--r--sys/amd64/amd64/mp_machdep.c20
1 files changed, 13 insertions, 7 deletions
diff --git a/sys/amd64/amd64/mp_machdep.c b/sys/amd64/amd64/mp_machdep.c
index b7c03d9..59e3e9b 100644
--- a/sys/amd64/amd64/mp_machdep.c
+++ b/sys/amd64/amd64/mp_machdep.c
@@ -101,8 +101,6 @@ extern pt_entry_t *KPTphys;
/* SMP page table page */
extern pt_entry_t *SMPpt;
-extern int _udatasel;
-
struct pcb stoppcbs[MAXCPU];
struct xpcb *stopxpcbs = NULL;
@@ -463,7 +461,8 @@ init_secondary(void)
/* Init tss */
common_tss[cpu] = common_tss[0];
common_tss[cpu].tss_rsp0 = 0; /* not used until after switch */
- common_tss[cpu].tss_iobase = sizeof(struct amd64tss);
+ common_tss[cpu].tss_iobase = sizeof(struct amd64tss) +
+ IOPAGES * PAGE_SIZE;
common_tss[cpu].tss_ist1 = (long)&doublefault_stack[PAGE_SIZE];
/* The NMI stack runs on IST2. */
@@ -472,12 +471,13 @@ init_secondary(void)
/* Prepare private GDT */
gdt_segs[GPROC0_SEL].ssd_base = (long) &common_tss[cpu];
- ssdtosyssd(&gdt_segs[GPROC0_SEL],
- (struct system_segment_descriptor *)&gdt[NGDT * cpu + GPROC0_SEL]);
for (x = 0; x < NGDT; x++) {
- if (x != GPROC0_SEL && x != (GPROC0_SEL + 1))
+ if (x != GPROC0_SEL && x != (GPROC0_SEL + 1) &&
+ x != GUSERLDT_SEL && x != (GUSERLDT_SEL + 1))
ssdtosd(&gdt_segs[x], &gdt[NGDT * cpu + x]);
}
+ ssdtosyssd(&gdt_segs[GPROC0_SEL],
+ (struct system_segment_descriptor *)&gdt[NGDT * cpu + GPROC0_SEL]);
ap_gdt.rd_limit = NGDT * sizeof(gdt[0]) - 1;
ap_gdt.rd_base = (long) &gdt[NGDT * cpu];
lgdt(&ap_gdt); /* does magic intra-segment return */
@@ -491,8 +491,14 @@ init_secondary(void)
pc->pc_prvspace = pc;
pc->pc_curthread = 0;
pc->pc_tssp = &common_tss[cpu];
+ pc->pc_commontssp = &common_tss[cpu];
pc->pc_rsp0 = 0;
+ pc->pc_tss = (struct system_segment_descriptor *)&gdt[NGDT * cpu +
+ GPROC0_SEL];
+ pc->pc_fs32p = &gdt[NGDT * cpu + GUFS32_SEL];
pc->pc_gs32p = &gdt[NGDT * cpu + GUGS32_SEL];
+ pc->pc_ldt = (struct system_segment_descriptor *)&gdt[NGDT * cpu +
+ GUSERLDT_SEL];
/* Save the per-cpu pointer for use by the NMI handler. */
np->np_pcpu = (register_t) pc;
@@ -601,7 +607,7 @@ init_secondary(void)
load_cr4(rcr4() | CR4_PGE);
load_ds(_udatasel);
load_es(_udatasel);
- load_fs(_udatasel);
+ load_fs(_ufssel);
mtx_unlock_spin(&ap_boot_mtx);
/* wait until all the AP's are up */
OpenPOWER on IntegriCloud