On multiprocessor systems, it is possible that a lev1map might be in use
by two processors concurrently. This means that we cannot modify the lev1map in use by the processor which wishes to use the PROM. Fix this by creating a separate lev1map for PROM users. This lev1map is a copy of the kernel_lev1map, with the exception of the necessary PROM mapping. When a processor wishes to use the PROM, it switches its PTBR to point at the prom_lev1map, performs the PROM operation, and switches back to its previous lev1map. Note that kernels without multiprocessor support use the old method of modifying the current lev1map. Also, serialize access to the PROM via a spin lock.
This commit is contained in:
parent
1b92119539
commit
07304bd858
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: pmap.c,v 1.81 1999/02/24 19:36:04 thorpej Exp $ */
|
||||
/* $NetBSD: pmap.c,v 1.82 1999/02/25 03:43:14 thorpej Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1998, 1999 The NetBSD Foundation, Inc.
|
||||
@ -156,7 +156,7 @@
|
||||
|
||||
#include <sys/cdefs.h> /* RCS ID & Copyright macro defns */
|
||||
|
||||
__KERNEL_RCSID(0, "$NetBSD: pmap.c,v 1.81 1999/02/24 19:36:04 thorpej Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: pmap.c,v 1.82 1999/02/25 03:43:14 thorpej Exp $");
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/systm.h>
|
||||
@ -793,26 +793,6 @@ pmap_bootstrap(ptaddr, maxasn, ncpuids)
|
||||
* Set up level 1 page table
|
||||
*/
|
||||
|
||||
#ifdef _PMAP_MAY_USE_PROM_CONSOLE
|
||||
{
|
||||
extern pt_entry_t rom_pte; /* XXX */
|
||||
extern int prom_mapped; /* XXX */
|
||||
|
||||
if (pmap_uses_prom_console()) {
|
||||
/* XXX save old pte so that we can remap prom if necessary */
|
||||
rom_pte = *(pt_entry_t *)ptaddr & ~PG_ASM; /* XXX */
|
||||
}
|
||||
prom_mapped = 0;
|
||||
|
||||
/*
|
||||
* Actually, this code lies. The prom is still mapped, and will
|
||||
* remain so until the context switch after alpha_init() returns.
|
||||
* Printfs using the firmware before then will end up frobbing
|
||||
* kernel_lev1map unnecessarily, but that's OK.
|
||||
*/
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Map all of the level 2 pte pages */
|
||||
for (i = 0; i < howmany(lev2mapsize, NPTEPG); i++) {
|
||||
pte = (ALPHA_K0SEG_TO_PHYS(((vaddr_t)lev2map) +
|
||||
@ -829,6 +809,44 @@ pmap_bootstrap(ptaddr, maxasn, ncpuids)
|
||||
kernel_lev1map[l1pte_index(VPTBASE)] = pte;
|
||||
VPT = (pt_entry_t *)VPTBASE;
|
||||
|
||||
#ifdef _PMAP_MAY_USE_PROM_CONSOLE
|
||||
{
|
||||
#if defined(MULTIPROCESSOR)
|
||||
extern pt_entry_t *prom_lev1map; /* XXX */
|
||||
#else
|
||||
extern pt_entry_t prom_pte; /* XXX */
|
||||
#endif
|
||||
extern int prom_mapped; /* XXX */
|
||||
|
||||
if (pmap_uses_prom_console()) {
|
||||
/*
|
||||
* XXX Save old PTE so we can remap the PROM, if
|
||||
* XXX necessary.
|
||||
* XXX
|
||||
* XXX On MP systems, the processor using the PROM
|
||||
* XXX actually has to switch to another page table
|
||||
* XXX so as to avoid stomping on an existing mapping
|
||||
* XXX which may be shared with another processor.
|
||||
*/
|
||||
#if defined(MULTIPROCESSOR)
|
||||
prom_lev1map = (pt_entry_t *)
|
||||
pmap_steal_memory(sizeof(pt_entry_t) * NPTEPG, NULL, NULL);
|
||||
memcpy(prom_lev1map, kernel_lev1map,
|
||||
sizeof(pt_entry_t) * NPTEPG);
|
||||
prom_lev1map[0] = *(pt_entry_t *)ptaddr & ~PG_ASM;
|
||||
#else
|
||||
prom_pte = *(pt_entry_t *)ptaddr & ~PG_ASM;
|
||||
#endif
|
||||
}
|
||||
prom_mapped = 0;
|
||||
|
||||
/*
|
||||
* Actually, this code lies. The prom is still mapped, and will
|
||||
* remain so until the context switch after alpha_init() returns.
|
||||
*/
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Set up level 2 page table.
|
||||
*/
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: prom.c,v 1.33 1999/02/24 19:25:56 thorpej Exp $ */
|
||||
/* $NetBSD: prom.c,v 1.34 1999/02/25 03:43:14 thorpej Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1992, 1994, 1995, 1996 Carnegie Mellon University
|
||||
@ -27,11 +27,14 @@
|
||||
|
||||
#include <sys/cdefs.h> /* RCS ID & Copyright macro defns */
|
||||
|
||||
__KERNEL_RCSID(0, "$NetBSD: prom.c,v 1.33 1999/02/24 19:25:56 thorpej Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: prom.c,v 1.34 1999/02/25 03:43:14 thorpej Exp $");
|
||||
|
||||
#include "opt_multiprocessor.h"
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/systm.h>
|
||||
#include <vm/vm.h>
|
||||
#include <sys/lock.h>
|
||||
#include <sys/proc.h>
|
||||
#include <sys/user.h>
|
||||
|
||||
@ -55,23 +58,35 @@ extern struct prom_vec prom_dispatch_v;
|
||||
|
||||
#ifdef _PMAP_MAY_USE_PROM_CONSOLE
|
||||
int prom_mapped = 1; /* Is PROM still mapped? */
|
||||
pt_entry_t rom_pte, saved_pte[1]; /* XXX */
|
||||
|
||||
static pt_entry_t *rom_lev1map __P((void));
|
||||
struct simplelock prom_slock;
|
||||
|
||||
#if defined(MULTIPROCESSOR)
|
||||
pt_entry_t *prom_lev1map, *saved_lev1map;
|
||||
static pt_entry_t *prom_swaplev1map __P((pt_entry_t *));
|
||||
|
||||
static pt_entry_t *
|
||||
rom_lev1map()
|
||||
prom_swaplev1map(l1map)
|
||||
pt_entry_t *l1map;
|
||||
{
|
||||
struct alpha_pcb *apcb;
|
||||
extern pt_entry_t *kernel_lev1map;
|
||||
pt_entry_t *rl1map;
|
||||
|
||||
/*
|
||||
* We may be called before the first context switch
|
||||
* after alpha_init(), in which case we just need
|
||||
* to use the kernel kernel_lev1map.
|
||||
*/
|
||||
if (curpcb == 0)
|
||||
return (kernel_lev1map);
|
||||
apcb = (struct alpha_pcb *)ALPHA_PHYS_TO_K0SEG(curpcb);
|
||||
|
||||
rl1map = (pt_entry_t *)ALPHA_PHYS_TO_K0SEG(apcb->apcb_ptbr << PGSHIFT);
|
||||
apcb->apcb_ptbr = ALPHA_K0SEG_TO_PHYS((vaddr_t)l1map) >> PGSHIFT;
|
||||
(void) alpha_pal_swpctx(curpcb);
|
||||
return (rl1map);
|
||||
}
|
||||
#else /* ! MULTIPROCESSOR */
|
||||
pt_entry_t prom_pte, saved_pte[1]; /* XXX */
|
||||
static pt_entry_t *prom_lev1map __P((void));
|
||||
|
||||
static pt_entry_t *
|
||||
prom_lev1map()
|
||||
{
|
||||
struct alpha_pcb *apcb;
|
||||
|
||||
/*
|
||||
* Find the level 1 map that we're currently running on.
|
||||
@ -80,6 +95,7 @@ rom_lev1map()
|
||||
|
||||
return ((pt_entry_t *)ALPHA_PHYS_TO_K0SEG(apcb->apcb_ptbr << PGSHIFT));
|
||||
}
|
||||
#endif /* MULTIPROCESSOR */
|
||||
#endif /* _PMAP_MAY_USE_PROM_CONSOLE */
|
||||
|
||||
void
|
||||
@ -92,6 +108,8 @@ init_prom_interface(rpb)
|
||||
|
||||
prom_dispatch_v.routine_arg = c->crb_v_dispatch;
|
||||
prom_dispatch_v.routine = c->crb_v_dispatch->entry_va;
|
||||
|
||||
simple_lock_init(&prom_slock);
|
||||
}
|
||||
|
||||
void
|
||||
@ -115,21 +133,31 @@ static void prom_cache_sync __P((void));
|
||||
int
|
||||
prom_enter()
|
||||
{
|
||||
int s = splhigh();
|
||||
int s;
|
||||
|
||||
s = splhigh();
|
||||
simple_lock(&prom_slock);
|
||||
|
||||
#ifdef _PMAP_MAY_USE_PROM_CONSOLE
|
||||
pt_entry_t *lev1map;
|
||||
|
||||
/*
|
||||
* XXX THIS IS COMPLETELY BROKEN ON MULTIPROCESSOR SYSTEMS!
|
||||
* If we have not yet switched out of the PROM's context
|
||||
* (i.e. the first one after alpha_init()), then the PROM
|
||||
* is still mapped, regardless of the `prom_mapped' setting.
|
||||
*/
|
||||
|
||||
if (!prom_mapped) {
|
||||
if (prom_mapped == 0 && curpcb != 0) {
|
||||
if (!pmap_uses_prom_console())
|
||||
panic("prom_enter");
|
||||
lev1map = rom_lev1map(); /* XXX */
|
||||
saved_pte[0] = lev1map[0]; /* XXX */
|
||||
lev1map[0] = rom_pte; /* XXX */
|
||||
#if defined(MULTIPROCESSOR)
|
||||
saved_lev1map = prom_swaplev1map(prom_lev1map);
|
||||
#else
|
||||
{
|
||||
pt_entry_t *lev1map;
|
||||
|
||||
lev1map = prom_lev1map(); /* XXX */
|
||||
saved_pte[0] = lev1map[0]; /* XXX */
|
||||
lev1map[0] = prom_pte; /* XXX */
|
||||
}
|
||||
#endif
|
||||
prom_cache_sync(); /* XXX */
|
||||
}
|
||||
#endif
|
||||
@ -142,16 +170,26 @@ prom_leave(s)
|
||||
{
|
||||
|
||||
#ifdef _PMAP_MAY_USE_PROM_CONSOLE
|
||||
pt_entry_t *lev1map;
|
||||
|
||||
if (!prom_mapped) {
|
||||
/*
|
||||
* See comment above.
|
||||
*/
|
||||
if (prom_mapped == 0 && curpcb != 0) {
|
||||
if (!pmap_uses_prom_console())
|
||||
panic("prom_leave");
|
||||
lev1map = rom_lev1map(); /* XXX */
|
||||
lev1map[0] = saved_pte[0]; /* XXX */
|
||||
#if defined(MULTIPROCESSOR)
|
||||
(void) prom_swaplev1map(saved_lev1map);
|
||||
#else
|
||||
{
|
||||
pt_entry_t *lev1map;
|
||||
|
||||
lev1map = prom_lev1map(); /* XXX */
|
||||
lev1map[0] = saved_pte[0]; /* XXX */
|
||||
}
|
||||
#endif
|
||||
prom_cache_sync(); /* XXX */
|
||||
}
|
||||
#endif
|
||||
simple_unlock(&prom_slock);
|
||||
splx(s);
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user