The highlights are: * Enable VFIO device on PowerPC, from David Gibson * Optimizations to speed up IPIs between vcpus in HV KVM, from Suresh Warrier (who is also Suresh E. Warrier) * In-kernel handling of IOMMU hypercalls, and support for dynamic DMA windows (DDW), from Alexey Kardashevskiy.
Unified · Split
| @@ -3035,6 +3035,63 @@ Returns: 0 on success, -1 on error · 3034 unmodified lines | ||
| 3035 | 3035 | |
| 3036 | 3036 | Queues an SMI on the thread's vcpu. |
| 3037 | 3037 | |
| 3038 | +4.97 KVM_CAP_PPC_MULTITCE | |
| 3039 | + | |
| 3040 | +Capability: KVM_CAP_PPC_MULTITCE | |
| 3041 | +Architectures: ppc | |
| 3042 | +Type: vm | |
| 3043 | + | |
| 3044 | +This capability means the kernel is capable of handling hypercalls | |
| 3045 | +H_PUT_TCE_INDIRECT and H_STUFF_TCE without passing those into the user | |
| 3046 | +space. This significantly accelerates DMA operations for PPC KVM guests. | |
| 3047 | +User space should expect that its handlers for these hypercalls | |
| 3048 | +are not going to be called if user space previously registered LIOBN | |
| 3049 | +in KVM (via KVM_CREATE_SPAPR_TCE or similar calls). | |
| 3050 | + | |
| 3051 | +In order to enable H_PUT_TCE_INDIRECT and H_STUFF_TCE use in the guest, | |
| 3052 | +user space might have to advertise it for the guest. For example, | |
| 3053 | +IBM pSeries (sPAPR) guest starts using them if "hcall-multi-tce" is | |
| 3054 | +present in the "ibm,hypertas-functions" device-tree property. | |
| 3055 | + | |
| 3056 | +The hypercalls mentioned above may or may not be processed successfully | |
| 3057 | +in the kernel based fast path. If they can not be handled by the kernel, | |
| 3058 | +they will get passed on to user space. So user space still has to have | |
| 3059 | +an implementation for these despite the in kernel acceleration. | |
| 3060 | + | |
| 3061 | +This capability is always enabled. | |
| 3062 | + | |
| 3063 | +4.98 KVM_CREATE_SPAPR_TCE_64 | |
| 3064 | + | |
| 3065 | +Capability: KVM_CAP_SPAPR_TCE_64 | |
| 3066 | +Architectures: powerpc | |
| 3067 | +Type: vm ioctl | |
| 3068 | +Parameters: struct kvm_create_spapr_tce_64 (in) | |
| 3069 | +Returns: file descriptor for manipulating the created TCE table | |
| 3070 | + | |
| 3071 | +This is an extension for KVM_CAP_SPAPR_TCE which only supports 32bit | |
| 3072 | +windows, described in 4.62 KVM_CREATE_SPAPR_TCE | |
| 3073 | + | |
| 3074 | +This capability uses extended struct in ioctl interface: | |
| 3075 | + | |
| 3076 | +/* for KVM_CAP_SPAPR_TCE_64 */ | |
| 3077 | +struct kvm_create_spapr_tce_64 { | |
| 3078 | + __u64 liobn; | |
| 3079 | + __u32 page_shift; | |
| 3080 | + __u32 flags; | |
| 3081 | + __u64 offset; /* in pages */ | |
| 3082 | + __u64 size; /* in pages */ | |
| 3083 | +}; | |
| 3084 | + | |
| 3085 | +The aim of extension is to support an additional bigger DMA window with | |
| 3086 | +a variable page size. | |
| 3087 | +KVM_CREATE_SPAPR_TCE_64 receives a 64bit window size, an IOMMU page shift and | |
| 3088 | +a bus offset of the corresponding DMA window, @size and @offset are numbers | |
| 3089 | +of IOMMU pages. | |
| 3090 | + | |
| 3091 | +@flags are not used at the moment. | |
| 3092 | + | |
| 3093 | +The rest of functionality is identical to KVM_CREATE_SPAPR_TCE. | |
| 3094 | + | |
| 3038 | 3095 | 5. The kvm_run structure |
| 3039 | 3096 | ------------------------ |
| 3040 | 3097 | |
| @@ -33,8 +33,6 @@ static inline void svcpu_put(struct kvmppc_book3s_shadow_vcpu *svcpu) · 32 unmodified lines | ||
| 33 | 33 | } |
| 34 | 34 | #endif |
| 35 | 35 | |
| 36 | −#define SPAPR_TCE_SHIFT 12 | |
| 37 | − | |
| 38 | 36 | #ifdef CONFIG_KVM_BOOK3S_HV_POSSIBLE |
| 39 | 37 | #define KVM_DEFAULT_HPT_ORDER 24 /* 16MB HPT by default */ |
| 40 | 38 | #endif |
| @@ -182,7 +182,10 @@ struct kvmppc_spapr_tce_table { · 181 unmodified lines | ||
| 182 | 182 | struct list_head list; |
| 183 | 183 | struct kvm *kvm; |
| 184 | 184 | u64 liobn; |
| 185 | − u32 window_size; | |
| 185 | + struct rcu_head rcu; | |
| 186 | + u32 page_shift; | |
| 187 | + u64 offset; /* in pages */ | |
| 188 | + u64 size; /* window size in pages */ | |
| 186 | 189 | struct page *pages[0]; |
| 187 | 190 | }; |
| 188 | 191 | |
| @@ -165,9 +165,25 @@ extern void kvmppc_map_vrma(struct kvm_vcpu *vcpu, · 164 unmodified lines | ||
| 165 | 165 | extern int kvmppc_pseries_do_hcall(struct kvm_vcpu *vcpu); |
| 166 | 166 | |
| 167 | 167 | extern long kvm_vm_ioctl_create_spapr_tce(struct kvm *kvm, |
| 168 | − struct kvm_create_spapr_tce *args); | |
| 168 | + struct kvm_create_spapr_tce_64 *args); | |
| 169 | +extern struct kvmppc_spapr_tce_table *kvmppc_find_table( | |
| 170 | + struct kvm_vcpu *vcpu, unsigned long liobn); | |
| 171 | +extern long kvmppc_ioba_validate(struct kvmppc_spapr_tce_table *stt, | |
| 172 | + unsigned long ioba, unsigned long npages); | |
| 173 | +extern long kvmppc_tce_validate(struct kvmppc_spapr_tce_table *tt, | |
| 174 | + unsigned long tce); | |
| 175 | +extern long kvmppc_gpa_to_ua(struct kvm *kvm, unsigned long gpa, | |
| 176 | + unsigned long *ua, unsigned long **prmap); | |
| 177 | +extern void kvmppc_tce_put(struct kvmppc_spapr_tce_table *tt, | |
| 178 | + unsigned long idx, unsigned long tce); | |
| 169 | 179 | extern long kvmppc_h_put_tce(struct kvm_vcpu *vcpu, unsigned long liobn, |
| 170 | 180 | unsigned long ioba, unsigned long tce); |
| 181 | +extern long kvmppc_h_put_tce_indirect(struct kvm_vcpu *vcpu, | |
| 182 | + unsigned long liobn, unsigned long ioba, | |
| 183 | + unsigned long tce_list, unsigned long npages); | |
| 184 | +extern long kvmppc_h_stuff_tce(struct kvm_vcpu *vcpu, | |
| 185 | + unsigned long liobn, unsigned long ioba, | |
| 186 | + unsigned long tce_value, unsigned long npages); | |
| 171 | 187 | extern long kvmppc_h_get_tce(struct kvm_vcpu *vcpu, unsigned long liobn, |
| 172 | 188 | unsigned long ioba); |
| 173 | 189 | extern struct page *kvm_alloc_hpt(unsigned long nr_pages); |
| @@ -437,6 +453,8 @@ static inline int kvmppc_xics_enabled(struct kvm_vcpu *vcpu) · 263 unmodified lines | ||
| 437 | 453 | { |
| 438 | 454 | return vcpu->arch.irq_type == KVMPPC_IRQ_XICS; |
| 439 | 455 | } |
| 456 | +extern void kvmppc_alloc_host_rm_ops(void); | |
| 457 | +extern void kvmppc_free_host_rm_ops(void); | |
| 440 | 458 | extern void kvmppc_xics_free_icp(struct kvm_vcpu *vcpu); |
| 441 | 459 | extern int kvmppc_xics_create_icp(struct kvm_vcpu *vcpu, unsigned long server); |
| 442 | 460 | extern int kvm_vm_ioctl_xics_irq(struct kvm *kvm, struct kvm_irq_level *args); |
| @@ -445,7 +463,11 @@ extern u64 kvmppc_xics_get_icp(struct kvm_vcpu *vcpu); · 2 unmodified lines | ||
| 445 | 463 | extern int kvmppc_xics_set_icp(struct kvm_vcpu *vcpu, u64 icpval); |
| 446 | 464 | extern int kvmppc_xics_connect_vcpu(struct kvm_device *dev, |
| 447 | 465 | struct kvm_vcpu *vcpu, u32 cpu); |
| 466 | +extern void kvmppc_xics_ipi_action(void); | |
| 467 | +extern int h_ipi_redirect; | |
| 448 | 468 | #else |
| 469 | +static inline void kvmppc_alloc_host_rm_ops(void) {}; | |
| 470 | +static inline void kvmppc_free_host_rm_ops(void) {}; | |
| 449 | 471 | static inline int kvmppc_xics_enabled(struct kvm_vcpu *vcpu) |
| 450 | 472 | { return 0; } |
| 451 | 473 | static inline void kvmppc_xics_free_icp(struct kvm_vcpu *vcpu) { } |
| @@ -459,6 +481,33 @@ static inline int kvmppc_xics_hcall(struct kvm_vcpu *vcpu, u32 cmd) · 7 unmodified lines | ||
| 459 | 481 | { return 0; } |
| 460 | 482 | #endif |
| 461 | 483 | |
| 484 | +/* | |
| 485 | + * Host-side operations we want to set up while running in real | |
| 486 | + * mode in the guest operating on the xics. | |
| 487 | + * Currently only VCPU wakeup is supported. | |
| 488 | + */ | |
| 489 | + | |
| 490 | +union kvmppc_rm_state { | |
| 491 | + unsigned long raw; | |
| 492 | + struct { | |
| 493 | + u32 in_host; | |
| 494 | + u32 rm_action; | |
| 495 | + }; | |
| 496 | +}; | |
| 497 | + | |
| 498 | +struct kvmppc_host_rm_core { | |
| 499 | + union kvmppc_rm_state rm_state; | |
| 500 | + void *rm_data; | |
| 501 | + char pad[112]; | |
| 502 | +}; | |
| 503 | + | |
| 504 | +struct kvmppc_host_rm_ops { | |
| 505 | + struct kvmppc_host_rm_core *rm_core; | |
| 506 | + void (*vcpu_kick)(struct kvm_vcpu *vcpu); | |
| 507 | +}; | |
| 508 | + | |
| 509 | +extern struct kvmppc_host_rm_ops *kvmppc_host_rm_ops_hv; | |
| 510 | + | |
| 462 | 511 | static inline unsigned long kvmppc_get_epr(struct kvm_vcpu *vcpu) |
| 463 | 512 | { |
| 464 | 513 | #ifdef CONFIG_KVM_BOOKE_HV |
| @@ -78,6 +78,9 @@ static inline pte_t *find_linux_pte_or_hugepte(pgd_t *pgdir, unsigned long ea, · 77 unmodified lines | ||
| 78 | 78 | } |
| 79 | 79 | return __find_linux_pte_or_hugepte(pgdir, ea, is_thp, shift); |
| 80 | 80 | } |
| 81 | + | |
| 82 | +unsigned long vmalloc_to_phys(void *vmalloc_addr); | |
| 83 | + | |
| 81 | 84 | #endif /* __ASSEMBLY__ */ |
| 82 | 85 | |
| 83 | 86 | #endif /* _ASM_POWERPC_PGTABLE_H */ |
| @@ -114,6 +114,9 @@ extern int cpu_to_core_id(int cpu); · 113 unmodified lines | ||
| 114 | 114 | #define PPC_MSG_TICK_BROADCAST 2 |
| 115 | 115 | #define PPC_MSG_DEBUGGER_BREAK 3 |
| 116 | 116 | |
| 117 | +/* This is only used by the powernv kernel */ | |
| 118 | +#define PPC_MSG_RM_HOST_ACTION 4 | |
| 119 | + | |
| 117 | 120 | /* for irq controllers that have dedicated ipis per message (4) */ |
| 118 | 121 | extern int smp_request_message_ipi(int virq, int message); |
| 119 | 122 | extern const char *smp_ipi_name[]; |
| @@ -121,6 +124,7 @@ extern const char *smp_ipi_name[]; · 1 unmodified line | ||
| 121 | 124 | /* for irq controllers with only a single ipi */ |
| 122 | 125 | extern void smp_muxed_ipi_set_data(int cpu, unsigned long data); |
| 123 | 126 | extern void smp_muxed_ipi_message_pass(int cpu, int msg); |
| 127 | +extern void smp_muxed_ipi_set_message(int cpu, int msg); | |
| 124 | 128 | extern irqreturn_t smp_ipi_demux(void); |
| 125 | 129 | |
| 126 | 130 | void smp_init_pSeries(void); |
| @@ -30,6 +30,7 @@ · 29 unmodified lines | ||
| 30 | 30 | #ifdef CONFIG_PPC_ICP_NATIVE |
| 31 | 31 | extern int icp_native_init(void); |
| 32 | 32 | extern void icp_native_flush_interrupt(void); |
| 33 | +extern void icp_native_cause_ipi_rm(int cpu); | |
| 33 | 34 | #else |
| 34 | 35 | static inline int icp_native_init(void) { return -ENODEV; } |
| 35 | 36 | #endif |
| @@ -333,6 +333,15 @@ struct kvm_create_spapr_tce { · 332 unmodified lines | ||
| 333 | 333 | __u32 window_size; |
| 334 | 334 | }; |
| 335 | 335 | |
| 336 | +/* for KVM_CAP_SPAPR_TCE_64 */ | |
| 337 | +struct kvm_create_spapr_tce_64 { | |
| 338 | + __u64 liobn; | |
| 339 | + __u32 page_shift; | |
| 340 | + __u32 flags; | |
| 341 | + __u64 offset; /* in pages */ | |
| 342 | + __u64 size; /* in pages */ | |
| 343 | +}; | |
| 344 | + | |
| 336 | 345 | /* for KVM_ALLOCATE_RMA */ |
| 337 | 346 | struct kvm_allocate_rma { |
| 338 | 347 | __u64 rma_size; |
| @@ -206,7 +206,7 @@ int smp_request_message_ipi(int virq, int msg) · 205 unmodified lines | ||
| 206 | 206 | |
| 207 | 207 | #ifdef CONFIG_PPC_SMP_MUXED_IPI |
| 208 | 208 | struct cpu_messages { |
| 209 | − int messages; /* current messages */ | |
| 209 | + long messages; /* current messages */ | |
| 210 | 210 | unsigned long data; /* data for cause ipi */ |
| 211 | 211 | }; |
| 212 | 212 | static DEFINE_PER_CPU_SHARED_ALIGNED(struct cpu_messages, ipi_message); |
| @@ -218,7 +218,7 @@ void smp_muxed_ipi_set_data(int cpu, unsigned long data) · 5 unmodified lines | ||
| 218 | 218 | info->data = data; |
| 219 | 219 | } |
| 220 | 220 | |
| 221 | −void smp_muxed_ipi_message_pass(int cpu, int msg) | |
| 221 | +void smp_muxed_ipi_set_message(int cpu, int msg) | |
| 222 | 222 | { |
| 223 | 223 | struct cpu_messages *info = &per_cpu(ipi_message, cpu); |
| 224 | 224 | char *message = (char *)&info->messages; |
| @@ -228,6 +228,13 @@ void smp_muxed_ipi_message_pass(int cpu, int msg) · 3 unmodified lines | ||
| 228 | 228 | */ |
| 229 | 229 | smp_mb(); |
| 230 | 230 | message[msg] = 1; |
| 231 | +} | |
| 232 | + | |
| 233 | +void smp_muxed_ipi_message_pass(int cpu, int msg) | |
| 234 | +{ | |
| 235 | + struct cpu_messages *info = &per_cpu(ipi_message, cpu); | |
| 236 | + | |
| 237 | + smp_muxed_ipi_set_message(cpu, msg); | |
| 231 | 238 | /* |
| 232 | 239 | * cause_ipi functions are required to include a full barrier |
| 233 | 240 | * before doing whatever causes the IPI. |
| @@ -236,20 +243,31 @@ void smp_muxed_ipi_message_pass(int cpu, int msg) · 2 unmodified lines | ||
| 236 | 243 | } |
| 237 | 244 | |
| 238 | 245 | #ifdef __BIG_ENDIAN__ |
| 239 | −#define IPI_MESSAGE(A) (1 << (24 - 8 * (A))) | |
| 246 | +#define IPI_MESSAGE(A) (1uL << ((BITS_PER_LONG - 8) - 8 * (A))) | |
| 240 | 247 | #else |
| 241 | −#define IPI_MESSAGE(A) (1 << (8 * (A))) | |
| 248 | +#define IPI_MESSAGE(A) (1uL << (8 * (A))) | |
| 242 | 249 | #endif |
| 243 | 250 | |
| 244 | 251 | irqreturn_t smp_ipi_demux(void) |
| 245 | 252 | { |
| 246 | 253 | struct cpu_messages *info = this_cpu_ptr(&ipi_message); |
| 247 | − unsigned int all; | |
| 254 | + unsigned long all; | |
| 248 | 255 | |
| 249 | 256 | mb(); /* order any irq clear */ |
| 250 | 257 | |
| 251 | 258 | do { |
| 252 | 259 | all = xchg(&info->messages, 0); |
| 260 | +#if defined(CONFIG_KVM_XICS) && defined(CONFIG_KVM_BOOK3S_HV_POSSIBLE) | |
| 261 | + /* | |
| 262 | + * Must check for PPC_MSG_RM_HOST_ACTION messages | |
| 263 | + * before PPC_MSG_CALL_FUNCTION messages because when | |
| 264 | + * a VM is destroyed, we call kick_all_cpus_sync() | |
| 265 | + * to ensure that any pending PPC_MSG_RM_HOST_ACTION | |
| 266 | + * messages have completed before we free any VCPUs. | |
| 267 | + */ | |
| 268 | + if (all & IPI_MESSAGE(PPC_MSG_RM_HOST_ACTION)) | |
| 269 | + kvmppc_xics_ipi_action(); | |
| 270 | +#endif | |
| 253 | 271 | if (all & IPI_MESSAGE(PPC_MSG_CALL_FUNCTION)) |
| 254 | 272 | generic_smp_call_function_interrupt(); |
| 255 | 273 | if (all & IPI_MESSAGE(PPC_MSG_RESCHEDULE)) |
| @@ -8,7 +8,7 @@ ccflags-y := -Ivirt/kvm -Iarch/powerpc/kvm · 7 unmodified lines | ||
| 8 | 8 | KVM := ../../../virt/kvm |
| 9 | 9 | |
| 10 | 10 | common-objs-y = $(KVM)/kvm_main.o $(KVM)/coalesced_mmio.o \ |
| 11 | − $(KVM)/eventfd.o | |
| 11 | + $(KVM)/eventfd.o $(KVM)/vfio.o | |
| 12 | 12 | |
| 13 | 13 | CFLAGS_e500_mmu.o := -I. |
| 14 | 14 | CFLAGS_e500_mmu_host.o := -I. |
| @@ -807,7 +807,7 @@ int kvmppc_core_init_vm(struct kvm *kvm) · 806 unmodified lines | ||
| 807 | 807 | { |
| 808 | 808 | |
| 809 | 809 | #ifdef CONFIG_PPC64 |
| 810 | − INIT_LIST_HEAD(&kvm->arch.spapr_tce_tables); | |
| 810 | + INIT_LIST_HEAD_RCU(&kvm->arch.spapr_tce_tables); | |
| 811 | 811 | INIT_LIST_HEAD(&kvm->arch.rtas_tokens); |
| 812 | 812 | #endif |
| 813 | 813 | |
| @@ -14,6 +14,7 @@ · 13 unmodified lines | ||
| 14 | 14 | * |
| 15 | 15 | * Copyright 2010 Paul Mackerras, IBM Corp. <paulus@au1.ibm.com> |
| 16 | 16 | * Copyright 2011 David Gibson, IBM Corporation <dwg@au1.ibm.com> |
| 17 | + * Copyright 2016 Alexey Kardashevskiy, IBM Corporation <aik@au1.ibm.com> | |
| 17 | 18 | */ |
| 18 | 19 | |
| 19 | 20 | #include <linux/types.h> |
| @@ -36,28 +37,69 @@ · 16 unmodified lines | ||
| 36 | 37 | #include <asm/ppc-opcode.h> |
| 37 | 38 | #include <asm/kvm_host.h> |
| 38 | 39 | #include <asm/udbg.h> |
| 40 | +#include <asm/iommu.h> | |
| 41 | +#include <asm/tce.h> | |
| 39 | 42 | |
| 40 | −#define TCES_PER_PAGE (PAGE_SIZE / sizeof(u64)) | |
| 43 | +static unsigned long kvmppc_tce_pages(unsigned long iommu_pages) | |
| 44 | +{ | |
| 45 | + return ALIGN(iommu_pages * sizeof(u64), PAGE_SIZE) / PAGE_SIZE; | |
| 46 | +} | |
| 41 | 47 | |
| 42 | −static long kvmppc_stt_npages(unsigned long window_size) | |
| 48 | +static unsigned long kvmppc_stt_pages(unsigned long tce_pages) | |
| 43 | 49 | { |
| 44 | − return ALIGN((window_size >> SPAPR_TCE_SHIFT) | |
| 45 | − * sizeof(u64), PAGE_SIZE) / PAGE_SIZE; | |
| 50 | + unsigned long stt_bytes = sizeof(struct kvmppc_spapr_tce_table) + | |
| 51 | + (tce_pages * sizeof(struct page *)); | |
| 52 | + | |
| 53 | + return tce_pages + ALIGN(stt_bytes, PAGE_SIZE) / PAGE_SIZE; | |
| 46 | 54 | } |
| 47 | 55 | |
| 48 | −static void release_spapr_tce_table(struct kvmppc_spapr_tce_table *stt) | |
| 56 | +static long kvmppc_account_memlimit(unsigned long stt_pages, bool inc) | |
| 49 | 57 | { |
| 50 | − struct kvm *kvm = stt->kvm; | |
| 51 | − int i; | |
| 58 | + long ret = 0; | |
| 52 | 59 | |
| 53 | − mutex_lock(&kvm->lock); | |
| 54 | − list_del(&stt->list); | |
| 55 | − for (i = 0; i < kvmppc_stt_npages(stt->window_size); i++) | |
| 60 | + if (!current || !current->mm) | |
| 61 | + return ret; /* process exited */ | |
| 62 | + | |
| 63 | + down_write(¤t->mm->mmap_sem); | |
| 64 | + | |
| 65 | + if (inc) { | |
| 66 | + unsigned long locked, lock_limit; | |
| 67 | + | |
| 68 | + locked = current->mm->locked_vm + stt_pages; | |
| 69 | + lock_limit = rlimit(RLIMIT_MEMLOCK) >> PAGE_SHIFT; | |
| 70 | + if (locked > lock_limit && !capable(CAP_IPC_LOCK)) | |
| 71 | + ret = -ENOMEM; | |
| 72 | + else | |
| 73 | + current->mm->locked_vm += stt_pages; | |
| 74 | + } else { | |
| 75 | + if (WARN_ON_ONCE(stt_pages > current->mm->locked_vm)) | |
| 76 | + stt_pages = current->mm->locked_vm; | |
| 77 | + | |
| 78 | + current->mm->locked_vm -= stt_pages; | |
| 79 | + } | |
| 80 | + | |
| 81 | + pr_debug("[%d] RLIMIT_MEMLOCK KVM %c%ld %ld/%ld%s\n", current->pid, | |
| 82 | + inc ? '+' : '-', | |
| 83 | + stt_pages << PAGE_SHIFT, | |
| 84 | + current->mm->locked_vm << PAGE_SHIFT, | |
| 85 | + rlimit(RLIMIT_MEMLOCK), | |
| 86 | + ret ? " - exceeded" : ""); | |
| 87 | + | |
| 88 | + up_write(¤t->mm->mmap_sem); | |
| 89 | + | |
| 90 | + return ret; | |
| 91 | +} | |
| 92 | + | |
| 93 | +static void release_spapr_tce_table(struct rcu_head *head) | |
| 94 | +{ | |
| 95 | + struct kvmppc_spapr_tce_table *stt = container_of(head, | |
| 96 | + struct kvmppc_spapr_tce_table, rcu); | |
| 97 | + unsigned long i, npages = kvmppc_tce_pages(stt->size); | |
| 98 | + | |
| 99 | + for (i = 0; i < npages; i++) | |
| 56 | 100 | __free_page(stt->pages[i]); |
| 57 | − kfree(stt); | |
| 58 | − mutex_unlock(&kvm->lock); | |
| 59 | 101 | |
| 60 | − kvm_put_kvm(kvm); | |
| 102 | + kfree(stt); | |
| 61 | 103 | } |
| 62 | 104 | |
| 63 | 105 | static int kvm_spapr_tce_fault(struct vm_area_struct *vma, struct vm_fault *vmf) |
| @@ -65,7 +107,7 @@ static int kvm_spapr_tce_fault(struct vm_area_struct *vma, struct vm_fault *vmf) · 1 unmodified line | ||
| 65 | 107 | struct kvmppc_spapr_tce_table *stt = vma->vm_file->private_data; |
| 66 | 108 | struct page *page; |
| 67 | 109 | |
| 68 | − if (vmf->pgoff >= kvmppc_stt_npages(stt->window_size)) | |
| 110 | + if (vmf->pgoff >= kvmppc_tce_pages(stt->size)) | |
| 69 | 111 | return VM_FAULT_SIGBUS; |
| 70 | 112 | |
| 71 | 113 | page = stt->pages[vmf->pgoff]; |
| @@ -88,7 +130,14 @@ static int kvm_spapr_tce_release(struct inode *inode, struct file *filp) · 16 unmodified lines | ||
| 88 | 130 | { |
| 89 | 131 | struct kvmppc_spapr_tce_table *stt = filp->private_data; |
| 90 | 132 | |
| 91 | − release_spapr_tce_table(stt); | |
| 133 | + list_del_rcu(&stt->list); | |
| 134 | + | |
| 135 | + kvm_put_kvm(stt->kvm); | |
| 136 | + | |
| 137 | + kvmppc_account_memlimit( | |
| 138 | + kvmppc_stt_pages(kvmppc_tce_pages(stt->size)), false); | |
| 139 | + call_rcu(&stt->rcu, release_spapr_tce_table); | |
| 140 | + | |
| 92 | 141 | return 0; |
| 93 | 142 | } |
| 94 | 143 | |
| @@ -98,20 +147,29 @@ static const struct file_operations kvm_spapr_tce_fops = { · 3 unmodified lines | ||
| 98 | 147 | }; |
| 99 | 148 | |
| 100 | 149 | long kvm_vm_ioctl_create_spapr_tce(struct kvm *kvm, |
| 101 | − struct kvm_create_spapr_tce *args) | |
| 150 | + struct kvm_create_spapr_tce_64 *args) | |
| 102 | 151 | { |
| 103 | 152 | struct kvmppc_spapr_tce_table *stt = NULL; |
| 104 | − long npages; | |
| 153 | + unsigned long npages, size; | |
| 105 | 154 | int ret = -ENOMEM; |
| 106 | 155 | int i; |
| 107 | 156 | |
| 157 | + if (!args->size) | |
| 158 | + return -EINVAL; | |
| 159 | + | |
| 108 | 160 | /* Check this LIOBN hasn't been previously allocated */ |
| 109 | 161 | list_for_each_entry(stt, &kvm->arch.spapr_tce_tables, list) { |
| 110 | 162 | if (stt->liobn == args->liobn) |
| 111 | 163 | return -EBUSY; |
| 112 | 164 | } |
| 113 | 165 | |
| 114 | − npages = kvmppc_stt_npages(args->window_size); | |
| 166 | + size = args->size; | |
| 167 | + npages = kvmppc_tce_pages(size); | |
| 168 | + ret = kvmppc_account_memlimit(kvmppc_stt_pages(npages), true); | |
| 169 | + if (ret) { | |
| 170 | + stt = NULL; | |
| 171 | + goto fail; | |
| 172 | + } | |
| 115 | 173 | |
| 116 | 174 | stt = kzalloc(sizeof(*stt) + npages * sizeof(struct page *), |
| 117 | 175 | GFP_KERNEL); |
| @@ -119,7 +177,9 @@ long kvm_vm_ioctl_create_spapr_tce(struct kvm *kvm, · 1 unmodified line | ||
| 119 | 177 | goto fail; |
| 120 | 178 | |
| 121 | 179 | stt->liobn = args->liobn; |
| 122 | − stt->window_size = args->window_size; | |
| 180 | + stt->page_shift = args->page_shift; | |
| 181 | + stt->offset = args->offset; | |
| 182 | + stt->size = size; | |
| 123 | 183 | stt->kvm = kvm; |
| 124 | 184 | |
| 125 | 185 | for (i = 0; i < npages; i++) { |
| @@ -131,7 +191,7 @@ long kvm_vm_ioctl_create_spapr_tce(struct kvm *kvm, · 5 unmodified lines | ||
| 131 | 191 | kvm_get_kvm(kvm); |
| 132 | 192 | |
| 133 | 193 | mutex_lock(&kvm->lock); |
| 134 | − list_add(&stt->list, &kvm->arch.spapr_tce_tables); | |
| 194 | + list_add_rcu(&stt->list, &kvm->arch.spapr_tce_tables); | |
| 135 | 195 | |
| 136 | 196 | mutex_unlock(&kvm->lock); |
| 137 | 197 | |
| @@ -148,3 +208,59 @@ fail: · 10 unmodified lines | ||
| 148 | 208 | } |
| 149 | 209 | return ret; |
| 150 | 210 | } |
| 211 | + | |
| 212 | +long kvmppc_h_put_tce_indirect(struct kvm_vcpu *vcpu, | |
| 213 | + unsigned long liobn, unsigned long ioba, | |
| 214 | + unsigned long tce_list, unsigned long npages) | |
| 215 | +{ | |
| 216 | + struct kvmppc_spapr_tce_table *stt; | |
| 217 | + long i, ret = H_SUCCESS, idx; | |
| 218 | + unsigned long entry, ua = 0; | |
| 219 | + u64 __user *tces, tce; | |
| 220 | + | |
| 221 | + stt = kvmppc_find_table(vcpu, liobn); | |
| 222 | + if (!stt) | |
| 223 | + return H_TOO_HARD; | |
| 224 | + | |
| 225 | + entry = ioba >> stt->page_shift; | |
| 226 | + /* | |
| 227 | + * SPAPR spec says that the maximum size of the list is 512 TCEs | |
| 228 | + * so the whole table fits in 4K page | |
| 229 | + */ | |
| 230 | + if (npages > 512) | |
| 231 | + return H_PARAMETER; | |
| 232 | + | |
| 233 | + if (tce_list & (SZ_4K - 1)) | |
| 234 | + return H_PARAMETER; | |
| 235 | + | |
| 236 | + ret = kvmppc_ioba_validate(stt, ioba, npages); | |
| 237 | + if (ret != H_SUCCESS) | |
| 238 | + return ret; | |
| 239 | + | |
| 240 | + idx = srcu_read_lock(&vcpu->kvm->srcu); | |
| 241 | + if (kvmppc_gpa_to_ua(vcpu->kvm, tce_list, &ua, NULL)) { | |
| 242 | + ret = H_TOO_HARD; | |
| 243 | + goto unlock_exit; | |
| 244 | + } | |
| 245 | + tces = (u64 __user *) ua; | |
| 246 | + | |
| 247 | + for (i = 0; i < npages; ++i) { | |
| 248 | + if (get_user(tce, tces + i)) { | |
| 249 | + ret = H_TOO_HARD; | |
| 250 | + goto unlock_exit; | |
| 251 | + } | |
| 252 | + tce = be64_to_cpu(tce); | |
| 253 | + | |
| 254 | + ret = kvmppc_tce_validate(stt, tce); | |
| 255 | + if (ret != H_SUCCESS) | |
| 256 | + goto unlock_exit; | |
| 257 | + | |
| 258 | + kvmppc_tce_put(stt, entry + i, tce); | |
| 259 | + } | |
| 260 | + | |
| 261 | +unlock_exit: | |
| 262 | + srcu_read_unlock(&vcpu->kvm->srcu, idx); | |
| 263 | + | |
| 264 | + return ret; | |
| 265 | +} | |
| 266 | +EXPORT_SYMBOL_GPL(kvmppc_h_put_tce_indirect); | |
| @@ -14,6 +14,7 @@ · 13 unmodified lines | ||
| 14 | 14 | * |
| 15 | 15 | * Copyright 2010 Paul Mackerras, IBM Corp. <paulus@au1.ibm.com> |
| 16 | 16 | * Copyright 2011 David Gibson, IBM Corporation <dwg@au1.ibm.com> |
| 17 | + * Copyright 2016 Alexey Kardashevskiy, IBM Corporation <aik@au1.ibm.com> | |
| 17 | 18 | */ |
| 18 | 19 | |
| 19 | 20 | #include <linux/types.h> |
| @@ -30,76 +31,321 @@ · 10 unmodified lines | ||
| 30 | 31 | #include <asm/kvm_ppc.h> |
| 31 | 32 | #include <asm/kvm_book3s.h> |
| 32 | 33 | #include <asm/mmu-hash64.h> |
| 34 | +#include <asm/mmu_context.h> | |
| 33 | 35 | #include <asm/hvcall.h> |
| 34 | 36 | #include <asm/synch.h> |
| 35 | 37 | #include <asm/ppc-opcode.h> |
| 36 | 38 | #include <asm/kvm_host.h> |
| 37 | 39 | #include <asm/udbg.h> |
| 40 | +#include <asm/iommu.h> | |
| 41 | +#include <asm/tce.h> | |
| 42 | +#include <asm/iommu.h> | |
| 38 | 43 | |
| 39 | 44 | #define TCES_PER_PAGE (PAGE_SIZE / sizeof(u64)) |
| 40 | 45 | |
| 41 | −/* WARNING: This will be called in real-mode on HV KVM and virtual | |
| 46 | +/* | |
| 47 | + * Finds a TCE table descriptor by LIOBN. | |
| 48 | + * | |
| 49 | + * WARNING: This will be called in real or virtual mode on HV KVM and virtual | |
| 42 | 50 | * mode on PR KVM |
| 43 | 51 | */ |
| 44 | −long kvmppc_h_put_tce(struct kvm_vcpu *vcpu, unsigned long liobn, | |
| 45 | − unsigned long ioba, unsigned long tce) | |
| 52 | +struct kvmppc_spapr_tce_table *kvmppc_find_table(struct kvm_vcpu *vcpu, | |
| 53 | + unsigned long liobn) | |
| 46 | 54 | { |
| 47 | 55 | struct kvm *kvm = vcpu->kvm; |
| 48 | 56 | struct kvmppc_spapr_tce_table *stt; |
| 49 | 57 | |
| 58 | + list_for_each_entry_lockless(stt, &kvm->arch.spapr_tce_tables, list) | |
| 59 | + if (stt->liobn == liobn) | |
| 60 | + return stt; | |
| 61 | + | |
| 62 | + return NULL; | |
| 63 | +} | |
| 64 | +EXPORT_SYMBOL_GPL(kvmppc_find_table); | |
| 65 | + | |
| 66 | +/* | |
| 67 | + * Validates IO address. | |
| 68 | + * | |
| 69 | + * WARNING: This will be called in real-mode on HV KVM and virtual | |
| 70 | + * mode on PR KVM | |
| 71 | + */ | |
| 72 | +long kvmppc_ioba_validate(struct kvmppc_spapr_tce_table *stt, | |
| 73 | + unsigned long ioba, unsigned long npages) | |
| 74 | +{ | |
| 75 | + unsigned long mask = (1ULL << stt->page_shift) - 1; | |
| 76 | + unsigned long idx = ioba >> stt->page_shift; | |
| 77 | + | |
| 78 | + if ((ioba & mask) || (idx < stt->offset) || | |
| 79 | + (idx - stt->offset + npages > stt->size) || | |
| 80 | + (idx + npages < idx)) | |
| 81 | + return H_PARAMETER; | |
| 82 | + | |
| 83 | + return H_SUCCESS; | |
| 84 | +} | |
| 85 | +EXPORT_SYMBOL_GPL(kvmppc_ioba_validate); | |
| 86 | + | |
| 87 | +/* | |
| 88 | + * Validates TCE address. | |
| 89 | + * At the moment flags and page mask are validated. | |
| 90 | + * As the host kernel does not access those addresses (just puts them | |
| 91 | + * to the table and user space is supposed to process them), we can skip | |
| 92 | + * checking other things (such as TCE is a guest RAM address or the page | |
| 93 | + * was actually allocated). | |
| 94 | + * | |
| 95 | + * WARNING: This will be called in real-mode on HV KVM and virtual | |
| 96 | + * mode on PR KVM | |
| 97 | + */ | |
| 98 | +long kvmppc_tce_validate(struct kvmppc_spapr_tce_table *stt, unsigned long tce) | |
| 99 | +{ | |
| 100 | + unsigned long page_mask = ~((1ULL << stt->page_shift) - 1); | |
| 101 | + unsigned long mask = ~(page_mask | TCE_PCI_WRITE | TCE_PCI_READ); | |
| 102 | + | |
| 103 | + if (tce & mask) | |
| 104 | + return H_PARAMETER; | |
| 105 | + | |
| 106 | + return H_SUCCESS; | |
| 107 | +} | |
| 108 | +EXPORT_SYMBOL_GPL(kvmppc_tce_validate); | |
| 109 | + | |
| 110 | +/* Note on the use of page_address() in real mode, | |
| 111 | + * | |
| 112 | + * It is safe to use page_address() in real mode on ppc64 because | |
| 113 | + * page_address() is always defined as lowmem_page_address() | |
| 114 | + * which returns __va(PFN_PHYS(page_to_pfn(page))) which is arithmetic | |
| 115 | + * operation and does not access page struct. | |
| 116 | + * | |
| 117 | + * Theoretically page_address() could be defined different | |
| 118 | + * but either WANT_PAGE_VIRTUAL or HASHED_PAGE_VIRTUAL | |
| 119 | + * would have to be enabled. | |
| 120 | + * WANT_PAGE_VIRTUAL is never enabled on ppc32/ppc64, | |
| 121 | + * HASHED_PAGE_VIRTUAL could be enabled for ppc32 only and only | |
| 122 | + * if CONFIG_HIGHMEM is defined. As CONFIG_SPARSEMEM_VMEMMAP | |
| 123 | + * is not expected to be enabled on ppc32, page_address() | |
| 124 | + * is safe for ppc32 as well. | |
| 125 | + * | |
| 126 | + * WARNING: This will be called in real-mode on HV KVM and virtual | |
| 127 | + * mode on PR KVM | |
| 128 | + */ | |
| 129 | +static u64 *kvmppc_page_address(struct page *page) | |
| 130 | +{ | |
| 131 | +#if defined(HASHED_PAGE_VIRTUAL) || defined(WANT_PAGE_VIRTUAL) | |
| 132 | +#error TODO: fix to avoid page_address() here | |
| 133 | +#endif | |
| 134 | + return (u64 *) page_address(page); | |
| 135 | +} | |
| 136 | + | |
| 137 | +/* | |
| 138 | + * Handles TCE requests for emulated devices. | |
| 139 | + * Puts guest TCE values to the table and expects user space to convert them. | |
| 140 | + * Called in both real and virtual modes. | |
| 141 | + * Cannot fail so kvmppc_tce_validate must be called before it. | |
| 142 | + * | |
| 143 | + * WARNING: This will be called in real-mode on HV KVM and virtual | |
| 144 | + * mode on PR KVM | |
| 145 | + */ | |
| 146 | +void kvmppc_tce_put(struct kvmppc_spapr_tce_table *stt, | |
| 147 | + unsigned long idx, unsigned long tce) | |
| 148 | +{ | |
| 149 | + struct page *page; | |
| 150 | + u64 *tbl; | |
| 151 | + | |
| 152 | + idx -= stt->offset; | |
| 153 | + page = stt->pages[idx / TCES_PER_PAGE]; | |
| 154 | + tbl = kvmppc_page_address(page); | |
| 155 | + | |
| 156 | + tbl[idx % TCES_PER_PAGE] = tce; | |
| 157 | +} | |
| 158 | +EXPORT_SYMBOL_GPL(kvmppc_tce_put); | |
| 159 | + | |
| 160 | +long kvmppc_gpa_to_ua(struct kvm *kvm, unsigned long gpa, | |
| 161 | + unsigned long *ua, unsigned long **prmap) | |
| 162 | +{ | |
| 163 | + unsigned long gfn = gpa >> PAGE_SHIFT; | |
| 164 | + struct kvm_memory_slot *memslot; | |
| 165 | + | |
| 166 | + memslot = search_memslots(kvm_memslots(kvm), gfn); | |
| 167 | + if (!memslot) | |
| 168 | + return -EINVAL; | |
| 169 | + | |
| 170 | + *ua = __gfn_to_hva_memslot(memslot, gfn) | | |
| 171 | + (gpa & ~(PAGE_MASK | TCE_PCI_READ | TCE_PCI_WRITE)); | |
| 172 | + | |
| 173 | +#ifdef CONFIG_KVM_BOOK3S_HV_POSSIBLE | |
| 174 | + if (prmap) | |
| 175 | + *prmap = &memslot->arch.rmap[gfn - memslot->base_gfn]; | |
| 176 | +#endif | |
| 177 | + | |
| 178 | + return 0; | |
| 179 | +} | |
| 180 | +EXPORT_SYMBOL_GPL(kvmppc_gpa_to_ua); | |
| 181 | + | |
| 182 | +#ifdef CONFIG_KVM_BOOK3S_HV_POSSIBLE | |
| 183 | +long kvmppc_h_put_tce(struct kvm_vcpu *vcpu, unsigned long liobn, | |
| 184 | + unsigned long ioba, unsigned long tce) | |
| 185 | +{ | |
| 186 | + struct kvmppc_spapr_tce_table *stt = kvmppc_find_table(vcpu, liobn); | |
| 187 | + long ret; | |
| 188 | + | |
| 50 | 189 | /* udbg_printf("H_PUT_TCE(): liobn=0x%lx ioba=0x%lx, tce=0x%lx\n", */ |
| 51 | 190 | /* liobn, ioba, tce); */ |
| 52 | 191 | |
| 53 | − list_for_each_entry(stt, &kvm->arch.spapr_tce_tables, list) { | |
| 54 | − if (stt->liobn == liobn) { | |
| 55 | − unsigned long idx = ioba >> SPAPR_TCE_SHIFT; | |
| 56 | − struct page *page; | |
| 57 | − u64 *tbl; | |
| 58 | − | |
| 59 | − /* udbg_printf("H_PUT_TCE: liobn 0x%lx => stt=%p window_size=0x%x\n", */ | |
| 60 | − /* liobn, stt, stt->window_size); */ | |
| 61 | − if (ioba >= stt->window_size) | |
| 62 | − return H_PARAMETER; | |
| 63 | − | |
| 64 | − page = stt->pages[idx / TCES_PER_PAGE]; | |
| 65 | − tbl = (u64 *)page_address(page); | |
| 66 | − | |
| 67 | − /* FIXME: Need to validate the TCE itself */ | |
| 68 | − /* udbg_printf("tce @ %p\n", &tbl[idx % TCES_PER_PAGE]); */ | |
| 69 | − tbl[idx % TCES_PER_PAGE] = tce; | |
| 70 | − return H_SUCCESS; | |
| 71 | − } | |
| 72 | − } | |
| 192 | + if (!stt) | |
| 193 | + return H_TOO_HARD; | |
| 194 | + | |
| 195 | + ret = kvmppc_ioba_validate(stt, ioba, 1); | |
| 196 | + if (ret != H_SUCCESS) | |
| 197 | + return ret; | |
| 73 | 198 | |
| 74 | − /* Didn't find the liobn, punt it to userspace */ | |
| 75 | − return H_TOO_HARD; | |
| 199 | + ret = kvmppc_tce_validate(stt, tce); | |
| 200 | + if (ret != H_SUCCESS) | |
| 201 | + return ret; | |
| 202 | + | |
| 203 | + kvmppc_tce_put(stt, ioba >> stt->page_shift, tce); | |
| 204 | + | |
| 205 | + return H_SUCCESS; | |
| 76 | 206 | } |
| 77 | 207 | EXPORT_SYMBOL_GPL(kvmppc_h_put_tce); |
| 78 | 208 | |
| 79 | −long kvmppc_h_get_tce(struct kvm_vcpu *vcpu, unsigned long liobn, | |
| 80 | − unsigned long ioba) | |
| 209 | +static long kvmppc_rm_ua_to_hpa(struct kvm_vcpu *vcpu, | |
| 210 | + unsigned long ua, unsigned long *phpa) | |
| 211 | +{ | |
| 212 | + pte_t *ptep, pte; | |
| 213 | + unsigned shift = 0; | |
| 214 | + | |
| 215 | + ptep = __find_linux_pte_or_hugepte(vcpu->arch.pgdir, ua, NULL, &shift); | |
| 216 | + if (!ptep || !pte_present(*ptep)) | |
| 217 | + return -ENXIO; | |
| 218 | + pte = *ptep; | |
| 219 | + | |
| 220 | + if (!shift) | |
| 221 | + shift = PAGE_SHIFT; | |
| 222 | + | |
| 223 | + /* Avoid handling anything potentially complicated in realmode */ | |
| 224 | + if (shift > PAGE_SHIFT) | |
| 225 | + return -EAGAIN; | |
| 226 | + | |
| 227 | + if (!pte_young(pte)) | |
| 228 | + return -EAGAIN; | |
| 229 | + | |
| 230 | + *phpa = (pte_pfn(pte) << PAGE_SHIFT) | (ua & ((1ULL << shift) - 1)) | | |
| 231 | + (ua & ~PAGE_MASK); | |
| 232 | + | |
| 233 | + return 0; | |
| 234 | +} | |
| 235 | + | |
| 236 | +long kvmppc_rm_h_put_tce_indirect(struct kvm_vcpu *vcpu, | |
| 237 | + unsigned long liobn, unsigned long ioba, | |
| 238 | + unsigned long tce_list, unsigned long npages) | |
| 81 | 239 | { |
| 82 | − struct kvm *kvm = vcpu->kvm; | |
| 83 | 240 | struct kvmppc_spapr_tce_table *stt; |
| 241 | + long i, ret = H_SUCCESS; | |
| 242 | + unsigned long tces, entry, ua = 0; | |
| 243 | + unsigned long *rmap = NULL; | |
| 244 | + | |
| 245 | + stt = kvmppc_find_table(vcpu, liobn); | |
| 246 | + if (!stt) | |
| 247 | + return H_TOO_HARD; | |
| 248 | + | |
| 249 | + entry = ioba >> stt->page_shift; | |
| 250 | + /* | |
| 251 | + * The spec says that the maximum size of the list is 512 TCEs | |
| 252 | + * so the whole table addressed resides in 4K page | |
| 253 | + */ | |
| 254 | + if (npages > 512) | |
| 255 | + return H_PARAMETER; | |
| 256 | + | |
| 257 | + if (tce_list & (SZ_4K - 1)) | |
| 258 | + return H_PARAMETER; | |
| 259 | + | |
| 260 | + ret = kvmppc_ioba_validate(stt, ioba, npages); | |
| 261 | + if (ret != H_SUCCESS) | |
| 262 | + return ret; | |
| 84 | 263 | |
| 85 | − list_for_each_entry(stt, &kvm->arch.spapr_tce_tables, list) { | |
| 86 | − if (stt->liobn == liobn) { | |
| 87 | − unsigned long idx = ioba >> SPAPR_TCE_SHIFT; | |
| 88 | − struct page *page; | |
| 89 | − u64 *tbl; | |
| 264 | + if (kvmppc_gpa_to_ua(vcpu->kvm, tce_list, &ua, &rmap)) | |
| 265 | + return H_TOO_HARD; | |
| 90 | 266 | |
| 91 | − if (ioba >= stt->window_size) | |
| 92 | − return H_PARAMETER; | |
| 267 | + rmap = (void *) vmalloc_to_phys(rmap); | |
| 93 | 268 | |
| 94 | − page = stt->pages[idx / TCES_PER_PAGE]; | |
| 95 | − tbl = (u64 *)page_address(page); | |
| 269 | + /* | |
| 270 | + * Synchronize with the MMU notifier callbacks in | |
| 271 | + * book3s_64_mmu_hv.c (kvm_unmap_hva_hv etc.). | |
| 272 | + * While we have the rmap lock, code running on other CPUs | |
| 273 | + * cannot finish unmapping the host real page that backs | |
| 274 | + * this guest real page, so we are OK to access the host | |
| 275 | + * real page. | |
| 276 | + */ | |
| 277 | + lock_rmap(rmap); | |
| 278 | + if (kvmppc_rm_ua_to_hpa(vcpu, ua, &tces)) { | |
| 279 | + ret = H_TOO_HARD; | |
| 280 | + goto unlock_exit; | |
| 281 | + } | |
| 282 | + | |
| 283 | + for (i = 0; i < npages; ++i) { | |
| 284 | + unsigned long tce = be64_to_cpu(((u64 *)tces)[i]); | |
| 285 | + | |
| 286 | + ret = kvmppc_tce_validate(stt, tce); | |
| 287 | + if (ret != H_SUCCESS) | |
| 288 | + goto unlock_exit; | |
| 96 | 289 | |
| 97 | − vcpu->arch.gpr[4] = tbl[idx % TCES_PER_PAGE]; | |
| 98 | − return H_SUCCESS; | |
| 99 | − } | |
| 290 | + kvmppc_tce_put(stt, entry + i, tce); | |
| 100 | 291 | } |
| 101 | 292 | |
| 102 | − /* Didn't find the liobn, punt it to userspace */ | |
| 103 | − return H_TOO_HARD; | |
| 293 | +unlock_exit: | |
| 294 | + unlock_rmap(rmap); | |
| 295 | + | |
| 296 | + return ret; | |
| 297 | +} | |
| 298 | + | |
| 299 | +long kvmppc_h_stuff_tce(struct kvm_vcpu *vcpu, | |
| 300 | + unsigned long liobn, unsigned long ioba, | |
| 301 | + unsigned long tce_value, unsigned long npages) | |
| 302 | +{ | |
| 303 | + struct kvmppc_spapr_tce_table *stt; | |
| 304 | + long i, ret; | |
| 305 | + | |
| 306 | + stt = kvmppc_find_table(vcpu, liobn); | |
| 307 | + if (!stt) | |
| 308 | + return H_TOO_HARD; | |
| 309 | + | |
| 310 | + ret = kvmppc_ioba_validate(stt, ioba, npages); | |
| 311 | + if (ret != H_SUCCESS) | |
| 312 | + return ret; | |
| 313 | + | |
| 314 | + /* Check permission bits only to allow userspace poison TCE for debug */ | |
| 315 | + if (tce_value & (TCE_PCI_WRITE | TCE_PCI_READ)) | |
| 316 | + return H_PARAMETER; | |
| 317 | + | |
| 318 | + for (i = 0; i < npages; ++i, ioba += (1ULL << stt->page_shift)) | |
| 319 | + kvmppc_tce_put(stt, ioba >> stt->page_shift, tce_value); | |
| 320 | + | |
| 321 | + return H_SUCCESS; | |
| 322 | +} | |
| 323 | +EXPORT_SYMBOL_GPL(kvmppc_h_stuff_tce); | |
| 324 | + | |
| 325 | +long kvmppc_h_get_tce(struct kvm_vcpu *vcpu, unsigned long liobn, | |
| 326 | + unsigned long ioba) | |
| 327 | +{ | |
| 328 | + struct kvmppc_spapr_tce_table *stt = kvmppc_find_table(vcpu, liobn); | |
| 329 | + long ret; | |
| 330 | + unsigned long idx; | |
| 331 | + struct page *page; | |
| 332 | + u64 *tbl; | |
| 333 | + | |
| 334 | + if (!stt) | |
| 335 | + return H_TOO_HARD; | |
| 336 | + | |
| 337 | + ret = kvmppc_ioba_validate(stt, ioba, 1); | |
| 338 | + if (ret != H_SUCCESS) | |
| 339 | + return ret; | |
| 340 | + | |
| 341 | + idx = (ioba >> stt->page_shift) - stt->offset; | |
| 342 | + page = stt->pages[idx / TCES_PER_PAGE]; | |
| 343 | + tbl = (u64 *)page_address(page); | |
| 344 | + | |
| 345 | + vcpu->arch.gpr[4] = tbl[idx % TCES_PER_PAGE]; | |
| 346 | + | |
| 347 | + return H_SUCCESS; | |
| 104 | 348 | } |
| 105 | 349 | EXPORT_SYMBOL_GPL(kvmppc_h_get_tce); |
| 350 | + | |
| 351 | +#endif /* KVM_BOOK3S_HV_POSSIBLE */ | |
| @@ -81,6 +81,17 @@ static int target_smt_mode; · 80 unmodified lines | ||
| 81 | 81 | module_param(target_smt_mode, int, S_IRUGO | S_IWUSR); |
| 82 | 82 | MODULE_PARM_DESC(target_smt_mode, "Target threads per core (0 = max)"); |
| 83 | 83 | |
| 84 | +#ifdef CONFIG_KVM_XICS | |
| 85 | +static struct kernel_param_ops module_param_ops = { | |
| 86 | + .set = param_set_int, | |
| 87 | + .get = param_get_int, | |
| 88 | +}; | |
| 89 | + | |
| 90 | +module_param_cb(h_ipi_redirect, &module_param_ops, &h_ipi_redirect, | |
| 91 | + S_IRUGO | S_IWUSR); | |
| 92 | +MODULE_PARM_DESC(h_ipi_redirect, "Redirect H_IPI wakeup to a free host core"); | |
| 93 | +#endif | |
| 94 | + | |
| 84 | 95 | static void kvmppc_end_cede(struct kvm_vcpu *vcpu); |
| 85 | 96 | static int kvmppc_hv_setup_htab_rma(struct kvm_vcpu *vcpu); |
| 86 | 97 | |
| @@ -768,7 +779,31 @@ int kvmppc_pseries_do_hcall(struct kvm_vcpu *vcpu) · 681 unmodified lines | ||
| 768 | 779 | if (kvmppc_xics_enabled(vcpu)) { |
| 769 | 780 | ret = kvmppc_xics_hcall(vcpu, req); |
| 770 | 781 | break; |
| 771 | − } /* fallthrough */ | |
| 782 | + } | |
| 783 | + return RESUME_HOST; | |
| 784 | + case H_PUT_TCE: | |
| 785 | + ret = kvmppc_h_put_tce(vcpu, kvmppc_get_gpr(vcpu, 4), | |
| 786 | + kvmppc_get_gpr(vcpu, 5), | |
| 787 | + kvmppc_get_gpr(vcpu, 6)); | |
| 788 | + if (ret == H_TOO_HARD) | |
| 789 | + return RESUME_HOST; | |
| 790 | + break; | |
| 791 | + case H_PUT_TCE_INDIRECT: | |
| 792 | + ret = kvmppc_h_put_tce_indirect(vcpu, kvmppc_get_gpr(vcpu, 4), | |
| 793 | + kvmppc_get_gpr(vcpu, 5), | |
| 794 | + kvmppc_get_gpr(vcpu, 6), | |
| 795 | + kvmppc_get_gpr(vcpu, 7)); | |
| 796 | + if (ret == H_TOO_HARD) | |
| 797 | + return RESUME_HOST; | |
| 798 | + break; | |
| 799 | + case H_STUFF_TCE: | |
| 800 | + ret = kvmppc_h_stuff_tce(vcpu, kvmppc_get_gpr(vcpu, 4), | |
| 801 | + kvmppc_get_gpr(vcpu, 5), | |
| 802 | + kvmppc_get_gpr(vcpu, 6), | |
| 803 | + kvmppc_get_gpr(vcpu, 7)); | |
| 804 | + if (ret == H_TOO_HARD) | |
| 805 | + return RESUME_HOST; | |
| 806 | + break; | |
| 772 | 807 | default: |
| 773 | 808 | return RESUME_HOST; |
| 774 | 809 | } |
| @@ -2278,6 +2313,46 @@ static void post_guest_process(struct kvmppc_vcore *vc, bool is_master) · 1503 unmodified lines | ||
| 2278 | 2313 | spin_unlock(&vc->lock); |
| 2279 | 2314 | } |
| 2280 | 2315 | |
| 2316 | +/* | |
| 2317 | + * Clear core from the list of active host cores as we are about to | |
| 2318 | + * enter the guest. Only do this if it is the primary thread of the | |
| 2319 | + * core (not if a subcore) that is entering the guest. | |
| 2320 | + */ | |
| 2321 | +static inline void kvmppc_clear_host_core(int cpu) | |
| 2322 | +{ | |
| 2323 | + int core; | |
| 2324 | + | |
| 2325 | + if (!kvmppc_host_rm_ops_hv || cpu_thread_in_core(cpu)) | |
| 2326 | + return; | |
| 2327 | + /* | |
| 2328 | + * Memory barrier can be omitted here as we will do a smp_wmb() | |
| 2329 | + * later in kvmppc_start_thread and we need ensure that state is | |
| 2330 | + * visible to other CPUs only after we enter guest. | |
| 2331 | + */ | |
| 2332 | + core = cpu >> threads_shift; | |
| 2333 | + kvmppc_host_rm_ops_hv->rm_core[core].rm_state.in_host = 0; | |
| 2334 | +} | |
| 2335 | + | |
| 2336 | +/* | |
| 2337 | + * Advertise this core as an active host core since we exited the guest | |
| 2338 | + * Only need to do this if it is the primary thread of the core that is | |
| 2339 | + * exiting. | |
| 2340 | + */ | |
| 2341 | +static inline void kvmppc_set_host_core(int cpu) | |
| 2342 | +{ | |
| 2343 | + int core; | |
| 2344 | + | |
| 2345 | + if (!kvmppc_host_rm_ops_hv || cpu_thread_in_core(cpu)) | |
| 2346 | + return; | |
| 2347 | + | |
| 2348 | + /* | |
| 2349 | + * Memory barrier can be omitted here because we do a spin_unlock | |
| 2350 | + * immediately after this which provides the memory barrier. | |
| 2351 | + */ | |
| 2352 | + core = cpu >> threads_shift; | |
| 2353 | + kvmppc_host_rm_ops_hv->rm_core[core].rm_state.in_host = 1; | |
| 2354 | +} | |
| 2355 | + | |
| 2281 | 2356 | /* |
| 2282 | 2357 | * Run a set of guest threads on a physical core. |
| 2283 | 2358 | * Called with vc->lock held. |
| @@ -2390,6 +2465,8 @@ static noinline void kvmppc_run_core(struct kvmppc_vcore *vc) · 106 unmodified lines | ||
| 2390 | 2465 | } |
| 2391 | 2466 | } |
| 2392 | 2467 | |
| 2468 | + kvmppc_clear_host_core(pcpu); | |
| 2469 | + | |
| 2393 | 2470 | /* Start all the threads */ |
| 2394 | 2471 | active = 0; |
| 2395 | 2472 | for (sub = 0; sub < core_info.n_subcores; ++sub) { |
| @@ -2486,6 +2563,8 @@ static noinline void kvmppc_run_core(struct kvmppc_vcore *vc) · 90 unmodified lines | ||
| 2486 | 2563 | kvmppc_ipi_thread(pcpu + i); |
| 2487 | 2564 | } |
| 2488 | 2565 | |
| 2566 | + kvmppc_set_host_core(pcpu); | |
| 2567 | + | |
| 2489 | 2568 | spin_unlock(&vc->lock); |
| 2490 | 2569 | |
| 2491 | 2570 | /* make sure updates to secondary vcpu structs are visible now */ |
| @@ -2984,6 +3063,114 @@ static int kvmppc_hv_setup_htab_rma(struct kvm_vcpu *vcpu) · 492 unmodified lines | ||
| 2984 | 3063 | goto out_srcu; |
| 2985 | 3064 | } |
| 2986 | 3065 | |
| 3066 | +#ifdef CONFIG_KVM_XICS | |
| 3067 | +static int kvmppc_cpu_notify(struct notifier_block *self, unsigned long action, | |
| 3068 | + void *hcpu) | |
| 3069 | +{ | |
| 3070 | + unsigned long cpu = (long)hcpu; | |
| 3071 | + | |
| 3072 | + switch (action) { | |
| 3073 | + case CPU_UP_PREPARE: | |
| 3074 | + case CPU_UP_PREPARE_FROZEN: | |
| 3075 | + kvmppc_set_host_core(cpu); | |
| 3076 | + break; | |
| 3077 | + | |
| 3078 | +#ifdef CONFIG_HOTPLUG_CPU | |
| 3079 | + case CPU_DEAD: | |
| 3080 | + case CPU_DEAD_FROZEN: | |
| 3081 | + case CPU_UP_CANCELED: | |
| 3082 | + case CPU_UP_CANCELED_FROZEN: | |
| 3083 | + kvmppc_clear_host_core(cpu); | |
| 3084 | + break; | |
| 3085 | +#endif | |
| 3086 | + default: | |
| 3087 | + break; | |
| 3088 | + } | |
| 3089 | + | |
| 3090 | + return NOTIFY_OK; | |
| 3091 | +} | |
| 3092 | + | |
| 3093 | +static struct notifier_block kvmppc_cpu_notifier = { | |
| 3094 | + .notifier_call = kvmppc_cpu_notify, | |
| 3095 | +}; | |
| 3096 | + | |
| 3097 | +/* | |
| 3098 | + * Allocate a per-core structure for managing state about which cores are | |
| 3099 | + * running in the host versus the guest and for exchanging data between | |
| 3100 | + * real mode KVM and CPU running in the host. | |
| 3101 | + * This is only done for the first VM. | |
| 3102 | + * The allocated structure stays even if all VMs have stopped. | |
| 3103 | + * It is only freed when the kvm-hv module is unloaded. | |
| 3104 | + * It's OK for this routine to fail, we just don't support host | |
| 3105 | + * core operations like redirecting H_IPI wakeups. | |
| 3106 | + */ | |
| 3107 | +void kvmppc_alloc_host_rm_ops(void) | |
| 3108 | +{ | |
| 3109 | + struct kvmppc_host_rm_ops *ops; | |
| 3110 | + unsigned long l_ops; | |
| 3111 | + int cpu, core; | |
| 3112 | + int size; | |
| 3113 | + | |
| 3114 | + /* Not the first time here ? */ | |
| 3115 | + if (kvmppc_host_rm_ops_hv != NULL) | |
| 3116 | + return; | |
| 3117 | + | |
| 3118 | + ops = kzalloc(sizeof(struct kvmppc_host_rm_ops), GFP_KERNEL); | |
| 3119 | + if (!ops) | |
| 3120 | + return; | |
| 3121 | + | |
| 3122 | + size = cpu_nr_cores() * sizeof(struct kvmppc_host_rm_core); | |
| 3123 | + ops->rm_core = kzalloc(size, GFP_KERNEL); | |
| 3124 | + | |
| 3125 | + if (!ops->rm_core) { | |
| 3126 | + kfree(ops); | |
| 3127 | + return; | |
| 3128 | + } | |
| 3129 | + | |
| 3130 | + get_online_cpus(); | |
| 3131 | + | |
| 3132 | + for (cpu = 0; cpu < nr_cpu_ids; cpu += threads_per_core) { | |
| 3133 | + if (!cpu_online(cpu)) | |
| 3134 | + continue; | |
| 3135 | + | |
| 3136 | + core = cpu >> threads_shift; | |
| 3137 | + ops->rm_core[core].rm_state.in_host = 1; | |
| 3138 | + } | |
| 3139 | + | |
| 3140 | + ops->vcpu_kick = kvmppc_fast_vcpu_kick_hv; | |
| 3141 | + | |
| 3142 | + /* | |
| 3143 | + * Make the contents of the kvmppc_host_rm_ops structure visible | |
| 3144 | + * to other CPUs before we assign it to the global variable. | |
| 3145 | + * Do an atomic assignment (no locks used here), but if someone | |
| 3146 | + * beats us to it, just free our copy and return. | |
| 3147 | + */ | |
| 3148 | + smp_wmb(); | |
| 3149 | + l_ops = (unsigned long) ops; | |
| 3150 | + | |
| 3151 | + if (cmpxchg64((unsigned long *)&kvmppc_host_rm_ops_hv, 0, l_ops)) { | |
| 3152 | + put_online_cpus(); | |
| 3153 | + kfree(ops->rm_core); | |
| 3154 | + kfree(ops); | |
| 3155 | + return; | |
| 3156 | + } | |
| 3157 | + | |
| 3158 | + register_cpu_notifier(&kvmppc_cpu_notifier); | |
| 3159 | + | |
| 3160 | + put_online_cpus(); | |
| 3161 | +} | |
| 3162 | + | |
| 3163 | +void kvmppc_free_host_rm_ops(void) | |
| 3164 | +{ | |
| 3165 | + if (kvmppc_host_rm_ops_hv) { | |
| 3166 | + unregister_cpu_notifier(&kvmppc_cpu_notifier); | |
| 3167 | + kfree(kvmppc_host_rm_ops_hv->rm_core); | |
| 3168 | + kfree(kvmppc_host_rm_ops_hv); | |
| 3169 | + kvmppc_host_rm_ops_hv = NULL; | |
| 3170 | + } | |
| 3171 | +} | |
| 3172 | +#endif | |
| 3173 | + | |
| 2987 | 3174 | static int kvmppc_core_init_vm_hv(struct kvm *kvm) |
| 2988 | 3175 | { |
| 2989 | 3176 | unsigned long lpcr, lpid; |
| @@ -2996,6 +3183,8 @@ static int kvmppc_core_init_vm_hv(struct kvm *kvm) · 6 unmodified lines | ||
| 2996 | 3183 | return -ENOMEM; |
| 2997 | 3184 | kvm->arch.lpid = lpid; |
| 2998 | 3185 | |
| 3186 | + kvmppc_alloc_host_rm_ops(); | |
| 3187 | + | |
| 2999 | 3188 | /* |
| 3000 | 3189 | * Since we don't flush the TLB when tearing down a VM, |
| 3001 | 3190 | * and this lpid might have previously been used, |
| @@ -3229,6 +3418,7 @@ static int kvmppc_book3s_init_hv(void) · 227 unmodified lines | ||
| 3229 | 3418 | |
| 3230 | 3419 | static void kvmppc_book3s_exit_hv(void) |
| 3231 | 3420 | { |
| 3421 | + kvmppc_free_host_rm_ops(); | |
| 3232 | 3422 | kvmppc_hv_ops = NULL; |
| 3233 | 3423 | } |
| 3234 | 3424 | |
| @@ -283,3 +283,6 @@ void kvmhv_commence_exit(int trap) · 282 unmodified lines | ||
| 283 | 283 | kvmhv_interrupt_vcore(vc, ee); |
| 284 | 284 | } |
| 285 | 285 | } |
| 286 | + | |
| 287 | +struct kvmppc_host_rm_ops *kvmppc_host_rm_ops_hv; | |
| 288 | +EXPORT_SYMBOL_GPL(kvmppc_host_rm_ops_hv); | |
| @@ -17,12 +17,16 @@ · 16 unmodified lines | ||
| 17 | 17 | #include <asm/xics.h> |
| 18 | 18 | #include <asm/debug.h> |
| 19 | 19 | #include <asm/synch.h> |
| 20 | +#include <asm/cputhreads.h> | |
| 20 | 21 | #include <asm/ppc-opcode.h> |
| 21 | 22 | |
| 22 | 23 | #include "book3s_xics.h" |
| 23 | 24 | |
| 24 | 25 | #define DEBUG_PASSUP |
| 25 | 26 | |
| 27 | +int h_ipi_redirect = 1; | |
| 28 | +EXPORT_SYMBOL(h_ipi_redirect); | |
| 29 | + | |
| 26 | 30 | static void icp_rm_deliver_irq(struct kvmppc_xics *xics, struct kvmppc_icp *icp, |
| 27 | 31 | u32 new_irq); |
| 28 | 32 | |
| @@ -50,11 +54,84 @@ static void ics_rm_check_resend(struct kvmppc_xics *xics, · 21 unmodified lines | ||
| 50 | 54 | |
| 51 | 55 | /* -- ICP routines -- */ |
| 52 | 56 | |
| 57 | +#ifdef CONFIG_SMP | |
| 58 | +static inline void icp_send_hcore_msg(int hcore, struct kvm_vcpu *vcpu) | |
| 59 | +{ | |
| 60 | + int hcpu; | |
| 61 | + | |
| 62 | + hcpu = hcore << threads_shift; | |
| 63 | + kvmppc_host_rm_ops_hv->rm_core[hcore].rm_data = vcpu; | |
| 64 | + smp_muxed_ipi_set_message(hcpu, PPC_MSG_RM_HOST_ACTION); | |
| 65 | + icp_native_cause_ipi_rm(hcpu); | |
| 66 | +} | |
| 67 | +#else | |
| 68 | +static inline void icp_send_hcore_msg(int hcore, struct kvm_vcpu *vcpu) { } | |
| 69 | +#endif | |
| 70 | + | |
| 71 | +/* | |
| 72 | + * We start the search from our current CPU Id in the core map | |
| 73 | + * and go in a circle until we get back to our ID looking for a | |
| 74 | + * core that is running in host context and that hasn't already | |
| 75 | + * been targeted for another rm_host_ops. | |
| 76 | + * | |
| 77 | + * In the future, could consider using a fairer algorithm (one | |
| 78 | + * that distributes the IPIs better) | |
| 79 | + * | |
| 80 | + * Returns -1, if no CPU could be found in the host | |
| 81 | + * Else, returns a CPU Id which has been reserved for use | |
| 82 | + */ | |
| 83 | +static inline int grab_next_hostcore(int start, | |
| 84 | + struct kvmppc_host_rm_core *rm_core, int max, int action) | |
| 85 | +{ | |
| 86 | + bool success; | |
| 87 | + int core; | |
| 88 | + union kvmppc_rm_state old, new; | |
| 89 | + | |
| 90 | + for (core = start + 1; core < max; core++) { | |
| 91 | + old = new = READ_ONCE(rm_core[core].rm_state); | |
| 92 | + | |
| 93 | + if (!old.in_host || old.rm_action) | |
| 94 | + continue; | |
| 95 | + | |
| 96 | + /* Try to grab this host core if not taken already. */ | |
| 97 | + new.rm_action = action; | |
| 98 | + | |
| 99 | + success = cmpxchg64(&rm_core[core].rm_state.raw, | |
| 100 | + old.raw, new.raw) == old.raw; | |
| 101 | + if (success) { | |
| 102 | + /* | |
| 103 | + * Make sure that the store to the rm_action is made | |
| 104 | + * visible before we return to caller (and the | |
| 105 | + * subsequent store to rm_data) to synchronize with | |
| 106 | + * the IPI handler. | |
| 107 | + */ | |
| 108 | + smp_wmb(); | |
| 109 | + return core; | |
| 110 | + } | |
| 111 | + } | |
| 112 | + | |
| 113 | + return -1; | |
| 114 | +} | |
| 115 | + | |
| 116 | +static inline int find_available_hostcore(int action) | |
| 117 | +{ | |
| 118 | + int core; | |
| 119 | + int my_core = smp_processor_id() >> threads_shift; | |
| 120 | + struct kvmppc_host_rm_core *rm_core = kvmppc_host_rm_ops_hv->rm_core; | |
| 121 | + | |
| 122 | + core = grab_next_hostcore(my_core, rm_core, cpu_nr_cores(), action); | |
| 123 | + if (core == -1) | |
| 124 | + core = grab_next_hostcore(core, rm_core, my_core, action); | |
| 125 | + | |
| 126 | + return core; | |
| 127 | +} | |
| 128 | + | |
| 53 | 129 | static void icp_rm_set_vcpu_irq(struct kvm_vcpu *vcpu, |
| 54 | 130 | struct kvm_vcpu *this_vcpu) |
| 55 | 131 | { |
| 56 | 132 | struct kvmppc_icp *this_icp = this_vcpu->arch.icp; |
| 57 | 133 | int cpu; |
| 134 | + int hcore; | |
| 58 | 135 | |
| 59 | 136 | /* Mark the target VCPU as having an interrupt pending */ |
| 60 | 137 | vcpu->stat.queue_intr++; |
| @@ -66,11 +143,22 @@ static void icp_rm_set_vcpu_irq(struct kvm_vcpu *vcpu, · 5 unmodified lines | ||
| 66 | 143 | return; |
| 67 | 144 | } |
| 68 | 145 | |
| 69 | − /* Check if the core is loaded, if not, too hard */ | |
| 146 | + /* | |
| 147 | + * Check if the core is loaded, | |
| 148 | + * if not, find an available host core to post to wake the VCPU, | |
| 149 | + * if we can't find one, set up state to eventually return too hard. | |
| 150 | + */ | |
| 70 | 151 | cpu = vcpu->arch.thread_cpu; |
| 71 | 152 | if (cpu < 0 || cpu >= nr_cpu_ids) { |
| 72 | − this_icp->rm_action |= XICS_RM_KICK_VCPU; | |
| 73 | − this_icp->rm_kick_target = vcpu; | |
| 153 | + hcore = -1; | |
| 154 | + if (kvmppc_host_rm_ops_hv && h_ipi_redirect) | |
| 155 | + hcore = find_available_hostcore(XICS_RM_KICK_VCPU); | |
| 156 | + if (hcore != -1) { | |
| 157 | + icp_send_hcore_msg(hcore, vcpu); | |
| 158 | + } else { | |
| 159 | + this_icp->rm_action |= XICS_RM_KICK_VCPU; | |
| 160 | + this_icp->rm_kick_target = vcpu; | |
| 161 | + } | |
| 74 | 162 | return; |
| 75 | 163 | } |
| 76 | 164 | |
| @@ -623,3 +711,40 @@ int kvmppc_rm_h_eoi(struct kvm_vcpu *vcpu, unsigned long xirr) · 546 unmodified lines | ||
| 623 | 711 | bail: |
| 624 | 712 | return check_too_hard(xics, icp); |
| 625 | 713 | } |
| 714 | + | |
| 715 | +/* --- Non-real mode XICS-related built-in routines --- */ | |
| 716 | + | |
| 717 | +/** | |
| 718 | + * Host Operations poked by RM KVM | |
| 719 | + */ | |
| 720 | +static void rm_host_ipi_action(int action, void *data) | |
| 721 | +{ | |
| 722 | + switch (action) { | |
| 723 | + case XICS_RM_KICK_VCPU: | |
| 724 | + kvmppc_host_rm_ops_hv->vcpu_kick(data); | |
| 725 | + break; | |
| 726 | + default: | |
| 727 | + WARN(1, "Unexpected rm_action=%d data=%p\n", action, data); | |
| 728 | + break; | |
| 729 | + } | |
| 730 | + | |
| 731 | +} | |
| 732 | + | |
| 733 | +void kvmppc_xics_ipi_action(void) | |
| 734 | +{ | |
| 735 | + int core; | |
| 736 | + unsigned int cpu = smp_processor_id(); | |
| 737 | + struct kvmppc_host_rm_core *rm_corep; | |
| 738 | + | |
| 739 | + core = cpu >> threads_shift; | |
| 740 | + rm_corep = &kvmppc_host_rm_ops_hv->rm_core[core]; | |
| 741 | + | |
| 742 | + if (rm_corep->rm_data) { | |
| 743 | + rm_host_ipi_action(rm_corep->rm_state.rm_action, | |
| 744 | + rm_corep->rm_data); | |
| 745 | + /* Order these stores against the real mode KVM */ | |
| 746 | + rm_corep->rm_data = NULL; | |
| 747 | + smp_wmb(); | |
| 748 | + rm_corep->rm_state.rm_action = 0; | |
| 749 | + } | |
| 750 | +} | |
| @@ -2006,8 +2006,8 @@ hcall_real_table: · 2005 unmodified lines | ||
| 2006 | 2006 | .long 0 /* 0x12c */ |
| 2007 | 2007 | .long 0 /* 0x130 */ |
| 2008 | 2008 | .long DOTSYM(kvmppc_h_set_xdabr) - hcall_real_table |
| 2009 | − .long 0 /* 0x138 */ | |
| 2010 | − .long 0 /* 0x13c */ | |
| 2009 | + .long DOTSYM(kvmppc_h_stuff_tce) - hcall_real_table | |
| 2010 | + .long DOTSYM(kvmppc_rm_h_put_tce_indirect) - hcall_real_table | |
| 2011 | 2011 | .long 0 /* 0x140 */ |
| 2012 | 2012 | .long 0 /* 0x144 */ |
| 2013 | 2013 | .long 0 /* 0x148 */ |
| @@ -280,6 +280,37 @@ static int kvmppc_h_pr_logical_ci_store(struct kvm_vcpu *vcpu) · 279 unmodified lines | ||
| 280 | 280 | return EMULATE_DONE; |
| 281 | 281 | } |
| 282 | 282 | |
| 283 | +static int kvmppc_h_pr_put_tce_indirect(struct kvm_vcpu *vcpu) | |
| 284 | +{ | |
| 285 | + unsigned long liobn = kvmppc_get_gpr(vcpu, 4); | |
| 286 | + unsigned long ioba = kvmppc_get_gpr(vcpu, 5); | |
| 287 | + unsigned long tce = kvmppc_get_gpr(vcpu, 6); | |
| 288 | + unsigned long npages = kvmppc_get_gpr(vcpu, 7); | |
| 289 | + long rc; | |
| 290 | + | |
| 291 | + rc = kvmppc_h_put_tce_indirect(vcpu, liobn, ioba, | |
| 292 | + tce, npages); | |
| 293 | + if (rc == H_TOO_HARD) | |
| 294 | + return EMULATE_FAIL; | |
| 295 | + kvmppc_set_gpr(vcpu, 3, rc); | |
| 296 | + return EMULATE_DONE; | |
| 297 | +} | |
| 298 | + | |
| 299 | +static int kvmppc_h_pr_stuff_tce(struct kvm_vcpu *vcpu) | |
| 300 | +{ | |
| 301 | + unsigned long liobn = kvmppc_get_gpr(vcpu, 4); | |
| 302 | + unsigned long ioba = kvmppc_get_gpr(vcpu, 5); | |
| 303 | + unsigned long tce_value = kvmppc_get_gpr(vcpu, 6); | |
| 304 | + unsigned long npages = kvmppc_get_gpr(vcpu, 7); | |
| 305 | + long rc; | |
| 306 | + | |
| 307 | + rc = kvmppc_h_stuff_tce(vcpu, liobn, ioba, tce_value, npages); | |
| 308 | + if (rc == H_TOO_HARD) | |
| 309 | + return EMULATE_FAIL; | |
| 310 | + kvmppc_set_gpr(vcpu, 3, rc); | |
| 311 | + return EMULATE_DONE; | |
| 312 | +} | |
| 313 | + | |
| 283 | 314 | static int kvmppc_h_pr_xics_hcall(struct kvm_vcpu *vcpu, u32 cmd) |
| 284 | 315 | { |
| 285 | 316 | long rc = kvmppc_xics_hcall(vcpu, cmd); |
| @@ -306,6 +337,10 @@ int kvmppc_h_pr(struct kvm_vcpu *vcpu, unsigned long cmd) · 20 unmodified lines | ||
| 306 | 337 | return kvmppc_h_pr_bulk_remove(vcpu); |
| 307 | 338 | case H_PUT_TCE: |
| 308 | 339 | return kvmppc_h_pr_put_tce(vcpu); |
| 340 | + case H_PUT_TCE_INDIRECT: | |
| 341 | + return kvmppc_h_pr_put_tce_indirect(vcpu); | |
| 342 | + case H_STUFF_TCE: | |
| 343 | + return kvmppc_h_pr_stuff_tce(vcpu); | |
| 309 | 344 | case H_CEDE: |
| 310 | 345 | kvmppc_set_msr_fast(vcpu, kvmppc_get_msr(vcpu) | MSR_EE); |
| 311 | 346 | kvm_vcpu_block(vcpu); |
| @@ -33,6 +33,7 @@ · 32 unmodified lines | ||
| 33 | 33 | #include <asm/tlbflush.h> |
| 34 | 34 | #include <asm/cputhreads.h> |
| 35 | 35 | #include <asm/irqflags.h> |
| 36 | +#include <asm/iommu.h> | |
| 36 | 37 | #include "timing.h" |
| 37 | 38 | #include "irq.h" |
| 38 | 39 | #include "../mm/mmu_decl.h" |
| @@ -437,6 +438,16 @@ void kvm_arch_destroy_vm(struct kvm *kvm) · 398 unmodified lines | ||
| 437 | 438 | unsigned int i; |
| 438 | 439 | struct kvm_vcpu *vcpu; |
| 439 | 440 | |
| 441 | +#ifdef CONFIG_KVM_XICS | |
| 442 | + /* | |
| 443 | + * We call kick_all_cpus_sync() to ensure that all | |
| 444 | + * CPUs have executed any pending IPIs before we | |
| 445 | + * continue and free VCPUs structures below. | |
| 446 | + */ | |
| 447 | + if (is_kvmppc_hv_enabled(kvm)) | |
| 448 | + kick_all_cpus_sync(); | |
| 449 | +#endif | |
| 450 | + | |
| 440 | 451 | kvm_for_each_vcpu(i, vcpu, kvm) |
| 441 | 452 | kvm_arch_vcpu_free(vcpu); |
| 442 | 453 | |
| @@ -509,6 +520,7 @@ int kvm_vm_ioctl_check_extension(struct kvm *kvm, long ext) · 66 unmodified lines | ||
| 509 | 520 | |
| 510 | 521 | #ifdef CONFIG_PPC_BOOK3S_64 |
| 511 | 522 | case KVM_CAP_SPAPR_TCE: |
| 523 | + case KVM_CAP_SPAPR_TCE_64: | |
| 512 | 524 | case KVM_CAP_PPC_ALLOC_HTAB: |
| 513 | 525 | case KVM_CAP_PPC_RTAS: |
| 514 | 526 | case KVM_CAP_PPC_FIXUP_HCALL: |
| @@ -569,6 +581,9 @@ int kvm_vm_ioctl_check_extension(struct kvm *kvm, long ext) · 54 unmodified lines | ||
| 569 | 581 | case KVM_CAP_PPC_GET_SMMU_INFO: |
| 570 | 582 | r = 1; |
| 571 | 583 | break; |
| 584 | + case KVM_CAP_SPAPR_MULTITCE: | |
| 585 | + r = 1; | |
| 586 | + break; | |
| 572 | 587 | #endif |
| 573 | 588 | default: |
| 574 | 589 | r = 0; |
| @@ -1331,13 +1346,34 @@ long kvm_arch_vm_ioctl(struct file *filp, · 756 unmodified lines | ||
| 1331 | 1346 | break; |
| 1332 | 1347 | } |
| 1333 | 1348 | #ifdef CONFIG_PPC_BOOK3S_64 |
| 1349 | + case KVM_CREATE_SPAPR_TCE_64: { | |
| 1350 | + struct kvm_create_spapr_tce_64 create_tce_64; | |
| 1351 | + | |
| 1352 | + r = -EFAULT; | |
| 1353 | + if (copy_from_user(&create_tce_64, argp, sizeof(create_tce_64))) | |
| 1354 | + goto out; | |
| 1355 | + if (create_tce_64.flags) { | |
| 1356 | + r = -EINVAL; | |
| 1357 | + goto out; | |
| 1358 | + } | |
| 1359 | + r = kvm_vm_ioctl_create_spapr_tce(kvm, &create_tce_64); | |
| 1360 | + goto out; | |
| 1361 | + } | |
| 1334 | 1362 | case KVM_CREATE_SPAPR_TCE: { |
| 1335 | 1363 | struct kvm_create_spapr_tce create_tce; |
| 1364 | + struct kvm_create_spapr_tce_64 create_tce_64; | |
| 1336 | 1365 | |
| 1337 | 1366 | r = -EFAULT; |
| 1338 | 1367 | if (copy_from_user(&create_tce, argp, sizeof(create_tce))) |
| 1339 | 1368 | goto out; |
| 1340 | − r = kvm_vm_ioctl_create_spapr_tce(kvm, &create_tce); | |
| 1369 | + | |
| 1370 | + create_tce_64.liobn = create_tce.liobn; | |
| 1371 | + create_tce_64.page_shift = IOMMU_PAGE_SHIFT_4K; | |
| 1372 | + create_tce_64.offset = 0; | |
| 1373 | + create_tce_64.size = create_tce.window_size >> | |
| 1374 | + IOMMU_PAGE_SHIFT_4K; | |
| 1375 | + create_tce_64.flags = 0; | |
| 1376 | + r = kvm_vm_ioctl_create_spapr_tce(kvm, &create_tce_64); | |
| 1341 | 1377 | goto out; |
| 1342 | 1378 | } |
| 1343 | 1379 | case KVM_PPC_GET_SMMU_INFO: { |
| @@ -243,3 +243,11 @@ void assert_pte_locked(struct mm_struct *mm, unsigned long addr) · 242 unmodified lines | ||
| 243 | 243 | } |
| 244 | 244 | #endif /* CONFIG_DEBUG_VM */ |
| 245 | 245 | |
| 246 | +unsigned long vmalloc_to_phys(void *va) | |
| 247 | +{ | |
| 248 | + unsigned long pfn = vmalloc_to_pfn(va); | |
| 249 | + | |
| 250 | + BUG_ON(!pfn); | |
| 251 | + return __pa(pfn_to_kaddr(pfn)) + offset_in_page(va); | |
| 252 | +} | |
| 253 | +EXPORT_SYMBOL_GPL(vmalloc_to_phys); | |
| @@ -493,14 +493,6 @@ static size_t event_to_attr_ct(struct hv_24x7_event_data *event) · 492 unmodified lines | ||
| 493 | 493 | } |
| 494 | 494 | } |
| 495 | 495 | |
| 496 | −static unsigned long vmalloc_to_phys(void *v) | |
| 497 | −{ | |
| 498 | − struct page *p = vmalloc_to_page(v); | |
| 499 | − | |
| 500 | − BUG_ON(!p); | |
| 501 | − return page_to_phys(p) + offset_in_page(v); | |
| 502 | −} | |
| 503 | − | |
| 504 | 496 | /* */ |
| 505 | 497 | struct event_uniq { |
| 506 | 498 | struct rb_node node; |
| @@ -159,6 +159,27 @@ static void icp_native_cause_ipi(int cpu, unsigned long data) · 158 unmodified lines | ||
| 159 | 159 | icp_native_set_qirr(cpu, IPI_PRIORITY); |
| 160 | 160 | } |
| 161 | 161 | |
| 162 | +#ifdef CONFIG_KVM_BOOK3S_HV_POSSIBLE | |
| 163 | +void icp_native_cause_ipi_rm(int cpu) | |
| 164 | +{ | |
| 165 | + /* | |
| 166 | + * Currently not used to send IPIs to another CPU | |
| 167 | + * on the same core. Only caller is KVM real mode. | |
| 168 | + * Need the physical address of the XICS to be | |
| 169 | + * previously saved in kvm_hstate in the paca. | |
| 170 | + */ | |
| 171 | + unsigned long xics_phys; | |
| 172 | + | |
| 173 | + /* | |
| 174 | + * Just like the cause_ipi functions, it is required to | |
| 175 | + * include a full barrier (out8 includes a sync) before | |
| 176 | + * causing the IPI. | |
| 177 | + */ | |
| 178 | + xics_phys = paca[cpu].kvm_hstate.xics_phys; | |
| 179 | + out_rm8((u8 *)(xics_phys + XICS_MFRR), IPI_PRIORITY); | |
| 180 | +} | |
| 181 | +#endif | |
| 182 | + | |
| 162 | 183 | /* |
| 163 | 184 | * Called when an interrupt is received on an off-line CPU to |
| 164 | 185 | * clear the interrupt, so that the CPU can go back to nap mode. |
| @@ -862,6 +862,7 @@ struct kvm_ppc_smmu_info { · 861 unmodified lines | ||
| 862 | 862 | #define KVM_CAP_IOEVENTFD_ANY_LENGTH 122 |
| 863 | 863 | #define KVM_CAP_HYPERV_SYNIC 123 |
| 864 | 864 | #define KVM_CAP_S390_RI 124 |
| 865 | +#define KVM_CAP_SPAPR_TCE_64 125 | |
| 865 | 866 | |
| 866 | 867 | #ifdef KVM_CAP_IRQ_ROUTING |
| 867 | 868 | |
| @@ -1154,6 +1155,8 @@ struct kvm_s390_ucas_mapping { · 286 unmodified lines | ||
| 1154 | 1155 | /* Available with KVM_CAP_PPC_ALLOC_HTAB */ |
| 1155 | 1156 | #define KVM_PPC_ALLOCATE_HTAB _IOWR(KVMIO, 0xa7, __u32) |
| 1156 | 1157 | #define KVM_CREATE_SPAPR_TCE _IOW(KVMIO, 0xa8, struct kvm_create_spapr_tce) |
| 1158 | +#define KVM_CREATE_SPAPR_TCE_64 _IOW(KVMIO, 0xa8, \ | |
| 1159 | + struct kvm_create_spapr_tce_64) | |
| 1157 | 1160 | /* Available with KVM_CAP_RMA */ |
| 1158 | 1161 | #define KVM_ALLOCATE_RMA _IOR(KVMIO, 0xa9, struct kvm_allocate_rma) |
| 1159 | 1162 | /* Available with KVM_CAP_PPC_HTAB_FD */ |