KVM: PPC: Book3S PR: PAPR: Access RTAS in big endian
When the guest does an RTAS hypercall it keeps all RTAS variables inside a big endian data structure. To make sure we don't have to bother about endianness inside the actual RTAS handlers, let's just convert the whole structure to host endian before we call our RTAS handlers and back to big endian when we return to the guest. Signed-off-by: Alexander Graf <agraf@suse.de>
This commit is contained in:
parent
1692aa3faa
commit
b59d9d26be
1 changed files with 29 additions and 0 deletions
|
@ -205,6 +205,32 @@ int kvm_vm_ioctl_rtas_define_token(struct kvm *kvm, void __user *argp)
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void kvmppc_rtas_swap_endian_in(struct rtas_args *args)
|
||||||
|
{
|
||||||
|
#ifdef __LITTLE_ENDIAN__
|
||||||
|
int i;
|
||||||
|
|
||||||
|
args->token = be32_to_cpu(args->token);
|
||||||
|
args->nargs = be32_to_cpu(args->nargs);
|
||||||
|
args->nret = be32_to_cpu(args->nret);
|
||||||
|
for (i = 0; i < args->nargs; i++)
|
||||||
|
args->args[i] = be32_to_cpu(args->args[i]);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
static void kvmppc_rtas_swap_endian_out(struct rtas_args *args)
|
||||||
|
{
|
||||||
|
#ifdef __LITTLE_ENDIAN__
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 0; i < args->nret; i++)
|
||||||
|
args->args[i] = cpu_to_be32(args->args[i]);
|
||||||
|
args->token = cpu_to_be32(args->token);
|
||||||
|
args->nargs = cpu_to_be32(args->nargs);
|
||||||
|
args->nret = cpu_to_be32(args->nret);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
int kvmppc_rtas_hcall(struct kvm_vcpu *vcpu)
|
int kvmppc_rtas_hcall(struct kvm_vcpu *vcpu)
|
||||||
{
|
{
|
||||||
struct rtas_token_definition *d;
|
struct rtas_token_definition *d;
|
||||||
|
@ -223,6 +249,8 @@ int kvmppc_rtas_hcall(struct kvm_vcpu *vcpu)
|
||||||
if (rc)
|
if (rc)
|
||||||
goto fail;
|
goto fail;
|
||||||
|
|
||||||
|
kvmppc_rtas_swap_endian_in(&args);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* args->rets is a pointer into args->args. Now that we've
|
* args->rets is a pointer into args->args. Now that we've
|
||||||
* copied args we need to fix it up to point into our copy,
|
* copied args we need to fix it up to point into our copy,
|
||||||
|
@ -247,6 +275,7 @@ int kvmppc_rtas_hcall(struct kvm_vcpu *vcpu)
|
||||||
|
|
||||||
if (rc == 0) {
|
if (rc == 0) {
|
||||||
args.rets = orig_rets;
|
args.rets = orig_rets;
|
||||||
|
kvmppc_rtas_swap_endian_out(&args);
|
||||||
rc = kvm_write_guest(vcpu->kvm, args_phys, &args, sizeof(args));
|
rc = kvm_write_guest(vcpu->kvm, args_phys, &args, sizeof(args));
|
||||||
if (rc)
|
if (rc)
|
||||||
goto fail;
|
goto fail;
|
||||||
|
|
Loading…
Reference in a new issue