Re: [PATCH] arm: Add simple arch timer test

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Mon, Sep 19, 2016 at 04:52:01PM +0200, Andrew Jones wrote:
> On Mon, Sep 19, 2016 at 01:44:40PM +0200, Alexander Graf wrote:
> > All virtualization capable ARM cores support the ARM architected virtual timer.
> > 
> > This patch adds minimalistic checks whether we can fire a virtual timer event
> > using them. It does not actually trigger an interrupt yet, as infrastructure
> > for that is missing. However, it does check whether the timer pin is marked as
> > pending on the GIC.
> > 
> > Signed-off-by: Alexander Graf <agraf@xxxxxxx>
> > ---
> >  arm/Makefile.arm64 |   2 +-
> >  arm/vtimer-test.c  | 122 +++++++++++++++++++++++++++++++++++++++++++++++++++++
> >  2 files changed, 123 insertions(+), 1 deletion(-)
> >  create mode 100644 arm/vtimer-test.c
> > 
> > diff --git a/arm/Makefile.arm64 b/arm/Makefile.arm64
> > index 0b0761c..5b3fbe8 100644
> > --- a/arm/Makefile.arm64
> > +++ b/arm/Makefile.arm64
> > @@ -12,7 +12,7 @@ cflatobjs += lib/arm64/processor.o
> >  cflatobjs += lib/arm64/spinlock.o
> >  
> >  # arm64 specific tests
> > -tests =
> > +tests = $(TEST_DIR)/vtimer-test.flat
> >  
> >  include $(TEST_DIR)/Makefile.common
> >  
> > diff --git a/arm/vtimer-test.c b/arm/vtimer-test.c
> > new file mode 100644
> > index 0000000..a3e24ce
> > --- /dev/null
> > +++ b/arm/vtimer-test.c
> > @@ -0,0 +1,122 @@
> > +/*
> > + * Unit tests for the virtual timer on the ARM virt machine
> > + *
> > + * Copyright (C) 2016, Alexander Graf <agraf@xxxxxxx>
> > + *
> > + * This work is licensed under the terms of the GNU LGPL, version 2.
> > + */
> > +#include <libcflat.h>
> > +#include <asm/io.h>
> > +
> > +#define VTIMER_CTL_ENABLE  (1 << 0)
> > +#define VTIMER_CTL_IMASK   (1 << 1)
> > +#define VTIMER_CTL_ISTATUS (1 << 2)
> > +
> > +#define VIRT_GIC_DIST_BASE 0x08000000
> > +#define GIC_DIST_PENDING_SET            0x200
> > +#define GIC_DIST_PENDING_CLEAR          0x280
> > +#define GIC_DIST_ACTIVE_SET             0x300
> > +#define GIC_DIST_ACTIVE_CLEAR           0x380
> > +
> > +#define VIRT_GIC_CPU_BASE  0x08010000
> 
> Once I get my arm/gic series in we won't need to hard code
> the gic base addresses and these gic register offsets will
> also be provided.
> 
> > +
> > +#define ARCH_TIMER_VIRT_IRQ   11
> > +#define ARCH_TIMER_S_EL1_IRQ  13
> > +#define ARCH_TIMER_NS_EL1_IRQ 14
> > +#define ARCH_TIMER_NS_EL2_IRQ 10
> 
> We can pull these out of the DT.
> 
> > +
> > +static void write_vtimer_ctl(u64 val)
> > +{
> > +	asm volatile("msr cntv_ctl_el0, %0" : : "r" (val));
> > +}
> > +
> > +static void write_vtimer_cval(u64 val)
> > +{
> > +	asm volatile("msr cntv_cval_el0, %0" : : "r" (val));
> > +}
> > +
> > +static u64 read_vtimer_ctl(void)
> > +{
> > +	u64 val;
> > +	asm volatile("mrs %0, cntv_ctl_el0" : "=r" (val));
> > +	return val;
> > +}
> > +
> > +static u64 read_vtimer_cval(void)
> > +{
> > +	u64 val;
> > +	asm volatile("mrs %0, cntv_cval_el0" : "=r" (val));
> > +	return val;
> > +}
> > +
> > +static u64 read_vtimer_val(void)
> > +{
> > +	u64 val;
> > +	asm volatile("mrs %0, cntvct_el0" : "=r" (val));
> > +	return val;
> > +}
> > +
> > +static u64 read_vtimer_freq(void)
> > +{
> > +	u64 val;
> > +	asm volatile("mrs %0, cntfrq_el0" : "=r" (val));
> > +	return val;
> > +}
> > +
> > +static bool gic_vtimer_pending(void)
> > +{
> > +	u32 *pending = (u32*)(VIRT_GIC_DIST_BASE + GIC_DIST_PENDING_SET);
> > +	return (readl(pending) & (1 << (ARCH_TIMER_VIRT_IRQ + 16)));
> 
> nit: don't need the outer ()
> 
> I think I'd like to add the PPI(irq) macro we added to QEMU for
> the +16's.
> 
> > +}
> > +
> > +static bool test_cval_10msec(void)
> > +{
> > +	u64 time_10ms = read_vtimer_freq() / 100;
> > +	u64 time_1us = time_10ms / 10000;
> > +	u64 before_timer = read_vtimer_val();
> > +	u64 after_timer, latency;
> > +
> > +	/* Program timer to fire in 10ms */
> > +	write_vtimer_cval(before_timer + time_10ms);
> > +
> > +	/* Wait for the timer to fire */
> > +	while (!(read_vtimer_ctl() & VTIMER_CTL_ISTATUS)) ;
> 
> If emulation fails to set the status bit then we'll spin forever.
> That's OK if we set the test timeout (arm/unittests.cfg:timeout
> for this test appropriately) Or, maybe can add a trial count here
> that's sufficiently large?
> 
> > +
> > +	/* It fired, check how long it took */
> > +	after_timer = read_vtimer_val();
> > +
> > +	latency = (after_timer - (before_timer + time_10ms));
> 
> nit: don't need the outer ()
> 
> Shouldn't latency be signed so we can see if the status bit was
> set too soon? Or just compare time_10ms with after - before?
> 
> > +	printf("After timer: 0x%lx\n", after_timer);
> > +	printf("Expected   : 0x%lx\n", before_timer + time_10ms);
> > +	printf("Latency    : %ld us\n", latency / time_1us);
> > +
> > +	return latency < time_10ms;
> 
> Does this mean that the threshold for success is 10ms? If so,
> then that's not too large?
> 
> > +}
> > +
> > +static void test_vtimer(void)
> > +{
> > +	printf("\n=== vtimer with busy loop ===\n");
> 
> I guess this is a subtest header, i.e. this file will get
> other subtests and headers like this one will divide up
> the test output. That's fine, but new, at least for arm tests.
> Currently we're dividing subtests with report prefixes. In
> this case, instead of the above printf, we'd do
> 
>  report_prefix_push("busy-loop");
> 
> or whatever the prefix should be. At the end of the function
> we'd pop the prefix. I prefer the prefix style as it makes
> grepping test logs easier.
> 
> > +
> > +	/* Enable the timer */
> > +	write_vtimer_cval(-1);
> 
> nit: I prefer ~0
> 
> > +	write_vtimer_ctl(VTIMER_CTL_ENABLE);
> > +
> > +	report("timer is not pending before", !gic_vtimer_pending());
> > +	report("latency is within 10ms", test_cval_10msec());
> > +	report("timer is pending after", gic_vtimer_pending());
> > +
> > +	/* Disable the timer again */
> > +	write_vtimer_ctl(0);
> > +}
> > +
> > +int main(void)
> > +{
> > +	printf("vtimer ctl:  0x%lx\n", read_vtimer_ctl());
> > +	printf("vtimer cval: 0x%lx\n", read_vtimer_cval());
> > +	printf("vtimer val:  0x%lx\n", read_vtimer_val());
> > +	printf("vtimer freq: 0x%lx\n", read_vtimer_freq());
> > +
> > +	test_vtimer();
> > +
> > +	return report_summary();
> > +}
> > -- 
> > 1.8.5.6
> >
> 
> Thanks for submitting this Alex. I'll bump the arm/gic patches up in my
> priority queue.
>

Hi Alex,

Just checking on this. Do you plan to resubmit based on the gic series?
If so, then you may want to grab v6[*], which is hopefully pretty much
the last revision, as your base.

[*] https://github.com/rhdrjones/kvm-unit-tests/commits/arm/gic-v6

Thanks,
drew
--
To unsubscribe from this list: send the line "unsubscribe kvm" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html



[Index of Archives]     [KVM ARM]     [KVM ia64]     [KVM ppc]     [Virtualization Tools]     [Spice Development]     [Libvirt]     [Libvirt Users]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite Questions]     [Linux Kernel]     [Linux SCSI]     [XFree86]
  Powered by Linux