habanalabs/gaudi: disable GIC usage if security is enabled
authorKoby Elbaz <kelbaz@habana.ai>
Tue, 18 May 2021 12:43:47 +0000 (15:43 +0300)
committerOded Gabbay <ogabbay@kernel.org>
Fri, 18 Jun 2021 12:23:40 +0000 (15:23 +0300)
Security is set based on PCI ID, and after reading preboot status bits.
GIC usage is set in both scenarios since GIC can't be used when security
is enabled.
Moreover, writing to GIC/SP is enabled only after Linux is fully loaded.

Signed-off-by: Koby Elbaz <kelbaz@habana.ai>
Reviewed-by: Oded Gabbay <ogabbay@kernel.org>
Signed-off-by: Oded Gabbay <ogabbay@kernel.org>
drivers/misc/habanalabs/common/firmware_if.c
drivers/misc/habanalabs/common/habanalabs.h
drivers/misc/habanalabs/gaudi/gaudi.c

index cdec7212f3775de9a11a8b3bcfcf047bf3f86fbd..399d64e4f4c237fc03f08c22d982a291a0a39f68 100644 (file)
@@ -1115,19 +1115,13 @@ static void hl_fw_preboot_update_state(struct hl_device *hdev)
         *                     b. Check whether hard reset is done by fw app
         *
         * Preboot:
-        * Check security status bit (CPU_BOOT_DEV_STS0_ENABLED), if it is set
+        * Check security status bit (CPU_BOOT_DEV_STS0_ENABLED). If set, then-
         * check security enabled bit (CPU_BOOT_DEV_STS0_SECURITY_EN)
-        * Check GIC privileged bit (CPU_BOOT_DEV_STS0_GIC_PRIVILEGED_EN)
+        * If set, then mark GIC controller to be disabled.
         */
        if (cpu_boot_dev_sts0 & CPU_BOOT_DEV_STS0_ENABLED) {
                prop->fw_cpu_boot_dev_sts0_valid = 1;
 
-               /* FW security should be derived from PCI ID, we keep this
-                * check for backward compatibility
-                */
-               if (cpu_boot_dev_sts0 & CPU_BOOT_DEV_STS0_SECURITY_EN)
-                       prop->fw_security_disabled = false;
-
                if (cpu_boot_dev_sts0 & CPU_BOOT_DEV_STS0_FW_HARD_RST_EN)
                        prop->hard_reset_done_by_fw = true;
        } else {
@@ -1149,6 +1143,9 @@ static void hl_fw_preboot_update_state(struct hl_device *hdev)
 
        dev_dbg(hdev->dev, "firmware-level security is %s\n",
                        prop->fw_security_disabled ? "disabled" : "enabled");
+
+       dev_dbg(hdev->dev, "GIC controller is %s\n",
+                       prop->gic_interrupts_enable ? "enabled" : "disabled");
 }
 
 static int hl_fw_static_read_preboot_status(struct hl_device *hdev)
@@ -1941,9 +1938,13 @@ static int hl_fw_dynamic_wait_for_linux_active(struct hl_device *hdev,
 }
 
 /**
- * hl_fw_linux_update_state - update internal data structures after loading
- *                            Linux
- *
+ * hl_fw_linux_update_state -  update internal data structures after Linux
+ *                             is loaded.
+ *                             Note: Linux initialization is comprised mainly
+ *                             of two stages - loading kernel (SRAM_AVAIL)
+ *                             & loading ARMCP.
+ *                             Therefore reading boot device status in any of
+ *                             these stages might result in different values.
  *
  * @hdev: pointer to the habanalabs device structure
  * @cpu_boot_dev_sts0_reg: register holding CPU boot dev status 0
@@ -1957,6 +1958,8 @@ static void hl_fw_linux_update_state(struct hl_device *hdev,
 {
        struct asic_fixed_properties *prop = &hdev->asic_prop;
 
+       hdev->fw_loader.linux_loaded = true;
+
        /* Clear reset status since we need to read again from app */
        prop->hard_reset_done_by_fw = false;
 
index c3f41f0b609f23a6e8659d6303bdc31af7178b62..433262bfb7e6be9a8f903c7740a4589cab53a2b3 100644 (file)
@@ -956,6 +956,7 @@ struct fw_image_props {
  * @skip_bmc: should BMC be skipped
  * @sram_bar_id: SRAM bar ID
  * @dram_bar_id: DRAM bar ID
+ * @linux_loaded: true if linux was loaded so far
  */
 struct fw_load_mgr {
        union {
@@ -969,6 +970,7 @@ struct fw_load_mgr {
        u8 skip_bmc;
        u8 sram_bar_id;
        u8 dram_bar_id;
+       u8 linux_loaded;
 };
 
 /**
index 1fa12394e3b6e5b6cbd2b17c6636163c078a5851..4249dffdb7f7a177cf1c9e97344643cd5cc3ae85 100644 (file)
@@ -689,6 +689,12 @@ static int gaudi_early_init(struct hl_device *hdev)
        /* If FW security is enabled at this point it means no access to ELBI */
        if (!hdev->asic_prop.fw_security_disabled) {
                hdev->asic_prop.iatu_done_by_fw = true;
+
+               /*
+                * GIC-security-bit can ONLY be set by CPUCP, so in this stage
+                * decision can only be taken based on PCI ID security.
+                */
+               hdev->asic_prop.gic_interrupts_enable = false;
                goto pci_init;
        }
 
@@ -3829,6 +3835,7 @@ static void gaudi_init_firmware_loader(struct hl_device *hdev)
        struct fw_load_mgr *fw_loader = &hdev->fw_loader;
 
        /* fill common fields */
+       fw_loader->linux_loaded = false;
        fw_loader->boot_fit_img.image_name = GAUDI_BOOT_FIT_FILE;
        fw_loader->linux_img.image_name = GAUDI_LINUX_FW_FILE;
        fw_loader->cpu_timeout = GAUDI_CPU_TIMEOUT_USEC;
@@ -4103,11 +4110,13 @@ static void gaudi_hw_fini(struct hl_device *hdev, bool hard_reset)
        else
                WREG32(mmPSOC_GLOBAL_CONF_KMD_MSG_TO_CPU, KMD_MSG_GOTO_WFE);
 
-       irq_handler_offset = hdev->asic_prop.gic_interrupts_enable ?
-                       mmGIC_DISTRIBUTOR__5_GICD_SETSPI_NSR :
-                       le32_to_cpu(dyn_regs->gic_host_irq_ctrl);
+       if (hdev->fw_loader.linux_loaded) {
+               irq_handler_offset = hdev->asic_prop.gic_interrupts_enable ?
+                               mmGIC_DISTRIBUTOR__5_GICD_SETSPI_NSR :
+                               le32_to_cpu(dyn_regs->gic_host_irq_ctrl);
 
-       WREG32(irq_handler_offset, GAUDI_EVENT_HALT_MACHINE);
+               WREG32(irq_handler_offset, GAUDI_EVENT_HALT_MACHINE);
+       }
 
        if (hdev->asic_prop.fw_security_disabled &&
                                !hdev->asic_prop.hard_reset_done_by_fw) {