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
This commit is contained in:
Reto Buerki 2016-04-25 13:16:59 +02:00 committed by Norman Feske
parent 7d00763861
commit 68bab6a411
3 changed files with 24 additions and 6 deletions

View File

@ -21,8 +21,11 @@ namespace Genode
enum { enum {
TIMER_BASE_ADDR = 0xe00010000, TIMER_BASE_ADDR = 0xe00010000,
TIMER_SIZE = 0x1000, TIMER_SIZE = 0x1000,
TIMER_PREEMPT_BASE_ADDR = 0xe00011000,
TIMER_PREEMPT_SIZE = 0x1000,
VECTOR_REMAP_BASE = 48, VECTOR_REMAP_BASE = 48,
TIMER_EVENT_PREEMPT = 30,
TIMER_EVENT_KERNEL = 31, TIMER_EVENT_KERNEL = 31,
TIMER_VECTOR_KERNEL = 32, TIMER_VECTOR_KERNEL = 32,
TIMER_VECTOR_USER = 50, TIMER_VECTOR_USER = 50,

View File

@ -46,7 +46,8 @@ class Genode::Timer
uint8_t event_nr :5; uint8_t event_nr :5;
} __attribute__((packed)); } __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() inline uint64_t rdtsc()
@ -75,15 +76,27 @@ class Genode::Timer
_event_page = (Subject_timed_event *)region.address; _event_page = (Subject_timed_event *)region.address;
_event_page->event_nr = Board::TIMER_EVENT_KERNEL; _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); region.address, _tics_per_ms, _event_page->event_nr);
if (sinfo()->get_memregion_info("monitor_timed_event", &region)) {
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) { static unsigned interrupt_id(int) {
return Board::TIMER_VECTOR_KERNEL; } return Board::TIMER_VECTOR_KERNEL; }
inline void start_one_shot(time_t const tics, unsigned) { inline void start_one_shot(time_t const tics, unsigned)
_event_page->tsc_trigger = rdtsc() + tics; } {
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 { time_t tics_to_us(time_t const tics) const {

View File

@ -65,6 +65,8 @@ Native_region * Platform::_core_only_mmio_regions(unsigned const i)
{ Sinfo::PHYSICAL_BASE_ADDR, Sinfo::SIZE }, { Sinfo::PHYSICAL_BASE_ADDR, Sinfo::SIZE },
/* Timer page */ /* Timer page */
{ Board::TIMER_BASE_ADDR, Board::TIMER_SIZE }, { 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; return i < sizeof(_regions)/sizeof(_regions[0]) ? &_regions[i] : 0;
} }