Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit ddb78a29 authored by Neeti Desai's avatar Neeti Desai Committed by Sarangdhar Joshi
Browse files

coresight: add checks to validate etm trace unit resource values



Hardware sets the register values to indicate how many resources the trace
unit supports. Add checks to validate these values to avoid any out of
bounds access.

Change-Id: I5f19a1351af3bc727f6fb7743a258727fa80fc06
Signed-off-by: default avatarNeeti Desai <neetid@codeaurora.org>
Signed-off-by: default avatarSarangdhar Joshi <spjoshi@codeaurora.org>
parent 5f953ec6
Loading
Loading
Loading
Loading
+34 −0
Original line number Diff line number Diff line
@@ -151,8 +151,11 @@ do { \
#define ETMPDSR				(0x314)

#define ETM_MAX_ADDR_CMP		(16)
#define ETM_MAX_DATA_CMP		(8)
#define ETM_MAX_CNTR			(4)
#define ETM_MAX_CTXID_CMP		(3)
#define ETM_MAX_EXT_INP			(4)
#define ETM_MAX_EXT_OUTP		(4)

#define ETM_MODE_EXCLUDE		BIT(0)
#define ETM_MODE_CYCACC			BIT(1)
@@ -1978,11 +1981,42 @@ static void etm_init_arch_data(void *info)

	etmccr = etm_readl(drvdata, ETMCCR);
	drvdata->nr_addr_cmp = BMVAL(etmccr, 0, 3) * 2;
	if (drvdata->nr_addr_cmp > ETM_MAX_ADDR_CMP) {
		dev_err(drvdata->dev,
			"nr_addr_cmp out of bounds %u\n", drvdata->nr_addr_cmp);
		drvdata->nr_addr_cmp = ETM_MAX_ADDR_CMP;
	}
	drvdata->nr_cntr = BMVAL(etmccr, 13, 15);
	if (drvdata->nr_cntr > ETM_MAX_CNTR) {
		dev_err(drvdata->dev,
			"nr_cntr out of bounds %u\n", drvdata->nr_cntr);
		drvdata->nr_cntr = ETM_MAX_CNTR;
	}
	drvdata->nr_ext_inp = BMVAL(etmccr, 17, 19);
	if (drvdata->nr_ext_inp > ETM_MAX_EXT_INP) {
		dev_err(drvdata->dev,
			"nr_ext_inp out of bounds %u\n", drvdata->nr_ext_inp);
		drvdata->nr_ext_inp = ETM_MAX_EXT_INP;
	}
	drvdata->nr_ext_out = BMVAL(etmccr, 20, 22);
	if (drvdata->nr_ext_out > ETM_MAX_EXT_OUTP) {
		dev_err(drvdata->dev,
			"nr_ext_out out of bounds %u\n", drvdata->nr_ext_out);
		drvdata->nr_ext_out = ETM_MAX_EXT_OUTP;
	}
	drvdata->nr_ctxid_cmp = BMVAL(etmccr, 24, 25);
	if (drvdata->nr_ctxid_cmp > ETM_MAX_CTXID_CMP) {
		dev_err(drvdata->dev,
			"nr_ctxid_cmp out of bounds %u\n",
			drvdata->nr_ctxid_cmp);
		drvdata->nr_ctxid_cmp = ETM_MAX_CTXID_CMP;
	}
	drvdata->nr_data_cmp = BMVAL(etmccr, 4, 7);
	if (drvdata->nr_data_cmp > ETM_MAX_DATA_CMP) {
		dev_err(drvdata->dev,
			"nr_data_cmp out of bounds %u\n", drvdata->nr_data_cmp);
		drvdata->nr_data_cmp = ETM_MAX_DATA_CMP;
	}

	if (etm_version_gte(drvdata->arch, ETM_ARCH_V1_0)) {
		etmcr = etm_readl(drvdata, ETMCR);
+65 −1
Original line number Diff line number Diff line
@@ -302,7 +302,7 @@ struct etm_drvdata {
	uint8_t				nr_addr_cmp; /* comparator pairs */
	uint8_t				nr_data_cmp;
	uint8_t				nr_cntr;
	uint8_t				nr_ext_inp;
	uint32_t			nr_ext_inp;
	uint8_t				nr_ext_inp_sel;
	uint8_t				nr_ext_out;
	uint8_t				nr_ctxid_cmp;
@@ -3025,20 +3025,71 @@ static void etm_init_arch_data(void *info)
	/* number of resources trace unit supports */
	etmidr4 = etm_readl(drvdata, TRCIDR4);
	drvdata->nr_addr_cmp = BMVAL(etmidr4, 0, 3);
	if (drvdata->nr_addr_cmp > ETM_MAX_ADDR_RANGE_CMP) {
		dev_err(drvdata->dev,
			"nr_addr_cmp out of bounds %u\n", drvdata->nr_addr_cmp);
		drvdata->nr_addr_cmp = ETM_MAX_ADDR_RANGE_CMP;
	}
	drvdata->nr_data_cmp = BMVAL(etmidr4, 4, 7);
	if (drvdata->nr_data_cmp > ETM_MAX_DATA_VAL_CMP) {
		dev_err(drvdata->dev,
			"nr_data_cmp out of bounds %u\n", drvdata->nr_data_cmp);
		drvdata->nr_data_cmp = ETM_MAX_DATA_VAL_CMP;
	}

	if (BVAL(etmidr4, 8))
		drvdata->data_addr_cmp_support = true;
	else
		drvdata->data_addr_cmp_support = false;

	drvdata->nr_pe_cmp = BMVAL(etmidr4, 12, 15);
	if (drvdata->nr_pe_cmp > ETM_MAX_PE_CMP) {
		dev_err(drvdata->dev,
			"nr_pe_cmp out of bounds %u\n", drvdata->nr_pe_cmp);
		drvdata->nr_pe_cmp = ETM_MAX_PE_CMP;
	}
	drvdata->nr_resource = BMVAL(etmidr4, 16, 19);
	if (drvdata->nr_resource > ETM_MAX_RES_SEL) {
		dev_err(drvdata->dev,
			"nr_resource out of bounds %u\n", drvdata->nr_resource);
		drvdata->nr_resource = ETM_MAX_RES_SEL;
	}
	drvdata->nr_ss_cmp = BMVAL(etmidr4, 20, 23);
	if (drvdata->nr_ss_cmp > ETM_MAX_SS_CMP) {
		dev_err(drvdata->dev,
			"nr_ss_cmp out of bounds %u\n", drvdata->nr_ss_cmp);
		drvdata->nr_ss_cmp = ETM_MAX_SS_CMP;
	}
	drvdata->nr_ctxid_cmp = BMVAL(etmidr4, 24, 27);
	if (drvdata->nr_ctxid_cmp > ETM_MAX_CTXID_CMP) {
		dev_err(drvdata->dev,
			"nr_ctxid_cmp out of bounds %u\n",
			drvdata->nr_ctxid_cmp);
		drvdata->nr_ctxid_cmp = ETM_MAX_CTXID_CMP;
	}
	drvdata->nr_vmid_cmp = BMVAL(etmidr4, 28, 31);
	if (drvdata->nr_vmid_cmp > ETM_MAX_VMID_CMP) {
		dev_err(drvdata->dev,
			"nr_vmid_cmp out of bounds %u\n", drvdata->nr_vmid_cmp);
		drvdata->nr_vmid_cmp = ETM_MAX_VMID_CMP;
	}

	etmidr5 = etm_readl(drvdata, TRCIDR5);
	drvdata->nr_ext_inp = BMVAL(etmidr5, 0, 8);
	if (drvdata->nr_ext_inp > ETM_MAX_EXT_INP) {
		dev_err(drvdata->dev,
			"nr_ext_inp out of bounds %lu\n",
			(unsigned long)drvdata->nr_ext_inp);
		drvdata->nr_ext_inp = ETM_MAX_EXT_INP;
	}
	drvdata->nr_ext_inp_sel = BMVAL(etmidr5, 9, 11);
	if (drvdata->nr_ext_inp_sel > ETM_MAX_EXT_INP_SEL) {
		dev_err(drvdata->dev,
			"nr_ext_inp_sel out of bounds %u\n",
			drvdata->nr_ext_inp_sel);
		drvdata->nr_ext_inp_sel = ETM_MAX_EXT_INP_SEL;
	}

	drvdata->trcid_size = BMVAL(etmidr5, 16, 21);
	if (BVAL(etmidr5, 22))
		drvdata->atbtrig_support = true;
@@ -3048,8 +3099,21 @@ static void etm_init_arch_data(void *info)
		drvdata->lp_override_support = true;
	else
		drvdata->lp_override_support = false;

	drvdata->nr_seq_state = BMVAL(etmidr5, 25, 27);
	if (drvdata->nr_seq_state > ETM_MAX_SEQ_STATES) {
		dev_err(drvdata->dev,
			"nr_seq_state out of bounds %u\n",
			drvdata->nr_seq_state);
		drvdata->nr_seq_state = ETM_MAX_SEQ_STATES;
	}
	drvdata->nr_cntr = BMVAL(etmidr5, 28, 30);
	if (drvdata->nr_cntr > ETM_MAX_CNTR) {
		dev_err(drvdata->dev,
			"nr_cntr out of bounds %u\n", drvdata->nr_cntr);
		drvdata->nr_cntr = ETM_MAX_CNTR;
	}

	if (BVAL(etmidr5, 31))
		drvdata->reduced_cntr_support = true;
	else