lkml.org 
[lkml]   [2021]   [Apr]   [6]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    Date
    Subject[PATCH v2 4/8] crypto: ccp: Play nice with vmalloc'd memory for SEV command structs
    From
    Copy the incoming @data comman to an internal buffer so that callers can
    put SEV command buffers on the stack without running afoul of
    CONFIG_VMAP_STACK=y, i.e. without bombing on vmalloc'd pointers. As of
    today, the largest supported command takes a 68 byte buffer, i.e. pretty
    much every command can be put on the stack. Because sev_cmd_mutex is
    held for the entirety of a transaction, only a single bounce buffer is
    required.

    Use the internal buffer unconditionally, as the majority of in-kernel
    users will soon switch to using the stack. At that point, checking
    virt_addr_valid() becomes (negligible) overhead in most cases, and
    supporting both paths slightly increases complexity. Since the commands
    are all quite small, the cost of the copies is insignificant compared to
    the latency of communicating with the PSP.

    Allocate a full page for the buffer as opportunistic preparation for
    SEV-SNP, which requires the command buffer to be in firmware state for
    commands that trigger memory writes from the PSP firmware. Using a full
    page now will allow SEV-SNP support to simply transition the page as
    needed.

    Cc: Brijesh Singh <brijesh.singh@amd.com>
    Cc: Borislav Petkov <bp@suse.de>
    Cc: Tom Lendacky <thomas.lendacky@amd.com>
    Cc: Christophe Leroy <christophe.leroy@csgroup.eu>
    Signed-off-by: Sean Christopherson <seanjc@google.com>
    ---
    drivers/crypto/ccp/sev-dev.c | 28 +++++++++++++++++++++++-----
    drivers/crypto/ccp/sev-dev.h | 2 ++
    2 files changed, 25 insertions(+), 5 deletions(-)

    diff --git a/drivers/crypto/ccp/sev-dev.c b/drivers/crypto/ccp/sev-dev.c
    index 47a372e07223..4aedbdaffe90 100644
    --- a/drivers/crypto/ccp/sev-dev.c
    +++ b/drivers/crypto/ccp/sev-dev.c
    @@ -155,12 +155,17 @@ static int __sev_do_cmd_locked(int cmd, void *data, int *psp_ret)
    if (WARN_ON_ONCE(!data != !buf_len))
    return -EINVAL;

    - if (data && WARN_ON_ONCE(!virt_addr_valid(data)))
    - return -EINVAL;
    + /*
    + * Copy the incoming data to driver's scratch buffer as __pa() will not
    + * work for some memory, e.g. vmalloc'd addresses, and @data may not be
    + * physically contiguous.
    + */
    + if (data)
    + memcpy(sev->cmd_buf, data, buf_len);

    /* Get the physical address of the command buffer */
    - phys_lsb = data ? lower_32_bits(__psp_pa(data)) : 0;
    - phys_msb = data ? upper_32_bits(__psp_pa(data)) : 0;
    + phys_lsb = data ? lower_32_bits(__psp_pa(sev->cmd_buf)) : 0;
    + phys_msb = data ? upper_32_bits(__psp_pa(sev->cmd_buf)) : 0;

    dev_dbg(sev->dev, "sev command id %#x buffer 0x%08x%08x timeout %us\n",
    cmd, phys_msb, phys_lsb, psp_timeout);
    @@ -204,6 +209,13 @@ static int __sev_do_cmd_locked(int cmd, void *data, int *psp_ret)
    print_hex_dump_debug("(out): ", DUMP_PREFIX_OFFSET, 16, 2, data,
    buf_len, false);

    + /*
    + * Copy potential output from the PSP back to data. Do this even on
    + * failure in case the caller wants to glean something from the error.
    + */
    + if (data)
    + memcpy(data, sev->cmd_buf, buf_len);
    +
    return ret;
    }

    @@ -984,6 +996,10 @@ int sev_dev_init(struct psp_device *psp)
    if (!sev)
    goto e_err;

    + sev->cmd_buf = (void *)devm_get_free_pages(dev, GFP_KERNEL, 0);
    + if (!sev->cmd_buf)
    + goto e_sev;
    +
    psp->sev_data = sev;

    sev->dev = dev;
    @@ -995,7 +1011,7 @@ int sev_dev_init(struct psp_device *psp)
    if (!sev->vdata) {
    ret = -ENODEV;
    dev_err(dev, "sev: missing driver data\n");
    - goto e_sev;
    + goto e_buf;
    }

    psp_set_sev_irq_handler(psp, sev_irq_handler, sev);
    @@ -1010,6 +1026,8 @@ int sev_dev_init(struct psp_device *psp)

    e_irq:
    psp_clear_sev_irq_handler(psp);
    +e_buf:
    + devm_free_pages(dev, (unsigned long)sev->cmd_buf);
    e_sev:
    devm_kfree(dev, sev);
    e_err:
    diff --git a/drivers/crypto/ccp/sev-dev.h b/drivers/crypto/ccp/sev-dev.h
    index dd5c4fe82914..e1572f408577 100644
    --- a/drivers/crypto/ccp/sev-dev.h
    +++ b/drivers/crypto/ccp/sev-dev.h
    @@ -52,6 +52,8 @@ struct sev_device {
    u8 api_major;
    u8 api_minor;
    u8 build;
    +
    + void *cmd_buf;
    };

    int sev_dev_init(struct psp_device *psp);
    --
    2.31.0.208.g409f899ff0-goog
    \
     
     \ /
      Last update: 2021-04-07 00:52    [W:3.333 / U:0.012 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site