Venezia
VENEZIA (Vision Enabling Engine / Zen-Inspired Architecture) (or VIP) is a Toshiba original multi-core sub-system which has multiple sets of “MPE (Media Processing Engine)” suitable for image processing and multiple image processing accelerators.
Description
The VENEZIA is multi-grain parallellism architecture – application level (multi-core), instruction level (VLIW) and data level (SIMD).
The VENEZIA includes 4 sets of Toshiba original media processing engine “MPE” that enables simultaneous execution of up to four image recognition applications. Each MPE has a Toshiba original 32-bit RISC CPU core MeP-c5 and an image recognition coprocessor IVC2. The MPE is 3way VLIW machine that can issue up to 3 instructions (one CPU instruction and up to 2 coprocessor instructions). The IVC2 provides SIMD instructions for simultaneous operations on eight sets of 8-bit data, four sets of 16-bit data, and two sets of 32-bit data. The IVC2 can execute simultaneously up to 2 SIMD instructions. Since parallel processing of two instructions is enabled, operations on a maximum of 16 sets of 8-bit data can be processed simultaneously.
There are 8 MeP cores that serve as the media co-processor Venezia. The CPU ID register for them are:
0x00300500 0x00310500 0x00320500 0x00330500 0x00340500 0x00350500 0x00360500 0x00370500
This means they are MeP c5 cores and are uniquely numbered 48-55.
Running Code
It is easy to run your own MeP code. It appears that the code is DMA copied to MeP's private memory before resetting and executing it.
MeP payload:
.text _start: jmp 0x800018 jmp 0x800018 jmp 0x800018 jmp 0x800018 jmp 0x800018 jmp 0x800018 _init: movh $0,0xf184 add3 $0,$0,0 mov $1,0x8 sw $1,0($0) _writecpuid: ldc $2,17 srl $2,14 ldc $1,17 add3 $2,$2,$0 add3 $2,$2,4 sw $1,0($2) .wait: bra .wait
On ARM:
// the following code has hard coded offsets in 1.69 int restart_vnz() { volatile unsigned int *regs, *spram; // r4@1 int v1; // r6@1 unsigned int img_paddr; // r3@2 int dram_base; // r0@2 int size; unsigned int v4; // r0@3 unsigned int v5; // r3@3 int v7; // r1@6 int v8; // r2@6 spram = *(volatile unsigned int **)0x0190F67C; regs = *(volatile unsigned int **)0x0190F670; printf("ScePervasive2Reg: 0x%08X, spram: 0x%08X\n", regs, spram); ScePervasiveForDriver_0xFB01A2DD(); img_paddr = 0x40800000; // paddr of region dram_base = 0x40300000; size = 0x400000; regs[192] = 0x1D001000; if ( dram_base < img_paddr ) { v7 = img_paddr + size; v8 = dram_base + 0x2500000; if ( img_paddr + size < v8 ) { regs[193] = dram_base; regs[194] = img_paddr; regs[195] = v7; regs[196] = v8; } } v4 = img_paddr >> 23 << 23; regs[224] = v4; regs[228] = 0x1E000000; regs[229] = 0x20000000; regs[230] = 0x22000000; regs[231] = img_paddr & 0xFE000000; regs[232] = 0x18000000; regs[233] = 0x20000000; regs[234] = img_paddr & 0xF8000000; regs[235] = (img_paddr + 0x8000000) & 0xF8000000; regs[236] = 0x1E000000; regs[237] = 0x20000000; regs[238] = 0x22000000; regs[239] = img_paddr & 0xFE000000; regs[256] = v4; regs[898] = 0xFFFF0000; spram[0] = 1; SceCpuForDriver_0xE813EBB2_clean_l2(); regs[898]; __asm__("dsb sy" ::: "memory"); ScePervasiveForDriver_0xA7E64C6F_reset_vnz(); v1 = 0; while (spram[0] != 8) { printf("waiting..."); sceKernelDelayThread(100); if (v1++ > 20) break; } return 0; } int vnz_hack() { volatile unsigned int *spram_vaddr; unsigned int *img_vaddr; int i; int ret; spram_vaddr = *(volatile unsigned int **)0x0190F67C; img_vaddr = *(unsigned int **)0x0190F664; printf("Vaddr: %08X\n", img_vaddr); ret = make_smc_call(1, 1, 0, 0, 0x110); printf("Reset VNZ: 0x%08X\n", ret); memset(spram_vaddr, 0, 256); memcpy(img_vaddr, YOUR_MEP_CODE, YOUR_MEP_CODE_LEN); ret = restart_vnz(); printf("Restart VNZ: 0x%08X\n", ret); return 0; }