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

vgic-v2-cpuif-proxy.c (2074B)


      1// SPDX-License-Identifier: GPL-2.0-only
      2/*
      3 * Copyright (C) 2012-2015 - ARM Ltd
      4 * Author: Marc Zyngier <marc.zyngier@arm.com>
      5 */
      6
      7#include <hyp/adjust_pc.h>
      8
      9#include <linux/compiler.h>
     10#include <linux/irqchip/arm-gic.h>
     11#include <linux/kvm_host.h>
     12#include <linux/swab.h>
     13
     14#include <asm/kvm_emulate.h>
     15#include <asm/kvm_hyp.h>
     16#include <asm/kvm_mmu.h>
     17
     18static bool __is_be(struct kvm_vcpu *vcpu)
     19{
     20	if (vcpu_mode_is_32bit(vcpu))
     21		return !!(read_sysreg_el2(SYS_SPSR) & PSR_AA32_E_BIT);
     22
     23	return !!(read_sysreg(SCTLR_EL1) & SCTLR_ELx_EE);
     24}
     25
     26/*
     27 * __vgic_v2_perform_cpuif_access -- perform a GICV access on behalf of the
     28 *				     guest.
     29 *
     30 * @vcpu: the offending vcpu
     31 *
     32 * Returns:
     33 *  1: GICV access successfully performed
     34 *  0: Not a GICV access
     35 * -1: Illegal GICV access successfully performed
     36 */
     37int __vgic_v2_perform_cpuif_access(struct kvm_vcpu *vcpu)
     38{
     39	struct kvm *kvm = kern_hyp_va(vcpu->kvm);
     40	struct vgic_dist *vgic = &kvm->arch.vgic;
     41	phys_addr_t fault_ipa;
     42	void __iomem *addr;
     43	int rd;
     44
     45	/* Build the full address */
     46	fault_ipa  = kvm_vcpu_get_fault_ipa(vcpu);
     47	fault_ipa |= kvm_vcpu_get_hfar(vcpu) & GENMASK(11, 0);
     48
     49	/* If not for GICV, move on */
     50	if (fault_ipa <  vgic->vgic_cpu_base ||
     51	    fault_ipa >= (vgic->vgic_cpu_base + KVM_VGIC_V2_CPU_SIZE))
     52		return 0;
     53
     54	/* Reject anything but a 32bit access */
     55	if (kvm_vcpu_dabt_get_as(vcpu) != sizeof(u32)) {
     56		__kvm_skip_instr(vcpu);
     57		return -1;
     58	}
     59
     60	/* Not aligned? Don't bother */
     61	if (fault_ipa & 3) {
     62		__kvm_skip_instr(vcpu);
     63		return -1;
     64	}
     65
     66	rd = kvm_vcpu_dabt_get_rd(vcpu);
     67	addr  = kvm_vgic_global_state.vcpu_hyp_va;
     68	addr += fault_ipa - vgic->vgic_cpu_base;
     69
     70	if (kvm_vcpu_dabt_iswrite(vcpu)) {
     71		u32 data = vcpu_get_reg(vcpu, rd);
     72		if (__is_be(vcpu)) {
     73			/* guest pre-swabbed data, undo this for writel() */
     74			data = __kvm_swab32(data);
     75		}
     76		writel_relaxed(data, addr);
     77	} else {
     78		u32 data = readl_relaxed(addr);
     79		if (__is_be(vcpu)) {
     80			/* guest expects swabbed data */
     81			data = __kvm_swab32(data);
     82		}
     83		vcpu_set_reg(vcpu, rd, data);
     84	}
     85
     86	__kvm_skip_instr(vcpu);
     87
     88	return 1;
     89}