Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

KVM: arm64: selftests: Add no-vgic-v5 selftest

Now that GICv5 is supported, it is important to check that all of the
GICv5 register state is hidden from a guest that doesn't create a
vGICv5.

Rename the no-vgic-v3 selftest to no-vgic, and extend it to check
GICv5 system registers too.

Signed-off-by: Sascha Bischoff <sascha.bischoff@arm.com>
Link: https://patch.msgid.link/20260319154937.3619520-42-sascha.bischoff@arm.com
Signed-off-by: Marc Zyngier <maz@kernel.org>

authored by

Sascha Bischoff and committed by
Marc Zyngier
ce29261e 0a9f38bf

+298 -178
+1 -1
tools/testing/selftests/kvm/Makefile.kvm
··· 179 179 TEST_GEN_PROGS_arm64 += arm64/vgic_lpi_stress 180 180 TEST_GEN_PROGS_arm64 += arm64/vgic_v5 181 181 TEST_GEN_PROGS_arm64 += arm64/vpmu_counter_access 182 - TEST_GEN_PROGS_arm64 += arm64/no-vgic-v3 182 + TEST_GEN_PROGS_arm64 += arm64/no-vgic 183 183 TEST_GEN_PROGS_arm64 += arm64/idreg-idst 184 184 TEST_GEN_PROGS_arm64 += arm64/kvm-uuid 185 185 TEST_GEN_PROGS_arm64 += access_tracking_perf_test
-177
tools/testing/selftests/kvm/arm64/no-vgic-v3.c
··· 1 - // SPDX-License-Identifier: GPL-2.0 2 - 3 - // Check that, on a GICv3 system, not configuring GICv3 correctly 4 - // results in all of the sysregs generating an UNDEF exception. 5 - 6 - #include <test_util.h> 7 - #include <kvm_util.h> 8 - #include <processor.h> 9 - 10 - static volatile bool handled; 11 - 12 - #define __check_sr_read(r) \ 13 - ({ \ 14 - uint64_t val; \ 15 - \ 16 - handled = false; \ 17 - dsb(sy); \ 18 - val = read_sysreg_s(SYS_ ## r); \ 19 - val; \ 20 - }) 21 - 22 - #define __check_sr_write(r) \ 23 - do { \ 24 - handled = false; \ 25 - dsb(sy); \ 26 - write_sysreg_s(0, SYS_ ## r); \ 27 - isb(); \ 28 - } while(0) 29 - 30 - /* Fatal checks */ 31 - #define check_sr_read(r) \ 32 - do { \ 33 - __check_sr_read(r); \ 34 - __GUEST_ASSERT(handled, #r " no read trap"); \ 35 - } while(0) 36 - 37 - #define check_sr_write(r) \ 38 - do { \ 39 - __check_sr_write(r); \ 40 - __GUEST_ASSERT(handled, #r " no write trap"); \ 41 - } while(0) 42 - 43 - #define check_sr_rw(r) \ 44 - do { \ 45 - check_sr_read(r); \ 46 - check_sr_write(r); \ 47 - } while(0) 48 - 49 - static void guest_code(void) 50 - { 51 - uint64_t val; 52 - 53 - /* 54 - * Check that we advertise that ID_AA64PFR0_EL1.GIC == 0, having 55 - * hidden the feature at runtime without any other userspace action. 56 - */ 57 - __GUEST_ASSERT(FIELD_GET(ID_AA64PFR0_EL1_GIC, 58 - read_sysreg(id_aa64pfr0_el1)) == 0, 59 - "GICv3 wrongly advertised"); 60 - 61 - /* 62 - * Access all GICv3 registers, and fail if we don't get an UNDEF. 63 - * Note that we happily access all the APxRn registers without 64 - * checking their existance, as all we want to see is a failure. 65 - */ 66 - check_sr_rw(ICC_PMR_EL1); 67 - check_sr_read(ICC_IAR0_EL1); 68 - check_sr_write(ICC_EOIR0_EL1); 69 - check_sr_rw(ICC_HPPIR0_EL1); 70 - check_sr_rw(ICC_BPR0_EL1); 71 - check_sr_rw(ICC_AP0R0_EL1); 72 - check_sr_rw(ICC_AP0R1_EL1); 73 - check_sr_rw(ICC_AP0R2_EL1); 74 - check_sr_rw(ICC_AP0R3_EL1); 75 - check_sr_rw(ICC_AP1R0_EL1); 76 - check_sr_rw(ICC_AP1R1_EL1); 77 - check_sr_rw(ICC_AP1R2_EL1); 78 - check_sr_rw(ICC_AP1R3_EL1); 79 - check_sr_write(ICC_DIR_EL1); 80 - check_sr_read(ICC_RPR_EL1); 81 - check_sr_write(ICC_SGI1R_EL1); 82 - check_sr_write(ICC_ASGI1R_EL1); 83 - check_sr_write(ICC_SGI0R_EL1); 84 - check_sr_read(ICC_IAR1_EL1); 85 - check_sr_write(ICC_EOIR1_EL1); 86 - check_sr_rw(ICC_HPPIR1_EL1); 87 - check_sr_rw(ICC_BPR1_EL1); 88 - check_sr_rw(ICC_CTLR_EL1); 89 - check_sr_rw(ICC_IGRPEN0_EL1); 90 - check_sr_rw(ICC_IGRPEN1_EL1); 91 - 92 - /* 93 - * ICC_SRE_EL1 may not be trappable, as ICC_SRE_EL2.Enable can 94 - * be RAO/WI. Engage in non-fatal accesses, starting with a 95 - * write of 0 to try and disable SRE, and let's see if it 96 - * sticks. 97 - */ 98 - __check_sr_write(ICC_SRE_EL1); 99 - if (!handled) 100 - GUEST_PRINTF("ICC_SRE_EL1 write not trapping (OK)\n"); 101 - 102 - val = __check_sr_read(ICC_SRE_EL1); 103 - if (!handled) { 104 - __GUEST_ASSERT((val & BIT(0)), 105 - "ICC_SRE_EL1 not trapped but ICC_SRE_EL1.SRE not set\n"); 106 - GUEST_PRINTF("ICC_SRE_EL1 read not trapping (OK)\n"); 107 - } 108 - 109 - GUEST_DONE(); 110 - } 111 - 112 - static void guest_undef_handler(struct ex_regs *regs) 113 - { 114 - /* Success, we've gracefully exploded! */ 115 - handled = true; 116 - regs->pc += 4; 117 - } 118 - 119 - static void test_run_vcpu(struct kvm_vcpu *vcpu) 120 - { 121 - struct ucall uc; 122 - 123 - do { 124 - vcpu_run(vcpu); 125 - 126 - switch (get_ucall(vcpu, &uc)) { 127 - case UCALL_ABORT: 128 - REPORT_GUEST_ASSERT(uc); 129 - break; 130 - case UCALL_PRINTF: 131 - printf("%s", uc.buffer); 132 - break; 133 - case UCALL_DONE: 134 - break; 135 - default: 136 - TEST_FAIL("Unknown ucall %lu", uc.cmd); 137 - } 138 - } while (uc.cmd != UCALL_DONE); 139 - } 140 - 141 - static void test_guest_no_gicv3(void) 142 - { 143 - struct kvm_vcpu *vcpu; 144 - struct kvm_vm *vm; 145 - 146 - /* Create a VM without a GICv3 */ 147 - vm = vm_create_with_one_vcpu(&vcpu, guest_code); 148 - 149 - vm_init_descriptor_tables(vm); 150 - vcpu_init_descriptor_tables(vcpu); 151 - 152 - vm_install_sync_handler(vm, VECTOR_SYNC_CURRENT, 153 - ESR_ELx_EC_UNKNOWN, guest_undef_handler); 154 - 155 - test_run_vcpu(vcpu); 156 - 157 - kvm_vm_free(vm); 158 - } 159 - 160 - int main(int argc, char *argv[]) 161 - { 162 - struct kvm_vcpu *vcpu; 163 - struct kvm_vm *vm; 164 - uint64_t pfr0; 165 - 166 - test_disable_default_vgic(); 167 - 168 - vm = vm_create_with_one_vcpu(&vcpu, NULL); 169 - pfr0 = vcpu_get_reg(vcpu, KVM_ARM64_SYS_REG(SYS_ID_AA64PFR0_EL1)); 170 - __TEST_REQUIRE(FIELD_GET(ID_AA64PFR0_EL1_GIC, pfr0), 171 - "GICv3 not supported."); 172 - kvm_vm_free(vm); 173 - 174 - test_guest_no_gicv3(); 175 - 176 - return 0; 177 - }
+297
tools/testing/selftests/kvm/arm64/no-vgic.c
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + 3 + // Check that, on a GICv3-capable system (GICv3 native, or GICv5 with 4 + // FEAT_GCIE_LEGACY), not configuring GICv3 correctly results in all 5 + // of the sysregs generating an UNDEF exception. Do the same for GICv5 6 + // on a GICv5 host. 7 + 8 + #include <test_util.h> 9 + #include <kvm_util.h> 10 + #include <processor.h> 11 + 12 + #include <arm64/gic_v5.h> 13 + 14 + static volatile bool handled; 15 + 16 + #define __check_sr_read(r) \ 17 + ({ \ 18 + uint64_t val; \ 19 + \ 20 + handled = false; \ 21 + dsb(sy); \ 22 + val = read_sysreg_s(SYS_ ## r); \ 23 + val; \ 24 + }) 25 + 26 + #define __check_sr_write(r) \ 27 + do { \ 28 + handled = false; \ 29 + dsb(sy); \ 30 + write_sysreg_s(0, SYS_ ## r); \ 31 + isb(); \ 32 + } while (0) 33 + 34 + #define __check_gicv5_gicr_op(r) \ 35 + ({ \ 36 + uint64_t val; \ 37 + \ 38 + handled = false; \ 39 + dsb(sy); \ 40 + val = read_sysreg_s(GICV5_OP_GICR_ ## r); \ 41 + val; \ 42 + }) 43 + 44 + #define __check_gicv5_gic_op(r) \ 45 + do { \ 46 + handled = false; \ 47 + dsb(sy); \ 48 + write_sysreg_s(0, GICV5_OP_GIC_ ## r); \ 49 + isb(); \ 50 + } while (0) 51 + 52 + /* Fatal checks */ 53 + #define check_sr_read(r) \ 54 + do { \ 55 + __check_sr_read(r); \ 56 + __GUEST_ASSERT(handled, #r " no read trap"); \ 57 + } while (0) 58 + 59 + #define check_sr_write(r) \ 60 + do { \ 61 + __check_sr_write(r); \ 62 + __GUEST_ASSERT(handled, #r " no write trap"); \ 63 + } while (0) 64 + 65 + #define check_sr_rw(r) \ 66 + do { \ 67 + check_sr_read(r); \ 68 + check_sr_write(r); \ 69 + } while (0) 70 + 71 + #define check_gicv5_gicr_op(r) \ 72 + do { \ 73 + __check_gicv5_gicr_op(r); \ 74 + __GUEST_ASSERT(handled, #r " no read trap"); \ 75 + } while (0) 76 + 77 + #define check_gicv5_gic_op(r) \ 78 + do { \ 79 + __check_gicv5_gic_op(r); \ 80 + __GUEST_ASSERT(handled, #r " no write trap"); \ 81 + } while (0) 82 + 83 + static void guest_code_gicv3(void) 84 + { 85 + uint64_t val; 86 + 87 + /* 88 + * Check that we advertise that ID_AA64PFR0_EL1.GIC == 0, having 89 + * hidden the feature at runtime without any other userspace action. 90 + */ 91 + __GUEST_ASSERT(FIELD_GET(ID_AA64PFR0_EL1_GIC, 92 + read_sysreg(id_aa64pfr0_el1)) == 0, 93 + "GICv3 wrongly advertised"); 94 + 95 + /* 96 + * Access all GICv3 registers, and fail if we don't get an UNDEF. 97 + * Note that we happily access all the APxRn registers without 98 + * checking their existence, as all we want to see is a failure. 99 + */ 100 + check_sr_rw(ICC_PMR_EL1); 101 + check_sr_read(ICC_IAR0_EL1); 102 + check_sr_write(ICC_EOIR0_EL1); 103 + check_sr_rw(ICC_HPPIR0_EL1); 104 + check_sr_rw(ICC_BPR0_EL1); 105 + check_sr_rw(ICC_AP0R0_EL1); 106 + check_sr_rw(ICC_AP0R1_EL1); 107 + check_sr_rw(ICC_AP0R2_EL1); 108 + check_sr_rw(ICC_AP0R3_EL1); 109 + check_sr_rw(ICC_AP1R0_EL1); 110 + check_sr_rw(ICC_AP1R1_EL1); 111 + check_sr_rw(ICC_AP1R2_EL1); 112 + check_sr_rw(ICC_AP1R3_EL1); 113 + check_sr_write(ICC_DIR_EL1); 114 + check_sr_read(ICC_RPR_EL1); 115 + check_sr_write(ICC_SGI1R_EL1); 116 + check_sr_write(ICC_ASGI1R_EL1); 117 + check_sr_write(ICC_SGI0R_EL1); 118 + check_sr_read(ICC_IAR1_EL1); 119 + check_sr_write(ICC_EOIR1_EL1); 120 + check_sr_rw(ICC_HPPIR1_EL1); 121 + check_sr_rw(ICC_BPR1_EL1); 122 + check_sr_rw(ICC_CTLR_EL1); 123 + check_sr_rw(ICC_IGRPEN0_EL1); 124 + check_sr_rw(ICC_IGRPEN1_EL1); 125 + 126 + /* 127 + * ICC_SRE_EL1 may not be trappable, as ICC_SRE_EL2.Enable can 128 + * be RAO/WI. Engage in non-fatal accesses, starting with a 129 + * write of 0 to try and disable SRE, and let's see if it 130 + * sticks. 131 + */ 132 + __check_sr_write(ICC_SRE_EL1); 133 + if (!handled) 134 + GUEST_PRINTF("ICC_SRE_EL1 write not trapping (OK)\n"); 135 + 136 + val = __check_sr_read(ICC_SRE_EL1); 137 + if (!handled) { 138 + __GUEST_ASSERT((val & BIT(0)), 139 + "ICC_SRE_EL1 not trapped but ICC_SRE_EL1.SRE not set\n"); 140 + GUEST_PRINTF("ICC_SRE_EL1 read not trapping (OK)\n"); 141 + } 142 + 143 + GUEST_DONE(); 144 + } 145 + 146 + static void guest_code_gicv5(void) 147 + { 148 + /* 149 + * Check that we advertise that ID_AA64PFR2_EL1.GCIE == 0, having 150 + * hidden the feature at runtime without any other userspace action. 151 + */ 152 + __GUEST_ASSERT(FIELD_GET(ID_AA64PFR2_EL1_GCIE, 153 + read_sysreg_s(SYS_ID_AA64PFR2_EL1)) == 0, 154 + "GICv5 wrongly advertised"); 155 + 156 + /* 157 + * Try all GICv5 instructions, and fail if we don't get an UNDEF. 158 + */ 159 + check_gicv5_gic_op(CDAFF); 160 + check_gicv5_gic_op(CDDI); 161 + check_gicv5_gic_op(CDDIS); 162 + check_gicv5_gic_op(CDEOI); 163 + check_gicv5_gic_op(CDHM); 164 + check_gicv5_gic_op(CDPEND); 165 + check_gicv5_gic_op(CDPRI); 166 + check_gicv5_gic_op(CDRCFG); 167 + check_gicv5_gicr_op(CDIA); 168 + check_gicv5_gicr_op(CDNMIA); 169 + 170 + /* Check General System Register acccesses */ 171 + check_sr_rw(ICC_APR_EL1); 172 + check_sr_rw(ICC_CR0_EL1); 173 + check_sr_read(ICC_HPPIR_EL1); 174 + check_sr_read(ICC_IAFFIDR_EL1); 175 + check_sr_rw(ICC_ICSR_EL1); 176 + check_sr_read(ICC_IDR0_EL1); 177 + check_sr_rw(ICC_PCR_EL1); 178 + 179 + /* Check PPI System Register accessess */ 180 + check_sr_rw(ICC_PPI_CACTIVER0_EL1); 181 + check_sr_rw(ICC_PPI_CACTIVER1_EL1); 182 + check_sr_rw(ICC_PPI_SACTIVER0_EL1); 183 + check_sr_rw(ICC_PPI_SACTIVER1_EL1); 184 + check_sr_rw(ICC_PPI_CPENDR0_EL1); 185 + check_sr_rw(ICC_PPI_CPENDR1_EL1); 186 + check_sr_rw(ICC_PPI_SPENDR0_EL1); 187 + check_sr_rw(ICC_PPI_SPENDR1_EL1); 188 + check_sr_rw(ICC_PPI_ENABLER0_EL1); 189 + check_sr_rw(ICC_PPI_ENABLER1_EL1); 190 + check_sr_read(ICC_PPI_HMR0_EL1); 191 + check_sr_read(ICC_PPI_HMR1_EL1); 192 + check_sr_rw(ICC_PPI_PRIORITYR0_EL1); 193 + check_sr_rw(ICC_PPI_PRIORITYR1_EL1); 194 + check_sr_rw(ICC_PPI_PRIORITYR2_EL1); 195 + check_sr_rw(ICC_PPI_PRIORITYR3_EL1); 196 + check_sr_rw(ICC_PPI_PRIORITYR4_EL1); 197 + check_sr_rw(ICC_PPI_PRIORITYR5_EL1); 198 + check_sr_rw(ICC_PPI_PRIORITYR6_EL1); 199 + check_sr_rw(ICC_PPI_PRIORITYR7_EL1); 200 + check_sr_rw(ICC_PPI_PRIORITYR8_EL1); 201 + check_sr_rw(ICC_PPI_PRIORITYR9_EL1); 202 + check_sr_rw(ICC_PPI_PRIORITYR10_EL1); 203 + check_sr_rw(ICC_PPI_PRIORITYR11_EL1); 204 + check_sr_rw(ICC_PPI_PRIORITYR12_EL1); 205 + check_sr_rw(ICC_PPI_PRIORITYR13_EL1); 206 + check_sr_rw(ICC_PPI_PRIORITYR14_EL1); 207 + check_sr_rw(ICC_PPI_PRIORITYR15_EL1); 208 + 209 + GUEST_DONE(); 210 + } 211 + 212 + static void guest_undef_handler(struct ex_regs *regs) 213 + { 214 + /* Success, we've gracefully exploded! */ 215 + handled = true; 216 + regs->pc += 4; 217 + } 218 + 219 + static void test_run_vcpu(struct kvm_vcpu *vcpu) 220 + { 221 + struct ucall uc; 222 + 223 + do { 224 + vcpu_run(vcpu); 225 + 226 + switch (get_ucall(vcpu, &uc)) { 227 + case UCALL_ABORT: 228 + REPORT_GUEST_ASSERT(uc); 229 + break; 230 + case UCALL_PRINTF: 231 + printf("%s", uc.buffer); 232 + break; 233 + case UCALL_DONE: 234 + break; 235 + default: 236 + TEST_FAIL("Unknown ucall %lu", uc.cmd); 237 + } 238 + } while (uc.cmd != UCALL_DONE); 239 + } 240 + 241 + static void test_guest_no_vgic(void *guest_code) 242 + { 243 + struct kvm_vcpu *vcpu; 244 + struct kvm_vm *vm; 245 + 246 + /* Create a VM without a GIC */ 247 + vm = vm_create_with_one_vcpu(&vcpu, guest_code); 248 + 249 + vm_init_descriptor_tables(vm); 250 + vcpu_init_descriptor_tables(vcpu); 251 + 252 + vm_install_sync_handler(vm, VECTOR_SYNC_CURRENT, 253 + ESR_ELx_EC_UNKNOWN, guest_undef_handler); 254 + 255 + test_run_vcpu(vcpu); 256 + 257 + kvm_vm_free(vm); 258 + } 259 + 260 + int main(int argc, char *argv[]) 261 + { 262 + struct kvm_vcpu *vcpu; 263 + struct kvm_vm *vm; 264 + bool has_v3, has_v5; 265 + uint64_t pfr; 266 + 267 + test_disable_default_vgic(); 268 + 269 + vm = vm_create_with_one_vcpu(&vcpu, NULL); 270 + 271 + pfr = vcpu_get_reg(vcpu, KVM_ARM64_SYS_REG(SYS_ID_AA64PFR0_EL1)); 272 + has_v3 = !!FIELD_GET(ID_AA64PFR0_EL1_GIC, pfr); 273 + 274 + pfr = vcpu_get_reg(vcpu, KVM_ARM64_SYS_REG(SYS_ID_AA64PFR2_EL1)); 275 + has_v5 = !!FIELD_GET(ID_AA64PFR2_EL1_GCIE, pfr); 276 + 277 + kvm_vm_free(vm); 278 + 279 + __TEST_REQUIRE(has_v3 || has_v5, 280 + "Neither GICv3 nor GICv5 supported."); 281 + 282 + if (has_v3) { 283 + pr_info("Testing no-vgic-v3\n"); 284 + test_guest_no_vgic(guest_code_gicv3); 285 + } else { 286 + pr_info("No GICv3 support: skipping no-vgic-v3 test\n"); 287 + } 288 + 289 + if (has_v5) { 290 + pr_info("Testing no-vgic-v5\n"); 291 + test_guest_no_vgic(guest_code_gicv5); 292 + } else { 293 + pr_info("No GICv5 support: skipping no-vgic-v5 test\n"); 294 + } 295 + 296 + return 0; 297 + }