1/*- 2 * Mach Operating System 3 * Copyright (c) 1991,1990 Carnegie Mellon University 4 * All Rights Reserved. 5 * 6 * Permission to use, copy, modify and distribute this software and its 7 * documentation is hereby granted, provided that both the copyright 8 * notice and this permission notice appear in all copies of the 9 * software, derivative works or modified versions, and any portions 10 * thereof, and that both notices appear in supporting documentation. 11 * 12 * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS 13 * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR 14 * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. 15 * 16 * Carnegie Mellon requests users of this software to return to 17 * 18 * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU 19 * School of Computer Science 20 * Carnegie Mellon University 21 * Pittsburgh PA 15213-3890 22 * 23 * any improvements or extensions that they make and grant Carnegie the 24 * rights to redistribute these changes. 25 */ 26 27#include <sys/cdefs.h> 28__FBSDID("$FreeBSD: stable/11/sys/i386/i386/db_interface.c 342825 2019-01-07 00:32:19Z kib $"); 29 30/* 31 * Interface to new debugger. 32 */ 33#include <sys/param.h> 34#include <sys/systm.h> 35#include <sys/cons.h> 36#include <sys/kdb.h> 37#include <sys/pcpu.h> 38#include <sys/proc.h> 39 40#include <machine/cpu.h> 41 42#include <vm/vm.h> 43#include <vm/pmap.h> 44 45#include <ddb/ddb.h> 46 47/* 48 * Read bytes from kernel address space for debugger. 49 */ 50int 51db_read_bytes(vm_offset_t addr, size_t size, char *data) 52{ 53 jmp_buf jb; 54 void *prev_jb; 55 char *src; 56 int ret; 57 58 prev_jb = kdb_jmpbuf(jb); 59 ret = setjmp(jb); 60 if (ret == 0) { 61 src = (char *)addr; 62 while (size-- > 0) 63 *data++ = *src++; 64 } 65 (void)kdb_jmpbuf(prev_jb); 66 return (ret); 67} 68 69/* 70 * Write bytes to kernel address space for debugger. 71 */ 72int 73db_write_bytes(vm_offset_t addr, size_t size, char *data) 74{ 75 jmp_buf jb; 76 void *prev_jb; 77 char *dst; 78 pt_entry_t *ptep0 = NULL; 79 pt_entry_t oldmap0 = 0; 80 vm_offset_t addr1; 81 pt_entry_t *ptep1 = NULL; 82 pt_entry_t oldmap1 = 0; 83 int ret; 84 85 prev_jb = kdb_jmpbuf(jb); 86 ret = setjmp(jb); 87 if (ret == 0) { 88 if (addr > trunc_page((vm_offset_t)btext) - size && 89 addr < round_page((vm_offset_t)etext)) { 90 91 ptep0 = pmap_pte(kernel_pmap, addr); 92 oldmap0 = *ptep0; 93 *ptep0 |= PG_RW; 94 95 /* 96 * Map another page if the data crosses a page 97 * boundary. 98 */ 99 if ((*ptep0 & PG_PS) == 0) { 100 addr1 = trunc_page(addr + size - 1); 101 if (trunc_page(addr) != addr1) { 102 ptep1 = pmap_pte(kernel_pmap, addr1); 103 oldmap1 = *ptep1; 104 *ptep1 |= PG_RW; 105 } 106 } else { 107 addr1 = trunc_4mpage(addr + size - 1); 108 if (trunc_4mpage(addr) != addr1) { 109 ptep1 = pmap_pte(kernel_pmap, addr1); 110 oldmap1 = *ptep1; 111 *ptep1 |= PG_RW; 112 } 113 } 114 115 invltlb(); 116 } 117 118 dst = (char *)addr; 119 120 while (size-- > 0) 121 *dst++ = *data++; 122 } 123 124 (void)kdb_jmpbuf(prev_jb); 125 126 if (ptep0) { 127 *ptep0 = oldmap0; 128 129 if (ptep1) 130 *ptep1 = oldmap1; 131 132 invltlb(); 133 } 134 135 return (ret); 136} 137 138int 139db_segsize(struct trapframe *tfp) 140{ 141 struct proc_ldt *plp; 142 struct segment_descriptor *sdp; 143 int sel; 144 145 if (tfp == NULL) 146 return (32); 147 if (tfp->tf_eflags & PSL_VM) 148 return (16); 149 sel = tfp->tf_cs & 0xffff; 150 if (sel == GSEL(GCODE_SEL, SEL_KPL)) 151 return (32); 152 /* Rare cases follow. User mode cases are currently unreachable. */ 153 if (ISLDT(sel)) { 154 plp = curthread->td_proc->p_md.md_ldt; 155 sdp = (plp != NULL) ? &plp->ldt_sd : &ldt[0].sd; 156 } else { 157 sdp = &gdt[PCPU_GET(cpuid) * NGDT].sd; 158 } 159 return (sdp[IDXSEL(sel)].sd_def32 == 0 ? 16 : 32); 160} 161 162void 163db_show_mdpcpu(struct pcpu *pc) 164{ 165 166 db_printf("APIC ID = %d\n", pc->pc_apic_id); 167 db_printf("currentldt = 0x%x\n", pc->pc_currentldt); 168 db_printf("tlb gen = %u\n", pc->pc_smp_tlb_done); 169} 170