diff mbox

i915: Add module option to support VGA arbiter on HD devices

Message ID 20140509201655.2849.97478.stgit@bling.home (mailing list archive)
State New, archived
Headers show

Commit Message

Alex Williamson May 9, 2014, 8:20 p.m. UTC
Commit 81b5c7bc found that the current VGA arbiter support in i915
only works for ancient GMCH-based IGD devices and attempted to update
support for newer HD devices.  Unfortunately newer devices cannot
completely opt-out of VGA arbitration like the old devices could.
The VGA I/O space cannot be disabled internally.  The only way to
route VGA I/O elsewhere is by disabling I/O at the device PCI command
register.  This means that with commit 81b5c7bc and multiple VGA
adapters, the VGA arbiter will report that multiple VGA devices are
participating in arbitration, Xorg will notice this and disable DRI.
Therefore, 81b5c7bc was reverted because DRI is more important than
being correct.

There is however an actual need for i915 to correctly participate in
VGA arbitration; VGA device assignment.  If we want to use VFIO to
assign a VGA device to a virtual machine, we need to be able to
access the VGA resources of that device.  By adding an i915 module
option we can allow i915 to continue with its charade by default, but
also allow an easy path for users who require working VGA arbitration.
Hopefully Xorg can someday be taught to behave better with multiple
VGA devices.

This also rolls in reverted commit 6e1b4fda, which corrected an
ordering issue with 81b5c7bc by delaying the disabling of VGA memory
until after vgacon->fbcon handoff.

Signed-off-by: Alex Williamson <alex.williamson@redhat.com>
Cc: Ville Syrjälä <ville.syrjala@linux.intel.com>
Cc: Daniel Vetter <daniel.vetter@ffwll.ch>
Cc: Dave Airlie <airlied@redhat.com>
---

This should be a nop with the default module setting, so if there's
any opportunity to get this into v3.15, it would be appreciated.

 drivers/gpu/drm/i915/i915_dma.c      |   22 +++++++++++++++++++---
 drivers/gpu/drm/i915/i915_drv.h      |    1 +
 drivers/gpu/drm/i915/i915_params.c   |    5 +++++
 drivers/gpu/drm/i915/intel_display.c |   30 ++++++++++++++++++++++++++++++
 drivers/gpu/drm/i915/intel_drv.h     |    2 ++
 include/linux/vgaarb.h               |    7 +++++++
 6 files changed, 64 insertions(+), 3 deletions(-)

Comments

Daniel Vetter May 12, 2014, 7:08 p.m. UTC | #1
On Fri, May 09, 2014 at 02:20:41PM -0600, Alex Williamson wrote:
> Commit 81b5c7bc found that the current VGA arbiter support in i915
> only works for ancient GMCH-based IGD devices and attempted to update
> support for newer HD devices.  Unfortunately newer devices cannot
> completely opt-out of VGA arbitration like the old devices could.
> The VGA I/O space cannot be disabled internally.  The only way to
> route VGA I/O elsewhere is by disabling I/O at the device PCI command
> register.  This means that with commit 81b5c7bc and multiple VGA
> adapters, the VGA arbiter will report that multiple VGA devices are
> participating in arbitration, Xorg will notice this and disable DRI.
> Therefore, 81b5c7bc was reverted because DRI is more important than
> being correct.
> 
> There is however an actual need for i915 to correctly participate in
> VGA arbitration; VGA device assignment.  If we want to use VFIO to
> assign a VGA device to a virtual machine, we need to be able to
> access the VGA resources of that device.  By adding an i915 module
> option we can allow i915 to continue with its charade by default, but
> also allow an easy path for users who require working VGA arbitration.
> Hopefully Xorg can someday be taught to behave better with multiple
> VGA devices.
> 
> This also rolls in reverted commit 6e1b4fda, which corrected an
> ordering issue with 81b5c7bc by delaying the disabling of VGA memory
> until after vgacon->fbcon handoff.
> 
> Signed-off-by: Alex Williamson <alex.williamson@redhat.com>
> Cc: Ville Syrjälä <ville.syrjala@linux.intel.com>
> Cc: Daniel Vetter <daniel.vetter@ffwll.ch>
> Cc: Dave Airlie <airlied@redhat.com>
> ---
> 
> This should be a nop with the default module setting, so if there's
> any opportunity to get this into v3.15, it would be appreciated.

I really don't like module options to work around bugs elsewhere. It means
the 5 users who know about a given bug are now happen, and the 3
bazillion without enough clue/savy/time still suffer from problems.

My goal is to actually add a bit of support to the core kernel's module
option parsing code so that most of the options we have can spit warnings
into dmesg and taint the kernel.

Can't we fix this in any other way?
-Daniel

> 
>  drivers/gpu/drm/i915/i915_dma.c      |   22 +++++++++++++++++++---
>  drivers/gpu/drm/i915/i915_drv.h      |    1 +
>  drivers/gpu/drm/i915/i915_params.c   |    5 +++++
>  drivers/gpu/drm/i915/intel_display.c |   30 ++++++++++++++++++++++++++++++
>  drivers/gpu/drm/i915/intel_drv.h     |    2 ++
>  include/linux/vgaarb.h               |    7 +++++++
>  6 files changed, 64 insertions(+), 3 deletions(-)
> 
> diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c
> index 96177ee..c0d0c03 100644
> --- a/drivers/gpu/drm/i915/i915_dma.c
> +++ b/drivers/gpu/drm/i915/i915_dma.c
> @@ -1306,10 +1306,20 @@ static int i915_load_modeset_init(struct drm_device *dev)
>  	 * If we are a secondary display controller (!PCI_DISPLAY_CLASS_VGA),
>  	 * then we do not take part in VGA arbitration and the
>  	 * vga_client_register() fails with -ENODEV.
> +	 *
> +	 * NB.  The set_decode callback here actually only works on GMCH
> +	 * devices, on newer HD devices we can only disable VGA MMIO space.
> +	 * Disabling VGA I/O space requires disabling I/O in the PCI command
> +	 * register.  Nonetheless, we like to pretend that we participate in
> +	 * VGA arbitration and can dynamically disable VGA I/O space because
> +	 * this makes X happy, even though it's a complete lie.
>  	 */
> -	ret = vga_client_register(dev->pdev, dev, NULL, i915_vga_set_decode);
> -	if (ret && ret != -ENODEV)
> -		goto out;
> +	if (!i915.enable_hd_vgaarb || !HAS_PCH_SPLIT(dev)) {
> +		ret = vga_client_register(dev->pdev, dev, NULL,
> +					  i915_vga_set_decode);
> +		if (ret && ret != -ENODEV)
> +			goto out;
> +	}
>  
>  	intel_register_dsm_handler();
>  
> @@ -1369,6 +1379,12 @@ static int i915_load_modeset_init(struct drm_device *dev)
>  	 */
>  	intel_fbdev_initial_config(dev);
>  
> +	/*
> +	 * Must do this after fbcon init so that
> +	 * vgacon_save_screen() works during the handover.
> +	 */
> +	i915_disable_vga_mem(dev);
> +
>  	/* Only enable hotplug handling once the fbdev is fully set up. */
>  	dev_priv->enable_hotplug_processing = true;
>  
> diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
> index ec82f6b..f3908f6 100644
> --- a/drivers/gpu/drm/i915/i915_drv.h
> +++ b/drivers/gpu/drm/i915/i915_drv.h
> @@ -2080,6 +2080,7 @@ struct i915_params {
>  	bool prefault_disable;
>  	bool reset;
>  	bool disable_display;
> +	bool enable_hd_vgaarb;
>  };
>  extern struct i915_params i915 __read_mostly;
>  
> diff --git a/drivers/gpu/drm/i915/i915_params.c b/drivers/gpu/drm/i915/i915_params.c
> index d1d7980..64d96c6 100644
> --- a/drivers/gpu/drm/i915/i915_params.c
> +++ b/drivers/gpu/drm/i915/i915_params.c
> @@ -47,6 +47,7 @@ struct i915_params i915 __read_mostly = {
>  	.invert_brightness = 0,
>  	.disable_display = 0,
>  	.enable_cmd_parser = 0,
> +	.enable_hd_vgaarb = false,
>  };
>  
>  module_param_named(modeset, i915.modeset, int, 0400);
> @@ -152,3 +153,7 @@ MODULE_PARM_DESC(disable_display, "Disable display (default: false)");
>  module_param_named(enable_cmd_parser, i915.enable_cmd_parser, int, 0600);
>  MODULE_PARM_DESC(enable_cmd_parser,
>  		 "Enable command parsing (1=enabled, 0=disabled [default])");
> +
> +module_param_named(enable_hd_vgaarb, i915.enable_hd_vgaarb, bool, 0444);
> +MODULE_PARM_DESC(enable_hd_vgaarb,
> +	"Enable support for VGA arbitration on Intel HD IGD. (default: false)");
> diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
> index 69bcc42..2cd35ba 100644
> --- a/drivers/gpu/drm/i915/intel_display.c
> +++ b/drivers/gpu/drm/i915/intel_display.c
> @@ -11284,6 +11284,33 @@ static void i915_disable_vga(struct drm_device *dev)
>  	POSTING_READ(vga_reg);
>  }
>  
> +static void i915_enable_vga_mem(struct drm_device *dev)
> +{
> +	/* Enable VGA memory on Intel HD */
> +	if (i915.enable_hd_vgaarb && HAS_PCH_SPLIT(dev)) {
> +		vga_get_uninterruptible(dev->pdev, VGA_RSRC_LEGACY_IO);
> +		outb(inb(VGA_MSR_READ) | VGA_MSR_MEM_EN, VGA_MSR_WRITE);
> +		vga_set_legacy_decoding(dev->pdev, VGA_RSRC_LEGACY_IO |
> +						   VGA_RSRC_LEGACY_MEM |
> +						   VGA_RSRC_NORMAL_IO |
> +						   VGA_RSRC_NORMAL_MEM);
> +		vga_put(dev->pdev, VGA_RSRC_LEGACY_IO);
> +	}
> +}
> +
> +void i915_disable_vga_mem(struct drm_device *dev)
> +{
> +	/* Disable VGA memory on Intel HD */
> +	if (i915.enable_hd_vgaarb && HAS_PCH_SPLIT(dev)) {
> +		vga_get_uninterruptible(dev->pdev, VGA_RSRC_LEGACY_IO);
> +		outb(inb(VGA_MSR_READ) & ~VGA_MSR_MEM_EN, VGA_MSR_WRITE);
> +		vga_set_legacy_decoding(dev->pdev, VGA_RSRC_LEGACY_IO |
> +						   VGA_RSRC_NORMAL_IO |
> +						   VGA_RSRC_NORMAL_MEM);
> +		vga_put(dev->pdev, VGA_RSRC_LEGACY_IO);
> +	}
> +}
> +
>  void intel_modeset_init_hw(struct drm_device *dev)
>  {
>  	intel_prepare_ddi(dev);
> @@ -11594,6 +11621,7 @@ void i915_redisable_vga_power_on(struct drm_device *dev)
>  	if (!(I915_READ(vga_reg) & VGA_DISP_DISABLE)) {
>  		DRM_DEBUG_KMS("Something enabled VGA plane, disabling it\n");
>  		i915_disable_vga(dev);
> +		i915_disable_vga_mem(dev);
>  	}
>  }
>  
> @@ -11848,6 +11876,8 @@ void intel_modeset_cleanup(struct drm_device *dev)
>  
>  	intel_disable_fbc(dev);
>  
> +	i915_enable_vga_mem(dev);
> +
>  	intel_disable_gt_powersave(dev);
>  
>  	ironlake_teardown_rc6(dev);
> diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
> index 328b1a7..fbe5d360 100644
> --- a/drivers/gpu/drm/i915/intel_drv.h
> +++ b/drivers/gpu/drm/i915/intel_drv.h
> @@ -934,4 +934,6 @@ int intel_sprite_get_colorkey(struct drm_device *dev, void *data,
>  /* intel_tv.c */
>  void intel_tv_init(struct drm_device *dev);
>  
> +extern void i915_disable_vga_mem(struct drm_device *dev);
> +
>  #endif /* __INTEL_DRV_H__ */
> diff --git a/include/linux/vgaarb.h b/include/linux/vgaarb.h
> index 2c02f3a..80cf817 100644
> --- a/include/linux/vgaarb.h
> +++ b/include/linux/vgaarb.h
> @@ -65,8 +65,15 @@ struct pci_dev;
>   *     out of the arbitration process (and can be safe to take
>   *     interrupts at any time.
>   */
> +#if defined(CONFIG_VGA_ARB)
>  extern void vga_set_legacy_decoding(struct pci_dev *pdev,
>  				    unsigned int decodes);
> +#else
> +static inline void vga_set_legacy_decoding(struct pci_dev *pdev,
> +					   unsigned int decodes)
> +{
> +}
> +#endif
>  
>  /**
>   *     vga_get         - acquire & locks VGA resources
>
Alex Williamson May 12, 2014, 7:30 p.m. UTC | #2
On Mon, 2014-05-12 at 21:08 +0200, Daniel Vetter wrote:
> On Fri, May 09, 2014 at 02:20:41PM -0600, Alex Williamson wrote:
> > Commit 81b5c7bc found that the current VGA arbiter support in i915
> > only works for ancient GMCH-based IGD devices and attempted to update
> > support for newer HD devices.  Unfortunately newer devices cannot
> > completely opt-out of VGA arbitration like the old devices could.
> > The VGA I/O space cannot be disabled internally.  The only way to
> > route VGA I/O elsewhere is by disabling I/O at the device PCI command
> > register.  This means that with commit 81b5c7bc and multiple VGA
> > adapters, the VGA arbiter will report that multiple VGA devices are
> > participating in arbitration, Xorg will notice this and disable DRI.
> > Therefore, 81b5c7bc was reverted because DRI is more important than
> > being correct.
> > 
> > There is however an actual need for i915 to correctly participate in
> > VGA arbitration; VGA device assignment.  If we want to use VFIO to
> > assign a VGA device to a virtual machine, we need to be able to
> > access the VGA resources of that device.  By adding an i915 module
> > option we can allow i915 to continue with its charade by default, but
> > also allow an easy path for users who require working VGA arbitration.
> > Hopefully Xorg can someday be taught to behave better with multiple
> > VGA devices.
> > 
> > This also rolls in reverted commit 6e1b4fda, which corrected an
> > ordering issue with 81b5c7bc by delaying the disabling of VGA memory
> > until after vgacon->fbcon handoff.
> > 
> > Signed-off-by: Alex Williamson <alex.williamson@redhat.com>
> > Cc: Ville Syrjälä <ville.syrjala@linux.intel.com>
> > Cc: Daniel Vetter <daniel.vetter@ffwll.ch>
> > Cc: Dave Airlie <airlied@redhat.com>
> > ---
> > 
> > This should be a nop with the default module setting, so if there's
> > any opportunity to get this into v3.15, it would be appreciated.
> 
> I really don't like module options to work around bugs elsewhere. It means
> the 5 users who know about a given bug are now happen, and the 3
> bazillion without enough clue/savy/time still suffer from problems.
> 
> My goal is to actually add a bit of support to the core kernel's module
> option parsing code so that most of the options we have can spit warnings
> into dmesg and taint the kernel.
> 
> Can't we fix this in any other way?

Do you have any suggestions?  I proposed creating a new VGA arbiter
interface that would allow Xorg to mmap the legacy VGA MMIO space
regardless of the number of VGA arbitration participants, but didn't get
any nibbles on supporting that through the rest of the stack.  Dave
suggested maybe he could rip out the VGA arbiter support from Xorg and
nobody would notice.  In either case, at what point do we get to flip
i915 to behave correctly with arbitration?  It seems like anything we do
has a compatibility period where we must leave i915 in it's current
broken state, which means that anyone wanting VGA arbitration needs to
patch their kernel.  In the best case, that compatibility window could
extend for years.  Since we don't seem to be making progress on any of
the other fronts, it seemed time to propose a module switch.  It's not a
good solution, but it's better than leaving it broken.  Thanks,

Alex
Daniel Vetter May 12, 2014, 7:38 p.m. UTC | #3
On Mon, May 12, 2014 at 01:30:39PM -0600, Alex Williamson wrote:
> On Mon, 2014-05-12 at 21:08 +0200, Daniel Vetter wrote:
> > On Fri, May 09, 2014 at 02:20:41PM -0600, Alex Williamson wrote:
> > > Commit 81b5c7bc found that the current VGA arbiter support in i915
> > > only works for ancient GMCH-based IGD devices and attempted to update
> > > support for newer HD devices.  Unfortunately newer devices cannot
> > > completely opt-out of VGA arbitration like the old devices could.
> > > The VGA I/O space cannot be disabled internally.  The only way to
> > > route VGA I/O elsewhere is by disabling I/O at the device PCI command
> > > register.  This means that with commit 81b5c7bc and multiple VGA
> > > adapters, the VGA arbiter will report that multiple VGA devices are
> > > participating in arbitration, Xorg will notice this and disable DRI.
> > > Therefore, 81b5c7bc was reverted because DRI is more important than
> > > being correct.
> > > 
> > > There is however an actual need for i915 to correctly participate in
> > > VGA arbitration; VGA device assignment.  If we want to use VFIO to
> > > assign a VGA device to a virtual machine, we need to be able to
> > > access the VGA resources of that device.  By adding an i915 module
> > > option we can allow i915 to continue with its charade by default, but
> > > also allow an easy path for users who require working VGA arbitration.
> > > Hopefully Xorg can someday be taught to behave better with multiple
> > > VGA devices.
> > > 
> > > This also rolls in reverted commit 6e1b4fda, which corrected an
> > > ordering issue with 81b5c7bc by delaying the disabling of VGA memory
> > > until after vgacon->fbcon handoff.
> > > 
> > > Signed-off-by: Alex Williamson <alex.williamson@redhat.com>
> > > Cc: Ville Syrjälä <ville.syrjala@linux.intel.com>
> > > Cc: Daniel Vetter <daniel.vetter@ffwll.ch>
> > > Cc: Dave Airlie <airlied@redhat.com>
> > > ---
> > > 
> > > This should be a nop with the default module setting, so if there's
> > > any opportunity to get this into v3.15, it would be appreciated.
> > 
> > I really don't like module options to work around bugs elsewhere. It means
> > the 5 users who know about a given bug are now happen, and the 3
> > bazillion without enough clue/savy/time still suffer from problems.
> > 
> > My goal is to actually add a bit of support to the core kernel's module
> > option parsing code so that most of the options we have can spit warnings
> > into dmesg and taint the kernel.
> > 
> > Can't we fix this in any other way?
> 
> Do you have any suggestions?  I proposed creating a new VGA arbiter
> interface that would allow Xorg to mmap the legacy VGA MMIO space
> regardless of the number of VGA arbitration participants, but didn't get
> any nibbles on supporting that through the rest of the stack.  Dave
> suggested maybe he could rip out the VGA arbiter support from Xorg and
> nobody would notice.  In either case, at what point do we get to flip
> i915 to behave correctly with arbitration?  It seems like anything we do
> has a compatibility period where we must leave i915 in it's current
> broken state, which means that anyone wanting VGA arbitration needs to
> patch their kernel.  In the best case, that compatibility window could
> extend for years.  Since we don't seem to be making progress on any of
> the other fronts, it seemed time to propose a module switch.  It's not a
> good solution, but it's better than leaving it broken.  Thanks,

Ripping out the vga arbiter stuff from X (or at least disabling it if
there's only kms drivers) seems like a good start - we want that in any
case I think.

Then we could also look into disabling the userspace interface on the
kernel side if we have modeset drivers for everything, and X is the
requesting process. I.e. lie to Xorg. Ugly, but might work.

Then once we've fixed userspace to no longer be stupid and have some way
to work around old stupid userspace, we can fix i915.
-Daniel
Alex Williamson May 15, 2014, 9:43 p.m. UTC | #4
On Mon, 2014-05-12 at 21:38 +0200, Daniel Vetter wrote:
> On Mon, May 12, 2014 at 01:30:39PM -0600, Alex Williamson wrote:
> > On Mon, 2014-05-12 at 21:08 +0200, Daniel Vetter wrote:
> > > On Fri, May 09, 2014 at 02:20:41PM -0600, Alex Williamson wrote:
> > > > Commit 81b5c7bc found that the current VGA arbiter support in i915
> > > > only works for ancient GMCH-based IGD devices and attempted to update
> > > > support for newer HD devices.  Unfortunately newer devices cannot
> > > > completely opt-out of VGA arbitration like the old devices could.
> > > > The VGA I/O space cannot be disabled internally.  The only way to
> > > > route VGA I/O elsewhere is by disabling I/O at the device PCI command
> > > > register.  This means that with commit 81b5c7bc and multiple VGA
> > > > adapters, the VGA arbiter will report that multiple VGA devices are
> > > > participating in arbitration, Xorg will notice this and disable DRI.
> > > > Therefore, 81b5c7bc was reverted because DRI is more important than
> > > > being correct.
> > > > 
> > > > There is however an actual need for i915 to correctly participate in
> > > > VGA arbitration; VGA device assignment.  If we want to use VFIO to
> > > > assign a VGA device to a virtual machine, we need to be able to
> > > > access the VGA resources of that device.  By adding an i915 module
> > > > option we can allow i915 to continue with its charade by default, but
> > > > also allow an easy path for users who require working VGA arbitration.
> > > > Hopefully Xorg can someday be taught to behave better with multiple
> > > > VGA devices.
> > > > 
> > > > This also rolls in reverted commit 6e1b4fda, which corrected an
> > > > ordering issue with 81b5c7bc by delaying the disabling of VGA memory
> > > > until after vgacon->fbcon handoff.
> > > > 
> > > > Signed-off-by: Alex Williamson <alex.williamson@redhat.com>
> > > > Cc: Ville Syrjälä <ville.syrjala@linux.intel.com>
> > > > Cc: Daniel Vetter <daniel.vetter@ffwll.ch>
> > > > Cc: Dave Airlie <airlied@redhat.com>
> > > > ---
> > > > 
> > > > This should be a nop with the default module setting, so if there's
> > > > any opportunity to get this into v3.15, it would be appreciated.
> > > 
> > > I really don't like module options to work around bugs elsewhere. It means
> > > the 5 users who know about a given bug are now happen, and the 3
> > > bazillion without enough clue/savy/time still suffer from problems.
> > > 
> > > My goal is to actually add a bit of support to the core kernel's module
> > > option parsing code so that most of the options we have can spit warnings
> > > into dmesg and taint the kernel.
> > > 
> > > Can't we fix this in any other way?
> > 
> > Do you have any suggestions?  I proposed creating a new VGA arbiter
> > interface that would allow Xorg to mmap the legacy VGA MMIO space
> > regardless of the number of VGA arbitration participants, but didn't get
> > any nibbles on supporting that through the rest of the stack.  Dave
> > suggested maybe he could rip out the VGA arbiter support from Xorg and
> > nobody would notice.  In either case, at what point do we get to flip
> > i915 to behave correctly with arbitration?  It seems like anything we do
> > has a compatibility period where we must leave i915 in it's current
> > broken state, which means that anyone wanting VGA arbitration needs to
> > patch their kernel.  In the best case, that compatibility window could
> > extend for years.  Since we don't seem to be making progress on any of
> > the other fronts, it seemed time to propose a module switch.  It's not a
> > good solution, but it's better than leaving it broken.  Thanks,
> 
> Ripping out the vga arbiter stuff from X (or at least disabling it if
> there's only kms drivers) seems like a good start - we want that in any
> case I think.
> 
> Then we could also look into disabling the userspace interface on the
> kernel side if we have modeset drivers for everything, and X is the
> requesting process. I.e. lie to Xorg. Ugly, but might work.
> 
> Then once we've fixed userspace to no longer be stupid and have some way
> to work around old stupid userspace, we can fix i915.

I don't know what to do with this.  It seems like a lot of wishful
thinking that in the best case would drag on for years.  Even if we get
VGA arbitration out of Xorg, the bit about making the userspace VGA
arbiter interface lie depending on current->comm sounds tricky and
horrible.  If we can lie to Xorg there, why don't we do that now?  If we
can't lie to Xorg now, then what deprecation event or detection of the
caller is going to allow us to do so in the future?

Meanwhile anyone that wants i915 to participate in arbitration like it
should have from the start needs to patch their kernel with forward
ports of the reverted commits.

I just don't see this moving forward, which is why I thought a module
option at least gives us a workaround.  Thanks,

Alex
Daniel Vetter May 15, 2014, 10:50 p.m. UTC | #5
On Thu, May 15, 2014 at 11:43 PM, Alex Williamson
<alex.williamson@redhat.com> wrote:
> I don't know what to do with this.  It seems like a lot of wishful
> thinking that in the best case would drag on for years.  Even if we get
> VGA arbitration out of Xorg, the bit about making the userspace VGA
> arbiter interface lie depending on current->comm sounds tricky and
> horrible.  If we can lie to Xorg there, why don't we do that now?  If we
> can't lie to Xorg now, then what deprecation event or detection of the
> caller is going to allow us to do so in the future?

Well we wouldn't necessarily need to lie to X, but could instead look
whether all the vga devices in a system are claimed by kms drivers. If
that's the case the userspace doesn't have an awful lot of business
touching the VGA registers and we could simply not obey a vga arb
request from userspace.

More advanced would be if we still obey it for those devices not
claimed by kms drivers. So not really a need to key on current->comm.

> Meanwhile anyone that wants i915 to participate in arbitration like it
> should have from the start needs to patch their kernel with forward
> ports of the reverted commits.
>
> I just don't see this moving forward, which is why I thought a module
> option at least gives us a workaround.  Thanks,

I know that this is awful, but a module option means that the few
people interested in moving this forward will be happy enough to no
longer bother. Which is even worse from my pov as driver maintainer. I
highly consider module options used in production evil.
-Daniel
Alex Williamson May 16, 2014, 4:46 a.m. UTC | #6
On Fri, 2014-05-16 at 00:50 +0200, Daniel Vetter wrote:
> On Thu, May 15, 2014 at 11:43 PM, Alex Williamson
> <alex.williamson@redhat.com> wrote:
> > I don't know what to do with this.  It seems like a lot of wishful
> > thinking that in the best case would drag on for years.  Even if we get
> > VGA arbitration out of Xorg, the bit about making the userspace VGA
> > arbiter interface lie depending on current->comm sounds tricky and
> > horrible.  If we can lie to Xorg there, why don't we do that now?  If we
> > can't lie to Xorg now, then what deprecation event or detection of the
> > caller is going to allow us to do so in the future?
> 
> Well we wouldn't necessarily need to lie to X, but could instead look
> whether all the vga devices in a system are claimed by kms drivers. If
> that's the case the userspace doesn't have an awful lot of business
> touching the VGA registers and we could simply not obey a vga arb
> request from userspace.
> 
> More advanced would be if we still obey it for those devices not
> claimed by kms drivers. So not really a need to key on current->comm.

This is a requirement for me, I don't really care about KMS or Xorg, the
use case I want to enable is binding a VGA device to vfio-pci so that it
can be assigned to a guest virtual machine.  This works on an unmodified
kernel today so long as you don't have an Intel IGD in your system.  If
you do, we try to switch the VGA device, but it doesn't actually get
switched because i915 opts-out of arbitration yet still claims VGA
accesses.

> > Meanwhile anyone that wants i915 to participate in arbitration like it
> > should have from the start needs to patch their kernel with forward
> > ports of the reverted commits.
> >
> > I just don't see this moving forward, which is why I thought a module
> > option at least gives us a workaround.  Thanks,
> 
> I know that this is awful, but a module option means that the few
> people interested in moving this forward will be happy enough to no
> longer bother. Which is even worse from my pov as driver maintainer. I
> highly consider module options used in production evil.

If I had a solution, I wouldn't be sending this patch :-\  Thanks,

Alex
Daniel Vetter May 16, 2014, 9:06 a.m. UTC | #7
On Thu, May 15, 2014 at 10:46:50PM -0600, Alex Williamson wrote:
> On Fri, 2014-05-16 at 00:50 +0200, Daniel Vetter wrote:
> > On Thu, May 15, 2014 at 11:43 PM, Alex Williamson
> > <alex.williamson@redhat.com> wrote:
> > > I don't know what to do with this.  It seems like a lot of wishful
> > > thinking that in the best case would drag on for years.  Even if we get
> > > VGA arbitration out of Xorg, the bit about making the userspace VGA
> > > arbiter interface lie depending on current->comm sounds tricky and
> > > horrible.  If we can lie to Xorg there, why don't we do that now?  If we
> > > can't lie to Xorg now, then what deprecation event or detection of the
> > > caller is going to allow us to do so in the future?
> > 
> > Well we wouldn't necessarily need to lie to X, but could instead look
> > whether all the vga devices in a system are claimed by kms drivers. If
> > that's the case the userspace doesn't have an awful lot of business
> > touching the VGA registers and we could simply not obey a vga arb
> > request from userspace.
> > 
> > More advanced would be if we still obey it for those devices not
> > claimed by kms drivers. So not really a need to key on current->comm.
> 
> This is a requirement for me, I don't really care about KMS or Xorg, the
> use case I want to enable is binding a VGA device to vfio-pci so that it
> can be assigned to a guest virtual machine.  This works on an unmodified
> kernel today so long as you don't have an Intel IGD in your system.  If
> you do, we try to switch the VGA device, but it doesn't actually get
> switched because i915 opts-out of arbitration yet still claims VGA
> accesses.

I get that its a requirement for you.

I've also just detailed the solution for you above, but I'm not going to
write the patch itself (since I can't test it really).

We have two users of the vga-arb crap relevant here:
- pci/pci-sysfs.c, used by X through libpciaccess
- vfio/pci/vfio_pci_rdwr.c, for vfio-pci vga forwarding

Make the former lie if all vga devices have kms drivers and the latter
still work correctly. That will prevent X from going nasty if there are
kms drivers, while still keeping vfio going.

Then we re-re-revert the i915 to have proper vga-arb.

Afaics no need for hacks, module options, special casing or breaking old
userspace. And really, if there is a kms driver userspace has zero
business touching the vga registers, so imo we don't lose an real
functionality. You can always opt to not load kms drivers if you want
userspace access.

What am I missing?
-Daniel
Alex Williamson May 16, 2014, 2:38 p.m. UTC | #8
On Fri, 2014-05-16 at 11:06 +0200, Daniel Vetter wrote:
> On Thu, May 15, 2014 at 10:46:50PM -0600, Alex Williamson wrote:
> > On Fri, 2014-05-16 at 00:50 +0200, Daniel Vetter wrote:
> > > On Thu, May 15, 2014 at 11:43 PM, Alex Williamson
> > > <alex.williamson@redhat.com> wrote:
> > > > I don't know what to do with this.  It seems like a lot of wishful
> > > > thinking that in the best case would drag on for years.  Even if we get
> > > > VGA arbitration out of Xorg, the bit about making the userspace VGA
> > > > arbiter interface lie depending on current->comm sounds tricky and
> > > > horrible.  If we can lie to Xorg there, why don't we do that now?  If we
> > > > can't lie to Xorg now, then what deprecation event or detection of the
> > > > caller is going to allow us to do so in the future?
> > > 
> > > Well we wouldn't necessarily need to lie to X, but could instead look
> > > whether all the vga devices in a system are claimed by kms drivers. If
> > > that's the case the userspace doesn't have an awful lot of business
> > > touching the VGA registers and we could simply not obey a vga arb
> > > request from userspace.
> > > 
> > > More advanced would be if we still obey it for those devices not
> > > claimed by kms drivers. So not really a need to key on current->comm.
> > 
> > This is a requirement for me, I don't really care about KMS or Xorg, the
> > use case I want to enable is binding a VGA device to vfio-pci so that it
> > can be assigned to a guest virtual machine.  This works on an unmodified
> > kernel today so long as you don't have an Intel IGD in your system.  If
> > you do, we try to switch the VGA device, but it doesn't actually get
> > switched because i915 opts-out of arbitration yet still claims VGA
> > accesses.
> 
> I get that its a requirement for you.
> 
> I've also just detailed the solution for you above, but I'm not going to
> write the patch itself (since I can't test it really).

I repeat it because it seems incompatible with any plan that involves
modes of operation where the VGA arbiter says one thing if all VGA
devices are bound to KMS drivers and another if they're not.  That means
Xorg would have a different feature set depending on the driver state of
devices we might be using for entirely different purposes.

Users want to be able to run X on the host i915 at the same time that
they have other VGA devices assigned to guests.

> We have two users of the vga-arb crap relevant here:
> - pci/pci-sysfs.c, used by X through libpciaccess
> - vfio/pci/vfio_pci_rdwr.c, for vfio-pci vga forwarding

Do we really know that we only have these two users?

> Make the former lie if all vga devices have kms drivers and the latter

There's that "if all vga devices" again.  Is the user expected to start
Xorg with all devices attached to KMS drivers, then unbind the extra VGA
devices to be used for other purposes?  What happens if the user wants
to restart X, do they get a different feature set?  Does the output of
the VGA arbiter change while X is running when the other devices are
unbound from their KMS driver?  (unbinding a graphics card from it's
driver isn't a foolproof operation btw, so the driver may be blacklisted
or avoided through other means)

> still work correctly. That will prevent X from going nasty if there are
> kms drivers, while still keeping vfio going.

But by lying to Xorg, I think we're saying that it's ok to go mmap VGA
MMIO space through /dev/mem and poke VGA I/O through inb/outb, it's not
going to change... then at the same time we provide this other interface
that allows it to change.  Are we just masking i915's bug by breaking
the entire interface?

> Then we re-re-revert the i915 to have proper vga-arb.
> 
> Afaics no need for hacks, module options, special casing or breaking old
> userspace. 

But there is special casing isn't there?  Aren't we only able to make
the assumption that it's ok to lie through the VGA arbiter userspace
interface if only KMS drivers are in use?

> And really, if there is a kms driver userspace has zero
> business touching the vga registers, so imo we don't lose an real
> functionality. You can always opt to not load kms drivers if you want
> userspace access.
> 
> What am I missing?

I must be the one missing something because this still all sounds
terribly convoluted and fragile.  Thanks,

Alex
diff mbox

Patch

diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c
index 96177ee..c0d0c03 100644
--- a/drivers/gpu/drm/i915/i915_dma.c
+++ b/drivers/gpu/drm/i915/i915_dma.c
@@ -1306,10 +1306,20 @@  static int i915_load_modeset_init(struct drm_device *dev)
 	 * If we are a secondary display controller (!PCI_DISPLAY_CLASS_VGA),
 	 * then we do not take part in VGA arbitration and the
 	 * vga_client_register() fails with -ENODEV.
+	 *
+	 * NB.  The set_decode callback here actually only works on GMCH
+	 * devices, on newer HD devices we can only disable VGA MMIO space.
+	 * Disabling VGA I/O space requires disabling I/O in the PCI command
+	 * register.  Nonetheless, we like to pretend that we participate in
+	 * VGA arbitration and can dynamically disable VGA I/O space because
+	 * this makes X happy, even though it's a complete lie.
 	 */
-	ret = vga_client_register(dev->pdev, dev, NULL, i915_vga_set_decode);
-	if (ret && ret != -ENODEV)
-		goto out;
+	if (!i915.enable_hd_vgaarb || !HAS_PCH_SPLIT(dev)) {
+		ret = vga_client_register(dev->pdev, dev, NULL,
+					  i915_vga_set_decode);
+		if (ret && ret != -ENODEV)
+			goto out;
+	}
 
 	intel_register_dsm_handler();
 
@@ -1369,6 +1379,12 @@  static int i915_load_modeset_init(struct drm_device *dev)
 	 */
 	intel_fbdev_initial_config(dev);
 
+	/*
+	 * Must do this after fbcon init so that
+	 * vgacon_save_screen() works during the handover.
+	 */
+	i915_disable_vga_mem(dev);
+
 	/* Only enable hotplug handling once the fbdev is fully set up. */
 	dev_priv->enable_hotplug_processing = true;
 
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index ec82f6b..f3908f6 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -2080,6 +2080,7 @@  struct i915_params {
 	bool prefault_disable;
 	bool reset;
 	bool disable_display;
+	bool enable_hd_vgaarb;
 };
 extern struct i915_params i915 __read_mostly;
 
diff --git a/drivers/gpu/drm/i915/i915_params.c b/drivers/gpu/drm/i915/i915_params.c
index d1d7980..64d96c6 100644
--- a/drivers/gpu/drm/i915/i915_params.c
+++ b/drivers/gpu/drm/i915/i915_params.c
@@ -47,6 +47,7 @@  struct i915_params i915 __read_mostly = {
 	.invert_brightness = 0,
 	.disable_display = 0,
 	.enable_cmd_parser = 0,
+	.enable_hd_vgaarb = false,
 };
 
 module_param_named(modeset, i915.modeset, int, 0400);
@@ -152,3 +153,7 @@  MODULE_PARM_DESC(disable_display, "Disable display (default: false)");
 module_param_named(enable_cmd_parser, i915.enable_cmd_parser, int, 0600);
 MODULE_PARM_DESC(enable_cmd_parser,
 		 "Enable command parsing (1=enabled, 0=disabled [default])");
+
+module_param_named(enable_hd_vgaarb, i915.enable_hd_vgaarb, bool, 0444);
+MODULE_PARM_DESC(enable_hd_vgaarb,
+	"Enable support for VGA arbitration on Intel HD IGD. (default: false)");
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index 69bcc42..2cd35ba 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -11284,6 +11284,33 @@  static void i915_disable_vga(struct drm_device *dev)
 	POSTING_READ(vga_reg);
 }
 
+static void i915_enable_vga_mem(struct drm_device *dev)
+{
+	/* Enable VGA memory on Intel HD */
+	if (i915.enable_hd_vgaarb && HAS_PCH_SPLIT(dev)) {
+		vga_get_uninterruptible(dev->pdev, VGA_RSRC_LEGACY_IO);
+		outb(inb(VGA_MSR_READ) | VGA_MSR_MEM_EN, VGA_MSR_WRITE);
+		vga_set_legacy_decoding(dev->pdev, VGA_RSRC_LEGACY_IO |
+						   VGA_RSRC_LEGACY_MEM |
+						   VGA_RSRC_NORMAL_IO |
+						   VGA_RSRC_NORMAL_MEM);
+		vga_put(dev->pdev, VGA_RSRC_LEGACY_IO);
+	}
+}
+
+void i915_disable_vga_mem(struct drm_device *dev)
+{
+	/* Disable VGA memory on Intel HD */
+	if (i915.enable_hd_vgaarb && HAS_PCH_SPLIT(dev)) {
+		vga_get_uninterruptible(dev->pdev, VGA_RSRC_LEGACY_IO);
+		outb(inb(VGA_MSR_READ) & ~VGA_MSR_MEM_EN, VGA_MSR_WRITE);
+		vga_set_legacy_decoding(dev->pdev, VGA_RSRC_LEGACY_IO |
+						   VGA_RSRC_NORMAL_IO |
+						   VGA_RSRC_NORMAL_MEM);
+		vga_put(dev->pdev, VGA_RSRC_LEGACY_IO);
+	}
+}
+
 void intel_modeset_init_hw(struct drm_device *dev)
 {
 	intel_prepare_ddi(dev);
@@ -11594,6 +11621,7 @@  void i915_redisable_vga_power_on(struct drm_device *dev)
 	if (!(I915_READ(vga_reg) & VGA_DISP_DISABLE)) {
 		DRM_DEBUG_KMS("Something enabled VGA plane, disabling it\n");
 		i915_disable_vga(dev);
+		i915_disable_vga_mem(dev);
 	}
 }
 
@@ -11848,6 +11876,8 @@  void intel_modeset_cleanup(struct drm_device *dev)
 
 	intel_disable_fbc(dev);
 
+	i915_enable_vga_mem(dev);
+
 	intel_disable_gt_powersave(dev);
 
 	ironlake_teardown_rc6(dev);
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index 328b1a7..fbe5d360 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -934,4 +934,6 @@  int intel_sprite_get_colorkey(struct drm_device *dev, void *data,
 /* intel_tv.c */
 void intel_tv_init(struct drm_device *dev);
 
+extern void i915_disable_vga_mem(struct drm_device *dev);
+
 #endif /* __INTEL_DRV_H__ */
diff --git a/include/linux/vgaarb.h b/include/linux/vgaarb.h
index 2c02f3a..80cf817 100644
--- a/include/linux/vgaarb.h
+++ b/include/linux/vgaarb.h
@@ -65,8 +65,15 @@  struct pci_dev;
  *     out of the arbitration process (and can be safe to take
  *     interrupts at any time.
  */
+#if defined(CONFIG_VGA_ARB)
 extern void vga_set_legacy_decoding(struct pci_dev *pdev,
 				    unsigned int decodes);
+#else
+static inline void vga_set_legacy_decoding(struct pci_dev *pdev,
+					   unsigned int decodes)
+{
+}
+#endif
 
 /**
  *     vga_get         - acquire & locks VGA resources