mirror of
https://github.com/AuxXxilium/linux_dsm_epyc7002.git
synced 2024-12-26 10:05:18 +07:00
104 lines
2.9 KiB
C
104 lines
2.9 KiB
C
|
/*
|
||
|
* GICv3 ITS emulation
|
||
|
*
|
||
|
* Copyright (C) 2015,2016 ARM Ltd.
|
||
|
* Author: Andre Przywara <andre.przywara@arm.com>
|
||
|
*
|
||
|
* This program is free software; you can redistribute it and/or modify
|
||
|
* it under the terms of the GNU General Public License version 2 as
|
||
|
* published by the Free Software Foundation.
|
||
|
*
|
||
|
* This program is distributed in the hope that it will be useful,
|
||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||
|
* GNU General Public License for more details.
|
||
|
*
|
||
|
* You should have received a copy of the GNU General Public License
|
||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||
|
*/
|
||
|
|
||
|
#include <linux/cpu.h>
|
||
|
#include <linux/kvm.h>
|
||
|
#include <linux/kvm_host.h>
|
||
|
#include <linux/interrupt.h>
|
||
|
|
||
|
#include <linux/irqchip/arm-gic-v3.h>
|
||
|
|
||
|
#include <asm/kvm_emulate.h>
|
||
|
#include <asm/kvm_arm.h>
|
||
|
#include <asm/kvm_mmu.h>
|
||
|
|
||
|
#include "vgic.h"
|
||
|
#include "vgic-mmio.h"
|
||
|
|
||
|
#define REGISTER_ITS_DESC(off, rd, wr, length, acc) \
|
||
|
{ \
|
||
|
.reg_offset = off, \
|
||
|
.len = length, \
|
||
|
.access_flags = acc, \
|
||
|
.its_read = rd, \
|
||
|
.its_write = wr, \
|
||
|
}
|
||
|
|
||
|
static unsigned long its_mmio_read_raz(struct kvm *kvm, struct vgic_its *its,
|
||
|
gpa_t addr, unsigned int len)
|
||
|
{
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
static void its_mmio_write_wi(struct kvm *kvm, struct vgic_its *its,
|
||
|
gpa_t addr, unsigned int len, unsigned long val)
|
||
|
{
|
||
|
/* Ignore */
|
||
|
}
|
||
|
|
||
|
static struct vgic_register_region its_registers[] = {
|
||
|
REGISTER_ITS_DESC(GITS_CTLR,
|
||
|
its_mmio_read_raz, its_mmio_write_wi, 4,
|
||
|
VGIC_ACCESS_32bit),
|
||
|
REGISTER_ITS_DESC(GITS_IIDR,
|
||
|
its_mmio_read_raz, its_mmio_write_wi, 4,
|
||
|
VGIC_ACCESS_32bit),
|
||
|
REGISTER_ITS_DESC(GITS_TYPER,
|
||
|
its_mmio_read_raz, its_mmio_write_wi, 8,
|
||
|
VGIC_ACCESS_64bit | VGIC_ACCESS_32bit),
|
||
|
REGISTER_ITS_DESC(GITS_CBASER,
|
||
|
its_mmio_read_raz, its_mmio_write_wi, 8,
|
||
|
VGIC_ACCESS_64bit | VGIC_ACCESS_32bit),
|
||
|
REGISTER_ITS_DESC(GITS_CWRITER,
|
||
|
its_mmio_read_raz, its_mmio_write_wi, 8,
|
||
|
VGIC_ACCESS_64bit | VGIC_ACCESS_32bit),
|
||
|
REGISTER_ITS_DESC(GITS_CREADR,
|
||
|
its_mmio_read_raz, its_mmio_write_wi, 8,
|
||
|
VGIC_ACCESS_64bit | VGIC_ACCESS_32bit),
|
||
|
REGISTER_ITS_DESC(GITS_BASER,
|
||
|
its_mmio_read_raz, its_mmio_write_wi, 0x40,
|
||
|
VGIC_ACCESS_64bit | VGIC_ACCESS_32bit),
|
||
|
REGISTER_ITS_DESC(GITS_IDREGS_BASE,
|
||
|
its_mmio_read_raz, its_mmio_write_wi, 0x30,
|
||
|
VGIC_ACCESS_32bit),
|
||
|
};
|
||
|
|
||
|
static int vgic_its_init_its(struct kvm *kvm, struct vgic_its *its)
|
||
|
{
|
||
|
struct vgic_io_device *iodev = &its->iodev;
|
||
|
int ret;
|
||
|
|
||
|
if (IS_VGIC_ADDR_UNDEF(its->vgic_its_base))
|
||
|
return -ENXIO;
|
||
|
|
||
|
iodev->regions = its_registers;
|
||
|
iodev->nr_regions = ARRAY_SIZE(its_registers);
|
||
|
kvm_iodevice_init(&iodev->dev, &kvm_io_gic_ops);
|
||
|
|
||
|
iodev->base_addr = its->vgic_its_base;
|
||
|
iodev->iodev_type = IODEV_ITS;
|
||
|
iodev->its = its;
|
||
|
mutex_lock(&kvm->slots_lock);
|
||
|
ret = kvm_io_bus_register_dev(kvm, KVM_MMIO_BUS, iodev->base_addr,
|
||
|
KVM_VGIC_V3_ITS_SIZE, &iodev->dev);
|
||
|
mutex_unlock(&kvm->slots_lock);
|
||
|
|
||
|
return ret;
|
||
|
}
|