Commit d1737fdbec7f90edc52dd0c5c3767457f28e78d8

Authored by Andi Kleen
Committed by Andi Kleen
1 parent ad5fa91399

HWPOISON: Add basic support for poisoned pages in fault handler v3

- Add a new VM_FAULT_HWPOISON error code to handle_mm_fault. Right now
architectures have to explicitely enable poison page support, so
this is forward compatible to all architectures. They only need
to add it when they enable poison page support.
- Add poison page handling in swap in fault code

v2: Add missing delayacct_clear_flag (Hidehiro Kawai)
v3: Really use delayacct_clear_flag (Hidehiro Kawai)

Signed-off-by: Andi Kleen <ak@linux.intel.com>

Showing 2 changed files with 17 additions and 4 deletions Side-by-side Diff

... ... @@ -685,11 +685,12 @@
685 685 #define VM_FAULT_SIGBUS 0x0002
686 686 #define VM_FAULT_MAJOR 0x0004
687 687 #define VM_FAULT_WRITE 0x0008 /* Special case for get_user_pages */
  688 +#define VM_FAULT_HWPOISON 0x0010 /* Hit poisoned page */
688 689  
689 690 #define VM_FAULT_NOPAGE 0x0100 /* ->fault installed the pte, not return page */
690 691 #define VM_FAULT_LOCKED 0x0200 /* ->fault locked the returned page */
691 692  
692   -#define VM_FAULT_ERROR (VM_FAULT_OOM | VM_FAULT_SIGBUS)
  693 +#define VM_FAULT_ERROR (VM_FAULT_OOM | VM_FAULT_SIGBUS | VM_FAULT_HWPOISON)
693 694  
694 695 /*
695 696 * Can be called by the pagefault handler when it gets a VM_FAULT_OOM.
... ... @@ -1319,7 +1319,8 @@
1319 1319 if (ret & VM_FAULT_ERROR) {
1320 1320 if (ret & VM_FAULT_OOM)
1321 1321 return i ? i : -ENOMEM;
1322   - else if (ret & VM_FAULT_SIGBUS)
  1322 + if (ret &
  1323 + (VM_FAULT_HWPOISON|VM_FAULT_SIGBUS))
1323 1324 return i ? i : -EFAULT;
1324 1325 BUG();
1325 1326 }
... ... @@ -2511,8 +2512,15 @@
2511 2512 goto out;
2512 2513  
2513 2514 entry = pte_to_swp_entry(orig_pte);
2514   - if (is_migration_entry(entry)) {
2515   - migration_entry_wait(mm, pmd, address);
  2515 + if (unlikely(non_swap_entry(entry))) {
  2516 + if (is_migration_entry(entry)) {
  2517 + migration_entry_wait(mm, pmd, address);
  2518 + } else if (is_hwpoison_entry(entry)) {
  2519 + ret = VM_FAULT_HWPOISON;
  2520 + } else {
  2521 + print_bad_pte(vma, address, orig_pte, NULL);
  2522 + ret = VM_FAULT_OOM;
  2523 + }
2516 2524 goto out;
2517 2525 }
2518 2526 delayacct_set_flag(DELAYACCT_PF_SWAPIN);
... ... @@ -2536,6 +2544,10 @@
2536 2544 /* Had to read the page from swap area: Major fault */
2537 2545 ret = VM_FAULT_MAJOR;
2538 2546 count_vm_event(PGMAJFAULT);
  2547 + } else if (PageHWPoison(page)) {
  2548 + ret = VM_FAULT_HWPOISON;
  2549 + delayacct_clear_flag(DELAYACCT_PF_SWAPIN);
  2550 + goto out;
2539 2551 }
2540 2552  
2541 2553 lock_page(page);