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