• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // SPDX-License-Identifier: GPL-2.0
2 
3 /*
4  * Copyright 2016-2019 HabanaLabs, Ltd.
5  * All Rights Reserved.
6  */
7 
8 #include <uapi/misc/habanalabs.h>
9 #include "habanalabs.h"
10 
11 #include <linux/fs.h>
12 #include <linux/uaccess.h>
13 #include <linux/slab.h>
14 
15 static u32 hl_debug_struct_size[HL_DEBUG_OP_TIMESTAMP + 1] = {
16 	[HL_DEBUG_OP_ETR] = sizeof(struct hl_debug_params_etr),
17 	[HL_DEBUG_OP_ETF] = sizeof(struct hl_debug_params_etf),
18 	[HL_DEBUG_OP_STM] = sizeof(struct hl_debug_params_stm),
19 	[HL_DEBUG_OP_FUNNEL] = 0,
20 	[HL_DEBUG_OP_BMON] = sizeof(struct hl_debug_params_bmon),
21 	[HL_DEBUG_OP_SPMU] = sizeof(struct hl_debug_params_spmu),
22 	[HL_DEBUG_OP_TIMESTAMP] = 0
23 
24 };
25 
device_status_info(struct hl_device * hdev,struct hl_info_args * args)26 static int device_status_info(struct hl_device *hdev, struct hl_info_args *args)
27 {
28 	struct hl_info_device_status dev_stat = {0};
29 	u32 size = args->return_size;
30 	void __user *out = (void __user *) (uintptr_t) args->return_pointer;
31 
32 	if ((!size) || (!out))
33 		return -EINVAL;
34 
35 	dev_stat.status = hl_device_status(hdev);
36 
37 	return copy_to_user(out, &dev_stat,
38 			min((size_t)size, sizeof(dev_stat))) ? -EFAULT : 0;
39 }
40 
hw_ip_info(struct hl_device * hdev,struct hl_info_args * args)41 static int hw_ip_info(struct hl_device *hdev, struct hl_info_args *args)
42 {
43 	struct hl_info_hw_ip_info hw_ip = {0};
44 	u32 size = args->return_size;
45 	void __user *out = (void __user *) (uintptr_t) args->return_pointer;
46 	struct asic_fixed_properties *prop = &hdev->asic_prop;
47 	u64 sram_kmd_size, dram_kmd_size;
48 
49 	if ((!size) || (!out))
50 		return -EINVAL;
51 
52 	sram_kmd_size = (prop->sram_user_base_address -
53 				prop->sram_base_address);
54 	dram_kmd_size = (prop->dram_user_base_address -
55 				prop->dram_base_address);
56 
57 	hw_ip.device_id = hdev->asic_funcs->get_pci_id(hdev);
58 	hw_ip.sram_base_address = prop->sram_user_base_address;
59 	hw_ip.dram_base_address = prop->dram_user_base_address;
60 	hw_ip.tpc_enabled_mask = prop->tpc_enabled_mask;
61 	hw_ip.sram_size = prop->sram_size - sram_kmd_size;
62 	hw_ip.dram_size = prop->dram_size - dram_kmd_size;
63 	if (hw_ip.dram_size > 0)
64 		hw_ip.dram_enabled = 1;
65 	hw_ip.num_of_events = prop->num_of_events;
66 	memcpy(hw_ip.armcp_version,
67 		prop->armcp_info.armcp_version, VERSION_MAX_LEN);
68 	hw_ip.armcp_cpld_version = le32_to_cpu(prop->armcp_info.cpld_version);
69 	hw_ip.psoc_pci_pll_nr = prop->psoc_pci_pll_nr;
70 	hw_ip.psoc_pci_pll_nf = prop->psoc_pci_pll_nf;
71 	hw_ip.psoc_pci_pll_od = prop->psoc_pci_pll_od;
72 	hw_ip.psoc_pci_pll_div_factor = prop->psoc_pci_pll_div_factor;
73 
74 	return copy_to_user(out, &hw_ip,
75 		min((size_t)size, sizeof(hw_ip))) ? -EFAULT : 0;
76 }
77 
hw_events_info(struct hl_device * hdev,bool aggregate,struct hl_info_args * args)78 static int hw_events_info(struct hl_device *hdev, bool aggregate,
79 			struct hl_info_args *args)
80 {
81 	u32 size, max_size = args->return_size;
82 	void __user *out = (void __user *) (uintptr_t) args->return_pointer;
83 	void *arr;
84 
85 	if ((!max_size) || (!out))
86 		return -EINVAL;
87 
88 	arr = hdev->asic_funcs->get_events_stat(hdev, aggregate, &size);
89 
90 	return copy_to_user(out, arr, min(max_size, size)) ? -EFAULT : 0;
91 }
92 
dram_usage_info(struct hl_fpriv * hpriv,struct hl_info_args * args)93 static int dram_usage_info(struct hl_fpriv *hpriv, struct hl_info_args *args)
94 {
95 	struct hl_device *hdev = hpriv->hdev;
96 	struct hl_info_dram_usage dram_usage = {0};
97 	u32 max_size = args->return_size;
98 	void __user *out = (void __user *) (uintptr_t) args->return_pointer;
99 	struct asic_fixed_properties *prop = &hdev->asic_prop;
100 	u64 dram_kmd_size;
101 
102 	if ((!max_size) || (!out))
103 		return -EINVAL;
104 
105 	dram_kmd_size = (prop->dram_user_base_address -
106 				prop->dram_base_address);
107 	dram_usage.dram_free_mem = (prop->dram_size - dram_kmd_size) -
108 					atomic64_read(&hdev->dram_used_mem);
109 	if (hpriv->ctx)
110 		dram_usage.ctx_dram_mem =
111 			atomic64_read(&hpriv->ctx->dram_phys_mem);
112 
113 	return copy_to_user(out, &dram_usage,
114 		min((size_t) max_size, sizeof(dram_usage))) ? -EFAULT : 0;
115 }
116 
hw_idle(struct hl_device * hdev,struct hl_info_args * args)117 static int hw_idle(struct hl_device *hdev, struct hl_info_args *args)
118 {
119 	struct hl_info_hw_idle hw_idle = {0};
120 	u32 max_size = args->return_size;
121 	void __user *out = (void __user *) (uintptr_t) args->return_pointer;
122 
123 	if ((!max_size) || (!out))
124 		return -EINVAL;
125 
126 	hw_idle.is_idle = hdev->asic_funcs->is_device_idle(hdev,
127 					&hw_idle.busy_engines_mask, NULL);
128 
129 	return copy_to_user(out, &hw_idle,
130 		min((size_t) max_size, sizeof(hw_idle))) ? -EFAULT : 0;
131 }
132 
debug_coresight(struct hl_device * hdev,struct hl_debug_args * args)133 static int debug_coresight(struct hl_device *hdev, struct hl_debug_args *args)
134 {
135 	struct hl_debug_params *params;
136 	void *input = NULL, *output = NULL;
137 	int rc;
138 
139 	params = kzalloc(sizeof(*params), GFP_KERNEL);
140 	if (!params)
141 		return -ENOMEM;
142 
143 	params->reg_idx = args->reg_idx;
144 	params->enable = args->enable;
145 	params->op = args->op;
146 
147 	if (args->input_ptr && args->input_size) {
148 		input = kzalloc(hl_debug_struct_size[args->op], GFP_KERNEL);
149 		if (!input) {
150 			rc = -ENOMEM;
151 			goto out;
152 		}
153 
154 		if (copy_from_user(input, u64_to_user_ptr(args->input_ptr),
155 					args->input_size)) {
156 			rc = -EFAULT;
157 			dev_err(hdev->dev, "failed to copy input debug data\n");
158 			goto out;
159 		}
160 
161 		params->input = input;
162 	}
163 
164 	if (args->output_ptr && args->output_size) {
165 		output = kzalloc(args->output_size, GFP_KERNEL);
166 		if (!output) {
167 			rc = -ENOMEM;
168 			goto out;
169 		}
170 
171 		params->output = output;
172 		params->output_size = args->output_size;
173 	}
174 
175 	rc = hdev->asic_funcs->debug_coresight(hdev, params);
176 	if (rc) {
177 		dev_err(hdev->dev,
178 			"debug coresight operation failed %d\n", rc);
179 		goto out;
180 	}
181 
182 	if (output) {
183 		if (copy_to_user((void __user *) (uintptr_t) args->output_ptr,
184 					output,
185 					args->output_size)) {
186 			dev_err(hdev->dev,
187 				"copy to user failed in debug ioctl\n");
188 			rc = -EFAULT;
189 			goto out;
190 		}
191 	}
192 
193 out:
194 	kfree(params);
195 	kfree(output);
196 	kfree(input);
197 
198 	return rc;
199 }
200 
device_utilization(struct hl_device * hdev,struct hl_info_args * args)201 static int device_utilization(struct hl_device *hdev, struct hl_info_args *args)
202 {
203 	struct hl_info_device_utilization device_util = {0};
204 	u32 max_size = args->return_size;
205 	void __user *out = (void __user *) (uintptr_t) args->return_pointer;
206 
207 	if ((!max_size) || (!out))
208 		return -EINVAL;
209 
210 	if ((args->period_ms < 100) || (args->period_ms > 1000) ||
211 		(args->period_ms % 100)) {
212 		dev_err(hdev->dev,
213 			"period %u must be between 100 - 1000 and must be divisible by 100\n",
214 			args->period_ms);
215 		return -EINVAL;
216 	}
217 
218 	device_util.utilization = hl_device_utilization(hdev, args->period_ms);
219 
220 	return copy_to_user(out, &device_util,
221 		min((size_t) max_size, sizeof(device_util))) ? -EFAULT : 0;
222 }
223 
_hl_info_ioctl(struct hl_fpriv * hpriv,void * data,struct device * dev)224 static int _hl_info_ioctl(struct hl_fpriv *hpriv, void *data,
225 				struct device *dev)
226 {
227 	struct hl_info_args *args = data;
228 	struct hl_device *hdev = hpriv->hdev;
229 	int rc;
230 
231 	/*
232 	 * Information is returned for the following opcodes even if the device
233 	 * is disabled or in reset.
234 	 */
235 	switch (args->op) {
236 	case HL_INFO_HW_IP_INFO:
237 		return hw_ip_info(hdev, args);
238 
239 	case HL_INFO_DEVICE_STATUS:
240 		return device_status_info(hdev, args);
241 
242 	default:
243 		break;
244 	}
245 
246 	if (hl_device_disabled_or_in_reset(hdev)) {
247 		dev_warn_ratelimited(dev,
248 			"Device is %s. Can't execute INFO IOCTL\n",
249 			atomic_read(&hdev->in_reset) ? "in_reset" : "disabled");
250 		return -EBUSY;
251 	}
252 
253 	switch (args->op) {
254 	case HL_INFO_HW_EVENTS:
255 		rc = hw_events_info(hdev, false, args);
256 		break;
257 
258 	case HL_INFO_DRAM_USAGE:
259 		rc = dram_usage_info(hpriv, args);
260 		break;
261 
262 	case HL_INFO_HW_IDLE:
263 		rc = hw_idle(hdev, args);
264 		break;
265 
266 	case HL_INFO_DEVICE_UTILIZATION:
267 		rc = device_utilization(hdev, args);
268 		break;
269 
270 	case HL_INFO_HW_EVENTS_AGGREGATE:
271 		rc = hw_events_info(hdev, true, args);
272 		break;
273 
274 	default:
275 		dev_err(dev, "Invalid request %d\n", args->op);
276 		rc = -ENOTTY;
277 		break;
278 	}
279 
280 	return rc;
281 }
282 
hl_info_ioctl(struct hl_fpriv * hpriv,void * data)283 static int hl_info_ioctl(struct hl_fpriv *hpriv, void *data)
284 {
285 	return _hl_info_ioctl(hpriv, data, hpriv->hdev->dev);
286 }
287 
hl_info_ioctl_control(struct hl_fpriv * hpriv,void * data)288 static int hl_info_ioctl_control(struct hl_fpriv *hpriv, void *data)
289 {
290 	return _hl_info_ioctl(hpriv, data, hpriv->hdev->dev_ctrl);
291 }
292 
hl_debug_ioctl(struct hl_fpriv * hpriv,void * data)293 static int hl_debug_ioctl(struct hl_fpriv *hpriv, void *data)
294 {
295 	struct hl_debug_args *args = data;
296 	struct hl_device *hdev = hpriv->hdev;
297 	int rc = 0;
298 
299 	if (hl_device_disabled_or_in_reset(hdev)) {
300 		dev_warn_ratelimited(hdev->dev,
301 			"Device is %s. Can't execute DEBUG IOCTL\n",
302 			atomic_read(&hdev->in_reset) ? "in_reset" : "disabled");
303 		return -EBUSY;
304 	}
305 
306 	switch (args->op) {
307 	case HL_DEBUG_OP_ETR:
308 	case HL_DEBUG_OP_ETF:
309 	case HL_DEBUG_OP_STM:
310 	case HL_DEBUG_OP_FUNNEL:
311 	case HL_DEBUG_OP_BMON:
312 	case HL_DEBUG_OP_SPMU:
313 	case HL_DEBUG_OP_TIMESTAMP:
314 		if (!hdev->in_debug) {
315 			dev_err_ratelimited(hdev->dev,
316 				"Rejecting debug configuration request because device not in debug mode\n");
317 			return -EFAULT;
318 		}
319 		args->input_size =
320 			min(args->input_size, hl_debug_struct_size[args->op]);
321 		rc = debug_coresight(hdev, args);
322 		break;
323 	case HL_DEBUG_OP_SET_MODE:
324 		rc = hl_device_set_debug_mode(hdev, (bool) args->enable);
325 		break;
326 	default:
327 		dev_err(hdev->dev, "Invalid request %d\n", args->op);
328 		rc = -ENOTTY;
329 		break;
330 	}
331 
332 	return rc;
333 }
334 
335 #define HL_IOCTL_DEF(ioctl, _func) \
336 	[_IOC_NR(ioctl)] = {.cmd = ioctl, .func = _func}
337 
338 static const struct hl_ioctl_desc hl_ioctls[] = {
339 	HL_IOCTL_DEF(HL_IOCTL_INFO, hl_info_ioctl),
340 	HL_IOCTL_DEF(HL_IOCTL_CB, hl_cb_ioctl),
341 	HL_IOCTL_DEF(HL_IOCTL_CS, hl_cs_ioctl),
342 	HL_IOCTL_DEF(HL_IOCTL_WAIT_CS, hl_cs_wait_ioctl),
343 	HL_IOCTL_DEF(HL_IOCTL_MEMORY, hl_mem_ioctl),
344 	HL_IOCTL_DEF(HL_IOCTL_DEBUG, hl_debug_ioctl)
345 };
346 
347 static const struct hl_ioctl_desc hl_ioctls_control[] = {
348 	HL_IOCTL_DEF(HL_IOCTL_INFO, hl_info_ioctl_control)
349 };
350 
_hl_ioctl(struct file * filep,unsigned int cmd,unsigned long arg,const struct hl_ioctl_desc * ioctl,struct device * dev)351 static long _hl_ioctl(struct file *filep, unsigned int cmd, unsigned long arg,
352 		const struct hl_ioctl_desc *ioctl, struct device *dev)
353 {
354 	struct hl_fpriv *hpriv = filep->private_data;
355 	struct hl_device *hdev = hpriv->hdev;
356 	unsigned int nr = _IOC_NR(cmd);
357 	char stack_kdata[128] = {0};
358 	char *kdata = NULL;
359 	unsigned int usize, asize;
360 	hl_ioctl_t *func;
361 	u32 hl_size;
362 	int retcode;
363 
364 	if (hdev->hard_reset_pending) {
365 		dev_crit_ratelimited(hdev->dev_ctrl,
366 			"Device HARD reset pending! Please close FD\n");
367 		return -ENODEV;
368 	}
369 
370 	/* Do not trust userspace, use our own definition */
371 	func = ioctl->func;
372 
373 	if (unlikely(!func)) {
374 		dev_dbg(dev, "no function\n");
375 		retcode = -ENOTTY;
376 		goto out_err;
377 	}
378 
379 	hl_size = _IOC_SIZE(ioctl->cmd);
380 	usize = asize = _IOC_SIZE(cmd);
381 	if (hl_size > asize)
382 		asize = hl_size;
383 
384 	cmd = ioctl->cmd;
385 
386 	if (cmd & (IOC_IN | IOC_OUT)) {
387 		if (asize <= sizeof(stack_kdata)) {
388 			kdata = stack_kdata;
389 		} else {
390 			kdata = kzalloc(asize, GFP_KERNEL);
391 			if (!kdata) {
392 				retcode = -ENOMEM;
393 				goto out_err;
394 			}
395 		}
396 	}
397 
398 	if (cmd & IOC_IN) {
399 		if (copy_from_user(kdata, (void __user *)arg, usize)) {
400 			retcode = -EFAULT;
401 			goto out_err;
402 		}
403 	} else if (cmd & IOC_OUT) {
404 		memset(kdata, 0, usize);
405 	}
406 
407 	retcode = func(hpriv, kdata);
408 
409 	if (cmd & IOC_OUT)
410 		if (copy_to_user((void __user *)arg, kdata, usize))
411 			retcode = -EFAULT;
412 
413 out_err:
414 	if (retcode)
415 		dev_dbg(dev, "error in ioctl: pid=%d, cmd=0x%02x, nr=0x%02x\n",
416 			  task_pid_nr(current), cmd, nr);
417 
418 	if (kdata != stack_kdata)
419 		kfree(kdata);
420 
421 	return retcode;
422 }
423 
hl_ioctl(struct file * filep,unsigned int cmd,unsigned long arg)424 long hl_ioctl(struct file *filep, unsigned int cmd, unsigned long arg)
425 {
426 	struct hl_fpriv *hpriv = filep->private_data;
427 	struct hl_device *hdev = hpriv->hdev;
428 	const struct hl_ioctl_desc *ioctl = NULL;
429 	unsigned int nr = _IOC_NR(cmd);
430 
431 	if ((nr >= HL_COMMAND_START) && (nr < HL_COMMAND_END)) {
432 		ioctl = &hl_ioctls[nr];
433 	} else {
434 		dev_err(hdev->dev, "invalid ioctl: pid=%d, nr=0x%02x\n",
435 			task_pid_nr(current), nr);
436 		return -ENOTTY;
437 	}
438 
439 	return _hl_ioctl(filep, cmd, arg, ioctl, hdev->dev);
440 }
441 
hl_ioctl_control(struct file * filep,unsigned int cmd,unsigned long arg)442 long hl_ioctl_control(struct file *filep, unsigned int cmd, unsigned long arg)
443 {
444 	struct hl_fpriv *hpriv = filep->private_data;
445 	struct hl_device *hdev = hpriv->hdev;
446 	const struct hl_ioctl_desc *ioctl = NULL;
447 	unsigned int nr = _IOC_NR(cmd);
448 
449 	if (nr == _IOC_NR(HL_IOCTL_INFO)) {
450 		ioctl = &hl_ioctls_control[nr];
451 	} else {
452 		dev_err(hdev->dev_ctrl, "invalid ioctl: pid=%d, nr=0x%02x\n",
453 			task_pid_nr(current), nr);
454 		return -ENOTTY;
455 	}
456 
457 	return _hl_ioctl(filep, cmd, arg, ioctl, hdev->dev_ctrl);
458 }
459