| .. SPDX-License-Identifier: GPL-2.0 |
| .. _ultravisor: |
| |
| ============================ |
| Protected Execution Facility |
| ============================ |
| |
| .. contents:: |
| :depth: 3 |
| |
| Introduction |
| ############ |
| |
| Protected Execution Facility (PEF) is an architectural change for |
| POWER 9 that enables Secure Virtual Machines (SVMs). DD2.3 chips |
| (PVR=0x004e1203) or greater will be PEF-capable. A new ISA release |
| will include the PEF RFC02487 changes. |
| |
| When enabled, PEF adds a new higher privileged mode, called Ultravisor |
| mode, to POWER architecture. Along with the new mode there is new |
| firmware called the Protected Execution Ultravisor (or Ultravisor |
| for short). Ultravisor mode is the highest privileged mode in POWER |
| architecture. |
| |
| +------------------+ |
| | Privilege States | |
| +==================+ |
| | Problem | |
| +------------------+ |
| | Supervisor | |
| +------------------+ |
| | Hypervisor | |
| +------------------+ |
| | Ultravisor | |
| +------------------+ |
| |
| PEF protects SVMs from the hypervisor, privileged users, and other |
| VMs in the system. SVMs are protected while at rest and can only be |
| executed by an authorized machine. All virtual machines utilize |
| hypervisor services. The Ultravisor filters calls between the SVMs |
| and the hypervisor to assure that information does not accidentally |
| leak. All hypercalls except H_RANDOM are reflected to the hypervisor. |
| H_RANDOM is not reflected to prevent the hypervisor from influencing |
| random values in the SVM. |
| |
| To support this there is a refactoring of the ownership of resources |
| in the CPU. Some of the resources which were previously hypervisor |
| privileged are now ultravisor privileged. |
| |
| Hardware |
| ======== |
| |
| The hardware changes include the following: |
| |
| * There is a new bit in the MSR that determines whether the current |
| process is running in secure mode, MSR(S) bit 41. MSR(S)=1, process |
| is in secure mode, MSR(s)=0 process is in normal mode. |
| |
| * The MSR(S) bit can only be set by the Ultravisor. |
| |
| * HRFID cannot be used to set the MSR(S) bit. If the hypervisor needs |
| to return to a SVM it must use an ultracall. It can determine if |
| the VM it is returning to is secure. |
| |
| * There is a new Ultravisor privileged register, SMFCTRL, which has an |
| enable/disable bit SMFCTRL(E). |
| |
| * The privilege of a process is now determined by three MSR bits, |
| MSR(S, HV, PR). In each of the tables below the modes are listed |
| from least privilege to highest privilege. The higher privilege |
| modes can access all the resources of the lower privilege modes. |
| |
| **Secure Mode MSR Settings** |
| |
| +---+---+---+---------------+ |
| | S | HV| PR|Privilege | |
| +===+===+===+===============+ |
| | 1 | 0 | 1 | Problem | |
| +---+---+---+---------------+ |
| | 1 | 0 | 0 | Privileged(OS)| |
| +---+---+---+---------------+ |
| | 1 | 1 | 0 | Ultravisor | |
| +---+---+---+---------------+ |
| | 1 | 1 | 1 | Reserved | |
| +---+---+---+---------------+ |
| |
| **Normal Mode MSR Settings** |
| |
| +---+---+---+---------------+ |
| | S | HV| PR|Privilege | |
| +===+===+===+===============+ |
| | 0 | 0 | 1 | Problem | |
| +---+---+---+---------------+ |
| | 0 | 0 | 0 | Privileged(OS)| |
| +---+---+---+---------------+ |
| | 0 | 1 | 0 | Hypervisor | |
| +---+---+---+---------------+ |
| | 0 | 1 | 1 | Problem (Host)| |
| +---+---+---+---------------+ |
| |
| * Memory is partitioned into secure and normal memory. Only processes |
| that are running in secure mode can access secure memory. |
| |
| * The hardware does not allow anything that is not running secure to |
| access secure memory. This means that the Hypervisor cannot access |
| the memory of the SVM without using an ultracall (asking the |
| Ultravisor). The Ultravisor will only allow the hypervisor to see |
| the SVM memory encrypted. |
| |
| * I/O systems are not allowed to directly address secure memory. This |
| limits the SVMs to virtual I/O only. |
| |
| * The architecture allows the SVM to share pages of memory with the |
| hypervisor that are not protected with encryption. However, this |
| sharing must be initiated by the SVM. |
| |
| * When a process is running in secure mode all hypercalls |
| (syscall lev=1) go to the Ultravisor. |
| |
| * When a process is in secure mode all interrupts go to the |
| Ultravisor. |
| |
| * The following resources have become Ultravisor privileged and |
| require an Ultravisor interface to manipulate: |
| |
| * Processor configurations registers (SCOMs). |
| |
| * Stop state information. |
| |
| * The debug registers CIABR, DAWR, and DAWRX when SMFCTRL(D) is set. |
| If SMFCTRL(D) is not set they do not work in secure mode. When set, |
| reading and writing requires an Ultravisor call, otherwise that |
| will cause a Hypervisor Emulation Assistance interrupt. |
| |
| * PTCR and partition table entries (partition table is in secure |
| memory). An attempt to write to PTCR will cause a Hypervisor |
| Emulation Assistance interrupt. |
| |
| * LDBAR (LD Base Address Register) and IMC (In-Memory Collection) |
| non-architected registers. An attempt to write to them will cause a |
| Hypervisor Emulation Assistance interrupt. |
| |
| * Paging for an SVM, sharing of memory with Hypervisor for an SVM. |
| (Including Virtual Processor Area (VPA) and virtual I/O). |
| |
| |
| Software/Microcode |
| ================== |
| |
| The software changes include: |
| |
| * SVMs are created from normal VM using (open source) tooling supplied |
| by IBM. |
| |
| * All SVMs start as normal VMs and utilize an ultracall, UV_ESM |
| (Enter Secure Mode), to make the transition. |
| |
| * When the UV_ESM ultracall is made the Ultravisor copies the VM into |
| secure memory, decrypts the verification information, and checks the |
| integrity of the SVM. If the integrity check passes the Ultravisor |
| passes control in secure mode. |
| |
| * The verification information includes the pass phrase for the |
| encrypted disk associated with the SVM. This pass phrase is given |
| to the SVM when requested. |
| |
| * The Ultravisor is not involved in protecting the encrypted disk of |
| the SVM while at rest. |
| |
| * For external interrupts the Ultravisor saves the state of the SVM, |
| and reflects the interrupt to the hypervisor for processing. |
| For hypercalls, the Ultravisor inserts neutral state into all |
| registers not needed for the hypercall then reflects the call to |
| the hypervisor for processing. The H_RANDOM hypercall is performed |
| by the Ultravisor and not reflected. |
| |
| * For virtual I/O to work bounce buffering must be done. |
| |
| * The Ultravisor uses AES (IAPM) for protection of SVM memory. IAPM |
| is a mode of AES that provides integrity and secrecy concurrently. |
| |
| * The movement of data between normal and secure pages is coordinated |
| with the Ultravisor by a new HMM plug-in in the Hypervisor. |
| |
| The Ultravisor offers new services to the hypervisor and SVMs. These |
| are accessed through ultracalls. |
| |
| Terminology |
| =========== |
| |
| * Hypercalls: special system calls used to request services from |
| Hypervisor. |
| |
| * Normal memory: Memory that is accessible to Hypervisor. |
| |
| * Normal page: Page backed by normal memory and available to |
| Hypervisor. |
| |
| * Shared page: A page backed by normal memory and available to both |
| the Hypervisor/QEMU and the SVM (i.e page has mappings in SVM and |
| Hypervisor/QEMU). |
| |
| * Secure memory: Memory that is accessible only to Ultravisor and |
| SVMs. |
| |
| * Secure page: Page backed by secure memory and only available to |
| Ultravisor and SVM. |
| |
| * SVM: Secure Virtual Machine. |
| |
| * Ultracalls: special system calls used to request services from |
| Ultravisor. |
| |
| |
| Ultravisor calls API |
| #################### |
| |
| This section describes Ultravisor calls (ultracalls) needed to |
| support Secure Virtual Machines (SVM)s and Paravirtualized KVM. The |
| ultracalls allow the SVMs and Hypervisor to request services from the |
| Ultravisor such as accessing a register or memory region that can only |
| be accessed when running in Ultravisor-privileged mode. |
| |
| The specific service needed from an ultracall is specified in register |
| R3 (the first parameter to the ultracall). Other parameters to the |
| ultracall, if any, are specified in registers R4 through R12. |
| |
| Return value of all ultracalls is in register R3. Other output values |
| from the ultracall, if any, are returned in registers R4 through R12. |
| The only exception to this register usage is the ``UV_RETURN`` |
| ultracall described below. |
| |
| Each ultracall returns specific error codes, applicable in the context |
| of the ultracall. However, like with the PowerPC Architecture Platform |
| Reference (PAPR), if no specific error code is defined for a |
| particular situation, then the ultracall will fallback to an erroneous |
| parameter-position based code. i.e U_PARAMETER, U_P2, U_P3 etc |
| depending on the ultracall parameter that may have caused the error. |
| |
| Some ultracalls involve transferring a page of data between Ultravisor |
| and Hypervisor. Secure pages that are transferred from secure memory |
| to normal memory may be encrypted using dynamically generated keys. |
| When the secure pages are transferred back to secure memory, they may |
| be decrypted using the same dynamically generated keys. Generation and |
| management of these keys will be covered in a separate document. |
| |
| For now this only covers ultracalls currently implemented and being |
| used by Hypervisor and SVMs but others can be added here when it |
| makes sense. |
| |
| The full specification for all hypercalls/ultracalls will eventually |
| be made available in the public/OpenPower version of the PAPR |
| specification. |
| |
| .. note:: |
| |
| If PEF is not enabled, the ultracalls will be redirected to the |
| Hypervisor which must handle/fail the calls. |
| |
| Ultracalls used by Hypervisor |
| ============================= |
| |
| This section describes the virtual memory management ultracalls used |
| by the Hypervisor to manage SVMs. |
| |
| UV_PAGE_OUT |
| ----------- |
| |
| Encrypt and move the contents of a page from secure memory to normal |
| memory. |
| |
| Syntax |
| ~~~~~~ |
| |
| .. code-block:: c |
| |
| uint64_t ultracall(const uint64_t UV_PAGE_OUT, |
| uint16_t lpid, /* LPAR ID */ |
| uint64_t dest_ra, /* real address of destination page */ |
| uint64_t src_gpa, /* source guest-physical-address */ |
| uint8_t flags, /* flags */ |
| uint64_t order) /* page size order */ |
| |
| Return values |
| ~~~~~~~~~~~~~ |
| |
| One of the following values: |
| |
| * U_SUCCESS on success. |
| * U_PARAMETER if ``lpid`` is invalid. |
| * U_P2 if ``dest_ra`` is invalid. |
| * U_P3 if the ``src_gpa`` address is invalid. |
| * U_P4 if any bit in the ``flags`` is unrecognized |
| * U_P5 if the ``order`` parameter is unsupported. |
| * U_FUNCTION if functionality is not supported. |
| * U_BUSY if page cannot be currently paged-out. |
| |
| Description |
| ~~~~~~~~~~~ |
| |
| Encrypt the contents of a secure-page and make it available to |
| Hypervisor in a normal page. |
| |
| By default, the source page is unmapped from the SVM's partition- |
| scoped page table. But the Hypervisor can provide a hint to the |
| Ultravisor to retain the page mapping by setting the ``UV_SNAPSHOT`` |
| flag in ``flags`` parameter. |
| |
| If the source page is already a shared page the call returns |
| U_SUCCESS, without doing anything. |
| |
| Use cases |
| ~~~~~~~~~ |
| |
| #. QEMU attempts to access an address belonging to the SVM but the |
| page frame for that address is not mapped into QEMU's address |
| space. In this case, the Hypervisor will allocate a page frame, |
| map it into QEMU's address space and issue the ``UV_PAGE_OUT`` |
| call to retrieve the encrypted contents of the page. |
| |
| #. When Ultravisor runs low on secure memory and it needs to page-out |
| an LRU page. In this case, Ultravisor will issue the |
| ``H_SVM_PAGE_OUT`` hypercall to the Hypervisor. The Hypervisor will |
| then allocate a normal page and issue the ``UV_PAGE_OUT`` ultracall |
| and the Ultravisor will encrypt and move the contents of the secure |
| page into the normal page. |
| |
| #. When Hypervisor accesses SVM data, the Hypervisor requests the |
| Ultravisor to transfer the corresponding page into a insecure page, |
| which the Hypervisor can access. The data in the normal page will |
| be encrypted though. |
| |
| UV_PAGE_IN |
| ---------- |
| |
| Move the contents of a page from normal memory to secure memory. |
| |
| Syntax |
| ~~~~~~ |
| |
| .. code-block:: c |
| |
| uint64_t ultracall(const uint64_t UV_PAGE_IN, |
| uint16_t lpid, /* the LPAR ID */ |
| uint64_t src_ra, /* source real address of page */ |
| uint64_t dest_gpa, /* destination guest physical address */ |
| uint64_t flags, /* flags */ |
| uint64_t order) /* page size order */ |
| |
| Return values |
| ~~~~~~~~~~~~~ |
| |
| One of the following values: |
| |
| * U_SUCCESS on success. |
| * U_BUSY if page cannot be currently paged-in. |
| * U_FUNCTION if functionality is not supported |
| * U_PARAMETER if ``lpid`` is invalid. |
| * U_P2 if ``src_ra`` is invalid. |
| * U_P3 if the ``dest_gpa`` address is invalid. |
| * U_P4 if any bit in the ``flags`` is unrecognized |
| * U_P5 if the ``order`` parameter is unsupported. |
| |
| Description |
| ~~~~~~~~~~~ |
| |
| Move the contents of the page identified by ``src_ra`` from normal |
| memory to secure memory and map it to the guest physical address |
| ``dest_gpa``. |
| |
| If `dest_gpa` refers to a shared address, map the page into the |
| partition-scoped page-table of the SVM. If `dest_gpa` is not shared, |
| copy the contents of the page into the corresponding secure page. |
| Depending on the context, decrypt the page before being copied. |
| |
| The caller provides the attributes of the page through the ``flags`` |
| parameter. Valid values for ``flags`` are: |
| |
| * CACHE_INHIBITED |
| * CACHE_ENABLED |
| * WRITE_PROTECTION |
| |
| The Hypervisor must pin the page in memory before making |
| ``UV_PAGE_IN`` ultracall. |
| |
| Use cases |
| ~~~~~~~~~ |
| |
| #. When a normal VM switches to secure mode, all its pages residing |
| in normal memory, are moved into secure memory. |
| |
| #. When an SVM requests to share a page with Hypervisor the Hypervisor |
| allocates a page and informs the Ultravisor. |
| |
| #. When an SVM accesses a secure page that has been paged-out, |
| Ultravisor invokes the Hypervisor to locate the page. After |
| locating the page, the Hypervisor uses UV_PAGE_IN to make the |
| page available to Ultravisor. |
| |
| UV_PAGE_INVAL |
| ------------- |
| |
| Invalidate the Ultravisor mapping of a page. |
| |
| Syntax |
| ~~~~~~ |
| |
| .. code-block:: c |
| |
| uint64_t ultracall(const uint64_t UV_PAGE_INVAL, |
| uint16_t lpid, /* the LPAR ID */ |
| uint64_t guest_pa, /* destination guest-physical-address */ |
| uint64_t order) /* page size order */ |
| |
| Return values |
| ~~~~~~~~~~~~~ |
| |
| One of the following values: |
| |
| * U_SUCCESS on success. |
| * U_PARAMETER if ``lpid`` is invalid. |
| * U_P2 if ``guest_pa`` is invalid (or corresponds to a secure |
| page mapping). |
| * U_P3 if the ``order`` is invalid. |
| * U_FUNCTION if functionality is not supported. |
| * U_BUSY if page cannot be currently invalidated. |
| |
| Description |
| ~~~~~~~~~~~ |
| |
| This ultracall informs Ultravisor that the page mapping in Hypervisor |
| corresponding to the given guest physical address has been invalidated |
| and that the Ultravisor should not access the page. If the specified |
| ``guest_pa`` corresponds to a secure page, Ultravisor will ignore the |
| attempt to invalidate the page and return U_P2. |
| |
| Use cases |
| ~~~~~~~~~ |
| |
| #. When a shared page is unmapped from the QEMU's page table, possibly |
| because it is paged-out to disk, Ultravisor needs to know that the |
| page should not be accessed from its side too. |
| |
| |
| UV_WRITE_PATE |
| ------------- |
| |
| Validate and write the partition table entry (PATE) for a given |
| partition. |
| |
| Syntax |
| ~~~~~~ |
| |
| .. code-block:: c |
| |
| uint64_t ultracall(const uint64_t UV_WRITE_PATE, |
| uint32_t lpid, /* the LPAR ID */ |
| uint64_t dw0 /* the first double word to write */ |
| uint64_t dw1) /* the second double word to write */ |
| |
| Return values |
| ~~~~~~~~~~~~~ |
| |
| One of the following values: |
| |
| * U_SUCCESS on success. |
| * U_BUSY if PATE cannot be currently written to. |
| * U_FUNCTION if functionality is not supported. |
| * U_PARAMETER if ``lpid`` is invalid. |
| * U_P2 if ``dw0`` is invalid. |
| * U_P3 if the ``dw1`` address is invalid. |
| * U_PERMISSION if the Hypervisor is attempting to change the PATE |
| of a secure virtual machine or if called from a |
| context other than Hypervisor. |
| |
| Description |
| ~~~~~~~~~~~ |
| |
| Validate and write a LPID and its partition-table-entry for the given |
| LPID. If the LPID is already allocated and initialized, this call |
| results in changing the partition table entry. |
| |
| Use cases |
| ~~~~~~~~~ |
| |
| #. The Partition table resides in Secure memory and its entries, |
| called PATE (Partition Table Entries), point to the partition- |
| scoped page tables for the Hypervisor as well as each of the |
| virtual machines (both secure and normal). The Hypervisor |
| operates in partition 0 and its partition-scoped page tables |
| reside in normal memory. |
| |
| #. This ultracall allows the Hypervisor to register the partition- |
| scoped and process-scoped page table entries for the Hypervisor |
| and other partitions (virtual machines) with the Ultravisor. |
| |
| #. If the value of the PATE for an existing partition (VM) changes, |
| the TLB cache for the partition is flushed. |
| |
| #. The Hypervisor is responsible for allocating LPID. The LPID and |
| its PATE entry are registered together. The Hypervisor manages |
| the PATE entries for a normal VM and can change the PATE entry |
| anytime. Ultravisor manages the PATE entries for an SVM and |
| Hypervisor is not allowed to modify them. |
| |
| UV_RETURN |
| --------- |
| |
| Return control from the Hypervisor back to the Ultravisor after |
| processing an hypercall or interrupt that was forwarded (aka |
| *reflected*) to the Hypervisor. |
| |
| Syntax |
| ~~~~~~ |
| |
| .. code-block:: c |
| |
| uint64_t ultracall(const uint64_t UV_RETURN) |
| |
| Return values |
| ~~~~~~~~~~~~~ |
| |
| This call never returns to Hypervisor on success. It returns |
| U_INVALID if ultracall is not made from a Hypervisor context. |
| |
| Description |
| ~~~~~~~~~~~ |
| |
| When an SVM makes an hypercall or incurs some other exception, the |
| Ultravisor usually forwards (aka *reflects*) the exceptions to the |
| Hypervisor. After processing the exception, Hypervisor uses the |
| ``UV_RETURN`` ultracall to return control back to the SVM. |
| |
| The expected register state on entry to this ultracall is: |
| |
| * Non-volatile registers are restored to their original values. |
| * If returning from an hypercall, register R0 contains the return |
| value (**unlike other ultracalls**) and, registers R4 through R12 |
| contain any output values of the hypercall. |
| * R3 contains the ultracall number, i.e UV_RETURN. |
| * If returning with a synthesized interrupt, R2 contains the |
| synthesized interrupt number. |
| |
| Use cases |
| ~~~~~~~~~ |
| |
| #. Ultravisor relies on the Hypervisor to provide several services to |
| the SVM such as processing hypercall and other exceptions. After |
| processing the exception, Hypervisor uses UV_RETURN to return |
| control back to the Ultravisor. |
| |
| #. Hypervisor has to use this ultracall to return control to the SVM. |
| |
| |
| UV_REGISTER_MEM_SLOT |
| -------------------- |
| |
| Register an SVM address-range with specified properties. |
| |
| Syntax |
| ~~~~~~ |
| |
| .. code-block:: c |
| |
| uint64_t ultracall(const uint64_t UV_REGISTER_MEM_SLOT, |
| uint64_t lpid, /* LPAR ID of the SVM */ |
| uint64_t start_gpa, /* start guest physical address */ |
| uint64_t size, /* size of address range in bytes */ |
| uint64_t flags /* reserved for future expansion */ |
| uint16_t slotid) /* slot identifier */ |
| |
| Return values |
| ~~~~~~~~~~~~~ |
| |
| One of the following values: |
| |
| * U_SUCCESS on success. |
| * U_PARAMETER if ``lpid`` is invalid. |
| * U_P2 if ``start_gpa`` is invalid. |
| * U_P3 if ``size`` is invalid. |
| * U_P4 if any bit in the ``flags`` is unrecognized. |
| * U_P5 if the ``slotid`` parameter is unsupported. |
| * U_PERMISSION if called from context other than Hypervisor. |
| * U_FUNCTION if functionality is not supported. |
| |
| |
| Description |
| ~~~~~~~~~~~ |
| |
| Register a memory range for an SVM. The memory range starts at the |
| guest physical address ``start_gpa`` and is ``size`` bytes long. |
| |
| Use cases |
| ~~~~~~~~~ |
| |
| |
| #. When a virtual machine goes secure, all the memory slots managed by |
| the Hypervisor move into secure memory. The Hypervisor iterates |
| through each of memory slots, and registers the slot with |
| Ultravisor. Hypervisor may discard some slots such as those used |
| for firmware (SLOF). |
| |
| #. When new memory is hot-plugged, a new memory slot gets registered. |
| |
| |
| UV_UNREGISTER_MEM_SLOT |
| ---------------------- |
| |
| Unregister an SVM address-range that was previously registered using |
| UV_REGISTER_MEM_SLOT. |
| |
| Syntax |
| ~~~~~~ |
| |
| .. code-block:: c |
| |
| uint64_t ultracall(const uint64_t UV_UNREGISTER_MEM_SLOT, |
| uint64_t lpid, /* LPAR ID of the SVM */ |
| uint64_t slotid) /* reservation slotid */ |
| |
| Return values |
| ~~~~~~~~~~~~~ |
| |
| One of the following values: |
| |
| * U_SUCCESS on success. |
| * U_FUNCTION if functionality is not supported. |
| * U_PARAMETER if ``lpid`` is invalid. |
| * U_P2 if ``slotid`` is invalid. |
| * U_PERMISSION if called from context other than Hypervisor. |
| |
| Description |
| ~~~~~~~~~~~ |
| |
| Release the memory slot identified by ``slotid`` and free any |
| resources allocated towards the reservation. |
| |
| Use cases |
| ~~~~~~~~~ |
| |
| #. Memory hot-remove. |
| |
| |
| UV_SVM_TERMINATE |
| ---------------- |
| |
| Terminate an SVM and release its resources. |
| |
| Syntax |
| ~~~~~~ |
| |
| .. code-block:: c |
| |
| uint64_t ultracall(const uint64_t UV_SVM_TERMINATE, |
| uint64_t lpid, /* LPAR ID of the SVM */) |
| |
| Return values |
| ~~~~~~~~~~~~~ |
| |
| One of the following values: |
| |
| * U_SUCCESS on success. |
| * U_FUNCTION if functionality is not supported. |
| * U_PARAMETER if ``lpid`` is invalid. |
| * U_INVALID if VM is not secure. |
| * U_PERMISSION if not called from a Hypervisor context. |
| |
| Description |
| ~~~~~~~~~~~ |
| |
| Terminate an SVM and release all its resources. |
| |
| Use cases |
| ~~~~~~~~~ |
| |
| #. Called by Hypervisor when terminating an SVM. |
| |
| |
| Ultracalls used by SVM |
| ====================== |
| |
| UV_SHARE_PAGE |
| ------------- |
| |
| Share a set of guest physical pages with the Hypervisor. |
| |
| Syntax |
| ~~~~~~ |
| |
| .. code-block:: c |
| |
| uint64_t ultracall(const uint64_t UV_SHARE_PAGE, |
| uint64_t gfn, /* guest page frame number */ |
| uint64_t num) /* number of pages of size PAGE_SIZE */ |
| |
| Return values |
| ~~~~~~~~~~~~~ |
| |
| One of the following values: |
| |
| * U_SUCCESS on success. |
| * U_FUNCTION if functionality is not supported. |
| * U_INVALID if the VM is not secure. |
| * U_PARAMETER if ``gfn`` is invalid. |
| * U_P2 if ``num`` is invalid. |
| |
| Description |
| ~~~~~~~~~~~ |
| |
| Share the ``num`` pages starting at guest physical frame number ``gfn`` |
| with the Hypervisor. Assume page size is PAGE_SIZE bytes. Zero the |
| pages before returning. |
| |
| If the address is already backed by a secure page, unmap the page and |
| back it with an insecure page, with the help of the Hypervisor. If it |
| is not backed by any page yet, mark the PTE as insecure and back it |
| with an insecure page when the address is accessed. If it is already |
| backed by an insecure page, zero the page and return. |
| |
| Use cases |
| ~~~~~~~~~ |
| |
| #. The Hypervisor cannot access the SVM pages since they are backed by |
| secure pages. Hence an SVM must explicitly request Ultravisor for |
| pages it can share with Hypervisor. |
| |
| #. Shared pages are needed to support virtio and Virtual Processor Area |
| (VPA) in SVMs. |
| |
| |
| UV_UNSHARE_PAGE |
| --------------- |
| |
| Restore a shared SVM page to its initial state. |
| |
| Syntax |
| ~~~~~~ |
| |
| .. code-block:: c |
| |
| uint64_t ultracall(const uint64_t UV_UNSHARE_PAGE, |
| uint64_t gfn, /* guest page frame number */ |
| uint73 num) /* number of pages of size PAGE_SIZE*/ |
| |
| Return values |
| ~~~~~~~~~~~~~ |
| |
| One of the following values: |
| |
| * U_SUCCESS on success. |
| * U_FUNCTION if functionality is not supported. |
| * U_INVALID if VM is not secure. |
| * U_PARAMETER if ``gfn`` is invalid. |
| * U_P2 if ``num`` is invalid. |
| |
| Description |
| ~~~~~~~~~~~ |
| |
| Stop sharing ``num`` pages starting at ``gfn`` with the Hypervisor. |
| Assume that the page size is PAGE_SIZE. Zero the pages before |
| returning. |
| |
| If the address is already backed by an insecure page, unmap the page |
| and back it with a secure page. Inform the Hypervisor to release |
| reference to its shared page. If the address is not backed by a page |
| yet, mark the PTE as secure and back it with a secure page when that |
| address is accessed. If it is already backed by an secure page zero |
| the page and return. |
| |
| Use cases |
| ~~~~~~~~~ |
| |
| #. The SVM may decide to unshare a page from the Hypervisor. |
| |
| |
| UV_UNSHARE_ALL_PAGES |
| -------------------- |
| |
| Unshare all pages the SVM has shared with Hypervisor. |
| |
| Syntax |
| ~~~~~~ |
| |
| .. code-block:: c |
| |
| uint64_t ultracall(const uint64_t UV_UNSHARE_ALL_PAGES) |
| |
| Return values |
| ~~~~~~~~~~~~~ |
| |
| One of the following values: |
| |
| * U_SUCCESS on success. |
| * U_FUNCTION if functionality is not supported. |
| * U_INVAL if VM is not secure. |
| |
| Description |
| ~~~~~~~~~~~ |
| |
| Unshare all shared pages from the Hypervisor. All unshared pages are |
| zeroed on return. Only pages explicitly shared by the SVM with the |
| Hypervisor (using UV_SHARE_PAGE ultracall) are unshared. Ultravisor |
| may internally share some pages with the Hypervisor without explicit |
| request from the SVM. These pages will not be unshared by this |
| ultracall. |
| |
| Use cases |
| ~~~~~~~~~ |
| |
| #. This call is needed when ``kexec`` is used to boot a different |
| kernel. It may also be needed during SVM reset. |
| |
| UV_ESM |
| ------ |
| |
| Secure the virtual machine (*enter secure mode*). |
| |
| Syntax |
| ~~~~~~ |
| |
| .. code-block:: c |
| |
| uint64_t ultracall(const uint64_t UV_ESM, |
| uint64_t esm_blob_addr, /* location of the ESM blob */ |
| unint64_t fdt) /* Flattened device tree */ |
| |
| Return values |
| ~~~~~~~~~~~~~ |
| |
| One of the following values: |
| |
| * U_SUCCESS on success (including if VM is already secure). |
| * U_FUNCTION if functionality is not supported. |
| * U_INVALID if VM is not secure. |
| * U_PARAMETER if ``esm_blob_addr`` is invalid. |
| * U_P2 if ``fdt`` is invalid. |
| * U_PERMISSION if any integrity checks fail. |
| * U_RETRY insufficient memory to create SVM. |
| * U_NO_KEY symmetric key unavailable. |
| |
| Description |
| ~~~~~~~~~~~ |
| |
| Secure the virtual machine. On successful completion, return |
| control to the virtual machine at the address specified in the |
| ESM blob. |
| |
| Use cases |
| ~~~~~~~~~ |
| |
| #. A normal virtual machine can choose to switch to a secure mode. |
| |
| Hypervisor Calls API |
| #################### |
| |
| This document describes the Hypervisor calls (hypercalls) that are |
| needed to support the Ultravisor. Hypercalls are services provided by |
| the Hypervisor to virtual machines and Ultravisor. |
| |
| Register usage for these hypercalls is identical to that of the other |
| hypercalls defined in the Power Architecture Platform Reference (PAPR) |
| document. i.e on input, register R3 identifies the specific service |
| that is being requested and registers R4 through R11 contain |
| additional parameters to the hypercall, if any. On output, register |
| R3 contains the return value and registers R4 through R9 contain any |
| other output values from the hypercall. |
| |
| This document only covers hypercalls currently implemented/planned |
| for Ultravisor usage but others can be added here when it makes sense. |
| |
| The full specification for all hypercalls/ultracalls will eventually |
| be made available in the public/OpenPower version of the PAPR |
| specification. |
| |
| Hypervisor calls to support Ultravisor |
| ====================================== |
| |
| Following are the set of hypercalls needed to support Ultravisor. |
| |
| H_SVM_INIT_START |
| ---------------- |
| |
| Begin the process of converting a normal virtual machine into an SVM. |
| |
| Syntax |
| ~~~~~~ |
| |
| .. code-block:: c |
| |
| uint64_t hypercall(const uint64_t H_SVM_INIT_START) |
| |
| Return values |
| ~~~~~~~~~~~~~ |
| |
| One of the following values: |
| |
| * H_SUCCESS on success. |
| * H_STATE if the VM is not in a position to switch to secure. |
| |
| Description |
| ~~~~~~~~~~~ |
| |
| Initiate the process of securing a virtual machine. This involves |
| coordinating with the Ultravisor, using ultracalls, to allocate |
| resources in the Ultravisor for the new SVM, transferring the VM's |
| pages from normal to secure memory etc. When the process is |
| completed, Ultravisor issues the H_SVM_INIT_DONE hypercall. |
| |
| Use cases |
| ~~~~~~~~~ |
| |
| #. Ultravisor uses this hypercall to inform Hypervisor that a VM |
| has initiated the process of switching to secure mode. |
| |
| |
| H_SVM_INIT_DONE |
| --------------- |
| |
| Complete the process of securing an SVM. |
| |
| Syntax |
| ~~~~~~ |
| |
| .. code-block:: c |
| |
| uint64_t hypercall(const uint64_t H_SVM_INIT_DONE) |
| |
| Return values |
| ~~~~~~~~~~~~~ |
| |
| One of the following values: |
| |
| * H_SUCCESS on success. |
| * H_UNSUPPORTED if called from the wrong context (e.g. |
| from an SVM or before an H_SVM_INIT_START |
| hypercall). |
| * H_STATE if the hypervisor could not successfully |
| transition the VM to Secure VM. |
| |
| Description |
| ~~~~~~~~~~~ |
| |
| Complete the process of securing a virtual machine. This call must |
| be made after a prior call to ``H_SVM_INIT_START`` hypercall. |
| |
| Use cases |
| ~~~~~~~~~ |
| |
| On successfully securing a virtual machine, the Ultravisor informs |
| Hypervisor about it. Hypervisor can use this call to finish setting |
| up its internal state for this virtual machine. |
| |
| |
| H_SVM_INIT_ABORT |
| ---------------- |
| |
| Abort the process of securing an SVM. |
| |
| Syntax |
| ~~~~~~ |
| |
| .. code-block:: c |
| |
| uint64_t hypercall(const uint64_t H_SVM_INIT_ABORT) |
| |
| Return values |
| ~~~~~~~~~~~~~ |
| |
| One of the following values: |
| |
| * H_PARAMETER on successfully cleaning up the state, |
| Hypervisor will return this value to the |
| **guest**, to indicate that the underlying |
| UV_ESM ultracall failed. |
| |
| * H_STATE if called after a VM has gone secure (i.e |
| H_SVM_INIT_DONE hypercall was successful). |
| |
| * H_UNSUPPORTED if called from a wrong context (e.g. from a |
| normal VM). |
| |
| Description |
| ~~~~~~~~~~~ |
| |
| Abort the process of securing a virtual machine. This call must |
| be made after a prior call to ``H_SVM_INIT_START`` hypercall and |
| before a call to ``H_SVM_INIT_DONE``. |
| |
| On entry into this hypercall the non-volatile GPRs and FPRs are |
| expected to contain the values they had at the time the VM issued |
| the UV_ESM ultracall. Further ``SRR0`` is expected to contain the |
| address of the instruction after the ``UV_ESM`` ultracall and ``SRR1`` |
| the MSR value with which to return to the VM. |
| |
| This hypercall will cleanup any partial state that was established for |
| the VM since the prior ``H_SVM_INIT_START`` hypercall, including paging |
| out pages that were paged-into secure memory, and issue the |
| ``UV_SVM_TERMINATE`` ultracall to terminate the VM. |
| |
| After the partial state is cleaned up, control returns to the VM |
| (**not Ultravisor**), at the address specified in ``SRR0`` with the |
| MSR values set to the value in ``SRR1``. |
| |
| Use cases |
| ~~~~~~~~~ |
| |
| If after a successful call to ``H_SVM_INIT_START``, the Ultravisor |
| encounters an error while securing a virtual machine, either due |
| to lack of resources or because the VM's security information could |
| not be validated, Ultravisor informs the Hypervisor about it. |
| Hypervisor should use this call to clean up any internal state for |
| this virtual machine and return to the VM. |
| |
| H_SVM_PAGE_IN |
| ------------- |
| |
| Move the contents of a page from normal memory to secure memory. |
| |
| Syntax |
| ~~~~~~ |
| |
| .. code-block:: c |
| |
| uint64_t hypercall(const uint64_t H_SVM_PAGE_IN, |
| uint64_t guest_pa, /* guest-physical-address */ |
| uint64_t flags, /* flags */ |
| uint64_t order) /* page size order */ |
| |
| Return values |
| ~~~~~~~~~~~~~ |
| |
| One of the following values: |
| |
| * H_SUCCESS on success. |
| * H_PARAMETER if ``guest_pa`` is invalid. |
| * H_P2 if ``flags`` is invalid. |
| * H_P3 if ``order`` of page is invalid. |
| |
| Description |
| ~~~~~~~~~~~ |
| |
| Retrieve the content of the page, belonging to the VM at the specified |
| guest physical address. |
| |
| Only valid value(s) in ``flags`` are: |
| |
| * H_PAGE_IN_SHARED which indicates that the page is to be shared |
| with the Ultravisor. |
| |
| * H_PAGE_IN_NONSHARED indicates that the UV is not anymore |
| interested in the page. Applicable if the page is a shared page. |
| |
| The ``order`` parameter must correspond to the configured page size. |
| |
| Use cases |
| ~~~~~~~~~ |
| |
| #. When a normal VM becomes a secure VM (using the UV_ESM ultracall), |
| the Ultravisor uses this hypercall to move contents of each page of |
| the VM from normal memory to secure memory. |
| |
| #. Ultravisor uses this hypercall to ask Hypervisor to provide a page |
| in normal memory that can be shared between the SVM and Hypervisor. |
| |
| #. Ultravisor uses this hypercall to page-in a paged-out page. This |
| can happen when the SVM touches a paged-out page. |
| |
| #. If SVM wants to disable sharing of pages with Hypervisor, it can |
| inform Ultravisor to do so. Ultravisor will then use this hypercall |
| and inform Hypervisor that it has released access to the normal |
| page. |
| |
| H_SVM_PAGE_OUT |
| --------------- |
| |
| Move the contents of the page to normal memory. |
| |
| Syntax |
| ~~~~~~ |
| |
| .. code-block:: c |
| |
| uint64_t hypercall(const uint64_t H_SVM_PAGE_OUT, |
| uint64_t guest_pa, /* guest-physical-address */ |
| uint64_t flags, /* flags (currently none) */ |
| uint64_t order) /* page size order */ |
| |
| Return values |
| ~~~~~~~~~~~~~ |
| |
| One of the following values: |
| |
| * H_SUCCESS on success. |
| * H_PARAMETER if ``guest_pa`` is invalid. |
| * H_P2 if ``flags`` is invalid. |
| * H_P3 if ``order`` is invalid. |
| |
| Description |
| ~~~~~~~~~~~ |
| |
| Move the contents of the page identified by ``guest_pa`` to normal |
| memory. |
| |
| Currently ``flags`` is unused and must be set to 0. The ``order`` |
| parameter must correspond to the configured page size. |
| |
| Use cases |
| ~~~~~~~~~ |
| |
| #. If Ultravisor is running low on secure pages, it can move the |
| contents of some secure pages, into normal pages using this |
| hypercall. The content will be encrypted. |
| |
| References |
| ########## |
| |
| - `Supporting Protected Computing on IBM Power Architecture <https://developer.ibm.com/articles/l-support-protected-computing/>`_ |