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);