mirror of
				https://github.com/torvalds/linux.git
				synced 2025-11-04 10:40:15 +02:00 
			
		
		
		
	powerpc: Documentation for transactional memory on powerpc
Signed-off-by: Matt Evans <matt@ozlabs.org> Signed-off-by: Michael Neuling <mikey@neuling.org> Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
This commit is contained in:
		
							parent
							
								
									81afe7d101
								
							
						
					
					
						commit
						db8ff90702
					
				
					 1 changed files with 175 additions and 0 deletions
				
			
		
							
								
								
									
										175
									
								
								Documentation/powerpc/transactional_memory.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										175
									
								
								Documentation/powerpc/transactional_memory.txt
									
									
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,175 @@
 | 
				
			||||||
 | 
					Transactional Memory support
 | 
				
			||||||
 | 
					============================
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					POWER kernel support for this feature is currently limited to supporting
 | 
				
			||||||
 | 
					its use by user programs.  It is not currently used by the kernel itself.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					This file aims to sum up how it is supported by Linux and what behaviour you
 | 
				
			||||||
 | 
					can expect from your user programs.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Basic overview
 | 
				
			||||||
 | 
					==============
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Hardware Transactional Memory is supported on POWER8 processors, and is a
 | 
				
			||||||
 | 
					feature that enables a different form of atomic memory access.  Several new
 | 
				
			||||||
 | 
					instructions are presented to delimit transactions; transactions are
 | 
				
			||||||
 | 
					guaranteed to either complete atomically or roll back and undo any partial
 | 
				
			||||||
 | 
					changes.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					A simple transaction looks like this:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					begin_move_money:
 | 
				
			||||||
 | 
					  tbegin
 | 
				
			||||||
 | 
					  beq   abort_handler
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  ld    r4, SAVINGS_ACCT(r3)
 | 
				
			||||||
 | 
					  ld    r5, CURRENT_ACCT(r3)
 | 
				
			||||||
 | 
					  subi  r5, r5, 1
 | 
				
			||||||
 | 
					  addi  r4, r4, 1
 | 
				
			||||||
 | 
					  std   r4, SAVINGS_ACCT(r3)
 | 
				
			||||||
 | 
					  std   r5, CURRENT_ACCT(r3)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  tend
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  b     continue
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					abort_handler:
 | 
				
			||||||
 | 
					  ... test for odd failures ...
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  /* Retry the transaction if it failed because it conflicted with
 | 
				
			||||||
 | 
					   * someone else: */
 | 
				
			||||||
 | 
					  b     begin_move_money
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					The 'tbegin' instruction denotes the start point, and 'tend' the end point.
 | 
				
			||||||
 | 
					Between these points the processor is in 'Transactional' state; any memory
 | 
				
			||||||
 | 
					references will complete in one go if there are no conflicts with other
 | 
				
			||||||
 | 
					transactional or non-transactional accesses within the system.  In this
 | 
				
			||||||
 | 
					example, the transaction completes as though it were normal straight-line code
 | 
				
			||||||
 | 
					IF no other processor has touched SAVINGS_ACCT(r3) or CURRENT_ACCT(r3); an
 | 
				
			||||||
 | 
					atomic move of money from the current account to the savings account has been
 | 
				
			||||||
 | 
					performed.  Even though the normal ld/std instructions are used (note no
 | 
				
			||||||
 | 
					lwarx/stwcx), either *both* SAVINGS_ACCT(r3) and CURRENT_ACCT(r3) will be
 | 
				
			||||||
 | 
					updated, or neither will be updated.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					If, in the meantime, there is a conflict with the locations accessed by the
 | 
				
			||||||
 | 
					transaction, the transaction will be aborted by the CPU.  Register and memory
 | 
				
			||||||
 | 
					state will roll back to that at the 'tbegin', and control will continue from
 | 
				
			||||||
 | 
					'tbegin+4'.  The branch to abort_handler will be taken this second time; the
 | 
				
			||||||
 | 
					abort handler can check the cause of the failure, and retry.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Checkpointed registers include all GPRs, FPRs, VRs/VSRs, LR, CCR/CR, CTR, FPCSR
 | 
				
			||||||
 | 
					and a few other status/flag regs; see the ISA for details.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Causes of transaction aborts
 | 
				
			||||||
 | 
					============================
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					- Conflicts with cache lines used by other processors
 | 
				
			||||||
 | 
					- Signals
 | 
				
			||||||
 | 
					- Context switches
 | 
				
			||||||
 | 
					- See the ISA for full documentation of everything that will abort transactions.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Syscalls
 | 
				
			||||||
 | 
					========
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Performing syscalls from within transaction is not recommended, and can lead
 | 
				
			||||||
 | 
					to unpredictable results.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Syscalls do not by design abort transactions, but beware: The kernel code will
 | 
				
			||||||
 | 
					not be running in transactional state.  The effect of syscalls will always
 | 
				
			||||||
 | 
					remain visible, but depending on the call they may abort your transaction as a
 | 
				
			||||||
 | 
					side-effect, read soon-to-be-aborted transactional data that should not remain
 | 
				
			||||||
 | 
					invisible, etc.  If you constantly retry a transaction that constantly aborts
 | 
				
			||||||
 | 
					itself by calling a syscall, you'll have a livelock & make no progress.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Simple syscalls (e.g. sigprocmask()) "could" be OK.  Even things like write()
 | 
				
			||||||
 | 
					from, say, printf() should be OK as long as the kernel does not access any
 | 
				
			||||||
 | 
					memory that was accessed transactionally.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Consider any syscalls that happen to work as debug-only -- not recommended for
 | 
				
			||||||
 | 
					production use.  Best to queue them up till after the transaction is over.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Signals
 | 
				
			||||||
 | 
					=======
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Delivery of signals (both sync and async) during transactions provides a second
 | 
				
			||||||
 | 
					thread state (ucontext/mcontext) to represent the second transactional register
 | 
				
			||||||
 | 
					state.  Signal delivery 'treclaim's to capture both register states, so signals
 | 
				
			||||||
 | 
					abort transactions.  The usual ucontext_t passed to the signal handler
 | 
				
			||||||
 | 
					represents the checkpointed/original register state; the signal appears to have
 | 
				
			||||||
 | 
					arisen at 'tbegin+4'.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					If the sighandler ucontext has uc_link set, a second ucontext has been
 | 
				
			||||||
 | 
					delivered.  For future compatibility the MSR.TS field should be checked to
 | 
				
			||||||
 | 
					determine the transactional state -- if so, the second ucontext in uc->uc_link
 | 
				
			||||||
 | 
					represents the active transactional registers at the point of the signal.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					For 64-bit processes, uc->uc_mcontext.regs->msr is a full 64-bit MSR and its TS
 | 
				
			||||||
 | 
					field shows the transactional mode.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					For 32-bit processes, the mcontext's MSR register is only 32 bits; the top 32
 | 
				
			||||||
 | 
					bits are stored in the MSR of the second ucontext, i.e. in
 | 
				
			||||||
 | 
					uc->uc_link->uc_mcontext.regs->msr.  The top word contains the transactional
 | 
				
			||||||
 | 
					state TS.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					However, basic signal handlers don't need to be aware of transactions
 | 
				
			||||||
 | 
					and simply returning from the handler will deal with things correctly:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Transaction-aware signal handlers can read the transactional register state
 | 
				
			||||||
 | 
					from the second ucontext.  This will be necessary for crash handlers to
 | 
				
			||||||
 | 
					determine, for example, the address of the instruction causing the SIGSEGV.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Example signal handler:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    void crash_handler(int sig, siginfo_t *si, void *uc)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					      ucontext_t *ucp = uc;
 | 
				
			||||||
 | 
					      ucontext_t *transactional_ucp = ucp->uc_link;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      if (ucp_link) {
 | 
				
			||||||
 | 
					        u64 msr = ucp->uc_mcontext.regs->msr;
 | 
				
			||||||
 | 
					        /* May have transactional ucontext! */
 | 
				
			||||||
 | 
					#ifndef __powerpc64__
 | 
				
			||||||
 | 
					        msr |= ((u64)transactional_ucp->uc_mcontext.regs->msr) << 32;
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					        if (MSR_TM_ACTIVE(msr)) {
 | 
				
			||||||
 | 
					           /* Yes, we crashed during a transaction.  Oops. */
 | 
				
			||||||
 | 
					   fprintf(stderr, "Transaction to be restarted at 0x%llx, but "
 | 
				
			||||||
 | 
					                           "crashy instruction was at 0x%llx\n",
 | 
				
			||||||
 | 
					                           ucp->uc_mcontext.regs->nip,
 | 
				
			||||||
 | 
					                           transactional_ucp->uc_mcontext.regs->nip);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      fix_the_problem(ucp->dar);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Failure cause codes used by kernel
 | 
				
			||||||
 | 
					==================================
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					These are defined in <asm/reg.h>, and distinguish different reasons why the
 | 
				
			||||||
 | 
					kernel aborted a transaction:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 TM_CAUSE_RESCHED       Thread was rescheduled.
 | 
				
			||||||
 | 
					 TM_CAUSE_FAC_UNAV      FP/VEC/VSX unavailable trap.
 | 
				
			||||||
 | 
					 TM_CAUSE_SYSCALL       Currently unused; future syscalls that must abort
 | 
				
			||||||
 | 
					                        transactions for consistency will use this.
 | 
				
			||||||
 | 
					 TM_CAUSE_SIGNAL        Signal delivered.
 | 
				
			||||||
 | 
					 TM_CAUSE_MISC          Currently unused.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					These can be checked by the user program's abort handler as TEXASR[0:7].
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					GDB
 | 
				
			||||||
 | 
					===
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					GDB and ptrace are not currently TM-aware.  If one stops during a transaction,
 | 
				
			||||||
 | 
					it looks like the transaction has just started (the checkpointed state is
 | 
				
			||||||
 | 
					presented).  The transaction cannot then be continued and will take the failure
 | 
				
			||||||
 | 
					handler route.  Furthermore, the transactional 2nd register state will be
 | 
				
			||||||
 | 
					inaccessible.  GDB can currently be used on programs using TM, but not sensibly
 | 
				
			||||||
 | 
					in parts within transactions.
 | 
				
			||||||
		Loading…
	
		Reference in a new issue