mirror of
https://github.com/projectacrn/acrn-hypervisor.git
synced 2025-11-14 19:02:02 +00:00
This patch:
- abstracts the common logic from existing x86 implementation
- moves x86-specific logic to arch/x86/notify.c
A new common/notify.{c,h} is introduced to provide a common SMP call framework for
multi-arch support in ACRN.
arch-specific files such as arch/{x86,riscv}/notify.c is aim to provide the
corresponding implementations respectively.
The framework provides the following common APIs:
- init_smp_call(): initialize the SMP call support during pCPU initialization
- handle_smp_call(): execute the SMP call notification handler
- smp_call_function(): trigger the SMP call request to target pCPUs
Other SW modules should invoke these common APIs to perform arch-independent
SMP operations.
Two arch-specific hooks are abstracted:
- arch_smp_call_kick_pcpu():
- On x86, special handling is required when LAPIC is passthrough.
- On RISC-V, a plain IPI is sufficient to kick the target pCPU.
- arch_init_smp_call():
- On x86, CPU initialization reserves dedicated vectors and
registers callback handlers for purposes such as notifications
or posted interrupts.
- On RISC-V, no special handling is required at present; this
can be extended in the future if needed.
----------
Changelog:
* Merged the following two patches into one:
[RFC PATCH v2 4/7] hv: introduce common/smp.{c,h}
[RFC PATCH v2 5/7] hv: smpcall: x86: adapt to common SMP call
Tracked-On: #8786
Signed-off-by: Shiqing Gao <shiqing.gao@intel.com>
Acked-by: Wang, Yu1 <yu1.wang@intel.com>
103 lines
2.8 KiB
C
103 lines
2.8 KiB
C
/*
|
|
* Copyright (C) 2025 Intel Corporation.
|
|
*
|
|
* SPDX-License-Identifier: BSD-3-Clause
|
|
*/
|
|
|
|
#include <asm/cpu.h>
|
|
#include <asm/lib/atomic.h>
|
|
#include <asm/lib/bits.h>
|
|
#include <asm/per_cpu.h>
|
|
#include <asm/notify.h>
|
|
#include <common/notify.h>
|
|
|
|
static volatile uint64_t smp_call_mask = 0UL;
|
|
|
|
/**
|
|
* Run in interrupt context.
|
|
*
|
|
* Two use cases are covered:
|
|
* - SMP call: when the corresponding bit in smp_call_mask is set and
|
|
* smp_call_info in the per-CPU region is specified.
|
|
* The registered callback will be invoked.
|
|
*
|
|
* - Kick pCPU out of non-root mode: when the corresponding bit in smp_call_mask is clear and
|
|
* smp_call_info in the per-CPU region is not specified.
|
|
* No callback is invoked.
|
|
*/
|
|
void kick_notification(__unused uint32_t irq, __unused void *data)
|
|
{
|
|
uint16_t pcpu_id = get_pcpu_id();
|
|
|
|
if (bitmap_test(pcpu_id, &smp_call_mask)) {
|
|
struct smp_call_info_data *smp_call = &per_cpu(smp_call_info, pcpu_id);
|
|
|
|
if (smp_call->func != NULL) {
|
|
smp_call->func(smp_call->data);
|
|
}
|
|
bitmap_clear_lock(pcpu_id, &smp_call_mask);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Execute the SMP call notification handler
|
|
*/
|
|
void handle_smp_call(void)
|
|
{
|
|
kick_notification(0U, NULL);
|
|
}
|
|
|
|
/**
|
|
* Trigger the SMP call request to target pCPUs
|
|
*/
|
|
void smp_call_function(uint64_t mask, smp_call_func_t func, void *data)
|
|
{
|
|
uint16_t pcpu_id;
|
|
struct smp_call_info_data *smp_call;
|
|
|
|
/* wait for previous smp call complete, which may run on other cpus */
|
|
while (atomic_cmpxchg64(&smp_call_mask, 0UL, mask) != 0UL);
|
|
|
|
pcpu_id = ffs64(mask);
|
|
while (pcpu_id < MAX_PCPU_NUM) {
|
|
bitmap_clear_nolock(pcpu_id, &mask);
|
|
if (pcpu_id == get_pcpu_id()) {
|
|
func(data);
|
|
bitmap_clear_nolock(pcpu_id, &smp_call_mask);
|
|
} else if (is_pcpu_active(pcpu_id)) {
|
|
smp_call = &per_cpu(smp_call_info, pcpu_id);
|
|
|
|
smp_call->func = func;
|
|
smp_call->data = data;
|
|
|
|
/**
|
|
* arch_smp_call_kick_pcpu() is abstracted because:
|
|
* - On x86, special handling is required when LAPIC is passthrough.
|
|
* - On RISC-V, a plain IPI is sufficient to kick the target pCPU.
|
|
*/
|
|
arch_smp_call_kick_pcpu(pcpu_id);
|
|
} else {
|
|
/* pcpu is not in active, print error */
|
|
pr_err("pcpu_id %d not in active!", pcpu_id);
|
|
bitmap_clear_nolock(pcpu_id, &smp_call_mask);
|
|
}
|
|
pcpu_id = ffs64(mask);
|
|
}
|
|
/* wait for current smp call complete */
|
|
wait_sync_change(&smp_call_mask, 0UL);
|
|
}
|
|
|
|
/**
|
|
* Initialize the SMP call support during pCPU initialization
|
|
*/
|
|
void init_smp_call(void)
|
|
{
|
|
/**
|
|
* arch_init_smp_call() is abstracted because:
|
|
* - On x86, during CPU initialization, software reserves dedicated vectors and registers callback handlers
|
|
* for purposes such as notifications or posted interrupts.
|
|
* - On RISC-V, no special handling is required at present; this can be extended in the future if needed.
|
|
*/
|
|
arch_init_smp_call();
|
|
}
|