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 void test_fc(void) 75 { 76 report(stsi(pagebuf, 7, 0, 0) == 3, "invalid fc"); 77 report(stsi(pagebuf, 1, 0, 1) == 3, "invalid selector 1"); 78 report(stsi(pagebuf, 1, 1, 0) == 3, "invalid selector 2"); 79 report(stsi_get_fc() >= 2, "query fc >= 2"); 80 } 81 82 static void test_3_2_2(void) 83 { 84 int rc; 85 /* EBCDIC for "kvm-unit" */ 86 const uint8_t vm_name[] = { 0x92, 0xa5, 0x94, 0x60, 0xa4, 0x95, 0x89, 87 0xa3 }; 88 const uint8_t uuid[] = { 0x0f, 0xb8, 0x4a, 0x86, 0x72, 0x7c, 89 0x11, 0xea, 0xbc, 0x55, 0x02, 0x42, 0xac, 0x13, 90 0x00, 0x03 }; 91 /* EBCDIC for "KVM/" */ 92 const uint8_t cpi_kvm[] = { 0xd2, 0xe5, 0xd4, 0x61 }; 93 const char vm_name_ext[] = "kvm-unit-test"; 94 struct stsi_322 *data = (void *)pagebuf; 95 96 report_prefix_push("3.2.2"); 97 98 /* Is the function code available at all? */ 99 if (stsi_get_fc() < 3) { 100 report_skip("Running under lpar, no level 3 to test."); 101 goto out; 102 } 103 104 rc = stsi(pagebuf, 3, 2, 2); 105 report(!rc, "call"); 106 107 /* For now we concentrate on KVM/QEMU */ 108 if (memcmp(&data->vm[0].cpi, cpi_kvm, sizeof(cpi_kvm))) { 109 report_skip("Not running under KVM/QEMU."); 110 goto out; 111 } 112 113 report(!memcmp(data->vm[0].uuid, uuid, sizeof(uuid)), "uuid"); 114 report(data->vm[0].conf_cpus == smp_query_num_cpus(), "cpu count configured"); 115 report(data->vm[0].total_cpus == 116 data->vm[0].reserved_cpus + data->vm[0].conf_cpus, 117 "cpu count total == conf + reserved"); 118 report(data->vm[0].standby_cpus == 0, "cpu count standby"); 119 report(!memcmp(data->vm[0].name, vm_name, sizeof(data->vm[0].name)), 120 "VM name == kvm-unit-test"); 121 122 if (data->vm[0].ext_name_encoding != 2) { 123 report_skip("Extended VM names are not UTF-8."); 124 goto out; 125 } 126 report(!memcmp(data->ext_names[0], vm_name_ext, sizeof(vm_name_ext)), 127 "ext VM name == kvm-unit-test"); 128 129 out: 130 report_prefix_pop(); 131 } 132 133 int main(void) 134 { 135 report_prefix_push("stsi"); 136 test_priv(); 137 test_specs(); 138 test_fc(); 139 test_3_2_2(); 140 return report_summary(); 141 } 142