code:
.. SPDX-License-Identifier: GPL-2.0

============================================================
Hardware-Feedback Interface for scheduling on Intel Hardware
============================================================

Overview
--------

Intel has described the Hardware Feedback Interface (HFI) in the Intel 64 and
IA-32 Architectures Software Developer's Manual (Intel SDM) Volume 3 Section
14.6 [1]_.

The HFI gives the operating system a performance and energy efficiency
capability data for each CPU in the system. Linux can use the information from
the HFI to influence task placement decisions.

The Hardware Feedback Interface
-------------------------------

The Hardware Feedback Interface provides to the operating system information
about the performance and energy efficiency of each CPU in the system. Each
capability is given as a unit-less quantity in the range [0-255]. Higher values
indicate higher capability. Energy efficiency and performance are reported in
separate capabilities. Even though on some systems these two metrics may be
related, they are specified as independent capabilities in the Intel SDM.

These capabilities may change at runtime as a result of changes in the
operating conditions of the system or the action of external factors. The rate
at which these capabilities are updated is specific to each processor model. On
some models, capabilities are set at boot time and never change. On others,
capabilities may change every tens of milliseconds. For instance, a remote
mechanism may be used to lower Thermal Design Power. Such change can be
reflected in the HFI. Likewise, if the system needs to be throttled due to
excessive heat, the HFI may reflect reduced performance on specific CPUs.

The kernel or a userspace policy daemon can use these capabilities to modify
task placement decisions. For instance, if either the performance or energy
capabilities of a given logical processor becomes zero, it is an indication that
the hardware recommends to the operating system to not schedule any tasks on
that processor for performance or energy efficiency reasons, respectively.

Implementation details for Linux
--------------------------------

The infrastructure to handle thermal event interrupts has two parts. In the
Local Vector Table of a CPU's local APIC, there exists a register for the
Thermal Monitor Register. This register controls how interrupts are delivered
to a CPU when the thermal monitor generates and interrupt. Further details
can be found in the Intel SDM Vol. 3 Section 10.5 [1]_.

The thermal monitor may generate interrupts per CPU or per package. The HFI
generates package-level interrupts. This monitor is configured and initialized
via a set of machine-specific registers. Specifically, the HFI interrupt and
status are controlled via designated bits in the IA32_PACKAGE_THERM_INTERRUPT
and IA32_PACKAGE_THERM_STATUS registers, respectively. There exists one HFI
table per package. Further details can be found in the Intel SDM Vol. 3
Section 14.9 [1]_.

The hardware issues an HFI interrupt after updating the HFI table and is ready
for the operating system to consume it. CPUs receive such interrupt via the
thermal entry in the Local APIC's Local Vector Table.

When servicing such interrupt, the HFI driver parses the updated table and
relays the update to userspace using the thermal notification framework. Given
that there may be many HFI updates every second, the updates relayed to
userspace are throttled at a rate of CONFIG_HZ jiffies.

References
----------

.. [1] https://www.intel.com/sdm


code:
=====================
Intel(R) TXT Overview
=====================

Intel's technology for safer computing, Intel(R) Trusted Execution
Technology (Intel(R) TXT), defines platform-level enhancements that
provide the building blocks for creating trusted platforms.

Intel TXT was formerly known by the code name LaGrande Technology (LT).

Intel TXT in Brief:

-  Provides dynamic root of trust for measurement (DRTM)
-  Data protection in case of improper shutdown
-  Measurement and verification of launched environment

Intel TXT is part of the vPro(TM) brand and is also available some
non-vPro systems.  It is currently available on desktop systems
based on the Q35, X38, Q45, and Q43 Express chipsets (e.g. Dell
Optiplex 755, HP dc7800, etc.) and mobile systems based on the GM45,
PM45, and GS45 Express chipsets.

For more information, see http://www.intel.com/technology/security/.
This site also has a link to the Intel TXT MLE Developers Manual,
which has been updated for the new released platforms.

Intel TXT has been presented at various events over the past few
years, some of which are:

      - LinuxTAG 2008:
          http://www.linuxtag.org/2008/en/conf/events/vp-donnerstag.html

      - TRUST2008:
          http://www.trust-conference.eu/downloads/Keynote-Speakers/
          3_David-Grawrock_The-Front-Door-of-Trusted-Computing.pdf

      - IDF, Shanghai:
          http://www.prcidf.com.cn/index_en.html

      - IDFs 2006, 2007
	  (I'm not sure if/where they are online)

Trusted Boot Project Overview
=============================

Trusted Boot (tboot) is an open source, pre-kernel/VMM module that
uses Intel TXT to perform a measured and verified launch of an OS
kernel/VMM.

It is hosted on SourceForge at http://sourceforge.net/projects/tboot.
The mercurial source repo is available at http://www.bughost.org/
repos.hg/tboot.hg.

Tboot currently supports launching Xen (open source VMM/hypervisor
w/ TXT support since v3.2), and now Linux kernels.

Value Proposition for Linux or "Why should you care?"
=====================================================

While there are many products and technologies that attempt to
measure or protect the integrity of a running kernel, they all
assume the kernel is "good" to begin with.  The Integrity
Measurement Architecture (IMA) and Linux Integrity Module interface
are examples of such solutions.

To get trust in the initial kernel without using Intel TXT, a
static root of trust must be used.  This bases trust in BIOS
starting at system reset and requires measurement of all code
executed between system reset through the completion of the kernel
boot as well as data objects used by that code.  In the case of a
Linux kernel, this means all of BIOS, any option ROMs, the
bootloader and the boot config.  In practice, this is a lot of
code/data, much of which is subject to change from boot to boot
(e.g. changing NICs may change option ROMs).  Without reference
hashes, these measurement changes are difficult to assess or
confirm as benign.  This process also does not provide DMA
protection, memory configuration/alias checks and locks, crash
protection, or policy support.

By using the hardware-based root of trust that Intel TXT provides,
many of these issues can be mitigated.  Specifically: many
pre-launch components can be removed from the trust chain, DMA
protection is provided to all launched components, a large number
of platform configuration checks are performed and values locked,
protection is provided for any data in the event of an improper
shutdown, and there is support for policy-based execution/verification.
This provides a more stable measurement and a higher assurance of
system configuration and initial state than would be otherwise
possible.  Since the tboot project is open source, source code for
almost all parts of the trust chain is available (excepting SMM and
Intel-provided firmware).

How Does it Work?
=================

-  Tboot is an executable that is launched by the bootloader as
   the "kernel" (the binary the bootloader executes).
-  It performs all of the work necessary to determine if the
   platform supports Intel TXT and, if so, executes the GETSEC[SENTER]
   processor instruction that initiates the dynamic root of trust.

   -  If tboot determines that the system does not support Intel TXT
      or is not configured correctly (e.g. the SINIT AC Module was
      incorrect), it will directly launch the kernel with no changes
      to any state.
   -  Tboot will output various information about its progress to the
      terminal, serial port, and/or an in-memory log; the output
      locations can be configured with a command line switch.

-  The GETSEC[SENTER] instruction will return control to tboot and
   tboot then verifies certain aspects of the environment (e.g. TPM NV
   lock, e820 table does not have invalid entries, etc.).
-  It will wake the APs from the special sleep state the GETSEC[SENTER]
   instruction had put them in and place them into a wait-for-SIPI
   state.

   -  Because the processors will not respond to an INIT or SIPI when
      in the TXT environment, it is necessary to create a small VT-x
      guest for the APs.  When they run in this guest, they will
      simply wait for the INIT-SIPI-SIPI sequence, which will cause
      VMEXITs, and then disable VT and jump to the SIPI vector.  This
      approach seemed like a better choice than having to insert
      special code into the kernel's MP wakeup sequence.

-  Tboot then applies an (optional) user-defined launch policy to
   verify the kernel and initrd.

   -  This policy is rooted in TPM NV and is described in the tboot
      project.  The tboot project also contains code for tools to
      create and provision the policy.
   -  Policies are completely under user control and if not present
      then any kernel will be launched.
   -  Policy action is flexible and can include halting on failures
      or simply logging them and continuing.

-  Tboot adjusts the e820 table provided by the bootloader to reserve
   its own location in memory as well as to reserve certain other
   TXT-related regions.
-  As part of its launch, tboot DMA protects all of RAM (using the
   VT-d PMRs).  Thus, the kernel must be booted with 'intel_iommu=on'
   in order to remove this blanket protection and use VT-d's
   page-level protection.
-  Tboot will populate a shared page with some data about itself and
   pass this to the Linux kernel as it transfers control.

   -  The location of the shared page is passed via the boot_params
      struct as a physical address.

-  The kernel will look for the tboot shared page address and, if it
   exists, map it.
-  As one of the checks/protections provided by TXT, it makes a copy
   of the VT-d DMARs in a DMA-protected region of memory and verifies
   them for correctness.  The VT-d code will detect if the kernel was
   launched with tboot and use this copy instead of the one in the
   ACPI table.
-  At this point, tboot and TXT are out of the picture until a
   shutdown (S<n>)
-  In order to put a system into any of the sleep states after a TXT
   launch, TXT must first be exited.  This is to prevent attacks that
   attempt to crash the system to gain control on reboot and steal
   data left in memory.

   -  The kernel will perform all of its sleep preparation and
      populate the shared page with the ACPI data needed to put the
      platform in the desired sleep state.
   -  Then the kernel jumps into tboot via the vector specified in the
      shared page.
   -  Tboot will clean up the environment and disable TXT, then use the
      kernel-provided ACPI information to actually place the platform
      into the desired sleep state.
   -  In the case of S3, tboot will also register itself as the resume
      vector.  This is necessary because it must re-establish the
      measured environment upon resume.  Once the TXT environment
      has been restored, it will restore the TPM PCRs and then
      transfer control back to the kernel's S3 resume vector.
      In order to preserve system integrity across S3, the kernel
      provides tboot with a set of memory ranges (RAM and RESERVED_KERN
      in the e820 table, but not any memory that BIOS might alter over
      the S3 transition) that tboot will calculate a MAC (message
      authentication code) over and then seal with the TPM. On resume
      and once the measured environment has been re-established, tboot
      will re-calculate the MAC and verify it against the sealed value.
      Tboot's policy determines what happens if the verification fails.
      Note that the c/s 194 of tboot which has the new MAC code supports
      this.

That's pretty much it for TXT support.

Configuring the System
======================

This code works with 32bit, 32bit PAE, and 64bit (x86_64) kernels.

In BIOS, the user must enable:  TPM, TXT, VT-x, VT-d.  Not all BIOSes
allow these to be individually enabled/disabled and the screens in
which to find them are BIOS-specific.

grub.conf needs to be modified as follows::

        title Linux 2.6.29-tip w/ tboot
          root (hd0,0)
                kernel /tboot.gz logging=serial,vga,memory
                module /vmlinuz-2.6.29-tip intel_iommu=on ro
                       root=LABEL=/ rhgb console=ttyS0,115200 3
                module /initrd-2.6.29-tip.img
                module /Q35_SINIT_17.BIN

The kernel option for enabling Intel TXT support is found under the
Security top-level menu and is called "Enable Intel(R) Trusted
Execution Technology (TXT)".  It is considered EXPERIMENTAL and
depends on the generic x86 support (to allow maximum flexibility in
kernel build options), since the tboot code will detect whether the
platform actually supports Intel TXT and thus whether any of the
kernel code is executed.

The Q35_SINIT_17.BIN file is what Intel TXT refers to as an
Authenticated Code Module.  It is specific to the chipset in the
system and can also be found on the Trusted Boot site.  It is an
(unencrypted) module signed by Intel that is used as part of the
DRTM process to verify and configure the system.  It is signed
because it operates at a higher privilege level in the system than
any other macrocode and its correct operation is critical to the
establishment of the DRTM.  The process for determining the correct
SINIT ACM for a system is documented in the SINIT-guide.txt file
that is on the tboot SourceForge site under the SINIT ACM downloads.

repo_name: angery/linux


code:
=================
x86 IOMMU Support
=================

The architecture specs can be obtained from the below locations.

- Intel: http://www.intel.com/content/dam/www/public/us/en/documents/product-specifications/vt-directed-io-spec.pdf
- AMD: https://www.amd.com/system/files/TechDocs/48882_IOMMU.pdf

This guide gives a quick cheat sheet for some basic understanding.

Basic stuff
-----------

ACPI enumerates and lists the different IOMMUs on the platform, and
device scope relationships between devices and which IOMMU controls
them.

Some ACPI Keywords:

- DMAR - Intel DMA Remapping table
- DRHD - Intel DMA Remapping Hardware Unit Definition
- RMRR - Intel Reserved Memory Region Reporting Structure
- IVRS - AMD I/O Virtualization Reporting Structure
- IVDB - AMD I/O Virtualization Definition Block
- IVHD - AMD I/O Virtualization Hardware Definition

What is Intel RMRR?
^^^^^^^^^^^^^^^^^^^

There are some devices the BIOS controls, for e.g USB devices to perform
PS2 emulation. The regions of memory used for these devices are marked
reserved in the e820 map. When we turn on DMA translation, DMA to those
regions will fail. Hence BIOS uses RMRR to specify these regions along with
devices that need to access these regions. OS is expected to setup
unity mappings for these regions for these devices to access these regions.

What is AMD IVRS?
^^^^^^^^^^^^^^^^^

The architecture defines an ACPI-compatible data structure called an I/O
Virtualization Reporting Structure (IVRS) that is used to convey information
related to I/O virtualization to system software.  The IVRS describes the
configuration and capabilities of the IOMMUs contained in the platform as
well as information about the devices that each IOMMU virtualizes.

The IVRS provides information about the following:

- IOMMUs present in the platform including their capabilities and proper configuration
- System I/O topology relevant to each IOMMU
- Peripheral devices that cannot be otherwise enumerated
- Memory regions used by SMI/SMM, platform firmware, and platform hardware. These are generally exclusion ranges to be configured by system software.

How is an I/O Virtual Address (IOVA) generated?
-----------------------------------------------

Well behaved drivers call dma_map_*() calls before sending command to device
that needs to perform DMA. Once DMA is completed and mapping is no longer
required, driver performs dma_unmap_*() calls to unmap the region.

Intel Specific Notes
--------------------

Graphics Problems?
^^^^^^^^^^^^^^^^^^

If you encounter issues with graphics devices, you can try adding
option intel_iommu=igfx_off to turn off the integrated graphics engine.
If this fixes anything, please ensure you file a bug reporting the problem.

Some exceptions to IOVA
^^^^^^^^^^^^^^^^^^^^^^^

Interrupt ranges are not address translated, (0xfee00000 - 0xfeefffff).
The same is true for peer to peer transactions. Hence we reserve the
address from PCI MMIO ranges so they are not allocated for IOVA addresses.

AMD Specific Notes
------------------

Graphics Problems?
^^^^^^^^^^^^^^^^^^

If you encounter issues with integrated graphics devices, you can try adding
option iommu=pt to the kernel command line use a 1:1 mapping for the IOMMU.  If
this fixes anything, please ensure you file a bug reporting the problem.

Fault reporting
---------------
When errors are reported, the IOMMU signals via an interrupt. The fault
reason and device that caused it is printed on the console.

Kernel Log Samples
------------------

Intel Boot Messages
^^^^^^^^^^^^^^^^^^^

Something like this gets printed indicating presence of DMAR tables
in ACPI:

::

	ACPI: DMAR (v001 A M I  OEMDMAR  0x00000001 MSFT 0x00000097) @ 0x000000007f5b5ef0

When DMAR is being processed and initialized by ACPI, prints DMAR locations
and any RMRR's processed:

::

	ACPI DMAR:Host address width 36
	ACPI DMAR:DRHD (flags: 0x00000000)base: 0x00000000fed90000
	ACPI DMAR:DRHD (flags: 0x00000000)base: 0x00000000fed91000
	ACPI DMAR:DRHD (flags: 0x00000001)base: 0x00000000fed93000
	ACPI DMAR:RMRR base: 0x00000000000ed000 end: 0x00000000000effff
	ACPI DMAR:RMRR base: 0x000000007f600000 end: 0x000000007fffffff

When DMAR is enabled for use, you will notice:

::

	PCI-DMA: Using DMAR IOMMU

Intel Fault reporting
^^^^^^^^^^^^^^^^^^^^^

::

	DMAR:[DMA Write] Request device [00:02.0] fault addr 6df084000
	DMAR:[fault reason 05] PTE Write access is not set
	DMAR:[DMA Write] Request device [00:02.0] fault addr 6df084000
	DMAR:[fault reason 05] PTE Write access is not set

AMD Boot Messages
^^^^^^^^^^^^^^^^^

Something like this gets printed indicating presence of the IOMMU:

::

	iommu: Default domain type: Translated
	iommu: DMA domain TLB invalidation policy: lazy mode

AMD Fault reporting
^^^^^^^^^^^^^^^^^^^

::

	AMD-Vi: Event logged [IO_PAGE_FAULT domain=0x0007 address=0xffffc02000 flags=0x0000]
	AMD-Vi: Event logged [IO_PAGE_FAULT device=07:00.0 domain=0x0007 address=0xffffc02000 flags=0x0000]


code:
.. SPDX-License-Identifier: GPL-2.0

=============
Kernel Stacks
=============

Kernel stacks on x86-64 bit
===========================

Most of the text from Keith Owens, hacked by AK

x86_64 page size (PAGE_SIZE) is 4K.

Like all other architectures, x86_64 has a kernel stack for every
active thread.  These thread stacks are THREAD_SIZE (2*PAGE_SIZE) big.
These stacks contain useful data as long as a thread is alive or a
zombie. While the thread is in user space the kernel stack is empty
except for the thread_info structure at the bottom.

In addition to the per thread stacks, there are specialized stacks
associated with each CPU.  These stacks are only used while the kernel
is in control on that CPU; when a CPU returns to user space the
specialized stacks contain no useful data.  The main CPU stacks are:

* Interrupt stack.  IRQ_STACK_SIZE

  Used for external hardware interrupts.  If this is the first external
  hardware interrupt (i.e. not a nested hardware interrupt) then the
  kernel switches from the current task to the interrupt stack.  Like
  the split thread and interrupt stacks on i386, this gives more room
  for kernel interrupt processing without having to increase the size
  of every per thread stack.

  The interrupt stack is also used when processing a softirq.

Switching to the kernel interrupt stack is done by software based on a
per CPU interrupt nest counter. This is needed because x86-64 "IST"
hardware stacks cannot nest without races.

x86_64 also has a feature which is not available on i386, the ability
to automatically switch to a new stack for designated events such as
double fault or NMI, which makes it easier to handle these unusual
events on x86_64.  This feature is called the Interrupt Stack Table
(IST).  There can be up to 7 IST entries per CPU. The IST code is an
index into the Task State Segment (TSS). The IST entries in the TSS
point to dedicated stacks; each stack can be a different size.

An IST is selected by a non-zero value in the IST field of an
interrupt-gate descriptor.  When an interrupt occurs and the hardware
loads such a descriptor, the hardware automatically sets the new stack
pointer based on the IST value, then invokes the interrupt handler.  If
the interrupt came from user mode, then the interrupt handler prologue
will switch back to the per-thread stack.  If software wants to allow
nested IST interrupts then the handler must adjust the IST values on
entry to and exit from the interrupt handler.  (This is occasionally
done, e.g. for debug exceptions.)

Events with different IST codes (i.e. with different stacks) can be
nested.  For example, a debug interrupt can safely be interrupted by an
NMI.  arch/x86_64/kernel/entry.S::paranoidentry adjusts the stack
pointers on entry to and exit from all IST events, in theory allowing
IST events with the same code to be nested.  However in most cases, the
stack size allocated to an IST assumes no nesting for the same code.
If that assumption is ever broken then the stacks will become corrupt.

The currently assigned IST stacks are:

* ESTACK_DF.  EXCEPTION_STKSZ (PAGE_SIZE).

  Used for interrupt 8 - Double Fault Exception (#DF).

  Invoked when handling one exception causes another exception. Happens
  when the kernel is very confused (e.g. kernel stack pointer corrupt).
  Using a separate stack allows the kernel to recover from it well enough
  in many cases to still output an oops.

* ESTACK_NMI.  EXCEPTION_STKSZ (PAGE_SIZE).

  Used for non-maskable interrupts (NMI).

  NMI can be delivered at any time, including when the kernel is in the
  middle of switching stacks.  Using IST for NMI events avoids making
  assumptions about the previous state of the kernel stack.

* ESTACK_DB.  EXCEPTION_STKSZ (PAGE_SIZE).

  Used for hardware debug interrupts (interrupt 1) and for software
  debug interrupts (INT3).

  When debugging a kernel, debug interrupts (both hardware and
  software) can occur at any time.  Using IST for these interrupts
  avoids making assumptions about the previous state of the kernel
  stack.

  To handle nested #DB correctly there exist two instances of DB stacks. On
  #DB entry the IST stackpointer for #DB is switched to the second instance
  so a nested #DB starts from a clean stack. The nested #DB switches
  the IST stackpointer to a guard hole to catch triple nesting.

* ESTACK_MCE.  EXCEPTION_STKSZ (PAGE_SIZE).

  Used for interrupt 18 - Machine Check Exception (#MC).

  MCE can be delivered at any time, including when the kernel is in the
  middle of switching stacks.  Using IST for MCE events avoids making
  assumptions about the previous state of the kernel stack.

For more details see the Intel IA32 or AMD AMD64 architecture manuals.

Printing backtraces on x86
==========================

The question about the '?' preceding function names in an x86 stacktrace
keeps popping up, here's an indepth explanation. It helps if the reader
stares at print_context_stack() and the whole machinery in and around
arch/x86/kernel/dumpstack.c.

Adapted from Ingo's mail, Message-ID: <20150521101614.GA10889@gmail.com>:

We always scan the full kernel stack for return addresses stored on
the kernel stack(s) [1]_, from stack top to stack bottom, and print out
anything that 'looks like' a kernel text address.

If it fits into the frame pointer chain, we print it without a question
mark, knowing that it's part of the real backtrace.

If the address does not fit into our expected frame pointer chain we
still print it, but we print a '?'. It can mean two things:

 - either the address is not part of the call chain: it's just stale
   values on the kernel stack, from earlier function calls. This is
   the common case.

 - or it is part of the call chain, but the frame pointer was not set
   up properly within the function, so we don't recognize it.

This way we will always print out the real call chain (plus a few more
entries), regardless of whether the frame pointer was set up correctly
or not - but in most cases we'll get the call chain right as well. The
entries printed are strictly in stack order, so you can deduce more
information from that as well.

The most important property of this method is that we _never_ lose
information: we always strive to print _all_ addresses on the stack(s)
that look like kernel text addresses, so if debug information is wrong,
we still print out the real call chain as well - just with more question
marks than ideal.

.. [1] For things like IRQ and IST stacks, we also scan those stacks, in
       the right order, and try to cross from one stack into another
       reconstructing the call chain. This works most of the time.


code:
Microarchitectural Data Sampling (MDS) mitigation
=================================================

.. _mds:

Overview
--------

Microarchitectural Data Sampling (MDS) is a family of side channel attacks
on internal buffers in Intel CPUs. The variants are:

 - Microarchitectural Store Buffer Data Sampling (MSBDS) (CVE-2018-12126)
 - Microarchitectural Fill Buffer Data Sampling (MFBDS) (CVE-2018-12130)
 - Microarchitectural Load Port Data Sampling (MLPDS) (CVE-2018-12127)
 - Microarchitectural Data Sampling Uncacheable Memory (MDSUM) (CVE-2019-11091)

MSBDS leaks Store Buffer Entries which can be speculatively forwarded to a
dependent load (store-to-load forwarding) as an optimization. The forward
can also happen to a faulting or assisting load operation for a different
memory address, which can be exploited under certain conditions. Store
buffers are partitioned between Hyper-Threads so cross thread forwarding is
not possible. But if a thread enters or exits a sleep state the store
buffer is repartitioned which can expose data from one thread to the other.

MFBDS leaks Fill Buffer Entries. Fill buffers are used internally to manage
L1 miss situations and to hold data which is returned or sent in response
to a memory or I/O operation. Fill buffers can forward data to a load
operation and also write data to the cache. When the fill buffer is
deallocated it can retain the stale data of the preceding operations which
can then be forwarded to a faulting or assisting load operation, which can
be exploited under certain conditions. Fill buffers are shared between
Hyper-Threads so cross thread leakage is possible.

MLPDS leaks Load Port Data. Load ports are used to perform load operations
from memory or I/O. The received data is then forwarded to the register
file or a subsequent operation. In some implementations the Load Port can
contain stale data from a previous operation which can be forwarded to
faulting or assisting loads under certain conditions, which again can be
exploited eventually. Load ports are shared between Hyper-Threads so cross
thread leakage is possible.

MDSUM is a special case of MSBDS, MFBDS and MLPDS. An uncacheable load from
memory that takes a fault or assist can leave data in a microarchitectural
structure that may later be observed using one of the same methods used by
MSBDS, MFBDS or MLPDS.

Exposure assumptions
--------------------

It is assumed that attack code resides in user space or in a guest with one
exception. The rationale behind this assumption is that the code construct
needed for exploiting MDS requires:

 - to control the load to trigger a fault or assist

 - to have a disclosure gadget which exposes the speculatively accessed
   data for consumption through a side channel.

 - to control the pointer through which the disclosure gadget exposes the
   data

The existence of such a construct in the kernel cannot be excluded with
100% certainty, but the complexity involved makes it extremly unlikely.

There is one exception, which is untrusted BPF. The functionality of
untrusted BPF is limited, but it needs to be thoroughly investigated
whether it can be used to create such a construct.

Mitigation strategy
-------------------

All variants have the same mitigation strategy at least for the single CPU
thread case (SMT off): Force the CPU to clear the affected buffers.

This is achieved by using the otherwise unused and obsolete VERW
instruction in combination with a microcode update. The microcode clears
the affected CPU buffers when the VERW instruction is executed.

For virtualization there are two ways to achieve CPU buffer
clearing. Either the modified VERW instruction or via the L1D Flush
command. The latter is issued when L1TF mitigation is enabled so the extra
VERW can be avoided. If the CPU is not affected by L1TF then VERW needs to
be issued.

If the VERW instruction with the supplied segment selector argument is
executed on a CPU without the microcode update there is no side effect
other than a small number of pointlessly wasted CPU cycles.

This does not protect against cross Hyper-Thread attacks except for MSBDS
which is only exploitable cross Hyper-thread when one of the Hyper-Threads
enters a C-state.

The kernel provides a function to invoke the buffer clearing:

    mds_clear_cpu_buffers()

The mitigation is invoked on kernel/userspace, hypervisor/guest and C-state
(idle) transitions.

As a special quirk to address virtualization scenarios where the host has
the microcode updated, but the hypervisor does not (yet) expose the
MD_CLEAR CPUID bit to guests, the kernel issues the VERW instruction in the
hope that it might actually clear the buffers. The state is reflected
accordingly.

According to current knowledge additional mitigations inside the kernel
itself are not required because the necessary gadgets to expose the leaked
data cannot be controlled in a way which allows exploitation from malicious
user space or VM guests.

Kernel internal mitigation modes
--------------------------------

 ======= ============================================================
 off      Mitigation is disabled. Either the CPU is not affected or
          mds=off is supplied on the kernel command line

 full     Mitigation is enabled. CPU is affected and MD_CLEAR is
          advertised in CPUID.

 vmwerv	  Mitigation is enabled. CPU is affected and MD_CLEAR is not
	  advertised in CPUID. That is mainly for virtualization
	  scenarios where the host has the updated microcode but the
	  hypervisor does not expose MD_CLEAR in CPUID. It's a best
	  effort approach without guarantee.
 ======= ============================================================

If the CPU is affected and mds=off is not supplied on the kernel command
line then the kernel selects the appropriate mitigation mode depending on
the availability of the MD_CLEAR CPUID bit.

Mitigation points
-----------------

1. Return to user space
^^^^^^^^^^^^^^^^^^^^^^^

   When transitioning from kernel to user space the CPU buffers are flushed
   on affected CPUs when the mitigation is not disabled on the kernel
   command line. The migitation is enabled through the static key
   mds_user_clear.

   The mitigation is invoked in prepare_exit_to_usermode() which covers
   all but one of the kernel to user space transitions.  The exception
   is when we return from a Non Maskable Interrupt (NMI), which is
   handled directly in do_nmi().

   (The reason that NMI is special is that prepare_exit_to_usermode() can
    enable IRQs.  In NMI context, NMIs are blocked, and we don't want to
    enable IRQs with NMIs blocked.)

2. C-State transition
^^^^^^^^^^^^^^^^^^^^^

   When a CPU goes idle and enters a C-State the CPU buffers need to be
   cleared on affected CPUs when SMT is active. This addresses the
   repartitioning of the store buffer when one of the Hyper-Threads enters
   a C-State.

   When SMT is inactive, i.e. either the CPU does not support it or all
   sibling threads are offline CPU buffer clearing is not required.

   The idle clearing is enabled on CPUs which are only affected by MSBDS
   and not by any other MDS variant. The other MDS variants cannot be
   protected against cross Hyper-Thread attacks because the Fill Buffer and
   the Load Ports are shared. So on CPUs affected by other variants, the
   idle clearing would be a window dressing exercise and is therefore not
   activated.

   The invocation is controlled by the static key mds_idle_clear which is
   switched depending on the chosen mitigation mode and the SMT state of
   the system.

   The buffer clear is only invoked before entering the C-State to prevent
   that stale data from the idling CPU from spilling to the Hyper-Thread
   sibling after the store buffer got repartitioned and all entries are
   available to the non idle sibling.

   When coming out of idle the store buffer is partitioned again so each
   sibling has half of it available. The back from idle CPU could be then
   speculatively exposed to contents of the sibling. The buffers are
   flushed either on exit to user space or on VMENTER so malicious code
   in user space or the guest cannot speculatively access them.

   The mitigation is hooked into all variants of halt()/mwait(), but does
   not cover the legacy ACPI IO-Port mechanism because the ACPI idle driver
   has been superseded by the intel_idle driver around 2010 and is
   preferred on all affected CPUs which are expected to gain the MD_CLEAR
   functionality in microcode. Aside of that the IO-Port mechanism is a
   legacy interface which is only used on older systems which are either
   not affected or do not receive microcode updates anymore.


code:
.. SPDX-License-Identifier: GPL-2.0

==========================
The Linux Microcode Loader
==========================

:Authors: - Fenghua Yu <fenghua.yu@intel.com>
          - Borislav Petkov <bp@suse.de>
	  - Ashok Raj <ashok.raj@intel.com>

The kernel has a x86 microcode loading facility which is supposed to
provide microcode loading methods in the OS. Potential use cases are
updating the microcode on platforms beyond the OEM End-Of-Life support,
and updating the microcode on long-running systems without rebooting.

The loader supports three loading methods:

Early load microcode
====================

The kernel can update microcode very early during boot. Loading
microcode early can fix CPU issues before they are observed during
kernel boot time.

The microcode is stored in an initrd file. During boot, it is read from
it and loaded into the CPU cores.

The format of the combined initrd image is microcode in (uncompressed)
cpio format followed by the (possibly compressed) initrd image. The
loader parses the combined initrd image during boot.

The microcode files in cpio name space are:

on Intel:
  kernel/x86/microcode/GenuineIntel.bin
on AMD  :
  kernel/x86/microcode/AuthenticAMD.bin

During BSP (BootStrapping Processor) boot (pre-SMP), the kernel
scans the microcode file in the initrd. If microcode matching the
CPU is found, it will be applied in the BSP and later on in all APs
(Application Processors).

The loader also saves the matching microcode for the CPU in memory.
Thus, the cached microcode patch is applied when CPUs resume from a
sleep state.

Here's a crude example how to prepare an initrd with microcode (this is
normally done automatically by the distribution, when recreating the
initrd, so you don't really have to do it yourself. It is documented
here for future reference only).
::

  #!/bin/bash

  if [ -z "$1" ]; then
      echo "You need to supply an initrd file"
      exit 1
  fi

  INITRD="$1"

  DSTDIR=kernel/x86/microcode
  TMPDIR=/tmp/initrd

  rm -rf $TMPDIR

  mkdir $TMPDIR
  cd $TMPDIR
  mkdir -p $DSTDIR

  if [ -d /lib/firmware/amd-ucode ]; then
          cat /lib/firmware/amd-ucode/microcode_amd*.bin > $DSTDIR/AuthenticAMD.bin
  fi

  if [ -d /lib/firmware/intel-ucode ]; then
          cat /lib/firmware/intel-ucode/* > $DSTDIR/GenuineIntel.bin
  fi

  find . | cpio -o -H newc >../ucode.cpio
  cd ..
  mv $INITRD $INITRD.orig
  cat ucode.cpio $INITRD.orig > $INITRD

  rm -rf $TMPDIR

The system needs to have the microcode packages installed into
/lib/firmware or you need to fixup the paths above if yours are
somewhere else and/or you've downloaded them directly from the processor
vendor's site.

Late loading
============

You simply install the microcode packages your distro supplies and
run::

  # echo 1 > /sys/devices/system/cpu/microcode/reload

as root.

The loading mechanism looks for microcode blobs in
/lib/firmware/{intel-ucode,amd-ucode}. The default distro installation
packages already put them there.

Since kernel 5.19, late loading is not enabled by default.

The /dev/cpu/microcode method has been removed in 5.19.

Why is late loading dangerous?
==============================

Synchronizing all CPUs
----------------------

The microcode engine which receives the microcode update is shared
between the two logical threads in a SMT system. Therefore, when
the update is executed on one SMT thread of the core, the sibling
"automatically" gets the update.

Since the microcode can "simulate" MSRs too, while the microcode update
is in progress, those simulated MSRs transiently cease to exist. This
can result in unpredictable results if the SMT sibling thread happens to
be in the middle of an access to such an MSR. The usual observation is
that such MSR accesses cause #GPs to be raised to signal that former are
not present.

The disappearing MSRs are just one common issue which is being observed.
Any other instruction that's being patched and gets concurrently
executed by the other SMT sibling, can also result in similar,
unpredictable behavior.

To eliminate this case, a stop_machine()-based CPU synchronization was
introduced as a way to guarantee that all logical CPUs will not execute
any code but just wait in a spin loop, polling an atomic variable.

While this took care of device or external interrupts, IPIs including
LVT ones, such as CMCI etc, it cannot address other special interrupts
that can't be shut off. Those are Machine Check (#MC), System Management
(#SMI) and Non-Maskable interrupts (#NMI).

Machine Checks
--------------

Machine Checks (#MC) are non-maskable. There are two kinds of MCEs.
Fatal un-recoverable MCEs and recoverable MCEs. While un-recoverable
errors are fatal, recoverable errors can also happen in kernel context
are also treated as fatal by the kernel.

On certain Intel machines, MCEs are also broadcast to all threads in a
system. If one thread is in the middle of executing WRMSR, a MCE will be
taken at the end of the flow. Either way, they will wait for the thread
performing the wrmsr(0x79) to rendezvous in the MCE handler and shutdown
eventually if any of the threads in the system fail to check in to the
MCE rendezvous.

To be paranoid and get predictable behavior, the OS can choose to set
MCG_STATUS.MCIP. Since MCEs can be at most one in a system, if an
MCE was signaled, the above condition will promote to a system reset
automatically. OS can turn off MCIP at the end of the update for that
core.

System Management Interrupt
---------------------------

SMIs are also broadcast to all CPUs in the platform. Microcode update
requests exclusive access to the core before writing to MSR 0x79. So if
it does happen such that, one thread is in WRMSR flow, and the 2nd got
an SMI, that thread will be stopped in the first instruction in the SMI
handler.

Since the secondary thread is stopped in the first instruction in SMI,
there is very little chance that it would be in the middle of executing
an instruction being patched. Plus OS has no way to stop SMIs from
happening.

Non-Maskable Interrupts
-----------------------

When thread0 of a core is doing the microcode update, if thread1 is
pulled into NMI, that can cause unpredictable behavior due to the
reasons above.

OS can choose a variety of methods to avoid running into this situation.

Is the microcode suitable for late loading?
-------------------------------------------

Late loading is done when the system is fully operational and running
real workloads. Late loading behavior depends on what the base patch on
the CPU is before upgrading to the new patch.

This is true for Intel CPUs.

Consider, for example, a CPU has patch level 1 and the update is to
patch level 3.

Between patch1 and patch3, patch2 might have deprecated a software-visible
feature.

This is unacceptable if software is even potentially using that feature.
For instance, say MSR_X is no longer available after an update,
accessing that MSR will cause a #GP fault.

Basically there is no way to declare a new microcode update suitable
for late-loading. This is another one of the problems that caused late
loading to be not enabled by default.

Builtin microcode
=================

The loader supports also loading of a builtin microcode supplied through
the regular builtin firmware method CONFIG_EXTRA_FIRMWARE. Only 64-bit is
currently supported.

Here's an example::

  CONFIG_EXTRA_FIRMWARE="intel-ucode/06-3a-09 amd-ucode/microcode_amd_fam15h.bin"
  CONFIG_EXTRA_FIRMWARE_DIR="/lib/firmware"

This basically means, you have the following tree structure locally::

  /lib/firmware/
  |-- amd-ucode
  ...
  |   |-- microcode_amd_fam15h.bin
  ...
  |-- intel-ucode
  ...
  |   |-- 06-3a-09
  ...

so that the build system can find those files and integrate them into
the final kernel image. The early loader finds them and applies them.

Needless to say, this method is not the most flexible one because it
requires rebuilding the kernel each time updated microcode from the CPU
vendor is available.


code:
.. SPDX-License-Identifier: GPL-2.0

=========================================
MTRR (Memory Type Range Register) control
=========================================

:Authors: - Richard Gooch <rgooch@atnf.csiro.au> - 3 Jun 1999
          - Luis R. Rodriguez <mcgrof@do-not-panic.com> - April 9, 2015

Phasing out MTRR use
====================

MTRR use is replaced on modern x86 hardware with PAT. Direct MTRR use by
drivers on Linux is now completely phased out, device drivers should use
arch_phys_wc_add() in combination with ioremap_wc() to make MTRR effective on
non-PAT systems while a no-op but equally effective on PAT enabled systems.

Even if Linux does not use MTRRs directly, some x86 platform firmware may still
set up MTRRs early before booting the OS. They do this as some platform
firmware may still have implemented access to MTRRs which would be controlled
and handled by the platform firmware directly. An example of platform use of
MTRRs is through the use of SMI handlers, one case could be for fan control,
the platform code would need uncachable access to some of its fan control
registers. Such platform access does not need any Operating System MTRR code in
place other than mtrr_type_lookup() to ensure any OS specific mapping requests
are aligned with platform MTRR setup. If MTRRs are only set up by the platform
firmware code though and the OS does not make any specific MTRR mapping
requests mtrr_type_lookup() should always return MTRR_TYPE_INVALID.

For details refer to Documentation/x86/pat.rst.

.. tip::
  On Intel P6 family processors (Pentium Pro, Pentium II and later)
  the Memory Type Range Registers (MTRRs) may be used to control
  processor access to memory ranges. This is most useful when you have
  a video (VGA) card on a PCI or AGP bus. Enabling write-combining
  allows bus write transfers to be combined into a larger transfer
  before bursting over the PCI/AGP bus. This can increase performance
  of image write operations 2.5 times or more.

  The Cyrix 6x86, 6x86MX and M II processors have Address Range
  Registers (ARRs) which provide a similar functionality to MTRRs. For
  these, the ARRs are used to emulate the MTRRs.

  The AMD K6-2 (stepping 8 and above) and K6-3 processors have two
  MTRRs. These are supported.  The AMD Athlon family provide 8 Intel
  style MTRRs.

  The Centaur C6 (WinChip) has 8 MCRs, allowing write-combining. These
  are supported.

  The VIA Cyrix III and VIA C3 CPUs offer 8 Intel style MTRRs.

  The CONFIG_MTRR option creates a /proc/mtrr file which may be used
  to manipulate your MTRRs. Typically the X server should use
  this. This should have a reasonably generic interface so that
  similar control registers on other processors can be easily
  supported.

There are two interfaces to /proc/mtrr: one is an ASCII interface
which allows you to read and write. The other is an ioctl()
interface. The ASCII interface is meant for administration. The
ioctl() interface is meant for C programs (i.e. the X server). The
interfaces are described below, with sample commands and C code.

Reading MTRRs from the shell
============================
::

  % cat /proc/mtrr
  reg00: base=0x00000000 (   0MB), size= 128MB: write-back, count=1
  reg01: base=0x08000000 ( 128MB), size=  64MB: write-back, count=1

Creating MTRRs from the C-shell::

  # echo "base=0xf8000000 size=0x400000 type=write-combining" >! /proc/mtrr

or if you use bash::

  # echo "base=0xf8000000 size=0x400000 type=write-combining" >| /proc/mtrr

And the result thereof::

  % cat /proc/mtrr
  reg00: base=0x00000000 (   0MB), size= 128MB: write-back, count=1
  reg01: base=0x08000000 ( 128MB), size=  64MB: write-back, count=1
  reg02: base=0xf8000000 (3968MB), size=   4MB: write-combining, count=1

This is for video RAM at base address 0xf8000000 and size 4 megabytes. To
find out your base address, you need to look at the output of your X
server, which tells you where the linear framebuffer address is. A
typical line that you may get is::

  (--) S3: PCI: 968 rev 0, Linear FB @ 0xf8000000

Note that you should only use the value from the X server, as it may
move the framebuffer base address, so the only value you can trust is
that reported by the X server.

To find out the size of your framebuffer (what, you don't actually
know?), the following line will tell you::

  (--) S3: videoram:  4096k

That's 4 megabytes, which is 0x400000 bytes (in hexadecimal).
A patch is being written for XFree86 which will make this automatic:
in other words the X server will manipulate /proc/mtrr using the
ioctl() interface, so users won't have to do anything. If you use a
commercial X server, lobby your vendor to add support for MTRRs.

Creating overlapping MTRRs
==========================
::

  %echo "base=0xfb000000 size=0x1000000 type=write-combining" >/proc/mtrr
  %echo "base=0xfb000000 size=0x1000 type=uncachable" >/proc/mtrr

And the results::

  % cat /proc/mtrr
  reg00: base=0x00000000 (   0MB), size=  64MB: write-back, count=1
  reg01: base=0xfb000000 (4016MB), size=  16MB: write-combining, count=1
  reg02: base=0xfb000000 (4016MB), size=   4kB: uncachable, count=1

Some cards (especially Voodoo Graphics boards) need this 4 kB area
excluded from the beginning of the region because it is used for
registers.

NOTE: You can only create type=uncachable region, if the first
region that you created is type=write-combining.

Removing MTRRs from the C-shel
==============================
::

  % echo "disable=2" >! /proc/mtrr

or using bash::

  % echo "disable=2" >| /proc/mtrr

Reading MTRRs from a C program using ioctl()'s
==============================================
::

  /*  mtrr-show.c

      Source file for mtrr-show (example program to show MTRRs using ioctl()'s)

      Copyright (C) 1997-1998  Richard Gooch

      This program is free software; you can redistribute it and/or modify
      it under the terms of the GNU General Public License as published by
      the Free Software Foundation; either version 2 of the License, or
      (at your option) any later version.

      This program is distributed in the hope that it will be useful,
      but WITHOUT ANY WARRANTY; without even the implied warranty of
      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      GNU General Public License for more details.

      You should have received a copy of the GNU General Public License
      along with this program; if not, write to the Free Software
      Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.

      Richard Gooch may be reached by email at  rgooch@atnf.csiro.au
      The postal address is:
        Richard Gooch, c/o ATNF, P. O. Box 76, Epping, N.S.W., 2121, Australia.
  */

  /*
      This program will use an ioctl() on /proc/mtrr to show the current MTRR
      settings. This is an alternative to reading /proc/mtrr.

      Written by      Richard Gooch   17-DEC-1997

      Last updated by Richard Gooch   2-MAY-1998

  */
  #include <stdio.h>
  #include <stdlib.h>
  #include <string.h>
  #include <sys/types.h>
  #include <sys/stat.h>
  #include <fcntl.h>
  #include <sys/ioctl.h>
  #include <errno.h>
  #include <asm/mtrr.h>

  #define TRUE 1
  #define FALSE 0
  #define ERRSTRING strerror (errno)

  static char *mtrr_strings[MTRR_NUM_TYPES] =
  {
      "uncachable",               /* 0 */
      "write-combining",          /* 1 */
      "?",                        /* 2 */
      "?",                        /* 3 */
      "write-through",            /* 4 */
      "write-protect",            /* 5 */
      "write-back",               /* 6 */
  };

  int main ()
  {
      int fd;
      struct mtrr_gentry gentry;

      if ( ( fd = open ("/proc/mtrr", O_RDONLY, 0) ) == -1 )
      {
    if (errno == ENOENT)
    {
        fputs ("/proc/mtrr not found: not supported or you don't have a PPro?\n",
        stderr);
        exit (1);
    }
    fprintf (stderr, "Error opening /proc/mtrr\t%s\n", ERRSTRING);
    exit (2);
      }
      for (gentry.regnum = 0; ioctl (fd, MTRRIOC_GET_ENTRY, &gentry) == 0;
    ++gentry.regnum)
      {
    if (gentry.size < 1)
    {
        fprintf (stderr, "Register: %u disabled\n", gentry.regnum);
        continue;
    }
    fprintf (stderr, "Register: %u base: 0x%lx size: 0x%lx type: %s\n",
      gentry.regnum, gentry.base, gentry.size,
      mtrr_strings[gentry.type]);
      }
      if (errno == EINVAL) exit (0);
      fprintf (stderr, "Error doing ioctl(2) on /dev/mtrr\t%s\n", ERRSTRING);
      exit (3);
  }   /*  End Function main  */

Creating MTRRs from a C programme using ioctl()'s
=================================================
::

  /*  mtrr-add.c

      Source file for mtrr-add (example programme to add an MTRRs using ioctl())

      Copyright (C) 1997-1998  Richard Gooch

      This program is free software; you can redistribute it and/or modify
      it under the terms of the GNU General Public License as published by
      the Free Software Foundation; either version 2 of the License, or
      (at your option) any later version.

      This program is distributed in the hope that it will be useful,
      but WITHOUT ANY WARRANTY; without even the implied warranty of
      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      GNU General Public License for more details.

      You should have received a copy of the GNU General Public License
      along with this program; if not, write to the Free Software
      Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.

      Richard Gooch may be reached by email at  rgooch@atnf.csiro.au
      The postal address is:
        Richard Gooch, c/o ATNF, P. O. Box 76, Epping, N.S.W., 2121, Australia.
  */

  /*
      This programme will use an ioctl() on /proc/mtrr to add an entry. The first
      available mtrr is used. This is an alternative to writing /proc/mtrr.

      Written by      Richard Gooch   17-DEC-1997

      Last updated by Richard Gooch   2-MAY-1998

  */
  #include <stdio.h>
  #include <string.h>
  #include <stdlib.h>
  #include <unistd.h>
  #include <sys/types.h>
  #include <sys/stat.h>
  #include <fcntl.h>
  #include <sys/ioctl.h>
  #include <errno.h>
  #include <asm/mtrr.h>

  #define TRUE 1
  #define FALSE 0
  #define ERRSTRING strerror (errno)

  static char *mtrr_strings[MTRR_NUM_TYPES] =
  {
      "uncachable",               /* 0 */
      "write-combining",          /* 1 */
      "?",                        /* 2 */
      "?",                        /* 3 */
      "write-through",            /* 4 */
      "write-protect",            /* 5 */
      "write-back",               /* 6 */
  };

  int main (int argc, char **argv)
  {
      int fd;
      struct mtrr_sentry sentry;

      if (argc != 4)
      {
    fprintf (stderr, "Usage:\tmtrr-add base size type\n");
    exit (1);
      }
      sentry.base = strtoul (argv[1], NULL, 0);
      sentry.size = strtoul (argv[2], NULL, 0);
      for (sentry.type = 0; sentry.type < MTRR_NUM_TYPES; ++sentry.type)
      {
    if (strcmp (argv[3], mtrr_strings[sentry.type]) == 0) break;
      }
      if (sentry.type >= MTRR_NUM_TYPES)
      {
    fprintf (stderr, "Illegal type: \"%s\"\n", argv[3]);
    exit (2);
      }
      if ( ( fd = open ("/proc/mtrr", O_WRONLY, 0) ) == -1 )
      {
    if (errno == ENOENT)
    {
        fputs ("/proc/mtrr not found: not supported or you don't have a PPro?\n",
        stderr);
        exit (3);
    }
    fprintf (stderr, "Error opening /proc/mtrr\t%s\n", ERRSTRING);
    exit (4);
      }
      if (ioctl (fd, MTRRIOC_ADD_ENTRY, &sentry) == -1)
      {
    fprintf (stderr, "Error doing ioctl(2) on /dev/mtrr\t%s\n", ERRSTRING);
    exit (5);
      }
      fprintf (stderr, "Sleeping for 5 seconds so you can see the new entry\n");
      sleep (5);
      close (fd);
      fputs ("I've just closed /proc/mtrr so now the new entry should be gone\n",
      stderr);
  }   /*  End Function main  */


code:
.. SPDX-License-Identifier: GPL-2.0

============
ORC unwinder
============

Overview
========

The kernel CONFIG_UNWINDER_ORC option enables the ORC unwinder, which is
similar in concept to a DWARF unwinder.  The difference is that the
format of the ORC data is much simpler than DWARF, which in turn allows
the ORC unwinder to be much simpler and faster.

The ORC data consists of unwind tables which are generated by objtool.
They contain out-of-band data which is used by the in-kernel ORC
unwinder.  Objtool generates the ORC data by first doing compile-time
stack metadata validation (CONFIG_STACK_VALIDATION).  After analyzing
all the code paths of a .o file, it determines information about the
stack state at each instruction address in the file and outputs that
information to the .orc_unwind and .orc_unwind_ip sections.

The per-object ORC sections are combined at link time and are sorted and
post-processed at boot time.  The unwinder uses the resulting data to
correlate instruction addresses with their stack states at run time.

ORC vs frame pointers
=====================

With frame pointers enabled, GCC adds instrumentation code to every
function in the kernel.  The kernel's .text size increases by about
3.2%, resulting in a broad kernel-wide slowdown.  Measurements by Mel
Gorman [1]_ have shown a slowdown of 5-10% for some workloads.

In contrast, the ORC unwinder has no effect on text size or runtime
performance, because the debuginfo is out of band.  So if you disable
frame pointers and enable the ORC unwinder, you get a nice performance
improvement across the board, and still have reliable stack traces.

Ingo Molnar says:

  "Note that it's not just a performance improvement, but also an
  instruction cache locality improvement: 3.2% .text savings almost
  directly transform into a similarly sized reduction in cache
  footprint. That can transform to even higher speedups for workloads
  whose cache locality is borderline."

Another benefit of ORC compared to frame pointers is that it can
reliably unwind across interrupts and exceptions.  Frame pointer based
unwinds can sometimes skip the caller of the interrupted function, if it
was a leaf function or if the interrupt hit before the frame pointer was
saved.

The main disadvantage of the ORC unwinder compared to frame pointers is
that it needs more memory to store the ORC unwind tables: roughly 2-4MB
depending on the kernel config.

ORC vs DWARF
============

ORC debuginfo's advantage over DWARF itself is that it's much simpler.
It gets rid of the complex DWARF CFI state machine and also gets rid of
the tracking of unnecessary registers.  This allows the unwinder to be
much simpler, meaning fewer bugs, which is especially important for
mission critical oops code.

The simpler debuginfo format also enables the unwinder to be much faster
than DWARF, which is important for perf and lockdep.  In a basic
performance test by Jiri Slaby [2]_, the ORC unwinder was about 20x
faster than an out-of-tree DWARF unwinder.  (Note: That measurement was
taken before some performance tweaks were added, which doubled
performance, so the speedup over DWARF may be closer to 40x.)

The ORC data format does have a few downsides compared to DWARF.  ORC
unwind tables take up ~50% more RAM (+1.3MB on an x86 defconfig kernel)
than DWARF-based eh_frame tables.

Another potential downside is that, as GCC evolves, it's conceivable
that the ORC data may end up being *too* simple to describe the state of
the stack for certain optimizations.  But IMO this is unlikely because
GCC saves the frame pointer for any unusual stack adjustments it does,
so I suspect we'll really only ever need to keep track of the stack
pointer and the frame pointer between call frames.  But even if we do
end up having to track all the registers DWARF tracks, at least we will
still be able to control the format, e.g. no complex state machines.

ORC unwind table generation
===========================

The ORC data is generated by objtool.  With the existing compile-time
stack metadata validation feature, objtool already follows all code
paths, and so it already has all the information it needs to be able to
generate ORC data from scratch.  So it's an easy step to go from stack
validation to ORC data generation.

It should be possible to instead generate the ORC data with a simple
tool which converts DWARF to ORC data.  However, such a solution would
be incomplete due to the kernel's extensive use of asm, inline asm, and
special sections like exception tables.

That could be rectified by manually annotating those special code paths
using GNU assembler .cfi annotations in .S files, and homegrown
annotations for inline asm in .c files.  But asm annotations were tried
in the past and were found to be unmaintainable.  They were often
incorrect/incomplete and made the code harder to read and keep updated.
And based on looking at glibc code, annotating inline asm in .c files
might be even worse.

Objtool still needs a few annotations, but only in code which does
unusual things to the stack like entry code.  And even then, far fewer
annotations are needed than what DWARF would need, so they're much more
maintainable than DWARF CFI annotations.

So the advantages of using objtool to generate ORC data are that it
gives more accurate debuginfo, with very few annotations.  It also
insulates the kernel from toolchain bugs which can be very painful to
deal with in the kernel since we often have to workaround issues in
older versions of the toolchain for years.

The downside is that the unwinder now becomes dependent on objtool's
ability to reverse engineer GCC code flow.  If GCC optimizations become
too complicated for objtool to follow, the ORC data generation might
stop working or become incomplete.  (It's worth noting that livepatch
already has such a dependency on objtool's ability to follow GCC code
flow.)

If newer versions of GCC come up with some optimizations which break
objtool, we may need to revisit the current implementation.  Some
possible solutions would be asking GCC to make the optimizations more
palatable, or having objtool use DWARF as an additional input, or
creating a GCC plugin to assist objtool with its analysis.  But for now,
objtool follows GCC code quite well.

Unwinder implementation details
===============================

Objtool generates the ORC data by integrating with the compile-time
stack metadata validation feature, which is described in detail in
tools/objtool/Documentation/objtool.txt.  After analyzing all
the code paths of a .o file, it creates an array of orc_entry structs,
and a parallel array of instruction addresses associated with those
structs, and writes them to the .orc_unwind and .orc_unwind_ip sections
respectively.

The ORC data is split into the two arrays for performance reasons, to
make the searchable part of the data (.orc_unwind_ip) more compact.  The
arrays are sorted in parallel at boot time.

Performance is further improved by the use of a fast lookup table which
is created at runtime.  The fast lookup table associates a given address
with a range of indices for the .orc_unwind table, so that only a small
subset of the table needs to be searched.

Etymology
=========

Orcs, fearsome creatures of medieval folklore, are the Dwarves' natural
enemies.  Similarly, the ORC unwinder was created in opposition to the
complexity and slowness of DWARF.

"Although Orcs rarely consider multiple solutions to a problem, they do
excel at getting things done because they are creatures of action, not
thought." [3]_  Similarly, unlike the esoteric DWARF unwinder, the
veracious ORC unwinder wastes no time or siloconic effort decoding
variable-length zero-extended unsigned-integer byte-coded
state-machine-based debug information entries.

Similar to how Orcs frequently unravel the well-intentioned plans of
their adversaries, the ORC unwinder frequently unravels stacks with
brutal, unyielding efficiency.

ORC stands for Oops Rewind Capability.

.. [1] https://lore.kernel.org/r/20170602104048.jkkzssljsompjdwy@suse.de
.. [2] https://lore.kernel.org/r/d2ca5435-6386-29b8-db87-7f227c2b713a@suse.cz
.. [3] http://dustin.wikidot.com/half-orcs-and-orcs


code:
.. SPDX-License-Identifier: GPL-2.0

==========================
PAT (Page Attribute Table)
==========================

x86 Page Attribute Table (PAT) allows for setting the memory attribute at the
page level granularity. PAT is complementary to the MTRR settings which allows
for setting of memory types over physical address ranges. However, PAT is
more flexible than MTRR due to its capability to set attributes at page level
and also due to the fact that there are no hardware limitations on number of
such attribute settings allowed. Added flexibility comes with guidelines for
not having memory type aliasing for the same physical memory with multiple
virtual addresses.

PAT allows for different types of memory attributes. The most commonly used
ones that will be supported at this time are:

===  ==============
WB   Write-back
UC   Uncached
WC   Write-combined
WT   Write-through
UC-  Uncached Minus
===  ==============

PAT APIs
========

There are many different APIs in the kernel that allows setting of memory
attributes at the page level. In order to avoid aliasing, these interfaces
should be used thoughtfully. Below is a table of interfaces available,
their intended usage and their memory attribute relationships. Internally,
these APIs use a reserve_memtype()/free_memtype() interface on the physical
address range to avoid any aliasing.

+------------------------+----------+--------------+------------------+
| API                    |    RAM   |  ACPI,...    |  Reserved/Holes  |
+------------------------+----------+--------------+------------------+
| ioremap                |    --    |    UC-       |       UC-        |
+------------------------+----------+--------------+------------------+
| ioremap_cache          |    --    |    WB        |       WB         |
+------------------------+----------+--------------+------------------+
| ioremap_uc             |    --    |    UC        |       UC         |
+------------------------+----------+--------------+------------------+
| ioremap_wc             |    --    |    --        |       WC         |
+------------------------+----------+--------------+------------------+
| ioremap_wt             |    --    |    --        |       WT         |
+------------------------+----------+--------------+------------------+
| set_memory_uc,         |    UC-   |    --        |       --         |
| set_memory_wb          |          |              |                  |
+------------------------+----------+--------------+------------------+
| set_memory_wc,         |    WC    |    --        |       --         |
| set_memory_wb          |          |              |                  |
+------------------------+----------+--------------+------------------+
| set_memory_wt,         |    WT    |    --        |       --         |
| set_memory_wb          |          |              |                  |
+------------------------+----------+--------------+------------------+
| pci sysfs resource     |    --    |    --        |       UC-        |
+------------------------+----------+--------------+------------------+
| pci sysfs resource_wc  |    --    |    --        |       WC         |
| is IORESOURCE_PREFETCH |          |              |                  |
+------------------------+----------+--------------+------------------+
| pci proc               |    --    |    --        |       UC-        |
| !PCIIOC_WRITE_COMBINE  |          |              |                  |
+------------------------+----------+--------------+------------------+
| pci proc               |    --    |    --        |       WC         |
| PCIIOC_WRITE_COMBINE   |          |              |                  |
+------------------------+----------+--------------+------------------+
| /dev/mem               |    --    |   WB/WC/UC-  |    WB/WC/UC-     |
| read-write             |          |              |                  |
+------------------------+----------+--------------+------------------+
| /dev/mem               |    --    |    UC-       |       UC-        |
| mmap SYNC flag         |          |              |                  |
+------------------------+----------+--------------+------------------+
| /dev/mem               |    --    |   WB/WC/UC-  |  WB/WC/UC-       |
| mmap !SYNC flag        |          |              |                  |
| and                    |          |(from existing|  (from existing  |
| any alias to this area |          |alias)        |  alias)          |
+------------------------+----------+--------------+------------------+
| /dev/mem               |    --    |    WB        |       WB         |
| mmap !SYNC flag        |          |              |                  |
| no alias to this area  |          |              |                  |
| and                    |          |              |                  |
| MTRR says WB           |          |              |                  |
+------------------------+----------+--------------+------------------+
| /dev/mem               |    --    |    --        |       UC-        |
| mmap !SYNC flag        |          |              |                  |
| no alias to this area  |          |              |                  |
| and                    |          |              |                  |
| MTRR says !WB          |          |              |                  |
+------------------------+----------+--------------+------------------+

Advanced APIs for drivers
=========================

A. Exporting pages to users with remap_pfn_range, io_remap_pfn_range,
vmf_insert_pfn.

Drivers wanting to export some pages to userspace do it by using mmap
interface and a combination of:

  1) pgprot_noncached()
  2) io_remap_pfn_range() or remap_pfn_range() or vmf_insert_pfn()

With PAT support, a new API pgprot_writecombine is being added. So, drivers can
continue to use the above sequence, with either pgprot_noncached() or
pgprot_writecombine() in step 1, followed by step 2.

In addition, step 2 internally tracks the region as UC or WC in memtype
list in order to ensure no conflicting mapping.

Note that this set of APIs only works with IO (non RAM) regions. If driver
wants to export a RAM region, it has to do set_memory_uc() or set_memory_wc()
as step 0 above and also track the usage of those pages and use set_memory_wb()
before the page is freed to free pool.

MTRR effects on PAT / non-PAT systems
=====================================

The following table provides the effects of using write-combining MTRRs when
using ioremap*() calls on x86 for both non-PAT and PAT systems. Ideally
mtrr_add() usage will be phased out in favor of arch_phys_wc_add() which will
be a no-op on PAT enabled systems. The region over which a arch_phys_wc_add()
is made, should already have been ioremapped with WC attributes or PAT entries,
this can be done by using ioremap_wc() / set_memory_wc().  Devices which
combine areas of IO memory desired to remain uncacheable with areas where
write-combining is desirable should consider use of ioremap_uc() followed by
set_memory_wc() to white-list effective write-combined areas.  Such use is
nevertheless discouraged as the effective memory type is considered
implementation defined, yet this strategy can be used as last resort on devices
with size-constrained regions where otherwise MTRR write-combining would
otherwise not be effective.
::

  ====  =======  ===  =========================  =====================
  MTRR  Non-PAT  PAT  Linux ioremap value        Effective memory type
  ====  =======  ===  =========================  =====================
        PAT                                        Non-PAT |  PAT
        |PCD                                               |
        ||PWT                                              |
        |||                                                |
  WC    000      WB   _PAGE_CACHE_MODE_WB             WC   |   WC
  WC    001      WC   _PAGE_CACHE_MODE_WC             WC*  |   WC
  WC    010      UC-  _PAGE_CACHE_MODE_UC_MINUS       WC*  |   UC
  WC    011      UC   _PAGE_CACHE_MODE_UC             UC   |   UC
  ====  =======  ===  =========================  =====================

  (*) denotes implementation defined and is discouraged

.. note:: -- in the above table mean "Not suggested usage for the API". Some
  of the --'s are strictly enforced by the kernel. Some others are not really
  enforced today, but may be enforced in future.

For ioremap and pci access through /sys or /proc - The actual type returned
can be more restrictive, in case of any existing aliasing for that address.
For example: If there is an existing uncached mapping, a new ioremap_wc can
return uncached mapping in place of write-combine requested.

set_memory_[uc|wc|wt] and set_memory_wb should be used in pairs, where driver
will first make a region uc, wc or wt and switch it back to wb after use.

Over time writes to /proc/mtrr will be deprecated in favor of using PAT based
interfaces. Users writing to /proc/mtrr are suggested to use above interfaces.

Drivers should use ioremap_[uc|wc] to access PCI BARs with [uc|wc] access
types.

Drivers should use set_memory_[uc|wc|wt] to set access type for RAM ranges.

PAT debugging
=============

With CONFIG_DEBUG_FS enabled, PAT memtype list can be examined by::

  # mount -t debugfs debugfs /sys/kernel/debug
  # cat /sys/kernel/debug/x86/pat_memtype_list
  PAT memtype list:
  uncached-minus @ 0x7fadf000-0x7fae0000
  uncached-minus @ 0x7fb19000-0x7fb1a000
  uncached-minus @ 0x7fb1a000-0x7fb1b000
  uncached-minus @ 0x7fb1b000-0x7fb1c000
  uncached-minus @ 0x7fb1c000-0x7fb1d000
  uncached-minus @ 0x7fb1d000-0x7fb1e000
  uncached-minus @ 0x7fb1e000-0x7fb25000
  uncached-minus @ 0x7fb25000-0x7fb26000
  uncached-minus @ 0x7fb26000-0x7fb27000
  uncached-minus @ 0x7fb27000-0x7fb28000
  uncached-minus @ 0x7fb28000-0x7fb2e000
  uncached-minus @ 0x7fb2e000-0x7fb2f000
  uncached-minus @ 0x7fb2f000-0x7fb30000
  uncached-minus @ 0x7fb31000-0x7fb32000
  uncached-minus @ 0x80000000-0x90000000

This list shows physical address ranges and various PAT settings used to
access those physical address ranges.

Another, more verbose way of getting PAT related debug messages is with
"debugpat" boot parameter. With this parameter, various debug messages are
printed to dmesg log.

PAT Initialization
==================

The following table describes how PAT is initialized under various
configurations. The PAT MSR must be updated by Linux in order to support WC
and WT attributes. Otherwise, the PAT MSR has the value programmed in it
by the firmware. Note, Xen enables WC attribute in the PAT MSR for guests.

 ==== ===== ==========================  =========  =======
 MTRR PAT   Call Sequence               PAT State  PAT MSR
 ==== ===== ==========================  =========  =======
 E    E     MTRR -> PAT init            Enabled    OS
 E    D     MTRR -> PAT init            Disabled    -
 D    E     MTRR -> PAT disable         Disabled   BIOS
 D    D     MTRR -> PAT disable         Disabled    -
 -    np/E  PAT  -> PAT disable         Disabled   BIOS
 -    np/D  PAT  -> PAT disable         Disabled    -
 E    !P/E  MTRR -> PAT init            Disabled   BIOS
 D    !P/E  MTRR -> PAT disable         Disabled   BIOS
 !M   !P/E  MTRR stub -> PAT disable    Disabled   BIOS
 ==== ===== ==========================  =========  =======

  Legend

 ========= =======================================
 E         Feature enabled in CPU
 D	   Feature disabled/unsupported in CPU
 np	   "nopat" boot option specified
 !P	   CONFIG_X86_PAT option unset
 !M	   CONFIG_MTRR option unset
 Enabled   PAT state set to enabled
 Disabled  PAT state set to disabled
 OS        PAT initializes PAT MSR with OS setting
 BIOS      PAT keeps PAT MSR with BIOS setting
 ========= =======================================


code:
.. SPDX-License-Identifier: GPL-2.0

==========================
Page Table Isolation (PTI)
==========================

Overview
========

Page Table Isolation (pti, previously known as KAISER [1]_) is a
countermeasure against attacks on the shared user/kernel address
space such as the "Meltdown" approach [2]_.

To mitigate this class of attacks, we create an independent set of
page tables for use only when running userspace applications.  When
the kernel is entered via syscalls, interrupts or exceptions, the
page tables are switched to the full "kernel" copy.  When the system
switches back to user mode, the user copy is used again.

The userspace page tables contain only a minimal amount of kernel
data: only what is needed to enter/exit the kernel such as the
entry/exit functions themselves and the interrupt descriptor table
(IDT).  There are a few strictly unnecessary things that get mapped
such as the first C function when entering an interrupt (see
comments in pti.c).

This approach helps to ensure that side-channel attacks leveraging
the paging structures do not function when PTI is enabled.  It can be
enabled by setting CONFIG_PAGE_TABLE_ISOLATION=y at compile time.
Once enabled at compile-time, it can be disabled at boot with the
'nopti' or 'pti=' kernel parameters (see kernel-parameters.txt).

Page Table Management
=====================

When PTI is enabled, the kernel manages two sets of page tables.
The first set is very similar to the single set which is present in
kernels without PTI.  This includes a complete mapping of userspace
that the kernel can use for things like copy_to_user().

Although _complete_, the user portion of the kernel page tables is
crippled by setting the NX bit in the top level.  This ensures
that any missed kernel->user CR3 switch will immediately crash
userspace upon executing its first instruction.

The userspace page tables map only the kernel data needed to enter
and exit the kernel.  This data is entirely contained in the 'struct
cpu_entry_area' structure which is placed in the fixmap which gives
each CPU's copy of the area a compile-time-fixed virtual address.

For new userspace mappings, the kernel makes the entries in its
page tables like normal.  The only difference is when the kernel
makes entries in the top (PGD) level.  In addition to setting the
entry in the main kernel PGD, a copy of the entry is made in the
userspace page tables' PGD.

This sharing at the PGD level also inherently shares all the lower
layers of the page tables.  This leaves a single, shared set of
userspace page tables to manage.  One PTE to lock, one set of
accessed bits, dirty bits, etc...

Overhead
========

Protection against side-channel attacks is important.  But,
this protection comes at a cost:

1. Increased Memory Use

  a. Each process now needs an order-1 PGD instead of order-0.
     (Consumes an additional 4k per process).
  b. The 'cpu_entry_area' structure must be 2MB in size and 2MB
     aligned so that it can be mapped by setting a single PMD
     entry.  This consumes nearly 2MB of RAM once the kernel
     is decompressed, but no space in the kernel image itself.

2. Runtime Cost

  a. CR3 manipulation to switch between the page table copies
     must be done at interrupt, syscall, and exception entry
     and exit (it can be skipped when the kernel is interrupted,
     though.)  Moves to CR3 are on the order of a hundred
     cycles, and are required at every entry and exit.
  b. A "trampoline" must be used for SYSCALL entry.  This
     trampoline depends on a smaller set of resources than the
     non-PTI SYSCALL entry code, so requires mapping fewer
     things into the userspace page tables.  The downside is
     that stacks must be switched at entry time.
  c. Global pages are disabled for all kernel structures not
     mapped into both kernel and userspace page tables.  This
     feature of the MMU allows different processes to share TLB
     entries mapping the kernel.  Losing the feature means more
     TLB misses after a context switch.  The actual loss of
     performance is very small, however, never exceeding 1%.
  d. Process Context IDentifiers (PCID) is a CPU feature that
     allows us to skip flushing the entire TLB when switching page
     tables by setting a special bit in CR3 when the page tables
     are changed.  This makes switching the page tables (at context
     switch, or kernel entry/exit) cheaper.  But, on systems with
     PCID support, the context switch code must flush both the user
     and kernel entries out of the TLB.  The user PCID TLB flush is
     deferred until the exit to userspace, minimizing the cost.
     See intel.com/sdm for the gory PCID/INVPCID details.
  e. The userspace page tables must be populated for each new
     process.  Even without PTI, the shared kernel mappings
     are created by copying top-level (PGD) entries into each
     new process.  But, with PTI, there are now *two* kernel
     mappings: one in the kernel page tables that maps everything
     and one for the entry/exit structures.  At fork(), we need to
     copy both.
  f. In addition to the fork()-time copying, there must also
     be an update to the userspace PGD any time a set_pgd() is done
     on a PGD used to map userspace.  This ensures that the kernel
     and userspace copies always map the same userspace
     memory.
  g. On systems without PCID support, each CR3 write flushes
     the entire TLB.  That means that each syscall, interrupt
     or exception flushes the TLB.
  h. INVPCID is a TLB-flushing instruction which allows flushing
     of TLB entries for non-current PCIDs.  Some systems support
     PCIDs, but do not support INVPCID.  On these systems, addresses
     can only be flushed from the TLB for the current PCID.  When
     flushing a kernel address, we need to flush all PCIDs, so a
     single kernel address flush will require a TLB-flushing CR3
     write upon the next use of every PCID.

Possible Future Work
====================
1. We can be more careful about not actually writing to CR3
   unless its value is actually changed.
2. Allow PTI to be enabled/disabled at runtime in addition to the
   boot-time switching.

Testing
========

To test stability of PTI, the following test procedure is recommended,
ideally doing all of these in parallel:

1. Set CONFIG_DEBUG_ENTRY=y
2. Run several copies of all of the tools/testing/selftests/x86/ tests
   (excluding MPX and protection_keys) in a loop on multiple CPUs for
   several minutes.  These tests frequently uncover corner cases in the
   kernel entry code.  In general, old kernels might cause these tests
   themselves to crash, but they should never crash the kernel.
3. Run the 'perf' tool in a mode (top or record) that generates many
   frequent performance monitoring non-maskable interrupts (see "NMI"
   in /proc/interrupts).  This exercises the NMI entry/exit code which
   is known to trigger bugs in code paths that did not expect to be
   interrupted, including nested NMIs.  Using "-c" boosts the rate of
   NMIs, and using two -c with separate counters encourages nested NMIs
   and less deterministic behavior.
   ::

	while true; do perf record -c 10000 -e instructions,cycles -a sleep 10; done

4. Launch a KVM virtual machine.
5. Run 32-bit binaries on systems supporting the SYSCALL instruction.
   This has been a lightly-tested code path and needs extra scrutiny.

Debugging
=========

Bugs in PTI cause a few different signatures of crashes
that are worth noting here.

 * Failures of the selftests/x86 code.  Usually a bug in one of the
   more obscure corners of entry_64.S
 * Crashes in early boot, especially around CPU bringup.  Bugs
   in the trampoline code or mappings cause these.
 * Crashes at the first interrupt.  Caused by bugs in entry_64.S,
   like screwing up a page table switch.  Also caused by
   incorrectly mapping the IRQ handler entry code.
 * Crashes at the first NMI.  The NMI code is separate from main
   interrupt handlers and can have bugs that do not affect
   normal interrupts.  Also caused by incorrectly mapping NMI
   code.  NMIs that interrupt the entry code must be very
   careful and can be the cause of crashes that show up when
   running perf.
 * Kernel crashes at the first exit to userspace.  entry_64.S
   bugs, or failing to map some of the exit code.
 * Crashes at first interrupt that interrupts userspace. The paths
   in entry_64.S that return to userspace are sometimes separate
   from the ones that return to the kernel.
 * Double faults: overflowing the kernel stack because of page
   faults upon page faults.  Caused by touching non-pti-mapped
   data in the entry code, or forgetting to switch to kernel
   CR3 before calling into C functions which are not pti-mapped.
 * Userspace segfaults early in boot, sometimes manifesting
   as mount(8) failing to mount the rootfs.  These have
   tended to be TLB invalidation issues.  Usually invalidating
   the wrong PCID, or otherwise missing an invalidation.

.. [1] https://gruss.cc/files/kaiser.pdf
.. [2] https://meltdownattack.com/meltdown.pdf