[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [PATCH v5 3/9] xen/arm: add a primitive FF-A mediator



Hi Jens,

More remarks.

On 18/08/2022 11:55, Jens Wiklander wrote:
+/* Negotiated FF-A version to use with the SPMC */
+static uint32_t ffa_version __read_mostly;

NIT: if this is not meant to be modified after boot, then I would suggest to use __ro_after_init. This was introduced recently and will prevent the variable to be modified after boot.
+
+static bool ffa_get_version(uint32_t *vers)

This is not __init. Is this going to be called at runtime by a domain? If yes...

+{
+    const struct arm_smccc_1_2_regs arg = {
+        .a0 = FFA_VERSION,
+        .a1 = FFA_MY_VERSION,
+    };
+    struct arm_smccc_1_2_regs resp;
+
+    arm_smccc_1_2_smc(&arg, &resp);
+    if ( resp.a0 == FFA_RET_NOT_SUPPORTED )
+    {
+        printk(XENLOG_ERR "ffa: FFA_VERSION returned not supported\n");

... this wants to be a XENLOG_G_ERR to rate limited it. XENLOG_ERR is not by default and will allow a domain to spam Xen console.

A rule of thumb is any code reachable for a domain (other than dom0) should use XENLOG_G_* when printing or gprintk(XENLOG_*, ) if you want to print the domain ID and ratelimit. Note that the latter doesn't require the G_* becauce it will add it automatically.

+        return false;
+    }
+
+    *vers = resp.a0;
+
+    return true;
+}
+
+static u16 get_vm_id(const struct domain *d)
+{
+    /* +1 since 0 is reserved for the hypervisor in FF-A */
+    return d->domain_id + 1;
+}
+
+static void set_regs(struct cpu_user_regs *regs, register_t v0, register_t v1,
+                     register_t v2, register_t v3, register_t v4, register_t 
v5,
+                     register_t v6, register_t v7)
+{
+        set_user_reg(regs, 0, v0);
+        set_user_reg(regs, 1, v1);
+        set_user_reg(regs, 2, v2);
+        set_user_reg(regs, 3, v3);
+        set_user_reg(regs, 4, v4);
+        set_user_reg(regs, 5, v5);
+        set_user_reg(regs, 6, v6);
+        set_user_reg(regs, 7, v7);
+}
+
+static void set_regs_success(struct cpu_user_regs *regs, uint32_t w2,
+                             uint32_t w3)
+{
+    set_regs(regs, FFA_SUCCESS_32, 0, w2, w3, 0, 0, 0, 0);
+}
+
+static void handle_version(struct cpu_user_regs *regs)
+{
+    struct domain *d = current->domain;
+    struct ffa_ctx *ctx = d->arch.ffa;
+    uint32_t vers = get_user_reg(regs, 1);
+
+    if ( vers < FFA_VERSION_1_1 )
+        vers = FFA_VERSION_1_0;
+    else
+        vers = FFA_VERSION_1_1;
+
+    ctx->guest_vers = vers;
+    set_regs(regs, vers, 0, 0, 0, 0, 0, 0, 0);
+}
+
+bool ffa_handle_call(struct cpu_user_regs *regs, uint32_t fid)
+{
+    struct domain *d = current->domain;
+    struct ffa_ctx *ctx = d->arch.ffa;
+
+    if ( !ctx )
+        return false;
+
+    switch ( fid )
+    {
+    case FFA_VERSION:
+        handle_version(regs);
+        return true;
+    case FFA_ID_GET:
+        set_regs_success(regs, get_vm_id(d), 0);
+        return true;
+
+    default:
+        printk(XENLOG_ERR "ffa: unhandled fid 0x%x\n", fid);

This one definitely want to be a XENLOG_G_ERR. But I would use gprintk(XENLOG_ERR, ).

Cheers,

--
Julien Grall



 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.