no-vgic-v3.c 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177
  1. // SPDX-License-Identifier: GPL-2.0
  2. // Check that, on a GICv3 system, not configuring GICv3 correctly
  3. // results in all of the sysregs generating an UNDEF exception.
  4. #include <test_util.h>
  5. #include <kvm_util.h>
  6. #include <processor.h>
  7. static volatile bool handled;
  8. #define __check_sr_read(r) \
  9. ({ \
  10. uint64_t val; \
  11. \
  12. handled = false; \
  13. dsb(sy); \
  14. val = read_sysreg_s(SYS_ ## r); \
  15. val; \
  16. })
  17. #define __check_sr_write(r) \
  18. do { \
  19. handled = false; \
  20. dsb(sy); \
  21. write_sysreg_s(0, SYS_ ## r); \
  22. isb(); \
  23. } while(0)
  24. /* Fatal checks */
  25. #define check_sr_read(r) \
  26. do { \
  27. __check_sr_read(r); \
  28. __GUEST_ASSERT(handled, #r " no read trap"); \
  29. } while(0)
  30. #define check_sr_write(r) \
  31. do { \
  32. __check_sr_write(r); \
  33. __GUEST_ASSERT(handled, #r " no write trap"); \
  34. } while(0)
  35. #define check_sr_rw(r) \
  36. do { \
  37. check_sr_read(r); \
  38. check_sr_write(r); \
  39. } while(0)
  40. static void guest_code(void)
  41. {
  42. uint64_t val;
  43. /*
  44. * Check that we advertise that ID_AA64PFR0_EL1.GIC == 0, having
  45. * hidden the feature at runtime without any other userspace action.
  46. */
  47. __GUEST_ASSERT(FIELD_GET(ID_AA64PFR0_EL1_GIC,
  48. read_sysreg(id_aa64pfr0_el1)) == 0,
  49. "GICv3 wrongly advertised");
  50. /*
  51. * Access all GICv3 registers, and fail if we don't get an UNDEF.
  52. * Note that we happily access all the APxRn registers without
  53. * checking their existance, as all we want to see is a failure.
  54. */
  55. check_sr_rw(ICC_PMR_EL1);
  56. check_sr_read(ICC_IAR0_EL1);
  57. check_sr_write(ICC_EOIR0_EL1);
  58. check_sr_rw(ICC_HPPIR0_EL1);
  59. check_sr_rw(ICC_BPR0_EL1);
  60. check_sr_rw(ICC_AP0R0_EL1);
  61. check_sr_rw(ICC_AP0R1_EL1);
  62. check_sr_rw(ICC_AP0R2_EL1);
  63. check_sr_rw(ICC_AP0R3_EL1);
  64. check_sr_rw(ICC_AP1R0_EL1);
  65. check_sr_rw(ICC_AP1R1_EL1);
  66. check_sr_rw(ICC_AP1R2_EL1);
  67. check_sr_rw(ICC_AP1R3_EL1);
  68. check_sr_write(ICC_DIR_EL1);
  69. check_sr_read(ICC_RPR_EL1);
  70. check_sr_write(ICC_SGI1R_EL1);
  71. check_sr_write(ICC_ASGI1R_EL1);
  72. check_sr_write(ICC_SGI0R_EL1);
  73. check_sr_read(ICC_IAR1_EL1);
  74. check_sr_write(ICC_EOIR1_EL1);
  75. check_sr_rw(ICC_HPPIR1_EL1);
  76. check_sr_rw(ICC_BPR1_EL1);
  77. check_sr_rw(ICC_CTLR_EL1);
  78. check_sr_rw(ICC_IGRPEN0_EL1);
  79. check_sr_rw(ICC_IGRPEN1_EL1);
  80. /*
  81. * ICC_SRE_EL1 may not be trappable, as ICC_SRE_EL2.Enable can
  82. * be RAO/WI. Engage in non-fatal accesses, starting with a
  83. * write of 0 to try and disable SRE, and let's see if it
  84. * sticks.
  85. */
  86. __check_sr_write(ICC_SRE_EL1);
  87. if (!handled)
  88. GUEST_PRINTF("ICC_SRE_EL1 write not trapping (OK)\n");
  89. val = __check_sr_read(ICC_SRE_EL1);
  90. if (!handled) {
  91. __GUEST_ASSERT((val & BIT(0)),
  92. "ICC_SRE_EL1 not trapped but ICC_SRE_EL1.SRE not set\n");
  93. GUEST_PRINTF("ICC_SRE_EL1 read not trapping (OK)\n");
  94. }
  95. GUEST_DONE();
  96. }
  97. static void guest_undef_handler(struct ex_regs *regs)
  98. {
  99. /* Success, we've gracefully exploded! */
  100. handled = true;
  101. regs->pc += 4;
  102. }
  103. static void test_run_vcpu(struct kvm_vcpu *vcpu)
  104. {
  105. struct ucall uc;
  106. do {
  107. vcpu_run(vcpu);
  108. switch (get_ucall(vcpu, &uc)) {
  109. case UCALL_ABORT:
  110. REPORT_GUEST_ASSERT(uc);
  111. break;
  112. case UCALL_PRINTF:
  113. printf("%s", uc.buffer);
  114. break;
  115. case UCALL_DONE:
  116. break;
  117. default:
  118. TEST_FAIL("Unknown ucall %lu", uc.cmd);
  119. }
  120. } while (uc.cmd != UCALL_DONE);
  121. }
  122. static void test_guest_no_gicv3(void)
  123. {
  124. struct kvm_vcpu *vcpu;
  125. struct kvm_vm *vm;
  126. /* Create a VM without a GICv3 */
  127. vm = vm_create_with_one_vcpu(&vcpu, guest_code);
  128. vm_init_descriptor_tables(vm);
  129. vcpu_init_descriptor_tables(vcpu);
  130. vm_install_sync_handler(vm, VECTOR_SYNC_CURRENT,
  131. ESR_ELx_EC_UNKNOWN, guest_undef_handler);
  132. test_run_vcpu(vcpu);
  133. kvm_vm_free(vm);
  134. }
  135. int main(int argc, char *argv[])
  136. {
  137. struct kvm_vcpu *vcpu;
  138. struct kvm_vm *vm;
  139. uint64_t pfr0;
  140. test_disable_default_vgic();
  141. vm = vm_create_with_one_vcpu(&vcpu, NULL);
  142. pfr0 = vcpu_get_reg(vcpu, KVM_ARM64_SYS_REG(SYS_ID_AA64PFR0_EL1));
  143. __TEST_REQUIRE(FIELD_GET(ID_AA64PFR0_EL1_GIC, pfr0),
  144. "GICv3 not supported.");
  145. kvm_vm_free(vm);
  146. test_guest_no_gicv3();
  147. return 0;
  148. }