PAE correctness

Bruce M Simpson bms at spc.org
Mon Jul 21 06:49:49 PDT 2003


I should be most grateful if someone reviews the attached code fragment
and let me know how to do the right thing for PAE whilst remaining
machine-independent.

My previous version of this code was written after reading the pre-busdma'd
bktr(4) driver, which used pmap_kenter() - bad puppy!

Should I even be using pmap_map() in this case? This does make the
assumption that the cardbus/pccard drivers take care of pushing the
memory window into PCI visibility, and that the PCI regions can be
mapped into the 'real' memory address space.

I should note I also peeked at sparc64_bus_mem_map() this morning
for pointers.

Love and hugs,
BMS
-------------- next part --------------

...

struct pcmem_softc {
	...

	/* common memory mapping descriptors */
	vm_paddr_t		 sc_cm_base;
	vm_paddr_t		 sc_cm_size;
	vm_offset_t		 sc_cm_kva_base;
	vm_size_t		 sc_cm_kva_size;
	...
};

...

/*
 * pcmem_phys_map():
 *
 * Map the common memory window of the PCMCIA memory card in an
 * architecture-independent and SMP coherent manner. Record the
 * addresses used within the card's soft-state structure for
 * later use by pcmem_phys_unmap().
 *
 * The pccard code does not map the window for us, therefore
 * this code is necessary.
 *
 * Returns the first mapped virtual address of the card's common
 * memory, or 0 to indicate failure.
 *
 * XXX needs address arithmetic review for PAE
 */
static vm_offset_t
pcmem_phys_map(struct pcmem_softc *sc)
{
	vm_paddr_t	 pa, off, psize;
	vm_offset_t	 va;
	vm_size_t	 vsize;

	/* clip all address ranges to within page boundaries */
	pa = trunc_page(sc->sc_cm_base);
	psize = round_page(sc->sc_cm_size);
	vsize = (vm_size_t) psize;
	off = sc->sc_cm_base - pa;

	/* reserve a non-pageable memory range within the kva. */
	va = kmem_alloc_nofault(kernel_map, vsize);
	if (va == (vm_offset_t) 0)
		return (0);

	va = pmap_map(&va, pa, pa + psize, VM_PROT_READ);
	if (va == (vm_offset_t) 0) {
		kmem_free(kernel_map, va, vsize);
		return (0);
	}
	sc->sc_cm_kva_size = vsize;
	sc->sc_cm_kva_base = va;

	return (va + off);
}

/*
 * pcmem_phys_unmap():
 *
 * Unmap the common memory window of the PCMCIA memory card in an
 * architecture-independent and SMP coherent manner.
 */
static void
pcmem_phys_unmap(struct pcmem_softc *sc)
{
	pmap_remove(kernel_pmap, sc->sc_cm_kva_base, sc->sc_cm_kva_size);
	kmem_free(kernel_map, sc->sc_cm_kva_base, sc->sc_cm_kva_size);
	sc->sc_cm_kva_base = sc->sc_cm_kva_size = 0;
}


More information about the freebsd-hackers mailing list