From 393643515c4486292411cdfad4d12b352cf02f77 Mon Sep 17 00:00:00 2001 From: Alexander Boettcher Date: Wed, 14 Nov 2018 14:57:45 +0100 Subject: [PATCH] base: extend attach of vm_session by offset, size, writeable and executable parameter Issue #3111 --- .../src/core/include/vm_session_component.h | 4 +- .../base-foc/src/core/vm_session_component.cc | 13 +++--- .../arm_v7/trustzone/vm_session_component.h | 2 +- .../virtualization/vm_session_component.cc | 5 +-- .../virtualization/vm_session_component.h | 4 +- .../spec/x86_64/muen/vm_session_component.h | 2 +- .../src/core/include/vm_session_component.h | 4 +- .../src/core/vm_session_component.cc | 12 ++--- .../src/core/include/page_table_registry.h | 11 +++-- .../src/core/include/vm_session_component.h | 4 +- .../src/core/spec/x86/vm_session_component.cc | 45 +++++++++++++++---- repos/base/include/vm_session/client.h | 10 ++++- repos/base/include/vm_session/vm_session.h | 11 ++++- repos/base/src/core/vm_session_common.cc | 34 ++++++++++---- 14 files changed, 111 insertions(+), 50 deletions(-) diff --git a/repos/base-foc/src/core/include/vm_session_component.h b/repos/base-foc/src/core/include/vm_session_component.h index 3b8db0a88..6a9f55fc4 100644 --- a/repos/base-foc/src/core/include/vm_session_component.h +++ b/repos/base-foc/src/core/include/vm_session_component.h @@ -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); diff --git a/repos/base-foc/src/core/vm_session_component.cc b/repos/base-foc/src/core/vm_session_component.cc index 7f1f680b2..b35bf555f 100644 --- a/repos/base-foc/src/core/vm_session_component.cc +++ b/repos/base-foc/src/core/vm_session_component.cc @@ -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(); diff --git a/repos/base-hw/src/core/spec/arm_v7/trustzone/vm_session_component.h b/repos/base-hw/src/core/spec/arm_v7/trustzone/vm_session_component.h index 67cde9db2..f71fd6975 100644 --- a/repos/base-hw/src/core/spec/arm_v7/trustzone/vm_session_component.h +++ b/repos/base-hw/src/core/spec/arm_v7/trustzone/vm_session_component.h @@ -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 { diff --git a/repos/base-hw/src/core/spec/arm_v7/virtualization/vm_session_component.cc b/repos/base-hw/src/core/spec/arm_v7/virtualization/vm_session_component.cc index fd2288d5c..f2313cc6d 100644 --- a/repos/base-hw/src/core/spec/arm_v7/virtualization/vm_session_component.cc +++ b/repos/base-hw/src/core/spec/arm_v7/virtualization/vm_session_component.cc @@ -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); } diff --git a/repos/base-hw/src/core/spec/arm_v7/virtualization/vm_session_component.h b/repos/base-hw/src/core/spec/arm_v7/virtualization/vm_session_component.h index 8b3e3b841..caf9e190c 100644 --- a/repos/base-hw/src/core/spec/arm_v7/virtualization/vm_session_component.h +++ b/repos/base-hw/src/core/spec/arm_v7/virtualization/vm_session_component.h @@ -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) {} diff --git a/repos/base-hw/src/core/spec/x86_64/muen/vm_session_component.h b/repos/base-hw/src/core/spec/x86_64/muen/vm_session_component.h index 7a226345c..f5e17182f 100644 --- a/repos/base-hw/src/core/spec/x86_64/muen/vm_session_component.h +++ b/repos/base-hw/src/core/spec/x86_64/muen/vm_session_component.h @@ -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) { } diff --git a/repos/base-nova/src/core/include/vm_session_component.h b/repos/base-nova/src/core/include/vm_session_component.h index 0067e0b5d..a6ad59ad5 100644 --- a/repos/base-nova/src/core/include/vm_session_component.h +++ b/repos/base-nova/src/core/include/vm_session_component.h @@ -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); diff --git a/repos/base-nova/src/core/vm_session_component.cc b/repos/base-nova/src/core/vm_session_component.cc index 071171641..5d6506206 100644 --- a/repos/base-nova/src/core/vm_session_component.cc +++ b/repos/base-nova/src/core/vm_session_component.cc @@ -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(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); diff --git a/repos/base-sel4/src/core/include/page_table_registry.h b/repos/base-sel4/src/core/include/page_table_registry.h index f7fbbbc0b..bff0c9c33 100644 --- a/repos/base-sel4/src/core/include/page_table_registry.h +++ b/repos/base-sel4/src/core/include/page_table_registry.h @@ -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); } } diff --git a/repos/base-sel4/src/core/include/vm_session_component.h b/repos/base-sel4/src/core/include/vm_session_component.h index 4e5c2e781..faaa9a027 100644 --- a/repos/base-sel4/src/core/include/vm_session_component.h +++ b/repos/base-sel4/src/core/include/vm_session_component.h @@ -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); diff --git a/repos/base-sel4/src/core/spec/x86/vm_session_component.cc b/repos/base-sel4/src/core/spec/x86/vm_session_component.cc index 844a39de8..a251fb34e 100644 --- a/repos/base-sel4/src/core/spec/x86/vm_session_component.cc +++ b/repos/base-sel4/src/core/spec/x86/vm_session_component.cc @@ -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) diff --git a/repos/base/include/vm_session/client.h b/repos/base/include/vm_session/client.h index 925e8a841..089d38ebd 100644 --- a/repos/base/include/vm_session/client.h +++ b/repos/base/include/vm_session/client.h @@ -42,8 +42,14 @@ struct Genode::Vm_session_client : Rpc_client void run(Vcpu_id); void pause(Vcpu_id); - void attach(Dataspace_capability ds,addr_t vm_addr) override { - call(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(ds, vm_addr, attr); + } void detach(addr_t vm_addr, size_t size) override { call(vm_addr, size); } diff --git a/repos/base/include/vm_session/vm_session.h b/repos/base/include/vm_session/vm_session.h index fd39db7db..8a050c71e 100644 --- a/repos/base/include/vm_session/vm_session.h +++ b/repos/base/include/vm_session/vm_session.h @@ -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, diff --git a/repos/base/src/core/vm_session_common.cc b/repos/base/src/core/vm_session_common.cc index ec63b0801..fdea568bd 100644 --- a/repos/base/src/core/vm_session_common.cc +++ b/repos/base/src/core/vm_session_common.cc @@ -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::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); }); }