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

drm/amdkfd: Add skeleton H/W debugger module support

This patch adds the skeleton H/W debugger module support. This code
enables registration and unregistration of a single HSA process at a
time.

The module saves the process's pasid and use it to verify that only the
registered process is allowed to execute debugger operations through the
kernel driver.

v2: rename get_dbgmgr_mutex to kfd_get_dbgmgr_mutex to namespace it

Signed-off-by: Yair Shachar <yair.shachar@amd.com>
Signed-off-by: Oded Gabbay <oded.gabbay@gmail.com>

authored by

Yair Shachar and committed by
Oded Gabbay
fbeb661b 992839ad

+1058 -2
+2 -1
drivers/gpu/drm/amd/amdkfd/Makefile
··· 12 12 kfd_kernel_queue_vi.o kfd_packet_manager.o \ 13 13 kfd_process_queue_manager.o kfd_device_queue_manager.o \ 14 14 kfd_device_queue_manager_cik.o kfd_device_queue_manager_vi.o \ 15 - kfd_interrupt.o kfd_events.o cik_event_interrupt.o 15 + kfd_interrupt.o kfd_events.o cik_event_interrupt.o \ 16 + kfd_dbgdev.o kfd_dbgmgr.o 16 17 17 18 obj-$(CONFIG_HSA_AMD) += amdkfd.o
+142
drivers/gpu/drm/amd/amdkfd/kfd_dbgdev.c
··· 1 + /* 2 + * Copyright 2014 Advanced Micro Devices, Inc. 3 + * 4 + * Permission is hereby granted, free of charge, to any person obtaining a 5 + * copy of this software and associated documentation files (the "Software"), 6 + * to deal in the Software without restriction, including without limitation 7 + * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 + * and/or sell copies of the Software, and to permit persons to whom the 9 + * Software is furnished to do so, subject to the following conditions: 10 + * 11 + * The above copyright notice and this permission notice shall be included in 12 + * all copies or substantial portions of the Software. 13 + * 14 + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 17 + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR 18 + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 19 + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 20 + * OTHER DEALINGS IN THE SOFTWARE. 21 + * 22 + */ 23 + 24 + #include <linux/types.h> 25 + #include <linux/kernel.h> 26 + #include <linux/log2.h> 27 + #include <linux/sched.h> 28 + #include <linux/slab.h> 29 + #include <linux/mutex.h> 30 + #include <linux/device.h> 31 + 32 + #include "kfd_pm4_headers.h" 33 + #include "kfd_pm4_headers_diq.h" 34 + #include "kfd_kernel_queue.h" 35 + #include "kfd_priv.h" 36 + #include "kfd_pm4_opcodes.h" 37 + #include "cik_regs.h" 38 + #include "kfd_dbgmgr.h" 39 + #include "kfd_dbgdev.h" 40 + #include "kfd_device_queue_manager.h" 41 + #include "../../radeon/cik_reg.h" 42 + 43 + static void dbgdev_address_watch_disable_nodiq(struct kfd_dev *dev) 44 + { 45 + BUG_ON(!dev || !dev->kfd2kgd); 46 + 47 + dev->kfd2kgd->address_watch_disable(dev->kgd); 48 + } 49 + 50 + static int dbgdev_register_nodiq(struct kfd_dbgdev *dbgdev) 51 + { 52 + BUG_ON(!dbgdev); 53 + 54 + /* 55 + * no action is needed in this case, 56 + * just make sure diq will not be used 57 + */ 58 + 59 + dbgdev->kq = NULL; 60 + 61 + return 0; 62 + } 63 + 64 + static int dbgdev_register_diq(struct kfd_dbgdev *dbgdev) 65 + { 66 + struct queue_properties properties; 67 + unsigned int qid; 68 + struct kernel_queue *kq = NULL; 69 + int status; 70 + 71 + BUG_ON(!dbgdev || !dbgdev->pqm || !dbgdev->dev); 72 + 73 + status = pqm_create_queue(dbgdev->pqm, dbgdev->dev, NULL, 74 + &properties, 0, KFD_QUEUE_TYPE_DIQ, 75 + &qid); 76 + 77 + if (status) { 78 + pr_err("amdkfd: Failed to create DIQ\n"); 79 + return status; 80 + } 81 + 82 + pr_debug("DIQ Created with queue id: %d\n", qid); 83 + 84 + kq = pqm_get_kernel_queue(dbgdev->pqm, qid); 85 + 86 + if (kq == NULL) { 87 + pr_err("amdkfd: Error getting DIQ\n"); 88 + pqm_destroy_queue(dbgdev->pqm, qid); 89 + return -EFAULT; 90 + } 91 + 92 + dbgdev->kq = kq; 93 + 94 + return status; 95 + } 96 + 97 + static int dbgdev_unregister_nodiq(struct kfd_dbgdev *dbgdev) 98 + { 99 + BUG_ON(!dbgdev || !dbgdev->dev); 100 + 101 + /* disable watch address */ 102 + dbgdev_address_watch_disable_nodiq(dbgdev->dev); 103 + return 0; 104 + } 105 + 106 + static int dbgdev_unregister_diq(struct kfd_dbgdev *dbgdev) 107 + { 108 + /* todo - disable address watch */ 109 + int status; 110 + 111 + BUG_ON(!dbgdev || !dbgdev->pqm || !dbgdev->kq); 112 + 113 + status = pqm_destroy_queue(dbgdev->pqm, 114 + dbgdev->kq->queue->properties.queue_id); 115 + dbgdev->kq = NULL; 116 + 117 + return status; 118 + } 119 + 120 + void kfd_dbgdev_init(struct kfd_dbgdev *pdbgdev, struct kfd_dev *pdev, 121 + enum DBGDEV_TYPE type) 122 + { 123 + BUG_ON(!pdbgdev || !pdev); 124 + 125 + pdbgdev->dev = pdev; 126 + pdbgdev->kq = NULL; 127 + pdbgdev->type = type; 128 + pdbgdev->pqm = NULL; 129 + 130 + switch (type) { 131 + case DBGDEV_TYPE_NODIQ: 132 + pdbgdev->dbgdev_register = dbgdev_register_nodiq; 133 + pdbgdev->dbgdev_unregister = dbgdev_unregister_nodiq; 134 + break; 135 + case DBGDEV_TYPE_DIQ: 136 + default: 137 + pdbgdev->dbgdev_register = dbgdev_register_diq; 138 + pdbgdev->dbgdev_unregister = dbgdev_unregister_diq; 139 + break; 140 + } 141 + 142 + }
+193
drivers/gpu/drm/amd/amdkfd/kfd_dbgdev.h
··· 1 + /* 2 + * Copyright 2014 Advanced Micro Devices, Inc. 3 + * 4 + * Permission is hereby granted, free of charge, to any person obtaining a 5 + * copy of this software and associated documentation files (the "Software"), 6 + * to deal in the Software without restriction, including without limitation 7 + * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 + * and/or sell copies of the Software, and to permit persons to whom the 9 + * Software is furnished to do so, subject to the following conditions: 10 + * 11 + * The above copyright notice and this permission notice shall be included in 12 + * all copies or substantial portions of the Software. 13 + * 14 + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 17 + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR 18 + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 19 + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 20 + * OTHER DEALINGS IN THE SOFTWARE. 21 + */ 22 + 23 + #ifndef KFD_DBGDEV_H_ 24 + #define KFD_DBGDEV_H_ 25 + 26 + enum { 27 + SQ_CMD_VMID_OFFSET = 28, 28 + ADDRESS_WATCH_CNTL_OFFSET = 24 29 + }; 30 + 31 + enum { 32 + PRIV_QUEUE_SYNC_TIME_MS = 200 33 + }; 34 + 35 + /* CONTEXT reg space definition */ 36 + enum { 37 + CONTEXT_REG_BASE = 0xA000, 38 + CONTEXT_REG_END = 0xA400, 39 + CONTEXT_REG_SIZE = CONTEXT_REG_END - CONTEXT_REG_BASE 40 + }; 41 + 42 + /* USER CONFIG reg space definition */ 43 + enum { 44 + USERCONFIG_REG_BASE = 0xC000, 45 + USERCONFIG_REG_END = 0x10000, 46 + USERCONFIG_REG_SIZE = USERCONFIG_REG_END - USERCONFIG_REG_BASE 47 + }; 48 + 49 + /* CONFIG reg space definition */ 50 + enum { 51 + CONFIG_REG_BASE = 0x2000, /* in dwords */ 52 + CONFIG_REG_END = 0x2B00, 53 + CONFIG_REG_SIZE = CONFIG_REG_END - CONFIG_REG_BASE 54 + }; 55 + 56 + /* SH reg space definition */ 57 + enum { 58 + SH_REG_BASE = 0x2C00, 59 + SH_REG_END = 0x3000, 60 + SH_REG_SIZE = SH_REG_END - SH_REG_BASE 61 + }; 62 + 63 + enum SQ_IND_CMD_CMD { 64 + SQ_IND_CMD_CMD_NULL = 0x00000000, 65 + SQ_IND_CMD_CMD_HALT = 0x00000001, 66 + SQ_IND_CMD_CMD_RESUME = 0x00000002, 67 + SQ_IND_CMD_CMD_KILL = 0x00000003, 68 + SQ_IND_CMD_CMD_DEBUG = 0x00000004, 69 + SQ_IND_CMD_CMD_TRAP = 0x00000005, 70 + }; 71 + 72 + enum SQ_IND_CMD_MODE { 73 + SQ_IND_CMD_MODE_SINGLE = 0x00000000, 74 + SQ_IND_CMD_MODE_BROADCAST = 0x00000001, 75 + SQ_IND_CMD_MODE_BROADCAST_QUEUE = 0x00000002, 76 + SQ_IND_CMD_MODE_BROADCAST_PIPE = 0x00000003, 77 + SQ_IND_CMD_MODE_BROADCAST_ME = 0x00000004, 78 + }; 79 + 80 + union SQ_IND_INDEX_BITS { 81 + struct { 82 + uint32_t wave_id:4; 83 + uint32_t simd_id:2; 84 + uint32_t thread_id:6; 85 + uint32_t:1; 86 + uint32_t force_read:1; 87 + uint32_t read_timeout:1; 88 + uint32_t unindexed:1; 89 + uint32_t index:16; 90 + 91 + } bitfields, bits; 92 + uint32_t u32All; 93 + signed int i32All; 94 + float f32All; 95 + }; 96 + 97 + union SQ_IND_CMD_BITS { 98 + struct { 99 + uint32_t data:32; 100 + } bitfields, bits; 101 + uint32_t u32All; 102 + signed int i32All; 103 + float f32All; 104 + }; 105 + 106 + union SQ_CMD_BITS { 107 + struct { 108 + uint32_t cmd:3; 109 + uint32_t:1; 110 + uint32_t mode:3; 111 + uint32_t check_vmid:1; 112 + uint32_t trap_id:3; 113 + uint32_t:5; 114 + uint32_t wave_id:4; 115 + uint32_t simd_id:2; 116 + uint32_t:2; 117 + uint32_t queue_id:3; 118 + uint32_t:1; 119 + uint32_t vm_id:4; 120 + } bitfields, bits; 121 + uint32_t u32All; 122 + signed int i32All; 123 + float f32All; 124 + }; 125 + 126 + union SQ_IND_DATA_BITS { 127 + struct { 128 + uint32_t data:32; 129 + } bitfields, bits; 130 + uint32_t u32All; 131 + signed int i32All; 132 + float f32All; 133 + }; 134 + 135 + union GRBM_GFX_INDEX_BITS { 136 + struct { 137 + uint32_t instance_index:8; 138 + uint32_t sh_index:8; 139 + uint32_t se_index:8; 140 + uint32_t:5; 141 + uint32_t sh_broadcast_writes:1; 142 + uint32_t instance_broadcast_writes:1; 143 + uint32_t se_broadcast_writes:1; 144 + } bitfields, bits; 145 + uint32_t u32All; 146 + signed int i32All; 147 + float f32All; 148 + }; 149 + 150 + union TCP_WATCH_ADDR_H_BITS { 151 + struct { 152 + uint32_t addr:16; 153 + uint32_t:16; 154 + 155 + } bitfields, bits; 156 + uint32_t u32All; 157 + signed int i32All; 158 + float f32All; 159 + }; 160 + 161 + union TCP_WATCH_ADDR_L_BITS { 162 + struct { 163 + uint32_t:6; 164 + uint32_t addr:26; 165 + } bitfields, bits; 166 + uint32_t u32All; 167 + signed int i32All; 168 + float f32All; 169 + }; 170 + 171 + enum { 172 + QUEUESTATE__INVALID = 0, /* so by default we'll get invalid state */ 173 + QUEUESTATE__ACTIVE_COMPLETION_PENDING, 174 + QUEUESTATE__ACTIVE 175 + }; 176 + 177 + union ULARGE_INTEGER { 178 + struct { 179 + uint32_t low_part; 180 + uint32_t high_part; 181 + } u; 182 + unsigned long long quad_part; 183 + }; 184 + 185 + 186 + #define KFD_CIK_VMID_START_OFFSET (8) 187 + #define KFD_CIK_VMID_END_OFFSET (KFD_CIK_VMID_START_OFFSET + (8)) 188 + 189 + 190 + void kfd_dbgdev_init(struct kfd_dbgdev *pdbgdev, struct kfd_dev *pdev, 191 + enum DBGDEV_TYPE type); 192 + 193 + #endif /* KFD_DBGDEV_H_ */
+135
drivers/gpu/drm/amd/amdkfd/kfd_dbgmgr.c
··· 1 + /* 2 + * Copyright 2014 Advanced Micro Devices, Inc. 3 + * 4 + * Permission is hereby granted, free of charge, to any person obtaining a 5 + * copy of this software and associated documentation files (the "Software"), 6 + * to deal in the Software without restriction, including without limitation 7 + * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 + * and/or sell copies of the Software, and to permit persons to whom the 9 + * Software is furnished to do so, subject to the following conditions: 10 + * 11 + * The above copyright notice and this permission notice shall be included in 12 + * all copies or substantial portions of the Software. 13 + * 14 + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 17 + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR 18 + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 19 + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 20 + * OTHER DEALINGS IN THE SOFTWARE. 21 + * 22 + */ 23 + #include <linux/types.h> 24 + #include <linux/kernel.h> 25 + #include <linux/log2.h> 26 + #include <linux/sched.h> 27 + #include <linux/slab.h> 28 + #include <linux/device.h> 29 + 30 + #include "kfd_priv.h" 31 + #include "cik_regs.h" 32 + #include "kfd_pm4_headers.h" 33 + #include "kfd_pm4_headers_diq.h" 34 + #include "kfd_dbgmgr.h" 35 + #include "kfd_dbgdev.h" 36 + 37 + static DEFINE_MUTEX(kfd_dbgmgr_mutex); 38 + 39 + struct mutex *kfd_get_dbgmgr_mutex(void) 40 + { 41 + return &kfd_dbgmgr_mutex; 42 + } 43 + 44 + 45 + static void kfd_dbgmgr_uninitialize(struct kfd_dbgmgr *pmgr) 46 + { 47 + BUG_ON(!pmgr); 48 + 49 + kfree(pmgr->dbgdev); 50 + 51 + pmgr->dbgdev = NULL; 52 + pmgr->pasid = 0; 53 + pmgr->dev = NULL; 54 + } 55 + 56 + void kfd_dbgmgr_destroy(struct kfd_dbgmgr *pmgr) 57 + { 58 + if (pmgr != NULL) { 59 + kfd_dbgmgr_uninitialize(pmgr); 60 + kfree(pmgr); 61 + } 62 + } 63 + 64 + bool kfd_dbgmgr_create(struct kfd_dbgmgr **ppmgr, struct kfd_dev *pdev) 65 + { 66 + enum DBGDEV_TYPE type = DBGDEV_TYPE_DIQ; 67 + struct kfd_dbgmgr *new_buff; 68 + 69 + BUG_ON(pdev == NULL); 70 + BUG_ON(!pdev->init_complete); 71 + 72 + new_buff = kfd_alloc_struct(new_buff); 73 + if (!new_buff) { 74 + pr_err("amdkfd: Failed to allocate dbgmgr instance\n"); 75 + return false; 76 + } 77 + 78 + new_buff->pasid = 0; 79 + new_buff->dev = pdev; 80 + new_buff->dbgdev = kfd_alloc_struct(new_buff->dbgdev); 81 + if (!new_buff->dbgdev) { 82 + pr_err("amdkfd: Failed to allocate dbgdev instance\n"); 83 + kfree(new_buff); 84 + return false; 85 + } 86 + 87 + /* get actual type of DBGDevice cpsch or not */ 88 + if (sched_policy == KFD_SCHED_POLICY_NO_HWS) 89 + type = DBGDEV_TYPE_NODIQ; 90 + 91 + kfd_dbgdev_init(new_buff->dbgdev, pdev, type); 92 + *ppmgr = new_buff; 93 + 94 + return true; 95 + } 96 + 97 + long kfd_dbgmgr_register(struct kfd_dbgmgr *pmgr, struct kfd_process *p) 98 + { 99 + BUG_ON(!p || !pmgr || !pmgr->dbgdev); 100 + 101 + if (pmgr->pasid != 0) { 102 + pr_debug("H/W debugger is already active using pasid %d\n", 103 + pmgr->pasid); 104 + return -EBUSY; 105 + } 106 + 107 + /* remember pasid */ 108 + pmgr->pasid = p->pasid; 109 + 110 + /* provide the pqm for diq generation */ 111 + pmgr->dbgdev->pqm = &p->pqm; 112 + 113 + /* activate the actual registering */ 114 + pmgr->dbgdev->dbgdev_register(pmgr->dbgdev); 115 + 116 + return 0; 117 + } 118 + 119 + long kfd_dbgmgr_unregister(struct kfd_dbgmgr *pmgr, struct kfd_process *p) 120 + { 121 + BUG_ON(!p || !pmgr || !pmgr->dbgdev); 122 + 123 + /* Is the requests coming from the already registered process? */ 124 + if (pmgr->pasid != p->pasid) { 125 + pr_debug("H/W debugger is not registered by calling pasid %d\n", 126 + p->pasid); 127 + return -EINVAL; 128 + } 129 + 130 + pmgr->dbgdev->dbgdev_unregister(pmgr->dbgdev); 131 + 132 + pmgr->pasid = 0; 133 + 134 + return 0; 135 + }
+287
drivers/gpu/drm/amd/amdkfd/kfd_dbgmgr.h
··· 1 + /* 2 + * Copyright 2014 Advanced Micro Devices, Inc. 3 + * 4 + * Permission is hereby granted, free of charge, to any person obtaining a 5 + * copy of this software and associated documentation files (the "Software"), 6 + * to deal in the Software without restriction, including without limitation 7 + * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 + * and/or sell copies of the Software, and to permit persons to whom the 9 + * Software is furnished to do so, subject to the following conditions: 10 + * 11 + * The above copyright notice and this permission notice shall be included in 12 + * all copies or substantial portions of the Software. 13 + * 14 + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 17 + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR 18 + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 19 + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 20 + * OTHER DEALINGS IN THE SOFTWARE. 21 + * 22 + */ 23 + 24 + #ifndef KFD_DBGMGR_H_ 25 + #define KFD_DBGMGR_H_ 26 + 27 + #include "kfd_priv.h" 28 + 29 + /* must align with hsakmttypes definition */ 30 + #pragma pack(push, 4) 31 + 32 + enum HSA_DBG_WAVEOP { 33 + HSA_DBG_WAVEOP_HALT = 1, /* Halts a wavefront */ 34 + HSA_DBG_WAVEOP_RESUME = 2, /* Resumes a wavefront */ 35 + HSA_DBG_WAVEOP_KILL = 3, /* Kills a wavefront */ 36 + HSA_DBG_WAVEOP_DEBUG = 4, /* Causes wavefront to enter 37 + debug mode */ 38 + HSA_DBG_WAVEOP_TRAP = 5, /* Causes wavefront to take 39 + a trap */ 40 + HSA_DBG_NUM_WAVEOP = 5, 41 + HSA_DBG_MAX_WAVEOP = 0xFFFFFFFF 42 + }; 43 + 44 + enum HSA_DBG_WAVEMODE { 45 + /* send command to a single wave */ 46 + HSA_DBG_WAVEMODE_SINGLE = 0, 47 + /* 48 + * Broadcast to all wavefronts of all processes is not 49 + * supported for HSA user mode 50 + */ 51 + 52 + /* send to waves within current process */ 53 + HSA_DBG_WAVEMODE_BROADCAST_PROCESS = 2, 54 + /* send to waves within current process on CU */ 55 + HSA_DBG_WAVEMODE_BROADCAST_PROCESS_CU = 3, 56 + HSA_DBG_NUM_WAVEMODE = 3, 57 + HSA_DBG_MAX_WAVEMODE = 0xFFFFFFFF 58 + }; 59 + 60 + enum HSA_DBG_WAVEMSG_TYPE { 61 + HSA_DBG_WAVEMSG_AUTO = 0, 62 + HSA_DBG_WAVEMSG_USER = 1, 63 + HSA_DBG_WAVEMSG_ERROR = 2, 64 + HSA_DBG_NUM_WAVEMSG, 65 + HSA_DBG_MAX_WAVEMSG = 0xFFFFFFFF 66 + }; 67 + 68 + enum HSA_DBG_WATCH_MODE { 69 + HSA_DBG_WATCH_READ = 0, /* Read operations only */ 70 + HSA_DBG_WATCH_NONREAD = 1, /* Write or Atomic operations only */ 71 + HSA_DBG_WATCH_ATOMIC = 2, /* Atomic Operations only */ 72 + HSA_DBG_WATCH_ALL = 3, /* Read, Write or Atomic operations */ 73 + HSA_DBG_WATCH_NUM, 74 + HSA_DBG_WATCH_SIZE = 0xFFFFFFFF 75 + }; 76 + 77 + /* This structure is hardware specific and may change in the future */ 78 + struct HsaDbgWaveMsgAMDGen2 { 79 + union { 80 + struct ui32 { 81 + uint32_t UserData:8; /* user data */ 82 + uint32_t ShaderArray:1; /* Shader array */ 83 + uint32_t Priv:1; /* Privileged */ 84 + uint32_t Reserved0:4; /* This field is reserved, 85 + should be 0 */ 86 + uint32_t WaveId:4; /* wave id */ 87 + uint32_t SIMD:2; /* SIMD id */ 88 + uint32_t HSACU:4; /* Compute unit */ 89 + uint32_t ShaderEngine:2;/* Shader engine */ 90 + uint32_t MessageType:2; /* see HSA_DBG_WAVEMSG_TYPE */ 91 + uint32_t Reserved1:4; /* This field is reserved, 92 + should be 0 */ 93 + } ui32; 94 + uint32_t Value; 95 + }; 96 + uint32_t Reserved2; 97 + }; 98 + 99 + union HsaDbgWaveMessageAMD { 100 + struct HsaDbgWaveMsgAMDGen2 WaveMsgInfoGen2; 101 + /* for future HsaDbgWaveMsgAMDGen3; */ 102 + }; 103 + 104 + struct HsaDbgWaveMessage { 105 + void *MemoryVA; /* ptr to associated host-accessible data */ 106 + union HsaDbgWaveMessageAMD DbgWaveMsg; 107 + }; 108 + 109 + /* 110 + * TODO: This definitions to be MOVED to kfd_event, once it is implemented. 111 + * 112 + * HSA sync primitive, Event and HW Exception notification API definitions. 113 + * The API functions allow the runtime to define a so-called sync-primitive, 114 + * a SW object combining a user-mode provided "syncvar" and a scheduler event 115 + * that can be signaled through a defined GPU interrupt. A syncvar is 116 + * a process virtual memory location of a certain size that can be accessed 117 + * by CPU and GPU shader code within the process to set and query the content 118 + * within that memory. The definition of the content is determined by the HSA 119 + * runtime and potentially GPU shader code interfacing with the HSA runtime. 120 + * The syncvar values may be commonly written through an PM4 WRITE_DATA packet 121 + * in the user mode instruction stream. The OS scheduler event is typically 122 + * associated and signaled by an interrupt issued by the GPU, but other HSA 123 + * system interrupt conditions from other HW (e.g. IOMMUv2) may be surfaced 124 + * by the KFD by this mechanism, too. */ 125 + 126 + /* these are the new definitions for events */ 127 + enum HSA_EVENTTYPE { 128 + HSA_EVENTTYPE_SIGNAL = 0, /* user-mode generated GPU signal */ 129 + HSA_EVENTTYPE_NODECHANGE = 1, /* HSA node change (attach/detach) */ 130 + HSA_EVENTTYPE_DEVICESTATECHANGE = 2, /* HSA device state change 131 + (start/stop) */ 132 + HSA_EVENTTYPE_HW_EXCEPTION = 3, /* GPU shader exception event */ 133 + HSA_EVENTTYPE_SYSTEM_EVENT = 4, /* GPU SYSCALL with parameter info */ 134 + HSA_EVENTTYPE_DEBUG_EVENT = 5, /* GPU signal for debugging */ 135 + HSA_EVENTTYPE_PROFILE_EVENT = 6,/* GPU signal for profiling */ 136 + HSA_EVENTTYPE_QUEUE_EVENT = 7, /* GPU signal queue idle state 137 + (EOP pm4) */ 138 + /* ... */ 139 + HSA_EVENTTYPE_MAXID, 140 + HSA_EVENTTYPE_TYPE_SIZE = 0xFFFFFFFF 141 + }; 142 + 143 + /* Sub-definitions for various event types: Syncvar */ 144 + struct HsaSyncVar { 145 + union SyncVar { 146 + void *UserData; /* pointer to user mode data */ 147 + uint64_t UserDataPtrValue; /* 64bit compatibility of value */ 148 + } SyncVar; 149 + uint64_t SyncVarSize; 150 + }; 151 + 152 + /* Sub-definitions for various event types: NodeChange */ 153 + 154 + enum HSA_EVENTTYPE_NODECHANGE_FLAGS { 155 + HSA_EVENTTYPE_NODECHANGE_ADD = 0, 156 + HSA_EVENTTYPE_NODECHANGE_REMOVE = 1, 157 + HSA_EVENTTYPE_NODECHANGE_SIZE = 0xFFFFFFFF 158 + }; 159 + 160 + struct HsaNodeChange { 161 + /* HSA node added/removed on the platform */ 162 + enum HSA_EVENTTYPE_NODECHANGE_FLAGS Flags; 163 + }; 164 + 165 + /* Sub-definitions for various event types: DeviceStateChange */ 166 + enum HSA_EVENTTYPE_DEVICESTATECHANGE_FLAGS { 167 + /* device started (and available) */ 168 + HSA_EVENTTYPE_DEVICESTATUSCHANGE_START = 0, 169 + /* device stopped (i.e. unavailable) */ 170 + HSA_EVENTTYPE_DEVICESTATUSCHANGE_STOP = 1, 171 + HSA_EVENTTYPE_DEVICESTATUSCHANGE_SIZE = 0xFFFFFFFF 172 + }; 173 + 174 + enum HSA_DEVICE { 175 + HSA_DEVICE_CPU = 0, 176 + HSA_DEVICE_GPU = 1, 177 + MAX_HSA_DEVICE = 2 178 + }; 179 + 180 + struct HsaDeviceStateChange { 181 + uint32_t NodeId; /* F-NUMA node that contains the device */ 182 + enum HSA_DEVICE Device; /* device type: GPU or CPU */ 183 + enum HSA_EVENTTYPE_DEVICESTATECHANGE_FLAGS Flags; /* event flags */ 184 + }; 185 + 186 + struct HsaEventData { 187 + enum HSA_EVENTTYPE EventType; /* event type */ 188 + union EventData { 189 + /* 190 + * return data associated with HSA_EVENTTYPE_SIGNAL 191 + * and other events 192 + */ 193 + struct HsaSyncVar SyncVar; 194 + 195 + /* data associated with HSA_EVENTTYPE_NODE_CHANGE */ 196 + struct HsaNodeChange NodeChangeState; 197 + 198 + /* data associated with HSA_EVENTTYPE_DEVICE_STATE_CHANGE */ 199 + struct HsaDeviceStateChange DeviceState; 200 + } EventData; 201 + 202 + /* the following data entries are internal to the KFD & thunk itself */ 203 + 204 + /* internal thunk store for Event data (OsEventHandle) */ 205 + uint64_t HWData1; 206 + /* internal thunk store for Event data (HWAddress) */ 207 + uint64_t HWData2; 208 + /* internal thunk store for Event data (HWData) */ 209 + uint32_t HWData3; 210 + }; 211 + 212 + struct HsaEventDescriptor { 213 + /* event type to allocate */ 214 + enum HSA_EVENTTYPE EventType; 215 + /* H-NUMA node containing GPU device that is event source */ 216 + uint32_t NodeId; 217 + /* pointer to user mode syncvar data, syncvar->UserDataPtrValue 218 + * may be NULL 219 + */ 220 + struct HsaSyncVar SyncVar; 221 + }; 222 + 223 + struct HsaEvent { 224 + uint32_t EventId; 225 + struct HsaEventData EventData; 226 + }; 227 + 228 + #pragma pack(pop) 229 + 230 + enum DBGDEV_TYPE { 231 + DBGDEV_TYPE_ILLEGAL = 0, 232 + DBGDEV_TYPE_NODIQ = 1, 233 + DBGDEV_TYPE_DIQ = 2, 234 + DBGDEV_TYPE_TEST = 3 235 + }; 236 + 237 + struct dbg_address_watch_info { 238 + struct kfd_process *process; 239 + enum HSA_DBG_WATCH_MODE *watch_mode; 240 + uint64_t *watch_address; 241 + uint64_t *watch_mask; 242 + struct HsaEvent *watch_event; 243 + uint32_t num_watch_points; 244 + }; 245 + 246 + struct dbg_wave_control_info { 247 + struct kfd_process *process; 248 + uint32_t trapId; 249 + enum HSA_DBG_WAVEOP operand; 250 + enum HSA_DBG_WAVEMODE mode; 251 + struct HsaDbgWaveMessage dbgWave_msg; 252 + }; 253 + 254 + struct kfd_dbgdev { 255 + 256 + /* The device that owns this data. */ 257 + struct kfd_dev *dev; 258 + 259 + /* kernel queue for DIQ */ 260 + struct kernel_queue *kq; 261 + 262 + /* a pointer to the pqm of the calling process */ 263 + struct process_queue_manager *pqm; 264 + 265 + /* type of debug device ( DIQ, non DIQ, etc. ) */ 266 + enum DBGDEV_TYPE type; 267 + 268 + /* virtualized function pointers to device dbg */ 269 + int (*dbgdev_register)(struct kfd_dbgdev *dbgdev); 270 + int (*dbgdev_unregister)(struct kfd_dbgdev *dbgdev); 271 + 272 + }; 273 + 274 + struct kfd_dbgmgr { 275 + unsigned int pasid; 276 + struct kfd_dev *dev; 277 + struct kfd_dbgdev *dbgdev; 278 + }; 279 + 280 + /* prototypes for debug manager functions */ 281 + struct mutex *kfd_get_dbgmgr_mutex(void); 282 + void kfd_dbgmgr_destroy(struct kfd_dbgmgr *pmgr); 283 + bool kfd_dbgmgr_create(struct kfd_dbgmgr **ppmgr, struct kfd_dev *pdev); 284 + long kfd_dbgmgr_register(struct kfd_dbgmgr *pmgr, struct kfd_process *p); 285 + long kfd_dbgmgr_unregister(struct kfd_dbgmgr *pmgr, struct kfd_process *p); 286 + 287 + #endif /* KFD_DBGMGR_H_ */
+3
drivers/gpu/drm/amd/amdkfd/kfd_device.c
··· 37 37 .max_no_of_hqd = 24, 38 38 .ih_ring_entry_size = 4 * sizeof(uint32_t), 39 39 .event_interrupt_class = &event_interrupt_class_cik, 40 + .num_of_watch_points = 4, 40 41 .mqd_size_aligned = MQD_SIZE_ALIGNED 41 42 }; 42 43 ··· 296 295 kfd->pdev->vendor, kfd->pdev->device); 297 296 goto dqm_start_error; 298 297 } 298 + 299 + kfd->dbgmgr = NULL; 299 300 300 301 kfd->init_complete = true; 301 302 dev_info(kfd_device, "added device (%x:%x)\n", kfd->pdev->vendor,
+290
drivers/gpu/drm/amd/amdkfd/kfd_pm4_headers_diq.h
··· 1 + /* 2 + * Copyright 2014 Advanced Micro Devices, Inc. 3 + * 4 + * Permission is hereby granted, free of charge, to any person obtaining a 5 + * copy of this software and associated documentation files (the "Software"), 6 + * to deal in the Software without restriction, including without limitation 7 + * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 + * and/or sell copies of the Software, and to permit persons to whom the 9 + * Software is furnished to do so, subject to the following conditions: 10 + * 11 + * The above copyright notice and this permission notice shall be included in 12 + * all copies or substantial portions of the Software. 13 + * 14 + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 17 + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR 18 + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 19 + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 20 + * OTHER DEALINGS IN THE SOFTWARE. 21 + * 22 + */ 23 + 24 + #ifndef KFD_PM4_HEADERS_DIQ_H_ 25 + #define KFD_PM4_HEADERS_DIQ_H_ 26 + 27 + /*--------------------_INDIRECT_BUFFER-------------------- */ 28 + 29 + #ifndef _PM4__INDIRECT_BUFFER_DEFINED 30 + #define _PM4__INDIRECT_BUFFER_DEFINED 31 + enum _INDIRECT_BUFFER_cache_policy_enum { 32 + cache_policy___indirect_buffer__lru = 0, 33 + cache_policy___indirect_buffer__stream = 1, 34 + cache_policy___indirect_buffer__bypass = 2 35 + }; 36 + 37 + enum { 38 + IT_INDIRECT_BUFFER_PASID = 0x5C 39 + }; 40 + 41 + struct pm4__indirect_buffer_pasid { 42 + union { 43 + union PM4_MES_TYPE_3_HEADER header; /* header */ 44 + unsigned int ordinal1; 45 + }; 46 + 47 + union { 48 + struct { 49 + unsigned int reserved1:2; 50 + unsigned int ib_base_lo:30; 51 + } bitfields2; 52 + unsigned int ordinal2; 53 + }; 54 + 55 + union { 56 + struct { 57 + unsigned int ib_base_hi:16; 58 + unsigned int reserved2:16; 59 + } bitfields3; 60 + unsigned int ordinal3; 61 + }; 62 + 63 + union { 64 + unsigned int control; 65 + unsigned int ordinal4; 66 + }; 67 + 68 + union { 69 + struct { 70 + unsigned int pasid:10; 71 + unsigned int reserved4:22; 72 + } bitfields5; 73 + unsigned int ordinal5; 74 + }; 75 + 76 + }; 77 + 78 + #endif 79 + 80 + /*--------------------_RELEASE_MEM-------------------- */ 81 + 82 + #ifndef _PM4__RELEASE_MEM_DEFINED 83 + #define _PM4__RELEASE_MEM_DEFINED 84 + enum _RELEASE_MEM_event_index_enum { 85 + event_index___release_mem__end_of_pipe = 5, 86 + event_index___release_mem__shader_done = 6 87 + }; 88 + 89 + enum _RELEASE_MEM_cache_policy_enum { 90 + cache_policy___release_mem__lru = 0, 91 + cache_policy___release_mem__stream = 1, 92 + cache_policy___release_mem__bypass = 2 93 + }; 94 + 95 + enum _RELEASE_MEM_dst_sel_enum { 96 + dst_sel___release_mem__memory_controller = 0, 97 + dst_sel___release_mem__tc_l2 = 1, 98 + dst_sel___release_mem__queue_write_pointer_register = 2, 99 + dst_sel___release_mem__queue_write_pointer_poll_mask_bit = 3 100 + }; 101 + 102 + enum _RELEASE_MEM_int_sel_enum { 103 + int_sel___release_mem__none = 0, 104 + int_sel___release_mem__send_interrupt_only = 1, 105 + int_sel___release_mem__send_interrupt_after_write_confirm = 2, 106 + int_sel___release_mem__send_data_after_write_confirm = 3 107 + }; 108 + 109 + enum _RELEASE_MEM_data_sel_enum { 110 + data_sel___release_mem__none = 0, 111 + data_sel___release_mem__send_32_bit_low = 1, 112 + data_sel___release_mem__send_64_bit_data = 2, 113 + data_sel___release_mem__send_gpu_clock_counter = 3, 114 + data_sel___release_mem__send_cp_perfcounter_hi_lo = 4, 115 + data_sel___release_mem__store_gds_data_to_memory = 5 116 + }; 117 + 118 + struct pm4__release_mem { 119 + union { 120 + union PM4_MES_TYPE_3_HEADER header; /*header */ 121 + unsigned int ordinal1; 122 + }; 123 + 124 + union { 125 + struct { 126 + unsigned int event_type:6; 127 + unsigned int reserved1:2; 128 + enum _RELEASE_MEM_event_index_enum event_index:4; 129 + unsigned int tcl1_vol_action_ena:1; 130 + unsigned int tc_vol_action_ena:1; 131 + unsigned int reserved2:1; 132 + unsigned int tc_wb_action_ena:1; 133 + unsigned int tcl1_action_ena:1; 134 + unsigned int tc_action_ena:1; 135 + unsigned int reserved3:6; 136 + unsigned int atc:1; 137 + enum _RELEASE_MEM_cache_policy_enum cache_policy:2; 138 + unsigned int reserved4:5; 139 + } bitfields2; 140 + unsigned int ordinal2; 141 + }; 142 + 143 + union { 144 + struct { 145 + unsigned int reserved5:16; 146 + enum _RELEASE_MEM_dst_sel_enum dst_sel:2; 147 + unsigned int reserved6:6; 148 + enum _RELEASE_MEM_int_sel_enum int_sel:3; 149 + unsigned int reserved7:2; 150 + enum _RELEASE_MEM_data_sel_enum data_sel:3; 151 + } bitfields3; 152 + unsigned int ordinal3; 153 + }; 154 + 155 + union { 156 + struct { 157 + unsigned int reserved8:2; 158 + unsigned int address_lo_32b:30; 159 + } bitfields4; 160 + struct { 161 + unsigned int reserved9:3; 162 + unsigned int address_lo_64b:29; 163 + } bitfields5; 164 + unsigned int ordinal4; 165 + }; 166 + 167 + unsigned int address_hi; 168 + 169 + unsigned int data_lo; 170 + 171 + unsigned int data_hi; 172 + 173 + }; 174 + #endif 175 + 176 + 177 + /*--------------------_SET_CONFIG_REG-------------------- */ 178 + 179 + #ifndef _PM4__SET_CONFIG_REG_DEFINED 180 + #define _PM4__SET_CONFIG_REG_DEFINED 181 + 182 + struct pm4__set_config_reg { 183 + union { 184 + union PM4_MES_TYPE_3_HEADER header; /*header */ 185 + unsigned int ordinal1; 186 + }; 187 + 188 + union { 189 + struct { 190 + unsigned int reg_offset:16; 191 + unsigned int reserved1:7; 192 + unsigned int vmid_shift:5; 193 + unsigned int insert_vmid:1; 194 + unsigned int reserved2:3; 195 + } bitfields2; 196 + unsigned int ordinal2; 197 + }; 198 + 199 + unsigned int reg_data[1]; /*1..N of these fields */ 200 + 201 + }; 202 + #endif 203 + 204 + /*--------------------_WAIT_REG_MEM-------------------- */ 205 + 206 + #ifndef _PM4__WAIT_REG_MEM_DEFINED 207 + #define _PM4__WAIT_REG_MEM_DEFINED 208 + enum _WAIT_REG_MEM_function_enum { 209 + function___wait_reg_mem__always_pass = 0, 210 + function___wait_reg_mem__less_than_ref_value = 1, 211 + function___wait_reg_mem__less_than_equal_to_the_ref_value = 2, 212 + function___wait_reg_mem__equal_to_the_reference_value = 3, 213 + function___wait_reg_mem__not_equal_reference_value = 4, 214 + function___wait_reg_mem__greater_than_or_equal_reference_value = 5, 215 + function___wait_reg_mem__greater_than_reference_value = 6, 216 + function___wait_reg_mem__reserved = 7 217 + }; 218 + 219 + enum _WAIT_REG_MEM_mem_space_enum { 220 + mem_space___wait_reg_mem__register_space = 0, 221 + mem_space___wait_reg_mem__memory_space = 1 222 + }; 223 + 224 + enum _WAIT_REG_MEM_operation_enum { 225 + operation___wait_reg_mem__wait_reg_mem = 0, 226 + operation___wait_reg_mem__wr_wait_wr_reg = 1 227 + }; 228 + 229 + struct pm4__wait_reg_mem { 230 + union { 231 + union PM4_MES_TYPE_3_HEADER header; /*header */ 232 + unsigned int ordinal1; 233 + }; 234 + 235 + union { 236 + struct { 237 + enum _WAIT_REG_MEM_function_enum function:3; 238 + unsigned int reserved1:1; 239 + enum _WAIT_REG_MEM_mem_space_enum mem_space:2; 240 + enum _WAIT_REG_MEM_operation_enum operation:2; 241 + unsigned int reserved2:24; 242 + } bitfields2; 243 + unsigned int ordinal2; 244 + }; 245 + 246 + union { 247 + struct { 248 + unsigned int reserved3:2; 249 + unsigned int memory_poll_addr_lo:30; 250 + } bitfields3; 251 + struct { 252 + unsigned int register_poll_addr:16; 253 + unsigned int reserved4:16; 254 + } bitfields4; 255 + struct { 256 + unsigned int register_write_addr:16; 257 + unsigned int reserved5:16; 258 + } bitfields5; 259 + unsigned int ordinal3; 260 + }; 261 + 262 + union { 263 + struct { 264 + unsigned int poll_address_hi:16; 265 + unsigned int reserved6:16; 266 + } bitfields6; 267 + struct { 268 + unsigned int register_write_addr:16; 269 + unsigned int reserved7:16; 270 + } bitfields7; 271 + unsigned int ordinal4; 272 + }; 273 + 274 + unsigned int reference; 275 + 276 + unsigned int mask; 277 + 278 + union { 279 + struct { 280 + unsigned int poll_interval:16; 281 + unsigned int reserved8:16; 282 + } bitfields8; 283 + unsigned int ordinal7; 284 + }; 285 + 286 + }; 287 + #endif 288 + 289 + 290 + #endif /* KFD_PM4_HEADERS_DIQ_H_ */
+5
drivers/gpu/drm/amd/amdkfd/kfd_priv.h
··· 196 196 * from the HW ring into a SW ring. 197 197 */ 198 198 bool interrupts_active; 199 + 200 + /* Debug manager */ 201 + struct kfd_dbgmgr *dbgmgr; 199 202 }; 200 203 201 204 /* KGD2KFD callbacks */ ··· 653 650 int pqm_destroy_queue(struct process_queue_manager *pqm, unsigned int qid); 654 651 int pqm_update_queue(struct process_queue_manager *pqm, unsigned int qid, 655 652 struct queue_properties *p); 653 + struct kernel_queue *pqm_get_kernel_queue(struct process_queue_manager *pqm, 654 + unsigned int qid); 656 655 657 656 /* Packet Manager */ 658 657
+1 -1
drivers/gpu/drm/amd/amdkfd/kfd_process_queue_manager.c
··· 357 357 return 0; 358 358 } 359 359 360 - static __attribute__((unused)) struct kernel_queue *pqm_get_kernel_queue( 360 + struct kernel_queue *pqm_get_kernel_queue( 361 361 struct process_queue_manager *pqm, 362 362 unsigned int qid) 363 363 {