mirror of
https://github.com/RGBCube/serenity
synced 2025-05-18 20:25:07 +00:00
UserspaceEmulator: Add support for shared buffers (shbuf)
We track these separately from regular mmap() regions, as they have slightly different behaviors.
This commit is contained in:
parent
0ce4d3e942
commit
2da44dba44
7 changed files with 312 additions and 13 deletions
|
@ -1,6 +1,7 @@
|
||||||
set(SOURCES
|
set(SOURCES
|
||||||
Emulator.cpp
|
Emulator.cpp
|
||||||
MmapRegion.cpp
|
MmapRegion.cpp
|
||||||
|
SharedBufferRegion.cpp
|
||||||
SimpleRegion.cpp
|
SimpleRegion.cpp
|
||||||
SoftCPU.cpp
|
SoftCPU.cpp
|
||||||
SoftMMU.cpp
|
SoftMMU.cpp
|
||||||
|
|
|
@ -26,12 +26,14 @@
|
||||||
|
|
||||||
#include "Emulator.h"
|
#include "Emulator.h"
|
||||||
#include "MmapRegion.h"
|
#include "MmapRegion.h"
|
||||||
|
#include "SharedBufferRegion.h"
|
||||||
#include "SimpleRegion.h"
|
#include "SimpleRegion.h"
|
||||||
#include "SoftCPU.h"
|
#include "SoftCPU.h"
|
||||||
#include <AK/LexicalPath.h>
|
#include <AK/LexicalPath.h>
|
||||||
#include <AK/LogStream.h>
|
#include <AK/LogStream.h>
|
||||||
#include <Kernel/API/Syscall.h>
|
#include <Kernel/API/Syscall.h>
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
|
#include <serenity.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <sys/mman.h>
|
#include <sys/mman.h>
|
||||||
|
@ -194,6 +196,20 @@ u32 Emulator::virt_syscall(u32 function, u32 arg1, u32 arg2, u32 arg3)
|
||||||
dbgprintf("Syscall: %s (%x)\n", Syscall::to_string((Syscall::Function)function), function);
|
dbgprintf("Syscall: %s (%x)\n", Syscall::to_string((Syscall::Function)function), function);
|
||||||
#endif
|
#endif
|
||||||
switch (function) {
|
switch (function) {
|
||||||
|
case SC_shbuf_create:
|
||||||
|
return virt$shbuf_create(arg1, arg2);
|
||||||
|
case SC_shbuf_allow_pid:
|
||||||
|
return virt$shbuf_allow_pid(arg1, arg2);
|
||||||
|
case SC_shbuf_allow_all:
|
||||||
|
return virt$shbuf_allow_all(arg1);
|
||||||
|
case SC_shbuf_get:
|
||||||
|
return virt$shbuf_get(arg1, arg2);
|
||||||
|
case SC_shbuf_release:
|
||||||
|
return virt$shbuf_release(arg1);
|
||||||
|
case SC_shbuf_seal:
|
||||||
|
return virt$shbuf_seal(arg1);
|
||||||
|
case SC_shbuf_set_volatile:
|
||||||
|
return virt$shbuf_set_volatile(arg1, arg2);
|
||||||
case SC_mmap:
|
case SC_mmap:
|
||||||
return virt$mmap(arg1);
|
return virt$mmap(arg1);
|
||||||
case SC_munmap:
|
case SC_munmap:
|
||||||
|
@ -260,6 +276,8 @@ u32 Emulator::virt_syscall(u32 function, u32 arg1, u32 arg2, u32 arg3)
|
||||||
return virt$recvfrom(arg1);
|
return virt$recvfrom(arg1);
|
||||||
case SC_kill:
|
case SC_kill:
|
||||||
return virt$kill(arg1, arg2);
|
return virt$kill(arg1, arg2);
|
||||||
|
case SC_set_mmap_name:
|
||||||
|
return virt$set_mmap_name(arg1);
|
||||||
case SC_exit:
|
case SC_exit:
|
||||||
virt$exit((int)arg1);
|
virt$exit((int)arg1);
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -270,6 +288,69 @@ u32 Emulator::virt_syscall(u32 function, u32 arg1, u32 arg2, u32 arg3)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int Emulator::virt$shbuf_create(int size, FlatPtr buffer)
|
||||||
|
{
|
||||||
|
u8* host_data = nullptr;
|
||||||
|
int shbuf_id = syscall(SC_shbuf_create, size, &host_data);
|
||||||
|
if (shbuf_id < 0)
|
||||||
|
return -errno;
|
||||||
|
FlatPtr address = allocate_vm(size, PAGE_SIZE);
|
||||||
|
auto region = SharedBufferRegion::create_with_shbuf_id(address, size, shbuf_id, host_data);
|
||||||
|
m_mmu.add_region(move(region));
|
||||||
|
m_mmu.copy_to_vm(buffer, &address, sizeof(address));
|
||||||
|
return shbuf_id;
|
||||||
|
}
|
||||||
|
|
||||||
|
FlatPtr Emulator::virt$shbuf_get(int shbuf_id, FlatPtr size_ptr)
|
||||||
|
{
|
||||||
|
size_t host_size = 0;
|
||||||
|
void* host_data = (void*)syscall(SC_shbuf_get, shbuf_id, &host_size);
|
||||||
|
if (host_data == (void*)-1)
|
||||||
|
return -errno;
|
||||||
|
FlatPtr address = allocate_vm(host_size, PAGE_SIZE);
|
||||||
|
auto region = SharedBufferRegion::create_with_shbuf_id(address, host_size, shbuf_id, (u8*)host_data);
|
||||||
|
m_mmu.add_region(move(region));
|
||||||
|
m_mmu.copy_to_vm(size_ptr, &host_size, sizeof(host_size));
|
||||||
|
return address;
|
||||||
|
}
|
||||||
|
|
||||||
|
int Emulator::virt$shbuf_allow_pid(int shbuf_id, pid_t peer_pid)
|
||||||
|
{
|
||||||
|
auto* region = m_mmu.shbuf_region(shbuf_id);
|
||||||
|
ASSERT(region);
|
||||||
|
return region->allow_pid(peer_pid);
|
||||||
|
}
|
||||||
|
|
||||||
|
int Emulator::virt$shbuf_allow_all(int shbuf_id)
|
||||||
|
{
|
||||||
|
auto* region = m_mmu.shbuf_region(shbuf_id);
|
||||||
|
ASSERT(region);
|
||||||
|
return region->allow_all();
|
||||||
|
}
|
||||||
|
|
||||||
|
int Emulator::virt$shbuf_release(int shbuf_id)
|
||||||
|
{
|
||||||
|
auto* region = m_mmu.shbuf_region(shbuf_id);
|
||||||
|
ASSERT(region);
|
||||||
|
auto rc = region->release();
|
||||||
|
m_mmu.remove_region(*region);
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
int Emulator::virt$shbuf_seal(int shbuf_id)
|
||||||
|
{
|
||||||
|
auto* region = m_mmu.shbuf_region(shbuf_id);
|
||||||
|
ASSERT(region);
|
||||||
|
return region->seal();
|
||||||
|
}
|
||||||
|
|
||||||
|
int Emulator::virt$shbuf_set_volatile(int shbuf_id, bool is_volatile)
|
||||||
|
{
|
||||||
|
auto* region = m_mmu.shbuf_region(shbuf_id);
|
||||||
|
ASSERT(region);
|
||||||
|
return region->set_volatile(is_volatile);
|
||||||
|
}
|
||||||
|
|
||||||
int Emulator::virt$fstat(int fd, FlatPtr statbuf)
|
int Emulator::virt$fstat(int fd, FlatPtr statbuf)
|
||||||
{
|
{
|
||||||
struct stat local_statbuf;
|
struct stat local_statbuf;
|
||||||
|
@ -337,6 +418,12 @@ int Emulator::virt$kill(pid_t pid, int signal)
|
||||||
return syscall(SC_kill, pid, signal);
|
return syscall(SC_kill, pid, signal);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int Emulator::virt$set_mmap_name(FlatPtr)
|
||||||
|
{
|
||||||
|
// FIXME: Implement.
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
int Emulator::virt$get_process_name(FlatPtr buffer, int size)
|
int Emulator::virt$get_process_name(FlatPtr buffer, int size)
|
||||||
{
|
{
|
||||||
if (size < 9)
|
if (size < 9)
|
||||||
|
@ -503,6 +590,24 @@ u32 Emulator::virt$munmap(FlatPtr address, u32 size)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
FlatPtr Emulator::allocate_vm(size_t size, size_t alignment)
|
||||||
|
{
|
||||||
|
// FIXME: Write a proper VM allocator
|
||||||
|
static FlatPtr next_address = 0x30000000;
|
||||||
|
|
||||||
|
FlatPtr final_address;
|
||||||
|
|
||||||
|
if (alignment) {
|
||||||
|
// FIXME: What if alignment is not a power of 2?
|
||||||
|
final_address = round_up_to_power_of_two(next_address, alignment);
|
||||||
|
} else {
|
||||||
|
final_address = next_address;
|
||||||
|
}
|
||||||
|
|
||||||
|
next_address = final_address + size;
|
||||||
|
return final_address;
|
||||||
|
}
|
||||||
|
|
||||||
u32 Emulator::virt$mmap(u32 params_addr)
|
u32 Emulator::virt$mmap(u32 params_addr)
|
||||||
{
|
{
|
||||||
Syscall::SC_mmap_params params;
|
Syscall::SC_mmap_params params;
|
||||||
|
@ -510,20 +615,8 @@ u32 Emulator::virt$mmap(u32 params_addr)
|
||||||
|
|
||||||
ASSERT(params.addr == 0);
|
ASSERT(params.addr == 0);
|
||||||
|
|
||||||
// FIXME: Write a proper VM allocator
|
|
||||||
static u32 next_address = 0x30000000;
|
|
||||||
|
|
||||||
u32 final_address = 0;
|
|
||||||
u32 final_size = round_up_to_power_of_two(params.size, PAGE_SIZE);
|
u32 final_size = round_up_to_power_of_two(params.size, PAGE_SIZE);
|
||||||
|
u32 final_address = allocate_vm(final_size, params.alignment);
|
||||||
if (params.alignment) {
|
|
||||||
// FIXME: What if alignment is not a power of 2?
|
|
||||||
final_address = round_up_to_power_of_two(next_address, params.alignment);
|
|
||||||
} else {
|
|
||||||
final_address = next_address;
|
|
||||||
}
|
|
||||||
|
|
||||||
next_address = final_address + final_size;
|
|
||||||
|
|
||||||
if (params.flags & MAP_ANONYMOUS)
|
if (params.flags & MAP_ANONYMOUS)
|
||||||
mmu().add_region(MmapRegion::create_anonymous(final_address, final_size, params.prot));
|
mmu().add_region(MmapRegion::create_anonymous(final_address, final_size, params.prot));
|
||||||
|
|
|
@ -57,6 +57,13 @@ private:
|
||||||
|
|
||||||
void setup_stack(const Vector<String>& arguments);
|
void setup_stack(const Vector<String>& arguments);
|
||||||
|
|
||||||
|
int virt$shbuf_create(int size, FlatPtr buffer);
|
||||||
|
int virt$shbuf_allow_pid(int, pid_t peer_pid);
|
||||||
|
int virt$shbuf_allow_all(int);
|
||||||
|
FlatPtr virt$shbuf_get(int shbuf_id, FlatPtr size);
|
||||||
|
int virt$shbuf_release(int shbuf_id);
|
||||||
|
int virt$shbuf_seal(int shbuf_id);
|
||||||
|
int virt$shbuf_set_volatile(int shbuf_id, bool);
|
||||||
u32 virt$mmap(u32);
|
u32 virt$mmap(u32);
|
||||||
u32 virt$munmap(FlatPtr address, u32 size);
|
u32 virt$munmap(FlatPtr address, u32 size);
|
||||||
u32 virt$gettid();
|
u32 virt$gettid();
|
||||||
|
@ -75,6 +82,7 @@ private:
|
||||||
int virt$mkdir(FlatPtr path, size_t path_length, mode_t mode);
|
int virt$mkdir(FlatPtr path, size_t path_length, mode_t mode);
|
||||||
int virt$unlink(FlatPtr path, size_t path_length);
|
int virt$unlink(FlatPtr path, size_t path_length);
|
||||||
int virt$get_process_name(FlatPtr buffer, int size);
|
int virt$get_process_name(FlatPtr buffer, int size);
|
||||||
|
int virt$set_mmap_name(FlatPtr);
|
||||||
int virt$dbgputstr(FlatPtr characters, int length);
|
int virt$dbgputstr(FlatPtr characters, int length);
|
||||||
int virt$dbgputch(char);
|
int virt$dbgputch(char);
|
||||||
int virt$fchmod(int, mode_t);
|
int virt$fchmod(int, mode_t);
|
||||||
|
@ -92,6 +100,8 @@ private:
|
||||||
int virt$connect(int sockfd, FlatPtr address, socklen_t address_size);
|
int virt$connect(int sockfd, FlatPtr address, socklen_t address_size);
|
||||||
void virt$exit(int);
|
void virt$exit(int);
|
||||||
|
|
||||||
|
FlatPtr allocate_vm(size_t size, size_t alignment);
|
||||||
|
|
||||||
bool m_shutdown { false };
|
bool m_shutdown { false };
|
||||||
int m_exit_status { 0 };
|
int m_exit_status { 0 };
|
||||||
};
|
};
|
||||||
|
|
112
DevTools/UserspaceEmulator/SharedBufferRegion.cpp
Normal file
112
DevTools/UserspaceEmulator/SharedBufferRegion.cpp
Normal file
|
@ -0,0 +1,112 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2020, Andreas Kling <kling@serenityos.org>
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions are met:
|
||||||
|
*
|
||||||
|
* 1. Redistributions of source code must retain the above copyright notice, this
|
||||||
|
* list of conditions and the following disclaimer.
|
||||||
|
*
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||||
|
* this list of conditions and the following disclaimer in the documentation
|
||||||
|
* and/or other materials provided with the distribution.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||||
|
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||||
|
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||||
|
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||||
|
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||||
|
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||||
|
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "SharedBufferRegion.h"
|
||||||
|
#include "Emulator.h"
|
||||||
|
#include <Kernel/API/Syscall.h>
|
||||||
|
#include <serenity.h>
|
||||||
|
#include <sys/mman.h>
|
||||||
|
|
||||||
|
namespace UserspaceEmulator {
|
||||||
|
|
||||||
|
NonnullOwnPtr<SharedBufferRegion> SharedBufferRegion::create_with_shbuf_id(u32 base, u32 size, int shbuf_id, u8* host_data)
|
||||||
|
{
|
||||||
|
return adopt_own(*new SharedBufferRegion(base, size, shbuf_id, host_data));
|
||||||
|
}
|
||||||
|
|
||||||
|
SharedBufferRegion::SharedBufferRegion(u32 base, u32 size, int shbuf_id, u8* host_data)
|
||||||
|
: Region(base, size)
|
||||||
|
, m_data(host_data)
|
||||||
|
, m_shbuf_id(shbuf_id)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
SharedBufferRegion::~SharedBufferRegion()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
u8 SharedBufferRegion::read8(FlatPtr offset)
|
||||||
|
{
|
||||||
|
ASSERT(offset < size());
|
||||||
|
return *reinterpret_cast<const u8*>(m_data + offset);
|
||||||
|
}
|
||||||
|
|
||||||
|
u16 SharedBufferRegion::read16(u32 offset)
|
||||||
|
{
|
||||||
|
ASSERT(offset + 1 < size());
|
||||||
|
return *reinterpret_cast<const u16*>(m_data + offset);
|
||||||
|
}
|
||||||
|
|
||||||
|
u32 SharedBufferRegion::read32(u32 offset)
|
||||||
|
{
|
||||||
|
ASSERT(offset + 3 < size());
|
||||||
|
return *reinterpret_cast<const u32*>(m_data + offset);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SharedBufferRegion::write8(u32 offset, u8 value)
|
||||||
|
{
|
||||||
|
ASSERT(offset < size());
|
||||||
|
*reinterpret_cast<u8*>(m_data + offset) = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SharedBufferRegion::write16(u32 offset, u16 value)
|
||||||
|
{
|
||||||
|
ASSERT(offset + 1 < size());
|
||||||
|
*reinterpret_cast<u16*>(m_data + offset) = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SharedBufferRegion::write32(u32 offset, u32 value)
|
||||||
|
{
|
||||||
|
ASSERT(offset + 3 < size());
|
||||||
|
*reinterpret_cast<u32*>(m_data + offset) = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
int SharedBufferRegion::allow_all()
|
||||||
|
{
|
||||||
|
return syscall(SC_shbuf_allow_all, m_shbuf_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
int SharedBufferRegion::allow_pid(pid_t pid)
|
||||||
|
{
|
||||||
|
return syscall(SC_shbuf_allow_pid, m_shbuf_id, pid);
|
||||||
|
}
|
||||||
|
|
||||||
|
int SharedBufferRegion::seal()
|
||||||
|
{
|
||||||
|
return syscall(SC_shbuf_seal, m_shbuf_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
int SharedBufferRegion::release()
|
||||||
|
{
|
||||||
|
return syscall(SC_shbuf_release, m_shbuf_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
int SharedBufferRegion::set_volatile(bool is_volatile)
|
||||||
|
{
|
||||||
|
return syscall(SC_shbuf_set_volatile, m_shbuf_id, is_volatile);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
66
DevTools/UserspaceEmulator/SharedBufferRegion.h
Normal file
66
DevTools/UserspaceEmulator/SharedBufferRegion.h
Normal file
|
@ -0,0 +1,66 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2020, Andreas Kling <kling@serenityos.org>
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions are met:
|
||||||
|
*
|
||||||
|
* 1. Redistributions of source code must retain the above copyright notice, this
|
||||||
|
* list of conditions and the following disclaimer.
|
||||||
|
*
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||||
|
* this list of conditions and the following disclaimer in the documentation
|
||||||
|
* and/or other materials provided with the distribution.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||||
|
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||||
|
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||||
|
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||||
|
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||||
|
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||||
|
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "SoftMMU.h"
|
||||||
|
#include <sys/mman.h>
|
||||||
|
|
||||||
|
namespace UserspaceEmulator {
|
||||||
|
|
||||||
|
class SharedBufferRegion final : public SoftMMU::Region {
|
||||||
|
public:
|
||||||
|
static NonnullOwnPtr<SharedBufferRegion> create_with_shbuf_id(u32 base, u32 size, int shbuf_id, u8* shbuf_data);
|
||||||
|
virtual ~SharedBufferRegion() override;
|
||||||
|
|
||||||
|
virtual u8 read8(u32 offset) override;
|
||||||
|
virtual u16 read16(u32 offset) override;
|
||||||
|
virtual u32 read32(u32 offset) override;
|
||||||
|
|
||||||
|
virtual void write8(u32 offset, u8 value) override;
|
||||||
|
virtual void write16(u32 offset, u16 value) override;
|
||||||
|
virtual void write32(u32 offset, u32 value) override;
|
||||||
|
|
||||||
|
u8* data() { return m_data; }
|
||||||
|
|
||||||
|
bool is_shared_buffer() const override { return true; }
|
||||||
|
|
||||||
|
int shbuf_id() const { return m_shbuf_id; }
|
||||||
|
|
||||||
|
int allow_all();
|
||||||
|
int allow_pid(pid_t);
|
||||||
|
int seal();
|
||||||
|
int release();
|
||||||
|
int set_volatile(bool);
|
||||||
|
|
||||||
|
private:
|
||||||
|
SharedBufferRegion(u32 base, u32 size, int shbuf_id, u8* shbuf_data);
|
||||||
|
|
||||||
|
u8* m_data { nullptr };
|
||||||
|
int m_shbuf_id { 0 };
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
|
@ -25,6 +25,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "SoftMMU.h"
|
#include "SoftMMU.h"
|
||||||
|
#include "SharedBufferRegion.h"
|
||||||
#include <AK/ByteBuffer.h>
|
#include <AK/ByteBuffer.h>
|
||||||
|
|
||||||
namespace UserspaceEmulator {
|
namespace UserspaceEmulator {
|
||||||
|
@ -45,11 +46,15 @@ void SoftMMU::add_region(NonnullOwnPtr<Region> region)
|
||||||
{
|
{
|
||||||
ASSERT(!find_region({ 0x20, region->base() }));
|
ASSERT(!find_region({ 0x20, region->base() }));
|
||||||
// FIXME: More sanity checks pls
|
// FIXME: More sanity checks pls
|
||||||
|
if (region->is_shared_buffer())
|
||||||
|
m_shbuf_regions.set(static_cast<SharedBufferRegion*>(region.ptr())->shbuf_id(), region.ptr());
|
||||||
m_regions.append(move(region));
|
m_regions.append(move(region));
|
||||||
}
|
}
|
||||||
|
|
||||||
void SoftMMU::remove_region(Region& region)
|
void SoftMMU::remove_region(Region& region)
|
||||||
{
|
{
|
||||||
|
if (region.is_shared_buffer())
|
||||||
|
m_shbuf_regions.remove(static_cast<SharedBufferRegion&>(region).shbuf_id());
|
||||||
m_regions.remove_first_matching([&](auto& entry) { return entry.ptr() == ®ion; });
|
m_regions.remove_first_matching([&](auto& entry) { return entry.ptr() == ®ion; });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -144,4 +149,9 @@ ByteBuffer SoftMMU::copy_buffer_from_vm(const FlatPtr source, size_t size)
|
||||||
return buffer;
|
return buffer;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SharedBufferRegion* SoftMMU::shbuf_region(int shbuf_id)
|
||||||
|
{
|
||||||
|
return (SharedBufferRegion*)m_shbuf_regions.get(shbuf_id).value_or(nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -26,6 +26,7 @@
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <AK/HashMap.h>
|
||||||
#include <AK/NonnullOwnPtrVector.h>
|
#include <AK/NonnullOwnPtrVector.h>
|
||||||
#include <AK/OwnPtr.h>
|
#include <AK/OwnPtr.h>
|
||||||
#include <AK/Types.h>
|
#include <AK/Types.h>
|
||||||
|
@ -33,6 +34,8 @@
|
||||||
|
|
||||||
namespace UserspaceEmulator {
|
namespace UserspaceEmulator {
|
||||||
|
|
||||||
|
class SharedBufferRegion;
|
||||||
|
|
||||||
class SoftMMU {
|
class SoftMMU {
|
||||||
public:
|
public:
|
||||||
class Region {
|
class Region {
|
||||||
|
@ -54,6 +57,7 @@ public:
|
||||||
virtual u32 read32(u32 offset) = 0;
|
virtual u32 read32(u32 offset) = 0;
|
||||||
|
|
||||||
virtual u8* cacheable_ptr([[maybe_unused]] u32 offset) { return nullptr; }
|
virtual u8* cacheable_ptr([[maybe_unused]] u32 offset) { return nullptr; }
|
||||||
|
virtual bool is_shared_buffer() const { return false; }
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
Region(u32 base, u32 size)
|
Region(u32 base, u32 size)
|
||||||
|
@ -86,9 +90,12 @@ public:
|
||||||
void copy_from_vm(void* destination, const FlatPtr source, size_t);
|
void copy_from_vm(void* destination, const FlatPtr source, size_t);
|
||||||
ByteBuffer copy_buffer_from_vm(const FlatPtr source, size_t);
|
ByteBuffer copy_buffer_from_vm(const FlatPtr source, size_t);
|
||||||
|
|
||||||
|
SharedBufferRegion* shbuf_region(int shbuf_id);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
OwnPtr<Region> m_tls_region;
|
OwnPtr<Region> m_tls_region;
|
||||||
NonnullOwnPtrVector<Region> m_regions;
|
NonnullOwnPtrVector<Region> m_regions;
|
||||||
|
HashMap<int, Region*> m_shbuf_regions;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue