arch/loongarch/kernel/kgdb.c

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

File Facts

System
Linux kernel
Corpus path
arch/loongarch/kernel/kgdb.c
Extension
.c
Size
18495 bytes
Lines
729
Domain
Architecture Layer
Bucket
arch/loongarch
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 (!bp->attr.disabled) {
			arch_uninstall_hw_breakpoint(bp);
			bp->attr.disabled = 1;
			continue;
		}

		if (hw_break_release_slot(i))
			pr_err("KGDB: hw bpt remove failed %lx\n", breakinfo[i].addr);
		breakinfo[i].enabled = 0;
	}

	csr_xchg32(0, CSR_CRMD_WE, LOONGARCH_CSR_CRMD);
	kgdb_watch_activated = 0;
}

static void kgdb_correct_hw_break(void)
{
	int i, activated = 0;

	for (i = 0; i < LOONGARCH_MAX_BRP; i++) {
		struct perf_event *bp;
		int val;
		int cpu = raw_smp_processor_id();

		if (!breakinfo[i].enabled)
			continue;

		bp = *per_cpu_ptr(breakinfo[i].pev, cpu);
		if (bp->attr.disabled != 1)
			continue;

		bp->attr.bp_addr = breakinfo[i].addr;
		bp->attr.bp_len = breakinfo[i].len;
		bp->attr.bp_type = breakinfo[i].type;

		val = hw_breakpoint_arch_parse(bp, &bp->attr, counter_arch_bp(bp));
		if (val)
			return;

		val = arch_install_hw_breakpoint(bp);
		if (!val)
			bp->attr.disabled = 0;
		activated = 1;
	}

	csr_xchg32(activated ? CSR_CRMD_WE : 0, CSR_CRMD_WE, LOONGARCH_CSR_CRMD);
	kgdb_watch_activated = activated;
}

const struct kgdb_arch arch_kgdb_ops = {
	.gdb_bpt_instr		= {0x02, 0x00, break_op >> 1, 0x00}, /* BRK_KDB = 2 */
	.flags			= KGDB_HW_BREAKPOINT,
	.set_hw_breakpoint	= kgdb_set_hw_break,
	.remove_hw_breakpoint	= kgdb_remove_hw_break,
	.disable_hw_break	= kgdb_disable_hw_break,
	.remove_all_hw_break	= kgdb_remove_all_hw_break,
	.correct_hw_break	= kgdb_correct_hw_break,
};

int kgdb_arch_init(void)
{
	return register_die_notifier(&kgdb_notifier);
}

void kgdb_arch_late(void)
{
	int i, cpu;
	struct perf_event_attr attr;
	struct perf_event **pevent;

	hw_breakpoint_init(&attr);

	attr.bp_addr = (unsigned long)kgdb_arch_init;
	attr.bp_len = HW_BREAKPOINT_LEN_4;
	attr.bp_type = HW_BREAKPOINT_W;
	attr.disabled = 1;

	for (i = 0; i < LOONGARCH_MAX_BRP; i++) {
		if (breakinfo[i].pev)
			continue;

		breakinfo[i].pev = register_wide_hw_breakpoint(&attr, NULL, NULL);
		if (IS_ERR_PCPU(breakinfo[i].pev)) {
			pr_err("kgdb: Could not allocate hw breakpoints.\n");
			breakinfo[i].pev = NULL;
			return;
		}

		for_each_online_cpu(cpu) {
			pevent = per_cpu_ptr(breakinfo[i].pev, cpu);

Annotation

Implementation Notes