[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