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

kgdb.c (4661B)


      1// SPDX-License-Identifier: GPL-2.0-or-later
      2/*
      3 * Nios2 KGDB support
      4 *
      5 * Copyright (C) 2015 Altera Corporation
      6 * Copyright (C) 2011 Tobias Klauser <tklauser@distanz.ch>
      7 *
      8 * Based on the code posted by Kazuyasu on the Altera Forum at:
      9 * http://www.alteraforum.com/forum/showpost.php?p=77003&postcount=20
     10 */
     11#include <linux/ptrace.h>
     12#include <linux/kgdb.h>
     13#include <linux/kdebug.h>
     14#include <linux/io.h>
     15
     16static int wait_for_remote_debugger;
     17
     18struct dbg_reg_def_t dbg_reg_def[DBG_MAX_REG_NUM] =
     19{
     20	{ "zero", GDB_SIZEOF_REG, -1 },
     21	{ "at", GDB_SIZEOF_REG, offsetof(struct pt_regs, r1) },
     22	{ "r2", GDB_SIZEOF_REG, offsetof(struct pt_regs, r2) },
     23	{ "r3", GDB_SIZEOF_REG, offsetof(struct pt_regs, r3) },
     24	{ "r4", GDB_SIZEOF_REG, offsetof(struct pt_regs, r4) },
     25	{ "r5", GDB_SIZEOF_REG, offsetof(struct pt_regs, r5) },
     26	{ "r6", GDB_SIZEOF_REG, offsetof(struct pt_regs, r6) },
     27	{ "r7", GDB_SIZEOF_REG, offsetof(struct pt_regs, r7) },
     28	{ "r8", GDB_SIZEOF_REG, offsetof(struct pt_regs, r8) },
     29	{ "r9", GDB_SIZEOF_REG, offsetof(struct pt_regs, r9) },
     30	{ "r10", GDB_SIZEOF_REG, offsetof(struct pt_regs, r10) },
     31	{ "r11", GDB_SIZEOF_REG, offsetof(struct pt_regs, r11) },
     32	{ "r12", GDB_SIZEOF_REG, offsetof(struct pt_regs, r12) },
     33	{ "r13", GDB_SIZEOF_REG, offsetof(struct pt_regs, r13) },
     34	{ "r14", GDB_SIZEOF_REG, offsetof(struct pt_regs, r14) },
     35	{ "r15", GDB_SIZEOF_REG, offsetof(struct pt_regs, r15) },
     36	{ "r16", GDB_SIZEOF_REG, -1 },
     37	{ "r17", GDB_SIZEOF_REG, -1 },
     38	{ "r18", GDB_SIZEOF_REG, -1 },
     39	{ "r19", GDB_SIZEOF_REG, -1 },
     40	{ "r20", GDB_SIZEOF_REG, -1 },
     41	{ "r21", GDB_SIZEOF_REG, -1 },
     42	{ "r22", GDB_SIZEOF_REG, -1 },
     43	{ "r23", GDB_SIZEOF_REG, -1 },
     44	{ "et", GDB_SIZEOF_REG, -1 },
     45	{ "bt", GDB_SIZEOF_REG, -1 },
     46	{ "gp", GDB_SIZEOF_REG, offsetof(struct pt_regs, gp) },
     47	{ "sp", GDB_SIZEOF_REG, offsetof(struct pt_regs, sp) },
     48	{ "fp", GDB_SIZEOF_REG, offsetof(struct pt_regs, fp) },
     49	{ "ea", GDB_SIZEOF_REG, -1 },
     50	{ "ba", GDB_SIZEOF_REG, -1 },
     51	{ "ra", GDB_SIZEOF_REG, offsetof(struct pt_regs, ra) },
     52	{ "pc", GDB_SIZEOF_REG, offsetof(struct pt_regs, ea) },
     53	{ "status", GDB_SIZEOF_REG, -1 },
     54	{ "estatus", GDB_SIZEOF_REG, offsetof(struct pt_regs, estatus) },
     55	{ "bstatus", GDB_SIZEOF_REG, -1 },
     56	{ "ienable", GDB_SIZEOF_REG, -1 },
     57	{ "ipending", GDB_SIZEOF_REG, -1},
     58	{ "cpuid", GDB_SIZEOF_REG, -1 },
     59	{ "ctl6", GDB_SIZEOF_REG, -1 },
     60	{ "exception", GDB_SIZEOF_REG, -1 },
     61	{ "pteaddr", GDB_SIZEOF_REG, -1 },
     62	{ "tlbacc", GDB_SIZEOF_REG, -1 },
     63	{ "tlbmisc", GDB_SIZEOF_REG, -1 },
     64	{ "eccinj", GDB_SIZEOF_REG, -1 },
     65	{ "badaddr", GDB_SIZEOF_REG, -1 },
     66	{ "config", GDB_SIZEOF_REG, -1 },
     67	{ "mpubase", GDB_SIZEOF_REG, -1 },
     68	{ "mpuacc", GDB_SIZEOF_REG, -1 },
     69};
     70
     71char *dbg_get_reg(int regno, void *mem, struct pt_regs *regs)
     72{
     73	if (regno >= DBG_MAX_REG_NUM || regno < 0)
     74		return NULL;
     75
     76	if (dbg_reg_def[regno].offset != -1)
     77		memcpy(mem, (void *)regs + dbg_reg_def[regno].offset,
     78		       dbg_reg_def[regno].size);
     79	else
     80		memset(mem, 0, dbg_reg_def[regno].size);
     81
     82	return dbg_reg_def[regno].name;
     83}
     84
     85int dbg_set_reg(int regno, void *mem, struct pt_regs *regs)
     86{
     87	if (regno >= DBG_MAX_REG_NUM || regno < 0)
     88		return -EINVAL;
     89
     90	if (dbg_reg_def[regno].offset != -1)
     91		memcpy((void *)regs + dbg_reg_def[regno].offset, mem,
     92		       dbg_reg_def[regno].size);
     93
     94	return 0;
     95}
     96
     97void sleeping_thread_to_gdb_regs(unsigned long *gdb_regs, struct task_struct *p)
     98{
     99	memset((char *)gdb_regs, 0, NUMREGBYTES);
    100	gdb_regs[GDB_SP] = p->thread.kregs->sp;
    101	gdb_regs[GDB_PC] = p->thread.kregs->ea;
    102}
    103
    104void kgdb_arch_set_pc(struct pt_regs *regs, unsigned long pc)
    105{
    106	regs->ea = pc;
    107}
    108
    109int kgdb_arch_handle_exception(int vector, int signo, int err_code,
    110				char *remcom_in_buffer, char *remcom_out_buffer,
    111				struct pt_regs *regs)
    112{
    113	char *ptr;
    114	unsigned long addr;
    115
    116	switch (remcom_in_buffer[0]) {
    117	case 's':
    118	case 'c':
    119		/* handle the optional parameters */
    120		ptr = &remcom_in_buffer[1];
    121		if (kgdb_hex2long(&ptr, &addr))
    122			regs->ea = addr;
    123
    124		return 0;
    125	}
    126
    127	return -1; /* this means that we do not want to exit from the handler */
    128}
    129
    130asmlinkage void kgdb_breakpoint_c(struct pt_regs *regs)
    131{
    132	/*
    133	 * The breakpoint entry code has moved the PC on by 4 bytes, so we must
    134	 * move it back.  This could be done on the host but we do it here
    135	 */
    136	if (!wait_for_remote_debugger)
    137		regs->ea -= 4;
    138	else	/* pass the first trap 30 code */
    139		wait_for_remote_debugger = 0;
    140
    141	kgdb_handle_exception(30, SIGTRAP, 0, regs);
    142}
    143
    144int kgdb_arch_init(void)
    145{
    146	wait_for_remote_debugger = 1;
    147	return 0;
    148}
    149
    150void kgdb_arch_exit(void)
    151{
    152	/* Nothing to do */
    153}
    154
    155const struct kgdb_arch arch_kgdb_ops = {
    156	/* Breakpoint instruction: trap 30 */
    157	.gdb_bpt_instr = { 0xba, 0x6f, 0x3b, 0x00 },
    158};