1e7324a48SNicholas Piggin /*
2e7324a48SNicholas Piggin * Test sPAPR "Per Virtual Processor Area" and H_REGISTER_VPA hypervisor call
3e7324a48SNicholas Piggin * (also known as VPA, also known as lppaca in the Linux pseries kernel).
4e7324a48SNicholas Piggin *
5e7324a48SNicholas Piggin * This work is licensed under the terms of the GNU LGPL, version 2.
6e7324a48SNicholas Piggin */
7e7324a48SNicholas Piggin #include <libcflat.h>
8e7324a48SNicholas Piggin #include <libfdt/libfdt.h>
9e7324a48SNicholas Piggin #include <devicetree.h>
10e7324a48SNicholas Piggin #include <util.h>
11e7324a48SNicholas Piggin #include <alloc.h>
12e7324a48SNicholas Piggin #include <asm/processor.h>
138b10d4faSNicholas Piggin #include <asm/time.h>
14e7324a48SNicholas Piggin #include <asm/setup.h>
15e7324a48SNicholas Piggin #include <asm/hcall.h>
16e7324a48SNicholas Piggin #include <asm/vpa.h>
17e7324a48SNicholas Piggin #include <asm/io.h> /* for endian accessors */
18e7324a48SNicholas Piggin
19e7324a48SNicholas Piggin static int verbose;
20e7324a48SNicholas Piggin
print_vpa(struct vpa * vpa)21e7324a48SNicholas Piggin static void print_vpa(struct vpa *vpa)
22e7324a48SNicholas Piggin {
23e7324a48SNicholas Piggin printf("VPA\n");
24e7324a48SNicholas Piggin printf("descriptor: 0x%08x\n", be32_to_cpu(vpa->descriptor));
25e7324a48SNicholas Piggin printf("size: 0x%04x\n", be16_to_cpu(vpa->size));
26e7324a48SNicholas Piggin printf("status: 0x%02x\n", vpa->status);
27e7324a48SNicholas Piggin printf("fru_node_id: 0x%08x\n", be32_to_cpu(vpa->fru_node_id));
28e7324a48SNicholas Piggin printf("fru_proc_id: 0x%08x\n", be32_to_cpu(vpa->fru_proc_id));
29e7324a48SNicholas Piggin printf("vhpn_change_counters: 0x%02x %02x %02x %02x %02x %02x %02x %02x\n", vpa->vhpn_change_counters[0], vpa->vhpn_change_counters[1], vpa->vhpn_change_counters[2], vpa->vhpn_change_counters[3], vpa->vhpn_change_counters[4], vpa->vhpn_change_counters[5], vpa->vhpn_change_counters[6], vpa->vhpn_change_counters[7]);
30e7324a48SNicholas Piggin printf("vp_dispatch_count: 0x%08x\n", be32_to_cpu(vpa->vp_dispatch_count));
31e7324a48SNicholas Piggin printf("vp_dispatch_dispersion: 0x%08x\n", be32_to_cpu(vpa->vp_dispatch_dispersion));
32e7324a48SNicholas Piggin printf("vp_fault_count: 0x%08lx\n", be64_to_cpu(vpa->vp_fault_count));
33e7324a48SNicholas Piggin printf("vp_fault_tb: 0x%08lx\n", be64_to_cpu(vpa->vp_fault_tb));
34e7324a48SNicholas Piggin printf("purr_exprop_idle: 0x%08lx\n", be64_to_cpu(vpa->purr_exprop_idle));
35e7324a48SNicholas Piggin printf("spurr_exprop_idle: 0x%08lx\n", be64_to_cpu(vpa->spurr_exprop_idle));
36e7324a48SNicholas Piggin printf("purr_exprop_busy: 0x%08lx\n", be64_to_cpu(vpa->purr_exprop_busy));
37e7324a48SNicholas Piggin printf("spurr_exprop_busy: 0x%08lx\n", be64_to_cpu(vpa->spurr_exprop_busy));
38e7324a48SNicholas Piggin printf("purr_donate_idle: 0x%08lx\n", be64_to_cpu(vpa->purr_donate_idle));
39e7324a48SNicholas Piggin printf("spurr_donate_idle: 0x%08lx\n", be64_to_cpu(vpa->spurr_donate_idle));
40e7324a48SNicholas Piggin printf("purr_donate_busy: 0x%08lx\n", be64_to_cpu(vpa->purr_donate_busy));
41e7324a48SNicholas Piggin printf("spurr_donate_busy: 0x%08lx\n", be64_to_cpu(vpa->spurr_donate_busy));
42e7324a48SNicholas Piggin printf("vp_wait3_tb: 0x%08lx\n", be64_to_cpu(vpa->vp_wait3_tb));
43e7324a48SNicholas Piggin printf("vp_wait2_tb: 0x%08lx\n", be64_to_cpu(vpa->vp_wait2_tb));
44e7324a48SNicholas Piggin printf("vp_wait1_tb: 0x%08lx\n", be64_to_cpu(vpa->vp_wait1_tb));
45e7324a48SNicholas Piggin printf("purr_exprop_adjunct_busy: 0x%08lx\n", be64_to_cpu(vpa->purr_exprop_adjunct_busy));
46e7324a48SNicholas Piggin printf("spurr_exprop_adjunct_busy: 0x%08lx\n", be64_to_cpu(vpa->spurr_exprop_adjunct_busy));
47e7324a48SNicholas Piggin printf("purr_exprop_adjunct_idle: 0x%08lx\n", be64_to_cpu(vpa->purr_exprop_adjunct_idle));
48e7324a48SNicholas Piggin printf("spurr_exprop_adjunct_idle: 0x%08lx\n", be64_to_cpu(vpa->spurr_exprop_adjunct_idle));
49e7324a48SNicholas Piggin printf("adjunct_insns_executed: 0x%08lx\n", be64_to_cpu(vpa->adjunct_insns_executed));
50e7324a48SNicholas Piggin printf("dtl_index: 0x%08lx\n", be64_to_cpu(vpa->dtl_index));
51e7324a48SNicholas Piggin }
52e7324a48SNicholas Piggin
53e7324a48SNicholas Piggin #define SUBFUNC_RESERVED (0ULL << 45)
54e7324a48SNicholas Piggin #define SUBFUNC_REGISTER (1ULL << 45)
55e7324a48SNicholas Piggin #define SUBFUNC_DEREGISTER (5ULL << 45)
56e7324a48SNicholas Piggin
5762cdf7a5SNico Boehr /*
58e7324a48SNicholas Piggin * Test the H_REGISTER_VPA h-call register/deregister calls.
59e7324a48SNicholas Piggin */
test_register_vpa(void)60e7324a48SNicholas Piggin static void test_register_vpa(void)
61e7324a48SNicholas Piggin {
62e7324a48SNicholas Piggin struct vpa *vpa;
63e7324a48SNicholas Piggin uint32_t cpuid = fdt_boot_cpuid_phys(dt_fdt());
64e7324a48SNicholas Piggin int rc;
65e7324a48SNicholas Piggin
66e7324a48SNicholas Piggin report_prefix_push("H_REGISTER_VPA");
67e7324a48SNicholas Piggin
68e7324a48SNicholas Piggin vpa = memalign(4096, sizeof(*vpa));
69e7324a48SNicholas Piggin
70e7324a48SNicholas Piggin memset(vpa, 0, sizeof(*vpa));
71e7324a48SNicholas Piggin
72e7324a48SNicholas Piggin vpa->size = cpu_to_be16(sizeof(*vpa));
73e7324a48SNicholas Piggin
74e7324a48SNicholas Piggin rc = hcall(H_REGISTER_VPA, SUBFUNC_RESERVED, cpuid, vpa);
75e7324a48SNicholas Piggin report(rc == H_PARAMETER, "Reserved sub-function fails with H_PARAMETER");
76e7324a48SNicholas Piggin
77e7324a48SNicholas Piggin rc = hcall(H_REGISTER_VPA, SUBFUNC_REGISTER, 0xbadbad, vpa);
78e7324a48SNicholas Piggin report(rc == H_PARAMETER, "Register with invalid proc-no fails");
79e7324a48SNicholas Piggin
80e7324a48SNicholas Piggin rc = hcall(H_REGISTER_VPA, SUBFUNC_REGISTER, cpuid, (void *)vpa + 8);
81e7324a48SNicholas Piggin report(rc == H_PARAMETER, "Register with VPA not cacheline aligned fails");
82e7324a48SNicholas Piggin
83e7324a48SNicholas Piggin
84e7324a48SNicholas Piggin rc = hcall(H_REGISTER_VPA, SUBFUNC_REGISTER, cpuid, (void *)vpa + 4096 - 128);
85e7324a48SNicholas Piggin report(rc == H_PARAMETER, "Register with VPA spanning 4096 bytes fails");
86e7324a48SNicholas Piggin
87e7324a48SNicholas Piggin vpa->size = cpu_to_be16(632);
88e7324a48SNicholas Piggin rc = hcall(H_REGISTER_VPA, SUBFUNC_REGISTER, cpuid, (void *)vpa);
89e7324a48SNicholas Piggin report(rc == H_PARAMETER, "Register with VPA size < 640 bytes fails");
90e7324a48SNicholas Piggin vpa->size = cpu_to_be16(sizeof(*vpa));
91e7324a48SNicholas Piggin
92e7324a48SNicholas Piggin rc = hcall(H_REGISTER_VPA, SUBFUNC_REGISTER, cpuid, PHYSICAL_END);
93e7324a48SNicholas Piggin report(rc == H_PARAMETER, "Register with VPA outside guest real memory fails");
94e7324a48SNicholas Piggin
95e7324a48SNicholas Piggin
96e7324a48SNicholas Piggin rc = hcall(H_REGISTER_VPA, SUBFUNC_REGISTER, cpuid, vpa);
97e7324a48SNicholas Piggin report(rc == H_SUCCESS, "VPA registered");
98e7324a48SNicholas Piggin
99e7324a48SNicholas Piggin rc = hcall(H_REGISTER_VPA, SUBFUNC_DEREGISTER, cpuid, NULL);
100e7324a48SNicholas Piggin report(rc == H_SUCCESS, "VPA deregistered");
101e7324a48SNicholas Piggin
102e7324a48SNicholas Piggin /*
103e7324a48SNicholas Piggin * From PAPR: "note no check is made that a valid VPA registration
104e7324a48SNicholas Piggin * exists".
105e7324a48SNicholas Piggin */
106e7324a48SNicholas Piggin rc = hcall(H_REGISTER_VPA, SUBFUNC_DEREGISTER, cpuid, NULL);
107e7324a48SNicholas Piggin report(rc == H_SUCCESS, "Deregister succeeds with no VPA registered");
108e7324a48SNicholas Piggin
109e7324a48SNicholas Piggin rc = hcall(H_REGISTER_VPA, SUBFUNC_DEREGISTER, 0xbadbad, NULL);
110e7324a48SNicholas Piggin report(rc == H_PARAMETER, "Deregister with invalid proc-no fails");
111e7324a48SNicholas Piggin
112e7324a48SNicholas Piggin report_prefix_pop();
113e7324a48SNicholas Piggin }
114e7324a48SNicholas Piggin
11562cdf7a5SNico Boehr /*
116e7324a48SNicholas Piggin * Test some VPA fields.
117e7324a48SNicholas Piggin */
test_vpa(void)118e7324a48SNicholas Piggin static void test_vpa(void)
119e7324a48SNicholas Piggin {
120e7324a48SNicholas Piggin struct vpa *vpa;
121e7324a48SNicholas Piggin uint32_t cpuid = fdt_boot_cpuid_phys(dt_fdt());
122e7324a48SNicholas Piggin int disp_count1, disp_count2;
123e7324a48SNicholas Piggin int rc;
124e7324a48SNicholas Piggin
125e7324a48SNicholas Piggin report_prefix_push("VPA");
126e7324a48SNicholas Piggin
127e7324a48SNicholas Piggin vpa = memalign(4096, sizeof(*vpa));
128e7324a48SNicholas Piggin
129e7324a48SNicholas Piggin memset(vpa, 0, sizeof(*vpa));
130e7324a48SNicholas Piggin
131e7324a48SNicholas Piggin vpa->size = cpu_to_be16(sizeof(*vpa));
132e7324a48SNicholas Piggin
133e7324a48SNicholas Piggin rc = hcall(H_REGISTER_VPA, SUBFUNC_REGISTER, cpuid, vpa);
134e7324a48SNicholas Piggin if (rc != H_SUCCESS) {
135e7324a48SNicholas Piggin report_skip("VPA could not be registered");
136e7324a48SNicholas Piggin return;
137e7324a48SNicholas Piggin }
138e7324a48SNicholas Piggin
139e7324a48SNicholas Piggin if (verbose)
140e7324a48SNicholas Piggin print_vpa(vpa);
141e7324a48SNicholas Piggin
142e7324a48SNicholas Piggin disp_count1 = be32_to_cpu(vpa->vp_dispatch_count);
143e7324a48SNicholas Piggin report(disp_count1 % 2 == 0, "Dispatch count is even while running");
144e7324a48SNicholas Piggin msleep(100);
145e7324a48SNicholas Piggin disp_count2 = be32_to_cpu(vpa->vp_dispatch_count);
146e7324a48SNicholas Piggin report(disp_count1 != disp_count2, "Dispatch count increments over H_CEDE");
147e7324a48SNicholas Piggin
148e7324a48SNicholas Piggin rc = hcall(H_REGISTER_VPA, SUBFUNC_DEREGISTER, cpuid, vpa);
149e7324a48SNicholas Piggin if (rc != H_SUCCESS)
150e7324a48SNicholas Piggin report_fail("Could not deregister after registration");
151e7324a48SNicholas Piggin
152e7324a48SNicholas Piggin disp_count1 = be32_to_cpu(vpa->vp_dispatch_count);
153*34508e8dSNicholas Piggin /* TCG known fail, could be wrong test, must verify against PowerVM */
154*34508e8dSNicholas Piggin report_kfail(true, disp_count1 % 2 == 1, "Dispatch count is odd after deregister");
155e7324a48SNicholas Piggin
156e7324a48SNicholas Piggin report_prefix_pop();
157e7324a48SNicholas Piggin }
158e7324a48SNicholas Piggin
main(int argc,char * argv[])159e7324a48SNicholas Piggin int main(int argc, char *argv[])
160e7324a48SNicholas Piggin {
161e7324a48SNicholas Piggin int i;
162e7324a48SNicholas Piggin
163e7324a48SNicholas Piggin for (i = 1; i < argc; i++) {
164e7324a48SNicholas Piggin if (strcmp(argv[i], "-v") == 0) {
165e7324a48SNicholas Piggin verbose = 1;
166e7324a48SNicholas Piggin }
167e7324a48SNicholas Piggin }
168e7324a48SNicholas Piggin
169e7324a48SNicholas Piggin test_register_vpa();
170e7324a48SNicholas Piggin
171e7324a48SNicholas Piggin test_vpa();
172e7324a48SNicholas Piggin
173e7324a48SNicholas Piggin return report_summary();
174e7324a48SNicholas Piggin }
175