cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

pmc.c (11317B)


      1// SPDX-License-Identifier: ISC
      2/*
      3 * Copyright (c) 2012-2015,2017 Qualcomm Atheros, Inc.
      4 * Copyright (c) 2018, The Linux Foundation. All rights reserved.
      5 */
      6
      7#include <linux/types.h>
      8#include <linux/errno.h>
      9#include <linux/fs.h>
     10#include <linux/seq_file.h>
     11#include "wmi.h"
     12#include "wil6210.h"
     13#include "txrx.h"
     14#include "pmc.h"
     15
     16struct desc_alloc_info {
     17	dma_addr_t pa;
     18	void	  *va;
     19};
     20
     21static int wil_is_pmc_allocated(struct pmc_ctx *pmc)
     22{
     23	return !!pmc->pring_va;
     24}
     25
     26void wil_pmc_init(struct wil6210_priv *wil)
     27{
     28	memset(&wil->pmc, 0, sizeof(struct pmc_ctx));
     29	mutex_init(&wil->pmc.lock);
     30}
     31
     32/* Allocate the physical ring (p-ring) and the required
     33 * number of descriptors of required size.
     34 * Initialize the descriptors as required by pmc dma.
     35 * The descriptors' buffers dwords are initialized to hold
     36 * dword's serial number in the lsw and reserved value
     37 * PCM_DATA_INVALID_DW_VAL in the msw.
     38 */
     39void wil_pmc_alloc(struct wil6210_priv *wil,
     40		   int num_descriptors,
     41		   int descriptor_size)
     42{
     43	u32 i;
     44	struct pmc_ctx *pmc = &wil->pmc;
     45	struct device *dev = wil_to_dev(wil);
     46	struct wil6210_vif *vif = ndev_to_vif(wil->main_ndev);
     47	struct wmi_pmc_cmd pmc_cmd = {0};
     48	int last_cmd_err = -ENOMEM;
     49
     50	mutex_lock(&pmc->lock);
     51
     52	if (wil_is_pmc_allocated(pmc)) {
     53		/* sanity check */
     54		wil_err(wil, "ERROR pmc is already allocated\n");
     55		goto no_release_err;
     56	}
     57	if ((num_descriptors <= 0) || (descriptor_size <= 0)) {
     58		wil_err(wil,
     59			"Invalid params num_descriptors(%d), descriptor_size(%d)\n",
     60			num_descriptors, descriptor_size);
     61		last_cmd_err = -EINVAL;
     62		goto no_release_err;
     63	}
     64
     65	if (num_descriptors > (1 << WIL_RING_SIZE_ORDER_MAX)) {
     66		wil_err(wil,
     67			"num_descriptors(%d) exceeds max ring size %d\n",
     68			num_descriptors, 1 << WIL_RING_SIZE_ORDER_MAX);
     69		last_cmd_err = -EINVAL;
     70		goto no_release_err;
     71	}
     72
     73	if (num_descriptors > INT_MAX / descriptor_size) {
     74		wil_err(wil,
     75			"Overflow in num_descriptors(%d)*descriptor_size(%d)\n",
     76			num_descriptors, descriptor_size);
     77		last_cmd_err = -EINVAL;
     78		goto no_release_err;
     79	}
     80
     81	pmc->num_descriptors = num_descriptors;
     82	pmc->descriptor_size = descriptor_size;
     83
     84	wil_dbg_misc(wil, "pmc_alloc: %d descriptors x %d bytes each\n",
     85		     num_descriptors, descriptor_size);
     86
     87	/* allocate descriptors info list in pmc context*/
     88	pmc->descriptors = kcalloc(num_descriptors,
     89				  sizeof(struct desc_alloc_info),
     90				  GFP_KERNEL);
     91	if (!pmc->descriptors) {
     92		wil_err(wil, "ERROR allocating pmc skb list\n");
     93		goto no_release_err;
     94	}
     95
     96	wil_dbg_misc(wil, "pmc_alloc: allocated descriptors info list %p\n",
     97		     pmc->descriptors);
     98
     99	/* Allocate pring buffer and descriptors.
    100	 * vring->va should be aligned on its size rounded up to power of 2
    101	 * This is granted by the dma_alloc_coherent.
    102	 *
    103	 * HW has limitation that all vrings addresses must share the same
    104	 * upper 16 msb bits part of 48 bits address. To workaround that,
    105	 * if we are using more than 32 bit addresses switch to 32 bit
    106	 * allocation before allocating vring memory.
    107	 *
    108	 * There's no check for the return value of dma_set_mask_and_coherent,
    109	 * since we assume if we were able to set the mask during
    110	 * initialization in this system it will not fail if we set it again
    111	 */
    112	if (wil->dma_addr_size > 32)
    113		dma_set_mask_and_coherent(dev, DMA_BIT_MASK(32));
    114
    115	pmc->pring_va = dma_alloc_coherent(dev,
    116			sizeof(struct vring_tx_desc) * num_descriptors,
    117			&pmc->pring_pa,
    118			GFP_KERNEL);
    119
    120	if (wil->dma_addr_size > 32)
    121		dma_set_mask_and_coherent(dev,
    122					  DMA_BIT_MASK(wil->dma_addr_size));
    123
    124	wil_dbg_misc(wil,
    125		     "pmc_alloc: allocated pring %p => %pad. %zd x %d = total %zd bytes\n",
    126		     pmc->pring_va, &pmc->pring_pa,
    127		     sizeof(struct vring_tx_desc),
    128		     num_descriptors,
    129		     sizeof(struct vring_tx_desc) * num_descriptors);
    130
    131	if (!pmc->pring_va) {
    132		wil_err(wil, "ERROR allocating pmc pring\n");
    133		goto release_pmc_skb_list;
    134	}
    135
    136	/* initially, all descriptors are SW owned
    137	 * For Tx, Rx, and PMC, ownership bit is at the same location, thus
    138	 * we can use any
    139	 */
    140	for (i = 0; i < num_descriptors; i++) {
    141		struct vring_tx_desc *_d = &pmc->pring_va[i];
    142		struct vring_tx_desc dd = {}, *d = &dd;
    143		int j = 0;
    144
    145		pmc->descriptors[i].va = dma_alloc_coherent(dev,
    146			descriptor_size,
    147			&pmc->descriptors[i].pa,
    148			GFP_KERNEL);
    149
    150		if (unlikely(!pmc->descriptors[i].va)) {
    151			wil_err(wil, "ERROR allocating pmc descriptor %d", i);
    152			goto release_pmc_skbs;
    153		}
    154
    155		for (j = 0; j < descriptor_size / sizeof(u32); j++) {
    156			u32 *p = (u32 *)pmc->descriptors[i].va + j;
    157			*p = PCM_DATA_INVALID_DW_VAL | j;
    158		}
    159
    160		/* configure dma descriptor */
    161		d->dma.addr.addr_low =
    162			cpu_to_le32(lower_32_bits(pmc->descriptors[i].pa));
    163		d->dma.addr.addr_high =
    164			cpu_to_le16((u16)upper_32_bits(pmc->descriptors[i].pa));
    165		d->dma.status = 0; /* 0 = HW_OWNED */
    166		d->dma.length = cpu_to_le16(descriptor_size);
    167		d->dma.d0 = BIT(9) | RX_DMA_D0_CMD_DMA_IT;
    168		*_d = *d;
    169	}
    170
    171	wil_dbg_misc(wil, "pmc_alloc: allocated successfully\n");
    172
    173	pmc_cmd.op = WMI_PMC_ALLOCATE;
    174	pmc_cmd.ring_size = cpu_to_le16(pmc->num_descriptors);
    175	pmc_cmd.mem_base = cpu_to_le64(pmc->pring_pa);
    176
    177	wil_dbg_misc(wil, "pmc_alloc: send WMI_PMC_CMD with ALLOCATE op\n");
    178	pmc->last_cmd_status = wmi_send(wil,
    179					WMI_PMC_CMDID,
    180					vif->mid,
    181					&pmc_cmd,
    182					sizeof(pmc_cmd));
    183	if (pmc->last_cmd_status) {
    184		wil_err(wil,
    185			"WMI_PMC_CMD with ALLOCATE op failed with status %d",
    186			pmc->last_cmd_status);
    187		goto release_pmc_skbs;
    188	}
    189
    190	mutex_unlock(&pmc->lock);
    191
    192	return;
    193
    194release_pmc_skbs:
    195	wil_err(wil, "exit on error: Releasing skbs...\n");
    196	for (i = 0; i < num_descriptors && pmc->descriptors[i].va; i++) {
    197		dma_free_coherent(dev,
    198				  descriptor_size,
    199				  pmc->descriptors[i].va,
    200				  pmc->descriptors[i].pa);
    201
    202		pmc->descriptors[i].va = NULL;
    203	}
    204	wil_err(wil, "exit on error: Releasing pring...\n");
    205
    206	dma_free_coherent(dev,
    207			  sizeof(struct vring_tx_desc) * num_descriptors,
    208			  pmc->pring_va,
    209			  pmc->pring_pa);
    210
    211	pmc->pring_va = NULL;
    212
    213release_pmc_skb_list:
    214	wil_err(wil, "exit on error: Releasing descriptors info list...\n");
    215	kfree(pmc->descriptors);
    216	pmc->descriptors = NULL;
    217
    218no_release_err:
    219	pmc->last_cmd_status = last_cmd_err;
    220	mutex_unlock(&pmc->lock);
    221}
    222
    223/* Traverse the p-ring and release all buffers.
    224 * At the end release the p-ring memory
    225 */
    226void wil_pmc_free(struct wil6210_priv *wil, int send_pmc_cmd)
    227{
    228	struct pmc_ctx *pmc = &wil->pmc;
    229	struct device *dev = wil_to_dev(wil);
    230	struct wil6210_vif *vif = ndev_to_vif(wil->main_ndev);
    231	struct wmi_pmc_cmd pmc_cmd = {0};
    232
    233	mutex_lock(&pmc->lock);
    234
    235	pmc->last_cmd_status = 0;
    236
    237	if (!wil_is_pmc_allocated(pmc)) {
    238		wil_dbg_misc(wil,
    239			     "pmc_free: Error, can't free - not allocated\n");
    240		pmc->last_cmd_status = -EPERM;
    241		mutex_unlock(&pmc->lock);
    242		return;
    243	}
    244
    245	if (send_pmc_cmd) {
    246		wil_dbg_misc(wil, "send WMI_PMC_CMD with RELEASE op\n");
    247		pmc_cmd.op = WMI_PMC_RELEASE;
    248		pmc->last_cmd_status =
    249				wmi_send(wil, WMI_PMC_CMDID, vif->mid,
    250					 &pmc_cmd, sizeof(pmc_cmd));
    251		if (pmc->last_cmd_status) {
    252			wil_err(wil,
    253				"WMI_PMC_CMD with RELEASE op failed, status %d",
    254				pmc->last_cmd_status);
    255			/* There's nothing we can do with this error.
    256			 * Normally, it should never occur.
    257			 * Continue to freeing all memory allocated for pmc.
    258			 */
    259		}
    260	}
    261
    262	if (pmc->pring_va) {
    263		size_t buf_size = sizeof(struct vring_tx_desc) *
    264				  pmc->num_descriptors;
    265
    266		wil_dbg_misc(wil, "pmc_free: free pring va %p\n",
    267			     pmc->pring_va);
    268		dma_free_coherent(dev, buf_size, pmc->pring_va, pmc->pring_pa);
    269
    270		pmc->pring_va = NULL;
    271	} else {
    272		pmc->last_cmd_status = -ENOENT;
    273	}
    274
    275	if (pmc->descriptors) {
    276		int i;
    277
    278		for (i = 0;
    279		     i < pmc->num_descriptors && pmc->descriptors[i].va; i++) {
    280			dma_free_coherent(dev,
    281					  pmc->descriptor_size,
    282					  pmc->descriptors[i].va,
    283					  pmc->descriptors[i].pa);
    284			pmc->descriptors[i].va = NULL;
    285		}
    286		wil_dbg_misc(wil, "pmc_free: free descriptor info %d/%d\n", i,
    287			     pmc->num_descriptors);
    288		wil_dbg_misc(wil,
    289			     "pmc_free: free pmc descriptors info list %p\n",
    290			     pmc->descriptors);
    291		kfree(pmc->descriptors);
    292		pmc->descriptors = NULL;
    293	} else {
    294		pmc->last_cmd_status = -ENOENT;
    295	}
    296
    297	mutex_unlock(&pmc->lock);
    298}
    299
    300/* Status of the last operation requested via debugfs: alloc/free/read.
    301 * 0 - success or negative errno
    302 */
    303int wil_pmc_last_cmd_status(struct wil6210_priv *wil)
    304{
    305	wil_dbg_misc(wil, "pmc_last_cmd_status: status %d\n",
    306		     wil->pmc.last_cmd_status);
    307
    308	return wil->pmc.last_cmd_status;
    309}
    310
    311/* Read from required position up to the end of current descriptor,
    312 * depends on descriptor size configured during alloc request.
    313 */
    314ssize_t wil_pmc_read(struct file *filp, char __user *buf, size_t count,
    315		     loff_t *f_pos)
    316{
    317	struct wil6210_priv *wil = filp->private_data;
    318	struct pmc_ctx *pmc = &wil->pmc;
    319	size_t retval = 0;
    320	unsigned long long idx;
    321	loff_t offset;
    322	size_t pmc_size;
    323
    324	mutex_lock(&pmc->lock);
    325
    326	if (!wil_is_pmc_allocated(pmc)) {
    327		wil_err(wil, "error, pmc is not allocated!\n");
    328		pmc->last_cmd_status = -EPERM;
    329		mutex_unlock(&pmc->lock);
    330		return -EPERM;
    331	}
    332
    333	pmc_size = pmc->descriptor_size * pmc->num_descriptors;
    334
    335	wil_dbg_misc(wil,
    336		     "pmc_read: size %u, pos %lld\n",
    337		     (u32)count, *f_pos);
    338
    339	pmc->last_cmd_status = 0;
    340
    341	idx = *f_pos;
    342	do_div(idx, pmc->descriptor_size);
    343	offset = *f_pos - (idx * pmc->descriptor_size);
    344
    345	if (*f_pos >= pmc_size) {
    346		wil_dbg_misc(wil,
    347			     "pmc_read: reached end of pmc buf: %lld >= %u\n",
    348			     *f_pos, (u32)pmc_size);
    349		pmc->last_cmd_status = -ERANGE;
    350		goto out;
    351	}
    352
    353	wil_dbg_misc(wil,
    354		     "pmc_read: read from pos %lld (descriptor %llu, offset %llu) %zu bytes\n",
    355		     *f_pos, idx, offset, count);
    356
    357	/* if no errors, return the copied byte count */
    358	retval = simple_read_from_buffer(buf,
    359					 count,
    360					 &offset,
    361					 pmc->descriptors[idx].va,
    362					 pmc->descriptor_size);
    363	*f_pos += retval;
    364out:
    365	mutex_unlock(&pmc->lock);
    366
    367	return retval;
    368}
    369
    370loff_t wil_pmc_llseek(struct file *filp, loff_t off, int whence)
    371{
    372	loff_t newpos;
    373	struct wil6210_priv *wil = filp->private_data;
    374	struct pmc_ctx *pmc = &wil->pmc;
    375	size_t pmc_size;
    376
    377	mutex_lock(&pmc->lock);
    378
    379	if (!wil_is_pmc_allocated(pmc)) {
    380		wil_err(wil, "error, pmc is not allocated!\n");
    381		pmc->last_cmd_status = -EPERM;
    382		mutex_unlock(&pmc->lock);
    383		return -EPERM;
    384	}
    385
    386	pmc_size = pmc->descriptor_size * pmc->num_descriptors;
    387
    388	switch (whence) {
    389	case 0: /* SEEK_SET */
    390		newpos = off;
    391		break;
    392
    393	case 1: /* SEEK_CUR */
    394		newpos = filp->f_pos + off;
    395		break;
    396
    397	case 2: /* SEEK_END */
    398		newpos = pmc_size;
    399		break;
    400
    401	default: /* can't happen */
    402		newpos = -EINVAL;
    403		goto out;
    404	}
    405
    406	if (newpos < 0) {
    407		newpos = -EINVAL;
    408		goto out;
    409	}
    410	if (newpos > pmc_size)
    411		newpos = pmc_size;
    412
    413	filp->f_pos = newpos;
    414
    415out:
    416	mutex_unlock(&pmc->lock);
    417
    418	return newpos;
    419}
    420
    421int wil_pmcring_read(struct seq_file *s, void *data)
    422{
    423	struct wil6210_priv *wil = s->private;
    424	struct pmc_ctx *pmc = &wil->pmc;
    425	size_t pmc_ring_size =
    426		sizeof(struct vring_rx_desc) * pmc->num_descriptors;
    427
    428	mutex_lock(&pmc->lock);
    429
    430	if (!wil_is_pmc_allocated(pmc)) {
    431		wil_err(wil, "error, pmc is not allocated!\n");
    432		pmc->last_cmd_status = -EPERM;
    433		mutex_unlock(&pmc->lock);
    434		return -EPERM;
    435	}
    436
    437	wil_dbg_misc(wil, "pmcring_read: size %zu\n", pmc_ring_size);
    438
    439	seq_write(s, pmc->pring_va, pmc_ring_size);
    440
    441	mutex_unlock(&pmc->lock);
    442
    443	return 0;
    444}