linux-arm-kernel.lists.infradead.org archive mirror
 help / color / mirror / Atom feed
From: eric.auger@redhat.com (Eric Auger)
To: linux-arm-kernel@lists.infradead.org
Subject: [PATCH v5 20/22] KVM: arm64: vgic-its: Device table save/restore
Date: Fri, 14 Apr 2017 12:15:32 +0200	[thread overview]
Message-ID: <1492164934-988-21-git-send-email-eric.auger@redhat.com> (raw)
In-Reply-To: <1492164934-988-1-git-send-email-eric.auger@redhat.com>

This patch saves the device table entries into guest RAM.
Both flat table and 2 stage tables are supported. DeviceId
indexing is used.

For each device listed in the device table, we also save
the translation table using the vgic_its_save/restore_itt
routines.

On restore, devices are re-allocated and their ite are
re-built.

Signed-off-by: Eric Auger <eric.auger@redhat.com>

---
v4 -> v5:
- sort the device list by deviceid on device table save
- use defines for shifts and masks
- use abi->dte_esz
- clatify entry sizes for L1 and L2 tables

v3 -> v4:
- use the new proto for its_alloc_device
- compute_next_devid_offset, vgic_its_flush/restore_itt
  become static in this patch
- change in the DTE entry format with the introduction of the
  valid bit and next field width decrease; ittaddr encoded
  on its full range
- fix handle_l1_entry entry handling
- correct vgic_its_table_restore error handling

v2 -> v3:
- fix itt_addr bitmask in vgic_its_restore_dte
- addition of return 0 in vgic_its_restore_ite moved to
  the ITE related patch

v1 -> v2:
- use 8 byte format for DTE and ITE
- support 2 stage format
- remove kvm parameter
- ITT flush/restore moved in a separate patch
- use deviceid indexing
---
 virt/kvm/arm/vgic/vgic-its.c | 183 +++++++++++++++++++++++++++++++++++++++++--
 virt/kvm/arm/vgic/vgic.h     |   7 ++
 2 files changed, 185 insertions(+), 5 deletions(-)

diff --git a/virt/kvm/arm/vgic/vgic-its.c b/virt/kvm/arm/vgic/vgic-its.c
index b02fc3f..86dfc6c 100644
--- a/virt/kvm/arm/vgic/vgic-its.c
+++ b/virt/kvm/arm/vgic/vgic-its.c
@@ -1682,7 +1682,8 @@ int vgic_its_attr_regs_access(struct kvm_device *dev,
 	return ret;
 }
 
-u32 compute_next_devid_offset(struct list_head *h, struct its_device *dev)
+static u32 compute_next_devid_offset(struct list_head *h,
+				     struct its_device *dev)
 {
 	struct list_head *e = &dev->dev_list;
 	struct its_device *next;
@@ -1858,7 +1859,7 @@ static int vgic_its_ite_cmp(void *priv, struct list_head *a,
 		return 1;
 }
 
-int vgic_its_save_itt(struct vgic_its *its, struct its_device *device)
+static int vgic_its_save_itt(struct vgic_its *its, struct its_device *device)
 {
 	const struct vgic_its_abi *abi = vgic_its_get_abi(its);
 	gpa_t base = device->itt_addr;
@@ -1877,7 +1878,7 @@ int vgic_its_save_itt(struct vgic_its *its, struct its_device *device)
 	return 0;
 }
 
-int vgic_its_restore_itt(struct vgic_its *its, struct its_device *dev)
+static int vgic_its_restore_itt(struct vgic_its *its, struct its_device *dev)
 {
 	const struct vgic_its_abi *abi = vgic_its_get_abi(its);
 	gpa_t base = dev->itt_addr;
@@ -1895,12 +1896,161 @@ int vgic_its_restore_itt(struct vgic_its *its, struct its_device *dev)
 }
 
 /**
+ * vgic_its_save_dte - Save a device table entry at a given GPA
+ *
+ * @its: ITS handle
+ * @dev: ITS device
+ * @ptr: GPA
+ */
+static int vgic_its_save_dte(struct vgic_its *its, struct its_device *dev,
+			     gpa_t ptr, int dte_esz)
+{
+	struct kvm *kvm = its->dev->kvm;
+	u64 val, itt_addr_field;
+	int ret;
+	u32 next_offset;
+
+	itt_addr_field = dev->itt_addr >> 8;
+	next_offset = compute_next_devid_offset(&its->device_list, dev);
+	val = (1ULL << KVM_ITS_DTE_VALID_SHIFT |
+	       ((u64)next_offset << KVM_ITS_DTE_NEXT_SHIFT) |
+	       (itt_addr_field << KVM_ITS_DTE_ITTADDR_SHIFT) |
+		(dev->nb_eventid_bits - 1));
+	val = cpu_to_le64(val);
+	ret = kvm_write_guest(kvm, ptr, &val, dte_esz);
+	return ret;
+}
+
+/**
+ * vgic_its_restore_dte - restore a device table entry
+ *
+ * @its: its handle
+ * @id: device id the DTE corresponds to
+ * @ptr: kernel VA where the 8 byte DTE is located
+ * @opaque: unused
+ * @next: offset to the next valid device id
+ *
+ * Return: < 0 on error, 0 otherwise
+ */
+static int vgic_its_restore_dte(struct vgic_its *its, u32 id,
+				void *ptr, void *opaque, u32 *next)
+{
+	struct its_device *dev;
+	gpa_t itt_addr;
+	u8 nb_eventid_bits;
+	u64 entry = *(u64 *)ptr;
+	bool valid;
+	int ret;
+
+	entry = le64_to_cpu(entry);
+
+	valid = entry >> KVM_ITS_DTE_VALID_SHIFT;
+	nb_eventid_bits = (entry & KVM_ITS_DTE_SIZE_MASK) + 1;
+	itt_addr = ((entry & KVM_ITS_DTE_ITTADDR_MASK)
+			>> KVM_ITS_DTE_ITTADDR_SHIFT) << 8;
+	*next = 1;
+
+	if (!valid)
+		return 0;
+
+	/* dte entry is valid */
+	*next = (entry & KVM_ITS_DTE_NEXT_MASK) >> KVM_ITS_DTE_NEXT_SHIFT;
+
+	ret = vgic_its_alloc_device(its, &dev, id,
+				    itt_addr, nb_eventid_bits);
+	if (ret)
+		return ret;
+	ret = vgic_its_restore_itt(its, dev);
+
+	return ret;
+}
+
+static int vgic_its_device_cmp(void *priv, struct list_head *a,
+			       struct list_head *b)
+{
+	struct its_device *deva = container_of(a, struct its_device, dev_list);
+	struct its_device *devb = container_of(b, struct its_device, dev_list);
+
+	if (deva->device_id < devb->device_id)
+		return -1;
+	else
+		return 1;
+}
+
+/**
  * vgic_its_save_device_tables - Save the device table and all ITT
  * into guest RAM
+ *
+ * L1/L2 handling is hidden by vgic_its_check_id() helper which directly
+ * returns the GPA of the device entry
  */
 static int vgic_its_save_device_tables(struct vgic_its *its)
 {
-	return -ENXIO;
+	const struct vgic_its_abi *abi = vgic_its_get_abi(its);
+	struct its_device *dev;
+	int dte_esz = abi->dte_esz;
+	u64 baser;
+
+	baser = its->baser_device_table;
+
+	list_sort(NULL, &its->device_list, vgic_its_device_cmp);
+
+	list_for_each_entry(dev, &its->device_list, dev_list) {
+		int ret;
+		gpa_t eaddr;
+
+		if (!vgic_its_check_id(its, baser,
+				       dev->device_id, &eaddr))
+			return -EINVAL;
+
+		ret = vgic_its_save_itt(its, dev);
+		if (ret)
+			return ret;
+
+		ret = vgic_its_save_dte(its, dev, eaddr, dte_esz);
+		if (ret)
+			return ret;
+	}
+	return 0;
+}
+
+/**
+ * handle_l1_entry - callback used for L1 entries (2 stage case)
+ *
+ * @its: its handle
+ * @id: id
+ * @addr: kernel VA
+ * @opaque: unused
+ * @next_offset: offset to the next L1 entry: 0 if the last element
+ * was found, 1 otherwise
+ */
+static int handle_l1_entry(struct vgic_its *its, u32 id, void *addr,
+			   void *opaque, u32 *next_offset)
+{
+	const struct vgic_its_abi *abi = vgic_its_get_abi(its);
+	int l2_start_id = id * (SZ_64K / GITS_LVL1_ENTRY_SIZE);
+	u64 entry = *(u64 *)addr;
+	int ret, ite_esz = abi->ite_esz;
+	gpa_t gpa;
+
+	entry = le64_to_cpu(entry);
+	*next_offset = 1;
+
+	if (!(entry & BIT_ULL(63)))
+		return 0;
+
+	gpa = entry & GENMASK_ULL(51, 16);
+
+	ret = lookup_table(its, gpa, SZ_64K, ite_esz,
+			   l2_start_id, vgic_its_restore_dte, NULL);
+
+	if (ret == 1) {
+		/* last entry was found in this L2 table */
+		*next_offset = 0;
+		ret = 0;
+	}
+
+	return ret;
 }
 
 /**
@@ -1909,7 +2059,30 @@ static int vgic_its_save_device_tables(struct vgic_its *its)
  */
 static int vgic_its_restore_device_tables(struct vgic_its *its)
 {
-	return -ENXIO;
+	const struct vgic_its_abi *abi = vgic_its_get_abi(its);
+	u64 baser = its->baser_device_table;
+	int l1_esz, ret, l1_tbl_size = GITS_BASER_NR_PAGES(baser) * SZ_64K;
+	gpa_t l1_gpa;
+
+	l1_gpa = BASER_ADDRESS(baser);
+	if (!l1_gpa)
+		return 0;
+
+	if (baser & GITS_BASER_INDIRECT) {
+		l1_esz = 8;
+		ret = lookup_table(its, l1_gpa, l1_tbl_size, l1_esz, 0,
+				   handle_l1_entry, NULL);
+	} else {
+		l1_esz = abi->dte_esz;
+		ret = lookup_table(its, l1_gpa, l1_tbl_size, l1_esz, 0,
+				   vgic_its_restore_dte, NULL);
+	}
+
+	if (ret < 0)
+		return ret;
+
+	/* if last element was not found we have an issue here */
+	return ret ? 0 : -EINVAL;
 }
 
 static int vgic_its_save_cte(struct vgic_its *its,
diff --git a/virt/kvm/arm/vgic/vgic.h b/virt/kvm/arm/vgic/vgic.h
index ce57fbd..9bc52ef 100644
--- a/virt/kvm/arm/vgic/vgic.h
+++ b/virt/kvm/arm/vgic/vgic.h
@@ -85,6 +85,13 @@
 #define KVM_ITS_ITE_PINTID_SHIFT	16
 #define KVM_ITS_ITE_PINTID_MASK		GENMASK_ULL(47, 16)
 #define KVM_ITS_ITE_ICID_MASK		GENMASK_ULL(15, 0)
+#define KVM_ITS_DTE_VALID_SHIFT		63
+#define KVM_ITS_DTE_VALID_MASK		BIT_ULL(63)
+#define KVM_ITS_DTE_NEXT_SHIFT		49
+#define KVM_ITS_DTE_NEXT_MASK		GENMASK_ULL(62, 49)
+#define KVM_ITS_DTE_ITTADDR_SHIFT	5
+#define KVM_ITS_DTE_ITTADDR_MASK	GENMASK_ULL(48, 5)
+#define KVM_ITS_DTE_SIZE_MASK		GENMASK_ULL(4, 0)
 
 static inline bool irq_is_pending(struct vgic_irq *irq)
 {
-- 
2.5.5

  parent reply	other threads:[~2017-04-14 10:15 UTC|newest]

Thread overview: 132+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2017-04-14 10:15 [PATCH v5 00/22] vITS save/restore Eric Auger
2017-04-14 10:15 ` [PATCH v5 01/22] KVM: arm/arm64: Add ITS save/restore API documentation Eric Auger
2017-04-25 10:38   ` Peter Maydell
2017-04-26 12:31   ` Christoffer Dall
2017-04-26 15:48     ` Auger Eric
2017-04-27  8:57       ` Christoffer Dall
2017-04-27  9:33         ` Auger Eric
2017-04-27 11:02           ` Christoffer Dall
2017-04-27 12:51             ` Auger Eric
2017-04-27 14:45               ` Christoffer Dall
2017-04-27 15:29                 ` Auger Eric
2017-04-27 16:23                   ` Marc Zyngier
2017-04-27 17:14                     ` Auger Eric
2017-04-27 17:27                       ` Christoffer Dall
2017-04-27 16:38                   ` Christoffer Dall
2017-04-27 17:27                     ` Auger Eric
2017-04-27 17:54                       ` Christoffer Dall
2017-04-27 19:27                         ` Auger Eric
2017-05-04  7:00                 ` Auger Eric
2017-05-04  7:40                   ` Marc Zyngier
2017-05-04  7:54                     ` Auger Eric
2017-05-04  7:46                   ` Christoffer Dall
2017-04-14 10:15 ` [PATCH v5 02/22] KVM: arm/arm64: Add GICV3 pending table save " Eric Auger
2017-04-25 10:43   ` Peter Maydell
2017-04-26  8:26     ` Auger Eric
2017-04-26  8:44       ` Peter Maydell
2017-04-26  8:48         ` Dr. David Alan Gilbert
2017-04-26  9:57           ` Auger Eric
2017-04-26 13:00             ` Christoffer Dall
2017-04-26 13:01               ` Peter Maydell
2017-04-26 13:14                 ` Christoffer Dall
2017-04-26 13:26                   ` Peter Maydell
2017-04-26 14:47                     ` Auger Eric
2017-04-14 10:15 ` [PATCH v5 03/22] KVM: arm/arm64: vgic-its: rename itte into ite Eric Auger
2017-04-26 11:21   ` Prakash B
2017-04-27  9:05   ` Christoffer Dall
2017-04-27  9:20     ` Andre Przywara
2017-04-27  9:40       ` Auger Eric
2017-04-27 11:09         ` Christoffer Dall
2017-04-14 10:15 ` [PATCH v5 04/22] arm/arm64: vgic: turn vgic_find_mmio_region into public Eric Auger
2017-04-26 11:22   ` Prakash B
2017-04-27  9:07   ` Christoffer Dall
2017-04-14 10:15 ` [PATCH v5 05/22] KVM: arm64: vgic-its: KVM_DEV_ARM_VGIC_GRP_ITS_REGS group Eric Auger
2017-04-26 11:23   ` Prakash B
2017-04-27  9:12   ` Christoffer Dall
2017-04-14 10:15 ` [PATCH v5 06/22] KVM: arm/arm64: vgic: expose (un)lock_all_vcpus Eric Auger
2017-04-26 11:23   ` Prakash B
2017-04-27  9:18   ` Christoffer Dall
2017-04-14 10:15 ` [PATCH v5 07/22] KVM: arm64: vgic-its: Implement vgic_its_has_attr_regs and attr_regs_access Eric Auger
2017-04-26 11:24   ` Prakash B
2017-04-27 11:00   ` Christoffer Dall
2017-04-27 12:22     ` Auger Eric
2017-04-14 10:15 ` [PATCH v5 08/22] KVM: arm64: vgic-its: Implement vgic_mmio_uaccess_write_its_creadr Eric Auger
2017-04-26 11:24   ` Prakash B
2017-04-27 11:27   ` Christoffer Dall
2017-04-27 12:53     ` Auger Eric
2017-04-14 10:15 ` [PATCH v5 09/22] KVM: arm64: vgic-its: Introduce migration ABI infrastructure Eric Auger
2017-04-26 11:27   ` Prakash B
2017-04-27 13:14   ` Christoffer Dall
2017-04-14 10:15 ` [PATCH v5 10/22] KVM: arm64: vgic-its: Implement vgic_mmio_uaccess_write_its_iidr Eric Auger
2017-04-26 11:27   ` Prakash B
2017-04-27 14:57   ` Christoffer Dall
2017-04-14 10:15 ` [PATCH v5 11/22] KVM: arm64: vgic-its: Interpret MAPD Size field and check related errors Eric Auger
2017-04-26 11:28   ` Prakash B
2017-04-27 16:25   ` Christoffer Dall
2017-04-27 17:15     ` Auger Eric
2017-04-27 17:28       ` Christoffer Dall
2017-04-14 10:15 ` [PATCH v5 12/22] KVM: arm64: vgic-its: Interpret MAPD ITT_addr field Eric Auger
2017-04-26 11:29   ` Prakash B
2017-04-27 16:43   ` Christoffer Dall
2017-04-27 17:44     ` Auger Eric
2017-04-27 18:09       ` Christoffer Dall
2017-04-27 19:18         ` Auger Eric
2017-04-14 10:15 ` [PATCH v5 13/22] KVM: arm64: vgic-its: Check the device id matches TYPER DEVBITS range Eric Auger
2017-04-26 11:29   ` Prakash B
2017-04-27 16:48   ` Christoffer Dall
2017-04-27 17:24     ` Auger Eric
2017-04-14 10:15 ` [PATCH v5 14/22] KVM: arm64: vgic-its: KVM_DEV_ARM_ITS_SAVE/RESTORE_TABLES Eric Auger
2017-04-26 11:31   ` Prakash B
2017-04-27 17:24   ` Christoffer Dall
2017-04-14 10:15 ` [PATCH v5 15/22] KVM: arm64: vgic-its: vgic_its_alloc_ite/device Eric Auger
2017-04-26 11:31   ` Prakash B
2017-04-27 17:31   ` Christoffer Dall
2017-04-14 10:15 ` [PATCH v5 16/22] KVM: arm64: vgic-its: Add infrastructure for table lookup Eric Auger
2017-04-26 11:32   ` Prakash B
2017-04-27 18:06   ` Christoffer Dall
2017-04-27 19:24     ` Auger Eric
2017-04-28  9:47       ` Christoffer Dall
2017-04-30 19:33   ` Christoffer Dall
2017-05-03 13:40     ` Auger Eric
2017-05-03 14:38       ` Christoffer Dall
2017-04-30 19:35   ` Christoffer Dall
2017-05-03  6:53     ` Auger Eric
2017-05-03  8:01       ` Christoffer Dall
2017-05-03 10:22         ` Auger Eric
2017-04-30 20:13   ` Christoffer Dall
2017-04-14 10:15 ` [PATCH v5 17/22] KVM: arm64: vgic-its: Collection table save/restore Eric Auger
2017-04-26 11:33   ` Prakash B
2017-04-28 10:44   ` Christoffer Dall
2017-04-28 11:05     ` Auger Eric
2017-04-28 17:42       ` Christoffer Dall
2017-04-14 10:15 ` [PATCH v5 18/22] KVM: arm64: vgic-its: vgic_its_check_id returns the entry's GPA Eric Auger
2017-04-26 11:33   ` Prakash B
2017-05-02  8:29   ` Christoffer Dall
2017-04-14 10:15 ` [PATCH v5 19/22] KVM: arm64: vgic-its: ITT save and restore Eric Auger
2017-04-26 11:34   ` Prakash B
2017-04-30 20:14   ` Christoffer Dall
2017-05-03 16:08     ` Auger Eric
2017-05-03 16:37       ` Christoffer Dall
2017-05-03 21:55         ` Auger Eric
2017-05-04  7:31           ` Christoffer Dall
2017-05-04  7:40             ` Auger Eric
2017-05-04  8:23               ` Christoffer Dall
2017-05-04  8:44                 ` Auger Eric
2017-04-14 10:15 ` Eric Auger [this message]
2017-04-26 11:34   ` [PATCH v5 20/22] KVM: arm64: vgic-its: Device table save/restore Prakash B
2017-04-30 20:55   ` Christoffer Dall
2017-05-03 14:07     ` Auger Eric
2017-05-03 15:29       ` Christoffer Dall
2017-05-03 21:38         ` Auger Eric
2017-04-14 10:15 ` [PATCH v5 21/22] KVM: arm64: vgic-its: Fix pending table sync Eric Auger
2017-04-26 11:35   ` Prakash B
2017-04-30 21:10   ` Christoffer Dall
2017-05-03 22:20     ` Auger Eric
2017-05-04  7:32       ` Christoffer Dall
2017-04-14 10:15 ` [PATCH v5 22/22] KVM: arm64: vgic-v3: KVM_DEV_ARM_VGIC_SAVE_PENDING_TABLES Eric Auger
2017-04-26 11:35   ` Prakash B
2017-04-30 21:32   ` Christoffer Dall
2017-05-03 22:22     ` Auger Eric
2017-04-26 11:38 ` [PATCH v5 00/22] vITS save/restore Prakash B
2017-04-26 13:02   ` Christoffer Dall
2017-04-27  6:55   ` Auger Eric

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1492164934-988-21-git-send-email-eric.auger@redhat.com \
    --to=eric.auger@redhat.com \
    --cc=linux-arm-kernel@lists.infradead.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).