diff options
-rw-r--r-- | arch/powerpc/kernel/asm-offsets.c | 3 | ||||
-rw-r--r-- | arch/powerpc/kvm/book3s_hv.c | 51 | ||||
-rw-r--r-- | arch/powerpc/kvm/book3s_hv_builtin.c | 16 | ||||
-rw-r--r-- | arch/powerpc/kvm/book3s_hv_rmhandlers.S | 22 |
4 files changed, 70 insertions, 22 deletions
diff --git a/arch/powerpc/kernel/asm-offsets.c b/arch/powerpc/kernel/asm-offsets.c index 0d07efbe3fa7..0034b6b3556a 100644 --- a/arch/powerpc/kernel/asm-offsets.c +++ b/arch/powerpc/kernel/asm-offsets.c | |||
@@ -37,6 +37,7 @@ | |||
37 | #include <asm/thread_info.h> | 37 | #include <asm/thread_info.h> |
38 | #include <asm/rtas.h> | 38 | #include <asm/rtas.h> |
39 | #include <asm/vdso_datapage.h> | 39 | #include <asm/vdso_datapage.h> |
40 | #include <asm/dbell.h> | ||
40 | #ifdef CONFIG_PPC64 | 41 | #ifdef CONFIG_PPC64 |
41 | #include <asm/paca.h> | 42 | #include <asm/paca.h> |
42 | #include <asm/lppaca.h> | 43 | #include <asm/lppaca.h> |
@@ -759,5 +760,7 @@ int main(void) | |||
759 | offsetof(struct paca_struct, subcore_sibling_mask)); | 760 | offsetof(struct paca_struct, subcore_sibling_mask)); |
760 | #endif | 761 | #endif |
761 | 762 | ||
763 | DEFINE(PPC_DBELL_SERVER, PPC_DBELL_SERVER); | ||
764 | |||
762 | return 0; | 765 | return 0; |
763 | } | 766 | } |
diff --git a/arch/powerpc/kvm/book3s_hv.c b/arch/powerpc/kvm/book3s_hv.c index ea1600ff52b2..48d3c5d2ecc9 100644 --- a/arch/powerpc/kvm/book3s_hv.c +++ b/arch/powerpc/kvm/book3s_hv.c | |||
@@ -51,6 +51,7 @@ | |||
51 | #include <asm/hvcall.h> | 51 | #include <asm/hvcall.h> |
52 | #include <asm/switch_to.h> | 52 | #include <asm/switch_to.h> |
53 | #include <asm/smp.h> | 53 | #include <asm/smp.h> |
54 | #include <asm/dbell.h> | ||
54 | #include <linux/gfp.h> | 55 | #include <linux/gfp.h> |
55 | #include <linux/vmalloc.h> | 56 | #include <linux/vmalloc.h> |
56 | #include <linux/highmem.h> | 57 | #include <linux/highmem.h> |
@@ -84,9 +85,35 @@ static DECLARE_BITMAP(default_enabled_hcalls, MAX_HCALL_OPCODE/4 + 1); | |||
84 | static void kvmppc_end_cede(struct kvm_vcpu *vcpu); | 85 | static void kvmppc_end_cede(struct kvm_vcpu *vcpu); |
85 | static int kvmppc_hv_setup_htab_rma(struct kvm_vcpu *vcpu); | 86 | static int kvmppc_hv_setup_htab_rma(struct kvm_vcpu *vcpu); |
86 | 87 | ||
88 | static bool kvmppc_ipi_thread(int cpu) | ||
89 | { | ||
90 | /* On POWER8 for IPIs to threads in the same core, use msgsnd */ | ||
91 | if (cpu_has_feature(CPU_FTR_ARCH_207S)) { | ||
92 | preempt_disable(); | ||
93 | if (cpu_first_thread_sibling(cpu) == | ||
94 | cpu_first_thread_sibling(smp_processor_id())) { | ||
95 | unsigned long msg = PPC_DBELL_TYPE(PPC_DBELL_SERVER); | ||
96 | msg |= cpu_thread_in_core(cpu); | ||
97 | smp_mb(); | ||
98 | __asm__ __volatile__ (PPC_MSGSND(%0) : : "r" (msg)); | ||
99 | preempt_enable(); | ||
100 | return true; | ||
101 | } | ||
102 | preempt_enable(); | ||
103 | } | ||
104 | |||
105 | #if defined(CONFIG_PPC_ICP_NATIVE) && defined(CONFIG_SMP) | ||
106 | if (cpu >= 0 && cpu < nr_cpu_ids && paca[cpu].kvm_hstate.xics_phys) { | ||
107 | xics_wake_cpu(cpu); | ||
108 | return true; | ||
109 | } | ||
110 | #endif | ||
111 | |||
112 | return false; | ||
113 | } | ||
114 | |||
87 | static void kvmppc_fast_vcpu_kick_hv(struct kvm_vcpu *vcpu) | 115 | static void kvmppc_fast_vcpu_kick_hv(struct kvm_vcpu *vcpu) |
88 | { | 116 | { |
89 | int me; | ||
90 | int cpu = vcpu->cpu; | 117 | int cpu = vcpu->cpu; |
91 | wait_queue_head_t *wqp; | 118 | wait_queue_head_t *wqp; |
92 | 119 | ||
@@ -96,20 +123,12 @@ static void kvmppc_fast_vcpu_kick_hv(struct kvm_vcpu *vcpu) | |||
96 | ++vcpu->stat.halt_wakeup; | 123 | ++vcpu->stat.halt_wakeup; |
97 | } | 124 | } |
98 | 125 | ||
99 | me = get_cpu(); | 126 | if (kvmppc_ipi_thread(cpu + vcpu->arch.ptid)) |
127 | return; | ||
100 | 128 | ||
101 | /* CPU points to the first thread of the core */ | 129 | /* CPU points to the first thread of the core */ |
102 | if (cpu != me && cpu >= 0 && cpu < nr_cpu_ids) { | 130 | if (cpu >= 0 && cpu < nr_cpu_ids && cpu_online(cpu)) |
103 | #ifdef CONFIG_PPC_ICP_NATIVE | 131 | smp_send_reschedule(cpu); |
104 | int real_cpu = cpu + vcpu->arch.ptid; | ||
105 | if (paca[real_cpu].kvm_hstate.xics_phys) | ||
106 | xics_wake_cpu(real_cpu); | ||
107 | else | ||
108 | #endif | ||
109 | if (cpu_online(cpu)) | ||
110 | smp_send_reschedule(cpu); | ||
111 | } | ||
112 | put_cpu(); | ||
113 | } | 132 | } |
114 | 133 | ||
115 | /* | 134 | /* |
@@ -1781,10 +1800,8 @@ static void kvmppc_start_thread(struct kvm_vcpu *vcpu) | |||
1781 | /* Order stores to hstate.kvm_vcore etc. before store to kvm_vcpu */ | 1800 | /* Order stores to hstate.kvm_vcore etc. before store to kvm_vcpu */ |
1782 | smp_wmb(); | 1801 | smp_wmb(); |
1783 | tpaca->kvm_hstate.kvm_vcpu = vcpu; | 1802 | tpaca->kvm_hstate.kvm_vcpu = vcpu; |
1784 | #if defined(CONFIG_PPC_ICP_NATIVE) && defined(CONFIG_SMP) | ||
1785 | if (cpu != smp_processor_id()) | 1803 | if (cpu != smp_processor_id()) |
1786 | xics_wake_cpu(cpu); | 1804 | kvmppc_ipi_thread(cpu); |
1787 | #endif | ||
1788 | } | 1805 | } |
1789 | 1806 | ||
1790 | static void kvmppc_wait_for_nap(void) | 1807 | static void kvmppc_wait_for_nap(void) |
@@ -1933,7 +1950,7 @@ static void post_guest_process(struct kvmppc_vcore *vc) | |||
1933 | * Run a set of guest threads on a physical core. | 1950 | * Run a set of guest threads on a physical core. |
1934 | * Called with vc->lock held. | 1951 | * Called with vc->lock held. |
1935 | */ | 1952 | */ |
1936 | static void kvmppc_run_core(struct kvmppc_vcore *vc) | 1953 | static noinline void kvmppc_run_core(struct kvmppc_vcore *vc) |
1937 | { | 1954 | { |
1938 | struct kvm_vcpu *vcpu; | 1955 | struct kvm_vcpu *vcpu; |
1939 | int i; | 1956 | int i; |
diff --git a/arch/powerpc/kvm/book3s_hv_builtin.c b/arch/powerpc/kvm/book3s_hv_builtin.c index c42aa55b885f..ed2589d4593f 100644 --- a/arch/powerpc/kvm/book3s_hv_builtin.c +++ b/arch/powerpc/kvm/book3s_hv_builtin.c | |||
@@ -23,6 +23,8 @@ | |||
23 | #include <asm/kvm_book3s.h> | 23 | #include <asm/kvm_book3s.h> |
24 | #include <asm/archrandom.h> | 24 | #include <asm/archrandom.h> |
25 | #include <asm/xics.h> | 25 | #include <asm/xics.h> |
26 | #include <asm/dbell.h> | ||
27 | #include <asm/cputhreads.h> | ||
26 | 28 | ||
27 | #define KVM_CMA_CHUNK_ORDER 18 | 29 | #define KVM_CMA_CHUNK_ORDER 18 |
28 | 30 | ||
@@ -193,7 +195,7 @@ static inline void rm_writeb(unsigned long paddr, u8 val) | |||
193 | } | 195 | } |
194 | 196 | ||
195 | /* | 197 | /* |
196 | * Send an interrupt to another CPU. | 198 | * Send an interrupt or message to another CPU. |
197 | * This can only be called in real mode. | 199 | * This can only be called in real mode. |
198 | * The caller needs to include any barrier needed to order writes | 200 | * The caller needs to include any barrier needed to order writes |
199 | * to memory vs. the IPI/message. | 201 | * to memory vs. the IPI/message. |
@@ -202,7 +204,17 @@ void kvmhv_rm_send_ipi(int cpu) | |||
202 | { | 204 | { |
203 | unsigned long xics_phys; | 205 | unsigned long xics_phys; |
204 | 206 | ||
205 | /* Poke the target */ | 207 | /* On POWER8 for IPIs to threads in the same core, use msgsnd */ |
208 | if (cpu_has_feature(CPU_FTR_ARCH_207S) && | ||
209 | cpu_first_thread_sibling(cpu) == | ||
210 | cpu_first_thread_sibling(raw_smp_processor_id())) { | ||
211 | unsigned long msg = PPC_DBELL_TYPE(PPC_DBELL_SERVER); | ||
212 | msg |= cpu_thread_in_core(cpu); | ||
213 | __asm__ __volatile__ (PPC_MSGSND(%0) : : "r" (msg)); | ||
214 | return; | ||
215 | } | ||
216 | |||
217 | /* Else poke the target with an IPI */ | ||
206 | xics_phys = paca[cpu].kvm_hstate.xics_phys; | 218 | xics_phys = paca[cpu].kvm_hstate.xics_phys; |
207 | rm_writeb(xics_phys + XICS_MFRR, IPI_PRIORITY); | 219 | rm_writeb(xics_phys + XICS_MFRR, IPI_PRIORITY); |
208 | } | 220 | } |
diff --git a/arch/powerpc/kvm/book3s_hv_rmhandlers.S b/arch/powerpc/kvm/book3s_hv_rmhandlers.S index fcf3a617cc8a..4d70df26c402 100644 --- a/arch/powerpc/kvm/book3s_hv_rmhandlers.S +++ b/arch/powerpc/kvm/book3s_hv_rmhandlers.S | |||
@@ -1123,6 +1123,13 @@ END_FTR_SECTION_IFSET(CPU_FTR_HAS_PPR) | |||
1123 | cmpwi r12,BOOK3S_INTERRUPT_SYSCALL | 1123 | cmpwi r12,BOOK3S_INTERRUPT_SYSCALL |
1124 | beq hcall_try_real_mode | 1124 | beq hcall_try_real_mode |
1125 | 1125 | ||
1126 | /* Hypervisor doorbell - exit only if host IPI flag set */ | ||
1127 | cmpwi r12, BOOK3S_INTERRUPT_H_DOORBELL | ||
1128 | bne 3f | ||
1129 | lbz r0, HSTATE_HOST_IPI(r13) | ||
1130 | beq 4f | ||
1131 | b guest_exit_cont | ||
1132 | 3: | ||
1126 | /* External interrupt ? */ | 1133 | /* External interrupt ? */ |
1127 | cmpwi r12, BOOK3S_INTERRUPT_EXTERNAL | 1134 | cmpwi r12, BOOK3S_INTERRUPT_EXTERNAL |
1128 | bne+ guest_exit_cont | 1135 | bne+ guest_exit_cont |
@@ -1135,7 +1142,7 @@ END_FTR_SECTION_IFSET(CPU_FTR_HAS_PPR) | |||
1135 | bgt guest_exit_cont | 1142 | bgt guest_exit_cont |
1136 | 1143 | ||
1137 | /* Check if any CPU is heading out to the host, if so head out too */ | 1144 | /* Check if any CPU is heading out to the host, if so head out too */ |
1138 | ld r5, HSTATE_KVM_VCORE(r13) | 1145 | 4: ld r5, HSTATE_KVM_VCORE(r13) |
1139 | lwz r0, VCORE_ENTRY_EXIT(r5) | 1146 | lwz r0, VCORE_ENTRY_EXIT(r5) |
1140 | cmpwi r0, 0x100 | 1147 | cmpwi r0, 0x100 |
1141 | mr r4, r9 | 1148 | mr r4, r9 |
@@ -2148,7 +2155,7 @@ _GLOBAL(kvmppc_h_cede) /* r3 = vcpu pointer, r11 = msr, r13 = paca */ | |||
2148 | /* | 2155 | /* |
2149 | * Take a nap until a decrementer or external or doobell interrupt | 2156 | * Take a nap until a decrementer or external or doobell interrupt |
2150 | * occurs, with PECE1 and PECE0 set in LPCR. | 2157 | * occurs, with PECE1 and PECE0 set in LPCR. |
2151 | * On POWER8, if we are ceding, also set PECEDP. | 2158 | * On POWER8, set PECEDH, and if we are ceding, also set PECEDP. |
2152 | * Also clear the runlatch bit before napping. | 2159 | * Also clear the runlatch bit before napping. |
2153 | */ | 2160 | */ |
2154 | kvm_do_nap: | 2161 | kvm_do_nap: |
@@ -2161,6 +2168,7 @@ kvm_do_nap: | |||
2161 | mfspr r5,SPRN_LPCR | 2168 | mfspr r5,SPRN_LPCR |
2162 | ori r5,r5,LPCR_PECE0 | LPCR_PECE1 | 2169 | ori r5,r5,LPCR_PECE0 | LPCR_PECE1 |
2163 | BEGIN_FTR_SECTION | 2170 | BEGIN_FTR_SECTION |
2171 | ori r5, r5, LPCR_PECEDH | ||
2164 | rlwimi r5, r3, 0, LPCR_PECEDP | 2172 | rlwimi r5, r3, 0, LPCR_PECEDP |
2165 | END_FTR_SECTION_IFSET(CPU_FTR_ARCH_207S) | 2173 | END_FTR_SECTION_IFSET(CPU_FTR_ARCH_207S) |
2166 | mtspr SPRN_LPCR,r5 | 2174 | mtspr SPRN_LPCR,r5 |
@@ -2299,7 +2307,7 @@ machine_check_realmode: | |||
2299 | * Returns (in r3): | 2307 | * Returns (in r3): |
2300 | * 0 if nothing needs to be done | 2308 | * 0 if nothing needs to be done |
2301 | * 1 if something happened that needs to be handled by the host | 2309 | * 1 if something happened that needs to be handled by the host |
2302 | * -1 if there was a guest wakeup (IPI) | 2310 | * -1 if there was a guest wakeup (IPI or msgsnd) |
2303 | * | 2311 | * |
2304 | * Also sets r12 to the interrupt vector for any interrupt that needs | 2312 | * Also sets r12 to the interrupt vector for any interrupt that needs |
2305 | * to be handled now by the host (0x500 for external interrupt), or zero. | 2313 | * to be handled now by the host (0x500 for external interrupt), or zero. |
@@ -2330,7 +2338,15 @@ END_FTR_SECTION_IFSET(CPU_FTR_ARCH_207S) | |||
2330 | 2338 | ||
2331 | /* hypervisor doorbell */ | 2339 | /* hypervisor doorbell */ |
2332 | 3: li r12, BOOK3S_INTERRUPT_H_DOORBELL | 2340 | 3: li r12, BOOK3S_INTERRUPT_H_DOORBELL |
2341 | /* see if it's a host IPI */ | ||
2333 | li r3, 1 | 2342 | li r3, 1 |
2343 | lbz r0, HSTATE_HOST_IPI(r13) | ||
2344 | cmpwi r0, 0 | ||
2345 | bnelr | ||
2346 | /* if not, clear it and return -1 */ | ||
2347 | lis r6, (PPC_DBELL_SERVER << (63-36))@h | ||
2348 | PPC_MSGCLR(6) | ||
2349 | li r3, -1 | ||
2334 | blr | 2350 | blr |
2335 | 2351 | ||
2336 | /* | 2352 | /* |