linux-arm-msm.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Bjorn Andersson <bjorn.andersson@linaro.org>
To: Jordan Crouse <jcrouse@codeaurora.org>
Cc: freedreno@lists.freedesktop.org,
	linux-arm-msm <linux-arm-msm@vger.kernel.org>,
	ML dri-devel <dri-devel@lists.freedesktop.org>
Subject: Re: [PATCH 11/12] drm/msm: Add a quick and dirty PIL loader
Date: Mon, 5 Dec 2016 11:57:43 -0800	[thread overview]
Message-ID: <20161205195743.GM9322@tuxbot> (raw)
In-Reply-To: <1480361317-9937-12-git-send-email-jcrouse@codeaurora.org>

On Mon 28 Nov 11:28 PST 2016, Jordan Crouse wrote:

> In order to switch the GPU out of secure mode on most systems we
> need to load a zap shader into memory and get it authenticated
> and into the secure world.  All the bits and pieces to do
> the load are scattered throughout the kernel, but we need to
> bring everything together.
>
> Add a semi-custom loader that will read a MDT file and get
> it loaded and authenticated through SCM.
>

I've been trying to figure out a reasonable way to provide a
scm/pas/mdt-loader, but haven't come up with anything sane yet. Perhaps
it's better to provide helpers for the scm case and open code the MDT
loading in the non-scm driver. I think this is an okay approach for now.

But it's not a "PIL loader", that's just a side effect of reusing parts
of the existing PIL load in the Qualcomm tree. I would suggest just
making the subject "Add ZAP MDT loader".

Some minor comments below.

> Signed-off-by: Jordan Crouse <jcrouse@codeaurora.org>
> ---
>  drivers/gpu/drm/msm/adreno/a5xx_gpu.c | 166 ++++++++++++++++++++++++++++++++++
>  1 file changed, 166 insertions(+)
>
> diff --git a/drivers/gpu/drm/msm/adreno/a5xx_gpu.c b/drivers/gpu/drm/msm/adreno/a5xx_gpu.c
> index 3824bc4..eefe197 100644
> --- a/drivers/gpu/drm/msm/adreno/a5xx_gpu.c
> +++ b/drivers/gpu/drm/msm/adreno/a5xx_gpu.c
> @@ -11,12 +11,178 @@
>   *
>   */
>  
> +#include <linux/elf.h>
> +#include <linux/types.h>
> +#include <linux/cpumask.h>
> +#include <linux/qcom_scm.h>
> +#include <linux/dma-mapping.h>
> +#include <linux/of_reserved_mem.h>
>  #include "msm_gem.h"
>  #include "a5xx_gpu.h"
>  
>  extern bool hang_debug;
>  static void a5xx_dump(struct msm_gpu *gpu);
>  
> +static inline bool _check_segment(const struct elf32_phdr *phdr)
> +{
> + return ((phdr->p_type == PT_LOAD) &&
> + ((phdr->p_flags & (7 << 24)) != (2 << 24)) &&
> + phdr->p_memsz);
> +}
> +
> +static int __pil_tz_load_image(struct platform_device *pdev,

Rather than throwing more underscores at it I would have named this
"zap_load_segments".

> + const struct firmware *mdt, const char *fwname,
> + void *fwptr, size_t fw_size, unsigned long fw_min_addr)
> +{
> + char str[64] = { 0 };

Name this filename or similar and no need to initialize it.

> + const struct elf32_hdr *ehdr = (struct elf32_hdr *) mdt->data;
> + const struct elf32_phdr *phdrs = (struct elf32_phdr *) (ehdr + 1);
> + const struct firmware *fw;
> + int i, ret = 0;
> +
> + for (i = 0; i < ehdr->e_phnum; i++) {
> + const struct elf32_phdr *phdr = &phdrs[i];
> + size_t offset;
> +
> + /* Make sure the segment is loadable */
> + if (!_check_segment(phdr))
> + continue; > +
> + /* Get the offset of the segment within the region */
> + offset = (phdr->p_paddr - fw_min_addr);
> +
> + /* Request the file containing the segment */
> + snprintf(str, sizeof(str) - 1, "%s.b%02d", fwname, i);

snprintf(, size, ) writes at most size bytes and includes null
termination, so drop the "- 1".

> +
> + ret = request_firmware(&fw, str, &pdev->dev);
> + if (ret) {
> + dev_err(&pdev->dev, "Failed to load segment %s\n", str);
> + break;
> + }
> +
> + if (offset + fw->size > fw_size) {
> + dev_err(&pdev->dev, "Segment %s is too big\n", str);
> + ret = -EINVAL;
> + release_firmware(fw);
> + break;
> + }
> +
> + /* Copy the segment into place */
> + memcpy(fwptr + offset, fw->data, fw->size);

Just to be on the safe side, please add:

if (phdr->p_memsz > phdr->p_filesz)
memset(fwptr + fw->size, 0, phdr->p_memsz - phdr->p_filesz);

> + release_firmware(fw);
> + }
> +
> + return ret;
> +}
> +
> +static int _pil_tz_load_image(struct platform_device *pdev)

zap_load_mdt() ?

> +{
> + char str[64] = { 0 };
> + const char *fwname;
> + const struct elf32_hdr *ehdr;
> + const struct elf32_phdr *phdrs;
> + const struct firmware *mdt;
> + phys_addr_t fw_min_addr, fw_max_addr;
> + dma_addr_t fw_phys;
> + size_t fw_size;
> + u32 pas_id;
> + void *ptr;
> + int i, ret;
> +
> + if (pdev == NULL)
> + return -ENODEV;

This should not happen.

> +
> + if (!qcom_scm_is_available()) {
> + dev_err(&pdev->dev, "SCM is not available\n");
> + return -EINVAL;

We generally return -EPROBE_DEFER here.

> + }
> +
> + ret = of_reserved_mem_device_init(&pdev->dev);
> +

Please drop the extra newline.

> + if (ret) {
> + dev_err(&pdev->dev, "Unable to set up the reserved memory\n");
> + return ret;
> + }
> +
> + /* Get the firmware and PAS id from the device node */
> + if (of_property_read_string(pdev->dev.of_node, "qcom,firmware",
> + &fwname)) {
> + dev_err(&pdev->dev, "Could not read a firmware name\n");
> + return -EINVAL;
> + }
> +
> + if (of_property_read_u32(pdev->dev.of_node, "qcom,pas-id", &pas_id)) {

This is constant, so define it in the driver.

> + dev_err(&pdev->dev, "Could not read the pas ID\n");
> + return -EINVAL;
> + }
> +
> + snprintf(str, sizeof(str) - 1, "%s.mdt", fwname);

As above, re "- 1", name of str and initialization.

> +
> + /* Request the MDT file for the firmware */
> + ret = request_firmware(&mdt, str, &pdev->dev);
> + if (ret) {
> + dev_err(&pdev->dev, "Unable to load %s\n", str);
> + return ret;
> + }
> +
> + ehdr = (struct elf32_hdr *) mdt->data;
> + phdrs = (struct elf32_phdr *) (ehdr + 1);
> +
> + /* Get the extents of the firmware image */
> +
> + fw_min_addr = (phys_addr_t) ULLONG_MAX;
> + fw_max_addr = 0;
> +
> + for (i = 0; i < ehdr->e_phnum; i++) {
> + const struct elf32_phdr *phdr = &phdrs[i];
> +
> + if (!_check_segment(phdr))
> + continue;
> +
> + fw_min_addr = min_t(phys_addr_t, fw_min_addr, phdr->p_paddr);
> + fw_max_addr = max_t(phys_addr_t, fw_max_addr,
> + PAGE_ALIGN(phdr->p_paddr + phdr->p_memsz));
> + }
> +
> + if (fw_min_addr == (phys_addr_t) ULLONG_MAX && fw_max_addr == 0)
> + goto out;
> +
> + fw_size = (size_t) (fw_max_addr - fw_min_addr);
> +
> + /* Verify the MDT header */
> + ret = qcom_scm_pas_init_image(pas_id, mdt->data, mdt->size);
> + if (ret) {
> + dev_err(&pdev->dev, "Invalid firmware metadata\n");
> + goto out;
> + }
> +
> + /* allocate some memory */
> + ptr = dma_alloc_coherent(&pdev->dev, fw_size, &fw_phys, GFP_KERNEL);
> + if (ptr == NULL)
> + goto out;
> +
> + /* Set up the newly allocated memory region */
> + ret = qcom_scm_pas_mem_setup(pas_id, fw_phys, fw_size);
> + if (ret) {
> + dev_err(&pdev->dev, "Unable to set up firmware memory\n");
> + goto out;
> + }
> +
> + ret = __pil_tz_load_image(pdev, mdt, fwname, ptr, fw_size, fw_min_addr);
> + if (!ret) {

Please don't mix style like this, goto out on error.

> + ret = qcom_scm_pas_auth_and_reset(pas_id);
> + if (ret)
> + dev_err(&pdev->dev, "Unable to authorize the image\n");
> + }
> +
> +out:
> + if (ret && ptr)
> + dma_free_coherent(&pdev->dev, fw_size, ptr, fw_phys);
> +
> + release_firmware(mdt);
> + return ret;
> +}
> +

Regards,
Bjorn

  reply	other threads:[~2016-12-05 19:57 UTC|newest]

Thread overview: 34+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2016-11-28 19:28 [PATCH 00/12] Adreno A5XX support Jordan Crouse
2016-11-28 19:28 ` [PATCH 01/12] drm/msm: gpu: Cut down the list of "generic" registers to the ones we use Jordan Crouse
2016-11-28 19:28 ` [PATCH 03/12] drm/msm: gpu Add new gpu register read/write functions Jordan Crouse
2016-11-28 19:28 ` [PATCH 04/12] drm/msm: Add adreno_gpu_write64() Jordan Crouse
     [not found] ` <1480361317-9937-1-git-send-email-jcrouse-sgV2jX0FEOL9JmXXK+q4OQ@public.gmane.org>
2016-11-28 19:28   ` [PATCH 02/12] drm/msm: gpu: Return error on hw_init failure Jordan Crouse
2016-11-28 19:28   ` [PATCH 05/12] drm/msm: gpu: Add OUT_TYPE4 and OUT_TYPE7 Jordan Crouse
2016-11-28 19:28   ` [PATCH 06/12] drm/msm: Remove 'src_clk' from adreno configuration Jordan Crouse
2016-11-28 19:28 ` [PATCH 07/12] drm/msm: Disable interrupts during init Jordan Crouse
2016-11-28 19:28 ` [PATCH 08/12] drm/msm: gpu: Add A5XX target support Jordan Crouse
2016-11-28 19:28 ` [PATCH 09/12] drm/msm: gpu: Add support for the GPMU Jordan Crouse
2016-11-28 19:28 ` [PATCH 10/12] firmware: qcom_scm: Add qcom_scm_gpu_zap_resume() Jordan Crouse
2017-01-13 17:12   ` Andy Gross
     [not found]     ` <20170113171241.GH5710-3KkwrOJo9xYlRp7syxWybdHuzzzSOjJt@public.gmane.org>
2017-01-13 17:22       ` Jordan Crouse
     [not found]         ` <20170113172244.GA28592-9PYrDHPZ2Orvke4nUoYGnHL1okKdlPRT@public.gmane.org>
2017-01-13 17:45           ` Andy Gross
2017-01-13 23:24     ` [Freedreno] " Jordan Crouse
     [not found]       ` <20170113232438.GA24139-9PYrDHPZ2Orvke4nUoYGnHL1okKdlPRT@public.gmane.org>
2017-01-15  3:49         ` Andy Gross
2017-01-15  5:20           ` [Freedreno] " Andy Gross
2017-01-16 15:13             ` Stanimir Varbanov
2017-01-17 17:04             ` Jordan Crouse
     [not found]               ` <20170117170459.GA29647-9PYrDHPZ2Orvke4nUoYGnHL1okKdlPRT@public.gmane.org>
2017-01-17 19:31                 ` Andy Gross
     [not found]   ` <1480361317-9937-11-git-send-email-jcrouse-sgV2jX0FEOL9JmXXK+q4OQ@public.gmane.org>
2017-01-17  5:56     ` [PATCH] firmware: qcom_scm: Add set remote state API Andy Gross
     [not found]       ` <1484632578-4539-1-git-send-email-andy.gross-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
2017-01-18 16:51         ` Jordan Crouse
2017-01-18 17:37       ` Stanimir Varbanov
2017-01-24  9:54       ` Stanimir Varbanov
2017-01-24 16:11         ` Andy Gross
2016-11-28 19:28 ` [PATCH 11/12] drm/msm: Add a quick and dirty PIL loader Jordan Crouse
2016-12-05 19:57   ` Bjorn Andersson [this message]
2016-12-06 17:49     ` Jordan Crouse
2016-11-28 19:28 ` [PATCH 12/12] drm/msm: gpu: Use the zap shader on 5XX if we can Jordan Crouse
2016-12-05 19:57   ` Bjorn Andersson
2016-12-05 20:10     ` Bjorn Andersson
2016-12-06 15:35     ` Jordan Crouse
2016-12-06 16:37       ` [Freedreno] " Rob Clark
     [not found]       ` <20161206153501.GA25541-9PYrDHPZ2Orvke4nUoYGnHL1okKdlPRT@public.gmane.org>
2016-12-06 17:18         ` Bjorn Andersson

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=20161205195743.GM9322@tuxbot \
    --to=bjorn.andersson@linaro.org \
    --cc=dri-devel@lists.freedesktop.org \
    --cc=freedreno@lists.freedesktop.org \
    --cc=jcrouse@codeaurora.org \
    --cc=linux-arm-msm@vger.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).