summaryrefslogtreecommitdiff
path: root/mali_kbase
diff options
context:
space:
mode:
authorJack Diver <diverj@google.com>2023-01-30 11:13:07 +0000
committerJack Diver <diverj@google.com>2023-03-23 12:11:40 +0000
commite1c6d0e4f7aaf0a5876a9801eb68c3bcc29f3abf (patch)
treee16a7a7ba6e30737157080041016107460b30e26 /mali_kbase
parentc1bfc7dd8cc50224da90f2532be9102eeb3739a9 (diff)
downloadgpu-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.h21
-rw-r--r--mali_kbase/platform/pixel/pixel_gpu_slc.c195
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;
}