at.c 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166
  1. // SPDX-License-Identifier: GPL-2.0-only
  2. /*
  3. * at - Test for KVM's AT emulation in the EL2&0 and EL1&0 translation regimes.
  4. */
  5. #include "kvm_util.h"
  6. #include "processor.h"
  7. #include "test_util.h"
  8. #include "ucall.h"
  9. #include <asm/sysreg.h>
  10. #define TEST_ADDR 0x80000000
  11. enum {
  12. CLEAR_ACCESS_FLAG,
  13. TEST_ACCESS_FLAG,
  14. };
  15. static u64 *ptep_hva;
  16. #define copy_el2_to_el1(reg) \
  17. write_sysreg_s(read_sysreg_s(SYS_##reg##_EL1), SYS_##reg##_EL12)
  18. /* Yes, this is an ugly hack */
  19. #define __at(op, addr) write_sysreg_s(addr, op)
  20. #define test_at_insn(op, expect_fault) \
  21. do { \
  22. u64 par, fsc; \
  23. bool fault; \
  24. \
  25. GUEST_SYNC(CLEAR_ACCESS_FLAG); \
  26. \
  27. __at(OP_AT_##op, TEST_ADDR); \
  28. isb(); \
  29. par = read_sysreg(par_el1); \
  30. \
  31. fault = par & SYS_PAR_EL1_F; \
  32. fsc = FIELD_GET(SYS_PAR_EL1_FST, par); \
  33. \
  34. __GUEST_ASSERT((expect_fault) == fault, \
  35. "AT "#op": %sexpected fault (par: %lx)1", \
  36. (expect_fault) ? "" : "un", par); \
  37. if ((expect_fault)) { \
  38. __GUEST_ASSERT(fsc == ESR_ELx_FSC_ACCESS_L(3), \
  39. "AT "#op": expected access flag fault (par: %lx)", \
  40. par); \
  41. } else { \
  42. GUEST_ASSERT_EQ(FIELD_GET(SYS_PAR_EL1_ATTR, par), MAIR_ATTR_NORMAL); \
  43. GUEST_ASSERT_EQ(FIELD_GET(SYS_PAR_EL1_SH, par), PTE_SHARED >> 8); \
  44. GUEST_ASSERT_EQ(par & SYS_PAR_EL1_PA, TEST_ADDR); \
  45. GUEST_SYNC(TEST_ACCESS_FLAG); \
  46. } \
  47. } while (0)
  48. static void test_at(bool expect_fault)
  49. {
  50. test_at_insn(S1E2R, expect_fault);
  51. test_at_insn(S1E2W, expect_fault);
  52. /* Reuse the stage-1 MMU context from EL2 at EL1 */
  53. copy_el2_to_el1(SCTLR);
  54. copy_el2_to_el1(MAIR);
  55. copy_el2_to_el1(TCR);
  56. copy_el2_to_el1(TTBR0);
  57. copy_el2_to_el1(TTBR1);
  58. /* Disable stage-2 translation and enter a non-host context */
  59. write_sysreg(0, vtcr_el2);
  60. write_sysreg(0, vttbr_el2);
  61. sysreg_clear_set(hcr_el2, HCR_EL2_TGE | HCR_EL2_VM, 0);
  62. isb();
  63. test_at_insn(S1E1R, expect_fault);
  64. test_at_insn(S1E1W, expect_fault);
  65. }
  66. static void guest_code(void)
  67. {
  68. sysreg_clear_set(tcr_el1, TCR_HA, 0);
  69. isb();
  70. test_at(true);
  71. if (!SYS_FIELD_GET(ID_AA64MMFR1_EL1, HAFDBS, read_sysreg(id_aa64mmfr1_el1)))
  72. GUEST_DONE();
  73. /*
  74. * KVM's software PTW makes the implementation choice that the AT
  75. * instruction sets the access flag.
  76. */
  77. sysreg_clear_set(tcr_el1, 0, TCR_HA);
  78. isb();
  79. test_at(false);
  80. GUEST_DONE();
  81. }
  82. static void handle_sync(struct kvm_vcpu *vcpu, struct ucall *uc)
  83. {
  84. switch (uc->args[1]) {
  85. case CLEAR_ACCESS_FLAG:
  86. /*
  87. * Delete + reinstall the memslot to invalidate stage-2
  88. * mappings of the stage-1 page tables, forcing KVM to
  89. * use the 'slow' AT emulation path.
  90. *
  91. * This and clearing the access flag from host userspace
  92. * ensures that the access flag cannot be set speculatively
  93. * and is reliably cleared at the time of the AT instruction.
  94. */
  95. clear_bit(__ffs(PTE_AF), ptep_hva);
  96. vm_mem_region_reload(vcpu->vm, vcpu->vm->memslots[MEM_REGION_PT]);
  97. break;
  98. case TEST_ACCESS_FLAG:
  99. TEST_ASSERT(test_bit(__ffs(PTE_AF), ptep_hva),
  100. "Expected access flag to be set (desc: %lu)", *ptep_hva);
  101. break;
  102. default:
  103. TEST_FAIL("Unexpected SYNC arg: %lu", uc->args[1]);
  104. }
  105. }
  106. static void run_test(struct kvm_vcpu *vcpu)
  107. {
  108. struct ucall uc;
  109. while (true) {
  110. vcpu_run(vcpu);
  111. switch (get_ucall(vcpu, &uc)) {
  112. case UCALL_DONE:
  113. return;
  114. case UCALL_SYNC:
  115. handle_sync(vcpu, &uc);
  116. continue;
  117. case UCALL_ABORT:
  118. REPORT_GUEST_ASSERT(uc);
  119. return;
  120. default:
  121. TEST_FAIL("Unexpected ucall: %lu", uc.cmd);
  122. }
  123. }
  124. }
  125. int main(void)
  126. {
  127. struct kvm_vcpu_init init;
  128. struct kvm_vcpu *vcpu;
  129. struct kvm_vm *vm;
  130. TEST_REQUIRE(kvm_check_cap(KVM_CAP_ARM_EL2));
  131. vm = vm_create(1);
  132. kvm_get_default_vcpu_target(vm, &init);
  133. init.features[0] |= BIT(KVM_ARM_VCPU_HAS_EL2);
  134. vcpu = aarch64_vcpu_add(vm, 0, &init, guest_code);
  135. kvm_arch_vm_finalize_vcpus(vm);
  136. virt_map(vm, TEST_ADDR, TEST_ADDR, 1);
  137. ptep_hva = virt_get_pte_hva_at_level(vm, TEST_ADDR, 3);
  138. run_test(vcpu);
  139. kvm_vm_free(vm);
  140. return 0;
  141. }