diff options
34 files changed, 2294 insertions, 100 deletions
diff --git a/Documentation/powerpc/transactional_memory.txt b/Documentation/powerpc/transactional_memory.txt new file mode 100644 index 000000000000..c907be41d60f --- /dev/null +++ b/Documentation/powerpc/transactional_memory.txt | |||
@@ -0,0 +1,175 @@ | |||
1 | Transactional Memory support | ||
2 | ============================ | ||
3 | |||
4 | POWER kernel support for this feature is currently limited to supporting | ||
5 | its use by user programs. It is not currently used by the kernel itself. | ||
6 | |||
7 | This file aims to sum up how it is supported by Linux and what behaviour you | ||
8 | can expect from your user programs. | ||
9 | |||
10 | |||
11 | Basic overview | ||
12 | ============== | ||
13 | |||
14 | Hardware Transactional Memory is supported on POWER8 processors, and is a | ||
15 | feature that enables a different form of atomic memory access. Several new | ||
16 | instructions are presented to delimit transactions; transactions are | ||
17 | guaranteed to either complete atomically or roll back and undo any partial | ||
18 | changes. | ||
19 | |||
20 | A simple transaction looks like this: | ||
21 | |||
22 | begin_move_money: | ||
23 | tbegin | ||
24 | beq abort_handler | ||
25 | |||
26 | ld r4, SAVINGS_ACCT(r3) | ||
27 | ld r5, CURRENT_ACCT(r3) | ||
28 | subi r5, r5, 1 | ||
29 | addi r4, r4, 1 | ||
30 | std r4, SAVINGS_ACCT(r3) | ||
31 | std r5, CURRENT_ACCT(r3) | ||
32 | |||
33 | tend | ||
34 | |||
35 | b continue | ||
36 | |||
37 | abort_handler: | ||
38 | ... test for odd failures ... | ||
39 | |||
40 | /* Retry the transaction if it failed because it conflicted with | ||
41 | * someone else: */ | ||
42 | b begin_move_money | ||
43 | |||
44 | |||
45 | The 'tbegin' instruction denotes the start point, and 'tend' the end point. | ||
46 | Between these points the processor is in 'Transactional' state; any memory | ||
47 | references will complete in one go if there are no conflicts with other | ||
48 | transactional or non-transactional accesses within the system. In this | ||
49 | example, the transaction completes as though it were normal straight-line code | ||
50 | IF no other processor has touched SAVINGS_ACCT(r3) or CURRENT_ACCT(r3); an | ||
51 | atomic move of money from the current account to the savings account has been | ||
52 | performed. Even though the normal ld/std instructions are used (note no | ||
53 | lwarx/stwcx), either *both* SAVINGS_ACCT(r3) and CURRENT_ACCT(r3) will be | ||
54 | updated, or neither will be updated. | ||
55 | |||
56 | If, in the meantime, there is a conflict with the locations accessed by the | ||
57 | transaction, the transaction will be aborted by the CPU. Register and memory | ||
58 | state will roll back to that at the 'tbegin', and control will continue from | ||
59 | 'tbegin+4'. The branch to abort_handler will be taken this second time; the | ||
60 | abort handler can check the cause of the failure, and retry. | ||
61 | |||
62 | Checkpointed registers include all GPRs, FPRs, VRs/VSRs, LR, CCR/CR, CTR, FPCSR | ||
63 | and a few other status/flag regs; see the ISA for details. | ||
64 | |||
65 | Causes of transaction aborts | ||
66 | ============================ | ||
67 | |||
68 | - Conflicts with cache lines used by other processors | ||
69 | - Signals | ||
70 | - Context switches | ||
71 | - See the ISA for full documentation of everything that will abort transactions. | ||
72 | |||
73 | |||
74 | Syscalls | ||
75 | ======== | ||
76 | |||
77 | Performing syscalls from within transaction is not recommended, and can lead | ||
78 | to unpredictable results. | ||
79 | |||
80 | Syscalls do not by design abort transactions, but beware: The kernel code will | ||
81 | not be running in transactional state. The effect of syscalls will always | ||
82 | remain visible, but depending on the call they may abort your transaction as a | ||
83 | side-effect, read soon-to-be-aborted transactional data that should not remain | ||
84 | invisible, etc. If you constantly retry a transaction that constantly aborts | ||
85 | itself by calling a syscall, you'll have a livelock & make no progress. | ||
86 | |||
87 | Simple syscalls (e.g. sigprocmask()) "could" be OK. Even things like write() | ||
88 | from, say, printf() should be OK as long as the kernel does not access any | ||
89 | memory that was accessed transactionally. | ||
90 | |||
91 | Consider any syscalls that happen to work as debug-only -- not recommended for | ||
92 | production use. Best to queue them up till after the transaction is over. | ||
93 | |||
94 | |||
95 | Signals | ||
96 | ======= | ||
97 | |||
98 | Delivery of signals (both sync and async) during transactions provides a second | ||
99 | thread state (ucontext/mcontext) to represent the second transactional register | ||
100 | state. Signal delivery 'treclaim's to capture both register states, so signals | ||
101 | abort transactions. The usual ucontext_t passed to the signal handler | ||
102 | represents the checkpointed/original register state; the signal appears to have | ||
103 | arisen at 'tbegin+4'. | ||
104 | |||
105 | If the sighandler ucontext has uc_link set, a second ucontext has been | ||
106 | delivered. For future compatibility the MSR.TS field should be checked to | ||
107 | determine the transactional state -- if so, the second ucontext in uc->uc_link | ||
108 | represents the active transactional registers at the point of the signal. | ||
109 | |||
110 | For 64-bit processes, uc->uc_mcontext.regs->msr is a full 64-bit MSR and its TS | ||
111 | field shows the transactional mode. | ||
112 | |||
113 | For 32-bit processes, the mcontext's MSR register is only 32 bits; the top 32 | ||
114 | bits are stored in the MSR of the second ucontext, i.e. in | ||
115 | uc->uc_link->uc_mcontext.regs->msr. The top word contains the transactional | ||
116 | state TS. | ||
117 | |||
118 | However, basic signal handlers don't need to be aware of transactions | ||
119 | and simply returning from the handler will deal with things correctly: | ||
120 | |||
121 | Transaction-aware signal handlers can read the transactional register state | ||
122 | from the second ucontext. This will be necessary for crash handlers to | ||
123 | determine, for example, the address of the instruction causing the SIGSEGV. | ||
124 | |||
125 | Example signal handler: | ||
126 | |||
127 | void crash_handler(int sig, siginfo_t *si, void *uc) | ||
128 | { | ||
129 | ucontext_t *ucp = uc; | ||
130 | ucontext_t *transactional_ucp = ucp->uc_link; | ||
131 | |||
132 | if (ucp_link) { | ||
133 | u64 msr = ucp->uc_mcontext.regs->msr; | ||
134 | /* May have transactional ucontext! */ | ||
135 | #ifndef __powerpc64__ | ||
136 | msr |= ((u64)transactional_ucp->uc_mcontext.regs->msr) << 32; | ||
137 | #endif | ||
138 | if (MSR_TM_ACTIVE(msr)) { | ||
139 | /* Yes, we crashed during a transaction. Oops. */ | ||
140 | fprintf(stderr, "Transaction to be restarted at 0x%llx, but " | ||
141 | "crashy instruction was at 0x%llx\n", | ||
142 | ucp->uc_mcontext.regs->nip, | ||
143 | transactional_ucp->uc_mcontext.regs->nip); | ||
144 | } | ||
145 | } | ||
146 | |||
147 | fix_the_problem(ucp->dar); | ||
148 | } | ||
149 | |||
150 | |||
151 | Failure cause codes used by kernel | ||
152 | ================================== | ||
153 | |||
154 | These are defined in <asm/reg.h>, and distinguish different reasons why the | ||
155 | kernel aborted a transaction: | ||
156 | |||
157 | TM_CAUSE_RESCHED Thread was rescheduled. | ||
158 | TM_CAUSE_FAC_UNAV FP/VEC/VSX unavailable trap. | ||
159 | TM_CAUSE_SYSCALL Currently unused; future syscalls that must abort | ||
160 | transactions for consistency will use this. | ||
161 | TM_CAUSE_SIGNAL Signal delivered. | ||
162 | TM_CAUSE_MISC Currently unused. | ||
163 | |||
164 | These can be checked by the user program's abort handler as TEXASR[0:7]. | ||
165 | |||
166 | |||
167 | GDB | ||
168 | === | ||
169 | |||
170 | GDB and ptrace are not currently TM-aware. If one stops during a transaction, | ||
171 | it looks like the transaction has just started (the checkpointed state is | ||
172 | presented). The transaction cannot then be continued and will take the failure | ||
173 | handler route. Furthermore, the transactional 2nd register state will be | ||
174 | inaccessible. GDB can currently be used on programs using TM, but not sensibly | ||
175 | in parts within transactions. | ||
diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig index 4b27edbdb799..85ff3a080360 100644 --- a/arch/powerpc/Kconfig +++ b/arch/powerpc/Kconfig | |||
@@ -313,6 +313,14 @@ config MATH_EMULATION | |||
313 | unit, which will allow programs that use floating-point | 313 | unit, which will allow programs that use floating-point |
314 | instructions to run. | 314 | instructions to run. |
315 | 315 | ||
316 | config PPC_TRANSACTIONAL_MEM | ||
317 | bool "Transactional Memory support for POWERPC" | ||
318 | depends on PPC_BOOK3S_64 | ||
319 | depends on SMP | ||
320 | default n | ||
321 | ---help--- | ||
322 | Support user-mode Transactional Memory on POWERPC. | ||
323 | |||
316 | config 8XX_MINIMAL_FPEMU | 324 | config 8XX_MINIMAL_FPEMU |
317 | bool "Minimal math emulation for 8xx" | 325 | bool "Minimal math emulation for 8xx" |
318 | depends on 8xx && !MATH_EMULATION | 326 | depends on 8xx && !MATH_EMULATION |
diff --git a/arch/powerpc/configs/ppc64_defconfig b/arch/powerpc/configs/ppc64_defconfig index 6cbdeb4290e2..aef3f71de5ad 100644 --- a/arch/powerpc/configs/ppc64_defconfig +++ b/arch/powerpc/configs/ppc64_defconfig | |||
@@ -49,6 +49,8 @@ CONFIG_CPU_FREQ_GOV_USERSPACE=y | |||
49 | CONFIG_CPU_FREQ_PMAC64=y | 49 | CONFIG_CPU_FREQ_PMAC64=y |
50 | CONFIG_HZ_100=y | 50 | CONFIG_HZ_100=y |
51 | CONFIG_BINFMT_MISC=m | 51 | CONFIG_BINFMT_MISC=m |
52 | CONFIG_PPC_TRANSACTIONAL_MEM=y | ||
53 | CONFIG_HOTPLUG_CPU=y | ||
52 | CONFIG_KEXEC=y | 54 | CONFIG_KEXEC=y |
53 | CONFIG_IRQ_ALL_CPUS=y | 55 | CONFIG_IRQ_ALL_CPUS=y |
54 | CONFIG_MEMORY_HOTREMOVE=y | 56 | CONFIG_MEMORY_HOTREMOVE=y |
diff --git a/arch/powerpc/configs/ps3_defconfig b/arch/powerpc/configs/ps3_defconfig index c2f4b4a86ece..7a5c15fcc7cf 100644 --- a/arch/powerpc/configs/ps3_defconfig +++ b/arch/powerpc/configs/ps3_defconfig | |||
@@ -6,6 +6,7 @@ CONFIG_NR_CPUS=2 | |||
6 | CONFIG_EXPERIMENTAL=y | 6 | CONFIG_EXPERIMENTAL=y |
7 | CONFIG_SYSVIPC=y | 7 | CONFIG_SYSVIPC=y |
8 | CONFIG_POSIX_MQUEUE=y | 8 | CONFIG_POSIX_MQUEUE=y |
9 | CONFIG_HIGH_RES_TIMERS=y | ||
9 | CONFIG_BLK_DEV_INITRD=y | 10 | CONFIG_BLK_DEV_INITRD=y |
10 | CONFIG_CC_OPTIMIZE_FOR_SIZE=y | 11 | CONFIG_CC_OPTIMIZE_FOR_SIZE=y |
11 | CONFIG_EMBEDDED=y | 12 | CONFIG_EMBEDDED=y |
@@ -24,12 +25,13 @@ CONFIG_PS3_DISK=y | |||
24 | CONFIG_PS3_ROM=y | 25 | CONFIG_PS3_ROM=y |
25 | CONFIG_PS3_FLASH=y | 26 | CONFIG_PS3_FLASH=y |
26 | CONFIG_PS3_VRAM=m | 27 | CONFIG_PS3_VRAM=m |
28 | CONFIG_PS3_LPM=m | ||
27 | # CONFIG_PPC_OF_BOOT_TRAMPOLINE is not set | 29 | # CONFIG_PPC_OF_BOOT_TRAMPOLINE is not set |
28 | CONFIG_HIGH_RES_TIMERS=y | ||
29 | # CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set | 30 | # CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set |
30 | CONFIG_BINFMT_MISC=y | 31 | CONFIG_BINFMT_MISC=y |
31 | CONFIG_KEXEC=y | 32 | CONFIG_KEXEC=y |
32 | # CONFIG_SPARSEMEM_VMEMMAP is not set | 33 | # CONFIG_SPARSEMEM_VMEMMAP is not set |
34 | # CONFIG_COMPACTION is not set | ||
33 | CONFIG_SCHED_SMT=y | 35 | CONFIG_SCHED_SMT=y |
34 | CONFIG_CMDLINE_BOOL=y | 36 | CONFIG_CMDLINE_BOOL=y |
35 | CONFIG_CMDLINE="" | 37 | CONFIG_CMDLINE="" |
@@ -59,6 +61,7 @@ CONFIG_BT_BNEP_PROTO_FILTER=y | |||
59 | CONFIG_BT_HIDP=m | 61 | CONFIG_BT_HIDP=m |
60 | CONFIG_BT_HCIBTUSB=m | 62 | CONFIG_BT_HCIBTUSB=m |
61 | CONFIG_CFG80211=m | 63 | CONFIG_CFG80211=m |
64 | CONFIG_CFG80211_WEXT=y | ||
62 | CONFIG_MAC80211=m | 65 | CONFIG_MAC80211=m |
63 | CONFIG_MAC80211_RC_PID=y | 66 | CONFIG_MAC80211_RC_PID=y |
64 | # CONFIG_MAC80211_RC_MINSTREL is not set | 67 | # CONFIG_MAC80211_RC_MINSTREL is not set |
@@ -78,7 +81,6 @@ CONFIG_MD=y | |||
78 | CONFIG_BLK_DEV_DM=m | 81 | CONFIG_BLK_DEV_DM=m |
79 | CONFIG_NETDEVICES=y | 82 | CONFIG_NETDEVICES=y |
80 | # CONFIG_NET_VENDOR_BROADCOM is not set | 83 | # CONFIG_NET_VENDOR_BROADCOM is not set |
81 | # CONFIG_NET_VENDOR_CHELSIO is not set | ||
82 | # CONFIG_NET_VENDOR_INTEL is not set | 84 | # CONFIG_NET_VENDOR_INTEL is not set |
83 | # CONFIG_NET_VENDOR_MARVELL is not set | 85 | # CONFIG_NET_VENDOR_MARVELL is not set |
84 | # CONFIG_NET_VENDOR_MICREL is not set | 86 | # CONFIG_NET_VENDOR_MICREL is not set |
@@ -119,21 +121,21 @@ CONFIG_SND=m | |||
119 | # CONFIG_SND_DRIVERS is not set | 121 | # CONFIG_SND_DRIVERS is not set |
120 | CONFIG_SND_USB_AUDIO=m | 122 | CONFIG_SND_USB_AUDIO=m |
121 | CONFIG_HIDRAW=y | 123 | CONFIG_HIDRAW=y |
122 | CONFIG_USB_HIDDEV=y | ||
123 | CONFIG_HID_APPLE=m | 124 | CONFIG_HID_APPLE=m |
124 | CONFIG_HID_BELKIN=m | 125 | CONFIG_HID_BELKIN=m |
125 | CONFIG_HID_CHERRY=m | 126 | CONFIG_HID_CHERRY=m |
126 | CONFIG_HID_EZKEY=m | 127 | CONFIG_HID_EZKEY=m |
127 | CONFIG_HID_TWINHAN=m | 128 | CONFIG_HID_TWINHAN=m |
128 | CONFIG_HID_LOGITECH=m | 129 | CONFIG_HID_LOGITECH=m |
130 | CONFIG_HID_LOGITECH_DJ=m | ||
129 | CONFIG_HID_MICROSOFT=m | 131 | CONFIG_HID_MICROSOFT=m |
132 | CONFIG_HID_PS3REMOTE=m | ||
130 | CONFIG_HID_SONY=m | 133 | CONFIG_HID_SONY=m |
131 | CONFIG_HID_SUNPLUS=m | 134 | CONFIG_HID_SUNPLUS=m |
132 | CONFIG_HID_SMARTJOYPLUS=m | 135 | CONFIG_HID_SMARTJOYPLUS=m |
136 | CONFIG_USB_HIDDEV=y | ||
133 | CONFIG_USB=m | 137 | CONFIG_USB=m |
134 | CONFIG_USB_ANNOUNCE_NEW_DEVICES=y | 138 | CONFIG_USB_ANNOUNCE_NEW_DEVICES=y |
135 | CONFIG_USB_DEVICEFS=y | ||
136 | # CONFIG_USB_DEVICE_CLASS is not set | ||
137 | CONFIG_USB_SUSPEND=y | 139 | CONFIG_USB_SUSPEND=y |
138 | CONFIG_USB_MON=m | 140 | CONFIG_USB_MON=m |
139 | CONFIG_USB_EHCI_HCD=m | 141 | CONFIG_USB_EHCI_HCD=m |
@@ -158,8 +160,8 @@ CONFIG_PROC_KCORE=y | |||
158 | CONFIG_TMPFS=y | 160 | CONFIG_TMPFS=y |
159 | CONFIG_HUGETLBFS=y | 161 | CONFIG_HUGETLBFS=y |
160 | CONFIG_NFS_FS=y | 162 | CONFIG_NFS_FS=y |
161 | CONFIG_NFS_V3=y | ||
162 | CONFIG_NFS_V4=y | 163 | CONFIG_NFS_V4=y |
164 | CONFIG_NFS_SWAP=y | ||
163 | CONFIG_ROOT_NFS=y | 165 | CONFIG_ROOT_NFS=y |
164 | CONFIG_CIFS=m | 166 | CONFIG_CIFS=m |
165 | CONFIG_NLS=y | 167 | CONFIG_NLS=y |
@@ -176,6 +178,7 @@ CONFIG_DEBUG_INFO=y | |||
176 | CONFIG_DEBUG_WRITECOUNT=y | 178 | CONFIG_DEBUG_WRITECOUNT=y |
177 | CONFIG_DEBUG_MEMORY_INIT=y | 179 | CONFIG_DEBUG_MEMORY_INIT=y |
178 | CONFIG_DEBUG_LIST=y | 180 | CONFIG_DEBUG_LIST=y |
181 | CONFIG_RCU_CPU_STALL_TIMEOUT=60 | ||
179 | # CONFIG_FTRACE is not set | 182 | # CONFIG_FTRACE is not set |
180 | CONFIG_DEBUG_STACKOVERFLOW=y | 183 | CONFIG_DEBUG_STACKOVERFLOW=y |
181 | CONFIG_CRYPTO_CCM=m | 184 | CONFIG_CRYPTO_CCM=m |
diff --git a/arch/powerpc/configs/pseries_defconfig b/arch/powerpc/configs/pseries_defconfig index 04fa7f2e295f..c4dfbaf8b192 100644 --- a/arch/powerpc/configs/pseries_defconfig +++ b/arch/powerpc/configs/pseries_defconfig | |||
@@ -43,6 +43,8 @@ CONFIG_RTAS_FLASH=m | |||
43 | CONFIG_IBMEBUS=y | 43 | CONFIG_IBMEBUS=y |
44 | CONFIG_HZ_100=y | 44 | CONFIG_HZ_100=y |
45 | CONFIG_BINFMT_MISC=m | 45 | CONFIG_BINFMT_MISC=m |
46 | CONFIG_PPC_TRANSACTIONAL_MEM=y | ||
47 | CONFIG_HOTPLUG_CPU=y | ||
46 | CONFIG_KEXEC=y | 48 | CONFIG_KEXEC=y |
47 | CONFIG_IRQ_ALL_CPUS=y | 49 | CONFIG_IRQ_ALL_CPUS=y |
48 | CONFIG_MEMORY_HOTPLUG=y | 50 | CONFIG_MEMORY_HOTPLUG=y |
diff --git a/arch/powerpc/include/asm/cputable.h b/arch/powerpc/include/asm/cputable.h index 5f1938fcce40..fb3245e928ea 100644 --- a/arch/powerpc/include/asm/cputable.h +++ b/arch/powerpc/include/asm/cputable.h | |||
@@ -220,6 +220,13 @@ extern const char *powerpc_base_platform; | |||
220 | #define PPC_FEATURE_HAS_EFP_DOUBLE_COMP 0 | 220 | #define PPC_FEATURE_HAS_EFP_DOUBLE_COMP 0 |
221 | #endif | 221 | #endif |
222 | 222 | ||
223 | /* We only set the TM feature if the kernel was compiled with TM supprt */ | ||
224 | #ifdef CONFIG_PPC_TRANSACTIONAL_MEM | ||
225 | #define CPU_FTR_TM_COMP CPU_FTR_TM | ||
226 | #else | ||
227 | #define CPU_FTR_TM_COMP 0 | ||
228 | #endif | ||
229 | |||
223 | /* We need to mark all pages as being coherent if we're SMP or we have a | 230 | /* We need to mark all pages as being coherent if we're SMP or we have a |
224 | * 74[45]x and an MPC107 host bridge. Also 83xx and PowerQUICC II | 231 | * 74[45]x and an MPC107 host bridge. Also 83xx and PowerQUICC II |
225 | * require it for PCI "streaming/prefetch" to work properly. | 232 | * require it for PCI "streaming/prefetch" to work properly. |
@@ -414,7 +421,8 @@ extern const char *powerpc_base_platform; | |||
414 | CPU_FTR_DSCR | CPU_FTR_SAO | \ | 421 | CPU_FTR_DSCR | CPU_FTR_SAO | \ |
415 | CPU_FTR_STCX_CHECKS_ADDRESS | CPU_FTR_POPCNTB | CPU_FTR_POPCNTD | \ | 422 | CPU_FTR_STCX_CHECKS_ADDRESS | CPU_FTR_POPCNTB | CPU_FTR_POPCNTD | \ |
416 | CPU_FTR_ICSWX | CPU_FTR_CFAR | CPU_FTR_HVMODE | CPU_FTR_VMX_COPY | \ | 423 | CPU_FTR_ICSWX | CPU_FTR_CFAR | CPU_FTR_HVMODE | CPU_FTR_VMX_COPY | \ |
417 | CPU_FTR_DBELL | CPU_FTR_HAS_PPR | CPU_FTR_DAWR | CPU_FTR_BCTAR) | 424 | CPU_FTR_DBELL | CPU_FTR_HAS_PPR | CPU_FTR_DAWR | CPU_FTR_BCTAR | \ |
425 | CPU_FTR_TM_COMP) | ||
418 | #define CPU_FTRS_CELL (CPU_FTR_USE_TB | CPU_FTR_LWSYNC | \ | 426 | #define CPU_FTRS_CELL (CPU_FTR_USE_TB | CPU_FTR_LWSYNC | \ |
419 | CPU_FTR_PPCAS_ARCH_V2 | CPU_FTR_CTRL | \ | 427 | CPU_FTR_PPCAS_ARCH_V2 | CPU_FTR_CTRL | \ |
420 | CPU_FTR_ALTIVEC_COMP | CPU_FTR_MMCRA | CPU_FTR_SMT | \ | 428 | CPU_FTR_ALTIVEC_COMP | CPU_FTR_MMCRA | CPU_FTR_SMT | \ |
diff --git a/arch/powerpc/include/asm/exception-64s.h b/arch/powerpc/include/asm/exception-64s.h index 370298a0bca3..05e6d2ee1db9 100644 --- a/arch/powerpc/include/asm/exception-64s.h +++ b/arch/powerpc/include/asm/exception-64s.h | |||
@@ -50,7 +50,7 @@ | |||
50 | #define EX_PPR 88 /* SMT thread status register (priority) */ | 50 | #define EX_PPR 88 /* SMT thread status register (priority) */ |
51 | 51 | ||
52 | #ifdef CONFIG_RELOCATABLE | 52 | #ifdef CONFIG_RELOCATABLE |
53 | #define EXCEPTION_RELON_PROLOG_PSERIES_1(label, h) \ | 53 | #define __EXCEPTION_RELON_PROLOG_PSERIES_1(label, h) \ |
54 | ld r12,PACAKBASE(r13); /* get high part of &label */ \ | 54 | ld r12,PACAKBASE(r13); /* get high part of &label */ \ |
55 | mfspr r11,SPRN_##h##SRR0; /* save SRR0 */ \ | 55 | mfspr r11,SPRN_##h##SRR0; /* save SRR0 */ \ |
56 | LOAD_HANDLER(r12,label); \ | 56 | LOAD_HANDLER(r12,label); \ |
@@ -61,13 +61,15 @@ | |||
61 | blr; | 61 | blr; |
62 | #else | 62 | #else |
63 | /* If not relocatable, we can jump directly -- and save messing with LR */ | 63 | /* If not relocatable, we can jump directly -- and save messing with LR */ |
64 | #define EXCEPTION_RELON_PROLOG_PSERIES_1(label, h) \ | 64 | #define __EXCEPTION_RELON_PROLOG_PSERIES_1(label, h) \ |
65 | mfspr r11,SPRN_##h##SRR0; /* save SRR0 */ \ | 65 | mfspr r11,SPRN_##h##SRR0; /* save SRR0 */ \ |
66 | mfspr r12,SPRN_##h##SRR1; /* and SRR1 */ \ | 66 | mfspr r12,SPRN_##h##SRR1; /* and SRR1 */ \ |
67 | li r10,MSR_RI; \ | 67 | li r10,MSR_RI; \ |
68 | mtmsrd r10,1; /* Set RI (EE=0) */ \ | 68 | mtmsrd r10,1; /* Set RI (EE=0) */ \ |
69 | b label; | 69 | b label; |
70 | #endif | 70 | #endif |
71 | #define EXCEPTION_RELON_PROLOG_PSERIES_1(label, h) \ | ||
72 | __EXCEPTION_RELON_PROLOG_PSERIES_1(label, h) \ | ||
71 | 73 | ||
72 | /* | 74 | /* |
73 | * As EXCEPTION_PROLOG_PSERIES(), except we've already got relocation on | 75 | * As EXCEPTION_PROLOG_PSERIES(), except we've already got relocation on |
@@ -75,6 +77,7 @@ | |||
75 | * case EXCEPTION_RELON_PROLOG_PSERIES_1 will be using lr. | 77 | * case EXCEPTION_RELON_PROLOG_PSERIES_1 will be using lr. |
76 | */ | 78 | */ |
77 | #define EXCEPTION_RELON_PROLOG_PSERIES(area, label, h, extra, vec) \ | 79 | #define EXCEPTION_RELON_PROLOG_PSERIES(area, label, h, extra, vec) \ |
80 | EXCEPTION_PROLOG_0(area); \ | ||
78 | EXCEPTION_PROLOG_1(area, extra, vec); \ | 81 | EXCEPTION_PROLOG_1(area, extra, vec); \ |
79 | EXCEPTION_RELON_PROLOG_PSERIES_1(label, h) | 82 | EXCEPTION_RELON_PROLOG_PSERIES_1(label, h) |
80 | 83 | ||
@@ -135,25 +138,32 @@ BEGIN_FTR_SECTION_NESTED(942) \ | |||
135 | END_FTR_SECTION_NESTED(CPU_FTR_HAS_PPR,0,942) /*non P7*/ | 138 | END_FTR_SECTION_NESTED(CPU_FTR_HAS_PPR,0,942) /*non P7*/ |
136 | 139 | ||
137 | /* | 140 | /* |
138 | * Save PPR in paca whenever some register is available to use. | 141 | * Get an SPR into a register if the CPU has the given feature |
139 | * Then increase the priority. | ||
140 | */ | 142 | */ |
141 | #define HMT_MEDIUM_PPR_SAVE(area, ra) \ | 143 | #define OPT_GET_SPR(ra, spr, ftr) \ |
142 | BEGIN_FTR_SECTION_NESTED(943) \ | 144 | BEGIN_FTR_SECTION_NESTED(943) \ |
143 | mfspr ra,SPRN_PPR; \ | 145 | mfspr ra,spr; \ |
144 | std ra,area+EX_PPR(r13); \ | 146 | END_FTR_SECTION_NESTED(ftr,ftr,943) |
145 | HMT_MEDIUM; \ | ||
146 | END_FTR_SECTION_NESTED(CPU_FTR_HAS_PPR,CPU_FTR_HAS_PPR,943) | ||
147 | 147 | ||
148 | #define __EXCEPTION_PROLOG_1(area, extra, vec) \ | 148 | /* |
149 | * Save a register to the PACA if the CPU has the given feature | ||
150 | */ | ||
151 | #define OPT_SAVE_REG_TO_PACA(offset, ra, ftr) \ | ||
152 | BEGIN_FTR_SECTION_NESTED(943) \ | ||
153 | std ra,offset(r13); \ | ||
154 | END_FTR_SECTION_NESTED(ftr,ftr,943) | ||
155 | |||
156 | #define EXCEPTION_PROLOG_0(area) \ | ||
149 | GET_PACA(r13); \ | 157 | GET_PACA(r13); \ |
150 | std r9,area+EX_R9(r13); /* save r9 */ \ | 158 | std r9,area+EX_R9(r13); /* save r9 */ \ |
151 | HMT_MEDIUM_PPR_SAVE(area, r9); \ | 159 | OPT_GET_SPR(r9, SPRN_PPR, CPU_FTR_HAS_PPR); \ |
160 | HMT_MEDIUM; \ | ||
152 | std r10,area+EX_R10(r13); /* save r10 - r12 */ \ | 161 | std r10,area+EX_R10(r13); /* save r10 - r12 */ \ |
153 | BEGIN_FTR_SECTION_NESTED(66); \ | 162 | OPT_GET_SPR(r10, SPRN_CFAR, CPU_FTR_CFAR) |
154 | mfspr r10,SPRN_CFAR; \ | 163 | |
155 | std r10,area+EX_CFAR(r13); \ | 164 | #define __EXCEPTION_PROLOG_1(area, extra, vec) \ |
156 | END_FTR_SECTION_NESTED(CPU_FTR_CFAR, CPU_FTR_CFAR, 66); \ | 165 | OPT_SAVE_REG_TO_PACA(area+EX_PPR, r9, CPU_FTR_HAS_PPR); \ |
166 | OPT_SAVE_REG_TO_PACA(area+EX_CFAR, r10, CPU_FTR_CFAR); \ | ||
157 | SAVE_LR(r10, area); \ | 167 | SAVE_LR(r10, area); \ |
158 | mfcr r9; \ | 168 | mfcr r9; \ |
159 | extra(vec); \ | 169 | extra(vec); \ |
@@ -178,6 +188,7 @@ END_FTR_SECTION_NESTED(CPU_FTR_HAS_PPR,CPU_FTR_HAS_PPR,943) | |||
178 | __EXCEPTION_PROLOG_PSERIES_1(label, h) | 188 | __EXCEPTION_PROLOG_PSERIES_1(label, h) |
179 | 189 | ||
180 | #define EXCEPTION_PROLOG_PSERIES(area, label, h, extra, vec) \ | 190 | #define EXCEPTION_PROLOG_PSERIES(area, label, h, extra, vec) \ |
191 | EXCEPTION_PROLOG_0(area); \ | ||
181 | EXCEPTION_PROLOG_1(area, extra, vec); \ | 192 | EXCEPTION_PROLOG_1(area, extra, vec); \ |
182 | EXCEPTION_PROLOG_PSERIES_1(label, h); | 193 | EXCEPTION_PROLOG_PSERIES_1(label, h); |
183 | 194 | ||
@@ -188,10 +199,14 @@ END_FTR_SECTION_NESTED(CPU_FTR_HAS_PPR,CPU_FTR_HAS_PPR,943) | |||
188 | 199 | ||
189 | #define __KVM_HANDLER(area, h, n) \ | 200 | #define __KVM_HANDLER(area, h, n) \ |
190 | do_kvm_##n: \ | 201 | do_kvm_##n: \ |
202 | BEGIN_FTR_SECTION_NESTED(947) \ | ||
203 | ld r10,area+EX_CFAR(r13); \ | ||
204 | std r10,HSTATE_CFAR(r13); \ | ||
205 | END_FTR_SECTION_NESTED(CPU_FTR_CFAR,CPU_FTR_CFAR,947); \ | ||
191 | ld r10,area+EX_R10(r13); \ | 206 | ld r10,area+EX_R10(r13); \ |
192 | stw r9,HSTATE_SCRATCH1(r13); \ | 207 | stw r9,HSTATE_SCRATCH1(r13); \ |
193 | ld r9,area+EX_R9(r13); \ | 208 | ld r9,area+EX_R9(r13); \ |
194 | std r12,HSTATE_SCRATCH0(r13); \ | 209 | std r12,HSTATE_SCRATCH0(r13); \ |
195 | li r12,n; \ | 210 | li r12,n; \ |
196 | b kvmppc_interrupt | 211 | b kvmppc_interrupt |
197 | 212 | ||
@@ -312,6 +327,13 @@ label##_pSeries: \ | |||
312 | EXCEPTION_PROLOG_PSERIES(PACA_EXGEN, label##_common, \ | 327 | EXCEPTION_PROLOG_PSERIES(PACA_EXGEN, label##_common, \ |
313 | EXC_STD, KVMTEST_PR, vec) | 328 | EXC_STD, KVMTEST_PR, vec) |
314 | 329 | ||
330 | /* Version of above for when we have to branch out-of-line */ | ||
331 | #define STD_EXCEPTION_PSERIES_OOL(vec, label) \ | ||
332 | .globl label##_pSeries; \ | ||
333 | label##_pSeries: \ | ||
334 | EXCEPTION_PROLOG_1(PACA_EXGEN, KVMTEST_PR, vec); \ | ||
335 | EXCEPTION_PROLOG_PSERIES_1(label##_common, EXC_STD) | ||
336 | |||
315 | #define STD_EXCEPTION_HV(loc, vec, label) \ | 337 | #define STD_EXCEPTION_HV(loc, vec, label) \ |
316 | . = loc; \ | 338 | . = loc; \ |
317 | .globl label##_hv; \ | 339 | .globl label##_hv; \ |
@@ -321,6 +343,13 @@ label##_hv: \ | |||
321 | EXCEPTION_PROLOG_PSERIES(PACA_EXGEN, label##_common, \ | 343 | EXCEPTION_PROLOG_PSERIES(PACA_EXGEN, label##_common, \ |
322 | EXC_HV, KVMTEST, vec) | 344 | EXC_HV, KVMTEST, vec) |
323 | 345 | ||
346 | /* Version of above for when we have to branch out-of-line */ | ||
347 | #define STD_EXCEPTION_HV_OOL(vec, label) \ | ||
348 | .globl label##_hv; \ | ||
349 | label##_hv: \ | ||
350 | EXCEPTION_PROLOG_1(PACA_EXGEN, KVMTEST, vec); \ | ||
351 | EXCEPTION_PROLOG_PSERIES_1(label##_common, EXC_HV) | ||
352 | |||
324 | #define STD_RELON_EXCEPTION_PSERIES(loc, vec, label) \ | 353 | #define STD_RELON_EXCEPTION_PSERIES(loc, vec, label) \ |
325 | . = loc; \ | 354 | . = loc; \ |
326 | .globl label##_relon_pSeries; \ | 355 | .globl label##_relon_pSeries; \ |
@@ -331,6 +360,12 @@ label##_relon_pSeries: \ | |||
331 | EXCEPTION_RELON_PROLOG_PSERIES(PACA_EXGEN, label##_common, \ | 360 | EXCEPTION_RELON_PROLOG_PSERIES(PACA_EXGEN, label##_common, \ |
332 | EXC_STD, KVMTEST_PR, vec) | 361 | EXC_STD, KVMTEST_PR, vec) |
333 | 362 | ||
363 | #define STD_RELON_EXCEPTION_PSERIES_OOL(vec, label) \ | ||
364 | .globl label##_relon_pSeries; \ | ||
365 | label##_relon_pSeries: \ | ||
366 | EXCEPTION_PROLOG_1(PACA_EXGEN, KVMTEST_PR, vec); \ | ||
367 | EXCEPTION_RELON_PROLOG_PSERIES_1(label##_common, EXC_STD) | ||
368 | |||
334 | #define STD_RELON_EXCEPTION_HV(loc, vec, label) \ | 369 | #define STD_RELON_EXCEPTION_HV(loc, vec, label) \ |
335 | . = loc; \ | 370 | . = loc; \ |
336 | .globl label##_relon_hv; \ | 371 | .globl label##_relon_hv; \ |
@@ -341,6 +376,12 @@ label##_relon_hv: \ | |||
341 | EXCEPTION_RELON_PROLOG_PSERIES(PACA_EXGEN, label##_common, \ | 376 | EXCEPTION_RELON_PROLOG_PSERIES(PACA_EXGEN, label##_common, \ |
342 | EXC_HV, KVMTEST, vec) | 377 | EXC_HV, KVMTEST, vec) |
343 | 378 | ||
379 | #define STD_RELON_EXCEPTION_HV_OOL(vec, label) \ | ||
380 | .globl label##_relon_hv; \ | ||
381 | label##_relon_hv: \ | ||
382 | EXCEPTION_PROLOG_1(PACA_EXGEN, KVMTEST, vec); \ | ||
383 | EXCEPTION_RELON_PROLOG_PSERIES_1(label##_common, EXC_HV) | ||
384 | |||
344 | /* This associate vector numbers with bits in paca->irq_happened */ | 385 | /* This associate vector numbers with bits in paca->irq_happened */ |
345 | #define SOFTEN_VALUE_0x500 PACA_IRQ_EE | 386 | #define SOFTEN_VALUE_0x500 PACA_IRQ_EE |
346 | #define SOFTEN_VALUE_0x502 PACA_IRQ_EE | 387 | #define SOFTEN_VALUE_0x502 PACA_IRQ_EE |
@@ -375,8 +416,10 @@ label##_relon_hv: \ | |||
375 | #define __MASKABLE_EXCEPTION_PSERIES(vec, label, h, extra) \ | 416 | #define __MASKABLE_EXCEPTION_PSERIES(vec, label, h, extra) \ |
376 | HMT_MEDIUM_PPR_DISCARD; \ | 417 | HMT_MEDIUM_PPR_DISCARD; \ |
377 | SET_SCRATCH0(r13); /* save r13 */ \ | 418 | SET_SCRATCH0(r13); /* save r13 */ \ |
378 | __EXCEPTION_PROLOG_1(PACA_EXGEN, extra, vec); \ | 419 | EXCEPTION_PROLOG_0(PACA_EXGEN); \ |
420 | __EXCEPTION_PROLOG_1(PACA_EXGEN, extra, vec); \ | ||
379 | EXCEPTION_PROLOG_PSERIES_1(label##_common, h); | 421 | EXCEPTION_PROLOG_PSERIES_1(label##_common, h); |
422 | |||
380 | #define _MASKABLE_EXCEPTION_PSERIES(vec, label, h, extra) \ | 423 | #define _MASKABLE_EXCEPTION_PSERIES(vec, label, h, extra) \ |
381 | __MASKABLE_EXCEPTION_PSERIES(vec, label, h, extra) | 424 | __MASKABLE_EXCEPTION_PSERIES(vec, label, h, extra) |
382 | 425 | ||
@@ -394,9 +437,16 @@ label##_hv: \ | |||
394 | _MASKABLE_EXCEPTION_PSERIES(vec, label, \ | 437 | _MASKABLE_EXCEPTION_PSERIES(vec, label, \ |
395 | EXC_HV, SOFTEN_TEST_HV) | 438 | EXC_HV, SOFTEN_TEST_HV) |
396 | 439 | ||
440 | #define MASKABLE_EXCEPTION_HV_OOL(vec, label) \ | ||
441 | .globl label##_hv; \ | ||
442 | label##_hv: \ | ||
443 | EXCEPTION_PROLOG_1(PACA_EXGEN, SOFTEN_TEST_HV, vec); \ | ||
444 | EXCEPTION_PROLOG_PSERIES_1(label##_common, EXC_HV); | ||
445 | |||
397 | #define __MASKABLE_RELON_EXCEPTION_PSERIES(vec, label, h, extra) \ | 446 | #define __MASKABLE_RELON_EXCEPTION_PSERIES(vec, label, h, extra) \ |
398 | HMT_MEDIUM_PPR_DISCARD; \ | 447 | HMT_MEDIUM_PPR_DISCARD; \ |
399 | SET_SCRATCH0(r13); /* save r13 */ \ | 448 | SET_SCRATCH0(r13); /* save r13 */ \ |
449 | EXCEPTION_PROLOG_0(PACA_EXGEN); \ | ||
400 | __EXCEPTION_PROLOG_1(PACA_EXGEN, extra, vec); \ | 450 | __EXCEPTION_PROLOG_1(PACA_EXGEN, extra, vec); \ |
401 | EXCEPTION_RELON_PROLOG_PSERIES_1(label##_common, h); | 451 | EXCEPTION_RELON_PROLOG_PSERIES_1(label##_common, h); |
402 | #define _MASKABLE_RELON_EXCEPTION_PSERIES(vec, label, h, extra) \ | 452 | #define _MASKABLE_RELON_EXCEPTION_PSERIES(vec, label, h, extra) \ |
@@ -416,6 +466,12 @@ label##_relon_hv: \ | |||
416 | _MASKABLE_RELON_EXCEPTION_PSERIES(vec, label, \ | 466 | _MASKABLE_RELON_EXCEPTION_PSERIES(vec, label, \ |
417 | EXC_HV, SOFTEN_NOTEST_HV) | 467 | EXC_HV, SOFTEN_NOTEST_HV) |
418 | 468 | ||
469 | #define MASKABLE_RELON_EXCEPTION_HV_OOL(vec, label) \ | ||
470 | .globl label##_relon_hv; \ | ||
471 | label##_relon_hv: \ | ||
472 | EXCEPTION_PROLOG_1(PACA_EXGEN, SOFTEN_NOTEST_HV, vec); \ | ||
473 | EXCEPTION_PROLOG_PSERIES_1(label##_common, EXC_HV); | ||
474 | |||
419 | /* | 475 | /* |
420 | * Our exception common code can be passed various "additions" | 476 | * Our exception common code can be passed various "additions" |
421 | * to specify the behaviour of interrupts, whether to kick the | 477 | * to specify the behaviour of interrupts, whether to kick the |
diff --git a/arch/powerpc/include/asm/kvm_book3s_asm.h b/arch/powerpc/include/asm/kvm_book3s_asm.h index 88609b23b775..cdc3d2717cc6 100644 --- a/arch/powerpc/include/asm/kvm_book3s_asm.h +++ b/arch/powerpc/include/asm/kvm_book3s_asm.h | |||
@@ -93,6 +93,9 @@ struct kvmppc_host_state { | |||
93 | u64 host_dscr; | 93 | u64 host_dscr; |
94 | u64 dec_expires; | 94 | u64 dec_expires; |
95 | #endif | 95 | #endif |
96 | #ifdef CONFIG_PPC_BOOK3S_64 | ||
97 | u64 cfar; | ||
98 | #endif | ||
96 | }; | 99 | }; |
97 | 100 | ||
98 | struct kvmppc_book3s_shadow_vcpu { | 101 | struct kvmppc_book3s_shadow_vcpu { |
diff --git a/arch/powerpc/include/asm/kvm_host.h b/arch/powerpc/include/asm/kvm_host.h index ca9bf459db6a..03d7beae89a0 100644 --- a/arch/powerpc/include/asm/kvm_host.h +++ b/arch/powerpc/include/asm/kvm_host.h | |||
@@ -440,6 +440,7 @@ struct kvm_vcpu_arch { | |||
440 | ulong uamor; | 440 | ulong uamor; |
441 | u32 ctrl; | 441 | u32 ctrl; |
442 | ulong dabr; | 442 | ulong dabr; |
443 | ulong cfar; | ||
443 | #endif | 444 | #endif |
444 | u32 vrsave; /* also USPRG0 */ | 445 | u32 vrsave; /* also USPRG0 */ |
445 | u32 mmucr; | 446 | u32 mmucr; |
diff --git a/arch/powerpc/include/asm/paca.h b/arch/powerpc/include/asm/paca.h index c47d687ab01b..77c91e74b612 100644 --- a/arch/powerpc/include/asm/paca.h +++ b/arch/powerpc/include/asm/paca.h | |||
@@ -137,6 +137,9 @@ struct paca_struct { | |||
137 | u8 irq_work_pending; /* IRQ_WORK interrupt while soft-disable */ | 137 | u8 irq_work_pending; /* IRQ_WORK interrupt while soft-disable */ |
138 | u8 nap_state_lost; /* NV GPR values lost in power7_idle */ | 138 | u8 nap_state_lost; /* NV GPR values lost in power7_idle */ |
139 | u64 sprg3; /* Saved user-visible sprg */ | 139 | u64 sprg3; /* Saved user-visible sprg */ |
140 | #ifdef CONFIG_PPC_TRANSACTIONAL_MEM | ||
141 | u64 tm_scratch; /* TM scratch area for reclaim */ | ||
142 | #endif | ||
140 | 143 | ||
141 | #ifdef CONFIG_PPC_POWERNV | 144 | #ifdef CONFIG_PPC_POWERNV |
142 | /* Pointer to OPAL machine check event structure set by the | 145 | /* Pointer to OPAL machine check event structure set by the |
@@ -167,7 +170,6 @@ struct paca_struct { | |||
167 | }; | 170 | }; |
168 | 171 | ||
169 | extern struct paca_struct *paca; | 172 | extern struct paca_struct *paca; |
170 | extern __initdata struct paca_struct boot_paca; | ||
171 | extern void initialise_paca(struct paca_struct *new_paca, int cpu); | 173 | extern void initialise_paca(struct paca_struct *new_paca, int cpu); |
172 | extern void setup_paca(struct paca_struct *new_paca); | 174 | extern void setup_paca(struct paca_struct *new_paca); |
173 | extern void allocate_pacas(void); | 175 | extern void allocate_pacas(void); |
diff --git a/arch/powerpc/include/asm/ppc-opcode.h b/arch/powerpc/include/asm/ppc-opcode.h index 0fd1928efb93..8752bc8e34a3 100644 --- a/arch/powerpc/include/asm/ppc-opcode.h +++ b/arch/powerpc/include/asm/ppc-opcode.h | |||
@@ -129,6 +129,9 @@ | |||
129 | #define PPC_INST_TLBSRX_DOT 0x7c0006a5 | 129 | #define PPC_INST_TLBSRX_DOT 0x7c0006a5 |
130 | #define PPC_INST_XXLOR 0xf0000510 | 130 | #define PPC_INST_XXLOR 0xf0000510 |
131 | #define PPC_INST_XVCPSGNDP 0xf0000780 | 131 | #define PPC_INST_XVCPSGNDP 0xf0000780 |
132 | #define PPC_INST_TRECHKPT 0x7c0007dd | ||
133 | #define PPC_INST_TRECLAIM 0x7c00075d | ||
134 | #define PPC_INST_TABORT 0x7c00071d | ||
132 | 135 | ||
133 | #define PPC_INST_NAP 0x4c000364 | 136 | #define PPC_INST_NAP 0x4c000364 |
134 | #define PPC_INST_SLEEP 0x4c0003a4 | 137 | #define PPC_INST_SLEEP 0x4c0003a4 |
@@ -294,4 +297,11 @@ | |||
294 | #define PPC_NAP stringify_in_c(.long PPC_INST_NAP) | 297 | #define PPC_NAP stringify_in_c(.long PPC_INST_NAP) |
295 | #define PPC_SLEEP stringify_in_c(.long PPC_INST_SLEEP) | 298 | #define PPC_SLEEP stringify_in_c(.long PPC_INST_SLEEP) |
296 | 299 | ||
300 | /* Transactional memory instructions */ | ||
301 | #define TRECHKPT stringify_in_c(.long PPC_INST_TRECHKPT) | ||
302 | #define TRECLAIM(r) stringify_in_c(.long PPC_INST_TRECLAIM \ | ||
303 | | __PPC_RA(r)) | ||
304 | #define TABORT(r) stringify_in_c(.long PPC_INST_TABORT \ | ||
305 | | __PPC_RA(r)) | ||
306 | |||
297 | #endif /* _ASM_POWERPC_PPC_OPCODE_H */ | 307 | #endif /* _ASM_POWERPC_PPC_OPCODE_H */ |
diff --git a/arch/powerpc/include/asm/ppc_asm.h b/arch/powerpc/include/asm/ppc_asm.h index c2d0e58aba31..54219cea9e88 100644 --- a/arch/powerpc/include/asm/ppc_asm.h +++ b/arch/powerpc/include/asm/ppc_asm.h | |||
@@ -123,6 +123,89 @@ END_FW_FTR_SECTION_IFSET(FW_FEATURE_SPLPAR) | |||
123 | #define REST_16VRS(n,b,base) REST_8VRS(n,b,base); REST_8VRS(n+8,b,base) | 123 | #define REST_16VRS(n,b,base) REST_8VRS(n,b,base); REST_8VRS(n+8,b,base) |
124 | #define REST_32VRS(n,b,base) REST_16VRS(n,b,base); REST_16VRS(n+16,b,base) | 124 | #define REST_32VRS(n,b,base) REST_16VRS(n,b,base); REST_16VRS(n+16,b,base) |
125 | 125 | ||
126 | /* Save/restore FPRs, VRs and VSRs from their checkpointed backups in | ||
127 | * thread_struct: | ||
128 | */ | ||
129 | #define SAVE_FPR_TRANSACT(n, base) stfd n,THREAD_TRANSACT_FPR0+ \ | ||
130 | 8*TS_FPRWIDTH*(n)(base) | ||
131 | #define SAVE_2FPRS_TRANSACT(n, base) SAVE_FPR_TRANSACT(n, base); \ | ||
132 | SAVE_FPR_TRANSACT(n+1, base) | ||
133 | #define SAVE_4FPRS_TRANSACT(n, base) SAVE_2FPRS_TRANSACT(n, base); \ | ||
134 | SAVE_2FPRS_TRANSACT(n+2, base) | ||
135 | #define SAVE_8FPRS_TRANSACT(n, base) SAVE_4FPRS_TRANSACT(n, base); \ | ||
136 | SAVE_4FPRS_TRANSACT(n+4, base) | ||
137 | #define SAVE_16FPRS_TRANSACT(n, base) SAVE_8FPRS_TRANSACT(n, base); \ | ||
138 | SAVE_8FPRS_TRANSACT(n+8, base) | ||
139 | #define SAVE_32FPRS_TRANSACT(n, base) SAVE_16FPRS_TRANSACT(n, base); \ | ||
140 | SAVE_16FPRS_TRANSACT(n+16, base) | ||
141 | |||
142 | #define REST_FPR_TRANSACT(n, base) lfd n,THREAD_TRANSACT_FPR0+ \ | ||
143 | 8*TS_FPRWIDTH*(n)(base) | ||
144 | #define REST_2FPRS_TRANSACT(n, base) REST_FPR_TRANSACT(n, base); \ | ||
145 | REST_FPR_TRANSACT(n+1, base) | ||
146 | #define REST_4FPRS_TRANSACT(n, base) REST_2FPRS_TRANSACT(n, base); \ | ||
147 | REST_2FPRS_TRANSACT(n+2, base) | ||
148 | #define REST_8FPRS_TRANSACT(n, base) REST_4FPRS_TRANSACT(n, base); \ | ||
149 | REST_4FPRS_TRANSACT(n+4, base) | ||
150 | #define REST_16FPRS_TRANSACT(n, base) REST_8FPRS_TRANSACT(n, base); \ | ||
151 | REST_8FPRS_TRANSACT(n+8, base) | ||
152 | #define REST_32FPRS_TRANSACT(n, base) REST_16FPRS_TRANSACT(n, base); \ | ||
153 | REST_16FPRS_TRANSACT(n+16, base) | ||
154 | |||
155 | |||
156 | #define SAVE_VR_TRANSACT(n,b,base) li b,THREAD_TRANSACT_VR0+(16*(n)); \ | ||
157 | stvx n,b,base | ||
158 | #define SAVE_2VRS_TRANSACT(n,b,base) SAVE_VR_TRANSACT(n,b,base); \ | ||
159 | SAVE_VR_TRANSACT(n+1,b,base) | ||
160 | #define SAVE_4VRS_TRANSACT(n,b,base) SAVE_2VRS_TRANSACT(n,b,base); \ | ||
161 | SAVE_2VRS_TRANSACT(n+2,b,base) | ||
162 | #define SAVE_8VRS_TRANSACT(n,b,base) SAVE_4VRS_TRANSACT(n,b,base); \ | ||
163 | SAVE_4VRS_TRANSACT(n+4,b,base) | ||
164 | #define SAVE_16VRS_TRANSACT(n,b,base) SAVE_8VRS_TRANSACT(n,b,base); \ | ||
165 | SAVE_8VRS_TRANSACT(n+8,b,base) | ||
166 | #define SAVE_32VRS_TRANSACT(n,b,base) SAVE_16VRS_TRANSACT(n,b,base); \ | ||
167 | SAVE_16VRS_TRANSACT(n+16,b,base) | ||
168 | |||
169 | #define REST_VR_TRANSACT(n,b,base) li b,THREAD_TRANSACT_VR0+(16*(n)); \ | ||
170 | lvx n,b,base | ||
171 | #define REST_2VRS_TRANSACT(n,b,base) REST_VR_TRANSACT(n,b,base); \ | ||
172 | REST_VR_TRANSACT(n+1,b,base) | ||
173 | #define REST_4VRS_TRANSACT(n,b,base) REST_2VRS_TRANSACT(n,b,base); \ | ||
174 | REST_2VRS_TRANSACT(n+2,b,base) | ||
175 | #define REST_8VRS_TRANSACT(n,b,base) REST_4VRS_TRANSACT(n,b,base); \ | ||
176 | REST_4VRS_TRANSACT(n+4,b,base) | ||
177 | #define REST_16VRS_TRANSACT(n,b,base) REST_8VRS_TRANSACT(n,b,base); \ | ||
178 | REST_8VRS_TRANSACT(n+8,b,base) | ||
179 | #define REST_32VRS_TRANSACT(n,b,base) REST_16VRS_TRANSACT(n,b,base); \ | ||
180 | REST_16VRS_TRANSACT(n+16,b,base) | ||
181 | |||
182 | |||
183 | #define SAVE_VSR_TRANSACT(n,b,base) li b,THREAD_TRANSACT_VSR0+(16*(n)); \ | ||
184 | STXVD2X(n,R##base,R##b) | ||
185 | #define SAVE_2VSRS_TRANSACT(n,b,base) SAVE_VSR_TRANSACT(n,b,base); \ | ||
186 | SAVE_VSR_TRANSACT(n+1,b,base) | ||
187 | #define SAVE_4VSRS_TRANSACT(n,b,base) SAVE_2VSRS_TRANSACT(n,b,base); \ | ||
188 | SAVE_2VSRS_TRANSACT(n+2,b,base) | ||
189 | #define SAVE_8VSRS_TRANSACT(n,b,base) SAVE_4VSRS_TRANSACT(n,b,base); \ | ||
190 | SAVE_4VSRS_TRANSACT(n+4,b,base) | ||
191 | #define SAVE_16VSRS_TRANSACT(n,b,base) SAVE_8VSRS_TRANSACT(n,b,base); \ | ||
192 | SAVE_8VSRS_TRANSACT(n+8,b,base) | ||
193 | #define SAVE_32VSRS_TRANSACT(n,b,base) SAVE_16VSRS_TRANSACT(n,b,base); \ | ||
194 | SAVE_16VSRS_TRANSACT(n+16,b,base) | ||
195 | |||
196 | #define REST_VSR_TRANSACT(n,b,base) li b,THREAD_TRANSACT_VSR0+(16*(n)); \ | ||
197 | LXVD2X(n,R##base,R##b) | ||
198 | #define REST_2VSRS_TRANSACT(n,b,base) REST_VSR_TRANSACT(n,b,base); \ | ||
199 | REST_VSR_TRANSACT(n+1,b,base) | ||
200 | #define REST_4VSRS_TRANSACT(n,b,base) REST_2VSRS_TRANSACT(n,b,base); \ | ||
201 | REST_2VSRS_TRANSACT(n+2,b,base) | ||
202 | #define REST_8VSRS_TRANSACT(n,b,base) REST_4VSRS_TRANSACT(n,b,base); \ | ||
203 | REST_4VSRS_TRANSACT(n+4,b,base) | ||
204 | #define REST_16VSRS_TRANSACT(n,b,base) REST_8VSRS_TRANSACT(n,b,base); \ | ||
205 | REST_8VSRS_TRANSACT(n+8,b,base) | ||
206 | #define REST_32VSRS_TRANSACT(n,b,base) REST_16VSRS_TRANSACT(n,b,base); \ | ||
207 | REST_16VSRS_TRANSACT(n+16,b,base) | ||
208 | |||
126 | /* Save the lower 32 VSRs in the thread VSR region */ | 209 | /* Save the lower 32 VSRs in the thread VSR region */ |
127 | #define SAVE_VSR(n,b,base) li b,THREAD_VSR0+(16*(n)); STXVD2X(n,R##base,R##b) | 210 | #define SAVE_VSR(n,b,base) li b,THREAD_VSR0+(16*(n)); STXVD2X(n,R##base,R##b) |
128 | #define SAVE_2VSRS(n,b,base) SAVE_VSR(n,b,base); SAVE_VSR(n+1,b,base) | 211 | #define SAVE_2VSRS(n,b,base) SAVE_VSR(n,b,base); SAVE_VSR(n+1,b,base) |
diff --git a/arch/powerpc/include/asm/processor.h b/arch/powerpc/include/asm/processor.h index 42ac53cebacd..7ff9eaa3ea6c 100644 --- a/arch/powerpc/include/asm/processor.h +++ b/arch/powerpc/include/asm/processor.h | |||
@@ -152,6 +152,7 @@ typedef struct { | |||
152 | #define TS_FPROFFSET 0 | 152 | #define TS_FPROFFSET 0 |
153 | #define TS_VSRLOWOFFSET 1 | 153 | #define TS_VSRLOWOFFSET 1 |
154 | #define TS_FPR(i) fpr[i][TS_FPROFFSET] | 154 | #define TS_FPR(i) fpr[i][TS_FPROFFSET] |
155 | #define TS_TRANS_FPR(i) transact_fpr[i][TS_FPROFFSET] | ||
155 | 156 | ||
156 | struct thread_struct { | 157 | struct thread_struct { |
157 | unsigned long ksp; /* Kernel stack pointer */ | 158 | unsigned long ksp; /* Kernel stack pointer */ |
@@ -246,6 +247,34 @@ struct thread_struct { | |||
246 | unsigned long spefscr; /* SPE & eFP status */ | 247 | unsigned long spefscr; /* SPE & eFP status */ |
247 | int used_spe; /* set if process has used spe */ | 248 | int used_spe; /* set if process has used spe */ |
248 | #endif /* CONFIG_SPE */ | 249 | #endif /* CONFIG_SPE */ |
250 | #ifdef CONFIG_PPC_TRANSACTIONAL_MEM | ||
251 | u64 tm_tfhar; /* Transaction fail handler addr */ | ||
252 | u64 tm_texasr; /* Transaction exception & summary */ | ||
253 | u64 tm_tfiar; /* Transaction fail instr address reg */ | ||
254 | unsigned long tm_orig_msr; /* Thread's MSR on ctx switch */ | ||
255 | struct pt_regs ckpt_regs; /* Checkpointed registers */ | ||
256 | |||
257 | /* | ||
258 | * Transactional FP and VSX 0-31 register set. | ||
259 | * NOTE: the sense of these is the opposite of the integer ckpt_regs! | ||
260 | * | ||
261 | * When a transaction is active/signalled/scheduled etc., *regs is the | ||
262 | * most recent set of/speculated GPRs with ckpt_regs being the older | ||
263 | * checkpointed regs to which we roll back if transaction aborts. | ||
264 | * | ||
265 | * However, fpr[] is the checkpointed 'base state' of FP regs, and | ||
266 | * transact_fpr[] is the new set of transactional values. | ||
267 | * VRs work the same way. | ||
268 | */ | ||
269 | double transact_fpr[32][TS_FPRWIDTH]; | ||
270 | struct { | ||
271 | unsigned int pad; | ||
272 | unsigned int val; /* Floating point status */ | ||
273 | } transact_fpscr; | ||
274 | vector128 transact_vr[32] __attribute__((aligned(16))); | ||
275 | vector128 transact_vscr __attribute__((aligned(16))); | ||
276 | unsigned long transact_vrsave; | ||
277 | #endif /* CONFIG_PPC_TRANSACTIONAL_MEM */ | ||
249 | #ifdef CONFIG_KVM_BOOK3S_32_HANDLER | 278 | #ifdef CONFIG_KVM_BOOK3S_32_HANDLER |
250 | void* kvm_shadow_vcpu; /* KVM internal data */ | 279 | void* kvm_shadow_vcpu; /* KVM internal data */ |
251 | #endif /* CONFIG_KVM_BOOK3S_32_HANDLER */ | 280 | #endif /* CONFIG_KVM_BOOK3S_32_HANDLER */ |
diff --git a/arch/powerpc/include/asm/ps3.h b/arch/powerpc/include/asm/ps3.h index 0e15db4d703b..678a7c1d9cb8 100644 --- a/arch/powerpc/include/asm/ps3.h +++ b/arch/powerpc/include/asm/ps3.h | |||
@@ -245,7 +245,7 @@ enum lv1_result { | |||
245 | 245 | ||
246 | static inline const char* ps3_result(int result) | 246 | static inline const char* ps3_result(int result) |
247 | { | 247 | { |
248 | #if defined(DEBUG) | 248 | #if defined(DEBUG) || defined(PS3_VERBOSE_RESULT) |
249 | switch (result) { | 249 | switch (result) { |
250 | case LV1_SUCCESS: | 250 | case LV1_SUCCESS: |
251 | return "LV1_SUCCESS (0)"; | 251 | return "LV1_SUCCESS (0)"; |
diff --git a/arch/powerpc/include/asm/reg.h b/arch/powerpc/include/asm/reg.h index e09ac51961d7..7035e608f3fa 100644 --- a/arch/powerpc/include/asm/reg.h +++ b/arch/powerpc/include/asm/reg.h | |||
@@ -29,6 +29,10 @@ | |||
29 | #define MSR_SF_LG 63 /* Enable 64 bit mode */ | 29 | #define MSR_SF_LG 63 /* Enable 64 bit mode */ |
30 | #define MSR_ISF_LG 61 /* Interrupt 64b mode valid on 630 */ | 30 | #define MSR_ISF_LG 61 /* Interrupt 64b mode valid on 630 */ |
31 | #define MSR_HV_LG 60 /* Hypervisor state */ | 31 | #define MSR_HV_LG 60 /* Hypervisor state */ |
32 | #define MSR_TS_T_LG 34 /* Trans Mem state: Transactional */ | ||
33 | #define MSR_TS_S_LG 33 /* Trans Mem state: Suspended */ | ||
34 | #define MSR_TS_LG 33 /* Trans Mem state (2 bits) */ | ||
35 | #define MSR_TM_LG 32 /* Trans Mem Available */ | ||
32 | #define MSR_VEC_LG 25 /* Enable AltiVec */ | 36 | #define MSR_VEC_LG 25 /* Enable AltiVec */ |
33 | #define MSR_VSX_LG 23 /* Enable VSX */ | 37 | #define MSR_VSX_LG 23 /* Enable VSX */ |
34 | #define MSR_POW_LG 18 /* Enable Power Management */ | 38 | #define MSR_POW_LG 18 /* Enable Power Management */ |
@@ -98,6 +102,26 @@ | |||
98 | #define MSR_RI __MASK(MSR_RI_LG) /* Recoverable Exception */ | 102 | #define MSR_RI __MASK(MSR_RI_LG) /* Recoverable Exception */ |
99 | #define MSR_LE __MASK(MSR_LE_LG) /* Little Endian */ | 103 | #define MSR_LE __MASK(MSR_LE_LG) /* Little Endian */ |
100 | 104 | ||
105 | #define MSR_TM __MASK(MSR_TM_LG) /* Transactional Mem Available */ | ||
106 | #define MSR_TS_N 0 /* Non-transactional */ | ||
107 | #define MSR_TS_S __MASK(MSR_TS_S_LG) /* Transaction Suspended */ | ||
108 | #define MSR_TS_T __MASK(MSR_TS_T_LG) /* Transaction Transactional */ | ||
109 | #define MSR_TS_MASK (MSR_TS_T | MSR_TS_S) /* Transaction State bits */ | ||
110 | #define MSR_TM_ACTIVE(x) (((x) & MSR_TS_MASK) != 0) /* Transaction active? */ | ||
111 | #define MSR_TM_TRANSACTIONAL(x) (((x) & MSR_TS_MASK) == MSR_TS_T) | ||
112 | #define MSR_TM_SUSPENDED(x) (((x) & MSR_TS_MASK) == MSR_TS_S) | ||
113 | |||
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 | |||
101 | #if defined(CONFIG_PPC_BOOK3S_64) | 125 | #if defined(CONFIG_PPC_BOOK3S_64) |
102 | #define MSR_64BIT MSR_SF | 126 | #define MSR_64BIT MSR_SF |
103 | 127 | ||
@@ -193,6 +217,10 @@ | |||
193 | #define SPRN_UAMOR 0x9d /* User Authority Mask Override Register */ | 217 | #define SPRN_UAMOR 0x9d /* User Authority Mask Override Register */ |
194 | #define SPRN_AMOR 0x15d /* Authority Mask Override Register */ | 218 | #define SPRN_AMOR 0x15d /* Authority Mask Override Register */ |
195 | #define SPRN_ACOP 0x1F /* Available Coprocessor Register */ | 219 | #define SPRN_ACOP 0x1F /* Available Coprocessor Register */ |
220 | #define SPRN_TFIAR 0x81 /* Transaction Failure Inst Addr */ | ||
221 | #define SPRN_TEXASR 0x82 /* Transaction EXception & Summary */ | ||
222 | #define SPRN_TEXASRU 0x83 /* '' '' '' Upper 32 */ | ||
223 | #define SPRN_TFHAR 0x80 /* Transaction Failure Handler Addr */ | ||
196 | #define SPRN_CTRLF 0x088 | 224 | #define SPRN_CTRLF 0x088 |
197 | #define SPRN_CTRLT 0x098 | 225 | #define SPRN_CTRLT 0x098 |
198 | #define CTRL_CT 0xc0000000 /* current thread */ | 226 | #define CTRL_CT 0xc0000000 /* current thread */ |
@@ -770,7 +798,7 @@ | |||
770 | * HV mode in which case it is HSPRG0 | 798 | * HV mode in which case it is HSPRG0 |
771 | * | 799 | * |
772 | * 64-bit server: | 800 | * 64-bit server: |
773 | * - SPRG0 unused (reserved for HV on Power4) | 801 | * - SPRG0 scratch for TM recheckpoint/reclaim (reserved for HV on Power4) |
774 | * - SPRG2 scratch for exception vectors | 802 | * - SPRG2 scratch for exception vectors |
775 | * - SPRG3 CPU and NUMA node for VDSO getcpu (user visible) | 803 | * - SPRG3 CPU and NUMA node for VDSO getcpu (user visible) |
776 | * - HSPRG0 stores PACA in HV mode | 804 | * - HSPRG0 stores PACA in HV mode |
diff --git a/arch/powerpc/include/asm/tm.h b/arch/powerpc/include/asm/tm.h new file mode 100644 index 000000000000..4b4449abf3f8 --- /dev/null +++ b/arch/powerpc/include/asm/tm.h | |||
@@ -0,0 +1,20 @@ | |||
1 | /* | ||
2 | * Transactional memory support routines to reclaim and recheckpoint | ||
3 | * transactional process state. | ||
4 | * | ||
5 | * Copyright 2012 Matt Evans & Michael Neuling, IBM Corporation. | ||
6 | */ | ||
7 | |||
8 | #ifdef CONFIG_PPC_TRANSACTIONAL_MEM | ||
9 | extern void do_load_up_transact_fpu(struct thread_struct *thread); | ||
10 | extern void do_load_up_transact_altivec(struct thread_struct *thread); | ||
11 | #endif | ||
12 | |||
13 | extern void tm_enable(void); | ||
14 | extern void tm_reclaim(struct thread_struct *thread, | ||
15 | unsigned long orig_msr, uint8_t cause); | ||
16 | extern void tm_recheckpoint(struct thread_struct *thread, | ||
17 | unsigned long orig_msr); | ||
18 | extern void tm_abort(uint8_t cause); | ||
19 | extern void tm_save_sprs(struct thread_struct *thread); | ||
20 | extern void tm_restore_sprs(struct thread_struct *thread); | ||
diff --git a/arch/powerpc/kernel/Makefile b/arch/powerpc/kernel/Makefile index b4f0e360e414..f960a7944553 100644 --- a/arch/powerpc/kernel/Makefile +++ b/arch/powerpc/kernel/Makefile | |||
@@ -121,6 +121,8 @@ ifneq ($(CONFIG_PPC_INDIRECT_IO),y) | |||
121 | obj-y += iomap.o | 121 | obj-y += iomap.o |
122 | endif | 122 | endif |
123 | 123 | ||
124 | obj64-$(CONFIG_PPC_TRANSACTIONAL_MEM) += tm.o | ||
125 | |||
124 | obj-$(CONFIG_PPC64) += $(obj64-y) | 126 | obj-$(CONFIG_PPC64) += $(obj64-y) |
125 | obj-$(CONFIG_PPC32) += $(obj32-y) | 127 | obj-$(CONFIG_PPC32) += $(obj32-y) |
126 | 128 | ||
diff --git a/arch/powerpc/kernel/asm-offsets.c b/arch/powerpc/kernel/asm-offsets.c index beddba432518..781190367292 100644 --- a/arch/powerpc/kernel/asm-offsets.c +++ b/arch/powerpc/kernel/asm-offsets.c | |||
@@ -125,6 +125,30 @@ int main(void) | |||
125 | #ifdef CONFIG_PPC_BOOK3S_64 | 125 | #ifdef CONFIG_PPC_BOOK3S_64 |
126 | DEFINE(THREAD_TAR, offsetof(struct thread_struct, tar)); | 126 | DEFINE(THREAD_TAR, offsetof(struct thread_struct, tar)); |
127 | #endif | 127 | #endif |
128 | #ifdef CONFIG_PPC_TRANSACTIONAL_MEM | ||
129 | DEFINE(PACATMSCRATCH, offsetof(struct paca_struct, tm_scratch)); | ||
130 | DEFINE(THREAD_TM_TFHAR, offsetof(struct thread_struct, tm_tfhar)); | ||
131 | DEFINE(THREAD_TM_TEXASR, offsetof(struct thread_struct, tm_texasr)); | ||
132 | DEFINE(THREAD_TM_TFIAR, offsetof(struct thread_struct, tm_tfiar)); | ||
133 | DEFINE(PT_CKPT_REGS, offsetof(struct thread_struct, ckpt_regs)); | ||
134 | DEFINE(THREAD_TRANSACT_VR0, offsetof(struct thread_struct, | ||
135 | transact_vr[0])); | ||
136 | DEFINE(THREAD_TRANSACT_VSCR, offsetof(struct thread_struct, | ||
137 | transact_vscr)); | ||
138 | DEFINE(THREAD_TRANSACT_VRSAVE, offsetof(struct thread_struct, | ||
139 | transact_vrsave)); | ||
140 | DEFINE(THREAD_TRANSACT_FPR0, offsetof(struct thread_struct, | ||
141 | transact_fpr[0])); | ||
142 | DEFINE(THREAD_TRANSACT_FPSCR, offsetof(struct thread_struct, | ||
143 | transact_fpscr)); | ||
144 | #ifdef CONFIG_VSX | ||
145 | DEFINE(THREAD_TRANSACT_VSR0, offsetof(struct thread_struct, | ||
146 | transact_fpr[0])); | ||
147 | #endif | ||
148 | /* Local pt_regs on stack for Transactional Memory funcs. */ | ||
149 | DEFINE(TM_FRAME_SIZE, STACK_FRAME_OVERHEAD + | ||
150 | sizeof(struct pt_regs) + 16); | ||
151 | #endif /* CONFIG_PPC_TRANSACTIONAL_MEM */ | ||
128 | 152 | ||
129 | DEFINE(TI_FLAGS, offsetof(struct thread_info, flags)); | 153 | DEFINE(TI_FLAGS, offsetof(struct thread_info, flags)); |
130 | DEFINE(TI_LOCAL_FLAGS, offsetof(struct thread_info, local_flags)); | 154 | DEFINE(TI_LOCAL_FLAGS, offsetof(struct thread_info, local_flags)); |
@@ -479,6 +503,7 @@ int main(void) | |||
479 | DEFINE(VCPU_LAST_INST, offsetof(struct kvm_vcpu, arch.last_inst)); | 503 | DEFINE(VCPU_LAST_INST, offsetof(struct kvm_vcpu, arch.last_inst)); |
480 | DEFINE(VCPU_TRAP, offsetof(struct kvm_vcpu, arch.trap)); | 504 | DEFINE(VCPU_TRAP, offsetof(struct kvm_vcpu, arch.trap)); |
481 | DEFINE(VCPU_PTID, offsetof(struct kvm_vcpu, arch.ptid)); | 505 | DEFINE(VCPU_PTID, offsetof(struct kvm_vcpu, arch.ptid)); |
506 | DEFINE(VCPU_CFAR, offsetof(struct kvm_vcpu, arch.cfar)); | ||
482 | DEFINE(VCORE_ENTRY_EXIT, offsetof(struct kvmppc_vcore, entry_exit_count)); | 507 | DEFINE(VCORE_ENTRY_EXIT, offsetof(struct kvmppc_vcore, entry_exit_count)); |
483 | DEFINE(VCORE_NAP_COUNT, offsetof(struct kvmppc_vcore, nap_count)); | 508 | DEFINE(VCORE_NAP_COUNT, offsetof(struct kvmppc_vcore, nap_count)); |
484 | DEFINE(VCORE_IN_GUEST, offsetof(struct kvmppc_vcore, in_guest)); | 509 | DEFINE(VCORE_IN_GUEST, offsetof(struct kvmppc_vcore, in_guest)); |
@@ -558,6 +583,10 @@ int main(void) | |||
558 | DEFINE(IPI_PRIORITY, IPI_PRIORITY); | 583 | DEFINE(IPI_PRIORITY, IPI_PRIORITY); |
559 | #endif /* CONFIG_KVM_BOOK3S_64_HV */ | 584 | #endif /* CONFIG_KVM_BOOK3S_64_HV */ |
560 | 585 | ||
586 | #ifdef CONFIG_PPC_BOOK3S_64 | ||
587 | HSTATE_FIELD(HSTATE_CFAR, cfar); | ||
588 | #endif /* CONFIG_PPC_BOOK3S_64 */ | ||
589 | |||
561 | #else /* CONFIG_PPC_BOOK3S */ | 590 | #else /* CONFIG_PPC_BOOK3S */ |
562 | DEFINE(VCPU_CR, offsetof(struct kvm_vcpu, arch.cr)); | 591 | DEFINE(VCPU_CR, offsetof(struct kvm_vcpu, arch.cr)); |
563 | DEFINE(VCPU_XER, offsetof(struct kvm_vcpu, arch.xer)); | 592 | DEFINE(VCPU_XER, offsetof(struct kvm_vcpu, arch.xer)); |
diff --git a/arch/powerpc/kernel/entry_64.S b/arch/powerpc/kernel/entry_64.S index 9ae8451bbc83..612ea130c5d2 100644 --- a/arch/powerpc/kernel/entry_64.S +++ b/arch/powerpc/kernel/entry_64.S | |||
@@ -785,6 +785,10 @@ fast_exception_return: | |||
785 | andc r4,r4,r0 /* r0 contains MSR_RI here */ | 785 | andc r4,r4,r0 /* r0 contains MSR_RI here */ |
786 | mtmsrd r4,1 | 786 | mtmsrd r4,1 |
787 | 787 | ||
788 | #ifdef CONFIG_PPC_TRANSACTIONAL_MEM | ||
789 | /* TM debug */ | ||
790 | std r3, PACATMSCRATCH(r13) /* Stash returned-to MSR */ | ||
791 | #endif | ||
788 | /* | 792 | /* |
789 | * r13 is our per cpu area, only restore it if we are returning to | 793 | * r13 is our per cpu area, only restore it if we are returning to |
790 | * userspace the value stored in the stack frame may belong to | 794 | * userspace the value stored in the stack frame may belong to |
diff --git a/arch/powerpc/kernel/exceptions-64s.S b/arch/powerpc/kernel/exceptions-64s.S index 7a1c87cbb890..a8a5361fb70c 100644 --- a/arch/powerpc/kernel/exceptions-64s.S +++ b/arch/powerpc/kernel/exceptions-64s.S | |||
@@ -153,7 +153,10 @@ machine_check_pSeries_1: | |||
153 | * some code path might still want to branch into the original | 153 | * some code path might still want to branch into the original |
154 | * vector | 154 | * vector |
155 | */ | 155 | */ |
156 | b machine_check_pSeries | 156 | HMT_MEDIUM_PPR_DISCARD |
157 | SET_SCRATCH0(r13) /* save r13 */ | ||
158 | EXCEPTION_PROLOG_0(PACA_EXMC) | ||
159 | b machine_check_pSeries_0 | ||
157 | 160 | ||
158 | . = 0x300 | 161 | . = 0x300 |
159 | .globl data_access_pSeries | 162 | .globl data_access_pSeries |
@@ -172,6 +175,7 @@ END_MMU_FTR_SECTION_IFCLR(MMU_FTR_SLB) | |||
172 | data_access_slb_pSeries: | 175 | data_access_slb_pSeries: |
173 | HMT_MEDIUM_PPR_DISCARD | 176 | HMT_MEDIUM_PPR_DISCARD |
174 | SET_SCRATCH0(r13) | 177 | SET_SCRATCH0(r13) |
178 | EXCEPTION_PROLOG_0(PACA_EXSLB) | ||
175 | EXCEPTION_PROLOG_1(PACA_EXSLB, KVMTEST, 0x380) | 179 | EXCEPTION_PROLOG_1(PACA_EXSLB, KVMTEST, 0x380) |
176 | std r3,PACA_EXSLB+EX_R3(r13) | 180 | std r3,PACA_EXSLB+EX_R3(r13) |
177 | mfspr r3,SPRN_DAR | 181 | mfspr r3,SPRN_DAR |
@@ -203,6 +207,7 @@ data_access_slb_pSeries: | |||
203 | instruction_access_slb_pSeries: | 207 | instruction_access_slb_pSeries: |
204 | HMT_MEDIUM_PPR_DISCARD | 208 | HMT_MEDIUM_PPR_DISCARD |
205 | SET_SCRATCH0(r13) | 209 | SET_SCRATCH0(r13) |
210 | EXCEPTION_PROLOG_0(PACA_EXSLB) | ||
206 | EXCEPTION_PROLOG_1(PACA_EXSLB, KVMTEST_PR, 0x480) | 211 | EXCEPTION_PROLOG_1(PACA_EXSLB, KVMTEST_PR, 0x480) |
207 | std r3,PACA_EXSLB+EX_R3(r13) | 212 | std r3,PACA_EXSLB+EX_R3(r13) |
208 | mfspr r3,SPRN_SRR0 /* SRR0 is faulting address */ | 213 | mfspr r3,SPRN_SRR0 /* SRR0 is faulting address */ |
@@ -284,16 +289,28 @@ system_call_pSeries: | |||
284 | */ | 289 | */ |
285 | . = 0xe00 | 290 | . = 0xe00 |
286 | hv_exception_trampoline: | 291 | hv_exception_trampoline: |
292 | SET_SCRATCH0(r13) | ||
293 | EXCEPTION_PROLOG_0(PACA_EXGEN) | ||
287 | b h_data_storage_hv | 294 | b h_data_storage_hv |
295 | |||
288 | . = 0xe20 | 296 | . = 0xe20 |
297 | SET_SCRATCH0(r13) | ||
298 | EXCEPTION_PROLOG_0(PACA_EXGEN) | ||
289 | b h_instr_storage_hv | 299 | b h_instr_storage_hv |
300 | |||
290 | . = 0xe40 | 301 | . = 0xe40 |
302 | SET_SCRATCH0(r13) | ||
303 | EXCEPTION_PROLOG_0(PACA_EXGEN) | ||
291 | b emulation_assist_hv | 304 | b emulation_assist_hv |
292 | . = 0xe50 | 305 | |
293 | b hmi_exception_hv | ||
294 | . = 0xe60 | 306 | . = 0xe60 |
307 | SET_SCRATCH0(r13) | ||
308 | EXCEPTION_PROLOG_0(PACA_EXGEN) | ||
295 | b hmi_exception_hv | 309 | b hmi_exception_hv |
310 | |||
296 | . = 0xe80 | 311 | . = 0xe80 |
312 | SET_SCRATCH0(r13) | ||
313 | EXCEPTION_PROLOG_0(PACA_EXGEN) | ||
297 | b h_doorbell_hv | 314 | b h_doorbell_hv |
298 | 315 | ||
299 | /* We need to deal with the Altivec unavailable exception | 316 | /* We need to deal with the Altivec unavailable exception |
@@ -303,16 +320,27 @@ hv_exception_trampoline: | |||
303 | */ | 320 | */ |
304 | performance_monitor_pSeries_1: | 321 | performance_monitor_pSeries_1: |
305 | . = 0xf00 | 322 | . = 0xf00 |
323 | SET_SCRATCH0(r13) | ||
324 | EXCEPTION_PROLOG_0(PACA_EXGEN) | ||
306 | b performance_monitor_pSeries | 325 | b performance_monitor_pSeries |
307 | 326 | ||
308 | altivec_unavailable_pSeries_1: | 327 | altivec_unavailable_pSeries_1: |
309 | . = 0xf20 | 328 | . = 0xf20 |
329 | SET_SCRATCH0(r13) | ||
330 | EXCEPTION_PROLOG_0(PACA_EXGEN) | ||
310 | b altivec_unavailable_pSeries | 331 | b altivec_unavailable_pSeries |
311 | 332 | ||
312 | vsx_unavailable_pSeries_1: | 333 | vsx_unavailable_pSeries_1: |
313 | . = 0xf40 | 334 | . = 0xf40 |
335 | SET_SCRATCH0(r13) | ||
336 | EXCEPTION_PROLOG_0(PACA_EXGEN) | ||
314 | b vsx_unavailable_pSeries | 337 | b vsx_unavailable_pSeries |
315 | 338 | ||
339 | . = 0xf60 | ||
340 | SET_SCRATCH0(r13) | ||
341 | EXCEPTION_PROLOG_0(PACA_EXGEN) | ||
342 | b tm_unavailable_pSeries | ||
343 | |||
316 | #ifdef CONFIG_CBE_RAS | 344 | #ifdef CONFIG_CBE_RAS |
317 | STD_EXCEPTION_HV(0x1200, 0x1202, cbe_system_error) | 345 | STD_EXCEPTION_HV(0x1200, 0x1202, cbe_system_error) |
318 | KVM_HANDLER_SKIP(PACA_EXGEN, EXC_HV, 0x1202) | 346 | KVM_HANDLER_SKIP(PACA_EXGEN, EXC_HV, 0x1202) |
@@ -326,10 +354,7 @@ vsx_unavailable_pSeries_1: | |||
326 | denorm_exception_hv: | 354 | denorm_exception_hv: |
327 | HMT_MEDIUM_PPR_DISCARD | 355 | HMT_MEDIUM_PPR_DISCARD |
328 | mtspr SPRN_SPRG_HSCRATCH0,r13 | 356 | mtspr SPRN_SPRG_HSCRATCH0,r13 |
329 | mfspr r13,SPRN_SPRG_HPACA | 357 | EXCEPTION_PROLOG_0(PACA_EXGEN) |
330 | std r9,PACA_EXGEN+EX_R9(r13) | ||
331 | HMT_MEDIUM_PPR_SAVE(PACA_EXGEN, r9) | ||
332 | std r10,PACA_EXGEN+EX_R10(r13) | ||
333 | std r11,PACA_EXGEN+EX_R11(r13) | 358 | std r11,PACA_EXGEN+EX_R11(r13) |
334 | std r12,PACA_EXGEN+EX_R12(r13) | 359 | std r12,PACA_EXGEN+EX_R12(r13) |
335 | mfspr r9,SPRN_SPRG_HSCRATCH0 | 360 | mfspr r9,SPRN_SPRG_HSCRATCH0 |
@@ -372,8 +397,10 @@ machine_check_pSeries: | |||
372 | machine_check_fwnmi: | 397 | machine_check_fwnmi: |
373 | HMT_MEDIUM_PPR_DISCARD | 398 | HMT_MEDIUM_PPR_DISCARD |
374 | SET_SCRATCH0(r13) /* save r13 */ | 399 | SET_SCRATCH0(r13) /* save r13 */ |
375 | EXCEPTION_PROLOG_PSERIES(PACA_EXMC, machine_check_common, | 400 | EXCEPTION_PROLOG_0(PACA_EXMC) |
376 | EXC_STD, KVMTEST, 0x200) | 401 | machine_check_pSeries_0: |
402 | EXCEPTION_PROLOG_1(PACA_EXMC, KVMTEST, 0x200) | ||
403 | EXCEPTION_PROLOG_PSERIES_1(machine_check_common, EXC_STD) | ||
377 | KVM_HANDLER_SKIP(PACA_EXMC, EXC_STD, 0x200) | 404 | KVM_HANDLER_SKIP(PACA_EXMC, EXC_STD, 0x200) |
378 | 405 | ||
379 | /* moved from 0x300 */ | 406 | /* moved from 0x300 */ |
@@ -510,24 +537,26 @@ ALT_FTR_SECTION_END_IFCLR(CPU_FTR_ARCH_206) | |||
510 | 537 | ||
511 | .align 7 | 538 | .align 7 |
512 | /* moved from 0xe00 */ | 539 | /* moved from 0xe00 */ |
513 | STD_EXCEPTION_HV(., 0xe02, h_data_storage) | 540 | STD_EXCEPTION_HV_OOL(0xe02, h_data_storage) |
514 | KVM_HANDLER_SKIP(PACA_EXGEN, EXC_HV, 0xe02) | 541 | KVM_HANDLER_SKIP(PACA_EXGEN, EXC_HV, 0xe02) |
515 | STD_EXCEPTION_HV(., 0xe22, h_instr_storage) | 542 | STD_EXCEPTION_HV_OOL(0xe22, h_instr_storage) |
516 | KVM_HANDLER(PACA_EXGEN, EXC_HV, 0xe22) | 543 | KVM_HANDLER(PACA_EXGEN, EXC_HV, 0xe22) |
517 | STD_EXCEPTION_HV(., 0xe42, emulation_assist) | 544 | STD_EXCEPTION_HV_OOL(0xe42, emulation_assist) |
518 | KVM_HANDLER(PACA_EXGEN, EXC_HV, 0xe42) | 545 | KVM_HANDLER(PACA_EXGEN, EXC_HV, 0xe42) |
519 | STD_EXCEPTION_HV(., 0xe62, hmi_exception) /* need to flush cache ? */ | 546 | STD_EXCEPTION_HV_OOL(0xe62, hmi_exception) /* need to flush cache ? */ |
520 | KVM_HANDLER(PACA_EXGEN, EXC_HV, 0xe62) | 547 | KVM_HANDLER(PACA_EXGEN, EXC_HV, 0xe62) |
521 | MASKABLE_EXCEPTION_HV(., 0xe82, h_doorbell) | 548 | MASKABLE_EXCEPTION_HV_OOL(0xe82, h_doorbell) |
522 | KVM_HANDLER(PACA_EXGEN, EXC_HV, 0xe82) | 549 | KVM_HANDLER(PACA_EXGEN, EXC_HV, 0xe82) |
523 | 550 | ||
524 | /* moved from 0xf00 */ | 551 | /* moved from 0xf00 */ |
525 | STD_EXCEPTION_PSERIES(., 0xf00, performance_monitor) | 552 | STD_EXCEPTION_PSERIES_OOL(0xf00, performance_monitor) |
526 | KVM_HANDLER_PR(PACA_EXGEN, EXC_STD, 0xf00) | 553 | KVM_HANDLER_PR(PACA_EXGEN, EXC_STD, 0xf00) |
527 | STD_EXCEPTION_PSERIES(., 0xf20, altivec_unavailable) | 554 | STD_EXCEPTION_PSERIES_OOL(0xf20, altivec_unavailable) |
528 | KVM_HANDLER_PR(PACA_EXGEN, EXC_STD, 0xf20) | 555 | KVM_HANDLER_PR(PACA_EXGEN, EXC_STD, 0xf20) |
529 | STD_EXCEPTION_PSERIES(., 0xf40, vsx_unavailable) | 556 | STD_EXCEPTION_PSERIES_OOL(0xf40, vsx_unavailable) |
530 | KVM_HANDLER_PR(PACA_EXGEN, EXC_STD, 0xf40) | 557 | KVM_HANDLER_PR(PACA_EXGEN, EXC_STD, 0xf40) |
558 | STD_EXCEPTION_PSERIES_OOL(0xf60, tm_unavailable) | ||
559 | KVM_HANDLER_PR(PACA_EXGEN, EXC_STD, 0xf60) | ||
531 | 560 | ||
532 | /* | 561 | /* |
533 | * An interrupt came in while soft-disabled. We set paca->irq_happened, then: | 562 | * An interrupt came in while soft-disabled. We set paca->irq_happened, then: |
@@ -718,8 +747,8 @@ machine_check_common: | |||
718 | . = 0x4380 | 747 | . = 0x4380 |
719 | .globl data_access_slb_relon_pSeries | 748 | .globl data_access_slb_relon_pSeries |
720 | data_access_slb_relon_pSeries: | 749 | data_access_slb_relon_pSeries: |
721 | HMT_MEDIUM_PPR_DISCARD | ||
722 | SET_SCRATCH0(r13) | 750 | SET_SCRATCH0(r13) |
751 | EXCEPTION_PROLOG_0(PACA_EXSLB) | ||
723 | EXCEPTION_PROLOG_1(PACA_EXSLB, NOTEST, 0x380) | 752 | EXCEPTION_PROLOG_1(PACA_EXSLB, NOTEST, 0x380) |
724 | std r3,PACA_EXSLB+EX_R3(r13) | 753 | std r3,PACA_EXSLB+EX_R3(r13) |
725 | mfspr r3,SPRN_DAR | 754 | mfspr r3,SPRN_DAR |
@@ -743,8 +772,8 @@ data_access_slb_relon_pSeries: | |||
743 | . = 0x4480 | 772 | . = 0x4480 |
744 | .globl instruction_access_slb_relon_pSeries | 773 | .globl instruction_access_slb_relon_pSeries |
745 | instruction_access_slb_relon_pSeries: | 774 | instruction_access_slb_relon_pSeries: |
746 | HMT_MEDIUM_PPR_DISCARD | ||
747 | SET_SCRATCH0(r13) | 775 | SET_SCRATCH0(r13) |
776 | EXCEPTION_PROLOG_0(PACA_EXSLB) | ||
748 | EXCEPTION_PROLOG_1(PACA_EXSLB, NOTEST, 0x480) | 777 | EXCEPTION_PROLOG_1(PACA_EXSLB, NOTEST, 0x480) |
749 | std r3,PACA_EXSLB+EX_R3(r13) | 778 | std r3,PACA_EXSLB+EX_R3(r13) |
750 | mfspr r3,SPRN_SRR0 /* SRR0 is faulting address */ | 779 | mfspr r3,SPRN_SRR0 /* SRR0 is faulting address */ |
@@ -788,55 +817,64 @@ system_call_relon_pSeries: | |||
788 | STD_RELON_EXCEPTION_PSERIES(0x4d00, 0xd00, single_step) | 817 | STD_RELON_EXCEPTION_PSERIES(0x4d00, 0xd00, single_step) |
789 | 818 | ||
790 | . = 0x4e00 | 819 | . = 0x4e00 |
820 | SET_SCRATCH0(r13) | ||
821 | EXCEPTION_PROLOG_0(PACA_EXGEN) | ||
791 | b h_data_storage_relon_hv | 822 | b h_data_storage_relon_hv |
792 | 823 | ||
793 | . = 0x4e20 | 824 | . = 0x4e20 |
825 | SET_SCRATCH0(r13) | ||
826 | EXCEPTION_PROLOG_0(PACA_EXGEN) | ||
794 | b h_instr_storage_relon_hv | 827 | b h_instr_storage_relon_hv |
795 | 828 | ||
796 | . = 0x4e40 | 829 | . = 0x4e40 |
830 | SET_SCRATCH0(r13) | ||
831 | EXCEPTION_PROLOG_0(PACA_EXGEN) | ||
797 | b emulation_assist_relon_hv | 832 | b emulation_assist_relon_hv |
798 | 833 | ||
799 | . = 0x4e50 | ||
800 | b hmi_exception_relon_hv | ||
801 | |||
802 | . = 0x4e60 | 834 | . = 0x4e60 |
835 | SET_SCRATCH0(r13) | ||
836 | EXCEPTION_PROLOG_0(PACA_EXGEN) | ||
803 | b hmi_exception_relon_hv | 837 | b hmi_exception_relon_hv |
804 | 838 | ||
805 | . = 0x4e80 | 839 | . = 0x4e80 |
840 | SET_SCRATCH0(r13) | ||
841 | EXCEPTION_PROLOG_0(PACA_EXGEN) | ||
806 | b h_doorbell_relon_hv | 842 | b h_doorbell_relon_hv |
807 | 843 | ||
808 | performance_monitor_relon_pSeries_1: | 844 | performance_monitor_relon_pSeries_1: |
809 | . = 0x4f00 | 845 | . = 0x4f00 |
846 | SET_SCRATCH0(r13) | ||
847 | EXCEPTION_PROLOG_0(PACA_EXGEN) | ||
810 | b performance_monitor_relon_pSeries | 848 | b performance_monitor_relon_pSeries |
811 | 849 | ||
812 | altivec_unavailable_relon_pSeries_1: | 850 | altivec_unavailable_relon_pSeries_1: |
813 | . = 0x4f20 | 851 | . = 0x4f20 |
852 | SET_SCRATCH0(r13) | ||
853 | EXCEPTION_PROLOG_0(PACA_EXGEN) | ||
814 | b altivec_unavailable_relon_pSeries | 854 | b altivec_unavailable_relon_pSeries |
815 | 855 | ||
816 | vsx_unavailable_relon_pSeries_1: | 856 | vsx_unavailable_relon_pSeries_1: |
817 | . = 0x4f40 | 857 | . = 0x4f40 |
858 | SET_SCRATCH0(r13) | ||
859 | EXCEPTION_PROLOG_0(PACA_EXGEN) | ||
818 | b vsx_unavailable_relon_pSeries | 860 | b vsx_unavailable_relon_pSeries |
819 | 861 | ||
820 | #ifdef CONFIG_CBE_RAS | 862 | tm_unavailable_relon_pSeries_1: |
821 | STD_RELON_EXCEPTION_HV(0x5200, 0x1202, cbe_system_error) | 863 | . = 0x4f60 |
822 | #endif /* CONFIG_CBE_RAS */ | 864 | SET_SCRATCH0(r13) |
865 | EXCEPTION_PROLOG_0(PACA_EXGEN) | ||
866 | b tm_unavailable_relon_pSeries | ||
867 | |||
823 | STD_RELON_EXCEPTION_PSERIES(0x5300, 0x1300, instruction_breakpoint) | 868 | STD_RELON_EXCEPTION_PSERIES(0x5300, 0x1300, instruction_breakpoint) |
824 | #ifdef CONFIG_PPC_DENORMALISATION | 869 | #ifdef CONFIG_PPC_DENORMALISATION |
825 | . = 0x5500 | 870 | . = 0x5500 |
826 | b denorm_exception_hv | 871 | b denorm_exception_hv |
827 | #endif | 872 | #endif |
828 | #ifdef CONFIG_CBE_RAS | ||
829 | STD_RELON_EXCEPTION_HV(0x5600, 0x1602, cbe_maintenance) | ||
830 | #else | ||
831 | #ifdef CONFIG_HVC_SCOM | 873 | #ifdef CONFIG_HVC_SCOM |
832 | STD_RELON_EXCEPTION_HV(0x5600, 0x1600, maintence_interrupt) | 874 | STD_RELON_EXCEPTION_HV(0x5600, 0x1600, maintence_interrupt) |
833 | KVM_HANDLER_SKIP(PACA_EXGEN, EXC_HV, 0x1600) | 875 | KVM_HANDLER_SKIP(PACA_EXGEN, EXC_HV, 0x1600) |
834 | #endif /* CONFIG_HVC_SCOM */ | 876 | #endif /* CONFIG_HVC_SCOM */ |
835 | #endif /* CONFIG_CBE_RAS */ | ||
836 | STD_RELON_EXCEPTION_PSERIES(0x5700, 0x1700, altivec_assist) | 877 | STD_RELON_EXCEPTION_PSERIES(0x5700, 0x1700, altivec_assist) |
837 | #ifdef CONFIG_CBE_RAS | ||
838 | STD_RELON_EXCEPTION_HV(0x5800, 0x1802, cbe_thermal) | ||
839 | #endif /* CONFIG_CBE_RAS */ | ||
840 | 878 | ||
841 | /* Other future vectors */ | 879 | /* Other future vectors */ |
842 | .align 7 | 880 | .align 7 |
@@ -1138,9 +1176,26 @@ fp_unavailable_common: | |||
1138 | addi r3,r1,STACK_FRAME_OVERHEAD | 1176 | addi r3,r1,STACK_FRAME_OVERHEAD |
1139 | bl .kernel_fp_unavailable_exception | 1177 | bl .kernel_fp_unavailable_exception |
1140 | BUG_OPCODE | 1178 | BUG_OPCODE |
1141 | 1: bl .load_up_fpu | 1179 | 1: |
1180 | #ifdef CONFIG_PPC_TRANSACTIONAL_MEM | ||
1181 | BEGIN_FTR_SECTION | ||
1182 | /* Test if 2 TM state bits are zero. If non-zero (ie. userspace was in | ||
1183 | * transaction), go do TM stuff | ||
1184 | */ | ||
1185 | rldicl. r0, r12, (64-MSR_TS_LG), (64-2) | ||
1186 | bne- 2f | ||
1187 | END_FTR_SECTION_IFSET(CPU_FTR_TM) | ||
1188 | #endif | ||
1189 | bl .load_up_fpu | ||
1142 | b fast_exception_return | 1190 | b fast_exception_return |
1143 | 1191 | #ifdef CONFIG_PPC_TRANSACTIONAL_MEM | |
1192 | 2: /* User process was in a transaction */ | ||
1193 | bl .save_nvgprs | ||
1194 | DISABLE_INTS | ||
1195 | addi r3,r1,STACK_FRAME_OVERHEAD | ||
1196 | bl .fp_unavailable_tm | ||
1197 | b .ret_from_except | ||
1198 | #endif | ||
1144 | .align 7 | 1199 | .align 7 |
1145 | .globl altivec_unavailable_common | 1200 | .globl altivec_unavailable_common |
1146 | altivec_unavailable_common: | 1201 | altivec_unavailable_common: |
@@ -1148,8 +1203,25 @@ altivec_unavailable_common: | |||
1148 | #ifdef CONFIG_ALTIVEC | 1203 | #ifdef CONFIG_ALTIVEC |
1149 | BEGIN_FTR_SECTION | 1204 | BEGIN_FTR_SECTION |
1150 | beq 1f | 1205 | beq 1f |
1206 | #ifdef CONFIG_PPC_TRANSACTIONAL_MEM | ||
1207 | BEGIN_FTR_SECTION_NESTED(69) | ||
1208 | /* Test if 2 TM state bits are zero. If non-zero (ie. userspace was in | ||
1209 | * transaction), go do TM stuff | ||
1210 | */ | ||
1211 | rldicl. r0, r12, (64-MSR_TS_LG), (64-2) | ||
1212 | bne- 2f | ||
1213 | END_FTR_SECTION_NESTED(CPU_FTR_TM, CPU_FTR_TM, 69) | ||
1214 | #endif | ||
1151 | bl .load_up_altivec | 1215 | bl .load_up_altivec |
1152 | b fast_exception_return | 1216 | b fast_exception_return |
1217 | #ifdef CONFIG_PPC_TRANSACTIONAL_MEM | ||
1218 | 2: /* User process was in a transaction */ | ||
1219 | bl .save_nvgprs | ||
1220 | DISABLE_INTS | ||
1221 | addi r3,r1,STACK_FRAME_OVERHEAD | ||
1222 | bl .altivec_unavailable_tm | ||
1223 | b .ret_from_except | ||
1224 | #endif | ||
1153 | 1: | 1225 | 1: |
1154 | END_FTR_SECTION_IFSET(CPU_FTR_ALTIVEC) | 1226 | END_FTR_SECTION_IFSET(CPU_FTR_ALTIVEC) |
1155 | #endif | 1227 | #endif |
@@ -1166,7 +1238,24 @@ vsx_unavailable_common: | |||
1166 | #ifdef CONFIG_VSX | 1238 | #ifdef CONFIG_VSX |
1167 | BEGIN_FTR_SECTION | 1239 | BEGIN_FTR_SECTION |
1168 | beq 1f | 1240 | beq 1f |
1241 | #ifdef CONFIG_PPC_TRANSACTIONAL_MEM | ||
1242 | BEGIN_FTR_SECTION_NESTED(69) | ||
1243 | /* Test if 2 TM state bits are zero. If non-zero (ie. userspace was in | ||
1244 | * transaction), go do TM stuff | ||
1245 | */ | ||
1246 | rldicl. r0, r12, (64-MSR_TS_LG), (64-2) | ||
1247 | bne- 2f | ||
1248 | END_FTR_SECTION_NESTED(CPU_FTR_TM, CPU_FTR_TM, 69) | ||
1249 | #endif | ||
1169 | b .load_up_vsx | 1250 | b .load_up_vsx |
1251 | #ifdef CONFIG_PPC_TRANSACTIONAL_MEM | ||
1252 | 2: /* User process was in a transaction */ | ||
1253 | bl .save_nvgprs | ||
1254 | DISABLE_INTS | ||
1255 | addi r3,r1,STACK_FRAME_OVERHEAD | ||
1256 | bl .vsx_unavailable_tm | ||
1257 | b .ret_from_except | ||
1258 | #endif | ||
1170 | 1: | 1259 | 1: |
1171 | END_FTR_SECTION_IFSET(CPU_FTR_VSX) | 1260 | END_FTR_SECTION_IFSET(CPU_FTR_VSX) |
1172 | #endif | 1261 | #endif |
@@ -1177,24 +1266,35 @@ END_FTR_SECTION_IFSET(CPU_FTR_VSX) | |||
1177 | b .ret_from_except | 1266 | b .ret_from_except |
1178 | 1267 | ||
1179 | .align 7 | 1268 | .align 7 |
1269 | .globl tm_unavailable_common | ||
1270 | tm_unavailable_common: | ||
1271 | EXCEPTION_PROLOG_COMMON(0xf60, PACA_EXGEN) | ||
1272 | bl .save_nvgprs | ||
1273 | DISABLE_INTS | ||
1274 | addi r3,r1,STACK_FRAME_OVERHEAD | ||
1275 | bl .tm_unavailable_exception | ||
1276 | b .ret_from_except | ||
1277 | |||
1278 | .align 7 | ||
1180 | .globl __end_handlers | 1279 | .globl __end_handlers |
1181 | __end_handlers: | 1280 | __end_handlers: |
1182 | 1281 | ||
1183 | /* Equivalents to the above handlers for relocation-on interrupt vectors */ | 1282 | /* Equivalents to the above handlers for relocation-on interrupt vectors */ |
1184 | STD_RELON_EXCEPTION_HV(., 0xe00, h_data_storage) | 1283 | STD_RELON_EXCEPTION_HV_OOL(0xe00, h_data_storage) |
1185 | KVM_HANDLER(PACA_EXGEN, EXC_HV, 0xe00) | 1284 | KVM_HANDLER(PACA_EXGEN, EXC_HV, 0xe00) |
1186 | STD_RELON_EXCEPTION_HV(., 0xe20, h_instr_storage) | 1285 | STD_RELON_EXCEPTION_HV_OOL(0xe20, h_instr_storage) |
1187 | KVM_HANDLER(PACA_EXGEN, EXC_HV, 0xe20) | 1286 | KVM_HANDLER(PACA_EXGEN, EXC_HV, 0xe20) |
1188 | STD_RELON_EXCEPTION_HV(., 0xe40, emulation_assist) | 1287 | STD_RELON_EXCEPTION_HV_OOL(0xe40, emulation_assist) |
1189 | KVM_HANDLER(PACA_EXGEN, EXC_HV, 0xe40) | 1288 | KVM_HANDLER(PACA_EXGEN, EXC_HV, 0xe40) |
1190 | STD_RELON_EXCEPTION_HV(., 0xe60, hmi_exception) | 1289 | STD_RELON_EXCEPTION_HV_OOL(0xe60, hmi_exception) |
1191 | KVM_HANDLER(PACA_EXGEN, EXC_HV, 0xe60) | 1290 | KVM_HANDLER(PACA_EXGEN, EXC_HV, 0xe60) |
1192 | MASKABLE_RELON_EXCEPTION_HV(., 0xe80, h_doorbell) | 1291 | MASKABLE_RELON_EXCEPTION_HV_OOL(0xe80, h_doorbell) |
1193 | KVM_HANDLER(PACA_EXGEN, EXC_HV, 0xe80) | 1292 | KVM_HANDLER(PACA_EXGEN, EXC_HV, 0xe80) |
1194 | 1293 | ||
1195 | STD_RELON_EXCEPTION_PSERIES(., 0xf00, performance_monitor) | 1294 | STD_RELON_EXCEPTION_PSERIES_OOL(0xf00, performance_monitor) |
1196 | STD_RELON_EXCEPTION_PSERIES(., 0xf20, altivec_unavailable) | 1295 | STD_RELON_EXCEPTION_PSERIES_OOL(0xf20, altivec_unavailable) |
1197 | STD_RELON_EXCEPTION_PSERIES(., 0xf40, vsx_unavailable) | 1296 | STD_RELON_EXCEPTION_PSERIES_OOL(0xf40, vsx_unavailable) |
1297 | STD_RELON_EXCEPTION_PSERIES_OOL(0xf60, tm_unavailable) | ||
1198 | 1298 | ||
1199 | #if defined(CONFIG_PPC_PSERIES) || defined(CONFIG_PPC_POWERNV) | 1299 | #if defined(CONFIG_PPC_PSERIES) || defined(CONFIG_PPC_POWERNV) |
1200 | /* | 1300 | /* |
diff --git a/arch/powerpc/kernel/fpu.S b/arch/powerpc/kernel/fpu.S index e0ada05f2df3..caeaabf11a2f 100644 --- a/arch/powerpc/kernel/fpu.S +++ b/arch/powerpc/kernel/fpu.S | |||
@@ -35,6 +35,15 @@ END_FTR_SECTION_IFSET(CPU_FTR_VSX); \ | |||
35 | 2: REST_32VSRS(n,c,base); \ | 35 | 2: REST_32VSRS(n,c,base); \ |
36 | 3: | 36 | 3: |
37 | 37 | ||
38 | #define __REST_32FPVSRS_TRANSACT(n,c,base) \ | ||
39 | BEGIN_FTR_SECTION \ | ||
40 | b 2f; \ | ||
41 | END_FTR_SECTION_IFSET(CPU_FTR_VSX); \ | ||
42 | REST_32FPRS_TRANSACT(n,base); \ | ||
43 | b 3f; \ | ||
44 | 2: REST_32VSRS_TRANSACT(n,c,base); \ | ||
45 | 3: | ||
46 | |||
38 | #define __SAVE_32FPVSRS(n,c,base) \ | 47 | #define __SAVE_32FPVSRS(n,c,base) \ |
39 | BEGIN_FTR_SECTION \ | 48 | BEGIN_FTR_SECTION \ |
40 | b 2f; \ | 49 | b 2f; \ |
@@ -45,11 +54,68 @@ END_FTR_SECTION_IFSET(CPU_FTR_VSX); \ | |||
45 | 3: | 54 | 3: |
46 | #else | 55 | #else |
47 | #define __REST_32FPVSRS(n,b,base) REST_32FPRS(n, base) | 56 | #define __REST_32FPVSRS(n,b,base) REST_32FPRS(n, base) |
57 | #define __REST_32FPVSRS_TRANSACT(n,b,base) REST_32FPRS(n, base) | ||
48 | #define __SAVE_32FPVSRS(n,b,base) SAVE_32FPRS(n, base) | 58 | #define __SAVE_32FPVSRS(n,b,base) SAVE_32FPRS(n, base) |
49 | #endif | 59 | #endif |
50 | #define REST_32FPVSRS(n,c,base) __REST_32FPVSRS(n,__REG_##c,__REG_##base) | 60 | #define REST_32FPVSRS(n,c,base) __REST_32FPVSRS(n,__REG_##c,__REG_##base) |
61 | #define REST_32FPVSRS_TRANSACT(n,c,base) \ | ||
62 | __REST_32FPVSRS_TRANSACT(n,__REG_##c,__REG_##base) | ||
51 | #define SAVE_32FPVSRS(n,c,base) __SAVE_32FPVSRS(n,__REG_##c,__REG_##base) | 63 | #define SAVE_32FPVSRS(n,c,base) __SAVE_32FPVSRS(n,__REG_##c,__REG_##base) |
52 | 64 | ||
65 | #ifdef CONFIG_PPC_TRANSACTIONAL_MEM | ||
66 | /* | ||
67 | * Wrapper to call load_up_fpu from C. | ||
68 | * void do_load_up_fpu(struct pt_regs *regs); | ||
69 | */ | ||
70 | _GLOBAL(do_load_up_fpu) | ||
71 | mflr r0 | ||
72 | std r0, 16(r1) | ||
73 | stdu r1, -112(r1) | ||
74 | |||
75 | subi r6, r3, STACK_FRAME_OVERHEAD | ||
76 | /* load_up_fpu expects r12=MSR, r13=PACA, and returns | ||
77 | * with r12 = new MSR. | ||
78 | */ | ||
79 | ld r12,_MSR(r6) | ||
80 | GET_PACA(r13) | ||
81 | |||
82 | bl load_up_fpu | ||
83 | std r12,_MSR(r6) | ||
84 | |||
85 | ld r0, 112+16(r1) | ||
86 | addi r1, r1, 112 | ||
87 | mtlr r0 | ||
88 | blr | ||
89 | |||
90 | |||
91 | /* void do_load_up_transact_fpu(struct thread_struct *thread) | ||
92 | * | ||
93 | * This is similar to load_up_fpu but for the transactional version of the FP | ||
94 | * register set. It doesn't mess with the task MSR or valid flags. | ||
95 | * Furthermore, we don't do lazy FP with TM currently. | ||
96 | */ | ||
97 | _GLOBAL(do_load_up_transact_fpu) | ||
98 | mfmsr r6 | ||
99 | ori r5,r6,MSR_FP | ||
100 | #ifdef CONFIG_VSX | ||
101 | BEGIN_FTR_SECTION | ||
102 | oris r5,r5,MSR_VSX@h | ||
103 | END_FTR_SECTION_IFSET(CPU_FTR_VSX) | ||
104 | #endif | ||
105 | SYNC | ||
106 | MTMSRD(r5) | ||
107 | |||
108 | lfd fr0,THREAD_TRANSACT_FPSCR(r3) | ||
109 | MTFSF_L(fr0) | ||
110 | REST_32FPVSRS_TRANSACT(0, R4, R3) | ||
111 | |||
112 | /* FP/VSX off again */ | ||
113 | MTMSRD(r6) | ||
114 | SYNC | ||
115 | |||
116 | blr | ||
117 | #endif /* CONFIG_PPC_TRANSACTIONAL_MEM */ | ||
118 | |||
53 | /* | 119 | /* |
54 | * This task wants to use the FPU now. | 120 | * This task wants to use the FPU now. |
55 | * On UP, disable FP for the task which had the FPU previously, | 121 | * On UP, disable FP for the task which had the FPU previously, |
diff --git a/arch/powerpc/kernel/paca.c b/arch/powerpc/kernel/paca.c index cd6da855090c..f8f24685f10a 100644 --- a/arch/powerpc/kernel/paca.c +++ b/arch/powerpc/kernel/paca.c | |||
@@ -120,8 +120,6 @@ struct slb_shadow slb_shadow[] __cacheline_aligned = { | |||
120 | struct paca_struct *paca; | 120 | struct paca_struct *paca; |
121 | EXPORT_SYMBOL(paca); | 121 | EXPORT_SYMBOL(paca); |
122 | 122 | ||
123 | struct paca_struct boot_paca; | ||
124 | |||
125 | void __init initialise_paca(struct paca_struct *new_paca, int cpu) | 123 | void __init initialise_paca(struct paca_struct *new_paca, int cpu) |
126 | { | 124 | { |
127 | /* The TOC register (GPR2) points 32kB into the TOC, so that 64kB | 125 | /* The TOC register (GPR2) points 32kB into the TOC, so that 64kB |
diff --git a/arch/powerpc/kernel/process.c b/arch/powerpc/kernel/process.c index 96e31de89b43..59dd545fdde1 100644 --- a/arch/powerpc/kernel/process.c +++ b/arch/powerpc/kernel/process.c | |||
@@ -50,6 +50,7 @@ | |||
50 | #include <asm/runlatch.h> | 50 | #include <asm/runlatch.h> |
51 | #include <asm/syscalls.h> | 51 | #include <asm/syscalls.h> |
52 | #include <asm/switch_to.h> | 52 | #include <asm/switch_to.h> |
53 | #include <asm/tm.h> | ||
53 | #include <asm/debug.h> | 54 | #include <asm/debug.h> |
54 | #ifdef CONFIG_PPC64 | 55 | #ifdef CONFIG_PPC64 |
55 | #include <asm/firmware.h> | 56 | #include <asm/firmware.h> |
@@ -57,6 +58,13 @@ | |||
57 | #include <linux/kprobes.h> | 58 | #include <linux/kprobes.h> |
58 | #include <linux/kdebug.h> | 59 | #include <linux/kdebug.h> |
59 | 60 | ||
61 | /* Transactional Memory debug */ | ||
62 | #ifdef TM_DEBUG_SW | ||
63 | #define TM_DEBUG(x...) printk(KERN_INFO x) | ||
64 | #else | ||
65 | #define TM_DEBUG(x...) do { } while(0) | ||
66 | #endif | ||
67 | |||
60 | extern unsigned long _get_SP(void); | 68 | extern unsigned long _get_SP(void); |
61 | 69 | ||
62 | #ifndef CONFIG_SMP | 70 | #ifndef CONFIG_SMP |
@@ -460,6 +468,117 @@ static inline bool hw_brk_match(struct arch_hw_breakpoint *a, | |||
460 | return false; | 468 | return false; |
461 | return true; | 469 | return true; |
462 | } | 470 | } |
471 | #ifdef CONFIG_PPC_TRANSACTIONAL_MEM | ||
472 | static inline void tm_reclaim_task(struct task_struct *tsk) | ||
473 | { | ||
474 | /* We have to work out if we're switching from/to a task that's in the | ||
475 | * middle of a transaction. | ||
476 | * | ||
477 | * In switching we need to maintain a 2nd register state as | ||
478 | * oldtask->thread.ckpt_regs. We tm_reclaim(oldproc); this saves the | ||
479 | * checkpointed (tbegin) state in ckpt_regs and saves the transactional | ||
480 | * (current) FPRs into oldtask->thread.transact_fpr[]. | ||
481 | * | ||
482 | * We also context switch (save) TFHAR/TEXASR/TFIAR in here. | ||
483 | */ | ||
484 | struct thread_struct *thr = &tsk->thread; | ||
485 | |||
486 | if (!thr->regs) | ||
487 | return; | ||
488 | |||
489 | if (!MSR_TM_ACTIVE(thr->regs->msr)) | ||
490 | goto out_and_saveregs; | ||
491 | |||
492 | /* Stash the original thread MSR, as giveup_fpu et al will | ||
493 | * modify it. We hold onto it to see whether the task used | ||
494 | * FP & vector regs. | ||
495 | */ | ||
496 | thr->tm_orig_msr = thr->regs->msr; | ||
497 | |||
498 | TM_DEBUG("--- tm_reclaim on pid %d (NIP=%lx, " | ||
499 | "ccr=%lx, msr=%lx, trap=%lx)\n", | ||
500 | tsk->pid, thr->regs->nip, | ||
501 | thr->regs->ccr, thr->regs->msr, | ||
502 | thr->regs->trap); | ||
503 | |||
504 | tm_reclaim(thr, thr->regs->msr, TM_CAUSE_RESCHED); | ||
505 | |||
506 | TM_DEBUG("--- tm_reclaim on pid %d complete\n", | ||
507 | tsk->pid); | ||
508 | |||
509 | out_and_saveregs: | ||
510 | /* Always save the regs here, even if a transaction's not active. | ||
511 | * This context-switches a thread's TM info SPRs. We do it here to | ||
512 | * be consistent with the restore path (in recheckpoint) which | ||
513 | * cannot happen later in _switch(). | ||
514 | */ | ||
515 | tm_save_sprs(thr); | ||
516 | } | ||
517 | |||
518 | static inline void tm_recheckpoint_new_task(struct task_struct *new) | ||
519 | { | ||
520 | unsigned long msr; | ||
521 | |||
522 | if (!cpu_has_feature(CPU_FTR_TM)) | ||
523 | return; | ||
524 | |||
525 | /* Recheckpoint the registers of the thread we're about to switch to. | ||
526 | * | ||
527 | * If the task was using FP, we non-lazily reload both the original and | ||
528 | * the speculative FP register states. This is because the kernel | ||
529 | * doesn't see if/when a TM rollback occurs, so if we take an FP | ||
530 | * unavoidable later, we are unable to determine which set of FP regs | ||
531 | * need to be restored. | ||
532 | */ | ||
533 | if (!new->thread.regs) | ||
534 | return; | ||
535 | |||
536 | /* The TM SPRs are restored here, so that TEXASR.FS can be set | ||
537 | * before the trecheckpoint and no explosion occurs. | ||
538 | */ | ||
539 | tm_restore_sprs(&new->thread); | ||
540 | |||
541 | if (!MSR_TM_ACTIVE(new->thread.regs->msr)) | ||
542 | return; | ||
543 | msr = new->thread.tm_orig_msr; | ||
544 | /* Recheckpoint to restore original checkpointed register state. */ | ||
545 | TM_DEBUG("*** tm_recheckpoint of pid %d " | ||
546 | "(new->msr 0x%lx, new->origmsr 0x%lx)\n", | ||
547 | new->pid, new->thread.regs->msr, msr); | ||
548 | |||
549 | /* This loads the checkpointed FP/VEC state, if used */ | ||
550 | tm_recheckpoint(&new->thread, msr); | ||
551 | |||
552 | /* This loads the speculative FP/VEC state, if used */ | ||
553 | if (msr & MSR_FP) { | ||
554 | do_load_up_transact_fpu(&new->thread); | ||
555 | new->thread.regs->msr |= | ||
556 | (MSR_FP | new->thread.fpexc_mode); | ||
557 | } | ||
558 | if (msr & MSR_VEC) { | ||
559 | do_load_up_transact_altivec(&new->thread); | ||
560 | new->thread.regs->msr |= MSR_VEC; | ||
561 | } | ||
562 | /* We may as well turn on VSX too since all the state is restored now */ | ||
563 | if (msr & MSR_VSX) | ||
564 | new->thread.regs->msr |= MSR_VSX; | ||
565 | |||
566 | TM_DEBUG("*** tm_recheckpoint of pid %d complete " | ||
567 | "(kernel msr 0x%lx)\n", | ||
568 | new->pid, mfmsr()); | ||
569 | } | ||
570 | |||
571 | static inline void __switch_to_tm(struct task_struct *prev) | ||
572 | { | ||
573 | if (cpu_has_feature(CPU_FTR_TM)) { | ||
574 | tm_enable(); | ||
575 | tm_reclaim_task(prev); | ||
576 | } | ||
577 | } | ||
578 | #else | ||
579 | #define tm_recheckpoint_new_task(new) | ||
580 | #define __switch_to_tm(prev) | ||
581 | #endif /* CONFIG_PPC_TRANSACTIONAL_MEM */ | ||
463 | 582 | ||
464 | struct task_struct *__switch_to(struct task_struct *prev, | 583 | struct task_struct *__switch_to(struct task_struct *prev, |
465 | struct task_struct *new) | 584 | struct task_struct *new) |
@@ -471,6 +590,8 @@ struct task_struct *__switch_to(struct task_struct *prev, | |||
471 | struct ppc64_tlb_batch *batch; | 590 | struct ppc64_tlb_batch *batch; |
472 | #endif | 591 | #endif |
473 | 592 | ||
593 | __switch_to_tm(prev); | ||
594 | |||
474 | #ifdef CONFIG_SMP | 595 | #ifdef CONFIG_SMP |
475 | /* avoid complexity of lazy save/restore of fpu | 596 | /* avoid complexity of lazy save/restore of fpu |
476 | * by just saving it every time we switch out if | 597 | * by just saving it every time we switch out if |
@@ -586,6 +707,9 @@ struct task_struct *__switch_to(struct task_struct *prev, | |||
586 | * of sync. Hard disable here. | 707 | * of sync. Hard disable here. |
587 | */ | 708 | */ |
588 | hard_irq_disable(); | 709 | hard_irq_disable(); |
710 | |||
711 | tm_recheckpoint_new_task(new); | ||
712 | |||
589 | last = _switch(old_thread, new_thread); | 713 | last = _switch(old_thread, new_thread); |
590 | 714 | ||
591 | #ifdef CONFIG_PPC_BOOK3S_64 | 715 | #ifdef CONFIG_PPC_BOOK3S_64 |
@@ -747,6 +871,9 @@ void show_regs(struct pt_regs * regs) | |||
747 | printk("NIP ["REG"] %pS\n", regs->nip, (void *)regs->nip); | 871 | printk("NIP ["REG"] %pS\n", regs->nip, (void *)regs->nip); |
748 | printk("LR ["REG"] %pS\n", regs->link, (void *)regs->link); | 872 | printk("LR ["REG"] %pS\n", regs->link, (void *)regs->link); |
749 | #endif | 873 | #endif |
874 | #ifdef CONFIG_PPC_TRANSACTIONAL_MEM | ||
875 | printk("PACATMSCRATCH [%llx]\n", get_paca()->tm_scratch); | ||
876 | #endif | ||
750 | show_stack(current, (unsigned long *) regs->gpr[1]); | 877 | show_stack(current, (unsigned long *) regs->gpr[1]); |
751 | if (!user_mode(regs)) | 878 | if (!user_mode(regs)) |
752 | show_instructions(regs); | 879 | show_instructions(regs); |
@@ -958,7 +1085,6 @@ void start_thread(struct pt_regs *regs, unsigned long start, unsigned long sp) | |||
958 | regs->msr = MSR_USER32; | 1085 | regs->msr = MSR_USER32; |
959 | } | 1086 | } |
960 | #endif | 1087 | #endif |
961 | |||
962 | discard_lazy_cpu_state(); | 1088 | discard_lazy_cpu_state(); |
963 | #ifdef CONFIG_VSX | 1089 | #ifdef CONFIG_VSX |
964 | current->thread.used_vsr = 0; | 1090 | current->thread.used_vsr = 0; |
@@ -978,6 +1104,13 @@ void start_thread(struct pt_regs *regs, unsigned long start, unsigned long sp) | |||
978 | current->thread.spefscr = 0; | 1104 | current->thread.spefscr = 0; |
979 | current->thread.used_spe = 0; | 1105 | current->thread.used_spe = 0; |
980 | #endif /* CONFIG_SPE */ | 1106 | #endif /* CONFIG_SPE */ |
1107 | #ifdef CONFIG_PPC_TRANSACTIONAL_MEM | ||
1108 | if (cpu_has_feature(CPU_FTR_TM)) | ||
1109 | regs->msr |= MSR_TM; | ||
1110 | current->thread.tm_tfhar = 0; | ||
1111 | current->thread.tm_texasr = 0; | ||
1112 | current->thread.tm_tfiar = 0; | ||
1113 | #endif /* CONFIG_PPC_TRANSACTIONAL_MEM */ | ||
981 | } | 1114 | } |
982 | 1115 | ||
983 | #define PR_FP_ALL_EXCEPT (PR_FP_EXC_DIV | PR_FP_EXC_OVF | PR_FP_EXC_UND \ | 1116 | #define PR_FP_ALL_EXCEPT (PR_FP_EXC_DIV | PR_FP_EXC_OVF | PR_FP_EXC_UND \ |
diff --git a/arch/powerpc/kernel/setup_64.c b/arch/powerpc/kernel/setup_64.c index 6da881b35dac..75fbaceb5c87 100644 --- a/arch/powerpc/kernel/setup_64.c +++ b/arch/powerpc/kernel/setup_64.c | |||
@@ -156,6 +156,15 @@ early_param("smt-enabled", early_smt_enabled); | |||
156 | #define check_smt_enabled() | 156 | #define check_smt_enabled() |
157 | #endif /* CONFIG_SMP */ | 157 | #endif /* CONFIG_SMP */ |
158 | 158 | ||
159 | /** Fix up paca fields required for the boot cpu */ | ||
160 | static void fixup_boot_paca(void) | ||
161 | { | ||
162 | /* The boot cpu is started */ | ||
163 | get_paca()->cpu_start = 1; | ||
164 | /* Allow percpu accesses to work until we setup percpu data */ | ||
165 | get_paca()->data_offset = 0; | ||
166 | } | ||
167 | |||
159 | /* | 168 | /* |
160 | * Early initialization entry point. This is called by head.S | 169 | * Early initialization entry point. This is called by head.S |
161 | * with MMU translation disabled. We rely on the "feature" of | 170 | * with MMU translation disabled. We rely on the "feature" of |
@@ -177,6 +186,8 @@ early_param("smt-enabled", early_smt_enabled); | |||
177 | 186 | ||
178 | void __init early_setup(unsigned long dt_ptr) | 187 | void __init early_setup(unsigned long dt_ptr) |
179 | { | 188 | { |
189 | static __initdata struct paca_struct boot_paca; | ||
190 | |||
180 | /* -------- printk is _NOT_ safe to use here ! ------- */ | 191 | /* -------- printk is _NOT_ safe to use here ! ------- */ |
181 | 192 | ||
182 | /* Identify CPU type */ | 193 | /* Identify CPU type */ |
@@ -185,6 +196,7 @@ void __init early_setup(unsigned long dt_ptr) | |||
185 | /* Assume we're on cpu 0 for now. Don't write to the paca yet! */ | 196 | /* Assume we're on cpu 0 for now. Don't write to the paca yet! */ |
186 | initialise_paca(&boot_paca, 0); | 197 | initialise_paca(&boot_paca, 0); |
187 | setup_paca(&boot_paca); | 198 | setup_paca(&boot_paca); |
199 | fixup_boot_paca(); | ||
188 | 200 | ||
189 | /* Initialize lockdep early or else spinlocks will blow */ | 201 | /* Initialize lockdep early or else spinlocks will blow */ |
190 | lockdep_init(); | 202 | lockdep_init(); |
@@ -205,11 +217,7 @@ void __init early_setup(unsigned long dt_ptr) | |||
205 | 217 | ||
206 | /* Now we know the logical id of our boot cpu, setup the paca. */ | 218 | /* Now we know the logical id of our boot cpu, setup the paca. */ |
207 | setup_paca(&paca[boot_cpuid]); | 219 | setup_paca(&paca[boot_cpuid]); |
208 | 220 | fixup_boot_paca(); | |
209 | /* Fix up paca fields required for the boot cpu */ | ||
210 | get_paca()->cpu_start = 1; | ||
211 | /* Allow percpu accesses to "work" until we setup percpu data */ | ||
212 | get_paca()->data_offset = 0; | ||
213 | 221 | ||
214 | /* Probe the machine type */ | 222 | /* Probe the machine type */ |
215 | probe_machine(); | 223 | probe_machine(); |
diff --git a/arch/powerpc/kernel/signal.h b/arch/powerpc/kernel/signal.h index e00acb413934..ec84c901ceab 100644 --- a/arch/powerpc/kernel/signal.h +++ b/arch/powerpc/kernel/signal.h | |||
@@ -25,13 +25,21 @@ extern int handle_rt_signal32(unsigned long sig, struct k_sigaction *ka, | |||
25 | 25 | ||
26 | extern unsigned long copy_fpr_to_user(void __user *to, | 26 | extern unsigned long copy_fpr_to_user(void __user *to, |
27 | struct task_struct *task); | 27 | struct task_struct *task); |
28 | extern unsigned long copy_transact_fpr_to_user(void __user *to, | ||
29 | struct task_struct *task); | ||
28 | extern unsigned long copy_fpr_from_user(struct task_struct *task, | 30 | extern unsigned long copy_fpr_from_user(struct task_struct *task, |
29 | void __user *from); | 31 | void __user *from); |
32 | extern unsigned long copy_transact_fpr_from_user(struct task_struct *task, | ||
33 | void __user *from); | ||
30 | #ifdef CONFIG_VSX | 34 | #ifdef CONFIG_VSX |
31 | extern unsigned long copy_vsx_to_user(void __user *to, | 35 | extern unsigned long copy_vsx_to_user(void __user *to, |
32 | struct task_struct *task); | 36 | struct task_struct *task); |
37 | extern unsigned long copy_transact_vsx_to_user(void __user *to, | ||
38 | struct task_struct *task); | ||
33 | extern unsigned long copy_vsx_from_user(struct task_struct *task, | 39 | extern unsigned long copy_vsx_from_user(struct task_struct *task, |
34 | void __user *from); | 40 | void __user *from); |
41 | extern unsigned long copy_transact_vsx_from_user(struct task_struct *task, | ||
42 | void __user *from); | ||
35 | #endif | 43 | #endif |
36 | 44 | ||
37 | #ifdef CONFIG_PPC64 | 45 | #ifdef CONFIG_PPC64 |
diff --git a/arch/powerpc/kernel/signal_32.c b/arch/powerpc/kernel/signal_32.c index 804e323c139d..e4a88d340de6 100644 --- a/arch/powerpc/kernel/signal_32.c +++ b/arch/powerpc/kernel/signal_32.c | |||
@@ -43,6 +43,7 @@ | |||
43 | #include <asm/sigcontext.h> | 43 | #include <asm/sigcontext.h> |
44 | #include <asm/vdso.h> | 44 | #include <asm/vdso.h> |
45 | #include <asm/switch_to.h> | 45 | #include <asm/switch_to.h> |
46 | #include <asm/tm.h> | ||
46 | #ifdef CONFIG_PPC64 | 47 | #ifdef CONFIG_PPC64 |
47 | #include "ppc32.h" | 48 | #include "ppc32.h" |
48 | #include <asm/unistd.h> | 49 | #include <asm/unistd.h> |
@@ -293,6 +294,10 @@ long sys_sigaction(int sig, struct old_sigaction __user *act, | |||
293 | struct sigframe { | 294 | struct sigframe { |
294 | struct sigcontext sctx; /* the sigcontext */ | 295 | struct sigcontext sctx; /* the sigcontext */ |
295 | struct mcontext mctx; /* all the register values */ | 296 | struct mcontext mctx; /* all the register values */ |
297 | #ifdef CONFIG_PPC_TRANSACTIONAL_MEM | ||
298 | struct sigcontext sctx_transact; | ||
299 | struct mcontext mctx_transact; | ||
300 | #endif | ||
296 | /* | 301 | /* |
297 | * Programs using the rs6000/xcoff abi can save up to 19 gp | 302 | * Programs using the rs6000/xcoff abi can save up to 19 gp |
298 | * regs and 18 fp regs below sp before decrementing it. | 303 | * regs and 18 fp regs below sp before decrementing it. |
@@ -321,6 +326,9 @@ struct rt_sigframe { | |||
321 | struct siginfo info; | 326 | struct siginfo info; |
322 | #endif | 327 | #endif |
323 | struct ucontext uc; | 328 | struct ucontext uc; |
329 | #ifdef CONFIG_PPC_TRANSACTIONAL_MEM | ||
330 | struct ucontext uc_transact; | ||
331 | #endif | ||
324 | /* | 332 | /* |
325 | * Programs using the rs6000/xcoff abi can save up to 19 gp | 333 | * Programs using the rs6000/xcoff abi can save up to 19 gp |
326 | * regs and 18 fp regs below sp before decrementing it. | 334 | * regs and 18 fp regs below sp before decrementing it. |
@@ -381,6 +389,61 @@ unsigned long copy_vsx_from_user(struct task_struct *task, | |||
381 | task->thread.fpr[i][TS_VSRLOWOFFSET] = buf[i]; | 389 | task->thread.fpr[i][TS_VSRLOWOFFSET] = buf[i]; |
382 | return 0; | 390 | return 0; |
383 | } | 391 | } |
392 | |||
393 | #ifdef CONFIG_PPC_TRANSACTIONAL_MEM | ||
394 | unsigned long copy_transact_fpr_to_user(void __user *to, | ||
395 | struct task_struct *task) | ||
396 | { | ||
397 | double buf[ELF_NFPREG]; | ||
398 | int i; | ||
399 | |||
400 | /* save FPR copy to local buffer then write to the thread_struct */ | ||
401 | for (i = 0; i < (ELF_NFPREG - 1) ; i++) | ||
402 | buf[i] = task->thread.TS_TRANS_FPR(i); | ||
403 | memcpy(&buf[i], &task->thread.transact_fpscr, sizeof(double)); | ||
404 | return __copy_to_user(to, buf, ELF_NFPREG * sizeof(double)); | ||
405 | } | ||
406 | |||
407 | unsigned long copy_transact_fpr_from_user(struct task_struct *task, | ||
408 | void __user *from) | ||
409 | { | ||
410 | double buf[ELF_NFPREG]; | ||
411 | int i; | ||
412 | |||
413 | if (__copy_from_user(buf, from, ELF_NFPREG * sizeof(double))) | ||
414 | return 1; | ||
415 | for (i = 0; i < (ELF_NFPREG - 1) ; i++) | ||
416 | task->thread.TS_TRANS_FPR(i) = buf[i]; | ||
417 | memcpy(&task->thread.transact_fpscr, &buf[i], sizeof(double)); | ||
418 | |||
419 | return 0; | ||
420 | } | ||
421 | |||
422 | unsigned long copy_transact_vsx_to_user(void __user *to, | ||
423 | struct task_struct *task) | ||
424 | { | ||
425 | double buf[ELF_NVSRHALFREG]; | ||
426 | int i; | ||
427 | |||
428 | /* save FPR copy to local buffer then write to the thread_struct */ | ||
429 | for (i = 0; i < ELF_NVSRHALFREG; i++) | ||
430 | buf[i] = task->thread.transact_fpr[i][TS_VSRLOWOFFSET]; | ||
431 | return __copy_to_user(to, buf, ELF_NVSRHALFREG * sizeof(double)); | ||
432 | } | ||
433 | |||
434 | unsigned long copy_transact_vsx_from_user(struct task_struct *task, | ||
435 | void __user *from) | ||
436 | { | ||
437 | double buf[ELF_NVSRHALFREG]; | ||
438 | int i; | ||
439 | |||
440 | if (__copy_from_user(buf, from, ELF_NVSRHALFREG * sizeof(double))) | ||
441 | return 1; | ||
442 | for (i = 0; i < ELF_NVSRHALFREG ; i++) | ||
443 | task->thread.transact_fpr[i][TS_VSRLOWOFFSET] = buf[i]; | ||
444 | return 0; | ||
445 | } | ||
446 | #endif /* CONFIG_PPC_TRANSACTIONAL_MEM */ | ||
384 | #else | 447 | #else |
385 | inline unsigned long copy_fpr_to_user(void __user *to, | 448 | inline unsigned long copy_fpr_to_user(void __user *to, |
386 | struct task_struct *task) | 449 | struct task_struct *task) |
@@ -395,6 +458,22 @@ inline unsigned long copy_fpr_from_user(struct task_struct *task, | |||
395 | return __copy_from_user(task->thread.fpr, from, | 458 | return __copy_from_user(task->thread.fpr, from, |
396 | ELF_NFPREG * sizeof(double)); | 459 | ELF_NFPREG * sizeof(double)); |
397 | } | 460 | } |
461 | |||
462 | #ifdef CONFIG_PPC_TRANSACTIONAL_MEM | ||
463 | inline unsigned long copy_transact_fpr_to_user(void __user *to, | ||
464 | struct task_struct *task) | ||
465 | { | ||
466 | return __copy_to_user(to, task->thread.transact_fpr, | ||
467 | ELF_NFPREG * sizeof(double)); | ||
468 | } | ||
469 | |||
470 | inline unsigned long copy_transact_fpr_from_user(struct task_struct *task, | ||
471 | void __user *from) | ||
472 | { | ||
473 | return __copy_from_user(task->thread.transact_fpr, from, | ||
474 | ELF_NFPREG * sizeof(double)); | ||
475 | } | ||
476 | #endif /* CONFIG_PPC_TRANSACTIONAL_MEM */ | ||
398 | #endif | 477 | #endif |
399 | 478 | ||
400 | /* | 479 | /* |
@@ -483,6 +562,156 @@ static int save_user_regs(struct pt_regs *regs, struct mcontext __user *frame, | |||
483 | return 0; | 562 | return 0; |
484 | } | 563 | } |
485 | 564 | ||
565 | #ifdef CONFIG_PPC_TRANSACTIONAL_MEM | ||
566 | /* | ||
567 | * Save the current user registers on the user stack. | ||
568 | * We only save the altivec/spe registers if the process has used | ||
569 | * altivec/spe instructions at some point. | ||
570 | * We also save the transactional registers to a second ucontext in the | ||
571 | * frame. | ||
572 | * | ||
573 | * See save_user_regs() and signal_64.c:setup_tm_sigcontexts(). | ||
574 | */ | ||
575 | static int save_tm_user_regs(struct pt_regs *regs, | ||
576 | struct mcontext __user *frame, | ||
577 | struct mcontext __user *tm_frame, int sigret) | ||
578 | { | ||
579 | unsigned long msr = regs->msr; | ||
580 | |||
581 | /* tm_reclaim rolls back all reg states, updating thread.ckpt_regs, | ||
582 | * thread.transact_fpr[], thread.transact_vr[], etc. | ||
583 | */ | ||
584 | tm_enable(); | ||
585 | tm_reclaim(¤t->thread, msr, TM_CAUSE_SIGNAL); | ||
586 | |||
587 | /* Make sure floating point registers are stored in regs */ | ||
588 | flush_fp_to_thread(current); | ||
589 | |||
590 | /* Save both sets of general registers */ | ||
591 | if (save_general_regs(¤t->thread.ckpt_regs, frame) | ||
592 | || save_general_regs(regs, tm_frame)) | ||
593 | return 1; | ||
594 | |||
595 | /* Stash the top half of the 64bit MSR into the 32bit MSR word | ||
596 | * of the transactional mcontext. This way we have a backward-compatible | ||
597 | * MSR in the 'normal' (checkpointed) mcontext and additionally one can | ||
598 | * also look at what type of transaction (T or S) was active at the | ||
599 | * time of the signal. | ||
600 | */ | ||
601 | if (__put_user((msr >> 32), &tm_frame->mc_gregs[PT_MSR])) | ||
602 | return 1; | ||
603 | |||
604 | #ifdef CONFIG_ALTIVEC | ||
605 | /* save altivec registers */ | ||
606 | if (current->thread.used_vr) { | ||
607 | flush_altivec_to_thread(current); | ||
608 | if (__copy_to_user(&frame->mc_vregs, current->thread.vr, | ||
609 | ELF_NVRREG * sizeof(vector128))) | ||
610 | return 1; | ||
611 | if (msr & MSR_VEC) { | ||
612 | if (__copy_to_user(&tm_frame->mc_vregs, | ||
613 | current->thread.transact_vr, | ||
614 | ELF_NVRREG * sizeof(vector128))) | ||
615 | return 1; | ||
616 | } else { | ||
617 | if (__copy_to_user(&tm_frame->mc_vregs, | ||
618 | current->thread.vr, | ||
619 | ELF_NVRREG * sizeof(vector128))) | ||
620 | return 1; | ||
621 | } | ||
622 | |||
623 | /* set MSR_VEC in the saved MSR value to indicate that | ||
624 | * frame->mc_vregs contains valid data | ||
625 | */ | ||
626 | msr |= MSR_VEC; | ||
627 | } | ||
628 | |||
629 | /* We always copy to/from vrsave, it's 0 if we don't have or don't | ||
630 | * use altivec. Since VSCR only contains 32 bits saved in the least | ||
631 | * significant bits of a vector, we "cheat" and stuff VRSAVE in the | ||
632 | * most significant bits of that same vector. --BenH | ||
633 | */ | ||
634 | if (__put_user(current->thread.vrsave, | ||
635 | (u32 __user *)&frame->mc_vregs[32])) | ||
636 | return 1; | ||
637 | if (msr & MSR_VEC) { | ||
638 | if (__put_user(current->thread.transact_vrsave, | ||
639 | (u32 __user *)&tm_frame->mc_vregs[32])) | ||
640 | return 1; | ||
641 | } else { | ||
642 | if (__put_user(current->thread.vrsave, | ||
643 | (u32 __user *)&tm_frame->mc_vregs[32])) | ||
644 | return 1; | ||
645 | } | ||
646 | #endif /* CONFIG_ALTIVEC */ | ||
647 | |||
648 | if (copy_fpr_to_user(&frame->mc_fregs, current)) | ||
649 | return 1; | ||
650 | if (msr & MSR_FP) { | ||
651 | if (copy_transact_fpr_to_user(&tm_frame->mc_fregs, current)) | ||
652 | return 1; | ||
653 | } else { | ||
654 | if (copy_fpr_to_user(&tm_frame->mc_fregs, current)) | ||
655 | return 1; | ||
656 | } | ||
657 | |||
658 | #ifdef CONFIG_VSX | ||
659 | /* | ||
660 | * Copy VSR 0-31 upper half from thread_struct to local | ||
661 | * buffer, then write that to userspace. Also set MSR_VSX in | ||
662 | * the saved MSR value to indicate that frame->mc_vregs | ||
663 | * contains valid data | ||
664 | */ | ||
665 | if (current->thread.used_vsr) { | ||
666 | __giveup_vsx(current); | ||
667 | if (copy_vsx_to_user(&frame->mc_vsregs, current)) | ||
668 | return 1; | ||
669 | if (msr & MSR_VSX) { | ||
670 | if (copy_transact_vsx_to_user(&tm_frame->mc_vsregs, | ||
671 | current)) | ||
672 | return 1; | ||
673 | } else { | ||
674 | if (copy_vsx_to_user(&tm_frame->mc_vsregs, current)) | ||
675 | return 1; | ||
676 | } | ||
677 | |||
678 | msr |= MSR_VSX; | ||
679 | } | ||
680 | #endif /* CONFIG_VSX */ | ||
681 | #ifdef CONFIG_SPE | ||
682 | /* SPE regs are not checkpointed with TM, so this section is | ||
683 | * simply the same as in save_user_regs(). | ||
684 | */ | ||
685 | if (current->thread.used_spe) { | ||
686 | flush_spe_to_thread(current); | ||
687 | if (__copy_to_user(&frame->mc_vregs, current->thread.evr, | ||
688 | ELF_NEVRREG * sizeof(u32))) | ||
689 | return 1; | ||
690 | /* set MSR_SPE in the saved MSR value to indicate that | ||
691 | * frame->mc_vregs contains valid data */ | ||
692 | msr |= MSR_SPE; | ||
693 | } | ||
694 | |||
695 | /* We always copy to/from spefscr */ | ||
696 | if (__put_user(current->thread.spefscr, (u32 __user *)&frame->mc_vregs + ELF_NEVRREG)) | ||
697 | return 1; | ||
698 | #endif /* CONFIG_SPE */ | ||
699 | |||
700 | if (__put_user(msr, &frame->mc_gregs[PT_MSR])) | ||
701 | return 1; | ||
702 | if (sigret) { | ||
703 | /* Set up the sigreturn trampoline: li r0,sigret; sc */ | ||
704 | if (__put_user(0x38000000UL + sigret, &frame->tramp[0]) | ||
705 | || __put_user(0x44000002UL, &frame->tramp[1])) | ||
706 | return 1; | ||
707 | flush_icache_range((unsigned long) &frame->tramp[0], | ||
708 | (unsigned long) &frame->tramp[2]); | ||
709 | } | ||
710 | |||
711 | return 0; | ||
712 | } | ||
713 | #endif | ||
714 | |||
486 | /* | 715 | /* |
487 | * Restore the current user register values from the user stack, | 716 | * Restore the current user register values from the user stack, |
488 | * (except for MSR). | 717 | * (except for MSR). |
@@ -588,6 +817,139 @@ static long restore_user_regs(struct pt_regs *regs, | |||
588 | return 0; | 817 | return 0; |
589 | } | 818 | } |
590 | 819 | ||
820 | #ifdef CONFIG_PPC_TRANSACTIONAL_MEM | ||
821 | /* | ||
822 | * Restore the current user register values from the user stack, except for | ||
823 | * MSR, and recheckpoint the original checkpointed register state for processes | ||
824 | * in transactions. | ||
825 | */ | ||
826 | static long restore_tm_user_regs(struct pt_regs *regs, | ||
827 | struct mcontext __user *sr, | ||
828 | struct mcontext __user *tm_sr) | ||
829 | { | ||
830 | long err; | ||
831 | unsigned long msr; | ||
832 | #ifdef CONFIG_VSX | ||
833 | int i; | ||
834 | #endif | ||
835 | |||
836 | /* | ||
837 | * restore general registers but not including MSR or SOFTE. Also | ||
838 | * take care of keeping r2 (TLS) intact if not a signal. | ||
839 | * See comment in signal_64.c:restore_tm_sigcontexts(); | ||
840 | * TFHAR is restored from the checkpointed NIP; TEXASR and TFIAR | ||
841 | * were set by the signal delivery. | ||
842 | */ | ||
843 | err = restore_general_regs(regs, tm_sr); | ||
844 | err |= restore_general_regs(¤t->thread.ckpt_regs, sr); | ||
845 | |||
846 | err |= __get_user(current->thread.tm_tfhar, &sr->mc_gregs[PT_NIP]); | ||
847 | |||
848 | err |= __get_user(msr, &sr->mc_gregs[PT_MSR]); | ||
849 | if (err) | ||
850 | return 1; | ||
851 | |||
852 | /* Restore the previous little-endian mode */ | ||
853 | regs->msr = (regs->msr & ~MSR_LE) | (msr & MSR_LE); | ||
854 | |||
855 | /* | ||
856 | * Do this before updating the thread state in | ||
857 | * current->thread.fpr/vr/evr. That way, if we get preempted | ||
858 | * and another task grabs the FPU/Altivec/SPE, it won't be | ||
859 | * tempted to save the current CPU state into the thread_struct | ||
860 | * and corrupt what we are writing there. | ||
861 | */ | ||
862 | discard_lazy_cpu_state(); | ||
863 | |||
864 | #ifdef CONFIG_ALTIVEC | ||
865 | regs->msr &= ~MSR_VEC; | ||
866 | if (msr & MSR_VEC) { | ||
867 | /* restore altivec registers from the stack */ | ||
868 | if (__copy_from_user(current->thread.vr, &sr->mc_vregs, | ||
869 | sizeof(sr->mc_vregs)) || | ||
870 | __copy_from_user(current->thread.transact_vr, | ||
871 | &tm_sr->mc_vregs, | ||
872 | sizeof(sr->mc_vregs))) | ||
873 | return 1; | ||
874 | } else if (current->thread.used_vr) { | ||
875 | memset(current->thread.vr, 0, ELF_NVRREG * sizeof(vector128)); | ||
876 | memset(current->thread.transact_vr, 0, | ||
877 | ELF_NVRREG * sizeof(vector128)); | ||
878 | } | ||
879 | |||
880 | /* Always get VRSAVE back */ | ||
881 | if (__get_user(current->thread.vrsave, | ||
882 | (u32 __user *)&sr->mc_vregs[32]) || | ||
883 | __get_user(current->thread.transact_vrsave, | ||
884 | (u32 __user *)&tm_sr->mc_vregs[32])) | ||
885 | return 1; | ||
886 | #endif /* CONFIG_ALTIVEC */ | ||
887 | |||
888 | regs->msr &= ~(MSR_FP | MSR_FE0 | MSR_FE1); | ||
889 | |||
890 | if (copy_fpr_from_user(current, &sr->mc_fregs) || | ||
891 | copy_transact_fpr_from_user(current, &tm_sr->mc_fregs)) | ||
892 | return 1; | ||
893 | |||
894 | #ifdef CONFIG_VSX | ||
895 | regs->msr &= ~MSR_VSX; | ||
896 | if (msr & MSR_VSX) { | ||
897 | /* | ||
898 | * Restore altivec registers from the stack to a local | ||
899 | * buffer, then write this out to the thread_struct | ||
900 | */ | ||
901 | if (copy_vsx_from_user(current, &sr->mc_vsregs) || | ||
902 | copy_transact_vsx_from_user(current, &tm_sr->mc_vsregs)) | ||
903 | return 1; | ||
904 | } else if (current->thread.used_vsr) | ||
905 | for (i = 0; i < 32 ; i++) { | ||
906 | current->thread.fpr[i][TS_VSRLOWOFFSET] = 0; | ||
907 | current->thread.transact_fpr[i][TS_VSRLOWOFFSET] = 0; | ||
908 | } | ||
909 | #endif /* CONFIG_VSX */ | ||
910 | |||
911 | #ifdef CONFIG_SPE | ||
912 | /* SPE regs are not checkpointed with TM, so this section is | ||
913 | * simply the same as in restore_user_regs(). | ||
914 | */ | ||
915 | regs->msr &= ~MSR_SPE; | ||
916 | if (msr & MSR_SPE) { | ||
917 | if (__copy_from_user(current->thread.evr, &sr->mc_vregs, | ||
918 | ELF_NEVRREG * sizeof(u32))) | ||
919 | return 1; | ||
920 | } else if (current->thread.used_spe) | ||
921 | memset(current->thread.evr, 0, ELF_NEVRREG * sizeof(u32)); | ||
922 | |||
923 | /* Always get SPEFSCR back */ | ||
924 | if (__get_user(current->thread.spefscr, (u32 __user *)&sr->mc_vregs | ||
925 | + ELF_NEVRREG)) | ||
926 | return 1; | ||
927 | #endif /* CONFIG_SPE */ | ||
928 | |||
929 | /* Now, recheckpoint. This loads up all of the checkpointed (older) | ||
930 | * registers, including FP and V[S]Rs. After recheckpointing, the | ||
931 | * transactional versions should be loaded. | ||
932 | */ | ||
933 | tm_enable(); | ||
934 | /* This loads the checkpointed FP/VEC state, if used */ | ||
935 | tm_recheckpoint(¤t->thread, msr); | ||
936 | /* The task has moved into TM state S, so ensure MSR reflects this */ | ||
937 | regs->msr = (regs->msr & ~MSR_TS_MASK) | MSR_TS_S; | ||
938 | |||
939 | /* This loads the speculative FP/VEC state, if used */ | ||
940 | if (msr & MSR_FP) { | ||
941 | do_load_up_transact_fpu(¤t->thread); | ||
942 | regs->msr |= (MSR_FP | current->thread.fpexc_mode); | ||
943 | } | ||
944 | if (msr & MSR_VEC) { | ||
945 | do_load_up_transact_altivec(¤t->thread); | ||
946 | regs->msr |= MSR_VEC; | ||
947 | } | ||
948 | |||
949 | return 0; | ||
950 | } | ||
951 | #endif | ||
952 | |||
591 | #ifdef CONFIG_PPC64 | 953 | #ifdef CONFIG_PPC64 |
592 | long compat_sys_rt_sigaction(int sig, const struct sigaction32 __user *act, | 954 | long compat_sys_rt_sigaction(int sig, const struct sigaction32 __user *act, |
593 | struct sigaction32 __user *oact, size_t sigsetsize) | 955 | struct sigaction32 __user *oact, size_t sigsetsize) |
@@ -827,6 +1189,8 @@ int handle_rt_signal32(unsigned long sig, struct k_sigaction *ka, | |||
827 | struct mcontext __user *frame; | 1189 | struct mcontext __user *frame; |
828 | void __user *addr; | 1190 | void __user *addr; |
829 | unsigned long newsp = 0; | 1191 | unsigned long newsp = 0; |
1192 | int sigret; | ||
1193 | unsigned long tramp; | ||
830 | 1194 | ||
831 | /* Set up Signal Frame */ | 1195 | /* Set up Signal Frame */ |
832 | /* Put a Real Time Context onto stack */ | 1196 | /* Put a Real Time Context onto stack */ |
@@ -838,7 +1202,6 @@ int handle_rt_signal32(unsigned long sig, struct k_sigaction *ka, | |||
838 | /* Put the siginfo & fill in most of the ucontext */ | 1202 | /* Put the siginfo & fill in most of the ucontext */ |
839 | if (copy_siginfo_to_user(&rt_sf->info, info) | 1203 | if (copy_siginfo_to_user(&rt_sf->info, info) |
840 | || __put_user(0, &rt_sf->uc.uc_flags) | 1204 | || __put_user(0, &rt_sf->uc.uc_flags) |
841 | || __put_user(0, &rt_sf->uc.uc_link) | ||
842 | || __put_user(current->sas_ss_sp, &rt_sf->uc.uc_stack.ss_sp) | 1205 | || __put_user(current->sas_ss_sp, &rt_sf->uc.uc_stack.ss_sp) |
843 | || __put_user(sas_ss_flags(regs->gpr[1]), | 1206 | || __put_user(sas_ss_flags(regs->gpr[1]), |
844 | &rt_sf->uc.uc_stack.ss_flags) | 1207 | &rt_sf->uc.uc_stack.ss_flags) |
@@ -852,14 +1215,37 @@ int handle_rt_signal32(unsigned long sig, struct k_sigaction *ka, | |||
852 | frame = &rt_sf->uc.uc_mcontext; | 1215 | frame = &rt_sf->uc.uc_mcontext; |
853 | addr = frame; | 1216 | addr = frame; |
854 | if (vdso32_rt_sigtramp && current->mm->context.vdso_base) { | 1217 | if (vdso32_rt_sigtramp && current->mm->context.vdso_base) { |
855 | if (save_user_regs(regs, frame, 0, 1)) | 1218 | sigret = 0; |
856 | goto badframe; | 1219 | tramp = current->mm->context.vdso_base + vdso32_rt_sigtramp; |
857 | regs->link = current->mm->context.vdso_base + vdso32_rt_sigtramp; | ||
858 | } else { | 1220 | } else { |
859 | if (save_user_regs(regs, frame, __NR_rt_sigreturn, 1)) | 1221 | sigret = __NR_rt_sigreturn; |
1222 | tramp = (unsigned long) frame->tramp; | ||
1223 | } | ||
1224 | |||
1225 | #ifdef CONFIG_PPC_TRANSACTIONAL_MEM | ||
1226 | if (MSR_TM_ACTIVE(regs->msr)) { | ||
1227 | if (save_tm_user_regs(regs, &rt_sf->uc.uc_mcontext, | ||
1228 | &rt_sf->uc_transact.uc_mcontext, sigret)) | ||
860 | goto badframe; | 1229 | goto badframe; |
861 | regs->link = (unsigned long) frame->tramp; | ||
862 | } | 1230 | } |
1231 | else | ||
1232 | #endif | ||
1233 | if (save_user_regs(regs, frame, sigret, 1)) | ||
1234 | goto badframe; | ||
1235 | regs->link = tramp; | ||
1236 | |||
1237 | #ifdef CONFIG_PPC_TRANSACTIONAL_MEM | ||
1238 | if (MSR_TM_ACTIVE(regs->msr)) { | ||
1239 | if (__put_user((unsigned long)&rt_sf->uc_transact, | ||
1240 | &rt_sf->uc.uc_link) | ||
1241 | || __put_user(to_user_ptr(&rt_sf->uc_transact.uc_mcontext), | ||
1242 | &rt_sf->uc_transact.uc_regs)) | ||
1243 | goto badframe; | ||
1244 | } | ||
1245 | else | ||
1246 | #endif | ||
1247 | if (__put_user(0, &rt_sf->uc.uc_link)) | ||
1248 | goto badframe; | ||
863 | 1249 | ||
864 | current->thread.fpscr.val = 0; /* turn off all fp exceptions */ | 1250 | current->thread.fpscr.val = 0; /* turn off all fp exceptions */ |
865 | 1251 | ||
@@ -878,6 +1264,13 @@ int handle_rt_signal32(unsigned long sig, struct k_sigaction *ka, | |||
878 | regs->nip = (unsigned long) ka->sa.sa_handler; | 1264 | regs->nip = (unsigned long) ka->sa.sa_handler; |
879 | /* enter the signal handler in big-endian mode */ | 1265 | /* enter the signal handler in big-endian mode */ |
880 | regs->msr &= ~MSR_LE; | 1266 | regs->msr &= ~MSR_LE; |
1267 | #ifdef CONFIG_PPC_TRANSACTIONAL_MEM | ||
1268 | /* Remove TM bits from thread's MSR. The MSR in the sigcontext | ||
1269 | * just indicates to userland that we were doing a transaction, but we | ||
1270 | * don't want to return in transactional state: | ||
1271 | */ | ||
1272 | regs->msr &= ~MSR_TS_MASK; | ||
1273 | #endif | ||
881 | return 1; | 1274 | return 1; |
882 | 1275 | ||
883 | badframe: | 1276 | badframe: |
@@ -925,6 +1318,35 @@ static int do_setcontext(struct ucontext __user *ucp, struct pt_regs *regs, int | |||
925 | return 0; | 1318 | return 0; |
926 | } | 1319 | } |
927 | 1320 | ||
1321 | #ifdef CONFIG_PPC_TRANSACTIONAL_MEM | ||
1322 | static int do_setcontext_tm(struct ucontext __user *ucp, | ||
1323 | struct ucontext __user *tm_ucp, | ||
1324 | struct pt_regs *regs) | ||
1325 | { | ||
1326 | sigset_t set; | ||
1327 | struct mcontext __user *mcp; | ||
1328 | struct mcontext __user *tm_mcp; | ||
1329 | u32 cmcp; | ||
1330 | u32 tm_cmcp; | ||
1331 | |||
1332 | if (get_sigset_t(&set, &ucp->uc_sigmask)) | ||
1333 | return -EFAULT; | ||
1334 | |||
1335 | if (__get_user(cmcp, &ucp->uc_regs) || | ||
1336 | __get_user(tm_cmcp, &tm_ucp->uc_regs)) | ||
1337 | return -EFAULT; | ||
1338 | mcp = (struct mcontext __user *)(u64)cmcp; | ||
1339 | tm_mcp = (struct mcontext __user *)(u64)tm_cmcp; | ||
1340 | /* no need to check access_ok(mcp), since mcp < 4GB */ | ||
1341 | |||
1342 | set_current_blocked(&set); | ||
1343 | if (restore_tm_user_regs(regs, mcp, tm_mcp)) | ||
1344 | return -EFAULT; | ||
1345 | |||
1346 | return 0; | ||
1347 | } | ||
1348 | #endif | ||
1349 | |||
928 | long sys_swapcontext(struct ucontext __user *old_ctx, | 1350 | long sys_swapcontext(struct ucontext __user *old_ctx, |
929 | struct ucontext __user *new_ctx, | 1351 | struct ucontext __user *new_ctx, |
930 | int ctx_size, int r6, int r7, int r8, struct pt_regs *regs) | 1352 | int ctx_size, int r6, int r7, int r8, struct pt_regs *regs) |
@@ -1020,7 +1442,12 @@ long sys_rt_sigreturn(int r3, int r4, int r5, int r6, int r7, int r8, | |||
1020 | struct pt_regs *regs) | 1442 | struct pt_regs *regs) |
1021 | { | 1443 | { |
1022 | struct rt_sigframe __user *rt_sf; | 1444 | struct rt_sigframe __user *rt_sf; |
1023 | 1445 | #ifdef CONFIG_PPC_TRANSACTIONAL_MEM | |
1446 | struct ucontext __user *uc_transact; | ||
1447 | unsigned long msr_hi; | ||
1448 | unsigned long tmp; | ||
1449 | int tm_restore = 0; | ||
1450 | #endif | ||
1024 | /* Always make any pending restarted system calls return -EINTR */ | 1451 | /* Always make any pending restarted system calls return -EINTR */ |
1025 | current_thread_info()->restart_block.fn = do_no_restart_syscall; | 1452 | current_thread_info()->restart_block.fn = do_no_restart_syscall; |
1026 | 1453 | ||
@@ -1028,6 +1455,34 @@ long sys_rt_sigreturn(int r3, int r4, int r5, int r6, int r7, int r8, | |||
1028 | (regs->gpr[1] + __SIGNAL_FRAMESIZE + 16); | 1455 | (regs->gpr[1] + __SIGNAL_FRAMESIZE + 16); |
1029 | if (!access_ok(VERIFY_READ, rt_sf, sizeof(*rt_sf))) | 1456 | if (!access_ok(VERIFY_READ, rt_sf, sizeof(*rt_sf))) |
1030 | goto bad; | 1457 | goto bad; |
1458 | #ifdef CONFIG_PPC_TRANSACTIONAL_MEM | ||
1459 | if (__get_user(tmp, &rt_sf->uc.uc_link)) | ||
1460 | goto bad; | ||
1461 | uc_transact = (struct ucontext __user *)(uintptr_t)tmp; | ||
1462 | if (uc_transact) { | ||
1463 | u32 cmcp; | ||
1464 | struct mcontext __user *mcp; | ||
1465 | |||
1466 | if (__get_user(cmcp, &uc_transact->uc_regs)) | ||
1467 | return -EFAULT; | ||
1468 | mcp = (struct mcontext __user *)(u64)cmcp; | ||
1469 | /* The top 32 bits of the MSR are stashed in the transactional | ||
1470 | * ucontext. */ | ||
1471 | if (__get_user(msr_hi, &mcp->mc_gregs[PT_MSR])) | ||
1472 | goto bad; | ||
1473 | |||
1474 | if (MSR_TM_SUSPENDED(msr_hi<<32)) { | ||
1475 | /* We only recheckpoint on return if we're | ||
1476 | * transaction. | ||
1477 | */ | ||
1478 | tm_restore = 1; | ||
1479 | if (do_setcontext_tm(&rt_sf->uc, uc_transact, regs)) | ||
1480 | goto bad; | ||
1481 | } | ||
1482 | } | ||
1483 | if (!tm_restore) | ||
1484 | /* Fall through, for non-TM restore */ | ||
1485 | #endif | ||
1031 | if (do_setcontext(&rt_sf->uc, regs, 1)) | 1486 | if (do_setcontext(&rt_sf->uc, regs, 1)) |
1032 | goto bad; | 1487 | goto bad; |
1033 | 1488 | ||
@@ -1179,6 +1634,8 @@ int handle_signal32(unsigned long sig, struct k_sigaction *ka, | |||
1179 | struct sigcontext __user *sc; | 1634 | struct sigcontext __user *sc; |
1180 | struct sigframe __user *frame; | 1635 | struct sigframe __user *frame; |
1181 | unsigned long newsp = 0; | 1636 | unsigned long newsp = 0; |
1637 | int sigret; | ||
1638 | unsigned long tramp; | ||
1182 | 1639 | ||
1183 | /* Set up Signal Frame */ | 1640 | /* Set up Signal Frame */ |
1184 | frame = get_sigframe(ka, regs, sizeof(*frame), 1); | 1641 | frame = get_sigframe(ka, regs, sizeof(*frame), 1); |
@@ -1201,14 +1658,25 @@ int handle_signal32(unsigned long sig, struct k_sigaction *ka, | |||
1201 | goto badframe; | 1658 | goto badframe; |
1202 | 1659 | ||
1203 | if (vdso32_sigtramp && current->mm->context.vdso_base) { | 1660 | if (vdso32_sigtramp && current->mm->context.vdso_base) { |
1204 | if (save_user_regs(regs, &frame->mctx, 0, 1)) | 1661 | sigret = 0; |
1205 | goto badframe; | 1662 | tramp = current->mm->context.vdso_base + vdso32_sigtramp; |
1206 | regs->link = current->mm->context.vdso_base + vdso32_sigtramp; | ||
1207 | } else { | 1663 | } else { |
1208 | if (save_user_regs(regs, &frame->mctx, __NR_sigreturn, 1)) | 1664 | sigret = __NR_sigreturn; |
1665 | tramp = (unsigned long) frame->mctx.tramp; | ||
1666 | } | ||
1667 | |||
1668 | #ifdef CONFIG_PPC_TRANSACTIONAL_MEM | ||
1669 | if (MSR_TM_ACTIVE(regs->msr)) { | ||
1670 | if (save_tm_user_regs(regs, &frame->mctx, &frame->mctx_transact, | ||
1671 | sigret)) | ||
1209 | goto badframe; | 1672 | goto badframe; |
1210 | regs->link = (unsigned long) frame->mctx.tramp; | ||
1211 | } | 1673 | } |
1674 | else | ||
1675 | #endif | ||
1676 | if (save_user_regs(regs, &frame->mctx, sigret, 1)) | ||
1677 | goto badframe; | ||
1678 | |||
1679 | regs->link = tramp; | ||
1212 | 1680 | ||
1213 | current->thread.fpscr.val = 0; /* turn off all fp exceptions */ | 1681 | current->thread.fpscr.val = 0; /* turn off all fp exceptions */ |
1214 | 1682 | ||
@@ -1223,7 +1691,13 @@ int handle_signal32(unsigned long sig, struct k_sigaction *ka, | |||
1223 | regs->nip = (unsigned long) ka->sa.sa_handler; | 1691 | regs->nip = (unsigned long) ka->sa.sa_handler; |
1224 | /* enter the signal handler in big-endian mode */ | 1692 | /* enter the signal handler in big-endian mode */ |
1225 | regs->msr &= ~MSR_LE; | 1693 | regs->msr &= ~MSR_LE; |
1226 | 1694 | #ifdef CONFIG_PPC_TRANSACTIONAL_MEM | |
1695 | /* Remove TM bits from thread's MSR. The MSR in the sigcontext | ||
1696 | * just indicates to userland that we were doing a transaction, but we | ||
1697 | * don't want to return in transactional state: | ||
1698 | */ | ||
1699 | regs->msr &= ~MSR_TS_MASK; | ||
1700 | #endif | ||
1227 | return 1; | 1701 | return 1; |
1228 | 1702 | ||
1229 | badframe: | 1703 | badframe: |
diff --git a/arch/powerpc/kernel/signal_64.c b/arch/powerpc/kernel/signal_64.c index 1ca045d44324..7a76ee48a952 100644 --- a/arch/powerpc/kernel/signal_64.c +++ b/arch/powerpc/kernel/signal_64.c | |||
@@ -34,6 +34,7 @@ | |||
34 | #include <asm/syscalls.h> | 34 | #include <asm/syscalls.h> |
35 | #include <asm/vdso.h> | 35 | #include <asm/vdso.h> |
36 | #include <asm/switch_to.h> | 36 | #include <asm/switch_to.h> |
37 | #include <asm/tm.h> | ||
37 | 38 | ||
38 | #include "signal.h" | 39 | #include "signal.h" |
39 | 40 | ||
@@ -56,6 +57,9 @@ | |||
56 | struct rt_sigframe { | 57 | struct rt_sigframe { |
57 | /* sys_rt_sigreturn requires the ucontext be the first field */ | 58 | /* sys_rt_sigreturn requires the ucontext be the first field */ |
58 | struct ucontext uc; | 59 | struct ucontext uc; |
60 | #ifdef CONFIG_PPC_TRANSACTIONAL_MEM | ||
61 | struct ucontext uc_transact; | ||
62 | #endif | ||
59 | unsigned long _unused[2]; | 63 | unsigned long _unused[2]; |
60 | unsigned int tramp[TRAMP_SIZE]; | 64 | unsigned int tramp[TRAMP_SIZE]; |
61 | struct siginfo __user *pinfo; | 65 | struct siginfo __user *pinfo; |
@@ -145,6 +149,145 @@ static long setup_sigcontext(struct sigcontext __user *sc, struct pt_regs *regs, | |||
145 | return err; | 149 | return err; |
146 | } | 150 | } |
147 | 151 | ||
152 | #ifdef CONFIG_PPC_TRANSACTIONAL_MEM | ||
153 | /* | ||
154 | * As above, but Transactional Memory is in use, so deliver sigcontexts | ||
155 | * containing checkpointed and transactional register states. | ||
156 | * | ||
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. | ||
162 | */ | ||
163 | static long setup_tm_sigcontexts(struct sigcontext __user *sc, | ||
164 | struct sigcontext __user *tm_sc, | ||
165 | struct pt_regs *regs, | ||
166 | int signr, sigset_t *set, unsigned long handler) | ||
167 | { | ||
168 | /* When CONFIG_ALTIVEC is set, we _always_ setup v_regs even if the | ||
169 | * process never used altivec yet (MSR_VEC is zero in pt_regs of | ||
170 | * the context). This is very important because we must ensure we | ||
171 | * don't lose the VRSAVE content that may have been set prior to | ||
172 | * the process doing its first vector operation | ||
173 | * Userland shall check AT_HWCAP to know wether it can rely on the | ||
174 | * v_regs pointer or not. | ||
175 | */ | ||
176 | #ifdef CONFIG_ALTIVEC | ||
177 | elf_vrreg_t __user *v_regs = (elf_vrreg_t __user *) | ||
178 | (((unsigned long)sc->vmx_reserve + 15) & ~0xful); | ||
179 | elf_vrreg_t __user *tm_v_regs = (elf_vrreg_t __user *) | ||
180 | (((unsigned long)tm_sc->vmx_reserve + 15) & ~0xful); | ||
181 | #endif | ||
182 | unsigned long msr = regs->msr; | ||
183 | long err = 0; | ||
184 | |||
185 | BUG_ON(!MSR_TM_ACTIVE(regs->msr)); | ||
186 | |||
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(¤t->thread, msr, TM_CAUSE_SIGNAL); | ||
196 | |||
197 | flush_fp_to_thread(current); | ||
198 | |||
199 | #ifdef CONFIG_ALTIVEC | ||
200 | err |= __put_user(v_regs, &sc->v_regs); | ||
201 | err |= __put_user(tm_v_regs, &tm_sc->v_regs); | ||
202 | |||
203 | /* save altivec registers */ | ||
204 | if (current->thread.used_vr) { | ||
205 | flush_altivec_to_thread(current); | ||
206 | /* Copy 33 vec registers (vr0..31 and vscr) to the stack */ | ||
207 | err |= __copy_to_user(v_regs, current->thread.vr, | ||
208 | 33 * sizeof(vector128)); | ||
209 | /* If VEC was enabled there are transactional VRs valid too, | ||
210 | * else they're a copy of the checkpointed VRs. | ||
211 | */ | ||
212 | if (msr & MSR_VEC) | ||
213 | err |= __copy_to_user(tm_v_regs, | ||
214 | current->thread.transact_vr, | ||
215 | 33 * sizeof(vector128)); | ||
216 | else | ||
217 | err |= __copy_to_user(tm_v_regs, | ||
218 | current->thread.vr, | ||
219 | 33 * sizeof(vector128)); | ||
220 | |||
221 | /* set MSR_VEC in the MSR value in the frame to indicate | ||
222 | * that sc->v_reg contains valid data. | ||
223 | */ | ||
224 | msr |= MSR_VEC; | ||
225 | } | ||
226 | /* We always copy to/from vrsave, it's 0 if we don't have or don't | ||
227 | * use altivec. | ||
228 | */ | ||
229 | err |= __put_user(current->thread.vrsave, (u32 __user *)&v_regs[33]); | ||
230 | if (msr & MSR_VEC) | ||
231 | err |= __put_user(current->thread.transact_vrsave, | ||
232 | (u32 __user *)&tm_v_regs[33]); | ||
233 | else | ||
234 | err |= __put_user(current->thread.vrsave, | ||
235 | (u32 __user *)&tm_v_regs[33]); | ||
236 | |||
237 | #else /* CONFIG_ALTIVEC */ | ||
238 | err |= __put_user(0, &sc->v_regs); | ||
239 | err |= __put_user(0, &tm_sc->v_regs); | ||
240 | #endif /* CONFIG_ALTIVEC */ | ||
241 | |||
242 | /* copy fpr regs and fpscr */ | ||
243 | err |= copy_fpr_to_user(&sc->fp_regs, current); | ||
244 | if (msr & MSR_FP) | ||
245 | err |= copy_transact_fpr_to_user(&tm_sc->fp_regs, current); | ||
246 | else | ||
247 | err |= copy_fpr_to_user(&tm_sc->fp_regs, current); | ||
248 | |||
249 | #ifdef CONFIG_VSX | ||
250 | /* | ||
251 | * Copy VSX low doubleword to local buffer for formatting, | ||
252 | * then out to userspace. Update v_regs to point after the | ||
253 | * VMX data. | ||
254 | */ | ||
255 | if (current->thread.used_vsr) { | ||
256 | __giveup_vsx(current); | ||
257 | v_regs += ELF_NVRREG; | ||
258 | tm_v_regs += ELF_NVRREG; | ||
259 | |||
260 | err |= copy_vsx_to_user(v_regs, current); | ||
261 | |||
262 | if (msr & MSR_VSX) | ||
263 | err |= copy_transact_vsx_to_user(tm_v_regs, current); | ||
264 | else | ||
265 | err |= copy_vsx_to_user(tm_v_regs, current); | ||
266 | |||
267 | /* set MSR_VSX in the MSR value in the frame to | ||
268 | * indicate that sc->vs_reg) contains valid data. | ||
269 | */ | ||
270 | msr |= MSR_VSX; | ||
271 | } | ||
272 | #endif /* CONFIG_VSX */ | ||
273 | |||
274 | err |= __put_user(&sc->gp_regs, &sc->regs); | ||
275 | err |= __put_user(&tm_sc->gp_regs, &tm_sc->regs); | ||
276 | WARN_ON(!FULL_REGS(regs)); | ||
277 | err |= __copy_to_user(&tm_sc->gp_regs, regs, GP_REGS_SIZE); | ||
278 | err |= __copy_to_user(&sc->gp_regs, | ||
279 | ¤t->thread.ckpt_regs, GP_REGS_SIZE); | ||
280 | err |= __put_user(msr, &tm_sc->gp_regs[PT_MSR]); | ||
281 | err |= __put_user(msr, &sc->gp_regs[PT_MSR]); | ||
282 | err |= __put_user(signr, &sc->signal); | ||
283 | err |= __put_user(handler, &sc->handler); | ||
284 | if (set != NULL) | ||
285 | err |= __put_user(set->sig[0], &sc->oldmask); | ||
286 | |||
287 | return err; | ||
288 | } | ||
289 | #endif | ||
290 | |||
148 | /* | 291 | /* |
149 | * Restore the sigcontext from the signal frame. | 292 | * Restore the sigcontext from the signal frame. |
150 | */ | 293 | */ |
@@ -241,6 +384,153 @@ static long restore_sigcontext(struct pt_regs *regs, sigset_t *set, int sig, | |||
241 | return err; | 384 | return err; |
242 | } | 385 | } |
243 | 386 | ||
387 | #ifdef CONFIG_PPC_TRANSACTIONAL_MEM | ||
388 | /* | ||
389 | * Restore the two sigcontexts from the frame of a transactional processes. | ||
390 | */ | ||
391 | |||
392 | static long restore_tm_sigcontexts(struct pt_regs *regs, | ||
393 | struct sigcontext __user *sc, | ||
394 | struct sigcontext __user *tm_sc) | ||
395 | { | ||
396 | #ifdef CONFIG_ALTIVEC | ||
397 | elf_vrreg_t __user *v_regs, *tm_v_regs; | ||
398 | #endif | ||
399 | unsigned long err = 0; | ||
400 | unsigned long msr; | ||
401 | #ifdef CONFIG_VSX | ||
402 | int i; | ||
403 | #endif | ||
404 | /* copy the GPRs */ | ||
405 | err |= __copy_from_user(regs->gpr, tm_sc->gp_regs, sizeof(regs->gpr)); | ||
406 | err |= __copy_from_user(¤t->thread.ckpt_regs, sc->gp_regs, | ||
407 | sizeof(regs->gpr)); | ||
408 | |||
409 | /* | ||
410 | * TFHAR is restored from the checkpointed 'wound-back' ucontext's NIP. | ||
411 | * TEXASR was set by the signal delivery reclaim, as was TFIAR. | ||
412 | * Users doing anything abhorrent like thread-switching w/ signals for | ||
413 | * TM-Suspended code will have to back TEXASR/TFIAR up themselves. | ||
414 | * For the case of getting a signal and simply returning from it, | ||
415 | * we don't need to re-copy them here. | ||
416 | */ | ||
417 | err |= __get_user(regs->nip, &tm_sc->gp_regs[PT_NIP]); | ||
418 | err |= __get_user(current->thread.tm_tfhar, &sc->gp_regs[PT_NIP]); | ||
419 | |||
420 | /* get MSR separately, transfer the LE bit if doing signal return */ | ||
421 | err |= __get_user(msr, &sc->gp_regs[PT_MSR]); | ||
422 | regs->msr = (regs->msr & ~MSR_LE) | (msr & MSR_LE); | ||
423 | |||
424 | /* The following non-GPR non-FPR non-VR state is also checkpointed: */ | ||
425 | err |= __get_user(regs->ctr, &tm_sc->gp_regs[PT_CTR]); | ||
426 | err |= __get_user(regs->link, &tm_sc->gp_regs[PT_LNK]); | ||
427 | err |= __get_user(regs->xer, &tm_sc->gp_regs[PT_XER]); | ||
428 | err |= __get_user(regs->ccr, &tm_sc->gp_regs[PT_CCR]); | ||
429 | err |= __get_user(current->thread.ckpt_regs.ctr, | ||
430 | &sc->gp_regs[PT_CTR]); | ||
431 | err |= __get_user(current->thread.ckpt_regs.link, | ||
432 | &sc->gp_regs[PT_LNK]); | ||
433 | err |= __get_user(current->thread.ckpt_regs.xer, | ||
434 | &sc->gp_regs[PT_XER]); | ||
435 | err |= __get_user(current->thread.ckpt_regs.ccr, | ||
436 | &sc->gp_regs[PT_CCR]); | ||
437 | |||
438 | /* These regs are not checkpointed; they can go in 'regs'. */ | ||
439 | err |= __get_user(regs->trap, &sc->gp_regs[PT_TRAP]); | ||
440 | err |= __get_user(regs->dar, &sc->gp_regs[PT_DAR]); | ||
441 | err |= __get_user(regs->dsisr, &sc->gp_regs[PT_DSISR]); | ||
442 | err |= __get_user(regs->result, &sc->gp_regs[PT_RESULT]); | ||
443 | |||
444 | /* | ||
445 | * Do this before updating the thread state in | ||
446 | * current->thread.fpr/vr. That way, if we get preempted | ||
447 | * and another task grabs the FPU/Altivec, it won't be | ||
448 | * tempted to save the current CPU state into the thread_struct | ||
449 | * and corrupt what we are writing there. | ||
450 | */ | ||
451 | discard_lazy_cpu_state(); | ||
452 | |||
453 | /* | ||
454 | * Force reload of FP/VEC. | ||
455 | * This has to be done before copying stuff into current->thread.fpr/vr | ||
456 | * for the reasons explained in the previous comment. | ||
457 | */ | ||
458 | regs->msr &= ~(MSR_FP | MSR_FE0 | MSR_FE1 | MSR_VEC | MSR_VSX); | ||
459 | |||
460 | #ifdef CONFIG_ALTIVEC | ||
461 | err |= __get_user(v_regs, &sc->v_regs); | ||
462 | err |= __get_user(tm_v_regs, &tm_sc->v_regs); | ||
463 | if (err) | ||
464 | return err; | ||
465 | if (v_regs && !access_ok(VERIFY_READ, v_regs, 34 * sizeof(vector128))) | ||
466 | return -EFAULT; | ||
467 | if (tm_v_regs && !access_ok(VERIFY_READ, | ||
468 | tm_v_regs, 34 * sizeof(vector128))) | ||
469 | return -EFAULT; | ||
470 | /* Copy 33 vec registers (vr0..31 and vscr) from the stack */ | ||
471 | if (v_regs != 0 && tm_v_regs != 0 && (msr & MSR_VEC) != 0) { | ||
472 | err |= __copy_from_user(current->thread.vr, v_regs, | ||
473 | 33 * sizeof(vector128)); | ||
474 | err |= __copy_from_user(current->thread.transact_vr, tm_v_regs, | ||
475 | 33 * sizeof(vector128)); | ||
476 | } | ||
477 | else if (current->thread.used_vr) { | ||
478 | memset(current->thread.vr, 0, 33 * sizeof(vector128)); | ||
479 | memset(current->thread.transact_vr, 0, 33 * sizeof(vector128)); | ||
480 | } | ||
481 | /* Always get VRSAVE back */ | ||
482 | if (v_regs != 0 && tm_v_regs != 0) { | ||
483 | err |= __get_user(current->thread.vrsave, | ||
484 | (u32 __user *)&v_regs[33]); | ||
485 | err |= __get_user(current->thread.transact_vrsave, | ||
486 | (u32 __user *)&tm_v_regs[33]); | ||
487 | } | ||
488 | else { | ||
489 | current->thread.vrsave = 0; | ||
490 | current->thread.transact_vrsave = 0; | ||
491 | } | ||
492 | #endif /* CONFIG_ALTIVEC */ | ||
493 | /* restore floating point */ | ||
494 | err |= copy_fpr_from_user(current, &sc->fp_regs); | ||
495 | err |= copy_transact_fpr_from_user(current, &tm_sc->fp_regs); | ||
496 | #ifdef CONFIG_VSX | ||
497 | /* | ||
498 | * Get additional VSX data. Update v_regs to point after the | ||
499 | * VMX data. Copy VSX low doubleword from userspace to local | ||
500 | * buffer for formatting, then into the taskstruct. | ||
501 | */ | ||
502 | if (v_regs && ((msr & MSR_VSX) != 0)) { | ||
503 | v_regs += ELF_NVRREG; | ||
504 | tm_v_regs += ELF_NVRREG; | ||
505 | err |= copy_vsx_from_user(current, v_regs); | ||
506 | err |= copy_transact_vsx_from_user(current, tm_v_regs); | ||
507 | } else { | ||
508 | for (i = 0; i < 32 ; i++) { | ||
509 | current->thread.fpr[i][TS_VSRLOWOFFSET] = 0; | ||
510 | current->thread.transact_fpr[i][TS_VSRLOWOFFSET] = 0; | ||
511 | } | ||
512 | } | ||
513 | #endif | ||
514 | tm_enable(); | ||
515 | /* This loads the checkpointed FP/VEC state, if used */ | ||
516 | tm_recheckpoint(¤t->thread, msr); | ||
517 | /* The task has moved into TM state S, so ensure MSR reflects this: */ | ||
518 | regs->msr = (regs->msr & ~MSR_TS_MASK) | __MASK(33); | ||
519 | |||
520 | /* This loads the speculative FP/VEC state, if used */ | ||
521 | if (msr & MSR_FP) { | ||
522 | do_load_up_transact_fpu(¤t->thread); | ||
523 | regs->msr |= (MSR_FP | current->thread.fpexc_mode); | ||
524 | } | ||
525 | if (msr & MSR_VEC) { | ||
526 | do_load_up_transact_altivec(¤t->thread); | ||
527 | regs->msr |= MSR_VEC; | ||
528 | } | ||
529 | |||
530 | return err; | ||
531 | } | ||
532 | #endif | ||
533 | |||
244 | /* | 534 | /* |
245 | * Setup the trampoline code on the stack | 535 | * Setup the trampoline code on the stack |
246 | */ | 536 | */ |
@@ -355,6 +645,9 @@ int sys_rt_sigreturn(unsigned long r3, unsigned long r4, unsigned long r5, | |||
355 | { | 645 | { |
356 | struct ucontext __user *uc = (struct ucontext __user *)regs->gpr[1]; | 646 | struct ucontext __user *uc = (struct ucontext __user *)regs->gpr[1]; |
357 | sigset_t set; | 647 | sigset_t set; |
648 | #ifdef CONFIG_PPC_TRANSACTIONAL_MEM | ||
649 | unsigned long msr; | ||
650 | #endif | ||
358 | 651 | ||
359 | /* Always make any pending restarted system calls return -EINTR */ | 652 | /* Always make any pending restarted system calls return -EINTR */ |
360 | current_thread_info()->restart_block.fn = do_no_restart_syscall; | 653 | current_thread_info()->restart_block.fn = do_no_restart_syscall; |
@@ -365,6 +658,21 @@ int sys_rt_sigreturn(unsigned long r3, unsigned long r4, unsigned long r5, | |||
365 | if (__copy_from_user(&set, &uc->uc_sigmask, sizeof(set))) | 658 | if (__copy_from_user(&set, &uc->uc_sigmask, sizeof(set))) |
366 | goto badframe; | 659 | goto badframe; |
367 | set_current_blocked(&set); | 660 | set_current_blocked(&set); |
661 | #ifdef CONFIG_PPC_TRANSACTIONAL_MEM | ||
662 | if (__get_user(msr, &uc->uc_mcontext.gp_regs[PT_MSR])) | ||
663 | goto badframe; | ||
664 | if (MSR_TM_SUSPENDED(msr)) { | ||
665 | /* We recheckpoint on return. */ | ||
666 | struct ucontext __user *uc_transact; | ||
667 | if (__get_user(uc_transact, &uc->uc_link)) | ||
668 | goto badframe; | ||
669 | if (restore_tm_sigcontexts(regs, &uc->uc_mcontext, | ||
670 | &uc_transact->uc_mcontext)) | ||
671 | goto badframe; | ||
672 | } | ||
673 | else | ||
674 | /* Fall through, for non-TM restore */ | ||
675 | #endif | ||
368 | if (restore_sigcontext(regs, NULL, 1, &uc->uc_mcontext)) | 676 | if (restore_sigcontext(regs, NULL, 1, &uc->uc_mcontext)) |
369 | goto badframe; | 677 | goto badframe; |
370 | 678 | ||
@@ -415,19 +723,42 @@ int handle_rt_signal64(int signr, struct k_sigaction *ka, siginfo_t *info, | |||
415 | 723 | ||
416 | /* Create the ucontext. */ | 724 | /* Create the ucontext. */ |
417 | err |= __put_user(0, &frame->uc.uc_flags); | 725 | err |= __put_user(0, &frame->uc.uc_flags); |
418 | err |= __put_user(0, &frame->uc.uc_link); | ||
419 | err |= __put_user(current->sas_ss_sp, &frame->uc.uc_stack.ss_sp); | 726 | err |= __put_user(current->sas_ss_sp, &frame->uc.uc_stack.ss_sp); |
420 | err |= __put_user(sas_ss_flags(regs->gpr[1]), | 727 | err |= __put_user(sas_ss_flags(regs->gpr[1]), |
421 | &frame->uc.uc_stack.ss_flags); | 728 | &frame->uc.uc_stack.ss_flags); |
422 | err |= __put_user(current->sas_ss_size, &frame->uc.uc_stack.ss_size); | 729 | err |= __put_user(current->sas_ss_size, &frame->uc.uc_stack.ss_size); |
423 | err |= setup_sigcontext(&frame->uc.uc_mcontext, regs, signr, NULL, | 730 | #ifdef CONFIG_PPC_TRANSACTIONAL_MEM |
424 | (unsigned long)ka->sa.sa_handler, 1); | 731 | if (MSR_TM_ACTIVE(regs->msr)) { |
732 | /* The ucontext_t passed to userland points to the second | ||
733 | * ucontext_t (for transactional state) with its uc_link ptr. | ||
734 | */ | ||
735 | err |= __put_user(&frame->uc_transact, &frame->uc.uc_link); | ||
736 | err |= setup_tm_sigcontexts(&frame->uc.uc_mcontext, | ||
737 | &frame->uc_transact.uc_mcontext, | ||
738 | regs, signr, | ||
739 | NULL, | ||
740 | (unsigned long)ka->sa.sa_handler); | ||
741 | } else | ||
742 | #endif | ||
743 | { | ||
744 | err |= __put_user(0, &frame->uc.uc_link); | ||
745 | err |= setup_sigcontext(&frame->uc.uc_mcontext, regs, signr, | ||
746 | NULL, (unsigned long)ka->sa.sa_handler, | ||
747 | 1); | ||
748 | } | ||
425 | err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set)); | 749 | err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set)); |
426 | if (err) | 750 | if (err) |
427 | goto badframe; | 751 | goto badframe; |
428 | 752 | ||
429 | /* Make sure signal handler doesn't get spurious FP exceptions */ | 753 | /* Make sure signal handler doesn't get spurious FP exceptions */ |
430 | current->thread.fpscr.val = 0; | 754 | current->thread.fpscr.val = 0; |
755 | #ifdef CONFIG_PPC_TRANSACTIONAL_MEM | ||
756 | /* Remove TM bits from thread's MSR. The MSR in the sigcontext | ||
757 | * just indicates to userland that we were doing a transaction, but we | ||
758 | * don't want to return in transactional state: | ||
759 | */ | ||
760 | regs->msr &= ~MSR_TS_MASK; | ||
761 | #endif | ||
431 | 762 | ||
432 | /* Set up to return from userspace. */ | 763 | /* Set up to return from userspace. */ |
433 | if (vdso64_rt_sigtramp && current->mm->context.vdso_base) { | 764 | if (vdso64_rt_sigtramp && current->mm->context.vdso_base) { |
diff --git a/arch/powerpc/kernel/tm.S b/arch/powerpc/kernel/tm.S new file mode 100644 index 000000000000..84dbace657ce --- /dev/null +++ b/arch/powerpc/kernel/tm.S | |||
@@ -0,0 +1,388 @@ | |||
1 | /* | ||
2 | * Transactional memory support routines to reclaim and recheckpoint | ||
3 | * transactional process state. | ||
4 | * | ||
5 | * Copyright 2012 Matt Evans & Michael Neuling, IBM Corporation. | ||
6 | */ | ||
7 | |||
8 | #include <asm/asm-offsets.h> | ||
9 | #include <asm/ppc_asm.h> | ||
10 | #include <asm/ppc-opcode.h> | ||
11 | #include <asm/ptrace.h> | ||
12 | #include <asm/reg.h> | ||
13 | |||
14 | #ifdef CONFIG_VSX | ||
15 | /* See fpu.S, this is very similar but to save/restore checkpointed FPRs/VSRs */ | ||
16 | #define __SAVE_32FPRS_VSRS_TRANSACT(n,c,base) \ | ||
17 | BEGIN_FTR_SECTION \ | ||
18 | b 2f; \ | ||
19 | END_FTR_SECTION_IFSET(CPU_FTR_VSX); \ | ||
20 | SAVE_32FPRS_TRANSACT(n,base); \ | ||
21 | b 3f; \ | ||
22 | 2: SAVE_32VSRS_TRANSACT(n,c,base); \ | ||
23 | 3: | ||
24 | /* ...and this is just plain borrowed from there. */ | ||
25 | #define __REST_32FPRS_VSRS(n,c,base) \ | ||
26 | BEGIN_FTR_SECTION \ | ||
27 | b 2f; \ | ||
28 | END_FTR_SECTION_IFSET(CPU_FTR_VSX); \ | ||
29 | REST_32FPRS(n,base); \ | ||
30 | b 3f; \ | ||
31 | 2: REST_32VSRS(n,c,base); \ | ||
32 | 3: | ||
33 | #else | ||
34 | #define __SAVE_32FPRS_VSRS_TRANSACT(n,c,base) SAVE_32FPRS_TRANSACT(n, base) | ||
35 | #define __REST_32FPRS_VSRS(n,c,base) REST_32FPRS(n, base) | ||
36 | #endif | ||
37 | #define SAVE_32FPRS_VSRS_TRANSACT(n,c,base) \ | ||
38 | __SAVE_32FPRS_VSRS_TRANSACT(n,__REG_##c,__REG_##base) | ||
39 | #define REST_32FPRS_VSRS(n,c,base) \ | ||
40 | __REST_32FPRS_VSRS(n,__REG_##c,__REG_##base) | ||
41 | |||
42 | /* Stack frame offsets for local variables. */ | ||
43 | #define TM_FRAME_L0 TM_FRAME_SIZE-16 | ||
44 | #define TM_FRAME_L1 TM_FRAME_SIZE-8 | ||
45 | #define STACK_PARAM(x) (48+((x)*8)) | ||
46 | |||
47 | |||
48 | /* In order to access the TM SPRs, TM must be enabled. So, do so: */ | ||
49 | _GLOBAL(tm_enable) | ||
50 | mfmsr r4 | ||
51 | li r3, MSR_TM >> 32 | ||
52 | sldi r3, r3, 32 | ||
53 | and. r0, r4, r3 | ||
54 | bne 1f | ||
55 | or r4, r4, r3 | ||
56 | mtmsrd r4 | ||
57 | 1: blr | ||
58 | |||
59 | _GLOBAL(tm_save_sprs) | ||
60 | mfspr r0, SPRN_TFHAR | ||
61 | std r0, THREAD_TM_TFHAR(r3) | ||
62 | mfspr r0, SPRN_TEXASR | ||
63 | std r0, THREAD_TM_TEXASR(r3) | ||
64 | mfspr r0, SPRN_TFIAR | ||
65 | std r0, THREAD_TM_TFIAR(r3) | ||
66 | blr | ||
67 | |||
68 | _GLOBAL(tm_restore_sprs) | ||
69 | ld r0, THREAD_TM_TFHAR(r3) | ||
70 | mtspr SPRN_TFHAR, r0 | ||
71 | ld r0, THREAD_TM_TEXASR(r3) | ||
72 | mtspr SPRN_TEXASR, r0 | ||
73 | ld r0, THREAD_TM_TFIAR(r3) | ||
74 | mtspr SPRN_TFIAR, r0 | ||
75 | blr | ||
76 | |||
77 | /* Passed an 8-bit failure cause as first argument. */ | ||
78 | _GLOBAL(tm_abort) | ||
79 | TABORT(R3) | ||
80 | blr | ||
81 | |||
82 | |||
83 | /* void tm_reclaim(struct thread_struct *thread, | ||
84 | * unsigned long orig_msr, | ||
85 | * uint8_t cause) | ||
86 | * | ||
87 | * - Performs a full reclaim. This destroys outstanding | ||
88 | * transactions and updates thread->regs.tm_ckpt_* with the | ||
89 | * original checkpointed state. Note that thread->regs is | ||
90 | * unchanged. | ||
91 | * - FP regs are written back to thread->transact_fpr before | ||
92 | * reclaiming. These are the transactional (current) versions. | ||
93 | * | ||
94 | * Purpose is to both abort transactions of, and preserve the state of, | ||
95 | * a transactions at a context switch. We preserve/restore both sets of process | ||
96 | * state to restore them when the thread's scheduled again. We continue in | ||
97 | * userland as though nothing happened, but when the transaction is resumed | ||
98 | * they will abort back to the checkpointed state we save out here. | ||
99 | * | ||
100 | * Call with IRQs off, stacks get all out of sync for some periods in here! | ||
101 | */ | ||
102 | _GLOBAL(tm_reclaim) | ||
103 | mfcr r6 | ||
104 | mflr r0 | ||
105 | std r6, 8(r1) | ||
106 | std r0, 16(r1) | ||
107 | std r2, 40(r1) | ||
108 | stdu r1, -TM_FRAME_SIZE(r1) | ||
109 | |||
110 | /* We've a struct pt_regs at [r1+STACK_FRAME_OVERHEAD]. */ | ||
111 | |||
112 | std r3, STACK_PARAM(0)(r1) | ||
113 | SAVE_NVGPRS(r1) | ||
114 | |||
115 | mfmsr r14 | ||
116 | mr r15, r14 | ||
117 | ori r15, r15, MSR_FP | ||
118 | oris r15, r15, MSR_VEC@h | ||
119 | #ifdef CONFIG_VSX | ||
120 | BEGIN_FTR_SECTION | ||
121 | oris r15,r15, MSR_VSX@h | ||
122 | END_FTR_SECTION_IFSET(CPU_FTR_VSX) | ||
123 | #endif | ||
124 | mtmsrd r15 | ||
125 | std r14, TM_FRAME_L0(r1) | ||
126 | |||
127 | /* Stash the stack pointer away for use after reclaim */ | ||
128 | std r1, PACAR1(r13) | ||
129 | |||
130 | /* ******************** FPR/VR/VSRs ************ | ||
131 | * Before reclaiming, capture the current/transactional FPR/VR | ||
132 | * versions /if used/. | ||
133 | * | ||
134 | * (If VSX used, FP and VMX are implied. Or, we don't need to look | ||
135 | * at MSR.VSX as copying FP regs if .FP, vector regs if .VMX covers it.) | ||
136 | * | ||
137 | * We're passed the thread's MSR as parameter 2. | ||
138 | * | ||
139 | * We enabled VEC/FP/VSX in the msr above, so we can execute these | ||
140 | * instructions! | ||
141 | */ | ||
142 | andis. r0, r4, MSR_VEC@h | ||
143 | beq dont_backup_vec | ||
144 | |||
145 | SAVE_32VRS_TRANSACT(0, r6, r3) /* r6 scratch, r3 thread */ | ||
146 | mfvscr vr0 | ||
147 | li r6, THREAD_TRANSACT_VSCR | ||
148 | stvx vr0, r3, r6 | ||
149 | mfspr r0, SPRN_VRSAVE | ||
150 | std r0, THREAD_TRANSACT_VRSAVE(r3) | ||
151 | |||
152 | dont_backup_vec: | ||
153 | andi. r0, r4, MSR_FP | ||
154 | beq dont_backup_fp | ||
155 | |||
156 | SAVE_32FPRS_VSRS_TRANSACT(0, R6, R3) /* r6 scratch, r3 thread */ | ||
157 | |||
158 | mffs fr0 | ||
159 | stfd fr0,THREAD_TRANSACT_FPSCR(r3) | ||
160 | |||
161 | dont_backup_fp: | ||
162 | /* The moment we treclaim, ALL of our GPRs will switch | ||
163 | * to user register state. (FPRs, CCR etc. also!) | ||
164 | * Use an sprg and a tm_scratch in the PACA to shuffle. | ||
165 | */ | ||
166 | TRECLAIM(R5) /* Cause in r5 */ | ||
167 | |||
168 | /* ******************** GPRs ******************** */ | ||
169 | /* Stash the checkpointed r13 away in the scratch SPR and get the real | ||
170 | * paca | ||
171 | */ | ||
172 | SET_SCRATCH0(r13) | ||
173 | GET_PACA(r13) | ||
174 | |||
175 | /* Stash the checkpointed r1 away in paca tm_scratch and get the real | ||
176 | * stack pointer back | ||
177 | */ | ||
178 | std r1, PACATMSCRATCH(r13) | ||
179 | ld r1, PACAR1(r13) | ||
180 | |||
181 | /* Now get some more GPRS free */ | ||
182 | std r7, GPR7(r1) /* Temporary stash */ | ||
183 | std r12, GPR12(r1) /* '' '' '' */ | ||
184 | ld r12, STACK_PARAM(0)(r1) /* Param 0, thread_struct * */ | ||
185 | |||
186 | addi r7, r12, PT_CKPT_REGS /* Thread's ckpt_regs */ | ||
187 | |||
188 | /* Make r7 look like an exception frame so that we | ||
189 | * can use the neat GPRx(n) macros. r7 is NOT a pt_regs ptr! | ||
190 | */ | ||
191 | subi r7, r7, STACK_FRAME_OVERHEAD | ||
192 | |||
193 | /* Sync the userland GPRs 2-12, 14-31 to thread->regs: */ | ||
194 | SAVE_GPR(0, r7) /* user r0 */ | ||
195 | SAVE_GPR(2, r7) /* user r2 */ | ||
196 | SAVE_4GPRS(3, r7) /* user r3-r6 */ | ||
197 | SAVE_4GPRS(8, r7) /* user r8-r11 */ | ||
198 | ld r3, PACATMSCRATCH(r13) /* user r1 */ | ||
199 | ld r4, GPR7(r1) /* user r7 */ | ||
200 | ld r5, GPR12(r1) /* user r12 */ | ||
201 | GET_SCRATCH0(6) /* user r13 */ | ||
202 | std r3, GPR1(r7) | ||
203 | std r4, GPR7(r7) | ||
204 | std r5, GPR12(r7) | ||
205 | std r6, GPR13(r7) | ||
206 | |||
207 | SAVE_NVGPRS(r7) /* user r14-r31 */ | ||
208 | |||
209 | /* ******************** NIP ******************** */ | ||
210 | mfspr r3, SPRN_TFHAR | ||
211 | std r3, _NIP(r7) /* Returns to failhandler */ | ||
212 | /* The checkpointed NIP is ignored when rescheduling/rechkpting, | ||
213 | * but is used in signal return to 'wind back' to the abort handler. | ||
214 | */ | ||
215 | |||
216 | /* ******************** CR,LR,CCR,MSR ********** */ | ||
217 | mfctr r3 | ||
218 | mflr r4 | ||
219 | mfcr r5 | ||
220 | mfxer r6 | ||
221 | |||
222 | std r3, _CTR(r7) | ||
223 | std r4, _LINK(r7) | ||
224 | std r5, _CCR(r7) | ||
225 | std r6, _XER(r7) | ||
226 | |||
227 | /* MSR and flags: We don't change CRs, and we don't need to alter | ||
228 | * MSR. | ||
229 | */ | ||
230 | |||
231 | /* TM regs, incl TEXASR -- these live in thread_struct. Note they've | ||
232 | * been updated by the treclaim, to explain to userland the failure | ||
233 | * cause (aborted). | ||
234 | */ | ||
235 | mfspr r0, SPRN_TEXASR | ||
236 | mfspr r3, SPRN_TFHAR | ||
237 | mfspr r4, SPRN_TFIAR | ||
238 | std r0, THREAD_TM_TEXASR(r12) | ||
239 | std r3, THREAD_TM_TFHAR(r12) | ||
240 | std r4, THREAD_TM_TFIAR(r12) | ||
241 | |||
242 | /* AMR and PPR are checkpointed too, but are unsupported by Linux. */ | ||
243 | |||
244 | /* Restore original MSR/IRQ state & clear TM mode */ | ||
245 | ld r14, TM_FRAME_L0(r1) /* Orig MSR */ | ||
246 | li r15, 0 | ||
247 | rldimi r14, r15, MSR_TS_LG, (63-MSR_TS_LG)-1 | ||
248 | mtmsrd r14 | ||
249 | |||
250 | REST_NVGPRS(r1) | ||
251 | |||
252 | addi r1, r1, TM_FRAME_SIZE | ||
253 | ld r4, 8(r1) | ||
254 | ld r0, 16(r1) | ||
255 | mtcr r4 | ||
256 | mtlr r0 | ||
257 | ld r2, 40(r1) | ||
258 | blr | ||
259 | |||
260 | |||
261 | /* void tm_recheckpoint(struct thread_struct *thread, | ||
262 | * unsigned long orig_msr) | ||
263 | * - Restore the checkpointed register state saved by tm_reclaim | ||
264 | * when we switch_to a process. | ||
265 | * | ||
266 | * Call with IRQs off, stacks get all out of sync for | ||
267 | * some periods in here! | ||
268 | */ | ||
269 | _GLOBAL(tm_recheckpoint) | ||
270 | mfcr r5 | ||
271 | mflr r0 | ||
272 | std r5, 8(r1) | ||
273 | std r0, 16(r1) | ||
274 | std r2, 40(r1) | ||
275 | stdu r1, -TM_FRAME_SIZE(r1) | ||
276 | |||
277 | /* We've a struct pt_regs at [r1+STACK_FRAME_OVERHEAD]. | ||
278 | * This is used for backing up the NVGPRs: | ||
279 | */ | ||
280 | SAVE_NVGPRS(r1) | ||
281 | |||
282 | std r1, PACAR1(r13) | ||
283 | |||
284 | /* Load complete register state from ts_ckpt* registers */ | ||
285 | |||
286 | addi r7, r3, PT_CKPT_REGS /* Thread's ckpt_regs */ | ||
287 | |||
288 | /* Make r7 look like an exception frame so that we | ||
289 | * can use the neat GPRx(n) macros. r7 is now NOT a pt_regs ptr! | ||
290 | */ | ||
291 | subi r7, r7, STACK_FRAME_OVERHEAD | ||
292 | |||
293 | SET_SCRATCH0(r1) | ||
294 | |||
295 | mfmsr r6 | ||
296 | /* R4 = original MSR to indicate whether thread used FP/Vector etc. */ | ||
297 | |||
298 | /* Enable FP/vec in MSR if necessary! */ | ||
299 | lis r5, MSR_VEC@h | ||
300 | ori r5, r5, MSR_FP | ||
301 | and. r5, r4, r5 | ||
302 | beq restore_gprs /* if neither, skip both */ | ||
303 | |||
304 | #ifdef CONFIG_VSX | ||
305 | BEGIN_FTR_SECTION | ||
306 | oris r5, r5, MSR_VSX@h | ||
307 | END_FTR_SECTION_IFSET(CPU_FTR_VSX) | ||
308 | #endif | ||
309 | or r5, r6, r5 /* Set MSR.FP+.VSX/.VEC */ | ||
310 | mtmsr r5 | ||
311 | |||
312 | /* FP and VEC registers: These are recheckpointed from thread.fpr[] | ||
313 | * and thread.vr[] respectively. The thread.transact_fpr[] version | ||
314 | * is more modern, and will be loaded subsequently by any FPUnavailable | ||
315 | * trap. | ||
316 | */ | ||
317 | andis. r0, r4, MSR_VEC@h | ||
318 | beq dont_restore_vec | ||
319 | |||
320 | li r5, THREAD_VSCR | ||
321 | lvx vr0, r3, r5 | ||
322 | mtvscr vr0 | ||
323 | REST_32VRS(0, r5, r3) /* r5 scratch, r3 THREAD ptr */ | ||
324 | ld r5, THREAD_VRSAVE(r3) | ||
325 | mtspr SPRN_VRSAVE, r5 | ||
326 | |||
327 | dont_restore_vec: | ||
328 | andi. r0, r4, MSR_FP | ||
329 | beq dont_restore_fp | ||
330 | |||
331 | lfd fr0, THREAD_FPSCR(r3) | ||
332 | MTFSF_L(fr0) | ||
333 | REST_32FPRS_VSRS(0, R4, R3) | ||
334 | |||
335 | dont_restore_fp: | ||
336 | mtmsr r6 /* FP/Vec off again! */ | ||
337 | |||
338 | restore_gprs: | ||
339 | /* ******************** CR,LR,CCR,MSR ********** */ | ||
340 | ld r3, _CTR(r7) | ||
341 | ld r4, _LINK(r7) | ||
342 | ld r5, _CCR(r7) | ||
343 | ld r6, _XER(r7) | ||
344 | |||
345 | mtctr r3 | ||
346 | mtlr r4 | ||
347 | mtcr r5 | ||
348 | mtxer r6 | ||
349 | |||
350 | /* MSR and flags: We don't change CRs, and we don't need to alter | ||
351 | * MSR. | ||
352 | */ | ||
353 | |||
354 | REST_4GPRS(0, r7) /* GPR0-3 */ | ||
355 | REST_GPR(4, r7) /* GPR4-6 */ | ||
356 | REST_GPR(5, r7) | ||
357 | REST_GPR(6, r7) | ||
358 | REST_4GPRS(8, r7) /* GPR8-11 */ | ||
359 | REST_2GPRS(12, r7) /* GPR12-13 */ | ||
360 | |||
361 | REST_NVGPRS(r7) /* GPR14-31 */ | ||
362 | |||
363 | ld r7, GPR7(r7) /* GPR7 */ | ||
364 | |||
365 | /* Commit register state as checkpointed state: */ | ||
366 | TRECHKPT | ||
367 | |||
368 | /* Our transactional state has now changed. | ||
369 | * | ||
370 | * Now just get out of here. Transactional (current) state will be | ||
371 | * updated once restore is called on the return path in the _switch-ed | ||
372 | * -to process. | ||
373 | */ | ||
374 | |||
375 | GET_PACA(r13) | ||
376 | GET_SCRATCH0(r1) | ||
377 | |||
378 | REST_NVGPRS(r1) | ||
379 | |||
380 | addi r1, r1, TM_FRAME_SIZE | ||
381 | ld r4, 8(r1) | ||
382 | ld r0, 16(r1) | ||
383 | mtcr r4 | ||
384 | mtlr r0 | ||
385 | ld r2, 40(r1) | ||
386 | blr | ||
387 | |||
388 | /* ****************************************************************** */ | ||
diff --git a/arch/powerpc/kernel/traps.c b/arch/powerpc/kernel/traps.c index a008cf5c0fce..f9b751b29558 100644 --- a/arch/powerpc/kernel/traps.c +++ b/arch/powerpc/kernel/traps.c | |||
@@ -58,6 +58,7 @@ | |||
58 | #include <asm/rio.h> | 58 | #include <asm/rio.h> |
59 | #include <asm/fadump.h> | 59 | #include <asm/fadump.h> |
60 | #include <asm/switch_to.h> | 60 | #include <asm/switch_to.h> |
61 | #include <asm/tm.h> | ||
61 | #include <asm/debug.h> | 62 | #include <asm/debug.h> |
62 | 63 | ||
63 | #if defined(CONFIG_DEBUGGER) || defined(CONFIG_KEXEC) | 64 | #if defined(CONFIG_DEBUGGER) || defined(CONFIG_KEXEC) |
@@ -78,6 +79,13 @@ EXPORT_SYMBOL(__debugger_break_match); | |||
78 | EXPORT_SYMBOL(__debugger_fault_handler); | 79 | EXPORT_SYMBOL(__debugger_fault_handler); |
79 | #endif | 80 | #endif |
80 | 81 | ||
82 | /* Transactional Memory trap debug */ | ||
83 | #ifdef TM_DEBUG_SW | ||
84 | #define TM_DEBUG(x...) printk(KERN_INFO x) | ||
85 | #else | ||
86 | #define TM_DEBUG(x...) do { } while(0) | ||
87 | #endif | ||
88 | |||
81 | /* | 89 | /* |
82 | * Trap & Exception support | 90 | * Trap & Exception support |
83 | */ | 91 | */ |
@@ -350,6 +358,7 @@ static inline int check_io_access(struct pt_regs *regs) | |||
350 | exception is in the MSR. */ | 358 | exception is in the MSR. */ |
351 | #define get_reason(regs) ((regs)->msr) | 359 | #define get_reason(regs) ((regs)->msr) |
352 | #define get_mc_reason(regs) ((regs)->msr) | 360 | #define get_mc_reason(regs) ((regs)->msr) |
361 | #define REASON_TM 0x200000 | ||
353 | #define REASON_FP 0x100000 | 362 | #define REASON_FP 0x100000 |
354 | #define REASON_ILLEGAL 0x80000 | 363 | #define REASON_ILLEGAL 0x80000 |
355 | #define REASON_PRIVILEGED 0x40000 | 364 | #define REASON_PRIVILEGED 0x40000 |
@@ -1020,6 +1029,38 @@ void __kprobes program_check_exception(struct pt_regs *regs) | |||
1020 | _exception(SIGTRAP, regs, TRAP_BRKPT, regs->nip); | 1029 | _exception(SIGTRAP, regs, TRAP_BRKPT, regs->nip); |
1021 | return; | 1030 | return; |
1022 | } | 1031 | } |
1032 | #ifdef CONFIG_PPC_TRANSACTIONAL_MEM | ||
1033 | if (reason & REASON_TM) { | ||
1034 | /* This is a TM "Bad Thing Exception" program check. | ||
1035 | * This occurs when: | ||
1036 | * - An rfid/hrfid/mtmsrd attempts to cause an illegal | ||
1037 | * transition in TM states. | ||
1038 | * - A trechkpt is attempted when transactional. | ||
1039 | * - A treclaim is attempted when non transactional. | ||
1040 | * - A tend is illegally attempted. | ||
1041 | * - writing a TM SPR when transactional. | ||
1042 | */ | ||
1043 | if (!user_mode(regs) && | ||
1044 | report_bug(regs->nip, regs) == BUG_TRAP_TYPE_WARN) { | ||
1045 | regs->nip += 4; | ||
1046 | return; | ||
1047 | } | ||
1048 | /* If usermode caused this, it's done something illegal and | ||
1049 | * gets a SIGILL slap on the wrist. We call it an illegal | ||
1050 | * operand to distinguish from the instruction just being bad | ||
1051 | * (e.g. executing a 'tend' on a CPU without TM!); it's an | ||
1052 | * illegal /placement/ of a valid instruction. | ||
1053 | */ | ||
1054 | if (user_mode(regs)) { | ||
1055 | _exception(SIGILL, regs, ILL_ILLOPN, regs->nip); | ||
1056 | return; | ||
1057 | } else { | ||
1058 | printk(KERN_EMERG "Unexpected TM Bad Thing exception " | ||
1059 | "at %lx (msr 0x%x)\n", regs->nip, reason); | ||
1060 | die("Unrecoverable exception", regs, SIGABRT); | ||
1061 | } | ||
1062 | } | ||
1063 | #endif | ||
1023 | 1064 | ||
1024 | /* We restore the interrupt state now */ | 1065 | /* We restore the interrupt state now */ |
1025 | if (!arch_irq_disabled_regs(regs)) | 1066 | if (!arch_irq_disabled_regs(regs)) |
@@ -1160,6 +1201,109 @@ void vsx_unavailable_exception(struct pt_regs *regs) | |||
1160 | die("Unrecoverable VSX Unavailable Exception", regs, SIGABRT); | 1201 | die("Unrecoverable VSX Unavailable Exception", regs, SIGABRT); |
1161 | } | 1202 | } |
1162 | 1203 | ||
1204 | void tm_unavailable_exception(struct pt_regs *regs) | ||
1205 | { | ||
1206 | /* We restore the interrupt state now */ | ||
1207 | if (!arch_irq_disabled_regs(regs)) | ||
1208 | local_irq_enable(); | ||
1209 | |||
1210 | /* Currently we never expect a TMU exception. Catch | ||
1211 | * this and kill the process! | ||
1212 | */ | ||
1213 | printk(KERN_EMERG "Unexpected TM unavailable exception at %lx " | ||
1214 | "(msr %lx)\n", | ||
1215 | regs->nip, regs->msr); | ||
1216 | |||
1217 | if (user_mode(regs)) { | ||
1218 | _exception(SIGILL, regs, ILL_ILLOPC, regs->nip); | ||
1219 | return; | ||
1220 | } | ||
1221 | |||
1222 | die("Unexpected TM unavailable exception", regs, SIGABRT); | ||
1223 | } | ||
1224 | |||
1225 | #ifdef CONFIG_PPC_TRANSACTIONAL_MEM | ||
1226 | |||
1227 | extern void do_load_up_fpu(struct pt_regs *regs); | ||
1228 | |||
1229 | void fp_unavailable_tm(struct pt_regs *regs) | ||
1230 | { | ||
1231 | /* Note: This does not handle any kind of FP laziness. */ | ||
1232 | |||
1233 | TM_DEBUG("FP Unavailable trap whilst transactional at 0x%lx, MSR=%lx\n", | ||
1234 | regs->nip, regs->msr); | ||
1235 | tm_enable(); | ||
1236 | |||
1237 | /* We can only have got here if the task started using FP after | ||
1238 | * beginning the transaction. So, the transactional regs are just a | ||
1239 | * copy of the checkpointed ones. But, we still need to recheckpoint | ||
1240 | * as we're enabling FP for the process; it will return, abort the | ||
1241 | * transaction, and probably retry but now with FP enabled. So the | ||
1242 | * checkpointed FP registers need to be loaded. | ||
1243 | */ | ||
1244 | tm_reclaim(¤t->thread, current->thread.regs->msr, | ||
1245 | TM_CAUSE_FAC_UNAV); | ||
1246 | /* Reclaim didn't save out any FPRs to transact_fprs. */ | ||
1247 | |||
1248 | /* Enable FP for the task: */ | ||
1249 | regs->msr |= (MSR_FP | current->thread.fpexc_mode); | ||
1250 | |||
1251 | /* This loads and recheckpoints the FP registers from | ||
1252 | * thread.fpr[]. They will remain in registers after the | ||
1253 | * checkpoint so we don't need to reload them after. | ||
1254 | */ | ||
1255 | tm_recheckpoint(¤t->thread, regs->msr); | ||
1256 | } | ||
1257 | |||
1258 | #ifdef CONFIG_ALTIVEC | ||
1259 | extern void do_load_up_altivec(struct pt_regs *regs); | ||
1260 | |||
1261 | void altivec_unavailable_tm(struct pt_regs *regs) | ||
1262 | { | ||
1263 | /* See the comments in fp_unavailable_tm(). This function operates | ||
1264 | * the same way. | ||
1265 | */ | ||
1266 | |||
1267 | TM_DEBUG("Vector Unavailable trap whilst transactional at 0x%lx," | ||
1268 | "MSR=%lx\n", | ||
1269 | regs->nip, regs->msr); | ||
1270 | tm_enable(); | ||
1271 | tm_reclaim(¤t->thread, current->thread.regs->msr, | ||
1272 | TM_CAUSE_FAC_UNAV); | ||
1273 | regs->msr |= MSR_VEC; | ||
1274 | tm_recheckpoint(¤t->thread, regs->msr); | ||
1275 | current->thread.used_vr = 1; | ||
1276 | } | ||
1277 | #endif | ||
1278 | |||
1279 | #ifdef CONFIG_VSX | ||
1280 | void vsx_unavailable_tm(struct pt_regs *regs) | ||
1281 | { | ||
1282 | /* See the comments in fp_unavailable_tm(). This works similarly, | ||
1283 | * though we're loading both FP and VEC registers in here. | ||
1284 | * | ||
1285 | * If FP isn't in use, load FP regs. If VEC isn't in use, load VEC | ||
1286 | * regs. Either way, set MSR_VSX. | ||
1287 | */ | ||
1288 | |||
1289 | TM_DEBUG("VSX Unavailable trap whilst transactional at 0x%lx," | ||
1290 | "MSR=%lx\n", | ||
1291 | regs->nip, regs->msr); | ||
1292 | |||
1293 | tm_enable(); | ||
1294 | /* This reclaims FP and/or VR regs if they're already enabled */ | ||
1295 | tm_reclaim(¤t->thread, current->thread.regs->msr, | ||
1296 | TM_CAUSE_FAC_UNAV); | ||
1297 | |||
1298 | regs->msr |= MSR_VEC | MSR_FP | current->thread.fpexc_mode | | ||
1299 | MSR_VSX; | ||
1300 | /* This loads & recheckpoints FP and VRs. */ | ||
1301 | tm_recheckpoint(¤t->thread, regs->msr); | ||
1302 | current->thread.used_vsr = 1; | ||
1303 | } | ||
1304 | #endif | ||
1305 | #endif /* CONFIG_PPC_TRANSACTIONAL_MEM */ | ||
1306 | |||
1163 | void performance_monitor_exception(struct pt_regs *regs) | 1307 | void performance_monitor_exception(struct pt_regs *regs) |
1164 | { | 1308 | { |
1165 | __get_cpu_var(irq_stat).pmu_irqs++; | 1309 | __get_cpu_var(irq_stat).pmu_irqs++; |
diff --git a/arch/powerpc/kernel/vector.S b/arch/powerpc/kernel/vector.S index e830289d2e48..9e20999aaef2 100644 --- a/arch/powerpc/kernel/vector.S +++ b/arch/powerpc/kernel/vector.S | |||
@@ -7,6 +7,57 @@ | |||
7 | #include <asm/page.h> | 7 | #include <asm/page.h> |
8 | #include <asm/ptrace.h> | 8 | #include <asm/ptrace.h> |
9 | 9 | ||
10 | #ifdef CONFIG_PPC_TRANSACTIONAL_MEM | ||
11 | /* | ||
12 | * Wrapper to call load_up_altivec from C. | ||
13 | * void do_load_up_altivec(struct pt_regs *regs); | ||
14 | */ | ||
15 | _GLOBAL(do_load_up_altivec) | ||
16 | mflr r0 | ||
17 | std r0, 16(r1) | ||
18 | stdu r1, -112(r1) | ||
19 | |||
20 | subi r6, r3, STACK_FRAME_OVERHEAD | ||
21 | /* load_up_altivec expects r12=MSR, r13=PACA, and returns | ||
22 | * with r12 = new MSR. | ||
23 | */ | ||
24 | ld r12,_MSR(r6) | ||
25 | GET_PACA(r13) | ||
26 | bl load_up_altivec | ||
27 | std r12,_MSR(r6) | ||
28 | |||
29 | ld r0, 112+16(r1) | ||
30 | addi r1, r1, 112 | ||
31 | mtlr r0 | ||
32 | blr | ||
33 | |||
34 | /* void do_load_up_transact_altivec(struct thread_struct *thread) | ||
35 | * | ||
36 | * This is similar to load_up_altivec but for the transactional version of the | ||
37 | * vector regs. It doesn't mess with the task MSR or valid flags. | ||
38 | * Furthermore, VEC laziness is not supported with TM currently. | ||
39 | */ | ||
40 | _GLOBAL(do_load_up_transact_altivec) | ||
41 | mfmsr r6 | ||
42 | oris r5,r6,MSR_VEC@h | ||
43 | MTMSRD(r5) | ||
44 | isync | ||
45 | |||
46 | li r4,1 | ||
47 | stw r4,THREAD_USED_VR(r3) | ||
48 | |||
49 | li r10,THREAD_TRANSACT_VSCR | ||
50 | lvx vr0,r10,r3 | ||
51 | mtvscr vr0 | ||
52 | REST_32VRS_TRANSACT(0,r4,r3) | ||
53 | |||
54 | /* Disable VEC again. */ | ||
55 | MTMSRD(r6) | ||
56 | isync | ||
57 | |||
58 | blr | ||
59 | #endif | ||
60 | |||
10 | /* | 61 | /* |
11 | * load_up_altivec(unused, unused, tsk) | 62 | * load_up_altivec(unused, unused, tsk) |
12 | * Disable VMX for the task which had it previously, | 63 | * Disable VMX for the task which had it previously, |
diff --git a/arch/powerpc/kvm/book3s_hv_rmhandlers.S b/arch/powerpc/kvm/book3s_hv_rmhandlers.S index 10b6c358dd77..e33d11f1b977 100644 --- a/arch/powerpc/kvm/book3s_hv_rmhandlers.S +++ b/arch/powerpc/kvm/book3s_hv_rmhandlers.S | |||
@@ -539,6 +539,11 @@ fast_guest_return: | |||
539 | 539 | ||
540 | /* Enter guest */ | 540 | /* Enter guest */ |
541 | 541 | ||
542 | BEGIN_FTR_SECTION | ||
543 | ld r5, VCPU_CFAR(r4) | ||
544 | mtspr SPRN_CFAR, r5 | ||
545 | END_FTR_SECTION_IFSET(CPU_FTR_CFAR) | ||
546 | |||
542 | ld r5, VCPU_LR(r4) | 547 | ld r5, VCPU_LR(r4) |
543 | lwz r6, VCPU_CR(r4) | 548 | lwz r6, VCPU_CR(r4) |
544 | mtlr r5 | 549 | mtlr r5 |
@@ -604,6 +609,10 @@ kvmppc_interrupt: | |||
604 | lwz r4, HSTATE_SCRATCH1(r13) | 609 | lwz r4, HSTATE_SCRATCH1(r13) |
605 | std r3, VCPU_GPR(R12)(r9) | 610 | std r3, VCPU_GPR(R12)(r9) |
606 | stw r4, VCPU_CR(r9) | 611 | stw r4, VCPU_CR(r9) |
612 | BEGIN_FTR_SECTION | ||
613 | ld r3, HSTATE_CFAR(r13) | ||
614 | std r3, VCPU_CFAR(r9) | ||
615 | END_FTR_SECTION_IFSET(CPU_FTR_CFAR) | ||
607 | 616 | ||
608 | /* Restore R1/R2 so we can handle faults */ | 617 | /* Restore R1/R2 so we can handle faults */ |
609 | ld r1, HSTATE_HOST_R1(r13) | 618 | ld r1, HSTATE_HOST_R1(r13) |
diff --git a/arch/powerpc/kvm/book3s_pr.c b/arch/powerpc/kvm/book3s_pr.c index 67e4708388a0..6702442ca818 100644 --- a/arch/powerpc/kvm/book3s_pr.c +++ b/arch/powerpc/kvm/book3s_pr.c | |||
@@ -35,6 +35,7 @@ | |||
35 | #include <asm/mmu_context.h> | 35 | #include <asm/mmu_context.h> |
36 | #include <asm/switch_to.h> | 36 | #include <asm/switch_to.h> |
37 | #include <asm/firmware.h> | 37 | #include <asm/firmware.h> |
38 | #include <asm/hvcall.h> | ||
38 | #include <linux/gfp.h> | 39 | #include <linux/gfp.h> |
39 | #include <linux/sched.h> | 40 | #include <linux/sched.h> |
40 | #include <linux/vmalloc.h> | 41 | #include <linux/vmalloc.h> |
diff --git a/arch/powerpc/mm/hash_utils_64.c b/arch/powerpc/mm/hash_utils_64.c index 3a292be2e079..1b6e1271719f 100644 --- a/arch/powerpc/mm/hash_utils_64.c +++ b/arch/powerpc/mm/hash_utils_64.c | |||
@@ -55,6 +55,7 @@ | |||
55 | #include <asm/code-patching.h> | 55 | #include <asm/code-patching.h> |
56 | #include <asm/fadump.h> | 56 | #include <asm/fadump.h> |
57 | #include <asm/firmware.h> | 57 | #include <asm/firmware.h> |
58 | #include <asm/tm.h> | ||
58 | 59 | ||
59 | #ifdef DEBUG | 60 | #ifdef DEBUG |
60 | #define DBG(fmt...) udbg_printf(fmt) | 61 | #define DBG(fmt...) udbg_printf(fmt) |
@@ -1171,6 +1172,21 @@ void flush_hash_page(unsigned long vpn, real_pte_t pte, int psize, int ssize, | |||
1171 | DBG_LOW(" sub %ld: hash=%lx, hidx=%lx\n", index, slot, hidx); | 1172 | DBG_LOW(" sub %ld: hash=%lx, hidx=%lx\n", index, slot, hidx); |
1172 | ppc_md.hpte_invalidate(slot, vpn, psize, ssize, local); | 1173 | ppc_md.hpte_invalidate(slot, vpn, psize, ssize, local); |
1173 | } pte_iterate_hashed_end(); | 1174 | } pte_iterate_hashed_end(); |
1175 | |||
1176 | #ifdef CONFIG_PPC_TRANSACTIONAL_MEM | ||
1177 | /* Transactions are not aborted by tlbiel, only tlbie. | ||
1178 | * Without, syncing a page back to a block device w/ PIO could pick up | ||
1179 | * transactional data (bad!) so we force an abort here. Before the | ||
1180 | * sync the page will be made read-only, which will flush_hash_page. | ||
1181 | * BIG ISSUE here: if the kernel uses a page from userspace without | ||
1182 | * unmapping it first, it may see the speculated version. | ||
1183 | */ | ||
1184 | if (local && cpu_has_feature(CPU_FTR_TM) && | ||
1185 | MSR_TM_ACTIVE(current->thread.regs->msr)) { | ||
1186 | tm_enable(); | ||
1187 | tm_abort(TM_CAUSE_TLBI); | ||
1188 | } | ||
1189 | #endif | ||
1174 | } | 1190 | } |
1175 | 1191 | ||
1176 | void flush_hash_range(unsigned long number, int local) | 1192 | void flush_hash_range(unsigned long number, int local) |
diff --git a/arch/powerpc/platforms/ps3/htab.c b/arch/powerpc/platforms/ps3/htab.c index d00d7b0a3bda..6cc58201db8c 100644 --- a/arch/powerpc/platforms/ps3/htab.c +++ b/arch/powerpc/platforms/ps3/htab.c | |||
@@ -27,6 +27,7 @@ | |||
27 | #include <asm/lv1call.h> | 27 | #include <asm/lv1call.h> |
28 | #include <asm/ps3fb.h> | 28 | #include <asm/ps3fb.h> |
29 | 29 | ||
30 | #define PS3_VERBOSE_RESULT | ||
30 | #include "platform.h" | 31 | #include "platform.h" |
31 | 32 | ||
32 | /** | 33 | /** |
@@ -75,8 +76,9 @@ static long ps3_hpte_insert(unsigned long hpte_group, unsigned long vpn, | |||
75 | 76 | ||
76 | if (result) { | 77 | if (result) { |
77 | /* all entries bolted !*/ | 78 | /* all entries bolted !*/ |
78 | pr_info("%s:result=%d vpn=%lx pa=%lx ix=%lx v=%llx r=%llx\n", | 79 | pr_info("%s:result=%s vpn=%lx pa=%lx ix=%lx v=%llx r=%llx\n", |
79 | __func__, result, vpn, pa, hpte_group, hpte_v, hpte_r); | 80 | __func__, ps3_result(result), vpn, pa, hpte_group, |
81 | hpte_v, hpte_r); | ||
80 | BUG(); | 82 | BUG(); |
81 | } | 83 | } |
82 | 84 | ||
@@ -125,8 +127,8 @@ static long ps3_hpte_updatepp(unsigned long slot, unsigned long newpp, | |||
125 | &hpte_rs); | 127 | &hpte_rs); |
126 | 128 | ||
127 | if (result) { | 129 | if (result) { |
128 | pr_info("%s: res=%d read vpn=%lx slot=%lx psize=%d\n", | 130 | pr_info("%s: result=%s read vpn=%lx slot=%lx psize=%d\n", |
129 | __func__, result, vpn, slot, psize); | 131 | __func__, ps3_result(result), vpn, slot, psize); |
130 | BUG(); | 132 | BUG(); |
131 | } | 133 | } |
132 | 134 | ||
@@ -170,8 +172,8 @@ static void ps3_hpte_invalidate(unsigned long slot, unsigned long vpn, | |||
170 | result = lv1_write_htab_entry(PS3_LPAR_VAS_ID_CURRENT, slot, 0, 0); | 172 | result = lv1_write_htab_entry(PS3_LPAR_VAS_ID_CURRENT, slot, 0, 0); |
171 | 173 | ||
172 | if (result) { | 174 | if (result) { |
173 | pr_info("%s: res=%d vpn=%lx slot=%lx psize=%d\n", | 175 | pr_info("%s: result=%s vpn=%lx slot=%lx psize=%d\n", |
174 | __func__, result, vpn, slot, psize); | 176 | __func__, ps3_result(result), vpn, slot, psize); |
175 | BUG(); | 177 | BUG(); |
176 | } | 178 | } |
177 | 179 | ||