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.
next prev parent 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).