Changeset View
Changeset View
Standalone View
Standalone View
head/sys/arm/arm/physmem.c
Show First 20 Lines • Show All 210 Lines • ▼ Show 20 Lines | for (exi = 0, exp = exregions; exi < excnt; ++exi, ++exp) { | ||||
* region without abutting or overlapping the beginning | * region without abutting or overlapping the beginning | ||||
* or end, create an available entry from the leading | * or end, create an available entry from the leading | ||||
* fragment, then adjust the start of this hw region to | * fragment, then adjust the start of this hw region to | ||||
* the end of the excluded region, and continue checking | * the end of the excluded region, and continue checking | ||||
* the next excluded region because another exclusion | * the next excluded region because another exclusion | ||||
* could affect the remainder of this hw region. | * could affect the remainder of this hw region. | ||||
*/ | */ | ||||
if ((xstart > start) && (xend < end)) { | if ((xstart > start) && (xend < end)) { | ||||
if (acnt > 0 && | |||||
avail[acnt - 1] == (vm_paddr_t)start) { | |||||
avail[acnt - 1] = (vm_paddr_t)xstart; | |||||
} else { | |||||
avail[acnt++] = (vm_paddr_t)start; | avail[acnt++] = (vm_paddr_t)start; | ||||
avail[acnt++] = (vm_paddr_t)xstart; | avail[acnt++] = (vm_paddr_t)xstart; | ||||
} | |||||
availmem += | availmem += | ||||
arm32_btop((vm_offset_t)(xstart - start)); | arm32_btop((vm_offset_t)(xstart - start)); | ||||
start = xend; | start = xend; | ||||
continue; | continue; | ||||
} | } | ||||
/* | /* | ||||
* We know the excluded region overlaps either the start | * We know the excluded region overlaps either the start | ||||
* or end of this hardware region (but not both), trim | * or end of this hardware region (but not both), trim | ||||
* the excluded portion off the appropriate end. | * the excluded portion off the appropriate end. | ||||
*/ | */ | ||||
if (xstart <= start) | if (xstart <= start) | ||||
start = xend; | start = xend; | ||||
else | else | ||||
end = xstart; | end = xstart; | ||||
} | } | ||||
/* | /* | ||||
* If the trimming actions above left a non-zero size, create an | * If the trimming actions above left a non-zero size, create an | ||||
* available entry for it. | * available entry for it. | ||||
*/ | */ | ||||
if (end > start) { | if (end > start) { | ||||
if (acnt > 0 && avail[acnt - 1] == (vm_paddr_t)start) { | |||||
avail[acnt - 1] = (vm_paddr_t)end; | |||||
} else { | |||||
avail[acnt++] = (vm_paddr_t)start; | avail[acnt++] = (vm_paddr_t)start; | ||||
avail[acnt++] = (vm_paddr_t)end; | avail[acnt++] = (vm_paddr_t)end; | ||||
} | |||||
availmem += arm32_btop((vm_offset_t)(end - start)); | availmem += arm32_btop((vm_offset_t)(end - start)); | ||||
} | } | ||||
if (acnt >= MAX_AVAIL_ENTRIES) | if (acnt >= MAX_AVAIL_ENTRIES) | ||||
panic("Not enough space in the dump/phys_avail arrays"); | panic("Not enough space in the dump/phys_avail arrays"); | ||||
} | } | ||||
if (pavail) | if (pavail) | ||||
*pavail = availmem; | *pavail = availmem; | ||||
return (acnt); | return (acnt); | ||||
} | } | ||||
/* | /* | ||||
* Insertion-sort a new entry into a regions list; sorted by start address. | * Insertion-sort a new entry into a regions list; sorted by start address. | ||||
*/ | */ | ||||
static void | static size_t | ||||
insert_region(struct region *regions, size_t rcnt, vm_paddr_t addr, | insert_region(struct region *regions, size_t rcnt, vm_paddr_t addr, | ||||
vm_size_t size, uint32_t flags) | vm_size_t size, uint32_t flags) | ||||
{ | { | ||||
size_t i; | size_t i; | ||||
struct region *ep, *rp; | struct region *ep, *rp; | ||||
ep = regions + rcnt; | ep = regions + rcnt; | ||||
for (i = 0, rp = regions; i < rcnt; ++i, ++rp) { | for (i = 0, rp = regions; i < rcnt; ++i, ++rp) { | ||||
if (flags == rp->flags) { | |||||
if (addr + size == rp->addr) { | |||||
rp->addr = addr; | |||||
rp->size += size; | |||||
return (rcnt); | |||||
} else if (rp->addr + rp->size == addr) { | |||||
rp->size += size; | |||||
return (rcnt); | |||||
} | |||||
} | |||||
if (addr < rp->addr) { | if (addr < rp->addr) { | ||||
bcopy(rp, rp + 1, (ep - rp) * sizeof(*rp)); | bcopy(rp, rp + 1, (ep - rp) * sizeof(*rp)); | ||||
break; | break; | ||||
} | } | ||||
} | } | ||||
rp->addr = addr; | rp->addr = addr; | ||||
rp->size = size; | rp->size = size; | ||||
rp->flags = flags; | rp->flags = flags; | ||||
rcnt++; | |||||
return (rcnt); | |||||
} | } | ||||
/* | /* | ||||
* Add a hardware memory region. | * Add a hardware memory region. | ||||
*/ | */ | ||||
void | void | ||||
arm_physmem_hardware_region(uint64_t pa, uint64_t sz) | arm_physmem_hardware_region(uint64_t pa, uint64_t sz) | ||||
{ | { | ||||
Show All 35 Lines | arm_physmem_hardware_region(uint64_t pa, uint64_t sz) | ||||
* Round the starting address up to a page boundary, and truncate the | * Round the starting address up to a page boundary, and truncate the | ||||
* ending page down to a page boundary. | * ending page down to a page boundary. | ||||
*/ | */ | ||||
adj = round_page(pa) - pa; | adj = round_page(pa) - pa; | ||||
pa = round_page(pa); | pa = round_page(pa); | ||||
sz = trunc_page(sz - adj); | sz = trunc_page(sz - adj); | ||||
if (sz > 0 && hwcnt < nitems(hwregions)) | if (sz > 0 && hwcnt < nitems(hwregions)) | ||||
insert_region(hwregions, hwcnt++, pa, sz, 0); | hwcnt = insert_region(hwregions, hwcnt, pa, sz, 0); | ||||
} | } | ||||
/* | /* | ||||
* Add an exclusion region. | * Add an exclusion region. | ||||
*/ | */ | ||||
void arm_physmem_exclude_region(vm_paddr_t pa, vm_size_t sz, uint32_t exflags) | void arm_physmem_exclude_region(vm_paddr_t pa, vm_size_t sz, uint32_t exflags) | ||||
{ | { | ||||
vm_offset_t adj; | vm_offset_t adj; | ||||
/* | /* | ||||
* Truncate the starting address down to a page boundary, and round the | * Truncate the starting address down to a page boundary, and round the | ||||
* ending page up to a page boundary. | * ending page up to a page boundary. | ||||
*/ | */ | ||||
adj = pa - trunc_page(pa); | adj = pa - trunc_page(pa); | ||||
pa = trunc_page(pa); | pa = trunc_page(pa); | ||||
sz = round_page(sz + adj); | sz = round_page(sz + adj); | ||||
if (excnt < nitems(exregions)) | if (excnt < nitems(exregions)) | ||||
insert_region(exregions, excnt++, pa, sz, exflags); | excnt = insert_region(exregions, excnt, pa, sz, exflags); | ||||
} | } | ||||
/* | /* | ||||
* Process all the regions added earlier into the global avail lists. | * Process all the regions added earlier into the global avail lists. | ||||
* | * | ||||
* Updates the kernel global 'physmem' with the number of physical pages | * Updates the kernel global 'physmem' with the number of physical pages | ||||
* available for use (all pages not in any exclusion region). | * available for use (all pages not in any exclusion region). | ||||
* | * | ||||
Show All 26 Lines |