[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