Orange Pi5 kernel

Deprecated Linux kernel 5.10.110 for OrangePi 5/5B/5+ boards

3 Commits   0 Branches   0 Tags
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   1) // SPDX-License-Identifier: GPL-2.0-only
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   3)  * Copyright (C) 2016,2017 ARM Limited, All Rights Reserved.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   4)  * Author: Marc Zyngier <marc.zyngier@arm.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   5)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   6) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   7) #include <linux/interrupt.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   8) #include <linux/irq.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   9) #include <linux/irqdomain.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  10) #include <linux/msi.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  11) #include <linux/sched.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  12) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  13) #include <linux/irqchip/arm-gic-v4.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  14) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  15) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  16)  * WARNING: The blurb below assumes that you understand the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  17)  * intricacies of GICv3, GICv4, and how a guest's view of a GICv3 gets
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  18)  * translated into GICv4 commands. So it effectively targets at most
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  19)  * two individuals. You know who you are.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  20)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  21)  * The core GICv4 code is designed to *avoid* exposing too much of the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  22)  * core GIC code (that would in turn leak into the hypervisor code),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  23)  * and instead provide a hypervisor agnostic interface to the HW (of
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  24)  * course, the astute reader will quickly realize that hypervisor
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  25)  * agnostic actually means KVM-specific - what were you thinking?).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  26)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  27)  * In order to achieve a modicum of isolation, we try to hide most of
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  28)  * the GICv4 "stuff" behind normal irqchip operations:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  29)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  30)  * - Any guest-visible VLPI is backed by a Linux interrupt (and a
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  31)  *   physical LPI which gets unmapped when the guest maps the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  32)  *   VLPI). This allows the same DevID/EventID pair to be either
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  33)  *   mapped to the LPI (host) or the VLPI (guest). Note that this is
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  34)  *   exclusive, and you cannot have both.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  35)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  36)  * - Enabling/disabling a VLPI is done by issuing mask/unmask calls.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  37)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  38)  * - Guest INT/CLEAR commands are implemented through
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  39)  *   irq_set_irqchip_state().
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  40)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  41)  * - The *bizarre* stuff (mapping/unmapping an interrupt to a VLPI, or
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  42)  *   issuing an INV after changing a priority) gets shoved into the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  43)  *   irq_set_vcpu_affinity() method. While this is quite horrible
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  44)  *   (let's face it, this is the irqchip version of an ioctl), it
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  45)  *   confines the crap to a single location. And map/unmap really is
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  46)  *   about setting the affinity of a VLPI to a vcpu, so only INV is
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  47)  *   majorly out of place. So there.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  48)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  49)  * A number of commands are simply not provided by this interface, as
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  50)  * they do not make direct sense. For example, MAPD is purely local to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  51)  * the virtual ITS (because it references a virtual device, and the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  52)  * physical ITS is still very much in charge of the physical
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  53)  * device). Same goes for things like MAPC (the physical ITS deals
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  54)  * with the actual vPE affinity, and not the braindead concept of
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  55)  * collection). SYNC is not provided either, as each and every command
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  56)  * is followed by a VSYNC. This could be relaxed in the future, should
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  57)  * this be seen as a bottleneck (yes, this means *never*).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  58)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  59)  * But handling VLPIs is only one side of the job of the GICv4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  60)  * code. The other (darker) side is to take care of the doorbell
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  61)  * interrupts which are delivered when a VLPI targeting a non-running
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  62)  * vcpu is being made pending.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  63)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  64)  * The choice made here is that each vcpu (VPE in old northern GICv4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  65)  * dialect) gets a single doorbell LPI, no matter how many interrupts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  66)  * are targeting it. This has a nice property, which is that the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  67)  * interrupt becomes a handle for the VPE, and that the hypervisor
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  68)  * code can manipulate it through the normal interrupt API:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  69)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  70)  * - VMs (or rather the VM abstraction that matters to the GIC)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  71)  *   contain an irq domain where each interrupt maps to a VPE. In
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  72)  *   turn, this domain sits on top of the normal LPI allocator, and a
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  73)  *   specially crafted irq_chip implementation.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  74)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  75)  * - mask/unmask do what is expected on the doorbell interrupt.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  76)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  77)  * - irq_set_affinity is used to move a VPE from one redistributor to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  78)  *   another.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  79)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  80)  * - irq_set_vcpu_affinity once again gets hijacked for the purpose of
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  81)  *   creating a new sub-API, namely scheduling/descheduling a VPE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  82)  *   (which involves programming GICR_V{PROP,PEND}BASER) and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  83)  *   performing INVALL operations.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  84)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  85) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  86) static struct irq_domain *gic_domain;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  87) static const struct irq_domain_ops *vpe_domain_ops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  88) static const struct irq_domain_ops *sgi_domain_ops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  89) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  90) static bool has_v4_1(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  91) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  92) 	return !!sgi_domain_ops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  93) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  94) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  95) static int its_alloc_vcpu_sgis(struct its_vpe *vpe, int idx)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  96) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  97) 	char *name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  98) 	int sgi_base;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  99) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) 	if (!has_v4_1())
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) 		return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) 	name = kasprintf(GFP_KERNEL, "GICv4-sgi-%d", task_pid_nr(current));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) 	if (!name)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) 		goto err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) 	vpe->fwnode = irq_domain_alloc_named_id_fwnode(name, idx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) 	if (!vpe->fwnode)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) 		goto err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) 	kfree(name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) 	name = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) 	vpe->sgi_domain = irq_domain_create_linear(vpe->fwnode, 16,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) 						   sgi_domain_ops, vpe);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) 	if (!vpe->sgi_domain)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) 		goto err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) 	sgi_base = __irq_domain_alloc_irqs(vpe->sgi_domain, -1, 16,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) 					       NUMA_NO_NODE, vpe,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) 					       false, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) 	if (sgi_base <= 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) 		goto err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) err:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) 	if (vpe->sgi_domain)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) 		irq_domain_remove(vpe->sgi_domain);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) 	if (vpe->fwnode)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) 		irq_domain_free_fwnode(vpe->fwnode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) 	kfree(name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) 	return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) int its_alloc_vcpu_irqs(struct its_vm *vm)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) 	int vpe_base_irq, i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) 	vm->fwnode = irq_domain_alloc_named_id_fwnode("GICv4-vpe",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) 						      task_pid_nr(current));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) 	if (!vm->fwnode)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) 		goto err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) 	vm->domain = irq_domain_create_hierarchy(gic_domain, 0, vm->nr_vpes,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) 						 vm->fwnode, vpe_domain_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) 						 vm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) 	if (!vm->domain)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) 		goto err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) 	for (i = 0; i < vm->nr_vpes; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) 		vm->vpes[i]->its_vm = vm;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) 		vm->vpes[i]->idai = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) 	vpe_base_irq = __irq_domain_alloc_irqs(vm->domain, -1, vm->nr_vpes,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) 					       NUMA_NO_NODE, vm,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) 					       false, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) 	if (vpe_base_irq <= 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) 		goto err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) 	for (i = 0; i < vm->nr_vpes; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) 		int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) 		vm->vpes[i]->irq = vpe_base_irq + i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) 		ret = its_alloc_vcpu_sgis(vm->vpes[i], i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) 		if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) 			goto err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) err:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) 	if (vm->domain)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) 		irq_domain_remove(vm->domain);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) 	if (vm->fwnode)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) 		irq_domain_free_fwnode(vm->fwnode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) 	return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) static void its_free_sgi_irqs(struct its_vm *vm)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) 	int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) 	if (!has_v4_1())
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) 		return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) 	for (i = 0; i < vm->nr_vpes; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) 		unsigned int irq = irq_find_mapping(vm->vpes[i]->sgi_domain, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) 		if (WARN_ON(!irq))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) 			continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) 		irq_domain_free_irqs(irq, 16);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) 		irq_domain_remove(vm->vpes[i]->sgi_domain);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) 		irq_domain_free_fwnode(vm->vpes[i]->fwnode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) void its_free_vcpu_irqs(struct its_vm *vm)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) 	its_free_sgi_irqs(vm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) 	irq_domain_free_irqs(vm->vpes[0]->irq, vm->nr_vpes);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) 	irq_domain_remove(vm->domain);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) 	irq_domain_free_fwnode(vm->fwnode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) static int its_send_vpe_cmd(struct its_vpe *vpe, struct its_cmd_info *info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) 	return irq_set_vcpu_affinity(vpe->irq, info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) int its_make_vpe_non_resident(struct its_vpe *vpe, bool db)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) 	struct irq_desc *desc = irq_to_desc(vpe->irq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) 	struct its_cmd_info info = { };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) 	int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) 	WARN_ON(preemptible());
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) 	info.cmd_type = DESCHEDULE_VPE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) 	if (has_v4_1()) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) 		/* GICv4.1 can directly deal with doorbells */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) 		info.req_db = db;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) 	} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) 		/* Undo the nested disable_irq() calls... */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) 		while (db && irqd_irq_disabled(&desc->irq_data))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) 			enable_irq(vpe->irq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) 	ret = its_send_vpe_cmd(vpe, &info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) 	if (!ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) 		vpe->resident = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) 	vpe->ready = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) 	return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) int its_make_vpe_resident(struct its_vpe *vpe, bool g0en, bool g1en)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) 	struct its_cmd_info info = { };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) 	int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) 	WARN_ON(preemptible());
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) 	info.cmd_type = SCHEDULE_VPE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) 	if (has_v4_1()) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) 		info.g0en = g0en;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) 		info.g1en = g1en;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) 	} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) 		/* Disabled the doorbell, as we're about to enter the guest */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) 		disable_irq_nosync(vpe->irq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) 	ret = its_send_vpe_cmd(vpe, &info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) 	if (!ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) 		vpe->resident = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) 	return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) int its_commit_vpe(struct its_vpe *vpe)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) 	struct its_cmd_info info = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) 		.cmd_type = COMMIT_VPE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) 	};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) 	int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) 	WARN_ON(preemptible());
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) 	ret = its_send_vpe_cmd(vpe, &info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) 	if (!ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) 		vpe->ready = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) 	return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) int its_invall_vpe(struct its_vpe *vpe)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) 	struct its_cmd_info info = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) 		.cmd_type = INVALL_VPE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) 	};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) 	return its_send_vpe_cmd(vpe, &info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) int its_map_vlpi(int irq, struct its_vlpi_map *map)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) 	struct its_cmd_info info = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) 		.cmd_type = MAP_VLPI,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) 		{
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) 			.map      = map,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) 		},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) 	};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) 	int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) 	 * The host will never see that interrupt firing again, so it
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) 	 * is vital that we don't do any lazy masking.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) 	irq_set_status_flags(irq, IRQ_DISABLE_UNLAZY);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) 	ret = irq_set_vcpu_affinity(irq, &info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) 	if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) 		irq_clear_status_flags(irq, IRQ_DISABLE_UNLAZY);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) 	return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) int its_get_vlpi(int irq, struct its_vlpi_map *map)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) 	struct its_cmd_info info = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) 		.cmd_type = GET_VLPI,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) 		{
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) 			.map      = map,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) 		},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) 	};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) 	return irq_set_vcpu_affinity(irq, &info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) int its_unmap_vlpi(int irq)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) 	irq_clear_status_flags(irq, IRQ_DISABLE_UNLAZY);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) 	return irq_set_vcpu_affinity(irq, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) int its_prop_update_vlpi(int irq, u8 config, bool inv)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) 	struct its_cmd_info info = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) 		.cmd_type = inv ? PROP_UPDATE_AND_INV_VLPI : PROP_UPDATE_VLPI,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) 		{
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) 			.config   = config,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) 		},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) 	};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) 	return irq_set_vcpu_affinity(irq, &info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) int its_prop_update_vsgi(int irq, u8 priority, bool group)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) 	struct its_cmd_info info = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) 		.cmd_type = PROP_UPDATE_VSGI,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) 		{
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) 			.priority	= priority,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) 			.group		= group,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) 		},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) 	};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) 	return irq_set_vcpu_affinity(irq, &info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) int its_init_v4(struct irq_domain *domain,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) 		const struct irq_domain_ops *vpe_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) 		const struct irq_domain_ops *sgi_ops)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) 	if (domain) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) 		pr_info("ITS: Enabling GICv4 support\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) 		gic_domain = domain;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) 		vpe_domain_ops = vpe_ops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) 		sgi_domain_ops = sgi_ops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) 		return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) 	pr_err("ITS: No GICv4 VPE domain allocated\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) 	return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) }