mirror of
https://github.com/skyline-emu/skyline.git
synced 2024-11-27 00:34:20 +01:00
Implement SvcUnmapSharedMemory + Remove Redundant [[unlikely]]
This commit is contained in:
parent
a9de99357b
commit
d595b9fe4f
@ -24,6 +24,6 @@ namespace skyline::input {
|
|||||||
NpadManager npad;
|
NpadManager npad;
|
||||||
TouchManager touch;
|
TouchManager touch;
|
||||||
|
|
||||||
Input(const DeviceState &state) : state(state), kHid(std::make_shared<kernel::type::KSharedMemory>(state, sizeof(HidSharedMemory))), hid(reinterpret_cast<HidSharedMemory *>(kHid->kernel.ptr)), npad(state, hid), touch(state, hid) {}
|
Input(const DeviceState &state) : state(state), kHid(std::make_shared<kernel::type::KSharedMemory>(state, sizeof(HidSharedMemory))), hid(reinterpret_cast<HidSharedMemory *>(kHid->host.ptr)), npad(state, hid), touch(state, hid) {}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -62,7 +62,7 @@ namespace skyline::kernel {
|
|||||||
throw exception("Cannot find a suitable carveout for the guest address space");
|
throw exception("Cannot find a suitable carveout for the guest address space");
|
||||||
|
|
||||||
auto result{mmap(reinterpret_cast<void *>(base.address), base.size, PROT_NONE, MAP_FIXED | MAP_ANONYMOUS | MAP_PRIVATE, -1, 0)};
|
auto result{mmap(reinterpret_cast<void *>(base.address), base.size, PROT_NONE, MAP_FIXED | MAP_ANONYMOUS | MAP_PRIVATE, -1, 0)};
|
||||||
if (result == MAP_FAILED) [[unlikely]]
|
if (result == MAP_FAILED)
|
||||||
throw exception("Failed to mmap guest address space: {}", strerror(errno));
|
throw exception("Failed to mmap guest address space: {}", strerror(errno));
|
||||||
|
|
||||||
chunks = {
|
chunks = {
|
||||||
|
@ -216,7 +216,7 @@ namespace skyline::kernel {
|
|||||||
auto &front{core.queue.front()};
|
auto &front{core.queue.front()};
|
||||||
if (front != thread)
|
if (front != thread)
|
||||||
front->scheduleCondition.notify_one(); // If we aren't at the front of the queue, only then should we wake the thread at the front up
|
front->scheduleCondition.notify_one(); // If we aren't at the front of the queue, only then should we wake the thread at the front up
|
||||||
} else if (!thread->forceYield) [[unlikely]] {
|
} else if (!thread->forceYield) {
|
||||||
throw exception("T{} called Rotate while not being in C{}'s queue", thread->id, thread->coreId);
|
throw exception("T{} called Rotate while not being in C{}'s queue", thread->id, thread->coreId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -508,6 +508,35 @@ namespace skyline::kernel::svc {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void UnmapSharedMemory(const DeviceState &state) {
|
||||||
|
try {
|
||||||
|
auto object{state.process->GetHandle<type::KSharedMemory>(state.ctx->gpr.w0)};
|
||||||
|
auto pointer{reinterpret_cast<u8 *>(state.ctx->gpr.x1)};
|
||||||
|
|
||||||
|
if (!util::PageAligned(pointer)) {
|
||||||
|
state.ctx->gpr.w0 = result::InvalidAddress;
|
||||||
|
state.logger->Warn("'pointer' not page aligned: 0x{:X}", pointer);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t size{state.ctx->gpr.x2};
|
||||||
|
if (!util::PageAligned(size)) {
|
||||||
|
state.ctx->gpr.w0 = result::InvalidSize;
|
||||||
|
state.logger->Warn("'size' {}: 0x{:X}", size ? "not page aligned" : "is zero", size);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
state.logger->Debug("Unmapping shared memory at 0x{:X} - 0x{:X} (0x{:X} bytes)", pointer, pointer + size, size);
|
||||||
|
|
||||||
|
object->Unmap(pointer, size);
|
||||||
|
|
||||||
|
state.ctx->gpr.w0 = Result{};
|
||||||
|
} catch (const std::out_of_range &) {
|
||||||
|
state.logger->Warn("'handle' invalid: 0x{:X}", static_cast<u32>(state.ctx->gpr.w0));
|
||||||
|
state.ctx->gpr.w0 = result::InvalidHandle;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void CreateTransferMemory(const DeviceState &state) {
|
void CreateTransferMemory(const DeviceState &state) {
|
||||||
auto pointer{reinterpret_cast<u8 *>(state.ctx->gpr.x1)};
|
auto pointer{reinterpret_cast<u8 *>(state.ctx->gpr.x1)};
|
||||||
if (!util::PageAligned(pointer)) {
|
if (!util::PageAligned(pointer)) {
|
||||||
|
@ -103,11 +103,17 @@ namespace skyline::kernel::svc {
|
|||||||
void ClearEvent(const DeviceState &state);
|
void ClearEvent(const DeviceState &state);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Maps the block supplied by the handle
|
* @brief Maps shared memory into a memory region
|
||||||
* @url https://switchbrew.org/wiki/SVC#MapSharedMemory
|
* @url https://switchbrew.org/wiki/SVC#MapSharedMemory
|
||||||
*/
|
*/
|
||||||
void MapSharedMemory(const DeviceState &state);
|
void MapSharedMemory(const DeviceState &state);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Unmaps shared memory which has been mapped
|
||||||
|
* @url https://switchbrew.org/wiki/SVC#UnmapSharedMemory
|
||||||
|
*/
|
||||||
|
void UnmapSharedMemory(const DeviceState &state);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Returns a handle to a KSharedMemory object
|
* @brief Returns a handle to a KSharedMemory object
|
||||||
* @url https://switchbrew.org/wiki/SVC#CreateTransferMemory
|
* @url https://switchbrew.org/wiki/SVC#CreateTransferMemory
|
||||||
@ -269,7 +275,7 @@ namespace skyline::kernel::svc {
|
|||||||
SVC_NONE, // 0x11
|
SVC_NONE, // 0x11
|
||||||
SVC_ENTRY(ClearEvent), // 0x12
|
SVC_ENTRY(ClearEvent), // 0x12
|
||||||
SVC_ENTRY(MapSharedMemory), // 0x13
|
SVC_ENTRY(MapSharedMemory), // 0x13
|
||||||
SVC_NONE, // 0x14
|
SVC_ENTRY(UnmapSharedMemory), // 0x14
|
||||||
SVC_ENTRY(CreateTransferMemory), // 0x15
|
SVC_ENTRY(CreateTransferMemory), // 0x15
|
||||||
SVC_ENTRY(CloseHandle), // 0x16
|
SVC_ENTRY(CloseHandle), // 0x16
|
||||||
SVC_ENTRY(ResetSignal), // 0x17
|
SVC_ENTRY(ResetSignal), // 0x17
|
||||||
|
@ -13,12 +13,11 @@ namespace skyline::kernel::type {
|
|||||||
if (fd < 0)
|
if (fd < 0)
|
||||||
throw exception("An error occurred while creating shared memory: {}", fd);
|
throw exception("An error occurred while creating shared memory: {}", fd);
|
||||||
|
|
||||||
kernel.ptr = reinterpret_cast<u8 *>(mmap(nullptr, size, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_SHARED, fd, 0));
|
host.ptr = reinterpret_cast<u8 *>(mmap(nullptr, size, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_SHARED, fd, 0));
|
||||||
if (kernel.ptr == MAP_FAILED)
|
if (host.ptr == MAP_FAILED)
|
||||||
[[unlikely]]
|
throw exception("An occurred while mapping shared memory: {}", strerror(errno));
|
||||||
throw exception("An occurred while mapping shared memory: {}", strerror(errno));
|
|
||||||
|
|
||||||
kernel.size = size;
|
host.size = size;
|
||||||
}
|
}
|
||||||
|
|
||||||
u8 *KSharedMemory::Map(u8 *ptr, u64 size, memory::Permission permission) {
|
u8 *KSharedMemory::Map(u8 *ptr, u64 size, memory::Permission permission) {
|
||||||
@ -26,11 +25,12 @@ namespace skyline::kernel::type {
|
|||||||
throw exception("KPrivateMemory allocation isn't inside guest address space: 0x{:X} - 0x{:X}", ptr, ptr + size);
|
throw exception("KPrivateMemory allocation isn't inside guest address space: 0x{:X} - 0x{:X}", ptr, ptr + size);
|
||||||
if (!util::PageAligned(ptr) || !util::PageAligned(size))
|
if (!util::PageAligned(ptr) || !util::PageAligned(size))
|
||||||
throw exception("KSharedMemory mapping isn't page-aligned: 0x{:X} - 0x{:X} (0x{:X})", ptr, ptr + size, size);
|
throw exception("KSharedMemory mapping isn't page-aligned: 0x{:X} - 0x{:X} (0x{:X})", ptr, ptr + size, size);
|
||||||
|
if (guest.Valid())
|
||||||
|
throw exception("Mapping KSharedMemory multiple times on guest is not supported: Requested Mapping: 0x{:X} - 0x{:X} (0x{:X}), Current Mapping: 0x{:X} - 0x{:X} (0x{:X})", ptr, ptr + size, size, guest.ptr, guest.ptr + guest.size, guest.size);
|
||||||
|
|
||||||
guest.ptr = reinterpret_cast<u8 *>(mmap(ptr, size, permission.Get(), MAP_SHARED | (ptr ? MAP_FIXED : 0), fd, 0));
|
guest.ptr = reinterpret_cast<u8 *>(mmap(ptr, size, permission.Get(), MAP_SHARED | (ptr ? MAP_FIXED : 0), fd, 0));
|
||||||
if (guest.ptr == MAP_FAILED)
|
if (guest.ptr == MAP_FAILED)
|
||||||
[[unlikely]]
|
throw exception("An error occurred while mapping shared memory in guest: {}", strerror(errno));
|
||||||
throw exception("An error occurred while mapping shared memory in guest: {}", strerror(errno));
|
|
||||||
guest.size = size;
|
guest.size = size;
|
||||||
|
|
||||||
state.process->memory.InsertChunk(ChunkDescriptor{
|
state.process->memory.InsertChunk(ChunkDescriptor{
|
||||||
@ -43,6 +43,25 @@ namespace skyline::kernel::type {
|
|||||||
return guest.ptr;
|
return guest.ptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void KSharedMemory::Unmap(u8 *ptr, u64 size) {
|
||||||
|
if (!state.process->memory.base.IsInside(ptr) || !state.process->memory.base.IsInside(ptr + size))
|
||||||
|
throw exception("KPrivateMemory allocation isn't inside guest address space: 0x{:X} - 0x{:X}", ptr, ptr + size);
|
||||||
|
if (!util::PageAligned(ptr) || !util::PageAligned(size))
|
||||||
|
throw exception("KSharedMemory mapping isn't page-aligned: 0x{:X} - 0x{:X} (0x{:X})", ptr, ptr + size, size);
|
||||||
|
if (guest.ptr != ptr && guest.size != size)
|
||||||
|
throw exception("Unmapping KSharedMemory partially is not supported: Requested Unmap: 0x{:X} - 0x{:X} (0x{:X}), Current Mapping: 0x{:X} - 0x{:X} (0x{:X})", ptr, ptr + size, size, guest.ptr, guest.ptr + guest.size, guest.size);
|
||||||
|
|
||||||
|
if (mmap(ptr, size, PROT_NONE, MAP_ANONYMOUS | MAP_PRIVATE | MAP_FIXED, 0, 0) == MAP_FAILED)
|
||||||
|
throw exception("An error occurred while unmapping shared memory in guest: {}", strerror(errno));
|
||||||
|
|
||||||
|
guest = {};
|
||||||
|
state.process->memory.InsertChunk(ChunkDescriptor{
|
||||||
|
.ptr = ptr,
|
||||||
|
.size = size,
|
||||||
|
.state = memory::states::Unmapped,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
void KSharedMemory::UpdatePermission(u8 *ptr, size_t size, memory::Permission permission) {
|
void KSharedMemory::UpdatePermission(u8 *ptr, size_t size, memory::Permission permission) {
|
||||||
if (ptr && !util::PageAligned(ptr))
|
if (ptr && !util::PageAligned(ptr))
|
||||||
throw exception("KSharedMemory permission updated with a non-page-aligned address: 0x{:X}", ptr);
|
throw exception("KSharedMemory permission updated with a non-page-aligned address: 0x{:X}", ptr);
|
||||||
@ -50,8 +69,7 @@ namespace skyline::kernel::type {
|
|||||||
if (guest.Valid()) {
|
if (guest.Valid()) {
|
||||||
mprotect(ptr, size, permission.Get());
|
mprotect(ptr, size, permission.Get());
|
||||||
if (guest.ptr == MAP_FAILED)
|
if (guest.ptr == MAP_FAILED)
|
||||||
[[unlikely]]
|
throw exception("An error occurred while updating shared memory's permissions in guest: {}", strerror(errno));
|
||||||
throw exception("An error occurred while updating shared memory's permissions in guest: {}", strerror(errno));
|
|
||||||
|
|
||||||
state.process->memory.InsertChunk(ChunkDescriptor{
|
state.process->memory.InsertChunk(ChunkDescriptor{
|
||||||
.ptr = ptr,
|
.ptr = ptr,
|
||||||
@ -63,8 +81,8 @@ namespace skyline::kernel::type {
|
|||||||
}
|
}
|
||||||
|
|
||||||
KSharedMemory::~KSharedMemory() {
|
KSharedMemory::~KSharedMemory() {
|
||||||
if (kernel.Valid())
|
if (host.Valid())
|
||||||
munmap(kernel.ptr, kernel.size);
|
munmap(host.ptr, host.size);
|
||||||
|
|
||||||
if (state.process && guest.Valid()) {
|
if (state.process && guest.Valid()) {
|
||||||
mmap(guest.ptr, guest.size, PROT_NONE, MAP_ANONYMOUS | MAP_PRIVATE, -1, 0); // As this is the destructor, we cannot throw on this failing
|
mmap(guest.ptr, guest.size, PROT_NONE, MAP_ANONYMOUS | MAP_PRIVATE, -1, 0); // As this is the destructor, we cannot throw on this failing
|
||||||
|
@ -22,7 +22,7 @@ namespace skyline::kernel::type {
|
|||||||
constexpr bool Valid() {
|
constexpr bool Valid() {
|
||||||
return ptr && size;
|
return ptr && size;
|
||||||
}
|
}
|
||||||
} kernel, guest{};
|
} host, guest{}; //!< We keep two mirrors of the underlying shared memory for guest access and host access, the host mirror is persistently mapped and should be used by anything accessing the memory on the host
|
||||||
|
|
||||||
KSharedMemory(const DeviceState &state, size_t size, memory::MemoryState memState = memory::states::SharedMemory, KType type = KType::KSharedMemory);
|
KSharedMemory(const DeviceState &state, size_t size, memory::MemoryState memState = memory::states::SharedMemory, KType type = KType::KSharedMemory);
|
||||||
|
|
||||||
@ -31,6 +31,11 @@ namespace skyline::kernel::type {
|
|||||||
*/
|
*/
|
||||||
u8 *Map(u8 *ptr, u64 size, memory::Permission permission);
|
u8 *Map(u8 *ptr, u64 size, memory::Permission permission);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @note 'ptr' needs to be in guest-reserved address space
|
||||||
|
*/
|
||||||
|
void Unmap(u8 *ptr, u64 size);
|
||||||
|
|
||||||
span<u8> Get() override {
|
span<u8> Get() override {
|
||||||
return span(guest.ptr, guest.size);
|
return span(guest.ptr, guest.size);
|
||||||
}
|
}
|
||||||
|
@ -15,7 +15,7 @@ namespace skyline::kernel::type {
|
|||||||
* @note 'ptr' needs to be in guest-reserved address space
|
* @note 'ptr' needs to be in guest-reserved address space
|
||||||
*/
|
*/
|
||||||
KTransferMemory(const DeviceState &state, u8 *ptr, size_t size, memory::Permission permission, memory::MemoryState memState = memory::states::TransferMemory) : KSharedMemory(state, size, memState, KType::KTransferMemory) {
|
KTransferMemory(const DeviceState &state, u8 *ptr, size_t size, memory::Permission permission, memory::MemoryState memState = memory::states::TransferMemory) : KSharedMemory(state, size, memState, KType::KTransferMemory) {
|
||||||
std::memcpy(kernel.ptr, ptr, size);
|
std::memcpy(host.ptr, ptr, size);
|
||||||
Map(ptr, size, permission);
|
Map(ptr, size, permission);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -23,7 +23,7 @@ namespace skyline::nce {
|
|||||||
if (svc) [[likely]] {
|
if (svc) [[likely]] {
|
||||||
TRACE_EVENT("kernel", perfetto::StaticString{svc.name});
|
TRACE_EVENT("kernel", perfetto::StaticString{svc.name});
|
||||||
(svc.function)(state);
|
(svc.function)(state);
|
||||||
} else [[unlikely]] {
|
} else {
|
||||||
throw exception("Unimplemented SVC 0x{:X}", svcId);
|
throw exception("Unimplemented SVC 0x{:X}", svcId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -33,11 +33,11 @@ namespace skyline::service::pl {
|
|||||||
constexpr u32 SharedFontMagic{0x36F81A1E}; //!< The encrypted magic for a single font in the shared font data
|
constexpr u32 SharedFontMagic{0x36F81A1E}; //!< The encrypted magic for a single font in the shared font data
|
||||||
constexpr u32 SharedFontKey{SharedFontMagic ^ SharedFontResult}; //!< The XOR key for encrypting the font size
|
constexpr u32 SharedFontKey{SharedFontMagic ^ SharedFontResult}; //!< The XOR key for encrypting the font size
|
||||||
|
|
||||||
auto ptr{reinterpret_cast<u32 *>(fontSharedMem->kernel.ptr)};
|
auto ptr{reinterpret_cast<u32 *>(fontSharedMem->host.ptr)};
|
||||||
for (auto &font : fontTable) {
|
for (auto &font : fontTable) {
|
||||||
*ptr++ = SharedFontResult;
|
*ptr++ = SharedFontResult;
|
||||||
*ptr++ = font.length ^ SharedFontKey;
|
*ptr++ = font.length ^ SharedFontKey;
|
||||||
font.offset = reinterpret_cast<u64>(ptr) - reinterpret_cast<u64>(fontSharedMem->kernel.ptr);
|
font.offset = reinterpret_cast<u64>(ptr) - reinterpret_cast<u64>(fontSharedMem->host.ptr);
|
||||||
|
|
||||||
std::memcpy(ptr, font.data, font.length);
|
std::memcpy(ptr, font.data, font.length);
|
||||||
ptr = reinterpret_cast<u32 *>(reinterpret_cast<u8 *>(ptr) + font.length);
|
ptr = reinterpret_cast<u32 *>(reinterpret_cast<u8 *>(ptr) + font.length);
|
||||||
|
@ -57,7 +57,7 @@ namespace skyline::service::timesrv::core {
|
|||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
|
|
||||||
TimeSharedMemory::TimeSharedMemory(const DeviceState &state) : kTimeSharedMemory(std::make_shared<kernel::type::KSharedMemory>(state, TimeSharedMemorySize)), timeSharedMemory(reinterpret_cast<TimeSharedMemoryLayout *>(kTimeSharedMemory->kernel.ptr)) {}
|
TimeSharedMemory::TimeSharedMemory(const DeviceState &state) : kTimeSharedMemory(std::make_shared<kernel::type::KSharedMemory>(state, TimeSharedMemorySize)), timeSharedMemory(reinterpret_cast<TimeSharedMemoryLayout *>(kTimeSharedMemory->host.ptr)) {}
|
||||||
|
|
||||||
void TimeSharedMemory::SetupStandardSteadyClock(UUID rtcId, TimeSpanType baseTimePoint) {
|
void TimeSharedMemory::SetupStandardSteadyClock(UUID rtcId, TimeSpanType baseTimePoint) {
|
||||||
SteadyClockTimePoint context{
|
SteadyClockTimePoint context{
|
||||||
@ -143,4 +143,4 @@ namespace skyline::service::timesrv::core {
|
|||||||
SignalOperationEvent();
|
SignalOperationEvent();
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user