cregit-Linux how code gets into the kernel

Release 4.14 arch/powerpc/kernel/process.c

/*
 *  Derived from "arch/i386/kernel/process.c"
 *    Copyright (C) 1995  Linus Torvalds
 *
 *  Updated and modified by Cort Dougan (cort@cs.nmt.edu) and
 *  Paul Mackerras (paulus@cs.anu.edu.au)
 *
 *  PowerPC version
 *    Copyright (C) 1995-1996 Gary Thomas (gdt@linuxppc.org)
 *
 *  This program is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU General Public License
 *  as published by the Free Software Foundation; either version
 *  2 of the License, or (at your option) any later version.
 */

#include <linux/errno.h>
#include <linux/sched.h>
#include <linux/sched/debug.h>
#include <linux/sched/task.h>
#include <linux/sched/task_stack.h>
#include <linux/kernel.h>
#include <linux/mm.h>
#include <linux/smp.h>
#include <linux/stddef.h>
#include <linux/unistd.h>
#include <linux/ptrace.h>
#include <linux/slab.h>
#include <linux/user.h>
#include <linux/elf.h>
#include <linux/prctl.h>
#include <linux/init_task.h>
#include <linux/export.h>
#include <linux/kallsyms.h>
#include <linux/mqueue.h>
#include <linux/hardirq.h>
#include <linux/utsname.h>
#include <linux/ftrace.h>
#include <linux/kernel_stat.h>
#include <linux/personality.h>
#include <linux/random.h>
#include <linux/hw_breakpoint.h>
#include <linux/uaccess.h>
#include <linux/elf-randomize.h>

#include <asm/pgtable.h>
#include <asm/io.h>
#include <asm/processor.h>
#include <asm/mmu.h>
#include <asm/prom.h>
#include <asm/machdep.h>
#include <asm/time.h>
#include <asm/runlatch.h>
#include <asm/syscalls.h>
#include <asm/switch_to.h>
#include <asm/tm.h>
#include <asm/debug.h>
#ifdef CONFIG_PPC64
#include <asm/firmware.h>
#endif
#include <asm/code-patching.h>
#include <asm/exec.h>
#include <asm/livepatch.h>
#include <asm/cpu_has_feature.h>
#include <asm/asm-prototypes.h>

#include <linux/kprobes.h>
#include <linux/kdebug.h>

/* Transactional Memory debug */
#ifdef TM_DEBUG_SW

#define TM_DEBUG(x...) printk(KERN_INFO x)
#else

#define TM_DEBUG(x...) do { } while(0)
#endif

extern unsigned long _get_SP(void);

#ifdef CONFIG_PPC_TRANSACTIONAL_MEM

static void check_if_tm_restore_required(struct task_struct *tsk) { /* * If we are saving the current thread's registers, and the * thread is in a transactional state, set the TIF_RESTORE_TM * bit so that we know to restore the registers before * returning to userspace. */ if (tsk == current && tsk->thread.regs && MSR_TM_ACTIVE(tsk->thread.regs->msr) && !test_thread_flag(TIF_RESTORE_TM)) { tsk->thread.ckpt_regs.msr = tsk->thread.regs->msr; set_thread_flag(TIF_RESTORE_TM); } }

Contributors

PersonTokensPropCommitsCommitProp
Paul Mackerras5992.19%133.33%
Anshuman Khandual34.69%133.33%
Anton Blanchard23.12%133.33%
Total64100.00%3100.00%


static inline bool msr_tm_active(unsigned long msr) { return MSR_TM_ACTIVE(msr); }

Contributors

PersonTokensPropCommitsCommitProp
Cyril Bur17100.00%1100.00%
Total17100.00%1100.00%

#else
static inline bool msr_tm_active(unsigned long msr) { return false; }

Contributors

PersonTokensPropCommitsCommitProp
Cyril Bur14100.00%1100.00%
Total14100.00%1100.00%


static inline void check_if_tm_restore_required(struct task_struct *tsk) { }

Contributors

PersonTokensPropCommitsCommitProp
Paul Mackerras763.64%150.00%
Anton Blanchard436.36%150.00%
Total11100.00%2100.00%

#endif /* CONFIG_PPC_TRANSACTIONAL_MEM */ bool strict_msr_control; EXPORT_SYMBOL(strict_msr_control);
static int __init enable_strict_msr_control(char *str) { strict_msr_control = true; pr_info("Enabling strict facility control\n"); return 0; }

Contributors

PersonTokensPropCommitsCommitProp
Anton Blanchard23100.00%2100.00%
Total23100.00%2100.00%

early_param("ppc_strict_facility_enable", enable_strict_msr_control);
unsigned long msr_check_and_set(unsigned long bits) { unsigned long oldmsr = mfmsr(); unsigned long newmsr; newmsr = oldmsr | bits; #ifdef CONFIG_VSX if (cpu_has_feature(CPU_FTR_VSX) && (bits & MSR_FP)) newmsr |= MSR_VSX; #endif if (oldmsr != newmsr) mtmsr_isync(newmsr); return newmsr; }

Contributors

PersonTokensPropCommitsCommitProp
Anton Blanchard5892.06%266.67%
Cyril Bur57.94%133.33%
Total63100.00%3100.00%


void __msr_check_and_clear(unsigned long bits) { unsigned long oldmsr = mfmsr(); unsigned long newmsr; newmsr = oldmsr & ~bits; #ifdef CONFIG_VSX if (cpu_has_feature(CPU_FTR_VSX) && (bits & MSR_FP)) newmsr &= ~MSR_VSX; #endif if (oldmsr != newmsr) mtmsr_isync(newmsr); }

Contributors

PersonTokensPropCommitsCommitProp
Anton Blanchard61100.00%3100.00%
Total61100.00%3100.00%

EXPORT_SYMBOL(__msr_check_and_clear); #ifdef CONFIG_PPC_FPU
void __giveup_fpu(struct task_struct *tsk) { unsigned long msr; save_fpu(tsk); msr = tsk->thread.regs->msr; msr &= ~MSR_FP; #ifdef CONFIG_VSX if (cpu_has_feature(CPU_FTR_VSX)) msr &= ~MSR_VSX; #endif tsk->thread.regs->msr = msr; }

Contributors

PersonTokensPropCommitsCommitProp
Cyril Bur4472.13%150.00%
Anton Blanchard1727.87%150.00%
Total61100.00%2100.00%


void giveup_fpu(struct task_struct *tsk) { check_if_tm_restore_required(tsk); msr_check_and_set(MSR_FP); __giveup_fpu(tsk); msr_check_and_clear(MSR_FP); }

Contributors

PersonTokensPropCommitsCommitProp
Anton Blanchard30100.00%2100.00%
Total30100.00%2100.00%

EXPORT_SYMBOL(giveup_fpu); /* * Make sure the floating-point register state in the * the thread_struct is up to date for task tsk. */
void flush_fp_to_thread(struct task_struct *tsk) { if (tsk->thread.regs) { /* * We need to disable preemption here because if we didn't, * another process could get scheduled after the regs->msr * test but before we have finished saving the FP registers * to the thread_struct. That process could take over the * FPU, and then when we get scheduled again we would store * bogus values for the remaining FP registers. */ preempt_disable(); if (tsk->thread.regs->msr & MSR_FP) { /* * This should only ever be called for current or * for a stopped child process. Since we save away * the FP register state on context switch, * there is something wrong if a stopped child appears * to still have its FP state in the CPU registers. */ BUG_ON(tsk != current); giveup_fpu(tsk); } preempt_enable(); } }

Contributors

PersonTokensPropCommitsCommitProp
Paul Mackerras5194.44%125.00%
Anton Blanchard23.70%250.00%
Kumar Gala11.85%125.00%
Total54100.00%4100.00%

EXPORT_SYMBOL_GPL(flush_fp_to_thread);
void enable_kernel_fp(void) { unsigned long cpumsr; WARN_ON(preemptible()); cpumsr = msr_check_and_set(MSR_FP); if (current->thread.regs && (current->thread.regs->msr & MSR_FP)) { check_if_tm_restore_required(current); /* * If a thread has already been reclaimed then the * checkpointed registers are on the CPU but have definitely * been saved by the reclaim code. Don't need to and *cannot* * giveup as this would save to the 'live' structure not the * checkpointed structure. */ if(!msr_tm_active(cpumsr) && msr_tm_active(current->thread.regs->msr)) return; __giveup_fpu(current); } }

Contributors

PersonTokensPropCommitsCommitProp
Paul Mackerras3646.75%120.00%
Cyril Bur2735.06%120.00%
Anton Blanchard1418.18%360.00%
Total77100.00%5100.00%

EXPORT_SYMBOL(enable_kernel_fp);
static int restore_fp(struct task_struct *tsk) { if (tsk->thread.load_fp || msr_tm_active(tsk->thread.regs->msr)) { load_fp_state(&current->thread.fp_state); current->thread.load_fp++; return 1; } return 0; }

Contributors

PersonTokensPropCommitsCommitProp
Cyril Bur55100.00%2100.00%
Total55100.00%2100.00%

#else
static int restore_fp(struct task_struct *tsk) { return 0; }

Contributors

PersonTokensPropCommitsCommitProp
Cyril Bur14100.00%1100.00%
Total14100.00%1100.00%

#endif /* CONFIG_PPC_FPU */ #ifdef CONFIG_ALTIVEC #define loadvec(thr) ((thr).load_vec)
static void __giveup_altivec(struct task_struct *tsk) { unsigned long msr; save_altivec(tsk); msr = tsk->thread.regs->msr; msr &= ~MSR_VEC; #ifdef CONFIG_VSX if (cpu_has_feature(CPU_FTR_VSX)) msr &= ~MSR_VSX; #endif tsk->thread.regs->msr = msr; }

Contributors

PersonTokensPropCommitsCommitProp
Cyril Bur4572.58%150.00%
Anton Blanchard1727.42%150.00%
Total62100.00%2100.00%


void giveup_altivec(struct task_struct *tsk) { check_if_tm_restore_required(tsk); msr_check_and_set(MSR_VEC); __giveup_altivec(tsk); msr_check_and_clear(MSR_VEC); }

Contributors

PersonTokensPropCommitsCommitProp
Anton Blanchard30100.00%2100.00%
Total30100.00%2100.00%

EXPORT_SYMBOL(giveup_altivec);
void enable_kernel_altivec(void) { unsigned long cpumsr; WARN_ON(preemptible()); cpumsr = msr_check_and_set(MSR_VEC); if (current->thread.regs && (current->thread.regs->msr & MSR_VEC)) { check_if_tm_restore_required(current); /* * If a thread has already been reclaimed then the * checkpointed registers are on the CPU but have definitely * been saved by the reclaim code. Don't need to and *cannot* * giveup as this would save to the 'live' structure not the * checkpointed structure. */ if(!msr_tm_active(cpumsr) && msr_tm_active(current->thread.regs->msr)) return; __giveup_altivec(current); } }

Contributors

PersonTokensPropCommitsCommitProp
Paul Mackerras3241.56%120.00%
Cyril Bur2735.06%120.00%
Anton Blanchard1823.38%360.00%
Total77100.00%5100.00%

EXPORT_SYMBOL(enable_kernel_altivec); /* * Make sure the VMX/Altivec register state in the * the thread_struct is up to date for task tsk. */
void flush_altivec_to_thread(struct task_struct *tsk) { if (tsk->thread.regs) { preempt_disable(); if (tsk->thread.regs->msr & MSR_VEC) { BUG_ON(tsk != current); giveup_altivec(tsk); } preempt_enable(); } }

Contributors

PersonTokensPropCommitsCommitProp
Paul Mackerras5096.15%133.33%
Anton Blanchard11.92%133.33%
Kumar Gala11.92%133.33%
Total52100.00%3100.00%

EXPORT_SYMBOL_GPL(flush_altivec_to_thread);
static int restore_altivec(struct task_struct *tsk) { if (cpu_has_feature(CPU_FTR_ALTIVEC) && (tsk->thread.load_vec || msr_tm_active(tsk->thread.regs->msr))) { load_vr_state(&tsk->thread.vr_state); tsk->thread.used_vr = 1; tsk->thread.load_vec++; return 1; } return 0; }

Contributors

PersonTokensPropCommitsCommitProp
Cyril Bur4564.29%266.67%
Anton Blanchard2535.71%133.33%
Total70100.00%3100.00%

#else #define loadvec(thr) 0
static inline int restore_altivec(struct task_struct *tsk) { return 0; }

Contributors

PersonTokensPropCommitsCommitProp
Cyril Bur15100.00%1100.00%
Total15100.00%1100.00%

#endif /* CONFIG_ALTIVEC */ #ifdef CONFIG_VSX
static void __giveup_vsx(struct task_struct *tsk) { unsigned long msr = tsk->thread.regs->msr; /* * We should never be ssetting MSR_VSX without also setting * MSR_FP and MSR_VEC */ WARN_ON((msr & MSR_VSX) && !((msr & MSR_FP) && (msr & MSR_VEC))); /* __giveup_fpu will clear MSR_VSX */ if (msr & MSR_FP) __giveup_fpu(tsk); if (msr & MSR_VEC) __giveup_altivec(tsk); }

Contributors

PersonTokensPropCommitsCommitProp
Anton Blanchard3549.30%250.00%
Benjamin Herrenschmidt3447.89%125.00%
Cyril Bur22.82%125.00%
Total71100.00%4100.00%


static void giveup_vsx(struct task_struct *tsk) { check_if_tm_restore_required(tsk); msr_check_and_set(MSR_FP|MSR_VEC|MSR_VSX); __giveup_vsx(tsk); msr_check_and_clear(MSR_FP|MSR_VEC|MSR_VSX); }

Contributors

PersonTokensPropCommitsCommitProp
Cyril Bur2153.85%133.33%
Anton Blanchard1846.15%266.67%
Total39100.00%3100.00%


void enable_kernel_vsx(void) { unsigned long cpumsr; WARN_ON(preemptible()); cpumsr = msr_check_and_set(MSR_FP|MSR_VEC|MSR_VSX); if (current->thread.regs && (current->thread.regs->msr & (MSR_VSX|MSR_VEC|MSR_FP))) { check_if_tm_restore_required(current); /* * If a thread has already been reclaimed then the * checkpointed registers are on the CPU but have definitely * been saved by the reclaim code. Don't need to and *cannot* * giveup as this would save to the 'live' structure not the * checkpointed structure. */ if(!msr_tm_active(cpumsr) && msr_tm_active(current->thread.regs->msr)) return; __giveup_vsx(current); } }

Contributors

PersonTokensPropCommitsCommitProp
Leonidas Da Silva Barbosa3540.23%116.67%
Cyril Bur2731.03%116.67%
Anton Blanchard1921.84%350.00%
Benjamin Herrenschmidt66.90%116.67%
Total87100.00%6100.00%

EXPORT_SYMBOL(enable_kernel_vsx);
void flush_vsx_to_thread(struct task_struct *tsk) { if (tsk->thread.regs) { preempt_disable(); if (tsk->thread.regs->msr & (MSR_VSX|MSR_VEC|MSR_FP)) { BUG_ON(tsk != current); giveup_vsx(tsk); } preempt_enable(); } }

Contributors

PersonTokensPropCommitsCommitProp
Michael Neuling5289.66%150.00%
Benjamin Herrenschmidt610.34%150.00%
Total58100.00%2100.00%

EXPORT_SYMBOL_GPL(flush_vsx_to_thread);
static int restore_vsx(struct task_struct *tsk) { if (cpu_has_feature(CPU_FTR_VSX)) { tsk->thread.used_vsr = 1; return 1; } return 0; }

Contributors

PersonTokensPropCommitsCommitProp
Cyril Bur34100.00%1100.00%
Total34100.00%1100.00%

#else
static inline int restore_vsx(struct task_struct *tsk) { return 0; }

Contributors

PersonTokensPropCommitsCommitProp
Cyril Bur15100.00%1100.00%
Total15100.00%1100.00%

#endif /* CONFIG_VSX */ #ifdef CONFIG_SPE
void giveup_spe(struct task_struct *tsk) { check_if_tm_restore_required(tsk); msr_check_and_set(MSR_SPE); __giveup_spe(tsk); msr_check_and_clear(MSR_SPE); }

Contributors

PersonTokensPropCommitsCommitProp
Anton Blanchard30100.00%2100.00%
Total30100.00%2100.00%

EXPORT_SYMBOL(giveup_spe);
void enable_kernel_spe(void) { WARN_ON(preemptible()); msr_check_and_set(MSR_SPE); if (current->thread.regs && (current->thread.regs->msr & MSR_SPE)) { check_if_tm_restore_required(current); __giveup_spe(current); } }

Contributors

PersonTokensPropCommitsCommitProp
Paul Mackerras3672.00%125.00%
Anton Blanchard1428.00%375.00%
Total50100.00%4100.00%

EXPORT_SYMBOL(enable_kernel_spe);
void flush_spe_to_thread(struct task_struct *tsk) { if (tsk->thread.regs) { preempt_disable(); if (tsk->thread.regs->msr & MSR_SPE) { BUG_ON(tsk != current); tsk->thread.spefscr = mfspr(SPRN_SPEFSCR); giveup_spe(tsk); } preempt_enable(); } }

Contributors

PersonTokensPropCommitsCommitProp
Paul Mackerras5180.95%133.33%
Liu Yu1117.46%133.33%
Kumar Gala11.59%133.33%
Total63100.00%3100.00%

#endif /* CONFIG_SPE */ static unsigned long msr_all_available;
static int __init init_msr_all_available(void) { #ifdef CONFIG_PPC_FPU msr_all_available |= MSR_FP; #endif #ifdef CONFIG_ALTIVEC if (cpu_has_feature(CPU_FTR_ALTIVEC)) msr_all_available |= MSR_VEC; #endif #ifdef CONFIG_VSX if (cpu_has_feature(CPU_FTR_VSX)) msr_all_available |= MSR_VSX; #endif #ifdef CONFIG_SPE if (cpu_has_feature(CPU_FTR_SPE)) msr_all_available |= MSR_SPE; #endif return 0; }

Contributors

PersonTokensPropCommitsCommitProp
Anton Blanchard69100.00%1100.00%
Total69100.00%1100.00%

early_initcall(init_msr_all_available);
void giveup_all(struct task_struct *tsk) { unsigned long usermsr; if (!tsk->thread.regs) return; usermsr = tsk->thread.regs->msr; if ((usermsr & msr_all_available) == 0) return; msr_check_and_set(msr_all_available); check_if_tm_restore_required(tsk); WARN_ON((usermsr & MSR_VSX) && !((usermsr & MSR_FP) && (usermsr & MSR_VEC))); #ifdef CONFIG_PPC_FPU if (usermsr & MSR_FP) __giveup_fpu(tsk); #endif #ifdef CONFIG_ALTIVEC if (usermsr & MSR_VEC) __giveup_altivec(tsk); #endif #ifdef CONFIG_SPE if (usermsr & MSR_SPE) __giveup_spe(tsk); #endif msr_check_and_clear(msr_all_available); }

Contributors

PersonTokensPropCommitsCommitProp
Anton Blanchard10378.03%133.33%
Benjamin Herrenschmidt2418.18%133.33%
Cyril Bur53.79%133.33%
Total132100.00%3100.00%

EXPORT_SYMBOL(giveup_all);
void restore_math(struct pt_regs *regs) { unsigned long msr; if (!msr_tm_active(regs->msr) && !current->thread.load_fp && !loadvec(current->thread)) return; msr = regs->msr; msr_check_and_set(msr_all_available); /* * Only reload if the bit is not set in the user MSR, the bit BEING set * indicates that the registers are hot */ if ((!(msr & MSR_FP)) && restore_fp(current)) msr |= MSR_FP | current->thread.fpexc_mode; if ((!(msr & MSR_VEC)) && restore_altivec(current)) msr |= MSR_VEC; if ((msr & (MSR_FP | MSR_VEC)) == (MSR_FP | MSR_VEC) && restore_vsx(current)) { msr |= MSR_VSX; } msr_check_and_clear(msr_all_available); regs->msr = msr; }

Contributors

PersonTokensPropCommitsCommitProp
Cyril Bur11281.16%266.67%
Anton Blanchard2618.84%133.33%
Total138100.00%3100.00%


void save_all(struct task_struct *tsk) { unsigned long usermsr; if (!tsk->thread.regs) return; usermsr = tsk->thread.regs->msr; if ((usermsr & msr_all_available) == 0) return; msr_check_and_set(msr_all_available); WARN_ON((usermsr & MSR_VSX) && !((usermsr & MSR_FP) && (usermsr & MSR_VEC))); if (usermsr & MSR_FP) save_fpu(tsk); if (usermsr & MSR_VEC) save_altivec(tsk); if (usermsr & MSR_SPE) __giveup_spe(tsk); msr_check_and_clear(msr_all_available); }

Contributors

PersonTokensPropCommitsCommitProp
Anton Blanchard8777.68%125.00%
Benjamin Herrenschmidt1916.96%125.00%
Cyril Bur65.36%250.00%
Total112100.00%4100.00%


void flush_all_to_thread(struct task_struct *tsk) { if (tsk->thread.regs) { preempt_disable(); BUG_ON(tsk != current); save_all(tsk); #ifdef CONFIG_SPE if (tsk->thread.regs->msr & MSR_SPE) tsk->thread.spefscr = mfspr(SPRN_SPEFSCR); #endif preempt_enable(); } }

Contributors

PersonTokensPropCommitsCommitProp
Anton Blanchard6598.48%150.00%
Cyril Bur11.52%150.00%
Total66100.00%2100.00%

EXPORT_SYMBOL(flush_all_to_thread); #ifdef CONFIG_PPC_ADV_DEBUG_REGS
void do_send_trap(struct pt_regs *regs, unsigned long address, unsigned long error_code, int signal_code, int breakpt) { siginfo_t info; current->thread.trap_nr = signal_code; if (notify_die(DIE_DABR_MATCH, "dabr_match", regs, error_code, 11, SIGSEGV) == NOTIFY_STOP) return; /* Deliver the signal to userspace */ info.si_signo = SIGTRAP; info.si_errno = breakpt; /* breakpoint or watchpoint id */ info.si_code = signal_code; info.si_addr = (void __user *)address; force_sig_info(SIGTRAP, &info, current); }

Contributors

PersonTokensPropCommitsCommitProp
Dave Kleikamp8891.67%150.00%
Ananth N. Mavinakayanahalli88.33%150.00%
Total96100.00%2100.00%

#else /* !CONFIG_PPC_ADV_DEBUG_REGS */
void do_break (struct pt_regs *regs, unsigned long address, unsigned long error_code) { siginfo_t info; current->thread.trap_nr = TRAP_HWBKPT; if (notify_die(DIE_DABR_MATCH, "dabr_match", regs, error_code, 11, SIGSEGV) == NOTIFY_STOP) return; if (debugger_break_match(regs)) return; /* Clear the breakpoint */ hw_breakpoint_disable(); /* Deliver the signal to userspace */ info.si_signo = SIGTRAP; info.si_errno = 0; info.si_code = TRAP_HWBKPT; info.si_addr = (void __user *)address; force_sig_info(SIGTRAP, &info, current); }

Contributors

PersonTokensPropCommitsCommitProp
Luis Machado8887.13%133.33%
Ananth N. Mavinakayanahalli87.92%133.33%
Michael Neuling54.95%133.33%
Total101100.00%3100.00%

#endif /* CONFIG_PPC_ADV_DEBUG_REGS */ static DEFINE_PER_CPU(struct arch_hw_breakpoint, current_brk); #ifdef CONFIG_PPC_ADV_DEBUG_REGS /* * Set the debug registers back to their default "safe" values. */
static void set_debug_reg_defaults(struct thread_struct *thread) { thread->debug.iac1 = thread->debug.iac2 = 0; #if CONFIG_PPC_ADV_DEBUG_IACS > 2 thread->debug.iac3 = thread->debug.iac4 = 0; #endif thread->debug.dac1 = thread->debug.dac2 = 0; #if CONFIG_PPC_ADV_DEBUG_DVCS > 0 thread->debug.dvc1 = thread->debug.dvc2 = 0; #endif thread->debug.dbcr0 = 0; #ifdef CONFIG_BOOKE /* * Force User/Supervisor bits to b11 (user-only MSR[PR]=1) */ thread->debug.dbcr1 = DBCR1_IAC1US | DBCR1_IAC2US | DBCR1_IAC3US | DBCR1_IAC4US; /* * Force Data Address Compare User/Supervisor bits to be User-only * (0b11 MSR[PR]=1) and set all other bits in DBCR2 register to be 0. */ thread->debug.dbcr2 = DBCR2_DAC1US | DBCR2_DAC2US; #else thread->debug.dbcr1 = 0; #endif }

Contributors

PersonTokensPropCommitsCommitProp
Dave Kleikamp10681.54%150.00%
Bharat Bhushan2418.46%150.00%
Total130100.00%2100.00%


static void prime_debug_regs(struct debug_reg *debug) { /* * We could have inherited MSR_DE from userspace, since * it doesn't get cleared on exception entry. Make sure * MSR_DE is clear before we enable any debug events. */ mtmsr(mfmsr() & ~MSR_DE); mtspr(SPRN_IAC1, debug->iac1); mtspr(SPRN_IAC2, debug->iac2); #if CONFIG_PPC_ADV_DEBUG_IACS > 2 mtspr(SPRN_IAC3, debug->iac3); mtspr(SPRN_IAC4, debug->iac4); #endif mtspr(SPRN_DAC1, debug->dac1); mtspr(SPRN_DAC2, debug->dac2); #if CONFIG_PPC_ADV_DEBUG_DVCS > 0 mtspr(SPRN_DVC1, debug->dvc1); mtspr(SPRN_DVC2, debug->dvc2); #endif mtspr(SPRN_DBCR0, debug->dbcr0); mtspr(SPRN_DBCR1, debug->dbcr1); #ifdef CONFIG_BOOKE mtspr(SPRN_DBCR2, debug->dbcr2); #endif }

Contributors

PersonTokensPropCommitsCommitProp
Dave Kleikamp10575.54%125.00%
Scott Wood2316.55%250.00%
Bharat Bhushan117.91%125.00%
Total139100.00%4100.00%

/* * Unless neither the old or new thread are making use of the * debug registers, set the debug registers from the values * stored in the new thread. */
void switch_booke_debug_regs(struct debug_reg *new_debug) { if ((current->thread.debug.dbcr0 & DBCR0_IDM) || (new_debug->dbcr0 & DBCR0_IDM)) prime_debug_regs(new_debug); }

Contributors

PersonTokensPropCommitsCommitProp
Dave Kleikamp3183.78%133.33%
Scott Wood410.81%133.33%
Bharat Bhushan25.41%133.33%
Total37100.00%3100.00%

EXPORT_SYMBOL_GPL(switch_booke_debug_regs); #else /* !CONFIG_PPC_ADV_DEBUG_REGS */ #ifndef CONFIG_HAVE_HW_BREAKPOINT
static void set_debug_reg_defaults(struct thread_struct *thread) { thread->hw_brk.address = 0; thread->hw_brk.type = 0; set_breakpoint(&thread->hw_brk); }

Contributors

PersonTokensPropCommitsCommitProp
Dave Kleikamp1954.29%125.00%
Michael Neuling1645.71%375.00%
Total35100.00%4100.00%

#endif /* !CONFIG_HAVE_HW_BREAKPOINT */ #endif /* CONFIG_PPC_ADV_DEBUG_REGS */ #ifdef CONFIG_PPC_ADV_DEBUG_REGS
static inline int __set_dabr(unsigned long dabr, unsigned long dabrx) { mtspr(SPRN_DAC1, dabr); #ifdef CONFIG_PPC_47x isync(); #endif return 0; }

Contributors

PersonTokensPropCommitsCommitProp
Paul Mackerras1133.33%116.67%
Michael Neuling1133.33%233.33%
Dave Kleikamp824.24%116.67%
Michael Ellerman26.06%116.67%
Benjamin Herrenschmidt13.03%116.67%
Total33100.00%6100.00%

#elif defined(CONFIG_PPC_BOOK3S)
static inline int __set_dabr(unsigned long dabr, unsigned long dabrx) { mtspr(SPRN_DABR, dabr); if (cpu_has_feature(CPU_FTR_DABRX)) mtspr(SPRN_DABRX, dabrx); return 0; }

Contributors

PersonTokensPropCommitsCommitProp
Michael Neuling3282.05%360.00%
Luis Machado615.38%120.00%
Benjamin Herrenschmidt12.56%120.00%
Total39100.00%5100.00%

#elif defined(CONFIG_PPC_8xx)
static inline int __set_dabr(unsigned long dabr, unsigned long dabrx) { unsigned long addr = dabr & ~HW_BRK_TYPE_DABR; unsigned long lctrl1 = 0x90000000; /* compare type: equal on E & F */ unsigned long lctrl2 = 0x8e000002; /* watchpoint 1 on cmp E | F */ if ((dabr & HW_BRK_TYPE_RDWR) == HW_BRK_TYPE_READ) lctrl1 |= 0xa0000; else if ((dabr & HW_BRK_TYPE_RDWR) == HW_BRK_TYPE_WRITE) lctrl1 |= 0xf0000; else if ((dabr & HW_BRK_TYPE_RDWR) == 0) lctrl2 = 0; mtspr(