lots of changes, too many printfs

This commit is contained in:
glass 1993-08-08 12:21:50 +00:00
parent 3b87958501
commit 3cdabf7870
17 changed files with 2454 additions and 122 deletions

View File

@ -0,0 +1,239 @@
/*
* Mach Operating System
* Copyright (c) 1992 Carnegie Mellon University
* All Rights Reserved.
*
* Permission to use, copy, modify and distribute this software and its
* documentation is hereby granted, provided that both the copyright
* notice and this permission notice appear in all copies of the
* software, derivative works or modified versions, and any portions
* thereof, and that both notices appear in supporting documentation.
*
* CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
* CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
* ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
*
* Carnegie Mellon requests users of this software to return to
*
* Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
* School of Computer Science
* Carnegie Mellon University
* Pittsburgh PA 15213-3890
*
* any improvements or extensions that they make and grant Carnegie Mellon
* the rights to redistribute these changes.
*/
/*
* HISTORY
* $Log: db_interface.c,v $
* Revision 1.1 1993/08/08 12:22:06 glass
* lots of changes, too many printfs
*
* Revision 2.6 92/01/03 20:31:01 dbg
* Ignore RB_KDB - always enter DDB.
* [91/11/06 dbg]
*
* Revision 2.5 91/07/31 18:12:50 dbg
* Stack switching support.
* [91/07/12 dbg]
*
* Revision 2.4 91/03/16 14:58:16 rpd
* Replaced db_nofault with db_recover.
* [91/03/14 rpd]
*
* Revision 2.3 90/10/25 14:47:16 rwd
* Added watchpoint support.
* [90/10/16 rwd]
*
* Revision 2.2 90/08/27 22:11:17 dbg
* Reduce lint.
* [90/08/07 dbg]
* Created.
* [90/07/25 dbg]
*
*/
/*
* Interface to new debugger.
*/
#include "param.h"
#include "proc.h"
#include <machine/db_machdep.h>
#include <sys/reboot.h>
#include <vm/vm_statistics.h>
#include <vm/pmap.h>
#include <setjmp.h>
#include <sys/systm.h> /* just for boothowto --eichin */
#include "machine/trap.h"
#include "machine/mon.h"
#define jmp_buf_t jmp_buf
int db_active = 0;
/*
* Received keyboard interrupt sequence.
*/
kdb_kintr(regs)
register struct mc68020_saved_state *regs;
{
if (db_active == 0 && (boothowto & RB_KDB)) {
printf("\n\nkernel: keyboard interrupt\n");
kdb_trap(-1, regs);
}
}
#define T_BRKPT T_TRAP15
/*
* kdb_trap - field a TRACE or BPT trap
*/
extern jmp_buf_t *db_recover;
kdb_trap(type, regs)
int type;
register struct mc68020_saved_state *regs;
{
switch (type)
{
case T_TRACE: /* single-step */
case T_BRKPT: /* breakpoint */
/* case T_WATCHPOINT:*/
break;
#if 0
case EXC_BREAKPOINT:
type = T_BRKPT;
break;
#endif
case -1:
break;
default:
{
kdbprinttrap(type, 0);
if (db_recover != 0) {
db_printf("Caught exception in ddb.\n");
db_error("");
/*NOTREACHED*/
}
}
}
/* Should switch to kdb's own stack here. */
ddb_regs = *regs;
db_active++;
cnpollc(TRUE);
/* (void) setvideoenable(1);*/
db_trap(type, 0);
cnpollc(FALSE);
db_active--;
*regs = ddb_regs;
/*
* Indicate that single_step is for KDB.
* But lock out interrupts to prevent TRACE_KDB from setting the
* trace bit in the current SR (and trapping while exiting KDB).
*/
(void) spl7();
/*
if (!USERMODE(regs->sr) && (regs->sr & SR_T1) && (current_thread())) {
current_thread()->pcb->pcb_flag |= TRACE_KDB;
*/
/* if ((regs->sr & SR_T1) && (current_thread())) {
current_thread()->pcb->flag |= TRACE_KDB;
}*/
return(1);
}
extern char * trap_type[];
extern int TRAP_TYPES;
/*
* Print trap reason.
*/
kdbprinttrap(type, code)
int type, code;
{
printf("kernel: ");
if (type >= TRAP_TYPES || type < 0)
printf("type %d", type);
else
printf("%s", trap_type[type]);
printf(" trap\n");
}
/*
* Read bytes from kernel address space for debugger.
*/
extern jmp_buf_t db_jmpbuf;
void
db_read_bytes(addr, size, data)
vm_offset_t addr;
register int size;
register char *data;
{
register char *src;
src = (char *)addr;
while (--size >= 0)
*data++ = *src++;
}
/*
* Write bytes to kernel address space for debugger.
*/
void
db_write_bytes(addr, size, data)
vm_offset_t addr;
register int size;
register char *data;
{
register char *dst;
int oldmap0 = 0;
int oldmap1 = 0;
vm_offset_t addr1;
extern char etext;
if (addr >= VM_MIN_KERNEL_ADDRESS &&
addr <= (vm_offset_t)&etext)
{
mon_printf("stupid db_write_bytes\n");
#ifdef 0
oldmap0 = getpgmap(addr);
setpgmap(addr, (oldmap0 & ~PG_PROT) | PG_KW);
addr1 = sun_trunc_page(addr + size - 1);
if (sun_trunc_page(addr) != addr1) {
/* data crosses a page boundary */
oldmap1 = getpgmap(addr1);
setpgmap(addr1, (oldmap1 & ~PG_PROT) | PG_KW);
}
#endif
}
dst = (char *)addr;
while (--size >= 0)
*dst++ = *data++;
#if 0
if (oldmap0) {
setpgmap(addr, oldmap0);
if (oldmap1) {
setpgmap(addr1, oldmap1);
}
}
#endif
}

View File

@ -0,0 +1,572 @@
/*
* Mach Operating System
* Copyright (c) 1992 Carnegie Mellon University
* All Rights Reserved.
*
* Permission to use, copy, modify and distribute this software and its
* documentation is hereby granted, provided that both the copyright
* notice and this permission notice appear in all copies of the
* software, derivative works or modified versions, and any portions
* thereof, and that both notices appear in supporting documentation.
*
* CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
* CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
* ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
*
* Carnegie Mellon requests users of this software to return to
*
* Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
* School of Computer Science
* Carnegie Mellon University
* Pittsburgh PA 15213-3890
*
* any improvements or extensions that they make and grant Carnegie Mellon
* the rights to redistribute these changes.
*/
/*
* HISTORY
* $Log: db_trace.c,v $
* Revision 1.1 1993/08/08 12:22:09 glass
* lots of changes, too many printfs
*
* Revision 2.5 91/10/09 16:17:23 af
* Added parens in initializers for db_regs.
* [91/10/07 af]
*
* Revision 2.4 91/07/31 18:13:03 dbg
* Stack switching support.
* [91/07/12 dbg]
*
* Revision 2.3 91/03/16 14:58:27 rpd
* Replaced db_jmpbuf with db_recover.
* [91/03/14 rpd]
*
* Revision 2.2 90/08/27 22:11:36 dbg
* Import ddb/db_sym.h.
* [90/08/21 dbg]
* Detect the bad return address at the end of the stack trace.
* [90/08/07 dbg]
* Rewrote for new debugger.
* [90/07/23 dbg]
*
* Revision 2.3 90/05/29 18:38:17 rwd
* Don't continue trace when cursym == NULL
* [90/05/07 rwd]
*
* Revision 2.2 89/12/08 19:52:49 rwd
* Make <thread>$C work correctly
* [89/11/28 rwd]
*
* Revision 2.1 89/08/03 16:50:22 rwd
* Created.
*
* 25-May-89 Randall Dean (rwd) at Carnegie-Mellon University
* Added copyright to version originated by dbg. Fixed frame
* tracing to recognize fp=0 as end.
*
*/
#include "param.h"
#include "proc.h"
#include <machine/db_machdep.h>
#include <ddb/db_access.h>
#include <ddb/db_sym.h>
#include <ddb/db_variables.h>
#include <machine/setjmp.h>
#define jmp_buf_t jmp_buf
extern jmp_buf_t *db_recover;
/*
* Register list
*/
struct db_variable db_regs[] = {
{ "d0", (int *)&ddb_regs.d0, FCN_NULL },
{ "d1", (int *)&ddb_regs.d1, FCN_NULL },
{ "d2", (int *)&ddb_regs.d2, FCN_NULL },
{ "d3", (int *)&ddb_regs.d3, FCN_NULL },
{ "d4", (int *)&ddb_regs.d4, FCN_NULL },
{ "d5", (int *)&ddb_regs.d5, FCN_NULL },
{ "d6", (int *)&ddb_regs.d6, FCN_NULL },
{ "d7", (int *)&ddb_regs.d7, FCN_NULL },
{ "a0", (int *)&ddb_regs.a0, FCN_NULL },
{ "a1", (int *)&ddb_regs.a1, FCN_NULL },
{ "a2", (int *)&ddb_regs.a2, FCN_NULL },
{ "a3", (int *)&ddb_regs.a3, FCN_NULL },
{ "a4", (int *)&ddb_regs.a4, FCN_NULL },
{ "a5", (int *)&ddb_regs.a5, FCN_NULL },
{ "a6", (int *)&ddb_regs.a6, FCN_NULL },
{ "sp", (int *)&ddb_regs.sp, FCN_NULL },
{ "pc", (int *)&ddb_regs.pc, FCN_NULL },
{ "sr", (int *)&ddb_regs.sr, FCN_NULL }
};
struct db_variable *db_eregs = db_regs + sizeof(db_regs)/sizeof(db_regs[0]);
#define MAXINT 0x7fffffff
#define INKERNEL(va) (((vm_offset_t)(va)) >= VM_MIN_KERNEL_ADDRESS)
#define printf db_printf
#define get(addr, space) \
(db_get_value((db_addr_t)(addr), sizeof(int), FALSE))
#define NREGISTERS 48
struct stackpos {
int k_pc;
int k_fp;
int k_nargs;
int k_entry;
int k_caller;
int k_flags;
int k_regloc[NREGISTERS];
};
#define FR_SAVFP 0
#define FR_SAVPC 4
#define K_CALLTRAMP 1 /* for k_flags: caller is __sigtramp */
#define K_SIGTRAMP 2 /* for k_flags: this is __sigtramp */
stacktop(regs, sp)
register struct mc68020_saved_state *regs;
register struct stackpos *sp;
{
sp->k_regloc[0] = (int) &regs->d0;
sp->k_regloc[1] = (int) &regs->d1;
sp->k_regloc[2] = (int) &regs->d2;
sp->k_regloc[3] = (int) &regs->d3;
sp->k_regloc[4] = (int) &regs->d4;
sp->k_regloc[5] = (int) &regs->d5;
sp->k_regloc[6] = (int) &regs->d6;
sp->k_regloc[7] = (int) &regs->d7;
sp->k_regloc[8] = (int) &regs->a0;
sp->k_regloc[9] = (int) &regs->a1;
sp->k_regloc[10] = (int) &regs->a2;
sp->k_regloc[11] = (int) &regs->a3;
sp->k_regloc[12] = (int) &regs->a4;
sp->k_regloc[13] = (int) &regs->a5;
sp->k_fp = db_get_value((db_addr_t) &regs->a6,
sizeof(int), FALSE);
sp->k_pc = db_get_value((db_addr_t) &regs->pc,
sizeof(int), FALSE);
sp->k_flags = 0;
findentry( sp );
}
/*
The VAX has a very nice calling convention, and it is quite easy to
find saved registers, and the number of parameters. We are not nearly
so lucky. We must grub around in code for much of this information
(remember the PDP-11?), and the saved register list seems to be
especially hard to find.
*/
#define HIWORD 0xffff0000
#define LOWORD 0x0000ffff
#define LINKA6 0x4e560000 /* link a6,#x */
#define ADDLSP 0xdffc0000 /* addl #x,sp */
#define ADDWSP 0xdefc0000 /* addw #x,sp */
#define LEASP 0x4fef0000 /* lea sp@(x),sp*/
#define TSTBSP 0x4a2f0000 /* tstb sp@(x) */
#define INSMSK 0xfff80000
#define MOVLSP 0x2e800000 /* movl dx,sp@ */
#define MOVLD0 0x20000000 /* movl d0,dx */
#define MOVLA0 0x20400000 /* movl d0,ax */
#define MVLMSK 0xf1ff0000
#define MOVEML 0x48d70000 /* moveml #x,sp@ */
#define JSR 0x4eb80000 /* jsr x.[WL] */
#define JSRPC 0x4eba0000 /* jsr PC@( ) */
#define LONGBIT 0x00010000
#define BSR 0x61000000 /* bsr x */
#ifdef mc68020
#define BSRL 0x61ff0000 /* bsrl x */
#endif mc68020
#define BYTE3 0x0000ff00
#define LOBYTE 0x000000ff
#define ADQMSK 0xf1ff0000
#define ADDQSP 0x508f0000 /* addql #x,sp */
#define ADDQWSP 0x504f0000 /* addqw #x,sp */
struct nlist * trampsym = 0;
struct nlist * funcsym = 0;
nextframe(sp, kerneltrace)
register struct stackpos *sp;
int kerneltrace;
{
int val, regp, i;
db_addr_t addr;
db_addr_t calladdr;
register int instruc;
db_addr_t oldfp = sp->k_fp;
/*
* Find our entry point. Then find out
* which registers we saved, and map them.
* Our entry point is the address our caller called.
*/
calladdr = sp->k_caller;
addr = sp->k_entry;
if (sp->k_flags & K_CALLTRAMP){
#if 0
/* we never set CALLTRAMP */
/*
* caller was sigtramp:
* - no registers were saved;
* - no new frame-pointer
* - caller found in sigcontext structure.
* - WE become sigtramp
* - we have no parameters
* MUCH MAGIC USED IN FINDING CALLER'S PC.
*/
sp->k_pc = sp->k_caller;
sp->k_entry = trampsym->n_value;
sp->k_flags = 0;
addr = get( sp->k_fp+(sizeof(int))*(11), DSP);
sp->k_nargs = 0;
#if DEBUG
printf("nextframe: sigcontext at 0x%X, signaled at 0x%X\n",
addr, sp->k_caller);
#endif
errflg = 0;
#endif 0
} else {
if (addr == MAXINT){
/* we don't know what registers are involved here--invalidate all */
for(i=0; i<14; i++){
sp->k_regloc[i] = -1;
}
} else {
findregs( sp, addr );
}
/* find caller's pc and fp */
sp->k_pc = calladdr;
sp->k_fp = get(sp->k_fp+FR_SAVFP, DSP);
/*
now that we have assumed the identity of our caller, find
how many longwords of argument WE were called with.
*/
sp->k_flags = 0;
/*
* Don't dig around in user stack to find no. of args
* and entry point if just tracing the kernel
*/
if (kerneltrace && !INKERNEL(sp->k_fp)){
sp->k_nargs = 0;
sp->k_entry = MAXINT;
}
else
findentry( sp );
}
if (sp->k_fp == 0 || oldfp == sp->k_fp)
return 0;
return (sp->k_fp);
}
findentry( sp )
register struct stackpos *sp;
{
/*
set the k_nargs and k_entry fields in the stackpos structure. This
is called from stacktop() and from nextframe().
our caller will do an addq or addl or addw to sp just after
we return to pop off our arguments. find that instruction
and extract the value.
*/
register instruc;
register val;
db_addr_t addr, calladdr, nextword;
jmp_buf_t db_jmpbuf;
jmp_buf_t *savejmp = db_recover;
if (_setjmp(db_recover = &db_jmpbuf)) {
/* oops -- we touched something we ought not to have */
/* cannot trace caller of "start" */
sp->k_entry = MAXINT;
sp->k_nargs = 0;
db_recover = savejmp;
return;
}
addr = get(sp->k_fp+FR_SAVPC, DSP);
if (addr == 0) {
/* oops -- we touched something we ought not to have */
/* cannot trace caller of "start" */
sp->k_entry = MAXINT;
sp->k_nargs = 0;
db_recover = savejmp;
return;
}
instruc = get(addr-6, ISP);
nextword = get(addr-4, ISP);
db_recover = savejmp;
if ((instruc&HIWORD) == (JSR | LONGBIT)) {
/* longword offset here */
sp->k_caller = addr-6;
sp->k_entry = nextword;
#ifdef mc68020
} else if ((instruc&HIWORD) == BSRL) {
/* longword self-relative offset */
sp->k_caller = addr-6;
sp->k_entry = nextword + (addr-4);
#endif mc68020
} else {
instruc = nextword;
if ((instruc&HIWORD) == JSR) {
/* short word offset */
sp->k_caller = addr-4;
sp->k_entry = instruc & LOWORD;
} else if ((instruc&HIWORD) == BSR ){
/* short word, self-relative offset */
sp->k_caller = addr-4;
sp->k_entry = (addr-2) + (short)(instruc & LOWORD);
} else if ((instruc&HIWORD) == JSRPC ){
/* PC-relative, short word offset */
sp->k_caller = addr-4;
sp->k_entry = (addr-2) + (instruc & LOWORD);
} else {
if((instruc&BYTE3) == (BSR>>16)){
/* byte, self-relative offset */
sp->k_caller = addr-2;
sp->k_entry = addr + (char)(instruc&LOBYTE);
} else {
/* was a call through a proc parameter */
sp->k_caller = addr-2;
sp->k_entry = MAXINT;
/*
* we know that sigtramp calls your signal catcher
* this way -- see if this is the tramp: if so then:
* - set the K_CALLTRAMP flag, for use by nextframe();
* - take k_entry from __sigfunc array.
*/
#if 0
/* not in kernel */
/*
* the number (9) in the below expression is magic:
* it is the number of stack items below callee`s fp and
* sigtramp`s copy of the signal number.
*/
if (trampsym && (findsym( sp->k_caller, ISYM), cursym == trampsym) ){
int signl;
sp->k_flags |= K_CALLTRAMP;
if (funcsym){
signl = get( sp->k_fp+(sizeof (int))*(9), DSP );
sp->k_entry = get( funcsym->n_value+(sizeof(int(*)()))*signl, DSP);
} else {
sp->k_entry = -1;
}
errflg = 0;
#ifdef DEBUG
printf("Caller is sigtramp: signal is %d: entry is %x\n",
signl, sp->k_entry);
#endif
}
#ifdef DEBUG
else
printf("Non-tramp jsr a0@\n");
#endif
#endif 0
}
}
}
instruc = get(addr, ISP);
/* on bad days, the compiler dumps a register move here */
if ((instruc&MVLMSK) == MOVLA0 || (instruc&MVLMSK) == MOVLD0 ){
instruc = get( addr+= 2, ISP);
}
if ((instruc&ADQMSK) == ADDQSP
|| (instruc&ADQMSK) == ADDQWSP){
val = (instruc >> (16+9)) & 07;
if (val==0)
val = 8;
} else if ((instruc&HIWORD) == ADDLSP){
val = get(addr+2, ISP);
} else if ((instruc&HIWORD) == ADDWSP || (instruc&HIWORD) == LEASP ){
val = instruc&LOWORD;
} else {
val = 0;
}
sp->k_nargs = val/4;
}
/*
* look at the procedure prolog of the current called procedure.
* figure out which registers we saved, and where they are
*/
findregs( sp , addr)
register struct stackpos *sp;
register db_addr_t addr;
{
register long instruc, val, i;
int regp;
instruc = get( addr, ISP);
if ( (instruc&HIWORD) != LINKA6 )
goto nolink;
if (( instruc &= LOWORD) == 0) {
/* look for addl */
instruc = get(( addr += 4), ISP);
if ( (instruc&HIWORD) == ADDLSP){
instruc = get( addr+2, ISP);
addr += 6;
}
/* else { frame size is zero } */
} else {
/* link offset was non-zero -- sign extend it */
instruc <<= 16 ; instruc >>= 16;
}
/* we now have the negative frame size */
regp = sp->k_fp + instruc;
nolink:
/* find which registers were saved */
/* (expecting probe instruction next) */
instruc = get( addr, ISP );
if ((instruc&HIWORD) == TSTBSP)
addr += 4;
/* now we expect either a moveml or a movl */
instruc = get( addr, ISP );
if ((instruc&INSMSK) == MOVLSP){
/* only saving one register */
i = (instruc>>16) & 07;
sp->k_regloc[i] = regp;
} else if ((instruc&HIWORD) == MOVEML ) {
/* saving multiple registers or unoptimized code */
val = instruc & LOWORD;
i = 0;
while (val) {
if (val & 1) {
sp->k_regloc[i] = regp;
regp += sizeof (int);
}
val >>= 1;
i++;
}
}
/* else{ no registers saved } */
}
/*
* Frame tracing.
*/
void
db_stack_trace_cmd(addr, have_addr, count, modif)
db_expr_t addr;
int have_addr;
db_expr_t count;
char *modif;
{
int i, val, nargs, spa;
db_addr_t regp;
char * name;
struct stackpos pos;
boolean_t kernel_only = TRUE;
boolean_t trace_thread = FALSE;
{
register char *cp = modif;
register char c;
while ((c = *cp++) != 0) {
if (c == 'u')
kernel_only = FALSE;
}
}
if (count == -1)
count = 65535;
if (!have_addr) {
stacktop(&ddb_regs, &pos);
}
#if 0
else {
/*
* Only have user register state.
*/
register pcb_t t_pcb;
register struct mc68020_saved_state *user_regs;
t_pcb = (pcb_t) get(&th->pcb, 0);
user_regs = (struct mc68020_saved_state *)
db_get_value((db_addr_t) &t_pcb->user_regs,
sizeof(int), FALSE);
stacktop(user_regs, &pos);
/* foo*/
}
#endif
else {
pos.k_flags = 0;
pos.k_fp = addr;
pos.k_nargs = 0;
pos.k_pc = MAXINT;
pos.k_entry = MAXINT;
/* sorry, we cannot find our registers without knowing our pc */
for( i=0; i<NREGISTERS; pos.k_regloc[i++] = 0) ;
findentry( &pos );
}
while (count) {
count--;
/* HACK */
if (pos.k_pc == MAXINT) {
name = "?";
pos.k_pc = 0;
}
else {
db_find_sym_and_offset(pos.k_pc, &name, &val);
if (name == 0)
name = "?";
}
printf("%s", name);
if (pos.k_entry != MAXINT && name) {
char * entry_name;
int e_val;
db_find_sym_and_offset(pos.k_entry, &entry_name, &e_val);
if (entry_name != 0 && entry_name != name &&
e_val != val) {
printf("(?)\n");
printf("%s", entry_name);
}
}
printf("(");
regp = pos.k_fp+FR_SAVFP+4;
if ((nargs = pos.k_nargs)) {
while (nargs--) {
printf("%X", get(regp += 4, DSP));
if (nargs)
printf(",");
}
}
if (val == MAXINT)
printf(") at %X\n", pos.k_pc );
else
printf(") + %X\n", val);
/*
* Stop tracing if frame ptr no longer points into kernel
* stack.
*/
if (kernel_only && !INKERNEL(pos.k_fp))
break;
if (nextframe(&pos, kernel_only) == 0)
break;
}
}

63
sys/arch/sun3/dev/obio.c Normal file
View File

@ -0,0 +1,63 @@
#include "systm.h"
#include "machine/obio.h"
#include "machine/pte.h"
#include "machine/param.h"
#include "machine/mon.h"
#define ALL 0xFF
extern vm_offset_t intersil_va;
char *interrupt_reg;
vm_offset_t eeprom_va;
vm_offset_t memerr_va;
static struct obio_internal {
vm_offset_t *obio_internal_va;
vm_offset_t obio_addr;
unsigned char obio_cpu_mask;
unsigned int obio_size;
int obio_rw;
} obio_internal_dev[] = {
{&eeprom_va, OBIO_EEPROM, ALL, OBIO_EEPROM_SIZE ,1},
{&intersil_va, OBIO_CLOCK, ALL, OBIO_CLOCK_SIZE ,1},
{(vm_offset_t *) &interrupt_reg, OBIO_INTERREG, ALL, OBIO_INTERREG_SIZE,1},
{&memerr_va, OBIO_MEMERR, ALL, OBIO_MEMERR_SIZE ,1},
{NULL, 0, 0, 0 ,0}
/* {&ecc_va, OBIO_MEMERR, ALL, OBIO_MEMERR_SIZE }, */
};
/*
* this routine "configures" any internal OBIO devices which must be
* accessible before the mainline OBIO autoconfiguration as part of
* configure().
*
* In reality this maps in a few control registers. VA space is allocated
* out of the high_segment...
*
*/
void obio_internal_configure()
{
struct obio_internal *oip;
extern unsigned char cpu_machine_id;
vm_offset_t va, high_segment_alloc(), pte_proto,obio_pa;
int npages;
for (oip = obio_internal_dev; oip->obio_internal_va; oip++) {
if ((cpu_machine_id & oip->obio_cpu_mask) == 0) continue;
npages = (sun3_round_page(oip->obio_size)) >>PGSHIFT;
va = high_segment_alloc(npages);
if (!va)
mon_panic("obio_internal_configure: short pages for internal devs");
*oip->obio_internal_va = va;
pte_proto = PG_VALID|PG_SYSTEM|PG_NC|PG_OBIO;
if (oip->obio_rw)
pte_proto |= PG_WRITE;
obio_pa = oip->obio_addr;
for (; npages != 0; npages--, va += NBPG, obio_pa += NBPG)
set_pte(va, pte_proto | (obio_pa >> PGSHIFT));
}
}

View File

@ -0,0 +1,73 @@
/*
* Copyright (c) 1988 University of Utah.
* Copyright (c) 1982, 1986, 1990 The Regents of the University of California.
* All rights reserved.
*
* This code is derived from software contributed to Berkeley by
* the Systems Programming Group of the University of Utah Computer
* Science Department.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``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.
*
* from: Utah $Hdr: autoconf.c 1.31 91/01/21$
*
* from: @(#)autoconf.c 7.5 (Berkeley) 5/7/91
* autoconf.c,v 1.4 1993/07/07 06:26:59 cgd Exp
*/
/*
* Setup the system to run on the current machine.
*
* Configure() is called at boot time. Available
* devices are determined (from possibilities mentioned in ioconf.c),
* and the drivers are initialized.
*/
#include "sys/param.h"
#include "sys/systm.h"
#include "sys/map.h"
#include "sys/buf.h"
#include "sys/dkstat.h"
#include "sys/conf.h"
#include "sys/dmap.h"
#include "sys/reboot.h"
#include "../include/vmparam.h"
#include "../include/cpu.h"
#include "pte.h"
#include "isr.h"
struct isr isrqueue[NISR];
void
configure()
{
isrinit();
}

View File

@ -2,7 +2,7 @@
* machine-dependent clock routines; intersil7170
* by Adam Glass
*
* $Header: /cvsroot/src/sys/arch/sun3/sun3/clock.c,v 1.5 1993/08/02 02:08:25 glass Exp $
* $Header: /cvsroot/src/sys/arch/sun3/sun3/clock.c,v 1.6 1993/08/08 12:21:53 glass Exp $
*/
#include "systm.h"
@ -12,11 +12,10 @@
#include <machine/psl.h>
#include <machine/cpu.h>
#include "obio.h"
#include <machine/mon.h>
#include <machine/obio.h>
#define CLOCK_ADDR 0x6000000
#define intersil_clock ((struct intersil7170 *) CLOCK_ADDR)
#define intersil_clock ((struct intersil7170 *) intersil_va)
#define intersil_command(run, interrupt) \
(run | interrupt | INTERSIL_CMD_FREQ_32K | INTERSIL_CMD_24HR_MODE | \
INTERSIL_CMD_NORMAL_MODE)
@ -32,7 +31,7 @@
#define SECS_YEAR(year) \
(INTERSIL_LEAP_YEAR(year) ? SECS_PER_LEAP : SECS_PER_YEAR)
vm_offset_t intersil_va = NULL;
static int month_days[12] = {
31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
@ -57,6 +56,8 @@ static int month_days[12] = {
*/
void startrtclock()
{
if (!intersil_va)
mon_panic("clock: va address for rt clock not initialized");
intersil_clock->command_reg = intersil_command(INTERSIL_CMD_RUN,
INTERSIL_CMD_IDISABLE);
intersil_clock->interrupt_reg = INTERSIL_INTER_CSECONDS;

View File

@ -1 +1 @@
revision 1.4 intentionally removed
revision 1.5 intentionally removed

View File

@ -101,6 +101,7 @@ cninit()
*/
cn_tty = cp->cn_tp;
(*cp->cn_init)(cp);
cn_tty = cp->cn_tp;
}
cnopen(dev, flag, mode, p)

View File

@ -74,9 +74,12 @@ void set_pte_pmeg(pmeg_num, page_num,pte)
{
vm_offset_t va;
printf("starting set_pte_pmeg\n");
va = temp_seg_va;
set_segmap(temp_seg_va, pmeg_num);
va += NBPG*page_num;
set_pte(va, pte);
set_segmap(temp_seg_va, SEGINV);
printf("ending set_pte_pmeg\n");
}

View File

@ -0,0 +1,239 @@
/*
* Mach Operating System
* Copyright (c) 1992 Carnegie Mellon University
* All Rights Reserved.
*
* Permission to use, copy, modify and distribute this software and its
* documentation is hereby granted, provided that both the copyright
* notice and this permission notice appear in all copies of the
* software, derivative works or modified versions, and any portions
* thereof, and that both notices appear in supporting documentation.
*
* CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
* CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
* ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
*
* Carnegie Mellon requests users of this software to return to
*
* Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
* School of Computer Science
* Carnegie Mellon University
* Pittsburgh PA 15213-3890
*
* any improvements or extensions that they make and grant Carnegie Mellon
* the rights to redistribute these changes.
*/
/*
* HISTORY
* $Log: db_interface.c,v $
* Revision 1.1 1993/08/08 12:22:06 glass
* lots of changes, too many printfs
*
* Revision 2.6 92/01/03 20:31:01 dbg
* Ignore RB_KDB - always enter DDB.
* [91/11/06 dbg]
*
* Revision 2.5 91/07/31 18:12:50 dbg
* Stack switching support.
* [91/07/12 dbg]
*
* Revision 2.4 91/03/16 14:58:16 rpd
* Replaced db_nofault with db_recover.
* [91/03/14 rpd]
*
* Revision 2.3 90/10/25 14:47:16 rwd
* Added watchpoint support.
* [90/10/16 rwd]
*
* Revision 2.2 90/08/27 22:11:17 dbg
* Reduce lint.
* [90/08/07 dbg]
* Created.
* [90/07/25 dbg]
*
*/
/*
* Interface to new debugger.
*/
#include "param.h"
#include "proc.h"
#include <machine/db_machdep.h>
#include <sys/reboot.h>
#include <vm/vm_statistics.h>
#include <vm/pmap.h>
#include <setjmp.h>
#include <sys/systm.h> /* just for boothowto --eichin */
#include "machine/trap.h"
#include "machine/mon.h"
#define jmp_buf_t jmp_buf
int db_active = 0;
/*
* Received keyboard interrupt sequence.
*/
kdb_kintr(regs)
register struct mc68020_saved_state *regs;
{
if (db_active == 0 && (boothowto & RB_KDB)) {
printf("\n\nkernel: keyboard interrupt\n");
kdb_trap(-1, regs);
}
}
#define T_BRKPT T_TRAP15
/*
* kdb_trap - field a TRACE or BPT trap
*/
extern jmp_buf_t *db_recover;
kdb_trap(type, regs)
int type;
register struct mc68020_saved_state *regs;
{
switch (type)
{
case T_TRACE: /* single-step */
case T_BRKPT: /* breakpoint */
/* case T_WATCHPOINT:*/
break;
#if 0
case EXC_BREAKPOINT:
type = T_BRKPT;
break;
#endif
case -1:
break;
default:
{
kdbprinttrap(type, 0);
if (db_recover != 0) {
db_printf("Caught exception in ddb.\n");
db_error("");
/*NOTREACHED*/
}
}
}
/* Should switch to kdb's own stack here. */
ddb_regs = *regs;
db_active++;
cnpollc(TRUE);
/* (void) setvideoenable(1);*/
db_trap(type, 0);
cnpollc(FALSE);
db_active--;
*regs = ddb_regs;
/*
* Indicate that single_step is for KDB.
* But lock out interrupts to prevent TRACE_KDB from setting the
* trace bit in the current SR (and trapping while exiting KDB).
*/
(void) spl7();
/*
if (!USERMODE(regs->sr) && (regs->sr & SR_T1) && (current_thread())) {
current_thread()->pcb->pcb_flag |= TRACE_KDB;
*/
/* if ((regs->sr & SR_T1) && (current_thread())) {
current_thread()->pcb->flag |= TRACE_KDB;
}*/
return(1);
}
extern char * trap_type[];
extern int TRAP_TYPES;
/*
* Print trap reason.
*/
kdbprinttrap(type, code)
int type, code;
{
printf("kernel: ");
if (type >= TRAP_TYPES || type < 0)
printf("type %d", type);
else
printf("%s", trap_type[type]);
printf(" trap\n");
}
/*
* Read bytes from kernel address space for debugger.
*/
extern jmp_buf_t db_jmpbuf;
void
db_read_bytes(addr, size, data)
vm_offset_t addr;
register int size;
register char *data;
{
register char *src;
src = (char *)addr;
while (--size >= 0)
*data++ = *src++;
}
/*
* Write bytes to kernel address space for debugger.
*/
void
db_write_bytes(addr, size, data)
vm_offset_t addr;
register int size;
register char *data;
{
register char *dst;
int oldmap0 = 0;
int oldmap1 = 0;
vm_offset_t addr1;
extern char etext;
if (addr >= VM_MIN_KERNEL_ADDRESS &&
addr <= (vm_offset_t)&etext)
{
mon_printf("stupid db_write_bytes\n");
#ifdef 0
oldmap0 = getpgmap(addr);
setpgmap(addr, (oldmap0 & ~PG_PROT) | PG_KW);
addr1 = sun_trunc_page(addr + size - 1);
if (sun_trunc_page(addr) != addr1) {
/* data crosses a page boundary */
oldmap1 = getpgmap(addr1);
setpgmap(addr1, (oldmap1 & ~PG_PROT) | PG_KW);
}
#endif
}
dst = (char *)addr;
while (--size >= 0)
*dst++ = *data++;
#if 0
if (oldmap0) {
setpgmap(addr, oldmap0);
if (oldmap1) {
setpgmap(addr1, oldmap1);
}
}
#endif
}

View File

@ -0,0 +1,572 @@
/*
* Mach Operating System
* Copyright (c) 1992 Carnegie Mellon University
* All Rights Reserved.
*
* Permission to use, copy, modify and distribute this software and its
* documentation is hereby granted, provided that both the copyright
* notice and this permission notice appear in all copies of the
* software, derivative works or modified versions, and any portions
* thereof, and that both notices appear in supporting documentation.
*
* CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
* CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
* ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
*
* Carnegie Mellon requests users of this software to return to
*
* Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
* School of Computer Science
* Carnegie Mellon University
* Pittsburgh PA 15213-3890
*
* any improvements or extensions that they make and grant Carnegie Mellon
* the rights to redistribute these changes.
*/
/*
* HISTORY
* $Log: db_trace.c,v $
* Revision 1.1 1993/08/08 12:22:09 glass
* lots of changes, too many printfs
*
* Revision 2.5 91/10/09 16:17:23 af
* Added parens in initializers for db_regs.
* [91/10/07 af]
*
* Revision 2.4 91/07/31 18:13:03 dbg
* Stack switching support.
* [91/07/12 dbg]
*
* Revision 2.3 91/03/16 14:58:27 rpd
* Replaced db_jmpbuf with db_recover.
* [91/03/14 rpd]
*
* Revision 2.2 90/08/27 22:11:36 dbg
* Import ddb/db_sym.h.
* [90/08/21 dbg]
* Detect the bad return address at the end of the stack trace.
* [90/08/07 dbg]
* Rewrote for new debugger.
* [90/07/23 dbg]
*
* Revision 2.3 90/05/29 18:38:17 rwd
* Don't continue trace when cursym == NULL
* [90/05/07 rwd]
*
* Revision 2.2 89/12/08 19:52:49 rwd
* Make <thread>$C work correctly
* [89/11/28 rwd]
*
* Revision 2.1 89/08/03 16:50:22 rwd
* Created.
*
* 25-May-89 Randall Dean (rwd) at Carnegie-Mellon University
* Added copyright to version originated by dbg. Fixed frame
* tracing to recognize fp=0 as end.
*
*/
#include "param.h"
#include "proc.h"
#include <machine/db_machdep.h>
#include <ddb/db_access.h>
#include <ddb/db_sym.h>
#include <ddb/db_variables.h>
#include <machine/setjmp.h>
#define jmp_buf_t jmp_buf
extern jmp_buf_t *db_recover;
/*
* Register list
*/
struct db_variable db_regs[] = {
{ "d0", (int *)&ddb_regs.d0, FCN_NULL },
{ "d1", (int *)&ddb_regs.d1, FCN_NULL },
{ "d2", (int *)&ddb_regs.d2, FCN_NULL },
{ "d3", (int *)&ddb_regs.d3, FCN_NULL },
{ "d4", (int *)&ddb_regs.d4, FCN_NULL },
{ "d5", (int *)&ddb_regs.d5, FCN_NULL },
{ "d6", (int *)&ddb_regs.d6, FCN_NULL },
{ "d7", (int *)&ddb_regs.d7, FCN_NULL },
{ "a0", (int *)&ddb_regs.a0, FCN_NULL },
{ "a1", (int *)&ddb_regs.a1, FCN_NULL },
{ "a2", (int *)&ddb_regs.a2, FCN_NULL },
{ "a3", (int *)&ddb_regs.a3, FCN_NULL },
{ "a4", (int *)&ddb_regs.a4, FCN_NULL },
{ "a5", (int *)&ddb_regs.a5, FCN_NULL },
{ "a6", (int *)&ddb_regs.a6, FCN_NULL },
{ "sp", (int *)&ddb_regs.sp, FCN_NULL },
{ "pc", (int *)&ddb_regs.pc, FCN_NULL },
{ "sr", (int *)&ddb_regs.sr, FCN_NULL }
};
struct db_variable *db_eregs = db_regs + sizeof(db_regs)/sizeof(db_regs[0]);
#define MAXINT 0x7fffffff
#define INKERNEL(va) (((vm_offset_t)(va)) >= VM_MIN_KERNEL_ADDRESS)
#define printf db_printf
#define get(addr, space) \
(db_get_value((db_addr_t)(addr), sizeof(int), FALSE))
#define NREGISTERS 48
struct stackpos {
int k_pc;
int k_fp;
int k_nargs;
int k_entry;
int k_caller;
int k_flags;
int k_regloc[NREGISTERS];
};
#define FR_SAVFP 0
#define FR_SAVPC 4
#define K_CALLTRAMP 1 /* for k_flags: caller is __sigtramp */
#define K_SIGTRAMP 2 /* for k_flags: this is __sigtramp */
stacktop(regs, sp)
register struct mc68020_saved_state *regs;
register struct stackpos *sp;
{
sp->k_regloc[0] = (int) &regs->d0;
sp->k_regloc[1] = (int) &regs->d1;
sp->k_regloc[2] = (int) &regs->d2;
sp->k_regloc[3] = (int) &regs->d3;
sp->k_regloc[4] = (int) &regs->d4;
sp->k_regloc[5] = (int) &regs->d5;
sp->k_regloc[6] = (int) &regs->d6;
sp->k_regloc[7] = (int) &regs->d7;
sp->k_regloc[8] = (int) &regs->a0;
sp->k_regloc[9] = (int) &regs->a1;
sp->k_regloc[10] = (int) &regs->a2;
sp->k_regloc[11] = (int) &regs->a3;
sp->k_regloc[12] = (int) &regs->a4;
sp->k_regloc[13] = (int) &regs->a5;
sp->k_fp = db_get_value((db_addr_t) &regs->a6,
sizeof(int), FALSE);
sp->k_pc = db_get_value((db_addr_t) &regs->pc,
sizeof(int), FALSE);
sp->k_flags = 0;
findentry( sp );
}
/*
The VAX has a very nice calling convention, and it is quite easy to
find saved registers, and the number of parameters. We are not nearly
so lucky. We must grub around in code for much of this information
(remember the PDP-11?), and the saved register list seems to be
especially hard to find.
*/
#define HIWORD 0xffff0000
#define LOWORD 0x0000ffff
#define LINKA6 0x4e560000 /* link a6,#x */
#define ADDLSP 0xdffc0000 /* addl #x,sp */
#define ADDWSP 0xdefc0000 /* addw #x,sp */
#define LEASP 0x4fef0000 /* lea sp@(x),sp*/
#define TSTBSP 0x4a2f0000 /* tstb sp@(x) */
#define INSMSK 0xfff80000
#define MOVLSP 0x2e800000 /* movl dx,sp@ */
#define MOVLD0 0x20000000 /* movl d0,dx */
#define MOVLA0 0x20400000 /* movl d0,ax */
#define MVLMSK 0xf1ff0000
#define MOVEML 0x48d70000 /* moveml #x,sp@ */
#define JSR 0x4eb80000 /* jsr x.[WL] */
#define JSRPC 0x4eba0000 /* jsr PC@( ) */
#define LONGBIT 0x00010000
#define BSR 0x61000000 /* bsr x */
#ifdef mc68020
#define BSRL 0x61ff0000 /* bsrl x */
#endif mc68020
#define BYTE3 0x0000ff00
#define LOBYTE 0x000000ff
#define ADQMSK 0xf1ff0000
#define ADDQSP 0x508f0000 /* addql #x,sp */
#define ADDQWSP 0x504f0000 /* addqw #x,sp */
struct nlist * trampsym = 0;
struct nlist * funcsym = 0;
nextframe(sp, kerneltrace)
register struct stackpos *sp;
int kerneltrace;
{
int val, regp, i;
db_addr_t addr;
db_addr_t calladdr;
register int instruc;
db_addr_t oldfp = sp->k_fp;
/*
* Find our entry point. Then find out
* which registers we saved, and map them.
* Our entry point is the address our caller called.
*/
calladdr = sp->k_caller;
addr = sp->k_entry;
if (sp->k_flags & K_CALLTRAMP){
#if 0
/* we never set CALLTRAMP */
/*
* caller was sigtramp:
* - no registers were saved;
* - no new frame-pointer
* - caller found in sigcontext structure.
* - WE become sigtramp
* - we have no parameters
* MUCH MAGIC USED IN FINDING CALLER'S PC.
*/
sp->k_pc = sp->k_caller;
sp->k_entry = trampsym->n_value;
sp->k_flags = 0;
addr = get( sp->k_fp+(sizeof(int))*(11), DSP);
sp->k_nargs = 0;
#if DEBUG
printf("nextframe: sigcontext at 0x%X, signaled at 0x%X\n",
addr, sp->k_caller);
#endif
errflg = 0;
#endif 0
} else {
if (addr == MAXINT){
/* we don't know what registers are involved here--invalidate all */
for(i=0; i<14; i++){
sp->k_regloc[i] = -1;
}
} else {
findregs( sp, addr );
}
/* find caller's pc and fp */
sp->k_pc = calladdr;
sp->k_fp = get(sp->k_fp+FR_SAVFP, DSP);
/*
now that we have assumed the identity of our caller, find
how many longwords of argument WE were called with.
*/
sp->k_flags = 0;
/*
* Don't dig around in user stack to find no. of args
* and entry point if just tracing the kernel
*/
if (kerneltrace && !INKERNEL(sp->k_fp)){
sp->k_nargs = 0;
sp->k_entry = MAXINT;
}
else
findentry( sp );
}
if (sp->k_fp == 0 || oldfp == sp->k_fp)
return 0;
return (sp->k_fp);
}
findentry( sp )
register struct stackpos *sp;
{
/*
set the k_nargs and k_entry fields in the stackpos structure. This
is called from stacktop() and from nextframe().
our caller will do an addq or addl or addw to sp just after
we return to pop off our arguments. find that instruction
and extract the value.
*/
register instruc;
register val;
db_addr_t addr, calladdr, nextword;
jmp_buf_t db_jmpbuf;
jmp_buf_t *savejmp = db_recover;
if (_setjmp(db_recover = &db_jmpbuf)) {
/* oops -- we touched something we ought not to have */
/* cannot trace caller of "start" */
sp->k_entry = MAXINT;
sp->k_nargs = 0;
db_recover = savejmp;
return;
}
addr = get(sp->k_fp+FR_SAVPC, DSP);
if (addr == 0) {
/* oops -- we touched something we ought not to have */
/* cannot trace caller of "start" */
sp->k_entry = MAXINT;
sp->k_nargs = 0;
db_recover = savejmp;
return;
}
instruc = get(addr-6, ISP);
nextword = get(addr-4, ISP);
db_recover = savejmp;
if ((instruc&HIWORD) == (JSR | LONGBIT)) {
/* longword offset here */
sp->k_caller = addr-6;
sp->k_entry = nextword;
#ifdef mc68020
} else if ((instruc&HIWORD) == BSRL) {
/* longword self-relative offset */
sp->k_caller = addr-6;
sp->k_entry = nextword + (addr-4);
#endif mc68020
} else {
instruc = nextword;
if ((instruc&HIWORD) == JSR) {
/* short word offset */
sp->k_caller = addr-4;
sp->k_entry = instruc & LOWORD;
} else if ((instruc&HIWORD) == BSR ){
/* short word, self-relative offset */
sp->k_caller = addr-4;
sp->k_entry = (addr-2) + (short)(instruc & LOWORD);
} else if ((instruc&HIWORD) == JSRPC ){
/* PC-relative, short word offset */
sp->k_caller = addr-4;
sp->k_entry = (addr-2) + (instruc & LOWORD);
} else {
if((instruc&BYTE3) == (BSR>>16)){
/* byte, self-relative offset */
sp->k_caller = addr-2;
sp->k_entry = addr + (char)(instruc&LOBYTE);
} else {
/* was a call through a proc parameter */
sp->k_caller = addr-2;
sp->k_entry = MAXINT;
/*
* we know that sigtramp calls your signal catcher
* this way -- see if this is the tramp: if so then:
* - set the K_CALLTRAMP flag, for use by nextframe();
* - take k_entry from __sigfunc array.
*/
#if 0
/* not in kernel */
/*
* the number (9) in the below expression is magic:
* it is the number of stack items below callee`s fp and
* sigtramp`s copy of the signal number.
*/
if (trampsym && (findsym( sp->k_caller, ISYM), cursym == trampsym) ){
int signl;
sp->k_flags |= K_CALLTRAMP;
if (funcsym){
signl = get( sp->k_fp+(sizeof (int))*(9), DSP );
sp->k_entry = get( funcsym->n_value+(sizeof(int(*)()))*signl, DSP);
} else {
sp->k_entry = -1;
}
errflg = 0;
#ifdef DEBUG
printf("Caller is sigtramp: signal is %d: entry is %x\n",
signl, sp->k_entry);
#endif
}
#ifdef DEBUG
else
printf("Non-tramp jsr a0@\n");
#endif
#endif 0
}
}
}
instruc = get(addr, ISP);
/* on bad days, the compiler dumps a register move here */
if ((instruc&MVLMSK) == MOVLA0 || (instruc&MVLMSK) == MOVLD0 ){
instruc = get( addr+= 2, ISP);
}
if ((instruc&ADQMSK) == ADDQSP
|| (instruc&ADQMSK) == ADDQWSP){
val = (instruc >> (16+9)) & 07;
if (val==0)
val = 8;
} else if ((instruc&HIWORD) == ADDLSP){
val = get(addr+2, ISP);
} else if ((instruc&HIWORD) == ADDWSP || (instruc&HIWORD) == LEASP ){
val = instruc&LOWORD;
} else {
val = 0;
}
sp->k_nargs = val/4;
}
/*
* look at the procedure prolog of the current called procedure.
* figure out which registers we saved, and where they are
*/
findregs( sp , addr)
register struct stackpos *sp;
register db_addr_t addr;
{
register long instruc, val, i;
int regp;
instruc = get( addr, ISP);
if ( (instruc&HIWORD) != LINKA6 )
goto nolink;
if (( instruc &= LOWORD) == 0) {
/* look for addl */
instruc = get(( addr += 4), ISP);
if ( (instruc&HIWORD) == ADDLSP){
instruc = get( addr+2, ISP);
addr += 6;
}
/* else { frame size is zero } */
} else {
/* link offset was non-zero -- sign extend it */
instruc <<= 16 ; instruc >>= 16;
}
/* we now have the negative frame size */
regp = sp->k_fp + instruc;
nolink:
/* find which registers were saved */
/* (expecting probe instruction next) */
instruc = get( addr, ISP );
if ((instruc&HIWORD) == TSTBSP)
addr += 4;
/* now we expect either a moveml or a movl */
instruc = get( addr, ISP );
if ((instruc&INSMSK) == MOVLSP){
/* only saving one register */
i = (instruc>>16) & 07;
sp->k_regloc[i] = regp;
} else if ((instruc&HIWORD) == MOVEML ) {
/* saving multiple registers or unoptimized code */
val = instruc & LOWORD;
i = 0;
while (val) {
if (val & 1) {
sp->k_regloc[i] = regp;
regp += sizeof (int);
}
val >>= 1;
i++;
}
}
/* else{ no registers saved } */
}
/*
* Frame tracing.
*/
void
db_stack_trace_cmd(addr, have_addr, count, modif)
db_expr_t addr;
int have_addr;
db_expr_t count;
char *modif;
{
int i, val, nargs, spa;
db_addr_t regp;
char * name;
struct stackpos pos;
boolean_t kernel_only = TRUE;
boolean_t trace_thread = FALSE;
{
register char *cp = modif;
register char c;
while ((c = *cp++) != 0) {
if (c == 'u')
kernel_only = FALSE;
}
}
if (count == -1)
count = 65535;
if (!have_addr) {
stacktop(&ddb_regs, &pos);
}
#if 0
else {
/*
* Only have user register state.
*/
register pcb_t t_pcb;
register struct mc68020_saved_state *user_regs;
t_pcb = (pcb_t) get(&th->pcb, 0);
user_regs = (struct mc68020_saved_state *)
db_get_value((db_addr_t) &t_pcb->user_regs,
sizeof(int), FALSE);
stacktop(user_regs, &pos);
/* foo*/
}
#endif
else {
pos.k_flags = 0;
pos.k_fp = addr;
pos.k_nargs = 0;
pos.k_pc = MAXINT;
pos.k_entry = MAXINT;
/* sorry, we cannot find our registers without knowing our pc */
for( i=0; i<NREGISTERS; pos.k_regloc[i++] = 0) ;
findentry( &pos );
}
while (count) {
count--;
/* HACK */
if (pos.k_pc == MAXINT) {
name = "?";
pos.k_pc = 0;
}
else {
db_find_sym_and_offset(pos.k_pc, &name, &val);
if (name == 0)
name = "?";
}
printf("%s", name);
if (pos.k_entry != MAXINT && name) {
char * entry_name;
int e_val;
db_find_sym_and_offset(pos.k_entry, &entry_name, &e_val);
if (entry_name != 0 && entry_name != name &&
e_val != val) {
printf("(?)\n");
printf("%s", entry_name);
}
}
printf("(");
regp = pos.k_fp+FR_SAVFP+4;
if ((nargs = pos.k_nargs)) {
while (nargs--) {
printf("%X", get(regp += 4, DSP));
if (nargs)
printf(",");
}
}
if (val == MAXINT)
printf(") at %X\n", pos.k_pc );
else
printf(") + %X\n", val);
/*
* Stop tracing if frame ptr no longer points into kernel
* stack.
*/
if (kernel_only && !INKERNEL(pos.k_fp))
break;
if (nextframe(&pos, kernel_only) == 0)
break;
}
}

View File

@ -0,0 +1,53 @@
.globl _cnt
.data
.globl _intrcnt
_intrcnt:
/* 0 1 2 3 4 5 6 7, spurious */
.long 0, 0, 0, 0, 0, 0, 0, 0, 0
.text
#define INTERRUPT_HANDLE(interrupt num) \
addql #1,_intrcnt+interrupt_num \
movw sr,sp@- | push current SR value \
clrw sp@- | padded to longword \
jbsr _intrhand | handle interrupt \
addql #4,sp | pop SR
moveml sp@+,#0x0303 \
addql #2,sp \
addql #1, _cnt+V_INTR \
jra rei
.globl _level1intr, _level2intr, _level3intr, _level4intr
.globl _level5intr, _level6intr, _level7intr
/* system enable register 1 */
_level1intr:
INTERRUPT_HANDLE(1)
/* system enable register 2, SCSI */
_level2intr:
INTERRUPT_HANDLE(2)
/* system enable register 3, Ethernet */
_level3intr:
INTERRUPT_HANDLE(3)
/* video */
_level4intr:
INTERRUPT_HANDLE(4)
/* clock */
_level5intr:
INTERRUPT_HANDLE(5)
/* SCCs */
_level6intr:
INTERRUPT_HANDLE(6)
/* Memory Error */
_level7intr:
INTERRUPT_HANDLE(7)
_spurintr:

View File

@ -98,4 +98,4 @@ _szicode:
#include "signal.s"
#include "process.s"
#include "softint.s"
#include "interrupt.s"

View File

@ -9,21 +9,24 @@
#include "machine/control.h"
#include "machine/pte.h"
#include "machine/pmap.h"
#include "machine/idprom.h"
#include "machine/frame.h"
#include "vector.h"
#include "../dev/idprom.h"
unsigned int *old_vector_table;
static struct idprom identity_prom;
unsigned char cpu_machine_id;
vm_offset_t high_segment_free_start = 0;
vm_offset_t high_segment_free_end = 0;
int msgbufmapped = 0;
struct msgbuf *msgbufp = NULL;
caddr_t vmmap;
extern vm_offset_t tmp_vpages[];
static void initialize_vector_table()
{
int i;
@ -38,11 +41,34 @@ static void initialize_vector_table()
mon_printf("initializing vector table (ended)\n");
}
vm_offset_t high_segment_alloc(npages)
int npages;
{
int i;
vm_offset_t va, tmp;
if (npages == 0)
mon_panic("panic: request for high segment allocation of 0 pages");
if (high_segment_free_start == high_segment_free_end) return NULL;
va = high_segment_free_start + (npages*NBPG);
if (va > high_segment_free_end) return NULL;
tmp = high_segment_free_start;
high_segment_free_start = va;
return tmp;
}
void sun3_stop()
{
mon_exit_to_mon();
}
void sun3_printf(str)
char *str;
{
mon_printf(str);
}
/*
* will this actually work or will it have problems because of this supposed
* wierd thing with (word or short?) aligned addresses
@ -77,7 +103,7 @@ void sun3_context_equiv()
void sun3_vm_init()
{
unsigned int monitor_memory = 0;
vm_offset_t va, eva, sva, pte;
vm_offset_t va, eva, sva, pte, temp_seg;
extern char start[], etext[], end[];
unsigned char sme;
int valid;
@ -99,6 +125,8 @@ void sun3_vm_init()
}
virtual_avail = sun3_round_seg(end); /* start a new segment */
mon_printf("literal kernel_end %x\nvirtual_avail_after %x\n",
end, virtual_avail);
virtual_end = VM_MAX_KERNEL_ADDRESS;
if (romp->romvecVersion >=1)
@ -179,6 +207,56 @@ void sun3_vm_init()
va += NBSG;
}
/*
* we need to kill off a segment to handle the stupid non-contexted
* pmeg
*
*/
temp_seg = sun3_round_seg(virtual_avail);
set_temp_seg_addr(temp_seg);
mon_printf("%x virtual bytes lost allocating temporary segment for pmap\n",
temp_seg - virtual_avail);
set_segmap(temp_seg, SEGINV);
virtual_avail = temp_seg + NBSG;
mon_printf("temp_seg: starts at %x ends at %x\n", temp_seg, virtual_avail);
/* allocating page for msgbuf */
sme = get_segmap(virtual_avail);
if (sme == SEGINV)
mon_printf("bad pmeg encountered while looking for msgbuf page\n");
pmeg_steal(sme);
eva = sun3_round_up_seg(virtual_avail);
/* msgbuf */
avail_end -= NBPG;
msgbufp = (struct msgbuf *) virtual_avail;
pte = PG_VALID | PG_WRITE |PG_SYSTEM | PG_NC | (avail_end >>PGSHIFT);
set_pte((vm_offset_t) msgbufp, pte);
msgbufmapped = 1;
/* cleaning rest of page */
virtual_avail +=NBPG;
for (va = virtual_avail; va < eva; va += NBPG)
set_pte(va, PG_INVAL);
/* vmmap (used by /dev/mem */
vmmap = (caddr_t) virtual_avail;
virtual_avail += NBPG;
/*
* vpages array:
* just some virtual addresses for temporary mappings
* in the pmap module
*/
tmp_vpages[0] = virtual_avail;
virtual_avail += NBPG;
tmp_vpages[1] = virtual_avail;
virtual_avail += NBPG;
virtual_avail = eva;
mon_printf("unmapping range: %x to %x\n", virtual_avail, virtual_end);
/*
* unmap kernel virtual space (only segments. if it squished ptes, bad
* things might happen.
@ -196,7 +274,6 @@ void sun3_vm_init()
void sun3_verify_hardware()
{
unsigned char cpu_machine_id;
unsigned char arch;
int cpu_match = 0;
char *cpu_string;
@ -252,6 +329,100 @@ void sun3_verify_hardware()
mon_printf("kernel configured for Sun 3/%s\n", cpu_string);
}
/*
* Print out a traceback for the caller - can be called anywhere
* within the kernel or from the monitor by typing "g4" (for sun-2
* compatibility) or "w trace". This causes the monitor to call
* the v_handler() routine which will call tracedump() for these cases.
*/
/*VARARGS0*/
tracedump(x1)
caddr_t x1;
{
struct funcall_frame *fp = (struct funcall_frame *)(&x1 - 2);
u_int tospage = btoc(fp);
mon_printf("Begin traceback...fp = %x\n", fp);
while (btoc(fp) == tospage) {
if (fp == fp->fr_savfp) {
mon_printf("FP loop at %x", fp);
break;
}
mon_printf("Called from %x, fp=%x, args=%x %x %x %x\n",
fp->fr_savpc, fp->fr_savfp,
fp->fr_arg[0], fp->fr_arg[1], fp->fr_arg[2], fp->fr_arg[3]);
fp = fp->fr_savfp;
}
mon_printf("End traceback...\n");
}
/*
* Handler for monitor vector cmd -
* For now we just implement the old "g0" and "g4"
* commands and a printf hack. [lifted from freed cmu mach3 sun3 port]
*/
void
v_handler(addr, str)
int addr;
char *str;
{
switch (*str) {
case '\0':
/*
* No (non-hex) letter was specified on
* command line, use only the number given
*/
switch (addr) {
case 0: /* old g0 */
case 0xd: /* 'd'ump short hand */
panic("zero");
/*NOTREACHED*/
case 4: /* old g4 */
tracedump();
break;
default:
goto err;
}
break;
case 'p': /* 'p'rint string command */
case 'P':
mon_printf("%s\n", (char *)addr);
break;
case '%': /* p'%'int anything a la printf */
mon_printf(str, addr);
mon_printf("\n");
break;
case 't': /* 't'race kernel stack */
case 'T':
tracedump();
break;
case 'u': /* d'u'mp hack ('d' look like hex) */
case 'U':
if (addr == 0xd) {
panic("zero");
} else
goto err;
break;
default:
err:
mon_printf("Don't understand 0x%x '%s'\n", addr, str);
}
}
void sun3_monitor_hooks()
{
if (romp->romvecVersion >= 2)
*romp->vector_cmd = v_handler;
}
void sun3_bootstrap()
{
static char hello[] = "hello world";
@ -273,8 +444,12 @@ void sun3_bootstrap()
sun3_vm_init(); /* handle kernel mapping problems, etc */
mon_printf("ending sun3 vm init\n");
sun3_monitor_hooks();
pmap_bootstrap(); /* */
internal_configure(); /* stuff that can't wait for configure() */
main();
mon_exit_to_mon();

View File

@ -45,12 +45,17 @@ void cpu_startup()
cold = 0;
}
void internal_configure()
{
obio_internal_configure();
}
void consinit()
{
extern void cninit();
mon_printf("determining console:");
mon_printf("determining console\n");
cninit();
mon_printf("determining console (completed)\n");
}
void cpu_reset()
@ -549,6 +554,9 @@ int waittime = -1;
void boot(howto)
int howto;
{
mon_printf("booting....\n");
mon_exit_to_mon();
if ((howto&RB_NOSYNC) == 0 && waittime < 0 && bfreelist[0].b_forw) {
struct buf *bp;
int iter, nbusy;
@ -709,3 +717,40 @@ netintr()
}
#endif
}
intrhand(sr)
int sr;
{
register struct isr *isr;
register int found = 0;
register int ipl;
extern struct isr isrqueue[];
ipl = (sr >> 8) & 7;
switch (ipl) {
case 1:
case 2:
case 3:
case 4:
case 5:
case 6:
case 7:
ipl = ISRIPL(ipl);
isr = isrqueue[ipl].isr_forw;
for (; isr != &isrqueue[ipl]; isr = isr->isr_forw) {
if ((isr->isr_intr)(isr->isr_arg)) {
found++;
break;
}
}
if (found == 0)
printf("stray interrupt, sr 0x%x\n", sr);
break;
case 0:
default:
printf("intrhand: unexpected sr 0x%x\n", sr);
break;
}
}

63
sys/arch/sun3/sun3/obio.c Normal file
View File

@ -0,0 +1,63 @@
#include "systm.h"
#include "machine/obio.h"
#include "machine/pte.h"
#include "machine/param.h"
#include "machine/mon.h"
#define ALL 0xFF
extern vm_offset_t intersil_va;
char *interrupt_reg;
vm_offset_t eeprom_va;
vm_offset_t memerr_va;
static struct obio_internal {
vm_offset_t *obio_internal_va;
vm_offset_t obio_addr;
unsigned char obio_cpu_mask;
unsigned int obio_size;
int obio_rw;
} obio_internal_dev[] = {
{&eeprom_va, OBIO_EEPROM, ALL, OBIO_EEPROM_SIZE ,1},
{&intersil_va, OBIO_CLOCK, ALL, OBIO_CLOCK_SIZE ,1},
{(vm_offset_t *) &interrupt_reg, OBIO_INTERREG, ALL, OBIO_INTERREG_SIZE,1},
{&memerr_va, OBIO_MEMERR, ALL, OBIO_MEMERR_SIZE ,1},
{NULL, 0, 0, 0 ,0}
/* {&ecc_va, OBIO_MEMERR, ALL, OBIO_MEMERR_SIZE }, */
};
/*
* this routine "configures" any internal OBIO devices which must be
* accessible before the mainline OBIO autoconfiguration as part of
* configure().
*
* In reality this maps in a few control registers. VA space is allocated
* out of the high_segment...
*
*/
void obio_internal_configure()
{
struct obio_internal *oip;
extern unsigned char cpu_machine_id;
vm_offset_t va, high_segment_alloc(), pte_proto,obio_pa;
int npages;
for (oip = obio_internal_dev; oip->obio_internal_va; oip++) {
if ((cpu_machine_id & oip->obio_cpu_mask) == 0) continue;
npages = (sun3_round_page(oip->obio_size)) >>PGSHIFT;
va = high_segment_alloc(npages);
if (!va)
mon_panic("obio_internal_configure: short pages for internal devs");
*oip->obio_internal_va = va;
pte_proto = PG_VALID|PG_SYSTEM|PG_NC|PG_OBIO;
if (oip->obio_rw)
pte_proto |= PG_WRITE;
obio_pa = oip->obio_addr;
for (; npages != 0; npages--, va += NBPG, obio_pa += NBPG)
set_pte(va, pte_proto | (obio_pa >> PGSHIFT));
}
}

View File

@ -20,14 +20,15 @@
/*
* globals needed by the vm system
*
* [frankly the stupid vm system should allocate these]
*/
vm_offset_t virtual_avail, virtual_end;
vm_offset_t avail_start, avail_end;
int msgbufmapped = 0;
struct msgbuf *msgbufp = NULL;
caddr_t vmmap;
/* current_projects:
@ -77,6 +78,12 @@ caddr_t vmmap;
#define PMAP_LOCK() s = splpmap()
#define PMAP_UNLOCK() splx(s)
#define dequeue_first(val, type, queue) { \
val = (type) queue_first(queue); \
dequeue_head(queue); \
}
/*
* locking issues:
*
@ -95,8 +102,8 @@ struct pv_entry {
};
typedef struct pv_entry *pv_entry_t;
pv_entry_t pv_head_table;
#define pa_to_pvp(pa) &pv_head_table[pa >>PGSHIFT]
pv_entry_t pv_head_table = NULL;
#define pa_to_pvp(pa) &pv_head_table[PA_PGNUM(pa)]
#define PV_VALID 8
#define PV_WRITE 4
@ -110,10 +117,10 @@ pv_entry_t pv_head_table;
/* cache support */
static unsigned char *pv_cache_table = NULL;
#define set_cache_flags(pa, flags) \
pv_cache_table[pa >>PGSHIFT] |= flags & PV_NC
pv_cache_table[PA_PGNUM(pa)] |= flags & PV_NC
#define force_cache_flags(pa, flags) \
pv_cache_table[pa >>PGSHIFT] = flags & PV_NC
#define get_cache_flags(pa) (pv_cache_table[pa >>PGSHIFT])
pv_cache_table[PA_PGNUM(pa)] = flags & PV_NC
#define get_cache_flags(pa) (pv_cache_table[PA_PGNUM(pa)])
/* modified bits support */
static unsigned char *pv_modified_table = NULL;
@ -123,7 +130,7 @@ static unsigned char *pv_modified_table = NULL;
(pte & (PG_OBIO|PG_VME16D|PG_VME32D) ? 0 : \
((pte & PG_MOD) >>PG_MOD_SHIFT))
int pv_initialized = 0;
#define PMEG_INVAL (NPMEG-1)
#define PMEG_NULL (pmeg_t) NULL
@ -243,14 +250,14 @@ void pmap_protect __P((pmap_t pmap, vm_offset_t sva, vm_offset_t eva, vm_prot_t
void pmap_update __P((void));
int get_pte_val(pmap, va,ptep)
int get_pte_val(pmap, va, ptep)
pmap_t pmap;
vm_offset_t va,*ptep;
vm_offset_t va, *ptep;
{
int saved_context,s;
unsigned char sme;
pmeg_t pmegp;
int module_debug;
if (pmap->pm_context) {
PMAP_LOCK();
@ -316,10 +323,10 @@ void context_allocate(pmap)
if (queue_empty(&context_free_queue)) { /* steal one from active*/
if (queue_empty(&context_active_queue))
panic("pmap: no contexts to be found");
context = (context_t) dequeue_head(&context_active_queue);
dequeue_first(context, context_t, &context_active_queue);
context_free(context->context_upmap);
} else
context = (context_t) dequeue_head(&context_free_queue);
dequeue_first(context, context_t, &context_free_queue);
enqueue_tail(&context_active_queue,context);
if (context->context_upmap != NULL)
panic("pmap: context in use???");
@ -384,6 +391,40 @@ void pmeg_steal(pmeg_num)
remqueue(&pmeg_free_queue, pmegp);
}
void pmeg_clean(pmegp)
pmeg_t pmegp;
{
int i;
for (i = 0; i < NPAGSEG; i++)
set_pte_pmeg(pmegp->pmeg_index, i, PG_INVAL);
}
/*
* This routine makes sure that pmegs on the pmeg_free_queue contain
* no valid ptes. It pulls things off the queue, cleans them, and
* puts them at the end. Ending condition is finding the first queue element
* at the head of the queue again.
*/
void pmeg_clean_free()
{
pmeg_t pmegp, pmegp_first;
int loop = 0;
if (queue_empty(&pmeg_free_queue))
panic("pmap: no free pmegs available to clean");
pmegp_first = NULL;
dequeue_first(pmegp, pmeg_t, &pmeg_free_queue);
while (pmegp != pmegp_first) {
pmeg_clean(pmegp);
if (pmegp_first == NULL)
pmegp_first = pmegp;
enqueue_tail(&pmeg_free_queue, pmegp);
dequeue_first(pmegp, pmeg_t, &pmeg_free_queue);
}
}
void pmeg_flush(pmegp)
pmeg_t pmegp;
{
@ -396,7 +437,8 @@ void pmeg_flush(pmegp)
if (pmegp->pmeg_owner) {
pte = get_pte_pmeg(pmegp->pmeg_index, i);
if (pte & PG_VALID) {
save_modified_bits(pte);
if (pv_initialized)
save_modified_bits(pte);
pv_unlink(pmegp->pmeg_owner, PG_PA(pte), pmegp->pmeg_va);
pmegp->pmeg_vpages--;
set_pte_pmeg(pmegp->pmeg_index, i, PG_INVAL);
@ -418,16 +460,16 @@ pmeg_t pmeg_allocate_invalid(pmap, va)
pmeg_t pmegp;
if (!queue_empty(&pmeg_free_queue))
pmegp = (pmeg_t) dequeue_head(&pmeg_free_queue);
else if (!queue_empty(&pmeg_inactive_queue)){
pmegp = (pmeg_t) dequeue_head(&pmeg_inactive_queue);
dequeue_first(pmegp, pmeg_t, &pmeg_free_queue)
else if (!queue_empty(&pmeg_inactive_queue)) {
dequeue_first(pmegp, pmeg_t, &pmeg_inactive_queue);
pmeg_flush(pmegp);
}
else if (!queue_empty(&pmeg_active_queue)) {
pmegp = (pmeg_t) dequeue_head(&pmeg_active_queue);
dequeue_first(pmegp, pmeg_t, &pmeg_active_queue);
while (pmegp->pmeg_owner == kernel_pmap) {
enqueue_tail(&pmeg_inactive_queue, pmegp);
pmegp = (pmeg_t) dequeue_head(&pmeg_active_queue);
enqueue_tail(&pmeg_active_queue, pmegp);
dequeue_first(pmegp, pmeg_t, &pmeg_active_queue);
}
pmap_remove_range(pmegp->pmeg_owner, pmegp->pmeg_va,
pmegp->pmeg_va+NBSG);
@ -441,12 +483,14 @@ pmeg_t pmeg_allocate_invalid(pmap, va)
pmegp = (pmeg_t) enqueue_tail(&pmeg_active_queue, pmegp);
return pmegp;
}
void pmeg_release(pmegp)
pmeg_t pmegp;
{
remqueue(&pmeg_active_queue, pmegp);
enqueue_tail(&pmeg_inactive_queue, pmegp);
}
void pmeg_release_empty(pmegp, segnum, update)
pmeg_t pmegp;
int segnum;
@ -521,6 +565,7 @@ unsigned char pv_compute_cache(head)
pv_entry_t pv;
int cread, cwrite, ccache, clen;
if (!pv_initialized) return 0;
cread = cwrite = ccache = clen = 0;
if (!head->pv_pmap) return 0;
for (pv = head; pv != NULL; pv=pv->pv_next) {
@ -542,6 +587,7 @@ int pv_compute_modified(head)
unsigned int seg;
if (!pv_initialized) return 0;
if (!head->pv_pmap) return 0;
modified = 0;
for (pv = head; pv != NULL; pv=pv->pv_next) {
@ -567,6 +613,7 @@ void pv_remove_all(pa)
{
pv_entry_t npv,head,last;
if (!pv_initialized) return 0;
head = pa_to_pvp(pa);
for (npv = head ; npv != NULL; last= npv, npv = npv->pv_next ) {
if (npv->pv_pmap == NULL) continue; /* empty */
@ -583,42 +630,58 @@ unsigned char pv_link(pmap, pa, va, flags)
pv_entry_t last,pv,head,npv;
int s;
if (!pv_initialized) return 0;
head = pv = pa_to_pvp(pa);
PMAP_LOCK();
printf("entering pv_link, pv == %x\n", pv);
printf("entering pv_link, pv_head_table == %x\n", pv_head_table);
printf("entering pv_link, pa == %x pgnum %x\n", pa, PA_PGNUM(pa));
if (pv->pv_pmap == NULL) { /* not currently "managed" */
pv->pv_va = va;
pv->pv_pmap = pmap,
pv->pv_next = NULL;
pv->pv_flags = flags;
printf("pv_link: before force_cache_flags\n");
force_cache_flags(pa, flags);
printf("pv_link: not currently managed\n");
return flags & PV_NC;
}
printf("entering pv_link loop\n");
for (npv = pv ; npv != NULL; last= npv, npv = npv->pv_next ) {
if ((pv->pv_pmap != pmap) || (pv->pv_va != va)) {
if (flags == npv->pv_flags) /* no change */
return get_cache_flags(pa);
npv->pv_flags = flags;
goto recompute;
}
if ((npv->pv_pmap != pmap) || (npv->pv_va != va)) continue;
printf("pv_link: found match\n");
if (flags == npv->pv_flags) /* no change */
return get_cache_flags(pa);
npv->pv_flags = flags;
goto recompute;
}
printf("entering pv_link new entry\n");
/*zalloc(pv_zone);*/
pv = malloc(sizeof(struct pv_entry), M_VMPVENT, M_WAITOK);
pv->pv_va = va;
pv->pv_pmap = pmap,
pv->pv_next = NULL;
pv->pv_flags = flags;
printf("entering pv_link before last\n");
last->pv_next = pv;
printf("entering pv_link after last\n");
recompute:
if (get_cache_flags(pa) & PG_NC) return flags & PV_NC; /* already NC */
if (flags & PV_NC) { /* being NCed, wasn't before */
force_cache_flags(pa, flags);
printf("pv_link: change pte 1\n");
pv_change_pte(head, MAKE_PV_REAL(PV_NC), 0);
printf("pv_link: change pte 1 end\n");
return flags & PV_NC;
}
printf("pv_link: cache compute\n");
nflags = pv_compute_cache(head);
force_cache_flags(pa, nflags);
printf("pv_link: change pte 2 \n");
pv_change_pte(head, MAKE_PV_REAL(nflags), 0); /* */
printf("pv_link: change pte 2 after\n");
return nflags & PV_NC;
}
void pv_change_pte(pv_list, set_bits, clear_bits)
@ -631,6 +694,7 @@ void pv_change_pte(pv_list, set_bits, clear_bits)
vm_offset_t pte;
unsigned int seg;
if (!pv_initialized) return;
if (pv_list->pv_pmap == NULL) /* nothing to hack on */
return;
if (!set_bits && !clear_bits) return; /* nothing to do */
@ -660,6 +724,7 @@ void pv_unlink(pmap, pa, va)
pv_entry_t pv,pv_list,dead,last;
unsigned char saved_flags,nflags;
if (!pv_initialized) return;
pv_list = pa_to_pvp(pa);
if (pv_list->pv_pmap == NULL) {
printf("pv_unlinking too many times\n");
@ -709,20 +774,33 @@ void pv_init()
{
int i;
mon_printf("kernel_map: %x\n", kernel_map);
pv_head_table = (pv_entry_t) kmem_alloc(kernel_map,
(avail_end >> PGSHIFT) *
PA_PGNUM(avail_end) *
sizeof(struct pv_entry));
for (i = 0; i < (avail_end >>PGSHIFT); i++) { /* dumb XXX*/
if (!pv_head_table)
mon_panic("pmap: kmem_alloc() of pv table failed");
for (i = 0; i < PA_PGNUM(avail_end); i++) { /* dumb XXX*/
bzero(&pv_head_table[i], sizeof(struct pv_entry));
}
pv_modified_table = (unsigned char *) kmem_alloc(kernel_map,
(avail_end >> PGSHIFT)*
PA_PGNUM(avail_end)*
sizeof(char));
bzero(pv_modified_table, sizeof(char)* (avail_end >> PGSHIFT));
if (!pv_modified_table)
mon_panic("pmap: kmem_alloc() of pv modified table failed");
bzero(pv_modified_table, sizeof(char)* PA_PGNUM(avail_end));
pv_cache_table = (unsigned char *) kmem_alloc(kernel_map,
(avail_end >> PGSHIFT) *
PA_PGNUM(avail_end) *
sizeof(char));
bzero(pv_cache_table, sizeof(char)* (avail_end >> PGSHIFT));
if (!pv_cache_table)
mon_panic("pmap: kmem_alloc() of pv cache table failed");
bzero(pv_cache_table, sizeof(char)* PA_PGNUM(avail_end));
pv_initialized++;
printf("PV: head: %x\n modified: %x\n cache: %x\n",
pv_head_table,
pv_modified_table,
pv_cache_table);
}
void sun3_protection_init()
@ -781,60 +859,14 @@ void pmap_bootstrap()
/* pmeg_init(); done in sun3_vm_init() */
context_init();
/*
* we need to kill off a segment to handle the stupid non-contexted
* pmeg
*
*/
temp_seg = sun3_round_seg(virtual_avail);
set_temp_seg_addr(temp_seg);
mon_printf("%x virtual bytes lost allocating temporary segment for pmap\n",
temp_seg - virtual_avail);
set_segmap(temp_seg, SEGINV);
virtual_avail = temp_seg + NBSG;
sme = get_segmap(virtual_avail);
if (sme == SEGINV)
printf("bad pmeg encountered while looking for msgbuf page");
pmeg_steal(sme);
/* msgbuf */
avail_end -= NBPG;
msgbufp = (struct msgbuf *) virtual_avail;
/* could use pmap_map(), but i want to make sure.*/
pte = PG_VALID | PG_WRITE |PG_SYSTEM | PG_NC | (avail_end >>PGSHIFT);
set_pte((vm_offset_t) msgbufp, pte);
msgbufmapped = 1;
virtual_avail +=NBPG;
eva = sun3_round_up_seg(virtual_avail);
for (va = virtual_avail; va < eva; va += NBPG)
set_pte(va, PG_INVAL);
/* vmmap (used by /dev/mem */
vmmap = (caddr_t) virtual_avail;
set_pte((vm_offset_t) vmmap, PG_INVAL);
virtual_avail += NBPG;
/*
* vpages array:
* just some virtual addresses for temporary mappings
* in the pmap module
*/
tmp_vpages[0] = virtual_avail;
set_pte(tmp_vpages[0], PG_INVAL);
virtual_avail += NBPG;
tmp_vpages[1] = virtual_avail;
set_pte(tmp_vpages[0], PG_INVAL);
virtual_avail += NBPG;
virtual_avail = eva;
mon_printf("kernel virtual address begin:\t %x\n", virtual_avail);
mon_printf("kernel virtual address end:\t %x\n", virtual_end);
mon_printf("physical memory begin:\t %x\n", avail_start);
mon_printf("physical memory end:\t %x\n", avail_end);
pmeg_clean_free();
mon_printf("free pmegs cleaned\n");
}
/*
* Initialize the pmap module.
@ -993,31 +1025,44 @@ void pmap_remove_range_mmu(pmap, sva, eva)
pmeg_t pmegp;
vm_offset_t va,pte;
printf("entering pmap_remove_range_mmu: %x -> %x\n", sva, eva);
saved_context = get_context();
if (pmap != kernel_pmap)
set_context(pmap->pm_context->context_num);
printf("pmap_remove_range_mmu: past stupid context thing\n");
sme = get_segmap(sva);
if (sme == SEGINV) {
if (pmap == kernel_pmap) return;
pmegp = pmeg_cache(pmap, VA_SEGNUM(sva), PM_UPDATE_CACHE);
if (!pmegp) return;
if (!pmegp) goto outta_here;
set_segmap(sva, pmegp->pmeg_index);
}
else
pmegp = pmeg_p(sme);
/* have pmeg, will travel */
if (!pmegp->pmeg_vpages) return; /* no valid pages anyway */
if (!pmegp->pmeg_vpages) goto outta_here; /* no valid pages anyway */
printf("pmap_remove_range_mmu: starting removal");
va = sva;
while (va < eva) {
pte = get_pte(va);
if (pte & PG_VALID) {
save_modified_bits(pte);
printf("before save_modified_bits(): %x\n", pv_modified_table);
printf("before save_modified_bits(): PG_PGNUM(pte)== %x\n",
PG_PGNUM(pte));
printf("before save_modified_bits(): pv_init %d\n",
pv_initialized);
if (pv_initialized)
save_modified_bits(pte);
printf("after save_modified_bits()\n");
pv_unlink(pmap, PG_PA(pte), va);
printf("after after pv_unlink()\n");
pmegp->pmeg_vpages--;
printf("after pmegp->pmeg_vpages--\n");
set_pte(va, PG_INVAL);
}
va+= NBPG;
}
printf("pmap_remove_range_mmu: past removal");
if (pmegp->pmeg_vpages <= 0) {
if (is_pmeg_wired(pmegp))
printf("pmap: removing wired pmeg\n");
@ -1031,6 +1076,8 @@ void pmap_remove_range_mmu(pmap, sva, eva)
else
set_segmap(sva, SEGINV);
}
printf("pmap_remove_range_mmu: past cleanup");
outta_here:
set_context(saved_context);
}
@ -1048,7 +1095,8 @@ void pmap_remove_range_contextless(pmap, sva, eva,pmegp)
for (i = sp; i < ep; i++) {
pte = get_pte_pmeg(pmegp->pmeg_index, i);
if (pte & PG_VALID) {
save_modified_bits(pte);
if (pv_initialized)
save_modified_bits(pte);
pv_unlink(pmap, PG_PA(pte), va);
pmegp->pmeg_vpages--;
set_pte_pmeg(pmegp->pmeg_index, i, PG_INVAL);
@ -1196,7 +1244,8 @@ void pmap_enter_kernel(va, pa, prot, wired, pte_proto, mem_type)
current_pte = get_pte(va);
if (!(current_pte & PG_VALID)) goto add_pte; /* just adding */
pmegp->pmeg_vpages--; /* removing valid page here, way lame XXX*/
save_modified_bits(current_pte);
if (pv_initialized)
save_modified_bits(current_pte);
if (PG_PGNUM(current_pte) != PG_PGNUM(pte_proto)) /* !same physical addr*/
pv_unlink(kernel_pmap, PG_PA(current_pte), va);
@ -1212,7 +1261,9 @@ add_pte: /* can be destructive */
if (mem_type & PG_TYPE)
set_pte(va, pte_proto | PG_NC);
else {
printf("before pv_link\n");
nflags = pv_link(kernel_pmap, pa, va, PG_TO_PV_FLAGS(pte_proto));
printf("after pv_link\n");
if (nflags & PV_NC)
set_pte(va, pte_proto | PG_NC);
else
@ -1270,7 +1321,8 @@ void pmap_enter_user(pmap, va, pa, prot, wired, pte_proto, mem_type)
*/
current_pte = get_pte(va);
if (!(current_pte & PG_VALID)) goto add_pte;
save_modified_bits(current_pte);
if (pv_initialized)
save_modified_bits(current_pte);
pmegp->pmeg_vpages--; /* removing valid page here, way lame XXX*/
if (PG_PGNUM(current_pte) != PG_PGNUM(pte_proto))
pv_unlink(pmap, PG_PA(current_pte), va);
@ -1315,7 +1367,7 @@ pmap_enter(pmap, va, pa, prot, wired)
mem_type = pa & PMAP_MEMMASK;
pte_proto = PG_VALID | pmap_pte_prot(prot) | (pa & PMAP_NC ? PG_NC : 0);
pa &= ~PMAP_SPECMASK;
pte_proto |= (pa >> PGSHIFT);
pte_proto |= PA_PGNUM(pa);
/* treatment varies significantly:
* kernel ptes are in all contexts, and are always in the mmu
@ -1337,9 +1389,11 @@ pmap_clear_modify(pa)
{
int s;
if (!pv_initialized) return;
PMAP_LOCK();
pv_modified_table[PG_PGNUM(pa)] = 0;
pv_change_pte(&pv_head_table[PG_PGNUM(pa)], 0, PG_MOD);
pv_modified_table[PA_PGNUM(pa)] = 0;
pv_change_pte(&pv_head_table[PA_PGNUM(pa)], 0, PG_MOD);
PMAP_UNLOCK();
}
boolean_t
@ -1348,11 +1402,12 @@ pmap_is_modified(pa)
{
int s;
if (pv_modified_table[PG_PGNUM(pa)]) return 1;
if (!pv_initialized) return 0;
if (pv_modified_table[PA_PGNUM(pa)]) return 1;
PMAP_LOCK();
pv_modified_table[PG_PGNUM(pa)] = pv_compute_modified(pa_to_pvp(pa));
pv_modified_table[PA_PGNUM(pa)] = pv_compute_modified(pa_to_pvp(pa));
PMAP_UNLOCK();
return pv_modified_table[PG_PGNUM(pa)];
return pv_modified_table[PA_PGNUM(pa)];
}
void pmap_clear_reference(pa)
@ -1360,6 +1415,7 @@ void pmap_clear_reference(pa)
{
int s;
if (!pv_initialized) return;
PMAP_LOCK();
pv_remove_all(pa);
PMAP_UNLOCK();
@ -1443,9 +1499,9 @@ void pmap_copy_page(src, dst)
int s;
PMAP_LOCK();
pte = PG_VALID |PG_SYSTEM|PG_WRITE|PG_NC|PG_MMEM| (src >>PGSHIFT);
pte = PG_VALID |PG_SYSTEM|PG_WRITE|PG_NC|PG_MMEM| PA_PGNUM(src);
set_pte(tmp_vpages[0], pte);
pte = PG_VALID |PG_SYSTEM|PG_WRITE|PG_NC|PG_MMEM| (dst >>PGSHIFT);
pte = PG_VALID |PG_SYSTEM|PG_WRITE|PG_NC|PG_MMEM| PA_PGNUM(dst);
set_pte(tmp_vpages[1], pte);
bcopy((char *) tmp_vpages[0], (char *) tmp_vpages[1], NBPG);
set_pte(tmp_vpages[0], PG_INVAL);
@ -1549,7 +1605,8 @@ void pmap_protect_range_contextless(pmap, sva, eva,pte_proto, pmegp)
for (i = sp; i < ep; i++) {
pte = get_pte_pmeg(pmegp->pmeg_index, i);
if (pte & PG_VALID) {
save_modified_bits(pte);
if (pv_initialized)
save_modified_bits(pte);
pte_proto |= (PG_MOD|PG_SYSTEM|PG_TYPE|PG_ACCESS|PG_FRAME) & pte;
nflags = pv_link(pmap, PG_PA(pte), va, PG_TO_PV_FLAGS(pte_proto));
if (nflags & PV_NC)
@ -1589,7 +1646,8 @@ void pmap_protect_range_mmu(pmap, sva, eva,pte_proto)
while (va < eva) {
pte = get_pte(va);
if (pte & PG_VALID) {
save_modified_bits(pte);
if (pv_initialized)
save_modified_bits(pte);
pte_proto |= (PG_MOD|PG_SYSTEM|PG_TYPE|PG_ACCESS|PG_FRAME) & pte;
nflags = pv_link(pmap, PG_PA(pte), va, PG_TO_PV_FLAGS(pte_proto));
if (nflags & PV_NC)
@ -1685,7 +1743,7 @@ void pmap_zero_page(pa)
int s;
PMAP_LOCK();
pte = PG_VALID |PG_SYSTEM|PG_WRITE|PG_NC|PG_MMEM| (pa >>PGSHIFT);
pte = PG_VALID |PG_SYSTEM|PG_WRITE|PG_NC|PG_MMEM| PA_PGNUM(pa);
set_pte(tmp_vpages[0], pte);
bzero((char *) tmp_vpages[0], NBPG);
set_pte(tmp_vpages[0], PG_INVAL);

View File

@ -9,21 +9,24 @@
#include "machine/control.h"
#include "machine/pte.h"
#include "machine/pmap.h"
#include "machine/idprom.h"
#include "machine/frame.h"
#include "vector.h"
#include "../dev/idprom.h"
unsigned int *old_vector_table;
static struct idprom identity_prom;
unsigned char cpu_machine_id;
vm_offset_t high_segment_free_start = 0;
vm_offset_t high_segment_free_end = 0;
int msgbufmapped = 0;
struct msgbuf *msgbufp = NULL;
caddr_t vmmap;
extern vm_offset_t tmp_vpages[];
static void initialize_vector_table()
{
int i;
@ -38,11 +41,34 @@ static void initialize_vector_table()
mon_printf("initializing vector table (ended)\n");
}
vm_offset_t high_segment_alloc(npages)
int npages;
{
int i;
vm_offset_t va, tmp;
if (npages == 0)
mon_panic("panic: request for high segment allocation of 0 pages");
if (high_segment_free_start == high_segment_free_end) return NULL;
va = high_segment_free_start + (npages*NBPG);
if (va > high_segment_free_end) return NULL;
tmp = high_segment_free_start;
high_segment_free_start = va;
return tmp;
}
void sun3_stop()
{
mon_exit_to_mon();
}
void sun3_printf(str)
char *str;
{
mon_printf(str);
}
/*
* will this actually work or will it have problems because of this supposed
* wierd thing with (word or short?) aligned addresses
@ -77,7 +103,7 @@ void sun3_context_equiv()
void sun3_vm_init()
{
unsigned int monitor_memory = 0;
vm_offset_t va, eva, sva, pte;
vm_offset_t va, eva, sva, pte, temp_seg;
extern char start[], etext[], end[];
unsigned char sme;
int valid;
@ -99,6 +125,8 @@ void sun3_vm_init()
}
virtual_avail = sun3_round_seg(end); /* start a new segment */
mon_printf("literal kernel_end %x\nvirtual_avail_after %x\n",
end, virtual_avail);
virtual_end = VM_MAX_KERNEL_ADDRESS;
if (romp->romvecVersion >=1)
@ -179,6 +207,56 @@ void sun3_vm_init()
va += NBSG;
}
/*
* we need to kill off a segment to handle the stupid non-contexted
* pmeg
*
*/
temp_seg = sun3_round_seg(virtual_avail);
set_temp_seg_addr(temp_seg);
mon_printf("%x virtual bytes lost allocating temporary segment for pmap\n",
temp_seg - virtual_avail);
set_segmap(temp_seg, SEGINV);
virtual_avail = temp_seg + NBSG;
mon_printf("temp_seg: starts at %x ends at %x\n", temp_seg, virtual_avail);
/* allocating page for msgbuf */
sme = get_segmap(virtual_avail);
if (sme == SEGINV)
mon_printf("bad pmeg encountered while looking for msgbuf page\n");
pmeg_steal(sme);
eva = sun3_round_up_seg(virtual_avail);
/* msgbuf */
avail_end -= NBPG;
msgbufp = (struct msgbuf *) virtual_avail;
pte = PG_VALID | PG_WRITE |PG_SYSTEM | PG_NC | (avail_end >>PGSHIFT);
set_pte((vm_offset_t) msgbufp, pte);
msgbufmapped = 1;
/* cleaning rest of page */
virtual_avail +=NBPG;
for (va = virtual_avail; va < eva; va += NBPG)
set_pte(va, PG_INVAL);
/* vmmap (used by /dev/mem */
vmmap = (caddr_t) virtual_avail;
virtual_avail += NBPG;
/*
* vpages array:
* just some virtual addresses for temporary mappings
* in the pmap module
*/
tmp_vpages[0] = virtual_avail;
virtual_avail += NBPG;
tmp_vpages[1] = virtual_avail;
virtual_avail += NBPG;
virtual_avail = eva;
mon_printf("unmapping range: %x to %x\n", virtual_avail, virtual_end);
/*
* unmap kernel virtual space (only segments. if it squished ptes, bad
* things might happen.
@ -196,7 +274,6 @@ void sun3_vm_init()
void sun3_verify_hardware()
{
unsigned char cpu_machine_id;
unsigned char arch;
int cpu_match = 0;
char *cpu_string;
@ -252,6 +329,100 @@ void sun3_verify_hardware()
mon_printf("kernel configured for Sun 3/%s\n", cpu_string);
}
/*
* Print out a traceback for the caller - can be called anywhere
* within the kernel or from the monitor by typing "g4" (for sun-2
* compatibility) or "w trace". This causes the monitor to call
* the v_handler() routine which will call tracedump() for these cases.
*/
/*VARARGS0*/
tracedump(x1)
caddr_t x1;
{
struct funcall_frame *fp = (struct funcall_frame *)(&x1 - 2);
u_int tospage = btoc(fp);
mon_printf("Begin traceback...fp = %x\n", fp);
while (btoc(fp) == tospage) {
if (fp == fp->fr_savfp) {
mon_printf("FP loop at %x", fp);
break;
}
mon_printf("Called from %x, fp=%x, args=%x %x %x %x\n",
fp->fr_savpc, fp->fr_savfp,
fp->fr_arg[0], fp->fr_arg[1], fp->fr_arg[2], fp->fr_arg[3]);
fp = fp->fr_savfp;
}
mon_printf("End traceback...\n");
}
/*
* Handler for monitor vector cmd -
* For now we just implement the old "g0" and "g4"
* commands and a printf hack. [lifted from freed cmu mach3 sun3 port]
*/
void
v_handler(addr, str)
int addr;
char *str;
{
switch (*str) {
case '\0':
/*
* No (non-hex) letter was specified on
* command line, use only the number given
*/
switch (addr) {
case 0: /* old g0 */
case 0xd: /* 'd'ump short hand */
panic("zero");
/*NOTREACHED*/
case 4: /* old g4 */
tracedump();
break;
default:
goto err;
}
break;
case 'p': /* 'p'rint string command */
case 'P':
mon_printf("%s\n", (char *)addr);
break;
case '%': /* p'%'int anything a la printf */
mon_printf(str, addr);
mon_printf("\n");
break;
case 't': /* 't'race kernel stack */
case 'T':
tracedump();
break;
case 'u': /* d'u'mp hack ('d' look like hex) */
case 'U':
if (addr == 0xd) {
panic("zero");
} else
goto err;
break;
default:
err:
mon_printf("Don't understand 0x%x '%s'\n", addr, str);
}
}
void sun3_monitor_hooks()
{
if (romp->romvecVersion >= 2)
*romp->vector_cmd = v_handler;
}
void sun3_bootstrap()
{
static char hello[] = "hello world";
@ -273,8 +444,12 @@ void sun3_bootstrap()
sun3_vm_init(); /* handle kernel mapping problems, etc */
mon_printf("ending sun3 vm init\n");
sun3_monitor_hooks();
pmap_bootstrap(); /* */
internal_configure(); /* stuff that can't wait for configure() */
main();
mon_exit_to_mon();