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