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

lima_pp.c (10398B)


      1// SPDX-License-Identifier: GPL-2.0 OR MIT
      2/* Copyright 2017-2019 Qiang Yu <yuq825@gmail.com> */
      3
      4#include <linux/interrupt.h>
      5#include <linux/io.h>
      6#include <linux/device.h>
      7#include <linux/slab.h>
      8
      9#include <drm/lima_drm.h>
     10
     11#include "lima_device.h"
     12#include "lima_pp.h"
     13#include "lima_dlbu.h"
     14#include "lima_bcast.h"
     15#include "lima_vm.h"
     16#include "lima_regs.h"
     17
     18#define pp_write(reg, data) writel(data, ip->iomem + reg)
     19#define pp_read(reg) readl(ip->iomem + reg)
     20
     21static void lima_pp_handle_irq(struct lima_ip *ip, u32 state)
     22{
     23	struct lima_device *dev = ip->dev;
     24	struct lima_sched_pipe *pipe = dev->pipe + lima_pipe_pp;
     25
     26	if (state & LIMA_PP_IRQ_MASK_ERROR) {
     27		u32 status = pp_read(LIMA_PP_STATUS);
     28
     29		dev_err(dev->dev, "pp error irq state=%x status=%x\n",
     30			state, status);
     31
     32		pipe->error = true;
     33
     34		/* mask all interrupts before hard reset */
     35		pp_write(LIMA_PP_INT_MASK, 0);
     36	}
     37
     38	pp_write(LIMA_PP_INT_CLEAR, state);
     39}
     40
     41static irqreturn_t lima_pp_irq_handler(int irq, void *data)
     42{
     43	struct lima_ip *ip = data;
     44	struct lima_device *dev = ip->dev;
     45	struct lima_sched_pipe *pipe = dev->pipe + lima_pipe_pp;
     46	u32 state = pp_read(LIMA_PP_INT_STATUS);
     47
     48	/* for shared irq case */
     49	if (!state)
     50		return IRQ_NONE;
     51
     52	lima_pp_handle_irq(ip, state);
     53
     54	if (atomic_dec_and_test(&pipe->task))
     55		lima_sched_pipe_task_done(pipe);
     56
     57	return IRQ_HANDLED;
     58}
     59
     60static irqreturn_t lima_pp_bcast_irq_handler(int irq, void *data)
     61{
     62	int i;
     63	irqreturn_t ret = IRQ_NONE;
     64	struct lima_ip *pp_bcast = data;
     65	struct lima_device *dev = pp_bcast->dev;
     66	struct lima_sched_pipe *pipe = dev->pipe + lima_pipe_pp;
     67	struct drm_lima_m450_pp_frame *frame;
     68
     69	/* for shared irq case */
     70	if (!pipe->current_task)
     71		return IRQ_NONE;
     72
     73	frame = pipe->current_task->frame;
     74
     75	for (i = 0; i < frame->num_pp; i++) {
     76		struct lima_ip *ip = pipe->processor[i];
     77		u32 status, state;
     78
     79		if (pipe->done & (1 << i))
     80			continue;
     81
     82		/* status read first in case int state change in the middle
     83		 * which may miss the interrupt handling
     84		 */
     85		status = pp_read(LIMA_PP_STATUS);
     86		state = pp_read(LIMA_PP_INT_STATUS);
     87
     88		if (state) {
     89			lima_pp_handle_irq(ip, state);
     90			ret = IRQ_HANDLED;
     91		} else {
     92			if (status & LIMA_PP_STATUS_RENDERING_ACTIVE)
     93				continue;
     94		}
     95
     96		pipe->done |= (1 << i);
     97		if (atomic_dec_and_test(&pipe->task))
     98			lima_sched_pipe_task_done(pipe);
     99	}
    100
    101	return ret;
    102}
    103
    104static void lima_pp_soft_reset_async(struct lima_ip *ip)
    105{
    106	if (ip->data.async_reset)
    107		return;
    108
    109	pp_write(LIMA_PP_INT_MASK, 0);
    110	pp_write(LIMA_PP_INT_RAWSTAT, LIMA_PP_IRQ_MASK_ALL);
    111	pp_write(LIMA_PP_CTRL, LIMA_PP_CTRL_SOFT_RESET);
    112	ip->data.async_reset = true;
    113}
    114
    115static int lima_pp_soft_reset_poll(struct lima_ip *ip)
    116{
    117	return !(pp_read(LIMA_PP_STATUS) & LIMA_PP_STATUS_RENDERING_ACTIVE) &&
    118		pp_read(LIMA_PP_INT_RAWSTAT) == LIMA_PP_IRQ_RESET_COMPLETED;
    119}
    120
    121static int lima_pp_soft_reset_async_wait_one(struct lima_ip *ip)
    122{
    123	struct lima_device *dev = ip->dev;
    124	int ret;
    125
    126	ret = lima_poll_timeout(ip, lima_pp_soft_reset_poll, 0, 100);
    127	if (ret) {
    128		dev_err(dev->dev, "pp %s reset time out\n", lima_ip_name(ip));
    129		return ret;
    130	}
    131
    132	pp_write(LIMA_PP_INT_CLEAR, LIMA_PP_IRQ_MASK_ALL);
    133	pp_write(LIMA_PP_INT_MASK, LIMA_PP_IRQ_MASK_USED);
    134	return 0;
    135}
    136
    137static int lima_pp_soft_reset_async_wait(struct lima_ip *ip)
    138{
    139	int i, err = 0;
    140
    141	if (!ip->data.async_reset)
    142		return 0;
    143
    144	if (ip->id == lima_ip_pp_bcast) {
    145		struct lima_device *dev = ip->dev;
    146		struct lima_sched_pipe *pipe = dev->pipe + lima_pipe_pp;
    147		struct drm_lima_m450_pp_frame *frame = pipe->current_task->frame;
    148
    149		for (i = 0; i < frame->num_pp; i++)
    150			err |= lima_pp_soft_reset_async_wait_one(pipe->processor[i]);
    151	} else
    152		err = lima_pp_soft_reset_async_wait_one(ip);
    153
    154	ip->data.async_reset = false;
    155	return err;
    156}
    157
    158static void lima_pp_write_frame(struct lima_ip *ip, u32 *frame, u32 *wb)
    159{
    160	int i, j, n = 0;
    161
    162	for (i = 0; i < LIMA_PP_FRAME_REG_NUM; i++)
    163		writel(frame[i], ip->iomem + LIMA_PP_FRAME + i * 4);
    164
    165	for (i = 0; i < 3; i++) {
    166		for (j = 0; j < LIMA_PP_WB_REG_NUM; j++)
    167			writel(wb[n++], ip->iomem + LIMA_PP_WB(i) + j * 4);
    168	}
    169}
    170
    171static int lima_pp_hard_reset_poll(struct lima_ip *ip)
    172{
    173	pp_write(LIMA_PP_PERF_CNT_0_LIMIT, 0xC01A0000);
    174	return pp_read(LIMA_PP_PERF_CNT_0_LIMIT) == 0xC01A0000;
    175}
    176
    177static int lima_pp_hard_reset(struct lima_ip *ip)
    178{
    179	struct lima_device *dev = ip->dev;
    180	int ret;
    181
    182	pp_write(LIMA_PP_PERF_CNT_0_LIMIT, 0xC0FFE000);
    183	pp_write(LIMA_PP_INT_MASK, 0);
    184	pp_write(LIMA_PP_CTRL, LIMA_PP_CTRL_FORCE_RESET);
    185	ret = lima_poll_timeout(ip, lima_pp_hard_reset_poll, 10, 100);
    186	if (ret) {
    187		dev_err(dev->dev, "pp hard reset timeout\n");
    188		return ret;
    189	}
    190
    191	pp_write(LIMA_PP_PERF_CNT_0_LIMIT, 0);
    192	pp_write(LIMA_PP_INT_CLEAR, LIMA_PP_IRQ_MASK_ALL);
    193	pp_write(LIMA_PP_INT_MASK, LIMA_PP_IRQ_MASK_USED);
    194	return 0;
    195}
    196
    197static void lima_pp_print_version(struct lima_ip *ip)
    198{
    199	u32 version, major, minor;
    200	char *name;
    201
    202	version = pp_read(LIMA_PP_VERSION);
    203	major = (version >> 8) & 0xFF;
    204	minor = version & 0xFF;
    205	switch (version >> 16) {
    206	case 0xC807:
    207	    name = "mali200";
    208		break;
    209	case 0xCE07:
    210		name = "mali300";
    211		break;
    212	case 0xCD07:
    213		name = "mali400";
    214		break;
    215	case 0xCF07:
    216		name = "mali450";
    217		break;
    218	default:
    219		name = "unknown";
    220		break;
    221	}
    222	dev_info(ip->dev->dev, "%s - %s version major %d minor %d\n",
    223		 lima_ip_name(ip), name, major, minor);
    224}
    225
    226static int lima_pp_hw_init(struct lima_ip *ip)
    227{
    228	ip->data.async_reset = false;
    229	lima_pp_soft_reset_async(ip);
    230	return lima_pp_soft_reset_async_wait(ip);
    231}
    232
    233int lima_pp_resume(struct lima_ip *ip)
    234{
    235	return lima_pp_hw_init(ip);
    236}
    237
    238void lima_pp_suspend(struct lima_ip *ip)
    239{
    240
    241}
    242
    243int lima_pp_init(struct lima_ip *ip)
    244{
    245	struct lima_device *dev = ip->dev;
    246	int err;
    247
    248	lima_pp_print_version(ip);
    249
    250	err = lima_pp_hw_init(ip);
    251	if (err)
    252		return err;
    253
    254	err = devm_request_irq(dev->dev, ip->irq, lima_pp_irq_handler,
    255			       IRQF_SHARED, lima_ip_name(ip), ip);
    256	if (err) {
    257		dev_err(dev->dev, "pp %s fail to request irq\n",
    258			lima_ip_name(ip));
    259		return err;
    260	}
    261
    262	dev->pp_version = pp_read(LIMA_PP_VERSION);
    263
    264	return 0;
    265}
    266
    267void lima_pp_fini(struct lima_ip *ip)
    268{
    269
    270}
    271
    272int lima_pp_bcast_resume(struct lima_ip *ip)
    273{
    274	/* PP has been reset by individual PP resume */
    275	ip->data.async_reset = false;
    276	return 0;
    277}
    278
    279void lima_pp_bcast_suspend(struct lima_ip *ip)
    280{
    281
    282}
    283
    284int lima_pp_bcast_init(struct lima_ip *ip)
    285{
    286	struct lima_device *dev = ip->dev;
    287	int err;
    288
    289	err = devm_request_irq(dev->dev, ip->irq, lima_pp_bcast_irq_handler,
    290			       IRQF_SHARED, lima_ip_name(ip), ip);
    291	if (err) {
    292		dev_err(dev->dev, "pp %s fail to request irq\n",
    293			lima_ip_name(ip));
    294		return err;
    295	}
    296
    297	return 0;
    298}
    299
    300void lima_pp_bcast_fini(struct lima_ip *ip)
    301{
    302
    303}
    304
    305static int lima_pp_task_validate(struct lima_sched_pipe *pipe,
    306				 struct lima_sched_task *task)
    307{
    308	u32 num_pp;
    309
    310	if (pipe->bcast_processor) {
    311		struct drm_lima_m450_pp_frame *f = task->frame;
    312
    313		num_pp = f->num_pp;
    314
    315		if (f->_pad)
    316			return -EINVAL;
    317	} else {
    318		struct drm_lima_m400_pp_frame *f = task->frame;
    319
    320		num_pp = f->num_pp;
    321	}
    322
    323	if (num_pp == 0 || num_pp > pipe->num_processor)
    324		return -EINVAL;
    325
    326	return 0;
    327}
    328
    329static void lima_pp_task_run(struct lima_sched_pipe *pipe,
    330			     struct lima_sched_task *task)
    331{
    332	if (pipe->bcast_processor) {
    333		struct drm_lima_m450_pp_frame *frame = task->frame;
    334		struct lima_device *dev = pipe->bcast_processor->dev;
    335		struct lima_ip *ip = pipe->bcast_processor;
    336		int i;
    337
    338		pipe->done = 0;
    339		atomic_set(&pipe->task, frame->num_pp);
    340
    341		if (frame->use_dlbu) {
    342			lima_dlbu_enable(dev, frame->num_pp);
    343
    344			frame->frame[LIMA_PP_FRAME >> 2] = LIMA_VA_RESERVE_DLBU;
    345			lima_dlbu_set_reg(dev->ip + lima_ip_dlbu, frame->dlbu_regs);
    346		} else
    347			lima_dlbu_disable(dev);
    348
    349		lima_bcast_enable(dev, frame->num_pp);
    350
    351		lima_pp_soft_reset_async_wait(ip);
    352
    353		lima_pp_write_frame(ip, frame->frame, frame->wb);
    354
    355		for (i = 0; i < frame->num_pp; i++) {
    356			struct lima_ip *ip = pipe->processor[i];
    357
    358			pp_write(LIMA_PP_STACK, frame->fragment_stack_address[i]);
    359			if (!frame->use_dlbu)
    360				pp_write(LIMA_PP_FRAME, frame->plbu_array_address[i]);
    361		}
    362
    363		pp_write(LIMA_PP_CTRL, LIMA_PP_CTRL_START_RENDERING);
    364	} else {
    365		struct drm_lima_m400_pp_frame *frame = task->frame;
    366		int i;
    367
    368		atomic_set(&pipe->task, frame->num_pp);
    369
    370		for (i = 0; i < frame->num_pp; i++) {
    371			struct lima_ip *ip = pipe->processor[i];
    372
    373			frame->frame[LIMA_PP_FRAME >> 2] =
    374				frame->plbu_array_address[i];
    375			frame->frame[LIMA_PP_STACK >> 2] =
    376				frame->fragment_stack_address[i];
    377
    378			lima_pp_soft_reset_async_wait(ip);
    379
    380			lima_pp_write_frame(ip, frame->frame, frame->wb);
    381
    382			pp_write(LIMA_PP_CTRL, LIMA_PP_CTRL_START_RENDERING);
    383		}
    384	}
    385}
    386
    387static void lima_pp_task_fini(struct lima_sched_pipe *pipe)
    388{
    389	if (pipe->bcast_processor)
    390		lima_pp_soft_reset_async(pipe->bcast_processor);
    391	else {
    392		int i;
    393
    394		for (i = 0; i < pipe->num_processor; i++)
    395			lima_pp_soft_reset_async(pipe->processor[i]);
    396	}
    397}
    398
    399static void lima_pp_task_error(struct lima_sched_pipe *pipe)
    400{
    401	int i;
    402
    403	for (i = 0; i < pipe->num_processor; i++) {
    404		struct lima_ip *ip = pipe->processor[i];
    405
    406		dev_err(ip->dev->dev, "pp task error %d int_state=%x status=%x\n",
    407			i, pp_read(LIMA_PP_INT_STATUS), pp_read(LIMA_PP_STATUS));
    408
    409		lima_pp_hard_reset(ip);
    410	}
    411}
    412
    413static void lima_pp_task_mmu_error(struct lima_sched_pipe *pipe)
    414{
    415	if (atomic_dec_and_test(&pipe->task))
    416		lima_sched_pipe_task_done(pipe);
    417}
    418
    419static struct kmem_cache *lima_pp_task_slab;
    420static int lima_pp_task_slab_refcnt;
    421
    422int lima_pp_pipe_init(struct lima_device *dev)
    423{
    424	int frame_size;
    425	struct lima_sched_pipe *pipe = dev->pipe + lima_pipe_pp;
    426
    427	if (dev->id == lima_gpu_mali400)
    428		frame_size = sizeof(struct drm_lima_m400_pp_frame);
    429	else
    430		frame_size = sizeof(struct drm_lima_m450_pp_frame);
    431
    432	if (!lima_pp_task_slab) {
    433		lima_pp_task_slab = kmem_cache_create_usercopy(
    434			"lima_pp_task", sizeof(struct lima_sched_task) + frame_size,
    435			0, SLAB_HWCACHE_ALIGN, sizeof(struct lima_sched_task),
    436			frame_size, NULL);
    437		if (!lima_pp_task_slab)
    438			return -ENOMEM;
    439	}
    440	lima_pp_task_slab_refcnt++;
    441
    442	pipe->frame_size = frame_size;
    443	pipe->task_slab = lima_pp_task_slab;
    444
    445	pipe->task_validate = lima_pp_task_validate;
    446	pipe->task_run = lima_pp_task_run;
    447	pipe->task_fini = lima_pp_task_fini;
    448	pipe->task_error = lima_pp_task_error;
    449	pipe->task_mmu_error = lima_pp_task_mmu_error;
    450
    451	return 0;
    452}
    453
    454void lima_pp_pipe_fini(struct lima_device *dev)
    455{
    456	if (!--lima_pp_task_slab_refcnt) {
    457		kmem_cache_destroy(lima_pp_task_slab);
    458		lima_pp_task_slab = NULL;
    459	}
    460}