Applied to drm-misc-next

On 9/25/2025 8:30 PM, Lizhi Hou wrote:
> Reviewed-by: Lizhi Hou <lizhi....@amd.com>
>
> On 9/25/25 00:42, Karol Wachowski wrote:
>> Split firmware boot parameters (4KB) and FW version (4KB) into dedicated
>> buffer objects, separating them from the FW runtime memory buffer. This
>> creates three distinct buffers with independent allocation control.
>>
>> This enables future modifications, particularly allowing the FW
>> image memory to be moved into a read-only buffer.
>>
>> Fix user range starting address from incorrect 0x88000000 (2GB + 128MB)
>> overlapping global aperture on 37XX to intended 0xa0000000 (2GB +
>> 512MB).
>> This caused no issues as FW aligned this range to 512MB anyway, but
>> corrected for consistency.
>>
>> Convert ivpu_hw_range_init() from inline helper to function with
>> overflow
>> validation to prevent potential security issues from address range
>> arithmetic overflows.
>>
>> Improve readability of ivpu_fw_parse() function, remove unrelated
>> constant
>> defines and validate firmware header values based on vdev->hw->ranges.
>>
>> Signed-off-by: Karol Wachowski <karol.wachow...@linux.intel.com>
>> Link:
>> https://lore.kernel.org/r/20250923111855.1112087-1-karol.wachow...@linux.intel.com
>> ---
>> Changes between v1 and v2:
>> Apply review suggestions:
>> - Use ivpu_hw_range_init() to initialize fw_image_range in
>> ivpu_fw_parse()
>> - Ensure FW entry point is at least 4K before the end of the image
>> ---
>>   drivers/accel/ivpu/ivpu_drv.c         |   3 +-
>>   drivers/accel/ivpu/ivpu_fw.c          | 151 ++++++++++++++++----------
>>   drivers/accel/ivpu/ivpu_fw.h          |   7 ++
>>   drivers/accel/ivpu/ivpu_gem.c         |  16 +++
>>   drivers/accel/ivpu/ivpu_gem.h         |   1 +
>>   drivers/accel/ivpu/ivpu_hw.c          |  36 ++++--
>>   drivers/accel/ivpu/ivpu_hw.h          |   9 +-
>>   drivers/accel/ivpu/ivpu_mmu_context.c |   2 +-
>>   drivers/accel/ivpu/ivpu_pm.c          |   2 +-
>>   9 files changed, 152 insertions(+), 75 deletions(-)
>>
>> diff --git a/drivers/accel/ivpu/ivpu_drv.c
>> b/drivers/accel/ivpu/ivpu_drv.c
>> index a08f99c3ba4a..1792d0bbec71 100644
>> --- a/drivers/accel/ivpu/ivpu_drv.c
>> +++ b/drivers/accel/ivpu/ivpu_drv.c
>> @@ -380,8 +380,7 @@ int ivpu_boot(struct ivpu_device *vdev)
>>       drm_WARN_ON(&vdev->drm, atomic_read(&vdev->job_timeout_counter));
>>       drm_WARN_ON(&vdev->drm, !xa_empty(&vdev->submitted_jobs_xa));
>>   -    /* Update boot params located at first 4KB of FW memory */
>> -    ivpu_fw_boot_params_setup(vdev, ivpu_bo_vaddr(vdev->fw->mem));
>> +    ivpu_fw_boot_params_setup(vdev, ivpu_bo_vaddr(vdev->fw->mem_bp));
>>         ret = ivpu_hw_boot_fw(vdev);
>>       if (ret) {
>> diff --git a/drivers/accel/ivpu/ivpu_fw.c b/drivers/accel/ivpu/ivpu_fw.c
>> index 32f513499829..b81bd143a285 100644
>> --- a/drivers/accel/ivpu/ivpu_fw.c
>> +++ b/drivers/accel/ivpu/ivpu_fw.c
>> @@ -17,14 +17,7 @@
>>   #include "ivpu_ipc.h"
>>   #include "ivpu_pm.h"
>>   -#define FW_GLOBAL_MEM_START    (2ull * SZ_1G)
>> -#define FW_GLOBAL_MEM_END    (3ull * SZ_1G)
>> -#define FW_SHARED_MEM_SIZE    SZ_256M /* Must be aligned to
>> FW_SHARED_MEM_ALIGNMENT */
>> -#define FW_SHARED_MEM_ALIGNMENT    SZ_128K /* VPU MTRR limitation */
>> -#define FW_RUNTIME_MAX_SIZE    SZ_512M
>>   #define FW_SHAVE_NN_MAX_SIZE    SZ_2M
>> -#define FW_RUNTIME_MIN_ADDR    (FW_GLOBAL_MEM_START)
>> -#define FW_RUNTIME_MAX_ADDR    (FW_GLOBAL_MEM_END - FW_SHARED_MEM_SIZE)
>>   #define FW_FILE_IMAGE_OFFSET    (VPU_FW_HEADER_SIZE +
>> FW_VERSION_HEADER_SIZE)
>>   #define FW_PREEMPT_BUF_MIN_SIZE SZ_4K
>>   #define FW_PREEMPT_BUF_MAX_SIZE SZ_32M
>> @@ -133,9 +126,14 @@ ivpu_fw_check_api_ver_lt(struct ivpu_device
>> *vdev, const struct vpu_firmware_hea
>>       return false;
>>   }
>>   -static bool is_within_range(u64 addr, size_t size, u64
>> range_start, size_t range_size)
>> +bool ivpu_is_within_range(u64 addr, size_t size, struct
>> ivpu_addr_range *range)
>>   {
>> -    if (addr < range_start || addr + size > range_start + range_size)
>> +    u64 addr_end;
>> +
>> +    if (!range || check_add_overflow(addr, size, &addr_end))
>> +        return false;
>> +
>> +    if (addr < range->start || addr_end > range->end)
>>           return false;
>>         return true;
>> @@ -198,7 +196,11 @@ static int ivpu_fw_parse(struct ivpu_device *vdev)
>>   {
>>       struct ivpu_fw_info *fw = vdev->fw;
>>       const struct vpu_firmware_header *fw_hdr = (const void
>> *)fw->file->data;
>> -    u64 runtime_addr, image_load_addr, runtime_size, image_size;
>> +    struct ivpu_addr_range fw_image_range;
>> +    u64 boot_params_addr, boot_params_size;
>> +    u64 fw_version_addr, fw_version_size;
>> +    u64 runtime_addr, runtime_size;
>> +    u64 image_load_addr, image_size;
>>         if (fw->file->size <= FW_FILE_IMAGE_OFFSET) {
>>           ivpu_err(vdev, "Firmware file is too small: %zu\n",
>> fw->file->size);
>> @@ -210,18 +212,37 @@ static int ivpu_fw_parse(struct ivpu_device *vdev)
>>           return -EINVAL;
>>       }
>>   -    runtime_addr = fw_hdr->boot_params_load_address;
>> -    runtime_size = fw_hdr->runtime_size;
>> -    image_load_addr = fw_hdr->image_load_address;
>> -    image_size = fw_hdr->image_size;
>> +    boot_params_addr = fw_hdr->boot_params_load_address;
>> +    boot_params_size = SZ_4K;
>> +
>> +    if (!ivpu_is_within_range(boot_params_addr, boot_params_size,
>> &vdev->hw->ranges.runtime)) {
>> +        ivpu_err(vdev, "Invalid boot params address: 0x%llx\n",
>> boot_params_addr);
>> +        return -EINVAL;
>> +    }
>> +
>> +    fw_version_addr = fw_hdr->firmware_version_load_address;
>> +    fw_version_size = ALIGN(fw_hdr->firmware_version_size, SZ_4K);
>> +
>> +    if (fw_version_size != SZ_4K) {
>> +        ivpu_err(vdev, "Invalid firmware version size: %u\n",
>> +             fw_hdr->firmware_version_size);
>> +        return -EINVAL;
>> +    }
>>   -    if (runtime_addr < FW_RUNTIME_MIN_ADDR || runtime_addr >
>> FW_RUNTIME_MAX_ADDR) {
>> -        ivpu_err(vdev, "Invalid firmware runtime address: 0x%llx\n",
>> runtime_addr);
>> +    if (!ivpu_is_within_range(fw_version_addr, fw_version_size,
>> &vdev->hw->ranges.runtime)) {
>> +        ivpu_err(vdev, "Invalid firmware version address: 0x%llx\n",
>> fw_version_addr);
>>           return -EINVAL;
>>       }
>>   -    if (runtime_size < fw->file->size || runtime_size >
>> FW_RUNTIME_MAX_SIZE) {
>> -        ivpu_err(vdev, "Invalid firmware runtime size: %llu\n",
>> runtime_size);
>> +    runtime_addr = fw_hdr->image_load_address;
>> +    runtime_size = fw_hdr->runtime_size - boot_params_size -
>> fw_version_size;
>> +
>> +    image_load_addr = fw_hdr->image_load_address;
>> +    image_size = fw_hdr->image_size;
>> +
>> +    if (!ivpu_is_within_range(runtime_addr, runtime_size,
>> &vdev->hw->ranges.runtime)) {
>> +        ivpu_err(vdev, "Invalid firmware runtime address: 0x%llx and
>> size %llu\n",
>> +             runtime_addr, runtime_size);
>>           return -EINVAL;
>>       }
>>   @@ -230,23 +251,25 @@ static int ivpu_fw_parse(struct ivpu_device
>> *vdev)
>>           return -EINVAL;
>>       }
>>   -    if (image_load_addr < runtime_addr ||
>> -        image_load_addr + image_size > runtime_addr + runtime_size) {
>> -        ivpu_err(vdev, "Invalid firmware load address size: 0x%llx
>> and size %llu\n",
>> +    if (!ivpu_is_within_range(image_load_addr, image_size,
>> &vdev->hw->ranges.runtime)) {
>> +        ivpu_err(vdev, "Invalid firmware load address: 0x%llx and
>> size %llu\n",
>>                image_load_addr, image_size);
>>           return -EINVAL;
>>       }
>>   -    if (fw_hdr->shave_nn_fw_size > FW_SHAVE_NN_MAX_SIZE) {
>> -        ivpu_err(vdev, "SHAVE NN firmware is too big: %u\n",
>> fw_hdr->shave_nn_fw_size);
>> +    if (ivpu_hw_range_init(vdev, &fw_image_range, image_load_addr,
>> image_size))
>>           return -EINVAL;
>> -    }
>>   -    if (fw_hdr->entry_point < image_load_addr ||
>> -        fw_hdr->entry_point >= image_load_addr + image_size) {
>> +    if (!ivpu_is_within_range(fw_hdr->entry_point, SZ_4K,
>> &fw_image_range)) {
>>           ivpu_err(vdev, "Invalid entry point: 0x%llx\n",
>> fw_hdr->entry_point);
>>           return -EINVAL;
>>       }
>> +
>> +    if (fw_hdr->shave_nn_fw_size > FW_SHAVE_NN_MAX_SIZE) {
>> +        ivpu_err(vdev, "SHAVE NN firmware is too big: %u\n",
>> fw_hdr->shave_nn_fw_size);
>> +        return -EINVAL;
>> +    }
>> +
>>       ivpu_dbg(vdev, FW_BOOT, "Header version: 0x%x, format 0x%x\n",
>>            fw_hdr->header_version, fw_hdr->image_format);
>>   @@ -260,6 +283,10 @@ static int ivpu_fw_parse(struct ivpu_device
>> *vdev)
>>       if (IVPU_FW_CHECK_API_COMPAT(vdev, fw_hdr, JSM, 3))
>>           return -EINVAL;
>>   +    fw->boot_params_addr = boot_params_addr;
>> +    fw->boot_params_size = boot_params_size;
>> +    fw->fw_version_addr = fw_version_addr;
>> +    fw->fw_version_size = fw_version_size;
>>       fw->runtime_addr = runtime_addr;
>>       fw->runtime_size = runtime_size;
>>       fw->image_load_offset = image_load_addr - runtime_addr;
>> @@ -282,10 +309,9 @@ static int ivpu_fw_parse(struct ivpu_device *vdev)
>>       ivpu_dbg(vdev, FW_BOOT, "Mid-inference preemption %s supported\n",
>>            ivpu_fw_preempt_buf_size(vdev) ? "is" : "is not");
>>   -    if (fw_hdr->ro_section_start_address &&
>> !is_within_range(fw_hdr->ro_section_start_address,
>> -                                 fw_hdr->ro_section_size,
>> -                                 fw_hdr->image_load_address,
>> -                                 fw_hdr->image_size)) {
>> +    if (fw_hdr->ro_section_start_address &&
>> +        !ivpu_is_within_range(fw_hdr->ro_section_start_address,
>> fw_hdr->ro_section_size,
>> +                  &fw_image_range)) {
>>           ivpu_err(vdev, "Invalid read-only section: start address
>> 0x%llx, size %u\n",
>>                fw_hdr->ro_section_start_address,
>> fw_hdr->ro_section_size);
>>           return -EINVAL;
>> @@ -294,12 +320,18 @@ static int ivpu_fw_parse(struct ivpu_device *vdev)
>>       fw->read_only_addr = fw_hdr->ro_section_start_address;
>>       fw->read_only_size = fw_hdr->ro_section_size;
>>   -    ivpu_dbg(vdev, FW_BOOT, "Size: file %lu image %u runtime %u
>> shavenn %u\n",
>> -         fw->file->size, fw->image_size, fw->runtime_size,
>> fw->shave_nn_size);
>> -    ivpu_dbg(vdev, FW_BOOT, "Address: runtime 0x%llx, load 0x%llx,
>> entry point 0x%llx\n",
>> -         fw->runtime_addr, image_load_addr, fw->entry_point);
>> +    ivpu_dbg(vdev, FW_BOOT, "Boot params: address 0x%llx, size %llu\n",
>> +         fw->boot_params_addr, fw->boot_params_size);
>> +    ivpu_dbg(vdev, FW_BOOT, "FW version:  address 0x%llx, size %llu\n",
>> +         fw->fw_version_addr, fw->fw_version_size);
>> +    ivpu_dbg(vdev, FW_BOOT, "Runtime:     address 0x%llx, size %u\n",
>> +         fw->runtime_addr, fw->runtime_size);
>> +    ivpu_dbg(vdev, FW_BOOT, "Image load offset: 0x%llx, size %u\n",
>> +         fw->image_load_offset, fw->image_size);
>>       ivpu_dbg(vdev, FW_BOOT, "Read-only section: address 0x%llx,
>> size %u\n",
>>            fw->read_only_addr, fw->read_only_size);
>> +    ivpu_dbg(vdev, FW_BOOT, "FW entry point: 0x%llx\n",
>> fw->entry_point);
>> +    ivpu_dbg(vdev, FW_BOOT, "SHAVE NN size: %u\n", fw->shave_nn_size);
>>         return 0;
>>   }
>> @@ -326,39 +358,33 @@ ivpu_fw_init_wa(struct ivpu_device *vdev)
>>       IVPU_PRINT_WA(disable_d0i3_msg);
>>   }
>>   -static int ivpu_fw_update_global_range(struct ivpu_device *vdev)
>> -{
>> -    struct ivpu_fw_info *fw = vdev->fw;
>> -    u64 start = ALIGN(fw->runtime_addr + fw->runtime_size,
>> FW_SHARED_MEM_ALIGNMENT);
>> -    u64 size = FW_SHARED_MEM_SIZE;
>> -
>> -    if (start + size > FW_GLOBAL_MEM_END) {
>> -        ivpu_err(vdev, "No space for shared region, start %lld, size
>> %lld\n", start, size);
>> -        return -EINVAL;
>> -    }
>> -
>> -    ivpu_hw_range_init(&vdev->hw->ranges.global, start, size);
>> -    return 0;
>> -}
>> -
>>   static int ivpu_fw_mem_init(struct ivpu_device *vdev)
>>   {
>>       struct ivpu_fw_info *fw = vdev->fw;
>> -    struct ivpu_addr_range fw_range;
>>       int log_verb_size;
>>       int ret;
>>   -    ret = ivpu_fw_update_global_range(vdev);
>> -    if (ret)
>> -        return ret;
>> +    fw->mem_bp = ivpu_bo_create_runtime(vdev, fw->boot_params_addr,
>> fw->boot_params_size,
>> +                        DRM_IVPU_BO_WC | DRM_IVPU_BO_MAPPABLE);
>> +    if (!fw->mem_bp) {
>> +        ivpu_err(vdev, "Failed to create firmware boot params memory
>> buffer\n");
>> +        return -ENOMEM;
>> +    }
>>   -    fw_range.start = fw->runtime_addr;
>> -    fw_range.end = fw->runtime_addr + fw->runtime_size;
>> -    fw->mem = ivpu_bo_create(vdev, &vdev->gctx, &fw_range,
>> fw->runtime_size,
>> -                 DRM_IVPU_BO_WC | DRM_IVPU_BO_MAPPABLE);
>> +    fw->mem_fw_ver = ivpu_bo_create_runtime(vdev,
>> fw->fw_version_addr, fw->fw_version_size,
>> +                        DRM_IVPU_BO_WC | DRM_IVPU_BO_MAPPABLE);
>> +    if (!fw->mem_fw_ver) {
>> +        ivpu_err(vdev, "Failed to create firmware version memory
>> buffer\n");
>> +        ret = -ENOMEM;
>> +        goto err_free_bp;
>> +    }
>> +
>> +    fw->mem = ivpu_bo_create_runtime(vdev, fw->runtime_addr,
>> fw->runtime_size,
>> +                     DRM_IVPU_BO_WC | DRM_IVPU_BO_MAPPABLE);
>>       if (!fw->mem) {
>>           ivpu_err(vdev, "Failed to create firmware runtime memory
>> buffer\n");
>> -        return -ENOMEM;
>> +        ret = -ENOMEM;
>> +        goto err_free_fw_ver;
>>       }
>>         ret = ivpu_mmu_context_set_pages_ro(vdev, &vdev->gctx,
>> fw->read_only_addr,
>> @@ -407,6 +433,10 @@ static int ivpu_fw_mem_init(struct ivpu_device
>> *vdev)
>>       ivpu_bo_free(fw->mem_log_crit);
>>   err_free_fw_mem:
>>       ivpu_bo_free(fw->mem);
>> +err_free_fw_ver:
>> +    ivpu_bo_free(fw->mem_fw_ver);
>> +err_free_bp:
>> +    ivpu_bo_free(fw->mem_bp);
>>       return ret;
>>   }
>>   @@ -422,10 +452,14 @@ static void ivpu_fw_mem_fini(struct
>> ivpu_device *vdev)
>>       ivpu_bo_free(fw->mem_log_verb);
>>       ivpu_bo_free(fw->mem_log_crit);
>>       ivpu_bo_free(fw->mem);
>> +    ivpu_bo_free(fw->mem_fw_ver);
>> +    ivpu_bo_free(fw->mem_bp);
>>         fw->mem_log_verb = NULL;
>>       fw->mem_log_crit = NULL;
>>       fw->mem = NULL;
>> +    fw->mem_fw_ver = NULL;
>> +    fw->mem_bp = NULL;
>>   }
>>     int ivpu_fw_init(struct ivpu_device *vdev)
>> @@ -598,6 +632,7 @@ void ivpu_fw_boot_params_setup(struct ivpu_device
>> *vdev, struct vpu_boot_params
>>           return;
>>       }
>>   +    memset(boot_params, 0, sizeof(*boot_params));
>>       vdev->pm->is_warmboot = false;
>>         boot_params->magic = VPU_BOOT_PARAMS_MAGIC;
>> diff --git a/drivers/accel/ivpu/ivpu_fw.h b/drivers/accel/ivpu/ivpu_fw.h
>> index 6fe2917abda6..00945892b55e 100644
>> --- a/drivers/accel/ivpu/ivpu_fw.h
>> +++ b/drivers/accel/ivpu/ivpu_fw.h
>> @@ -19,10 +19,16 @@ struct ivpu_fw_info {
>>       const struct firmware *file;
>>       const char *name;
>>       char version[FW_VERSION_STR_SIZE];
>> +    struct ivpu_bo *mem_bp;
>> +    struct ivpu_bo *mem_fw_ver;
>>       struct ivpu_bo *mem;
>>       struct ivpu_bo *mem_shave_nn;
>>       struct ivpu_bo *mem_log_crit;
>>       struct ivpu_bo *mem_log_verb;
>> +    u64 boot_params_addr;
>> +    u64 boot_params_size;
>> +    u64 fw_version_addr;
>> +    u64 fw_version_size;
>>       u64 runtime_addr;
>>       u32 runtime_size;
>>       u64 image_load_offset;
>> @@ -42,6 +48,7 @@ struct ivpu_fw_info {
>>       u64 last_heartbeat;
>>   };
>>   +bool ivpu_is_within_range(u64 addr, size_t size, struct
>> ivpu_addr_range *range);
>>   int ivpu_fw_init(struct ivpu_device *vdev);
>>   void ivpu_fw_fini(struct ivpu_device *vdev);
>>   void ivpu_fw_load(struct ivpu_device *vdev);
>> diff --git a/drivers/accel/ivpu/ivpu_gem.c
>> b/drivers/accel/ivpu/ivpu_gem.c
>> index 59cfcf3eaded..cceb07232e12 100644
>> --- a/drivers/accel/ivpu/ivpu_gem.c
>> +++ b/drivers/accel/ivpu/ivpu_gem.c
>> @@ -15,6 +15,7 @@
>>   #include <drm/drm_utils.h>
>>     #include "ivpu_drv.h"
>> +#include "ivpu_fw.h"
>>   #include "ivpu_gem.h"
>>   #include "ivpu_hw.h"
>>   #include "ivpu_mmu.h"
>> @@ -391,6 +392,21 @@ ivpu_bo_create(struct ivpu_device *vdev, struct
>> ivpu_mmu_context *ctx,
>>       return NULL;
>>   }
>>   +struct ivpu_bo *ivpu_bo_create_runtime(struct ivpu_device *vdev,
>> u64 addr, u64 size, u32 flags)
>> +{
>> +    struct ivpu_addr_range range;
>> +
>> +    if (!ivpu_is_within_range(addr, size, &vdev->hw->ranges.runtime)) {
>> +        ivpu_err(vdev, "Invalid runtime BO address 0x%llx size
>> %llu\n", addr, size);
>> +        return NULL;
>> +    }
>> +
>> +    if (ivpu_hw_range_init(vdev, &range, addr, size))
>> +        return NULL;
>> +
>> +    return ivpu_bo_create(vdev, &vdev->gctx, &range, size, flags);
>> +}
>> +
>>   struct ivpu_bo *ivpu_bo_create_global(struct ivpu_device *vdev, u64
>> size, u32 flags)
>>   {
>>       return ivpu_bo_create(vdev, &vdev->gctx,
>> &vdev->hw->ranges.global, size, flags);
>> diff --git a/drivers/accel/ivpu/ivpu_gem.h
>> b/drivers/accel/ivpu/ivpu_gem.h
>> index 3ee996d503b2..3a208f3bf0a6 100644
>> --- a/drivers/accel/ivpu/ivpu_gem.h
>> +++ b/drivers/accel/ivpu/ivpu_gem.h
>> @@ -31,6 +31,7 @@ struct drm_gem_object
>> *ivpu_gem_create_object(struct drm_device *dev, size_t siz
>>   struct drm_gem_object *ivpu_gem_prime_import(struct drm_device
>> *dev, struct dma_buf *dma_buf);
>>   struct ivpu_bo *ivpu_bo_create(struct ivpu_device *vdev, struct
>> ivpu_mmu_context *ctx,
>>                      struct ivpu_addr_range *range, u64 size, u32
>> flags);
>> +struct ivpu_bo *ivpu_bo_create_runtime(struct ivpu_device *vdev, u64
>> addr, u64 size, u32 flags);
>>   struct ivpu_bo *ivpu_bo_create_global(struct ivpu_device *vdev, u64
>> size, u32 flags);
>>   void ivpu_bo_free(struct ivpu_bo *bo);
>>   diff --git a/drivers/accel/ivpu/ivpu_hw.c
>> b/drivers/accel/ivpu/ivpu_hw.c
>> index 08dcc31b56f4..8dbf8780920a 100644
>> --- a/drivers/accel/ivpu/ivpu_hw.c
>> +++ b/drivers/accel/ivpu/ivpu_hw.c
>> @@ -20,6 +20,8 @@ module_param_named_unsafe(fail_hw, ivpu_fail_hw,
>> charp, 0444);
>>   MODULE_PARM_DESC(fail_hw, "<interval>,<probability>,<space>,<times>");
>>   #endif
>>   +#define FW_SHARED_MEM_ALIGNMENT    SZ_512K /* VPU MTRR limitation */
>> +
>>   static char *platform_to_str(u32 platform)
>>   {
>>       switch (platform) {
>> @@ -147,19 +149,39 @@ static void priority_bands_init(struct
>> ivpu_device *vdev)
>>      
>> vdev->hw->hws.process_quantum[VPU_JOB_SCHEDULING_PRIORITY_BAND_REALTIME]
>> = 200000;
>>   }
>>   +int ivpu_hw_range_init(struct ivpu_device *vdev, struct
>> ivpu_addr_range *range, u64 start, u64 size)
>> +{
>> +    u64 end;
>> +
>> +    if (!range || check_add_overflow(start, size, &end)) {
>> +        ivpu_err(vdev, "Invalid range: start 0x%llx size %llu\n",
>> start, size);
>> +        return -EINVAL;
>> +    }
>> +
>> +    range->start = start;
>> +    range->end = end;
>> +
>> +    return 0;
>> +}
>> +
>>   static void memory_ranges_init(struct ivpu_device *vdev)
>>   {
>>       if (ivpu_hw_ip_gen(vdev) == IVPU_HW_IP_37XX) {
>> -        ivpu_hw_range_init(&vdev->hw->ranges.global, 0x80000000,
>> SZ_512M);
>> -        ivpu_hw_range_init(&vdev->hw->ranges.user,   0x88000000, 511
>> * SZ_1M);
>> -        ivpu_hw_range_init(&vdev->hw->ranges.shave, 0x180000000,
>> SZ_2G);
>> -        ivpu_hw_range_init(&vdev->hw->ranges.dma,   0x200000000,
>> SZ_128G);
>> +        ivpu_hw_range_init(vdev, &vdev->hw->ranges.runtime,
>> 0x84800000, SZ_64M);
>> +        ivpu_hw_range_init(vdev, &vdev->hw->ranges.global, 
>> 0x90000000, SZ_256M);
>> +        ivpu_hw_range_init(vdev, &vdev->hw->ranges.user,   
>> 0xa0000000, 511 * SZ_1M);
>> +        ivpu_hw_range_init(vdev, &vdev->hw->ranges.shave, 
>> 0x180000000, SZ_2G);
>> +        ivpu_hw_range_init(vdev, &vdev->hw->ranges.dma,   
>> 0x200000000, SZ_128G);
>>       } else {
>> -        ivpu_hw_range_init(&vdev->hw->ranges.global, 0x80000000,
>> SZ_512M);
>> -        ivpu_hw_range_init(&vdev->hw->ranges.shave,  0x80000000,
>> SZ_2G);
>> -        ivpu_hw_range_init(&vdev->hw->ranges.user,  0x100000000,
>> SZ_256G);
>> +        ivpu_hw_range_init(vdev, &vdev->hw->ranges.runtime,
>> 0x80000000, SZ_64M);
>> +        ivpu_hw_range_init(vdev, &vdev->hw->ranges.global, 
>> 0x90000000, SZ_256M);
>> +        ivpu_hw_range_init(vdev, &vdev->hw->ranges.shave,  
>> 0x80000000, SZ_2G);
>> +        ivpu_hw_range_init(vdev, &vdev->hw->ranges.user,  
>> 0x100000000, SZ_256G);
>>           vdev->hw->ranges.dma = vdev->hw->ranges.user;
>>       }
>> +
>> +    drm_WARN_ON(&vdev->drm, !IS_ALIGNED(vdev->hw->ranges.global.start,
>> +                        FW_SHARED_MEM_ALIGNMENT));
>>   }
>>     static int wp_enable(struct ivpu_device *vdev)
>> diff --git a/drivers/accel/ivpu/ivpu_hw.h b/drivers/accel/ivpu/ivpu_hw.h
>> index d79668fe1609..511a1a29f7f6 100644
>> --- a/drivers/accel/ivpu/ivpu_hw.h
>> +++ b/drivers/accel/ivpu/ivpu_hw.h
>> @@ -21,6 +21,7 @@ struct ivpu_hw_info {
>>           bool (*ip_irq_handler)(struct ivpu_device *vdev, int irq);
>>       } irq;
>>       struct {
>> +        struct ivpu_addr_range runtime;
>>           struct ivpu_addr_range global;
>>           struct ivpu_addr_range user;
>>           struct ivpu_addr_range shave;
>> @@ -51,6 +52,8 @@ struct ivpu_hw_info {
>>   };
>>     int ivpu_hw_init(struct ivpu_device *vdev);
>> +int ivpu_hw_range_init(struct ivpu_device *vdev, struct
>> ivpu_addr_range *range, u64 start,
>> +               u64 size);
>>   int ivpu_hw_power_up(struct ivpu_device *vdev);
>>   int ivpu_hw_power_down(struct ivpu_device *vdev);
>>   int ivpu_hw_reset(struct ivpu_device *vdev);
>> @@ -71,12 +74,6 @@ static inline u32 ivpu_hw_ip_irq_handler(struct
>> ivpu_device *vdev, int irq)
>>       return vdev->hw->irq.ip_irq_handler(vdev, irq);
>>   }
>>   -static inline void ivpu_hw_range_init(struct ivpu_addr_range
>> *range, u64 start, u64 size)
>> -{
>> -    range->start = start;
>> -    range->end = start + size;
>> -}
>> -
>>   static inline u64 ivpu_hw_range_size(const struct ivpu_addr_range
>> *range)
>>   {
>>       return range->end - range->start;
>> diff --git a/drivers/accel/ivpu/ivpu_mmu_context.c
>> b/drivers/accel/ivpu/ivpu_mmu_context.c
>> index f0267efa55aa..4ffc783426be 100644
>> --- a/drivers/accel/ivpu/ivpu_mmu_context.c
>> +++ b/drivers/accel/ivpu/ivpu_mmu_context.c
>> @@ -568,7 +568,7 @@ void ivpu_mmu_context_init(struct ivpu_device
>> *vdev, struct ivpu_mmu_context *ct
>>       mutex_init(&ctx->lock);
>>         if (!context_id) {
>> -        start = vdev->hw->ranges.global.start;
>> +        start = vdev->hw->ranges.runtime.start;
>>           end = vdev->hw->ranges.shave.end;
>>       } else {
>>           start = min_t(u64, vdev->hw->ranges.user.start,
>> vdev->hw->ranges.shave.start);
>> diff --git a/drivers/accel/ivpu/ivpu_pm.c b/drivers/accel/ivpu/ivpu_pm.c
>> index 475ddc94f1cf..7514f580eef4 100644
>> --- a/drivers/accel/ivpu/ivpu_pm.c
>> +++ b/drivers/accel/ivpu/ivpu_pm.c
>> @@ -54,7 +54,7 @@ static void ivpu_pm_prepare_cold_boot(struct
>> ivpu_device *vdev)
>>   static void ivpu_pm_prepare_warm_boot(struct ivpu_device *vdev)
>>   {
>>       struct ivpu_fw_info *fw = vdev->fw;
>> -    struct vpu_boot_params *bp = ivpu_bo_vaddr(fw->mem);
>> +    struct vpu_boot_params *bp = ivpu_bo_vaddr(fw->mem_bp);
>>         if (!bp->save_restore_ret_address) {
>>           ivpu_pm_prepare_cold_boot(vdev);

Reply via email to