# Inside hvix64: the guest execution engine

Tracing VMCS ownership, segment state, host interrupts, enlightened VMCS access and VTL switching through Hyper-⁠V's Intel execution paths.

Author: Berkan YILDIZ
Published: 2026-10-08
Tags: Hyper-V, Reverse engineering, Intel VMX, VTL, Windows internals
Canonical: <https://blog.berkan.fr/hvix64-execution-engine>


Guest execution in `hvix64.exe` spans several objects: the partition, a scheduled virtual processor, its active virtual trust level, and the logical processor executing it. The scheduler connects those objects to a selected virtual-machine control structure (VMCS), while assembly entry and exit paths transfer the processor state that VMX leaves to software.

This analysis reconstructs that execution path in build **`10.0.26100.9444`**. It follows VMCS ownership and launch state, host and guest segment state, native and enlightened field access, interrupt dispatch, and the transition between VTL contexts. This is the second part of a series; the [first part](/hvix64-partition-lifecycle) covers the partition object's lifetime and access checks beneath this execution model.

Three implementation details connect these paths. VMCS selection includes explicit processor ownership tracking. Interrupts delivered through the host IDT and external-interrupt VM exits can feed the same per-processor queue. VTL isolation combines a selectable execution context within each VP with separately managed memory protections.

## Target binary and methodology

The target is **`hvix64.exe` version `10.0.26100.9444`**, an Intel x64 Hyper-V image of **2,057,688 bytes**, with preferred image base **`0xFFFFF80000000000`**. The analysis uses IDA 9.4 and Hex-Rays.

```text SHA-256
cf5af317f300b7da25f37d5dc6ca75bff91b6b868d89f337d23ec1773340ce8a
```

All code addresses below are **RVAs**. Structure offsets are relative to the named base object and apply to this build. Recovered names such as `HvpScheduleVp_ContextSwitch` and `_HV_PCR` are analyst annotations; the associated behavior is established from instructions, field accesses and callers.

Assembly listings are shortened transcriptions. C listings are reduced reconstructions with descriptive local names, with omissions identified in the surrounding text. The findings are based on static analysis. Runtime backend selection, configuration-dependent allocation counts and completion of cross-processor operations remain outside the verified scope.

## Partition, VP, VTL and logical processor

Four identities determine the execution context:

| Identity | Role |
| --- | --- |
| Partition | The owning isolation and resource context. |
| Virtual processor, or VP | A guest processor whose execution can be scheduled. |
| VTL context | The selected trust context and associated state within a VP. |
| Logical processor, or LP | The hardware execution context currently running hypervisor or guest code. |

VMX operates on logical processors, including separate hardware threads on a physical core. VMX root operation is the hypervisor's execution environment. The Windows root partition's kernel executes as a guest under that hypervisor and has its own processor state.

![Conceptual execution model: partition P owns VP0 and VP1; VP0 selects a VTL context, whose VMCS state is made current on logical processor 3. The logical processor has its own processor record and VMXON pointer.](/images/blog/hvix64-execution-contexts.svg)

*Example placement of a context on an LP. The diagram does not specify allocation counts or permanent processor affinity.*

The inspected hypervisor paths access the current execution context through GS: `gs:[0]` supplies the per-processor record, `gs:[0x358]` the current VP, and `gs:[0x360]` the current partition. The partition-ID query handler described in the [partition analysis](/hvix64-partition-lifecycle#a-tiny-handler-identifies-the-current-partition) uses the same current-partition pointer.

The VP links this processor-local state to the active VTL context and its VMCS software record:

| Base object | Offset | Observed use |
| --- | --- | --- |
| VP | `0x408` | Owning partition pointer. |
| VP | `0x148 + 8 * vtl` | Pointer to a selected VTL context. |
| VP | `0x3C0` | Current VTL-context pointer. |
| VTL context | `0x14` | VTL number read by the switch paths. |
| VTL context | `0x13C0` | Start of the execution-control record passed to VMX helpers. |
| VTL context | `0x13E8` | Pointer to the selected VMCS software record. |
| VMCS software record | `0x120` | Processor-owner identifier compared with `PCR + 0x8`. |
| VMCS software record | `0x180` / `0x188` | Backing virtual pointer / address used by the VMCS-selection path. |

These offsets describe software records surrounding the opaque hardware VMCS region. In particular, record offset `0x188` stores the backing address used for VMCS selection; architectural VMCS-field encodings belong to a separate interface.

## VMCS selection and processor ownership

`HvpScheduleVp_ContextSwitch`, at **`0x216F00`**, updates the processor's current VP and partition and selects the associated VMCS state. Its selection condition checks both whether the VP changed and whether the selected VMCS record's owner identifier matches the processor identifier at `PCR + 0x8`.

The relevant portion reduces to:

```c Reduced reconstruction · RVA 0x216F00
trust = *(void **)((unsigned char *)vp + 0x3C0);
state = *(void **)((unsigned char *)trust + 0x13E8);

if (vp != currentVp || state->Owner != processor->Identifier) {
    processor->CurrentVp = vp;                  // PCR + 0x358
    processor->CurrentPartition = vp->Owner;    // PCR + 0x360
    SelectVmcs(trust);
    ReconcileProcessorState(vp, trust);
}
```

`SelectVmcs` and `ReconcileProcessorState` are descriptive names for portions of this function. The full path also handles MSRs, debug state, accounting and configuration-dependent state.

On the native VMX branch, selection reaches `VMPTRLD` using the address at the selected software record's `0x188`. A related helper at **`0x216E98`** writes the current processor identifier into `state + 0x120`. Together, these accesses establish explicit processor ownership tracking and a selection path that accounts for the record's current owner.

The ordinary VMCS initialization path at **`0x351898`** zeroes a 4 KiB backing region, initializes its revision identifier from VMX capability data on the native branch, and sets up host and guest controls. It also supports the enlightened interface described below. Other helpers select an embedded default record or an additional descriptor. The inspected paths establish the relationship between these records, but leave the complete allocation count dependent on configuration and additional allocation paths.

Intel requires an active VMCS to belong to only one LP at a time. Moving it to another LP requires clearing it on the previous processor before loading it on the destination. This architectural constraint provides the context for hvix64's owner identifier and reselection logic. See the [SDM, Volume 3C, §27.11.1](https://cdrdv2.intel.com/v1/dl/getContent/671506) (order number 326019-093, September 2026).

### Per-processor VMXON state

`HvVmxOn`, at **`0x340A60`**, enters VMX operation using a pointer held in the processor record. After feature-control setup and setting `CR4.VMXE`, it executes:

```asm HvVmxOn · shortened native path
mov     r10, gs:0
; Feature-control setup omitted.
mov     rax, cr4
bts     rax, 0Dh
mov     cr4, rax
vmxon   qword ptr [r10+29F58h]
```

The VMXON region belongs to the logical processor's VMX setup. The VMCS backing address is selected separately through the VP's execution context, giving the two allocations distinct roles in the entry path.

### Launch state belongs to the selected VMCS

The entry loop uses a byte at **VMCS software record `+ 0x127`** to choose between launch and resume. A helper at **`0x21F1F0`** resets it to zero and, when backing VMCS storage is present, executes `VMCLEAR` on the address at `+0x188`.

The byte therefore tracks launch state for the selected VMCS. Clearing the VMCS and resetting the byte prepares that record for a subsequent `VMLAUNCH`.

## The entry and exit loop

The central assembly loop is labeled `HvpVmxRunGuestLoop`, at **`0x3A8000`**. It spans guest entry and a VM-exit landing point selected through the VMCS host RIP. That hardware transition connects blocks that a conventional call/return graph does not capture.

The loop calls the housekeeping helper at **`0x35D330`** and `HvpVmxPrepareVmEntry` at **`0x35C180`**. It restores guest register state from a software transfer area, then reaches the launch-state decision:

```asm Guest entry · shortened from RVA 0x3A8000 {3,6,8-11}
xor     eax, eax
mov     edx, 1
cmpxchg [r9+127h], dl
; Guest-register loads follow, without changing the decision's flags.
; r9 here initially identifies the selected VMCS software record.
jz      first_entry

vmresume
jmp     entry_failed
first_entry:
vmlaunch
jmp     entry_failed
```

The `VMPTRLD` instruction chooses the current VMCS; `VMLAUNCH` and `VMRESUME` enter the guest described by it. A normal VM exit does not return to the instruction following `VMLAUNCH`. It loads the host state programmed into the VMCS.

For the main path, the host RIP is **`0x3A843D`**, inside this same loop. There the assembly saves guest GPRs and XMM transfer state, obtains the exit reason, and handles the external-interrupt case before calling the main C-level exit handler:

```text Main native execution cycle · selected RVAs
0x35C180  Prepare entry state
0x3A8308  VMRESUME
0x3A8310  VMLAUNCH
    ... guest execution ...
0x3A843D  Host RIP used by the main VM-exit path
    ... save guest transfer state; read exit reason ...
0x3A78F0  External-interrupt triage, when basic reason == 1
0x3A857D  Call HvVmExitHandler
0x3A8582  Jump back to the entry loop
```

The assembly loop performs external-interrupt triage before `HvVmExitHandler` receives control. The exit handler consequently represents only the inner portion of the exit path; the outer assembly code owns the transfer of register state and the first dispatch decision.

Guest GPRs and XMM transfer state are loaded and saved explicitly by the loop. It also clears portions of the transfer storage and scratch registers along the path. Separate helpers handle additional processor state, with the exact sequence depending on the entry backend and enabled features. The complete context transition therefore combines hardware VMCS state with software register management.

`HvVmExitHandler`, at **`0x35E230`**, and `HvpDispatchVmExitByReason`, at **`0x35D460`**, connect exit reasons to emulation, hypercall handling, event processing and other workers. The dispatcher's exception/NMI case reads interruption information and examines the event type before choosing its path. Entry preparation reconciles the resulting state before execution resumes.

## Segment registers and the host context

Segment-state management covers the hypervisor's execution environment and the guest state loaded on VM entry. The two use separate descriptor tables, selectors and base values.

### The hypervisor establishes its own tables and GS base

At the image's startup entry, **`0x3A6610`**, the assembly loads a GDT and IDT, loads data-segment selectors, loads the task register, and programs `IA32_GS_BASE`:

```asm Startup · selected instructions
lgdt    fword ptr [image_base+232C6h]
lidt    fword ptr [image_base+232B6h]
mov     eax, 20h
mov     fs, ax
mov     gs, ax
mov     ds, ax
mov     es, ax
mov     ss, ax
mov     eax, 30h
ltr     ax
; WRMSR IA32_GS_BASE (C0000101h) points at the initial processor record.
```

The `image_base` notation identifies image-relative descriptor locations in this shortened listing.

For later VM exits, the helper at **`0x3527C8`** programs the corresponding VMCS host-state fields. A checking routine at **`0x35EE44`** compares them with the expected live state. These routines establish the following host-context values:

| Host state | Value or source in this build's inspected path |
| --- | --- |
| CS selector | `0x10` |
| SS, DS, ES, FS, GS selectors | `0x20` |
| TR selector | `0x30` |
| FS base | Zero |
| GS base | Current processor-record pointer |
| TR base | Pointer at `PCR + 0x450` |
| GDTR base | Pointer at `PCR + 0x448` |
| IDTR base | Pointer at `PCR + 0x440` |
| CR3 | Value at `PCR + 0x458` |
| RIP | Main exit landing point `0x3A843D` |
| RSP | A separately programmed host stack pointer |

These selectors describe hvix64's own descriptor tables. On the native branch, the GS-base field is `0x6C08`, the IDTR-base field is `0x6C0E`, and host RSP is `0x6C14`.

That GS base explains why a VM exit can immediately use `gs:[0x358]` and `gs:[0x360]` even if the guest had been using GS for entirely different data. The host's base is part of the transition state. The selector value alone does not describe the 64-bit GS base.

### Guest segment descriptors

The guest-side wrappers separately access descriptor state. For example, the inspected CS setters are:

| Guest CS component | VMCS encoding | Setter RVA | Enlightened-page offset |
| --- | --- | --- | --- |
| Base | `0x6808` | `0x332524` | `0xE0` |
| Limit | `0x4802` | `0x33255C` | `0x94` |
| Access rights | `0x4816` | `0x3324EC` | `0xBC` |

The getter at **`0x34EA00`** reads the same CS-base field. On the native branch it executes `VMREAD`; on the enlightened branch it reads the corresponding memory slot. These matching accesses establish that the descriptor's hidden state is represented separately from its visible selector.

The hypervisor programs the selected guest context's segment state through its VMCS representation. VM entry loads that state; VM exit restores the host environment described in the earlier table. The visible selector and the descriptor's base, limit and access rights are distinct components of the transition.

The VP/VTL switch path also explicitly saves and restores **`IA32_KERNEL_GS_BASE` (`0xC0000102`)**. This MSR supplies the guest's kernel-GS swap partner and is managed separately from the host GS base loaded on VM exit.

## Native and enlightened VMCS access

The field-access wrappers support two backends: architectural VMCS instructions and a memory interface reached through **`gs:[0x2C740]`**. The memory layout and write-side synchronization identify the latter as an enlightened VMCS page.

`HvpVmreadExitQualification`, at **`0x332194`**, checks bit zero of the global dword at **`0xAF150`**. When clear, it executes a hardware VMREAD of field **`0x6400`**. When set, it reads a qword at offset **`0x2D0`** of the memory object referenced through GS.

```c Reduced reconstruction · RVA 0x332194
if (EnlightenedVmcsEnabled) {
    *value = *(UINT64 *)((unsigned char *)enlightenedVmcs + 0x2D0);
} else {
    *value = ReadHardwareVmcs(0x6400);
}
```

The offsets match Microsoft's published [`HV_VMX_ENLIGHTENED_VMCS`](https://learn.microsoft.com/en-us/virtualization/hyper-v-on-windows/tlfs/datatypes/hv_vmx_enlightened_vmcs):

| Accessed value | Native VMCS encoding | Enlightened-page offset |
| --- | --- | --- |
| Guest physical address associated with an exit | `0x2400` | `0x2A8` |
| Basic exit reason and flags | `0x4402` | `0x2B4` |
| Exit interruption information | `0x4404` | `0x2B8` |
| IDT-vectoring information | `0x4408` | `0x2C0` |
| Exit qualification | `0x6400` | `0x2D0` |
| Guest RFLAGS | `0x6820` | `0x308` |
| Guest interruptibility | `0x4824` | `0x310` |
| Entry interruption information | `0x4016` | `0x320` |

The enlightened VMCS is a documented memory interface for nested virtualization. An L1 hypervisor updates the page with ordinary loads and stores, while L0 consumes it for nested execution. Microsoft's [nested-virtualization documentation](https://learn.microsoft.com/en-us/virtualization/hyper-v-on-windows/tlfs/nested-virtualization) defines this interface and its clean-field contract. Its offsets describe a public structure, whereas the hardware VMCS region remains opaque. The enlightened branches in the accessors below are taken when hvix64 itself is that L1 hypervisor, running nested under another Hyper-V.

### Clean bits describe modified groups

The write-side accessors maintain clean-field groups. The guest-interruptibility setter at **`0x32F410`** performs the following sequence on its enlightened branch:

```asm Guest-interruptibility setter · enlightened branch
mov     rdx, gs:2C740h
mov     eax, [rcx]
btr     dword ptr [rdx+338h], 0Ah
mov     [rdx+310h], eax
```

Offset `0x338` holds clean-field groups. Bit 10 is the guest-basic group (`GUEST_BASIC`); clearing it tells the consuming hypervisor that this group changed. The native branch instead writes VMCS field `0x4824`.

There are matching examples elsewhere. The host-RSP setter at **`0x3407E0`** clears clean bit 13 (`HOST_POINTER`) and writes page offset `0x268`, or uses native field `0x6C14`. The entry-interruption setter at **`0x3323D8`** clears bit 5 (`CONTROL_EVENT`) and writes `0x320`, or uses native field `0x4016`. The CS setters above clear bit 12 (`GUEST_GRP2`) before updating their descriptor slots.

A clean bit communicates whether the consuming hypervisor can reuse a field group's previous values. The producer clears the bit when updating that group. The native exit-qualification wrapper follows a different access pattern: each invocation of its native branch issues `VMREAD`, with no per-field read-validity check in the inspected wrapper.

### Saved exit state and emulated state

Separate paths retain exit information and reconcile emulated register state. The external-interrupt triage routine can obtain interruption information from a saved record at `context + 0x48` on an alternate entry path. The RFLAGS helper at **`0x229424`** reads current RFLAGS through the backend accessor, then conditionally merges selected bits with a software-held value at VTL execution-control record offset `0x118`.

These paths serve separate purposes: saved records retain exit information, the RFLAGS helper reconciles emulated state, and the enlightened page exchanges VMCS fields with another hypervisor. Their storage and validity rules must be analyzed independently.

The outer loop constructs its entry record at **`VP + 0xEC0`**. Its backend-selection byte at **entry record `+ 0xB1`** consequently resides at **`VP + 0xF71`**. This field belongs to the embedded entry record; the recovered VP type separately names a field `CacheValidFlags` at `VP + 0xB1`. Tracking the base pointer through the loop resolves the apparent overlap and identifies the alternate sources of saved exit information.

The enlightened branches are therefore the L1 side of the interface: hvix64 writes the page and an outer Hyper-V consumes it. When hvix64 is the L0 hypervisor hosting a nested one, it reads that hypervisor's page instead, which is a different role from the one these accessors implement. VTL switching is an independent relationship within a partition, examined below.

## Host IDT and interrupt handlers

hvix64 installs a host IDT and contains executable interrupt and exception handlers. Three parts of the initialization and execution paths establish how that environment is selected:

1. Startup at `0x3A6610` executes `LIDT` with the descriptor at image RVA `0x232B6`.
2. Processor setup places an IDT pointer in `PCR + 0x440`; `0x3527C8` programs it into `HOST_IDTR_BASE` for subsequent exits.
3. The image contains vector stubs that save state, dispatch or queue work, and return with `IRETQ`.

The on-disk descriptor specifies a `0xFFF` limit and a table at image RVA `0x22000`. The stored records contain handler targets and gate metadata. Reconstructing the final live gate layout requires tracing any loader-time transformation, which is outside this analysis. The initialization instructions, host-state fields and handler bodies establish the host interrupt environment independently of that reconstruction.

For a concrete example, the vector-`0x20` stub at **`0x3B0040`** queues the vector through GS and returns:

```asm Host vector 0x20 stub · shortened from RVA 0x3B0040
push    rax
movzx   eax, byte ptr gs:340h
mov     dword ptr gs:308h[rax*4], 20h
inc     eax
mov     gs:340h, eax
; Restore the saved register and remove temporary stack storage.
iretq
```

The image also contains exception stubs for page fault at **`0x3A89C0`** and machine check at **`0x3A8D80`**. The `0xFF` path at **`0x3AF940`** returns with `IRETQ`. Handler complexity varies by vector, from short return paths to exception processing.

### External-interrupt VM exits

With the relevant controls enabled, an external interrupt occurring during guest execution can cause a VM exit. The outer loop sees basic reason **1** and invokes `HvpTriageExternalInterruptExit`, at **`0x3A78F0`**, before the main exit handler.

The routine reads interruption information from the selected backend. The enlightened interface supplies it at **`0x2B8`**; the adjacent slot at `0x2B4` holds the exit reason.

The inspected vector split is:

| Vector | Action in this triage routine |
| --- | --- |
| `0xF0`–`0xFE` | Call the global interrupt-dispatch pointer. |
| `0xFF` | Select a spurious-interrupt path using `PCR + 0x198`. |
| `0xDF` | Skip both dispatch and queuing here. |
| Other vectors | Append the vector at `PCR + 0x308 + 4 * index`; update the index at `PCR + 0x340`. |

The `0xDF` case refers to an external-interrupt vector; the architectural double-fault exception is vector `8`. The queue offsets match those used by the vector-`0x20` host stub. Host-IDT delivery and external-interrupt VM exits can therefore converge on the same processor-local storage. The complete queue-drain and device-ownership policies remain outside this trace.

The event's arrival path determines the initial dispatch mechanism. An external-interrupt VM exit reaches the programmed host RIP and triage routine, while an event delivered through the host IDT reaches a vector stub. The shared queue connects these paths to deferred interrupt processing.

### Pending events and guest injection

A queued physical vector does not automatically become a guest interrupt with the same number. Guest delivery involves the selected VP/VTL's virtual interrupt state and the VM-entry interface.

The dispatcher at **`0x35D460`** classifies exception/NMI exits using the interruption-info type bits. Type **2** selects the NMI path. In one NMI-window handling branch, it clears execution-control bit `0x400000` (bit 22, NMI-window exiting) before requesting pending-event reevaluation; another configuration can reflect the exit through a different path.

The helper labeled `HvpEvaluatePendingInterrupts`, at **`0x2C93AC`**, reaches **`0x2EF3B0`**, which updates pending-work flags in the current VTL context. This schedules reevaluation of event delivery; injection is handled through the subsequent entry path.

The virtual-APIC side also starts with the active trust context. `HvpEvaluatePendingApicInterrupt`, at **`0x2FC19C`**, obtains it through `VP + 0x3C0` and invokes a worker using the interrupt-state block at **VTL context `+ 0x80`**. Its branches inspect pending-event state and update delivery flags or guest interrupt-control state. The active VTL context thus participates directly in the guest interrupt-delivery decision, with configuration-dependent paths through the worker.

The final architectural delivery interface is explicit. `HvVmxWriteEntryInterruptionInfo`, at **`0x3323D8`**, writes VM-entry field **`0x4016`**, or the equivalent enlightened-page slot. It is called by entry preparation and exit-handling paths. Error-code and instruction-length state have separate accessors.

The NMI path also contains a helper at **`0x3A5840`** that builds a return frame and ends with `IRETQ`. Its frame construction and architectural return semantics form part of the hypervisor's event handling. A complete account of pending-event selection, APIC priority and nested intercepts requires tracing the callers and configuration-specific branches beyond these shared primitives.

## VTL switching selects another context within the VP

Microsoft's [VSM description](https://learn.microsoft.com/en-us/virtualization/hyper-v-on-windows/tlfs/vsm) defines VTLs as hierarchical protection contexts with private VP state and memory protections within a partition. The active VTL selects a trust context inside the existing VP and partition.

The corresponding data flow is visible in the binary. `HvCallVtlCall`, at **`0x2931A0`**, reads the current VTL through `VP + 0x3C0`, then context offset `0x14`, and selects the next higher enabled target. Its candidate bitmap comes from **`VP + 0x1B0`**. This agrees with the documented [VTL-call operation](https://learn.microsoft.com/en-us/virtualization/hyper-v-on-windows/tlfs/hypercalls/hvcallvtlcall).

The enabled-target bitmap is specifically at `VP + 0x1B0`. The recovered type also names a `VtlBitmask` field at `VP + 0x3E0`, used by other state-management code. The call path's field accesses distinguish these two values.

The switching helper at **`0x2AFBC4`** compares the requested level with the current one. If they differ, it invokes a save helper at **`0x2AFFB0`** and a restore helper at **`0x2AFD8C`**. The central part of the restore path is:

```c Reduced reconstruction · RVA 0x2AFD8C
target = *(void **)((unsigned char *)vp + 0x148 + 8 * targetVtl);
*(void **)((unsigned char *)vp + 0x3C0) = target;
*((unsigned char *)vp + 0x404) = targetVtl;

vmxContext = (unsigned char *)target + 0x13C0;
SelectControlContext(processor, vmxContext);  // helper at 0x21C8E0
```

That last helper selects the target's VMCS backing state on the native path. The VP and its owning partition remain the same identities while the active trust context changes.

The save helper reads `IA32_KERNEL_GS_BASE` into **old VTL context `+ 0x1420`**. The selection helper restores that MSR from **new execution record `+ 0x60`**, the same offset viewed from `new VTL context + 0x13C0`. It also reconciles `STAR`, `LSTAR` and `FMASK` on an enabled branch.

The matching MSR offsets link the save and restore operations to the VTL execution-control record. A VTL transition consequently updates the active-context pointer, selects the target's VMCS backing state, and restores processor state held outside the basic segment fields.

`HvCallVtlReturn`, at **`0x293230`**, performs its own checks and lower-context selection, corresponding to the [documented return operation](https://learn.microsoft.com/en-us/virtualization/hyper-v-on-windows/tlfs/hypercalls/hvcallvtlreturn). Its validation path governs the reverse transition before the lower context is selected.

The public model allows an architectural VTL namespace larger than the common VTL0/VTL1 configuration. This binary also contains additional numeric cases in its validation paths. Establishing which of those cases are usable requires tracing the complete configuration and enablement paths.

## Memory isolation connects VTLs to SLAT

The processor-state switch is only part of VTL isolation. Guest page tables translate guest virtual addresses into guest physical addresses; the hypervisor's second-level translation and permission machinery controls what those guest physical accesses may reach. Changing a guest CR3 cannot by itself grant the lower VTL permission to a protected backing page.

`HvCallModifyVtlProtectionMask`, at **`0x28EF80`**, connects the VTL model to the mapping implementation. The [public interface](https://learn.microsoft.com/en-us/virtualization/hyper-v-on-windows/tlfs/hypercalls/hvcallmodifyvtlprotectionmask) operates on a list of guest physical pages. The inspected implementation validates reserved input fields, resolves the target partition, checks the target VTL and caller relationship, and then reaches the mapping workers.

The traced path is:

```text Selected VTL-protection update path
HvCallModifyVtlProtectionMask  0x28EF80
    validation / access checks
    0x2DA778
        0x36EB78             GPA iteration with SLAT locking
            0x37276C         Read mapping; derive changed permissions
                0x3837C4     Compare old and proposed mapping
                0x386A24     HvpSlatCommitGpaMapping, if changed
```

At `0x37276C`, the worker reads the current mapping, copies its representation, changes permission data indexed by the target VTL, and compares the proposed mapping with the original before committing. The path uses `HvpSlatAcquireGpaLock` and `HvpSlatReleaseGpaLock` around the relevant mapping operations.

Afterward, `0x2DA778` can call a coordination helper at **`0x2DBAC0`** with a mask derived from **`(1 << targetVtl) - 1`**, selecting lower-level contexts. The update path therefore includes both a mapping change and a separate operation coordinating the affected execution contexts.

The complete remote-processor invalidation and completion protocol behind that coordination remains unverified. The traced mapping write establishes where permissions change; determining when every affected processor stops using an old translation requires following the coordination protocol through to its acknowledgements.

## Execution flow and remaining research questions

The recovered paths connect the execution model as follows:

1. A scheduled VP identifies its partition and active VTL context.
2. The context identifies selected VMCS backing state; processor ownership and current pointers are reconciled.
3. Host segment, table and stack state describe where an exit will land. Guest state is represented through the native or enlightened interface, with additional software-managed registers alongside it.
4. Entry preparation resolves pending work, then the assembly loop launches or resumes the guest.
5. A VM exit lands in the hypervisor's programmed host context. The outer loop saves transfer state, triages external interrupts where applicable, and calls the inner exit handler.
6. The exit can lead to emulation, pending-event work, a VTL switch, a mapping change, or another entry. An event delivered through the host IDT is a distinct arrival path.

For analysis across builds, `VMXON`, `VMPTRLD`, `VMCLEAR`, the launch/resume branch, the host-RIP write and the GS-relative accesses provide instruction-level anchors. Native VMCS encodings and the documented enlightened-page layout provide independent checks on the recovered field accessors.

Further runtime analysis is needed to establish backend selection, configuration-specific VMCS allocation, ownership transfer between LPs, interrupt-queue draining and cross-processor acknowledgement of protection updates. Those questions concern the transitions between the structures recovered here: the per-processor record, the VP, its selected VTL context, and the VMCS backing state.

