From: Oliver Upton <oliver.upton@linux.dev>
To: Marc Zyngier <maz@kernel.org>
Cc: James Morse <james.morse@arm.com>,
Suzuki K Poulose <suzuki.poulose@arm.com>,
kvmarm@lists.linux.dev, Akihiko Odaki <akihiko.odaki@daynix.com>,
Zenghui Yu <yuzenghui@huawei.com>,
Raghavendra Rao Ananta <rananta@google.com>,
linux-arm-kernel@lists.infradead.org,
Salil Mehta <salil.mehta@huawei.com>,
Oliver Upton <oliver.upton@linux.dev>
Subject: [RFC PATCH v2 4/6] KVM: arm64: Use a maple tree to represent the SMCCC filter
Date: Sat, 11 Feb 2023 01:37:57 +0000 [thread overview]
Message-ID: <20230211013759.3556016-5-oliver.upton@linux.dev> (raw)
In-Reply-To: <20230211013759.3556016-1-oliver.upton@linux.dev>
Maple tree is an efficient B-tree implementation that is intended for
storing non-overlapping intervals. Such a data structure is a good fit
for the SMCCC filter as it is desirable to sparsely allocate the 32 bit
function ID space.
To that end, add a maple tree to kvm_arch and correctly init/teardown
along with the VM. Wire in a test against the hypercall filter for HVCs
which does nothing until the controls are exposed to userspace.
Signed-off-by: Oliver Upton <oliver.upton@linux.dev>
---
arch/arm64/include/asm/kvm_host.h | 5 +++-
arch/arm64/kvm/arm.c | 2 ++
arch/arm64/kvm/hypercalls.c | 38 +++++++++++++++++++++++++++++++
include/kvm/arm_hypercalls.h | 1 +
4 files changed, 45 insertions(+), 1 deletion(-)
diff --git a/arch/arm64/include/asm/kvm_host.h b/arch/arm64/include/asm/kvm_host.h
index 012e94bc9e4a..a20875dde1f5 100644
--- a/arch/arm64/include/asm/kvm_host.h
+++ b/arch/arm64/include/asm/kvm_host.h
@@ -16,6 +16,7 @@
#include <linux/types.h>
#include <linux/jump_label.h>
#include <linux/kvm_types.h>
+#include <linux/maple_tree.h>
#include <linux/percpu.h>
#include <linux/psci.h>
#include <asm/arch_gicv3.h>
@@ -213,7 +214,8 @@ struct kvm_arch {
#define KVM_ARCH_FLAG_EL1_32BIT 4
/* PSCI SYSTEM_SUSPEND enabled for the guest */
#define KVM_ARCH_FLAG_SYSTEM_SUSPEND_ENABLED 5
-
+ /* SMCCC filter initialized for the VM */
+#define KVM_ARCH_FLAG_SMCCC_FILTER_CONFIGURED 6
unsigned long flags;
/*
@@ -234,6 +236,7 @@ struct kvm_arch {
/* Hypercall features firmware registers' descriptor */
struct kvm_smccc_features smccc_feat;
+ struct maple_tree smccc_filter;
/*
* For an untrusted host VM, 'pkvm.handle' is used to lookup
diff --git a/arch/arm64/kvm/arm.c b/arch/arm64/kvm/arm.c
index 09efa893e03a..e04690caad77 100644
--- a/arch/arm64/kvm/arm.c
+++ b/arch/arm64/kvm/arm.c
@@ -202,6 +202,8 @@ void kvm_arch_destroy_vm(struct kvm *kvm)
kvm_destroy_vcpus(kvm);
kvm_unshare_hyp(kvm, kvm + 1);
+
+ kvm_arm_teardown_hypercalls(kvm);
}
int kvm_vm_ioctl_check_extension(struct kvm *kvm, long ext)
diff --git a/arch/arm64/kvm/hypercalls.c b/arch/arm64/kvm/hypercalls.c
index 980546b295b3..45b8371816fd 100644
--- a/arch/arm64/kvm/hypercalls.c
+++ b/arch/arm64/kvm/hypercalls.c
@@ -121,8 +121,39 @@ static bool kvm_smccc_test_fw_bmap(struct kvm_vcpu *vcpu, u32 func_id)
}
}
+static bool kvm_smccc_filter_configured(struct kvm *kvm)
+{
+ return test_bit(KVM_ARCH_FLAG_SMCCC_FILTER_CONFIGURED, &kvm->arch.flags);
+}
+
+static u8 kvm_smccc_filter_get_action(struct kvm *kvm, u32 func_id)
+{
+ unsigned long index = func_id;
+ void *val;
+
+ if (!kvm_smccc_filter_configured(kvm))
+ return KVM_SMCCC_FILTER_ALLOW;
+
+ /*
+ * But where's the error handling, you say?
+ *
+ * mt_find() returns NULL if no entry was found, which just so happens
+ * to match KVM_SMCCC_FILTER_ALLOW.
+ */
+ val = mt_find(&kvm->arch.smccc_filter, &index, index);
+ return xa_to_value(val);
+}
+
static u8 kvm_hvc_get_action(struct kvm_vcpu *vcpu, u32 func_id)
{
+ /*
+ * Intervening actions in the SMCCC filter take precedence over the
+ * pseudo-firmware register bitmaps.
+ */
+ u8 action = kvm_smccc_filter_get_action(vcpu->kvm, func_id);
+ if (action != KVM_SMCCC_FILTER_ALLOW)
+ return action;
+
if (kvm_smccc_default_call(func_id) ||
kvm_smccc_test_fw_bmap(vcpu, func_id))
return KVM_SMCCC_FILTER_ALLOW;
@@ -256,6 +287,13 @@ void kvm_arm_init_hypercalls(struct kvm *kvm)
smccc_feat->std_bmap = KVM_ARM_SMCCC_STD_FEATURES;
smccc_feat->std_hyp_bmap = KVM_ARM_SMCCC_STD_HYP_FEATURES;
smccc_feat->vendor_hyp_bmap = KVM_ARM_SMCCC_VENDOR_HYP_FEATURES;
+
+ mt_init(&kvm->arch.smccc_filter);
+}
+
+void kvm_arm_teardown_hypercalls(struct kvm *kvm)
+{
+ mtree_destroy(&kvm->arch.smccc_filter);
}
int kvm_arm_get_fw_num_regs(struct kvm_vcpu *vcpu)
diff --git a/include/kvm/arm_hypercalls.h b/include/kvm/arm_hypercalls.h
index 1188f116cf4e..ae1ada68cdc2 100644
--- a/include/kvm/arm_hypercalls.h
+++ b/include/kvm/arm_hypercalls.h
@@ -43,6 +43,7 @@ static inline void smccc_set_retval(struct kvm_vcpu *vcpu,
struct kvm_one_reg;
void kvm_arm_init_hypercalls(struct kvm *kvm);
+void kvm_arm_teardown_hypercalls(struct kvm *kvm);
int kvm_arm_get_fw_num_regs(struct kvm_vcpu *vcpu);
int kvm_arm_copy_fw_reg_indices(struct kvm_vcpu *vcpu, u64 __user *uindices);
int kvm_arm_get_fw_reg(struct kvm_vcpu *vcpu, const struct kvm_one_reg *reg);
--
2.39.1.581.gbfd45094c4-goog
WARNING: multiple messages have this Message-ID (diff)
From: Oliver Upton <oliver.upton@linux.dev>
To: Marc Zyngier <maz@kernel.org>
Cc: James Morse <james.morse@arm.com>,
Suzuki K Poulose <suzuki.poulose@arm.com>,
kvmarm@lists.linux.dev, Akihiko Odaki <akihiko.odaki@daynix.com>,
Zenghui Yu <yuzenghui@huawei.com>,
Raghavendra Rao Ananta <rananta@google.com>,
linux-arm-kernel@lists.infradead.org,
Salil Mehta <salil.mehta@huawei.com>,
Oliver Upton <oliver.upton@linux.dev>
Subject: [RFC PATCH v2 4/6] KVM: arm64: Use a maple tree to represent the SMCCC filter
Date: Sat, 11 Feb 2023 01:37:57 +0000 [thread overview]
Message-ID: <20230211013759.3556016-5-oliver.upton@linux.dev> (raw)
In-Reply-To: <20230211013759.3556016-1-oliver.upton@linux.dev>
Maple tree is an efficient B-tree implementation that is intended for
storing non-overlapping intervals. Such a data structure is a good fit
for the SMCCC filter as it is desirable to sparsely allocate the 32 bit
function ID space.
To that end, add a maple tree to kvm_arch and correctly init/teardown
along with the VM. Wire in a test against the hypercall filter for HVCs
which does nothing until the controls are exposed to userspace.
Signed-off-by: Oliver Upton <oliver.upton@linux.dev>
---
arch/arm64/include/asm/kvm_host.h | 5 +++-
arch/arm64/kvm/arm.c | 2 ++
arch/arm64/kvm/hypercalls.c | 38 +++++++++++++++++++++++++++++++
include/kvm/arm_hypercalls.h | 1 +
4 files changed, 45 insertions(+), 1 deletion(-)
diff --git a/arch/arm64/include/asm/kvm_host.h b/arch/arm64/include/asm/kvm_host.h
index 012e94bc9e4a..a20875dde1f5 100644
--- a/arch/arm64/include/asm/kvm_host.h
+++ b/arch/arm64/include/asm/kvm_host.h
@@ -16,6 +16,7 @@
#include <linux/types.h>
#include <linux/jump_label.h>
#include <linux/kvm_types.h>
+#include <linux/maple_tree.h>
#include <linux/percpu.h>
#include <linux/psci.h>
#include <asm/arch_gicv3.h>
@@ -213,7 +214,8 @@ struct kvm_arch {
#define KVM_ARCH_FLAG_EL1_32BIT 4
/* PSCI SYSTEM_SUSPEND enabled for the guest */
#define KVM_ARCH_FLAG_SYSTEM_SUSPEND_ENABLED 5
-
+ /* SMCCC filter initialized for the VM */
+#define KVM_ARCH_FLAG_SMCCC_FILTER_CONFIGURED 6
unsigned long flags;
/*
@@ -234,6 +236,7 @@ struct kvm_arch {
/* Hypercall features firmware registers' descriptor */
struct kvm_smccc_features smccc_feat;
+ struct maple_tree smccc_filter;
/*
* For an untrusted host VM, 'pkvm.handle' is used to lookup
diff --git a/arch/arm64/kvm/arm.c b/arch/arm64/kvm/arm.c
index 09efa893e03a..e04690caad77 100644
--- a/arch/arm64/kvm/arm.c
+++ b/arch/arm64/kvm/arm.c
@@ -202,6 +202,8 @@ void kvm_arch_destroy_vm(struct kvm *kvm)
kvm_destroy_vcpus(kvm);
kvm_unshare_hyp(kvm, kvm + 1);
+
+ kvm_arm_teardown_hypercalls(kvm);
}
int kvm_vm_ioctl_check_extension(struct kvm *kvm, long ext)
diff --git a/arch/arm64/kvm/hypercalls.c b/arch/arm64/kvm/hypercalls.c
index 980546b295b3..45b8371816fd 100644
--- a/arch/arm64/kvm/hypercalls.c
+++ b/arch/arm64/kvm/hypercalls.c
@@ -121,8 +121,39 @@ static bool kvm_smccc_test_fw_bmap(struct kvm_vcpu *vcpu, u32 func_id)
}
}
+static bool kvm_smccc_filter_configured(struct kvm *kvm)
+{
+ return test_bit(KVM_ARCH_FLAG_SMCCC_FILTER_CONFIGURED, &kvm->arch.flags);
+}
+
+static u8 kvm_smccc_filter_get_action(struct kvm *kvm, u32 func_id)
+{
+ unsigned long index = func_id;
+ void *val;
+
+ if (!kvm_smccc_filter_configured(kvm))
+ return KVM_SMCCC_FILTER_ALLOW;
+
+ /*
+ * But where's the error handling, you say?
+ *
+ * mt_find() returns NULL if no entry was found, which just so happens
+ * to match KVM_SMCCC_FILTER_ALLOW.
+ */
+ val = mt_find(&kvm->arch.smccc_filter, &index, index);
+ return xa_to_value(val);
+}
+
static u8 kvm_hvc_get_action(struct kvm_vcpu *vcpu, u32 func_id)
{
+ /*
+ * Intervening actions in the SMCCC filter take precedence over the
+ * pseudo-firmware register bitmaps.
+ */
+ u8 action = kvm_smccc_filter_get_action(vcpu->kvm, func_id);
+ if (action != KVM_SMCCC_FILTER_ALLOW)
+ return action;
+
if (kvm_smccc_default_call(func_id) ||
kvm_smccc_test_fw_bmap(vcpu, func_id))
return KVM_SMCCC_FILTER_ALLOW;
@@ -256,6 +287,13 @@ void kvm_arm_init_hypercalls(struct kvm *kvm)
smccc_feat->std_bmap = KVM_ARM_SMCCC_STD_FEATURES;
smccc_feat->std_hyp_bmap = KVM_ARM_SMCCC_STD_HYP_FEATURES;
smccc_feat->vendor_hyp_bmap = KVM_ARM_SMCCC_VENDOR_HYP_FEATURES;
+
+ mt_init(&kvm->arch.smccc_filter);
+}
+
+void kvm_arm_teardown_hypercalls(struct kvm *kvm)
+{
+ mtree_destroy(&kvm->arch.smccc_filter);
}
int kvm_arm_get_fw_num_regs(struct kvm_vcpu *vcpu)
diff --git a/include/kvm/arm_hypercalls.h b/include/kvm/arm_hypercalls.h
index 1188f116cf4e..ae1ada68cdc2 100644
--- a/include/kvm/arm_hypercalls.h
+++ b/include/kvm/arm_hypercalls.h
@@ -43,6 +43,7 @@ static inline void smccc_set_retval(struct kvm_vcpu *vcpu,
struct kvm_one_reg;
void kvm_arm_init_hypercalls(struct kvm *kvm);
+void kvm_arm_teardown_hypercalls(struct kvm *kvm);
int kvm_arm_get_fw_num_regs(struct kvm_vcpu *vcpu);
int kvm_arm_copy_fw_reg_indices(struct kvm_vcpu *vcpu, u64 __user *uindices);
int kvm_arm_get_fw_reg(struct kvm_vcpu *vcpu, const struct kvm_one_reg *reg);
--
2.39.1.581.gbfd45094c4-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:[~2023-02-11 2:01 UTC|newest]
Thread overview: 32+ messages / expand[flat|nested] mbox.gz Atom feed top
2023-02-11 1:37 [RFC PATCH v2 0/6] KVM: arm64: Userspace SMCCC call filtering Oliver Upton
2023-02-11 1:37 ` Oliver Upton
2023-02-11 1:37 ` [RFC PATCH v2 1/6] KVM: arm64: Add a helper to check if a VM has ran once Oliver Upton
2023-02-11 1:37 ` Oliver Upton
2023-02-13 15:36 ` Sean Christopherson
2023-02-13 15:36 ` Sean Christopherson
2023-02-13 15:49 ` Marc Zyngier
2023-02-13 15:49 ` Marc Zyngier
2023-02-11 1:37 ` [RFC PATCH v2 2/6] KVM: arm64: Add vm fd device attribute accessors Oliver Upton
2023-02-11 1:37 ` Oliver Upton
2023-02-11 1:37 ` [RFC PATCH v2 3/6] KVM: arm64: Refactor hvc filtering to support different actions Oliver Upton
2023-02-11 1:37 ` Oliver Upton
2023-02-11 1:37 ` Oliver Upton [this message]
2023-02-11 1:37 ` [RFC PATCH v2 4/6] KVM: arm64: Use a maple tree to represent the SMCCC filter Oliver Upton
2023-02-11 1:37 ` [RFC PATCH v2 5/6] KVM: arm64: Add support for KVM_EXIT_HYPERCALL Oliver Upton
2023-02-11 1:37 ` Oliver Upton
2023-02-13 16:01 ` Sean Christopherson
2023-02-13 16:01 ` Sean Christopherson
2023-02-13 19:24 ` Oliver Upton
2023-02-13 19:24 ` Oliver Upton
2023-02-24 15:12 ` James Morse
2023-02-24 15:12 ` James Morse
2023-02-24 21:42 ` Oliver Upton
2023-02-24 21:42 ` Oliver Upton
2023-02-11 1:37 ` [RFC PATCH v2 6/6] KVM: arm64: Indroduce support for userspace SMCCC filtering Oliver Upton
2023-02-11 1:37 ` Oliver Upton
2023-02-17 18:35 ` Oliver Upton
2023-02-17 18:35 ` Oliver Upton
2023-02-24 15:12 ` [RFC PATCH v2 0/6] KVM: arm64: Userspace SMCCC call filtering James Morse
2023-02-24 15:12 ` James Morse
2023-02-24 21:32 ` Oliver Upton
2023-02-24 21:32 ` Oliver Upton
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=20230211013759.3556016-5-oliver.upton@linux.dev \
--to=oliver.upton@linux.dev \
--cc=akihiko.odaki@daynix.com \
--cc=james.morse@arm.com \
--cc=kvmarm@lists.linux.dev \
--cc=linux-arm-kernel@lists.infradead.org \
--cc=maz@kernel.org \
--cc=rananta@google.com \
--cc=salil.mehta@huawei.com \
--cc=suzuki.poulose@arm.com \
--cc=yuzenghui@huawei.com \
/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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.