/* hypercalls: Check the ARM64's psuedo-firmware bitmap register interface. * * The test validates the basic hypercall functionalities that are exposed * via the psuedo-firmware bitmap register. This includes the registers' * read/write behavior before and after the VM has started, and if the * hypercalls are properly masked or unmasked to the guest when disabled or * enabled from the KVM userspace, respectively.
*/ #include <errno.h> #include <linux/arm-smccc.h> #include <asm/kvm.h> #include <kvm_util.h>
struct kvm_fw_reg_info {
uint64_t reg; /* Register definition */
uint64_t max_feat_bit; /* Bit that represents the upper limit of the feature-map */
uint64_t reset_val; /* Reset value for the register */
};
/* Feed false hypercall info to test the KVM behavior */ staticconststruct test_hvc_info false_hvc_info[] = { /* Feature support check against a different family of hypercalls */
TEST_HVC_INFO(ARM_SMCCC_TRNG_FEATURES, ARM_SMCCC_VENDOR_HYP_KVM_PTP_FUNC_ID),
TEST_HVC_INFO(ARM_SMCCC_ARCH_FEATURES_FUNC_ID, ARM_SMCCC_TRNG_RND64),
TEST_HVC_INFO(ARM_SMCCC_HV_PV_TIME_FEATURES, ARM_SMCCC_TRNG_RND64),
};
for (i = 0; i < ARRAY_SIZE(fw_reg_info); i++) { conststruct kvm_fw_reg_info *reg_info = &fw_reg_info[i];
uint64_t set_val;
/* First 'read' should be the reset value for the reg */
val = vcpu_get_reg(vcpu, reg_info->reg);
TEST_ASSERT(val == reg_info->reset_val, "Unexpected reset value for reg: 0x%lx; expected: 0x%lx; read: 0x%lx",
reg_info->reg, reg_info->reset_val, val);
if (reg_info->reset_val)
set_val = 0; else
set_val = FW_REG_ULIMIT_VAL(reg_info->max_feat_bit);
ret = __vcpu_set_reg(vcpu, reg_info->reg, set_val);
TEST_ASSERT(ret == 0, "Failed to %s all the features of reg: 0x%lx; ret: %d",
(set_val ? "set" : "clear"), reg_info->reg, errno);
val = vcpu_get_reg(vcpu, reg_info->reg);
TEST_ASSERT(val == set_val, "Expected all the features to be %s for reg: 0x%lx",
(set_val ? "set" : "cleared"), reg_info->reg);
/* * If the reg has been set, clear it as test_fw_regs_after_vm_start() * expects it to be cleared.
*/ if (set_val) {
ret = __vcpu_set_reg(vcpu, reg_info->reg, 0);
TEST_ASSERT(ret == 0, "Failed to clear all the features of reg: 0x%lx; ret: %d",
reg_info->reg, errno);
}
/* * Test enabling a feature that's not supported. * Avoid this check if all the bits are occupied.
*/ if (reg_info->max_feat_bit < 63) {
ret = __vcpu_set_reg(vcpu, reg_info->reg, BIT(reg_info->max_feat_bit + 1));
TEST_ASSERT(ret != 0 && errno == EINVAL, "Unexpected behavior or return value (%d) while setting an unsupported feature for reg: 0x%lx",
errno, reg_info->reg);
}
}
}
for (i = 0; i < ARRAY_SIZE(fw_reg_info); i++) { conststruct kvm_fw_reg_info *reg_info = &fw_reg_info[i];
/* * Before starting the VM, the test clears all the bits. * Check if that's still the case.
*/
val = vcpu_get_reg(vcpu, reg_info->reg);
TEST_ASSERT(val == 0, "Expected all the features to be cleared for reg: 0x%lx",
reg_info->reg);
/* * Since the VM has run at least once, KVM shouldn't allow modification of * the registers and should return EBUSY. Set the registers and check for * the expected errno.
*/
ret = __vcpu_set_reg(vcpu, reg_info->reg, FW_REG_ULIMIT_VAL(reg_info->max_feat_bit));
TEST_ASSERT(ret != 0 && errno == EBUSY, "Unexpected behavior or return value (%d) while setting a feature while VM is running for reg: 0x%lx",
errno, reg_info->reg);
}
}
/* Sync the stage early, the VM might be freed below. */
stage++;
sync_global_to_guest(*vm, stage);
switch (prev_stage) { case TEST_STAGE_REG_IFACE:
test_fw_regs_after_vm_start(*vcpu); break; case TEST_STAGE_HVC_IFACE_FEAT_DISABLED: /* Start a new VM so that all the features are now enabled by default */
kvm_vm_free(*vm);
*vm = test_vm_create(vcpu); break; case TEST_STAGE_HVC_IFACE_FEAT_ENABLED: case TEST_STAGE_HVC_IFACE_FALSE_INFO: break; default:
TEST_FAIL("Unknown test stage: %d", prev_stage);
}
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.