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.

Dependency Surface

Detected Declarations

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

Implementation Notes