diff mbox

[V5] x86/vm_event: Added support for VM_EVENT_REASON_INTERRUPT

Message ID 1478880542-3950-1-git-send-email-rcojocaru@bitdefender.com (mailing list archive)
State New, archived
Headers show

Commit Message

Razvan Cojocaru Nov. 11, 2016, 4:09 p.m. UTC
Added support for a new event type, VM_EVENT_REASON_INTERRUPT,
which is now fired in a one-shot manner when enabled via the new
VM_EVENT_FLAG_GET_NEXT_INTERRUPT vm_event response flag.
The patch also fixes the behaviour of the xc_hvm_inject_trap()
hypercall, which would lead to non-architectural interrupts
overwriting pending (specifically reinjected) architectural ones.

Signed-off-by: Razvan Cojocaru <rcojocaru@bitdefender.com>
Acked-by: Tamas K Lengyel <tamas@tklengyel.com>

---
Changes since V4:
 - Fixed typo in vm_event_monitor_next_interrupt()
   ( v->arch.monitor.next_interrupt_enabled should have been set
   to true, not false ).

Changes in V4 since V3:
 - Const-ified struct vmcb_struct *vmcb in svm_get_pending_event().
 - Made next_interrupt_enabled into a bool.
---
 xen/arch/x86/hvm/hvm.c            | 22 +++++++++++++++++++++-
 xen/arch/x86/hvm/monitor.c        | 14 ++++++++++++++
 xen/arch/x86/hvm/svm/svm.c        | 15 +++++++++++++++
 xen/arch/x86/hvm/vmx/vmx.c        | 20 ++++++++++++++++++++
 xen/arch/x86/vm_event.c           |  5 +++++
 xen/common/vm_event.c             |  3 +++
 xen/include/asm-arm/vm_event.h    |  6 ++++++
 xen/include/asm-x86/domain.h      |  4 ++++
 xen/include/asm-x86/hvm/hvm.h     |  1 +
 xen/include/asm-x86/hvm/monitor.h |  2 ++
 xen/include/asm-x86/monitor.h     |  3 ++-
 xen/include/public/domctl.h       |  1 +
 xen/include/public/vm_event.h     | 18 ++++++++++++++++++
 xen/include/xen/vm_event.h        |  2 ++
 14 files changed, 114 insertions(+), 2 deletions(-)

Comments

Jan Beulich Nov. 11, 2016, 4:31 p.m. UTC | #1
>>> On 11.11.16 at 17:09, <rcojocaru@bitdefender.com> wrote:
> Added support for a new event type, VM_EVENT_REASON_INTERRUPT,
> which is now fired in a one-shot manner when enabled via the new
> VM_EVENT_FLAG_GET_NEXT_INTERRUPT vm_event response flag.
> The patch also fixes the behaviour of the xc_hvm_inject_trap()
> hypercall, which would lead to non-architectural interrupts
> overwriting pending (specifically reinjected) architectural ones.
> 
> Signed-off-by: Razvan Cojocaru <rcojocaru@bitdefender.com>
> Acked-by: Tamas K Lengyel <tamas@tklengyel.com>

Acked-by: Jan Beulich <jbeulich@suse.com>
Tian, Kevin Nov. 16, 2016, 7:22 a.m. UTC | #2
> From: Razvan Cojocaru [mailto:rcojocaru@bitdefender.com]
> Sent: Saturday, November 12, 2016 12:09 AM
> 
> Added support for a new event type, VM_EVENT_REASON_INTERRUPT,
> which is now fired in a one-shot manner when enabled via the new
> VM_EVENT_FLAG_GET_NEXT_INTERRUPT vm_event response flag.
> The patch also fixes the behaviour of the xc_hvm_inject_trap()
> hypercall, which would lead to non-architectural interrupts
> overwriting pending (specifically reinjected) architectural ones.
> 
> Signed-off-by: Razvan Cojocaru <rcojocaru@bitdefender.com>
> Acked-by: Tamas K Lengyel <tamas@tklengyel.com>
> 
> ---
> Changes since V4:
>  - Fixed typo in vm_event_monitor_next_interrupt()
>    ( v->arch.monitor.next_interrupt_enabled should have been set
>    to true, not false ).
> 
> Changes in V4 since V3:
>  - Const-ified struct vmcb_struct *vmcb in svm_get_pending_event().
>  - Made next_interrupt_enabled into a bool.
> ---
>  xen/arch/x86/hvm/hvm.c            | 22 +++++++++++++++++++++-
>  xen/arch/x86/hvm/monitor.c        | 14 ++++++++++++++
>  xen/arch/x86/hvm/svm/svm.c        | 15 +++++++++++++++
>  xen/arch/x86/hvm/vmx/vmx.c        | 20 ++++++++++++++++++++
>  xen/arch/x86/vm_event.c           |  5 +++++
>  xen/common/vm_event.c             |  3 +++
>  xen/include/asm-arm/vm_event.h    |  6 ++++++
>  xen/include/asm-x86/domain.h      |  4 ++++
>  xen/include/asm-x86/hvm/hvm.h     |  1 +
>  xen/include/asm-x86/hvm/monitor.h |  2 ++
>  xen/include/asm-x86/monitor.h     |  3 ++-
>  xen/include/public/domctl.h       |  1 +
>  xen/include/public/vm_event.h     | 18 ++++++++++++++++++
>  xen/include/xen/vm_event.h        |  2 ++
>  14 files changed, 114 insertions(+), 2 deletions(-)
> 
> diff --git a/xen/arch/x86/hvm/hvm.c b/xen/arch/x86/hvm/hvm.c
> index 704fd64..93af5b8 100644
> --- a/xen/arch/x86/hvm/hvm.c
> +++ b/xen/arch/x86/hvm/hvm.c
> @@ -469,6 +469,12 @@ void hvm_migrate_pirqs(struct vcpu *v)
>      spin_unlock(&d->event_lock);
>  }
> 
> +static bool hvm_get_pending_event(struct vcpu *v, struct hvm_trap *info)
> +{
> +    info->cr2 = v->arch.hvm_vcpu.guest_cr[2];
> +    return hvm_funcs.get_pending_event(v, info);
> +}
> +
>  void hvm_do_resume(struct vcpu *v)
>  {
>      check_wakeup_from_wait();
> @@ -535,9 +541,23 @@ void hvm_do_resume(struct vcpu *v)
>      /* Inject pending hw/sw trap */
>      if ( v->arch.hvm_vcpu.inject_trap.vector != -1 )
>      {
> -        hvm_inject_trap(&v->arch.hvm_vcpu.inject_trap);
> +        if ( !hvm_event_pending(v) )
> +            hvm_inject_trap(&v->arch.hvm_vcpu.inject_trap);
> +
>          v->arch.hvm_vcpu.inject_trap.vector = -1;
>      }
> +
> +    if ( unlikely(v->arch.vm_event) && v->arch.monitor.next_interrupt_enabled )
> +    {
> +        struct hvm_trap info;
> +
> +        if ( hvm_get_pending_event(v, &info) )
> +        {
> +            hvm_monitor_interrupt(info.vector, info.type, info.error_code,
> +                                  info.cr2);
> +            v->arch.monitor.next_interrupt_enabled = false;
> +        }
> +    }
>  }
> 
>  static int hvm_print_line(
> diff --git a/xen/arch/x86/hvm/monitor.c b/xen/arch/x86/hvm/monitor.c
> index 401a8c6..69a88ad 100644
> --- a/xen/arch/x86/hvm/monitor.c
> +++ b/xen/arch/x86/hvm/monitor.c
> @@ -150,6 +150,20 @@ int hvm_monitor_cpuid(unsigned long insn_length, unsigned int
> leaf,
>      return monitor_traps(curr, 1, &req);
>  }
> 
> +void hvm_monitor_interrupt(unsigned int vector, unsigned int type,
> +                           unsigned int err, uint64_t cr2)
> +{
> +    vm_event_request_t req = {
> +        .reason = VM_EVENT_REASON_INTERRUPT,
> +        .u.interrupt.x86.vector = vector,
> +        .u.interrupt.x86.type = type,
> +        .u.interrupt.x86.error_code = err,
> +        .u.interrupt.x86.cr2 = cr2,
> +    };
> +
> +    monitor_traps(current, 1, &req);
> +}
> +
>  /*
>   * Local variables:
>   * mode: C
> diff --git a/xen/arch/x86/hvm/svm/svm.c b/xen/arch/x86/hvm/svm/svm.c
> index c9dbbea..7fe27e4 100644
> --- a/xen/arch/x86/hvm/svm/svm.c
> +++ b/xen/arch/x86/hvm/svm/svm.c
> @@ -2222,6 +2222,20 @@ static void svm_invlpg(struct vcpu *v, unsigned long vaddr)
>      svm_asid_g_invlpg(v, vaddr);
>  }
> 
> +static bool svm_get_pending_event(struct vcpu *v, struct hvm_trap *info)
> +{
> +    const struct vmcb_struct *vmcb = v->arch.hvm_svm.vmcb;
> +
> +    if ( vmcb->eventinj.fields.v )
> +        return false;
> +
> +    info->vector = vmcb->eventinj.fields.vector;
> +    info->type = vmcb->eventinj.fields.type;
> +    info->error_code = vmcb->eventinj.fields.errorcode;
> +
> +    return true;
> +}
> +
>  static struct hvm_function_table __initdata svm_function_table = {
>      .name                 = "SVM",
>      .cpu_up_prepare       = svm_cpu_up_prepare,
> @@ -2252,6 +2266,7 @@ static struct hvm_function_table __initdata svm_function_table
> = {
>      .inject_trap          = svm_inject_trap,
>      .init_hypercall_page  = svm_init_hypercall_page,
>      .event_pending        = svm_event_pending,
> +    .get_pending_event    = svm_get_pending_event,
>      .invlpg               = svm_invlpg,
>      .cpuid_intercept      = svm_cpuid_intercept,
>      .wbinvd_intercept     = svm_wbinvd_intercept,
> diff --git a/xen/arch/x86/hvm/vmx/vmx.c b/xen/arch/x86/hvm/vmx/vmx.c
> index 9a8f694..961a20b 100644
> --- a/xen/arch/x86/hvm/vmx/vmx.c
> +++ b/xen/arch/x86/hvm/vmx/vmx.c
> @@ -2134,6 +2134,25 @@ static int vmx_set_mode(struct vcpu *v, int mode)
>      return 0;
>  }
> 
> +static bool vmx_get_pending_event(struct vcpu *v, struct hvm_trap *info)
> +{
> +    unsigned long intr_info, error_code;
> +
> +    vmx_vmcs_enter(v);
> +    __vmread(VM_ENTRY_INTR_INFO, &intr_info);
> +    __vmread(VM_ENTRY_EXCEPTION_ERROR_CODE, &error_code);
> +    vmx_vmcs_exit(v);
> +
> +    if ( !(intr_info & INTR_INFO_VALID_MASK) )
> +        return false;
> +
> +    info->vector = MASK_EXTR(intr_info, INTR_INFO_VECTOR_MASK);
> +    info->type = MASK_EXTR(intr_info, INTR_INFO_INTR_TYPE_MASK);
> +    info->error_code = error_code;
> +
> +    return true;
> +}
> +

Looks not working with APICv virtual interrupt delivery...

Thanks
Kevin
Razvan Cojocaru Nov. 16, 2016, 7:48 a.m. UTC | #3
On 11/16/2016 09:22 AM, Tian, Kevin wrote:
> Looks not working with APICv virtual interrupt delivery...

It's only meant to work with "regular" injections (we'd like to be able
to tell if xc_hvm_inject_trap() can succeed). APICv support could be a
later patch, if desirable (AFAICT, the two types shouldn't collide, i.e.
impede trap delivery as done by the xc_hvm_inject_trap() hypercall).


Thanks,
Razvan
Tian, Kevin Nov. 17, 2016, 5:11 a.m. UTC | #4
> From: Razvan Cojocaru [mailto:rcojocaru@bitdefender.com]
> Sent: Wednesday, November 16, 2016 3:49 PM
> 
> On 11/16/2016 09:22 AM, Tian, Kevin wrote:
> > Looks not working with APICv virtual interrupt delivery...
> 
> It's only meant to work with "regular" injections (we'd like to be able
> to tell if xc_hvm_inject_trap() can succeed). APICv support could be a
> later patch, if desirable (AFAICT, the two types shouldn't collide, i.e.
> impede trap delivery as done by the xc_hvm_inject_trap() hypercall).
> 
> 

OK then. Acked-by: Kevin Tian <kevin.tian@intel.com>
Razvan Cojocaru Dec. 13, 2016, 8:50 a.m. UTC | #5
On 11/17/2016 07:11 AM, Tian, Kevin wrote:
>> From: Razvan Cojocaru [mailto:rcojocaru@bitdefender.com]
>> Sent: Wednesday, November 16, 2016 3:49 PM
>>
>> On 11/16/2016 09:22 AM, Tian, Kevin wrote:
>>> Looks not working with APICv virtual interrupt delivery...
>>
>> It's only meant to work with "regular" injections (we'd like to be able
>> to tell if xc_hvm_inject_trap() can succeed). APICv support could be a
>> later patch, if desirable (AFAICT, the two types shouldn't collide, i.e.
>> impede trap delivery as done by the xc_hvm_inject_trap() hypercall).
>>
>>
> 
> OK then. Acked-by: Kevin Tian <kevin.tian@intel.com>

AFAIK this has been acked by everyone a while back, is further action
required on my part, or is just low in the patch queue?


Thanks,
Razvan
Jan Beulich Dec. 13, 2016, 9:09 a.m. UTC | #6
>>> On 13.12.16 at 09:50, <rcojocaru@bitdefender.com> wrote:
> On 11/17/2016 07:11 AM, Tian, Kevin wrote:
>>> From: Razvan Cojocaru [mailto:rcojocaru@bitdefender.com]
>>> Sent: Wednesday, November 16, 2016 3:49 PM
>>>
>>> On 11/16/2016 09:22 AM, Tian, Kevin wrote:
>>>> Looks not working with APICv virtual interrupt delivery...
>>>
>>> It's only meant to work with "regular" injections (we'd like to be able
>>> to tell if xc_hvm_inject_trap() can succeed). APICv support could be a
>>> later patch, if desirable (AFAICT, the two types shouldn't collide, i.e.
>>> impede trap delivery as done by the xc_hvm_inject_trap() hypercall).
>>>
>>>
>> 
>> OK then. Acked-by: Kevin Tian <kevin.tian@intel.com>
> 
> AFAIK this has been acked by everyone a while back,

Has it? I've meant to apply it the other day, but couldn't find
any ARM or AMD SVM maintainer acks.

Jan
Razvan Cojocaru Dec. 13, 2016, 9:14 a.m. UTC | #7
On 12/13/2016 11:09 AM, Jan Beulich wrote:
>>>> On 13.12.16 at 09:50, <rcojocaru@bitdefender.com> wrote:
>> On 11/17/2016 07:11 AM, Tian, Kevin wrote:
>>>> From: Razvan Cojocaru [mailto:rcojocaru@bitdefender.com]
>>>> Sent: Wednesday, November 16, 2016 3:49 PM
>>>>
>>>> On 11/16/2016 09:22 AM, Tian, Kevin wrote:
>>>>> Looks not working with APICv virtual interrupt delivery...
>>>>
>>>> It's only meant to work with "regular" injections (we'd like to be able
>>>> to tell if xc_hvm_inject_trap() can succeed). APICv support could be a
>>>> later patch, if desirable (AFAICT, the two types shouldn't collide, i.e.
>>>> impede trap delivery as done by the xc_hvm_inject_trap() hypercall).
>>>>
>>>>
>>>
>>> OK then. Acked-by: Kevin Tian <kevin.tian@intel.com>
>>
>> AFAIK this has been acked by everyone a while back,
> 
> Has it? I've meant to apply it the other day, but couldn't find
> any ARM or AMD SVM maintainer acks.

Oh I see. At one point Julien came into the conversation but it was just
a friendly discussion about spelling somewhere - I've misremembered that
as an ack, I now see.


Thanks,
Razvan
Suthikulpanit, Suravee Dec. 13, 2016, 10:34 a.m. UTC | #8
On 12/13/2016 04:09 PM, Jan Beulich wrote:
>>>> On 13.12.16 at 09:50, <rcojocaru@bitdefender.com> wrote:
>> On 11/17/2016 07:11 AM, Tian, Kevin wrote:
>>>> From: Razvan Cojocaru [mailto:rcojocaru@bitdefender.com]
>>>> Sent: Wednesday, November 16, 2016 3:49 PM
>>>>
>>>> On 11/16/2016 09:22 AM, Tian, Kevin wrote:
>>>>> Looks not working with APICv virtual interrupt delivery...
>>>>
>>>> It's only meant to work with "regular" injections (we'd like to be able
>>>> to tell if xc_hvm_inject_trap() can succeed). APICv support could be a
>>>> later patch, if desirable (AFAICT, the two types shouldn't collide, i.e.
>>>> impede trap delivery as done by the xc_hvm_inject_trap() hypercall).
>>>>
>>>>
>>>
>>> OK then. Acked-by: Kevin Tian <kevin.tian@intel.com>
>>
>> AFAIK this has been acked by everyone a while back,
>
> Has it? I've meant to apply it the other day, but couldn't find
> any ARM or AMD SVM maintainer acks.
>
> Jan
>

Acked-by: Suravee Suthikulpanit <suravee.suthikulpanit@amd.com>
Julien Grall Dec. 13, 2016, 12:53 p.m. UTC | #9
Hi Razvan,

On 13/12/16 09:14, Razvan Cojocaru wrote:
> On 12/13/2016 11:09 AM, Jan Beulich wrote:
>>>>> On 13.12.16 at 09:50, <rcojocaru@bitdefender.com> wrote:
>>> On 11/17/2016 07:11 AM, Tian, Kevin wrote:
>>>>> From: Razvan Cojocaru [mailto:rcojocaru@bitdefender.com]
>>>>> Sent: Wednesday, November 16, 2016 3:49 PM
>>>>>
>>>>> On 11/16/2016 09:22 AM, Tian, Kevin wrote:
>>>>>> Looks not working with APICv virtual interrupt delivery...
>>>>>
>>>>> It's only meant to work with "regular" injections (we'd like to be able
>>>>> to tell if xc_hvm_inject_trap() can succeed). APICv support could be a
>>>>> later patch, if desirable (AFAICT, the two types shouldn't collide, i.e.
>>>>> impede trap delivery as done by the xc_hvm_inject_trap() hypercall).
>>>>>
>>>>>
>>>>
>>>> OK then. Acked-by: Kevin Tian <kevin.tian@intel.com>
>>>
>>> AFAIK this has been acked by everyone a while back,
>>
>> Has it? I've meant to apply it the other day, but couldn't find
>> any ARM or AMD SVM maintainer acks.
>
> Oh I see. At one point Julien came into the conversation but it was just
> a friendly discussion about spelling somewhere - I've misremembered that
> as an ack, I now see.

Thank you for reminding me:

Acked-by: Julien Grall <julien.grall@arm.com>

Cheers,
Jan Beulich Dec. 13, 2016, 1:18 p.m. UTC | #10
>>> On 13.12.16 at 09:50, <rcojocaru@bitdefender.com> wrote:
> On 11/17/2016 07:11 AM, Tian, Kevin wrote:
>>> From: Razvan Cojocaru [mailto:rcojocaru@bitdefender.com]
>>> Sent: Wednesday, November 16, 2016 3:49 PM
>>>
>>> On 11/16/2016 09:22 AM, Tian, Kevin wrote:
>>>> Looks not working with APICv virtual interrupt delivery...
>>>
>>> It's only meant to work with "regular" injections (we'd like to be able
>>> to tell if xc_hvm_inject_trap() can succeed). APICv support could be a
>>> later patch, if desirable (AFAICT, the two types shouldn't collide, i.e.
>>> impede trap delivery as done by the xc_hvm_inject_trap() hypercall).
>>>
>>>
>> 
>> OK then. Acked-by: Kevin Tian <kevin.tian@intel.com>
> 
> AFAIK this has been acked by everyone a while back, is further action
> required on my part, or is just low in the patch queue?

Before asking, did you check the patch still applies and builds?
I've taken the time to make it apply, but it really needs more
than that. Please re-base.

Jan
Razvan Cojocaru Dec. 13, 2016, 1:42 p.m. UTC | #11
On 12/13/2016 03:18 PM, Jan Beulich wrote:
>>>> On 13.12.16 at 09:50, <rcojocaru@bitdefender.com> wrote:
>> On 11/17/2016 07:11 AM, Tian, Kevin wrote:
>>>> From: Razvan Cojocaru [mailto:rcojocaru@bitdefender.com]
>>>> Sent: Wednesday, November 16, 2016 3:49 PM
>>>>
>>>> On 11/16/2016 09:22 AM, Tian, Kevin wrote:
>>>>> Looks not working with APICv virtual interrupt delivery...
>>>>
>>>> It's only meant to work with "regular" injections (we'd like to be able
>>>> to tell if xc_hvm_inject_trap() can succeed). APICv support could be a
>>>> later patch, if desirable (AFAICT, the two types shouldn't collide, i.e.
>>>> impede trap delivery as done by the xc_hvm_inject_trap() hypercall).
>>>>
>>>>
>>>
>>> OK then. Acked-by: Kevin Tian <kevin.tian@intel.com>
>>
>> AFAIK this has been acked by everyone a while back, is further action
>> required on my part, or is just low in the patch queue?
> 
> Before asking, did you check the patch still applies and builds?
> I've taken the time to make it apply, but it really needs more
> than that. Please re-base.

I did not. Will check ASAP.


Thanks,
Razvan
Razvan Cojocaru Dec. 13, 2016, 2:17 p.m. UTC | #12
On 12/13/2016 03:18 PM, Jan Beulich wrote:
>>>> On 13.12.16 at 09:50, <rcojocaru@bitdefender.com> wrote:
>> On 11/17/2016 07:11 AM, Tian, Kevin wrote:
>>>> From: Razvan Cojocaru [mailto:rcojocaru@bitdefender.com]
>>>> Sent: Wednesday, November 16, 2016 3:49 PM
>>>>
>>>> On 11/16/2016 09:22 AM, Tian, Kevin wrote:
>>>>> Looks not working with APICv virtual interrupt delivery...
>>>>
>>>> It's only meant to work with "regular" injections (we'd like to be able
>>>> to tell if xc_hvm_inject_trap() can succeed). APICv support could be a
>>>> later patch, if desirable (AFAICT, the two types shouldn't collide, i.e.
>>>> impede trap delivery as done by the xc_hvm_inject_trap() hypercall).
>>>>
>>>>
>>>
>>> OK then. Acked-by: Kevin Tian <kevin.tian@intel.com>
>>
>> AFAIK this has been acked by everyone a while back, is further action
>> required on my part, or is just low in the patch queue?
> 
> Before asking, did you check the patch still applies and builds?
> I've taken the time to make it apply, but it really needs more
> than that. Please re-base.

While re-basing the patch on staging, I've got this (unrelated) error
while doing 'make dist':

make[9]: Entering directory `~/work/xen.git/tools/firmware/rombios/32bit'
gcc   -m32 -march=i686 -DBUILD_ID -g -fno-strict-aliasing -std=gnu99
-Wall -Wstrict-prototypes -Wdeclaration-after-statement
-Wno-unused-but-set-variable -Wno-unused-local-typedefs   -O0 -g3
-fno-omit-frame-pointer
-D__XEN_INTERFACE_VERSION__=__XEN_LATEST_INTERFACE_VERSION__ -MMD -MF
.util.o.d -D_LARGEFILE_SOURCE -D_LARGEFILE64_SOURCE
-mno-tls-direct-seg-refs  -Werror -fno-stack-protector -fno-exceptions
-fno-builtin -msoft-float
-I/home/red/work/xen.git/tools/firmware/rombios/32bit/../../../../tools/include
-I.. -I../../../libacpi  -c -o util.o util.c
util.c: In function ‘get_s3_waking_vector’:
util.c:453:23: error: dereferencing pointer to incomplete type
     if (!fadt || (fadt->header.signature != ACPI_2_0_FADT_SIGNATURE))
                       ^
util.c:453:45: error: ‘ACPI_2_0_FADT_SIGNATURE’ undeclared (first use in
this function)
     if (!fadt || (fadt->header.signature != ACPI_2_0_FADT_SIGNATURE))
                                             ^
util.c:453:45: note: each undeclared identifier is reported only once
for each function it appears in
util.c:456:45: error: dereferencing pointer to incomplete type
     facs = (struct acpi_20_facs *)(long)fadt->x_firmware_ctrl;
                                             ^
make[9]: *** [util.o] Error 1

I'm not where this is best reported, but thought someone might like to know.


Thanks,
Razvan
Jan Beulich Dec. 13, 2016, 2:53 p.m. UTC | #13
>>> On 13.12.16 at 15:17, <rcojocaru@bitdefender.com> wrote:
> While re-basing the patch on staging, I've got this (unrelated) error
> while doing 'make dist':
> 
> make[9]: Entering directory `~/work/xen.git/tools/firmware/rombios/32bit'
> gcc   -m32 -march=i686 -DBUILD_ID -g -fno-strict-aliasing -std=gnu99
> -Wall -Wstrict-prototypes -Wdeclaration-after-statement
> -Wno-unused-but-set-variable -Wno-unused-local-typedefs   -O0 -g3
> -fno-omit-frame-pointer
> -D__XEN_INTERFACE_VERSION__=__XEN_LATEST_INTERFACE_VERSION__ -MMD -MF
> .util.o.d -D_LARGEFILE_SOURCE -D_LARGEFILE64_SOURCE
> -mno-tls-direct-seg-refs  -Werror -fno-stack-protector -fno-exceptions
> -fno-builtin -msoft-float
> -I/home/red/work/xen.git/tools/firmware/rombios/32bit/../../../../tools/inclu
> de
> -I.. -I../../../libacpi  -c -o util.o util.c
> util.c: In function ‘get_s3_waking_vector’:
> util.c:453:23: error: dereferencing pointer to incomplete type
>      if (!fadt || (fadt->header.signature != ACPI_2_0_FADT_SIGNATURE))
>                        ^
> util.c:453:45: error: ‘ACPI_2_0_FADT_SIGNATURE’ undeclared (first use in
> this function)
>      if (!fadt || (fadt->header.signature != ACPI_2_0_FADT_SIGNATURE))
>                                              ^
> util.c:453:45: note: each undeclared identifier is reported only once
> for each function it appears in
> util.c:456:45: error: dereferencing pointer to incomplete type
>      facs = (struct acpi_20_facs *)(long)fadt->x_firmware_ctrl;
>                                              ^
> make[9]: *** [util.o] Error 1

Roger, this indicates you didn't build everything that can be built
with the libacpi changes which went in today. Please indicate
whether you think a fix is easy to put together, or whether to
revert.

Jan
Roger Pau Monné Dec. 13, 2016, 5:15 p.m. UTC | #14
On Tue, Dec 13, 2016 at 07:53:02AM -0700, Jan Beulich wrote:
> >>> On 13.12.16 at 15:17, <rcojocaru@bitdefender.com> wrote:
> > While re-basing the patch on staging, I've got this (unrelated) error
> > while doing 'make dist':
> > 
> > make[9]: Entering directory `~/work/xen.git/tools/firmware/rombios/32bit'
> > gcc   -m32 -march=i686 -DBUILD_ID -g -fno-strict-aliasing -std=gnu99
> > -Wall -Wstrict-prototypes -Wdeclaration-after-statement
> > -Wno-unused-but-set-variable -Wno-unused-local-typedefs   -O0 -g3
> > -fno-omit-frame-pointer
> > -D__XEN_INTERFACE_VERSION__=__XEN_LATEST_INTERFACE_VERSION__ -MMD -MF
> > .util.o.d -D_LARGEFILE_SOURCE -D_LARGEFILE64_SOURCE
> > -mno-tls-direct-seg-refs  -Werror -fno-stack-protector -fno-exceptions
> > -fno-builtin -msoft-float
> > -I/home/red/work/xen.git/tools/firmware/rombios/32bit/../../../../tools/inclu
> > de
> > -I.. -I../../../libacpi  -c -o util.o util.c
> > util.c: In function ‘get_s3_waking_vector’:
> > util.c:453:23: error: dereferencing pointer to incomplete type
> >      if (!fadt || (fadt->header.signature != ACPI_2_0_FADT_SIGNATURE))
> >                        ^
> > util.c:453:45: error: ‘ACPI_2_0_FADT_SIGNATURE’ undeclared (first use in
> > this function)
> >      if (!fadt || (fadt->header.signature != ACPI_2_0_FADT_SIGNATURE))
> >                                              ^
> > util.c:453:45: note: each undeclared identifier is reported only once
> > for each function it appears in
> > util.c:456:45: error: dereferencing pointer to incomplete type
> >      facs = (struct acpi_20_facs *)(long)fadt->x_firmware_ctrl;
> >                                              ^
> > make[9]: *** [util.o] Error 1
> 
> Roger, this indicates you didn't build everything that can be built
> with the libacpi changes which went in today. Please indicate
> whether you think a fix is easy to put together, or whether to
> revert.

Hello,

Sorry, rombios doesn't build on FreeBSD, neither I was expecting libacpi headers 
to leak into it (TBH it looks like a layering violantion). Just send a patch to 
fix the build.

Roger.
diff mbox

Patch

diff --git a/xen/arch/x86/hvm/hvm.c b/xen/arch/x86/hvm/hvm.c
index 704fd64..93af5b8 100644
--- a/xen/arch/x86/hvm/hvm.c
+++ b/xen/arch/x86/hvm/hvm.c
@@ -469,6 +469,12 @@  void hvm_migrate_pirqs(struct vcpu *v)
     spin_unlock(&d->event_lock);
 }
 
+static bool hvm_get_pending_event(struct vcpu *v, struct hvm_trap *info)
+{
+    info->cr2 = v->arch.hvm_vcpu.guest_cr[2];
+    return hvm_funcs.get_pending_event(v, info);
+}
+
 void hvm_do_resume(struct vcpu *v)
 {
     check_wakeup_from_wait();
@@ -535,9 +541,23 @@  void hvm_do_resume(struct vcpu *v)
     /* Inject pending hw/sw trap */
     if ( v->arch.hvm_vcpu.inject_trap.vector != -1 )
     {
-        hvm_inject_trap(&v->arch.hvm_vcpu.inject_trap);
+        if ( !hvm_event_pending(v) )
+            hvm_inject_trap(&v->arch.hvm_vcpu.inject_trap);
+
         v->arch.hvm_vcpu.inject_trap.vector = -1;
     }
+
+    if ( unlikely(v->arch.vm_event) && v->arch.monitor.next_interrupt_enabled )
+    {
+        struct hvm_trap info;
+
+        if ( hvm_get_pending_event(v, &info) )
+        {
+            hvm_monitor_interrupt(info.vector, info.type, info.error_code,
+                                  info.cr2);
+            v->arch.monitor.next_interrupt_enabled = false;
+        }
+    }
 }
 
 static int hvm_print_line(
diff --git a/xen/arch/x86/hvm/monitor.c b/xen/arch/x86/hvm/monitor.c
index 401a8c6..69a88ad 100644
--- a/xen/arch/x86/hvm/monitor.c
+++ b/xen/arch/x86/hvm/monitor.c
@@ -150,6 +150,20 @@  int hvm_monitor_cpuid(unsigned long insn_length, unsigned int leaf,
     return monitor_traps(curr, 1, &req);
 }
 
+void hvm_monitor_interrupt(unsigned int vector, unsigned int type,
+                           unsigned int err, uint64_t cr2)
+{
+    vm_event_request_t req = {
+        .reason = VM_EVENT_REASON_INTERRUPT,
+        .u.interrupt.x86.vector = vector,
+        .u.interrupt.x86.type = type,
+        .u.interrupt.x86.error_code = err,
+        .u.interrupt.x86.cr2 = cr2,
+    };
+
+    monitor_traps(current, 1, &req);
+}
+
 /*
  * Local variables:
  * mode: C
diff --git a/xen/arch/x86/hvm/svm/svm.c b/xen/arch/x86/hvm/svm/svm.c
index c9dbbea..7fe27e4 100644
--- a/xen/arch/x86/hvm/svm/svm.c
+++ b/xen/arch/x86/hvm/svm/svm.c
@@ -2222,6 +2222,20 @@  static void svm_invlpg(struct vcpu *v, unsigned long vaddr)
     svm_asid_g_invlpg(v, vaddr);
 }
 
+static bool svm_get_pending_event(struct vcpu *v, struct hvm_trap *info)
+{
+    const struct vmcb_struct *vmcb = v->arch.hvm_svm.vmcb;
+
+    if ( vmcb->eventinj.fields.v )
+        return false;
+
+    info->vector = vmcb->eventinj.fields.vector;
+    info->type = vmcb->eventinj.fields.type;
+    info->error_code = vmcb->eventinj.fields.errorcode;
+
+    return true;
+}
+
 static struct hvm_function_table __initdata svm_function_table = {
     .name                 = "SVM",
     .cpu_up_prepare       = svm_cpu_up_prepare,
@@ -2252,6 +2266,7 @@  static struct hvm_function_table __initdata svm_function_table = {
     .inject_trap          = svm_inject_trap,
     .init_hypercall_page  = svm_init_hypercall_page,
     .event_pending        = svm_event_pending,
+    .get_pending_event    = svm_get_pending_event,
     .invlpg               = svm_invlpg,
     .cpuid_intercept      = svm_cpuid_intercept,
     .wbinvd_intercept     = svm_wbinvd_intercept,
diff --git a/xen/arch/x86/hvm/vmx/vmx.c b/xen/arch/x86/hvm/vmx/vmx.c
index 9a8f694..961a20b 100644
--- a/xen/arch/x86/hvm/vmx/vmx.c
+++ b/xen/arch/x86/hvm/vmx/vmx.c
@@ -2134,6 +2134,25 @@  static int vmx_set_mode(struct vcpu *v, int mode)
     return 0;
 }
 
+static bool vmx_get_pending_event(struct vcpu *v, struct hvm_trap *info)
+{
+    unsigned long intr_info, error_code;
+
+    vmx_vmcs_enter(v);
+    __vmread(VM_ENTRY_INTR_INFO, &intr_info);
+    __vmread(VM_ENTRY_EXCEPTION_ERROR_CODE, &error_code);
+    vmx_vmcs_exit(v);
+
+    if ( !(intr_info & INTR_INFO_VALID_MASK) )
+        return false;
+
+    info->vector = MASK_EXTR(intr_info, INTR_INFO_VECTOR_MASK);
+    info->type = MASK_EXTR(intr_info, INTR_INFO_INTR_TYPE_MASK);
+    info->error_code = error_code;
+
+    return true;
+}
+
 static struct hvm_function_table __initdata vmx_function_table = {
     .name                 = "VMX",
     .cpu_up_prepare       = vmx_cpu_up_prepare,
@@ -2163,6 +2182,7 @@  static struct hvm_function_table __initdata vmx_function_table = {
     .inject_trap          = vmx_inject_trap,
     .init_hypercall_page  = vmx_init_hypercall_page,
     .event_pending        = vmx_event_pending,
+    .get_pending_event    = vmx_get_pending_event,
     .invlpg               = vmx_invlpg,
     .cpu_up               = vmx_cpu_up,
     .cpu_down             = vmx_cpu_down,
diff --git a/xen/arch/x86/vm_event.c b/xen/arch/x86/vm_event.c
index 1e88d67..e9a689c 100644
--- a/xen/arch/x86/vm_event.c
+++ b/xen/arch/x86/vm_event.c
@@ -134,6 +134,11 @@  void vm_event_set_registers(struct vcpu *v, vm_event_response_t *rsp)
     v->arch.user_regs.eip = rsp->data.regs.x86.rip;
 }
 
+void vm_event_monitor_next_interrupt(struct vcpu *v)
+{
+    v->arch.monitor.next_interrupt_enabled = true;
+}
+
 void vm_event_fill_regs(vm_event_request_t *req)
 {
     const struct cpu_user_regs *regs = guest_cpu_user_regs();
diff --git a/xen/common/vm_event.c b/xen/common/vm_event.c
index 907ab40..c947706 100644
--- a/xen/common/vm_event.c
+++ b/xen/common/vm_event.c
@@ -433,6 +433,9 @@  void vm_event_resume(struct domain *d, struct vm_event_domain *ved)
             if ( rsp.flags & VM_EVENT_FLAG_SET_REGISTERS )
                 vm_event_set_registers(v, &rsp);
 
+            if ( rsp.flags & VM_EVENT_FLAG_GET_NEXT_INTERRUPT )
+                vm_event_monitor_next_interrupt(v);
+
             if ( rsp.flags & VM_EVENT_FLAG_VCPU_PAUSED )
                 vm_event_vcpu_unpause(v);
         }
diff --git a/xen/include/asm-arm/vm_event.h b/xen/include/asm-arm/vm_event.h
index 66f2474..ab9c8cb 100644
--- a/xen/include/asm-arm/vm_event.h
+++ b/xen/include/asm-arm/vm_event.h
@@ -52,4 +52,10 @@  void vm_event_emulate_check(struct vcpu *v, vm_event_response_t *rsp)
     /* Not supported on ARM. */
 }
 
+static inline
+void vm_event_monitor_next_interrupt(struct vcpu *v)
+{
+    /* Not supported on ARM. */
+}
+
 #endif /* __ASM_ARM_VM_EVENT_H__ */
diff --git a/xen/include/asm-x86/domain.h b/xen/include/asm-x86/domain.h
index f6a40eb..4641a49 100644
--- a/xen/include/asm-x86/domain.h
+++ b/xen/include/asm-x86/domain.h
@@ -576,6 +576,10 @@  struct arch_vcpu
     XEN_GUEST_HANDLE(vcpu_time_info_t) time_info_guest;
 
     struct arch_vm_event *vm_event;
+
+    struct {
+        bool next_interrupt_enabled;
+    } monitor;
 };
 
 smap_check_policy_t smap_policy_change(struct vcpu *v,
diff --git a/xen/include/asm-x86/hvm/hvm.h b/xen/include/asm-x86/hvm/hvm.h
index 7e7462e..4cb76b5 100644
--- a/xen/include/asm-x86/hvm/hvm.h
+++ b/xen/include/asm-x86/hvm/hvm.h
@@ -157,6 +157,7 @@  struct hvm_function_table {
     void (*init_hypercall_page)(struct domain *d, void *hypercall_page);
 
     int  (*event_pending)(struct vcpu *v);
+    bool (*get_pending_event)(struct vcpu *v, struct hvm_trap *info);
     void (*invlpg)(struct vcpu *v, unsigned long vaddr);
 
     int  (*cpu_up_prepare)(unsigned int cpu);
diff --git a/xen/include/asm-x86/hvm/monitor.h b/xen/include/asm-x86/hvm/monitor.h
index 82b85ec..85ca678 100644
--- a/xen/include/asm-x86/hvm/monitor.h
+++ b/xen/include/asm-x86/hvm/monitor.h
@@ -42,6 +42,8 @@  int hvm_monitor_debug(unsigned long rip, enum hvm_monitor_debug_type type,
                       unsigned long trap_type, unsigned long insn_length);
 int hvm_monitor_cpuid(unsigned long insn_length, unsigned int leaf,
                       unsigned int subleaf);
+void hvm_monitor_interrupt(unsigned int vector, unsigned int type,
+                           unsigned int err, uint64_t cr2);
 
 #endif /* __ASM_X86_HVM_MONITOR_H__ */
 
diff --git a/xen/include/asm-x86/monitor.h b/xen/include/asm-x86/monitor.h
index 63a994b..e409373 100644
--- a/xen/include/asm-x86/monitor.h
+++ b/xen/include/asm-x86/monitor.h
@@ -76,7 +76,8 @@  static inline uint32_t arch_monitor_get_capabilities(struct domain *d)
                    (1U << XEN_DOMCTL_MONITOR_EVENT_SOFTWARE_BREAKPOINT) |
                    (1U << XEN_DOMCTL_MONITOR_EVENT_GUEST_REQUEST) |
                    (1U << XEN_DOMCTL_MONITOR_EVENT_DEBUG_EXCEPTION) |
-                   (1U << XEN_DOMCTL_MONITOR_EVENT_CPUID);
+                   (1U << XEN_DOMCTL_MONITOR_EVENT_CPUID) |
+                   (1U << XEN_DOMCTL_MONITOR_EVENT_INTERRUPT);
 
     /* Since we know this is on VMX, we can just call the hvm func */
     if ( hvm_is_singlestep_supported() )
diff --git a/xen/include/public/domctl.h b/xen/include/public/domctl.h
index 177319d..85cbb7c 100644
--- a/xen/include/public/domctl.h
+++ b/xen/include/public/domctl.h
@@ -1086,6 +1086,7 @@  DEFINE_XEN_GUEST_HANDLE(xen_domctl_psr_cmt_op_t);
 #define XEN_DOMCTL_MONITOR_EVENT_DEBUG_EXCEPTION       5
 #define XEN_DOMCTL_MONITOR_EVENT_CPUID                 6
 #define XEN_DOMCTL_MONITOR_EVENT_PRIVILEGED_CALL       7
+#define XEN_DOMCTL_MONITOR_EVENT_INTERRUPT             8
 
 struct xen_domctl_monitor_op {
     uint32_t op; /* XEN_DOMCTL_MONITOR_OP_* */
diff --git a/xen/include/public/vm_event.h b/xen/include/public/vm_event.h
index c28be5a..b7487a1 100644
--- a/xen/include/public/vm_event.h
+++ b/xen/include/public/vm_event.h
@@ -105,6 +105,11 @@ 
  * if any of those flags are set, only those will be honored).
  */
 #define VM_EVENT_FLAG_SET_EMUL_INSN_DATA (1 << 9)
+/*
+ * Have a one-shot VM_EVENT_REASON_INTERRUPT event sent for the first
+ * interrupt pending after resuming the VCPU.
+ */
+#define VM_EVENT_FLAG_GET_NEXT_INTERRUPT (1 << 10)
 
 /*
  * Reasons for the vm event request
@@ -139,6 +144,8 @@ 
  *       These kinds of events will be filtered out in future versions.
  */
 #define VM_EVENT_REASON_PRIVILEGED_CALL         11
+/* An interrupt has been delivered. */
+#define VM_EVENT_REASON_INTERRUPT               12
 
 /* Supported values for the vm_event_write_ctrlreg index. */
 #define VM_EVENT_X86_CR0    0
@@ -259,6 +266,14 @@  struct vm_event_cpuid {
     uint32_t _pad;
 };
 
+struct vm_event_interrupt_x86 {
+    uint32_t vector;
+    uint32_t type;
+    uint32_t error_code;
+    uint32_t _pad;
+    uint64_t cr2;
+};
+
 #define MEM_PAGING_DROP_PAGE       (1 << 0)
 #define MEM_PAGING_EVICT_FAIL      (1 << 1)
 
@@ -302,6 +317,9 @@  typedef struct vm_event_st {
         struct vm_event_debug                 software_breakpoint;
         struct vm_event_debug                 debug_exception;
         struct vm_event_cpuid                 cpuid;
+        union {
+            struct vm_event_interrupt_x86     x86;
+        } interrupt;
     } u;
 
     union {
diff --git a/xen/include/xen/vm_event.h b/xen/include/xen/vm_event.h
index 4f088c8..2fb3951 100644
--- a/xen/include/xen/vm_event.h
+++ b/xen/include/xen/vm_event.h
@@ -78,6 +78,8 @@  void vm_event_vcpu_unpause(struct vcpu *v);
 void vm_event_fill_regs(vm_event_request_t *req);
 void vm_event_set_registers(struct vcpu *v, vm_event_response_t *rsp);
 
+void vm_event_monitor_next_interrupt(struct vcpu *v);
+
 #endif /* __VM_EVENT_H__ */
 
 /*