From: Jani Nikula <jani.nikula@linux.intel.com>
To: Lucas De Marchi <lucas.demarchi@intel.com>,
intel-gfx@lists.freedesktop.org
Subject: Re: [PATCH 4/4] drm/i915/bios: do not discard address space
Date: Fri, 08 Nov 2019 13:14:03 +0200 [thread overview]
Message-ID: <87eeyi62o4.fsf@intel.com> (raw)
In-Reply-To: <20191108003602.33526-4-lucas.demarchi@intel.com>
On Thu, 07 Nov 2019, Lucas De Marchi <lucas.demarchi@intel.com> wrote:
> When we are mapping the VBT through pci_map_rom() we may not be allowed
> to simply discard the address space and go on reading the memory. After
> checking on my test system that dumping the rom via sysfs I could
> actually get the correct vbt, I decided to change the implementation to
> use the same approach, by calling memcpy_fromio().
>
> In order to avoid copying the entire oprom this implements a simple
> memmem() searching for "$VBT". Contrary to the previous implementation
> this also takes care of not issuing unaligned PCI reads that would
> otherwise get translated into more even more reads. I also vaguely
> remember unaligned reads failing in the past with some devices.
>
> Also make sure we copy only the VBT and not the entire oprom that is
> usually much larger.
So you have
1. a fix to unaligned reads
2. an optimization to avoid reading individual bytes four times
3. respecting __iomem and copying (I guess these are tied together)
Seems to me that really should be at least three patches. Not
necessarily in the above order.
Follow-up: store pointer to the oprom vbt somewhere under i915->vbt, and
have debugfs i915_vbt() handle that properly.
>
> Signed-off-by: Lucas De Marchi <lucas.demarchi@intel.com>
> ---
> drivers/gpu/drm/i915/display/intel_bios.c | 95 +++++++++++++++++++----
> 1 file changed, 79 insertions(+), 16 deletions(-)
>
> diff --git a/drivers/gpu/drm/i915/display/intel_bios.c b/drivers/gpu/drm/i915/display/intel_bios.c
> index 671bbce6ba5b..c401e90b7cf1 100644
> --- a/drivers/gpu/drm/i915/display/intel_bios.c
> +++ b/drivers/gpu/drm/i915/display/intel_bios.c
> @@ -1806,31 +1806,88 @@ bool intel_bios_is_valid_vbt(const void *buf, size_t size)
> return vbt;
> }
>
> -static const struct vbt_header *find_vbt(void __iomem *oprom, size_t size)
> +void __iomem *find_vbt(void __iomem *oprom, size_t size)
> {
> - size_t i;
> + const u32 MAGIC = *((const u32 *)"$VBT");
> + size_t done = 0, cur = 0;
> + void __iomem *p;
> + u8 buf[128];
> + u32 val;
>
> - /* Scour memory looking for the VBT signature. */
> - for (i = 0; i + 4 < size; i++) {
> - void *vbt;
> + /*
> + * poor's man memmem() with sizeof(buf) window to avoid frequent
> + * wrap-arounds and using u32 for comparison. This gives us 4
> + * comparisons per ioread32() and avoids unaligned io reads (although it
> + * still does unaligned cpu access).
> + */
If we're really worried about performance here, and use a local buffer
to optimize the wraparounds, would it actually be more efficient to use
memcpy_fromio() which has an arch specific implementation in asm?
In any case makes you think you should first have the patch that the
patch subject claims, fix unaligned reads and add optimizations
next. This one does too much.
BR,
Jani.
> + for (p = oprom; p < oprom + size; p += 4) {
> + *(u32 *)(&buf[done]) = ioread32(p);
> + done += 4;
>
> - if (ioread32(oprom + i) != *((const u32 *)"$VBT"))
> - continue;
> + while (cur + 4 <= done) {
> + val = *(u32 *)(buf + cur);
> + if (val == MAGIC)
> + return p - (done - cur) + 4;
>
> - /*
> - * This is the one place where we explicitly discard the address
> - * space (__iomem) of the BIOS/VBT.
> - */
> - vbt = (void __force *)oprom + i;
> - if (intel_bios_is_valid_vbt(vbt, size - i))
> - return vbt;
> + cur++;
> + }
>
> - break;
> + /* wrap-around */
> + if (done + 4 >= sizeof(buf)) {
> + buf[0] = buf[done - 3];
> + buf[1] = buf[done - 2];
> + buf[2] = buf[done - 1];
> + cur = 0;
> + done = 3;
> + }
> }
>
> + /* Read the entire oprom and no VBT found */
> return NULL;
> }
>
> +/*
> + * Copy vbt to a new allocated buffer and update @psize to match the VBT
> + * size
> + */
> +static struct vbt_header *copy_vbt(void __iomem *oprom, size_t *psize)
> +{
> + off_t vbt_size_offset = offsetof(struct vbt_header, vbt_size);
> + struct vbt_header *vbt;
> + void __iomem *p;
> + u16 vbt_size;
> + size_t size;
> +
> + size = *psize;
> + p = find_vbt(oprom, size);
> + if (!p)
> + return NULL;
> +
> + size -= p - oprom;
> +
> + /*
> + * We need to at least be able to read the size and make sure it doesn't
> + * overflow the oprom. The rest will be validated later.
> + */
> + if (sizeof(*vbt) > size) {
> + DRM_DEBUG_DRIVER("VBT header incomplete\n");
> + return NULL;
> + }
> +
> + vbt_size = ioread16(p + vbt_size_offset);
> + if (vbt_size > size) {
> + DRM_DEBUG_DRIVER("VBT incomplete\n");
> + return NULL;
> + }
> +
> + vbt = kmalloc(vbt_size, GFP_KERNEL);
> + memcpy_fromio(vbt, p, vbt_size);
> +
> + *psize = vbt_size;
> +
> + return vbt;
> +}
> +
> /**
> * intel_bios_init - find VBT and initialize settings from the BIOS
> * @dev_priv: i915 device instance
> @@ -1861,10 +1918,13 @@ void intel_bios_init(struct drm_i915_private *dev_priv)
> if (!oprom)
> goto out;
>
> - vbt = find_vbt(oprom, size);
> + vbt = copy_vbt(oprom, &size);
> if (!vbt)
> goto out;
>
> + if (!intel_bios_is_valid_vbt(vbt, size))
> + goto out;
> +
> DRM_DEBUG_KMS("Found valid VBT in PCI ROM\n");
> }
>
> @@ -1897,6 +1957,9 @@ void intel_bios_init(struct drm_i915_private *dev_priv)
>
> if (oprom)
> pci_unmap_rom(pdev, oprom);
> +
> + if (vbt != dev_priv->opregion.vbt)
> + kfree(vbt);
> }
>
> /**
--
Jani Nikula, Intel Open Source Graphics Center
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx
WARNING: multiple messages have this Message-ID (diff)
From: Jani Nikula <jani.nikula@linux.intel.com>
To: Lucas De Marchi <lucas.demarchi@intel.com>,
intel-gfx@lists.freedesktop.org
Subject: Re: [Intel-gfx] [PATCH 4/4] drm/i915/bios: do not discard address space
Date: Fri, 08 Nov 2019 13:14:03 +0200 [thread overview]
Message-ID: <87eeyi62o4.fsf@intel.com> (raw)
Message-ID: <20191108111403.OIKFOG6vKwVJVsquzC1qb8oW6wFBRM3BamrGYHzMnrE@z> (raw)
In-Reply-To: <20191108003602.33526-4-lucas.demarchi@intel.com>
On Thu, 07 Nov 2019, Lucas De Marchi <lucas.demarchi@intel.com> wrote:
> When we are mapping the VBT through pci_map_rom() we may not be allowed
> to simply discard the address space and go on reading the memory. After
> checking on my test system that dumping the rom via sysfs I could
> actually get the correct vbt, I decided to change the implementation to
> use the same approach, by calling memcpy_fromio().
>
> In order to avoid copying the entire oprom this implements a simple
> memmem() searching for "$VBT". Contrary to the previous implementation
> this also takes care of not issuing unaligned PCI reads that would
> otherwise get translated into more even more reads. I also vaguely
> remember unaligned reads failing in the past with some devices.
>
> Also make sure we copy only the VBT and not the entire oprom that is
> usually much larger.
So you have
1. a fix to unaligned reads
2. an optimization to avoid reading individual bytes four times
3. respecting __iomem and copying (I guess these are tied together)
Seems to me that really should be at least three patches. Not
necessarily in the above order.
Follow-up: store pointer to the oprom vbt somewhere under i915->vbt, and
have debugfs i915_vbt() handle that properly.
>
> Signed-off-by: Lucas De Marchi <lucas.demarchi@intel.com>
> ---
> drivers/gpu/drm/i915/display/intel_bios.c | 95 +++++++++++++++++++----
> 1 file changed, 79 insertions(+), 16 deletions(-)
>
> diff --git a/drivers/gpu/drm/i915/display/intel_bios.c b/drivers/gpu/drm/i915/display/intel_bios.c
> index 671bbce6ba5b..c401e90b7cf1 100644
> --- a/drivers/gpu/drm/i915/display/intel_bios.c
> +++ b/drivers/gpu/drm/i915/display/intel_bios.c
> @@ -1806,31 +1806,88 @@ bool intel_bios_is_valid_vbt(const void *buf, size_t size)
> return vbt;
> }
>
> -static const struct vbt_header *find_vbt(void __iomem *oprom, size_t size)
> +void __iomem *find_vbt(void __iomem *oprom, size_t size)
> {
> - size_t i;
> + const u32 MAGIC = *((const u32 *)"$VBT");
> + size_t done = 0, cur = 0;
> + void __iomem *p;
> + u8 buf[128];
> + u32 val;
>
> - /* Scour memory looking for the VBT signature. */
> - for (i = 0; i + 4 < size; i++) {
> - void *vbt;
> + /*
> + * poor's man memmem() with sizeof(buf) window to avoid frequent
> + * wrap-arounds and using u32 for comparison. This gives us 4
> + * comparisons per ioread32() and avoids unaligned io reads (although it
> + * still does unaligned cpu access).
> + */
If we're really worried about performance here, and use a local buffer
to optimize the wraparounds, would it actually be more efficient to use
memcpy_fromio() which has an arch specific implementation in asm?
In any case makes you think you should first have the patch that the
patch subject claims, fix unaligned reads and add optimizations
next. This one does too much.
BR,
Jani.
> + for (p = oprom; p < oprom + size; p += 4) {
> + *(u32 *)(&buf[done]) = ioread32(p);
> + done += 4;
>
> - if (ioread32(oprom + i) != *((const u32 *)"$VBT"))
> - continue;
> + while (cur + 4 <= done) {
> + val = *(u32 *)(buf + cur);
> + if (val == MAGIC)
> + return p - (done - cur) + 4;
>
> - /*
> - * This is the one place where we explicitly discard the address
> - * space (__iomem) of the BIOS/VBT.
> - */
> - vbt = (void __force *)oprom + i;
> - if (intel_bios_is_valid_vbt(vbt, size - i))
> - return vbt;
> + cur++;
> + }
>
> - break;
> + /* wrap-around */
> + if (done + 4 >= sizeof(buf)) {
> + buf[0] = buf[done - 3];
> + buf[1] = buf[done - 2];
> + buf[2] = buf[done - 1];
> + cur = 0;
> + done = 3;
> + }
> }
>
> + /* Read the entire oprom and no VBT found */
> return NULL;
> }
>
> +/*
> + * Copy vbt to a new allocated buffer and update @psize to match the VBT
> + * size
> + */
> +static struct vbt_header *copy_vbt(void __iomem *oprom, size_t *psize)
> +{
> + off_t vbt_size_offset = offsetof(struct vbt_header, vbt_size);
> + struct vbt_header *vbt;
> + void __iomem *p;
> + u16 vbt_size;
> + size_t size;
> +
> + size = *psize;
> + p = find_vbt(oprom, size);
> + if (!p)
> + return NULL;
> +
> + size -= p - oprom;
> +
> + /*
> + * We need to at least be able to read the size and make sure it doesn't
> + * overflow the oprom. The rest will be validated later.
> + */
> + if (sizeof(*vbt) > size) {
> + DRM_DEBUG_DRIVER("VBT header incomplete\n");
> + return NULL;
> + }
> +
> + vbt_size = ioread16(p + vbt_size_offset);
> + if (vbt_size > size) {
> + DRM_DEBUG_DRIVER("VBT incomplete\n");
> + return NULL;
> + }
> +
> + vbt = kmalloc(vbt_size, GFP_KERNEL);
> + memcpy_fromio(vbt, p, vbt_size);
> +
> + *psize = vbt_size;
> +
> + return vbt;
> +}
> +
> /**
> * intel_bios_init - find VBT and initialize settings from the BIOS
> * @dev_priv: i915 device instance
> @@ -1861,10 +1918,13 @@ void intel_bios_init(struct drm_i915_private *dev_priv)
> if (!oprom)
> goto out;
>
> - vbt = find_vbt(oprom, size);
> + vbt = copy_vbt(oprom, &size);
> if (!vbt)
> goto out;
>
> + if (!intel_bios_is_valid_vbt(vbt, size))
> + goto out;
> +
> DRM_DEBUG_KMS("Found valid VBT in PCI ROM\n");
> }
>
> @@ -1897,6 +1957,9 @@ void intel_bios_init(struct drm_i915_private *dev_priv)
>
> if (oprom)
> pci_unmap_rom(pdev, oprom);
> +
> + if (vbt != dev_priv->opregion.vbt)
> + kfree(vbt);
> }
>
> /**
--
Jani Nikula, Intel Open Source Graphics Center
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx
next prev parent reply other threads:[~2019-11-08 11:14 UTC|newest]
Thread overview: 44+ messages / expand[flat|nested] mbox.gz Atom feed top
2019-11-08 0:35 [PATCH 1/4] drm/i915/opregion: fix leaking fw on error path Lucas De Marchi
2019-11-08 0:35 ` [Intel-gfx] " Lucas De Marchi
2019-11-08 0:36 ` [PATCH 2/4] drm/i915/bios: rename bios to oprom when mapping pci rom Lucas De Marchi
2019-11-08 0:36 ` [Intel-gfx] " Lucas De Marchi
2019-11-08 10:01 ` Jani Nikula
2019-11-08 10:01 ` [Intel-gfx] " Jani Nikula
2019-11-08 0:36 ` [PATCH 3/4] drm/i915/bios: make sure to check vbt size Lucas De Marchi
2019-11-08 0:36 ` [Intel-gfx] " Lucas De Marchi
2019-11-08 10:08 ` Jani Nikula
2019-11-08 10:08 ` [Intel-gfx] " Jani Nikula
2019-11-08 17:41 ` Lucas De Marchi
2019-11-08 17:41 ` [Intel-gfx] " Lucas De Marchi
2019-11-08 0:36 ` [PATCH 4/4] drm/i915/bios: do not discard address space Lucas De Marchi
2019-11-08 0:36 ` [Intel-gfx] " Lucas De Marchi
2019-11-08 11:14 ` Jani Nikula [this message]
2019-11-08 11:14 ` Jani Nikula
2019-11-08 18:18 ` Lucas De Marchi
2019-11-08 18:18 ` [Intel-gfx] " Lucas De Marchi
2019-11-08 19:19 ` Ville Syrjälä
2019-11-08 19:19 ` [Intel-gfx] " Ville Syrjälä
2019-11-08 20:14 ` Lucas De Marchi
2019-11-08 20:14 ` [Intel-gfx] " Lucas De Marchi
2019-11-08 21:02 ` Ville Syrjälä
2019-11-08 21:02 ` [Intel-gfx] " Ville Syrjälä
2019-11-08 21:09 ` Lucas De Marchi
2019-11-08 21:09 ` [Intel-gfx] " Lucas De Marchi
2019-11-11 11:10 ` Jani Nikula
2019-11-11 11:10 ` [Intel-gfx] " Jani Nikula
2019-11-10 16:57 ` kbuild test robot
2019-11-10 16:57 ` [Intel-gfx] " kbuild test robot
2019-11-10 16:57 ` kbuild test robot
2019-11-10 16:57 ` [RFC PATCH] drm/i915/bios: find_vbt() can be static kbuild test robot
2019-11-10 16:57 ` kbuild test robot
2019-11-10 16:57 ` [Intel-gfx] " kbuild test robot
2019-11-08 1:53 ` ✗ Fi.CI.SPARSE: warning for series starting with [1/4] drm/i915/opregion: fix leaking fw on error path Patchwork
2019-11-08 1:53 ` [Intel-gfx] " Patchwork
2019-11-08 2:18 ` ✓ Fi.CI.BAT: success " Patchwork
2019-11-08 2:18 ` [Intel-gfx] " Patchwork
2019-11-08 9:16 ` [PATCH 1/4] " Jani Nikula
2019-11-08 9:16 ` [Intel-gfx] " Jani Nikula
2019-11-08 17:34 ` Lucas De Marchi
2019-11-08 17:34 ` [Intel-gfx] " Lucas De Marchi
2019-11-09 13:23 ` ✓ Fi.CI.IGT: success for series starting with [1/4] " Patchwork
2019-11-09 13:23 ` [Intel-gfx] " Patchwork
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=87eeyi62o4.fsf@intel.com \
--to=jani.nikula@linux.intel.com \
--cc=intel-gfx@lists.freedesktop.org \
--cc=lucas.demarchi@intel.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.