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 <bitops.h> 13 #include <asm/page.h> 14 #include <asm/asm-offsets.h> 15 #include <asm/interrupt.h> 16 #include <smp.h> 17 #include <stsi.h> 18 19 static uint8_t pagebuf[PAGE_SIZE * 2] __attribute__((aligned(PAGE_SIZE * 2))); 20 21 static void test_specs(void) 22 { 23 int i; 24 int cc; 25 26 report_prefix_push("specification"); 27 28 for (i = 36; i <= 55; i++) { 29 report_prefix_pushf("set invalid r0 bit %d", i); 30 expect_pgm_int(); 31 stsi(pagebuf, 0, BIT(63 - i), 0); 32 check_pgm_int_code(PGM_INT_CODE_SPECIFICATION); 33 report_prefix_pop(); 34 } 35 36 for (i = 32; i <= 47; i++) { 37 report_prefix_pushf("set invalid r1 bit %d", i); 38 expect_pgm_int(); 39 stsi(pagebuf, 1, 0, BIT(63 - i)); 40 check_pgm_int_code(PGM_INT_CODE_SPECIFICATION); 41 report_prefix_pop(); 42 } 43 44 for (i = 0; i < 32; i++) { 45 report_prefix_pushf("r0 bit %d ignored", i); 46 cc = stsi(pagebuf, 3, 2 | BIT(63 - i), 2); 47 report(!cc, "CC = 0"); 48 report_prefix_pop(); 49 } 50 51 for (i = 0; i < 32; i++) { 52 report_prefix_pushf("r1 bit %d ignored", i); 53 cc = stsi(pagebuf, 3, 2, 2 | BIT(63 - i)); 54 report(!cc, "CC = 0"); 55 report_prefix_pop(); 56 } 57 58 report_prefix_push("unaligned"); 59 expect_pgm_int(); 60 stsi(pagebuf + 42, 1, 1, 1); 61 check_pgm_int_code(PGM_INT_CODE_SPECIFICATION); 62 report_prefix_pop(); 63 64 report_prefix_pop(); 65 } 66 67 static void test_priv(void) 68 { 69 report_prefix_push("privileged"); 70 expect_pgm_int(); 71 enter_pstate(); 72 stsi(pagebuf, 0, 0, 0); 73 check_pgm_int_code(PGM_INT_CODE_PRIVILEGED_OPERATION); 74 report_prefix_pop(); 75 } 76 77 static void test_fc(void) 78 { 79 report(stsi(pagebuf, 7, 0, 0) == 3, "invalid fc"); 80 report(stsi(pagebuf, 1, 0, 1) == 3, "invalid selector 1"); 81 report(stsi(pagebuf, 1, 1, 0) == 3, "invalid selector 2"); 82 report(stsi_get_fc() >= 2, "query fc >= 2"); 83 } 84 85 static void test_3_2_2(void) 86 { 87 int rc; 88 /* EBCDIC for "kvm-unit" */ 89 const uint8_t vm_name[] = { 0x92, 0xa5, 0x94, 0x60, 0xa4, 0x95, 0x89, 90 0xa3 }; 91 const uint8_t uuid[] = { 0x0f, 0xb8, 0x4a, 0x86, 0x72, 0x7c, 92 0x11, 0xea, 0xbc, 0x55, 0x02, 0x42, 0xac, 0x13, 93 0x00, 0x03 }; 94 /* EBCDIC for "KVM/" */ 95 const uint8_t cpi_kvm[] = { 0xd2, 0xe5, 0xd4, 0x61 }; 96 const char vm_name_ext[] = "kvm-unit-test"; 97 struct sysinfo_3_2_2 *data = (void *)pagebuf; 98 99 report_prefix_push("3.2.2"); 100 101 /* Is the function code available at all? */ 102 if (stsi_get_fc() < 3) { 103 report_skip("Running under lpar, no level 3 to test."); 104 goto out; 105 } 106 107 rc = stsi(pagebuf, 3, 2, 2); 108 report(!rc, "call"); 109 110 /* For now we concentrate on KVM/QEMU */ 111 if (memcmp(&data->vm[0].cpi, cpi_kvm, sizeof(cpi_kvm))) { 112 report_skip("Not running under KVM/QEMU."); 113 goto out; 114 } 115 116 report(!memcmp(data->vm[0].uuid, uuid, sizeof(uuid)), "uuid"); 117 report(data->vm[0].conf_cpus == smp_query_num_cpus(), "cpu count configured"); 118 report(data->vm[0].total_cpus == 119 data->vm[0].reserved_cpus + data->vm[0].conf_cpus, 120 "cpu count total == conf + reserved"); 121 report(data->vm[0].standby_cpus == 0, "cpu count standby"); 122 report(!memcmp(data->vm[0].name, vm_name, sizeof(data->vm[0].name)), 123 "VM name == kvm-unit-test"); 124 125 if (data->vm[0].ext_name_encoding != 2) { 126 report_skip("Extended VM names are not UTF-8."); 127 goto out; 128 } 129 report(!memcmp(data->ext_names[0], vm_name_ext, sizeof(vm_name_ext)), 130 "ext VM name == kvm-unit-test"); 131 132 out: 133 report_prefix_pop(); 134 } 135 136 int main(void) 137 { 138 report_prefix_push("stsi"); 139 test_priv(); 140 test_specs(); 141 test_fc(); 142 test_3_2_2(); 143 return report_summary(); 144 } 145