mirror of
https://github.com/skyline-emu/skyline.git
synced 2024-11-04 23:15:08 +01:00
Remove support for multiple guest processes
This commit removes support for more than one guest processes as it requires a fair bit of extra code to support in addition the HLE service implementations don't support it anyway.
This commit is contained in:
parent
48d47a2b25
commit
b84859d352
@ -91,7 +91,7 @@ namespace skyline {
|
||||
}
|
||||
|
||||
DeviceState::DeviceState(kernel::OS *os, std::shared_ptr<kernel::type::KProcess> &thisProcess, std::shared_ptr<kernel::type::KThread> &thisThread, std::shared_ptr<JvmManager> jvmManager, std::shared_ptr<Settings> settings, std::shared_ptr<Logger> logger)
|
||||
: os(os), jvmManager(std::move(jvmManager)), settings(std::move(settings)), logger(std::move(logger)), thisProcess(thisProcess), thisThread(thisThread) {
|
||||
: os(os), jvmManager(std::move(jvmManager)), settings(std::move(settings)), logger(std::move(logger)), process(thisProcess), thread(thisThread) {
|
||||
// We assign these later as they use the state in their constructor and we don't want null pointers
|
||||
nce = std::move(std::make_shared<NCE>(*this));
|
||||
gpu = std::move(std::make_shared<gpu::GPU>(*this));
|
||||
|
@ -306,8 +306,8 @@ namespace skyline {
|
||||
DeviceState(kernel::OS *os, std::shared_ptr<kernel::type::KProcess> &thisProcess, std::shared_ptr<kernel::type::KThread> &thisThread, std::shared_ptr<JvmManager> jvmManager, std::shared_ptr<Settings> settings, std::shared_ptr<Logger> logger);
|
||||
|
||||
kernel::OS *os; //!< This holds a reference to the OS class
|
||||
std::shared_ptr<kernel::type::KProcess> &thisProcess; //!< This holds a reference to the current process object
|
||||
std::shared_ptr<kernel::type::KThread> &thisThread; //!< This holds a reference to the current thread object
|
||||
std::shared_ptr<kernel::type::KProcess> &process; //!< This holds a reference to the process object
|
||||
std::shared_ptr<kernel::type::KThread> &thread; //!< This holds a reference to the current thread object
|
||||
std::shared_ptr<NCE> nce; //!< This holds a reference to the NCE class
|
||||
std::shared_ptr<gpu::GPU> gpu; //!< This holds a reference to the GPU class
|
||||
std::shared_ptr<JvmManager> jvmManager; //!< This holds a reference to the JvmManager class
|
||||
|
@ -18,7 +18,7 @@ namespace skyline::gpu {
|
||||
std::unordered_map<device::NvDeviceType, std::shared_ptr<device::NvDevice>> deviceMap; //!< A map from a NvDeviceType to the NvDevice object
|
||||
std::unordered_map<u32, std::shared_ptr<device::NvDevice>> fdMap; //!< A map from an FD to a shared pointer to it's NvDevice object
|
||||
bool surfaceUpdate{}; //!< If the surface needs to be updated
|
||||
double prevTime{};
|
||||
double prevTime{}; //!< The time passed from the last frame
|
||||
|
||||
public:
|
||||
DisplayId displayId{DisplayId::Null}; //!< The ID of this display
|
||||
|
@ -21,7 +21,7 @@ namespace skyline::gpu::device {
|
||||
void NvHostChannel::SetErrorNotifier(skyline::gpu::device::IoctlData &buffer) {}
|
||||
|
||||
void NvHostChannel::SetPriority(skyline::gpu::device::IoctlData &buffer) {
|
||||
auto priority = state.thisProcess->ReadMemory<NvChannelPriority>(buffer.input[0].address);
|
||||
auto priority = state.process->ReadMemory<NvChannelPriority>(buffer.input[0].address);
|
||||
switch (priority) {
|
||||
case NvChannelPriority::Low:
|
||||
timeslice = 1300;
|
||||
|
@ -12,7 +12,7 @@ namespace skyline::gpu::device {
|
||||
|
||||
void NvHostCtrlGpu::ZCullGetCtxSize(IoctlData &buffer) {
|
||||
u32 size = 0x1;
|
||||
state.thisProcess->WriteMemory(size, buffer.output[0].address);
|
||||
state.process->WriteMemory(size, buffer.output[0].address);
|
||||
}
|
||||
|
||||
void NvHostCtrlGpu::ZCullGetInfo(skyline::gpu::device::IoctlData &buffer) {
|
||||
@ -28,7 +28,7 @@ namespace skyline::gpu::device {
|
||||
u32 subregionHeightAlignPixels{0x40};
|
||||
u32 subregionCount{0x10};
|
||||
} zCullInfo;
|
||||
state.thisProcess->WriteMemory(zCullInfo, buffer.output[0].address);
|
||||
state.process->WriteMemory(zCullInfo, buffer.output[0].address);
|
||||
}
|
||||
|
||||
void NvHostCtrlGpu::GetCharacteristics(IoctlData &buffer) {
|
||||
@ -73,7 +73,7 @@ namespace skyline::gpu::device {
|
||||
u64 gpuCharacteristicsBufSize; // InOut
|
||||
u64 gpuCharacteristicsBufAddr; // In
|
||||
GpuCharacteristics gpuCharacteristics; // Out
|
||||
} data = state.thisProcess->ReadMemory<Data>(buffer.input[0].address);
|
||||
} data = state.process->ReadMemory<Data>(buffer.input[0].address);
|
||||
data.gpuCharacteristics = {
|
||||
.arch = 0x120,
|
||||
.impl = 0xB,
|
||||
@ -111,7 +111,7 @@ namespace skyline::gpu::device {
|
||||
.grCompbitStoreBaseHw = 0x0
|
||||
};
|
||||
data.gpuCharacteristicsBufSize = 0xA0;
|
||||
state.thisProcess->WriteMemory(data, buffer.output[0].address);
|
||||
state.process->WriteMemory(data, buffer.output[0].address);
|
||||
}
|
||||
|
||||
void NvHostCtrlGpu::GetTpcMasks(IoctlData &buffer) {
|
||||
@ -119,10 +119,10 @@ namespace skyline::gpu::device {
|
||||
u32 maskBufSize; // In
|
||||
u32 reserved[3]; // In
|
||||
u64 maskBuf; // Out
|
||||
} data = state.thisProcess->ReadMemory<Data>(buffer.input[0].address);
|
||||
} data = state.process->ReadMemory<Data>(buffer.input[0].address);
|
||||
if (data.maskBufSize)
|
||||
data.maskBuf = 0x3;
|
||||
state.thisProcess->WriteMemory(data, buffer.output[0].address);
|
||||
state.process->WriteMemory(data, buffer.output[0].address);
|
||||
}
|
||||
|
||||
void NvHostCtrlGpu::GetActiveSlotMask(IoctlData &buffer) {
|
||||
@ -133,6 +133,6 @@ namespace skyline::gpu::device {
|
||||
.slot = 0x07,
|
||||
.mask = 0x01
|
||||
};
|
||||
state.thisProcess->WriteMemory(data, buffer.output[0].address);
|
||||
state.process->WriteMemory(data, buffer.output[0].address);
|
||||
}
|
||||
}
|
||||
|
@ -17,10 +17,10 @@ namespace skyline::gpu::device {
|
||||
struct Data {
|
||||
u32 size; // In
|
||||
u32 handle; // Out
|
||||
} data = state.thisProcess->ReadMemory<Data>(buffer.input[0].address);
|
||||
} data = state.process->ReadMemory<Data>(buffer.input[0].address);
|
||||
handleTable[handleIndex] = std::make_shared<NvMapObject>(idIndex++, data.size);
|
||||
data.handle = handleIndex++;
|
||||
state.thisProcess->WriteMemory(data, buffer.output[0].address);
|
||||
state.process->WriteMemory(data, buffer.output[0].address);
|
||||
state.logger->Debug("Create: Input: Size: 0x{:X}, Output: Handle: 0x{:X}, Status: {}", data.size, data.handle, buffer.status);
|
||||
}
|
||||
|
||||
@ -28,7 +28,7 @@ namespace skyline::gpu::device {
|
||||
struct Data {
|
||||
u32 id; // In
|
||||
u32 handle; // Out
|
||||
} data = state.thisProcess->ReadMemory<Data>(buffer.input[0].address);
|
||||
} data = state.process->ReadMemory<Data>(buffer.input[0].address);
|
||||
bool found{};
|
||||
for (const auto &object : handleTable) {
|
||||
if (object.second->id == data.id) {
|
||||
@ -38,7 +38,7 @@ namespace skyline::gpu::device {
|
||||
}
|
||||
}
|
||||
if (found)
|
||||
state.thisProcess->WriteMemory(data, buffer.output[0].address);
|
||||
state.process->WriteMemory(data, buffer.output[0].address);
|
||||
else
|
||||
buffer.status = NvStatus::BadValue;
|
||||
state.logger->Debug("FromId: Input: Handle: 0x{:X}, Output: ID: 0x{:X}, Status: {}", data.handle, data.id, buffer.status);
|
||||
@ -53,7 +53,7 @@ namespace skyline::gpu::device {
|
||||
u8 kind; // In
|
||||
u8 _pad0_[7];
|
||||
u64 address; // InOut
|
||||
} data = state.thisProcess->ReadMemory<Data>(buffer.input[0].address);
|
||||
} data = state.process->ReadMemory<Data>(buffer.input[0].address);
|
||||
auto &object = handleTable.at(data.handle);
|
||||
object->heapMask = data.heapMask;
|
||||
object->flags = data.flags;
|
||||
@ -71,7 +71,7 @@ namespace skyline::gpu::device {
|
||||
u32 address; // Out
|
||||
u32 size; // Out
|
||||
u64 flags; // Out
|
||||
} data = state.thisProcess->ReadMemory<Data>(buffer.input[0].address);
|
||||
} data = state.process->ReadMemory<Data>(buffer.input[0].address);
|
||||
const auto &object = handleTable.at(data.handle);
|
||||
if (object.use_count() > 1) {
|
||||
data.address = static_cast<u32>(object->address);
|
||||
@ -82,7 +82,7 @@ namespace skyline::gpu::device {
|
||||
}
|
||||
data.size = object->size;
|
||||
handleTable.erase(data.handle);
|
||||
state.thisProcess->WriteMemory(data, buffer.output[0].address);
|
||||
state.process->WriteMemory(data, buffer.output[0].address);
|
||||
}
|
||||
|
||||
void NvMap::Param(IoctlData &buffer) {
|
||||
@ -91,7 +91,7 @@ namespace skyline::gpu::device {
|
||||
u32 handle; // In
|
||||
Parameter parameter; // In
|
||||
u32 result; // Out
|
||||
} data = state.thisProcess->ReadMemory<Data>(buffer.input[0].address);
|
||||
} data = state.process->ReadMemory<Data>(buffer.input[0].address);
|
||||
auto &object = handleTable.at(data.handle);
|
||||
switch (data.parameter) {
|
||||
case Parameter::Size:
|
||||
@ -124,7 +124,7 @@ namespace skyline::gpu::device {
|
||||
buffer.status = NvStatus::NotImplemented;
|
||||
break;
|
||||
}
|
||||
state.thisProcess->WriteMemory(data, buffer.output[0].address);
|
||||
state.process->WriteMemory(data, buffer.output[0].address);
|
||||
state.logger->Debug("Param: Input: Handle: 0x{:X}, Parameter: {}, Output: Result: 0x{:X}, Status: {}", data.handle, data.parameter, data.result, buffer.status);
|
||||
}
|
||||
|
||||
@ -132,9 +132,9 @@ namespace skyline::gpu::device {
|
||||
struct Data {
|
||||
u32 id; // Out
|
||||
u32 handle; // In
|
||||
} data = state.thisProcess->ReadMemory<Data>(buffer.input[0].address);
|
||||
} data = state.process->ReadMemory<Data>(buffer.input[0].address);
|
||||
data.id = handleTable.at(data.handle)->id;
|
||||
state.thisProcess->WriteMemory(data, buffer.output[0].address);
|
||||
state.process->WriteMemory(data, buffer.output[0].address);
|
||||
state.logger->Debug("GetId: Input: Handle: 0x{:X}, Output: ID: 0x{:X}, Status: {}", data.handle, data.id, buffer.status);
|
||||
}
|
||||
}
|
||||
|
@ -31,7 +31,7 @@ namespace skyline::gpu {
|
||||
}
|
||||
|
||||
void Buffer::UpdateBuffer() {
|
||||
state.thisProcess->ReadMemory(dataBuffer.data(), nvBuffer->address + gbpBuffer.offset, gbpBuffer.size);
|
||||
state.process->ReadMemory(dataBuffer.data(), nvBuffer->address + gbpBuffer.offset, gbpBuffer.size);
|
||||
}
|
||||
|
||||
BufferQueue::WaitContext::WaitContext(std::shared_ptr<kernel::type::KThread> thread, DequeueIn input, kernel::ipc::OutputBuffer& buffer) : thread(std::move(thread)), input(input), buffer(buffer) {}
|
||||
@ -59,8 +59,8 @@ namespace skyline::gpu {
|
||||
}
|
||||
}
|
||||
if (slot == -1) {
|
||||
state.thisThread->Sleep();
|
||||
waitVec.emplace_back(state.thisThread, *data, buffer);
|
||||
state.thread->Sleep();
|
||||
waitVec.emplace_back(state.thread, *data, buffer);
|
||||
state.logger->Debug("DequeueBuffer: Width: {}, Height: {}, Format: {}, Usage: {}, Timestamps: {}, No Free Buffers", data->width, data->height, data->format, data->usage, data->timestamps);
|
||||
return true;
|
||||
}
|
||||
@ -135,7 +135,7 @@ namespace skyline::gpu {
|
||||
gpu::Parcel out(state);
|
||||
DequeueOut output(slotNo);
|
||||
out.WriteData(output);
|
||||
out.WriteParcel(context->buffer, context->thread->pid);
|
||||
out.WriteParcel(context->buffer);
|
||||
slot->status = BufferStatus::Dequeued;
|
||||
waitVec.erase(context);
|
||||
break;
|
||||
|
@ -6,22 +6,22 @@ namespace skyline::gpu {
|
||||
Parcel::Parcel(kernel::ipc::InputBuffer &buffer, const DeviceState &state) : Parcel(buffer.address, buffer.size, state) {}
|
||||
|
||||
Parcel::Parcel(u64 address, u64 size, const DeviceState &state) : state(state) {
|
||||
state.thisProcess->ReadMemory(&header, address, sizeof(ParcelHeader));
|
||||
state.process->ReadMemory(&header, address, sizeof(ParcelHeader));
|
||||
if (size < (sizeof(ParcelHeader) + header.dataSize + header.objectsSize))
|
||||
throw exception("The size of the parcel according to the header exceeds the specified size");
|
||||
data.resize(header.dataSize);
|
||||
state.thisProcess->ReadMemory(data.data(), address + header.dataOffset, header.dataSize);
|
||||
state.process->ReadMemory(data.data(), address + header.dataOffset, header.dataSize);
|
||||
objects.resize(header.objectsSize);
|
||||
state.thisProcess->ReadMemory(objects.data(), address + header.objectsOffset, header.objectsSize);
|
||||
state.process->ReadMemory(objects.data(), address + header.objectsOffset, header.objectsSize);
|
||||
}
|
||||
|
||||
Parcel::Parcel(const DeviceState &state) : state(state) {}
|
||||
|
||||
u64 Parcel::WriteParcel(kernel::ipc::OutputBuffer& buffer, pid_t process) {
|
||||
return WriteParcel(buffer.address, buffer.size, process);
|
||||
u64 Parcel::WriteParcel(kernel::ipc::OutputBuffer& buffer) {
|
||||
return WriteParcel(buffer.address, buffer.size);
|
||||
}
|
||||
|
||||
u64 Parcel::WriteParcel(u64 address, u64 maxSize, pid_t process) {
|
||||
u64 Parcel::WriteParcel(u64 address, u64 maxSize) {
|
||||
header.dataSize = static_cast<u32>(data.size());
|
||||
header.dataOffset = sizeof(ParcelHeader);
|
||||
header.objectsSize = static_cast<u32>(objects.size());
|
||||
@ -29,16 +29,9 @@ namespace skyline::gpu {
|
||||
u64 totalSize = sizeof(ParcelHeader) + header.dataSize + header.objectsSize;
|
||||
if (maxSize < totalSize)
|
||||
throw exception("The size of the parcel exceeds maxSize");
|
||||
if (process) {
|
||||
auto &object = state.os->processMap.at(process);
|
||||
object->WriteMemory(header, address);
|
||||
object->WriteMemory(data.data(), address + header.dataOffset, data.size());
|
||||
object->WriteMemory(objects.data(), address + header.objectsOffset, objects.size());
|
||||
} else {
|
||||
state.thisProcess->WriteMemory(header, address);
|
||||
state.thisProcess->WriteMemory(data.data(), address + header.dataOffset, data.size());
|
||||
state.thisProcess->WriteMemory(objects.data(), address + header.objectsOffset, objects.size());
|
||||
}
|
||||
state.process->WriteMemory(header, address);
|
||||
state.process->WriteMemory(data.data(), address + header.dataOffset, data.size());
|
||||
state.process->WriteMemory(objects.data(), address + header.objectsOffset, objects.size());
|
||||
return totalSize;
|
||||
}
|
||||
}
|
||||
|
@ -80,18 +80,16 @@ namespace skyline::gpu {
|
||||
/**
|
||||
* @brief Writes the Parcel object into a particular output buffer on a process
|
||||
* @param buffer The buffer to write into
|
||||
* @param process The process to write the Parcel to
|
||||
* @return The total size of the message
|
||||
*/
|
||||
u64 WriteParcel(kernel::ipc::OutputBuffer& buffer, pid_t process = 0);
|
||||
u64 WriteParcel(kernel::ipc::OutputBuffer& buffer);
|
||||
|
||||
/**
|
||||
* @brief Writes the Parcel object into the process's memory
|
||||
* @param address The address to write the Parcel object to
|
||||
* @param maxSize The maximum size of the Parcel
|
||||
* @param process The process to write the Parcel to
|
||||
* @return The total size of the message
|
||||
*/
|
||||
u64 WriteParcel(u64 address, u64 maxSize, pid_t process = 0);
|
||||
u64 WriteParcel(u64 address, u64 maxSize);
|
||||
};
|
||||
}
|
||||
|
@ -1,8 +1,179 @@
|
||||
#pragma once
|
||||
|
||||
namespace skyline::guest {
|
||||
constexpr size_t saveCtxSize = 20 * sizeof(u32);
|
||||
constexpr size_t loadCtxSize = 20 * sizeof(u32);
|
||||
extern "C" void saveCtx(void);
|
||||
extern "C" void loadCtx(void);
|
||||
namespace skyline {
|
||||
namespace guest {
|
||||
constexpr size_t saveCtxSize = 20 * sizeof(u32);
|
||||
constexpr size_t loadCtxSize = 20 * sizeof(u32);
|
||||
extern "C" void saveCtx(void);
|
||||
extern "C" void loadCtx(void);
|
||||
}
|
||||
|
||||
namespace instr {
|
||||
/**
|
||||
* @brief A bit-field struct that encapsulates a BRK instruction. See https://developer.arm.com/docs/ddi0596/latest/base-instructions-alphabetic-order/brk-breakpoint-instruction.
|
||||
*/
|
||||
struct Brk {
|
||||
/**
|
||||
* @brief Creates a BRK instruction with a specific immediate value, used for generating BRK opcodes
|
||||
* @param value The immediate value of the instruction
|
||||
*/
|
||||
explicit Brk(u16 value) {
|
||||
start = 0x0; // First 5 bits of a BRK instruction are 0
|
||||
this->value = value;
|
||||
end = 0x6A1; // Last 11 bits of a BRK instruction stored as u16
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Returns if the opcode is valid or not
|
||||
* @return If the opcode represents a valid BRK instruction
|
||||
*/
|
||||
inline bool Verify() {
|
||||
return (start == 0x0 && end == 0x6A1);
|
||||
}
|
||||
|
||||
union {
|
||||
struct {
|
||||
u8 start : 5;
|
||||
u32 value : 16;
|
||||
u16 end : 11;
|
||||
};
|
||||
u32 raw{};
|
||||
};
|
||||
};
|
||||
|
||||
static_assert(sizeof(Brk) == sizeof(u32));
|
||||
|
||||
/**
|
||||
* @brief A bit-field struct that encapsulates a SVC instruction. See https://developer.arm.com/docs/ddi0596/latest/base-instructions-alphabetic-order/svc-supervisor-call.
|
||||
*/
|
||||
struct Svc {
|
||||
/**
|
||||
* @brief Returns if the opcode is valid or not
|
||||
* @return If the opcode represents a valid SVC instruction
|
||||
*/
|
||||
inline bool Verify() {
|
||||
return (start == 0x1 && end == 0x6A0);
|
||||
}
|
||||
|
||||
union {
|
||||
struct {
|
||||
u8 start : 5;
|
||||
u32 value : 16;
|
||||
u16 end : 11;
|
||||
};
|
||||
u32 raw{};
|
||||
};
|
||||
};
|
||||
|
||||
static_assert(sizeof(Svc) == sizeof(u32));
|
||||
|
||||
/**
|
||||
* @brief A bit-field struct that encapsulates a MRS instruction. See https://developer.arm.com/docs/ddi0596/latest/base-instructions-alphabetic-order/mrs-move-system-register.
|
||||
*/
|
||||
struct Mrs {
|
||||
/**
|
||||
* @brief Creates a MRS instruction, used for generating BRK opcodes
|
||||
* @param srcReg The source system register
|
||||
* @param dstReg The destination Xn register
|
||||
*/
|
||||
Mrs(u32 srcReg, u8 dstReg) {
|
||||
this->srcReg = srcReg;
|
||||
this->dstReg = dstReg;
|
||||
end = 0xD53; // Last 12 bits of a MRS instruction stored as u16
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Returns if the opcode is valid or not
|
||||
* @return If the opcode represents a valid MRS instruction
|
||||
*/
|
||||
inline bool Verify() {
|
||||
return (end == 0xD53);
|
||||
}
|
||||
|
||||
union {
|
||||
struct {
|
||||
u8 dstReg : 5;
|
||||
u32 srcReg : 15;
|
||||
u16 end : 12;
|
||||
};
|
||||
u32 raw{};
|
||||
};
|
||||
};
|
||||
|
||||
static_assert(sizeof(Mrs) == sizeof(u32));
|
||||
|
||||
/**
|
||||
* @brief A bit-field struct that encapsulates a B instruction. See https://developer.arm.com/docs/ddi0596/latest/base-instructions-alphabetic-order/b-branch.
|
||||
*/
|
||||
struct B {
|
||||
public:
|
||||
explicit B(i64 offset) {
|
||||
this->offset = static_cast<i32>(offset / 4);
|
||||
end = 0x5;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Returns the offset of the instruction
|
||||
* @return The offset encoded within the instruction
|
||||
*/
|
||||
inline i32 Offset() {
|
||||
return offset * 4;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Returns if the opcode is valid or not
|
||||
* @return If the opcode represents a valid Branch instruction
|
||||
*/
|
||||
inline bool Verify() {
|
||||
return (end == 0x5);
|
||||
}
|
||||
|
||||
union {
|
||||
struct {
|
||||
i32 offset : 26;
|
||||
u8 end : 6;
|
||||
};
|
||||
u32 raw{};
|
||||
};
|
||||
};
|
||||
|
||||
static_assert(sizeof(B) == sizeof(u32));
|
||||
|
||||
/**
|
||||
* @brief A bit-field struct that encapsulates a BL instruction. See https://developer.arm.com/docs/ddi0596/latest/base-instructions-alphabetic-order/b-branch.
|
||||
*/
|
||||
struct BL {
|
||||
public:
|
||||
explicit BL(i64 offset) {
|
||||
this->offset = static_cast<i32>(offset / 4);
|
||||
end = 0x25;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Returns the offset of the instruction
|
||||
* @return The offset encoded within the instruction
|
||||
*/
|
||||
inline i32 Offset() {
|
||||
return offset * 4;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Returns if the opcode is valid or not
|
||||
* @return If the opcode represents a valid Branch instruction
|
||||
*/
|
||||
inline bool Verify() {
|
||||
return (end == 0x85);
|
||||
}
|
||||
|
||||
union {
|
||||
struct {
|
||||
i32 offset : 26;
|
||||
u8 end : 6;
|
||||
};
|
||||
u32 raw{};
|
||||
};
|
||||
};
|
||||
|
||||
static_assert(sizeof(BL) == sizeof(u32));
|
||||
}
|
||||
}
|
||||
|
@ -14,7 +14,7 @@ namespace skyline::kernel::ipc {
|
||||
|
||||
IpcRequest::IpcRequest(bool isDomain, const DeviceState &state) : isDomain(isDomain), state(state), tls() {
|
||||
u8 *currPtr = tls.data();
|
||||
state.thisProcess->ReadMemory(currPtr, state.thisThread->tls, constant::TlsIpcSize);
|
||||
state.process->ReadMemory(currPtr, state.thread->tls, constant::TlsIpcSize);
|
||||
|
||||
header = reinterpret_cast<CommandHeader *>(currPtr);
|
||||
currPtr += sizeof(CommandHeader);
|
||||
@ -184,12 +184,12 @@ namespace skyline::kernel::ipc {
|
||||
|
||||
state.logger->Debug("Output: Raw Size: {}, Command ID: 0x{:X}, Copy Handles: {}, Move Handles: {}", u32(header->rawSize), u32(payload->value), copyHandles.size(), moveHandles.size());
|
||||
|
||||
state.thisProcess->WriteMemory(tls.data(), state.thisThread->tls, constant::TlsIpcSize);
|
||||
state.process->WriteMemory(tls.data(), state.thread->tls, constant::TlsIpcSize);
|
||||
}
|
||||
|
||||
std::vector<u8> BufferDescriptorABW::Read(const DeviceState &state) {
|
||||
std::vector<u8> vec(Size());
|
||||
state.thisProcess->ReadMemory(vec.data(), Address(), Size());
|
||||
state.process->ReadMemory(vec.data(), Address(), Size());
|
||||
return std::move(vec);
|
||||
}
|
||||
}
|
||||
|
@ -12,12 +12,12 @@ namespace skyline::kernel::svc {
|
||||
}
|
||||
std::shared_ptr<type::KPrivateMemory> heap;
|
||||
try {
|
||||
heap = state.thisProcess->memoryRegionMap.at(memory::Region::Heap);
|
||||
heap = state.process->memoryRegionMap.at(memory::Region::Heap);
|
||||
heap->Resize(size, true);
|
||||
} catch (const exception &) {
|
||||
state.logger->Warn("svcSetHeapSize: Falling back to recreating memory");
|
||||
state.thisProcess->UnmapPrivateRegion(memory::Region::Heap);
|
||||
heap = state.thisProcess->MapPrivateRegion(constant::HeapAddr, size, {true, true, false}, memory::Type::Heap, memory::Region::Heap).item;
|
||||
state.process->UnmapPrivateRegion(memory::Region::Heap);
|
||||
heap = state.process->MapPrivateRegion(constant::HeapAddr, size, {true, true, false}, memory::Type::Heap, memory::Region::Heap).item;
|
||||
}
|
||||
state.nce->SetRegister(Wreg::W0, constant::status::Success);
|
||||
state.nce->SetRegister(Xreg::X1, heap->address);
|
||||
@ -47,7 +47,7 @@ namespace skyline::kernel::svc {
|
||||
}
|
||||
memory::MemoryAttribute attribute = *reinterpret_cast<memory::MemoryAttribute*>(&maskedValue);
|
||||
bool found = false;
|
||||
for (const auto&[address, region] : state.thisProcess->memoryMap) {
|
||||
for (const auto&[address, region] : state.process->memoryMap) {
|
||||
if (addr >= address && addr < (address + region->size)) {
|
||||
bool subFound = false;
|
||||
for (auto &subregion : region->regionInfoVec) {
|
||||
@ -72,54 +72,53 @@ namespace skyline::kernel::svc {
|
||||
}
|
||||
|
||||
void QueryMemory(DeviceState &state) {
|
||||
memory::MemoryInfo memInf;
|
||||
memory::MemoryInfo memInfo{};
|
||||
u64 addr = state.nce->GetRegister(Xreg::X2);
|
||||
bool found = false;
|
||||
for (const auto&[address, region] : state.thisProcess->memoryMap) {
|
||||
for (const auto&[address, region] : state.process->memoryMap) {
|
||||
if (addr >= address && addr < (address + region->size)) {
|
||||
memInf = region->GetInfo(addr);
|
||||
memInfo = region->GetInfo(addr);
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!found) {
|
||||
for (const auto &object : state.thisProcess->handleTable) {
|
||||
for (const auto &object : state.process->handleTable) {
|
||||
if (object.second->objectType == type::KType::KSharedMemory) {
|
||||
const auto &mem = state.thisProcess->GetHandle<type::KSharedMemory>(object.first);
|
||||
if (mem->procInfMap.count(state.thisProcess->mainThread)) {
|
||||
const auto &map = mem->procInfMap.at(state.thisProcess->mainThread);
|
||||
if (addr >= map.address && addr < (map.address + map.size)) {
|
||||
memInf = mem->GetInfo(state.thisProcess->mainThread);
|
||||
const auto &mem = state.process->GetHandle<type::KSharedMemory>(object.first);
|
||||
if (mem->guest.valid()) {
|
||||
if (addr >= mem->guest.address && addr < (mem->guest.address + mem->guest.size)) {
|
||||
memInfo = mem->GetInfo();
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else if (object.second->objectType == type::KType::KTransferMemory) {
|
||||
const auto &mem = state.thisProcess->GetHandle<type::KTransferMemory>(object.first);
|
||||
const auto &mem = state.process->GetHandle<type::KTransferMemory>(object.first);
|
||||
if (addr >= mem->cAddress && addr < (mem->cAddress + mem->cSize)) {
|
||||
memInf = mem->GetInfo();
|
||||
memInfo = mem->GetInfo();
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!found) {
|
||||
memInf = {
|
||||
.baseAddress = constant::BaseEnd,
|
||||
.size = static_cast<u64>(-constant::BaseEnd + 1),
|
||||
memInfo = {
|
||||
.baseAddress = constant::BaseAddr,
|
||||
.size = static_cast<u64>(constant::BaseEnd),
|
||||
.type = static_cast<u64>(memory::Type::Unmapped)
|
||||
};
|
||||
state.logger->Debug("svcQueryMemory: Cannot find block of address: 0x{:X}", addr);
|
||||
}
|
||||
}
|
||||
state.logger->Debug("svcQueryMemory: Address: 0x{:X}, Size: 0x{:X}, Type: {}, Is Uncached: {}, Permissions: {}{}{}", memInf.baseAddress, memInf.size, memInf.type, static_cast<bool>(memInf.memoryAttribute.isUncached), memInf.perms.r ? "R" : "-", memInf.perms.w ? "W" : "-", memInf.perms.x ? "X" : "-");
|
||||
state.thisProcess->WriteMemory<memory::MemoryInfo>(memInf, state.nce->GetRegister(Xreg::X0));
|
||||
state.logger->Debug("svcQueryMemory: Address: 0x{:X}, Size: 0x{:X}, Type: {}, Is Uncached: {}, Permissions: {}{}{}", memInfo.baseAddress, memInfo.size, memInfo.type, static_cast<bool>(memInfo.memoryAttribute.isUncached), memInfo.r ? "R" : "-", memInfo.w ? "W" : "-", memInfo.x ? "X" : "-");
|
||||
state.process->WriteMemory<memory::MemoryInfo>(memInfo, state.nce->GetRegister(Xreg::X0));
|
||||
state.nce->SetRegister(Wreg::W0, constant::status::Success);
|
||||
}
|
||||
|
||||
void ExitProcess(DeviceState &state) {
|
||||
state.logger->Debug("svcExitProcess: Exiting current process: {}", state.thisProcess->mainThread);
|
||||
state.os->KillThread(state.thisProcess->mainThread);
|
||||
state.logger->Debug("svcExitProcess: Exiting current process: {}", state.process->pid);
|
||||
state.os->KillThread(state.process->pid);
|
||||
}
|
||||
|
||||
void CreateThread(DeviceState &state) {
|
||||
@ -132,7 +131,7 @@ namespace skyline::kernel::svc {
|
||||
state.logger->Warn("svcCreateThread: 'priority' invalid: {}", priority);
|
||||
return;
|
||||
}
|
||||
auto thread = state.thisProcess->CreateThread(entryAddr, entryArg, stackTop, priority);
|
||||
auto thread = state.process->CreateThread(entryAddr, entryArg, stackTop, priority);
|
||||
state.logger->Debug("svcCreateThread: Created thread with handle 0x{:X} (Entry Point: 0x{:X}, Argument: 0x{:X}, Stack Pointer: 0x{:X}, Priority: {}, PID: {})", thread->handle, entryAddr, entryArg, stackTop, priority, thread->pid);
|
||||
state.nce->SetRegister(Wreg::W1, thread->handle);
|
||||
state.nce->SetRegister(Wreg::W0, constant::status::Success);
|
||||
@ -141,7 +140,7 @@ namespace skyline::kernel::svc {
|
||||
void StartThread(DeviceState &state) {
|
||||
auto handle = state.nce->GetRegister(Wreg::W0);
|
||||
try {
|
||||
auto thread = state.thisProcess->GetHandle<type::KThread>(handle);
|
||||
auto thread = state.process->GetHandle<type::KThread>(handle);
|
||||
state.logger->Debug("svcStartThread: Starting thread: 0x{:X}, PID: {}", handle, thread->pid);
|
||||
thread->Start();
|
||||
} catch (const std::exception&) {
|
||||
@ -151,8 +150,8 @@ namespace skyline::kernel::svc {
|
||||
}
|
||||
|
||||
void ExitThread(DeviceState &state) {
|
||||
state.logger->Debug("svcExitProcess: Exiting current thread: {}", state.thisThread->pid);
|
||||
state.os->KillThread(state.thisThread->pid);
|
||||
state.logger->Debug("svcExitProcess: Exiting current thread: {}", state.thread->pid);
|
||||
state.os->KillThread(state.thread->pid);
|
||||
}
|
||||
|
||||
void SleepThread(DeviceState &state) {
|
||||
@ -162,19 +161,19 @@ namespace skyline::kernel::svc {
|
||||
case 1:
|
||||
case 2:
|
||||
state.logger->Debug("svcSleepThread: Yielding thread: {}", in);
|
||||
state.thisThread->status = type::KThread::Status::Runnable; // Will cause the application to awaken on the next iteration of the main loop
|
||||
state.thread->status = type::KThread::Status::Runnable; // Will cause the application to awaken on the next iteration of the main loop
|
||||
break;
|
||||
default:
|
||||
state.logger->Debug("svcSleepThread: Thread sleeping for {} ns", in);
|
||||
state.thisThread->timeout = GetCurrTimeNs() + in;
|
||||
state.thisThread->status = type::KThread::Status::Sleeping;
|
||||
state.thread->timeout = GetCurrTimeNs() + in;
|
||||
state.thread->status = type::KThread::Status::Sleeping;
|
||||
}
|
||||
}
|
||||
|
||||
void GetThreadPriority(DeviceState &state) {
|
||||
auto handle = state.nce->GetRegister(Wreg::W0);
|
||||
try {
|
||||
auto priority = state.thisProcess->GetHandle<type::KThread>(handle)->priority;
|
||||
auto priority = state.process->GetHandle<type::KThread>(handle)->priority;
|
||||
state.nce->SetRegister(Wreg::W1, priority);
|
||||
state.nce->SetRegister(Wreg::W0, constant::status::Success);
|
||||
state.logger->Debug("svcGetThreadPriority: Writing thread priority {}", priority);
|
||||
@ -188,7 +187,7 @@ namespace skyline::kernel::svc {
|
||||
auto handle = state.nce->GetRegister(Wreg::W0);
|
||||
auto priority = state.nce->GetRegister(Wreg::W1);
|
||||
try {
|
||||
state.thisProcess->GetHandle<type::KThread>(handle)->UpdatePriority(static_cast<u8>(priority));
|
||||
state.process->GetHandle<type::KThread>(handle)->UpdatePriority(static_cast<u8>(priority));
|
||||
state.nce->SetRegister(Wreg::W0, constant::status::Success);
|
||||
state.logger->Debug("svcSetThreadPriority: Setting thread priority to {}", priority);
|
||||
} catch (const std::exception&) {
|
||||
@ -199,7 +198,7 @@ namespace skyline::kernel::svc {
|
||||
|
||||
void MapSharedMemory(DeviceState &state) {
|
||||
try {
|
||||
auto object = state.thisProcess->GetHandle<type::KSharedMemory>(state.nce->GetRegister(Wreg::W0));
|
||||
auto object = state.process->GetHandle<type::KSharedMemory>(state.nce->GetRegister(Wreg::W0));
|
||||
u64 addr = state.nce->GetRegister(Xreg::X1);
|
||||
if ((addr & (PAGE_SIZE - 1U))) {
|
||||
state.nce->SetRegister(Wreg::W0, constant::status::InvAddress);
|
||||
@ -220,7 +219,7 @@ namespace skyline::kernel::svc {
|
||||
return;
|
||||
}
|
||||
state.logger->Debug("svcMapSharedMemory: Mapping shared memory at 0x{:X} for {} bytes ({}{}{})", addr, size, permission.r ? "R" : "-", permission.w ? "W" : "-", permission.x ? "X" : "-");
|
||||
object->Map(addr, size, permission, state.thisProcess->mainThread);
|
||||
object->Map(addr, size, permission);
|
||||
state.nce->SetRegister(Wreg::W0, constant::status::Success);
|
||||
} catch (const std::exception &) {
|
||||
state.logger->Warn("svcMapSharedMemory: 'handle' invalid: 0x{:X}", state.nce->GetRegister(Wreg::W0));
|
||||
@ -249,7 +248,7 @@ namespace skyline::kernel::svc {
|
||||
return;
|
||||
}
|
||||
state.logger->Debug("svcCreateTransferMemory: Creating transfer memory at 0x{:X} for {} bytes ({}{}{})", addr, size, permission.r ? "R" : "-", permission.w ? "W" : "-", permission.x ? "X" : "-");
|
||||
auto shmem = state.thisProcess->NewHandle<type::KTransferMemory>(state.thisProcess->mainThread, addr, size, permission);
|
||||
auto shmem = state.process->NewHandle<type::KTransferMemory>(state.process->pid, addr, size, permission);
|
||||
state.nce->SetRegister(Wreg::W0, constant::status::Success);
|
||||
state.nce->SetRegister(Wreg::W1, shmem.handle);
|
||||
}
|
||||
@ -257,7 +256,7 @@ namespace skyline::kernel::svc {
|
||||
void CloseHandle(DeviceState &state) {
|
||||
auto handle = static_cast<handle_t>(state.nce->GetRegister(Wreg::W0));
|
||||
try {
|
||||
state.thisProcess->handleTable.erase(handle);
|
||||
state.process->handleTable.erase(handle);
|
||||
state.logger->Debug("svcCloseHandle: Closing handle: 0x{:X}", handle);
|
||||
state.nce->SetRegister(Wreg::W0, constant::status::Success);
|
||||
} catch(const std::exception&) {
|
||||
@ -269,7 +268,7 @@ namespace skyline::kernel::svc {
|
||||
void ResetSignal(DeviceState &state) {
|
||||
auto handle = state.nce->GetRegister(Wreg::W0);
|
||||
try {
|
||||
auto &object = state.thisProcess->handleTable.at(handle);
|
||||
auto &object = state.process->handleTable.at(handle);
|
||||
switch (object->objectType) {
|
||||
case (type::KType::KEvent):
|
||||
std::static_pointer_cast<type::KEvent>(object)->ResetSignal();
|
||||
@ -299,12 +298,12 @@ namespace skyline::kernel::svc {
|
||||
return;
|
||||
}
|
||||
std::vector<handle_t> waitHandles(numHandles);
|
||||
state.thisProcess->ReadMemory(waitHandles.data(), state.nce->GetRegister(Xreg::X1), numHandles * sizeof(handle_t));
|
||||
state.process->ReadMemory(waitHandles.data(), state.nce->GetRegister(Xreg::X1), numHandles * sizeof(handle_t));
|
||||
std::string handleStr;
|
||||
uint index{};
|
||||
for (const auto &handle : waitHandles) {
|
||||
handleStr += fmt::format("* 0x{:X}\n", handle);
|
||||
auto object = state.thisProcess->handleTable.at(handle);
|
||||
auto object = state.process->handleTable.at(handle);
|
||||
switch (object->objectType) {
|
||||
case type::KType::KProcess:
|
||||
case type::KType::KThread:
|
||||
@ -313,7 +312,7 @@ namespace skyline::kernel::svc {
|
||||
break;
|
||||
default: {
|
||||
state.nce->SetRegister(Wreg::W0, constant::status::InvHandle);
|
||||
state.thisThread->ClearWaitObjects();
|
||||
state.thread->ClearWaitObjects();
|
||||
return;
|
||||
}
|
||||
}
|
||||
@ -322,19 +321,19 @@ namespace skyline::kernel::svc {
|
||||
state.logger->Debug("svcWaitSynchronization: Signalled handle: 0x{:X}", handle);
|
||||
state.nce->SetRegister(Wreg::W0, constant::status::Success);
|
||||
state.nce->SetRegister(Wreg::W1, index);
|
||||
state.thisThread->ClearWaitObjects();
|
||||
state.thread->ClearWaitObjects();
|
||||
return;
|
||||
}
|
||||
state.thisThread->waitObjects.push_back(syncObject);
|
||||
syncObject->waitThreads.emplace_back(state.thisThread->pid, index);
|
||||
state.thread->waitObjects.push_back(syncObject);
|
||||
syncObject->waitThreads.emplace_back(state.thread->pid, index);
|
||||
}
|
||||
auto timeout = state.nce->GetRegister(Xreg::X3);
|
||||
state.logger->Debug("svcWaitSynchronization: Waiting on handles:\n{}Timeout: 0x{:X} ns", handleStr, timeout);
|
||||
if (state.nce->GetRegister(Xreg::X3) != std::numeric_limits<u64>::max())
|
||||
state.thisThread->timeout = GetCurrTimeNs() + timeout;
|
||||
state.thread->timeout = GetCurrTimeNs() + timeout;
|
||||
else
|
||||
state.thisThread->timeout = 0;
|
||||
state.thisThread->status = type::KThread::Status::WaitSync;
|
||||
state.thread->timeout = 0;
|
||||
state.thread->status = type::KThread::Status::WaitSync;
|
||||
}
|
||||
|
||||
void ArbitrateLock(DeviceState &state) {
|
||||
@ -345,10 +344,10 @@ namespace skyline::kernel::svc {
|
||||
return;
|
||||
}
|
||||
auto handle = state.nce->GetRegister(Wreg::W2);
|
||||
if (handle != state.thisThread->handle)
|
||||
if (handle != state.thread->handle)
|
||||
throw exception("svcArbitrateLock: Called from another thread");
|
||||
state.logger->Debug("svcArbitrateLock: Locking mutex at 0x{:X} for thread 0x{:X}", addr, handle);
|
||||
state.thisProcess->MutexLock(addr);
|
||||
state.process->MutexLock(addr);
|
||||
state.nce->SetRegister(Wreg::W0, constant::status::Success);
|
||||
}
|
||||
|
||||
@ -360,7 +359,7 @@ namespace skyline::kernel::svc {
|
||||
return;
|
||||
}
|
||||
state.logger->Debug("svcArbitrateUnlock: Unlocking mutex at 0x{:X}", addr);
|
||||
state.thisProcess->MutexUnlock(addr);
|
||||
state.process->MutexUnlock(addr);
|
||||
state.nce->SetRegister(Wreg::W0, constant::status::Success);
|
||||
}
|
||||
|
||||
@ -372,24 +371,24 @@ namespace skyline::kernel::svc {
|
||||
return;
|
||||
}
|
||||
auto handle = state.nce->GetRegister(Wreg::W2);
|
||||
if (handle != state.thisThread->handle)
|
||||
if (handle != state.thread->handle)
|
||||
throw exception("svcWaitProcessWideKeyAtomic: Called from another thread");
|
||||
state.thisProcess->MutexUnlock(mtxAddr);
|
||||
state.process->MutexUnlock(mtxAddr);
|
||||
auto condAddr = state.nce->GetRegister(Xreg::X1);
|
||||
auto &cvarVec = state.thisProcess->condVarMap[condAddr];
|
||||
auto &cvarVec = state.process->condVarMap[condAddr];
|
||||
for (auto thread = cvarVec.begin();; thread++) {
|
||||
if ((*thread)->priority < state.thisThread->priority) {
|
||||
cvarVec.insert(thread, state.thisThread);
|
||||
if ((*thread)->priority < state.thread->priority) {
|
||||
cvarVec.insert(thread, state.thread);
|
||||
break;
|
||||
} else if (thread + 1 == cvarVec.end()) {
|
||||
cvarVec.push_back(state.thisThread);
|
||||
cvarVec.push_back(state.thread);
|
||||
break;
|
||||
}
|
||||
}
|
||||
auto timeout = state.nce->GetRegister(Xreg::X3);
|
||||
state.logger->Debug("svcWaitProcessWideKeyAtomic: Mutex: 0x{:X}, Conditional-Variable: 0x:{:X}, Timeout: {} ns", mtxAddr, condAddr, timeout);
|
||||
state.thisThread->status = type::KThread::Status::WaitCondVar;
|
||||
state.thisThread->timeout = GetCurrTimeNs() + timeout;
|
||||
state.thread->status = type::KThread::Status::WaitCondVar;
|
||||
state.thread->timeout = GetCurrTimeNs() + timeout;
|
||||
state.nce->SetRegister(Wreg::W0, constant::status::Success);
|
||||
}
|
||||
|
||||
@ -397,17 +396,17 @@ namespace skyline::kernel::svc {
|
||||
auto address = state.nce->GetRegister(Xreg::X0);
|
||||
auto count = state.nce->GetRegister(Wreg::W1);
|
||||
state.nce->SetRegister(Wreg::W0, constant::status::Success);
|
||||
if (!state.thisProcess->condVarMap.count(address)) {
|
||||
if (!state.process->condVarMap.count(address)) {
|
||||
state.logger->Debug("svcSignalProcessWideKey: No Conditional-Variable at 0x{:X}", address);
|
||||
return;
|
||||
}
|
||||
auto &cvarVec = state.thisProcess->condVarMap.at(address);
|
||||
auto &cvarVec = state.process->condVarMap.at(address);
|
||||
count = std::min(count, static_cast<u32>(cvarVec.size()));
|
||||
for (uint index = 0; index < count; index++)
|
||||
cvarVec[index]->status = type::KThread::Status::Runnable;
|
||||
cvarVec.erase(cvarVec.begin(), cvarVec.begin() + count);
|
||||
if (cvarVec.empty())
|
||||
state.thisProcess->condVarMap.erase(address);
|
||||
state.process->condVarMap.erase(address);
|
||||
state.logger->Debug("svcSignalProcessWideKey: Signalling Conditional-Variable at 0x{:X} for {}", address, count);
|
||||
}
|
||||
|
||||
@ -426,7 +425,7 @@ namespace skyline::kernel::svc {
|
||||
|
||||
void ConnectToNamedPort(DeviceState &state) {
|
||||
char port[constant::PortSize + 1]{0};
|
||||
state.os->thisProcess->ReadMemory(port, state.nce->GetRegister(Xreg::X1), constant::PortSize);
|
||||
state.process->ReadMemory(port, state.nce->GetRegister(Xreg::X1), constant::PortSize);
|
||||
handle_t handle{};
|
||||
if (std::strcmp(port, "sm:") == 0)
|
||||
handle = state.os->serviceManager.NewSession(service::Service::sm);
|
||||
@ -449,9 +448,9 @@ namespace skyline::kernel::svc {
|
||||
pid_t pid{};
|
||||
auto handle = state.nce->GetRegister(Wreg::W1);
|
||||
if (handle != constant::ThreadSelf) {
|
||||
pid = state.thisProcess->GetHandle<type::KThread>(handle)->pid;
|
||||
pid = state.process->GetHandle<type::KThread>(handle)->pid;
|
||||
} else
|
||||
pid = state.thisThread->pid;
|
||||
pid = state.thread->pid;
|
||||
state.logger->Debug("svcGetThreadId: Handle: 0x{:X}, PID: {}", handle, pid);
|
||||
state.nce->SetRegister(Xreg::X1, static_cast<u64>(pid));
|
||||
state.nce->SetRegister(Wreg::W0, constant::status::Success);
|
||||
@ -459,7 +458,7 @@ namespace skyline::kernel::svc {
|
||||
|
||||
void OutputDebugString(DeviceState &state) {
|
||||
std::string debug(state.nce->GetRegister(Xreg::X1), '\0');
|
||||
state.os->thisProcess->ReadMemory(debug.data(), state.nce->GetRegister(Xreg::X0), state.nce->GetRegister(Xreg::X1));
|
||||
state.process->ReadMemory(debug.data(), state.nce->GetRegister(Xreg::X0), state.nce->GetRegister(Xreg::X1));
|
||||
if(debug.back() == '\n')
|
||||
debug.pop_back();
|
||||
state.logger->Info("Debug Output: {}", debug);
|
||||
@ -485,16 +484,16 @@ namespace skyline::kernel::svc {
|
||||
out = constant::MapSize;
|
||||
break;
|
||||
case constant::infoState::HeapRegionBaseAddr:
|
||||
out = state.os->thisProcess->memoryRegionMap.at(memory::Region::Heap)->address;
|
||||
out = state.process->memoryRegionMap.at(memory::Region::Heap)->address;
|
||||
break;
|
||||
case constant::infoState::HeapRegionSize:
|
||||
out = state.os->thisProcess->memoryRegionMap.at(memory::Region::Heap)->size;
|
||||
out = state.process->memoryRegionMap.at(memory::Region::Heap)->size;
|
||||
break;
|
||||
case constant::infoState::TotalMemoryAvailable:
|
||||
out = constant::TotalPhyMem;
|
||||
break;
|
||||
case constant::infoState::TotalMemoryUsage:
|
||||
out = state.os->thisProcess->memoryRegionMap.at(memory::Region::Heap)->address + state.thisProcess->mainThreadStackSz + state.thisProcess->GetProgramSize();
|
||||
out = state.process->memoryRegionMap.at(memory::Region::Heap)->address + state.process->mainThreadStackSz + state.process->GetProgramSize();
|
||||
break;
|
||||
case constant::infoState::AddressSpaceBaseAddr:
|
||||
out = constant::BaseAddr;
|
||||
@ -503,25 +502,25 @@ namespace skyline::kernel::svc {
|
||||
out = constant::BaseSize;
|
||||
break;
|
||||
case constant::infoState::StackRegionBaseAddr:
|
||||
out = state.thisThread->stackTop;
|
||||
out = state.thread->stackTop;
|
||||
break;
|
||||
case constant::infoState::StackRegionSize:
|
||||
out = state.thisProcess->mainThreadStackSz;
|
||||
out = state.process->mainThreadStackSz;
|
||||
break;
|
||||
case constant::infoState::PersonalMmHeapSize:
|
||||
out = constant::TotalPhyMem;
|
||||
break;
|
||||
case constant::infoState::PersonalMmHeapUsage:
|
||||
out = state.os->thisProcess->memoryRegionMap.at(memory::Region::Heap)->address + state.thisProcess->mainThreadStackSz;
|
||||
out = state.process->memoryRegionMap.at(memory::Region::Heap)->address + state.process->mainThreadStackSz;
|
||||
break;
|
||||
case constant::infoState::TotalMemoryAvailableWithoutMmHeap:
|
||||
out = constant::TotalPhyMem; // TODO: NPDM specifies SystemResourceSize, subtract that from this
|
||||
break;
|
||||
case constant::infoState::TotalMemoryUsedWithoutMmHeap:
|
||||
out = state.os->thisProcess->memoryRegionMap.at(memory::Region::Heap)->address + state.thisProcess->mainThreadStackSz; // TODO: Same as above
|
||||
out = state.process->memoryRegionMap.at(memory::Region::Heap)->address + state.process->mainThreadStackSz; // TODO: Same as above
|
||||
break;
|
||||
case constant::infoState::UserExceptionContextAddr:
|
||||
out = state.thisProcess->tlsPages[0]->Get(0);
|
||||
out = state.process->tlsPages[0]->Get(0);
|
||||
break;
|
||||
default:
|
||||
state.logger->Warn("svcGetInfo: Unimplemented case ID0: {}, ID1: {}", id0, id1);
|
||||
|
@ -1,4 +1,5 @@
|
||||
#include "KPrivateMemory.h"
|
||||
#include "KProcess.h"
|
||||
#include <nce.h>
|
||||
|
||||
namespace skyline::kernel::type {
|
||||
@ -11,13 +12,13 @@ namespace skyline::kernel::type {
|
||||
return dstAddress;
|
||||
}
|
||||
|
||||
KPrivateMemory::KPrivateMemory(const DeviceState &state, pid_t pid, u64 dstAddress, u64 srcAddress, size_t size, memory::Permission permission, const memory::Type type) : state(state), owner(pid), address(dstAddress), size(size), permission(permission), type(type), KObject(state, KType::KPrivateMemory) {
|
||||
KPrivateMemory::KPrivateMemory(const DeviceState &state, u64 dstAddress, u64 srcAddress, size_t size, memory::Permission permission, const memory::Type type, const pid_t pid) : state(state), address(dstAddress), size(size), permission(permission), type(type), KObject(state, KType::KPrivateMemory) {
|
||||
user_pt_regs fregs = {0};
|
||||
fregs.regs[0] = dstAddress;
|
||||
fregs.regs[1] = srcAddress;
|
||||
fregs.regs[2] = size;
|
||||
fregs.regs[3] = static_cast<u64>(permission.Get());
|
||||
state.nce->ExecuteFunction(reinterpret_cast<void *>(MapPrivateFunc), fregs, pid);
|
||||
state.nce->ExecuteFunction(reinterpret_cast<void *>(MapPrivateFunc), fregs, pid ? pid : state.process->pid);
|
||||
if (reinterpret_cast<void *>(fregs.regs[0]) == MAP_FAILED)
|
||||
throw exception("An error occurred while mapping private region in child process");
|
||||
if (!this->address)
|
||||
@ -34,7 +35,7 @@ namespace skyline::kernel::type {
|
||||
fregs.regs[1] = size;
|
||||
fregs.regs[2] = newSize;
|
||||
fregs.regs[3] = canMove ? MREMAP_MAYMOVE : 0;
|
||||
state.nce->ExecuteFunction(reinterpret_cast<void *>(RemapPrivateFunc), fregs, owner);
|
||||
state.nce->ExecuteFunction(reinterpret_cast<void *>(RemapPrivateFunc), fregs, state.process->pid);
|
||||
if (reinterpret_cast<void *>(fregs.regs[0]) == MAP_FAILED)
|
||||
throw exception("An error occurred while remapping private region in child process");
|
||||
address = fregs.regs[0];
|
||||
@ -51,7 +52,7 @@ namespace skyline::kernel::type {
|
||||
fregs.regs[0] = address;
|
||||
fregs.regs[1] = size;
|
||||
fregs.regs[2] = static_cast<u64>(permission.Get());
|
||||
state.nce->ExecuteFunction(reinterpret_cast<void *>(UpdatePermissionPrivateFunc), fregs, owner);
|
||||
state.nce->ExecuteFunction(reinterpret_cast<void *>(UpdatePermissionPrivateFunc), fregs, state.process->pid);
|
||||
if (static_cast<int>(fregs.regs[0]) == -1)
|
||||
throw exception("An error occurred while updating private region's permissions in child process");
|
||||
this->permission = permission;
|
||||
@ -61,14 +62,15 @@ namespace skyline::kernel::type {
|
||||
memory::MemoryInfo info{};
|
||||
info.baseAddress = address;
|
||||
info.size = size;
|
||||
info.type = static_cast<u64>(type);
|
||||
for (const auto ®ion : regionInfoVec) {
|
||||
info.type = static_cast<u32>(type);
|
||||
for (const auto ®ion : regionInfoVec)
|
||||
if ((address >= region.address) && (address < (region.address + region.size)))
|
||||
info.memoryAttribute.isUncached = region.isUncached;
|
||||
}
|
||||
info.memoryAttribute.isIpcLocked = (info.ipcRefCount > 0);
|
||||
info.memoryAttribute.isDeviceShared = (info.deviceRefCount > 0);
|
||||
info.perms = permission;
|
||||
info.r = permission.r;
|
||||
info.w = permission.w;
|
||||
info.x = permission.x;
|
||||
info.ipcRefCount = ipcRefCount;
|
||||
info.deviceRefCount = deviceRefCount;
|
||||
return info;
|
||||
@ -83,7 +85,7 @@ namespace skyline::kernel::type {
|
||||
user_pt_regs fregs = {0};
|
||||
fregs.regs[0] = address;
|
||||
fregs.regs[1] = size;
|
||||
state.nce->ExecuteFunction(reinterpret_cast<void *>(UnmapPrivateFunc), fregs, owner);
|
||||
state.nce->ExecuteFunction(reinterpret_cast<void *>(UnmapPrivateFunc), fregs, state.process->pid);
|
||||
} catch (const std::exception &) {
|
||||
}
|
||||
}
|
||||
|
@ -12,7 +12,6 @@ namespace skyline::kernel::type {
|
||||
const DeviceState &state; //!< The state of the device
|
||||
|
||||
public:
|
||||
pid_t owner; //!< The PID of the process owning this memory
|
||||
u64 address; //!< The address of the allocated memory
|
||||
size_t size; //!< The size of the allocated memory
|
||||
u16 ipcRefCount{}; //!< The amount of reference to this memory for IPC
|
||||
@ -23,14 +22,14 @@ namespace skyline::kernel::type {
|
||||
|
||||
/**
|
||||
* @param state The state of the device
|
||||
* @param pid The PID of the main
|
||||
* @param dstAddress The address to map to (If NULL then an arbitrary address is picked)
|
||||
* @param srcAddress The address to map from (If NULL then no copy is performed)
|
||||
* @param size The size of the allocation
|
||||
* @param permission The permissions for the allocated memory
|
||||
* @param type The type of the memory
|
||||
* @param pid The PID of the me
|
||||
*/
|
||||
KPrivateMemory(const DeviceState &state, pid_t pid, u64 dstAddress, u64 srcAddress, size_t size, memory::Permission permission, const memory::Type type);
|
||||
KPrivateMemory(const DeviceState &state, u64 dstAddress, u64 srcAddress, size_t size, memory::Permission permission, const memory::Type type, const pid_t pid=0);
|
||||
|
||||
/**
|
||||
* @brief Remap a chunk of memory as to change the size occupied by it
|
||||
|
@ -29,7 +29,7 @@ namespace skyline::kernel::type {
|
||||
if (!tlsPage->Full())
|
||||
return tlsPage->ReserveSlot();
|
||||
}
|
||||
auto tlsMem = NewHandle<KPrivateMemory>(mainThread, 0, 0, PAGE_SIZE, memory::Permission(true, true, false), memory::Type::ThreadLocal).item;
|
||||
auto tlsMem = NewHandle<KPrivateMemory>(0, 0, PAGE_SIZE, memory::Permission(true, true, false), memory::Type::ThreadLocal, pid).item;
|
||||
memoryMap[tlsMem->address] = tlsMem;
|
||||
tlsPages.push_back(std::make_shared<TlsPage>(tlsMem->address));
|
||||
auto &tlsPage = tlsPages.back();
|
||||
@ -38,7 +38,7 @@ namespace skyline::kernel::type {
|
||||
return tlsPage->ReserveSlot();
|
||||
}
|
||||
|
||||
KProcess::KProcess(const DeviceState &state, pid_t pid, u64 entryPoint, u64 stackBase, u64 stackSize) : mainThread(pid), mainThreadStackSz(stackSize), KSyncObject(state, KType::KProcess) {
|
||||
KProcess::KProcess(const DeviceState &state, pid_t pid, u64 entryPoint, u64 stackBase, u64 stackSize) : pid(pid), mainThreadStackSz(stackSize), KSyncObject(state, KType::KProcess) {
|
||||
state.nce->WaitRdy(pid);
|
||||
threadMap[pid] = NewHandle<KThread>(pid, entryPoint, 0x0, stackBase + stackSize, GetTlsSlot(), constant::DefaultPriority, this).item;
|
||||
MapPrivateRegion(constant::HeapAddr, constant::DefHeapSize, {true, true, false}, memory::Type::Heap, memory::Region::Heap);
|
||||
@ -68,13 +68,12 @@ namespace skyline::kernel::type {
|
||||
user_pt_regs fregs = {0};
|
||||
fregs.regs[0] = entryPoint;
|
||||
fregs.regs[1] = stackTop;
|
||||
state.nce->ExecuteFunction((void *) CreateThreadFunc, fregs, mainThread);
|
||||
state.nce->ExecuteFunction((void *) CreateThreadFunc, fregs, pid);
|
||||
auto pid = static_cast<pid_t>(fregs.regs[0]);
|
||||
if (pid == -1)
|
||||
throw exception("Cannot create thread: Address: 0x{:X}, Stack Top: 0x{:X}", entryPoint, stackTop);
|
||||
auto process = NewHandle<KThread>(pid, entryPoint, entryArg, stackTop, GetTlsSlot(), priority, this).item;
|
||||
threadMap[pid] = process;
|
||||
state.os->processMap[pid] = state.os->processMap[mainThread];
|
||||
return process;
|
||||
}
|
||||
|
||||
@ -91,7 +90,7 @@ namespace skyline::kernel::type {
|
||||
}
|
||||
|
||||
KProcess::HandleOut<KPrivateMemory> KProcess::MapPrivateRegion(u64 address, size_t size, const memory::Permission perms, const memory::Type type, const memory::Region region) {
|
||||
auto mem = NewHandle<KPrivateMemory>(mainThread, address, 0, size, perms, type);
|
||||
auto mem = NewHandle<KPrivateMemory>(address, 0, size, perms, type, pid);
|
||||
memoryMap[mem.item->address] = mem.item;
|
||||
memoryRegionMap[region] = mem.item;
|
||||
return mem;
|
||||
@ -113,29 +112,29 @@ namespace skyline::kernel::type {
|
||||
}
|
||||
|
||||
void KProcess::MutexLock(u64 address) {
|
||||
auto mtxVec = state.thisProcess->mutexMap[address];
|
||||
u32 mtxVal = state.thisProcess->ReadMemory<u32>(address);
|
||||
auto mtxVec = state.process->mutexMap[address];
|
||||
u32 mtxVal = state.process->ReadMemory<u32>(address);
|
||||
if (mtxVec.empty()) {
|
||||
mtxVal = (mtxVal & ~constant::MtxOwnerMask) | state.thisThread->handle;
|
||||
state.thisProcess->WriteMemory(mtxVal, address);
|
||||
mtxVal = (mtxVal & ~constant::MtxOwnerMask) | state.thread->handle;
|
||||
state.process->WriteMemory(mtxVal, address);
|
||||
} else {
|
||||
for (auto thread = mtxVec.begin();; thread++) {
|
||||
if ((*thread)->priority < state.thisThread->priority) {
|
||||
mtxVec.insert(thread, state.thisThread);
|
||||
if ((*thread)->priority < state.thread->priority) {
|
||||
mtxVec.insert(thread, state.thread);
|
||||
break;
|
||||
} else if (thread + 1 == mtxVec.end()) {
|
||||
mtxVec.push_back(state.thisThread);
|
||||
mtxVec.push_back(state.thread);
|
||||
break;
|
||||
}
|
||||
}
|
||||
state.thisThread->status = KThread::Status::WaitMutex;
|
||||
state.thread->status = KThread::Status::WaitMutex;
|
||||
}
|
||||
}
|
||||
|
||||
void KProcess::MutexUnlock(u64 address) {
|
||||
auto mtxVec = state.thisProcess->mutexMap[address];
|
||||
u32 mtxVal = state.thisProcess->ReadMemory<u32>(address);
|
||||
if ((mtxVal & constant::MtxOwnerMask) != state.thisThread->pid)
|
||||
auto mtxVec = state.process->mutexMap[address];
|
||||
u32 mtxVal = state.process->ReadMemory<u32>(address);
|
||||
if ((mtxVal & constant::MtxOwnerMask) != state.thread->pid)
|
||||
throw exception("A non-owner thread tried to release a mutex");
|
||||
if (mtxVec.empty()) {
|
||||
mtxVal = 0;
|
||||
@ -147,7 +146,7 @@ namespace skyline::kernel::type {
|
||||
if (!mtxVec.empty())
|
||||
mtxVal |= (~constant::MtxOwnerMask);
|
||||
}
|
||||
state.thisProcess->WriteMemory(mtxVal, address);
|
||||
state.process->WriteMemory(mtxVal, address);
|
||||
}
|
||||
|
||||
void KProcess::ResetSignal() {
|
||||
|
@ -63,7 +63,7 @@ namespace skyline::kernel::type {
|
||||
Exiting //!< The process is exiting
|
||||
} status = Status::Created; //!< The state of the process
|
||||
handle_t handleIndex = constant::BaseHandleIndex; //!< This is used to keep track of what to map as an handle
|
||||
pid_t mainThread; //!< The PID of the main thread
|
||||
pid_t pid; //!< The PID of the main thread
|
||||
size_t mainThreadStackSz; //!< The size of the main thread's stack (All other threads map stack themselves so we don't know the size per-se)
|
||||
int memFd; //!< The file descriptor to the memory of the process
|
||||
std::unordered_map<u64, std::shared_ptr<KPrivateMemory>> memoryMap; //!< A mapping from every address to a shared pointer of it's corresponding KPrivateMemory, used to keep track of KPrivateMemory instances
|
||||
|
@ -1,4 +1,5 @@
|
||||
#include "KSharedMemory.h"
|
||||
#include "KProcess.h"
|
||||
#include <nce.h>
|
||||
#include <android/sharedmem.h>
|
||||
#include <unistd.h>
|
||||
@ -15,19 +16,19 @@ namespace skyline::kernel::type {
|
||||
address = MapSharedFunc(address, size, static_cast<u64>(permission.Get()), static_cast<u64>(fd));
|
||||
if (address == reinterpret_cast<u64>(MAP_FAILED)) // NOLINT(hicpp-signed-bitwise)
|
||||
throw exception("An occurred while mapping shared region: {}", strerror(errno));
|
||||
procInfMap[0] = {address, size, permission};
|
||||
kernel = {address, size, permission};
|
||||
}
|
||||
|
||||
u64 KSharedMemory::Map(u64 address, u64 size, memory::Permission permission, pid_t pid) {
|
||||
u64 KSharedMemory::Map(u64 address, u64 size, memory::Permission permission) {
|
||||
user_pt_regs fregs = {0};
|
||||
fregs.regs[0] = address;
|
||||
fregs.regs[1] = size;
|
||||
fregs.regs[2] = static_cast<u64>(permission.Get());
|
||||
fregs.regs[3] = static_cast<u64>(fd);
|
||||
state.nce->ExecuteFunction(reinterpret_cast<void *>(MapSharedFunc), fregs, pid);
|
||||
state.nce->ExecuteFunction(reinterpret_cast<void *>(MapSharedFunc), fregs, state.process->pid);
|
||||
if (reinterpret_cast<void *>(fregs.regs[0]) == MAP_FAILED)
|
||||
throw exception("An error occurred while mapping shared region in child process");
|
||||
procInfMap[pid] = {fregs.regs[0], size, permission};
|
||||
guest = {fregs.regs[0], size, permission};
|
||||
return fregs.regs[0];
|
||||
}
|
||||
|
||||
@ -36,16 +37,16 @@ namespace skyline::kernel::type {
|
||||
}
|
||||
|
||||
KSharedMemory::~KSharedMemory() {
|
||||
for (auto[process, procInf] : procInfMap) {
|
||||
try {
|
||||
if(process) {
|
||||
user_pt_regs fregs = {0};
|
||||
fregs.regs[0] = procInf.address;
|
||||
fregs.regs[1] = procInf.size;
|
||||
state.nce->ExecuteFunction(reinterpret_cast<void *>(UnmapSharedFunc), fregs, process);
|
||||
} else
|
||||
UnmapSharedFunc(procInf.address, procInf.size);
|
||||
} catch (const std::exception &) {}
|
||||
try {
|
||||
if (guest.valid()) {
|
||||
user_pt_regs fregs = {0};
|
||||
fregs.regs[0] = guest.address;
|
||||
fregs.regs[1] = guest.size;
|
||||
state.nce->ExecuteFunction(reinterpret_cast<void *>(UnmapSharedFunc), fregs, state.process->pid);
|
||||
}
|
||||
if (kernel.valid())
|
||||
UnmapSharedFunc(kernel.address, kernel.size);
|
||||
} catch (const std::exception &) {
|
||||
}
|
||||
close(fd);
|
||||
}
|
||||
@ -54,21 +55,21 @@ namespace skyline::kernel::type {
|
||||
return reinterpret_cast<u64>(mremap(reinterpret_cast<void *>(address), oldSize, size, 0));
|
||||
}
|
||||
|
||||
void KSharedMemory::Resize(size_t newSize) {
|
||||
for (auto&[process, procInf] : procInfMap) {
|
||||
if(process) {
|
||||
user_pt_regs fregs = {0};
|
||||
fregs.regs[0] = procInf.address;
|
||||
fregs.regs[1] = procInf.size;
|
||||
fregs.regs[2] = newSize;
|
||||
state.nce->ExecuteFunction(reinterpret_cast<void *>(RemapSharedFunc), fregs, process);
|
||||
if (reinterpret_cast<void *>(fregs.regs[0]) == MAP_FAILED)
|
||||
throw exception("An error occurred while remapping shared region in child process");
|
||||
} else {
|
||||
if (RemapSharedFunc(procInf.address, procInf.size, newSize) == reinterpret_cast<u64>(MAP_FAILED))
|
||||
throw exception("An occurred while remapping shared region: {}", strerror(errno));
|
||||
}
|
||||
procInf.size = newSize;
|
||||
void KSharedMemory::Resize(size_t size) {
|
||||
if (guest.valid()) {
|
||||
user_pt_regs fregs = {0};
|
||||
fregs.regs[0] = guest.address;
|
||||
fregs.regs[1] = guest.size;
|
||||
fregs.regs[2] = size;
|
||||
state.nce->ExecuteFunction(reinterpret_cast<void *>(RemapSharedFunc), fregs, state.process->pid);
|
||||
if (reinterpret_cast<void *>(fregs.regs[0]) == MAP_FAILED)
|
||||
throw exception("An error occurred while remapping shared region in child process");
|
||||
guest.size = size;
|
||||
}
|
||||
if (kernel.valid()) {
|
||||
if (RemapSharedFunc(kernel.address, kernel.size, size) == reinterpret_cast<u64>(MAP_FAILED))
|
||||
throw exception("An occurred while remapping shared region: {}", strerror(errno));
|
||||
kernel.size = size;
|
||||
}
|
||||
}
|
||||
|
||||
@ -76,33 +77,34 @@ namespace skyline::kernel::type {
|
||||
return static_cast<u64>(mprotect(reinterpret_cast<void *>(address), size, static_cast<int>(perms)));
|
||||
}
|
||||
|
||||
void KSharedMemory::UpdatePermission(pid_t pid, memory::Permission permission) {
|
||||
for (auto&[process, procInf] : procInfMap) {
|
||||
if(process) {
|
||||
user_pt_regs fregs = {0};
|
||||
fregs.regs[0] = procInf.address;
|
||||
fregs.regs[1] = procInf.size;
|
||||
fregs.regs[2] = static_cast<u64>(procInf.permission.Get());
|
||||
state.nce->ExecuteFunction(reinterpret_cast<void *>(UpdatePermissionSharedFunc), fregs, process);
|
||||
if (static_cast<int>(fregs.regs[0]) == -1)
|
||||
throw exception("An error occurred while updating shared region's permissions in child process");
|
||||
} else {
|
||||
if (UpdatePermissionSharedFunc(procInf.address, procInf.size, static_cast<u64>(permission.Get())) == reinterpret_cast<u64>(MAP_FAILED))
|
||||
throw exception("An occurred while remapping shared region: {}", strerror(errno));
|
||||
}
|
||||
procInf.permission = permission;
|
||||
void KSharedMemory::UpdatePermission(memory::Permission permission, bool host) {
|
||||
if (guest.valid() && !host) {
|
||||
user_pt_regs fregs = {0};
|
||||
fregs.regs[0] = guest.address;
|
||||
fregs.regs[1] = guest.size;
|
||||
fregs.regs[2] = static_cast<u64>(guest.permission.Get());
|
||||
state.nce->ExecuteFunction(reinterpret_cast<void *>(UpdatePermissionSharedFunc), fregs, state.process->pid);
|
||||
if (static_cast<int>(fregs.regs[0]) == -1)
|
||||
throw exception("An error occurred while updating shared region's permissions in child process");
|
||||
guest.permission = permission;
|
||||
}
|
||||
if (kernel.valid() && host) {
|
||||
if (UpdatePermissionSharedFunc(kernel.address, kernel.size, static_cast<u64>(permission.Get())) == reinterpret_cast<u64>(MAP_FAILED))
|
||||
throw exception("An occurred while remapping shared region: {}", strerror(errno));
|
||||
kernel.permission = permission;
|
||||
}
|
||||
}
|
||||
|
||||
memory::MemoryInfo KSharedMemory::GetInfo(pid_t pid) {
|
||||
memory::MemoryInfo KSharedMemory::GetInfo() {
|
||||
memory::MemoryInfo info{};
|
||||
const auto &procInf = procInfMap.at(pid);
|
||||
info.baseAddress = procInf.address;
|
||||
info.size = procInf.size;
|
||||
info.type = static_cast<u64>(type);
|
||||
info.baseAddress = guest.address;
|
||||
info.size = guest.size;
|
||||
info.type = static_cast<u32>(type);
|
||||
info.memoryAttribute.isIpcLocked = (info.ipcRefCount > 0);
|
||||
info.memoryAttribute.isDeviceShared = (info.deviceRefCount > 0);
|
||||
info.perms = procInf.permission;
|
||||
info.r = guest.permission.r;
|
||||
info.w = guest.permission.w;
|
||||
info.x = guest.permission.x;
|
||||
info.ipcRefCount = ipcRefCount;
|
||||
info.deviceRefCount = deviceRefCount;
|
||||
return info;
|
||||
|
@ -15,12 +15,18 @@ namespace skyline::kernel::type {
|
||||
/**
|
||||
* @brief This holds the address and size of a process's mapping
|
||||
*/
|
||||
struct ProcessInfo {
|
||||
struct MapInfo {
|
||||
u64 address;
|
||||
size_t size;
|
||||
memory::Permission permission;
|
||||
};
|
||||
std::unordered_map<pid_t, ProcessInfo> procInfMap; //!< Maps from a PID to where the memory was mapped to
|
||||
|
||||
/**
|
||||
* @brief Returns if the object is valid
|
||||
* @return If the MapInfo object is valid
|
||||
*/
|
||||
inline bool valid() { return address && size && permission.Get(); }
|
||||
} kernel, guest;
|
||||
|
||||
u16 ipcRefCount{}; //!< The amount of reference to this memory for IPC
|
||||
u16 deviceRefCount{}; //!< The amount of reference to this memory for IPC
|
||||
memory::Type type; //!< The type of this memory allocation
|
||||
@ -35,33 +41,32 @@ namespace skyline::kernel::type {
|
||||
KSharedMemory(const DeviceState &state, u64 address, size_t size, const memory::Permission permission, memory::Type type);
|
||||
|
||||
/**
|
||||
* @brief Maps the shared memory at an address
|
||||
* @brief Maps the shared memory at an address in the guest
|
||||
* @param address The address to map to (If NULL an arbitrary address is picked)
|
||||
* @param size The amount of shared memory to map
|
||||
* @param permission The permission of the kernel process
|
||||
* @param pid The PID of the process
|
||||
* @return The address of the allocation
|
||||
*/
|
||||
u64 Map(const u64 address, const u64 size, memory::Permission permission, pid_t pid);
|
||||
u64 Map(const u64 address, const u64 size, memory::Permission permission);
|
||||
|
||||
/**
|
||||
* @brief Resize a chunk of memory as to change the size occupied by it
|
||||
* @param newSize The new size of the memory
|
||||
* @param size The new size of the memory
|
||||
*/
|
||||
void Resize(size_t newSize);
|
||||
void Resize(size_t size);
|
||||
|
||||
/**
|
||||
* Updates the permissions of a chunk of mapped memory
|
||||
* @param pid The PID of the requesting process
|
||||
* @brief Updates the permissions of a chunk of mapped memory
|
||||
* @param permission The new permissions to be set for the memory
|
||||
* @param kernel Set the permissions for the kernel rather than the guest
|
||||
*/
|
||||
void UpdatePermission(pid_t pid, memory::Permission permission);
|
||||
void UpdatePermission(memory::Permission permission, bool host=0);
|
||||
|
||||
/**
|
||||
* @param pid The PID of the requesting process
|
||||
* @brief Creates a MemoryInfo struct from the current instance
|
||||
* @return A Memory::MemoryInfo struct based on attributes of the memory
|
||||
*/
|
||||
memory::MemoryInfo GetInfo(pid_t pid);
|
||||
memory::MemoryInfo GetInfo();
|
||||
|
||||
/**
|
||||
* @brief The destructor of shared memory, it deallocates the memory from all processes
|
||||
|
@ -9,7 +9,7 @@ namespace skyline::kernel::type {
|
||||
void KSyncObject::Signal() {
|
||||
for (const auto &info : waitThreads) {
|
||||
state.nce->SetRegister(Wreg::W1, info.index);
|
||||
state.os->processMap.at(info.process)->threadMap.at(info.process)->status = KThread::Status::Runnable;
|
||||
state.process->threadMap.at(info.process)->status = KThread::Status::Runnable;
|
||||
}
|
||||
waitThreads.clear();
|
||||
}
|
||||
|
@ -14,7 +14,7 @@ namespace skyline::kernel::type {
|
||||
|
||||
void KThread::Start() {
|
||||
if(status == Status::Created) {
|
||||
if (pid == parent->mainThread)
|
||||
if (pid == parent->pid)
|
||||
parent->status = KProcess::Status::Started;
|
||||
status = Status::Running;
|
||||
state.nce->StartProcess(entryPoint, entryArg, stackTop, handle, pid);
|
||||
|
@ -45,17 +45,12 @@ namespace skyline::kernel::type {
|
||||
throw exception("An error occurred while mapping transfer memory in kernel");
|
||||
}
|
||||
size_t copySz = std::min(size, cSize);
|
||||
if (process && owner) {
|
||||
std::vector<u8> tempBuf(copySz);
|
||||
state.os->processMap.at(process)->ReadMemory(tempBuf.data(), cAddress, copySz);
|
||||
state.os->processMap.at(owner)->WriteMemory(tempBuf.data(), address, copySz);
|
||||
} else if (process && !owner) {
|
||||
state.os->processMap.at(process)->WriteMemory(reinterpret_cast<void *>(cAddress), address, copySz);
|
||||
if (process && !owner) {
|
||||
state.process->WriteMemory(reinterpret_cast<void *>(cAddress), address, copySz);
|
||||
} else if (!process && owner) {
|
||||
state.os->processMap.at(owner)->ReadMemory(reinterpret_cast<void *>(address), cAddress, copySz);
|
||||
} else {
|
||||
state.process->ReadMemory(reinterpret_cast<void *>(address), cAddress, copySz);
|
||||
} else
|
||||
throw exception("Transferring from kernel to kernel is not supported");
|
||||
}
|
||||
if (owner) {
|
||||
user_pt_regs fregs = {0};
|
||||
fregs.regs[0] = address;
|
||||
@ -81,7 +76,9 @@ namespace skyline::kernel::type {
|
||||
info.type = static_cast<u64>(memory::Type::TransferMemory);
|
||||
info.memoryAttribute.isIpcLocked = (info.ipcRefCount > 0);
|
||||
info.memoryAttribute.isDeviceShared = (info.deviceRefCount > 0);
|
||||
info.perms = permission;
|
||||
info.r = permission.r;
|
||||
info.w = permission.w;
|
||||
info.x = permission.x;
|
||||
info.ipcRefCount = ipcRefCount;
|
||||
info.deviceRefCount = deviceRefCount;
|
||||
return info;
|
||||
|
@ -30,12 +30,12 @@ namespace skyline::memory {
|
||||
/**
|
||||
* @brief Equality operator between two Permission objects
|
||||
*/
|
||||
bool operator==(const Permission &rhs) const { return (this->r == rhs.r && this->w == rhs.w && this->x == rhs.x); };
|
||||
inline bool operator==(const Permission &rhs) const { return (this->r == rhs.r && this->w == rhs.w && this->x == rhs.x); };
|
||||
|
||||
/**
|
||||
* @brief Inequality operator between two Permission objects
|
||||
*/
|
||||
bool operator!=(const Permission &rhs) const { return !operator==(rhs); };
|
||||
inline bool operator!=(const Permission &rhs) const { return !operator==(rhs); };
|
||||
|
||||
/**
|
||||
* @return The value of the permission struct in mmap(2) format
|
||||
@ -51,18 +51,24 @@ namespace skyline::memory {
|
||||
return perm;
|
||||
};
|
||||
|
||||
bool r : 1, w : 1, x : 1;
|
||||
bool r;
|
||||
bool w;
|
||||
bool x;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief This holds certain attributes of a chunk of memory: https://switchbrew.org/wiki/SVC#MemoryAttribute
|
||||
*/
|
||||
struct MemoryAttribute {
|
||||
bool isBorrowed : 1;
|
||||
bool isIpcLocked : 1;
|
||||
bool isDeviceShared : 1;
|
||||
bool isUncached : 1;
|
||||
union MemoryAttribute {
|
||||
struct {
|
||||
bool isBorrowed : 1;
|
||||
bool isIpcLocked : 1;
|
||||
bool isDeviceShared : 1;
|
||||
bool isUncached : 1;
|
||||
};
|
||||
u32 value;
|
||||
};
|
||||
static_assert(sizeof(MemoryAttribute) == sizeof(u32));
|
||||
|
||||
/**
|
||||
* @brief This describes the properties of a region of the allocated memory
|
||||
@ -81,12 +87,17 @@ namespace skyline::memory {
|
||||
struct MemoryInfo {
|
||||
u64 baseAddress;
|
||||
u64 size;
|
||||
u64 type;
|
||||
u32 type;
|
||||
MemoryAttribute memoryAttribute;
|
||||
Permission perms;
|
||||
union {
|
||||
u32 _pad0_;
|
||||
struct {
|
||||
bool r : 1, w : 1, x : 1;
|
||||
};
|
||||
};
|
||||
u32 ipcRefCount;
|
||||
u32 deviceRefCount;
|
||||
u32 : 32;
|
||||
u32 : 32;
|
||||
};
|
||||
static_assert(sizeof(MemoryInfo) == 0x28);
|
||||
|
||||
|
@ -9,175 +9,6 @@ extern bool Halt;
|
||||
extern skyline::Mutex jniMtx;
|
||||
|
||||
namespace skyline {
|
||||
namespace instr {
|
||||
/**
|
||||
* @brief A bit-field struct that encapsulates a BRK instruction. See https://developer.arm.com/docs/ddi0596/latest/base-instructions-alphabetic-order/brk-breakpoint-instruction.
|
||||
*/
|
||||
struct Brk {
|
||||
/**
|
||||
* @brief Creates a BRK instruction with a specific immediate value, used for generating BRK opcodes
|
||||
* @param value The immediate value of the instruction
|
||||
*/
|
||||
explicit Brk(u16 value) {
|
||||
start = 0x0; // First 5 bits of a BRK instruction are 0
|
||||
this->value = value;
|
||||
end = 0x6A1; // Last 11 bits of a BRK instruction stored as u16
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Returns if the opcode is valid or not
|
||||
* @return If the opcode represents a valid BRK instruction
|
||||
*/
|
||||
inline bool Verify() {
|
||||
return (start == 0x0 && end == 0x6A1);
|
||||
}
|
||||
|
||||
union {
|
||||
struct {
|
||||
u8 start : 5;
|
||||
u32 value : 16;
|
||||
u16 end : 11;
|
||||
};
|
||||
u32 raw{};
|
||||
};
|
||||
};
|
||||
|
||||
static_assert(sizeof(Brk) == sizeof(u32));
|
||||
|
||||
/**
|
||||
* @brief A bit-field struct that encapsulates a SVC instruction. See https://developer.arm.com/docs/ddi0596/latest/base-instructions-alphabetic-order/svc-supervisor-call.
|
||||
*/
|
||||
struct Svc {
|
||||
/**
|
||||
* @brief Returns if the opcode is valid or not
|
||||
* @return If the opcode represents a valid SVC instruction
|
||||
*/
|
||||
inline bool Verify() {
|
||||
return (start == 0x1 && end == 0x6A0);
|
||||
}
|
||||
|
||||
union {
|
||||
struct {
|
||||
u8 start : 5;
|
||||
u32 value : 16;
|
||||
u16 end : 11;
|
||||
};
|
||||
u32 raw{};
|
||||
};
|
||||
};
|
||||
|
||||
static_assert(sizeof(Svc) == sizeof(u32));
|
||||
|
||||
/**
|
||||
* @brief A bit-field struct that encapsulates a MRS instruction. See https://developer.arm.com/docs/ddi0596/latest/base-instructions-alphabetic-order/mrs-move-system-register.
|
||||
*/
|
||||
struct Mrs {
|
||||
/**
|
||||
* @brief Creates a MRS instruction, used for generating BRK opcodes
|
||||
* @param srcReg The source system register
|
||||
* @param dstReg The destination Xn register
|
||||
*/
|
||||
Mrs(u32 srcReg, u8 dstReg) {
|
||||
this->srcReg = srcReg;
|
||||
this->dstReg = dstReg;
|
||||
end = 0xD53; // Last 12 bits of a MRS instruction stored as u16
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Returns if the opcode is valid or not
|
||||
* @return If the opcode represents a valid MRS instruction
|
||||
*/
|
||||
inline bool Verify() {
|
||||
return (end == 0xD53);
|
||||
}
|
||||
|
||||
union {
|
||||
struct {
|
||||
u8 dstReg : 5;
|
||||
u32 srcReg : 15;
|
||||
u16 end : 12;
|
||||
};
|
||||
u32 raw{};
|
||||
};
|
||||
};
|
||||
|
||||
static_assert(sizeof(Mrs) == sizeof(u32));
|
||||
|
||||
/**
|
||||
* @brief A bit-field struct that encapsulates a B instruction. See https://developer.arm.com/docs/ddi0596/latest/base-instructions-alphabetic-order/b-branch.
|
||||
*/
|
||||
struct B {
|
||||
public:
|
||||
explicit B(i64 offset) {
|
||||
this->offset = static_cast<i32>(offset / 4);
|
||||
end = 0x5;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Returns the offset of the instruction
|
||||
* @return The offset encoded within the instruction
|
||||
*/
|
||||
inline i32 Offset() {
|
||||
return offset * 4;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Returns if the opcode is valid or not
|
||||
* @return If the opcode represents a valid Branch instruction
|
||||
*/
|
||||
inline bool Verify() {
|
||||
return (end == 0x5);
|
||||
}
|
||||
|
||||
union {
|
||||
struct {
|
||||
i32 offset : 26;
|
||||
u8 end : 6;
|
||||
};
|
||||
u32 raw{};
|
||||
};
|
||||
};
|
||||
|
||||
static_assert(sizeof(B) == sizeof(u32));
|
||||
|
||||
/**
|
||||
* @brief A bit-field struct that encapsulates a BL instruction. See https://developer.arm.com/docs/ddi0596/latest/base-instructions-alphabetic-order/b-branch.
|
||||
*/
|
||||
struct BL {
|
||||
public:
|
||||
explicit BL(i64 offset) {
|
||||
this->offset = static_cast<i32>(offset / 4);
|
||||
end = 0x25;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Returns the offset of the instruction
|
||||
* @return The offset encoded within the instruction
|
||||
*/
|
||||
inline i32 Offset() {
|
||||
return offset * 4;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Returns if the opcode is valid or not
|
||||
* @return If the opcode represents a valid Branch instruction
|
||||
*/
|
||||
inline bool Verify() {
|
||||
return (end == 0x85);
|
||||
}
|
||||
|
||||
union {
|
||||
struct {
|
||||
i32 offset : 26;
|
||||
u8 end : 6;
|
||||
};
|
||||
u32 raw{};
|
||||
};
|
||||
};
|
||||
|
||||
static_assert(sizeof(BL) == sizeof(u32));
|
||||
}
|
||||
|
||||
void NCE::ReadRegisters(user_pt_regs ®isters, pid_t pid) const {
|
||||
iovec iov = {®isters, sizeof(registers)};
|
||||
long status = ptrace(PTRACE_GETREGSET, pid ? pid : currPid, NT_PRSTATUS, &iov);
|
||||
@ -203,15 +34,14 @@ namespace skyline {
|
||||
|
||||
void NCE::Execute() {
|
||||
int status = 0;
|
||||
while (!Halt && !state.os->processMap.empty()) {
|
||||
while (!Halt && state.os->process) {
|
||||
std::lock_guard jniGd(jniMtx);
|
||||
for (const auto &process : state.os->processMap) {
|
||||
state.os->thisProcess = process.second;
|
||||
state.os->thisThread = process.second->threadMap.at(process.first);
|
||||
currPid = process.first;
|
||||
for (const auto &thread : state.os->process->threadMap) {
|
||||
state.os->thisThread = thread.second;
|
||||
currPid = thread.first;
|
||||
auto &currRegs = registerMap[currPid];
|
||||
if (state.thisThread->status == kernel::type::KThread::Status::Running) {
|
||||
if (waitpid(state.thisThread->pid, &status, WNOHANG) == state.thisThread->pid) {
|
||||
if (state.thread->status == kernel::type::KThread::Status::Running) {
|
||||
if (waitpid(state.thread->pid, &status, WNOHANG) == state.thread->pid) {
|
||||
if (WIFSTOPPED(status) && (WSTOPSIG(status) == SIGTRAP || WSTOPSIG(status) == SIGSTOP)) { // NOLINT(hicpp-signed-bitwise)
|
||||
ReadRegisters(currRegs);
|
||||
auto instr = ReadBrk(currRegs.pc);
|
||||
@ -219,11 +49,11 @@ namespace skyline {
|
||||
// We store the instruction value as the immediate value in BRK. 0x0 to 0x7F are SVC, 0x80 to 0x9E is MRS for TPIDRRO_EL0.
|
||||
if (instr.value <= constant::SvcLast) {
|
||||
state.os->SvcHandler(static_cast<u16>(instr.value));
|
||||
if (state.thisThread->status != kernel::type::KThread::Status::Running)
|
||||
if (state.thread->status != kernel::type::KThread::Status::Running)
|
||||
continue;
|
||||
} else if (instr.value > constant::SvcLast && instr.value <= constant::SvcLast + constant::NumRegs) {
|
||||
// Catch MRS that reads the value of TPIDRRO_EL0 (TLS)
|
||||
SetRegister(static_cast<Xreg>(instr.value - (constant::SvcLast + 1)), state.thisThread->tls);
|
||||
SetRegister(static_cast<Xreg>(instr.value - (constant::SvcLast + 1)), state.thread->tls);
|
||||
} else if (instr.value == constant::BrkRdy)
|
||||
continue;
|
||||
else {
|
||||
@ -244,17 +74,18 @@ namespace skyline {
|
||||
state.os->KillThread(currPid);
|
||||
}
|
||||
}
|
||||
} else if ((state.thisThread->status == kernel::type::KThread::Status::WaitSync || state.thisThread->status == kernel::type::KThread::Status::Sleeping || state.thisThread->status == kernel::type::KThread::Status::WaitCondVar) && state.thisThread->timeout != 0) { // timeout == 0 means sleep forever
|
||||
if (state.thisThread->timeout <= GetCurrTimeNs()) {
|
||||
state.logger->Info("An event has timed out: {}", state.thisThread->status);
|
||||
if (state.thisThread->status == kernel::type::KThread::Status::WaitSync || state.thisThread->status == kernel::type::KThread::Status::WaitCondVar)
|
||||
} else if ((state.thread->status == kernel::type::KThread::Status::WaitSync || state.thread->status == kernel::type::KThread::Status::Sleeping || state.thread->status == kernel::type::KThread::Status::WaitCondVar) && state.thread->timeout != 0) { // timeout == 0 means sleep forever
|
||||
if (state.thread->timeout <= GetCurrTimeNs()) {
|
||||
if(state.thread->status != kernel::type::KThread::Status::Sleeping)
|
||||
state.logger->Info("An event has timed out: {}", state.thread->status);
|
||||
if (state.thread->status == kernel::type::KThread::Status::WaitSync || state.thread->status == kernel::type::KThread::Status::WaitCondVar)
|
||||
SetRegister(Wreg::W0, constant::status::Timeout);
|
||||
state.thisThread->status = kernel::type::KThread::Status::Runnable;
|
||||
state.thread->status = kernel::type::KThread::Status::Runnable;
|
||||
}
|
||||
}
|
||||
if (state.thisThread->status == kernel::type::KThread::Status::Runnable) {
|
||||
state.thisThread->ClearWaitObjects();
|
||||
state.thisThread->status = kernel::type::KThread::Status::Running;
|
||||
if (state.thread->status == kernel::type::KThread::Status::Runnable) {
|
||||
state.thread->ClearWaitObjects();
|
||||
state.thread->status = kernel::type::KThread::Status::Running;
|
||||
currRegs.pc += sizeof(u32);
|
||||
WriteRegisters(currRegs);
|
||||
ResumeProcess();
|
||||
@ -263,9 +94,6 @@ namespace skyline {
|
||||
state.os->serviceManager.Loop();
|
||||
state.gpu->Loop();
|
||||
}
|
||||
for (const auto &process : state.os->processMap) {
|
||||
state.os->KillThread(process.first);
|
||||
}
|
||||
}
|
||||
|
||||
void BrkLr() {
|
||||
|
@ -12,6 +12,7 @@ namespace skyline {
|
||||
namespace instr {
|
||||
struct Brk;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief The NCE (Native Code Execution) class is responsible for managing the state of catching instructions and directly controlling processes/threads
|
||||
*/
|
||||
|
@ -3,7 +3,7 @@
|
||||
#include "loader/nro.h"
|
||||
|
||||
namespace skyline::kernel {
|
||||
OS::OS(std::shared_ptr<JvmManager>& jvmManager, std::shared_ptr<Logger> &logger, std::shared_ptr<Settings> &settings) : state(this, thisProcess, thisThread, jvmManager, settings, logger), serviceManager(state) {}
|
||||
OS::OS(std::shared_ptr<JvmManager>& jvmManager, std::shared_ptr<Logger> &logger, std::shared_ptr<Settings> &settings) : state(this, process, thisThread, jvmManager, settings, logger), serviceManager(state) {}
|
||||
|
||||
void OS::Execute(const int romFd, const TitleFormat romType) {
|
||||
auto process = CreateProcess(constant::BaseAddr, constant::DefStackSize);
|
||||
@ -12,7 +12,7 @@ namespace skyline::kernel {
|
||||
loader.LoadProcessData(process, state);
|
||||
} else
|
||||
throw exception("Unsupported ROM extension.");
|
||||
process->threadMap.at(process->mainThread)->Start(); // The kernel itself is responsible for starting the main thread
|
||||
process->threadMap.at(process->pid)->Start(); // The kernel itself is responsible for starting the main thread
|
||||
state.nce->Execute();
|
||||
}
|
||||
|
||||
@ -36,27 +36,22 @@ namespace skyline::kernel {
|
||||
pid_t pid = clone(&ExecuteChild, stack + stackSize, CLONE_FILES | CLONE_FS | SIGCHLD, nullptr); // NOLINT(hicpp-signed-bitwise)
|
||||
if (pid == -1)
|
||||
throw exception("Call to clone() has failed: {}", strerror(errno));
|
||||
std::shared_ptr<type::KProcess> process = std::make_shared<kernel::type::KProcess>(state, pid, address, reinterpret_cast<u64>(stack), stackSize);
|
||||
processMap[pid] = process;
|
||||
processVec.push_back(pid);
|
||||
process = std::make_shared<kernel::type::KProcess>(state, pid, address, reinterpret_cast<u64>(stack), stackSize);
|
||||
state.logger->Debug("Successfully created process with PID: {}", pid);
|
||||
return process;
|
||||
}
|
||||
|
||||
void OS::KillThread(pid_t pid) {
|
||||
auto process = processMap.at(pid);
|
||||
if (process->mainThread == pid) {
|
||||
if (process->pid == pid) {
|
||||
state.logger->Debug("Killing process with PID: {}", pid);
|
||||
for (auto&[key, value]: process->threadMap) {
|
||||
value->Kill();
|
||||
processMap.erase(key);
|
||||
}
|
||||
processVec.erase(std::remove(processVec.begin(), processVec.end(), pid), processVec.end());
|
||||
process.reset();
|
||||
} else {
|
||||
state.logger->Debug("Killing thread with TID: {}", pid);
|
||||
process->threadMap.at(pid)->Kill();
|
||||
process->threadMap.erase(pid);
|
||||
processMap.erase(pid);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -19,9 +19,7 @@ namespace skyline::kernel {
|
||||
DeviceState state; //!< The state of the device
|
||||
|
||||
public:
|
||||
std::unordered_map<pid_t, std::shared_ptr<type::KProcess>> processMap; //!< A mapping from a threat's PID to it's KProcess object
|
||||
std::vector<pid_t> processVec; //!< A vector of all processes by their main thread's PID
|
||||
std::shared_ptr<type::KProcess> thisProcess; //!< The corresponding KProcess object of the process that's called an SVC
|
||||
std::shared_ptr<type::KProcess> process; //!< The KProcess object for the emulator, representing the guest process
|
||||
std::shared_ptr<type::KThread> thisThread; //!< The corresponding KThread object of the thread that's called an SVC
|
||||
service::ServiceManager serviceManager; //!< This manages all of the service functions
|
||||
|
||||
|
@ -20,7 +20,7 @@ namespace skyline::service::am {
|
||||
}
|
||||
|
||||
void ICommonStateGetter::GetEventHandle(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
||||
auto handle = state.thisProcess->InsertItem(messageEvent);
|
||||
auto handle = state.process->InsertItem(messageEvent);
|
||||
state.logger->Debug("Event Handle: 0x{:X}", handle);
|
||||
response.copyHandles.push_back(handle);
|
||||
}
|
||||
@ -86,7 +86,7 @@ namespace skyline::service::am {
|
||||
}) {}
|
||||
|
||||
void IWindowController::GetAppletResourceUserId(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
||||
response.Push(static_cast<u64>(state.thisProcess->mainThread));
|
||||
response.Push(static_cast<u64>(state.process->pid));
|
||||
}
|
||||
|
||||
void IWindowController::AcquireForegroundRights(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {}
|
||||
|
@ -8,7 +8,7 @@ namespace skyline::service::hid {
|
||||
|
||||
void IAppletResource::GetSharedMemoryHandle(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
||||
hidSharedMemory = std::make_shared<kernel::type::KSharedMemory>(state, NULL, constant::hidSharedMemSize, memory::Permission(true, false, false), memory::Type::SharedMemory);
|
||||
auto handle = state.thisProcess->InsertItem<type::KSharedMemory>(hidSharedMemory);
|
||||
auto handle = state.process->InsertItem<type::KSharedMemory>(hidSharedMemory);
|
||||
state.logger->Debug("HID Shared Memory Handle: {}", handle);
|
||||
response.copyHandles.push_back(handle);
|
||||
}
|
||||
@ -40,7 +40,7 @@ namespace skyline::service::hid {
|
||||
size_t numId = buffer.size / sizeof(NpadId);
|
||||
u64 address = buffer.address;
|
||||
for (size_t i = 0; i < numId; i++) {
|
||||
auto id = state.thisProcess->ReadMemory<NpadId>(address);
|
||||
auto id = state.process->ReadMemory<NpadId>(address);
|
||||
deviceMap[id] = JoyConDevice(id);
|
||||
address += sizeof(NpadId);
|
||||
}
|
||||
|
@ -14,7 +14,7 @@ namespace skyline::service::nvdrv {
|
||||
void nvdrv::Open(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
||||
auto buffer = request.inputBuf.at(0);
|
||||
std::string path(buffer.size, '\0');
|
||||
state.thisProcess->ReadMemory(path.data(), buffer.address, buffer.size);
|
||||
state.process->ReadMemory(path.data(), buffer.address, buffer.size);
|
||||
response.Push<u32>(state.gpu->OpenDevice(path));
|
||||
response.Push<u32>(constant::status::Success);
|
||||
}
|
||||
@ -39,7 +39,7 @@ namespace skyline::service::nvdrv {
|
||||
auto fd = request.Pop<u32>();
|
||||
auto eventId = request.Pop<u32>();
|
||||
auto event = std::make_shared<type::KEvent>(state);
|
||||
auto handle = state.thisProcess->InsertItem<type::KEvent>(event);
|
||||
auto handle = state.process->InsertItem<type::KEvent>(event);
|
||||
state.logger->Debug("QueryEvent: FD: {}, Event ID: {}, Handle: {}", fd, eventId, handle);
|
||||
response.copyHandles.push_back(handle);
|
||||
}
|
||||
|
@ -64,7 +64,7 @@ namespace skyline::service::nvnflinger {
|
||||
}
|
||||
|
||||
void dispdrv::GetNativeHandle(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
||||
handle_t handle = state.thisProcess->InsertItem(state.gpu->bufferEvent);
|
||||
handle_t handle = state.process->InsertItem(state.gpu->bufferEvent);
|
||||
state.logger->Debug("BufferEvent Handle: 0x{:X}", handle);
|
||||
response.copyHandles.push_back(handle);
|
||||
response.Push<u32>(constant::status::Success);
|
||||
|
@ -120,7 +120,7 @@ namespace skyline::service {
|
||||
}
|
||||
|
||||
handle_t ServiceManager::NewSession(const Service serviceType) {
|
||||
return state.thisProcess->NewHandle<type::KSession>(GetService(serviceType)).handle;
|
||||
return state.process->NewHandle<type::KSession>(GetService(serviceType)).handle;
|
||||
}
|
||||
|
||||
std::shared_ptr<BaseService> ServiceManager::NewService(const std::string &serviceName, type::KSession &session, ipc::IpcResponse &response) {
|
||||
@ -131,7 +131,7 @@ namespace skyline::service {
|
||||
response.domainObjects.push_back(session.handleIndex);
|
||||
handle = session.handleIndex;
|
||||
} else {
|
||||
handle = state.thisProcess->NewHandle<type::KSession>(serviceObject).handle;
|
||||
handle = state.process->NewHandle<type::KSession>(serviceObject).handle;
|
||||
response.moveHandles.push_back(handle);
|
||||
}
|
||||
state.logger->Debug("Service has been created: \"{}\" (0x{:X})", serviceName, handle);
|
||||
@ -145,14 +145,14 @@ namespace skyline::service {
|
||||
response.domainObjects.push_back(session.handleIndex);
|
||||
handle = session.handleIndex++;
|
||||
} else {
|
||||
handle = state.thisProcess->NewHandle<type::KSession>(serviceObject).handle;
|
||||
handle = state.process->NewHandle<type::KSession>(serviceObject).handle;
|
||||
response.moveHandles.push_back(handle);
|
||||
}
|
||||
state.logger->Debug("Service has been registered: \"{}\" (0x{:X})", serviceObject->getName(), handle);
|
||||
}
|
||||
|
||||
void ServiceManager::CloseSession(const handle_t handle) {
|
||||
auto session = state.thisProcess->GetHandle<type::KSession>(handle);
|
||||
auto session = state.process->GetHandle<type::KSession>(handle);
|
||||
if (session->serviceStatus == type::KSession::ServiceStatus::Open) {
|
||||
if (session->isDomain) {
|
||||
for (const auto &[objectId, service] : session->domainTable)
|
||||
@ -170,7 +170,7 @@ namespace skyline::service {
|
||||
}
|
||||
|
||||
void ServiceManager::SyncRequestHandler(const handle_t handle) {
|
||||
auto session = state.thisProcess->GetHandle<type::KSession>(handle);
|
||||
auto session = state.process->GetHandle<type::KSession>(handle);
|
||||
state.logger->Debug("----Start----");
|
||||
state.logger->Debug("Handle is 0x{:X}", handle);
|
||||
|
||||
@ -211,7 +211,7 @@ namespace skyline::service {
|
||||
break;
|
||||
case ipc::ControlCommand::CloneCurrentObject:
|
||||
case ipc::ControlCommand::CloneCurrentObjectEx:
|
||||
response.Push(state.thisProcess->InsertItem(session));
|
||||
response.Push(state.process->InsertItem(session));
|
||||
break;
|
||||
case ipc::ControlCommand::QueryPointerBufferSize:
|
||||
response.Push<u32>(0x1000);
|
||||
|
@ -6,6 +6,6 @@ namespace skyline::service::set {
|
||||
|
||||
void sys::GetFirmwareVersion(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
||||
SysVerTitle title{.minor=9, .major=0, .micro=0, .revMajor=4, .platform="NX", .verHash="4de65c071fd0869695b7629f75eb97b2551dbf2f", .dispVer="9.0.0", .dispTitle="NintendoSDK Firmware for NX 9.0.0-4.0"};
|
||||
state.thisProcess->WriteMemory(title, request.outputBuf.at(0).address);
|
||||
state.process->WriteMemory(title, request.outputBuf.at(0).address);
|
||||
}
|
||||
}
|
||||
|
@ -105,7 +105,7 @@ namespace skyline::service::vi {
|
||||
}
|
||||
|
||||
void IApplicationDisplayService::GetDisplayVsyncEvent(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
||||
handle_t handle = state.thisProcess->InsertItem(state.gpu->vsyncEvent);
|
||||
handle_t handle = state.process->InsertItem(state.gpu->vsyncEvent);
|
||||
state.logger->Debug("VSync Event Handle: 0x{:X}", handle);
|
||||
response.copyHandles.push_back(handle);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user