+/*
+ * Mach Operating System
+ * Copyright (c) 1991,1990 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
+ * 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 the
+ * rights to redistribute these changes.
+ */
+/*
+ * HISTORY
+ * $Log: db_interface.c,v $
+ * Revision 1.1 1992/03/25 21:42:03 pace
+ * Initial revision
+ *
+ * Revision 2.4 91/02/05 17:11:13 mrt
+ * Changed to new Mach copyright
+ * [91/02/01 17:31:17 mrt]
+ *
+ * Revision 2.3 90/12/04 14:45:55 jsb
+ * Changes for merged intel/pmap.{c,h}.
+ * [90/12/04 11:14:41 jsb]
+ *
+ * Revision 2.2 90/10/25 14:44:43 rwd
+ * Added watchpoint support.
+ * [90/10/18 rpd]
+ *
+ * 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 */
+int db_active = 0;
+
+/*
+ * Received keyboard interrupt sequence.
+ */
+kdb_kbd_trap(regs)
+ struct i386_saved_state *regs;
+{
+ if (db_active == 0 && (boothowto & RB_KDB)) {
+ printf("\n\nkernel: keyboard interrupt\n");
+ kdb_trap(-1, 0, regs);
+ }
+}
+
+/*
+ * kdb_trap - field a TRACE or BPT trap
+ */
+
+static jmp_buf *db_nofault = 0;
+
+kdb_trap(type, code, regs)
+ int type, code;
+ register struct i386_saved_state *regs;
+{
+#if 0
+ if ((boothowto&RB_KDB) == 0)
+ return(0);
+#endif
+
+ switch (type) {
+ case T_BPTFLT /* T_INT3 */: /* breakpoint */
+ case T_KDBTRAP /* T_WATCHPOINT */: /* watchpoint */
+ case T_PRIVINFLT /* T_DEBUG */: /* single_step */
+
+ case -1: /* keyboard interrupt */
+ break;
+
+ default:
+ kdbprinttrap(type, code);
+
+ if (db_nofault) {
+ jmp_buf *no_fault = db_nofault;
+ db_nofault = 0;
+ longjmp(*no_fault, 1);
+ }
+ }
+
+ /* Should switch to kdb`s own stack here. */
+
+ ddb_regs = *regs;
+
+ if ((regs->tf_cs & 0x3) == 0) {
+ /*
+ * Kernel mode - esp and ss not saved
+ */
+ ddb_regs.tf_esp = (int)®s->tf_esp; /* kernel stack pointer */
+#if 0
+ ddb_regs.ss = KERNEL_DS;
+#endif
+ asm(" movw %%ss,%%ax; movl %%eax,%0 "
+ : "=g" (ddb_regs.tf_ss)
+ :
+ : "ax");
+ }
+
+ db_active++;
+ cnpollc(TRUE);
+ db_trap(type, code);
+ cnpollc(FALSE);
+ db_active--;
+
+ regs->tf_eip = ddb_regs.tf_eip;
+ regs->tf_eflags = ddb_regs.tf_eflags;
+ regs->tf_eax = ddb_regs.tf_eax;
+ regs->tf_ecx = ddb_regs.tf_ecx;
+ regs->tf_edx = ddb_regs.tf_edx;
+ regs->tf_ebx = ddb_regs.tf_ebx;
+ if (regs->tf_cs & 0x3) {
+ /*
+ * user mode - saved esp and ss valid
+ */
+ regs->tf_esp = ddb_regs.tf_esp; /* user stack pointer */
+ regs->tf_ss = ddb_regs.tf_ss & 0xffff; /* user stack segment */
+ }
+ regs->tf_ebp = ddb_regs.tf_ebp;
+ regs->tf_esi = ddb_regs.tf_esi;
+ regs->tf_edi = ddb_regs.tf_edi;
+ regs->tf_es = ddb_regs.tf_es & 0xffff;
+ regs->tf_cs = ddb_regs.tf_cs & 0xffff;
+ regs->tf_ds = ddb_regs.tf_ds & 0xffff;
+#if 0
+ regs->tf_fs = ddb_regs.tf_fs & 0xffff;
+ regs->tf_gs = ddb_regs.tf_gs & 0xffff;
+#endif
+
+ return (1);
+}
+
+/*
+ * Print trap reason.
+ */
+kdbprinttrap(type, code)
+ int type, code;
+{
+ printf("kernel: ");
+ printf("type %d", type);
+ printf(" trap, code=%x\n", code);
+}
+
+/*
+ * Read bytes from kernel address space for debugger.
+ */
+
+extern jmp_buf db_jmpbuf;
+
+void
+db_read_bytes(addr, size, data)
+ vm_offset_t addr;
+ register int size;
+ register char *data;
+{
+ register char *src;
+
+ db_nofault = &db_jmpbuf;
+
+ src = (char *)addr;
+ while (--size >= 0)
+ *data++ = *src++;
+
+ db_nofault = 0;
+}
+
+struct pte *pmap_pte(pmap_t, vm_offset_t);
+
+/*
+ * 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;
+
+ register pt_entry_t *ptep0 = 0;
+ pt_entry_t oldmap0 = { 0 };
+ vm_offset_t addr1;
+ register pt_entry_t *ptep1 = 0;
+ pt_entry_t oldmap1 = { 0 };
+ extern char etext;
+
+ db_nofault = &db_jmpbuf;
+
+ if (addr >= VM_MIN_KERNEL_ADDRESS &&
+ addr <= (vm_offset_t)&etext)
+ {
+ ptep0 = pmap_pte(kernel_pmap, addr);
+ oldmap0 = *ptep0;
+ *(int *)ptep0 |= /* INTEL_PTE_WRITE */ PG_RW;
+
+ addr1 = i386_trunc_page(addr + size - 1);
+ if (i386_trunc_page(addr) != addr1) {
+ /* data crosses a page boundary */
+
+ ptep1 = pmap_pte(kernel_pmap, addr1);
+ oldmap1 = *ptep1;
+ *(int *)ptep1 |= /* INTEL_PTE_WRITE */ PG_RW;
+ }
+ tlbflush();
+ }
+
+ dst = (char *)addr;
+
+ while (--size >= 0)
+ *dst++ = *data++;
+
+ db_nofault = 0;
+
+ if (ptep0) {
+ *ptep0 = oldmap0;
+ if (ptep1) {
+ *ptep1 = oldmap1;
+ }
+ tlbflush();
+ }
+}
+
+Debugger (msg)
+char *msg;
+{
+ asm ("int $3");
+}