summaryrefslogtreecommitdiffstats
path: root/sys/amd64
diff options
context:
space:
mode:
authorbde <bde@FreeBSD.org>1997-06-07 04:36:10 +0000
committerbde <bde@FreeBSD.org>1997-06-07 04:36:10 +0000
commit6babbddd762aaa221ade16215d4b4e93bb669f79 (patch)
tree9369720c6fe0f8bc2adda5e0852adf5a669345ef /sys/amd64
parent093956d0d4afe268c9113da9f84c22d843b9e750 (diff)
downloadFreeBSD-src-6babbddd762aaa221ade16215d4b4e93bb669f79.zip
FreeBSD-src-6babbddd762aaa221ade16215d4b4e93bb669f79.tar.gz
Preserve %fs and %gs across context switches. This has a relatively low
cost since it is only done in cpu_switch(), not for every exception. The extra state is kept in the pcb, and handled much like the npx state, with similar deficiencies (the state is not preserved across signal handlers, and error handling loses state).
Diffstat (limited to 'sys/amd64')
-rw-r--r--sys/amd64/amd64/cpu_switch.S14
-rw-r--r--sys/amd64/amd64/genassym.c4
-rw-r--r--sys/amd64/amd64/machdep.c10
-rw-r--r--sys/amd64/amd64/swtch.s14
-rw-r--r--sys/amd64/amd64/trap.c21
-rw-r--r--sys/amd64/include/md_var.h4
-rw-r--r--sys/amd64/include/pcb.h6
-rw-r--r--sys/amd64/include/reg.h14
8 files changed, 78 insertions, 9 deletions
diff --git a/sys/amd64/amd64/cpu_switch.S b/sys/amd64/amd64/cpu_switch.S
index 094e75b..923d694 100644
--- a/sys/amd64/amd64/cpu_switch.S
+++ b/sys/amd64/amd64/cpu_switch.S
@@ -33,7 +33,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $Id: swtch.s,v 1.50 1997/05/29 05:11:11 peter Exp $
+ * $Id: swtch.s,v 1.51 1997/05/31 09:27:29 peter Exp $
*/
#include "npx.h"
@@ -336,6 +336,8 @@ ENTRY(cpu_switch)
movl %ebp,PCB_EBP(%ecx)
movl %esi,PCB_ESI(%ecx)
movl %edi,PCB_EDI(%ecx)
+ movl %fs,PCB_FS(%ecx)
+ movl %gs,PCB_GS(%ecx)
#ifdef SMP
movl _mp_lock, %eax
@@ -562,6 +564,14 @@ swtch_com:
2:
#endif
+ /* This must be done after loading the user LDT. */
+ .globl cpu_switch_load_fs
+cpu_switch_load_fs:
+ movl PCB_FS(%edx),%fs
+ .globl cpu_switch_load_gs
+cpu_switch_load_gs:
+ movl PCB_GS(%edx),%gs
+
sti
ret
@@ -592,6 +602,8 @@ ENTRY(savectx)
movl %ebp,PCB_EBP(%ecx)
movl %esi,PCB_ESI(%ecx)
movl %edi,PCB_EDI(%ecx)
+ movl %fs,PCB_FS(%ecx)
+ movl %gs,PCB_GS(%ecx)
#if NNPX > 0
/*
diff --git a/sys/amd64/amd64/genassym.c b/sys/amd64/amd64/genassym.c
index 18ecadc..d9473cf 100644
--- a/sys/amd64/amd64/genassym.c
+++ b/sys/amd64/amd64/genassym.c
@@ -34,7 +34,7 @@
* SUCH DAMAGE.
*
* from: @(#)genassym.c 5.11 (Berkeley) 5/10/91
- * $Id: genassym.c,v 1.45 1997/04/26 11:45:06 peter Exp $
+ * $Id: genassym.c,v 1.46 1997/05/10 08:01:13 bde Exp $
*/
#include <stdio.h>
@@ -127,6 +127,8 @@ main()
printf("#define\tPCB_EIP %p\n", &pcb->pcb_eip);
printf("#define\tTSS_ESP0 %p\n", &tss->tss_esp0);
printf("#define\tPCB_USERLDT %p\n", &pcb->pcb_ldt);
+ printf("#define\tPCB_FS %p\n", &pcb->pcb_fs);
+ printf("#define\tPCB_GS %p\n", &pcb->pcb_gs);
#ifdef SMP
printf("#define\tPCB_MPNEST %p\n", &pcb->pcb_mpnest);
#endif
diff --git a/sys/amd64/amd64/machdep.c b/sys/amd64/amd64/machdep.c
index 186541c..b59d92e 100644
--- a/sys/amd64/amd64/machdep.c
+++ b/sys/amd64/amd64/machdep.c
@@ -35,7 +35,7 @@
* SUCH DAMAGE.
*
* from: @(#)machdep.c 7.4 (Berkeley) 6/3/91
- * $Id: machdep.c,v 1.245 1997/05/26 18:40:45 fsmp Exp $
+ * $Id: machdep.c,v 1.246 1997/06/02 08:19:03 dfr Exp $
*/
#include "npx.h"
@@ -1516,6 +1516,7 @@ fill_regs(p, regs)
struct proc *p;
struct reg *regs;
{
+ struct pcb *pcb;
struct trapframe *tp;
tp = p->p_md.md_regs;
@@ -1533,6 +1534,9 @@ fill_regs(p, regs)
regs->r_eflags = tp->tf_eflags;
regs->r_esp = tp->tf_esp;
regs->r_ss = tp->tf_ss;
+ pcb = &p->p_addr->u_pcb;
+ regs->r_fs = pcb->pcb_fs;
+ regs->r_gs = pcb->pcb_gs;
return (0);
}
@@ -1541,6 +1545,7 @@ set_regs(p, regs)
struct proc *p;
struct reg *regs;
{
+ struct pcb *pcb;
struct trapframe *tp;
tp = p->p_md.md_regs;
@@ -1561,6 +1566,9 @@ set_regs(p, regs)
tp->tf_eflags = regs->r_eflags;
tp->tf_esp = regs->r_esp;
tp->tf_ss = regs->r_ss;
+ pcb = &p->p_addr->u_pcb;
+ pcb->pcb_fs = regs->r_fs;
+ pcb->pcb_gs = regs->r_gs;
return (0);
}
diff --git a/sys/amd64/amd64/swtch.s b/sys/amd64/amd64/swtch.s
index 094e75b..923d694 100644
--- a/sys/amd64/amd64/swtch.s
+++ b/sys/amd64/amd64/swtch.s
@@ -33,7 +33,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $Id: swtch.s,v 1.50 1997/05/29 05:11:11 peter Exp $
+ * $Id: swtch.s,v 1.51 1997/05/31 09:27:29 peter Exp $
*/
#include "npx.h"
@@ -336,6 +336,8 @@ ENTRY(cpu_switch)
movl %ebp,PCB_EBP(%ecx)
movl %esi,PCB_ESI(%ecx)
movl %edi,PCB_EDI(%ecx)
+ movl %fs,PCB_FS(%ecx)
+ movl %gs,PCB_GS(%ecx)
#ifdef SMP
movl _mp_lock, %eax
@@ -562,6 +564,14 @@ swtch_com:
2:
#endif
+ /* This must be done after loading the user LDT. */
+ .globl cpu_switch_load_fs
+cpu_switch_load_fs:
+ movl PCB_FS(%edx),%fs
+ .globl cpu_switch_load_gs
+cpu_switch_load_gs:
+ movl PCB_GS(%edx),%gs
+
sti
ret
@@ -592,6 +602,8 @@ ENTRY(savectx)
movl %ebp,PCB_EBP(%ecx)
movl %esi,PCB_ESI(%ecx)
movl %edi,PCB_EDI(%ecx)
+ movl %fs,PCB_FS(%ecx)
+ movl %gs,PCB_GS(%ecx)
#if NNPX > 0
/*
diff --git a/sys/amd64/amd64/trap.c b/sys/amd64/amd64/trap.c
index f73c4f2..89dd34f 100644
--- a/sys/amd64/amd64/trap.c
+++ b/sys/amd64/amd64/trap.c
@@ -35,7 +35,7 @@
* SUCH DAMAGE.
*
* from: @(#)trap.c 7.4 (Berkeley) 5/13/91
- * $Id: trap.c,v 1.97 1997/05/31 09:27:29 peter Exp $
+ * $Id: trap.c,v 1.98 1997/06/02 08:19:03 dfr Exp $
*/
/*
@@ -352,6 +352,25 @@ trap(frame)
} while (0)
if (intr_nesting_level == 0) {
+ /*
+ * Invalid %fs's and %gs's can be created using
+ * procfs or PT_SETREGS or by invalidating the
+ * underlying LDT entry. This causes a fault
+ * in kernel mode when the kernel attempts to
+ * switch contexts. Lose the bad context
+ * (XXX) so that we can continue, and generate
+ * a signal.
+ */
+ if (frame.tf_eip == (int)cpu_switch_load_fs) {
+ curpcb->pcb_fs = 0;
+ psignal(p, SIGBUS);
+ return;
+ }
+ if (frame.tf_eip == (int)cpu_switch_load_gs) {
+ curpcb->pcb_gs = 0;
+ psignal(p, SIGBUS);
+ return;
+ }
MAYBE_DORETI_FAULT(doreti_iret,
doreti_iret_fault);
MAYBE_DORETI_FAULT(doreti_popl_ds,
diff --git a/sys/amd64/include/md_var.h b/sys/amd64/include/md_var.h
index 307257c..a7e7856 100644
--- a/sys/amd64/include/md_var.h
+++ b/sys/amd64/include/md_var.h
@@ -26,7 +26,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $Id: md_var.h,v 1.12 1997/02/22 09:34:49 peter Exp $
+ * $Id: md_var.h,v 1.13 1997/03/22 18:53:08 kato Exp $
*/
#ifndef _MACHINE_MD_VAR_H_
@@ -57,6 +57,8 @@ struct reg;
void bcopyb __P((const void *from, void *to, size_t len));
void cpu_reset __P((void));
void cpu_halt __P((void));
+void cpu_switch_load_fs __P((void)) __asm(__STRING(cpu_switch_load_fs));
+void cpu_switch_load_gs __P((void)) __asm(__STRING(cpu_switch_load_gs));
void doreti_iret __P((void)) __asm(__STRING(doreti_iret));
void doreti_iret_fault __P((void)) __asm(__STRING(doreti_iret_fault));
void doreti_popl_ds __P((void)) __asm(__STRING(doreti_popl_ds));
diff --git a/sys/amd64/include/pcb.h b/sys/amd64/include/pcb.h
index 1cbca02..c93ed87 100644
--- a/sys/amd64/include/pcb.h
+++ b/sys/amd64/include/pcb.h
@@ -34,7 +34,7 @@
* SUCH DAMAGE.
*
* from: @(#)pcb.h 5.10 (Berkeley) 5/12/91
- * $Id: pcb.h,v 1.20 1997/04/26 11:45:39 peter Exp $
+ * $Id: pcb.h,v 1.21 1997/05/07 19:49:32 peter Exp $
*/
#ifndef _I386_PCB_H_
@@ -64,7 +64,9 @@ struct pcb {
#define FP_SOFTFP 0x01 /* process using software fltng pnt emulator */
caddr_t pcb_onfault; /* copyin/out fault recovery */
u_long pcb_mpnest;
- u_long __pcb_spare[7]; /* adjust to avoid core dump size changes */
+ int pcb_fs;
+ int pcb_gs;
+ u_long __pcb_spare[5]; /* adjust to avoid core dump size changes */
#if 0 /* some day we may switch between procs that have their own i386tss */
struct i386tss pcb_tss;
u_char pcb_iomap[NPORT/sizeof(u_char)]; /* i/o port bitmap */
diff --git a/sys/amd64/include/reg.h b/sys/amd64/include/reg.h
index c896fe5..5d36f27 100644
--- a/sys/amd64/include/reg.h
+++ b/sys/amd64/include/reg.h
@@ -34,7 +34,7 @@
* SUCH DAMAGE.
*
* from: @(#)reg.h 5.5 (Berkeley) 1/18/91
- * $Id: reg.h,v 1.13 1997/02/22 09:35:07 peter Exp $
+ * $Id: reg.h,v 1.14 1997/06/07 00:49:45 bde Exp $
*/
#ifndef _MACHINE_REG_H_
@@ -69,6 +69,16 @@
#define tSS (16)
/*
+ * Indices for registers in `struct regs' only.
+ *
+ * Some registers live in the pcb and are only in an "array" with the
+ * other registers in application interfaces that copy all the registers
+ * to or from a `struct regs'.
+ */
+#define tFS (17)
+#define tGS (18)
+
+/*
* Register set accessible via /proc/$pid/regs and PT_{SET,GET}REGS.
*/
struct reg {
@@ -89,6 +99,8 @@ struct reg {
unsigned int r_eflags;
unsigned int r_esp;
unsigned int r_ss;
+ unsigned int r_fs;
+ unsigned int r_gs;
};
/*
OpenPOWER on IntegriCloud