cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

kdb_debugger.c (4567B)


      1/*
      2 * Created by: Jason Wessel <jason.wessel@windriver.com>
      3 *
      4 * Copyright (c) 2009 Wind River Systems, Inc.  All Rights Reserved.
      5 *
      6 * This file is licensed under the terms of the GNU General Public
      7 * License version 2. This program is licensed "as is" without any
      8 * warranty of any kind, whether express or implied.
      9 */
     10
     11#include <linux/kgdb.h>
     12#include <linux/kdb.h>
     13#include <linux/kdebug.h>
     14#include <linux/export.h>
     15#include <linux/hardirq.h>
     16#include "kdb_private.h"
     17#include "../debug_core.h"
     18
     19/*
     20 * KDB interface to KGDB internals
     21 */
     22get_char_func kdb_poll_funcs[] = {
     23	dbg_io_get_char,
     24	NULL,
     25	NULL,
     26	NULL,
     27	NULL,
     28	NULL,
     29};
     30EXPORT_SYMBOL_GPL(kdb_poll_funcs);
     31
     32int kdb_poll_idx = 1;
     33EXPORT_SYMBOL_GPL(kdb_poll_idx);
     34
     35static struct kgdb_state *kdb_ks;
     36
     37int kdb_common_init_state(struct kgdb_state *ks)
     38{
     39	kdb_initial_cpu = atomic_read(&kgdb_active);
     40	kdb_current_task = kgdb_info[ks->cpu].task;
     41	kdb_current_regs = kgdb_info[ks->cpu].debuggerinfo;
     42	return 0;
     43}
     44
     45int kdb_common_deinit_state(void)
     46{
     47	kdb_initial_cpu = -1;
     48	kdb_current_task = NULL;
     49	kdb_current_regs = NULL;
     50	return 0;
     51}
     52
     53int kdb_stub(struct kgdb_state *ks)
     54{
     55	int error = 0;
     56	kdb_bp_t *bp;
     57	unsigned long addr = kgdb_arch_pc(ks->ex_vector, ks->linux_regs);
     58	kdb_reason_t reason = KDB_REASON_OOPS;
     59	kdb_dbtrap_t db_result = KDB_DB_NOBPT;
     60	int i;
     61
     62	kdb_ks = ks;
     63	if (KDB_STATE(REENTRY)) {
     64		reason = KDB_REASON_SWITCH;
     65		KDB_STATE_CLEAR(REENTRY);
     66		addr = instruction_pointer(ks->linux_regs);
     67	}
     68	ks->pass_exception = 0;
     69	if (atomic_read(&kgdb_setting_breakpoint))
     70		reason = KDB_REASON_KEYBOARD;
     71
     72	if (ks->err_code == KDB_REASON_SYSTEM_NMI && ks->signo == SIGTRAP)
     73		reason = KDB_REASON_SYSTEM_NMI;
     74
     75	else if (in_nmi())
     76		reason = KDB_REASON_NMI;
     77
     78	for (i = 0, bp = kdb_breakpoints; i < KDB_MAXBPT; i++, bp++) {
     79		if ((bp->bp_enabled) && (bp->bp_addr == addr)) {
     80			reason = KDB_REASON_BREAK;
     81			db_result = KDB_DB_BPT;
     82			if (addr != instruction_pointer(ks->linux_regs))
     83				kgdb_arch_set_pc(ks->linux_regs, addr);
     84			break;
     85		}
     86	}
     87	if (reason == KDB_REASON_BREAK || reason == KDB_REASON_SWITCH) {
     88		for (i = 0, bp = kdb_breakpoints; i < KDB_MAXBPT; i++, bp++) {
     89			if (bp->bp_free)
     90				continue;
     91			if (bp->bp_addr == addr) {
     92				bp->bp_delay = 1;
     93				bp->bp_delayed = 1;
     94	/*
     95	 * SSBPT is set when the kernel debugger must single step a
     96	 * task in order to re-establish an instruction breakpoint
     97	 * which uses the instruction replacement mechanism.  It is
     98	 * cleared by any action that removes the need to single-step
     99	 * the breakpoint.
    100	 */
    101				reason = KDB_REASON_BREAK;
    102				db_result = KDB_DB_BPT;
    103				KDB_STATE_SET(SSBPT);
    104				break;
    105			}
    106		}
    107	}
    108
    109	if (reason != KDB_REASON_BREAK && ks->ex_vector == 0 &&
    110		ks->signo == SIGTRAP) {
    111		reason = KDB_REASON_SSTEP;
    112		db_result = KDB_DB_BPT;
    113	}
    114	/* Set initial kdb state variables */
    115	KDB_STATE_CLEAR(KGDB_TRANS);
    116	kdb_common_init_state(ks);
    117	/* Remove any breakpoints as needed by kdb and clear single step */
    118	kdb_bp_remove();
    119	KDB_STATE_CLEAR(DOING_SS);
    120	KDB_STATE_SET(PAGER);
    121	if (ks->err_code == DIE_OOPS || reason == KDB_REASON_OOPS) {
    122		ks->pass_exception = 1;
    123		KDB_FLAG_SET(CATASTROPHIC);
    124	}
    125	/* set CATASTROPHIC if the system contains unresponsive processors */
    126	for_each_online_cpu(i)
    127		if (!kgdb_info[i].enter_kgdb)
    128			KDB_FLAG_SET(CATASTROPHIC);
    129	if (KDB_STATE(SSBPT) && reason == KDB_REASON_SSTEP) {
    130		KDB_STATE_CLEAR(SSBPT);
    131		KDB_STATE_CLEAR(DOING_SS);
    132	} else {
    133		/* Start kdb main loop */
    134		error = kdb_main_loop(KDB_REASON_ENTER, reason,
    135				      ks->err_code, db_result, ks->linux_regs);
    136	}
    137	/*
    138	 * Upon exit from the kdb main loop setup break points and restart
    139	 * the system based on the requested continue state
    140	 */
    141	kdb_common_deinit_state();
    142	KDB_STATE_CLEAR(PAGER);
    143	if (error == KDB_CMD_KGDB) {
    144		if (KDB_STATE(DOING_KGDB))
    145			KDB_STATE_CLEAR(DOING_KGDB);
    146		return DBG_PASS_EVENT;
    147	}
    148	kdb_bp_install(ks->linux_regs);
    149	/* Set the exit state to a single step or a continue */
    150	if (KDB_STATE(DOING_SS))
    151		gdbstub_state(ks, "s");
    152	else
    153		gdbstub_state(ks, "c");
    154
    155	KDB_FLAG_CLEAR(CATASTROPHIC);
    156
    157	/* Invoke arch specific exception handling prior to system resume */
    158	kgdb_info[ks->cpu].ret_state = gdbstub_state(ks, "e");
    159	if (ks->pass_exception)
    160		kgdb_info[ks->cpu].ret_state = 1;
    161	if (error == KDB_CMD_CPU) {
    162		KDB_STATE_SET(REENTRY);
    163		/*
    164		 * Force clear the single step bit because kdb emulates this
    165		 * differently vs the gdbstub
    166		 */
    167		kgdb_single_step = 0;
    168		return DBG_SWITCH_CPU_EVENT;
    169	}
    170	return kgdb_info[ks->cpu].ret_state;
    171}
    172
    173void kdb_gdb_state_pass(char *buf)
    174{
    175	gdbstub_state(kdb_ks, buf);
    176}