[Nouveau] [PATCH] drm/nouveau: fix early vram corruption originating from vgacon
Marcin Slusarz
marcin.slusarz at gmail.com
Thu Oct 4 04:35:15 PDT 2012
On Thu, Sep 13, 2012 at 12:52:30AM +0200, Marcin Slusarz wrote:
> There's a short window between module load and fbcon initalization when
> it's possible for vgacon to write to VGA RAM. Nouveau uses this memory
> for different purposes, so if we are unlucky, it causes mysterious memory
> corruptions.
>
> For me, booting with nv_printk debug levels set to 5 was enough to trigger it.
> It manifested as long stream of:
> "trapped write at ... on channel 0x0001fea0 BAR/PFIFO_WRITE/IN reason:
> DMAOBJ_LIMIT / PT_NOT_PRESENT / PAGE_SYSTEM_ONLY / PAGE_NOT_PRESENT"
> which eventually lead to complete hang.
>
> Disabling access to VGA memory (through 0x54 PCI config space register) is
> enough to fix it, but it breaks copying screen data between old and new
> console (because old data is inaccessible). But blanking console (with
> entering_gfx==1) is enough to move vgacon screen buffer from VRAM to RAM
> and let handover to work correctly.
>
> Signed-off-by: Marcin Slusarz <marcin.slusarz at gmail.com>
> ---
> drivers/gpu/drm/nouveau/nouveau_drm.c | 31 ++++++++++++++++++++++++++++++-
> 1 file changed, 30 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/gpu/drm/nouveau/nouveau_drm.c b/drivers/gpu/drm/nouveau/nouveau_drm.c
> index 6826525..1641bd9 100644
> --- a/drivers/gpu/drm/nouveau/nouveau_drm.c
> +++ b/drivers/gpu/drm/nouveau/nouveau_drm.c
> @@ -25,6 +25,7 @@
> #include <linux/console.h>
> #include <linux/module.h>
> #include <linux/pci.h>
> +#include <linux/vt_kern.h>
>
> #include <core/device.h>
> #include <core/client.h>
> @@ -51,6 +52,8 @@
>
> #include "nouveau_ttm.h"
>
> +#define NV_PCI_VGAMEM_ENABLE 0x54
> +
> MODULE_PARM_DESC(config, "option string to pass to driver core");
> static char *nouveau_config;
> module_param_named(config, nouveau_config, charp, 0400);
> @@ -247,9 +250,20 @@ nouveau_drm_load(struct drm_device *dev, unsigned long flags)
> struct nouveau_drm *drm;
> int ret;
>
> + /* Blank initial console to prevent VRAM corruption while we initialize
> + * the HW. For vgacon it will move console memory from VGA VRAM to RAM.
> + */
> + console_lock();
> + do_blank_screen(1);
> + console_unlock();
> +
> + /* Completely disable access to VGA IO/memory, just to be sure no one
> + * will change it. */
> + pci_write_config_byte(pdev, NV_PCI_VGAMEM_ENABLE, 0);
> +
> ret = nouveau_cli_create(pdev, "DRM", sizeof(*drm), (void**)&drm);
> if (ret)
> - return ret;
> + goto fail_cli;
>
> dev->dev_private = drm;
> drm->dev = dev;
> @@ -336,6 +350,11 @@ nouveau_drm_load(struct drm_device *dev, unsigned long flags)
>
> nouveau_accel_init(drm);
> nouveau_fbcon_init(dev);
> +
> + console_lock();
> + do_unblank_screen(1);
> + console_unlock();
> +
> return 0;
>
> fail_dispinit:
> @@ -351,12 +370,20 @@ fail_ttm:
> nouveau_vga_fini(drm);
> fail_device:
> nouveau_cli_destroy(&drm->client);
> +fail_cli:
> + pci_write_config_byte(pdev, NV_PCI_VGAMEM_ENABLE, 1);
> +
> + console_lock();
> + do_unblank_screen(1);
> + console_unlock();
> +
> return ret;
> }
>
> static int
> nouveau_drm_unload(struct drm_device *dev)
> {
> + struct pci_dev *pdev = dev->pdev;
> struct nouveau_drm *drm = nouveau_drm(dev);
>
> nouveau_fbcon_fini(dev);
> @@ -375,6 +402,8 @@ nouveau_drm_unload(struct drm_device *dev)
> nouveau_vga_fini(drm);
>
> nouveau_cli_destroy(&drm->client);
> +
> + pci_write_config_byte(pdev, NV_PCI_VGAMEM_ENABLE, 1);
> return 0;
> }
>
> --
What's up with this patch?
More information about the Nouveau
mailing list