KVM: vmx: handle_cr ignores 32/64-bit mode
On 32-bit mode only bits [31:0] of the CR should be used for setting the CR value. Otherwise, the host may incorrectly assume the value is invalid if bits [63:32] are not zero. Moreover, the CR is currently being read twice when CR8 is used. Last, nested mov-cr exiting is modified to handle the CR value correctly as well. Signed-off-by: Nadav Amit <namit@cs.technion.ac.il> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
This commit is contained in:
parent
a449c7aa51
commit
1e32c07955
|
@ -5058,7 +5058,7 @@ static int handle_cr(struct kvm_vcpu *vcpu)
|
||||||
reg = (exit_qualification >> 8) & 15;
|
reg = (exit_qualification >> 8) & 15;
|
||||||
switch ((exit_qualification >> 4) & 3) {
|
switch ((exit_qualification >> 4) & 3) {
|
||||||
case 0: /* mov to cr */
|
case 0: /* mov to cr */
|
||||||
val = kvm_register_read(vcpu, reg);
|
val = kvm_register_readl(vcpu, reg);
|
||||||
trace_kvm_cr_write(cr, val);
|
trace_kvm_cr_write(cr, val);
|
||||||
switch (cr) {
|
switch (cr) {
|
||||||
case 0:
|
case 0:
|
||||||
|
@ -5075,7 +5075,7 @@ static int handle_cr(struct kvm_vcpu *vcpu)
|
||||||
return 1;
|
return 1;
|
||||||
case 8: {
|
case 8: {
|
||||||
u8 cr8_prev = kvm_get_cr8(vcpu);
|
u8 cr8_prev = kvm_get_cr8(vcpu);
|
||||||
u8 cr8 = kvm_register_read(vcpu, reg);
|
u8 cr8 = (u8)val;
|
||||||
err = kvm_set_cr8(vcpu, cr8);
|
err = kvm_set_cr8(vcpu, cr8);
|
||||||
kvm_complete_insn_gp(vcpu, err);
|
kvm_complete_insn_gp(vcpu, err);
|
||||||
if (irqchip_in_kernel(vcpu->kvm))
|
if (irqchip_in_kernel(vcpu->kvm))
|
||||||
|
@ -6770,7 +6770,7 @@ static bool nested_vmx_exit_handled_cr(struct kvm_vcpu *vcpu,
|
||||||
unsigned long exit_qualification = vmcs_readl(EXIT_QUALIFICATION);
|
unsigned long exit_qualification = vmcs_readl(EXIT_QUALIFICATION);
|
||||||
int cr = exit_qualification & 15;
|
int cr = exit_qualification & 15;
|
||||||
int reg = (exit_qualification >> 8) & 15;
|
int reg = (exit_qualification >> 8) & 15;
|
||||||
unsigned long val = kvm_register_read(vcpu, reg);
|
unsigned long val = kvm_register_readl(vcpu, reg);
|
||||||
|
|
||||||
switch ((exit_qualification >> 4) & 3) {
|
switch ((exit_qualification >> 4) & 3) {
|
||||||
case 0: /* mov to cr */
|
case 0: /* mov to cr */
|
||||||
|
|
Loading…
Reference in New Issue