diff options
Diffstat (limited to 'arch/x86/mm/pageattr.c')
-rw-r--r-- | arch/x86/mm/pageattr.c | 87 |
1 files changed, 39 insertions, 48 deletions
diff --git a/arch/x86/mm/pageattr.c b/arch/x86/mm/pageattr.c index 145f5edf488a..55f5b5cdb12e 100644 --- a/arch/x86/mm/pageattr.c +++ b/arch/x86/mm/pageattr.c | |||
@@ -301,8 +301,8 @@ static int change_page_attr_addr(unsigned long address, pgprot_t prot) | |||
301 | * This function is different from change_page_attr() in that only selected bits | 301 | * This function is different from change_page_attr() in that only selected bits |
302 | * are impacted, all other bits remain as is. | 302 | * are impacted, all other bits remain as is. |
303 | */ | 303 | */ |
304 | static int change_page_attr_set(unsigned long addr, int numpages, | 304 | static int __change_page_attr_set(unsigned long addr, int numpages, |
305 | pgprot_t prot) | 305 | pgprot_t prot) |
306 | { | 306 | { |
307 | pgprot_t current_prot, new_prot; | 307 | pgprot_t current_prot, new_prot; |
308 | int level; | 308 | int level; |
@@ -325,9 +325,19 @@ static int change_page_attr_set(unsigned long addr, int numpages, | |||
325 | return ret; | 325 | return ret; |
326 | addr += PAGE_SIZE; | 326 | addr += PAGE_SIZE; |
327 | } | 327 | } |
328 | |||
328 | return 0; | 329 | return 0; |
329 | } | 330 | } |
330 | 331 | ||
332 | static int change_page_attr_set(unsigned long addr, int numpages, pgprot_t prot) | ||
333 | { | ||
334 | int ret = __change_page_attr_set(addr, numpages, prot); | ||
335 | |||
336 | global_flush_tlb(); | ||
337 | return ret; | ||
338 | |||
339 | } | ||
340 | |||
331 | /** | 341 | /** |
332 | * change_page_attr_clear - Change page table attributes in the linear mapping. | 342 | * change_page_attr_clear - Change page table attributes in the linear mapping. |
333 | * @addr: Virtual address in linear mapping. | 343 | * @addr: Virtual address in linear mapping. |
@@ -347,8 +357,8 @@ static int change_page_attr_set(unsigned long addr, int numpages, | |||
347 | * This function is different from change_page_attr() in that only selected bits | 357 | * This function is different from change_page_attr() in that only selected bits |
348 | * are impacted, all other bits remain as is. | 358 | * are impacted, all other bits remain as is. |
349 | */ | 359 | */ |
350 | static int change_page_attr_clear(unsigned long addr, int numpages, | 360 | static int __change_page_attr_clear(unsigned long addr, int numpages, |
351 | pgprot_t prot) | 361 | pgprot_t prot) |
352 | { | 362 | { |
353 | pgprot_t current_prot, new_prot; | 363 | pgprot_t current_prot, new_prot; |
354 | int level; | 364 | int level; |
@@ -371,81 +381,59 @@ static int change_page_attr_clear(unsigned long addr, int numpages, | |||
371 | return ret; | 381 | return ret; |
372 | addr += PAGE_SIZE; | 382 | addr += PAGE_SIZE; |
373 | } | 383 | } |
384 | |||
374 | return 0; | 385 | return 0; |
375 | } | 386 | } |
376 | 387 | ||
377 | int set_memory_uc(unsigned long addr, int numpages) | 388 | static int change_page_attr_clear(unsigned long addr, int numpages, |
389 | pgprot_t prot) | ||
378 | { | 390 | { |
379 | int err; | 391 | int ret = __change_page_attr_clear(addr, numpages, prot); |
380 | 392 | ||
381 | err = change_page_attr_set(addr, numpages, | ||
382 | __pgprot(_PAGE_PCD | _PAGE_PWT)); | ||
383 | global_flush_tlb(); | 393 | global_flush_tlb(); |
384 | return err; | 394 | return ret; |
395 | |||
396 | } | ||
397 | |||
398 | int set_memory_uc(unsigned long addr, int numpages) | ||
399 | { | ||
400 | return change_page_attr_set(addr, numpages, | ||
401 | __pgprot(_PAGE_PCD | _PAGE_PWT)); | ||
385 | } | 402 | } |
386 | EXPORT_SYMBOL(set_memory_uc); | 403 | EXPORT_SYMBOL(set_memory_uc); |
387 | 404 | ||
388 | int set_memory_wb(unsigned long addr, int numpages) | 405 | int set_memory_wb(unsigned long addr, int numpages) |
389 | { | 406 | { |
390 | int err; | 407 | return change_page_attr_clear(addr, numpages, |
391 | 408 | __pgprot(_PAGE_PCD | _PAGE_PWT)); | |
392 | err = change_page_attr_clear(addr, numpages, | ||
393 | __pgprot(_PAGE_PCD | _PAGE_PWT)); | ||
394 | global_flush_tlb(); | ||
395 | return err; | ||
396 | } | 409 | } |
397 | EXPORT_SYMBOL(set_memory_wb); | 410 | EXPORT_SYMBOL(set_memory_wb); |
398 | 411 | ||
399 | int set_memory_x(unsigned long addr, int numpages) | 412 | int set_memory_x(unsigned long addr, int numpages) |
400 | { | 413 | { |
401 | int err; | 414 | return change_page_attr_clear(addr, numpages, __pgprot(_PAGE_NX)); |
402 | |||
403 | err = change_page_attr_clear(addr, numpages, | ||
404 | __pgprot(_PAGE_NX)); | ||
405 | global_flush_tlb(); | ||
406 | return err; | ||
407 | } | 415 | } |
408 | EXPORT_SYMBOL(set_memory_x); | 416 | EXPORT_SYMBOL(set_memory_x); |
409 | 417 | ||
410 | int set_memory_nx(unsigned long addr, int numpages) | 418 | int set_memory_nx(unsigned long addr, int numpages) |
411 | { | 419 | { |
412 | int err; | 420 | return change_page_attr_set(addr, numpages, __pgprot(_PAGE_NX)); |
413 | |||
414 | err = change_page_attr_set(addr, numpages, | ||
415 | __pgprot(_PAGE_NX)); | ||
416 | global_flush_tlb(); | ||
417 | return err; | ||
418 | } | 421 | } |
419 | EXPORT_SYMBOL(set_memory_nx); | 422 | EXPORT_SYMBOL(set_memory_nx); |
420 | 423 | ||
421 | int set_memory_ro(unsigned long addr, int numpages) | 424 | int set_memory_ro(unsigned long addr, int numpages) |
422 | { | 425 | { |
423 | int err; | 426 | return change_page_attr_clear(addr, numpages, __pgprot(_PAGE_RW)); |
424 | |||
425 | err = change_page_attr_clear(addr, numpages, | ||
426 | __pgprot(_PAGE_RW)); | ||
427 | global_flush_tlb(); | ||
428 | return err; | ||
429 | } | 427 | } |
430 | 428 | ||
431 | int set_memory_rw(unsigned long addr, int numpages) | 429 | int set_memory_rw(unsigned long addr, int numpages) |
432 | { | 430 | { |
433 | int err; | 431 | return change_page_attr_set(addr, numpages, __pgprot(_PAGE_RW)); |
434 | |||
435 | err = change_page_attr_set(addr, numpages, | ||
436 | __pgprot(_PAGE_RW)); | ||
437 | global_flush_tlb(); | ||
438 | return err; | ||
439 | } | 432 | } |
440 | 433 | ||
441 | int set_memory_np(unsigned long addr, int numpages) | 434 | int set_memory_np(unsigned long addr, int numpages) |
442 | { | 435 | { |
443 | int err; | 436 | return change_page_attr_clear(addr, numpages, __pgprot(_PAGE_PRESENT)); |
444 | |||
445 | err = change_page_attr_clear(addr, numpages, | ||
446 | __pgprot(_PAGE_PRESENT)); | ||
447 | global_flush_tlb(); | ||
448 | return err; | ||
449 | } | 437 | } |
450 | 438 | ||
451 | int set_pages_uc(struct page *page, int numpages) | 439 | int set_pages_uc(struct page *page, int numpages) |
@@ -500,14 +488,17 @@ int set_pages_rw(struct page *page, int numpages) | |||
500 | static int __set_pages_p(struct page *page, int numpages) | 488 | static int __set_pages_p(struct page *page, int numpages) |
501 | { | 489 | { |
502 | unsigned long addr = (unsigned long)page_address(page); | 490 | unsigned long addr = (unsigned long)page_address(page); |
503 | return change_page_attr_set(addr, numpages, | 491 | |
504 | __pgprot(_PAGE_PRESENT | _PAGE_RW)); | 492 | return __change_page_attr_set(addr, numpages, |
493 | __pgprot(_PAGE_PRESENT | _PAGE_RW)); | ||
505 | } | 494 | } |
506 | 495 | ||
507 | static int __set_pages_np(struct page *page, int numpages) | 496 | static int __set_pages_np(struct page *page, int numpages) |
508 | { | 497 | { |
509 | unsigned long addr = (unsigned long)page_address(page); | 498 | unsigned long addr = (unsigned long)page_address(page); |
510 | return change_page_attr_clear(addr, numpages, __pgprot(_PAGE_PRESENT)); | 499 | |
500 | return __change_page_attr_clear(addr, numpages, | ||
501 | __pgprot(_PAGE_PRESENT)); | ||
511 | } | 502 | } |
512 | 503 | ||
513 | void kernel_map_pages(struct page *page, int numpages, int enable) | 504 | void kernel_map_pages(struct page *page, int numpages, int enable) |