LCOV - code coverage report
Current view: top level - drivers/gpu/drm/i915/gt/uc - intel_huc.c (source / functions) Hit Total Coverage
Test: combined.info Lines: 0 83 0.0 %
Date: 2022-04-01 14:17:54 Functions: 0 6 0.0 %
Branches: 0 26 0.0 %

           Branch data     Line data    Source code
       1                 :            : // SPDX-License-Identifier: MIT
       2                 :            : /*
       3                 :            :  * Copyright © 2016-2019 Intel Corporation
       4                 :            :  */
       5                 :            : 
       6                 :            : #include <linux/types.h>
       7                 :            : 
       8                 :            : #include "gt/intel_gt.h"
       9                 :            : #include "intel_huc.h"
      10                 :            : #include "i915_drv.h"
      11                 :            : 
      12                 :            : /**
      13                 :            :  * DOC: HuC
      14                 :            :  *
      15                 :            :  * The HuC is a dedicated microcontroller for usage in media HEVC (High
      16                 :            :  * Efficiency Video Coding) operations. Userspace can directly use the firmware
      17                 :            :  * capabilities by adding HuC specific commands to batch buffers.
      18                 :            :  *
      19                 :            :  * The kernel driver is only responsible for loading the HuC firmware and
      20                 :            :  * triggering its security authentication, which is performed by the GuC. For
      21                 :            :  * The GuC to correctly perform the authentication, the HuC binary must be
      22                 :            :  * loaded before the GuC one. Loading the HuC is optional; however, not using
      23                 :            :  * the HuC might negatively impact power usage and/or performance of media
      24                 :            :  * workloads, depending on the use-cases.
      25                 :            :  *
      26                 :            :  * See https://github.com/intel/media-driver for the latest details on HuC
      27                 :            :  * functionality.
      28                 :            :  */
      29                 :            : 
      30                 :            : /**
      31                 :            :  * DOC: HuC Memory Management
      32                 :            :  *
      33                 :            :  * Similarly to the GuC, the HuC can't do any memory allocations on its own,
      34                 :            :  * with the difference being that the allocations for HuC usage are handled by
      35                 :            :  * the userspace driver instead of the kernel one. The HuC accesses the memory
      36                 :            :  * via the PPGTT belonging to the context loaded on the VCS executing the
      37                 :            :  * HuC-specific commands.
      38                 :            :  */
      39                 :            : 
      40                 :          0 : void intel_huc_init_early(struct intel_huc *huc)
      41                 :            : {
      42                 :          0 :         struct drm_i915_private *i915 = huc_to_gt(huc)->i915;
      43                 :            : 
      44                 :          0 :         intel_huc_fw_init_early(huc);
      45                 :            : 
      46         [ #  # ]:          0 :         if (INTEL_GEN(i915) >= 11) {
      47                 :          0 :                 huc->status.reg = GEN11_HUC_KERNEL_LOAD_INFO;
      48                 :          0 :                 huc->status.mask = HUC_LOAD_SUCCESSFUL;
      49                 :          0 :                 huc->status.value = HUC_LOAD_SUCCESSFUL;
      50                 :            :         } else {
      51                 :          0 :                 huc->status.reg = HUC_STATUS2;
      52                 :          0 :                 huc->status.mask = HUC_FW_VERIFIED;
      53                 :          0 :                 huc->status.value = HUC_FW_VERIFIED;
      54                 :            :         }
      55                 :          0 : }
      56                 :            : 
      57                 :          0 : static int intel_huc_rsa_data_create(struct intel_huc *huc)
      58                 :            : {
      59                 :          0 :         struct intel_gt *gt = huc_to_gt(huc);
      60                 :          0 :         struct intel_guc *guc = &gt->uc.guc;
      61                 :          0 :         struct i915_vma *vma;
      62                 :          0 :         size_t copied;
      63                 :          0 :         void *vaddr;
      64                 :          0 :         int err;
      65                 :            : 
      66                 :          0 :         err = i915_inject_probe_error(gt->i915, -ENXIO);
      67                 :          0 :         if (err)
      68                 :            :                 return err;
      69                 :            : 
      70                 :            :         /*
      71                 :            :          * HuC firmware will sit above GUC_GGTT_TOP and will not map
      72                 :            :          * through GTT. Unfortunately, this means GuC cannot perform
      73                 :            :          * the HuC auth. as the rsa offset now falls within the GuC
      74                 :            :          * inaccessible range. We resort to perma-pinning an additional
      75                 :            :          * vma within the accessible range that only contains the rsa
      76                 :            :          * signature. The GuC can use this extra pinning to perform
      77                 :            :          * the authentication since its GGTT offset will be GuC
      78                 :            :          * accessible.
      79                 :            :          */
      80                 :          0 :         GEM_BUG_ON(huc->fw.rsa_size > PAGE_SIZE);
      81                 :          0 :         vma = intel_guc_allocate_vma(guc, PAGE_SIZE);
      82         [ #  # ]:          0 :         if (IS_ERR(vma))
      83                 :          0 :                 return PTR_ERR(vma);
      84                 :            : 
      85                 :          0 :         vaddr = i915_gem_object_pin_map(vma->obj, I915_MAP_WB);
      86         [ #  # ]:          0 :         if (IS_ERR(vaddr)) {
      87                 :          0 :                 i915_vma_unpin_and_release(&vma, 0);
      88                 :          0 :                 return PTR_ERR(vaddr);
      89                 :            :         }
      90                 :            : 
      91                 :          0 :         copied = intel_uc_fw_copy_rsa(&huc->fw, vaddr, vma->size);
      92                 :          0 :         GEM_BUG_ON(copied < huc->fw.rsa_size);
      93                 :            : 
      94                 :          0 :         i915_gem_object_unpin_map(vma->obj);
      95                 :            : 
      96                 :          0 :         huc->rsa_data = vma;
      97                 :            : 
      98                 :          0 :         return 0;
      99                 :            : }
     100                 :            : 
     101                 :          0 : static void intel_huc_rsa_data_destroy(struct intel_huc *huc)
     102                 :            : {
     103                 :          0 :         i915_vma_unpin_and_release(&huc->rsa_data, 0);
     104                 :            : }
     105                 :            : 
     106                 :          0 : int intel_huc_init(struct intel_huc *huc)
     107                 :            : {
     108                 :          0 :         struct drm_i915_private *i915 = huc_to_gt(huc)->i915;
     109                 :          0 :         int err;
     110                 :            : 
     111                 :          0 :         err = intel_uc_fw_init(&huc->fw);
     112         [ #  # ]:          0 :         if (err)
     113                 :          0 :                 goto out;
     114                 :            : 
     115                 :            :         /*
     116                 :            :          * HuC firmware image is outside GuC accessible range.
     117                 :            :          * Copy the RSA signature out of the image into
     118                 :            :          * a perma-pinned region set aside for it
     119                 :            :          */
     120                 :          0 :         err = intel_huc_rsa_data_create(huc);
     121         [ #  # ]:          0 :         if (err)
     122                 :          0 :                 goto out_fini;
     123                 :            : 
     124                 :            :         return 0;
     125                 :            : 
     126                 :            : out_fini:
     127                 :          0 :         intel_uc_fw_fini(&huc->fw);
     128                 :          0 : out:
     129                 :          0 :         intel_uc_fw_cleanup_fetch(&huc->fw);
     130                 :          0 :         DRM_DEV_DEBUG_DRIVER(i915->drm.dev, "failed with %d\n", err);
     131                 :          0 :         return err;
     132                 :            : }
     133                 :            : 
     134                 :          0 : void intel_huc_fini(struct intel_huc *huc)
     135                 :            : {
     136         [ #  # ]:          0 :         if (!intel_uc_fw_is_available(&huc->fw))
     137                 :            :                 return;
     138                 :            : 
     139                 :          0 :         intel_huc_rsa_data_destroy(huc);
     140                 :          0 :         intel_uc_fw_fini(&huc->fw);
     141                 :            : }
     142                 :            : 
     143                 :            : /**
     144                 :            :  * intel_huc_auth() - Authenticate HuC uCode
     145                 :            :  * @huc: intel_huc structure
     146                 :            :  *
     147                 :            :  * Called after HuC and GuC firmware loading during intel_uc_init_hw().
     148                 :            :  *
     149                 :            :  * This function invokes the GuC action to authenticate the HuC firmware,
     150                 :            :  * passing the offset of the RSA signature to intel_guc_auth_huc(). It then
     151                 :            :  * waits for up to 50ms for firmware verification ACK.
     152                 :            :  */
     153                 :          0 : int intel_huc_auth(struct intel_huc *huc)
     154                 :            : {
     155         [ #  # ]:          0 :         struct intel_gt *gt = huc_to_gt(huc);
     156                 :          0 :         struct intel_guc *guc = &gt->uc.guc;
     157                 :          0 :         int ret;
     158                 :            : 
     159                 :          0 :         GEM_BUG_ON(intel_huc_is_authenticated(huc));
     160                 :            : 
     161         [ #  # ]:          0 :         if (!intel_uc_fw_is_loaded(&huc->fw))
     162                 :            :                 return -ENOEXEC;
     163                 :            : 
     164                 :          0 :         ret = i915_inject_probe_error(gt->i915, -ENXIO);
     165                 :          0 :         if (ret)
     166                 :            :                 goto fail;
     167                 :            : 
     168                 :          0 :         ret = intel_guc_auth_huc(guc,
     169                 :            :                                  intel_guc_ggtt_offset(guc, huc->rsa_data));
     170         [ #  # ]:          0 :         if (ret) {
     171                 :          0 :                 DRM_ERROR("HuC: GuC did not ack Auth request %d\n", ret);
     172                 :          0 :                 goto fail;
     173                 :            :         }
     174                 :            : 
     175                 :            :         /* Check authentication status, it should be done by now */
     176                 :          0 :         ret = __intel_wait_for_register(gt->uncore,
     177                 :            :                                         huc->status.reg,
     178                 :            :                                         huc->status.mask,
     179                 :            :                                         huc->status.value,
     180                 :            :                                         2, 50, NULL);
     181         [ #  # ]:          0 :         if (ret) {
     182                 :          0 :                 DRM_ERROR("HuC: Firmware not verified %d\n", ret);
     183                 :          0 :                 goto fail;
     184                 :            :         }
     185                 :            : 
     186                 :          0 :         intel_uc_fw_change_status(&huc->fw, INTEL_UC_FIRMWARE_RUNNING);
     187                 :          0 :         return 0;
     188                 :            : 
     189                 :          0 : fail:
     190                 :          0 :         i915_probe_error(gt->i915, "HuC: Authentication failed %d\n", ret);
     191                 :          0 :         intel_uc_fw_change_status(&huc->fw, INTEL_UC_FIRMWARE_FAIL);
     192                 :          0 :         return ret;
     193                 :            : }
     194                 :            : 
     195                 :            : /**
     196                 :            :  * intel_huc_check_status() - check HuC status
     197                 :            :  * @huc: intel_huc structure
     198                 :            :  *
     199                 :            :  * This function reads status register to verify if HuC
     200                 :            :  * firmware was successfully loaded.
     201                 :            :  *
     202                 :            :  * Returns: 1 if HuC firmware is loaded and verified,
     203                 :            :  * 0 if HuC firmware is not loaded and -ENODEV if HuC
     204                 :            :  * is not present on this platform.
     205                 :            :  */
     206                 :          0 : int intel_huc_check_status(struct intel_huc *huc)
     207                 :            : {
     208         [ #  # ]:          0 :         struct intel_gt *gt = huc_to_gt(huc);
     209                 :          0 :         intel_wakeref_t wakeref;
     210                 :          0 :         u32 status = 0;
     211                 :            : 
     212         [ #  # ]:          0 :         if (!intel_huc_is_supported(huc))
     213                 :            :                 return -ENODEV;
     214                 :            : 
     215         [ #  # ]:          0 :         with_intel_runtime_pm(gt->uncore->rpm, wakeref)
     216                 :          0 :                 status = intel_uncore_read(gt->uncore, huc->status.reg);
     217                 :            : 
     218                 :          0 :         return (status & huc->status.mask) == huc->status.value;
     219                 :            : }

Generated by: LCOV version 1.14