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 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 */ 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 */ 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 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