diff options
Diffstat (limited to 'arch/powerpc/kvm/book3s.c')
| -rw-r--r-- | arch/powerpc/kvm/book3s.c | 125 | 
1 files changed, 125 insertions, 0 deletions
| diff --git a/arch/powerpc/kvm/book3s.c b/arch/powerpc/kvm/book3s.c index 3f2a8360c857..a4b645285240 100644 --- a/arch/powerpc/kvm/book3s.c +++ b/arch/powerpc/kvm/book3s.c @@ -411,6 +411,15 @@ int kvm_arch_vcpu_setup(struct kvm_vcpu *vcpu)  	return 0;  } +int kvmppc_subarch_vcpu_init(struct kvm_vcpu *vcpu) +{ +	return 0; +} + +void kvmppc_subarch_vcpu_uninit(struct kvm_vcpu *vcpu) +{ +} +  int kvm_arch_vcpu_ioctl_get_regs(struct kvm_vcpu *vcpu, struct kvm_regs *regs)  {  	int i; @@ -476,6 +485,122 @@ int kvm_arch_vcpu_ioctl_set_fpu(struct kvm_vcpu *vcpu, struct kvm_fpu *fpu)  	return -ENOTSUPP;  } +int kvm_vcpu_ioctl_get_one_reg(struct kvm_vcpu *vcpu, struct kvm_one_reg *reg) +{ +	int r; +	union kvmppc_one_reg val; +	int size; +	long int i; + +	size = one_reg_size(reg->id); +	if (size > sizeof(val)) +		return -EINVAL; + +	r = kvmppc_get_one_reg(vcpu, reg->id, &val); + +	if (r == -EINVAL) { +		r = 0; +		switch (reg->id) { +		case KVM_REG_PPC_DAR: +			val = get_reg_val(reg->id, vcpu->arch.shared->dar); +			break; +		case KVM_REG_PPC_DSISR: +			val = get_reg_val(reg->id, vcpu->arch.shared->dsisr); +			break; +		case KVM_REG_PPC_FPR0 ... KVM_REG_PPC_FPR31: +			i = reg->id - KVM_REG_PPC_FPR0; +			val = get_reg_val(reg->id, vcpu->arch.fpr[i]); +			break; +		case KVM_REG_PPC_FPSCR: +			val = get_reg_val(reg->id, vcpu->arch.fpscr); +			break; +#ifdef CONFIG_ALTIVEC +		case KVM_REG_PPC_VR0 ... KVM_REG_PPC_VR31: +			if (!cpu_has_feature(CPU_FTR_ALTIVEC)) { +				r = -ENXIO; +				break; +			} +			val.vval = vcpu->arch.vr[reg->id - KVM_REG_PPC_VR0]; +			break; +		case KVM_REG_PPC_VSCR: +			if (!cpu_has_feature(CPU_FTR_ALTIVEC)) { +				r = -ENXIO; +				break; +			} +			val = get_reg_val(reg->id, vcpu->arch.vscr.u[3]); +			break; +#endif /* CONFIG_ALTIVEC */ +		default: +			r = -EINVAL; +			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; +	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; + +	r = kvmppc_set_one_reg(vcpu, reg->id, &val); + +	if (r == -EINVAL) { +		r = 0; +		switch (reg->id) { +		case KVM_REG_PPC_DAR: +			vcpu->arch.shared->dar = set_reg_val(reg->id, val); +			break; +		case KVM_REG_PPC_DSISR: +			vcpu->arch.shared->dsisr = set_reg_val(reg->id, val); +			break; +		case KVM_REG_PPC_FPR0 ... KVM_REG_PPC_FPR31: +			i = reg->id - KVM_REG_PPC_FPR0; +			vcpu->arch.fpr[i] = set_reg_val(reg->id, val); +			break; +		case KVM_REG_PPC_FPSCR: +			vcpu->arch.fpscr = set_reg_val(reg->id, val); +			break; +#ifdef CONFIG_ALTIVEC +		case KVM_REG_PPC_VR0 ... KVM_REG_PPC_VR31: +			if (!cpu_has_feature(CPU_FTR_ALTIVEC)) { +				r = -ENXIO; +				break; +			} +			vcpu->arch.vr[reg->id - KVM_REG_PPC_VR0] = val.vval; +			break; +		case KVM_REG_PPC_VSCR: +			if (!cpu_has_feature(CPU_FTR_ALTIVEC)) { +				r = -ENXIO; +				break; +			} +			vcpu->arch.vscr.u[3] = set_reg_val(reg->id, val); +			break; +#endif /* CONFIG_ALTIVEC */ +		default: +			r = -EINVAL; +			break; +		} +	} + +	return r; +} +  int kvm_arch_vcpu_ioctl_translate(struct kvm_vcpu *vcpu,                                    struct kvm_translation *tr)  { |