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 e6e6eef740..4065918740 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 c5b179028d..17064e4319 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 601c208e2d..301be48b31 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; }