diff options
Diffstat (limited to 'arch/powerpc/kvm/booke.c')
| -rw-r--r-- | arch/powerpc/kvm/booke.c | 123 | 
1 files changed, 73 insertions, 50 deletions
diff --git a/arch/powerpc/kvm/booke.c b/arch/powerpc/kvm/booke.c index a49a68a25c3..1020119226d 100644 --- a/arch/powerpc/kvm/booke.c +++ b/arch/powerpc/kvm/booke.c @@ -346,7 +346,7 @@ static int kvmppc_booke_irqprio_deliver(struct kvm_vcpu *vcpu,  		keep_irq = true;  	} -	if ((priority == BOOKE_IRQPRIO_EXTERNAL) && vcpu->arch.epr_enabled) +	if ((priority == BOOKE_IRQPRIO_EXTERNAL) && vcpu->arch.epr_flags)  		update_epr = true;  	switch (priority) { @@ -427,8 +427,14 @@ static int kvmppc_booke_irqprio_deliver(struct kvm_vcpu *vcpu,  			set_guest_esr(vcpu, vcpu->arch.queued_esr);  		if (update_dear == true)  			set_guest_dear(vcpu, vcpu->arch.queued_dear); -		if (update_epr == true) -			kvm_make_request(KVM_REQ_EPR_EXIT, vcpu); +		if (update_epr == true) { +			if (vcpu->arch.epr_flags & KVMPPC_EPR_USER) +				kvm_make_request(KVM_REQ_EPR_EXIT, vcpu); +			else if (vcpu->arch.epr_flags & KVMPPC_EPR_KERNEL) { +				BUG_ON(vcpu->arch.irq_type != KVMPPC_IRQ_MPIC); +				kvmppc_mpic_set_epr(vcpu); +			} +		}  		new_msr &= msr_mask;  #if defined(CONFIG_64BIT) @@ -745,6 +751,9 @@ static int emulation_exit(struct kvm_run *run, struct kvm_vcpu *vcpu)  		kvmppc_core_queue_program(vcpu, ESR_PIL);  		return RESUME_HOST; +	case EMULATE_EXIT_USER: +		return RESUME_HOST; +  	default:  		BUG();  	} @@ -1412,120 +1421,134 @@ 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;  } +int kvm_arch_vcpu_ioctl_set_guest_debug(struct kvm_vcpu *vcpu, +					 struct kvm_guest_debug *dbg) +{ +	return -EINVAL; +} +  int kvm_arch_vcpu_ioctl_get_fpu(struct kvm_vcpu *vcpu, struct kvm_fpu *fpu)  {  	return -ENOTSUPP;  |