1
0
mirror of https://github.com/RPCS3/rpcs3.git synced 2024-11-25 20:22:30 +01:00

Implement lv2_spu_image

- Improved sys_spu_image_.. error checking
- sys_process SYS_SPUIMAGE_OBJECT handling implemented
This commit is contained in:
Eladash 2019-08-14 20:00:51 +03:00 committed by Ivan
parent 80827aa31a
commit 0dce6be8cb
3 changed files with 65 additions and 7 deletions

View File

@ -23,6 +23,7 @@
#include "sys_timer.h"
#include "sys_trace.h"
#include "sys_fs.h"
#include "sys_spu.h"
@ -69,7 +70,7 @@ s32 sys_process_get_number_of_object(u32 object, vm::ptr<u32> nump)
case SYS_EVENT_QUEUE_OBJECT: *nump = idm_get_count<lv2_obj, lv2_event_queue>(); break;
case SYS_EVENT_PORT_OBJECT: *nump = idm_get_count<lv2_obj, lv2_event_port>(); break;
case SYS_TRACE_OBJECT: sys_process.error("sys_process_get_number_of_object: object = SYS_TRACE_OBJECT"); *nump = 0; break;
case SYS_SPUIMAGE_OBJECT: fmt::throw_exception("SYS_SPUIMAGE_OBJECT" HERE);
case SYS_SPUIMAGE_OBJECT: *nump = idm_get_count<lv2_obj, lv2_spu_image>(); break;
case SYS_PRX_OBJECT: *nump = idm_get_count<lv2_obj, lv2_prx>(); break;
case SYS_SPUPORT_OBJECT: fmt::throw_exception("SYS_SPUPORT_OBJECT" HERE);
case SYS_OVERLAY_OBJECT: *nump = idm_get_count<lv2_obj, lv2_overlay>(); break;
@ -117,7 +118,7 @@ s32 sys_process_get_id(u32 object, vm::ptr<u32> buffer, u32 size, vm::ptr<u32> s
case SYS_EVENT_QUEUE_OBJECT: idm_get_set<lv2_obj, lv2_event_queue>(objects); break;
case SYS_EVENT_PORT_OBJECT: idm_get_set<lv2_obj, lv2_event_port>(objects); break;
case SYS_TRACE_OBJECT: fmt::throw_exception("SYS_TRACE_OBJECT" HERE);
case SYS_SPUIMAGE_OBJECT: fmt::throw_exception("SYS_SPUIMAGE_OBJECT" HERE);
case SYS_SPUIMAGE_OBJECT: idm_get_set<lv2_obj, lv2_spu_image>(objects); break;
case SYS_PRX_OBJECT: idm_get_set<lv2_obj, lv2_prx>(objects); break;
case SYS_SPUPORT_OBJECT: fmt::throw_exception("SYS_SPUPORT_OBJECT" HERE);
case SYS_OVERLAY_OBJECT: idm_get_set<lv2_obj, lv2_overlay>(objects); break;

View File

@ -43,12 +43,15 @@ void sys_spu_image::load(const fs::file& stream)
}
type = SYS_SPU_IMAGE_TYPE_KERNEL;
entry_point = obj.header.e_entry;
nsegs = sys_spu_image::get_nsegs(obj.progs);
const u32 mem_size = nsegs * sizeof(sys_spu_segment) + ::size32(stream);
segs = vm::cast(vm::alloc(mem_size, vm::main));
// Write ID and save entry
entry_point = idm::make<lv2_obj, lv2_spu_image>(+obj.header.e_entry);
const u32 src = segs.addr() + nsegs * sizeof(sys_spu_segment);
stream.seek(0);
@ -158,7 +161,19 @@ error_code _sys_spu_image_get_information(ppu_thread& ppu, vm::ptr<sys_spu_image
sys_spu.warning("_sys_spu_image_get_information(img=*0x%x, entry_point=*0x%x, nsegs=*0x%x)", img, entry_point, nsegs);
*entry_point = img->entry_point;
if (img->type != SYS_SPU_IMAGE_TYPE_KERNEL)
{
return CELL_EINVAL;
}
const auto image = idm::get<lv2_obj, lv2_spu_image>(img->entry_point);
if (!image)
{
return CELL_ESRCH;
}
*entry_point = image->e_entry;
*nsegs = img->nsegs;
return CELL_OK;
}
@ -178,7 +193,6 @@ error_code sys_spu_image_open(ppu_thread& ppu, vm::ptr<sys_spu_image> img, vm::c
}
img->load(elf_file);
return CELL_OK;
}
@ -198,6 +212,16 @@ error_code _sys_spu_image_close(ppu_thread& ppu, vm::ptr<sys_spu_image> img)
sys_spu.warning("_sys_spu_image_close(img=*0x%x)", img);
if (img->type != SYS_SPU_IMAGE_TYPE_KERNEL)
{
return CELL_EINVAL;
}
if (!idm::remove<lv2_obj, lv2_spu_image>(img->entry_point))
{
return CELL_ESRCH;
}
vm::dealloc(img->segs.addr(), vm::main);
return CELL_OK;
}
@ -236,11 +260,31 @@ error_code sys_spu_thread_initialize(ppu_thread& ppu, vm::ptr<u32> thread, u32 g
return CELL_EINVAL;
}
if (img->type != SYS_SPU_IMAGE_TYPE_KERNEL && img->type != SYS_SPU_IMAGE_TYPE_USER)
{
return CELL_EINVAL;
}
if (group->threads[spu_num] || group->run_state != SPU_THREAD_GROUP_STATUS_NOT_INITIALIZED)
{
return CELL_EBUSY;
}
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);
if (!handle)
{
return CELL_ESRCH;
}
// Save actual entry point
image.entry_point = handle->e_entry;
}
if (u32 option = attr->option)
{
sys_spu.todo("Unimplemented SPU Thread options (0x%x)", option);
@ -266,7 +310,7 @@ error_code sys_spu_thread_initialize(ppu_thread& ppu, vm::ptr<u32> thread, u32 g
*thread = tid;
group->args[spu_num] = {arg->arg1, arg->arg2, arg->arg3, arg->arg4};
group->imgs[spu_num] = std::make_pair(*img, std::vector<sys_spu_segment>());
group->imgs[spu_num] = std::make_pair(image, std::vector<sys_spu_segment>());
group->imgs[spu_num].second.assign(img->segs.get_ptr(), img->segs.get_ptr() + img->nsegs);
if (++group->init == group->max_num)

View File

@ -1,5 +1,6 @@
#pragma once
#include "sys_sync.h"
#include "sys_event.h"
#include "Emu/Cell/SPUThread.h"
@ -112,7 +113,7 @@ enum : u32
struct sys_spu_image
{
be_t<u32> type; // user, kernel
be_t<u32> entry_point;
be_t<u32> entry_point; // Note: in kernel mode it's used to store id
vm::bptr<sys_spu_segment> segs;
be_t<s32> nsegs;
@ -210,6 +211,18 @@ enum : u32
SYS_SPU_IMAGE_DIRECT = 1,
};
struct lv2_spu_image : lv2_obj
{
static const u32 id_base = 0x22000000;
const u32 e_entry;
lv2_spu_image(u32 entry)
: e_entry(entry)
{
}
};
struct lv2_spu_group
{
static const u32 id_base = 0x04000100;