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

tu102.c (5635B)


      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 "priv.h"
     23
     24#include <core/memory.h>
     25#include <subdev/mc.h>
     26#include <subdev/mmu.h>
     27#include <engine/fifo.h>
     28
     29#include <nvif/class.h>
     30
     31static void
     32tu102_fault_buffer_intr(struct nvkm_fault_buffer *buffer, bool enable)
     33{
     34	/*XXX: Earlier versions of RM touched the old regs on Turing,
     35	 *     which don't appear to actually work anymore, but newer
     36	 *     versions of RM don't appear to touch anything at all..
     37	 */
     38	struct nvkm_device *device = buffer->fault->subdev.device;
     39
     40	nvkm_mc_intr_mask(device, NVKM_SUBDEV_FAULT, 0, enable);
     41}
     42
     43static void
     44tu102_fault_buffer_fini(struct nvkm_fault_buffer *buffer)
     45{
     46	struct nvkm_device *device = buffer->fault->subdev.device;
     47	const u32 foff = buffer->id * 0x20;
     48
     49	/* Disable the fault interrupts */
     50	nvkm_wr32(device, 0xb81408, 0x1);
     51	nvkm_wr32(device, 0xb81410, 0x10);
     52
     53	nvkm_mask(device, 0xb83010 + foff, 0x80000000, 0x00000000);
     54}
     55
     56static void
     57tu102_fault_buffer_init(struct nvkm_fault_buffer *buffer)
     58{
     59	struct nvkm_device *device = buffer->fault->subdev.device;
     60	const u32 foff = buffer->id * 0x20;
     61
     62	/* Enable the fault interrupts */
     63	nvkm_wr32(device, 0xb81208, 0x1);
     64	nvkm_wr32(device, 0xb81210, 0x10);
     65
     66	nvkm_mask(device, 0xb83010 + foff, 0xc0000000, 0x40000000);
     67	nvkm_wr32(device, 0xb83004 + foff, upper_32_bits(buffer->addr));
     68	nvkm_wr32(device, 0xb83000 + foff, lower_32_bits(buffer->addr));
     69	nvkm_mask(device, 0xb83010 + foff, 0x80000000, 0x80000000);
     70}
     71
     72static void
     73tu102_fault_buffer_info(struct nvkm_fault_buffer *buffer)
     74{
     75	struct nvkm_device *device = buffer->fault->subdev.device;
     76	const u32 foff = buffer->id * 0x20;
     77
     78	nvkm_mask(device, 0xb83010 + foff, 0x40000000, 0x40000000);
     79
     80	buffer->entries = nvkm_rd32(device, 0xb83010 + foff) & 0x000fffff;
     81	buffer->get = 0xb83008 + foff;
     82	buffer->put = 0xb8300c + foff;
     83}
     84
     85static void
     86tu102_fault_intr_fault(struct nvkm_fault *fault)
     87{
     88	struct nvkm_subdev *subdev = &fault->subdev;
     89	struct nvkm_device *device = subdev->device;
     90	struct nvkm_fault_data info;
     91	const u32 addrlo = nvkm_rd32(device, 0xb83080);
     92	const u32 addrhi = nvkm_rd32(device, 0xb83084);
     93	const u32  info0 = nvkm_rd32(device, 0xb83088);
     94	const u32 insthi = nvkm_rd32(device, 0xb8308c);
     95	const u32  info1 = nvkm_rd32(device, 0xb83090);
     96
     97	info.addr = ((u64)addrhi << 32) | addrlo;
     98	info.inst = ((u64)insthi << 32) | (info0 & 0xfffff000);
     99	info.time = 0;
    100	info.engine = (info0 & 0x000000ff);
    101	info.valid  = (info1 & 0x80000000) >> 31;
    102	info.gpc    = (info1 & 0x1f000000) >> 24;
    103	info.hub    = (info1 & 0x00100000) >> 20;
    104	info.access = (info1 & 0x000f0000) >> 16;
    105	info.client = (info1 & 0x00007f00) >> 8;
    106	info.reason = (info1 & 0x0000001f);
    107
    108	nvkm_fifo_fault(device->fifo, &info);
    109}
    110
    111static void
    112tu102_fault_intr(struct nvkm_fault *fault)
    113{
    114	struct nvkm_subdev *subdev = &fault->subdev;
    115	struct nvkm_device *device = subdev->device;
    116	u32 stat = nvkm_rd32(device, 0xb83094);
    117
    118	if (stat & 0x80000000) {
    119		tu102_fault_intr_fault(fault);
    120		nvkm_wr32(device, 0xb83094, 0x80000000);
    121		stat &= ~0x80000000;
    122	}
    123
    124	if (stat & 0x00000200) {
    125		/* Clear the associated interrupt flag */
    126		nvkm_wr32(device, 0xb81010, 0x10);
    127
    128		if (fault->buffer[0]) {
    129			nvkm_event_send(&fault->event, 1, 0, NULL, 0);
    130			stat &= ~0x00000200;
    131		}
    132	}
    133
    134	/* Replayable MMU fault */
    135	if (stat & 0x00000100) {
    136		/* Clear the associated interrupt flag */
    137		nvkm_wr32(device, 0xb81008, 0x1);
    138
    139		if (fault->buffer[1]) {
    140			nvkm_event_send(&fault->event, 1, 1, NULL, 0);
    141			stat &= ~0x00000100;
    142		}
    143	}
    144
    145	if (stat) {
    146		nvkm_debug(subdev, "intr %08x\n", stat);
    147	}
    148}
    149
    150static void
    151tu102_fault_fini(struct nvkm_fault *fault)
    152{
    153	nvkm_notify_put(&fault->nrpfb);
    154	if (fault->buffer[0])
    155		fault->func->buffer.fini(fault->buffer[0]);
    156	/*XXX: disable priv faults */
    157}
    158
    159static void
    160tu102_fault_init(struct nvkm_fault *fault)
    161{
    162	/*XXX: enable priv faults */
    163	fault->func->buffer.init(fault->buffer[0]);
    164	nvkm_notify_get(&fault->nrpfb);
    165}
    166
    167static const struct nvkm_fault_func
    168tu102_fault = {
    169	.oneinit = gv100_fault_oneinit,
    170	.init = tu102_fault_init,
    171	.fini = tu102_fault_fini,
    172	.intr = tu102_fault_intr,
    173	.buffer.nr = 2,
    174	.buffer.entry_size = 32,
    175	.buffer.info = tu102_fault_buffer_info,
    176	.buffer.pin = gp100_fault_buffer_pin,
    177	.buffer.init = tu102_fault_buffer_init,
    178	.buffer.fini = tu102_fault_buffer_fini,
    179	.buffer.intr = tu102_fault_buffer_intr,
    180	.user = { { 0, 0, VOLTA_FAULT_BUFFER_A }, 1 },
    181};
    182
    183int
    184tu102_fault_new(struct nvkm_device *device, enum nvkm_subdev_type type, int inst,
    185		struct nvkm_fault **pfault)
    186{
    187	return nvkm_fault_new_(&tu102_fault, device, type, inst, pfault);
    188}