[coreboot] Intel native graphics init: Questions about GTT setup
Paul Menzel
paulepanter at users.sourceforge.net
Mon Jun 9 00:22:48 CEST 2014
Dear coreboot folks,
since Linux 3.12+ graphics stolen memory seems to be used, which causes
a regression with coreboot and native graphics init at least on the
Intel 945 based Lenovo X60 [1].
This seems to be solved by properly setting register `PGETBL_CTL` [2],
but the Linux kernel Intel graphics driver still reports a GTT (Graphics
Translation Table) related error during start-up, but everything else
seems to work.
[ 1.235640] [drm] GPU crash dump saved to /sys/class/drm/card0/error
[ 1.236583] [drm] GPU hangs can indicate a bug anywhere in the entire gfx stack, including userspace.
[ 1.236583] [drm] Please file a _new_ bug report on bugs.freedesktop.org against DRI -> DRM/Intel
[ 1.236583] [drm] drm/i915 developers can then reassign to the right component if it's not a kernel issue.
[ 1.236583] [drm] The gpu crash dump is required to analyze gpu hangs, so please always attach it.
[ 1.236583] i915: render error detected, EIR: 0x00000010
[ 1.236583] i915: page table error
[ 1.236583] i915: PGTBL_ER: 0x00000013
[ 1.236583] [drm:i915_report_and_clear_eir] *ERROR* EIR stuck: 0x00000010, masking
[ 1.236583] i915: render error detected, EIR: 0x00000010
[ 1.236583] i915: page table error
[ 1.236583] i915: PGTBL_ER: 0x00000013
Looking further into the native graphics init code for Intel IGDs, I
wonder what `setgtt()` does.
Looking at Google Link, where this was introduced, there is the code
below.
$ nl -ba src/mainboard/google/link/i915.c
[…]
95 void io_i915_WRITE32(unsigned long val, unsigned long addr)
96 {
97 if (verbose & vio)
98 printk(BIOS_SPEW, "%s: outl %08lx\n", regname(addr), val);
99 outl(addr, addrport);
100 outl(val, dataport);
101 }
102
103
104 /*
105 2560
106 4 words per
107 4 *p
108 10240
109 4k bytes per page
110 4096/p
111 2.50
112 1700 lines
113 1700 * p
114 4250.00
115 PTEs
116 */
117 static void
118 setgtt(int start, int end, unsigned long base, int inc)
119 {
120 int i;
121
122 for(i = start; i < end; i++){
123 u32 word = base + i*inc;
124 WRITE32(word|1,(i*4)|1);
125 }
126 }
[…]
349 /* GTT is the Global Translation Table for the graphics pipeline.
350 * It is used to translate graphics addresses to physical
351 * memory addresses. As in the CPU, GTTs map 4K pages.
352 * There are 32 bits per pixel, or 4 bytes,
353 * which means 1024 pixels per page.
354 * There are 4250 GTTs on Link:
355 * 2650 (X) * 1700 (Y) pixels / 1024 pixels per page.
356 * The setgtt function adds a further bit of flexibility:
357 * it allows you to set a range (the first two parameters) to point
358 * to a physical address (third parameter);the physical address is
359 * incremented by a count (fourth parameter) for each GTT in the
360 * range.
361 * Why do it this way? For ultrafast startup,
362 * we can point all the GTT entries to point to one page,
363 * and set that page to 0s:
364 * memset(physbase, 0, 4096);
365 * setgtt(0, 4250, physbase, 0);
366 * this takes about 2 ms, and is a win because zeroing
367 * the page takes a up to 200 ms. We will be exploiting this
368 * trick in a later rev of this code.
369 * This call sets the GTT to point to a linear range of pages
370 * starting at physbase.
371 */
372 setgtt(0, FRAME_BUFFER_PAGES, physbase, 4096);
373 printk(BIOS_SPEW, "memset %p to 0 for %d bytes\n",
374 (void *)graphics, FRAME_BUFFER_BYTES);
[…]
$ git grep FRAME_BUFFER src/mainboard/google/link/i915io.h
src/mainboard/google/link/i915io.h:#define FRAME_BUFFER_PAGES ((2560*1700)/1024)
src/mainboard/google/link/i915io.h:#define FRAME_BUFFER_BYTES (FRAME_BUFFER_PAGES*4096)
Looking at the code of the Lenovo X60 with the resolution of 1024×768,
instead of `FRAME_BUFFER_PAGES` = 768 it is the higher number 800.
Otherwise there are graphical corruptions on the GRUB screen.
Furthermore Vladimir’s native graphics patch up for review in Gerrit [3]
uses the code below [3].
/* Setup GTT. */
for (i = 0; i < 0x2000; i++)
{
outl((i << 2) | 1, piobase);
outl(pphysbase + (i << 12) + 1, piobase + 4);
}
This is equivalent to `setgtt(0, 8192, physbase, 4096)`. As the code
should be not hardcoded to one resolution (for example the Lenovo T60
has a different one than the Lenovo X60), the code should be dynamic.
Unfortunately, I did not find anything in the datasheet [4][5]
explaining, why this `setgtt()` is needed at all. I guess this was
figured out by tracing the Video BIOS? Ron, Denis, Peter, Vladimir, it’d
be great if you could explain that to me?
At least on Intel 945, the GTT is 256 KB big and is placed below TOLUD
into the graphics stolen memory, which is currently hardcoded to 8 MB.
So how should the pages be setup then?
Thanks,
Paul
[1] https://bugs.freedesktop.org/show_bug.cgi?id=79038
[2] http://review.coreboot.org/5927
[3] http://review.coreboot.org/#/c/5320/9/src/northbridge/intel/i945/gma.c
[4] http://www.intel.com/content/dam/www/public/us/en/documents/datasheets/mobile-945-express-chipset-datasheet.pdf
[5] https://01.org/linuxgraphics/sites/default/files/documentation/965_g35_vol_1_graphics_core_0.pdf
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 198 bytes
Desc: This is a digitally signed message part
URL: <http://www.coreboot.org/pipermail/coreboot/attachments/20140609/58fccaba/attachment.asc>
More information about the coreboot
mailing list