Commit 989fec19 authored by Kunkun Jiang's avatar Kunkun Jiang Committed by Dongxu Sun
Browse files

irqchip/gic-v4.1:Check whether indirect table is supported in allocate_vpe_l1_table

virt inclusion
category: other
bugzilla: https://gitee.com/openeuler/kernel/issues/I9SGLA



-------------------------------------------------------------

In allocate_vpe_l1_table, when we fail to inherit VPE table from other
redistributors or ITSs, and we allocate a new vpe table for current common
affinity field without checking whether indirect table is supported.
Let's fix it.

Signed-off-by: default avatarNianyao Tang <tangnianyao@huawei.com>
Signed-off-by: default avatarMarc Zyngier <maz@kernel.org>
Signed-off-by: default avatarKunkun Jiang <jiangkunkun@huawei.com>
parent 716da49e
Loading
Loading
Loading
Loading
+6 −2
Original line number Diff line number Diff line
@@ -3208,6 +3208,7 @@ static int allocate_vpe_l1_table(void)
	unsigned int psz = SZ_64K;
	unsigned int np, epp, esz;
	struct page *page;
	bool indirect;

	if (!gic_rdists->has_rvpeid)
		return 0;
@@ -3242,10 +3243,12 @@ static int allocate_vpe_l1_table(void)

	/* First probe the page size */
	val = FIELD_PREP(GICR_VPROPBASER_4_1_PAGE_SIZE, GIC_PAGE_SIZE_64K);
	val |= GICR_VPROPBASER_4_1_INDIRECT;
	gicr_write_vpropbaser(val, vlpi_base + GICR_VPROPBASER);
	val = gicr_read_vpropbaser(vlpi_base + GICR_VPROPBASER);
	gpsz = FIELD_GET(GICR_VPROPBASER_4_1_PAGE_SIZE, val);
	esz = FIELD_GET(GICR_VPROPBASER_4_1_ENTRY_SIZE, val);
	indirect = !!(val & GICR_VPROPBASER_4_1_INDIRECT);

	switch (gpsz) {
	default:
@@ -3278,7 +3281,7 @@ static int allocate_vpe_l1_table(void)
	 * If we need more than just a single L1 page, flag the table
	 * as indirect and compute the number of required L1 pages.
	 */
	if (epp < ITS_MAX_VPEID) {
	if (epp < ITS_MAX_VPEID && indirect) {
		int nl2;

		val |= GICR_VPROPBASER_4_1_INDIRECT;
@@ -3289,7 +3292,8 @@ static int allocate_vpe_l1_table(void)
		/* Number of L1 pages to point to the L2 pages */
		npg = DIV_ROUND_UP(nl2 * SZ_8, psz);
	} else {
		npg = 1;
		npg = DIV_ROUND_UP(ITS_MAX_VPEID, epp);
		npg = clamp_val(npg, 1, (GICR_VPROPBASER_4_1_SIZE + 1));
	}

	val |= FIELD_PREP(GICR_VPROPBASER_4_1_SIZE, npg - 1);