diff options
author | Jack Diver <diverj@google.com> | 2023-01-30 11:13:07 +0000 |
---|---|---|
committer | Jack Diver <diverj@google.com> | 2023-03-23 12:11:40 +0000 |
commit | e1c6d0e4f7aaf0a5876a9801eb68c3bcc29f3abf (patch) | |
tree | e16a7a7ba6e30737157080041016107460b30e26 /mali_kbase | |
parent | c1bfc7dd8cc50224da90f2532be9102eeb3739a9 (diff) | |
download | gpu-e1c6d0e4f7aaf0a5876a9801eb68c3bcc29f3abf.tar.gz |
platform: Implement SLC partition accounting
Track the per kctx usage and demand of SLC, updating in response to the
buffer_liveness_ioctl.
Setting SLC PBHA bits and resizing the partition are stubbed for now.
Bug: 264990406
Test: Boot to home
Test: Manual ioctl call
Change-Id: Idfe54f7baad25b9403a69f7269b7c8fc53dedaaa
Signed-off-by: Jack Diver <diverj@google.com>
Diffstat (limited to 'mali_kbase')
-rw-r--r-- | mali_kbase/platform/pixel/mali_kbase_config_platform.h | 21 | ||||
-rw-r--r-- | mali_kbase/platform/pixel/pixel_gpu_slc.c | 195 |
2 files changed, 212 insertions, 4 deletions
diff --git a/mali_kbase/platform/pixel/mali_kbase_config_platform.h b/mali_kbase/platform/pixel/mali_kbase_config_platform.h index 3e18eed..bb13101 100644 --- a/mali_kbase/platform/pixel/mali_kbase_config_platform.h +++ b/mali_kbase/platform/pixel/mali_kbase_config_platform.h @@ -293,6 +293,11 @@ struct gpu_dvfs_metrics_uid_stats; * @dvfs.qos.bts.enabled: Stores whether Bus Traffic Shaping (BTS) is currently enabled * @dvfs.qos.bts.threshold: The G3D shader stack clock at which BTS will be enabled. Set via DT. * @dvfs.qos.bts.scenario: The index of the BTS scenario to be used. Set via DT. + * + * @slc.lock: Synchronize updates to the SLC partition accounting variables. + * @slc.partition_size: The size of the GPU's SLC partition. + * @slc.demand: The total demand for SLC space, an aggregation of each kctx's demand. + * @slc.usage: The total amount of SLC space used, an aggregation of each kctx's usage. */ struct pixel_context { struct kbase_device *kbdev; @@ -402,15 +407,29 @@ struct pixel_context { #endif /* CONFIG_MALI_PIXEL_GPU_THERMAL */ } dvfs; #endif /* CONFIG_MALI_MIDGARD_DVFS */ + + struct { + struct mutex lock; + u64 partition_size; + u64 demand; + u64 usage; + } slc; }; /** * struct pixel_platform_data - Per kbase_context Pixel specific platform data * - * @stats: Tracks the dvfs metrics for the UID associated with this context + * @stats: Tracks the dvfs metrics for the UID associated with this context + * + * @slc.peak_demand: The parent context's maximum demand for SLC space + * @slc.peak_usage: The parent context's maximum use of SLC space */ struct pixel_platform_data { struct gpu_dvfs_metrics_uid_stats* stats; + struct { + u64 peak_demand; + u64 peak_usage; + } slc; }; #endif /* _KBASE_CONFIG_PLATFORM_H_ */ diff --git a/mali_kbase/platform/pixel/pixel_gpu_slc.c b/mali_kbase/platform/pixel/pixel_gpu_slc.c index 240fa8e..48e61c4 100644 --- a/mali_kbase/platform/pixel/pixel_gpu_slc.c +++ b/mali_kbase/platform/pixel/pixel_gpu_slc.c @@ -33,6 +33,97 @@ struct gpu_slc_liveness_update_info { }; /** + * gpu_slc_lock_as - Lock the current process address space + * + * @kctx: The &struct kbase_context + */ +static void gpu_slc_lock_as(struct kbase_context *kctx) +{ + down_write(kbase_mem_get_process_mmap_lock()); + kbase_gpu_vm_lock(kctx); +} + +/** + * gpu_slc_unlock_as - Unlock the current process address space + * + * @kctx: The &struct kbase_context + */ +static void gpu_slc_unlock_as(struct kbase_context *kctx) +{ + kbase_gpu_vm_unlock(kctx); + up_write(kbase_mem_get_process_mmap_lock()); +} + +/** + * gpu_slc_in_group - Check whether the region is SLC cacheable + * + * @reg: The gpu memory region to check for an SLC cacheable memory group. + */ +static bool gpu_slc_in_group(struct kbase_va_region* reg) +{ + /* TODO */ + return false; +} + +/** + * gpu_slc_get_region - Find the gpu memory region from a virtual address + * + * @kctx: The &struct kbase_context + * @va: The base gpu virtual address of the region + * + * Return: On success, returns a valid memory region. On failure NULL is returned. + */ +static struct kbase_va_region* gpu_slc_get_region(struct kbase_context *kctx, u64 va) +{ + struct kbase_va_region *reg; + + if (!va) + goto invalid; + + if ((va & ~PAGE_MASK) && (va >= PAGE_SIZE)) + goto invalid; + + /* Find the region that the virtual address belongs to */ + reg = kbase_region_tracker_find_region_base_address(kctx, va); + + /* Validate the region */ + if (kbase_is_region_invalid_or_free(reg)) + goto invalid; + + return reg; + +invalid: + dev_warn(kctx->kbdev->dev, "pixel: failed to find valid region for gpu_va: %llu", va); + return NULL; +} + +/** + * gpu_slc_migrate_region - Add PBHA that will make the pages SLC cacheable + * + * @kctx: The &struct kbase_context + * @reg: The gpu memory region migrate to an SLC cacheable memory group + */ +static void gpu_slc_migrate_region(struct kbase_context *kctx, struct kbase_va_region* reg) +{ + /* TODO */ + (void)kctx; + (void)reg; +} + +/** + * gpu_slc_resize_partition - Attempt to resize the GPU's SLC partition to meet demand. + * + * @kbdev: The &struct kbase_device for the GPU. + */ +static void gpu_slc_resize_partition(struct kbase_device* kbdev) +{ + struct pixel_context *pc = kbdev->platform_context; + dev_dbg(kbdev->dev, "pixel: resizing GPU SLC partition to meet demand: %llu", pc->slc.demand); + + /* TODO */ +} + +/** * gpu_slc_liveness_update - Respond to a liveness update by trying to put the new buffers into free * SLC space, and resizing the partition to meet demand. * @@ -44,8 +135,89 @@ static void gpu_slc_liveness_update(struct kbase_context* kctx, struct gpu_slc_liveness_update_info* info) { struct kbase_device* kbdev = kctx->kbdev; + struct pixel_context *pc = kbdev->platform_context; + struct pixel_platform_data *kctx_pd = kctx->platform_data; + u64 current_usage = 0; + u64 current_demand = 0; + u64 free_space; + int i; + + /* Lock the process address space before modifying ATE's */ + gpu_slc_lock_as(kctx); + + /* Synchronize updates to the partition size and usage */ + mutex_lock(&pc->slc.lock); + dev_dbg(kbdev->dev, "pixel: buffer liveness update received"); - (void)info; + + /* Remove the usage and demand from the previous liveness update */ + pc->slc.demand -= kctx_pd->slc.peak_demand; + pc->slc.usage -= kctx_pd->slc.peak_usage; + kctx_pd->slc.peak_demand = 0; + kctx_pd->slc.peak_usage = 0; + + /* Calculate the remaining free space in the SLC partition */ + free_space = pc->slc.partition_size - pc->slc.usage; + + for (i = 0; i < info->live_ranges_count; ++i) + { + struct kbase_va_region *reg; + u64 const size = info->buffer_sizes[info->live_ranges[i].index]; + u64 const va = info->buffer_va[info->live_ranges[i].index]; + + reg = gpu_slc_get_region(kctx, va); + if(!reg) + continue; + + switch (info->live_ranges[i].type) + { + case KBASE_PIXEL_GPU_LIVE_RANGE_BEGIN: + /* Update demand as though there's no size limit */ + current_demand += size; + kctx_pd->slc.peak_demand = max(kctx_pd->slc.peak_demand, current_demand); + + /* Check whether there's free space in the partition to store the buffer */ + if (free_space >= current_usage + size) + gpu_slc_migrate_region(kctx, reg); + + /* This may be true, even if the space calculation above returned false, + * as a previous call to this function may have migrated the region. + * In such a scenario, the current_usage may exceed the available free_space + * and we will be oversubscribed to the SLC partition. + * We could migrate the region back to the non-SLC group, but this would + * require an SLC flush, so for now we do nothing. + */ + if (gpu_slc_in_group(reg)) { + current_usage += size; + kctx_pd->slc.peak_usage = max(kctx_pd->slc.peak_usage, current_usage); + } + break; + case KBASE_PIXEL_GPU_LIVE_RANGE_END: + current_demand -= size; + if (gpu_slc_in_group(reg)) + current_usage -= size; + break; + } + } + /* Indicates a missing live range end marker */ + WARN_ON_ONCE(current_demand != 0 || current_usage != 0); + + /* Update the total usage and demand */ + pc->slc.demand += kctx_pd->slc.peak_demand; + pc->slc.usage += kctx_pd->slc.peak_usage; + + dev_dbg(kbdev->dev, + "pixel: kctx_%d, peak_demand: %llu, peak_usage: %llu", + kctx->id, + kctx_pd->slc.peak_demand, + kctx_pd->slc.peak_usage); + dev_dbg(kbdev->dev, "pixel: kbdev, demand: %llu, usage: %llu", pc->slc.demand, pc->slc.usage); + + /* Trigger partition resize based on the new demand */ + gpu_slc_resize_partition(kctx->kbdev); + + mutex_unlock(&pc->slc.lock); + gpu_slc_unlock_as(kctx); } /** @@ -148,10 +320,24 @@ int gpu_slc_kctx_init(struct kbase_context *kctx) * * @kctx: The &struct kbase_context that is being terminated * + * Free up SLC space used by the buffers that this context owns. */ void gpu_slc_kctx_term(struct kbase_context *kctx) { - (void)kctx; + struct kbase_device* kbdev = kctx->kbdev; + struct pixel_context *pc = kbdev->platform_context; + struct pixel_platform_data *kctx_pd = kctx->platform_data; + + mutex_lock(&pc->slc.lock); + + /* Deduct the usage and demand, freeing that SLC space for the next update */ + pc->slc.demand -= kctx_pd->slc.peak_demand; + pc->slc.usage -= kctx_pd->slc.peak_usage; + + /* Trigger partition resize based on the new demand */ + gpu_slc_resize_partition(kctx->kbdev); + + mutex_unlock(&pc->slc.lock); } @@ -164,7 +350,10 @@ void gpu_slc_kctx_term(struct kbase_context *kctx) */ int gpu_slc_init(struct kbase_device *kbdev) { - (void)kbdev; + struct pixel_context *pc = kbdev->platform_context; + + mutex_init(&pc->slc.lock); + return 0; } |