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