From: Suraj Jitindar Singh <sjitindarsingh@gmail.com> To: kvm@vger.kernel.org Cc: sjitindarsingh@gmail.com, pbonzini@redhat.com, rkrcmar@redhat.com, kvm-ppc@vger.kernel.org, lvivier@redhat.com, thuth@redhat.com, drjones@redhat.com Subject: [kvm-unit-tests PATCH V2 4/4] powerpc/tm: Add a test for H_CEDE while tm suspended Date: Wed, 10 Aug 2016 11:59:37 +1000 [thread overview] Message-ID: <1470794377-14427-4-git-send-email-sjitindarsingh@gmail.com> (raw) In-Reply-To: <1470794377-14427-1-git-send-email-sjitindarsingh@gmail.com> On Power machines if a guest cedes while a tm transaction is in the suspended state then the checkpointed state of the vcpu may be lost and we lose the cpu in the host. Add a file for tm tests "powerpc/tm.c" and add a test to check if the fix has been applied to the host kernel. If this fix hasn't been applied then the test will never complete and the cpu will be lost. Otherwise the test should succeed. Since this has the ability to mess things up in the host mark this test as don't run by default. Based on initial work done by: Cyril Bur <cyril.bur@au1.ibm.com> Signed-off-by: Suraj Jitindar Singh <sjitindarsingh@gmail.com> --- lib/powerpc/asm/hcall.h | 1 + powerpc/Makefile.common | 3 +- powerpc/tm.c | 176 ++++++++++++++++++++++++++++++++++++++++++++++++ powerpc/unittests.cfg | 6 ++ 4 files changed, 185 insertions(+), 1 deletion(-) create mode 100644 powerpc/tm.c diff --git a/lib/powerpc/asm/hcall.h b/lib/powerpc/asm/hcall.h index 99bce79..80aa3e3 100644 --- a/lib/powerpc/asm/hcall.h +++ b/lib/powerpc/asm/hcall.h @@ -18,6 +18,7 @@ #define H_SET_SPRG0 0x24 #define H_SET_DABR 0x28 #define H_PAGE_INIT 0x2c +#define H_CEDE 0xE0 #define H_PUT_TERM_CHAR 0x58 #define H_RANDOM 0x300 #define H_SET_MODE 0x31C diff --git a/powerpc/Makefile.common b/powerpc/Makefile.common index 677030a..93e4f66 100644 --- a/powerpc/Makefile.common +++ b/powerpc/Makefile.common @@ -8,7 +8,8 @@ tests-common = \ $(TEST_DIR)/selftest.elf \ $(TEST_DIR)/spapr_hcall.elf \ $(TEST_DIR)/rtas.elf \ - $(TEST_DIR)/emulator.elf + $(TEST_DIR)/emulator.elf \ + $(TEST_DIR)/tm.elf all: $(TEST_DIR)/boot_rom.bin test_cases diff --git a/powerpc/tm.c b/powerpc/tm.c new file mode 100644 index 0000000..7f675ff --- /dev/null +++ b/powerpc/tm.c @@ -0,0 +1,176 @@ +/* + * Transactional Memory Unit Tests + * + * Copyright 2016 Suraj Jitindar Singh, IBM. + * + * This work is licensed under the terms of the GNU LGPL, version 2. + */ +#include <libcflat.h> +#include <libfdt/libfdt.h> +#include <devicetree.h> +#include <util.h> +#include <alloc.h> +#include <asm/hcall.h> +#include <asm/ppc_asm.h> +#include <asm/processor.h> +#include <asm/handlers.h> +#include <asm/smp.h> + +#define US_TO_CYCLES(us) (us << 9) + +/* + * Get decrementer value + */ +static uint64_t get_dec(void) +{ + uint64_t dec = 0; + + asm volatile ( "mfdec %[dec]" : [dec] "+r" (dec) + : + : + ); + + return dec; +} + +/* + * Sleep for <us> micro-seconds (must be less than 4 seconds) + */ +static void sleep(uint64_t us) +{ + uint64_t expire_time, dec, cycles = US_TO_CYCLES(us); + + if (cycles > 0x7FFFFFFF) + cycles = 0x7FFFFFFF; + + if (cycles > (dec = get_dec())) { + expire_time = 0x7FFFFFFF + dec - cycles; + while (get_dec() < dec) + ; + } else { + expire_time = dec - cycles; + } + + while (get_dec() > expire_time) + ; +} + +static int h_cede(void) +{ + register uint64_t r3 asm("r3") = H_CEDE; + + asm volatile ( "sc 1" : "+r"(r3) + : + : "r0", "r4", "r5", "r6", "r7", "r8", "r9", + "r10", "r11", "r12", "xer", "ctr", "cc" + ); + + return r3; +} + +/* + * Enable transactional memory + * Returns: 0 - Failure + * 1 - Success + */ +static bool enable_tm(void) +{ + uint64_t msr = 0; + + asm volatile ( "mfmsr %[msr]" : [msr] "+r" (msr) + : + : + ); + + msr |= (((uint64_t) 1) << 32); + + asm volatile ( "mtmsrd %1\n\t" + "mfmsr %0" : "+r" (msr) + : "r" (msr) + : + ); + + return !!(msr & (((uint64_t) 1) << 32)); +} + +/* + * Test H_CEDE call while transactional memory transaction is suspended + * + * WARNING: This tests for a known vulnerability in which the host may go down. + * Probably best not to run this if your host going down is going to cause + * problems. + * + * If the test passes then your kernel probably has the necessary patch. + * If the test fails then the H_CEDE call was unsuccessful and the + * vulnerability wasn't tested. + * If the test hits the vulnerability then it will never complete or report and + * the qemu process will block indefinately. RCU stalls will be detected on the + * cpu and any process scheduled on the lost cpu will also block indefinitely. + */ +static void test_h_cede_tm(int argc, char **argv) +{ + bool pass = true; + int i; + + if (argc > 2) + report_abort("Unsupported argument: '%s'", argv[2]); + + handle_exception(0x900, &dec_except_handler, NULL); + + if (!start_all_cpus(&halt, 0)) + report_abort("Failed to start secondary cpus"); + + if (!enable_tm()) + report_abort("Failed to enable tm"); + + /* + * Begin a transaction and guarantee we are in the suspend state + * before continuing + */ + asm volatile ( "1: tbegin.\n\t" + "beq 2f\n\t" + "tsuspend.\n\t" + "2: tcheck cr0\n\t" + "bf 2,1b" : + : + : "cr0" + ); + + for (i = 0; i < 500 && pass; i++) { + uint64_t rval = h_cede(); + + if (rval != H_SUCCESS) + pass = false; + sleep(5000); + } + + report("H_CEDE TM", pass); +} + +struct { + const char *name; + void (*func)(int argc, char **argv); +} hctests[] = { + { "h_cede_tm", test_h_cede_tm }, + { NULL, NULL } +}; + +int main(int argc, char **argv) +{ + bool all = false; + int i; + + report_prefix_push("tm"); + + all = (argc == 1 || (argc == 2 && !strcmp(argv[1], "all"))); + + for (i = 0; hctests[i].name != NULL; i++) { + if (all || strcmp(argv[1], hctests[i].name) == 0) { + report_prefix_push(hctests[i].name); + hctests[i].func(argc, argv); + report_prefix_pop(); + } + } + + return report_summary(); +} diff --git a/powerpc/unittests.cfg b/powerpc/unittests.cfg index 0098cb6..20dbde6 100644 --- a/powerpc/unittests.cfg +++ b/powerpc/unittests.cfg @@ -53,3 +53,9 @@ groups = rtas [emulator] file = emulator.elf + +[h_cede_tm] +file = tm.elf +smp = 2,threads=2 +extra_params = -append "h_cede_tm" +groups = nodefault,h_cede_tm -- 2.5.5
WARNING: multiple messages have this Message-ID (diff)
From: Suraj Jitindar Singh <sjitindarsingh@gmail.com> To: kvm@vger.kernel.org Cc: sjitindarsingh@gmail.com, pbonzini@redhat.com, rkrcmar@redhat.com, kvm-ppc@vger.kernel.org, lvivier@redhat.com, thuth@redhat.com, drjones@redhat.com Subject: [kvm-unit-tests PATCH V2 4/4] powerpc/tm: Add a test for H_CEDE while tm suspended Date: Wed, 10 Aug 2016 01:59:37 +0000 [thread overview] Message-ID: <1470794377-14427-4-git-send-email-sjitindarsingh@gmail.com> (raw) In-Reply-To: <1470794377-14427-1-git-send-email-sjitindarsingh@gmail.com> On Power machines if a guest cedes while a tm transaction is in the suspended state then the checkpointed state of the vcpu may be lost and we lose the cpu in the host. Add a file for tm tests "powerpc/tm.c" and add a test to check if the fix has been applied to the host kernel. If this fix hasn't been applied then the test will never complete and the cpu will be lost. Otherwise the test should succeed. Since this has the ability to mess things up in the host mark this test as don't run by default. Based on initial work done by: Cyril Bur <cyril.bur@au1.ibm.com> Signed-off-by: Suraj Jitindar Singh <sjitindarsingh@gmail.com> --- lib/powerpc/asm/hcall.h | 1 + powerpc/Makefile.common | 3 +- powerpc/tm.c | 176 ++++++++++++++++++++++++++++++++++++++++++++++++ powerpc/unittests.cfg | 6 ++ 4 files changed, 185 insertions(+), 1 deletion(-) create mode 100644 powerpc/tm.c diff --git a/lib/powerpc/asm/hcall.h b/lib/powerpc/asm/hcall.h index 99bce79..80aa3e3 100644 --- a/lib/powerpc/asm/hcall.h +++ b/lib/powerpc/asm/hcall.h @@ -18,6 +18,7 @@ #define H_SET_SPRG0 0x24 #define H_SET_DABR 0x28 #define H_PAGE_INIT 0x2c +#define H_CEDE 0xE0 #define H_PUT_TERM_CHAR 0x58 #define H_RANDOM 0x300 #define H_SET_MODE 0x31C diff --git a/powerpc/Makefile.common b/powerpc/Makefile.common index 677030a..93e4f66 100644 --- a/powerpc/Makefile.common +++ b/powerpc/Makefile.common @@ -8,7 +8,8 @@ tests-common = \ $(TEST_DIR)/selftest.elf \ $(TEST_DIR)/spapr_hcall.elf \ $(TEST_DIR)/rtas.elf \ - $(TEST_DIR)/emulator.elf + $(TEST_DIR)/emulator.elf \ + $(TEST_DIR)/tm.elf all: $(TEST_DIR)/boot_rom.bin test_cases diff --git a/powerpc/tm.c b/powerpc/tm.c new file mode 100644 index 0000000..7f675ff --- /dev/null +++ b/powerpc/tm.c @@ -0,0 +1,176 @@ +/* + * Transactional Memory Unit Tests + * + * Copyright 2016 Suraj Jitindar Singh, IBM. + * + * This work is licensed under the terms of the GNU LGPL, version 2. + */ +#include <libcflat.h> +#include <libfdt/libfdt.h> +#include <devicetree.h> +#include <util.h> +#include <alloc.h> +#include <asm/hcall.h> +#include <asm/ppc_asm.h> +#include <asm/processor.h> +#include <asm/handlers.h> +#include <asm/smp.h> + +#define US_TO_CYCLES(us) (us << 9) + +/* + * Get decrementer value + */ +static uint64_t get_dec(void) +{ + uint64_t dec = 0; + + asm volatile ( "mfdec %[dec]" : [dec] "+r" (dec) + : + : + ); + + return dec; +} + +/* + * Sleep for <us> micro-seconds (must be less than 4 seconds) + */ +static void sleep(uint64_t us) +{ + uint64_t expire_time, dec, cycles = US_TO_CYCLES(us); + + if (cycles > 0x7FFFFFFF) + cycles = 0x7FFFFFFF; + + if (cycles > (dec = get_dec())) { + expire_time = 0x7FFFFFFF + dec - cycles; + while (get_dec() < dec) + ; + } else { + expire_time = dec - cycles; + } + + while (get_dec() > expire_time) + ; +} + +static int h_cede(void) +{ + register uint64_t r3 asm("r3") = H_CEDE; + + asm volatile ( "sc 1" : "+r"(r3) + : + : "r0", "r4", "r5", "r6", "r7", "r8", "r9", + "r10", "r11", "r12", "xer", "ctr", "cc" + ); + + return r3; +} + +/* + * Enable transactional memory + * Returns: 0 - Failure + * 1 - Success + */ +static bool enable_tm(void) +{ + uint64_t msr = 0; + + asm volatile ( "mfmsr %[msr]" : [msr] "+r" (msr) + : + : + ); + + msr |= (((uint64_t) 1) << 32); + + asm volatile ( "mtmsrd %1\n\t" + "mfmsr %0" : "+r" (msr) + : "r" (msr) + : + ); + + return !!(msr & (((uint64_t) 1) << 32)); +} + +/* + * Test H_CEDE call while transactional memory transaction is suspended + * + * WARNING: This tests for a known vulnerability in which the host may go down. + * Probably best not to run this if your host going down is going to cause + * problems. + * + * If the test passes then your kernel probably has the necessary patch. + * If the test fails then the H_CEDE call was unsuccessful and the + * vulnerability wasn't tested. + * If the test hits the vulnerability then it will never complete or report and + * the qemu process will block indefinately. RCU stalls will be detected on the + * cpu and any process scheduled on the lost cpu will also block indefinitely. + */ +static void test_h_cede_tm(int argc, char **argv) +{ + bool pass = true; + int i; + + if (argc > 2) + report_abort("Unsupported argument: '%s'", argv[2]); + + handle_exception(0x900, &dec_except_handler, NULL); + + if (!start_all_cpus(&halt, 0)) + report_abort("Failed to start secondary cpus"); + + if (!enable_tm()) + report_abort("Failed to enable tm"); + + /* + * Begin a transaction and guarantee we are in the suspend state + * before continuing + */ + asm volatile ( "1: tbegin.\n\t" + "beq 2f\n\t" + "tsuspend.\n\t" + "2: tcheck cr0\n\t" + "bf 2,1b" : + : + : "cr0" + ); + + for (i = 0; i < 500 && pass; i++) { + uint64_t rval = h_cede(); + + if (rval != H_SUCCESS) + pass = false; + sleep(5000); + } + + report("H_CEDE TM", pass); +} + +struct { + const char *name; + void (*func)(int argc, char **argv); +} hctests[] = { + { "h_cede_tm", test_h_cede_tm }, + { NULL, NULL } +}; + +int main(int argc, char **argv) +{ + bool all = false; + int i; + + report_prefix_push("tm"); + + all = (argc = 1 || (argc = 2 && !strcmp(argv[1], "all"))); + + for (i = 0; hctests[i].name != NULL; i++) { + if (all || strcmp(argv[1], hctests[i].name) = 0) { + report_prefix_push(hctests[i].name); + hctests[i].func(argc, argv); + report_prefix_pop(); + } + } + + return report_summary(); +} diff --git a/powerpc/unittests.cfg b/powerpc/unittests.cfg index 0098cb6..20dbde6 100644 --- a/powerpc/unittests.cfg +++ b/powerpc/unittests.cfg @@ -53,3 +53,9 @@ groups = rtas [emulator] file = emulator.elf + +[h_cede_tm] +file = tm.elf +smp = 2,threads=2 +extra_params = -append "h_cede_tm" +groups = nodefault,h_cede_tm -- 2.5.5
next prev parent reply other threads:[~2016-08-10 2:01 UTC|newest] Thread overview: 52+ messages / expand[flat|nested] mbox.gz Atom feed top 2016-08-10 1:59 [kvm-unit-tests PATCH V2 1/4] scripts/runtime: Add ability to mark test as don't run by default Suraj Jitindar Singh 2016-08-10 1:59 ` Suraj Jitindar Singh 2016-08-10 1:59 ` [kvm-unit-tests PATCH V2 2/4] lib/powerpc: Add generic decrementer exception handler Suraj Jitindar Singh 2016-08-10 1:59 ` Suraj Jitindar Singh 2016-08-10 10:38 ` Thomas Huth 2016-08-10 10:38 ` Thomas Huth 2016-08-12 6:17 ` Suraj Jitindar Singh 2016-08-12 6:17 ` Suraj Jitindar Singh 2016-08-10 1:59 ` [kvm-unit-tests PATCH V2 3/4] lib/powerpc: Add function to start secondary threads Suraj Jitindar Singh 2016-08-10 1:59 ` Suraj Jitindar Singh 2016-08-10 11:25 ` Thomas Huth 2016-08-10 11:25 ` Thomas Huth 2016-08-12 6:30 ` Suraj Jitindar Singh 2016-08-12 6:30 ` Suraj Jitindar Singh 2016-08-12 11:19 ` Thomas Huth 2016-08-12 11:19 ` Thomas Huth 2016-08-15 1:01 ` Suraj Jitindar Singh 2016-08-15 1:01 ` Suraj Jitindar Singh 2016-08-12 17:07 ` Andrew Jones 2016-08-12 17:07 ` Andrew Jones 2016-08-15 1:58 ` Suraj Jitindar Singh 2016-08-15 1:58 ` Suraj Jitindar Singh 2016-08-15 6:27 ` Andrew Jones 2016-08-15 6:27 ` Andrew Jones 2016-08-16 5:10 ` Suraj Jitindar Singh 2016-08-16 5:10 ` Suraj Jitindar Singh 2016-08-10 1:59 ` Suraj Jitindar Singh [this message] 2016-08-10 1:59 ` [kvm-unit-tests PATCH V2 4/4] powerpc/tm: Add a test for H_CEDE while tm suspended Suraj Jitindar Singh 2016-08-10 9:43 ` Thomas Huth 2016-08-10 9:43 ` Thomas Huth 2016-08-12 6:36 ` Suraj Jitindar Singh 2016-08-12 6:36 ` Suraj Jitindar Singh 2016-08-10 11:33 ` Thomas Huth 2016-08-10 11:33 ` Thomas Huth 2016-08-12 6:36 ` Suraj Jitindar Singh 2016-08-12 6:36 ` Suraj Jitindar Singh 2016-08-12 17:19 ` Andrew Jones 2016-08-12 17:19 ` Andrew Jones 2016-08-15 2:01 ` Suraj Jitindar Singh 2016-08-15 2:01 ` Suraj Jitindar Singh 2016-08-10 13:22 ` [kvm-unit-tests PATCH V2 1/4] scripts/runtime: Add ability to mark test as don't run by default Radim Krčmář 2016-08-10 13:22 ` Radim Krčmář 2016-08-12 6:13 ` Suraj Jitindar Singh 2016-08-12 6:13 ` Suraj Jitindar Singh 2016-08-12 10:00 ` Andrew Jones 2016-08-12 10:00 ` Andrew Jones 2016-08-12 12:06 ` Radim Krčmář 2016-08-12 12:06 ` Radim Krčmář 2016-08-12 12:58 ` Andrew Jones 2016-08-12 12:58 ` Andrew Jones 2016-08-14 23:41 ` Suraj Jitindar Singh 2016-08-14 23:41 ` Suraj Jitindar Singh
Reply instructions: You may reply publicly to this message via plain-text email using any one of the following methods: * Save the following mbox file, import it into your mail client, and reply-to-all from there: mbox Avoid top-posting and favor interleaved quoting: https://en.wikipedia.org/wiki/Posting_style#Interleaved_style * Reply using the --to, --cc, and --in-reply-to switches of git-send-email(1): git send-email \ --in-reply-to=1470794377-14427-4-git-send-email-sjitindarsingh@gmail.com \ --to=sjitindarsingh@gmail.com \ --cc=drjones@redhat.com \ --cc=kvm-ppc@vger.kernel.org \ --cc=kvm@vger.kernel.org \ --cc=lvivier@redhat.com \ --cc=pbonzini@redhat.com \ --cc=rkrcmar@redhat.com \ --cc=thuth@redhat.com \ /path/to/YOUR_REPLY https://kernel.org/pub/software/scm/git/docs/git-send-email.html * If your mail client supports setting the In-Reply-To header via mailto: links, try the mailto: linkBe sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes, see mirroring instructions on how to clone and mirror all data and code used by this external index.