|
8 | 8 |
|
9 | 9 | static uint32_t notification_irq = IRQ_INVALID;
|
10 | 10 |
|
| 11 | +static volatile uint64_t smp_call_mask = 0UL; |
| 12 | + |
11 | 13 | /* run in interrupt context */
|
12 | 14 | static int kick_notification(__unused uint32_t irq, __unused void *data)
|
13 | 15 | {
|
14 |
| - /* Notification vector does not require handling here, it's just used |
15 |
| - * to kick taget cpu out of non-root mode. |
| 16 | + /* Notification vector is used to kick taget cpu out of non-root mode. |
| 17 | + * And it also serves for smp call. |
16 | 18 | */
|
| 19 | + uint16_t pcpu_id = get_cpu_id(); |
| 20 | + |
| 21 | + if (bitmap_test(pcpu_id, &smp_call_mask)) { |
| 22 | + struct smp_call_info_data *smp_call = |
| 23 | + &per_cpu(smp_call_info, pcpu_id); |
| 24 | + |
| 25 | + if (smp_call->func) |
| 26 | + smp_call->func(smp_call->data); |
| 27 | + bitmap_clear_nolock(pcpu_id, &smp_call_mask); |
| 28 | + } |
| 29 | + |
17 | 30 | return 0;
|
18 | 31 | }
|
19 | 32 |
|
| 33 | +void smp_call_function(uint64_t mask, smp_call_func_t func, void *data) |
| 34 | +{ |
| 35 | + uint16_t pcpu_id; |
| 36 | + struct smp_call_info_data *smp_call; |
| 37 | + |
| 38 | + /* wait for previous smp call complete, which may run on other cpus */ |
| 39 | + while (atomic_cmpxchg64(&smp_call_mask, 0UL, mask & INVALID_BIT_INDEX)); |
| 40 | + while ((pcpu_id = ffs64(mask)) != INVALID_BIT_INDEX) { |
| 41 | + bitmap_clear_nolock(pcpu_id, &mask); |
| 42 | + if (bitmap_test(pcpu_id, &pcpu_active_bitmap)) { |
| 43 | + smp_call = &per_cpu(smp_call_info, pcpu_id); |
| 44 | + smp_call->func = func; |
| 45 | + smp_call->data = data; |
| 46 | + } else { |
| 47 | + /* pcpu is not in active, print error */ |
| 48 | + pr_err("pcpu_id %d not in active!", pcpu_id); |
| 49 | + bitmap_clear_nolock(pcpu_id, &smp_call_mask); |
| 50 | + } |
| 51 | + } |
| 52 | + send_dest_ipi(smp_call_mask, VECTOR_NOTIFY_VCPU, |
| 53 | + INTR_LAPIC_ICR_LOGICAL); |
| 54 | + /* wait for current smp call complete */ |
| 55 | + wait_sync_change(&smp_call_mask, 0UL); |
| 56 | +} |
| 57 | + |
20 | 58 | static int request_notification_irq(irq_action_t func, void *data,
|
21 | 59 | const char *name)
|
22 | 60 | {
|
|
0 commit comments