[PATCH 3/3 V2] hv: improve smp call to support debugging RTVM


Minggui Cao
 

Improve SMP call to support ACRN shell to operate RTVM.
before, the RTVM CPU can't be kicked off by IPI, so some
shell commands can't support it, like rdmsr/wrmsr, memory/
registers dump.

Signed-off-by: Minggui Cao <minggui.cao@...>
---
hypervisor/arch/x86/guest/virq.c | 5 +++++
hypervisor/arch/x86/notify.c | 20 ++++++++++++++++--
hypervisor/debug/shell.c | 22 +++++++++++---------
hypervisor/include/arch/x86/asm/guest/vcpu.h | 2 ++
hypervisor/include/arch/x86/asm/notify.h | 1 +
5 files changed, 38 insertions(+), 12 deletions(-)

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 <asm/per_cpu.h>
#include <asm/lapic.h>
#include <asm/guest/vm.h>
+#include <asm/guest/virq.h>

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 87f6930a6..6e1750d46 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
--
2.25.1


Eddie Dong
 

Acked-by: Eddie Dong <eddie.dong@...>

-----Original Message-----
From: acrn-dev@... <acrn-dev@...> On
Behalf Of Minggui Cao
Sent: Friday, September 23, 2022 12:08 AM
To: acrn-dev@...
Cc: Cao, Minggui <minggui.cao@...>
Subject: [acrn-dev] [PATCH 3/3 V2] hv: improve smp call to support debugging
RTVM

Improve SMP call to support ACRN shell to operate RTVM.
before, the RTVM CPU can't be kicked off by IPI, so some shell commands
can't support it, like rdmsr/wrmsr, memory/ registers dump.

Signed-off-by: Minggui Cao <minggui.cao@...>
---
hypervisor/arch/x86/guest/virq.c | 5 +++++
hypervisor/arch/x86/notify.c | 20 ++++++++++++++++--
hypervisor/debug/shell.c | 22 +++++++++++---------
hypervisor/include/arch/x86/asm/guest/vcpu.h | 2 ++
hypervisor/include/arch/x86/asm/notify.h | 1 +
5 files changed, 38 insertions(+), 12 deletions(-)

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 <asm/per_cpu.h>
#include <asm/lapic.h>
#include <asm/guest/vm.h>
+#include <asm/guest/virq.h>

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 87f6930a6..6e1750d46 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
--
2.25.1