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
23412341 KVM_CREATE_IRQCHIP, but before calling KVM_RUN on any of the VCPUs. Calling
23422342 this ioctl twice for any of the base addresses will return -EEXIST.
23432343
2344+4.82 KVM_PPC_RTAS_DEFINE_TOKEN
2345+
2346+Capability: KVM_CAP_PPC_RTAS
2347+Architectures: ppc
2348+Type: vm ioctl
2349+Parameters: struct kvm_rtas_token_args
2350+Returns: 0 on success, -1 on error
2351+
2352+Defines a token value for a RTAS (Run Time Abstraction Services)
2353+service in order to allow it to be handled in the kernel. The
2354+argument struct gives the name of the service, which must be the name
2355+of a service that has a kernel-side implementation. If the token
2356+value is non-zero, it will be associated with that service, and
2357+subsequent RTAS calls by the guest specifying that token will be
2358+handled by the kernel. If the token value is 0, then any token
2359+associated with the service will be forgotten, and subsequent RTAS
2360+calls by the guest for that service will be passed to userspace to be
2361+handled.
2362+
23442363
23452364 5. The kvm_run structure
23462365 ------------------------
arch/powerpc/include/asm/hvcall.h+3−0
@@ -270,6 +270,9 @@ · 269 unmodified lines
270270 #define H_SET_MODE 0x31C
271271 #define MAX_HCALL_OPCODE H_SET_MODE
272272
273+/* Platform specific hcalls, used by KVM */
274+#define H_RTAS 0xf000
275+
273276 #ifndef __ASSEMBLY__
274277
275278 /**
arch/powerpc/include/asm/kvm_host.h+1−0
@@ -259,6 +259,7 @@ struct kvm_arch { · 258 unmodified lines
259259 #endif /* CONFIG_KVM_BOOK3S_64_HV */
260260 #ifdef CONFIG_PPC_BOOK3S_64
261261 struct list_head spapr_tce_tables;
262+ struct list_head rtas_tokens;
262263 #endif
263264 #ifdef CONFIG_KVM_MPIC
264265 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
166166
167167 int kvm_vcpu_ioctl_interrupt(struct kvm_vcpu *vcpu, struct kvm_interrupt *irq);
168168
169+extern int kvm_vm_ioctl_rtas_define_token(struct kvm *kvm, void __user *argp);
170+extern int kvmppc_rtas_hcall(struct kvm_vcpu *vcpu);
171+extern void kvmppc_rtas_tokens_free(struct kvm *kvm);
172+
169173 /*
170174 * Cuts out inst bits with ordering according to spec.
171175 * 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
324324 __u64 rma_size;
325325 };
326326
327+/* for KVM_CAP_PPC_RTAS */
328+struct kvm_rtas_token_args {
329+ char name[120];
330+ __u64 token; /* Use a token of 0 to undefine a mapping */
331+};
332+
327333 struct kvm_book3e_206_tlb_entry {
328334 __u32 mas8;
329335 __u32 mas1;
arch/powerpc/kvm/Makefile+1−0
@@ -86,6 +86,7 @@ kvm-book3s_64-module-objs := \ · 85 unmodified lines
8686 emulate.o \
8787 book3s.o \
8888 book3s_64_vio.o \
89+ book3s_rtas.o \
8990 $(kvm-book3s_64-objs-y)
9091
9192 kvm-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
483483 unsigned long req = kvmppc_get_gpr(vcpu, 3);
484484 unsigned long target, ret = H_SUCCESS;
485485 struct kvm_vcpu *tvcpu;
486− int idx;
486+ int idx, rc;
487487
488488 switch (req) {
489489 case H_ENTER:
@@ -519,6 +519,19 @@ int kvmppc_pseries_do_hcall(struct kvm_vcpu *vcpu) · 29 unmodified lines
519519 kvmppc_get_gpr(vcpu, 5),
520520 kvmppc_get_gpr(vcpu, 6));
521521 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;
522535 default:
523536 return RESUME_HOST;
524537 }
@@ -1829,6 +1842,7 @@ int kvmppc_core_init_vm(struct kvm *kvm) · 1304 unmodified lines
18291842 cpumask_setall(&kvm->arch.need_tlb_flush);
18301843
18311844 INIT_LIST_HEAD(&kvm->arch.spapr_tce_tables);
1845+ INIT_LIST_HEAD(&kvm->arch.rtas_tokens);
18321846
18331847 kvm->arch.rma = NULL;
18341848
@@ -1874,6 +1888,8 @@ void kvmppc_core_destroy_vm(struct kvm *kvm) · 39 unmodified lines
18741888 kvm->arch.rma = NULL;
18751889 }
18761890
1891+ kvmppc_rtas_tokens_free(kvm);
1892+
18771893 kvmppc_free_hpt(kvm);
18781894 WARN_ON(!list_empty(&kvm->arch.spapr_tce_tables));
18791895 }
arch/powerpc/kvm/book3s_pr.c+1−0
@@ -1296,6 +1296,7 @@ int kvmppc_core_init_vm(struct kvm *kvm) · 1295 unmodified lines
12961296 {
12971297 #ifdef CONFIG_PPC64
12981298 INIT_LIST_HEAD(&kvm->arch.spapr_tce_tables);
1299+ INIT_LIST_HEAD(&kvm->arch.rtas_tokens);
12991300 #endif
13001301
13011302 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
246246 clear_bit(KVM_REQ_UNHALT, &vcpu->requests);
247247 vcpu->stat.halt_wakeup++;
248248 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;
249256 }
250257
251258 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+
21+struct rtas_handler {
22+ void (*handler)(struct kvm_vcpu *vcpu, struct rtas_args *args);
23+ char *name;
24+};
25+
26+static struct rtas_handler rtas_handlers[] = { };
27+
28+struct rtas_token_definition {
29+ struct list_head list;
30+ struct rtas_handler *handler;
31+ u64 token;
32+};
33+
34+static 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+
40+static 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+
58+static 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+
96+int 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+
116+int 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+
162+fail:
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+
172+void 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
341341 #ifdef CONFIG_PPC_BOOK3S_64
342342 case KVM_CAP_SPAPR_TCE:
343343 case KVM_CAP_PPC_ALLOC_HTAB:
344+ case KVM_CAP_PPC_RTAS:
344345 r = 1;
345346 break;
346347 #endif /* CONFIG_PPC_BOOK3S_64 */
@@ -986,6 +987,7 @@ long kvm_arch_vm_ioctl(struct file *filp, · 639 unmodified lines
986987 #ifdef CONFIG_KVM_BOOK3S_64_HV
987988 case KVM_ALLOCATE_RMA: {
988989 struct kvm_allocate_rma rma;
990+ struct kvm *kvm = filp->private_data;
989991
990992 r = kvm_vm_ioctl_allocate_rma(kvm, &rma);
991993 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
10301032 r = -EFAULT;
10311033 break;
10321034 }
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+ }
10331041 #endif /* CONFIG_PPC_BOOK3S_64 */
10341042 default:
10351043 r = -ENOTTY;
include/uapi/linux/kvm.h+3−0
@@ -668,6 +668,7 @@ struct kvm_ppc_smmu_info { · 667 unmodified lines
668668 #define KVM_CAP_ARM_SET_DEVICE_ADDR 88
669669 #define KVM_CAP_DEVICE_CTRL 89
670670 #define KVM_CAP_IRQ_MPIC 90
671+#define KVM_CAP_PPC_RTAS 91
671672
672673 #ifdef KVM_CAP_IRQ_ROUTING
673674
@@ -928,6 +929,8 @@ struct kvm_s390_ucas_mapping { · 254 unmodified lines
928929 #define KVM_PPC_GET_HTAB_FD _IOW(KVMIO, 0xaa, struct kvm_get_htab_fd)
929930 /* Available with KVM_CAP_ARM_SET_DEVICE_ADDR */
930931 #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)
931934
932935 /* ioctl for vm fd */
933936 #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