diff mbox series

[kvm-unit-tests,v2,8/8] arm64: microbench: Add vtimer latency test

Message ID 20200702030132.20252-9-wangjingyi11@huawei.com (mailing list archive)
State New, archived
Headers show
Series arm/arm64: Add IPI/LPI/vtimer latency test | expand

Commit Message

Jingyi Wang July 2, 2020, 3:01 a.m. UTC
Trigger PPIs by setting up a 10msec timer and test the latency.

Signed-off-by: Jingyi Wang <wangjingyi11@huawei.com>
---
 arm/micro-bench.c | 56 ++++++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 55 insertions(+), 1 deletion(-)

Comments

Andrew Jones July 2, 2020, 5:44 a.m. UTC | #1
On Thu, Jul 02, 2020 at 11:01:32AM +0800, Jingyi Wang wrote:
> Trigger PPIs by setting up a 10msec timer and test the latency.
> 
> Signed-off-by: Jingyi Wang <wangjingyi11@huawei.com>
> ---
>  arm/micro-bench.c | 56 ++++++++++++++++++++++++++++++++++++++++++++++-
>  1 file changed, 55 insertions(+), 1 deletion(-)
> 
> diff --git a/arm/micro-bench.c b/arm/micro-bench.c
> index 4c962b7..6822084 100644
> --- a/arm/micro-bench.c
> +++ b/arm/micro-bench.c
> @@ -23,8 +23,13 @@
>  #include <asm/gic-v3-its.h>
>  
>  #define NTIMES (1U << 16)
> +#define NTIMES_MINOR (1U << 8)

As mentioned in the previous patch, no need for this define, just put the
number in the table.

>  #define MAX_NS (5 * 1000 * 1000 * 1000UL)
>  
> +#define IRQ_VTIMER		27

As you can see in the timer test (arm/timer.c) we've been doing our best
not to hard code stuff like this. I'd prefer we don't start now. Actually,
since the timer irqs may come in handy for other tests I'll extract the
DT stuff from arm/timer.c and save those irqs at setup time. I'll send
a patch for that now, then this patch can use the new saved state.

> +#define ARCH_TIMER_CTL_ENABLE	(1 << 0)
> +#define ARCH_TIMER_CTL_IMASK	(1 << 1)

I'll put these defines somewhere common as well.

> +
>  static u32 cntfrq;
>  
>  static volatile bool irq_ready, irq_received;
> @@ -33,9 +38,16 @@ static void (*write_eoir)(u32 irqstat);
>  
>  static void gic_irq_handler(struct pt_regs *regs)
>  {
> +	u32 irqstat = gic_read_iar();
>  	irq_ready = false;
>  	irq_received = true;
> -	gic_write_eoir(gic_read_iar());
> +	gic_write_eoir(irqstat);
> +
> +	if (irqstat == IRQ_VTIMER) {
> +		write_sysreg((ARCH_TIMER_CTL_IMASK | ARCH_TIMER_CTL_ENABLE),
> +			     cntv_ctl_el0);
> +		isb();
> +	}
>  	irq_ready = true;
>  }
>  
> @@ -189,6 +201,47 @@ static void lpi_exec(void)
>  	assert_msg(irq_received, "failed to receive LPI in time, but received %d successfully\n", received);
>  }
>  
> +static bool timer_prep(void)
> +{
> +	static void *gic_isenabler;
> +
> +	gic_enable_defaults();
> +	install_irq_handler(EL1H_IRQ, gic_irq_handler);
> +	local_irq_enable();
> +
> +	gic_isenabler = gicv3_sgi_base() + GICR_ISENABLER0;
> +	writel(1 << 27, gic_isenabler);

You should have used your define here.

> +	write_sysreg(ARCH_TIMER_CTL_ENABLE, cntv_ctl_el0);
> +	isb();
> +
> +	gic_prep_common();
> +	return true;
> +}
> +
> +static void timer_exec(void)
> +{
> +	u64 before_timer;
> +	u64 timer_10ms;
> +	unsigned tries = 1 << 28;
> +	static int received = 0;
> +
> +	irq_received = false;
> +
> +	before_timer = read_sysreg(cntvct_el0);
> +	timer_10ms = cntfrq / 100;
> +	write_sysreg(before_timer + timer_10ms, cntv_cval_el0);
> +	write_sysreg(ARCH_TIMER_CTL_ENABLE, cntv_ctl_el0);
> +	isb();
> +
> +	while (!irq_received && tries--)
> +		cpu_relax();
> +
> +	if (irq_received)
> +		++received;
> +
> +	assert_msg(irq_received, "failed to receive PPI in time, but received %d successfully\n", received);
> +}
> +
>  static void hvc_exec(void)
>  {
>  	asm volatile("mov w0, #0x4b000000; hvc #0" ::: "w0");
> @@ -236,6 +289,7 @@ static struct exit_test tests[] = {
>  	{"ipi",			ipi_prep,	ipi_exec,		NTIMES,		true},
>  	{"ipi_hw",		ipi_hw_prep,	ipi_exec,		NTIMES,		true},
>  	{"lpi",			lpi_prep,	lpi_exec,		NTIMES,		true},
> +	{"timer_10ms",		timer_prep,	timer_exec,		NTIMES_MINOR,	true},
>  };
>  
>  struct ns_time {
> -- 
> 2.19.1
> 
> 

Thanks,
drew
Jingyi Wang July 2, 2020, 8:56 a.m. UTC | #2
Hi Drew,

On 7/2/2020 1:44 PM, Andrew Jones wrote:
> On Thu, Jul 02, 2020 at 11:01:32AM +0800, Jingyi Wang wrote:
>> Trigger PPIs by setting up a 10msec timer and test the latency.
>>
>> Signed-off-by: Jingyi Wang <wangjingyi11@huawei.com>
>> ---
>>   arm/micro-bench.c | 56 ++++++++++++++++++++++++++++++++++++++++++++++-
>>   1 file changed, 55 insertions(+), 1 deletion(-)
>>
>> diff --git a/arm/micro-bench.c b/arm/micro-bench.c
>> index 4c962b7..6822084 100644
>> --- a/arm/micro-bench.c
>> +++ b/arm/micro-bench.c
>> @@ -23,8 +23,13 @@
>>   #include <asm/gic-v3-its.h>
>>   
>>   #define NTIMES (1U << 16)
>> +#define NTIMES_MINOR (1U << 8)
> 
> As mentioned in the previous patch, no need for this define, just put the
> number in the table.
> 
>>   #define MAX_NS (5 * 1000 * 1000 * 1000UL)
>>   
>> +#define IRQ_VTIMER		27
> 
> As you can see in the timer test (arm/timer.c) we've been doing our best
> not to hard code stuff like this. I'd prefer we don't start now. Actually,
> since the timer irqs may come in handy for other tests I'll extract the
> DT stuff from arm/timer.c and save those irqs at setup time. I'll send
> a patch for that now, then this patch can use the new saved state.
> 
>> +#define ARCH_TIMER_CTL_ENABLE	(1 << 0)
>> +#define ARCH_TIMER_CTL_IMASK	(1 << 1)
> 
> I'll put these defines somewhere common as well.
> 

The common implement for timer irqs will be much helpful, I will
rebase this patch on that.

>> +
>>   static u32 cntfrq;
>>   
>>   static volatile bool irq_ready, irq_received;
>> @@ -33,9 +38,16 @@ static void (*write_eoir)(u32 irqstat);
>>   
>>   static void gic_irq_handler(struct pt_regs *regs)
>>   {
>> +	u32 irqstat = gic_read_iar();
>>   	irq_ready = false;
>>   	irq_received = true;
>> -	gic_write_eoir(gic_read_iar());
>> +	gic_write_eoir(irqstat);
>> +
>> +	if (irqstat == IRQ_VTIMER) {
>> +		write_sysreg((ARCH_TIMER_CTL_IMASK | ARCH_TIMER_CTL_ENABLE),
>> +			     cntv_ctl_el0);
>> +		isb();
>> +	}
>>   	irq_ready = true;
>>   }
>>   
>> @@ -189,6 +201,47 @@ static void lpi_exec(void)
>>   	assert_msg(irq_received, "failed to receive LPI in time, but received %d successfully\n", received);
>>   }
>>   
>> +static bool timer_prep(void)
>> +{
>> +	static void *gic_isenabler;
>> +
>> +	gic_enable_defaults();
>> +	install_irq_handler(EL1H_IRQ, gic_irq_handler);
>> +	local_irq_enable();
>> +
>> +	gic_isenabler = gicv3_sgi_base() + GICR_ISENABLER0;
>> +	writel(1 << 27, gic_isenabler);
> 
> You should have used your define here.
> 

Done.

>> +	write_sysreg(ARCH_TIMER_CTL_ENABLE, cntv_ctl_el0);
>> +	isb();
>> +
>> +	gic_prep_common();
>> +	return true;
>> +}
>> +
>> +static void timer_exec(void)
>> +{
>> +	u64 before_timer;
>> +	u64 timer_10ms;
>> +	unsigned tries = 1 << 28;
>> +	static int received = 0;
>> +
>> +	irq_received = false;
>> +
>> +	before_timer = read_sysreg(cntvct_el0);
>> +	timer_10ms = cntfrq / 100;
>> +	write_sysreg(before_timer + timer_10ms, cntv_cval_el0);
>> +	write_sysreg(ARCH_TIMER_CTL_ENABLE, cntv_ctl_el0);
>> +	isb();
>> +
>> +	while (!irq_received && tries--)
>> +		cpu_relax();
>> +
>> +	if (irq_received)
>> +		++received;
>> +
>> +	assert_msg(irq_received, "failed to receive PPI in time, but received %d successfully\n", received);
>> +}
>> +
>>   static void hvc_exec(void)
>>   {
>>   	asm volatile("mov w0, #0x4b000000; hvc #0" ::: "w0");
>> @@ -236,6 +289,7 @@ static struct exit_test tests[] = {
>>   	{"ipi",			ipi_prep,	ipi_exec,		NTIMES,		true},
>>   	{"ipi_hw",		ipi_hw_prep,	ipi_exec,		NTIMES,		true},
>>   	{"lpi",			lpi_prep,	lpi_exec,		NTIMES,		true},
>> +	{"timer_10ms",		timer_prep,	timer_exec,		NTIMES_MINOR,	true},
>>   };
>>   
>>   struct ns_time {
>> -- 
>> 2.19.1
>>
>>
> 
> Thanks,
> drew
> 
> 
> .
> 

Thanks,
Jingyi
Eric Auger July 2, 2020, 1:36 p.m. UTC | #3
Hi Jingyi,

On 7/2/20 5:01 AM, Jingyi Wang wrote:
> Trigger PPIs by setting up a 10msec timer and test the latency.

so for each iteration the accumulated valued is 10 ms + latency, right?
and what is printed at the end does include the accumulated periods.
Wouldn't it make sense to have a test->post() that substract this value.
You would need to store the actual number of iterations.

Thanks

Eric
> 
> Signed-off-by: Jingyi Wang <wangjingyi11@huawei.com>
> ---
>  arm/micro-bench.c | 56 ++++++++++++++++++++++++++++++++++++++++++++++-
>  1 file changed, 55 insertions(+), 1 deletion(-)
> 
> diff --git a/arm/micro-bench.c b/arm/micro-bench.c
> index 4c962b7..6822084 100644
> --- a/arm/micro-bench.c
> +++ b/arm/micro-bench.c
> @@ -23,8 +23,13 @@
>  #include <asm/gic-v3-its.h>
>  
>  #define NTIMES (1U << 16)
> +#define NTIMES_MINOR (1U << 8)
>  #define MAX_NS (5 * 1000 * 1000 * 1000UL)
>  
> +#define IRQ_VTIMER		27
> +#define ARCH_TIMER_CTL_ENABLE	(1 << 0)
> +#define ARCH_TIMER_CTL_IMASK	(1 << 1)
> +
>  static u32 cntfrq;
>  
>  static volatile bool irq_ready, irq_received;
> @@ -33,9 +38,16 @@ static void (*write_eoir)(u32 irqstat);
>  
>  static void gic_irq_handler(struct pt_regs *regs)
>  {
> +	u32 irqstat = gic_read_iar();
>  	irq_ready = false;
>  	irq_received = true;
> -	gic_write_eoir(gic_read_iar());
> +	gic_write_eoir(irqstat);
> +
> +	if (irqstat == IRQ_VTIMER) {
> +		write_sysreg((ARCH_TIMER_CTL_IMASK | ARCH_TIMER_CTL_ENABLE),
> +			     cntv_ctl_el0);
> +		isb();
> +	}
>  	irq_ready = true;
>  }
>  
> @@ -189,6 +201,47 @@ static void lpi_exec(void)
>  	assert_msg(irq_received, "failed to receive LPI in time, but received %d successfully\n", received);
>  }
>  
> +static bool timer_prep(void)
> +{
> +	static void *gic_isenabler;
> +
> +	gic_enable_defaults();
> +	install_irq_handler(EL1H_IRQ, gic_irq_handler);
> +	local_irq_enable();
> +
> +	gic_isenabler = gicv3_sgi_base() + GICR_ISENABLER0;
> +	writel(1 << 27, gic_isenabler);
> +	write_sysreg(ARCH_TIMER_CTL_ENABLE, cntv_ctl_el0);
> +	isb();
> +
> +	gic_prep_common();
> +	return true;
> +}
> +
> +static void timer_exec(void)
> +{
> +	u64 before_timer;
> +	u64 timer_10ms;
> +	unsigned tries = 1 << 28;
> +	static int received = 0;
> +
> +	irq_received = false;
> +
> +	before_timer = read_sysreg(cntvct_el0);
> +	timer_10ms = cntfrq / 100;
> +	write_sysreg(before_timer + timer_10ms, cntv_cval_el0);
> +	write_sysreg(ARCH_TIMER_CTL_ENABLE, cntv_ctl_el0);
> +	isb();
> +
> +	while (!irq_received && tries--)
> +		cpu_relax();
> +
> +	if (irq_received)
> +		++received;
> +
> +	assert_msg(irq_received, "failed to receive PPI in time, but received %d successfully\n", received);
> +}
> +
>  static void hvc_exec(void)
>  {
>  	asm volatile("mov w0, #0x4b000000; hvc #0" ::: "w0");
> @@ -236,6 +289,7 @@ static struct exit_test tests[] = {
>  	{"ipi",			ipi_prep,	ipi_exec,		NTIMES,		true},
>  	{"ipi_hw",		ipi_hw_prep,	ipi_exec,		NTIMES,		true},
>  	{"lpi",			lpi_prep,	lpi_exec,		NTIMES,		true},
> +	{"timer_10ms",		timer_prep,	timer_exec,		NTIMES_MINOR,	true},
>  };
>  
>  struct ns_time {
>
Jingyi Wang July 3, 2020, 7:41 a.m. UTC | #4
Hi Eric, Drew,

On 7/2/2020 9:36 PM, Auger Eric wrote:
> Hi Jingyi,
> 
> On 7/2/20 5:01 AM, Jingyi Wang wrote:
>> Trigger PPIs by setting up a 10msec timer and test the latency.
> 
> so for each iteration the accumulated valued is 10 ms + latency, right?
> and what is printed at the end does include the accumulated periods.
> Wouldn't it make sense to have a test->post() that substract this value.
> You would need to store the actual number of iterations.
> 
> Thanks
> 
> Eric

That's right, the result indicates 10ms + latency, which is a 10msec
timer actually costs. I think using the difference instead of the total
time cost can be a little confusing here. Maybe we can use test->post()
to get the latency and print an extra result in logs? Do you have any
opinions on that?

Thanks,
Jingyi

>>
>> Signed-off-by: Jingyi Wang <wangjingyi11@huawei.com>
>> ---
>>   arm/micro-bench.c | 56 ++++++++++++++++++++++++++++++++++++++++++++++-
>>   1 file changed, 55 insertions(+), 1 deletion(-)
>>
>> diff --git a/arm/micro-bench.c b/arm/micro-bench.c
>> index 4c962b7..6822084 100644
>> --- a/arm/micro-bench.c
>> +++ b/arm/micro-bench.c
>> @@ -23,8 +23,13 @@
>>   #include <asm/gic-v3-its.h>
>>   
>>   #define NTIMES (1U << 16)
>> +#define NTIMES_MINOR (1U << 8)
>>   #define MAX_NS (5 * 1000 * 1000 * 1000UL)
>>   
>> +#define IRQ_VTIMER		27
>> +#define ARCH_TIMER_CTL_ENABLE	(1 << 0)
>> +#define ARCH_TIMER_CTL_IMASK	(1 << 1)
>> +
>>   static u32 cntfrq;
>>   
>>   static volatile bool irq_ready, irq_received;
>> @@ -33,9 +38,16 @@ static void (*write_eoir)(u32 irqstat);
>>   
>>   static void gic_irq_handler(struct pt_regs *regs)
>>   {
>> +	u32 irqstat = gic_read_iar();
>>   	irq_ready = false;
>>   	irq_received = true;
>> -	gic_write_eoir(gic_read_iar());
>> +	gic_write_eoir(irqstat);
>> +
>> +	if (irqstat == IRQ_VTIMER) {
>> +		write_sysreg((ARCH_TIMER_CTL_IMASK | ARCH_TIMER_CTL_ENABLE),
>> +			     cntv_ctl_el0);
>> +		isb();
>> +	}
>>   	irq_ready = true;
>>   }
>>   
>> @@ -189,6 +201,47 @@ static void lpi_exec(void)
>>   	assert_msg(irq_received, "failed to receive LPI in time, but received %d successfully\n", received);
>>   }
>>   
>> +static bool timer_prep(void)
>> +{
>> +	static void *gic_isenabler;
>> +
>> +	gic_enable_defaults();
>> +	install_irq_handler(EL1H_IRQ, gic_irq_handler);
>> +	local_irq_enable();
>> +
>> +	gic_isenabler = gicv3_sgi_base() + GICR_ISENABLER0;
>> +	writel(1 << 27, gic_isenabler);
>> +	write_sysreg(ARCH_TIMER_CTL_ENABLE, cntv_ctl_el0);
>> +	isb();
>> +
>> +	gic_prep_common();
>> +	return true;
>> +}
>> +
>> +static void timer_exec(void)
>> +{
>> +	u64 before_timer;
>> +	u64 timer_10ms;
>> +	unsigned tries = 1 << 28;
>> +	static int received = 0;
>> +
>> +	irq_received = false;
>> +
>> +	before_timer = read_sysreg(cntvct_el0);
>> +	timer_10ms = cntfrq / 100;
>> +	write_sysreg(before_timer + timer_10ms, cntv_cval_el0);
>> +	write_sysreg(ARCH_TIMER_CTL_ENABLE, cntv_ctl_el0);
>> +	isb();
>> +
>> +	while (!irq_received && tries--)
>> +		cpu_relax();
>> +
>> +	if (irq_received)
>> +		++received;
>> +
>> +	assert_msg(irq_received, "failed to receive PPI in time, but received %d successfully\n", received);
>> +}
>> +
>>   static void hvc_exec(void)
>>   {
>>   	asm volatile("mov w0, #0x4b000000; hvc #0" ::: "w0");
>> @@ -236,6 +289,7 @@ static struct exit_test tests[] = {
>>   	{"ipi",			ipi_prep,	ipi_exec,		NTIMES,		true},
>>   	{"ipi_hw",		ipi_hw_prep,	ipi_exec,		NTIMES,		true},
>>   	{"lpi",			lpi_prep,	lpi_exec,		NTIMES,		true},
>> +	{"timer_10ms",		timer_prep,	timer_exec,		NTIMES_MINOR,	true},
>>   };
>>   
>>   struct ns_time {
>>
> 
> 
> .
>
Eric Auger July 3, 2020, 7:45 a.m. UTC | #5
Hi Jingyi,

On 7/3/20 9:41 AM, Jingyi Wang wrote:
> Hi Eric, Drew,
> 
> On 7/2/2020 9:36 PM, Auger Eric wrote:
>> Hi Jingyi,
>>
>> On 7/2/20 5:01 AM, Jingyi Wang wrote:
>>> Trigger PPIs by setting up a 10msec timer and test the latency.
>>
>> so for each iteration the accumulated valued is 10 ms + latency, right?
>> and what is printed at the end does include the accumulated periods.
>> Wouldn't it make sense to have a test->post() that substract this value.
>> You would need to store the actual number of iterations.
>>
>> Thanks
>>
>> Eric
> 
> That's right, the result indicates 10ms + latency, which is a 10msec
> timer actually costs. I think using the difference instead of the total
> time cost can be a little confusing here. Maybe we can use test->post()
> to get the latency and print an extra result in logs? Do you have any
> opinions on that?

for other interrupts you only print the latency, right? Here if I
understand correctly you use the timer to trigger the PPI but still you
care about the latency, hence my suggestion to only print the latency.

Thanks

Eric
> 
> Thanks,
> Jingyi
> 
>>>
>>> Signed-off-by: Jingyi Wang <wangjingyi11@huawei.com>
>>> ---
>>>   arm/micro-bench.c | 56 ++++++++++++++++++++++++++++++++++++++++++++++-
>>>   1 file changed, 55 insertions(+), 1 deletion(-)
>>>
>>> diff --git a/arm/micro-bench.c b/arm/micro-bench.c
>>> index 4c962b7..6822084 100644
>>> --- a/arm/micro-bench.c
>>> +++ b/arm/micro-bench.c
>>> @@ -23,8 +23,13 @@
>>>   #include <asm/gic-v3-its.h>
>>>     #define NTIMES (1U << 16)
>>> +#define NTIMES_MINOR (1U << 8)
>>>   #define MAX_NS (5 * 1000 * 1000 * 1000UL)
>>>   +#define IRQ_VTIMER        27
>>> +#define ARCH_TIMER_CTL_ENABLE    (1 << 0)
>>> +#define ARCH_TIMER_CTL_IMASK    (1 << 1)
>>> +
>>>   static u32 cntfrq;
>>>     static volatile bool irq_ready, irq_received;
>>> @@ -33,9 +38,16 @@ static void (*write_eoir)(u32 irqstat);
>>>     static void gic_irq_handler(struct pt_regs *regs)
>>>   {
>>> +    u32 irqstat = gic_read_iar();
>>>       irq_ready = false;
>>>       irq_received = true;
>>> -    gic_write_eoir(gic_read_iar());
>>> +    gic_write_eoir(irqstat);
>>> +
>>> +    if (irqstat == IRQ_VTIMER) {
>>> +        write_sysreg((ARCH_TIMER_CTL_IMASK | ARCH_TIMER_CTL_ENABLE),
>>> +                 cntv_ctl_el0);
>>> +        isb();
>>> +    }
>>>       irq_ready = true;
>>>   }
>>>   @@ -189,6 +201,47 @@ static void lpi_exec(void)
>>>       assert_msg(irq_received, "failed to receive LPI in time, but
>>> received %d successfully\n", received);
>>>   }
>>>   +static bool timer_prep(void)
>>> +{
>>> +    static void *gic_isenabler;
>>> +
>>> +    gic_enable_defaults();
>>> +    install_irq_handler(EL1H_IRQ, gic_irq_handler);
>>> +    local_irq_enable();
>>> +
>>> +    gic_isenabler = gicv3_sgi_base() + GICR_ISENABLER0;
>>> +    writel(1 << 27, gic_isenabler);
>>> +    write_sysreg(ARCH_TIMER_CTL_ENABLE, cntv_ctl_el0);
>>> +    isb();
>>> +
>>> +    gic_prep_common();
>>> +    return true;
>>> +}
>>> +
>>> +static void timer_exec(void)
>>> +{
>>> +    u64 before_timer;
>>> +    u64 timer_10ms;
>>> +    unsigned tries = 1 << 28;
>>> +    static int received = 0;
>>> +
>>> +    irq_received = false;
>>> +
>>> +    before_timer = read_sysreg(cntvct_el0);
>>> +    timer_10ms = cntfrq / 100;
>>> +    write_sysreg(before_timer + timer_10ms, cntv_cval_el0);
>>> +    write_sysreg(ARCH_TIMER_CTL_ENABLE, cntv_ctl_el0);
>>> +    isb();
>>> +
>>> +    while (!irq_received && tries--)
>>> +        cpu_relax();
>>> +
>>> +    if (irq_received)
>>> +        ++received;
>>> +
>>> +    assert_msg(irq_received, "failed to receive PPI in time, but
>>> received %d successfully\n", received);
>>> +}
>>> +
>>>   static void hvc_exec(void)
>>>   {
>>>       asm volatile("mov w0, #0x4b000000; hvc #0" ::: "w0");
>>> @@ -236,6 +289,7 @@ static struct exit_test tests[] = {
>>>       {"ipi",            ipi_prep,    ipi_exec,        NTIMES,       
>>> true},
>>>       {"ipi_hw",        ipi_hw_prep,    ipi_exec,       
>>> NTIMES,        true},
>>>       {"lpi",            lpi_prep,    lpi_exec,        NTIMES,       
>>> true},
>>> +    {"timer_10ms",        timer_prep,    timer_exec,       
>>> NTIMES_MINOR,    true},
>>>   };
>>>     struct ns_time {
>>>
>>
>>
>> .
>>
>
Jingyi Wang July 6, 2020, 12:23 p.m. UTC | #6
Hi Eric,

On 7/3/2020 3:45 PM, Auger Eric wrote:
> Hi Jingyi,
> 
> On 7/3/20 9:41 AM, Jingyi Wang wrote:
>> Hi Eric, Drew,
>>
>> On 7/2/2020 9:36 PM, Auger Eric wrote:
>>> Hi Jingyi,
>>>
>>> On 7/2/20 5:01 AM, Jingyi Wang wrote:
>>>> Trigger PPIs by setting up a 10msec timer and test the latency.
>>>
>>> so for each iteration the accumulated valued is 10 ms + latency, right?
>>> and what is printed at the end does include the accumulated periods.
>>> Wouldn't it make sense to have a test->post() that substract this value.
>>> You would need to store the actual number of iterations.
>>>
>>> Thanks
>>>
>>> Eric
>>
>> That's right, the result indicates 10ms + latency, which is a 10msec
>> timer actually costs. I think using the difference instead of the total
>> time cost can be a little confusing here. Maybe we can use test->post()
>> to get the latency and print an extra result in logs? Do you have any
>> opinions on that?
> 
> for other interrupts you only print the latency, right? Here if I
> understand correctly you use the timer to trigger the PPI but still you
> care about the latency, hence my suggestion to only print the latency.
> 
> Thanks
> 
> Eric

Okay, I will create a separate patch to extract the vtimer difference
in the next version, thanks for you suggestion.

Thanks,
Jingyi

>>
>> Thanks,
>> Jingyi
>>
>>>>
>>>> Signed-off-by: Jingyi Wang <wangjingyi11@huawei.com>
>>>> ---
>>>>    arm/micro-bench.c | 56 ++++++++++++++++++++++++++++++++++++++++++++++-
>>>>    1 file changed, 55 insertions(+), 1 deletion(-)
>>>>
>>>> diff --git a/arm/micro-bench.c b/arm/micro-bench.c
>>>> index 4c962b7..6822084 100644
>>>> --- a/arm/micro-bench.c
>>>> +++ b/arm/micro-bench.c
>>>> @@ -23,8 +23,13 @@
>>>>    #include <asm/gic-v3-its.h>
>>>>      #define NTIMES (1U << 16)
>>>> +#define NTIMES_MINOR (1U << 8)
>>>>    #define MAX_NS (5 * 1000 * 1000 * 1000UL)
>>>>    +#define IRQ_VTIMER        27
>>>> +#define ARCH_TIMER_CTL_ENABLE    (1 << 0)
>>>> +#define ARCH_TIMER_CTL_IMASK    (1 << 1)
>>>> +
>>>>    static u32 cntfrq;
>>>>      static volatile bool irq_ready, irq_received;
>>>> @@ -33,9 +38,16 @@ static void (*write_eoir)(u32 irqstat);
>>>>      static void gic_irq_handler(struct pt_regs *regs)
>>>>    {
>>>> +    u32 irqstat = gic_read_iar();
>>>>        irq_ready = false;
>>>>        irq_received = true;
>>>> -    gic_write_eoir(gic_read_iar());
>>>> +    gic_write_eoir(irqstat);
>>>> +
>>>> +    if (irqstat == IRQ_VTIMER) {
>>>> +        write_sysreg((ARCH_TIMER_CTL_IMASK | ARCH_TIMER_CTL_ENABLE),
>>>> +                 cntv_ctl_el0);
>>>> +        isb();
>>>> +    }
>>>>        irq_ready = true;
>>>>    }
>>>>    @@ -189,6 +201,47 @@ static void lpi_exec(void)
>>>>        assert_msg(irq_received, "failed to receive LPI in time, but
>>>> received %d successfully\n", received);
>>>>    }
>>>>    +static bool timer_prep(void)
>>>> +{
>>>> +    static void *gic_isenabler;
>>>> +
>>>> +    gic_enable_defaults();
>>>> +    install_irq_handler(EL1H_IRQ, gic_irq_handler);
>>>> +    local_irq_enable();
>>>> +
>>>> +    gic_isenabler = gicv3_sgi_base() + GICR_ISENABLER0;
>>>> +    writel(1 << 27, gic_isenabler);
>>>> +    write_sysreg(ARCH_TIMER_CTL_ENABLE, cntv_ctl_el0);
>>>> +    isb();
>>>> +
>>>> +    gic_prep_common();
>>>> +    return true;
>>>> +}
>>>> +
>>>> +static void timer_exec(void)
>>>> +{
>>>> +    u64 before_timer;
>>>> +    u64 timer_10ms;
>>>> +    unsigned tries = 1 << 28;
>>>> +    static int received = 0;
>>>> +
>>>> +    irq_received = false;
>>>> +
>>>> +    before_timer = read_sysreg(cntvct_el0);
>>>> +    timer_10ms = cntfrq / 100;
>>>> +    write_sysreg(before_timer + timer_10ms, cntv_cval_el0);
>>>> +    write_sysreg(ARCH_TIMER_CTL_ENABLE, cntv_ctl_el0);
>>>> +    isb();
>>>> +
>>>> +    while (!irq_received && tries--)
>>>> +        cpu_relax();
>>>> +
>>>> +    if (irq_received)
>>>> +        ++received;
>>>> +
>>>> +    assert_msg(irq_received, "failed to receive PPI in time, but
>>>> received %d successfully\n", received);
>>>> +}
>>>> +
>>>>    static void hvc_exec(void)
>>>>    {
>>>>        asm volatile("mov w0, #0x4b000000; hvc #0" ::: "w0");
>>>> @@ -236,6 +289,7 @@ static struct exit_test tests[] = {
>>>>        {"ipi",            ipi_prep,    ipi_exec,        NTIMES,
>>>> true},
>>>>        {"ipi_hw",        ipi_hw_prep,    ipi_exec,
>>>> NTIMES,        true},
>>>>        {"lpi",            lpi_prep,    lpi_exec,        NTIMES,
>>>> true},
>>>> +    {"timer_10ms",        timer_prep,    timer_exec,
>>>> NTIMES_MINOR,    true},
>>>>    };
>>>>      struct ns_time {
>>>>
>>>
>>>
>>> .
>>>
>>
> 
> 
> .
>
diff mbox series

Patch

diff --git a/arm/micro-bench.c b/arm/micro-bench.c
index 4c962b7..6822084 100644
--- a/arm/micro-bench.c
+++ b/arm/micro-bench.c
@@ -23,8 +23,13 @@ 
 #include <asm/gic-v3-its.h>
 
 #define NTIMES (1U << 16)
+#define NTIMES_MINOR (1U << 8)
 #define MAX_NS (5 * 1000 * 1000 * 1000UL)
 
+#define IRQ_VTIMER		27
+#define ARCH_TIMER_CTL_ENABLE	(1 << 0)
+#define ARCH_TIMER_CTL_IMASK	(1 << 1)
+
 static u32 cntfrq;
 
 static volatile bool irq_ready, irq_received;
@@ -33,9 +38,16 @@  static void (*write_eoir)(u32 irqstat);
 
 static void gic_irq_handler(struct pt_regs *regs)
 {
+	u32 irqstat = gic_read_iar();
 	irq_ready = false;
 	irq_received = true;
-	gic_write_eoir(gic_read_iar());
+	gic_write_eoir(irqstat);
+
+	if (irqstat == IRQ_VTIMER) {
+		write_sysreg((ARCH_TIMER_CTL_IMASK | ARCH_TIMER_CTL_ENABLE),
+			     cntv_ctl_el0);
+		isb();
+	}
 	irq_ready = true;
 }
 
@@ -189,6 +201,47 @@  static void lpi_exec(void)
 	assert_msg(irq_received, "failed to receive LPI in time, but received %d successfully\n", received);
 }
 
+static bool timer_prep(void)
+{
+	static void *gic_isenabler;
+
+	gic_enable_defaults();
+	install_irq_handler(EL1H_IRQ, gic_irq_handler);
+	local_irq_enable();
+
+	gic_isenabler = gicv3_sgi_base() + GICR_ISENABLER0;
+	writel(1 << 27, gic_isenabler);
+	write_sysreg(ARCH_TIMER_CTL_ENABLE, cntv_ctl_el0);
+	isb();
+
+	gic_prep_common();
+	return true;
+}
+
+static void timer_exec(void)
+{
+	u64 before_timer;
+	u64 timer_10ms;
+	unsigned tries = 1 << 28;
+	static int received = 0;
+
+	irq_received = false;
+
+	before_timer = read_sysreg(cntvct_el0);
+	timer_10ms = cntfrq / 100;
+	write_sysreg(before_timer + timer_10ms, cntv_cval_el0);
+	write_sysreg(ARCH_TIMER_CTL_ENABLE, cntv_ctl_el0);
+	isb();
+
+	while (!irq_received && tries--)
+		cpu_relax();
+
+	if (irq_received)
+		++received;
+
+	assert_msg(irq_received, "failed to receive PPI in time, but received %d successfully\n", received);
+}
+
 static void hvc_exec(void)
 {
 	asm volatile("mov w0, #0x4b000000; hvc #0" ::: "w0");
@@ -236,6 +289,7 @@  static struct exit_test tests[] = {
 	{"ipi",			ipi_prep,	ipi_exec,		NTIMES,		true},
 	{"ipi_hw",		ipi_hw_prep,	ipi_exec,		NTIMES,		true},
 	{"lpi",			lpi_prep,	lpi_exec,		NTIMES,		true},
+	{"timer_10ms",		timer_prep,	timer_exec,		NTIMES_MINOR,	true},
 };
 
 struct ns_time {