1

AMD's BIOS and Kernel Developer’s Guide (BKDG) documents GMM registers and access to them:

GMMxXXXXX: GPU memory mapped registers; XXXXX specifies the hexadecimal byte address offset (this may be 2 to 5 digits) from the base address register; The base address for this space is specified by D1F0x18 [Graphics Memory Mapped Registers Base Address].

D1F0x18 has the following structure (I also add a column with values that I get):

Bits My value Description
31:18 0x3c08 BaseAddr[31:18]: base address.
17:16 0 BaseAddr[17:16]: base address.
15:4 0 BaseAddr[15:4]: base address.
3 0 prefetchable. 0=Non-prefetchable memory region.
2:1 0 base address register type. 00b=32-bit BAR. 10b=64-bit BAR.
0 0 memory space type. 0=Memory mapped base address.

How to properly access registers in the GMM space?

There are three base address fields in the D1F0x18 register, and the guide doesn't explain any further how to compile the base address. I tried to read memory (in Linux with root privileges) at the following memory offsets, but all of them return me Segmentation fault error.

printf("%02x\n", (unsigned)*(unsigned char*)0x3c08); // Base address itself
printf("%02x\n", (unsigned)*(unsigned char*)0x4378); // 0x3c08+0x770 (GMMx770)
printf("%02x\n", (unsigned)*(unsigned char*)0x4381); // 0x3c08+0x770+3

printf("%02x\n", (unsigned)*(unsigned char*)0x3c080000); // Base address appended with zeroes
printf("%02x\n", (unsigned)*(unsigned char*)0x3c080770); // plus GMMx770 offset
printf("%02x\n", (unsigned)*(unsigned char*)0x3c080773); // plus size of the GMMx770

printf("%02x\n", (unsigned)*(unsigned char*)0xf0200000); // 0x3c08 shifted left by 2 bits (so that to align 31:18 field to 16 bits)
printf("%02x\n", (unsigned)*(unsigned char*)0xf0200770); // plus GMMx770 offset
printf("%02x\n", (unsigned)*(unsigned char*)0xf0200773); // plus size GMMx770 offset

Edit

There is a source code of the Coreboot project available on the Internet. There are clear footprints that they implement access to the GMM space, but I couldn't extract the method from their code either. The code gives some clues:

  1. It looks, like they use the base address as is, i.e. it is 0x3c080000 in my case.
  2. They set bits 0 and 1 in D1F0x04 so that apparently to enable access to the device's memory area (I have both of these bits set by default).
  3. They read memory with __readfsdword. Because I am on GCC, I redefined this function as follows, but still get the Segmentation fault:
unsigned long __readfsdword(const unsigned long Offset)
{
    unsigned long value;
    __asm__ __volatile__("movl %%fs:%a[Offset], %k[value]" : [value] "=r" (value) : [Offset] "ir" (Offset));
    return value;
}

0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.