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