Commit 9b50f539 authored by Omer Shpigelman's avatar Omer Shpigelman Committed by Oded Gabbay
Browse files

habanalabs: improve security in Debug IOCTL



This patch improves the security in the Debug IOCTL.
It adds checks that:
- The register index value is in the allowed range for all opcodes.
- The event types number is in the allowed range in SPMU enable.
- The events number is in the allowed range in SPMU disable.

Signed-off-by: default avatarOmer Shpigelman <oshpigelman@habana.ai>
Reviewed-by: default avatarOded Gabbay <oded.gabbay@gmail.com>
Signed-off-by: default avatarOded Gabbay <oded.gabbay@gmail.com>
parent 8d175932
Loading
Loading
Loading
Loading
+62 −10
Original line number Diff line number Diff line
@@ -15,6 +15,10 @@

#define GOYA_PLDM_CORESIGHT_TIMEOUT_USEC	(CORESIGHT_TIMEOUT_USEC * 100)

#define SPMU_SECTION_SIZE		DMA_CH_0_CS_SPMU_MAX_OFFSET
#define SPMU_EVENT_TYPES_OFFSET		0x400
#define SPMU_MAX_COUNTERS		6

static u64 debug_stm_regs[GOYA_STM_LAST + 1] = {
	[GOYA_STM_CPU]		= mmCPU_STM_BASE,
	[GOYA_STM_DMA_CH_0_CS]	= mmDMA_CH_0_CS_STM_BASE,
@@ -226,9 +230,16 @@ static int goya_config_stm(struct hl_device *hdev,
		struct hl_debug_params *params)
{
	struct hl_debug_params_stm *input;
	u64 base_reg = debug_stm_regs[params->reg_idx] - CFG_BASE;
	u64 base_reg;
	int rc;

	if (params->reg_idx >= ARRAY_SIZE(debug_stm_regs)) {
		dev_err(hdev->dev, "Invalid register index in STM\n");
		return -EINVAL;
	}

	base_reg = debug_stm_regs[params->reg_idx] - CFG_BASE;

	WREG32(base_reg + 0xFB0, CORESIGHT_UNLOCK);

	if (params->enable) {
@@ -288,10 +299,17 @@ static int goya_config_etf(struct hl_device *hdev,
		struct hl_debug_params *params)
{
	struct hl_debug_params_etf *input;
	u64 base_reg = debug_etf_regs[params->reg_idx] - CFG_BASE;
	u64 base_reg;
	u32 val;
	int rc;

	if (params->reg_idx >= ARRAY_SIZE(debug_etf_regs)) {
		dev_err(hdev->dev, "Invalid register index in ETF\n");
		return -EINVAL;
	}

	base_reg = debug_etf_regs[params->reg_idx] - CFG_BASE;

	WREG32(base_reg + 0xFB0, CORESIGHT_UNLOCK);

	val = RREG32(base_reg + 0x304);
@@ -445,11 +463,18 @@ static int goya_config_etr(struct hl_device *hdev,
static int goya_config_funnel(struct hl_device *hdev,
		struct hl_debug_params *params)
{
	WREG32(debug_funnel_regs[params->reg_idx] - CFG_BASE + 0xFB0,
			CORESIGHT_UNLOCK);
	u64 base_reg;

	if (params->reg_idx >= ARRAY_SIZE(debug_funnel_regs)) {
		dev_err(hdev->dev, "Invalid register index in FUNNEL\n");
		return -EINVAL;
	}

	WREG32(debug_funnel_regs[params->reg_idx] - CFG_BASE,
			params->enable ? 0x33F : 0);
	base_reg = debug_funnel_regs[params->reg_idx] - CFG_BASE;

	WREG32(base_reg + 0xFB0, CORESIGHT_UNLOCK);

	WREG32(base_reg, params->enable ? 0x33F : 0);

	return 0;
}
@@ -458,9 +483,16 @@ static int goya_config_bmon(struct hl_device *hdev,
		struct hl_debug_params *params)
{
	struct hl_debug_params_bmon *input;
	u64 base_reg = debug_bmon_regs[params->reg_idx] - CFG_BASE;
	u64 base_reg;
	u32 pcie_base = 0;

	if (params->reg_idx >= ARRAY_SIZE(debug_bmon_regs)) {
		dev_err(hdev->dev, "Invalid register index in BMON\n");
		return -EINVAL;
	}

	base_reg = debug_bmon_regs[params->reg_idx] - CFG_BASE;

	WREG32(base_reg + 0x104, 1);

	if (params->enable) {
@@ -522,7 +554,7 @@ static int goya_config_bmon(struct hl_device *hdev,
static int goya_config_spmu(struct hl_device *hdev,
		struct hl_debug_params *params)
{
	u64 base_reg = debug_spmu_regs[params->reg_idx] - CFG_BASE;
	u64 base_reg;
	struct hl_debug_params_spmu *input = params->input;
	u64 *output;
	u32 output_arr_len;
@@ -531,6 +563,13 @@ static int goya_config_spmu(struct hl_device *hdev,
	u32 cycle_cnt_idx;
	int i;

	if (params->reg_idx >= ARRAY_SIZE(debug_spmu_regs)) {
		dev_err(hdev->dev, "Invalid register index in SPMU\n");
		return -EINVAL;
	}

	base_reg = debug_spmu_regs[params->reg_idx] - CFG_BASE;

	if (params->enable) {
		input = params->input;

@@ -539,7 +578,13 @@ static int goya_config_spmu(struct hl_device *hdev,

		if (input->event_types_num < 3) {
			dev_err(hdev->dev,
				"not enough values for SPMU enable\n");
				"not enough event types values for SPMU enable\n");
			return -EINVAL;
		}

		if (input->event_types_num > SPMU_MAX_COUNTERS) {
			dev_err(hdev->dev,
				"too many event types values for SPMU enable\n");
			return -EINVAL;
		}

@@ -547,7 +592,8 @@ static int goya_config_spmu(struct hl_device *hdev,
		WREG32(base_reg + 0xE04, 0x41013040);

		for (i = 0 ; i < input->event_types_num ; i++)
			WREG32(base_reg + 0x400 + i * 4, input->event_types[i]);
			WREG32(base_reg + SPMU_EVENT_TYPES_OFFSET + i * 4,
				input->event_types[i]);

		WREG32(base_reg + 0xE04, 0x41013041);
		WREG32(base_reg + 0xC00, 0x8000003F);
@@ -567,6 +613,12 @@ static int goya_config_spmu(struct hl_device *hdev,
			return -EINVAL;
		}

		if (events_num > SPMU_MAX_COUNTERS) {
			dev_err(hdev->dev,
				"too many events values for SPMU disable\n");
			return -EINVAL;
		}

		WREG32(base_reg + 0xE04, 0x41013040);

		for (i = 0 ; i < events_num ; i++)