diff --git a/hypervisor/arch/x86/guest/virq.c b/hypervisor/arch/x86/guest/virq.c index 7fc825ef1..8b8f5dd9f 100644 --- a/hypervisor/arch/x86/guest/virq.c +++ b/hypervisor/arch/x86/guest/virq.c @@ -388,6 +388,11 @@ int32_t acrn_handle_pending_request(struct acrn_vcpu *vcpu) if (bitmap_test_and_clear_lock(ACRN_REQUEST_EOI_EXIT_BITMAP_UPDATE, pending_req_bits)) { vcpu_set_vmcs_eoi_exit(vcpu); } + + if (bitmap_test_and_clear_lock(ACRN_REQUEST_SMP_CALL, pending_req_bits)) { + handle_smp_call(); + } + } } diff --git a/hypervisor/arch/x86/notify.c b/hypervisor/arch/x86/notify.c index 1fc0d2591..d3361cf78 100644 --- a/hypervisor/arch/x86/notify.c +++ b/hypervisor/arch/x86/notify.c @@ -13,6 +13,7 @@ #include #include #include +#include static uint32_t notification_irq = IRQ_INVALID; @@ -37,6 +38,11 @@ static void kick_notification(__unused uint32_t irq, __unused void *data) } } +void handle_smp_call(void) +{ + kick_notification(0, NULL); +} + void smp_call_function(uint64_t mask, smp_call_func_t func, void *data) { uint16_t pcpu_id; @@ -47,10 +53,21 @@ void smp_call_function(uint64_t mask, smp_call_func_t func, void *data) pcpu_id = ffs64(mask); while (pcpu_id < MAX_PCPU_NUM) { bitmap_clear_nolock(pcpu_id, &mask); - if (is_pcpu_active(pcpu_id)) { + 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; + + struct acrn_vcpu *vcpu = get_ever_run_vcpu(pcpu_id); + + if ((vcpu != NULL) && (is_lapic_pt_enabled(vcpu))) { + vcpu_make_request(vcpu, ACRN_REQUEST_SMP_CALL); + } else { + send_single_ipi(pcpu_id, NOTIFY_VCPU_VECTOR); + } } else { /* pcpu is not in active, print error */ pr_err("pcpu_id %d not in active!", pcpu_id); @@ -58,7 +75,6 @@ void smp_call_function(uint64_t mask, smp_call_func_t func, void *data) } pcpu_id = ffs64(mask); } - send_dest_ipi_mask((uint32_t)smp_call_mask, NOTIFY_VCPU_VECTOR); /* wait for current smp call complete */ wait_sync_change(&smp_call_mask, 0UL); } diff --git a/hypervisor/debug/shell.c b/hypervisor/debug/shell.c index ec8eb1f59..4a0451fd5 100644 --- a/hypervisor/debug/shell.c +++ b/hypervisor/debug/shell.c @@ -993,12 +993,6 @@ static int32_t shell_vcpu_dumpreg(int32_t argc, char **argv) goto out; } - if (is_lapic_pt_enabled(vcpu)) { - shell_puts("Please switch to vlapic mode for vcpu register dump!\r\n"); - status = 0; - goto out; - } - pcpu_id = pcpuid_from_vcpu(vcpu); dump.vcpu = vcpu; dump.str = shell_log_buf; @@ -1568,9 +1562,13 @@ static int32_t shell_rdmsr(int32_t argc, char **argv) } if (ret == 0) { - val = msr_read_pcpu(msr_index, pcpu_id); - snprintf(str, MAX_STR_SIZE, "rdmsr(0x%x):0x%lx\n", msr_index, val); - shell_puts(str); + if (pcpu_id < get_pcpu_nums()) { + val = msr_read_pcpu(msr_index, pcpu_id); + snprintf(str, MAX_STR_SIZE, "rdmsr(0x%x):0x%lx\n", msr_index, val); + shell_puts(str); + } else { + shell_puts("pcpu id is out of range!\n"); + } } return ret; @@ -1606,7 +1604,11 @@ static int32_t shell_wrmsr(int32_t argc, char **argv) } if (ret == 0) { - msr_write_pcpu(msr_index, val, pcpu_id); + if (pcpu_id < get_pcpu_nums()) { + msr_write_pcpu(msr_index, val, pcpu_id); + } else { + shell_puts("pcpu id is out of range!\n"); + } } return ret; diff --git a/hypervisor/include/arch/x86/asm/guest/vcpu.h b/hypervisor/include/arch/x86/asm/guest/vcpu.h index 95527e432..925dab65d 100644 --- a/hypervisor/include/arch/x86/asm/guest/vcpu.h +++ b/hypervisor/include/arch/x86/asm/guest/vcpu.h @@ -105,6 +105,8 @@ */ #define ACRN_REQUEST_SPLIT_LOCK 10U +#define ACRN_REQUEST_SMP_CALL 11U + /** * @} */ diff --git a/hypervisor/include/arch/x86/asm/notify.h b/hypervisor/include/arch/x86/asm/notify.h index d8473a16e..f9d38b6d1 100644 --- a/hypervisor/include/arch/x86/asm/notify.h +++ b/hypervisor/include/arch/x86/asm/notify.h @@ -17,6 +17,7 @@ struct acrn_vm; void smp_call_function(uint64_t mask, smp_call_func_t func, void *data); void setup_notification(void); +void handle_smp_call(void); void setup_pi_notification(void); #endif