Difference between revisions of "SceSysmem"

From Vita Development Wiki
Jump to navigation Jump to search
Line 477: Line 477:
//this signature is for 3.60 - now allows to give a name
//this signature is for 3.60 - now allows to give a name
int map_user_to_kernel(char *name, int permission, int type, void *user_buf, int size, void **kernel_page, int *kernel_size, int *kernel_offset)
int map_user_to_kernel(char *name, int permission, int type, void *user_buf, int size, void **kernel_page, int *kernel_size, int *kernel_offset);

Revision as of 23:35, 13 May 2017

SceSysmem is a kernel module that acts as the heart of the kernel. It exports multiple libraries for different functionalities (one of the few modules that do so). SceSysmem is the first module that is loaded in the kernel load sequence and its libraries are imported by almost all other modules. See Memory for more details on the memory subsystem.


This module exists in both non-secure and secure world. The non-secure world SELF can be found in os0:kd/sysmem.skprx. It also can be found in the Boot Image.

Known NIDs

Version Name World Privilege NID
1.69 SceSysmem Non-secure Kernel 0xB93950C6
3.60 SceSysmem ? Kernel 0x3380B323
3.61 SceSysmem Non-secure Kernel 0x3380B323
1.69 SceSysmem Secure Kernel 0x502BE0E5


This module only exports kernel libraries.

Known NIDs

Version Name World Visibility NID
1.69 SceSysmemForKernel Non-secure Kernel 0x63A519E5
3.60 SceSysmemForKernel ? Kernel 0x63A519E5
1.69 SceSysmemForDriver Non-secure Kernel 0x6F25E18A
3.60 SceSysmemForDriver ? Kernel 0x6F25E18A
1.69 SceSysmem Non-secure User 0x37FE725A
3.60 SceSysmem ? User 0x37FE725A
1.69 SceSysmemForDebugger Non-secure Kernel 0xC7309957
1.69 SceDipsw Non-secure User 0xB36D5922
3.60 SceDipsw ? User 0xB36D5922
1.69 SceDipswForDriver Non-secure Kernel 0xC9E26388
3.60 SceDipswForDriver ? Kernel 0xC9E26388
1.69 SceUartForKernel Non-secure Kernel 0xC03DBE40
3.60 SceUartForKernel ? Kernel 0xC03DBE40
1.69 SceCpu Non-secure User 0x45265161
3.60 SceCpu ? User 0x45265161
1.69 SceCpuForKernel Non-secure Kernel 0x54BF2BAB
3.60 SceCpuForKernel ? Kernel 0x54BF2BAB
1.69 SceCpuForDriver Non-secure Kernel 0x40ECDB0E
3.60 SceCpuForDriver ? Kernel 0x40ECDB0E
1.69 SceSysclibForKernel Non-secure Kernel 0x24878615
1.69 SceSysclibForDriver Non-secure Kernel 0x7EE45391
3.60 SceSysclibForDriver ? Kernel 0x7EE45391
1.69 SceSysrootForKernel Non-secure Kernel 0x3691DA45
3.60 SceSysrootForKernel ? Kernel 0x3691DA45
1.69 SceKernelUtilsForDriver Non-secure Kernel 0x496AD8B4
3.60 SceKernelUtilsForDriver ? Kernel 0x496AD8B4
1.69 SceZlibForDriver Non-secure Kernel 0xE241534E
1.69 SceKernelSuspendForDriver Non-secure Kernel 0x7290B21C
3.60 SceKernelSuspendForDriver ? Kernel 0x7290B21C
1.69 SceQafMgrForDriver Non-secure Kernel 0x4E29D3B6
3.60 SceQafMgrForDriver ? Kernel 0x4E29D3B6
1.69 ScePmMgrForDriver Non-secure Kernel 0xF13F32F9
3.60 ScePmMgrForDriver ? Kernel 0xF13F32F9
1.69 SceSblAIMgrForDriver Non-secure Kernel 0xFD00C69A
3.60 SceSblAIMgrForDriver ? Kernel 0xFD00C69A
1.69 SceProcEventForDriver Non-secure Kernel 0x887F19D0
3.60 SceProcEventForDriver ? Kernel 0x887F19D0
1.69 SceSysrootForDriver Non-secure Kernel 0x2ED7F97A
3.60 SceSysrootForDriver ? Kernel 0x2ED7F97A
3.60 SceDebugLed ? ? 0xAE004C0A
3.60 SceDebugLedForDriver ? Kernel 0x7BC05EAD
3.60 SceDebugForKernel ? Kernel 0x88C17370
3.60 SceDebugForDriver ? Kernel 0x88758561
1.69 SceSysmemForTZS Secure Kernel 0x8680060
1.69 SceDipswForTZS Secure Kernel 0x9DBF584C
1.69 SceCpuForTZS Secure Kernel 0xC516B23E
1.69 SceSysclibForTZS Secure Kernel 0xC839BB78
1.69 SceSysrootForTZS Secure Kernel 0xFEFF641D
1.69 SceQafMgrForTZS Secure Kernel 0x637069DD
1.69 ScePmMgrForTZS Secure Kernel 0x27F1AFD8
1.69 SceSblAIMgrForTZS Secure Kernel 0x60D19047

Memory Block Type

The type parameter indicates what kind of memory to allocate. Here is a mapping of type flags to ARM MMU flags. Higher bits are used for other options including where to allocate from. Not all flag values are valid, there is a table of valid types in the kernel. You cannot, for example, allocate RWX memory.

Mask Value Description
0x10000 0x10000 Global. nG bit NOT set
0xFF00 0x800 B bit set. Sharable device memory.
0xFF00 0x2000 TEX[2] and TEX[0] bit set. Outer cache Write-back, Write-Allocate. Inner cache non-cachable.
0xFF00 0x4000 TEX[2] and B bit set. Outer cache non-cachable. Inner cache Write-back, Write-Allocate
0xFF00 0x8000 TEX[0] bit set. S bit unset. Outer and inner non-cachable. Not sharable.
0xFF00 0xD000 TEX[0] bit set. C,B bits set. Outer and inner Write-back, Write-Allocate.
0xFF 0x4 AP[2:0] = 5, XN=1. Privileged RO, User NA.
0xFF 0x5 AP[2:0] = 5. Privileged RX, User NA.
0xFF 0x6 AP[2:0] = 1, XN=1. Privileged RW, User NA.
0xFF 0x7 AP[2:0] = 1. Privileged RWX, User NA. (Never used)
0xFF 0x50 AP[2:0] = 7. Privileged RX, User RX.
0xFF 0x60 AP[2:0] = 3, XN=1. Privileged RW, User RW.
0xFF 0x40 AP[2:0] = 7, XN=1. Privileged RO, User RO.



Version NID
1.69 (non-secure) 0xC94850C9
1.69 (secure) 0x402EB970
struct SceKernelAllocMemKernelBlockOpt_old
    uint32_t size; // 0x34
    uint32_t unk;
    uint32_t attr;
    uint32_t unk2;
    uint32_t paddr;
    uint32_t align;
    uint32_t unk3[3];
    uint32_t processid;
    uint32_t unk4[3];

// specific to 3.60
typedef struct SceKernelAllocMemBlockKernelOpt {
  SceSize size; // 0x58
  SceUInt32 field_4;
  SceUInt32 attr;
  SceUInt32 field_C;
  SceUInt32 paddr;
  SceSize alignment;
  SceUInt32 field_18;
  SceUInt32 field_1C;
  SceUInt32 mirror_blkid;
  SceUID pid;
  SceUInt32 field_28;
  SceUInt32 field_2C;
  SceUInt32 field_30;
  SceUInt32 field_34;
  SceUInt32 field_38;
  SceUInt32 field_3C;
  SceUInt32 field_40;
  SceUInt32 field_44;
  SceUInt32 field_48;
  SceUInt32 field_4C;
  SceUInt32 field_50;
  SceUInt32 field_54;
} SceKernelAllocMemBlockKernelOpt;

int sceKernelAllocMemBlockForKernel(const char *name, int32_t type, uint32_t vsize, struct SceKernelAllocMemKernelBlockOpt *pOpt);

The interface is the same as the user version of this call, however more types can be specified and more options are in the pOpt argument.

To allocate a kernel RW block of memory, specify type = 0x6020D006.

To allocate a block of memory with a specific physical address, specify type = 0x20100206, pOpt->attr = 2, and pOpt->paddr = physical address.

To allocate a block of memory that is kernel executable, specify type = 0x1020D005.

To allocate a block of memory that is physically contiguous, specify type = 0x30808006, pOpt->attr = 0x200004 and an alignment to pOpt->alignment.

To allocate a block of memory inside the CDRAM, specify type = 0x40404006.

Unrestricted Write for Process

Unrestricted memcpy to the virtual address space for process pid. Both dst and src must be in the address space of pid but src must also be accessible in the address space of the caller. This is normally used for resolving stubs in module loads.

Version NID
1.69 (non-secure) 0x30931572
int unrestricted_memcpy_for_pid(int pid, void *dst, void *src, size_t len);



Version NID
1.69 (non-secure) 0x6D88EF8A
int sceKernelMemcpyKernelToUser(uint32_t uaddr, const void *kaddr, uint32_t len);


Version NID
1.69 (non-secure) 0xBC996A7A
int sceKernelMemcpyUserToKernel(void *kaddr, uint32_t uaddr, uint32_t len);


Version NID
3.60 (non-secure) 0x605275F8
int sceKernelMemcpyUserToKernelForPid(int pid, void *kaddr, uint32_t uaddr, uint32_t len);

Same as above, but copies from the specified process.


Version NID
1.69 (non-secure) 0x80BD6FEB
int strncpyKernelToUser(uint32_t uaddr, const void *kaddr, uint32_t maxlen);


Version NID
1.69 (non-secure) 0xDB3EC244
int strncpyUserToKernel(void *kaddr, uint32_t uaddr, uint32_t maxlen);


Version NID
1.69 (non-secure) 0xB429D419
int strnlenUserSrc(uint32_t uaddr, uint32_t maxlen);


Version NID
1.69 (non-secure) 0x8D160E65
1.69 (secure) 0x1DEADF6C
int get_paddr(void *vaddr, void **result);

This will write the physical address for a virtual address vaddr to memory pointed to by result. Returns <0 on error, values >=0 indicate success.

get paddr list

Version NID
1.69 (non-secure) 0xE68BEEBD
struct addr_pair
    uint32_t addr;
    uint32_t length;
struct paddr_list_req
    uint32_t size; // 0x14
    uint32_t output_buffer_size;
    uint32_t unk;
    uint32_t ret_count;
    struct addr_pair *output_buffer;
input.addr = vaddr;
input.length = length;
int get_paddr_list(struct addr_pair *input, struct paddr_list_req *req);

This function takes in two parameters: an array of length 2 specifying the virtual address and the size of the block of memory and a request information. The function will write into output_buffer an array of addr_pair that encompasses the block of memory specified in the input. req->ret_count will contain the number of entries written. If output_buffer is null, it will just write the count.


Version NID
1.69 (non-secure) 0xA841EDDA
int sceKernelGetMemBlockBaseForDriver(int blkid, void **base);


Version NID
1.69 (non-secure) 0x8A1742F6
int sceKernelFindMemBlockByAddrForDriver(void *base, int);

Remap Block

Version NID
1.05 (non-secure) 0x8d332ae1
1.69 (non-secure) 0xDFE2C8CB
int sysmem_remap(int blkid, int type);

This is used to remap RW memory as RX. To do this, first allocate a memory block of type 0x1020D006. After you are done writing, call this with type set to 0x1020D005.

Create Heap Pool

Version NID
1.69 (non-secure) 0x9328E0E8
typedef struct {
    int size; // 28
    int flags; // usually 0x1 
    int unk;
    int unk;
    int block_type;
    int unk;
    int unk;
} pool_arg_t;
int heap_pool_create(const char *name, int size, pool_arg_t *opt); // opt can be NULL

The heap pool is thread safe.

Destroy Heap Pool

Version NID
1.69 (non-secure) 0xD6437637
int heap_pool_destroy(int pool_uid);

Alloc from Heap Pool

Version NID
1.69 (non-secure) 0x7B4CB60A
void *heap_pool_malloc(int pool_uid);

Free from Heap Pool

Version NID
1.69 (non-secure) 0x3EBCE343
int heap_pool_free(int pool_uid, void *ptr);

Map User to Kernel

Version NID
1.69 (non-secure) 0x7D4F8B5F 3.60 (?) 0x7D4F8B5F

Permission is either "1" for read only, no execute or "2"/"3" for read write, no execute. Type is either 0, 1, or 17 and affects the block type. 0 is default. This will allocate kernel memory starting at kernel_page. To get the same memory as the user pointer, add the kernel_offset. kernel_size is how much is allocated.

//this signature is for 1.69
int map_user_to_kernel(int permission, int type, void *user_buf, int size, void **kernel_page, int *kernel_size, int *kernel_offset);

//this signature is for 3.60 - now allows to give a name
int map_user_to_kernel(char *name, int permission, int type, void *user_buf, int size, void **kernel_page, int *kernel_size, int *kernel_offset);

Switch TTB to PID

Changes the TTBR to point to the tables for a given PID.

Version NID
1.69 (non-secure) 0x6F2ACDAE
3.60 (non-secure) N/A
int switch_ttb(int pid);

Write to RO for PID

Version NID
1.69 (non-secure) 0x571D2739
int write_to_ro(int pid, void *dst, const void *src, int size);

Write to RX for PID

Same as write to RO but does a cache flush.

Version NID
1.69 (non-secure) 0x30931572
int write_to_rx(int pid, void *dst, const void *src, int size);

Find Int for PID

Looks for an integer in user space.

Version NID
1.69 (non-secure) 0x8334454F
int find_int(int pid, void *haystack, int needle, int size);

strnlen for PID

Version NID
1.69 (non-secure) 0x9929EB07
int user_strnlen(int pid, char *ptr, int size);

strncpy for PID

Version NID
1.69 (non-secure) 0x75AAF178
int user_strncpy(int pid, char *dst, const char *kern_src, int size);

memcpyk2u unchecked for PID

Version NID
1.69 (non-secure) 0xFED82F2D
int user_memcpyk2u(int pid, void *dst, const void *kern_src, int size);

memcpyk2u checked for PID

This will not crash on invalid user pointers, but instead return error.

Version NID
1.69 (non-secure) 0x6B825479
int user_safe_memcpyk2u(int pid, void *dst, const void *kern_src, int size);

memcpyu2u for PID

Version NID
1.69 (non-secure) 0x8E086C33
int user_memcpyu2u(int pid, void *dst, const void *src, int size);


The SceSysmem library is responsible for both low-level and high-level memory management. There are functions for allocating raw blocks of memory (similar to Linux sbrk) as well as functions for maintaining a heap-like structure (similar to malloc) for kernel, however SceLibKernel implements a proper heap and that is used for user code.


Version NID
1.69 0x6F3DB4


Version NID
1.69 0x19D2A81A


Version NID
1.69 0x3B29E0F5


Version NID
1.69 0x4010AD65


Version NID
1.69 0x7B763A21


Version NID
1.69 0x832B4A65


Version NID
1.69 0x87CC580B


Version NID
1.69 0x8EB8DFBB


Version NID
1.69 0x9CA3EB2B


Version NID
1.69 0xA33B99D1


Version NID
1.69 0xA91E15EE


Version NID
1.69 0xB680E3A0


Version NID
1.69 0xB8EF5818


Version NID
1.69 0xB9D5EBDE


Version NID
1.69 0xC0A59868


Version NID
1.69 0xCA99929B


Version NID
1.69 0xD6CA56CA


Version NID
1.69 0xE2D7E137


Version NID
1.69 0xEE30D976



This library provides wrapper for much ARM CP15 co-processor access as well as low level support of spinlocks and other synchronization primitives.


The C standard library for use in the kernel only. (User code have SceLibKernel, which confusingly is user-only code). Include standard string functions (no insecure variants like strcpy).


Version NID
1.69 (non-secure) 0x0B33BC43


Version NID
1.69 (non-secure) 0x12cee649


Version NID
1.69 (non-secure) 0x1304A69D


Version NID
1.69 (non-secure) 0x1D89F6C0


Version NID
1.69 (non-secure) 0x40c88316


Version NID
1.69 (non-secure) 0x38463759


Version NID
1.69 (non-secure) 0x502B000D


On 1.69, this seems to be implemented incorrectly.

Version NID
1.69 (non-secure) 0x6CC9C1A1


Version NID
1.69 (non-secure) 0x7F0E0835


Version NID
1.69 (non-secure) 0xA1D1C32C


Version NID
1.69 (non-secure) 0xAB77C5AA


Version NID
1.69 (non-secure) 0xAE7A8981


Version NID
1.69 (non-secure) 0xb997493d


Version NID
1.69 (non-secure) 0xCD4BD884


Version NID
1.69 (non-secure) 0xCFC6A9AC


Version NID
1.69 (non-secure) 0xF939E83D



Version NID
1.69 0x1C783FB2


Version NID
1.69 0x800EDCC1


Version NID
1.69 0x817053D4





Version NID
1.69 0x2704CFEE


void SceCpuForKernel_1BB2BB8D(void); // BPIALLIS, Branch predictor invalidate all (IS)

void SceCpuForKernel_264DA250(void); // ICIALLUIS, Instruction cache invalidate all (PoU, IS)

void SceCpuForKernel_2F3BF020(void); //DCISW, Data cache invalidate by set/way (all the cache)

void SceCpuForKernel_470EAE1E(int mva); //DCIMVAC, Data cache invalidate by MVA (PoC)

void SceCpuForKernel_4C4C7D6B(void); //BPIALL, Branch predictor invalidate all

void SceCpuForKernel_583F30D1(void *addr, unsigned int size); //DCIMVAC, Data cache invalidate by MVA (PoC)

void SceCpuForKernel_6BA2E51C(void *addr, unsigned int size); // DCCIMVAC, Data cache clean and invalidate by MVA (PoC)

void SceCpuForKernel_73A30DB2(void); // DCCSW, Data cache clean by set/way (all the cache)

void SceCpuForKernel_76DAB4D0(void); // DCCISW, Data cache clean and invalidate by set/way (all the cache)

void SceCpuForKernel_AEE0B489(void); //ICIALLU, Instruction cache invalidate all (PoU)

void SceCpuForKernel_C5C1EE4E(void *addr, unsigned int size); // DCCMVAC, Data cache clean by MVA (PoC)

void SceCpuForKernel_C8E8C9E9(int mva); //DCCIMVAC, Data cache clean and invalidate by MVA (PoC)

void SceCpuForKernel_F4C7F578(void *addr, unsigned int size); // ICIMVAU, Instruction cache invalidate by MVA (PoU)

void SceCpuForKernel_F7159B55(int mva); // DCCMVAC, Data cache clean by MVA (PoC)

Unrestricted Write for Kernel

Unrestricted memcpy by first setting the DACR register to 0xFFFF0000 and then doing a memcpy.

Version NID
1.69 0x8C683DEC
int unrestricted_memcpy_for_kernel(void *dst, void *src, size_t len);



Version NID
1.60 0xBF82DEB2
int SceCpuForDriver_BF82DEB2_lock(int *addr);


Version NID
1.60 0xD6ED0C46
int SceCpuForDriver_D6ED0C46_unlock(int *addr);

These two functions implement a simple mutual exclusive access on a resource addr using LDREX/STREX.


Version NID
3.35 0xD32ACE9E
int SceCpuForDriver_D32ACE9E_lock_int(int *addr);


Version NID
3.35 0x7BB9D5DF
void SceCpuForDriver_7BB9D5DF_unlock_int(int *addr, int prev_state);

Same as the pair above, but while mutex is held, interrupts are disabled. Used like this:

int prev_state = SceCpuForDriver_D32ACE9E_lock_int(mutex);
// do work
SceCpuForDriver_7BB9D5DF_unlock_int(mutex, prev_state);


Version NID
3.35 0x4C38CE4D


Version NID
3.35 0x9EC91017

Same as the pair above, but stores 0x80000000 as the addr value instead of LR.


Version NID
1.60 0x821FC0EE
int SceCpuForDriver_821FC0EE_disable_irq(void);

Disables irq (but not fiq) and returns previous interrupt bit status (so either 0 or 0x80).


Version NID
1.60 0xF5BAD43B
void SceCpuForDriver_F5BAD43B_restore_irq(int previous_state);

Restores previous irq state, pass either 0 or 0x80.


Version NID
1.50 0x5E4D5DE1

Return the CPU ID of the current core.




Version NID
3.35 0xA9FF1205


Version NID
3.35 0xA46CB7DE


Version NID
1.60 0x40C88316


Version NID
1.60 0x0AB9BF5C


Version NID
3.35 0x38463759


Version NID
1.60 0x12CEE649



Version NID
3.60 0xF10AB792
typedef struct elf_info_pair
   uint32_t size; // 0x0C
   char* elf_data; 
   uint32_t elf_size;
} elf_info_pair;

int sceSysrootGetElfInfo(int index, elf_info_pair* state);


Version NID
3.60 0xCC85905B

Returns the exception vectors base address. The address of the exception vectors for the CPU i is: SceSysrootForKernel_CC85905B() + 0x40 * i.


Crypto utilities

AES Init

This sets up the AES engine. ctx is a 960 byte buffer (int 1.69). blocksize and keysize is the security in bits. 128/196/256 are supported values.

Version NID
1.69 0xF12B6451
int aes_init(void *ctx, int blocksize, int keysize, const char *key);

AES Encrypt

Encrypt with AES. There are two functions that are the same on 1.69.

Version NID
1.69 0xC2A61770
1.69 0x302947B6
int aes_encrypt(void *ctx, const char *src, char *dst);

AES Decrypt

Decrypt with AES.

Version NID
1.69 0xD8678061
int aes_decrypt(void *ctx, const char *src, char *dst);


zlib compression library.

Firmware zlib version
1.60 1.2.5


Version NID
1.60 0xE4F34A68


Version NID
1.60 0xE859D60F


Version NID
1.60 0x68CFEA45


Version NID
1.60 0xE0CE06C0


Version NID
1.60 0x98619620


Version NID
1.60 0x7B16DBD6


Libraries can register callbacks for handling suspend/resume related events.

Register Callback

Version NID
1.69 0x04C05D10
typedef struct {
    uint32_t size; // 24
    uint32_t unk1;
    uint32_t unk2;
    uint32_t unk3;
    uint32_t unk4;
    uint32_t unk5;
} suspend_args_t;
typedef int (suspend_callback_t)(int resume, int eventid, suspend_args_t *args, void *opt);
int suspend_register_callback(const char *name, suspend_callback_t *callback_func, void *opt);

Registers a function for handling suspend/resume. resume is 0 if we are currently suspending and 1 if we are currently resuming. opt is passed from the registration. Registration adds an entry to a linked list and returns the block id for the new entry.


Version NID
1.69 0xDD61D621
int suspend_unregister(int id);

Call with the id returned from suspend_register_callback to remove the entry from the linked list and free the memory.

Make Callback

Version NID
1.69 0xD4622EA8
int suspend_make_callback(int resume, int eventid, suspend_args_t *args, int stop_on_error);

This will go through the linked list and call each callback. If stop_on_error is set, then the first callback that returns a negative value will stop the call chain and return the block id of the callback that broke the chain. Otherwise, this function will invoke each callback and return zero.

Reset auto-suspend timer

Version NID
3.60 0xE0489831
int reset_autosuspend_timer(int unk);


Provides many device permission checks including Vita model checks, running app privilege checks, and so on.