On Tue, 2016-08-16 at 14:57 +0200, Andrew Jones wrote: > On Tue, Aug 16, 2016 at 05:18:15PM +1000, Suraj Jitindar Singh wrote: > > > > 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. > > > > This vulnerability has been assigned the ID CVE-2016-5412. > > > > Based on initial work done by: Cyril Bur <cyril.bur@xxxxxxxxxxx> > > > > Signed-off-by: Suraj Jitindar Singh <sjitindarsingh@xxxxxxxxx> > > --- > > > > Change Log: > > > > V2 -> V3: > > - Remove get_dec() and sleep() functions as sleep functionality > > is > > now provided by a generic implementation in processor.c. > > - Replace TM instructions with raw machine code to support > > older > > compilers > > > > Signed-off-by: Suraj Jitindar Singh <sjitindarsingh@xxxxxxxxx> > > --- > > lib/powerpc/asm/hcall.h | 1 + > > powerpc/Makefile.common | 3 +- > > powerpc/tm.c | 121 > > ++++++++++++++++++++++++++++++++++++++++++++++++ > > powerpc/unittests.cfg | 6 +++ > > 4 files changed, 130 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..ba01f95 > > --- /dev/null > > +++ b/powerpc/tm.c > > @@ -0,0 +1,121 @@ > > +/* > > + * 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 <asm/hcall.h> > > +#include <asm/processor.h> > > +#include <asm/handlers.h> > > +#include <asm/smp.h> > > + > > +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: FALSE - Failure > > + * TRUE - 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 %[msr]\n\t" > > + "mfmsr %[msr]" : [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 indefinitely. 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)) > nit: more unnecessary '&' on function pointers Ok, guess I should change both > > > > > + 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: .long 0x7c00051d\n\t" /* tbegin. > > */ > > + "beq 2f\n\t" > > + ".long 0x7c0005dd\n\t" /* tsuspend. > > */ > > + "2: .long 0x7c00059c\n\t" /* tcheck > > cr0 */ > > + "bf 2,1b" : : : "cr0"); > > + > > + for (i = 0; i < 500 && pass; i++) { > > + uint64_t rval = h_cede(); > > + > > + if (rval != H_SUCCESS) > > + pass = false; > nit: you could drop the '&& pass' and just do a break here. Yes > > > > > + mdelay(5); > > + } > > + > > + report("H_CEDE TM", pass); > nit: with a break above you could just test for i == 500 here. ok > > > > > +} > > + > > +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; > > + int i; > > + > > + report_prefix_push("tm"); > > + > > + all = argc == 1 || (argc == 2 && !strcmp(argv[1], "all")); > I'd drop the argc == 2 test. You already know argc >= 2 at this > point. And, if it's > 2, then you want to call the test function > so the "Unsupported argument" abort will fire. Sounds good > > > > > + > > + 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 -- To unsubscribe from this list: send the line "unsubscribe kvm" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html