[Skiboot] [PATCH v2 4/8] npu2: Prepare purge_l2_l3_caches() for reuse

Alexey Kardashevskiy aik at ozlabs.ru
Wed Jul 10 13:07:29 AEST 2019



On 09/07/2019 07:07, Reza Arbab wrote:
> Move this to a separate compilation unit with its own header, for reuse.


Reviewed-by: Alexey Kardashevskiy <aik at ozlabs.ru>

But please mention in the commit log what changes you made when moving 
blocks other than just moving. I spotted PPC_BIT->PPC_BITMASK (good 
ones) and registers address case changes (why?) so I had to compare the 
entire chunks in case there are some other changes too. Thanks,



> 
> Signed-off-by: Reza Arbab <arbab at linux.ibm.com>
> Reviewed-by: Andrew Donnellan <ajd at linux.ibm.com>
 >
> ---
>   hw/Makefile.inc     |   2 +-
>   hw/cache-p9.c       | 173 ++++++++++++++++++++++++++++++++++++++++++++++++++++
>   hw/npu2.c           | 139 +----------------------------------------
>   include/cache-p9.h  |  22 +++++++
>   include/npu2-regs.h |  13 ----
>   5 files changed, 197 insertions(+), 152 deletions(-)
>   create mode 100644 hw/cache-p9.c
>   create mode 100644 include/cache-p9.h
> 
> diff --git a/hw/Makefile.inc b/hw/Makefile.inc
> index b6727bdfc133..0c8a40367769 100644
> --- a/hw/Makefile.inc
> +++ b/hw/Makefile.inc
> @@ -7,7 +7,7 @@ HW_OBJS += phb3.o sfc-ctrl.o fake-rtc.o bt.o p8-i2c.o prd.o
>   HW_OBJS += dts.o lpc-rtc.o npu.o npu-hw-procedures.o xive.o phb4.o
>   HW_OBJS += fake-nvram.o lpc-mbox.o npu2.o npu2-hw-procedures.o
>   HW_OBJS += npu2-common.o npu2-opencapi.o phys-map.o sbe-p9.o capp.o
> -HW_OBJS += occ-sensor.o vas.o sbe-p8.o dio-p9.o lpc-port80h.o
> +HW_OBJS += occ-sensor.o vas.o sbe-p8.o dio-p9.o lpc-port80h.o cache-p9.o
>   HW=hw/built-in.a
>   
>   include $(SRC)/hw/fsp/Makefile.inc
> diff --git a/hw/cache-p9.c b/hw/cache-p9.c
> new file mode 100644
> index 000000000000..ea6f00bb5ee9
> --- /dev/null
> +++ b/hw/cache-p9.c
> @@ -0,0 +1,173 @@
> +/* Copyright 2019 IBM Corp.
> + *
> + * Licensed under the Apache License, Version 2.0 (the "License");
> + * you may not use this file except in compliance with the License.
> + * You may obtain a copy of the License at
> + *
> + *      http://www.apache.org/licenses/LICENSE-2.0
> + *
> + * Unless required by applicable law or agreed to in writing, software
> + * distributed under the License is distributed on an "AS IS" BASIS,
> + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
> + * implied.
> + * See the License for the specific language governing permissions and
> + * limitations under the License.
> + */
> +
> +#include <skiboot.h>
> +#include <chip.h>
> +#include <xscom.h>
> +#include <timebase.h>
> +#include <xscom-p9-regs.h>
> +#include <cache-p9.h>
> +
> +/* Registers and bits used to clear the L2 and L3 cache */
> +#define L2_PRD_PURGE_CMD_REG			0x1080e
> +#define   L2_PRD_PURGE_CMD_TRIGGER		PPC_BIT(0)
> +#define   L2_PRD_PURGE_CMD_TYPE_MASK		PPC_BITMASK(1, 4)
> +#define     L2CAC_FLUSH				0x0
> +#define   L2_PRD_PURGE_CMD_REG_BUSY		PPC_BIT(9)
> +#define L3_PRD_PURGE_REG			0x1180e
> +#define   L3_PRD_PURGE_REQ			PPC_BIT(0)
> +#define   L3_PRD_PURGE_TTYPE_MASK		PPC_BITMASK(1, 4)
> +#define     L3_FULL_PURGE			0x0
> +
> +#define L2_L3_PRD_PURGE_TIMEOUT_MS		20
> +
> +static int start_l2_purge(uint32_t chip_id, uint32_t core_id)
> +{
> +	uint64_t addr = XSCOM_ADDR_P9_EX(core_id, L2_PRD_PURGE_CMD_REG);
> +	int rc;
> +
> +	rc = xscom_write_mask(chip_id, addr, L2CAC_FLUSH,
> +			      L2_PRD_PURGE_CMD_TYPE_MASK);
> +	if (!rc)
> +		rc = xscom_write_mask(chip_id, addr, L2_PRD_PURGE_CMD_TRIGGER,
> +			      L2_PRD_PURGE_CMD_TRIGGER);
> +	if (rc)
> +		prlog(PR_ERR, "PURGE L2 on core 0x%x: XSCOM write_mask "
> +		      "failed %i\n", core_id, rc);
> +	return rc;
> +}
> +
> +static int wait_l2_purge(uint32_t chip_id, uint32_t core_id)
> +{
> +	uint64_t val;
> +	uint64_t addr = XSCOM_ADDR_P9_EX(core_id, L2_PRD_PURGE_CMD_REG);
> +	unsigned long now = mftb();
> +	unsigned long end = now + msecs_to_tb(L2_L3_PRD_PURGE_TIMEOUT_MS);
> +	int rc;
> +
> +	while (1) {
> +		rc = xscom_read(chip_id, addr, &val);
> +		if (rc) {
> +			prlog(PR_ERR, "PURGE L2 on core 0x%x: XSCOM read "
> +			      "failed %i\n", core_id, rc);
> +			break;
> +		}
> +		if (!(val & L2_PRD_PURGE_CMD_REG_BUSY))
> +			break;
> +		now = mftb();
> +		if (tb_compare(now, end) == TB_AAFTERB) {
> +			prlog(PR_ERR, "PURGE L2 on core 0x%x timed out %i\n",
> +			      core_id, rc);
> +			return OPAL_BUSY;
> +		}
> +	}
> +
> +	/* We have to clear the trigger bit ourselves */
> +	val &= ~L2_PRD_PURGE_CMD_TRIGGER;
> +	rc = xscom_write(chip_id, addr, val);
> +	if (rc)
> +		prlog(PR_ERR, "PURGE L2 on core 0x%x: XSCOM write failed %i\n",
> +		      core_id, rc);
> +	return rc;
> +}
> +
> +static int start_l3_purge(uint32_t chip_id, uint32_t core_id)
> +{
> +	uint64_t addr = XSCOM_ADDR_P9_EX(core_id, L3_PRD_PURGE_REG);
> +	int rc;
> +
> +	rc = xscom_write_mask(chip_id, addr, L3_FULL_PURGE,
> +			      L3_PRD_PURGE_TTYPE_MASK);
> +	if (!rc)
> +		rc = xscom_write_mask(chip_id, addr, L3_PRD_PURGE_REQ,
> +			      L3_PRD_PURGE_REQ);
> +	if (rc)
> +		prlog(PR_ERR, "PURGE L3 on core 0x%x: XSCOM write_mask "
> +		      "failed %i\n", core_id, rc);
> +	return rc;
> +}
> +
> +static int wait_l3_purge(uint32_t chip_id, uint32_t core_id)
> +{
> +	uint64_t val;
> +	uint64_t addr = XSCOM_ADDR_P9_EX(core_id, L3_PRD_PURGE_REG);
> +	unsigned long now = mftb();
> +	unsigned long end = now + msecs_to_tb(L2_L3_PRD_PURGE_TIMEOUT_MS);
> +	int rc;
> +
> +	/* Trigger bit is automatically set to zero when flushing is done */
> +	while (1) {
> +		rc = xscom_read(chip_id, addr, &val);
> +		if (rc) {
> +			prlog(PR_ERR, "PURGE L3 on core 0x%x: XSCOM read "
> +			      "failed %i\n", core_id, rc);
> +			break;
> +		}
> +		if (!(val & L3_PRD_PURGE_REQ))
> +			break;
> +		now = mftb();
> +		if (tb_compare(now, end) == TB_AAFTERB) {
> +			prlog(PR_ERR, "PURGE L3 on core 0x%x timed out %i\n",
> +			      core_id, rc);
> +			return OPAL_BUSY;
> +		}
> +	}
> +	return rc;
> +}
> +
> +int64_t purge_l2_l3_caches(void)
> +{
> +	struct cpu_thread *t;
> +	uint64_t core_id, prev_core_id = (uint64_t)-1;
> +	int rc;
> +	unsigned long now = mftb();
> +
> +	for_each_ungarded_cpu(t) {
> +		/* Only need to do it once per core chiplet */
> +		core_id = pir_to_core_id(t->pir);
> +		if (prev_core_id == core_id)
> +			continue;
> +		prev_core_id = core_id;
> +		rc = start_l2_purge(t->chip_id, core_id);
> +		if (rc)
> +			goto trace_exit;
> +		rc = start_l3_purge(t->chip_id, core_id);
> +		if (rc)
> +			goto trace_exit;
> +	}
> +
> +	prev_core_id = (uint64_t)-1;
> +	for_each_ungarded_cpu(t) {
> +		/* Only need to do it once per core chiplet */
> +		core_id = pir_to_core_id(t->pir);
> +		if (prev_core_id == core_id)
> +			continue;
> +		prev_core_id = core_id;
> +
> +		rc = wait_l2_purge(t->chip_id, core_id);
> +		if (rc)
> +			goto trace_exit;
> +		rc = wait_l3_purge(t->chip_id, core_id);
> +		if (rc)
> +			goto trace_exit;
> +	}
> +
> +trace_exit:
> +	prlog(PR_TRACE, "L2/L3 purging took %ldus\n",
> +			tb_to_usecs(mftb() - now));
> +
> +	return rc;
> +}
> diff --git a/hw/npu2.c b/hw/npu2.c
> index e8ec5cc9a43d..23e6157aefdf 100644
> --- a/hw/npu2.c
> +++ b/hw/npu2.c
> @@ -36,6 +36,7 @@
>   #include <nvram.h>
>   #include <xscom-p9-regs.h>
>   #include <phb4.h>
> +#include <cache-p9.h>
>   
>   #define VENDOR_CAP_START    0x80
>   #define VENDOR_CAP_END      0x90
> @@ -315,144 +316,6 @@ static int64_t npu2_dev_cfg_bar(void *dev, struct pci_cfg_reg_filter *pcrf,
>   	return npu2_cfg_read_bar(ndev, pcrf, offset, len, data);
>   }
>   
> -static int start_l2_purge(uint32_t chip_id, uint32_t core_id)
> -{
> -	uint64_t addr = XSCOM_ADDR_P9_EX(core_id, L2_PRD_PURGE_CMD_REG);
> -	int rc;
> -
> -	rc = xscom_write_mask(chip_id, addr, L2CAC_FLUSH,
> -			      L2_PRD_PURGE_CMD_TYPE_MASK);
> -	if (!rc)
> -		rc = xscom_write_mask(chip_id, addr, L2_PRD_PURGE_CMD_TRIGGER,
> -			      L2_PRD_PURGE_CMD_TRIGGER);
> -	if (rc)
> -		prlog(PR_ERR, "PURGE L2 on core 0x%x: XSCOM write_mask "
> -		      "failed %i\n", core_id, rc);
> -	return rc;
> -}
> -
> -static int wait_l2_purge(uint32_t chip_id, uint32_t core_id)
> -{
> -	uint64_t val;
> -	uint64_t addr = XSCOM_ADDR_P9_EX(core_id, L2_PRD_PURGE_CMD_REG);
> -	unsigned long now = mftb();
> -	unsigned long end = now + msecs_to_tb(L2_L3_PRD_PURGE_TIMEOUT_MS);
> -	int rc;
> -
> -	while (1) {
> -		rc = xscom_read(chip_id, addr, &val);
> -		if (rc) {
> -			prlog(PR_ERR, "PURGE L2 on core 0x%x: XSCOM read "
> -			      "failed %i\n", core_id, rc);
> -			break;
> -		}
> -		if (!(val & L2_PRD_PURGE_CMD_REG_BUSY))
> -			break;
> -		now = mftb();
> -		if (tb_compare(now, end) == TB_AAFTERB) {
> -			prlog(PR_ERR, "PURGE L2 on core 0x%x timed out %i\n",
> -			      core_id, rc);
> -			return OPAL_BUSY;
> -		}
> -	}
> -
> -	/* We have to clear the trigger bit ourselves */
> -	val &= ~L2_PRD_PURGE_CMD_TRIGGER;
> -	rc = xscom_write(chip_id, addr, val);
> -	if (rc)
> -		prlog(PR_ERR, "PURGE L2 on core 0x%x: XSCOM write failed %i\n",
> -		      core_id, rc);
> -	return rc;
> -}
> -
> -static int start_l3_purge(uint32_t chip_id, uint32_t core_id)
> -{
> -	uint64_t addr = XSCOM_ADDR_P9_EX(core_id, L3_PRD_PURGE_REG);
> -	int rc;
> -
> -	rc = xscom_write_mask(chip_id, addr, L3_FULL_PURGE,
> -			      L3_PRD_PURGE_TTYPE_MASK);
> -	if (!rc)
> -		rc = xscom_write_mask(chip_id, addr, L3_PRD_PURGE_REQ,
> -			      L3_PRD_PURGE_REQ);
> -	if (rc)
> -		prlog(PR_ERR, "PURGE L3 on core 0x%x: XSCOM write_mask "
> -		      "failed %i\n", core_id, rc);
> -	return rc;
> -}
> -
> -static int wait_l3_purge(uint32_t chip_id, uint32_t core_id)
> -{
> -	uint64_t val;
> -	uint64_t addr = XSCOM_ADDR_P9_EX(core_id, L3_PRD_PURGE_REG);
> -	unsigned long now = mftb();
> -	unsigned long end = now + msecs_to_tb(L2_L3_PRD_PURGE_TIMEOUT_MS);
> -	int rc;
> -
> -	/* Trigger bit is automatically set to zero when flushing is done */
> -	while (1) {
> -		rc = xscom_read(chip_id, addr, &val);
> -		if (rc) {
> -			prlog(PR_ERR, "PURGE L3 on core 0x%x: XSCOM read "
> -			      "failed %i\n", core_id, rc);
> -			break;
> -		}
> -		if (!(val & L3_PRD_PURGE_REQ))
> -			break;
> -		now = mftb();
> -		if (tb_compare(now, end) == TB_AAFTERB) {
> -			prlog(PR_ERR, "PURGE L3 on core 0x%x timed out %i\n",
> -			      core_id, rc);
> -			return OPAL_BUSY;
> -		}
> -	}
> -	return rc;
> -}
> -
> -static int64_t purge_l2_l3_caches(void)
> -{
> -	struct cpu_thread *t;
> -	uint64_t core_id, prev_core_id = (uint64_t)-1;
> -	int rc;
> -	unsigned long now = mftb();
> -
> -	for_each_ungarded_cpu(t) {
> -		/* Only need to do it once per core chiplet */
> -		core_id = pir_to_core_id(t->pir);
> -		if (prev_core_id == core_id)
> -			continue;
> -		prev_core_id = core_id;
> -		rc = start_l2_purge(t->chip_id, core_id);
> -		if (rc)
> -			goto trace_exit;
> -		rc = start_l3_purge(t->chip_id, core_id);
> -		if (rc)
> -			goto trace_exit;
> -	}
> -
> -	prev_core_id = (uint64_t)-1;
> -	for_each_ungarded_cpu(t) {
> -		/* Only need to do it once per core chiplet */
> -		core_id = pir_to_core_id(t->pir);
> -		if (prev_core_id == core_id)
> -			continue;
> -		prev_core_id = core_id;
> -
> -		rc = wait_l2_purge(t->chip_id, core_id);
> -		if (rc)
> -			goto trace_exit;
> -		rc = wait_l3_purge(t->chip_id, core_id);
> -		if (rc)
> -			goto trace_exit;
> -	}
> -
> -trace_exit:
> -	prlog(PR_TRACE, "L2/L3 purging took %ldus\n",
> -			tb_to_usecs(mftb() - now));
> -
> -	return rc;
> -}
> -
>   static int64_t npu2_dev_cfg_exp_devcap(void *dev,
>   		struct pci_cfg_reg_filter *pcrf __unused,
>   		uint32_t offset, uint32_t size,
> diff --git a/include/cache-p9.h b/include/cache-p9.h
> new file mode 100644
> index 000000000000..e763433b6b4e
> --- /dev/null
> +++ b/include/cache-p9.h
> @@ -0,0 +1,22 @@
> +/* Copyright 2019 IBM Corp.
> + *
> + * Licensed under the Apache License, Version 2.0 (the "License");
> + * you may not use this file except in compliance with the License.
> + * You may obtain a copy of the License at
> + *
> + * 	http://www.apache.org/licenses/LICENSE-2.0
> + *
> + * Unless required by applicable law or agreed to in writing, software
> + * distributed under the License is distributed on an "AS IS" BASIS,
> + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
> + * implied.
> + * See the License for the specific language governing permissions and
> + * limitations under the License.
> + */
> +
> +#ifndef __CACHE_P9_H
> +#define __CACHE_P9_H
> +
> +int64_t purge_l2_l3_caches(void);
> +
> +#endif
> diff --git a/include/npu2-regs.h b/include/npu2-regs.h
> index 00a72e685b6e..ba2abe1e0cf2 100644
> --- a/include/npu2-regs.h
> +++ b/include/npu2-regs.h
> @@ -787,19 +787,6 @@ void npu2_scom_write(uint64_t gcid, uint64_t scom_base,
>   #define OB_ODL_ENDPOINT_INFO(brick_index)		\
>   	(0x9010832 + OB_ODL_OFFSET(brick_index))
>   
> -/* Registers and bits used to clear the L2 and L3 cache */
> -#define L2_PRD_PURGE_CMD_REG 			0x1080E
> -#define L2_PRD_PURGE_CMD_REG_BUSY 		0x0040000000000000UL
> -#define L2_PRD_PURGE_CMD_TYPE_MASK		PPC_BIT(1) | PPC_BIT(2) | PPC_BIT(3) | PPC_BIT(4)
> -#define L2_PRD_PURGE_CMD_TRIGGER		PPC_BIT(0)
> -#define L2CAC_FLUSH				0x0
> -#define L3_PRD_PURGE_REG			0x1180E
> -#define L3_PRD_PURGE_REQ			PPC_BIT(0)
> -#define L3_PRD_PURGE_TTYPE_MASK 		PPC_BIT(1) | PPC_BIT(2) | PPC_BIT(3) | PPC_BIT(4)
> -#define L3_FULL_PURGE				0x0
> -
> -#define L2_L3_PRD_PURGE_TIMEOUT_MS		20
> -
>   /* Config registers for NPU2 */
>   #define NPU_STCK0_CS_SM0_MISC_CONFIG0		0x5011000
>   #define NPU_STCK0_CS_SM1_MISC_CONFIG0		0x5011030
> 

-- 
Alexey


More information about the Skiboot mailing list