mirror of
https://github.com/RPCS3/rpcs3.git
synced 2024-11-26 04:32:35 +01:00
sys_spu: protect sys_spu_image members in kernel mode
Save relevant info in idm, set sys_spu_image segs and nsegs members to 0.
This commit is contained in:
parent
8a176de6a1
commit
fad8b38b28
@ -1132,6 +1132,7 @@ void spu_thread::cpu_task()
|
|||||||
|
|
||||||
skip_npc_set = false;
|
skip_npc_set = false;
|
||||||
|
|
||||||
|
// Note: works both on RawSPU and threaded SPU!
|
||||||
set_interrupt_status((pc & 1) != 0);
|
set_interrupt_status((pc & 1) != 0);
|
||||||
|
|
||||||
pc &= 0x3fffc;
|
pc &= 0x3fffc;
|
||||||
|
@ -45,26 +45,31 @@ void sys_spu_image::load(const fs::file& stream)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
type = SYS_SPU_IMAGE_TYPE_KERNEL;
|
this->type = SYS_SPU_IMAGE_TYPE_KERNEL;
|
||||||
|
const s32 nsegs = sys_spu_image::get_nsegs(obj.progs);
|
||||||
nsegs = sys_spu_image::get_nsegs(obj.progs);
|
|
||||||
|
|
||||||
const u32 mem_size = nsegs * sizeof(sys_spu_segment) + ::size32(stream);
|
const u32 mem_size = nsegs * sizeof(sys_spu_segment) + ::size32(stream);
|
||||||
segs = vm::cast(vm::alloc(mem_size, vm::main));
|
const vm::ptr<sys_spu_segment> segs = vm::cast(vm::alloc(mem_size, vm::main));
|
||||||
|
|
||||||
// Write ID and save entry
|
const u32 entry = obj.header.e_entry;
|
||||||
entry_point = idm::make<lv2_obj, lv2_spu_image>(+obj.header.e_entry);
|
|
||||||
|
|
||||||
const u32 src = segs.addr() + nsegs * sizeof(sys_spu_segment);
|
const u32 src = segs.addr() + nsegs * sizeof(sys_spu_segment);
|
||||||
|
|
||||||
stream.seek(0);
|
stream.seek(0);
|
||||||
stream.read(vm::base(src), stream.size());
|
stream.read(vm::base(src), stream.size());
|
||||||
|
|
||||||
if (nsegs < 0 || sys_spu_image::fill(segs, nsegs, obj.progs, src) != nsegs)
|
if (nsegs <= 0 || nsegs > 0x20 || sys_spu_image::fill(segs, nsegs, obj.progs, src) != nsegs)
|
||||||
{
|
{
|
||||||
fmt::throw_exception("Failed to load SPU segments (%d)" HERE, nsegs);
|
fmt::throw_exception("Failed to load SPU segments (%d)" HERE, nsegs);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Write ID and save entry
|
||||||
|
this->entry_point = idm::make<lv2_obj, lv2_spu_image>(+obj.header.e_entry, segs, nsegs);
|
||||||
|
|
||||||
|
// Unused and set to 0
|
||||||
|
this->nsegs = 0;
|
||||||
|
this->segs = vm::null;
|
||||||
|
|
||||||
vm::page_protect(segs.addr(), ::align(mem_size, 4096), 0, 0, vm::page_writable);
|
vm::page_protect(segs.addr(), ::align(mem_size, 4096), 0, 0, vm::page_writable);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -200,7 +205,7 @@ error_code _sys_spu_image_get_information(ppu_thread& ppu, vm::ptr<sys_spu_image
|
|||||||
}
|
}
|
||||||
|
|
||||||
*entry_point = image->e_entry;
|
*entry_point = image->e_entry;
|
||||||
*nsegs = img->nsegs;
|
*nsegs = image->nsegs;
|
||||||
return CELL_OK;
|
return CELL_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -243,12 +248,14 @@ error_code _sys_spu_image_close(ppu_thread& ppu, vm::ptr<sys_spu_image> img)
|
|||||||
return CELL_EINVAL;
|
return CELL_EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!idm::remove<lv2_obj, lv2_spu_image>(img->entry_point))
|
const auto handle = idm::withdraw<lv2_obj, lv2_spu_image>(img->entry_point);
|
||||||
|
|
||||||
|
if (!handle)
|
||||||
{
|
{
|
||||||
return CELL_ESRCH;
|
return CELL_ESRCH;
|
||||||
}
|
}
|
||||||
|
|
||||||
vm::dealloc(img->segs.addr(), vm::main);
|
verify(HERE), vm::dealloc(handle->segs.addr(), vm::main);
|
||||||
return CELL_OK;
|
return CELL_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -258,8 +265,20 @@ error_code _sys_spu_image_get_segments(ppu_thread& ppu, vm::ptr<sys_spu_image> i
|
|||||||
|
|
||||||
sys_spu.error("_sys_spu_image_get_segments(img=*0x%x, segments=*0x%x, nseg=%d)", img, segments, nseg);
|
sys_spu.error("_sys_spu_image_get_segments(img=*0x%x, segments=*0x%x, nseg=%d)", img, segments, nseg);
|
||||||
|
|
||||||
|
if (nseg <= 0 || nseg > 0x20 || img->type != SYS_SPU_IMAGE_TYPE_KERNEL)
|
||||||
|
{
|
||||||
|
return CELL_EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto handle = idm::get<lv2_obj, lv2_spu_image>(img->entry_point);
|
||||||
|
|
||||||
|
if (!handle)
|
||||||
|
{
|
||||||
|
return CELL_ESRCH;
|
||||||
|
}
|
||||||
|
|
||||||
// TODO: apply SPU patches
|
// TODO: apply SPU patches
|
||||||
std::memcpy(segments.get_ptr(), img->segs.get_ptr(), sizeof(sys_spu_segment) * nseg);
|
std::memcpy(segments.get_ptr(), handle->segs.get_ptr(), sizeof(sys_spu_segment) * std::min<s32>(nseg, handle->nsegs));
|
||||||
return CELL_OK;
|
return CELL_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -274,14 +293,11 @@ error_code sys_spu_thread_initialize(ppu_thread& ppu, vm::ptr<u32> thread, u32 g
|
|||||||
return CELL_EINVAL;
|
return CELL_EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (img->type != SYS_SPU_IMAGE_TYPE_KERNEL && img->type != SYS_SPU_IMAGE_TYPE_USER)
|
sys_spu_image image;
|
||||||
|
|
||||||
|
switch (img->type)
|
||||||
{
|
{
|
||||||
return CELL_EINVAL;
|
case SYS_SPU_IMAGE_TYPE_KERNEL:
|
||||||
}
|
|
||||||
|
|
||||||
sys_spu_image image = *img;
|
|
||||||
|
|
||||||
if (img->type == SYS_SPU_IMAGE_TYPE_KERNEL)
|
|
||||||
{
|
{
|
||||||
const auto handle = idm::get<lv2_obj, lv2_spu_image>(img->entry_point);
|
const auto handle = idm::get<lv2_obj, lv2_spu_image>(img->entry_point);
|
||||||
|
|
||||||
@ -290,8 +306,24 @@ error_code sys_spu_thread_initialize(ppu_thread& ppu, vm::ptr<u32> thread, u32 g
|
|||||||
return CELL_ESRCH;
|
return CELL_ESRCH;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Save actual entry point
|
// Image information is stored in IDM
|
||||||
image.entry_point = handle->e_entry;
|
image.entry_point = handle->e_entry;
|
||||||
|
image.nsegs = handle->nsegs;
|
||||||
|
image.segs = handle->segs;
|
||||||
|
image.type = SYS_SPU_IMAGE_TYPE_KERNEL;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case SYS_SPU_IMAGE_TYPE_USER:
|
||||||
|
{
|
||||||
|
if (img->entry_point > 0x3fffc || img->nsegs <= 0 || img->nsegs > 0x20)
|
||||||
|
{
|
||||||
|
return CELL_EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
image = *img;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default: return CELL_EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Read thread name
|
// Read thread name
|
||||||
|
@ -225,9 +225,13 @@ struct lv2_spu_image : lv2_obj
|
|||||||
static const u32 id_base = 0x22000000;
|
static const u32 id_base = 0x22000000;
|
||||||
|
|
||||||
const u32 e_entry;
|
const u32 e_entry;
|
||||||
|
const vm::ptr<sys_spu_segment> segs;
|
||||||
|
const s32 nsegs;
|
||||||
|
|
||||||
lv2_spu_image(u32 entry)
|
lv2_spu_image(u32 entry, vm::ptr<sys_spu_segment> segs, s32 nsegs)
|
||||||
: e_entry(entry)
|
: e_entry(entry)
|
||||||
|
, segs(segs)
|
||||||
|
, nsegs(nsegs)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
Loading…
Reference in New Issue
Block a user