On Sun, Apr 21, 2013 at 2:49 PM, Gleb Natapov <[email protected]> wrote:
> On Sun, Apr 21, 2013 at 02:12:21PM +0530, [email protected] wrote:
>> From: Prasad Joshi <[email protected]>
>>
>> Write only SVM_KEY can be used to create a password protected mechanism
>> to clear VM_CR.LOCK.
>>
>> This key can only be set when VM_CR.LOCK is unset. Once this key is set,
>> a write to it compares the written value with already set key. The
>> VM_CR.LOCK is unset only if the key matches. All reads from this MSR
>> must return 0.
>>
>> Signed-off-by: Prasad Joshi <[email protected]>
>> ---
>> arch/x86/include/uapi/asm/msr-index.h | 1 +
>> arch/x86/kvm/svm.c | 31 +++++++++++++++++++++++++++++++
>> 2 files changed, 32 insertions(+)
>>
>> diff --git a/arch/x86/include/uapi/asm/msr-index.h
>> b/arch/x86/include/uapi/asm/msr-index.h
>> index 892ce40..eda8346 100644
>> --- a/arch/x86/include/uapi/asm/msr-index.h
>> +++ b/arch/x86/include/uapi/asm/msr-index.h
>> @@ -170,6 +170,7 @@
>>
>> #define MSR_AMD64_PATCH_LEVEL 0x0000008b
>> #define MSR_AMD64_TSC_RATIO 0xc0000104
>> +#define MSR_AMD64_SVM_KEY 0xc0010118
>> #define MSR_AMD64_NB_CFG 0xc001001f
>> #define MSR_AMD64_PATCH_LOADER 0xc0010020
>> #define MSR_AMD64_OSVW_ID_LENGTH 0xc0010140
>> diff --git a/arch/x86/kvm/svm.c b/arch/x86/kvm/svm.c
>> index fcdfdea..73b2dc2 100644
>> --- a/arch/x86/kvm/svm.c
>> +++ b/arch/x86/kvm/svm.c
>> @@ -150,6 +150,8 @@ struct vcpu_svm {
>>
>> struct nested_state nested;
>>
>> + u64 svm_key; /* Write only SVM Key */
>> +
>> bool nmi_singlestep;
>>
>> unsigned int3_injected;
>> @@ -3079,6 +3081,13 @@ static int svm_get_msr(struct kvm_vcpu *vcpu,
>> unsigned ecx, u64 *data)
>> case MSR_VM_CR:
>> *data = svm->nested.vm_cr_msr;
>> break;
>> + case MSR_AMD64_SVM_KEY:
>> + /*
>> + * SVM Key is password protected mechanism to manage
>> + * VM_CR.LOCK and therefore reading it must always return 0.
>> + */
>> + *data = 0;
>> + break;
>> case MSR_IA32_UCODE_REV:
>> *data = 0x01000065;
>> break;
>> @@ -3132,6 +3141,26 @@ static int svm_set_vm_cr(struct kvm_vcpu *vcpu, u64
>> data)
>> return 0;
>> }
>>
>> +static int svm_set_svm_key(struct kvm_vcpu *vcpu, u64 data)
>> +{
>> + struct vcpu_svm *svm = to_svm(vcpu);
>> +
>> + if (!boot_cpu_has(X86_FEATURE_SVML))
>> + return 1;
>> +
> Since the feature is emulated why do you care if host cpu supports it?
Thanks Gleb. I changed this to checking SVML feature on the guest CPU.
Something like this should work
if (!(cpuid_edx(SVM_CPUID_FUNC) & SVM_FEATURE_SVML))
return 1;
>
>> + if (!(svm->nested.vm_cr_msr & SVM_VM_CR_SVM_LOCK_MASK) && data) {
>> + /* vm_cr.lock not set: set the password key */
>> + svm->svm_key = data;
>> + } else {
>> + /* vm_cr.lock is set */
>> + if (data && svm->svm_key == data) {
>> + /* password key matched: reset the lock */
>> + svm->nested.vm_cr_msr &= ~SVM_VM_CR_SVM_LOCK_MASK;
>> + }
>> + }
> That's not enough. First of all KVM does not currently checks
> SVMDIS before allowing setting of EFER_SVME. Second svm_set_vm_cr()
> erroneously
> ignores writes into VM_CR SVMDIS/LOCK if SVMDIS is set, while it should
> check LOCK.
I was aware of these changes (BUGs), however thought they must go in
another patch.
Any ways, I will include them in the next patch series.
> Third when write is done by a userspace during reset the
> key check should be ignored.
I missed this part. I think, CPU reset must set svm_key to 0 and reset
the VM_CR.LOCK. Both of these can be part of init_vmcb() which is
called during CPU reset. It should ensure that the no key is
registered during CPU reset.
Thanks.
-- Prasad
--
To unsubscribe from this list: send the line "unsubscribe kvm" in
the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html