diff options
| -rw-r--r-- | Documentation/vm/page-types.c | 73 |
1 files changed, 72 insertions, 1 deletions
diff --git a/Documentation/vm/page-types.c b/Documentation/vm/page-types.c index 11b9a03f7b10..3ec4f2a22585 100644 --- a/Documentation/vm/page-types.c +++ b/Documentation/vm/page-types.c | |||
| @@ -170,6 +170,13 @@ static int page_size; | |||
| 170 | static int pagemap_fd; | 170 | static int pagemap_fd; |
| 171 | static int kpageflags_fd; | 171 | static int kpageflags_fd; |
| 172 | 172 | ||
| 173 | static int opt_hwpoison; | ||
| 174 | static int opt_unpoison; | ||
| 175 | |||
| 176 | static char *hwpoison_debug_fs = "/debug/hwpoison"; | ||
| 177 | static int hwpoison_inject_fd; | ||
| 178 | static int hwpoison_forget_fd; | ||
| 179 | |||
| 173 | #define HASH_SHIFT 13 | 180 | #define HASH_SHIFT 13 |
| 174 | #define HASH_SIZE (1 << HASH_SHIFT) | 181 | #define HASH_SIZE (1 << HASH_SHIFT) |
| 175 | #define HASH_MASK (HASH_SIZE - 1) | 182 | #define HASH_MASK (HASH_SIZE - 1) |
| @@ -447,6 +454,53 @@ static uint64_t kpageflags_flags(uint64_t flags) | |||
| 447 | } | 454 | } |
| 448 | 455 | ||
| 449 | /* | 456 | /* |
| 457 | * page actions | ||
| 458 | */ | ||
| 459 | |||
| 460 | static void prepare_hwpoison_fd(void) | ||
| 461 | { | ||
| 462 | char buf[100]; | ||
| 463 | |||
| 464 | if (opt_hwpoison && !hwpoison_inject_fd) { | ||
| 465 | sprintf(buf, "%s/corrupt-pfn", hwpoison_debug_fs); | ||
| 466 | hwpoison_inject_fd = checked_open(buf, O_WRONLY); | ||
| 467 | } | ||
| 468 | |||
| 469 | if (opt_unpoison && !hwpoison_forget_fd) { | ||
| 470 | sprintf(buf, "%s/renew-pfn", hwpoison_debug_fs); | ||
| 471 | hwpoison_forget_fd = checked_open(buf, O_WRONLY); | ||
| 472 | } | ||
| 473 | } | ||
| 474 | |||
| 475 | static int hwpoison_page(unsigned long offset) | ||
| 476 | { | ||
| 477 | char buf[100]; | ||
| 478 | int len; | ||
| 479 | |||
| 480 | len = sprintf(buf, "0x%lx\n", offset); | ||
| 481 | len = write(hwpoison_inject_fd, buf, len); | ||
| 482 | if (len < 0) { | ||
| 483 | perror("hwpoison inject"); | ||
| 484 | return len; | ||
| 485 | } | ||
| 486 | return 0; | ||
| 487 | } | ||
| 488 | |||
| 489 | static int unpoison_page(unsigned long offset) | ||
| 490 | { | ||
| 491 | char buf[100]; | ||
| 492 | int len; | ||
| 493 | |||
| 494 | len = sprintf(buf, "0x%lx\n", offset); | ||
| 495 | len = write(hwpoison_forget_fd, buf, len); | ||
| 496 | if (len < 0) { | ||
| 497 | perror("hwpoison forget"); | ||
| 498 | return len; | ||
| 499 | } | ||
| 500 | return 0; | ||
| 501 | } | ||
| 502 | |||
| 503 | /* | ||
| 450 | * page frame walker | 504 | * page frame walker |
| 451 | */ | 505 | */ |
| 452 | 506 | ||
| @@ -485,6 +539,11 @@ static void add_page(unsigned long voffset, | |||
| 485 | if (!bit_mask_ok(flags)) | 539 | if (!bit_mask_ok(flags)) |
| 486 | return; | 540 | return; |
| 487 | 541 | ||
| 542 | if (opt_hwpoison) | ||
| 543 | hwpoison_page(offset); | ||
| 544 | if (opt_unpoison) | ||
| 545 | unpoison_page(offset); | ||
| 546 | |||
| 488 | if (opt_list == 1) | 547 | if (opt_list == 1) |
| 489 | show_page_range(voffset, offset, flags); | 548 | show_page_range(voffset, offset, flags); |
| 490 | else if (opt_list == 2) | 549 | else if (opt_list == 2) |
| @@ -624,6 +683,8 @@ static void usage(void) | |||
| 624 | " -l|--list Show page details in ranges\n" | 683 | " -l|--list Show page details in ranges\n" |
| 625 | " -L|--list-each Show page details one by one\n" | 684 | " -L|--list-each Show page details one by one\n" |
| 626 | " -N|--no-summary Don't show summay info\n" | 685 | " -N|--no-summary Don't show summay info\n" |
| 686 | " -X|--hwpoison hwpoison pages\n" | ||
| 687 | " -x|--unpoison unpoison pages\n" | ||
| 627 | " -h|--help Show this usage message\n" | 688 | " -h|--help Show this usage message\n" |
| 628 | "addr-spec:\n" | 689 | "addr-spec:\n" |
| 629 | " N one page at offset N (unit: pages)\n" | 690 | " N one page at offset N (unit: pages)\n" |
| @@ -833,6 +894,8 @@ static struct option opts[] = { | |||
| 833 | { "list" , 0, NULL, 'l' }, | 894 | { "list" , 0, NULL, 'l' }, |
| 834 | { "list-each" , 0, NULL, 'L' }, | 895 | { "list-each" , 0, NULL, 'L' }, |
| 835 | { "no-summary", 0, NULL, 'N' }, | 896 | { "no-summary", 0, NULL, 'N' }, |
| 897 | { "hwpoison" , 0, NULL, 'X' }, | ||
| 898 | { "unpoison" , 0, NULL, 'x' }, | ||
| 836 | { "help" , 0, NULL, 'h' }, | 899 | { "help" , 0, NULL, 'h' }, |
| 837 | { NULL , 0, NULL, 0 } | 900 | { NULL , 0, NULL, 0 } |
| 838 | }; | 901 | }; |
| @@ -844,7 +907,7 @@ int main(int argc, char *argv[]) | |||
| 844 | page_size = getpagesize(); | 907 | page_size = getpagesize(); |
| 845 | 908 | ||
| 846 | while ((c = getopt_long(argc, argv, | 909 | while ((c = getopt_long(argc, argv, |
| 847 | "rp:f:a:b:lLNh", opts, NULL)) != -1) { | 910 | "rp:f:a:b:lLNXxh", opts, NULL)) != -1) { |
| 848 | switch (c) { | 911 | switch (c) { |
| 849 | case 'r': | 912 | case 'r': |
| 850 | opt_raw = 1; | 913 | opt_raw = 1; |
| @@ -870,6 +933,14 @@ int main(int argc, char *argv[]) | |||
| 870 | case 'N': | 933 | case 'N': |
| 871 | opt_no_summary = 1; | 934 | opt_no_summary = 1; |
| 872 | break; | 935 | break; |
| 936 | case 'X': | ||
| 937 | opt_hwpoison = 1; | ||
| 938 | prepare_hwpoison_fd(); | ||
| 939 | break; | ||
| 940 | case 'x': | ||
| 941 | opt_unpoison = 1; | ||
| 942 | prepare_hwpoison_fd(); | ||
| 943 | break; | ||
| 873 | case 'h': | 944 | case 'h': |
| 874 | usage(); | 945 | usage(); |
| 875 | exit(0); | 946 | exit(0); |
