Xen Test Framework
Invlpg Handling

The invlpg instruction was introduced in the 486 processor.

Its purpose is to invalidate a specific TLB entry without being a general TLB flush. It takes a single memory operand, but doesn't behave like other instructions referencing memory.

It is not documented to suffer the usual memory-based faults (#GP/#SS) for a bad segment, or segment limit violation. It is documented to be a NOP when given a non-canonical address, as opposed to raising a fault.

Experimentally, it does take into account segment bases when calculating which mapping to invalidate, but will also invalidate mappings beyond the segment limit.

This test is divided into two parts.

1) TLB Refill test

This code was originally built to confirm whether segment bases were taken into account by the invlpg instruction. It is kept because it is useful to compare the behaviour of the HAP and shadow paging modes, as well as the emulated invlpg path in each mode.

The algorithm relies on the fact that a hardware pagetable walk which loads a mapping into the TLB for writing will perform an atomic set of the Accessed and Dirty bits in the pagetable entry. Subsequent writes via a mapping present in the TLB do not alter the pagetable entries.

Two mappings are chosen (in this example, the mapping for 4k and 8k physical addresses, but any two will do). Writes are performed to force a TLB fill, then the A/D bits are cleared in the PTEs. An invlpg instruction is issued to invalidate one of mappings, and further writes are performed.

By inspecting the A/D bits in the PTEs after the second write, it can be determined which mappings where invalidated. A mapping which wasn't invalidated will not require a refill, so the A/D bits will be left clear. A mapping which was invalidated will necessarily require a refill, which will set the A/D bits.

There is a race condition with vcpu scheduling; if a reschedule occurs between the two sets of writes, the TLB might be flushed for reasons not related to this test. As a result, if both mappings are seen to refill, the test is repeated (up to a maximum number of tries).

The interaction of segment bases can be identified by issuing an invlpg against the first mapping, with a segment base with would shift the linear address to the second mapping, by observing which mapping was refilled into the TLB.

2) Faulting conditions

This part of the test checks that the invlpg instruction doesn't fault under conditions which a normal instruction with a memory operand would.

  • A virtual address with a valid mapping.
  • A virtual address with an invalid mapping.
  • A NULL segment override.
  • Beyond the segment limit.
  • Between the base and limit of an expand-down segment.

Additionally, for 64bit environments:

  • A non-canonical virtual address.
  • A virtual address which, when combined with a segment base, becomes non-canonical.

This part of the test is applicable to non-paged environments.

Todo:
Find a better way dealing with forced emulation. Versions of Xen older than 4.7 crash the domain if they find an invlpg instruction while in hap mode, which is unhelpful when trying to test behaviour.
See also
tests/invlpg/main.c