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).
This commit is contained in:
Bruce Evans 1997-06-07 04:36:10 +00:00
parent e728d480d2
commit 7b3c84247b
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=26494
16 changed files with 163 additions and 18 deletions

View file

@ -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
/*

View file

@ -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

View file

@ -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);
}

View file

@ -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
/*

View file

@ -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,

View file

@ -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));

View file

@ -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 */

View file

@ -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_
@ -68,6 +68,16 @@
#define tESP (15)
#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.
*/
@ -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;
};
/*

View file

@ -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

View file

@ -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);
}

View file

@ -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
/*

View file

@ -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,

View file

@ -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));

View file

@ -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 */

View file

@ -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_
@ -68,6 +68,16 @@
#define tESP (15)
#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.
*/
@ -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;
};
/*

View file

@ -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,