Get boothowto flags from PROM flags; fix reboot.

This commit is contained in:
gwr 1994-09-20 16:50:28 +00:00
parent 4e9d2ade85
commit 5189af7e96
3 changed files with 1313 additions and 1031 deletions

View File

@ -1,4 +1,5 @@
/*
* Copyright (c) 1994 Gordon W. Ross
* Copyright (c) 1993 Adam Glass
* All rights reserved.
*
@ -13,22 +14,21 @@
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by Adam Glass.
* 4. The name of the Author may not be used to endorse or promote products
* 4. The name of the authors may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY Adam Glass ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
* THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* $Id: locore2.c,v 1.23 1994/07/11 03:41:33 gwr Exp $
* $Id: locore2.c,v 1.24 1994/09/20 16:50:30 gwr Exp $
*/
#include <sys/param.h>
@ -103,63 +103,76 @@ vm_offset_t high_segment_alloc(npages)
return tmp;
}
static void
sun3_stop(how)
int how; /* borrowing howto codes here... */
/*
* Prepare for running the PROM monitor
*/
static void sun3_mode_monitor()
{
static unsigned int *save_vbr;
/* Restore vector table and NMI clock for PROM. */
/* Install PROM vector table and enable NMI clock. */
/* XXX - Disable watchdog action? */
set_clk_mode(0, IREG_CLOCK_ENAB_5, 0);
save_vbr = getvbr();
setvbr(old_vector_table);
set_clk_mode(IREG_CLOCK_ENAB_7, 0, 1);
if (how) {
#if 0
/* Not sure about this... -gwr */
if (how == RB_KDB)
(romVectorPtr->abortEntry)();
#endif
mon_printf("exit to monitor\n");
mon_exit_to_mon();
} else {
mon_printf("rebooting...\n");
mon_reboot(""); /* or do i have to get the value out of
* the eeprom...bleh
*/
}
/* The user has continued from an abort. */
/* XXX - Does not work. Maybe setjmp/longjmp would work. */
/* Restore our vector table and disable the NMI clock. */
/*
* Prepare for running the kernel
*/
static void sun3_mode_normal()
{
/* Install our vector table and disable the NMI clock. */
set_clk_mode(0, IREG_CLOCK_ENAB_7, 0);
setvbr(save_vbr);
setvbr((unsigned int *) vector_table);
set_clk_mode(IREG_CLOCK_ENAB_5, 0, 1);
}
void
sun3_rom_abort()
/*
* This function takes care of restoring enough of the
* hardware state to allow the PROM to run normally.
* The PROM needs: NMI enabled, it's own vector table.
* In case of a temporary "drop into PROM", this will
* also put our hardware state back into place after
* the PROM "c" (continue) command is given.
*/
void sun3_rom_abort()
{
sun3_stop(RB_KDB);
int s = splhigh();
sun3_mode_monitor();
/*
* Drop into the PROM in a way that allows a continue.
* That's what the PROM function (romp->abortEntry) is for,
* but that wants to be entered as a trap hander, so I just
* plug that into the vector table for trap zero and do it.
*/
mon_printf("kernel stop: enter c to continue or g0 to panic\n");
delay(100000);
old_vector_table[32] = (int)romp->abortEntry;
__asm __volatile (" trap #0");
__asm __volatile("_sun3_rom_continued: nop");
/* We have continued from a PROM abort. */
sun3_mode_normal();
splx(s);
}
void
sun3_rom_halt()
void sun3_rom_halt()
{
sun3_stop(RB_HALT);
(void) splhigh();
sun3_mode_monitor();
mon_exit_to_mon();
/*NOTREACHED*/
}
void
sun3_rom_reboot()
void sun3_rom_reboot(bootstring)
char *bootstring;
{
sun3_stop(0);
}
void sun3_printf(str)
char *str;
{
mon_printf(str);
(void) splhigh();
sun3_mode_monitor();
mon_reboot(bootstring);
mon_exit_to_mon();
/*NOTREACHED*/
}
/*
@ -204,69 +217,91 @@ void u_area_bootstrap(u_va, u_pa)
set_pte(va, pte_proto|PA_PGNUM(pa));
}
static void
sun3_mon_init(sva, eva, keep)
vm_offset_t sva, eva;
int keep; /* true: steal, false: clear */
{
vm_offset_t pgva, endseg;
int pte, valid;
unsigned char sme;
sva &= ~(NBSG-1);
while (sva < eva) {
sme = get_segmap(sva);
if (sme != SEGINV) {
#ifdef DEBUG
mon_printf("mon va=0x%x seg=0x%x\n", sva, sme);
#endif
valid = 0;
endseg = sva + NBSG;
for (pgva = sva; pgva < endseg; pgva += NBPG) {
pte = get_pte(pgva);
if (pte & PG_VALID) {
valid++;
#ifdef DEBUG
mon_printf("mon va=0x%x pte=0x%x\n", pgva, pte);
#endif
}
}
if (keep && valid) pmeg_steal(sme);
else set_segmap(sva, SEGINV);
}
sva += NBSG;
}
}
/* This is called just before pmap_bootstrap() */
void sun3_vm_init()
{
unsigned int monitor_memory = 0;
vm_offset_t va, eva, sva, pte, temp_seg, clock_va;
vm_offset_t va, eva, sva, pte, temp_seg;
extern char start[], etext[], end[];
unsigned char sme;
int valid;
pmeg_init();
va = (vm_offset_t) start;
/* Reserve kernel text/data/bss */
va = (vm_offset_t) VM_MIN_KERNEL_ADDRESS;
while (va < (vm_offset_t) end) {
sme = get_segmap(va);
if (sme == SEGINV)
mon_panic("stealing pages for kernel text/data/etc\n");
mon_panic("kernel text/data/bss not mapped\n");
pmeg_steal(sme);
va = sun3_round_up_seg(va);
va += NBSG;
}
virtual_avail = sun3_round_seg(end); /* start a new segment */
virtual_avail = va; /* start a new segment */
virtual_end = VM_MAX_KERNEL_ADDRESS;
if (romp->romvecVersion >=1)
monitor_memory = *romp->memorySize - *romp->memoryAvail;
avail_start = sun3_round_page(end) - KERNBASE; /* XXX */
avail_end = sun3_trunc_page(*romp->memoryAvail);
/* Physical memory was remapped to KERNBASE. */
avail_start = sun3_round_page(end) - KERNBASE;
/* How much of the end of RAM did the PROM steal? */
if (romp->romvecVersion < 1) {
mon_printf("Warning: ancient PROM version=%d\n",
romp->romvecVersion);
/* Guess that PROM version 0.X used two pages. */
avail_end = *romp->memorySize - (2*NBPG);
} else {
/* PROM version 1 or later. */
avail_end = *romp->memoryAvail;
}
avail_end = sun3_trunc_page(avail_end);
/*
* preserve/protect monitor:
* need to preserve/protect pmegs used to map monitor between
* need to preserve/protect mappings between
* MONSTART, MONEND.
* free up any pmegs in this range which are
* free up any pmegs in this range which have no mappings
* deal with the awful MONSHORTSEG/MONSHORTPAGE
*/
va = MONSTART;
while (va < MONEND) {
sme = get_segmap(va);
if (sme == SEGINV) {
va = sun3_round_up_seg(va);
continue;
}
eva = sun3_round_up_seg(va);
if (eva > MONEND)
eva = MONEND;
valid = 0;
sva = va;
for (; va < eva; va += NBPG) {
pte = get_pte(va);
if (pte & PG_VALID) {
valid++;
break;
}
}
if (valid)
pmeg_steal(sme);
else {
set_segmap(sva, SEGINV);
}
va = eva;
}
sun3_mon_init(MONSTART, MONEND, TRUE);
/*
* Make sure the hole between MONEND, MONSHORTSEG is clear.
*/
sun3_mon_init(MONEND, MONSHORTSEG, FALSE);
/*
* MONSHORTSEG contains MONSHORTPAGE which is some stupid page
* allocated by the monitor. One page, in an otherwise empty segment.
@ -277,7 +312,6 @@ void sun3_vm_init()
* the range of acceptable kernel vm, and not in space.
*
*/
sme = get_segmap(MONSHORTSEG);
pmeg_steal(sme);
high_segment_free_start = MONSHORTSEG;
@ -314,7 +348,7 @@ void sun3_vm_init()
pmeg_steal(sme);
eva = sun3_round_up_seg(virtual_avail);
/* msgbuf, pg 0 */
/* msgbuf, pg 0 XXX - Put at KERNBASE? */
avail_end -= NBPG;
msgbufp = (struct msgbuf *) virtual_avail;
pte = PG_VALID | PG_WRITE |PG_SYSTEM | PG_NC | (avail_end >>PGSHIFT);
@ -395,17 +429,6 @@ void sun3_vm_init()
load_u_area(&proc0paddr->u_pcb);
curpcb = &proc0paddr->u_pcb;
clock_va = (vm_offset_t) obio_alloc((caddr_t) OBIO_CLOCK,
OBIO_CLOCK_SIZE, OBIO_WRITE);
if (clock_va != CLOCK_VA)
mon_printf("clock is not at CLOCK_VA, %x vs. %x\n", clock_va,
CLOCK_VA);
interrupt_reg = obio_alloc((caddr_t) OBIO_INTERREG,
OBIO_INTERREG_SIZE, OBIO_WRITE);
if ((unsigned int) interrupt_reg != INTERREG_VA)
mon_printf("interrupt_reg is not at INTERREG_VA, %x vs. %x\n",
interrupt_reg, INTERREG_VA);
sun3_context_equiv();
}
@ -534,6 +557,7 @@ v_handler(addr, str)
switch (addr) {
case 0: /* old g0 */
case 0xd: /* 'd'ump short hand */
sun3_mode_normal();
panic("zero");
/*NOTREACHED*/
@ -563,9 +587,6 @@ v_handler(addr, str)
case 'u': /* d'u'mp hack ('d' look like hex) */
case 'U':
if (addr == 0xd) {
panic("zero");
} else
goto err;
break;
@ -574,10 +595,53 @@ v_handler(addr, str)
mon_printf("Don't understand 0x%x '%s'\n", addr, str);
}
}
/*
* Set the PROM vector handler (for g0, g4, etc.)
* and set boothowto from the PROM arg strings.
*/
void sun3_monitor_hooks()
{
MachMonBootParam *bpp;
char *p;
int i;
if (romp->romvecVersion >= 2)
*romp->vector_cmd = v_handler;
/* Set boothowto flags from PROM args. */
bpp = *romp->bootParam;
for (i = 0; i < 8; i++) {
p = bpp->argPtr[i];
/* Null arg? We're done. */
if (p == NULL || *p == '\0')
break;
#ifdef DEBUG
mon_printf("arg[%d]=\"%s\"\n", i, p);
#endif
/* Not switches? Skip it. */
if (*p++ != '-')
continue;
while (*p) {
switch (*p++) {
case 'a':
boothowto |= RB_ASKNAME;
break;
case 's':
boothowto |= RB_SINGLE;
break;
case 'd':
boothowto |= RB_KDB;
break;
}
}
}
#ifdef DEBUG
mon_printf("boothowto=0x%x\n", boothowto);
#endif
}
void pte_print(pte)
@ -617,16 +681,27 @@ void set_interrupt_reg(value)
{
*interrupt_reg = (unsigned char) value;
}
unsigned int get_interrupt_reg()
{
vm_offset_t pte;
return (unsigned int) *interrupt_reg;
}
void internal_configure()
{
obio_init();
/* now other obio devices */
zs_init();
eeprom_init();
clock_init();
isr_init();
}
void sun3_bootstrap()
{
int i;
extern int cold, astpending;
extern int cold;
/*
* would do bzero of bss here but our bzero only works <64k stuff
@ -646,6 +721,4 @@ void sun3_bootstrap()
pmap_bootstrap(); /* bootstrap pmap module */
internal_configure(); /* stuff that can't wait for configure() */
astpending =0;
}

View File

@ -1,4 +1,6 @@
/* Copyright (c) 1993 Adam Glass
/*
* Copyright (c) 1994 Gordon W. Ross
* Copyright (c) 1993 Adam Glass
* Copyright (c) 1988 University of Utah.
* Copyright (c) 1982, 1986, 1990 The Regents of the University of California.
* All rights reserved.
@ -38,7 +40,7 @@
* from: Utah Hdr: machdep.c 1.63 91/04/24
* from: @(#)machdep.c 7.16 (Berkeley) 6/3/91
* machdep.c,v 1.3 1993/07/07 07:20:03 cgd Exp
* $Id: machdep.c,v 1.36 1994/07/27 04:52:00 gwr Exp $
* $Id: machdep.c,v 1.37 1994/09/20 16:50:28 gwr Exp $
*/
#include <sys/param.h>
@ -92,16 +94,17 @@
#include <net/netisr.h>
#ifdef COMPAT_SUNOS
void sun_sendsig();
#endif
extern char *cpu_string;
int physmem;
int cold;
extern char kstack[];
extern short exframesize[];
#ifdef COMPAT_SUNOS
void sun_sendsig();
static void hack_sun_reboot(); /* XXX - Temporary hack... */
#endif
/*
* Declare these as initialized data so we can patch them.
*/
@ -166,6 +169,11 @@ void load_u_area(pcbp)
}
/*
* This is called early in init_main.c:main(), after the
* kernel memory allocator is ready for use, but before
* the creation of process 0,1,2 and mountroot, etc.
*/
void cpu_startup()
{
caddr_t v;
@ -174,8 +182,6 @@ void cpu_startup()
int base, residual;
vm_offset_t minaddr, maxaddr, uarea_pages;
/* XXX - Get boot parameters from PROM. */
/* msgbuf mapped earlier, should figure out why? */
printf(version);
identifycpu();
@ -276,11 +282,10 @@ void cpu_startup()
*/
nofault = NULL;
configure();
swapconf();
dumpconf();
cold = 0;
#ifdef COMPAT_SUNOS
hack_sun_reboot(); /* XXX - Temporary hack... */
#endif
}
/*
@ -346,19 +351,15 @@ allocsys(v)
return v;
}
void internal_configure()
{
obio_internal_configure();
}
/*
* This is called at the beginning of init_main.c:main()
* to get the console device ready for kernel printf calls.
*/
void consinit()
{
extern void cninit();
cninit();
/* XXX - Temporary hack... */
boothowto = RB_SINGLE | RB_NOSYNC | RB_KDB;
#ifdef DDB
/* Well, this is where the hp300 does it... -gwr */
ddb_init();
@ -367,11 +368,6 @@ void consinit()
#endif DDB
}
void cpu_reset()
{
sun3_rom_reboot();
}
/*
* machine dependent system variables.
*/
@ -547,8 +543,6 @@ struct hpuxsigframe {
};
#endif
#define DEBUG XXX
#ifdef DEBUG
int sigdebug = 0;
int sigpid = 0;
@ -1053,25 +1047,31 @@ sigreturn(p, uap, retval)
return (EJUSTRETURN);
}
int waittime = -1;
void boot(howto)
int howto;
/*
* Do a sync in preparation for a reboot.
* XXX - This could probably be common code. -gwr
*/
int waittime = -1; /* XXX - Who else looks at this? -gwr */
static void reboot_sync()
{
printf("kernel ended deliberately\n");
if ((howto&RB_NOSYNC) == 0 && waittime < 0) {
struct buf *bp;
int iter, nbusy;
if (waittime >= 0)
return;
waittime = 0;
/* XXX - Should this be spl0() like hp300? -gwr */
(void) splnet();
printf("syncing disks... ");
/*
* Release inodes held by texts before update.
* Release vnodes held by texts before sync.
*/
if (panicstr == 0)
vnode_pager_umount(NULL);
sync(&proc0, (void *)0, (int *)0);
for (iter = 0; iter < 20; iter++) {
@ -1090,57 +1090,193 @@ void boot(howto)
printf("done\n");
DELAY(10000); /* wait for printf to finish */
}
/*
* Common part of the BSD and SunOS reboot system calls.
*/
static int reboot2(howto, user_boot_string)
int howto;
char *user_boot_string;
{
char *bs, *p;
char default_boot_string[16];
if ((howto & RB_NOSYNC) == 0) {
reboot_sync();
}
/*
* If we've been adjusting the clock, the todr
* will be out of synch; adjust it now.
*/
resettodr();
/* Write out a crash dump if asked. */
splhigh();
if (howto&RB_HALT) {
printf("\n");
printf("The operating system has halted.\n");
sun3_rom_halt();
} else {
if (howto & RB_DUMP) {
if (howto & RB_DUMP)
dumpsys();
if (howto & RB_HALT) {
printf("Kernel halted.\n");
sun3_rom_halt();
}
/*
* Automatic reboot.
*/
bs = user_boot_string;
if (bs == NULL) {
/*
* Build our own boot string with an empty
* boot device/file and (maybe) some flags.
* The PROM will supply the device/file name.
*/
bs = default_boot_string;
*bs = '\0';
if (howto & (RB_KDB|RB_ASKNAME|RB_SINGLE)) {
/* Append the boot flags. */
p = bs;
*p++ = ' ';
*p++ = '-';
if (howto & RB_KDB)
*p++ = 'd';
if (howto & RB_ASKNAME)
*p++ = 'a';
if (howto & RB_SINGLE)
*p++ = 's';
*p = '\0';
}
}
sun3_rom_reboot();
for(;;) ;
printf("Kernel rebooting...\n");
sun3_rom_reboot(bs);
/*NOTREACHED*/
}
/*
* BSD reboot system call
* XXX - Should be named: cpu_reboot maybe? -gwr
* XXX - It would be nice to allow a second argument
* that specifies a machine-dependent boot string that
* is passed to the boot program if RB_STRING is set.
*/
void boot(howto)
int howto;
{
(void) reboot2(howto, NULL);
}
#ifdef COMPAT_SUNOS
/*
* SunOS reboot system call (for compatibility).
* Sun lets you pass in a boot string which the PROM
* saves and provides to the next boot program.
* XXX - Stuff this into sun_sysent at boot time?
*/
static struct sun_howto_conv {
int sun_howto;
int bsd_howto;
} sun_howto_conv[] = {
0x001, RB_ASKNAME,
0x002, RB_SINGLE,
0x004, RB_NOSYNC,
0x008, RB_HALT,
0x080, RB_DUMP,
};
struct sun_reboot_args {
int howto;
char *bootstr;
};
int sun_reboot(p, uap, retval)
struct proc *p;
struct sun_reboot_args *uap;
int *retval;
{
struct sun_howto_conv *convp;
int error, bsd_howto, sun_howto;
char bs[128];
char *bsd_bootstr = NULL;
if (error = suser(p->p_ucred, &p->p_acflag))
return (error);
/*
* Convert howto bits to BSD format.
*/
sun_howto = uap->howto;
bsd_howto = 0;
convp = sun_howto_conv;
while (convp->sun_howto) {
if (sun_howto & convp->sun_howto)
bsd_howto |= convp->bsd_howto;
convp++;
}
/*
* Sun RB_STRING (Get user supplied bootstring.)
*/
bsd_bootstr = NULL;
if (sun_howto & 0x200) {
error = copyinstr(uap->bootstr, bs, sizeof(bs), 0);
if (error) return error;
bsd_bootstr = bs;
}
return (reboot2(bsd_howto, bsd_bootstr));
}
/*
* XXX - Temporary hack: Install sun_reboot() syscall.
* Fix compat/sunos/sun_sysent instead.
*/
static void hack_sun_reboot()
{
extern struct sysent sun_sysent[];
sun_sysent[55].sy_narg = 2;
sun_sysent[55].sy_call = sun_reboot;
}
#endif /* COMPAT_SUNOS */
/*
* These variables are needed by /sbin/savecore
*/
u_long dumpmag = 0x8fca0101; /* magic number for savecore */
int dumpsize = 0; /* also for savecore */
long dumplo = 0;
u_long dumpmag = 0x8fca0101; /* magic number */
int dumpsize = 0; /* pages */
long dumplo = 0; /* blocks */
/*
* This is called by cpu_startup to set dumplo, dumpsize.
* Dumps always skip the first CLBYTES of disk space
* in case there might be a disk label stored there.
* If there is extra space, put dump at the end.
*/
void
dumpconf()
{
int nblks;
int nblks; /* size of dump area */
int maj;
int (*getsize)();
dumpsize = physmem;
if (dumpdev == NODEV)
return;
if (dumpdev != NODEV && bdevsw[major(dumpdev)].d_psize) {
nblks = (*bdevsw[major(dumpdev)].d_psize)(dumpdev);
/*
* Don't dump on the first CLBYTES (why CLBYTES?)
* in case the dump device includes a disk label.
*/
if (dumplo < btodb(CLBYTES))
dumplo = btodb(CLBYTES);
maj = major(dumpdev);
if (maj < 0 || maj >= nblkdev)
panic("dumpconf: bad dumpdev=0x%x", dumpdev);
getsize = bdevsw[maj].d_psize;
if (getsize == NULL)
return;
nblks = (*getsize)(dumpdev);
if (nblks <= ctod(1))
return;
/*
* If dumpsize is too big for the partition, truncate it.
* Otherwise, put the dump at the end of the partition
* by making dumplo as large as possible.
*/
if (dumpsize > btoc(dbtob(nblks - dumplo)))
dumpsize = btoc(dbtob(nblks - dumplo));
else if (dumplo + ctod(dumpsize) > nblks)
/* Position dump image near end of space, page aligned. */
dumpsize = physmem; /* pages */
dumplo = nblks - ctod(dumpsize);
dumplo &= ~(ctod(1)-1);
/* If it does not fit, truncate it by moving dumplo. */
if (dumplo < ctod(1)) {
dumplo = ctod(1);
dumpsize = dtoc(nblks - dumplo);
}
}

View File

@ -1,4 +1,5 @@
/*
* Copyright (c) 1994 Gordon W. Ross
* Copyright (c) 1993 Adam Glass
* All rights reserved.
*
@ -13,22 +14,21 @@
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by Adam Glass.
* 4. The name of the Author may not be used to endorse or promote products
* 4. The name of the authors may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY Adam Glass ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
* THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* $Id: sun3_startup.c,v 1.23 1994/07/11 03:41:33 gwr Exp $
* $Id: sun3_startup.c,v 1.24 1994/09/20 16:50:30 gwr Exp $
*/
#include <sys/param.h>
@ -103,63 +103,76 @@ vm_offset_t high_segment_alloc(npages)
return tmp;
}
static void
sun3_stop(how)
int how; /* borrowing howto codes here... */
/*
* Prepare for running the PROM monitor
*/
static void sun3_mode_monitor()
{
static unsigned int *save_vbr;
/* Restore vector table and NMI clock for PROM. */
/* Install PROM vector table and enable NMI clock. */
/* XXX - Disable watchdog action? */
set_clk_mode(0, IREG_CLOCK_ENAB_5, 0);
save_vbr = getvbr();
setvbr(old_vector_table);
set_clk_mode(IREG_CLOCK_ENAB_7, 0, 1);
if (how) {
#if 0
/* Not sure about this... -gwr */
if (how == RB_KDB)
(romVectorPtr->abortEntry)();
#endif
mon_printf("exit to monitor\n");
mon_exit_to_mon();
} else {
mon_printf("rebooting...\n");
mon_reboot(""); /* or do i have to get the value out of
* the eeprom...bleh
*/
}
/* The user has continued from an abort. */
/* XXX - Does not work. Maybe setjmp/longjmp would work. */
/* Restore our vector table and disable the NMI clock. */
/*
* Prepare for running the kernel
*/
static void sun3_mode_normal()
{
/* Install our vector table and disable the NMI clock. */
set_clk_mode(0, IREG_CLOCK_ENAB_7, 0);
setvbr(save_vbr);
setvbr((unsigned int *) vector_table);
set_clk_mode(IREG_CLOCK_ENAB_5, 0, 1);
}
void
sun3_rom_abort()
/*
* This function takes care of restoring enough of the
* hardware state to allow the PROM to run normally.
* The PROM needs: NMI enabled, it's own vector table.
* In case of a temporary "drop into PROM", this will
* also put our hardware state back into place after
* the PROM "c" (continue) command is given.
*/
void sun3_rom_abort()
{
sun3_stop(RB_KDB);
int s = splhigh();
sun3_mode_monitor();
/*
* Drop into the PROM in a way that allows a continue.
* That's what the PROM function (romp->abortEntry) is for,
* but that wants to be entered as a trap hander, so I just
* plug that into the vector table for trap zero and do it.
*/
mon_printf("kernel stop: enter c to continue or g0 to panic\n");
delay(100000);
old_vector_table[32] = (int)romp->abortEntry;
__asm __volatile (" trap #0");
__asm __volatile("_sun3_rom_continued: nop");
/* We have continued from a PROM abort. */
sun3_mode_normal();
splx(s);
}
void
sun3_rom_halt()
void sun3_rom_halt()
{
sun3_stop(RB_HALT);
(void) splhigh();
sun3_mode_monitor();
mon_exit_to_mon();
/*NOTREACHED*/
}
void
sun3_rom_reboot()
void sun3_rom_reboot(bootstring)
char *bootstring;
{
sun3_stop(0);
}
void sun3_printf(str)
char *str;
{
mon_printf(str);
(void) splhigh();
sun3_mode_monitor();
mon_reboot(bootstring);
mon_exit_to_mon();
/*NOTREACHED*/
}
/*
@ -204,69 +217,91 @@ void u_area_bootstrap(u_va, u_pa)
set_pte(va, pte_proto|PA_PGNUM(pa));
}
static void
sun3_mon_init(sva, eva, keep)
vm_offset_t sva, eva;
int keep; /* true: steal, false: clear */
{
vm_offset_t pgva, endseg;
int pte, valid;
unsigned char sme;
sva &= ~(NBSG-1);
while (sva < eva) {
sme = get_segmap(sva);
if (sme != SEGINV) {
#ifdef DEBUG
mon_printf("mon va=0x%x seg=0x%x\n", sva, sme);
#endif
valid = 0;
endseg = sva + NBSG;
for (pgva = sva; pgva < endseg; pgva += NBPG) {
pte = get_pte(pgva);
if (pte & PG_VALID) {
valid++;
#ifdef DEBUG
mon_printf("mon va=0x%x pte=0x%x\n", pgva, pte);
#endif
}
}
if (keep && valid) pmeg_steal(sme);
else set_segmap(sva, SEGINV);
}
sva += NBSG;
}
}
/* This is called just before pmap_bootstrap() */
void sun3_vm_init()
{
unsigned int monitor_memory = 0;
vm_offset_t va, eva, sva, pte, temp_seg, clock_va;
vm_offset_t va, eva, sva, pte, temp_seg;
extern char start[], etext[], end[];
unsigned char sme;
int valid;
pmeg_init();
va = (vm_offset_t) start;
/* Reserve kernel text/data/bss */
va = (vm_offset_t) VM_MIN_KERNEL_ADDRESS;
while (va < (vm_offset_t) end) {
sme = get_segmap(va);
if (sme == SEGINV)
mon_panic("stealing pages for kernel text/data/etc\n");
mon_panic("kernel text/data/bss not mapped\n");
pmeg_steal(sme);
va = sun3_round_up_seg(va);
va += NBSG;
}
virtual_avail = sun3_round_seg(end); /* start a new segment */
virtual_avail = va; /* start a new segment */
virtual_end = VM_MAX_KERNEL_ADDRESS;
if (romp->romvecVersion >=1)
monitor_memory = *romp->memorySize - *romp->memoryAvail;
avail_start = sun3_round_page(end) - KERNBASE; /* XXX */
avail_end = sun3_trunc_page(*romp->memoryAvail);
/* Physical memory was remapped to KERNBASE. */
avail_start = sun3_round_page(end) - KERNBASE;
/* How much of the end of RAM did the PROM steal? */
if (romp->romvecVersion < 1) {
mon_printf("Warning: ancient PROM version=%d\n",
romp->romvecVersion);
/* Guess that PROM version 0.X used two pages. */
avail_end = *romp->memorySize - (2*NBPG);
} else {
/* PROM version 1 or later. */
avail_end = *romp->memoryAvail;
}
avail_end = sun3_trunc_page(avail_end);
/*
* preserve/protect monitor:
* need to preserve/protect pmegs used to map monitor between
* need to preserve/protect mappings between
* MONSTART, MONEND.
* free up any pmegs in this range which are
* free up any pmegs in this range which have no mappings
* deal with the awful MONSHORTSEG/MONSHORTPAGE
*/
va = MONSTART;
while (va < MONEND) {
sme = get_segmap(va);
if (sme == SEGINV) {
va = sun3_round_up_seg(va);
continue;
}
eva = sun3_round_up_seg(va);
if (eva > MONEND)
eva = MONEND;
valid = 0;
sva = va;
for (; va < eva; va += NBPG) {
pte = get_pte(va);
if (pte & PG_VALID) {
valid++;
break;
}
}
if (valid)
pmeg_steal(sme);
else {
set_segmap(sva, SEGINV);
}
va = eva;
}
sun3_mon_init(MONSTART, MONEND, TRUE);
/*
* Make sure the hole between MONEND, MONSHORTSEG is clear.
*/
sun3_mon_init(MONEND, MONSHORTSEG, FALSE);
/*
* MONSHORTSEG contains MONSHORTPAGE which is some stupid page
* allocated by the monitor. One page, in an otherwise empty segment.
@ -277,7 +312,6 @@ void sun3_vm_init()
* the range of acceptable kernel vm, and not in space.
*
*/
sme = get_segmap(MONSHORTSEG);
pmeg_steal(sme);
high_segment_free_start = MONSHORTSEG;
@ -314,7 +348,7 @@ void sun3_vm_init()
pmeg_steal(sme);
eva = sun3_round_up_seg(virtual_avail);
/* msgbuf, pg 0 */
/* msgbuf, pg 0 XXX - Put at KERNBASE? */
avail_end -= NBPG;
msgbufp = (struct msgbuf *) virtual_avail;
pte = PG_VALID | PG_WRITE |PG_SYSTEM | PG_NC | (avail_end >>PGSHIFT);
@ -395,17 +429,6 @@ void sun3_vm_init()
load_u_area(&proc0paddr->u_pcb);
curpcb = &proc0paddr->u_pcb;
clock_va = (vm_offset_t) obio_alloc((caddr_t) OBIO_CLOCK,
OBIO_CLOCK_SIZE, OBIO_WRITE);
if (clock_va != CLOCK_VA)
mon_printf("clock is not at CLOCK_VA, %x vs. %x\n", clock_va,
CLOCK_VA);
interrupt_reg = obio_alloc((caddr_t) OBIO_INTERREG,
OBIO_INTERREG_SIZE, OBIO_WRITE);
if ((unsigned int) interrupt_reg != INTERREG_VA)
mon_printf("interrupt_reg is not at INTERREG_VA, %x vs. %x\n",
interrupt_reg, INTERREG_VA);
sun3_context_equiv();
}
@ -534,6 +557,7 @@ v_handler(addr, str)
switch (addr) {
case 0: /* old g0 */
case 0xd: /* 'd'ump short hand */
sun3_mode_normal();
panic("zero");
/*NOTREACHED*/
@ -563,9 +587,6 @@ v_handler(addr, str)
case 'u': /* d'u'mp hack ('d' look like hex) */
case 'U':
if (addr == 0xd) {
panic("zero");
} else
goto err;
break;
@ -574,10 +595,53 @@ v_handler(addr, str)
mon_printf("Don't understand 0x%x '%s'\n", addr, str);
}
}
/*
* Set the PROM vector handler (for g0, g4, etc.)
* and set boothowto from the PROM arg strings.
*/
void sun3_monitor_hooks()
{
MachMonBootParam *bpp;
char *p;
int i;
if (romp->romvecVersion >= 2)
*romp->vector_cmd = v_handler;
/* Set boothowto flags from PROM args. */
bpp = *romp->bootParam;
for (i = 0; i < 8; i++) {
p = bpp->argPtr[i];
/* Null arg? We're done. */
if (p == NULL || *p == '\0')
break;
#ifdef DEBUG
mon_printf("arg[%d]=\"%s\"\n", i, p);
#endif
/* Not switches? Skip it. */
if (*p++ != '-')
continue;
while (*p) {
switch (*p++) {
case 'a':
boothowto |= RB_ASKNAME;
break;
case 's':
boothowto |= RB_SINGLE;
break;
case 'd':
boothowto |= RB_KDB;
break;
}
}
}
#ifdef DEBUG
mon_printf("boothowto=0x%x\n", boothowto);
#endif
}
void pte_print(pte)
@ -617,16 +681,27 @@ void set_interrupt_reg(value)
{
*interrupt_reg = (unsigned char) value;
}
unsigned int get_interrupt_reg()
{
vm_offset_t pte;
return (unsigned int) *interrupt_reg;
}
void internal_configure()
{
obio_init();
/* now other obio devices */
zs_init();
eeprom_init();
clock_init();
isr_init();
}
void sun3_bootstrap()
{
int i;
extern int cold, astpending;
extern int cold;
/*
* would do bzero of bss here but our bzero only works <64k stuff
@ -646,6 +721,4 @@ void sun3_bootstrap()
pmap_bootstrap(); /* bootstrap pmap module */
internal_configure(); /* stuff that can't wait for configure() */
astpending =0;
}