linux/arch/powerpc/kvm/book3s_rtas.c
<<
>>
Prefs
   1/*
   2 * Copyright 2012 Michael Ellerman, IBM Corporation.
   3 *
   4 * This program is free software; you can redistribute it and/or modify
   5 * it under the terms of the GNU General Public License, version 2, as
   6 * published by the Free Software Foundation.
   7 */
   8
   9#include <linux/kernel.h>
  10#include <linux/kvm_host.h>
  11#include <linux/kvm.h>
  12#include <linux/err.h>
  13
  14#include <asm/uaccess.h>
  15#include <asm/kvm_book3s.h>
  16#include <asm/kvm_ppc.h>
  17#include <asm/hvcall.h>
  18#include <asm/rtas.h>
  19
  20#ifdef CONFIG_KVM_XICS
  21static void kvm_rtas_set_xive(struct kvm_vcpu *vcpu, struct rtas_args *args)
  22{
  23        u32 irq, server, priority;
  24        int rc;
  25
  26        if (be32_to_cpu(args->nargs) != 3 || be32_to_cpu(args->nret) != 1) {
  27                rc = -3;
  28                goto out;
  29        }
  30
  31        irq = be32_to_cpu(args->args[0]);
  32        server = be32_to_cpu(args->args[1]);
  33        priority = be32_to_cpu(args->args[2]);
  34
  35        rc = kvmppc_xics_set_xive(vcpu->kvm, irq, server, priority);
  36        if (rc)
  37                rc = -3;
  38out:
  39        args->rets[0] = cpu_to_be32(rc);
  40}
  41
  42static void kvm_rtas_get_xive(struct kvm_vcpu *vcpu, struct rtas_args *args)
  43{
  44        u32 irq, server, priority;
  45        int rc;
  46
  47        if (be32_to_cpu(args->nargs) != 1 || be32_to_cpu(args->nret) != 3) {
  48                rc = -3;
  49                goto out;
  50        }
  51
  52        irq = be32_to_cpu(args->args[0]);
  53
  54        server = priority = 0;
  55        rc = kvmppc_xics_get_xive(vcpu->kvm, irq, &server, &priority);
  56        if (rc) {
  57                rc = -3;
  58                goto out;
  59        }
  60
  61        args->rets[1] = cpu_to_be32(server);
  62        args->rets[2] = cpu_to_be32(priority);
  63out:
  64        args->rets[0] = cpu_to_be32(rc);
  65}
  66
  67static void kvm_rtas_int_off(struct kvm_vcpu *vcpu, struct rtas_args *args)
  68{
  69        u32 irq;
  70        int rc;
  71
  72        if (be32_to_cpu(args->nargs) != 1 || be32_to_cpu(args->nret) != 1) {
  73                rc = -3;
  74                goto out;
  75        }
  76
  77        irq = be32_to_cpu(args->args[0]);
  78
  79        rc = kvmppc_xics_int_off(vcpu->kvm, irq);
  80        if (rc)
  81                rc = -3;
  82out:
  83        args->rets[0] = cpu_to_be32(rc);
  84}
  85
  86static void kvm_rtas_int_on(struct kvm_vcpu *vcpu, struct rtas_args *args)
  87{
  88        u32 irq;
  89        int rc;
  90
  91        if (be32_to_cpu(args->nargs) != 1 || be32_to_cpu(args->nret) != 1) {
  92                rc = -3;
  93                goto out;
  94        }
  95
  96        irq = be32_to_cpu(args->args[0]);
  97
  98        rc = kvmppc_xics_int_on(vcpu->kvm, irq);
  99        if (rc)
 100                rc = -3;
 101out:
 102        args->rets[0] = cpu_to_be32(rc);
 103}
 104#endif /* CONFIG_KVM_XICS */
 105
 106struct rtas_handler {
 107        void (*handler)(struct kvm_vcpu *vcpu, struct rtas_args *args);
 108        char *name;
 109};
 110
 111static struct rtas_handler rtas_handlers[] = {
 112#ifdef CONFIG_KVM_XICS
 113        { .name = "ibm,set-xive", .handler = kvm_rtas_set_xive },
 114        { .name = "ibm,get-xive", .handler = kvm_rtas_get_xive },
 115        { .name = "ibm,int-off",  .handler = kvm_rtas_int_off },
 116        { .name = "ibm,int-on",   .handler = kvm_rtas_int_on },
 117#endif
 118};
 119
 120struct rtas_token_definition {
 121        struct list_head list;
 122        struct rtas_handler *handler;
 123        u64 token;
 124};
 125
 126static int rtas_name_matches(char *s1, char *s2)
 127{
 128        struct kvm_rtas_token_args args;
 129        return !strncmp(s1, s2, sizeof(args.name));
 130}
 131
 132static int rtas_token_undefine(struct kvm *kvm, char *name)
 133{
 134        struct rtas_token_definition *d, *tmp;
 135
 136        lockdep_assert_held(&kvm->lock);
 137
 138        list_for_each_entry_safe(d, tmp, &kvm->arch.rtas_tokens, list) {
 139                if (rtas_name_matches(d->handler->name, name)) {
 140                        list_del(&d->list);
 141                        kfree(d);
 142                        return 0;
 143                }
 144        }
 145
 146        /* It's not an error to undefine an undefined token */
 147        return 0;
 148}
 149
 150static int rtas_token_define(struct kvm *kvm, char *name, u64 token)
 151{
 152        struct rtas_token_definition *d;
 153        struct rtas_handler *h = NULL;
 154        bool found;
 155        int i;
 156
 157        lockdep_assert_held(&kvm->lock);
 158
 159        list_for_each_entry(d, &kvm->arch.rtas_tokens, list) {
 160                if (d->token == token)
 161                        return -EEXIST;
 162        }
 163
 164        found = false;
 165        for (i = 0; i < ARRAY_SIZE(rtas_handlers); i++) {
 166                h = &rtas_handlers[i];
 167                if (rtas_name_matches(h->name, name)) {
 168                        found = true;
 169                        break;
 170                }
 171        }
 172
 173        if (!found)
 174                return -ENOENT;
 175
 176        d = kzalloc(sizeof(*d), GFP_KERNEL);
 177        if (!d)
 178                return -ENOMEM;
 179
 180        d->handler = h;
 181        d->token = token;
 182
 183        list_add_tail(&d->list, &kvm->arch.rtas_tokens);
 184
 185        return 0;
 186}
 187
 188int kvm_vm_ioctl_rtas_define_token(struct kvm *kvm, void __user *argp)
 189{
 190        struct kvm_rtas_token_args args;
 191        int rc;
 192
 193        if (copy_from_user(&args, argp, sizeof(args)))
 194                return -EFAULT;
 195
 196        mutex_lock(&kvm->lock);
 197
 198        if (args.token)
 199                rc = rtas_token_define(kvm, args.name, args.token);
 200        else
 201                rc = rtas_token_undefine(kvm, args.name);
 202
 203        mutex_unlock(&kvm->lock);
 204
 205        return rc;
 206}
 207
 208int kvmppc_rtas_hcall(struct kvm_vcpu *vcpu)
 209{
 210        struct rtas_token_definition *d;
 211        struct rtas_args args;
 212        rtas_arg_t *orig_rets;
 213        gpa_t args_phys;
 214        int rc;
 215
 216        /*
 217         * r4 contains the guest physical address of the RTAS args
 218         * Mask off the top 4 bits since this is a guest real address
 219         */
 220        args_phys = kvmppc_get_gpr(vcpu, 4) & KVM_PAM;
 221
 222        rc = kvm_read_guest(vcpu->kvm, args_phys, &args, sizeof(args));
 223        if (rc)
 224                goto fail;
 225
 226        /*
 227         * args->rets is a pointer into args->args. Now that we've
 228         * copied args we need to fix it up to point into our copy,
 229         * not the guest args. We also need to save the original
 230         * value so we can restore it on the way out.
 231         */
 232        orig_rets = args.rets;
 233        args.rets = &args.args[be32_to_cpu(args.nargs)];
 234
 235        mutex_lock(&vcpu->kvm->lock);
 236
 237        rc = -ENOENT;
 238        list_for_each_entry(d, &vcpu->kvm->arch.rtas_tokens, list) {
 239                if (d->token == be32_to_cpu(args.token)) {
 240                        d->handler->handler(vcpu, &args);
 241                        rc = 0;
 242                        break;
 243                }
 244        }
 245
 246        mutex_unlock(&vcpu->kvm->lock);
 247
 248        if (rc == 0) {
 249                args.rets = orig_rets;
 250                rc = kvm_write_guest(vcpu->kvm, args_phys, &args, sizeof(args));
 251                if (rc)
 252                        goto fail;
 253        }
 254
 255        return rc;
 256
 257fail:
 258        /*
 259         * We only get here if the guest has called RTAS with a bogus
 260         * args pointer. That means we can't get to the args, and so we
 261         * can't fail the RTAS call. So fail right out to userspace,
 262         * which should kill the guest.
 263         */
 264        return rc;
 265}
 266EXPORT_SYMBOL_GPL(kvmppc_rtas_hcall);
 267
 268void kvmppc_rtas_tokens_free(struct kvm *kvm)
 269{
 270        struct rtas_token_definition *d, *tmp;
 271
 272        lockdep_assert_held(&kvm->lock);
 273
 274        list_for_each_entry_safe(d, tmp, &kvm->arch.rtas_tokens, list) {
 275                list_del(&d->list);
 276                kfree(d);
 277        }
 278}
 279