mirror of
https://github.com/skyline-emu/skyline.git
synced 2024-12-27 13:55:29 +03:00
Implement SvcUnmapSharedMemory + Remove Redundant [[unlikely]]
This commit is contained in:
parent
f1433ad0d9
commit
0d6d90c4cd
@ -24,6 +24,6 @@ namespace skyline::input {
|
||||
NpadManager npad;
|
||||
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");
|
||||
|
||||
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));
|
||||
|
||||
chunks = {
|
||||
|
@ -216,7 +216,7 @@ namespace skyline::kernel {
|
||||
auto &front{core.queue.front()};
|
||||
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
|
||||
} 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);
|
||||
}
|
||||
|
||||
|
@ -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) {
|
||||
auto pointer{reinterpret_cast<u8 *>(state.ctx->gpr.x1)};
|
||||
if (!util::PageAligned(pointer)) {
|
||||
|
@ -103,11 +103,17 @@ namespace skyline::kernel::svc {
|
||||
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
|
||||
*/
|
||||
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
|
||||
* @url https://switchbrew.org/wiki/SVC#CreateTransferMemory
|
||||
@ -269,7 +275,7 @@ namespace skyline::kernel::svc {
|
||||
SVC_NONE, // 0x11
|
||||
SVC_ENTRY(ClearEvent), // 0x12
|
||||
SVC_ENTRY(MapSharedMemory), // 0x13
|
||||
SVC_NONE, // 0x14
|
||||
SVC_ENTRY(UnmapSharedMemory), // 0x14
|
||||
SVC_ENTRY(CreateTransferMemory), // 0x15
|
||||
SVC_ENTRY(CloseHandle), // 0x16
|
||||
SVC_ENTRY(ResetSignal), // 0x17
|
||||
|
@ -13,12 +13,11 @@ namespace skyline::kernel::type {
|
||||
if (fd < 0)
|
||||
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));
|
||||
if (kernel.ptr == MAP_FAILED)
|
||||
[[unlikely]]
|
||||
throw exception("An occurred while mapping shared memory: {}", strerror(errno));
|
||||
host.ptr = reinterpret_cast<u8 *>(mmap(nullptr, size, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_SHARED, fd, 0));
|
||||
if (host.ptr == MAP_FAILED)
|
||||
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) {
|
||||
@ -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);
|
||||
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.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));
|
||||
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;
|
||||
|
||||
state.process->memory.InsertChunk(ChunkDescriptor{
|
||||
@ -43,6 +43,25 @@ namespace skyline::kernel::type {
|
||||
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) {
|
||||
if (ptr && !util::PageAligned(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()) {
|
||||
mprotect(ptr, size, permission.Get());
|
||||
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{
|
||||
.ptr = ptr,
|
||||
@ -63,8 +81,8 @@ namespace skyline::kernel::type {
|
||||
}
|
||||
|
||||
KSharedMemory::~KSharedMemory() {
|
||||
if (kernel.Valid())
|
||||
munmap(kernel.ptr, kernel.size);
|
||||
if (host.Valid())
|
||||
munmap(host.ptr, host.size);
|
||||
|
||||
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
|
||||
|
@ -22,7 +22,7 @@ namespace skyline::kernel::type {
|
||||
constexpr bool Valid() {
|
||||
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);
|
||||
|
||||
@ -31,6 +31,11 @@ namespace skyline::kernel::type {
|
||||
*/
|
||||
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 {
|
||||
return span(guest.ptr, guest.size);
|
||||
}
|
||||
|
@ -15,7 +15,7 @@ namespace skyline::kernel::type {
|
||||
* @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) {
|
||||
std::memcpy(kernel.ptr, ptr, size);
|
||||
std::memcpy(host.ptr, ptr, size);
|
||||
Map(ptr, size, permission);
|
||||
}
|
||||
};
|
||||
|
@ -23,7 +23,7 @@ namespace skyline::nce {
|
||||
if (svc) [[likely]] {
|
||||
TRACE_EVENT("kernel", perfetto::StaticString{svc.name});
|
||||
(svc.function)(state);
|
||||
} else [[unlikely]] {
|
||||
} else {
|
||||
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 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) {
|
||||
*ptr++ = SharedFontResult;
|
||||
*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);
|
||||
ptr = reinterpret_cast<u32 *>(reinterpret_cast<u8 *>(ptr) + font.length);
|
||||
|
@ -57,7 +57,7 @@ namespace skyline::service::timesrv::core {
|
||||
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) {
|
||||
SteadyClockTimePoint context{
|
||||
|
Loading…
Reference in New Issue
Block a user