Editing Hypervisor Reverse Engineering
Jump to navigation
Jump to search
The edit can be undone. Please check the comparison below to verify that this is what you want to do, and then publish the changes below to finish undoing the edit.
Latest revision | Your text | ||
Line 1: | Line 1: | ||
This is a copy of the page from 22nd of February 2011, right before ps3wiki.lan.st went down. | |||
= LPAR Memory Management = | |||
= | |||
== Memory Region class == | |||
This class is the base class for different memory region types. | |||
= | === vtable === | ||
0x003578B0 (3.15) | |||
= | === Member variables === | ||
LPAR | offset 0x40 - pointer to LPAR object that owns this memory region | ||
offset 0x48 - type of memory region (8 bytes) | |||
offset 0x50 - LPAR start address of memory region | |||
offset 0x58 - size of memory region (8 bytes) | |||
offset 0x60 - flags (8 bytes) | |||
offset 0xA0 - log2 of page size | |||
=== Generating New LPAR Memory Region Addresses === | |||
generate_new_lpar_mem_region_address(?, memory region size, log2(page size), ?, ?) - 002C82E8 (3.15) | |||
generate_new_lpar_mem_region_address - 002C6570 (3.41) | |||
*The function returns a new LPAR memory region address. | |||
*This method is used e.g. in all HV calls which create any kind of memory regions, e.g. '''lv1_allocate_memory''', '''lv1_map_htab''', '''lv1_undocumented_function_114''', '''lv1_construct_logical_spe''', '''lv1_map_device_mmio_region''' or '''syscall 0x10040'''. | |||
==== Encoding LPAR Memory Region Start Addresses and Sizes ==== | |||
*Size of LPAR memory region is encoded in the LPAR memory region start address. | |||
*That is why e.g. the LPAR Memory Region Start Addresses of LPAR Memory Region of size 4096 byte begin with '''0x300000000000''', '''0x300000000000 >> 42 = 0xC = log2(4096)'''. | |||
*Each LPAR has a counter (8 bytes) which is incremented by 1 every time a new LPAR Memory Region is created. | |||
*Before incrementing, the counter is shifted left by '''log2(LPAR Memory Region Size)''' and ored with '''log2(LPAR Memory Region Size) << 42'''. | |||
LPAR Memory Region Start Address >> 42 = log2(LPAR Memory Region Size) | |||
LPAR Memory Region Start Address = (log2(LPAR Memory Region Size) << 42) | | |||
(counter << log2(LPAR Memory Region Size)) | |||
===== LPAR Memory Region Address Counter ===== | |||
*LPAR Memory Region Address Counter is stored at address: '''0x38(LPAR ptr) + 0x9E8''' | |||
*LPAR1's Memory Region Address Counter is at address '''0x00677A48''' in HV dump 3.15 | |||
*LPAR2's Memory Region Address Counter is at address '''0x007632D8''' in HV dump 3.15 | |||
*LPAR1's Memory Region Address Counter is at address '''0x00677A48''' in HV dump 3.41 | |||
*LPAR2's Memory Region Address Counter is at address '''0x00161E68''' in HV dump 3.41 | |||
== | == Physical Memory Region class == | ||
This type of memory region is created e.g. in '''lv1_allocate_memory''' HV call or in '''syscall 0x10000'''. | |||
=== vtable === | |||
0x00357D08 (3.15) | |||
=== Member variables === | |||
offset 0xB0 - pointer to object that stores a list of addresses of physical pages owned by this memory region | |||
offset | offset 0xB8 - pointer to LPAR object that owns this memory region | ||
offset | offset 0xC0 - reference counter (8 bytes) | ||
=== Objects === | |||
Here is the list of physical memory region objects i found in HV 3.15. | |||
= | {| class="wikitable FCK__ShowTableBorders" | ||
|- | |||
! Address in HV dump | |||
! LPAR id | |||
! LPAR Start Address | |||
! Size | |||
! Flags | |||
! log2(Page Size) | |||
! Physical Page Addresses | |||
|- | |||
| 0x006B5510 | |||
| 1 | |||
| 0x300000001000 | |||
| 0x1000 | |||
| 0x0 | |||
| 0xC | |||
| 0x672000 | |||
|- | |||
| 0x006B5E50 | |||
| 1 | |||
| 0x440000040000 | |||
| 0x20000 | |||
| 0x0 | |||
| 0x11 | |||
| 0x6C0000 | |||
|- | |||
| 0x006B6980 | |||
| 1 | |||
| 0x440000060000 | |||
| 0x20000 | |||
| 0x0 | |||
| 0x11 | |||
| 0x6E0000 | |||
|- | |||
| 0x006B7F00 | |||
| 1 | |||
| 0x400000040000 | |||
| 0x10000 | |||
| 0x0 | |||
| 0x10 | |||
| 0x100000 | |||
|- | |||
| 0x003A80F0 | |||
| 2 | |||
| 0x6C0058000000 | |||
| 0x7000000 | |||
| 0x4 | |||
| 0x18 | |||
| 0x1000000 - 0x7000000 | |||
|- | |||
| 0x003BE800 | |||
| 2 | |||
| 0x300000047000 | |||
| 0x1000 | |||
| 0x0 | |||
| 0xC | |||
| 0x1FA000 | |||
|- | |||
| 0x006BDAA0 | |||
| 2 | |||
| 0x0 | |||
| 0x8000000 | |||
| 0x8 | |||
| 0x1B (single huge page) | |||
| 0x8000000 | |||
|} | |||
So, Linux kernel should be located at physical address 0x8000000 and Linux syscall handler at 0x8000C00. Too bad that the HV dump is not large enough. | |||
=== GameOS Physical Memory Regions === | |||
*GameOS allocates nearly all physical memory of PS3 for itself !!! That is why new HV calls '''lv1_allocate_memory''' with large memory region sizes will fail. | |||
*So when someone wants a large piece of physical memory, he can borrow it from GameOS's LPAR memory region that starts at '''0x700020000000'''. It can be used for example to send update packages to Update Manager which are very large. | |||
Here is the list of physical memory regions of GameOS i found in HV 3.41: | |||
{| class="wikitable FCK__ShowTableBorders" | |||
|- | |||
! Start Address | |||
! Size | |||
! Access Right | |||
! Max Page Size | |||
! Flags | |||
! Real Addresses | |||
|- | |||
| 0x0 | |||
| 0x1000000 | |||
| 0x3 | |||
| 0x18 | |||
| 0x8 | |||
| 0x1000000 - 0x1FFF000 | |||
|- | |||
| 0x500000300000 | |||
| 0xA0000 | |||
| 0x3 | |||
| 0x10 | |||
| 0x8 | |||
| 0x380000 - 0x38F000, 0x3B0000 - 0x3BF000, 0x1E0000 - 0x1FF000, 0x3C0000 - 0x3FF000, 0xFF00000 - 0xFF1F000 | |||
|- | |||
| 0x700020000000 | |||
| 0xE900000 (huge memory region) | |||
| 0x3 | |||
| 0x14 | |||
| 0x0 | |||
| 0x400000 - 0x5FF000, 0x800000 - 0xFFF000, 0x2000000 - 0xFEFF000 | |||
|} | |||
== | == HTAB Memory Region class == | ||
lv1_map_htab | This memory region is created when a HTAB is mapped into LPAR's address space. It's created in '''lv1_map_htab''' HV call. | ||
=== vtable === | |||
0x00357C98 (3.15) | |||
=== Member variables === | |||
offset 0xB0 - pointer to VAS object that owns the HTAB | |||
=== Objects === | |||
Here is the list of HTAB memory region objects i found in HV 3.15. | |||
{| class="wikitable FCK__ShowTableBorders" | |||
|- | |||
! Address in HV dump | |||
! LPAR id | |||
! VAS id | |||
! LPAR Start Address | |||
! Size | |||
! Flags | |||
! log2(Page Size) | |||
|- | |||
| 0x001FE0F0 | |||
| 2 | |||
| 3 | |||
| 0x500000C00000 | |||
| 0x100000 | |||
| 0xC000000000000000 | |||
| 0x14 | |||
|- | |||
| 0x003BD850 | |||
| 2 | |||
| 3 | |||
| 0x500004300000 | |||
| 0x100000 | |||
| 0xC000000000000000 | |||
| 0x14 | |||
|- | |||
| 0x003BDEA0 | |||
| 2 | |||
| 3 | |||
| 0x500004500000 | |||
| 0x100000 | |||
| 0xC000000000000000 | |||
| 0x14 | |||
|} | |||
=== GameOS HTAB === | |||
*HTAB of GameOS is already mapped into address space of GameOS so that is why HV call '''lv1_map_htab''' will fail until you unmap it with '''lv1_unmap_htab''' | |||
*Effective address of GameOS HTAB is '''0x800000000F000000''' | |||
*Virtual address of GameOS HTAB is '''0xF000000''' | |||
*Size of GameOS HTAB is '''0x40000''' | |||
*GameOS HTAB supports large pages of size '''64K''' and '''1M''' | |||
*GameOS HTAB can be easily dumped by reading 0x40000 bytes at EA 0x800000000F000000 | |||
=== GameOS SLB === | |||
Here is the dump of SLB entries from GameOS 3.41: | |||
<pre>0x8000000008000000 0x0000000000000500 | |||
0x8000000208000000 0x0000000000020500 | |||
0x8000000300000000 0x0000000000030510 | |||
0x0000000000000000 0x0000000000000000 | |||
0x0000000080000000 0x0000000000038C00 | |||
0x00000000A0000000 0x000000000003AC00 | |||
0x00000000C0000000 0x000000000003CC00 | |||
0x0000000000000000 0x0000000000000000 | |||
0x0000000000000000 0x0000000000000000 | |||
0x0000000000000000 0x0000000000000000 | |||
0x0000000000000000 0x0000000000000000 | |||
0x0000000000000000 0x0000000000000000 | |||
0x0000000000000000 0x0000000000000000 | |||
0x0000000000000000 0x0000000000000000 | |||
0x0000000000000000 0x0000000000000000 | |||
0x0000000000000000 0x0000000000000000 | |||
0x0000000000000000 0x0000000000000000 | |||
0x0000000000000000 0x0000000000000000 | |||
0x0000000000000000 0x0000000000000000 | |||
0x0000000000000000 0x0000000000000000 | |||
0x0000000000000000 0x0000000000000000 | |||
0x0000000000000000 0x0000000000000000 | |||
0x0000000000000000 0x0000000000000000 | |||
0x0000000000000000 0x0000000000000000 | |||
0x0000000000000000 0x0000000000000000 | |||
0x0000000000000000 0x0000000000000000 | |||
0x0000000000000000 0x0000000000000000 | |||
0x0000000000000000 0x0000000000000000 | |||
0x0000000000000000 0x0000000000000000 | |||
0x0000000000000000 0x0000000000000000 | |||
0x0000000000000000 0x0000000000000000 | |||
0x0000000000000000 0x0000000000000000 | |||
0x8000000010057960 0x8000000000313E78 | |||
0x8000000010057940 0x0000000000000000 | |||
0x800000000001B698 0x0000000000000000 | |||
0x8000000010057930 0x8000000000490708 | |||
0x80000000002B6C68 0x80000000003DE928 | |||
0x8000000010057EC0 0x80000000003DE920 | |||
0x0000000000000000 0x8000000000309810 | |||
0x80000000004B3000 0x0000000000000000 | |||
0x8000000010057CC0 0x0000000000000000 | |||
0x80000000004AF000 0x80000000004E1F00 | |||
0x80000000100579C8 0x80000000100579C0 | |||
0x80000000100579E0 0x2400002200000000 | |||
0x80000000004CF5B0 0x8000000200012000 | |||
0x80000000100579F8 0x80000000100579F0 | |||
0x8000000010057A10 0x80000000004A3A00 | |||
0x80000000004CF5B0 0x80000000004C8D00 | |||
0x800000000001BF6C 0x80000000004CD400 | |||
0x800000000001B698 0x80000000004C8100 | |||
0x80000000100579D0 0x80000000004B48C0 | |||
0x0000000000001C08 0x0000000000000000 | |||
0x8000000010057A78 0x8000000010057A70 | |||
0x8000000010057A90 0x0000000000000000 | |||
0x80000000004CF90C 0x0000000000000000 | |||
0x0000000000000000 0x8000000010057A80 | |||
0x8000000010057A90 0x8000000000309810 | |||
0x80000000004CF62C 0x0000000000000000 | |||
0x8000000010057CC0 0x0000000000000000 | |||
0x80000000004AF000 0x80000000004B48C0 | |||
0x00004000001C0000 0x0000000000000001 | |||
0x00000000D0000000 0x0000A8E3EE7D10DA | |||
0x0000000000000000 0x0000000000000000 | |||
0x80000000004D8088 0x80000000004D9000 | |||
</pre> | |||
== SPE MMIO Memory Region class == | |||
This type of memory region represents MMIO memory region of a SPE. It's created e.g. in '''lv1_construct_logical_spe''' or in '''syscall 0x10040'''. | |||
=== vtable === | |||
0x003583F8 (3.15) | |||
=== Member variables === | |||
=== Objects === | |||
Here is the list of SPE memory region objects i found in HV 3.15. | |||
{| class="wikitable FCK__ShowTableBorders" | |||
|- | |||
! Address in HV dump | |||
! LPAR id | |||
! SPE | |||
! LPAR Start Address | |||
! Size | |||
! Physical Address | |||
! Flags | |||
! log2(Page Size) | |||
|- | |||
| 0x003ABC20 | |||
| 2 | |||
| 1 | |||
| 0x4C0000880000 | |||
| 0x80000 | |||
| 0x20000080000 | |||
| 0xA000000000000000 | |||
| 0xC | |||
|- | |||
| 0x003AAD70 | |||
| 2 | |||
| 2 | |||
| 0x4C0000980000 | |||
| 0x80000 | |||
| 0x20000100000 | |||
| 0xA000000000000000 | |||
| 0xC | |||
|- | |||
| 0x003A8880 | |||
| 2 | |||
| 3 | |||
| 0x4C0000780000 | |||
| 0x80000 | |||
| 0x20000180000 | |||
| 0xA000000000000000 | |||
| 0xC | |||
|- | |||
| 0x003B4F70 | |||
| 2 | |||
| 4 | |||
| 0x4C0000A80000 | |||
| 0x80000 | |||
| 0x20000200000 | |||
| 0xA000000000000000 | |||
| 0xC | |||
|- | |||
| 0x003AB700 | |||
| 2 | |||
| 5 | |||
| 0x4C0000680000 | |||
| 0x80000 | |||
| 0x20000280000 | |||
| 0xA000000000000000 | |||
| 0xC | |||
|- | |||
| 0x003B5BE0 | |||
| 2 | |||
| 6 | |||
| 0x4C0000B80000 | |||
| 0x80000 | |||
| 0x20000300000 | |||
| 0xA000000000000000 | |||
| 0xC | |||
|} | |||
== SPE Shadow Registers Memory Region class == | |||
This type of memory region represents shadow registers memory region of a SPE. It's created e.g. in '''lv1_construct_logical_spe''' or in '''syscall 0x10040'''. | |||
=== vtable === | |||
0x00358448 (3.15) | |||
=== Objects === | |||
Here is the list of SPE Shadow Registers memory region objects i found in HV 3.15. | |||
{| class="wikitable FCK__ShowTableBorders" | |||
|- | |||
! Address in HV dump | |||
! LPAR id | |||
! SPE | |||
! LPAR Start Address | |||
! Size | |||
! Physical Address | |||
! Flags | |||
! log2(Page Size) | |||
|- | |||
| 0x003ABDA0 | |||
| 2 | |||
| 1 | |||
| 0x300000012000 | |||
| 0x1000 | |||
| - | |||
| 0xA000000000000000 | |||
| 0xC | |||
|- | |||
| 0x003B4290 | |||
| 2 | |||
| 2 | |||
| 0x300000014000 | |||
| 0x1000 | |||
| - | |||
| 0xA000000000000000 | |||
| 0xC | |||
|- | |||
| 0x003A8A00 | |||
| 2 | |||
| 3 | |||
| 0x300000010000 | |||
| 0x1000 | |||
| - | |||
| 0xA000000000000000 | |||
| 0xC | |||
|- | |||
| 0x003B50F0 | |||
| 2 | |||
| 4 | |||
| 0x300000016000 | |||
| 0x1000 | |||
| - | |||
| 0xA000000000000000 | |||
| 0xC | |||
|- | |||
| 0x001FFC90 | |||
| 2 | |||
| 5 | |||
| 0x30000000E000 | |||
| 0x1000 | |||
| - | |||
| 0xA000000000000000 | |||
| 0xC | |||
|- | |||
| 0x003AE5B0 | |||
| 2 | |||
| 6 | |||
| 0x300000018000 | |||
| 0x1000 | |||
| - | |||
| 0xA000000000000000 | |||
| 0xC | |||
|} | |||
== Device MMIO Memory Region class == | |||
This type of memory region is created when a device MMIO region is mapped into LPAR address space, e.g. in '''lv1_map_device_mmio_region'''. | |||
=== vtable === | |||
0x00352468 (3.15) | |||
=== Member variables === | |||
offset 0xA8 - physical address where the device MMIO region is mapped to | |||
=== Objects === | |||
Here is the list of Device MMIO memory region objects i found in HV 3.15. | |||
{| class="wikitable FCK__ShowTableBorders" | |||
|- | |||
! Address in HV dump | |||
! LPAR id | |||
! LPAR Start Address | |||
! Size | |||
! Flags | |||
! log2(Page Size) | |||
! Physical Address | |||
! Device | |||
|- | |||
| 0x001FDF00 | |||
| 2 | |||
| 0x4000001D0000 | |||
| 0x10000 | |||
| 0x8000000000000000 | |||
| 0xC | |||
| 0x24003010000 | |||
| USB controller | |||
|- | |||
| 0x003B3850 | |||
| 2 | |||
| 0x400000200000 | |||
| 0x10000 | |||
| 0x8000000000000000 | |||
| 0xC | |||
| 0x24003020000 | |||
| USB controller | |||
|- | |||
| 0x003B6E50 | |||
| 2 | |||
| 0x4000001E0000 | |||
| 0x10000 | |||
| 0x8000000000000000 | |||
| 0xC | |||
| 0x24003810000 | |||
| USB controller | |||
|- | |||
| 0x003B9950 | |||
| 2 | |||
| 0x4000001F0000 | |||
| 0x10000 | |||
| 0x8000000000000000 | |||
| 0xC | |||
| 0x24003820000 | |||
| USB controller | |||
|} | |||
== GPU Device Memory Region class == | |||
This type of memory region is created e.g. in '''lv1_gpu_open''', '''lv1_gpu_device_map''' and '''lv1_undocumented_function_114'''. | |||
=== vtable === | |||
0x00357C48 (3.15) | |||
=== Member variables === | |||
offset 0xA8 - physical address | |||
=== Objects === | |||
Here is the list of Device GPU memory region objects i found in HV 3.15. | |||
= | {| class="wikitable FCK__ShowTableBorders" | ||
|- | |||
! Address in HV dump | |||
! LPAR id | |||
! LPAR Start Address | |||
! Size | |||
! Flags | |||
! log2(Page Size) | |||
! Physical Address | |||
|- | |||
| 0x003AF380 | |||
| 2 | |||
| 0x700190000000 | |||
| 0xFE00000 | |||
| 0x8000000000000000 | |||
| 0x14 | |||
| 0x28080000000 | |||
|- | |||
| 0x003AF500 | |||
| 2 | |||
| 0x4000001A0000 | |||
| 0xC000 | |||
| 0x8000000000000000 | |||
| 0xC | |||
| 0x3C0000 | |||
|- | |||
| 0x003AF680 | |||
| 2 | |||
| 0x4800006C0000 | |||
| 0x40000 | |||
| 0x8000000000000000 | |||
| 0xC | |||
| 0x2808FE00000 | |||
|- | |||
| 0x003AFC30 | |||
| 2 | |||
| 0x440000380000 | |||
| 0x20000 | |||
| 0x8000000000000000 | |||
| 0xC | |||
| 0x28000C00000 | |||
|- | |||
| 0x003BB420 | |||
| 2 | |||
| 0x3C0000108000 | |||
| 0x8000 | |||
| 0x8000000000000000 | |||
| 0xC | |||
| 0x28000080100 | |||
|} | |||
== | == Direct Map Memory Region class == | ||
This type of memory region is created in HV call '''lv1_undocumented_function_114'''. | |||
'''lv1_undocumented_function_114''' allows you to map any memory address into LPAR's memory address. | |||
* The HV call '''lv1_undocumented_function_115''' destroys a memory region of this type. | |||
* HV allows GameOS to create objects of this type of size 0 only !!! But it can be exploited with a dangling HTAB entry. | |||
=== vtable === | |||
0x00357C48 (3.15) | |||
=== Member variables === | |||
offset | offset 0xA8 - physical address | ||
=== Exploiting HV with memory glitching and HV call lv1_undocumented_function_114 === | |||
Here is a short description of the method i used to exploit HV from GameOS 3.15 and 3.41. | |||
* First i used the Geohot's method to create a dangling HTAB entry. | |||
* Making memory glitch work on GameOS was the largest of my obstacles but i solved it and i'm able to create a dangling HTAB entry from GameOS within 1-3 minutes. | |||
* Then i created many '''Direct Map Memory Region''' objects of size 0 with HV call '''lv1_undocumented_function_114''' and checked if they are within the page to which the dangling HTAB entry points to. | |||
* When i found one such '''Direct Map Memory Region''' object i patched the size of this object to 0x1000. Then i pointed this memory region object to the code of HV call '''lv1_undocumented_function_114''' and patched 4 bytes in this HV call which allows me to create any '''Direct Map Memory Region''' objects without any restrictions. | |||
* Function '''LPAR_construct_direct_mapping_mem_region''' which is used by HV call '''lv1_undocumented_function_114''' has a parameter (register %r9) and when this parameter is not 0 then HV will allow you to create any '''Direct Map Memory Region''' objects without restrictions, but unfortunately the HV call '''lv1_undocumented_function_114''' passes 0 in this parameter, so i just patched it. | |||
* Then i mapped whole HV memory range with the patched HV call '''lv1_undocumented_function_114''' into the address space of GameOS. | |||
* And now you have read/write access to the whole HV. | |||
* $ONY could fix this exploit by disallowing creating of '''Direct Map Memory Region''' objects of size 0, but i know tons of other HV C++ classes which will allow me to exploit the HV in a similar way, so it wouldn't bring $ONY anything :-) And they have to change member variable offsets in those objects to make sure that i cannot patch them easily :-) | |||
== Methods == | |||
LPAR_get_memory_region_by_start_address - 0x002C7C40 (3.15) | |||
LPAR_get_memory_region_by_address - 0x002C7DA8 (3.15) | |||
LPAR_mem_addr_to_phys_addr(LPAR id, LPAR address, phys_addr) - 0x002FB8F0 (3.15) | |||
LPAR_construct_direct_mapping_mem_region - 0x002D4D04 (3.15) | |||
= Network Devices = | |||
== | == Ethernet Gelic Device == | ||
device id = 0 | |||
MAC Address: 00:1F:A7:C6:2A:C5 | |||
== | device memory base address = 0x24003004000 (size = 0x1000) | ||
== WLAN Gelic Device == | |||
device id = 0 | |||
MAC Address: 02:1F:A7:C6:2A:C5 (locally administered) | |||
== | === Net Manager === | ||
*Net Manager runs in Process 9 | |||
*It sends commands to '''/dev/sc1''' to reset WLAN Gelic device | |||
*It opens '''/dev/net0''', sets MAC address and writes device firmware '''eurus_fw.bin''' to WLAN device by using '''ioctl''' syscall | |||
== | === /dev/net0 === | ||
The device supports 3 ioctl commands: | |||
*0 - 0x002AC10C (3.15) | |||
*1 - 0x002AC250 (3.15) | |||
*2 - EURUS_STAT 0x002AC320 (3.15) | |||
= | === Methods === | ||
net_control_cmd_GELIC_LV1_POST_WLAN_CMD - 0x0024A55C (3.15) | |||
net_control_wlan_cmd_GELIC_EURUS_CMD_ASSOC - 0x00246C78 (3.15) | |||
net_control_wlan_cmd_GELIC_EURUS_CMD_START_SCAN - 0x00248A14 (3.15) | |||
net_control_wlan_cmd_GELIC_EURUS_CMD_SET_WEP_CFG - 0x00249F24 (3.15) | |||
net_control_wlan_cmd_GELIC_EURUS_CMD_SET_WPA_CFG - 0x002497B8 (3.15) | |||
= Event Notification = | |||
*Event Notfication is used e.g. to notify a LPAR about some event, e.g. device interrupt or notify a LPAR about destruction of another LPAR. | |||
*For example Process 9 is notified through Event Notification when LPAR 2 is destructed. | |||
*During LPAR construction, Process 9 creates an Outlet object with '''syscall 0x1001A''' and then passes the outlet ID to the '''syscall 0x10009''' that constructs the LINUX LPAR. In this way Process 9 is notified when LINUX LPAR is destructed. | |||
== Outlet class == | |||
This is the base Outlet class. There are different types of Outlet and they derive from this base class. | |||
=== vtable === | |||
0x00357DC0 (3.15) | |||
== | === Member variables === | ||
offset 0x30 - type (8 bytes) | |||
offset 0x38 - pointer to LPAR that owns this Outlet object | |||
offset | offset 0x48 - outlet id (8 bytes) | ||
offset | offset 0x90 - VIRQ assigned to this Outlet object (4 bytes) | ||
== Event Receive Port class == | |||
*This type of Outlet is created e.g. in '''lv1_construct_event_receive_port''' and in '''syscall 0x1001A'''. | |||
*HV calls '''lv1_connect_irq_plug''' and '''lv1_connect_irq_plug_ext''' assigns a VIRQ to Event Receive Port object. | |||
=== vtable === | |||
0x00357E88 | |||
== VUART Outlet == | |||
*HV supports only one VUART Outlet per LPAR | |||
*'''lv1_configure_virtual_uart_irq''' constructs a VUART Outlet object and passes the address of LPAR's VUART IRQ Bitmap to HV | |||
== vtable == | === vtable === | ||
0x00357DC0 | |||
== | === VUART IRQ Bitmap === | ||
*At address 0x38(LPAR ptr) + 0x158 is the VUART IRQ Bitmap owned by HV for LPAR (4 * 8 bytes = 256 bits) | |||
*At address 0x38(LPAR ptr) + 0x150 is stored the physical address of LPAR's VUART IRQ Bitmap that was passed to '''lv1_configure_virtual_uart_irq''' | |||
*When a VUART interrupt is generated by HV then first the VUART IRQ Bitmap owned by HV is updated and then this bitmap is copied to LPAR's VUART IRQ Bitmap, so VUART IRQ Bitmap is stored twice, once in HV and once in LPAR, just like IRQ State Bitmap. | |||
*VUART IRQ Bitmap is not allowed to cross page boundary of LPAR memory region where it is stored. HV checks it and makes sure that it doesn't happen. | |||
*'''GameOS 3.41''' VUART IRQ bitmap is at address '''0x80000000003556E8''' and of size '''32 bytes (256 bits, each bit corresponds to a VUART port)'''. | |||
*'''GameOS 3.15''' VUART IRQ bitmap is at address '''0x8000000000354768'''. | |||
= Logical PPE = | |||
*Logical PPE is used for interrupt management of LPAR. | |||
*A Logical PPE object is created in '''syscall 0x10005'''. It' used e.g. in Process 9 during LPAR construction. | |||
*'''syscall 0x10007''' activates a Logical PPE object | |||
*0x67F0(HSPRG0) - pointer to currently active Logical PPE object (in HV dump it points to Linux PPE object naturally because the dump was made on Linux, so Linux LPAR was active at that time) | |||
*E.g. '''lv1_get_logical_ppe_id''', '''lv1_start_ppe_periodic_tracer''' and '''lv1_set_ppe_periodic_tracer_frequency''' grab the currently active Logical PPE object | |||
== vtable == | == vtable == | ||
0x00357DF0 (3.15) | |||
== Member variables == | == Member variables == | ||
offset | offset 0x90 - pointer to an object that contains VIRQ-Outlet mapping table for thread 0 | ||
offset | offset 0x98 - pointer to an object that contains VIRQ-Outlet mapping table for thread 1 | ||
= | == Objects == | ||
Here is the list of Logical PPE objects i found in HV 3.15. | |||
{| class="wikitable FCK__ShowTableBorders" | |||
|- | |||
! Address in HV dump | |||
! LPAR id | |||
! PPE id | |||
|- | |||
| 0x0069C7F0 | |||
| 1 | |||
| 1 | |||
|- | |||
| 0x007A8900 | |||
| 2 | |||
| 1 | |||
|} | |||
= | == Virtual IRQ - Outlet Mapping == | ||
*HV maintains 2 tables per PPE that map a VIRQ to an Outlet object. | |||
*The table has 256 entries and is indexed by VIRQ. | |||
*Each entry is a pointer to Outlet object. | |||
*Each Logical PPE object has 2 tables, one for each thread of Cell CPU. | |||
=== LPAR 1 PPE 1 Thread 0 === | |||
0x0069C990 (3.15) - address of VIRQ-Outlet table for '''LPAR 1 PPE 1 Thread 0''' (not empty) | |||
{| class="wikitable FCK__ShowTableBorders" | |||
|- | |||
! VIRQ | |||
! Address of Outlet object in HV dump | |||
! Description | |||
|- | |||
| 58 | |||
| 0x00090D10 | |||
| - | |||
|- | |||
| 59 | |||
| 0x006BAC50 | |||
| - | |||
|- | |||
| 60 | |||
| 0x006B3ED0 | |||
| FLASH storage device / Storage device notification for LPAR 1 | |||
|- | |||
| 61 | |||
| 0x00697E70 | |||
| VUART interrupts | |||
|- | |||
| 62 | |||
| 0x001C8F20 | |||
| - | |||
|} | |||
= | === LPAR 1 PPE 1 Thread 1 === | ||
0x0069D9B0 (3.15) - address of VIRQ-Outlet table for '''LPAR 1 PPE 1 Thread 1''' (empty) | |||
== | === LPAR 2 PPE 1 Thread 0 === | ||
0x000A06B0 (3.15) - address of VIRQ-Outlet table for '''LPAR 2 PPE 1 Thread 0''' (not empty) | |||
= | {| class="wikitable FCK__ShowTableBorders" | ||
|- | |||
! VIRQ | |||
! Address of Outlet object in HV dump | |||
! Description | |||
|- | |||
| 20 | |||
| 0x003AA210 | |||
| - | |||
|- | |||
| 21 | |||
| 0x003AFEC0 | |||
| - | |||
|- | |||
| 22 | |||
| 0x001FC010 | |||
| - | |||
|- | |||
| 23 | |||
| 0x003A8E50 | |||
| - | |||
|- | |||
| 24 | |||
| 0x001FFED0 | |||
| SPE 0 Class 0 Interrupt | |||
|- | |||
| 25 | |||
| 0x003AE160 | |||
| SPE 0 Class 1 Interrupt | |||
|- | |||
| 26 | |||
| 0x003AE350 | |||
| SPE 0 Class 2 Interrupt | |||
|- | |||
| 27 | |||
| 0x003AB100 | |||
| SPE 1 Class 0 Interrupt | |||
|- | |||
| 28 | |||
| 0x003AB2F0 | |||
| SPE 1 Class 1 Interrupt | |||
|- | |||
| 29 | |||
| 0x003AB4E0 | |||
| SPE 1 Class 2 Interrupt | |||
|- | |||
| 30 | |||
| 0x003AA6A0 | |||
| SPE 2 Class 0 Interrupt | |||
|- | |||
| 31 | |||
| 0x003AA890 | |||
| SPE 2 Class 1 Interrupt | |||
|- | |||
| 32 | |||
| 0x003AAA80 | |||
| SPE 2 Class 2 Interrupt | |||
|- | |||
| 33 | |||
| 0x003B44A0 | |||
| SPE 3 Class 0 Interrupt | |||
|- | |||
| 34 | |||
| 0x003B4690 | |||
| SPE 3 Class 1 Interrupt | |||
|- | |||
| 35 | |||
| 0x003B4AD0 | |||
| SPE 3 Class 2 Interrupt | |||
|- | |||
| 36 | |||
| 0x003B5300 | |||
| SPE 4 Class 0 Interrupt | |||
|- | |||
| 37 | |||
| 0x003B54F0 | |||
| SPE 4 Class 1 Interrupt | |||
|- | |||
| 38 | |||
| 0x003B56E0 | |||
| SPE 4 Class 2 Interrupt | |||
|- | |||
| 39 | |||
| 0x003AE7C0 | |||
| SPE 5 Class 0 Interrupt | |||
|- | |||
| 40 | |||
| 0x003AE9B0 | |||
| SPE 5 Class 1 Interrupt | |||
|- | |||
| 41 | |||
| 0x003AEBA0 | |||
| SPE 5 Class 2 Interrupt | |||
|- | |||
| 42 | |||
| 0x003B2040 | |||
| Storage device notification for LPAR 2 | |||
|- | |||
| 43 | |||
| 0x003AEE30 | |||
| VUART interrupts | |||
|- | |||
| 44 | |||
| 0x001FEAA0 | |||
| - | |||
|- | |||
| 45 | |||
| 0x001FEED0 | |||
| HDD storage device | |||
|- | |||
| 46 | |||
| 0x003B5E20 | |||
| - | |||
|- | |||
| 47 | |||
| 0x003B7040 | |||
| - | |||
|- | |||
| 48 | |||
| 0x003B9B40 | |||
| - | |||
|- | |||
| 49 | |||
| 0x003B3A40 | |||
| - | |||
|- | |||
| 50 | |||
| 0x003BACA0 | |||
| Gelic device | |||
|- | |||
| 51 | |||
| 0x003BAE10 | |||
| UNKNOWN storage device | |||
|- | |||
| 52 | |||
| 0x003B8350 | |||
| - | |||
|} | |||
} | |||
== | === LPAR 2 PPE 1 Thread 1 === | ||
0x007A89E0 (3.15) - address of VIRQ-Outlet table for '''LPAR 2 PPE 1 Thread 1''' (not empty) | |||
{| class="wikitable FCK__ShowTableBorders" | |||
|- | |||
! VIRQ | |||
! Address of Outlet object in HV dump | |||
! Description | |||
|- | |||
| 16 | |||
| 0x003B2480 | |||
| - | |||
|- | |||
| 17 | |||
| 0x003B2590 | |||
| - | |||
|- | |||
| 18 | |||
| 0x003B26A0 | |||
| - | |||
|- | |||
| 19 | |||
| 0x003B27B0 | |||
| - | |||
|} | |||
== | == IRQ State Bitmap == | ||
*There is one IRQ State Bitmap (256 bits = 32 bytes) per thread of Logical PPE | |||
*'''HSPRG0 value is per thread''', so there are 2 HSPRG0 values in HV dump !!! | |||
*The IRQ State Bitmap of a thread is stored at -0x68E0(HSPRG0) | |||
*When an Event or Interrupt happens then the bitmap at 0x68E0(HSPRG0) is updated | |||
*The physical address of '''LPAR's IRQ State Bitmap''' of thread is stored at offset -0x68C0(HSPRG0) | |||
*The address of LPAR's IRQ State Bitmap is passed to Hypervisor through HV call '''lv1_configure_irq_state_bitmap''' | |||
*'''lv1_detect_pending_interrupts''' returns value of current IRQ State Bitmap. | |||
*The IRQ State Bitmap is updated if an Outlet object is assigned to VIRQ and when Outlet generates an event | |||
*After IRQ State Bitmap update, it's copied to LPAR's IRQ State Bitmap and a hardware interrupt is generated so that LPAR can read it's IRQ State Bitmap and handle interrupts. | |||
*So, IRQ State Bitmap is stored twice, once in HV and once in LPAR, just like VUART IRQ Bitmap. | |||
*'''GameOS''' IRQ state bitmap is stored at address '''SPRG0 + 0x1C0 and of size 64 bytes (256 bits state + 256 bits mask) per thread of Cell CPU'''. So there are 2 IRQ state bitmaps. | |||
0x8941FC0 - physical address of LPAR's IRQ State Bitmap for Thread 0 of LINUX LPAR | |||
0x8948FC0 - physical address of LPAR's IRQ State Bitmap for Thread 1 of LINUX LPAR | |||
= System Controller (SC or SYSCON) = | |||
*Data received from SC is sent to a VUART | |||
*'''lv1_get_rtc''' and '''syscall 0x10036''' communicate with '''SC VUART 4'''. | |||
=== VUART Table === | |||
*Address of SC VUART Table - 0x00610410 (3.15). | |||
*There are 5 VUARTs for SC in HV 3.15 | |||
Here is the SC VUART table from HV 3.15: | |||
{| class="wikitable FCK__ShowTableBorders" | |||
|- | |||
! Index | |||
! Address of VUART object in HV dump | |||
! Description | |||
|- | |||
| 0 | |||
| 0x0060FD20 | |||
| This VUART is connected with the '''VUART 0 (/dev/sc0)''' of LPAR 1 | |||
|- | |||
| 1 | |||
| 0x0060FE20 | |||
| This VUART is connected with the '''VUART 1 (/dev/sc1)''' of LPAR 1 | |||
|- | |||
| 2 | |||
| 0x0060FF20 | |||
| This VUART is not connected to some peer VUART but i guess that it should be connected to '''VUART 2 (/dev/sc2)''' of LPAR1 | |||
|- | |||
| 3 | |||
| 0x006124E0 | |||
| This VUART is connected with the '''VUART 3 (/dev/sc3)''' of LPAR 1 | |||
|- | |||
| 4 | |||
| 0x00612DF0 | |||
| '''lv1_get_rtc''' and '''syscall 0x10036''' communicate with this VUART. | |||
|} | |||
== | == Interrupt Handling == | ||
spider_sc_interrupt_handler - 0x0020A68C (3.15) | |||
== Methods == | |||
sc_vuart_4_get_peer_vuart - 0x002ED384 (3.15) | |||
sc_send - 0x0020A908 (3.15) | |||
== lv1_get_rtc == | |||
*'''lv1_get_rtc''' communicates with SC VUART 4. | |||
*20 bytes are written to the peer VUART of SC VUART 4. | |||
*After a request is sent to SC VUART 4, '''lv1_get_rtc''' busy waits until SC VUART 4 receive data buffer is not empty. | |||
*When SC VUART 4 receive data buffer is not empty, '''lv1_get_rtc''' reads 24 bytes from the VUART. | |||
* | |||