• Michael Kelley's avatar
    x86/hyperv: Change vTOM handling to use standard coco mechanisms · 812b0597
    Michael Kelley authored
    Hyper-V guests on AMD SEV-SNP hardware have the option of using the
    "virtual Top Of Memory" (vTOM) feature specified by the SEV-SNP
    architecture. With vTOM, shared vs. private memory accesses are
    controlled by splitting the guest physical address space into two
    halves.
    
    vTOM is the dividing line where the uppermost bit of the physical
    address space is set; e.g., with 47 bits of guest physical address
    space, vTOM is 0x400000000000 (bit 46 is set).  Guest physical memory is
    accessible at two parallel physical addresses -- one below vTOM and one
    above vTOM.  Accesses below vTOM are private (encrypted) while accesses
    above vTOM are shared (decrypted). In this sense, vTOM is like the
    GPA.SHARED bit in Intel TDX.
    
    Support for Hyper-V guests using vTOM was added to the Linux kernel in
    two patch sets[1][2]. This support treats the vTOM bit as part of
    the physical address. For accessing shared (decrypted) memory, these
    patch sets create a second kernel virtual mapping that maps to physical
    addresses above vTOM.
    
    A better approach is to treat the vTOM bit as a protection flag, not
    as part of the physical address. This new approach is like the approach
    for the GPA.SHARED bit in Intel TDX. Rather than creating a second kernel
    virtual mapping, the existing mapping is updated using recently added
    coco mechanisms.
    
    When memory is changed between private and shared using
    set_memory_decrypted() and set_memory_encrypted(), the PTEs for the
    existing kernel mapping are changed to add or remove the vTOM bit in the
    guest physical address, just as with TDX. The hypercalls to change the
    memory status on the host side are made using the existing callback
    mechanism. Everything just works, with a minor tweak to map the IO-APIC
    to use private accesses.
    
    To accomplish the switch in approach, the following must be done:
    
    * Update Hyper-V initialization to set the cc_mask based on vTOM
      and do other coco initialization.
    
    * Update physical_mask so the vTOM bit is no longer treated as part
      of the physical address
    
    * Remove CC_VENDOR_HYPERV and merge the associated vTOM functionality
      under CC_VENDOR_AMD. Update cc_mkenc() and cc_mkdec() to set/clear
      the vTOM bit as a protection flag.
    
    * Code already exists to make hypercalls to inform Hyper-V about pages
      changing between shared and private.  Update this code to run as a
      callback from __set_memory_enc_pgtable().
    
    * Remove the Hyper-V special case from __set_memory_enc_dec()
    
    * Remove the Hyper-V specific call to swiotlb_update_mem_attributes()
      since mem_encrypt_init() will now do it.
    
    * Add a Hyper-V specific implementation of the is_private_mmio()
      callback that returns true for the IO-APIC and vTPM MMIO addresses
    
      [1] https://lore.kernel.org/all/20211025122116.264793-1-ltykernel@gmail.com/
      [2] https://lore.kernel.org/all/20211213071407.314309-1-ltykernel@gmail.com/
    
      [ bp: Touchups. ]
    Signed-off-by: default avatarMichael Kelley <mikelley@microsoft.com>
    Signed-off-by: default avatarBorislav Petkov (AMD) <bp@alien8.de>
    Link: https://lore.kernel.org/r/1679838727-87310-7-git-send-email-mikelley@microsoft.com
    812b0597
ivm.c 10.1 KB