public inbox for linux-kernel@vger.kernel.org
 help / color / mirror / Atom feed
From: Andrew Cooper <andrew.cooper3@citrix.com>
To: Frediano Ziglio <frediano.ziglio@citrix.com>,
	Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>,
	Boris Ostrovsky <boris.ostrovsky@oracle.com>,
	David Vrabel <david.vrabel@citrix.com>
Cc: xen-devel <xen-devel@lists.xenproject.org>,
	linux-kernel <linux-kernel@vger.kernel.org>
Subject: Re: [Xen-devel] xen: Fix possible page fault in fifo events
Date: Tue, 15 Jul 2014 15:32:58 +0100	[thread overview]
Message-ID: <53C53B9A.6070608@citrix.com> (raw)
In-Reply-To: <1405432129.1749.5.camel@hamster.uk.xensource.com>

On 15/07/14 14:48, Frediano Ziglio wrote:
> sync_test_bit function require a long* read access to pointer.
> This is a problem if the you are using last entry in the page causing
> an access to next page. If this page is not readable you get a memory
> access failure (page fault).
> All other x64 bit functions access memory using 32 bit operations.
> For processors different than x64 long aligned operations are used.
>
> Signed-off-by: Frediano Ziglio <frediano.ziglio@citrix.com>

The core issue is that the Linux bitops primitives are inconsistent. 
They all use unsigned long pointers to refer to memory; the purely C
primitives then make memory accesses at the native width of an unsigned
long, while the assembly optimised primitives use 32bit accesses (either
explicitly with an 'l' asm suffix, or implicitly as the default operand
width is 32bit without a REX prefix in x86_64).

Xen suffers from a similar mess of primitives, but all its C primitives
use unsigned int pointers rather than unsigned long, meaning that they
still generate 32bit memory accesses when compiled as 64bit.  This means
the Xen side of the event fifo code is safe, but by luck rather than
good guidance.

In this case, an event_word_t is strictly a 32bit quantity, and should
never be accessed with a 64bit memory access.  This in turn would fix
the alignment issues which affected arm64, and this pagefault because
the 4 bytes we didn't care about were in a non-present page.

However, there doesn't appear to be a systematic way of enforcing a
specific memory access width given the existing primitives.

~Andrew

> ---
>  drivers/xen/events/events_fifo.c | 9 +++++++--
>  1 file changed, 7 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/xen/events/events_fifo.c b/drivers/xen/events/events_fifo.c
> index d302639..af4672d 100644
> --- a/drivers/xen/events/events_fifo.c
> +++ b/drivers/xen/events/events_fifo.c
> @@ -168,6 +168,11 @@ static int evtchn_fifo_setup(struct irq_info *info)
>  	return ret;
>  }
>  
> +static __always_inline int test_fifo_bit(int nr, event_word_t *word)
> +{
> +	return (ACCESS_ONCE(*word) & (((event_word_t) 1) << nr)) != 0;
> +}
> +
>  static void evtchn_fifo_bind_to_cpu(struct irq_info *info, unsigned cpu)
>  {
>  	/* no-op */
> @@ -188,7 +193,7 @@ static void evtchn_fifo_set_pending(unsigned port)
>  static bool evtchn_fifo_is_pending(unsigned port)
>  {
>  	event_word_t *word = event_word_from_port(port);
> -	return sync_test_bit(EVTCHN_FIFO_BIT(PENDING, word), BM(word));
> +	return test_fifo_bit(EVTCHN_FIFO_PENDING, word);
>  }
>  
>  static bool evtchn_fifo_test_and_set_mask(unsigned port)
> @@ -206,7 +211,7 @@ static void evtchn_fifo_mask(unsigned port)
>  static bool evtchn_fifo_is_masked(unsigned port)
>  {
>  	event_word_t *word = event_word_from_port(port);
> -	return sync_test_bit(EVTCHN_FIFO_BIT(MASKED, word), BM(word));
> +	return test_fifo_bit(EVTCHN_FIFO_MASKED, word);
>  }
>  /*
>   * Clear MASKED, spinning if BUSY is set.


  reply	other threads:[~2014-07-15 14:33 UTC|newest]

Thread overview: 5+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2014-07-15 13:48 xen: Fix possible page fault in fifo events Frediano Ziglio
2014-07-15 14:32 ` Andrew Cooper [this message]
2014-07-15 15:27   ` [Xen-devel] " Konrad Rzeszutek Wilk
2014-07-15 15:54   ` Frediano Ziglio
2014-07-28 12:55 ` David Vrabel

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=53C53B9A.6070608@citrix.com \
    --to=andrew.cooper3@citrix.com \
    --cc=boris.ostrovsky@oracle.com \
    --cc=david.vrabel@citrix.com \
    --cc=frediano.ziglio@citrix.com \
    --cc=konrad.wilk@oracle.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=xen-devel@lists.xenproject.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox