[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [Xen-devel] [PATCH V2] x86/vm_event: block interrupt injection for sync vm_events



On 12/13/18 2:39 PM, Julien Grall wrote:
> Hi,
> 
> On 12/13/18 12:15 PM, Razvan Cojocaru wrote:
>> On 12/13/18 2:04 PM, Julien Grall wrote:
>>> Hi,
>>>
>>> On 12/13/18 8:03 AM, Razvan Cojocaru wrote:
>>>> On 12/13/18 8:54 AM, Tian, Kevin wrote:
>>>>>> From: Razvan Cojocaru [mailto:rcojocaru@xxxxxxxxxxxxxxx]
>>>>>> Sent: Tuesday, December 11, 2018 8:33 PM
>>>>>>
>>>>>>> In any case, I think you want to rename the function and/or document
>>>>>>> more that expected behavior.
>>>>>>
>>>>>> You're right, I should probably rename that function / variable to
>>>>>> better reflect what it signifies - that sync vm_event processing
>>>>>> is in
>>>>>> progress. For VMX and SVM, that simply means that interrupts will be
>>>>>> blocked, and the value of the variable will be correct and possibly
>>>>>> useful for ARM as well.
>>>>>>
>>>>>
>>>>> what about vm_event_block_interrupt_injection? in that case
>>>>> it's injection instead of interrupt itself being blocked. blocking
>>>>> injection should mean same thing cross archs?
>>>
>>> Why would you want to block all interrupts injections? When I looked at
>>> the details, it feels more you want to block exceptions.
>>>
>>> I can see use for blocking exception on Arm, blocking all the interrupts
>>> is likely going to bring more issues than solving anything.
>>>
>>> So a better name would be vm_event_block_exception_injection.
>>
>> I'd like to block the writing of anything, by vmx_intr_assist(), into
>> VM_ENTRY_INTR_INFO, because an emulation attempt that happens
>> post-vmx_intr_assist() (because the vm_event client application has
>> requested it) may write an exception of its own there.
>>
>> Since vmx_intr_assist() is called on VMX between the time of sending out
>> the vm_event and the emulation (which happens in
>> hvm_vm_event_do_resume()), we want to block everything that it may write
>> in the VMCS until the emulation is done. I think that's more than just
>> exceptions.
> 
> I don't know in details how x86 virtualization works, so it is a bit
> hard to comment on that. However, it feels to me that you are
> introducing in common code a function that will workaround an
> architecture specific problem.
> 
> Can you try to explain it in agnostic word?

I'll certainly do my best. :)

Assume the following scenario:

1. A guest instruction tries to write into read-only memory (as set in
the EPT), with monitoring active for the domain.

2. An EPT violation exit occurs, and in the course of it, the VCPU that
was running the code that produced the violation is paused and a
vm_event is sent to an introspection application.

3. The introspection application is processing the vm_event. During this
time, some event may occur (which will remain pending).

4. The introspection agent replies with "please emulate" the current
instruction - since the emulator (currently) does not care about EPT
restrictions, so this is a cheap way of proceeding without lifting them.

5. With x86, we have {vmx,svm}_intr_assist(), which is guaranteed to be
called _before_ the VCPU is woken up again. This is the designated "pick
up pending interrupts" function on x86. Perhaps this (real-life)
backtrace is helpful:

(XEN) Xen call trace:
(XEN)    [<ffff82d08031b55d>] vmx.c#__vmx_inject_exception+0xa1/0xda
(XEN)    [<ffff82d08031eb5c>] vmx_inject_extint+0x94/0x9f
(XEN)    [<ffff82d080315a0a>] vmx_intr_assist+0x4ee/0x5ad
(XEN)    [<ffff82d0803258ff>] vmx_asm_vmexit_handler+0xff/0x270

On x86, there can (currently) be only one scheduled interrupt /
exception, and that is written into VM_ENTRY_INTR_INFO in the VMCS on Intel.

6. _After_ vmx_intr_assist() has run, we are now trying to emulate the
current instruction, which may cause an exception, which will overwrite
the pending interrupt.

So, long story short, on VMX we first send out the vm_event, while
processing it an interrupt / exception may become pending, before
resuming the VCPU that has sent out the vm_event there's a Xen function
that picks up the pending interrupt and schedules it (writes it in the
VMCS), and only then we attempt the emulation, which may overwrite it
(because there's only one place we can write to schedule interrupts /
exceptions).

> To expand what I said above, I think it is reasonable to request
> blocking exception (e.g page-fault...) because they can be generated by
> an instruction. However, all interrupts generated by the interrupt
> controller (e.g device, IPI..) should not be blocked.
> 
> AFAIU your description, it is the same path to handle the two on x86,
> right?

Pretty much, yes. Technically speaking there are two that I am aware of,
the second of them being the IDT vectoring case just before the EPT
fault exit - but that's outside the scope of this patch. Just mentioning
it for completeness.

Also, it is worth mentioning that:

1. This is the exact same strategy employed by the single-stepping
functionality on VMX / Intel. In fact, if you look at
xen/arch/x86/hvm/vmx/intr.c, in vmx_intr_assist(), you'll see an early
return blocking injection of interrupts for the duration of single
stepping ("if ( unlikely(v->arch.hvm.single_step) )").

2. Interrupts are not blocked indefinitely - only until the emulation is
done. It could be argued that that's really the proper place for them to
be processed anyway - on an instruction boundary, _after_ the
in-progress instruction has finished executing. It's just that with the
vm_event introspection thing you could say that executing the current
instruction may take a bit longer.

I hope I've been able to explain it better this time. :)


Thanks,
Razvan

_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxxxxxxxxx
https://lists.xenproject.org/mailman/listinfo/xen-devel

 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.