-vtophys(space, addr)
- unsigned space;
- CORE_ADDR addr;
-{
- struct pde *pptr;
- u_int hindx, vpageno, ppageno;
- CORE_ADDR phys = ~0;
-
- if (!vtophys_ready) {
- phys = addr; /* XXX for kvread */
- } else if (kerneltype == OS_BSD) {
- /* make offset into a virtual page no */
- vpageno = btop(addr);
- /*
- * Determine index into hash table, initialize pptr to this
- * entry (since first word of pte & hte are same), and set
- * physical page number for first entry in chain.
- */
- hindx = pdirhash(space, addr) & (nhtbl-1);
- pptr = (struct pde *) &htbl[hindx];
- ppageno = pptr->pde_next;
- while (1) {
- if (pptr->pde_end)
- break;
- pptr = &pdir[ppageno];
- /*
- * If space id & virtual page number match, return
- * "next PDIR entry of previous PDIR entry" as the
- * physical page or'd with offset into page.
- */
- if (pptr->pde_space == space &&
- pptr->pde_page == vpageno) {
- phys = (CORE_ADDR) ((u_int)ptob(ppageno) |
- (addr & PGOFSET));
- break;
- }
- ppageno = pptr->pde_next;
- }
- }
-#ifdef MACHKERNELDEBUG
- else if (kerneltype == OS_MACH) {
- (void) mach_vtophys(space, addr, &phys);
- }
-#endif
-#if 0
- printf("vtophys(%x.%x) -> %x\n", space, addr, phys);
-#endif
- return (phys);
-}
-
-static
-kvread(addr)
- CORE_ADDR addr;
-{
- CORE_ADDR paddr;
-
- paddr = vtophys(0, addr);
- if (paddr != ~0)
- if (physrd(paddr, (char *)&addr, sizeof(addr)) == 0)
- return (addr);
-
- return (~0);
-}
-
-static void
-read_pcb(addr)
- u_int addr;
-{
- int i, off;
- extern char registers[];
- static int reg2pcb[] = {
- /* RPB */
- -1, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17,
- 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33,
- 45, 52, 51, 75, 74, 49, 53, 54, 55, 56, -1, 70, 66, 67, 68, 69,
- 71, 72, 73, 34, 42, 43, 44, 46, 47, 58, 59, 60, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1,
- /* BSD */
- -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
- 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30,
- 43, 64, 67, 68, 67, 47, 51, 52, 53, 54, -1, 35, 31, 32, 33, 34,
- 36, 37, 38, 39, 40, 41, 42, 44, 45, 56, 57, 58,102,103,104, -1,
- 70, 71, 72, 73, 74, 75, 76, 77, 78, 80, 82, 84, 86, 88, 90, 92,
- 94, 96, 98, 100,
- /* Mach */
- -1, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13,
- 14, 15, 16, -1, -1, -1, -1, -1, -1, -1, -1, 17, -1, -1, 18, -1,
- 25, -1, -1, -1, -1, 30, -1, -1, -1, -1, -1, 20, -1, -1, -1, 19,
- 21, 22, 23, 24, 26, 27, -1, 28, 29, -1, -1, -1, -1, -1, -1, -1,
- 34, 35, 36, 37, 38, 39, 40, 41, -1, -1, -1, -1, -1, -1, -1, -1,
- 42, 44, 46, 48
- };
- static struct rpb *rpbaddr = (struct rpb *) 0;
- static u_int rpbpcbaddr = 0;
-
- if (!remote_debugging) {
- /*
- * If we are debugging a post-mortem and this is the first
- * call of read_pcb, read the RPB. Also assoicate the
- * thread/proc running at the time with the RPB.
- */
- if (!devmem && rpbpcbaddr == 0) {
- CORE_ADDR raddr = ksym_lookup("rpb");
- int usepcb = 1;
-
- if (raddr != ~0) {
- rpbaddr = (struct rpb *) malloc(sizeof *rpbaddr);
- if (!physrd(raddr, (char *)rpbaddr, sizeof *rpbaddr)) {
- rpbpcbaddr = addr;
- usepcb = 0;
- }
- }
- if (usepcb) {
- error("cannot read rpb, using pcb for registers\n");
- if (rpbaddr)
- free((char *)rpbaddr);
- rpbpcbaddr = ~0;
- }
- }
- if (physrd (addr, (char *)&pcb, sizeof pcb))
- error ("cannot read pcb at %x.\n", addr);
- } else {
- if (remote_read_inferior_memory(addr, (char *)&pcb, sizeof pcb))
- error ("cannot read pcb at %x.\n", addr);
- }
-
- if (kerneltype == OS_BSD) {
- printf("p0br %lx p0lr %lx p1br %lx p1lr %lx\n",
- pcb.pcb_p0br, pcb.pcb_p0lr, pcb.pcb_p1br, pcb.pcb_p1lr);
- off = NUM_REGS;
- } else {
- printf("pcb %lx psw %lx ksp %lx\n",
- addr, ((int *)&pcb)[31], ((int *)&pcb)[32]);
- off = NUM_REGS * 2;
- }
- /*
- * get the register values out of the sys pcb and
- * store them where `read_register' will find them.
- */
- bzero(registers, REGISTER_BYTES);
- for (i = 0; i < NUM_REGS; ++i)
- if (reg2pcb[i+off] != -1)
- supply_register(i, &((int *)&pcb)[reg2pcb[i+off]]);
- /*
- * If the RPB is valid for this thread/proc use the register values
- * contained there.
- */
- if (addr == rpbpcbaddr) {
- off = 0;
- for (i = 0; i < NUM_REGS; ++i)
- if (reg2pcb[i+off] != -1)
- supply_register(i, &((int *)rpbaddr)[reg2pcb[i+off]]);
- }
-}
-
-void
-setup_kernel_debugging()
-{
- struct stat stb;
- CORE_ADDR addr;
-
- fstat(corechan, &stb);
- devmem = 0;
- if ((stb.st_mode & S_IFMT) == S_IFCHR && stb.st_rdev == makedev(2, 0))
- devmem = 1;
-
- /* XXX */
- if (lookup_misc_func("Sysmap") < 0)
- kerneltype = OS_MACH;
- else
- kerneltype = OS_BSD;
-
- if (kerneltype == OS_BSD) {
- int len, err = 0;
-
- /*
- * Hash table and PDIR are equivalently mapped
- */
- nhtbl = kvread(ksym_lookup("nhtbl"));
- if (nhtbl != ~0) {
- len = nhtbl * sizeof(*htbl);
- htbl = (struct hte *) malloc(len);
- if (htbl) {
- addr = kvread(ksym_lookup("htbl"));
- if (physrd(addr, (char *)htbl, len))
- err++;
- } else
- err++;
- } else
- err++;
- npdir = kvread(ksym_lookup("npdir"));
- if (npdir != ~0) {
- len = npdir * sizeof(*pdir);
- pdir = (struct pde *) malloc(len);
- if (pdir) {
- addr = kvread(ksym_lookup("pdir"));
- if (physrd(addr, (char *)pdir, len))
- err++;
- } else
- err++;
- } else
- err++;
- if (err) {
- error("cannot read PDIR/HTBL");
- return;
- }
- vtophys_ready = 1;
-
- /*
- * pcb where "panic" saved registers in first thing in
- * current u-area. The current u-area is pointed to by
- * "uptr".
- */
- addr = kvread(ksym_lookup("uptr"));
- if (addr == ~0) {
- error("cannot read current u-area address");
- return;
- }
- read_pcb(vtophys(0, addr)); /* XXX space */
- if (!devmem) {
- /* find stack frame */
- CORE_ADDR panicstr;
- char buf[256];
- register char *cp;
-
- panicstr = kvread(ksym_lookup("panicstr"));
- if (panicstr == ~0)
- return;
- (void) kernel_core_file_hook(panicstr, buf, sizeof(buf));
- for (cp = buf; cp < &buf[sizeof(buf)] && *cp; cp++)
- if (!isascii(*cp) || (!isprint(*cp) && !isspace(*cp)))
- *cp = '?';
- if (*cp)
- *cp = '\0';
- printf("panic: %s\n", buf);
- }
- }
-#ifdef MACHKERNELDEBUG
- else {
- int *thread;
-
- /*
- * Set up address translation
- */
- if (mach_vtophys_init() == 0) {
- error("cannot initialize vtophys for Mach");
- return;
- }
- vtophys_ready = 1;
-
- /*
- * Locate active thread and read PCB
- * XXX MAJOR HACK
- * - assumes uni-processor
- * - assumes position of pcb to avoid mach includes
- */
- thread = (int *)kvread(ksym_lookup("active_threads"));
- addr = kvread(&thread[9]); /* XXX: pcb addr */
- read_pcb(vtophys(0, addr));
- }
-#endif
-}
-
-vtop_command(arg)
- char *arg;
-{
- u_int sp, off, pa;
-
- if (!arg)
- error_no_arg("kernel virtual address");
- if (!kernel_debugging)
- error("not debugging kernel");
-
- sp = 0; /* XXX */
- off = (u_int) parse_and_eval_address(arg);
- pa = vtophys(sp, off);
- printf("%lx.%lx -> ", sp, off);
- if (pa == ~0)
- printf("<invalid>\n");
- else
- printf("%lx\n", pa);
-}
-
-set_paddr_command(arg)
- char *arg;
-{
- u_int addr;
-
- if (!arg) {
- if (kerneltype == OS_BSD)
- error_no_arg("ps-style address for new process");
- else
- error_no_arg("thread structure virtual address");
- }
- if (!kernel_debugging)
- error("not debugging kernel");
-
- addr = (u_int) parse_and_eval_address(arg);
- if (kerneltype == OS_BSD)
- addr = ctob(addr);
- else {
- addr = kvread(&(((int *)addr)[9])); /* XXX: pcb addr */
- addr = vtophys(0, addr); /* XXX space */
- }
- read_pcb(addr);
-
- flush_cached_frames();
- set_current_frame(create_new_frame(read_register(FP_REGNUM), read_pc()));
- select_frame(get_current_frame(), 0);
-}
-
-/*
- * read len bytes from kernel virtual address 'addr' into local
- * buffer 'buf'. Return 0 if read ok, 1 otherwise. On read
- * errors, portion of buffer not read is zeroed.
- */
-kernel_core_file_hook(addr, buf, len)
- CORE_ADDR addr;
- char *buf;
- int len;
-{
- int i;
- CORE_ADDR paddr;
-
- while (len > 0) {
- paddr = vtophys(0, addr); /* XXX space */
- if (paddr == ~0) {
- bzero(buf, len);
- return (1);
- }
- /* we can't read across a page boundary */
- i = min(len, NBPG - (addr & PGOFSET));
- if (physrd(paddr, buf, i)) {
- bzero(buf, len);
- return (1);
- }
- buf += i;
- addr += i;
- len -= i;
- }
- return (0);
-}
-#endif
-
-
-\f
-
-
-/* Routines to extract various sized constants out of hppa
- instructions. */
-
-/* This assumes that no garbage lies outside of the lower bits of
- value. */
-
-int
-sign_extend (val, bits)
- unsigned val, bits;
-{
- return (int)(val >> bits - 1 ? (-1 << bits) | val : val);
-}
-
-/* For many immediate values the sign bit is the low bit! */
-
-int
-low_sign_extend (val, bits)
- unsigned val, bits;
-{
- return (int)((val & 0x1 ? (-1 << (bits - 1)) : 0) | val >> 1);
-}
-/* extract the immediate field from a ld{bhw}s instruction */
-
-
-
-unsigned
-get_field (val, from, to)
- unsigned val, from, to;
-{
- val = val >> 31 - to;
- return val & ((1 << 32 - from) - 1);
-}
-
-unsigned
-set_field (val, from, to, new_val)
- unsigned *val, from, to;
-{
- unsigned mask = ~((1 << (to - from + 1)) << (31 - from));
- return *val = *val & mask | (new_val << (31 - from));
-}
-
-/* extract a 3-bit space register number from a be, ble, mtsp or mfsp */
-
-extract_3 (word)
- unsigned word;
-{
- return GET_FIELD (word, 18, 18) << 2 | GET_FIELD (word, 16, 17);
-}
-
-extract_5_load (word)
- unsigned word;
-{
- return low_sign_extend (word >> 16 & MASK_5, 5);
-}
-
-/* extract the immediate field from a st{bhw}s instruction */
-
-int
-extract_5_store (word)
- unsigned word;
-{
- return low_sign_extend (word & MASK_5, 5);
-}
-
-/* extract an 11 bit immediate field */
-
-int
-extract_11 (word)
- unsigned word;
-{
- return low_sign_extend (word & MASK_11, 11);
-}
-
-/* extract a 14 bit immediate field */
-
-int
-extract_14 (word)
- unsigned word;
-{
- return low_sign_extend (word & MASK_14, 14);
-}
-
-/* deposit a 14 bit constant in a word */
-
-unsigned
-deposit_14 (opnd, word)
- int opnd;
- unsigned word;
-{
- unsigned sign = (opnd < 0 ? 1 : 0);
-
- return word | ((unsigned)opnd << 1 & MASK_14) | sign;
-}
-
-/* extract a 21 bit constant */
-
-int
-extract_21 (word)
- unsigned word;
-{
- int val;
-
- word &= MASK_21;
- word <<= 11;
- val = GET_FIELD (word, 20, 20);
- val <<= 11;
- val |= GET_FIELD (word, 9, 19);
- val <<= 2;
- val |= GET_FIELD (word, 5, 6);
- val <<= 5;
- val |= GET_FIELD (word, 0, 4);
- val <<= 2;
- val |= GET_FIELD (word, 7, 8);
- return sign_extend (val, 21) << 11;
-}
-
-/* deposit a 21 bit constant in a word. Although 21 bit constants are
- usually the top 21 bits of a 32 bit constant, we assume that only
- the low 21 bits of opnd are relevant */
-
-unsigned
-deposit_21 (opnd, word)
- unsigned opnd, word;