Don't assume pmap_mapdev() gets called only for memory mapped I/O
addresses (i.e. uncacheable). ACPI in particular uses pmap_mapdev() rather excessively (number of calls) just to get a valid KVA. To that end, have pmap_mapdev(): 1. cache the last result so that we don't waste time for multiple consecutive invocations with the same PA/SZ. 2. find the memory descriptor that covers the PA and return NULL if none was found or when the PA is for a common DRAM address. 3. Use either a region 6 or region 7 KVA, in accordance with the memory attribute.
This commit is contained in:
parent
ae78a2ad86
commit
08f72ab5dc
@ -66,6 +66,7 @@ __FBSDID("$FreeBSD$");
|
||||
#include <vm/uma.h>
|
||||
|
||||
#include <machine/bootinfo.h>
|
||||
#include <machine/efi.h>
|
||||
#include <machine/md_var.h>
|
||||
#include <machine/pal.h>
|
||||
|
||||
@ -2235,12 +2236,37 @@ pmap_remove_write(vm_page_t m)
|
||||
* NOT real memory.
|
||||
*/
|
||||
void *
|
||||
pmap_mapdev(vm_paddr_t pa, vm_size_t size)
|
||||
pmap_mapdev(vm_paddr_t pa, vm_size_t sz)
|
||||
{
|
||||
static void *last_va = NULL;
|
||||
static vm_paddr_t last_pa = 0;
|
||||
static vm_size_t last_sz = 0;
|
||||
struct efi_md *md;
|
||||
vm_offset_t va;
|
||||
|
||||
va = pa | IA64_RR_BASE(6);
|
||||
return ((void *)va);
|
||||
if (pa == last_pa && sz == last_sz)
|
||||
return (last_va);
|
||||
|
||||
md = efi_md_find(pa);
|
||||
if (md == NULL) {
|
||||
printf("%s: [%#lx..%#lx] not covered by memory descriptor\n",
|
||||
__func__, pa, pa + sz - 1);
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
if (md->md_type == EFI_MD_TYPE_FREE) {
|
||||
printf("%s: [%#lx..%#lx] is in DRAM\n", __func__, pa,
|
||||
pa + sz - 1);
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
va = (md->md_attr & EFI_MD_ATTR_WB) ? IA64_PHYS_TO_RR7(pa) :
|
||||
IA64_PHYS_TO_RR6(pa);
|
||||
|
||||
last_va = (void *)va;
|
||||
last_pa = pa;
|
||||
last_sz = sz;
|
||||
return (last_va);
|
||||
}
|
||||
|
||||
/*
|
||||
|
Loading…
x
Reference in New Issue
Block a user