mirror of
https://github.com/skyline-emu/skyline.git
synced 2024-11-23 01:19:16 +01:00
Improve KMemory + Fix Service Implementation Warning
* Improve KMemory Comments * Add parameter prefix 'p-' to `KPrivateMemory::UpdatePermission` * Fix the missing trailing double quote in missing service prints, this was due to `stringName` being padded with extra 0s
This commit is contained in:
parent
2edca83b8b
commit
1155394d58
@ -1017,7 +1017,7 @@ namespace skyline::kernel::svc {
|
|||||||
if (memory) {
|
if (memory) {
|
||||||
auto item{static_pointer_cast<type::KPrivateMemory>(memory->item)};
|
auto item{static_pointer_cast<type::KPrivateMemory>(memory->item)};
|
||||||
auto initialSize{item->size};
|
auto initialSize{item->size};
|
||||||
if (item->memState == memory::states::Heap) {
|
if (item->memoryState == memory::states::Heap) {
|
||||||
if (item->ptr >= pointer) {
|
if (item->ptr >= pointer) {
|
||||||
if (item->size <= size) {
|
if (item->size <= size) {
|
||||||
item->Resize(0);
|
item->Resize(0);
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
#include "KProcess.h"
|
#include "KProcess.h"
|
||||||
|
|
||||||
namespace skyline::kernel::type {
|
namespace skyline::kernel::type {
|
||||||
KPrivateMemory::KPrivateMemory(const DeviceState &state, u8 *ptr, size_t size, memory::Permission permission, memory::MemoryState memState) : ptr(ptr), size(size), permission(permission), memState(memState), KMemory(state, KType::KPrivateMemory) {
|
KPrivateMemory::KPrivateMemory(const DeviceState &state, u8 *ptr, size_t size, memory::Permission permission, memory::MemoryState memState) : ptr(ptr), size(size), permission(permission), memoryState(memState), KMemory(state, KType::KPrivateMemory) {
|
||||||
if (!state.process->memory.base.IsInside(ptr) || !state.process->memory.base.IsInside(ptr + 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);
|
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))
|
||||||
@ -40,7 +40,7 @@ namespace skyline::kernel::type {
|
|||||||
.ptr = ptr + size,
|
.ptr = ptr + size,
|
||||||
.size = nSize - size,
|
.size = nSize - size,
|
||||||
.permission = permission,
|
.permission = permission,
|
||||||
.state = memState,
|
.state = memoryState,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -60,22 +60,22 @@ namespace skyline::kernel::type {
|
|||||||
throw exception("An occurred while remapping private memory: {}", strerror(errno));
|
throw exception("An occurred while remapping private memory: {}", strerror(errno));
|
||||||
}
|
}
|
||||||
|
|
||||||
void KPrivateMemory::UpdatePermission(u8 *ptr, size_t size, memory::Permission permission) {
|
void KPrivateMemory::UpdatePermission(u8 *pPtr, size_t pSize, memory::Permission pPermission) {
|
||||||
ptr = std::clamp(ptr, this->ptr, this->ptr + this->size);
|
pPtr = std::clamp(pPtr, ptr, ptr + size);
|
||||||
size = std::min(size, static_cast<size_t>((this->ptr + this->size) - ptr));
|
pSize = std::min(pSize, static_cast<size_t>((ptr + size) - pPtr));
|
||||||
|
|
||||||
if (ptr && !util::PageAligned(ptr))
|
if (pPtr && !util::PageAligned(pPtr))
|
||||||
throw exception("KPrivateMemory permission updated with a non-page-aligned address: 0x{:X}", ptr);
|
throw exception("KPrivateMemory permission updated with a non-page-aligned address: 0x{:X}", pPtr);
|
||||||
|
|
||||||
// If a static code region has been mapped as writable it needs to be changed to mutable
|
// If a static code region has been mapped as writable it needs to be changed to mutable
|
||||||
if (memState == memory::states::CodeStatic && permission.w)
|
if (memoryState == memory::states::CodeStatic && pPermission.w)
|
||||||
memState = memory::states::CodeMutable;
|
memoryState = memory::states::CodeMutable;
|
||||||
|
|
||||||
state.process->memory.InsertChunk(ChunkDescriptor{
|
state.process->memory.InsertChunk(ChunkDescriptor{
|
||||||
.ptr = ptr,
|
.ptr = pPtr,
|
||||||
.size = size,
|
.size = pSize,
|
||||||
.permission = permission,
|
.permission = pPermission,
|
||||||
.state = memState,
|
.state = memoryState,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -8,13 +8,14 @@
|
|||||||
namespace skyline::kernel::type {
|
namespace skyline::kernel::type {
|
||||||
/**
|
/**
|
||||||
* @brief KPrivateMemory is used to map memory local to the guest process
|
* @brief KPrivateMemory is used to map memory local to the guest process
|
||||||
|
* @note This does not reflect a kernel object in Horizon OS, it is an abstraction which makes things simpler to manage in Skyline instead
|
||||||
*/
|
*/
|
||||||
class KPrivateMemory : public KMemory {
|
class KPrivateMemory : public KMemory {
|
||||||
public:
|
public:
|
||||||
u8 *ptr{};
|
u8 *ptr{};
|
||||||
size_t size{};
|
size_t size{};
|
||||||
memory::Permission permission;
|
memory::Permission permission;
|
||||||
memory::MemoryState memState;
|
memory::MemoryState memoryState;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param permission The permissions for the allocated memory (As reported to the application, host memory permissions aren't reflected by this)
|
* @param permission The permissions for the allocated memory (As reported to the application, host memory permissions aren't reflected by this)
|
||||||
@ -22,10 +23,14 @@ namespace skyline::kernel::type {
|
|||||||
*/
|
*/
|
||||||
KPrivateMemory(const DeviceState &state, u8 *ptr, size_t size, memory::Permission permission, memory::MemoryState memState);
|
KPrivateMemory(const DeviceState &state, u8 *ptr, size_t size, memory::Permission permission, memory::MemoryState memState);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @note There is no check regarding if any expansions will cause the memory mapping to leak into other mappings
|
||||||
|
* @note Any extensions will have the same permissions and memory state as the initial mapping as opposed to extending the end
|
||||||
|
*/
|
||||||
void Resize(size_t size);
|
void Resize(size_t size);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @note Only contents of any overlapping regions will be retained
|
* @note This does not copy over anything, only contents of any overlapping regions will be retained
|
||||||
*/
|
*/
|
||||||
void Remap(u8 *ptr, size_t size);
|
void Remap(u8 *ptr, size_t size);
|
||||||
|
|
||||||
@ -33,7 +38,7 @@ namespace skyline::kernel::type {
|
|||||||
return span(ptr, size);
|
return span(ptr, size);
|
||||||
}
|
}
|
||||||
|
|
||||||
void UpdatePermission(u8 *ptr, size_t size, memory::Permission permission) override;
|
void UpdatePermission(u8 *pPtr, size_t pSize, memory::Permission pPermission) override;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief The destructor of private memory, it deallocates the memory
|
* @brief The destructor of private memory, it deallocates the memory
|
||||||
|
@ -8,14 +8,15 @@
|
|||||||
#include "KProcess.h"
|
#include "KProcess.h"
|
||||||
|
|
||||||
namespace skyline::kernel::type {
|
namespace skyline::kernel::type {
|
||||||
KSharedMemory::KSharedMemory(const DeviceState &state, size_t size, memory::MemoryState memState, KType type) : initialState(memState), KMemory(state, type) {
|
KSharedMemory::KSharedMemory(const DeviceState &state, size_t size, memory::MemoryState memState, KType type) : memoryState(memState), KMemory(state, type) {
|
||||||
fd = ASharedMemory_create("KSharedMemory", size);
|
fd = ASharedMemory_create("KSharedMemory", size);
|
||||||
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));
|
kernel.ptr = reinterpret_cast<u8 *>(mmap(nullptr, size, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_SHARED, fd, 0));
|
||||||
if (kernel.ptr == MAP_FAILED)
|
if (kernel.ptr == MAP_FAILED)
|
||||||
throw exception("An occurred while mapping shared memory: {}", strerror(errno));
|
[[unlikely]]
|
||||||
|
throw exception("An occurred while mapping shared memory: {}", strerror(errno));
|
||||||
|
|
||||||
kernel.size = size;
|
kernel.size = size;
|
||||||
}
|
}
|
||||||
@ -28,14 +29,15 @@ namespace skyline::kernel::type {
|
|||||||
|
|
||||||
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)
|
||||||
throw exception("An error occurred while mapping shared memory in guest");
|
[[unlikely]]
|
||||||
|
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{
|
||||||
.ptr = guest.ptr,
|
.ptr = guest.ptr,
|
||||||
.size = size,
|
.size = size,
|
||||||
.permission = permission,
|
.permission = permission,
|
||||||
.state = initialState,
|
.state = memoryState,
|
||||||
});
|
});
|
||||||
|
|
||||||
return guest.ptr;
|
return guest.ptr;
|
||||||
@ -47,15 +49,15 @@ 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)
|
||||||
throw exception("An error occurred while updating shared memory's permissions in guest");
|
[[unlikely]]
|
||||||
|
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,
|
||||||
.size = size,
|
.size = size,
|
||||||
.permission = permission,
|
.permission = permission,
|
||||||
.state = initialState,
|
.state = memoryState,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -65,7 +67,7 @@ namespace skyline::kernel::type {
|
|||||||
munmap(kernel.ptr, kernel.size);
|
munmap(kernel.ptr, kernel.size);
|
||||||
|
|
||||||
if (state.process && guest.Valid()) {
|
if (state.process && guest.Valid()) {
|
||||||
mmap(guest.ptr, guest.size, PROT_NONE, MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
|
mmap(guest.ptr, guest.size, PROT_NONE, MAP_ANONYMOUS | MAP_PRIVATE, -1, 0); // As this is the destructor, we cannot throw on this failing
|
||||||
state.process->memory.InsertChunk(ChunkDescriptor{
|
state.process->memory.InsertChunk(ChunkDescriptor{
|
||||||
.ptr = guest.ptr,
|
.ptr = guest.ptr,
|
||||||
.size = guest.size,
|
.size = guest.size,
|
||||||
|
@ -7,12 +7,12 @@
|
|||||||
|
|
||||||
namespace skyline::kernel::type {
|
namespace skyline::kernel::type {
|
||||||
/**
|
/**
|
||||||
* @brief KSharedMemory is used to retain two mappings of the same underlying memory, allowing persistence of the memory
|
* @brief KSharedMemory is used to retain two mappings of the same underlying memory, allowing sharing memory between two processes
|
||||||
*/
|
*/
|
||||||
class KSharedMemory : public KMemory {
|
class KSharedMemory : public KMemory {
|
||||||
private:
|
private:
|
||||||
int fd; //!< A file descriptor to the underlying shared memory
|
int fd; //!< A file descriptor to the underlying shared memory
|
||||||
memory::MemoryState initialState;
|
memory::MemoryState memoryState; //!< The state of the memory as supplied initially, this is retained for any mappings
|
||||||
|
|
||||||
public:
|
public:
|
||||||
struct MapInfo {
|
struct MapInfo {
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
|
|
||||||
namespace skyline::kernel::type {
|
namespace skyline::kernel::type {
|
||||||
/**
|
/**
|
||||||
* @brief KTransferMemory is used to transfer memory from one application to another on HOS, we emulate this abstraction using KSharedMemory as it's functionally indistinguishable for the guest and allows access from the kernel regardless of if it's mapped on the guest
|
* @brief KTransferMemory is used to transfer memory from one application to another on HOS, we emulate this abstraction using KSharedMemory as it's essentially the same with the main difference being that KSharedMemory is allocated by the kernel while KTransferMemory is created from memory that's been allocated by the guest beforehand
|
||||||
*/
|
*/
|
||||||
class KTransferMemory : public KSharedMemory {
|
class KTransferMemory : public KSharedMemory {
|
||||||
public:
|
public:
|
||||||
|
@ -20,7 +20,7 @@ namespace skyline::service::sm {
|
|||||||
manager.NewService(name, session, response);
|
manager.NewService(name, session, response);
|
||||||
return {};
|
return {};
|
||||||
} catch (std::out_of_range &) {
|
} catch (std::out_of_range &) {
|
||||||
std::string_view stringName(reinterpret_cast<char *>(&name), sizeof(u64));
|
std::string_view stringName(span(reinterpret_cast<char *>(&name), sizeof(u64)).as_string(true));
|
||||||
state.logger->Warn("Service has not been implemented: \"{}\"", stringName);
|
state.logger->Warn("Service has not been implemented: \"{}\"", stringName);
|
||||||
return result::InvalidServiceName;
|
return result::InvalidServiceName;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user