Changeset View
Changeset View
Standalone View
Standalone View
sys/compat/linuxkpi/common/src/linux_page.c
Show First 20 Lines • Show All 86 Lines • ▼ Show 20 Lines | |||||
vm_page_t | vm_page_t | ||||
linux_alloc_pages(gfp_t flags, unsigned int order) | linux_alloc_pages(gfp_t flags, unsigned int order) | ||||
{ | { | ||||
vm_page_t page; | vm_page_t page; | ||||
if (PMAP_HAS_DMAP) { | if (PMAP_HAS_DMAP) { | ||||
unsigned long npages = 1UL << order; | unsigned long npages = 1UL << order; | ||||
int req = VM_ALLOC_NOOBJ | VM_ALLOC_WIRED | VM_ALLOC_NORMAL; | int req = VM_ALLOC_WIRED | VM_ALLOC_NORMAL; | ||||
if ((flags & M_ZERO) != 0) | if ((flags & M_ZERO) != 0) | ||||
req |= VM_ALLOC_ZERO; | req |= VM_ALLOC_ZERO; | ||||
if (order == 0 && (flags & GFP_DMA32) == 0) { | if (order == 0 && (flags & GFP_DMA32) == 0) { | ||||
page = vm_page_alloc_noobj(req); | page = vm_page_alloc_noobj(req); | ||||
if (page == NULL) | if (page == NULL) | ||||
return (NULL); | return (NULL); | ||||
} else { | } else { | ||||
vm_paddr_t pmax = (flags & GFP_DMA32) ? | vm_paddr_t pmax = (flags & GFP_DMA32) ? | ||||
BUS_SPACE_MAXADDR_32BIT : BUS_SPACE_MAXADDR; | BUS_SPACE_MAXADDR_32BIT : BUS_SPACE_MAXADDR; | ||||
retry: | retry: | ||||
page = vm_page_alloc_contig(NULL, 0, req, | page = vm_page_alloc_noobj_contig(req, npages, 0, pmax, | ||||
npages, 0, pmax, PAGE_SIZE, 0, VM_MEMATTR_DEFAULT); | PAGE_SIZE, 0, VM_MEMATTR_DEFAULT); | ||||
if (page == NULL) { | if (page == NULL) { | ||||
alc: Is PAGE_SIZE actually correct? I would guess that Linux guarantees that an order n allocation… | |||||
Done Inline ActionsI can't find any Linux documentation or code that definitively answers this. Looking at the alloc_pages() implementation, it does seem to return self-aligned runs in practice, but I can't tell if this is a guarantee of the interface. alloc_contig_pages() has a comment stating that self-alignment is guaranteed if the size of the run is a power of 2, but this function is not used much. markj: I can't find any Linux documentation or code that definitively answers this. Looking at the… | |||||
if (flags & M_WAITOK) { | if (flags & M_WAITOK) { | ||||
if (!vm_page_reclaim_contig(req, | if (!vm_page_reclaim_contig(req, | ||||
npages, 0, pmax, PAGE_SIZE, 0)) { | npages, 0, pmax, PAGE_SIZE, 0)) { | ||||
vm_wait(NULL); | vm_wait(NULL); | ||||
} | } | ||||
flags &= ~M_WAITOK; | flags &= ~M_WAITOK; | ||||
goto retry; | goto retry; | ||||
} | } | ||||
return (NULL); | return (NULL); | ||||
} | |||||
} | |||||
if (flags & M_ZERO) { | |||||
unsigned long x; | |||||
for (x = 0; x != npages; x++) { | |||||
vm_page_t pgo = page + x; | |||||
if ((pgo->flags & PG_ZERO) == 0) | |||||
pmap_zero_page(pgo); | |||||
} | } | ||||
} | } | ||||
} else { | } else { | ||||
vm_offset_t vaddr; | vm_offset_t vaddr; | ||||
vaddr = linux_alloc_kmem(flags, order); | vaddr = linux_alloc_kmem(flags, order); | ||||
if (vaddr == 0) | if (vaddr == 0) | ||||
return (NULL); | return (NULL); | ||||
▲ Show 20 Lines • Show All 140 Lines • Show Last 20 Lines |
Is PAGE_SIZE actually correct? I would guess that Linux guarantees that an order n allocation is aligned to an order n address. That said, at the moment, this is probably not an issue because of the way that vm_phys does contig allocations.