|
@@ -1415,117 +1415,125 @@ int kvm_arch_vcpu_ioctl_set_sregs(struct kvm_vcpu *vcpu,
|
|
|
|
|
|
int kvm_vcpu_ioctl_get_one_reg(struct kvm_vcpu *vcpu, struct kvm_one_reg *reg)
|
|
|
{
|
|
|
- int r = -EINVAL;
|
|
|
+ int r = 0;
|
|
|
+ union kvmppc_one_reg val;
|
|
|
+ int size;
|
|
|
+ long int i;
|
|
|
+
|
|
|
+ size = one_reg_size(reg->id);
|
|
|
+ if (size > sizeof(val))
|
|
|
+ return -EINVAL;
|
|
|
|
|
|
switch (reg->id) {
|
|
|
case KVM_REG_PPC_IAC1:
|
|
|
case KVM_REG_PPC_IAC2:
|
|
|
case KVM_REG_PPC_IAC3:
|
|
|
- case KVM_REG_PPC_IAC4: {
|
|
|
- int iac = reg->id - KVM_REG_PPC_IAC1;
|
|
|
- r = copy_to_user((u64 __user *)(long)reg->addr,
|
|
|
- &vcpu->arch.dbg_reg.iac[iac], sizeof(u64));
|
|
|
+ case KVM_REG_PPC_IAC4:
|
|
|
+ i = reg->id - KVM_REG_PPC_IAC1;
|
|
|
+ val = get_reg_val(reg->id, vcpu->arch.dbg_reg.iac[i]);
|
|
|
break;
|
|
|
- }
|
|
|
case KVM_REG_PPC_DAC1:
|
|
|
- case KVM_REG_PPC_DAC2: {
|
|
|
- int dac = reg->id - KVM_REG_PPC_DAC1;
|
|
|
- r = copy_to_user((u64 __user *)(long)reg->addr,
|
|
|
- &vcpu->arch.dbg_reg.dac[dac], sizeof(u64));
|
|
|
+ case KVM_REG_PPC_DAC2:
|
|
|
+ i = reg->id - KVM_REG_PPC_DAC1;
|
|
|
+ val = get_reg_val(reg->id, vcpu->arch.dbg_reg.dac[i]);
|
|
|
break;
|
|
|
- }
|
|
|
case KVM_REG_PPC_EPR: {
|
|
|
u32 epr = get_guest_epr(vcpu);
|
|
|
- r = put_user(epr, (u32 __user *)(long)reg->addr);
|
|
|
+ val = get_reg_val(reg->id, epr);
|
|
|
break;
|
|
|
}
|
|
|
#if defined(CONFIG_64BIT)
|
|
|
case KVM_REG_PPC_EPCR:
|
|
|
- r = put_user(vcpu->arch.epcr, (u32 __user *)(long)reg->addr);
|
|
|
+ val = get_reg_val(reg->id, vcpu->arch.epcr);
|
|
|
break;
|
|
|
#endif
|
|
|
case KVM_REG_PPC_TCR:
|
|
|
- r = put_user(vcpu->arch.tcr, (u32 __user *)(long)reg->addr);
|
|
|
+ val = get_reg_val(reg->id, vcpu->arch.tcr);
|
|
|
break;
|
|
|
case KVM_REG_PPC_TSR:
|
|
|
- r = put_user(vcpu->arch.tsr, (u32 __user *)(long)reg->addr);
|
|
|
+ val = get_reg_val(reg->id, vcpu->arch.tsr);
|
|
|
break;
|
|
|
- case KVM_REG_PPC_DEBUG_INST: {
|
|
|
- u32 opcode = KVMPPC_INST_EHPRIV;
|
|
|
- r = copy_to_user((u32 __user *)(long)reg->addr,
|
|
|
- &opcode, sizeof(u32));
|
|
|
+ case KVM_REG_PPC_DEBUG_INST:
|
|
|
+ val = get_reg_val(reg->id, KVMPPC_INST_EHPRIV);
|
|
|
break;
|
|
|
- }
|
|
|
default:
|
|
|
+ r = kvmppc_get_one_reg(vcpu, reg->id, &val);
|
|
|
break;
|
|
|
}
|
|
|
+
|
|
|
+ if (r)
|
|
|
+ return r;
|
|
|
+
|
|
|
+ if (copy_to_user((char __user *)(unsigned long)reg->addr, &val, size))
|
|
|
+ r = -EFAULT;
|
|
|
+
|
|
|
return r;
|
|
|
}
|
|
|
|
|
|
int kvm_vcpu_ioctl_set_one_reg(struct kvm_vcpu *vcpu, struct kvm_one_reg *reg)
|
|
|
{
|
|
|
- int r = -EINVAL;
|
|
|
+ int r = 0;
|
|
|
+ union kvmppc_one_reg val;
|
|
|
+ int size;
|
|
|
+ long int i;
|
|
|
+
|
|
|
+ size = one_reg_size(reg->id);
|
|
|
+ if (size > sizeof(val))
|
|
|
+ return -EINVAL;
|
|
|
+
|
|
|
+ if (copy_from_user(&val, (char __user *)(unsigned long)reg->addr, size))
|
|
|
+ return -EFAULT;
|
|
|
|
|
|
switch (reg->id) {
|
|
|
case KVM_REG_PPC_IAC1:
|
|
|
case KVM_REG_PPC_IAC2:
|
|
|
case KVM_REG_PPC_IAC3:
|
|
|
- case KVM_REG_PPC_IAC4: {
|
|
|
- int iac = reg->id - KVM_REG_PPC_IAC1;
|
|
|
- r = copy_from_user(&vcpu->arch.dbg_reg.iac[iac],
|
|
|
- (u64 __user *)(long)reg->addr, sizeof(u64));
|
|
|
+ case KVM_REG_PPC_IAC4:
|
|
|
+ i = reg->id - KVM_REG_PPC_IAC1;
|
|
|
+ vcpu->arch.dbg_reg.iac[i] = set_reg_val(reg->id, val);
|
|
|
break;
|
|
|
- }
|
|
|
case KVM_REG_PPC_DAC1:
|
|
|
- case KVM_REG_PPC_DAC2: {
|
|
|
- int dac = reg->id - KVM_REG_PPC_DAC1;
|
|
|
- r = copy_from_user(&vcpu->arch.dbg_reg.dac[dac],
|
|
|
- (u64 __user *)(long)reg->addr, sizeof(u64));
|
|
|
+ case KVM_REG_PPC_DAC2:
|
|
|
+ i = reg->id - KVM_REG_PPC_DAC1;
|
|
|
+ vcpu->arch.dbg_reg.dac[i] = set_reg_val(reg->id, val);
|
|
|
break;
|
|
|
- }
|
|
|
case KVM_REG_PPC_EPR: {
|
|
|
- u32 new_epr;
|
|
|
- r = get_user(new_epr, (u32 __user *)(long)reg->addr);
|
|
|
- if (!r)
|
|
|
- kvmppc_set_epr(vcpu, new_epr);
|
|
|
+ u32 new_epr = set_reg_val(reg->id, val);
|
|
|
+ kvmppc_set_epr(vcpu, new_epr);
|
|
|
break;
|
|
|
}
|
|
|
#if defined(CONFIG_64BIT)
|
|
|
case KVM_REG_PPC_EPCR: {
|
|
|
- u32 new_epcr;
|
|
|
- r = get_user(new_epcr, (u32 __user *)(long)reg->addr);
|
|
|
- if (r == 0)
|
|
|
- kvmppc_set_epcr(vcpu, new_epcr);
|
|
|
+ u32 new_epcr = set_reg_val(reg->id, val);
|
|
|
+ kvmppc_set_epcr(vcpu, new_epcr);
|
|
|
break;
|
|
|
}
|
|
|
#endif
|
|
|
case KVM_REG_PPC_OR_TSR: {
|
|
|
- u32 tsr_bits;
|
|
|
- r = get_user(tsr_bits, (u32 __user *)(long)reg->addr);
|
|
|
+ u32 tsr_bits = set_reg_val(reg->id, val);
|
|
|
kvmppc_set_tsr_bits(vcpu, tsr_bits);
|
|
|
break;
|
|
|
}
|
|
|
case KVM_REG_PPC_CLEAR_TSR: {
|
|
|
- u32 tsr_bits;
|
|
|
- r = get_user(tsr_bits, (u32 __user *)(long)reg->addr);
|
|
|
+ u32 tsr_bits = set_reg_val(reg->id, val);
|
|
|
kvmppc_clr_tsr_bits(vcpu, tsr_bits);
|
|
|
break;
|
|
|
}
|
|
|
case KVM_REG_PPC_TSR: {
|
|
|
- u32 tsr;
|
|
|
- r = get_user(tsr, (u32 __user *)(long)reg->addr);
|
|
|
+ u32 tsr = set_reg_val(reg->id, val);
|
|
|
kvmppc_set_tsr(vcpu, tsr);
|
|
|
break;
|
|
|
}
|
|
|
case KVM_REG_PPC_TCR: {
|
|
|
- u32 tcr;
|
|
|
- r = get_user(tcr, (u32 __user *)(long)reg->addr);
|
|
|
+ u32 tcr = set_reg_val(reg->id, val);
|
|
|
kvmppc_set_tcr(vcpu, tcr);
|
|
|
break;
|
|
|
}
|
|
|
default:
|
|
|
+ r = kvmppc_set_one_reg(vcpu, reg->id, &val);
|
|
|
break;
|
|
|
}
|
|
|
+
|
|
|
return r;
|
|
|
}
|
|
|
|