From: Daniel Vetter <daniel@ffwll.ch>
To: Zhigang Gong <zhigang.gong@linux.intel.com>
Cc: 'Brad Volkin' <bradley.d.volkin@intel.com>,
intel-gfx@lists.freedesktop.org
Subject: Re: [PATCH 1/3] drm/i915: Fix command parser to validate multiple register access with the same command.
Date: Mon, 15 Jun 2015 12:35:59 +0200 [thread overview]
Message-ID: <20150615103559.GX8341@phenom.ffwll.local> (raw)
In-Reply-To: <000901d09d17$99c5f380$cd51da80$@linux.intel.com>
On Tue, Jun 02, 2015 at 05:36:26PM +0800, Zhigang Gong wrote:
> The patchset LGTM and works well with beignet. The 80%+ performance regression issue in darktable also has been fixed
> after this patchset applied and enable the atomic in L3 at beignet side. So,
>
> Reviewed-by: Zhigang Gong <zhigang.gong@linux.intel.com>
All three merged. Aside: Dont we need an increment for the cmd parser
version for userspace to be able to detect this?
And please follow up with a link to the beignet patches used to validate
these kernel patches for references.
Thanks, Daniel
>
> Thanks,
> Zhigang Gong.
>
> > -----Original Message-----
> > From: Francisco Jerez [mailto:currojerez@riseup.net]
> > Sent: Friday, May 29, 2015 9:44 PM
> > To: intel-gfx@lists.freedesktop.org
> > Cc: Ville Syrjälä; Zhigang Gong; Brad Volkin
> > Subject: [PATCH 1/3] drm/i915: Fix command parser to validate multiple
> > register access with the same command.
> >
> > Until now the software command checker assumed that commands could read
> > or write at most a single register per packet. This is not necessarily the case,
> > MI_LOAD_REGISTER_IMM expects a variable-length list of offset/value pairs
> > and writes them in sequence. The previous code would only check whether
> > the first entry was valid, effectively allowing userspace to write unrestricted
> > registers of the MMIO space by sending a multi-register write with a legal first
> > register, with potential security implications on Gen6 and 7 hardware.
> >
> > Fix it by extending the drm_i915_cmd_descriptor table to represent
> > multi-register access and making validate_cmd() iterate for all register offsets
> > present in the command packet.
> >
> > Signed-off-by: Francisco Jerez <currojerez@riseup.net>
> > ---
> > drivers/gpu/drm/i915/i915_cmd_parser.c | 74
> > ++++++++++++++++++++--------------
> > drivers/gpu/drm/i915/i915_drv.h | 5 +++
> > 2 files changed, 48 insertions(+), 31 deletions(-)
> >
> > diff --git a/drivers/gpu/drm/i915/i915_cmd_parser.c
> > b/drivers/gpu/drm/i915/i915_cmd_parser.c
> > index 61ae8ff..c4a5f73 100644
> > --- a/drivers/gpu/drm/i915/i915_cmd_parser.c
> > +++ b/drivers/gpu/drm/i915/i915_cmd_parser.c
> > @@ -123,7 +123,7 @@ static const struct drm_i915_cmd_descriptor
> > common_cmds[] = {
> > CMD( MI_SEMAPHORE_MBOX, SMI, !F, 0xFF,
> > R ),
> > CMD( MI_STORE_DWORD_INDEX, SMI, !F, 0xFF,
> > R ),
> > CMD( MI_LOAD_REGISTER_IMM(1), SMI, !F, 0xFF,
> > W,
> > - .reg = { .offset = 1, .mask = 0x007FFFFC } ),
> > + .reg = { .offset = 1, .mask = 0x007FFFFC, .step = 2 } ),
> > CMD( MI_STORE_REGISTER_MEM(1), SMI, !F, 0xFF,
> > W | B,
> > .reg = { .offset = 1, .mask = 0x007FFFFC },
> > .bits = {{
> > @@ -939,7 +939,7 @@ bool i915_needs_cmd_parser(struct intel_engine_cs
> > *ring)
> >
> > static bool check_cmd(const struct intel_engine_cs *ring,
> > const struct drm_i915_cmd_descriptor *desc,
> > - const u32 *cmd,
> > + const u32 *cmd, u32 length,
> > const bool is_master,
> > bool *oacontrol_set)
> > {
> > @@ -955,38 +955,49 @@ static bool check_cmd(const struct intel_engine_cs
> > *ring,
> > }
> >
> > if (desc->flags & CMD_DESC_REGISTER) {
> > - u32 reg_addr = cmd[desc->reg.offset] & desc->reg.mask;
> > -
> > /*
> > - * OACONTROL requires some special handling for writes. We
> > - * want to make sure that any batch which enables OA also
> > - * disables it before the end of the batch. The goal is to
> > - * prevent one process from snooping on the perf data from
> > - * another process. To do that, we need to check the value
> > - * that will be written to the register. Hence, limit
> > - * OACONTROL writes to only MI_LOAD_REGISTER_IMM
> > commands.
> > + * Get the distance between individual register offset
> > + * fields if the command can perform more than one
> > + * access at a time.
> > */
> > - if (reg_addr == OACONTROL) {
> > - if (desc->cmd.value == MI_LOAD_REGISTER_MEM) {
> > - DRM_DEBUG_DRIVER("CMD: Rejected LRM to
> > OACONTROL\n");
> > - return false;
> > + const u32 step = desc->reg.step ? desc->reg.step : length;
> > + u32 offset;
> > +
> > + for (offset = desc->reg.offset; offset < length;
> > + offset += step) {
> > + const u32 reg_addr = cmd[offset] & desc->reg.mask;
> > +
> > + /*
> > + * OACONTROL requires some special handling for
> > + * writes. We want to make sure that any batch which
> > + * enables OA also disables it before the end of the
> > + * batch. The goal is to prevent one process from
> > + * snooping on the perf data from another process. To do
> > + * that, we need to check the value that will be written
> > + * to the register. Hence, limit OACONTROL writes to
> > + * only MI_LOAD_REGISTER_IMM commands.
> > + */
> > + if (reg_addr == OACONTROL) {
> > + if (desc->cmd.value == MI_LOAD_REGISTER_MEM) {
> > + DRM_DEBUG_DRIVER("CMD: Rejected LRM to
> > OACONTROL\n");
> > + return false;
> > + }
> > +
> > + if (desc->cmd.value == MI_LOAD_REGISTER_IMM(1))
> > + *oacontrol_set = (cmd[offset + 1] != 0);
> > }
> >
> > - if (desc->cmd.value == MI_LOAD_REGISTER_IMM(1))
> > - *oacontrol_set = (cmd[2] != 0);
> > - }
> > -
> > - if (!valid_reg(ring->reg_table,
> > - ring->reg_count, reg_addr)) {
> > - if (!is_master ||
> > - !valid_reg(ring->master_reg_table,
> > - ring->master_reg_count,
> > - reg_addr)) {
> > - DRM_DEBUG_DRIVER("CMD: Rejected register 0x%08X in
> > command: 0x%08X (ring=%d)\n",
> > - reg_addr,
> > - *cmd,
> > - ring->id);
> > - return false;
> > + if (!valid_reg(ring->reg_table,
> > + ring->reg_count, reg_addr)) {
> > + if (!is_master ||
> > + !valid_reg(ring->master_reg_table,
> > + ring->master_reg_count,
> > + reg_addr)) {
> > + DRM_DEBUG_DRIVER("CMD: Rejected register
> > 0x%08X in command: 0x%08X (ring=%d)\n",
> > + reg_addr, *cmd,
> > + ring->id);
> > + return false;
> > + }
> > }
> > }
> > }
> > @@ -1110,7 +1121,8 @@ int i915_parse_cmds(struct intel_engine_cs *ring,
> > break;
> > }
> >
> > - if (!check_cmd(ring, desc, cmd, is_master, &oacontrol_set)) {
> > + if (!check_cmd(ring, desc, cmd, length, is_master,
> > + &oacontrol_set)) {
> > ret = -EINVAL;
> > break;
> > }
> > diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
> > index 8ae6f7f..3850288 100644
> > --- a/drivers/gpu/drm/i915/i915_drv.h
> > +++ b/drivers/gpu/drm/i915/i915_drv.h
> > @@ -2228,10 +2228,15 @@ struct drm_i915_cmd_descriptor {
> > * Describes where to find a register address in the command to check
> > * against the ring's register whitelist. Only valid if flags has the
> > * CMD_DESC_REGISTER bit set.
> > + *
> > + * A non-zero step value implies that the command may access multiple
> > + * registers in sequence (e.g. LRI), in that case step gives the
> > + * distance in dwords between individual offset fields.
> > */
> > struct {
> > u32 offset;
> > u32 mask;
> > + u32 step;
> > } reg;
> >
> > #define MAX_CMD_DESC_BITMASKS 3
> > --
> > 2.3.5
>
> _______________________________________________
> Intel-gfx mailing list
> Intel-gfx@lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/intel-gfx
--
Daniel Vetter
Software Engineer, Intel Corporation
http://blog.ffwll.ch
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx
next prev parent reply other threads:[~2015-06-15 10:33 UTC|newest]
Thread overview: 13+ messages / expand[flat|nested] mbox.gz Atom feed top
2015-05-29 13:44 [PATCH 1/3] drm/i915: Fix command parser to validate multiple register access with the same command Francisco Jerez
2015-05-29 13:44 ` [PATCH 2/3] drm/i915: Extend the parser to check register writes against a mask/value pair Francisco Jerez
2015-05-29 13:44 ` [PATCH 3/3] drm/i915: Add SCRATCH1 and ROW_CHICKEN3 to the register whitelist Francisco Jerez
2015-06-02 9:36 ` [PATCH 1/3] drm/i915: Fix command parser to validate multiple register access with the same command Zhigang Gong
2015-06-02 11:02 ` Francisco Jerez
2015-06-15 10:35 ` Daniel Vetter [this message]
2015-06-15 11:18 ` Francisco Jerez
2015-06-15 11:26 ` Ville Syrjälä
2015-06-15 11:40 ` Daniel Vetter
2015-06-15 12:05 ` Francisco Jerez
2015-08-30 22:19 ` Francisco Jerez
2015-09-01 9:41 ` Daniel Vetter
2015-06-15 13:15 ` Jani Nikula
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=20150615103559.GX8341@phenom.ffwll.local \
--to=daniel@ffwll.ch \
--cc=bradley.d.volkin@intel.com \
--cc=intel-gfx@lists.freedesktop.org \
--cc=zhigang.gong@linux.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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox