From 68bab6a411fa3638db3758d956d914a9273eb923 Mon Sep 17 00:00:00 2001 From: Reto Buerki Date: Mon, 25 Apr 2016 13:16:59 +0200 Subject: [PATCH] hw_x86_64_muen: Use timed events for guest preemption Write tick count of next kernel timer to the guest timed events page if present. This causes the guest VM to be preempted at the requested tick count and ensures that the guest VM can not monopolize the CPU if no traps occur. The base-hw kernel expects a configured switch-event from the guest VM to base-hw with ID 30 and target vector 32 to be present in the system policy. Issue #2016 --- .../src/core/include/spec/x86_64/muen/board.h | 7 +++++-- .../src/core/include/spec/x86_64/muen/timer.h | 21 +++++++++++++++---- .../core/spec/x86_64/muen/platform_support.cc | 2 ++ 3 files changed, 24 insertions(+), 6 deletions(-) diff --git a/repos/base-hw/src/core/include/spec/x86_64/muen/board.h b/repos/base-hw/src/core/include/spec/x86_64/muen/board.h index e6e6eef74..406591874 100644 --- a/repos/base-hw/src/core/include/spec/x86_64/muen/board.h +++ b/repos/base-hw/src/core/include/spec/x86_64/muen/board.h @@ -19,10 +19,13 @@ namespace Genode struct Board { enum { - TIMER_BASE_ADDR = 0xe00010000, - TIMER_SIZE = 0x1000, + TIMER_BASE_ADDR = 0xe00010000, + TIMER_SIZE = 0x1000, + TIMER_PREEMPT_BASE_ADDR = 0xe00011000, + TIMER_PREEMPT_SIZE = 0x1000, VECTOR_REMAP_BASE = 48, + TIMER_EVENT_PREEMPT = 30, TIMER_EVENT_KERNEL = 31, TIMER_VECTOR_KERNEL = 32, TIMER_VECTOR_USER = 50, diff --git a/repos/base-hw/src/core/include/spec/x86_64/muen/timer.h b/repos/base-hw/src/core/include/spec/x86_64/muen/timer.h index c5b179028..17064e431 100644 --- a/repos/base-hw/src/core/include/spec/x86_64/muen/timer.h +++ b/repos/base-hw/src/core/include/spec/x86_64/muen/timer.h @@ -46,7 +46,8 @@ class Genode::Timer uint8_t event_nr :5; } __attribute__((packed)); - struct Subject_timed_event * _event_page; + struct Subject_timed_event * _event_page = 0; + struct Subject_timed_event * _guest_event_page = 0; inline uint64_t rdtsc() @@ -75,15 +76,27 @@ class Genode::Timer _event_page = (Subject_timed_event *)region.address; _event_page->event_nr = Board::TIMER_EVENT_KERNEL; - PINF("muen-timer: page @0x%llx, frequency %llu kHz, event %u", + PINF("muen-timer: Page @0x%llx, frequency %llu kHz, event %u", region.address, _tics_per_ms, _event_page->event_nr); + + if (sinfo()->get_memregion_info("monitor_timed_event", ®ion)) { + PINF("muen-timer: Found guest timed event page @0x%llx" + " -> enabling preemption", region.address); + _guest_event_page = (Subject_timed_event *)region.address; + _guest_event_page->event_nr = Board::TIMER_EVENT_PREEMPT; + } } static unsigned interrupt_id(int) { return Board::TIMER_VECTOR_KERNEL; } - inline void start_one_shot(time_t const tics, unsigned) { - _event_page->tsc_trigger = rdtsc() + tics; } + inline void start_one_shot(time_t const tics, unsigned) + { + const uint64_t t = rdtsc() + tics; + _event_page->tsc_trigger = t; + + if (_guest_event_page) + _guest_event_page->tsc_trigger = t; } time_t tics_to_us(time_t const tics) const { diff --git a/repos/base-hw/src/core/spec/x86_64/muen/platform_support.cc b/repos/base-hw/src/core/spec/x86_64/muen/platform_support.cc index 601c208e2..301be48b3 100644 --- a/repos/base-hw/src/core/spec/x86_64/muen/platform_support.cc +++ b/repos/base-hw/src/core/spec/x86_64/muen/platform_support.cc @@ -65,6 +65,8 @@ Native_region * Platform::_core_only_mmio_regions(unsigned const i) { Sinfo::PHYSICAL_BASE_ADDR, Sinfo::SIZE }, /* Timer page */ { Board::TIMER_BASE_ADDR, Board::TIMER_SIZE }, + /* Optional guest timed event page for preemption */ + { Board::TIMER_PREEMPT_BASE_ADDR, Board::TIMER_PREEMPT_SIZE }, }; return i < sizeof(_regions)/sizeof(_regions[0]) ? &_regions[i] : 0; }