lots of changes, too many printfs
This commit is contained in:
parent
3b87958501
commit
3cdabf7870
239
sys/arch/m68k/m68k/db_interface.c
Normal file
239
sys/arch/m68k/m68k/db_interface.c
Normal 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
|
||||
}
|
||||
|
572
sys/arch/m68k/m68k/db_trace.c
Normal file
572
sys/arch/m68k/m68k/db_trace.c
Normal 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) ®s->d0;
|
||||
sp->k_regloc[1] = (int) ®s->d1;
|
||||
sp->k_regloc[2] = (int) ®s->d2;
|
||||
sp->k_regloc[3] = (int) ®s->d3;
|
||||
sp->k_regloc[4] = (int) ®s->d4;
|
||||
sp->k_regloc[5] = (int) ®s->d5;
|
||||
sp->k_regloc[6] = (int) ®s->d6;
|
||||
sp->k_regloc[7] = (int) ®s->d7;
|
||||
sp->k_regloc[8] = (int) ®s->a0;
|
||||
sp->k_regloc[9] = (int) ®s->a1;
|
||||
sp->k_regloc[10] = (int) ®s->a2;
|
||||
sp->k_regloc[11] = (int) ®s->a3;
|
||||
sp->k_regloc[12] = (int) ®s->a4;
|
||||
sp->k_regloc[13] = (int) ®s->a5;
|
||||
|
||||
sp->k_fp = db_get_value((db_addr_t) ®s->a6,
|
||||
sizeof(int), FALSE);
|
||||
sp->k_pc = db_get_value((db_addr_t) ®s->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
63
sys/arch/sun3/dev/obio.c
Normal 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));
|
||||
}
|
||||
}
|
73
sys/arch/sun3/sun3/autoconf.c
Normal file
73
sys/arch/sun3/sun3/autoconf.c
Normal 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();
|
||||
}
|
@ -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;
|
||||
|
@ -1 +1 @@
|
||||
revision 1.4 intentionally removed
|
||||
revision 1.5 intentionally removed
|
||||
|
@ -101,6 +101,7 @@ cninit()
|
||||
*/
|
||||
cn_tty = cp->cn_tp;
|
||||
(*cp->cn_init)(cp);
|
||||
cn_tty = cp->cn_tp;
|
||||
}
|
||||
|
||||
cnopen(dev, flag, mode, p)
|
||||
|
@ -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");
|
||||
}
|
||||
|
||||
|
239
sys/arch/sun3/sun3/db_interface.c
Normal file
239
sys/arch/sun3/sun3/db_interface.c
Normal 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
|
||||
}
|
||||
|
572
sys/arch/sun3/sun3/db_trace.c
Normal file
572
sys/arch/sun3/sun3/db_trace.c
Normal 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) ®s->d0;
|
||||
sp->k_regloc[1] = (int) ®s->d1;
|
||||
sp->k_regloc[2] = (int) ®s->d2;
|
||||
sp->k_regloc[3] = (int) ®s->d3;
|
||||
sp->k_regloc[4] = (int) ®s->d4;
|
||||
sp->k_regloc[5] = (int) ®s->d5;
|
||||
sp->k_regloc[6] = (int) ®s->d6;
|
||||
sp->k_regloc[7] = (int) ®s->d7;
|
||||
sp->k_regloc[8] = (int) ®s->a0;
|
||||
sp->k_regloc[9] = (int) ®s->a1;
|
||||
sp->k_regloc[10] = (int) ®s->a2;
|
||||
sp->k_regloc[11] = (int) ®s->a3;
|
||||
sp->k_regloc[12] = (int) ®s->a4;
|
||||
sp->k_regloc[13] = (int) ®s->a5;
|
||||
|
||||
sp->k_fp = db_get_value((db_addr_t) ®s->a6,
|
||||
sizeof(int), FALSE);
|
||||
sp->k_pc = db_get_value((db_addr_t) ®s->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;
|
||||
}
|
||||
}
|
||||
|
53
sys/arch/sun3/sun3/interrupt.s
Normal file
53
sys/arch/sun3/sun3/interrupt.s
Normal 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:
|
||||
|
@ -98,4 +98,4 @@ _szicode:
|
||||
#include "signal.s"
|
||||
#include "process.s"
|
||||
#include "softint.s"
|
||||
|
||||
#include "interrupt.s"
|
||||
|
@ -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();
|
||||
|
@ -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
63
sys/arch/sun3/sun3/obio.c
Normal 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));
|
||||
}
|
||||
}
|
@ -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);
|
||||
|
@ -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();
|
||||
|
Loading…
Reference in New Issue
Block a user