mirror of
https://github.com/Atmosphere-NX/Atmosphere
synced 2024-12-01 22:09:15 +00:00
kern: implement first half of SvcCreateProcess
This commit is contained in:
parent
fb6e85b291
commit
8759cb4da3
9 changed files with 228 additions and 26 deletions
|
@ -22,9 +22,9 @@ namespace ams::kern {
|
|||
struct KAddressSpaceInfo {
|
||||
public:
|
||||
enum Type {
|
||||
Type_32Bit = 0,
|
||||
Type_Small64Bit = 1,
|
||||
Type_Large64Bit = 2,
|
||||
Type_MapSmall = 0,
|
||||
Type_MapLarge = 1,
|
||||
Type_Map39Bit = 2,
|
||||
Type_Heap = 3,
|
||||
Type_Stack = 4,
|
||||
Type_Alias = 5,
|
||||
|
|
|
@ -48,6 +48,8 @@ namespace ams::kern {
|
|||
};
|
||||
|
||||
using ThreadList = util::IntrusiveListMemberTraits<&KThread::process_list_node>::ListType;
|
||||
|
||||
static constexpr size_t AslrAlignment = KernelAslrAlignment;
|
||||
private:
|
||||
using SharedMemoryInfoList = util::IntrusiveListBaseTraits<KSharedMemoryInfo>::ListType;
|
||||
using TLPTree = util::IntrusiveRedBlackTreeBaseTraits<KThreadLocalPage>::TreeType<KThreadLocalPage>;
|
||||
|
@ -123,6 +125,7 @@ namespace ams::kern {
|
|||
virtual ~KProcess() { /* ... */ }
|
||||
|
||||
Result Initialize(const ams::svc::CreateProcessParameter ¶ms, const KPageGroup &pg, const u32 *caps, s32 num_caps, KResourceLimit *res_limit, KMemoryManager::Pool pool);
|
||||
Result Initialize(const ams::svc::CreateProcessParameter ¶ms, svc::KUserPointer<const u32 *> caps, s32 num_caps, KResourceLimit *res_limit, KMemoryManager::Pool pool);
|
||||
void Exit();
|
||||
|
||||
constexpr const char *GetName() const { return this->name; }
|
||||
|
|
|
@ -22,16 +22,16 @@ namespace ams::kern {
|
|||
constexpr uintptr_t Invalid = std::numeric_limits<uintptr_t>::max();
|
||||
|
||||
constexpr KAddressSpaceInfo AddressSpaceInfos[] = {
|
||||
{ .bit_width = 32, .address = 2_MB, .size = 1_GB - 2_MB, .type = KAddressSpaceInfo::Type_32Bit, },
|
||||
{ .bit_width = 32, .address = 1_GB, .size = 4_GB - 1_GB, .type = KAddressSpaceInfo::Type_Small64Bit, },
|
||||
{ .bit_width = 32, .address = 2_MB, .size = 1_GB - 2_MB, .type = KAddressSpaceInfo::Type_MapSmall, },
|
||||
{ .bit_width = 32, .address = 1_GB, .size = 4_GB - 1_GB, .type = KAddressSpaceInfo::Type_MapLarge, },
|
||||
{ .bit_width = 32, .address = Invalid, .size = 1_GB, .type = KAddressSpaceInfo::Type_Heap, },
|
||||
{ .bit_width = 32, .address = Invalid, .size = 1_GB, .type = KAddressSpaceInfo::Type_Alias, },
|
||||
{ .bit_width = 36, .address = 128_MB, .size = 2_GB - 128_MB, .type = KAddressSpaceInfo::Type_32Bit, },
|
||||
{ .bit_width = 36, .address = 2_GB, .size = 64_GB - 2_GB, .type = KAddressSpaceInfo::Type_Small64Bit, },
|
||||
{ .bit_width = 36, .address = 128_MB, .size = 2_GB - 128_MB, .type = KAddressSpaceInfo::Type_MapSmall, },
|
||||
{ .bit_width = 36, .address = 2_GB, .size = 64_GB - 2_GB, .type = KAddressSpaceInfo::Type_MapLarge, },
|
||||
{ .bit_width = 36, .address = Invalid, .size = 6_GB, .type = KAddressSpaceInfo::Type_Heap, },
|
||||
{ .bit_width = 36, .address = Invalid, .size = 6_GB, .type = KAddressSpaceInfo::Type_Alias, },
|
||||
{ .bit_width = 39, .address = 128_MB, .size = 512_GB - 128_MB, .type = KAddressSpaceInfo::Type_Large64Bit, },
|
||||
{ .bit_width = 39, .address = Invalid, .size = 64_GB, .type = KAddressSpaceInfo::Type_32Bit, },
|
||||
{ .bit_width = 39, .address = 128_MB, .size = 512_GB - 128_MB, .type = KAddressSpaceInfo::Type_Map39Bit, },
|
||||
{ .bit_width = 39, .address = Invalid, .size = 64_GB, .type = KAddressSpaceInfo::Type_MapSmall, },
|
||||
{ .bit_width = 39, .address = Invalid, .size = 6_GB, .type = KAddressSpaceInfo::Type_Heap, },
|
||||
{ .bit_width = 39, .address = Invalid, .size = 64_GB, .type = KAddressSpaceInfo::Type_Alias, },
|
||||
{ .bit_width = 39, .address = Invalid, .size = 2_GB, .type = KAddressSpaceInfo::Type_Stack, },
|
||||
|
@ -54,15 +54,15 @@ namespace ams::kern {
|
|||
};
|
||||
|
||||
constexpr bool IsAllowed32BitType(KAddressSpaceInfo::Type type) {
|
||||
return type < KAddressSpaceInfo::Type_Count && type != KAddressSpaceInfo::Type_Large64Bit && type != KAddressSpaceInfo::Type_Stack;
|
||||
return type < KAddressSpaceInfo::Type_Count && type != KAddressSpaceInfo::Type_Map39Bit && type != KAddressSpaceInfo::Type_Stack;
|
||||
}
|
||||
|
||||
constexpr bool IsAllowed36BitType(KAddressSpaceInfo::Type type) {
|
||||
return type < KAddressSpaceInfo::Type_Count && type != KAddressSpaceInfo::Type_Large64Bit && type != KAddressSpaceInfo::Type_Stack;
|
||||
return type < KAddressSpaceInfo::Type_Count && type != KAddressSpaceInfo::Type_Map39Bit && type != KAddressSpaceInfo::Type_Stack;
|
||||
}
|
||||
|
||||
constexpr bool IsAllowed39BitType(KAddressSpaceInfo::Type type) {
|
||||
return type < KAddressSpaceInfo::Type_Count && type != KAddressSpaceInfo::Type_Small64Bit;
|
||||
return type < KAddressSpaceInfo::Type_Count && type != KAddressSpaceInfo::Type_MapLarge;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -106,7 +106,7 @@ namespace ams::kern {
|
|||
const uintptr_t start_address = rx_address;
|
||||
const uintptr_t end_address = bss_size > 0 ? bss_address + bss_size : rw_address + rw_size;
|
||||
const size_t as_width = this->Is64BitAddressSpace() ? 39 : 32;
|
||||
const ASType as_type = this->Is64BitAddressSpace() ? KAddressSpaceInfo::Type_Large64Bit : KAddressSpaceInfo::Type_32Bit;
|
||||
const ASType as_type = this->Is64BitAddressSpace() ? KAddressSpaceInfo::Type_Map39Bit : KAddressSpaceInfo::Type_MapSmall;
|
||||
const uintptr_t map_start = KAddressSpaceInfo::GetAddressSpaceStart(as_width, as_type);
|
||||
const size_t map_size = KAddressSpaceInfo::GetAddressSpaceSize(as_width, as_type);
|
||||
const uintptr_t map_end = map_start + map_size;
|
||||
|
|
|
@ -100,9 +100,9 @@ namespace ams::kern {
|
|||
alias_region_size = GetSpaceSize(KAddressSpaceInfo::Type_Alias);
|
||||
heap_region_size = GetSpaceSize(KAddressSpaceInfo::Type_Heap);
|
||||
stack_region_size = GetSpaceSize(KAddressSpaceInfo::Type_Stack);
|
||||
kernel_map_region_size = GetSpaceSize(KAddressSpaceInfo::Type_32Bit);
|
||||
this->code_region_start = GetSpaceStart(KAddressSpaceInfo::Type_Large64Bit);
|
||||
this->code_region_end = this->code_region_start + GetSpaceSize(KAddressSpaceInfo::Type_Large64Bit);
|
||||
kernel_map_region_size = GetSpaceSize(KAddressSpaceInfo::Type_MapSmall);
|
||||
this->code_region_start = GetSpaceStart(KAddressSpaceInfo::Type_Map39Bit);
|
||||
this->code_region_end = this->code_region_start + GetSpaceSize(KAddressSpaceInfo::Type_Map39Bit);
|
||||
this->alias_code_region_start = this->code_region_start;
|
||||
this->alias_code_region_end = this->code_region_end;
|
||||
process_code_start = util::AlignDown(GetInteger(code_address), RegionAlignment);
|
||||
|
@ -110,11 +110,11 @@ namespace ams::kern {
|
|||
} else {
|
||||
stack_region_size = 0;
|
||||
kernel_map_region_size = 0;
|
||||
this->code_region_start = GetSpaceStart(KAddressSpaceInfo::Type_32Bit);
|
||||
this->code_region_end = this->code_region_start + GetSpaceSize(KAddressSpaceInfo::Type_32Bit);
|
||||
this->code_region_start = GetSpaceStart(KAddressSpaceInfo::Type_MapSmall);
|
||||
this->code_region_end = this->code_region_start + GetSpaceSize(KAddressSpaceInfo::Type_MapSmall);
|
||||
this->stack_region_start = this->code_region_start;
|
||||
this->alias_code_region_start = this->code_region_start;
|
||||
this->alias_code_region_end = GetSpaceStart(KAddressSpaceInfo::Type_Small64Bit) + GetSpaceSize(KAddressSpaceInfo::Type_Small64Bit);
|
||||
this->alias_code_region_end = GetSpaceStart(KAddressSpaceInfo::Type_MapLarge) + GetSpaceSize(KAddressSpaceInfo::Type_MapLarge);
|
||||
this->stack_region_end = this->code_region_end;
|
||||
this->kernel_map_region_start = this->code_region_start;
|
||||
this->kernel_map_region_end = this->code_region_end;
|
||||
|
|
|
@ -106,7 +106,7 @@ namespace ams::kern {
|
|||
Result KProcess::Initialize(const ams::svc::CreateProcessParameter ¶ms, const KPageGroup &pg, const u32 *caps, s32 num_caps, KResourceLimit *res_limit, KMemoryManager::Pool pool) {
|
||||
MESOSPHERE_ASSERT_THIS();
|
||||
MESOSPHERE_ASSERT(res_limit != nullptr);
|
||||
MESOSPHERE_ABORT_UNLESS((params.code_num_pages * PageSize) / PageSize == params.code_num_pages);
|
||||
MESOSPHERE_ABORT_UNLESS((params.code_num_pages * PageSize) / PageSize == static_cast<size_t>(params.code_num_pages));
|
||||
|
||||
/* Set members. */
|
||||
this->memory_pool = pool;
|
||||
|
@ -153,6 +153,10 @@ namespace ams::kern {
|
|||
return ResultSuccess();
|
||||
}
|
||||
|
||||
Result KProcess::Initialize(const ams::svc::CreateProcessParameter ¶ms, svc::KUserPointer<const u32 *> caps, s32 num_caps, KResourceLimit *res_limit, KMemoryManager::Pool pool) {
|
||||
MESOSPHERE_UNIMPLEMENTED();
|
||||
}
|
||||
|
||||
void KProcess::DoWorkerTask() {
|
||||
MESOSPHERE_UNIMPLEMENTED();
|
||||
}
|
||||
|
|
|
@ -65,6 +65,192 @@ namespace ams::kern::svc {
|
|||
return KProcess::GetProcessList(out_num_processes, out_process_ids, max_out_count);
|
||||
}
|
||||
|
||||
Result CreateProcess(ams::svc::Handle *out, const ams::svc::CreateProcessParameter ¶ms, KUserPointer<const uint32_t *> user_caps, int32_t num_caps) {
|
||||
/* Validate the capabilities pointer. */
|
||||
R_UNLESS(num_caps >= 0, svc::ResultInvalidPointer());
|
||||
if (num_caps > 0) {
|
||||
/* Check for overflow. */
|
||||
R_UNLESS(((num_caps * sizeof(u32)) / sizeof(u32)) == static_cast<size_t>(num_caps), svc::ResultInvalidPointer());
|
||||
|
||||
/* Validate that the pointer is in range. */
|
||||
R_UNLESS(GetCurrentProcess().GetPageTable().Contains(KProcessAddress(user_caps.GetUnsafePointer()), num_caps * sizeof(u32)), svc::ResultInvalidPointer());
|
||||
}
|
||||
|
||||
/* Validate that the parameter flags are valid. */
|
||||
R_UNLESS((params.flags & ~ams::svc::CreateProcessFlag_All) == 0, svc::ResultInvalidEnumValue());
|
||||
|
||||
/* Validate that 64-bit process is okay. */
|
||||
const bool is_64_bit = (params.flags & ams::svc::CreateProcessFlag_Is64Bit) != 0;
|
||||
if constexpr (sizeof(void *) < sizeof(u64)) {
|
||||
R_UNLESS(!is_64_bit, svc::ResultInvalidCombination());
|
||||
}
|
||||
|
||||
/* Decide on an address space map region. */
|
||||
uintptr_t map_start, map_end;
|
||||
size_t map_size;
|
||||
switch (params.flags & ams::svc::CreateProcessFlag_AddressSpaceMask) {
|
||||
case ams::svc::CreateProcessFlag_AddressSpace32Bit:
|
||||
case ams::svc::CreateProcessFlag_AddressSpace32BitWithoutAlias:
|
||||
{
|
||||
map_start = KAddressSpaceInfo::GetAddressSpaceStart(32, KAddressSpaceInfo::Type_MapSmall);
|
||||
map_size = KAddressSpaceInfo::GetAddressSpaceSize(32, KAddressSpaceInfo::Type_MapSmall);
|
||||
map_end = map_start + map_size;
|
||||
}
|
||||
break;
|
||||
case ams::svc::CreateProcessFlag_AddressSpace64BitDeprecated:
|
||||
{
|
||||
/* 64-bit address space requires 64-bit process. */
|
||||
R_UNLESS(is_64_bit, svc::ResultInvalidCombination());
|
||||
|
||||
map_start = KAddressSpaceInfo::GetAddressSpaceStart(36, KAddressSpaceInfo::Type_MapSmall);
|
||||
map_size = KAddressSpaceInfo::GetAddressSpaceSize(36, KAddressSpaceInfo::Type_MapSmall);
|
||||
map_end = map_start + map_size;
|
||||
}
|
||||
break;
|
||||
case ams::svc::CreateProcessFlag_AddressSpace64Bit:
|
||||
{
|
||||
/* 64-bit address space requires 64-bit process. */
|
||||
R_UNLESS(is_64_bit, svc::ResultInvalidCombination());
|
||||
|
||||
map_start = KAddressSpaceInfo::GetAddressSpaceStart(39, KAddressSpaceInfo::Type_Map39Bit);
|
||||
map_end = map_start + KAddressSpaceInfo::GetAddressSpaceSize(39, KAddressSpaceInfo::Type_Map39Bit);
|
||||
|
||||
map_size = KAddressSpaceInfo::GetAddressSpaceSize(39, KAddressSpaceInfo::Type_Heap);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
return svc::ResultInvalidEnumValue();
|
||||
}
|
||||
|
||||
/* Validate the pool partition. */
|
||||
/* TODO: 4.0.0 UseSecureMemory flag, pre-4.0.0 behavior. */
|
||||
switch (params.flags & ams::svc::CreateProcessFlag_PoolPartitionMask) {
|
||||
case ams::svc::CreateProcessFlag_PoolPartitionApplication:
|
||||
case ams::svc::CreateProcessFlag_PoolPartitionApplet:
|
||||
case ams::svc::CreateProcessFlag_PoolPartitionSystem:
|
||||
case ams::svc::CreateProcessFlag_PoolPartitionSystemNonSecure:
|
||||
break;
|
||||
default:
|
||||
return svc::ResultInvalidEnumValue();
|
||||
}
|
||||
|
||||
/* Check that the code address is aligned. */
|
||||
R_UNLESS(util::IsAligned(params.code_address, KProcess::AslrAlignment), svc::ResultInvalidAddress());
|
||||
|
||||
/* Check that the number of code pages is >= 0. */
|
||||
R_UNLESS(params.code_num_pages >= 0, svc::ResultInvalidSize());
|
||||
|
||||
/* Check that the number of extra resource pages is >= 0. */
|
||||
R_UNLESS(params.system_resource_num_pages >= 0, svc::ResultInvalidSize());
|
||||
|
||||
/* Convert to sizes. */
|
||||
const size_t code_num_pages = params.code_num_pages;
|
||||
const size_t system_resource_num_pages = params.system_resource_num_pages;
|
||||
const size_t total_pages = code_num_pages + system_resource_num_pages;
|
||||
const size_t code_size = code_num_pages * PageSize;
|
||||
const size_t system_resource_size = system_resource_num_pages * PageSize;
|
||||
const size_t total_size = code_size + system_resource_size;
|
||||
|
||||
/* Check for overflow. */
|
||||
R_UNLESS((code_size / PageSize) == code_num_pages, svc::ResultInvalidSize());
|
||||
R_UNLESS((system_resource_size / PageSize) == system_resource_num_pages, svc::ResultInvalidSize());
|
||||
R_UNLESS((code_num_pages + system_resource_num_pages) >= code_num_pages, svc::ResultOutOfMemory());
|
||||
R_UNLESS((total_size / PageSize) == total_pages, svc::ResultInvalidSize());
|
||||
|
||||
/* Check that the number of pages is valid. */
|
||||
R_UNLESS(code_num_pages < (map_size / PageSize), svc::ResultInvalidMemoryRegion());
|
||||
|
||||
/* Validate that the code falls within the map reigon. */
|
||||
R_UNLESS(map_start <= params.code_address, svc::ResultInvalidMemoryRegion());
|
||||
R_UNLESS(params.code_address < params.code_address + code_size, svc::ResultInvalidMemoryRegion());
|
||||
R_UNLESS(params.code_address + code_size - 1 <= map_end - 1, svc::ResultInvalidMemoryRegion());
|
||||
|
||||
/* Check that the number of pages is valid for the kernel address space. */
|
||||
R_UNLESS(code_num_pages < (kern::MainMemorySize / PageSize), svc::ResultOutOfMemory());
|
||||
R_UNLESS(system_resource_num_pages < (kern::MainMemorySize / PageSize), svc::ResultOutOfMemory());
|
||||
R_UNLESS(total_pages < (kern::MainMemorySize / PageSize), svc::ResultOutOfMemory());
|
||||
|
||||
/* Check that optimized memory allocation is used only for applications. */
|
||||
const bool optimize_allocs = (params.flags & ams::svc::CreateProcessFlag_OptimizeMemoryAllocation) != 0;
|
||||
const bool is_application = (params.flags & ams::svc::CreateProcessFlag_IsApplication) != 0;
|
||||
R_UNLESS(!optimize_allocs || is_application, svc::ResultBusy());
|
||||
|
||||
/* Get the current handle table. */
|
||||
auto &handle_table = GetCurrentProcess().GetHandleTable();
|
||||
|
||||
/* Create the new process. */
|
||||
KProcess *process = KProcess::Create();
|
||||
R_UNLESS(process != nullptr, svc::ResultOutOfResource());
|
||||
|
||||
/* Ensure that the only reference to the process is in the handle table when we're done. */
|
||||
ON_SCOPE_EXIT { process->Close(); };
|
||||
|
||||
/* Get the resource limit from the handle. */
|
||||
KScopedAutoObject resource_limit = handle_table.GetObject<KResourceLimit>(params.reslimit);
|
||||
R_UNLESS(resource_limit.IsNotNull() || params.reslimit == ams::svc::InvalidHandle, svc::ResultInvalidHandle());
|
||||
|
||||
/* Decide on a resource limit for the process. */
|
||||
KResourceLimit *process_resource_limit = resource_limit.IsNotNull() ? resource_limit.GetPointerUnsafe() : std::addressof(Kernel::GetSystemResourceLimit());
|
||||
|
||||
/* Get the pool for the process. */
|
||||
/* TODO: 4.0.0 UseSecureMemory flag, pre-4.0.0 behavior. */
|
||||
KMemoryManager::Pool pool;
|
||||
switch (params.flags & ams::svc::CreateProcessFlag_PoolPartitionMask) {
|
||||
case ams::svc::CreateProcessFlag_PoolPartitionApplication:
|
||||
pool = KMemoryManager::Pool_Application;
|
||||
break;
|
||||
case ams::svc::CreateProcessFlag_PoolPartitionApplet:
|
||||
pool = KMemoryManager::Pool_Applet;
|
||||
break;
|
||||
case ams::svc::CreateProcessFlag_PoolPartitionSystem:
|
||||
pool = KMemoryManager::Pool_System;
|
||||
break;
|
||||
case ams::svc::CreateProcessFlag_PoolPartitionSystemNonSecure:
|
||||
default:
|
||||
pool = KMemoryManager::Pool_SystemNonSecure;
|
||||
break;
|
||||
}
|
||||
|
||||
/* Initialize the process. */
|
||||
R_TRY(process->Initialize(params, user_caps, num_caps, process_resource_limit, pool));
|
||||
|
||||
/* Register the process. */
|
||||
R_TRY(KProcess::Register(process));
|
||||
|
||||
/* Add the process to the handle table. */
|
||||
R_TRY(handle_table.Add(out, process));
|
||||
|
||||
return ResultSuccess();
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
Result CreateProcess(ams::svc::Handle *out, KUserPointer<const T *> user_parameters, KUserPointer<const uint32_t *> user_caps, int32_t num_caps) {
|
||||
/* Read the parameters from user space. */
|
||||
T params;
|
||||
R_TRY(user_parameters.CopyTo(std::addressof(params)));
|
||||
|
||||
/* Invoke the implementation. */
|
||||
if constexpr (std::same_as<T, ams::svc::CreateProcessParameter>) {
|
||||
return CreateProcess(out, params, user_caps, num_caps);
|
||||
} else {
|
||||
/* Convert the parameters. */
|
||||
ams::svc::CreateProcessParameter converted_params;
|
||||
static_assert(sizeof(T{}.name) == sizeof(ams::svc::CreateProcessParameter{}.name));
|
||||
|
||||
std::memcpy(converted_params.name, params.name, sizeof(converted_params.name));
|
||||
converted_params.version = params.version;
|
||||
converted_params.program_id = params.program_id;
|
||||
converted_params.code_address = params.code_address;
|
||||
converted_params.code_num_pages = params.code_num_pages;
|
||||
converted_params.flags = params.flags;
|
||||
converted_params.reslimit = params.reslimit;
|
||||
converted_params.system_resource_num_pages = params.system_resource_num_pages;
|
||||
|
||||
/* Invoke. */
|
||||
return CreateProcess(out, converted_params, user_caps, num_caps);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/* ============================= 64 ABI ============================= */
|
||||
|
@ -82,7 +268,7 @@ namespace ams::kern::svc {
|
|||
}
|
||||
|
||||
Result CreateProcess64(ams::svc::Handle *out_handle, KUserPointer<const ams::svc::lp64::CreateProcessParameter *> parameters, KUserPointer<const uint32_t *> caps, int32_t num_caps) {
|
||||
MESOSPHERE_PANIC("Stubbed SvcCreateProcess64 was called.");
|
||||
return CreateProcess(out_handle, parameters, caps, num_caps);
|
||||
}
|
||||
|
||||
Result StartProcess64(ams::svc::Handle process_handle, int32_t priority, int32_t core_id, uint64_t main_thread_stack_size) {
|
||||
|
@ -112,7 +298,7 @@ namespace ams::kern::svc {
|
|||
}
|
||||
|
||||
Result CreateProcess64From32(ams::svc::Handle *out_handle, KUserPointer<const ams::svc::ilp32::CreateProcessParameter *> parameters, KUserPointer<const uint32_t *> caps, int32_t num_caps) {
|
||||
MESOSPHERE_PANIC("Stubbed SvcCreateProcess64From32 was called.");
|
||||
return CreateProcess(out_handle, parameters, caps, num_caps);
|
||||
}
|
||||
|
||||
Result StartProcess64From32(ams::svc::Handle process_handle, int32_t priority, int32_t core_id, uint64_t main_thread_stack_size) {
|
||||
|
|
|
@ -374,6 +374,15 @@ namespace ams::svc {
|
|||
|
||||
/* 7.x+ Should memory allocation be optimized? This requires IsApplication. */
|
||||
CreateProcessFlag_OptimizeMemoryAllocation = (1 << 11),
|
||||
|
||||
/* Mask of all flags. */
|
||||
CreateProcessFlag_All = CreateProcessFlag_Is64Bit |
|
||||
CreateProcessFlag_AddressSpaceMask |
|
||||
CreateProcessFlag_EnableDebug |
|
||||
CreateProcessFlag_EnableAslr |
|
||||
CreateProcessFlag_IsApplication |
|
||||
CreateProcessFlag_PoolPartitionMask |
|
||||
CreateProcessFlag_OptimizeMemoryAllocation,
|
||||
};
|
||||
|
||||
/* Debug types. */
|
||||
|
|
|
@ -25,10 +25,10 @@ namespace ams::svc {
|
|||
u32 version;
|
||||
u64 program_id;
|
||||
u64 code_address;
|
||||
u32 code_num_pages;
|
||||
s32 code_num_pages;
|
||||
u32 flags;
|
||||
Handle reslimit;
|
||||
u32 system_resource_num_pages;
|
||||
s32 system_resource_num_pages;
|
||||
};
|
||||
static_assert(sizeof(CreateProcessParameter) == 0x30);
|
||||
|
||||
|
@ -41,10 +41,10 @@ namespace ams::svc {
|
|||
u32 version;
|
||||
u64 program_id;
|
||||
u64 code_address;
|
||||
u32 code_num_pages;
|
||||
s32 code_num_pages;
|
||||
u32 flags;
|
||||
Handle reslimit;
|
||||
u32 system_resource_num_pages;
|
||||
s32 system_resource_num_pages;
|
||||
};
|
||||
static_assert(sizeof(CreateProcessParameter) == 0x30);
|
||||
|
||||
|
|
Loading…
Reference in a new issue