seoul: reduce CPU load in graphic mode

- Stop refreshing if all CPUs go to sleep, also in text mode.
- Any input resets update rate to 100Hz in graphic mode, which gets
  decreased step by step down to 25Hz if no input is available (looking video
  without input by user).

Fixes #3576
This commit is contained in:
Alexander Boettcher 2019-11-15 11:07:52 +01:00 committed by Christian Helmuth
parent d385749ead
commit 9812799b24
5 changed files with 81 additions and 29 deletions

View File

@ -71,7 +71,7 @@ foreach binary $guest_os_binaries {
source ${genode_dir}/repos/ports/run/seoul.inc
append qemu_args " -cpu phenom "
append qemu_args " -cpu phenom -smp 2 "
append qemu_args " -net nic,model=e1000 "
append qemu_args " -nographic "

View File

@ -74,7 +74,7 @@ build $build_components
# write Seoul config file
set vm_cfg_fd [open "bin/vm_seoul.cfg" w]
puts $vm_cfg_fd "<config map_small=\"$map_small\" vmm_vcpu_same_cpu=\"$vmm_vcpu_same_cpu\">"
puts $vm_cfg_fd { <machine>
puts $vm_cfg_fd { <machine verbose="no">
<mem start="0x0" end="0x9a000"/>
<mem start="0x100000" end="0xfffff000"/>
<!--<ioio/>-->

View File

@ -785,7 +785,9 @@ class Machine : public StaticReceiver<Machine>
Seoul::Network *_nic { nullptr };
Rtc::Session *_rtc { nullptr };
Vcpu * _vcpus[32] { nullptr };
enum { MAX_CPUS = 8 };
Vcpu * _vcpus[MAX_CPUS] { nullptr };
Genode::Bit_array<64> _vcpus_active { };
/*
* Noncopyable
@ -907,6 +909,8 @@ class Machine : public StaticReceiver<Machine>
ep_name->string(),
location);
_vcpus_active.set(_vcpus_up, 1);
Vcpu * vcpu = new Vcpu(*ep, _vm_con, _heap, _env,
_motherboard_lock, msg.vcpu,
_guest_memory, _motherboard,
@ -956,12 +960,26 @@ class Machine : public StaticReceiver<Machine>
if (!_vcpus[vcpu_id])
return false;
_vcpus_active.clear(vcpu_id, 1);
if (!_vcpus_active.get(0, 64)) {
MessageConsole msgcon(MessageConsole::Type::TYPE_KILL);
_unsynchronized_motherboard.bus_console.send(msgcon);
}
_motherboard_lock.unlock();
_vcpus[vcpu_id]->block();
_motherboard_lock.lock();
if (!_vcpus_active.get(0, 64)) {
MessageConsole msgcon(MessageConsole::Type::TYPE_RESET);
_unsynchronized_motherboard.bus_console.send(msgcon);
}
_vcpus_active.set(vcpu_id, 1);
return true;
}
@ -1218,6 +1236,8 @@ class Machine : public StaticReceiver<Machine>
{
using namespace Genode;
bool const verbose = machine_node.attribute_value("verbose", false);
Xml_node node = machine_node.sub_node();
for (;; node = node.next()) {
@ -1225,7 +1245,9 @@ class Machine : public StaticReceiver<Machine>
char name[MODEL_NAME_MAX_LEN];
node.type_name(name, sizeof(name));
Genode::log("device: ", (char const *)name);
if (verbose)
Genode::log("device: ", (char const *)name);
Device_model_info *dmi = device_model_registry()->lookup(name);
if (!dmi) {
@ -1249,7 +1271,8 @@ class Machine : public StaticReceiver<Machine>
Xml_node::Attribute arg = node.attribute(dmi->arg_names[i]);
arg.value(&argv[i]);
Genode::log(" arg[", i, "]: ", Genode::Hex(argv[i]));
if (verbose)
Genode::log(" arg[", i, "]: ", Genode::Hex(argv[i]));
}
catch (Xml_node::Nonexistent_attribute) { }
}

View File

@ -38,13 +38,13 @@ static Tff_font::Static_glyph_buffer<4096> glyph_buffer { };
static Tff_font default_font(_binary_mono_tff_start, glyph_buffer);
static struct {
Genode::uint64_t checksum1 = 0;
Genode::uint64_t checksum2 = 0;
unsigned unchanged = 0;
bool cmp_even = 1;
bool active = false;
bool revoked = false;
bool vga_update= false; /* update indirectly by vbios */
Genode::uint64_t checksum1 = 0;
Genode::uint64_t checksum2 = 0;
unsigned unchanged = 0;
bool cmp_even = 1;
bool active = false;
bool vga_revoked = false;
bool vga_update = false; /* update indirectly by vbios */
} fb_state;
@ -153,15 +153,17 @@ unsigned Seoul::Console::_input_to_ps2wheel(Input::Event const &ev)
bool Seoul::Console::receive(MessageConsole &msg)
{
if (msg.type == MessageConsole::TYPE_ALLOC_VIEW) {
switch (msg.type) {
case MessageConsole::TYPE_ALLOC_VIEW :
_guest_fb = msg.ptr;
_regs = msg.regs;
msg.view = 0;
} else if (msg.type == MessageConsole::TYPE_SWITCH_VIEW) {
return true;
case MessageConsole::TYPE_SWITCH_VIEW:
/* XXX: For now, we only have one view. */
} else if (msg.type == MessageConsole::TYPE_GET_MODEINFO) {
return true;
case MessageConsole::TYPE_GET_MODEINFO:
enum {
MEMORY_MODEL_TEXT = 0,
MEMORY_MODEL_DIRECT_COLOR = 6,
@ -210,9 +212,18 @@ bool Seoul::Console::receive(MessageConsole &msg)
msg.info->phys_base = 0xe0000000;
msg.info->_phys_size = _fb_mode.width()*_fb_mode.height()*2;
return true;
} else return false;
}
return false;
case MessageConsole::TYPE_KILL: /* all CPUs go idle */
_handle_fb(); /* refresh before going to sleep */
fb_state.active = false;
return true;
case MessageConsole::TYPE_RESET: /* first of all sleeping CPUs woke up */
_reactivate();
return true;
default:
return true;
}
return true;
}
void Screen::vga_updated()
@ -220,6 +231,14 @@ void Screen::vga_updated()
fb_state.vga_update = true;
}
void Seoul::Console::_reactivate()
{
fb_state.active = true;
MessageTimer msg(_timer, _unsynchronized_motherboard.clock()->abstime(1, 1000));
_unsynchronized_motherboard.bus_timer.send(msg);
}
bool Seoul::Console::receive(MessageMemRegion &msg)
{
/* we had a fault in the text framebuffer */
@ -234,11 +253,11 @@ bool Seoul::Console::receive(MessageMemRegion &msg)
}
if (reactivate) {
if (!fb_state.active) fb_state.active = true;
fb_state.vga_revoked = false;
Logging::printf("Reactivating text buffer loop.\n");
MessageTimer msg(_timer, _unsynchronized_motherboard.clock()->abstime(1, 1000));
_unsynchronized_motherboard.bus_timer.send(msg);
_reactivate();
}
return false;
}
@ -254,8 +273,7 @@ unsigned Seoul::Console::_handle_fb()
/* transfer text buffer content into chunky canvas */
if (_regs->mode == TEXT_MODE) {
if (fb_state.revoked || !fb_state.active)
return 0;
if (fb_state.vga_revoked || !fb_state.active) return 0;
memset(_pixels, 0, _fb_size);
@ -299,24 +317,32 @@ unsigned Seoul::Console::_handle_fb()
_memory.detach(PHYS_FRAME_VGA_COLOR << 12,
FRAME_COUNT_COLOR << 12);
fb_state.vga_revoked = true;
fb_state.unchanged = 0;
fb_state.active = false;
_framebuffer.refresh(0, 0, _fb_mode.width(), _fb_mode.height());
Logging::printf("Deactivated text buffer loop.\n");
return 0;
}
if (!fb_state.revoked) {
if (!fb_state.vga_revoked) {
_memory.detach(PHYS_FRAME_VGA_COLOR << 12,
FRAME_COUNT_COLOR << 12);
fb_state.revoked = true;
fb_state.vga_revoked = true;
}
if (!fb_state.active) {
fb_state.unchanged = 0;
return 0;
}
_framebuffer.refresh(0, 0, _fb_mode.width(), _fb_mode.height());
return 10;
fb_state.unchanged++;
return (fb_state.unchanged > 4) ? 4 * 10 : fb_state.unchanged * 10;
}

View File

@ -25,6 +25,7 @@
#include <base/env.h>
#include <dataspace/client.h>
#include <util/string.h>
#include <util/bit_array.h>
/* os includes */
#include <framebuffer_session/connection.h>
@ -64,13 +65,13 @@ class Seoul::Console : public StaticReceiver<Seoul::Console>
Genode::addr_t const _vm_phys_fb;
short *_pixels;
Genode::Surface<Pixel_rgb565> _surface;
unsigned _timer { 0 };
Keyboard _vkeyb { _motherboard };
char *_guest_fb { nullptr };
VgaRegs *_regs { nullptr };
bool _left { false };
bool _middle { false };
bool _right { false };
unsigned _timer { 0 };
unsigned _input_to_ps2mouse(Input::Event const &);
unsigned _input_to_ps2wheel(Input::Event const &);
@ -81,6 +82,8 @@ class Seoul::Console : public StaticReceiver<Seoul::Console>
void _handle_input();
unsigned _handle_fb();
void _reactivate();
/*
* Noncopyable
*/