From: Reiji Watanabe <reijiw@google.com>
To: Marc Zyngier <maz@kernel.org>, kvmarm@lists.cs.columbia.edu
Cc: kvm@vger.kernel.org, linux-arm-kernel@lists.infradead.org,
James Morse <james.morse@arm.com>,
Alexandru Elisei <alexandru.elisei@arm.com>,
Suzuki K Poulose <suzuki.poulose@arm.com>,
Paolo Bonzini <pbonzini@redhat.com>,
Will Deacon <will@kernel.org>, Andrew Jones <drjones@redhat.com>,
Fuad Tabba <tabba@google.com>,
Peng Liang <liangpeng10@huawei.com>,
Peter Shier <pshier@google.com>,
Ricardo Koller <ricarkol@google.com>,
Oliver Upton <oupton@google.com>,
Jing Zhang <jingzhangos@google.com>,
Raghavendra Rao Anata <rananta@google.com>,
Reiji Watanabe <reijiw@google.com>
Subject: [PATCH v6 24/25] KVM: arm64: Add kunit test for trap initialization
Date: Thu, 10 Mar 2022 20:48:10 -0800 [thread overview]
Message-ID: <20220311044811.1980336-25-reijiw@google.com> (raw)
In-Reply-To: <20220311044811.1980336-1-reijiw@google.com>
Add KUnit tests for functions in arch/arm64/kvm/sys_regs_test.c
that activates traps for disabled features.
Signed-off-by: Reiji Watanabe <reijiw@google.com>
---
arch/arm64/kvm/sys_regs_test.c | 255 +++++++++++++++++++++++++++++++++
1 file changed, 255 insertions(+)
diff --git a/arch/arm64/kvm/sys_regs_test.c b/arch/arm64/kvm/sys_regs_test.c
index 954c01876977..d26c589cbb93 100644
--- a/arch/arm64/kvm/sys_regs_test.c
+++ b/arch/arm64/kvm/sys_regs_test.c
@@ -957,6 +957,258 @@ static void validate_id_reg_test(struct kunit *test)
}
}
+struct trap_config_test {
+ u64 set;
+ u64 clear;
+ u64 prev_val;
+ u64 expect_val;
+};
+
+struct trap_config_test trap_params[] = {
+ {0x30000800000, 0, 0, 0x30000800000},
+ {0, 0x30000800000, 0, 0},
+ {0x30000800000, 0, (u64)-1, (u64)-1},
+ {0, 0x30000800000, (u64)-1, (u64)0xfffffcffff7fffff},
+};
+
+static void trap_case_to_desc(struct trap_config_test *t, char *desc)
+{
+ snprintf(desc, KUNIT_PARAM_DESC_SIZE,
+ "trap - set:0x%llx, clear:0x%llx, prev_val:0x%llx\n",
+ t->set, t->clear, t->prev_val);
+}
+
+KUNIT_ARRAY_PARAM(trap, trap_params, trap_case_to_desc);
+
+/* Tests for feature_trap_activate(). */
+static void feature_trap_activate_test(struct kunit *test)
+{
+ struct kvm_vcpu *vcpu;
+ const struct trap_config_test *trap = test->param_value;
+
+ vcpu = test_kvm_vcpu_init(test);
+ KUNIT_ASSERT_TRUE(test, vcpu);
+
+ /* Test for HCR_EL2 */
+ vcpu->arch.hcr_el2 = trap->prev_val;
+ feature_trap_activate(vcpu, VCPU_HCR_EL2, trap->set, trap->clear);
+ KUNIT_EXPECT_EQ(test, vcpu->arch.hcr_el2, trap->expect_val);
+
+ /* Test for MDCR_EL2 */
+ vcpu->arch.mdcr_el2 = trap->prev_val;
+ feature_trap_activate(vcpu, VCPU_MDCR_EL2, trap->set, trap->clear);
+ KUNIT_EXPECT_EQ(test, vcpu->arch.mdcr_el2, trap->expect_val);
+
+ /* Test for CPTR_EL2 */
+ vcpu->arch.cptr_el2 = trap->prev_val;
+ feature_trap_activate(vcpu, VCPU_CPTR_EL2, trap->set, trap->clear);
+ KUNIT_EXPECT_EQ(test, vcpu->arch.cptr_el2, trap->expect_val);
+}
+
+static u64 test_trap_set0;
+static u64 test_trap_clear0;
+static void test_trap_activate0(struct kvm_vcpu *vcpu)
+{
+ feature_trap_activate(vcpu, VCPU_HCR_EL2,
+ test_trap_set0, test_trap_clear0);
+}
+
+static u64 test_trap_set1;
+static u64 test_trap_clear1;
+static void test_trap_activate1(struct kvm_vcpu *vcpu)
+{
+ feature_trap_activate(vcpu, VCPU_HCR_EL2,
+ test_trap_set1, test_trap_clear1);
+}
+
+static u64 test_trap_set2;
+static u64 test_trap_clear2;
+static void test_trap_activate2(struct kvm_vcpu *vcpu)
+{
+ feature_trap_activate(vcpu, VCPU_HCR_EL2,
+ test_trap_set2, test_trap_clear2);
+}
+
+
+static void setup_feature_config_ctrl(struct feature_config_ctrl *config,
+ u32 id, int shift, int min, bool sign,
+ void *fn)
+{
+ memset(config, 0, sizeof(*config));
+ config->ftr_reg = id;
+ config->ftr_shift = shift;
+ config->ftr_min = min;
+ config->ftr_signed = sign;
+ config->trap_activate = fn;
+}
+
+/*
+ * Tests for id_reg_features_trap_activate.
+ * Setup a id_reg_desc with three entries in id_reg_desc->trap_features[].
+ * Check if the config register is updated to enable trap for the disabled
+ * features.
+ */
+static void id_reg_features_trap_activate_test(struct kunit *test)
+{
+ struct kvm_vcpu *vcpu;
+ u32 id;
+ u64 cfg_set, cfg_clear, id_reg_sys_val, id_reg_val;
+ struct id_reg_desc id_reg_data = {};
+ struct feature_config_ctrl config0, config1, config2;
+ struct feature_config_ctrl *trap_features[] = {
+ &config0, &config1, &config2, NULL,
+ };
+
+ vcpu = test_kvm_vcpu_init(test);
+ KUNIT_EXPECT_TRUE(test, vcpu);
+ if (!vcpu)
+ return;
+
+ /* Setup id_reg_desc */
+ id_reg_sys_val = 0x7777777777777777;
+ id = SYS_ID_AA64DFR0_EL1;
+ set_sys_desc((struct sys_reg_desc *)&id_reg_data.reg_desc, id);
+ id_reg_data.sys_val = id_reg_sys_val;
+ id_reg_data.vcpu_limit_val = (u64)-1;
+ id_reg_data.trap_features =
+ (const struct feature_config_ctrl *(*)[])trap_features;
+
+ /* Setup the 1st feature_config_ctrl */
+ test_trap_set0 = 0x3;
+ test_trap_clear0 = 0x0;
+ setup_feature_config_ctrl(&config0, id, 60, 2, FTR_UNSIGNED,
+ &test_trap_activate0);
+
+ /* Setup the 2nd feature_config_ctrl */
+ test_trap_set1 = 0x30000040;
+ test_trap_clear1 = 0x40000000;
+ setup_feature_config_ctrl(&config1, id, 0, 1, FTR_UNSIGNED,
+ &test_trap_activate1);
+
+ /* Setup the 3rd feature_config_ctrl */
+ test_trap_set2 = 0x30000000800;
+ test_trap_clear2 = 0x40000000000;
+ setup_feature_config_ctrl(&config2, id, 4, 0, FTR_SIGNED,
+ &test_trap_activate2);
+
+#define ftr_dis(cfg) \
+ ((u64)(((cfg)->ftr_min - 1) & 0xf) << (cfg)->ftr_shift)
+
+#define ftr_en(cfg) \
+ ((u64)(cfg)->ftr_min << (cfg)->ftr_shift)
+
+ /* Test with features enabled for config0, 1 and 2 */
+ id_reg_val = ftr_en(&config0) | ftr_en(&config1) | ftr_en(&config2);
+ write_kvm_id_reg(vcpu->kvm, id, id_reg_val);
+ vcpu->arch.hcr_el2 = 0;
+ id_reg_features_trap_activate(vcpu, &id_reg_data);
+ KUNIT_EXPECT_EQ(test, vcpu->arch.hcr_el2, 0);
+
+
+ /* Test with features disabled for config0 only */
+ id_reg_val = ftr_dis(&config0) | ftr_en(&config1) | ftr_en(&config2);
+ write_kvm_id_reg(vcpu->kvm, id, id_reg_val);
+ vcpu->arch.hcr_el2 = 0;
+ cfg_set = test_trap_set0;
+ cfg_clear = test_trap_clear0;
+
+ id_reg_features_trap_activate(vcpu, &id_reg_data);
+ KUNIT_EXPECT_EQ(test, vcpu->arch.hcr_el2 & cfg_set, cfg_set);
+ KUNIT_EXPECT_EQ(test, vcpu->arch.hcr_el2 & cfg_clear, 0);
+
+
+ /* Test with features disabled for config0 and config1 */
+ id_reg_val = ftr_dis(&config0) | ftr_dis(&config1) | ftr_en(&config2);
+ write_kvm_id_reg(vcpu->kvm, id, id_reg_val);
+ vcpu->arch.hcr_el2 = 0;
+
+ cfg_set = test_trap_set0 | test_trap_set1;
+ cfg_clear = test_trap_clear0 | test_trap_clear1;
+
+ id_reg_features_trap_activate(vcpu, &id_reg_data);
+ KUNIT_EXPECT_EQ(test, vcpu->arch.hcr_el2 & cfg_set, cfg_set);
+ KUNIT_EXPECT_EQ(test, vcpu->arch.hcr_el2 & cfg_clear, 0);
+
+
+ /* Test with features disabled for config0, config1, and config2 */
+ id_reg_val = ftr_dis(&config0) | ftr_dis(&config1) | ftr_dis(&config2);
+ write_kvm_id_reg(vcpu->kvm, id, id_reg_val);
+ vcpu->arch.hcr_el2 = 0;
+
+ cfg_set = test_trap_set0 | test_trap_set1 | test_trap_set2;
+ cfg_clear = test_trap_clear0 | test_trap_clear1 | test_trap_clear2;
+
+ id_reg_features_trap_activate(vcpu, &id_reg_data);
+ KUNIT_EXPECT_EQ(test, vcpu->arch.hcr_el2 & cfg_set, cfg_set);
+ KUNIT_EXPECT_EQ(test, vcpu->arch.hcr_el2 & cfg_clear, 0);
+
+
+ /* Test with id_reg_data.trap_features = NULL */
+ id_reg_data.trap_features = NULL;
+ vcpu->arch.hcr_el2 = 0;
+ id_reg_features_trap_activate(vcpu, &id_reg_data);
+ KUNIT_EXPECT_EQ(test, vcpu->arch.hcr_el2, 0);
+}
+
+/* Tests for vcpu_need_trap_ptrauth(). */
+static void vcpu_need_trap_ptrauth_test(struct kunit *test)
+{
+ struct kvm_vcpu *vcpu;
+ u32 id = SYS_ID_AA64ISAR1_EL1;
+
+ vcpu = test_kvm_vcpu_init(test);
+ KUNIT_EXPECT_TRUE(test, vcpu);
+ if (!vcpu)
+ return;
+
+ if (system_has_full_ptr_auth()) {
+ /* Tests with PTRAUTH disabled vCPU */
+ write_kvm_id_reg(vcpu->kvm, id, 0x0);
+ KUNIT_EXPECT_TRUE(test, vcpu_need_trap_ptrauth(vcpu));
+
+ /* GPI = 1, API = 1 */
+ write_kvm_id_reg(vcpu->kvm, id, 0x10000100);
+ KUNIT_EXPECT_TRUE(test, vcpu_need_trap_ptrauth(vcpu));
+
+ /* GPI = 1, APA = 1 */
+ write_kvm_id_reg(vcpu->kvm, id, 0x10000010);
+ KUNIT_EXPECT_TRUE(test, vcpu_need_trap_ptrauth(vcpu));
+
+ /* GPA = 1, API = 1 */
+ write_kvm_id_reg(vcpu->kvm, id, 0x01000100);
+ KUNIT_EXPECT_TRUE(test, vcpu_need_trap_ptrauth(vcpu));
+
+ /* GPA = 1, APA = 1 */
+ write_kvm_id_reg(vcpu->kvm, id, 0x01000010);
+ KUNIT_EXPECT_TRUE(test, vcpu_need_trap_ptrauth(vcpu));
+
+
+ /* Tests with PTRAUTH enabled vCPU */
+ vcpu->arch.flags |= KVM_ARM64_GUEST_HAS_PTRAUTH;
+
+ write_kvm_id_reg(vcpu->kvm, id, 0x0);
+ KUNIT_EXPECT_TRUE(test, vcpu_need_trap_ptrauth(vcpu));
+
+ /* GPI = 1, API = 1 */
+ write_kvm_id_reg(vcpu->kvm, id, 0x10000100);
+ KUNIT_EXPECT_FALSE(test, vcpu_need_trap_ptrauth(vcpu));
+
+ /* GPI = 1, APA = 1 */
+ write_kvm_id_reg(vcpu->kvm, id, 0x10000010);
+ KUNIT_EXPECT_FALSE(test, vcpu_need_trap_ptrauth(vcpu));
+
+ /* GPA = 1, API = 1 */
+ write_kvm_id_reg(vcpu->kvm, id, 0x01000100);
+ KUNIT_EXPECT_FALSE(test, vcpu_need_trap_ptrauth(vcpu));
+
+ /* GPA = 1, APA = 1 */
+ write_kvm_id_reg(vcpu->kvm, id, 0x01000010);
+ KUNIT_EXPECT_FALSE(test, vcpu_need_trap_ptrauth(vcpu));
+ } else {
+ KUNIT_EXPECT_FALSE(test, vcpu_need_trap_ptrauth(vcpu));
+ }
+}
+
static struct kunit_case kvm_sys_regs_test_cases[] = {
KUNIT_CASE_PARAM(vcpu_id_reg_feature_frac_check_test, frac_gen_params),
KUNIT_CASE_PARAM(validate_id_aa64mmfr0_tgran2_test, tgran4_2_gen_params),
@@ -971,6 +1223,9 @@ static struct kunit_case kvm_sys_regs_test_cases[] = {
KUNIT_CASE(validate_id_dfr0_el1_test),
KUNIT_CASE(validate_mvfr1_el1_test),
KUNIT_CASE(validate_id_reg_test),
+ KUNIT_CASE(vcpu_need_trap_ptrauth_test),
+ KUNIT_CASE_PARAM(feature_trap_activate_test, trap_gen_params),
+ KUNIT_CASE(id_reg_features_trap_activate_test),
{}
};
--
2.35.1.723.g4982287a31-goog
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
next prev parent reply other threads:[~2022-03-11 5:06 UTC|newest]
Thread overview: 48+ messages / expand[flat|nested] mbox.gz Atom feed top
2022-03-11 4:47 [PATCH v6 00/25] KVM: arm64: Make CPU ID registers writable by userspace Reiji Watanabe
2022-03-11 4:47 ` [PATCH v6 01/25] KVM: arm64: Introduce a validation function for an ID register Reiji Watanabe
2022-03-22 7:42 ` Oliver Upton
2022-03-23 6:06 ` Reiji Watanabe
2022-03-23 7:05 ` Oliver Upton
2022-03-24 6:00 ` Reiji Watanabe
2022-03-24 7:37 ` Oliver Upton
2022-03-29 1:57 ` Reiji Watanabe
2022-03-11 4:47 ` [PATCH v6 02/25] KVM: arm64: Save ID registers' sanitized value per guest Reiji Watanabe
2022-03-23 19:22 ` Oliver Upton
2022-03-24 16:23 ` Reiji Watanabe
2022-03-24 17:54 ` Oliver Upton
2022-03-26 2:35 ` Reiji Watanabe
2022-03-27 22:57 ` Oliver Upton
2022-03-28 0:04 ` Reiji Watanabe
2022-03-11 4:47 ` [PATCH v6 03/25] KVM: arm64: Introduce struct id_reg_desc Reiji Watanabe
2022-03-11 4:47 ` [PATCH v6 04/25] KVM: arm64: Make ID_AA64PFR0_EL1 writable Reiji Watanabe
2022-03-11 4:47 ` [PATCH v6 05/25] KVM: arm64: Make ID_AA64PFR1_EL1 writable Reiji Watanabe
2022-03-11 4:47 ` [PATCH v6 06/25] KVM: arm64: Make ID_AA64ISAR0_EL1 writable Reiji Watanabe
2022-03-11 4:47 ` [PATCH v6 07/25] KVM: arm64: Make ID_AA64ISAR1_EL1 writable Reiji Watanabe
2022-03-11 4:47 ` [PATCH v6 08/25] KVM: arm64: Make ID_AA64MMFR0_EL1 writable Reiji Watanabe
2022-03-11 4:47 ` [PATCH v6 09/25] KVM: arm64: Make ID_AA64DFR0_EL1/ID_DFR0_EL1 writable Reiji Watanabe
2022-03-11 4:47 ` [PATCH v6 10/25] KVM: arm64: Make MVFR1_EL1 writable Reiji Watanabe
2022-03-11 4:47 ` [PATCH v6 11/25] KVM: arm64: Add remaining ID registers to id_reg_desc_table Reiji Watanabe
2022-03-23 19:53 ` Oliver Upton
2022-03-23 20:13 ` Ricardo Koller
2022-03-23 20:44 ` Oliver Upton
2022-03-23 22:22 ` Ricardo Koller
2022-03-23 22:25 ` Oliver Upton
2022-03-24 2:26 ` Oliver Upton
2022-03-24 20:23 ` Reiji Watanabe
2022-03-24 23:01 ` Oliver Upton
2022-03-25 5:15 ` Reiji Watanabe
2022-03-25 8:51 ` Oliver Upton
2022-03-11 4:47 ` [PATCH v6 12/25] KVM: arm64: Use id_reg_desc_table for ID registers Reiji Watanabe
2022-03-11 4:47 ` [PATCH v6 13/25] KVM: arm64: Add consistency checking for frac fields of " Reiji Watanabe
2022-03-11 4:48 ` [PATCH v6 14/25] KVM: arm64: Introduce KVM_CAP_ARM_ID_REG_CONFIGURABLE capability Reiji Watanabe
2022-03-11 4:48 ` [PATCH v6 15/25] KVM: arm64: Add kunit test for ID register validation Reiji Watanabe
2022-03-11 4:48 ` [PATCH v6 16/25] KVM: arm64: Use vcpu->arch cptr_el2 to track value of cptr_el2 for VHE Reiji Watanabe
2022-03-11 4:48 ` [PATCH v6 17/25] KVM: arm64: Use vcpu->arch.mdcr_el2 to track value of mdcr_el2 Reiji Watanabe
2022-03-11 4:48 ` [PATCH v6 18/25] KVM: arm64: Introduce framework to trap disabled features Reiji Watanabe
2022-03-11 4:48 ` [PATCH v6 19/25] KVM: arm64: Trap disabled features of ID_AA64PFR0_EL1 Reiji Watanabe
2022-03-11 4:48 ` [PATCH v6 20/25] KVM: arm64: Trap disabled features of ID_AA64PFR1_EL1 Reiji Watanabe
2022-03-11 4:48 ` [PATCH v6 21/25] KVM: arm64: Trap disabled features of ID_AA64DFR0_EL1 Reiji Watanabe
2022-03-11 4:48 ` [PATCH v6 22/25] KVM: arm64: Trap disabled features of ID_AA64MMFR1_EL1 Reiji Watanabe
2022-03-11 4:48 ` [PATCH v6 23/25] KVM: arm64: Trap disabled features of ID_AA64ISAR1_EL1 Reiji Watanabe
2022-03-11 4:48 ` Reiji Watanabe [this message]
2022-03-11 4:48 ` [PATCH v6 25/25] KVM: arm64: selftests: Introduce id_reg_test Reiji Watanabe
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20220311044811.1980336-25-reijiw@google.com \
--to=reijiw@google.com \
--cc=alexandru.elisei@arm.com \
--cc=drjones@redhat.com \
--cc=james.morse@arm.com \
--cc=jingzhangos@google.com \
--cc=kvm@vger.kernel.org \
--cc=kvmarm@lists.cs.columbia.edu \
--cc=liangpeng10@huawei.com \
--cc=linux-arm-kernel@lists.infradead.org \
--cc=maz@kernel.org \
--cc=oupton@google.com \
--cc=pbonzini@redhat.com \
--cc=pshier@google.com \
--cc=rananta@google.com \
--cc=ricarkol@google.com \
--cc=suzuki.poulose@arm.com \
--cc=tabba@google.com \
--cc=will@kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).