qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
From: Paolo Bonzini <pbonzini@redhat.com>
To: James Hogan <james.hogan@imgtec.com>
Cc: Aurelien Jarno <aurelien@aurel32.net>,
	Gleb Natapov <gleb@redhat.com>,
	qemu-devel@nongnu.org, kvm@vger.kernel.org,
	Sanjay Lal <sanjayl@kymasys.com>
Subject: Re: [Qemu-devel] [PATCH v4 01/10] hw/mips/cputimer: Don't start periodic timer in KVM mode
Date: Thu, 20 Mar 2014 23:36:27 +0100	[thread overview]
Message-ID: <532B6D6B.3030709@redhat.com> (raw)
In-Reply-To: <532ABBA1.3060507@imgtec.com>

Il 20/03/2014 10:57, James Hogan ha scritto:
> On 19/03/14 16:29, Paolo Bonzini wrote:
>> Il 14/03/2014 13:47, James Hogan ha scritto:
>>> From: Sanjay Lal <sanjayl@kymasys.com>
>>>
>>> Compare/Count timer interrupts are handled in-kernel for KVM, so don't
>>> bother starting it in QEMU.
>>>
>>> Signed-off-by: Sanjay Lal <sanjayl@kymasys.com>
>>> Signed-off-by: James Hogan <james.hogan@imgtec.com>
>>> Reviewed-by: Aurelien Jarno <aurelien@aurel32.net>
>>> ---
>>> Changes in v2:
>>>  - Expand commit message
>>>  - Rebase on v1.7.0
>>>  - Wrap comment
>>> ---
>>>  hw/mips/cputimer.c | 13 ++++++++++---
>>>  1 file changed, 10 insertions(+), 3 deletions(-)
>>>
>>> diff --git a/hw/mips/cputimer.c b/hw/mips/cputimer.c
>>> index c8b4b00..52570fd 100644
>>> --- a/hw/mips/cputimer.c
>>> +++ b/hw/mips/cputimer.c
>>> @@ -23,6 +23,7 @@
>>>  #include "hw/hw.h"
>>>  #include "hw/mips/cpudevs.h"
>>>  #include "qemu/timer.h"
>>> +#include "sysemu/kvm.h"
>>>
>>>  #define TIMER_FREQ    100 * 1000 * 1000
>>>
>>> @@ -141,7 +142,13 @@ static void mips_timer_cb (void *opaque)
>>>
>>>  void cpu_mips_clock_init (CPUMIPSState *env)
>>>  {
>>> -    env->timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, &mips_timer_cb, env);
>>> -    env->CP0_Compare = 0;
>>> -    cpu_mips_store_count(env, 1);
>>> +    /*
>>> +     * If we're in KVM mode, don't start the periodic timer, that is
>>> handled in
>>> +     * kernel.
>>> +     */
>>> +    if (!kvm_enabled()) {
>>> +        env->timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, &mips_timer_cb,
>>> env);
>>> +        env->CP0_Compare = 0;
>>> +        cpu_mips_store_count(env, 1);
>>> +    }
>>>  }
>>>
>>
>> I hate to make you do unrelated changes, but... initializing CP0_Compare
>> is unnecessary, it should already be 0;
> 
> You mean because of the memset in object_initialize_with_type, when
> object_new is called? Although that wouldn't handle reset, although
> technically the reset state of Compare is undefined.

No, see mips_cpu_reset:

static void mips_cpu_reset(CPUState *s)
{
    MIPSCPU *cpu = MIPS_CPU(s);
    MIPSCPUClass *mcc = MIPS_CPU_GET_CLASS(cpu);
    CPUMIPSState *env = &cpu->env;

    mcc->parent_reset(s);

    memset(env, 0, offsetof(CPUMIPSState, mvp));
    tlb_flush(s, 1);

    cpu_state_reset(env);
}

Fields before mvp are reset to zero (including CP0_Compare and CP0_Count).

> Am I right that the correct way to prevent clock drift is for
> kvm_arch_put_registers to only set the Count register if level !=
> KVM_PUT_RUNTIME_STATE?

Yes, that makes sense.  Or, better, do not provide a set_onereg 
interface for CP0_Count.  Instead, in the kernel you can base the CPU 
timer on the value of CLOCK_MONOTONIC, like this:

+static inline u64 get_monotonic_ns(void)
+{
+	struct timespec ts;
+
+	ktime_get_ts(&ts);
+	return timespec_to_ns(&ts);
+}
+

Then you provide three set_onereg interfaces.  One is normal cp0_count, 
but it is only used if the timer is not running (according to 
cp0_cause).  The second is the rate at which the timer counts 
(cp0_count_hz).  The third is used when the timer is running, and
it is:

	cp0_count_bias
	   = cp0_count * 10^9 / cp0_count_hz - get_monotonic_ns()

So when the timer is running cp0_count is computed as follows:

	cp0_count =
	  = (get_monotonic_ns() + cp0_count_bias) * cp0_count_hz / 10^9

QEMU can then set:

  cp0_count = cpu_mips_get_count(env)
  cp0_count_bias =
     cpu_mips_get_count(env) * 10^9 / cp0_count_hz - qemu_get_clock_ns(rt_clock)

Note that QEMU's qemu_get_clock_ns(rt_clock) == kernel's get_monotonic_ns().

So when the guest reads cp0_count (and the timer was running at the time
kvm_arch_put_registers was set), the kernel will return:

	cp0_count =
	 = (get_monotonic_ns() + cp0_count_bias) * cp0_count_hz / 10^9
	 = env->cp0_count
           + (get_monotonic_ns() - qemu_get_clock_ns(rt_clock)
                                 + qemu_get_clock_ns(vm_clock)) * cp0_count_hz / 10^9
	 = env->cp0_count + qemu_get_clock_ns(vm_clock) * cp0_count_hz / 10^9
         = cpu_mips_get_count(env)
	
Paolo

  reply	other threads:[~2014-03-20 22:36 UTC|newest]

Thread overview: 25+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2014-03-14 12:47 [Qemu-devel] [PATCH v4 00/10] KVM Support for MIPS32 Processors James Hogan
2014-03-14 12:47 ` [Qemu-devel] [PATCH v4 01/10] hw/mips/cputimer: Don't start periodic timer in KVM mode James Hogan
2014-03-19 16:29   ` Paolo Bonzini
2014-03-20  9:57     ` James Hogan
2014-03-20 22:36       ` Paolo Bonzini [this message]
2014-03-14 12:47 ` [Qemu-devel] [PATCH v4 02/10] hw/mips: Add API to convert KVM guest KSEG0 <-> GPA James Hogan
2014-03-14 12:47 ` [Qemu-devel] [PATCH v4 03/10] target-mips: get_physical_address: Add defines for segment bases James Hogan
2014-03-19 16:33   ` Paolo Bonzini
2014-03-14 12:47 ` [Qemu-devel] [PATCH v4 04/10] target-mips: get_physical_address: Add KVM awareness James Hogan
2014-03-19 16:33   ` Paolo Bonzini
2014-03-20 10:08     ` James Hogan
2014-03-14 12:47 ` [Qemu-devel] [PATCH v4 05/10] kvm: Allow arch to set sigmask length James Hogan
2014-03-14 12:47 ` [Qemu-devel] [PATCH v4 06/10] target-mips: kvm: Add main KVM support for MIPS James Hogan
2014-03-14 12:47 ` [Qemu-devel] [PATCH v4 07/10] hw/mips: In KVM mode, inject IRQ2 (I/O) interupts via ioctls James Hogan
2014-03-14 12:47 ` [Qemu-devel] [PATCH v4 08/10] hw/mips: malta: Add KVM support James Hogan
2014-03-19 16:39   ` Paolo Bonzini
2014-03-20 10:17     ` James Hogan
2014-03-14 12:48 ` [Qemu-devel] [PATCH v4 09/10] target-mips: Enable KVM support in build system James Hogan
2014-03-14 12:48 ` [Qemu-devel] [PATCH v4 10/10] MAINTAINERS: Add entry for MIPS KVM James Hogan
2014-03-14 13:27 ` [Qemu-devel] [PATCH v4 00/10] KVM Support for MIPS32 Processors Peter Maydell
2014-03-14 13:29   ` James Hogan
2014-03-19 16:39 ` Paolo Bonzini
2014-03-20 10:00   ` James Hogan
2014-03-20 12:44     ` Paolo Bonzini
2014-03-21 16:51       ` James Hogan

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=532B6D6B.3030709@redhat.com \
    --to=pbonzini@redhat.com \
    --cc=aurelien@aurel32.net \
    --cc=gleb@redhat.com \
    --cc=james.hogan@imgtec.com \
    --cc=kvm@vger.kernel.org \
    --cc=qemu-devel@nongnu.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 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).