diff mbox

[11/16] x86/monitor: fix: treat -monitor- properly, as a subsys of the vm-event subsys

Message ID 1468038011-6935-1-git-send-email-czuzu@bitdefender.com (mailing list archive)
State New, archived
Headers show

Commit Message

Corneliu ZUZU July 9, 2016, 4:20 a.m. UTC
As it can be seen looking @ the vm_event_per_domain structure, there are 3
defined vm-event subsystems: share, paging and monitor. In a number of places in
the codebase, the monitor vm-events subsystem is mistakenly confounded with the
vm-event subsystem as a whole: i.e. it is wrongfully checked if v->arch.vm_event
is allocated to determine if the monitor subsystem is initialized.

To fix that, add an 'initialised' bit in d->monitor which will determine if the
monitor subsystem is initialised, create an inline stub
monitor_domain_initialised() and use that instead where it applies.

Signed-off-by: Corneliu ZUZU <czuzu@bitdefender.com>
---
 xen/arch/x86/hvm/emulate.c    |  3 ++-
 xen/arch/x86/hvm/hvm.c        | 10 +++++-----
 xen/arch/x86/monitor.c        |  3 +++
 xen/include/asm-arm/monitor.h |  3 ++-
 xen/include/asm-x86/monitor.h |  9 ++++-----
 xen/include/xen/monitor.h     | 11 +++++++----
 xen/include/xen/sched.h       |  1 +
 7 files changed, 24 insertions(+), 16 deletions(-)

Comments

Tamas K Lengyel July 9, 2016, 5:34 p.m. UTC | #1
> diff --git a/xen/arch/x86/monitor.c b/xen/arch/x86/monitor.c
> index aeee435..4a29cad 100644
> --- a/xen/arch/x86/monitor.c
> +++ b/xen/arch/x86/monitor.c
> @@ -62,6 +62,8 @@ int monitor_init_domain(struct domain *d)
>              return -ENOMEM;
>      }
>
> +    d->monitor.initialised = 1;
> +
>      return 0;
>  }
>
> @@ -78,6 +80,7 @@ void monitor_cleanup_domain(struct domain *d)
>
>      memset(&d->arch.monitor, 0, sizeof(d->arch.monitor));
>      memset(&d->monitor, 0, sizeof(d->monitor));
> +    d->monitor.initialised = 0;

So d->monitor is already memset to zero above, thus this is not needed here.

>  }
>
>  void monitor_ctrlreg_write_resume(struct vcpu *v, vm_event_response_t *rsp)
> diff --git a/xen/include/asm-arm/monitor.h b/xen/include/asm-arm/monitor.h
> index 9a9734a..7ef30f1 100644

[snip]

> diff --git a/xen/include/xen/monitor.h b/xen/include/xen/monitor.h
> index 2171d04..605caf0 100644
> --- a/xen/include/xen/monitor.h
> +++ b/xen/include/xen/monitor.h
> @@ -22,12 +22,15 @@
>  #ifndef __XEN_MONITOR_H__
>  #define __XEN_MONITOR_H__
>
> -#include <public/vm_event.h>
> -
> -struct domain;
> -struct xen_domctl_monitor_op;
> +#include <xen/sched.h>
>
>  int monitor_domctl(struct domain *d, struct xen_domctl_monitor_op *op);
> +
> +static inline bool_t monitor_domain_initialised(const struct domain *d)
> +{
> +    return d->monitor.initialised;

This should be !!d->monitor.initialised.

> +}
> +
>  void monitor_guest_request(void);
>
>  int monitor_traps(struct vcpu *v, bool_t sync, vm_event_request_t *req);

Cheers,
Tamas
Corneliu ZUZU July 9, 2016, 5:46 p.m. UTC | #2
On 7/9/2016 8:34 PM, Tamas K Lengyel wrote:
>> diff --git a/xen/arch/x86/monitor.c b/xen/arch/x86/monitor.c
>> index aeee435..4a29cad 100644
>> --- a/xen/arch/x86/monitor.c
>> +++ b/xen/arch/x86/monitor.c
>> @@ -62,6 +62,8 @@ int monitor_init_domain(struct domain *d)
>>               return -ENOMEM;
>>       }
>>
>> +    d->monitor.initialised = 1;
>> +
>>       return 0;
>>   }
>>
>> @@ -78,6 +80,7 @@ void monitor_cleanup_domain(struct domain *d)
>>
>>       memset(&d->arch.monitor, 0, sizeof(d->arch.monitor));
>>       memset(&d->monitor, 0, sizeof(d->monitor));
>> +    d->monitor.initialised = 0;
> So d->monitor is already memset to zero above, thus this is not needed here.

Yep.

>
>>   }
>>
>>   void monitor_ctrlreg_write_resume(struct vcpu *v, vm_event_response_t *rsp)
>> diff --git a/xen/include/asm-arm/monitor.h b/xen/include/asm-arm/monitor.h
>> index 9a9734a..7ef30f1 100644
> [snip]

I keep seeing '[snip]' lately but I don't know what it means.

>
>> diff --git a/xen/include/xen/monitor.h b/xen/include/xen/monitor.h
>> index 2171d04..605caf0 100644
>> --- a/xen/include/xen/monitor.h
>> +++ b/xen/include/xen/monitor.h
>> @@ -22,12 +22,15 @@
>>   #ifndef __XEN_MONITOR_H__
>>   #define __XEN_MONITOR_H__
>>
>> -#include <public/vm_event.h>
>> -
>> -struct domain;
>> -struct xen_domctl_monitor_op;
>> +#include <xen/sched.h>
>>
>>   int monitor_domctl(struct domain *d, struct xen_domctl_monitor_op *op);
>> +
>> +static inline bool_t monitor_domain_initialised(const struct domain *d)
>> +{
>> +    return d->monitor.initialised;
> This should be !!d->monitor.initialised.

It's the value of a bit, thus should be 0 or 1. Am I missing something?

>
>> +}
>> +
>>   void monitor_guest_request(void);
>>
>>   int monitor_traps(struct vcpu *v, bool_t sync, vm_event_request_t *req);
> Cheers,
> Tamas
>

Thanks,
Zuzu.
Tamas K Lengyel July 11, 2016, 4:38 p.m. UTC | #3
>>> diff --git a/xen/include/asm-arm/monitor.h
>>> b/xen/include/asm-arm/monitor.h
>>> index 9a9734a..7ef30f1 100644
>>
>> [snip]
>
>
> I keep seeing '[snip]' lately but I don't know what it means.

Placeholder for "I've cut some of your patch content here to shorten
the message I'm sending".

>
>>
>>> diff --git a/xen/include/xen/monitor.h b/xen/include/xen/monitor.h
>>> index 2171d04..605caf0 100644
>>> --- a/xen/include/xen/monitor.h
>>> +++ b/xen/include/xen/monitor.h
>>> @@ -22,12 +22,15 @@
>>>   #ifndef __XEN_MONITOR_H__
>>>   #define __XEN_MONITOR_H__
>>>
>>> -#include <public/vm_event.h>
>>> -
>>> -struct domain;
>>> -struct xen_domctl_monitor_op;
>>> +#include <xen/sched.h>
>>>
>>>   int monitor_domctl(struct domain *d, struct xen_domctl_monitor_op *op);
>>> +
>>> +static inline bool_t monitor_domain_initialised(const struct domain *d)
>>> +{
>>> +    return d->monitor.initialised;
>>
>> This should be !!d->monitor.initialised.
>
>
> It's the value of a bit, thus should be 0 or 1. Am I missing something?

Using a bitfield is effectively doing a bitmask for the bit(s).
However, returning the value after applying a bitmask is not
necessarily 0/1 (ie. bool_t). For example I ran into problems with
this in the past (see
https://lists.xen.org/archives/html/xen-devel/2015-08/msg01948.html).

Tamas
Corneliu ZUZU July 11, 2016, 8:20 p.m. UTC | #4
On 7/11/2016 7:38 PM, Tamas K Lengyel wrote:
>>>> diff --git a/xen/include/asm-arm/monitor.h
>>>> b/xen/include/asm-arm/monitor.h
>>>> index 9a9734a..7ef30f1 100644
>>> [snip]
>>
>> I keep seeing '[snip]' lately but I don't know what it means.
> Placeholder for "I've cut some of your patch content here to shorten
> the message I'm sending".
>
>>>> diff --git a/xen/include/xen/monitor.h b/xen/include/xen/monitor.h
>>>> index 2171d04..605caf0 100644
>>>> --- a/xen/include/xen/monitor.h
>>>> +++ b/xen/include/xen/monitor.h
>>>> @@ -22,12 +22,15 @@
>>>>    #ifndef __XEN_MONITOR_H__
>>>>    #define __XEN_MONITOR_H__
>>>>
>>>> -#include <public/vm_event.h>
>>>> -
>>>> -struct domain;
>>>> -struct xen_domctl_monitor_op;
>>>> +#include <xen/sched.h>
>>>>
>>>>    int monitor_domctl(struct domain *d, struct xen_domctl_monitor_op *op);
>>>> +
>>>> +static inline bool_t monitor_domain_initialised(const struct domain *d)
>>>> +{
>>>> +    return d->monitor.initialised;
>>> This should be !!d->monitor.initialised.
>>
>> It's the value of a bit, thus should be 0 or 1. Am I missing something?
> Using a bitfield is effectively doing a bitmask for the bit(s).
> However, returning the value after applying a bitmask is not
> necessarily 0/1 (ie. bool_t). For example I ran into problems with
> this in the past (see
> https://lists.xen.org/archives/html/xen-devel/2015-08/msg01948.html).
>
> Tamas

The example you provided actually returns a value &-ed with a flag 
(bitmask), of course it returns either 0 or the flag itself :-). AFAIK a 
single-bit item in a bitfield (note a -bitfield-, not e.g. an unsigned 
int &-ed with (1<<x)) will always be either 0 or 1.

Corneliu.
Tamas K Lengyel July 11, 2016, 9:27 p.m. UTC | #5
On Mon, Jul 11, 2016 at 2:20 PM, Corneliu ZUZU <czuzu@bitdefender.com> wrote:
> On 7/11/2016 7:38 PM, Tamas K Lengyel wrote:
>>>>>
>>>>> diff --git a/xen/include/asm-arm/monitor.h
>>>>> b/xen/include/asm-arm/monitor.h
>>>>> index 9a9734a..7ef30f1 100644
>>>>
>>>> [snip]
>>>
>>>
>>> I keep seeing '[snip]' lately but I don't know what it means.
>>
>> Placeholder for "I've cut some of your patch content here to shorten
>> the message I'm sending".
>>
>>>>> diff --git a/xen/include/xen/monitor.h b/xen/include/xen/monitor.h
>>>>> index 2171d04..605caf0 100644
>>>>> --- a/xen/include/xen/monitor.h
>>>>> +++ b/xen/include/xen/monitor.h
>>>>> @@ -22,12 +22,15 @@
>>>>>    #ifndef __XEN_MONITOR_H__
>>>>>    #define __XEN_MONITOR_H__
>>>>>
>>>>> -#include <public/vm_event.h>
>>>>> -
>>>>> -struct domain;
>>>>> -struct xen_domctl_monitor_op;
>>>>> +#include <xen/sched.h>
>>>>>
>>>>>    int monitor_domctl(struct domain *d, struct xen_domctl_monitor_op
>>>>> *op);
>>>>> +
>>>>> +static inline bool_t monitor_domain_initialised(const struct domain
>>>>> *d)
>>>>> +{
>>>>> +    return d->monitor.initialised;
>>>>
>>>> This should be !!d->monitor.initialised.
>>>
>>>
>>> It's the value of a bit, thus should be 0 or 1. Am I missing something?
>>
>> Using a bitfield is effectively doing a bitmask for the bit(s).
>> However, returning the value after applying a bitmask is not
>> necessarily 0/1 (ie. bool_t). For example I ran into problems with
>> this in the past (see
>> https://lists.xen.org/archives/html/xen-devel/2015-08/msg01948.html).
>>
>> Tamas
>
>
> The example you provided actually returns a value &-ed with a flag
> (bitmask), of course it returns either 0 or the flag itself :-). AFAIK a
> single-bit item in a bitfield (note a -bitfield-, not e.g. an unsigned int
> &-ed with (1<<x)) will always be either 0 or 1.
>

I would assume as well but I'm not actually sure if that's guaranteed
or if it's only compiler defined behavior.

Tamas
Corneliu ZUZU July 11, 2016, 9:47 p.m. UTC | #6
On 7/12/2016 12:27 AM, Tamas K Lengyel wrote:
> On Mon, Jul 11, 2016 at 2:20 PM, Corneliu ZUZU <czuzu@bitdefender.com> wrote:
>> On 7/11/2016 7:38 PM, Tamas K Lengyel wrote:
>>>>>> diff --git a/xen/include/asm-arm/monitor.h
>>>>>> b/xen/include/asm-arm/monitor.h
>>>>>> index 9a9734a..7ef30f1 100644
>>>>> [snip]
>>>>
>>>> I keep seeing '[snip]' lately but I don't know what it means.
>>> Placeholder for "I've cut some of your patch content here to shorten
>>> the message I'm sending".
>>>
>>>>>> diff --git a/xen/include/xen/monitor.h b/xen/include/xen/monitor.h
>>>>>> index 2171d04..605caf0 100644
>>>>>> --- a/xen/include/xen/monitor.h
>>>>>> +++ b/xen/include/xen/monitor.h
>>>>>> @@ -22,12 +22,15 @@
>>>>>>     #ifndef __XEN_MONITOR_H__
>>>>>>     #define __XEN_MONITOR_H__
>>>>>>
>>>>>> -#include <public/vm_event.h>
>>>>>> -
>>>>>> -struct domain;
>>>>>> -struct xen_domctl_monitor_op;
>>>>>> +#include <xen/sched.h>
>>>>>>
>>>>>>     int monitor_domctl(struct domain *d, struct xen_domctl_monitor_op
>>>>>> *op);
>>>>>> +
>>>>>> +static inline bool_t monitor_domain_initialised(const struct domain
>>>>>> *d)
>>>>>> +{
>>>>>> +    return d->monitor.initialised;
>>>>> This should be !!d->monitor.initialised.
>>>>
>>>> It's the value of a bit, thus should be 0 or 1. Am I missing something?
>>> Using a bitfield is effectively doing a bitmask for the bit(s).
>>> However, returning the value after applying a bitmask is not
>>> necessarily 0/1 (ie. bool_t). For example I ran into problems with
>>> this in the past (see
>>> https://lists.xen.org/archives/html/xen-devel/2015-08/msg01948.html).
>>>
>>> Tamas
>>
>> The example you provided actually returns a value &-ed with a flag
>> (bitmask), of course it returns either 0 or the flag itself :-). AFAIK a
>> single-bit item in a bitfield (note a -bitfield-, not e.g. an unsigned int
>> &-ed with (1<<x)) will always be either 0 or 1.
>>
> I would assume as well but I'm not actually sure if that's guaranteed
> or if it's only compiler defined behavior.
>
> Tamas
>

As per http://en.cppreference.com/w/c/language/bit_field .

"The number of bits in a bit field (width) sets the limit to the range 
of values it can hold"

So if it's width is 1, it can either be 0 or 1.

Corneliu.
diff mbox

Patch

diff --git a/xen/arch/x86/hvm/emulate.c b/xen/arch/x86/hvm/emulate.c
index 855af4d..a0094e9 100644
--- a/xen/arch/x86/hvm/emulate.c
+++ b/xen/arch/x86/hvm/emulate.c
@@ -12,6 +12,7 @@ 
 #include <xen/config.h>
 #include <xen/init.h>
 #include <xen/lib.h>
+#include <xen/monitor.h>
 #include <xen/sched.h>
 #include <xen/paging.h>
 #include <xen/trace.h>
@@ -73,7 +74,7 @@  static int set_context_data(void *buffer, unsigned int size)
 {
     struct vcpu *curr = current;
 
-    if ( curr->arch.vm_event )
+    if ( unlikely(monitor_domain_initialised(curr->domain)) )
     {
         unsigned int safe_size =
             min(size, curr->arch.vm_event->emul_read_data.size);
diff --git a/xen/arch/x86/hvm/hvm.c b/xen/arch/x86/hvm/hvm.c
index 79ba185..46fed33 100644
--- a/xen/arch/x86/hvm/hvm.c
+++ b/xen/arch/x86/hvm/hvm.c
@@ -471,7 +471,7 @@  void hvm_do_resume(struct vcpu *v)
     if ( !handle_hvm_io_completion(v) )
         return;
 
-    if ( unlikely(v->arch.vm_event) )
+    if ( unlikely(monitor_domain_initialised(v->domain)) )
     {
         if ( unlikely(v->arch.vm_event->emulate_flags) )
         {
@@ -2176,7 +2176,7 @@  int hvm_set_cr0(unsigned long value, bool_t may_defer)
     if ( may_defer && unlikely(v->domain->arch.monitor.write_ctrlreg_enabled &
                                monitor_ctrlreg_bitmask(VM_EVENT_X86_CR0)) )
     {
-        ASSERT(v->arch.vm_event);
+        ASSERT(monitor_domain_initialised(v->domain));
 
         if ( hvm_monitor_crX(CR0, value, old_value) )
         {
@@ -2281,7 +2281,7 @@  int hvm_set_cr3(unsigned long value, bool_t may_defer)
     if ( may_defer && unlikely(v->domain->arch.monitor.write_ctrlreg_enabled &
                                monitor_ctrlreg_bitmask(VM_EVENT_X86_CR3)) )
     {
-        ASSERT(v->arch.vm_event);
+        ASSERT(monitor_domain_initialised(v->domain));
 
         if ( hvm_monitor_crX(CR3, value, old) )
         {
@@ -2364,7 +2364,7 @@  int hvm_set_cr4(unsigned long value, bool_t may_defer)
     if ( may_defer && unlikely(v->domain->arch.monitor.write_ctrlreg_enabled &
                                monitor_ctrlreg_bitmask(VM_EVENT_X86_CR4)) )
     {
-        ASSERT(v->arch.vm_event);
+        ASSERT(monitor_domain_initialised(v->domain));
 
         if ( hvm_monitor_crX(CR4, value, old_cr) )
         {
@@ -3748,7 +3748,7 @@  int hvm_msr_write_intercept(unsigned int msr, uint64_t msr_content,
 
     if ( may_defer && unlikely(monitored_msr(v->domain, msr)) )
     {
-        ASSERT(v->arch.vm_event);
+        ASSERT(monitor_domain_initialised(v->domain));
 
         /*
          * The actual write will occur in monitor_ctrlreg_write_data(), if
diff --git a/xen/arch/x86/monitor.c b/xen/arch/x86/monitor.c
index aeee435..4a29cad 100644
--- a/xen/arch/x86/monitor.c
+++ b/xen/arch/x86/monitor.c
@@ -62,6 +62,8 @@  int monitor_init_domain(struct domain *d)
             return -ENOMEM;
     }
 
+    d->monitor.initialised = 1;
+
     return 0;
 }
 
@@ -78,6 +80,7 @@  void monitor_cleanup_domain(struct domain *d)
 
     memset(&d->arch.monitor, 0, sizeof(d->arch.monitor));
     memset(&d->monitor, 0, sizeof(d->monitor));
+    d->monitor.initialised = 0;
 }
 
 void monitor_ctrlreg_write_resume(struct vcpu *v, vm_event_response_t *rsp)
diff --git a/xen/include/asm-arm/monitor.h b/xen/include/asm-arm/monitor.h
index 9a9734a..7ef30f1 100644
--- a/xen/include/asm-arm/monitor.h
+++ b/xen/include/asm-arm/monitor.h
@@ -48,13 +48,14 @@  int arch_monitor_domctl_event(struct domain *d,
 
 static inline int monitor_init_domain(struct domain *d)
 {
-    /* No arch-specific domain initialization on ARM. */
+    d->monitor.initialised = 1;
     return 0;
 }
 
 static inline void monitor_cleanup_domain(struct domain *d)
 {
     memset(&d->monitor, 0, sizeof(d->monitor));
+    d->monitor.initialised = 0;
 }
 
 static inline
diff --git a/xen/include/asm-x86/monitor.h b/xen/include/asm-x86/monitor.h
index 3ae24dd..4014f8d 100644
--- a/xen/include/asm-x86/monitor.h
+++ b/xen/include/asm-x86/monitor.h
@@ -22,6 +22,7 @@ 
 #ifndef __ASM_X86_MONITOR_H__
 #define __ASM_X86_MONITOR_H__
 
+#include <xen/monitor.h>
 #include <xen/sched.h>
 
 #define monitor_ctrlreg_bitmask(ctrlreg_index) (1U << (ctrlreg_index))
@@ -41,11 +42,9 @@  int arch_monitor_domctl_op(struct domain *d, struct xen_domctl_monitor_op *mop)
     {
     case XEN_DOMCTL_MONITOR_OP_EMULATE_EACH_REP:
         domain_pause(d);
-        /*
-         * Enabling mem_access_emulate_each_rep without a vm_event subscriber
-         * is meaningless.
-         */
-        if ( d->max_vcpus && d->vcpu[0] && d->vcpu[0]->arch.vm_event )
+
+        /* Meaningless without a monitor vm-events subscriber. */
+        if ( likely(monitor_domain_initialised(d)) )
             d->arch.mem_access_emulate_each_rep = !!mop->event;
         else
             rc = -EINVAL;
diff --git a/xen/include/xen/monitor.h b/xen/include/xen/monitor.h
index 2171d04..605caf0 100644
--- a/xen/include/xen/monitor.h
+++ b/xen/include/xen/monitor.h
@@ -22,12 +22,15 @@ 
 #ifndef __XEN_MONITOR_H__
 #define __XEN_MONITOR_H__
 
-#include <public/vm_event.h>
-
-struct domain;
-struct xen_domctl_monitor_op;
+#include <xen/sched.h>
 
 int monitor_domctl(struct domain *d, struct xen_domctl_monitor_op *op);
+
+static inline bool_t monitor_domain_initialised(const struct domain *d)
+{
+    return d->monitor.initialised;
+}
+
 void monitor_guest_request(void);
 
 int monitor_traps(struct vcpu *v, bool_t sync, vm_event_request_t *req);
diff --git a/xen/include/xen/sched.h b/xen/include/xen/sched.h
index 46c82e7..e6bd13f 100644
--- a/xen/include/xen/sched.h
+++ b/xen/include/xen/sched.h
@@ -472,6 +472,7 @@  struct domain
     struct {
         unsigned int guest_request_enabled       : 1;
         unsigned int guest_request_sync          : 1;
+        unsigned int initialised                 : 1;
     } monitor;
 };