HV Syscall Reference

From PS3 Developer wiki
Revision as of 04:04, 19 May 2011 by MikeM6464 (talk | contribs) (Upto syscall 183 ported)
Jump to navigation Jump to search

HV Syscalls

NOTE: Update with graf's work. It'll probably fill in some of the undocumented functions.

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
bit 62: destruction_scheme: DS_NO_CONNECTIONS = 0×00, DS_ANYTIME = 0×02
bit 61: fail or alternative: FA_FAIL = 0×00, FA_ALTERNATIVE = 0×04
bit 60: need LPAR address 0: ADDR_ANY = 0×00, ADDR_0 = 0×08
function unknown.

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
R3
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)
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:

0x4c0000660000
lpar 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.


lv1_set_interrupt_mask

Not used in current kernel.

Abstract Call
result = lv1_set_interrupt_mask( /*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_logical_partition_id

Called during Kernel setup.

The single output parameter, logical partition id, is later used as a parameter to call other Hypervisor functions.

Kernel Call
result = lv1_get_logical_partition_id(/*OUT*/ &lp_id );
Parameters
Outputs
register Description
R3 result: 0 = LV1_SUCCESS
R4 lp_id - logical partition id

Notes:

When called from kernel module init function, lp_id always seems to be 2.

The “read_node” function contained in “repository.c” is passed a parameter, lpar_id (logical partition id). If lpar_id is equal to PS3_LPAR_ID_CURRENT (0) then lv1_get_logical_partition_id is called to retrieve the current logical partition id. Any other value for lpar_id is passed directly to the following HV calls, though the only other value in use appears to be PS3_LPAR_ID_PME (1)


lv1_undocumented_function_75

Exists in PAL 1.7; Returned 0 (LV1_SUCCESS) when passed 0 in R3 to R10.


lv1_configure_execution_time_variable

Not used in current kernel.

Abstract Call
result = lv1_configure_execution_time_variable( /*IN*/ p1 );
Parameters
Inputs
Register Description
R3 p1 - Unknown
Outputs
Register Description
R3 Status?

lv1_get_spe_irq_outlet

Get an IRQ outlet of a certain class from the specified SPE.

Kernel Call
result = lv1_get_spe_irq_outlet( /*IN*/ spe_id, class, /*OUT*/ &outlet );
Parameters
Inputs
Register Description
R3 spe_id - logical spe id
R4 class - spe interrupt class (0, 1 or 2)
Outputs
Register Description
R3 Status - 0 = OK, Other values are unknown, but indicate failure.
R4 outlet - irq outlet

SPE Interrupt Class:

Class Description Examples
0 Errors SPE errors, DMA errors, DMA alignment errors
1 DMA translation exceptions MFC page faults, segment faults
2 Application events SPE stop and signal, DMA completion interrupt, mailbox interrupts

lv1_set_spe_privilege_state_area_1_register

Sets a register in SPE privilege area 1.

Kernel Call
lv1_set_spe_privilege_state_area_1_register( /*IN*/ spe_id, offset, value );
Parameters
Inputs
Register Description
R3 spe_id - spe id
R4 offset - register offset, 0, 0x600, 0x710, 0x808, 0x820
R5 value - register value
Outputs
Register Description
R3 Status?

lv1_undocumented_function_89

Exists in PAL 1.7; Returned -6 (LV1_NO_ENTRY) when passed 0 in R3 to R10.


lv1_create_repository_node

The repository appears to be an area of storage for use by the Hypervisor.

Abstract Call
status = lv1_create_repository_node(/*IN*/ n1, n2, n3, n4, v1, v2 );
Parameters
Inputs
Register Description
R3 top level key
R4 2nd level key
R5 3rd level key
R6 4th level key
R7 value 1
R8 value 2
Outputs
Register Description
R3 Status - 0 = OK, Other values are unknown, but indicate failure.

Notes:

This call is not used within the current Kernel, so the parameter list is based on speculation. It will still return 0 if the specified node already exists, and it will not change current data.

See “lv1_get_repository_node_value” for an example of actual key/value usage within the Kernel.


lv1_get_repository_node_value

The repository appears to be an area of storage for use by the Hypervisor. 256-bit keys are used to reference 128-bit values stored in the repository. Functions exist to create, get, modify and remove repository nodes.

See notes below for usage speculation.

Kernel Call
status = lv1_get_repository_node_value(/*IN*/ lpar_id, n1, n2, n3, n4 /*OUT*/ &v1, &v2 );
Parameters
Inputs
Register Description
R3 logical partion id
R4 top level key
R5 2nd level key
R6 3rd level key
R7 4th level key
Outputs
Register Description
R3 Status: 0 = OK, -6 = LV1_NO_ENTRY
R4 value 1
R5 value 2

Notes:

The logical partition id is also required as an input parameter to get a repository node value, but this parameter does not appear to be passed when creating, modifying or removing nodes.

There are instances in the Kernel code where the keys are constructed from string values, which appear to follow a 4-level key/subkey hierarchy.

Test Results

Calling lv1_get_repository_node_value for the node ‘bi.pu.#1.rm_size’ produces the following result:

bi.pu.(1).rm_size - Real mode memory size
Register Hex Value Value Comment
R3 0000000000000002 (2) PS3_LPAR_ID_CURRENT
R4 0000000062690000 ....bi.. boot info?
R5 7075000000000000 pu...... processor unit
R6 0000000000000001 ........ pu id (1)
R7 726d5f73697a6500 rm_size. real mode size
Outputs
R3 0000000000000000 (0) LV1_SUCCESS
R4 0000000008000000 (134217728) 128 Mb
R5 0000000000000000 (0)

Other nodes referenced in “repository.c”:

lpar_id = PS3_LPAR_ID_CURRENT (0×2)
Node v1 v2 Comment
bi.spun.#0.#0 0000000000000006 (6) 0 (0) number of physical spus reserved
bi.spursvn.#0.#0 0000000000000006 (6) 0 (0) number of spu resource reservations
bi.spursv.(0..5).#0 8000000000000000 (PS3_SPU_RESOURCE_TYPE_EXCLUSIVE) (0..5) spu resource reservation id value
bi.boot_dat.address.#0 0000000007fff000 (134213632) 0 (0) boot data address
bi.boot_dat.size.#0 0000000000000800 (2048) 0 (0) boot data size
bi.pu.(1).rm_size 0000000008000000 (134217728) 0 (0) real mode limit
bi.rgntotal.#0.#0 000000000f800000 (260046848) 0 (0) max memory size
lpar_id = PS3_LPAR_ID_PME (0×1)
Node v1 v2 Comment
ben.#0.#0.#0 0000000000000001 (1) 0000000000000000 (0) Unused - in function “ps3_repository_read_num_be”
be(0).#0.#0.#0 0000000000000000 (0) 0000000000000000 (0) be node id (used to retrieve clock freq)
be.(0).clock.#0 0000000004c1a6c0 (79800000) 0000000000000000 (0) decrementer frequency (3.2 Ghz / 40)
lpar_id = PS3_LPAR_ID_PME (0×1) - FW 3.15 PAL 60GB PS3, First Generation (Fat)
Node v1 v2 Comment
sys.flash.fmt.#0 00000000000001 (1) 00000000000000 (0) Flash format.
v1: 1 = NAND , 2 = VFLASH?
sys.hw.config.#0 20000000fffffeff 00000000000000 (0) 0×20000000000000 mask + something
sys.flash.ext.#0 000000000000ff (255) 00000000000000 (0)
plat.id.#0.#0 436f6b4231300000 (ASCII‘CokB10’) 00000000000000 (0) Platform ID
sys.ac.sd.#0 00000000000000 (0) 00000000000000 (0)
sys.flash.boot.#0 00000000000000 (0) 00000000000000 (0)
be.0.lpm.priv 00000000000002 (2) 00000000780101 (7864577)
rsx.rdcy.1.#0 ffff0d020a02ffff 00000000000000 (0)
rsx.rdcy.2.#0 ffffffffffffffff 00000000000000 (0)
rsx.rdcy.3.#0 00000000000000 (0) 00000000000000 (0)
rsx.rdcy.4.#0 00000000000000 (0) 00000000000000 (0)
rsx.rdcy.5.#0 00000000000000 (0) 00000000000000 (0)
rsx.rdcy.6.#0 00000000000000 (0) 00000000000000 (0)
rsx.rdcy.7.#0 00000000000000 (0) 00000000000000 (0)
rsx.rdcy.8.#0 00000000000000 (0) 00000000000000 (0)
mu.1.size.#0 00000010000000 (268435456) 00000000000000 (0)
be.0.tb_clk.#0 00000004c1a6c0 (79800000) 00000000000000 (0)
be.0.nclk.#0 000000be420e00 (3192000000) 00000000000000 (0)
ios.net.eurus.lpar 00000000000000 (0) 00000000000000 (0)
sys.syscon.pversion.#0 00000000000001 (1) 00000000000000 (0)
sys.param.load.rom1st 00000000000001 (1) 00000000000000 (0)
lv1.maxplgid.#0.#0 00000000000100 (256) 00000000000000 (0)
lv1.specver.#0.#0 00000300010005 00000000000000 (0) Matches firmware 3.1.5
lv1.buildid.#0.#0 00000000000000 (0) 00000000000000 (0)
lv1.ts.size.#0 00000000000000 (0) 00000000000000 (0)
lv1.ts.start.#0 00000010000000 (268435456) 00000000000000 (0)

lv1_modify_repository_node_value

The repository appears to be an area of storage for use by the Hypervisor.

Abstract Call
status = lv1_modify_repository_node_value(/*IN*/ n1, n2, n3, n4, v1, v2 );
Parameters
Inputs
Register Description
R3 top level key
R4 2nd level key
R5 3rd level key
R6 4th level key
R7 value 1
R8 value 2
Outputs
Register Description
R3 Status - 0 = OK, Other values are unknown, but indicate failure.

Parameter list based on speculation. Not used in current Kernel.


lv1_remove_repository_node

The repository appears to be an area of storage for use by the Hypervisor.

Abstract Call
status = lv1_remove_repository_node( /*IN*/ n1, n2, n3, n4 );
Parameters
Inputs
Register Description
R3 top level key
R4 2nd level key
R5 3rd level key
R6 4th level key
Outputs
Register Description
R3 Status - 0 = OK, Other values are unknown, but indicate failure.

Parameter list based on speculation. Not used in current Kernel.


lv1_read_htab_entries

Not used in current Kernel.

Abstract Call
result = lv1_read_htab_entries( /*IN*/ p1, p2, /*OUT*/ &v1, &v2, &v3, &v4, &v5 );
Parameters
Inputs
Register Description
R3 p1 - vas_id
R4 p2 - offset
Outputs
Register Description
R3 Status?
R4 v1 - unknown
R5 v2 - unknown
R6 v3 - unknown
R7 v4 - unknown
R8 v5 - unknown

Notes: offset is 64-bit indexed. r4-r7 seem to be right from the htab. r8 is 16-bit indexed reading from something 0xFFFB is max offset


lv1_set_dabr

Sets dabr (data address breakpoint register) - an exception should be thrown upon access to data at this address (range?)

Kernel Call
result = lv1_set_dabr( /*IN*/ dabr, DABR_KERNEL | DABR_USER);
Parameters
Inputs
Register Description
R3 dabr - data address
R4 DABR_USER) - see notes
Outputs
Register Description
R3 Status - 0 = OK, Other values are unknown, but indicate failure.

Notes:

DABR_KERNEL and DABR_USER are defined in “setup.c” as follows

enum {DABR_USER = 1, DABR_KERNEL = 2,};

lv1_set_vmx_graphics_mode

Set the Single Precision mode of the vmx graphics units in the PPU

Abstract Call
result = lv1_set_vmx_graphics_mode( mode );
Parameters
Inputs
Register Description
R3 mode - 0 = IEEE 754-1985 SIMD rounding mode for VMX/Altivec Instructions
mode - 1 = SPE-compatible SIMD graphics-rounding mode for VMX/Altivec Instructions
Outputs
Register Description
R3 result: 0 = LV1_SUCCESS, -17 = LV1_ILLEGAL_PARAMETER_VALUE

Notes:

This is a call to set the single precision rounding mode of the VMX units in the Cell PPUs. The AltiVec/VMX SIMD/Vector processing unit has 2 rounding modes for dealing with Single-precision floating-point. IEEE 754-1985 and SPE-compatible SIMD graphics-rounding mode.

The Cell Broadband Engine Programming Handbook has this to say on the subject: The first implementation of the Cell Broadband Engine Architecture (CBEA) (the CBE processor) supports instructions with a graphics rounding mode. This mode allows programs written with vector/SIMD multimedia extension instructions to produce floating-point results that are equivalent in precision to those written in the SPU instruction set. In this mode, as in the SPU environment, the default rounding mode is round to zero, denormals are treated as zero, and there are no infinities or NaNs.

To change this mode, bit 12 in the HID1 register (known as grap_md or grap_mode in various documents). HID1 is a HV privileged resource, hence to change the mode from Supervisor mode requires a HV call.

Reference Documents: Cell Broadband Engine Programming Handbook V1.1 Cell Broadband Engine Registers V1.5

Tests:

Info taken from kboot-10\dl\linux-2.6.16\include\asm-powerpc\lv1calltab.h (kboot-20061208)

When recompiled into Kernel module init function, accepts values of 0 and 1 for p1. All other values return -17 (LV1_ILLEGAL_PARAMETER_VALUE)


lv1_set_thread_switch_control_register

Not used in current Kernel.

Abstract Call
result = lv1_set_thread_switch_control_register( /*IN*/ p1 );
Parameters
Inputs
Register Description
R3 p1 - Unknown
Outputs
Register Description
R3 Status?

Notes:

Info taken from kboot-10\dl\linux-2.6.16\include\asm-powerpc\lv1calltab.h (kboot-20061208)


lv1_undocumented_function_99

Exists in PAL 1.7; Returned -4 (LV1_DENIED_BY_POLICY) when passed 0 in R3 to R10.


lv1_undocumented_function_102

Exists in PAL 1.7; Returned 0 (LV1_SUCCESS) and R4 = 0x692F5D1E7h when passed 0 in R3 to R10.


lv1_get_total_execution_time

Not used in current kernel. Does not exist in 3.15 HV dump.

Abstract Call
result = lv1_get_total_execution_time( /*IN*/ p1, p2, /*OUT*/ &v1 );
Parameters
Inputs
Register Description
R3 p1 - Unknown
R4 p2 - Unknown
Outputs
Register Description
R3 Status?
R4 v1 - Unknown

Notes:

I always get LV1_NOT_IMPLEMENTED


lv1_undocumented_function_105

Exists in PAL 1.7. Returns -17 (LV1_ILLEGAL_PARAMETER_VALUE, 0, 0, C000000000537EF8h, F09B89AF5001h, 6C0061D8E190h, C0000000008DF718h, F09B89AF5001h, when passed 0 in R3 to R10.


lv1_undocumented_function_106

Exists in PAL 1.7. Returns the same as lv1_undocumented_function_105.


lv1_undocumented_function_107

Exists in PAL 1.7. Returns the same as lv1_undocumented_function_105.


lv1_undocumented_function_108

Exists in PAL 1.7. Returns the same as lv1_undocumented_function_105.


lv1_undocumented_function_109

Exists in PAL 1.7. Returns the same as lv1_undocumented_function_105.


lv1_undocumented_function_110

Exists in PAL 1.7. Returns -6 (LV1_NO_ENTRY) in R3, rest same as lv1_undocumented_function_105.


lv1_undocumented_function_111

Exists in PAL 1.7. Returns -6 (LV1_NO_ENTRY) in R3, rest same as lv1_undocumented_function_105.


lv1_undocumented_function_112

Exists in PAL 1.7. Returns -6 (LV1_NO_ENTRY) in R3, rest same as lv1_undocumented_function_105.


lv1_undocumented_function_114

Exists in PAL 1.7. Returns -17 (LV1_ILLEGAL_PARAMETER_VALUE) in R3, 0 in R4-R10. Passed 0 in R3 to R10.


lv1_undocumented_function_115

Exists in PAL 1.7. Returns -8 (LV1_TYPE_MISMATCH) in R3, 0 in R4-R10. Passed 0 in R3 to R10.


lv1_allocate_io_segment

Allocate an io segment.

kboot Call
result = lv1_allocate_io_segment( /*IN*/ ioas_id, segment_size, io_page_size, /*OUT*/ &ioif_addr );
Parameters
Inputs
Register Description
R3 ioas_id - io address space id
R4 segment_size - io segment size
R5 io_page_size - io page size, 0xC, 0×10, 0×14
Outputs
Register Description
R3 Status - 0 = OK, Other values are unknown, but indicate failure.
R4 ioif_addr - io interface address

Notes:

Code taken from kboot-10\dl\linux-2.6.16\sound\powerpc\snd_ps3pf.c (kboot-20061208)

ret64 = lv1_allocate_io_segment(0,           /* io space */
   IO_SEGMENTSIZE, /* segment size */
   IO_PAGESIZE_SHIFT, /* io page size */
   &(ioif_map_info_array[current_segment].ioif_addr));

lv1_release_io_segment

Release an io segment.

kboot Call
result = lv1_release_io_segment( /*IN*/ ioas_id, ioif_addr );
Parameters
Inputs
Register Description
R3 ioas_id - io address space id
R4 ioif_addr - io interface address
Outputs
Register Description
R3 Status - 0 = OK, Other values are unknown, but indicate failure.

Notes:

Code taken from kboot-10\dl\linux-2.6.16\sound\powerpc\snd_ps3pf.c (kboot-20061208)

ret64 = lv1_release_io_segment(0, /* io space */
   ioif_map_info_array[current_segment].ioif_addr);

lv1_allocate_ioid

Not used in current kernel.

Abstract Call
result = lv1_allocate_ioid( /*IN*/ p1, /*OUT*/ &v1 );
Parameters
Inputs
Register Description
R3 SBZ
Outputs
Register Description
R3 Status?
R4 the ioid

Notes:

Info taken from kboot-10\dl\linux-2.6.16\include\asm-powerpc\lv1calltab.h (kboot-20061208)


lv1_release_ioid

Not used in current Kernel.

Abstract Call
result = lv1_release_ioid( /*IN*/ p1, p2 );
Parameters
Inputs
Register Description
R3 p1 - Unknown
R4 p2 - Unknown
Outputs
Register Description
R3 Status?

Notes:

Info taken from kboot-10\dl\linux-2.6.16\include\asm-powerpc\lv1calltab.h (kboot-20061208)


lv1_construct_io_irq_outlet

Construct an outlet for a non-virtualized device interrupt.

Kernel Call
result = lv1_construct_io_irq_outlet( /*IN*/ interrupt_id, /*OUT*/ &outlet );
Parameters
Inputs
Register Description
R3 interrupt_id - interrupt id
Outputs
Register Description
R3 Status - 0 = OK, Other values are unknown, but indicate failure.
R4 outlet - interrupt outlet

lv1_destruct_io_irq_outlet

Destruct a previously constructed device interrupt outlet.

Kernel Call
result = lv1_destruct_io_irq_outlet( /*IN*/ outlet );
Parameters
Inputs
Register Description
R3 outlet - interrupt outlet
Outputs
Register Description
R3 Status - 0 = OK, Other values are unknown, but indicate failure.

lv1_map_htab

Map the hash page table.

Kernel Call
result = lv1_map_htab( /*IN*/ 0, /*OUT*/ &htab_addr );
Parameters
Inputs
Register Description
R3 0 - Unknown (lpid?)
Outputs
Register Description
R3 Status?
R4 htab_addr - hash page table address

Notes:

In “htab.c” return code is assigned, but not used. Must be translated and ioremapped before it can be used in the kernel. It’s 1MB long


lv1_unmap_htab

Unmap the hash page table.

Kernel Call
lv1_unmap_htab( /*IN*/ htab_addr );
Parameters
Inputs
Register Description
R3 htab_addr - hash page table address
Outputs
Register Description
R3 Status?

lv1_undocumented_function_124

Exists in PAL 1.7. Returns -6 (LV1_NO_ENTRY) in R3, rest same as lv1_undocumented_function_105.


lv1_undocumented_function_125

Exists in PAL 1.7. Returns -6 (LV1_NO_ENTRY) in R3, rest same as lv1_undocumented_function_105.


lv1_undocumented_function_126

Exists in PAL 1.7. Returns -6 (LV1_NO_ENTRY) in R3, rest same as lv1_undocumented_function_105.


lv1_get_version_info

Returns PS3 firmware version information.

Kernel Call
result = lv1_get_version_info( /*OUT*/ &raw );
Parameters
Outputs
Register Description
R3 Status - 0 = OK, Other values are unknown, but indicate failure.
R4 raw - firmware data (see notes)

Notes:

The firmware information is accessed using the following union:

union ps3_firmware_version {
	u64 raw;
	struct {
		u16 pad;
		u16 major;
		u16 minor;
		u16 rev;
	};
};

lv1_undocumented_function_134

Exists in PAL 1.7. Returns 0 when passed R3-R10=0.


lv1_undocumented_function_135

Exists in PAL 1.7. Returns -6 (LV1_NO_ENTRY) in R3, rest same as lv1_undocumented_function_105.


lv1_undocumented_function_136

Exists in PAL 1.7. Returns -6 (LV1_NO_ENTRY) in R3, rest same as lv1_undocumented_function_105.


lv1_undocumented_function_137

Exists in PAL 1.7. Returns -4 (LV1_DENIED_BY_POLICY) when passed 0 in R3-R10.


lv1_undocumented_function_138

Exists in PAL 1.7. Returns -4 (LV1_DENIED_BY_POLICY) when passed 0 in R3-R10.


lv1_construct_lpm

Not used in current kernel.

Abstract Call
result = lv1_construct_lpm( /*IN*/ p1, p2, p3, p4, p5, p6, /*OUT*/ &v1, &v2, &v3 );
Parameters
Inputs
Register Description
R3 p1 - node_id, this is the node id of the processor, 0 is only valid value
R4 p2 - tb_type, 0 is none, 1 is internal
R5 p3 - Unknown, is 0
R6 p4 - Unknown, is 0
R7 p5 - tb_cache in lpar, 128 byte aligned
R8 p6 - tb_cache_size
Outputs
Register Description
R3 Status
R4 v1 - lpm_id
R5 v2 - outlet_id
R6 v3 - tb_size

lv1_destruct_lpm

Not used in current kernel.

Abstract Call
result = lv1_destruct_lpm( /*IN*/ p1 );
Parameters
Inputs
Register Description
R3 p1 - lpm_id
Outputs
Register Description
R3 Status?

lv1_start_lpm

Not used in current kernel.

Abstract Call
result = lv1_start_lpm( /*IN*/ p1 );
Parameters
Inputs
Register Description
R3 p1 - lpm_id
Outputs
Register Description
R3 Status?

lv1_stop_lpm

Not used in current kernel.

Abstract Call
result = lv1_stop_lpm( /*IN*/ p1, /*OUT*/ &v1 );
Parameters
Inputs
Register Description
R3 p1 - Unknown
Outputs
Register Description
R3 Status?
R4 v1 - Unknown

lv1_copy_lpm_trace_buffer

Not used in current kernel.

Abstract Call
result = lv1_copy_lpm_trace_buffer( /*IN*/ p1, p2, p3 /*OUT*/ &v1 );
Parameters
Inputs
Register Description
R3 p1 - lpm_id
R3 p2 - offset
R3 p3 - request
Outputs
Register Description
R3 Status
R4 v1 - tmp

lv1_add_lpm_event_bookmark

Not in current kernel.

Abstract Call
result = lv1_add_lpm_event_bookmark( /*IN*/ p1, p2, p3, p4, p5 );
Parameters
Inputs
Register Description
R3 p1 - Unknown
R3 p2 - Unknown
R3 p3 - Unknown
R6 p4 - Unknown
R7 p5 - Unknown
Outputs
Register Description
R3 Status?

lv1_delete_lpm_event_bookmark

Not used in current kernel.

Abstract Call
result = lv1_delete_lpm_event_bookmark( /*IN*/ p1, p2, p3 );
Parameters
Inputs
Register Description
R3 p1 - Unknown
R3 p2 - Unknown
R3 p3 - Unknown
Outputs
Register Description
R3 Status?

lv1_set_lpm_interrupt_mask

Not used in current kernel.

Abstract Call
result = lv1_set_lpm_interrupt_mask( /*IN*/ p1, p2, p3, /*OUT*/ &v1 );
Parameters
Inputs
Register Description
R3 p1 - Unknown
R3 p2 - Unknown
R3 p3 - Unknown
Outputs
Register Description
R3 Status?
R4 v1 - Unknown

lv1_get_lpm_interrupt_status

Not used in current kernel.

Abstract Call
result = lv1_get_lpm_interrupt_status( /*IN*/ p1, /*OUT*/ &v1 );
Parameters
Inputs
Register Description
R3 p1 - Unknown
Outputs
Register Description
R3 Status?
R4 v1 - Unknown

lv1_set_lpm_general_control

Not used in current kernel.

Abstract Call
result = lv1_set_lpm_general_control( /*IN*/ p1, p2, p3, p4, p5, /*OUT*/ &v1, &v2 );
Parameters
Inputs
Register Description
R3 p1 - Unknown
R4 p2 - Unknown
R5 p3 - Unknown
R6 p4 - Unknown
R7 p5 - Unknown
Outputs
Register Description
R3 Status?
R4 v1 - Unknown
R5 v2 - Unknown

lv1_set_lpm_interval

Not used in current kernel.

Abstract Call
result = lv1_set_lpm_interval( /*IN*/ p1, p2, p3, /*OUT*/ &v1 );
Parameters
Inputs
Register Description
R3 p1 - Unknown
R4 p2 - Unknown
R5 p3 - Unknown
Outputs
Register Description
R3 Status?
R4 v1 - Unknown

lv1_set_lpm_trigger_control

Not used in current kernel.

Abstract Call
result = lv1_set_lpm_trigger_control( /*IN*/ p1, p2, p3, /*OUT*/ &v1 );
Parameters
Inputs
Register Description
R3 p1 - Unknown
R4 p2 - Unknown
R5 p3 - Unknown
Outputs
Register Description
R3 Status?
R4 v1 - Unknown

lv1_set_lpm_counter_control

Not used in current kernel.

Abstract Call
result = lv1_set_lpm_counter_control( /*IN*/ p1, p2, p3, p4, /*OUT*/ &v1 );
Parameters
Inputs
Register Description
R3 p1 - Unknown
R4 p2 - Unknown
R5 p3 - Unknown
R6 p4 - Unknown
Outputs
Register Description
R3 Status?
R4 v1 - Unknown

lv1_set_lpm_group_control

Not used in current kernel.

Abstract Call
result = lv1_set_lpm_group_control( /*IN*/ p1, p2, p3, /*OUT*/ &v1 );
Parameters
Inputs
Register Description
R3 p1 - Unknown
R4 p2 - Unknown
R5 p3 - Unknown
Outputs
Register Description
R3 Status?
R4 v1 - Unknown

lv1_set_lpm_debug_bus_control

Not used in current kernel.

Abstract Call
result = lv1_set_lpm_debug_bus_control( /*IN*/ p1, p2, p3, /*OUT*/ &v1 );
Parameters
Inputs
Register Description
R3 p1 - Unknown
R4 p2 - Unknown
R5 p3 - Unknown
Outputs
Register Description
R3 Status?
R4 v1 - Unknown

lv1_set_lpm_counter

Not used in current kernel.

Abstract Call
result = lv1_set_lpm_counter( /*IN*/ p1, p2, p3, p4, p5, /*OUT*/ &v1, &v2 );
Parameters
Inputs
Register Description
R3 p1 - Unknown
R4 p2 - Unknown
R5 p3 - Unknown
R6 p4 - Unknown
R7 p5 - Unknown
Outputs
Register Description
R3 Status?
R4 v1 - Unknown
R5 v2 - Unknown

lv1_set_lpm_signal

Not used in current kernel.

Abstract Call
result = lv1_set_lpm_signal( /*IN*/ p1, p2, p3, p4, p5, p6, p7 );
Parameters
Inputs
Register Description
R3 p1 - Unknown
R4 p2 - Unknown
R5 p3 - Unknown
R6 p4 - Unknown
R7 p5 - Unknown
R8 p6 - Unknown
R9 p7 - Unknown
Outputs
Register Description
R3 Status?

lv1_set_lpm_spr_trigger

Not used in current kernel.

Abstract Call
result = lv1_set_lpm_spr_trigger( /*IN*/ p1, p2 );
Parameters
Inputs
Register Description
R3 p1 - Unknown
R4 p2 - Unknown
Outputs
Register Description
R3 Status?

lv1_insert_htab_entry

Used in current kernel.

Kernel Call
result = lv1_insert_htab_entry( /*IN*/ p1, p2, p3, p4, p5, p6, /*OUT*/ &v1, &v2, &v3 );
Parameters
Inputs
Register Description
R3 p1 - htab ID, 0 or returns -6
R4 p2 - hpte_group, 0 or returns -17
R5 p3 - hpte_v
R6 p4 - hpte_r
R7 p5 - Bolted flag
R8 p6 - flags?
Outputs
Register Description
R3 Status?
R4 v1 - inserted_index
R5 v2 - evicted_v
R6 v3 - evicted_r

Notes: Kernel usage:

result = lv1_insert_htab_entry(PS3_LPAR_VAS_ID_CURRENT, hpte_group,
				       hpte_v, hpte_r,
				       HPTE_V_BOLTED, 0,
				       &inserted_index,
				       &evicted_v, &evicted_r);

lv1_read_virtual_uart

Read data from a VUART port into a provided buffer.

Kernel Call
result = lv1_read_virtual_uart( /*IN*/ port_number, buffer, bytes, /*OUT*/ bytes_read );
Parameters
Inputs
Register Description
R3 port_number - VUART port number
R4 buffer - pointer to buffer (must be address in lpar)
R5 bytes - buffer size?
Outputs
Register Description
R3 Status - 0 = OK, Other values are unknown, but indicate failure.
R4 bytes_read - number of bytes read into buffer

lv1_write_virtual_uart

Write a buffer of data to a VUART port.

Kernel Call
result = lv1_write_virtual_uart( /*IN*/ port_number, buffer, bytes, /*OUT*/ bytes_written );
Parameters
Inputs
Register Description
R3 port_number - VUART port number
R4 buffer - pointer to buffer (must be address in lpar)
R5 bytes - buffer size?
Outputs
Register Description
R3 Status - 0 = OK, Other values are unknown, but indicate failure.
R4 bytes_written - number of bytes written to VUART

lv1_set_virtual_uart_param

Set a parameter for a port on the VUART.

Kernel Call
result = lv1_set_virtual_uart_param( /*IN*/ port_number, param_id, param_value );
Parameters
Inputs
Register Description
R3 port_number - VUART port number
R4 param_id - id of parameter to set (see notes)
R5 param_value - parameter value
Outputs
Register Description
R3 Status - 0 = OK, Other values are unknown, but indicate failure.

See lv1_get_virtual_uart_param for parameter information.


lv1_get_virtual_uart_param

Get a parameter for a port on the VUART.

Kernel Call
result = lv1_get_virtual_uart_param( /*IN*/ port_number, param_id, /*OUT*/ &param_value );
Parameters
Inputs
Register Description
R3 port_number - VUART port number
R4 param_id - id of parameter to set (see notes)
Outputs
Register Description
R3 Status - 0 = OK, Other values are unknown, but indicate failure.
R4 param_value - parameter value

VUART parameters defined in vuart.c:

Parameter param_id Notes
PARAM_TX_TRIGGER 0
PARAM_RX_TRIGGER 1
PARAM_INTERRUPT_MASK 2
PARAM_RX_BUF_SIZE 3 read only
PARAM_RX_BYTES 4 read only
PARAM_TX_BUF_SIZE 5 read only, not referenced in current Kernel
PARAM_TX_BYTES 6 read only, not referenced in current Kernel
PARAM_INTERRUPT_STATUS 7 read only

lv1_configure_virtual_uart_irq

Configure the VUART IRQ.

Kernel Call
result = lv1_configure_virtual_uart_irq( /*IN*/ lpar_addr, /*OUT*/ &outlet );
Parameters
Inputs
Register Description
R3 lpar_addr - logical partition address of virtual uart interrupt bitmap
Outputs
Register Description
R3 Status - 0 = OK, Other values are unknown, but indicate failure.
R4 outlet - irq outlet

Notes:

Comment from interrupt.c:

/**
* The system supports only a single virtual uart, so multiple calls without
* freeing the interrupt will return a wrong state error.
*/

lv1_undocumented_function_167

Exists on PAL 1.7. Returns -4 (LV1_DENIED_BY_POLICY) when passed 0 in R3 to R10.


lv1_undocumented_function_168

Exists on PAL 1.7. Returns -4 (LV1_DENIED_BY_POLICY) when passed 0 in R3 to R10.


lv1_open_device

Open the device for a given bus and device id.

Kernel Call
result = lv1_open_device( /*IN*/ bus_id, dev_id, 0 );
Parameters
Inputs
Register Description
R3 bus_id - bus id
R4 dev_id - device id
R5 0 - Unknown
Outputs
Register Description
R3 Status: LV1_SUCCESS (0) - OK

LV1_NO_ENTRY (-6) - invalid dev_id LV1_BUSY (-9) - device already open LV1_ILLEGAL_PARAMETER_VALUE (-17) - invalid bus_id

Notes:

Valid values for bus_id and dev_id can be obtained from the repository (see lv1_get_repository_node_value).

Once open, functions such as lv1_map_device_mmio_region and lv1_allocate_device_dma_region can be used to map the device into memory.

The value of R5 does not seem to affect the outcome of the call (powers of 2 in the 64 bit range were tested). One reason for the flag could be to indicate whether to open the device in shared mode or not (and thus prevent the LV1_BUSY return code).


lv1_close_device

Close the device for a given bus and device id.

Kernel Call

result = lv1_close_device( /*IN*/ bus_id, dev_id );

Parameters
Inputs
Register Description
R3 bus_id - bus id
R4 dev_id - device id
Outputs
Register Description
R3 Status - 0 = OK, Other values are unknown, but indicate failure.

lv1_map_device_mmio_region

Map an MMIO region to the specified device.

Kernel Call
result = lv1_map_device_mmio_region( /*IN*/ bus_id, dev_id, bus_addr, size, page_size, /*OUT*/ &lpar_addr );
Parameters
Inputs
Register Description
R3 bus_id - bus id
R4 dev_id - device id
R5 bus_addr - address of the region
R6 size - size of the region
R7 page_size - page size of the region
Outputs
Register Description
R3 Status - 0 = OK, Other values are unknown, but indicate failure.
R4 lpar_addr - logical partition address of the mapped region

lv1_unmap_device_mmio_region

Unmap an MMIO region from the specified device.

Kernel Call
result = lv1_unmap_device_mmio_region( /*IN*/ bus_id, dev_id, lpar_addr );
Parameters
Inputs
Register Description
R3 bus_id - bus id
R4 dev_id - device id
R5 lpar_addr - logical partition address of the mapped region
Outputs
Register Description
R3 Status - 0 = OK, Other values are unknown, but indicate failure.

lv1_allocate_device_dma_region

Allocate a DMA region for the specified device.

Kernel Call
result = lv1_allocate_device_dma_region( /*IN*/ bus_id, dev_id, io_size, io_pagesize, flag, &dma_region );
Parameters
Inputs
Register Description
R3 bus_id - bus id
R4 dev_id - device id
R5 io_size - region size
R6 io_pagesize - specified as a PAGE_SHIFT (i.e. n where pagesize = 2^n)
R7 flag - 0=32 bit mode, 2=8 bit mode
Outputs
Register Description
R3 Status - 0 = OK, Other values are unknown, but indicate failure.
R4 dma_region - dma region address

Notes: When the device is little endian, the mode must be set to 8 bit for 8 bit DMA to work as expected, otherwise the bytes will be read/written in the wrong order. OTOH, this mode requires that 16 and 32-bit values are byte-swapped by the CPU since they will appear as little endian in memory.


lv1_free_device_dma_region

Free a previously allocated DMA region for the specified device.

Kernel Call
lv1_free_device_dma_region( /*IN*/ bus_id, dev_id, dma_region );
Parameters
Inputs
Register Description
R3 bus_id - bus id
R4 dev_id - device id
R5 dma_region - dma region address
Outputs
Register Description
R3 Status?

lv1_map_device_dma_region

Map a DMA region for the specified device.

Kernel Call
result = lv1_map_device_dma_region( /*IN*/ bus_id, dev_id, lpar_addr, dma_region, size, flags );
Parameters
Inputs
Register Description
R3 bus_id - bus id
R4 dev_id - device id
R5 lpar_addr - logical partition address
R6 dma_region - dma region address
R7 size - region size
R8 flags - see notes
Outputs
Register Description
R3 Status - 0 = OK, Other values are unknown, but indicate failure.

Notes:

In “mm.c” and “ps3_storage.c”, flags parameter is always specified as 0xf800000000000000UL. They are the same flags as the IOPTE entry ones.


lv1_unmap_device_dma_region

Unmap a DMA region for the specified device.

Kernel Call
result = lv1_unmap_device_dma_region( /*IN*/ bus_id, dev_id, dma_region, size );
Parameters
Inputs
Register Description
R3 bus_id - bus id
R4 dev_id - device id
R5 dma_region - dma region address
R6 size - region size
Outputs
Register Description
R3 Status - 0 = OK, Other values are unknown, but indicate failure.

lv1_read_pci_config

Read external PCI config. PS3tool only?

kboot Call
result = lv1_read_pci_config( /*IN*/ bus_id, pci_bus_id, dev_id, func_id, offset, size, /*OUT*/ &config_data );
Parameters
Inputs
Register Description
R3 bus_id - ps3 bus id
R4 pci_bus_id - pci bus id
R5 dev_id - pci device id
R6 func_id - pci function
R7 offset - offset to store data within config_data
R8 size - size of config_data
Outputs
Register Description
R3 Status - 0 = OK, Other values are unknown, but indicate failure.
R4 config_data - pci config data

Notes:

Code taken from kboot-10\dl\linux-2.6.16\arch\powerpc\platforms\ps3pf\pci.c (kboot-20061208)

status = lv1_read_pci_config(p->bus_id, p->bus_pci_bus, p->bus_pci_dev, p->bus_pci_func,
	(uint64_t)offset, size, &data);

lv1_write_pci_config

Write external PCI config. PS3tool only?

kboot Call
result = lv1_write_pci_config( /*IN*/ bus_id, pci_bus_id, dev_id, func_id, offset, size, config_data );
Parameters
Inputs
Register Description
R3 bus_id - ps3 bus id
R4 pci_bus_id - pci bus id
R5 dev_id - pci device id
R6 func_id - pci function
R7 offset - offset to store data within config_data
R8 size - size of config_data
R9 config_data - pci config data
Outputs
Register Description
R3 Status - 0 = OK, Other values are unknown, but indicate failure.

Notes:

Code taken from kboot-10\dl\linux-2.6.16\arch\powerpc\platforms\ps3pf\pci.c (kboot-20061208)

status = lv1_write_pci_config(p->bus_id, p->bus_pci_bus, p->bus_pci_dev, p->bus_pci_func,
   (uint64_t)offset, size, (uint64_t)val);
if(status) {
   /* lv1_write_pci_config can't write reg from 0x10 to 0x3f */
}

lv1_read_pci_io

Not used in current kernel.

Abstract Call
result = lv1_read_pci_io( /*IN*/ p1, p2, p3, p4, /*OUT*/ &v1 );
Parameters
Inputs
Register Description
R3 p1 - Unknown
R4 p2 - Unknown
R5 p3 - Unknown
R6 p4 - Unknown
Outputs
Register Description
R3 Status?
R4 v1 - Unknown

Notes:

Info taken from kboot-10\dl\linux-2.6.16\include\asm-powerpc\lv1calltab.h (kboot-20061208)


lv1_write_pci_io

Not used in current kernel.

Abstract Call
result = lv1_write_pci_io( /*IN*/ p1, p2, p3, p4, p5 );
Parameters
Inputs
Register Description
R3 p1 - Unknown
R4 p2 - Unknown
R5 p3 - Unknown
R6 p4 - Unknown
Outputs
Register Description
R3 Status?

Notes:

Info taken from kboot-10\dl\linux-2.6.16\include\asm-powerpc\lv1calltab.h (kboot-20061208)


lv1_undocumented_function_182

Exists in PAL 3.15. Nothing known so far.


lv1_undocumented_function_183

Exists in PAL 3.15. Nothing known so far.