HV Syscall Reference

From PS3 Developer wiki
Revision as of 21:35, 18 May 2011 by MikeM6464 (talk | contribs) (Upto syscall 78 ported)
Jump to navigation Jump to search

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
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