Commit 6fcc8cea authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'powerpc-4.9-4' of git://git.kernel.org/pub/scm/linux/kernel/git/powerpc/linux

Pull powerpc fixes from Michael Ellerman:
 "Fixes marked for stable:
   - Convert cmp to cmpd in idle enter sequence (Segher Boessenkool)
   - cxl: Fix leaking pid refs in some error paths (Vaibhav Jain)
   - Re-fix race condition between going idle and entering guest (Paul Mackerras)
   - Fix race condition in setting lock bit in idle/wakeup code (Paul Mackerras)
   - radix: Use tlbiel only if we ever ran on the current cpu (Aneesh Kumar K.V)
   - relocation, register save fixes for system reset interrupt (Nicholas Piggin)

  Fixes for code merged this cycle:
   - Fix CONFIG_ALIVEC typo in restore_tm_state() (Valentin Rothberg)
   - KVM: PPC: Book3S HV: Fix build error when SMP=n (Michael Ellerman)"

* tag 'powerpc-4.9-4' of git://git.kernel.org/pub/scm/linux/kernel/git/powerpc/linux:
  powerpc/64s: relocation, register save fixes for system reset interrupt
  powerpc/mm/radix: Use tlbiel only if we ever ran on the current cpu
  powerpc/process: Fix CONFIG_ALIVEC typo in restore_tm_state()
  powerpc/64: Fix race condition in setting lock bit in idle/wakeup code
  powerpc/64: Re-fix race condition between going idle and entering guest
  cxl: Fix leaking pid refs in some error paths
  powerpc: Convert cmp to cmpd in idle enter sequence
  KVM: PPC: Book3S HV: Fix build error when SMP=n
parents b49c3170 fb479e44
...@@ -26,7 +26,7 @@ extern u64 pnv_first_deep_stop_state; ...@@ -26,7 +26,7 @@ extern u64 pnv_first_deep_stop_state;
std r0,0(r1); \ std r0,0(r1); \
ptesync; \ ptesync; \
ld r0,0(r1); \ ld r0,0(r1); \
1: cmp cr0,r0,r0; \ 1: cmpd cr0,r0,r0; \
bne 1b; \ bne 1b; \
IDLE_INST; \ IDLE_INST; \
b . b .
......
...@@ -93,6 +93,10 @@ ...@@ -93,6 +93,10 @@
ld reg,PACAKBASE(r13); /* get high part of &label */ \ ld reg,PACAKBASE(r13); /* get high part of &label */ \
ori reg,reg,(FIXED_SYMBOL_ABS_ADDR(label))@l; ori reg,reg,(FIXED_SYMBOL_ABS_ADDR(label))@l;
#define __LOAD_HANDLER(reg, label) \
ld reg,PACAKBASE(r13); \
ori reg,reg,(ABS_ADDR(label))@l;
/* Exception register prefixes */ /* Exception register prefixes */
#define EXC_HV H #define EXC_HV H
#define EXC_STD #define EXC_STD
...@@ -208,6 +212,18 @@ END_FTR_SECTION_NESTED(ftr,ftr,943) ...@@ -208,6 +212,18 @@ END_FTR_SECTION_NESTED(ftr,ftr,943)
#define kvmppc_interrupt kvmppc_interrupt_pr #define kvmppc_interrupt kvmppc_interrupt_pr
#endif #endif
#ifdef CONFIG_RELOCATABLE
#define BRANCH_TO_COMMON(reg, label) \
__LOAD_HANDLER(reg, label); \
mtctr reg; \
bctr
#else
#define BRANCH_TO_COMMON(reg, label) \
b label
#endif
#define __KVM_HANDLER_PROLOG(area, n) \ #define __KVM_HANDLER_PROLOG(area, n) \
BEGIN_FTR_SECTION_NESTED(947) \ BEGIN_FTR_SECTION_NESTED(947) \
ld r10,area+EX_CFAR(r13); \ ld r10,area+EX_CFAR(r13); \
......
...@@ -52,11 +52,23 @@ static inline int mm_is_core_local(struct mm_struct *mm) ...@@ -52,11 +52,23 @@ static inline int mm_is_core_local(struct mm_struct *mm)
return cpumask_subset(mm_cpumask(mm), return cpumask_subset(mm_cpumask(mm),
topology_sibling_cpumask(smp_processor_id())); topology_sibling_cpumask(smp_processor_id()));
} }
static inline int mm_is_thread_local(struct mm_struct *mm)
{
return cpumask_equal(mm_cpumask(mm),
cpumask_of(smp_processor_id()));
}
#else #else
static inline int mm_is_core_local(struct mm_struct *mm) static inline int mm_is_core_local(struct mm_struct *mm)
{ {
return 1; return 1;
} }
static inline int mm_is_thread_local(struct mm_struct *mm)
{
return 1;
}
#endif #endif
#endif /* __KERNEL__ */ #endif /* __KERNEL__ */
......
...@@ -95,19 +95,35 @@ __start_interrupts: ...@@ -95,19 +95,35 @@ __start_interrupts:
/* No virt vectors corresponding with 0x0..0x100 */ /* No virt vectors corresponding with 0x0..0x100 */
EXC_VIRT_NONE(0x4000, 0x4100) EXC_VIRT_NONE(0x4000, 0x4100)
EXC_REAL_BEGIN(system_reset, 0x100, 0x200)
SET_SCRATCH0(r13)
#ifdef CONFIG_PPC_P7_NAP #ifdef CONFIG_PPC_P7_NAP
BEGIN_FTR_SECTION /*
/* Running native on arch 2.06 or later, check if we are * If running native on arch 2.06 or later, check if we are waking up
* waking up from nap/sleep/winkle. * from nap/sleep/winkle, and branch to idle handler.
*/ */
mfspr r13,SPRN_SRR1 #define IDLETEST(n) \
rlwinm. r13,r13,47-31,30,31 BEGIN_FTR_SECTION ; \
beq 9f mfspr r10,SPRN_SRR1 ; \
rlwinm. r10,r10,47-31,30,31 ; \
beq- 1f ; \
cmpwi cr3,r10,2 ; \
BRANCH_TO_COMMON(r10, system_reset_idle_common) ; \
1: \
END_FTR_SECTION_IFSET(CPU_FTR_HVMODE | CPU_FTR_ARCH_206)
#else
#define IDLETEST NOTEST
#endif
cmpwi cr3,r13,2 EXC_REAL_BEGIN(system_reset, 0x100, 0x200)
GET_PACA(r13) SET_SCRATCH0(r13)
EXCEPTION_PROLOG_PSERIES(PACA_EXGEN, system_reset_common, EXC_STD,
IDLETEST, 0x100)
EXC_REAL_END(system_reset, 0x100, 0x200)
EXC_VIRT_NONE(0x4100, 0x4200)
#ifdef CONFIG_PPC_P7_NAP
EXC_COMMON_BEGIN(system_reset_idle_common)
bl pnv_restore_hyp_resource bl pnv_restore_hyp_resource
li r0,PNV_THREAD_RUNNING li r0,PNV_THREAD_RUNNING
...@@ -130,14 +146,8 @@ BEGIN_FTR_SECTION ...@@ -130,14 +146,8 @@ BEGIN_FTR_SECTION
blt cr3,2f blt cr3,2f
b pnv_wakeup_loss b pnv_wakeup_loss
2: b pnv_wakeup_noloss 2: b pnv_wakeup_noloss
#endif
9:
END_FTR_SECTION_IFSET(CPU_FTR_HVMODE | CPU_FTR_ARCH_206)
#endif /* CONFIG_PPC_P7_NAP */
EXCEPTION_PROLOG_PSERIES(PACA_EXGEN, system_reset_common, EXC_STD,
NOTEST, 0x100)
EXC_REAL_END(system_reset, 0x100, 0x200)
EXC_VIRT_NONE(0x4100, 0x4200)
EXC_COMMON(system_reset_common, 0x100, system_reset_exception) EXC_COMMON(system_reset_common, 0x100, system_reset_exception)
#ifdef CONFIG_PPC_PSERIES #ifdef CONFIG_PPC_PSERIES
...@@ -817,10 +827,8 @@ EXC_VIRT(trap_0b, 0x4b00, 0x4c00, 0xb00) ...@@ -817,10 +827,8 @@ EXC_VIRT(trap_0b, 0x4b00, 0x4c00, 0xb00)
TRAMP_KVM(PACA_EXGEN, 0xb00) TRAMP_KVM(PACA_EXGEN, 0xb00)
EXC_COMMON(trap_0b_common, 0xb00, unknown_exception) EXC_COMMON(trap_0b_common, 0xb00, unknown_exception)
#define LOAD_SYSCALL_HANDLER(reg) \
#define LOAD_SYSCALL_HANDLER(reg) \ __LOAD_HANDLER(reg, system_call_common)
ld reg,PACAKBASE(r13); \
ori reg,reg,(ABS_ADDR(system_call_common))@l;
/* Syscall routine is used twice, in reloc-off and reloc-on paths */ /* Syscall routine is used twice, in reloc-off and reloc-on paths */
#define SYSCALL_PSERIES_1 \ #define SYSCALL_PSERIES_1 \
......
...@@ -90,6 +90,7 @@ ALT_FTR_SECTION_END_IFSET(CPU_FTR_ARCH_300) ...@@ -90,6 +90,7 @@ ALT_FTR_SECTION_END_IFSET(CPU_FTR_ARCH_300)
* Threads will spin in HMT_LOW until the lock bit is cleared. * Threads will spin in HMT_LOW until the lock bit is cleared.
* r14 - pointer to core_idle_state * r14 - pointer to core_idle_state
* r15 - used to load contents of core_idle_state * r15 - used to load contents of core_idle_state
* r9 - used as a temporary variable
*/ */
core_idle_lock_held: core_idle_lock_held:
...@@ -99,6 +100,8 @@ core_idle_lock_held: ...@@ -99,6 +100,8 @@ core_idle_lock_held:
bne 3b bne 3b
HMT_MEDIUM HMT_MEDIUM
lwarx r15,0,r14 lwarx r15,0,r14
andi. r9,r15,PNV_CORE_IDLE_LOCK_BIT
bne core_idle_lock_held
blr blr
/* /*
...@@ -163,12 +166,6 @@ _GLOBAL(pnv_powersave_common) ...@@ -163,12 +166,6 @@ _GLOBAL(pnv_powersave_common)
std r9,_MSR(r1) std r9,_MSR(r1)
std r1,PACAR1(r13) std r1,PACAR1(r13)
#ifdef CONFIG_KVM_BOOK3S_HV_POSSIBLE
/* Tell KVM we're entering idle */
li r4,KVM_HWTHREAD_IN_IDLE
stb r4,HSTATE_HWTHREAD_STATE(r13)
#endif
/* /*
* Go to real mode to do the nap, as required by the architecture. * Go to real mode to do the nap, as required by the architecture.
* Also, we need to be in real mode before setting hwthread_state, * Also, we need to be in real mode before setting hwthread_state,
...@@ -185,6 +182,26 @@ _GLOBAL(pnv_powersave_common) ...@@ -185,6 +182,26 @@ _GLOBAL(pnv_powersave_common)
.globl pnv_enter_arch207_idle_mode .globl pnv_enter_arch207_idle_mode
pnv_enter_arch207_idle_mode: pnv_enter_arch207_idle_mode:
#ifdef CONFIG_KVM_BOOK3S_HV_POSSIBLE
/* Tell KVM we're entering idle */
li r4,KVM_HWTHREAD_IN_IDLE
/******************************************************/
/* N O T E W E L L ! ! ! N O T E W E L L */
/* The following store to HSTATE_HWTHREAD_STATE(r13) */
/* MUST occur in real mode, i.e. with the MMU off, */
/* and the MMU must stay off until we clear this flag */
/* and test HSTATE_HWTHREAD_REQ(r13) in the system */
/* reset interrupt vector in exceptions-64s.S. */
/* The reason is that another thread can switch the */
/* MMU to a guest context whenever this flag is set */
/* to KVM_HWTHREAD_IN_IDLE, and if the MMU was on, */
/* that would potentially cause this thread to start */
/* executing instructions from guest memory in */
/* hypervisor mode, leading to a host crash or data */
/* corruption, or worse. */
/******************************************************/
stb r4,HSTATE_HWTHREAD_STATE(r13)
#endif
stb r3,PACA_THREAD_IDLE_STATE(r13) stb r3,PACA_THREAD_IDLE_STATE(r13)
cmpwi cr3,r3,PNV_THREAD_SLEEP cmpwi cr3,r3,PNV_THREAD_SLEEP
bge cr3,2f bge cr3,2f
...@@ -250,6 +267,12 @@ enter_winkle: ...@@ -250,6 +267,12 @@ enter_winkle:
* r3 - requested stop state * r3 - requested stop state
*/ */
power_enter_stop: power_enter_stop:
#ifdef CONFIG_KVM_BOOK3S_HV_POSSIBLE
/* Tell KVM we're entering idle */
li r4,KVM_HWTHREAD_IN_IDLE
/* DO THIS IN REAL MODE! See comment above. */
stb r4,HSTATE_HWTHREAD_STATE(r13)
#endif
/* /*
* Check if the requested state is a deep idle state. * Check if the requested state is a deep idle state.
*/ */
......
...@@ -1012,7 +1012,7 @@ void restore_tm_state(struct pt_regs *regs) ...@@ -1012,7 +1012,7 @@ void restore_tm_state(struct pt_regs *regs)
/* Ensure that restore_math() will restore */ /* Ensure that restore_math() will restore */
if (msr_diff & MSR_FP) if (msr_diff & MSR_FP)
current->thread.load_fp = 1; current->thread.load_fp = 1;
#ifdef CONFIG_ALIVEC #ifdef CONFIG_ALTIVEC
if (cpu_has_feature(CPU_FTR_ALTIVEC) && msr_diff & MSR_VEC) if (cpu_has_feature(CPU_FTR_ALTIVEC) && msr_diff & MSR_VEC)
current->thread.load_vec = 1; current->thread.load_vec = 1;
#endif #endif
......
...@@ -23,6 +23,7 @@ ...@@ -23,6 +23,7 @@
#include <asm/ppc-opcode.h> #include <asm/ppc-opcode.h>
#include <asm/pnv-pci.h> #include <asm/pnv-pci.h>
#include <asm/opal.h> #include <asm/opal.h>
#include <asm/smp.h>
#include "book3s_xics.h" #include "book3s_xics.h"
......
...@@ -175,7 +175,7 @@ void radix__flush_tlb_mm(struct mm_struct *mm) ...@@ -175,7 +175,7 @@ void radix__flush_tlb_mm(struct mm_struct *mm)
if (unlikely(pid == MMU_NO_CONTEXT)) if (unlikely(pid == MMU_NO_CONTEXT))
goto no_context; goto no_context;
if (!mm_is_core_local(mm)) { if (!mm_is_thread_local(mm)) {
int lock_tlbie = !mmu_has_feature(MMU_FTR_LOCKLESS_TLBIE); int lock_tlbie = !mmu_has_feature(MMU_FTR_LOCKLESS_TLBIE);
if (lock_tlbie) if (lock_tlbie)
...@@ -201,7 +201,7 @@ void radix__flush_tlb_pwc(struct mmu_gather *tlb, unsigned long addr) ...@@ -201,7 +201,7 @@ void radix__flush_tlb_pwc(struct mmu_gather *tlb, unsigned long addr)
if (unlikely(pid == MMU_NO_CONTEXT)) if (unlikely(pid == MMU_NO_CONTEXT))
goto no_context; goto no_context;
if (!mm_is_core_local(mm)) { if (!mm_is_thread_local(mm)) {
int lock_tlbie = !mmu_has_feature(MMU_FTR_LOCKLESS_TLBIE); int lock_tlbie = !mmu_has_feature(MMU_FTR_LOCKLESS_TLBIE);
if (lock_tlbie) if (lock_tlbie)
...@@ -226,7 +226,7 @@ void radix__flush_tlb_page_psize(struct mm_struct *mm, unsigned long vmaddr, ...@@ -226,7 +226,7 @@ void radix__flush_tlb_page_psize(struct mm_struct *mm, unsigned long vmaddr,
pid = mm ? mm->context.id : 0; pid = mm ? mm->context.id : 0;
if (unlikely(pid == MMU_NO_CONTEXT)) if (unlikely(pid == MMU_NO_CONTEXT))
goto bail; goto bail;
if (!mm_is_core_local(mm)) { if (!mm_is_thread_local(mm)) {
int lock_tlbie = !mmu_has_feature(MMU_FTR_LOCKLESS_TLBIE); int lock_tlbie = !mmu_has_feature(MMU_FTR_LOCKLESS_TLBIE);
if (lock_tlbie) if (lock_tlbie)
...@@ -321,7 +321,7 @@ void radix__flush_tlb_range_psize(struct mm_struct *mm, unsigned long start, ...@@ -321,7 +321,7 @@ void radix__flush_tlb_range_psize(struct mm_struct *mm, unsigned long start,
{ {
unsigned long pid; unsigned long pid;
unsigned long addr; unsigned long addr;
int local = mm_is_core_local(mm); int local = mm_is_thread_local(mm);
unsigned long ap = mmu_get_ap(psize); unsigned long ap = mmu_get_ap(psize);
int lock_tlbie = !mmu_has_feature(MMU_FTR_LOCKLESS_TLBIE); int lock_tlbie = !mmu_has_feature(MMU_FTR_LOCKLESS_TLBIE);
unsigned long page_size = 1UL << mmu_psize_defs[psize].shift; unsigned long page_size = 1UL << mmu_psize_defs[psize].shift;
......
...@@ -247,7 +247,9 @@ int cxl_start_context(struct cxl_context *ctx, u64 wed, ...@@ -247,7 +247,9 @@ int cxl_start_context(struct cxl_context *ctx, u64 wed,
cxl_ctx_get(); cxl_ctx_get();
if ((rc = cxl_ops->attach_process(ctx, kernel, wed, 0))) { if ((rc = cxl_ops->attach_process(ctx, kernel, wed, 0))) {
put_pid(ctx->glpid);
put_pid(ctx->pid); put_pid(ctx->pid);
ctx->glpid = ctx->pid = NULL;
cxl_adapter_context_put(ctx->afu->adapter); cxl_adapter_context_put(ctx->afu->adapter);
cxl_ctx_put(); cxl_ctx_put();
goto out; goto out;
......
...@@ -193,6 +193,16 @@ static long afu_ioctl_start_work(struct cxl_context *ctx, ...@@ -193,6 +193,16 @@ static long afu_ioctl_start_work(struct cxl_context *ctx,
ctx->mmio_err_ff = !!(work.flags & CXL_START_WORK_ERR_FF); ctx->mmio_err_ff = !!(work.flags & CXL_START_WORK_ERR_FF);
/*
* Increment the mapped context count for adapter. This also checks
* if adapter_context_lock is taken.
*/
rc = cxl_adapter_context_get(ctx->afu->adapter);
if (rc) {
afu_release_irqs(ctx, ctx);
goto out;
}
/* /*
* We grab the PID here and not in the file open to allow for the case * We grab the PID here and not in the file open to allow for the case
* where a process (master, some daemon, etc) has opened the chardev on * where a process (master, some daemon, etc) has opened the chardev on
...@@ -205,15 +215,6 @@ static long afu_ioctl_start_work(struct cxl_context *ctx, ...@@ -205,15 +215,6 @@ static long afu_ioctl_start_work(struct cxl_context *ctx,
ctx->pid = get_task_pid(current, PIDTYPE_PID); ctx->pid = get_task_pid(current, PIDTYPE_PID);
ctx->glpid = get_task_pid(current->group_leader, PIDTYPE_PID); ctx->glpid = get_task_pid(current->group_leader, PIDTYPE_PID);
/*
* Increment the mapped context count for adapter. This also checks
* if adapter_context_lock is taken.
*/
rc = cxl_adapter_context_get(ctx->afu->adapter);
if (rc) {
afu_release_irqs(ctx, ctx);
goto out;
}
trace_cxl_attach(ctx, work.work_element_descriptor, work.num_interrupts, amr); trace_cxl_attach(ctx, work.work_element_descriptor, work.num_interrupts, amr);
...@@ -221,6 +222,9 @@ static long afu_ioctl_start_work(struct cxl_context *ctx, ...@@ -221,6 +222,9 @@ static long afu_ioctl_start_work(struct cxl_context *ctx,
amr))) { amr))) {
afu_release_irqs(ctx, ctx); afu_release_irqs(ctx, ctx);
cxl_adapter_context_put(ctx->afu->adapter); cxl_adapter_context_put(ctx->afu->adapter);
put_pid(ctx->glpid);
put_pid(ctx->pid);
ctx->glpid = ctx->pid = NULL;
goto out; goto out;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment