kvm.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: "Radim Krčmář" <rkrcmar@redhat.com>
To: Wanpeng Li <kernellwp@gmail.com>
Cc: kvm@vger.kernel.org, Wanpeng Li <wanpeng.li@hotmail.com>,
	Paolo Bonzini <pbonzini@redhat.com>
Subject: Re: [PATCH] x86: apic: add APIC Timer periodic/oneshot mode latency test
Date: Tue, 25 Oct 2016 13:55:51 +0200	[thread overview]
Message-ID: <20161025115550.GE2247@potion> (raw)
In-Reply-To: <1476692917-3554-1-git-send-email-wanpeng.li@hotmail.com>

2016-10-17 16:28+0800, Wanpeng Li:
> From: Wanpeng Li <wanpeng.li@hotmail.com>
> 
> Add APIC Timer periodic/oneshot mode latency test.
> 
> Cc: Paolo Bonzini <pbonzini@redhat.com>
> Cc: Radim Krčmář <rkrcmar@redhat.com>
> Signed-off-by: Wanpeng Li <wanpeng.li@hotmail.com>
> ---
>  x86/Makefile.x86_64      |   1 +
>  x86/apic_timer_latency.c | 125 +++++++++++++++++++++++++++++++++++++++++++++++
>  x86/unittests.cfg        |   6 +++
>  3 files changed, 132 insertions(+)
>  create mode 100644 x86/apic_timer_latency.c
> 
> diff --git a/x86/Makefile.x86_64 b/x86/Makefile.x86_64
> index e166911..c9eda46 100644
> --- a/x86/Makefile.x86_64
> +++ b/x86/Makefile.x86_64
> @@ -14,6 +14,7 @@ tests = $(TEST_DIR)/access.flat $(TEST_DIR)/apic.flat \
>  tests += $(TEST_DIR)/svm.flat
>  tests += $(TEST_DIR)/vmx.flat
>  tests += $(TEST_DIR)/tscdeadline_latency.flat
> +tests += $(TEST_DIR)/apic_timer_latency.flat
>  
>  include $(TEST_DIR)/Makefile.common
>  
> diff --git a/x86/apic_timer_latency.c b/x86/apic_timer_latency.c
> new file mode 100644
> index 0000000..4dd285f
> --- /dev/null
> +++ b/x86/apic_timer_latency.c
> @@ -0,0 +1,125 @@
> +/*
> + * qemu command line | grep latency | cut -f 2 -d ":" > latency
> + *
> + * In octave:
> + * load latency
> + * min(latency)
> + * max(latency)
> + * mean(latency)
> + * hist(latency, 50)
> + */
> +
> +/*
> + * for host tracing of breakmax option:
> + *
> + * # cd /sys/kernel/debug/tracing/
> + * # echo x86-tsc > trace_clock
> + * # echo "kvm_exit kvm_entry kvm_msr" > set_event
> + * # echo "sched_switch $extratracepoints" >> set_event
> + * # echo apic_timer_fn > set_ftrace_filter
> + * # echo "function" > current_tracer
> + */
> +
> +#include "libcflat.h"
> +#include "apic.h"
> +#include "vm.h"
> +#include "smp.h"
> +#include "desc.h"
> +#include "isr.h"
> +#include "msr.h"
> +
> +static void test_lapic_existence(void)
> +{
> +    u32 lvr;
> +
> +    lvr = apic_read(APIC_LVR);
> +    printf("apic version: %x\n", lvr);
> +    report("apic existence", (u16)lvr == 0x14);
> +}
> +
> +static int tdt_count;
> +u64 exptime;
> +int delta;
> +int mode;
> +#define TABLE_SIZE 100000
> +u64 table[TABLE_SIZE];
> +volatile int table_idx;
> +volatile int hitmax = 0;
> +int breakmax = 0;
> +#define APIC_LVT_TIMER_ONE_SHOT  (0)
> +#define APIC_LVT_TIMER_VECTOR (0xee)
> +
> +static void apic_timer_isr(isr_regs_t *regs)
> +{
> +    u64 now = rdtsc();
> +    ++tdt_count;
> +
> +    if (table_idx < TABLE_SIZE && tdt_count > 1)
> +        table[table_idx++] = now - exptime;
> +
> +    if (breakmax && tdt_count > 1 && (now - exptime) > breakmax) {
> +        hitmax = 1;
> +        apic_write(APIC_EOI, 0);
> +        return;
> +    }
> +
> +    exptime = now+delta;

Two problems on this line:

1) with periodic timer, the delta is added to last expiration time, not
   to now().
   What you are measuring now is the stability of the period -- very
   important as well, but if we used now() only once, you could also
   measure the latency.

2) delta is in nanoseconds while exptime is in cycles.  Type error.

> +
> +    if (mode == APIC_LVT_TIMER_ONE_SHOT)
> +        /* Set "Initial Counter Register", which starts the timer */
> +        apic_write(APIC_TMICT, delta);

This is not deadline, so it would be better to read now() for exptime
right before the apic_write, so as little time as possible passes in
between.

> +
> +    apic_write(APIC_EOI, 0);
> +}
> +
> +static void test_apic_timer(int mode)
> +{
> +    handle_irq(APIC_LVT_TIMER_VECTOR, apic_timer_isr);
> +    irq_enable();
> +
> +	/* Periodic mode */
> +    apic_write(APIC_LVTT, mode | APIC_LVT_TIMER_VECTOR);
> +    /* Divider == 1 */
> +    apic_write(APIC_TDCR, 0x0000000b);
> +    apic_write(APIC_TMICT, delta);
> +}
> +
> +int main(int argc, char **argv)
> +{
> +    int i, size;
> +    u64 count = 0;
> +
> +    setup_vm();
> +    smp_init();
> +    setup_idt();
> +
> +    test_lapic_existence();
> +
> +    mask_pic_interrupts();
> +
> +    mode = argc <= 1 ? APIC_LVT_TIMER_PERIODIC : atol(argv[1]);
> +    delta = argc <= 2 ? 0x100000 : atol(argv[2]);
> +    size = argc <= 3 ? TABLE_SIZE : atol(argv[3]);
> +    breakmax = argc <= 4 ? 0 : atol(argv[4]);
> +    printf("breakmax=%d\n", breakmax);
> +    if (mode == APIC_LVT_TIMER_PERIODIC)
> +        printf("APIC Timer Periodic Mode\n");
> +    else if (mode == APIC_LVT_TIMER_ONE_SHOT)
> +        printf("APIC Timer Oneshot Mode\n");
> +    test_apic_timer(mode);
> +    irq_enable();
> +
> +    do {
> +        asm volatile("hlt");

We'll want to have two modes here -- testing the vmx preemption timer,
which requires that the guest runs (I use "pause" here) and the test for
hrtimer, where "hlt" is optimal.

> +    } while (!hitmax && table_idx < size);
> +
> +    for (i = 0; i < table_idx; i++) {
> +        if (hitmax && i == table_idx-1)
> +            printf("hit max: %d < ", breakmax);
> +        count += table[i];
> +        printf("latency: %" PRId64 "\n", table[i]);
> +    }
> +
> +    printf("average latency = %lu\n", count/size);
> +    return report_summary();
> +}
> diff --git a/x86/unittests.cfg b/x86/unittests.cfg
> @@ -32,6 +32,12 @@ extra_params = -cpu qemu64,+x2apic,+tsc-deadline
>  arch = x86_64
>  timeout = 30
>  
> +[apic_timer_latency]
> +file = apic_timer_latency.flat
> +smp = 1
> +arch = x86_64
> +timeout = 30

Please drop the test from x86/unittests.cfg.  Is not useful without
looking at the average latency, like tscdeadline_latency, so we don't
want to run it with ./run_tests.sh.

(And it takes way over 30 seconds for me.)

Thanks.

  reply	other threads:[~2016-10-25 11:55 UTC|newest]

Thread overview: 5+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2016-10-17  8:28 [PATCH] x86: apic: add APIC Timer periodic/oneshot mode latency test Wanpeng Li
2016-10-25 11:55 ` Radim Krčmář [this message]
2016-10-26  6:35   ` Wanpeng Li
2016-10-26 14:13     ` Radim Krčmář
2016-10-27  8:51       ` Wanpeng Li

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=20161025115550.GE2247@potion \
    --to=rkrcmar@redhat.com \
    --cc=kernellwp@gmail.com \
    --cc=kvm@vger.kernel.org \
    --cc=pbonzini@redhat.com \
    --cc=wanpeng.li@hotmail.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).