diff options
Diffstat (limited to 'arch/ppc64/kernel/process.c')
| -rw-r--r-- | arch/ppc64/kernel/process.c | 34 |
1 files changed, 34 insertions, 0 deletions
diff --git a/arch/ppc64/kernel/process.c b/arch/ppc64/kernel/process.c index 7a7e027653ad..887005358eb1 100644 --- a/arch/ppc64/kernel/process.c +++ b/arch/ppc64/kernel/process.c | |||
| @@ -54,6 +54,7 @@ | |||
| 54 | #include <asm/sections.h> | 54 | #include <asm/sections.h> |
| 55 | #include <asm/tlbflush.h> | 55 | #include <asm/tlbflush.h> |
| 56 | #include <asm/time.h> | 56 | #include <asm/time.h> |
| 57 | #include <asm/plpar_wrappers.h> | ||
| 57 | 58 | ||
| 58 | #ifndef CONFIG_SMP | 59 | #ifndef CONFIG_SMP |
| 59 | struct task_struct *last_task_used_math = NULL; | 60 | struct task_struct *last_task_used_math = NULL; |
| @@ -163,7 +164,30 @@ int dump_task_altivec(struct pt_regs *regs, elf_vrregset_t *vrregs) | |||
| 163 | 164 | ||
| 164 | #endif /* CONFIG_ALTIVEC */ | 165 | #endif /* CONFIG_ALTIVEC */ |
| 165 | 166 | ||
| 167 | static void set_dabr_spr(unsigned long val) | ||
| 168 | { | ||
| 169 | mtspr(SPRN_DABR, val); | ||
| 170 | } | ||
| 171 | |||
| 172 | int set_dabr(unsigned long dabr) | ||
| 173 | { | ||
| 174 | int ret = 0; | ||
| 175 | |||
| 176 | if (firmware_has_feature(FW_FEATURE_XDABR)) { | ||
| 177 | /* We want to catch accesses from kernel and userspace */ | ||
| 178 | unsigned long flags = H_DABRX_KERNEL|H_DABRX_USER; | ||
| 179 | ret = plpar_set_xdabr(dabr, flags); | ||
| 180 | } else if (firmware_has_feature(FW_FEATURE_DABR)) { | ||
| 181 | ret = plpar_set_dabr(dabr); | ||
| 182 | } else { | ||
| 183 | set_dabr_spr(dabr); | ||
| 184 | } | ||
| 185 | |||
| 186 | return ret; | ||
| 187 | } | ||
| 188 | |||
| 166 | DEFINE_PER_CPU(struct cpu_usage, cpu_usage_array); | 189 | DEFINE_PER_CPU(struct cpu_usage, cpu_usage_array); |
| 190 | static DEFINE_PER_CPU(unsigned long, current_dabr); | ||
| 167 | 191 | ||
| 168 | struct task_struct *__switch_to(struct task_struct *prev, | 192 | struct task_struct *__switch_to(struct task_struct *prev, |
| 169 | struct task_struct *new) | 193 | struct task_struct *new) |
| @@ -198,6 +222,11 @@ struct task_struct *__switch_to(struct task_struct *prev, | |||
| 198 | new->thread.regs->msr |= MSR_VEC; | 222 | new->thread.regs->msr |= MSR_VEC; |
| 199 | #endif /* CONFIG_ALTIVEC */ | 223 | #endif /* CONFIG_ALTIVEC */ |
| 200 | 224 | ||
| 225 | if (unlikely(__get_cpu_var(current_dabr) != new->thread.dabr)) { | ||
| 226 | set_dabr(new->thread.dabr); | ||
| 227 | __get_cpu_var(current_dabr) = new->thread.dabr; | ||
| 228 | } | ||
| 229 | |||
| 201 | flush_tlb_pending(); | 230 | flush_tlb_pending(); |
| 202 | 231 | ||
| 203 | new_thread = &new->thread; | 232 | new_thread = &new->thread; |
| @@ -334,6 +363,11 @@ void flush_thread(void) | |||
| 334 | last_task_used_altivec = NULL; | 363 | last_task_used_altivec = NULL; |
| 335 | #endif /* CONFIG_ALTIVEC */ | 364 | #endif /* CONFIG_ALTIVEC */ |
| 336 | #endif /* CONFIG_SMP */ | 365 | #endif /* CONFIG_SMP */ |
| 366 | |||
| 367 | if (current->thread.dabr) { | ||
| 368 | current->thread.dabr = 0; | ||
| 369 | set_dabr(0); | ||
| 370 | } | ||
| 337 | } | 371 | } |
| 338 | 372 | ||
| 339 | void | 373 | void |
