mirror of
https://github.com/genodelabs/genode.git
synced 2025-01-31 00:24:51 +00:00
parent
7eb6ef226f
commit
537dde1f40
@ -26,7 +26,8 @@
|
||||
#define _INCLUDE__VMM__GUEST_MEMORY_H_
|
||||
|
||||
/* Genode includes */
|
||||
#include <os/attached_ram_dataspace.h>
|
||||
#include <base/attached_ram_dataspace.h>
|
||||
#include <base/env.h>
|
||||
#include <rm_session/connection.h>
|
||||
#include <region_map/client.h>
|
||||
|
||||
@ -48,9 +49,13 @@ namespace Vmm {
|
||||
*/
|
||||
struct Vmm::Virtual_reservation : private Rm_connection, Region_map_client
|
||||
{
|
||||
Virtual_reservation(addr_t vm_size)
|
||||
Genode::Env &_env;
|
||||
|
||||
Virtual_reservation(Genode::Env &env, addr_t vm_size)
|
||||
:
|
||||
Region_map_client(Rm_connection::create(vm_size))
|
||||
Rm_connection(env),
|
||||
Region_map_client(Rm_connection::create(vm_size)),
|
||||
_env(env)
|
||||
{
|
||||
try {
|
||||
/*
|
||||
@ -58,8 +63,8 @@ struct Vmm::Virtual_reservation : private Rm_connection, Region_map_client
|
||||
* space. We leave out the very first page because core denies
|
||||
* the attachment of anything at the zero page.
|
||||
*/
|
||||
env()->rm_session()->attach_at(Region_map_client::dataspace(),
|
||||
PAGE_SIZE, 0, PAGE_SIZE);
|
||||
env.rm().attach_at(Region_map_client::dataspace(), PAGE_SIZE, 0,
|
||||
PAGE_SIZE);
|
||||
|
||||
} catch (Rm_session::Region_conflict) {
|
||||
error("region conflict while attaching guest-physical memory");
|
||||
@ -68,29 +73,9 @@ struct Vmm::Virtual_reservation : private Rm_connection, Region_map_client
|
||||
|
||||
~Virtual_reservation()
|
||||
{
|
||||
env()->rm_session()->detach((void *)PAGE_SIZE);
|
||||
_env.rm().detach((void *)PAGE_SIZE);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Representation of guest memory
|
||||
*
|
||||
*/
|
||||
struct Vmm::Guest_memory : Attached_ram_dataspace
|
||||
{
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* \param backing_store_size number of bytes of physical RAM to be
|
||||
* used as guest-physical and device memory,
|
||||
* allocated from core's RAM service
|
||||
*/
|
||||
Guest_memory(size_t backing_store_size)
|
||||
:
|
||||
Attached_ram_dataspace(env()->ram_session(), backing_store_size)
|
||||
{ }
|
||||
};
|
||||
|
||||
|
||||
#endif /* _INCLUDE__VMM__GUEST_MEMORY_H_ */
|
||||
|
@ -16,7 +16,6 @@
|
||||
|
||||
/* Genode includes */
|
||||
#include <base/thread.h>
|
||||
#include <cap_session/connection.h>
|
||||
#include <cpu_session/connection.h>
|
||||
#include <pd_session/connection.h>
|
||||
#include <region_map/client.h>
|
||||
|
@ -27,8 +27,6 @@ set memory_vmm_vm "512M"
|
||||
|
||||
set vcpus_to_be_used 1
|
||||
|
||||
source ${genode_dir}/repos/ports/run/seoul.inc
|
||||
|
||||
if {[have_include power_on/qemu]} {
|
||||
|
||||
if {![file exists bin/seoul-disc.raw]} {
|
||||
@ -41,4 +39,6 @@ if {[have_include power_on/qemu]} {
|
||||
append_if $use_block_sata qemu_args " -drive id=disk,file=bin/seoul-disc.raw,format=raw,if=none -device ahci,id=ahci -device ide-drive,drive=disk,bus=ahci.0 -boot d"
|
||||
}
|
||||
|
||||
source ${genode_dir}/repos/ports/run/seoul.inc
|
||||
|
||||
run_genode_until forever
|
||||
|
@ -33,7 +33,7 @@ set use_multiboot_modaddr 0x2800000
|
||||
|
||||
# Use a Genode run script of a 32bit platform and turn it into a bootable
|
||||
# setup for Seoul - adjust build_dir and run_script variable accordingly
|
||||
set run_script "printf"
|
||||
set run_script "log"
|
||||
set build_dir "."
|
||||
set run_script_path "$build_dir/var/run/$run_script"
|
||||
set genode_iso "$build_dir/var/run/$run_script.iso"
|
||||
@ -44,7 +44,7 @@ if {[catch {exec cp $genode_iso bin/genode.iso}]} {
|
||||
exit 1
|
||||
}
|
||||
|
||||
set files_vm [exec cat $run_script_path/boot/grub/menu.lst]
|
||||
set files_vm [exec isoinfo -i $genode_iso -x "/BOOT/GRUB/MENU.LST;1"]
|
||||
|
||||
set vm [split $files_vm "\n"]
|
||||
set guest_os_binaries {}
|
||||
|
@ -26,7 +26,6 @@
|
||||
#include <util/string.h>
|
||||
#include <util/misc_math.h>
|
||||
#include <util/xml_node.h>
|
||||
#include <base/env.h>
|
||||
#include <base/log.h>
|
||||
#include <rom_session/connection.h>
|
||||
|
||||
@ -69,7 +68,7 @@ class Boot_module_provider
|
||||
* \return module size in bytes, or 0 if module does not exist
|
||||
* \throw Destination_buffer_too_small
|
||||
*/
|
||||
Genode::size_t data(int module_index,
|
||||
Genode::size_t data(Genode::Env &env, int module_index,
|
||||
void *dst, Genode::size_t dst_len) const
|
||||
{
|
||||
using namespace Genode;
|
||||
@ -94,7 +93,7 @@ class Boot_module_provider
|
||||
/*
|
||||
* Open ROM session
|
||||
*/
|
||||
Rom_connection rom(name);
|
||||
Rom_connection rom(env, name);
|
||||
Dataspace_capability ds = rom.dataspace();
|
||||
Genode::size_t const src_len = Dataspace_client(ds).size();
|
||||
|
||||
@ -103,7 +102,7 @@ class Boot_module_provider
|
||||
throw Destination_buffer_too_small();
|
||||
}
|
||||
|
||||
void * const src = env()->rm_session()->attach(ds);
|
||||
void * const src = env.rm().attach(ds);
|
||||
|
||||
/*
|
||||
* Copy content to destination buffer
|
||||
@ -115,7 +114,7 @@ class Boot_module_provider
|
||||
* session will be closed automatically when we leave the
|
||||
* current scope and the 'rom' object gets destructed.
|
||||
*/
|
||||
env()->rm_session()->detach(src);
|
||||
env.rm().detach(src);
|
||||
|
||||
return src_len;
|
||||
} else if (mod_node.has_type("inline")) {
|
||||
|
@ -2,11 +2,12 @@
|
||||
* \brief Manager of all VM requested console functionality
|
||||
* \author Markus Partheymueller
|
||||
* \author Norman Feske
|
||||
* \author Alexander Boettcher
|
||||
* \date 2012-07-31
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2011-2013 Genode Labs GmbH
|
||||
* Copyright (C) 2011-2017 Genode Labs GmbH
|
||||
* Copyright (C) 2012 Intel Corporation
|
||||
*
|
||||
* This file is distributed under the terms of the GNU General Public License
|
||||
@ -19,30 +20,28 @@
|
||||
* conditions of the GNU General Public License version 2.
|
||||
*/
|
||||
|
||||
/* Genode includes */
|
||||
#include <base/snprintf.h>
|
||||
/* base includes */
|
||||
#include <util/register.h>
|
||||
|
||||
/* nitpicker graphics backend */
|
||||
#include <os/pixel_rgb565.h>
|
||||
#include <nitpicker_gfx/text_painter.h>
|
||||
|
||||
#include <nul/motherboard.h>
|
||||
|
||||
/* local includes */
|
||||
#include "console.h"
|
||||
#include "keyboard.h"
|
||||
|
||||
using Genode::env;
|
||||
using Genode::Dataspace_client;
|
||||
using Genode::Surface;
|
||||
using Genode::Pixel_rgb565;
|
||||
typedef Text_painter::Font Font;
|
||||
|
||||
extern char _binary_mono_tff_start;
|
||||
Font default_font(&_binary_mono_tff_start);
|
||||
Text_painter::Font default_font(&_binary_mono_tff_start);
|
||||
|
||||
bool fb_active = true;
|
||||
static struct {
|
||||
Genode::uint64_t checksum1 = 0;
|
||||
Genode::uint64_t checksum2 = 0;
|
||||
unsigned unchanged = 0;
|
||||
bool cmp_even = 1;
|
||||
bool active = true;
|
||||
bool revoked = false;
|
||||
} fb_state;
|
||||
|
||||
|
||||
/**
|
||||
@ -82,7 +81,7 @@ static bool mouse_event(Input::Event const &ev)
|
||||
*
|
||||
* This function updates _left, _middle, and _right as a side effect.
|
||||
*/
|
||||
unsigned Vancouver_console::_input_to_ps2mouse(Input::Event const &ev)
|
||||
unsigned Seoul::Console::_input_to_ps2mouse(Input::Event const &ev)
|
||||
{
|
||||
/* track state of mouse buttons */
|
||||
using Input::Event;
|
||||
@ -128,7 +127,7 @@ unsigned Vancouver_console::_input_to_ps2mouse(Input::Event const &ev)
|
||||
|
||||
/* bus callbacks */
|
||||
|
||||
bool Vancouver_console::receive(MessageConsole &msg)
|
||||
bool Seoul::Console::receive(MessageConsole &msg)
|
||||
{
|
||||
if (msg.type == MessageConsole::TYPE_ALLOC_VIEW) {
|
||||
_guest_fb = msg.ptr;
|
||||
@ -197,182 +196,190 @@ bool Vancouver_console::receive(MessageConsole &msg)
|
||||
}
|
||||
|
||||
|
||||
bool Vancouver_console::receive(MessageMemRegion &msg)
|
||||
bool Seoul::Console::receive(MessageMemRegion &msg)
|
||||
{
|
||||
if (msg.page >= 0xb8 && msg.page <= 0xbf) {
|
||||
|
||||
/* we had a fault in the text framebuffer */
|
||||
if (!fb_active) fb_active = true;
|
||||
if (!fb_state.active) fb_state.active = true;
|
||||
Logging::printf("Reactivating text buffer loop.\n");
|
||||
|
||||
MessageTimer msg(_timer, _unsynchronized_motherboard.clock()->abstime(1, 1000));
|
||||
_unsynchronized_motherboard.bus_timer.send(msg);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
void Vancouver_console::entry()
|
||||
unsigned Seoul::Console::_handle_fb()
|
||||
{
|
||||
/*
|
||||
* Init sessions to the required external services
|
||||
*/
|
||||
enum { CONFIG_ALPHA = false };
|
||||
if (!_guest_fb || !_regs)
|
||||
return 0;
|
||||
|
||||
static Input::Connection input;
|
||||
static Timer::Connection timer;
|
||||
Framebuffer::Connection *framebuffer = 0;
|
||||
enum { TEXT_MODE = 0 };
|
||||
|
||||
/* transfer text buffer content into chunky canvas */
|
||||
if (_regs->mode == TEXT_MODE) {
|
||||
|
||||
if (fb_state.revoked || !fb_state.active)
|
||||
return 0;
|
||||
|
||||
memset(_pixels, 0, _fb_size);
|
||||
|
||||
if (fb_state.cmp_even) fb_state.checksum1 = 0;
|
||||
else fb_state.checksum2 = 0;
|
||||
|
||||
for (int j=0; j<25; j++) {
|
||||
for (int i=0; i<80; i++) {
|
||||
Genode::Surface_base::Point where(i*8, j*15);
|
||||
char character = *((char *) (_guest_fb +(_regs->offset << 1) +j*80*2+i*2));
|
||||
char colorvalue = *((char *) (_guest_fb+(_regs->offset << 1)+j*80*2+i*2+1));
|
||||
char buffer[2]; buffer[0] = character; buffer[1] = 0;
|
||||
char fg = colorvalue & 0xf;
|
||||
if (fg == 0x8) fg = 0x7;
|
||||
unsigned lum = ((fg & 0x8) >> 3)*127;
|
||||
Genode::Color color(((fg & 0x4) >> 2)*127+lum, /* R+luminosity */
|
||||
((fg & 0x2) >> 1)*127+lum, /* G+luminosity */
|
||||
(fg & 0x1)*127+lum /* B+luminosity */);
|
||||
|
||||
Text_painter::paint(*_surface, where, default_font, color, buffer);
|
||||
|
||||
/* Checksum for comparing */
|
||||
if (fb_state.cmp_even) fb_state.checksum1 += character;
|
||||
else fb_state.checksum2 += character;
|
||||
}
|
||||
}
|
||||
|
||||
fb_state.cmp_even = !fb_state.cmp_even;
|
||||
|
||||
/* compare checksums to detect changed buffer */
|
||||
if (fb_state.checksum1 != fb_state.checksum2) {
|
||||
fb_state.unchanged = 0;
|
||||
_framebuffer->refresh(0, 0, _fb_mode.width(), _fb_mode.height());
|
||||
return 100;
|
||||
}
|
||||
|
||||
if (++fb_state.unchanged < 10)
|
||||
return fb_state.unchanged * 30;
|
||||
|
||||
/* if we copy the same data 10 times, unmap the text buffer from guest */
|
||||
_env.rm().detach((void *)_guest_fb);
|
||||
_env.rm().attach_at(_fb_ds, (Genode::addr_t)_guest_fb);
|
||||
|
||||
fb_state.unchanged = 0;
|
||||
fb_state.active = false;
|
||||
|
||||
Logging::printf("Deactivated text buffer loop.\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!fb_state.revoked) {
|
||||
|
||||
_env.rm().detach((void *)_guest_fb);
|
||||
_env.rm().attach_at(_framebuffer->dataspace(),
|
||||
(Genode::addr_t)_guest_fb);
|
||||
|
||||
/* if the VGA model expects a larger FB, pad to that size. */
|
||||
if (_fb_size < _vm_fb_size) {
|
||||
Genode::Ram_dataspace_capability _backup =
|
||||
_env.ram().alloc(_vm_fb_size-_fb_size);
|
||||
|
||||
_env.rm().attach_at(_backup,
|
||||
(Genode::addr_t) (_guest_fb+_fb_size));
|
||||
}
|
||||
|
||||
fb_state.revoked = true;
|
||||
}
|
||||
_framebuffer->refresh(0, 0, _fb_mode.width(), _fb_mode.height());
|
||||
return 10;
|
||||
}
|
||||
|
||||
|
||||
void Seoul::Console::_handle_input()
|
||||
{
|
||||
_input.for_each_event([&] (Input::Event const &ev) {
|
||||
|
||||
if (!fb_state.active) {
|
||||
fb_state.active = true;
|
||||
|
||||
MessageTimer msg(_timer, _motherboard()->clock()->abstime(1, 1000));
|
||||
_motherboard()->bus_timer.send(msg);
|
||||
}
|
||||
|
||||
/* update mouse model (PS2) */
|
||||
if (mouse_event(ev)) {
|
||||
MessageInput msg(0x10001, _input_to_ps2mouse(ev));
|
||||
_motherboard()->bus_input.send(msg);
|
||||
}
|
||||
|
||||
if (ev.type() == Input::Event::PRESS) {
|
||||
if (ev.code() <= 0xee) {
|
||||
_vkeyb.handle_keycode_press(ev.code());
|
||||
}
|
||||
}
|
||||
if (ev.type() == Input::Event::RELEASE) {
|
||||
if (ev.code() <= 0xee) { /* keyboard event */
|
||||
_vkeyb.handle_keycode_release(ev.code());
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
void Seoul::Console::register_host_operations(Motherboard &motherboard)
|
||||
{
|
||||
motherboard.bus_console .add(this, receive_static<MessageConsole>);
|
||||
motherboard.bus_memregion.add(this, receive_static<MessageMemRegion>);
|
||||
motherboard.bus_timeout .add(this, receive_static<MessageTimeout>);
|
||||
|
||||
MessageTimer msg;
|
||||
if (!motherboard.bus_timer.send(msg))
|
||||
Logging::panic("%s can't get a timer", __PRETTY_FUNCTION__);
|
||||
|
||||
_timer = msg.nr;
|
||||
}
|
||||
|
||||
|
||||
bool Seoul::Console::receive(MessageTimeout &msg) {
|
||||
if (msg.nr != _timer)
|
||||
return false;
|
||||
|
||||
unsigned next_timeout_ms = _handle_fb();
|
||||
|
||||
if (next_timeout_ms) {
|
||||
MessageTimer msg_t(_timer, _unsynchronized_motherboard.clock()->abstime(next_timeout_ms, 1000));
|
||||
_unsynchronized_motherboard.bus_timer.send(msg_t);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
Seoul::Console::Console(Genode::Env &env, Synced_motherboard &mb,
|
||||
Motherboard &unsynchronized_motherboard,
|
||||
Genode::size_t vm_fb_size,
|
||||
Genode::Dataspace_capability fb_ds)
|
||||
:
|
||||
_env(env),
|
||||
_unsynchronized_motherboard(unsynchronized_motherboard),
|
||||
_motherboard(mb), _fb_ds(fb_ds), _vm_fb_size(vm_fb_size)
|
||||
{
|
||||
_input.sigh(_signal_input);
|
||||
|
||||
try {
|
||||
framebuffer = new (env()->heap()) Framebuffer::Connection();
|
||||
using Framebuffer::Mode;
|
||||
_framebuffer.construct(_env, Mode(0, 0, Mode::INVALID));
|
||||
} catch (...) {
|
||||
Genode::error("Headless mode - no framebuffer session available");
|
||||
_startup_lock.unlock();
|
||||
return;
|
||||
}
|
||||
|
||||
_fb_size = Dataspace_client(framebuffer->dataspace()).size();
|
||||
_fb_mode = framebuffer->mode();
|
||||
_fb_size = Genode::Dataspace_client(_framebuffer->dataspace()).size();
|
||||
_fb_mode = _framebuffer->mode();
|
||||
_pixels = _env.rm().attach(_framebuffer->dataspace());
|
||||
|
||||
_pixels = env()->rm_session()->attach(framebuffer->dataspace());
|
||||
|
||||
Surface<Pixel_rgb565> surface((Pixel_rgb565 *) _pixels,
|
||||
Genode::Surface_base::Area(_fb_mode.width(),
|
||||
_fb_mode.height()));
|
||||
|
||||
/*
|
||||
* Handle input events
|
||||
*/
|
||||
unsigned long count = 0;
|
||||
bool revoked = false;
|
||||
Vancouver_keyboard vkeyb(_motherboard);
|
||||
|
||||
Genode::uint64_t checksum1 = 0;
|
||||
Genode::uint64_t checksum2 = 0;
|
||||
unsigned unchanged = 0;
|
||||
bool cmp_even = 1;
|
||||
|
||||
_startup_lock.unlock();
|
||||
|
||||
while (1) {
|
||||
while (!input.pending()) {
|
||||
|
||||
/* transfer text buffer content into chunky canvas */
|
||||
if (_regs && ++count % 10 == 0 && _regs->mode == 0
|
||||
&& _guest_fb && !revoked && fb_active) {
|
||||
|
||||
memset(_pixels, 0, _fb_size);
|
||||
if (cmp_even) checksum1 = 0;
|
||||
else checksum2 = 0;
|
||||
for (int j=0; j<25; j++) {
|
||||
for (int i=0; i<80; i++) {
|
||||
Genode::Surface_base::Point where(i*8, j*15);
|
||||
char character = *((char *) (_guest_fb +(_regs->offset << 1) +j*80*2+i*2));
|
||||
char colorvalue = *((char *) (_guest_fb+(_regs->offset << 1)+j*80*2+i*2+1));
|
||||
char buffer[2]; buffer[0] = character; buffer[1] = 0;
|
||||
char fg = colorvalue & 0xf;
|
||||
if (fg == 0x8) fg = 0x7;
|
||||
unsigned lum = ((fg & 0x8) >> 3)*127;
|
||||
Genode::Color color(((fg & 0x4) >> 2)*127+lum, /* R+luminosity */
|
||||
((fg & 0x2) >> 1)*127+lum, /* G+luminosity */
|
||||
(fg & 0x1)*127+lum /* B+luminosity */);
|
||||
|
||||
Text_painter::paint(surface, where, default_font, color, buffer);
|
||||
|
||||
/* Checksum for comparing */
|
||||
if (cmp_even) checksum1 += character;
|
||||
else checksum2 += character;
|
||||
}
|
||||
}
|
||||
/* compare checksums to detect idle buffer */
|
||||
if (checksum1 == checksum2) {
|
||||
unchanged++;
|
||||
|
||||
/* if we copy the same data 10 times, unmap the text buffer from guest */
|
||||
if (unchanged == 10) {
|
||||
|
||||
Genode::Lock::Guard guard(_console_lock);
|
||||
|
||||
env()->rm_session()->detach((void *)_guest_fb);
|
||||
env()->rm_session()->attach_at(_fb_ds, (Genode::addr_t)_guest_fb);
|
||||
unchanged = 0;
|
||||
fb_active = false;
|
||||
|
||||
Logging::printf("Deactivated text buffer loop.\n");
|
||||
}
|
||||
} else {
|
||||
unchanged = 0;
|
||||
framebuffer->refresh(0, 0, _fb_mode.width(), _fb_mode.height());
|
||||
}
|
||||
|
||||
cmp_even = !cmp_even;
|
||||
} else if (_regs && _guest_fb && _regs->mode != 0) {
|
||||
|
||||
if (!revoked) {
|
||||
|
||||
Genode::Lock::Guard guard(_console_lock);
|
||||
|
||||
env()->rm_session()->detach((void *)_guest_fb);
|
||||
env()->rm_session()->attach_at(framebuffer->dataspace(),
|
||||
(Genode::addr_t)_guest_fb);
|
||||
|
||||
/* if the VGA model expects a larger FB, pad to that size. */
|
||||
if (_fb_size < _vm_fb_size) {
|
||||
Genode::Ram_dataspace_capability _backup =
|
||||
Genode::env()->ram_session()->alloc(_vm_fb_size-_fb_size);
|
||||
|
||||
env()->rm_session()->attach_at(_backup,
|
||||
(Genode::addr_t) (_guest_fb+_fb_size));
|
||||
}
|
||||
|
||||
revoked = true;
|
||||
}
|
||||
framebuffer->refresh(0, 0, _fb_mode.width(), _fb_mode.height());
|
||||
}
|
||||
|
||||
timer.msleep(10);
|
||||
}
|
||||
|
||||
input.for_each_event([&] (Input::Event const &ev) {
|
||||
if (!fb_active) fb_active = true;
|
||||
|
||||
/* update mouse model (PS2) */
|
||||
if (mouse_event(ev)) {
|
||||
MessageInput msg(0x10001, _input_to_ps2mouse(ev));
|
||||
_motherboard()->bus_input.send(msg);
|
||||
}
|
||||
|
||||
if (ev.type() == Input::Event::PRESS) {
|
||||
if (ev.code() <= 0xee) {
|
||||
vkeyb.handle_keycode_press(ev.code());
|
||||
}
|
||||
}
|
||||
if (ev.type() == Input::Event::RELEASE) {
|
||||
if (ev.code() <= 0xee) { /* keyboard event */
|
||||
vkeyb.handle_keycode_release(ev.code());
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Vancouver_console::register_host_operations(Motherboard &motherboard)
|
||||
{
|
||||
motherboard.bus_console. add(this, receive_static<MessageConsole>);
|
||||
motherboard.bus_memregion.add(this, receive_static<MessageMemRegion>);
|
||||
}
|
||||
|
||||
|
||||
Vancouver_console::Vancouver_console(Synced_motherboard &mb,
|
||||
Genode::size_t vm_fb_size,
|
||||
Genode::Dataspace_capability fb_ds)
|
||||
:
|
||||
Thread_deprecated("vmm_console"),
|
||||
_startup_lock(Genode::Lock::LOCKED),
|
||||
_motherboard(mb), _pixels(0), _guest_fb(0), _fb_size(0),
|
||||
_fb_ds(fb_ds), _vm_fb_size(vm_fb_size), _regs(0),
|
||||
_left(false), _middle(false), _right(false)
|
||||
{
|
||||
start();
|
||||
|
||||
/* shake hands with console thread */
|
||||
_startup_lock.lock();
|
||||
_surface.construct(reinterpret_cast<Genode::Pixel_rgb565 *>(_pixels),
|
||||
Genode::Surface_base::Area(_fb_mode.width(),
|
||||
_fb_mode.height()));
|
||||
}
|
||||
|
@ -21,59 +21,73 @@
|
||||
#ifndef _CONSOLE_H_
|
||||
#define _CONSOLE_H_
|
||||
|
||||
/* Genode includes */
|
||||
/* base includes */
|
||||
#include <base/env.h>
|
||||
#include <dataspace/client.h>
|
||||
#include <util/reconstructible.h>
|
||||
#include <util/string.h>
|
||||
|
||||
/* os includes */
|
||||
#include <framebuffer_session/connection.h>
|
||||
#include <input/event.h>
|
||||
#include <input_session/connection.h>
|
||||
#include <timer_session/connection.h>
|
||||
#include <dataspace/client.h>
|
||||
|
||||
#include <os/pixel_rgb565.h>
|
||||
|
||||
/* local includes */
|
||||
#include "keyboard.h"
|
||||
#include "synced_motherboard.h"
|
||||
|
||||
/* includes for I/O */
|
||||
#include <base/env.h>
|
||||
#include <util/list.h>
|
||||
#include <input/event.h>
|
||||
namespace Seoul {
|
||||
class Console;
|
||||
}
|
||||
|
||||
using Genode::List;
|
||||
using Genode::Thread_deprecated;
|
||||
|
||||
class Vancouver_console : public Thread_deprecated<8192>, public StaticReceiver<Vancouver_console>
|
||||
class Seoul::Console : public StaticReceiver<Seoul::Console>
|
||||
{
|
||||
private:
|
||||
|
||||
Genode::Lock _startup_lock;
|
||||
Genode::Env &_env;
|
||||
Motherboard &_unsynchronized_motherboard;
|
||||
Synced_motherboard &_motherboard;
|
||||
Genode::Lock _console_lock;
|
||||
short *_pixels;
|
||||
char *_guest_fb;
|
||||
unsigned long _fb_size;
|
||||
Genode::Constructible<Framebuffer::Connection> _framebuffer;
|
||||
Genode::Constructible<Genode::Surface<Genode::Pixel_rgb565> > _surface;
|
||||
Input::Connection _input = { _env };
|
||||
Keyboard _vkeyb = { _motherboard };
|
||||
short *_pixels = nullptr;
|
||||
char *_guest_fb = nullptr;
|
||||
unsigned long _fb_size = 0;
|
||||
Genode::Dataspace_capability _fb_ds;
|
||||
Genode::size_t _vm_fb_size;
|
||||
VgaRegs *_regs;
|
||||
VgaRegs *_regs = nullptr;
|
||||
Framebuffer::Mode _fb_mode;
|
||||
bool _left, _middle, _right;
|
||||
bool _left = false;
|
||||
bool _middle = false;
|
||||
bool _right = false;
|
||||
unsigned _timer;
|
||||
|
||||
unsigned _input_to_ps2mouse(Input::Event const &);
|
||||
|
||||
Genode::Signal_handler<Console> _signal_input
|
||||
= { _env.ep(), *this, &Console::_handle_input };
|
||||
|
||||
void _handle_input();
|
||||
unsigned _handle_fb();
|
||||
|
||||
public:
|
||||
|
||||
/* bus callbacks */
|
||||
bool receive(MessageConsole &msg);
|
||||
bool receive(MessageMemRegion &msg);
|
||||
bool receive(MessageConsole &);
|
||||
bool receive(MessageMemRegion &);
|
||||
bool receive(MessageTimeout &);
|
||||
|
||||
void register_host_operations(Motherboard &);
|
||||
|
||||
/* initialisation */
|
||||
void entry();
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
Vancouver_console(Synced_motherboard &,
|
||||
Genode::size_t vm_fb_size,
|
||||
Genode::Dataspace_capability fb_ds);
|
||||
Console(Genode::Env &env, Synced_motherboard &, Motherboard &,
|
||||
Genode::size_t vm_fb_size, Genode::Dataspace_capability fb_ds);
|
||||
};
|
||||
|
||||
#endif /* _CONSOLE_H_ */
|
||||
|
@ -20,14 +20,9 @@
|
||||
*/
|
||||
|
||||
/* Genode includes */
|
||||
#include <base/allocator_avl.h>
|
||||
#include <base/log.h>
|
||||
#include <base/sleep.h>
|
||||
#include <base/thread.h>
|
||||
#include <block_session/connection.h>
|
||||
#include <util/string.h>
|
||||
#include <base/heap.h>
|
||||
#include <base/lock.h>
|
||||
|
||||
/* VMM utility includes */
|
||||
#include <vmm/utcb_guard.h>
|
||||
@ -38,71 +33,52 @@
|
||||
/* Seoul includes */
|
||||
#include <host/dma.h>
|
||||
|
||||
static Genode::Signal_receiver* disk_receiver()
|
||||
static Genode::Heap * disk_heap(Genode::Ram_session *ram = nullptr,
|
||||
Genode::Region_map *rm = nullptr)
|
||||
{
|
||||
static Genode::Signal_receiver receiver;
|
||||
return &receiver;
|
||||
}
|
||||
|
||||
|
||||
static Genode::Heap * disk_heap() {
|
||||
using namespace Genode;
|
||||
static Heap heap(env()->ram_session(), env()->rm_session());
|
||||
static Genode::Heap heap(ram, rm);
|
||||
return &heap;
|
||||
}
|
||||
static Genode::Heap * disk_heap_msg() {
|
||||
using namespace Genode;
|
||||
static Heap heap(env()->ram_session(), env()->rm_session(), 4096);
|
||||
static Genode::Heap * disk_heap_msg(Genode::Env &env)
|
||||
{
|
||||
static Genode::Heap heap(&env.ram(), &env.rm(), 4096);
|
||||
return &heap;
|
||||
}
|
||||
static Genode::Heap * disk_heap_avl() {
|
||||
using namespace Genode;
|
||||
static Heap heap(env()->ram_session(), env()->rm_session(), 4096);
|
||||
static Genode::Heap * disk_heap_avl(Genode::Env &env)
|
||||
{
|
||||
static Genode::Heap heap(&env.ram(), &env.rm(), 4096);
|
||||
return &heap;
|
||||
}
|
||||
|
||||
|
||||
Vancouver_disk::Vancouver_disk(Synced_motherboard &mb,
|
||||
char * backing_store_base,
|
||||
Genode::size_t backing_store_size)
|
||||
Seoul::Disk::Disk(Genode::Env &env, Synced_motherboard &mb,
|
||||
char * backing_store_base, Genode::size_t backing_store_size)
|
||||
:
|
||||
Thread_deprecated("vmm_disk"),
|
||||
_env(env),
|
||||
_motherboard(mb),
|
||||
_backing_store_base(backing_store_base),
|
||||
_backing_store_size(backing_store_size),
|
||||
_tslab_msg(disk_heap_msg()),
|
||||
_tslab_avl(disk_heap_avl())
|
||||
_tslab_msg(disk_heap_msg(env)),
|
||||
_tslab_avl(disk_heap_avl(env))
|
||||
{
|
||||
/* initialize disk heap */
|
||||
disk_heap(&env.ram(), &env.rm());
|
||||
|
||||
/* initialize struct with 0 size */
|
||||
for (int i=0; i < MAX_DISKS; i++) {
|
||||
_diskcon[i].blk_size = 0;
|
||||
}
|
||||
|
||||
start();
|
||||
}
|
||||
|
||||
|
||||
void Vancouver_disk::register_host_operations(Motherboard &motherboard)
|
||||
void Seoul::Disk::register_host_operations(Motherboard &motherboard)
|
||||
{
|
||||
motherboard.bus_disk.add(this, receive_static<MessageDisk>);
|
||||
}
|
||||
|
||||
void Seoul::Disk_signal::_signal() { _obj.handle_disk(_id); }
|
||||
|
||||
void Vancouver_disk::entry()
|
||||
{
|
||||
Logging::printf("Hello, this is Vancouver_disk.\n");
|
||||
|
||||
while (true) {
|
||||
Genode::Signal signal = disk_receiver()->wait_for_signal();
|
||||
Vancouver_disk_signal * disk_source =
|
||||
reinterpret_cast<Vancouver_disk_signal *>(signal.context());
|
||||
|
||||
this->_signal_dispatch_entry(disk_source->disk_nr());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Vancouver_disk::_signal_dispatch_entry(unsigned disknr)
|
||||
void Seoul::Disk::handle_disk(unsigned disknr)
|
||||
{
|
||||
Block::Session::Tx::Source *source = _diskcon[disknr].blk_con->tx();
|
||||
|
||||
@ -179,7 +155,7 @@ void Vancouver_disk::_signal_dispatch_entry(unsigned disknr)
|
||||
}
|
||||
|
||||
|
||||
bool Vancouver_disk::receive(MessageDisk &msg)
|
||||
bool Seoul::Disk::receive(MessageDisk &msg)
|
||||
{
|
||||
static Vmm::Utcb_guard::Utcb_backup utcb_backup;
|
||||
Vmm::Utcb_guard guard(utcb_backup);
|
||||
@ -191,23 +167,23 @@ bool Vancouver_disk::receive(MessageDisk &msg)
|
||||
* If we receive a message for this disk the first time, create the
|
||||
* structure for it.
|
||||
*/
|
||||
char label[16];
|
||||
Genode::snprintf(label, 16, "VirtualDisk %u", msg.disknr);
|
||||
Genode::String<16> label("VirtualDisk ", msg.disknr);
|
||||
|
||||
if (!_diskcon[msg.disknr].blk_size) {
|
||||
try {
|
||||
Genode::Allocator_avl * block_alloc =
|
||||
new Genode::Allocator_avl(disk_heap());
|
||||
new (disk_heap()) Genode::Allocator_avl(disk_heap());
|
||||
|
||||
_diskcon[msg.disknr].blk_con =
|
||||
new Block::Connection(block_alloc, 4*512*1024, label);
|
||||
_diskcon[msg.disknr].dispatcher =
|
||||
new Vancouver_disk_signal(*disk_receiver(), *this,
|
||||
&Vancouver_disk::_signal_dispatch_entry,
|
||||
msg.disknr);
|
||||
new (disk_heap()) Block::Connection(_env, block_alloc,
|
||||
4*512*1024,
|
||||
label.string());
|
||||
_diskcon[msg.disknr].signal =
|
||||
new (disk_heap()) Seoul::Disk_signal(_env.ep(), *this,
|
||||
msg.disknr);
|
||||
|
||||
_diskcon[msg.disknr].blk_con->tx_channel()->sigh_ack_avail(
|
||||
*_diskcon[msg.disknr].dispatcher);
|
||||
_diskcon[msg.disknr].signal->sigh);
|
||||
} catch (...) {
|
||||
/* there is none. */
|
||||
return false;
|
||||
@ -234,8 +210,7 @@ bool Vancouver_disk::receive(MessageDisk &msg)
|
||||
msg.params->sectors = _diskcon[msg.disknr].blk_cnt;
|
||||
msg.params->sectorsize = _diskcon[msg.disknr].blk_size;
|
||||
msg.params->maxrequestcount = _diskcon[msg.disknr].blk_cnt;
|
||||
memcpy(msg.params->name, label, strlen(label));
|
||||
msg.params->name[strlen(label)] = 0;
|
||||
memcpy(msg.params->name, label.string(), label.length());
|
||||
}
|
||||
return true;
|
||||
case MessageDisk::DISK_READ:
|
||||
@ -328,7 +303,7 @@ bool Vancouver_disk::receive(MessageDisk &msg)
|
||||
}
|
||||
|
||||
|
||||
Vancouver_disk::~Vancouver_disk()
|
||||
Seoul::Disk::~Disk()
|
||||
{
|
||||
/* XXX: Close all connections */
|
||||
}
|
||||
|
@ -7,7 +7,7 @@
|
||||
|
||||
/*
|
||||
* Copyright (C) 2012 Intel Corporation
|
||||
* Copyright (C) 2013 Genode Labs GmbH
|
||||
* Copyright (C) 2013-2017 Genode Labs GmbH
|
||||
*
|
||||
* This file is distributed under the terms of the GNU General Public License
|
||||
* version 2.
|
||||
@ -19,13 +19,11 @@
|
||||
* conditions of the GNU General Public License version 2.
|
||||
*/
|
||||
|
||||
#ifndef _VANCOUVER_DISK_H_
|
||||
#define _VANCOUVER_DISK_H_
|
||||
#ifndef _DISK_H_
|
||||
#define _DISK_H_
|
||||
|
||||
/* Genode includes */
|
||||
#include <base/allocator_avl.h>
|
||||
#include <base/printf.h>
|
||||
#include <base/thread.h>
|
||||
#include <block_session/connection.h>
|
||||
#include <util/string.h>
|
||||
#include <base/synced_allocator.h>
|
||||
@ -33,31 +31,37 @@
|
||||
/* local includes */
|
||||
#include "synced_motherboard.h"
|
||||
|
||||
class Vancouver_disk;
|
||||
namespace Seoul {
|
||||
class Disk;
|
||||
class Disk_signal;
|
||||
}
|
||||
|
||||
class Vancouver_disk_signal : public Genode::Signal_dispatcher<Vancouver_disk>
|
||||
class Seoul::Disk_signal
|
||||
{
|
||||
private:
|
||||
|
||||
unsigned _disk_nr;
|
||||
Disk &_obj;
|
||||
unsigned _id;
|
||||
|
||||
void _signal();
|
||||
|
||||
public:
|
||||
|
||||
Vancouver_disk_signal(Genode::Signal_receiver &sig_rec,
|
||||
Vancouver_disk &obj,
|
||||
void (Vancouver_disk::*member)(unsigned),
|
||||
unsigned disk_nr)
|
||||
: Genode::Signal_dispatcher<Vancouver_disk>(sig_rec, obj, member),
|
||||
_disk_nr(disk_nr) {}
|
||||
Genode::Signal_handler<Disk_signal> const sigh;
|
||||
|
||||
unsigned disk_nr() { return _disk_nr; }
|
||||
Disk_signal(Genode::Entrypoint &ep, Disk &obj, unsigned disk_nr)
|
||||
:
|
||||
_obj(obj), _id(disk_nr), sigh(ep, *this, &Disk_signal::_signal)
|
||||
{ }
|
||||
};
|
||||
|
||||
|
||||
class Vancouver_disk : public Genode::Thread_deprecated<8192>, public StaticReceiver<Vancouver_disk>
|
||||
class Seoul::Disk : public StaticReceiver<Seoul::Disk>
|
||||
{
|
||||
private:
|
||||
|
||||
Genode::Env &_env;
|
||||
|
||||
/* helper class to lookup a MessageDisk object */
|
||||
class Avl_entry : public Genode::Avl_node<Avl_entry>
|
||||
{
|
||||
@ -91,7 +95,7 @@ class Vancouver_disk : public Genode::Thread_deprecated<8192>, public StaticRece
|
||||
Block::Session::Operations ops;
|
||||
Genode::size_t blk_size;
|
||||
Block::sector_t blk_cnt;
|
||||
Vancouver_disk_signal *dispatcher;
|
||||
Disk_signal *signal;
|
||||
} _diskcon[MAX_DISKS];
|
||||
|
||||
Synced_motherboard &_motherboard;
|
||||
@ -113,25 +117,21 @@ class Vancouver_disk : public Genode::Thread_deprecated<8192>, public StaticRece
|
||||
Genode::Avl_tree<Avl_entry> _lookup_msg;
|
||||
Genode::Lock _lookup_msg_lock;
|
||||
|
||||
/* entry function if signal must be dispatched */
|
||||
void _signal_dispatch_entry(unsigned);
|
||||
|
||||
public:
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
Vancouver_disk(Synced_motherboard &,
|
||||
char * backing_store_base,
|
||||
Genode::size_t backing_store_size);
|
||||
Disk(Genode::Env &, Synced_motherboard &, char * backing_store_base,
|
||||
Genode::size_t backing_store_size);
|
||||
|
||||
~Vancouver_disk();
|
||||
~Disk();
|
||||
|
||||
void entry();
|
||||
void handle_disk(unsigned);
|
||||
|
||||
bool receive(MessageDisk &msg);
|
||||
|
||||
void register_host_operations(Motherboard &);
|
||||
};
|
||||
|
||||
#endif /* _VANCOUVER_DISK_H_ */
|
||||
#endif /* _DISK_H_ */
|
||||
|
@ -26,14 +26,12 @@
|
||||
#include <nul/vcpu.h>
|
||||
|
||||
|
||||
Vancouver_keyboard::Vancouver_keyboard(Synced_motherboard &mb)
|
||||
Seoul::Keyboard::Keyboard(Synced_motherboard &mb)
|
||||
: _motherboard(mb), _flags(0) { }
|
||||
|
||||
|
||||
void Vancouver_keyboard::handle_keycode_press(unsigned keycode)
|
||||
bool Seoul::Keyboard::_map_keycode(unsigned &keycode, bool press)
|
||||
{
|
||||
unsigned orig_keycode = keycode;
|
||||
|
||||
switch (keycode) {
|
||||
|
||||
/* modifiers */
|
||||
@ -43,9 +41,12 @@ void Vancouver_keyboard::handle_keycode_press(unsigned keycode)
|
||||
case Input::KEY_RIGHTALT: _flags |= KBFLAG_RALT; keycode = 0x11; break;
|
||||
case Input::KEY_LEFTCTRL: _flags |= KBFLAG_LCTRL; keycode = 0x14; break;
|
||||
case Input::KEY_RIGHTCTRL: _flags |= KBFLAG_RCTRL; keycode = 0x14; break;
|
||||
case Input::KEY_LEFTMETA: _flags |= KBFLAG_LWIN; keycode = 0x1f; return;
|
||||
case Input::KEY_RIGHTMETA: _flags |= KBFLAG_RWIN; keycode = 0x27; return;
|
||||
|
||||
case Input::KEY_LEFTMETA: _flags |= KBFLAG_LWIN; keycode = 0x1f;
|
||||
if (press) return false;
|
||||
break;
|
||||
case Input::KEY_RIGHTMETA: _flags |= KBFLAG_RWIN; keycode = 0x27;
|
||||
if (press) return false;
|
||||
break;
|
||||
case Input::KEY_KPSLASH: _flags |= KBFLAG_EXTEND0;
|
||||
keycode = GenericKeyboard::translate_sc1_to_sc2(0x35); break;
|
||||
case Input::KEY_KPENTER: _flags |= KBFLAG_EXTEND0;
|
||||
@ -80,9 +81,20 @@ void Vancouver_keyboard::handle_keycode_press(unsigned keycode)
|
||||
if (keycode <= 0x53) {
|
||||
keycode = GenericKeyboard::translate_sc1_to_sc2(keycode);
|
||||
break;
|
||||
} else return;
|
||||
} else return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
void Seoul::Keyboard::handle_keycode_press(unsigned keycode)
|
||||
{
|
||||
unsigned orig_keycode = keycode;
|
||||
|
||||
if (!_map_keycode(keycode, true))
|
||||
return;
|
||||
|
||||
MessageInput msg(0x10000, _flags | keycode);
|
||||
|
||||
/* debug */
|
||||
@ -108,58 +120,12 @@ void Vancouver_keyboard::handle_keycode_press(unsigned keycode)
|
||||
}
|
||||
|
||||
|
||||
void Vancouver_keyboard::handle_keycode_release(unsigned keycode)
|
||||
void Seoul::Keyboard::handle_keycode_release(unsigned keycode)
|
||||
{
|
||||
_flags |= KBFLAG_RELEASE;
|
||||
|
||||
switch (keycode) {
|
||||
|
||||
/* modifiers */
|
||||
case Input::KEY_LEFTSHIFT: _flags |= KBFLAG_LSHIFT; keycode = 0x12; break;
|
||||
case Input::KEY_RIGHTSHIFT: _flags |= KBFLAG_RSHIFT; keycode = 0x59; break;
|
||||
case Input::KEY_LEFTALT: _flags |= KBFLAG_LALT; keycode = 0x11; break;
|
||||
case Input::KEY_RIGHTALT: _flags |= KBFLAG_RALT; keycode = 0x11; break;
|
||||
case Input::KEY_LEFTCTRL: _flags |= KBFLAG_LCTRL; keycode = 0x14; break;
|
||||
case Input::KEY_RIGHTCTRL: _flags |= KBFLAG_RCTRL; keycode = 0x14; break;
|
||||
case Input::KEY_LEFTMETA: _flags |= KBFLAG_LWIN; keycode = 0x1f; break;
|
||||
case Input::KEY_RIGHTMETA: _flags |= KBFLAG_RWIN; keycode = 0x27; break;
|
||||
|
||||
case Input::KEY_KPSLASH: _flags |= KBFLAG_EXTEND0;
|
||||
keycode = GenericKeyboard::translate_sc1_to_sc2(0x35); break;
|
||||
case Input::KEY_KPENTER: _flags |= KBFLAG_EXTEND0;
|
||||
keycode = GenericKeyboard::translate_sc1_to_sc2(0x1c); break;
|
||||
case Input::KEY_F11: _flags |= KBFLAG_EXTEND0;
|
||||
keycode = GenericKeyboard::translate_sc1_to_sc2(0x57); break;
|
||||
case Input::KEY_F12: _flags |= KBFLAG_EXTEND0;
|
||||
keycode = GenericKeyboard::translate_sc1_to_sc2(0x58); break;
|
||||
case Input::KEY_INSERT: _flags |= KBFLAG_EXTEND0;
|
||||
keycode = GenericKeyboard::translate_sc1_to_sc2(0x52); break;
|
||||
case Input::KEY_DELETE: _flags |= KBFLAG_EXTEND0;
|
||||
keycode = GenericKeyboard::translate_sc1_to_sc2(0x53); break;
|
||||
case Input::KEY_HOME: _flags |= KBFLAG_EXTEND0;
|
||||
keycode = GenericKeyboard::translate_sc1_to_sc2(0x47); break;
|
||||
case Input::KEY_END: _flags |= KBFLAG_EXTEND0;
|
||||
keycode = GenericKeyboard::translate_sc1_to_sc2(0x4f); break;
|
||||
case Input::KEY_PAGEUP: _flags |= KBFLAG_EXTEND0;
|
||||
keycode = GenericKeyboard::translate_sc1_to_sc2(0x49); break;
|
||||
case Input::KEY_PAGEDOWN: _flags |= KBFLAG_EXTEND0;
|
||||
keycode = GenericKeyboard::translate_sc1_to_sc2(0x51); break;
|
||||
case Input::KEY_LEFT: _flags |= KBFLAG_EXTEND0;
|
||||
keycode = GenericKeyboard::translate_sc1_to_sc2(0x4b); break;
|
||||
case Input::KEY_RIGHT: _flags |= KBFLAG_EXTEND0;
|
||||
keycode = GenericKeyboard::translate_sc1_to_sc2(0x4d); break;
|
||||
case Input::KEY_UP: _flags |= KBFLAG_EXTEND0;
|
||||
keycode = GenericKeyboard::translate_sc1_to_sc2(0x48); break;
|
||||
case Input::KEY_DOWN: _flags |= KBFLAG_EXTEND0;
|
||||
keycode = GenericKeyboard::translate_sc1_to_sc2(0x50); break;
|
||||
|
||||
/* up to 0x53, the Genode key codes correspond to scan code set 1 */
|
||||
default:
|
||||
if (keycode <= 0x53) {
|
||||
keycode = GenericKeyboard::translate_sc1_to_sc2(keycode);
|
||||
break;
|
||||
} else return;
|
||||
}
|
||||
if (!_map_keycode(keycode, false))
|
||||
return;
|
||||
|
||||
MessageInput msg(0x10000, _flags | keycode);
|
||||
_motherboard()->bus_input.send(msg);
|
||||
|
@ -30,19 +30,25 @@
|
||||
/* local includes */
|
||||
#include "synced_motherboard.h"
|
||||
|
||||
class Vancouver_keyboard
|
||||
namespace Seoul {
|
||||
class Keyboard;
|
||||
}
|
||||
|
||||
class Seoul::Keyboard
|
||||
{
|
||||
private:
|
||||
|
||||
Synced_motherboard &_motherboard;
|
||||
unsigned _flags;
|
||||
|
||||
bool _map_keycode(unsigned &, bool);
|
||||
|
||||
public:
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
Vancouver_keyboard(Synced_motherboard &);
|
||||
Keyboard(Synced_motherboard &);
|
||||
|
||||
void handle_keycode_press(unsigned keycode);
|
||||
void handle_keycode_release(unsigned keycode);
|
||||
|
@ -18,7 +18,7 @@
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2011-2013 Genode Labs GmbH
|
||||
* Copyright (C) 2011-2017 Genode Labs GmbH
|
||||
* Copyright (C) 2012 Intel Corporation
|
||||
*
|
||||
* This file is distributed under the terms of the GNU General Public License
|
||||
@ -31,19 +31,21 @@
|
||||
* conditions of the GNU General Public License version 2.
|
||||
*/
|
||||
|
||||
/* Genode includes */
|
||||
#include <base/component.h>
|
||||
#include <util/touch.h>
|
||||
#include <base/rpc_server.h>
|
||||
#include <util/misc_math.h>
|
||||
#include <rom_session/connection.h>
|
||||
#include <rm_session/connection.h>
|
||||
/* base includes */
|
||||
#include <base/allocator_avl.h>
|
||||
#include <base/attached_rom_dataspace.h>
|
||||
#include <base/component.h>
|
||||
#include <base/heap.h>
|
||||
#include <base/rpc_server.h>
|
||||
#include <base/synced_interface.h>
|
||||
#include <rm_session/connection.h>
|
||||
#include <rom_session/connection.h>
|
||||
#include <util/touch.h>
|
||||
#include <util/misc_math.h>
|
||||
|
||||
/* os includes */
|
||||
#include <nic_session/connection.h>
|
||||
#include <nic/packet_allocator.h>
|
||||
#include <os/config.h>
|
||||
#include <os/alarm.h>
|
||||
#include <base/synced_interface.h>
|
||||
#include <timer_session/connection.h>
|
||||
#include <rtc_session/connection.h>
|
||||
|
||||
@ -88,57 +90,71 @@ Genode::Lock *utcb_lock()
|
||||
}
|
||||
|
||||
|
||||
/* timer service */
|
||||
using Genode::Thread_deprecated;
|
||||
using Genode::Alarm_scheduler;
|
||||
using Genode::Alarm;
|
||||
using Genode::Attached_rom_dataspace;
|
||||
|
||||
typedef Genode::Synced_interface<TimeoutList<32, void> > Synced_timeout_list;
|
||||
|
||||
class Alarm_thread : Thread_deprecated<4096>, public Alarm_scheduler
|
||||
class Timeouts
|
||||
{
|
||||
private:
|
||||
|
||||
Timer::Connection _timer;
|
||||
Alarm::Time _curr_time; /* jiffies value */
|
||||
|
||||
Synced_motherboard &_motherboard;
|
||||
Synced_timeout_list &_timeouts;
|
||||
|
||||
/**
|
||||
* Thread entry function
|
||||
*/
|
||||
void entry()
|
||||
Genode::Signal_handler<Timeouts> _timeout_sigh;
|
||||
|
||||
void check_timeouts()
|
||||
{
|
||||
while (true) {
|
||||
unsigned long long now = _motherboard()->clock()->time();
|
||||
unsigned nr;
|
||||
timevalue const now = _motherboard()->clock()->time();
|
||||
|
||||
while ((nr = _timeouts()->trigger(now))) {
|
||||
unsigned nr;
|
||||
|
||||
MessageTimeout msg(nr, _timeouts()->timeout());
|
||||
while ((nr = _timeouts()->trigger(now))) {
|
||||
|
||||
if (_timeouts()->cancel(nr) < 0)
|
||||
Logging::printf("Timeout not cancelled.\n");
|
||||
MessageTimeout msg(nr, _timeouts()->timeout());
|
||||
|
||||
_motherboard()->bus_timeout.send(msg);
|
||||
}
|
||||
if (_timeouts()->cancel(nr) < 0)
|
||||
Logging::printf("Timeout not cancelled.\n");
|
||||
|
||||
_timer.usleep(1000);
|
||||
_motherboard()->bus_timeout.send(msg);
|
||||
}
|
||||
|
||||
|
||||
unsigned long long next = _timeouts()->timeout();
|
||||
|
||||
if (next == ~0ULL)
|
||||
return;
|
||||
|
||||
timevalue rel_timeout_us = _motherboard()->clock()->delta(next, 1000 * 1000);
|
||||
if (rel_timeout_us == 0)
|
||||
rel_timeout_us = 1;
|
||||
|
||||
_timer.trigger_once(rel_timeout_us);
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
void reprogram()
|
||||
{
|
||||
Genode::Signal_transmitter(_timeout_sigh).submit();
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
Alarm_thread(Synced_motherboard &mb, Synced_timeout_list &timeouts)
|
||||
: Thread_deprecated("alarm"), _curr_time(0), _motherboard(mb), _timeouts(timeouts)
|
||||
{ start(); }
|
||||
Timeouts(Genode::Env &env, Synced_motherboard &mb,
|
||||
Synced_timeout_list &timeouts)
|
||||
:
|
||||
_timer(env),
|
||||
_motherboard(mb),
|
||||
_timeouts(timeouts),
|
||||
_timeout_sigh(env.ep(), *this, &Timeouts::check_timeouts)
|
||||
{
|
||||
_timer.sigh(_timeout_sigh);
|
||||
}
|
||||
|
||||
Alarm::Time curr_time() { return _curr_time; }
|
||||
unsigned long long curr_time_long() { return _motherboard()->clock()->time(); }
|
||||
};
|
||||
|
||||
|
||||
@ -160,8 +176,9 @@ class Guest_memory
|
||||
{
|
||||
private:
|
||||
|
||||
Genode::Ram_dataspace_capability _ds;
|
||||
Genode::Ram_dataspace_capability _fb_ds;
|
||||
Genode::Env &_env;
|
||||
Genode::Ram_dataspace_capability _ds;
|
||||
Genode::Ram_dataspace_capability _fb_ds;
|
||||
|
||||
Genode::size_t _backing_store_size;
|
||||
Genode::size_t _fb_size;
|
||||
@ -192,10 +209,12 @@ class Guest_memory
|
||||
* used as guest-physical and device memory,
|
||||
* allocated from core's RAM service
|
||||
*/
|
||||
Guest_memory(Genode::size_t backing_store_size, Genode::size_t fb_size)
|
||||
Guest_memory(Genode::Env &env, Genode::size_t backing_store_size,
|
||||
Genode::size_t fb_size)
|
||||
:
|
||||
_ds(Genode::env()->ram_session()->alloc(backing_store_size-fb_size)),
|
||||
_fb_ds(Genode::env()->ram_session()->alloc(fb_size)),
|
||||
_env(env),
|
||||
_ds(env.ram().alloc(backing_store_size-fb_size)),
|
||||
_fb_ds(env.ram().alloc(fb_size)),
|
||||
_backing_store_size(backing_store_size),
|
||||
_fb_size(fb_size),
|
||||
_local_addr(0),
|
||||
@ -206,8 +225,8 @@ class Guest_memory
|
||||
/*
|
||||
* RAM used as backing store for guest-physical memory
|
||||
*/
|
||||
_local_addr = Genode::env()->rm_session()->attach(_ds);
|
||||
_fb_addr = Genode::env()->rm_session()->attach_at(_fb_ds,
|
||||
_local_addr = env.rm().attach(_ds);
|
||||
_fb_addr = env.rm().attach_at(_fb_ds,
|
||||
((Genode::addr_t) _local_addr)+backing_store_size-fb_size);
|
||||
|
||||
} catch (Genode::Rm_session::Region_conflict) {
|
||||
@ -218,11 +237,11 @@ class Guest_memory
|
||||
~Guest_memory()
|
||||
{
|
||||
/* detach and free backing store */
|
||||
Genode::env()->rm_session()->detach((void *)_local_addr);
|
||||
Genode::env()->ram_session()->free(_ds);
|
||||
_env.rm().detach((void *)_local_addr);
|
||||
_env.ram().free(_ds);
|
||||
|
||||
Genode::env()->rm_session()->detach((void *)_fb_addr);
|
||||
Genode::env()->ram_session()->free(_fb_ds);
|
||||
_env.rm().detach((void *)_fb_addr);
|
||||
_env.ram().free(_fb_ds);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -842,15 +861,15 @@ class Vcpu_dispatcher : public Vcpu_handler,
|
||||
};
|
||||
|
||||
|
||||
const void * _forward_pkt;
|
||||
|
||||
|
||||
class Machine : public StaticReceiver<Machine>
|
||||
{
|
||||
private:
|
||||
|
||||
Genode::Env &_env;;
|
||||
Genode::Rom_connection _hip_rom;
|
||||
Genode::Env &_env;
|
||||
Genode::Heap &_heap;
|
||||
Attached_rom_dataspace _hip_rom = { _env, "hypervisor_info_page" };
|
||||
Genode::Cpu_connection _cpu_session = { _env, "Seoul vCPUs", Genode::Cpu_session::PRIORITY_LIMIT / 16 };
|
||||
Hip * const _hip;
|
||||
Clock _clock;
|
||||
Genode::Lock _motherboard_lock;
|
||||
@ -861,15 +880,14 @@ class Machine : public StaticReceiver<Machine>
|
||||
Synced_timeout_list _timeouts;
|
||||
Guest_memory &_guest_memory;
|
||||
Boot_module_provider &_boot_modules;
|
||||
Alarm_thread *_alarm_thread;
|
||||
Genode::Pd_connection *_pd_vcpus = nullptr;
|
||||
|
||||
bool _alloc_fb_mem; /* For detecting FB alloc message */
|
||||
Timeouts _alarm_thread = { _env, _motherboard, _timeouts };
|
||||
bool _colocate_vm_vmm;
|
||||
unsigned short _vcpus_up;
|
||||
unsigned short _vcpus_up = 0;
|
||||
|
||||
Nic::Session *_nic;
|
||||
Rtc::Session *_rtc;
|
||||
bool _alloc_fb_mem = false; /* For detecting FB alloc message */
|
||||
Genode::Pd_connection *_pd_vcpus = nullptr;
|
||||
Seoul::Network *_nic = nullptr;
|
||||
Rtc::Session *_rtc = nullptr;
|
||||
|
||||
public:
|
||||
|
||||
@ -943,19 +961,17 @@ class Machine : public StaticReceiver<Machine>
|
||||
|
||||
_vcpus_up ++;
|
||||
|
||||
long const prio = Genode::Cpu_session::PRIORITY_LIMIT / 16;
|
||||
static Genode::Cpu_connection * cpu_session = new (Genode::env()->heap()) Genode::Cpu_connection("Seoul vCPUs", prio);
|
||||
Genode::Affinity::Space cpu_space = cpu_session->affinity_space();
|
||||
Genode::Affinity::Space cpu_space = _cpu_session.affinity_space();
|
||||
Genode::Affinity::Location location = cpu_space.location_of_index(_vcpus_up);
|
||||
|
||||
Vmm::Vcpu_thread * vcpu_thread;
|
||||
if (_colocate_vm_vmm)
|
||||
vcpu_thread = new Vmm::Vcpu_same_pd(cpu_session, location, _env.pd_session_cap(), Vcpu_dispatcher::STACK_SIZE);
|
||||
vcpu_thread = new Vmm::Vcpu_same_pd(&_cpu_session, location, _env.pd_session_cap(), Vcpu_dispatcher::STACK_SIZE);
|
||||
else {
|
||||
if (!_pd_vcpus)
|
||||
_pd_vcpus = new Genode::Pd_connection("VM");
|
||||
_pd_vcpus = new Genode::Pd_connection(_env, "VM");
|
||||
|
||||
vcpu_thread = new Vmm::Vcpu_other_pd(cpu_session, location, *_pd_vcpus);
|
||||
vcpu_thread = new Vmm::Vcpu_other_pd(&_cpu_session, location, *_pd_vcpus);
|
||||
}
|
||||
|
||||
Vcpu_dispatcher *vcpu_dispatcher =
|
||||
@ -967,7 +983,7 @@ class Machine : public StaticReceiver<Machine>
|
||||
_hip->has_feature_svm(),
|
||||
_hip->has_feature_vmx(),
|
||||
vcpu_thread,
|
||||
cpu_session,
|
||||
&_cpu_session,
|
||||
location);
|
||||
|
||||
msg.value = vcpu_dispatcher->sel_sm_ec();
|
||||
@ -1020,7 +1036,8 @@ class Machine : public StaticReceiver<Machine>
|
||||
*/
|
||||
Genode::size_t data_len = 0;
|
||||
try {
|
||||
data_len = _boot_modules.data(index, data_dst, dst_len);
|
||||
data_len = _boot_modules.data(_env, index,
|
||||
data_dst, dst_len);
|
||||
} catch (Boot_module_provider::Destination_buffer_too_small) {
|
||||
Logging::panic("could not load module, destination buffer too small\n");
|
||||
return false;
|
||||
@ -1069,45 +1086,37 @@ class Machine : public StaticReceiver<Machine>
|
||||
}
|
||||
case MessageHostOp::OP_GET_MAC:
|
||||
{
|
||||
Nic::Packet_allocator *tx_block_alloc =
|
||||
new (Genode::env()->heap()) Nic::Packet_allocator(Genode::env()->heap());
|
||||
|
||||
enum {
|
||||
PACKET_SIZE = Nic::Packet_allocator::DEFAULT_PACKET_SIZE,
|
||||
BUF_SIZE = Nic::Session::QUEUE_SIZE * PACKET_SIZE,
|
||||
};
|
||||
|
||||
try {
|
||||
_nic = new Nic::Connection(tx_block_alloc, BUF_SIZE, BUF_SIZE);
|
||||
} catch (...) {
|
||||
Logging::printf("No NIC connection possible!\n");
|
||||
if (_nic) {
|
||||
Logging::printf("Solely one network connection supported\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
Logging::printf("Our mac address is %2x:%2x:%2x:%2x:%2x:%2x\n",
|
||||
_nic->mac_address().addr[0],
|
||||
_nic->mac_address().addr[1],
|
||||
_nic->mac_address().addr[2],
|
||||
_nic->mac_address().addr[3],
|
||||
_nic->mac_address().addr[4],
|
||||
_nic->mac_address().addr[5]
|
||||
);
|
||||
msg.mac = ((Genode::uint64_t)_nic->mac_address().addr[0] & 0xff) << 40 |
|
||||
((Genode::uint64_t)_nic->mac_address().addr[1] & 0xff) << 32 |
|
||||
((Genode::uint64_t)_nic->mac_address().addr[2] & 0xff) << 24 |
|
||||
((Genode::uint64_t)_nic->mac_address().addr[3] & 0xff) << 16 |
|
||||
((Genode::uint64_t)_nic->mac_address().addr[4] & 0xff) << 8 |
|
||||
((Genode::uint64_t)_nic->mac_address().addr[5] & 0xff);
|
||||
try {
|
||||
_nic = new (_heap) Seoul::Network(_env, _heap,
|
||||
_motherboard);
|
||||
} catch (...) {
|
||||
Logging::printf("Creating network connection failed\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
/* start receiver thread for this MAC */
|
||||
Vancouver_network * netreceiver = new Vancouver_network(_motherboard, _nic);
|
||||
assert(netreceiver);
|
||||
Nic::Mac_address mac = _nic->mac_address();
|
||||
|
||||
Logging::printf("Mac address: %2x:%2x:%2x:%2x:%2x:%2x\n",
|
||||
mac.addr[0], mac.addr[1], mac.addr[2],
|
||||
mac.addr[3], mac.addr[4], mac.addr[5]);
|
||||
|
||||
msg.mac = ((Genode::uint64_t)mac.addr[0] & 0xff) << 40 |
|
||||
((Genode::uint64_t)mac.addr[1] & 0xff) << 32 |
|
||||
((Genode::uint64_t)mac.addr[2] & 0xff) << 24 |
|
||||
((Genode::uint64_t)mac.addr[3] & 0xff) << 16 |
|
||||
((Genode::uint64_t)mac.addr[4] & 0xff) << 8 |
|
||||
((Genode::uint64_t)mac.addr[5] & 0xff);
|
||||
|
||||
return true;
|
||||
}
|
||||
default:
|
||||
|
||||
PWRN("HostOp %d not implemented", msg.type);
|
||||
Logging::printf("HostOp %d not implemented\n", msg.type);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@ -1127,22 +1136,21 @@ class Machine : public StaticReceiver<Machine>
|
||||
if (verbose_debug)
|
||||
Logging::printf("TIMER_NEW\n");
|
||||
|
||||
if (_alarm_thread == NULL) {
|
||||
Logging::printf("Creating alarm thread\n");
|
||||
_alarm_thread = new Alarm_thread(_motherboard, _timeouts);
|
||||
}
|
||||
|
||||
msg.nr = _timeouts()->alloc();
|
||||
|
||||
return true;
|
||||
|
||||
case MessageTimer::TIMER_REQUEST_TIMEOUT:
|
||||
|
||||
if (_timeouts()->request(msg.nr, msg.abstime) < 0)
|
||||
{
|
||||
int res = _timeouts()->request(msg.nr, msg.abstime);
|
||||
if (res == 0)
|
||||
_alarm_thread.reprogram();
|
||||
else
|
||||
if (res < 0)
|
||||
Logging::printf("Could not program timeout.\n");
|
||||
|
||||
return true;
|
||||
|
||||
}
|
||||
default:
|
||||
return false;
|
||||
};
|
||||
@ -1157,7 +1165,7 @@ class Machine : public StaticReceiver<Machine>
|
||||
|
||||
if (!_rtc) {
|
||||
try {
|
||||
_rtc = new Rtc::Connection;
|
||||
_rtc = new Rtc::Connection(_env);
|
||||
} catch (...) {
|
||||
Logging::printf("No RTC present, returning dummy time.\n");
|
||||
msg.wallclocktime = msg.timestamp = 0;
|
||||
@ -1185,44 +1193,14 @@ class Machine : public StaticReceiver<Machine>
|
||||
{
|
||||
if (msg.type != MessageNetwork::PACKET) return false;
|
||||
|
||||
if (!_nic)
|
||||
return false;
|
||||
|
||||
Genode::Lock::Guard guard(*utcb_lock());
|
||||
|
||||
Vmm::Utcb_guard utcb_guard(utcb_backup);
|
||||
|
||||
if (msg.buffer == _forward_pkt) {
|
||||
/* don't end in an endless forwarding loop */
|
||||
return false;
|
||||
}
|
||||
|
||||
/* allocate transmit packet */
|
||||
Nic::Packet_descriptor tx_packet;
|
||||
try {
|
||||
tx_packet = _nic->tx()->alloc_packet(msg.len);
|
||||
} catch (Nic::Session::Tx::Source::Packet_alloc_failed) {
|
||||
Logging::printf("error: tx packet alloc failed\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
/* fill packet with content */
|
||||
char *tx_content = _nic->tx()->packet_content(tx_packet);
|
||||
_forward_pkt = tx_content;
|
||||
for (unsigned i = 0; i < msg.len; i++) {
|
||||
tx_content[i] = msg.buffer[i];
|
||||
}
|
||||
_nic->tx()->submit_packet(tx_packet);
|
||||
|
||||
/* wait for acknowledgement */
|
||||
Nic::Packet_descriptor ack_tx_packet = _nic->tx()->get_acked_packet();
|
||||
|
||||
if (ack_tx_packet.size() != tx_packet.size()
|
||||
|| ack_tx_packet.offset() != tx_packet.offset()) {
|
||||
Logging::printf("error: unexpected acked packet\n");
|
||||
}
|
||||
|
||||
/* release sent packet to free the space in the tx communication buffer */
|
||||
_nic->tx()->release_packet(tx_packet);
|
||||
|
||||
return true;
|
||||
return _nic->transmit(msg.buffer, msg.len);
|
||||
}
|
||||
|
||||
bool receive(MessagePciConfig &msg)
|
||||
@ -1251,12 +1229,12 @@ class Machine : public StaticReceiver<Machine>
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
Machine(Genode::Env &env, Boot_module_provider &boot_modules,
|
||||
Machine(Genode::Env &env, Genode::Heap &heap,
|
||||
Boot_module_provider &boot_modules,
|
||||
Guest_memory &guest_memory, bool colocate)
|
||||
:
|
||||
_env(env),
|
||||
_hip_rom(_env, "hypervisor_info_page"),
|
||||
_hip(Genode::env()->rm_session()->attach(_hip_rom.dataspace())),
|
||||
_env(env), _heap(heap),
|
||||
_hip(_hip_rom.local_addr<Hip>()),
|
||||
_clock(_hip->tsc_freq*1000),
|
||||
_motherboard_lock(Genode::Lock::LOCKED),
|
||||
_unsynchronized_motherboard(&_clock, _hip),
|
||||
@ -1264,8 +1242,7 @@ class Machine : public StaticReceiver<Machine>
|
||||
_timeouts(_timeouts_lock, &_unsynchronized_timeouts),
|
||||
_guest_memory(guest_memory),
|
||||
_boot_modules(boot_modules),
|
||||
_colocate_vm_vmm(colocate),
|
||||
_vcpus_up(0)
|
||||
_colocate_vm_vmm(colocate)
|
||||
{
|
||||
_timeouts()->init();
|
||||
|
||||
@ -1307,11 +1284,12 @@ class Machine : public StaticReceiver<Machine>
|
||||
char name[MODEL_NAME_MAX_LEN];
|
||||
node.type_name(name, sizeof(name));
|
||||
|
||||
PINF("device: %s", name);
|
||||
Genode::log("device: ", (char const *)name);
|
||||
Device_model_info *dmi = device_model_registry()->lookup(name);
|
||||
|
||||
if (!dmi) {
|
||||
PERR("configuration error: device model '%s' does not exist", name);
|
||||
Genode::error("configuration error: device model '",
|
||||
(char const *)name, "' does not exist");
|
||||
throw Config_error();
|
||||
}
|
||||
|
||||
@ -1330,7 +1308,7 @@ class Machine : public StaticReceiver<Machine>
|
||||
Xml_node::Attribute arg = node.attribute(dmi->arg_names[i]);
|
||||
arg.value(&argv[i]);
|
||||
|
||||
PINF(" arg[%d]: 0x%x", i, (int)argv[i]);
|
||||
Genode::log(" arg[", i, "]: ", Genode::Hex(argv[i]));
|
||||
}
|
||||
catch (Xml_node::Nonexistent_attribute) { }
|
||||
}
|
||||
@ -1353,9 +1331,10 @@ class Machine : public StaticReceiver<Machine>
|
||||
*/
|
||||
void boot()
|
||||
{
|
||||
PINF("VM and VMM are %s. VM is starting with %u %s.",
|
||||
_colocate_vm_vmm ? "co-located" : "not co-located",
|
||||
_vcpus_up, _vcpus_up > 1 ? "vCPUs" : "vCPU");
|
||||
Genode::log("VM and VMM are ",
|
||||
_colocate_vm_vmm ? "co-located" : "not co-located",
|
||||
". VM is starting with ", _vcpus_up, " vCPU",
|
||||
_vcpus_up > 1 ? "s" : "");
|
||||
|
||||
/* init VCPUs */
|
||||
for (VCpu *vcpu = _unsynchronized_motherboard.last_vcpu; vcpu; vcpu = vcpu->get_last()) {
|
||||
@ -1395,19 +1374,13 @@ class Machine : public StaticReceiver<Machine>
|
||||
Synced_motherboard &motherboard() { return _motherboard; }
|
||||
|
||||
Motherboard &unsynchronized_motherboard() { return _unsynchronized_motherboard; }
|
||||
|
||||
Genode::Lock &motherboard_lock() { return _motherboard_lock; }
|
||||
|
||||
~Machine()
|
||||
{
|
||||
Genode::env()->rm_session()->detach(_hip);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
extern unsigned long _prog_img_beg; /* begin of program image (link address) */
|
||||
extern unsigned long _prog_img_end; /* end of program image */
|
||||
|
||||
extern void heap_init_env(Genode::Heap *);
|
||||
|
||||
void Component::construct(Genode::Env &env)
|
||||
{
|
||||
@ -1415,6 +1388,8 @@ void Component::construct(Genode::Env &env)
|
||||
Genode::addr_t vm_size;
|
||||
unsigned colocate = 1; /* by default co-locate VM and VMM in same PD */
|
||||
|
||||
static Attached_rom_dataspace config(env, "config");
|
||||
|
||||
{
|
||||
/*
|
||||
* Reserve complete lower address space so that nobody else can take
|
||||
@ -1423,13 +1398,12 @@ void Component::construct(Genode::Env &env)
|
||||
* reservation will be dropped when this scope is left and re-acquired
|
||||
* with the actual VM size which is determined below inside this scope.
|
||||
*/
|
||||
Vmm::Virtual_reservation
|
||||
reservation(Genode::Thread::stack_area_virtual_base());
|
||||
Vmm::Virtual_reservation reservation(env, Genode::Thread::stack_area_virtual_base());
|
||||
|
||||
Genode::printf("--- Vancouver VMM starting ---\n");
|
||||
Genode::log("--- Vancouver VMM starting ---");
|
||||
|
||||
/* request max available memory */
|
||||
vm_size = Genode::env()->ram_session()->avail();
|
||||
vm_size = env.ram().avail();
|
||||
/* reserve some memory for the VMM */
|
||||
vm_size -= 8 * 1024 * 1024;
|
||||
/* calculate max memory for the VM */
|
||||
@ -1437,7 +1411,7 @@ void Component::construct(Genode::Env &env)
|
||||
|
||||
/* Find out framebuffer size (default: 4 MiB) */
|
||||
try {
|
||||
Genode::Xml_node node = Genode::config()->xml_node().sub_node("machine").sub_node("vga");
|
||||
Genode::Xml_node node = config.xml().sub_node("machine").sub_node("vga");
|
||||
Genode::Xml_node::Attribute arg = node.attribute("fb_size");
|
||||
|
||||
unsigned long val = 0;
|
||||
@ -1447,76 +1421,83 @@ void Component::construct(Genode::Env &env)
|
||||
|
||||
/* read out whether VM and VMM should be colocated or not */
|
||||
try {
|
||||
Genode::config()->xml_node().attribute("colocate").value(&colocate);
|
||||
config.xml().attribute("colocate").value(&colocate);
|
||||
} catch (...) { }
|
||||
}
|
||||
|
||||
if (colocate)
|
||||
/* re-adjust reservation to actual VM size */
|
||||
static Vmm::Virtual_reservation reservation(vm_size);
|
||||
static Vmm::Virtual_reservation reservation(env, vm_size);
|
||||
|
||||
/* setup guest memory */
|
||||
static Guest_memory guest_memory(vm_size, fb_size);
|
||||
static Guest_memory guest_memory(env, vm_size, fb_size);
|
||||
|
||||
typedef Genode::Hex_range<unsigned long> Hex_range;
|
||||
|
||||
/* diagnostic messages */
|
||||
if (colocate)
|
||||
Genode::printf("[0x%012lx, 0x%012lx) - %lu MiB - VM accessible "
|
||||
"memory\n", 0UL, vm_size, vm_size / 1024 / 1024);
|
||||
Genode::log(Hex_range(0UL, vm_size), " - ", vm_size / 1024 / 1024,
|
||||
" MiB - VM accessible memory");
|
||||
|
||||
if (guest_memory.backing_store_local_base())
|
||||
Genode::printf("[0x%12p, 0x%12p) - %lu MiB - VMM accessible shadow "
|
||||
"mapping of VM memory \n",
|
||||
guest_memory.backing_store_local_base(),
|
||||
guest_memory.backing_store_local_base() +
|
||||
guest_memory.remaining_size, vm_size / 1024 / 1024);
|
||||
Genode::log(Hex_range((unsigned long)guest_memory.backing_store_local_base(),
|
||||
guest_memory.remaining_size),
|
||||
" - ", vm_size / 1024 / 1024, " MiB",
|
||||
" - VMM accessible shadow mapping of VM memory");
|
||||
|
||||
if (guest_memory.backing_store_fb_local_base())
|
||||
Genode::printf("[0x%12p, 0x%12p) - %lu MiB - VMM accessible "
|
||||
"framebuffer memory of VM\n",
|
||||
guest_memory.backing_store_fb_local_base(),
|
||||
guest_memory.backing_store_fb_local_base() + fb_size,
|
||||
fb_size / 1024 / 1024);
|
||||
Genode::log(Hex_range((unsigned long)guest_memory.backing_store_fb_local_base(),
|
||||
fb_size),
|
||||
" - ", fb_size / 1024 / 1024, " MiB"
|
||||
" - VMM accessible framebuffer memory of VM");
|
||||
|
||||
Genode::printf("[0x%012lx, 0x%012lx) - Genode stack area\n",
|
||||
Genode::Thread::stack_area_virtual_base(),
|
||||
Genode::Thread::stack_area_virtual_base() +
|
||||
Genode::Thread::stack_area_virtual_size());
|
||||
Genode::log(Hex_range(Genode::Thread::stack_area_virtual_base(),
|
||||
Genode::Thread::stack_area_virtual_size()),
|
||||
" - Genode stack area");
|
||||
|
||||
Genode::printf("[0x%012lx, 0x%012lx) - VMM program image\n",
|
||||
(Genode::addr_t)&_prog_img_beg,
|
||||
(Genode::addr_t)&_prog_img_end);
|
||||
Genode::log(Hex_range((Genode::addr_t)&_prog_img_beg,
|
||||
(Genode::addr_t)&_prog_img_end -
|
||||
(Genode::addr_t)&_prog_img_beg),
|
||||
" - VMM program image");
|
||||
|
||||
if (!guest_memory.backing_store_local_base() ||
|
||||
!guest_memory.backing_store_fb_local_base()) {
|
||||
PERR("Not enough space left for %s - exit",
|
||||
guest_memory.backing_store_local_base() ? "framebuffer" : "VMM");
|
||||
Genode::error("Not enough space left for ",
|
||||
guest_memory.backing_store_local_base() ? "framebuffer"
|
||||
: "VMM");
|
||||
env.parent().exit(-1);
|
||||
return;
|
||||
}
|
||||
|
||||
Genode::printf("\n--- Setup VM ---\n");
|
||||
Genode::log("\n--- Setup VM ---");
|
||||
|
||||
static Genode::Heap heap(env.ram(), env.rm());
|
||||
|
||||
heap_init_env(&heap);
|
||||
|
||||
static Boot_module_provider
|
||||
boot_modules(Genode::config()->xml_node().sub_node("multiboot"));
|
||||
boot_modules(config.xml().sub_node("multiboot"));
|
||||
|
||||
/* create the PC machine based on the configuration given */
|
||||
static Machine machine(env, boot_modules, guest_memory, colocate);
|
||||
static Machine machine(env, heap, boot_modules, guest_memory, colocate);
|
||||
|
||||
/* create console thread */
|
||||
static Vancouver_console vcon(machine.motherboard(), fb_size, guest_memory.fb_ds());
|
||||
static Seoul::Console vcon(env, machine.motherboard(),
|
||||
machine.unsynchronized_motherboard(), fb_size,
|
||||
guest_memory.fb_ds());
|
||||
|
||||
vcon.register_host_operations(machine.unsynchronized_motherboard());
|
||||
|
||||
/* create disk thread */
|
||||
static Vancouver_disk vdisk(machine.motherboard(),
|
||||
guest_memory.backing_store_local_base(),
|
||||
guest_memory.backing_store_size());
|
||||
static Seoul::Disk vdisk(env, machine.motherboard(),
|
||||
guest_memory.backing_store_local_base(),
|
||||
guest_memory.backing_store_size());
|
||||
|
||||
vdisk.register_host_operations(machine.unsynchronized_motherboard());
|
||||
|
||||
machine.setup_devices(Genode::config()->xml_node().sub_node("machine"));
|
||||
machine.setup_devices(config.xml().sub_node("machine"));
|
||||
|
||||
Genode::printf("\n--- Booting VM ---\n");
|
||||
Genode::log("\n--- Booting VM ---");
|
||||
|
||||
machine.boot();
|
||||
}
|
||||
|
@ -1,12 +1,13 @@
|
||||
/*
|
||||
* \brief Network receive handler per MAC address
|
||||
* \author Markus Partheymueller
|
||||
* \author Alexander Boettcher
|
||||
* \date 2012-07-31
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2012 Intel Corporation
|
||||
* Copyright (C) 2013 Genode Labs GmbH
|
||||
* Copyright (C) 2013-2017 Genode Labs GmbH
|
||||
*
|
||||
* This file is distributed under the terms of the GNU General Public License
|
||||
* version 2.
|
||||
@ -21,29 +22,68 @@
|
||||
/* local includes */
|
||||
#include "network.h"
|
||||
|
||||
extern const void * _forward_pkt;
|
||||
|
||||
|
||||
Vancouver_network::Vancouver_network(Synced_motherboard &mb, Nic::Session *nic)
|
||||
: Thread_deprecated("vmm_network"), _motherboard(mb), _nic(nic)
|
||||
Seoul::Network::Network(Genode::Env &env, Genode::Heap &heap,
|
||||
Synced_motherboard &mb)
|
||||
:
|
||||
_motherboard(mb), _tx_block_alloc(&heap),
|
||||
_nic(env, &_tx_block_alloc, BUF_SIZE, BUF_SIZE),
|
||||
_packet_avail(env.ep(), *this, &Network::_handle_packets)
|
||||
{
|
||||
start();
|
||||
_nic.rx_channel()->sigh_packet_avail(_packet_avail);
|
||||
}
|
||||
|
||||
|
||||
void Vancouver_network::entry()
|
||||
void Seoul::Network::_handle_packets()
|
||||
{
|
||||
while (true) {
|
||||
Nic::Packet_descriptor rx_packet = _nic->rx()->get_packet();
|
||||
while (_nic.rx()->packet_avail()) {
|
||||
|
||||
Nic::Packet_descriptor rx_packet = _nic.rx()->get_packet();
|
||||
|
||||
/* send it to the network bus */
|
||||
char * rx_content = _nic->rx()->packet_content(rx_packet);
|
||||
char * rx_content = _nic.rx()->packet_content(rx_packet);
|
||||
_forward_pkt = rx_content;
|
||||
MessageNetwork msg((unsigned char *)rx_content, rx_packet.size(), 0);
|
||||
_motherboard()->bus_network.send(msg);
|
||||
_forward_pkt = 0;
|
||||
|
||||
/* acknowledge received packet */
|
||||
_nic->rx()->acknowledge_packet(rx_packet);
|
||||
_nic.rx()->acknowledge_packet(rx_packet);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool Seoul::Network::transmit(void const * const packet, Genode::size_t len)
|
||||
{
|
||||
if (packet == _forward_pkt)
|
||||
/* don't end in an endless forwarding loop */
|
||||
return false;
|
||||
|
||||
/* allocate transmit packet */
|
||||
Nic::Packet_descriptor tx_packet;
|
||||
try {
|
||||
tx_packet = _nic.tx()->alloc_packet(len);
|
||||
} catch (Nic::Session::Tx::Source::Packet_alloc_failed) {
|
||||
Logging::printf("error: tx packet alloc failed\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
/* fill packet with content */
|
||||
char * const tx_content = _nic.tx()->packet_content(tx_packet);
|
||||
_forward_pkt = tx_content;
|
||||
memcpy(tx_content, packet, len);
|
||||
|
||||
_nic.tx()->submit_packet(tx_packet);
|
||||
|
||||
/* wait for acknowledgement */
|
||||
Nic::Packet_descriptor ack_tx_packet = _nic.tx()->get_acked_packet();
|
||||
|
||||
if (ack_tx_packet.size() != tx_packet.size() ||
|
||||
ack_tx_packet.offset() != tx_packet.offset())
|
||||
Logging::printf("error: unexpected acked packet\n");
|
||||
|
||||
/* release sent packet to free the space in the tx communication buffer */
|
||||
_nic.tx()->release_packet(tx_packet);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -1,12 +1,13 @@
|
||||
/*
|
||||
* \brief Network receive handler per MAC address
|
||||
* \author Markus Partheymueller
|
||||
* \author Alexander Boettcher
|
||||
* \date 2012-07-31
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2012 Intel Corporation
|
||||
* Copyright (C) 2013 Genode Labs GmbH
|
||||
* Copyright (C) 2013-2017 Genode Labs GmbH
|
||||
*
|
||||
* This file is distributed under the terms of the GNU General Public License
|
||||
* version 2.
|
||||
@ -21,31 +22,45 @@
|
||||
#ifndef _NETWORK_H_
|
||||
#define _NETWORK_H_
|
||||
|
||||
/* Genode includes */
|
||||
/* base includes */
|
||||
#include <base/heap.h>
|
||||
|
||||
/* os includes */
|
||||
#include <nic_session/connection.h>
|
||||
#include <nic/packet_allocator.h>
|
||||
|
||||
/* local includes */
|
||||
#include "synced_motherboard.h"
|
||||
|
||||
using Genode::List;
|
||||
using Genode::Thread_deprecated;
|
||||
namespace Seoul {
|
||||
class Network;
|
||||
}
|
||||
|
||||
class Vancouver_network : public Thread_deprecated<4096>
|
||||
class Seoul::Network
|
||||
{
|
||||
private:
|
||||
|
||||
Synced_motherboard &_motherboard;
|
||||
Nic::Session *_nic;
|
||||
enum {
|
||||
PACKET_SIZE = Nic::Packet_allocator::DEFAULT_PACKET_SIZE,
|
||||
BUF_SIZE = Nic::Session::QUEUE_SIZE * PACKET_SIZE,
|
||||
};
|
||||
|
||||
Synced_motherboard &_motherboard;
|
||||
Nic::Packet_allocator _tx_block_alloc;
|
||||
Nic::Connection _nic;
|
||||
|
||||
Genode::Signal_handler<Network> const _packet_avail;
|
||||
void const * _forward_pkt = nullptr;
|
||||
|
||||
void _handle_packets();
|
||||
|
||||
public:
|
||||
|
||||
/* initialisation */
|
||||
void entry();
|
||||
Network(Genode::Env &, Genode::Heap &, Synced_motherboard &);
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
Vancouver_network(Synced_motherboard &, Nic::Session *);
|
||||
Nic::Mac_address mac_address() { return _nic.mac_address(); }
|
||||
|
||||
bool transmit(void const * const packet, Genode::size_t len);
|
||||
};
|
||||
|
||||
#endif /* _NETWORK_H_ */
|
||||
|
@ -14,6 +14,7 @@
|
||||
/* Genode includes */
|
||||
#include <base/printf.h>
|
||||
#include <base/env.h>
|
||||
#include <base/heap.h>
|
||||
#include <base/sleep.h>
|
||||
#include <base/thread.h>
|
||||
|
||||
@ -65,7 +66,7 @@ void Logging::vprintf(const char *format, va_list &ap)
|
||||
|
||||
Genode::printf("VMM: ");
|
||||
Genode::printf(format);
|
||||
PWRN("Logging::vprintf not implemented");
|
||||
Genode::error("Logging::vprintf not implemented");
|
||||
|
||||
*(Utcb_backup *)Genode::Thread::myself()->utcb() = utcb_backup;
|
||||
}
|
||||
@ -86,25 +87,31 @@ void Logging::panic(const char *format, ...)
|
||||
Genode::sleep_forever();
|
||||
}
|
||||
|
||||
static Genode::Allocator * heap = nullptr;
|
||||
|
||||
void heap_init_env(Genode::Heap *h)
|
||||
{
|
||||
heap = h;
|
||||
}
|
||||
|
||||
static void *heap_alloc(size_t size)
|
||||
{
|
||||
void *res = Genode::env()->heap()->alloc(size);
|
||||
void *res = heap->alloc(size);
|
||||
if (res)
|
||||
return res;
|
||||
|
||||
PERR("out of memory");
|
||||
Genode::error("out of memory");
|
||||
Genode::sleep_forever();
|
||||
}
|
||||
|
||||
static void heap_free(void * ptr)
|
||||
{
|
||||
if (Genode::env()->heap()->need_size_for_free()) {
|
||||
PWRN("leaking memory");
|
||||
if (heap->need_size_for_free()) {
|
||||
Genode::warning("leaking memory");
|
||||
return;
|
||||
}
|
||||
|
||||
Genode::env()->heap()->free(ptr, 0);
|
||||
heap->free(ptr, 0);
|
||||
}
|
||||
|
||||
|
||||
@ -141,7 +148,7 @@ void *operator new (size_t size)
|
||||
void operator delete[](void *ptr)
|
||||
{
|
||||
if (verbose_memory_leak)
|
||||
PWRN("delete[] not implemented");
|
||||
Genode::warning("delete[] not implemented ", ptr);
|
||||
}
|
||||
|
||||
void operator delete (void * ptr)
|
||||
|
@ -5,7 +5,7 @@ SEOUL_GENODE_DIR = $(SEOUL_CONTRIB_DIR)/genode
|
||||
|
||||
REQUIRES += nova
|
||||
|
||||
LIBS += base-nova blit alarm seoul_libc_support config
|
||||
LIBS += base-nova blit seoul_libc_support
|
||||
SRC_CC = main.cc nova_user_env.cc device_model_registry.cc
|
||||
SRC_CC += console.cc keyboard.cc network.cc disk.cc
|
||||
SRC_BIN = mono.tff
|
||||
|
Loading…
x
Reference in New Issue
Block a user