|
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] Re: [Xen-devel] [PATCH V5] x86/hvm: fix domain crash when CR3 has the noflush bit set
On 02/27/2018 06:26 PM, George Dunlap wrote:
>>> As an aside -- are you sure clearing the NOFLUSH from reported CR3
>>> values during introspection is the right thing to do? You don't think
>>> your introspection engine will ever want to know if the guest OS is
>>> setting this bit?
>>
>> We can't be sure this will never be useful to know, but at least for now
>> I've not seen any requests to be able to, and our introspection engine
>> is not interested in the information (in fact, one of the reasons why
>> we've even missed the problem until it's been reported is that we
>> haven't even been subscribing to CR3 write events for a while now).
>>
>> So as far as we're concerned, losing the information about the NOFLUSH
>> bit is no problem at all (and it's definitely preferable to a domain
>> crash). Since Tamas has acked the patch, it's safe to assume that they
>> have no problem with it either, and Bitweasil seemed happy with the
>> solution as well.
>>
>> I suppose we can always write a patch later if it turns out that this is
>> valuable information.
>
> Well if you want to maintain backwards compatibility, you'd need to
> either have the bit opt-in, or pass the noflush bit back somewhere else
> (either with a flag or with a different part of the struct).
>
> If everyone is happy with it I don't mind.
A bool-like .noflush field could be nice, except it would only apply to
CR3 but affect both the common CR structure:
243 struct vm_event_write_ctrlreg {
244 uint32_t index;
245 uint32_t _pad;
246 uint64_t new_value;
247 uint64_t old_value;
248 };
and the common CR monitor function:
33 bool hvm_monitor_cr(unsigned int index, unsigned long value,
unsigned long old)
34 {
35 struct vcpu *curr = current;
36 struct arch_domain *ad = &curr->domain->arch;
37 unsigned int ctrlreg_bitmask = monitor_ctrlreg_bitmask(index);
38
39 if ( index == VM_EVENT_X86_CR3 && hvm_pcid_enabled(curr) )
40 value &= ~X86_CR3_NOFLUSH; /* Clear the noflush bit. */
41
42 if ( (ad->monitor.write_ctrlreg_enabled & ctrlreg_bitmask) &&
43 (!(ad->monitor.write_ctrlreg_onchangeonly & ctrlreg_bitmask) ||
44 value != old) &&
45 ((value ^ old) & ~ad->monitor.write_ctrlreg_mask[index]) )
46 {
47 bool sync = ad->monitor.write_ctrlreg_sync & ctrlreg_bitmask;
48
49 vm_event_request_t req = {
50 .reason = VM_EVENT_REASON_WRITE_CTRLREG,
51 .u.write_ctrlreg.index = index,
52 .u.write_ctrlreg.new_value = value,
53 .u.write_ctrlreg.old_value = old
54 };
55
56 if ( monitor_traps(curr, sync, &req) >= 0 )
57 return 1;
58 }
59
60 return 0;
61 }
There's the additional problem of old vs. new values, as compared in the
above code: the way things work, the previous (old) value will always be
NOFLUSH-free (since we clear the NOFLUSH bit before storing). That means
that a NOFLUSH-set new value, identical to the old one except for the
NOFLUSH bit will trigger an "onchangeonly" event - which we don't want,
since the actual values are really identical (it's just that the NOFLUSH
bit has been removed before storing previously).
For example: previously we had (0x1 | NOFLUSH). We didn't flush, and
we've cleared the NOFLUSH bit, and now old value == 0x1.
CR3 is now being set again to (0x1 | NOFLUSH). Compared to the old
value, it's different, but is it? Was the previous value simply 0x1? Or
was it (0x1 | NOFLUSH)?
Thanks,
Razvan
_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxxxxxxxxx
https://lists.xenproject.org/mailman/listinfo/xen-devel
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |