mirror of https://gitee.com/openkylin/linux.git
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: Ram Pai <linuxram@linux.ibm.com> Signed-off-by: Sukadev Bhattiprolu <sukadev@linux.ibm.com> Signed-off-by: Bharata B Rao <bharata@linux.ibm.com> Signed-off-by: Paul Mackerras <paulus@ozlabs.org>
This commit is contained in:
parent
ce477a7a1c
commit
3a43970d55
|
@ -948,6 +948,66 @@ Use cases
|
||||||
up its internal state for this virtual machine.
|
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
|
H_SVM_PAGE_IN
|
||||||
-------------
|
-------------
|
||||||
|
|
||||||
|
|
|
@ -350,6 +350,7 @@
|
||||||
#define H_SVM_PAGE_OUT 0xEF04
|
#define H_SVM_PAGE_OUT 0xEF04
|
||||||
#define H_SVM_INIT_START 0xEF08
|
#define H_SVM_INIT_START 0xEF08
|
||||||
#define H_SVM_INIT_DONE 0xEF0C
|
#define H_SVM_INIT_DONE 0xEF0C
|
||||||
|
#define H_SVM_INIT_ABORT 0xEF14
|
||||||
|
|
||||||
/* Values for 2nd argument to H_SET_MODE */
|
/* Values for 2nd argument to H_SET_MODE */
|
||||||
#define H_SET_MODE_RESOURCE_SET_CIABR 1
|
#define H_SET_MODE_RESOURCE_SET_CIABR 1
|
||||||
|
|
|
@ -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_start(struct kvm *kvm);
|
||||||
unsigned long kvmppc_h_svm_init_done(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);
|
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,
|
void kvmppc_uvmem_drop_pages(const struct kvm_memory_slot *free,
|
||||||
struct kvm *kvm, bool skip_page_out);
|
struct kvm *kvm, bool skip_page_out);
|
||||||
#else
|
#else
|
||||||
|
@ -62,6 +63,11 @@ static inline unsigned long kvmppc_h_svm_init_done(struct kvm *kvm)
|
||||||
return H_UNSUPPORTED;
|
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)
|
static inline int kvmppc_send_page_to_uv(struct kvm *kvm, unsigned long gfn)
|
||||||
{
|
{
|
||||||
return -EFAULT;
|
return -EFAULT;
|
||||||
|
|
|
@ -278,6 +278,7 @@ struct kvm_resize_hpt;
|
||||||
/* Flag values for kvm_arch.secure_guest */
|
/* Flag values for kvm_arch.secure_guest */
|
||||||
#define KVMPPC_SECURE_INIT_START 0x1 /* H_SVM_INIT_START has been called */
|
#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_DONE 0x2 /* H_SVM_INIT_DONE completed */
|
||||||
|
#define KVMPPC_SECURE_INIT_ABORT 0x4 /* H_SVM_INIT_ABORT issued */
|
||||||
|
|
||||||
struct kvm_arch {
|
struct kvm_arch {
|
||||||
unsigned int lpid;
|
unsigned int lpid;
|
||||||
|
|
|
@ -1091,6 +1091,9 @@ int kvmppc_pseries_do_hcall(struct kvm_vcpu *vcpu)
|
||||||
case H_SVM_INIT_DONE:
|
case H_SVM_INIT_DONE:
|
||||||
ret = kvmppc_h_svm_init_done(vcpu->kvm);
|
ret = kvmppc_h_svm_init_done(vcpu->kvm);
|
||||||
break;
|
break;
|
||||||
|
case H_SVM_INIT_ABORT:
|
||||||
|
ret = kvmppc_h_svm_init_abort(vcpu->kvm);
|
||||||
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
return RESUME_HOST;
|
return RESUME_HOST;
|
||||||
|
|
|
@ -286,6 +286,34 @@ void kvmppc_uvmem_drop_pages(const struct kvm_memory_slot *free,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
unsigned long kvmppc_h_svm_init_abort(struct kvm *kvm)
|
||||||
|
{
|
||||||
|
int srcu_idx;
|
||||||
|
struct kvm_memory_slot *memslot;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Expect to be called only after INIT_START and before INIT_DONE.
|
||||||
|
* If INIT_DONE was completed, use normal VM termination sequence.
|
||||||
|
*/
|
||||||
|
if (!(kvm->arch.secure_guest & KVMPPC_SECURE_INIT_START))
|
||||||
|
return H_UNSUPPORTED;
|
||||||
|
|
||||||
|
if (kvm->arch.secure_guest & KVMPPC_SECURE_INIT_DONE)
|
||||||
|
return H_STATE;
|
||||||
|
|
||||||
|
srcu_idx = srcu_read_lock(&kvm->srcu);
|
||||||
|
|
||||||
|
kvm_for_each_memslot(memslot, kvm_memslots(kvm))
|
||||||
|
kvmppc_uvmem_drop_pages(memslot, kvm, false);
|
||||||
|
|
||||||
|
srcu_read_unlock(&kvm->srcu, srcu_idx);
|
||||||
|
|
||||||
|
kvm->arch.secure_guest = 0;
|
||||||
|
uv_svm_terminate(kvm->arch.lpid);
|
||||||
|
|
||||||
|
return H_PARAMETER;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Get a free device PFN from the pool
|
* Get a free device PFN from the pool
|
||||||
*
|
*
|
||||||
|
|
Loading…
Reference in New Issue