ProcessManager: Fix svcCreateEvent handle inversion bug, and others.

NOTE: Debugging logs have been left in, and will be cleaned up once PM
is working.
This commit is contained in:
Michael Scire 2018-05-06 02:23:47 -06:00
parent 6e5d4b8fc9
commit 6d6ecb503a
8 changed files with 81 additions and 35 deletions

View file

@ -1,10 +1,14 @@
#include <switch.h> #include <switch.h>
#include "pm_boot_mode.hpp" #include "pm_boot_mode.hpp"
#include "pm_debug.hpp"
static bool g_is_maintenance_boot = false; static bool g_is_maintenance_boot = false;
Result BootModeService::dispatch(IpcParsedCommand &r, IpcCommand &out_c, u64 cmd_id, u8 *pointer_buffer, size_t pointer_buffer_size) { Result BootModeService::dispatch(IpcParsedCommand &r, IpcCommand &out_c, u64 cmd_id, u8 *pointer_buffer, size_t pointer_buffer_size) {
Result rc = 0xF601; Result rc = 0xF601;
LogForService("BOOTMODE\x00", 8);
LogForService(&cmd_id, 8);
LogForService(armGetTls(), 0x100);
switch ((BootModeCmd)cmd_id) { switch ((BootModeCmd)cmd_id) {
case BootMode_Cmd_GetBootMode: case BootMode_Cmd_GetBootMode:
rc = WrapIpcCommandImpl<&BootModeService::get_boot_mode>(this, r, out_c, pointer_buffer, pointer_buffer_size); rc = WrapIpcCommandImpl<&BootModeService::get_boot_mode>(this, r, out_c, pointer_buffer, pointer_buffer_size);
@ -15,6 +19,10 @@ Result BootModeService::dispatch(IpcParsedCommand &r, IpcCommand &out_c, u64 cmd
default: default:
break; break;
} }
LogForService(armGetTls(), 0x100);
if (R_FAILED(rc)) {
Reboot();
}
return rc; return rc;
} }

View file

@ -1,9 +1,13 @@
#include <switch.h> #include <switch.h>
#include "pm_registration.hpp" #include "pm_registration.hpp"
#include "pm_info.hpp" #include "pm_info.hpp"
#include "pm_debug.hpp"
Result InformationService::dispatch(IpcParsedCommand &r, IpcCommand &out_c, u64 cmd_id, u8 *pointer_buffer, size_t pointer_buffer_size) { Result InformationService::dispatch(IpcParsedCommand &r, IpcCommand &out_c, u64 cmd_id, u8 *pointer_buffer, size_t pointer_buffer_size) {
Result rc = 0xF601; Result rc = 0xF601;
LogForService("INFOSRV\x00", 8);
LogForService(&cmd_id, 8);
LogForService(armGetTls(), 0x100);
switch ((InformationCmd)cmd_id) { switch ((InformationCmd)cmd_id) {
case Information_Cmd_GetTitleId: case Information_Cmd_GetTitleId:
rc = WrapIpcCommandImpl<&InformationService::get_title_id>(this, r, out_c, pointer_buffer, pointer_buffer_size); rc = WrapIpcCommandImpl<&InformationService::get_title_id>(this, r, out_c, pointer_buffer, pointer_buffer_size);
@ -11,6 +15,10 @@ Result InformationService::dispatch(IpcParsedCommand &r, IpcCommand &out_c, u64
default: default:
break; break;
} }
LogForService(armGetTls(), 0x100);
if (R_FAILED(rc)) {
Reboot();
}
return rc; return rc;
} }

View file

@ -11,6 +11,7 @@
#include "pm_shell.hpp" #include "pm_shell.hpp"
#include "pm_process_track.hpp" #include "pm_process_track.hpp"
#include "pm_registration.hpp" #include "pm_registration.hpp"
#include "pm_debug.hpp"
extern "C" { extern "C" {
extern u32 __start__; extern u32 __start__;

View file

@ -2,15 +2,26 @@
#include <stratosphere.hpp> #include <stratosphere.hpp>
#include "pm_process_track.hpp" #include "pm_process_track.hpp"
#include "pm_registration.hpp" #include "pm_registration.hpp"
#include "pm_debug.hpp"
void ProcessTracking::MainLoop(void *arg) { void ProcessTracking::MainLoop(void *arg) {
/* Make a new waitable manager. */ /* Make a new waitable manager. */
WaitableManager *process_waiter = new WaitableManager(U64_MAX); WaitableManager *process_waiter = new WaitableManager(1000);
process_waiter->add_waitable(Registration::GetProcessLaunchStartEvent());
process_waiter->add_waitable(Registration::GetProcessList()); process_waiter->add_waitable(Registration::GetProcessList());
static unsigned int i = 0;
/* Service processes. */ /* Service processes. */
process_waiter->process(); while (true) {
process_waiter->process_until_timeout();
i++;
if (Registration::TryWaitProcessLaunchStartEvent()) {
Registration::HandleProcessLaunch();
}
if (i > 1000000) {
Reboot();
}
}
delete process_waiter; delete process_waiter;
svcExitThread(); svcExitThread();

View file

@ -2,6 +2,9 @@
#include <switch.h> #include <switch.h>
#include <stratosphere.hpp> #include <stratosphere.hpp>
#include "pm_registration.hpp"
#include "pm_debug.hpp"
class ProcessWaiter : public IWaitable { class ProcessWaiter : public IWaitable {
public: public:
Registration::Process process; Registration::Process process;

View file

@ -8,6 +8,7 @@
static ProcessList g_process_list; static ProcessList g_process_list;
static ProcessList g_dead_process_list; static ProcessList g_dead_process_list;
static HosSemaphore g_sema_start_launch;
static HosSemaphore g_sema_finish_launch; static HosSemaphore g_sema_finish_launch;
static HosMutex g_process_launch_mutex; static HosMutex g_process_launch_mutex;
@ -19,7 +20,6 @@ static std::atomic<u64> g_debug_on_launch_tid(0);
static SystemEvent *g_process_event = NULL; static SystemEvent *g_process_event = NULL;
static SystemEvent *g_debug_title_event = NULL; static SystemEvent *g_debug_title_event = NULL;
static SystemEvent *g_debug_application_event = NULL; static SystemEvent *g_debug_application_event = NULL;
static SystemEvent *g_process_launch_start_event = NULL;
static const u64 g_memory_resource_limits[5][3] = { static const u64 g_memory_resource_limits[5][3] = {
{0x010D00000ULL, 0x0CD500000ULL, 0x021700000ULL}, {0x010D00000ULL, 0x0CD500000ULL, 0x021700000ULL},
@ -61,7 +61,6 @@ void Registration::InitializeSystemResources() {
g_process_event = new SystemEvent(&IEvent::PanicCallback); g_process_event = new SystemEvent(&IEvent::PanicCallback);
g_debug_title_event = new SystemEvent(&IEvent::PanicCallback); g_debug_title_event = new SystemEvent(&IEvent::PanicCallback);
g_debug_application_event = new SystemEvent(&IEvent::PanicCallback); g_debug_application_event = new SystemEvent(&IEvent::PanicCallback);
g_process_launch_start_event = new SystemEvent(&Registration::ProcessLaunchStartCallback);
/* Get memory limits. */ /* Get memory limits. */
u64 memory_arrangement; u64 memory_arrangement;
@ -112,13 +111,8 @@ void Registration::InitializeSystemResources() {
} }
} }
Result Registration::ProcessLaunchStartCallback(Handle *handles, size_t num_handles, u64 timeout) { bool Registration::TryWaitProcessLaunchStartEvent() {
Registration::HandleProcessLaunch(); return g_sema_start_launch.TryWait();
return 0;
}
IWaitable *Registration::GetProcessLaunchStartEvent() {
return g_process_launch_start_event;
} }
IWaitable *Registration::GetProcessList() { IWaitable *Registration::GetProcessList() {
@ -129,17 +123,19 @@ void Registration::HandleProcessLaunch() {
LoaderProgramInfo program_info = {0}; LoaderProgramInfo program_info = {0};
Result rc; Result rc;
u64 launch_flags = g_process_launch_state.launch_flags; u64 launch_flags = g_process_launch_state.launch_flags;
const u8 *acid_fac, *aci0_fah, *acid_sac, *aci0_sac;
u64 *out_pid = g_process_launch_state.out_pid; u64 *out_pid = g_process_launch_state.out_pid;
u32 reslimit_idx; u32 reslimit_idx;
Process new_process = {0}; Process new_process = {0};
new_process.tid_sid = g_process_launch_state.tid_sid; new_process.tid_sid = g_process_launch_state.tid_sid;
u8 *ac_buf = new u8[4 * sizeof(LoaderProgramInfo)];
std::fill(ac_buf, ac_buf + 4 * sizeof(LoaderProgramInfo), 0xCC);
u8 *acid_sac = ac_buf, *aci0_sac = acid_sac + sizeof(LoaderProgramInfo), *fac = aci0_sac + sizeof(LoaderProgramInfo), *fah = fac + sizeof(LoaderProgramInfo);
/* Check that this is a real program. */ /* Check that this is a real program. */
if (R_FAILED((rc = ldrPmGetProgramInfo(new_process.tid_sid.title_id, new_process.tid_sid.storage_id, &program_info)))) { if (R_FAILED((rc = ldrPmGetProgramInfo(new_process.tid_sid.title_id, new_process.tid_sid.storage_id, &program_info)))) {
goto HANDLE_PROCESS_LAUNCH_END; goto HANDLE_PROCESS_LAUNCH_END;
} }
/* Get the resource limit handle, ensure that we can launch the program. */ /* Get the resource limit handle, ensure that we can launch the program. */
if ((program_info.application_type & 3) == 1) { if ((program_info.application_type & 3) == 1) {
if (HasApplicationProcess(NULL)) { if (HasApplicationProcess(NULL)) {
@ -155,7 +151,7 @@ void Registration::HandleProcessLaunch() {
if (R_FAILED((rc = ldrPmRegisterTitle(new_process.tid_sid.title_id, new_process.tid_sid.storage_id, &new_process.ldr_queue_index)))) { if (R_FAILED((rc = ldrPmRegisterTitle(new_process.tid_sid.title_id, new_process.tid_sid.storage_id, &new_process.ldr_queue_index)))) {
goto HANDLE_PROCESS_LAUNCH_END; goto HANDLE_PROCESS_LAUNCH_END;
} }
/* Make sure the previous application is cleaned up. */ /* Make sure the previous application is cleaned up. */
if ((program_info.application_type & 3) == 1) { if ((program_info.application_type & 3) == 1) {
EnsureApplicationResourcesAvailable(); EnsureApplicationResourcesAvailable();
@ -165,24 +161,24 @@ void Registration::HandleProcessLaunch() {
if (R_FAILED((rc = ldrPmCreateProcess(LAUNCHFLAGS_ARGLOW(launch_flags) | LAUNCHFLAGS_ARGHIGH(launch_flags), new_process.ldr_queue_index, g_resource_limit_handles[reslimit_idx], &new_process.handle)))) { if (R_FAILED((rc = ldrPmCreateProcess(LAUNCHFLAGS_ARGLOW(launch_flags) | LAUNCHFLAGS_ARGHIGH(launch_flags), new_process.ldr_queue_index, g_resource_limit_handles[reslimit_idx], &new_process.handle)))) {
goto PROCESS_CREATION_FAILED; goto PROCESS_CREATION_FAILED;
} }
/* Get the new process's id. */ /* Get the new process's id. */
svcGetProcessId(&new_process.pid, new_process.handle); svcGetProcessId(&new_process.pid, new_process.handle);
/* Register with FS. */ /* Register with FS. */
acid_fac = program_info.ac_buffer + program_info.acid_sac_size + program_info.aci0_sac_size; memcpy(fac, program_info.ac_buffer + program_info.acid_sac_size + program_info.aci0_sac_size, program_info.acid_fac_size);
aci0_fah = acid_fac + program_info.acid_fac_size; memcpy(fah, program_info.ac_buffer + program_info.acid_sac_size + program_info.aci0_sac_size + program_info.acid_fac_size, program_info.aci0_fah_size);
if (R_FAILED((rc = fsprRegisterProgram(new_process.pid, new_process.tid_sid.title_id, new_process.tid_sid.storage_id, aci0_fah, program_info.aci0_fah_size, acid_fac, program_info.acid_fac_size)))) { if (R_FAILED((rc = fsprRegisterProgram(new_process.pid, new_process.tid_sid.title_id, new_process.tid_sid.storage_id, fah, program_info.aci0_fah_size, fac, program_info.acid_fac_size)))) {
goto FS_REGISTRATION_FAILED; goto FS_REGISTRATION_FAILED;
} }
/* Register with PM. */ /* Register with SM. */
acid_sac = program_info.ac_buffer; memcpy(acid_sac, program_info.ac_buffer, program_info.acid_sac_size);
aci0_sac = program_info.ac_buffer + program_info.acid_sac_size; memcpy(aci0_sac, program_info.ac_buffer + program_info.acid_sac_size, program_info.aci0_sac_size);
if (R_FAILED((rc = smManagerRegisterProcess(new_process.pid, acid_sac, program_info.acid_sac_size, aci0_sac, program_info.aci0_sac_size)))) { if (R_FAILED((rc = smManagerRegisterProcess(new_process.pid, acid_sac, program_info.acid_sac_size, aci0_sac, program_info.aci0_sac_size)))) {
goto SM_REGISTRATION_FAILED; goto SM_REGISTRATION_FAILED;
} }
/* Setup process flags. */ /* Setup process flags. */
if (program_info.application_type & 1) { if (program_info.application_type & 1) {
new_process.flags |= 0x40; new_process.flags |= 0x40;
@ -213,8 +209,11 @@ void Registration::HandleProcessLaunch() {
rc = 0; rc = 0;
} else { } else {
rc = svcStartProcess(new_process.handle, program_info.main_thread_priority, program_info.default_cpu_id, program_info.main_thread_stack_size); rc = svcStartProcess(new_process.handle, program_info.main_thread_priority, program_info.default_cpu_id, program_info.main_thread_stack_size);
if (R_SUCCEEDED(rc)) { if (R_SUCCEEDED(rc)) {
SetProcessState(new_process.pid, ProcessState_DebugDetached); SetProcessState(new_process.pid, ProcessState_DebugDetached);
Log("MADENEWPROCESS", 16);
Log(GetProcess(new_process.pid), sizeof(Process));
} }
} }
@ -243,6 +242,7 @@ HANDLE_PROCESS_LAUNCH_END:
if (R_SUCCEEDED(rc)) { if (R_SUCCEEDED(rc)) {
*out_pid = new_process.pid; *out_pid = new_process.pid;
} }
delete ac_buf;
g_sema_finish_launch.Signal(); g_sema_finish_launch.Signal();
} }
@ -257,7 +257,7 @@ Result Registration::LaunchProcess(u64 title_id, FsStorageId storage_id, u64 lau
g_process_launch_state.out_pid = out_pid; g_process_launch_state.out_pid = out_pid;
/* Start a launch, and wait for it to exit. */ /* Start a launch, and wait for it to exit. */
g_process_launch_start_event->signal_event(); g_sema_start_launch.Signal();
g_sema_finish_launch.Wait(); g_sema_finish_launch.Wait();
rc = g_process_launch_state.result; rc = g_process_launch_state.result;
@ -272,7 +272,10 @@ Result Registration::LaunchProcessByTidSid(TidSid tid_sid, u64 launch_flags, u64
void Registration::HandleSignaledProcess(Process *process) { void Registration::HandleSignaledProcess(Process *process) {
u64 tmp; u64 tmp;
Log("PROCESSIGNALED\x00", 16);
Log(process, sizeof(*process));
/* Reset the signal. */ /* Reset the signal. */
svcResetSignal(process->handle); svcResetSignal(process->handle);
@ -280,6 +283,7 @@ void Registration::HandleSignaledProcess(Process *process) {
old_state = process->state; old_state = process->state;
svcGetProcessInfo(&tmp, process->handle, ProcessInfoType_ProcessState); svcGetProcessInfo(&tmp, process->handle, ProcessInfoType_ProcessState);
process->state = (ProcessState)tmp; process->state = (ProcessState)tmp;
Log(process, sizeof(*process));
if (old_state == ProcessState_Crashed && process->state != ProcessState_Crashed) { if (old_state == ProcessState_Crashed && process->state != ProcessState_Crashed) {
process->flags &= ~0x4; process->flags &= ~0x4;
@ -317,6 +321,7 @@ void Registration::HandleSignaledProcess(Process *process) {
} else { } else {
FinalizeExitedProcess(process); FinalizeExitedProcess(process);
} }
//Reboot();
break; break;
case ProcessState_DebugSuspended: case ProcessState_DebugSuspended:
if (process->flags & 8) { if (process->flags & 8) {
@ -454,9 +459,10 @@ void Registration::GetProcessEventType(u64 *out_pid, u64 *out_type) {
return; return;
} }
if (p->flags & 0x10) { if (p->flags & 0x10) {
u64 old_flags = p->flags;
p->flags &= ~0x10; p->flags &= ~0x10;
*out_pid = p->pid; *out_pid = p->pid;
*out_type = kernelAbove500() ? (((p->flags >> 5) & 1) | 4) : (((p->flags >> 5) & 1) + 3); *out_type = kernelAbove500() ? (((old_flags >> 5) & 1) | 4) : (((old_flags >> 5) & 1) + 3);
return; return;
} }
if (p->flags & 2) { if (p->flags & 2) {

View file

@ -5,7 +5,7 @@
#define LAUNCHFLAGS_NOTIFYWHENEXITED(flags) (flags & 1) #define LAUNCHFLAGS_NOTIFYWHENEXITED(flags) (flags & 1)
#define LAUNCHFLAGS_STARTSUSPENDED(flags) (flags & (kernelAbove500() ? 0x10 : 0x2)) #define LAUNCHFLAGS_STARTSUSPENDED(flags) (flags & (kernelAbove500() ? 0x10 : 0x2))
#define LAUNCHFLAGS_ARGLOW(flags) (kernelAbove500() ? ((flags & 0x14) != 0x10) : (kernelAbove200() ? ((flags & 0x6) != 0x2) : ((flags >> 2) & 1))) #define LAUNCHFLAGS_ARGLOW(flags) (kernelAbove500() ? ((flags & 0x14) != 0x10) : (kernelAbove200() ? ((flags & 0x6) != 0x2) : ((flags >> 2) & 1)))
#define LAUNCHFLAGS_ARGHIGH(flags) (flags & (kernelAbove500() ? 0x20 : 0x8)) #define LAUNCHFLAGS_ARGHIGH(flags) ((flags & (kernelAbove500() ? 0x20 : 0x8)) ? 2 : 0)
#define LAUNCHFLAGS_NOTIFYDEBUGEVENTS(flags) (flags & (kernelAbove500() ? 0x8 : 0x10)) #define LAUNCHFLAGS_NOTIFYDEBUGEVENTS(flags) (flags & (kernelAbove500() ? 0x8 : 0x10))
#define LAUNCHFLAGS_NOTIYDEBUGSPECIAL(flags) (flags & (kernelAbove500() ? 0x2 : (kernelAbove200() ? 0x20 : 0x0))) #define LAUNCHFLAGS_NOTIYDEBUGSPECIAL(flags) (flags & (kernelAbove500() ? 0x2 : (kernelAbove200() ? 0x20 : 0x0)))
@ -41,8 +41,7 @@ class Registration {
}; };
static void InitializeSystemResources(); static void InitializeSystemResources();
static IWaitable *GetProcessLaunchStartEvent(); static bool TryWaitProcessLaunchStartEvent();
static Result ProcessLaunchStartCallback(Handle *handles, size_t num_handles, u64 timeout);
static IWaitable *GetProcessList(); static IWaitable *GetProcessList();
static void HandleSignaledProcess(Process *process); static void HandleSignaledProcess(Process *process);

View file

@ -1,11 +1,15 @@
#include <switch.h> #include <switch.h>
#include "pm_registration.hpp" #include "pm_registration.hpp"
#include "pm_shell.hpp" #include "pm_shell.hpp"
#include "pm_debug.hpp"
static bool g_has_boot_finished = false; static bool g_has_boot_finished = false;
Result ShellService::dispatch(IpcParsedCommand &r, IpcCommand &out_c, u64 cmd_id, u8 *pointer_buffer, size_t pointer_buffer_size) { Result ShellService::dispatch(IpcParsedCommand &r, IpcCommand &out_c, u64 cmd_id, u8 *pointer_buffer, size_t pointer_buffer_size) {
Result rc = 0xF601; Result rc = 0xF601;
LogForService("SHELLSRV", 8);
LogForService(&cmd_id, 8);
LogForService(armGetTls(), 0x100);
if (kernelAbove500()) { if (kernelAbove500()) {
switch ((ShellCmd_5X)cmd_id) { switch ((ShellCmd_5X)cmd_id) {
case Shell_Cmd_5X_LaunchProcess: case Shell_Cmd_5X_LaunchProcess:
@ -69,6 +73,12 @@ Result ShellService::dispatch(IpcParsedCommand &r, IpcCommand &out_c, u64 cmd_id
break; break;
} }
} }
//Log(armGetTls(), 0x100);
LogForService(armGetTls(), 0x100);
if (R_FAILED(rc)) {
Reboot();
}
return rc; return rc;
} }
@ -88,7 +98,7 @@ std::tuple<Result> ShellService::terminate_process_id(u64 pid) {
Registration::Process *proc = Registration::GetProcess(pid); Registration::Process *proc = Registration::GetProcess(pid);
if (proc != NULL) { if (proc != NULL) {
return {svcCloseHandle(proc->handle)}; return {svcTerminateProcess(proc->handle)};
} else { } else {
return {0x20F}; return {0x20F};
} }
@ -99,7 +109,7 @@ std::tuple<Result> ShellService::terminate_title_id(u64 tid) {
Registration::Process *proc = Registration::GetProcessByTitleId(tid); Registration::Process *proc = Registration::GetProcessByTitleId(tid);
if (proc != NULL) { if (proc != NULL) {
return {svcCloseHandle(proc->handle)}; return {svcTerminateProcess(proc->handle)};
} else { } else {
return {0x20F}; return {0x20F};
} }