arch/riscv/kernel/kgdb.c
Source file repositories/reference/linux-study-clean/arch/riscv/kernel/kgdb.c
File Facts
- System
- Linux kernel
- Corpus path
arch/riscv/kernel/kgdb.c- Extension
.c- Size
- 11065 bytes
- Lines
- 379
- Domain
- Architecture Layer
- Bucket
- arch/riscv
- 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.
- CPU and platform-specific kernel glue: boot entry, traps, syscall entry, interrupts, page tables, context switch, and low-level barriers.
- Uses kernel synchronization; read lock ordering, sleepability, and interrupt context assumptions before translating.
- Defines or uses C structs; map object ownership, embedded links, reference counts, and lock ownership.
Dependency Surface
linux/ptrace.hlinux/kdebug.hlinux/bug.hlinux/kgdb.hlinux/irqflags.hlinux/string.hasm/cacheflush.hasm/gdb_xml.hasm/insn.h
Detected Declarations
function decode_register_indexfunction decode_register_index_shortfunction get_step_addressfunction riscv_insn_is_c_jalfunction do_single_stepfunction undo_single_stepfunction dbg_set_regfunction sleeping_thread_to_gdb_regsfunction kgdb_arch_set_pcfunction arch_kgdb_breakpointfunction kgdb_arch_handle_qxfer_pktfunction kgdb_arch_update_addrfunction kgdb_arch_handle_exceptionfunction kgdb_riscv_kgdbbreakfunction kgdb_riscv_notifyfunction kgdb_arch_initfunction kgdb_arch_exit
Annotated Snippet
riscv_insn_is_c_jr(op_code)) {
rs1_num = decode_register_index(op_code, RVC_C2_RS1_OPOFF);
*next_addr = regs_ptr[rs1_num];
} else if (riscv_insn_is_c_j(op_code) ||
riscv_insn_is_c_jal(op_code)) {
*next_addr = RVC_EXTRACT_JTYPE_IMM(op_code) + pc;
} else if (riscv_insn_is_c_beqz(op_code)) {
rs1_num = decode_register_index_short(op_code,
RVC_C1_RS1_OPOFF);
if (!rs1_num || regs_ptr[rs1_num] == 0)
*next_addr = RVC_EXTRACT_BTYPE_IMM(op_code) + pc;
else
*next_addr = pc + 2;
} else if (riscv_insn_is_c_bnez(op_code)) {
rs1_num =
decode_register_index_short(op_code, RVC_C1_RS1_OPOFF);
if (rs1_num && regs_ptr[rs1_num] != 0)
*next_addr = RVC_EXTRACT_BTYPE_IMM(op_code) + pc;
else
*next_addr = pc + 2;
} else {
*next_addr = pc + 2;
}
} else {
if ((op_code & __INSN_OPCODE_MASK) == __INSN_BRANCH_OPCODE) {
bool result = false;
long imm = RV_EXTRACT_BTYPE_IMM(op_code);
unsigned long rs1_val = 0, rs2_val = 0;
rs1_num = decode_register_index(op_code, RVG_RS1_OPOFF);
rs2_num = decode_register_index(op_code, RVG_RS2_OPOFF);
if (rs1_num)
rs1_val = regs_ptr[rs1_num];
if (rs2_num)
rs2_val = regs_ptr[rs2_num];
if (riscv_insn_is_beq(op_code))
result = (rs1_val == rs2_val) ? true : false;
else if (riscv_insn_is_bne(op_code))
result = (rs1_val != rs2_val) ? true : false;
else if (riscv_insn_is_blt(op_code))
result =
((long)rs1_val <
(long)rs2_val) ? true : false;
else if (riscv_insn_is_bge(op_code))
result =
((long)rs1_val >=
(long)rs2_val) ? true : false;
else if (riscv_insn_is_bltu(op_code))
result = (rs1_val < rs2_val) ? true : false;
else if (riscv_insn_is_bgeu(op_code))
result = (rs1_val >= rs2_val) ? true : false;
if (result)
*next_addr = imm + pc;
else
*next_addr = pc + 4;
} else if (riscv_insn_is_jal(op_code)) {
*next_addr = RV_EXTRACT_JTYPE_IMM(op_code) + pc;
} else if (riscv_insn_is_jalr(op_code)) {
rs1_num = decode_register_index(op_code, RVG_RS1_OPOFF);
if (rs1_num)
*next_addr = ((unsigned long *)regs)[rs1_num];
*next_addr += RV_EXTRACT_ITYPE_IMM(op_code);
} else if (riscv_insn_is_sret(op_code)) {
*next_addr = pc;
} else {
*next_addr = pc + 4;
}
}
return 0;
}
static int do_single_step(struct pt_regs *regs)
{
/* Determine where the target instruction will send us to */
unsigned long addr = 0;
int error = get_step_address(regs, &addr);
if (error)
return error;
/* Store the op code in the stepped address */
error = get_kernel_nofault(stepped_opcode, (void *)addr);
if (error)
return error;
stepped_address = addr;
/* Replace the op code with the break instruction */
error = copy_to_kernel_nofault((void *)stepped_address,
Annotation
- Immediate include surface: `linux/ptrace.h`, `linux/kdebug.h`, `linux/bug.h`, `linux/kgdb.h`, `linux/irqflags.h`, `linux/string.h`, `asm/cacheflush.h`, `asm/gdb_xml.h`.
- Detected declarations: `function decode_register_index`, `function decode_register_index_short`, `function get_step_address`, `function riscv_insn_is_c_jal`, `function do_single_step`, `function undo_single_step`, `function dbg_set_reg`, `function sleeping_thread_to_gdb_regs`, `function kgdb_arch_set_pc`, `function arch_kgdb_breakpoint`.
- Atlas domain: Architecture Layer / arch/riscv.
- Implementation status: source implementation candidate.
- Synchronization appears in or near this file; preserve lock ordering, sleepability, and interrupt-context constraints.
Implementation Notes
- This generated page is the file-by-file coverage layer; curated subsystem chapters should link here when they synthesize a multi-file control flow.
- Core OS pages should be promoted from atlas-only to deep-reviewed when they explain data structures, invariants, locking, lifecycle, and C implementation snippets.
- Driver-family pages are intentionally pattern-oriented unless they are part of the selected PCIe/NVMe representative device path.