arm64 debug-register installation

osfmk/arm64/pcb.c · 1454 lines · browse source

Installation and validation of saved hardware breakpoint/watchpoint controls and addresses. arm_debug_set64 programs the debug registers, updates MDSCR_EL1.SS and saved processor state for single stepping, and issues an instruction synchronization barrier.

arm_debug_set64 source
void
arm_debug_set64(arm_debug_state_t *debug_state)
{
	struct cpu_data *  cpu_data_ptr;
	arm_debug_info_t * debug_info    = arm_debug_info();
	boolean_t          intr;
	arm_debug_state_t  off_state;
	arm_debug_state_t  *cpu_debug;
	uint64_t           all_ctrls = 0;

	// Non-developers should never need to have hardware break/watchpoints
	// set on their phones.
	extern bool developer_mode_state(void);
	if (!developer_mode_state()) {
		return;
	}

	intr = ml_set_interrupts_enabled(FALSE);
	cpu_data_ptr = getCpuDatap();
	cpu_debug = cpu_data_ptr->cpu_user_debug;

	/*
	 * Retain and set new per-cpu state.
	 * Reference count does not matter when turning off debug state.
	 */
	if (debug_state == NULL) {
		bzero(&off_state, sizeof(off_state));
		cpu_data_ptr->cpu_user_debug = NULL;
		debug_state = &off_state;
	} else {
… more in source
arm_debug_set source
void
arm_debug_set(arm_debug_state_t *debug_state)
{
	if (debug_state) {
		switch (debug_state->dsh.flavor) {
		case ARM_DEBUG_STATE32:
			arm_debug_set32(debug_state);
			break;
		case ARM_DEBUG_STATE64:
			arm_debug_set64(debug_state);
			break;
		default:
			panic("arm_debug_set");
			break;
		}
	} else {
		if (thread_is_64bit_data(current_thread())) {
			arm_debug_set64(debug_state);
		} else {
			arm_debug_set32(debug_state);
		}
	}
}
debug_state_is_valid64 source
boolean_t
debug_state_is_valid64(arm_debug_state64_t *debug_state)
{
	arm_debug_info_t *debug_info = arm_debug_info();
	uint32_t i;
	for (i = 0; i < debug_info->num_breakpoint_pairs; i++) {
		if (0 != debug_state->bcr[i] && MACH_VM_MAX_ADDRESS <= debug_state->bvr[i]) {
			return FALSE;
		}
	}

	for (i = 0; i < debug_info->num_watchpoint_pairs; i++) {
		if (0 != debug_state->wcr[i] && MACH_VM_MAX_ADDRESS <= debug_state->wvr[i]) {
			return FALSE;
		}
	}
	return TRUE;
}