Page 1 of 1

HD Graphics framebuffer not working

Posted: Sat Dec 05, 2020 3:34 pm
by Octacone
Still working on my HD Graphics driver.
I've spent months debugging it, without any luck.
All the bugs have been fixed and I can set any mode I want.
I just can't get it to plot pixels. No matter what I do.

This code should make my display pink (or light blue). It doesn't!

Code: Select all

framebuffer = (uint32_t*) BAR_2; //(0xB0000000 on my PC)
for(uint32_t x = 0; x < 1920; x++)
{
        for(uint32_t y = 0; y < 1080; y++)
        {
               framebuffer[(y * 1920) + x] = 0xFFABCDFF;
        }
}
This code sets the framebuffer address offset to 0.

Code: Select all

plane_surface_1_A[0] = 0;
plane_surface_1_A:
Intel Manuals wrote: It represents an offset from
the graphics memory aperture base and is mapped to physical pages through the global GTT.
the graphics memory aperture base == BAR_2 afaik

Here is how I map it:

Code: Select all

uint64_t* GTT = (uint64_t*) (MMIO_address + 0x800000);  //each page (entry) is 8 Bytes long and maps 4096 bytes of RAM
for(uint32_t i = 0; i < (1920 * 1080 * 4); i += 4096)
{
       GTT[(BAR_2 + i) / 4096] = (BAR_2 + i) | (1 << 0);
}
//also tried this GTT[i / 4096] = (BAR_2 + i) | (1 << 0);
//and this GTT[i / 4096] = i | (1 << 0);
Any help would be appreciated.

Re: HD Graphics framebuffer not working

Posted: Sat Dec 05, 2020 6:14 pm
by Gigasoft
Here is how I map it:
What's that supposed to do? GTT entries need to point to valid DRAM addresses.

Re: HD Graphics framebuffer not working

Posted: Sun Dec 06, 2020 12:14 pm
by Octacone
Gigasoft wrote:
Here is how I map it:
What's that supposed to do? GTT entries need to point to valid DRAM addresses.
Honestly I have no idea.
What I know is that Linux sets the PLANE_SURF_1_A register to 0x04c40000 (entry 0x04c40000 / 4096 in GTT) and that entry points to 0x000000020b0f801b (ignore the last 3 bytes).
That region is 16 MiB in size and ends with 0x05c3c000 (0x000000020833e01b)

I don't know what my GTT entries should point to.
I know for a fact that GTT maps a 4 GiB virtual address space (8 MiB worth of 8 byte entries, each entry maps 4K of RAM).
What do the virtual GTT addresses point to? As far as I can tell they point to some physical addresses in RAM (and they support PAE).

The question is,
If I set my PLANE_SURFACE_1_A to 0. Then what should GTT[0] point to, in order for me to be able to access the framebuffer?
I tried setting GTT[0] to BAR_2 and then writing directly to BAR_2 but it doesn't work.

Re: HD Graphics framebuffer not working

Posted: Sun Dec 06, 2020 5:55 pm
by Gigasoft
GTT entries need to point to RAM. Setting a GTT entry equal to BAR 2 won't accomplish anything, since that's not a RAM address. You can use any address marked as available in the E820 memory map, as well as addresses within the DSM area.

Re: HD Graphics framebuffer not working

Posted: Sun Dec 06, 2020 6:31 pm
by Octacone
Gigasoft wrote:GTT entries need to point to RAM. Setting a GTT entry equal to BAR 2 won't accomplish anything, since that's not a RAM address. You can use any address marked as available in the E820 memory map, as well as addresses within the DSM area.
Okay,
So I allocated 8 MiB of RAM for my framebuffer. I set the PLANE_SURFACE_1_A to 0x80000 (has to be 256 KiB aligned address) and made GTT[(0x80000 + i) / 4096] equal to that 8 MiB of RAM.
Now I tried the following: (fbn = 8 MiB chunk of RAM)
framebuffer = (uint32_t*) (BAR_2 + fbn);
framebuffer = (uint32_t*) (fbn);
None of it worked. There has to be a catch.

Re: HD Graphics framebuffer not working

Posted: Sun Dec 06, 2020 7:51 pm
by Gigasoft
If bit 2 of the GTT entry is set, the memory must be accessed by its address in main memory. If it is clear, the memory must be accessed by its virtual address through the Graphics Memory Aperture (i.e. BAR_2 + 0x80000).

Re: HD Graphics framebuffer not working

Posted: Mon Dec 07, 2020 3:20 am
by Octacone
Gigasoft wrote:If bit 2 of the GTT entry is set, the memory must be accessed by its address in main memory. If it is clear, the memory must be accessed by its virtual address through the Graphics Memory Aperture (i.e. BAR_2 + 0x80000).
I have a Kaby Lake with HD 630 and per manual bits 1-11 are ignored.
According to you,
If I do this:
plane_surface_1_A[0] = 0x00080000;
GTT[(0x00080000 + i) / 4096] = (fbn + i) | (1 << 0);
framebuffer = (uint32_t*) (BAR_2 + 0x800000);
I should be able to plot pixels.

It still doesn't work. What is the purpose of mapping those 8 MiB and pointing 0x80000 to them?
Maybe GTT[(0x00080000 + i) / 4096] = (fbn + i) | (1 << 0); is not correct and it should point to somewhere else?

Re: HD Graphics framebuffer not working

Posted: Mon Dec 07, 2020 7:58 am
by Gigasoft
Ah, I see. On Kaby Lake I think you always just access graphics memory through BAR 2, but you are using the wrong offset. It should be 0x80000, the virtual address where you placed it.

Re: HD Graphics framebuffer not working

Posted: Mon Dec 07, 2020 11:36 am
by Octacone
Gigasoft wrote:Ah, I see. On Kaby Lake I think you always just access graphics memory through BAR 2, but you are using the wrong offset. It should be 0x80000, the virtual address where you placed it.
Sorry, that was a typo, yes it is 0x80000.
In theory I should be able to write to BAR_2 + 0x80000 (offset chosen in PLANE_SURF_1_A) directly and have something displayed on the screen.
In practice it doesn't do anything.
I still have no idea what I should map 0x80000 to, and what difference will it make in relation to the framebuffer. 8-[
At this point I'm just trying random values. lol

Re: HD Graphics framebuffer not working

Posted: Tue Dec 08, 2020 6:57 am
by Octacone
New findings:
Looks like BAR_2 and stolen memory are not the same thing.
After some digging it looks as if stolen memory begins at 0x7C00000 and BAR_2 is at 0xB0000000.
That is why I was seeing 0x7C000001 entries at GTT[0].
The more I learn the less I know.
Now I just need to find out how to tie everything together.
There is a library called libgfxinit that has some super relevant code and it is written in SPARK. :x

Re: HD Graphics framebuffer not working

Posted: Tue Dec 08, 2020 9:30 am
by Korona
BAR 2 just allows you access to whatever is mapped in your GTT (whether that's stolen memory that is set up by the BIOS or GTT entires that you initialized in your driver).

Loosely speaking: the GTT is a page table and BAR2 is a virtual address space.

Re: HD Graphics framebuffer not working

Posted: Tue Dec 08, 2020 12:21 pm
by Octacone
Korona wrote:BAR 2 just allows you access to whatever is mapped in your GTT (whether that's stolen memory that is set up by the BIOS or GTT entires that you initialized in your driver).

Loosely speaking: the GTT is a page table and BAR2 is a virtual address space.
Correct me if I'm wrong:

PLANE_SURF_1_A = some_virtual_address_in_GTT (has to be 256 KB aligned as per manual)

GTT[some_virtual_address_in_GTT / 4096] = any_physical_address_in_RAM (this can be stolen memory too)

framebuffer = BAR_2 + any_physical_address_in_RAM

Re: HD Graphics framebuffer not working

Posted: Tue Dec 08, 2020 12:31 pm
by Korona
Octacone wrote:framebuffer = BAR_2 + any_physical_address_in_RAM
What do you mean by that last line?
If you set PLANE_SURF_1_A to x, you can access the framebuffer (from the host CPU) by accessing BAR2 + x (assuming that the GTT maps RAM to that location).

Re: HD Graphics framebuffer not working

Posted: Fri Dec 11, 2020 11:20 am
by Octacone
Korona wrote:
Octacone wrote:framebuffer = BAR_2 + any_physical_address_in_RAM
What do you mean by that last line?
If you set PLANE_SURF_1_A to x, you can access the framebuffer (from the host CPU) by accessing BAR2 + x (assuming that the GTT maps RAM to that location).
Oh, oh, oh! Did not know that!
Since I set my PLANE_SURF_1_A to 0x80000 I should be accessing my framebuffer with BAR_2 + 0x80000. Got you!
What should 0x80000 be mapped to:
BAR_2 + stolen_memory?
stolen_memory?
BAR_2 + 0x8000?
BAR_2 + 0x8000 + stolen_memory?
stolen_memory + 0x80000?
0x8000?
That part is still not fully clear to me.