Skip to content

Commit aa3ae6d

Browse files
committed
Merge branch 'merge' of git://git.kernel.org/pub/scm/linux/kernel/git/benh/powerpc
Pull powerpc fixes from Ben Herrenschmidt: "Here are a few more fixes for powerpc 3.10. It's a bit more than I would have liked this late in the game but I suppose that's what happens with a brand new chip generation coming out. A few regression fixes, some last minute fixes for new P8 features such as transactional memory,... There's also one powerpc KVM patch that I requested that adds two missing functions to our in-kernel interrupt controller support which is itself a new 3.10 feature. These are defined by the base hypervisor specification. We didn't implement them originally because Linux doesn't use them but they are simple and I'm not comfortable having a half-implemented interface in 3.10 and having to deal with versionning etc... later when something starts needing those calls. They cannot be emulated in qemu when using in-kernel interrupt controller (not enough shared state). Just added a last minute patch to fix a typo introducing a breakage in our cputable for Power7+ processors, sorry about that, but the regression it fixes just hurt me :-)" * 'merge' of git://git.kernel.org/pub/scm/linux/kernel/git/benh/powerpc: powerpc/cputable: Fix typo on P7+ cputable entry powerpc/perf: Add missing SIER support powerpc/perf: Revert to original NO_SIPR logic powerpc/pci: Remove the unused variables in pci_process_bridge_OF_ranges powerpc/pci: Remove the stale comments of pci_process_bridge_OF_ranges powerpc/pseries: Always enable CONFIG_HOTPLUG_CPU on PSERIES SMP powerpc/kvm/book3s: Add support for H_IPOLL and H_XIRR_X in XICS emulation powerpc/32bit:Store temporary result in r0 instead of r8 powerpc/mm: Always invalidate tlb on hpte invalidate and update powerpc/pseries: Improve stream generation comments in copypage/user powerpc/pseries: Kill all prefetch streams on context switch powerpc/cputable: Fix oprofile_cpu_type on power8 powerpc/mpic: Fix irq distribution problem when MPIC_SINGLE_DEST_CPU powerpc/tm: Fix userspace stack corruption on signal delivery for active transactions powerpc/tm: Move TM abort cause codes to uapi powerpc/tm: Abort on emulation and alignment faults powerpc/tm: Update cause codes documentation powerpc/tm: Make room for hypervisor in abort cause codes
2 parents 008bd2d + badec11 commit aa3ae6d

27 files changed

+262
-125
lines changed

Documentation/powerpc/transactional_memory.txt

Lines changed: 25 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -147,6 +147,25 @@ Example signal handler:
147147
fix_the_problem(ucp->dar);
148148
}
149149

150+
When in an active transaction that takes a signal, we need to be careful with
151+
the stack. It's possible that the stack has moved back up after the tbegin.
152+
The obvious case here is when the tbegin is called inside a function that
153+
returns before a tend. In this case, the stack is part of the checkpointed
154+
transactional memory state. If we write over this non transactionally or in
155+
suspend, we are in trouble because if we get a tm abort, the program counter and
156+
stack pointer will be back at the tbegin but our in memory stack won't be valid
157+
anymore.
158+
159+
To avoid this, when taking a signal in an active transaction, we need to use
160+
the stack pointer from the checkpointed state, rather than the speculated
161+
state. This ensures that the signal context (written tm suspended) will be
162+
written below the stack required for the rollback. The transaction is aborted
163+
becuase of the treclaim, so any memory written between the tbegin and the
164+
signal will be rolled back anyway.
165+
166+
For signals taken in non-TM or suspended mode, we use the
167+
normal/non-checkpointed stack pointer.
168+
150169

151170
Failure cause codes used by kernel
152171
==================================
@@ -155,14 +174,18 @@ These are defined in <asm/reg.h>, and distinguish different reasons why the
155174
kernel aborted a transaction:
156175

157176
TM_CAUSE_RESCHED Thread was rescheduled.
177+
TM_CAUSE_TLBI Software TLB invalide.
158178
TM_CAUSE_FAC_UNAV FP/VEC/VSX unavailable trap.
159179
TM_CAUSE_SYSCALL Currently unused; future syscalls that must abort
160180
transactions for consistency will use this.
161181
TM_CAUSE_SIGNAL Signal delivered.
162182
TM_CAUSE_MISC Currently unused.
183+
TM_CAUSE_ALIGNMENT Alignment fault.
184+
TM_CAUSE_EMULATE Emulation that touched memory.
163185

164-
These can be checked by the user program's abort handler as TEXASR[0:7].
165-
186+
These can be checked by the user program's abort handler as TEXASR[0:7]. If
187+
bit 7 is set, it indicates that the error is consider persistent. For example
188+
a TM_CAUSE_ALIGNMENT will be persistent while a TM_CAUSE_RESCHED will not.q
166189

167190
GDB
168191
===

arch/powerpc/include/asm/hvcall.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -264,6 +264,7 @@
264264
#define H_GET_MPP 0x2D4
265265
#define H_HOME_NODE_ASSOCIATIVITY 0x2EC
266266
#define H_BEST_ENERGY 0x2F4
267+
#define H_XIRR_X 0x2FC
267268
#define H_RANDOM 0x300
268269
#define H_COP 0x304
269270
#define H_GET_MPP_X 0x314

arch/powerpc/include/asm/ppc_asm.h

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -523,6 +523,17 @@ END_FTR_SECTION_NESTED(CPU_FTR_HAS_PPR,CPU_FTR_HAS_PPR,946)
523523
#define PPC440EP_ERR42
524524
#endif
525525

526+
/* The following stops all load and store data streams associated with stream
527+
* ID (ie. streams created explicitly). The embedded and server mnemonics for
528+
* dcbt are different so we use machine "power4" here explicitly.
529+
*/
530+
#define DCBT_STOP_ALL_STREAM_IDS(scratch) \
531+
.machine push ; \
532+
.machine "power4" ; \
533+
lis scratch,0x60000000@h; \
534+
dcbt r0,scratch,0b01010; \
535+
.machine pop
536+
526537
/*
527538
* toreal/fromreal/tophys/tovirt macros. 32-bit BookE makes them
528539
* keep the address intact to be compatible with code shared with

arch/powerpc/include/asm/processor.h

Lines changed: 4 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -409,21 +409,16 @@ static inline void prefetchw(const void *x)
409409
#endif
410410

411411
#ifdef CONFIG_PPC64
412-
static inline unsigned long get_clean_sp(struct pt_regs *regs, int is_32)
412+
static inline unsigned long get_clean_sp(unsigned long sp, int is_32)
413413
{
414-
unsigned long sp;
415-
416414
if (is_32)
417-
sp = regs->gpr[1] & 0x0ffffffffUL;
418-
else
419-
sp = regs->gpr[1];
420-
415+
return sp & 0x0ffffffffUL;
421416
return sp;
422417
}
423418
#else
424-
static inline unsigned long get_clean_sp(struct pt_regs *regs, int is_32)
419+
static inline unsigned long get_clean_sp(unsigned long sp, int is_32)
425420
{
426-
return regs->gpr[1];
421+
return sp;
427422
}
428423
#endif
429424

arch/powerpc/include/asm/reg.h

Lines changed: 0 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -111,17 +111,6 @@
111111
#define MSR_TM_TRANSACTIONAL(x) (((x) & MSR_TS_MASK) == MSR_TS_T)
112112
#define MSR_TM_SUSPENDED(x) (((x) & MSR_TS_MASK) == MSR_TS_S)
113113

114-
/* Reason codes describing kernel causes for transaction aborts. By
115-
convention, bit0 is copied to TEXASR[56] (IBM bit 7) which is set if
116-
the failure is persistent.
117-
*/
118-
#define TM_CAUSE_RESCHED 0xfe
119-
#define TM_CAUSE_TLBI 0xfc
120-
#define TM_CAUSE_FAC_UNAV 0xfa
121-
#define TM_CAUSE_SYSCALL 0xf9 /* Persistent */
122-
#define TM_CAUSE_MISC 0xf6
123-
#define TM_CAUSE_SIGNAL 0xf4
124-
125114
#if defined(CONFIG_PPC_BOOK3S_64)
126115
#define MSR_64BIT MSR_SF
127116

arch/powerpc/include/asm/signal.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,5 +3,8 @@
33

44
#define __ARCH_HAS_SA_RESTORER
55
#include <uapi/asm/signal.h>
6+
#include <uapi/asm/ptrace.h>
7+
8+
extern unsigned long get_tm_stackpointer(struct pt_regs *regs);
69

710
#endif /* _ASM_POWERPC_SIGNAL_H */

arch/powerpc/include/asm/tm.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@
55
* Copyright 2012 Matt Evans & Michael Neuling, IBM Corporation.
66
*/
77

8+
#include <uapi/asm/tm.h>
9+
810
#ifdef CONFIG_PPC_TRANSACTIONAL_MEM
911
extern void do_load_up_transact_fpu(struct thread_struct *thread);
1012
extern void do_load_up_transact_altivec(struct thread_struct *thread);

arch/powerpc/include/uapi/asm/Kbuild

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ header-y += statfs.h
4040
header-y += swab.h
4141
header-y += termbits.h
4242
header-y += termios.h
43+
header-y += tm.h
4344
header-y += types.h
4445
header-y += ucontext.h
4546
header-y += unistd.h

arch/powerpc/include/uapi/asm/tm.h

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
#ifndef _ASM_POWERPC_TM_H
2+
#define _ASM_POWERPC_TM_H
3+
4+
/* Reason codes describing kernel causes for transaction aborts. By
5+
* convention, bit0 is copied to TEXASR[56] (IBM bit 7) which is set if
6+
* the failure is persistent. PAPR saves 0xff-0xe0 for the hypervisor.
7+
*/
8+
#define TM_CAUSE_PERSISTENT 0x01
9+
#define TM_CAUSE_RESCHED 0xde
10+
#define TM_CAUSE_TLBI 0xdc
11+
#define TM_CAUSE_FAC_UNAV 0xda
12+
#define TM_CAUSE_SYSCALL 0xd8 /* future use */
13+
#define TM_CAUSE_MISC 0xd6 /* future use */
14+
#define TM_CAUSE_SIGNAL 0xd4
15+
#define TM_CAUSE_ALIGNMENT 0xd2
16+
#define TM_CAUSE_EMULATE 0xd0
17+
18+
#endif

arch/powerpc/kernel/cputable.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -453,7 +453,7 @@ static struct cpu_spec __initdata cpu_specs[] = {
453453
.icache_bsize = 128,
454454
.dcache_bsize = 128,
455455
.oprofile_type = PPC_OPROFILE_POWER4,
456-
.oprofile_cpu_type = "ppc64/ibm-compat-v1",
456+
.oprofile_cpu_type = 0,
457457
.cpu_setup = __setup_cpu_power8,
458458
.cpu_restore = __restore_cpu_power8,
459459
.platform = "power8",
@@ -482,7 +482,7 @@ static struct cpu_spec __initdata cpu_specs[] = {
482482
.cpu_name = "POWER7+ (raw)",
483483
.cpu_features = CPU_FTRS_POWER7,
484484
.cpu_user_features = COMMON_USER_POWER7,
485-
.cpu_user_features = COMMON_USER2_POWER7,
485+
.cpu_user_features2 = COMMON_USER2_POWER7,
486486
.mmu_features = MMU_FTRS_POWER7,
487487
.icache_bsize = 128,
488488
.dcache_bsize = 128,
@@ -506,7 +506,7 @@ static struct cpu_spec __initdata cpu_specs[] = {
506506
.dcache_bsize = 128,
507507
.num_pmcs = 6,
508508
.pmc_type = PPC_PMC_IBM,
509-
.oprofile_cpu_type = "ppc64/power8",
509+
.oprofile_cpu_type = 0,
510510
.oprofile_type = PPC_OPROFILE_POWER4,
511511
.cpu_setup = __setup_cpu_power8,
512512
.cpu_restore = __restore_cpu_power8,

arch/powerpc/kernel/entry_32.S

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -849,7 +849,7 @@ resume_kernel:
849849
/* check current_thread_info, _TIF_EMULATE_STACK_STORE */
850850
CURRENT_THREAD_INFO(r9, r1)
851851
lwz r8,TI_FLAGS(r9)
852-
andis. r8,r8,_TIF_EMULATE_STACK_STORE@h
852+
andis. r0,r8,_TIF_EMULATE_STACK_STORE@h
853853
beq+ 1f
854854

855855
addi r8,r1,INT_FRAME_SIZE /* Get the kprobed function entry */

arch/powerpc/kernel/entry_64.S

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -501,6 +501,13 @@ BEGIN_FTR_SECTION
501501
ldarx r6,0,r1
502502
END_FTR_SECTION_IFSET(CPU_FTR_STCX_CHECKS_ADDRESS)
503503

504+
#ifdef CONFIG_PPC_BOOK3S
505+
/* Cancel all explict user streams as they will have no use after context
506+
* switch and will stop the HW from creating streams itself
507+
*/
508+
DCBT_STOP_ALL_STREAM_IDS(r6)
509+
#endif
510+
504511
addi r6,r4,-THREAD /* Convert THREAD to 'current' */
505512
std r6,PACACURRENT(r13) /* Set new 'current' */
506513

arch/powerpc/kernel/pci-common.c

Lines changed: 1 addition & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -657,15 +657,6 @@ void pci_resource_to_user(const struct pci_dev *dev, int bar,
657657
* ranges. However, some machines (thanks Apple !) tend to split their
658658
* space into lots of small contiguous ranges. So we have to coalesce.
659659
*
660-
* - We can only cope with all memory ranges having the same offset
661-
* between CPU addresses and PCI addresses. Unfortunately, some bridges
662-
* are setup for a large 1:1 mapping along with a small "window" which
663-
* maps PCI address 0 to some arbitrary high address of the CPU space in
664-
* order to give access to the ISA memory hole.
665-
* The way out of here that I've chosen for now is to always set the
666-
* offset based on the first resource found, then override it if we
667-
* have a different offset and the previous was set by an ISA hole.
668-
*
669660
* - Some busses have IO space not starting at 0, which causes trouble with
670661
* the way we do our IO resource renumbering. The code somewhat deals with
671662
* it for 64 bits but I would expect problems on 32 bits.
@@ -680,10 +671,9 @@ void pci_process_bridge_OF_ranges(struct pci_controller *hose,
680671
int rlen;
681672
int pna = of_n_addr_cells(dev);
682673
int np = pna + 5;
683-
int memno = 0, isa_hole = -1;
674+
int memno = 0;
684675
u32 pci_space;
685676
unsigned long long pci_addr, cpu_addr, pci_next, cpu_next, size;
686-
unsigned long long isa_mb = 0;
687677
struct resource *res;
688678

689679
printk(KERN_INFO "PCI host bridge %s %s ranges:\n",
@@ -777,8 +767,6 @@ void pci_process_bridge_OF_ranges(struct pci_controller *hose,
777767
}
778768
/* Handles ISA memory hole space here */
779769
if (pci_addr == 0) {
780-
isa_mb = cpu_addr;
781-
isa_hole = memno;
782770
if (primary || isa_mem_base == 0)
783771
isa_mem_base = cpu_addr;
784772
hose->isa_mem_phys = cpu_addr;

arch/powerpc/kernel/signal.c

Lines changed: 38 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
#include <asm/uaccess.h>
1919
#include <asm/unistd.h>
2020
#include <asm/debug.h>
21+
#include <asm/tm.h>
2122

2223
#include "signal.h"
2324

@@ -30,13 +31,13 @@ int show_unhandled_signals = 1;
3031
/*
3132
* Allocate space for the signal frame
3233
*/
33-
void __user * get_sigframe(struct k_sigaction *ka, struct pt_regs *regs,
34+
void __user * get_sigframe(struct k_sigaction *ka, unsigned long sp,
3435
size_t frame_size, int is_32)
3536
{
3637
unsigned long oldsp, newsp;
3738

3839
/* Default to using normal stack */
39-
oldsp = get_clean_sp(regs, is_32);
40+
oldsp = get_clean_sp(sp, is_32);
4041

4142
/* Check for alt stack */
4243
if ((ka->sa.sa_flags & SA_ONSTACK) &&
@@ -175,3 +176,38 @@ void do_notify_resume(struct pt_regs *regs, unsigned long thread_info_flags)
175176

176177
user_enter();
177178
}
179+
180+
unsigned long get_tm_stackpointer(struct pt_regs *regs)
181+
{
182+
/* When in an active transaction that takes a signal, we need to be
183+
* careful with the stack. It's possible that the stack has moved back
184+
* up after the tbegin. The obvious case here is when the tbegin is
185+
* called inside a function that returns before a tend. In this case,
186+
* the stack is part of the checkpointed transactional memory state.
187+
* If we write over this non transactionally or in suspend, we are in
188+
* trouble because if we get a tm abort, the program counter and stack
189+
* pointer will be back at the tbegin but our in memory stack won't be
190+
* valid anymore.
191+
*
192+
* To avoid this, when taking a signal in an active transaction, we
193+
* need to use the stack pointer from the checkpointed state, rather
194+
* than the speculated state. This ensures that the signal context
195+
* (written tm suspended) will be written below the stack required for
196+
* the rollback. The transaction is aborted becuase of the treclaim,
197+
* so any memory written between the tbegin and the signal will be
198+
* rolled back anyway.
199+
*
200+
* For signals taken in non-TM or suspended mode, we use the
201+
* normal/non-checkpointed stack pointer.
202+
*/
203+
204+
#ifdef CONFIG_PPC_TRANSACTIONAL_MEM
205+
if (MSR_TM_ACTIVE(regs->msr)) {
206+
tm_enable();
207+
tm_reclaim(&current->thread, regs->msr, TM_CAUSE_SIGNAL);
208+
if (MSR_TM_TRANSACTIONAL(regs->msr))
209+
return current->thread.ckpt_regs.gpr[1];
210+
}
211+
#endif
212+
return regs->gpr[1];
213+
}

arch/powerpc/kernel/signal.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212

1313
extern void do_notify_resume(struct pt_regs *regs, unsigned long thread_info_flags);
1414

15-
extern void __user * get_sigframe(struct k_sigaction *ka, struct pt_regs *regs,
15+
extern void __user * get_sigframe(struct k_sigaction *ka, unsigned long sp,
1616
size_t frame_size, int is_32);
1717

1818
extern int handle_signal32(unsigned long sig, struct k_sigaction *ka,

arch/powerpc/kernel/signal_32.c

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -503,12 +503,6 @@ static int save_tm_user_regs(struct pt_regs *regs,
503503
{
504504
unsigned long msr = regs->msr;
505505

506-
/* tm_reclaim rolls back all reg states, updating thread.ckpt_regs,
507-
* thread.transact_fpr[], thread.transact_vr[], etc.
508-
*/
509-
tm_enable();
510-
tm_reclaim(&current->thread, msr, TM_CAUSE_SIGNAL);
511-
512506
/* Make sure floating point registers are stored in regs */
513507
flush_fp_to_thread(current);
514508

@@ -965,7 +959,7 @@ int handle_rt_signal32(unsigned long sig, struct k_sigaction *ka,
965959

966960
/* Set up Signal Frame */
967961
/* Put a Real Time Context onto stack */
968-
rt_sf = get_sigframe(ka, regs, sizeof(*rt_sf), 1);
962+
rt_sf = get_sigframe(ka, get_tm_stackpointer(regs), sizeof(*rt_sf), 1);
969963
addr = rt_sf;
970964
if (unlikely(rt_sf == NULL))
971965
goto badframe;
@@ -1403,7 +1397,7 @@ int handle_signal32(unsigned long sig, struct k_sigaction *ka,
14031397
unsigned long tramp;
14041398

14051399
/* Set up Signal Frame */
1406-
frame = get_sigframe(ka, regs, sizeof(*frame), 1);
1400+
frame = get_sigframe(ka, get_tm_stackpointer(regs), sizeof(*frame), 1);
14071401
if (unlikely(frame == NULL))
14081402
goto badframe;
14091403
sc = (struct sigcontext __user *) &frame->sctx;

arch/powerpc/kernel/signal_64.c

Lines changed: 7 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -154,11 +154,12 @@ static long setup_sigcontext(struct sigcontext __user *sc, struct pt_regs *regs,
154154
* As above, but Transactional Memory is in use, so deliver sigcontexts
155155
* containing checkpointed and transactional register states.
156156
*
157-
* To do this, we treclaim to gather both sets of registers and set up the
158-
* 'normal' sigcontext registers with rolled-back register values such that a
159-
* simple signal handler sees a correct checkpointed register state.
160-
* If interested, a TM-aware sighandler can examine the transactional registers
161-
* in the 2nd sigcontext to determine the real origin of the signal.
157+
* To do this, we treclaim (done before entering here) to gather both sets of
158+
* registers and set up the 'normal' sigcontext registers with rolled-back
159+
* register values such that a simple signal handler sees a correct
160+
* checkpointed register state. If interested, a TM-aware sighandler can
161+
* examine the transactional registers in the 2nd sigcontext to determine the
162+
* real origin of the signal.
162163
*/
163164
static long setup_tm_sigcontexts(struct sigcontext __user *sc,
164165
struct sigcontext __user *tm_sc,
@@ -184,16 +185,6 @@ static long setup_tm_sigcontexts(struct sigcontext __user *sc,
184185

185186
BUG_ON(!MSR_TM_ACTIVE(regs->msr));
186187

187-
/* tm_reclaim rolls back all reg states, saving checkpointed (older)
188-
* GPRs to thread.ckpt_regs and (if used) FPRs to (newer)
189-
* thread.transact_fp and/or VRs to (newer) thread.transact_vr.
190-
* THEN we save out FP/VRs, if necessary, to the checkpointed (older)
191-
* thread.fr[]/vr[]s. The transactional (newer) GPRs are on the
192-
* stack, in *regs.
193-
*/
194-
tm_enable();
195-
tm_reclaim(&current->thread, msr, TM_CAUSE_SIGNAL);
196-
197188
flush_fp_to_thread(current);
198189

199190
#ifdef CONFIG_ALTIVEC
@@ -711,7 +702,7 @@ int handle_rt_signal64(int signr, struct k_sigaction *ka, siginfo_t *info,
711702
unsigned long newsp = 0;
712703
long err = 0;
713704

714-
frame = get_sigframe(ka, regs, sizeof(*frame), 0);
705+
frame = get_sigframe(ka, get_tm_stackpointer(regs), sizeof(*frame), 0);
715706
if (unlikely(frame == NULL))
716707
goto badframe;
717708

0 commit comments

Comments
 (0)