From: Wei Hu <weh@linux.microsoft.com>
To: linux-hyperv@vger.kernel.org
Cc: linux-kernel@vger.kernel.org,
"K. Y. Srinivasan" <kys@microsoft.com>,
Haiyang Zhang <haiyangz@microsoft.com>,
Wei Liu <wei.liu@kernel.org>, Dexuan Cui <decui@microsoft.com>,
Long Li <longli@microsoft.com>, Wei Hu <weh@microsoft.com>
Subject: [PATCH v4 2/9] mshv: clear SynIC mappings before freeing them
Date: Mon, 31 Aug 2026 11:26:40 +0000 [thread overview]
Message-ID: <20260831112704.2851147-3-weh@linux.microsoft.com> (raw)
In-Reply-To: <20260831112704.2851147-1-weh@linux.microsoft.com>
From: Wei Hu <weh@microsoft.com>
Publish and withdraw per-CPU SynIC mapping pointers explicitly so
interrupt readers cannot retain stale addresses across CPU hotplug
teardown or initialization failure. Address the CPUHP callback CPU
directly and guard all cleanup paths against missing pages.
Signed-off-by: Wei Hu <weh@microsoft.com>
---
drivers/hv/mshv_synic.c | 136 ++++++++++++++++++++--------------------
1 file changed, 69 insertions(+), 67 deletions(-)
diff --git a/drivers/hv/mshv_synic.c b/drivers/hv/mshv_synic.c
index 7c168e5a740d..c77688b8d23c 100644
--- a/drivers/hv/mshv_synic.c
+++ b/drivers/hv/mshv_synic.c
@@ -28,33 +28,31 @@ static int mshv_sint_irq = -1; /* Linux IRQ for mshv_sint_vector */
static u32 synic_event_ring_get_queued_port(u32 sint_index)
{
- struct hv_synic_event_ring_page **event_ring_page;
+ struct hv_synic_event_ring_page *event_ring_page;
volatile struct hv_synic_event_ring *ring;
struct hv_synic_pages *spages;
- u8 **synic_eventring_tail;
+ u8 *eventring_tail;
u32 message;
u8 tail;
spages = this_cpu_ptr(synic_pages);
- event_ring_page = &spages->synic_event_ring_page;
- synic_eventring_tail = (u8 **)this_cpu_ptr(hv_synic_eventring_tail);
+ event_ring_page = READ_ONCE(spages->synic_event_ring_page);
+ eventring_tail = READ_ONCE(*this_cpu_ptr(hv_synic_eventring_tail));
- if (unlikely(!*synic_eventring_tail)) {
+ if (unlikely(!eventring_tail)) {
pr_debug("Missing synic event ring tail!\n");
return 0;
}
- tail = (*synic_eventring_tail)[sint_index];
+ tail = eventring_tail[sint_index];
- if (unlikely(!*event_ring_page)) {
+ if (unlikely(!event_ring_page)) {
pr_debug("Missing synic event ring page!\n");
return 0;
}
- ring = &(*event_ring_page)->sint_event_ring[sint_index];
+ ring = &event_ring_page->sint_event_ring[sint_index];
- /*
- * Get the message.
- */
+ /* Get the message. */
message = ring->data[tail];
if (!message) {
@@ -78,9 +76,6 @@ static u32 synic_event_ring_get_queued_port(u32 sint_index)
mb();
message = ring->data[tail];
- /*
- * Ok, lets bail out.
- */
if (!message)
return 0;
}
@@ -88,15 +83,13 @@ static u32 synic_event_ring_get_queued_port(u32 sint_index)
ring->signal_masked = 1;
}
- /*
- * Clear the message in the ring buffer.
- */
+ /* Clear the message in the ring buffer. */
ring->data[tail] = 0;
if (++tail == HV_SYNIC_EVENT_RING_MESSAGE_COUNT)
tail = 0;
- (*synic_eventring_tail)[sint_index] = tail;
+ eventring_tail[sint_index] = tail;
return message;
}
@@ -408,16 +401,17 @@ mshv_intercept_isr(struct hv_message *msg)
void mshv_isr(void)
{
struct hv_synic_pages *spages = this_cpu_ptr(synic_pages);
- struct hv_message_page **msg_page = &spages->hyp_synic_message_page;
+ struct hv_message_page *msg_page;
struct hv_message *msg;
bool handled;
- if (unlikely(!(*msg_page))) {
+ msg_page = READ_ONCE(spages->hyp_synic_message_page);
+ if (unlikely(!msg_page)) {
pr_debug("Missing synic page!\n");
return;
}
- msg = &((*msg_page)->sint_message[HV_SYNIC_INTERCEPTION_SINT_INDEX]);
+ msg = &msg_page->sint_message[HV_SYNIC_INTERCEPTION_SINT_INDEX];
/*
* If the type isn't set, there isn't really a message;
@@ -462,12 +456,10 @@ static int mshv_synic_cpu_init(unsigned int cpu)
union hv_synic_siefp siefp;
union hv_synic_sirbp sirbp;
union hv_synic_sint sint;
- struct hv_synic_pages *spages = this_cpu_ptr(synic_pages);
- struct hv_message_page **msg_page = &spages->hyp_synic_message_page;
- struct hv_synic_event_flags_page **event_flags_page =
- &spages->synic_event_flags_page;
- struct hv_synic_event_ring_page **event_ring_page =
- &spages->synic_event_ring_page;
+ struct hv_synic_pages *spages = per_cpu_ptr(synic_pages, cpu);
+ struct hv_message_page *msg_page;
+ struct hv_synic_event_flags_page *event_flags_page;
+ struct hv_synic_event_ring_page *event_ring_page;
/*
* VMBus owns SIMP/SIEFP/SCONTROL when it is active.
* See hv_hyp_synic_enable_regs() for that initialization.
@@ -484,11 +476,11 @@ static int mshv_synic_cpu_init(unsigned int cpu)
simp.simp_enabled = true;
hv_set_non_nested_msr(HV_MSR_SIMP, simp.as_uint64);
}
- *msg_page = memremap(simp.base_simp_gpa << HV_HYP_PAGE_SHIFT,
- HV_HYP_PAGE_SIZE,
- MEMREMAP_WB);
+ msg_page = memremap(simp.base_simp_gpa << HV_HYP_PAGE_SHIFT,
+ HV_HYP_PAGE_SIZE, MEMREMAP_WB);
+ WRITE_ONCE(spages->hyp_synic_message_page, msg_page);
- if (!(*msg_page))
+ if (!msg_page)
goto cleanup_simp;
/*
@@ -500,35 +492,37 @@ static int mshv_synic_cpu_init(unsigned int cpu)
siefp.siefp_enabled = true;
hv_set_non_nested_msr(HV_MSR_SIEFP, siefp.as_uint64);
}
- *event_flags_page = memremap(siefp.base_siefp_gpa << HV_HYP_PAGE_SHIFT,
- HV_HYP_PAGE_SIZE, MEMREMAP_WB);
+ event_flags_page = memremap(siefp.base_siefp_gpa << HV_HYP_PAGE_SHIFT,
+ HV_HYP_PAGE_SIZE, MEMREMAP_WB);
+ WRITE_ONCE(spages->synic_event_flags_page, event_flags_page);
- if (!(*event_flags_page))
+ if (!event_flags_page)
goto cleanup_siefp;
/* Setup the Synic's event ring page */
sirbp.as_uint64 = hv_get_non_nested_msr(HV_MSR_SIRBP);
if (hv_root_partition()) {
- *event_ring_page = memremap(sirbp.base_sirbp_gpa << HV_HYP_PAGE_SHIFT,
- HV_HYP_PAGE_SIZE, MEMREMAP_WB);
+ event_ring_page = memremap(sirbp.base_sirbp_gpa << HV_HYP_PAGE_SHIFT,
+ HV_HYP_PAGE_SIZE, MEMREMAP_WB);
- if (!(*event_ring_page))
+ if (!event_ring_page)
goto cleanup_siefp;
} else {
/*
* On L1VH the hypervisor does not provide a SIRBP page.
* Allocate one and program its GPA into the MSR.
*/
- *event_ring_page = (struct hv_synic_event_ring_page *)
+ event_ring_page = (struct hv_synic_event_ring_page *)
get_zeroed_page(GFP_KERNEL);
- if (!(*event_ring_page))
+ if (!event_ring_page)
goto cleanup_siefp;
- sirbp.base_sirbp_gpa = virt_to_phys(*event_ring_page)
+ sirbp.base_sirbp_gpa = virt_to_phys(event_ring_page)
>> HV_HYP_PAGE_SHIFT;
}
+ WRITE_ONCE(spages->synic_event_ring_page, event_ring_page);
sirbp.sirbp_enabled = true;
hv_set_non_nested_msr(HV_MSR_SIRBP, sirbp.as_uint64);
@@ -565,19 +559,22 @@ static int mshv_synic_cpu_init(unsigned int cpu)
return 0;
cleanup_siefp:
- if (*event_flags_page)
- memunmap(*event_flags_page);
if (!vmbus_active) {
siefp.siefp_enabled = false;
hv_set_non_nested_msr(HV_MSR_SIEFP, siefp.as_uint64);
}
+ WRITE_ONCE(spages->synic_event_ring_page, NULL);
+ WRITE_ONCE(spages->synic_event_flags_page, NULL);
+ if (event_flags_page)
+ memunmap(event_flags_page);
cleanup_simp:
- if (*msg_page)
- memunmap(*msg_page);
if (!vmbus_active) {
simp.simp_enabled = false;
hv_set_non_nested_msr(HV_MSR_SIMP, simp.as_uint64);
}
+ WRITE_ONCE(spages->hyp_synic_message_page, NULL);
+ if (msg_page)
+ memunmap(msg_page);
return -EFAULT;
}
@@ -586,15 +583,17 @@ static int mshv_synic_cpu_exit(unsigned int cpu)
{
union hv_synic_sint sint;
union hv_synic_sirbp sirbp;
- struct hv_synic_pages *spages = this_cpu_ptr(synic_pages);
- struct hv_message_page **msg_page = &spages->hyp_synic_message_page;
- struct hv_synic_event_flags_page **event_flags_page =
- &spages->synic_event_flags_page;
- struct hv_synic_event_ring_page **event_ring_page =
- &spages->synic_event_ring_page;
+ struct hv_synic_pages *spages = per_cpu_ptr(synic_pages, cpu);
+ struct hv_message_page *msg_page;
+ struct hv_synic_event_flags_page *event_flags_page;
+ struct hv_synic_event_ring_page *event_ring_page;
/* VMBus owns SIMP/SIEFP/SCONTROL when it is active */
bool vmbus_active = hv_vmbus_exists();
+ msg_page = READ_ONCE(spages->hyp_synic_message_page);
+ event_flags_page = READ_ONCE(spages->synic_event_flags_page);
+ event_ring_page = READ_ONCE(spages->synic_event_ring_page);
+
/* Disable the interrupt */
sint.as_uint64 = hv_get_non_nested_msr(HV_MSR_SINT0 + HV_SYNIC_INTERCEPTION_SINT_INDEX);
sint.masked = true;
@@ -614,24 +613,18 @@ static int mshv_synic_cpu_exit(unsigned int cpu)
sirbp.as_uint64 = hv_get_non_nested_msr(HV_MSR_SIRBP);
sirbp.sirbp_enabled = false;
- if (hv_root_partition()) {
- hv_set_non_nested_msr(HV_MSR_SIRBP, sirbp.as_uint64);
- memunmap(*event_ring_page);
- } else {
+ if (!hv_root_partition())
sirbp.base_sirbp_gpa = 0;
- hv_set_non_nested_msr(HV_MSR_SIRBP, sirbp.as_uint64);
- free_page((unsigned long)*event_ring_page);
- }
+ hv_set_non_nested_msr(HV_MSR_SIRBP, sirbp.as_uint64);
/*
- * Release our mappings of the message and event flags pages.
- * When VMBus is not active, we enabled SIMP/SIEFP — disable
- * them. Otherwise VMBus owns the MSRs — leave them.
+ * When VMBus is not active, disable registers before withdrawing the
+ * pointers visible to interrupt readers.
*/
- memunmap(*event_flags_page);
if (!vmbus_active) {
union hv_synic_simp simp;
union hv_synic_siefp siefp;
+ union hv_synic_scontrol sctrl;
siefp.as_uint64 = hv_get_non_nested_msr(HV_MSR_SIEFP);
siefp.siefp_enabled = false;
@@ -640,18 +633,27 @@ static int mshv_synic_cpu_exit(unsigned int cpu)
simp.as_uint64 = hv_get_non_nested_msr(HV_MSR_SIMP);
simp.simp_enabled = false;
hv_set_non_nested_msr(HV_MSR_SIMP, simp.as_uint64);
- }
- memunmap(*msg_page);
-
- /* When VMBus is active it owns SCONTROL — leave it. */
- if (!vmbus_active) {
- union hv_synic_scontrol sctrl;
sctrl.as_uint64 = hv_get_non_nested_msr(HV_MSR_SCONTROL);
sctrl.enable = 0;
hv_set_non_nested_msr(HV_MSR_SCONTROL, sctrl.as_uint64);
}
+ WRITE_ONCE(spages->synic_event_ring_page, NULL);
+ WRITE_ONCE(spages->synic_event_flags_page, NULL);
+ WRITE_ONCE(spages->hyp_synic_message_page, NULL);
+
+ if (event_ring_page) {
+ if (hv_root_partition())
+ memunmap(event_ring_page);
+ else
+ free_page((unsigned long)event_ring_page);
+ }
+ if (event_flags_page)
+ memunmap(event_flags_page);
+ if (msg_page)
+ memunmap(msg_page);
+
return 0;
}
--
2.43.0
next prev parent reply other threads:[~2026-08-31 11:27 UTC|newest]
Thread overview: 27+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-08-25 4:04 [PATCH v3 0/7] mshv: add SEV-SNP support for MSHV root partitions Wei Hu
2026-08-25 4:04 ` [PATCH v3 1/7] mshv: add SEV-SNP UAPI definitions Wei Hu
2026-08-25 4:04 ` [PATCH v3 2/7] mshv: add SEV-SNP PSP request hypercall Wei Hu
2026-08-25 4:17 ` sashiko-bot
2026-08-25 4:04 ` [PATCH v3 3/7] mshv: add SEV-SNP isolated page hypercalls Wei Hu
2026-08-25 4:04 ` [PATCH v3 4/7] mshv: wire SEV-SNP partition ioctls Wei Hu
2026-08-25 4:22 ` sashiko-bot
2026-08-25 4:04 ` [PATCH v3 5/7] mshv: detect and report SEV-SNP support at init Wei Hu
2026-08-25 4:19 ` sashiko-bot
2026-08-25 4:04 ` [PATCH v3 6/7] mshv: use safe partition CPU feature defaults Wei Hu
2026-08-25 4:04 ` [PATCH v3 7/7] mshv: set up own SynIC registers on a nested root partition Wei Hu
2026-08-25 4:20 ` sashiko-bot
2026-08-31 11:26 ` [PATCH v4 0/9] mshv: add SEV-SNP support for MSHV root partitions Wei Hu
2026-08-31 11:26 ` [PATCH v4 1/9] mshv: retain memory regions until unmap succeeds Wei Hu
2026-08-31 11:48 ` sashiko-bot
2026-09-01 12:04 ` [EXTERNAL] " Wei Hu
2026-08-31 11:26 ` Wei Hu [this message]
2026-08-31 11:26 ` [PATCH v4 3/9] mshv: add SEV-SNP UAPI definitions Wei Hu
2026-08-31 11:26 ` [PATCH v4 4/9] mshv: add SEV-SNP PSP request hypercall Wei Hu
2026-08-31 11:26 ` [PATCH v4 5/9] mshv: add SEV-SNP isolated page hypercalls Wei Hu
2026-08-31 11:53 ` sashiko-bot
2026-08-31 11:26 ` [PATCH v4 6/9] mshv: wire SEV-SNP partition ioctls Wei Hu
2026-08-31 12:07 ` sashiko-bot
2026-08-31 11:26 ` [PATCH v4 7/9] mshv: detect and report SEV-SNP support at init Wei Hu
2026-08-31 11:26 ` [PATCH v4 8/9] mshv: use safe partition CPU feature defaults Wei Hu
2026-08-31 11:26 ` [PATCH v4 9/9] mshv: set up own SynIC registers on a nested root partition Wei Hu
2026-08-31 12:09 ` sashiko-bot
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20260831112704.2851147-3-weh@linux.microsoft.com \
--to=weh@linux.microsoft.com \
--cc=decui@microsoft.com \
--cc=haiyangz@microsoft.com \
--cc=kys@microsoft.com \
--cc=linux-hyperv@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=longli@microsoft.com \
--cc=weh@microsoft.com \
--cc=wei.liu@kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox