powerpc/pmap: Make use of tlb1_mapin_region in pmap_mapdev_attr()
tlb1_mapin_region() and pmap_mapdev_attr() do roughly the same thing -- map a chunk of physical address space(memory or MMIO) into virtual, but do it in differing ways. Unify the code, settling on pmap_mapdev_attr()'s algorithm, to simplify and unify the logic. This fixes a bug with growing the kernel mappings in mmu_booke_bootstrap(), where part of the mapping was not getting done, leading to a hang when the unmapped VAs were accessed.
This commit is contained in:
parent
d7a3eada0a
commit
730de0f746
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=354326
@ -237,11 +237,11 @@ static void tlb_print_entry(int, uint32_t, uint32_t, uint32_t, uint32_t);
|
||||
static void tlb1_read_entry(tlb_entry_t *, unsigned int);
|
||||
static void tlb1_write_entry(tlb_entry_t *, unsigned int);
|
||||
static int tlb1_iomapped(int, vm_paddr_t, vm_size_t, vm_offset_t *);
|
||||
static vm_size_t tlb1_mapin_region(vm_offset_t, vm_paddr_t, vm_size_t);
|
||||
static vm_size_t tlb1_mapin_region(vm_offset_t, vm_paddr_t, vm_size_t, int);
|
||||
|
||||
static vm_size_t tsize2size(unsigned int);
|
||||
static unsigned int size2tsize(vm_size_t);
|
||||
static unsigned int ilog2(unsigned long);
|
||||
static unsigned long ilog2(unsigned long);
|
||||
|
||||
static void set_mas4_defaults(void);
|
||||
|
||||
@ -1619,10 +1619,16 @@ mmu_booke_bootstrap(mmu_t mmu, vm_offset_t start, vm_offset_t kernelend)
|
||||
debugf(" kernel pdir at 0x%"PRI0ptrX" end = 0x%"PRI0ptrX"\n",
|
||||
kernel_pdir, data_end);
|
||||
|
||||
/* Pre-round up to 1MB. This wastes some space, but saves TLB entries */
|
||||
data_end = roundup2(data_end, 1 << 20);
|
||||
debugf(" data_end: 0x%"PRI0ptrX"\n", data_end);
|
||||
debugf(" kernstart: %p\n", kernstart);
|
||||
debugf(" kernsize: %lx\n", kernsize);
|
||||
|
||||
if (data_end - kernstart > kernsize) {
|
||||
kernsize += tlb1_mapin_region(kernstart + kernsize,
|
||||
kernload + kernsize, (data_end - kernstart) - kernsize);
|
||||
kernload + kernsize, (data_end - kernstart) - kernsize,
|
||||
_TLB_ENTRY_MEM);
|
||||
}
|
||||
data_end = kernstart + kernsize;
|
||||
debugf(" updated data_end: 0x%"PRI0ptrX"\n", data_end);
|
||||
@ -1819,7 +1825,7 @@ mmu_booke_bootstrap(mmu_t mmu, vm_offset_t start, vm_offset_t kernelend)
|
||||
* Round so it fits into a single mapping.
|
||||
*/
|
||||
tlb1_mapin_region(DMAP_BASE_ADDRESS, 0,
|
||||
phys_avail[i + 1]);
|
||||
phys_avail[i + 1], _TLB_ENTRY_MEM);
|
||||
#endif
|
||||
|
||||
/*******************************************************/
|
||||
@ -3500,30 +3506,8 @@ mmu_booke_mapdev_attr(mmu_t mmu, vm_paddr_t pa, vm_size_t size, vm_memattr_t ma)
|
||||
#endif
|
||||
res = (void *)va;
|
||||
|
||||
do {
|
||||
sz = 1 << (ilog2(size) & ~1);
|
||||
/* Align size to PA */
|
||||
if (pa % sz != 0) {
|
||||
do {
|
||||
sz >>= 2;
|
||||
} while (pa % sz != 0);
|
||||
}
|
||||
/* Now align from there to VA */
|
||||
if (va % sz != 0) {
|
||||
do {
|
||||
sz >>= 2;
|
||||
} while (va % sz != 0);
|
||||
}
|
||||
if (bootverbose)
|
||||
printf("Wiring VA=%p to PA=%jx (size=%lx)\n",
|
||||
(void *)va, (uintmax_t)pa, (long)sz);
|
||||
if (tlb1_set_entry(va, pa, sz,
|
||||
_TLB_ENTRY_SHARED | tlb_calc_wimg(pa, ma)) < 0)
|
||||
return (NULL);
|
||||
size -= sz;
|
||||
pa += sz;
|
||||
va += sz;
|
||||
} while (size > 0);
|
||||
if (tlb1_mapin_region(va, pa, size, tlb_calc_wimg(pa, ma)) != size)
|
||||
return (NULL);
|
||||
|
||||
return (res);
|
||||
}
|
||||
@ -3864,7 +3848,7 @@ tlb1_write_entry(tlb_entry_t *e, unsigned int idx)
|
||||
/*
|
||||
* Return the largest uint value log such that 2^log <= num.
|
||||
*/
|
||||
static unsigned int
|
||||
static unsigned long
|
||||
ilog2(unsigned long num)
|
||||
{
|
||||
long lz;
|
||||
@ -3952,69 +3936,49 @@ tlb1_set_entry(vm_offset_t va, vm_paddr_t pa, vm_size_t size,
|
||||
}
|
||||
|
||||
/*
|
||||
* Map in contiguous RAM region into the TLB1 using maximum of
|
||||
* KERNEL_REGION_MAX_TLB_ENTRIES entries.
|
||||
*
|
||||
* If necessary round up last entry size and return total size
|
||||
* used by all allocated entries.
|
||||
* Map in contiguous RAM region into the TLB1.
|
||||
*/
|
||||
vm_size_t
|
||||
tlb1_mapin_region(vm_offset_t va, vm_paddr_t pa, vm_size_t size)
|
||||
static vm_size_t
|
||||
tlb1_mapin_region(vm_offset_t va, vm_paddr_t pa, vm_size_t size, int wimge)
|
||||
{
|
||||
vm_size_t pgs[KERNEL_REGION_MAX_TLB_ENTRIES];
|
||||
vm_size_t mapped, pgsz, base, mask;
|
||||
int idx, nents;
|
||||
|
||||
/* Round up to the next 1M */
|
||||
size = roundup2(size, 1 << 20);
|
||||
vm_offset_t base;
|
||||
vm_size_t mapped, sz, ssize;
|
||||
|
||||
mapped = 0;
|
||||
idx = 0;
|
||||
base = va;
|
||||
pgsz = 64*1024*1024;
|
||||
while (mapped < size) {
|
||||
while (mapped < size && idx < KERNEL_REGION_MAX_TLB_ENTRIES) {
|
||||
while (pgsz > (size - mapped))
|
||||
pgsz >>= 2;
|
||||
pgs[idx++] = pgsz;
|
||||
mapped += pgsz;
|
||||
ssize = size;
|
||||
|
||||
while (size > 0) {
|
||||
sz = 1UL << (ilog2(size) & ~1);
|
||||
/* Align size to PA */
|
||||
if (pa % sz != 0) {
|
||||
do {
|
||||
sz >>= 2;
|
||||
} while (pa % sz != 0);
|
||||
}
|
||||
|
||||
/* We under-map. Correct for this. */
|
||||
if (mapped < size) {
|
||||
while (pgs[idx - 1] == pgsz) {
|
||||
idx--;
|
||||
mapped -= pgsz;
|
||||
}
|
||||
/* XXX We may increase beyond out starting point. */
|
||||
pgsz <<= 2;
|
||||
pgs[idx++] = pgsz;
|
||||
mapped += pgsz;
|
||||
/* Now align from there to VA */
|
||||
if (va % sz != 0) {
|
||||
do {
|
||||
sz >>= 2;
|
||||
} while (va % sz != 0);
|
||||
}
|
||||
}
|
||||
|
||||
nents = idx;
|
||||
mask = pgs[0] - 1;
|
||||
/* Align address to the boundary */
|
||||
if (va & mask) {
|
||||
va = (va + mask) & ~mask;
|
||||
pa = (pa + mask) & ~mask;
|
||||
}
|
||||
|
||||
for (idx = 0; idx < nents; idx++) {
|
||||
pgsz = pgs[idx];
|
||||
debugf("%u: %jx -> %jx, size=%jx\n", idx, (uintmax_t)pa,
|
||||
(uintmax_t)va, (uintmax_t)pgsz);
|
||||
tlb1_set_entry(va, pa, pgsz,
|
||||
_TLB_ENTRY_SHARED | _TLB_ENTRY_MEM);
|
||||
pa += pgsz;
|
||||
va += pgsz;
|
||||
/* Now align from there to VA */
|
||||
if (bootverbose)
|
||||
printf("Wiring VA=%p to PA=%jx (size=%lx)\n",
|
||||
(void *)va, (uintmax_t)pa, (long)sz);
|
||||
if (tlb1_set_entry(va, pa, sz,
|
||||
_TLB_ENTRY_SHARED | wimge) < 0)
|
||||
return (mapped);
|
||||
size -= sz;
|
||||
pa += sz;
|
||||
va += sz;
|
||||
}
|
||||
|
||||
mapped = (va - base);
|
||||
if (bootverbose)
|
||||
printf("mapped size 0x%"PRIxPTR" (wasted space 0x%"PRIxPTR")\n",
|
||||
mapped, mapped - size);
|
||||
mapped, mapped - ssize);
|
||||
|
||||
return (mapped);
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user