arch/mips/kernel/kgdb.c

Source file repositories/reference/linux-study-clean/arch/mips/kernel/kgdb.c

File Facts

System
Linux kernel
Corpus path
arch/mips/kernel/kgdb.c
Extension
.c
Size
11315 bytes
Lines
395
Domain
Architecture Layer
Bucket
arch/mips
Inferred role
Architecture Layer: implementation source
Status
source implementation candidate

Why This File Exists

CPU and platform-specific kernel glue: boot entry, traps, syscall entry, interrupts, page tables, context switch, and low-level barriers.

Dependency Surface

Detected Declarations

Annotated Snippet

if (regno == 70) {
			/* Process the fcr31/fsr (register 70) */
			memcpy((void *)&current->thread.fpu.fcr31, mem,
			       dbg_reg_def[regno].size);
			goto out_save;
		} else if (regno == 71) {
			/* Ignore the fir (register 71) */
			goto out_save;
		}
		fp_reg = dbg_reg_def[regno].offset;
		memcpy((void *)&current->thread.fpu.fpr[fp_reg], mem,
		       dbg_reg_def[regno].size);
out_save:
		restore_fp(current);
	}

	return 0;
}

char *dbg_get_reg(int regno, void *mem, struct pt_regs *regs)
{
	int fp_reg;

	if (regno >= DBG_MAX_REG_NUM || regno < 0)
		return NULL;

	if (dbg_reg_def[regno].offset != -1 && regno < 38) {
		/* First 38 registers */
		memcpy(mem, (void *)regs + dbg_reg_def[regno].offset,
		       dbg_reg_def[regno].size);
	} else if (current && dbg_reg_def[regno].offset != -1 && regno < 72) {
		/* FP registers 38 -> 69 */
		if (!(regs->cp0_status & ST0_CU1))
			goto out;
		save_fp(current);
		if (regno == 70) {
			/* Process the fcr31/fsr (register 70) */
			memcpy(mem, (void *)&current->thread.fpu.fcr31,
			       dbg_reg_def[regno].size);
			goto out;
		} else if (regno == 71) {
			/* Ignore the fir (register 71) */
			memset(mem, 0, dbg_reg_def[regno].size);
			goto out;
		}
		fp_reg = dbg_reg_def[regno].offset;
		memcpy(mem, (void *)&current->thread.fpu.fpr[fp_reg],
		       dbg_reg_def[regno].size);
	}

out:
	return dbg_reg_def[regno].name;

}

void arch_kgdb_breakpoint(void)
{
	__asm__ __volatile__(
		".globl breakinst\n\t"
		".set\tnoreorder\n\t"
		"nop\n"
		"breakinst:\tbreak\n\t"
		"nop\n\t"
		".set\treorder");
}

static int compute_signal(int tt)
{
	struct hard_trap_info *ht;

	for (ht = hard_trap_info; ht->tt && ht->signo; ht++)
		if (ht->tt == tt)
			return ht->signo;

	return SIGHUP;		/* default for things we don't know about */
}

/*
 * Similar to regs_to_gdb_regs() except that process is sleeping and so
 * we may not be able to get all the info.
 */
void sleeping_thread_to_gdb_regs(unsigned long *gdb_regs, struct task_struct *p)
{
	int reg;
#if (KGDB_GDB_REG_SIZE == 32)
	u32 *ptr = (u32 *)gdb_regs;
#else
	u64 *ptr = (u64 *)gdb_regs;
#endif

Annotation

Implementation Notes