From mboxrd@z Thu Jan 1 00:00:00 1970 From: Avi Kivity Subject: Re: [PATCH 14/27] nVMX: Implement VMREAD and VMWRITE Date: Sun, 17 Oct 2010 15:25:43 +0200 Message-ID: <4CBAF957.3090103@redhat.com> References: <1287309814-nyh@il.ibm.com> <201010171010.o9HAAjYv029458@rice.haifa.ibm.com> Mime-Version: 1.0 Content-Type: text/plain; charset=ISO-8859-1; format=flowed Content-Transfer-Encoding: 7bit Cc: kvm@vger.kernel.org, gleb@redhat.com To: "Nadav Har'El" Return-path: Received: from mx1.redhat.com ([209.132.183.28]:59005 "EHLO mx1.redhat.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1756613Ab0JQNZt (ORCPT ); Sun, 17 Oct 2010 09:25:49 -0400 In-Reply-To: <201010171010.o9HAAjYv029458@rice.haifa.ibm.com> Sender: kvm-owner@vger.kernel.org List-ID: On 10/17/2010 12:10 PM, Nadav Har'El wrote: > Implement the VMREAD and VMWRITE instructions. With these instructions, L1 > can read and write to the VMCS it is holding. The values are read or written > to the fields of the vmcs_fields structure introduced in the previous patch. > > > + > +static inline bool vmcs12_read_any(struct kvm_vcpu *vcpu, > + unsigned long field, u64 *ret) > +{ > + short offset = vmcs_field_to_offset(field); > + char *p; > + > + if (offset< 0) > + return 0; > + > + p = ((char *)(get_vmcs12_fields(vcpu))) + offset; > + > + switch (vmcs_field_type(field)) { > + case VMCS_FIELD_TYPE_ULONG: > + *ret = *((unsigned long *)p); The cast here should depend on guest mode. A !is_long_mode() guest needs to cast this to u32. > + return 1; > + case VMCS_FIELD_TYPE_U16: > + *ret = (u16) *((unsigned long *)p); > + return 1; > + case VMCS_FIELD_TYPE_U32: > + *ret = (u32) *((unsigned long *)p); > + return 1; > + case VMCS_FIELD_TYPE_U64: > + *ret = *((u64 *)p); Ditto. > + return 1; > + default: > + return 0; /* can never happen. */ > + } > +} > + > + > +static int handle_vmwrite(struct kvm_vcpu *vcpu) > +{ > + unsigned long field; > + u64 field_value = 0; > + gva_t gva; > + int field_type; > + unsigned long exit_qualification = vmcs_readl(EXIT_QUALIFICATION); > + u32 vmx_instruction_info = vmcs_read32(VMX_INSTRUCTION_INFO); > + char *p; > + short offset; > + > + if (!nested_vmx_check_permission(vcpu)) > + return 1; > + > + if (vmx_instruction_info& (1u<< 10)) > + field_value = kvm_register_read(vcpu, > + (((vmx_instruction_info)>> 3)& 0xf)); > + else { > + if (get_vmx_mem_address(vcpu, exit_qualification, > + vmx_instruction_info,&gva)) > + return 1; > + if(kvm_read_guest_virt(gva,&field_value, > + (is_long_mode(vcpu) ? 8 : 4), vcpu, NULL)){ Whitespace. > + kvm_queue_exception(vcpu, PF_VECTOR); > + return 1; > + } > + } > + > + > + field = kvm_register_read(vcpu, (((vmx_instruction_info)>> 28)& 0xf)); > + > + if (vmcs_field_readonly(field)) { > + nested_vmx_failValid(vcpu, > + VMXERR_VMWRITE_READ_ONLY_VMCS_COMPONENT); > + skip_emulated_instruction(vcpu); > + return 1; > + } > + > + field_type = vmcs_field_type(field); > + > + offset = vmcs_field_to_offset(field); > + if (offset< 0) { > + nested_vmx_failValid(vcpu, VMXERR_UNSUPPORTED_VMCS_COMPONENT); > + skip_emulated_instruction(vcpu); > + return 1; > + } > + p = ((char *) get_vmcs12_fields(vcpu)) + offset; > + > + switch (field_type) { > + case VMCS_FIELD_TYPE_U16: > + *(u16 *)p = field_value; > + break; > + case VMCS_FIELD_TYPE_U32: > + *(u32 *)p = field_value; > + break; > + case VMCS_FIELD_TYPE_U64: > +#ifdef CONFIG_X86_64 > + *(unsigned long *)p = field_value; > +#else > + *(unsigned long *)p = field_value; > + *(((unsigned long *)p)+1) = field_value>> 32; Depend on guest bitness here, not host bitness. 32-bit guests only write the first word. > +#endif > + break; > + case VMCS_FIELD_TYPE_ULONG: > + *(unsigned long *)p = field_value; > + break; > + default: > + nested_vmx_failValid(vcpu, VMXERR_UNSUPPORTED_VMCS_COMPONENT); > + skip_emulated_instruction(vcpu); > + return 1; > + } > + > + nested_vmx_succeed(vcpu); > + skip_emulated_instruction(vcpu); > + return 1; > +} > + -- error compiling committee.c: too many arguments to function