diff options
Diffstat (limited to 'arch/x86/mm/pageattr.c')
| -rw-r--r-- | arch/x86/mm/pageattr.c | 39 | 
1 files changed, 27 insertions, 12 deletions
diff --git a/arch/x86/mm/pageattr.c b/arch/x86/mm/pageattr.c index 1b734d7a896..7e600c1962d 100644 --- a/arch/x86/mm/pageattr.c +++ b/arch/x86/mm/pageattr.c @@ -591,9 +591,12 @@ static int __change_page_attr(struct cpa_data *cpa, int primary)  	unsigned int level;  	pte_t *kpte, old_pte; -	if (cpa->flags & CPA_PAGES_ARRAY) -		address = (unsigned long)page_address(cpa->pages[cpa->curpage]); -	else if (cpa->flags & CPA_ARRAY) +	if (cpa->flags & CPA_PAGES_ARRAY) { +		struct page *page = cpa->pages[cpa->curpage]; +		if (unlikely(PageHighMem(page))) +			return 0; +		address = (unsigned long)page_address(page); +	} else if (cpa->flags & CPA_ARRAY)  		address = cpa->vaddr[cpa->curpage];  	else  		address = *cpa->vaddr; @@ -697,9 +700,12 @@ static int cpa_process_alias(struct cpa_data *cpa)  	 * No need to redo, when the primary call touched the direct  	 * mapping already:  	 */ -	if (cpa->flags & CPA_PAGES_ARRAY) -		vaddr = (unsigned long)page_address(cpa->pages[cpa->curpage]); -	else if (cpa->flags & CPA_ARRAY) +	if (cpa->flags & CPA_PAGES_ARRAY) { +		struct page *page = cpa->pages[cpa->curpage]; +		if (unlikely(PageHighMem(page))) +			return 0; +		vaddr = (unsigned long)page_address(page); +	} else if (cpa->flags & CPA_ARRAY)  		vaddr = cpa->vaddr[cpa->curpage];  	else  		vaddr = *cpa->vaddr; @@ -997,12 +1003,15 @@ EXPORT_SYMBOL(set_memory_array_uc);  int _set_memory_wc(unsigned long addr, int numpages)  {  	int ret; +	unsigned long addr_copy = addr; +  	ret = change_page_attr_set(&addr, numpages,  				    __pgprot(_PAGE_CACHE_UC_MINUS), 0); -  	if (!ret) { -		ret = change_page_attr_set(&addr, numpages, -				    __pgprot(_PAGE_CACHE_WC), 0); +		ret = change_page_attr_set_clr(&addr_copy, numpages, +					       __pgprot(_PAGE_CACHE_WC), +					       __pgprot(_PAGE_CACHE_MASK), +					       0, 0, NULL);  	}  	return ret;  } @@ -1119,7 +1128,9 @@ int set_pages_array_uc(struct page **pages, int addrinarray)  	int free_idx;  	for (i = 0; i < addrinarray; i++) { -		start = (unsigned long)page_address(pages[i]); +		if (PageHighMem(pages[i])) +			continue; +		start = page_to_pfn(pages[i]) << PAGE_SHIFT;  		end = start + PAGE_SIZE;  		if (reserve_memtype(start, end, _PAGE_CACHE_UC_MINUS, NULL))  			goto err_out; @@ -1132,7 +1143,9 @@ int set_pages_array_uc(struct page **pages, int addrinarray)  err_out:  	free_idx = i;  	for (i = 0; i < free_idx; i++) { -		start = (unsigned long)page_address(pages[i]); +		if (PageHighMem(pages[i])) +			continue; +		start = page_to_pfn(pages[i]) << PAGE_SHIFT;  		end = start + PAGE_SIZE;  		free_memtype(start, end);  	} @@ -1161,7 +1174,9 @@ int set_pages_array_wb(struct page **pages, int addrinarray)  		return retval;  	for (i = 0; i < addrinarray; i++) { -		start = (unsigned long)page_address(pages[i]); +		if (PageHighMem(pages[i])) +			continue; +		start = page_to_pfn(pages[i]) << PAGE_SHIFT;  		end = start + PAGE_SIZE;  		free_memtype(start, end);  	}  |