Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

drm/amdgpu: Add sysfs interface for running cleaner shader

This patch adds a new sysfs interface for running the cleaner shader on
AMD GPUs. The cleaner shader is used to clear GPU memory before it's
reused, which can help prevent data leakage between different processes.

The new sysfs file is write-only and is named `run_cleaner_shader`.
Write the number of the partition to this file to trigger the cleaner shader
on that partition. There is only one partition on GPUs which do not
support partitioning.

Changes made in this patch:

- Added `amdgpu_set_run_cleaner_shader` function to handle writes to the
`run_cleaner_shader` sysfs file.
- Added `run_cleaner_shader` to the list of device attributes in
`amdgpu_device_attrs`.
- Updated `default_attr_update` to handle `run_cleaner_shader`.
- Added `AMDGPU_DEVICE_ATTR_WO` macro to create write-only device
attributes.

v2: fix error handling (Alex)

Cc: Christian König <christian.koenig@amd.com>
Cc: Alex Deucher <alexander.deucher@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
Signed-off-by: Srinivasan Shanmugam <srinivasan.shanmugam@amd.com>

authored by

Srinivasan Shanmugam and committed by
Alex Deucher
d361ad5d e189be9b

+134
+134
drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.c
··· 24 24 */ 25 25 26 26 #include <linux/firmware.h> 27 + #include <linux/pm_runtime.h> 28 + 27 29 #include "amdgpu.h" 28 30 #include "amdgpu_gfx.h" 29 31 #include "amdgpu_rlc.h" 30 32 #include "amdgpu_ras.h" 33 + #include "amdgpu_reset.h" 31 34 #include "amdgpu_xcp.h" 32 35 #include "amdgpu_xgmi.h" 33 36 ··· 1394 1391 return sysfs_emit(buf, "%s\n", supported_partition); 1395 1392 } 1396 1393 1394 + static int amdgpu_gfx_run_cleaner_shader_job(struct amdgpu_ring *ring) 1395 + { 1396 + struct amdgpu_device *adev = ring->adev; 1397 + long timeout = msecs_to_jiffies(1000); 1398 + struct dma_fence *f = NULL; 1399 + struct amdgpu_job *job; 1400 + struct amdgpu_ib *ib; 1401 + int i, r; 1402 + 1403 + r = amdgpu_job_alloc_with_ib(adev, NULL, NULL, 1404 + 64, AMDGPU_IB_POOL_DIRECT, 1405 + &job); 1406 + if (r) 1407 + goto err; 1408 + 1409 + job->enforce_isolation = true; 1410 + 1411 + ib = &job->ibs[0]; 1412 + for (i = 0; i <= ring->funcs->align_mask; ++i) 1413 + ib->ptr[i] = ring->funcs->nop; 1414 + ib->length_dw = ring->funcs->align_mask + 1; 1415 + 1416 + r = amdgpu_job_submit_direct(job, ring, &f); 1417 + if (r) 1418 + goto err_free; 1419 + 1420 + r = dma_fence_wait_timeout(f, false, timeout); 1421 + if (r == 0) 1422 + r = -ETIMEDOUT; 1423 + else if (r > 0) 1424 + r = 0; 1425 + 1426 + amdgpu_ib_free(adev, ib, f); 1427 + dma_fence_put(f); 1428 + 1429 + return 0; 1430 + 1431 + err_free: 1432 + amdgpu_job_free(job); 1433 + amdgpu_ib_free(adev, ib, f); 1434 + err: 1435 + return r; 1436 + } 1437 + 1438 + static int amdgpu_gfx_run_cleaner_shader(struct amdgpu_device *adev, int xcp_id) 1439 + { 1440 + int num_xcc = NUM_XCC(adev->gfx.xcc_mask); 1441 + struct amdgpu_ring *ring; 1442 + int num_xcc_to_clear; 1443 + int i, r, xcc_id; 1444 + 1445 + if (adev->gfx.num_xcc_per_xcp) 1446 + num_xcc_to_clear = adev->gfx.num_xcc_per_xcp; 1447 + else 1448 + num_xcc_to_clear = 1; 1449 + 1450 + for (xcc_id = 0; xcc_id < num_xcc; xcc_id++) { 1451 + for (i = 0; i < adev->gfx.num_compute_rings; i++) { 1452 + ring = &adev->gfx.compute_ring[i + xcc_id * adev->gfx.num_compute_rings]; 1453 + if ((ring->xcp_id == xcp_id) && ring->sched.ready) { 1454 + r = amdgpu_gfx_run_cleaner_shader_job(ring); 1455 + if (r) 1456 + return r; 1457 + num_xcc_to_clear--; 1458 + break; 1459 + } 1460 + } 1461 + } 1462 + 1463 + if (num_xcc_to_clear) 1464 + return -ENOENT; 1465 + 1466 + return 0; 1467 + } 1468 + 1469 + static ssize_t amdgpu_gfx_set_run_cleaner_shader(struct device *dev, 1470 + struct device_attribute *attr, 1471 + const char *buf, 1472 + size_t count) 1473 + { 1474 + struct drm_device *ddev = dev_get_drvdata(dev); 1475 + struct amdgpu_device *adev = drm_to_adev(ddev); 1476 + int ret; 1477 + long value; 1478 + 1479 + if (amdgpu_in_reset(adev)) 1480 + return -EPERM; 1481 + if (adev->in_suspend && !adev->in_runpm) 1482 + return -EPERM; 1483 + 1484 + ret = kstrtol(buf, 0, &value); 1485 + 1486 + if (ret) 1487 + return -EINVAL; 1488 + 1489 + if (value < 0) 1490 + return -EINVAL; 1491 + 1492 + if (adev->xcp_mgr) { 1493 + if (value >= adev->xcp_mgr->num_xcps) 1494 + return -EINVAL; 1495 + } else { 1496 + if (value > 1) 1497 + return -EINVAL; 1498 + } 1499 + 1500 + ret = pm_runtime_get_sync(ddev->dev); 1501 + if (ret < 0) { 1502 + pm_runtime_put_autosuspend(ddev->dev); 1503 + return ret; 1504 + } 1505 + 1506 + ret = amdgpu_gfx_run_cleaner_shader(adev, value); 1507 + 1508 + pm_runtime_mark_last_busy(ddev->dev); 1509 + pm_runtime_put_autosuspend(ddev->dev); 1510 + 1511 + if (ret) 1512 + return ret; 1513 + 1514 + return count; 1515 + } 1516 + 1397 1517 static ssize_t amdgpu_gfx_get_enforce_isolation(struct device *dev, 1398 1518 struct device_attribute *attr, 1399 1519 char *buf) ··· 1595 1469 return count; 1596 1470 } 1597 1471 1472 + static DEVICE_ATTR(run_cleaner_shader, 0200, 1473 + NULL, amdgpu_gfx_set_run_cleaner_shader); 1474 + 1598 1475 static DEVICE_ATTR(enforce_isolation, 0644, 1599 1476 amdgpu_gfx_get_enforce_isolation, 1600 1477 amdgpu_gfx_set_enforce_isolation); ··· 1638 1509 return r; 1639 1510 } 1640 1511 1512 + r = device_create_file(adev->dev, &dev_attr_run_cleaner_shader); 1513 + if (r) 1514 + return r; 1515 + 1641 1516 return 0; 1642 1517 } 1643 1518 ··· 1649 1516 { 1650 1517 if (!amdgpu_sriov_vf(adev)) 1651 1518 device_remove_file(adev->dev, &dev_attr_enforce_isolation); 1519 + device_remove_file(adev->dev, &dev_attr_run_cleaner_shader); 1652 1520 } 1653 1521 1654 1522 int amdgpu_gfx_cleaner_shader_sw_init(struct amdgpu_device *adev,