Re: [Intel-gfx] [PATCH v2] kernel-doc: rename the kernel-doc directive 'functions' to 'identifiers'

2019-10-31 Thread Changbin Du
On Tue, Oct 29, 2019 at 02:00:27AM -0600, Jonathan Corbet wrote:
> On Tue, 29 Oct 2019 08:31:22 +0800
> Changbin Du  wrote:
> 
> > Here python is different from C. Both empty string and None are False in 
> > python.
> > Note such condition is common in python.
> 
> Treating both as a False value is reasonably common.  Treating them
> elsewhere in the same code block as separate values is less
> so; that's the part I would prefer to avoid.
>
ok, please check update in v3.

> Thanks,
> 
> jon

-- 
Cheers,
Changbin Du
___
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

Re: [Intel-gfx] [PATCH v2] kernel-doc: rename the kernel-doc directive 'functions' to 'identifiers'

2019-10-29 Thread Changbin Du
On Mon, Oct 28, 2019 at 11:24:22AM +0200, Jani Nikula wrote:
> On Fri, 25 Oct 2019, Changbin Du  wrote:
> > On Fri, Oct 25, 2019 at 09:57:48AM +0300, Jani Nikula wrote:
> >> On Thu, 24 Oct 2019, Jonathan Corbet  wrote:
> >> > On Sun, 20 Oct 2019 21:17:17 +0800
> >> > Changbin Du  wrote:
> >> >
> >> >> The 'functions' directive is not only for functions, but also works for
> >> >> structs/unions. So the name is misleading. This patch renames it to
> >> >> 'identifiers', which specific the functions/types to be included in
> >> >> documentation. We keep the old name as an alias of the new one before
> >> >> all documentation are updated.
> >> >> 
> >> >> Signed-off-by: Changbin Du 
> >> >
> >> > So I think this is basically OK, but I have one more request...
> >> >
> >> > [...]
> >> >
> >> >> diff --git a/Documentation/sphinx/kerneldoc.py 
> >> >> b/Documentation/sphinx/kerneldoc.py
> >> >> index 1159405cb920..0689f9c37f1e 100644
> >> >> --- a/Documentation/sphinx/kerneldoc.py
> >> >> +++ b/Documentation/sphinx/kerneldoc.py
> >> >> @@ -59,9 +59,10 @@ class KernelDocDirective(Directive):
> >> >>  optional_arguments = 4
> >> >>  option_spec = {
> >> >>  'doc': directives.unchanged_required,
> >> >> -'functions': directives.unchanged,
> >> >>  'export': directives.unchanged,
> >> >>  'internal': directives.unchanged,
> >> >> +'identifiers': directives.unchanged,
> >> >> +'functions': directives.unchanged,  # alias of 'identifiers'
> >> >>  }
> >> >>  has_content = False
> >> >>  
> >> >> @@ -71,6 +72,7 @@ class KernelDocDirective(Directive):
> >> >>  
> >> >>  filename = env.config.kerneldoc_srctree + '/' + 
> >> >> self.arguments[0]
> >> >>  export_file_patterns = []
> >> >> +identifiers = None
> >> >>  
> >> >>  # Tell sphinx of the dependency
> >> >>  env.note_dependency(os.path.abspath(filename))
> >> >> @@ -86,19 +88,22 @@ class KernelDocDirective(Directive):
> >> >>  export_file_patterns = 
> >> >> str(self.options.get('internal')).split()
> >> >>  elif 'doc' in self.options:
> >> >>  cmd += ['-function', str(self.options.get('doc'))]
> >> >> +elif 'identifiers' in self.options:
> >> >> +identifiers = self.options.get('identifiers').split()
> >> >>  elif 'functions' in self.options:
> >> >> -functions = self.options.get('functions').split()
> >> >> -if functions:
> >> >> -for f in functions:
> >> >> -cmd += ['-function', f]
> >> >> -else:
> >> >> -cmd += ['-no-doc-sections']
> >> >> +identifiers = self.options.get('functions').split()
> >> >
> >> > Rather than do this, can you just change the elif line to read:
> >> >
> >> > elif ('identifiers' in self.options) or ('functions' in 
> >> > self.options):
> >> >
> >> > ...then leave the rest of the code intact?  It keeps the logic together,
> >> > and avoids the confusing distinction between identifiers=='' and
> >> > identifiers==None .
> >> 
> >> I think the problem is you still need to distinguish between the two for
> >> the get('functions') part.
> >> 
> >> One option is to rename 'functions' to 'identifiers' in the above block,
> >> and put something like this above the whole if ladder (untested):
> >> 
> >> # backward compat
> >> if 'functions' in self.options:
> >> if 'identifiers' in self.options:
> >> kernellog.warn(env.app, "fail")
> > This will miss the content of 'functions' directive if both exist in
> > same doc.
> 
> Did you not notice your patch does the same, except silently, while this
> would produce a warning? Which one is less surprising?
>
yes, my mistake. Mine does the same thing.

> >
> >> else:
> >> self.options.set('identifiers', 
> >> self.options.get('functions'))
> >> 
> >> BR,
> >> Jani.
> >>
> > After comparing, I still perfer my original code which is simpler. :)
> 
> But is it, really? I agree with Jon about the distinction between None
> and '' being confusing.
>
Here python is different from C. Both empty string and None are False in python.
Note such condition is common in python.

Again, I am ok with both.

> 
> BR,
> Jani.
> 
> 
> 
> >
> >> 
> >> -- 
> >> Jani Nikula, Intel Open Source Graphics Center
> 
> -- 
> Jani Nikula, Intel Open Source Graphics Center

-- 
Cheers,
Changbin Du
___
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

Re: [Intel-gfx] [PATCH v2] kernel-doc: rename the kernel-doc directive 'functions' to 'identifiers'

2019-10-25 Thread Changbin Du
On Fri, Oct 25, 2019 at 09:57:48AM +0300, Jani Nikula wrote:
> On Thu, 24 Oct 2019, Jonathan Corbet  wrote:
> > On Sun, 20 Oct 2019 21:17:17 +0800
> > Changbin Du  wrote:
> >
> >> The 'functions' directive is not only for functions, but also works for
> >> structs/unions. So the name is misleading. This patch renames it to
> >> 'identifiers', which specific the functions/types to be included in
> >> documentation. We keep the old name as an alias of the new one before
> >> all documentation are updated.
> >> 
> >> Signed-off-by: Changbin Du 
> >
> > So I think this is basically OK, but I have one more request...
> >
> > [...]
> >
> >> diff --git a/Documentation/sphinx/kerneldoc.py 
> >> b/Documentation/sphinx/kerneldoc.py
> >> index 1159405cb920..0689f9c37f1e 100644
> >> --- a/Documentation/sphinx/kerneldoc.py
> >> +++ b/Documentation/sphinx/kerneldoc.py
> >> @@ -59,9 +59,10 @@ class KernelDocDirective(Directive):
> >>  optional_arguments = 4
> >>  option_spec = {
> >>  'doc': directives.unchanged_required,
> >> -'functions': directives.unchanged,
> >>  'export': directives.unchanged,
> >>  'internal': directives.unchanged,
> >> +'identifiers': directives.unchanged,
> >> +'functions': directives.unchanged,  # alias of 'identifiers'
> >>  }
> >>  has_content = False
> >>  
> >> @@ -71,6 +72,7 @@ class KernelDocDirective(Directive):
> >>  
> >>  filename = env.config.kerneldoc_srctree + '/' + self.arguments[0]
> >>  export_file_patterns = []
> >> +identifiers = None
> >>  
> >>  # Tell sphinx of the dependency
> >>  env.note_dependency(os.path.abspath(filename))
> >> @@ -86,19 +88,22 @@ class KernelDocDirective(Directive):
> >>  export_file_patterns = 
> >> str(self.options.get('internal')).split()
> >>  elif 'doc' in self.options:
> >>  cmd += ['-function', str(self.options.get('doc'))]
> >> +elif 'identifiers' in self.options:
> >> +identifiers = self.options.get('identifiers').split()
> >>  elif 'functions' in self.options:
> >> -functions = self.options.get('functions').split()
> >> -if functions:
> >> -for f in functions:
> >> -cmd += ['-function', f]
> >> -else:
> >> -cmd += ['-no-doc-sections']
> >> +identifiers = self.options.get('functions').split()
> >
> > Rather than do this, can you just change the elif line to read:
> >
> > elif ('identifiers' in self.options) or ('functions' in self.options):
> >
> > ...then leave the rest of the code intact?  It keeps the logic together,
> > and avoids the confusing distinction between identifiers=='' and
> > identifiers==None .
> 
> I think the problem is you still need to distinguish between the two for
> the get('functions') part.
> 
> One option is to rename 'functions' to 'identifiers' in the above block,
> and put something like this above the whole if ladder (untested):
> 
> # backward compat
> if 'functions' in self.options:
> if 'identifiers' in self.options:
> kernellog.warn(env.app, "fail")
This will miss the content of 'functions' directive if both exist in
same doc.

> else:
> self.options.set('identifiers', self.options.get('functions'))
> 
> BR,
> Jani.
>
After comparing, I still perfer my original code which is simpler. :)

> 
> -- 
> Jani Nikula, Intel Open Source Graphics Center

-- 
Cheers,
Changbin Du
___
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

[Intel-gfx] [PATCH v2] kernel-doc: rename the kernel-doc directive 'functions' to 'identifiers'

2019-10-20 Thread Changbin Du
The 'functions' directive is not only for functions, but also works for
structs/unions. So the name is misleading. This patch renames it to
'identifiers', which specific the functions/types to be included in
documentation. We keep the old name as an alias of the new one before
all documentation are updated.

Signed-off-by: Changbin Du 

---
v2:
  o use 'identifiers' as the new directive name.
---
 Documentation/doc-guide/kernel-doc.rst | 29 ++
 Documentation/sphinx/kerneldoc.py  | 19 ++---
 2 files changed, 28 insertions(+), 20 deletions(-)

diff --git a/Documentation/doc-guide/kernel-doc.rst 
b/Documentation/doc-guide/kernel-doc.rst
index 192c36af39e2..fff6604631ea 100644
--- a/Documentation/doc-guide/kernel-doc.rst
+++ b/Documentation/doc-guide/kernel-doc.rst
@@ -476,6 +476,22 @@ internal: *[source-pattern ...]*
 .. kernel-doc:: drivers/gpu/drm/i915/intel_audio.c
:internal:
 
+identifiers: *[ function/type ...]*
+  Include documentation for each *function* and *type* in *source*.
+  If no *function* is specified, the documentation for all functions
+  and types in the *source* will be included.
+
+  Examples::
+
+.. kernel-doc:: lib/bitmap.c
+   :identifiers: bitmap_parselist bitmap_parselist_user
+
+.. kernel-doc:: lib/idr.c
+   :identifiers:
+
+functions: *[ function/type ...]*
+  This is an alias of the 'identifiers' directive and deprecated.
+
 doc: *title*
   Include documentation for the ``DOC:`` paragraph identified by *title* in
   *source*. Spaces are allowed in *title*; do not quote the *title*. The 
*title*
@@ -488,19 +504,6 @@ doc: *title*
 .. kernel-doc:: drivers/gpu/drm/i915/intel_audio.c
:doc: High Definition Audio over HDMI and Display Port
 
-functions: *[ function ...]*
-  Include documentation for each *function* in *source*.
-  If no *function* is specified, the documentation for all functions
-  and types in the *source* will be included.
-
-  Examples::
-
-.. kernel-doc:: lib/bitmap.c
-   :functions: bitmap_parselist bitmap_parselist_user
-
-.. kernel-doc:: lib/idr.c
-   :functions:
-
 Without options, the kernel-doc directive includes all documentation comments
 from the source file.
 
diff --git a/Documentation/sphinx/kerneldoc.py 
b/Documentation/sphinx/kerneldoc.py
index 1159405cb920..0689f9c37f1e 100644
--- a/Documentation/sphinx/kerneldoc.py
+++ b/Documentation/sphinx/kerneldoc.py
@@ -59,9 +59,10 @@ class KernelDocDirective(Directive):
 optional_arguments = 4
 option_spec = {
 'doc': directives.unchanged_required,
-'functions': directives.unchanged,
 'export': directives.unchanged,
 'internal': directives.unchanged,
+'identifiers': directives.unchanged,
+'functions': directives.unchanged,  # alias of 'identifiers'
 }
 has_content = False
 
@@ -71,6 +72,7 @@ class KernelDocDirective(Directive):
 
 filename = env.config.kerneldoc_srctree + '/' + self.arguments[0]
 export_file_patterns = []
+identifiers = None
 
 # Tell sphinx of the dependency
 env.note_dependency(os.path.abspath(filename))
@@ -86,19 +88,22 @@ class KernelDocDirective(Directive):
 export_file_patterns = str(self.options.get('internal')).split()
 elif 'doc' in self.options:
 cmd += ['-function', str(self.options.get('doc'))]
+elif 'identifiers' in self.options:
+identifiers = self.options.get('identifiers').split()
 elif 'functions' in self.options:
-functions = self.options.get('functions').split()
-if functions:
-for f in functions:
-cmd += ['-function', f]
-else:
-cmd += ['-no-doc-sections']
+identifiers = self.options.get('functions').split()
 
 for pattern in export_file_patterns:
 for f in glob.glob(env.config.kerneldoc_srctree + '/' + pattern):
 env.note_dependency(os.path.abspath(f))
 cmd += ['-export-file', f]
 
+if identifiers:
+for i in identifiers:
+cmd += ['-function', i]
+elif identifiers is not None:
+cmd += ['-no-doc-sections']
+
 cmd += [filename]
 
 try:
-- 
2.20.1

___
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

Re: [Intel-gfx] [PATCH] kernel-doc: rename the kernel-doc directive 'functions' to 'specific'

2019-10-16 Thread Changbin Du
On Tue, Oct 15, 2019 at 04:54:39AM -0700, Matthew Wilcox wrote:
> On Tue, Oct 15, 2019 at 11:25:53AM +0200, Thomas Zimmermann wrote:
> > > My preference would be to use 'symbols'.  I tried to come up with 
> > > something
> > > but 'symbols' is better than anything I came up with.
> > 
> > Maybe 'interfaces' or 'artifacts'. The term 'symbols' is just as
> > imprecise as 'functions'.
> 
> I suggested 'identifier' because that's the term used in the C spec (6.2.1):
> 
> : An identifier can denote an object; a function; a tag or a member
> : of a structure, union, or enumeration; a typedef name; a label name;
> : a macro name; or a macro parameter.
>
I also prefer this one now. I was looking for something like this. My original
idea is 'prototype', but that is only for function.

> We don't allow documenting all those things separately, but it does cover
> all the things we do allow to be individually documented.

-- 
Cheers,
Changbin Du
___
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

Re: [Intel-gfx] [PATCH] kernel-doc: rename the kernel-doc directive 'functions' to 'specific'

2019-10-16 Thread Changbin Du
On Tue, Oct 15, 2019 at 12:27:26PM -0600, Jonathan Corbet wrote:
> On Sun, 13 Oct 2019 13:53:59 +0800
> Changbin Du  wrote:
> 
> > The 'functions' directive is not only for functions, but also works for
> > structs/unions. So the name is misleading. This patch renames it to
> > 'specific', so now we have export/internal/specific directives to limit
> > the functions/types to be included in documentation. Meanwhile we improved
> > the warning message.
> 
> I agree with the others that "specific" doesn't really make things
> better.  "Interfaces" maybe; otherwise we could go for something like
> "filter" or "select".
>
Jonathan, How about 'identifier' suggested by Matthew as it is mentioned in Then
C spec?

> Paint mine green :)
> 
> Whatever we end up with, I think it should be added as a synonym for
> "functions".  Then the various selectors that are actually pulling out
> docs for functions could be changed at leisure - or not at all.  I'd
> rather not see a big patch changing everything at once.
>
Sure, I'll make 'functions' deprecated and as an alias to our new directive 
name.

> Thanks,
> 
> jon

-- 
Cheers,
Changbin Du
___
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

[Intel-gfx] [PATCH] kernel-doc: rename the kernel-doc directive 'functions' to 'specific'

2019-10-14 Thread Changbin Du
The 'functions' directive is not only for functions, but also works for
structs/unions. So the name is misleading. This patch renames it to
'specific', so now we have export/internal/specific directives to limit
the functions/types to be included in documentation. Meanwhile we improved
the warning message.

Signed-off-by: Changbin Du 
---
 Documentation/PCI/pci.rst |   4 +-
 Documentation/core-api/boot-time-mm.rst   |   2 +-
 Documentation/core-api/debug-objects.rst  |  14 +-
 Documentation/core-api/genalloc.rst   |  34 +--
 Documentation/core-api/generic-radix-tree.rst |   2 +-
 .../core-api/gfp_mask-from-fs-io.rst  |   4 +-
 Documentation/core-api/idr.rst|   4 +-
 Documentation/core-api/kernel-api.rst |  12 +-
 Documentation/core-api/mm-api.rst |   4 +-
 Documentation/crypto/api-aead.rst |   6 +-
 Documentation/crypto/api-akcipher.rst |   6 +-
 Documentation/crypto/api-digest.rst   |   8 +-
 Documentation/crypto/api-kpp.rst  |  10 +-
 Documentation/crypto/api-rng.rst  |   4 +-
 Documentation/crypto/api-skcipher.rst |  14 +-
 Documentation/dev-tools/kselftest.rst |   4 +-
 Documentation/doc-guide/kernel-doc.rst|  26 +--
 Documentation/driver-api/80211/cfg80211.rst   | 200 +-
 .../driver-api/80211/mac80211-advanced.rst|  88 
 Documentation/driver-api/80211/mac80211.rst   |  80 +++
 .../driver-api/device_connection.rst  |   2 +-
 Documentation/driver-api/device_link.rst  |   4 +-
 .../firmware/fallback-mechanisms.rst  |   2 +-
 .../driver-api/firmware/other_interfaces.rst  |  10 +-
 .../driver-api/firmware/request_firmware.rst  |  12 +-
 Documentation/driver-api/fpga/fpga-bridge.rst |  10 +-
 Documentation/driver-api/fpga/fpga-mgr.rst|  12 +-
 .../driver-api/fpga/fpga-programming.rst  |   8 +-
 Documentation/driver-api/fpga/fpga-region.rst |  20 +-
 Documentation/driver-api/i2c.rst  |   2 +-
 Documentation/driver-api/mei/hdcp.rst |   2 +-
 Documentation/driver-api/spi.rst  |   2 +-
 Documentation/driver-api/usb/typec.rst|  26 +--
 Documentation/driver-api/usb/typec_bus.rst|  10 +-
 Documentation/gpu/amdgpu-dc.rst   |   6 +-
 Documentation/gpu/drm-kms-helpers.rst |   2 +-
 Documentation/gpu/i915.rst|  70 +++---
 Documentation/gpu/vga-switcheroo.rst  |  14 +-
 Documentation/security/tpm/tpm_vtpm_proxy.rst |   2 +-
 Documentation/sphinx/kerneldoc.py |  10 +-
 .../it_IT/doc-guide/kernel-doc.rst|   2 +-
 Documentation/vm/ksm.rst  |   2 +-
 scripts/kernel-doc|   9 +-
 43 files changed, 385 insertions(+), 380 deletions(-)

diff --git a/Documentation/PCI/pci.rst b/Documentation/PCI/pci.rst
index 6864f9a70f5f..6f310807f74c 100644
--- a/Documentation/PCI/pci.rst
+++ b/Documentation/PCI/pci.rst
@@ -79,13 +79,13 @@ initialization with a pointer to a structure describing the 
driver
 (``struct pci_driver``):
 
 .. kernel-doc:: include/linux/pci.h
-   :functions: pci_driver
+   :specific: pci_driver
 
 The ID table is an array of ``struct pci_device_id`` entries ending with an
 all-zero entry.  Definitions with static const are generally preferred.
 
 .. kernel-doc:: include/linux/mod_devicetable.h
-   :functions: pci_device_id
+   :specific: pci_device_id
 
 Most drivers only need ``PCI_DEVICE()`` or ``PCI_DEVICE_CLASS()`` to set up
 a pci_device_id table.
diff --git a/Documentation/core-api/boot-time-mm.rst 
b/Documentation/core-api/boot-time-mm.rst
index e5ec9f1a563d..54824740d010 100644
--- a/Documentation/core-api/boot-time-mm.rst
+++ b/Documentation/core-api/boot-time-mm.rst
@@ -38,4 +38,4 @@ really happens under the hood.
 
 .. kernel-doc:: include/linux/memblock.h
 .. kernel-doc:: mm/memblock.c
-   :functions:
+   :specific:
diff --git a/Documentation/core-api/debug-objects.rst 
b/Documentation/core-api/debug-objects.rst
index ac926fd55a64..352fc2d8abbd 100644
--- a/Documentation/core-api/debug-objects.rst
+++ b/Documentation/core-api/debug-objects.rst
@@ -65,7 +65,7 @@ Debug functions
 ===
 
 .. kernel-doc:: lib/debugobjects.c
-   :functions: debug_object_init
+   :specific: debug_object_init
 
 This function is called whenever the initialization function of a real
 object is called.
@@ -88,7 +88,7 @@ calling code must use debug_object_init_on_stack() and remove 
the
 object before leaving the function which allocated it. See next section.
 
 .. kernel-doc:: lib/debugobjects.c
-   :functions: debug_object_init_on_stack
+   :specific: debug_object_init_on_stack
 
 This function is called whenever the initialization function of a real
 object which resides on the stack is called.
@@ -112,7 +112,7 @@ calling debug_object_free() before the function which 
allocates the
 object returns. Otherwise we keep track of stale objects

[Intel-gfx] [PATCH] drm/i915: Add new vGPU cap info bit VGT_CAPS_HUGE_GTT

2018-05-08 Thread changbin . du
From: Changbin Du <changbin...@intel.com>

This adds a new vGPU cap info bit VGT_CAPS_HUGE_GTT, which is to detect
whether the host supports shadowing of huge gtt pages. If host does
support it, remove the page sizes restriction for vGPU.

Signed-off-by: Changbin Du <changbin...@intel.com>
---
 drivers/gpu/drm/i915/i915_gem.c| 8 ++--
 drivers/gpu/drm/i915/i915_pvinfo.h | 1 +
 drivers/gpu/drm/i915/i915_vgpu.h   | 6 ++
 3 files changed, 9 insertions(+), 6 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c
index 484354f..e0ddfa1 100644
--- a/drivers/gpu/drm/i915/i915_gem.c
+++ b/drivers/gpu/drm/i915/i915_gem.c
@@ -5355,12 +5355,8 @@ int i915_gem_init(struct drm_i915_private *dev_priv)
 {
int ret;
 
-   /*
-* We need to fallback to 4K pages since gvt gtt handling doesn't
-* support huge page entries - we will need to check either hypervisor
-* mm can support huge guest page or just do emulation in gvt.
-*/
-   if (intel_vgpu_active(dev_priv))
+   /* We need to fallback to 4K pages if host doesn't support huge gtt. */
+   if (intel_vgpu_active(dev_priv) && !intel_vgpu_has_huge_gtt(dev_priv))
mkwrite_device_info(dev_priv)->page_sizes =
I915_GTT_PAGE_SIZE_4K;
 
diff --git a/drivers/gpu/drm/i915/i915_pvinfo.h 
b/drivers/gpu/drm/i915/i915_pvinfo.h
index 195203f..55bde4a 100644
--- a/drivers/gpu/drm/i915/i915_pvinfo.h
+++ b/drivers/gpu/drm/i915/i915_pvinfo.h
@@ -54,6 +54,7 @@ enum vgt_g2v_type {
  */
 #define VGT_CAPS_FULL_48BIT_PPGTT  BIT(2)
 #define VGT_CAPS_HWSP_EMULATIONBIT(3)
+#define VGT_CAPS_HUGE_GTT  BIT(4)
 
 struct vgt_if {
u64 magic;  /* VGT_MAGIC */
diff --git a/drivers/gpu/drm/i915/i915_vgpu.h b/drivers/gpu/drm/i915/i915_vgpu.h
index bb83384..551acc3 100644
--- a/drivers/gpu/drm/i915/i915_vgpu.h
+++ b/drivers/gpu/drm/i915/i915_vgpu.h
@@ -36,6 +36,12 @@ intel_vgpu_has_hwsp_emulation(struct drm_i915_private 
*dev_priv)
return dev_priv->vgpu.caps & VGT_CAPS_HWSP_EMULATION;
 }
 
+static inline bool
+intel_vgpu_has_huge_gtt(struct drm_i915_private *dev_priv)
+{
+   return dev_priv->vgpu.caps & VGT_CAPS_HUGE_GTT;
+}
+
 int intel_vgt_balloon(struct drm_i915_private *dev_priv);
 void intel_vgt_deballoon(struct drm_i915_private *dev_priv);
 
-- 
2.7.4

___
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx


[Intel-gfx] [PATCH v6 13/14] drm/i915/gvt: Fix error handling in ppgtt_populate_spt_by_guest_entry

2018-05-08 Thread changbin . du
From: Changbin Du <changbin...@intel.com>

Don't forget to free allocated spt if shadowing failed.

Signed-off-by: Changbin Du <changbin...@intel.com>
---
 drivers/gpu/drm/i915/gvt/gtt.c | 33 +
 1 file changed, 21 insertions(+), 12 deletions(-)

diff --git a/drivers/gpu/drm/i915/gvt/gtt.c b/drivers/gpu/drm/i915/gvt/gtt.c
index 2bf85be..f83ac08 100644
--- a/drivers/gpu/drm/i915/gvt/gtt.c
+++ b/drivers/gpu/drm/i915/gvt/gtt.c
@@ -907,15 +907,22 @@ static struct intel_vgpu_ppgtt_spt *ppgtt_alloc_spt_gfn(
 i += (spt->shadow_page.pde_ips ? GTT_64K_PTE_STRIDE : 1)) \
if (!ppgtt_get_shadow_entry(spt, e, i))
 
-static void ppgtt_get_spt(struct intel_vgpu_ppgtt_spt *spt)
+static inline void ppgtt_get_spt(struct intel_vgpu_ppgtt_spt *spt)
 {
int v = atomic_read(>refcount);
 
trace_spt_refcount(spt->vgpu->id, "inc", spt, v, (v + 1));
-
atomic_inc(>refcount);
 }
 
+static inline int ppgtt_put_spt(struct intel_vgpu_ppgtt_spt *spt)
+{
+   int v = atomic_read(>refcount);
+
+   trace_spt_refcount(spt->vgpu->id, "dec", spt, v, (v - 1));
+   return atomic_dec_return(>refcount);
+}
+
 static int ppgtt_invalidate_spt(struct intel_vgpu_ppgtt_spt *spt);
 
 static int ppgtt_invalidate_spt_by_shadow_entry(struct intel_vgpu *vgpu,
@@ -967,14 +974,11 @@ static int ppgtt_invalidate_spt(struct 
intel_vgpu_ppgtt_spt *spt)
struct intel_gvt_gtt_entry e;
unsigned long index;
int ret;
-   int v = atomic_read(>refcount);
 
trace_spt_change(spt->vgpu->id, "die", spt,
spt->guest_page.gfn, spt->shadow_page.type);
 
-   trace_spt_refcount(spt->vgpu->id, "dec", spt, v, (v - 1));
-
-   if (atomic_dec_return(>refcount) > 0)
+   if (ppgtt_put_spt(spt) > 0)
return 0;
 
for_each_present_shadow_entry(spt, , index) {
@@ -1056,8 +1060,10 @@ static struct intel_vgpu_ppgtt_spt 
*ppgtt_populate_spt_by_guest_entry(
gvt_dbg_mm("reshadow PDE since ips changed\n");
clear_page(spt->shadow_page.vaddr);
ret = ppgtt_populate_spt(spt);
-   if (ret)
-   goto fail;
+   if (ret) {
+   ppgtt_put_spt(spt);
+   goto err;
+   }
}
} else {
int type = get_next_pt_type(we->type);
@@ -1065,22 +1071,25 @@ static struct intel_vgpu_ppgtt_spt 
*ppgtt_populate_spt_by_guest_entry(
spt = ppgtt_alloc_spt_gfn(vgpu, type, ops->get_pfn(we), ips);
if (IS_ERR(spt)) {
ret = PTR_ERR(spt);
-   goto fail;
+   goto err;
}
 
ret = intel_vgpu_enable_page_track(vgpu, spt->guest_page.gfn);
if (ret)
-   goto fail;
+   goto err_free_spt;
 
ret = ppgtt_populate_spt(spt);
if (ret)
-   goto fail;
+   goto err_free_spt;
 
trace_spt_change(vgpu->id, "new", spt, spt->guest_page.gfn,
 spt->shadow_page.type);
}
return spt;
-fail:
+
+err_free_spt:
+   ppgtt_free_spt(spt);
+err:
gvt_vgpu_err("fail: shadow page %p guest entry 0x%llx type %d\n",
 spt, we->val64, we->type);
return ERR_PTR(ret);
-- 
2.7.4

___
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx


[Intel-gfx] [PATCH v6 11/14] drm/i915/gvt: Add 2M huge gtt support

2018-05-08 Thread changbin . du
From: Changbin Du <changbin...@intel.com>

This add 2M huge gtt support for GVTg. Unlike 64K gtt entry, we can
shadow 2M guest entry with real huge gtt. But before that, we have to
check memory physical continuous, alignment and if it is supported on
the host. We can get all supported page sizes from
intel_device_info.page_sizes.

Finally we must split the 2M page into smaller pages if we cannot
satisfy guest Huge Page.

Signed-off-by: Changbin Du <changbin...@intel.com>
---
 drivers/gpu/drm/i915/gvt/gtt.c | 100 ++---
 1 file changed, 95 insertions(+), 5 deletions(-)

diff --git a/drivers/gpu/drm/i915/gvt/gtt.c b/drivers/gpu/drm/i915/gvt/gtt.c
index ffeecda..bf718a3 100644
--- a/drivers/gpu/drm/i915/gvt/gtt.c
+++ b/drivers/gpu/drm/i915/gvt/gtt.c
@@ -902,6 +902,11 @@ static struct intel_vgpu_ppgtt_spt *ppgtt_alloc_spt_gfn(
if (!ppgtt_get_shadow_entry(spt, e, i) && \
spt->vgpu->gvt->gtt.pte_ops->test_present(e))
 
+#define for_each_shadow_entry(spt, e, i) \
+   for (i = 0; i < pt_entries(spt); \
+i += (spt->shadow_page.pde_ips ? GTT_64K_PTE_STRIDE : 1)) \
+   if (!ppgtt_get_shadow_entry(spt, e, i))
+
 static void ppgtt_get_spt(struct intel_vgpu_ppgtt_spt *spt)
 {
int v = atomic_read(>refcount);
@@ -949,7 +954,8 @@ static inline void ppgtt_invalidate_pte(struct 
intel_vgpu_ppgtt_spt *spt,
pfn = ops->get_pfn(entry);
type = spt->shadow_page.type;
 
-   if (pfn == vgpu->gtt.scratch_pt[type].page_mfn)
+   /* Uninitialized spte or unshadowed spte. */
+   if (!pfn || pfn == vgpu->gtt.scratch_pt[type].page_mfn)
return;
 
intel_gvt_hypervisor_dma_unmap_guest_page(vgpu, pfn << PAGE_SHIFT);
@@ -982,8 +988,10 @@ static int ppgtt_invalidate_spt(struct 
intel_vgpu_ppgtt_spt *spt)
WARN(1, "suspicious 64K gtt entry\n");
continue;
case GTT_TYPE_PPGTT_PTE_2M_ENTRY:
+   gvt_vdbg_mm("invalidate 2M entry\n");
+   continue;
case GTT_TYPE_PPGTT_PTE_1G_ENTRY:
-   WARN(1, "GVT doesn't support 2M/1GB page\n");
+   WARN(1, "GVT doesn't support 1GB page\n");
continue;
case GTT_TYPE_PPGTT_PML4_ENTRY:
case GTT_TYPE_PPGTT_PDP_ENTRY:
@@ -1083,6 +1091,73 @@ static inline void ppgtt_generate_shadow_entry(struct 
intel_gvt_gtt_entry *se,
ops->set_pfn(se, s->shadow_page.mfn);
 }
 
+/**
+ * Return 1 if 2MB huge gtt shadowing is possilbe, 0 if miscondition,
+ * negtive if found err.
+ */
+static int is_2MB_gtt_possible(struct intel_vgpu *vgpu,
+   struct intel_gvt_gtt_entry *entry)
+{
+   struct intel_gvt_gtt_pte_ops *ops = vgpu->gvt->gtt.pte_ops;
+   unsigned long pfn;
+
+   if (!HAS_PAGE_SIZES(vgpu->gvt->dev_priv, I915_GTT_PAGE_SIZE_2M))
+   return 0;
+
+   pfn = intel_gvt_hypervisor_gfn_to_mfn(vgpu, ops->get_pfn(entry));
+   if (pfn == INTEL_GVT_INVALID_ADDR)
+   return -EINVAL;
+
+   return PageTransHuge(pfn_to_page(pfn));
+}
+
+static int split_2MB_gtt_entry(struct intel_vgpu *vgpu,
+   struct intel_vgpu_ppgtt_spt *spt, unsigned long index,
+   struct intel_gvt_gtt_entry *se)
+{
+   struct intel_gvt_gtt_pte_ops *ops = vgpu->gvt->gtt.pte_ops;
+   struct intel_vgpu_ppgtt_spt *sub_spt;
+   struct intel_gvt_gtt_entry sub_se;
+   unsigned long start_gfn;
+   dma_addr_t dma_addr;
+   unsigned long sub_index;
+   int ret;
+
+   gvt_dbg_mm("Split 2M gtt entry, index %lu\n", index);
+
+   start_gfn = ops->get_pfn(se);
+
+   sub_spt = ppgtt_alloc_spt(vgpu, GTT_TYPE_PPGTT_PTE_PT);
+   if (IS_ERR(sub_spt))
+   return PTR_ERR(sub_spt);
+
+   for_each_shadow_entry(sub_spt, _se, sub_index) {
+   ret = intel_gvt_hypervisor_dma_map_guest_page(vgpu,
+   start_gfn + sub_index, PAGE_SIZE, _addr);
+   if (ret) {
+   ppgtt_invalidate_spt(spt);
+   return ret;
+   }
+   sub_se.val64 = se->val64;
+
+   /* Copy the PAT field from PDE. */
+   sub_se.val64 &= ~_PAGE_PAT;
+   sub_se.val64 |= (se->val64 & _PAGE_PAT_LARGE) >> 5;
+
+   ops->set_pfn(_se, dma_addr >> PAGE_SHIFT);
+   ppgtt_set_shadow_entry(sub_spt, _se, sub_index);
+   }
+
+   /* Clear dirty field. */
+   se->val64 &= ~_PAGE_DIRTY;
+
+   ops->clear_pse(se);
+   ops->clear_ips(se);
+   ops->set_pfn(se, sub_spt->shadow_page.mfn);
+   ppgtt_set_shadow_entry(spt, se, index);
+   return 0;
+}
+
 static int split_64KB_gtt_entry(s

[Intel-gfx] [PATCH v6 07/14] drm/i915/gvt: Split ppgtt_alloc_spt into two parts

2018-05-08 Thread changbin . du
From: Changbin Du <changbin...@intel.com>

We need a interface to allocate a pure shadow page which doesn't have
a guest page associated with. Such shadow page is used to shadow 2M
huge gtt entry.

Signed-off-by: Changbin Du <changbin...@intel.com>
---
 drivers/gpu/drm/i915/gvt/gtt.c | 62 +++---
 1 file changed, 40 insertions(+), 22 deletions(-)

diff --git a/drivers/gpu/drm/i915/gvt/gtt.c b/drivers/gpu/drm/i915/gvt/gtt.c
index 0966ee7..22e77d4 100644
--- a/drivers/gpu/drm/i915/gvt/gtt.c
+++ b/drivers/gpu/drm/i915/gvt/gtt.c
@@ -735,10 +735,12 @@ static void ppgtt_free_spt(struct intel_vgpu_ppgtt_spt 
*spt)
 
radix_tree_delete(>vgpu->gtt.spt_tree, spt->shadow_page.mfn);
 
-   if (spt->guest_page.oos_page)
-   detach_oos_page(spt->vgpu, spt->guest_page.oos_page);
+   if (spt->guest_page.gfn) {
+   if (spt->guest_page.oos_page)
+   detach_oos_page(spt->vgpu, spt->guest_page.oos_page);
 
-   intel_vgpu_unregister_page_track(spt->vgpu, spt->guest_page.gfn);
+   intel_vgpu_unregister_page_track(spt->vgpu, 
spt->guest_page.gfn);
+   }
 
list_del_init(>post_shadow_list);
free_spt(spt);
@@ -799,9 +801,9 @@ static inline struct intel_vgpu_ppgtt_spt 
*intel_vgpu_find_spt_by_mfn(
 
 static int reclaim_one_ppgtt_mm(struct intel_gvt *gvt);
 
+/* Allocate shadow page table without guest page. */
 static struct intel_vgpu_ppgtt_spt *ppgtt_alloc_spt(
-   struct intel_vgpu *vgpu, int type, unsigned long gfn,
-   bool guest_pde_ips)
+   struct intel_vgpu *vgpu, intel_gvt_gtt_type_t type)
 {
struct device *kdev = >gvt->dev_priv->drm.pdev->dev;
struct intel_vgpu_ppgtt_spt *spt = NULL;
@@ -836,27 +838,12 @@ static struct intel_vgpu_ppgtt_spt *ppgtt_alloc_spt(
spt->shadow_page.vaddr = page_address(spt->shadow_page.page);
spt->shadow_page.mfn = daddr >> I915_GTT_PAGE_SHIFT;
 
-   /*
-* Init guest_page.
-*/
-   spt->guest_page.type = type;
-   spt->guest_page.gfn = gfn;
-   spt->guest_page.pde_ips = guest_pde_ips;
-
-   ret = intel_vgpu_register_page_track(vgpu, spt->guest_page.gfn,
-   ppgtt_write_protection_handler, spt);
-   if (ret)
-   goto err_unmap_dma;
-
ret = radix_tree_insert(>gtt.spt_tree, spt->shadow_page.mfn, spt);
if (ret)
-   goto err_unreg_page_track;
+   goto err_unmap_dma;
 
-   trace_spt_alloc(vgpu->id, spt, type, spt->shadow_page.mfn, gfn);
return spt;
 
-err_unreg_page_track:
-   intel_vgpu_unregister_page_track(vgpu, spt->guest_page.gfn);
 err_unmap_dma:
dma_unmap_page(kdev, daddr, PAGE_SIZE, PCI_DMA_BIDIRECTIONAL);
 err_free_spt:
@@ -864,6 +851,37 @@ static struct intel_vgpu_ppgtt_spt *ppgtt_alloc_spt(
return ERR_PTR(ret);
 }
 
+/* Allocate shadow page table associated with specific gfn. */
+static struct intel_vgpu_ppgtt_spt *ppgtt_alloc_spt_gfn(
+   struct intel_vgpu *vgpu, intel_gvt_gtt_type_t type,
+   unsigned long gfn, bool guest_pde_ips)
+{
+   struct intel_vgpu_ppgtt_spt *spt;
+   int ret;
+
+   spt = ppgtt_alloc_spt(vgpu, type);
+   if (IS_ERR(spt))
+   return spt;
+
+   /*
+* Init guest_page.
+*/
+   ret = intel_vgpu_register_page_track(vgpu, gfn,
+   ppgtt_write_protection_handler, spt);
+   if (ret) {
+   ppgtt_free_spt(spt);
+   return ERR_PTR(ret);
+   }
+
+   spt->guest_page.type = type;
+   spt->guest_page.gfn = gfn;
+   spt->guest_page.pde_ips = guest_pde_ips;
+
+   trace_spt_alloc(vgpu->id, spt, type, spt->shadow_page.mfn, gfn);
+
+   return spt;
+}
+
 #define pt_entry_size_shift(spt) \
((spt)->vgpu->gvt->device_info.gtt_entry_size_shift)
 
@@ -1019,7 +1037,7 @@ static struct intel_vgpu_ppgtt_spt 
*ppgtt_populate_spt_by_guest_entry(
if (we->type == GTT_TYPE_PPGTT_PDE_ENTRY)
ips = vgpu_ips_enabled(vgpu) && ops->test_ips(we);
 
-   spt = ppgtt_alloc_spt(vgpu, type, ops->get_pfn(we), ips);
+   spt = ppgtt_alloc_spt_gfn(vgpu, type, ops->get_pfn(we), ips);
if (IS_ERR(spt)) {
ret = PTR_ERR(spt);
goto fail;
-- 
2.7.4

___
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx


[Intel-gfx] [PATCH v6 12/14] drm/i915/gvt: Handle special sequence on PDE IPS bit

2018-05-08 Thread changbin . du
From: Changbin Du <changbin...@intel.com>

If the guest update the 64K gtt entry before changing IPS bit of PDE, we
need to re-shadow the whole page table. Because we have ignored all
updates to unused entries.

Signed-off-by: Changbin Du <changbin...@intel.com>
---
 drivers/gpu/drm/i915/gvt/gtt.c | 20 +++-
 1 file changed, 15 insertions(+), 5 deletions(-)

diff --git a/drivers/gpu/drm/i915/gvt/gtt.c b/drivers/gpu/drm/i915/gvt/gtt.c
index bf718a3..2bf85be 100644
--- a/drivers/gpu/drm/i915/gvt/gtt.c
+++ b/drivers/gpu/drm/i915/gvt/gtt.c
@@ -1043,14 +1043,24 @@ static struct intel_vgpu_ppgtt_spt 
*ppgtt_populate_spt_by_guest_entry(
 
GEM_BUG_ON(!gtt_type_is_pt(get_next_pt_type(we->type)));
 
+   if (we->type == GTT_TYPE_PPGTT_PDE_ENTRY)
+   ips = vgpu_ips_enabled(vgpu) && ops->test_ips(we);
+
spt = intel_vgpu_find_spt_by_gfn(vgpu, ops->get_pfn(we));
-   if (spt)
+   if (spt) {
ppgtt_get_spt(spt);
-   else {
-   int type = get_next_pt_type(we->type);
 
-   if (we->type == GTT_TYPE_PPGTT_PDE_ENTRY)
-   ips = vgpu_ips_enabled(vgpu) && ops->test_ips(we);
+   if (ips != spt->guest_page.pde_ips) {
+   spt->guest_page.pde_ips = ips;
+
+   gvt_dbg_mm("reshadow PDE since ips changed\n");
+   clear_page(spt->shadow_page.vaddr);
+   ret = ppgtt_populate_spt(spt);
+   if (ret)
+   goto fail;
+   }
+   } else {
+   int type = get_next_pt_type(we->type);
 
spt = ppgtt_alloc_spt_gfn(vgpu, type, ops->get_pfn(we), ips);
if (IS_ERR(spt)) {
-- 
2.7.4

___
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx


[Intel-gfx] [PATCH v6 06/14] drm/i915/gvt: Add GTT clear_pse operation

2018-05-08 Thread changbin . du
From: Changbin Du <changbin...@intel.com>

Add clear_pse operation in case we need to split huge gtt into small pages.

v2: correct description.

Signed-off-by: Changbin Du <changbin...@intel.com>
---
 drivers/gpu/drm/i915/gvt/gtt.c | 19 +++
 drivers/gpu/drm/i915/gvt/gtt.h |  1 +
 2 files changed, 20 insertions(+)

diff --git a/drivers/gpu/drm/i915/gvt/gtt.c b/drivers/gpu/drm/i915/gvt/gtt.c
index f7bc8ff..0966ee7 100644
--- a/drivers/gpu/drm/i915/gvt/gtt.c
+++ b/drivers/gpu/drm/i915/gvt/gtt.c
@@ -390,6 +390,24 @@ static bool gen8_gtt_test_pse(struct intel_gvt_gtt_entry 
*e)
return !!(e->val64 & _PAGE_PSE);
 }
 
+static void gen8_gtt_clear_pse(struct intel_gvt_gtt_entry *e)
+{
+   if (gen8_gtt_test_pse(e)) {
+   switch (e->type) {
+   case GTT_TYPE_PPGTT_PTE_2M_ENTRY:
+   e->val64 &= ~_PAGE_PSE;
+   e->type = GTT_TYPE_PPGTT_PDE_ENTRY;
+   break;
+   case GTT_TYPE_PPGTT_PTE_1G_ENTRY:
+   e->type = GTT_TYPE_PPGTT_PDP_ENTRY;
+   e->val64 &= ~_PAGE_PSE;
+   break;
+   default:
+   WARN_ON(1);
+   }
+   }
+}
+
 static bool gen8_gtt_test_ips(struct intel_gvt_gtt_entry *e)
 {
if (GEM_WARN_ON(e->type != GTT_TYPE_PPGTT_PDE_ENTRY))
@@ -477,6 +495,7 @@ static struct intel_gvt_gtt_pte_ops gen8_gtt_pte_ops = {
.set_present = gtt_entry_set_present,
.test_present = gen8_gtt_test_present,
.test_pse = gen8_gtt_test_pse,
+   .clear_pse = gen8_gtt_clear_pse,
.clear_ips = gen8_gtt_clear_ips,
.test_ips = gen8_gtt_test_ips,
.clear_64k_splited = gen8_gtt_clear_64k_splited,
diff --git a/drivers/gpu/drm/i915/gvt/gtt.h b/drivers/gpu/drm/i915/gvt/gtt.h
index 162ef19..b7bf68c 100644
--- a/drivers/gpu/drm/i915/gvt/gtt.h
+++ b/drivers/gpu/drm/i915/gvt/gtt.h
@@ -63,6 +63,7 @@ struct intel_gvt_gtt_pte_ops {
void (*clear_present)(struct intel_gvt_gtt_entry *e);
void (*set_present)(struct intel_gvt_gtt_entry *e);
bool (*test_pse)(struct intel_gvt_gtt_entry *e);
+   void (*clear_pse)(struct intel_gvt_gtt_entry *e);
bool (*test_ips)(struct intel_gvt_gtt_entry *e);
void (*clear_ips)(struct intel_gvt_gtt_entry *e);
bool (*test_64k_splited)(struct intel_gvt_gtt_entry *e);
-- 
2.7.4

___
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx


[Intel-gfx] [PATCH v6 05/14] drm/i915/gvt: Add software PTE flag to mark special 64K splited entry

2018-05-08 Thread changbin . du
From: Changbin Du <changbin...@intel.com>

This add a software PTE flag on the Ignored bit of PTE. It will be used
to identify splited 64K shadow entries.

v2: fix mask definition.

Signed-off-by: Changbin Du <changbin...@intel.com>
---
 drivers/gpu/drm/i915/gvt/gtt.c | 21 +
 drivers/gpu/drm/i915/gvt/gtt.h |  3 +++
 2 files changed, 24 insertions(+)

diff --git a/drivers/gpu/drm/i915/gvt/gtt.c b/drivers/gpu/drm/i915/gvt/gtt.c
index 7a80518..f7bc8ff 100644
--- a/drivers/gpu/drm/i915/gvt/gtt.c
+++ b/drivers/gpu/drm/i915/gvt/gtt.c
@@ -348,6 +348,9 @@ static inline int gtt_set_entry64(void *pt,
 #define ADDR_64K_MASK  GENMASK_ULL(GTT_HAW - 1, 16)
 #define ADDR_4K_MASK   GENMASK_ULL(GTT_HAW - 1, 12)
 
+#define GTT_SPTE_FLAG_MASK GENMASK_ULL(62, 52)
+#define GTT_SPTE_FLAG_64K_SPLITED BIT(52) /* splited 64K gtt entry */
+
 static unsigned long gen8_gtt_get_pfn(struct intel_gvt_gtt_entry *e)
 {
unsigned long pfn;
@@ -427,6 +430,21 @@ static void gtt_entry_set_present(struct 
intel_gvt_gtt_entry *e)
e->val64 |= _PAGE_PRESENT;
 }
 
+static bool gen8_gtt_test_64k_splited(struct intel_gvt_gtt_entry *e)
+{
+   return !!(e->val64 & GTT_SPTE_FLAG_64K_SPLITED);
+}
+
+static void gen8_gtt_set_64k_splited(struct intel_gvt_gtt_entry *e)
+{
+   e->val64 |= GTT_SPTE_FLAG_64K_SPLITED;
+}
+
+static void gen8_gtt_clear_64k_splited(struct intel_gvt_gtt_entry *e)
+{
+   e->val64 &= ~GTT_SPTE_FLAG_64K_SPLITED;
+}
+
 /*
  * Per-platform GMA routines.
  */
@@ -461,6 +479,9 @@ static struct intel_gvt_gtt_pte_ops gen8_gtt_pte_ops = {
.test_pse = gen8_gtt_test_pse,
.clear_ips = gen8_gtt_clear_ips,
.test_ips = gen8_gtt_test_ips,
+   .clear_64k_splited = gen8_gtt_clear_64k_splited,
+   .set_64k_splited = gen8_gtt_set_64k_splited,
+   .test_64k_splited = gen8_gtt_test_64k_splited,
.get_pfn = gen8_gtt_get_pfn,
.set_pfn = gen8_gtt_set_pfn,
 };
diff --git a/drivers/gpu/drm/i915/gvt/gtt.h b/drivers/gpu/drm/i915/gvt/gtt.h
index c11284b..162ef19 100644
--- a/drivers/gpu/drm/i915/gvt/gtt.h
+++ b/drivers/gpu/drm/i915/gvt/gtt.h
@@ -65,6 +65,9 @@ struct intel_gvt_gtt_pte_ops {
bool (*test_pse)(struct intel_gvt_gtt_entry *e);
bool (*test_ips)(struct intel_gvt_gtt_entry *e);
void (*clear_ips)(struct intel_gvt_gtt_entry *e);
+   bool (*test_64k_splited)(struct intel_gvt_gtt_entry *e);
+   void (*clear_64k_splited)(struct intel_gvt_gtt_entry *e);
+   void (*set_64k_splited)(struct intel_gvt_gtt_entry *e);
void (*set_pfn)(struct intel_gvt_gtt_entry *e, unsigned long pfn);
unsigned long (*get_pfn)(struct intel_gvt_gtt_entry *e);
 };
-- 
2.7.4

___
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx


[Intel-gfx] [PATCH v6 03/14] drm/i915/gvt: Handle MMIO GEN8_GAMW_ECO_DEV_RW_IA for 64K GTT

2018-05-08 Thread changbin . du
From: Changbin Du <changbin...@intel.com>

The register RENDER_HWS_PGA_GEN7 is renamed to GEN8_GAMW_ECO_DEV_RW_IA
from GEN8 which can control IPS enabling.

v2: IPS of all engines must be enabled together for gen9.

Signed-off-by: Changbin Du <changbin...@intel.com>
---
 drivers/gpu/drm/i915/gvt/handlers.c | 29 -
 1 file changed, 28 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/i915/gvt/handlers.c 
b/drivers/gpu/drm/i915/gvt/handlers.c
index b77adcc..a3e439b 100644
--- a/drivers/gpu/drm/i915/gvt/handlers.c
+++ b/drivers/gpu/drm/i915/gvt/handlers.c
@@ -211,6 +211,31 @@ static int sanitize_fence_mmio_access(struct intel_vgpu 
*vgpu,
return 0;
 }
 
+static int gamw_echo_dev_rw_ia_write(struct intel_vgpu *vgpu,
+   unsigned int offset, void *p_data, unsigned int bytes)
+{
+   u32 ips = (*(u32 *)p_data) & GAMW_ECO_ENABLE_64K_IPS_FIELD;
+
+   if (INTEL_GEN(vgpu->gvt->dev_priv) == 9) {
+   if (ips == GAMW_ECO_ENABLE_64K_IPS_FIELD)
+   gvt_dbg_core("vgpu%d: ips enabled\n", vgpu->id);
+   else if (!ips)
+   gvt_dbg_core("vgpu%d: ips disabled\n", vgpu->id);
+   else {
+   /* All engines must be enabled together for vGPU,
+* since we don't know which engine the ppgtt will
+* bind to when shadowing.
+*/
+   gvt_vgpu_err("Unsupported IPS setting %x, cannot enable 
64K gtt.\n",
+ips);
+   return -EINVAL;
+   }
+   }
+
+   write_vreg(vgpu, offset, p_data, bytes);
+   return 0;
+}
+
 static int fence_mmio_read(struct intel_vgpu *vgpu, unsigned int off,
void *p_data, unsigned int bytes)
 {
@@ -1654,7 +1679,9 @@ static int init_generic_mmio_info(struct intel_gvt *gvt)
 
MMIO_RING_DFH(RING_HWSTAM, D_ALL, F_CMD_ACCESS, NULL, NULL);
 
-   MMIO_GM_RDR(RENDER_HWS_PGA_GEN7, D_ALL, NULL, NULL);
+   MMIO_DH(GEN8_GAMW_ECO_DEV_RW_IA, D_BDW_PLUS, NULL,
+   gamw_echo_dev_rw_ia_write);
+
MMIO_GM_RDR(BSD_HWS_PGA_GEN7, D_ALL, NULL, NULL);
MMIO_GM_RDR(BLT_HWS_PGA_GEN7, D_ALL, NULL, NULL);
MMIO_GM_RDR(VEBOX_HWS_PGA_GEN7, D_ALL, NULL, NULL);
-- 
2.7.4

___
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx


[Intel-gfx] [PATCH v6 00/14] drm/i915/gvt: Add huge gtt shadowing

2018-05-08 Thread changbin . du
From: Changbin Du <changbin...@intel.com>

Add huge gtt shadowing for GVT. This will alow huge gtt feature turned on for 
vGPU.

v6:
  o Split changes of last patch in i915 side into a separated patch.
v5:
  o IPS of all engines must be enabled together for gen9.
  o Coding style improvment.
v4:
  o Make first patch bisectable.
v3:
  o rebase.
v2:
  o fix comments from zhenyu.
  o rebase.

Changbin Du (14):
  drm/i915/gvt: Add new 64K entry type
  drm/i915/gvt: Add PTE IPS bit operations
  drm/i915/gvt: Handle MMIO GEN8_GAMW_ECO_DEV_RW_IA for 64K GTT
  drm/i915/gvt: Detect 64K gtt entry by IPS bit of PDE
  drm/i915/gvt: Add software PTE flag to mark special 64K splited entry
  drm/i915/gvt: Add GTT clear_pse operation
  drm/i915/gvt: Split ppgtt_alloc_spt into two parts
  drm/i915/gvt: Make PTE iterator 64K entry aware
  drm/i915/gvt: Add 64K huge gtt support
  drm/i915/kvmgt: Support setting dma map for huge pages
  drm/i915/gvt: Add 2M huge gtt support
  drm/i915/gvt: Handle special sequence on PDE IPS bit
  drm/i915/gvt: Fix error handling in ppgtt_populate_spt_by_guest_entry
  drm/i915: Enable platform support for vGPU huge gtt pages

 drivers/gpu/drm/i915/gvt/gtt.c   | 421 ++-
 drivers/gpu/drm/i915/gvt/gtt.h   |   9 +
 drivers/gpu/drm/i915/gvt/handlers.c  |  29 ++-
 drivers/gpu/drm/i915/gvt/hypercall.h |   2 +-
 drivers/gpu/drm/i915/gvt/kvmgt.c | 130 ---
 drivers/gpu/drm/i915/gvt/mpt.h   |   7 +-
 drivers/gpu/drm/i915/gvt/vgpu.c  |   1 +
 7 files changed, 500 insertions(+), 99 deletions(-)

-- 
2.7.4

___
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx


[Intel-gfx] [PATCH v6 01/14] drm/i915/gvt: Add new 64K entry type

2018-05-08 Thread changbin . du
From: Changbin Du <changbin...@intel.com>

Add a new entry type GTT_TYPE_PPGTT_PTE_64K_ENTRY. 64K entry is very
different from 2M/1G entry. 64K entry is controlled by IPS bit in upper
PDE. To leverage the current logic, I take IPS bit as 'PSE' for PTE
level. Which means, 64K entries can also processed by get_pse_type().

v2: Make it bisectable.

Signed-off-by: Changbin Du <changbin...@intel.com>
---
 drivers/gpu/drm/i915/gvt/gtt.c | 26 ++
 drivers/gpu/drm/i915/gvt/gtt.h |  1 +
 2 files changed, 23 insertions(+), 4 deletions(-)

diff --git a/drivers/gpu/drm/i915/gvt/gtt.c b/drivers/gpu/drm/i915/gvt/gtt.c
index 78e55aa..1fcc64a 100644
--- a/drivers/gpu/drm/i915/gvt/gtt.c
+++ b/drivers/gpu/drm/i915/gvt/gtt.c
@@ -216,16 +216,22 @@ static struct gtt_type_table_entry gtt_type_table[] = {
GTT_TYPE_PPGTT_PDE_PT,
GTT_TYPE_PPGTT_PTE_PT,
GTT_TYPE_PPGTT_PTE_2M_ENTRY),
+   /* We take IPS bit as 'PSE' for PTE level. */
GTT_TYPE_TABLE_ENTRY(GTT_TYPE_PPGTT_PTE_PT,
GTT_TYPE_PPGTT_PTE_4K_ENTRY,
GTT_TYPE_PPGTT_PTE_PT,
GTT_TYPE_INVALID,
-   GTT_TYPE_INVALID),
+   GTT_TYPE_PPGTT_PTE_64K_ENTRY),
GTT_TYPE_TABLE_ENTRY(GTT_TYPE_PPGTT_PTE_4K_ENTRY,
GTT_TYPE_PPGTT_PTE_4K_ENTRY,
GTT_TYPE_PPGTT_PTE_PT,
GTT_TYPE_INVALID,
-   GTT_TYPE_INVALID),
+   GTT_TYPE_PPGTT_PTE_64K_ENTRY),
+   GTT_TYPE_TABLE_ENTRY(GTT_TYPE_PPGTT_PTE_64K_ENTRY,
+   GTT_TYPE_PPGTT_PTE_4K_ENTRY,
+   GTT_TYPE_PPGTT_PTE_PT,
+   GTT_TYPE_INVALID,
+   GTT_TYPE_PPGTT_PTE_64K_ENTRY),
GTT_TYPE_TABLE_ENTRY(GTT_TYPE_PPGTT_PTE_2M_ENTRY,
GTT_TYPE_PPGTT_PDE_ENTRY,
GTT_TYPE_PPGTT_PDE_PT,
@@ -339,6 +345,7 @@ static inline int gtt_set_entry64(void *pt,
 
 #define ADDR_1G_MASK   GENMASK_ULL(GTT_HAW - 1, 30)
 #define ADDR_2M_MASK   GENMASK_ULL(GTT_HAW - 1, 21)
+#define ADDR_64K_MASK  GENMASK_ULL(GTT_HAW - 1, 16)
 #define ADDR_4K_MASK   GENMASK_ULL(GTT_HAW - 1, 12)
 
 static unsigned long gen8_gtt_get_pfn(struct intel_gvt_gtt_entry *e)
@@ -349,6 +356,8 @@ static unsigned long gen8_gtt_get_pfn(struct 
intel_gvt_gtt_entry *e)
pfn = (e->val64 & ADDR_1G_MASK) >> PAGE_SHIFT;
else if (e->type == GTT_TYPE_PPGTT_PTE_2M_ENTRY)
pfn = (e->val64 & ADDR_2M_MASK) >> PAGE_SHIFT;
+   else if (e->type == GTT_TYPE_PPGTT_PTE_64K_ENTRY)
+   pfn = (e->val64 & ADDR_64K_MASK) >> PAGE_SHIFT;
else
pfn = (e->val64 & ADDR_4K_MASK) >> PAGE_SHIFT;
return pfn;
@@ -362,6 +371,9 @@ static void gen8_gtt_set_pfn(struct intel_gvt_gtt_entry *e, 
unsigned long pfn)
} else if (e->type == GTT_TYPE_PPGTT_PTE_2M_ENTRY) {
e->val64 &= ~ADDR_2M_MASK;
pfn &= (ADDR_2M_MASK >> PAGE_SHIFT);
+   } else if (e->type == GTT_TYPE_PPGTT_PTE_64K_ENTRY) {
+   e->val64 &= ~ADDR_64K_MASK;
+   pfn &= (ADDR_64K_MASK >> PAGE_SHIFT);
} else {
e->val64 &= ~ADDR_4K_MASK;
pfn &= (ADDR_4K_MASK >> PAGE_SHIFT);
@@ -380,6 +392,10 @@ static bool gen8_gtt_test_pse(struct intel_gvt_gtt_entry 
*e)
if (!(e->val64 & _PAGE_PSE))
return false;
 
+   /* We don't support 64K entry yet, will remove this later. */
+   if (get_pse_type(e->type) == GTT_TYPE_PPGTT_PTE_64K_ENTRY)
+   return false;
+
e->type = get_pse_type(e->type);
return true;
 }
@@ -871,9 +887,10 @@ static int ppgtt_invalidate_spt(struct 
intel_vgpu_ppgtt_spt *spt)
gvt_vdbg_mm("invalidate 4K entry\n");
ppgtt_invalidate_pte(spt, );
break;
+   case GTT_TYPE_PPGTT_PTE_64K_ENTRY:
case GTT_TYPE_PPGTT_PTE_2M_ENTRY:
case GTT_TYPE_PPGTT_PTE_1G_ENTRY:
-   WARN(1, "GVT doesn't support 2M/1GB page\n");
+   WARN(1, "GVT doesn't support 64K/2M/1GB page\n");
continue;
case GTT_TYPE_PPGTT_PML4_ENTRY:
case GTT_TYPE_PPGTT_PDP_ENTRY:
@@ -970,9 +987,10 @@ static int ppgtt_populate_shadow_entry(struct intel_vgpu 
*vgpu,
case GTT_TYPE_PPGTT_PTE_4K_ENTRY:
gvt_vdbg_mm("shadow 4K gtt entry\n");
break;
+   case GTT_TYPE_PPGTT_PTE_64K_ENTRY:
case GTT_TYPE_PPGTT_PTE_2M_ENTRY:
case GTT_TYPE_PPGTT_PTE_1G_ENTRY:
-   gvt_vgpu_err("GVT doesn't 

[Intel-gfx] [PATCH v6 14/14] drm/i915: Enable platform support for vGPU huge gtt pages

2018-05-08 Thread changbin . du
From: Changbin Du <changbin...@intel.com>

Now GVTg supports shadowing both 2M/64K huge gtt pages. So let's turn on
the cap info bit VGT_CAPS_HUGE_GTT.

v2: Split changes in i915 side into a separated patch.

Signed-off-by: Changbin Du <changbin...@intel.com>
---
 drivers/gpu/drm/i915/gvt/vgpu.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/gpu/drm/i915/gvt/vgpu.c b/drivers/gpu/drm/i915/gvt/vgpu.c
index 2e0a02a..861b398 100644
--- a/drivers/gpu/drm/i915/gvt/vgpu.c
+++ b/drivers/gpu/drm/i915/gvt/vgpu.c
@@ -46,6 +46,7 @@ void populate_pvinfo_page(struct intel_vgpu *vgpu)
 
vgpu_vreg_t(vgpu, vgtif_reg(vgt_caps)) = VGT_CAPS_FULL_48BIT_PPGTT;
vgpu_vreg_t(vgpu, vgtif_reg(vgt_caps)) |= VGT_CAPS_HWSP_EMULATION;
+   vgpu_vreg_t(vgpu, vgtif_reg(vgt_caps)) |= VGT_CAPS_HUGE_GTT;
 
vgpu_vreg_t(vgpu, vgtif_reg(avail_rs.mappable_gmadr.base)) =
vgpu_aperture_gmadr_base(vgpu);
-- 
2.7.4

___
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx


[Intel-gfx] [PATCH v6 02/14] drm/i915/gvt: Add PTE IPS bit operations

2018-05-08 Thread changbin . du
From: Changbin Du <changbin...@intel.com>

Add three IPS operation functions to test/set/clear IPS in PDE.

Signed-off-by: Changbin Du <changbin...@intel.com>
---
 drivers/gpu/drm/i915/gvt/gtt.c | 18 ++
 drivers/gpu/drm/i915/gvt/gtt.h |  2 ++
 2 files changed, 20 insertions(+)

diff --git a/drivers/gpu/drm/i915/gvt/gtt.c b/drivers/gpu/drm/i915/gvt/gtt.c
index 1fcc64a..cd2a227 100644
--- a/drivers/gpu/drm/i915/gvt/gtt.c
+++ b/drivers/gpu/drm/i915/gvt/gtt.c
@@ -400,6 +400,22 @@ static bool gen8_gtt_test_pse(struct intel_gvt_gtt_entry 
*e)
return true;
 }
 
+static bool gen8_gtt_test_ips(struct intel_gvt_gtt_entry *e)
+{
+   if (GEM_WARN_ON(e->type != GTT_TYPE_PPGTT_PDE_ENTRY))
+   return false;
+
+   return !!(e->val64 & GEN8_PDE_IPS_64K);
+}
+
+static void gen8_gtt_clear_ips(struct intel_gvt_gtt_entry *e)
+{
+   if (GEM_WARN_ON(e->type != GTT_TYPE_PPGTT_PDE_ENTRY))
+   return;
+
+   e->val64 &= ~GEN8_PDE_IPS_64K;
+}
+
 static bool gen8_gtt_test_present(struct intel_gvt_gtt_entry *e)
 {
/*
@@ -456,6 +472,8 @@ static struct intel_gvt_gtt_pte_ops gen8_gtt_pte_ops = {
.set_present = gtt_entry_set_present,
.test_present = gen8_gtt_test_present,
.test_pse = gen8_gtt_test_pse,
+   .clear_ips = gen8_gtt_clear_ips,
+   .test_ips = gen8_gtt_test_ips,
.get_pfn = gen8_gtt_get_pfn,
.set_pfn = gen8_gtt_set_pfn,
 };
diff --git a/drivers/gpu/drm/i915/gvt/gtt.h b/drivers/gpu/drm/i915/gvt/gtt.h
index 6063081..9257b74 100644
--- a/drivers/gpu/drm/i915/gvt/gtt.h
+++ b/drivers/gpu/drm/i915/gvt/gtt.h
@@ -63,6 +63,8 @@ struct intel_gvt_gtt_pte_ops {
void (*clear_present)(struct intel_gvt_gtt_entry *e);
void (*set_present)(struct intel_gvt_gtt_entry *e);
bool (*test_pse)(struct intel_gvt_gtt_entry *e);
+   bool (*test_ips)(struct intel_gvt_gtt_entry *e);
+   void (*clear_ips)(struct intel_gvt_gtt_entry *e);
void (*set_pfn)(struct intel_gvt_gtt_entry *e, unsigned long pfn);
unsigned long (*get_pfn)(struct intel_gvt_gtt_entry *e);
 };
-- 
2.7.4

___
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx


[Intel-gfx] [PATCH v6 08/14] drm/i915/gvt: Make PTE iterator 64K entry aware

2018-05-08 Thread changbin . du
From: Changbin Du <changbin...@intel.com>

64K PTE is special, only PTE#0, PTE#16, PTE#32, ... PTE#496 are used in
the page table.

Signed-off-by: Changbin Du <changbin...@intel.com>
---
 drivers/gpu/drm/i915/gvt/gtt.c | 8 ++--
 1 file changed, 6 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/i915/gvt/gtt.c b/drivers/gpu/drm/i915/gvt/gtt.c
index 22e77d4..30b15e4 100644
--- a/drivers/gpu/drm/i915/gvt/gtt.c
+++ b/drivers/gpu/drm/i915/gvt/gtt.c
@@ -351,6 +351,8 @@ static inline int gtt_set_entry64(void *pt,
 #define GTT_SPTE_FLAG_MASK GENMASK_ULL(62, 52)
 #define GTT_SPTE_FLAG_64K_SPLITED BIT(52) /* splited 64K gtt entry */
 
+#define GTT_64K_PTE_STRIDE 16
+
 static unsigned long gen8_gtt_get_pfn(struct intel_gvt_gtt_entry *e)
 {
unsigned long pfn;
@@ -889,12 +891,14 @@ static struct intel_vgpu_ppgtt_spt *ppgtt_alloc_spt_gfn(
(I915_GTT_PAGE_SIZE >> pt_entry_size_shift(spt))
 
 #define for_each_present_guest_entry(spt, e, i) \
-   for (i = 0; i < pt_entries(spt); i++) \
+   for (i = 0; i < pt_entries(spt); \
+i += spt->guest_page.pde_ips ? GTT_64K_PTE_STRIDE : 1) \
if (!ppgtt_get_guest_entry(spt, e, i) && \
spt->vgpu->gvt->gtt.pte_ops->test_present(e))
 
 #define for_each_present_shadow_entry(spt, e, i) \
-   for (i = 0; i < pt_entries(spt); i++) \
+   for (i = 0; i < pt_entries(spt); \
+i += spt->shadow_page.pde_ips ? GTT_64K_PTE_STRIDE : 1) \
if (!ppgtt_get_shadow_entry(spt, e, i) && \
spt->vgpu->gvt->gtt.pte_ops->test_present(e))
 
-- 
2.7.4

___
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx


[Intel-gfx] [PATCH v6 09/14] drm/i915/gvt: Add 64K huge gtt support

2018-05-08 Thread changbin . du
From: Changbin Du <changbin...@intel.com>

Finally, this add the first huge gtt support for GVTg - 64K pages. Since
64K page and 4K page cannot be mixed on the same page table, so we always
split a 64K entry into small 4K page. And when unshadow guest 64K entry,
we need ensure all the shadowed entries in shadow page table also get
cleared.

For page table which has 64K gtt entry, only PTE#0, PTE#16, PTE#32, ...
PTE#496 are used. Unused PTEs update should be ignored.

Signed-off-by: Changbin Du <changbin...@intel.com>
---
 drivers/gpu/drm/i915/gvt/gtt.c | 86 +++---
 1 file changed, 80 insertions(+), 6 deletions(-)

diff --git a/drivers/gpu/drm/i915/gvt/gtt.c b/drivers/gpu/drm/i915/gvt/gtt.c
index 30b15e4..2f13464 100644
--- a/drivers/gpu/drm/i915/gvt/gtt.c
+++ b/drivers/gpu/drm/i915/gvt/gtt.c
@@ -978,9 +978,12 @@ static int ppgtt_invalidate_spt(struct 
intel_vgpu_ppgtt_spt *spt)
ppgtt_invalidate_pte(spt, );
break;
case GTT_TYPE_PPGTT_PTE_64K_ENTRY:
+   /* We don't setup 64K shadow entry so far. */
+   WARN(1, "suspicious 64K gtt entry\n");
+   continue;
case GTT_TYPE_PPGTT_PTE_2M_ENTRY:
case GTT_TYPE_PPGTT_PTE_1G_ENTRY:
-   WARN(1, "GVT doesn't support 64K/2M/1GB page\n");
+   WARN(1, "GVT doesn't support 2M/1GB page\n");
continue;
case GTT_TYPE_PPGTT_PML4_ENTRY:
case GTT_TYPE_PPGTT_PDP_ENTRY:
@@ -1073,9 +1076,44 @@ static inline void ppgtt_generate_shadow_entry(struct 
intel_gvt_gtt_entry *se,
se->type = ge->type;
se->val64 = ge->val64;
 
+   /* Because we always split 64KB pages, so clear IPS in shadow PDE. */
+   if (se->type == GTT_TYPE_PPGTT_PDE_ENTRY)
+   ops->clear_ips(se);
+
ops->set_pfn(se, s->shadow_page.mfn);
 }
 
+static int split_64KB_gtt_entry(struct intel_vgpu *vgpu,
+   struct intel_vgpu_ppgtt_spt *spt, unsigned long index,
+   struct intel_gvt_gtt_entry *se)
+{
+   struct intel_gvt_gtt_pte_ops *ops = vgpu->gvt->gtt.pte_ops;
+   struct intel_gvt_gtt_entry entry = *se;
+   unsigned long start_gfn;
+   dma_addr_t dma_addr;
+   int i, ret;
+
+   gvt_vdbg_mm("Split 64K gtt entry, index %lu\n", index);
+
+   GEM_BUG_ON(index % GTT_64K_PTE_STRIDE);
+
+   start_gfn = ops->get_pfn(se);
+
+   entry.type = GTT_TYPE_PPGTT_PTE_4K_ENTRY;
+   ops->set_64k_splited();
+
+   for (i = 0; i < GTT_64K_PTE_STRIDE; i++) {
+   ret = intel_gvt_hypervisor_dma_map_guest_page(vgpu,
+   start_gfn + i, _addr);
+   if (ret)
+   return ret;
+
+   ops->set_pfn(, dma_addr >> PAGE_SHIFT);
+   ppgtt_set_shadow_entry(spt, , index + i);
+   }
+   return 0;
+}
+
 static int ppgtt_populate_shadow_entry(struct intel_vgpu *vgpu,
struct intel_vgpu_ppgtt_spt *spt, unsigned long index,
struct intel_gvt_gtt_entry *ge)
@@ -1096,9 +1134,16 @@ static int ppgtt_populate_shadow_entry(struct intel_vgpu 
*vgpu,
gvt_vdbg_mm("shadow 4K gtt entry\n");
break;
case GTT_TYPE_PPGTT_PTE_64K_ENTRY:
+   gvt_vdbg_mm("shadow 64K gtt entry\n");
+   /*
+* The layout of 64K page is special, the page size is
+* controlled by uper PDE. To be simple, we always split
+* 64K page to smaller 4K pages in shadow PT.
+*/
+   return split_64KB_gtt_entry(vgpu, spt, index, );
case GTT_TYPE_PPGTT_PTE_2M_ENTRY:
case GTT_TYPE_PPGTT_PTE_1G_ENTRY:
-   gvt_vgpu_err("GVT doesn't support 64K/2M/1GB entry\n");
+   gvt_vgpu_err("GVT doesn't support 2M/1GB entry\n");
return -EINVAL;
default:
GEM_BUG_ON(1);
@@ -1188,8 +1233,12 @@ static int ppgtt_handle_guest_entry_removal(struct 
intel_vgpu_ppgtt_spt *spt,
ret = ppgtt_invalidate_spt(s);
if (ret)
goto fail;
-   } else
+   } else {
+   /* We don't setup 64K shadow entry so far. */
+   WARN(se->type == GTT_TYPE_PPGTT_PTE_64K_ENTRY,
+"suspicious 64K entry\n");
ppgtt_invalidate_pte(spt, se);
+   }
 
return 0;
 fail:
@@ -1412,7 +1461,7 @@ static int ppgtt_handle_guest_write_page_table(
struct intel_gvt_gtt_pte_ops *ops = vgpu->gvt->gtt.pte_ops;
struct intel_gvt_gtt_entry old_se;
int new_present;
-   int ret;
+   int i, ret;
 
new_present = ops->test_present(we);
 
@@ -

[Intel-gfx] [PATCH v6 10/14] drm/i915/kvmgt: Support setting dma map for huge pages

2018-05-08 Thread changbin . du
From: Changbin Du <changbin...@intel.com>

To support huge gtt, we need to support huge pages in kvmgt first.
This patch adds a 'size' param to the intel_gvt_mpt::dma_map_guest_page
API and implements it in kvmgt.

v2: rebase.

Signed-off-by: Changbin Du <changbin...@intel.com>
---
 drivers/gpu/drm/i915/gvt/gtt.c   |   6 +-
 drivers/gpu/drm/i915/gvt/hypercall.h |   2 +-
 drivers/gpu/drm/i915/gvt/kvmgt.c | 130 +--
 drivers/gpu/drm/i915/gvt/mpt.h   |   7 +-
 4 files changed, 101 insertions(+), 44 deletions(-)

diff --git a/drivers/gpu/drm/i915/gvt/gtt.c b/drivers/gpu/drm/i915/gvt/gtt.c
index 2f13464..ffeecda 100644
--- a/drivers/gpu/drm/i915/gvt/gtt.c
+++ b/drivers/gpu/drm/i915/gvt/gtt.c
@@ -1104,7 +1104,7 @@ static int split_64KB_gtt_entry(struct intel_vgpu *vgpu,
 
for (i = 0; i < GTT_64K_PTE_STRIDE; i++) {
ret = intel_gvt_hypervisor_dma_map_guest_page(vgpu,
-   start_gfn + i, _addr);
+   start_gfn + i, PAGE_SIZE, _addr);
if (ret)
return ret;
 
@@ -1150,7 +1150,7 @@ static int ppgtt_populate_shadow_entry(struct intel_vgpu 
*vgpu,
};
 
/* direct shadow */
-   ret = intel_gvt_hypervisor_dma_map_guest_page(vgpu, gfn, _addr);
+   ret = intel_gvt_hypervisor_dma_map_guest_page(vgpu, gfn, PAGE_SIZE, 
_addr);
if (ret)
return -ENXIO;
 
@@ -2078,7 +2078,7 @@ static int emulate_ggtt_mmio_write(struct intel_vgpu 
*vgpu, unsigned int off,
}
 
ret = intel_gvt_hypervisor_dma_map_guest_page(vgpu, gfn,
- _addr);
+   PAGE_SIZE, _addr);
if (ret) {
gvt_vgpu_err("fail to populate guest ggtt entry\n");
/* guest driver may read/write the entry when partial
diff --git a/drivers/gpu/drm/i915/gvt/hypercall.h 
b/drivers/gpu/drm/i915/gvt/hypercall.h
index f6dd9f7..5af11cf 100644
--- a/drivers/gpu/drm/i915/gvt/hypercall.h
+++ b/drivers/gpu/drm/i915/gvt/hypercall.h
@@ -53,7 +53,7 @@ struct intel_gvt_mpt {
unsigned long (*gfn_to_mfn)(unsigned long handle, unsigned long gfn);
 
int (*dma_map_guest_page)(unsigned long handle, unsigned long gfn,
- dma_addr_t *dma_addr);
+ unsigned long size, dma_addr_t *dma_addr);
void (*dma_unmap_guest_page)(unsigned long handle, dma_addr_t dma_addr);
 
int (*map_gfn_to_mfn)(unsigned long handle, unsigned long gfn,
diff --git a/drivers/gpu/drm/i915/gvt/kvmgt.c b/drivers/gpu/drm/i915/gvt/kvmgt.c
index df4e4a0..4d2f53a 100644
--- a/drivers/gpu/drm/i915/gvt/kvmgt.c
+++ b/drivers/gpu/drm/i915/gvt/kvmgt.c
@@ -94,6 +94,7 @@ struct gvt_dma {
struct rb_node dma_addr_node;
gfn_t gfn;
dma_addr_t dma_addr;
+   unsigned long size;
struct kref ref;
 };
 
@@ -106,51 +107,103 @@ static int kvmgt_guest_init(struct mdev_device *mdev);
 static void intel_vgpu_release_work(struct work_struct *work);
 static bool kvmgt_guest_exit(struct kvmgt_guest_info *info);
 
-static int gvt_dma_map_page(struct intel_vgpu *vgpu, unsigned long gfn,
-   dma_addr_t *dma_addr)
+static void gvt_unpin_guest_page(struct intel_vgpu *vgpu, unsigned long gfn,
+   unsigned long size)
 {
-   struct device *dev = >gvt->dev_priv->drm.pdev->dev;
-   struct page *page;
-   unsigned long pfn;
+   int total_pages;
+   int npage;
int ret;
 
-   /* Pin the page first. */
-   ret = vfio_pin_pages(mdev_dev(vgpu->vdev.mdev), , 1,
-IOMMU_READ | IOMMU_WRITE, );
-   if (ret != 1) {
-   gvt_vgpu_err("vfio_pin_pages failed for gfn 0x%lx: %d\n",
-gfn, ret);
-   return -EINVAL;
+   total_pages = roundup(size, PAGE_SIZE) / PAGE_SIZE;
+
+   for (npage = 0; npage < total_pages; npage++) {
+   unsigned long cur_gfn = gfn + npage;
+
+   ret = vfio_unpin_pages(mdev_dev(vgpu->vdev.mdev), _gfn, 1);
+   WARN_ON(ret != 1);
}
+}
 
-   if (!pfn_valid(pfn)) {
-   gvt_vgpu_err("pfn 0x%lx is not mem backed\n", pfn);
-   vfio_unpin_pages(mdev_dev(vgpu->vdev.mdev), , 1);
-   return -EINVAL;
+/* Pin a normal or compound guest page for dma. */
+static int gvt_pin_guest_page(struct intel_vgpu *vgpu, unsigned long gfn,
+   unsigned long size, struct page **page)
+{
+   unsigned long base_pfn = 0;
+   int total_pages;
+   int npage;
+   int ret;
+
+   total_pages = roundup(size, PAGE_SIZE) / PAGE_SIZE;
+   /*
+* We pin the pages one-by-one to avoid allocating a big arrary
+ 

[Intel-gfx] [PATCH v6 04/14] drm/i915/gvt: Detect 64K gtt entry by IPS bit of PDE

2018-05-08 Thread changbin . du
From: Changbin Du <changbin...@intel.com>

This change help us detect the real entry type per PSE and IPS setting.
For 64K entry, we also need to check reg GEN8_GAMW_ECO_DEV_RW_IA.

Signed-off-by: Changbin Du <changbin...@intel.com>
---
 drivers/gpu/drm/i915/gvt/gtt.c | 68 +-
 drivers/gpu/drm/i915/gvt/gtt.h |  2 ++
 2 files changed, 49 insertions(+), 21 deletions(-)

diff --git a/drivers/gpu/drm/i915/gvt/gtt.c b/drivers/gpu/drm/i915/gvt/gtt.c
index cd2a227..7a80518 100644
--- a/drivers/gpu/drm/i915/gvt/gtt.c
+++ b/drivers/gpu/drm/i915/gvt/gtt.c
@@ -384,20 +384,7 @@ static void gen8_gtt_set_pfn(struct intel_gvt_gtt_entry 
*e, unsigned long pfn)
 
 static bool gen8_gtt_test_pse(struct intel_gvt_gtt_entry *e)
 {
-   /* Entry doesn't have PSE bit. */
-   if (get_pse_type(e->type) == GTT_TYPE_INVALID)
-   return false;
-
-   e->type = get_entry_type(e->type);
-   if (!(e->val64 & _PAGE_PSE))
-   return false;
-
-   /* We don't support 64K entry yet, will remove this later. */
-   if (get_pse_type(e->type) == GTT_TYPE_PPGTT_PTE_64K_ENTRY)
-   return false;
-
-   e->type = get_pse_type(e->type);
-   return true;
+   return !!(e->val64 & _PAGE_PSE);
 }
 
 static bool gen8_gtt_test_ips(struct intel_gvt_gtt_entry *e)
@@ -487,6 +474,27 @@ static struct intel_gvt_gtt_gma_ops gen8_gtt_gma_ops = {
.gma_to_pml4_index = gen8_gma_to_pml4_index,
 };
 
+/* Update entry type per pse and ips bit. */
+static void update_entry_type_for_real(struct intel_gvt_gtt_pte_ops *pte_ops,
+   struct intel_gvt_gtt_entry *entry, bool ips)
+{
+   switch (entry->type) {
+   case GTT_TYPE_PPGTT_PDE_ENTRY:
+   case GTT_TYPE_PPGTT_PDP_ENTRY:
+   if (pte_ops->test_pse(entry))
+   entry->type = get_pse_type(entry->type);
+   break;
+   case GTT_TYPE_PPGTT_PTE_4K_ENTRY:
+   if (ips)
+   entry->type = get_pse_type(entry->type);
+   break;
+   default:
+   GEM_BUG_ON(!gtt_type_is_entry(entry->type));
+   }
+
+   GEM_BUG_ON(entry->type == GTT_TYPE_INVALID);
+}
+
 /*
  * MM helpers.
  */
@@ -502,8 +510,7 @@ static void _ppgtt_get_root_entry(struct intel_vgpu_mm *mm,
pte_ops->get_entry(guest ? mm->ppgtt_mm.guest_pdps :
   mm->ppgtt_mm.shadow_pdps,
   entry, index, false, 0, mm->vgpu);
-
-   pte_ops->test_pse(entry);
+   update_entry_type_for_real(pte_ops, entry, false);
 }
 
 static inline void ppgtt_get_guest_root_entry(struct intel_vgpu_mm *mm,
@@ -608,7 +615,8 @@ static inline int ppgtt_spt_get_entry(
if (ret)
return ret;
 
-   ops->test_pse(e);
+   update_entry_type_for_real(ops, e, guest ?
+  spt->guest_page.pde_ips : false);
 
gvt_vdbg_mm("read ppgtt entry, spt type %d, entry type %d, index %lu, 
value %llx\n",
type, e->type, index, e->val64);
@@ -752,7 +760,8 @@ static inline struct intel_vgpu_ppgtt_spt 
*intel_vgpu_find_spt_by_mfn(
 static int reclaim_one_ppgtt_mm(struct intel_gvt *gvt);
 
 static struct intel_vgpu_ppgtt_spt *ppgtt_alloc_spt(
-   struct intel_vgpu *vgpu, int type, unsigned long gfn)
+   struct intel_vgpu *vgpu, int type, unsigned long gfn,
+   bool guest_pde_ips)
 {
struct device *kdev = >gvt->dev_priv->drm.pdev->dev;
struct intel_vgpu_ppgtt_spt *spt = NULL;
@@ -792,6 +801,7 @@ static struct intel_vgpu_ppgtt_spt *ppgtt_alloc_spt(
 */
spt->guest_page.type = type;
spt->guest_page.gfn = gfn;
+   spt->guest_page.pde_ips = guest_pde_ips;
 
ret = intel_vgpu_register_page_track(vgpu, spt->guest_page.gfn,
ppgtt_write_protection_handler, spt);
@@ -934,6 +944,20 @@ static int ppgtt_invalidate_spt(struct 
intel_vgpu_ppgtt_spt *spt)
return ret;
 }
 
+static bool vgpu_ips_enabled(struct intel_vgpu *vgpu)
+{
+   if (INTEL_GEN(vgpu->gvt->dev_priv) == 9) {
+   u32 ips = vgpu_vreg_t(vgpu, GEN8_GAMW_ECO_DEV_RW_IA) &
+   GAMW_ECO_ENABLE_64K_IPS_FIELD;
+
+   return ips == GAMW_ECO_ENABLE_64K_IPS_FIELD;
+   } else if (INTEL_GEN(vgpu->gvt->dev_priv) >= 10) {
+   /* 64K paging only controlled by IPS bit in PTE now. */
+   return true;
+   } else
+   return false;
+}
+
 static int ppgtt_populate_spt(struct intel_vgpu_ppgtt_spt *spt);
 
 static struct intel_vgpu_ppgtt_spt *ppgtt_populate_spt_by_guest_entry(
@@ -941,6 +965,7 @@ static struct intel_vgpu_ppgtt_spt 
*ppgtt_populate_spt_by_guest_entry(
 {
struct intel_gvt_gtt_pte_ops *ops = vgpu->gvt->gtt.pte_ops;

[Intel-gfx] [PATCH v5 12/14] drm/i915/gvt: Handle special sequence on PDE IPS bit

2018-05-07 Thread changbin . du
From: Changbin Du <changbin...@intel.com>

If the guest update the 64K gtt entry before changing IPS bit of PDE, we
need to re-shadow the whole page table. Because we have ignored all
updates to unused entries.

Signed-off-by: Changbin Du <changbin...@intel.com>
---
 drivers/gpu/drm/i915/gvt/gtt.c | 20 +++-
 1 file changed, 15 insertions(+), 5 deletions(-)

diff --git a/drivers/gpu/drm/i915/gvt/gtt.c b/drivers/gpu/drm/i915/gvt/gtt.c
index bf718a3..2bf85be 100644
--- a/drivers/gpu/drm/i915/gvt/gtt.c
+++ b/drivers/gpu/drm/i915/gvt/gtt.c
@@ -1043,14 +1043,24 @@ static struct intel_vgpu_ppgtt_spt 
*ppgtt_populate_spt_by_guest_entry(
 
GEM_BUG_ON(!gtt_type_is_pt(get_next_pt_type(we->type)));
 
+   if (we->type == GTT_TYPE_PPGTT_PDE_ENTRY)
+   ips = vgpu_ips_enabled(vgpu) && ops->test_ips(we);
+
spt = intel_vgpu_find_spt_by_gfn(vgpu, ops->get_pfn(we));
-   if (spt)
+   if (spt) {
ppgtt_get_spt(spt);
-   else {
-   int type = get_next_pt_type(we->type);
 
-   if (we->type == GTT_TYPE_PPGTT_PDE_ENTRY)
-   ips = vgpu_ips_enabled(vgpu) && ops->test_ips(we);
+   if (ips != spt->guest_page.pde_ips) {
+   spt->guest_page.pde_ips = ips;
+
+   gvt_dbg_mm("reshadow PDE since ips changed\n");
+   clear_page(spt->shadow_page.vaddr);
+   ret = ppgtt_populate_spt(spt);
+   if (ret)
+   goto fail;
+   }
+   } else {
+   int type = get_next_pt_type(we->type);
 
spt = ppgtt_alloc_spt_gfn(vgpu, type, ops->get_pfn(we), ips);
if (IS_ERR(spt)) {
-- 
2.7.4

___
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx


[Intel-gfx] [PATCH v5 13/14] drm/i915/gvt: Fix error handling in ppgtt_populate_spt_by_guest_entry

2018-05-07 Thread changbin . du
From: Changbin Du <changbin...@intel.com>

Don't forget to free allocated spt if shadowing failed.

Signed-off-by: Changbin Du <changbin...@intel.com>
---
 drivers/gpu/drm/i915/gvt/gtt.c | 33 +
 1 file changed, 21 insertions(+), 12 deletions(-)

diff --git a/drivers/gpu/drm/i915/gvt/gtt.c b/drivers/gpu/drm/i915/gvt/gtt.c
index 2bf85be..f83ac08 100644
--- a/drivers/gpu/drm/i915/gvt/gtt.c
+++ b/drivers/gpu/drm/i915/gvt/gtt.c
@@ -907,15 +907,22 @@ static struct intel_vgpu_ppgtt_spt *ppgtt_alloc_spt_gfn(
 i += (spt->shadow_page.pde_ips ? GTT_64K_PTE_STRIDE : 1)) \
if (!ppgtt_get_shadow_entry(spt, e, i))
 
-static void ppgtt_get_spt(struct intel_vgpu_ppgtt_spt *spt)
+static inline void ppgtt_get_spt(struct intel_vgpu_ppgtt_spt *spt)
 {
int v = atomic_read(>refcount);
 
trace_spt_refcount(spt->vgpu->id, "inc", spt, v, (v + 1));
-
atomic_inc(>refcount);
 }
 
+static inline int ppgtt_put_spt(struct intel_vgpu_ppgtt_spt *spt)
+{
+   int v = atomic_read(>refcount);
+
+   trace_spt_refcount(spt->vgpu->id, "dec", spt, v, (v - 1));
+   return atomic_dec_return(>refcount);
+}
+
 static int ppgtt_invalidate_spt(struct intel_vgpu_ppgtt_spt *spt);
 
 static int ppgtt_invalidate_spt_by_shadow_entry(struct intel_vgpu *vgpu,
@@ -967,14 +974,11 @@ static int ppgtt_invalidate_spt(struct 
intel_vgpu_ppgtt_spt *spt)
struct intel_gvt_gtt_entry e;
unsigned long index;
int ret;
-   int v = atomic_read(>refcount);
 
trace_spt_change(spt->vgpu->id, "die", spt,
spt->guest_page.gfn, spt->shadow_page.type);
 
-   trace_spt_refcount(spt->vgpu->id, "dec", spt, v, (v - 1));
-
-   if (atomic_dec_return(>refcount) > 0)
+   if (ppgtt_put_spt(spt) > 0)
return 0;
 
for_each_present_shadow_entry(spt, , index) {
@@ -1056,8 +1060,10 @@ static struct intel_vgpu_ppgtt_spt 
*ppgtt_populate_spt_by_guest_entry(
gvt_dbg_mm("reshadow PDE since ips changed\n");
clear_page(spt->shadow_page.vaddr);
ret = ppgtt_populate_spt(spt);
-   if (ret)
-   goto fail;
+   if (ret) {
+   ppgtt_put_spt(spt);
+   goto err;
+   }
}
} else {
int type = get_next_pt_type(we->type);
@@ -1065,22 +1071,25 @@ static struct intel_vgpu_ppgtt_spt 
*ppgtt_populate_spt_by_guest_entry(
spt = ppgtt_alloc_spt_gfn(vgpu, type, ops->get_pfn(we), ips);
if (IS_ERR(spt)) {
ret = PTR_ERR(spt);
-   goto fail;
+   goto err;
}
 
ret = intel_vgpu_enable_page_track(vgpu, spt->guest_page.gfn);
if (ret)
-   goto fail;
+   goto err_free_spt;
 
ret = ppgtt_populate_spt(spt);
if (ret)
-   goto fail;
+   goto err_free_spt;
 
trace_spt_change(vgpu->id, "new", spt, spt->guest_page.gfn,
 spt->shadow_page.type);
}
return spt;
-fail:
+
+err_free_spt:
+   ppgtt_free_spt(spt);
+err:
gvt_vgpu_err("fail: shadow page %p guest entry 0x%llx type %d\n",
 spt, we->val64, we->type);
return ERR_PTR(ret);
-- 
2.7.4

___
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx


[Intel-gfx] [PATCH v5 11/14] drm/i915/gvt: Add 2M huge gtt support

2018-05-07 Thread changbin . du
From: Changbin Du <changbin...@intel.com>

This add 2M huge gtt support for GVTg. Unlike 64K gtt entry, we can
shadow 2M guest entry with real huge gtt. But before that, we have to
check memory physical continuous, alignment and if it is supported on
the host. We can get all supported page sizes from
intel_device_info.page_sizes.

Finally we must split the 2M page into smaller pages if we cannot
satisfy guest Huge Page.

Signed-off-by: Changbin Du <changbin...@intel.com>
---
 drivers/gpu/drm/i915/gvt/gtt.c | 100 ++---
 1 file changed, 95 insertions(+), 5 deletions(-)

diff --git a/drivers/gpu/drm/i915/gvt/gtt.c b/drivers/gpu/drm/i915/gvt/gtt.c
index ffeecda..bf718a3 100644
--- a/drivers/gpu/drm/i915/gvt/gtt.c
+++ b/drivers/gpu/drm/i915/gvt/gtt.c
@@ -902,6 +902,11 @@ static struct intel_vgpu_ppgtt_spt *ppgtt_alloc_spt_gfn(
if (!ppgtt_get_shadow_entry(spt, e, i) && \
spt->vgpu->gvt->gtt.pte_ops->test_present(e))
 
+#define for_each_shadow_entry(spt, e, i) \
+   for (i = 0; i < pt_entries(spt); \
+i += (spt->shadow_page.pde_ips ? GTT_64K_PTE_STRIDE : 1)) \
+   if (!ppgtt_get_shadow_entry(spt, e, i))
+
 static void ppgtt_get_spt(struct intel_vgpu_ppgtt_spt *spt)
 {
int v = atomic_read(>refcount);
@@ -949,7 +954,8 @@ static inline void ppgtt_invalidate_pte(struct 
intel_vgpu_ppgtt_spt *spt,
pfn = ops->get_pfn(entry);
type = spt->shadow_page.type;
 
-   if (pfn == vgpu->gtt.scratch_pt[type].page_mfn)
+   /* Uninitialized spte or unshadowed spte. */
+   if (!pfn || pfn == vgpu->gtt.scratch_pt[type].page_mfn)
return;
 
intel_gvt_hypervisor_dma_unmap_guest_page(vgpu, pfn << PAGE_SHIFT);
@@ -982,8 +988,10 @@ static int ppgtt_invalidate_spt(struct 
intel_vgpu_ppgtt_spt *spt)
WARN(1, "suspicious 64K gtt entry\n");
continue;
case GTT_TYPE_PPGTT_PTE_2M_ENTRY:
+   gvt_vdbg_mm("invalidate 2M entry\n");
+   continue;
case GTT_TYPE_PPGTT_PTE_1G_ENTRY:
-   WARN(1, "GVT doesn't support 2M/1GB page\n");
+   WARN(1, "GVT doesn't support 1GB page\n");
continue;
case GTT_TYPE_PPGTT_PML4_ENTRY:
case GTT_TYPE_PPGTT_PDP_ENTRY:
@@ -1083,6 +1091,73 @@ static inline void ppgtt_generate_shadow_entry(struct 
intel_gvt_gtt_entry *se,
ops->set_pfn(se, s->shadow_page.mfn);
 }
 
+/**
+ * Return 1 if 2MB huge gtt shadowing is possilbe, 0 if miscondition,
+ * negtive if found err.
+ */
+static int is_2MB_gtt_possible(struct intel_vgpu *vgpu,
+   struct intel_gvt_gtt_entry *entry)
+{
+   struct intel_gvt_gtt_pte_ops *ops = vgpu->gvt->gtt.pte_ops;
+   unsigned long pfn;
+
+   if (!HAS_PAGE_SIZES(vgpu->gvt->dev_priv, I915_GTT_PAGE_SIZE_2M))
+   return 0;
+
+   pfn = intel_gvt_hypervisor_gfn_to_mfn(vgpu, ops->get_pfn(entry));
+   if (pfn == INTEL_GVT_INVALID_ADDR)
+   return -EINVAL;
+
+   return PageTransHuge(pfn_to_page(pfn));
+}
+
+static int split_2MB_gtt_entry(struct intel_vgpu *vgpu,
+   struct intel_vgpu_ppgtt_spt *spt, unsigned long index,
+   struct intel_gvt_gtt_entry *se)
+{
+   struct intel_gvt_gtt_pte_ops *ops = vgpu->gvt->gtt.pte_ops;
+   struct intel_vgpu_ppgtt_spt *sub_spt;
+   struct intel_gvt_gtt_entry sub_se;
+   unsigned long start_gfn;
+   dma_addr_t dma_addr;
+   unsigned long sub_index;
+   int ret;
+
+   gvt_dbg_mm("Split 2M gtt entry, index %lu\n", index);
+
+   start_gfn = ops->get_pfn(se);
+
+   sub_spt = ppgtt_alloc_spt(vgpu, GTT_TYPE_PPGTT_PTE_PT);
+   if (IS_ERR(sub_spt))
+   return PTR_ERR(sub_spt);
+
+   for_each_shadow_entry(sub_spt, _se, sub_index) {
+   ret = intel_gvt_hypervisor_dma_map_guest_page(vgpu,
+   start_gfn + sub_index, PAGE_SIZE, _addr);
+   if (ret) {
+   ppgtt_invalidate_spt(spt);
+   return ret;
+   }
+   sub_se.val64 = se->val64;
+
+   /* Copy the PAT field from PDE. */
+   sub_se.val64 &= ~_PAGE_PAT;
+   sub_se.val64 |= (se->val64 & _PAGE_PAT_LARGE) >> 5;
+
+   ops->set_pfn(_se, dma_addr >> PAGE_SHIFT);
+   ppgtt_set_shadow_entry(sub_spt, _se, sub_index);
+   }
+
+   /* Clear dirty field. */
+   se->val64 &= ~_PAGE_DIRTY;
+
+   ops->clear_pse(se);
+   ops->clear_ips(se);
+   ops->set_pfn(se, sub_spt->shadow_page.mfn);
+   ppgtt_set_shadow_entry(spt, se, index);
+   return 0;
+}
+
 static int split_64KB_gtt_entry(s

[Intel-gfx] [PATCH v5 05/14] drm/i915/gvt: Add software PTE flag to mark special 64K splited entry

2018-05-07 Thread changbin . du
From: Changbin Du <changbin...@intel.com>

This add a software PTE flag on the Ignored bit of PTE. It will be used
to identify splited 64K shadow entries.

v2: fix mask definition.

Signed-off-by: Changbin Du <changbin...@intel.com>
---
 drivers/gpu/drm/i915/gvt/gtt.c | 21 +
 drivers/gpu/drm/i915/gvt/gtt.h |  3 +++
 2 files changed, 24 insertions(+)

diff --git a/drivers/gpu/drm/i915/gvt/gtt.c b/drivers/gpu/drm/i915/gvt/gtt.c
index 7a80518..f7bc8ff 100644
--- a/drivers/gpu/drm/i915/gvt/gtt.c
+++ b/drivers/gpu/drm/i915/gvt/gtt.c
@@ -348,6 +348,9 @@ static inline int gtt_set_entry64(void *pt,
 #define ADDR_64K_MASK  GENMASK_ULL(GTT_HAW - 1, 16)
 #define ADDR_4K_MASK   GENMASK_ULL(GTT_HAW - 1, 12)
 
+#define GTT_SPTE_FLAG_MASK GENMASK_ULL(62, 52)
+#define GTT_SPTE_FLAG_64K_SPLITED BIT(52) /* splited 64K gtt entry */
+
 static unsigned long gen8_gtt_get_pfn(struct intel_gvt_gtt_entry *e)
 {
unsigned long pfn;
@@ -427,6 +430,21 @@ static void gtt_entry_set_present(struct 
intel_gvt_gtt_entry *e)
e->val64 |= _PAGE_PRESENT;
 }
 
+static bool gen8_gtt_test_64k_splited(struct intel_gvt_gtt_entry *e)
+{
+   return !!(e->val64 & GTT_SPTE_FLAG_64K_SPLITED);
+}
+
+static void gen8_gtt_set_64k_splited(struct intel_gvt_gtt_entry *e)
+{
+   e->val64 |= GTT_SPTE_FLAG_64K_SPLITED;
+}
+
+static void gen8_gtt_clear_64k_splited(struct intel_gvt_gtt_entry *e)
+{
+   e->val64 &= ~GTT_SPTE_FLAG_64K_SPLITED;
+}
+
 /*
  * Per-platform GMA routines.
  */
@@ -461,6 +479,9 @@ static struct intel_gvt_gtt_pte_ops gen8_gtt_pte_ops = {
.test_pse = gen8_gtt_test_pse,
.clear_ips = gen8_gtt_clear_ips,
.test_ips = gen8_gtt_test_ips,
+   .clear_64k_splited = gen8_gtt_clear_64k_splited,
+   .set_64k_splited = gen8_gtt_set_64k_splited,
+   .test_64k_splited = gen8_gtt_test_64k_splited,
.get_pfn = gen8_gtt_get_pfn,
.set_pfn = gen8_gtt_set_pfn,
 };
diff --git a/drivers/gpu/drm/i915/gvt/gtt.h b/drivers/gpu/drm/i915/gvt/gtt.h
index c11284b..162ef19 100644
--- a/drivers/gpu/drm/i915/gvt/gtt.h
+++ b/drivers/gpu/drm/i915/gvt/gtt.h
@@ -65,6 +65,9 @@ struct intel_gvt_gtt_pte_ops {
bool (*test_pse)(struct intel_gvt_gtt_entry *e);
bool (*test_ips)(struct intel_gvt_gtt_entry *e);
void (*clear_ips)(struct intel_gvt_gtt_entry *e);
+   bool (*test_64k_splited)(struct intel_gvt_gtt_entry *e);
+   void (*clear_64k_splited)(struct intel_gvt_gtt_entry *e);
+   void (*set_64k_splited)(struct intel_gvt_gtt_entry *e);
void (*set_pfn)(struct intel_gvt_gtt_entry *e, unsigned long pfn);
unsigned long (*get_pfn)(struct intel_gvt_gtt_entry *e);
 };
-- 
2.7.4

___
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx


[Intel-gfx] [PATCH v5 14/14] drm/i915: Enable platform support for vGPU huge gtt pages

2018-05-07 Thread changbin . du
From: Changbin Du <changbin...@intel.com>

Now GVTg supports shadowing both 2M/64K huge gtt pages. So this is to
remove the restriction on guest side.

To be compatible with old host kernel, we defined a new cap info bit
VGT_CAPS_HUGE_GTT.

Cc: Zhenyu Wang <zhen...@linux.intel.com>
Signed-off-by: Changbin Du <changbin...@intel.com>
---
 drivers/gpu/drm/i915/gvt/vgpu.c| 1 +
 drivers/gpu/drm/i915/i915_gem.c| 8 ++--
 drivers/gpu/drm/i915/i915_pvinfo.h | 1 +
 drivers/gpu/drm/i915/i915_vgpu.h   | 6 ++
 4 files changed, 10 insertions(+), 6 deletions(-)

diff --git a/drivers/gpu/drm/i915/gvt/vgpu.c b/drivers/gpu/drm/i915/gvt/vgpu.c
index 2e0a02a..861b398 100644
--- a/drivers/gpu/drm/i915/gvt/vgpu.c
+++ b/drivers/gpu/drm/i915/gvt/vgpu.c
@@ -46,6 +46,7 @@ void populate_pvinfo_page(struct intel_vgpu *vgpu)
 
vgpu_vreg_t(vgpu, vgtif_reg(vgt_caps)) = VGT_CAPS_FULL_48BIT_PPGTT;
vgpu_vreg_t(vgpu, vgtif_reg(vgt_caps)) |= VGT_CAPS_HWSP_EMULATION;
+   vgpu_vreg_t(vgpu, vgtif_reg(vgt_caps)) |= VGT_CAPS_HUGE_GTT;
 
vgpu_vreg_t(vgpu, vgtif_reg(avail_rs.mappable_gmadr.base)) =
vgpu_aperture_gmadr_base(vgpu);
diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c
index 484354f..e0ddfa1 100644
--- a/drivers/gpu/drm/i915/i915_gem.c
+++ b/drivers/gpu/drm/i915/i915_gem.c
@@ -5355,12 +5355,8 @@ int i915_gem_init(struct drm_i915_private *dev_priv)
 {
int ret;
 
-   /*
-* We need to fallback to 4K pages since gvt gtt handling doesn't
-* support huge page entries - we will need to check either hypervisor
-* mm can support huge guest page or just do emulation in gvt.
-*/
-   if (intel_vgpu_active(dev_priv))
+   /* We need to fallback to 4K pages if host doesn't support huge gtt. */
+   if (intel_vgpu_active(dev_priv) && !intel_vgpu_has_huge_gtt(dev_priv))
mkwrite_device_info(dev_priv)->page_sizes =
I915_GTT_PAGE_SIZE_4K;
 
diff --git a/drivers/gpu/drm/i915/i915_pvinfo.h 
b/drivers/gpu/drm/i915/i915_pvinfo.h
index 195203f..55bde4a 100644
--- a/drivers/gpu/drm/i915/i915_pvinfo.h
+++ b/drivers/gpu/drm/i915/i915_pvinfo.h
@@ -54,6 +54,7 @@ enum vgt_g2v_type {
  */
 #define VGT_CAPS_FULL_48BIT_PPGTT  BIT(2)
 #define VGT_CAPS_HWSP_EMULATIONBIT(3)
+#define VGT_CAPS_HUGE_GTT  BIT(4)
 
 struct vgt_if {
u64 magic;  /* VGT_MAGIC */
diff --git a/drivers/gpu/drm/i915/i915_vgpu.h b/drivers/gpu/drm/i915/i915_vgpu.h
index bb83384..551acc3 100644
--- a/drivers/gpu/drm/i915/i915_vgpu.h
+++ b/drivers/gpu/drm/i915/i915_vgpu.h
@@ -36,6 +36,12 @@ intel_vgpu_has_hwsp_emulation(struct drm_i915_private 
*dev_priv)
return dev_priv->vgpu.caps & VGT_CAPS_HWSP_EMULATION;
 }
 
+static inline bool
+intel_vgpu_has_huge_gtt(struct drm_i915_private *dev_priv)
+{
+   return dev_priv->vgpu.caps & VGT_CAPS_HUGE_GTT;
+}
+
 int intel_vgt_balloon(struct drm_i915_private *dev_priv);
 void intel_vgt_deballoon(struct drm_i915_private *dev_priv);
 
-- 
2.7.4

___
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx


[Intel-gfx] [PATCH v5 08/14] drm/i915/gvt: Make PTE iterator 64K entry aware

2018-05-07 Thread changbin . du
From: Changbin Du <changbin...@intel.com>

64K PTE is special, only PTE#0, PTE#16, PTE#32, ... PTE#496 are used in
the page table.

Signed-off-by: Changbin Du <changbin...@intel.com>
---
 drivers/gpu/drm/i915/gvt/gtt.c | 8 ++--
 1 file changed, 6 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/i915/gvt/gtt.c b/drivers/gpu/drm/i915/gvt/gtt.c
index 22e77d4..30b15e4 100644
--- a/drivers/gpu/drm/i915/gvt/gtt.c
+++ b/drivers/gpu/drm/i915/gvt/gtt.c
@@ -351,6 +351,8 @@ static inline int gtt_set_entry64(void *pt,
 #define GTT_SPTE_FLAG_MASK GENMASK_ULL(62, 52)
 #define GTT_SPTE_FLAG_64K_SPLITED BIT(52) /* splited 64K gtt entry */
 
+#define GTT_64K_PTE_STRIDE 16
+
 static unsigned long gen8_gtt_get_pfn(struct intel_gvt_gtt_entry *e)
 {
unsigned long pfn;
@@ -889,12 +891,14 @@ static struct intel_vgpu_ppgtt_spt *ppgtt_alloc_spt_gfn(
(I915_GTT_PAGE_SIZE >> pt_entry_size_shift(spt))
 
 #define for_each_present_guest_entry(spt, e, i) \
-   for (i = 0; i < pt_entries(spt); i++) \
+   for (i = 0; i < pt_entries(spt); \
+i += spt->guest_page.pde_ips ? GTT_64K_PTE_STRIDE : 1) \
if (!ppgtt_get_guest_entry(spt, e, i) && \
spt->vgpu->gvt->gtt.pte_ops->test_present(e))
 
 #define for_each_present_shadow_entry(spt, e, i) \
-   for (i = 0; i < pt_entries(spt); i++) \
+   for (i = 0; i < pt_entries(spt); \
+i += spt->shadow_page.pde_ips ? GTT_64K_PTE_STRIDE : 1) \
if (!ppgtt_get_shadow_entry(spt, e, i) && \
spt->vgpu->gvt->gtt.pte_ops->test_present(e))
 
-- 
2.7.4

___
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx


[Intel-gfx] [PATCH v5 10/14] drm/i915/kvmgt: Support setting dma map for huge pages

2018-05-07 Thread changbin . du
From: Changbin Du <changbin...@intel.com>

To support huge gtt, we need to support huge pages in kvmgt first.
This patch adds a 'size' param to the intel_gvt_mpt::dma_map_guest_page
API and implements it in kvmgt.

v2: rebase.

Signed-off-by: Changbin Du <changbin...@intel.com>
---
 drivers/gpu/drm/i915/gvt/gtt.c   |   6 +-
 drivers/gpu/drm/i915/gvt/hypercall.h |   2 +-
 drivers/gpu/drm/i915/gvt/kvmgt.c | 130 +--
 drivers/gpu/drm/i915/gvt/mpt.h   |   7 +-
 4 files changed, 101 insertions(+), 44 deletions(-)

diff --git a/drivers/gpu/drm/i915/gvt/gtt.c b/drivers/gpu/drm/i915/gvt/gtt.c
index 2f13464..ffeecda 100644
--- a/drivers/gpu/drm/i915/gvt/gtt.c
+++ b/drivers/gpu/drm/i915/gvt/gtt.c
@@ -1104,7 +1104,7 @@ static int split_64KB_gtt_entry(struct intel_vgpu *vgpu,
 
for (i = 0; i < GTT_64K_PTE_STRIDE; i++) {
ret = intel_gvt_hypervisor_dma_map_guest_page(vgpu,
-   start_gfn + i, _addr);
+   start_gfn + i, PAGE_SIZE, _addr);
if (ret)
return ret;
 
@@ -1150,7 +1150,7 @@ static int ppgtt_populate_shadow_entry(struct intel_vgpu 
*vgpu,
};
 
/* direct shadow */
-   ret = intel_gvt_hypervisor_dma_map_guest_page(vgpu, gfn, _addr);
+   ret = intel_gvt_hypervisor_dma_map_guest_page(vgpu, gfn, PAGE_SIZE, 
_addr);
if (ret)
return -ENXIO;
 
@@ -2078,7 +2078,7 @@ static int emulate_ggtt_mmio_write(struct intel_vgpu 
*vgpu, unsigned int off,
}
 
ret = intel_gvt_hypervisor_dma_map_guest_page(vgpu, gfn,
- _addr);
+   PAGE_SIZE, _addr);
if (ret) {
gvt_vgpu_err("fail to populate guest ggtt entry\n");
/* guest driver may read/write the entry when partial
diff --git a/drivers/gpu/drm/i915/gvt/hypercall.h 
b/drivers/gpu/drm/i915/gvt/hypercall.h
index f6dd9f7..5af11cf 100644
--- a/drivers/gpu/drm/i915/gvt/hypercall.h
+++ b/drivers/gpu/drm/i915/gvt/hypercall.h
@@ -53,7 +53,7 @@ struct intel_gvt_mpt {
unsigned long (*gfn_to_mfn)(unsigned long handle, unsigned long gfn);
 
int (*dma_map_guest_page)(unsigned long handle, unsigned long gfn,
- dma_addr_t *dma_addr);
+ unsigned long size, dma_addr_t *dma_addr);
void (*dma_unmap_guest_page)(unsigned long handle, dma_addr_t dma_addr);
 
int (*map_gfn_to_mfn)(unsigned long handle, unsigned long gfn,
diff --git a/drivers/gpu/drm/i915/gvt/kvmgt.c b/drivers/gpu/drm/i915/gvt/kvmgt.c
index df4e4a0..4d2f53a 100644
--- a/drivers/gpu/drm/i915/gvt/kvmgt.c
+++ b/drivers/gpu/drm/i915/gvt/kvmgt.c
@@ -94,6 +94,7 @@ struct gvt_dma {
struct rb_node dma_addr_node;
gfn_t gfn;
dma_addr_t dma_addr;
+   unsigned long size;
struct kref ref;
 };
 
@@ -106,51 +107,103 @@ static int kvmgt_guest_init(struct mdev_device *mdev);
 static void intel_vgpu_release_work(struct work_struct *work);
 static bool kvmgt_guest_exit(struct kvmgt_guest_info *info);
 
-static int gvt_dma_map_page(struct intel_vgpu *vgpu, unsigned long gfn,
-   dma_addr_t *dma_addr)
+static void gvt_unpin_guest_page(struct intel_vgpu *vgpu, unsigned long gfn,
+   unsigned long size)
 {
-   struct device *dev = >gvt->dev_priv->drm.pdev->dev;
-   struct page *page;
-   unsigned long pfn;
+   int total_pages;
+   int npage;
int ret;
 
-   /* Pin the page first. */
-   ret = vfio_pin_pages(mdev_dev(vgpu->vdev.mdev), , 1,
-IOMMU_READ | IOMMU_WRITE, );
-   if (ret != 1) {
-   gvt_vgpu_err("vfio_pin_pages failed for gfn 0x%lx: %d\n",
-gfn, ret);
-   return -EINVAL;
+   total_pages = roundup(size, PAGE_SIZE) / PAGE_SIZE;
+
+   for (npage = 0; npage < total_pages; npage++) {
+   unsigned long cur_gfn = gfn + npage;
+
+   ret = vfio_unpin_pages(mdev_dev(vgpu->vdev.mdev), _gfn, 1);
+   WARN_ON(ret != 1);
}
+}
 
-   if (!pfn_valid(pfn)) {
-   gvt_vgpu_err("pfn 0x%lx is not mem backed\n", pfn);
-   vfio_unpin_pages(mdev_dev(vgpu->vdev.mdev), , 1);
-   return -EINVAL;
+/* Pin a normal or compound guest page for dma. */
+static int gvt_pin_guest_page(struct intel_vgpu *vgpu, unsigned long gfn,
+   unsigned long size, struct page **page)
+{
+   unsigned long base_pfn = 0;
+   int total_pages;
+   int npage;
+   int ret;
+
+   total_pages = roundup(size, PAGE_SIZE) / PAGE_SIZE;
+   /*
+* We pin the pages one-by-one to avoid allocating a big arrary
+ 

[Intel-gfx] [PATCH v5 07/14] drm/i915/gvt: Split ppgtt_alloc_spt into two parts

2018-05-07 Thread changbin . du
From: Changbin Du <changbin...@intel.com>

We need a interface to allocate a pure shadow page which doesn't have
a guest page associated with. Such shadow page is used to shadow 2M
huge gtt entry.

Signed-off-by: Changbin Du <changbin...@intel.com>
---
 drivers/gpu/drm/i915/gvt/gtt.c | 62 +++---
 1 file changed, 40 insertions(+), 22 deletions(-)

diff --git a/drivers/gpu/drm/i915/gvt/gtt.c b/drivers/gpu/drm/i915/gvt/gtt.c
index 0966ee7..22e77d4 100644
--- a/drivers/gpu/drm/i915/gvt/gtt.c
+++ b/drivers/gpu/drm/i915/gvt/gtt.c
@@ -735,10 +735,12 @@ static void ppgtt_free_spt(struct intel_vgpu_ppgtt_spt 
*spt)
 
radix_tree_delete(>vgpu->gtt.spt_tree, spt->shadow_page.mfn);
 
-   if (spt->guest_page.oos_page)
-   detach_oos_page(spt->vgpu, spt->guest_page.oos_page);
+   if (spt->guest_page.gfn) {
+   if (spt->guest_page.oos_page)
+   detach_oos_page(spt->vgpu, spt->guest_page.oos_page);
 
-   intel_vgpu_unregister_page_track(spt->vgpu, spt->guest_page.gfn);
+   intel_vgpu_unregister_page_track(spt->vgpu, 
spt->guest_page.gfn);
+   }
 
list_del_init(>post_shadow_list);
free_spt(spt);
@@ -799,9 +801,9 @@ static inline struct intel_vgpu_ppgtt_spt 
*intel_vgpu_find_spt_by_mfn(
 
 static int reclaim_one_ppgtt_mm(struct intel_gvt *gvt);
 
+/* Allocate shadow page table without guest page. */
 static struct intel_vgpu_ppgtt_spt *ppgtt_alloc_spt(
-   struct intel_vgpu *vgpu, int type, unsigned long gfn,
-   bool guest_pde_ips)
+   struct intel_vgpu *vgpu, intel_gvt_gtt_type_t type)
 {
struct device *kdev = >gvt->dev_priv->drm.pdev->dev;
struct intel_vgpu_ppgtt_spt *spt = NULL;
@@ -836,27 +838,12 @@ static struct intel_vgpu_ppgtt_spt *ppgtt_alloc_spt(
spt->shadow_page.vaddr = page_address(spt->shadow_page.page);
spt->shadow_page.mfn = daddr >> I915_GTT_PAGE_SHIFT;
 
-   /*
-* Init guest_page.
-*/
-   spt->guest_page.type = type;
-   spt->guest_page.gfn = gfn;
-   spt->guest_page.pde_ips = guest_pde_ips;
-
-   ret = intel_vgpu_register_page_track(vgpu, spt->guest_page.gfn,
-   ppgtt_write_protection_handler, spt);
-   if (ret)
-   goto err_unmap_dma;
-
ret = radix_tree_insert(>gtt.spt_tree, spt->shadow_page.mfn, spt);
if (ret)
-   goto err_unreg_page_track;
+   goto err_unmap_dma;
 
-   trace_spt_alloc(vgpu->id, spt, type, spt->shadow_page.mfn, gfn);
return spt;
 
-err_unreg_page_track:
-   intel_vgpu_unregister_page_track(vgpu, spt->guest_page.gfn);
 err_unmap_dma:
dma_unmap_page(kdev, daddr, PAGE_SIZE, PCI_DMA_BIDIRECTIONAL);
 err_free_spt:
@@ -864,6 +851,37 @@ static struct intel_vgpu_ppgtt_spt *ppgtt_alloc_spt(
return ERR_PTR(ret);
 }
 
+/* Allocate shadow page table associated with specific gfn. */
+static struct intel_vgpu_ppgtt_spt *ppgtt_alloc_spt_gfn(
+   struct intel_vgpu *vgpu, intel_gvt_gtt_type_t type,
+   unsigned long gfn, bool guest_pde_ips)
+{
+   struct intel_vgpu_ppgtt_spt *spt;
+   int ret;
+
+   spt = ppgtt_alloc_spt(vgpu, type);
+   if (IS_ERR(spt))
+   return spt;
+
+   /*
+* Init guest_page.
+*/
+   ret = intel_vgpu_register_page_track(vgpu, gfn,
+   ppgtt_write_protection_handler, spt);
+   if (ret) {
+   ppgtt_free_spt(spt);
+   return ERR_PTR(ret);
+   }
+
+   spt->guest_page.type = type;
+   spt->guest_page.gfn = gfn;
+   spt->guest_page.pde_ips = guest_pde_ips;
+
+   trace_spt_alloc(vgpu->id, spt, type, spt->shadow_page.mfn, gfn);
+
+   return spt;
+}
+
 #define pt_entry_size_shift(spt) \
((spt)->vgpu->gvt->device_info.gtt_entry_size_shift)
 
@@ -1019,7 +1037,7 @@ static struct intel_vgpu_ppgtt_spt 
*ppgtt_populate_spt_by_guest_entry(
if (we->type == GTT_TYPE_PPGTT_PDE_ENTRY)
ips = vgpu_ips_enabled(vgpu) && ops->test_ips(we);
 
-   spt = ppgtt_alloc_spt(vgpu, type, ops->get_pfn(we), ips);
+   spt = ppgtt_alloc_spt_gfn(vgpu, type, ops->get_pfn(we), ips);
if (IS_ERR(spt)) {
ret = PTR_ERR(spt);
goto fail;
-- 
2.7.4

___
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx


[Intel-gfx] [PATCH v5 06/14] drm/i915/gvt: Add GTT clear_pse operation

2018-05-07 Thread changbin . du
From: Changbin Du <changbin...@intel.com>

Add clear_pse operation in case we need to split huge gtt into small pages.

v2: correct description.

Signed-off-by: Changbin Du <changbin...@intel.com>
---
 drivers/gpu/drm/i915/gvt/gtt.c | 19 +++
 drivers/gpu/drm/i915/gvt/gtt.h |  1 +
 2 files changed, 20 insertions(+)

diff --git a/drivers/gpu/drm/i915/gvt/gtt.c b/drivers/gpu/drm/i915/gvt/gtt.c
index f7bc8ff..0966ee7 100644
--- a/drivers/gpu/drm/i915/gvt/gtt.c
+++ b/drivers/gpu/drm/i915/gvt/gtt.c
@@ -390,6 +390,24 @@ static bool gen8_gtt_test_pse(struct intel_gvt_gtt_entry 
*e)
return !!(e->val64 & _PAGE_PSE);
 }
 
+static void gen8_gtt_clear_pse(struct intel_gvt_gtt_entry *e)
+{
+   if (gen8_gtt_test_pse(e)) {
+   switch (e->type) {
+   case GTT_TYPE_PPGTT_PTE_2M_ENTRY:
+   e->val64 &= ~_PAGE_PSE;
+   e->type = GTT_TYPE_PPGTT_PDE_ENTRY;
+   break;
+   case GTT_TYPE_PPGTT_PTE_1G_ENTRY:
+   e->type = GTT_TYPE_PPGTT_PDP_ENTRY;
+   e->val64 &= ~_PAGE_PSE;
+   break;
+   default:
+   WARN_ON(1);
+   }
+   }
+}
+
 static bool gen8_gtt_test_ips(struct intel_gvt_gtt_entry *e)
 {
if (GEM_WARN_ON(e->type != GTT_TYPE_PPGTT_PDE_ENTRY))
@@ -477,6 +495,7 @@ static struct intel_gvt_gtt_pte_ops gen8_gtt_pte_ops = {
.set_present = gtt_entry_set_present,
.test_present = gen8_gtt_test_present,
.test_pse = gen8_gtt_test_pse,
+   .clear_pse = gen8_gtt_clear_pse,
.clear_ips = gen8_gtt_clear_ips,
.test_ips = gen8_gtt_test_ips,
.clear_64k_splited = gen8_gtt_clear_64k_splited,
diff --git a/drivers/gpu/drm/i915/gvt/gtt.h b/drivers/gpu/drm/i915/gvt/gtt.h
index 162ef19..b7bf68c 100644
--- a/drivers/gpu/drm/i915/gvt/gtt.h
+++ b/drivers/gpu/drm/i915/gvt/gtt.h
@@ -63,6 +63,7 @@ struct intel_gvt_gtt_pte_ops {
void (*clear_present)(struct intel_gvt_gtt_entry *e);
void (*set_present)(struct intel_gvt_gtt_entry *e);
bool (*test_pse)(struct intel_gvt_gtt_entry *e);
+   void (*clear_pse)(struct intel_gvt_gtt_entry *e);
bool (*test_ips)(struct intel_gvt_gtt_entry *e);
void (*clear_ips)(struct intel_gvt_gtt_entry *e);
bool (*test_64k_splited)(struct intel_gvt_gtt_entry *e);
-- 
2.7.4

___
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx


[Intel-gfx] [PATCH v5 01/14] drm/i915/gvt: Add new 64K entry type

2018-05-07 Thread changbin . du
From: Changbin Du <changbin...@intel.com>

Add a new entry type GTT_TYPE_PPGTT_PTE_64K_ENTRY. 64K entry is very
different from 2M/1G entry. 64K entry is controlled by IPS bit in upper
PDE. To leverage the current logic, I take IPS bit as 'PSE' for PTE
level. Which means, 64K entries can also processed by get_pse_type().

v2: Make it bisectable.

Signed-off-by: Changbin Du <changbin...@intel.com>
---
 drivers/gpu/drm/i915/gvt/gtt.c | 26 ++
 drivers/gpu/drm/i915/gvt/gtt.h |  1 +
 2 files changed, 23 insertions(+), 4 deletions(-)

diff --git a/drivers/gpu/drm/i915/gvt/gtt.c b/drivers/gpu/drm/i915/gvt/gtt.c
index 78e55aa..1fcc64a 100644
--- a/drivers/gpu/drm/i915/gvt/gtt.c
+++ b/drivers/gpu/drm/i915/gvt/gtt.c
@@ -216,16 +216,22 @@ static struct gtt_type_table_entry gtt_type_table[] = {
GTT_TYPE_PPGTT_PDE_PT,
GTT_TYPE_PPGTT_PTE_PT,
GTT_TYPE_PPGTT_PTE_2M_ENTRY),
+   /* We take IPS bit as 'PSE' for PTE level. */
GTT_TYPE_TABLE_ENTRY(GTT_TYPE_PPGTT_PTE_PT,
GTT_TYPE_PPGTT_PTE_4K_ENTRY,
GTT_TYPE_PPGTT_PTE_PT,
GTT_TYPE_INVALID,
-   GTT_TYPE_INVALID),
+   GTT_TYPE_PPGTT_PTE_64K_ENTRY),
GTT_TYPE_TABLE_ENTRY(GTT_TYPE_PPGTT_PTE_4K_ENTRY,
GTT_TYPE_PPGTT_PTE_4K_ENTRY,
GTT_TYPE_PPGTT_PTE_PT,
GTT_TYPE_INVALID,
-   GTT_TYPE_INVALID),
+   GTT_TYPE_PPGTT_PTE_64K_ENTRY),
+   GTT_TYPE_TABLE_ENTRY(GTT_TYPE_PPGTT_PTE_64K_ENTRY,
+   GTT_TYPE_PPGTT_PTE_4K_ENTRY,
+   GTT_TYPE_PPGTT_PTE_PT,
+   GTT_TYPE_INVALID,
+   GTT_TYPE_PPGTT_PTE_64K_ENTRY),
GTT_TYPE_TABLE_ENTRY(GTT_TYPE_PPGTT_PTE_2M_ENTRY,
GTT_TYPE_PPGTT_PDE_ENTRY,
GTT_TYPE_PPGTT_PDE_PT,
@@ -339,6 +345,7 @@ static inline int gtt_set_entry64(void *pt,
 
 #define ADDR_1G_MASK   GENMASK_ULL(GTT_HAW - 1, 30)
 #define ADDR_2M_MASK   GENMASK_ULL(GTT_HAW - 1, 21)
+#define ADDR_64K_MASK  GENMASK_ULL(GTT_HAW - 1, 16)
 #define ADDR_4K_MASK   GENMASK_ULL(GTT_HAW - 1, 12)
 
 static unsigned long gen8_gtt_get_pfn(struct intel_gvt_gtt_entry *e)
@@ -349,6 +356,8 @@ static unsigned long gen8_gtt_get_pfn(struct 
intel_gvt_gtt_entry *e)
pfn = (e->val64 & ADDR_1G_MASK) >> PAGE_SHIFT;
else if (e->type == GTT_TYPE_PPGTT_PTE_2M_ENTRY)
pfn = (e->val64 & ADDR_2M_MASK) >> PAGE_SHIFT;
+   else if (e->type == GTT_TYPE_PPGTT_PTE_64K_ENTRY)
+   pfn = (e->val64 & ADDR_64K_MASK) >> PAGE_SHIFT;
else
pfn = (e->val64 & ADDR_4K_MASK) >> PAGE_SHIFT;
return pfn;
@@ -362,6 +371,9 @@ static void gen8_gtt_set_pfn(struct intel_gvt_gtt_entry *e, 
unsigned long pfn)
} else if (e->type == GTT_TYPE_PPGTT_PTE_2M_ENTRY) {
e->val64 &= ~ADDR_2M_MASK;
pfn &= (ADDR_2M_MASK >> PAGE_SHIFT);
+   } else if (e->type == GTT_TYPE_PPGTT_PTE_64K_ENTRY) {
+   e->val64 &= ~ADDR_64K_MASK;
+   pfn &= (ADDR_64K_MASK >> PAGE_SHIFT);
} else {
e->val64 &= ~ADDR_4K_MASK;
pfn &= (ADDR_4K_MASK >> PAGE_SHIFT);
@@ -380,6 +392,10 @@ static bool gen8_gtt_test_pse(struct intel_gvt_gtt_entry 
*e)
if (!(e->val64 & _PAGE_PSE))
return false;
 
+   /* We don't support 64K entry yet, will remove this later. */
+   if (get_pse_type(e->type) == GTT_TYPE_PPGTT_PTE_64K_ENTRY)
+   return false;
+
e->type = get_pse_type(e->type);
return true;
 }
@@ -871,9 +887,10 @@ static int ppgtt_invalidate_spt(struct 
intel_vgpu_ppgtt_spt *spt)
gvt_vdbg_mm("invalidate 4K entry\n");
ppgtt_invalidate_pte(spt, );
break;
+   case GTT_TYPE_PPGTT_PTE_64K_ENTRY:
case GTT_TYPE_PPGTT_PTE_2M_ENTRY:
case GTT_TYPE_PPGTT_PTE_1G_ENTRY:
-   WARN(1, "GVT doesn't support 2M/1GB page\n");
+   WARN(1, "GVT doesn't support 64K/2M/1GB page\n");
continue;
case GTT_TYPE_PPGTT_PML4_ENTRY:
case GTT_TYPE_PPGTT_PDP_ENTRY:
@@ -970,9 +987,10 @@ static int ppgtt_populate_shadow_entry(struct intel_vgpu 
*vgpu,
case GTT_TYPE_PPGTT_PTE_4K_ENTRY:
gvt_vdbg_mm("shadow 4K gtt entry\n");
break;
+   case GTT_TYPE_PPGTT_PTE_64K_ENTRY:
case GTT_TYPE_PPGTT_PTE_2M_ENTRY:
case GTT_TYPE_PPGTT_PTE_1G_ENTRY:
-   gvt_vgpu_err("GVT doesn't 

[Intel-gfx] [PATCH v5 04/14] drm/i915/gvt: Detect 64K gtt entry by IPS bit of PDE

2018-05-07 Thread changbin . du
From: Changbin Du <changbin...@intel.com>

This change help us detect the real entry type per PSE and IPS setting.
For 64K entry, we also need to check reg GEN8_GAMW_ECO_DEV_RW_IA.

Signed-off-by: Changbin Du <changbin...@intel.com>
---
 drivers/gpu/drm/i915/gvt/gtt.c | 68 +-
 drivers/gpu/drm/i915/gvt/gtt.h |  2 ++
 2 files changed, 49 insertions(+), 21 deletions(-)

diff --git a/drivers/gpu/drm/i915/gvt/gtt.c b/drivers/gpu/drm/i915/gvt/gtt.c
index cd2a227..7a80518 100644
--- a/drivers/gpu/drm/i915/gvt/gtt.c
+++ b/drivers/gpu/drm/i915/gvt/gtt.c
@@ -384,20 +384,7 @@ static void gen8_gtt_set_pfn(struct intel_gvt_gtt_entry 
*e, unsigned long pfn)
 
 static bool gen8_gtt_test_pse(struct intel_gvt_gtt_entry *e)
 {
-   /* Entry doesn't have PSE bit. */
-   if (get_pse_type(e->type) == GTT_TYPE_INVALID)
-   return false;
-
-   e->type = get_entry_type(e->type);
-   if (!(e->val64 & _PAGE_PSE))
-   return false;
-
-   /* We don't support 64K entry yet, will remove this later. */
-   if (get_pse_type(e->type) == GTT_TYPE_PPGTT_PTE_64K_ENTRY)
-   return false;
-
-   e->type = get_pse_type(e->type);
-   return true;
+   return !!(e->val64 & _PAGE_PSE);
 }
 
 static bool gen8_gtt_test_ips(struct intel_gvt_gtt_entry *e)
@@ -487,6 +474,27 @@ static struct intel_gvt_gtt_gma_ops gen8_gtt_gma_ops = {
.gma_to_pml4_index = gen8_gma_to_pml4_index,
 };
 
+/* Update entry type per pse and ips bit. */
+static void update_entry_type_for_real(struct intel_gvt_gtt_pte_ops *pte_ops,
+   struct intel_gvt_gtt_entry *entry, bool ips)
+{
+   switch (entry->type) {
+   case GTT_TYPE_PPGTT_PDE_ENTRY:
+   case GTT_TYPE_PPGTT_PDP_ENTRY:
+   if (pte_ops->test_pse(entry))
+   entry->type = get_pse_type(entry->type);
+   break;
+   case GTT_TYPE_PPGTT_PTE_4K_ENTRY:
+   if (ips)
+   entry->type = get_pse_type(entry->type);
+   break;
+   default:
+   GEM_BUG_ON(!gtt_type_is_entry(entry->type));
+   }
+
+   GEM_BUG_ON(entry->type == GTT_TYPE_INVALID);
+}
+
 /*
  * MM helpers.
  */
@@ -502,8 +510,7 @@ static void _ppgtt_get_root_entry(struct intel_vgpu_mm *mm,
pte_ops->get_entry(guest ? mm->ppgtt_mm.guest_pdps :
   mm->ppgtt_mm.shadow_pdps,
   entry, index, false, 0, mm->vgpu);
-
-   pte_ops->test_pse(entry);
+   update_entry_type_for_real(pte_ops, entry, false);
 }
 
 static inline void ppgtt_get_guest_root_entry(struct intel_vgpu_mm *mm,
@@ -608,7 +615,8 @@ static inline int ppgtt_spt_get_entry(
if (ret)
return ret;
 
-   ops->test_pse(e);
+   update_entry_type_for_real(ops, e, guest ?
+  spt->guest_page.pde_ips : false);
 
gvt_vdbg_mm("read ppgtt entry, spt type %d, entry type %d, index %lu, 
value %llx\n",
type, e->type, index, e->val64);
@@ -752,7 +760,8 @@ static inline struct intel_vgpu_ppgtt_spt 
*intel_vgpu_find_spt_by_mfn(
 static int reclaim_one_ppgtt_mm(struct intel_gvt *gvt);
 
 static struct intel_vgpu_ppgtt_spt *ppgtt_alloc_spt(
-   struct intel_vgpu *vgpu, int type, unsigned long gfn)
+   struct intel_vgpu *vgpu, int type, unsigned long gfn,
+   bool guest_pde_ips)
 {
struct device *kdev = >gvt->dev_priv->drm.pdev->dev;
struct intel_vgpu_ppgtt_spt *spt = NULL;
@@ -792,6 +801,7 @@ static struct intel_vgpu_ppgtt_spt *ppgtt_alloc_spt(
 */
spt->guest_page.type = type;
spt->guest_page.gfn = gfn;
+   spt->guest_page.pde_ips = guest_pde_ips;
 
ret = intel_vgpu_register_page_track(vgpu, spt->guest_page.gfn,
ppgtt_write_protection_handler, spt);
@@ -934,6 +944,20 @@ static int ppgtt_invalidate_spt(struct 
intel_vgpu_ppgtt_spt *spt)
return ret;
 }
 
+static bool vgpu_ips_enabled(struct intel_vgpu *vgpu)
+{
+   if (INTEL_GEN(vgpu->gvt->dev_priv) == 9) {
+   u32 ips = vgpu_vreg_t(vgpu, GEN8_GAMW_ECO_DEV_RW_IA) &
+   GAMW_ECO_ENABLE_64K_IPS_FIELD;
+
+   return ips == GAMW_ECO_ENABLE_64K_IPS_FIELD;
+   } else if (INTEL_GEN(vgpu->gvt->dev_priv) >= 10) {
+   /* 64K paging only controlled by IPS bit in PTE now. */
+   return true;
+   } else
+   return false;
+}
+
 static int ppgtt_populate_spt(struct intel_vgpu_ppgtt_spt *spt);
 
 static struct intel_vgpu_ppgtt_spt *ppgtt_populate_spt_by_guest_entry(
@@ -941,6 +965,7 @@ static struct intel_vgpu_ppgtt_spt 
*ppgtt_populate_spt_by_guest_entry(
 {
struct intel_gvt_gtt_pte_ops *ops = vgpu->gvt->gtt.pte_ops;

[Intel-gfx] [PATCH v5 03/14] drm/i915/gvt: Handle MMIO GEN8_GAMW_ECO_DEV_RW_IA for 64K GTT

2018-05-07 Thread changbin . du
From: Changbin Du <changbin...@intel.com>

The register RENDER_HWS_PGA_GEN7 is renamed to GEN8_GAMW_ECO_DEV_RW_IA
from GEN8 which can control IPS enabling.

v2: IPS of all engines must be enabled together for gen9.

Signed-off-by: Changbin Du <changbin...@intel.com>
---
 drivers/gpu/drm/i915/gvt/handlers.c | 29 -
 1 file changed, 28 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/i915/gvt/handlers.c 
b/drivers/gpu/drm/i915/gvt/handlers.c
index b77adcc..a3e439b 100644
--- a/drivers/gpu/drm/i915/gvt/handlers.c
+++ b/drivers/gpu/drm/i915/gvt/handlers.c
@@ -211,6 +211,31 @@ static int sanitize_fence_mmio_access(struct intel_vgpu 
*vgpu,
return 0;
 }
 
+static int gamw_echo_dev_rw_ia_write(struct intel_vgpu *vgpu,
+   unsigned int offset, void *p_data, unsigned int bytes)
+{
+   u32 ips = (*(u32 *)p_data) & GAMW_ECO_ENABLE_64K_IPS_FIELD;
+
+   if (INTEL_GEN(vgpu->gvt->dev_priv) == 9) {
+   if (ips == GAMW_ECO_ENABLE_64K_IPS_FIELD)
+   gvt_dbg_core("vgpu%d: ips enabled\n", vgpu->id);
+   else if (!ips)
+   gvt_dbg_core("vgpu%d: ips disabled\n", vgpu->id);
+   else {
+   /* All engines must be enabled together for vGPU,
+* since we don't know which engine the ppgtt will
+* bind to when shadowing.
+*/
+   gvt_vgpu_err("Unsupported IPS setting %x, cannot enable 
64K gtt.\n",
+ips);
+   return -EINVAL;
+   }
+   }
+
+   write_vreg(vgpu, offset, p_data, bytes);
+   return 0;
+}
+
 static int fence_mmio_read(struct intel_vgpu *vgpu, unsigned int off,
void *p_data, unsigned int bytes)
 {
@@ -1654,7 +1679,9 @@ static int init_generic_mmio_info(struct intel_gvt *gvt)
 
MMIO_RING_DFH(RING_HWSTAM, D_ALL, F_CMD_ACCESS, NULL, NULL);
 
-   MMIO_GM_RDR(RENDER_HWS_PGA_GEN7, D_ALL, NULL, NULL);
+   MMIO_DH(GEN8_GAMW_ECO_DEV_RW_IA, D_BDW_PLUS, NULL,
+   gamw_echo_dev_rw_ia_write);
+
MMIO_GM_RDR(BSD_HWS_PGA_GEN7, D_ALL, NULL, NULL);
MMIO_GM_RDR(BLT_HWS_PGA_GEN7, D_ALL, NULL, NULL);
MMIO_GM_RDR(VEBOX_HWS_PGA_GEN7, D_ALL, NULL, NULL);
-- 
2.7.4

___
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx


[Intel-gfx] [PATCH v5 02/14] drm/i915/gvt: Add PTE IPS bit operations

2018-05-07 Thread changbin . du
From: Changbin Du <changbin...@intel.com>

Add three IPS operation functions to test/set/clear IPS in PDE.

Signed-off-by: Changbin Du <changbin...@intel.com>
---
 drivers/gpu/drm/i915/gvt/gtt.c | 18 ++
 drivers/gpu/drm/i915/gvt/gtt.h |  2 ++
 2 files changed, 20 insertions(+)

diff --git a/drivers/gpu/drm/i915/gvt/gtt.c b/drivers/gpu/drm/i915/gvt/gtt.c
index 1fcc64a..cd2a227 100644
--- a/drivers/gpu/drm/i915/gvt/gtt.c
+++ b/drivers/gpu/drm/i915/gvt/gtt.c
@@ -400,6 +400,22 @@ static bool gen8_gtt_test_pse(struct intel_gvt_gtt_entry 
*e)
return true;
 }
 
+static bool gen8_gtt_test_ips(struct intel_gvt_gtt_entry *e)
+{
+   if (GEM_WARN_ON(e->type != GTT_TYPE_PPGTT_PDE_ENTRY))
+   return false;
+
+   return !!(e->val64 & GEN8_PDE_IPS_64K);
+}
+
+static void gen8_gtt_clear_ips(struct intel_gvt_gtt_entry *e)
+{
+   if (GEM_WARN_ON(e->type != GTT_TYPE_PPGTT_PDE_ENTRY))
+   return;
+
+   e->val64 &= ~GEN8_PDE_IPS_64K;
+}
+
 static bool gen8_gtt_test_present(struct intel_gvt_gtt_entry *e)
 {
/*
@@ -456,6 +472,8 @@ static struct intel_gvt_gtt_pte_ops gen8_gtt_pte_ops = {
.set_present = gtt_entry_set_present,
.test_present = gen8_gtt_test_present,
.test_pse = gen8_gtt_test_pse,
+   .clear_ips = gen8_gtt_clear_ips,
+   .test_ips = gen8_gtt_test_ips,
.get_pfn = gen8_gtt_get_pfn,
.set_pfn = gen8_gtt_set_pfn,
 };
diff --git a/drivers/gpu/drm/i915/gvt/gtt.h b/drivers/gpu/drm/i915/gvt/gtt.h
index 6063081..9257b74 100644
--- a/drivers/gpu/drm/i915/gvt/gtt.h
+++ b/drivers/gpu/drm/i915/gvt/gtt.h
@@ -63,6 +63,8 @@ struct intel_gvt_gtt_pte_ops {
void (*clear_present)(struct intel_gvt_gtt_entry *e);
void (*set_present)(struct intel_gvt_gtt_entry *e);
bool (*test_pse)(struct intel_gvt_gtt_entry *e);
+   bool (*test_ips)(struct intel_gvt_gtt_entry *e);
+   void (*clear_ips)(struct intel_gvt_gtt_entry *e);
void (*set_pfn)(struct intel_gvt_gtt_entry *e, unsigned long pfn);
unsigned long (*get_pfn)(struct intel_gvt_gtt_entry *e);
 };
-- 
2.7.4

___
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx


[Intel-gfx] [PATCH v5 00/14] drm/i915/gvt: Add huge gtt shadowing

2018-05-07 Thread changbin . du
From: Changbin Du <changbin...@intel.com>

Add huge gtt shadowing for GVT. This will alow huge gtt feature turned on for 
vGPU.

v5:
  o IPS of all engines must be enabled together for gen9.
  o Coding style improvment.
v4:
  o Make first patch bisectable.
v3:
  o rebase.
v2:
  o fix comments from zhenyu.
  o rebase.

Changbin Du (14):
  drm/i915/gvt: Add new 64K entry type
  drm/i915/gvt: Add PTE IPS bit operations
  drm/i915/gvt: Handle MMIO GEN8_GAMW_ECO_DEV_RW_IA for 64K GTT
  drm/i915/gvt: Detect 64K gtt entry by IPS bit of PDE
  drm/i915/gvt: Add software PTE flag to mark special 64K splited entry
  drm/i915/gvt: Add GTT clear_pse operation
  drm/i915/gvt: Split ppgtt_alloc_spt into two parts
  drm/i915/gvt: Make PTE iterator 64K entry aware
  drm/i915/gvt: Add 64K huge gtt support
  drm/i915/kvmgt: Support setting dma map for huge pages
  drm/i915/gvt: Add 2M huge gtt support
  drm/i915/gvt: Handle special sequence on PDE IPS bit
  drm/i915/gvt: Fix error handling in ppgtt_populate_spt_by_guest_entry
  drm/i915: Enable platform support for vGPU huge gtt pages

 drivers/gpu/drm/i915/gvt/gtt.c   | 421 ++-
 drivers/gpu/drm/i915/gvt/gtt.h   |   9 +
 drivers/gpu/drm/i915/gvt/handlers.c  |  29 ++-
 drivers/gpu/drm/i915/gvt/hypercall.h |   2 +-
 drivers/gpu/drm/i915/gvt/kvmgt.c | 130 ---
 drivers/gpu/drm/i915/gvt/mpt.h   |   7 +-
 drivers/gpu/drm/i915/gvt/vgpu.c  |   1 +
 drivers/gpu/drm/i915/i915_gem.c  |   8 +-
 drivers/gpu/drm/i915/i915_pvinfo.h   |   1 +
 drivers/gpu/drm/i915/i915_vgpu.h |   6 +
 10 files changed, 509 insertions(+), 105 deletions(-)

-- 
2.7.4

___
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx


[Intel-gfx] [PATCH v5 09/14] drm/i915/gvt: Add 64K huge gtt support

2018-05-07 Thread changbin . du
From: Changbin Du <changbin...@intel.com>

Finally, this add the first huge gtt support for GVTg - 64K pages. Since
64K page and 4K page cannot be mixed on the same page table, so we always
split a 64K entry into small 4K page. And when unshadow guest 64K entry,
we need ensure all the shadowed entries in shadow page table also get
cleared.

For page table which has 64K gtt entry, only PTE#0, PTE#16, PTE#32, ...
PTE#496 are used. Unused PTEs update should be ignored.

Signed-off-by: Changbin Du <changbin...@intel.com>
---
 drivers/gpu/drm/i915/gvt/gtt.c | 86 +++---
 1 file changed, 80 insertions(+), 6 deletions(-)

diff --git a/drivers/gpu/drm/i915/gvt/gtt.c b/drivers/gpu/drm/i915/gvt/gtt.c
index 30b15e4..2f13464 100644
--- a/drivers/gpu/drm/i915/gvt/gtt.c
+++ b/drivers/gpu/drm/i915/gvt/gtt.c
@@ -978,9 +978,12 @@ static int ppgtt_invalidate_spt(struct 
intel_vgpu_ppgtt_spt *spt)
ppgtt_invalidate_pte(spt, );
break;
case GTT_TYPE_PPGTT_PTE_64K_ENTRY:
+   /* We don't setup 64K shadow entry so far. */
+   WARN(1, "suspicious 64K gtt entry\n");
+   continue;
case GTT_TYPE_PPGTT_PTE_2M_ENTRY:
case GTT_TYPE_PPGTT_PTE_1G_ENTRY:
-   WARN(1, "GVT doesn't support 64K/2M/1GB page\n");
+   WARN(1, "GVT doesn't support 2M/1GB page\n");
continue;
case GTT_TYPE_PPGTT_PML4_ENTRY:
case GTT_TYPE_PPGTT_PDP_ENTRY:
@@ -1073,9 +1076,44 @@ static inline void ppgtt_generate_shadow_entry(struct 
intel_gvt_gtt_entry *se,
se->type = ge->type;
se->val64 = ge->val64;
 
+   /* Because we always split 64KB pages, so clear IPS in shadow PDE. */
+   if (se->type == GTT_TYPE_PPGTT_PDE_ENTRY)
+   ops->clear_ips(se);
+
ops->set_pfn(se, s->shadow_page.mfn);
 }
 
+static int split_64KB_gtt_entry(struct intel_vgpu *vgpu,
+   struct intel_vgpu_ppgtt_spt *spt, unsigned long index,
+   struct intel_gvt_gtt_entry *se)
+{
+   struct intel_gvt_gtt_pte_ops *ops = vgpu->gvt->gtt.pte_ops;
+   struct intel_gvt_gtt_entry entry = *se;
+   unsigned long start_gfn;
+   dma_addr_t dma_addr;
+   int i, ret;
+
+   gvt_vdbg_mm("Split 64K gtt entry, index %lu\n", index);
+
+   GEM_BUG_ON(index % GTT_64K_PTE_STRIDE);
+
+   start_gfn = ops->get_pfn(se);
+
+   entry.type = GTT_TYPE_PPGTT_PTE_4K_ENTRY;
+   ops->set_64k_splited();
+
+   for (i = 0; i < GTT_64K_PTE_STRIDE; i++) {
+   ret = intel_gvt_hypervisor_dma_map_guest_page(vgpu,
+   start_gfn + i, _addr);
+   if (ret)
+   return ret;
+
+   ops->set_pfn(, dma_addr >> PAGE_SHIFT);
+   ppgtt_set_shadow_entry(spt, , index + i);
+   }
+   return 0;
+}
+
 static int ppgtt_populate_shadow_entry(struct intel_vgpu *vgpu,
struct intel_vgpu_ppgtt_spt *spt, unsigned long index,
struct intel_gvt_gtt_entry *ge)
@@ -1096,9 +1134,16 @@ static int ppgtt_populate_shadow_entry(struct intel_vgpu 
*vgpu,
gvt_vdbg_mm("shadow 4K gtt entry\n");
break;
case GTT_TYPE_PPGTT_PTE_64K_ENTRY:
+   gvt_vdbg_mm("shadow 64K gtt entry\n");
+   /*
+* The layout of 64K page is special, the page size is
+* controlled by uper PDE. To be simple, we always split
+* 64K page to smaller 4K pages in shadow PT.
+*/
+   return split_64KB_gtt_entry(vgpu, spt, index, );
case GTT_TYPE_PPGTT_PTE_2M_ENTRY:
case GTT_TYPE_PPGTT_PTE_1G_ENTRY:
-   gvt_vgpu_err("GVT doesn't support 64K/2M/1GB entry\n");
+   gvt_vgpu_err("GVT doesn't support 2M/1GB entry\n");
return -EINVAL;
default:
GEM_BUG_ON(1);
@@ -1188,8 +1233,12 @@ static int ppgtt_handle_guest_entry_removal(struct 
intel_vgpu_ppgtt_spt *spt,
ret = ppgtt_invalidate_spt(s);
if (ret)
goto fail;
-   } else
+   } else {
+   /* We don't setup 64K shadow entry so far. */
+   WARN(se->type == GTT_TYPE_PPGTT_PTE_64K_ENTRY,
+"suspicious 64K entry\n");
ppgtt_invalidate_pte(spt, se);
+   }
 
return 0;
 fail:
@@ -1412,7 +1461,7 @@ static int ppgtt_handle_guest_write_page_table(
struct intel_gvt_gtt_pte_ops *ops = vgpu->gvt->gtt.pte_ops;
struct intel_gvt_gtt_entry old_se;
int new_present;
-   int ret;
+   int i, ret;
 
new_present = ops->test_present(we);
 
@@ -

[Intel-gfx] [PATCH v2] drm/i915: Do not enable movntdqa optimization in hypervisor guest

2017-12-24 Thread changbin . du
From: Changbin Du <changbin...@intel.com>

Our QA reported a problem caused by movntdqa instructions. Currently,
the KVM hypervisor doesn't support VEX-prefix instructions emulation.
If users passthrough a GPU to guest with vfio option 'x-no-mmap=on',
then all access to the BARs will be trapped and emulated. The KVM
hypervisor would raise an inertal error to qemu which cause the guest
killed. (Since 'movntdqa' ins is not supported.)

This patch try not to enable movntdqa optimization if the driver is
running in hypervisor guest.

v2: update comment.

Signed-off-by: Changbin Du <changbin...@intel.com>
Reviewed-by: Chris Wilson <ch...@chris-wilson.co.uk>
---
 drivers/gpu/drm/i915/i915_memcpy.c | 7 ++-
 1 file changed, 6 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/i915/i915_memcpy.c 
b/drivers/gpu/drm/i915/i915_memcpy.c
index 49a0794..79f8ec7 100644
--- a/drivers/gpu/drm/i915/i915_memcpy.c
+++ b/drivers/gpu/drm/i915/i915_memcpy.c
@@ -96,6 +96,11 @@ bool i915_memcpy_from_wc(void *dst, const void *src, 
unsigned long len)
 
 void i915_memcpy_init_early(struct drm_i915_private *dev_priv)
 {
-   if (static_cpu_has(X86_FEATURE_XMM4_1))
+   /*
+* Some hypervisors (e.g. KVM) don't support VEX-prefix instructions
+* emulation. So don't enable movntdqa in hypervisor guest.
+*/
+   if (static_cpu_has(X86_FEATURE_XMM4_1) &&
+   !boot_cpu_has(X86_FEATURE_HYPERVISOR))
static_branch_enable(_movntdqa);
 }
-- 
2.7.4

___
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx


[Intel-gfx] [PATCH] drm/i915: Do not enable movntdqa optimization in hypervisor guest

2017-12-21 Thread changbin . du
From: Changbin Du <changbin...@intel.com>

Our QA reported a problem caused by movntdqa instructions. Currently,
the KVM hypervisor doesn't support VEX-prefix instructions emulation.
If users passthrough a GPU to guest with vfio option 'x-no-mmap=on',
then all access to the BARs will be trapped and emulated. The KVM
hypervisor would raise an inertal error to qemu which cause the guest
killed. (Since 'movntdqa' ins is not supported.)

This patch try not to enable movntdqa optimization if the driver is
running in hypervisor guest.

Signed-off-by: Changbin Du <changbin...@intel.com>
---
 drivers/gpu/drm/i915/i915_memcpy.c | 7 ++-
 1 file changed, 6 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/i915/i915_memcpy.c 
b/drivers/gpu/drm/i915/i915_memcpy.c
index 49a0794..8921f40 100644
--- a/drivers/gpu/drm/i915/i915_memcpy.c
+++ b/drivers/gpu/drm/i915/i915_memcpy.c
@@ -96,6 +96,11 @@ bool i915_memcpy_from_wc(void *dst, const void *src, 
unsigned long len)
 
 void i915_memcpy_init_early(struct drm_i915_private *dev_priv)
 {
-   if (static_cpu_has(X86_FEATURE_XMM4_1))
+   /**
+* Some hypervisors (e.g. KVM) don't support VEX-prefix instructions
+* emulation. So don't enable movntdqa in hypervisor guest.
+*/
+   if (static_cpu_has(X86_FEATURE_XMM4_1) &&
+   !boot_cpu_has(X86_FEATURE_HYPERVISOR))
static_branch_enable(_movntdqa);
 }
-- 
2.7.4

___
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx


[Intel-gfx] [PATCH i-g-t] overlay: fix debugfs path when debugfs mounted on path '/debug'

2017-12-06 Thread changbin . du
From: Changbin Du <changbin...@intel.com>

It mistakenly set debugfs root path to "/debug/dri", so correct it.

Signed-off-by: Changbin Du <changbin...@intel.com>
---
 overlay/debugfs.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/overlay/debugfs.c b/overlay/debugfs.c
index 9f3e5cc..5516949 100644
--- a/overlay/debugfs.c
+++ b/overlay/debugfs.c
@@ -40,7 +40,7 @@ int debugfs_init(void)
int n;
 
if (stat("/debug/dri", ) == 0) {
-   path = "/debug/dri";
+   path = "/debug";
goto find_minor;
}
 
-- 
2.7.4

___
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx


[Intel-gfx] [PATCH] Documentation/i915: Add "User command execution" to doc-tree

2017-10-16 Thread changbin . du
From: Changbin Du <changbin...@intel.com>

Just found this is a useful introduction about User command
execution, so add it to doc-tree.

Signed-off-by: Changbin Du <changbin...@intel.com>
---
 Documentation/gpu/i915.rst | 6 ++
 1 file changed, 6 insertions(+)

diff --git a/Documentation/gpu/i915.rst b/Documentation/gpu/i915.rst
index 2e7ee03..c339921 100644
--- a/Documentation/gpu/i915.rst
+++ b/Documentation/gpu/i915.rst
@@ -276,6 +276,12 @@ Logical Rings, Logical Ring Contexts and Execlists
 .. kernel-doc:: drivers/gpu/drm/i915/intel_lrc.c
:internal:
 
+User command execution
+--
+
+.. kernel-doc:: drivers/gpu/drm/i915/i915_gem_execbuffer.c
+   :doc: User command execution
+
 Global GTT views
 
 
-- 
2.7.4

___
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx


[Intel-gfx] [PATCH v3] drm/i915: Add interface to reserve fence registers for vGPU

2017-09-04 Thread changbin . du
From: Changbin Du <changbin...@intel.com>

In the past, vGPU alloc fence registers by walking through mm.fence_list
to find fence which pin_count = 0 and vma is empty. vGPU may not find
enough fence registers this way. Because a fence can be bind to vma even
though it is not in using. We have found such failure many times these
days.

An option to resolve this issue is that we can force-remove fence from
vma in this case.

This patch added two new api to the fence management code:
 - i915_reserve_fence() will try to find a free fence from fence_list
   and force-remove vma if need.
 - i915_unreserve_fence() reclaim a reserved fence after vGPU has
   finished.

With this change, the fence management is more clear to work with vGPU.
GVTg do not need remove fence from fence_list in private.

v3: (Chris)
  - Add struct_mutex lock assertion.
  - Only count for unpinned fence.

v2: (Chris)
  - Rename the new api for symmetry.
  - Add safeguard to ensure at least 1 fence remained for host display.

Signed-off-by: Changbin Du <changbin...@intel.com>
Reviewed-by: Chris Wilson <ch...@chris-wilson.co.uk>
---
 drivers/gpu/drm/i915/gvt/aperture_gm.c| 26 +++-
 drivers/gpu/drm/i915/i915_drv.h   |  3 ++
 drivers/gpu/drm/i915/i915_gem_fence_reg.c | 49 +++
 3 files changed, 63 insertions(+), 15 deletions(-)

diff --git a/drivers/gpu/drm/i915/gvt/aperture_gm.c 
b/drivers/gpu/drm/i915/gvt/aperture_gm.c
index ca3d192..7c9ec4f 100644
--- a/drivers/gpu/drm/i915/gvt/aperture_gm.c
+++ b/drivers/gpu/drm/i915/gvt/aperture_gm.c
@@ -173,8 +173,8 @@ static void free_vgpu_fence(struct intel_vgpu *vgpu)
_clear_vgpu_fence(vgpu);
for (i = 0; i < vgpu_fence_sz(vgpu); i++) {
reg = vgpu->fence.regs[i];
-   list_add_tail(>link,
- _priv->mm.fence_list);
+   i915_unreserve_fence(reg);
+   vgpu->fence.regs[i] = NULL;
}
mutex_unlock(_priv->drm.struct_mutex);
 
@@ -187,24 +187,19 @@ static int alloc_vgpu_fence(struct intel_vgpu *vgpu)
struct drm_i915_private *dev_priv = gvt->dev_priv;
struct drm_i915_fence_reg *reg;
int i;
-   struct list_head *pos, *q;
 
intel_runtime_pm_get(dev_priv);
 
/* Request fences from host */
mutex_lock(_priv->drm.struct_mutex);
-   i = 0;
-   list_for_each_safe(pos, q, _priv->mm.fence_list) {
-   reg = list_entry(pos, struct drm_i915_fence_reg, link);
-   if (reg->pin_count || reg->vma)
-   continue;
-   list_del(pos);
+
+   for (i = 0; i < vgpu_fence_sz(vgpu); i++) {
+   reg = i915_reserve_fence(dev_priv);
+   if (IS_ERR(reg))
+   goto out_free_fence;
+
vgpu->fence.regs[i] = reg;
-   if (++i == vgpu_fence_sz(vgpu))
-   break;
}
-   if (i != vgpu_fence_sz(vgpu))
-   goto out_free_fence;
 
_clear_vgpu_fence(vgpu);
 
@@ -212,13 +207,14 @@ static int alloc_vgpu_fence(struct intel_vgpu *vgpu)
intel_runtime_pm_put(dev_priv);
return 0;
 out_free_fence:
+   gvt_vgpu_err("Failed to alloc fences\n");
/* Return fences to host, if fail */
for (i = 0; i < vgpu_fence_sz(vgpu); i++) {
reg = vgpu->fence.regs[i];
if (!reg)
continue;
-   list_add_tail(>link,
- _priv->mm.fence_list);
+   i915_unreserve_fence(reg);
+   vgpu->fence.regs[i] = NULL;
}
mutex_unlock(_priv->drm.struct_mutex);
intel_runtime_pm_put(dev_priv);
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index 064bf0f..7c35d57 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -3673,6 +3673,9 @@ i915_vm_to_ppgtt(struct i915_address_space *vm)
 /* i915_gem_fence_reg.c */
 int __must_check i915_vma_get_fence(struct i915_vma *vma);
 int __must_check i915_vma_put_fence(struct i915_vma *vma);
+struct drm_i915_fence_reg *
+i915_reserve_fence(struct drm_i915_private *dev_priv);
+void i915_unreserve_fence(struct drm_i915_fence_reg *fence);
 
 void i915_gem_revoke_fences(struct drm_i915_private *dev_priv);
 void i915_gem_restore_fences(struct drm_i915_private *dev_priv);
diff --git a/drivers/gpu/drm/i915/i915_gem_fence_reg.c 
b/drivers/gpu/drm/i915/i915_gem_fence_reg.c
index 5fe2cd8..dc39758 100644
--- a/drivers/gpu/drm/i915/i915_gem_fence_reg.c
+++ b/drivers/gpu/drm/i915/i915_gem_fence_reg.c
@@ -360,6 +360,55 @@ i915_vma_get_fence(struct i915_vma *vma)
 }
 
 /**
+ * i915_reserve_fence - Reserve a fence for vGPU
+ * @dev_priv: i915 device private
+ *
+ * This function walks the fence regs looking for a free one and remove
+ * it from the fen

[Intel-gfx] [PATCH v2] drm/i915: Add interface to reserve fence registers for vGPU

2017-09-01 Thread changbin . du
From: Changbin Du <changbin...@intel.com>

In the past, vGPU alloc fence registers by walking through mm.fence_list
to find fence which pin_count = 0 and vma is empty. vGPU may not find
enough fence registers this way. Because a fence can be bind to vma even
though it is not in using. We have found such failure many times these
days.

An option to resolve this issue is that we can force-remove fence from
vma in this case.

This patch added two new api to the fence management code:
 - i915_reserve_fence() will try to find a free fence from fence_list
   and force-remove vma if need.
 - i915_unreserve_fence() reclaim a reserved fence after vGPU has
   finished.

With this change, the fence management is more clear to work with vGPU.
GVTg do not need remove fence from fence_list in private.

v2: (Chris)
  - Rename the new api for symmetry.
  - Add safeguard to ensure at least 1 fence remained for host display.

Signed-off-by: Changbin Du <changbin...@intel.com>
---
 drivers/gpu/drm/i915/gvt/aperture_gm.c| 26 --
 drivers/gpu/drm/i915/i915_drv.h   |  3 +++
 drivers/gpu/drm/i915/i915_gem_fence_reg.c | 44 +++
 3 files changed, 58 insertions(+), 15 deletions(-)

diff --git a/drivers/gpu/drm/i915/gvt/aperture_gm.c 
b/drivers/gpu/drm/i915/gvt/aperture_gm.c
index ca3d192..7c9ec4f 100644
--- a/drivers/gpu/drm/i915/gvt/aperture_gm.c
+++ b/drivers/gpu/drm/i915/gvt/aperture_gm.c
@@ -173,8 +173,8 @@ static void free_vgpu_fence(struct intel_vgpu *vgpu)
_clear_vgpu_fence(vgpu);
for (i = 0; i < vgpu_fence_sz(vgpu); i++) {
reg = vgpu->fence.regs[i];
-   list_add_tail(>link,
- _priv->mm.fence_list);
+   i915_unreserve_fence(reg);
+   vgpu->fence.regs[i] = NULL;
}
mutex_unlock(_priv->drm.struct_mutex);
 
@@ -187,24 +187,19 @@ static int alloc_vgpu_fence(struct intel_vgpu *vgpu)
struct drm_i915_private *dev_priv = gvt->dev_priv;
struct drm_i915_fence_reg *reg;
int i;
-   struct list_head *pos, *q;
 
intel_runtime_pm_get(dev_priv);
 
/* Request fences from host */
mutex_lock(_priv->drm.struct_mutex);
-   i = 0;
-   list_for_each_safe(pos, q, _priv->mm.fence_list) {
-   reg = list_entry(pos, struct drm_i915_fence_reg, link);
-   if (reg->pin_count || reg->vma)
-   continue;
-   list_del(pos);
+
+   for (i = 0; i < vgpu_fence_sz(vgpu); i++) {
+   reg = i915_reserve_fence(dev_priv);
+   if (IS_ERR(reg))
+   goto out_free_fence;
+
vgpu->fence.regs[i] = reg;
-   if (++i == vgpu_fence_sz(vgpu))
-   break;
}
-   if (i != vgpu_fence_sz(vgpu))
-   goto out_free_fence;
 
_clear_vgpu_fence(vgpu);
 
@@ -212,13 +207,14 @@ static int alloc_vgpu_fence(struct intel_vgpu *vgpu)
intel_runtime_pm_put(dev_priv);
return 0;
 out_free_fence:
+   gvt_vgpu_err("Failed to alloc fences\n");
/* Return fences to host, if fail */
for (i = 0; i < vgpu_fence_sz(vgpu); i++) {
reg = vgpu->fence.regs[i];
if (!reg)
continue;
-   list_add_tail(>link,
- _priv->mm.fence_list);
+   i915_unreserve_fence(reg);
+   vgpu->fence.regs[i] = NULL;
}
mutex_unlock(_priv->drm.struct_mutex);
intel_runtime_pm_put(dev_priv);
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index 7587ef5..763a720 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -3650,6 +3650,9 @@ i915_vm_to_ppgtt(struct i915_address_space *vm)
 /* i915_gem_fence_reg.c */
 int __must_check i915_vma_get_fence(struct i915_vma *vma);
 int __must_check i915_vma_put_fence(struct i915_vma *vma);
+struct drm_i915_fence_reg *
+i915_reserve_fence(struct drm_i915_private *dev_priv);
+void i915_unreserve_fence(struct drm_i915_fence_reg *fence);
 
 void i915_gem_revoke_fences(struct drm_i915_private *dev_priv);
 void i915_gem_restore_fences(struct drm_i915_private *dev_priv);
diff --git a/drivers/gpu/drm/i915/i915_gem_fence_reg.c 
b/drivers/gpu/drm/i915/i915_gem_fence_reg.c
index 5fe2cd8..429ce5f 100644
--- a/drivers/gpu/drm/i915/i915_gem_fence_reg.c
+++ b/drivers/gpu/drm/i915/i915_gem_fence_reg.c
@@ -360,6 +360,50 @@ i915_vma_get_fence(struct i915_vma *vma)
 }
 
 /**
+ * i915_reserve_fence - Reserve a fence for vGPU
+ * @dev_priv: i915 device private
+ *
+ * This function walks the fence regs looking for a free one and remove
+ * it from the fence_list. It is used to reserve fence for vGPU to use.
+ */
+struct drm_i915_fence_reg *
+i915_reserve_fence(struct drm_i915_private *dev_priv)
+{
+   struct 

[Intel-gfx] [PATCH] drm/i915: Add interface to reserve fence registers for vGPU

2017-08-30 Thread changbin . du
From: Changbin Du <changbin...@intel.com>

In the past, vGPU alloc fence registers by walking through mm.fence_list
to find fence which pin_count = 0 and vma is empty. vGPU may not find
enough fence registers this way. Because a fence can be bind to vma even
though it is not in using. We have found such failure many times these
days.

An option to resolve this issue is that we can force-remove fence from
vma in this case.

This patch added two new api to the fence management code:
 - i915_reserve_one_fence() will try to find a free fence from fence_list
   and force-remove vma if need.
 - i915_giveback_reserved_fence() reclaim a reserved fence after vGPU has
   finished.

With this change, the fence management is more clear to work with vGPU.
GVTg do not need remove fence from fence_list in private.

Signed-off-by: Changbin Du <changbin...@intel.com>
---
 drivers/gpu/drm/i915/gvt/aperture_gm.c| 26 +
 drivers/gpu/drm/i915/i915_drv.h   |  3 +++
 drivers/gpu/drm/i915/i915_gem_fence_reg.c | 39 +++
 3 files changed, 53 insertions(+), 15 deletions(-)

diff --git a/drivers/gpu/drm/i915/gvt/aperture_gm.c 
b/drivers/gpu/drm/i915/gvt/aperture_gm.c
index ca3d192..29f1bf7 100644
--- a/drivers/gpu/drm/i915/gvt/aperture_gm.c
+++ b/drivers/gpu/drm/i915/gvt/aperture_gm.c
@@ -173,8 +173,8 @@ static void free_vgpu_fence(struct intel_vgpu *vgpu)
_clear_vgpu_fence(vgpu);
for (i = 0; i < vgpu_fence_sz(vgpu); i++) {
reg = vgpu->fence.regs[i];
-   list_add_tail(>link,
- _priv->mm.fence_list);
+   i915_giveback_reserved_fence(reg);
+   vgpu->fence.regs[i] = NULL;
}
mutex_unlock(_priv->drm.struct_mutex);
 
@@ -187,24 +187,19 @@ static int alloc_vgpu_fence(struct intel_vgpu *vgpu)
struct drm_i915_private *dev_priv = gvt->dev_priv;
struct drm_i915_fence_reg *reg;
int i;
-   struct list_head *pos, *q;
 
intel_runtime_pm_get(dev_priv);
 
/* Request fences from host */
mutex_lock(_priv->drm.struct_mutex);
-   i = 0;
-   list_for_each_safe(pos, q, _priv->mm.fence_list) {
-   reg = list_entry(pos, struct drm_i915_fence_reg, link);
-   if (reg->pin_count || reg->vma)
-   continue;
-   list_del(pos);
+
+   for (i = 0; i < vgpu_fence_sz(vgpu); i++) {
+   reg = i915_reserve_one_fence(dev_priv);
+   if (IS_ERR(reg))
+   goto out_free_fence;
+
vgpu->fence.regs[i] = reg;
-   if (++i == vgpu_fence_sz(vgpu))
-   break;
}
-   if (i != vgpu_fence_sz(vgpu))
-   goto out_free_fence;
 
_clear_vgpu_fence(vgpu);
 
@@ -212,13 +207,14 @@ static int alloc_vgpu_fence(struct intel_vgpu *vgpu)
intel_runtime_pm_put(dev_priv);
return 0;
 out_free_fence:
+   gvt_vgpu_err("Failed to alloc fences\n");
/* Return fences to host, if fail */
for (i = 0; i < vgpu_fence_sz(vgpu); i++) {
reg = vgpu->fence.regs[i];
if (!reg)
continue;
-   list_add_tail(>link,
- _priv->mm.fence_list);
+   i915_giveback_reserved_fence(reg);
+   vgpu->fence.regs[i] = NULL;
}
mutex_unlock(_priv->drm.struct_mutex);
intel_runtime_pm_put(dev_priv);
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index 7587ef5..c505b44 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -3650,6 +3650,9 @@ i915_vm_to_ppgtt(struct i915_address_space *vm)
 /* i915_gem_fence_reg.c */
 int __must_check i915_vma_get_fence(struct i915_vma *vma);
 int __must_check i915_vma_put_fence(struct i915_vma *vma);
+struct drm_i915_fence_reg *
+i915_reserve_one_fence(struct drm_i915_private *dev_priv);
+void i915_giveback_reserved_fence(struct drm_i915_fence_reg *fence);
 
 void i915_gem_revoke_fences(struct drm_i915_private *dev_priv);
 void i915_gem_restore_fences(struct drm_i915_private *dev_priv);
diff --git a/drivers/gpu/drm/i915/i915_gem_fence_reg.c 
b/drivers/gpu/drm/i915/i915_gem_fence_reg.c
index 5fe2cd8..63e4e94 100644
--- a/drivers/gpu/drm/i915/i915_gem_fence_reg.c
+++ b/drivers/gpu/drm/i915/i915_gem_fence_reg.c
@@ -360,6 +360,45 @@ i915_vma_get_fence(struct i915_vma *vma)
 }
 
 /**
+ * i915_reserve_one_fence - Reserve a fence for vGPU
+ * @dev_priv: i915 device private
+ *
+ * This function walks the fence regs looking for a free one and remove
+ * it from the fence_list. It is used to reserve fence for vGPU to use.
+ */
+struct drm_i915_fence_reg *
+i915_reserve_one_fence(struct drm_i915_private *dev_priv)
+{
+   struct drm_i915_fence_reg *fence;
+   int ret;
+
+   fence 

[Intel-gfx] [PATCH] drm/i915: prevent generating unusable gvt build which no mpt module is selected

2017-05-24 Thread changbin . du
From: Changbin Du <changbin...@intel.com>

At least we need one MPT module (currently only have one) selected
to get GVTg functional. When GVTg is enabled while no MPT selected,
the build just includes useless GVTg code. This doesn't make sense.

With this patch, a submenut is created under i915 as below:
  -*- Enable Intel GVT-g graphics virtualization host support
   Enable KVM/VFIO support for Intel GVT-g

If no MPT is selected, GVTg will be disabled automatically.
  < > Enable KVM/VFIO support for Intel GVT-g

Signed-off-by: Changbin Du <changbin...@intel.com>
---
 drivers/gpu/drm/i915/Kconfig | 16 ++--
 1 file changed, 10 insertions(+), 6 deletions(-)

diff --git a/drivers/gpu/drm/i915/Kconfig b/drivers/gpu/drm/i915/Kconfig
index a5cd5da..e380a5d 100644
--- a/drivers/gpu/drm/i915/Kconfig
+++ b/drivers/gpu/drm/i915/Kconfig
@@ -91,12 +91,15 @@ config DRM_I915_USERPTR
 
  If in doubt, say "Y".
 
+menu "Intel GVT-g graphics virtualization host support"
+   depends on DRM_I915
+   depends on 64BIT
+
 config DRM_I915_GVT
-bool "Enable Intel GVT-g graphics virtualization host support"
-depends on DRM_I915
-depends on 64BIT
-default n
-help
+   bool "Enable Intel GVT-g graphics virtualization host support"
+   default n
+   depends on DRM_I915_GVT_KVMGT
+   help
  Choose this option if you want to enable Intel GVT-g graphics
  virtualization technology host support with integrated graphics.
  With GVT-g, it's possible to have one integrated graphics
@@ -116,13 +119,14 @@ config DRM_I915_GVT
 
 config DRM_I915_GVT_KVMGT
tristate "Enable KVM/VFIO support for Intel GVT-g"
-   depends on DRM_I915_GVT
+   select DRM_I915_GVT
depends on KVM
depends on VFIO_MDEV && VFIO_MDEV_DEVICE
default n
help
  Choose this option if you want to enable KVMGT support for
  Intel GVT-g.
+endmenu
 
 menu "drm/i915 Debugging"
 depends on DRM_I915
-- 
2.7.4

___
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx


[Intel-gfx] [PATCH v2] drm/i915: make context status notifier head be per engine

2017-03-12 Thread changbin . du
From: Changbin Du <changbin...@intel.com>

GVTg has introduced the context status notifier to schedule the GVTg
workload. At that time, the notifier is bound to GVTg context only,
so GVTg is not aware of host workloads.

Now we are going to improve GVTg's guest workload scheduler policy,
and add Guc emulation support for new Gen graphics. Both these two
features require acknowledgment for all contexts running on hardware.
(But will not alter host workload.) So here try to make some change.

The change is simple:
  1. Move the context status notifier head from i915_gem_context to
 intel_engine_cs. Which means there is a notifier head per engine
 instead of per context. Execlist driver still call notifier for
 each context sched-in/out events of current engine.
  2. At GVTg side, it binds a notifier_block for each physical engine
 at GVTg initialization period. Then GVTg can hear all context
 status events.

In this patch, GVTg do nothing for host context event, but later
will add a function there. But in any case, the notifier callback is
a noop if this is no active vGPU.

Since intel_gvt_init() is called at early initialization stage and
require the status notifier head has been initiated, I initiate it in
intel_engine_setup().

v2: remove a redundant newline. (chris)

Signed-off-by: Changbin Du <changbin...@intel.com>
Reviewed-by: Chris Wilson <ch...@chris-wilson.co.uk>
---
 drivers/gpu/drm/i915/gvt/gvt.h  |  2 +-
 drivers/gpu/drm/i915/gvt/scheduler.c| 45 ++---
 drivers/gpu/drm/i915/i915_gem_context.c |  1 -
 drivers/gpu/drm/i915/i915_gem_context.h |  3 ---
 drivers/gpu/drm/i915/intel_engine_cs.c  |  2 ++
 drivers/gpu/drm/i915/intel_lrc.c|  3 ++-
 drivers/gpu/drm/i915/intel_ringbuffer.h |  3 +++
 7 files changed, 27 insertions(+), 32 deletions(-)

diff --git a/drivers/gpu/drm/i915/gvt/gvt.h b/drivers/gpu/drm/i915/gvt/gvt.h
index 2379192..6dfc48b 100644
--- a/drivers/gpu/drm/i915/gvt/gvt.h
+++ b/drivers/gpu/drm/i915/gvt/gvt.h
@@ -162,7 +162,6 @@ struct intel_vgpu {
atomic_t running_workload_num;
DECLARE_BITMAP(tlb_handle_pending, I915_NUM_ENGINES);
struct i915_gem_context *shadow_ctx;
-   struct notifier_block shadow_ctx_notifier_block;
 
 #if IS_ENABLED(CONFIG_DRM_I915_GVT_KVMGT)
struct {
@@ -233,6 +232,7 @@ struct intel_gvt {
struct intel_gvt_gtt gtt;
struct intel_gvt_opregion opregion;
struct intel_gvt_workload_scheduler scheduler;
+   struct notifier_block shadow_ctx_notifier_block[I915_NUM_ENGINES];
DECLARE_HASHTABLE(cmd_table, GVT_CMD_HASH_BITS);
struct intel_vgpu_type *types;
unsigned int num_types;
diff --git a/drivers/gpu/drm/i915/gvt/scheduler.c 
b/drivers/gpu/drm/i915/gvt/scheduler.c
index d3a56c9..48e5088 100644
--- a/drivers/gpu/drm/i915/gvt/scheduler.c
+++ b/drivers/gpu/drm/i915/gvt/scheduler.c
@@ -130,12 +130,10 @@ static int populate_shadow_context(struct 
intel_vgpu_workload *workload)
 static int shadow_context_status_change(struct notifier_block *nb,
unsigned long action, void *data)
 {
-   struct intel_vgpu *vgpu = container_of(nb,
-   struct intel_vgpu, shadow_ctx_notifier_block);
-   struct drm_i915_gem_request *req =
-   (struct drm_i915_gem_request *)data;
-   struct intel_gvt_workload_scheduler *scheduler =
-   >gvt->scheduler;
+   struct drm_i915_gem_request *req = (struct drm_i915_gem_request *)data;
+   struct intel_gvt *gvt = container_of(nb, struct intel_gvt,
+   shadow_ctx_notifier_block[req->engine->id]);
+   struct intel_gvt_workload_scheduler *scheduler = >scheduler;
struct intel_vgpu_workload *workload =
scheduler->current_workload[req->engine->id];
 
@@ -513,15 +511,16 @@ void intel_gvt_wait_vgpu_idle(struct intel_vgpu *vgpu)
 void intel_gvt_clean_workload_scheduler(struct intel_gvt *gvt)
 {
struct intel_gvt_workload_scheduler *scheduler = >scheduler;
-   int i;
+   struct intel_engine_cs *engine;
+   enum intel_engine_id i;
 
gvt_dbg_core("clean workload scheduler\n");
 
-   for (i = 0; i < I915_NUM_ENGINES; i++) {
-   if (scheduler->thread[i]) {
-   kthread_stop(scheduler->thread[i]);
-   scheduler->thread[i] = NULL;
-   }
+   for_each_engine(engine, gvt->dev_priv, i) {
+   atomic_notifier_chain_unregister(
+   >context_status_notifier,
+   >shadow_ctx_notifier_block[i]);
+   kthread_stop(scheduler->thread[i]);
}
 }
 
@@ -529,18 +528,15 @@ int intel_gvt_init_workload_scheduler(struct intel_gvt 
*gvt)
 {
struct intel_gvt_workload_scheduler *scheduler = >scheduler;
struct workloa

[Intel-gfx] [PATCH] drm/i915: make context status notifier head be per engine

2017-03-09 Thread changbin . du
From: Changbin Du <changbin...@intel.com>

GVTg has introduced the context status notifier to schedule the GVTg
workload. At that time, the notifier is bound to GVTg context only,
so GVTg is not aware of host workloads.

Now we are going to improve GVTg's guest workload scheduler policy,
and add Guc emulation support for new Gen graphics. Both these two
features require acknowledgment for all contexts running on hardware.
(But will not alter host workload.) So here try to make some change.

The change is simple:
  1. Move the context status notifier head from i915_gem_context to
 intel_engine_cs. Which means there is a notifier head per engine
 instead of per context. Execlist driver still call notifier for
 each context sched-in/out events of current engine.
  2. At GVTg side, it binds a notifier_block for each physical engine
 at GVTg initialization period. Then GVTg can hear all context
 status events.

In this patch, GVTg do nothing for host context event, but later
will add a function there. But in any case, the notifier callback is
a noop if this is no active vGPU.

Since intel_gvt_init() is called at early initialization stage and
require the status notifier head has been initiated, I initiate it in
intel_engine_setup().

Signed-off-by: Changbin Du <changbin...@intel.com>
---
 drivers/gpu/drm/i915/gvt/gvt.h  |  2 +-
 drivers/gpu/drm/i915/gvt/scheduler.c| 46 ++---
 drivers/gpu/drm/i915/i915_gem_context.c |  1 -
 drivers/gpu/drm/i915/i915_gem_context.h |  3 ---
 drivers/gpu/drm/i915/intel_engine_cs.c  |  2 ++
 drivers/gpu/drm/i915/intel_lrc.c|  3 ++-
 drivers/gpu/drm/i915/intel_ringbuffer.h |  3 +++
 7 files changed, 28 insertions(+), 32 deletions(-)

diff --git a/drivers/gpu/drm/i915/gvt/gvt.h b/drivers/gpu/drm/i915/gvt/gvt.h
index 2379192..6dfc48b 100644
--- a/drivers/gpu/drm/i915/gvt/gvt.h
+++ b/drivers/gpu/drm/i915/gvt/gvt.h
@@ -162,7 +162,6 @@ struct intel_vgpu {
atomic_t running_workload_num;
DECLARE_BITMAP(tlb_handle_pending, I915_NUM_ENGINES);
struct i915_gem_context *shadow_ctx;
-   struct notifier_block shadow_ctx_notifier_block;
 
 #if IS_ENABLED(CONFIG_DRM_I915_GVT_KVMGT)
struct {
@@ -233,6 +232,7 @@ struct intel_gvt {
struct intel_gvt_gtt gtt;
struct intel_gvt_opregion opregion;
struct intel_gvt_workload_scheduler scheduler;
+   struct notifier_block shadow_ctx_notifier_block[I915_NUM_ENGINES];
DECLARE_HASHTABLE(cmd_table, GVT_CMD_HASH_BITS);
struct intel_vgpu_type *types;
unsigned int num_types;
diff --git a/drivers/gpu/drm/i915/gvt/scheduler.c 
b/drivers/gpu/drm/i915/gvt/scheduler.c
index d3a56c9..64875ec 100644
--- a/drivers/gpu/drm/i915/gvt/scheduler.c
+++ b/drivers/gpu/drm/i915/gvt/scheduler.c
@@ -127,15 +127,14 @@ static int populate_shadow_context(struct 
intel_vgpu_workload *workload)
return 0;
 }
 
+
 static int shadow_context_status_change(struct notifier_block *nb,
unsigned long action, void *data)
 {
-   struct intel_vgpu *vgpu = container_of(nb,
-   struct intel_vgpu, shadow_ctx_notifier_block);
-   struct drm_i915_gem_request *req =
-   (struct drm_i915_gem_request *)data;
-   struct intel_gvt_workload_scheduler *scheduler =
-   >gvt->scheduler;
+   struct drm_i915_gem_request *req = (struct drm_i915_gem_request *)data;
+   struct intel_gvt *gvt = container_of(nb, struct intel_gvt,
+   shadow_ctx_notifier_block[req->engine->id]);
+   struct intel_gvt_workload_scheduler *scheduler = >scheduler;
struct intel_vgpu_workload *workload =
scheduler->current_workload[req->engine->id];
 
@@ -513,15 +512,16 @@ void intel_gvt_wait_vgpu_idle(struct intel_vgpu *vgpu)
 void intel_gvt_clean_workload_scheduler(struct intel_gvt *gvt)
 {
struct intel_gvt_workload_scheduler *scheduler = >scheduler;
-   int i;
+   struct intel_engine_cs *engine;
+   enum intel_engine_id i;
 
gvt_dbg_core("clean workload scheduler\n");
 
-   for (i = 0; i < I915_NUM_ENGINES; i++) {
-   if (scheduler->thread[i]) {
-   kthread_stop(scheduler->thread[i]);
-   scheduler->thread[i] = NULL;
-   }
+   for_each_engine(engine, gvt->dev_priv, i) {
+   atomic_notifier_chain_unregister(
+   >context_status_notifier,
+   >shadow_ctx_notifier_block[i]);
+   kthread_stop(scheduler->thread[i]);
}
 }
 
@@ -529,18 +529,15 @@ int intel_gvt_init_workload_scheduler(struct intel_gvt 
*gvt)
 {
struct intel_gvt_workload_scheduler *scheduler = >scheduler;
struct workload_thread_param *param = NULL;
+   struct intel_engine_cs *engine;
+   en

[Intel-gfx] [RFC PATCH] drm/i915: make context status notifier head be per engine

2017-03-02 Thread changbin . du
From: Changbin Du <changbin...@intel.com>

hi, Daniel, Chris and All,
As you know, GVTg introduced the context status notifier to schedule
the GVTg workload. At that time, the notifier is bound to GVTg context
only, so GVTg is not aware of host workloads.

Now we are going to improve GVTg's guest workload scheduler policy,
and add Guc emulation support for new Gen graphics. Both these two
features require acknowledgment for all contexts running on hardware.
(But will not alter host workload.) So here try to make some change.

The change is easy:
  1. Move the context status notifier head from i915_gem_context to
 intel_engine_cs. Which means there is a notifier head per engine
 instead of per context. Execlist driver still call notifier for
 each context sched-in/out events of current engine.
  2. At GVTg side, it binds a notifier_block for each physical engine
 at GVTg initialization period. Then GVTg can hear all context
 status events.

In this RFC patch, GVTg do nothing for host context event, but later
will add a function there. But in any case, the notifier callback is
a noop if this is no active vGPU.

Since intel_gvt_init() is called at early initialization stage and
require the status notifier head has been initiated, I initiate it in
intel_engine_setup(). I am not sure if this is the right place, please
correct me if wrong. Thank you! Look forward to your feedback. :)

Signed-off-by: Changbin Du <changbin...@intel.com>
---
 drivers/gpu/drm/i915/gvt/gvt.h  |  2 +-
 drivers/gpu/drm/i915/gvt/scheduler.c| 46 ++---
 drivers/gpu/drm/i915/i915_gem_context.c |  1 -
 drivers/gpu/drm/i915/i915_gem_context.h |  3 ---
 drivers/gpu/drm/i915/intel_engine_cs.c  |  2 ++
 drivers/gpu/drm/i915/intel_lrc.c|  3 ++-
 drivers/gpu/drm/i915/intel_ringbuffer.h |  3 +++
 7 files changed, 28 insertions(+), 32 deletions(-)

diff --git a/drivers/gpu/drm/i915/gvt/gvt.h b/drivers/gpu/drm/i915/gvt/gvt.h
index a41b322..6c1ec7d6 100644
--- a/drivers/gpu/drm/i915/gvt/gvt.h
+++ b/drivers/gpu/drm/i915/gvt/gvt.h
@@ -162,7 +162,6 @@ struct intel_vgpu {
atomic_t running_workload_num;
DECLARE_BITMAP(tlb_handle_pending, I915_NUM_ENGINES);
struct i915_gem_context *shadow_ctx;
-   struct notifier_block shadow_ctx_notifier_block;
 
 #if IS_ENABLED(CONFIG_DRM_I915_GVT_KVMGT)
struct {
@@ -233,6 +232,7 @@ struct intel_gvt {
struct intel_gvt_gtt gtt;
struct intel_gvt_opregion opregion;
struct intel_gvt_workload_scheduler scheduler;
+   struct notifier_block shadow_ctx_notifier_block[I915_NUM_ENGINES];
DECLARE_HASHTABLE(cmd_table, GVT_CMD_HASH_BITS);
struct intel_vgpu_type *types;
unsigned int num_types;
diff --git a/drivers/gpu/drm/i915/gvt/scheduler.c 
b/drivers/gpu/drm/i915/gvt/scheduler.c
index e355a82..1cb90b8 100644
--- a/drivers/gpu/drm/i915/gvt/scheduler.c
+++ b/drivers/gpu/drm/i915/gvt/scheduler.c
@@ -127,15 +127,14 @@ static int populate_shadow_context(struct 
intel_vgpu_workload *workload)
return 0;
 }
 
+
 static int shadow_context_status_change(struct notifier_block *nb,
unsigned long action, void *data)
 {
-   struct intel_vgpu *vgpu = container_of(nb,
-   struct intel_vgpu, shadow_ctx_notifier_block);
-   struct drm_i915_gem_request *req =
-   (struct drm_i915_gem_request *)data;
-   struct intel_gvt_workload_scheduler *scheduler =
-   >gvt->scheduler;
+   struct drm_i915_gem_request *req = (struct drm_i915_gem_request *)data;
+   struct intel_gvt *gvt = container_of(nb, struct intel_gvt,
+   shadow_ctx_notifier_block[req->engine->id]);
+   struct intel_gvt_workload_scheduler *scheduler = >scheduler;
struct intel_vgpu_workload *workload =
scheduler->current_workload[req->engine->id];
 
@@ -496,15 +495,16 @@ void intel_gvt_wait_vgpu_idle(struct intel_vgpu *vgpu)
 void intel_gvt_clean_workload_scheduler(struct intel_gvt *gvt)
 {
struct intel_gvt_workload_scheduler *scheduler = >scheduler;
-   int i;
+   struct intel_engine_cs *engine;
+   enum intel_engine_id i;
 
gvt_dbg_core("clean workload scheduler\n");
 
-   for (i = 0; i < I915_NUM_ENGINES; i++) {
-   if (scheduler->thread[i]) {
-   kthread_stop(scheduler->thread[i]);
-   scheduler->thread[i] = NULL;
-   }
+   for_each_engine(engine, gvt->dev_priv, i) {
+   atomic_notifier_chain_unregister(
+   >context_status_notifier,
+   >shadow_ctx_notifier_block[i]);
+   kthread_stop(scheduler->thread[i]);
}
 }
 
@@ -512,18 +512,15 @@ int intel_gvt_init_workload_scheduler(struct intel_gvt 
*gvt)
 {
st

[Intel-gfx] [PATCH] drm/i915: check if execlist_port is empty before using its content

2016-12-22 Thread changbin . du
From: "Du, Changbin" <changbin...@intel.com>

This patch fix a crash in function reset_common_ring. In this case,
the port[0].request is null when reset the render ring, so a null
dereference exception is raised. We need to check execlist_port status
first.

[   35.748034] BUG: unable to handle kernel NULL pointer dereference at 
0070
[   35.749567] IP: [] reset_common_ring+0xbe/0x150
[   35.749567] Call Trace:
[   35.749567]  [] i915_gem_reset+0x150/0x270
[   35.749567]  [] i915_reset+0x8a/0xe0
[   35.749567]  [] i915_reset_and_wakeup+0x131/0x160
[   35.749567]  [] ? gen5_read8+0x110/0x110
[   35.749567]  [] i915_handle_error+0xca/0x5a0
[   35.749567]  [] ? scnprintf+0x3d/0x70
[   35.749567]  [] i915_hangcheck_elapsed+0x213/0x510
[   35.749567]  [] process_one_work+0x15b/0x470
[   35.749567]  [] worker_thread+0x43/0x4d0
[   35.749567]  [] ? process_one_work+0x470/0x470
[   35.749567]  [] ? process_one_work+0x470/0x470
[   35.749567]  [] ? 
call_usermodehelper_exec_async+0x12e/0x130
[   35.749567]  [] kthread+0xc5/0xe0
[   35.749567]  [] ? kthread_park+0x60/0x60
[   35.749567]  [] ? umh_complete+0x40/0x40
[   35.749567]  [] ret_from_fork+0x22/0x30

Signed-off-by: Changbin Du <changbin...@intel.com>
---
 drivers/gpu/drm/i915/intel_lrc.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/i915/intel_lrc.c b/drivers/gpu/drm/i915/intel_lrc.c
index 0a09024..81a9b0b 100644
--- a/drivers/gpu/drm/i915/intel_lrc.c
+++ b/drivers/gpu/drm/i915/intel_lrc.c
@@ -1450,7 +1450,7 @@ static void reset_common_ring(struct intel_engine_cs 
*engine,
 
/* Catch up with any missed context-switch interrupts */
I915_WRITE(RING_CONTEXT_STATUS_PTR(engine), _MASKED_FIELD(0x, 0));
-   if (request->ctx != port[0].request->ctx) {
+   if (!execlists_elsp_idle(engine) && request->ctx != 
port[0].request->ctx) {
i915_gem_request_put(port[0].request);
port[0] = port[1];
memset([1], 0, sizeof(port[1]));
-- 
2.7.4

___
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx