hypercalls.c 8.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313
  1. // SPDX-License-Identifier: GPL-2.0-only
  2. /* hypercalls: Check the ARM64's psuedo-firmware bitmap register interface.
  3. *
  4. * The test validates the basic hypercall functionalities that are exposed
  5. * via the psuedo-firmware bitmap register. This includes the registers'
  6. * read/write behavior before and after the VM has started, and if the
  7. * hypercalls are properly masked or unmasked to the guest when disabled or
  8. * enabled from the KVM userspace, respectively.
  9. */
  10. #include <errno.h>
  11. #include <linux/arm-smccc.h>
  12. #include <asm/kvm.h>
  13. #include <kvm_util.h>
  14. #include "processor.h"
  15. #define FW_REG_ULIMIT_VAL(max_feat_bit) (GENMASK(max_feat_bit, 0))
  16. /* Last valid bits of the bitmapped firmware registers */
  17. #define KVM_REG_ARM_STD_BMAP_BIT_MAX 0
  18. #define KVM_REG_ARM_STD_HYP_BMAP_BIT_MAX 0
  19. #define KVM_REG_ARM_VENDOR_HYP_BMAP_BIT_MAX 1
  20. struct kvm_fw_reg_info {
  21. uint64_t reg; /* Register definition */
  22. uint64_t max_feat_bit; /* Bit that represents the upper limit of the feature-map */
  23. };
  24. #define FW_REG_INFO(r) \
  25. { \
  26. .reg = r, \
  27. .max_feat_bit = r##_BIT_MAX, \
  28. }
  29. static const struct kvm_fw_reg_info fw_reg_info[] = {
  30. FW_REG_INFO(KVM_REG_ARM_STD_BMAP),
  31. FW_REG_INFO(KVM_REG_ARM_STD_HYP_BMAP),
  32. FW_REG_INFO(KVM_REG_ARM_VENDOR_HYP_BMAP),
  33. };
  34. enum test_stage {
  35. TEST_STAGE_REG_IFACE,
  36. TEST_STAGE_HVC_IFACE_FEAT_DISABLED,
  37. TEST_STAGE_HVC_IFACE_FEAT_ENABLED,
  38. TEST_STAGE_HVC_IFACE_FALSE_INFO,
  39. TEST_STAGE_END,
  40. };
  41. static int stage = TEST_STAGE_REG_IFACE;
  42. struct test_hvc_info {
  43. uint32_t func_id;
  44. uint64_t arg1;
  45. };
  46. #define TEST_HVC_INFO(f, a1) \
  47. { \
  48. .func_id = f, \
  49. .arg1 = a1, \
  50. }
  51. static const struct test_hvc_info hvc_info[] = {
  52. /* KVM_REG_ARM_STD_BMAP */
  53. TEST_HVC_INFO(ARM_SMCCC_TRNG_VERSION, 0),
  54. TEST_HVC_INFO(ARM_SMCCC_TRNG_FEATURES, ARM_SMCCC_TRNG_RND64),
  55. TEST_HVC_INFO(ARM_SMCCC_TRNG_GET_UUID, 0),
  56. TEST_HVC_INFO(ARM_SMCCC_TRNG_RND32, 0),
  57. TEST_HVC_INFO(ARM_SMCCC_TRNG_RND64, 0),
  58. /* KVM_REG_ARM_STD_HYP_BMAP */
  59. TEST_HVC_INFO(ARM_SMCCC_ARCH_FEATURES_FUNC_ID, ARM_SMCCC_HV_PV_TIME_FEATURES),
  60. TEST_HVC_INFO(ARM_SMCCC_HV_PV_TIME_FEATURES, ARM_SMCCC_HV_PV_TIME_ST),
  61. TEST_HVC_INFO(ARM_SMCCC_HV_PV_TIME_ST, 0),
  62. /* KVM_REG_ARM_VENDOR_HYP_BMAP */
  63. TEST_HVC_INFO(ARM_SMCCC_VENDOR_HYP_KVM_FEATURES_FUNC_ID,
  64. ARM_SMCCC_VENDOR_HYP_KVM_PTP_FUNC_ID),
  65. TEST_HVC_INFO(ARM_SMCCC_VENDOR_HYP_CALL_UID_FUNC_ID, 0),
  66. TEST_HVC_INFO(ARM_SMCCC_VENDOR_HYP_KVM_PTP_FUNC_ID, KVM_PTP_VIRT_COUNTER),
  67. };
  68. /* Feed false hypercall info to test the KVM behavior */
  69. static const struct test_hvc_info false_hvc_info[] = {
  70. /* Feature support check against a different family of hypercalls */
  71. TEST_HVC_INFO(ARM_SMCCC_TRNG_FEATURES, ARM_SMCCC_VENDOR_HYP_KVM_PTP_FUNC_ID),
  72. TEST_HVC_INFO(ARM_SMCCC_ARCH_FEATURES_FUNC_ID, ARM_SMCCC_TRNG_RND64),
  73. TEST_HVC_INFO(ARM_SMCCC_HV_PV_TIME_FEATURES, ARM_SMCCC_TRNG_RND64),
  74. };
  75. static void guest_test_hvc(const struct test_hvc_info *hc_info)
  76. {
  77. unsigned int i;
  78. struct arm_smccc_res res;
  79. unsigned int hvc_info_arr_sz;
  80. hvc_info_arr_sz =
  81. hc_info == hvc_info ? ARRAY_SIZE(hvc_info) : ARRAY_SIZE(false_hvc_info);
  82. for (i = 0; i < hvc_info_arr_sz; i++, hc_info++) {
  83. memset(&res, 0, sizeof(res));
  84. smccc_hvc(hc_info->func_id, hc_info->arg1, 0, 0, 0, 0, 0, 0, &res);
  85. switch (stage) {
  86. case TEST_STAGE_HVC_IFACE_FEAT_DISABLED:
  87. case TEST_STAGE_HVC_IFACE_FALSE_INFO:
  88. GUEST_ASSERT_3(res.a0 == SMCCC_RET_NOT_SUPPORTED,
  89. res.a0, hc_info->func_id, hc_info->arg1);
  90. break;
  91. case TEST_STAGE_HVC_IFACE_FEAT_ENABLED:
  92. GUEST_ASSERT_3(res.a0 != SMCCC_RET_NOT_SUPPORTED,
  93. res.a0, hc_info->func_id, hc_info->arg1);
  94. break;
  95. default:
  96. GUEST_ASSERT_1(0, stage);
  97. }
  98. }
  99. }
  100. static void guest_code(void)
  101. {
  102. while (stage != TEST_STAGE_END) {
  103. switch (stage) {
  104. case TEST_STAGE_REG_IFACE:
  105. break;
  106. case TEST_STAGE_HVC_IFACE_FEAT_DISABLED:
  107. case TEST_STAGE_HVC_IFACE_FEAT_ENABLED:
  108. guest_test_hvc(hvc_info);
  109. break;
  110. case TEST_STAGE_HVC_IFACE_FALSE_INFO:
  111. guest_test_hvc(false_hvc_info);
  112. break;
  113. default:
  114. GUEST_ASSERT_1(0, stage);
  115. }
  116. GUEST_SYNC(stage);
  117. }
  118. GUEST_DONE();
  119. }
  120. struct st_time {
  121. uint32_t rev;
  122. uint32_t attr;
  123. uint64_t st_time;
  124. };
  125. #define STEAL_TIME_SIZE ((sizeof(struct st_time) + 63) & ~63)
  126. #define ST_GPA_BASE (1 << 30)
  127. static void steal_time_init(struct kvm_vcpu *vcpu)
  128. {
  129. uint64_t st_ipa = (ulong)ST_GPA_BASE;
  130. unsigned int gpages;
  131. gpages = vm_calc_num_guest_pages(VM_MODE_DEFAULT, STEAL_TIME_SIZE);
  132. vm_userspace_mem_region_add(vcpu->vm, VM_MEM_SRC_ANONYMOUS, ST_GPA_BASE, 1, gpages, 0);
  133. vcpu_device_attr_set(vcpu, KVM_ARM_VCPU_PVTIME_CTRL,
  134. KVM_ARM_VCPU_PVTIME_IPA, &st_ipa);
  135. }
  136. static void test_fw_regs_before_vm_start(struct kvm_vcpu *vcpu)
  137. {
  138. uint64_t val;
  139. unsigned int i;
  140. int ret;
  141. for (i = 0; i < ARRAY_SIZE(fw_reg_info); i++) {
  142. const struct kvm_fw_reg_info *reg_info = &fw_reg_info[i];
  143. /* First 'read' should be an upper limit of the features supported */
  144. vcpu_get_reg(vcpu, reg_info->reg, &val);
  145. TEST_ASSERT(val == FW_REG_ULIMIT_VAL(reg_info->max_feat_bit),
  146. "Expected all the features to be set for reg: 0x%lx; expected: 0x%lx; read: 0x%lx\n",
  147. reg_info->reg, FW_REG_ULIMIT_VAL(reg_info->max_feat_bit), val);
  148. /* Test a 'write' by disabling all the features of the register map */
  149. ret = __vcpu_set_reg(vcpu, reg_info->reg, 0);
  150. TEST_ASSERT(ret == 0,
  151. "Failed to clear all the features of reg: 0x%lx; ret: %d\n",
  152. reg_info->reg, errno);
  153. vcpu_get_reg(vcpu, reg_info->reg, &val);
  154. TEST_ASSERT(val == 0,
  155. "Expected all the features to be cleared for reg: 0x%lx\n", reg_info->reg);
  156. /*
  157. * Test enabling a feature that's not supported.
  158. * Avoid this check if all the bits are occupied.
  159. */
  160. if (reg_info->max_feat_bit < 63) {
  161. ret = __vcpu_set_reg(vcpu, reg_info->reg, BIT(reg_info->max_feat_bit + 1));
  162. TEST_ASSERT(ret != 0 && errno == EINVAL,
  163. "Unexpected behavior or return value (%d) while setting an unsupported feature for reg: 0x%lx\n",
  164. errno, reg_info->reg);
  165. }
  166. }
  167. }
  168. static void test_fw_regs_after_vm_start(struct kvm_vcpu *vcpu)
  169. {
  170. uint64_t val;
  171. unsigned int i;
  172. int ret;
  173. for (i = 0; i < ARRAY_SIZE(fw_reg_info); i++) {
  174. const struct kvm_fw_reg_info *reg_info = &fw_reg_info[i];
  175. /*
  176. * Before starting the VM, the test clears all the bits.
  177. * Check if that's still the case.
  178. */
  179. vcpu_get_reg(vcpu, reg_info->reg, &val);
  180. TEST_ASSERT(val == 0,
  181. "Expected all the features to be cleared for reg: 0x%lx\n",
  182. reg_info->reg);
  183. /*
  184. * Since the VM has run at least once, KVM shouldn't allow modification of
  185. * the registers and should return EBUSY. Set the registers and check for
  186. * the expected errno.
  187. */
  188. ret = __vcpu_set_reg(vcpu, reg_info->reg, FW_REG_ULIMIT_VAL(reg_info->max_feat_bit));
  189. TEST_ASSERT(ret != 0 && errno == EBUSY,
  190. "Unexpected behavior or return value (%d) while setting a feature while VM is running for reg: 0x%lx\n",
  191. errno, reg_info->reg);
  192. }
  193. }
  194. static struct kvm_vm *test_vm_create(struct kvm_vcpu **vcpu)
  195. {
  196. struct kvm_vm *vm;
  197. vm = vm_create_with_one_vcpu(vcpu, guest_code);
  198. ucall_init(vm, NULL);
  199. steal_time_init(*vcpu);
  200. return vm;
  201. }
  202. static void test_guest_stage(struct kvm_vm **vm, struct kvm_vcpu **vcpu)
  203. {
  204. int prev_stage = stage;
  205. pr_debug("Stage: %d\n", prev_stage);
  206. /* Sync the stage early, the VM might be freed below. */
  207. stage++;
  208. sync_global_to_guest(*vm, stage);
  209. switch (prev_stage) {
  210. case TEST_STAGE_REG_IFACE:
  211. test_fw_regs_after_vm_start(*vcpu);
  212. break;
  213. case TEST_STAGE_HVC_IFACE_FEAT_DISABLED:
  214. /* Start a new VM so that all the features are now enabled by default */
  215. kvm_vm_free(*vm);
  216. *vm = test_vm_create(vcpu);
  217. break;
  218. case TEST_STAGE_HVC_IFACE_FEAT_ENABLED:
  219. case TEST_STAGE_HVC_IFACE_FALSE_INFO:
  220. break;
  221. default:
  222. TEST_FAIL("Unknown test stage: %d\n", prev_stage);
  223. }
  224. }
  225. static void test_run(void)
  226. {
  227. struct kvm_vcpu *vcpu;
  228. struct kvm_vm *vm;
  229. struct ucall uc;
  230. bool guest_done = false;
  231. vm = test_vm_create(&vcpu);
  232. test_fw_regs_before_vm_start(vcpu);
  233. while (!guest_done) {
  234. vcpu_run(vcpu);
  235. switch (get_ucall(vcpu, &uc)) {
  236. case UCALL_SYNC:
  237. test_guest_stage(&vm, &vcpu);
  238. break;
  239. case UCALL_DONE:
  240. guest_done = true;
  241. break;
  242. case UCALL_ABORT:
  243. REPORT_GUEST_ASSERT_N(uc, "values: 0x%lx, 0x%lx; 0x%lx, stage: %u",
  244. GUEST_ASSERT_ARG(uc, 0),
  245. GUEST_ASSERT_ARG(uc, 1),
  246. GUEST_ASSERT_ARG(uc, 2), stage);
  247. break;
  248. default:
  249. TEST_FAIL("Unexpected guest exit\n");
  250. }
  251. }
  252. kvm_vm_free(vm);
  253. }
  254. int main(void)
  255. {
  256. setbuf(stdout, NULL);
  257. test_run();
  258. return 0;
  259. }