x86/vhpet: check that the set interrupt route is valid

The value written by the guest must be valid according to the mask
provided in the interrupt routing capabilities register. If the
interrupt is not valid set it to the first valid IRQ in the
capabilities field if the timer is enabled, else just clear the field.

Also refuse to start any timer that has an invalid interrupt route.

Signed-off-by: Roger Pau Monné <roger.pau@citrix.com>
Reviewed-by: Jan Beulich <jbeulich@suse.com>
This commit is contained in:
Roger Pau Monné authored and Jan Beulich committed 2018-07-05 15:43:28 +02:00
1 parent 74bd642940
commit ec40d3fe21
1 file changed
+30
+30
View File
@@ -73,6 +73,9 @@
((timer_config(h, n) & HPET_TN_INT_ROUTE_CAP_MASK) \
>> HPET_TN_INT_ROUTE_CAP_SHIFT)
#define timer_int_route_valid(h, n) \
((1u << timer_int_route(h, n)) & timer_int_route_cap(h, n))
static inline uint64_t hpet_read_maincounter(HPETState *h, uint64_t guest_time)
{
ASSERT(rw_is_locked(&h->lock));
@@ -244,6 +247,12 @@ static void hpet_set_timer(HPETState *h, unsigned int tn,
if ( !timer_enabled(h, tn) )
return;
if ( !timer_int_route_valid(h, tn) )
{
ASSERT_UNREACHABLE();
return;
}
tn_cmp = hpet_get_comparator(h, tn, guest_time);
cur_tick = hpet_read_maincounter(h, guest_time);
if ( timer_is_32bit(h, tn) )
@@ -304,6 +313,24 @@ static inline uint64_t hpet_fixup_reg(
return new;
}
static void timer_sanitize_int_route(HPETState *h, unsigned int tn)
{
if ( timer_int_route_valid(h, tn) )
return;
timer_config(h, tn) &= ~HPET_TN_ROUTE;
if ( !timer_enabled(h, tn) )
return;
/*
* If the requested interrupt is not valid and the timer is
* enabled pick the first irq.
*/
timer_config(h, tn) |=
MASK_INSR(find_first_set_bit(timer_int_route_cap(h, tn)),
HPET_TN_ROUTE);
}
static int hpet_write(
struct vcpu *v, unsigned long addr,
unsigned int length, unsigned long val)
@@ -386,6 +413,8 @@ static int hpet_write(
h->hpet.timers[tn].config = hpet_fixup_reg(new_val, old_val, 0x3f4e);
timer_sanitize_int_route(h, tn);
if ( timer_level(h, tn) )
{
gdprintk(XENLOG_ERR,
@@ -621,6 +650,7 @@ static int hpet_load(struct domain *d, hvm_domain_context_t *h)
if ( timer_is_32bit(hp, i) )
cmp = (uint32_t)cmp;
hp->hpet.timers[i].cmp = cmp;
timer_sanitize_int_route(hp, i);
}
#undef C
Reference in new issue
Block a user
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.