mirror of
https://github.com/genodelabs/genode.git
synced 2024-12-18 21:27:56 +00:00
base: extend attach of vm_session
by offset, size, writeable and executable parameter Issue #3111
This commit is contained in:
parent
17fda73ca1
commit
393643515c
@ -72,7 +72,7 @@ class Genode::Vm_session_component
|
||||
Cap_mapping _task_vcpu { true };
|
||||
unsigned _id_alloc { 0 };
|
||||
|
||||
void _attach_vm_memory(Dataspace_component &, addr_t, bool, bool);
|
||||
void _attach_vm_memory(Dataspace_component &, addr_t, Attach_attr);
|
||||
void _detach_vm_memory(addr_t, size_t);
|
||||
|
||||
protected:
|
||||
@ -105,7 +105,7 @@ class Genode::Vm_session_component
|
||||
void _exception_handler(Signal_context_capability, Vcpu_id) { }
|
||||
void _run(Vcpu_id) { }
|
||||
void _pause(Vcpu_id) { }
|
||||
void attach(Dataspace_capability, addr_t) override;
|
||||
void attach(Dataspace_capability, addr_t, Attach_attr) override;
|
||||
void attach_pic(addr_t) override { }
|
||||
void detach(addr_t, size_t) override;
|
||||
void _create_vcpu(Thread_capability);
|
||||
|
@ -165,22 +165,21 @@ Dataspace_capability Vm_session_component::_cpu_state(Vcpu_id const vcpu_id)
|
||||
|
||||
void Vm_session_component::_attach_vm_memory(Dataspace_component &dsc,
|
||||
addr_t const guest_phys,
|
||||
bool const executable,
|
||||
bool const writeable)
|
||||
Attach_attr const attribute)
|
||||
{
|
||||
Flexpage_iterator flex(dsc.phys_addr(), dsc.size(),
|
||||
guest_phys, dsc.size(), guest_phys);
|
||||
Flexpage_iterator flex(dsc.phys_addr() + attribute.offset, attribute.size,
|
||||
guest_phys, attribute.size, guest_phys);
|
||||
|
||||
using namespace Fiasco;
|
||||
|
||||
uint8_t flags = L4_FPAGE_RO;
|
||||
if (dsc.writable() && writeable)
|
||||
if (executable)
|
||||
if (dsc.writable() && attribute.writeable)
|
||||
if (attribute.executable)
|
||||
flags = L4_FPAGE_RWX;
|
||||
else
|
||||
flags = L4_FPAGE_RW;
|
||||
else
|
||||
if (executable)
|
||||
if (attribute.executable)
|
||||
flags = L4_FPAGE_RX;
|
||||
|
||||
Flexpage page = flex.page();
|
||||
|
@ -80,7 +80,7 @@ class Genode::Vm_session_component
|
||||
void _run(Vcpu_id);
|
||||
void _pause(Vcpu_id);
|
||||
|
||||
void attach(Dataspace_capability, addr_t /* vm_addr */) override {
|
||||
void attach(Dataspace_capability, addr_t, Attach_attr) override {
|
||||
warning("Not implemented for TrustZone case"); }
|
||||
|
||||
void attach_pic(addr_t /* vm_addr */) override {
|
||||
|
@ -55,10 +55,9 @@ void Vm_session_component::_attach(addr_t phys_addr, addr_t vm_addr, size_t size
|
||||
|
||||
void Vm_session_component::_attach_vm_memory(Dataspace_component &dsc,
|
||||
addr_t const vm_addr,
|
||||
bool const /* executable */,
|
||||
bool const /* writeable */)
|
||||
Attach_attr const attribute)
|
||||
{
|
||||
_attach(dsc.phys_addr(), vm_addr, dsc.size());
|
||||
_attach(dsc.phys_addr() + attribute.offset, vm_addr, attribute.size);
|
||||
}
|
||||
|
||||
|
||||
|
@ -71,7 +71,7 @@ class Genode::Vm_session_component
|
||||
void * _alloc_table();
|
||||
void _attach(addr_t phys_addr, addr_t vm_addr, size_t size);
|
||||
|
||||
void _attach_vm_memory(Dataspace_component &, addr_t, bool, bool);
|
||||
void _attach_vm_memory(Dataspace_component &, addr_t, Attach_attr);
|
||||
void _detach_vm_memory(addr_t, size_t);
|
||||
|
||||
protected:
|
||||
@ -104,7 +104,7 @@ class Genode::Vm_session_component
|
||||
void _exception_handler(Signal_context_capability, Vcpu_id);
|
||||
void _run(Vcpu_id);
|
||||
void _pause(Vcpu_id);
|
||||
void attach(Dataspace_capability, addr_t) override;
|
||||
void attach(Dataspace_capability, addr_t, Attach_attr) override;
|
||||
void attach_pic(addr_t) override;
|
||||
void detach(addr_t, size_t) override;
|
||||
void _create_vcpu(Thread_capability) {}
|
||||
|
@ -83,7 +83,7 @@ class Genode::Vm_session_component
|
||||
Kernel::pause_vm(kernel_object());
|
||||
}
|
||||
|
||||
void attach(Dataspace_capability, addr_t) override { }
|
||||
void attach(Dataspace_capability, addr_t, Attach_attr) override { }
|
||||
void attach_pic(addr_t) override { }
|
||||
void detach(addr_t, size_t) override { }
|
||||
void _create_vcpu(Thread_capability) { }
|
||||
|
@ -93,7 +93,7 @@ class Genode::Vm_session_component
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void _attach_vm_memory(Dataspace_component &, addr_t, bool, bool);
|
||||
void _attach_vm_memory(Dataspace_component &, addr_t, Attach_attr);
|
||||
void _detach_vm_memory(addr_t, size_t);
|
||||
|
||||
protected:
|
||||
@ -126,7 +126,7 @@ class Genode::Vm_session_component
|
||||
void _exception_handler(Signal_context_capability, Vcpu_id);
|
||||
void _run(Vcpu_id);
|
||||
void _pause(Vcpu_id) { }
|
||||
void attach(Dataspace_capability, addr_t) override;
|
||||
void attach(Dataspace_capability, addr_t, Attach_attr) override;
|
||||
void attach_pic(addr_t) override {}
|
||||
void detach(addr_t, size_t) override;
|
||||
void _create_vcpu(Thread_capability);
|
||||
|
@ -331,20 +331,20 @@ Vm_session_component::~Vm_session_component()
|
||||
|
||||
void Vm_session_component::_attach_vm_memory(Dataspace_component &dsc,
|
||||
addr_t const guest_phys,
|
||||
bool const executable,
|
||||
bool const writeable)
|
||||
Attach_attr const attribute)
|
||||
{
|
||||
using Nova::Utcb;
|
||||
Utcb & utcb = *reinterpret_cast<Utcb *>(Thread::myself()->utcb());
|
||||
addr_t const src_pd = platform_specific().core_pd_sel();
|
||||
|
||||
Flexpage_iterator flex(dsc.phys_addr(), dsc.size(),
|
||||
guest_phys, dsc.size(), guest_phys);
|
||||
Flexpage_iterator flex(dsc.phys_addr() + attribute.offset, attribute.size,
|
||||
guest_phys, attribute.size, guest_phys);
|
||||
|
||||
Flexpage page = flex.page();
|
||||
while (page.valid()) {
|
||||
Nova::Rights const map_rights (true, dsc.writable() && writeable,
|
||||
executable);
|
||||
Nova::Rights const map_rights (true,
|
||||
dsc.writable() && attribute.writeable,
|
||||
attribute.executable);
|
||||
Nova::Mem_crd const mem(page.addr >> 12, page.log2_order - 12,
|
||||
map_rights);
|
||||
|
||||
|
@ -31,7 +31,12 @@ class Genode::Page_table_registry
|
||||
{
|
||||
public:
|
||||
|
||||
class Mapping_cache_full : Exception { };
|
||||
struct Mapping_cache_full : Exception
|
||||
{
|
||||
enum Type { MEMORY, CAPS } reason;
|
||||
|
||||
Mapping_cache_full(enum Type reason) : reason(reason) { };
|
||||
};
|
||||
|
||||
private:
|
||||
|
||||
@ -175,9 +180,9 @@ class Genode::Page_table_registry
|
||||
break;
|
||||
}
|
||||
} catch (Genode::Allocator::Out_of_memory) {
|
||||
throw Mapping_cache_full();
|
||||
throw Mapping_cache_full(Mapping_cache_full::Type::MEMORY);
|
||||
} catch (Genode::Out_of_caps) {
|
||||
throw Mapping_cache_full();
|
||||
throw Mapping_cache_full(Mapping_cache_full::Type::CAPS);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -83,7 +83,7 @@ class Genode::Vm_session_component
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void _attach_vm_memory(Dataspace_component &, addr_t, bool, bool);
|
||||
void _attach_vm_memory(Dataspace_component &, addr_t, Attach_attr);
|
||||
void _detach_vm_memory(addr_t, size_t);
|
||||
|
||||
protected:
|
||||
@ -116,7 +116,7 @@ class Genode::Vm_session_component
|
||||
void _exception_handler(Signal_context_capability, Vcpu_id) {}
|
||||
void _run(Vcpu_id) {}
|
||||
void _pause(Vcpu_id);
|
||||
void attach(Dataspace_capability, addr_t) override;
|
||||
void attach(Dataspace_capability, addr_t, Attach_attr) override;
|
||||
void attach_pic(addr_t) override {}
|
||||
void detach(addr_t, size_t) override;
|
||||
void _create_vcpu(Thread_capability);
|
||||
|
@ -242,16 +242,45 @@ void Vm_session_component::_pause(Vcpu_id const vcpu_id)
|
||||
|
||||
void Vm_session_component::_attach_vm_memory(Dataspace_component &dsc,
|
||||
addr_t const guest_phys,
|
||||
bool const executable,
|
||||
bool const writeable)
|
||||
Attach_attr const attribute)
|
||||
{
|
||||
_vm_space.alloc_guest_page_tables(guest_phys, dsc.size());
|
||||
Flexpage_iterator flex(dsc.phys_addr() + attribute.offset, attribute.size,
|
||||
guest_phys, attribute.size, guest_phys);
|
||||
|
||||
enum { FLUSHABLE = true };
|
||||
_vm_space.map_guest(dsc.phys_addr(), guest_phys, dsc.size() >> 12,
|
||||
dsc.cacheability(),
|
||||
dsc.writable() && writeable,
|
||||
executable, FLUSHABLE);
|
||||
Flexpage page = flex.page();
|
||||
while (page.valid()) {
|
||||
try {
|
||||
_vm_space.alloc_guest_page_tables(page.hotspot, 1 << page.log2_order);
|
||||
} catch (...) {
|
||||
// Alloc_page_table_failed
|
||||
Genode::error("alloc_guest_page_table exception");
|
||||
return;
|
||||
}
|
||||
|
||||
enum { NO_FLUSH = false, FLUSH = true };
|
||||
try {
|
||||
_vm_space.map_guest(page.addr, page.hotspot,
|
||||
(1 << page.log2_order) / 4096,
|
||||
dsc.cacheability(),
|
||||
dsc.writable() && attribute.writeable,
|
||||
attribute.executable, NO_FLUSH);
|
||||
} catch (Page_table_registry::Mapping_cache_full full) {
|
||||
if (full.reason == Page_table_registry::Mapping_cache_full::MEMORY)
|
||||
throw Out_of_ram();
|
||||
if (full.reason == Page_table_registry::Mapping_cache_full::CAPS)
|
||||
throw Out_of_caps();
|
||||
return;
|
||||
} catch (Genode::Bit_allocator<4096u>::Out_of_indices) {
|
||||
Genode::warning("run out of indices - flush all");
|
||||
_vm_space.map_guest(page.addr, page.hotspot,
|
||||
(1 << page.log2_order) / 4096,
|
||||
dsc.cacheability(),
|
||||
dsc.writable() && attribute.writeable,
|
||||
attribute.executable, FLUSH);
|
||||
}
|
||||
|
||||
page = flex.page();
|
||||
}
|
||||
}
|
||||
|
||||
void Vm_session_component::_detach_vm_memory(addr_t guest_phys, size_t size)
|
||||
|
@ -42,8 +42,14 @@ struct Genode::Vm_session_client : Rpc_client<Vm_session>
|
||||
void run(Vcpu_id);
|
||||
void pause(Vcpu_id);
|
||||
|
||||
void attach(Dataspace_capability ds,addr_t vm_addr) override {
|
||||
call<Rpc_attach>(ds, vm_addr); }
|
||||
void attach(Dataspace_capability ds, addr_t vm_addr,
|
||||
Attach_attr attr = { .offset = 0,
|
||||
.size = 0,
|
||||
.executable = true,
|
||||
.writeable = true } ) override
|
||||
{
|
||||
call<Rpc_attach>(ds, vm_addr, attr);
|
||||
}
|
||||
|
||||
void detach(addr_t vm_addr, size_t size) override {
|
||||
call<Rpc_detach>(vm_addr, size); }
|
||||
|
@ -28,6 +28,13 @@ struct Genode::Vm_session : Session
|
||||
static const char *service_name() { return "VM"; }
|
||||
|
||||
struct Vcpu_id { unsigned id; };
|
||||
struct Attach_attr
|
||||
{
|
||||
addr_t offset;
|
||||
addr_t size;
|
||||
bool executable;
|
||||
bool writeable;
|
||||
};
|
||||
|
||||
enum { CAP_QUOTA = 3 };
|
||||
|
||||
@ -45,7 +52,7 @@ struct Genode::Vm_session : Session
|
||||
* \param ds dataspace to be attached
|
||||
* \param vm_addr address in guest-physical memory address space
|
||||
*/
|
||||
virtual void attach(Dataspace_capability ds, addr_t vm_addr) = 0;
|
||||
virtual void attach(Dataspace_capability ds, addr_t, Attach_attr) = 0;
|
||||
|
||||
/**
|
||||
* Invalidate region of the guest-physical memory address space
|
||||
@ -78,7 +85,7 @@ struct Genode::Vm_session : Session
|
||||
GENODE_RPC_THROW(Rpc_attach, void, attach,
|
||||
GENODE_TYPE_LIST(Out_of_ram, Out_of_caps, Region_conflict,
|
||||
Invalid_dataspace),
|
||||
Dataspace_capability, addr_t);
|
||||
Dataspace_capability, addr_t, Attach_attr);
|
||||
GENODE_RPC(Rpc_detach, void, detach, addr_t, size_t);
|
||||
GENODE_RPC(Rpc_attach_pic, void, attach_pic, addr_t);
|
||||
GENODE_RPC_THROW(Rpc_create_vcpu, void, _create_vcpu,
|
||||
|
@ -23,7 +23,8 @@ using Genode::addr_t;
|
||||
using Genode::Vm_session_component;
|
||||
|
||||
void Vm_session_component::attach(Dataspace_capability const cap,
|
||||
addr_t const guest_phys)
|
||||
addr_t const guest_phys,
|
||||
Attach_attr attribute)
|
||||
{
|
||||
if (!cap.valid())
|
||||
throw Invalid_dataspace();
|
||||
@ -39,11 +40,25 @@ void Vm_session_component::attach(Dataspace_capability const cap,
|
||||
if (dsc.managed())
|
||||
throw Invalid_dataspace();
|
||||
|
||||
bool const writeable = true;
|
||||
bool const executable = true;
|
||||
unsigned const offset = 0;
|
||||
if (guest_phys & 0xffful || attribute.offset & 0xffful ||
|
||||
attribute.size & 0xffful)
|
||||
throw Invalid_dataspace();
|
||||
|
||||
switch (_map.alloc_addr(dsc.size(), guest_phys).value) {
|
||||
if (!attribute.size) {
|
||||
attribute.size = dsc.size();
|
||||
|
||||
if (attribute.offset < attribute.size)
|
||||
attribute.size -= attribute.offset;
|
||||
}
|
||||
|
||||
if (attribute.size > dsc.size())
|
||||
attribute.size = dsc.size();
|
||||
|
||||
if (attribute.offset >= dsc.size() ||
|
||||
attribute.offset > dsc.size() - attribute.size)
|
||||
throw Invalid_dataspace();
|
||||
|
||||
switch (_map.alloc_addr(attribute.size, guest_phys).value) {
|
||||
case Range_allocator::Alloc_return::OUT_OF_METADATA:
|
||||
throw Out_of_ram();
|
||||
case Range_allocator::Alloc_return::RANGE_CONFLICT:
|
||||
@ -68,9 +83,10 @@ void Vm_session_component::attach(Dataspace_capability const cap,
|
||||
/* store attachment info in meta data */
|
||||
try {
|
||||
_map.construct_metadata((void *)guest_phys,
|
||||
guest_phys, dsc.size(),
|
||||
dsc.writable() && writeable,
|
||||
dsc, offset, *this, executable);
|
||||
guest_phys, attribute.size,
|
||||
dsc.writable() && attribute.writeable,
|
||||
dsc, attribute.offset, *this,
|
||||
attribute.executable);
|
||||
} catch (Allocator_avl_tpl<Rm_region>::Assign_metadata_failed) {
|
||||
error("failed to store attachment info");
|
||||
throw Invalid_dataspace();
|
||||
@ -86,7 +102,7 @@ void Vm_session_component::attach(Dataspace_capability const cap,
|
||||
};
|
||||
|
||||
/* kernel specific code to attach memory to guest */
|
||||
_attach_vm_memory(dsc, guest_phys, executable, writeable);
|
||||
_attach_vm_memory(dsc, guest_phys, attribute);
|
||||
});
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user