Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

vm: Fix possible IDM deadlock with Page Fault Notifications #7921

Merged
merged 4 commits into from Apr 12, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
10 changes: 9 additions & 1 deletion Utilities/Thread.cpp
Expand Up @@ -1450,9 +1450,17 @@ bool handle_access_violation(u32 addr, bool is_writing, x64_context* context) no
pf_events->events.emplace(static_cast<u32>(data2), addr);
}

sig_log.error("Page_fault %s location 0x%x because of %s memory", is_writing ? "writing" : "reading",
sig_log.warning("Page_fault %s location 0x%x because of %s memory", is_writing ? "writing" : "reading",
addr, data3 == SYS_MEMORY_PAGE_FAULT_CAUSE_READ_ONLY ? "writing read-only" : "using unmapped");

if (cpu->id_type() == 1)
{
if (const auto func = static_cast<ppu_thread*>(cpu)->current_function)
{
sig_log.warning("Page_fault while in function %s", func);
}
}

error_code sending_error = sys_event_port_send(pf_port_id, data1, data2, data3);

// If we fail due to being busy, wait a bit and try again.
Expand Down
2 changes: 2 additions & 0 deletions rpcs3/Emu/Cell/PPUModule.cpp
Expand Up @@ -1261,6 +1261,8 @@ void ppu_load_exec(const ppu_exec_object& elf)
tls_vaddr = vm::cast(prog.p_vaddr, HERE);
tls_fsize = ::narrow<u32>(prog.p_filesz, "p_filesz" HERE);
tls_vsize = ::narrow<u32>(prog.p_memsz, "p_memsz" HERE);

ppu_loader.notice("TLS info segment found: tls-image=*0x%x, image-size=0x%x, tls-size=0x%x", tls_vaddr, tls_fsize, tls_vsize);
break;
}

Expand Down
12 changes: 7 additions & 5 deletions rpcs3/Emu/Cell/lv2/sys_cond.cpp
Expand Up @@ -24,13 +24,15 @@ error_code sys_cond_create(ppu_thread& ppu, vm::ptr<u32> cond_id, u32 mutex_id,
return CELL_ESRCH;
}

if (auto error = lv2_obj::create<lv2_cond>(attr->pshared, attr->ipc_key, attr->flags, [&]
const auto _attr = *attr;

if (auto error = lv2_obj::create<lv2_cond>(_attr.pshared, _attr.ipc_key, _attr.flags, [&]
{
return std::make_shared<lv2_cond>(
attr->pshared,
attr->flags,
attr->ipc_key,
attr->name_u64,
_attr.pshared,
_attr.flags,
_attr.ipc_key,
_attr.name_u64,
std::move(mutex));
}))
{
Expand Down
20 changes: 11 additions & 9 deletions rpcs3/Emu/Cell/lv2/sys_event_flag.cpp
Expand Up @@ -24,31 +24,33 @@ error_code sys_event_flag_create(ppu_thread& ppu, vm::ptr<u32> id, vm::ptr<sys_e
return CELL_EFAULT;
}

const u32 protocol = attr->protocol;
const auto _attr = *attr;

const u32 protocol = _attr.protocol;

if (protocol != SYS_SYNC_FIFO && protocol != SYS_SYNC_PRIORITY)
{
sys_event_flag.error("sys_event_flag_create(): unknown protocol (0x%x)", protocol);
return CELL_EINVAL;
}

const u32 type = attr->type;
const u32 type = _attr.type;

if (type != SYS_SYNC_WAITER_SINGLE && type != SYS_SYNC_WAITER_MULTIPLE)
{
sys_event_flag.error("sys_event_flag_create(): unknown type (0x%x)", type);
return CELL_EINVAL;
}

if (auto error = lv2_obj::create<lv2_event_flag>(attr->pshared, attr->ipc_key, attr->flags, [&]
if (auto error = lv2_obj::create<lv2_event_flag>(_attr.pshared, _attr.ipc_key, _attr.flags, [&]
{
return std::make_shared<lv2_event_flag>(
attr->protocol,
attr->pshared,
attr->ipc_key,
attr->flags,
attr->type,
attr->name_u64,
_attr.protocol,
_attr.pshared,
_attr.ipc_key,
_attr.flags,
_attr.type,
_attr.name_u64,
init);
}))
{
Expand Down
30 changes: 16 additions & 14 deletions rpcs3/Emu/Cell/lv2/sys_mutex.cpp
Expand Up @@ -22,7 +22,9 @@ error_code sys_mutex_create(ppu_thread& ppu, vm::ptr<u32> mutex_id, vm::ptr<sys_
return CELL_EFAULT;
}

switch (attr->protocol)
const auto _attr = *attr;

switch (_attr.protocol)
{
case SYS_SYNC_FIFO: break;
case SYS_SYNC_PRIORITY: break;
Expand All @@ -31,37 +33,37 @@ error_code sys_mutex_create(ppu_thread& ppu, vm::ptr<u32> mutex_id, vm::ptr<sys_
break;
default:
{
sys_mutex.error("sys_mutex_create(): unknown protocol (0x%x)", attr->protocol);
sys_mutex.error("sys_mutex_create(): unknown protocol (0x%x)", _attr.protocol);
return CELL_EINVAL;
}
}

switch (attr->recursive)
switch (_attr.recursive)
{
case SYS_SYNC_RECURSIVE: break;
case SYS_SYNC_NOT_RECURSIVE: break;
default:
{
sys_mutex.error("sys_mutex_create(): unknown recursive (0x%x)", attr->recursive);
sys_mutex.error("sys_mutex_create(): unknown recursive (0x%x)", _attr.recursive);
return CELL_EINVAL;
}
}

if (attr->adaptive != SYS_SYNC_NOT_ADAPTIVE)
if (_attr.adaptive != SYS_SYNC_NOT_ADAPTIVE)
{
sys_mutex.todo("sys_mutex_create(): unexpected adaptive (0x%x)", attr->adaptive);
sys_mutex.todo("sys_mutex_create(): unexpected adaptive (0x%x)", _attr.adaptive);
}

if (auto error = lv2_obj::create<lv2_mutex>(attr->pshared, attr->ipc_key, attr->flags, [&]()
if (auto error = lv2_obj::create<lv2_mutex>(_attr.pshared, _attr.ipc_key, _attr.flags, [&]()
{
return std::make_shared<lv2_mutex>(
attr->protocol,
attr->recursive,
attr->pshared,
attr->adaptive,
attr->ipc_key,
attr->flags,
attr->name_u64);
_attr.protocol,
_attr.recursive,
_attr.pshared,
_attr.adaptive,
_attr.ipc_key,
_attr.flags,
_attr.name_u64);
}))
{
return error;
Expand Down
16 changes: 10 additions & 6 deletions rpcs3/Emu/Cell/lv2/sys_ppu_thread.cpp
Expand Up @@ -364,6 +364,7 @@ error_code _sys_ppu_thread_create(vm::ptr<u64> thread_id, vm::ptr<ppu_thread_par
}

const ppu_func_opd_t entry = param->entry.opd();
const u32 tls = param->tls;

// Clean some detached thread (hack)
g_fxo->get<ppu_thread_cleaner>()->clean(0);
Expand All @@ -389,6 +390,13 @@ error_code _sys_ppu_thread_create(vm::ptr<u64> thread_id, vm::ptr<ppu_thread_par

std::string ppu_name;

if (threadname)
{
constexpr u32 max_size = 27; // max size including null terminator
const auto pname = threadname.get_ptr();
ppu_name.assign(pname, std::find(pname, pname + max_size, '\0'));
}

const u32 tid = idm::import<named_thread<ppu_thread>>([&]()
{
const u32 tid = idm::last_id();
Expand All @@ -397,10 +405,6 @@ error_code _sys_ppu_thread_create(vm::ptr<u64> thread_id, vm::ptr<ppu_thread_par

if (threadname)
{
constexpr u32 max_size = 27; // max size including null terminator
const auto pname = threadname.get_ptr();
ppu_name.assign(pname, std::find(pname, pname + max_size, '\0'));

if (!ppu_name.empty())
{
fmt::append(full_name, " (%s)", ppu_name);
Expand All @@ -410,7 +414,7 @@ error_code _sys_ppu_thread_create(vm::ptr<u64> thread_id, vm::ptr<ppu_thread_par
ppu_thread_params p;
p.stack_addr = stack_base;
p.stack_size = stack_size;
p.tls_addr = param->tls;
p.tls_addr = tls;
p.entry = entry;
p.arg0 = arg;
p.arg1 = unk;
Expand All @@ -426,7 +430,7 @@ error_code _sys_ppu_thread_create(vm::ptr<u64> thread_id, vm::ptr<ppu_thread_par
}

*thread_id = tid;
sys_ppu_thread.warning(u8"_sys_ppu_thread_create(): Thread “%s” created (id=0x%x, func=*0x%x, rtoc=0x%x)", ppu_name, tid, entry.addr, entry.rtoc);
sys_ppu_thread.warning(u8"_sys_ppu_thread_create(): Thread “%s” created (id=0x%x, func=*0x%x, rtoc=0x%x, user-tls=0x%x)", ppu_name, tid, entry.addr, entry.rtoc, tls);
return CELL_OK;
}

Expand Down
8 changes: 5 additions & 3 deletions rpcs3/Emu/Cell/lv2/sys_rwlock.cpp
Expand Up @@ -22,7 +22,9 @@ error_code sys_rwlock_create(ppu_thread& ppu, vm::ptr<u32> rw_lock_id, vm::ptr<s
return CELL_EFAULT;
}

const u32 protocol = attr->protocol;
const auto _attr = *attr;

const u32 protocol = _attr.protocol;

if (protocol == SYS_SYNC_PRIORITY_INHERIT)
sys_rwlock.todo("sys_rwlock_create(): SYS_SYNC_PRIORITY_INHERIT");
Expand All @@ -33,9 +35,9 @@ error_code sys_rwlock_create(ppu_thread& ppu, vm::ptr<u32> rw_lock_id, vm::ptr<s
return CELL_EINVAL;
}

if (auto error = lv2_obj::create<lv2_rwlock>(attr->pshared, attr->ipc_key, attr->flags, [&]
if (auto error = lv2_obj::create<lv2_rwlock>(_attr.pshared, _attr.ipc_key, _attr.flags, [&]
{
return std::make_shared<lv2_rwlock>(protocol, attr->pshared, attr->ipc_key, attr->flags, attr->name_u64);
return std::make_shared<lv2_rwlock>(protocol, _attr.pshared, _attr.ipc_key, _attr.flags, _attr.name_u64);
}))
{
return error;
Expand Down
17 changes: 11 additions & 6 deletions rpcs3/Emu/Cell/lv2/sys_semaphore.cpp
Expand Up @@ -28,17 +28,19 @@ error_code sys_semaphore_create(ppu_thread& ppu, vm::ptr<u32> sem_id, vm::ptr<sy
return CELL_EINVAL;
}

const u32 protocol = attr->protocol;
const auto _attr = *attr;

const u32 protocol = _attr.protocol;

if (protocol != SYS_SYNC_FIFO && protocol != SYS_SYNC_PRIORITY)
{
sys_semaphore.error("sys_semaphore_create(): unknown protocol (0x%x)", protocol);
return CELL_EINVAL;
}

if (auto error = lv2_obj::create<lv2_sema>(attr->pshared, attr->ipc_key, attr->flags, [&]
if (auto error = lv2_obj::create<lv2_sema>(_attr.pshared, _attr.ipc_key, _attr.flags, [&]
{
return std::make_shared<lv2_sema>(protocol, attr->pshared, attr->ipc_key, attr->flags, attr->name_u64, max_val, initial_val);
return std::make_shared<lv2_sema>(protocol, _attr.pshared, _attr.ipc_key, _attr.flags, _attr.name_u64, max_val, initial_val);
}))
{
return error;
Expand Down Expand Up @@ -268,13 +270,16 @@ error_code sys_semaphore_get_value(ppu_thread& ppu, u32 sem_id, vm::ptr<s32> cou
return CELL_EFAULT;
}

if (!idm::check<lv2_obj, lv2_sema>(sem_id, [=](lv2_sema& sema)
const auto sema = idm::check<lv2_obj, lv2_sema>(sem_id, [](lv2_sema& sema)
{
*count = std::max<s32>(0, sema.val);
}))
return std::max<s32>(0, sema.val);
});

if (!sema)
{
return CELL_ESRCH;
}

*count = sema.ret;
return CELL_OK;
}