seoul: adjust vga model to framebuffer host size

Configure the available vga/vesa memory based on the given Genode framebuffer
size and not the way around.

Issue #2715
This commit is contained in:
Alexander Boettcher 2018-03-14 23:04:43 +01:00 committed by Christian Helmuth
parent bb768c2cab
commit 57fcd5e0c4
5 changed files with 63 additions and 79 deletions

View File

@ -69,7 +69,7 @@ puts $vm_cfg_fd {<config colocate="1" >
<rtc io_base="0x70" irq="8"/>
<serial io_base="0x3f8" irq="0x4" host_serial="0x4711"/>
<hostsink host_dev="0x4712" buffer="80"/>
<vga io_base="0x03c0" fb_size="4096" readonly="1"/>}
<vga io_base="0x03c0"/>}
if {!$use_multiboot} {
puts $vm_cfg_fd {

View File

@ -133,10 +133,6 @@ bool Seoul::Console::receive(MessageConsole &msg)
{
if (msg.type == MessageConsole::TYPE_ALLOC_VIEW) {
_guest_fb = msg.ptr;
if (msg.size < _fb_size)
_fb_size = msg.size;
_regs = msg.regs;
msg.view = 0;
@ -256,7 +252,7 @@ unsigned Seoul::Console::_handle_fb()
((fg & 0x2) >> 1)*127+lum, /* G+luminosity */
(fg & 0x1)*127+lum /* B+luminosity */);
Text_painter::paint(*_surface, where, default_font, color, buffer);
Text_painter::paint(_surface, where, default_font, color, buffer);
/* Checksum for comparing */
if (fb_state.cmp_even) fb_state.checksum1 += character;
@ -269,7 +265,7 @@ unsigned Seoul::Console::_handle_fb()
/* 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());
_framebuffer.refresh(0, 0, _fb_mode.width(), _fb_mode.height());
return 100;
}
@ -278,7 +274,7 @@ unsigned Seoul::Console::_handle_fb()
/* 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);
_env.rm().attach_at(_guest_fb_ds, (Genode::addr_t)_guest_fb);
fb_state.unchanged = 0;
fb_state.active = false;
@ -291,21 +287,12 @@ unsigned Seoul::Console::_handle_fb()
if (!fb_state.revoked) {
_env.rm().detach((void *)_guest_fb);
_env.rm().attach_at(_framebuffer->dataspace(),
_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());
_framebuffer.refresh(0, 0, _fb_mode.width(), _fb_mode.height());
return 10;
}
@ -372,28 +359,20 @@ bool Seoul::Console::receive(MessageTimeout &msg) {
Seoul::Console::Console(Genode::Env &env, Synced_motherboard &mb,
Motherboard &unsynchronized_motherboard,
Genode::size_t vm_fb_size,
Genode::Dataspace_capability fb_ds)
Framebuffer::Connection &framebuffer,
Genode::Dataspace_capability guest_fb_ds)
:
_env(env),
_unsynchronized_motherboard(unsynchronized_motherboard),
_motherboard(mb), _fb_ds(fb_ds), _vm_fb_size(vm_fb_size)
_motherboard(mb),
_framebuffer(framebuffer),
_guest_fb_ds(guest_fb_ds),
_fb_mode(_framebuffer.mode()),
_fb_size(Genode::Dataspace_client(_framebuffer.dataspace()).size()),
_pixels(_env.rm().attach(_framebuffer.dataspace())),
_surface(reinterpret_cast<Genode::Pixel_rgb565 *>(_pixels),
Genode::Surface_base::Area(_fb_mode.width(),
_fb_mode.height()))
{
_input.sigh(_signal_input);
try {
using Framebuffer::Mode;
_framebuffer.construct(_env, Mode(0, 0, Mode::INVALID));
} catch (...) {
Genode::error("Headless mode - no framebuffer session available");
return;
}
_fb_size = Genode::Dataspace_client(_framebuffer->dataspace()).size();
_fb_mode = _framebuffer->mode();
_pixels = _env.rm().attach(_framebuffer->dataspace());
_surface.construct(reinterpret_cast<Genode::Pixel_rgb565 *>(_pixels),
Genode::Surface_base::Area(_fb_mode.width(),
_fb_mode.height()));
}

View File

@ -24,7 +24,6 @@
/* base includes */
#include <base/env.h>
#include <dataspace/client.h>
#include <util/reconstructible.h>
#include <util/string.h>
/* os includes */
@ -41,7 +40,6 @@
namespace Seoul {
class Console;
using Genode::Constructible;
using Genode::Pixel_rgb565;
}
@ -52,17 +50,16 @@ class Seoul::Console : public StaticReceiver<Seoul::Console>
Genode::Env &_env;
Motherboard &_unsynchronized_motherboard;
Synced_motherboard &_motherboard;
Constructible<Framebuffer::Connection> _framebuffer { };
Constructible<Genode::Surface<Pixel_rgb565> > _surface { };
Framebuffer::Connection &_framebuffer;
Genode::Dataspace_capability _guest_fb_ds;
Framebuffer::Mode _fb_mode;
size_t _fb_size;
short *_pixels;
Genode::Surface<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 { nullptr };
Framebuffer::Mode _fb_mode { };
bool _left { false };
bool _middle { false };
bool _right { false };
@ -95,7 +92,7 @@ class Seoul::Console : public StaticReceiver<Seoul::Console>
* Constructor
*/
Console(Genode::Env &env, Synced_motherboard &, Motherboard &,
Genode::size_t vm_fb_size, Genode::Dataspace_capability fb_ds);
Framebuffer::Connection &, Genode::Dataspace_capability fb_ds);
};
#endif /* _CONSOLE_H_ */

View File

@ -76,8 +76,9 @@ MODEL_INFO(keyb, "ps2_port", "host_keyboard")
MODEL_INFO(mouse, "ps2_port", "host_mouse")
MODEL_INFO(rtc, "io_base", "irq")
MODEL_INFO(serial, "io_base", "irq", "host_serial")
MODEL_INFO(vga, "io_base", "fb_size")
MODEL_INFO(pmtimer, "io_port")
MODEL_INFO(vga, "io_base", "fb_size")
MODEL_INFO(vga_fbsize, "fb_size")
MODEL_INFO(pcihostbridge, "bus_num", "bus_count", "io_base", "mem_base")
MODEL_INFO(intel82576vf, "promisc", "mem_mmio", "mem_msix", "txpoll_us", "rx_map")

View File

@ -44,10 +44,11 @@
#include <util/misc_math.h>
/* os includes */
#include <framebuffer_session/connection.h>
#include <nic_session/connection.h>
#include <nic/packet_allocator.h>
#include <timer_session/connection.h>
#include <rtc_session/connection.h>
#include <timer_session/connection.h>
/* VMM utilities includes */
#include <vmm/guest_memory.h>
@ -180,11 +181,11 @@ class Guest_memory
Genode::Ram_dataspace_capability _ds;
Genode::Ram_dataspace_capability _fb_ds;
Genode::size_t _backing_store_size;
Genode::size_t _fb_size;
Genode::size_t const _backing_store_size;
Genode::size_t const _fb_size;
char *_local_addr;
char *_fb_addr;
Genode::addr_t _local_addr;
Genode::addr_t _fb_addr;
/*
* Noncopyable
@ -228,19 +229,20 @@ class Guest_memory
remaining_size(backing_store_size-fb_size)
{
try {
/* reserve some contiguous memory region */
Genode::Rm_connection rm_conn(env);
Genode::Region_map_client rm(rm_conn.create(_backing_store_size));
Genode::addr_t const local_addr = env.rm().attach(rm.dataspace());
env.rm().detach(local_addr);
/*
* RAM used as backing store for guest-physical memory
*/
enum {
MAX_SIZE = 0, OFFSET = 0, ANY_LOCAL_ADDRESS = false,
EXECUTABLE = true
};
env.rm().attach_executable(_ds, local_addr);
_local_addr = local_addr;
_local_addr = env.rm().attach(_ds, MAX_SIZE, OFFSET,
ANY_LOCAL_ADDRESS, nullptr,
EXECUTABLE);
_fb_addr = env.rm().attach_at(_fb_ds,
((Genode::addr_t) _local_addr)+backing_store_size-fb_size);
Genode::addr_t const fb_addr = local_addr + remaining_size;
env.rm().attach_at(_fb_ds, fb_addr);
_fb_addr = fb_addr;
}
catch (Genode::Region_map::Region_conflict) {
Genode::error("region conflict"); }
@ -261,7 +263,7 @@ class Guest_memory
*/
char *backing_store_local_base()
{
return _local_addr;
return reinterpret_cast<char *>(_local_addr);
}
Genode::size_t backing_store_size()
@ -274,7 +276,7 @@ class Guest_memory
*/
char *backing_store_fb_local_base()
{
return _fb_addr;
return reinterpret_cast<char *>(_fb_addr);
}
Genode::size_t fb_size() { return _fb_size; }
@ -1246,7 +1248,8 @@ class Machine : public StaticReceiver<Machine>
*/
Machine(Genode::Env &env, Genode::Heap &heap,
Boot_module_provider &boot_modules,
Guest_memory &guest_memory, bool colocate)
Guest_memory &guest_memory, bool colocate,
size_t const fb_size)
:
_env(env), _heap(heap),
_clock(Attached_rom_dataspace(env, "platform_info").xml().sub_node("hardware").sub_node("tsc").attribute_value("freq_khz", 0ULL) * 1000ULL),
@ -1269,6 +1272,13 @@ class Machine : public StaticReceiver<Machine>
_unsynchronized_motherboard.bus_hwpcicfg.add(this, receive_static<MessageHwPciConfig>);
_unsynchronized_motherboard.bus_acpi.add (this, receive_static<MessageAcpi>);
_unsynchronized_motherboard.bus_legacy.add (this, receive_static<MessageLegacy>);
/* tell vga model about available framebuffer memory */
Device_model_info *dmi = device_model_registry()->lookup("vga_fbsize");
if (dmi) {
unsigned long argv[2] = { fb_size >> 10, ~0UL };
dmi->create(_unsynchronized_motherboard, argv, "", 0);
}
}
@ -1398,7 +1408,6 @@ extern void heap_init_env(Genode::Heap *);
void Component::construct(Genode::Env &env)
{
Genode::addr_t fb_size = 4*1024*1024;
Genode::addr_t vm_size;
unsigned colocate = 1; /* by default co-locate VM and VMM in same PD */
@ -1423,16 +1432,6 @@ void Component::construct(Genode::Env &env)
/* calculate max memory for the VM */
vm_size = vm_size & ~((1UL << Vmm::PAGE_SIZE_LOG2) - 1);
/* Find out framebuffer size (default: 4 MiB) */
try {
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;
arg.value(&val);
fb_size = val*1024;
} catch (...) { }
/* read out whether VM and VMM should be colocated or not */
try {
config.xml().attribute("colocate").value(&colocate);
@ -1443,6 +1442,13 @@ void Component::construct(Genode::Env &env)
/* re-adjust reservation to actual VM size */
static Vmm::Virtual_reservation reservation(env, vm_size);
/* setup framebuffer memory for guest */
static Framebuffer::Connection framebuffer(env, Framebuffer::Mode(0, 0, Framebuffer::Mode::INVALID));
Framebuffer::Mode const fb_mode = framebuffer.mode();
size_t const fb_size = Genode::align_addr(fb_mode.width() *
fb_mode.height() *
fb_mode.bytes_per_pixel(), 12);
/* setup guest memory */
static Guest_memory guest_memory(env, vm_size, fb_size);
@ -1493,11 +1499,12 @@ void Component::construct(Genode::Env &env)
boot_modules(config.xml().sub_node("multiboot"));
/* create the PC machine based on the configuration given */
static Machine machine(env, heap, boot_modules, guest_memory, colocate);
static Machine machine(env, heap, boot_modules, guest_memory, colocate, fb_size);
/* create console thread */
static Seoul::Console vcon(env, machine.motherboard(),
machine.unsynchronized_motherboard(), fb_size,
machine.unsynchronized_motherboard(),
framebuffer,
guest_memory.fb_ds());
vcon.register_host_operations(machine.unsynchronized_motherboard());