1*adb87bc4SSuraj Jitindar Singh /* 2*adb87bc4SSuraj Jitindar Singh * Transactional Memory Unit Tests 3*adb87bc4SSuraj Jitindar Singh * 4*adb87bc4SSuraj Jitindar Singh * Copyright 2016 Suraj Jitindar Singh, IBM. 5*adb87bc4SSuraj Jitindar Singh * 6*adb87bc4SSuraj Jitindar Singh * This work is licensed under the terms of the GNU LGPL, version 2. 7*adb87bc4SSuraj Jitindar Singh */ 8*adb87bc4SSuraj Jitindar Singh #include <libcflat.h> 9*adb87bc4SSuraj Jitindar Singh #include <asm/hcall.h> 10*adb87bc4SSuraj Jitindar Singh #include <asm/processor.h> 11*adb87bc4SSuraj Jitindar Singh #include <asm/handlers.h> 12*adb87bc4SSuraj Jitindar Singh #include <asm/smp.h> 13*adb87bc4SSuraj Jitindar Singh 14*adb87bc4SSuraj Jitindar Singh static int h_cede(void) 15*adb87bc4SSuraj Jitindar Singh { 16*adb87bc4SSuraj Jitindar Singh register uint64_t r3 asm("r3") = H_CEDE; 17*adb87bc4SSuraj Jitindar Singh 18*adb87bc4SSuraj Jitindar Singh asm volatile ("sc 1" : "+r"(r3) : 19*adb87bc4SSuraj Jitindar Singh : "r0", "r4", "r5", "r6", "r7", "r8", "r9", 20*adb87bc4SSuraj Jitindar Singh "r10", "r11", "r12", "xer", "ctr", "cc"); 21*adb87bc4SSuraj Jitindar Singh 22*adb87bc4SSuraj Jitindar Singh return r3; 23*adb87bc4SSuraj Jitindar Singh } 24*adb87bc4SSuraj Jitindar Singh 25*adb87bc4SSuraj Jitindar Singh /* 26*adb87bc4SSuraj Jitindar Singh * Enable transactional memory 27*adb87bc4SSuraj Jitindar Singh * Returns: FALSE - Failure 28*adb87bc4SSuraj Jitindar Singh * TRUE - Success 29*adb87bc4SSuraj Jitindar Singh */ 30*adb87bc4SSuraj Jitindar Singh static bool enable_tm(void) 31*adb87bc4SSuraj Jitindar Singh { 32*adb87bc4SSuraj Jitindar Singh uint64_t msr = 0; 33*adb87bc4SSuraj Jitindar Singh 34*adb87bc4SSuraj Jitindar Singh asm volatile ("mfmsr %[msr]" : [msr] "=r" (msr)); 35*adb87bc4SSuraj Jitindar Singh 36*adb87bc4SSuraj Jitindar Singh msr |= (((uint64_t) 1) << 32); 37*adb87bc4SSuraj Jitindar Singh 38*adb87bc4SSuraj Jitindar Singh asm volatile ("mtmsrd %[msr]\n\t" 39*adb87bc4SSuraj Jitindar Singh "mfmsr %[msr]" : [msr] "+r" (msr)); 40*adb87bc4SSuraj Jitindar Singh 41*adb87bc4SSuraj Jitindar Singh return !!(msr & (((uint64_t) 1) << 32)); 42*adb87bc4SSuraj Jitindar Singh } 43*adb87bc4SSuraj Jitindar Singh 44*adb87bc4SSuraj Jitindar Singh /* 45*adb87bc4SSuraj Jitindar Singh * Test H_CEDE call while transactional memory transaction is suspended 46*adb87bc4SSuraj Jitindar Singh * 47*adb87bc4SSuraj Jitindar Singh * WARNING: This tests for a known vulnerability in which the host may go down. 48*adb87bc4SSuraj Jitindar Singh * Probably best not to run this if your host going down is going to cause 49*adb87bc4SSuraj Jitindar Singh * problems. 50*adb87bc4SSuraj Jitindar Singh * 51*adb87bc4SSuraj Jitindar Singh * If the test passes then your kernel probably has the necessary patch. 52*adb87bc4SSuraj Jitindar Singh * If the test fails then the H_CEDE call was unsuccessful and the 53*adb87bc4SSuraj Jitindar Singh * vulnerability wasn't tested. 54*adb87bc4SSuraj Jitindar Singh * If the test hits the vulnerability then it will never complete or report and 55*adb87bc4SSuraj Jitindar Singh * the qemu process will block indefinitely. RCU stalls will be detected on the 56*adb87bc4SSuraj Jitindar Singh * cpu and any process scheduled on the lost cpu will also block indefinitely. 57*adb87bc4SSuraj Jitindar Singh */ 58*adb87bc4SSuraj Jitindar Singh static void test_h_cede_tm(int argc, char **argv) 59*adb87bc4SSuraj Jitindar Singh { 60*adb87bc4SSuraj Jitindar Singh int i; 61*adb87bc4SSuraj Jitindar Singh 62*adb87bc4SSuraj Jitindar Singh if (argc > 2) 63*adb87bc4SSuraj Jitindar Singh report_abort("Unsupported argument: '%s'", argv[2]); 64*adb87bc4SSuraj Jitindar Singh 65*adb87bc4SSuraj Jitindar Singh handle_exception(0x900, &dec_except_handler, NULL); 66*adb87bc4SSuraj Jitindar Singh 67*adb87bc4SSuraj Jitindar Singh if (!start_all_cpus(halt, 0)) 68*adb87bc4SSuraj Jitindar Singh report_abort("Failed to start secondary cpus"); 69*adb87bc4SSuraj Jitindar Singh 70*adb87bc4SSuraj Jitindar Singh if (!enable_tm()) 71*adb87bc4SSuraj Jitindar Singh report_abort("Failed to enable tm"); 72*adb87bc4SSuraj Jitindar Singh 73*adb87bc4SSuraj Jitindar Singh /* 74*adb87bc4SSuraj Jitindar Singh * Begin a transaction and guarantee we are in the suspend state 75*adb87bc4SSuraj Jitindar Singh * before continuing 76*adb87bc4SSuraj Jitindar Singh */ 77*adb87bc4SSuraj Jitindar Singh asm volatile ("1: .long 0x7c00051d\n\t" /* tbegin. */ 78*adb87bc4SSuraj Jitindar Singh "beq 2f\n\t" 79*adb87bc4SSuraj Jitindar Singh ".long 0x7c0005dd\n\t" /* tsuspend. */ 80*adb87bc4SSuraj Jitindar Singh "2: .long 0x7c00059c\n\t" /* tcheck cr0 */ 81*adb87bc4SSuraj Jitindar Singh "bf 2,1b" : : : "cr0"); 82*adb87bc4SSuraj Jitindar Singh 83*adb87bc4SSuraj Jitindar Singh for (i = 0; i < 500; i++) { 84*adb87bc4SSuraj Jitindar Singh uint64_t rval = h_cede(); 85*adb87bc4SSuraj Jitindar Singh 86*adb87bc4SSuraj Jitindar Singh if (rval != H_SUCCESS) 87*adb87bc4SSuraj Jitindar Singh break; 88*adb87bc4SSuraj Jitindar Singh mdelay(5); 89*adb87bc4SSuraj Jitindar Singh } 90*adb87bc4SSuraj Jitindar Singh 91*adb87bc4SSuraj Jitindar Singh report("H_CEDE TM", i == 500); 92*adb87bc4SSuraj Jitindar Singh } 93*adb87bc4SSuraj Jitindar Singh 94*adb87bc4SSuraj Jitindar Singh struct { 95*adb87bc4SSuraj Jitindar Singh const char *name; 96*adb87bc4SSuraj Jitindar Singh void (*func)(int argc, char **argv); 97*adb87bc4SSuraj Jitindar Singh } hctests[] = { 98*adb87bc4SSuraj Jitindar Singh { "h_cede_tm", test_h_cede_tm }, 99*adb87bc4SSuraj Jitindar Singh { NULL, NULL } 100*adb87bc4SSuraj Jitindar Singh }; 101*adb87bc4SSuraj Jitindar Singh 102*adb87bc4SSuraj Jitindar Singh int main(int argc, char **argv) 103*adb87bc4SSuraj Jitindar Singh { 104*adb87bc4SSuraj Jitindar Singh bool all; 105*adb87bc4SSuraj Jitindar Singh int i; 106*adb87bc4SSuraj Jitindar Singh 107*adb87bc4SSuraj Jitindar Singh report_prefix_push("tm"); 108*adb87bc4SSuraj Jitindar Singh 109*adb87bc4SSuraj Jitindar Singh all = argc == 1 || !strcmp(argv[1], "all"); 110*adb87bc4SSuraj Jitindar Singh 111*adb87bc4SSuraj Jitindar Singh for (i = 0; hctests[i].name != NULL; i++) { 112*adb87bc4SSuraj Jitindar Singh if (all || strcmp(argv[1], hctests[i].name) == 0) { 113*adb87bc4SSuraj Jitindar Singh report_prefix_push(hctests[i].name); 114*adb87bc4SSuraj Jitindar Singh hctests[i].func(argc, argv); 115*adb87bc4SSuraj Jitindar Singh report_prefix_pop(); 116*adb87bc4SSuraj Jitindar Singh } 117*adb87bc4SSuraj Jitindar Singh } 118*adb87bc4SSuraj Jitindar Singh 119*adb87bc4SSuraj Jitindar Singh return report_summary(); 120*adb87bc4SSuraj Jitindar Singh } 121