static void pcpu_depopulate_chunk(struct pcpu_chunk *chunk, int off, int size) { int page_start = PFN_DOWN(off); int page_end = PFN_UP(off + size); struct page **pages; unsigned long *populated; int rs, re; rs = page_start; pcpu_next_unpop(chunk, &rs, &re, page_end); if (rs == page_start && re == page_end) return; WARN_ON(chunk->immutable); pages = pcpu_get_pages_and_bitmap(chunk, &populated, false); BUG_ON(!pages); pcpu_pre_unmap_flush(chunk, page_start, page_end); pcpu_for_each_pop_region(chunk, rs, re, page_start, page_end) pcpu_unmap_pages(chunk, pages, populated, rs, re); pcpu_for_each_pop_region(chunk, rs, re, page_start, page_end) pcpu_free_pages(chunk, pages, populated, rs, re); bitmap_copy(chunk->populated, populated, pcpu_unit_pages); }
static int pcpu_populate_chunk(struct pcpu_chunk *chunk, int off, int size) { int page_start = PFN_DOWN(off); int page_end = PFN_UP(off + size); int free_end = page_start, unmap_end = page_start; struct page **pages; unsigned long *populated; unsigned int cpu; int rs, re, rc; rs = page_start; pcpu_next_pop(chunk, &rs, &re, page_end); if (rs == page_start && re == page_end) goto clear; WARN_ON(chunk->immutable); pages = pcpu_get_pages_and_bitmap(chunk, &populated, true); if (!pages) return -ENOMEM; pcpu_for_each_unpop_region(chunk, rs, re, page_start, page_end) { rc = pcpu_alloc_pages(chunk, pages, populated, rs, re); if (rc) goto err_free; free_end = re; }
/** * pcpu_populate_chunk - populate and map an area of a pcpu_chunk * @chunk: chunk of interest * @off: offset to the area to populate * @size: size of the area to populate in bytes * * For each cpu, populate and map pages [@page_start,@page_end) into * @chunk. The area is cleared on return. * * CONTEXT: * pcpu_alloc_mutex, does GFP_KERNEL allocation. */ static int pcpu_populate_chunk(struct pcpu_chunk *chunk, int off, int size) { int page_start = PFN_DOWN(off); int page_end = PFN_UP(off + size); int free_end = page_start, unmap_end = page_start; struct page **pages; unsigned long *populated; unsigned int cpu; int rs, re, rc; /* quick path, check whether all pages are already there */ rs = page_start; pcpu_next_pop(chunk, &rs, &re, page_end); if (rs == page_start && re == page_end) goto clear; /* need to allocate and map pages, this chunk can't be immutable */ WARN_ON(chunk->immutable); pages = pcpu_get_pages_and_bitmap(chunk, &populated, true); if (!pages) return -ENOMEM; /* alloc and map */ pcpu_for_each_unpop_region(chunk, rs, re, page_start, page_end) { rc = pcpu_alloc_pages(chunk, pages, populated, rs, re); if (rc) goto err_free; free_end = re; }
/** * pcpu_depopulate_chunk - depopulate and unmap an area of a pcpu_chunk * @chunk: chunk to depopulate * @off: offset to the area to depopulate * @size: size of the area to depopulate in bytes * @flush: whether to flush cache and tlb or not * * For each cpu, depopulate and unmap pages [@page_start,@page_end) * from @chunk. If @flush is true, vcache is flushed before unmapping * and tlb after. * * CONTEXT: * pcpu_alloc_mutex. */ static void pcpu_depopulate_chunk(struct pcpu_chunk *chunk, int off, int size) { int page_start = PFN_DOWN(off); int page_end = PFN_UP(off + size); struct page **pages; unsigned long *populated; int rs, re; /* quick path, check whether it's empty already */ rs = page_start; pcpu_next_unpop(chunk, &rs, &re, page_end); if (rs == page_start && re == page_end) return; /* immutable chunks can't be depopulated */ WARN_ON(chunk->immutable); /* * If control reaches here, there must have been at least one * successful population attempt so the temp pages array must * be available now. */ pages = pcpu_get_pages_and_bitmap(chunk, &populated, false); BUG_ON(!pages); /* unmap and free */ pcpu_pre_unmap_flush(chunk, page_start, page_end); pcpu_for_each_pop_region(chunk, rs, re, page_start, page_end) pcpu_unmap_pages(chunk, pages, populated, rs, re); /* no need to flush tlb, vmalloc will handle it lazily */ pcpu_for_each_pop_region(chunk, rs, re, page_start, page_end) pcpu_free_pages(chunk, pages, populated, rs, re); /* commit new bitmap */ bitmap_copy(chunk->populated, populated, pcpu_unit_pages); }
/*! 2016-03-19 study -ing */ static int pcpu_populate_chunk(struct pcpu_chunk *chunk, int off, int size) { int page_start = PFN_DOWN(off); int page_end = PFN_UP(off + size); int free_end = page_start, unmap_end = page_start; struct page **pages; unsigned long *populated; unsigned int cpu; int rs, re, rc; /* quick path, check whether all pages are already there */ rs = page_start; pcpu_next_pop(chunk, &rs, &re, page_end); /*! populate 하려는 page_start, end 와 populated 의 rs, re 가 일치하면 * 더 할일 없이 goto clear. */ if (rs == page_start && re == page_end) goto clear; /* need to allocate and map pages, this chunk can't be immutable */ WARN_ON(chunk->immutable); pages = pcpu_get_pages_and_bitmap(chunk, &populated, true); if (!pages) return -ENOMEM; /* alloc and map */ /*! rs: region start, re: region end (Page Frame number 단위) * page_start ~ page_end 까지 pcpu_next_unpop하며 loop 수행 */ pcpu_for_each_unpop_region(chunk, rs, re, page_start, page_end) { rc = pcpu_alloc_pages(chunk, pages, populated, rs, re); /*! 한번이라도 alloc 실패 시 go to err_free. */ if (rc) goto err_free; free_end = re; }