/* * Write bytes somewhere in the kernel text. Make the text * pages writable temporarily. */ static void db_write_text(vaddr_t addr, size_t size, char *data) { vaddr_t pgva; size_t limit; uint32_t bits; char *dst; if (size == 0) return; dst = (char *)addr; do { /* * Get the PTE for the page. */ bits = pmap_pte_bits(addr); if ((bits & PG_V) == 0) { printf(" address %p not a valid page\n", dst); return; } /* * Get the VA for the page. */ if (bits & PG_PS) { if (cpu_pae) pgva = (vaddr_t)dst & PG_LGFRAME_PAE; else pgva = (vaddr_t)dst & PG_LGFRAME; } else pgva = trunc_page((vaddr_t)dst); /* * Compute number of bytes that can be written * with this mapping and subtract it from the * total size. */ #ifdef NBPD_L2 if (bits & PG_PS) limit = NBPD_L2 - ((vaddr_t)dst & (NBPD_L2 - 1)); else #endif limit = PAGE_SIZE - ((vaddr_t)dst & PGOFSET); if (limit > size) limit = size; size -= limit; pmap_update_pg(pgva); pmap_pte_setbits(addr, PG_RW, 0); /* * Page is now writable. Do as much access as we * can in this page. */ for (; limit > 0; limit--) *dst++ = *data++; /* * Restore the old PTE. */ pmap_update_pg(pgva); pmap_pte_setbits(addr, 0, bits); } while (size != 0); }
/* * Write bytes somewhere in the kernel text. Make the text * pages writable temporarily. */ static void db_write_text(vaddr_t addr, size_t size, const char *data) { pt_entry_t *ppte, pte; size_t limit; char *dst; if (size == 0) return; dst = (char *)addr; do { addr = (vaddr_t)dst; /* * Get the PTE for the page. */ ppte = kvtopte(addr); pte = *ppte; if ((pte & PG_V) == 0) { printf(" address %p not a valid page\n", dst); return; } /* * Compute number of bytes that can be written * with this mapping and subtract it from the * total size. */ if (pte & PG_PS) limit = NBPD_L2 - (addr & (NBPD_L2 - 1)); else limit = PAGE_SIZE - (addr & PGOFSET); if (limit > size) limit = size; size -= limit; /* * Make the kernel text page writable. */ pmap_pte_clearbits(ppte, PG_KR); pmap_pte_setbits(ppte, PG_KW); pmap_update_pg(addr); /* * MULTIPROCESSOR: no shootdown required as the PTE continues to * map the same page and other CPUs do not need write access. */ /* * Page is now writable. Do as much access as we * can in this page. */ for (; limit > 0; limit--) *dst++ = *data++; /* * Turn the page back to read-only. */ pmap_pte_clearbits(ppte, PG_KW); pmap_pte_setbits(ppte, PG_KR); pmap_update_pg(addr); /* * MULTIPROCESSOR: no shootdown required as all other CPUs * should be in CPUF_PAUSE state and will not cache the PTE * with the write access set. */ } while (size != 0); }