1adb87bc4SSuraj Jitindar Singh /*
2adb87bc4SSuraj Jitindar Singh * Transactional Memory Unit Tests
3adb87bc4SSuraj Jitindar Singh *
4adb87bc4SSuraj Jitindar Singh * Copyright 2016 Suraj Jitindar Singh, IBM.
5adb87bc4SSuraj Jitindar Singh *
6adb87bc4SSuraj Jitindar Singh * This work is licensed under the terms of the GNU LGPL, version 2.
7adb87bc4SSuraj Jitindar Singh */
8adb87bc4SSuraj Jitindar Singh #include <libcflat.h>
9adb87bc4SSuraj Jitindar Singh #include <asm/hcall.h>
10adb87bc4SSuraj Jitindar Singh #include <asm/processor.h>
118b10d4faSNicholas Piggin #include <asm/time.h>
12adb87bc4SSuraj Jitindar Singh #include <asm/handlers.h>
13adb87bc4SSuraj Jitindar Singh #include <asm/smp.h>
14cf54ca71SThomas Huth #include <asm/setup.h>
15cf54ca71SThomas Huth #include <devicetree.h>
16cf54ca71SThomas Huth
17cf54ca71SThomas Huth /* Check "ibm,pa-features" property of a CPU node for the TM flag */
cpu_has_tm(int fdtnode,u64 regval __unused,void * ptr)187a20b74eSAndrew Jones static void cpu_has_tm(int fdtnode, u64 regval __unused, void *ptr)
19cf54ca71SThomas Huth {
20cf54ca71SThomas Huth const struct fdt_property *prop;
21cf54ca71SThomas Huth int plen;
22cf54ca71SThomas Huth
23cf54ca71SThomas Huth prop = fdt_get_property(dt_fdt(), fdtnode, "ibm,pa-features", &plen);
24cf54ca71SThomas Huth if (!prop) /* No features means TM is also not available */
25cf54ca71SThomas Huth return;
26cf54ca71SThomas Huth /* Sanity check for the property layout (first two bytes are header) */
27cf54ca71SThomas Huth assert(plen >= 8 && prop->data[1] == 0 && prop->data[0] <= plen - 2);
28cf54ca71SThomas Huth
29cf54ca71SThomas Huth /*
30cf54ca71SThomas Huth * The "Transactional Memory Category Support" flags are at byte
31cf54ca71SThomas Huth * offset 22 and 23 of the attribute type 0, so when adding the
32cf54ca71SThomas Huth * two bytes for the header, we've got to look at offset 24 for
33cf54ca71SThomas Huth * the TM support bit.
34cf54ca71SThomas Huth */
35cf54ca71SThomas Huth if (prop->data[0] >= 24 && (prop->data[24] & 0x80) != 0)
36cf54ca71SThomas Huth *(int *)ptr += 1;
37cf54ca71SThomas Huth }
38cf54ca71SThomas Huth
39831d679aSThomas Huth /* Check amount of CPUs nodes that have the TM flag */
count_cpus_with_tm(void)40831d679aSThomas Huth static int count_cpus_with_tm(void)
41cf54ca71SThomas Huth {
42cf54ca71SThomas Huth int ret;
43cf54ca71SThomas Huth int available = 0;
44cf54ca71SThomas Huth
45cf54ca71SThomas Huth ret = dt_for_each_cpu_node(cpu_has_tm, &available);
46831d679aSThomas Huth if (ret < 0)
47831d679aSThomas Huth return ret;
48cf54ca71SThomas Huth
49831d679aSThomas Huth return available;
50cf54ca71SThomas Huth }
51adb87bc4SSuraj Jitindar Singh
52adb87bc4SSuraj Jitindar Singh /*
53adb87bc4SSuraj Jitindar Singh * Enable transactional memory
54adb87bc4SSuraj Jitindar Singh * Returns: FALSE - Failure
55adb87bc4SSuraj Jitindar Singh * TRUE - Success
56adb87bc4SSuraj Jitindar Singh */
enable_tm(void)57adb87bc4SSuraj Jitindar Singh static bool enable_tm(void)
58adb87bc4SSuraj Jitindar Singh {
59adb87bc4SSuraj Jitindar Singh uint64_t msr = 0;
60adb87bc4SSuraj Jitindar Singh
61adb87bc4SSuraj Jitindar Singh asm volatile ("mfmsr %[msr]" : [msr] "=r" (msr));
62adb87bc4SSuraj Jitindar Singh
63adb87bc4SSuraj Jitindar Singh msr |= (((uint64_t) 1) << 32);
64adb87bc4SSuraj Jitindar Singh
65adb87bc4SSuraj Jitindar Singh asm volatile ("mtmsrd %[msr]\n\t"
66adb87bc4SSuraj Jitindar Singh "mfmsr %[msr]" : [msr] "+r" (msr));
67adb87bc4SSuraj Jitindar Singh
68adb87bc4SSuraj Jitindar Singh return !!(msr & (((uint64_t) 1) << 32));
69adb87bc4SSuraj Jitindar Singh }
70adb87bc4SSuraj Jitindar Singh
71adb87bc4SSuraj Jitindar Singh /*
72adb87bc4SSuraj Jitindar Singh * Test H_CEDE call while transactional memory transaction is suspended
73adb87bc4SSuraj Jitindar Singh *
74adb87bc4SSuraj Jitindar Singh * WARNING: This tests for a known vulnerability in which the host may go down.
75adb87bc4SSuraj Jitindar Singh * Probably best not to run this if your host going down is going to cause
76adb87bc4SSuraj Jitindar Singh * problems.
77adb87bc4SSuraj Jitindar Singh *
78adb87bc4SSuraj Jitindar Singh * If the test passes then your kernel probably has the necessary patch.
79adb87bc4SSuraj Jitindar Singh * If the test fails then the H_CEDE call was unsuccessful and the
80adb87bc4SSuraj Jitindar Singh * vulnerability wasn't tested.
81adb87bc4SSuraj Jitindar Singh * If the test hits the vulnerability then it will never complete or report and
82adb87bc4SSuraj Jitindar Singh * the qemu process will block indefinitely. RCU stalls will be detected on the
83adb87bc4SSuraj Jitindar Singh * cpu and any process scheduled on the lost cpu will also block indefinitely.
84adb87bc4SSuraj Jitindar Singh */
test_h_cede_tm(int argc,char ** argv)85adb87bc4SSuraj Jitindar Singh static void test_h_cede_tm(int argc, char **argv)
86adb87bc4SSuraj Jitindar Singh {
87adb87bc4SSuraj Jitindar Singh int i;
88adb87bc4SSuraj Jitindar Singh
89adb87bc4SSuraj Jitindar Singh if (argc > 2)
90adb87bc4SSuraj Jitindar Singh report_abort("Unsupported argument: '%s'", argv[2]);
91adb87bc4SSuraj Jitindar Singh
92c76b0d0aSNicholas Piggin if (!start_all_cpus(halt))
93adb87bc4SSuraj Jitindar Singh report_abort("Failed to start secondary cpus");
94adb87bc4SSuraj Jitindar Singh
95adb87bc4SSuraj Jitindar Singh if (!enable_tm())
96adb87bc4SSuraj Jitindar Singh report_abort("Failed to enable tm");
97adb87bc4SSuraj Jitindar Singh
98adb87bc4SSuraj Jitindar Singh /*
99adb87bc4SSuraj Jitindar Singh * Begin a transaction and guarantee we are in the suspend state
100adb87bc4SSuraj Jitindar Singh * before continuing
101adb87bc4SSuraj Jitindar Singh */
102adb87bc4SSuraj Jitindar Singh asm volatile ("1: .long 0x7c00051d\n\t" /* tbegin. */
103adb87bc4SSuraj Jitindar Singh "beq 2f\n\t"
104adb87bc4SSuraj Jitindar Singh ".long 0x7c0005dd\n\t" /* tsuspend. */
105adb87bc4SSuraj Jitindar Singh "2: .long 0x7c00059c\n\t" /* tcheck cr0 */
106adb87bc4SSuraj Jitindar Singh "bf 2,1b" : : : "cr0");
107adb87bc4SSuraj Jitindar Singh
108adb87bc4SSuraj Jitindar Singh for (i = 0; i < 500; i++) {
109ba33a96fSNicholas Piggin msleep(10);
110adb87bc4SSuraj Jitindar Singh mdelay(5);
111adb87bc4SSuraj Jitindar Singh }
112adb87bc4SSuraj Jitindar Singh
113a299895bSThomas Huth report(i == 500, "H_CEDE TM");
114adb87bc4SSuraj Jitindar Singh }
115adb87bc4SSuraj Jitindar Singh
116adb87bc4SSuraj Jitindar Singh struct {
117adb87bc4SSuraj Jitindar Singh const char *name;
118adb87bc4SSuraj Jitindar Singh void (*func)(int argc, char **argv);
119adb87bc4SSuraj Jitindar Singh } hctests[] = {
120adb87bc4SSuraj Jitindar Singh { "h_cede_tm", test_h_cede_tm },
121adb87bc4SSuraj Jitindar Singh { NULL, NULL }
122adb87bc4SSuraj Jitindar Singh };
123adb87bc4SSuraj Jitindar Singh
main(int argc,char ** argv)124adb87bc4SSuraj Jitindar Singh int main(int argc, char **argv)
125adb87bc4SSuraj Jitindar Singh {
126831d679aSThomas Huth bool all;
127831d679aSThomas Huth int i, cpus_with_tm;
128adb87bc4SSuraj Jitindar Singh
129adb87bc4SSuraj Jitindar Singh report_prefix_push("tm");
130adb87bc4SSuraj Jitindar Singh
131831d679aSThomas Huth cpus_with_tm = count_cpus_with_tm();
132831d679aSThomas Huth if (cpus_with_tm == 0) {
133831d679aSThomas Huth report_skip("TM is not available");
134831d679aSThomas Huth goto done;
135831d679aSThomas Huth }
136c76b0d0aSNicholas Piggin /* kvm-unit-tests can limit number of CPUs present */
13734508e8dSNicholas Piggin /* KVM does not report TM in secondary threads in POWER9 */
138*851ef516SNicholas Piggin report_kfail(host_is_kvm, cpus_with_tm >= nr_cpus_present,
139a299895bSThomas Huth "TM available in all 'ibm,pa-features' properties");
140cf54ca71SThomas Huth
141adb87bc4SSuraj Jitindar Singh all = argc == 1 || !strcmp(argv[1], "all");
142adb87bc4SSuraj Jitindar Singh
143adb87bc4SSuraj Jitindar Singh for (i = 0; hctests[i].name != NULL; i++) {
144adb87bc4SSuraj Jitindar Singh if (all || strcmp(argv[1], hctests[i].name) == 0) {
145adb87bc4SSuraj Jitindar Singh report_prefix_push(hctests[i].name);
146adb87bc4SSuraj Jitindar Singh hctests[i].func(argc, argv);
147adb87bc4SSuraj Jitindar Singh report_prefix_pop();
148adb87bc4SSuraj Jitindar Singh }
149adb87bc4SSuraj Jitindar Singh }
150adb87bc4SSuraj Jitindar Singh
151831d679aSThomas Huth done:
152831d679aSThomas Huth report_prefix_pop();
153adb87bc4SSuraj Jitindar Singh return report_summary();
154adb87bc4SSuraj Jitindar Singh }
155