Commit 3a43970d authored by Sukadev Bhattiprolu's avatar Sukadev Bhattiprolu Committed by Paul Mackerras
Browse files

KVM: PPC: Book3S HV: Implement H_SVM_INIT_ABORT hcall



Implement the H_SVM_INIT_ABORT hcall which the Ultravisor can use to
abort an SVM after it has issued the H_SVM_INIT_START and before the
H_SVM_INIT_DONE hcalls. This hcall could be used when Ultravisor
encounters security violations or other errors when starting an SVM.

Note that this hcall is different from UV_SVM_TERMINATE ucall which
is used by HV to terminate/cleanup an VM that has becore secure.

The H_SVM_INIT_ABORT basically undoes operations that were done
since the H_SVM_INIT_START hcall - i.e page-out all the VM pages back
to normal memory, and terminate the SVM.

(If we do not bring the pages back to normal memory, the text/data
of the VM would be stuck in secure memory and since the SVM did not
go secure, its MSR_S bit will be clear and the VM wont be able to
access its pages even to do a clean exit).

Based on patches and discussion with Paul Mackerras, Ram Pai and
Bharata Rao.

Signed-off-by: default avatarRam Pai <linuxram@linux.ibm.com>
Signed-off-by: default avatarSukadev Bhattiprolu <sukadev@linux.ibm.com>
Signed-off-by: default avatarBharata B Rao <bharata@linux.ibm.com>
Signed-off-by: default avatarPaul Mackerras <paulus@ozlabs.org>
parent ce477a7a
Loading
Loading
Loading
Loading
+60 −0
Original line number Diff line number Diff line
@@ -948,6 +948,66 @@ Use cases
    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
-------------

+1 −0
Original line number Diff line number Diff line
@@ -350,6 +350,7 @@
#define H_SVM_PAGE_OUT		0xEF04
#define H_SVM_INIT_START	0xEF08
#define H_SVM_INIT_DONE		0xEF0C
#define H_SVM_INIT_ABORT	0xEF14

/* Values for 2nd argument to H_SET_MODE */
#define H_SET_MODE_RESOURCE_SET_CIABR		1
+6 −0
Original line number Diff line number Diff line
@@ -19,6 +19,7 @@ unsigned long kvmppc_h_svm_page_out(struct kvm *kvm,
unsigned long kvmppc_h_svm_init_start(struct kvm *kvm);
unsigned long kvmppc_h_svm_init_done(struct kvm *kvm);
int kvmppc_send_page_to_uv(struct kvm *kvm, unsigned long gfn);
unsigned long kvmppc_h_svm_init_abort(struct kvm *kvm);
void kvmppc_uvmem_drop_pages(const struct kvm_memory_slot *free,
			     struct kvm *kvm, bool skip_page_out);
#else
@@ -62,6 +63,11 @@ static inline unsigned long kvmppc_h_svm_init_done(struct kvm *kvm)
	return H_UNSUPPORTED;
}

static inline unsigned long kvmppc_h_svm_init_abort(struct kvm *kvm)
{
	return H_UNSUPPORTED;
}

static inline int kvmppc_send_page_to_uv(struct kvm *kvm, unsigned long gfn)
{
	return -EFAULT;
+1 −0
Original line number Diff line number Diff line
@@ -278,6 +278,7 @@ struct kvm_resize_hpt;
/* Flag values for kvm_arch.secure_guest */
#define KVMPPC_SECURE_INIT_START 0x1 /* H_SVM_INIT_START has been called */
#define KVMPPC_SECURE_INIT_DONE  0x2 /* H_SVM_INIT_DONE completed */
#define KVMPPC_SECURE_INIT_ABORT 0x4 /* H_SVM_INIT_ABORT issued */

struct kvm_arch {
	unsigned int lpid;
+3 −0
Original line number Diff line number Diff line
@@ -1091,6 +1091,9 @@ int kvmppc_pseries_do_hcall(struct kvm_vcpu *vcpu)
	case H_SVM_INIT_DONE:
		ret = kvmppc_h_svm_init_done(vcpu->kvm);
		break;
	case H_SVM_INIT_ABORT:
		ret = kvmppc_h_svm_init_abort(vcpu->kvm);
		break;

	default:
		return RESUME_HOST;
Loading