1f08c3bdfSopenharmony_ci/* 2f08c3bdfSopenharmony_ci * ttranshuge.c: hwpoison test for THP(Transparent Huge Page). 3f08c3bdfSopenharmony_ci * 4f08c3bdfSopenharmony_ci * Copyright (C) 2011, FUJITSU LIMITED. 5f08c3bdfSopenharmony_ci * Author: Jin Dongming <jin.dongming@css.cn.fujitsu.com> 6f08c3bdfSopenharmony_ci * 7f08c3bdfSopenharmony_ci * This program is released under the GPLv2. 8f08c3bdfSopenharmony_ci * 9f08c3bdfSopenharmony_ci * This program is based on tinject.c and thugetlb.c in tsrc/ directory 10f08c3bdfSopenharmony_ci * in mcetest tool. 11f08c3bdfSopenharmony_ci */ 12f08c3bdfSopenharmony_ci 13f08c3bdfSopenharmony_ci/* 14f08c3bdfSopenharmony_ci * Even if THP is supported by Kernel, it could not be sure all the pages 15f08c3bdfSopenharmony_ci * you gotten belong to THP. 16f08c3bdfSopenharmony_ci * 17f08c3bdfSopenharmony_ci * Following is the structure of the memory mapped by mmap() 18f08c3bdfSopenharmony_ci * when the requested memory size is 8M and the THP's size is 2M, 19f08c3bdfSopenharmony_ci * O: means page belongs to 4k page; 20f08c3bdfSopenharmony_ci * T: means page belongs to THP. 21f08c3bdfSopenharmony_ci * Base ..... (Base + Size) 22f08c3bdfSopenharmony_ci * Size : 0M . . . . . 2M . . . . . 4M . . . . . 6M . . . . . 8M 23f08c3bdfSopenharmony_ci * case0: OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO 24f08c3bdfSopenharmony_ci * No THP. 25f08c3bdfSopenharmony_ci * case1: OOOOOOOTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTOOOOOO 26f08c3bdfSopenharmony_ci * Mixed with THP where it is possible. 27f08c3bdfSopenharmony_ci * case2: OOOOOOOOOOOOOOOOOOOOOOOOOOTTTTTTTTTTTTTTTTTTTTTTTTTT 28f08c3bdfSopenharmony_ci * Mixed with THP only some part of where it is possible. 29f08c3bdfSopenharmony_ci * case3: TTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTT 30f08c3bdfSopenharmony_ci * All pages are belong to THP. 31f08c3bdfSopenharmony_ci * 32f08c3bdfSopenharmony_ci * So the function find_thp_addr() could not be sure the calculated 33f08c3bdfSopenharmony_ci * address is the address of THP. And in the above structure, 34f08c3bdfSopenharmony_ci * the right address of THP could not be gotten in case 0 and 2 and 35f08c3bdfSopenharmony_ci * could be gotten in case 1 and 3 only. 36f08c3bdfSopenharmony_ci * 37f08c3bdfSopenharmony_ci * According to my experience, the most case gotten by APL is case 1. 38f08c3bdfSopenharmony_ci * So this program is made based on the case 1. 39f08c3bdfSopenharmony_ci * 40f08c3bdfSopenharmony_ci * To improve the rate of THP mapped by mmap(), it is better to do 41f08c3bdfSopenharmony_ci * hwpoison test: 42f08c3bdfSopenharmony_ci * - After reboot immediately. 43f08c3bdfSopenharmony_ci * Because there is a lot of freed memory. 44f08c3bdfSopenharmony_ci * - In the system which has plenty of memory prepared. 45f08c3bdfSopenharmony_ci * This can avoid hwpoison test failure caused by not enough memory. 46f08c3bdfSopenharmony_ci */ 47f08c3bdfSopenharmony_ci 48f08c3bdfSopenharmony_ci#define _GNU_SOURCE 1 49f08c3bdfSopenharmony_ci#include <stdlib.h> 50f08c3bdfSopenharmony_ci#include <stdio.h> 51f08c3bdfSopenharmony_ci#include <string.h> 52f08c3bdfSopenharmony_ci 53f08c3bdfSopenharmony_ci#include <unistd.h> 54f08c3bdfSopenharmony_ci#include <getopt.h> 55f08c3bdfSopenharmony_ci#include <signal.h> 56f08c3bdfSopenharmony_ci 57f08c3bdfSopenharmony_ci#include <sys/prctl.h> 58f08c3bdfSopenharmony_ci#include <sys/mman.h> 59f08c3bdfSopenharmony_ci#include <sys/wait.h> 60f08c3bdfSopenharmony_ci 61f08c3bdfSopenharmony_ci/* 62f08c3bdfSopenharmony_ci * This file supposes the following as default. 63f08c3bdfSopenharmony_ci * Regular Page Size : 4K(4096Bytes) 64f08c3bdfSopenharmony_ci * THP's Size : 2M(2UL * 1024 *1024Bytes) 65f08c3bdfSopenharmony_ci * Poisoned Page Size : 4K(4096Bytes) 66f08c3bdfSopenharmony_ci */ 67f08c3bdfSopenharmony_ci#define DEFAULT_PS 4096UL 68f08c3bdfSopenharmony_ci#define PS_MASK(ps_size) ((unsigned long)(ps_size -1)) 69f08c3bdfSopenharmony_ci#define DEFAULT_THP_SIZE 0x200000UL 70f08c3bdfSopenharmony_ci#define THP_MASK(thp_size) ((unsigned long)(thp_size - 1)) 71f08c3bdfSopenharmony_ci 72f08c3bdfSopenharmony_ci#define REQ_MEM_SIZE (8UL * 1024 * 1024) 73f08c3bdfSopenharmony_ci 74f08c3bdfSopenharmony_ci#define MADV_POISON 100 75f08c3bdfSopenharmony_ci#define MADV_HUGEPAGE 14 76f08c3bdfSopenharmony_ci 77f08c3bdfSopenharmony_ci#define PR_MCE_KILL 33 78f08c3bdfSopenharmony_ci#define PR_MCE_KILL_SET 1 79f08c3bdfSopenharmony_ci#define PR_MCE_KILL_EARLY 1 80f08c3bdfSopenharmony_ci#define PR_MCE_KILL_LATE 0 81f08c3bdfSopenharmony_ci 82f08c3bdfSopenharmony_ci#define THP_SUCCESS 0 83f08c3bdfSopenharmony_ci#define THP_FAILURE -1 84f08c3bdfSopenharmony_ci 85f08c3bdfSopenharmony_ci#define print_err(fmt, ...) printf("[ERROR] "fmt, ##__VA_ARGS__) 86f08c3bdfSopenharmony_ci#define print_success(fmt, ...) printf("[SUCCESS] "fmt, ##__VA_ARGS__) 87f08c3bdfSopenharmony_ci#define print_failure(fmt, ...) printf("[FAILURE] "fmt, ##__VA_ARGS__) 88f08c3bdfSopenharmony_ci 89f08c3bdfSopenharmony_cistatic char *corrupt_page_addr; 90f08c3bdfSopenharmony_cistatic char *mem_addr; 91f08c3bdfSopenharmony_ci 92f08c3bdfSopenharmony_cistatic unsigned int early_kill = 0; 93f08c3bdfSopenharmony_cistatic unsigned int avoid_touch = 0; 94f08c3bdfSopenharmony_ci 95f08c3bdfSopenharmony_cistatic int corrupt_page = -1; 96f08c3bdfSopenharmony_ci 97f08c3bdfSopenharmony_cistatic unsigned long thp_addr = 0; 98f08c3bdfSopenharmony_ci 99f08c3bdfSopenharmony_cistatic void print_prep_info(void) 100f08c3bdfSopenharmony_ci{ 101f08c3bdfSopenharmony_ci printf("\n%s Poison Test of THP.\n\n" 102f08c3bdfSopenharmony_ci "Information:\n" 103f08c3bdfSopenharmony_ci " PID %d\n" 104f08c3bdfSopenharmony_ci " PS(page size) 0x%lx\n" 105f08c3bdfSopenharmony_ci " mmap()'ed Memory Address %p; size 0x%lx\n" 106f08c3bdfSopenharmony_ci " THP(Transparent Huge Page) Address 0x%lx; size 0x%lx\n" 107f08c3bdfSopenharmony_ci " %s Page Poison Test At %p\n\n", 108f08c3bdfSopenharmony_ci 109f08c3bdfSopenharmony_ci early_kill ? "Early Kill" : "Late Kill", 110f08c3bdfSopenharmony_ci getpid(), 111f08c3bdfSopenharmony_ci DEFAULT_PS, 112f08c3bdfSopenharmony_ci mem_addr, REQ_MEM_SIZE, 113f08c3bdfSopenharmony_ci thp_addr, DEFAULT_THP_SIZE, 114f08c3bdfSopenharmony_ci (corrupt_page == 0) ? "Head" : "Tail", corrupt_page_addr 115f08c3bdfSopenharmony_ci ); 116f08c3bdfSopenharmony_ci} 117f08c3bdfSopenharmony_ci 118f08c3bdfSopenharmony_ci/* 119f08c3bdfSopenharmony_ci * Usage: 120f08c3bdfSopenharmony_ci * If avoid_flag == 1, 121f08c3bdfSopenharmony_ci * access all the memory except one DEFAULT_PS size memory 122f08c3bdfSopenharmony_ci * after the address in global variable corrupt_page_addr; 123f08c3bdfSopenharmony_ci * else 124f08c3bdfSopenharmony_ci * access all the memory from addr to (addr + size). 125f08c3bdfSopenharmony_ci */ 126f08c3bdfSopenharmony_cistatic int read_mem(char *addr, unsigned long size, int avoid_flag) 127f08c3bdfSopenharmony_ci{ 128f08c3bdfSopenharmony_ci int ret = 0; 129f08c3bdfSopenharmony_ci unsigned long i = 0; 130f08c3bdfSopenharmony_ci 131f08c3bdfSopenharmony_ci for (i = 0; i < size; i++) { 132f08c3bdfSopenharmony_ci if ((avoid_flag) && 133f08c3bdfSopenharmony_ci ((addr + i) >= corrupt_page_addr) && 134f08c3bdfSopenharmony_ci ((addr + i) < (corrupt_page_addr + DEFAULT_PS))) 135f08c3bdfSopenharmony_ci continue; 136f08c3bdfSopenharmony_ci 137f08c3bdfSopenharmony_ci if (*(addr + i) != (char)('a' + (i % 26))) { 138f08c3bdfSopenharmony_ci print_err("Mismatch at 0x%lx.\n", 139f08c3bdfSopenharmony_ci (unsigned long)(addr + i)); 140f08c3bdfSopenharmony_ci ret = -1; 141f08c3bdfSopenharmony_ci break; 142f08c3bdfSopenharmony_ci } 143f08c3bdfSopenharmony_ci } 144f08c3bdfSopenharmony_ci 145f08c3bdfSopenharmony_ci return ret; 146f08c3bdfSopenharmony_ci} 147f08c3bdfSopenharmony_ci 148f08c3bdfSopenharmony_cistatic void write_mem(char *addr, unsigned long size) 149f08c3bdfSopenharmony_ci{ 150f08c3bdfSopenharmony_ci int i = 0; 151f08c3bdfSopenharmony_ci 152f08c3bdfSopenharmony_ci for (i = 0; i < size; i++) { 153f08c3bdfSopenharmony_ci *(addr + i) = (char)('a' + (i % 26)); 154f08c3bdfSopenharmony_ci } 155f08c3bdfSopenharmony_ci} 156f08c3bdfSopenharmony_ci 157f08c3bdfSopenharmony_ci/* 158f08c3bdfSopenharmony_ci * Usage: 159f08c3bdfSopenharmony_ci * Use MADV_HUGEPAGE to make sure the page could be mapped as THP 160f08c3bdfSopenharmony_ci * when /sys/kernel/mm/transparent_hugepage/enabled is set with 161f08c3bdfSopenharmony_ci * madvise. 162f08c3bdfSopenharmony_ci * 163f08c3bdfSopenharmony_ci * Note: 164f08c3bdfSopenharmony_ci * MADV_HUGEPAGE must be set between mmap and read/write operation. 165f08c3bdfSopenharmony_ci * And it must follow mmap(). Please refer to patches of 166f08c3bdfSopenharmony_ci * MADV_HUGEPAGE about THP for more details. 167f08c3bdfSopenharmony_ci * 168f08c3bdfSopenharmony_ci * Patch Information: 169f08c3bdfSopenharmony_ci * Title: thp: khugepaged: make khugepaged aware about madvise 170f08c3bdfSopenharmony_ci * commit 60ab3244ec85c44276c585a2a20d3750402e1cf4 171f08c3bdfSopenharmony_ci */ 172f08c3bdfSopenharmony_cistatic int request_thp_with_madvise(unsigned long start) 173f08c3bdfSopenharmony_ci{ 174f08c3bdfSopenharmony_ci unsigned long madvise_addr = start & ~PS_MASK(DEFAULT_PS); 175f08c3bdfSopenharmony_ci unsigned long madvise_size = REQ_MEM_SIZE - (start % DEFAULT_PS); 176f08c3bdfSopenharmony_ci 177f08c3bdfSopenharmony_ci return madvise((void *)madvise_addr, madvise_size, MADV_HUGEPAGE); 178f08c3bdfSopenharmony_ci} 179f08c3bdfSopenharmony_ci 180f08c3bdfSopenharmony_ci/* 181f08c3bdfSopenharmony_ci * Usage: 182f08c3bdfSopenharmony_ci * This function is used for getting the address of first THP. 183f08c3bdfSopenharmony_ci * 184f08c3bdfSopenharmony_ci * Note: 185f08c3bdfSopenharmony_ci * This function could not make sure the address is the address of THP 186f08c3bdfSopenharmony_ci * really. Please refer to the explanation of mmap() of THP 187f08c3bdfSopenharmony_ci * at the head of this file. 188f08c3bdfSopenharmony_ci */ 189f08c3bdfSopenharmony_cistatic unsigned long find_thp_addr(unsigned long start, unsigned long size) 190f08c3bdfSopenharmony_ci{ 191f08c3bdfSopenharmony_ci unsigned long thp_align_addr = (start + (DEFAULT_THP_SIZE - 1)) & 192f08c3bdfSopenharmony_ci ~THP_MASK(DEFAULT_THP_SIZE); 193f08c3bdfSopenharmony_ci 194f08c3bdfSopenharmony_ci if ((thp_align_addr >= start) && 195f08c3bdfSopenharmony_ci ((thp_align_addr + DEFAULT_THP_SIZE) < (start + size))) 196f08c3bdfSopenharmony_ci return thp_align_addr; 197f08c3bdfSopenharmony_ci 198f08c3bdfSopenharmony_ci return 0; 199f08c3bdfSopenharmony_ci} 200f08c3bdfSopenharmony_ci 201f08c3bdfSopenharmony_cistatic int prep_memory_map(void) 202f08c3bdfSopenharmony_ci{ 203f08c3bdfSopenharmony_ci mem_addr = (char *)mmap(NULL, REQ_MEM_SIZE, PROT_WRITE | PROT_READ, 204f08c3bdfSopenharmony_ci MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); 205f08c3bdfSopenharmony_ci if (mem_addr == NULL) { 206f08c3bdfSopenharmony_ci print_err("Failed to mmap requested memory: size 0x%lx.\n", 207f08c3bdfSopenharmony_ci REQ_MEM_SIZE); 208f08c3bdfSopenharmony_ci return THP_FAILURE; 209f08c3bdfSopenharmony_ci } 210f08c3bdfSopenharmony_ci 211f08c3bdfSopenharmony_ci return THP_SUCCESS; 212f08c3bdfSopenharmony_ci} 213f08c3bdfSopenharmony_ci 214f08c3bdfSopenharmony_cistatic int prep_injection(void) 215f08c3bdfSopenharmony_ci{ 216f08c3bdfSopenharmony_ci /* enabled(=madvise) in /sys/kernel/mm/transparent_hugepage/. */ 217f08c3bdfSopenharmony_ci if (request_thp_with_madvise((unsigned long)mem_addr) < 0) { 218f08c3bdfSopenharmony_ci print_err("Failed to request THP for [madvise] in enabled.\n"); 219f08c3bdfSopenharmony_ci return THP_FAILURE; 220f08c3bdfSopenharmony_ci } 221f08c3bdfSopenharmony_ci 222f08c3bdfSopenharmony_ci write_mem(mem_addr, REQ_MEM_SIZE); 223f08c3bdfSopenharmony_ci if (read_mem(mem_addr, REQ_MEM_SIZE, 0) < 0) { 224f08c3bdfSopenharmony_ci print_err("Data is Mismatched(prep_injection).\n"); 225f08c3bdfSopenharmony_ci return THP_FAILURE; 226f08c3bdfSopenharmony_ci } 227f08c3bdfSopenharmony_ci 228f08c3bdfSopenharmony_ci /* find the address of THP. */ 229f08c3bdfSopenharmony_ci thp_addr = find_thp_addr((unsigned long)mem_addr, REQ_MEM_SIZE); 230f08c3bdfSopenharmony_ci if (!thp_addr) { 231f08c3bdfSopenharmony_ci print_err("No THP mapped.\n"); 232f08c3bdfSopenharmony_ci return THP_FAILURE; 233f08c3bdfSopenharmony_ci } 234f08c3bdfSopenharmony_ci 235f08c3bdfSopenharmony_ci /* Calculate the address of the page which will be poisoned */ 236f08c3bdfSopenharmony_ci if (corrupt_page < 0) 237f08c3bdfSopenharmony_ci corrupt_page = 0; 238f08c3bdfSopenharmony_ci 239f08c3bdfSopenharmony_ci corrupt_page_addr = (char *)(thp_addr + corrupt_page * DEFAULT_PS); 240f08c3bdfSopenharmony_ci 241f08c3bdfSopenharmony_ci /* Process will be killed here by kernel(SIGBUS AO). */ 242f08c3bdfSopenharmony_ci prctl(PR_MCE_KILL, PR_MCE_KILL_SET, 243f08c3bdfSopenharmony_ci early_kill ? PR_MCE_KILL_EARLY : PR_MCE_KILL_LATE, 244f08c3bdfSopenharmony_ci NULL, NULL); 245f08c3bdfSopenharmony_ci 246f08c3bdfSopenharmony_ci return THP_SUCCESS; 247f08c3bdfSopenharmony_ci} 248f08c3bdfSopenharmony_ci 249f08c3bdfSopenharmony_cistatic int do_injection(void) 250f08c3bdfSopenharmony_ci{ 251f08c3bdfSopenharmony_ci /* Early Kill */ 252f08c3bdfSopenharmony_ci if (madvise((void *)corrupt_page_addr, DEFAULT_PS, MADV_POISON) != 0) { 253f08c3bdfSopenharmony_ci print_err("Failed to poison at 0x%p.\n", corrupt_page_addr); 254f08c3bdfSopenharmony_ci printf("[INFO] Please check the authority of current user.\n"); 255f08c3bdfSopenharmony_ci return THP_FAILURE; 256f08c3bdfSopenharmony_ci } 257f08c3bdfSopenharmony_ci 258f08c3bdfSopenharmony_ci return THP_SUCCESS; 259f08c3bdfSopenharmony_ci} 260f08c3bdfSopenharmony_ci 261f08c3bdfSopenharmony_cistatic int post_injection(void) 262f08c3bdfSopenharmony_ci{ 263f08c3bdfSopenharmony_ci 264f08c3bdfSopenharmony_ci if (early_kill) { 265f08c3bdfSopenharmony_ci print_err("Failed to be killed by SIGBUS(Action Optional).\n"); 266f08c3bdfSopenharmony_ci return THP_FAILURE; 267f08c3bdfSopenharmony_ci } 268f08c3bdfSopenharmony_ci 269f08c3bdfSopenharmony_ci /* Late Kill */ 270f08c3bdfSopenharmony_ci if (read_mem(mem_addr, REQ_MEM_SIZE, avoid_touch) < 0) { 271f08c3bdfSopenharmony_ci print_err("Data is Mismatched(do_injection).\n"); 272f08c3bdfSopenharmony_ci return THP_FAILURE; 273f08c3bdfSopenharmony_ci } 274f08c3bdfSopenharmony_ci 275f08c3bdfSopenharmony_ci if (!avoid_touch) { 276f08c3bdfSopenharmony_ci print_err("Failed to be killed by SIGBUS(Action Required).\n"); 277f08c3bdfSopenharmony_ci return THP_FAILURE; 278f08c3bdfSopenharmony_ci } 279f08c3bdfSopenharmony_ci 280f08c3bdfSopenharmony_ci return THP_SUCCESS; 281f08c3bdfSopenharmony_ci} 282f08c3bdfSopenharmony_ci 283f08c3bdfSopenharmony_cistatic void post_memory_map() 284f08c3bdfSopenharmony_ci{ 285f08c3bdfSopenharmony_ci munmap(mem_addr, REQ_MEM_SIZE); 286f08c3bdfSopenharmony_ci} 287f08c3bdfSopenharmony_ci 288f08c3bdfSopenharmony_cistatic void usage(char *program) 289f08c3bdfSopenharmony_ci{ 290f08c3bdfSopenharmony_ci printf("%s [-o offset] [-ea]\n" 291f08c3bdfSopenharmony_ci" Usage:\n" 292f08c3bdfSopenharmony_ci" -o|--offset offset(page unit) Position of error injection from the first THP.\n" 293f08c3bdfSopenharmony_ci" -e|--early-kill Set PR_MCE_KILL_EARLY(default NOT early-kill).\n" 294f08c3bdfSopenharmony_ci" -a|--avoid-touch Avoid touching error page(page unit) and\n" 295f08c3bdfSopenharmony_ci" only used when early-kill is not set.\n" 296f08c3bdfSopenharmony_ci" -h|--help\n\n" 297f08c3bdfSopenharmony_ci" Examples:\n" 298f08c3bdfSopenharmony_ci" 1. Inject the 2nd page(4k) of THP and early killed.\n" 299f08c3bdfSopenharmony_ci" %s -o 1 -e\n\n" 300f08c3bdfSopenharmony_ci" 2. Inject the 4th page(4k) of THP, late killed and untouched.\n" 301f08c3bdfSopenharmony_ci" %s --offset 3 --avoid-touch\n\n" 302f08c3bdfSopenharmony_ci" Note:\n" 303f08c3bdfSopenharmony_ci" Options Default set\n" 304f08c3bdfSopenharmony_ci" early-kill no\n" 305f08c3bdfSopenharmony_ci" offset 0(head page)\n" 306f08c3bdfSopenharmony_ci" avoid-touch no\n\n" 307f08c3bdfSopenharmony_ci , program, program, program); 308f08c3bdfSopenharmony_ci} 309f08c3bdfSopenharmony_ci 310f08c3bdfSopenharmony_cistatic struct option opts[] = { 311f08c3bdfSopenharmony_ci { "offset" , 1, NULL, 'o' }, 312f08c3bdfSopenharmony_ci { "avoid-touch" , 0, NULL, 'a' }, 313f08c3bdfSopenharmony_ci { "early-kill" , 0, NULL, 'e' }, 314f08c3bdfSopenharmony_ci { "help" , 0, NULL, 'h' }, 315f08c3bdfSopenharmony_ci { NULL , 0, NULL, 0 } 316f08c3bdfSopenharmony_ci}; 317f08c3bdfSopenharmony_ci 318f08c3bdfSopenharmony_cistatic void get_options_or_die(int argc, char *argv[]) 319f08c3bdfSopenharmony_ci{ 320f08c3bdfSopenharmony_ci char c; 321f08c3bdfSopenharmony_ci 322f08c3bdfSopenharmony_ci while ((c = getopt_long(argc, argv, "o:aeh", opts, NULL)) != -1) { 323f08c3bdfSopenharmony_ci switch (c) { 324f08c3bdfSopenharmony_ci case 'o': 325f08c3bdfSopenharmony_ci corrupt_page = strtol(optarg, NULL, 10); 326f08c3bdfSopenharmony_ci break; 327f08c3bdfSopenharmony_ci case 'a': 328f08c3bdfSopenharmony_ci avoid_touch = 1; 329f08c3bdfSopenharmony_ci break; 330f08c3bdfSopenharmony_ci case 'e': 331f08c3bdfSopenharmony_ci early_kill = 1; 332f08c3bdfSopenharmony_ci break; 333f08c3bdfSopenharmony_ci case 'h': 334f08c3bdfSopenharmony_ci usage(argv[0]); 335f08c3bdfSopenharmony_ci exit(0); 336f08c3bdfSopenharmony_ci default: 337f08c3bdfSopenharmony_ci print_err("Wrong options, please check options!\n"); 338f08c3bdfSopenharmony_ci usage(argv[0]); 339f08c3bdfSopenharmony_ci exit(1); 340f08c3bdfSopenharmony_ci } 341f08c3bdfSopenharmony_ci } 342f08c3bdfSopenharmony_ci 343f08c3bdfSopenharmony_ci if ((avoid_touch) && (corrupt_page == -1)) { 344f08c3bdfSopenharmony_ci print_err("Avoid which page?\n"); 345f08c3bdfSopenharmony_ci usage(argv[0]); 346f08c3bdfSopenharmony_ci exit(1); 347f08c3bdfSopenharmony_ci } 348f08c3bdfSopenharmony_ci} 349f08c3bdfSopenharmony_ci 350f08c3bdfSopenharmony_ciint main(int argc, char *argv[]) 351f08c3bdfSopenharmony_ci{ 352f08c3bdfSopenharmony_ci int ret = THP_FAILURE; 353f08c3bdfSopenharmony_ci pid_t child; 354f08c3bdfSopenharmony_ci siginfo_t sig; 355f08c3bdfSopenharmony_ci 356f08c3bdfSopenharmony_ci /* 357f08c3bdfSopenharmony_ci * 1. Options check. 358f08c3bdfSopenharmony_ci */ 359f08c3bdfSopenharmony_ci get_options_or_die(argc, argv); 360f08c3bdfSopenharmony_ci 361f08c3bdfSopenharmony_ci /* Fork a child process for test */ 362f08c3bdfSopenharmony_ci child = fork(); 363f08c3bdfSopenharmony_ci if (child < 0) { 364f08c3bdfSopenharmony_ci print_err("Failed to fork child process.\n"); 365f08c3bdfSopenharmony_ci return THP_FAILURE; 366f08c3bdfSopenharmony_ci } 367f08c3bdfSopenharmony_ci 368f08c3bdfSopenharmony_ci if (child == 0) { 369f08c3bdfSopenharmony_ci /* Child process */ 370f08c3bdfSopenharmony_ci 371f08c3bdfSopenharmony_ci int ret = THP_FAILURE; 372f08c3bdfSopenharmony_ci 373f08c3bdfSopenharmony_ci signal(SIGBUS, SIG_DFL); 374f08c3bdfSopenharmony_ci 375f08c3bdfSopenharmony_ci /* 376f08c3bdfSopenharmony_ci * 2. Groundwork for hwpoison injection. 377f08c3bdfSopenharmony_ci */ 378f08c3bdfSopenharmony_ci if (prep_memory_map() == THP_FAILURE) 379f08c3bdfSopenharmony_ci _exit(1); 380f08c3bdfSopenharmony_ci 381f08c3bdfSopenharmony_ci if (prep_injection() == THP_FAILURE) 382f08c3bdfSopenharmony_ci goto free_mem; 383f08c3bdfSopenharmony_ci 384f08c3bdfSopenharmony_ci /* Print the prepared information before hwpoison injection. */ 385f08c3bdfSopenharmony_ci print_prep_info(); 386f08c3bdfSopenharmony_ci 387f08c3bdfSopenharmony_ci /* 388f08c3bdfSopenharmony_ci * 3. Hwpoison Injection. 389f08c3bdfSopenharmony_ci */ 390f08c3bdfSopenharmony_ci if (do_injection() == THP_FAILURE) 391f08c3bdfSopenharmony_ci goto free_mem; 392f08c3bdfSopenharmony_ci 393f08c3bdfSopenharmony_ci if (post_injection() == THP_FAILURE) 394f08c3bdfSopenharmony_ci goto free_mem; 395f08c3bdfSopenharmony_ci 396f08c3bdfSopenharmony_ci ret = THP_SUCCESS; 397f08c3bdfSopenharmony_cifree_mem: 398f08c3bdfSopenharmony_ci post_memory_map(); 399f08c3bdfSopenharmony_ci 400f08c3bdfSopenharmony_ci if (ret == THP_SUCCESS) 401f08c3bdfSopenharmony_ci _exit(0); 402f08c3bdfSopenharmony_ci 403f08c3bdfSopenharmony_ci _exit(1); 404f08c3bdfSopenharmony_ci } 405f08c3bdfSopenharmony_ci 406f08c3bdfSopenharmony_ci /* Parent process */ 407f08c3bdfSopenharmony_ci 408f08c3bdfSopenharmony_ci if (waitid(P_PID, child, &sig, WEXITED) < 0) { 409f08c3bdfSopenharmony_ci print_err("Failed to wait child process.\n"); 410f08c3bdfSopenharmony_ci return THP_FAILURE; 411f08c3bdfSopenharmony_ci } 412f08c3bdfSopenharmony_ci 413f08c3bdfSopenharmony_ci /* 414f08c3bdfSopenharmony_ci * 4. Check the result of hwpoison injection. 415f08c3bdfSopenharmony_ci */ 416f08c3bdfSopenharmony_ci if (avoid_touch) { 417f08c3bdfSopenharmony_ci if (sig.si_code == CLD_EXITED && sig.si_status == 0) { 418f08c3bdfSopenharmony_ci print_success("Child process survived.\n"); 419f08c3bdfSopenharmony_ci ret = THP_SUCCESS; 420f08c3bdfSopenharmony_ci } else 421f08c3bdfSopenharmony_ci print_failure("Child process could not survive.\n"); 422f08c3bdfSopenharmony_ci } else { 423f08c3bdfSopenharmony_ci if (sig.si_code == CLD_KILLED && sig.si_status == SIGBUS) { 424f08c3bdfSopenharmony_ci print_success("Child process was killed by SIGBUS.\n"); 425f08c3bdfSopenharmony_ci ret = THP_SUCCESS; 426f08c3bdfSopenharmony_ci } else 427f08c3bdfSopenharmony_ci print_failure("Child process could not be killed" 428f08c3bdfSopenharmony_ci " by SIGBUS.\n"); 429f08c3bdfSopenharmony_ci } 430f08c3bdfSopenharmony_ci 431f08c3bdfSopenharmony_ci return ret; 432f08c3bdfSopenharmony_ci} 433