pageattr.c 20.8 KB
Newer Older
1 2
/*
 * Copyright 2002 Andi Kleen, SuSE Labs.
L
Linus Torvalds 已提交
3
 * Thanks to Ben LaHaise for precious feedback.
4
 */
L
Linus Torvalds 已提交
5
#include <linux/highmem.h>
I
Ingo Molnar 已提交
6
#include <linux/bootmem.h>
L
Linus Torvalds 已提交
7
#include <linux/module.h>
8
#include <linux/sched.h>
L
Linus Torvalds 已提交
9
#include <linux/slab.h>
10
#include <linux/mm.h>
11
#include <linux/interrupt.h>
12

13
#include <asm/e820.h>
L
Linus Torvalds 已提交
14 15
#include <asm/processor.h>
#include <asm/tlbflush.h>
D
Dave Jones 已提交
16
#include <asm/sections.h>
17 18
#include <asm/uaccess.h>
#include <asm/pgalloc.h>
T
Thomas Gleixner 已提交
19
#include <asm/proto.h>
L
Linus Torvalds 已提交
20

I
Ingo Molnar 已提交
21 22 23
/*
 * The current flushing context - we pass it instead of 5 arguments:
 */
T
Thomas Gleixner 已提交
24 25 26 27
struct cpa_data {
	unsigned long	vaddr;
	pgprot_t	mask_set;
	pgprot_t	mask_clr;
28
	int		numpages;
29
	int		flushtlb;
T
Thomas Gleixner 已提交
30
	unsigned long	pfn;
T
Thomas Gleixner 已提交
31 32
};

T
Thomas Gleixner 已提交
33 34 35 36 37 38 39 40 41 42 43 44 45 46
#ifdef CONFIG_X86_64

static inline unsigned long highmap_start_pfn(void)
{
	return __pa(_text) >> PAGE_SHIFT;
}

static inline unsigned long highmap_end_pfn(void)
{
	return __pa(round_up((unsigned long)_end, PMD_SIZE)) >> PAGE_SHIFT;
}

#endif

47 48
static inline int
within(unsigned long addr, unsigned long start, unsigned long end)
I
Ingo Molnar 已提交
49
{
50 51 52
	return addr >= start && addr < end;
}

T
Thomas Gleixner 已提交
53 54 55
/*
 * Flushing functions
 */
56 57 58 59 60 61 62 63 64

/**
 * clflush_cache_range - flush a cache range with clflush
 * @addr:	virtual start address
 * @size:	number of bytes to flush
 *
 * clflush is an unordered instruction which needs fencing with mfence
 * to avoid ordering issues.
 */
I
Ingo Molnar 已提交
65
void clflush_cache_range(void *vaddr, unsigned int size)
T
Thomas Gleixner 已提交
66
{
I
Ingo Molnar 已提交
67
	void *vend = vaddr + size - 1;
T
Thomas Gleixner 已提交
68

69
	mb();
I
Ingo Molnar 已提交
70 71 72 73 74 75 76 77

	for (; vaddr < vend; vaddr += boot_cpu_data.x86_clflush_size)
		clflush(vaddr);
	/*
	 * Flush any possible final partial cacheline:
	 */
	clflush(vend);

78
	mb();
T
Thomas Gleixner 已提交
79 80
}

81
static void __cpa_flush_all(void *arg)
T
Thomas Gleixner 已提交
82
{
83 84
	unsigned long cache = (unsigned long)arg;

T
Thomas Gleixner 已提交
85 86 87 88 89 90
	/*
	 * Flush all to work around Errata in early athlons regarding
	 * large page flushing.
	 */
	__flush_tlb_all();

91
	if (cache && boot_cpu_data.x86_model >= 4)
T
Thomas Gleixner 已提交
92 93 94
		wbinvd();
}

95
static void cpa_flush_all(unsigned long cache)
T
Thomas Gleixner 已提交
96 97 98
{
	BUG_ON(irqs_disabled());

99
	on_each_cpu(__cpa_flush_all, (void *) cache, 1, 1);
T
Thomas Gleixner 已提交
100 101
}

102 103 104 105 106 107 108 109 110 111
static void __cpa_flush_range(void *arg)
{
	/*
	 * We could optimize that further and do individual per page
	 * tlb invalidates for a low number of pages. Caveat: we must
	 * flush the high aliases on 64bit as well.
	 */
	__flush_tlb_all();
}

112
static void cpa_flush_range(unsigned long start, int numpages, int cache)
113
{
I
Ingo Molnar 已提交
114 115 116
	unsigned int i, level;
	unsigned long addr;

117
	BUG_ON(irqs_disabled());
I
Ingo Molnar 已提交
118
	WARN_ON(PAGE_ALIGN(start) != start);
119

T
Thomas Gleixner 已提交
120
	on_each_cpu(__cpa_flush_range, NULL, 1, 1);
121

122 123 124
	if (!cache)
		return;

T
Thomas Gleixner 已提交
125 126 127 128 129 130
	/*
	 * We only need to flush on one CPU,
	 * clflush is a MESI-coherent instruction that
	 * will cause all other CPUs to flush the same
	 * cachelines:
	 */
I
Ingo Molnar 已提交
131 132 133 134 135 136
	for (i = 0, addr = start; i < numpages; i++, addr += PAGE_SIZE) {
		pte_t *pte = lookup_address(addr, &level);

		/*
		 * Only flush present addresses:
		 */
137
		if (pte && (pte_val(*pte) & _PAGE_PRESENT))
I
Ingo Molnar 已提交
138 139
			clflush_cache_range((void *) addr, PAGE_SIZE);
	}
140 141
}

142 143 144 145 146 147
/*
 * Certain areas of memory on x86 require very specific protection flags,
 * for example the BIOS area or kernel text. Callers don't always get this
 * right (again, ioremap() on BIOS memory is not uncommon) so this function
 * checks and fixes these known static required protection bits.
 */
T
Thomas Gleixner 已提交
148 149
static inline pgprot_t static_protections(pgprot_t prot, unsigned long address,
				   unsigned long pfn)
150 151 152
{
	pgprot_t forbidden = __pgprot(0);

I
Ingo Molnar 已提交
153
	/*
154 155
	 * The BIOS area between 640k and 1Mb needs to be executable for
	 * PCI BIOS based config access (CONFIG_PCI_GOBIOS) support.
I
Ingo Molnar 已提交
156
	 */
T
Thomas Gleixner 已提交
157
	if (within(pfn, BIOS_BEGIN >> PAGE_SHIFT, BIOS_END >> PAGE_SHIFT))
158 159 160 161
		pgprot_val(forbidden) |= _PAGE_NX;

	/*
	 * The kernel text needs to be executable for obvious reasons
T
Thomas Gleixner 已提交
162 163
	 * Does not cover __inittext since that is gone later on. On
	 * 64bit we do not enforce !NX on the low mapping
164 165 166
	 */
	if (within(address, (unsigned long)_text, (unsigned long)_etext))
		pgprot_val(forbidden) |= _PAGE_NX;
167 168

	/*
T
Thomas Gleixner 已提交
169 170
	 * The .rodata section needs to be read-only. Using the pfn
	 * catches all aliases.
171
	 */
T
Thomas Gleixner 已提交
172 173
	if (within(pfn, __pa((unsigned long)__start_rodata) >> PAGE_SHIFT,
		   __pa((unsigned long)__end_rodata) >> PAGE_SHIFT))
174
		pgprot_val(forbidden) |= _PAGE_RW;
175 176

	prot = __pgprot(pgprot_val(prot) & ~pgprot_val(forbidden));
I
Ingo Molnar 已提交
177 178 179 180

	return prot;
}

T
Thomas Gleixner 已提交
181 182 183 184 185 186 187 188
/*
 * Lookup the page table entry for a virtual address. Return a pointer
 * to the entry and the level of the mapping.
 *
 * Note: We return pud and pmd either when the entry is marked large
 * or when the present bit is not set. Otherwise we would return a
 * pointer to a nonexisting mapping.
 */
189
pte_t *lookup_address(unsigned long address, unsigned int *level)
190
{
L
Linus Torvalds 已提交
191 192 193
	pgd_t *pgd = pgd_offset_k(address);
	pud_t *pud;
	pmd_t *pmd;
194

T
Thomas Gleixner 已提交
195 196
	*level = PG_LEVEL_NONE;

L
Linus Torvalds 已提交
197 198
	if (pgd_none(*pgd))
		return NULL;
I
Ingo Molnar 已提交
199

L
Linus Torvalds 已提交
200 201 202
	pud = pud_offset(pgd, address);
	if (pud_none(*pud))
		return NULL;
203 204 205 206 207

	*level = PG_LEVEL_1G;
	if (pud_large(*pud) || !pud_present(*pud))
		return (pte_t *)pud;

L
Linus Torvalds 已提交
208 209 210
	pmd = pmd_offset(pud, address);
	if (pmd_none(*pmd))
		return NULL;
T
Thomas Gleixner 已提交
211 212

	*level = PG_LEVEL_2M;
T
Thomas Gleixner 已提交
213
	if (pmd_large(*pmd) || !pmd_present(*pmd))
L
Linus Torvalds 已提交
214 215
		return (pte_t *)pmd;

T
Thomas Gleixner 已提交
216
	*level = PG_LEVEL_4K;
I
Ingo Molnar 已提交
217

218 219 220
	return pte_offset_kernel(pmd, address);
}

I
Ingo Molnar 已提交
221 222 223
/*
 * Set the new pmd in all the pgds we know about:
 */
I
Ingo Molnar 已提交
224
static void __set_pmd_pte(pte_t *kpte, unsigned long address, pte_t pte)
225 226 227
{
	/* change init_mm */
	set_pte_atomic(kpte, pte);
228
#ifdef CONFIG_X86_32
229
	if (!SHARED_KERNEL_PMD) {
230 231
		struct page *page;

232
		list_for_each_entry(page, &pgd_list, lru) {
233 234 235 236 237 238 239 240 241
			pgd_t *pgd;
			pud_t *pud;
			pmd_t *pmd;

			pgd = (pgd_t *)page_address(page) + pgd_index(address);
			pud = pud_offset(pgd, address);
			pmd = pmd_offset(pud, address);
			set_pte_atomic((pte_t *)pmd, pte);
		}
L
Linus Torvalds 已提交
242
	}
243
#endif
L
Linus Torvalds 已提交
244 245
}

I
Ingo Molnar 已提交
246 247 248
static int
try_preserve_large_page(pte_t *kpte, unsigned long address,
			struct cpa_data *cpa)
249
{
T
Thomas Gleixner 已提交
250
	unsigned long nextpage_addr, numpages, pmask, psize, flags, addr, pfn;
251 252
	pte_t new_pte, old_pte, *tmp;
	pgprot_t old_prot, new_prot;
253
	int i, do_split = 1;
254
	unsigned int level;
255 256 257 258 259 260 261 262 263 264 265 266

	spin_lock_irqsave(&pgd_lock, flags);
	/*
	 * Check for races, another CPU might have split this page
	 * up already:
	 */
	tmp = lookup_address(address, &level);
	if (tmp != kpte)
		goto out_unlock;

	switch (level) {
	case PG_LEVEL_2M:
267 268
		psize = PMD_PAGE_SIZE;
		pmask = PMD_PAGE_MASK;
269
		break;
270
#ifdef CONFIG_X86_64
271
	case PG_LEVEL_1G:
272 273
		psize = PUD_PAGE_SIZE;
		pmask = PUD_PAGE_MASK;
274 275
		break;
#endif
276
	default:
I
Ingo Molnar 已提交
277
		do_split = -EINVAL;
278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297
		goto out_unlock;
	}

	/*
	 * Calculate the number of pages, which fit into this large
	 * page starting at address:
	 */
	nextpage_addr = (address + psize) & pmask;
	numpages = (nextpage_addr - address) >> PAGE_SHIFT;
	if (numpages < cpa->numpages)
		cpa->numpages = numpages;

	/*
	 * We are safe now. Check whether the new pgprot is the same:
	 */
	old_pte = *kpte;
	old_prot = new_prot = pte_pgprot(old_pte);

	pgprot_val(new_prot) &= ~pgprot_val(cpa->mask_clr);
	pgprot_val(new_prot) |= pgprot_val(cpa->mask_set);
T
Thomas Gleixner 已提交
298 299 300 301 302 303 304 305 306

	/*
	 * old_pte points to the large page base address. So we need
	 * to add the offset of the virtual address:
	 */
	pfn = pte_pfn(old_pte) + ((address & (psize - 1)) >> PAGE_SHIFT);
	cpa->pfn = pfn;

	new_prot = static_protections(new_prot, address, pfn);
307

308 309 310 311 312 313
	/*
	 * We need to check the full range, whether
	 * static_protection() requires a different pgprot for one of
	 * the pages in the range we try to preserve:
	 */
	addr = address + PAGE_SIZE;
T
Thomas Gleixner 已提交
314 315 316
	pfn++;
	for (i = 1; i < cpa->numpages; i++, addr += PAGE_SIZE, pfn++) {
		pgprot_t chk_prot = static_protections(new_prot, addr, pfn);
317 318 319 320 321

		if (pgprot_val(chk_prot) != pgprot_val(new_prot))
			goto out_unlock;
	}

322 323 324 325 326
	/*
	 * If there are no changes, return. maxpages has been updated
	 * above:
	 */
	if (pgprot_val(new_prot) == pgprot_val(old_prot)) {
I
Ingo Molnar 已提交
327
		do_split = 0;
328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346
		goto out_unlock;
	}

	/*
	 * We need to change the attributes. Check, whether we can
	 * change the large page in one go. We request a split, when
	 * the address is not aligned and the number of pages is
	 * smaller than the number of pages in the large page. Note
	 * that we limited the number of possible pages already to
	 * the number of pages in the large page.
	 */
	if (address == (nextpage_addr - psize) && cpa->numpages == numpages) {
		/*
		 * The address is aligned and the number of pages
		 * covers the full page.
		 */
		new_pte = pfn_pte(pte_pfn(old_pte), canon_pgprot(new_prot));
		__set_pmd_pte(kpte, address, new_pte);
		cpa->flushtlb = 1;
I
Ingo Molnar 已提交
347
		do_split = 0;
348 349 350 351
	}

out_unlock:
	spin_unlock_irqrestore(&pgd_lock, flags);
I
Ingo Molnar 已提交
352

I
Ingo Molnar 已提交
353
	return do_split;
354 355
}

356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426
static LIST_HEAD(page_pool);
static unsigned long pool_size, pool_pages, pool_low;
static unsigned long pool_used, pool_failed, pool_refill;

static void cpa_fill_pool(void)
{
	struct page *p;
	gfp_t gfp = GFP_KERNEL;

	/* Do not allocate from interrupt context */
	if (in_irq() || irqs_disabled())
		return;
	/*
	 * Check unlocked. I does not matter when we have one more
	 * page in the pool. The bit lock avoids recursive pool
	 * allocations:
	 */
	if (pool_pages >= pool_size || test_and_set_bit_lock(0, &pool_refill))
		return;

#ifdef CONFIG_DEBUG_PAGEALLOC
	/*
	 * We could do:
	 * gfp = in_atomic() ? GFP_ATOMIC : GFP_KERNEL;
	 * but this fails on !PREEMPT kernels
	 */
	gfp =  GFP_ATOMIC | __GFP_NORETRY | __GFP_NOWARN;
#endif

	while (pool_pages < pool_size) {
		p = alloc_pages(gfp, 0);
		if (!p) {
			pool_failed++;
			break;
		}
		spin_lock_irq(&pgd_lock);
		list_add(&p->lru, &page_pool);
		pool_pages++;
		spin_unlock_irq(&pgd_lock);
	}
	clear_bit_unlock(0, &pool_refill);
}

#define SHIFT_MB		(20 - PAGE_SHIFT)
#define ROUND_MB_GB		((1 << 10) - 1)
#define SHIFT_MB_GB		10
#define POOL_PAGES_PER_GB	16

void __init cpa_init(void)
{
	struct sysinfo si;
	unsigned long gb;

	si_meminfo(&si);
	/*
	 * Calculate the number of pool pages:
	 *
	 * Convert totalram (nr of pages) to MiB and round to the next
	 * GiB. Shift MiB to Gib and multiply the result by
	 * POOL_PAGES_PER_GB:
	 */
	gb = ((si.totalram >> SHIFT_MB) + ROUND_MB_GB) >> SHIFT_MB_GB;
	pool_size = POOL_PAGES_PER_GB * gb;
	pool_low = pool_size;

	cpa_fill_pool();
	printk(KERN_DEBUG
	       "CPA: page pool initialized %lu of %lu pages preallocated\n",
	       pool_pages, pool_size);
}

427
static int split_large_page(pte_t *kpte, unsigned long address)
428
{
T
Thomas Gleixner 已提交
429
	unsigned long flags, pfn, pfninc = 1;
I
Ingo Molnar 已提交
430
	unsigned int i, level;
431
	pte_t *pbase, *tmp;
I
Ingo Molnar 已提交
432
	pgprot_t ref_prot;
433 434
	struct page *base;

T
Thomas Gleixner 已提交
435 436 437 438 439 440 441 442
	/*
	 * Get a page from the pool. The pool list is protected by the
	 * pgd_lock, which we have to take anyway for the split
	 * operation:
	 */
	spin_lock_irqsave(&pgd_lock, flags);
	if (list_empty(&page_pool)) {
		spin_unlock_irqrestore(&pgd_lock, flags);
443
		return -ENOMEM;
T
Thomas Gleixner 已提交
444 445 446 447 448 449 450 451
	}

	base = list_first_entry(&page_pool, struct page, lru);
	list_del(&base->lru);
	pool_pages--;

	if (pool_pages < pool_low)
		pool_low = pool_pages;
452 453 454 455 456 457

	/*
	 * Check for races, another CPU might have split this page
	 * up for us already:
	 */
	tmp = lookup_address(address, &level);
I
Ingo Molnar 已提交
458
	if (tmp != kpte)
459 460 461
		goto out_unlock;

	pbase = (pte_t *)page_address(base);
462
#ifdef CONFIG_X86_32
463
	paravirt_alloc_pt(&init_mm, page_to_pfn(base));
464
#endif
T
Thomas Gleixner 已提交
465
	ref_prot = pte_pgprot(pte_clrhuge(*kpte));
466

467 468 469 470 471 472 473
#ifdef CONFIG_X86_64
	if (level == PG_LEVEL_1G) {
		pfninc = PMD_PAGE_SIZE >> PAGE_SHIFT;
		pgprot_val(ref_prot) |= _PAGE_PSE;
	}
#endif

474 475 476 477
	/*
	 * Get the target pfn from the original entry:
	 */
	pfn = pte_pfn(*kpte);
478
	for (i = 0; i < PTRS_PER_PTE; i++, pfn += pfninc)
479
		set_pte(&pbase[i], pfn_pte(pfn, ref_prot));
480 481

	/*
T
Thomas Gleixner 已提交
482
	 * Install the new, split up pagetable. Important details here:
483 484 485 486
	 *
	 * On Intel the NX bit of all levels must be cleared to make a
	 * page executable. See section 4.13.2 of Intel 64 and IA-32
	 * Architectures Software Developer's Manual).
T
Thomas Gleixner 已提交
487 488 489
	 *
	 * Mark the entry present. The current mapping might be
	 * set to not present, which we preserved above.
490
	 */
491
	ref_prot = pte_pgprot(pte_mkexec(pte_clrhuge(*kpte)));
T
Thomas Gleixner 已提交
492
	pgprot_val(ref_prot) |= _PAGE_PRESENT;
I
Ingo Molnar 已提交
493
	__set_pmd_pte(kpte, address, mk_pte(base, ref_prot));
494 495 496
	base = NULL;

out_unlock:
T
Thomas Gleixner 已提交
497 498 499 500 501 502 503 504 505
	/*
	 * If we dropped out via the lookup_address check under
	 * pgd_lock then stick the page back into the pool:
	 */
	if (base) {
		list_add(&base->lru, &page_pool);
		pool_pages++;
	} else
		pool_used++;
I
Ingo Molnar 已提交
506
	spin_unlock_irqrestore(&pgd_lock, flags);
507 508 509 510

	return 0;
}

T
Thomas Gleixner 已提交
511
static int __change_page_attr(struct cpa_data *cpa, int primary)
512
{
T
Thomas Gleixner 已提交
513
	unsigned long address = cpa->vaddr;
514 515
	int do_split, err;
	unsigned int level;
L
Linus Torvalds 已提交
516
	struct page *kpte_page;
T
Thomas Gleixner 已提交
517
	pte_t *kpte, old_pte;
L
Linus Torvalds 已提交
518

519
repeat:
520
	kpte = lookup_address(address, &level);
L
Linus Torvalds 已提交
521
	if (!kpte)
T
Thomas Gleixner 已提交
522 523 524 525 526 527 528 529 530 531
		return primary ? -EINVAL : 0;

	old_pte = *kpte;
	if (!pte_val(old_pte)) {
		if (!primary)
			return 0;
		printk(KERN_WARNING "CPA: called for zero pte. "
		       "vaddr = %lx cpa->vaddr = %lx\n", address,
		       cpa->vaddr);
		WARN_ON(1);
L
Linus Torvalds 已提交
532
		return -EINVAL;
T
Thomas Gleixner 已提交
533
	}
534

L
Linus Torvalds 已提交
535
	kpte_page = virt_to_page(kpte);
536 537 538
	BUG_ON(PageLRU(kpte_page));
	BUG_ON(PageCompound(kpte_page));

T
Thomas Gleixner 已提交
539
	if (level == PG_LEVEL_4K) {
T
Thomas Gleixner 已提交
540
		pte_t new_pte;
541
		pgprot_t new_prot = pte_pgprot(old_pte);
T
Thomas Gleixner 已提交
542
		unsigned long pfn = pte_pfn(old_pte);
I
Ingo Molnar 已提交
543

T
Thomas Gleixner 已提交
544 545
		pgprot_val(new_prot) &= ~pgprot_val(cpa->mask_clr);
		pgprot_val(new_prot) |= pgprot_val(cpa->mask_set);
I
Ingo Molnar 已提交
546

T
Thomas Gleixner 已提交
547
		new_prot = static_protections(new_prot, address, pfn);
I
Ingo Molnar 已提交
548

549 550 551 552 553
		/*
		 * We need to keep the pfn from the existing PTE,
		 * after all we're only going to change it's attributes
		 * not the memory it points to
		 */
T
Thomas Gleixner 已提交
554 555
		new_pte = pfn_pte(pfn, canon_pgprot(new_prot));
		cpa->pfn = pfn;
556 557 558 559 560 561 562
		/*
		 * Do we really change anything ?
		 */
		if (pte_val(old_pte) != pte_val(new_pte)) {
			set_pte_atomic(kpte, new_pte);
			cpa->flushtlb = 1;
		}
563 564
		cpa->numpages = 1;
		return 0;
L
Linus Torvalds 已提交
565
	}
566 567 568 569 570

	/*
	 * Check, whether we can keep the large page intact
	 * and just change the pte:
	 */
I
Ingo Molnar 已提交
571
	do_split = try_preserve_large_page(kpte, address, cpa);
572 573 574 575 576
	/*
	 * When the range fits into the existing large page,
	 * return. cp->numpages and cpa->tlbflush have been updated in
	 * try_large_page:
	 */
I
Ingo Molnar 已提交
577 578
	if (do_split <= 0)
		return do_split;
579 580 581 582

	/*
	 * We have to split the large page:
	 */
I
Ingo Molnar 已提交
583 584 585 586 587
	err = split_large_page(kpte, address);
	if (!err) {
		cpa->flushtlb = 1;
		goto repeat;
	}
I
Ingo Molnar 已提交
588

I
Ingo Molnar 已提交
589
	return err;
590
}
L
Linus Torvalds 已提交
591

T
Thomas Gleixner 已提交
592 593 594
static int __change_page_attr_set_clr(struct cpa_data *cpa, int checkalias);

static int cpa_process_alias(struct cpa_data *cpa)
L
Linus Torvalds 已提交
595
{
T
Thomas Gleixner 已提交
596 597
	struct cpa_data alias_cpa;
	int ret;
598

T
Thomas Gleixner 已提交
599 600
	if (cpa->pfn > max_pfn_mapped)
		return 0;
601

T
Thomas Gleixner 已提交
602 603
	alias_cpa = *cpa;
	alias_cpa.vaddr = (unsigned long) __va(cpa->pfn << PAGE_SHIFT);
604

T
Thomas Gleixner 已提交
605
	ret = __change_page_attr_set_clr(&alias_cpa, 0);
606 607

#ifdef CONFIG_X86_64
T
Thomas Gleixner 已提交
608 609
	if (ret)
		return ret;
A
Arjan van de Ven 已提交
610
	/*
611 612
	 * If the physical address is inside the kernel map, we need
	 * to touch the high mapped kernel as well:
A
Arjan van de Ven 已提交
613
	 */
T
Thomas Gleixner 已提交
614 615
	if (!within(cpa->pfn, highmap_start_pfn(), highmap_end_pfn()))
		return 0;
616

T
Thomas Gleixner 已提交
617 618 619 620 621 622 623 624
	alias_cpa = *cpa;
	alias_cpa.vaddr =
		(cpa->pfn << PAGE_SHIFT) + __START_KERNEL_map - phys_base;

	/*
	 * The high mapping range is imprecise, so ignore the return value.
	 */
	__change_page_attr_set_clr(&alias_cpa, 0);
A
Arjan van de Ven 已提交
625
#endif
T
Thomas Gleixner 已提交
626
	return ret;
L
Linus Torvalds 已提交
627 628
}

T
Thomas Gleixner 已提交
629
static int __change_page_attr_set_clr(struct cpa_data *cpa, int checkalias)
630
{
631
	int ret, numpages = cpa->numpages;
632

633 634 635 636 637 638
	while (numpages) {
		/*
		 * Store the remaining nr of pages for the large page
		 * preservation check.
		 */
		cpa->numpages = numpages;
T
Thomas Gleixner 已提交
639 640

		ret = __change_page_attr(cpa, checkalias);
641 642 643
		if (ret)
			return ret;

T
Thomas Gleixner 已提交
644 645 646 647 648 649
		if (checkalias) {
			ret = cpa_process_alias(cpa);
			if (ret)
				return ret;
		}

650 651 652 653 654 655 656 657 658
		/*
		 * Adjust the number of pages with the result of the
		 * CPA operation. Either a large page has been
		 * preserved or a single page update happened.
		 */
		BUG_ON(cpa->numpages > numpages);
		numpages -= cpa->numpages;
		cpa->vaddr += cpa->numpages * PAGE_SIZE;
	}
659 660 661
	return 0;
}

662 663 664 665 666 667
static inline int cache_attr(pgprot_t attr)
{
	return pgprot_val(attr) &
		(_PAGE_PAT | _PAGE_PAT_LARGE | _PAGE_PWT | _PAGE_PCD);
}

668 669 670
static int change_page_attr_set_clr(unsigned long addr, int numpages,
				    pgprot_t mask_set, pgprot_t mask_clr)
{
T
Thomas Gleixner 已提交
671
	struct cpa_data cpa;
672
	int ret, cache, checkalias;
673 674 675 676 677 678 679 680 681 682

	/*
	 * Check, if we are requested to change a not supported
	 * feature:
	 */
	mask_set = canon_pgprot(mask_set);
	mask_clr = canon_pgprot(mask_clr);
	if (!pgprot_val(mask_set) && !pgprot_val(mask_clr))
		return 0;

683 684 685 686 687 688 689 690 691
	/* Ensure we are PAGE_SIZE aligned */
	if (addr & ~PAGE_MASK) {
		addr &= PAGE_MASK;
		/*
		 * People should not be passing in unaligned addresses:
		 */
		WARN_ON_ONCE(1);
	}

T
Thomas Gleixner 已提交
692 693 694 695
	cpa.vaddr = addr;
	cpa.numpages = numpages;
	cpa.mask_set = mask_set;
	cpa.mask_clr = mask_clr;
696
	cpa.flushtlb = 0;
T
Thomas Gleixner 已提交
697

698 699 700 701
	/* No alias checking for _NX bit modifications */
	checkalias = (pgprot_val(mask_set) | pgprot_val(mask_clr)) != _PAGE_NX;

	ret = __change_page_attr_set_clr(&cpa, checkalias);
702

703 704 705 706
	/*
	 * Check whether we really changed something:
	 */
	if (!cpa.flushtlb)
707
		goto out;
708

709 710 711 712 713 714
	/*
	 * No need to flush, when we did not set any of the caching
	 * attributes:
	 */
	cache = cache_attr(mask_set);

715 716 717
	/*
	 * On success we use clflush, when the CPU supports it to
	 * avoid the wbindv. If the CPU does not support it and in the
718
	 * error case we fall back to cpa_flush_all (which uses
719 720 721
	 * wbindv):
	 */
	if (!ret && cpu_has_clflush)
722
		cpa_flush_range(addr, numpages, cache);
723
	else
724
		cpa_flush_all(cache);
725

726 727
out:
	cpa_fill_pool();
728 729 730
	return ret;
}

731 732
static inline int change_page_attr_set(unsigned long addr, int numpages,
				       pgprot_t mask)
733
{
734
	return change_page_attr_set_clr(addr, numpages, mask, __pgprot(0));
735 736
}

737 738
static inline int change_page_attr_clear(unsigned long addr, int numpages,
					 pgprot_t mask)
739
{
H
Huang, Ying 已提交
740
	return change_page_attr_set_clr(addr, numpages, __pgprot(0), mask);
741 742 743 744 745 746
}

int set_memory_uc(unsigned long addr, int numpages)
{
	return change_page_attr_set(addr, numpages,
				    __pgprot(_PAGE_PCD | _PAGE_PWT));
747 748 749 750 751
}
EXPORT_SYMBOL(set_memory_uc);

int set_memory_wb(unsigned long addr, int numpages)
{
752 753
	return change_page_attr_clear(addr, numpages,
				      __pgprot(_PAGE_PCD | _PAGE_PWT));
754 755 756 757 758
}
EXPORT_SYMBOL(set_memory_wb);

int set_memory_x(unsigned long addr, int numpages)
{
759
	return change_page_attr_clear(addr, numpages, __pgprot(_PAGE_NX));
760 761 762 763 764
}
EXPORT_SYMBOL(set_memory_x);

int set_memory_nx(unsigned long addr, int numpages)
{
765
	return change_page_attr_set(addr, numpages, __pgprot(_PAGE_NX));
766 767 768 769 770
}
EXPORT_SYMBOL(set_memory_nx);

int set_memory_ro(unsigned long addr, int numpages)
{
771
	return change_page_attr_clear(addr, numpages, __pgprot(_PAGE_RW));
772 773 774 775
}

int set_memory_rw(unsigned long addr, int numpages)
{
776
	return change_page_attr_set(addr, numpages, __pgprot(_PAGE_RW));
777
}
I
Ingo Molnar 已提交
778 779 780

int set_memory_np(unsigned long addr, int numpages)
{
781
	return change_page_attr_clear(addr, numpages, __pgprot(_PAGE_PRESENT));
I
Ingo Molnar 已提交
782
}
783 784 785 786 787

int set_pages_uc(struct page *page, int numpages)
{
	unsigned long addr = (unsigned long)page_address(page);

T
Thomas Gleixner 已提交
788
	return set_memory_uc(addr, numpages);
789 790 791 792 793 794 795
}
EXPORT_SYMBOL(set_pages_uc);

int set_pages_wb(struct page *page, int numpages)
{
	unsigned long addr = (unsigned long)page_address(page);

T
Thomas Gleixner 已提交
796
	return set_memory_wb(addr, numpages);
797 798 799 800 801 802 803
}
EXPORT_SYMBOL(set_pages_wb);

int set_pages_x(struct page *page, int numpages)
{
	unsigned long addr = (unsigned long)page_address(page);

T
Thomas Gleixner 已提交
804
	return set_memory_x(addr, numpages);
805 806 807 808 809 810 811
}
EXPORT_SYMBOL(set_pages_x);

int set_pages_nx(struct page *page, int numpages)
{
	unsigned long addr = (unsigned long)page_address(page);

T
Thomas Gleixner 已提交
812
	return set_memory_nx(addr, numpages);
813 814 815 816 817 818 819
}
EXPORT_SYMBOL(set_pages_nx);

int set_pages_ro(struct page *page, int numpages)
{
	unsigned long addr = (unsigned long)page_address(page);

T
Thomas Gleixner 已提交
820
	return set_memory_ro(addr, numpages);
821 822 823 824 825
}

int set_pages_rw(struct page *page, int numpages)
{
	unsigned long addr = (unsigned long)page_address(page);
826

T
Thomas Gleixner 已提交
827
	return set_memory_rw(addr, numpages);
I
Ingo Molnar 已提交
828 829
}

L
Linus Torvalds 已提交
830
#ifdef CONFIG_DEBUG_PAGEALLOC
I
Ingo Molnar 已提交
831 832 833

static int __set_pages_p(struct page *page, int numpages)
{
T
Thomas Gleixner 已提交
834 835 836 837
	struct cpa_data cpa = { .vaddr = (unsigned long) page_address(page),
				.numpages = numpages,
				.mask_set = __pgprot(_PAGE_PRESENT | _PAGE_RW),
				.mask_clr = __pgprot(0)};
838

T
Thomas Gleixner 已提交
839
	return __change_page_attr_set_clr(&cpa, 1);
I
Ingo Molnar 已提交
840 841 842 843
}

static int __set_pages_np(struct page *page, int numpages)
{
T
Thomas Gleixner 已提交
844 845 846 847
	struct cpa_data cpa = { .vaddr = (unsigned long) page_address(page),
				.numpages = numpages,
				.mask_set = __pgprot(0),
				.mask_clr = __pgprot(_PAGE_PRESENT | _PAGE_RW)};
848

T
Thomas Gleixner 已提交
849
	return __change_page_attr_set_clr(&cpa, 1);
I
Ingo Molnar 已提交
850 851
}

L
Linus Torvalds 已提交
852 853 854 855
void kernel_map_pages(struct page *page, int numpages, int enable)
{
	if (PageHighMem(page))
		return;
856
	if (!enable) {
857 858
		debug_check_no_locks_freed(page_address(page),
					   numpages * PAGE_SIZE);
859
	}
860

861 862 863 864 865 866
	/*
	 * If page allocator is not up yet then do not call c_p_a():
	 */
	if (!debug_pagealloc_enabled)
		return;

867
	/*
I
Ingo Molnar 已提交
868 869 870 871 872 873
	 * The return value is ignored as the calls cannot fail.
	 * Large pages are kept enabled at boot time, and are
	 * split up quickly with DEBUG_PAGEALLOC. If a splitup
	 * fails here (due to temporary memory shortage) no damage
	 * is done because we just keep the largepage intact up
	 * to the next attempt when it will likely be split up:
L
Linus Torvalds 已提交
874
	 */
I
Ingo Molnar 已提交
875 876 877 878
	if (enable)
		__set_pages_p(page, numpages);
	else
		__set_pages_np(page, numpages);
879 880

	/*
881 882
	 * We should perform an IPI and flush all tlbs,
	 * but that can deadlock->flush only current cpu:
L
Linus Torvalds 已提交
883 884
	 */
	__flush_tlb_all();
885 886 887 888 889 890

	/*
	 * Try to refill the page pool here. We can do this only after
	 * the tlb flush.
	 */
	cpa_fill_pool();
L
Linus Torvalds 已提交
891 892
}
#endif
893 894 895 896 897 898 899 900

/*
 * The testcases use internal knowledge of the implementation that shouldn't
 * be exposed to the rest of the kernel. Include these directly here.
 */
#ifdef CONFIG_CPA_DEBUG
#include "pageattr-test.c"
#endif