mirror of
https://github.com/genodelabs/genode.git
synced 2025-01-18 10:46:25 +00:00
parent
3a1bbfad28
commit
b75307b070
@ -21,7 +21,7 @@ CONFIG_IA32=y
|
||||
CONFIG_PF_PC=y
|
||||
# CONFIG_PF_UX is not set
|
||||
CONFIG_ABI_VF=y
|
||||
# CONFIG_CPU_VIRT is not set
|
||||
CONFIG_CPU_VIRT=y
|
||||
CONFIG_SCHED_APIC=y
|
||||
# CONFIG_WORKAROUND_AMD_FPU_LEAK is not set
|
||||
CONFIG_REGPARM3=y
|
||||
|
@ -20,7 +20,7 @@ CONFIG_AMD64=y
|
||||
# CONFIG_MIPS is not set
|
||||
CONFIG_PF_PC=y
|
||||
CONFIG_ABI_VF=y
|
||||
# CONFIG_CPU_VIRT is not set
|
||||
CONFIG_CPU_VIRT=y
|
||||
CONFIG_SCHED_APIC=y
|
||||
# CONFIG_WORKAROUND_AMD_FPU_LEAK is not set
|
||||
|
||||
|
@ -48,7 +48,7 @@ namespace Fiasco {
|
||||
static constexpr l4_cap_idx_t THREAD_AREA_BASE = 0xcUL << L4_CAP_SHIFT;
|
||||
|
||||
/* size of one thread slot */
|
||||
static constexpr l4_cap_idx_t THREAD_AREA_SLOT = 0x3UL << L4_CAP_SHIFT;
|
||||
static constexpr l4_cap_idx_t THREAD_AREA_SLOT = 0x5UL << L4_CAP_SHIFT;
|
||||
|
||||
/* offset to the ipc gate cap selector in the slot */
|
||||
static constexpr l4_cap_idx_t THREAD_GATE_CAP = 0;
|
||||
@ -59,6 +59,12 @@ namespace Fiasco {
|
||||
/* offset to the irq cap selector in the slot */
|
||||
static constexpr l4_cap_idx_t THREAD_IRQ_CAP = 0x2UL << L4_CAP_SHIFT;
|
||||
|
||||
/* offset to the irq cap selector in the slot */
|
||||
static constexpr l4_cap_idx_t TASK_VCPU_CAP = 0x3UL << L4_CAP_SHIFT;
|
||||
|
||||
/* offset to the irq cap selector in the slot */
|
||||
static constexpr l4_cap_idx_t TASK_VCPU_IRQ_CAP = 0x4UL << L4_CAP_SHIFT;
|
||||
|
||||
/* shortcut to the main thread's gate cap */
|
||||
static constexpr l4_cap_idx_t MAIN_THREAD_CAP = THREAD_AREA_BASE
|
||||
+ THREAD_GATE_CAP;
|
||||
|
15
repos/base-foc/lib/mk/base-foc-common.inc
Normal file
15
repos/base-foc/lib/mk/base-foc-common.inc
Normal file
@ -0,0 +1,15 @@
|
||||
#
|
||||
# \brief Portions of base library shared by core and non-core processes
|
||||
# \author Norman Feske
|
||||
# \date 2013-02-14
|
||||
#
|
||||
|
||||
include $(BASE_DIR)/lib/mk/base-common.inc
|
||||
|
||||
LIBS += syscall-foc startup-foc
|
||||
|
||||
SRC_CC += spin_lock.cc cap_map.cc
|
||||
SRC_CC += rpc_dispatch_loop.cc
|
||||
SRC_CC += thread.cc thread_bootstrap.cc thread_myself.cc utcb.cc
|
||||
SRC_CC += capability.cc
|
||||
SRC_CC += signal_source_client.cc
|
@ -4,12 +4,4 @@
|
||||
# \date 2013-02-14
|
||||
#
|
||||
|
||||
include $(BASE_DIR)/lib/mk/base-common.inc
|
||||
|
||||
LIBS += syscall-foc startup-foc
|
||||
|
||||
SRC_CC += spin_lock.cc cap_map.cc
|
||||
SRC_CC += rpc_dispatch_loop.cc
|
||||
SRC_CC += thread.cc thread_bootstrap.cc thread_myself.cc utcb.cc
|
||||
SRC_CC += capability.cc
|
||||
SRC_CC += signal_source_client.cc
|
||||
include $(REP_DIR)/lib/mk/base-foc-common.inc
|
||||
|
@ -27,7 +27,6 @@ SRC_CC += stack_area.cc \
|
||||
platform.cc \
|
||||
platform_rom_modules.cc \
|
||||
platform_pd.cc \
|
||||
platform_services.cc \
|
||||
platform_thread.cc \
|
||||
pd_session_component.cc \
|
||||
ram_dataspace_support.cc \
|
||||
@ -39,6 +38,7 @@ SRC_CC += stack_area.cc \
|
||||
signal_receiver.cc \
|
||||
thread_start.cc \
|
||||
trace_session_component.cc \
|
||||
vm_session_component.cc \
|
||||
heartbeat.cc
|
||||
|
||||
INC_DIR += $(REP_DIR)/src/core/include \
|
||||
|
@ -1,6 +1,7 @@
|
||||
REQUIRES += arm
|
||||
SRC_CC += spec/arm/platform_arm.cc \
|
||||
spec/arm/ipc_pager.cc
|
||||
spec/arm/ipc_pager.cc \
|
||||
platform_services.cc
|
||||
|
||||
# override default stack-area location
|
||||
INC_DIR += $(REP_DIR)/src/include/spec/arm
|
||||
|
9
repos/base-foc/lib/mk/spec/x86/base-foc-common.mk
Normal file
9
repos/base-foc/lib/mk/spec/x86/base-foc-common.mk
Normal file
@ -0,0 +1,9 @@
|
||||
#
|
||||
# \brief Portions of base library shared by core and non-core processes
|
||||
# \author Norman Feske
|
||||
# \date 2013-02-14
|
||||
#
|
||||
|
||||
vpath vm_session.cc $(REP_DIR)/src/lib/base/x86
|
||||
|
||||
include $(REP_DIR)/lib/mk/base-foc-common.inc
|
@ -1,10 +1,10 @@
|
||||
SRC_CC += io_port_session_component.cc \
|
||||
io_port_session_support.cc \
|
||||
spec/x86/ipc_pager.cc \
|
||||
spec/x86/platform.cc
|
||||
spec/x86/platform.cc \
|
||||
spec/x86/platform_services.cc
|
||||
|
||||
vpath io_port_session_component.cc $(BASE_DIR)/src/core/spec/x86
|
||||
vpath io_port_session_support.cc $(BASE_DIR)/src/core/spec/x86
|
||||
vpath platform_services.cc $(BASE_DIR)/src/core/spec/x86
|
||||
|
||||
include $(REP_DIR)/lib/mk/core-foc.inc
|
||||
|
@ -28,9 +28,14 @@
|
||||
#include <platform_pd.h>
|
||||
#include <assertion.h>
|
||||
|
||||
namespace Fiasco {
|
||||
struct l4_kernel_info_t;
|
||||
}
|
||||
|
||||
namespace Genode {
|
||||
|
||||
class Xml_generator;
|
||||
|
||||
class Platform : public Platform_generic
|
||||
{
|
||||
private:
|
||||
@ -73,12 +78,6 @@ namespace Genode {
|
||||
addr_t _vm_start = 0; /* begin of virtual memory */
|
||||
size_t _vm_size = 0; /* size of virtual memory */
|
||||
|
||||
|
||||
/*
|
||||
* We do not export any boot module loaded before FIRST_ROM.
|
||||
*/
|
||||
enum { FIRST_ROM = 3 };
|
||||
|
||||
/**
|
||||
* Setup base resources
|
||||
*
|
||||
@ -97,6 +96,12 @@ namespace Genode {
|
||||
*/
|
||||
void _setup_io_port_alloc();
|
||||
|
||||
/**
|
||||
* Setup content of platform_info ROM
|
||||
*/
|
||||
void _setup_platform_info(Xml_generator &,
|
||||
Fiasco::l4_kernel_info_t &);
|
||||
|
||||
/**
|
||||
* Setup IRQ allocator
|
||||
*/
|
||||
@ -116,6 +121,8 @@ namespace Genode {
|
||||
|
||||
public:
|
||||
|
||||
enum { VCPU_VIRT_EXT_START = 0x1000, VCPU_VIRT_EXT_END = 0x10000 };
|
||||
|
||||
/**
|
||||
* Core pager thread that handles core-internal page-faults
|
||||
*/
|
||||
|
@ -156,6 +156,12 @@ namespace Genode {
|
||||
*/
|
||||
Affinity::Location affinity() const;
|
||||
|
||||
/**
|
||||
* Make thread to vCPU
|
||||
*/
|
||||
Fiasco::l4_cap_idx_t setup_vcpu(unsigned, Cap_mapping const &,
|
||||
Cap_mapping &);
|
||||
|
||||
/************************
|
||||
** Accessor functions **
|
||||
************************/
|
||||
|
95
repos/base-foc/src/core/include/vm_session_component.h
Normal file
95
repos/base-foc/src/core/include/vm_session_component.h
Normal file
@ -0,0 +1,95 @@
|
||||
/*
|
||||
* \brief Core-specific instance of the VM session interface
|
||||
* \author Alexander Boettcher
|
||||
* \date 2018-08-26
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2018 Genode Labs GmbH
|
||||
*
|
||||
* This file is part of the Genode OS framework, which is distributed
|
||||
* under the terms of the GNU Affero General Public License version 3.
|
||||
*/
|
||||
|
||||
#ifndef _CORE__VM_SESSION_COMPONENT_H_
|
||||
#define _CORE__VM_SESSION_COMPONENT_H_
|
||||
|
||||
/* Genode includes */
|
||||
#include <base/allocator_guard.h>
|
||||
#include <base/rpc_server.h>
|
||||
#include <base/heap.h>
|
||||
#include <vm_session/vm_session.h>
|
||||
|
||||
/* Core includes */
|
||||
#include <dataspace_component.h>
|
||||
#include <cap_mapping.h>
|
||||
|
||||
namespace Genode { class Vm_session_component; struct Vcpu; }
|
||||
|
||||
class Genode::Vm_session_component
|
||||
:
|
||||
private Ram_quota_guard,
|
||||
private Cap_quota_guard,
|
||||
public Rpc_object<Vm_session, Vm_session_component>
|
||||
{
|
||||
private:
|
||||
|
||||
Rpc_entrypoint &_ep;
|
||||
Constrained_ram_allocator _constrained_md_ram_alloc;
|
||||
Sliced_heap _sliced_heap;
|
||||
List<Vcpu> _vcpus { };
|
||||
Cap_mapping _task_vcpu { true };
|
||||
unsigned _id_alloc { 0 };
|
||||
|
||||
protected:
|
||||
|
||||
Ram_quota_guard &_ram_quota_guard() { return *this; }
|
||||
Cap_quota_guard &_cap_quota_guard() { return *this; }
|
||||
|
||||
public:
|
||||
|
||||
using Ram_quota_guard::upgrade;
|
||||
using Cap_quota_guard::upgrade;
|
||||
|
||||
Vm_session_component(Rpc_entrypoint &, Resources, Label const &,
|
||||
Diag, Ram_allocator &ram, Region_map &);
|
||||
~Vm_session_component();
|
||||
|
||||
/**************************
|
||||
** Vm session interface **
|
||||
**************************/
|
||||
|
||||
Dataspace_capability _cpu_state(Vcpu_id);
|
||||
|
||||
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_pic(addr_t) override { }
|
||||
void detach(addr_t, size_t) override { }
|
||||
void _create_vcpu(Thread_capability);
|
||||
};
|
||||
|
||||
struct Genode::Vcpu : Genode::List<Vcpu>::Element
|
||||
{
|
||||
private:
|
||||
|
||||
Constrained_ram_allocator &_ram_alloc;
|
||||
Cap_quota_guard &_cap_alloc;
|
||||
Ram_dataspace_capability _ds_cap { };
|
||||
Vm_session::Vcpu_id const _id;
|
||||
Cap_mapping _recall { true };
|
||||
|
||||
public:
|
||||
|
||||
Vcpu(Constrained_ram_allocator &ram_alloc,
|
||||
Cap_quota_guard &cap_alloc, Vm_session::Vcpu_id const id);
|
||||
|
||||
~Vcpu();
|
||||
|
||||
bool match(Vm_session::Vcpu_id const id) const { return id.id == _id.id; }
|
||||
Dataspace_capability ds_cap() { return _ds_cap; }
|
||||
Cap_mapping &recall_cap() { return _recall; }
|
||||
};
|
||||
|
||||
#endif /* _CORE__VM_SESSION_COMPONENT_H_ */
|
@ -17,6 +17,7 @@
|
||||
#include <base/allocator_avl.h>
|
||||
#include <base/sleep.h>
|
||||
#include <util/misc_math.h>
|
||||
#include <util/xml_generator.h>
|
||||
|
||||
/* base-internal includes */
|
||||
#include <base/internal/crt0.h>
|
||||
@ -384,6 +385,13 @@ void Platform::_setup_basics()
|
||||
/* configure applicable address space but never use page0 */
|
||||
_vm_size = _vm_start == 0 ? _vm_size - L4_PAGESIZE : _vm_size;
|
||||
_vm_start = _vm_start == 0 ? L4_PAGESIZE : _vm_start;
|
||||
|
||||
/* reserve virtual range for extended vCPU features - better way XXX ? */
|
||||
if (_vm_start < VCPU_VIRT_EXT_END) {
|
||||
_vm_size -= VCPU_VIRT_EXT_END - _vm_start;
|
||||
_vm_start = VCPU_VIRT_EXT_END;
|
||||
}
|
||||
|
||||
_region_alloc.add_range(_vm_start, _vm_size);
|
||||
|
||||
/* preserve stack area in core's virtual address space */
|
||||
@ -456,40 +464,65 @@ Platform::Platform() :
|
||||
core_thread.pager(_sigma0);
|
||||
_core_pd->bind_thread(core_thread);
|
||||
|
||||
{
|
||||
/* export x86 platform specific infos */
|
||||
{
|
||||
void * core_local_ptr = nullptr;
|
||||
void * phys_ptr = nullptr;
|
||||
if (ram_alloc().alloc_aligned(get_page_size(), &phys_ptr,
|
||||
get_page_size_log2()).ok()) {
|
||||
unsigned const pages = 1;
|
||||
size_t const align = get_page_size_log2();
|
||||
size_t const size = pages << get_page_size_log2();
|
||||
|
||||
if (ram_alloc().alloc_aligned(size, &phys_ptr, align).error())
|
||||
return;
|
||||
if (region_alloc().alloc_aligned(size, &core_local_ptr, align).error())
|
||||
return;
|
||||
|
||||
addr_t const phys_addr = reinterpret_cast<addr_t>(phys_ptr);
|
||||
/* empty for now */
|
||||
_rom_fs.insert(new (core_mem_alloc()) Rom_module(phys_addr,
|
||||
get_page_size(),
|
||||
addr_t const core_local_addr = reinterpret_cast<addr_t>(core_local_ptr);
|
||||
|
||||
if (!map_local(phys_addr, core_local_addr, pages))
|
||||
return;
|
||||
|
||||
memset(core_local_ptr, 0, size);
|
||||
|
||||
Genode::Xml_generator xml(reinterpret_cast<char *>(core_local_addr),
|
||||
pages << get_page_size_log2(),
|
||||
"platform_info", [&] ()
|
||||
{
|
||||
xml.node("hardware", [&] () {
|
||||
_setup_platform_info(xml, sigma0_map_kip());
|
||||
});
|
||||
});
|
||||
|
||||
_rom_fs.insert(new (core_mem_alloc()) Rom_module(phys_addr, size,
|
||||
"platform_info"));
|
||||
}
|
||||
}
|
||||
|
||||
/* core log as ROM module */
|
||||
{
|
||||
void * core_local_ptr = nullptr;
|
||||
void * phys_ptr = nullptr;
|
||||
unsigned const pages = 1;
|
||||
size_t const log_size = pages << get_page_size_log2();
|
||||
size_t const align = get_page_size_log2();
|
||||
size_t const size = pages << get_page_size_log2();
|
||||
|
||||
if (ram_alloc().alloc_aligned(size, &phys_ptr, align).error())
|
||||
return;
|
||||
if (region_alloc().alloc_aligned(size, &core_local_ptr, align).error())
|
||||
return;
|
||||
|
||||
ram_alloc().alloc_aligned(log_size, &phys_ptr, get_page_size_log2());
|
||||
addr_t const phys_addr = reinterpret_cast<addr_t>(phys_ptr);
|
||||
|
||||
/* let one page free after the log buffer */
|
||||
region_alloc().alloc_aligned(log_size, &core_local_ptr, get_page_size_log2());
|
||||
addr_t const core_local_addr = reinterpret_cast<addr_t>(core_local_ptr);
|
||||
|
||||
map_local(phys_addr, core_local_addr, pages);
|
||||
memset(core_local_ptr, 0, log_size);
|
||||
if (!map_local(phys_addr, core_local_addr, pages))
|
||||
return;
|
||||
|
||||
_rom_fs.insert(new (core_mem_alloc()) Rom_module(phys_addr, log_size,
|
||||
memset(core_local_ptr, 0, size);
|
||||
|
||||
_rom_fs.insert(new (core_mem_alloc()) Rom_module(phys_addr, size,
|
||||
"core_log"));
|
||||
|
||||
init_core_log(Core_log_range { core_local_addr, log_size } );
|
||||
init_core_log(Core_log_range { core_local_addr, size } );
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -356,3 +356,43 @@ Platform_thread::~Platform_thread()
|
||||
if (_platform_pd)
|
||||
_platform_pd->unbind_thread(*this);
|
||||
}
|
||||
|
||||
Fiasco::l4_cap_idx_t Platform_thread::setup_vcpu(unsigned const vcpu_id,
|
||||
Cap_mapping const &task_vcpu,
|
||||
Cap_mapping &vcpu_irq)
|
||||
{
|
||||
if (!_platform_pd)
|
||||
return Fiasco::L4_INVALID_CAP;
|
||||
if (vcpu_id >= (Platform::VCPU_VIRT_EXT_END - Platform::VCPU_VIRT_EXT_START) / L4_PAGESIZE)
|
||||
return Fiasco::L4_INVALID_CAP;
|
||||
|
||||
Genode::addr_t const vcpu_addr = Platform::VCPU_VIRT_EXT_START +
|
||||
L4_PAGESIZE * vcpu_id;
|
||||
l4_fpage_t vm_page = l4_fpage( vcpu_addr, L4_PAGESHIFT, L4_FPAGE_RW);
|
||||
|
||||
l4_msgtag_t msg = l4_task_add_ku_mem(_platform_pd->native_task().data()->kcap(), vm_page);
|
||||
if (l4_error(msg)) {
|
||||
Genode::error("ku_mem failed ", l4_error(msg));
|
||||
return Fiasco::L4_INVALID_CAP;
|
||||
}
|
||||
|
||||
msg = l4_thread_vcpu_control_ext(_thread.local.data()->kcap(), vcpu_addr);
|
||||
if (l4_error(msg)) {
|
||||
Genode::error("vcpu_control_exit failed ", l4_error(msg));
|
||||
return Fiasco::L4_INVALID_CAP;
|
||||
}
|
||||
|
||||
/* attach thread to irq */
|
||||
vcpu_irq.remote = _gate.remote + TASK_VCPU_IRQ_CAP;
|
||||
l4_msgtag_t tag = l4_rcv_ep_bind_thread(vcpu_irq.local.data()->kcap(),
|
||||
_thread.local.data()->kcap(), 0);
|
||||
if (l4_msgtag_has_error(tag))
|
||||
warning("attaching thread's irq failed");
|
||||
|
||||
vcpu_irq.map(_platform_pd->native_task().data()->kcap());
|
||||
|
||||
/* set human readable name in kernel debugger */
|
||||
Cap_mapping map(task_vcpu.local, _gate.remote + TASK_VCPU_CAP);
|
||||
map.map(_platform_pd->native_task().data()->kcap());
|
||||
return map.remote;
|
||||
}
|
||||
|
@ -16,3 +16,6 @@
|
||||
void Genode::Platform::_setup_io_port_alloc() { }
|
||||
|
||||
void Genode::Platform::setup_irq_mode(unsigned, unsigned, unsigned) { }
|
||||
|
||||
void Genode::Platform::_setup_platform_info(Xml_generator &,
|
||||
Fiasco::l4_kernel_info_t &) { }
|
||||
|
@ -15,6 +15,7 @@
|
||||
/* Genode includes */
|
||||
#include <base/log.h>
|
||||
#include <irq_session/irq_session.h>
|
||||
#include <util/xml_generator.h>
|
||||
|
||||
#include "platform.h"
|
||||
#include "util.h"
|
||||
@ -23,6 +24,7 @@
|
||||
namespace Fiasco {
|
||||
#include <l4/sys/ipc.h>
|
||||
#include <l4/sys/icu.h>
|
||||
#include <l4/sys/kip.h>
|
||||
}
|
||||
|
||||
void Genode::Platform::_setup_io_port_alloc()
|
||||
@ -86,3 +88,27 @@ void Genode::Platform::setup_irq_mode(unsigned irq_number, unsigned trigger,
|
||||
if (l4_error(l4_icu_set_mode(L4_BASE_ICU_CAP, irq_number, mode)))
|
||||
error("setting mode for IRQ ", irq_number, " failed");
|
||||
}
|
||||
|
||||
static bool cpu_name(char const * name) {
|
||||
using Genode::uint32_t;
|
||||
|
||||
uint32_t cpuid = 0, edx = 0, ebx = 0, ecx = 0;
|
||||
asm volatile ("cpuid" : "+a" (cpuid), "=d" (edx), "=b"(ebx), "=c"(ecx));
|
||||
|
||||
return ebx == *reinterpret_cast<uint32_t const *>(name) &&
|
||||
edx == *reinterpret_cast<uint32_t const *>(name + 4) &&
|
||||
ecx == *reinterpret_cast<uint32_t const *>(name + 8);
|
||||
}
|
||||
|
||||
void Genode::Platform::_setup_platform_info(Xml_generator &xml,
|
||||
Fiasco::l4_kernel_info_t &kip)
|
||||
{
|
||||
xml.node("features", [&] () {
|
||||
/* XXX better detection required, best told us by kernel !? */
|
||||
xml.attribute("svm", cpu_name("AuthenticAMD"));
|
||||
xml.attribute("vmx", cpu_name("GenuineIntel"));
|
||||
});
|
||||
xml.node("tsc", [&] () {
|
||||
xml.attribute("freq_khz" , kip.frequency_cpu);
|
||||
});
|
||||
}
|
||||
|
35
repos/base-foc/src/core/spec/x86/platform_services.cc
Normal file
35
repos/base-foc/src/core/spec/x86/platform_services.cc
Normal file
@ -0,0 +1,35 @@
|
||||
/*
|
||||
* \brief Platform specific services for FOC
|
||||
* \author Alexander Boettcher
|
||||
* \date 2018-08-26
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2018 Genode Labs GmbH
|
||||
*
|
||||
* This file is part of the Genode OS framework, which is distributed
|
||||
* under the terms of the GNU Affero General Public License version 3.
|
||||
*/
|
||||
|
||||
/* core includes */
|
||||
#include <core_env.h>
|
||||
#include <platform_services.h>
|
||||
#include <vm_root.h>
|
||||
#include <io_port_root.h>
|
||||
|
||||
/*
|
||||
* Add x86 specific services
|
||||
*/
|
||||
void Genode::platform_add_local_services(Rpc_entrypoint &ep,
|
||||
Sliced_heap &heap,
|
||||
Registry<Service> &services)
|
||||
{
|
||||
static Vm_root vm_root(ep, heap, core_env().ram_allocator(),
|
||||
core_env().local_rm());
|
||||
static Core_service<Vm_session_component> vm(services, vm_root);
|
||||
|
||||
static Io_port_root io_root(*core_env().pd_session(),
|
||||
platform().io_port_alloc(), heap);
|
||||
|
||||
static Core_service<Io_port_session_component> io_port(services, io_root);
|
||||
}
|
191
repos/base-foc/src/core/vm_session_component.cc
Normal file
191
repos/base-foc/src/core/vm_session_component.cc
Normal file
@ -0,0 +1,191 @@
|
||||
/*
|
||||
* \brief Core-specific instance of the VM session interface
|
||||
* \author Alexander Boettcher
|
||||
* \date 2018-08-26
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2018 Genode Labs GmbH
|
||||
*
|
||||
* This file is part of the Genode OS framework, which is distributed
|
||||
* under the terms of the GNU Affero General Public License version 3.
|
||||
*/
|
||||
|
||||
/* base includes */
|
||||
#include <util/flex_iterator.h>
|
||||
#include <dataspace/client.h>
|
||||
|
||||
/* core includes */
|
||||
#include <vm_session_component.h>
|
||||
#include <pd_session_component.h>
|
||||
#include <cpu_thread_component.h>
|
||||
|
||||
namespace Fiasco {
|
||||
#include <l4/sys/factory.h>
|
||||
}
|
||||
|
||||
|
||||
using namespace Genode;
|
||||
|
||||
|
||||
Vm_session_component::Vm_session_component(Rpc_entrypoint &ep,
|
||||
Resources resources,
|
||||
Label const &,
|
||||
Diag,
|
||||
Ram_allocator &ram,
|
||||
Region_map &local_rm)
|
||||
:
|
||||
Ram_quota_guard(resources.ram_quota),
|
||||
Cap_quota_guard(resources.cap_quota),
|
||||
_ep(ep),
|
||||
_constrained_md_ram_alloc(ram, _ram_quota_guard(), _cap_quota_guard()),
|
||||
_sliced_heap(_constrained_md_ram_alloc, local_rm)
|
||||
{
|
||||
_cap_quota_guard().withdraw(Cap_quota{1});
|
||||
|
||||
using namespace Fiasco;
|
||||
l4_msgtag_t msg = l4_factory_create_vm(L4_BASE_FACTORY_CAP,
|
||||
_task_vcpu.local.data()->kcap());
|
||||
if (l4_error(msg)) {
|
||||
_cap_quota_guard().replenish(Cap_quota{1});
|
||||
Genode::error("create_vm failed ", l4_error(msg));
|
||||
throw 1;
|
||||
}
|
||||
}
|
||||
|
||||
Vm_session_component::~Vm_session_component()
|
||||
{
|
||||
_cap_quota_guard().replenish(Cap_quota{1});
|
||||
|
||||
for (;Vcpu * vcpu = _vcpus.first();) {
|
||||
_vcpus.remove(vcpu);
|
||||
destroy(_sliced_heap, vcpu);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Vcpu::Vcpu(Constrained_ram_allocator &ram_alloc,
|
||||
Cap_quota_guard &cap_alloc,
|
||||
Vm_session::Vcpu_id const id)
|
||||
:
|
||||
_ram_alloc(ram_alloc),
|
||||
_cap_alloc(cap_alloc),
|
||||
_id(id)
|
||||
{
|
||||
try {
|
||||
/* create ds for vCPU state */
|
||||
_ds_cap = _ram_alloc.alloc(4096, Cache_attribute::CACHED);
|
||||
} catch (...) {
|
||||
throw;
|
||||
}
|
||||
|
||||
Fiasco::l4_msgtag_t msg = l4_factory_create_irq(Fiasco::L4_BASE_FACTORY_CAP,
|
||||
_recall.local.data()->kcap());
|
||||
if (l4_error(msg)) {
|
||||
_ram_alloc.free(_ds_cap);
|
||||
Genode::error("vcpu irq creation failed", l4_error(msg));
|
||||
throw 1;
|
||||
}
|
||||
}
|
||||
|
||||
Vcpu::~Vcpu()
|
||||
{
|
||||
if (_ds_cap.valid())
|
||||
_ram_alloc.free(_ds_cap);
|
||||
}
|
||||
|
||||
void Vm_session_component::_create_vcpu(Thread_capability cap)
|
||||
{
|
||||
if (!cap.valid())
|
||||
return;
|
||||
|
||||
auto lambda = [&] (Cpu_thread_component *thread) {
|
||||
if (!thread)
|
||||
return;
|
||||
|
||||
/* allocate vCPU object */
|
||||
Vcpu * vcpu = nullptr;
|
||||
try {
|
||||
vcpu = new (_sliced_heap) Vcpu(_constrained_md_ram_alloc,
|
||||
_cap_quota_guard(),
|
||||
Vcpu_id {_id_alloc});
|
||||
|
||||
Fiasco::l4_cap_idx_t task = thread->platform_thread().setup_vcpu(_id_alloc, _task_vcpu, vcpu->recall_cap());
|
||||
if (task == Fiasco::L4_INVALID_CAP)
|
||||
throw 0;
|
||||
|
||||
_ep.apply(vcpu->ds_cap(), [&] (Dataspace_component *ds) {
|
||||
if (!ds)
|
||||
throw 1;
|
||||
/* tell client where to find task cap */
|
||||
*reinterpret_cast<Fiasco::l4_cap_idx_t *>(ds->phys_addr()) = task;
|
||||
});
|
||||
} catch (int) {
|
||||
if (vcpu)
|
||||
destroy(_sliced_heap, vcpu);
|
||||
|
||||
return;
|
||||
} catch (...) {
|
||||
if (vcpu)
|
||||
destroy(_sliced_heap, vcpu);
|
||||
|
||||
throw;
|
||||
}
|
||||
|
||||
_vcpus.insert(vcpu);
|
||||
_id_alloc++;
|
||||
};
|
||||
|
||||
_ep.apply(cap, lambda);
|
||||
}
|
||||
|
||||
Dataspace_capability Vm_session_component::_cpu_state(Vcpu_id const vcpu_id)
|
||||
{
|
||||
for (Vcpu *vcpu = _vcpus.first(); vcpu; vcpu = vcpu->next()) {
|
||||
if (!vcpu->match(vcpu_id))
|
||||
continue;
|
||||
|
||||
return vcpu->ds_cap();
|
||||
}
|
||||
|
||||
return Dataspace_capability();
|
||||
}
|
||||
|
||||
void Vm_session_component::attach(Dataspace_capability cap, addr_t guest_phys)
|
||||
{
|
||||
if (!cap.valid())
|
||||
throw Invalid_dataspace();
|
||||
|
||||
/* check dataspace validity */
|
||||
_ep.apply(cap, [&] (Dataspace_component *ptr) {
|
||||
if (!ptr)
|
||||
throw Invalid_dataspace();
|
||||
|
||||
Dataspace_component &dsc = *ptr;
|
||||
|
||||
/* unsupported - deny otherwise arbitrary physical memory can be mapped to a VM */
|
||||
if (dsc.managed())
|
||||
throw Invalid_dataspace();
|
||||
|
||||
Flexpage_iterator flex(dsc.phys_addr(), dsc.size(),
|
||||
guest_phys, dsc.size(), guest_phys);
|
||||
|
||||
using namespace Fiasco;
|
||||
|
||||
uint8_t const flags = dsc.writable() ? L4_FPAGE_RWX : L4_FPAGE_RX;
|
||||
|
||||
Flexpage page = flex.page();
|
||||
while (page.valid()) {
|
||||
l4_fpage_t fp = l4_fpage(page.addr, page.log2_order, flags);
|
||||
l4_msgtag_t msg = l4_task_map(_task_vcpu.local.data()->kcap(),
|
||||
L4_BASE_TASK_CAP, fp,
|
||||
l4_map_obj_control(page.hotspot,
|
||||
L4_MAP_ITEM_MAP));
|
||||
|
||||
if (l4_error(msg))
|
||||
Genode::error("task map failed ", l4_error(msg));
|
||||
|
||||
page = flex.page();
|
||||
}
|
||||
});
|
||||
}
|
1273
repos/base-foc/src/lib/base/x86/vm_session.cc
Normal file
1273
repos/base-foc/src/lib/base/x86/vm_session.cc
Normal file
File diff suppressed because it is too large
Load Diff
@ -18,7 +18,7 @@ if { [get_cmd_switch --autopilot] } {
|
||||
exit 0
|
||||
}
|
||||
|
||||
if {[have_spec nova]} {
|
||||
if {[have_spec nova] || [have_spec foc]} {
|
||||
} else {
|
||||
puts "\n Run script is not supported on this platform. \n";
|
||||
exit 0
|
||||
|
Loading…
Reference in New Issue
Block a user