[Intel-gfx] [PATCH v4] drm/i915: Determine the stolen memory base address on gen2

Daniel Vetter daniel at ffwll.ch
Fri Oct 9 01:14:51 PDT 2015


On Thu, Oct 08, 2015 at 12:08:20PM +0300, ville.syrjala at linux.intel.com wrote:
> From: Ville Syrjälä <ville.syrjala at linux.intel.com>
> 
> There isn't an explicit stolen memory base register on gen2.
> Some old comment in the i915 code suggests we should get it via
> max_low_pfn_mapped, but that's clearly a bad idea on my MGM.
> 
> The e820 map in said machine looks like this:
> [    0.000000] BIOS-e820: [mem 0x0000000000000000-0x000000000009f7ff] usable
> [    0.000000] BIOS-e820: [mem 0x000000000009f800-0x000000000009ffff] reserved
> [    0.000000] BIOS-e820: [mem 0x00000000000ce000-0x00000000000cffff] reserved
> [    0.000000] BIOS-e820: [mem 0x00000000000dc000-0x00000000000fffff] reserved
> [    0.000000] BIOS-e820: [mem 0x0000000000100000-0x000000001f6effff] usable
> [    0.000000] BIOS-e820: [mem 0x000000001f6f0000-0x000000001f6f7fff] ACPI data
> [    0.000000] BIOS-e820: [mem 0x000000001f6f8000-0x000000001f6fffff] ACPI NVS
> [    0.000000] BIOS-e820: [mem 0x000000001f700000-0x000000001fffffff] reserved
> [    0.000000] BIOS-e820: [mem 0x00000000fec10000-0x00000000fec1ffff] reserved
> [    0.000000] BIOS-e820: [mem 0x00000000ffb00000-0x00000000ffbfffff] reserved
> [    0.000000] BIOS-e820: [mem 0x00000000fff00000-0x00000000ffffffff] reserved
> 
> That makes max_low_pfn_mapped = 1f6f0000, so assuming our stolen memory
> would start there would place it on top of some ACPI memory regions.
> So not a good idea as already stated.
> 
> The 9MB region after the ACPI regions at 0x1f700000 however looks
> promising given that the macine reports the stolen memory size to be
> 8MB. Looking at the PGTBL_CTL register, the GTT entries are at offset
> 0x1fee00000, and given that the GTT entries occupy 128KB, it looks like
> the stolen memory could start at 0x1f700000 and the GTT entries would
> occupy the last 128KB of the stolen memory.
> 
> After some more digging through chipset documentation, I've determined
> the BIOS first allocates space for something called TSEG (something to
> do with SMM) from the top of memory, and then it allocates the graphics
> stolen memory below that. Accordind to the chipset documentation TSEG
> has a fixed size of 1MB on 855. So that explains the top 1MB in the
> e820 region. And it also confirms that the GTT entries are in fact at
> the end of the the stolen memory region.
> 
> Derive the stolen memory base address on gen2 the same as the BIOS does
> (TOM-TSEG_SIZE-stolen_size). There are a few differences between the
> registers on various gen2 chipsets, so a few different codepaths are
> required.
> 
> 865G is again bit more special since it seems to support enough memory
> to hit 4GB address space issues. This means the PCI allocations will
> also affect the location of the stolen memory. Fortunately there
> appears to be the TOUD register which may give us the correct answer
> directly. But the chipset docs are a bit unclear, so I'm not 100%
> sure that the graphics stolen memory is always the last thing the
> BIOS steals. Someone would need to verify it on a real system.
> 
> I tested this on the my 830 and 855 machines, and so far everything
> looks peachy.
> 
> v2: Rewrite to use the TOM-TSEG_SIZE-stolen_size and TOUD methods
> v3: Fix TSEG size for 830
> v4: Add missing 'else' (Chris)
> 
> Tested-by: Chris Wilson <chris at chris-wilson.co.uk>
> Signed-off-by: Ville Syrjälä <ville.syrjala at linux.intel.com>

Queued for -next, thanks for the patch.
-Daniel

> ---
>  drivers/gpu/drm/i915/i915_gem_stolen.c | 92 ++++++++++++++++++++++++++++++----
>  1 file changed, 81 insertions(+), 11 deletions(-)
> 
> diff --git a/drivers/gpu/drm/i915/i915_gem_stolen.c b/drivers/gpu/drm/i915/i915_gem_stolen.c
> index 69eebc6..cdacf3f 100644
> --- a/drivers/gpu/drm/i915/i915_gem_stolen.c
> +++ b/drivers/gpu/drm/i915/i915_gem_stolen.c
> @@ -30,6 +30,9 @@
>  #include <drm/i915_drm.h>
>  #include "i915_drv.h"
>  
> +#define KB(x) ((x) * 1024)
> +#define MB(x) (KB(x) * 1024)
> +
>  /*
>   * The BIOS typically reserves some of the system's memory for the exclusive
>   * use of the integrated graphics. This memory is no longer available for
> @@ -91,24 +94,91 @@ static unsigned long i915_stolen_to_physical(struct drm_device *dev)
>  	/* Almost universally we can find the Graphics Base of Stolen Memory
>  	 * at offset 0x5c in the igfx configuration space. On a few (desktop)
>  	 * machines this is also mirrored in the bridge device at different
> -	 * locations, or in the MCHBAR. On gen2, the layout is again slightly
> -	 * different with the Graphics Segment immediately following Top of
> -	 * Memory (or Top of Usable DRAM). Note it appears that TOUD is only
> -	 * reported by 865g, so we just use the top of memory as determined
> -	 * by the e820 probe.
> +	 * locations, or in the MCHBAR.
> +	 *
> +	 * On 865 we just check the TOUD register.
> +	 *
> +	 * On 830/845/85x the stolen memory base isn't available in any
> +	 * register. We need to calculate it as TOM-TSEG_SIZE-stolen_size.
>  	 *
> -	 * XXX However gen2 requires an unavailable symbol.
>  	 */
>  	base = 0;
>  	if (INTEL_INFO(dev)->gen >= 3) {
>  		/* Read Graphics Base of Stolen Memory directly */
>  		pci_read_config_dword(dev->pdev, 0x5c, &base);
>  		base &= ~((1<<20) - 1);
> -	} else { /* GEN2 */
> -#if 0
> -		/* Stolen is immediately above Top of Memory */
> -		base = max_low_pfn_mapped << PAGE_SHIFT;
> -#endif
> +	} else if (IS_I865G(dev)) {
> +		u16 toud = 0;
> +
> +		/*
> +		 * FIXME is the graphics stolen memory region
> +		 * always at TOUD? Ie. is it always the last
> +		 * one to be allocated by the BIOS?
> +		 */
> +		pci_bus_read_config_word(dev->pdev->bus, PCI_DEVFN(0, 0),
> +					 I865_TOUD, &toud);
> +
> +		base = toud << 16;
> +	} else if (IS_I85X(dev)) {
> +		u32 tseg_size = 0;
> +		u32 tom;
> +		u8 tmp;
> +
> +		pci_bus_read_config_byte(dev->pdev->bus, PCI_DEVFN(0, 0),
> +					 I85X_ESMRAMC, &tmp);
> +
> +		if (tmp & TSEG_ENABLE)
> +			tseg_size = MB(1);
> +
> +		pci_bus_read_config_byte(dev->pdev->bus, PCI_DEVFN(0, 1),
> +					 I85X_DRB3, &tmp);
> +		tom = tmp * MB(32);
> +
> +		base = tom - tseg_size - dev_priv->gtt.stolen_size;
> +	} else if (IS_845G(dev)) {
> +		u32 tseg_size = 0;
> +		u32 tom;
> +		u8 tmp;
> +
> +		pci_bus_read_config_byte(dev->pdev->bus, PCI_DEVFN(0, 0),
> +					 I845_ESMRAMC, &tmp);
> +
> +		if (tmp & TSEG_ENABLE) {
> +			switch (tmp & I845_TSEG_SIZE_MASK) {
> +			case I845_TSEG_SIZE_512K:
> +				tseg_size = KB(512);
> +				break;
> +			case I845_TSEG_SIZE_1M:
> +				tseg_size = MB(1);
> +				break;
> +			}
> +		}
> +
> +		pci_bus_read_config_byte(dev->pdev->bus, PCI_DEVFN(0, 0),
> +					 I830_DRB3, &tmp);
> +		tom = tmp * MB(32);
> +
> +		base = tom - tseg_size - dev_priv->gtt.stolen_size;
> +	} else if (IS_I830(dev)) {
> +		u32 tseg_size = 0;
> +		u32 tom;
> +		u8 tmp;
> +
> +		pci_bus_read_config_byte(dev->pdev->bus, PCI_DEVFN(0, 0),
> +					 I830_ESMRAMC, &tmp);
> +
> +		if (tmp & TSEG_ENABLE) {
> +			if (tmp & I830_TSEG_SIZE_1M)
> +				tseg_size = MB(1);
> +			else
> +				tseg_size = KB(512);
> +		}
> +
> +		pci_bus_read_config_byte(dev->pdev->bus, PCI_DEVFN(0, 0),
> +					 I830_DRB3, &tmp);
> +		tom = tmp * MB(32);
> +
> +		base = tom - tseg_size - dev_priv->gtt.stolen_size;
>  	}
>  
>  	if (base == 0)
> -- 
> 2.4.9
> 
> _______________________________________________
> Intel-gfx mailing list
> Intel-gfx at lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/intel-gfx

-- 
Daniel Vetter
Software Engineer, Intel Corporation
http://blog.ffwll.ch


More information about the Intel-gfx mailing list