XenParavirtOps/yielding

From Xen
Revision as of 01:00, 8 August 2015 by Mcgrof (talk | contribs)

Xen Paravirt yielding

While pv_ops enables multiple hypervisors to co-exist and produce a single binary the hypervisor and Linux must still avoid conflicts for functionality which Linux would otherwise implement. Prior to pv_ops, yielding was addressed through a series of Kconfig entries which would prevent certain architecture code from running when a hypervisor was be supported. This code never made it upstream, and over the years different yielding strategies have been devised to address this. The different yielding strategies and areas that Linux yields to or should yield to are documented in this section to Xen.

IOMMU yielding

Hypervisors can support PCI-passthrough for PV guests, when they do this an IOMMU is needed to translate bus (DMA) to virtual and vice-versa and a mechanism to provide contiguous pages for device drivers operations (DMA operations).

Paravirt hypervisor IOMMUs need to make use of the IOMMU_INIT*() macros and ensure they are are probed for in the appropriate order to ensure dependencies align and to avoid conflicts with other IOMMUs. For instance, once you find out in what order your IOMMU init code should run in consideration for the others you must also ensure to use IOMMU_INIT_FINISH() if no other IOMMUs init code should be run after yours.

Xen's IOMMU uses IOMMU_INIT_FINISH() and its IOMMU init code is the first to run, as such Linux PV guests only allow the Xen IOMMU to run.

Furthermore IOMMU API calls should always call iommu_present() prior to execution. This checks if the give bus_type has no iommu_ops registered, this would always return false for paravirt hypervisors.

CPU Microcode

The Linux kernel microcode code uses paravirt_enabled() to bail early and yield to CPU microcode control over to the hypervisor.

arch/x86/kernel/cpu/microcode/core.c

static int __init microcode_init(void) {

       struct cpuinfo_x86 *c = &cpu_data(0);                                                                                                                                   
       int error;                                                                                                                                                              
                                                                                                                                                                               
       if (paravirt_enabled() || dis_ucode_ldr)                                                                                                                                
               return 0;                                                                                                                                                       
       ...                                                                                                                                                                     

}

MTRR

Being written