xen-devel.lists.xenproject.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 0/3] irqsave/restore improvements
@ 2013-10-21 13:41 Andrew Cooper
  2013-10-21 13:41 ` [PATCH 1/3] x86/irq: local_irq_restore() should not blindly popf Andrew Cooper
                   ` (3 more replies)
  0 siblings, 4 replies; 21+ messages in thread
From: Andrew Cooper @ 2013-10-21 13:41 UTC (permalink / raw)
  To: Xen-devel
  Cc: Keir Fraser, Ian Campbell, George Dunlap, Andrew Cooper,
	Tim Deegan, Stefano Stabellini, Jan Beulich

This series contains two independent but related fixes to do with
irqsave/restore semantics.

The first patch prevents local_irq_restore() from corrupting system flags.

The second was constructed using the compile errors from the third patch,
separated for clarity and reordered to prevent bisection problems.

The third patch uses a BUILD_BUG_ON() to ensure that the flags parameter to
spin_lock_irqsave is wide enough to not trucate the result from
local_irq_save().

I have not compile tested on arm, so request that one of the maintainers
explicitly acks the final patch.  Any compile failures will almost certainly
be fixed with an int->unsigned long conversion on the affected variable(s).

Signed-off-by: Andrew Cooper <andrew.cooper3@citrix.com>
CC: Keir Fraser <keir@xen.org>
CC: Jan Beulich <JBeulich@suse.com>
CC: Ian Campbell <ian.campbell@citrix.com>
CC: Stefano Stabellini <stefano.stabellini@citrix.com>
CC: Tim Deegan <tim@xen.org>
CC: George Dunlap <george.dunlap@eu.citrix.com>

--
1.7.10.4

^ permalink raw reply	[flat|nested] 21+ messages in thread

* [PATCH 1/3] x86/irq: local_irq_restore() should not blindly popf
  2013-10-21 13:41 [PATCH 0/3] irqsave/restore improvements Andrew Cooper
@ 2013-10-21 13:41 ` Andrew Cooper
  2013-10-21 13:58   ` David Vrabel
  2013-10-21 14:42   ` Jan Beulich
  2013-10-21 13:41 ` [PATCH 2/3] xen: Widen flags parameter for spinlock_irqsave() and friends Andrew Cooper
                   ` (2 subsequent siblings)
  3 siblings, 2 replies; 21+ messages in thread
From: Andrew Cooper @ 2013-10-21 13:41 UTC (permalink / raw)
  To: Xen-devel; +Cc: Andrew Cooper, Keir Fraser, Jan Beulich

local_irq_restore() should only be concerned with possibly changing the
interrupt flag.  A blind popf could corrupt other system flags.

Signed-off-by: Andrew Cooper <andrew.cooper3@citrix.com>
CC: Keir Fraser <keir@xen.org>
CC: Jan Beulich <JBeulich@suse.com>
---
 xen/include/asm-x86/system.h |    6 ++++--
 1 file changed, 4 insertions(+), 2 deletions(-)

diff --git a/xen/include/asm-x86/system.h b/xen/include/asm-x86/system.h
index 6ab7d56..cbf0f6a 100644
--- a/xen/include/asm-x86/system.h
+++ b/xen/include/asm-x86/system.h
@@ -159,8 +159,10 @@ static always_inline unsigned long __cmpxchg(
 #define local_irq_restore(x)                                     \
 ({                                                               \
     BUILD_BUG_ON(sizeof(x) != sizeof(long));                     \
-    asm volatile ( "push" __OS " %0 ; popf" __OS                 \
-                   : : "g" (x) : "memory", "cc" );               \
+    if ( x & X86_EFLAGS_IF )                                     \
+        local_irq_enable();                                      \
+    else                                                         \
+        local_irq_disable();                                     \
 })
 
 static inline int local_irq_is_enabled(void)
-- 
1.7.10.4

^ permalink raw reply related	[flat|nested] 21+ messages in thread

* [PATCH 2/3] xen: Widen flags parameter for spinlock_irqsave() and friends
  2013-10-21 13:41 [PATCH 0/3] irqsave/restore improvements Andrew Cooper
  2013-10-21 13:41 ` [PATCH 1/3] x86/irq: local_irq_restore() should not blindly popf Andrew Cooper
@ 2013-10-21 13:41 ` Andrew Cooper
  2013-10-21 13:41 ` [PATCH 3/3] common/spinlock: Ensure the flags parameter is wide enough Andrew Cooper
  2013-10-21 14:08 ` [PATCH 0/3] irqsave/restore improvements Keir Fraser
  3 siblings, 0 replies; 21+ messages in thread
From: Andrew Cooper @ 2013-10-21 13:41 UTC (permalink / raw)
  To: Xen-devel; +Cc: George Dunlap, Andrew Cooper, Keir Fraser, Jan Beulich

These issues were detected using the subsequent patch which forces a
compilation error if the result from local_irq_save() would be truncated.

Signed-off-by: Andrew Cooper <andrew.cooper3@citrix.com>
CC: Keir Fraser <keir@xen.org>
CC: Jan Beulich <JBeulich@suse.com>
CC: George Dunlap <george.dunlap@eu.citrix.com>
---
 xen/common/sched_credit2.c |    7 ++++---
 xen/common/trace.c         |    2 +-
 2 files changed, 5 insertions(+), 4 deletions(-)

diff --git a/xen/common/sched_credit2.c b/xen/common/sched_credit2.c
index 84e547b..4e68375 100644
--- a/xen/common/sched_credit2.c
+++ b/xen/common/sched_credit2.c
@@ -1480,7 +1480,7 @@ static void *
 csched_alloc_domdata(const struct scheduler *ops, struct domain *dom)
 {
     struct csched_dom *sdom;
-    int flags;
+    unsigned long flags;
 
     sdom = xzalloc(struct csched_dom);
     if ( sdom == NULL )
@@ -1524,7 +1524,7 @@ csched_dom_init(const struct scheduler *ops, struct domain *dom)
 static void
 csched_free_domdata(const struct scheduler *ops, void *data)
 {
-    int flags;
+    unsigned long flags;
     struct csched_dom *sdom = data;
 
     spin_lock_irqsave(&CSCHED_PRIV(ops)->lock, flags);
@@ -1944,7 +1944,8 @@ static void deactivate_runqueue(struct csched_private *prv, int rqi)
 
 static void init_pcpu(const struct scheduler *ops, int cpu)
 {
-    int rqi, flags;
+    int rqi;
+    unsigned long flags;
     struct csched_private *prv = CSCHED_PRIV(ops);
     struct csched_runqueue_data *rqd;
     spinlock_t *old_lock;
diff --git a/xen/common/trace.c b/xen/common/trace.c
index 63ea0b7..41ddc33 100644
--- a/xen/common/trace.c
+++ b/xen/common/trace.c
@@ -420,7 +420,7 @@ int tb_control(xen_sysctl_tbuf_op_t *tbc)
          * hypercall returns, no more records should be placed into the buffers. */
         for_each_online_cpu(i)
         {
-            int flags;
+            unsigned long flags;
             spin_lock_irqsave(&per_cpu(t_lock, i), flags);
             per_cpu(lost_records, i)=0;
             spin_unlock_irqrestore(&per_cpu(t_lock, i), flags);
-- 
1.7.10.4

^ permalink raw reply related	[flat|nested] 21+ messages in thread

* [PATCH 3/3] common/spinlock: Ensure the flags parameter is wide enough
  2013-10-21 13:41 [PATCH 0/3] irqsave/restore improvements Andrew Cooper
  2013-10-21 13:41 ` [PATCH 1/3] x86/irq: local_irq_restore() should not blindly popf Andrew Cooper
  2013-10-21 13:41 ` [PATCH 2/3] xen: Widen flags parameter for spinlock_irqsave() and friends Andrew Cooper
@ 2013-10-21 13:41 ` Andrew Cooper
  2013-10-21 15:15   ` Ian Campbell
  2013-10-21 14:08 ` [PATCH 0/3] irqsave/restore improvements Keir Fraser
  3 siblings, 1 reply; 21+ messages in thread
From: Andrew Cooper @ 2013-10-21 13:41 UTC (permalink / raw)
  To: Xen-devel
  Cc: Keir Fraser, Ian Campbell, Andrew Cooper, Tim Deegan,
	Stefano Stabellini, Jan Beulich

Because of the construction of spin_lock_irq() (and varients), the flags
parameter could be trucated.  Use a BUILD_BUG_ON() to verify the width of the
parameter.

Signed-off-by: Andrew Cooper <andrew.cooper3@citrix.com>
CC: Keir Fraser <keir@xen.org>
CC: Jan Beulich <JBeulich@suse.com>
CC: Ian Campbell <ian.campbell@citrix.com>
CC: Stefano Stabellini <stefano.stabellini@citrix.com>
CC: Tim Deegan <tim@xen.org>

---

The previous patch in the series fixes the compilation issues I found as a
result of this patch, but I have not tested on arm.  I therefore request an
explicit ack from an arm maintainer before this is committed.
---
 xen/include/xen/spinlock.h |   18 +++++++++++++++---
 1 file changed, 15 insertions(+), 3 deletions(-)

diff --git a/xen/include/xen/spinlock.h b/xen/include/xen/spinlock.h
index 76581c5..12b0a89 100644
--- a/xen/include/xen/spinlock.h
+++ b/xen/include/xen/spinlock.h
@@ -188,7 +188,11 @@ int _rw_is_write_locked(rwlock_t *lock);
 
 #define spin_lock(l)                  _spin_lock(l)
 #define spin_lock_irq(l)              _spin_lock_irq(l)
-#define spin_lock_irqsave(l, f)       ((f) = _spin_lock_irqsave(l))
+#define spin_lock_irqsave(l, f)                                 \
+    ({                                                          \
+        BUILD_BUG_ON(sizeof(f) != sizeof(unsigned long));       \
+        ((f) = _spin_lock_irqsave(l));                          \
+    })
 
 #define spin_unlock(l)                _spin_unlock(l)
 #define spin_unlock_irq(l)            _spin_unlock_irq(l)
@@ -220,7 +224,11 @@ int _rw_is_write_locked(rwlock_t *lock);
 
 #define read_lock(l)                  _read_lock(l)
 #define read_lock_irq(l)              _read_lock_irq(l)
-#define read_lock_irqsave(l, f)       ((f) = _read_lock_irqsave(l))
+#define read_lock_irqsave(l, f)                                 \
+    ({                                                          \
+        BUILD_BUG_ON(sizeof(f) != sizeof(unsigned long));       \
+        ((f) = _read_lock_irqsave(l));                          \
+    })
 
 #define read_unlock(l)                _read_unlock(l)
 #define read_unlock_irq(l)            _read_unlock_irq(l)
@@ -229,7 +237,11 @@ int _rw_is_write_locked(rwlock_t *lock);
 
 #define write_lock(l)                 _write_lock(l)
 #define write_lock_irq(l)             _write_lock_irq(l)
-#define write_lock_irqsave(l, f)      ((f) = _write_lock_irqsave(l))
+#define write_lock_irqsave(l, f)                                \
+    ({                                                          \
+        BUILD_BUG_ON(sizeof(f) != sizeof(unsigned long));       \
+        ((f) = _write_lock_irqsave(l));                         \
+    })
 #define write_trylock(l)              _write_trylock(l)
 
 #define write_unlock(l)               _write_unlock(l)
-- 
1.7.10.4

^ permalink raw reply related	[flat|nested] 21+ messages in thread

* Re: [PATCH 1/3] x86/irq: local_irq_restore() should not blindly popf
  2013-10-21 13:41 ` [PATCH 1/3] x86/irq: local_irq_restore() should not blindly popf Andrew Cooper
@ 2013-10-21 13:58   ` David Vrabel
  2013-10-21 14:09     ` Keir Fraser
  2013-10-21 14:42   ` Jan Beulich
  1 sibling, 1 reply; 21+ messages in thread
From: David Vrabel @ 2013-10-21 13:58 UTC (permalink / raw)
  To: Andrew Cooper; +Cc: Keir Fraser, Jan Beulich, Xen-devel

On 21/10/13 14:41, Andrew Cooper wrote:
> local_irq_restore() should only be concerned with possibly changing the
> interrupt flag.  A blind popf could corrupt other system flags.
> 
> Signed-off-by: Andrew Cooper <andrew.cooper3@citrix.com>
> CC: Keir Fraser <keir@xen.org>
> CC: Jan Beulich <JBeulich@suse.com>
> ---
>  xen/include/asm-x86/system.h |    6 ++++--
>  1 file changed, 4 insertions(+), 2 deletions(-)
> 
> diff --git a/xen/include/asm-x86/system.h b/xen/include/asm-x86/system.h
> index 6ab7d56..cbf0f6a 100644
> --- a/xen/include/asm-x86/system.h
> +++ b/xen/include/asm-x86/system.h
> @@ -159,8 +159,10 @@ static always_inline unsigned long __cmpxchg(
>  #define local_irq_restore(x)                                     \
>  ({                                                               \
>      BUILD_BUG_ON(sizeof(x) != sizeof(long));                     \
> -    asm volatile ( "push" __OS " %0 ; popf" __OS                 \
> -                   : : "g" (x) : "memory", "cc" );               \
> +    if ( x & X86_EFLAGS_IF )                                     \
> +        local_irq_enable();                                      \
> +    else                                                         \
> +        local_irq_disable();                                     \
>  })

This adds a branch in a potentially hot path.

Is the local_irq_disable() needed? Interrupts should already be disabled
on entry.

David

^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: [PATCH 0/3] irqsave/restore improvements
  2013-10-21 13:41 [PATCH 0/3] irqsave/restore improvements Andrew Cooper
                   ` (2 preceding siblings ...)
  2013-10-21 13:41 ` [PATCH 3/3] common/spinlock: Ensure the flags parameter is wide enough Andrew Cooper
@ 2013-10-21 14:08 ` Keir Fraser
  3 siblings, 0 replies; 21+ messages in thread
From: Keir Fraser @ 2013-10-21 14:08 UTC (permalink / raw)
  To: Andrew Cooper, Xen-devel
  Cc: George Dunlap, Tim Deegan, Stefano Stabellini, Ian Campbell,
	Jan Beulich

On 21/10/2013 14:41, "Andrew Cooper" <andrew.cooper3@citrix.com> wrote:

> This series contains two independent but related fixes to do with
> irqsave/restore semantics.
> 
> The first patch prevents local_irq_restore() from corrupting system flags.
> 
> The second was constructed using the compile errors from the third patch,
> separated for clarity and reordered to prevent bisection problems.
> 
> The third patch uses a BUILD_BUG_ON() to ensure that the flags parameter to
> spin_lock_irqsave is wide enough to not trucate the result from
> local_irq_save().
> 
> I have not compile tested on arm, so request that one of the maintainers
> explicitly acks the final patch.  Any compile failures will almost certainly
> be fixed with an int->unsigned long conversion on the affected variable(s).
> 
> Signed-off-by: Andrew Cooper <andrew.cooper3@citrix.com>
> CC: Keir Fraser <keir@xen.org>
> CC: Jan Beulich <JBeulich@suse.com>
> CC: Ian Campbell <ian.campbell@citrix.com>
> CC: Stefano Stabellini <stefano.stabellini@citrix.com>
> CC: Tim Deegan <tim@xen.org>
> CC: George Dunlap <george.dunlap@eu.citrix.com>

Acked-by: Keir Fraser <keir@xen.org>

> --
> 1.7.10.4
> 

^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: [PATCH 1/3] x86/irq: local_irq_restore() should not blindly popf
  2013-10-21 13:58   ` David Vrabel
@ 2013-10-21 14:09     ` Keir Fraser
  2013-10-21 14:32       ` Jan Beulich
  0 siblings, 1 reply; 21+ messages in thread
From: Keir Fraser @ 2013-10-21 14:09 UTC (permalink / raw)
  To: David Vrabel, Andrew Cooper; +Cc: Jan Beulich, Xen-devel

On 21/10/2013 14:58, "David Vrabel" <david.vrabel@citrix.com> wrote:

> On 21/10/13 14:41, Andrew Cooper wrote:
>> local_irq_restore() should only be concerned with possibly changing the
>> interrupt flag.  A blind popf could corrupt other system flags.
>> 
>> Signed-off-by: Andrew Cooper <andrew.cooper3@citrix.com>
>> CC: Keir Fraser <keir@xen.org>
>> CC: Jan Beulich <JBeulich@suse.com>
>> ---
>>  xen/include/asm-x86/system.h |    6 ++++--
>>  1 file changed, 4 insertions(+), 2 deletions(-)
>> 
>> diff --git a/xen/include/asm-x86/system.h b/xen/include/asm-x86/system.h
>> index 6ab7d56..cbf0f6a 100644
>> --- a/xen/include/asm-x86/system.h
>> +++ b/xen/include/asm-x86/system.h
>> @@ -159,8 +159,10 @@ static always_inline unsigned long __cmpxchg(
>>  #define local_irq_restore(x)                                     \
>>  ({                                                               \
>>      BUILD_BUG_ON(sizeof(x) != sizeof(long));                     \
>> -    asm volatile ( "push" __OS " %0 ; popf" __OS                 \
>> -                   : : "g" (x) : "memory", "cc" );               \
>> +    if ( x & X86_EFLAGS_IF )                                     \
>> +        local_irq_enable();                                      \
>> +    else                                                         \
>> +        local_irq_disable();                                     \
>>  })
> 
> This adds a branch in a potentially hot path.
> 
> Is the local_irq_disable() needed? Interrupts should already be disabled
> on entry.

If that is always true, and so we get rid of the else, then
local_irq_restore() should ASSERT it on entry.

 -- Keir

> David

^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: [PATCH 1/3] x86/irq: local_irq_restore() should not blindly popf
  2013-10-21 14:09     ` Keir Fraser
@ 2013-10-21 14:32       ` Jan Beulich
  2013-10-21 15:24         ` Jan Beulich
  0 siblings, 1 reply; 21+ messages in thread
From: Jan Beulich @ 2013-10-21 14:32 UTC (permalink / raw)
  To: Andrew Cooper, David Vrabel, Keir Fraser; +Cc: Xen-devel

>>> On 21.10.13 at 16:09, Keir Fraser <keir.xen@gmail.com> wrote:
> On 21/10/2013 14:58, "David Vrabel" <david.vrabel@citrix.com> wrote:
> 
>> On 21/10/13 14:41, Andrew Cooper wrote:
>>> local_irq_restore() should only be concerned with possibly changing the
>>> interrupt flag.  A blind popf could corrupt other system flags.
>>> 
>>> Signed-off-by: Andrew Cooper <andrew.cooper3@citrix.com>
>>> CC: Keir Fraser <keir@xen.org>
>>> CC: Jan Beulich <JBeulich@suse.com>
>>> ---
>>>  xen/include/asm-x86/system.h |    6 ++++--
>>>  1 file changed, 4 insertions(+), 2 deletions(-)
>>> 
>>> diff --git a/xen/include/asm-x86/system.h b/xen/include/asm-x86/system.h
>>> index 6ab7d56..cbf0f6a 100644
>>> --- a/xen/include/asm-x86/system.h
>>> +++ b/xen/include/asm-x86/system.h
>>> @@ -159,8 +159,10 @@ static always_inline unsigned long __cmpxchg(
>>>  #define local_irq_restore(x)                                     \
>>>  ({                                                               \
>>>      BUILD_BUG_ON(sizeof(x) != sizeof(long));                     \
>>> -    asm volatile ( "push" __OS " %0 ; popf" __OS                 \
>>> -                   : : "g" (x) : "memory", "cc" );               \
>>> +    if ( x & X86_EFLAGS_IF )                                     \
>>> +        local_irq_enable();                                      \
>>> +    else                                                         \
>>> +        local_irq_disable();                                     \
>>>  })
>> 
>> This adds a branch in a potentially hot path.
>> 
>> Is the local_irq_disable() needed? Interrupts should already be disabled
>> on entry.
> 
> If that is always true, and so we get rid of the else, then
> local_irq_restore() should ASSERT it on entry.

Let's not go that route - the macro is supposed to do what it
says - restore the prior state of the interrupt flag.

To deal with the two branches the code adds I'd rather
recommend merging current and to-be-restored flags - the
necessary "and" and "or" are quite likely faster than any
mis-predicted branch (and perhaps as fast as a correctly
predicted one).

Jan

^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: [PATCH 1/3] x86/irq: local_irq_restore() should not blindly popf
  2013-10-21 13:41 ` [PATCH 1/3] x86/irq: local_irq_restore() should not blindly popf Andrew Cooper
  2013-10-21 13:58   ` David Vrabel
@ 2013-10-21 14:42   ` Jan Beulich
  2013-10-21 16:33     ` [Patch 1/3 v2] " Andrew Cooper
  1 sibling, 1 reply; 21+ messages in thread
From: Jan Beulich @ 2013-10-21 14:42 UTC (permalink / raw)
  To: Andrew Cooper; +Cc: xen-devel, Keir Fraser

>>> On 21.10.13 at 15:41, Andrew Cooper <andrew.cooper3@citrix.com> wrote:
> --- a/xen/include/asm-x86/system.h
> +++ b/xen/include/asm-x86/system.h
> @@ -159,8 +159,10 @@ static always_inline unsigned long __cmpxchg(
>  #define local_irq_restore(x)                                     \
>  ({                                                               \
>      BUILD_BUG_ON(sizeof(x) != sizeof(long));                     \
> -    asm volatile ( "push" __OS " %0 ; popf" __OS                 \
> -                   : : "g" (x) : "memory", "cc" );               \
> +    if ( x & X86_EFLAGS_IF )                                     \
> +        local_irq_enable();                                      \
> +    else                                                         \
> +        local_irq_disable();                                     \

_If_ you're going to re-do this using the mask-and-merge approach
I suggested in the other reply, may I ask that you also replace the
open coded (1<<9) a few lines down with X86_EFLAGS_IF (at once
making the comment there superfluous)?

Jan

^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: [PATCH 3/3] common/spinlock: Ensure the flags parameter is wide enough
  2013-10-21 13:41 ` [PATCH 3/3] common/spinlock: Ensure the flags parameter is wide enough Andrew Cooper
@ 2013-10-21 15:15   ` Ian Campbell
  0 siblings, 0 replies; 21+ messages in thread
From: Ian Campbell @ 2013-10-21 15:15 UTC (permalink / raw)
  To: Andrew Cooper
  Cc: Stefano Stabellini, Tim Deegan, Keir Fraser, Jan Beulich,
	Xen-devel

On Mon, 2013-10-21 at 14:41 +0100, Andrew Cooper wrote:
> The previous patch in the series fixes the compilation issues I found as a
> result of this patch, but I have not tested on arm.  I therefore request an
> explicit ack from an arm maintainer before this is committed.

I build tested just this patch on current staging and it failed, because
I hadn't spotted that the previous patch was generic and not x86
specific.

With patch 2/3 added both arm32 and arm64 hypervisors build for me, so:
Acked-by: Ian Campbell <ian.campbell@citrix.com>

BTW cross-compiling the hypervisor is more or less trivial, compilers
can be found at
https://launchpad.net/linaro-toolchain-binaries/+download and the runes
are:

	make dist-xen XEN_TARGET_ARCH=arm32 CROSS_COMPILER=arm-linux-gnueabihf-
	make dist-xen XEN_TARGET_ARCH=arm64 CROSS_COMPILER=aarch64-linux-gnu-

Ian.

^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: [PATCH 1/3] x86/irq: local_irq_restore() should not blindly popf
  2013-10-21 14:32       ` Jan Beulich
@ 2013-10-21 15:24         ` Jan Beulich
  0 siblings, 0 replies; 21+ messages in thread
From: Jan Beulich @ 2013-10-21 15:24 UTC (permalink / raw)
  To: Andrew Cooper, David Vrabel, Keir Fraser; +Cc: Xen-devel

>>> On 21.10.13 at 16:32, "Jan Beulich" <JBeulich@suse.com> wrote:
>>>> On 21.10.13 at 16:09, Keir Fraser <keir.xen@gmail.com> wrote:
>> On 21/10/2013 14:58, "David Vrabel" <david.vrabel@citrix.com> wrote:
>> 
>>> On 21/10/13 14:41, Andrew Cooper wrote:
>>>> local_irq_restore() should only be concerned with possibly changing the
>>>> interrupt flag.  A blind popf could corrupt other system flags.
>>>> 
>>>> Signed-off-by: Andrew Cooper <andrew.cooper3@citrix.com>
>>>> CC: Keir Fraser <keir@xen.org>
>>>> CC: Jan Beulich <JBeulich@suse.com>
>>>> ---
>>>>  xen/include/asm-x86/system.h |    6 ++++--
>>>>  1 file changed, 4 insertions(+), 2 deletions(-)
>>>> 
>>>> diff --git a/xen/include/asm-x86/system.h b/xen/include/asm-x86/system.h
>>>> index 6ab7d56..cbf0f6a 100644
>>>> --- a/xen/include/asm-x86/system.h
>>>> +++ b/xen/include/asm-x86/system.h
>>>> @@ -159,8 +159,10 @@ static always_inline unsigned long __cmpxchg(
>>>>  #define local_irq_restore(x)                                     \
>>>>  ({                                                               \
>>>>      BUILD_BUG_ON(sizeof(x) != sizeof(long));                     \
>>>> -    asm volatile ( "push" __OS " %0 ; popf" __OS                 \
>>>> -                   : : "g" (x) : "memory", "cc" );               \
>>>> +    if ( x & X86_EFLAGS_IF )                                     \
>>>> +        local_irq_enable();                                      \
>>>> +    else                                                         \
>>>> +        local_irq_disable();                                     \
>>>>  })
>>> 
>>> This adds a branch in a potentially hot path.
>>> 
>>> Is the local_irq_disable() needed? Interrupts should already be disabled
>>> on entry.
>> 
>> If that is always true, and so we get rid of the else, then
>> local_irq_restore() should ASSERT it on entry.
> 
> Let's not go that route - the macro is supposed to do what it
> says - restore the prior state of the interrupt flag.

And there is actually an example in the tree that might get
broken if we went that suggested route:
xen/arch/x86/io_apic.c:timer_irq_works(). Albeit I'm not sure - it
looks like the function gets called only in contexts where interrupts
are already enabled, but considering its use of local_irq_enable()
that may not have been the case earlier. In any event - I don't
think we should take the risk of some rarely executed (perhaps
error handling only) path doing something like that.

Jan

^ permalink raw reply	[flat|nested] 21+ messages in thread

* [Patch 1/3 v2] x86/irq: local_irq_restore() should not blindly popf
  2013-10-21 14:42   ` Jan Beulich
@ 2013-10-21 16:33     ` Andrew Cooper
  2013-10-21 18:18       ` Keir Fraser
  0 siblings, 1 reply; 21+ messages in thread
From: Andrew Cooper @ 2013-10-21 16:33 UTC (permalink / raw)
  To: Xen-devel; +Cc: Andrew Cooper, Keir Fraser, Jan Beulich

local_irq_restore() should only be concerned with possibly changing the
interrupt flag.  A blind popf could corrupt other system flags.

While playing in this area, fixup an opencoded use of X86_EFLAGS_IF.

Signed-off-by: Andrew Cooper <andrew.cooper3@citrix.com>
CC: Keir Fraser <keir@xen.org>
CC: Jan Beulich <JBeulich@suse.com>

---

This is rather more RFC.  It boots and runs VMs, so I am fairly sure it is
functionally correct, but I cant help feeling there might be a neater way to
do the inline assembly.  Suggestions welcome.
---
 xen/include/asm-x86/system.h |   11 ++++++++---
 1 file changed, 8 insertions(+), 3 deletions(-)

diff --git a/xen/include/asm-x86/system.h b/xen/include/asm-x86/system.h
index 6ab7d56..ff52671 100644
--- a/xen/include/asm-x86/system.h
+++ b/xen/include/asm-x86/system.h
@@ -3,6 +3,7 @@
 
 #include <xen/lib.h>
 #include <xen/bitops.h>
+#include <asm/processor.h>
 
 #define read_segment_register(name)                             \
 ({  u16 __sel;                                                  \
@@ -159,15 +160,19 @@ static always_inline unsigned long __cmpxchg(
 #define local_irq_restore(x)                                     \
 ({                                                               \
     BUILD_BUG_ON(sizeof(x) != sizeof(long));                     \
-    asm volatile ( "push" __OS " %0 ; popf" __OS                 \
-                   : : "g" (x) : "memory", "cc" );               \
+    asm volatile (                                               \
+    "pushf" __OS "\n\t"                                          \
+    "and" __OS " %0, (%%" __OP "sp)\n\t"                         \
+    "orw %1, (%%" __OP "sp)\n\t"                                 \
+    "popf" __OS "\n\t" : : "g" ( ~X86_EFLAGS_IF ),               \
+                           "g" ( x & X86_EFLAGS_IF ) );          \
 })
 
 static inline int local_irq_is_enabled(void)
 {
     unsigned long flags;
     local_save_flags(flags);
-    return !!(flags & (1<<9)); /* EFLAGS_IF */
+    return !!(flags & X86_EFLAGS_IF);
 }
 
 #define BROKEN_ACPI_Sx          0x0001
-- 
1.7.10.4

^ permalink raw reply related	[flat|nested] 21+ messages in thread

* Re: [Patch 1/3 v2] x86/irq: local_irq_restore() should not blindly popf
  2013-10-21 16:33     ` [Patch 1/3 v2] " Andrew Cooper
@ 2013-10-21 18:18       ` Keir Fraser
  2013-10-21 18:30         ` Andrew Cooper
  0 siblings, 1 reply; 21+ messages in thread
From: Keir Fraser @ 2013-10-21 18:18 UTC (permalink / raw)
  To: Andrew Cooper, Xen-devel; +Cc: Jan Beulich

On 21/10/2013 17:33, "Andrew Cooper" <andrew.cooper3@citrix.com> wrote:

> local_irq_restore() should only be concerned with possibly changing the
> interrupt flag.  A blind popf could corrupt other system flags.
> 
> While playing in this area, fixup an opencoded use of X86_EFLAGS_IF.
> 
> Signed-off-by: Andrew Cooper <andrew.cooper3@citrix.com>
> CC: Keir Fraser <keir@xen.org>
> CC: Jan Beulich <JBeulich@suse.com>
> 
> ---
> 
> This is rather more RFC.  It boots and runs VMs, so I am fairly sure it is
> functionally correct, but I cant help feeling there might be a neater way to
> do the inline assembly.  Suggestions welcome.
> ---
>  xen/include/asm-x86/system.h |   11 ++++++++---
>  1 file changed, 8 insertions(+), 3 deletions(-)
> 
> diff --git a/xen/include/asm-x86/system.h b/xen/include/asm-x86/system.h
> index 6ab7d56..ff52671 100644
> --- a/xen/include/asm-x86/system.h
> +++ b/xen/include/asm-x86/system.h
> @@ -3,6 +3,7 @@
>  
>  #include <xen/lib.h>
>  #include <xen/bitops.h>
> +#include <asm/processor.h>
>  
>  #define read_segment_register(name)                             \
>  ({  u16 __sel;                                                  \
> @@ -159,15 +160,19 @@ static always_inline unsigned long __cmpxchg(
>  #define local_irq_restore(x)                                     \
>  ({                                                               \
>      BUILD_BUG_ON(sizeof(x) != sizeof(long));                     \
> -    asm volatile ( "push" __OS " %0 ; popf" __OS                 \
> -                   : : "g" (x) : "memory", "cc" );               \
> +    asm volatile (                                               \
> +    "pushf" __OS "\n\t"                                          \
> +    "and" __OS " %0, (%%" __OP "sp)\n\t"                         \
> +    "orw %1, (%%" __OP "sp)\n\t"                                 \
> +    "popf" __OS "\n\t" : : "g" ( ~X86_EFLAGS_IF ),               \

Would this be better as a constant constraint ("i")?

> +                           "g" ( x & X86_EFLAGS_IF ) );          \
>  })
>  
>  static inline int local_irq_is_enabled(void)
>  {
>      unsigned long flags;
>      local_save_flags(flags);
> -    return !!(flags & (1<<9)); /* EFLAGS_IF */
> +    return !!(flags & X86_EFLAGS_IF);
>  }
>  
>  #define BROKEN_ACPI_Sx          0x0001

^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: [Patch 1/3 v2] x86/irq: local_irq_restore() should not blindly popf
  2013-10-21 18:18       ` Keir Fraser
@ 2013-10-21 18:30         ` Andrew Cooper
  2013-10-21 18:37           ` Keir Fraser
  0 siblings, 1 reply; 21+ messages in thread
From: Andrew Cooper @ 2013-10-21 18:30 UTC (permalink / raw)
  To: Keir Fraser; +Cc: Jan Beulich, Xen-devel

On 21/10/13 19:18, Keir Fraser wrote:
> On 21/10/2013 17:33, "Andrew Cooper" <andrew.cooper3@citrix.com> wrote:
>
>> local_irq_restore() should only be concerned with possibly changing the
>> interrupt flag.  A blind popf could corrupt other system flags.
>>
>> While playing in this area, fixup an opencoded use of X86_EFLAGS_IF.
>>
>> Signed-off-by: Andrew Cooper <andrew.cooper3@citrix.com>
>> CC: Keir Fraser <keir@xen.org>
>> CC: Jan Beulich <JBeulich@suse.com>
>>
>> ---
>>
>> This is rather more RFC.  It boots and runs VMs, so I am fairly sure it is
>> functionally correct, but I cant help feeling there might be a neater way to
>> do the inline assembly.  Suggestions welcome.
>> ---
>>  xen/include/asm-x86/system.h |   11 ++++++++---
>>  1 file changed, 8 insertions(+), 3 deletions(-)
>>
>> diff --git a/xen/include/asm-x86/system.h b/xen/include/asm-x86/system.h
>> index 6ab7d56..ff52671 100644
>> --- a/xen/include/asm-x86/system.h
>> +++ b/xen/include/asm-x86/system.h
>> @@ -3,6 +3,7 @@
>>  
>>  #include <xen/lib.h>
>>  #include <xen/bitops.h>
>> +#include <asm/processor.h>
>>  
>>  #define read_segment_register(name)                             \
>>  ({  u16 __sel;                                                  \
>> @@ -159,15 +160,19 @@ static always_inline unsigned long __cmpxchg(
>>  #define local_irq_restore(x)                                     \
>>  ({                                                               \
>>      BUILD_BUG_ON(sizeof(x) != sizeof(long));                     \
>> -    asm volatile ( "push" __OS " %0 ; popf" __OS                 \
>> -                   : : "g" (x) : "memory", "cc" );               \
>> +    asm volatile (                                               \
>> +    "pushf" __OS "\n\t"                                          \
>> +    "and" __OS " %0, (%%" __OP "sp)\n\t"                         \
>> +    "orw %1, (%%" __OP "sp)\n\t"                                 \
>> +    "popf" __OS "\n\t" : : "g" ( ~X86_EFLAGS_IF ),               \
> Would this be better as a constant constraint ("i")?

I was wondering what the best practice for this would be.

In most cases, I would imagine that an immediate would be used. 
However, as this is a define and therefore forcibly inlined everywhere
it is used, it is just possible that the compiler could find a
~X86_EFLAGS_IF already in context, and optimise down to an "and r64,r/m64".

~Andrew

>
>> +                           "g" ( x & X86_EFLAGS_IF ) );          \
>>  })
>>  
>>  static inline int local_irq_is_enabled(void)
>>  {
>>      unsigned long flags;
>>      local_save_flags(flags);
>> -    return !!(flags & (1<<9)); /* EFLAGS_IF */
>> +    return !!(flags & X86_EFLAGS_IF);
>>  }
>>  
>>  #define BROKEN_ACPI_Sx          0x0001
>

^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: [Patch 1/3 v2] x86/irq: local_irq_restore() should not blindly popf
  2013-10-21 18:30         ` Andrew Cooper
@ 2013-10-21 18:37           ` Keir Fraser
  2013-10-22  8:35             ` Jan Beulich
  0 siblings, 1 reply; 21+ messages in thread
From: Keir Fraser @ 2013-10-21 18:37 UTC (permalink / raw)
  To: Andrew Cooper; +Cc: Jan Beulich, Xen-devel

On 21/10/2013 19:30, "Andrew Cooper" <andrew.cooper3@citrix.com> wrote:

>>>  #define read_segment_register(name)                             \
>>>  ({  u16 __sel;                                                  \
>>> @@ -159,15 +160,19 @@ static always_inline unsigned long __cmpxchg(
>>>  #define local_irq_restore(x)                                     \
>>>  ({                                                               \
>>>      BUILD_BUG_ON(sizeof(x) != sizeof(long));                     \
>>> -    asm volatile ( "push" __OS " %0 ; popf" __OS                 \
>>> -                   : : "g" (x) : "memory", "cc" );               \
>>> +    asm volatile (                                               \
>>> +    "pushf" __OS "\n\t"                                          \
>>> +    "and" __OS " %0, (%%" __OP "sp)\n\t"                         \
>>> +    "orw %1, (%%" __OP "sp)\n\t"                                 \
>>> +    "popf" __OS "\n\t" : : "g" ( ~X86_EFLAGS_IF ),               \
>> Would this be better as a constant constraint ("i")?
> 
> I was wondering what the best practice for this would be.
> 
> In most cases, I would imagine that an immediate would be used.
> However, as this is a define and therefore forcibly inlined everywhere
> it is used, it is just possible that the compiler could find a
> ~X86_EFLAGS_IF already in context, and optimise down to an "and r64,r/m64".

Oh, g includes i, I forgot that. Well your choice is best then.

Acked-by: Keir Fraser <keir@xen.org>

> ~Andrew

^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: [Patch 1/3 v2] x86/irq: local_irq_restore() should not blindly popf
  2013-10-21 18:37           ` Keir Fraser
@ 2013-10-22  8:35             ` Jan Beulich
  2013-10-22  8:56               ` Andrew Cooper
  0 siblings, 1 reply; 21+ messages in thread
From: Jan Beulich @ 2013-10-22  8:35 UTC (permalink / raw)
  To: Andrew Cooper, Keir Fraser; +Cc: Xen-devel

>>> On 21.10.13 at 20:37, Keir Fraser <keir.xen@gmail.com> wrote:
> On 21/10/2013 19:30, "Andrew Cooper" <andrew.cooper3@citrix.com> wrote:
> 
>>>>  #define read_segment_register(name)                             \
>>>>  ({  u16 __sel;                                                  \
>>>> @@ -159,15 +160,19 @@ static always_inline unsigned long __cmpxchg(
>>>>  #define local_irq_restore(x)                                     \
>>>>  ({                                                               \
>>>>      BUILD_BUG_ON(sizeof(x) != sizeof(long));                     \
>>>> -    asm volatile ( "push" __OS " %0 ; popf" __OS                 \
>>>> -                   : : "g" (x) : "memory", "cc" );               \
>>>> +    asm volatile (                                               \
>>>> +    "pushf" __OS "\n\t"                                          \
>>>> +    "and" __OS " %0, (%%" __OP "sp)\n\t"                         \
>>>> +    "orw %1, (%%" __OP "sp)\n\t"                                 \
>>>> +    "popf" __OS "\n\t" : : "g" ( ~X86_EFLAGS_IF ),               \
>>> Would this be better as a constant constraint ("i")?
>> 
>> I was wondering what the best practice for this would be.
>> 
>> In most cases, I would imagine that an immediate would be used.
>> However, as this is a define and therefore forcibly inlined everywhere
>> it is used, it is just possible that the compiler could find a
>> ~X86_EFLAGS_IF already in context, and optimise down to an "and r64,r/m64".
> 
> Oh, g includes i, I forgot that. Well your choice is best then.

Sorry, but no. "g" also includes "m", and
- the other operand of both operations is a memory operand
  already, so this one can't also be a memory one,
- on a non-debug build (without frame pointers) an eventual
  %rsp-relative memory location would be broken due to the
  shifted stack offsets resulting from the PUSHF.
Hence both constraints can at best be "ri".

Further I have a hard time seeing how the "orw" used above
can even have built successfully: If a register gets picked
(which ought to be the common case), opcode suffix and
register name ought to collide. And "orw" is a bad choice here
anyway, in that this is a 2-byte write following an 8-byte one.

And finally - what's the point of using __OS in new assembly
constructs? I was actually considering cleaning up all this hard
to read cruft, since we no longer care about the 32-bit case.

Jan

^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: [Patch 1/3 v2] x86/irq: local_irq_restore() should not blindly popf
  2013-10-22  8:35             ` Jan Beulich
@ 2013-10-22  8:56               ` Andrew Cooper
  2013-10-22  9:28                 ` Jan Beulich
  0 siblings, 1 reply; 21+ messages in thread
From: Andrew Cooper @ 2013-10-22  8:56 UTC (permalink / raw)
  To: Jan Beulich; +Cc: Keir Fraser, Xen-devel

On 22/10/13 09:35, Jan Beulich wrote:
>>>> On 21.10.13 at 20:37, Keir Fraser <keir.xen@gmail.com> wrote:
>> On 21/10/2013 19:30, "Andrew Cooper" <andrew.cooper3@citrix.com> wrote:
>>
>>>>>  #define read_segment_register(name)                             \
>>>>>  ({  u16 __sel;                                                  \
>>>>> @@ -159,15 +160,19 @@ static always_inline unsigned long __cmpxchg(
>>>>>  #define local_irq_restore(x)                                     \
>>>>>  ({                                                               \
>>>>>      BUILD_BUG_ON(sizeof(x) != sizeof(long));                     \
>>>>> -    asm volatile ( "push" __OS " %0 ; popf" __OS                 \
>>>>> -                   : : "g" (x) : "memory", "cc" );               \
>>>>> +    asm volatile (                                               \
>>>>> +    "pushf" __OS "\n\t"                                          \
>>>>> +    "and" __OS " %0, (%%" __OP "sp)\n\t"                         \
>>>>> +    "orw %1, (%%" __OP "sp)\n\t"                                 \
>>>>> +    "popf" __OS "\n\t" : : "g" ( ~X86_EFLAGS_IF ),               \
>>>> Would this be better as a constant constraint ("i")?
>>> I was wondering what the best practice for this would be.
>>>
>>> In most cases, I would imagine that an immediate would be used.
>>> However, as this is a define and therefore forcibly inlined everywhere
>>> it is used, it is just possible that the compiler could find a
>>> ~X86_EFLAGS_IF already in context, and optimise down to an "and r64,r/m64".
>> Oh, g includes i, I forgot that. Well your choice is best then.
> Sorry, but no. "g" also includes "m", and
> - the other operand of both operations is a memory operand
>   already, so this one can't also be a memory one,
> - on a non-debug build (without frame pointers) an eventual
>   %rsp-relative memory location would be broken due to the
>   shifted stack offsets resulting from the PUSHF.
> Hence both constraints can at best be "ri".

Ok - I can change this.

>
> Further I have a hard time seeing how the "orw" used above
> can even have built successfully: If a register gets picked
> (which ought to be the common case), opcode suffix and
> register name ought to collide. And "orw" is a bad choice here
> anyway, in that this is a 2-byte write following an 8-byte one.

GCC correctly picks a 2-byte register given the orw.  Looking at the
disassembly, it usually chooses %r12w

Why is symmetry of writes important here?  We are possibly setting bit 9
alone.

>
> And finally - what's the point of using __OS in new assembly
> constructs? I was actually considering cleaning up all this hard
> to read cruft, since we no longer care about the 32-bit case.

I am happy to remove __OS/__OP if that is considered a good thing moving
forward - I was merely using the prevailing style.

~Andrew

^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: [Patch 1/3 v2] x86/irq: local_irq_restore() should not blindly popf
  2013-10-22  8:56               ` Andrew Cooper
@ 2013-10-22  9:28                 ` Jan Beulich
  2013-10-22 10:14                   ` [PATCH 1/3 v3] " Andrew Cooper
  2013-10-29 14:53                   ` [Patch 1/3 v2] " Jan Beulich
  0 siblings, 2 replies; 21+ messages in thread
From: Jan Beulich @ 2013-10-22  9:28 UTC (permalink / raw)
  To: Andrew Cooper; +Cc: Keir Fraser, Xen-devel

>>> On 22.10.13 at 10:56, Andrew Cooper <andrew.cooper3@citrix.com> wrote:
> On 22/10/13 09:35, Jan Beulich wrote:
>> Further I have a hard time seeing how the "orw" used above
>> can even have built successfully: If a register gets picked
>> (which ought to be the common case), opcode suffix and
>> register name ought to collide. And "orw" is a bad choice here
>> anyway, in that this is a 2-byte write following an 8-byte one.
> 
> GCC correctly picks a 2-byte register given the orw.  Looking at the
> disassembly, it usually chooses %r12w

Try compiling this

void test(unsigned long x) {
	asm volatile("orw %0, (%0)" :: "ri" (x));
}

with a 32-bit gcc (or with -m32). In fact I'm surprised the assembler
doesn't generate a warning (or even error) in the 64-bit case - this
very much smells like a bug (and I looked at that code the other day
and got the impression that the 64-bit one would be _less_ forgiving
here).

In any event - if you want to stay with "orw", you ought to use
"%w<number>" for the operand.

> Why is symmetry of writes important here?  We are possibly setting bit 9
> alone.

Store-to-load-forwarding works only when the store size is larger
than the load one. So I shouldn't have drawn your attention to
the preceding "andq" but to the following "pushfq" (though I
wouldn't be surprised if mixed size writes to overlapping memory
locations would also suffer from penalties).

Jan

^ permalink raw reply	[flat|nested] 21+ messages in thread

* [PATCH 1/3 v3] x86/irq: local_irq_restore() should not blindly popf
  2013-10-22  9:28                 ` Jan Beulich
@ 2013-10-22 10:14                   ` Andrew Cooper
  2013-10-22 13:27                     ` Keir Fraser
  2013-10-29 14:53                   ` [Patch 1/3 v2] " Jan Beulich
  1 sibling, 1 reply; 21+ messages in thread
From: Andrew Cooper @ 2013-10-22 10:14 UTC (permalink / raw)
  To: Xen-devel; +Cc: Andrew Cooper, Keir Fraser, Jan Beulich

local_irq_restore() should only be concerned with possibly changing the
interrupt flag.  A blind popf could corrupt other system flags.

While playing in this area, fixup an opencoded use of X86_EFLAGS_IF.

Signed-off-by: Andrew Cooper <andrew.cooper3@citrix.com>
CC: Keir Fraser <keir@xen.org>
CC: Jan Beulich <JBeulich@suse.com>

---

Change in v3:
 * asm tweaks
---
 xen/include/asm-x86/system.h |   11 ++++++++---
 1 file changed, 8 insertions(+), 3 deletions(-)

diff --git a/xen/include/asm-x86/system.h b/xen/include/asm-x86/system.h
index 6ab7d56..7d9f31b 100644
--- a/xen/include/asm-x86/system.h
+++ b/xen/include/asm-x86/system.h
@@ -3,6 +3,7 @@
 
 #include <xen/lib.h>
 #include <xen/bitops.h>
+#include <asm/processor.h>
 
 #define read_segment_register(name)                             \
 ({  u16 __sel;                                                  \
@@ -159,15 +160,19 @@ static always_inline unsigned long __cmpxchg(
 #define local_irq_restore(x)                                     \
 ({                                                               \
     BUILD_BUG_ON(sizeof(x) != sizeof(long));                     \
-    asm volatile ( "push" __OS " %0 ; popf" __OS                 \
-                   : : "g" (x) : "memory", "cc" );               \
+    asm volatile (                                               \
+        "pushfq\n\t"                                             \
+        "andq %0, (%%rsp)\n\t"                                   \
+        "orq  %1, (%%rsp)\n\t"                                   \
+        "popfq\n\t" : : "ri" ( ~X86_EFLAGS_IF ),                 \
+                        "ri" ( x & X86_EFLAGS_IF ) );            \
 })
 
 static inline int local_irq_is_enabled(void)
 {
     unsigned long flags;
     local_save_flags(flags);
-    return !!(flags & (1<<9)); /* EFLAGS_IF */
+    return !!(flags & X86_EFLAGS_IF);
 }
 
 #define BROKEN_ACPI_Sx          0x0001
-- 
1.7.10.4

^ permalink raw reply related	[flat|nested] 21+ messages in thread

* Re: [PATCH 1/3 v3] x86/irq: local_irq_restore() should not blindly popf
  2013-10-22 10:14                   ` [PATCH 1/3 v3] " Andrew Cooper
@ 2013-10-22 13:27                     ` Keir Fraser
  0 siblings, 0 replies; 21+ messages in thread
From: Keir Fraser @ 2013-10-22 13:27 UTC (permalink / raw)
  To: Andrew Cooper, Xen-devel; +Cc: Jan Beulich

On 22/10/2013 11:14, "Andrew Cooper" <andrew.cooper3@citrix.com> wrote:

> local_irq_restore() should only be concerned with possibly changing the
> interrupt flag.  A blind popf could corrupt other system flags.
> 
> While playing in this area, fixup an opencoded use of X86_EFLAGS_IF.
> 
> Signed-off-by: Andrew Cooper <andrew.cooper3@citrix.com>
> CC: Keir Fraser <keir@xen.org>
> CC: Jan Beulich <JBeulich@suse.com>

Acked-by: Keir Fraser <keir@xen.org>

> ---
> 
> Change in v3:
>  * asm tweaks
> ---
>  xen/include/asm-x86/system.h |   11 ++++++++---
>  1 file changed, 8 insertions(+), 3 deletions(-)
> 
> diff --git a/xen/include/asm-x86/system.h b/xen/include/asm-x86/system.h
> index 6ab7d56..7d9f31b 100644
> --- a/xen/include/asm-x86/system.h
> +++ b/xen/include/asm-x86/system.h
> @@ -3,6 +3,7 @@
>  
>  #include <xen/lib.h>
>  #include <xen/bitops.h>
> +#include <asm/processor.h>
>  
>  #define read_segment_register(name)                             \
>  ({  u16 __sel;                                                  \
> @@ -159,15 +160,19 @@ static always_inline unsigned long __cmpxchg(
>  #define local_irq_restore(x)                                     \
>  ({                                                               \
>      BUILD_BUG_ON(sizeof(x) != sizeof(long));                     \
> -    asm volatile ( "push" __OS " %0 ; popf" __OS                 \
> -                   : : "g" (x) : "memory", "cc" );               \
> +    asm volatile (                                               \
> +        "pushfq\n\t"                                             \
> +        "andq %0, (%%rsp)\n\t"                                   \
> +        "orq  %1, (%%rsp)\n\t"                                   \
> +        "popfq\n\t" : : "ri" ( ~X86_EFLAGS_IF ),                 \
> +                        "ri" ( x & X86_EFLAGS_IF ) );            \
>  })
>  
>  static inline int local_irq_is_enabled(void)
>  {
>      unsigned long flags;
>      local_save_flags(flags);
> -    return !!(flags & (1<<9)); /* EFLAGS_IF */
> +    return !!(flags & X86_EFLAGS_IF);
>  }
>  
>  #define BROKEN_ACPI_Sx          0x0001

^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: [Patch 1/3 v2] x86/irq: local_irq_restore() should not blindly popf
  2013-10-22  9:28                 ` Jan Beulich
  2013-10-22 10:14                   ` [PATCH 1/3 v3] " Andrew Cooper
@ 2013-10-29 14:53                   ` Jan Beulich
  1 sibling, 0 replies; 21+ messages in thread
From: Jan Beulich @ 2013-10-29 14:53 UTC (permalink / raw)
  To: Andrew Cooper; +Cc: Keir Fraser, Xen-devel

>>> On 22.10.13 at 11:28, "Jan Beulich" <JBeulich@suse.com> wrote:
>>>> On 22.10.13 at 10:56, Andrew Cooper <andrew.cooper3@citrix.com> wrote:
>> On 22/10/13 09:35, Jan Beulich wrote:
>>> Further I have a hard time seeing how the "orw" used above
>>> can even have built successfully: If a register gets picked
>>> (which ought to be the common case), opcode suffix and
>>> register name ought to collide. And "orw" is a bad choice here
>>> anyway, in that this is a 2-byte write following an 8-byte one.
>> 
>> GCC correctly picks a 2-byte register given the orw.  Looking at the
>> disassembly, it usually chooses %r12w
> 
> Try compiling this
> 
> void test(unsigned long x) {
> 	asm volatile("orw %0, (%0)" :: "ri" (x));
> }
> 
> with a 32-bit gcc (or with -m32). In fact I'm surprised the assembler
> doesn't generate a warning (or even error) in the 64-bit case - this
> very much smells like a bug (and I looked at that code the other day
> and got the impression that the 64-bit one would be _less_ forgiving
> here).

See http://www.sourceware.org/ml/binutils/2013-10/msg00358.html.

Jan

^ permalink raw reply	[flat|nested] 21+ messages in thread

end of thread, other threads:[~2013-10-29 14:53 UTC | newest]

Thread overview: 21+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2013-10-21 13:41 [PATCH 0/3] irqsave/restore improvements Andrew Cooper
2013-10-21 13:41 ` [PATCH 1/3] x86/irq: local_irq_restore() should not blindly popf Andrew Cooper
2013-10-21 13:58   ` David Vrabel
2013-10-21 14:09     ` Keir Fraser
2013-10-21 14:32       ` Jan Beulich
2013-10-21 15:24         ` Jan Beulich
2013-10-21 14:42   ` Jan Beulich
2013-10-21 16:33     ` [Patch 1/3 v2] " Andrew Cooper
2013-10-21 18:18       ` Keir Fraser
2013-10-21 18:30         ` Andrew Cooper
2013-10-21 18:37           ` Keir Fraser
2013-10-22  8:35             ` Jan Beulich
2013-10-22  8:56               ` Andrew Cooper
2013-10-22  9:28                 ` Jan Beulich
2013-10-22 10:14                   ` [PATCH 1/3 v3] " Andrew Cooper
2013-10-22 13:27                     ` Keir Fraser
2013-10-29 14:53                   ` [Patch 1/3 v2] " Jan Beulich
2013-10-21 13:41 ` [PATCH 2/3] xen: Widen flags parameter for spinlock_irqsave() and friends Andrew Cooper
2013-10-21 13:41 ` [PATCH 3/3] common/spinlock: Ensure the flags parameter is wide enough Andrew Cooper
2013-10-21 15:15   ` Ian Campbell
2013-10-21 14:08 ` [PATCH 0/3] irqsave/restore improvements Keir Fraser

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).