Example #1
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, 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);
}
Example #2
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);
}