All of lore.kernel.org
 help / color / mirror / Atom feed
From: James Hogan <james.hogan@imgtec.com>
To: linux-mips@linux-mips.org
Cc: David Daney <ddaney.cavm@gmail.com>,
	Paolo Bonzini <pbonzini@redhat.com>,
	Gleb Natapov <gleb@kernel.org>,
	kvm@vger.kernel.org, Ralf Baechle <ralf@linux-mips.org>,
	Sanjay Lal <sanjayl@kymasys.com>
Subject: Re: [PATCH 09/21] MIPS: KVM: Fix timer race modifying guest CP0_Cause
Date: Fri, 25 Apr 2014 21:42:08 +0100	[thread overview]
Message-ID: <3027239.6lcM6FV8mj@radagast> (raw)
In-Reply-To: <535A9393.9010907@gmail.com>

[-- Attachment #1: Type: text/plain, Size: 5983 bytes --]

Hi David,

On Friday 25 April 2014 09:55:47 David Daney wrote:
> On 04/25/2014 08:19 AM, James Hogan wrote:
> > The hrtimer callback for guest timer timeouts sets the guest's
> > CP0_Cause.TI bit to indicate to the guest that a timer interrupt is
> > pending, however there is no mutual exclusion implemented to prevent
> > this occurring while the guest's CP0_Cause register is being
> > read-modify-written elsewhere.
> > 
> > When this occurs the setting of the CP0_Cause.TI bit is undone and the
> > guest misses the timer interrupt and doesn't reprogram the CP0_Compare
> > register for the next timeout. Currently another timer interrupt will be
> > triggered again in another 10ms anyway due to the way timers are
> > emulated, but after the MIPS timer emulation is fixed this would result
> > in Linux guest time standing still and the guest scheduler not being
> > invoked until the guest CP0_Count has looped around again, which at
> > 100MHz takes just under 43 seconds.
> > 
> > Currently this is the only asynchronous modification of guest registers,
> > therefore it is fixed by adjusting the implementations of the
> > kvm_set_c0_guest_cause(), kvm_clear_c0_guest_cause(), and
> > kvm_change_c0_guest_cause() macros which are used for modifying the
> > guest CP0_Cause register to use ll/sc to ensure atomic modification.
> > This should work in both UP and SMP cases without requiring interrupts
> > to be disabled.
> > 
> > Signed-off-by: James Hogan <james.hogan@imgtec.com>
> > Cc: Paolo Bonzini <pbonzini@redhat.com>
> > Cc: Gleb Natapov <gleb@kernel.org>
> > Cc: kvm@vger.kernel.org
> > Cc: Ralf Baechle <ralf@linux-mips.org>
> > Cc: linux-mips@linux-mips.org
> > Cc: Sanjay Lal <sanjayl@kymasys.com>
> 
> NACK, I don't like the names of these functions.  They initially
> confused me too much...

It's just being consistent with all the other *set*, *clear*, and *change* 
macros in kvm_host.h, asm/mipsregs.h, and the 229 users of those macros across 
the arch. I see no reason to confuse things further by being inconsistent.

Cheers
James

> 
> > ---
> > 
> >   arch/mips/include/asm/kvm_host.h | 71
> >   ++++++++++++++++++++++++++++++++++++---- 1 file changed, 65
> >   insertions(+), 6 deletions(-)
> > 
> > diff --git a/arch/mips/include/asm/kvm_host.h
> > b/arch/mips/include/asm/kvm_host.h index 3eedcb3015e5..90e1c0005ff4
> > 100644
> > --- a/arch/mips/include/asm/kvm_host.h
> > +++ b/arch/mips/include/asm/kvm_host.h
> > @@ -481,15 +481,74 @@ struct kvm_vcpu_arch {
> > 
> >   #define
> >   kvm_read_c0_guest_errorepc(cop0)	(cop0->reg[MIPS_CP0_ERROR_PC][0])
> >   #define kvm_write_c0_guest_errorepc(cop0,
> >   val)	(cop0->reg[MIPS_CP0_ERROR_PC][0] = (val))> 
> > +/*
> > + * Some of the guest registers may be modified asynchronously (e.g. from
> > a
> > + * hrtimer callback in hard irq context) and therefore need stronger
> > atomicity + * guarantees than other registers.
> > + */
> > +
> > +static inline void _kvm_atomic_set_c0_guest_reg(unsigned long *reg,
> > +						unsigned long val)
> 
> The name of this function is too unclear.
> 
> It should be _kvm_atomic_or_c0_guest_reg, or
> _kvm_atomic_setbits_c0_guest_reg(unsigned long *reg, unsigned long mask)
> 
> > +{
> > +	unsigned long temp;
> > +	do {
> > +		__asm__ __volatile__(
> > +		"	.set	mips3				\n"
> > +		"	" __LL "%0, %1				\n"
> > +		"	or	%0, %2				\n"
> > +		"	" __SC	"%0, %1				\n"
> > +		"	.set	mips0				\n"
> > +		: "=&r" (temp), "+m" (*reg)
> > +		: "r" (val));
> > +	} while (unlikely(!temp));
> > +}
> > +
> > +static inline void _kvm_atomic_clear_c0_guest_reg(unsigned long *reg,
> > +						  unsigned long val)
> 
> Same here.
> 
> Perhaps _kvm_atomic_clearbits_c0_guest_reg(unsigned long *reg, unsigned
> long mask)
> 
> > +{
> > +	unsigned long temp;
> > +	do {
> > +		__asm__ __volatile__(
> > +		"	.set	mips3				\n"
> > +		"	" __LL "%0, %1				\n"
> > +		"	and	%0, %2				\n"
> > +		"	" __SC	"%0, %1				\n"
> > +		"	.set	mips0				\n"
> > +		: "=&r" (temp), "+m" (*reg)
> > +		: "r" (~val));
> > +	} while (unlikely(!temp));
> > +}
> > +
> > +static inline void _kvm_atomic_change_c0_guest_reg(unsigned long *reg,
> > +						   unsigned long change,
> > +						   unsigned long val)
> 
> Same here.
> 
> Perhaps
> 
> _kvm_atomic_setbits_c0_guest_reg(unsigned long *reg,
> 				unsigned long mask,
> 				unsigned long bits)
> 
> > +{
> > +	unsigned long temp;
> > +	do {
> > +		__asm__ __volatile__(
> > +		"	.set	mips3				\n"
> > +		"	" __LL "%0, %1				\n"
> > +		"	and	%0, %2				\n"
> > +		"	or	%0, %3				\n"
> > +		"	" __SC	"%0, %1				\n"
> > +		"	.set	mips0				\n"
> > +		: "=&r" (temp), "+m" (*reg)
> > +		: "r" (~change), "r" (val & change));
> > +	} while (unlikely(!temp));
> > +}
> > +
> > 
> >   #define kvm_set_c0_guest_status(cop0,
> >   val)	(cop0->reg[MIPS_CP0_STATUS][0] |= (val)) #define
> >   kvm_clear_c0_guest_status(cop0, val)	(cop0->reg[MIPS_CP0_STATUS][0] &=
> >   ~(val))> 
> > -#define kvm_set_c0_guest_cause(cop0, val)	(cop0->reg[MIPS_CP0_CAUSE][0]
> > |= (val)) -#define kvm_clear_c0_guest_cause(cop0,
> > val)	(cop0->reg[MIPS_CP0_CAUSE][0] &= ~(val)) +
> > +/* Cause can be modified asynchronously from hardirq hrtimer callback */
> > +#define kvm_set_c0_guest_cause(cop0, val)				\
> > +	_kvm_atomic_set_c0_guest_reg(&cop0->reg[MIPS_CP0_CAUSE][0], val)
> > +#define kvm_clear_c0_guest_cause(cop0, val)				\
> > +	_kvm_atomic_clear_c0_guest_reg(&cop0->reg[MIPS_CP0_CAUSE][0], val)
> > 
> >   #define kvm_change_c0_guest_cause(cop0, change, val)			\
> > 
> > -{									\
> > -	kvm_clear_c0_guest_cause(cop0, change);				\
> > -	kvm_set_c0_guest_cause(cop0, ((val) & (change)));		\
> > -}
> > +	_kvm_atomic_change_c0_guest_reg(&cop0->reg[MIPS_CP0_CAUSE][0],	\
> > +					change, val)
> > +
> > 
> >   #define kvm_set_c0_guest_ebase(cop0, val)	(cop0->reg[MIPS_CP0_PRID][1]
> >   |= (val)) #define kvm_clear_c0_guest_ebase(cop0,
> >   val)	(cop0->reg[MIPS_CP0_PRID][1] &= ~(val)) #define
> >   kvm_change_c0_guest_ebase(cop0, change, val)			\

[-- Attachment #2: This is a digitally signed message part. --]
[-- Type: application/pgp-signature, Size: 836 bytes --]

  reply	other threads:[~2014-04-25 20:42 UTC|newest]

Thread overview: 64+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2014-04-25 15:19 [PATCH 00/21] MIPS: KVM: Fixes and guest timer rewrite James Hogan
2014-04-25 15:19 ` James Hogan
2014-04-25 15:19 ` [PATCH 01/21] MIPS: KVM: Allocate at least 16KB for exception handlers James Hogan
2014-04-25 15:19   ` James Hogan
2014-04-25 15:19 ` [PATCH 02/21] MIPS: KVM: Use local_flush_icache_range to fix RI on XBurst James Hogan
2014-04-25 15:19   ` James Hogan
2014-04-25 15:19 ` [PATCH 03/21] MIPS: KVM: Use tlb_write_random James Hogan
2014-04-25 15:19   ` James Hogan
2014-04-25 15:19 ` [PATCH 04/21] MIPS: KVM: Fix CP0_EBASE KVM register id James Hogan
2014-04-25 15:19   ` James Hogan
2014-04-25 16:36   ` David Daney
2014-04-25 16:36     ` David Daney
2014-04-25 19:22     ` James Hogan
2014-04-25 15:19 ` [PATCH 05/21] MIPS: KVM: Add CP0_EPC KVM register access James Hogan
2014-04-25 15:19   ` James Hogan
2014-04-25 16:44   ` David Daney
2014-04-25 20:29     ` James Hogan
2014-04-25 21:45       ` David Daney
2014-04-25 15:19 ` [PATCH 06/21] MIPS: KVM: Move KVM_{GET,SET}_ONE_REG definitions into kvm_host.h James Hogan
2014-04-25 15:19   ` James Hogan
2014-04-25 15:19 ` [PATCH 07/21] MIPS: KVM: Add CP0_Count/Compare KVM register access James Hogan
2014-04-25 15:19   ` James Hogan
2014-04-25 15:19 ` [PATCH 08/21] MIPS: KVM: Deliver guest interrupts after local_irq_disable() James Hogan
2014-04-25 15:19   ` James Hogan
2014-04-25 15:19 ` [PATCH 09/21] MIPS: KVM: Fix timer race modifying guest CP0_Cause James Hogan
2014-04-25 15:19   ` James Hogan
2014-04-25 16:55   ` David Daney
2014-04-25 20:42     ` James Hogan [this message]
2014-04-25 15:19 ` [PATCH 10/21] MIPS: KVM: Migrate hrtimer to follow VCPU James Hogan
2014-04-25 15:19   ` James Hogan
2014-04-25 15:19 ` [PATCH 11/21] MIPS: KVM: Rewrite count/compare timer emulation James Hogan
2014-04-25 15:19   ` James Hogan
2014-04-25 17:00   ` David Daney
2014-04-25 21:05     ` James Hogan
2014-04-25 15:19 ` [PATCH 12/21] MIPS: KVM: Override guest kernel timer frequency directly James Hogan
2014-04-25 15:19   ` James Hogan
2014-04-25 15:19 ` [PATCH 13/21] MIPS: KVM: Add master disable count interface James Hogan
2014-04-25 15:19   ` James Hogan
2014-04-25 15:19 ` [PATCH 14/21] MIPS: KVM: Add nanosecond count bias KVM register James Hogan
2014-04-25 15:19   ` James Hogan
2014-04-25 17:27   ` David Daney
2014-04-25 22:34     ` James Hogan
2014-04-26  9:37       ` Paolo Bonzini
2014-05-28 14:21         ` James Hogan
2014-05-28 14:21           ` James Hogan
2014-05-28 16:24           ` Paolo Bonzini
2014-04-28 12:01   ` Paolo Bonzini
2014-04-28 15:17     ` James Hogan
2014-04-28 15:42       ` Paolo Bonzini
2014-04-25 15:19 ` [PATCH 15/21] MIPS: KVM: Add count frequency " James Hogan
2014-04-25 15:19   ` James Hogan
2014-04-25 15:19 ` [PATCH 16/21] MIPS: KVM: Make kvm_mips_comparecount_{func,wakeup} static James Hogan
2014-04-25 15:19   ` James Hogan
2014-04-25 15:20 ` [PATCH 17/21] MIPS: KVM: Whitespace fixes in kvm_mips_callbacks James Hogan
2014-04-25 15:20   ` James Hogan
2014-04-25 15:20 ` [PATCH 18/21] MIPS: KVM: Fix kvm_debug bit-rottage James Hogan
2014-04-25 15:20   ` James Hogan
2014-04-25 15:20 ` [PATCH 19/21] MIPS: KVM: Remove ifdef DEBUG around kvm_debug James Hogan
2014-04-25 15:20   ` James Hogan
2014-04-25 15:20 ` [PATCH 20/21] MIPS: KVM: Quieten kvm_info() logging James Hogan
2014-04-25 15:20   ` James Hogan
2014-04-25 15:20 ` [PATCH 21/21] MIPS: KVM: Remove redundant NULL checks before kfree() James Hogan
2014-04-25 15:20   ` James Hogan
2014-04-28 12:02 ` [PATCH 00/21] MIPS: KVM: Fixes and guest timer rewrite Paolo Bonzini

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=3027239.6lcM6FV8mj@radagast \
    --to=james.hogan@imgtec.com \
    --cc=ddaney.cavm@gmail.com \
    --cc=gleb@kernel.org \
    --cc=kvm@vger.kernel.org \
    --cc=linux-mips@linux-mips.org \
    --cc=pbonzini@redhat.com \
    --cc=ralf@linux-mips.org \
    --cc=sanjayl@kymasys.com \
    /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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.