public inbox for kvm@vger.kernel.org
 help / color / mirror / Atom feed
From: Christoffer Dall <christoffer.dall@arm.com>
To: Andrew Jones <drjones@redhat.com>
Cc: Christoffer Dall <cdall@cs.columbia.edu>,
	kvm@vger.kernel.org, marc.zyngier@arm.com,
	ynorov@caviumnetworks.com, kvmarm@lists.cs.columbia.edu,
	shihwei@cs.columbia.edu
Subject: Re: [PATCH kvm-unit-tests 2/2] arm64: add micro-bench
Date: Mon, 3 Sep 2018 13:12:36 +0200	[thread overview]
Message-ID: <20180903111236.GH4029@e113682-lin.lund.arm.com> (raw)
In-Reply-To: <20180830141733.21725-3-drjones@redhat.com>

On Thu, Aug 30, 2018 at 04:17:33PM +0200, Andrew Jones wrote:
> From: Shih-Wei Li <shihwei@cs.columbia.edu>
> 
> Here we provide the support for measuring various micro level
> operations on arm64. Measurements are currently obtained using
> timer counters. Further modifications in KVM will be required
> to support timestamping using cycle counters, as KVM now disables
> accesses to the PMU counters from the VM.
> 
> Signed-off-by: Shih-Wei Li <shihwei@cs.columbia.edu>
> Signed-off-by: Christoffer Dall <cdall@cs.columbia.edu>
> Signed-off-by: Andrew Jones <drjones@redhat.com>

Acked-by: Christoffer Dall <christoffer.dall@arm.com>

> ---
>  arm/Makefile.arm64 |   1 +
>  arm/micro-bench.c  | 213 +++++++++++++++++++++++++++++++++++++++++++++
>  arm/unittests.cfg  |   8 ++
>  3 files changed, 222 insertions(+)
>  create mode 100644 arm/micro-bench.c
> 
> diff --git a/arm/Makefile.arm64 b/arm/Makefile.arm64
> index f04bbf476763..637435c523da 100644
> --- a/arm/Makefile.arm64
> +++ b/arm/Makefile.arm64
> @@ -15,6 +15,7 @@ OBJDIRS += lib/arm64
>  
>  # arm64 specific tests
>  tests = $(TEST_DIR)/timer.flat
> +tests += $(TEST_DIR)/micro-bench.flat
>  
>  include $(SRCDIR)/$(TEST_DIR)/Makefile.common
>  
> diff --git a/arm/micro-bench.c b/arm/micro-bench.c
> new file mode 100644
> index 000000000000..76650d647f6a
> --- /dev/null
> +++ b/arm/micro-bench.c
> @@ -0,0 +1,213 @@
> +/*
> + * Measure the cost of micro level operations.
> + *
> + * This test provides support for quantifying the cost of micro level
> + * operations. To improve precision in the measurements, one should
> + * consider pinning each VCPU to a specific physical CPU (PCPU) and to
> + * ensure no other task could run on that PCPU to skew the results.
> + * This can be achieved by enabling QMP server in the QEMU command in
> + * unittest.cfg for micro-bench, allowing a client program to get the
> + * thread_id for each VCPU thread from the QMP server. Based on that
> + * information, the client program can then pin the corresponding VCPUs to
> + * dedicated PCPUs and isolate interrupts and tasks from those PCPUs.
> + *
> + * Copyright Columbia University
> + * Author: Shih-Wei Li <shihwei@cs.columbia.edu>
> + * Author: Christoffer Dall <cdall@cs.columbia.edu>
> + * Author: Andrew Jones <drjones@redhat.com>
> + *
> + * This work is licensed under the terms of the GNU LGPL, version 2.
> + */
> +#include <libcflat.h>
> +#include <asm/gic.h>
> +
> +#define NTIMES (1U << 16)
> +
> +static u32 cntfrq;
> +
> +static volatile bool ipi_ready, ipi_received;
> +static void *vgic_dist_base;
> +static void (*write_eoir)(u32 irqstat);
> +
> +static void ipi_irq_handler(struct pt_regs *regs)
> +{
> +	ipi_ready = false;
> +	ipi_received = true;
> +	gic_write_eoir(gic_read_iar());
> +	ipi_ready = true;
> +}
> +
> +static void ipi_secondary_entry(void *data)
> +{
> +	install_irq_handler(EL1H_IRQ, ipi_irq_handler);
> +	gic_enable_defaults();
> +	local_irq_enable();
> +	ipi_ready = true;
> +	while (true)
> +		cpu_relax();
> +}
> +
> +static bool test_init(void)
> +{
> +	int v = gic_init();
> +
> +	if (!v) {
> +		printf("No supported gic present, skipping tests...\n");
> +		return false;
> +	}
> +
> +	if (nr_cpus < 2) {
> +		printf("At least two cpus required, skipping tests...\n");
> +		return false;
> +	}
> +
> +	switch (v) {
> +	case 2:
> +		vgic_dist_base = gicv2_dist_base();
> +		write_eoir = gicv2_write_eoir;
> +	case 3:
> +		vgic_dist_base = gicv3_dist_base();
> +		write_eoir = gicv3_write_eoir;
> +	}
> +
> +	ipi_ready = false;
> +	gic_enable_defaults();
> +	on_cpu_async(1, ipi_secondary_entry, NULL);
> +
> +	cntfrq = get_cntfrq();
> +	printf("Timer Frequency %d Hz (Output in microseconds)\n", cntfrq);
> +
> +	return true;
> +}
> +
> +static void ipi_prep(void)
> +{
> +	unsigned tries = 1 << 28;
> +
> +	while (!ipi_ready && tries--)
> +		cpu_relax();
> +	assert(ipi_ready);
> +}
> +
> +static void ipi_exec(void)
> +{
> +	unsigned tries = 1 << 28;
> +	static int received = 0;
> +
> +	ipi_received = false;
> +
> +	gic_ipi_send_single(1, 1);
> +
> +	while (!ipi_received && tries--)
> +		cpu_relax();
> +
> +	++received;
> +	assert_msg(ipi_received, "failed to receive IPI in time, but received %d successfully\n", received);
> +}
> +
> +static void hvc_exec(void)
> +{
> +	asm volatile("mov w0, #0x4b000000; hvc #0" ::: "w0");
> +}
> +
> +static void mmio_read_user_exec(void)
> +{
> +	/*
> +	 * FIXME: Read device-id in virtio mmio here in order to
> +	 * force an exit to userspace. This address needs to be
> +	 * updated in the future if any relevant changes in QEMU
> +	 * test-dev are made.
> +	 */
> +	void *userspace_emulated_addr = (void*)0x0a000008;
> +
> +	readl(userspace_emulated_addr);
> +}
> +
> +static void mmio_read_vgic_exec(void)
> +{
> +	readl(vgic_dist_base + GICD_IIDR);
> +}
> +
> +static void eoi_exec(void)
> +{
> +	int spurious_id = 1023; /* writes to EOI are ignored */
> +
> +	/* Avoid measuring assert(..) in gic_write_eoir */
> +	write_eoir(spurious_id);
> +}
> +
> +struct exit_test {
> +	const char *name;
> +	void (*prep)(void);
> +	void (*exec)(void);
> +	bool run;
> +};
> +
> +static struct exit_test tests[] = {
> +	{"hvc",			NULL,		hvc_exec,		true},
> +	{"mmio_read_user",	NULL,		mmio_read_user_exec,	true},
> +	{"mmio_read_vgic",	NULL,		mmio_read_vgic_exec,	true},
> +	{"eoi",			NULL,		eoi_exec,		true},
> +	{"ipi",			ipi_prep,	ipi_exec,		true},
> +};
> +
> +struct ns_time {
> +	uint64_t ns;
> +	uint64_t ns_frac;
> +};
> +
> +#define PS_PER_SEC (1000 * 1000 * 1000 * 1000U)
> +static void ticks_to_ns_time(uint64_t ticks, struct ns_time *ns_time)
> +{
> +	uint64_t ps_per_tick = PS_PER_SEC / cntfrq + !!(PS_PER_SEC % cntfrq);
> +	uint64_t ps;
> +
> +	ps = ticks * ps_per_tick;
> +	ns_time->ns = ps / 1000;
> +	ns_time->ns_frac = (ps % 1000) / 100;
> +}
> +
> +static void loop_test(struct exit_test *test)
> +{
> +	uint64_t start, end, total_ticks, ntimes = NTIMES;
> +	struct ns_time total_ns, avg_ns;
> +
> +	if (test->prep)
> +		test->prep();
> +
> +	isb();
> +	start = read_sysreg(cntpct_el0);
> +	while (ntimes--)
> +		test->exec();
> +	isb();
> +	end = read_sysreg(cntpct_el0);
> +
> +	total_ticks = end - start;
> +	ticks_to_ns_time(total_ticks, &total_ns);
> +	avg_ns.ns = total_ns.ns / NTIMES;
> +	avg_ns.ns_frac = total_ns.ns_frac / NTIMES;
> +
> +	printf("%-30s%15" PRId64 ".%-15" PRId64 "%15" PRId64 ".%-15" PRId64 "\n",
> +		test->name, total_ns.ns, total_ns.ns_frac, avg_ns.ns, avg_ns.ns_frac);
> +}
> +
> +int main(int argc, char **argv)
> +{
> +	int i;
> +
> +	if (!test_init())
> +		return 1;
> +
> +	printf("\n%-30s%18s%13s%18s%13s\n", "name", "total ns", "", "avg ns", "");
> +	for (i = 0 ; i < 92; ++i)
> +		printf("%c", '-');
> +	printf("\n");
> +	for (i = 0; i < ARRAY_SIZE(tests); i++) {
> +		if (!tests[i].run)
> +			continue;
> +		assert(tests[i].name && tests[i].exec);
> +		loop_test(&tests[i]);
> +	}
> +
> +	return 0;
> +}
> diff --git a/arm/unittests.cfg b/arm/unittests.cfg
> index 44b98cfc7afd..5c8a332da004 100644
> --- a/arm/unittests.cfg
> +++ b/arm/unittests.cfg
> @@ -116,3 +116,11 @@ file = timer.flat
>  groups = timer
>  timeout = 2s
>  arch = arm64
> +
> +# Exit tests
> +[micro-bench]
> +file = micro-bench.flat
> +smp = 2
> +groups = nodefault,micro-bench
> +accel = kvm
> +arch = arm64
> -- 
> 2.17.1
> 

  reply	other threads:[~2018-09-03 11:12 UTC|newest]

Thread overview: 12+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2018-08-30 14:17 [PATCH kvm-unit-tests 0/2] Support micro operation measurement on arm64 Andrew Jones
2018-08-30 14:17 ` [PATCH kvm-unit-tests 1/2] arm/arm64: add GICD_IIDR definition Andrew Jones
2018-08-30 14:17 ` [PATCH kvm-unit-tests 2/2] arm64: add micro-bench Andrew Jones
2018-09-03 11:12   ` Christoffer Dall [this message]
2018-09-03 12:11     ` Andrew Jones
2018-09-03 13:14       ` Christoffer Dall
2018-09-03 14:59         ` Andrew Jones
2018-09-03 15:06   ` Shih-Wei Li
2018-09-03 16:31     ` Andrew Jones
2018-09-04  3:38       ` Shih-Wei Li
2018-09-04 15:02         ` Shih-Wei Li
2018-09-04 15:20           ` Andrew Jones

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=20180903111236.GH4029@e113682-lin.lund.arm.com \
    --to=christoffer.dall@arm.com \
    --cc=cdall@cs.columbia.edu \
    --cc=drjones@redhat.com \
    --cc=kvm@vger.kernel.org \
    --cc=kvmarm@lists.cs.columbia.edu \
    --cc=marc.zyngier@arm.com \
    --cc=shihwei@cs.columbia.edu \
    --cc=ynorov@caviumnetworks.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