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

core507d.c (5167B)


      1/*
      2 * Copyright 2018 Red Hat 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#include "core.h"
     23#include "head.h"
     24
     25#include <nvif/cl507d.h>
     26#include <nvif/push507c.h>
     27#include <nvif/timer.h>
     28
     29#include <nvhw/class/cl507d.h>
     30
     31#include "nouveau_bo.h"
     32
     33int
     34core507d_update(struct nv50_core *core, u32 *interlock, bool ntfy)
     35{
     36	struct nvif_push *push = core->chan.push;
     37	int ret;
     38
     39	if ((ret = PUSH_WAIT(push, (ntfy ? 2 : 0) + 3)))
     40		return ret;
     41
     42	if (ntfy) {
     43		PUSH_MTHD(push, NV507D, SET_NOTIFIER_CONTROL,
     44			  NVDEF(NV507D, SET_NOTIFIER_CONTROL, MODE, WRITE) |
     45			  NVVAL(NV507D, SET_NOTIFIER_CONTROL, OFFSET, NV50_DISP_CORE_NTFY >> 2) |
     46			  NVDEF(NV507D, SET_NOTIFIER_CONTROL, NOTIFY, ENABLE));
     47	}
     48
     49	PUSH_MTHD(push, NV507D, UPDATE, interlock[NV50_DISP_INTERLOCK_BASE] |
     50					interlock[NV50_DISP_INTERLOCK_OVLY] |
     51		  NVDEF(NV507D, UPDATE, NOT_DRIVER_FRIENDLY, FALSE) |
     52		  NVDEF(NV507D, UPDATE, NOT_DRIVER_UNFRIENDLY, FALSE) |
     53		  NVDEF(NV507D, UPDATE, INHIBIT_INTERRUPTS, FALSE),
     54
     55				SET_NOTIFIER_CONTROL,
     56		  NVDEF(NV507D, SET_NOTIFIER_CONTROL, NOTIFY, DISABLE));
     57
     58	return PUSH_KICK(push);
     59}
     60
     61int
     62core507d_ntfy_wait_done(struct nouveau_bo *bo, u32 offset,
     63			struct nvif_device *device)
     64{
     65	s64 time = nvif_msec(device, 2000ULL,
     66		if (NVBO_TD32(bo, offset, NV_DISP_CORE_NOTIFIER_1, COMPLETION_0, DONE, ==, TRUE))
     67			break;
     68		usleep_range(1, 2);
     69	);
     70	return time < 0 ? time : 0;
     71}
     72
     73void
     74core507d_ntfy_init(struct nouveau_bo *bo, u32 offset)
     75{
     76	NVBO_WR32(bo, offset, NV_DISP_CORE_NOTIFIER_1, COMPLETION_0,
     77			NVDEF(NV_DISP_CORE_NOTIFIER_1, COMPLETION_0, DONE, FALSE));
     78}
     79
     80int
     81core507d_read_caps(struct nv50_disp *disp)
     82{
     83	struct nvif_push *push = disp->core->chan.push;
     84	int ret;
     85
     86	ret = PUSH_WAIT(push, 6);
     87	if (ret)
     88		return ret;
     89
     90	PUSH_MTHD(push, NV507D, SET_NOTIFIER_CONTROL,
     91		  NVDEF(NV507D, SET_NOTIFIER_CONTROL, MODE, WRITE) |
     92		  NVVAL(NV507D, SET_NOTIFIER_CONTROL, OFFSET, NV50_DISP_CORE_NTFY >> 2) |
     93		  NVDEF(NV507D, SET_NOTIFIER_CONTROL, NOTIFY, ENABLE));
     94
     95	PUSH_MTHD(push, NV507D, GET_CAPABILITIES, 0x00000000);
     96
     97	PUSH_MTHD(push, NV507D, SET_NOTIFIER_CONTROL,
     98		  NVDEF(NV507D, SET_NOTIFIER_CONTROL, NOTIFY, DISABLE));
     99
    100	return PUSH_KICK(push);
    101}
    102
    103int
    104core507d_caps_init(struct nouveau_drm *drm, struct nv50_disp *disp)
    105{
    106	struct nv50_core *core = disp->core;
    107	struct nouveau_bo *bo = disp->sync;
    108	s64 time;
    109	int ret;
    110
    111	NVBO_WR32(bo, NV50_DISP_CORE_NTFY, NV_DISP_CORE_NOTIFIER_1, CAPABILITIES_1,
    112				     NVDEF(NV_DISP_CORE_NOTIFIER_1, CAPABILITIES_1, DONE, FALSE));
    113
    114	ret = core507d_read_caps(disp);
    115	if (ret < 0)
    116		return ret;
    117
    118	time = nvif_msec(core->chan.base.device, 2000ULL,
    119			 if (NVBO_TD32(bo, NV50_DISP_CORE_NTFY,
    120				       NV_DISP_CORE_NOTIFIER_1, CAPABILITIES_1, DONE, ==, TRUE))
    121				 break;
    122			 usleep_range(1, 2);
    123			 );
    124	if (time < 0)
    125		NV_ERROR(drm, "core caps notifier timeout\n");
    126
    127	return 0;
    128}
    129
    130int
    131core507d_init(struct nv50_core *core)
    132{
    133	struct nvif_push *push = core->chan.push;
    134	int ret;
    135
    136	if ((ret = PUSH_WAIT(push, 2)))
    137		return ret;
    138
    139	PUSH_MTHD(push, NV507D, SET_CONTEXT_DMA_NOTIFIER, core->chan.sync.handle);
    140	return PUSH_KICK(push);
    141}
    142
    143static const struct nv50_core_func
    144core507d = {
    145	.init = core507d_init,
    146	.ntfy_init = core507d_ntfy_init,
    147	.caps_init = core507d_caps_init,
    148	.ntfy_wait_done = core507d_ntfy_wait_done,
    149	.update = core507d_update,
    150	.head = &head507d,
    151	.dac = &dac507d,
    152	.sor = &sor507d,
    153	.pior = &pior507d,
    154};
    155
    156int
    157core507d_new_(const struct nv50_core_func *func, struct nouveau_drm *drm,
    158	      s32 oclass, struct nv50_core **pcore)
    159{
    160	struct nv50_disp_core_channel_dma_v0 args = {};
    161	struct nv50_disp *disp = nv50_disp(drm->dev);
    162	struct nv50_core *core;
    163	int ret;
    164
    165	if (!(core = *pcore = kzalloc(sizeof(*core), GFP_KERNEL)))
    166		return -ENOMEM;
    167	core->func = func;
    168
    169	ret = nv50_dmac_create(&drm->client.device, &disp->disp->object,
    170			       &oclass, 0, &args, sizeof(args),
    171			       disp->sync->offset, &core->chan);
    172	if (ret) {
    173		NV_ERROR(drm, "core%04x allocation failed: %d\n", oclass, ret);
    174		return ret;
    175	}
    176
    177	return 0;
    178}
    179
    180int
    181core507d_new(struct nouveau_drm *drm, s32 oclass, struct nv50_core **pcore)
    182{
    183	return core507d_new_(&core507d, drm, oclass, pcore);
    184}