diff options
author | Wen Jin <wenx.jin@intel.com> | 2016-03-22 15:11:52 +0800 |
---|---|---|
committer | Andi Kleen <ak@linux.intel.com> | 2016-04-11 15:32:38 -0700 |
commit | 42399a06a50b3de82c453f527ba8807b7f86f036 (patch) | |
tree | 9c2213850f38bd0bbdd47594e80ad4ae38d10ab3 | |
parent | f058829ed8a17a2d8f51d435d3f32afcd2704699 (diff) | |
download | mce-test-42399a06a50b3de82c453f527ba8807b7f86f036.tar.gz |
Merge pfa.c into victim.c
1. Merge pfa.c into victim.c because some functions such as
vtop is duplicated
2. run mcelog as daemon to get mcelog information background.
3. rewrite some codes in victim.c
Signed-off-by: Wen Jin <wenx.jin@intel.com>
Signed-off-by: Chen, Gong <gong.chen@linux.intel.com>
Signed-off-by: Andi Kleen <ak@linux.intel.com>
-rw-r--r-- | cases/function/pfa/Makefile | 5 | ||||
-rw-r--r-- | cases/function/pfa/pfa.c | 118 | ||||
-rwxr-xr-x | cases/function/pfa/run_pfa.sh | 34 | ||||
-rwxr-xr-x | cases/function/pfa/runtest.sh | 3 | ||||
-rw-r--r-- | tools/victim/victim.c | 184 |
5 files changed, 140 insertions, 204 deletions
diff --git a/cases/function/pfa/Makefile b/cases/function/pfa/Makefile index 4bcbf48..1ac3831 100644 --- a/cases/function/pfa/Makefile +++ b/cases/function/pfa/Makefile @@ -3,11 +3,10 @@ # but this hides MAP_ANONYMOUS which comes back via _BSD_SOURCE CFLAGS := -g -Wall -D _BSD_SOURCE -D _XOPEN_SOURCE=500 -all: pfa busy -pfa: pfa.o +all: busy busy: busy.o install: all clean: - rm -f *.o pfa busy + rm -f *.o busy diff --git a/cases/function/pfa/pfa.c b/cases/function/pfa/pfa.c deleted file mode 100644 index a6df354..0000000 --- a/cases/function/pfa/pfa.c +++ /dev/null @@ -1,118 +0,0 @@ -/* - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the Free - * Software Foundation; version 2. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should find a copy of v2 of the GNU General Public License somewhere on - * your Linux system; if not, write to the Free Software Foundation, Inc., 59 - * Temple Place, Suite 330, Boston, MA 02111-1307 USA. - * - * Copyright (C) 2012 Intel corporation - */ - -#include <stdio.h> -#include <unistd.h> -#include <fcntl.h> -#include <sys/mman.h> - -/* - * Definition of /proc/pid/pagemap - * Bits 0-54 page frame number (PFN) if present - * Bits 0-4 swap type if swapped - * Bits 5-54 swap offset if swapped - * Bits 55-60 page shift (page size = 1<<page shift) - * Bit 61 reserved for future use - * Bit 62 page swapped - * Bit 63 page present - */ - -struct pagemaps { - unsigned long long pfn:55; - unsigned long long pgshift:6; - unsigned long long rsvd:1; - unsigned long long swapped:1; - unsigned long long present:1; -}; - -static int pagesize; - -/* - * get information about address from /proc/{pid}/pagemap - */ -unsigned long long vtop(unsigned long long addr) -{ - struct pagemaps pinfo; - unsigned int pinfo_size = sizeof pinfo; - long offset; - int fd, pgmask; - char pagemapname[64]; - - if (!pagesize) - pagesize = getpagesize(); - offset = addr / pagesize * pinfo_size; - sprintf(pagemapname, "/proc/%d/pagemap", getpid()); - fd = open(pagemapname, O_RDONLY); - if (fd == -1) { - perror(pagemapname); - return 0; - } - if (pread(fd, (void*)&pinfo, pinfo_size, offset) != pinfo_size) { - perror(pagemapname); - close(fd); - return 0; - } - close(fd); - if (!pinfo.present) - return ~0ull; - pgmask = (1 << pinfo.pgshift) - 1; - return (pinfo.pfn << pinfo.pgshift) | (addr & pgmask); -} - -int main() -{ - char *p; - long total, i; - unsigned long long phys, newphys; - - p = mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0); - if (p == MAP_FAILED) { - perror("mmap"); - return 1; - } - *p = '*'; /* make kernel allocate page */ - phys = vtop((unsigned long long)p); - - printf("allocated page: virtual = %p physical = 0x%llx\n", p, phys); - fflush(stdout); - - for (;;) { - for (i = 0; i < pagesize; i += sizeof(int)) { - total += *(int*)(p + i); - *(int*)(p + i) = total; - } - - newphys = vtop((unsigned long long)p); - if (phys == newphys) { - for (i = 0; i < pagesize; i += sizeof(int)) { - total += *(int*)(p + i); - *(int*)(p + i) = i; - } - sleep(2); - newphys = vtop((unsigned long long)p); - if (phys != newphys) { - printf("Page was replaced. New physical address = 0x%llx\n", newphys); - fflush(stdout); - phys = newphys; - } - } else { - printf("Page was replaced. New physical address = 0x%llx\n", newphys); - fflush(stdout); - phys = newphys; - } - } -} diff --git a/cases/function/pfa/run_pfa.sh b/cases/function/pfa/run_pfa.sh index d9bd11b..e1e9347 100755 --- a/cases/function/pfa/run_pfa.sh +++ b/cases/function/pfa/run_pfa.sh @@ -1,6 +1,10 @@ #!/bin/bash -. ../../../lib/mce.sh +export ROOT=`(cd ../../../; pwd)` + +. $ROOT/lib/functions.sh +setup_path +. $ROOT/lib/mce.sh INJ_TYPE=0x00000008 APEI_IF="" @@ -33,13 +37,6 @@ usage() main() { - if [ X"$1" = X -o X"$2" = X ] - then - usage - exit 0 - fi - - PFA_BIN=$1 check_debugfs APEI_IF=`cat /proc/mounts | grep debugfs | cut -d ' ' -f2 | head -1`/apei/einj @@ -70,19 +67,25 @@ main() fi rmmod $EDAC_TYPE >/dev/null 2>&1 - killall $PFA_BIN > /dev/null 2>&1 - $PFA_BIN | tee log & + #mcelog must be run in daemon mode. + cat /dev/null > /var/log/mcelog + kill -9 `pidof mcelog` >/dev/null 2>&1 + sleep 1 + mcelog --ignorenodev --daemon + + killall victim &> /dev/null + victim -p | tee log & #wait to flush stdout into log sleep 1 - addr=`cat log |cut -d' ' -f8|tail -1` + addr=`cat log | awk '{print $NF}' | tail -1` last_addr=$addr start=`date +%s` while : do echo inject address = $addr apei_inj $addr - sleep $2 - addr=`cat log |cut -d' ' -f8|tail -1` + sleep 2 + addr=`cat log | awk '{print $NF}' | tail -1` end=`date +%s` timeout=`expr $end - $start` if [ X"$last_addr" != X"$addr" ] @@ -97,9 +100,10 @@ main() cleanup() { - rm -f trigger log + rm -f log + killall victim &> /dev/null modprobe $EDAC_TYPE >/dev/null 2>&1 } trap "cleanup" 0 -main "$@" +main diff --git a/cases/function/pfa/runtest.sh b/cases/function/pfa/runtest.sh index 8213e58..9d9d8db 100755 --- a/cases/function/pfa/runtest.sh +++ b/cases/function/pfa/runtest.sh @@ -27,9 +27,8 @@ export TMP_DIR echo 0 > $TMP_DIR/error.$$ pushd `dirname $0` > /dev/null -./run_pfa.sh ./pfa 8 +./run_pfa.sh [ $? -eq 0 ] || echo 1 > $TMP_DIR/error.$$ -killall ./pfa popd > /dev/null grep -q "1" $TMP_DIR/error.$$ diff --git a/tools/victim/victim.c b/tools/victim/victim.c index ca70915..31f868a 100644 --- a/tools/victim/victim.c +++ b/tools/victim/victim.c @@ -32,7 +32,7 @@ * Bits 0-54 page frame number (PFN) if present * Bits 0-4 swap type if swapped * Bits 5-54 swap offset if swapped - * Bits 55-60 page shift (page size = 1<<page shift) + * Bits 55-60 page shift, the bits definition is legacy. * Bit 61 reserved for future use * Bit 62 page swapped * Bit 63 page present @@ -40,7 +40,7 @@ struct pagemaps { unsigned long long pfn:55; - unsigned long long pgshift:6; + unsigned long long pgshift:6; /*legacy*/ unsigned long long rsvd:1; unsigned long long swapped:1; unsigned long long present:1; @@ -97,6 +97,7 @@ static void usage(void) " -d|--data Inject data error(DCU error) under user context\n" " -i|--instruction Inject instruction error(IFU error) under user context\n" " -k|--kick 0/1 Kick off trigger. Auto(0), Manual(1, by default)\n" +" -p|--pfa help to test memory PFA(Predictive Failure Analysis) function\n" " -h|--help Show this usage message\n" ); } @@ -107,18 +108,48 @@ static const struct option opts[] = { { "instruction" , 0, NULL, 'i' }, { "help" , 0, NULL, 'h' }, { "kick" , 1, NULL, 'k' }, + { "pfa" , 0, NULL, 'p' }, { NULL , 0, NULL, 0 } }; -int main(int argc, char **argv) +static void pfa_helper(char *p, pid_t pid, unsigned long long old_phys) { - unsigned long long virt, phys; - long total; - char *buf; - int c, i; - int iflag = 0, dflag = 0; - int kick = 1; - pid_t pid; + int i; + int total; + unsigned long long new_phys; + + for (;;) { + for (i = 0; i < pagesize; i += sizeof(int)) { + total += *(int*)(p + i); + *(int*)(p + i) = total; + } + + new_phys = vtop((unsigned long long)p, pid); + if (old_phys == new_phys) { + for (i = 0; i < pagesize; i += sizeof(int)) { + total += *(int*)(p + i); + *(int*)(p + i) = i; + } + sleep(2); + new_phys = vtop((unsigned long long)p, pid); + if (old_phys != new_phys) { + printf("Page was replaced. New physical address = 0x%llx\n", new_phys); + fflush(stdout); + old_phys = new_phys; + } + } else { + printf("Page was replaced. New physical address = 0x%llx\n", new_phys); + fflush(stdout); + old_phys = new_phys; + } + } +} + +static int parse_addr_subopts(char *subopts, unsigned long long *virt, + pid_t *pid) +{ + int err = 0; + int index; enum { I_VADDR = 0, I_PID @@ -128,12 +159,72 @@ int main(int argc, char **argv) [I_PID] = "pid", NULL }; - char *subopts; + char *p = subopts; char *subval; char *svaddr; char *spid; - int err; - int index; + + while (*p != '\0' && !err) { + index = getsubopt(&p, token, &subval); + switch (index) { + case I_VADDR: + if (subval != NULL) { + svaddr = subval; + break; + } else { + fprintf(stderr, + "miss value for %s\n", + token[I_VADDR]); + err++; + continue; + } + case I_PID: + if (subval != NULL) { + spid = subval; + break; + } else { + fprintf(stderr, + "miss value for %s\n", + token[I_PID]); + err++; + continue; + } + default: + err++; + break; + } + } + if (err > 0) { + usage(); + return 1; + } + errno = 0; + *virt = strtoull(svaddr, NULL, 0); + if ((*virt == 0 && svaddr[0] != '0') || errno != 0) { + fprintf(stderr, "Invalid virtual address: %s\n", + svaddr); + return 1; + } + errno = 0; + *pid = strtoul(spid, NULL, 0); + if ((*pid == 0 && spid[0] != '0') || errno != 0) { + fprintf(stderr, "Invalid process pid number: %s\n", + spid); + return 1; + } + return 0; +} + +int main(int argc, char **argv) +{ + unsigned long long virt, phys; + long total; + char *buf; + int c, i; + int iflag = 0, dflag = 0; + int kick = 1; + int pfa = 0; + pid_t pid; const char *trigger = "./trigger_start"; const char *trigger_flag = "trigger"; int fd; @@ -149,63 +240,16 @@ int main(int argc, char **argv) pagesize = getpagesize(); - while ((c = getopt_long(argc, argv, "a:dihk:", opts, NULL)) != -1) { + while ((c = getopt_long(argc, argv, "a:dihk:p", opts, NULL)) != -1) { switch (c) { case 'a': - err = 0; - subopts = optarg; - while (*subopts != '\0' && !err) { - index = getsubopt(&subopts, token, &subval); - switch (index) { - case I_VADDR: - if (subval != NULL) { - svaddr = subval; - break; - } else { - fprintf(stderr, - "miss value for %s\n", - token[I_VADDR]); - err++; - continue; - } - case I_PID: - if (subval != NULL) { - spid = subval; - break; - } else { - fprintf(stderr, - "miss value for %s\n", - token[I_PID]); - err++; - continue; - } - default: - err++; - break; - } - } - if (err > 0) { - usage(); + if (parse_addr_subopts(optarg, &virt, &pid) == 0) { + phys = vtop(virt, pid); + printf("physical address of (%d,0x%llx) = 0x%llx\n", + pid, virt, phys); return 0; } - errno = 0; - virt = strtoull(svaddr, NULL, 0); - if ((virt == 0 && svaddr[0] != '0') || errno != 0) { - fprintf(stderr, "Invalid virtual address: %s\n", - svaddr); - return 1; - } - errno = 0; - pid = strtoul(spid, NULL, 0); - if ((pid == 0 && spid[0] != '0') || errno != 0) { - fprintf(stderr, "Invalid process pid number: %s\n", - spid); - return 1; - } - phys = vtop(virt, pid); - printf("physical address of (%d,0x%llx) = 0x%llx\n", - pid, virt, phys); - return 0; + return 1; case 'd': dflag = 1; break; @@ -224,6 +268,9 @@ int main(int argc, char **argv) return 1; } break; + case 'p': + pfa = 1; + break; case 'h': default: usage(); @@ -256,6 +303,10 @@ int main(int argc, char **argv) printf("physical address of (0x%llx) = 0x%llx\n", (unsigned long long)buf, phys); fflush(stdout); + + if (pfa == 1) + pfa_helper(buf, pid, phys); + if (kick == 0) { errno = 0; if (unlink(trigger) < 0 && errno != ENOENT) { @@ -286,6 +337,7 @@ int main(int argc, char **argv) now = time(NULL); printf("Access time at %s\n", ctime(&now)); } + if (iflag) { void (*f)(void) = (void (*)(void))buf; |