Move the TSS selector out of the PCB and put it into mdproc. We
need to access this when we have the proclist locked for reading, and thus cannot store it in the PCB (which may be swapped out). As part of this, call pmap_activate() from cpu_switch() to switch to the new address space, and refresh the PCB's copy of the LDT selector from the pmap structure (see above paragraph). We need to do this for MP support anyhow. Fixes a "panic: spinlock_switchcheck: CPU 0 has 1 spin locks" via gdt_compact() reported by Nathan Williams.
This commit is contained in:
parent
5a7793edd9
commit
b0dc085df7
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: gdt.c,v 1.22 2000/06/29 08:44:51 mrg Exp $ */
|
||||
/* $NetBSD: gdt.c,v 1.23 2000/08/16 04:44:35 thorpej Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1996, 1997 The NetBSD Foundation, Inc.
|
||||
|
@ -104,15 +104,13 @@ void
|
|||
gdt_compact()
|
||||
{
|
||||
struct proc *p;
|
||||
struct pcb *pcb;
|
||||
pmap_t pmap;
|
||||
int slot = NGDT, oslot;
|
||||
|
||||
proclist_lock_read();
|
||||
for (p = allproc.lh_first; p != 0; p = p->p_list.le_next) {
|
||||
pcb = &p->p_addr->u_pcb;
|
||||
pmap = p->p_vmspace->vm_map.pmap;
|
||||
oslot = IDXSEL(pcb->pcb_tss_sel);
|
||||
oslot = IDXSEL(p->p_md.md_tss_sel);
|
||||
if (oslot >= gdt_count) {
|
||||
while (gdt[slot].sd.sd_type != SDT_SYSNULL) {
|
||||
if (++slot >= gdt_count)
|
||||
|
@ -120,7 +118,7 @@ gdt_compact()
|
|||
}
|
||||
gdt[slot] = gdt[oslot];
|
||||
gdt[oslot].gd.gd_type = SDT_SYSNULL;
|
||||
pcb->pcb_tss_sel = GSEL(slot, SEL_KPL);
|
||||
p->p_md.md_tss_sel = GSEL(slot, SEL_KPL);
|
||||
}
|
||||
simple_lock(&pmap->pm_lock);
|
||||
oslot = IDXSEL(pmap->pm_ldt_sel);
|
||||
|
@ -132,16 +130,10 @@ gdt_compact()
|
|||
gdt[slot] = gdt[oslot];
|
||||
gdt[oslot].gd.gd_type = SDT_SYSNULL;
|
||||
pmap->pm_ldt_sel = GSEL(slot, SEL_KPL);
|
||||
|
||||
/* Refresh the PCB. */
|
||||
pcb->pcb_pmap = pmap;
|
||||
pcb->pcb_ldt_sel = pmap->pm_ldt_sel;
|
||||
|
||||
/*
|
||||
* XXX We don't need to re-load the LDT on this
|
||||
* XXX processor, but if this pmap/pcb is in use
|
||||
* XXX on _another_ processor, we need to notify
|
||||
* XXX it!
|
||||
* XXXSMP: if the pmap is in use on other
|
||||
* processors, they need to reload thier
|
||||
* LDT!
|
||||
*/
|
||||
}
|
||||
simple_unlock(&pmap->pm_lock);
|
||||
|
@ -280,23 +272,24 @@ gdt_put_slot(slot)
|
|||
}
|
||||
|
||||
void
|
||||
tss_alloc(pcb)
|
||||
struct pcb *pcb;
|
||||
tss_alloc(p)
|
||||
struct proc *p;
|
||||
{
|
||||
struct pcb *pcb = &p->p_addr->u_pcb;
|
||||
int slot;
|
||||
|
||||
slot = gdt_get_slot();
|
||||
setsegment(&gdt[slot].sd, &pcb->pcb_tss, sizeof(struct pcb) - 1,
|
||||
SDT_SYS386TSS, SEL_KPL, 0, 0);
|
||||
pcb->pcb_tss_sel = GSEL(slot, SEL_KPL);
|
||||
p->p_md.md_tss_sel = GSEL(slot, SEL_KPL);
|
||||
}
|
||||
|
||||
void
|
||||
tss_free(pcb)
|
||||
struct pcb *pcb;
|
||||
tss_free(p)
|
||||
struct proc *p;
|
||||
{
|
||||
|
||||
gdt_put_slot(IDXSEL(pcb->pcb_tss_sel));
|
||||
gdt_put_slot(IDXSEL(p->p_md.md_tss_sel));
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
# $NetBSD: genassym.cf,v 1.20 2000/06/29 08:44:51 mrg Exp $
|
||||
# $NetBSD: genassym.cf,v 1.21 2000/08/16 04:44:35 thorpej Exp $
|
||||
|
||||
#
|
||||
# Copyright (c) 1998 The NetBSD Foundation, Inc.
|
||||
|
@ -134,8 +134,8 @@ define P_FORW offsetof(struct proc, p_forw)
|
|||
define P_PRIORITY offsetof(struct proc, p_priority)
|
||||
define P_STAT offsetof(struct proc, p_stat)
|
||||
define P_WCHAN offsetof(struct proc, p_wchan)
|
||||
define P_VMSPACE offsetof(struct proc, p_vmspace)
|
||||
define P_FLAG offsetof(struct proc, p_flag)
|
||||
define P_MD_TSS_SEL offsetof(struct proc, p_md.md_tss_sel)
|
||||
|
||||
define P_SYSTEM P_SYSTEM
|
||||
|
||||
|
@ -153,7 +153,6 @@ define PCB_FS offsetof(struct pcb, pcb_fs)
|
|||
define PCB_GS offsetof(struct pcb, pcb_gs)
|
||||
define PCB_CR0 offsetof(struct pcb, pcb_cr0)
|
||||
define PCB_LDT_SEL offsetof(struct pcb, pcb_ldt_sel)
|
||||
define PCB_TSS_SEL offsetof(struct pcb, pcb_tss_sel)
|
||||
define PCB_ONFAULT offsetof(struct pcb, pcb_onfault)
|
||||
|
||||
define TF_CS offsetof(struct trapframe, tf_cs)
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: locore.s,v 1.222 2000/05/31 05:09:16 thorpej Exp $ */
|
||||
/* $NetBSD: locore.s,v 1.223 2000/08/16 04:44:35 thorpej Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1998 The NetBSD Foundation, Inc.
|
||||
|
@ -2009,13 +2009,19 @@ switch_exited:
|
|||
jnz switch_restored
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Activate the address space. We're curproc, so %cr3 will
|
||||
* be reloaded, but we're not yet curpcb, so the LDT won't
|
||||
* be reloaded, although the PCB copy of the selector will
|
||||
* be refreshed from the pmap.
|
||||
*/
|
||||
pushl %edi
|
||||
call _C_LABEL(pmap_activate)
|
||||
addl $4,%esp
|
||||
|
||||
/* Load TSS info. */
|
||||
movl _C_LABEL(gdt),%eax
|
||||
movl PCB_TSS_SEL(%esi),%edx
|
||||
|
||||
/* Switch address space. */
|
||||
movl PCB_CR3(%esi),%ecx
|
||||
movl %ecx,%cr3
|
||||
movl P_MD_TSS_SEL(%edi),%edx
|
||||
|
||||
/* Switch TSS. Reset "task busy" flag before */
|
||||
andl $~0x0200,4(%eax,%edx, 1)
|
||||
|
@ -2087,7 +2093,7 @@ ENTRY(switch_exit)
|
|||
|
||||
/* Load TSS info. */
|
||||
movl _C_LABEL(gdt),%eax
|
||||
movl PCB_TSS_SEL(%esi),%edx
|
||||
movl P_MD_TSS_SEL(%ebx),%edx
|
||||
|
||||
/* Switch address space. */
|
||||
movl PCB_CR3(%esi),%ecx
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: machdep.c,v 1.393 2000/08/15 18:21:44 fvdl Exp $ */
|
||||
/* $NetBSD: machdep.c,v 1.394 2000/08/16 04:44:35 thorpej Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1996, 1997, 1998 The NetBSD Foundation, Inc.
|
||||
|
@ -393,13 +393,13 @@ i386_proc0_tss_ldt_init()
|
|||
for (x = 0; x < sizeof(pcb->pcb_iomap) / 4; x++)
|
||||
pcb->pcb_iomap[x] = 0xffffffff;
|
||||
|
||||
pcb->pcb_ldt_sel = GSEL(GLDT_SEL, SEL_KPL);
|
||||
pcb->pcb_ldt_sel = pmap_kernel()->pm_ldt_sel = GSEL(GLDT_SEL, SEL_KPL);
|
||||
pcb->pcb_cr0 = rcr0();
|
||||
pcb->pcb_tss.tss_ss0 = GSEL(GDATA_SEL, SEL_KPL);
|
||||
pcb->pcb_tss.tss_esp0 = (int)proc0.p_addr + USPACE - 16;
|
||||
tss_alloc(pcb);
|
||||
tss_alloc(&proc0);
|
||||
|
||||
ltr(pcb->pcb_tss_sel);
|
||||
ltr(proc0.p_md.md_tss_sel);
|
||||
lldt(pcb->pcb_ldt_sel);
|
||||
|
||||
proc0.p_md.md_regs = (struct trapframe *)pcb->pcb_tss.tss_esp0 - 1;
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: pmap.c,v 1.96 2000/06/29 08:44:53 mrg Exp $ */
|
||||
/* $NetBSD: pmap.c,v 1.97 2000/08/16 04:44:36 thorpej Exp $ */
|
||||
|
||||
/*
|
||||
*
|
||||
|
@ -1948,9 +1948,9 @@ pmap_ldt_cleanup(p)
|
|||
#endif /* USER_LDT */
|
||||
|
||||
/*
|
||||
* pmap_activate: activate a process' pmap (fill in %cr3 info)
|
||||
* pmap_activate: activate a process' pmap (fill in %cr3 and LDT info)
|
||||
*
|
||||
* => called from cpu_fork()
|
||||
* => called from cpu_switch()
|
||||
* => if proc is the curproc, then load it into the MMU
|
||||
*/
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: vm_machdep.c,v 1.91 2000/06/29 08:44:54 mrg Exp $ */
|
||||
/* $NetBSD: vm_machdep.c,v 1.92 2000/08/16 04:44:36 thorpej Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1995 Charles M. Hannum. All rights reserved.
|
||||
|
@ -132,19 +132,15 @@ cpu_fork(p1, p2, stack, stacksize, func, arg)
|
|||
* Preset these so that gdt_compact() doesn't get confused if called
|
||||
* during the allocations below.
|
||||
*
|
||||
* Note: pcb_ldt_sel is handled in the pmap_activate() call below.
|
||||
* Note: pcb_ldt_sel is handled in the pmap_activate() call when
|
||||
* we run the new process.
|
||||
*/
|
||||
pcb->pcb_tss_sel = GSEL(GNULL_SEL, SEL_KPL);
|
||||
|
||||
/*
|
||||
* Activate the addres space. Note this will refresh pcb_ldt_sel.
|
||||
*/
|
||||
pmap_activate(p2);
|
||||
p2->p_md.md_tss_sel = GSEL(GNULL_SEL, SEL_KPL);
|
||||
|
||||
/* Fix up the TSS. */
|
||||
pcb->pcb_tss.tss_ss0 = GSEL(GDATA_SEL, SEL_KPL);
|
||||
pcb->pcb_tss.tss_esp0 = (int)p2->p_addr + USPACE - 16;
|
||||
tss_alloc(pcb);
|
||||
tss_alloc(p2);
|
||||
|
||||
/*
|
||||
* Copy the trapframe.
|
||||
|
@ -219,7 +215,7 @@ cpu_wait(p)
|
|||
{
|
||||
|
||||
/* Nuke the TSS. */
|
||||
tss_free(&p->p_addr->u_pcb);
|
||||
tss_free(p);
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: gdt.h,v 1.7 1999/05/12 19:28:30 thorpej Exp $ */
|
||||
/* $NetBSD: gdt.h,v 1.8 2000/08/16 04:44:37 thorpej Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1996, 1997 The NetBSD Foundation, Inc.
|
||||
|
@ -36,10 +36,11 @@
|
|||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
struct proc;
|
||||
struct pmap;
|
||||
|
||||
void gdt_init __P((void));
|
||||
void tss_alloc __P((struct pcb *));
|
||||
void tss_free __P((struct pcb *));
|
||||
void tss_alloc __P((struct proc *));
|
||||
void tss_free __P((struct proc *));
|
||||
void ldt_alloc __P((struct pmap *, union descriptor *, size_t));
|
||||
void ldt_free __P((struct pmap *));
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: pcb.h,v 1.26 1999/09/12 01:17:07 chs Exp $ */
|
||||
/* $NetBSD: pcb.h,v 1.27 2000/08/16 04:44:37 thorpej Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1998 The NetBSD Foundation, Inc.
|
||||
|
@ -98,7 +98,6 @@ struct pcb {
|
|||
#define pcb_fs pcb_tss.tss_fs
|
||||
#define pcb_gs pcb_tss.tss_gs
|
||||
#define pcb_ldt_sel pcb_tss.tss_ldt
|
||||
int pcb_tss_sel;
|
||||
int pcb_cr0; /* saved image of CR0 */
|
||||
struct save87 pcb_savefpu; /* floating point state for 287/387 */
|
||||
struct emcsts pcb_saveemc; /* Cyrix EMC state */
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: proc.h,v 1.10 1995/08/06 05:33:23 mycroft Exp $ */
|
||||
/* $NetBSD: proc.h,v 1.11 2000/08/16 04:44:37 thorpej Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1991 Regents of the University of California.
|
||||
|
@ -41,6 +41,7 @@
|
|||
struct mdproc {
|
||||
struct trapframe *md_regs; /* registers on current frame */
|
||||
int md_flags; /* machine-dependent flags */
|
||||
int md_tss_sel; /* TSS selector */
|
||||
};
|
||||
|
||||
/* md_flags */
|
||||
|
|
Loading…
Reference in New Issue