diff mbox series

[RFC,12/16] target/arm/kvm-rme: Add Realm SVE vector length

Message ID 20230127150727.612594-13-jean-philippe@linaro.org (mailing list archive)
State New, archived
Headers show
Series arm: Run Arm CCA VMs with KVM | expand

Commit Message

Jean-Philippe Brucker Jan. 27, 2023, 3:07 p.m. UTC
The Realm configuration takes a SVE enable and vector length parameter.

We cannot reuse the -cpu SVE parameters for this because that
information is needed at Realm Descriptor creation which must happen
before VCPU creation.

Signed-off-by: Jean-Philippe Brucker <jean-philippe@linaro.org>
---
 qapi/qom.json        |  5 +++-
 target/arm/kvm-rme.c | 68 +++++++++++++++++++++++++++++++++++++++++++-
 2 files changed, 71 insertions(+), 2 deletions(-)

Comments

Richard Henderson Jan. 28, 2023, 12:22 a.m. UTC | #1
On 1/27/23 05:07, Jean-Philippe Brucker wrote:
> +static void rme_get_uint32(Object *obj, Visitor *v, const char *name,
> +                           void *opaque, Error **errp)
> +{
> +    RmeGuest *guest = RME_GUEST(obj);
> +    uint32_t value;
> +
> +    if (strcmp(name, "sve-vector-length") == 0) {
> +        value = guest->sve_vl;
> +    } else {
> +        g_assert_not_reached();
> +    }
> +
> +    visit_type_uint32(v, name, &value, errp);
> +}
> +
> +static void rme_set_uint32(Object *obj, Visitor *v, const char *name,
> +                           void *opaque, Error **errp)
> +{
> +    RmeGuest *guest = RME_GUEST(obj);
> +    uint32_t max_value;
> +    uint32_t value;
> +    uint32_t *var;
> +
> +    if (!visit_type_uint32(v, name, &value, errp)) {
> +        return;
> +    }
> +
> +    if (strcmp(name, "sve-vector-length") == 0) {
> +        max_value = ARM_MAX_VQ * 128;
> +        var = &guest->sve_vl;
> +        if (value & 0x7f) {
> +            error_setg(errp, "invalid SVE vector length %"PRIu32, value);
> +            return;
> +        }
> +    } else {
> +        g_assert_not_reached();
> +    }
> +
> +    if (value >= max_value) {
> +        error_setg(errp, "invalid %s length %"PRIu32, name, value);
> +        return;
> +    }
> +
> +    *var = value;
> +}

I don't think you should try to genericize these functions, comparing the name string. 
Just rename them and let them be specific to SVE.


r~
Richard Henderson Jan. 28, 2023, 12:31 a.m. UTC | #2
On 1/27/23 05:07, Jean-Philippe Brucker wrote:
> +static void rme_get_uint32(Object *obj, Visitor *v, const char *name,
> +                           void *opaque, Error **errp)
> +{
> +    RmeGuest *guest = RME_GUEST(obj);
> +    uint32_t value;
> +
> +    if (strcmp(name, "sve-vector-length") == 0) {
> +        value = guest->sve_vl;
> +    } else {
> +        g_assert_not_reached();
> +    }
> +
> +    visit_type_uint32(v, name, &value, errp);
> +}

Something I've used elsewhere just recently (and should probably make generic:

static void rme_get_uint32(...)
{
     intptr_t offset = (intptr_t)opaque;
     uint32_t *ptr = (void *)obj + offset;

     visit_type_uint32(v, name, ptr, errp);
}

     object_class_property_add(oc, "sve-vector-length", "uint32",
                               rme_get_uint32, rme_set_sve, NULL,
                               (void *)(intptr_t)offsetof(RmeGuest, sve_vl));


r~
diff mbox series

Patch

diff --git a/qapi/qom.json b/qapi/qom.json
index a012281628..94ecb87f6f 100644
--- a/qapi/qom.json
+++ b/qapi/qom.json
@@ -864,11 +864,14 @@ 
 #
 # @personalization-value: Realm personalization value (default: 0)
 #
+# @sve-vector-length: SVE vector length (default: 0, SVE disabled)
+#
 # Since: FIXME
 ##
 { 'struct': 'RmeGuestProperties',
   'data': { '*measurement-algo': 'str',
-            '*personalization-value': 'str' } }
+            '*personalization-value': 'str',
+            '*sve-vector-length': 'uint32' } }
 
 ##
 # @ObjectType:
diff --git a/target/arm/kvm-rme.c b/target/arm/kvm-rme.c
index e974c27e5c..0b2153a45c 100644
--- a/target/arm/kvm-rme.c
+++ b/target/arm/kvm-rme.c
@@ -22,7 +22,7 @@  OBJECT_DECLARE_SIMPLE_TYPE(RmeGuest, RME_GUEST)
 
 #define RME_PAGE_SIZE qemu_real_host_page_size()
 
-#define RME_MAX_CFG         2
+#define RME_MAX_CFG         3
 
 typedef struct RmeGuest RmeGuest;
 
@@ -30,6 +30,7 @@  struct RmeGuest {
     ConfidentialGuestSupport parent_obj;
     char *measurement_algo;
     char *personalization_value;
+    uint32_t sve_vl;
 };
 
 struct RmeImage {
@@ -137,6 +138,13 @@  static int rme_configure_one(RmeGuest *guest, uint32_t cfg, Error **errp)
         }
         cfg_str = "personalization value";
         break;
+    case KVM_CAP_ARM_RME_CFG_SVE:
+        if (!guest->sve_vl) {
+            return 0;
+        }
+        args.sve_vq = guest->sve_vl / 128;
+        cfg_str = "SVE";
+        break;
     default:
         g_assert_not_reached();
     }
@@ -346,6 +354,52 @@  static void rme_set_rpv(Object *obj, const char *value, Error **errp)
     guest->personalization_value = g_strdup(value);
 }
 
+static void rme_get_uint32(Object *obj, Visitor *v, const char *name,
+                           void *opaque, Error **errp)
+{
+    RmeGuest *guest = RME_GUEST(obj);
+    uint32_t value;
+
+    if (strcmp(name, "sve-vector-length") == 0) {
+        value = guest->sve_vl;
+    } else {
+        g_assert_not_reached();
+    }
+
+    visit_type_uint32(v, name, &value, errp);
+}
+
+static void rme_set_uint32(Object *obj, Visitor *v, const char *name,
+                           void *opaque, Error **errp)
+{
+    RmeGuest *guest = RME_GUEST(obj);
+    uint32_t max_value;
+    uint32_t value;
+    uint32_t *var;
+
+    if (!visit_type_uint32(v, name, &value, errp)) {
+        return;
+    }
+
+    if (strcmp(name, "sve-vector-length") == 0) {
+        max_value = ARM_MAX_VQ * 128;
+        var = &guest->sve_vl;
+        if (value & 0x7f) {
+            error_setg(errp, "invalid SVE vector length %"PRIu32, value);
+            return;
+        }
+    } else {
+        g_assert_not_reached();
+    }
+
+    if (value >= max_value) {
+        error_setg(errp, "invalid %s length %"PRIu32, name, value);
+        return;
+    }
+
+    *var = value;
+}
+
 static void rme_guest_class_init(ObjectClass *oc, void *data)
 {
     object_class_property_add_str(oc, "measurement-algo",
@@ -358,6 +412,18 @@  static void rme_guest_class_init(ObjectClass *oc, void *data)
                                   rme_set_rpv);
     object_class_property_set_description(oc, "personalization-value",
             "Realm personalization value (512-bit hexadecimal number)");
+
+    /*
+     * This is not ideal. Normally SVE parameters are given to -cpu, but the
+     * realm parameters are needed much earlier than CPU initialization. We also
+     * don't have a way to discover what is supported at the moment, the idea is
+     * that the user knows exactly what hardware it is running on because these
+     * parameters are part of the measurement and play in the attestation.
+     */
+    object_class_property_add(oc, "sve-vector-length", "uint32", rme_get_uint32,
+                              rme_set_uint32, NULL, NULL);
+    object_class_property_set_description(oc, "sve-vector-length",
+            "SVE vector length. 0 disables SVE (the default)");
 }
 
 static const TypeInfo rme_guest_info = {