Map system RAM address to GPU through the Cell FlexIO interface
status = lv1_gpu_context_iomap(ps3fb.context_handle, GPU_IOIF, xdr_lpar, ps3fb_videomemory.size, 0);
| Inputs | |
|---|---|
| Register | Description |
| R3 | ps3fb.context_handle as allocated by lv1_gpu_context_allocate |
| R4 | GPU_IOIF = 0x0d000000UL - GPU address where the system RAM virtual framebuffer is remapped |
| R5 | xdr_lpar - lpar version of the physical address of the virtual frame buffer in local memory. (Note: the lpar version = the physical address in the PS3) |
| R6 | ps3fb_videomemory.size = The size of the virtual frame buffer |
| R7 | 0 - IOPTE flags - bitfield describing protection, coherency and ordering of the I/O mapping. Any combination of 0 or 2^{11 (cache hint),59 (read ordering),60 (write ordering),61 (coherency),62 (read protection) ,63 (write protection)} seems valid |
| Outputs | |
| Register | Description |
| R3 | Status - 0 = OK, LV1_TYPE_MISMATCH (-8) if R5 set to a DDR lpar address, LV1_ILLEGAL_PARAMETER_VALUE (-17) if any other bit set in R7 than described above |
This function creates a mapping in GPU address space so that the RSX can access system RAM. The Kernel uses it to associate the virtual framebuffer residing in system RAM to the GPU, so that so that transfers can be initiated by the RSX from the system RAM to the video RAM using the lv1_gpu_context_attribute:fb_blit() call.
Comments:
It was previously suspected that GPU_IOIF was the address of GPU MMIO registers. However GPU_IOIF is a GPU address, not a lpar address, and therefore has no meaning on the Linux side, and cannot be directly mapped from the Linux address space. Reserving the memory block (using request_mem_region) and mapping (using ioremap) results in a block of memory that is used by Linux (nothing resembling IO registers was observed whilst single frame stepping a gfx demo). [was: As you’ve previously discovered that the top of RAM is 0x0e00 0000, GPU_IOIF here is 16Mb below that. That’s typically the size of the a graphics card PCI IO region on a PC, so given the name, I’d strongly suggest it’s not GPU memory that’s being mapped but the GPU IO registers. Although why this address range would overlap with RAM is a mystery.]
GPU_IOIF was successfully set to other values (0×00000000, 0×02000000, 0×04000000) with Linux booting and displaying correctly. A value of 0x0f000000 causes the PS3 to hang (need to retest 0x0e0000000)
Although it looks like GPU_IOIF would overlap video RAM, the RSX differentiates between the two by associating different DMA objects to the source and destination of the blit. The source is associated with DMA object handle 0xfeed0001 which targets system memory, while the destination is associated with DMA object handle 0xfeed0000 which targets video memory. This has been observed by analysing the FIFO commands sent to the GPU by the hypervisor during the lv1_gpu_context_attribute:fb_setup() and lv1_gpu_context_attribute:fb_blit() calls.
It seems a call to lv1_gpu_context_iomap(handle, bus_addr, xdr_lpar, size, flags) is equivalent to a series of call to lv1_put_iopte:
int i;
int context_number; /* derived from handle, 1st allocated context 0, 2nd allocated context 1, etc... */
for (i = 0; i < size; i += 1024 * 1024) {
lv1_put_iopte(0, /* IO ASID */
((0x08ULL + context_number) << 28) | bus_addr) + i, /* IO address */
xdr_lpar + i, /* Logical Partition address */
1, /* PS3_AUDIO_IOID, actually RSX IOID */
flags);
}
Tested by replacing the call to lv1_gpu_context_iomap with the code above in ps3fb.c.