1 /* SPDX-License-Identifier: GPL-2.0-only */ 2 /* 3 * Store System Information tests 4 * 5 * Copyright (c) 2019 IBM Corp 6 * 7 * Authors: 8 * Janosch Frank <frankja@linux.ibm.com> 9 */ 10 11 #include <libcflat.h> 12 #include <asm/page.h> 13 #include <asm/asm-offsets.h> 14 #include <asm/interrupt.h> 15 #include <smp.h> 16 17 struct stsi_322 { 18 uint8_t reserved[31]; 19 uint8_t count; 20 struct { 21 uint8_t reserved2[4]; 22 uint16_t total_cpus; 23 uint16_t conf_cpus; 24 uint16_t standby_cpus; 25 uint16_t reserved_cpus; 26 uint8_t name[8]; 27 uint32_t caf; 28 uint8_t cpi[16]; 29 uint8_t reserved5[3]; 30 uint8_t ext_name_encoding; 31 uint32_t reserved3; 32 uint8_t uuid[16]; 33 } vm[8]; 34 uint8_t reserved4[1504]; 35 uint8_t ext_names[8][256]; 36 }; 37 static uint8_t pagebuf[PAGE_SIZE * 2] __attribute__((aligned(PAGE_SIZE * 2))); 38 39 static void test_specs(void) 40 { 41 report_prefix_push("specification"); 42 43 report_prefix_push("inv r0"); 44 expect_pgm_int(); 45 stsi(pagebuf, 0, 1 << 8, 0); 46 check_pgm_int_code(PGM_INT_CODE_SPECIFICATION); 47 report_prefix_pop(); 48 49 report_prefix_push("inv r1"); 50 expect_pgm_int(); 51 stsi(pagebuf, 1, 0, 1 << 16); 52 check_pgm_int_code(PGM_INT_CODE_SPECIFICATION); 53 report_prefix_pop(); 54 55 report_prefix_push("unaligned"); 56 expect_pgm_int(); 57 stsi(pagebuf + 42, 1, 1, 1); 58 check_pgm_int_code(PGM_INT_CODE_SPECIFICATION); 59 report_prefix_pop(); 60 61 report_prefix_pop(); 62 } 63 64 static void test_priv(void) 65 { 66 report_prefix_push("privileged"); 67 expect_pgm_int(); 68 enter_pstate(); 69 stsi(pagebuf, 0, 0, 0); 70 check_pgm_int_code(PGM_INT_CODE_PRIVILEGED_OPERATION); 71 report_prefix_pop(); 72 } 73 74 static inline unsigned long stsi_get_fc(void *addr) 75 { 76 register unsigned long r0 asm("0") = 0; 77 register unsigned long r1 asm("1") = 0; 78 int cc; 79 80 asm volatile("stsi 0(%[addr])\n" 81 "ipm %[cc]\n" 82 "srl %[cc],28\n" 83 : "+d" (r0), [cc] "=d" (cc) 84 : "d" (r1), [addr] "a" (addr) 85 : "cc", "memory"); 86 assert(!cc); 87 return r0 >> 28; 88 } 89 90 static void test_fc(void) 91 { 92 report(stsi(pagebuf, 7, 0, 0) == 3, "invalid fc"); 93 report(stsi(pagebuf, 1, 0, 1) == 3, "invalid selector 1"); 94 report(stsi(pagebuf, 1, 1, 0) == 3, "invalid selector 2"); 95 report(stsi_get_fc(pagebuf) >= 2, "query fc >= 2"); 96 } 97 98 static void test_3_2_2(void) 99 { 100 int rc; 101 /* EBCDIC for "kvm-unit" */ 102 const uint8_t vm_name[] = { 0x92, 0xa5, 0x94, 0x60, 0xa4, 0x95, 0x89, 103 0xa3 }; 104 const uint8_t uuid[] = { 0x0f, 0xb8, 0x4a, 0x86, 0x72, 0x7c, 105 0x11, 0xea, 0xbc, 0x55, 0x02, 0x42, 0xac, 0x13, 106 0x00, 0x03 }; 107 /* EBCDIC for "KVM/" */ 108 const uint8_t cpi_kvm[] = { 0xd2, 0xe5, 0xd4, 0x61 }; 109 const char vm_name_ext[] = "kvm-unit-test"; 110 struct stsi_322 *data = (void *)pagebuf; 111 112 report_prefix_push("3.2.2"); 113 114 /* Is the function code available at all? */ 115 if (stsi_get_fc(pagebuf) < 3) { 116 report_skip("Running under lpar, no level 3 to test."); 117 goto out; 118 } 119 120 rc = stsi(pagebuf, 3, 2, 2); 121 report(!rc, "call"); 122 123 /* For now we concentrate on KVM/QEMU */ 124 if (memcmp(&data->vm[0].cpi, cpi_kvm, sizeof(cpi_kvm))) { 125 report_skip("Not running under KVM/QEMU."); 126 goto out; 127 } 128 129 report(!memcmp(data->vm[0].uuid, uuid, sizeof(uuid)), "uuid"); 130 report(data->vm[0].conf_cpus == smp_query_num_cpus(), "cpu count configured"); 131 report(data->vm[0].total_cpus == 132 data->vm[0].reserved_cpus + data->vm[0].conf_cpus, 133 "cpu count total == conf + reserved"); 134 report(data->vm[0].standby_cpus == 0, "cpu count standby"); 135 report(!memcmp(data->vm[0].name, vm_name, sizeof(data->vm[0].name)), 136 "VM name == kvm-unit-test"); 137 138 if (data->vm[0].ext_name_encoding != 2) { 139 report_skip("Extended VM names are not UTF-8."); 140 goto out; 141 } 142 report(!memcmp(data->ext_names[0], vm_name_ext, sizeof(vm_name_ext)), 143 "ext VM name == kvm-unit-test"); 144 145 out: 146 report_prefix_pop(); 147 } 148 149 int main(void) 150 { 151 report_prefix_push("stsi"); 152 test_priv(); 153 test_specs(); 154 test_fc(); 155 test_3_2_2(); 156 return report_summary(); 157 } 158