1/* $OpenBSD: db_memrw.c,v 1.3 2024/02/23 18:19:03 cheloha Exp $ */ 2/* $NetBSD: db_memrw.c,v 1.1 2003/04/26 18:39:27 fvdl Exp $ */ 3 4/*- 5 * Copyright (c) 1996, 2000 The NetBSD Foundation, Inc. 6 * All rights reserved. 7 * 8 * This code is derived from software contributed to The NetBSD Foundation 9 * by Gordon W. Ross and Jason R. Thorpe. 10 * 11 * Redistribution and use in source and binary forms, with or without 12 * modification, are permitted provided that the following conditions 13 * are met: 14 * 1. Redistributions of source code must retain the above copyright 15 * notice, this list of conditions and the following disclaimer. 16 * 2. Redistributions in binary form must reproduce the above copyright 17 * notice, this list of conditions and the following disclaimer in the 18 * documentation and/or other materials provided with the distribution. 19 * 20 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 21 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 22 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 23 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 24 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 25 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 26 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 27 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 28 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 29 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 30 * POSSIBILITY OF SUCH DAMAGE. 31 */ 32 33#include <sys/param.h> 34#include <sys/systm.h> 35 36#include <uvm/uvm_extern.h> 37 38#include <machine/cpufunc.h> 39#include <machine/db_machdep.h> 40#include <machine/pmap.h> 41#include <machine/pte.h> 42 43#include <ddb/db_access.h> 44 45/* 46 * Read bytes from kernel address space for debugger. 47 */ 48void 49db_read_bytes(vaddr_t addr, size_t size, void *datap) 50{ 51 char *data = datap, *src; 52 53 src = (char *)addr; 54 55 if (size == 8) { 56 *((long *)data) = *((long *)src); 57 return; 58 } 59 60 if (size == 4) { 61 *((int *)data) = *((int *)src); 62 return; 63 } 64 65 if (size == 2) { 66 *((short *)data) = *((short *)src); 67 return; 68 } 69 70 while (size-- > 0) 71 *data++ = *src++; 72} 73 74/* 75 * Write bytes somewhere in the kernel text. Make the text 76 * pages writable temporarily. 77 */ 78void 79db_write_text(vaddr_t addr, size_t size, char *data) 80{ 81 struct pte *pte; 82 uint64_t old_pte_lo; 83 vaddr_t pgva; 84 size_t limit; 85 char *dst; 86 87 if (size == 0) 88 return; 89 90 dst = (char *)addr; 91 92 do { 93 pte = pmap_get_kernel_pte((vaddr_t)dst); 94 if (pte == NULL) { 95 printf(" address %p not a valid page\n", dst); 96 return; 97 } 98 99 /* 100 * Compute number of bytes that can be written 101 * with this mapping and subtract it from the 102 * total size. 103 */ 104 pgva = trunc_page((vaddr_t)dst); 105 limit = PAGE_SIZE - ((vaddr_t)dst & PGOFSET); 106 if (limit > size) 107 limit = size; 108 size -= limit; 109 110 /* 111 * Gain write access to the page. We don't need 112 * tlbie to "add access authorities" (Power ISA 3.0 113 * III 5.10.1.2 Modifying a Translation Table Entry). 114 */ 115 old_pte_lo = pte->pte_lo; 116 pte->pte_lo = (old_pte_lo & ~PTE_PP) | PTE_RW; 117 ptesync(); 118 119 for (; limit > 0; limit--) 120 *dst++ = *data++; 121 122 /* Restore the old PTE. */ 123 pte->pte_lo = old_pte_lo; 124 ptesync(); 125 tlbie(pgva); 126 eieio(); 127 tlbsync(); 128 ptesync(); 129 130 } while (size != 0); 131 132 __syncicache((void *)addr, limit); 133} 134 135/* 136 * Write bytes to kernel address space for debugger. 137 */ 138void 139db_write_bytes(vaddr_t addr, size_t size, void *datap) 140{ 141 extern char _start[], _etext[]; 142 char *data = datap, *dst; 143 144 /* If any part is in kernel text, use db_write_text() */ 145 if (addr >= (vaddr_t)_start && addr < (vaddr_t)_etext) { 146 db_write_text(addr, size, data); 147 return; 148 } 149 150 dst = (char *)addr; 151 152 if (size == 8) { 153 *((long *)dst) = *((long *)data); 154 return; 155 } 156 157 if (size == 4) { 158 *((int *)dst) = *((int *)data); 159 return; 160 } 161 162 if (size == 2) { 163 *((short *)dst) = *((short *)data); 164 return; 165 } 166 167 while (size-- > 0) 168 *dst++ = *data++; 169} 170