Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 16 additions & 2 deletions src/asahi/drm-shim/asahi_noop.c
Original file line number Diff line number Diff line change
Expand Up @@ -1308,6 +1308,14 @@ shim_features(void)
return features;
}

static uint64_t
shim_vm_end(const struct drm_asahi_params_global *params)
{
if (params == &params_g15g && shim_env_on("ASAHI_SHIM_G15G_HAL200"))
return UINT64_C(0x3ffffff8000);
return params->vm_end;
}

static int
asahi_ioctl_get_param(int fd, unsigned long request, void *arg)
{
Expand All @@ -1323,6 +1331,11 @@ asahi_ioctl_get_param(int fd, unsigned long request, void *arg)
size_t size = MIN2((size_t)gp->size, sizeof(struct drm_asahi_params_global));
struct drm_asahi_params_global params = *shim_params();
params.features = shim_features();
if (shim_params() == &params_g15g &&
shim_env_on("ASAHI_SHIM_G15G_HAL200")) {
params.gpu_hal_generation = DRM_ASAHI_GPU_HAL_200;
params.vm_end = shim_vm_end(shim_params());
}
const char *command_limit = getenv("ASAHI_SHIM_COMMAND_LIMIT");
if (command_limit) {
unsigned limit = strtoul(command_limit, NULL, 0);
Expand Down Expand Up @@ -1410,6 +1423,7 @@ asahi_ioctl_vm_bind_unlocked(int fd, unsigned long request, void *arg)
{
const struct drm_asahi_vm_bind *bind = arg;
const struct drm_asahi_params_global *params = shim_params();
const uint64_t vm_end = shim_vm_end(params);

for (uint32_t i = 0; i < bind->num_binds; ++i) {
const struct drm_asahi_gem_bind_op *op =
Expand All @@ -1425,13 +1439,13 @@ asahi_ioctl_vm_bind_unlocked(int fd, unsigned long request, void *arg)
return -EINVAL;
}

if (end < start || start < params->vm_start || end > params->vm_end) {
if (end < start || start < params->vm_start || end > vm_end) {
fprintf(stderr,
"shim: gem_bind: Invalid map range %#llx..%#llx "
"(not contained in user range %#llx..%#llx)\n",
(unsigned long long)start, (unsigned long long)end,
(unsigned long long)params->vm_start,
(unsigned long long)params->vm_end);
(unsigned long long)vm_end);
return -EINVAL;
}

Expand Down
18 changes: 18 additions & 0 deletions src/asahi/drm-shim/meson.build
Original file line number Diff line number Diff line change
Expand Up @@ -29,3 +29,21 @@ libasahi_noop_drm_shim = shared_library(
gnu_symbol_visibility : 'hidden',
install : true,
)

if with_tests
asahi_vm_limits_test = executable(
'asahi-vm-limits', 'test-vm-limits.c',
include_directories : [inc_include],
dependencies : [dep_libdrm],
)
foreach hal : ['legacy', 'hal200']
test(
'asahi-vm-limits-' + hal, prog_python,
args : [files('../../gallium/drivers/asahi/tests/run-shim.py'),
libasahi_noop_drm_shim, asahi_vm_limits_test],
env : ['ASAHI_SHIM_CHIP=g15g',
'ASAHI_SHIM_G15G_HAL200=' + (hal == 'hal200' ? '1' : '0')],
suite : ['asahi'],
)
endforeach
endif
43 changes: 43 additions & 0 deletions src/asahi/drm-shim/test-vm-limits.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
/* SPDX-License-Identifier: MIT */
#include <errno.h>
#include <fcntl.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <xf86drm.h>
#include "drm-uapi/asahi_drm.h"

#define CHECK(x) do { if (!(x)) { fprintf(stderr, "%u: %s\n", __LINE__, #x); abort(); } } while (0)

int main(void)
{
int fd = open("/dev/dri/renderD128", O_RDWR | O_CLOEXEC);
CHECK(fd >= 0);
struct drm_asahi_params_global params = {0};
struct drm_asahi_get_params get = {
.pointer = (uintptr_t)&params, .size = sizeof(params),
};
CHECK(!drmIoctl(fd, DRM_IOCTL_ASAHI_GET_PARAMS, &get));
struct drm_asahi_vm_create vm = {0};
CHECK(!drmIoctl(fd, DRM_IOCTL_ASAHI_VM_CREATE, &vm));
struct drm_asahi_gem_create bo = {.size = 0x4000};
CHECK(!drmIoctl(fd, DRM_IOCTL_ASAHI_GEM_CREATE, &bo));
struct drm_asahi_gem_bind_op op = {
.handle = bo.handle, .range = 0x4000,
};
struct drm_asahi_vm_bind bind = {
.vm_id = vm.vm_id, .num_binds = 1,
.stride = sizeof(op), .userptr = (uintptr_t)&op,
};
const uint64_t addresses[] = {params.vm_start, UINT64_C(0x30000000000),
params.vm_end - 0x4000, params.vm_end};
for (unsigned i = 0; i < 4; ++i) {
op.addr = addresses[i];
int ret = drmIoctl(fd, DRM_IOCTL_ASAHI_VM_BIND, &bind);
CHECK((ret == 0) == (op.addr + op.range <= params.vm_end));
}
close(fd);
puts("PASS reported VM limits match bind admission");
return 0;
}
45 changes: 38 additions & 7 deletions src/asahi/lib/agx_chip.c
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@

#include <stddef.h>

#include "util/bitscan.h"

enum agx_chip
agx_chip_from_params(const struct drm_asahi_params_global *params)
{
Expand Down Expand Up @@ -276,6 +278,41 @@ agx_chip_driver_supported(enum agx_chip chip)
}
}

/* The firmware interface version does not determine the GPU record layout.
* Both T8122 interfaces consume G15 records and Gen4 sampler words. Keep the
* physical chip as G15G so compiler scheduling and hardware workarounds agree.
*/
static bool
agx_t8122_params_supported(const struct drm_asahi_params_global *params)
{
if (params->chip_id != 0x8122 || params->num_dies != 1 ||
params->num_clusters_total != 1 ||
params->usc_generation != AGX_ISA_AGX3)
return false;

if (params->gpu_hal_generation == DRM_ASAHI_GPU_HAL_LEGACY)
return true;

if (params->gpu_hal_generation != DRM_ASAHI_GPU_HAL_200 ||
params->gpu_revision != 0x20 || params->num_cores_per_cluster != 10)
return false;

const uint64_t mask = params->core_masks[0];
const unsigned cores = util_bitcount64(mask);
if ((mask >> 10) || (cores != 8 && cores != 10))
return false;
for (unsigned i = 1; i < DRM_ASAHI_MAX_CLUSTERS; ++i) {
if (params->core_masks[i])
return false;
}

return agx_chip_command_stream_generation(AGX_CHIP_G15G) ==
AGX_CS_GENERATION_G15 &&
agx_chip_sampler_generation(AGX_CHIP_G15G) ==
AGX_SAMPLER_GENERATION_GEN4 &&
agx_chip_sampler_heap_element_size(AGX_CHIP_G15G) == 32;
}

bool
agx_params_driver_supported(const struct drm_asahi_params_global *params)
{
Expand All @@ -301,13 +338,7 @@ agx_params_driver_supported(const struct drm_asahi_params_global *params)
params->gpu_hal_generation == DRM_ASAHI_GPU_HAL_200;
}
case AGX_CHIP_G15G:
/* T8122/M3: one die, one cluster, AGX3 shaders on the legacy firmware
* interface (14.8.3), through the kernel's T8122 runtime. The exact
* identity/runtime checks apply without a Mesa environment opt-in. */
return params->chip_id == 0x8122 && params->num_dies == 1 &&
params->num_clusters_total == 1 &&
params->usc_generation == AGX_ISA_AGX3 &&
params->gpu_hal_generation == DRM_ASAHI_GPU_HAL_LEGACY;
return agx_t8122_params_supported(params);
case AGX_CHIP_G15S:
/* T6030/M3 Pro: one die, two clusters, AGX3 shaders on the legacy
* (pre-HAL200) firmware interface. */
Expand Down
9 changes: 9 additions & 0 deletions src/asahi/lib/agx_device.h
Original file line number Diff line number Diff line change
Expand Up @@ -520,6 +520,15 @@ agx_native_graphics(const struct agx_device *dev)
return agx_chip_native_agx3(dev->chip);
}

/* This interface carries native sampler state in GPU records, not in the
* firmware command's optional sampler-heap fields. */
static inline bool
agx_stream_sampler_state(const struct agx_device *dev)
{
return dev->chip == AGX_CHIP_G15G &&
dev->params.gpu_hal_generation == DRM_ASAHI_GPU_HAL_200;
}

/* T6040 uses the G17P architecture profile, while capability rollout may
* still be product-specific. Device admission has already checked USC/HAL. */
static inline bool
Expand Down
46 changes: 44 additions & 2 deletions src/asahi/lib/tests/test-chip-admission.c
Original file line number Diff line number Diff line change
Expand Up @@ -223,9 +223,51 @@ main(void)
bad.num_clusters_total = 2;
assert(!agx_params_driver_supported(&bad));

bad = g15g;
bad.gpu_hal_generation = DRM_ASAHI_GPU_HAL_200;
struct drm_asahi_params_global modern = g15g;
modern.gpu_hal_generation = DRM_ASAHI_GPU_HAL_200;
modern.gpu_revision = 0x20;
assert(agx_params_driver_supported(&modern));
assert(agx_params_native_kernel_abi_supported(&modern));
enum agx_chip modern_chip = agx_chip_from_params(&modern);
assert(modern_chip == AGX_CHIP_G15G);
assert(agx_chip_command_stream_generation(modern_chip) ==
AGX_CS_GENERATION_G15);
assert(agx_chip_sampler_generation(modern_chip) ==
AGX_SAMPLER_GENERATION_GEN4);
assert(agx_chip_sampler_heap_element_size(modern_chip) == 32);
assert(agx_chip_isa_encoding(modern_chip) ==
agx_chip_isa_encoding(agx_chip_from_params(&g15g)));
assert(agx_chip_cdm_wide_visibility(modern_chip));
assert(!agx_chip_sampler_has_lod_bias(modern_chip));
modern.core_masks[0] = 0x3cf;
assert(agx_params_driver_supported(&modern));
modern.core_masks[0] = 0x3ff;

bad = modern;
bad.gpu_hal_generation = DRM_ASAHI_GPU_HAL_300;
assert(!agx_params_driver_supported(&bad));
bad = modern;
bad.gpu_revision = 0x21;
assert(!agx_params_driver_supported(&bad));
bad = modern;
bad.num_cores_per_cluster = 9;
assert(!agx_params_driver_supported(&bad));
bad = modern;
bad.core_masks[0] = 0x1ff;
assert(!agx_params_driver_supported(&bad));
bad = modern;
bad.core_masks[0] = 0x7ff;
assert(!agx_params_driver_supported(&bad));
bad = modern;
bad.core_masks[1] = 1;
assert(!agx_params_driver_supported(&bad));
bad = modern;
bad.gpu_variant = 'S';
assert(!agx_params_driver_supported(&bad));
bad = modern;
bad.features = DRM_ASAHI_FEATURE_EXACT_PRIOR_BARRIERS |
DRM_ASAHI_FEATURE_PER_COMMAND_INPUT_SYNCS;
assert(!agx_params_native_kernel_abi_supported(&bad));

bad = g15g;
bad.usc_generation = 2;
Expand Down
4 changes: 2 additions & 2 deletions src/asahi/vulkan/hk_queue.c
Original file line number Diff line number Diff line change
Expand Up @@ -134,7 +134,7 @@ asahi_fill_cdm_command(struct hk_device *dev, struct hk_cs *cs,
.ts.end.offset = cs->timestamp.end.offset_B,
};

if (cs->uses_sampler_heap) {
if (cs->uses_sampler_heap && !agx_stream_sampler_state(&dev->dev)) {
cmd->sampler_heap = dev->samplers.table.bo->va->addr;
cmd->sampler_count = dev->samplers.table.alloc;
}
Expand Down Expand Up @@ -296,7 +296,7 @@ asahi_fill_vdm_command(struct hk_device *dev, struct hk_cs *cs,
c->isp_scissor_base = cs->uploaded_scissor;
c->isp_dbias_base = cs->uploaded_zbias;

if (cs->uses_sampler_heap) {
if (cs->uses_sampler_heap && !agx_stream_sampler_state(&dev->dev)) {
c->sampler_heap = dev->samplers.table.bo->va->addr;
c->sampler_count = dev->samplers.table.alloc;
}
Expand Down
8 changes: 7 additions & 1 deletion src/gallium/drivers/asahi/agx_pipe.c
Original file line number Diff line number Diff line change
Expand Up @@ -1508,7 +1508,8 @@ agx_cmdbuf(struct agx_device *dev, struct drm_asahi_cmd_render *c,
c->isp_dbias_base = depth_bias_ptr;
c->isp_oclqry_base = visibility_result_ptr;

if (batch->sampler_heap.bo) {
if (batch->sampler_heap.bo &&
!agx_stream_sampler_state(dev)) {
c->sampler_heap = batch->sampler_heap.bo->va->addr;
c->sampler_count = batch->sampler_heap.count;
}
Expand Down Expand Up @@ -1673,6 +1674,11 @@ agx_flush_compute(struct agx_context *ctx, struct agx_batch *batch,
.sampler_count = batch->sampler_heap.count,
};

if (agx_stream_sampler_state(dev)) {
cmdbuf->sampler_heap = 0;
cmdbuf->sampler_count = 0;
}

if (batch->cs_scratch) {
// The commented out lines *may* be related to subgroup-level preemption,
// which we can't support without implementing threadgroup memory in the
Expand Down