HV Syscall Reference: Difference between revisions
m (Upto syscall 31 ported) |
m (Upto syscall 69 ported) |
||
Line 988: | Line 988: | ||
|- | |- | ||
|} | |} | ||
---- | |||
=== lv1_shutdown_logical_partition === | |||
Not used in current kernel. | |||
===== Abstract Call ===== | |||
result = lv1_shutdown_logical_partition( /*IN*/ p1 ); | |||
===== Parameters ===== | |||
{| class="wikitable" | |||
|- | |||
! colspan="2" | Inputs | |||
|- | |||
!Register | |||
!Description | |||
|- | |||
|R3 | |||
|p1 - shutdown command (see notes) | |||
|- | |||
! colspan="2" | Outputs | |||
|- | |||
!Register | |||
!Description | |||
|- | |||
|R3 | |||
|Status? | |||
|- | |||
|} | |||
Notes: | |||
Comment from kboot-10/dl/linux-2.6.16/include/asm-powerpc/lv1call.h (kboot-20061208) | |||
/* values for lv1_shutdown_logical_partition */ | |||
#define LV1_SHUTDOWN_LP_HALT 1 | |||
#define LV1_SHUTDOWN_LP_POWER_OFF 2 | |||
#define LV1_SHUTDOWN_LP_RESTART 3 | |||
---- | |||
=== lv1_destruct_logical_spe === | |||
Destructs a logical SPE. | |||
===== Kernel Call ===== | |||
result = lv1_destruct_logical_spe( /*IN*/ spe_id ); | |||
===== Parameters ===== | |||
{| class="wikitable" | |||
|- | |||
! colspan="2" | Inputs | |||
|- | |||
!Register | |||
!Description | |||
|- | |||
|R3 | |||
|spe_id - spe id | |||
|- | |||
! colspan="2" | Outputs | |||
|- | |||
!Register | |||
!Description | |||
|- | |||
|R3 | |||
|Status - 0 = OK, Other values are unknown, but indicate failure. | |||
|- | |||
|} | |||
---- | |||
=== lv1_construct_logical_spe === | |||
Constructs a logical SPE. | |||
===== Kernel Call ===== | |||
status = lv1_construct_logical_spe( /*IN*/ PAGE_SHIFT, PAGE_SHIFT, PAGE_SHIFT, PAGE_SHIFT, PAGE_SHIFT, vas_id, SPE_TYPE_LOGICAL, | |||
/*OUT*/ &priv2_addr, &problem_phys, &local_store_phys, &unused, &shadow_addr, &spe_id ); | |||
===== Parameters ===== | |||
{| class="wikitable" | |||
|- | |||
! colspan="2" | Inputs | |||
|- | |||
!Register | |||
!Description | |||
|- | |||
|R3 | |||
|PAGE_SHIFT | |||
|- | |||
|R4 | |||
|PAGE_SHIFT | |||
|- | |||
|R5 | |||
|PAGE_SHIFT | |||
|- | |||
|R6 | |||
|PAGE_SHIFT | |||
|- | |||
|R7 | |||
|PAGE_SHIFT | |||
|- | |||
|R8 | |||
|vas_id - virtual address space id | |||
|- | |||
|R9 | |||
|SPE_TYPE_LOGICAL (0) | |||
|- | |||
! colspan="2" | Outputs | |||
|- | |||
!Register | |||
!Description | |||
|- | |||
R3 | |||
|Status - 0 = OK, Other values are unknown, but indicate failure. | |||
|- | |||
|R4 | |||
|priv2_addr - lpar address of spe priv2 area | |||
|- | |||
|R5 | |||
|problem_phys - lpar address of spu_problem area | |||
|- | |||
|R6 | |||
|local_store_phys - lpar address of spu local storage | |||
|- | |||
|R7 | |||
|unused | |||
|- | |||
|R8 | |||
|shadow_addr - lpar address of spe register shadow area | |||
|- | |||
|R9 | |||
|spe_id - logical spe id | |||
|- | |||
|} | |||
Notes: | |||
R7 out parameter was referred to in a previous codebase as “ctxt_addr”. | |||
===== Test Results ===== | |||
{| class="wikitable" | |||
|- | |||
!priv2_addr | |||
!problem_phys | |||
!local_store_phys | |||
!unused | |||
!shadow_addr | |||
!spe_id | |||
|- | |||
|0x4c0000660000 | |||
|0x4c0000640000 | |||
|0x4c0000600000 | |||
|0×0 | |||
|0x30000000d000 | |||
|11 | |||
|- | |||
|0x4c0000760000 | |||
|0x4c0000740000 | |||
|0x4c0000700000 | |||
|0×0 | |||
|0x30000000f000 | |||
|15 | |||
|- | |||
|0x4c0000860000 | |||
|0x4c0000840000 | |||
|0x4c0000800000 | |||
|0×0 | |||
|0×300000011000 | |||
|19 | |||
|- | |||
|0x4c0000960000 | |||
|0x4c0000940000 | |||
|0x4c0000900000 | |||
|0×0 | |||
|0×300000013000 | |||
|23 | |||
|- | |||
|0x4c0000a60000 | |||
|0x4c0000a40000 | |||
|0x4c0000a00000 | |||
|0×0 | |||
|0×300000015000 | |||
|27 | |||
|- | |||
|0x4c0000b60000 | |||
|0x4c0000b40000 | |||
|0x4c0000b00000 | |||
|0×0 | |||
|0×300000017000 | |||
|31 | |||
|} | |||
For each entry, only two separate lpar are allocated by the hypervisor. Indeed, calling lv1_query_logical_partition_address_region_info on priv2_addr, problem_phys, local_store_phys and shadow_addr for the first entry returns the following info: | |||
{| class="wikitable" | |||
|- | |||
!lpar | |||
!start_address | |||
!size | |||
!access_right | |||
!max_page_size | |||
!flags | |||
!comment | |||
|- | |||
0x4c0000660000 | |||
|0x4c0000600000 | |||
|524288 | |||
|0×3 (RW) | |||
|12 | |||
|0xa000000000000000 | |||
|SPU MMIO lpar, privilege state 2 region (128kB) | |||
|- | |||
|0x4c0000640000 | |||
|0x4c0000600000 | |||
|524288 | |||
|0×3 (RW) | |||
|12 | |||
|0xa000000000000000 | |||
|SPU MMIO lpar, problem state region (128kB) | |||
|- | |||
|0x4c0000600000 | |||
|0x4c0000600000 | |||
|524288 | |||
|0×3 (RW) | |||
|12 | |||
|0xa000000000000000 | |||
|SPU MMIO lpar, local store region (256kB) | |||
|- | |||
|0x30000000d000 | |||
|0x30000000d000 | |||
|4096 | |||
|0×1 (RO) | |||
|12 | |||
|0xa000000000000000 | |||
|SPU shadow registers lpar (4kB, read-only) | |||
|- | |||
|} | |||
From this info we see a single lpar is used for all the SPU MMIO region (see figure 5-1 CBE Memory Map of the Cell Broadband Engine Programming Handbook) and another lpar is used for the SPE registers. | |||
---- | |||
=== lv1_set_spe_interrupt_mask === | |||
Set the interrupt mask of a specific spe. | |||
===== Kernel Call ===== | |||
lv1_set_spe_interrupt_mask( /*IN*/ spe_id, class, mask ); | |||
===== Parameters ===== | |||
{| class="wikitable" | |||
|- | |||
! colspan="2" | Inputs | |||
|- | |||
!Register | |||
!Description | |||
|- | |||
|R3 | |||
|spe_id - spe id | |||
|- | |||
|R4 | |||
|class - spe interrupt class | |||
|- | |||
|R5 | |||
|mask - spe interrupt mask | |||
|- | |||
! colspan="2" | Outputs | |||
|- | |||
!Register | |||
!Description | |||
|- | |||
|R3 | |||
|Status? | |||
|- | |||
|} | |||
---- | |||
=== lv1_undocumented_function_62 === | |||
Exists in PAL 1.7; Returned -4 (LV1_DENIED_BY_POLICY) when passed 0 in R3 to R10. | |||
---- | |||
=== lv1_undocumented_function_63 === | |||
Does not exist in 3.15. | |||
Exists in PAL 1.7; Returned -4 (LV1_DENIED_BY_POLICY) when passed 0 in R3 to R10. | |||
---- | |||
=== lv1_set_spe_transition_notifier === | |||
Not used in current kernel. | |||
===== Abstract Call ===== | |||
result = lv1_set_spe_transition_notifier( /*IN*/ p1, p2, p3 ); | |||
===== Parameters ===== | |||
{| class="wikitable" | |||
|- | |||
! colspan="2" | Inputs | |||
|- | |||
!Register | |||
!Description | |||
|- | |||
|R3 | |||
|spe_id - logical spe id | |||
|- | |||
|R4 | |||
|0 - Unknown usage | |||
|- | |||
! colspan="2" | Outputs | |||
|- | |||
!Register | |||
!Description | |||
|- | |||
|R3 | |||
|Status - 0 = OK, Other values are unknown, but indicate failure. | |||
|- | |||
|} | |||
---- | |||
=== lv1_disable_logical_spe === | |||
Disables a logical SPE. | |||
===== Kernel Call ===== | |||
result = lv1_disable_logical_spe( /*IN*/ spe_id, 0 ); | |||
===== Parameters ===== | |||
{| class="wikitable" | |||
|- | |||
! colspan="2" | Inputs | |||
|- | |||
!Register | |||
!Description | |||
|- | |||
|R3 | |||
|spe_id - logical spe id | |||
|- | |||
|R4 | |||
|0 - Unknown usage | |||
|- | |||
! colspan="2" | Outputs | |||
|- | |||
!Register | |||
!Description | |||
|- | |||
|R3 | |||
|Status - 0 = OK, Other values are unknown, but indicate failure. | |||
|- | |||
|} | |||
---- | |||
=== lv1_clear_spe_interrupt_status === | |||
Clear the interrupt status of a specific spe. | |||
===== Kernel Call ===== | |||
lv1_clear_spe_interrupt_status( /*IN*/ spe_id, class, stat, 0 ); | |||
===== Parameters ===== | |||
{| class="wikitable" | |||
|- | |||
! colspan="2" | Inputs | |||
|- | |||
!Register | |||
!Description | |||
|- | |||
|R3 | |||
|spe_id - logical spe id | |||
|- | |||
|R4 | |||
|class - spe interrupt class | |||
|- | |||
|R5 | |||
|stat - new interrupt status? | |||
|- | |||
|R6 | |||
|0 - Unknown | |||
|- | |||
! colspan="2" | Outputs | |||
|- | |||
!Register | |||
!Description | |||
|- | |||
|R3 | |||
|Status? | |||
|- | |||
|} | |||
---- | |||
=== lv1_get_spe_interrupt_status === | |||
Get the interrupt status of a specific spe. | |||
===== Kernel Call ===== | |||
lv1_get_spe_interrupt_status( /*IN*/ spe_id, class, /*OUT*/ &stat ); | |||
===== Parameters ===== | |||
{| class="wikitable" | |||
|- | |||
! colspan="2" | Inputs | |||
|- | |||
!Register | |||
!Description | |||
|- | |||
|R3 | |||
|spe_id - logical spe id | |||
|- | |||
|R4 | |||
|class - spe interrupt class | |||
|- | |||
! colspan="2" | Outputs | |||
|- | |||
!Register | |||
!Description | |||
|- | |||
|R3 | |||
|Status? | |||
|- | |||
|R4 | |||
|stat - interrupt status | |||
|- | |||
|} | |||
---- | |||
=== lv1_get_logical_ppe_id === | |||
Returns the logical PPE id. | |||
===== Kernel Call ===== | |||
status = lv1_get_logical_ppe_id( /*OUT*/ &ppe_id ); | |||
===== Parameters ===== | |||
{| class="wikitable" | |||
|- | |||
! colspan="2" | Outputs | |||
|- | |||
!Register | |||
!Description | |||
|- | |||
|R3 | |||
|Status? | |||
|- | |||
|R4 | |||
|logical PPE id | |||
|- | |||
|} | |||
Notes: | |||
When called from kernel module init function, ppe_id always seem to be 1. |
Revision as of 21:12, 18 May 2011
HV Syscalls
lv1_allocate_memory
Create a memory region in the Hypervisor Virtual Address Space (vas)
Kernel Call
result = lv1_allocate_memory( /*IN*/ size, page_size_exp, 0, flags, /*OUT*/ &addr, &muid );
Parameters
Inputs | |
---|---|
Register | Description |
R3 | size - of the region to allocate, must be a multiple of page_size |
R4 | page_size_exp - where required page_size = 2 ^ page_size_exp |
R5 | 0 - Unknown, see notes |
R6 | flags - (from linux/include/asm-powerpc/lv1call.h) bit 63: transferability: TF_NO = 0×00, TF_YES = 0×01 |
Outputs | |
Register | Description |
R3 | Status - 0 = OK, LV1_RESOURCE_SHORTAGE (-2), LV1_NO_ENTRY (-6), LV1_DUPLICATE_ENTRY (-7) |
R4 | addr - LPAR Address of region |
R5 | muid - Unknown, unused by Kernel |
Notes:
page_size_exp takes values of 12 (page_size = 4K) to 21 (page_size = 2M) before LV1_RESOURCE_SHORTAGE (-2) is returned under a fully booted Linux OS. Higher values (24, page_size = 16M) can be found in the actual kernel source and can presumably be made before the OS has fully booted. page_size_exp values below 12 cause a return status of LV1_ILLEGAL_PARAMETER_VALUE (-17).
Input R5 was speculated to be the initialization value for the allocated region, but appears not to be the case. Values other than 0 or 1 appear to return a status of LV1_NO_ENTRY (-6), though a valid value of page_size_exp appears to be checked first (-17 is returned for invalid values of page_size_exp, regardless of the value of R5).
Allocations with flags = 0×00, 0×01, 0×02, 0×03 and 0×04 were successful though the effects of the flags could not be tested at this point. Allocations with flags >= 0×400 return LV1_ILLEGAL_PARAMETER_VALUE.
Initial tests allocating memory with flags = 0×08 (ADDR_0, presumably request physical address rather than logical partition address) result in a status of LV1_DUPLICATE_ENTRY (-7). This and the previous return value of -6 suggest an association with a database of some kind (repository values or memory maps?). It appears that some form of allocation may be taking place as LV1_ILLEGAL_PARAMETER_VALUE and LV1_RESOURCE_SHORTAGE are reported for invalid input parameters, rather than LV1_DUPLICATE_ENTRY.
For all successful allocations so far, output muid (R5) = 1
lv1_write_htab_entry
Write an entry to the hash page table.
Kernel Call
result = lv1_write_htab_entry( /*IN*/ vas_id, slot, va, pa );
Parameters
Inputs | |
---|---|
Register | Description |
R3 | vas_id - virtual address space id (0 for current) |
R4 | slot - table slot to write entry to |
R5 | va - first half of PTE |
R6 | pa - second half of PTE, except RPN is replaced with LPAR address |
Outputs | |
Register | Description |
R3 | Status - 0 = OK, Other values are unknown, but indicate failure. |
lv1_construct_virtual_address_space
Construct a PPE virtual address space.
Kernel Call
result = lv1_construct_virtual_address_space( /*IN*/ htab_size, number_of_sizes, page_sizes, /*OUT*/ &vas_id, &act_htab_size );
Parameters
Inputs | |
---|---|
Register | Description |
R3 | htab_size - must be 18, 19 or 20 (256KB, 512KB or 1MB) |
R4 | number_of_sizes - How many page sizes are specified in page_sizes |
R5 | page_sizes - see notes |
Outputs | |
Register | Description |
R3 | Status - 0 = OK, Other values are unknown, but indicate failure. |
R4 | vas_id - virtual address space id |
R5 | act_htab_size - actual hash table size? |
Notes:
Page sizes are specified as the power of two for the desired sizes. Each power of two is stored as an 8 bit field in page_sizes, starting from the MSB.
The “pages_sizes” parameter is set in “mm.c” using the following function:
page_sizes = make_page_sizes(PAGE_SHIFT_16M, PAGE_SHIFT_64K); static unsigned long make_page_sizes(unsigned long a, unsigned long b) { return (a << 56) | (b << 48); }
lv1_invalidate_htab_entries
Not used in current kernel.
Abstract Call
result = lv1_invalidate_htab_entries( /*IN*/ p1, p2, p3, p4, p5 );
Parameters
Inputs | |
---|---|
Register | Description |
R3 | p1 - Unknown |
R4 | p2 - Unknown |
R5 | p3 - Unknown |
R6 | p4 - Unknown |
R7 | p5 - Unknown |
Outputs | |
Register | Description |
R3 | Status? |
lv1_get_virtual_address_space_id_of_ppe
Returns the virtual address space id of the PPE.
Kernel Call
result = lv1_get_virtual_address_space_id_of_ppe( /*IN*/ ppe_id , /*OUT*/ &vas_id );
Parameters
Inputs | |
---|---|
Register | Description |
R3 | PPE id |
Outputs | |
Register | Description |
R3 | status: 0 = LV1_SUCCESS |
R4 | vas_id - virtual address space id of the PPE |
Notes:
Regardless of the ppe_id, when called from kernel module init function, vas_id always seems to be 11.
lv1_query_logical_partition_address_region_info
Retrieve address region information for the specified logical partition address region.
Kernel Call
result = lv1_query_logical_partition_address_region_info( /*IN*/ 0, /*OUT*/ &start_address, &size, &access_right, &max_page_size, &flags);
Parameters
Inputs | |
---|---|
Register | Description |
R3 | 0 - logical partition address region (lpar) |
Outputs | |
Register | Description |
R3 | status: 0 = LV1_SUCCESS |
R4 | start_address - start address of logical partition address region |
R5 | size - size of logical partition address region |
R6 | access_right - ? |
R7 | max_page_size - maximum page size of logical partition address region? or order of the allocation? |
R8 | flags - ? |
Notes:
Only the “max_page_size” parameter is currently used by the Kernel, in “mm.c”
Test Results
Register | Hex | Decimal | Comment |
---|---|---|---|
R3 | 0x00000000 | (0) | value does not seem to effect result |
Outputs | |||
R3 | 0×00000000 | (0) | LV1_SUCCESS |
R4 | 0×00000000 | (0) | start_address |
R5 | 0×08000000 | (134217728) | size - 128 Mb |
R6 | 0×00000003 | (3) | access_right |
R7 | 0x0000001b | (27) | max_page_size |
R8 | 0×00000008 | (8) | flags |
This suggests lpar 0 is a special lpar representing the first 128MB of RAM that are always available at boot time. In this case, max_page_size seems to correspond to the order of the allocation (2**27 = 128 MB). The meaning of access_right and flags is unknown.
Also works on a lpar obtained from lv1_allocate_memory, for example
lv1_allocate_memory(4096 /* size */, 12 /* page size */, 0, 0, &lpar, &muid); lv1_query_logical_partition_address_region_info(lpar, &start_address, &size, &access_right, &max_page_size, &flags);
returns:
Register | Hex | Decimal | Comment |
---|---|---|---|
R3 | 0x30000001f00 | (3298534891264) | lpar obtained from lv1_allocate_memory |
Outputs | |||
R3 | 0×00000000 | (0) | LV1_SUCCESS |
R4 | 0×30000001f00 | (0) | start_address (same as input lpar) |
R5 | 0×00001000 | (4096) | size - 4kB |
R6 | 0×00000003 | (3) | access_right |
R7 | 0x0000000c | (12) | max_page_size |
R8 | 0×00000000 | (0) | flags |
lv1_select_virtual_address_space
Select an alternative virtual address space.
Kernel Call
result = lv1_select_virtual_address_space( /*IN*/ vas_id );
Parameters
Inputs | |
---|---|
Register | Description |
R3 | vas_id - virtual address space id |
Outputs | |
Register | Description |
R3 | Status - 0 = OK, Other values are unknown, but indicate failure. |
Notes:
In “mm.c” When destructing a virtual address space, a call to select address space 0 (default?) is performed first.
Calling lv1_select_virtual_address_space(0) from a kernel module init function causes the PS3 to hang.
lv1_undocumented_function_8
Returns current HV uptime. (NOTE: Use graf's work here)
lv1_pause
Called during the Kernel idle loop - puts the PPE thread into an inactive state.
Kernel Call
result = lv1_pause( /*IN*/ mode );
Parameters
Inputs | |
---|---|
Register | Description |
R3 | mode: 0 = wake on DEC interrupt, 1 = ignore DEC interrupt |
Outputs | |
Register | Description |
R3 | status: 0 = LV1_SUCCESS, -17 = LV1_ILLEGAL_PARAMETER_VALUE |
Notes:
LV1_ILLEGAL_PARAMETER_VALUE is returned for values of “mode” other than 0 or 1.
Comment from setup.c
/* * lv1_pause() puts the PPE thread into inactive state until an * irq on an unmasked plug exists. MSR[EE] has no effect. * flags: 0 = wake on DEC interrupt, 1 = ignore DEC interrupt. */
lv1_destruct_virtual_address_space
Destruct a virtual address space.
Kernel Call
lv1_destruct_virtual_address_space( /*IN*/ vas_id );
Parameters
Inputs | |
---|---|
Register | Description |
R3 | vas_id - virtual address space id |
Outputs | |
Register | Description |
R3 | Status? |
Notes:
Called with 0 in R3 crashes my PS3. Light turns red, appears to be off
lv1_configure_irq_state_bitmap
Register the address of a HV plug-outlet bitmap with the Hypervisor.
Kernel Call
result = lv1_configure_irq_state_bitmap( /*IN*/ ppe_id, cpu_id, bmp_addr );
Parameters
Inputs | |
---|---|
Register | Description |
R3 | ppe_id - PPE id |
R4 | cpu_id - PPE CPU id |
R5 | bmp_addr - lpar address of state bitmap |
Outputs | |
Register | Description |
R3 | Status - 0 = OK, Other values are unknown, but indicate failure. |
Notes:
Comment from interrupt.c:
/** * The HV mantains per SMT thread mappings of HV outlet to HV plug on * behalf of the guest. These mappings are implemented as 256 bit guest * supplied bitmaps indexed by plug number. The addresses of the bitmaps * are registered with the HV through lv1_configure_irq_state_bitmap(). * The HV requires that the 512 bits of status + mask not cross a page * boundary. PS3_BMP_MINALIGN is used to define this minimal 64 byte * alignment. * * The HV supports 256 plugs per thread, assigned as {0..255}, for a total * of 512 plugs supported on a processor. To simplify the logic this * implementation equates HV plug value to Linux virq value, constrains each * interrupt to have a system wide unique plug number, and limits the range * of the plug values to map into the first dword of the bitmaps. This * gives a usable range of plug values of {NUM_ISA_INTERRUPTS..63}. Note * that there is no constraint on how many in this set an individual thread * can acquire. */
lv1_connect_irq_plug_ext
Connect a HV outlet to a CPU and virtual irq.
Kernel Call
result = lv1_connect_irq_plug_ext( /*IN*/ ppe_id, cpu_id, virq, outlet, 0 );
Parameters
Inputs | |
---|---|
Register | Description |
R3 | ppe_id - PPE id |
R4 | cpu_id - PPE CPU id |
R5 | virq - virtual irq |
R6 | outlet - HV outlet |
R7 | 0 - unknown |
Outputs | |
Register | Description |
R3 | Status - 0 = OK, Other values are unknown, but indicate failure. |
lv1_release_memory
Releases a previously allocated memory region. Return code is not checked.
Kernel Call
lv1_release_memory( /*IN*/ base );
Parameters
Inputs | |
---|---|
Register | Description |
R3 | base - base address of memory region |
Outputs | |
Register | Description |
R3 | Status?? |
lv1_put_iopte
Put an io page table entry.
Kernel Call
result = lv1_put_iopte( /*IN*/ ioas_id, ioif_addr, lpar_addr, io_id, flags );
Parameters
Inputs | |
---|---|
Register | Description |
R3 | ioas_id - io address space id |
R4 | ioif_addr - io interface address |
R5 | lpar_addr - logical partition address |
R6 | io_id - io id |
R7 | flags - see notes |
Outputs | |
Register | Description |
R3 | Status?? |
Notes:
Code taken from kboot-10\dl\linux-2.6.16\sound\powerpc\snd_ps3pf.c (kboot-20061208)
ret64 = lv1_put_iopte(0, /* io address space id */ ioif_map_info_array[current_segment].ioif_addr + current_page * IO_PAGESIZE, /* ioif addr */ p_to_lp(current_paddr), /* lpar addr */ PS3PF_AUDIO_IOID, IOPTE_READONLY | IOPTE_COHERENT | IOPTE_STRICT_ORDER);
lv1_disconnect_irq_plug_ext
Disconnect a virtual irq from its HV outlet.
Kernel Call
lv1_disconnect_irq_plug_ext( /*IN*/ ppe_id, cpu_id, virq );
Parameters
Inputs | |
---|---|
Register | Description |
R3 | ppe_id - PPE id |
R4 | cpu_id - PPE CPU id |
R5 | virq - virtual irq |
R7 | flags - see notes |
Outputs | |
Register | Description |
R3 | Status? |
lv1_construct_event_receive_port
Creates an outlet that can be used with a virtual irq to receive system events.
Kernel Call
result = lv1_construct_event_receive_port( /*OUT*/ &outlet );
Parameters
Outputs | |
---|---|
Register | Description |
R3 | Status - 0 = OK, Other values are unknown, but indicate failure. |
R4 | outlet - event outlet |
lv1_destruct_event_receive_port
Destruct a previously constructed event receiving port.
Kernel Call
result = lv1_destruct_event_receive_port( /*IN*/ outlet );
Parameters
Inputs | |
---|---|
Register | Description |
R3 | outlet - event outlet |
Outputs | |
Register | Description |
R3 | Status - 0 = OK, Other values are unknown, but indicate failure. |
lv1_send_event_locally
Signal the specified event.
Kernel Call
result = lv1_send_event_locally( /*IN*/ outlet );
Parameters
Inputs | |
---|---|
Register | Description |
R3 | outlet - event outlet |
Outputs | |
Register | Description |
R3 | Status - 0 = OK, Other values are unknown, but indicate failure. |
lv1_detect_pending_interrupts
Not used in current kernel.
Abstract Call
result = lv1_detect_pending_interrupts( /*IN*/ p1, /*OUT*/ &v1, &v2, &v3, &v4 );
Parameters
Inputs | |
---|---|
Register | Description |
R3 | p1 - unknown |
Outputs | |
Register | Description |
R3 | Status? |
R4 | v1 - Unknown |
R5 | v2 - Unknown |
R6 | v3 - Unknown |
R7 | v4 - Unknown |
Notes:
Info taken from kboot-10\dl\linux-2.6.16\include\asm-powerpc\lv1calltab.h (kboot-20061208)
lv1_end_of_interrupt
Indicate the end of an interrupt handler has been reached.
kboot Call
result = lv1_end_of_interrupt( /*IN*/ irq );
Parameters
Inputs | |
---|---|
Register | Description |
R3 | irq - interrupt number |
Outputs | |
Register | Description |
R3 | Status - 0 = OK, Other values are unknown, but indicate failure. |
Notes:
Comment in kboot-10\dl\linux-2.6.16\arch\powerpc\platforms\ps3pf\pic.c (kboot-20061208)
/* lv1_end_of_interrupt must be called at end_irq. Some lv1 drivers clear irq status in it. */
lv1_connect_irq_plug
Bind a virtual interrupt to a CPU.
kboot Call
result = lv1_connect_irq_plug( /*IN*/ virq, hwirq );
Parameters
Inputs | |
---|---|
Register | Description |
R3 | virq - virtual interrupt |
R4 | hwirq - hardware interrupt |
Outputs | |
Register | Description |
R3 | Status - 0 = OK, Other values are unknown, but indicate failure. |
Notes:
Info taken from kboot-10/dl/linux-2.6.16/patches/cell-support/2.6.19-rc6-arnd1/ps3-support/ps3-interrupt.patch (kboot-20061208)
lv1_disconnect_irq_plug
Unbind a virtual interrupt from a CPU.
kboot Call
lv1_disconnect_irq_plug( /*IN*/ virq );
Parameters
Inputs | |
---|---|
Register | Description |
R3 | virq - virtual interrupt |
Outputs | |
Register | Description |
R3 | Status? |
Notes:
Info taken from kboot-10/dl/linux-2.6.16/patches/cell-support/2.6.19-rc6-arnd1/ps3-support/ps3-interrupt.patch (kboot-20061208)
lv1_end_of_interrupt_ext
Indicate that the end of an interrupt handler has been reached.
Kernel Call
lv1_end_of_interrupt_ext( /*IN*/ ppe_id, cpu_id, virq );
Parameters
Inputs | |
---|---|
Register | Description |
R3 | ppe_id - PPE id |
R4 | cpu_id - PPE CPU id |
R5 | virq - virtual irq |
Outputs | |
Register | Description |
R3 | Status? |
lv1_did_update_interrupt_mask
Indicate that CPU interrupt mask has been updated.
Kernel Call
lv1_did_update_interrupt_mask( /*IN*/ ppe_id, cpu_id );
Parameters
Inputs | |
---|---|
Register | Description |
R3 | ppe_id - PPE id |
R4 | cpu_id - PPE CPU id |
Outputs | |
Register | Description |
R3 | Status? |
lv1_shutdown_logical_partition
Not used in current kernel.
Abstract Call
result = lv1_shutdown_logical_partition( /*IN*/ p1 );
Parameters
Inputs | |
---|---|
Register | Description |
R3 | p1 - shutdown command (see notes) |
Outputs | |
Register | Description |
R3 | Status? |
Notes:
Comment from kboot-10/dl/linux-2.6.16/include/asm-powerpc/lv1call.h (kboot-20061208)
/* values for lv1_shutdown_logical_partition */ #define LV1_SHUTDOWN_LP_HALT 1 #define LV1_SHUTDOWN_LP_POWER_OFF 2 #define LV1_SHUTDOWN_LP_RESTART 3
lv1_destruct_logical_spe
Destructs a logical SPE.
Kernel Call
result = lv1_destruct_logical_spe( /*IN*/ spe_id );
Parameters
Inputs | |
---|---|
Register | Description |
R3 | spe_id - spe id |
Outputs | |
Register | Description |
R3 | Status - 0 = OK, Other values are unknown, but indicate failure. |
lv1_construct_logical_spe
Constructs a logical SPE.
Kernel Call
status = lv1_construct_logical_spe( /*IN*/ PAGE_SHIFT, PAGE_SHIFT, PAGE_SHIFT, PAGE_SHIFT, PAGE_SHIFT, vas_id, SPE_TYPE_LOGICAL, /*OUT*/ &priv2_addr, &problem_phys, &local_store_phys, &unused, &shadow_addr, &spe_id );
Parameters
R3Inputs | |
---|---|
Register | Description |
R3 | PAGE_SHIFT |
R4 | PAGE_SHIFT |
R5 | PAGE_SHIFT |
R6 | PAGE_SHIFT |
R7 | PAGE_SHIFT |
R8 | vas_id - virtual address space id |
R9 | SPE_TYPE_LOGICAL (0) |
Outputs | |
Register | Description |
Status - 0 = OK, Other values are unknown, but indicate failure. | |
R4 | priv2_addr - lpar address of spe priv2 area |
R5 | problem_phys - lpar address of spu_problem area |
R6 | local_store_phys - lpar address of spu local storage |
R7 | unused |
R8 | shadow_addr - lpar address of spe register shadow area |
R9 | spe_id - logical spe id |
Notes:
R7 out parameter was referred to in a previous codebase as “ctxt_addr”.
Test Results
priv2_addr | problem_phys | local_store_phys | unused | shadow_addr | spe_id |
---|---|---|---|---|---|
0x4c0000660000 | 0x4c0000640000 | 0x4c0000600000 | 0×0 | 0x30000000d000 | 11 |
0x4c0000760000 | 0x4c0000740000 | 0x4c0000700000 | 0×0 | 0x30000000f000 | 15 |
0x4c0000860000 | 0x4c0000840000 | 0x4c0000800000 | 0×0 | 0×300000011000 | 19 |
0x4c0000960000 | 0x4c0000940000 | 0x4c0000900000 | 0×0 | 0×300000013000 | 23 |
0x4c0000a60000 | 0x4c0000a40000 | 0x4c0000a00000 | 0×0 | 0×300000015000 | 27 |
0x4c0000b60000 | 0x4c0000b40000 | 0x4c0000b00000 | 0×0 | 0×300000017000 | 31 |
For each entry, only two separate lpar are allocated by the hypervisor. Indeed, calling lv1_query_logical_partition_address_region_info on priv2_addr, problem_phys, local_store_phys and shadow_addr for the first entry returns the following info:
0x4c0000660000lpar | start_address | size | access_right | max_page_size | flags | comment |
---|---|---|---|---|---|---|
0x4c0000600000 | 524288 | 0×3 (RW) | 12 | 0xa000000000000000 | SPU MMIO lpar, privilege state 2 region (128kB) | |
0x4c0000640000 | 0x4c0000600000 | 524288 | 0×3 (RW) | 12 | 0xa000000000000000 | SPU MMIO lpar, problem state region (128kB) |
0x4c0000600000 | 0x4c0000600000 | 524288 | 0×3 (RW) | 12 | 0xa000000000000000 | SPU MMIO lpar, local store region (256kB) |
0x30000000d000 | 0x30000000d000 | 4096 | 0×1 (RO) | 12 | 0xa000000000000000 | SPU shadow registers lpar (4kB, read-only) |
From this info we see a single lpar is used for all the SPU MMIO region (see figure 5-1 CBE Memory Map of the Cell Broadband Engine Programming Handbook) and another lpar is used for the SPE registers.
lv1_set_spe_interrupt_mask
Set the interrupt mask of a specific spe.
Kernel Call
lv1_set_spe_interrupt_mask( /*IN*/ spe_id, class, mask );
Parameters
Inputs | |
---|---|
Register | Description |
R3 | spe_id - spe id |
R4 | class - spe interrupt class |
R5 | mask - spe interrupt mask |
Outputs | |
Register | Description |
R3 | Status? |
lv1_undocumented_function_62
Exists in PAL 1.7; Returned -4 (LV1_DENIED_BY_POLICY) when passed 0 in R3 to R10.
lv1_undocumented_function_63
Does not exist in 3.15.
Exists in PAL 1.7; Returned -4 (LV1_DENIED_BY_POLICY) when passed 0 in R3 to R10.
lv1_set_spe_transition_notifier
Not used in current kernel.
Abstract Call
result = lv1_set_spe_transition_notifier( /*IN*/ p1, p2, p3 );
Parameters
Inputs | |
---|---|
Register | Description |
R3 | spe_id - logical spe id |
R4 | 0 - Unknown usage |
Outputs | |
Register | Description |
R3 | Status - 0 = OK, Other values are unknown, but indicate failure. |
lv1_disable_logical_spe
Disables a logical SPE.
Kernel Call
result = lv1_disable_logical_spe( /*IN*/ spe_id, 0 );
Parameters
Inputs | |
---|---|
Register | Description |
R3 | spe_id - logical spe id |
R4 | 0 - Unknown usage |
Outputs | |
Register | Description |
R3 | Status - 0 = OK, Other values are unknown, but indicate failure. |
lv1_clear_spe_interrupt_status
Clear the interrupt status of a specific spe.
Kernel Call
lv1_clear_spe_interrupt_status( /*IN*/ spe_id, class, stat, 0 );
Parameters
Inputs | |
---|---|
Register | Description |
R3 | spe_id - logical spe id |
R4 | class - spe interrupt class |
R5 | stat - new interrupt status? |
R6 | 0 - Unknown |
Outputs | |
Register | Description |
R3 | Status? |
lv1_get_spe_interrupt_status
Get the interrupt status of a specific spe.
Kernel Call
lv1_get_spe_interrupt_status( /*IN*/ spe_id, class, /*OUT*/ &stat );
Parameters
Inputs | |
---|---|
Register | Description |
R3 | spe_id - logical spe id |
R4 | class - spe interrupt class |
Outputs | |
Register | Description |
R3 | Status? |
R4 | stat - interrupt status |
lv1_get_logical_ppe_id
Returns the logical PPE id.
Kernel Call
status = lv1_get_logical_ppe_id( /*OUT*/ &ppe_id );
Parameters
Outputs | |
---|---|
Register | Description |
R3 | Status? |
R4 | logical PPE id |
Notes:
When called from kernel module init function, ppe_id always seem to be 1.