Hi Andre,
On 03/16/2017 11:20 AM, Andre Przywara wrote:
This introduces the ITS command handler for the CLEAR command, which
clears the pending state of an LPI.
This removes a not-yet injected, but already queued IRQ from a VCPU.
Signed-off-by: Andre Przywara <andre.przyw...@arm.com>
---
xen/arch/arm/vgic-v3-its.c | 35 +++++++++++++++++++++++++++++++++--
1 file changed, 33 insertions(+), 2 deletions(-)
diff --git a/xen/arch/arm/vgic-v3-its.c b/xen/arch/arm/vgic-v3-its.c
index 267a573..e808f43 100644
--- a/xen/arch/arm/vgic-v3-its.c
+++ b/xen/arch/arm/vgic-v3-its.c
@@ -131,8 +131,8 @@ static void put_devid_evid(struct virt_its *its, struct
vits_itte *itte)
* protect the ITTs with their less-than-page-size granularity.
* Takes and drops the its_lock.
*/
-bool read_itte(struct virt_its *its, uint32_t devid, uint32_t evid,
- struct vcpu **vcpu, uint32_t *vlpi)
+static bool read_itte(struct virt_its *its, uint32_t devid, uint32_t evid,
NIT: Please mention in the commit message why you turned those functions
to static.
+ struct vcpu **vcpu, uint32_t *vlpi)
{
struct vits_itte *itte;
int collid;
@@ -216,6 +216,34 @@ static uint64_t its_cmd_mask_field(uint64_t *its_cmd,
#define its_cmd_get_target_addr(cmd) its_cmd_mask_field(cmd, 2, 16, 32)
#define its_cmd_get_validbit(cmd) its_cmd_mask_field(cmd, 2, 63, 1)
+static int its_handle_clear(struct virt_its *its, uint64_t *cmdptr)
+{
+ uint32_t devid = its_cmd_get_deviceid(cmdptr);
+ uint32_t eventid = its_cmd_get_id(cmdptr);
+ struct pending_irq *pirq;
+ struct vcpu *vcpu;
+ uint32_t vlpi;
+
+ if ( !read_itte(its, devid, eventid, &vcpu, &vlpi) )
+ return -1;
+
+ /* Remove a pending, but not yet injected guest IRQ. */
Copying Stefano's comment from last year:
"We need to check that the vlpi hasn't already been added to an LR
register. We can do that with GIC_IRQ_GUEST_VISIBLE.
In case GIC_IRQ_GUEST_VISIBLE is set, we need to clear the lr
(clear_lr). If we don't handle this case, we should at least print a
warning."
+ pirq = lpi_to_pending(vcpu, vlpi, false);
+ if ( pirq )
+ {
+ clear_bit(GIC_IRQ_GUEST_QUEUED, &pirq->status);
+ gic_remove_from_queues(vcpu, vlpi);
+
+ /* Mark this pending IRQ struct as availabe again. */
+ if ( !test_bit(GIC_IRQ_GUEST_VISIBLE, &pirq->status) )
+ pirq->irq = 0;
+ }
+
+ clear_bit(vlpi - LPI_OFFSET, vcpu->arch.vgic.pendtable);
+
+ return 0;
+}
+
#define ITS_CMD_BUFFER_SIZE(baser) ((((baser) & 0xff) + 1) << 12)
static int vgic_its_handle_cmds(struct domain *d, struct virt_its *its,
@@ -236,6 +264,9 @@ static int vgic_its_handle_cmds(struct domain *d, struct
virt_its *its,
cmdptr = its->cmdbuf + (its->creadr / sizeof(*its->cmdbuf));
switch (its_cmd_get_command(cmdptr))
{
+ case GITS_CMD_CLEAR:
+ its_handle_clear(its, cmdptr);
Should not you check the return for its_handle_clear?
+ break;
case GITS_CMD_SYNC:
/* We handle ITS commands synchronously, so we ignore SYNC. */
break;
Regards,
--
Julien Grall
_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel