Skip to content

Remove VP assist page for SNP VMs - #165

Open
Jenna Goddard (jennagoddard) wants to merge 1 commit into
microsoft:product/hcl-main/6.18from
jennagoddard:entryreason
Open

Jenna Goddard (jennagoddard) wants to merge 1 commit into
microsoft:product/hcl-main/6.18from
jennagoddard:entryreason

Conversation

@jennagoddard

@jennagoddard Jenna Goddard (jennagoddard) commented Oct 26, 2026 •

Copy link
Copy Markdown

Remove mshv driver dependency on the hypervisor provided VP assist page in the main dispatch loop for SNP VMs. There is no user-visible impact. For SNP VMs the VP assist page is no longer registered, and the dispatch loop relies on VMSA state instead of hypervisor provided entry reason. Synic messsages are used instead of the intercept page.

Copilot AI balanced review requested due to automatic review settings October 26, 2026 06:31

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

Unresolved dispatch issues can return stale exit data, lose intercept messages, and mishandle VTL1 exits.

3 open issues
What changed in this PR

Removes the SNP dispatch loop’s dependency on the hypervisor-provided VP assist page, using VMSA state and SynIC messages instead.

Changes:

  • Stops allocating VP assist pages for SNP guests and makes APIC EOI access null-safe.
  • Uses VMSA exit codes and tracks whether the lower VTL ran.
  • Routes SNP intercept messages through SynIC and disables assist-page-dependent capabilities.
File Description
drivers/​hv/​mshv_vtl_main.c Reworks SNP exit handling around VMSA state and SynIC messages.
drivers/​hv/​hv_common.c Disables VP assist page allocation for SNP guests.
arch/​x86/​hyperv/​hv_apic.c Uses the null-safe VP assist page accessor.

Review effort: Balanced

Comment thread drivers/hv/mshv_vtl_main.c Resolved
Comment thread drivers/hv/mshv_vtl_main.c Resolved
Comment thread drivers/hv/mshv_vtl_main.c Resolved

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔵 Needs a closer look

The SNP dispatch changes need human validation of interrupt-only wakeup behavior before approval.

2 open issues
1 resolved since last review

Review effort: Balanced

Copilot AI balanced review requested due to automatic review settings October 28, 2026 00:39

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

With interrupt offloading disabled, the halt-wake path overwrites userspace-managed VMSA state without guest execution, while interrupt-only exits introduce unnecessary userspace round trips.

2 open issues
1 resolved since last review

Review effort: Balanced

Comment thread drivers/hv/mshv_vtl_main.c Resolved
Copilot AI balanced review requested due to automatic review settings October 28, 2026 01:35

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔵 Needs a closer look

Ignoring the intercept handler’s return value causes interrupt-only exits to return to userspace with HVMSG_NONE instead of re-entering the guest, adding a round trip for every host interrupt when injection offload is disabled.

No open issues 🎉

2 resolved since last review

Review effort: Balanced

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔵 Needs a closer look

With interrupt-injection offload disabled, interrupt-only wakeups without an intercept now return to userspace with HVMSG_NONE instead of retrying in kernel, adding unnecessary round trips and bypassing the configured reentry policy.

No open issues 🎉

Review effort: Balanced

Comment thread drivers/hv/mshv_vtl_main.c Resolved

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔵 Needs a closer look

Ignoring the intercept handler’s retry result sends non-offloaded SNP vCPUs back to userspace on interrupt-only wakes with no message, regressing the previous in-kernel reentry behavior.

No open issues 🎉

Review effort: Balanced

@jennagoddard
Jenna Goddard (jennagoddard) force-pushed the entryreason branch 2 times, most recently from a4362c9 to 012bddd Compare October 28, 2026 16:27
Copilot AI balanced review requested due to automatic review settings October 28, 2026 16:27

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

A SynIC-message race can leave a halted guest with queued messages unprocessed indefinitely, and interrupt-only wakeups now cause unnecessary userspace round trips when interrupt-injection offload is disabled.

1 open issue

Review effort: Balanced

Comment thread drivers/hv/mshv_vtl_main.c Resolved
@tiala

tiala commented Oct 29, 2026 •

Copy link
Copy Markdown
Contributor

From the previous test, the kernel change fails to go through SNP CI test pipeline and there is new oneline change from Open VMM. We may try SNP Ci test pipeline again.

@tiala
tiala self-requested a review October 29, 2026 23:19

@dcui Dexuan Cui (dcui) left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For TDX, the PR looks good to me since I don't think it really changes the TDX related code, and my TDX VM works fine with the PR.

The mshv SNP VTL return path uses vtl_entry_reason and intercept_message
from the VP assist page to classify lower-VTL exits. The page is shared
with the host in an SNP VM, so its contents are not trustworthy for exit
dispatch.

Do not allocate VP assist pages for SNP guests. Classify architectural
exits from protected VMSA state and obtain synthetic intercept messages
from the SynIC message page. Track whether the lower VTL ran so a local
halt wakeup is not mistaken for a new VMSA exit, and keep the existing
kernel exit offloads and timer state synchronized.

Use a NULL-safe assist-page lookup in the Hyper-V APIC EOI path, and stop
advertising assist-page-backed intercept and return-action capabilities
for SNP and TDX guests.

This does not change the userspace ABI.

Signed-off-by: Jenna Goddard <jennagoddard@microsoft.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

With interrupt-injection offload disabled, interrupt-only SNP returns unnecessarily exit to userspace instead of reentering in-kernel, adding kernel/userspace round trips.

1 open issue
1 resolved since last review

Review effort: Balanced

Comment thread drivers/hv/mshv_vtl_main.c Resolved

@tiala tiala left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Try these changes on the local machine.

Comment thread drivers/hv/mshv_vtl_main.c Resolved
Comment on lines 862 to 2537
@@ -890,6 +895,9 @@ static void mshv_vtl_scan_proxy_interrupts(struct hv_per_cpu_context *per_cpu)
break;

if (message_type != HVMSG_X64_PROXY_INTERRUPT_INTERCEPT) {
/* SNP exit dispatch consumes non-proxy messages. */
if (hv_isolation_type_snp())
break;
WARN_ONCE(1, "Unexpected message type: %d\n", message_type);
vmbus_signal_eom(msg, message_type);
continue;
@@ -1871,9 +1879,13 @@ static bool mshv_vtl_process_intercept(void)
{
struct hv_per_cpu_context *mshv_cpu;
void *synic_message_page;
struct hv_message *exit_msg;
struct hv_message *msg;
u32 message_type;

exit_msg = (struct hv_message *)mshv_vtl_this_run()->exit_message;
WRITE_ONCE(exit_msg->header.message_type, HVMSG_NONE);

mshv_cpu = this_cpu_ptr(hv_context.cpu_context);
synic_message_page = mshv_cpu->synic_message_page;
if (unlikely(!synic_message_page))
@@ -1884,7 +1896,7 @@ static bool mshv_vtl_process_intercept(void)
if (message_type == HVMSG_NONE)
return true;

memcpy(mshv_vtl_this_run()->exit_message, msg, sizeof(*msg));
memcpy(exit_msg, msg, sizeof(*msg));
vmbus_signal_eom(msg, message_type);

return false;
@@ -2041,7 +2053,7 @@ static void mshv_vtl_switch_to_vtl0_irqoff(void)

armed = mshv_tdx_halt_timer_pre(flags & MSHV_VTL_RUN_FLAG_HALTED);

/* A VTL2 TDX kernel doesn't allocate hv_vp_assist_page at the moment */
/* Hardware-isolated guests don't allocate hv_vp_assist_page. */
hvp = hv_vp_assist_page ? hv_vp_assist_page[smp_processor_id()] : NULL;

/*
@@ -2095,10 +2107,13 @@ static void mshv_vtl_switch_to_vtl0_irqoff(void)
#endif
} if (hv_isolation_type_snp()) {
#if defined(CONFIG_SEV_GUEST)
if (unlikely(flags & MSHV_VTL_RUN_FLAG_HALTED))
if (unlikely(flags & MSHV_VTL_RUN_FLAG_HALTED)) {
native_safe_halt();
else
} else {
this_cpu_write(mshv_vtl_lower_vtl_ran, true);
snp_mshv_vtl_return(target_vtl.use_target_vtl ? target_vtl.target_vtl : 0);
this_cpu_inc(num_vtl0_transitions);
}
return;
#endif
} else {
@@ -2450,25 +2465,6 @@ static void mshv_snp_clear_exit_code(struct sev_es_save_area *vmsa, bool int_sha
vmsa->vintr_ctrl &= ~V_GUEST_BUSY_MASK;
}

/*
* Determine if this interrupt was handled completely in the kernel.
*
* Returns true if the exit was handled entirely in kernel, and the VMPL should be re-entered.
* Returns false if the exit must be handled by user-space.
*/
static bool mshv_snp_try_handle_interrupt_entry(struct mshv_vtl_run *run)
{
struct hv_vp_assist_page *hvp = hv_vp_assist_page[smp_processor_id()];

if (!(run->offload_flags & MSHV_VTL_OFFLOAD_FLAG_INTR_INJECT) ||
READ_ONCE(hvp->vtl_entry_reason) != MSHV_ENTRY_REASON_INTERRUPT)
return false;

mshv_snp_clear_exit_code(snp_this_vmsa(), false);
return true;
}


/*
* Try to handle the incomplete IPI SEV-SNP exit.
*
@@ -2501,16 +2497,27 @@ static bool mshv_snp_try_handle_incomplete_ipi(struct mshv_vtl_run *run,
* Returns true if the exit was handled entirely in kernel, and the VMPL should be re-entered.
* Returns false if the exit must be handled by user-space.
*/
static bool mshv_snp_try_handle_exit(struct mshv_vtl_run *run)
static bool mshv_snp_try_handle_exit(struct mshv_vtl_run *run, bool lower_vtl_ran)
{
const bool intr_inject = MSHV_VTL_OFFLOAD_FLAG_INTR_INJECT & run->offload_flags;
const bool x2apic = MSHV_VTL_OFFLOAD_FLAG_X2APIC & run->offload_flags;
union hv_input_vtl target_vtl = READ_ONCE(run->target_vtl);
struct sev_es_save_area *vmsa;

if (!intr_inject)
/* Kernel exit offloads are supported only for VTL 0. */
if (target_vtl.use_target_vtl && target_vtl.target_vtl > 0)
return false;

vmsa = snp_this_vmsa();
/*
* native_safe_halt() may wake without entering the lower VTL. In that
* case the VMSA still contains the benign SVM_EXIT_INTR sentinel left
* by the previous handled exit.
*/
if (!intr_inject)
return false;
if (!lower_vtl_ran)
goto handled;

switch (vmsa->guest_exit_code) {
case SVM_EXIT_AVIC_INCOMPLETE_IPI:
@@ -2528,19 +2535,10 @@ static bool mshv_snp_try_handle_exit(struct mshv_vtl_run *run)
run->offload_flags |= MSHV_VTL_OFFLOAD_FLAG_HALT_IDLE;
goto handled;
case SVM_EXIT_INTR:

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please origin behavior

if (message_type != HVMSG_X64_PROXY_INTERRUPT_INTERCEPT) {
/* SNP exit dispatch consumes non-proxy messages. */
if (hv_isolation_type_snp())
break;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Keep “continue” here or just ignore warning for snp guest.

Comment on lines +2514 to +2515
* case the VMSA still contains the benign SVM_EXIT_INTR sentinel left
* by the previous handled exit.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is fast path code for halt operation while this version now only enables slow path for halt. So this will introduce conflict.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants