diff options
Diffstat (limited to 'arch/powerpc/mm/init_64.c')
| -rw-r--r-- | arch/powerpc/mm/init_64.c | 55 | 
1 files changed, 54 insertions, 1 deletions
diff --git a/arch/powerpc/mm/init_64.c b/arch/powerpc/mm/init_64.c index d0cd9e4c683..e3734edffa6 100644 --- a/arch/powerpc/mm/init_64.c +++ b/arch/powerpc/mm/init_64.c @@ -300,5 +300,58 @@ void vmemmap_free(unsigned long start, unsigned long end)  {  } -#endif /* CONFIG_SPARSEMEM_VMEMMAP */ +void register_page_bootmem_memmap(unsigned long section_nr, +				  struct page *start_page, unsigned long size) +{ +} + +/* + * We do not have access to the sparsemem vmemmap, so we fallback to + * walking the list of sparsemem blocks which we already maintain for + * the sake of crashdump. In the long run, we might want to maintain + * a tree if performance of that linear walk becomes a problem. + * + * realmode_pfn_to_page functions can fail due to: + * 1) As real sparsemem blocks do not lay in RAM continously (they + * are in virtual address space which is not available in the real mode), + * the requested page struct can be split between blocks so get_page/put_page + * may fail. + * 2) When huge pages are used, the get_page/put_page API will fail + * in real mode as the linked addresses in the page struct are virtual + * too. + */ +struct page *realmode_pfn_to_page(unsigned long pfn) +{ +	struct vmemmap_backing *vmem_back; +	struct page *page; +	unsigned long page_size = 1 << mmu_psize_defs[mmu_vmemmap_psize].shift; +	unsigned long pg_va = (unsigned long) pfn_to_page(pfn); + +	for (vmem_back = vmemmap_list; vmem_back; vmem_back = vmem_back->list) { +		if (pg_va < vmem_back->virt_addr) +			continue; + +		/* Check that page struct is not split between real pages */ +		if ((pg_va + sizeof(struct page)) > +				(vmem_back->virt_addr + page_size)) +			return NULL; + +		page = (struct page *) (vmem_back->phys + pg_va - +				vmem_back->virt_addr); +		return page; +	} + +	return NULL; +} +EXPORT_SYMBOL_GPL(realmode_pfn_to_page); + +#elif defined(CONFIG_FLATMEM) + +struct page *realmode_pfn_to_page(unsigned long pfn) +{ +	struct page *page = pfn_to_page(pfn); +	return page; +} +EXPORT_SYMBOL_GPL(realmode_pfn_to_page); +#endif /* CONFIG_SPARSEMEM_VMEMMAP/CONFIG_FLATMEM */  | 
