HV: bug fix in operating softirq

Current code is missing to handle the following race condition:

   Before:

     sti
      |
      V
handle softirq with
a while loop
      |          <----- if a new softirq generated at this point,
      V                 it will be missed to be handled.
     cli
      |
      V
return with unclear softirq bitmap

    After:

again:
     sti
      |
      V
handle softirq with
a while loop
      |
      V
     cli
      |
      V
check if a new softirq generated, if yes,
jump back to above again lable point,
and do a while loop again.
      |
      V
return with clear softirq bitmap

Signed-off-by: Zheng, Gen <gen.zheng@intel.com>
Acked-by: Eddie Dong <eddie.dong@intel.com>
This commit is contained in:
Zheng, Gen 2018-06-13 16:06:17 +08:00 committed by lijinxia
parent 8f3b36b224
commit a06f2d68dc
2 changed files with 11 additions and 12 deletions

View File

@ -40,27 +40,24 @@ void raise_softirq(int softirq_id)
void exec_softirq(void) void exec_softirq(void)
{ {
int cpu_id = get_cpu_id(); int cpu_id = get_cpu_id();
uint64_t *bitmap = &per_cpu(softirq_pending, cpu_id); volatile uint64_t *bitmap = &per_cpu(softirq_pending, cpu_id);
uint64_t rflag;
int softirq_id; int softirq_id;
if (cpu_id >= phy_cpu_num) if (cpu_id >= phy_cpu_num)
return; return;
if (((*bitmap) & SOFTIRQ_MASK) == 0UL)
return;
/* Disable softirq /* Disable softirq
* SOFTIRQ_ATOMIC bit = 0 means softirq already in execution * SOFTIRQ_ATOMIC bit = 0 means softirq already in execution
*/ */
if (!bitmap_test_and_clear(SOFTIRQ_ATOMIC, bitmap)) if (!bitmap_test_and_clear(SOFTIRQ_ATOMIC, bitmap))
return; return;
if (((*bitmap) & SOFTIRQ_MASK) == 0UL) again:
goto ENABLE_AND_EXIT; CPU_IRQ_ENABLE();
/* check if we are in interrupt context */
CPU_RFLAGS_SAVE(&rflag);
if (!(rflag & (1<<9)))
goto ENABLE_AND_EXIT;
while (1) { while (1) {
softirq_id = ffs64(*bitmap); softirq_id = ffs64(*bitmap);
@ -82,7 +79,11 @@ void exec_softirq(void)
} }
} }
ENABLE_AND_EXIT: CPU_IRQ_DISABLE();
if (((*bitmap) & SOFTIRQ_MASK))
goto again;
enable_softirq(cpu_id); enable_softirq(cpu_id);
} }

View File

@ -32,9 +32,7 @@ void vcpu_thread(struct vcpu *vcpu)
do { do {
/* handling pending softirq */ /* handling pending softirq */
CPU_IRQ_ENABLE();
exec_softirq(); exec_softirq();
CPU_IRQ_DISABLE();
/* Check and process pending requests(including interrupt) */ /* Check and process pending requests(including interrupt) */
ret = acrn_handle_pending_request(vcpu); ret = acrn_handle_pending_request(vcpu);