All of lore.kernel.org
 help / color / mirror / Atom feed
From: Joonas Lahtinen <joonas.lahtinen@linux.intel.com>
To: Jackie Li <yaodong.li@intel.com>, intel-gfx@lists.freedesktop.org
Subject: Re: [PATCH v9 6/7] drm/i915/guc: Check the locking status of GuC WOPCM registers
Date: Fri, 09 Feb 2018 12:47:15 +0200	[thread overview]
Message-ID: <151817323518.4964.3002962792973105876@jlahtine-desk.ger.corp.intel.com> (raw)
In-Reply-To: <1518131035-24108-6-git-send-email-yaodong.li@intel.com>

Quoting Jackie Li (2018-02-09 01:03:54)
> GuC WOPCM registers are write-once registers. Current driver code accesses
> these registers without checking the accessibility to these registers which
> will lead to unpredictable driver behaviors if these registers were touch
> by other components (such as faulty BIOS code).
> 
> This patch moves the GuC WOPCM registers updating code into
> intel_guc_wopcm.c and adds check before and after the update to GuC WOPCM
> registers so that we can make sure the driver is in a known state before
> and after writing to these write-once registers.
> 
> v6:
>  - Made sure module reloading won't bug the kernel while doing
>    locking status checking
> 
> v7:
>  - Fixed patch format issues
> 
> v8:
>  - Fixed coding style issue on register lock bit macro definition (Sagar)
> 
> v9:
>  - Avoided to use redundant !! to cast uint to bool (Chris)
>  - Return error code instead of GEM_BUG_ON for locked with invalid register
>    values case (Sagar)
>  - Updated guc_wopcm_hw_init to use guc_wopcm as first parameter (Michal)
>  - Added code to set and validate the HuC_LOADING_AGENT_GUC bit in GuC
>    WOPCM offset register based on the presence of HuC firmware (Michal)
>  - Use bit fields instead of macros for GuC WOPCM flags (Michal)
> 
> Cc: Michal Wajdeczko <michal.wajdeczko@intel.com>
> Cc: Chris Wilson <chris@chris-wilson.co.uk>
> Cc: Joonas Lahtinen <joonas.lahtinen@linux.intel.com>
> Signed-off-by: Jackie Li <yaodong.li@intel.com>

<SNIP>

> +++ b/drivers/gpu/drm/i915/intel_guc_wopcm.c
> +static inline bool guc_wopcm_locked(struct intel_guc *guc)
> +{
> +       struct drm_i915_private *i915 = guc_to_i915(guc);
> +       bool size_reg_locked = __reg_locked(i915, GUC_WOPCM_SIZE);
> +       bool offset_reg_locked = __reg_locked(i915, DMA_GUC_WOPCM_OFFSET);
> +
> +       return size_reg_locked && offset_reg_locked;

Hmm, isn't this supposed to be || instead, if either of the registers is
locked, we can't really do much?

> +static inline void guc_wopcm_hw_update(struct intel_guc *guc)
> +{
> +       struct drm_i915_private *dev_priv = guc_to_i915(guc);
> +       u32 offset_reg_val;
> +
> +       /* GuC WOPCM registers should be unlocked at this point. */
> +       GEM_BUG_ON(__reg_locked(dev_priv, GUC_WOPCM_SIZE));
> +       GEM_BUG_ON(__reg_locked(dev_priv, DMA_GUC_WOPCM_OFFSET));
> +
> +       offset_reg_val = guc->wopcm.offset;
> +       if (guc->wopcm.need_load_huc_fw)

"load_huc_fw" would read better here.

> +               offset_reg_val |= HUC_LOADING_AGENT_GUC;
> +
> +       I915_WRITE(GUC_WOPCM_SIZE, guc->wopcm.size);
> +       I915_WRITE(DMA_GUC_WOPCM_OFFSET, offset_reg_val);
> +
> +       GEM_BUG_ON(!__reg_locked(dev_priv, GUC_WOPCM_SIZE));
> +       GEM_BUG_ON(!__reg_locked(dev_priv, DMA_GUC_WOPCM_OFFSET));

This could use static inline write_lockable_reg() helper with a return value.
I think we need to propagate the error all the way up the chain, as it's
not a driver programmer error if these registers are locked, instead it is
likely to be a BIOS problem.

In the helper we could also test if the value is locked but happens to
match what we were intending to write, then we could call it success and
maybe emit an INFO message.

> +}
> +
> +static inline bool guc_wopcm_regs_valid(struct intel_guc *guc)
> +{
> +       struct drm_i915_private *dev_priv = guc_to_i915(guc);
> +       u32 size, offset;
> +       bool guc_loads_huc;
> +       u32 reg_val;
> +
> +       reg_val = I915_READ(GUC_WOPCM_SIZE);
> +       /* GuC WOPCM size should be always multiple of 4K pages. */
> +       size = reg_val & PAGE_MASK;
> +
> +       reg_val = I915_READ(DMA_GUC_WOPCM_OFFSET);
> +       guc_loads_huc = reg_val & HUC_LOADING_AGENT_GUC;
> +       offset = reg_val & GUC_WOPCM_OFFSET_MASK;
> +
> +       if (guc->wopcm.need_load_huc_fw && !guc_loads_huc)
> +               return false;
> +
> +       return (size == guc->wopcm.size) && (offset == guc->wopcm.offset);
> +}

This seems to have much of what I wrote above already. I'd still split
the actual writes in a helper that will report the per-register a
WARN about "mismatch between locked register value and computed value"
or so. Dumping both the computed an actual register value.

> @@ -147,6 +211,8 @@ int intel_guc_wopcm_init(struct intel_guc_wopcm *guc_wopcm, u32 guc_fw_size,
>         guc->wopcm.offset = offset;
>         guc->wopcm.size = size;
>         guc->wopcm.top = top;
> +       /* Use GuC to load HuC firmware if HuC firmware is present. */

Comment is again more on the "what" side, so can be dropped.

> +       guc->wopcm.need_load_huc_fw = huc_fw_size ? 1 : 0;

	... = huc_fw_size > 0;

Will literally read as "set guc load_huc_fw if huc_fw_size is
greater than zero."

> +int intel_guc_wopcm_init_hw(struct intel_guc_wopcm *guc_wopcm)
> +{
> +       struct intel_guc *guc = guc_wopcm_to_guc(guc_wopcm);
> +       bool locked = guc_wopcm_locked(guc);
> +
> +       GEM_BUG_ON(!guc->wopcm.valid);
> +
> +       /*
> +        * Bug if driver hasn't updated the HW Registers and GuC WOPCM has been
> +        * locked. Return directly if WOPCM was locked and we have updated
> +        * the registers.
> +        */
> +       if (locked) {
> +               if (guc->wopcm.hw_updated)
> +                       return 0;
> +
> +               /*
> +                * Mark as updated if registers contained correct values.
> +                * This will happen while reloading the driver module without
> +                * rebooting the system.
> +                */
> +               if (guc_wopcm_regs_valid(guc))
> +                       goto out;
> +
> +               /* Register locked without valid values. Abort HW init. */
> +               return -EINVAL;
> +       }
> +
> +       /* Always update registers when GuC WOPCM is not locked. */
> +       guc_wopcm_hw_update(guc);

This flow will become more clear with the helpers, and we will get a
splat in the kernel message with less code about which register actually
was locked and how the value mismatched.

I'm up for discussion, but to my eyes the code flow would become more clear if
we start with the assumption "we can write the register values to what we have
calculated", and then make it an error that is propagated back up if we can't.

Regards, Joonas
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

  parent reply	other threads:[~2018-02-09 10:47 UTC|newest]

Thread overview: 23+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2018-02-08 23:03 [PATCH v9 1/7] drm/i915/guc: Move GuC WOPCM related code into separate files Jackie Li
2018-02-08 23:03 ` [PATCH v9 2/7] drm/i915/guc: Rename guc_ggtt_offset to intel_guc_ggtt_offset Jackie Li
2018-02-09  8:01   ` Joonas Lahtinen
2018-02-08 23:03 ` [PATCH v9 3/7] drm/i915/guc: Implement dynamic GuC WOPCM offset and size Jackie Li
2018-02-09  9:31   ` Joonas Lahtinen
2018-02-09 17:24   ` Michal Wajdeczko
2018-02-09 19:32     ` Yaodong Li
2018-02-08 23:03 ` [PATCH v9 4/7] drm/i915/guc: Add support to return CNL specific reserved GuC WOPCM size Jackie Li
2018-02-09  9:37   ` Joonas Lahtinen
2018-02-08 23:03 ` [PATCH v9 5/7] drm/i915/guc: Add HuC firmware size related restriction for Gen9 and CNL A0 Jackie Li
2018-02-09  9:57   ` Joonas Lahtinen
2018-02-08 23:03 ` [PATCH v9 6/7] drm/i915/guc: Check the locking status of GuC WOPCM registers Jackie Li
2018-02-08 23:31   ` Chris Wilson
2018-02-09  5:05     ` Yaodong Li
2018-02-09 10:47   ` Joonas Lahtinen [this message]
2018-02-11  0:36     ` Yaodong Li
2018-02-09 19:42   ` Michal Wajdeczko
2018-02-09 22:12     ` Yaodong Li
2018-02-08 23:03 ` [PATCH v9 7/7] HAX Enable GuC Submission for CI Jackie Li
2018-02-08 23:29 ` ✗ Fi.CI.BAT: failure for series starting with [v9,1/7] drm/i915/guc: Move GuC WOPCM related code into separate files Patchwork
2018-02-09 16:46 ` [PATCH v9 1/7] " Michal Wajdeczko
2018-02-09 19:38   ` Yaodong Li
2018-02-09 20:59     ` Michel Thierry

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=151817323518.4964.3002962792973105876@jlahtine-desk.ger.corp.intel.com \
    --to=joonas.lahtinen@linux.intel.com \
    --cc=intel-gfx@lists.freedesktop.org \
    --cc=yaodong.li@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.