HD Graphics framebuffer not working

Question about which tools to use, bugs, the best way to implement a function, etc should go here. Don't forget to see if your question is answered in the wiki first! When in doubt post here.
Post Reply
User avatar
Octacone
Member
Member
Posts: 1138
Joined: Fri Aug 07, 2015 6:13 am

HD Graphics framebuffer not working

Post 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.
OS: Basic OS
About: 32 Bit Monolithic Kernel Written in C++ and Assembly, Custom FAT 32 Bootloader
Gigasoft
Member
Member
Posts: 856
Joined: Sat Nov 21, 2009 5:11 pm

Re: HD Graphics framebuffer not working

Post by Gigasoft »

Here is how I map it:
What's that supposed to do? GTT entries need to point to valid DRAM addresses.
User avatar
Octacone
Member
Member
Posts: 1138
Joined: Fri Aug 07, 2015 6:13 am

Re: HD Graphics framebuffer not working

Post 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.
OS: Basic OS
About: 32 Bit Monolithic Kernel Written in C++ and Assembly, Custom FAT 32 Bootloader
Gigasoft
Member
Member
Posts: 856
Joined: Sat Nov 21, 2009 5:11 pm

Re: HD Graphics framebuffer not working

Post 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.
User avatar
Octacone
Member
Member
Posts: 1138
Joined: Fri Aug 07, 2015 6:13 am

Re: HD Graphics framebuffer not working

Post 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.
OS: Basic OS
About: 32 Bit Monolithic Kernel Written in C++ and Assembly, Custom FAT 32 Bootloader
Gigasoft
Member
Member
Posts: 856
Joined: Sat Nov 21, 2009 5:11 pm

Re: HD Graphics framebuffer not working

Post 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).
User avatar
Octacone
Member
Member
Posts: 1138
Joined: Fri Aug 07, 2015 6:13 am

Re: HD Graphics framebuffer not working

Post 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?
OS: Basic OS
About: 32 Bit Monolithic Kernel Written in C++ and Assembly, Custom FAT 32 Bootloader
Gigasoft
Member
Member
Posts: 856
Joined: Sat Nov 21, 2009 5:11 pm

Re: HD Graphics framebuffer not working

Post 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.
User avatar
Octacone
Member
Member
Posts: 1138
Joined: Fri Aug 07, 2015 6:13 am

Re: HD Graphics framebuffer not working

Post 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
OS: Basic OS
About: 32 Bit Monolithic Kernel Written in C++ and Assembly, Custom FAT 32 Bootloader
User avatar
Octacone
Member
Member
Posts: 1138
Joined: Fri Aug 07, 2015 6:13 am

Re: HD Graphics framebuffer not working

Post 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
OS: Basic OS
About: 32 Bit Monolithic Kernel Written in C++ and Assembly, Custom FAT 32 Bootloader
Korona
Member
Member
Posts: 1000
Joined: Thu May 17, 2007 1:27 pm
Contact:

Re: HD Graphics framebuffer not working

Post 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.
managarm: Microkernel-based OS capable of running a Wayland desktop (Discord: https://discord.gg/7WB6Ur3). My OS-dev projects: [mlibc: Portable C library for managarm, qword, Linux, Sigma, ...] [LAI: AML interpreter] [xbstrap: Build system for OS distributions].
User avatar
Octacone
Member
Member
Posts: 1138
Joined: Fri Aug 07, 2015 6:13 am

Re: HD Graphics framebuffer not working

Post 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
OS: Basic OS
About: 32 Bit Monolithic Kernel Written in C++ and Assembly, Custom FAT 32 Bootloader
Korona
Member
Member
Posts: 1000
Joined: Thu May 17, 2007 1:27 pm
Contact:

Re: HD Graphics framebuffer not working

Post 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).
managarm: Microkernel-based OS capable of running a Wayland desktop (Discord: https://discord.gg/7WB6Ur3). My OS-dev projects: [mlibc: Portable C library for managarm, qword, Linux, Sigma, ...] [LAI: AML interpreter] [xbstrap: Build system for OS distributions].
User avatar
Octacone
Member
Member
Posts: 1138
Joined: Fri Aug 07, 2015 6:13 am

Re: HD Graphics framebuffer not working

Post 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.
OS: Basic OS
About: 32 Bit Monolithic Kernel Written in C++ and Assembly, Custom FAT 32 Bootloader
Post Reply