diff options
| author | Michael Ellerman <michael@ellerman.id.au> | 2013-04-17 16:30:00 -0400 |
|---|---|---|
| committer | Alexander Graf <agraf@suse.de> | 2013-04-26 14:27:29 -0400 |
| commit | 8e591cb7204739efa8e15967ea334eb367039dde (patch) | |
| tree | 3fa76d3875c8133eeafc2e36372aaf83232fc54f | |
| parent | 91194919a6b07d70081fe185a79b129efee84fff (diff) | |
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.
Signed-off-by: Michael Ellerman <michael@ellerman.id.au>
Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Signed-off-by: Paul Mackerras <paulus@samba.org>
[agraf: fix warning]
Signed-off-by: Alexander Graf <agraf@suse.de>
| -rw-r--r-- | Documentation/virtual/kvm/api.txt | 19 | ||||
| -rw-r--r-- | arch/powerpc/include/asm/hvcall.h | 3 | ||||
| -rw-r--r-- | arch/powerpc/include/asm/kvm_host.h | 1 | ||||
| -rw-r--r-- | arch/powerpc/include/asm/kvm_ppc.h | 4 | ||||
| -rw-r--r-- | arch/powerpc/include/uapi/asm/kvm.h | 6 | ||||
| -rw-r--r-- | arch/powerpc/kvm/Makefile | 1 | ||||
| -rw-r--r-- | arch/powerpc/kvm/book3s_hv.c | 18 | ||||
| -rw-r--r-- | arch/powerpc/kvm/book3s_pr.c | 1 | ||||
| -rw-r--r-- | arch/powerpc/kvm/book3s_pr_papr.c | 7 | ||||
| -rw-r--r-- | arch/powerpc/kvm/book3s_rtas.c | 182 | ||||
| -rw-r--r-- | arch/powerpc/kvm/powerpc.c | 8 | ||||
| -rw-r--r-- | include/uapi/linux/kvm.h | 3 |
12 files changed, 252 insertions, 1 deletions
diff --git a/Documentation/virtual/kvm/api.txt b/Documentation/virtual/kvm/api.txt index 149558b1e81e..fb308be8521b 100644 --- a/Documentation/virtual/kvm/api.txt +++ b/Documentation/virtual/kvm/api.txt | |||
| @@ -2341,6 +2341,25 @@ and distributor interface, the ioctl must be called after calling | |||
| 2341 | KVM_CREATE_IRQCHIP, but before calling KVM_RUN on any of the VCPUs. Calling | 2341 | KVM_CREATE_IRQCHIP, but before calling KVM_RUN on any of the VCPUs. Calling |
| 2342 | this ioctl twice for any of the base addresses will return -EEXIST. | 2342 | this ioctl twice for any of the base addresses will return -EEXIST. |
| 2343 | 2343 | ||
| 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 | |||
| 2344 | 2363 | ||
| 2345 | 5. The kvm_run structure | 2364 | 5. The kvm_run structure |
| 2346 | ------------------------ | 2365 | ------------------------ |
diff --git a/arch/powerpc/include/asm/hvcall.h b/arch/powerpc/include/asm/hvcall.h index 4bc2c3dad6ad..cf4df8e2139a 100644 --- a/arch/powerpc/include/asm/hvcall.h +++ b/arch/powerpc/include/asm/hvcall.h | |||
| @@ -270,6 +270,9 @@ | |||
| 270 | #define H_SET_MODE 0x31C | 270 | #define H_SET_MODE 0x31C |
| 271 | #define MAX_HCALL_OPCODE H_SET_MODE | 271 | #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 | /** |
diff --git a/arch/powerpc/include/asm/kvm_host.h b/arch/powerpc/include/asm/kvm_host.h index 13740a645a6d..311f7e6f09e9 100644 --- a/arch/powerpc/include/asm/kvm_host.h +++ b/arch/powerpc/include/asm/kvm_host.h | |||
| @@ -259,6 +259,7 @@ struct kvm_arch { | |||
| 259 | #endif /* CONFIG_KVM_BOOK3S_64_HV */ | 259 | #endif /* CONFIG_KVM_BOOK3S_64_HV */ |
| 260 | #ifdef CONFIG_PPC_BOOK3S_64 | 260 | #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 | #endif | 263 | #endif |
| 263 | #ifdef CONFIG_KVM_MPIC | 264 | #ifdef CONFIG_KVM_MPIC |
| 264 | struct openpic *mpic; | 265 | struct openpic *mpic; |
diff --git a/arch/powerpc/include/asm/kvm_ppc.h b/arch/powerpc/include/asm/kvm_ppc.h index df9c80b37905..8a30eb7f2bec 100644 --- a/arch/powerpc/include/asm/kvm_ppc.h +++ b/arch/powerpc/include/asm/kvm_ppc.h | |||
| @@ -166,6 +166,10 @@ extern int kvm_vm_ioctl_get_htab_fd(struct kvm *kvm, struct kvm_get_htab_fd *); | |||
| 166 | 166 | ||
| 167 | int kvm_vcpu_ioctl_interrupt(struct kvm_vcpu *vcpu, struct kvm_interrupt *irq); | 167 | int kvm_vcpu_ioctl_interrupt(struct kvm_vcpu *vcpu, struct kvm_interrupt *irq); |
| 168 | 168 | ||
| 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 | |||
| 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. |
diff --git a/arch/powerpc/include/uapi/asm/kvm.h b/arch/powerpc/include/uapi/asm/kvm.h index 03c7819a44a3..eb9e25c194ad 100644 --- a/arch/powerpc/include/uapi/asm/kvm.h +++ b/arch/powerpc/include/uapi/asm/kvm.h | |||
| @@ -324,6 +324,12 @@ struct kvm_allocate_rma { | |||
| 324 | __u64 rma_size; | 324 | __u64 rma_size; |
| 325 | }; | 325 | }; |
| 326 | 326 | ||
| 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 | |||
| 327 | struct kvm_book3e_206_tlb_entry { | 333 | struct kvm_book3e_206_tlb_entry { |
| 328 | __u32 mas8; | 334 | __u32 mas8; |
| 329 | __u32 mas1; | 335 | __u32 mas1; |
diff --git a/arch/powerpc/kvm/Makefile b/arch/powerpc/kvm/Makefile index 4eada0c01082..3faf5c07329c 100644 --- a/arch/powerpc/kvm/Makefile +++ b/arch/powerpc/kvm/Makefile | |||
| @@ -86,6 +86,7 @@ kvm-book3s_64-module-objs := \ | |||
| 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 | ||
| 91 | kvm-objs-$(CONFIG_KVM_BOOK3S_64) := $(kvm-book3s_64-module-objs) | 92 | kvm-objs-$(CONFIG_KVM_BOOK3S_64) := $(kvm-book3s_64-module-objs) |
diff --git a/arch/powerpc/kvm/book3s_hv.c b/arch/powerpc/kvm/book3s_hv.c index 5af0f2979833..f3d7af7981c7 100644 --- a/arch/powerpc/kvm/book3s_hv.c +++ b/arch/powerpc/kvm/book3s_hv.c | |||
| @@ -483,7 +483,7 @@ int kvmppc_pseries_do_hcall(struct kvm_vcpu *vcpu) | |||
| 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) | |||
| 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) | |||
| 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) | |||
| 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 | } |
diff --git a/arch/powerpc/kvm/book3s_pr.c b/arch/powerpc/kvm/book3s_pr.c index c1cffa882a69..d09baf143500 100644 --- a/arch/powerpc/kvm/book3s_pr.c +++ b/arch/powerpc/kvm/book3s_pr.c | |||
| @@ -1296,6 +1296,7 @@ int kvmppc_core_init_vm(struct kvm *kvm) | |||
| 1296 | { | 1296 | { |
| 1297 | #ifdef CONFIG_PPC64 | 1297 | #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 | #endif | 1300 | #endif |
| 1300 | 1301 | ||
