History

KVM: PPC: Book3S: Add infrastructure to implement kernel-side RTAS calls

For pseries machine emulation, in order to move the interrupt controller code to the kernel, we need to intercept some RTAS calls in the kernel itself. This adds an infrastructure to allow in-kernel handlers to be registered for RTAS services by name. A new ioctl, KVM_PPC_RTAS_DEFINE_TOKEN, then allows userspace to associate token values with those service names. Then, when the guest requests an RTAS service with one of those token values, it will be handled by the relevant in-kernel handler rather than being passed up to userspace as at present.

Michael Ellerman committed 13 years ago

Commit 8e591cb1 parent 911949112 files · +252 −1Browse files

Unified · Split

12 files
  1. Documentation/virtual/kvm/api.txt +19 −0
  2. arch/powerpc/include/asm/hvcall.h +3 −0
  3. arch/powerpc/include/asm/kvm_host.h +1 −0
  4. arch/powerpc/include/asm/kvm_ppc.h +4 −0
  5. arch/powerpc/include/uapi/asm/kvm.h +6 −0
  6. arch/powerpc/kvm/Makefile +1 −0
  7. arch/powerpc/kvm/book3s_hv.c +17 −1
  8. arch/powerpc/kvm/book3s_pr.c +1 −0
  9. arch/powerpc/kvm/book3s_pr_papr.c +7 −0
  10. arch/powerpc/kvm/book3s_rtas.c +182 −0
  11. arch/powerpc/kvm/powerpc.c +8 −0
  12. include/uapi/linux/kvm.h +3 −0
Documentation/virtual/kvm/api.txt+19−0
@@ -2341,6 +2341,25 @@ and distributor interface, the ioctl must be called after calling · 2340 unmodified lines
2341KVM_CREATE_IRQCHIP, but before calling KVM_RUN on any of the VCPUs. Calling2341KVM_CREATE_IRQCHIP, but before calling KVM_RUN on any of the VCPUs. Calling
2342this ioctl twice for any of the base addresses will return -EEXIST.2342this ioctl twice for any of the base addresses will return -EEXIST.
2343 2343
23444.82 KVM_PPC_RTAS_DEFINE_TOKEN
2345
2346Capability: KVM_CAP_PPC_RTAS
2347Architectures: ppc
2348Type: vm ioctl
2349Parameters: struct kvm_rtas_token_args
2350Returns: 0 on success, -1 on error
2351
2352Defines a token value for a RTAS (Run Time Abstraction Services)
2353service in order to allow it to be handled in the kernel. The
2354argument struct gives the name of the service, which must be the name
2355of a service that has a kernel-side implementation. If the token
2356value is non-zero, it will be associated with that service, and
2357subsequent RTAS calls by the guest specifying that token will be
2358handled by the kernel. If the token value is 0, then any token
2359associated with the service will be forgotten, and subsequent RTAS
2360calls by the guest for that service will be passed to userspace to be
2361handled.
2362
2344 2363
23455. The kvm_run structure23645. The kvm_run structure
2346------------------------2365------------------------
arch/powerpc/include/asm/hvcall.h+3−0
@@ -270,6 +270,9 @@ · 269 unmodified lines
270#define H_SET_MODE 0x31C270#define H_SET_MODE 0x31C
271#define MAX_HCALL_OPCODE H_SET_MODE271#define MAX_HCALL_OPCODE H_SET_MODE
272 272
273/* Platform specific hcalls, used by KVM */
274#define H_RTAS 0xf000
275
273#ifndef __ASSEMBLY__276#ifndef __ASSEMBLY__
274 277
275/**278/**
arch/powerpc/include/asm/kvm_host.h+1−0
@@ -259,6 +259,7 @@ struct kvm_arch { · 258 unmodified lines
259#endif /* CONFIG_KVM_BOOK3S_64_HV */259#endif /* CONFIG_KVM_BOOK3S_64_HV */
260#ifdef CONFIG_PPC_BOOK3S_64260#ifdef CONFIG_PPC_BOOK3S_64
261 struct list_head spapr_tce_tables;261 struct list_head spapr_tce_tables;
262 struct list_head rtas_tokens;
262#endif263#endif
263#ifdef CONFIG_KVM_MPIC264#ifdef CONFIG_KVM_MPIC
264 struct openpic *mpic;265 struct openpic *mpic;
arch/powerpc/include/asm/kvm_ppc.h+4−0
@@ -166,6 +166,10 @@ extern int kvm_vm_ioctl_get_htab_fd(struct kvm *kvm, struct kvm_get_htab_fd *); · 165 unmodified lines
166 166
167int kvm_vcpu_ioctl_interrupt(struct kvm_vcpu *vcpu, struct kvm_interrupt *irq);167int kvm_vcpu_ioctl_interrupt(struct kvm_vcpu *vcpu, struct kvm_interrupt *irq);
168 168
169extern int kvm_vm_ioctl_rtas_define_token(struct kvm *kvm, void __user *argp);
170extern int kvmppc_rtas_hcall(struct kvm_vcpu *vcpu);
171extern void kvmppc_rtas_tokens_free(struct kvm *kvm);
172
169/*173/*
170 * Cuts out inst bits with ordering according to spec.174 * Cuts out inst bits with ordering according to spec.
171 * That means the leftmost bit is zero. All given bits are included.175 * That means the leftmost bit is zero. All given bits are included.
arch/powerpc/include/uapi/asm/kvm.h+6−0
@@ -324,6 +324,12 @@ struct kvm_allocate_rma { · 323 unmodified lines
324 __u64 rma_size;324 __u64 rma_size;
325};325};
326 326
327/* for KVM_CAP_PPC_RTAS */
328struct kvm_rtas_token_args {
329 char name[120];
330 __u64 token; /* Use a token of 0 to undefine a mapping */
331};
332
327struct kvm_book3e_206_tlb_entry {333struct kvm_book3e_206_tlb_entry {
328 __u32 mas8;334 __u32 mas8;
329 __u32 mas1;335 __u32 mas1;
arch/powerpc/kvm/Makefile+1−0
@@ -86,6 +86,7 @@ kvm-book3s_64-module-objs := \ · 85 unmodified lines
86 emulate.o \86 emulate.o \
87 book3s.o \87 book3s.o \
88 book3s_64_vio.o \88 book3s_64_vio.o \
89 book3s_rtas.o \
89 $(kvm-book3s_64-objs-y)90 $(kvm-book3s_64-objs-y)
90 91
91kvm-objs-$(CONFIG_KVM_BOOK3S_64) := $(kvm-book3s_64-module-objs)92kvm-objs-$(CONFIG_KVM_BOOK3S_64) := $(kvm-book3s_64-module-objs)
arch/powerpc/kvm/book3s_hv.c+17−1
@@ -483,7 +483,7 @@ int kvmppc_pseries_do_hcall(struct kvm_vcpu *vcpu) · 482 unmodified lines
483 unsigned long req = kvmppc_get_gpr(vcpu, 3);483 unsigned long req = kvmppc_get_gpr(vcpu, 3);
484 unsigned long target, ret = H_SUCCESS;484 unsigned long target, ret = H_SUCCESS;
485 struct kvm_vcpu *tvcpu;485 struct kvm_vcpu *tvcpu;
486 int idx;486 int idx, rc;
487 487
488 switch (req) {488 switch (req) {
489 case H_ENTER:489 case H_ENTER:
@@ -519,6 +519,19 @@ int kvmppc_pseries_do_hcall(struct kvm_vcpu *vcpu) · 29 unmodified lines
519 kvmppc_get_gpr(vcpu, 5),519 kvmppc_get_gpr(vcpu, 5),
520 kvmppc_get_gpr(vcpu, 6));520 kvmppc_get_gpr(vcpu, 6));
521 break;521 break;
522 case H_RTAS:
523 if (list_empty(&vcpu->kvm->arch.rtas_tokens))
524 return RESUME_HOST;
525
526 rc = kvmppc_rtas_hcall(vcpu);
527
528 if (rc == -ENOENT)
529 return RESUME_HOST;
530 else if (rc == 0)
531 break;
532
533 /* Send the error out to userspace via KVM_RUN */
534 return rc;
522 default:535 default:
523 return RESUME_HOST;536 return RESUME_HOST;
524 }537 }
@@ -1829,6 +1842,7 @@ int kvmppc_core_init_vm(struct kvm *kvm) · 1304 unmodified lines
1829 cpumask_setall(&kvm->arch.need_tlb_flush);1842 cpumask_setall(&kvm->arch.need_tlb_flush);
1830 1843
1831 INIT_LIST_HEAD(&kvm->arch.spapr_tce_tables);1844 INIT_LIST_HEAD(&kvm->arch.spapr_tce_tables);
1845 INIT_LIST_HEAD(&kvm->arch.rtas_tokens);
1832 1846
1833 kvm->arch.rma = NULL;1847 kvm->arch.rma = NULL;
1834 1848
@@ -1874,6 +1888,8 @@ void kvmppc_core_destroy_vm(struct kvm *kvm) · 39 unmodified lines
1874 kvm->arch.rma = NULL;1888 kvm->arch.rma = NULL;
1875 }1889 }
1876 1890
1891 kvmppc_rtas_tokens_free(kvm);
1892
1877 kvmppc_free_hpt(kvm);1893 kvmppc_free_hpt(kvm);
1878 WARN_ON(!list_empty(&kvm->arch.spapr_tce_tables));1894 WARN_ON(!list_empty(&kvm->arch.spapr_tce_tables));
1879}1895}
arch/powerpc/kvm/book3s_pr.c+1−0
@@ -1296,6 +1296,7 @@ int kvmppc_core_init_vm(struct kvm *kvm) · 1295 unmodified lines
1296{1296{
1297#ifdef CONFIG_PPC641297#ifdef CONFIG_PPC64
1298 INIT_LIST_HEAD(&kvm->arch.spapr_tce_tables);1298 INIT_LIST_HEAD(&kvm->arch.spapr_tce_tables);
1299 INIT_LIST_HEAD(&kvm->arch.rtas_tokens);
1299#endif1300#endif
1300 1301
1301 if (firmware_has_feature(FW_FEATURE_SET_MODE)) {1302 if (firmware_has_feature(FW_FEATURE_SET_MODE)) {
arch/powerpc/kvm/book3s_pr_papr.c+7−0
@@ -246,6 +246,13 @@ int kvmppc_h_pr(struct kvm_vcpu *vcpu, unsigned long cmd) · 245 unmodified lines
246 clear_bit(KVM_REQ_UNHALT, &vcpu->requests);246 clear_bit(KVM_REQ_UNHALT, &vcpu->requests);
247 vcpu->stat.halt_wakeup++;247 vcpu->stat.halt_wakeup++;
248 return EMULATE_DONE;248 return EMULATE_DONE;
249 case H_RTAS:
250 if (list_empty(&vcpu->kvm->arch.rtas_tokens))
251 return RESUME_HOST;
252 if (kvmppc_rtas_hcall(vcpu))
253 break;
254 kvmppc_set_gpr(vcpu, 3, 0);
255 return EMULATE_DONE;
249 }256 }
250 257
251 return EMULATE_FAIL;258 return EMULATE_FAIL;
arch/powerpc/kvm/book3s_rtas.c+182−0
@@ -0,0 +1,182 @@
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
21struct rtas_handler {
22 void (*handler)(struct kvm_vcpu *vcpu, struct rtas_args *args);
23 char *name;
24};
25
26static struct rtas_handler rtas_handlers[] = { };
27
28struct rtas_token_definition {
29 struct list_head list;
30 struct rtas_handler *handler;
31 u64 token;
32};
33
34static int rtas_name_matches(char *s1, char *s2)
35{
36 struct kvm_rtas_token_args args;
37 return !strncmp(s1, s2, sizeof(args.name));
38}
39
40static int rtas_token_undefine(struct kvm *kvm, char *name)
41{
42 struct rtas_token_definition *d, *tmp;
43
44 lockdep_assert_held(&kvm->lock);
45
46 list_for_each_entry_safe(d, tmp, &kvm->arch.rtas_tokens, list) {
47 if (rtas_name_matches(d->handler->name, name)) {
48 list_del(&d->list);
49 kfree(d);
50 return 0;
51 }
52 }
53
54 /* It's not an error to undefine an undefined token */
55 return 0;
56}
57
58static int rtas_token_define(struct kvm *kvm, char *name, u64 token)
59{
60 struct rtas_token_definition *d;
61 struct rtas_handler *h = NULL;
62 bool found;
63 int i;
64
65 lockdep_assert_held(&kvm->lock);
66
67 list_for_each_entry(d, &kvm->arch.rtas_tokens, list) {
68 if (d->token == token)
69 return -EEXIST;
70 }
71
72 found = false;
73 for (i = 0; i < ARRAY_SIZE(rtas_handlers); i++) {
74 h = &rtas_handlers[i];
75 if (rtas_name_matches(h->name, name)) {
76 found = true;
77 break;
78 }
79 }
80
81 if (!found)
82 return -ENOENT;
83
84 d = kzalloc(sizeof(*d), GFP_KERNEL);
85 if (!d)
86 return -ENOMEM;
87
88 d->handler = h;
89 d->token = token;
90
91 list_add_tail(&d->list, &kvm->arch.rtas_tokens);
92
93 return 0;
94}
95
96int kvm_vm_ioctl_rtas_define_token(struct kvm *kvm, void __user *argp)
97{
98 struct kvm_rtas_token_args args;
99 int rc;
100
101 if (copy_from_user(&args, argp, sizeof(args)))
102 return -EFAULT;
103
104 mutex_lock(&kvm->lock);
105
106 if (args.token)
107 rc = rtas_token_define(kvm, args.name, args.token);
108 else
109 rc = rtas_token_undefine(kvm, args.name);
110
111 mutex_unlock(&kvm->lock);
112
113 return rc;
114}
115
116int kvmppc_rtas_hcall(struct kvm_vcpu *vcpu)
117{
118 struct rtas_token_definition *d;
119 struct rtas_args args;
120 rtas_arg_t *orig_rets;
121 gpa_t args_phys;
122 int rc;
123
124 /* r4 contains the guest physical address of the RTAS args */
125 args_phys = kvmppc_get_gpr(vcpu, 4);
126
127 rc = kvm_read_guest(vcpu->kvm, args_phys, &args, sizeof(args));
128 if (rc)
129 goto fail;
130
131 /*
132 * args->rets is a pointer into args->args. Now that we've
133 * copied args we need to fix it up to point into our copy,
134 * not the guest args. We also need to save the original
135 * value so we can restore it on the way out.
136 */
137 orig_rets = args.rets;
138 args.rets = &args.args[args.nargs];
139
140 mutex_lock(&vcpu->kvm->lock);
141
142 rc = -ENOENT;
143 list_for_each_entry(d, &vcpu->kvm->arch.rtas_tokens, list) {
144 if (d->token == args.token) {
145 d->handler->handler(vcpu, &args);
146 rc = 0;
147 break;
148 }
149 }
150
151 mutex_unlock(&vcpu->kvm->lock);
152
153 if (rc == 0) {
154 args.rets = orig_rets;
155 rc = kvm_write_guest(vcpu->kvm, args_phys, &args, sizeof(args));
156 if (rc)
157 goto fail;
158 }
159
160 return rc;
161
162fail:
163 /*
164 * We only get here if the guest has called RTAS with a bogus
165 * args pointer. That means we can't get to the args, and so we
166 * can't fail the RTAS call. So fail right out to userspace,
167 * which should kill the guest.
168 */
169 return rc;
170}
171
172void kvmppc_rtas_tokens_free(struct kvm *kvm)
173{
174 struct rtas_token_definition *d, *tmp;
175
176 lockdep_assert_held(&kvm->lock);
177
178 list_for_each_entry_safe(d, tmp, &kvm->arch.rtas_tokens, list) {
179 list_del(&d->list);
180 kfree(d);
181 }
182}
arch/powerpc/kvm/powerpc.c+8−0
@@ -341,6 +341,7 @@ int kvm_dev_ioctl_check_extension(long ext) · 340 unmodified lines
341#ifdef CONFIG_PPC_BOOK3S_64341#ifdef CONFIG_PPC_BOOK3S_64
342 case KVM_CAP_SPAPR_TCE:342 case KVM_CAP_SPAPR_TCE:
343 case KVM_CAP_PPC_ALLOC_HTAB:343 case KVM_CAP_PPC_ALLOC_HTAB:
344 case KVM_CAP_PPC_RTAS:
344 r = 1;345 r = 1;
345 break;346 break;
346#endif /* CONFIG_PPC_BOOK3S_64 */347#endif /* CONFIG_PPC_BOOK3S_64 */
@@ -986,6 +987,7 @@ long kvm_arch_vm_ioctl(struct file *filp, · 639 unmodified lines
986#ifdef CONFIG_KVM_BOOK3S_64_HV987#ifdef CONFIG_KVM_BOOK3S_64_HV
987 case KVM_ALLOCATE_RMA: {988 case KVM_ALLOCATE_RMA: {
988 struct kvm_allocate_rma rma;989 struct kvm_allocate_rma rma;
990 struct kvm *kvm = filp->private_data;
989 991
990 r = kvm_vm_ioctl_allocate_rma(kvm, &rma);992 r = kvm_vm_ioctl_allocate_rma(kvm, &rma);
991 if (r >= 0 && copy_to_user(argp, &rma, sizeof(rma)))993 if (r >= 0 && copy_to_user(argp, &rma, sizeof(rma)))
@@ -1030,6 +1032,12 @@ long kvm_arch_vm_ioctl(struct file *filp, · 38 unmodified lines
1030 r = -EFAULT;1032 r = -EFAULT;
1031 break;1033 break;
1032 }1034 }
1035 case KVM_PPC_RTAS_DEFINE_TOKEN: {
1036 struct kvm *kvm = filp->private_data;
1037
1038 r = kvm_vm_ioctl_rtas_define_token(kvm, argp);
1039 break;
1040 }
1033#endif /* CONFIG_PPC_BOOK3S_64 */1041#endif /* CONFIG_PPC_BOOK3S_64 */
1034 default:1042 default:
1035 r = -ENOTTY;1043 r = -ENOTTY;
include/uapi/linux/kvm.h+3−0
@@ -668,6 +668,7 @@ struct kvm_ppc_smmu_info { · 667 unmodified lines
668#define KVM_CAP_ARM_SET_DEVICE_ADDR 88668#define KVM_CAP_ARM_SET_DEVICE_ADDR 88
669#define KVM_CAP_DEVICE_CTRL 89669#define KVM_CAP_DEVICE_CTRL 89
670#define KVM_CAP_IRQ_MPIC 90670#define KVM_CAP_IRQ_MPIC 90
671#define KVM_CAP_PPC_RTAS 91
671 672
672#ifdef KVM_CAP_IRQ_ROUTING673#ifdef KVM_CAP_IRQ_ROUTING
673 674
@@ -928,6 +929,8 @@ struct kvm_s390_ucas_mapping { · 254 unmodified lines
928#define KVM_PPC_GET_HTAB_FD _IOW(KVMIO, 0xaa, struct kvm_get_htab_fd)929#define KVM_PPC_GET_HTAB_FD _IOW(KVMIO, 0xaa, struct kvm_get_htab_fd)
929/* Available with KVM_CAP_ARM_SET_DEVICE_ADDR */930/* Available with KVM_CAP_ARM_SET_DEVICE_ADDR */
930#define KVM_ARM_SET_DEVICE_ADDR _IOW(KVMIO, 0xab, struct kvm_arm_device_addr)931#define KVM_ARM_SET_DEVICE_ADDR _IOW(KVMIO, 0xab, struct kvm_arm_device_addr)
932/* Available with KVM_CAP_PPC_RTAS */
933#define KVM_PPC_RTAS_DEFINE_TOKEN _IOW(KVMIO, 0xac, struct kvm_rtas_token_args)
931 934
932/* ioctl for vm fd */935/* ioctl for vm fd */
933#define KVM_CREATE_DEVICE _IOWR(KVMIO, 0xe0, struct kvm_create_device)936#define KVM_CREATE_DEVICE _IOWR(KVMIO, 0xe0, struct kvm_create_device)

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t