| // SPDX-License-Identifier: GPL-2.0 |
| |
| /* |
| * Copyright (C) 2022 Intel Corporation |
| * Author: Tony Luck |
| * |
| * This software may be redistributed and/or modified under the terms of |
| * the GNU General Public License ("GPL") version 2 only as published by the |
| * Free Software Foundation. |
| */ |
| |
| /* |
| * Allocate memory - loop using EINJ to inject a soft error, |
| * consuming after each until the page is taken offline. |
| */ |
| #include <sys/mman.h> |
| #include "einj.h" |
| |
| char *progname; |
| long pagesize; |
| int Sflag; |
| |
| volatile int trigger; |
| |
| extern unsigned long long vtop(unsigned long long addr, pid_t pid); |
| |
| #define MAX_TRIES 30 |
| |
| int main(int argc, char **argv) |
| { |
| char *addr = mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_SHARED|MAP_ANONYMOUS, -1, 0); |
| unsigned long long paddr; |
| int tries = MAX_TRIES; |
| int i; |
| pid_t pid; |
| |
| progname = argv[0]; |
| |
| if (argc == 2) |
| tries = atoi(argv[1]); |
| |
| if (addr == MAP_FAILED) { |
| perror("mmap"); |
| return 1; |
| } |
| pid = getpid(); |
| |
| wfile(EINJ_ETYPE, 0x8); |
| wfile(EINJ_MASK, ~0x0ul); |
| wfile(EINJ_NOTRIGGER, 1); |
| |
| *addr = '*'; |
| paddr = vtop((unsigned long long)addr, pid); |
| |
| for (i = 0; i < tries; i++) { |
| printf("%d: Inject to vaddr=%p paddr=0x%llx\n", i, addr, paddr); |
| wfile(EINJ_ADDR, paddr); |
| wfile(EINJ_DOIT, 1); |
| usleep(250); |
| trigger += *addr; |
| sleep(2); |
| if (paddr != vtop((unsigned long long)addr, pid)) |
| break; |
| } |
| |
| if (i == tries) { |
| fprintf(stderr, "FAIL: Page was not offline after %d errors\n", i); |
| return 1; |
| } |
| |
| printf("PASS: page taken offline after %d corrected errors\n", i + 1); |
| return 0; |
| } |