Changeset View
Standalone View
sys/i386/i386/pmap.c
Show First 20 Lines • Show All 292 Lines • ▼ Show 20 Lines | |||||
/* | /* | ||||
* Internal flags for pmap_enter()'s helper functions. | * Internal flags for pmap_enter()'s helper functions. | ||||
*/ | */ | ||||
#define PMAP_ENTER_NORECLAIM 0x1000000 /* Don't reclaim PV entries. */ | #define PMAP_ENTER_NORECLAIM 0x1000000 /* Don't reclaim PV entries. */ | ||||
#define PMAP_ENTER_NOREPLACE 0x2000000 /* Don't replace mappings. */ | #define PMAP_ENTER_NOREPLACE 0x2000000 /* Don't replace mappings. */ | ||||
static void free_pv_chunk(struct pv_chunk *pc); | static void free_pv_chunk(struct pv_chunk *pc); | ||||
static void free_pv_entry(pmap_t pmap, pv_entry_t pv); | static void free_pv_entry(pmap_t pmap, pv_entry_t pv); | ||||
kib: Start with 1. I do not think we need compat with amd64. | |||||
Done Inline ActionsOk. In theory if anyone tried to boot an i386 kernel on the affected AMD systems they'd need the flush cache hack. Hmm, actually, no. The i386 cfgreg code uses pmap_kenter instead of pmap_mapdev so it doesn't do a cache flush. jhb: Ok. In theory if anyone tried to boot an i386 kernel on the affected AMD systems they'd need… | |||||
static pv_entry_t get_pv_entry(pmap_t pmap, boolean_t try); | static pv_entry_t get_pv_entry(pmap_t pmap, boolean_t try); | ||||
static void pmap_pv_demote_pde(pmap_t pmap, vm_offset_t va, vm_paddr_t pa); | static void pmap_pv_demote_pde(pmap_t pmap, vm_offset_t va, vm_paddr_t pa); | ||||
static bool pmap_pv_insert_pde(pmap_t pmap, vm_offset_t va, pd_entry_t pde, | static bool pmap_pv_insert_pde(pmap_t pmap, vm_offset_t va, pd_entry_t pde, | ||||
u_int flags); | u_int flags); | ||||
#if VM_NRESERVLEVEL > 0 | #if VM_NRESERVLEVEL > 0 | ||||
static void pmap_pv_promote_pde(pmap_t pmap, vm_offset_t va, vm_paddr_t pa); | static void pmap_pv_promote_pde(pmap_t pmap, vm_offset_t va, vm_paddr_t pa); | ||||
#endif | #endif | ||||
static void pmap_pvh_free(struct md_page *pvh, pmap_t pmap, vm_offset_t va); | static void pmap_pvh_free(struct md_page *pvh, pmap_t pmap, vm_offset_t va); | ||||
▲ Show 20 Lines • Show All 5,078 Lines • ▼ Show 20 Lines | |||||
/* | /* | ||||
* Map a set of physical memory pages into the kernel virtual | * Map a set of physical memory pages into the kernel virtual | ||||
* address space. Return a pointer to where it is mapped. This | * address space. Return a pointer to where it is mapped. This | ||||
* routine is intended to be used for mapping device memory, | * routine is intended to be used for mapping device memory, | ||||
* NOT real memory. | * NOT real memory. | ||||
*/ | */ | ||||
static void * | static void * | ||||
__CONCAT(PMTYPE, mapdev_attr)(vm_paddr_t pa, vm_size_t size, int mode) | __CONCAT(PMTYPE, mapdev_attr)(vm_paddr_t pa, vm_size_t size, int mode, | ||||
int flags) | |||||
{ | { | ||||
struct pmap_preinit_mapping *ppim; | struct pmap_preinit_mapping *ppim; | ||||
vm_offset_t va, offset; | vm_offset_t va, offset; | ||||
vm_page_t m; | |||||
vm_size_t tmpsize; | vm_size_t tmpsize; | ||||
int i; | int i; | ||||
offset = pa & PAGE_MASK; | offset = pa & PAGE_MASK; | ||||
size = round_page(offset + size); | size = round_page(offset + size); | ||||
pa = pa & PG_FRAME; | pa = pa & PG_FRAME; | ||||
if (pa < PMAP_MAP_LOW && pa + size <= PMAP_MAP_LOW) | if (pa < PMAP_MAP_LOW && pa + size <= PMAP_MAP_LOW) { | ||||
va = pa + PMAP_MAP_LOW; | va = pa + PMAP_MAP_LOW; | ||||
else if (!pmap_initialized) { | if ((flags & MAPDEV_SETATTR) == 0) | ||||
return ((void *)(va + offset)); | |||||
} else if (!pmap_initialized) { | |||||
Not Done Inline ActionsI think this condition should be added to the condition on line 5412. We can only use low PDE when we are fine with the existing attrs, otherwise we must remap. Also style: == 0. kib: I think this condition should be added to the condition on line 5412. We can only use low PDE… | |||||
Done Inline ActionsHmm, I think we want to change the low pmap if SETATTR is set. This is important for the rule that all PTEs for a given PA must use the same attribute. jhb: Hmm, I think we want to change the low pmap if SETATTR is set. This is important for the rule… | |||||
Not Done Inline ActionsI agree. I think this can be postponed. kib: I agree. I think this can be postponed. | |||||
Done Inline ActionsTo be clear, I think the existing code already rewrites the attributes for low mmap now and this patched code will do so now as well, so I don't think there is any future work to do here? jhb: To be clear, I think the existing code already rewrites the attributes for low mmap now and… | |||||
Not Done Inline ActionsIndeed, sorry. kib: Indeed, sorry. | |||||
va = 0; | va = 0; | ||||
for (i = 0; i < PMAP_PREINIT_MAPPING_COUNT; i++) { | for (i = 0; i < PMAP_PREINIT_MAPPING_COUNT; i++) { | ||||
ppim = pmap_preinit_mapping + i; | ppim = pmap_preinit_mapping + i; | ||||
if (ppim->va == 0) { | if (ppim->va == 0) { | ||||
ppim->pa = pa; | ppim->pa = pa; | ||||
ppim->sz = size; | ppim->sz = size; | ||||
ppim->mode = mode; | ppim->mode = mode; | ||||
ppim->va = virtual_avail; | ppim->va = virtual_avail; | ||||
virtual_avail += size; | virtual_avail += size; | ||||
va = ppim->va; | va = ppim->va; | ||||
break; | break; | ||||
} | } | ||||
} | } | ||||
if (va == 0) | if (va == 0) | ||||
panic("%s: too many preinit mappings", __func__); | panic("%s: too many preinit mappings", __func__); | ||||
} else { | } else { | ||||
/* | /* | ||||
* If we have a preinit mapping, re-use it. | * If we have a preinit mapping, re-use it. | ||||
*/ | */ | ||||
for (i = 0; i < PMAP_PREINIT_MAPPING_COUNT; i++) { | for (i = 0; i < PMAP_PREINIT_MAPPING_COUNT; i++) { | ||||
ppim = pmap_preinit_mapping + i; | ppim = pmap_preinit_mapping + i; | ||||
if (ppim->pa == pa && ppim->sz == size && | if (ppim->pa == pa && ppim->sz == size && | ||||
ppim->mode == mode) | (ppim->mode == mode || | ||||
(flags & MAPDEV_SETATTR) == 0)) | |||||
return ((void *)(ppim->va + offset)); | return ((void *)(ppim->va + offset)); | ||||
} | } | ||||
va = kva_alloc(size); | va = kva_alloc(size); | ||||
if (va == 0) | if (va == 0) | ||||
panic("%s: Couldn't allocate KVA", __func__); | panic("%s: Couldn't allocate KVA", __func__); | ||||
} | } | ||||
for (tmpsize = 0; tmpsize < size; tmpsize += PAGE_SIZE) | for (tmpsize = 0; tmpsize < size; tmpsize += PAGE_SIZE) { | ||||
if ((flags & MAPDEV_SETATTR) == 0 && pmap_initialized) { | |||||
m = PHYS_TO_VM_PAGE(pa); | |||||
Not Done Inline ActionsI think we still do not initialize all pages in vm_page_array. Noted just in case this would cause a problem. kib: I think we still do not initialize all pages in vm_page_array. Noted just in case this would… | |||||
Done Inline ActionsIs there a way to determine if a vm_page_t is valid? jhb: Is there a way to determine if a vm_page_t is valid? | |||||
Not Done Inline ActionsYou might compare VM_PAGE_TO_PHYS(m) with pa. I have WIP for making x86/iommu used by bhyve, where I have to initialize whole vm_page_array. kib: You might compare VM_PAGE_TO_PHYS(m) with pa.
I have WIP for making x86/iommu used by bhyve… | |||||
if (m != NULL) { | |||||
pmap_kenter_attr(va + tmpsize, pa + tmpsize, | |||||
m->md.pat_mode); | |||||
continue; | |||||
} | |||||
} | |||||
pmap_kenter_attr(va + tmpsize, pa + tmpsize, mode); | pmap_kenter_attr(va + tmpsize, pa + tmpsize, mode); | ||||
} | |||||
pmap_invalidate_range_int(kernel_pmap, va, va + tmpsize); | pmap_invalidate_range_int(kernel_pmap, va, va + tmpsize); | ||||
pmap_invalidate_cache_range(va, va + size); | pmap_invalidate_cache_range(va, va + size); | ||||
return ((void *)(va + offset)); | return ((void *)(va + offset)); | ||||
} | } | ||||
static void | static void | ||||
__CONCAT(PMTYPE, unmapdev)(vm_offset_t va, vm_size_t size) | __CONCAT(PMTYPE, unmapdev)(vm_offset_t va, vm_size_t size) | ||||
{ | { | ||||
▲ Show 20 Lines • Show All 764 Lines • Show Last 20 Lines |
Start with 1. I do not think we need compat with amd64.