Ejemplo n.º 1
0
static int
mmu_mapin(vm_offset_t va, vm_size_t len)
{
	vm_offset_t pa, mva;
	u_long data;

	if (va + len > curkva)
		curkva = va + len;

	pa = (vm_offset_t)-1;
	len += va & PAGE_MASK_4M;
	va &= ~PAGE_MASK_4M;
	while (len) {
		if (dtlb_va_to_pa(va) == (vm_offset_t)-1 ||
		    itlb_va_to_pa(va) == (vm_offset_t)-1) {
			/* Allocate a physical page, claim the virtual area */
			if (pa == (vm_offset_t)-1) {
				pa = (vm_offset_t)OF_alloc_phys(PAGE_SIZE_4M,
				    PAGE_SIZE_4M);
				if (pa == (vm_offset_t)-1)
					panic("out of memory");
				mva = (vm_offset_t)OF_claim_virt(va,
				    PAGE_SIZE_4M, 0);
				if (mva != va) {
					panic("can't claim virtual page "
					    "(wanted %#lx, got %#lx)",
					    va, mva);
				}
				/* The mappings may have changed, be paranoid. */
				continue;
			}
			/*
			 * Actually, we can only allocate two pages less at
			 * most (depending on the kernel TSB size).
			 */
			if (dtlb_slot >= dtlb_slot_max)
				panic("mmu_mapin: out of dtlb_slots");
			if (itlb_slot >= itlb_slot_max)
				panic("mmu_mapin: out of itlb_slots");
			data = TD_V | TD_4M | TD_PA(pa) | TD_L | TD_CP |
			    TD_CV | TD_P | TD_W;
			dtlb_store[dtlb_slot].te_pa = pa;
			dtlb_store[dtlb_slot].te_va = va;
			itlb_store[itlb_slot].te_pa = pa;
			itlb_store[itlb_slot].te_va = va;
			dtlb_slot++;
			itlb_slot++;
			dtlb_enter(va, data);
			itlb_enter(va, data);
			pa = (vm_offset_t)-1;
		}
		len -= len > PAGE_SIZE_4M ? PAGE_SIZE_4M : len;
		va += PAGE_SIZE_4M;
	}
	if (pa != (vm_offset_t)-1)
		OF_release_phys(pa, PAGE_SIZE_4M);
	return 0;
}
Ejemplo n.º 2
0
void *
OF_claim(void *virt, u_int size, u_int align)
{
#define SUNVMOF
#ifndef SUNVMOF
	struct {
		cell_t name;
		cell_t nargs;
		cell_t nreturns;
		cell_t virt;
		cell_t size;
		cell_t align;
		cell_t baseaddr;
	} args;


	args.name = ADR2CELL("claim");
	args.nargs = 3;
	args.nreturns = 1;
	args.virt = virt;
	args.size = size;
	args.align = align;
	if (openfirmware(&args) == -1)
		return (void *)-1;
	return (void *)args.baseaddr;
#else
/*
 * Sun Ultra machines run the firmware with VM enabled,
 * so you need to handle allocating and mapping both
 * virtual and physical memory.  Ugh.
 */

	paddr_t paddr;
	void * newvirt = NULL;

	if (virt == NULL) {
		virt = (void *)OF_alloc_virt(size, align);
		if (virt == (void *)-1LL) {
			printf("OF_alloc_virt(%d,%d) failed w/%x\n",
			       size, align, virt);
			return virt;
		}
	} else {
		newvirt = (void *)OF_claim_virt((vaddr_t)virt, size);
		if (newvirt == (void *)-1LL) {
			printf("OF_claim_virt(%x,%d) failed w/%x\n",
			       virt, size, newvirt);
			return newvirt;
		}
		virt = newvirt;
	}
	if ((paddr = OF_alloc_phys(size, align)) == (paddr_t)-1LL) {
		printf("OF_alloc_phys(%d,%d) failed\n", size, align);
		OF_free_virt((vaddr_t)virt, size);
		return (void *)-1LL;
	}
	if (OF_map_phys(paddr, size, (vaddr_t)virt, -1) == -1) {
		printf("OF_map_phys(%x,%d,%x,%d) failed\n",
		       paddr, size, virt, -1);
		OF_free_phys((paddr_t)paddr, size);
		OF_free_virt((vaddr_t)virt, size);
		return (void *)-1LL;
	}
	return virt;
#endif
}