RE: [PATCH 1/2] arm: irqchip: add lock in irqchip_inject_pending

2019-12-05 Thread Peng Fan
> Subject: Re: [PATCH 1/2] arm: irqchip: add lock in irqchip_inject_pending
> 
> On 05.12.19 09:41, Peng Fan wrote:
> >> Subject: Re: [PATCH 1/2] arm: irqchip: add lock in
> >> irqchip_inject_pending
> >>
> >> On 05.12.19 03:28, Peng Fan wrote:
> >>> Hi Jan,
> >>>
> >>>> -Original Message-
> >>>> From: Jan Kiszka 
> >>>> Sent: 2019年12月3日 17:18
> >>>> To: Peng Fan ; jailhouse-dev@googlegroups.com
> >>>> Cc: Alice Guo 
> >>>> Subject: Re: [PATCH 1/2] arm: irqchip: add lock in
> >>>> irqchip_inject_pending
> >>>>
> >>>> On 03.12.19 10:15, Peng Fan wrote:
> >>>>>> Subject: Re: [PATCH 1/2] arm: irqchip: add lock in
> >>>>>> irqchip_inject_pending
> >>>>>>
> >>>>>> On 03.12.19 09:58, Peng Fan wrote:
> >>>>>>>> Subject: Re: [PATCH 1/2] arm: irqchip: add lock in
> >>>>>>>> irqchip_inject_pending
> >>>>>>>>
> >>>>>>>> On 03.12.19 09:27, Peng Fan wrote:
> >>>>>>>>> Thinking about core0 is inject SGI to core1, core1 is handling
> >>>>>>>>> SGI interrupt.
> >>>>>>>>>
> >>>>>>>>> That means core0 might be in path to enqueue SGI into the
> >>>>>>>>> pending_irqs array, core1 might be in path handling SGI and
> >>>>>>>>> pick one from pending_irqs array. So need to use lock to
> >>>>>>>>> protect unqueue, not only enqueue.
> >>>>>>>>>
> >>>>>>>>> Signed-off-by: Peng Fan 
> >>>>>>>>> ---
> >>>>>>>>>
> >>>>>>>>> V1:
> >>>>>>>>>  The best case is only lock one entry, so no good solution,
> >>>>>>>>> because there is possibility that inject fail.
> >>>>>>>>>
> >>>>>>>>>  hypervisor/arch/arm-common/irqchip.c | 5 +
> >>>>>>>>>  1 file changed, 5 insertions(+)
> >>>>>>>>>
> >>>>>>>>> diff --git a/hypervisor/arch/arm-common/irqchip.c
> >>>>>>>>> b/hypervisor/arch/arm-common/irqchip.c
> >>>>>>>>> index 1c881b64..fbaa3099 100644
> >>>>>>>>> --- a/hypervisor/arch/arm-common/irqchip.c
> >>>>>>>>> +++ b/hypervisor/arch/arm-common/irqchip.c
> >>>>>>>>> @@ -279,11 +279,14 @@ void irqchip_inject_pending(void)
> >>>>>>>>> struct pending_irqs *pending =
> >> _cpu_public()->pending_irqs;
> >>>>>>>>> u16 irq_id, sender;
> >>>>>>>>>
> >>>>>>>>> +   spin_lock(>lock);
> >>>>>>>>> +
> >>>>>>>>> while (pending->head != pending->tail) {
> >>>>>>>>> irq_id = pending->irqs[pending->head];
> >>>>>>>>> sender = pending->sender[pending->head];
> >>>>>>>>>
> >>>>>>>>> if (irqchip.inject_irq(irq_id, sender) == -EBUSY) {
> >>>>>>>>> +   spin_unlock(>lock);
> >>>>>>>>> /*
> >>>>>>>>>  * The list registers are full, trigger 
> >>>>>>>>> maintenance
> >>>>>>>>>  * interrupt and leave.
> >>>>>>>>> @@ -295,6 +298,8 @@ void irqchip_inject_pending(void)
> >>>>>>>>> pending->head = (pending->head + 1) %
> >> MAX_PENDING_IRQS;
> >>>>>>>>> }
> >>>>>>>>>
> >>>>>>>>> +   spin_unlock(>lock);
> >>>>>>>>> +
> >>>>>>>>> /*
> >>>>>>>>>  * The software interrupt queue is empty - turn off the
> >>>>>> maintenance
> >>>>>>>>>  * interrupt.
> >>>>>>>>>
> >>>>>>>>
> >>>&g

Re: [PATCH 1/2] arm: irqchip: add lock in irqchip_inject_pending

2019-12-05 Thread Jan Kiszka
On 05.12.19 09:41, Peng Fan wrote:
>> Subject: Re: [PATCH 1/2] arm: irqchip: add lock in irqchip_inject_pending
>>
>> On 05.12.19 03:28, Peng Fan wrote:
>>> Hi Jan,
>>>
>>>> -Original Message-
>>>> From: Jan Kiszka 
>>>> Sent: 2019年12月3日 17:18
>>>> To: Peng Fan ; jailhouse-dev@googlegroups.com
>>>> Cc: Alice Guo 
>>>> Subject: Re: [PATCH 1/2] arm: irqchip: add lock in
>>>> irqchip_inject_pending
>>>>
>>>> On 03.12.19 10:15, Peng Fan wrote:
>>>>>> Subject: Re: [PATCH 1/2] arm: irqchip: add lock in
>>>>>> irqchip_inject_pending
>>>>>>
>>>>>> On 03.12.19 09:58, Peng Fan wrote:
>>>>>>>> Subject: Re: [PATCH 1/2] arm: irqchip: add lock in
>>>>>>>> irqchip_inject_pending
>>>>>>>>
>>>>>>>> On 03.12.19 09:27, Peng Fan wrote:
>>>>>>>>> Thinking about core0 is inject SGI to core1, core1 is handling
>>>>>>>>> SGI interrupt.
>>>>>>>>>
>>>>>>>>> That means core0 might be in path to enqueue SGI into the
>>>>>>>>> pending_irqs array, core1 might be in path handling SGI and pick
>>>>>>>>> one from pending_irqs array. So need to use lock to protect
>>>>>>>>> unqueue, not only enqueue.
>>>>>>>>>
>>>>>>>>> Signed-off-by: Peng Fan 
>>>>>>>>> ---
>>>>>>>>>
>>>>>>>>> V1:
>>>>>>>>>  The best case is only lock one entry, so no good solution,
>>>>>>>>> because there is possibility that inject fail.
>>>>>>>>>
>>>>>>>>>  hypervisor/arch/arm-common/irqchip.c | 5 +
>>>>>>>>>  1 file changed, 5 insertions(+)
>>>>>>>>>
>>>>>>>>> diff --git a/hypervisor/arch/arm-common/irqchip.c
>>>>>>>>> b/hypervisor/arch/arm-common/irqchip.c
>>>>>>>>> index 1c881b64..fbaa3099 100644
>>>>>>>>> --- a/hypervisor/arch/arm-common/irqchip.c
>>>>>>>>> +++ b/hypervisor/arch/arm-common/irqchip.c
>>>>>>>>> @@ -279,11 +279,14 @@ void irqchip_inject_pending(void)
>>>>>>>>>   struct pending_irqs *pending =
>> _cpu_public()->pending_irqs;
>>>>>>>>>   u16 irq_id, sender;
>>>>>>>>>
>>>>>>>>> + spin_lock(>lock);
>>>>>>>>> +
>>>>>>>>>   while (pending->head != pending->tail) {
>>>>>>>>>   irq_id = pending->irqs[pending->head];
>>>>>>>>>   sender = pending->sender[pending->head];
>>>>>>>>>
>>>>>>>>>   if (irqchip.inject_irq(irq_id, sender) == -EBUSY) {
>>>>>>>>> + spin_unlock(>lock);
>>>>>>>>>   /*
>>>>>>>>>* The list registers are full, trigger 
>>>>>>>>> maintenance
>>>>>>>>>* interrupt and leave.
>>>>>>>>> @@ -295,6 +298,8 @@ void irqchip_inject_pending(void)
>>>>>>>>>   pending->head = (pending->head + 1) %
>> MAX_PENDING_IRQS;
>>>>>>>>>   }
>>>>>>>>>
>>>>>>>>> + spin_unlock(>lock);
>>>>>>>>> +
>>>>>>>>>   /*
>>>>>>>>>* The software interrupt queue is empty - turn off the
>>>>>> maintenance
>>>>>>>>>* interrupt.
>>>>>>>>>
>>>>>>>>
>>>>>>>> Did you see real corruptions?
>>>>>>>
>>>>>>> No. just code inspection currently. We met some SGI inject return
>>>>>>> -EBUSY, so go through the code, and think this piece code needs a lock.
>>>>>>>
>>>>>>>>
>>>>>>>> The idea behind this was that the injection to the lock-less
>>&

RE: [PATCH 1/2] arm: irqchip: add lock in irqchip_inject_pending

2019-12-05 Thread Peng Fan
> Subject: Re: [PATCH 1/2] arm: irqchip: add lock in irqchip_inject_pending
> 
> On 05.12.19 03:28, Peng Fan wrote:
> > Hi Jan,
> >
> >> -Original Message-
> >> From: Jan Kiszka 
> >> Sent: 2019年12月3日 17:18
> >> To: Peng Fan ; jailhouse-dev@googlegroups.com
> >> Cc: Alice Guo 
> >> Subject: Re: [PATCH 1/2] arm: irqchip: add lock in
> >> irqchip_inject_pending
> >>
> >> On 03.12.19 10:15, Peng Fan wrote:
> >>>> Subject: Re: [PATCH 1/2] arm: irqchip: add lock in
> >>>> irqchip_inject_pending
> >>>>
> >>>> On 03.12.19 09:58, Peng Fan wrote:
> >>>>>> Subject: Re: [PATCH 1/2] arm: irqchip: add lock in
> >>>>>> irqchip_inject_pending
> >>>>>>
> >>>>>> On 03.12.19 09:27, Peng Fan wrote:
> >>>>>>> Thinking about core0 is inject SGI to core1, core1 is handling
> >>>>>>> SGI interrupt.
> >>>>>>>
> >>>>>>> That means core0 might be in path to enqueue SGI into the
> >>>>>>> pending_irqs array, core1 might be in path handling SGI and pick
> >>>>>>> one from pending_irqs array. So need to use lock to protect
> >>>>>>> unqueue, not only enqueue.
> >>>>>>>
> >>>>>>> Signed-off-by: Peng Fan 
> >>>>>>> ---
> >>>>>>>
> >>>>>>> V1:
> >>>>>>>  The best case is only lock one entry, so no good solution,
> >>>>>>> because there is possibility that inject fail.
> >>>>>>>
> >>>>>>>  hypervisor/arch/arm-common/irqchip.c | 5 +
> >>>>>>>  1 file changed, 5 insertions(+)
> >>>>>>>
> >>>>>>> diff --git a/hypervisor/arch/arm-common/irqchip.c
> >>>>>>> b/hypervisor/arch/arm-common/irqchip.c
> >>>>>>> index 1c881b64..fbaa3099 100644
> >>>>>>> --- a/hypervisor/arch/arm-common/irqchip.c
> >>>>>>> +++ b/hypervisor/arch/arm-common/irqchip.c
> >>>>>>> @@ -279,11 +279,14 @@ void irqchip_inject_pending(void)
> >>>>>>>   struct pending_irqs *pending =
> _cpu_public()->pending_irqs;
> >>>>>>>   u16 irq_id, sender;
> >>>>>>>
> >>>>>>> + spin_lock(>lock);
> >>>>>>> +
> >>>>>>>   while (pending->head != pending->tail) {
> >>>>>>>   irq_id = pending->irqs[pending->head];
> >>>>>>>   sender = pending->sender[pending->head];
> >>>>>>>
> >>>>>>>   if (irqchip.inject_irq(irq_id, sender) == -EBUSY) {
> >>>>>>> + spin_unlock(>lock);
> >>>>>>>   /*
> >>>>>>>* The list registers are full, trigger 
> >>>>>>> maintenance
> >>>>>>>* interrupt and leave.
> >>>>>>> @@ -295,6 +298,8 @@ void irqchip_inject_pending(void)
> >>>>>>>   pending->head = (pending->head + 1) %
> MAX_PENDING_IRQS;
> >>>>>>>   }
> >>>>>>>
> >>>>>>> + spin_unlock(>lock);
> >>>>>>> +
> >>>>>>>   /*
> >>>>>>>* The software interrupt queue is empty - turn off the
> >>>> maintenance
> >>>>>>>* interrupt.
> >>>>>>>
> >>>>>>
> >>>>>> Did you see real corruptions?
> >>>>>
> >>>>> No. just code inspection currently. We met some SGI inject return
> >>>>> -EBUSY, so go through the code, and think this piece code needs a lock.
> >>>>>
> >>>>>>
> >>>>>> The idea behind this was that the injection to the lock-less
> >>>>>> queue happens in a way that it won't make changes visible to the
> >>>>>> consumer that are inconsistent, hence the barrier in
> irqchip_set_pending.
> >>>>>> Looking that again, though, we possibly need another barrier,
> >

Re: [PATCH 1/2] arm: irqchip: add lock in irqchip_inject_pending

2019-12-05 Thread Jan Kiszka
On 05.12.19 03:28, Peng Fan wrote:
> Hi Jan,
> 
>> -Original Message-
>> From: Jan Kiszka 
>> Sent: 2019年12月3日 17:18
>> To: Peng Fan ; jailhouse-dev@googlegroups.com
>> Cc: Alice Guo 
>> Subject: Re: [PATCH 1/2] arm: irqchip: add lock in irqchip_inject_pending
>>
>> On 03.12.19 10:15, Peng Fan wrote:
>>>> Subject: Re: [PATCH 1/2] arm: irqchip: add lock in
>>>> irqchip_inject_pending
>>>>
>>>> On 03.12.19 09:58, Peng Fan wrote:
>>>>>> Subject: Re: [PATCH 1/2] arm: irqchip: add lock in
>>>>>> irqchip_inject_pending
>>>>>>
>>>>>> On 03.12.19 09:27, Peng Fan wrote:
>>>>>>> Thinking about core0 is inject SGI to core1, core1 is handling SGI
>>>>>>> interrupt.
>>>>>>>
>>>>>>> That means core0 might be in path to enqueue SGI into the
>>>>>>> pending_irqs array, core1 might be in path handling SGI and pick
>>>>>>> one from pending_irqs array. So need to use lock to protect
>>>>>>> unqueue, not only enqueue.
>>>>>>>
>>>>>>> Signed-off-by: Peng Fan 
>>>>>>> ---
>>>>>>>
>>>>>>> V1:
>>>>>>>  The best case is only lock one entry, so no good solution,
>>>>>>> because there is possibility that inject fail.
>>>>>>>
>>>>>>>  hypervisor/arch/arm-common/irqchip.c | 5 +
>>>>>>>  1 file changed, 5 insertions(+)
>>>>>>>
>>>>>>> diff --git a/hypervisor/arch/arm-common/irqchip.c
>>>>>>> b/hypervisor/arch/arm-common/irqchip.c
>>>>>>> index 1c881b64..fbaa3099 100644
>>>>>>> --- a/hypervisor/arch/arm-common/irqchip.c
>>>>>>> +++ b/hypervisor/arch/arm-common/irqchip.c
>>>>>>> @@ -279,11 +279,14 @@ void irqchip_inject_pending(void)
>>>>>>> struct pending_irqs *pending = _cpu_public()->pending_irqs;
>>>>>>> u16 irq_id, sender;
>>>>>>>
>>>>>>> +   spin_lock(>lock);
>>>>>>> +
>>>>>>> while (pending->head != pending->tail) {
>>>>>>> irq_id = pending->irqs[pending->head];
>>>>>>> sender = pending->sender[pending->head];
>>>>>>>
>>>>>>> if (irqchip.inject_irq(irq_id, sender) == -EBUSY) {
>>>>>>> +   spin_unlock(>lock);
>>>>>>> /*
>>>>>>>  * The list registers are full, trigger 
>>>>>>> maintenance
>>>>>>>  * interrupt and leave.
>>>>>>> @@ -295,6 +298,8 @@ void irqchip_inject_pending(void)
>>>>>>> pending->head = (pending->head + 1) % MAX_PENDING_IRQS;
>>>>>>> }
>>>>>>>
>>>>>>> +   spin_unlock(>lock);
>>>>>>> +
>>>>>>> /*
>>>>>>>  * The software interrupt queue is empty - turn off the
>>>> maintenance
>>>>>>>  * interrupt.
>>>>>>>
>>>>>>
>>>>>> Did you see real corruptions?
>>>>>
>>>>> No. just code inspection currently. We met some SGI inject return
>>>>> -EBUSY, so go through the code, and think this piece code needs a lock.
>>>>>
>>>>>>
>>>>>> The idea behind this was that the injection to the lock-less queue
>>>>>> happens in a way that it won't make changes visible to the consumer
>>>>>> that are inconsistent, hence the barrier in irqchip_set_pending.
>>>>>> Looking that again, though, we possibly need another barrier, right
>>>>>> before updating
>>>>>> pending->tail.
>>>>>
>>>>> Barrier could not prohibit enqueue/unqueue contention.
>>>>> enqueue will check head, unqueue will update head.
>>>>
>>>> Some topic as with lockless enqueuing: We need a barrier to shield
>>>> the readout of the head entry from the update of pending->head. So,
>>>> we are definitely lac

RE: [PATCH 1/2] arm: irqchip: add lock in irqchip_inject_pending

2019-12-04 Thread Peng Fan
Hi Jan,

> -Original Message-
> From: Jan Kiszka 
> Sent: 2019年12月3日 17:18
> To: Peng Fan ; jailhouse-dev@googlegroups.com
> Cc: Alice Guo 
> Subject: Re: [PATCH 1/2] arm: irqchip: add lock in irqchip_inject_pending
> 
> On 03.12.19 10:15, Peng Fan wrote:
> >> Subject: Re: [PATCH 1/2] arm: irqchip: add lock in
> >> irqchip_inject_pending
> >>
> >> On 03.12.19 09:58, Peng Fan wrote:
> >>>> Subject: Re: [PATCH 1/2] arm: irqchip: add lock in
> >>>> irqchip_inject_pending
> >>>>
> >>>> On 03.12.19 09:27, Peng Fan wrote:
> >>>>> Thinking about core0 is inject SGI to core1, core1 is handling SGI
> >>>>> interrupt.
> >>>>>
> >>>>> That means core0 might be in path to enqueue SGI into the
> >>>>> pending_irqs array, core1 might be in path handling SGI and pick
> >>>>> one from pending_irqs array. So need to use lock to protect
> >>>>> unqueue, not only enqueue.
> >>>>>
> >>>>> Signed-off-by: Peng Fan 
> >>>>> ---
> >>>>>
> >>>>> V1:
> >>>>>  The best case is only lock one entry, so no good solution,
> >>>>> because there is possibility that inject fail.
> >>>>>
> >>>>>  hypervisor/arch/arm-common/irqchip.c | 5 +
> >>>>>  1 file changed, 5 insertions(+)
> >>>>>
> >>>>> diff --git a/hypervisor/arch/arm-common/irqchip.c
> >>>>> b/hypervisor/arch/arm-common/irqchip.c
> >>>>> index 1c881b64..fbaa3099 100644
> >>>>> --- a/hypervisor/arch/arm-common/irqchip.c
> >>>>> +++ b/hypervisor/arch/arm-common/irqchip.c
> >>>>> @@ -279,11 +279,14 @@ void irqchip_inject_pending(void)
> >>>>> struct pending_irqs *pending = _cpu_public()->pending_irqs;
> >>>>> u16 irq_id, sender;
> >>>>>
> >>>>> +   spin_lock(>lock);
> >>>>> +
> >>>>> while (pending->head != pending->tail) {
> >>>>> irq_id = pending->irqs[pending->head];
> >>>>> sender = pending->sender[pending->head];
> >>>>>
> >>>>> if (irqchip.inject_irq(irq_id, sender) == -EBUSY) {
> >>>>> +   spin_unlock(>lock);
> >>>>> /*
> >>>>>  * The list registers are full, trigger 
> >>>>> maintenance
> >>>>>  * interrupt and leave.
> >>>>> @@ -295,6 +298,8 @@ void irqchip_inject_pending(void)
> >>>>> pending->head = (pending->head + 1) % MAX_PENDING_IRQS;
> >>>>> }
> >>>>>
> >>>>> +   spin_unlock(>lock);
> >>>>> +
> >>>>> /*
> >>>>>  * The software interrupt queue is empty - turn off the
> >> maintenance
> >>>>>  * interrupt.
> >>>>>
> >>>>
> >>>> Did you see real corruptions?
> >>>
> >>> No. just code inspection currently. We met some SGI inject return
> >>> -EBUSY, so go through the code, and think this piece code needs a lock.
> >>>
> >>>>
> >>>> The idea behind this was that the injection to the lock-less queue
> >>>> happens in a way that it won't make changes visible to the consumer
> >>>> that are inconsistent, hence the barrier in irqchip_set_pending.
> >>>> Looking that again, though, we possibly need another barrier, right
> >>>> before updating
> >>>> pending->tail.
> >>>
> >>> Barrier could not prohibit enqueue/unqueue contention.
> >>> enqueue will check head, unqueue will update head.
> >>
> >> Some topic as with lockless enqueuing: We need a barrier to shield
> >> the readout of the head entry from the update of pending->head. So,
> >> we are definitely lacking barriers here, but I don't think we need
> >> the spinlock between producer and consumer because there is only one
> consumer.
> >
> > Lock-free should be possible, let me work out a non-lock solution.
> 
> This is what comes to my mi

Re: [PATCH 1/2] arm: irqchip: add lock in irqchip_inject_pending

2019-12-03 Thread Jan Kiszka
On 03.12.19 10:15, Peng Fan wrote:
>> Subject: Re: [PATCH 1/2] arm: irqchip: add lock in irqchip_inject_pending
>>
>> On 03.12.19 09:58, Peng Fan wrote:
>>>> Subject: Re: [PATCH 1/2] arm: irqchip: add lock in
>>>> irqchip_inject_pending
>>>>
>>>> On 03.12.19 09:27, Peng Fan wrote:
>>>>> Thinking about core0 is inject SGI to core1, core1 is handling SGI
>>>>> interrupt.
>>>>>
>>>>> That means core0 might be in path to enqueue SGI into the
>>>>> pending_irqs array, core1 might be in path handling SGI and pick one
>>>>> from pending_irqs array. So need to use lock to protect unqueue, not
>>>>> only enqueue.
>>>>>
>>>>> Signed-off-by: Peng Fan 
>>>>> ---
>>>>>
>>>>> V1:
>>>>>  The best case is only lock one entry, so no good solution, because
>>>>> there is possibility that inject fail.
>>>>>
>>>>>  hypervisor/arch/arm-common/irqchip.c | 5 +
>>>>>  1 file changed, 5 insertions(+)
>>>>>
>>>>> diff --git a/hypervisor/arch/arm-common/irqchip.c
>>>>> b/hypervisor/arch/arm-common/irqchip.c
>>>>> index 1c881b64..fbaa3099 100644
>>>>> --- a/hypervisor/arch/arm-common/irqchip.c
>>>>> +++ b/hypervisor/arch/arm-common/irqchip.c
>>>>> @@ -279,11 +279,14 @@ void irqchip_inject_pending(void)
>>>>>   struct pending_irqs *pending = _cpu_public()->pending_irqs;
>>>>>   u16 irq_id, sender;
>>>>>
>>>>> + spin_lock(>lock);
>>>>> +
>>>>>   while (pending->head != pending->tail) {
>>>>>   irq_id = pending->irqs[pending->head];
>>>>>   sender = pending->sender[pending->head];
>>>>>
>>>>>   if (irqchip.inject_irq(irq_id, sender) == -EBUSY) {
>>>>> + spin_unlock(>lock);
>>>>>   /*
>>>>>* The list registers are full, trigger maintenance
>>>>>* interrupt and leave.
>>>>> @@ -295,6 +298,8 @@ void irqchip_inject_pending(void)
>>>>>   pending->head = (pending->head + 1) % MAX_PENDING_IRQS;
>>>>>   }
>>>>>
>>>>> + spin_unlock(>lock);
>>>>> +
>>>>>   /*
>>>>>* The software interrupt queue is empty - turn off the
>> maintenance
>>>>>* interrupt.
>>>>>
>>>>
>>>> Did you see real corruptions?
>>>
>>> No. just code inspection currently. We met some SGI inject return
>>> -EBUSY, so go through the code, and think this piece code needs a lock.
>>>
>>>>
>>>> The idea behind this was that the injection to the lock-less queue
>>>> happens in a way that it won't make changes visible to the consumer
>>>> that are inconsistent, hence the barrier in irqchip_set_pending.
>>>> Looking that again, though, we possibly need another barrier, right
>>>> before updating
>>>> pending->tail.
>>>
>>> Barrier could not prohibit enqueue/unqueue contention.
>>> enqueue will check head, unqueue will update head.
>>
>> Some topic as with lockless enqueuing: We need a barrier to shield the
>> readout of the head entry from the update of pending->head. So, we are
>> definitely lacking barriers here, but I don't think we need the spinlock
>> between producer and consumer because there is only one consumer.
> 
> Lock-free should be possible, let me work out a non-lock solution.

This is what comes to my mind so far, but please re-check carefully:

diff --git a/hypervisor/arch/arm-common/irqchip.c 
b/hypervisor/arch/arm-common/irqchip.c
index 1c881b64..a83cd81d 100644
--- a/hypervisor/arch/arm-common/irqchip.c
+++ b/hypervisor/arch/arm-common/irqchip.c
@@ -246,12 +246,12 @@ void irqchip_set_pending(struct public_per_cpu 
*cpu_public, u16 irq_id)
if (new_tail != pending->head) {
pending->irqs[pending->tail] = irq_id;
pending->sender[pending->tail] = sender;
-   pending->tail = new_tail;
/*
-* Make the change to pending_irqs.tail visible before the
-* caller sends SGI_INJECT.
+* Make the entry content visible before updating the tail
+* index.
 */
memo

RE: [PATCH 1/2] arm: irqchip: add lock in irqchip_inject_pending

2019-12-03 Thread Peng Fan
> Subject: Re: [PATCH 1/2] arm: irqchip: add lock in irqchip_inject_pending
> 
> On 03.12.19 09:58, Peng Fan wrote:
> >> Subject: Re: [PATCH 1/2] arm: irqchip: add lock in
> >> irqchip_inject_pending
> >>
> >> On 03.12.19 09:27, Peng Fan wrote:
> >>> Thinking about core0 is inject SGI to core1, core1 is handling SGI
> >>> interrupt.
> >>>
> >>> That means core0 might be in path to enqueue SGI into the
> >>> pending_irqs array, core1 might be in path handling SGI and pick one
> >>> from pending_irqs array. So need to use lock to protect unqueue, not
> >>> only enqueue.
> >>>
> >>> Signed-off-by: Peng Fan 
> >>> ---
> >>>
> >>> V1:
> >>>  The best case is only lock one entry, so no good solution, because
> >>> there is possibility that inject fail.
> >>>
> >>>  hypervisor/arch/arm-common/irqchip.c | 5 +
> >>>  1 file changed, 5 insertions(+)
> >>>
> >>> diff --git a/hypervisor/arch/arm-common/irqchip.c
> >>> b/hypervisor/arch/arm-common/irqchip.c
> >>> index 1c881b64..fbaa3099 100644
> >>> --- a/hypervisor/arch/arm-common/irqchip.c
> >>> +++ b/hypervisor/arch/arm-common/irqchip.c
> >>> @@ -279,11 +279,14 @@ void irqchip_inject_pending(void)
> >>>   struct pending_irqs *pending = _cpu_public()->pending_irqs;
> >>>   u16 irq_id, sender;
> >>>
> >>> + spin_lock(>lock);
> >>> +
> >>>   while (pending->head != pending->tail) {
> >>>   irq_id = pending->irqs[pending->head];
> >>>   sender = pending->sender[pending->head];
> >>>
> >>>   if (irqchip.inject_irq(irq_id, sender) == -EBUSY) {
> >>> + spin_unlock(>lock);
> >>>   /*
> >>>* The list registers are full, trigger maintenance
> >>>* interrupt and leave.
> >>> @@ -295,6 +298,8 @@ void irqchip_inject_pending(void)
> >>>   pending->head = (pending->head + 1) % MAX_PENDING_IRQS;
> >>>   }
> >>>
> >>> + spin_unlock(>lock);
> >>> +
> >>>   /*
> >>>* The software interrupt queue is empty - turn off the
> maintenance
> >>>* interrupt.
> >>>
> >>
> >> Did you see real corruptions?
> >
> > No. just code inspection currently. We met some SGI inject return
> > -EBUSY, so go through the code, and think this piece code needs a lock.
> >
> >>
> >> The idea behind this was that the injection to the lock-less queue
> >> happens in a way that it won't make changes visible to the consumer
> >> that are inconsistent, hence the barrier in irqchip_set_pending.
> >> Looking that again, though, we possibly need another barrier, right
> >> before updating
> >> pending->tail.
> >
> > Barrier could not prohibit enqueue/unqueue contention.
> > enqueue will check head, unqueue will update head.
> 
> Some topic as with lockless enqueuing: We need a barrier to shield the
> readout of the head entry from the update of pending->head. So, we are
> definitely lacking barriers here, but I don't think we need the spinlock
> between producer and consumer because there is only one consumer.

Lock-free should be possible, let me work out a non-lock solution.

Regards,
Peng.

> 
> Jan
> 
> --
> Siemens AG, Corporate Technology, CT RDA IOT SES-DE Corporate
> Competence Center Embedded Linux

-- 
You received this message because you are subscribed to the Google Groups 
"Jailhouse" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to jailhouse-dev+unsubscr...@googlegroups.com.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/jailhouse-dev/AM0PR04MB44811BEC3EDE072313C1F3B888420%40AM0PR04MB4481.eurprd04.prod.outlook.com.


Re: [PATCH 1/2] arm: irqchip: add lock in irqchip_inject_pending

2019-12-03 Thread Jan Kiszka
On 03.12.19 09:58, Peng Fan wrote:
>> Subject: Re: [PATCH 1/2] arm: irqchip: add lock in irqchip_inject_pending
>>
>> On 03.12.19 09:27, Peng Fan wrote:
>>> Thinking about core0 is inject SGI to core1, core1 is handling SGI
>>> interrupt.
>>>
>>> That means core0 might be in path to enqueue SGI into the pending_irqs
>>> array, core1 might be in path handling SGI and pick one from
>>> pending_irqs array. So need to use lock to protect unqueue, not only
>>> enqueue.
>>>
>>> Signed-off-by: Peng Fan 
>>> ---
>>>
>>> V1:
>>>  The best case is only lock one entry, so no good solution, because
>>> there is possibility that inject fail.
>>>
>>>  hypervisor/arch/arm-common/irqchip.c | 5 +
>>>  1 file changed, 5 insertions(+)
>>>
>>> diff --git a/hypervisor/arch/arm-common/irqchip.c
>>> b/hypervisor/arch/arm-common/irqchip.c
>>> index 1c881b64..fbaa3099 100644
>>> --- a/hypervisor/arch/arm-common/irqchip.c
>>> +++ b/hypervisor/arch/arm-common/irqchip.c
>>> @@ -279,11 +279,14 @@ void irqchip_inject_pending(void)
>>> struct pending_irqs *pending = _cpu_public()->pending_irqs;
>>> u16 irq_id, sender;
>>>
>>> +   spin_lock(>lock);
>>> +
>>> while (pending->head != pending->tail) {
>>> irq_id = pending->irqs[pending->head];
>>> sender = pending->sender[pending->head];
>>>
>>> if (irqchip.inject_irq(irq_id, sender) == -EBUSY) {
>>> +   spin_unlock(>lock);
>>> /*
>>>  * The list registers are full, trigger maintenance
>>>  * interrupt and leave.
>>> @@ -295,6 +298,8 @@ void irqchip_inject_pending(void)
>>> pending->head = (pending->head + 1) % MAX_PENDING_IRQS;
>>> }
>>>
>>> +   spin_unlock(>lock);
>>> +
>>> /*
>>>  * The software interrupt queue is empty - turn off the maintenance
>>>  * interrupt.
>>>
>>
>> Did you see real corruptions?
> 
> No. just code inspection currently. We met some SGI inject return -EBUSY,
> so go through the code, and think this piece code needs a lock.
> 
>>
>> The idea behind this was that the injection to the lock-less queue happens in
>> a way that it won't make changes visible to the consumer that are
>> inconsistent, hence the barrier in irqchip_set_pending. Looking that again,
>> though, we possibly need another barrier, right before updating
>> pending->tail.
> 
> Barrier could not prohibit enqueue/unqueue contention.
> enqueue will check head, unqueue will update head.

Some topic as with lockless enqueuing: We need a barrier to shield the
readout of the head entry from the update of pending->head. So, we are
definitely lacking barriers here, but I don't think we need the spinlock
between producer and consumer because there is only one consumer.

Jan

-- 
Siemens AG, Corporate Technology, CT RDA IOT SES-DE
Corporate Competence Center Embedded Linux

-- 
You received this message because you are subscribed to the Google Groups 
"Jailhouse" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to jailhouse-dev+unsubscr...@googlegroups.com.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/jailhouse-dev/81533a5d-8385-9872-ef22-4bcaa30c98f5%40siemens.com.


RE: [PATCH 1/2] arm: irqchip: add lock in irqchip_inject_pending

2019-12-03 Thread Peng Fan
> Subject: Re: [PATCH 1/2] arm: irqchip: add lock in irqchip_inject_pending
> 
> On 03.12.19 09:27, Peng Fan wrote:
> > Thinking about core0 is inject SGI to core1, core1 is handling SGI
> > interrupt.
> >
> > That means core0 might be in path to enqueue SGI into the pending_irqs
> > array, core1 might be in path handling SGI and pick one from
> > pending_irqs array. So need to use lock to protect unqueue, not only
> > enqueue.
> >
> > Signed-off-by: Peng Fan 
> > ---
> >
> > V1:
> >  The best case is only lock one entry, so no good solution, because
> > there is possibility that inject fail.
> >
> >  hypervisor/arch/arm-common/irqchip.c | 5 +
> >  1 file changed, 5 insertions(+)
> >
> > diff --git a/hypervisor/arch/arm-common/irqchip.c
> > b/hypervisor/arch/arm-common/irqchip.c
> > index 1c881b64..fbaa3099 100644
> > --- a/hypervisor/arch/arm-common/irqchip.c
> > +++ b/hypervisor/arch/arm-common/irqchip.c
> > @@ -279,11 +279,14 @@ void irqchip_inject_pending(void)
> > struct pending_irqs *pending = _cpu_public()->pending_irqs;
> > u16 irq_id, sender;
> >
> > +   spin_lock(>lock);
> > +
> > while (pending->head != pending->tail) {
> > irq_id = pending->irqs[pending->head];
> > sender = pending->sender[pending->head];
> >
> > if (irqchip.inject_irq(irq_id, sender) == -EBUSY) {
> > +   spin_unlock(>lock);
> > /*
> >  * The list registers are full, trigger maintenance
> >  * interrupt and leave.
> > @@ -295,6 +298,8 @@ void irqchip_inject_pending(void)
> > pending->head = (pending->head + 1) % MAX_PENDING_IRQS;
> > }
> >
> > +   spin_unlock(>lock);
> > +
> > /*
> >  * The software interrupt queue is empty - turn off the maintenance
> >  * interrupt.
> >
> 
> Did you see real corruptions?

No. just code inspection currently. We met some SGI inject return -EBUSY,
so go through the code, and think this piece code needs a lock.

> 
> The idea behind this was that the injection to the lock-less queue happens in
> a way that it won't make changes visible to the consumer that are
> inconsistent, hence the barrier in irqchip_set_pending. Looking that again,
> though, we possibly need another barrier, right before updating
> pending->tail.

Barrier could not prohibit enqueue/unqueue contention.
enqueue will check head, unqueue will update head.

Thanks,
Peng.

> 
> Jan
> 
> --
> Siemens AG, Corporate Technology, CT RDA IOT SES-DE Corporate
> Competence Center Embedded Linux

-- 
You received this message because you are subscribed to the Google Groups 
"Jailhouse" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to jailhouse-dev+unsubscr...@googlegroups.com.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/jailhouse-dev/AM0PR04MB4481FCD642715C2D03DA78EB88420%40AM0PR04MB4481.eurprd04.prod.outlook.com.


Re: [PATCH 1/2] arm: irqchip: add lock in irqchip_inject_pending

2019-12-03 Thread Jan Kiszka
On 03.12.19 09:27, Peng Fan wrote:
> Thinking about core0 is inject SGI to core1, core1 is handling SGI
> interrupt.
> 
> That means core0 might be in path to enqueue SGI into the pending_irqs
> array, core1 might be in path handling SGI and pick one from
> pending_irqs array. So need to use lock to protect unqueue, not only
> enqueue.
> 
> Signed-off-by: Peng Fan 
> ---
> 
> V1:
>  The best case is only lock one entry, so no good solution, because
>  there is possibility that inject fail.
> 
>  hypervisor/arch/arm-common/irqchip.c | 5 +
>  1 file changed, 5 insertions(+)
> 
> diff --git a/hypervisor/arch/arm-common/irqchip.c 
> b/hypervisor/arch/arm-common/irqchip.c
> index 1c881b64..fbaa3099 100644
> --- a/hypervisor/arch/arm-common/irqchip.c
> +++ b/hypervisor/arch/arm-common/irqchip.c
> @@ -279,11 +279,14 @@ void irqchip_inject_pending(void)
>   struct pending_irqs *pending = _cpu_public()->pending_irqs;
>   u16 irq_id, sender;
>  
> + spin_lock(>lock);
> +
>   while (pending->head != pending->tail) {
>   irq_id = pending->irqs[pending->head];
>   sender = pending->sender[pending->head];
>  
>   if (irqchip.inject_irq(irq_id, sender) == -EBUSY) {
> + spin_unlock(>lock);
>   /*
>* The list registers are full, trigger maintenance
>* interrupt and leave.
> @@ -295,6 +298,8 @@ void irqchip_inject_pending(void)
>   pending->head = (pending->head + 1) % MAX_PENDING_IRQS;
>   }
>  
> + spin_unlock(>lock);
> +
>   /*
>* The software interrupt queue is empty - turn off the maintenance
>* interrupt.
> 

Did you see real corruptions?

The idea behind this was that the injection to the lock-less queue
happens in a way that it won't make changes visible to the consumer that
are inconsistent, hence the barrier in irqchip_set_pending. Looking that
again, though, we possibly need another barrier, right before updating
pending->tail.

Jan

-- 
Siemens AG, Corporate Technology, CT RDA IOT SES-DE
Corporate Competence Center Embedded Linux

-- 
You received this message because you are subscribed to the Google Groups 
"Jailhouse" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to jailhouse-dev+unsubscr...@googlegroups.com.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/jailhouse-dev/3408fd87-22fa-31bc-657d-8661ad3998f3%40siemens.com.