All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v4 00/22] vITS save/restore
@ 2017-03-27  9:30 ` Eric Auger
  0 siblings, 0 replies; 144+ messages in thread
From: Eric Auger @ 2017-03-27  9:30 UTC (permalink / raw)
  To: eric.auger.pro, eric.auger, marc.zyngier, christoffer.dall,
	andre.przywara, vijayak, Vijaya.Kumar, peter.maydell,
	linux-arm-kernel, kvmarm, kvm
  Cc: Prasun.Kapoor, quintela, dgilbert, pbonzini

This series specifies and implements an API aimed at saving and restoring
the state of the in-kernel emulated ITS device.

The ITS is programmed through registers and tables. Those latter
are allocated by the guest. Their base address is programmed in
registers or table entries before the ITS is enabled.

The ITS is free to use some of them to flush its internal caches. This
is likely to be used when entering low power state.

Therefore, for save/restore use case, it looks natural to use this
guest RAM allocated space to save the table related data. However,
currently, The ITS in-kernel emulated device does not use all of those
tables and for those it uses, it does not always sync them with its
cached data. Additional sync must happen for:
- the collection table
- the device table
- the per-device translation tables
- the LPI pending tables.

The LPI configation table and the command queues do not need extra
syncs.

An alternative to flushing the tables into guest RAM could have been
to flush them into a separate user-space buffer. However the drawback
of this alternative is that the virtualizer would allocate dedicated
buffers to store the data that should normally be laid out in guest
RAM. It would also be obliged to re-compute their size from
register/table content.

So saving the tables in guest RAM better fit the ITS programming
model and optimizes the memory usage. The drawback of this solution
is it brings additional challenges at user-space level to make sure
the guest RAM is frozen after table sync.

Best Regards

Eric

Git: complete series available at
https://github.com/eauger/linux/tree/v4.11-rc3-its-mig-v4

* Testing:
- on Cavium ThunderX using a virtio-net-pci guest,
  virsh save/restore commands and virt-manager live migration.
  Tested with 1 and 2 stage device table.

History:
v3 -> v4:
- update the DTE format (ITT_addr 52 bit support, validity bit addition)
- Document ABI revision and implement check
- iidr save/restore (including a new patch for iidr user write access)
- changed locking: kvm lock + vcpu lock
- fix nb_eventid_bits mixup
- 2 new patches aiming at exposing next_segment() and lock_all_vcpus()
- rework errror handling of lookup_table functions

- I took into account all Andre's comments/suggestions except:
  - trigger the save/restore of pending tables from GICV3 KVM device
    instead of ITS KVM device
  - implement ITS flush/restore in KVM_DEV_ARM_VGIC_GRP_CTRL
    ITS group

See the ML replies for current justifications. In case other people
strongly disagree of course I will change the code.

v2 -> v3:
- fix restore ITS ITT_addr bit masking

v1 -> v2:
- rebased on Vijaya's v11
- all entries now are 8 byte large
- devid/eventid indexing for device table and ITT
- support 2 stage device table
- common infra to read indexed tables
- add cpu <-> le64 conversions
- itte renamed into ite
- do not care anymore about pending table 1st KB
  (not needed at the moment for coarse mapping)

RFC v1
- creation

Eric Auger (22):
  KVM: arm/arm64: Add vITS save/restore API documentation
  KVM: arm/arm64: rename itte into ite
  arm/arm64: vgic: turn vgic_find_mmio_region into public
  KVM: arm64: ITS: KVM_DEV_ARM_VGIC_GRP_ITS_REGS group
  KVM: arm/arm64: vgic: expose (un)lock_all_vcpus
  KVM: arm64: ITS: Implement vgic_its_has_attr_regs and attr_regs_access
  KVM: arm64: ITS: Implement vgic_mmio_uaccess_write_its_creadr
  KVM: arm64: ITS: Implement vgic_mmio_uaccess_write_its_iidr
  KVM: arm64: ITS: Report the ITE size in GITS_TYPER
  KVM: arm64: ITS: Interpret MAPD Size field and check related errors
  KVM: arm64: ITS: Interpret MAPD ITT_addr field
  KVM: arm64: ITS: Check the device id matches TYPER DEVBITS range
  KVM: arm64: ITS: KVM_DEV_ARM_VGIC_GRP_ITS_TABLES group
  KVM: arm64: ITS: vgic_its_alloc_ite/device
  KVM: arm64: ITS: Sort the device and ITE lists
  KVM: expose next_segment()
  KVM: arm64: ITS: Add infrastructure for table lookup
  KVM: arm64: ITS: Collection table save/restore
  KVM: arm64: ITS: vgic_its_check_id returns the entry's GPA
  KVM: arm64: ITS: ITT flush and restore
  KVM: arm64: ITS: Device table save/restore
  KVM: arm64: ITS: Pending table save/restore

 Documentation/virtual/kvm/devices/arm-vgic-its.txt |  118 +++
 arch/arm/include/uapi/asm/kvm.h                    |    2 +
 arch/arm64/include/uapi/asm/kvm.h                  |    2 +
 include/kvm/arm_vgic.h                             |    2 +
 include/linux/irqchip/arm-gic-v3.h                 |    3 +
 include/linux/kvm_host.h                           |    8 +
 virt/kvm/arm/vgic/vgic-its.c                       | 1106 ++++++++++++++++++--
 virt/kvm/arm/vgic/vgic-kvm-device.c                |    4 +-
 virt/kvm/arm/vgic/vgic-mmio.c                      |   11 +-
 virt/kvm/arm/vgic/vgic-mmio.h                      |   14 +-
 virt/kvm/arm/vgic/vgic.h                           |    3 +
 virt/kvm/kvm_main.c                                |    8 -
 12 files changed, 1161 insertions(+), 120 deletions(-)

-- 
2.5.5

^ permalink raw reply	[flat|nested] 144+ messages in thread

* [PATCH v4 00/22] vITS save/restore
@ 2017-03-27  9:30 ` Eric Auger
  0 siblings, 0 replies; 144+ messages in thread
From: Eric Auger @ 2017-03-27  9:30 UTC (permalink / raw)
  To: linux-arm-kernel

This series specifies and implements an API aimed at saving and restoring
the state of the in-kernel emulated ITS device.

The ITS is programmed through registers and tables. Those latter
are allocated by the guest. Their base address is programmed in
registers or table entries before the ITS is enabled.

The ITS is free to use some of them to flush its internal caches. This
is likely to be used when entering low power state.

Therefore, for save/restore use case, it looks natural to use this
guest RAM allocated space to save the table related data. However,
currently, The ITS in-kernel emulated device does not use all of those
tables and for those it uses, it does not always sync them with its
cached data. Additional sync must happen for:
- the collection table
- the device table
- the per-device translation tables
- the LPI pending tables.

The LPI configation table and the command queues do not need extra
syncs.

An alternative to flushing the tables into guest RAM could have been
to flush them into a separate user-space buffer. However the drawback
of this alternative is that the virtualizer would allocate dedicated
buffers to store the data that should normally be laid out in guest
RAM. It would also be obliged to re-compute their size from
register/table content.

So saving the tables in guest RAM better fit the ITS programming
model and optimizes the memory usage. The drawback of this solution
is it brings additional challenges at user-space level to make sure
the guest RAM is frozen after table sync.

Best Regards

Eric

Git: complete series available at
https://github.com/eauger/linux/tree/v4.11-rc3-its-mig-v4

* Testing:
- on Cavium ThunderX using a virtio-net-pci guest,
  virsh save/restore commands and virt-manager live migration.
  Tested with 1 and 2 stage device table.

History:
v3 -> v4:
- update the DTE format (ITT_addr 52 bit support, validity bit addition)
- Document ABI revision and implement check
- iidr save/restore (including a new patch for iidr user write access)
- changed locking: kvm lock + vcpu lock
- fix nb_eventid_bits mixup
- 2 new patches aiming at exposing next_segment() and lock_all_vcpus()
- rework errror handling of lookup_table functions

- I took into account all Andre's comments/suggestions except:
  - trigger the save/restore of pending tables from GICV3 KVM device
    instead of ITS KVM device
  - implement ITS flush/restore in KVM_DEV_ARM_VGIC_GRP_CTRL
    ITS group

See the ML replies for current justifications. In case other people
strongly disagree of course I will change the code.

v2 -> v3:
- fix restore ITS ITT_addr bit masking

v1 -> v2:
- rebased on Vijaya's v11
- all entries now are 8 byte large
- devid/eventid indexing for device table and ITT
- support 2 stage device table
- common infra to read indexed tables
- add cpu <-> le64 conversions
- itte renamed into ite
- do not care anymore about pending table 1st KB
  (not needed at the moment for coarse mapping)

RFC v1
- creation

Eric Auger (22):
  KVM: arm/arm64: Add vITS save/restore API documentation
  KVM: arm/arm64: rename itte into ite
  arm/arm64: vgic: turn vgic_find_mmio_region into public
  KVM: arm64: ITS: KVM_DEV_ARM_VGIC_GRP_ITS_REGS group
  KVM: arm/arm64: vgic: expose (un)lock_all_vcpus
  KVM: arm64: ITS: Implement vgic_its_has_attr_regs and attr_regs_access
  KVM: arm64: ITS: Implement vgic_mmio_uaccess_write_its_creadr
  KVM: arm64: ITS: Implement vgic_mmio_uaccess_write_its_iidr
  KVM: arm64: ITS: Report the ITE size in GITS_TYPER
  KVM: arm64: ITS: Interpret MAPD Size field and check related errors
  KVM: arm64: ITS: Interpret MAPD ITT_addr field
  KVM: arm64: ITS: Check the device id matches TYPER DEVBITS range
  KVM: arm64: ITS: KVM_DEV_ARM_VGIC_GRP_ITS_TABLES group
  KVM: arm64: ITS: vgic_its_alloc_ite/device
  KVM: arm64: ITS: Sort the device and ITE lists
  KVM: expose next_segment()
  KVM: arm64: ITS: Add infrastructure for table lookup
  KVM: arm64: ITS: Collection table save/restore
  KVM: arm64: ITS: vgic_its_check_id returns the entry's GPA
  KVM: arm64: ITS: ITT flush and restore
  KVM: arm64: ITS: Device table save/restore
  KVM: arm64: ITS: Pending table save/restore

 Documentation/virtual/kvm/devices/arm-vgic-its.txt |  118 +++
 arch/arm/include/uapi/asm/kvm.h                    |    2 +
 arch/arm64/include/uapi/asm/kvm.h                  |    2 +
 include/kvm/arm_vgic.h                             |    2 +
 include/linux/irqchip/arm-gic-v3.h                 |    3 +
 include/linux/kvm_host.h                           |    8 +
 virt/kvm/arm/vgic/vgic-its.c                       | 1106 ++++++++++++++++++--
 virt/kvm/arm/vgic/vgic-kvm-device.c                |    4 +-
 virt/kvm/arm/vgic/vgic-mmio.c                      |   11 +-
 virt/kvm/arm/vgic/vgic-mmio.h                      |   14 +-
 virt/kvm/arm/vgic/vgic.h                           |    3 +
 virt/kvm/kvm_main.c                                |    8 -
 12 files changed, 1161 insertions(+), 120 deletions(-)

-- 
2.5.5

^ permalink raw reply	[flat|nested] 144+ messages in thread

* [PATCH v4 01/22] KVM: arm/arm64: Add vITS save/restore API documentation
  2017-03-27  9:30 ` Eric Auger
@ 2017-03-27  9:30   ` Eric Auger
  -1 siblings, 0 replies; 144+ messages in thread
From: Eric Auger @ 2017-03-27  9:30 UTC (permalink / raw)
  To: eric.auger.pro, eric.auger, marc.zyngier, christoffer.dall,
	andre.przywara, vijayak, Vijaya.Kumar, peter.maydell,
	linux-arm-kernel, kvmarm, kvm
  Cc: Prasun.Kapoor, quintela, dgilbert, pbonzini

Add description for how to access vITS registers and how to flush/restore
vITS tables into/from memory

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

---
v3 -> v4:
- take into account Peter's comments:
  - typos
  - KVM_DEV_ARM_VGIC_GRP_ITS_TABLES kvm_device_attr = 0
  - add a validity bit in DTE
  - document all fields in CTE and ITE
  - document ABI revision
- take into account Andre's comments:
  - document restrictions about GITS_CREADR writing and GITS_IIDR
  - document -EBUSY error if one or more VCPUS are runnning
  - document 64b registers only can be accessed with 64b access
- itt_addr field matches bits [51:8] of the itt_addr

v1 -> v2:
- DTE and ITE now are 8 bytes
- DTE and ITE now indexed by deviceid/eventid
- use ITE name instead of ITTE
- mentions ITT_addr matches bits [51:8] of the actual address
- mentions LE layout
---
 Documentation/virtual/kvm/devices/arm-vgic-its.txt | 118 +++++++++++++++++++++
 1 file changed, 118 insertions(+)

diff --git a/Documentation/virtual/kvm/devices/arm-vgic-its.txt b/Documentation/virtual/kvm/devices/arm-vgic-its.txt
index 6081a5b..0902d20 100644
--- a/Documentation/virtual/kvm/devices/arm-vgic-its.txt
+++ b/Documentation/virtual/kvm/devices/arm-vgic-its.txt
@@ -36,3 +36,121 @@ Groups:
     -ENXIO:  ITS not properly configured as required prior to setting
              this attribute
     -ENOMEM: Memory shortage when allocating ITS internal data
+
+  KVM_DEV_ARM_VGIC_GRP_ITS_REGS
+  Attributes:
+      The attr field of kvm_device_attr encodes the offset of the
+      ITS register, relative to the ITS control frame base address
+      (ITS_base).
+
+      kvm_device_attr.addr points to a __u64 value whatever the width
+      of the addressed register (32/64 bits). 64 bit registers can only
+      be accessed with full length.
+
+      Writes to read-only registers are ignored by the kernel except for:
+      - GITS_READR. It needs to be restored otherwise commands in the queue
+        will be re-executed after CWRITER setting. Writing this register is
+        allowed if the ITS is not enabled (GITS_CTLR.enable = 0). Also it
+        needs to be restored after GITS_CBASER since a write to GITS_CBASER
+        resets GITS_CREADR.
+      - GITS_IIDR. Its Revision field encodes the table layout ABI revision.
+
+      For other registers, getting or setting a register has the same
+      effect as reading/writing the register on real hardware.
+  Errors:
+    -ENXIO: Offset does not correspond to any supported register
+    -EFAULT: Invalid user pointer for attr->addr
+    -EINVAL: Offset is not 64-bit aligned
+    -EBUSY: one or more VCPUS are running
+
+  KVM_DEV_ARM_VGIC_GRP_ITS_TABLES
+  Attributes
+       The attr field of kvm_device_attr must be zero.
+
+       request the flush-save/restore of the ITS tables, namely
+       the device table, the collection table, all the ITT tables,
+       the LPI pending tables. On save, the tables are flushed
+       into guest memory at the location provisioned by the guest
+       in GITS_BASER (device and collection tables), in the MAPD
+       command (ITT_addr), GICR_PENDBASERs (pending tables).
+
+       This means the GIC should be restored before the ITS and all
+       ITS registers but the GITS_CTLR must be restored before
+       restoring the ITS tables.
+
+       The GITS_READR and GITS_IIDR read-only registers must also
+       be restored before the table restore. The IIDR revision field
+       encodes the ABI revision of the table layout. If not set by
+       user space, the restoration of the tables will fail.
+
+       Note the LPI configuration table is read-only for the
+       in-kernel ITS and its save/restore goes through the standard
+       RAM save/restore.
+
+       The layout of the tables in guest memory defines an ABI.
+       The entries are laid in little endian format as follows;
+
+  Errors:
+    -EINVAL: kvm_device_attr not equal to 0, invalid table data
+    -EFAULT: invalid guest ram access
+    -EBUSY: one or more VCPUS are running
+
+    ITS Table ABI REV1:
+    -------------------
+
+    The device table and ITE are respectively indexed by device id and
+    eventid. The collection table however is not indexed by collection id:
+    CTE are written at the beginning of the buffer.
+
+    Device Table Entry (DTE) layout: entry size = 8 bytes
+
+    bits:     | 63| 62 ... 49 | 48 ... 5 | 4 ... 0 |
+    values:   | V |   next    | ITT_addr |  Size   |
+
+    where;
+    - V indicates whether the entry is valid,
+    - ITT_addr matches bits [51:8] of the ITT address (256B aligned),
+    - next field is meaningful only if the entry is valid.
+    It equals to 0 if this entry is the last one; otherwise it corresponds
+    to the minimum between the offset to the next device id and 2^14 -1.
+
+    Collection Table Entry (CTE) layout: entry size = 8 bytes
+
+    bits:     | 63| 62 ..  52  | 51 ... 16 | 15  ...   0 |
+    values:   | V |    RES0    |  RDBase   |    ICID     |
+
+    where:
+    - V indicates whether the entry is valid,
+    - RDBase matches the PE number (GICR_TYPER.Processor_Number),
+    - ICID matches the collection ID
+
+    Interrupt Translation Entry (ITE) layout: entry size = 8 bytes
+
+    bits:     | 63 ... 48 | 47 ... 16 | 15 ... 0 |
+    values:   |    next   |   pINTID  |  ICID    |
+
+    where:
+    - pINTID is the physical LPI ID,
+    - ICID is the collection ID,
+    - next field is meaningful only if the entry is valid (pINTID != 0).
+    It equals to 0 if this entry is the last one; otherwise it corresponds
+    to the minimum between the eventid offset to the next ITE and 2^16 -1.
+
+    LPI Pending Table layout:
+
+    As specified in the ARM Generic Interrupt Controller Architecture
+    Specification GIC Architecture version 3.0 and version 4. The first
+    1kB is not modified and therefore should contain zeroes.
+
+    Future evolutions of the ITS table layout:
+
+    At the moment the table layout is defined and optimized for physical
+    LPI support.
+
+    In the future we might implement direct injection of virtual LPIS.
+    This will require an upgrade of the table layout and an evolution of
+    the ABI. The ABI revision is encoded in the GITS_IIDR revision field.
+    That register must be restored before the table restoration, otherwise
+    the operation will fail.
+
+    ABI V1: GITS_IIDR.Revision = 1
-- 
2.5.5

^ permalink raw reply related	[flat|nested] 144+ messages in thread

* [PATCH v4 01/22] KVM: arm/arm64: Add vITS save/restore API documentation
@ 2017-03-27  9:30   ` Eric Auger
  0 siblings, 0 replies; 144+ messages in thread
From: Eric Auger @ 2017-03-27  9:30 UTC (permalink / raw)
  To: linux-arm-kernel

Add description for how to access vITS registers and how to flush/restore
vITS tables into/from memory

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

---
v3 -> v4:
- take into account Peter's comments:
  - typos
  - KVM_DEV_ARM_VGIC_GRP_ITS_TABLES kvm_device_attr = 0
  - add a validity bit in DTE
  - document all fields in CTE and ITE
  - document ABI revision
- take into account Andre's comments:
  - document restrictions about GITS_CREADR writing and GITS_IIDR
  - document -EBUSY error if one or more VCPUS are runnning
  - document 64b registers only can be accessed with 64b access
- itt_addr field matches bits [51:8] of the itt_addr

v1 -> v2:
- DTE and ITE now are 8 bytes
- DTE and ITE now indexed by deviceid/eventid
- use ITE name instead of ITTE
- mentions ITT_addr matches bits [51:8] of the actual address
- mentions LE layout
---
 Documentation/virtual/kvm/devices/arm-vgic-its.txt | 118 +++++++++++++++++++++
 1 file changed, 118 insertions(+)

diff --git a/Documentation/virtual/kvm/devices/arm-vgic-its.txt b/Documentation/virtual/kvm/devices/arm-vgic-its.txt
index 6081a5b..0902d20 100644
--- a/Documentation/virtual/kvm/devices/arm-vgic-its.txt
+++ b/Documentation/virtual/kvm/devices/arm-vgic-its.txt
@@ -36,3 +36,121 @@ Groups:
     -ENXIO:  ITS not properly configured as required prior to setting
              this attribute
     -ENOMEM: Memory shortage when allocating ITS internal data
+
+  KVM_DEV_ARM_VGIC_GRP_ITS_REGS
+  Attributes:
+      The attr field of kvm_device_attr encodes the offset of the
+      ITS register, relative to the ITS control frame base address
+      (ITS_base).
+
+      kvm_device_attr.addr points to a __u64 value whatever the width
+      of the addressed register (32/64 bits). 64 bit registers can only
+      be accessed with full length.
+
+      Writes to read-only registers are ignored by the kernel except for:
+      - GITS_READR. It needs to be restored otherwise commands in the queue
+        will be re-executed after CWRITER setting. Writing this register is
+        allowed if the ITS is not enabled (GITS_CTLR.enable = 0). Also it
+        needs to be restored after GITS_CBASER since a write to GITS_CBASER
+        resets GITS_CREADR.
+      - GITS_IIDR. Its Revision field encodes the table layout ABI revision.
+
+      For other registers, getting or setting a register has the same
+      effect as reading/writing the register on real hardware.
+  Errors:
+    -ENXIO: Offset does not correspond to any supported register
+    -EFAULT: Invalid user pointer for attr->addr
+    -EINVAL: Offset is not 64-bit aligned
+    -EBUSY: one or more VCPUS are running
+
+  KVM_DEV_ARM_VGIC_GRP_ITS_TABLES
+  Attributes
+       The attr field of kvm_device_attr must be zero.
+
+       request the flush-save/restore of the ITS tables, namely
+       the device table, the collection table, all the ITT tables,
+       the LPI pending tables. On save, the tables are flushed
+       into guest memory at the location provisioned by the guest
+       in GITS_BASER (device and collection tables), in the MAPD
+       command (ITT_addr), GICR_PENDBASERs (pending tables).
+
+       This means the GIC should be restored before the ITS and all
+       ITS registers but the GITS_CTLR must be restored before
+       restoring the ITS tables.
+
+       The GITS_READR and GITS_IIDR read-only registers must also
+       be restored before the table restore. The IIDR revision field
+       encodes the ABI revision of the table layout. If not set by
+       user space, the restoration of the tables will fail.
+
+       Note the LPI configuration table is read-only for the
+       in-kernel ITS and its save/restore goes through the standard
+       RAM save/restore.
+
+       The layout of the tables in guest memory defines an ABI.
+       The entries are laid in little endian format as follows;
+
+  Errors:
+    -EINVAL: kvm_device_attr not equal to 0, invalid table data
+    -EFAULT: invalid guest ram access
+    -EBUSY: one or more VCPUS are running
+
+    ITS Table ABI REV1:
+    -------------------
+
+    The device table and ITE are respectively indexed by device id and
+    eventid. The collection table however is not indexed by collection id:
+    CTE are written at the beginning of the buffer.
+
+    Device Table Entry (DTE) layout: entry size = 8 bytes
+
+    bits:     | 63| 62 ... 49 | 48 ... 5 | 4 ... 0 |
+    values:   | V |   next    | ITT_addr |  Size   |
+
+    where;
+    - V indicates whether the entry is valid,
+    - ITT_addr matches bits [51:8] of the ITT address (256B aligned),
+    - next field is meaningful only if the entry is valid.
+    It equals to 0 if this entry is the last one; otherwise it corresponds
+    to the minimum between the offset to the next device id and 2^14 -1.
+
+    Collection Table Entry (CTE) layout: entry size = 8 bytes
+
+    bits:     | 63| 62 ..  52  | 51 ... 16 | 15  ...   0 |
+    values:   | V |    RES0    |  RDBase   |    ICID     |
+
+    where:
+    - V indicates whether the entry is valid,
+    - RDBase matches the PE number (GICR_TYPER.Processor_Number),
+    - ICID matches the collection ID
+
+    Interrupt Translation Entry (ITE) layout: entry size = 8 bytes
+
+    bits:     | 63 ... 48 | 47 ... 16 | 15 ... 0 |
+    values:   |    next   |   pINTID  |  ICID    |
+
+    where:
+    - pINTID is the physical LPI ID,
+    - ICID is the collection ID,
+    - next field is meaningful only if the entry is valid (pINTID != 0).
+    It equals to 0 if this entry is the last one; otherwise it corresponds
+    to the minimum between the eventid offset to the next ITE and 2^16 -1.
+
+    LPI Pending Table layout:
+
+    As specified in the ARM Generic Interrupt Controller Architecture
+    Specification GIC Architecture version 3.0 and version 4. The first
+    1kB is not modified and therefore should contain zeroes.
+
+    Future evolutions of the ITS table layout:
+
+    At the moment the table layout is defined and optimized for physical
+    LPI support.
+
+    In the future we might implement direct injection of virtual LPIS.
+    This will require an upgrade of the table layout and an evolution of
+    the ABI. The ABI revision is encoded in the GITS_IIDR revision field.
+    That register must be restored before the table restoration, otherwise
+    the operation will fail.
+
+    ABI V1: GITS_IIDR.Revision = 1
-- 
2.5.5

^ permalink raw reply related	[flat|nested] 144+ messages in thread

* [PATCH v4 02/22] KVM: arm/arm64: rename itte into ite
  2017-03-27  9:30 ` Eric Auger
@ 2017-03-27  9:30   ` Eric Auger
  -1 siblings, 0 replies; 144+ messages in thread
From: Eric Auger @ 2017-03-27  9:30 UTC (permalink / raw)
  To: eric.auger.pro, eric.auger, marc.zyngier, christoffer.dall,
	andre.przywara, vijayak, Vijaya.Kumar, peter.maydell,
	linux-arm-kernel, kvmarm, kvm
  Cc: Prasun.Kapoor, quintela, dgilbert, pbonzini

The actual abbreviation for the interrupt translation table entry
is ITE. Let's rename all itte instances by ite.

Signed-off-by: Eric Auger <eric.auger@redhat.com>
---
 virt/kvm/arm/vgic/vgic-its.c | 148 +++++++++++++++++++++----------------------
 1 file changed, 74 insertions(+), 74 deletions(-)

diff --git a/virt/kvm/arm/vgic/vgic-its.c b/virt/kvm/arm/vgic/vgic-its.c
index 8d1da1a..3ffcbbe 100644
--- a/virt/kvm/arm/vgic/vgic-its.c
+++ b/virt/kvm/arm/vgic/vgic-its.c
@@ -114,8 +114,8 @@ struct its_collection {
 #define its_is_collection_mapped(coll) ((coll) && \
 				((coll)->target_addr != COLLECTION_NOT_MAPPED))
 
-struct its_itte {
-	struct list_head itte_list;
+struct its_ite {
+	struct list_head ite_list;
 
 	struct vgic_irq *irq;
 	struct its_collection *collection;
@@ -143,27 +143,27 @@ static struct its_device *find_its_device(struct vgic_its *its, u32 device_id)
  * Device ID/Event ID pair on an ITS.
  * Must be called with the its_lock mutex held.
  */
-static struct its_itte *find_itte(struct vgic_its *its, u32 device_id,
+static struct its_ite *find_ite(struct vgic_its *its, u32 device_id,
 				  u32 event_id)
 {
 	struct its_device *device;
-	struct its_itte *itte;
+	struct its_ite *ite;
 
 	device = find_its_device(its, device_id);
 	if (device == NULL)
 		return NULL;
 
-	list_for_each_entry(itte, &device->itt_head, itte_list)
-		if (itte->event_id == event_id)
-			return itte;
+	list_for_each_entry(ite, &device->itt_head, ite_list)
+		if (ite->event_id == event_id)
+			return ite;
 
 	return NULL;
 }
 
 /* To be used as an iterator this macro misses the enclosing parentheses */
-#define for_each_lpi_its(dev, itte, its) \
+#define for_each_lpi_its(dev, ite, its) \
 	list_for_each_entry(dev, &(its)->device_list, dev_list) \
-		list_for_each_entry(itte, &(dev)->itt_head, itte_list)
+		list_for_each_entry(ite, &(dev)->itt_head, ite_list)
 
 /*
  * We only implement 48 bits of PA at the moment, although the ITS
@@ -270,18 +270,18 @@ static int vgic_copy_lpi_list(struct kvm *kvm, u32 **intid_ptr)
  * Needs to be called whenever either the collection for a LPIs has
  * changed or the collection itself got retargeted.
  */
-static void update_affinity_itte(struct kvm *kvm, struct its_itte *itte)
+static void update_affinity_ite(struct kvm *kvm, struct its_ite *ite)
 {
 	struct kvm_vcpu *vcpu;
 
-	if (!its_is_collection_mapped(itte->collection))
+	if (!its_is_collection_mapped(ite->collection))
 		return;
 
-	vcpu = kvm_get_vcpu(kvm, itte->collection->target_addr);
+	vcpu = kvm_get_vcpu(kvm, ite->collection->target_addr);
 
-	spin_lock(&itte->irq->irq_lock);
-	itte->irq->target_vcpu = vcpu;
-	spin_unlock(&itte->irq->irq_lock);
+	spin_lock(&ite->irq->irq_lock);
+	ite->irq->target_vcpu = vcpu;
+	spin_unlock(&ite->irq->irq_lock);
 }
 
 /*
@@ -292,13 +292,13 @@ static void update_affinity_collection(struct kvm *kvm, struct vgic_its *its,
 				       struct its_collection *coll)
 {
 	struct its_device *device;
-	struct its_itte *itte;
+	struct its_ite *ite;
 
-	for_each_lpi_its(device, itte, its) {
-		if (!itte->collection || coll != itte->collection)
+	for_each_lpi_its(device, ite, its) {
+		if (!ite->collection || coll != ite->collection)
 			continue;
 
-		update_affinity_itte(kvm, itte);
+		update_affinity_ite(kvm, ite);
 	}
 }
 
@@ -425,25 +425,25 @@ static int vgic_its_trigger_msi(struct kvm *kvm, struct vgic_its *its,
 				u32 devid, u32 eventid)
 {
 	struct kvm_vcpu *vcpu;
-	struct its_itte *itte;
+	struct its_ite *ite;
 
 	if (!its->enabled)
 		return -EBUSY;
 
-	itte = find_itte(its, devid, eventid);
-	if (!itte || !its_is_collection_mapped(itte->collection))
+	ite = find_ite(its, devid, eventid);
+	if (!ite || !its_is_collection_mapped(ite->collection))
 		return E_ITS_INT_UNMAPPED_INTERRUPT;
 
-	vcpu = kvm_get_vcpu(kvm, itte->collection->target_addr);
+	vcpu = kvm_get_vcpu(kvm, ite->collection->target_addr);
 	if (!vcpu)
 		return E_ITS_INT_UNMAPPED_INTERRUPT;
 
 	if (!vcpu->arch.vgic_cpu.lpis_enabled)
 		return -EBUSY;
 
-	spin_lock(&itte->irq->irq_lock);
-	itte->irq->pending_latch = true;
-	vgic_queue_irq_unlock(kvm, itte->irq);
+	spin_lock(&ite->irq->irq_lock);
+	ite->irq->pending_latch = true;
+	vgic_queue_irq_unlock(kvm, ite->irq);
 
 	return 0;
 }
@@ -511,15 +511,15 @@ int vgic_its_inject_msi(struct kvm *kvm, struct kvm_msi *msi)
 }
 
 /* Requires the its_lock to be held. */
-static void its_free_itte(struct kvm *kvm, struct its_itte *itte)
+static void its_free_ite(struct kvm *kvm, struct its_ite *ite)
 {
-	list_del(&itte->itte_list);
+	list_del(&ite->ite_list);
 
 	/* This put matches the get in vgic_add_lpi. */
-	if (itte->irq)
-		vgic_put_irq(kvm, itte->irq);
+	if (ite->irq)
+		vgic_put_irq(kvm, ite->irq);
 
-	kfree(itte);
+	kfree(ite);
 }
 
 static u64 its_cmd_mask_field(u64 *its_cmd, int word, int shift, int size)
@@ -544,17 +544,17 @@ static int vgic_its_cmd_handle_discard(struct kvm *kvm, struct vgic_its *its,
 {
 	u32 device_id = its_cmd_get_deviceid(its_cmd);
 	u32 event_id = its_cmd_get_id(its_cmd);
-	struct its_itte *itte;
+	struct its_ite *ite;
 
 
-	itte = find_itte(its, device_id, event_id);
-	if (itte && itte->collection) {
+	ite = find_ite(its, device_id, event_id);
+	if (ite && ite->collection) {
 		/*
 		 * Though the spec talks about removing the pending state, we
 		 * don't bother here since we clear the ITTE anyway and the
 		 * pending state is a property of the ITTE struct.
 		 */
-		its_free_itte(kvm, itte);
+		its_free_ite(kvm, ite);
 		return 0;
 	}
 
@@ -572,26 +572,26 @@ static int vgic_its_cmd_handle_movi(struct kvm *kvm, struct vgic_its *its,
 	u32 event_id = its_cmd_get_id(its_cmd);
 	u32 coll_id = its_cmd_get_collection(its_cmd);
 	struct kvm_vcpu *vcpu;
-	struct its_itte *itte;
+	struct its_ite *ite;
 	struct its_collection *collection;
 
-	itte = find_itte(its, device_id, event_id);
-	if (!itte)
+	ite = find_ite(its, device_id, event_id);
+	if (!ite)
 		return E_ITS_MOVI_UNMAPPED_INTERRUPT;
 
-	if (!its_is_collection_mapped(itte->collection))
+	if (!its_is_collection_mapped(ite->collection))
 		return E_ITS_MOVI_UNMAPPED_COLLECTION;
 
 	collection = find_collection(its, coll_id);
 	if (!its_is_collection_mapped(collection))
 		return E_ITS_MOVI_UNMAPPED_COLLECTION;
 
-	itte->collection = collection;
+	ite->collection = collection;
 	vcpu = kvm_get_vcpu(kvm, collection->target_addr);
 
-	spin_lock(&itte->irq->irq_lock);
-	itte->irq->target_vcpu = vcpu;
-	spin_unlock(&itte->irq->irq_lock);
+	spin_lock(&ite->irq->irq_lock);
+	ite->irq->target_vcpu = vcpu;
+	spin_unlock(&ite->irq->irq_lock);
 
 	return 0;
 }
@@ -679,7 +679,7 @@ static void vgic_its_free_collection(struct vgic_its *its, u32 coll_id)
 {
 	struct its_collection *collection;
 	struct its_device *device;
-	struct its_itte *itte;
+	struct its_ite *ite;
 
 	/*
 	 * Clearing the mapping for that collection ID removes the
@@ -690,10 +690,10 @@ static void vgic_its_free_collection(struct vgic_its *its, u32 coll_id)
 	if (!collection)
 		return;
 
-	for_each_lpi_its(device, itte, its)
-		if (itte->collection &&
-		    itte->collection->collection_id == coll_id)
-			itte->collection = NULL;
+	for_each_lpi_its(device, ite, its)
+		if (ite->collection &&
+		    ite->collection->collection_id == coll_id)
+			ite->collection = NULL;
 
 	list_del(&collection->coll_list);
 	kfree(collection);
@@ -709,7 +709,7 @@ static int vgic_its_cmd_handle_mapi(struct kvm *kvm, struct vgic_its *its,
 	u32 device_id = its_cmd_get_deviceid(its_cmd);
 	u32 event_id = its_cmd_get_id(its_cmd);
 	u32 coll_id = its_cmd_get_collection(its_cmd);
-	struct its_itte *itte;
+	struct its_ite *ite;
 	struct its_device *device;
 	struct its_collection *collection, *new_coll = NULL;
 	int lpi_nr;
@@ -728,7 +728,7 @@ static int vgic_its_cmd_handle_mapi(struct kvm *kvm, struct vgic_its *its,
 		return E_ITS_MAPTI_PHYSICALID_OOR;
 
 	/* If there is an existing mapping, behavior is UNPREDICTABLE. */
-	if (find_itte(its, device_id, event_id))
+	if (find_ite(its, device_id, event_id))
 		return 0;
 
 	collection = find_collection(its, coll_id);
@@ -739,36 +739,36 @@ static int vgic_its_cmd_handle_mapi(struct kvm *kvm, struct vgic_its *its,
 		new_coll = collection;
 	}
 
-	itte = kzalloc(sizeof(struct its_itte), GFP_KERNEL);
-	if (!itte) {
+	ite = kzalloc(sizeof(struct its_ite), GFP_KERNEL);
+	if (!ite) {
 		if (new_coll)
 			vgic_its_free_collection(its, coll_id);
 		return -ENOMEM;
 	}
 
-	itte->event_id	= event_id;
-	list_add_tail(&itte->itte_list, &device->itt_head);
+	ite->event_id	= event_id;
+	list_add_tail(&ite->ite_list, &device->itt_head);
 
-	itte->collection = collection;
-	itte->lpi = lpi_nr;
+	ite->collection = collection;
+	ite->lpi = lpi_nr;
 
 	irq = vgic_add_lpi(kvm, lpi_nr);
 	if (IS_ERR(irq)) {
 		if (new_coll)
 			vgic_its_free_collection(its, coll_id);
-		its_free_itte(kvm, itte);
+		its_free_ite(kvm, ite);
 		return PTR_ERR(irq);
 	}
-	itte->irq = irq;
+	ite->irq = irq;
 
-	update_affinity_itte(kvm, itte);
+	update_affinity_ite(kvm, ite);
 
 	/*
 	 * We "cache" the configuration table entries in out struct vgic_irq's.
 	 * However we only have those structs for mapped IRQs, so we read in
 	 * the respective config data from memory here upon mapping the LPI.
 	 */
-	update_lpi_config(kvm, itte->irq, NULL);
+	update_lpi_config(kvm, ite->irq, NULL);
 
 	return 0;
 }
@@ -776,15 +776,15 @@ static int vgic_its_cmd_handle_mapi(struct kvm *kvm, struct vgic_its *its,
 /* Requires the its_lock to be held. */
 static void vgic_its_unmap_device(struct kvm *kvm, struct its_device *device)
 {
-	struct its_itte *itte, *temp;
+	struct its_ite *ite, *temp;
 
 	/*
 	 * The spec says that unmapping a device with still valid
 	 * ITTEs associated is UNPREDICTABLE. We remove all ITTEs,
 	 * since we cannot leave the memory unreferenced.
 	 */
-	list_for_each_entry_safe(itte, temp, &device->itt_head, itte_list)
-		its_free_itte(kvm, itte);
+	list_for_each_entry_safe(ite, temp, &device->itt_head, ite_list)
+		its_free_ite(kvm, ite);
 
 	list_del(&device->dev_list);
 	kfree(device);
@@ -883,14 +883,14 @@ static int vgic_its_cmd_handle_clear(struct kvm *kvm, struct vgic_its *its,
 {
 	u32 device_id = its_cmd_get_deviceid(its_cmd);
 	u32 event_id = its_cmd_get_id(its_cmd);
-	struct its_itte *itte;
+	struct its_ite *ite;
 
 
-	itte = find_itte(its, device_id, event_id);
-	if (!itte)
+	ite = find_ite(its, device_id, event_id);
+	if (!ite)
 		return E_ITS_CLEAR_UNMAPPED_INTERRUPT;
 
-	itte->irq->pending_latch = false;
+	ite->irq->pending_latch = false;
 
 	return 0;
 }
@@ -904,14 +904,14 @@ static int vgic_its_cmd_handle_inv(struct kvm *kvm, struct vgic_its *its,
 {
 	u32 device_id = its_cmd_get_deviceid(its_cmd);
 	u32 event_id = its_cmd_get_id(its_cmd);
-	struct its_itte *itte;
+	struct its_ite *ite;
 
 
-	itte = find_itte(its, device_id, event_id);
-	if (!itte)
+	ite = find_ite(its, device_id, event_id);
+	if (!ite)
 		return E_ITS_INV_UNMAPPED_INTERRUPT;
 
-	return update_lpi_config(kvm, itte->irq, NULL);
+	return update_lpi_config(kvm, ite->irq, NULL);
 }
 
 /*
@@ -1435,7 +1435,7 @@ static void vgic_its_destroy(struct kvm_device *kvm_dev)
 	struct kvm *kvm = kvm_dev->kvm;
 	struct vgic_its *its = kvm_dev->private;
 	struct its_device *dev;
-	struct its_itte *itte;
+	struct its_ite *ite;
 	struct list_head *dev_cur, *dev_temp;
 	struct list_head *cur, *temp;
 
@@ -1450,8 +1450,8 @@ static void vgic_its_destroy(struct kvm_device *kvm_dev)
 	list_for_each_safe(dev_cur, dev_temp, &its->device_list) {
 		dev = container_of(dev_cur, struct its_device, dev_list);
 		list_for_each_safe(cur, temp, &dev->itt_head) {
-			itte = (container_of(cur, struct its_itte, itte_list));
-			its_free_itte(kvm, itte);
+			ite = (container_of(cur, struct its_ite, ite_list));
+			its_free_ite(kvm, ite);
 		}
 		list_del(dev_cur);
 		kfree(dev);
-- 
2.5.5

^ permalink raw reply related	[flat|nested] 144+ messages in thread

* [PATCH v4 02/22] KVM: arm/arm64: rename itte into ite
@ 2017-03-27  9:30   ` Eric Auger
  0 siblings, 0 replies; 144+ messages in thread
From: Eric Auger @ 2017-03-27  9:30 UTC (permalink / raw)
  To: linux-arm-kernel

The actual abbreviation for the interrupt translation table entry
is ITE. Let's rename all itte instances by ite.

Signed-off-by: Eric Auger <eric.auger@redhat.com>
---
 virt/kvm/arm/vgic/vgic-its.c | 148 +++++++++++++++++++++----------------------
 1 file changed, 74 insertions(+), 74 deletions(-)

diff --git a/virt/kvm/arm/vgic/vgic-its.c b/virt/kvm/arm/vgic/vgic-its.c
index 8d1da1a..3ffcbbe 100644
--- a/virt/kvm/arm/vgic/vgic-its.c
+++ b/virt/kvm/arm/vgic/vgic-its.c
@@ -114,8 +114,8 @@ struct its_collection {
 #define its_is_collection_mapped(coll) ((coll) && \
 				((coll)->target_addr != COLLECTION_NOT_MAPPED))
 
-struct its_itte {
-	struct list_head itte_list;
+struct its_ite {
+	struct list_head ite_list;
 
 	struct vgic_irq *irq;
 	struct its_collection *collection;
@@ -143,27 +143,27 @@ static struct its_device *find_its_device(struct vgic_its *its, u32 device_id)
  * Device ID/Event ID pair on an ITS.
  * Must be called with the its_lock mutex held.
  */
-static struct its_itte *find_itte(struct vgic_its *its, u32 device_id,
+static struct its_ite *find_ite(struct vgic_its *its, u32 device_id,
 				  u32 event_id)
 {
 	struct its_device *device;
-	struct its_itte *itte;
+	struct its_ite *ite;
 
 	device = find_its_device(its, device_id);
 	if (device == NULL)
 		return NULL;
 
-	list_for_each_entry(itte, &device->itt_head, itte_list)
-		if (itte->event_id == event_id)
-			return itte;
+	list_for_each_entry(ite, &device->itt_head, ite_list)
+		if (ite->event_id == event_id)
+			return ite;
 
 	return NULL;
 }
 
 /* To be used as an iterator this macro misses the enclosing parentheses */
-#define for_each_lpi_its(dev, itte, its) \
+#define for_each_lpi_its(dev, ite, its) \
 	list_for_each_entry(dev, &(its)->device_list, dev_list) \
-		list_for_each_entry(itte, &(dev)->itt_head, itte_list)
+		list_for_each_entry(ite, &(dev)->itt_head, ite_list)
 
 /*
  * We only implement 48 bits of PA at the moment, although the ITS
@@ -270,18 +270,18 @@ static int vgic_copy_lpi_list(struct kvm *kvm, u32 **intid_ptr)
  * Needs to be called whenever either the collection for a LPIs has
  * changed or the collection itself got retargeted.
  */
-static void update_affinity_itte(struct kvm *kvm, struct its_itte *itte)
+static void update_affinity_ite(struct kvm *kvm, struct its_ite *ite)
 {
 	struct kvm_vcpu *vcpu;
 
-	if (!its_is_collection_mapped(itte->collection))
+	if (!its_is_collection_mapped(ite->collection))
 		return;
 
-	vcpu = kvm_get_vcpu(kvm, itte->collection->target_addr);
+	vcpu = kvm_get_vcpu(kvm, ite->collection->target_addr);
 
-	spin_lock(&itte->irq->irq_lock);
-	itte->irq->target_vcpu = vcpu;
-	spin_unlock(&itte->irq->irq_lock);
+	spin_lock(&ite->irq->irq_lock);
+	ite->irq->target_vcpu = vcpu;
+	spin_unlock(&ite->irq->irq_lock);
 }
 
 /*
@@ -292,13 +292,13 @@ static void update_affinity_collection(struct kvm *kvm, struct vgic_its *its,
 				       struct its_collection *coll)
 {
 	struct its_device *device;
-	struct its_itte *itte;
+	struct its_ite *ite;
 
-	for_each_lpi_its(device, itte, its) {
-		if (!itte->collection || coll != itte->collection)
+	for_each_lpi_its(device, ite, its) {
+		if (!ite->collection || coll != ite->collection)
 			continue;
 
-		update_affinity_itte(kvm, itte);
+		update_affinity_ite(kvm, ite);
 	}
 }
 
@@ -425,25 +425,25 @@ static int vgic_its_trigger_msi(struct kvm *kvm, struct vgic_its *its,
 				u32 devid, u32 eventid)
 {
 	struct kvm_vcpu *vcpu;
-	struct its_itte *itte;
+	struct its_ite *ite;
 
 	if (!its->enabled)
 		return -EBUSY;
 
-	itte = find_itte(its, devid, eventid);
-	if (!itte || !its_is_collection_mapped(itte->collection))
+	ite = find_ite(its, devid, eventid);
+	if (!ite || !its_is_collection_mapped(ite->collection))
 		return E_ITS_INT_UNMAPPED_INTERRUPT;
 
-	vcpu = kvm_get_vcpu(kvm, itte->collection->target_addr);
+	vcpu = kvm_get_vcpu(kvm, ite->collection->target_addr);
 	if (!vcpu)
 		return E_ITS_INT_UNMAPPED_INTERRUPT;
 
 	if (!vcpu->arch.vgic_cpu.lpis_enabled)
 		return -EBUSY;
 
-	spin_lock(&itte->irq->irq_lock);
-	itte->irq->pending_latch = true;
-	vgic_queue_irq_unlock(kvm, itte->irq);
+	spin_lock(&ite->irq->irq_lock);
+	ite->irq->pending_latch = true;
+	vgic_queue_irq_unlock(kvm, ite->irq);
 
 	return 0;
 }
@@ -511,15 +511,15 @@ int vgic_its_inject_msi(struct kvm *kvm, struct kvm_msi *msi)
 }
 
 /* Requires the its_lock to be held. */
-static void its_free_itte(struct kvm *kvm, struct its_itte *itte)
+static void its_free_ite(struct kvm *kvm, struct its_ite *ite)
 {
-	list_del(&itte->itte_list);
+	list_del(&ite->ite_list);
 
 	/* This put matches the get in vgic_add_lpi. */
-	if (itte->irq)
-		vgic_put_irq(kvm, itte->irq);
+	if (ite->irq)
+		vgic_put_irq(kvm, ite->irq);
 
-	kfree(itte);
+	kfree(ite);
 }
 
 static u64 its_cmd_mask_field(u64 *its_cmd, int word, int shift, int size)
@@ -544,17 +544,17 @@ static int vgic_its_cmd_handle_discard(struct kvm *kvm, struct vgic_its *its,
 {
 	u32 device_id = its_cmd_get_deviceid(its_cmd);
 	u32 event_id = its_cmd_get_id(its_cmd);
-	struct its_itte *itte;
+	struct its_ite *ite;
 
 
-	itte = find_itte(its, device_id, event_id);
-	if (itte && itte->collection) {
+	ite = find_ite(its, device_id, event_id);
+	if (ite && ite->collection) {
 		/*
 		 * Though the spec talks about removing the pending state, we
 		 * don't bother here since we clear the ITTE anyway and the
 		 * pending state is a property of the ITTE struct.
 		 */
-		its_free_itte(kvm, itte);
+		its_free_ite(kvm, ite);
 		return 0;
 	}
 
@@ -572,26 +572,26 @@ static int vgic_its_cmd_handle_movi(struct kvm *kvm, struct vgic_its *its,
 	u32 event_id = its_cmd_get_id(its_cmd);
 	u32 coll_id = its_cmd_get_collection(its_cmd);
 	struct kvm_vcpu *vcpu;
-	struct its_itte *itte;
+	struct its_ite *ite;
 	struct its_collection *collection;
 
-	itte = find_itte(its, device_id, event_id);
-	if (!itte)
+	ite = find_ite(its, device_id, event_id);
+	if (!ite)
 		return E_ITS_MOVI_UNMAPPED_INTERRUPT;
 
-	if (!its_is_collection_mapped(itte->collection))
+	if (!its_is_collection_mapped(ite->collection))
 		return E_ITS_MOVI_UNMAPPED_COLLECTION;
 
 	collection = find_collection(its, coll_id);
 	if (!its_is_collection_mapped(collection))
 		return E_ITS_MOVI_UNMAPPED_COLLECTION;
 
-	itte->collection = collection;
+	ite->collection = collection;
 	vcpu = kvm_get_vcpu(kvm, collection->target_addr);
 
-	spin_lock(&itte->irq->irq_lock);
-	itte->irq->target_vcpu = vcpu;
-	spin_unlock(&itte->irq->irq_lock);
+	spin_lock(&ite->irq->irq_lock);
+	ite->irq->target_vcpu = vcpu;
+	spin_unlock(&ite->irq->irq_lock);
 
 	return 0;
 }
@@ -679,7 +679,7 @@ static void vgic_its_free_collection(struct vgic_its *its, u32 coll_id)
 {
 	struct its_collection *collection;
 	struct its_device *device;
-	struct its_itte *itte;
+	struct its_ite *ite;
 
 	/*
 	 * Clearing the mapping for that collection ID removes the
@@ -690,10 +690,10 @@ static void vgic_its_free_collection(struct vgic_its *its, u32 coll_id)
 	if (!collection)
 		return;
 
-	for_each_lpi_its(device, itte, its)
-		if (itte->collection &&
-		    itte->collection->collection_id == coll_id)
-			itte->collection = NULL;
+	for_each_lpi_its(device, ite, its)
+		if (ite->collection &&
+		    ite->collection->collection_id == coll_id)
+			ite->collection = NULL;
 
 	list_del(&collection->coll_list);
 	kfree(collection);
@@ -709,7 +709,7 @@ static int vgic_its_cmd_handle_mapi(struct kvm *kvm, struct vgic_its *its,
 	u32 device_id = its_cmd_get_deviceid(its_cmd);
 	u32 event_id = its_cmd_get_id(its_cmd);
 	u32 coll_id = its_cmd_get_collection(its_cmd);
-	struct its_itte *itte;
+	struct its_ite *ite;
 	struct its_device *device;
 	struct its_collection *collection, *new_coll = NULL;
 	int lpi_nr;
@@ -728,7 +728,7 @@ static int vgic_its_cmd_handle_mapi(struct kvm *kvm, struct vgic_its *its,
 		return E_ITS_MAPTI_PHYSICALID_OOR;
 
 	/* If there is an existing mapping, behavior is UNPREDICTABLE. */
-	if (find_itte(its, device_id, event_id))
+	if (find_ite(its, device_id, event_id))
 		return 0;
 
 	collection = find_collection(its, coll_id);
@@ -739,36 +739,36 @@ static int vgic_its_cmd_handle_mapi(struct kvm *kvm, struct vgic_its *its,
 		new_coll = collection;
 	}
 
-	itte = kzalloc(sizeof(struct its_itte), GFP_KERNEL);
-	if (!itte) {
+	ite = kzalloc(sizeof(struct its_ite), GFP_KERNEL);
+	if (!ite) {
 		if (new_coll)
 			vgic_its_free_collection(its, coll_id);
 		return -ENOMEM;
 	}
 
-	itte->event_id	= event_id;
-	list_add_tail(&itte->itte_list, &device->itt_head);
+	ite->event_id	= event_id;
+	list_add_tail(&ite->ite_list, &device->itt_head);
 
-	itte->collection = collection;
-	itte->lpi = lpi_nr;
+	ite->collection = collection;
+	ite->lpi = lpi_nr;
 
 	irq = vgic_add_lpi(kvm, lpi_nr);
 	if (IS_ERR(irq)) {
 		if (new_coll)
 			vgic_its_free_collection(its, coll_id);
-		its_free_itte(kvm, itte);
+		its_free_ite(kvm, ite);
 		return PTR_ERR(irq);
 	}
-	itte->irq = irq;
+	ite->irq = irq;
 
-	update_affinity_itte(kvm, itte);
+	update_affinity_ite(kvm, ite);
 
 	/*
 	 * We "cache" the configuration table entries in out struct vgic_irq's.
 	 * However we only have those structs for mapped IRQs, so we read in
 	 * the respective config data from memory here upon mapping the LPI.
 	 */
-	update_lpi_config(kvm, itte->irq, NULL);
+	update_lpi_config(kvm, ite->irq, NULL);
 
 	return 0;
 }
@@ -776,15 +776,15 @@ static int vgic_its_cmd_handle_mapi(struct kvm *kvm, struct vgic_its *its,
 /* Requires the its_lock to be held. */
 static void vgic_its_unmap_device(struct kvm *kvm, struct its_device *device)
 {
-	struct its_itte *itte, *temp;
+	struct its_ite *ite, *temp;
 
 	/*
 	 * The spec says that unmapping a device with still valid
 	 * ITTEs associated is UNPREDICTABLE. We remove all ITTEs,
 	 * since we cannot leave the memory unreferenced.
 	 */
-	list_for_each_entry_safe(itte, temp, &device->itt_head, itte_list)
-		its_free_itte(kvm, itte);
+	list_for_each_entry_safe(ite, temp, &device->itt_head, ite_list)
+		its_free_ite(kvm, ite);
 
 	list_del(&device->dev_list);
 	kfree(device);
@@ -883,14 +883,14 @@ static int vgic_its_cmd_handle_clear(struct kvm *kvm, struct vgic_its *its,
 {
 	u32 device_id = its_cmd_get_deviceid(its_cmd);
 	u32 event_id = its_cmd_get_id(its_cmd);
-	struct its_itte *itte;
+	struct its_ite *ite;
 
 
-	itte = find_itte(its, device_id, event_id);
-	if (!itte)
+	ite = find_ite(its, device_id, event_id);
+	if (!ite)
 		return E_ITS_CLEAR_UNMAPPED_INTERRUPT;
 
-	itte->irq->pending_latch = false;
+	ite->irq->pending_latch = false;
 
 	return 0;
 }
@@ -904,14 +904,14 @@ static int vgic_its_cmd_handle_inv(struct kvm *kvm, struct vgic_its *its,
 {
 	u32 device_id = its_cmd_get_deviceid(its_cmd);
 	u32 event_id = its_cmd_get_id(its_cmd);
-	struct its_itte *itte;
+	struct its_ite *ite;
 
 
-	itte = find_itte(its, device_id, event_id);
-	if (!itte)
+	ite = find_ite(its, device_id, event_id);
+	if (!ite)
 		return E_ITS_INV_UNMAPPED_INTERRUPT;
 
-	return update_lpi_config(kvm, itte->irq, NULL);
+	return update_lpi_config(kvm, ite->irq, NULL);
 }
 
 /*
@@ -1435,7 +1435,7 @@ static void vgic_its_destroy(struct kvm_device *kvm_dev)
 	struct kvm *kvm = kvm_dev->kvm;
 	struct vgic_its *its = kvm_dev->private;
 	struct its_device *dev;
-	struct its_itte *itte;
+	struct its_ite *ite;
 	struct list_head *dev_cur, *dev_temp;
 	struct list_head *cur, *temp;
 
@@ -1450,8 +1450,8 @@ static void vgic_its_destroy(struct kvm_device *kvm_dev)
 	list_for_each_safe(dev_cur, dev_temp, &its->device_list) {
 		dev = container_of(dev_cur, struct its_device, dev_list);
 		list_for_each_safe(cur, temp, &dev->itt_head) {
-			itte = (container_of(cur, struct its_itte, itte_list));
-			its_free_itte(kvm, itte);
+			ite = (container_of(cur, struct its_ite, ite_list));
+			its_free_ite(kvm, ite);
 		}
 		list_del(dev_cur);
 		kfree(dev);
-- 
2.5.5

^ permalink raw reply related	[flat|nested] 144+ messages in thread

* [PATCH v4 03/22] arm/arm64: vgic: turn vgic_find_mmio_region into public
  2017-03-27  9:30 ` Eric Auger
@ 2017-03-27  9:30   ` Eric Auger
  -1 siblings, 0 replies; 144+ messages in thread
From: Eric Auger @ 2017-03-27  9:30 UTC (permalink / raw)
  To: eric.auger.pro, eric.auger, marc.zyngier, christoffer.dall,
	andre.przywara, vijayak, Vijaya.Kumar, peter.maydell,
	linux-arm-kernel, kvmarm, kvm
  Cc: Prasun.Kapoor, quintela, dgilbert, pbonzini

We plan to use vgic_find_mmio_region in vgic-its.c so let's
turn it into a public function.

Also let's take the opportunity to rename the region parameter
into regions to emphasize this latter is an array of regions.

Signed-off-by: Eric Auger <eric.auger@redhat.com>
Reviewed-by: Andre Przywara <andre.przywara@arm.com>

---

v3 -> v4:
- rename region parameter into regions
- add Andre's R-b
---
 virt/kvm/arm/vgic/vgic-mmio.c | 11 +++++------
 virt/kvm/arm/vgic/vgic-mmio.h |  5 +++++
 2 files changed, 10 insertions(+), 6 deletions(-)

diff --git a/virt/kvm/arm/vgic/vgic-mmio.c b/virt/kvm/arm/vgic/vgic-mmio.c
index 2a5db13..1c17b2a 100644
--- a/virt/kvm/arm/vgic/vgic-mmio.c
+++ b/virt/kvm/arm/vgic/vgic-mmio.c
@@ -446,13 +446,12 @@ static int match_region(const void *key, const void *elt)
 	return 0;
 }
 
-/* Find the proper register handler entry given a certain address offset. */
-static const struct vgic_register_region *
-vgic_find_mmio_region(const struct vgic_register_region *region, int nr_regions,
-		      unsigned int offset)
+const struct vgic_register_region *
+vgic_find_mmio_region(const struct vgic_register_region *regions,
+		      int nr_regions, unsigned int offset)
 {
-	return bsearch((void *)(uintptr_t)offset, region, nr_regions,
-		       sizeof(region[0]), match_region);
+	return bsearch((void *)(uintptr_t)offset, regions, nr_regions,
+		       sizeof(regions[0]), match_region);
 }
 
 void vgic_set_vmcr(struct kvm_vcpu *vcpu, struct vgic_vmcr *vmcr)
diff --git a/virt/kvm/arm/vgic/vgic-mmio.h b/virt/kvm/arm/vgic/vgic-mmio.h
index 98bb566..6eec91b 100644
--- a/virt/kvm/arm/vgic/vgic-mmio.h
+++ b/virt/kvm/arm/vgic/vgic-mmio.h
@@ -192,4 +192,9 @@ u64 vgic_sanitise_shareability(u64 reg);
 u64 vgic_sanitise_field(u64 reg, u64 field_mask, int field_shift,
 			u64 (*sanitise_fn)(u64));
 
+/* Find the proper register handler entry given a certain address offset */
+const struct vgic_register_region *
+vgic_find_mmio_region(const struct vgic_register_region *regions,
+		      int nr_regions, unsigned int offset);
+
 #endif
-- 
2.5.5

^ permalink raw reply related	[flat|nested] 144+ messages in thread

* [PATCH v4 03/22] arm/arm64: vgic: turn vgic_find_mmio_region into public
@ 2017-03-27  9:30   ` Eric Auger
  0 siblings, 0 replies; 144+ messages in thread
From: Eric Auger @ 2017-03-27  9:30 UTC (permalink / raw)
  To: linux-arm-kernel

We plan to use vgic_find_mmio_region in vgic-its.c so let's
turn it into a public function.

Also let's take the opportunity to rename the region parameter
into regions to emphasize this latter is an array of regions.

Signed-off-by: Eric Auger <eric.auger@redhat.com>
Reviewed-by: Andre Przywara <andre.przywara@arm.com>

---

v3 -> v4:
- rename region parameter into regions
- add Andre's R-b
---
 virt/kvm/arm/vgic/vgic-mmio.c | 11 +++++------
 virt/kvm/arm/vgic/vgic-mmio.h |  5 +++++
 2 files changed, 10 insertions(+), 6 deletions(-)

diff --git a/virt/kvm/arm/vgic/vgic-mmio.c b/virt/kvm/arm/vgic/vgic-mmio.c
index 2a5db13..1c17b2a 100644
--- a/virt/kvm/arm/vgic/vgic-mmio.c
+++ b/virt/kvm/arm/vgic/vgic-mmio.c
@@ -446,13 +446,12 @@ static int match_region(const void *key, const void *elt)
 	return 0;
 }
 
-/* Find the proper register handler entry given a certain address offset. */
-static const struct vgic_register_region *
-vgic_find_mmio_region(const struct vgic_register_region *region, int nr_regions,
-		      unsigned int offset)
+const struct vgic_register_region *
+vgic_find_mmio_region(const struct vgic_register_region *regions,
+		      int nr_regions, unsigned int offset)
 {
-	return bsearch((void *)(uintptr_t)offset, region, nr_regions,
-		       sizeof(region[0]), match_region);
+	return bsearch((void *)(uintptr_t)offset, regions, nr_regions,
+		       sizeof(regions[0]), match_region);
 }
 
 void vgic_set_vmcr(struct kvm_vcpu *vcpu, struct vgic_vmcr *vmcr)
diff --git a/virt/kvm/arm/vgic/vgic-mmio.h b/virt/kvm/arm/vgic/vgic-mmio.h
index 98bb566..6eec91b 100644
--- a/virt/kvm/arm/vgic/vgic-mmio.h
+++ b/virt/kvm/arm/vgic/vgic-mmio.h
@@ -192,4 +192,9 @@ u64 vgic_sanitise_shareability(u64 reg);
 u64 vgic_sanitise_field(u64 reg, u64 field_mask, int field_shift,
 			u64 (*sanitise_fn)(u64));
 
+/* Find the proper register handler entry given a certain address offset */
+const struct vgic_register_region *
+vgic_find_mmio_region(const struct vgic_register_region *regions,
+		      int nr_regions, unsigned int offset);
+
 #endif
-- 
2.5.5

^ permalink raw reply related	[flat|nested] 144+ messages in thread

* [PATCH v4 04/22] KVM: arm64: ITS: KVM_DEV_ARM_VGIC_GRP_ITS_REGS group
  2017-03-27  9:30 ` Eric Auger
@ 2017-03-27  9:30   ` Eric Auger
  -1 siblings, 0 replies; 144+ messages in thread
From: Eric Auger @ 2017-03-27  9:30 UTC (permalink / raw)
  To: eric.auger.pro, eric.auger, marc.zyngier, christoffer.dall,
	andre.przywara, vijayak, Vijaya.Kumar, peter.maydell,
	linux-arm-kernel, kvmarm, kvm
  Cc: Prasun.Kapoor, quintela, dgilbert, pbonzini

The ITS KVM device exposes a new KVM_DEV_ARM_VGIC_GRP_ITS_REGS
group which allows the userspace to save/restore ITS registers.

At this stage the get/set/has operations are not yet implemented.

Signed-off-by: Eric Auger <eric.auger@redhat.com>
Reviewed-by: Andre Przywara <andre.przywara@arm.com>

---

v3 -> v4:
- added Andre's R-b
---
 arch/arm/include/uapi/asm/kvm.h   |  1 +
 arch/arm64/include/uapi/asm/kvm.h |  1 +
 virt/kvm/arm/vgic/vgic-its.c      | 36 +++++++++++++++++++++++++++++++++++-
 3 files changed, 37 insertions(+), 1 deletion(-)

diff --git a/arch/arm/include/uapi/asm/kvm.h b/arch/arm/include/uapi/asm/kvm.h
index 6ebd3e6..4beb83b 100644
--- a/arch/arm/include/uapi/asm/kvm.h
+++ b/arch/arm/include/uapi/asm/kvm.h
@@ -192,6 +192,7 @@ struct kvm_arch_memory_slot {
 #define KVM_DEV_ARM_VGIC_GRP_REDIST_REGS 5
 #define KVM_DEV_ARM_VGIC_GRP_CPU_SYSREGS 6
 #define KVM_DEV_ARM_VGIC_GRP_LEVEL_INFO  7
+#define KVM_DEV_ARM_VGIC_GRP_ITS_REGS	8
 #define KVM_DEV_ARM_VGIC_LINE_LEVEL_INFO_SHIFT	10
 #define KVM_DEV_ARM_VGIC_LINE_LEVEL_INFO_MASK \
 			(0x3fffffULL << KVM_DEV_ARM_VGIC_LINE_LEVEL_INFO_SHIFT)
diff --git a/arch/arm64/include/uapi/asm/kvm.h b/arch/arm64/include/uapi/asm/kvm.h
index c286035..7e8dd69 100644
--- a/arch/arm64/include/uapi/asm/kvm.h
+++ b/arch/arm64/include/uapi/asm/kvm.h
@@ -212,6 +212,7 @@ struct kvm_arch_memory_slot {
 #define KVM_DEV_ARM_VGIC_GRP_REDIST_REGS 5
 #define KVM_DEV_ARM_VGIC_GRP_CPU_SYSREGS 6
 #define KVM_DEV_ARM_VGIC_GRP_LEVEL_INFO  7
+#define KVM_DEV_ARM_VGIC_GRP_ITS_REGS 8
 #define KVM_DEV_ARM_VGIC_LINE_LEVEL_INFO_SHIFT	10
 #define KVM_DEV_ARM_VGIC_LINE_LEVEL_INFO_MASK \
 			(0x3fffffULL << KVM_DEV_ARM_VGIC_LINE_LEVEL_INFO_SHIFT)
diff --git a/virt/kvm/arm/vgic/vgic-its.c b/virt/kvm/arm/vgic/vgic-its.c
index 3ffcbbe..f687e91 100644
--- a/virt/kvm/arm/vgic/vgic-its.c
+++ b/virt/kvm/arm/vgic/vgic-its.c
@@ -1466,6 +1466,19 @@ static void vgic_its_destroy(struct kvm_device *kvm_dev)
 	kfree(its);
 }
 
+int vgic_its_has_attr_regs(struct kvm_device *dev,
+			   struct kvm_device_attr *attr)
+{
+	return -ENXIO;
+}
+
+int vgic_its_attr_regs_access(struct kvm_device *dev,
+			      struct kvm_device_attr *attr,
+			      u64 *reg, bool is_write)
+{
+	return -ENXIO;
+}
+
 static int vgic_its_has_attr(struct kvm_device *dev,
 			     struct kvm_device_attr *attr)
 {
@@ -1482,6 +1495,8 @@ static int vgic_its_has_attr(struct kvm_device *dev,
 			return 0;
 		}
 		break;
+	case KVM_DEV_ARM_VGIC_GRP_ITS_REGS:
+		return vgic_its_has_attr_regs(dev, attr);
 	}
 	return -ENXIO;
 }
@@ -1521,6 +1536,15 @@ static int vgic_its_set_attr(struct kvm_device *dev,
 			return 0;
 		}
 		break;
+	case KVM_DEV_ARM_VGIC_GRP_ITS_REGS: {
+		u64 __user *uaddr = (u64 __user *)(long)attr->addr;
+		u64 reg;
+
+		if (get_user(reg, uaddr))
+			return -EFAULT;
+
+		return vgic_its_attr_regs_access(dev, attr, &reg, true);
+	}
 	}
 	return -ENXIO;
 }
@@ -1541,10 +1565,20 @@ static int vgic_its_get_attr(struct kvm_device *dev,
 		if (copy_to_user(uaddr, &addr, sizeof(addr)))
 			return -EFAULT;
 		break;
+	}
+	case KVM_DEV_ARM_VGIC_GRP_ITS_REGS: {
+		u64 __user *uaddr = (u64 __user *)(long)attr->addr;
+		u64 reg;
+		int ret;
+
+		ret = vgic_its_attr_regs_access(dev, attr, &reg, false);
+		if (ret)
+			return ret;
+		return put_user(reg, uaddr);
+	}
 	default:
 		return -ENXIO;
 	}
-	}
 
 	return 0;
 }
-- 
2.5.5

^ permalink raw reply related	[flat|nested] 144+ messages in thread

* [PATCH v4 04/22] KVM: arm64: ITS: KVM_DEV_ARM_VGIC_GRP_ITS_REGS group
@ 2017-03-27  9:30   ` Eric Auger
  0 siblings, 0 replies; 144+ messages in thread
From: Eric Auger @ 2017-03-27  9:30 UTC (permalink / raw)
  To: linux-arm-kernel

The ITS KVM device exposes a new KVM_DEV_ARM_VGIC_GRP_ITS_REGS
group which allows the userspace to save/restore ITS registers.

At this stage the get/set/has operations are not yet implemented.

Signed-off-by: Eric Auger <eric.auger@redhat.com>
Reviewed-by: Andre Przywara <andre.przywara@arm.com>

---

v3 -> v4:
- added Andre's R-b
---
 arch/arm/include/uapi/asm/kvm.h   |  1 +
 arch/arm64/include/uapi/asm/kvm.h |  1 +
 virt/kvm/arm/vgic/vgic-its.c      | 36 +++++++++++++++++++++++++++++++++++-
 3 files changed, 37 insertions(+), 1 deletion(-)

diff --git a/arch/arm/include/uapi/asm/kvm.h b/arch/arm/include/uapi/asm/kvm.h
index 6ebd3e6..4beb83b 100644
--- a/arch/arm/include/uapi/asm/kvm.h
+++ b/arch/arm/include/uapi/asm/kvm.h
@@ -192,6 +192,7 @@ struct kvm_arch_memory_slot {
 #define KVM_DEV_ARM_VGIC_GRP_REDIST_REGS 5
 #define KVM_DEV_ARM_VGIC_GRP_CPU_SYSREGS 6
 #define KVM_DEV_ARM_VGIC_GRP_LEVEL_INFO  7
+#define KVM_DEV_ARM_VGIC_GRP_ITS_REGS	8
 #define KVM_DEV_ARM_VGIC_LINE_LEVEL_INFO_SHIFT	10
 #define KVM_DEV_ARM_VGIC_LINE_LEVEL_INFO_MASK \
 			(0x3fffffULL << KVM_DEV_ARM_VGIC_LINE_LEVEL_INFO_SHIFT)
diff --git a/arch/arm64/include/uapi/asm/kvm.h b/arch/arm64/include/uapi/asm/kvm.h
index c286035..7e8dd69 100644
--- a/arch/arm64/include/uapi/asm/kvm.h
+++ b/arch/arm64/include/uapi/asm/kvm.h
@@ -212,6 +212,7 @@ struct kvm_arch_memory_slot {
 #define KVM_DEV_ARM_VGIC_GRP_REDIST_REGS 5
 #define KVM_DEV_ARM_VGIC_GRP_CPU_SYSREGS 6
 #define KVM_DEV_ARM_VGIC_GRP_LEVEL_INFO  7
+#define KVM_DEV_ARM_VGIC_GRP_ITS_REGS 8
 #define KVM_DEV_ARM_VGIC_LINE_LEVEL_INFO_SHIFT	10
 #define KVM_DEV_ARM_VGIC_LINE_LEVEL_INFO_MASK \
 			(0x3fffffULL << KVM_DEV_ARM_VGIC_LINE_LEVEL_INFO_SHIFT)
diff --git a/virt/kvm/arm/vgic/vgic-its.c b/virt/kvm/arm/vgic/vgic-its.c
index 3ffcbbe..f687e91 100644
--- a/virt/kvm/arm/vgic/vgic-its.c
+++ b/virt/kvm/arm/vgic/vgic-its.c
@@ -1466,6 +1466,19 @@ static void vgic_its_destroy(struct kvm_device *kvm_dev)
 	kfree(its);
 }
 
+int vgic_its_has_attr_regs(struct kvm_device *dev,
+			   struct kvm_device_attr *attr)
+{
+	return -ENXIO;
+}
+
+int vgic_its_attr_regs_access(struct kvm_device *dev,
+			      struct kvm_device_attr *attr,
+			      u64 *reg, bool is_write)
+{
+	return -ENXIO;
+}
+
 static int vgic_its_has_attr(struct kvm_device *dev,
 			     struct kvm_device_attr *attr)
 {
@@ -1482,6 +1495,8 @@ static int vgic_its_has_attr(struct kvm_device *dev,
 			return 0;
 		}
 		break;
+	case KVM_DEV_ARM_VGIC_GRP_ITS_REGS:
+		return vgic_its_has_attr_regs(dev, attr);
 	}
 	return -ENXIO;
 }
@@ -1521,6 +1536,15 @@ static int vgic_its_set_attr(struct kvm_device *dev,
 			return 0;
 		}
 		break;
+	case KVM_DEV_ARM_VGIC_GRP_ITS_REGS: {
+		u64 __user *uaddr = (u64 __user *)(long)attr->addr;
+		u64 reg;
+
+		if (get_user(reg, uaddr))
+			return -EFAULT;
+
+		return vgic_its_attr_regs_access(dev, attr, &reg, true);
+	}
 	}
 	return -ENXIO;
 }
@@ -1541,10 +1565,20 @@ static int vgic_its_get_attr(struct kvm_device *dev,
 		if (copy_to_user(uaddr, &addr, sizeof(addr)))
 			return -EFAULT;
 		break;
+	}
+	case KVM_DEV_ARM_VGIC_GRP_ITS_REGS: {
+		u64 __user *uaddr = (u64 __user *)(long)attr->addr;
+		u64 reg;
+		int ret;
+
+		ret = vgic_its_attr_regs_access(dev, attr, &reg, false);
+		if (ret)
+			return ret;
+		return put_user(reg, uaddr);
+	}
 	default:
 		return -ENXIO;
 	}
-	}
 
 	return 0;
 }
-- 
2.5.5

^ permalink raw reply related	[flat|nested] 144+ messages in thread

* [PATCH v4 05/22] KVM: arm/arm64: vgic: expose (un)lock_all_vcpus
  2017-03-27  9:30 ` Eric Auger
@ 2017-03-27  9:30   ` Eric Auger
  -1 siblings, 0 replies; 144+ messages in thread
From: Eric Auger @ 2017-03-27  9:30 UTC (permalink / raw)
  To: eric.auger.pro, eric.auger, marc.zyngier, christoffer.dall,
	andre.przywara, vijayak, Vijaya.Kumar, peter.maydell,
	linux-arm-kernel, kvmarm, kvm
  Cc: Prasun.Kapoor, quintela, dgilbert, pbonzini

We need to use those helpers in vgic-its.c so let's
expose them in the private vgic header.

Signed-off-by: Eric Auger <eric.auger@redhat.com>
---
 virt/kvm/arm/vgic/vgic-kvm-device.c | 4 ++--
 virt/kvm/arm/vgic/vgic.h            | 3 +++
 2 files changed, 5 insertions(+), 2 deletions(-)

diff --git a/virt/kvm/arm/vgic/vgic-kvm-device.c b/virt/kvm/arm/vgic/vgic-kvm-device.c
index d181d2b..859bfa8 100644
--- a/virt/kvm/arm/vgic/vgic-kvm-device.c
+++ b/virt/kvm/arm/vgic/vgic-kvm-device.c
@@ -259,13 +259,13 @@ static void unlock_vcpus(struct kvm *kvm, int vcpu_lock_idx)
 	}
 }
 
-static void unlock_all_vcpus(struct kvm *kvm)
+void unlock_all_vcpus(struct kvm *kvm)
 {
 	unlock_vcpus(kvm, atomic_read(&kvm->online_vcpus) - 1);
 }
 
 /* Returns true if all vcpus were locked, false otherwise */
-static bool lock_all_vcpus(struct kvm *kvm)
+bool lock_all_vcpus(struct kvm *kvm)
 {
 	struct kvm_vcpu *tmp_vcpu;
 	int c;
diff --git a/virt/kvm/arm/vgic/vgic.h b/virt/kvm/arm/vgic/vgic.h
index db28f7c..56ad0e0 100644
--- a/virt/kvm/arm/vgic/vgic.h
+++ b/virt/kvm/arm/vgic/vgic.h
@@ -175,4 +175,7 @@ int vgic_init(struct kvm *kvm);
 int vgic_debug_init(struct kvm *kvm);
 int vgic_debug_destroy(struct kvm *kvm);
 
+bool lock_all_vcpus(struct kvm *kvm);
+void unlock_all_vcpus(struct kvm *kvm);
+
 #endif
-- 
2.5.5

^ permalink raw reply related	[flat|nested] 144+ messages in thread

* [PATCH v4 05/22] KVM: arm/arm64: vgic: expose (un)lock_all_vcpus
@ 2017-03-27  9:30   ` Eric Auger
  0 siblings, 0 replies; 144+ messages in thread
From: Eric Auger @ 2017-03-27  9:30 UTC (permalink / raw)
  To: linux-arm-kernel

We need to use those helpers in vgic-its.c so let's
expose them in the private vgic header.

Signed-off-by: Eric Auger <eric.auger@redhat.com>
---
 virt/kvm/arm/vgic/vgic-kvm-device.c | 4 ++--
 virt/kvm/arm/vgic/vgic.h            | 3 +++
 2 files changed, 5 insertions(+), 2 deletions(-)

diff --git a/virt/kvm/arm/vgic/vgic-kvm-device.c b/virt/kvm/arm/vgic/vgic-kvm-device.c
index d181d2b..859bfa8 100644
--- a/virt/kvm/arm/vgic/vgic-kvm-device.c
+++ b/virt/kvm/arm/vgic/vgic-kvm-device.c
@@ -259,13 +259,13 @@ static void unlock_vcpus(struct kvm *kvm, int vcpu_lock_idx)
 	}
 }
 
-static void unlock_all_vcpus(struct kvm *kvm)
+void unlock_all_vcpus(struct kvm *kvm)
 {
 	unlock_vcpus(kvm, atomic_read(&kvm->online_vcpus) - 1);
 }
 
 /* Returns true if all vcpus were locked, false otherwise */
-static bool lock_all_vcpus(struct kvm *kvm)
+bool lock_all_vcpus(struct kvm *kvm)
 {
 	struct kvm_vcpu *tmp_vcpu;
 	int c;
diff --git a/virt/kvm/arm/vgic/vgic.h b/virt/kvm/arm/vgic/vgic.h
index db28f7c..56ad0e0 100644
--- a/virt/kvm/arm/vgic/vgic.h
+++ b/virt/kvm/arm/vgic/vgic.h
@@ -175,4 +175,7 @@ int vgic_init(struct kvm *kvm);
 int vgic_debug_init(struct kvm *kvm);
 int vgic_debug_destroy(struct kvm *kvm);
 
+bool lock_all_vcpus(struct kvm *kvm);
+void unlock_all_vcpus(struct kvm *kvm);
+
 #endif
-- 
2.5.5

^ permalink raw reply related	[flat|nested] 144+ messages in thread

* [PATCH v4 06/22] KVM: arm64: ITS: Implement vgic_its_has_attr_regs and attr_regs_access
  2017-03-27  9:30 ` Eric Auger
@ 2017-03-27  9:30   ` Eric Auger
  -1 siblings, 0 replies; 144+ messages in thread
From: Eric Auger @ 2017-03-27  9:30 UTC (permalink / raw)
  To: eric.auger.pro, eric.auger, marc.zyngier, christoffer.dall,
	andre.przywara, vijayak, Vijaya.Kumar, peter.maydell,
	linux-arm-kernel, kvmarm, kvm
  Cc: Prasun.Kapoor, quintela, dgilbert, pbonzini

This patch implements vgic_its_has_attr_regs and vgic_its_attr_regs_access
upon the MMIO framework. VGIC ITS KVM device KVM_DEV_ARM_VGIC_GRP_ITS_REGS
group becomes functional.

At least GITS_CREADR requires to differentiate a guest write action from a
user access. As such let's introduce a new uaccess_its_write
vgic_register_region callback.

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

---

v3 -> v4:
- remove changes to the REGISTER_ITS_DESC macro. This will be handled in
  subsequent patch with the introduction of a new REGISTER_ITS_DESC_UACCESS
  macro
- fix IIDR access and add a comment wrt full length access
- handle endianness
- add kvm lock and vcpus lock
---
 virt/kvm/arm/vgic/vgic-its.c  | 78 +++++++++++++++++++++++++++++++++++++++++--
 virt/kvm/arm/vgic/vgic-mmio.h |  9 +++--
 2 files changed, 83 insertions(+), 4 deletions(-)

diff --git a/virt/kvm/arm/vgic/vgic-its.c b/virt/kvm/arm/vgic/vgic-its.c
index f687e91..9b9ea86 100644
--- a/virt/kvm/arm/vgic/vgic-its.c
+++ b/virt/kvm/arm/vgic/vgic-its.c
@@ -1469,14 +1469,88 @@ static void vgic_its_destroy(struct kvm_device *kvm_dev)
 int vgic_its_has_attr_regs(struct kvm_device *dev,
 			   struct kvm_device_attr *attr)
 {
-	return -ENXIO;
+	const struct vgic_register_region *region;
+	struct vgic_io_device iodev = {
+		.regions = its_registers,
+		.nr_regions = ARRAY_SIZE(its_registers),
+	};
+	gpa_t offset = attr->attr;
+
+	region = vgic_find_mmio_region(iodev.regions,
+				       iodev.nr_regions,
+				       offset);
+	if (!region)
+		return -ENXIO;
+
+	return 0;
 }
 
 int vgic_its_attr_regs_access(struct kvm_device *dev,
 			      struct kvm_device_attr *attr,
 			      u64 *reg, bool is_write)
 {
-	return -ENXIO;
+	const struct vgic_register_region *region;
+	struct vgic_io_device iodev = {
+		.regions = its_registers,
+		.nr_regions = ARRAY_SIZE(its_registers),
+	};
+	struct vgic_its *its = dev->private;
+	gpa_t addr, offset = attr->attr;
+	unsigned int len;
+	unsigned long data = 0;
+	int ret = 0;
+
+	/*
+	 * Among supported registers, only GITS_CTLR (0x0) and GITS_IIDR (0x4)
+	 * are 32 bits. Others are 64 bits.
+	 */
+	if ((offset < 0x8 && offset & 0x3) || (offset >= 0x8 && offset & 0x7))
+		return -EINVAL;
+
+	mutex_lock(&dev->kvm->lock);
+
+	if (IS_VGIC_ADDR_UNDEF(its->vgic_its_base)) {
+		ret = -ENXIO;
+		goto out;
+	}
+
+	region = vgic_find_mmio_region(iodev.regions,
+				       iodev.nr_regions,
+				       offset);
+	if (!region) {
+		ret = -ENXIO;
+		goto out;
+	}
+
+	if (!lock_all_vcpus(dev->kvm)) {
+		ret = -EBUSY;
+		goto out;
+	}
+
+	addr = its->vgic_its_base + offset;
+
+	/*
+	 * Only full length register accesses are supported although
+	 * the architecture spec theoretically allows upper/lower 32
+	 * bits to be accessed independently
+	 */
+	len = region->access_flags & VGIC_ACCESS_64bit ? 8 : 4;
+
+	if (is_write) {
+		data = vgic_data_mmio_bus_to_host(reg, len);
+		if (region->uaccess_its_write)
+			region->uaccess_its_write(dev->kvm, its, addr,
+						  len, data);
+		else
+			region->its_write(dev->kvm, its, addr, len, data);
+	} else {
+		data = region->its_read(dev->kvm, its, addr, len);
+		vgic_data_host_to_mmio_bus(reg, len, data);
+	}
+	unlock_all_vcpus(dev->kvm);
+out:
+	mutex_unlock(&dev->kvm->lock);
+	return ret;
 }
 
 static int vgic_its_has_attr(struct kvm_device *dev,
diff --git a/virt/kvm/arm/vgic/vgic-mmio.h b/virt/kvm/arm/vgic/vgic-mmio.h
index 6eec91b..becc473 100644
--- a/virt/kvm/arm/vgic/vgic-mmio.h
+++ b/virt/kvm/arm/vgic/vgic-mmio.h
@@ -36,8 +36,13 @@ struct vgic_register_region {
 	};
 	unsigned long (*uaccess_read)(struct kvm_vcpu *vcpu, gpa_t addr,
 				      unsigned int len);
-	void (*uaccess_write)(struct kvm_vcpu *vcpu, gpa_t addr,
-			      unsigned int len, unsigned long val);
+	union {
+		void (*uaccess_write)(struct kvm_vcpu *vcpu, gpa_t addr,
+				      unsigned int len, unsigned long val);
+		void (*uaccess_its_write)(struct kvm *kvm, struct vgic_its *its,
+					  gpa_t addr, unsigned int len,
+					  unsigned long val);
+	};
 };
 
 extern struct kvm_io_device_ops kvm_io_gic_ops;
-- 
2.5.5

^ permalink raw reply related	[flat|nested] 144+ messages in thread

* [PATCH v4 06/22] KVM: arm64: ITS: Implement vgic_its_has_attr_regs and attr_regs_access
@ 2017-03-27  9:30   ` Eric Auger
  0 siblings, 0 replies; 144+ messages in thread
From: Eric Auger @ 2017-03-27  9:30 UTC (permalink / raw)
  To: linux-arm-kernel

This patch implements vgic_its_has_attr_regs and vgic_its_attr_regs_access
upon the MMIO framework. VGIC ITS KVM device KVM_DEV_ARM_VGIC_GRP_ITS_REGS
group becomes functional.

At least GITS_CREADR requires to differentiate a guest write action from a
user access. As such let's introduce a new uaccess_its_write
vgic_register_region callback.

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

---

v3 -> v4:
- remove changes to the REGISTER_ITS_DESC macro. This will be handled in
  subsequent patch with the introduction of a new REGISTER_ITS_DESC_UACCESS
  macro
- fix IIDR access and add a comment wrt full length access
- handle endianness
- add kvm lock and vcpus lock
---
 virt/kvm/arm/vgic/vgic-its.c  | 78 +++++++++++++++++++++++++++++++++++++++++--
 virt/kvm/arm/vgic/vgic-mmio.h |  9 +++--
 2 files changed, 83 insertions(+), 4 deletions(-)

diff --git a/virt/kvm/arm/vgic/vgic-its.c b/virt/kvm/arm/vgic/vgic-its.c
index f687e91..9b9ea86 100644
--- a/virt/kvm/arm/vgic/vgic-its.c
+++ b/virt/kvm/arm/vgic/vgic-its.c
@@ -1469,14 +1469,88 @@ static void vgic_its_destroy(struct kvm_device *kvm_dev)
 int vgic_its_has_attr_regs(struct kvm_device *dev,
 			   struct kvm_device_attr *attr)
 {
-	return -ENXIO;
+	const struct vgic_register_region *region;
+	struct vgic_io_device iodev = {
+		.regions = its_registers,
+		.nr_regions = ARRAY_SIZE(its_registers),
+	};
+	gpa_t offset = attr->attr;
+
+	region = vgic_find_mmio_region(iodev.regions,
+				       iodev.nr_regions,
+				       offset);
+	if (!region)
+		return -ENXIO;
+
+	return 0;
 }
 
 int vgic_its_attr_regs_access(struct kvm_device *dev,
 			      struct kvm_device_attr *attr,
 			      u64 *reg, bool is_write)
 {
-	return -ENXIO;
+	const struct vgic_register_region *region;
+	struct vgic_io_device iodev = {
+		.regions = its_registers,
+		.nr_regions = ARRAY_SIZE(its_registers),
+	};
+	struct vgic_its *its = dev->private;
+	gpa_t addr, offset = attr->attr;
+	unsigned int len;
+	unsigned long data = 0;
+	int ret = 0;
+
+	/*
+	 * Among supported registers, only GITS_CTLR (0x0) and GITS_IIDR (0x4)
+	 * are 32 bits. Others are 64 bits.
+	 */
+	if ((offset < 0x8 && offset & 0x3) || (offset >= 0x8 && offset & 0x7))
+		return -EINVAL;
+
+	mutex_lock(&dev->kvm->lock);
+
+	if (IS_VGIC_ADDR_UNDEF(its->vgic_its_base)) {
+		ret = -ENXIO;
+		goto out;
+	}
+
+	region = vgic_find_mmio_region(iodev.regions,
+				       iodev.nr_regions,
+				       offset);
+	if (!region) {
+		ret = -ENXIO;
+		goto out;
+	}
+
+	if (!lock_all_vcpus(dev->kvm)) {
+		ret = -EBUSY;
+		goto out;
+	}
+
+	addr = its->vgic_its_base + offset;
+
+	/*
+	 * Only full length register accesses are supported although
+	 * the architecture spec theoretically allows upper/lower 32
+	 * bits to be accessed independently
+	 */
+	len = region->access_flags & VGIC_ACCESS_64bit ? 8 : 4;
+
+	if (is_write) {
+		data = vgic_data_mmio_bus_to_host(reg, len);
+		if (region->uaccess_its_write)
+			region->uaccess_its_write(dev->kvm, its, addr,
+						  len, data);
+		else
+			region->its_write(dev->kvm, its, addr, len, data);
+	} else {
+		data = region->its_read(dev->kvm, its, addr, len);
+		vgic_data_host_to_mmio_bus(reg, len, data);
+	}
+	unlock_all_vcpus(dev->kvm);
+out:
+	mutex_unlock(&dev->kvm->lock);
+	return ret;
 }
 
 static int vgic_its_has_attr(struct kvm_device *dev,
diff --git a/virt/kvm/arm/vgic/vgic-mmio.h b/virt/kvm/arm/vgic/vgic-mmio.h
index 6eec91b..becc473 100644
--- a/virt/kvm/arm/vgic/vgic-mmio.h
+++ b/virt/kvm/arm/vgic/vgic-mmio.h
@@ -36,8 +36,13 @@ struct vgic_register_region {
 	};
 	unsigned long (*uaccess_read)(struct kvm_vcpu *vcpu, gpa_t addr,
 				      unsigned int len);
-	void (*uaccess_write)(struct kvm_vcpu *vcpu, gpa_t addr,
-			      unsigned int len, unsigned long val);
+	union {
+		void (*uaccess_write)(struct kvm_vcpu *vcpu, gpa_t addr,
+				      unsigned int len, unsigned long val);
+		void (*uaccess_its_write)(struct kvm *kvm, struct vgic_its *its,
+					  gpa_t addr, unsigned int len,
+					  unsigned long val);
+	};
 };
 
 extern struct kvm_io_device_ops kvm_io_gic_ops;
-- 
2.5.5

^ permalink raw reply related	[flat|nested] 144+ messages in thread

* [PATCH v4 07/22] KVM: arm64: ITS: Implement vgic_mmio_uaccess_write_its_creadr
  2017-03-27  9:30 ` Eric Auger
@ 2017-03-27  9:30   ` Eric Auger
  -1 siblings, 0 replies; 144+ messages in thread
From: Eric Auger @ 2017-03-27  9:30 UTC (permalink / raw)
  To: eric.auger.pro, eric.auger, marc.zyngier, christoffer.dall,
	andre.przywara, vijayak, Vijaya.Kumar, peter.maydell,
	linux-arm-kernel, kvmarm, kvm
  Cc: Prasun.Kapoor, quintela, dgilbert, pbonzini

GITS_CREADR needs to be restored so let's implement the associated
uaccess_write_its callback. The write only is allowed if the its
is disabled.

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

---

v3 -> v4:
- REGISTER_ITS_DESC_UACCESS now introduced in this patch
- we now check the its is disabled
---
 virt/kvm/arm/vgic/vgic-its.c | 37 +++++++++++++++++++++++++++++++++++--
 1 file changed, 35 insertions(+), 2 deletions(-)

diff --git a/virt/kvm/arm/vgic/vgic-its.c b/virt/kvm/arm/vgic/vgic-its.c
index 9b9ea86..a5f3abe 100644
--- a/virt/kvm/arm/vgic/vgic-its.c
+++ b/virt/kvm/arm/vgic/vgic-its.c
@@ -1213,6 +1213,28 @@ static unsigned long vgic_mmio_read_its_creadr(struct kvm *kvm,
 	return extract_bytes(its->creadr, addr & 0x7, len);
 }
 
+static void vgic_mmio_uaccess_write_its_creadr(struct kvm *kvm,
+					       struct vgic_its *its,
+					       gpa_t addr, unsigned int len,
+					       unsigned long val)
+{
+	u32 reg;
+
+	mutex_lock(&its->cmd_lock);
+
+	if (its->enabled)
+		goto out;
+ 
+	reg = update_64bit_reg(its->creadr, addr & 7, len, val);
+	reg = ITS_CMD_OFFSET(reg);
+	if (reg >= ITS_CMD_BUFFER_SIZE(its->cbaser))
+		goto out;
+
+	its->creadr = reg;
+out:
+	mutex_unlock(&its->cmd_lock);
+}
+
 #define BASER_INDEX(addr) (((addr) / sizeof(u64)) & 0x7)
 static unsigned long vgic_mmio_read_its_baser(struct kvm *kvm,
 					      struct vgic_its *its,
@@ -1317,6 +1339,16 @@ static void vgic_mmio_write_its_ctlr(struct kvm *kvm, struct vgic_its *its,
 	.its_write = wr,					\
 }
 
+#define REGISTER_ITS_DESC_UACCESS(off, rd, wr, uwr, length, acc)\
+{								\
+	.reg_offset = off,					\
+	.len = length,						\
+	.access_flags = acc,					\
+	.its_read = rd,						\
+	.its_write = wr,					\
+	.uaccess_its_write = uwr,				\
+}
+
 static void its_mmio_write_wi(struct kvm *kvm, struct vgic_its *its,
 			      gpa_t addr, unsigned int len, unsigned long val)
 {
@@ -1339,8 +1371,9 @@ static struct vgic_register_region its_registers[] = {
 	REGISTER_ITS_DESC(GITS_CWRITER,
 		vgic_mmio_read_its_cwriter, vgic_mmio_write_its_cwriter, 8,
 		VGIC_ACCESS_64bit | VGIC_ACCESS_32bit),
-	REGISTER_ITS_DESC(GITS_CREADR,
-		vgic_mmio_read_its_creadr, its_mmio_write_wi, 8,
+	REGISTER_ITS_DESC_UACCESS(GITS_CREADR,
+		vgic_mmio_read_its_creadr, its_mmio_write_wi,
+		vgic_mmio_uaccess_write_its_creadr, 8,
 		VGIC_ACCESS_64bit | VGIC_ACCESS_32bit),
 	REGISTER_ITS_DESC(GITS_BASER,
 		vgic_mmio_read_its_baser, vgic_mmio_write_its_baser, 0x40,
-- 
2.5.5

^ permalink raw reply related	[flat|nested] 144+ messages in thread

* [PATCH v4 07/22] KVM: arm64: ITS: Implement vgic_mmio_uaccess_write_its_creadr
@ 2017-03-27  9:30   ` Eric Auger
  0 siblings, 0 replies; 144+ messages in thread
From: Eric Auger @ 2017-03-27  9:30 UTC (permalink / raw)
  To: linux-arm-kernel

GITS_CREADR needs to be restored so let's implement the associated
uaccess_write_its callback. The write only is allowed if the its
is disabled.

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

---

v3 -> v4:
- REGISTER_ITS_DESC_UACCESS now introduced in this patch
- we now check the its is disabled
---
 virt/kvm/arm/vgic/vgic-its.c | 37 +++++++++++++++++++++++++++++++++++--
 1 file changed, 35 insertions(+), 2 deletions(-)

diff --git a/virt/kvm/arm/vgic/vgic-its.c b/virt/kvm/arm/vgic/vgic-its.c
index 9b9ea86..a5f3abe 100644
--- a/virt/kvm/arm/vgic/vgic-its.c
+++ b/virt/kvm/arm/vgic/vgic-its.c
@@ -1213,6 +1213,28 @@ static unsigned long vgic_mmio_read_its_creadr(struct kvm *kvm,
 	return extract_bytes(its->creadr, addr & 0x7, len);
 }
 
+static void vgic_mmio_uaccess_write_its_creadr(struct kvm *kvm,
+					       struct vgic_its *its,
+					       gpa_t addr, unsigned int len,
+					       unsigned long val)
+{
+	u32 reg;
+
+	mutex_lock(&its->cmd_lock);
+
+	if (its->enabled)
+		goto out;
+ 
+	reg = update_64bit_reg(its->creadr, addr & 7, len, val);
+	reg = ITS_CMD_OFFSET(reg);
+	if (reg >= ITS_CMD_BUFFER_SIZE(its->cbaser))
+		goto out;
+
+	its->creadr = reg;
+out:
+	mutex_unlock(&its->cmd_lock);
+}
+
 #define BASER_INDEX(addr) (((addr) / sizeof(u64)) & 0x7)
 static unsigned long vgic_mmio_read_its_baser(struct kvm *kvm,
 					      struct vgic_its *its,
@@ -1317,6 +1339,16 @@ static void vgic_mmio_write_its_ctlr(struct kvm *kvm, struct vgic_its *its,
 	.its_write = wr,					\
 }
 
+#define REGISTER_ITS_DESC_UACCESS(off, rd, wr, uwr, length, acc)\
+{								\
+	.reg_offset = off,					\
+	.len = length,						\
+	.access_flags = acc,					\
+	.its_read = rd,						\
+	.its_write = wr,					\
+	.uaccess_its_write = uwr,				\
+}
+
 static void its_mmio_write_wi(struct kvm *kvm, struct vgic_its *its,
 			      gpa_t addr, unsigned int len, unsigned long val)
 {
@@ -1339,8 +1371,9 @@ static struct vgic_register_region its_registers[] = {
 	REGISTER_ITS_DESC(GITS_CWRITER,
 		vgic_mmio_read_its_cwriter, vgic_mmio_write_its_cwriter, 8,
 		VGIC_ACCESS_64bit | VGIC_ACCESS_32bit),
-	REGISTER_ITS_DESC(GITS_CREADR,
-		vgic_mmio_read_its_creadr, its_mmio_write_wi, 8,
+	REGISTER_ITS_DESC_UACCESS(GITS_CREADR,
+		vgic_mmio_read_its_creadr, its_mmio_write_wi,
+		vgic_mmio_uaccess_write_its_creadr, 8,
 		VGIC_ACCESS_64bit | VGIC_ACCESS_32bit),
 	REGISTER_ITS_DESC(GITS_BASER,
 		vgic_mmio_read_its_baser, vgic_mmio_write_its_baser, 0x40,
-- 
2.5.5

^ permalink raw reply related	[flat|nested] 144+ messages in thread

* [PATCH v4 08/22] KVM: arm64: ITS: Implement vgic_mmio_uaccess_write_its_iidr
  2017-03-27  9:30 ` Eric Auger
@ 2017-03-27  9:30   ` Eric Auger
  -1 siblings, 0 replies; 144+ messages in thread
From: Eric Auger @ 2017-03-27  9:30 UTC (permalink / raw)
  To: eric.auger.pro, eric.auger, marc.zyngier, christoffer.dall,
	andre.przywara, vijayak, Vijaya.Kumar, peter.maydell,
	linux-arm-kernel, kvmarm, kvm
  Cc: Prasun.Kapoor, quintela, dgilbert, pbonzini

The GITS_IIDR revision field is used to encode the version of the
table layout (ABI). So we need to restore it to check the table
layout to be restored is compatible with the destination vITS.

The user selected revision is stored in the user_revision field.
It will be compared against the REV num at table restoration time.

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

---

v4: creation
---
 include/kvm/arm_vgic.h       |  2 ++
 virt/kvm/arm/vgic/vgic-its.c | 24 +++++++++++++++++++++---
 2 files changed, 23 insertions(+), 3 deletions(-)

diff --git a/include/kvm/arm_vgic.h b/include/kvm/arm_vgic.h
index b72dd2a..41b71ca 100644
--- a/include/kvm/arm_vgic.h
+++ b/include/kvm/arm_vgic.h
@@ -162,6 +162,8 @@ struct vgic_its {
 	u32			creadr;
 	u32			cwriter;
 
+	u32			user_revision;
+
 	/* Protects the device and collection lists */
 	struct mutex		its_lock;
 	struct list_head	device_list;
diff --git a/virt/kvm/arm/vgic/vgic-its.c b/virt/kvm/arm/vgic/vgic-its.c
index a5f3abe..169b486 100644
--- a/virt/kvm/arm/vgic/vgic-its.c
+++ b/virt/kvm/arm/vgic/vgic-its.c
@@ -33,6 +33,9 @@
 #include "vgic.h"
 #include "vgic-mmio.h"
 
+/* ITS Table Layout ABI Revision */
+#define REV 0x1
+
 /*
  * Creates a new (reference to a) struct vgic_irq for a given LPI.
  * If this LPI is already mapped on another ITS, we increase its refcount
@@ -384,7 +387,19 @@ static unsigned long vgic_mmio_read_its_iidr(struct kvm *kvm,
 					     struct vgic_its *its,
 					     gpa_t addr, unsigned int len)
 {
-	return (PRODUCT_ID_KVM << 24) | (IMPLEMENTER_ARM << 0);
+	return (PRODUCT_ID_KVM << 24) | (REV << 12) | IMPLEMENTER_ARM;
+}
+
+static void vgic_mmio_uaccess_write_its_iidr(struct kvm *kvm,
+					     struct vgic_its *its,
+					     gpa_t addr, unsigned int len,
+					     unsigned long val)
+{
+	u64 tmp = 0;
+
+	tmp = update_64bit_reg(tmp, addr & 3, len, val);
+	tmp = (tmp & GENMASK(15, 12)) >> 12;
+	its->user_revision = tmp;
 }
 
 static unsigned long vgic_mmio_read_its_idregs(struct kvm *kvm,
@@ -1359,8 +1374,9 @@ static struct vgic_register_region its_registers[] = {
 	REGISTER_ITS_DESC(GITS_CTLR,
 		vgic_mmio_read_its_ctlr, vgic_mmio_write_its_ctlr, 4,
 		VGIC_ACCESS_32bit),
-	REGISTER_ITS_DESC(GITS_IIDR,
-		vgic_mmio_read_its_iidr, its_mmio_write_wi, 4,
+	REGISTER_ITS_DESC_UACCESS(GITS_IIDR,
+		vgic_mmio_read_its_iidr, its_mmio_write_wi,
+		vgic_mmio_uaccess_write_its_iidr, 4,
 		VGIC_ACCESS_32bit),
 	REGISTER_ITS_DESC(GITS_TYPER,
 		vgic_mmio_read_its_typer, its_mmio_write_wi, 8,
@@ -1458,6 +1474,8 @@ static int vgic_its_create(struct kvm_device *dev, u32 type)
 		((u64)GITS_BASER_TYPE_COLLECTION << GITS_BASER_TYPE_SHIFT);
 	dev->kvm->arch.vgic.propbaser = INITIAL_PROPBASER_VALUE;
 
+	its->user_revision = 0;
+
 	dev->private = its;
 
 	return 0;
-- 
2.5.5

^ permalink raw reply related	[flat|nested] 144+ messages in thread

* [PATCH v4 08/22] KVM: arm64: ITS: Implement vgic_mmio_uaccess_write_its_iidr
@ 2017-03-27  9:30   ` Eric Auger
  0 siblings, 0 replies; 144+ messages in thread
From: Eric Auger @ 2017-03-27  9:30 UTC (permalink / raw)
  To: linux-arm-kernel

The GITS_IIDR revision field is used to encode the version of the
table layout (ABI). So we need to restore it to check the table
layout to be restored is compatible with the destination vITS.

The user selected revision is stored in the user_revision field.
It will be compared against the REV num at table restoration time.

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

---

v4: creation
---
 include/kvm/arm_vgic.h       |  2 ++
 virt/kvm/arm/vgic/vgic-its.c | 24 +++++++++++++++++++++---
 2 files changed, 23 insertions(+), 3 deletions(-)

diff --git a/include/kvm/arm_vgic.h b/include/kvm/arm_vgic.h
index b72dd2a..41b71ca 100644
--- a/include/kvm/arm_vgic.h
+++ b/include/kvm/arm_vgic.h
@@ -162,6 +162,8 @@ struct vgic_its {
 	u32			creadr;
 	u32			cwriter;
 
+	u32			user_revision;
+
 	/* Protects the device and collection lists */
 	struct mutex		its_lock;
 	struct list_head	device_list;
diff --git a/virt/kvm/arm/vgic/vgic-its.c b/virt/kvm/arm/vgic/vgic-its.c
index a5f3abe..169b486 100644
--- a/virt/kvm/arm/vgic/vgic-its.c
+++ b/virt/kvm/arm/vgic/vgic-its.c
@@ -33,6 +33,9 @@
 #include "vgic.h"
 #include "vgic-mmio.h"
 
+/* ITS Table Layout ABI Revision */
+#define REV 0x1
+
 /*
  * Creates a new (reference to a) struct vgic_irq for a given LPI.
  * If this LPI is already mapped on another ITS, we increase its refcount
@@ -384,7 +387,19 @@ static unsigned long vgic_mmio_read_its_iidr(struct kvm *kvm,
 					     struct vgic_its *its,
 					     gpa_t addr, unsigned int len)
 {
-	return (PRODUCT_ID_KVM << 24) | (IMPLEMENTER_ARM << 0);
+	return (PRODUCT_ID_KVM << 24) | (REV << 12) | IMPLEMENTER_ARM;
+}
+
+static void vgic_mmio_uaccess_write_its_iidr(struct kvm *kvm,
+					     struct vgic_its *its,
+					     gpa_t addr, unsigned int len,
+					     unsigned long val)
+{
+	u64 tmp = 0;
+
+	tmp = update_64bit_reg(tmp, addr & 3, len, val);
+	tmp = (tmp & GENMASK(15, 12)) >> 12;
+	its->user_revision = tmp;
 }
 
 static unsigned long vgic_mmio_read_its_idregs(struct kvm *kvm,
@@ -1359,8 +1374,9 @@ static struct vgic_register_region its_registers[] = {
 	REGISTER_ITS_DESC(GITS_CTLR,
 		vgic_mmio_read_its_ctlr, vgic_mmio_write_its_ctlr, 4,
 		VGIC_ACCESS_32bit),
-	REGISTER_ITS_DESC(GITS_IIDR,
-		vgic_mmio_read_its_iidr, its_mmio_write_wi, 4,
+	REGISTER_ITS_DESC_UACCESS(GITS_IIDR,
+		vgic_mmio_read_its_iidr, its_mmio_write_wi,
+		vgic_mmio_uaccess_write_its_iidr, 4,
 		VGIC_ACCESS_32bit),
 	REGISTER_ITS_DESC(GITS_TYPER,
 		vgic_mmio_read_its_typer, its_mmio_write_wi, 8,
@@ -1458,6 +1474,8 @@ static int vgic_its_create(struct kvm_device *dev, u32 type)
 		((u64)GITS_BASER_TYPE_COLLECTION << GITS_BASER_TYPE_SHIFT);
 	dev->kvm->arch.vgic.propbaser = INITIAL_PROPBASER_VALUE;
 
+	its->user_revision = 0;
+
 	dev->private = its;
 
 	return 0;
-- 
2.5.5

^ permalink raw reply related	[flat|nested] 144+ messages in thread

* [PATCH v4 09/22] KVM: arm64: ITS: Report the ITE size in GITS_TYPER
  2017-03-27  9:30 ` Eric Auger
@ 2017-03-27  9:30   ` Eric Auger
  -1 siblings, 0 replies; 144+ messages in thread
From: Eric Auger @ 2017-03-27  9:30 UTC (permalink / raw)
  To: eric.auger.pro, eric.auger, marc.zyngier, christoffer.dall,
	andre.przywara, vijayak, Vijaya.Kumar, peter.maydell,
	linux-arm-kernel, kvmarm, kvm
  Cc: Prasun.Kapoor, quintela, dgilbert, pbonzini

An ITE size of 8 Bytes is reported to the guest. Combining this
information with the number of event IDs the guest wants to support,
this latter will be able to allocate each device's ITT with the
right size.

Signed-off-by: Eric Auger <eric.auger@redhat.com>
Reviewed-by: Andre Przywara <andre.przywara@arm.com>

---

v2 -> v3:
- changed (u64)(VITS_ESZ - 1) to (VITS_ESZ - 1ULL) in
  vgic_register_its_iodev
- added Andre's R-b

v1 -> v2:
- correct ITT_ENTRY_SIZE field
- remove ITE_SIZE since all entries become 8 bytes
---
 include/linux/irqchip/arm-gic-v3.h | 1 +
 virt/kvm/arm/vgic/vgic-its.c       | 5 ++++-
 2 files changed, 5 insertions(+), 1 deletion(-)

diff --git a/include/linux/irqchip/arm-gic-v3.h b/include/linux/irqchip/arm-gic-v3.h
index 97cbca1..d86f963 100644
--- a/include/linux/irqchip/arm-gic-v3.h
+++ b/include/linux/irqchip/arm-gic-v3.h
@@ -232,6 +232,7 @@
 #define GITS_CTLR_QUIESCENT		(1U << 31)
 
 #define GITS_TYPER_PLPIS		(1UL << 0)
+#define GITS_TYPER_ITT_ENTRY_SIZE_SHIFT	4
 #define GITS_TYPER_IDBITS_SHIFT		8
 #define GITS_TYPER_DEVBITS_SHIFT	13
 #define GITS_TYPER_DEVBITS(r)		((((r) >> GITS_TYPER_DEVBITS_SHIFT) & 0x1f) + 1)
diff --git a/virt/kvm/arm/vgic/vgic-its.c b/virt/kvm/arm/vgic/vgic-its.c
index 169b486..fabcac1 100644
--- a/virt/kvm/arm/vgic/vgic-its.c
+++ b/virt/kvm/arm/vgic/vgic-its.c
@@ -179,6 +179,8 @@ static struct its_ite *find_ite(struct vgic_its *its, u32 device_id,
 
 #define GIC_LPI_OFFSET 8192
 
+#define VITS_ESZ 8
+
 /*
  * Finds and returns a collection in the ITS collection table.
  * Must be called with the its_lock mutex held.
@@ -379,6 +381,7 @@ static unsigned long vgic_mmio_read_its_typer(struct kvm *kvm,
 	 */
 	reg |= 0x0f << GITS_TYPER_DEVBITS_SHIFT;
 	reg |= 0x0f << GITS_TYPER_IDBITS_SHIFT;
+	reg |= (VITS_ESZ - 1) << GITS_TYPER_ITT_ENTRY_SIZE_SHIFT;
 
 	return extract_bytes(reg, addr & 7, len);
 }
@@ -1436,7 +1439,7 @@ static int vgic_register_its_iodev(struct kvm *kvm, struct vgic_its *its)
 	(GIC_BASER_CACHEABILITY(GITS_BASER, INNER, RaWb)		| \
 	 GIC_BASER_CACHEABILITY(GITS_BASER, OUTER, SameAsInner)		| \
 	 GIC_BASER_SHAREABILITY(GITS_BASER, InnerShareable)		| \
-	 ((8ULL - 1) << GITS_BASER_ENTRY_SIZE_SHIFT)			| \
+	 ((VITS_ESZ - 1ULL) << GITS_BASER_ENTRY_SIZE_SHIFT)		| \
 	 GITS_BASER_PAGE_SIZE_64K)
 
 #define INITIAL_PROPBASER_VALUE						  \
-- 
2.5.5

^ permalink raw reply related	[flat|nested] 144+ messages in thread

* [PATCH v4 09/22] KVM: arm64: ITS: Report the ITE size in GITS_TYPER
@ 2017-03-27  9:30   ` Eric Auger
  0 siblings, 0 replies; 144+ messages in thread
From: Eric Auger @ 2017-03-27  9:30 UTC (permalink / raw)
  To: linux-arm-kernel

An ITE size of 8 Bytes is reported to the guest. Combining this
information with the number of event IDs the guest wants to support,
this latter will be able to allocate each device's ITT with the
right size.

Signed-off-by: Eric Auger <eric.auger@redhat.com>
Reviewed-by: Andre Przywara <andre.przywara@arm.com>

---

v2 -> v3:
- changed (u64)(VITS_ESZ - 1) to (VITS_ESZ - 1ULL) in
  vgic_register_its_iodev
- added Andre's R-b

v1 -> v2:
- correct ITT_ENTRY_SIZE field
- remove ITE_SIZE since all entries become 8 bytes
---
 include/linux/irqchip/arm-gic-v3.h | 1 +
 virt/kvm/arm/vgic/vgic-its.c       | 5 ++++-
 2 files changed, 5 insertions(+), 1 deletion(-)

diff --git a/include/linux/irqchip/arm-gic-v3.h b/include/linux/irqchip/arm-gic-v3.h
index 97cbca1..d86f963 100644
--- a/include/linux/irqchip/arm-gic-v3.h
+++ b/include/linux/irqchip/arm-gic-v3.h
@@ -232,6 +232,7 @@
 #define GITS_CTLR_QUIESCENT		(1U << 31)
 
 #define GITS_TYPER_PLPIS		(1UL << 0)
+#define GITS_TYPER_ITT_ENTRY_SIZE_SHIFT	4
 #define GITS_TYPER_IDBITS_SHIFT		8
 #define GITS_TYPER_DEVBITS_SHIFT	13
 #define GITS_TYPER_DEVBITS(r)		((((r) >> GITS_TYPER_DEVBITS_SHIFT) & 0x1f) + 1)
diff --git a/virt/kvm/arm/vgic/vgic-its.c b/virt/kvm/arm/vgic/vgic-its.c
index 169b486..fabcac1 100644
--- a/virt/kvm/arm/vgic/vgic-its.c
+++ b/virt/kvm/arm/vgic/vgic-its.c
@@ -179,6 +179,8 @@ static struct its_ite *find_ite(struct vgic_its *its, u32 device_id,
 
 #define GIC_LPI_OFFSET 8192
 
+#define VITS_ESZ 8
+
 /*
  * Finds and returns a collection in the ITS collection table.
  * Must be called with the its_lock mutex held.
@@ -379,6 +381,7 @@ static unsigned long vgic_mmio_read_its_typer(struct kvm *kvm,
 	 */
 	reg |= 0x0f << GITS_TYPER_DEVBITS_SHIFT;
 	reg |= 0x0f << GITS_TYPER_IDBITS_SHIFT;
+	reg |= (VITS_ESZ - 1) << GITS_TYPER_ITT_ENTRY_SIZE_SHIFT;
 
 	return extract_bytes(reg, addr & 7, len);
 }
@@ -1436,7 +1439,7 @@ static int vgic_register_its_iodev(struct kvm *kvm, struct vgic_its *its)
 	(GIC_BASER_CACHEABILITY(GITS_BASER, INNER, RaWb)		| \
 	 GIC_BASER_CACHEABILITY(GITS_BASER, OUTER, SameAsInner)		| \
 	 GIC_BASER_SHAREABILITY(GITS_BASER, InnerShareable)		| \
-	 ((8ULL - 1) << GITS_BASER_ENTRY_SIZE_SHIFT)			| \
+	 ((VITS_ESZ - 1ULL) << GITS_BASER_ENTRY_SIZE_SHIFT)		| \
 	 GITS_BASER_PAGE_SIZE_64K)
 
 #define INITIAL_PROPBASER_VALUE						  \
-- 
2.5.5

^ permalink raw reply related	[flat|nested] 144+ messages in thread

* [PATCH v4 10/22] KVM: arm64: ITS: Interpret MAPD Size field and check related errors
  2017-03-27  9:30 ` Eric Auger
@ 2017-03-27  9:31   ` Eric Auger
  -1 siblings, 0 replies; 144+ messages in thread
From: Eric Auger @ 2017-03-27  9:31 UTC (permalink / raw)
  To: eric.auger.pro, eric.auger, marc.zyngier, christoffer.dall,
	andre.przywara, vijayak, Vijaya.Kumar, peter.maydell,
	linux-arm-kernel, kvmarm, kvm
  Cc: Prasun.Kapoor, drjones, pbonzini, dgilbert, quintela

Up to now the MAPD's ITT size field has been ignored. It encodes
the number of eventid bit minus 1. It should be used to check
the eventid when a MAPTI command is issued on a device. Let's
store the number of eventid bits in the its_device and do the
check on MAPTI. Also make sure the ITT size field does
not exceed the GITS_TYPER IDBITS field.

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

---

v3 -> v4:
- VITS_TYPER_IDBITS set to 16 to be homogeneous with VITS_ESZ definition
  and correct users
- nb_eventid_bits correspond to the actual number of eventid bits
---
 include/linux/irqchip/arm-gic-v3.h |  2 ++
 virt/kvm/arm/vgic/vgic-its.c       | 14 +++++++++++++-
 2 files changed, 15 insertions(+), 1 deletion(-)

diff --git a/include/linux/irqchip/arm-gic-v3.h b/include/linux/irqchip/arm-gic-v3.h
index d86f963..dcbb3e0 100644
--- a/include/linux/irqchip/arm-gic-v3.h
+++ b/include/linux/irqchip/arm-gic-v3.h
@@ -338,9 +338,11 @@
 #define E_ITS_INT_UNMAPPED_INTERRUPT		0x010307
 #define E_ITS_CLEAR_UNMAPPED_INTERRUPT		0x010507
 #define E_ITS_MAPD_DEVICE_OOR			0x010801
+#define E_ITS_MAPD_ITTSIZE_OOR			0x010802
 #define E_ITS_MAPC_PROCNUM_OOR			0x010902
 #define E_ITS_MAPC_COLLECTION_OOR		0x010903
 #define E_ITS_MAPTI_UNMAPPED_DEVICE		0x010a04
+#define E_ITS_MAPTI_ID_OOR			0x010a05
 #define E_ITS_MAPTI_PHYSICALID_OOR		0x010a06
 #define E_ITS_INV_UNMAPPED_INTERRUPT		0x010c07
 #define E_ITS_INVALL_UNMAPPED_COLLECTION	0x010d09
diff --git a/virt/kvm/arm/vgic/vgic-its.c b/virt/kvm/arm/vgic/vgic-its.c
index fabcac1..ddd2780 100644
--- a/virt/kvm/arm/vgic/vgic-its.c
+++ b/virt/kvm/arm/vgic/vgic-its.c
@@ -102,6 +102,7 @@ struct its_device {
 
 	/* the head for the list of ITTEs */
 	struct list_head itt_head;
+	u32 nb_eventid_bits;
 	u32 device_id;
 };
 
@@ -180,6 +181,7 @@ static struct its_ite *find_ite(struct vgic_its *its, u32 device_id,
 #define GIC_LPI_OFFSET 8192
 
 #define VITS_ESZ 8
+#define VITS_TYPER_IDBITS 16
 
 /*
  * Finds and returns a collection in the ITS collection table.
@@ -380,7 +382,7 @@ static unsigned long vgic_mmio_read_its_typer(struct kvm *kvm,
 	 * DevBits low - as least for the time being.
 	 */
 	reg |= 0x0f << GITS_TYPER_DEVBITS_SHIFT;
-	reg |= 0x0f << GITS_TYPER_IDBITS_SHIFT;
+	reg |= (VITS_TYPER_IDBITS - 1) << GITS_TYPER_IDBITS_SHIFT;
 	reg |= (VITS_ESZ - 1) << GITS_TYPER_ITT_ENTRY_SIZE_SHIFT;
 
 	return extract_bytes(reg, addr & 7, len);
@@ -547,6 +549,7 @@ static u64 its_cmd_mask_field(u64 *its_cmd, int word, int shift, int size)
 
 #define its_cmd_get_command(cmd)	its_cmd_mask_field(cmd, 0,  0,  8)
 #define its_cmd_get_deviceid(cmd)	its_cmd_mask_field(cmd, 0, 32, 32)
+#define its_cmd_get_size(cmd)		its_cmd_mask_field(cmd, 1,  0,  5)
 #define its_cmd_get_id(cmd)		its_cmd_mask_field(cmd, 1,  0, 32)
 #define its_cmd_get_physical_id(cmd)	its_cmd_mask_field(cmd, 1, 32, 32)
 #define its_cmd_get_collection(cmd)	its_cmd_mask_field(cmd, 2,  0, 16)
@@ -737,6 +740,9 @@ static int vgic_its_cmd_handle_mapi(struct kvm *kvm, struct vgic_its *its,
 	if (!device)
 		return E_ITS_MAPTI_UNMAPPED_DEVICE;
 
+	if (event_id >= BIT_ULL(device->nb_eventid_bits))
+		return E_ITS_MAPTI_ID_OOR;
+
 	if (its_cmd_get_command(its_cmd) == GITS_CMD_MAPTI)
 		lpi_nr = its_cmd_get_physical_id(its_cmd);
 	else
@@ -817,11 +823,15 @@ static int vgic_its_cmd_handle_mapd(struct kvm *kvm, struct vgic_its *its,
 {
 	u32 device_id = its_cmd_get_deviceid(its_cmd);
 	bool valid = its_cmd_get_validbit(its_cmd);
+	u8 nb_eventid_bits = its_cmd_get_size(its_cmd) + 1;
 	struct its_device *device;
 
 	if (!vgic_its_check_id(its, its->baser_device_table, device_id))
 		return E_ITS_MAPD_DEVICE_OOR;
 
+	if (valid && nb_eventid_bits > VITS_TYPER_IDBITS)
+		return E_ITS_MAPD_ITTSIZE_OOR;
+
 	device = find_its_device(its, device_id);
 
 	/*
@@ -844,6 +854,8 @@ static int vgic_its_cmd_handle_mapd(struct kvm *kvm, struct vgic_its *its,
 		return -ENOMEM;
 
 	device->device_id = device_id;
+	device->nb_eventid_bits = nb_eventid_bits;
+
 	INIT_LIST_HEAD(&device->itt_head);
 
 	list_add_tail(&device->dev_list, &its->device_list);
-- 
2.5.5

^ permalink raw reply related	[flat|nested] 144+ messages in thread

* [PATCH v4 10/22] KVM: arm64: ITS: Interpret MAPD Size field and check related errors
@ 2017-03-27  9:31   ` Eric Auger
  0 siblings, 0 replies; 144+ messages in thread
From: Eric Auger @ 2017-03-27  9:31 UTC (permalink / raw)
  To: linux-arm-kernel

Up to now the MAPD's ITT size field has been ignored. It encodes
the number of eventid bit minus 1. It should be used to check
the eventid when a MAPTI command is issued on a device. Let's
store the number of eventid bits in the its_device and do the
check on MAPTI. Also make sure the ITT size field does
not exceed the GITS_TYPER IDBITS field.

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

---

v3 -> v4:
- VITS_TYPER_IDBITS set to 16 to be homogeneous with VITS_ESZ definition
  and correct users
- nb_eventid_bits correspond to the actual number of eventid bits
---
 include/linux/irqchip/arm-gic-v3.h |  2 ++
 virt/kvm/arm/vgic/vgic-its.c       | 14 +++++++++++++-
 2 files changed, 15 insertions(+), 1 deletion(-)

diff --git a/include/linux/irqchip/arm-gic-v3.h b/include/linux/irqchip/arm-gic-v3.h
index d86f963..dcbb3e0 100644
--- a/include/linux/irqchip/arm-gic-v3.h
+++ b/include/linux/irqchip/arm-gic-v3.h
@@ -338,9 +338,11 @@
 #define E_ITS_INT_UNMAPPED_INTERRUPT		0x010307
 #define E_ITS_CLEAR_UNMAPPED_INTERRUPT		0x010507
 #define E_ITS_MAPD_DEVICE_OOR			0x010801
+#define E_ITS_MAPD_ITTSIZE_OOR			0x010802
 #define E_ITS_MAPC_PROCNUM_OOR			0x010902
 #define E_ITS_MAPC_COLLECTION_OOR		0x010903
 #define E_ITS_MAPTI_UNMAPPED_DEVICE		0x010a04
+#define E_ITS_MAPTI_ID_OOR			0x010a05
 #define E_ITS_MAPTI_PHYSICALID_OOR		0x010a06
 #define E_ITS_INV_UNMAPPED_INTERRUPT		0x010c07
 #define E_ITS_INVALL_UNMAPPED_COLLECTION	0x010d09
diff --git a/virt/kvm/arm/vgic/vgic-its.c b/virt/kvm/arm/vgic/vgic-its.c
index fabcac1..ddd2780 100644
--- a/virt/kvm/arm/vgic/vgic-its.c
+++ b/virt/kvm/arm/vgic/vgic-its.c
@@ -102,6 +102,7 @@ struct its_device {
 
 	/* the head for the list of ITTEs */
 	struct list_head itt_head;
+	u32 nb_eventid_bits;
 	u32 device_id;
 };
 
@@ -180,6 +181,7 @@ static struct its_ite *find_ite(struct vgic_its *its, u32 device_id,
 #define GIC_LPI_OFFSET 8192
 
 #define VITS_ESZ 8
+#define VITS_TYPER_IDBITS 16
 
 /*
  * Finds and returns a collection in the ITS collection table.
@@ -380,7 +382,7 @@ static unsigned long vgic_mmio_read_its_typer(struct kvm *kvm,
 	 * DevBits low - as least for the time being.
 	 */
 	reg |= 0x0f << GITS_TYPER_DEVBITS_SHIFT;
-	reg |= 0x0f << GITS_TYPER_IDBITS_SHIFT;
+	reg |= (VITS_TYPER_IDBITS - 1) << GITS_TYPER_IDBITS_SHIFT;
 	reg |= (VITS_ESZ - 1) << GITS_TYPER_ITT_ENTRY_SIZE_SHIFT;
 
 	return extract_bytes(reg, addr & 7, len);
@@ -547,6 +549,7 @@ static u64 its_cmd_mask_field(u64 *its_cmd, int word, int shift, int size)
 
 #define its_cmd_get_command(cmd)	its_cmd_mask_field(cmd, 0,  0,  8)
 #define its_cmd_get_deviceid(cmd)	its_cmd_mask_field(cmd, 0, 32, 32)
+#define its_cmd_get_size(cmd)		its_cmd_mask_field(cmd, 1,  0,  5)
 #define its_cmd_get_id(cmd)		its_cmd_mask_field(cmd, 1,  0, 32)
 #define its_cmd_get_physical_id(cmd)	its_cmd_mask_field(cmd, 1, 32, 32)
 #define its_cmd_get_collection(cmd)	its_cmd_mask_field(cmd, 2,  0, 16)
@@ -737,6 +740,9 @@ static int vgic_its_cmd_handle_mapi(struct kvm *kvm, struct vgic_its *its,
 	if (!device)
 		return E_ITS_MAPTI_UNMAPPED_DEVICE;
 
+	if (event_id >= BIT_ULL(device->nb_eventid_bits))
+		return E_ITS_MAPTI_ID_OOR;
+
 	if (its_cmd_get_command(its_cmd) == GITS_CMD_MAPTI)
 		lpi_nr = its_cmd_get_physical_id(its_cmd);
 	else
@@ -817,11 +823,15 @@ static int vgic_its_cmd_handle_mapd(struct kvm *kvm, struct vgic_its *its,
 {
 	u32 device_id = its_cmd_get_deviceid(its_cmd);
 	bool valid = its_cmd_get_validbit(its_cmd);
+	u8 nb_eventid_bits = its_cmd_get_size(its_cmd) + 1;
 	struct its_device *device;
 
 	if (!vgic_its_check_id(its, its->baser_device_table, device_id))
 		return E_ITS_MAPD_DEVICE_OOR;
 
+	if (valid && nb_eventid_bits > VITS_TYPER_IDBITS)
+		return E_ITS_MAPD_ITTSIZE_OOR;
+
 	device = find_its_device(its, device_id);
 
 	/*
@@ -844,6 +854,8 @@ static int vgic_its_cmd_handle_mapd(struct kvm *kvm, struct vgic_its *its,
 		return -ENOMEM;
 
 	device->device_id = device_id;
+	device->nb_eventid_bits = nb_eventid_bits;
+
 	INIT_LIST_HEAD(&device->itt_head);
 
 	list_add_tail(&device->dev_list, &its->device_list);
-- 
2.5.5

^ permalink raw reply related	[flat|nested] 144+ messages in thread

* [PATCH v4 11/22] KVM: arm64: ITS: Interpret MAPD ITT_addr field
  2017-03-27  9:30 ` Eric Auger
@ 2017-03-27  9:31   ` Eric Auger
  -1 siblings, 0 replies; 144+ messages in thread
From: Eric Auger @ 2017-03-27  9:31 UTC (permalink / raw)
  To: eric.auger.pro, eric.auger, marc.zyngier, christoffer.dall,
	andre.przywara, vijayak, Vijaya.Kumar, peter.maydell,
	linux-arm-kernel, kvmarm, kvm
  Cc: Prasun.Kapoor, quintela, dgilbert, pbonzini

Up to now the MAPD ITT_addr had been ignored. We will need it
for save/restore. Let's record it in the its_device struct.

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

---

v3 -> v4:
- in vgic_its_cmd_handle_mapd, itt_addr directly is shifted
- correct ittaddr bitmask to support 48bit GPA
---
 virt/kvm/arm/vgic/vgic-its.c | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/virt/kvm/arm/vgic/vgic-its.c b/virt/kvm/arm/vgic/vgic-its.c
index ddd2780..89a0db7 100644
--- a/virt/kvm/arm/vgic/vgic-its.c
+++ b/virt/kvm/arm/vgic/vgic-its.c
@@ -103,6 +103,7 @@ struct its_device {
 	/* the head for the list of ITTEs */
 	struct list_head itt_head;
 	u32 nb_eventid_bits;
+	gpa_t itt_addr;
 	u32 device_id;
 };
 
@@ -553,6 +554,7 @@ static u64 its_cmd_mask_field(u64 *its_cmd, int word, int shift, int size)
 #define its_cmd_get_id(cmd)		its_cmd_mask_field(cmd, 1,  0, 32)
 #define its_cmd_get_physical_id(cmd)	its_cmd_mask_field(cmd, 1, 32, 32)
 #define its_cmd_get_collection(cmd)	its_cmd_mask_field(cmd, 2,  0, 16)
+#define its_cmd_get_ittaddr(cmd)	its_cmd_mask_field(cmd, 2,  8, 47)
 #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)
 
@@ -824,6 +826,7 @@ static int vgic_its_cmd_handle_mapd(struct kvm *kvm, struct vgic_its *its,
 	u32 device_id = its_cmd_get_deviceid(its_cmd);
 	bool valid = its_cmd_get_validbit(its_cmd);
 	u8 nb_eventid_bits = its_cmd_get_size(its_cmd) + 1;
+	gpa_t itt_addr = its_cmd_get_ittaddr(its_cmd) << 8;
 	struct its_device *device;
 
 	if (!vgic_its_check_id(its, its->baser_device_table, device_id))
@@ -855,6 +858,7 @@ static int vgic_its_cmd_handle_mapd(struct kvm *kvm, struct vgic_its *its,
 
 	device->device_id = device_id;
 	device->nb_eventid_bits = nb_eventid_bits;
+	device->itt_addr = itt_addr;
 
 	INIT_LIST_HEAD(&device->itt_head);
 
-- 
2.5.5

^ permalink raw reply related	[flat|nested] 144+ messages in thread

* [PATCH v4 11/22] KVM: arm64: ITS: Interpret MAPD ITT_addr field
@ 2017-03-27  9:31   ` Eric Auger
  0 siblings, 0 replies; 144+ messages in thread
From: Eric Auger @ 2017-03-27  9:31 UTC (permalink / raw)
  To: linux-arm-kernel

Up to now the MAPD ITT_addr had been ignored. We will need it
for save/restore. Let's record it in the its_device struct.

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

---

v3 -> v4:
- in vgic_its_cmd_handle_mapd, itt_addr directly is shifted
- correct ittaddr bitmask to support 48bit GPA
---
 virt/kvm/arm/vgic/vgic-its.c | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/virt/kvm/arm/vgic/vgic-its.c b/virt/kvm/arm/vgic/vgic-its.c
index ddd2780..89a0db7 100644
--- a/virt/kvm/arm/vgic/vgic-its.c
+++ b/virt/kvm/arm/vgic/vgic-its.c
@@ -103,6 +103,7 @@ struct its_device {
 	/* the head for the list of ITTEs */
 	struct list_head itt_head;
 	u32 nb_eventid_bits;
+	gpa_t itt_addr;
 	u32 device_id;
 };
 
@@ -553,6 +554,7 @@ static u64 its_cmd_mask_field(u64 *its_cmd, int word, int shift, int size)
 #define its_cmd_get_id(cmd)		its_cmd_mask_field(cmd, 1,  0, 32)
 #define its_cmd_get_physical_id(cmd)	its_cmd_mask_field(cmd, 1, 32, 32)
 #define its_cmd_get_collection(cmd)	its_cmd_mask_field(cmd, 2,  0, 16)
+#define its_cmd_get_ittaddr(cmd)	its_cmd_mask_field(cmd, 2,  8, 47)
 #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)
 
@@ -824,6 +826,7 @@ static int vgic_its_cmd_handle_mapd(struct kvm *kvm, struct vgic_its *its,
 	u32 device_id = its_cmd_get_deviceid(its_cmd);
 	bool valid = its_cmd_get_validbit(its_cmd);
 	u8 nb_eventid_bits = its_cmd_get_size(its_cmd) + 1;
+	gpa_t itt_addr = its_cmd_get_ittaddr(its_cmd) << 8;
 	struct its_device *device;
 
 	if (!vgic_its_check_id(its, its->baser_device_table, device_id))
@@ -855,6 +858,7 @@ static int vgic_its_cmd_handle_mapd(struct kvm *kvm, struct vgic_its *its,
 
 	device->device_id = device_id;
 	device->nb_eventid_bits = nb_eventid_bits;
+	device->itt_addr = itt_addr;
 
 	INIT_LIST_HEAD(&device->itt_head);
 
-- 
2.5.5

^ permalink raw reply related	[flat|nested] 144+ messages in thread

* [PATCH v4 12/22] KVM: arm64: ITS: Check the device id matches TYPER DEVBITS range
  2017-03-27  9:30 ` Eric Auger
@ 2017-03-27  9:31   ` Eric Auger
  -1 siblings, 0 replies; 144+ messages in thread
From: Eric Auger @ 2017-03-27  9:31 UTC (permalink / raw)
  To: eric.auger.pro, eric.auger, marc.zyngier, christoffer.dall,
	andre.przywara, vijayak, Vijaya.Kumar, peter.maydell,
	linux-arm-kernel, kvmarm, kvm
  Cc: Prasun.Kapoor, quintela, dgilbert, pbonzini

On MAPD we currently check the device id can be stored in the device table.
Let's first check it can be encoded within the range defined by TYPER
DEVBITS.

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

---

v3 -> v4:
- VITS_TYPER_DEVBITS set to 16 for homogeneity
- use BIT_ULL
---
 virt/kvm/arm/vgic/vgic-its.c | 10 +++++++---
 1 file changed, 7 insertions(+), 3 deletions(-)

diff --git a/virt/kvm/arm/vgic/vgic-its.c b/virt/kvm/arm/vgic/vgic-its.c
index 89a0db7..b275aea 100644
--- a/virt/kvm/arm/vgic/vgic-its.c
+++ b/virt/kvm/arm/vgic/vgic-its.c
@@ -183,6 +183,7 @@ static struct its_ite *find_ite(struct vgic_its *its, u32 device_id,
 
 #define VITS_ESZ 8
 #define VITS_TYPER_IDBITS 16
+#define VITS_TYPER_DEVBITS 16
 
 /*
  * Finds and returns a collection in the ITS collection table.
@@ -382,8 +383,8 @@ static unsigned long vgic_mmio_read_its_typer(struct kvm *kvm,
 	 * To avoid memory waste in the guest, we keep the number of IDBits and
 	 * DevBits low - as least for the time being.
 	 */
-	reg |= 0x0f << GITS_TYPER_DEVBITS_SHIFT;
 	reg |= (VITS_TYPER_IDBITS - 1) << GITS_TYPER_IDBITS_SHIFT;
+	reg |= (VITS_TYPER_DEVBITS - 1) << GITS_TYPER_DEVBITS_SHIFT;
 	reg |= (VITS_ESZ - 1) << GITS_TYPER_ITT_ENTRY_SIZE_SHIFT;
 
 	return extract_bytes(reg, addr & 7, len);
@@ -623,10 +624,10 @@ static int vgic_its_cmd_handle_movi(struct kvm *kvm, struct vgic_its *its,
  * Check whether an ID can be stored into the corresponding guest table.
  * For a direct table this is pretty easy, but gets a bit nasty for
  * indirect tables. We check whether the resulting guest physical address
- * is actually valid (covered by a memslot and guest accessbible).
+ * is actually valid (covered by a memslot and guest accessible).
  * For this we have to read the respective first level entry.
  */
-static bool vgic_its_check_id(struct vgic_its *its, u64 baser, int id)
+static bool vgic_its_check_id(struct vgic_its *its, u64 baser, u32 id)
 {
 	int l1_tbl_size = GITS_BASER_NR_PAGES(baser) * SZ_64K;
 	int index;
@@ -634,6 +635,9 @@ static bool vgic_its_check_id(struct vgic_its *its, u64 baser, int id)
 	gfn_t gfn;
 	int esz = GITS_BASER_ENTRY_SIZE(baser);
 
+	if (id >= BIT_ULL(VITS_TYPER_DEVBITS))
+		return false;
+
 	if (!(baser & GITS_BASER_INDIRECT)) {
 		phys_addr_t addr;
 
-- 
2.5.5

^ permalink raw reply related	[flat|nested] 144+ messages in thread

* [PATCH v4 12/22] KVM: arm64: ITS: Check the device id matches TYPER DEVBITS range
@ 2017-03-27  9:31   ` Eric Auger
  0 siblings, 0 replies; 144+ messages in thread
From: Eric Auger @ 2017-03-27  9:31 UTC (permalink / raw)
  To: linux-arm-kernel

On MAPD we currently check the device id can be stored in the device table.
Let's first check it can be encoded within the range defined by TYPER
DEVBITS.

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

---

v3 -> v4:
- VITS_TYPER_DEVBITS set to 16 for homogeneity
- use BIT_ULL
---
 virt/kvm/arm/vgic/vgic-its.c | 10 +++++++---
 1 file changed, 7 insertions(+), 3 deletions(-)

diff --git a/virt/kvm/arm/vgic/vgic-its.c b/virt/kvm/arm/vgic/vgic-its.c
index 89a0db7..b275aea 100644
--- a/virt/kvm/arm/vgic/vgic-its.c
+++ b/virt/kvm/arm/vgic/vgic-its.c
@@ -183,6 +183,7 @@ static struct its_ite *find_ite(struct vgic_its *its, u32 device_id,
 
 #define VITS_ESZ 8
 #define VITS_TYPER_IDBITS 16
+#define VITS_TYPER_DEVBITS 16
 
 /*
  * Finds and returns a collection in the ITS collection table.
@@ -382,8 +383,8 @@ static unsigned long vgic_mmio_read_its_typer(struct kvm *kvm,
 	 * To avoid memory waste in the guest, we keep the number of IDBits and
 	 * DevBits low - as least for the time being.
 	 */
-	reg |= 0x0f << GITS_TYPER_DEVBITS_SHIFT;
 	reg |= (VITS_TYPER_IDBITS - 1) << GITS_TYPER_IDBITS_SHIFT;
+	reg |= (VITS_TYPER_DEVBITS - 1) << GITS_TYPER_DEVBITS_SHIFT;
 	reg |= (VITS_ESZ - 1) << GITS_TYPER_ITT_ENTRY_SIZE_SHIFT;
 
 	return extract_bytes(reg, addr & 7, len);
@@ -623,10 +624,10 @@ static int vgic_its_cmd_handle_movi(struct kvm *kvm, struct vgic_its *its,
  * Check whether an ID can be stored into the corresponding guest table.
  * For a direct table this is pretty easy, but gets a bit nasty for
  * indirect tables. We check whether the resulting guest physical address
- * is actually valid (covered by a memslot and guest accessbible).
+ * is actually valid (covered by a memslot and guest accessible).
  * For this we have to read the respective first level entry.
  */
-static bool vgic_its_check_id(struct vgic_its *its, u64 baser, int id)
+static bool vgic_its_check_id(struct vgic_its *its, u64 baser, u32 id)
 {
 	int l1_tbl_size = GITS_BASER_NR_PAGES(baser) * SZ_64K;
 	int index;
@@ -634,6 +635,9 @@ static bool vgic_its_check_id(struct vgic_its *its, u64 baser, int id)
 	gfn_t gfn;
 	int esz = GITS_BASER_ENTRY_SIZE(baser);
 
+	if (id >= BIT_ULL(VITS_TYPER_DEVBITS))
+		return false;
+
 	if (!(baser & GITS_BASER_INDIRECT)) {
 		phys_addr_t addr;
 
-- 
2.5.5

^ permalink raw reply related	[flat|nested] 144+ messages in thread

* [PATCH v4 13/22] KVM: arm64: ITS: KVM_DEV_ARM_VGIC_GRP_ITS_TABLES group
  2017-03-27  9:30 ` Eric Auger
@ 2017-03-27  9:31   ` Eric Auger
  -1 siblings, 0 replies; 144+ messages in thread
From: Eric Auger @ 2017-03-27  9:31 UTC (permalink / raw)
  To: eric.auger.pro, eric.auger, marc.zyngier, christoffer.dall,
	andre.przywara, vijayak, Vijaya.Kumar, peter.maydell,
	linux-arm-kernel, kvmarm, kvm
  Cc: Prasun.Kapoor, quintela, dgilbert, pbonzini

Introduce a new group aiming at saving/restoring the ITS
tables to/from the guest memory.

We hold the vcpus lock during the save and restore to make
sure no vcpu is running.

At this stage the functionality is not yet implemented. Only
the skeleton is put in place.

The ABI revision supposed to have been set through IIDR user
write is checked before the table restoration. This guarantees
this vITS knows how to restore the saved tables.

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

---

v3 -> v4:
- pass kvm struct handle to vgic_its_flush/restore_pending_tables
- take the kvm lock and vcpu locks
- ABI revision check
- check attr->attr is null

v1 -> v2:
- remove useless kvm parameter
---
 arch/arm/include/uapi/asm/kvm.h   |   1 +
 arch/arm64/include/uapi/asm/kvm.h |   1 +
 virt/kvm/arm/vgic/vgic-its.c      | 142 +++++++++++++++++++++++++++++++++++++-
 3 files changed, 143 insertions(+), 1 deletion(-)

diff --git a/arch/arm/include/uapi/asm/kvm.h b/arch/arm/include/uapi/asm/kvm.h
index 4beb83b..7b165e9 100644
--- a/arch/arm/include/uapi/asm/kvm.h
+++ b/arch/arm/include/uapi/asm/kvm.h
@@ -193,6 +193,7 @@ struct kvm_arch_memory_slot {
 #define KVM_DEV_ARM_VGIC_GRP_CPU_SYSREGS 6
 #define KVM_DEV_ARM_VGIC_GRP_LEVEL_INFO  7
 #define KVM_DEV_ARM_VGIC_GRP_ITS_REGS	8
+#define KVM_DEV_ARM_VGIC_GRP_ITS_TABLES	9
 #define KVM_DEV_ARM_VGIC_LINE_LEVEL_INFO_SHIFT	10
 #define KVM_DEV_ARM_VGIC_LINE_LEVEL_INFO_MASK \
 			(0x3fffffULL << KVM_DEV_ARM_VGIC_LINE_LEVEL_INFO_SHIFT)
diff --git a/arch/arm64/include/uapi/asm/kvm.h b/arch/arm64/include/uapi/asm/kvm.h
index 7e8dd69..166df68 100644
--- a/arch/arm64/include/uapi/asm/kvm.h
+++ b/arch/arm64/include/uapi/asm/kvm.h
@@ -213,6 +213,7 @@ struct kvm_arch_memory_slot {
 #define KVM_DEV_ARM_VGIC_GRP_CPU_SYSREGS 6
 #define KVM_DEV_ARM_VGIC_GRP_LEVEL_INFO  7
 #define KVM_DEV_ARM_VGIC_GRP_ITS_REGS 8
+#define KVM_DEV_ARM_VGIC_GRP_ITS_TABLES 9
 #define KVM_DEV_ARM_VGIC_LINE_LEVEL_INFO_SHIFT	10
 #define KVM_DEV_ARM_VGIC_LINE_LEVEL_INFO_MASK \
 			(0x3fffffULL << KVM_DEV_ARM_VGIC_LINE_LEVEL_INFO_SHIFT)
diff --git a/virt/kvm/arm/vgic/vgic-its.c b/virt/kvm/arm/vgic/vgic-its.c
index b275aea..76dd562 100644
--- a/virt/kvm/arm/vgic/vgic-its.c
+++ b/virt/kvm/arm/vgic/vgic-its.c
@@ -1627,6 +1627,135 @@ int vgic_its_attr_regs_access(struct kvm_device *dev,
 	return ret;
 }
 
+/**
+ * vgic_its_flush_pending_tables - Flush the pending tables into guest RAM
+ */
+static int vgic_its_flush_pending_tables(struct kvm *kvm)
+{
+	return -ENXIO;
+}
+
+/**
+ * vgic_its_restore_pending_tables - Restore the pending tables from guest
+ * RAM to internal data structs
+ */
+static int vgic_its_restore_pending_tables(struct kvm *kvm)
+{
+	return -ENXIO;
+}
+
+/**
+ * vgic_its_flush_device_tables - flush the device table and all ITT
+ * into guest RAM
+ */
+static int vgic_its_flush_device_tables(struct vgic_its *its)
+{
+	return -ENXIO;
+}
+
+/**
+ * vgic_its_restore_device_tables - restore the device table and all ITT
+ * from guest RAM to internal data structs
+ */
+static int vgic_its_restore_device_tables(struct vgic_its *its)
+{
+	return -ENXIO;
+}
+
+/**
+ * vgic_its_flush_collection_table - flush the collection table into
+ * guest RAM
+ */
+static int vgic_its_flush_collection_table(struct vgic_its *its)
+{
+	return -ENXIO;
+}
+
+/**
+ * vgic_its_restore_collection_table - reads the collection table
+ * in guest memory and restores the ITS internal state. Requires the
+ * BASER registers to be restored before.
+ */
+static int vgic_its_restore_collection_table(struct vgic_its *its)
+{
+	return -ENXIO;
+}
+
+/**
+ * vgic_its_table_flush - Flush all the tables into guest RAM
+ */
+static int vgic_its_table_flush(struct vgic_its *its)
+{
+	struct kvm *kvm = its->dev->kvm;
+	int ret;
+
+	mutex_lock(&kvm->lock);
+
+	if (!lock_all_vcpus(kvm)) {
+		mutex_unlock(&kvm->lock);
+		return -EBUSY;
+	}
+
+	ret = vgic_its_flush_pending_tables(kvm);
+	if (ret)
+		goto out;
+	ret = vgic_its_flush_device_tables(its);
+	if (ret)
+		goto out;
+
+	ret = vgic_its_flush_collection_table(its);
+
+out:
+	unlock_all_vcpus(kvm);
+	mutex_unlock(&kvm->lock);
+	return ret;
+}
+
+/**
+ * vgic_its_table_restore - Restore all tables from guest RAM to internal
+ * data structs
+ */
+static int vgic_its_table_restore(struct vgic_its *its)
+{
+	struct kvm *kvm = its->dev->kvm;
+	int ret;
+
+	mutex_lock(&kvm->lock);
+
+	if (its->user_revision < REV) {
+		mutex_unlock(&kvm->lock);
+		return -EINVAL;
+	}
+
+	if (!lock_all_vcpus(kvm)) {
+		mutex_unlock(&kvm->lock);
+		return -EBUSY;
+	}
+
+	ret = vgic_its_restore_collection_table(its);
+	if (ret)
+		goto out;
+
+	ret = vgic_its_restore_device_tables(its);
+	if (ret)
+		goto out;
+
+	ret = vgic_its_restore_pending_tables(kvm);
+
+out:
+	unlock_all_vcpus(kvm);
+	mutex_unlock(&kvm->lock);
+
+	if (ret)
+		return ret;
+
+	/*
+	 * On restore path, MSI injections can happen before the
+	 * first VCPU run so let's complete the GIC init here.
+	 */
+	return kvm_vgic_map_resources(its->dev->kvm);
+}
+
 static int vgic_its_has_attr(struct kvm_device *dev,
 			     struct kvm_device_attr *attr)
 {
@@ -1645,6 +1774,8 @@ static int vgic_its_has_attr(struct kvm_device *dev,
 		break;
 	case KVM_DEV_ARM_VGIC_GRP_ITS_REGS:
 		return vgic_its_has_attr_regs(dev, attr);
+	case KVM_DEV_ARM_VGIC_GRP_ITS_TABLES:
+		return 0;
 	}
 	return -ENXIO;
 }
@@ -1693,6 +1824,10 @@ static int vgic_its_set_attr(struct kvm_device *dev,
 
 		return vgic_its_attr_regs_access(dev, attr, &reg, true);
 	}
+	case KVM_DEV_ARM_VGIC_GRP_ITS_TABLES:
+		if (attr->attr)
+			return -EINVAL;
+		return vgic_its_table_restore(its);
 	}
 	return -ENXIO;
 }
@@ -1700,9 +1835,10 @@ static int vgic_its_set_attr(struct kvm_device *dev,
 static int vgic_its_get_attr(struct kvm_device *dev,
 			     struct kvm_device_attr *attr)
 {
+	struct vgic_its *its = dev->private;
+
 	switch (attr->group) {
 	case KVM_DEV_ARM_VGIC_GRP_ADDR: {
-		struct vgic_its *its = dev->private;
 		u64 addr = its->vgic_its_base;
 		u64 __user *uaddr = (u64 __user *)(long)attr->addr;
 		unsigned long type = (unsigned long)attr->attr;
@@ -1723,6 +1859,10 @@ static int vgic_its_get_attr(struct kvm_device *dev,
 		if (ret)
 			return ret;
 		return put_user(reg, uaddr);
+	case KVM_DEV_ARM_VGIC_GRP_ITS_TABLES:
+		if (attr->attr)
+			return -EINVAL;
+		return vgic_its_table_flush(its);
 	}
 	default:
 		return -ENXIO;
-- 
2.5.5

^ permalink raw reply related	[flat|nested] 144+ messages in thread

* [PATCH v4 13/22] KVM: arm64: ITS: KVM_DEV_ARM_VGIC_GRP_ITS_TABLES group
@ 2017-03-27  9:31   ` Eric Auger
  0 siblings, 0 replies; 144+ messages in thread
From: Eric Auger @ 2017-03-27  9:31 UTC (permalink / raw)
  To: linux-arm-kernel

Introduce a new group aiming at saving/restoring the ITS
tables to/from the guest memory.

We hold the vcpus lock during the save and restore to make
sure no vcpu is running.

At this stage the functionality is not yet implemented. Only
the skeleton is put in place.

The ABI revision supposed to have been set through IIDR user
write is checked before the table restoration. This guarantees
this vITS knows how to restore the saved tables.

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

---

v3 -> v4:
- pass kvm struct handle to vgic_its_flush/restore_pending_tables
- take the kvm lock and vcpu locks
- ABI revision check
- check attr->attr is null

v1 -> v2:
- remove useless kvm parameter
---
 arch/arm/include/uapi/asm/kvm.h   |   1 +
 arch/arm64/include/uapi/asm/kvm.h |   1 +
 virt/kvm/arm/vgic/vgic-its.c      | 142 +++++++++++++++++++++++++++++++++++++-
 3 files changed, 143 insertions(+), 1 deletion(-)

diff --git a/arch/arm/include/uapi/asm/kvm.h b/arch/arm/include/uapi/asm/kvm.h
index 4beb83b..7b165e9 100644
--- a/arch/arm/include/uapi/asm/kvm.h
+++ b/arch/arm/include/uapi/asm/kvm.h
@@ -193,6 +193,7 @@ struct kvm_arch_memory_slot {
 #define KVM_DEV_ARM_VGIC_GRP_CPU_SYSREGS 6
 #define KVM_DEV_ARM_VGIC_GRP_LEVEL_INFO  7
 #define KVM_DEV_ARM_VGIC_GRP_ITS_REGS	8
+#define KVM_DEV_ARM_VGIC_GRP_ITS_TABLES	9
 #define KVM_DEV_ARM_VGIC_LINE_LEVEL_INFO_SHIFT	10
 #define KVM_DEV_ARM_VGIC_LINE_LEVEL_INFO_MASK \
 			(0x3fffffULL << KVM_DEV_ARM_VGIC_LINE_LEVEL_INFO_SHIFT)
diff --git a/arch/arm64/include/uapi/asm/kvm.h b/arch/arm64/include/uapi/asm/kvm.h
index 7e8dd69..166df68 100644
--- a/arch/arm64/include/uapi/asm/kvm.h
+++ b/arch/arm64/include/uapi/asm/kvm.h
@@ -213,6 +213,7 @@ struct kvm_arch_memory_slot {
 #define KVM_DEV_ARM_VGIC_GRP_CPU_SYSREGS 6
 #define KVM_DEV_ARM_VGIC_GRP_LEVEL_INFO  7
 #define KVM_DEV_ARM_VGIC_GRP_ITS_REGS 8
+#define KVM_DEV_ARM_VGIC_GRP_ITS_TABLES 9
 #define KVM_DEV_ARM_VGIC_LINE_LEVEL_INFO_SHIFT	10
 #define KVM_DEV_ARM_VGIC_LINE_LEVEL_INFO_MASK \
 			(0x3fffffULL << KVM_DEV_ARM_VGIC_LINE_LEVEL_INFO_SHIFT)
diff --git a/virt/kvm/arm/vgic/vgic-its.c b/virt/kvm/arm/vgic/vgic-its.c
index b275aea..76dd562 100644
--- a/virt/kvm/arm/vgic/vgic-its.c
+++ b/virt/kvm/arm/vgic/vgic-its.c
@@ -1627,6 +1627,135 @@ int vgic_its_attr_regs_access(struct kvm_device *dev,
 	return ret;
 }
 
+/**
+ * vgic_its_flush_pending_tables - Flush the pending tables into guest RAM
+ */
+static int vgic_its_flush_pending_tables(struct kvm *kvm)
+{
+	return -ENXIO;
+}
+
+/**
+ * vgic_its_restore_pending_tables - Restore the pending tables from guest
+ * RAM to internal data structs
+ */
+static int vgic_its_restore_pending_tables(struct kvm *kvm)
+{
+	return -ENXIO;
+}
+
+/**
+ * vgic_its_flush_device_tables - flush the device table and all ITT
+ * into guest RAM
+ */
+static int vgic_its_flush_device_tables(struct vgic_its *its)
+{
+	return -ENXIO;
+}
+
+/**
+ * vgic_its_restore_device_tables - restore the device table and all ITT
+ * from guest RAM to internal data structs
+ */
+static int vgic_its_restore_device_tables(struct vgic_its *its)
+{
+	return -ENXIO;
+}
+
+/**
+ * vgic_its_flush_collection_table - flush the collection table into
+ * guest RAM
+ */
+static int vgic_its_flush_collection_table(struct vgic_its *its)
+{
+	return -ENXIO;
+}
+
+/**
+ * vgic_its_restore_collection_table - reads the collection table
+ * in guest memory and restores the ITS internal state. Requires the
+ * BASER registers to be restored before.
+ */
+static int vgic_its_restore_collection_table(struct vgic_its *its)
+{
+	return -ENXIO;
+}
+
+/**
+ * vgic_its_table_flush - Flush all the tables into guest RAM
+ */
+static int vgic_its_table_flush(struct vgic_its *its)
+{
+	struct kvm *kvm = its->dev->kvm;
+	int ret;
+
+	mutex_lock(&kvm->lock);
+
+	if (!lock_all_vcpus(kvm)) {
+		mutex_unlock(&kvm->lock);
+		return -EBUSY;
+	}
+
+	ret = vgic_its_flush_pending_tables(kvm);
+	if (ret)
+		goto out;
+	ret = vgic_its_flush_device_tables(its);
+	if (ret)
+		goto out;
+
+	ret = vgic_its_flush_collection_table(its);
+
+out:
+	unlock_all_vcpus(kvm);
+	mutex_unlock(&kvm->lock);
+	return ret;
+}
+
+/**
+ * vgic_its_table_restore - Restore all tables from guest RAM to internal
+ * data structs
+ */
+static int vgic_its_table_restore(struct vgic_its *its)
+{
+	struct kvm *kvm = its->dev->kvm;
+	int ret;
+
+	mutex_lock(&kvm->lock);
+
+	if (its->user_revision < REV) {
+		mutex_unlock(&kvm->lock);
+		return -EINVAL;
+	}
+
+	if (!lock_all_vcpus(kvm)) {
+		mutex_unlock(&kvm->lock);
+		return -EBUSY;
+	}
+
+	ret = vgic_its_restore_collection_table(its);
+	if (ret)
+		goto out;
+
+	ret = vgic_its_restore_device_tables(its);
+	if (ret)
+		goto out;
+
+	ret = vgic_its_restore_pending_tables(kvm);
+
+out:
+	unlock_all_vcpus(kvm);
+	mutex_unlock(&kvm->lock);
+
+	if (ret)
+		return ret;
+
+	/*
+	 * On restore path, MSI injections can happen before the
+	 * first VCPU run so let's complete the GIC init here.
+	 */
+	return kvm_vgic_map_resources(its->dev->kvm);
+}
+
 static int vgic_its_has_attr(struct kvm_device *dev,
 			     struct kvm_device_attr *attr)
 {
@@ -1645,6 +1774,8 @@ static int vgic_its_has_attr(struct kvm_device *dev,
 		break;
 	case KVM_DEV_ARM_VGIC_GRP_ITS_REGS:
 		return vgic_its_has_attr_regs(dev, attr);
+	case KVM_DEV_ARM_VGIC_GRP_ITS_TABLES:
+		return 0;
 	}
 	return -ENXIO;
 }
@@ -1693,6 +1824,10 @@ static int vgic_its_set_attr(struct kvm_device *dev,
 
 		return vgic_its_attr_regs_access(dev, attr, &reg, true);
 	}
+	case KVM_DEV_ARM_VGIC_GRP_ITS_TABLES:
+		if (attr->attr)
+			return -EINVAL;
+		return vgic_its_table_restore(its);
 	}
 	return -ENXIO;
 }
@@ -1700,9 +1835,10 @@ static int vgic_its_set_attr(struct kvm_device *dev,
 static int vgic_its_get_attr(struct kvm_device *dev,
 			     struct kvm_device_attr *attr)
 {
+	struct vgic_its *its = dev->private;
+
 	switch (attr->group) {
 	case KVM_DEV_ARM_VGIC_GRP_ADDR: {
-		struct vgic_its *its = dev->private;
 		u64 addr = its->vgic_its_base;
 		u64 __user *uaddr = (u64 __user *)(long)attr->addr;
 		unsigned long type = (unsigned long)attr->attr;
@@ -1723,6 +1859,10 @@ static int vgic_its_get_attr(struct kvm_device *dev,
 		if (ret)
 			return ret;
 		return put_user(reg, uaddr);
+	case KVM_DEV_ARM_VGIC_GRP_ITS_TABLES:
+		if (attr->attr)
+			return -EINVAL;
+		return vgic_its_table_flush(its);
 	}
 	default:
 		return -ENXIO;
-- 
2.5.5

^ permalink raw reply related	[flat|nested] 144+ messages in thread

* [PATCH v4 14/22] KVM: arm64: ITS: vgic_its_alloc_ite/device
  2017-03-27  9:30 ` Eric Auger
@ 2017-03-27  9:31   ` Eric Auger
  -1 siblings, 0 replies; 144+ messages in thread
From: Eric Auger @ 2017-03-27  9:31 UTC (permalink / raw)
  To: eric.auger.pro, eric.auger, marc.zyngier, christoffer.dall,
	andre.przywara, vijayak, Vijaya.Kumar, peter.maydell,
	linux-arm-kernel, kvmarm, kvm
  Cc: Prasun.Kapoor, quintela, dgilbert, pbonzini

Add two new helpers to allocate an its ite and an its device.
This will avoid duplication on restore path.

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

---

v3 -> v4:
- fix allocation
- add comment about its_lock mutex hold

v1 -> v2:
- report itt_size fix and remove ITE_SIZE
- s/itte/ite/g
---
 virt/kvm/arm/vgic/vgic-its.c | 73 ++++++++++++++++++++++++++++++--------------
 1 file changed, 50 insertions(+), 23 deletions(-)

diff --git a/virt/kvm/arm/vgic/vgic-its.c b/virt/kvm/arm/vgic/vgic-its.c
index 76dd562..2a1ccbf 100644
--- a/virt/kvm/arm/vgic/vgic-its.c
+++ b/virt/kvm/arm/vgic/vgic-its.c
@@ -726,6 +726,27 @@ static void vgic_its_free_collection(struct vgic_its *its, u32 coll_id)
 	kfree(collection);
 }
 
+/* Must be called with its_lock mutex held */
+static int vgic_its_alloc_ite(struct its_device *device,
+			       struct its_ite **itep,
+			       struct its_collection *collection,
+			       u32 lpi_id, u32 event_id)
+{
+	struct its_ite *ite;
+
+	ite = kzalloc(sizeof(*ite), GFP_KERNEL);
+	if (!ite)
+		return -ENOMEM;
+
+	ite->event_id	= event_id;
+	ite->collection = collection;
+	ite->lpi = lpi_id;
+
+	list_add_tail(&ite->ite_list, &device->itt_head);
+	*itep = ite;
+	return 0;
+}
+
 /*
  * The MAPTI and MAPI commands map LPIs to ITTEs.
  * Must be called with its_lock mutex held.
@@ -739,7 +760,7 @@ static int vgic_its_cmd_handle_mapi(struct kvm *kvm, struct vgic_its *its,
 	struct its_ite *ite;
 	struct its_device *device;
 	struct its_collection *collection, *new_coll = NULL;
-	int lpi_nr;
+	int lpi_nr, ret;
 	struct vgic_irq *irq;
 
 	device = find_its_device(its, device_id);
@@ -769,19 +790,13 @@ static int vgic_its_cmd_handle_mapi(struct kvm *kvm, struct vgic_its *its,
 		new_coll = collection;
 	}
 
-	ite = kzalloc(sizeof(struct its_ite), GFP_KERNEL);
-	if (!ite) {
+	ret = vgic_its_alloc_ite(device, &ite, collection, lpi_nr, event_id);
+	if (ret) {
 		if (new_coll)
 			vgic_its_free_collection(its, coll_id);
-		return -ENOMEM;
+		return ret;
 	}
 
-	ite->event_id	= event_id;
-	list_add_tail(&ite->ite_list, &device->itt_head);
-
-	ite->collection = collection;
-	ite->lpi = lpi_nr;
-
 	irq = vgic_add_lpi(kvm, lpi_nr);
 	if (IS_ERR(irq)) {
 		if (new_coll)
@@ -820,6 +835,29 @@ static void vgic_its_unmap_device(struct kvm *kvm, struct its_device *device)
 	kfree(device);
 }
 
+/* Must be called with its_lock mutex held */
+static int vgic_its_alloc_device(struct vgic_its *its,
+				 struct its_device **devp,
+				 u32 device_id, gpa_t itt_addr,
+				 u8 nb_eventid_bits)
+{
+	struct its_device *device;
+
+	device = kzalloc(sizeof(*device), GFP_KERNEL);
+	if (!device)
+		return -ENOMEM;
+
+	device->device_id = device_id;
+	device->itt_addr = itt_addr;
+	device->nb_eventid_bits = nb_eventid_bits;
+	INIT_LIST_HEAD(&device->itt_head);
+
+	list_add_tail(&device->dev_list, &its->device_list);
+	*devp = device;
+
+	return 0;
+}
+
 /*
  * MAPD maps or unmaps a device ID to Interrupt Translation Tables (ITTs).
  * Must be called with the its_lock mutex held.
@@ -856,19 +894,8 @@ static int vgic_its_cmd_handle_mapd(struct kvm *kvm, struct vgic_its *its,
 	if (!valid)
 		return 0;
 
-	device = kzalloc(sizeof(struct its_device), GFP_KERNEL);
-	if (!device)
-		return -ENOMEM;
-
-	device->device_id = device_id;
-	device->nb_eventid_bits = nb_eventid_bits;
-	device->itt_addr = itt_addr;
-
-	INIT_LIST_HEAD(&device->itt_head);
-
-	list_add_tail(&device->dev_list, &its->device_list);
-
-	return 0;
+	return vgic_its_alloc_device(its, &device, device_id,
+				     itt_addr, nb_eventid_bits);
 }
 
 /*
-- 
2.5.5

^ permalink raw reply related	[flat|nested] 144+ messages in thread

* [PATCH v4 14/22] KVM: arm64: ITS: vgic_its_alloc_ite/device
@ 2017-03-27  9:31   ` Eric Auger
  0 siblings, 0 replies; 144+ messages in thread
From: Eric Auger @ 2017-03-27  9:31 UTC (permalink / raw)
  To: linux-arm-kernel

Add two new helpers to allocate an its ite and an its device.
This will avoid duplication on restore path.

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

---

v3 -> v4:
- fix allocation
- add comment about its_lock mutex hold

v1 -> v2:
- report itt_size fix and remove ITE_SIZE
- s/itte/ite/g
---
 virt/kvm/arm/vgic/vgic-its.c | 73 ++++++++++++++++++++++++++++++--------------
 1 file changed, 50 insertions(+), 23 deletions(-)

diff --git a/virt/kvm/arm/vgic/vgic-its.c b/virt/kvm/arm/vgic/vgic-its.c
index 76dd562..2a1ccbf 100644
--- a/virt/kvm/arm/vgic/vgic-its.c
+++ b/virt/kvm/arm/vgic/vgic-its.c
@@ -726,6 +726,27 @@ static void vgic_its_free_collection(struct vgic_its *its, u32 coll_id)
 	kfree(collection);
 }
 
+/* Must be called with its_lock mutex held */
+static int vgic_its_alloc_ite(struct its_device *device,
+			       struct its_ite **itep,
+			       struct its_collection *collection,
+			       u32 lpi_id, u32 event_id)
+{
+	struct its_ite *ite;
+
+	ite = kzalloc(sizeof(*ite), GFP_KERNEL);
+	if (!ite)
+		return -ENOMEM;
+
+	ite->event_id	= event_id;
+	ite->collection = collection;
+	ite->lpi = lpi_id;
+
+	list_add_tail(&ite->ite_list, &device->itt_head);
+	*itep = ite;
+	return 0;
+}
+
 /*
  * The MAPTI and MAPI commands map LPIs to ITTEs.
  * Must be called with its_lock mutex held.
@@ -739,7 +760,7 @@ static int vgic_its_cmd_handle_mapi(struct kvm *kvm, struct vgic_its *its,
 	struct its_ite *ite;
 	struct its_device *device;
 	struct its_collection *collection, *new_coll = NULL;
-	int lpi_nr;
+	int lpi_nr, ret;
 	struct vgic_irq *irq;
 
 	device = find_its_device(its, device_id);
@@ -769,19 +790,13 @@ static int vgic_its_cmd_handle_mapi(struct kvm *kvm, struct vgic_its *its,
 		new_coll = collection;
 	}
 
-	ite = kzalloc(sizeof(struct its_ite), GFP_KERNEL);
-	if (!ite) {
+	ret = vgic_its_alloc_ite(device, &ite, collection, lpi_nr, event_id);
+	if (ret) {
 		if (new_coll)
 			vgic_its_free_collection(its, coll_id);
-		return -ENOMEM;
+		return ret;
 	}
 
-	ite->event_id	= event_id;
-	list_add_tail(&ite->ite_list, &device->itt_head);
-
-	ite->collection = collection;
-	ite->lpi = lpi_nr;
-
 	irq = vgic_add_lpi(kvm, lpi_nr);
 	if (IS_ERR(irq)) {
 		if (new_coll)
@@ -820,6 +835,29 @@ static void vgic_its_unmap_device(struct kvm *kvm, struct its_device *device)
 	kfree(device);
 }
 
+/* Must be called with its_lock mutex held */
+static int vgic_its_alloc_device(struct vgic_its *its,
+				 struct its_device **devp,
+				 u32 device_id, gpa_t itt_addr,
+				 u8 nb_eventid_bits)
+{
+	struct its_device *device;
+
+	device = kzalloc(sizeof(*device), GFP_KERNEL);
+	if (!device)
+		return -ENOMEM;
+
+	device->device_id = device_id;
+	device->itt_addr = itt_addr;
+	device->nb_eventid_bits = nb_eventid_bits;
+	INIT_LIST_HEAD(&device->itt_head);
+
+	list_add_tail(&device->dev_list, &its->device_list);
+	*devp = device;
+
+	return 0;
+}
+
 /*
  * MAPD maps or unmaps a device ID to Interrupt Translation Tables (ITTs).
  * Must be called with the its_lock mutex held.
@@ -856,19 +894,8 @@ static int vgic_its_cmd_handle_mapd(struct kvm *kvm, struct vgic_its *its,
 	if (!valid)
 		return 0;
 
-	device = kzalloc(sizeof(struct its_device), GFP_KERNEL);
-	if (!device)
-		return -ENOMEM;
-
-	device->device_id = device_id;
-	device->nb_eventid_bits = nb_eventid_bits;
-	device->itt_addr = itt_addr;
-
-	INIT_LIST_HEAD(&device->itt_head);
-
-	list_add_tail(&device->dev_list, &its->device_list);
-
-	return 0;
+	return vgic_its_alloc_device(its, &device, device_id,
+				     itt_addr, nb_eventid_bits);
 }
 
 /*
-- 
2.5.5

^ permalink raw reply related	[flat|nested] 144+ messages in thread

* [PATCH v4 15/22] KVM: arm64: ITS: Sort the device and ITE lists
  2017-03-27  9:30 ` Eric Auger
@ 2017-03-27  9:31   ` Eric Auger
  -1 siblings, 0 replies; 144+ messages in thread
From: Eric Auger @ 2017-03-27  9:31 UTC (permalink / raw)
  To: eric.auger.pro, eric.auger, marc.zyngier, christoffer.dall,
	andre.przywara, vijayak, Vijaya.Kumar, peter.maydell,
	linux-arm-kernel, kvmarm, kvm
  Cc: Prasun.Kapoor, quintela, dgilbert, pbonzini

Natively sort the device and ITE lists in ascending
deviceId/eventid order. This paves the way to optimized
DTE and ITE scan in guest RAM table where entries are chained
together using a next ID offset.

Signed-off-by: Eric Auger <eric.auger@redhat.com>
Reviewed-by: Andre Przywara <andre.przywara@arm.com>

---

v3 -> v4:
- added Andre's R-b
---
 virt/kvm/arm/vgic/vgic-its.c | 36 ++++++++++++++++++++++++++++++++++--
 1 file changed, 34 insertions(+), 2 deletions(-)

diff --git a/virt/kvm/arm/vgic/vgic-its.c b/virt/kvm/arm/vgic/vgic-its.c
index 2a1ccbf..7364b7d 100644
--- a/virt/kvm/arm/vgic/vgic-its.c
+++ b/virt/kvm/arm/vgic/vgic-its.c
@@ -726,6 +726,21 @@ static void vgic_its_free_collection(struct vgic_its *its, u32 coll_id)
 	kfree(collection);
 }
 
+static void ite_list_insert_sorted(struct list_head *h, struct its_ite *ite)
+{
+	struct list_head *pos = h->next;
+	u32 id = ite->event_id;
+
+	while (pos != h) {
+		struct its_ite *iter =
+			list_entry(pos, struct its_ite, ite_list);
+		if (id < iter->event_id)
+			break;
+		pos = pos->next;
+	}
+	list_add_tail(&ite->ite_list, pos);
+}
+
 /* Must be called with its_lock mutex held */
 static int vgic_its_alloc_ite(struct its_device *device,
 			       struct its_ite **itep,
@@ -742,7 +757,7 @@ static int vgic_its_alloc_ite(struct its_device *device,
 	ite->collection = collection;
 	ite->lpi = lpi_id;
 
-	list_add_tail(&ite->ite_list, &device->itt_head);
+	ite_list_insert_sorted(&device->itt_head, ite);
 	*itep = ite;
 	return 0;
 }
@@ -835,6 +850,22 @@ static void vgic_its_unmap_device(struct kvm *kvm, struct its_device *device)
 	kfree(device);
 }
 
+static void device_list_insert_sorted(struct list_head *h,
+				      struct its_device *dev)
+{
+	struct list_head *pos = h->next;
+	u32 id = dev->device_id;
+
+	while (pos != h) {
+		struct its_device *iter =
+			list_entry(pos, struct its_device, dev_list);
+		if (id < iter->device_id)
+			break;
+		pos = pos->next;
+	}
+	list_add_tail(&dev->dev_list, pos);
+}
+
 /* Must be called with its_lock mutex held */
 static int vgic_its_alloc_device(struct vgic_its *its,
 				 struct its_device **devp,
@@ -852,7 +883,8 @@ static int vgic_its_alloc_device(struct vgic_its *its,
 	device->nb_eventid_bits = nb_eventid_bits;
 	INIT_LIST_HEAD(&device->itt_head);
 
-	list_add_tail(&device->dev_list, &its->device_list);
+	device_list_insert_sorted(&its->device_list, device);
+
 	*devp = device;
 
 	return 0;
-- 
2.5.5

^ permalink raw reply related	[flat|nested] 144+ messages in thread

* [PATCH v4 15/22] KVM: arm64: ITS: Sort the device and ITE lists
@ 2017-03-27  9:31   ` Eric Auger
  0 siblings, 0 replies; 144+ messages in thread
From: Eric Auger @ 2017-03-27  9:31 UTC (permalink / raw)
  To: linux-arm-kernel

Natively sort the device and ITE lists in ascending
deviceId/eventid order. This paves the way to optimized
DTE and ITE scan in guest RAM table where entries are chained
together using a next ID offset.

Signed-off-by: Eric Auger <eric.auger@redhat.com>
Reviewed-by: Andre Przywara <andre.przywara@arm.com>

---

v3 -> v4:
- added Andre's R-b
---
 virt/kvm/arm/vgic/vgic-its.c | 36 ++++++++++++++++++++++++++++++++++--
 1 file changed, 34 insertions(+), 2 deletions(-)

diff --git a/virt/kvm/arm/vgic/vgic-its.c b/virt/kvm/arm/vgic/vgic-its.c
index 2a1ccbf..7364b7d 100644
--- a/virt/kvm/arm/vgic/vgic-its.c
+++ b/virt/kvm/arm/vgic/vgic-its.c
@@ -726,6 +726,21 @@ static void vgic_its_free_collection(struct vgic_its *its, u32 coll_id)
 	kfree(collection);
 }
 
+static void ite_list_insert_sorted(struct list_head *h, struct its_ite *ite)
+{
+	struct list_head *pos = h->next;
+	u32 id = ite->event_id;
+
+	while (pos != h) {
+		struct its_ite *iter =
+			list_entry(pos, struct its_ite, ite_list);
+		if (id < iter->event_id)
+			break;
+		pos = pos->next;
+	}
+	list_add_tail(&ite->ite_list, pos);
+}
+
 /* Must be called with its_lock mutex held */
 static int vgic_its_alloc_ite(struct its_device *device,
 			       struct its_ite **itep,
@@ -742,7 +757,7 @@ static int vgic_its_alloc_ite(struct its_device *device,
 	ite->collection = collection;
 	ite->lpi = lpi_id;
 
-	list_add_tail(&ite->ite_list, &device->itt_head);
+	ite_list_insert_sorted(&device->itt_head, ite);
 	*itep = ite;
 	return 0;
 }
@@ -835,6 +850,22 @@ static void vgic_its_unmap_device(struct kvm *kvm, struct its_device *device)
 	kfree(device);
 }
 
+static void device_list_insert_sorted(struct list_head *h,
+				      struct its_device *dev)
+{
+	struct list_head *pos = h->next;
+	u32 id = dev->device_id;
+
+	while (pos != h) {
+		struct its_device *iter =
+			list_entry(pos, struct its_device, dev_list);
+		if (id < iter->device_id)
+			break;
+		pos = pos->next;
+	}
+	list_add_tail(&dev->dev_list, pos);
+}
+
 /* Must be called with its_lock mutex held */
 static int vgic_its_alloc_device(struct vgic_its *its,
 				 struct its_device **devp,
@@ -852,7 +883,8 @@ static int vgic_its_alloc_device(struct vgic_its *its,
 	device->nb_eventid_bits = nb_eventid_bits;
 	INIT_LIST_HEAD(&device->itt_head);
 
-	list_add_tail(&device->dev_list, &its->device_list);
+	device_list_insert_sorted(&its->device_list, device);
+
 	*devp = device;
 
 	return 0;
-- 
2.5.5

^ permalink raw reply related	[flat|nested] 144+ messages in thread

* [PATCH v4 16/22] KVM: expose next_segment()
  2017-03-27  9:30 ` Eric Auger
@ 2017-03-27  9:31   ` Eric Auger
  -1 siblings, 0 replies; 144+ messages in thread
From: Eric Auger @ 2017-03-27  9:31 UTC (permalink / raw)
  To: eric.auger.pro, eric.auger, marc.zyngier, christoffer.dall,
	andre.przywara, vijayak, Vijaya.Kumar, peter.maydell,
	linux-arm-kernel, kvmarm, kvm
  Cc: Prasun.Kapoor, quintela, dgilbert, pbonzini

Expose next_segment() as we would like to reuse this routine in
ARM vgic-its code.

Signed-off-by: Eric Auger <eric.auger@redhat.com>
---
 include/linux/kvm_host.h | 8 ++++++++
 virt/kvm/kvm_main.c      | 8 --------
 2 files changed, 8 insertions(+), 8 deletions(-)

diff --git a/include/linux/kvm_host.h b/include/linux/kvm_host.h
index 2c14ad9..b4b5d82 100644
--- a/include/linux/kvm_host.h
+++ b/include/linux/kvm_host.h
@@ -92,6 +92,14 @@ static inline bool is_noslot_pfn(kvm_pfn_t pfn)
 	return pfn == KVM_PFN_NOSLOT;
 }
 
+static inline int next_segment(unsigned long len, int offset)
+{
+	if (len > PAGE_SIZE - offset)
+		return PAGE_SIZE - offset;
+	else
+		return len;
+}
+
 /*
  * architectures with KVM_HVA_ERR_BAD other than PAGE_OFFSET (e.g. s390)
  * provide own defines and kvm_is_error_hva
diff --git a/virt/kvm/kvm_main.c b/virt/kvm/kvm_main.c
index a17d787..b825e86 100644
--- a/virt/kvm/kvm_main.c
+++ b/virt/kvm/kvm_main.c
@@ -1738,14 +1738,6 @@ void kvm_get_pfn(kvm_pfn_t pfn)
 }
 EXPORT_SYMBOL_GPL(kvm_get_pfn);
 
-static int next_segment(unsigned long len, int offset)
-{
-	if (len > PAGE_SIZE - offset)
-		return PAGE_SIZE - offset;
-	else
-		return len;
-}
-
 static int __kvm_read_guest_page(struct kvm_memory_slot *slot, gfn_t gfn,
 				 void *data, int offset, int len)
 {
-- 
2.5.5

^ permalink raw reply related	[flat|nested] 144+ messages in thread

* [PATCH v4 16/22] KVM: expose next_segment()
@ 2017-03-27  9:31   ` Eric Auger
  0 siblings, 0 replies; 144+ messages in thread
From: Eric Auger @ 2017-03-27  9:31 UTC (permalink / raw)
  To: linux-arm-kernel

Expose next_segment() as we would like to reuse this routine in
ARM vgic-its code.

Signed-off-by: Eric Auger <eric.auger@redhat.com>
---
 include/linux/kvm_host.h | 8 ++++++++
 virt/kvm/kvm_main.c      | 8 --------
 2 files changed, 8 insertions(+), 8 deletions(-)

diff --git a/include/linux/kvm_host.h b/include/linux/kvm_host.h
index 2c14ad9..b4b5d82 100644
--- a/include/linux/kvm_host.h
+++ b/include/linux/kvm_host.h
@@ -92,6 +92,14 @@ static inline bool is_noslot_pfn(kvm_pfn_t pfn)
 	return pfn == KVM_PFN_NOSLOT;
 }
 
+static inline int next_segment(unsigned long len, int offset)
+{
+	if (len > PAGE_SIZE - offset)
+		return PAGE_SIZE - offset;
+	else
+		return len;
+}
+
 /*
  * architectures with KVM_HVA_ERR_BAD other than PAGE_OFFSET (e.g. s390)
  * provide own defines and kvm_is_error_hva
diff --git a/virt/kvm/kvm_main.c b/virt/kvm/kvm_main.c
index a17d787..b825e86 100644
--- a/virt/kvm/kvm_main.c
+++ b/virt/kvm/kvm_main.c
@@ -1738,14 +1738,6 @@ void kvm_get_pfn(kvm_pfn_t pfn)
 }
 EXPORT_SYMBOL_GPL(kvm_get_pfn);
 
-static int next_segment(unsigned long len, int offset)
-{
-	if (len > PAGE_SIZE - offset)
-		return PAGE_SIZE - offset;
-	else
-		return len;
-}
-
 static int __kvm_read_guest_page(struct kvm_memory_slot *slot, gfn_t gfn,
 				 void *data, int offset, int len)
 {
-- 
2.5.5

^ permalink raw reply related	[flat|nested] 144+ messages in thread

* [PATCH v4 17/22] KVM: arm64: ITS: Add infrastructure for table lookup
  2017-03-27  9:30 ` Eric Auger
@ 2017-03-27  9:31   ` Eric Auger
  -1 siblings, 0 replies; 144+ messages in thread
From: Eric Auger @ 2017-03-27  9:31 UTC (permalink / raw)
  To: eric.auger.pro, eric.auger, marc.zyngier, christoffer.dall,
	andre.przywara, vijayak, Vijaya.Kumar, peter.maydell,
	linux-arm-kernel, kvmarm, kvm
  Cc: Prasun.Kapoor, quintela, dgilbert, pbonzini

Add a generic lookup_table() helper whose role consists in
scanning a contiguous table located in guest RAM and applying
a callback on each entry. Entries can be handled as linked lists
since the callback may return an offset to the next entry and
also tell that an entry is the last one.

Helper functions also are added to compute the device/event ID
offset to the next DTE/ITE.

compute_next_devid_offset, compute_next_eventid_offset and
lookup_table will become static in subsequent patches

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

---

v3 -> v4:
- remove static to avoid compilation warning
- correct size computation in looup_table()
- defines now encode the number of bits used for devid and eventid offsets
- use BIT() - 1 to encode the max offets
---
 virt/kvm/arm/vgic/vgic-its.c | 107 +++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 107 insertions(+)

diff --git a/virt/kvm/arm/vgic/vgic-its.c b/virt/kvm/arm/vgic/vgic-its.c
index 7364b7d..8eaeba4 100644
--- a/virt/kvm/arm/vgic/vgic-its.c
+++ b/virt/kvm/arm/vgic/vgic-its.c
@@ -184,6 +184,8 @@ static struct its_ite *find_ite(struct vgic_its *its, u32 device_id,
 #define VITS_ESZ 8
 #define VITS_TYPER_IDBITS 16
 #define VITS_TYPER_DEVBITS 16
+#define VITS_DTE_MAX_DEVID_OFFSET	(BIT(14) - 1)
+#define VITS_ITE_MAX_EVENTID_OFFSET	(BIT(16) - 1)
 
 /*
  * Finds and returns a collection in the ITS collection table.
@@ -1686,6 +1688,111 @@ 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)
+{
+	struct list_head *e = &dev->dev_list;
+	struct its_device *next;
+	u32 next_offset;
+
+	if (e->next == h)
+		return 0;
+	next = list_entry(e->next, struct its_device, dev_list);
+	next_offset = next->device_id - dev->device_id;
+
+	return min_t(u32, next_offset, VITS_DTE_MAX_DEVID_OFFSET);
+}
+
+u32 compute_next_eventid_offset(struct list_head *h, struct its_ite *ite)
+{
+	struct list_head *e = &ite->ite_list;
+	struct its_ite *next;
+	u32 next_offset;
+
+	if (e->next == h)
+		return 0;
+	next = list_entry(e->next, struct its_ite, ite_list);
+	next_offset = next->event_id - ite->event_id;
+
+	return min_t(u32, next_offset, VITS_ITE_MAX_EVENTID_OFFSET);
+}
+
+/**
+ * entry_fn_t - Callback called on a table entry restore path
+ * @its: its handle
+ * @id: id of the entry
+ * @addr: kernel VA of the entry
+ * @opaque: pointer to an opaque data
+ * @next_offset: minimal ID offset to the next entry. 0 if this
+ * entry is the last one, 1 if the entry is invalid, >= 1 if an
+ * entry's next_offset field was truly decoded
+ *
+ * Return: < 0 on error, 0 otherwise
+ */
+typedef int (*entry_fn_t)(struct vgic_its *its, u32 id, void *addr,
+			  void *opaque, u32 *next_offset);
+
+/**
+ * lookup_table - scans a contiguous table in guest RAM and applies a function
+ * to each entry
+ *
+ * @its: its handle
+ * @base: base gpa of the table
+ * @size: size of the table in bytes
+ * @esz: entry size in bytes
+ * @start_id: first entry's ID
+ * @fn: function to apply on each entry
+ *
+ * Return: < 0 on error, 1 if last element identified, 0 otherwise
+ */
+int lookup_table(struct vgic_its *its, gpa_t base, int size, int esz,
+		 int start_id, entry_fn_t fn, void *opaque)
+{
+	gpa_t gpa = base, top = base + size - 1;
+	unsigned long len = size;
+	int ret, seg, offset = offset_in_page(gpa);
+	gfn_t gfn = gpa >> PAGE_SHIFT;
+	u32 id = start_id + (gpa - base)/esz;
+	struct kvm *kvm = its->dev->kvm;
+	kvm_pfn_t pfn;
+
+	while ((seg = next_segment(len, offset)) != 0) {
+		u32 next_offset;
+		bool writeable;
+		void *addr;
+
+		pfn = gfn_to_pfn_prot(kvm, gfn, true, &writeable);
+		if (is_error_noslot_pfn(pfn))
+			return -EINVAL;
+		addr = phys_to_virt((u64)pfn << PAGE_SHIFT);
+		addr += offset;
+
+		while (seg > 0) {
+			size_t byte_offset;
+
+			ret = fn(its, id, addr, opaque, &next_offset);
+			if (ret < 0 || (!ret && !next_offset))
+				goto out;
+
+			byte_offset = next_offset * esz;
+
+			id += next_offset;
+			gpa += byte_offset;
+			addr += byte_offset;
+			seg -= byte_offset;
+		}
+		kvm_release_pfn_clean(pfn);
+
+		len = top - gpa + 1;
+		offset = offset_in_page(gpa);
+		gfn = gpa >> PAGE_SHIFT;
+		id = start_id + (gpa - base)/esz;
+	}
+	return 0;
+out:
+	kvm_release_pfn_clean(pfn);
+	return (ret < 0 ? ret : 1);
+}
+
 /**
  * vgic_its_flush_pending_tables - Flush the pending tables into guest RAM
  */
-- 
2.5.5

^ permalink raw reply related	[flat|nested] 144+ messages in thread

* [PATCH v4 17/22] KVM: arm64: ITS: Add infrastructure for table lookup
@ 2017-03-27  9:31   ` Eric Auger
  0 siblings, 0 replies; 144+ messages in thread
From: Eric Auger @ 2017-03-27  9:31 UTC (permalink / raw)
  To: linux-arm-kernel

Add a generic lookup_table() helper whose role consists in
scanning a contiguous table located in guest RAM and applying
a callback on each entry. Entries can be handled as linked lists
since the callback may return an offset to the next entry and
also tell that an entry is the last one.

Helper functions also are added to compute the device/event ID
offset to the next DTE/ITE.

compute_next_devid_offset, compute_next_eventid_offset and
lookup_table will become static in subsequent patches

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

---

v3 -> v4:
- remove static to avoid compilation warning
- correct size computation in looup_table()
- defines now encode the number of bits used for devid and eventid offsets
- use BIT() - 1 to encode the max offets
---
 virt/kvm/arm/vgic/vgic-its.c | 107 +++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 107 insertions(+)

diff --git a/virt/kvm/arm/vgic/vgic-its.c b/virt/kvm/arm/vgic/vgic-its.c
index 7364b7d..8eaeba4 100644
--- a/virt/kvm/arm/vgic/vgic-its.c
+++ b/virt/kvm/arm/vgic/vgic-its.c
@@ -184,6 +184,8 @@ static struct its_ite *find_ite(struct vgic_its *its, u32 device_id,
 #define VITS_ESZ 8
 #define VITS_TYPER_IDBITS 16
 #define VITS_TYPER_DEVBITS 16
+#define VITS_DTE_MAX_DEVID_OFFSET	(BIT(14) - 1)
+#define VITS_ITE_MAX_EVENTID_OFFSET	(BIT(16) - 1)
 
 /*
  * Finds and returns a collection in the ITS collection table.
@@ -1686,6 +1688,111 @@ 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)
+{
+	struct list_head *e = &dev->dev_list;
+	struct its_device *next;
+	u32 next_offset;
+
+	if (e->next == h)
+		return 0;
+	next = list_entry(e->next, struct its_device, dev_list);
+	next_offset = next->device_id - dev->device_id;
+
+	return min_t(u32, next_offset, VITS_DTE_MAX_DEVID_OFFSET);
+}
+
+u32 compute_next_eventid_offset(struct list_head *h, struct its_ite *ite)
+{
+	struct list_head *e = &ite->ite_list;
+	struct its_ite *next;
+	u32 next_offset;
+
+	if (e->next == h)
+		return 0;
+	next = list_entry(e->next, struct its_ite, ite_list);
+	next_offset = next->event_id - ite->event_id;
+
+	return min_t(u32, next_offset, VITS_ITE_MAX_EVENTID_OFFSET);
+}
+
+/**
+ * entry_fn_t - Callback called on a table entry restore path
+ * @its: its handle
+ * @id: id of the entry
+ * @addr: kernel VA of the entry
+ * @opaque: pointer to an opaque data
+ * @next_offset: minimal ID offset to the next entry. 0 if this
+ * entry is the last one, 1 if the entry is invalid, >= 1 if an
+ * entry's next_offset field was truly decoded
+ *
+ * Return: < 0 on error, 0 otherwise
+ */
+typedef int (*entry_fn_t)(struct vgic_its *its, u32 id, void *addr,
+			  void *opaque, u32 *next_offset);
+
+/**
+ * lookup_table - scans a contiguous table in guest RAM and applies a function
+ * to each entry
+ *
+ * @its: its handle
+ * @base: base gpa of the table
+ * @size: size of the table in bytes
+ * @esz: entry size in bytes
+ * @start_id: first entry's ID
+ * @fn: function to apply on each entry
+ *
+ * Return: < 0 on error, 1 if last element identified, 0 otherwise
+ */
+int lookup_table(struct vgic_its *its, gpa_t base, int size, int esz,
+		 int start_id, entry_fn_t fn, void *opaque)
+{
+	gpa_t gpa = base, top = base + size - 1;
+	unsigned long len = size;
+	int ret, seg, offset = offset_in_page(gpa);
+	gfn_t gfn = gpa >> PAGE_SHIFT;
+	u32 id = start_id + (gpa - base)/esz;
+	struct kvm *kvm = its->dev->kvm;
+	kvm_pfn_t pfn;
+
+	while ((seg = next_segment(len, offset)) != 0) {
+		u32 next_offset;
+		bool writeable;
+		void *addr;
+
+		pfn = gfn_to_pfn_prot(kvm, gfn, true, &writeable);
+		if (is_error_noslot_pfn(pfn))
+			return -EINVAL;
+		addr = phys_to_virt((u64)pfn << PAGE_SHIFT);
+		addr += offset;
+
+		while (seg > 0) {
+			size_t byte_offset;
+
+			ret = fn(its, id, addr, opaque, &next_offset);
+			if (ret < 0 || (!ret && !next_offset))
+				goto out;
+
+			byte_offset = next_offset * esz;
+
+			id += next_offset;
+			gpa += byte_offset;
+			addr += byte_offset;
+			seg -= byte_offset;
+		}
+		kvm_release_pfn_clean(pfn);
+
+		len = top - gpa + 1;
+		offset = offset_in_page(gpa);
+		gfn = gpa >> PAGE_SHIFT;
+		id = start_id + (gpa - base)/esz;
+	}
+	return 0;
+out:
+	kvm_release_pfn_clean(pfn);
+	return (ret < 0 ? ret : 1);
+}
+
 /**
  * vgic_its_flush_pending_tables - Flush the pending tables into guest RAM
  */
-- 
2.5.5

^ permalink raw reply related	[flat|nested] 144+ messages in thread

* [PATCH v4 18/22] KVM: arm64: ITS: Collection table save/restore
  2017-03-27  9:30 ` Eric Auger
@ 2017-03-27  9:31   ` Eric Auger
  -1 siblings, 0 replies; 144+ messages in thread
From: Eric Auger @ 2017-03-27  9:31 UTC (permalink / raw)
  To: eric.auger.pro, eric.auger, marc.zyngier, christoffer.dall,
	andre.przywara, vijayak, Vijaya.Kumar, peter.maydell,
	linux-arm-kernel, kvmarm, kvm
  Cc: Prasun.Kapoor, quintela, dgilbert, pbonzini

The flush path copies the collection entries into guest RAM
at the GPA specified in the BASER register. This obviously
requires the BASER to be set. The last written element
is a dummy collection table entry.

We do not index by collection ID as the collection entry
can fit into 8 bytes while containing the collection ID.

On restore path we re-allocate the collection objects.

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

---

v3 -> v4:
- replaced u64 *ptr by gpa_t gpa
- check the collection does not exist before allocating it

v1 -> v2:
- reword commit message and directly use 8 as entry size
- no kvm parameter anymore
- add helper for flush/restore cte
- table size computed here
- add le64/cpu conversions
---
 virt/kvm/arm/vgic/vgic-its.c | 99 +++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 97 insertions(+), 2 deletions(-)

diff --git a/virt/kvm/arm/vgic/vgic-its.c b/virt/kvm/arm/vgic/vgic-its.c
index 8eaeba4..df984b6 100644
--- a/virt/kvm/arm/vgic/vgic-its.c
+++ b/virt/kvm/arm/vgic/vgic-its.c
@@ -1828,13 +1828,89 @@ static int vgic_its_restore_device_tables(struct vgic_its *its)
 	return -ENXIO;
 }
 
+static int vgic_its_flush_cte(struct vgic_its *its,
+			      struct its_collection *collection, gpa_t gpa)
+{
+	u64 val;
+	int ret;
+
+	val = ((u64)1 << 63 | ((u64)collection->target_addr << 16) |
+	       collection->collection_id);
+	val = cpu_to_le64(val);
+	ret = kvm_write_guest(its->dev->kvm, gpa, &val, 8);
+	return ret;
+}
+
+static int vgic_its_restore_cte(struct vgic_its *its, gpa_t gpa, bool *valid)
+{
+	struct its_collection *collection;
+	u32 target_addr;
+	u32 coll_id;
+	u64 val;
+	int ret;
+
+	*valid = false;
+
+	ret = kvm_read_guest(its->dev->kvm, gpa, &val, 8);
+	if (ret)
+		return ret;
+	val = le64_to_cpu(val);
+	*valid = val & BIT_ULL(63);
+
+	if (!*valid)
+		return 0;
+
+	target_addr = (u32)(val >> 16);
+	coll_id = val & 0xFFFF;
+
+	collection = find_collection(its, coll_id);
+	if (collection)
+		return -EEXIST;
+	ret = vgic_its_alloc_collection(its, &collection, coll_id);
+	if (ret)
+		return ret;
+	collection->target_addr = target_addr;
+	return 0;
+}
+
 /**
  * vgic_its_flush_collection_table - flush the collection table into
  * guest RAM
  */
 static int vgic_its_flush_collection_table(struct vgic_its *its)
 {
-	return -ENXIO;
+	struct its_collection *collection;
+	u64 val;
+	gpa_t gpa;
+	size_t max_size, filled = 0;
+	int ret;
+
+	gpa = BASER_ADDRESS(its->baser_coll_table);
+	if (!gpa)
+		return 0;
+
+	max_size = GITS_BASER_NR_PAGES(its->baser_coll_table) * SZ_64K;
+
+	list_for_each_entry(collection, &its->collection_list, coll_list) {
+		if (filled == max_size)
+			return -ENOSPC;
+		ret = vgic_its_flush_cte(its, collection, gpa);
+		if (ret)
+			return ret;
+		gpa += 8;
+		filled += 8;
+	}
+
+	if (filled == max_size)
+		return 0;
+
+	/*
+	 * table is not fully filled, add a last dummy element
+	 * with valid bit unset
+	 */
+	val = 0;
+	ret = kvm_write_guest(its->dev->kvm, gpa, &val, 8);
+	return ret;
 }
 
 /**
@@ -1844,7 +1920,26 @@ static int vgic_its_flush_collection_table(struct vgic_its *its)
  */
 static int vgic_its_restore_collection_table(struct vgic_its *its)
 {
-	return -ENXIO;
+	size_t max_size, read = 0;
+	gpa_t gpa;
+	int ret;
+
+	gpa = BASER_ADDRESS(its->baser_coll_table);
+	if (!gpa)
+		return 0;
+
+	max_size = GITS_BASER_NR_PAGES(its->baser_coll_table) * SZ_64K;
+
+	while (read < max_size) {
+		bool valid;
+
+		ret = vgic_its_restore_cte(its, gpa, &valid);
+		if (!valid || ret)
+			break;
+		gpa += 8;
+		read += 8;
+	}
+	return ret;
 }
 
 /**
-- 
2.5.5

^ permalink raw reply related	[flat|nested] 144+ messages in thread

* [PATCH v4 18/22] KVM: arm64: ITS: Collection table save/restore
@ 2017-03-27  9:31   ` Eric Auger
  0 siblings, 0 replies; 144+ messages in thread
From: Eric Auger @ 2017-03-27  9:31 UTC (permalink / raw)
  To: linux-arm-kernel

The flush path copies the collection entries into guest RAM
at the GPA specified in the BASER register. This obviously
requires the BASER to be set. The last written element
is a dummy collection table entry.

We do not index by collection ID as the collection entry
can fit into 8 bytes while containing the collection ID.

On restore path we re-allocate the collection objects.

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

---

v3 -> v4:
- replaced u64 *ptr by gpa_t gpa
- check the collection does not exist before allocating it

v1 -> v2:
- reword commit message and directly use 8 as entry size
- no kvm parameter anymore
- add helper for flush/restore cte
- table size computed here
- add le64/cpu conversions
---
 virt/kvm/arm/vgic/vgic-its.c | 99 +++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 97 insertions(+), 2 deletions(-)

diff --git a/virt/kvm/arm/vgic/vgic-its.c b/virt/kvm/arm/vgic/vgic-its.c
index 8eaeba4..df984b6 100644
--- a/virt/kvm/arm/vgic/vgic-its.c
+++ b/virt/kvm/arm/vgic/vgic-its.c
@@ -1828,13 +1828,89 @@ static int vgic_its_restore_device_tables(struct vgic_its *its)
 	return -ENXIO;
 }
 
+static int vgic_its_flush_cte(struct vgic_its *its,
+			      struct its_collection *collection, gpa_t gpa)
+{
+	u64 val;
+	int ret;
+
+	val = ((u64)1 << 63 | ((u64)collection->target_addr << 16) |
+	       collection->collection_id);
+	val = cpu_to_le64(val);
+	ret = kvm_write_guest(its->dev->kvm, gpa, &val, 8);
+	return ret;
+}
+
+static int vgic_its_restore_cte(struct vgic_its *its, gpa_t gpa, bool *valid)
+{
+	struct its_collection *collection;
+	u32 target_addr;
+	u32 coll_id;
+	u64 val;
+	int ret;
+
+	*valid = false;
+
+	ret = kvm_read_guest(its->dev->kvm, gpa, &val, 8);
+	if (ret)
+		return ret;
+	val = le64_to_cpu(val);
+	*valid = val & BIT_ULL(63);
+
+	if (!*valid)
+		return 0;
+
+	target_addr = (u32)(val >> 16);
+	coll_id = val & 0xFFFF;
+
+	collection = find_collection(its, coll_id);
+	if (collection)
+		return -EEXIST;
+	ret = vgic_its_alloc_collection(its, &collection, coll_id);
+	if (ret)
+		return ret;
+	collection->target_addr = target_addr;
+	return 0;
+}
+
 /**
  * vgic_its_flush_collection_table - flush the collection table into
  * guest RAM
  */
 static int vgic_its_flush_collection_table(struct vgic_its *its)
 {
-	return -ENXIO;
+	struct its_collection *collection;
+	u64 val;
+	gpa_t gpa;
+	size_t max_size, filled = 0;
+	int ret;
+
+	gpa = BASER_ADDRESS(its->baser_coll_table);
+	if (!gpa)
+		return 0;
+
+	max_size = GITS_BASER_NR_PAGES(its->baser_coll_table) * SZ_64K;
+
+	list_for_each_entry(collection, &its->collection_list, coll_list) {
+		if (filled == max_size)
+			return -ENOSPC;
+		ret = vgic_its_flush_cte(its, collection, gpa);
+		if (ret)
+			return ret;
+		gpa += 8;
+		filled += 8;
+	}
+
+	if (filled == max_size)
+		return 0;
+
+	/*
+	 * table is not fully filled, add a last dummy element
+	 * with valid bit unset
+	 */
+	val = 0;
+	ret = kvm_write_guest(its->dev->kvm, gpa, &val, 8);
+	return ret;
 }
 
 /**
@@ -1844,7 +1920,26 @@ static int vgic_its_flush_collection_table(struct vgic_its *its)
  */
 static int vgic_its_restore_collection_table(struct vgic_its *its)
 {
-	return -ENXIO;
+	size_t max_size, read = 0;
+	gpa_t gpa;
+	int ret;
+
+	gpa = BASER_ADDRESS(its->baser_coll_table);
+	if (!gpa)
+		return 0;
+
+	max_size = GITS_BASER_NR_PAGES(its->baser_coll_table) * SZ_64K;
+
+	while (read < max_size) {
+		bool valid;
+
+		ret = vgic_its_restore_cte(its, gpa, &valid);
+		if (!valid || ret)
+			break;
+		gpa += 8;
+		read += 8;
+	}
+	return ret;
 }
 
 /**
-- 
2.5.5

^ permalink raw reply related	[flat|nested] 144+ messages in thread

* [PATCH v4 19/22] KVM: arm64: ITS: vgic_its_check_id returns the entry's GPA
  2017-03-27  9:30 ` Eric Auger
@ 2017-03-27  9:31   ` Eric Auger
  -1 siblings, 0 replies; 144+ messages in thread
From: Eric Auger @ 2017-03-27  9:31 UTC (permalink / raw)
  To: eric.auger.pro, eric.auger, marc.zyngier, christoffer.dall,
	andre.przywara, vijayak, Vijaya.Kumar, peter.maydell,
	linux-arm-kernel, kvmarm, kvm
  Cc: Prasun.Kapoor, quintela, dgilbert, pbonzini

As vgic_its_check_id() computes the device/collection entry's
GPA, let's return it so that new callers can retrieve it easily.

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

---
v3 -> v4:
- check eaddr is not NULL to allow passing NULL eaddr parameter
  to vgic_its_check_id

v2: new
---
 virt/kvm/arm/vgic/vgic-its.c | 11 ++++++++---
 1 file changed, 8 insertions(+), 3 deletions(-)

diff --git a/virt/kvm/arm/vgic/vgic-its.c b/virt/kvm/arm/vgic/vgic-its.c
index df984b6..b907e3c 100644
--- a/virt/kvm/arm/vgic/vgic-its.c
+++ b/virt/kvm/arm/vgic/vgic-its.c
@@ -629,7 +629,8 @@ static int vgic_its_cmd_handle_movi(struct kvm *kvm, struct vgic_its *its,
  * is actually valid (covered by a memslot and guest accessible).
  * For this we have to read the respective first level entry.
  */
-static bool vgic_its_check_id(struct vgic_its *its, u64 baser, u32 id)
+static bool vgic_its_check_id(struct vgic_its *its, u64 baser, u32 id,
+			      gpa_t *eaddr)
 {
 	int l1_tbl_size = GITS_BASER_NR_PAGES(baser) * SZ_64K;
 	int index;
@@ -649,6 +650,8 @@ static bool vgic_its_check_id(struct vgic_its *its, u64 baser, u32 id)
 		addr = BASER_ADDRESS(baser) + id * esz;
 		gfn = addr >> PAGE_SHIFT;
 
+		if (eaddr)
+			*eaddr = addr;
 		return kvm_is_visible_gfn(its->dev->kvm, gfn);
 	}
 
@@ -681,6 +684,8 @@ static bool vgic_its_check_id(struct vgic_its *its, u64 baser, u32 id)
 	indirect_ptr += index * esz;
 	gfn = indirect_ptr >> PAGE_SHIFT;
 
+	if (eaddr)
+		*eaddr = indirect_ptr;
 	return kvm_is_visible_gfn(its->dev->kvm, gfn);
 }
 
@@ -690,7 +695,7 @@ static int vgic_its_alloc_collection(struct vgic_its *its,
 {
 	struct its_collection *collection;
 
-	if (!vgic_its_check_id(its, its->baser_coll_table, coll_id))
+	if (!vgic_its_check_id(its, its->baser_coll_table, coll_id, NULL))
 		return E_ITS_MAPC_COLLECTION_OOR;
 
 	collection = kzalloc(sizeof(*collection), GFP_KERNEL);
@@ -905,7 +910,7 @@ static int vgic_its_cmd_handle_mapd(struct kvm *kvm, struct vgic_its *its,
 	gpa_t itt_addr = its_cmd_get_ittaddr(its_cmd) << 8;
 	struct its_device *device;
 
-	if (!vgic_its_check_id(its, its->baser_device_table, device_id))
+	if (!vgic_its_check_id(its, its->baser_device_table, device_id, NULL))
 		return E_ITS_MAPD_DEVICE_OOR;
 
 	if (valid && nb_eventid_bits > VITS_TYPER_IDBITS)
-- 
2.5.5

^ permalink raw reply related	[flat|nested] 144+ messages in thread

* [PATCH v4 19/22] KVM: arm64: ITS: vgic_its_check_id returns the entry's GPA
@ 2017-03-27  9:31   ` Eric Auger
  0 siblings, 0 replies; 144+ messages in thread
From: Eric Auger @ 2017-03-27  9:31 UTC (permalink / raw)
  To: linux-arm-kernel

As vgic_its_check_id() computes the device/collection entry's
GPA, let's return it so that new callers can retrieve it easily.

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

---
v3 -> v4:
- check eaddr is not NULL to allow passing NULL eaddr parameter
  to vgic_its_check_id

v2: new
---
 virt/kvm/arm/vgic/vgic-its.c | 11 ++++++++---
 1 file changed, 8 insertions(+), 3 deletions(-)

diff --git a/virt/kvm/arm/vgic/vgic-its.c b/virt/kvm/arm/vgic/vgic-its.c
index df984b6..b907e3c 100644
--- a/virt/kvm/arm/vgic/vgic-its.c
+++ b/virt/kvm/arm/vgic/vgic-its.c
@@ -629,7 +629,8 @@ static int vgic_its_cmd_handle_movi(struct kvm *kvm, struct vgic_its *its,
  * is actually valid (covered by a memslot and guest accessible).
  * For this we have to read the respective first level entry.
  */
-static bool vgic_its_check_id(struct vgic_its *its, u64 baser, u32 id)
+static bool vgic_its_check_id(struct vgic_its *its, u64 baser, u32 id,
+			      gpa_t *eaddr)
 {
 	int l1_tbl_size = GITS_BASER_NR_PAGES(baser) * SZ_64K;
 	int index;
@@ -649,6 +650,8 @@ static bool vgic_its_check_id(struct vgic_its *its, u64 baser, u32 id)
 		addr = BASER_ADDRESS(baser) + id * esz;
 		gfn = addr >> PAGE_SHIFT;
 
+		if (eaddr)
+			*eaddr = addr;
 		return kvm_is_visible_gfn(its->dev->kvm, gfn);
 	}
 
@@ -681,6 +684,8 @@ static bool vgic_its_check_id(struct vgic_its *its, u64 baser, u32 id)
 	indirect_ptr += index * esz;
 	gfn = indirect_ptr >> PAGE_SHIFT;
 
+	if (eaddr)
+		*eaddr = indirect_ptr;
 	return kvm_is_visible_gfn(its->dev->kvm, gfn);
 }
 
@@ -690,7 +695,7 @@ static int vgic_its_alloc_collection(struct vgic_its *its,
 {
 	struct its_collection *collection;
 
-	if (!vgic_its_check_id(its, its->baser_coll_table, coll_id))
+	if (!vgic_its_check_id(its, its->baser_coll_table, coll_id, NULL))
 		return E_ITS_MAPC_COLLECTION_OOR;
 
 	collection = kzalloc(sizeof(*collection), GFP_KERNEL);
@@ -905,7 +910,7 @@ static int vgic_its_cmd_handle_mapd(struct kvm *kvm, struct vgic_its *its,
 	gpa_t itt_addr = its_cmd_get_ittaddr(its_cmd) << 8;
 	struct its_device *device;
 
-	if (!vgic_its_check_id(its, its->baser_device_table, device_id))
+	if (!vgic_its_check_id(its, its->baser_device_table, device_id, NULL))
 		return E_ITS_MAPD_DEVICE_OOR;
 
 	if (valid && nb_eventid_bits > VITS_TYPER_IDBITS)
-- 
2.5.5

^ permalink raw reply related	[flat|nested] 144+ messages in thread

* [PATCH v4 20/22] KVM: arm64: ITS: ITT flush and restore
  2017-03-27  9:30 ` Eric Auger
@ 2017-03-27  9:31   ` Eric Auger
  -1 siblings, 0 replies; 144+ messages in thread
From: Eric Auger @ 2017-03-27  9:31 UTC (permalink / raw)
  To: eric.auger.pro, eric.auger, marc.zyngier, christoffer.dall,
	andre.przywara, vijayak, Vijaya.Kumar, peter.maydell,
	linux-arm-kernel, kvmarm, kvm
  Cc: Prasun.Kapoor, quintela, dgilbert, pbonzini

Introduce routines to flush and restore device ITT and their
interrupt table entries (ITE).

The routines will be called on device table flush and
restore. They will become static in subsequent patches.

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

---

v3 -> v4:
- lookup_table and compute_next_eventid_offset become static in this
  patch
- remove static along with vgic_its_flush/restore_itt to avoid
  compilation warnings
- next field only computed with a shift (mask removed)
- handle the case where the last element has not been found

v2 -> v3:
- add return 0 in vgic_its_restore_ite (was in subsequent patch)

v2: creation
---
 virt/kvm/arm/vgic/vgic-its.c | 107 +++++++++++++++++++++++++++++++++++++++++--
 1 file changed, 104 insertions(+), 3 deletions(-)

diff --git a/virt/kvm/arm/vgic/vgic-its.c b/virt/kvm/arm/vgic/vgic-its.c
index b907e3c..02c0694 100644
--- a/virt/kvm/arm/vgic/vgic-its.c
+++ b/virt/kvm/arm/vgic/vgic-its.c
@@ -1707,7 +1707,7 @@ u32 compute_next_devid_offset(struct list_head *h, struct its_device *dev)
 	return min_t(u32, next_offset, VITS_DTE_MAX_DEVID_OFFSET);
 }
 
-u32 compute_next_eventid_offset(struct list_head *h, struct its_ite *ite)
+static u32 compute_next_eventid_offset(struct list_head *h, struct its_ite *ite)
 {
 	struct list_head *e = &ite->ite_list;
 	struct its_ite *next;
@@ -1749,8 +1749,8 @@ typedef int (*entry_fn_t)(struct vgic_its *its, u32 id, void *addr,
  *
  * Return: < 0 on error, 1 if last element identified, 0 otherwise
  */
-int lookup_table(struct vgic_its *its, gpa_t base, int size, int esz,
-		 int start_id, entry_fn_t fn, void *opaque)
+static int lookup_table(struct vgic_its *its, gpa_t base, int size, int esz,
+			int start_id, entry_fn_t fn, void *opaque)
 {
 	gpa_t gpa = base, top = base + size - 1;
 	unsigned long len = size;
@@ -1815,6 +1815,107 @@ static int vgic_its_restore_pending_tables(struct kvm *kvm)
 	return -ENXIO;
 }
 
+static int vgic_its_flush_ite(struct vgic_its *its, struct its_device *dev,
+			      struct its_ite *ite, gpa_t gpa)
+{
+	struct kvm *kvm = its->dev->kvm;
+	u32 next_offset;
+	u64 val;
+
+	next_offset = compute_next_eventid_offset(&dev->itt_head, ite);
+	val = ((u64)next_offset << 48) | ((u64)ite->lpi << 16) |
+		ite->collection->collection_id;
+	val = cpu_to_le64(val);
+	return kvm_write_guest(kvm, gpa, &val, VITS_ESZ);
+}
+
+/**
+ * vgic_its_restore_ite - restore an interrupt translation entry
+ * @event_id: id used for indexing
+ * @ptr: kernel VA where the 8 byte ITE is located
+ * @opaque: pointer to the its_device
+ * @next: id offset to the next entry
+ */
+static int vgic_its_restore_ite(struct vgic_its *its, u32 event_id,
+				void *ptr, void *opaque, u32 *next)
+{
+	struct its_device *dev = (struct its_device *)opaque;
+	struct its_collection *collection;
+	struct kvm *kvm = its->dev->kvm;
+	u64 val, *p = (u64 *)ptr;
+	struct vgic_irq *irq;
+	u32 coll_id, lpi_id;
+	struct its_ite *ite;
+	int ret;
+
+	val = *p;
+	*next = 1;
+
+	val = le64_to_cpu(val);
+
+	coll_id = val & GENMASK_ULL(15, 0);
+	lpi_id = (val & GENMASK_ULL(47, 16)) >> 16;
+
+	if (!lpi_id)
+		return 0;
+
+	*next = val >> 48;
+
+	collection = find_collection(its, coll_id);
+	if (!collection)
+		return -EINVAL;
+
+	ret = vgic_its_alloc_ite(dev, &ite, collection,
+				  lpi_id, event_id);
+	if (ret)
+		return ret;
+
+	irq = vgic_add_lpi(kvm, lpi_id);
+	if (IS_ERR(irq))
+		return PTR_ERR(irq);
+	ite->irq = irq;
+
+	/* restore the configuration of the LPI */
+	ret = update_lpi_config(kvm, irq, NULL);
+	if (ret)
+		return ret;
+
+	update_affinity_ite(kvm, ite);
+	return 0;
+}
+
+int vgic_its_flush_itt(struct vgic_its *its, struct its_device *device)
+{
+	gpa_t base = device->itt_addr;
+	struct its_ite *ite;
+	int ret;
+
+	list_for_each_entry(ite, &device->itt_head, ite_list) {
+		gpa_t gpa = base + ite->event_id * VITS_ESZ;
+
+		ret = vgic_its_flush_ite(its, device, ite, gpa);
+		if (ret)
+			return ret;
+	}
+	return 0;
+}
+
+int vgic_its_restore_itt(struct vgic_its *its, struct its_device *dev)
+{
+	size_t max_size = BIT_ULL(dev->nb_eventid_bits) * VITS_ESZ;
+	gpa_t base = dev->itt_addr;
+	int ret;
+
+	ret =  lookup_table(its, base, max_size, VITS_ESZ, 0,
+			    vgic_its_restore_ite, dev);
+
+	if (ret < 0)
+		return ret;
+
+	/* if the last element has not been found we are in trouble */
+	return ret ? 0 : -EINVAL;
+}
+
 /**
  * vgic_its_flush_device_tables - flush the device table and all ITT
  * into guest RAM
-- 
2.5.5

^ permalink raw reply related	[flat|nested] 144+ messages in thread

* [PATCH v4 20/22] KVM: arm64: ITS: ITT flush and restore
@ 2017-03-27  9:31   ` Eric Auger
  0 siblings, 0 replies; 144+ messages in thread
From: Eric Auger @ 2017-03-27  9:31 UTC (permalink / raw)
  To: linux-arm-kernel

Introduce routines to flush and restore device ITT and their
interrupt table entries (ITE).

The routines will be called on device table flush and
restore. They will become static in subsequent patches.

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

---

v3 -> v4:
- lookup_table and compute_next_eventid_offset become static in this
  patch
- remove static along with vgic_its_flush/restore_itt to avoid
  compilation warnings
- next field only computed with a shift (mask removed)
- handle the case where the last element has not been found

v2 -> v3:
- add return 0 in vgic_its_restore_ite (was in subsequent patch)

v2: creation
---
 virt/kvm/arm/vgic/vgic-its.c | 107 +++++++++++++++++++++++++++++++++++++++++--
 1 file changed, 104 insertions(+), 3 deletions(-)

diff --git a/virt/kvm/arm/vgic/vgic-its.c b/virt/kvm/arm/vgic/vgic-its.c
index b907e3c..02c0694 100644
--- a/virt/kvm/arm/vgic/vgic-its.c
+++ b/virt/kvm/arm/vgic/vgic-its.c
@@ -1707,7 +1707,7 @@ u32 compute_next_devid_offset(struct list_head *h, struct its_device *dev)
 	return min_t(u32, next_offset, VITS_DTE_MAX_DEVID_OFFSET);
 }
 
-u32 compute_next_eventid_offset(struct list_head *h, struct its_ite *ite)
+static u32 compute_next_eventid_offset(struct list_head *h, struct its_ite *ite)
 {
 	struct list_head *e = &ite->ite_list;
 	struct its_ite *next;
@@ -1749,8 +1749,8 @@ typedef int (*entry_fn_t)(struct vgic_its *its, u32 id, void *addr,
  *
  * Return: < 0 on error, 1 if last element identified, 0 otherwise
  */
-int lookup_table(struct vgic_its *its, gpa_t base, int size, int esz,
-		 int start_id, entry_fn_t fn, void *opaque)
+static int lookup_table(struct vgic_its *its, gpa_t base, int size, int esz,
+			int start_id, entry_fn_t fn, void *opaque)
 {
 	gpa_t gpa = base, top = base + size - 1;
 	unsigned long len = size;
@@ -1815,6 +1815,107 @@ static int vgic_its_restore_pending_tables(struct kvm *kvm)
 	return -ENXIO;
 }
 
+static int vgic_its_flush_ite(struct vgic_its *its, struct its_device *dev,
+			      struct its_ite *ite, gpa_t gpa)
+{
+	struct kvm *kvm = its->dev->kvm;
+	u32 next_offset;
+	u64 val;
+
+	next_offset = compute_next_eventid_offset(&dev->itt_head, ite);
+	val = ((u64)next_offset << 48) | ((u64)ite->lpi << 16) |
+		ite->collection->collection_id;
+	val = cpu_to_le64(val);
+	return kvm_write_guest(kvm, gpa, &val, VITS_ESZ);
+}
+
+/**
+ * vgic_its_restore_ite - restore an interrupt translation entry
+ * @event_id: id used for indexing
+ * @ptr: kernel VA where the 8 byte ITE is located
+ * @opaque: pointer to the its_device
+ * @next: id offset to the next entry
+ */
+static int vgic_its_restore_ite(struct vgic_its *its, u32 event_id,
+				void *ptr, void *opaque, u32 *next)
+{
+	struct its_device *dev = (struct its_device *)opaque;
+	struct its_collection *collection;
+	struct kvm *kvm = its->dev->kvm;
+	u64 val, *p = (u64 *)ptr;
+	struct vgic_irq *irq;
+	u32 coll_id, lpi_id;
+	struct its_ite *ite;
+	int ret;
+
+	val = *p;
+	*next = 1;
+
+	val = le64_to_cpu(val);
+
+	coll_id = val & GENMASK_ULL(15, 0);
+	lpi_id = (val & GENMASK_ULL(47, 16)) >> 16;
+
+	if (!lpi_id)
+		return 0;
+
+	*next = val >> 48;
+
+	collection = find_collection(its, coll_id);
+	if (!collection)
+		return -EINVAL;
+
+	ret = vgic_its_alloc_ite(dev, &ite, collection,
+				  lpi_id, event_id);
+	if (ret)
+		return ret;
+
+	irq = vgic_add_lpi(kvm, lpi_id);
+	if (IS_ERR(irq))
+		return PTR_ERR(irq);
+	ite->irq = irq;
+
+	/* restore the configuration of the LPI */
+	ret = update_lpi_config(kvm, irq, NULL);
+	if (ret)
+		return ret;
+
+	update_affinity_ite(kvm, ite);
+	return 0;
+}
+
+int vgic_its_flush_itt(struct vgic_its *its, struct its_device *device)
+{
+	gpa_t base = device->itt_addr;
+	struct its_ite *ite;
+	int ret;
+
+	list_for_each_entry(ite, &device->itt_head, ite_list) {
+		gpa_t gpa = base + ite->event_id * VITS_ESZ;
+
+		ret = vgic_its_flush_ite(its, device, ite, gpa);
+		if (ret)
+			return ret;
+	}
+	return 0;
+}
+
+int vgic_its_restore_itt(struct vgic_its *its, struct its_device *dev)
+{
+	size_t max_size = BIT_ULL(dev->nb_eventid_bits) * VITS_ESZ;
+	gpa_t base = dev->itt_addr;
+	int ret;
+
+	ret =  lookup_table(its, base, max_size, VITS_ESZ, 0,
+			    vgic_its_restore_ite, dev);
+
+	if (ret < 0)
+		return ret;
+
+	/* if the last element has not been found we are in trouble */
+	return ret ? 0 : -EINVAL;
+}
+
 /**
  * vgic_its_flush_device_tables - flush the device table and all ITT
  * into guest RAM
-- 
2.5.5

^ permalink raw reply related	[flat|nested] 144+ messages in thread

* [PATCH v4 21/22] KVM: arm64: ITS: Device table save/restore
  2017-03-27  9:30 ` Eric Auger
@ 2017-03-27  9:31   ` Eric Auger
  -1 siblings, 0 replies; 144+ messages in thread
From: Eric Auger @ 2017-03-27  9:31 UTC (permalink / raw)
  To: eric.auger.pro, eric.auger, marc.zyngier, christoffer.dall,
	andre.przywara, vijayak, Vijaya.Kumar, peter.maydell,
	linux-arm-kernel, kvmarm, kvm
  Cc: Prasun.Kapoor, drjones, pbonzini, dgilbert, quintela

This patch flushes 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 flush
the translation table using the vgic_its_flush/restore_itt
routines.

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

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

---
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 | 161 +++++++++++++++++++++++++++++++++++++++++--
 1 file changed, 156 insertions(+), 5 deletions(-)

diff --git a/virt/kvm/arm/vgic/vgic-its.c b/virt/kvm/arm/vgic/vgic-its.c
index 02c0694..a516bbb 100644
--- a/virt/kvm/arm/vgic/vgic-its.c
+++ b/virt/kvm/arm/vgic/vgic-its.c
@@ -1693,7 +1693,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;
@@ -1884,7 +1885,7 @@ static int vgic_its_restore_ite(struct vgic_its *its, u32 event_id,
 	return 0;
 }
 
-int vgic_its_flush_itt(struct vgic_its *its, struct its_device *device)
+static int vgic_its_flush_itt(struct vgic_its *its, struct its_device *device)
 {
 	gpa_t base = device->itt_addr;
 	struct its_ite *ite;
@@ -1900,7 +1901,7 @@ int vgic_its_flush_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)
 {
 	size_t max_size = BIT_ULL(dev->nb_eventid_bits) * VITS_ESZ;
 	gpa_t base = dev->itt_addr;
@@ -1917,12 +1918,141 @@ int vgic_its_restore_itt(struct vgic_its *its, struct its_device *dev)
 }
 
 /**
+ * vgic_its_flush_dte - Flush a device table entry at a given GPA
+ *
+ * @its: ITS handle
+ * @dev: ITS device
+ * @ptr: GPA
+ */
+static int vgic_its_flush_dte(struct vgic_its *its,
+			      struct its_device *dev, gpa_t ptr)
+{
+	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 << 63 | ((u64)next_offset << 49) | (itt_addr_field << 5) |
+		(dev->nb_eventid_bits - 1));
+	val = cpu_to_le64(val);
+	ret = kvm_write_guest(kvm, ptr, &val, 8);
+	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 >> 63;
+	nb_eventid_bits = (entry & GENMASK_ULL(4, 0)) + 1;
+	itt_addr = ((entry & GENMASK_ULL(48, 5)) >> 5) << 8;
+	*next = 1;
+
+	if (!valid)
+		return 0;
+
+	/* dte entry is valid */
+	*next = (entry & GENMASK_ULL(62, 49)) >> 49;
+
+	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;
+}
+
+/**
  * vgic_its_flush_device_tables - flush 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_flush_device_tables(struct vgic_its *its)
 {
-	return -ENXIO;
+	struct its_device *dev;
+	u64 baser;
+
+	baser = its->baser_device_table;
+
+	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_flush_itt(its, dev);
+		if (ret)
+			return ret;
+
+		ret = vgic_its_flush_dte(its, dev, eaddr);
+		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)
+{
+	int l2_start_id = id * (SZ_64K / GITS_LVL1_ENTRY_SIZE);
+	u64 entry = *(u64 *)addr;
+	gpa_t gpa;
+	int ret;
+
+	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, 8,
+			    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;
 }
 
 /**
@@ -1931,7 +2061,28 @@ static int vgic_its_flush_device_tables(struct vgic_its *its)
  */
 static int vgic_its_restore_device_tables(struct vgic_its *its)
 {
-	return -ENXIO;
+	u64 baser = its->baser_device_table;
+	int l1_tbl_size = GITS_BASER_NR_PAGES(baser) * SZ_64K;
+	int l1_esz = GITS_BASER_ENTRY_SIZE(baser);
+	gpa_t l1_gpa;
+	int ret;
+
+	l1_gpa = BASER_ADDRESS(baser);
+	if (!l1_gpa)
+		return 0;
+
+	if (baser & GITS_BASER_INDIRECT)
+		ret = lookup_table(its, l1_gpa, l1_tbl_size, 8, 0,
+			    	   handle_l1_entry, NULL);
+	else
+		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_flush_cte(struct vgic_its *its,
-- 
2.5.5

^ permalink raw reply related	[flat|nested] 144+ messages in thread

* [PATCH v4 21/22] KVM: arm64: ITS: Device table save/restore
@ 2017-03-27  9:31   ` Eric Auger
  0 siblings, 0 replies; 144+ messages in thread
From: Eric Auger @ 2017-03-27  9:31 UTC (permalink / raw)
  To: linux-arm-kernel

This patch flushes 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 flush
the translation table using the vgic_its_flush/restore_itt
routines.

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

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

---
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 | 161 +++++++++++++++++++++++++++++++++++++++++--
 1 file changed, 156 insertions(+), 5 deletions(-)

diff --git a/virt/kvm/arm/vgic/vgic-its.c b/virt/kvm/arm/vgic/vgic-its.c
index 02c0694..a516bbb 100644
--- a/virt/kvm/arm/vgic/vgic-its.c
+++ b/virt/kvm/arm/vgic/vgic-its.c
@@ -1693,7 +1693,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;
@@ -1884,7 +1885,7 @@ static int vgic_its_restore_ite(struct vgic_its *its, u32 event_id,
 	return 0;
 }
 
-int vgic_its_flush_itt(struct vgic_its *its, struct its_device *device)
+static int vgic_its_flush_itt(struct vgic_its *its, struct its_device *device)
 {
 	gpa_t base = device->itt_addr;
 	struct its_ite *ite;
@@ -1900,7 +1901,7 @@ int vgic_its_flush_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)
 {
 	size_t max_size = BIT_ULL(dev->nb_eventid_bits) * VITS_ESZ;
 	gpa_t base = dev->itt_addr;
@@ -1917,12 +1918,141 @@ int vgic_its_restore_itt(struct vgic_its *its, struct its_device *dev)
 }
 
 /**
+ * vgic_its_flush_dte - Flush a device table entry at a given GPA
+ *
+ * @its: ITS handle
+ * @dev: ITS device
+ * @ptr: GPA
+ */
+static int vgic_its_flush_dte(struct vgic_its *its,
+			      struct its_device *dev, gpa_t ptr)
+{
+	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 << 63 | ((u64)next_offset << 49) | (itt_addr_field << 5) |
+		(dev->nb_eventid_bits - 1));
+	val = cpu_to_le64(val);
+	ret = kvm_write_guest(kvm, ptr, &val, 8);
+	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 >> 63;
+	nb_eventid_bits = (entry & GENMASK_ULL(4, 0)) + 1;
+	itt_addr = ((entry & GENMASK_ULL(48, 5)) >> 5) << 8;
+	*next = 1;
+
+	if (!valid)
+		return 0;
+
+	/* dte entry is valid */
+	*next = (entry & GENMASK_ULL(62, 49)) >> 49;
+
+	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;
+}
+
+/**
  * vgic_its_flush_device_tables - flush 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_flush_device_tables(struct vgic_its *its)
 {
-	return -ENXIO;
+	struct its_device *dev;
+	u64 baser;
+
+	baser = its->baser_device_table;
+
+	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_flush_itt(its, dev);
+		if (ret)
+			return ret;
+
+		ret = vgic_its_flush_dte(its, dev, eaddr);
+		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)
+{
+	int l2_start_id = id * (SZ_64K / GITS_LVL1_ENTRY_SIZE);
+	u64 entry = *(u64 *)addr;
+	gpa_t gpa;
+	int ret;
+
+	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, 8,
+			    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;
 }
 
 /**
@@ -1931,7 +2061,28 @@ static int vgic_its_flush_device_tables(struct vgic_its *its)
  */
 static int vgic_its_restore_device_tables(struct vgic_its *its)
 {
-	return -ENXIO;
+	u64 baser = its->baser_device_table;
+	int l1_tbl_size = GITS_BASER_NR_PAGES(baser) * SZ_64K;
+	int l1_esz = GITS_BASER_ENTRY_SIZE(baser);
+	gpa_t l1_gpa;
+	int ret;
+
+	l1_gpa = BASER_ADDRESS(baser);
+	if (!l1_gpa)
+		return 0;
+
+	if (baser & GITS_BASER_INDIRECT)
+		ret = lookup_table(its, l1_gpa, l1_tbl_size, 8, 0,
+			    	   handle_l1_entry, NULL);
+	else
+		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_flush_cte(struct vgic_its *its,
-- 
2.5.5

^ permalink raw reply related	[flat|nested] 144+ messages in thread

* [PATCH v4 22/22] KVM: arm64: ITS: Pending table save/restore
  2017-03-27  9:30 ` Eric Auger
@ 2017-03-27  9:31   ` Eric Auger
  -1 siblings, 0 replies; 144+ messages in thread
From: Eric Auger @ 2017-03-27  9:31 UTC (permalink / raw)
  To: eric.auger.pro, eric.auger, marc.zyngier, christoffer.dall,
	andre.przywara, vijayak, Vijaya.Kumar, peter.maydell,
	linux-arm-kernel, kvmarm, kvm
  Cc: Prasun.Kapoor, quintela, dgilbert, pbonzini

Save and restore the pending tables.

Pending table restore obviously requires the pendbaser to be
already set.

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

---

v3 -> v4:
- remove the wrong comment about locking
- pass kvm struct instead of its handle
- add comment about restore method
- remove GITR_PENDABASER.PTZ check
- continue if target_vcpu == NULL
- new locking strategy

v1 -> v2:
- do not care about the 1st KB which should be zeroed according to
  the spec.
---
 virt/kvm/arm/vgic/vgic-its.c | 66 ++++++++++++++++++++++++++++++++++++++++++--
 1 file changed, 64 insertions(+), 2 deletions(-)

diff --git a/virt/kvm/arm/vgic/vgic-its.c b/virt/kvm/arm/vgic/vgic-its.c
index a516bbb..e10aa81 100644
--- a/virt/kvm/arm/vgic/vgic-its.c
+++ b/virt/kvm/arm/vgic/vgic-its.c
@@ -1804,16 +1804,78 @@ static int lookup_table(struct vgic_its *its, gpa_t base, int size, int esz,
  */
 static int vgic_its_flush_pending_tables(struct kvm *kvm)
 {
-	return -ENXIO;
+	struct vgic_dist *dist = &kvm->arch.vgic;
+	struct vgic_irq *irq;
+	int ret;
+
+	list_for_each_entry(irq, &dist->lpi_list_head, lpi_list) {
+		struct kvm_vcpu *vcpu;
+		gpa_t pendbase, ptr;
+		bool stored;
+		u8 val;
+
+		vcpu = irq->target_vcpu;
+		if (!vcpu)
+			continue;
+
+		pendbase = PENDBASER_ADDRESS(vcpu->arch.vgic_cpu.pendbaser);
+
+		ptr = pendbase + (irq->intid / BITS_PER_BYTE);
+
+		ret = kvm_read_guest(kvm, (gpa_t)ptr, &val, 1);
+		if (ret)
+			return ret;
+
+		stored = val & (irq->intid % BITS_PER_BYTE);
+		if (stored == irq->pending_latch)
+			continue;
+
+		if (irq->pending_latch)
+			val |= 1 << (irq->intid % BITS_PER_BYTE);
+		else
+			val &= ~(1 << (irq->intid % BITS_PER_BYTE));
+
+		ret = kvm_write_guest(kvm, (gpa_t)ptr, &val, 1);
+		if (ret)
+			return ret;
+	}
+
+	return 0;
 }
 
 /**
  * vgic_its_restore_pending_tables - Restore the pending tables from guest
  * RAM to internal data structs
+ *
+ * Does not scan the whole pending tables but just loop on all registered
+ * LPIS and scan their associated pending bit. This obviously requires
+ * the ITEs to be restored before.
  */
 static int vgic_its_restore_pending_tables(struct kvm *kvm)
 {
-	return -ENXIO;
+	struct vgic_dist *dist = &kvm->arch.vgic;
+	struct vgic_irq *irq;
+	int ret;
+
+	list_for_each_entry(irq, &dist->lpi_list_head, lpi_list) {
+		struct kvm_vcpu *vcpu;
+		gpa_t pendbase, ptr;
+		u8 val;
+
+		vcpu = irq->target_vcpu;
+		if (!vcpu)
+			continue;
+
+		pendbase = PENDBASER_ADDRESS(vcpu->arch.vgic_cpu.pendbaser);
+
+		ptr = pendbase + (irq->intid / BITS_PER_BYTE);
+
+		ret = kvm_read_guest(kvm, (gpa_t)ptr, &val, 1);
+		if (ret)
+			return ret;
+		irq->pending_latch = val & (1 << (irq->intid % BITS_PER_BYTE));
+	}
+	return 0;
 }
 
 static int vgic_its_flush_ite(struct vgic_its *its, struct its_device *dev,
-- 
2.5.5

^ permalink raw reply related	[flat|nested] 144+ messages in thread

* [PATCH v4 22/22] KVM: arm64: ITS: Pending table save/restore
@ 2017-03-27  9:31   ` Eric Auger
  0 siblings, 0 replies; 144+ messages in thread
From: Eric Auger @ 2017-03-27  9:31 UTC (permalink / raw)
  To: linux-arm-kernel

Save and restore the pending tables.

Pending table restore obviously requires the pendbaser to be
already set.

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

---

v3 -> v4:
- remove the wrong comment about locking
- pass kvm struct instead of its handle
- add comment about restore method
- remove GITR_PENDABASER.PTZ check
- continue if target_vcpu == NULL
- new locking strategy

v1 -> v2:
- do not care about the 1st KB which should be zeroed according to
  the spec.
---
 virt/kvm/arm/vgic/vgic-its.c | 66 ++++++++++++++++++++++++++++++++++++++++++--
 1 file changed, 64 insertions(+), 2 deletions(-)

diff --git a/virt/kvm/arm/vgic/vgic-its.c b/virt/kvm/arm/vgic/vgic-its.c
index a516bbb..e10aa81 100644
--- a/virt/kvm/arm/vgic/vgic-its.c
+++ b/virt/kvm/arm/vgic/vgic-its.c
@@ -1804,16 +1804,78 @@ static int lookup_table(struct vgic_its *its, gpa_t base, int size, int esz,
  */
 static int vgic_its_flush_pending_tables(struct kvm *kvm)
 {
-	return -ENXIO;
+	struct vgic_dist *dist = &kvm->arch.vgic;
+	struct vgic_irq *irq;
+	int ret;
+
+	list_for_each_entry(irq, &dist->lpi_list_head, lpi_list) {
+		struct kvm_vcpu *vcpu;
+		gpa_t pendbase, ptr;
+		bool stored;
+		u8 val;
+
+		vcpu = irq->target_vcpu;
+		if (!vcpu)
+			continue;
+
+		pendbase = PENDBASER_ADDRESS(vcpu->arch.vgic_cpu.pendbaser);
+
+		ptr = pendbase + (irq->intid / BITS_PER_BYTE);
+
+		ret = kvm_read_guest(kvm, (gpa_t)ptr, &val, 1);
+		if (ret)
+			return ret;
+
+		stored = val & (irq->intid % BITS_PER_BYTE);
+		if (stored == irq->pending_latch)
+			continue;
+
+		if (irq->pending_latch)
+			val |= 1 << (irq->intid % BITS_PER_BYTE);
+		else
+			val &= ~(1 << (irq->intid % BITS_PER_BYTE));
+
+		ret = kvm_write_guest(kvm, (gpa_t)ptr, &val, 1);
+		if (ret)
+			return ret;
+	}
+
+	return 0;
 }
 
 /**
  * vgic_its_restore_pending_tables - Restore the pending tables from guest
  * RAM to internal data structs
+ *
+ * Does not scan the whole pending tables but just loop on all registered
+ * LPIS and scan their associated pending bit. This obviously requires
+ * the ITEs to be restored before.
  */
 static int vgic_its_restore_pending_tables(struct kvm *kvm)
 {
-	return -ENXIO;
+	struct vgic_dist *dist = &kvm->arch.vgic;
+	struct vgic_irq *irq;
+	int ret;
+
+	list_for_each_entry(irq, &dist->lpi_list_head, lpi_list) {
+		struct kvm_vcpu *vcpu;
+		gpa_t pendbase, ptr;
+		u8 val;
+
+		vcpu = irq->target_vcpu;
+		if (!vcpu)
+			continue;
+
+		pendbase = PENDBASER_ADDRESS(vcpu->arch.vgic_cpu.pendbaser);
+
+		ptr = pendbase + (irq->intid / BITS_PER_BYTE);
+
+		ret = kvm_read_guest(kvm, (gpa_t)ptr, &val, 1);
+		if (ret)
+			return ret;
+		irq->pending_latch = val & (1 << (irq->intid % BITS_PER_BYTE));
+	}
+	return 0;
 }
 
 static int vgic_its_flush_ite(struct vgic_its *its, struct its_device *dev,
-- 
2.5.5

^ permalink raw reply related	[flat|nested] 144+ messages in thread

* Re: [PATCH v4 13/22] KVM: arm64: ITS: KVM_DEV_ARM_VGIC_GRP_ITS_TABLES group
  2017-03-27  9:31   ` Eric Auger
@ 2017-03-27 15:04     ` kbuild test robot
  -1 siblings, 0 replies; 144+ messages in thread
From: kbuild test robot @ 2017-03-27 15:04 UTC (permalink / raw)
  To: Eric Auger
  Cc: linux-arm-kernel, kvm, Prasun.Kapoor, marc.zyngier,
	andre.przywara, quintela, dgilbert, vijayak, Vijaya.Kumar,
	kbuild-all, pbonzini, kvmarm, eric.auger.pro

[-- Attachment #1: Type: text/plain, Size: 2153 bytes --]

Hi Eric,

[auto build test ERROR on kvmarm/next]
[also build test ERROR on v4.11-rc4 next-20170327]
[if your patch is applied to the wrong git tree, please drop us a note to help improve the system]

url:    https://github.com/0day-ci/linux/commits/Eric-Auger/vITS-save-restore/20170327-195443
base:   https://git.kernel.org/pub/scm/linux/kernel/git/kvmarm/kvmarm.git next
config: arm64-defconfig (attached as .config)
compiler: aarch64-linux-gnu-gcc (Debian 6.1.1-9) 6.1.1 20160705
reproduce:
        wget https://raw.githubusercontent.com/01org/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
        chmod +x ~/bin/make.cross
        # save the attached .config to linux build tree
        make.cross ARCH=arm64 

All errors (new ones prefixed by >>):

   arch/arm64/kvm/../../../virt/kvm/arm/vgic/vgic-its.c: In function 'vgic_its_has_attr':
>> arch/arm64/kvm/../../../virt/kvm/arm/vgic/vgic-its.c:1766:33: error: 'its' undeclared (first use in this function)
      return vgic_its_table_restore(its);
                                    ^~~
   arch/arm64/kvm/../../../virt/kvm/arm/vgic/vgic-its.c:1766:33: note: each undeclared identifier is reported only once for each function it appears in

vim +/its +1766 arch/arm64/kvm/../../../virt/kvm/arm/vgic/vgic-its.c

  1750			case KVM_DEV_ARM_VGIC_CTRL_INIT:
  1751				return 0;
  1752			}
  1753			break;
  1754		case KVM_DEV_ARM_VGIC_GRP_ITS_REGS: {
  1755			u64 __user *uaddr = (u64 __user *)(long)attr->addr;
  1756			u64 reg;
  1757	
  1758			if (get_user(reg, uaddr))
  1759				return -EFAULT;
  1760	
  1761			return vgic_its_attr_regs_access(dev, attr, &reg, true);
  1762		}
  1763		case KVM_DEV_ARM_VGIC_GRP_ITS_TABLES:
  1764			if (attr->attr)
  1765				return -EINVAL;
> 1766			return vgic_its_table_restore(its);
  1767		}
  1768		return -ENXIO;
  1769	}
  1770	
  1771	static int vgic_its_set_attr(struct kvm_device *dev,
  1772				     struct kvm_device_attr *attr)
  1773	{
  1774		struct vgic_its *its = dev->private;

---
0-DAY kernel test infrastructure                Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all                   Intel Corporation

[-- Attachment #2: .config.gz --]
[-- Type: application/gzip, Size: 33916 bytes --]

[-- Attachment #3: Type: text/plain, Size: 151 bytes --]

_______________________________________________
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm

^ permalink raw reply	[flat|nested] 144+ messages in thread

* [PATCH v4 13/22] KVM: arm64: ITS: KVM_DEV_ARM_VGIC_GRP_ITS_TABLES group
@ 2017-03-27 15:04     ` kbuild test robot
  0 siblings, 0 replies; 144+ messages in thread
From: kbuild test robot @ 2017-03-27 15:04 UTC (permalink / raw)
  To: linux-arm-kernel

Hi Eric,

[auto build test ERROR on kvmarm/next]
[also build test ERROR on v4.11-rc4 next-20170327]
[if your patch is applied to the wrong git tree, please drop us a note to help improve the system]

url:    https://github.com/0day-ci/linux/commits/Eric-Auger/vITS-save-restore/20170327-195443
base:   https://git.kernel.org/pub/scm/linux/kernel/git/kvmarm/kvmarm.git next
config: arm64-defconfig (attached as .config)
compiler: aarch64-linux-gnu-gcc (Debian 6.1.1-9) 6.1.1 20160705
reproduce:
        wget https://raw.githubusercontent.com/01org/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
        chmod +x ~/bin/make.cross
        # save the attached .config to linux build tree
        make.cross ARCH=arm64 

All errors (new ones prefixed by >>):

   arch/arm64/kvm/../../../virt/kvm/arm/vgic/vgic-its.c: In function 'vgic_its_has_attr':
>> arch/arm64/kvm/../../../virt/kvm/arm/vgic/vgic-its.c:1766:33: error: 'its' undeclared (first use in this function)
      return vgic_its_table_restore(its);
                                    ^~~
   arch/arm64/kvm/../../../virt/kvm/arm/vgic/vgic-its.c:1766:33: note: each undeclared identifier is reported only once for each function it appears in

vim +/its +1766 arch/arm64/kvm/../../../virt/kvm/arm/vgic/vgic-its.c

  1750			case KVM_DEV_ARM_VGIC_CTRL_INIT:
  1751				return 0;
  1752			}
  1753			break;
  1754		case KVM_DEV_ARM_VGIC_GRP_ITS_REGS: {
  1755			u64 __user *uaddr = (u64 __user *)(long)attr->addr;
  1756			u64 reg;
  1757	
  1758			if (get_user(reg, uaddr))
  1759				return -EFAULT;
  1760	
  1761			return vgic_its_attr_regs_access(dev, attr, &reg, true);
  1762		}
  1763		case KVM_DEV_ARM_VGIC_GRP_ITS_TABLES:
  1764			if (attr->attr)
  1765				return -EINVAL;
> 1766			return vgic_its_table_restore(its);
  1767		}
  1768		return -ENXIO;
  1769	}
  1770	
  1771	static int vgic_its_set_attr(struct kvm_device *dev,
  1772				     struct kvm_device_attr *attr)
  1773	{
  1774		struct vgic_its *its = dev->private;

---
0-DAY kernel test infrastructure                Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all                   Intel Corporation
-------------- next part --------------
A non-text attachment was scrubbed...
Name: .config.gz
Type: application/gzip
Size: 33916 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20170327/bc1b0096/attachment-0001.gz>

^ permalink raw reply	[flat|nested] 144+ messages in thread

* Re: [PATCH v4 13/22] KVM: arm64: ITS: KVM_DEV_ARM_VGIC_GRP_ITS_TABLES group
  2017-03-27 15:04     ` kbuild test robot
@ 2017-03-27 18:29       ` Auger Eric
  -1 siblings, 0 replies; 144+ messages in thread
From: Auger Eric @ 2017-03-27 18:29 UTC (permalink / raw)
  To: kbuild test robot
  Cc: kvm, Prasun.Kapoor, marc.zyngier, andre.przywara, quintela,
	dgilbert, Vijaya.Kumar, vijayak, kbuild-all, pbonzini, kvmarm,
	linux-arm-kernel, eric.auger.pro

Hi,

On 27/03/2017 17:04, kbuild test robot wrote:
> Hi Eric,
> 
> [auto build test ERROR on kvmarm/next]
> [also build test ERROR on v4.11-rc4 next-20170327]
> [if your patch is applied to the wrong git tree, please drop us a note to help improve the system]
> 
> url:    https://github.com/0day-ci/linux/commits/Eric-Auger/vITS-save-restore/20170327-195443
> base:   https://git.kernel.org/pub/scm/linux/kernel/git/kvmarm/kvmarm.git next
> config: arm64-defconfig (attached as .config)
> compiler: aarch64-linux-gnu-gcc (Debian 6.1.1-9) 6.1.1 20160705
> reproduce:
>         wget https://raw.githubusercontent.com/01org/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
>         chmod +x ~/bin/make.cross
>         # save the attached .config to linux build tree
>         make.cross ARCH=arm64 
> 
> All errors (new ones prefixed by >>):
> 
>    arch/arm64/kvm/../../../virt/kvm/arm/vgic/vgic-its.c: In function 'vgic_its_has_attr':
>>> arch/arm64/kvm/../../../virt/kvm/arm/vgic/vgic-its.c:1766:33: error: 'its' undeclared (first use in this function)
>       return vgic_its_table_restore(its);

I think this is due to the fact the series is applied on KVM: arm/arm64:
Emulate the EL1 phys timer registers (kvmarm-for-4.11).

Please apply it to (kvmarm/queue, kvmarm/next, kvm_next) KVM: arm/arm64:
vgic: Improve sync_hwstate performance  (255905e)
I also checked it compiles on 4.11-rc4.

Please let me know if I got something wrong.

Thanks

Eric
>                                     ^~~
>    arch/arm64/kvm/../../../virt/kvm/arm/vgic/vgic-its.c:1766:33: note: each undeclared identifier is reported only once for each function it appears in
> 
> vim +/its +1766 arch/arm64/kvm/../../../virt/kvm/arm/vgic/vgic-its.c
> 
>   1750			case KVM_DEV_ARM_VGIC_CTRL_INIT:
>   1751				return 0;
>   1752			}
>   1753			break;
>   1754		case KVM_DEV_ARM_VGIC_GRP_ITS_REGS: {
>   1755			u64 __user *uaddr = (u64 __user *)(long)attr->addr;
>   1756			u64 reg;
>   1757	
>   1758			if (get_user(reg, uaddr))
>   1759				return -EFAULT;
>   1760	
>   1761			return vgic_its_attr_regs_access(dev, attr, &reg, true);
>   1762		}
>   1763		case KVM_DEV_ARM_VGIC_GRP_ITS_TABLES:
>   1764			if (attr->attr)
>   1765				return -EINVAL;
>> 1766			return vgic_its_table_restore(its);
>   1767		}
>   1768		return -ENXIO;
>   1769	}
>   1770	
>   1771	static int vgic_its_set_attr(struct kvm_device *dev,
>   1772				     struct kvm_device_attr *attr)
>   1773	{
>   1774		struct vgic_its *its = dev->private;
> 
> ---
> 0-DAY kernel test infrastructure                Open Source Technology Center
> https://lists.01.org/pipermail/kbuild-all                   Intel Corporation
> 
> 
> 
> _______________________________________________
> linux-arm-kernel mailing list
> linux-arm-kernel@lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
> 

^ permalink raw reply	[flat|nested] 144+ messages in thread

* [PATCH v4 13/22] KVM: arm64: ITS: KVM_DEV_ARM_VGIC_GRP_ITS_TABLES group
@ 2017-03-27 18:29       ` Auger Eric
  0 siblings, 0 replies; 144+ messages in thread
From: Auger Eric @ 2017-03-27 18:29 UTC (permalink / raw)
  To: linux-arm-kernel

Hi,

On 27/03/2017 17:04, kbuild test robot wrote:
> Hi Eric,
> 
> [auto build test ERROR on kvmarm/next]
> [also build test ERROR on v4.11-rc4 next-20170327]
> [if your patch is applied to the wrong git tree, please drop us a note to help improve the system]
> 
> url:    https://github.com/0day-ci/linux/commits/Eric-Auger/vITS-save-restore/20170327-195443
> base:   https://git.kernel.org/pub/scm/linux/kernel/git/kvmarm/kvmarm.git next
> config: arm64-defconfig (attached as .config)
> compiler: aarch64-linux-gnu-gcc (Debian 6.1.1-9) 6.1.1 20160705
> reproduce:
>         wget https://raw.githubusercontent.com/01org/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
>         chmod +x ~/bin/make.cross
>         # save the attached .config to linux build tree
>         make.cross ARCH=arm64 
> 
> All errors (new ones prefixed by >>):
> 
>    arch/arm64/kvm/../../../virt/kvm/arm/vgic/vgic-its.c: In function 'vgic_its_has_attr':
>>> arch/arm64/kvm/../../../virt/kvm/arm/vgic/vgic-its.c:1766:33: error: 'its' undeclared (first use in this function)
>       return vgic_its_table_restore(its);

I think this is due to the fact the series is applied on KVM: arm/arm64:
Emulate the EL1 phys timer registers (kvmarm-for-4.11).

Please apply it to (kvmarm/queue, kvmarm/next, kvm_next) KVM: arm/arm64:
vgic: Improve sync_hwstate performance  (255905e)
I also checked it compiles on 4.11-rc4.

Please let me know if I got something wrong.

Thanks

Eric
>                                     ^~~
>    arch/arm64/kvm/../../../virt/kvm/arm/vgic/vgic-its.c:1766:33: note: each undeclared identifier is reported only once for each function it appears in
> 
> vim +/its +1766 arch/arm64/kvm/../../../virt/kvm/arm/vgic/vgic-its.c
> 
>   1750			case KVM_DEV_ARM_VGIC_CTRL_INIT:
>   1751				return 0;
>   1752			}
>   1753			break;
>   1754		case KVM_DEV_ARM_VGIC_GRP_ITS_REGS: {
>   1755			u64 __user *uaddr = (u64 __user *)(long)attr->addr;
>   1756			u64 reg;
>   1757	
>   1758			if (get_user(reg, uaddr))
>   1759				return -EFAULT;
>   1760	
>   1761			return vgic_its_attr_regs_access(dev, attr, &reg, true);
>   1762		}
>   1763		case KVM_DEV_ARM_VGIC_GRP_ITS_TABLES:
>   1764			if (attr->attr)
>   1765				return -EINVAL;
>> 1766			return vgic_its_table_restore(its);
>   1767		}
>   1768		return -ENXIO;
>   1769	}
>   1770	
>   1771	static int vgic_its_set_attr(struct kvm_device *dev,
>   1772				     struct kvm_device_attr *attr)
>   1773	{
>   1774		struct vgic_its *its = dev->private;
> 
> ---
> 0-DAY kernel test infrastructure                Open Source Technology Center
> https://lists.01.org/pipermail/kbuild-all                   Intel Corporation
> 
> 
> 
> _______________________________________________
> linux-arm-kernel mailing list
> linux-arm-kernel at lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
> 

^ permalink raw reply	[flat|nested] 144+ messages in thread

* Re: [kbuild-all] [PATCH v4 13/22] KVM: arm64: ITS: KVM_DEV_ARM_VGIC_GRP_ITS_TABLES group
  2017-03-27 18:29       ` Auger Eric
@ 2017-03-30  2:21         ` Ye Xiaolong
  -1 siblings, 0 replies; 144+ messages in thread
From: Ye Xiaolong @ 2017-03-30  2:21 UTC (permalink / raw)
  To: Auger Eric
  Cc: kbuild test robot, peter.maydell, drjones, christoffer.dall, kvm,
	Prasun.Kapoor, marc.zyngier, andre.przywara, quintela, dgilbert,
	Vijaya.Kumar, vijayak, kbuild-all, pbonzini, kvmarm,
	linux-arm-kernel, eric.auger.pro

Hi, Eric

On 03/27, Auger Eric wrote:
>Hi,
>
>On 27/03/2017 17:04, kbuild test robot wrote:
>> Hi Eric,
>> 
>> [auto build test ERROR on kvmarm/next]
>> [also build test ERROR on v4.11-rc4 next-20170327]
>> [if your patch is applied to the wrong git tree, please drop us a note to help improve the system]
>> 
>> url:    https://github.com/0day-ci/linux/commits/Eric-Auger/vITS-save-restore/20170327-195443
>> base:   https://git.kernel.org/pub/scm/linux/kernel/git/kvmarm/kvmarm.git next
>> config: arm64-defconfig (attached as .config)
>> compiler: aarch64-linux-gnu-gcc (Debian 6.1.1-9) 6.1.1 20160705
>> reproduce:
>>         wget https://raw.githubusercontent.com/01org/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
>>         chmod +x ~/bin/make.cross
>>         # save the attached .config to linux build tree
>>         make.cross ARCH=arm64 
>> 
>> All errors (new ones prefixed by >>):
>> 
>>    arch/arm64/kvm/../../../virt/kvm/arm/vgic/vgic-its.c: In function 'vgic_its_has_attr':
>>>> arch/arm64/kvm/../../../virt/kvm/arm/vgic/vgic-its.c:1766:33: error: 'its' undeclared (first use in this function)
>>       return vgic_its_table_restore(its);
>
>I think this is due to the fact the series is applied on KVM: arm/arm64:
>Emulate the EL1 phys timer registers (kvmarm-for-4.11).
>
>Please apply it to (kvmarm/queue, kvmarm/next, kvm_next) KVM: arm/arm64:
>vgic: Improve sync_hwstate performance  (255905e)
>I also checked it compiles on 4.11-rc4.

Hmm, we did apply your series on top of kvarm/next, judging from the function
code below, I can't see the 'its' declaration. 

static int vgic_its_has_attr(struct kvm_device *dev,
                             struct kvm_device_attr *attr)
{
        switch (attr->group) {
        case KVM_DEV_ARM_VGIC_GRP_ADDR:
                switch (attr->attr) {
                case KVM_VGIC_ITS_ADDR_TYPE:
                        return 0;
                }
                break;
        case KVM_DEV_ARM_VGIC_GRP_CTRL:
                switch (attr->attr) {
                case KVM_DEV_ARM_VGIC_CTRL_INIT:
                        return 0;
                }
                break;
        case KVM_DEV_ARM_VGIC_GRP_ITS_REGS: {
                u64 __user *uaddr = (u64 __user *)(long)attr->addr;
                u64 reg;

                if (get_user(reg, uaddr))
                        return -EFAULT;

                return vgic_its_attr_regs_access(dev, attr, &reg, true);
        }
        case KVM_DEV_ARM_VGIC_GRP_ITS_TABLES:
                if (attr->attr)
                        return -EINVAL;
                return vgic_its_table_restore(its);
        }
        return -ENXIO;
}

Thanks,
Xiaolong

>
>Please let me know if I got something wrong.
>
>Thanks
>
>Eric
>>                                     ^~~
>>    arch/arm64/kvm/../../../virt/kvm/arm/vgic/vgic-its.c:1766:33: note: each undeclared identifier is reported only once for each function it appears in
>> 
>> vim +/its +1766 arch/arm64/kvm/../../../virt/kvm/arm/vgic/vgic-its.c
>> 
>>   1750			case KVM_DEV_ARM_VGIC_CTRL_INIT:
>>   1751				return 0;
>>   1752			}
>>   1753			break;
>>   1754		case KVM_DEV_ARM_VGIC_GRP_ITS_REGS: {
>>   1755			u64 __user *uaddr = (u64 __user *)(long)attr->addr;
>>   1756			u64 reg;
>>   1757	
>>   1758			if (get_user(reg, uaddr))
>>   1759				return -EFAULT;
>>   1760	
>>   1761			return vgic_its_attr_regs_access(dev, attr, &reg, true);
>>   1762		}
>>   1763		case KVM_DEV_ARM_VGIC_GRP_ITS_TABLES:
>>   1764			if (attr->attr)
>>   1765				return -EINVAL;
>>> 1766			return vgic_its_table_restore(its);
>>   1767		}
>>   1768		return -ENXIO;
>>   1769	}
>>   1770	
>>   1771	static int vgic_its_set_attr(struct kvm_device *dev,
>>   1772				     struct kvm_device_attr *attr)
>>   1773	{
>>   1774		struct vgic_its *its = dev->private;
>> 
>> ---
>> 0-DAY kernel test infrastructure                Open Source Technology Center
>> https://lists.01.org/pipermail/kbuild-all                   Intel Corporation
>> 
>> 
>> 
>> _______________________________________________
>> linux-arm-kernel mailing list
>> linux-arm-kernel@lists.infradead.org
>> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
>> 
>_______________________________________________
>kbuild-all mailing list
>kbuild-all@lists.01.org
>https://lists.01.org/mailman/listinfo/kbuild-all

^ permalink raw reply	[flat|nested] 144+ messages in thread

* [kbuild-all] [PATCH v4 13/22] KVM: arm64: ITS: KVM_DEV_ARM_VGIC_GRP_ITS_TABLES group
@ 2017-03-30  2:21         ` Ye Xiaolong
  0 siblings, 0 replies; 144+ messages in thread
From: Ye Xiaolong @ 2017-03-30  2:21 UTC (permalink / raw)
  To: linux-arm-kernel

Hi, Eric

On 03/27, Auger Eric wrote:
>Hi,
>
>On 27/03/2017 17:04, kbuild test robot wrote:
>> Hi Eric,
>> 
>> [auto build test ERROR on kvmarm/next]
>> [also build test ERROR on v4.11-rc4 next-20170327]
>> [if your patch is applied to the wrong git tree, please drop us a note to help improve the system]
>> 
>> url:    https://github.com/0day-ci/linux/commits/Eric-Auger/vITS-save-restore/20170327-195443
>> base:   https://git.kernel.org/pub/scm/linux/kernel/git/kvmarm/kvmarm.git next
>> config: arm64-defconfig (attached as .config)
>> compiler: aarch64-linux-gnu-gcc (Debian 6.1.1-9) 6.1.1 20160705
>> reproduce:
>>         wget https://raw.githubusercontent.com/01org/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
>>         chmod +x ~/bin/make.cross
>>         # save the attached .config to linux build tree
>>         make.cross ARCH=arm64 
>> 
>> All errors (new ones prefixed by >>):
>> 
>>    arch/arm64/kvm/../../../virt/kvm/arm/vgic/vgic-its.c: In function 'vgic_its_has_attr':
>>>> arch/arm64/kvm/../../../virt/kvm/arm/vgic/vgic-its.c:1766:33: error: 'its' undeclared (first use in this function)
>>       return vgic_its_table_restore(its);
>
>I think this is due to the fact the series is applied on KVM: arm/arm64:
>Emulate the EL1 phys timer registers (kvmarm-for-4.11).
>
>Please apply it to (kvmarm/queue, kvmarm/next, kvm_next) KVM: arm/arm64:
>vgic: Improve sync_hwstate performance  (255905e)
>I also checked it compiles on 4.11-rc4.

Hmm, we did apply your series on top of kvarm/next, judging from the function
code below, I can't see the 'its' declaration. 

static int vgic_its_has_attr(struct kvm_device *dev,
                             struct kvm_device_attr *attr)
{
        switch (attr->group) {
        case KVM_DEV_ARM_VGIC_GRP_ADDR:
                switch (attr->attr) {
                case KVM_VGIC_ITS_ADDR_TYPE:
                        return 0;
                }
                break;
        case KVM_DEV_ARM_VGIC_GRP_CTRL:
                switch (attr->attr) {
                case KVM_DEV_ARM_VGIC_CTRL_INIT:
                        return 0;
                }
                break;
        case KVM_DEV_ARM_VGIC_GRP_ITS_REGS: {
                u64 __user *uaddr = (u64 __user *)(long)attr->addr;
                u64 reg;

                if (get_user(reg, uaddr))
                        return -EFAULT;

                return vgic_its_attr_regs_access(dev, attr, &reg, true);
        }
        case KVM_DEV_ARM_VGIC_GRP_ITS_TABLES:
                if (attr->attr)
                        return -EINVAL;
                return vgic_its_table_restore(its);
        }
        return -ENXIO;
}

Thanks,
Xiaolong

>
>Please let me know if I got something wrong.
>
>Thanks
>
>Eric
>>                                     ^~~
>>    arch/arm64/kvm/../../../virt/kvm/arm/vgic/vgic-its.c:1766:33: note: each undeclared identifier is reported only once for each function it appears in
>> 
>> vim +/its +1766 arch/arm64/kvm/../../../virt/kvm/arm/vgic/vgic-its.c
>> 
>>   1750			case KVM_DEV_ARM_VGIC_CTRL_INIT:
>>   1751				return 0;
>>   1752			}
>>   1753			break;
>>   1754		case KVM_DEV_ARM_VGIC_GRP_ITS_REGS: {
>>   1755			u64 __user *uaddr = (u64 __user *)(long)attr->addr;
>>   1756			u64 reg;
>>   1757	
>>   1758			if (get_user(reg, uaddr))
>>   1759				return -EFAULT;
>>   1760	
>>   1761			return vgic_its_attr_regs_access(dev, attr, &reg, true);
>>   1762		}
>>   1763		case KVM_DEV_ARM_VGIC_GRP_ITS_TABLES:
>>   1764			if (attr->attr)
>>   1765				return -EINVAL;
>>> 1766			return vgic_its_table_restore(its);
>>   1767		}
>>   1768		return -ENXIO;
>>   1769	}
>>   1770	
>>   1771	static int vgic_its_set_attr(struct kvm_device *dev,
>>   1772				     struct kvm_device_attr *attr)
>>   1773	{
>>   1774		struct vgic_its *its = dev->private;
>> 
>> ---
>> 0-DAY kernel test infrastructure                Open Source Technology Center
>> https://lists.01.org/pipermail/kbuild-all                   Intel Corporation
>> 
>> 
>> 
>> _______________________________________________
>> linux-arm-kernel mailing list
>> linux-arm-kernel at lists.infradead.org
>> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
>> 
>_______________________________________________
>kbuild-all mailing list
>kbuild-all at lists.01.org
>https://lists.01.org/mailman/listinfo/kbuild-all

^ permalink raw reply	[flat|nested] 144+ messages in thread

* Re: [kbuild-all] [PATCH v4 13/22] KVM: arm64: ITS: KVM_DEV_ARM_VGIC_GRP_ITS_TABLES group
  2017-03-30  2:21         ` Ye Xiaolong
@ 2017-03-30  6:46           ` Auger Eric
  -1 siblings, 0 replies; 144+ messages in thread
From: Auger Eric @ 2017-03-30  6:46 UTC (permalink / raw)
  To: Ye Xiaolong
  Cc: kbuild test robot, kvm, Prasun.Kapoor, marc.zyngier,
	andre.przywara, quintela, dgilbert, Vijaya.Kumar, vijayak,
	kbuild-all, pbonzini, kvmarm, linux-arm-kernel, eric.auger.pro

Hi Xiaolong

On 30/03/2017 04:21, Ye Xiaolong wrote:
> Hi, Eric
> 
> On 03/27, Auger Eric wrote:
>> Hi,
>>
>> On 27/03/2017 17:04, kbuild test robot wrote:
>>> Hi Eric,
>>>
>>> [auto build test ERROR on kvmarm/next]
>>> [also build test ERROR on v4.11-rc4 next-20170327]
>>> [if your patch is applied to the wrong git tree, please drop us a note to help improve the system]
>>>
>>> url:    https://github.com/0day-ci/linux/commits/Eric-Auger/vITS-save-restore/20170327-195443
>>> base:   https://git.kernel.org/pub/scm/linux/kernel/git/kvmarm/kvmarm.git next
>>> config: arm64-defconfig (attached as .config)
>>> compiler: aarch64-linux-gnu-gcc (Debian 6.1.1-9) 6.1.1 20160705
>>> reproduce:
>>>         wget https://raw.githubusercontent.com/01org/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
>>>         chmod +x ~/bin/make.cross
>>>         # save the attached .config to linux build tree
>>>         make.cross ARCH=arm64 
>>>
>>> All errors (new ones prefixed by >>):
>>>
>>>    arch/arm64/kvm/../../../virt/kvm/arm/vgic/vgic-its.c: In function 'vgic_its_has_attr':
>>>>> arch/arm64/kvm/../../../virt/kvm/arm/vgic/vgic-its.c:1766:33: error: 'its' undeclared (first use in this function)
>>>       return vgic_its_table_restore(its);
>>
>> I think this is due to the fact the series is applied on KVM: arm/arm64:
>> Emulate the EL1 phys timer registers (kvmarm-for-4.11).
>>
>> Please apply it to (kvmarm/queue, kvmarm/next, kvm_next) KVM: arm/arm64:
>> vgic: Improve sync_hwstate performance  (255905e)
>> I also checked it compiles on 4.11-rc4.
> 
> Hmm, we did apply your series on top of kvarm/next, judging from the function
> code below, I can't see the 'its' declaration. 
> 
> static int vgic_its_has_attr(struct kvm_device *dev,
>                              struct kvm_device_attr *attr)
> {
>         switch (attr->group) {
>         case KVM_DEV_ARM_VGIC_GRP_ADDR:
>                 switch (attr->attr) {
>                 case KVM_VGIC_ITS_ADDR_TYPE:
>                         return 0;
>                 }
>                 break;
>         case KVM_DEV_ARM_VGIC_GRP_CTRL:
>                 switch (attr->attr) {
>                 case KVM_DEV_ARM_VGIC_CTRL_INIT:
>                         return 0;
>                 }
>                 break;
>         case KVM_DEV_ARM_VGIC_GRP_ITS_REGS: {
>                 u64 __user *uaddr = (u64 __user *)(long)attr->addr;
>                 u64 reg;
> 
>                 if (get_user(reg, uaddr))
>                         return -EFAULT;
> 
>                 return vgic_its_attr_regs_access(dev, attr, &reg, true);
>         }
>         case KVM_DEV_ARM_VGIC_GRP_ITS_TABLES:
>                 if (attr->attr)
>                         return -EINVAL;
>                 return vgic_its_table_restore(its);
The above code shows that my series is not correctly applied since that
call to vgic_its_table_restore() should normally be in
vgic_its_set_attr() and not in vgic_its_has_attr() function
(virt/kvm/arm/vgic-its.c).

I pushed this series applied on top of up to date kvmarm/next at
https://github.com/eauger/linux/tree/v4.11-rc3-its-mig-v4.

As noticed earlier, the series is applied on top of 255905e (KVM:
arm/arm64: vgic: Improve sync_hwstate performance)

Thanks

Eric


>         }
>         return -ENXIO;
> }
> 
> Thanks,
> Xiaolong
> 
>>
>> Please let me know if I got something wrong.
>>
>> Thanks
>>
>> Eric
>>>                                     ^~~
>>>    arch/arm64/kvm/../../../virt/kvm/arm/vgic/vgic-its.c:1766:33: note: each undeclared identifier is reported only once for each function it appears in
>>>
>>> vim +/its +1766 arch/arm64/kvm/../../../virt/kvm/arm/vgic/vgic-its.c
>>>
>>>   1750			case KVM_DEV_ARM_VGIC_CTRL_INIT:
>>>   1751				return 0;
>>>   1752			}
>>>   1753			break;
>>>   1754		case KVM_DEV_ARM_VGIC_GRP_ITS_REGS: {
>>>   1755			u64 __user *uaddr = (u64 __user *)(long)attr->addr;
>>>   1756			u64 reg;
>>>   1757	
>>>   1758			if (get_user(reg, uaddr))
>>>   1759				return -EFAULT;
>>>   1760	
>>>   1761			return vgic_its_attr_regs_access(dev, attr, &reg, true);
>>>   1762		}
>>>   1763		case KVM_DEV_ARM_VGIC_GRP_ITS_TABLES:
>>>   1764			if (attr->attr)
>>>   1765				return -EINVAL;
>>>> 1766			return vgic_its_table_restore(its);
>>>   1767		}
>>>   1768		return -ENXIO;
>>>   1769	}
>>>   1770	
>>>   1771	static int vgic_its_set_attr(struct kvm_device *dev,
>>>   1772				     struct kvm_device_attr *attr)
>>>   1773	{
>>>   1774		struct vgic_its *its = dev->private;
>>>
>>> ---
>>> 0-DAY kernel test infrastructure                Open Source Technology Center
>>> https://lists.01.org/pipermail/kbuild-all                   Intel Corporation
>>>
>>>
>>>
>>> _______________________________________________
>>> linux-arm-kernel mailing list
>>> linux-arm-kernel@lists.infradead.org
>>> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
>>>
>> _______________________________________________
>> kbuild-all mailing list
>> kbuild-all@lists.01.org
>> https://lists.01.org/mailman/listinfo/kbuild-all
> 
> _______________________________________________
> linux-arm-kernel mailing list
> linux-arm-kernel@lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
> 

^ permalink raw reply	[flat|nested] 144+ messages in thread

* [kbuild-all] [PATCH v4 13/22] KVM: arm64: ITS: KVM_DEV_ARM_VGIC_GRP_ITS_TABLES group
@ 2017-03-30  6:46           ` Auger Eric
  0 siblings, 0 replies; 144+ messages in thread
From: Auger Eric @ 2017-03-30  6:46 UTC (permalink / raw)
  To: linux-arm-kernel

Hi Xiaolong

On 30/03/2017 04:21, Ye Xiaolong wrote:
> Hi, Eric
> 
> On 03/27, Auger Eric wrote:
>> Hi,
>>
>> On 27/03/2017 17:04, kbuild test robot wrote:
>>> Hi Eric,
>>>
>>> [auto build test ERROR on kvmarm/next]
>>> [also build test ERROR on v4.11-rc4 next-20170327]
>>> [if your patch is applied to the wrong git tree, please drop us a note to help improve the system]
>>>
>>> url:    https://github.com/0day-ci/linux/commits/Eric-Auger/vITS-save-restore/20170327-195443
>>> base:   https://git.kernel.org/pub/scm/linux/kernel/git/kvmarm/kvmarm.git next
>>> config: arm64-defconfig (attached as .config)
>>> compiler: aarch64-linux-gnu-gcc (Debian 6.1.1-9) 6.1.1 20160705
>>> reproduce:
>>>         wget https://raw.githubusercontent.com/01org/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
>>>         chmod +x ~/bin/make.cross
>>>         # save the attached .config to linux build tree
>>>         make.cross ARCH=arm64 
>>>
>>> All errors (new ones prefixed by >>):
>>>
>>>    arch/arm64/kvm/../../../virt/kvm/arm/vgic/vgic-its.c: In function 'vgic_its_has_attr':
>>>>> arch/arm64/kvm/../../../virt/kvm/arm/vgic/vgic-its.c:1766:33: error: 'its' undeclared (first use in this function)
>>>       return vgic_its_table_restore(its);
>>
>> I think this is due to the fact the series is applied on KVM: arm/arm64:
>> Emulate the EL1 phys timer registers (kvmarm-for-4.11).
>>
>> Please apply it to (kvmarm/queue, kvmarm/next, kvm_next) KVM: arm/arm64:
>> vgic: Improve sync_hwstate performance  (255905e)
>> I also checked it compiles on 4.11-rc4.
> 
> Hmm, we did apply your series on top of kvarm/next, judging from the function
> code below, I can't see the 'its' declaration. 
> 
> static int vgic_its_has_attr(struct kvm_device *dev,
>                              struct kvm_device_attr *attr)
> {
>         switch (attr->group) {
>         case KVM_DEV_ARM_VGIC_GRP_ADDR:
>                 switch (attr->attr) {
>                 case KVM_VGIC_ITS_ADDR_TYPE:
>                         return 0;
>                 }
>                 break;
>         case KVM_DEV_ARM_VGIC_GRP_CTRL:
>                 switch (attr->attr) {
>                 case KVM_DEV_ARM_VGIC_CTRL_INIT:
>                         return 0;
>                 }
>                 break;
>         case KVM_DEV_ARM_VGIC_GRP_ITS_REGS: {
>                 u64 __user *uaddr = (u64 __user *)(long)attr->addr;
>                 u64 reg;
> 
>                 if (get_user(reg, uaddr))
>                         return -EFAULT;
> 
>                 return vgic_its_attr_regs_access(dev, attr, &reg, true);
>         }
>         case KVM_DEV_ARM_VGIC_GRP_ITS_TABLES:
>                 if (attr->attr)
>                         return -EINVAL;
>                 return vgic_its_table_restore(its);
The above code shows that my series is not correctly applied since that
call to vgic_its_table_restore() should normally be in
vgic_its_set_attr() and not in vgic_its_has_attr() function
(virt/kvm/arm/vgic-its.c).

I pushed this series applied on top of up to date kvmarm/next at
https://github.com/eauger/linux/tree/v4.11-rc3-its-mig-v4.

As noticed earlier, the series is applied on top of 255905e (KVM:
arm/arm64: vgic: Improve sync_hwstate performance)

Thanks

Eric


>         }
>         return -ENXIO;
> }
> 
> Thanks,
> Xiaolong
> 
>>
>> Please let me know if I got something wrong.
>>
>> Thanks
>>
>> Eric
>>>                                     ^~~
>>>    arch/arm64/kvm/../../../virt/kvm/arm/vgic/vgic-its.c:1766:33: note: each undeclared identifier is reported only once for each function it appears in
>>>
>>> vim +/its +1766 arch/arm64/kvm/../../../virt/kvm/arm/vgic/vgic-its.c
>>>
>>>   1750			case KVM_DEV_ARM_VGIC_CTRL_INIT:
>>>   1751				return 0;
>>>   1752			}
>>>   1753			break;
>>>   1754		case KVM_DEV_ARM_VGIC_GRP_ITS_REGS: {
>>>   1755			u64 __user *uaddr = (u64 __user *)(long)attr->addr;
>>>   1756			u64 reg;
>>>   1757	
>>>   1758			if (get_user(reg, uaddr))
>>>   1759				return -EFAULT;
>>>   1760	
>>>   1761			return vgic_its_attr_regs_access(dev, attr, &reg, true);
>>>   1762		}
>>>   1763		case KVM_DEV_ARM_VGIC_GRP_ITS_TABLES:
>>>   1764			if (attr->attr)
>>>   1765				return -EINVAL;
>>>> 1766			return vgic_its_table_restore(its);
>>>   1767		}
>>>   1768		return -ENXIO;
>>>   1769	}
>>>   1770	
>>>   1771	static int vgic_its_set_attr(struct kvm_device *dev,
>>>   1772				     struct kvm_device_attr *attr)
>>>   1773	{
>>>   1774		struct vgic_its *its = dev->private;
>>>
>>> ---
>>> 0-DAY kernel test infrastructure                Open Source Technology Center
>>> https://lists.01.org/pipermail/kbuild-all                   Intel Corporation
>>>
>>>
>>>
>>> _______________________________________________
>>> linux-arm-kernel mailing list
>>> linux-arm-kernel at lists.infradead.org
>>> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
>>>
>> _______________________________________________
>> kbuild-all mailing list
>> kbuild-all at lists.01.org
>> https://lists.01.org/mailman/listinfo/kbuild-all
> 
> _______________________________________________
> linux-arm-kernel mailing list
> linux-arm-kernel at lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
> 

^ permalink raw reply	[flat|nested] 144+ messages in thread

* Re: [kbuild-all] [PATCH v4 13/22] KVM: arm64: ITS: KVM_DEV_ARM_VGIC_GRP_ITS_TABLES group
  2017-03-30  6:46           ` Auger Eric
@ 2017-03-30  7:29             ` Ye Xiaolong
  -1 siblings, 0 replies; 144+ messages in thread
From: Ye Xiaolong @ 2017-03-30  7:29 UTC (permalink / raw)
  To: Auger Eric
  Cc: linux-arm-kernel, peter.maydell, drjones, kbuild test robot, kvm,
	Prasun.Kapoor, marc.zyngier, andre.przywara, quintela, dgilbert,
	Vijaya.Kumar, vijayak, kbuild-all, pbonzini, kvmarm,
	christoffer.dall, eric.auger.pro

On 03/30, Auger Eric wrote:
>Hi Xiaolong
>
>On 30/03/2017 04:21, Ye Xiaolong wrote:
>> Hi, Eric
>> 
>> On 03/27, Auger Eric wrote:
>>> Hi,
>>>
>>> On 27/03/2017 17:04, kbuild test robot wrote:
>>>> Hi Eric,
>>>>
>>>> [auto build test ERROR on kvmarm/next]
>>>> [also build test ERROR on v4.11-rc4 next-20170327]
>>>> [if your patch is applied to the wrong git tree, please drop us a note to help improve the system]
>>>>
>>>> url:    https://github.com/0day-ci/linux/commits/Eric-Auger/vITS-save-restore/20170327-195443
>>>> base:   https://git.kernel.org/pub/scm/linux/kernel/git/kvmarm/kvmarm.git next
>>>> config: arm64-defconfig (attached as .config)
>>>> compiler: aarch64-linux-gnu-gcc (Debian 6.1.1-9) 6.1.1 20160705
>>>> reproduce:
>>>>         wget https://raw.githubusercontent.com/01org/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
>>>>         chmod +x ~/bin/make.cross
>>>>         # save the attached .config to linux build tree
>>>>         make.cross ARCH=arm64 
>>>>
>>>> All errors (new ones prefixed by >>):
>>>>
>>>>    arch/arm64/kvm/../../../virt/kvm/arm/vgic/vgic-its.c: In function 'vgic_its_has_attr':
>>>>>> arch/arm64/kvm/../../../virt/kvm/arm/vgic/vgic-its.c:1766:33: error: 'its' undeclared (first use in this function)
>>>>       return vgic_its_table_restore(its);
>>>
>>> I think this is due to the fact the series is applied on KVM: arm/arm64:
>>> Emulate the EL1 phys timer registers (kvmarm-for-4.11).
>>>
>>> Please apply it to (kvmarm/queue, kvmarm/next, kvm_next) KVM: arm/arm64:
>>> vgic: Improve sync_hwstate performance  (255905e)
>>> I also checked it compiles on 4.11-rc4.
>> 
>> Hmm, we did apply your series on top of kvarm/next, judging from the function
>> code below, I can't see the 'its' declaration. 
>> 
>> static int vgic_its_has_attr(struct kvm_device *dev,
>>                              struct kvm_device_attr *attr)
>> {
>>         switch (attr->group) {
>>         case KVM_DEV_ARM_VGIC_GRP_ADDR:
>>                 switch (attr->attr) {
>>                 case KVM_VGIC_ITS_ADDR_TYPE:
>>                         return 0;
>>                 }
>>                 break;
>>         case KVM_DEV_ARM_VGIC_GRP_CTRL:
>>                 switch (attr->attr) {
>>                 case KVM_DEV_ARM_VGIC_CTRL_INIT:
>>                         return 0;
>>                 }
>>                 break;
>>         case KVM_DEV_ARM_VGIC_GRP_ITS_REGS: {
>>                 u64 __user *uaddr = (u64 __user *)(long)attr->addr;
>>                 u64 reg;
>> 
>>                 if (get_user(reg, uaddr))
>>                         return -EFAULT;
>> 
>>                 return vgic_its_attr_regs_access(dev, attr, &reg, true);
>>         }
>>         case KVM_DEV_ARM_VGIC_GRP_ITS_TABLES:
>>                 if (attr->attr)
>>                         return -EINVAL;
>>                 return vgic_its_table_restore(its);
>The above code shows that my series is not correctly applied since that
>call to vgic_its_table_restore() should normally be in
>vgic_its_set_attr() and not in vgic_its_has_attr() function
>(virt/kvm/arm/vgic-its.c).
>

Er, you are right, the real problem here seems we had a rather old kvmarm/next mirror
at the time 0day applied your series.

Thanks for the clarification and sorry for the noise.

Thanks,
Xiaolong
>I pushed this series applied on top of up to date kvmarm/next at
>https://github.com/eauger/linux/tree/v4.11-rc3-its-mig-v4.
>
>As noticed earlier, the series is applied on top of 255905e (KVM:
>arm/arm64: vgic: Improve sync_hwstate performance)
>
>Thanks
>
>Eric
>
>
>>         }
>>         return -ENXIO;
>> }
>> 
>> Thanks,
>> Xiaolong
>> 
>>>
>>> Please let me know if I got something wrong.
>>>
>>> Thanks
>>>
>>> Eric
>>>>                                     ^~~
>>>>    arch/arm64/kvm/../../../virt/kvm/arm/vgic/vgic-its.c:1766:33: note: each undeclared identifier is reported only once for each function it appears in
>>>>
>>>> vim +/its +1766 arch/arm64/kvm/../../../virt/kvm/arm/vgic/vgic-its.c
>>>>
>>>>   1750			case KVM_DEV_ARM_VGIC_CTRL_INIT:
>>>>   1751				return 0;
>>>>   1752			}
>>>>   1753			break;
>>>>   1754		case KVM_DEV_ARM_VGIC_GRP_ITS_REGS: {
>>>>   1755			u64 __user *uaddr = (u64 __user *)(long)attr->addr;
>>>>   1756			u64 reg;
>>>>   1757	
>>>>   1758			if (get_user(reg, uaddr))
>>>>   1759				return -EFAULT;
>>>>   1760	
>>>>   1761			return vgic_its_attr_regs_access(dev, attr, &reg, true);
>>>>   1762		}
>>>>   1763		case KVM_DEV_ARM_VGIC_GRP_ITS_TABLES:
>>>>   1764			if (attr->attr)
>>>>   1765				return -EINVAL;
>>>>> 1766			return vgic_its_table_restore(its);
>>>>   1767		}
>>>>   1768		return -ENXIO;
>>>>   1769	}
>>>>   1770	
>>>>   1771	static int vgic_its_set_attr(struct kvm_device *dev,
>>>>   1772				     struct kvm_device_attr *attr)
>>>>   1773	{
>>>>   1774		struct vgic_its *its = dev->private;
>>>>
>>>> ---
>>>> 0-DAY kernel test infrastructure                Open Source Technology Center
>>>> https://lists.01.org/pipermail/kbuild-all                   Intel Corporation
>>>>
>>>>
>>>>
>>>> _______________________________________________
>>>> linux-arm-kernel mailing list
>>>> linux-arm-kernel@lists.infradead.org
>>>> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
>>>>
>>> _______________________________________________
>>> kbuild-all mailing list
>>> kbuild-all@lists.01.org
>>> https://lists.01.org/mailman/listinfo/kbuild-all
>> 
>> _______________________________________________
>> linux-arm-kernel mailing list
>> linux-arm-kernel@lists.infradead.org
>> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
>> 

^ permalink raw reply	[flat|nested] 144+ messages in thread

* [kbuild-all] [PATCH v4 13/22] KVM: arm64: ITS: KVM_DEV_ARM_VGIC_GRP_ITS_TABLES group
@ 2017-03-30  7:29             ` Ye Xiaolong
  0 siblings, 0 replies; 144+ messages in thread
From: Ye Xiaolong @ 2017-03-30  7:29 UTC (permalink / raw)
  To: linux-arm-kernel

On 03/30, Auger Eric wrote:
>Hi Xiaolong
>
>On 30/03/2017 04:21, Ye Xiaolong wrote:
>> Hi, Eric
>> 
>> On 03/27, Auger Eric wrote:
>>> Hi,
>>>
>>> On 27/03/2017 17:04, kbuild test robot wrote:
>>>> Hi Eric,
>>>>
>>>> [auto build test ERROR on kvmarm/next]
>>>> [also build test ERROR on v4.11-rc4 next-20170327]
>>>> [if your patch is applied to the wrong git tree, please drop us a note to help improve the system]
>>>>
>>>> url:    https://github.com/0day-ci/linux/commits/Eric-Auger/vITS-save-restore/20170327-195443
>>>> base:   https://git.kernel.org/pub/scm/linux/kernel/git/kvmarm/kvmarm.git next
>>>> config: arm64-defconfig (attached as .config)
>>>> compiler: aarch64-linux-gnu-gcc (Debian 6.1.1-9) 6.1.1 20160705
>>>> reproduce:
>>>>         wget https://raw.githubusercontent.com/01org/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
>>>>         chmod +x ~/bin/make.cross
>>>>         # save the attached .config to linux build tree
>>>>         make.cross ARCH=arm64 
>>>>
>>>> All errors (new ones prefixed by >>):
>>>>
>>>>    arch/arm64/kvm/../../../virt/kvm/arm/vgic/vgic-its.c: In function 'vgic_its_has_attr':
>>>>>> arch/arm64/kvm/../../../virt/kvm/arm/vgic/vgic-its.c:1766:33: error: 'its' undeclared (first use in this function)
>>>>       return vgic_its_table_restore(its);
>>>
>>> I think this is due to the fact the series is applied on KVM: arm/arm64:
>>> Emulate the EL1 phys timer registers (kvmarm-for-4.11).
>>>
>>> Please apply it to (kvmarm/queue, kvmarm/next, kvm_next) KVM: arm/arm64:
>>> vgic: Improve sync_hwstate performance  (255905e)
>>> I also checked it compiles on 4.11-rc4.
>> 
>> Hmm, we did apply your series on top of kvarm/next, judging from the function
>> code below, I can't see the 'its' declaration. 
>> 
>> static int vgic_its_has_attr(struct kvm_device *dev,
>>                              struct kvm_device_attr *attr)
>> {
>>         switch (attr->group) {
>>         case KVM_DEV_ARM_VGIC_GRP_ADDR:
>>                 switch (attr->attr) {
>>                 case KVM_VGIC_ITS_ADDR_TYPE:
>>                         return 0;
>>                 }
>>                 break;
>>         case KVM_DEV_ARM_VGIC_GRP_CTRL:
>>                 switch (attr->attr) {
>>                 case KVM_DEV_ARM_VGIC_CTRL_INIT:
>>                         return 0;
>>                 }
>>                 break;
>>         case KVM_DEV_ARM_VGIC_GRP_ITS_REGS: {
>>                 u64 __user *uaddr = (u64 __user *)(long)attr->addr;
>>                 u64 reg;
>> 
>>                 if (get_user(reg, uaddr))
>>                         return -EFAULT;
>> 
>>                 return vgic_its_attr_regs_access(dev, attr, &reg, true);
>>         }
>>         case KVM_DEV_ARM_VGIC_GRP_ITS_TABLES:
>>                 if (attr->attr)
>>                         return -EINVAL;
>>                 return vgic_its_table_restore(its);
>The above code shows that my series is not correctly applied since that
>call to vgic_its_table_restore() should normally be in
>vgic_its_set_attr() and not in vgic_its_has_attr() function
>(virt/kvm/arm/vgic-its.c).
>

Er, you are right, the real problem here seems we had a rather old kvmarm/next mirror
at the time 0day applied your series.

Thanks for the clarification and sorry for the noise.

Thanks,
Xiaolong
>I pushed this series applied on top of up to date kvmarm/next at
>https://github.com/eauger/linux/tree/v4.11-rc3-its-mig-v4.
>
>As noticed earlier, the series is applied on top of 255905e (KVM:
>arm/arm64: vgic: Improve sync_hwstate performance)
>
>Thanks
>
>Eric
>
>
>>         }
>>         return -ENXIO;
>> }
>> 
>> Thanks,
>> Xiaolong
>> 
>>>
>>> Please let me know if I got something wrong.
>>>
>>> Thanks
>>>
>>> Eric
>>>>                                     ^~~
>>>>    arch/arm64/kvm/../../../virt/kvm/arm/vgic/vgic-its.c:1766:33: note: each undeclared identifier is reported only once for each function it appears in
>>>>
>>>> vim +/its +1766 arch/arm64/kvm/../../../virt/kvm/arm/vgic/vgic-its.c
>>>>
>>>>   1750			case KVM_DEV_ARM_VGIC_CTRL_INIT:
>>>>   1751				return 0;
>>>>   1752			}
>>>>   1753			break;
>>>>   1754		case KVM_DEV_ARM_VGIC_GRP_ITS_REGS: {
>>>>   1755			u64 __user *uaddr = (u64 __user *)(long)attr->addr;
>>>>   1756			u64 reg;
>>>>   1757	
>>>>   1758			if (get_user(reg, uaddr))
>>>>   1759				return -EFAULT;
>>>>   1760	
>>>>   1761			return vgic_its_attr_regs_access(dev, attr, &reg, true);
>>>>   1762		}
>>>>   1763		case KVM_DEV_ARM_VGIC_GRP_ITS_TABLES:
>>>>   1764			if (attr->attr)
>>>>   1765				return -EINVAL;
>>>>> 1766			return vgic_its_table_restore(its);
>>>>   1767		}
>>>>   1768		return -ENXIO;
>>>>   1769	}
>>>>   1770	
>>>>   1771	static int vgic_its_set_attr(struct kvm_device *dev,
>>>>   1772				     struct kvm_device_attr *attr)
>>>>   1773	{
>>>>   1774		struct vgic_its *its = dev->private;
>>>>
>>>> ---
>>>> 0-DAY kernel test infrastructure                Open Source Technology Center
>>>> https://lists.01.org/pipermail/kbuild-all                   Intel Corporation
>>>>
>>>>
>>>>
>>>> _______________________________________________
>>>> linux-arm-kernel mailing list
>>>> linux-arm-kernel at lists.infradead.org
>>>> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
>>>>
>>> _______________________________________________
>>> kbuild-all mailing list
>>> kbuild-all at lists.01.org
>>> https://lists.01.org/mailman/listinfo/kbuild-all
>> 
>> _______________________________________________
>> linux-arm-kernel mailing list
>> linux-arm-kernel at lists.infradead.org
>> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
>> 

^ permalink raw reply	[flat|nested] 144+ messages in thread

* Re: [kbuild-all] [PATCH v4 13/22] KVM: arm64: ITS: KVM_DEV_ARM_VGIC_GRP_ITS_TABLES group
  2017-03-30  7:29             ` Ye Xiaolong
@ 2017-03-30  8:29               ` Auger Eric
  -1 siblings, 0 replies; 144+ messages in thread
From: Auger Eric @ 2017-03-30  8:29 UTC (permalink / raw)
  To: Ye Xiaolong
  Cc: kbuild test robot, kvm, Prasun.Kapoor, marc.zyngier,
	andre.przywara, quintela, dgilbert, Vijaya.Kumar, vijayak,
	kbuild-all, pbonzini, kvmarm, linux-arm-kernel, eric.auger.pro

Hi Xiaolong,

On 30/03/2017 09:29, Ye Xiaolong wrote:
> On 03/30, Auger Eric wrote:
>> Hi Xiaolong
>>
>> On 30/03/2017 04:21, Ye Xiaolong wrote:
>>> Hi, Eric
>>>
>>> On 03/27, Auger Eric wrote:
>>>> Hi,
>>>>
>>>> On 27/03/2017 17:04, kbuild test robot wrote:
>>>>> Hi Eric,
>>>>>
>>>>> [auto build test ERROR on kvmarm/next]
>>>>> [also build test ERROR on v4.11-rc4 next-20170327]
>>>>> [if your patch is applied to the wrong git tree, please drop us a note to help improve the system]
>>>>>
>>>>> url:    https://github.com/0day-ci/linux/commits/Eric-Auger/vITS-save-restore/20170327-195443
>>>>> base:   https://git.kernel.org/pub/scm/linux/kernel/git/kvmarm/kvmarm.git next
>>>>> config: arm64-defconfig (attached as .config)
>>>>> compiler: aarch64-linux-gnu-gcc (Debian 6.1.1-9) 6.1.1 20160705
>>>>> reproduce:
>>>>>         wget https://raw.githubusercontent.com/01org/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
>>>>>         chmod +x ~/bin/make.cross
>>>>>         # save the attached .config to linux build tree
>>>>>         make.cross ARCH=arm64 
>>>>>
>>>>> All errors (new ones prefixed by >>):
>>>>>
>>>>>    arch/arm64/kvm/../../../virt/kvm/arm/vgic/vgic-its.c: In function 'vgic_its_has_attr':
>>>>>>> arch/arm64/kvm/../../../virt/kvm/arm/vgic/vgic-its.c:1766:33: error: 'its' undeclared (first use in this function)
>>>>>       return vgic_its_table_restore(its);
>>>>
>>>> I think this is due to the fact the series is applied on KVM: arm/arm64:
>>>> Emulate the EL1 phys timer registers (kvmarm-for-4.11).
>>>>
>>>> Please apply it to (kvmarm/queue, kvmarm/next, kvm_next) KVM: arm/arm64:
>>>> vgic: Improve sync_hwstate performance  (255905e)
>>>> I also checked it compiles on 4.11-rc4.
>>>
>>> Hmm, we did apply your series on top of kvarm/next, judging from the function
>>> code below, I can't see the 'its' declaration. 
>>>
>>> static int vgic_its_has_attr(struct kvm_device *dev,
>>>                              struct kvm_device_attr *attr)
>>> {
>>>         switch (attr->group) {
>>>         case KVM_DEV_ARM_VGIC_GRP_ADDR:
>>>                 switch (attr->attr) {
>>>                 case KVM_VGIC_ITS_ADDR_TYPE:
>>>                         return 0;
>>>                 }
>>>                 break;
>>>         case KVM_DEV_ARM_VGIC_GRP_CTRL:
>>>                 switch (attr->attr) {
>>>                 case KVM_DEV_ARM_VGIC_CTRL_INIT:
>>>                         return 0;
>>>                 }
>>>                 break;
>>>         case KVM_DEV_ARM_VGIC_GRP_ITS_REGS: {
>>>                 u64 __user *uaddr = (u64 __user *)(long)attr->addr;
>>>                 u64 reg;
>>>
>>>                 if (get_user(reg, uaddr))
>>>                         return -EFAULT;
>>>
>>>                 return vgic_its_attr_regs_access(dev, attr, &reg, true);
>>>         }
>>>         case KVM_DEV_ARM_VGIC_GRP_ITS_TABLES:
>>>                 if (attr->attr)
>>>                         return -EINVAL;
>>>                 return vgic_its_table_restore(its);
>> The above code shows that my series is not correctly applied since that
>> call to vgic_its_table_restore() should normally be in
>> vgic_its_set_attr() and not in vgic_its_has_attr() function
>> (virt/kvm/arm/vgic-its.c).
>>
> 
> Er, you are right, the real problem here seems we had a rather old kvmarm/next mirror
> at the time 0day applied your series.
> 
> Thanks for the clarification and sorry for the noise.

no worries

Thanks

Eric
> 
> Thanks,
> Xiaolong
>> I pushed this series applied on top of up to date kvmarm/next at
>> https://github.com/eauger/linux/tree/v4.11-rc3-its-mig-v4.
>>
>> As noticed earlier, the series is applied on top of 255905e (KVM:
>> arm/arm64: vgic: Improve sync_hwstate performance)
>>
>> Thanks
>>
>> Eric
>>
>>
>>>         }
>>>         return -ENXIO;
>>> }
>>>
>>> Thanks,
>>> Xiaolong
>>>
>>>>
>>>> Please let me know if I got something wrong.
>>>>
>>>> Thanks
>>>>
>>>> Eric
>>>>>                                     ^~~
>>>>>    arch/arm64/kvm/../../../virt/kvm/arm/vgic/vgic-its.c:1766:33: note: each undeclared identifier is reported only once for each function it appears in
>>>>>
>>>>> vim +/its +1766 arch/arm64/kvm/../../../virt/kvm/arm/vgic/vgic-its.c
>>>>>
>>>>>   1750			case KVM_DEV_ARM_VGIC_CTRL_INIT:
>>>>>   1751				return 0;
>>>>>   1752			}
>>>>>   1753			break;
>>>>>   1754		case KVM_DEV_ARM_VGIC_GRP_ITS_REGS: {
>>>>>   1755			u64 __user *uaddr = (u64 __user *)(long)attr->addr;
>>>>>   1756			u64 reg;
>>>>>   1757	
>>>>>   1758			if (get_user(reg, uaddr))
>>>>>   1759				return -EFAULT;
>>>>>   1760	
>>>>>   1761			return vgic_its_attr_regs_access(dev, attr, &reg, true);
>>>>>   1762		}
>>>>>   1763		case KVM_DEV_ARM_VGIC_GRP_ITS_TABLES:
>>>>>   1764			if (attr->attr)
>>>>>   1765				return -EINVAL;
>>>>>> 1766			return vgic_its_table_restore(its);
>>>>>   1767		}
>>>>>   1768		return -ENXIO;
>>>>>   1769	}
>>>>>   1770	
>>>>>   1771	static int vgic_its_set_attr(struct kvm_device *dev,
>>>>>   1772				     struct kvm_device_attr *attr)
>>>>>   1773	{
>>>>>   1774		struct vgic_its *its = dev->private;
>>>>>
>>>>> ---
>>>>> 0-DAY kernel test infrastructure                Open Source Technology Center
>>>>> https://lists.01.org/pipermail/kbuild-all                   Intel Corporation
>>>>>
>>>>>
>>>>>
>>>>> _______________________________________________
>>>>> linux-arm-kernel mailing list
>>>>> linux-arm-kernel@lists.infradead.org
>>>>> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
>>>>>
>>>> _______________________________________________
>>>> kbuild-all mailing list
>>>> kbuild-all@lists.01.org
>>>> https://lists.01.org/mailman/listinfo/kbuild-all
>>>
>>> _______________________________________________
>>> linux-arm-kernel mailing list
>>> linux-arm-kernel@lists.infradead.org
>>> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
>>>

^ permalink raw reply	[flat|nested] 144+ messages in thread

* [kbuild-all] [PATCH v4 13/22] KVM: arm64: ITS: KVM_DEV_ARM_VGIC_GRP_ITS_TABLES group
@ 2017-03-30  8:29               ` Auger Eric
  0 siblings, 0 replies; 144+ messages in thread
From: Auger Eric @ 2017-03-30  8:29 UTC (permalink / raw)
  To: linux-arm-kernel

Hi Xiaolong,

On 30/03/2017 09:29, Ye Xiaolong wrote:
> On 03/30, Auger Eric wrote:
>> Hi Xiaolong
>>
>> On 30/03/2017 04:21, Ye Xiaolong wrote:
>>> Hi, Eric
>>>
>>> On 03/27, Auger Eric wrote:
>>>> Hi,
>>>>
>>>> On 27/03/2017 17:04, kbuild test robot wrote:
>>>>> Hi Eric,
>>>>>
>>>>> [auto build test ERROR on kvmarm/next]
>>>>> [also build test ERROR on v4.11-rc4 next-20170327]
>>>>> [if your patch is applied to the wrong git tree, please drop us a note to help improve the system]
>>>>>
>>>>> url:    https://github.com/0day-ci/linux/commits/Eric-Auger/vITS-save-restore/20170327-195443
>>>>> base:   https://git.kernel.org/pub/scm/linux/kernel/git/kvmarm/kvmarm.git next
>>>>> config: arm64-defconfig (attached as .config)
>>>>> compiler: aarch64-linux-gnu-gcc (Debian 6.1.1-9) 6.1.1 20160705
>>>>> reproduce:
>>>>>         wget https://raw.githubusercontent.com/01org/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
>>>>>         chmod +x ~/bin/make.cross
>>>>>         # save the attached .config to linux build tree
>>>>>         make.cross ARCH=arm64 
>>>>>
>>>>> All errors (new ones prefixed by >>):
>>>>>
>>>>>    arch/arm64/kvm/../../../virt/kvm/arm/vgic/vgic-its.c: In function 'vgic_its_has_attr':
>>>>>>> arch/arm64/kvm/../../../virt/kvm/arm/vgic/vgic-its.c:1766:33: error: 'its' undeclared (first use in this function)
>>>>>       return vgic_its_table_restore(its);
>>>>
>>>> I think this is due to the fact the series is applied on KVM: arm/arm64:
>>>> Emulate the EL1 phys timer registers (kvmarm-for-4.11).
>>>>
>>>> Please apply it to (kvmarm/queue, kvmarm/next, kvm_next) KVM: arm/arm64:
>>>> vgic: Improve sync_hwstate performance  (255905e)
>>>> I also checked it compiles on 4.11-rc4.
>>>
>>> Hmm, we did apply your series on top of kvarm/next, judging from the function
>>> code below, I can't see the 'its' declaration. 
>>>
>>> static int vgic_its_has_attr(struct kvm_device *dev,
>>>                              struct kvm_device_attr *attr)
>>> {
>>>         switch (attr->group) {
>>>         case KVM_DEV_ARM_VGIC_GRP_ADDR:
>>>                 switch (attr->attr) {
>>>                 case KVM_VGIC_ITS_ADDR_TYPE:
>>>                         return 0;
>>>                 }
>>>                 break;
>>>         case KVM_DEV_ARM_VGIC_GRP_CTRL:
>>>                 switch (attr->attr) {
>>>                 case KVM_DEV_ARM_VGIC_CTRL_INIT:
>>>                         return 0;
>>>                 }
>>>                 break;
>>>         case KVM_DEV_ARM_VGIC_GRP_ITS_REGS: {
>>>                 u64 __user *uaddr = (u64 __user *)(long)attr->addr;
>>>                 u64 reg;
>>>
>>>                 if (get_user(reg, uaddr))
>>>                         return -EFAULT;
>>>
>>>                 return vgic_its_attr_regs_access(dev, attr, &reg, true);
>>>         }
>>>         case KVM_DEV_ARM_VGIC_GRP_ITS_TABLES:
>>>                 if (attr->attr)
>>>                         return -EINVAL;
>>>                 return vgic_its_table_restore(its);
>> The above code shows that my series is not correctly applied since that
>> call to vgic_its_table_restore() should normally be in
>> vgic_its_set_attr() and not in vgic_its_has_attr() function
>> (virt/kvm/arm/vgic-its.c).
>>
> 
> Er, you are right, the real problem here seems we had a rather old kvmarm/next mirror
> at the time 0day applied your series.
> 
> Thanks for the clarification and sorry for the noise.

no worries

Thanks

Eric
> 
> Thanks,
> Xiaolong
>> I pushed this series applied on top of up to date kvmarm/next at
>> https://github.com/eauger/linux/tree/v4.11-rc3-its-mig-v4.
>>
>> As noticed earlier, the series is applied on top of 255905e (KVM:
>> arm/arm64: vgic: Improve sync_hwstate performance)
>>
>> Thanks
>>
>> Eric
>>
>>
>>>         }
>>>         return -ENXIO;
>>> }
>>>
>>> Thanks,
>>> Xiaolong
>>>
>>>>
>>>> Please let me know if I got something wrong.
>>>>
>>>> Thanks
>>>>
>>>> Eric
>>>>>                                     ^~~
>>>>>    arch/arm64/kvm/../../../virt/kvm/arm/vgic/vgic-its.c:1766:33: note: each undeclared identifier is reported only once for each function it appears in
>>>>>
>>>>> vim +/its +1766 arch/arm64/kvm/../../../virt/kvm/arm/vgic/vgic-its.c
>>>>>
>>>>>   1750			case KVM_DEV_ARM_VGIC_CTRL_INIT:
>>>>>   1751				return 0;
>>>>>   1752			}
>>>>>   1753			break;
>>>>>   1754		case KVM_DEV_ARM_VGIC_GRP_ITS_REGS: {
>>>>>   1755			u64 __user *uaddr = (u64 __user *)(long)attr->addr;
>>>>>   1756			u64 reg;
>>>>>   1757	
>>>>>   1758			if (get_user(reg, uaddr))
>>>>>   1759				return -EFAULT;
>>>>>   1760	
>>>>>   1761			return vgic_its_attr_regs_access(dev, attr, &reg, true);
>>>>>   1762		}
>>>>>   1763		case KVM_DEV_ARM_VGIC_GRP_ITS_TABLES:
>>>>>   1764			if (attr->attr)
>>>>>   1765				return -EINVAL;
>>>>>> 1766			return vgic_its_table_restore(its);
>>>>>   1767		}
>>>>>   1768		return -ENXIO;
>>>>>   1769	}
>>>>>   1770	
>>>>>   1771	static int vgic_its_set_attr(struct kvm_device *dev,
>>>>>   1772				     struct kvm_device_attr *attr)
>>>>>   1773	{
>>>>>   1774		struct vgic_its *its = dev->private;
>>>>>
>>>>> ---
>>>>> 0-DAY kernel test infrastructure                Open Source Technology Center
>>>>> https://lists.01.org/pipermail/kbuild-all                   Intel Corporation
>>>>>
>>>>>
>>>>>
>>>>> _______________________________________________
>>>>> linux-arm-kernel mailing list
>>>>> linux-arm-kernel at lists.infradead.org
>>>>> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
>>>>>
>>>> _______________________________________________
>>>> kbuild-all mailing list
>>>> kbuild-all at lists.01.org
>>>> https://lists.01.org/mailman/listinfo/kbuild-all
>>>
>>> _______________________________________________
>>> linux-arm-kernel mailing list
>>> linux-arm-kernel at lists.infradead.org
>>> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
>>>

^ permalink raw reply	[flat|nested] 144+ messages in thread

* Re: [PATCH v4 01/22] KVM: arm/arm64: Add vITS save/restore API documentation
  2017-03-27  9:30   ` Eric Auger
@ 2017-04-08 10:03     ` Marc Zyngier
  -1 siblings, 0 replies; 144+ messages in thread
From: Marc Zyngier @ 2017-04-08 10:03 UTC (permalink / raw)
  To: Eric Auger
  Cc: kvm, Prasun.Kapoor, vijayak, andre.przywara, quintela, dgilbert,
	Vijaya.Kumar, linux-arm-kernel, pbonzini, kvmarm, eric.auger.pro

On Mon, Mar 27 2017 at 10:30:51 AM, Eric Auger <eric.auger@redhat.com> wrote:
> Add description for how to access vITS registers and how to flush/restore
> vITS tables into/from memory
>
> Signed-off-by: Eric Auger <eric.auger@redhat.com>
>
> ---
> v3 -> v4:
> - take into account Peter's comments:
>   - typos
>   - KVM_DEV_ARM_VGIC_GRP_ITS_TABLES kvm_device_attr = 0
>   - add a validity bit in DTE
>   - document all fields in CTE and ITE
>   - document ABI revision
> - take into account Andre's comments:
>   - document restrictions about GITS_CREADR writing and GITS_IIDR
>   - document -EBUSY error if one or more VCPUS are runnning
>   - document 64b registers only can be accessed with 64b access
> - itt_addr field matches bits [51:8] of the itt_addr
>
> v1 -> v2:
> - DTE and ITE now are 8 bytes
> - DTE and ITE now indexed by deviceid/eventid
> - use ITE name instead of ITTE
> - mentions ITT_addr matches bits [51:8] of the actual address
> - mentions LE layout
> ---
>  Documentation/virtual/kvm/devices/arm-vgic-its.txt | 118 +++++++++++++++++++++
>  1 file changed, 118 insertions(+)
>
> diff --git a/Documentation/virtual/kvm/devices/arm-vgic-its.txt b/Documentation/virtual/kvm/devices/arm-vgic-its.txt
> index 6081a5b..0902d20 100644
> --- a/Documentation/virtual/kvm/devices/arm-vgic-its.txt
> +++ b/Documentation/virtual/kvm/devices/arm-vgic-its.txt
> @@ -36,3 +36,121 @@ Groups:
>      -ENXIO:  ITS not properly configured as required prior to setting
>               this attribute
>      -ENOMEM: Memory shortage when allocating ITS internal data
> +
> +  KVM_DEV_ARM_VGIC_GRP_ITS_REGS
> +  Attributes:
> +      The attr field of kvm_device_attr encodes the offset of the
> +      ITS register, relative to the ITS control frame base address
> +      (ITS_base).
> +
> +      kvm_device_attr.addr points to a __u64 value whatever the width
> +      of the addressed register (32/64 bits). 64 bit registers can only
> +      be accessed with full length.
> +
> +      Writes to read-only registers are ignored by the kernel except for:
> +      - GITS_READR. It needs to be restored otherwise commands in the queue
> +        will be re-executed after CWRITER setting. Writing this register is
> +        allowed if the ITS is not enabled (GITS_CTLR.enable = 0). Also it
> +        needs to be restored after GITS_CBASER since a write to GITS_CBASER
> +        resets GITS_CREADR.
> +      - GITS_IIDR. Its Revision field encodes the table layout ABI revision.
> +
> +      For other registers, getting or setting a register has the same
> +      effect as reading/writing the register on real hardware.
> +  Errors:
> +    -ENXIO: Offset does not correspond to any supported register
> +    -EFAULT: Invalid user pointer for attr->addr
> +    -EINVAL: Offset is not 64-bit aligned
> +    -EBUSY: one or more VCPUS are running
> +
> +  KVM_DEV_ARM_VGIC_GRP_ITS_TABLES
> +  Attributes
> +       The attr field of kvm_device_attr must be zero.
> +
> +       request the flush-save/restore of the ITS tables, namely
> +       the device table, the collection table, all the ITT tables,
> +       the LPI pending tables. On save, the tables are flushed
> +       into guest memory at the location provisioned by the guest
> +       in GITS_BASER (device and collection tables), in the MAPD
> +       command (ITT_addr), GICR_PENDBASERs (pending tables).

May I echo Andre's concern here? Seeing the GICR_PENDBASER registers
here feels wrong. The pending table is a redistributor concept, and is
local to it. Even more, it is perfectly possible to use the
redistributors (and its pending tables) without an ITS by using the
GICR_SETLPIR registers.

Granted, we do not support this (and I'm *not* looking forward to
supporting it), but I would rather implement a redistributor flush than
using the ITS to indirectly force it. That's not how the HW works, and I
don't think we should deviate from it.

I appreciate this brings additional complexity to userspace (having to
iterate over the vcpus or the redistributors is likely more costly than
hitting the ITS which is likely to be unique), but sticking to the
letter of the architecture is probably our best bet. Each time we tried
to deviate from it, we've had to backtrack (and I'm using the royal "we"
here).

Any chance you could revisit this aspect?

Thanks,

	M.
-- 
Jazz is not dead. It just smells funny.

^ permalink raw reply	[flat|nested] 144+ messages in thread

* [PATCH v4 01/22] KVM: arm/arm64: Add vITS save/restore API documentation
@ 2017-04-08 10:03     ` Marc Zyngier
  0 siblings, 0 replies; 144+ messages in thread
From: Marc Zyngier @ 2017-04-08 10:03 UTC (permalink / raw)
  To: linux-arm-kernel

On Mon, Mar 27 2017 at 10:30:51 AM, Eric Auger <eric.auger@redhat.com> wrote:
> Add description for how to access vITS registers and how to flush/restore
> vITS tables into/from memory
>
> Signed-off-by: Eric Auger <eric.auger@redhat.com>
>
> ---
> v3 -> v4:
> - take into account Peter's comments:
>   - typos
>   - KVM_DEV_ARM_VGIC_GRP_ITS_TABLES kvm_device_attr = 0
>   - add a validity bit in DTE
>   - document all fields in CTE and ITE
>   - document ABI revision
> - take into account Andre's comments:
>   - document restrictions about GITS_CREADR writing and GITS_IIDR
>   - document -EBUSY error if one or more VCPUS are runnning
>   - document 64b registers only can be accessed with 64b access
> - itt_addr field matches bits [51:8] of the itt_addr
>
> v1 -> v2:
> - DTE and ITE now are 8 bytes
> - DTE and ITE now indexed by deviceid/eventid
> - use ITE name instead of ITTE
> - mentions ITT_addr matches bits [51:8] of the actual address
> - mentions LE layout
> ---
>  Documentation/virtual/kvm/devices/arm-vgic-its.txt | 118 +++++++++++++++++++++
>  1 file changed, 118 insertions(+)
>
> diff --git a/Documentation/virtual/kvm/devices/arm-vgic-its.txt b/Documentation/virtual/kvm/devices/arm-vgic-its.txt
> index 6081a5b..0902d20 100644
> --- a/Documentation/virtual/kvm/devices/arm-vgic-its.txt
> +++ b/Documentation/virtual/kvm/devices/arm-vgic-its.txt
> @@ -36,3 +36,121 @@ Groups:
>      -ENXIO:  ITS not properly configured as required prior to setting
>               this attribute
>      -ENOMEM: Memory shortage when allocating ITS internal data
> +
> +  KVM_DEV_ARM_VGIC_GRP_ITS_REGS
> +  Attributes:
> +      The attr field of kvm_device_attr encodes the offset of the
> +      ITS register, relative to the ITS control frame base address
> +      (ITS_base).
> +
> +      kvm_device_attr.addr points to a __u64 value whatever the width
> +      of the addressed register (32/64 bits). 64 bit registers can only
> +      be accessed with full length.
> +
> +      Writes to read-only registers are ignored by the kernel except for:
> +      - GITS_READR. It needs to be restored otherwise commands in the queue
> +        will be re-executed after CWRITER setting. Writing this register is
> +        allowed if the ITS is not enabled (GITS_CTLR.enable = 0). Also it
> +        needs to be restored after GITS_CBASER since a write to GITS_CBASER
> +        resets GITS_CREADR.
> +      - GITS_IIDR. Its Revision field encodes the table layout ABI revision.
> +
> +      For other registers, getting or setting a register has the same
> +      effect as reading/writing the register on real hardware.
> +  Errors:
> +    -ENXIO: Offset does not correspond to any supported register
> +    -EFAULT: Invalid user pointer for attr->addr
> +    -EINVAL: Offset is not 64-bit aligned
> +    -EBUSY: one or more VCPUS are running
> +
> +  KVM_DEV_ARM_VGIC_GRP_ITS_TABLES
> +  Attributes
> +       The attr field of kvm_device_attr must be zero.
> +
> +       request the flush-save/restore of the ITS tables, namely
> +       the device table, the collection table, all the ITT tables,
> +       the LPI pending tables. On save, the tables are flushed
> +       into guest memory at the location provisioned by the guest
> +       in GITS_BASER (device and collection tables), in the MAPD
> +       command (ITT_addr), GICR_PENDBASERs (pending tables).

May I echo Andre's concern here? Seeing the GICR_PENDBASER registers
here feels wrong. The pending table is a redistributor concept, and is
local to it. Even more, it is perfectly possible to use the
redistributors (and its pending tables) without an ITS by using the
GICR_SETLPIR registers.

Granted, we do not support this (and I'm *not* looking forward to
supporting it), but I would rather implement a redistributor flush than
using the ITS to indirectly force it. That's not how the HW works, and I
don't think we should deviate from it.

I appreciate this brings additional complexity to userspace (having to
iterate over the vcpus or the redistributors is likely more costly than
hitting the ITS which is likely to be unique), but sticking to the
letter of the architecture is probably our best bet. Each time we tried
to deviate from it, we've had to backtrack (and I'm using the royal "we"
here).

Any chance you could revisit this aspect?

Thanks,

	M.
-- 
Jazz is not dead. It just smells funny.

^ permalink raw reply	[flat|nested] 144+ messages in thread

* Re: [PATCH v4 02/22] KVM: arm/arm64: rename itte into ite
  2017-03-27  9:30   ` Eric Auger
@ 2017-04-08 10:04     ` Marc Zyngier
  -1 siblings, 0 replies; 144+ messages in thread
From: Marc Zyngier @ 2017-04-08 10:04 UTC (permalink / raw)
  To: Eric Auger
  Cc: kvm, Prasun.Kapoor, vijayak, andre.przywara, quintela, dgilbert,
	Vijaya.Kumar, linux-arm-kernel, pbonzini, kvmarm, eric.auger.pro

On Mon, Mar 27 2017 at 10:30:52 AM, Eric Auger <eric.auger@redhat.com> wrote:
> The actual abbreviation for the interrupt translation table entry
> is ITE. Let's rename all itte instances by ite.
>
> Signed-off-by: Eric Auger <eric.auger@redhat.com>

Acked-by: Marc Zyngier <marc.zyngier@arm.com>

	M.
-- 
Jazz is not dead. It just smells funny.

^ permalink raw reply	[flat|nested] 144+ messages in thread

* [PATCH v4 02/22] KVM: arm/arm64: rename itte into ite
@ 2017-04-08 10:04     ` Marc Zyngier
  0 siblings, 0 replies; 144+ messages in thread
From: Marc Zyngier @ 2017-04-08 10:04 UTC (permalink / raw)
  To: linux-arm-kernel

On Mon, Mar 27 2017 at 10:30:52 AM, Eric Auger <eric.auger@redhat.com> wrote:
> The actual abbreviation for the interrupt translation table entry
> is ITE. Let's rename all itte instances by ite.
>
> Signed-off-by: Eric Auger <eric.auger@redhat.com>

Acked-by: Marc Zyngier <marc.zyngier@arm.com>

	M.
-- 
Jazz is not dead. It just smells funny.

^ permalink raw reply	[flat|nested] 144+ messages in thread

* Re: [PATCH v4 03/22] arm/arm64: vgic: turn vgic_find_mmio_region into public
  2017-03-27  9:30   ` Eric Auger
  (?)
@ 2017-04-08 10:06     ` Marc Zyngier
  -1 siblings, 0 replies; 144+ messages in thread
From: Marc Zyngier @ 2017-04-08 10:06 UTC (permalink / raw)
  To: Eric Auger
  Cc: eric.auger.pro, christoffer.dall, andre.przywara, vijayak,
	Vijaya.Kumar, peter.maydell, linux-arm-kernel, kvmarm, kvm,
	Prasun.Kapoor, drjones, pbonzini, dgilbert, quintela

On Mon, Mar 27 2017 at 10:30:53 AM, Eric Auger <eric.auger@redhat.com> wrote:
> We plan to use vgic_find_mmio_region in vgic-its.c so let's
> turn it into a public function.
>
> Also let's take the opportunity to rename the region parameter
> into regions to emphasize this latter is an array of regions.
>
> Signed-off-by: Eric Auger <eric.auger@redhat.com>
> Reviewed-by: Andre Przywara <andre.przywara@arm.com>

Acked-by: Marc Zyngier <marc.zyngier@arm.com>

	M.
-- 
Jazz is not dead. It just smells funny.

^ permalink raw reply	[flat|nested] 144+ messages in thread

* Re: [PATCH v4 03/22] arm/arm64: vgic: turn vgic_find_mmio_region into public
@ 2017-04-08 10:06     ` Marc Zyngier
  0 siblings, 0 replies; 144+ messages in thread
From: Marc Zyngier @ 2017-04-08 10:06 UTC (permalink / raw)
  To: Eric Auger
  Cc: eric.auger.pro, christoffer.dall, andre.przywara, vijayak,
	Vijaya.Kumar, peter.maydell, linux-arm-kernel, kvmarm, kvm,
	Prasun.Kapoor, drjones, pbonzini, dgilbert, quintela

On Mon, Mar 27 2017 at 10:30:53 AM, Eric Auger <eric.auger@redhat.com> wrote:
> We plan to use vgic_find_mmio_region in vgic-its.c so let's
> turn it into a public function.
>
> Also let's take the opportunity to rename the region parameter
> into regions to emphasize this latter is an array of regions.
>
> Signed-off-by: Eric Auger <eric.auger@redhat.com>
> Reviewed-by: Andre Przywara <andre.przywara@arm.com>

Acked-by: Marc Zyngier <marc.zyngier@arm.com>

	M.
-- 
Jazz is not dead. It just smells funny.

^ permalink raw reply	[flat|nested] 144+ messages in thread

* [PATCH v4 03/22] arm/arm64: vgic: turn vgic_find_mmio_region into public
@ 2017-04-08 10:06     ` Marc Zyngier
  0 siblings, 0 replies; 144+ messages in thread
From: Marc Zyngier @ 2017-04-08 10:06 UTC (permalink / raw)
  To: linux-arm-kernel

On Mon, Mar 27 2017 at 10:30:53 AM, Eric Auger <eric.auger@redhat.com> wrote:
> We plan to use vgic_find_mmio_region in vgic-its.c so let's
> turn it into a public function.
>
> Also let's take the opportunity to rename the region parameter
> into regions to emphasize this latter is an array of regions.
>
> Signed-off-by: Eric Auger <eric.auger@redhat.com>
> Reviewed-by: Andre Przywara <andre.przywara@arm.com>

Acked-by: Marc Zyngier <marc.zyngier@arm.com>

	M.
-- 
Jazz is not dead. It just smells funny.

^ permalink raw reply	[flat|nested] 144+ messages in thread

* Re: [PATCH v4 04/22] KVM: arm64: ITS: KVM_DEV_ARM_VGIC_GRP_ITS_REGS group
  2017-03-27  9:30   ` Eric Auger
@ 2017-04-08 10:07     ` Marc Zyngier
  -1 siblings, 0 replies; 144+ messages in thread
From: Marc Zyngier @ 2017-04-08 10:07 UTC (permalink / raw)
  To: Eric Auger
  Cc: kvm, Prasun.Kapoor, vijayak, andre.przywara, quintela, dgilbert,
	Vijaya.Kumar, linux-arm-kernel, pbonzini, kvmarm, eric.auger.pro

On Mon, Mar 27 2017 at 10:30:54 AM, Eric Auger <eric.auger@redhat.com> wrote:
> The ITS KVM device exposes a new KVM_DEV_ARM_VGIC_GRP_ITS_REGS
> group which allows the userspace to save/restore ITS registers.
>
> At this stage the get/set/has operations are not yet implemented.
>
> Signed-off-by: Eric Auger <eric.auger@redhat.com>
> Reviewed-by: Andre Przywara <andre.przywara@arm.com>

Acked-by: Marc Zyngier <marc.zyngier@arm.com>

	M.
-- 
Jazz is not dead. It just smells funny.

^ permalink raw reply	[flat|nested] 144+ messages in thread

* [PATCH v4 04/22] KVM: arm64: ITS: KVM_DEV_ARM_VGIC_GRP_ITS_REGS group
@ 2017-04-08 10:07     ` Marc Zyngier
  0 siblings, 0 replies; 144+ messages in thread
From: Marc Zyngier @ 2017-04-08 10:07 UTC (permalink / raw)
  To: linux-arm-kernel

On Mon, Mar 27 2017 at 10:30:54 AM, Eric Auger <eric.auger@redhat.com> wrote:
> The ITS KVM device exposes a new KVM_DEV_ARM_VGIC_GRP_ITS_REGS
> group which allows the userspace to save/restore ITS registers.
>
> At this stage the get/set/has operations are not yet implemented.
>
> Signed-off-by: Eric Auger <eric.auger@redhat.com>
> Reviewed-by: Andre Przywara <andre.przywara@arm.com>

Acked-by: Marc Zyngier <marc.zyngier@arm.com>

	M.
-- 
Jazz is not dead. It just smells funny.

^ permalink raw reply	[flat|nested] 144+ messages in thread

* Re: [PATCH v4 05/22] KVM: arm/arm64: vgic: expose (un)lock_all_vcpus
  2017-03-27  9:30   ` Eric Auger
@ 2017-04-08 10:09     ` Marc Zyngier
  -1 siblings, 0 replies; 144+ messages in thread
From: Marc Zyngier @ 2017-04-08 10:09 UTC (permalink / raw)
  To: Eric Auger
  Cc: kvm, Prasun.Kapoor, vijayak, andre.przywara, quintela, dgilbert,
	Vijaya.Kumar, linux-arm-kernel, pbonzini, kvmarm, eric.auger.pro

On Mon, Mar 27 2017 at 10:30:55 AM, Eric Auger <eric.auger@redhat.com> wrote:
> We need to use those helpers in vgic-its.c so let's
> expose them in the private vgic header.
>
> Signed-off-by: Eric Auger <eric.auger@redhat.com>

Acked-by: Marc Zyngier <marc.zyngier@arm.com>

	M.
-- 
Jazz is not dead. It just smells funny.

^ permalink raw reply	[flat|nested] 144+ messages in thread

* [PATCH v4 05/22] KVM: arm/arm64: vgic: expose (un)lock_all_vcpus
@ 2017-04-08 10:09     ` Marc Zyngier
  0 siblings, 0 replies; 144+ messages in thread
From: Marc Zyngier @ 2017-04-08 10:09 UTC (permalink / raw)
  To: linux-arm-kernel

On Mon, Mar 27 2017 at 10:30:55 AM, Eric Auger <eric.auger@redhat.com> wrote:
> We need to use those helpers in vgic-its.c so let's
> expose them in the private vgic header.
>
> Signed-off-by: Eric Auger <eric.auger@redhat.com>

Acked-by: Marc Zyngier <marc.zyngier@arm.com>

	M.
-- 
Jazz is not dead. It just smells funny.

^ permalink raw reply	[flat|nested] 144+ messages in thread

* Re: [PATCH v4 06/22] KVM: arm64: ITS: Implement vgic_its_has_attr_regs and attr_regs_access
  2017-03-27  9:30   ` Eric Auger
  (?)
@ 2017-04-08 10:24     ` Marc Zyngier
  -1 siblings, 0 replies; 144+ messages in thread
From: Marc Zyngier @ 2017-04-08 10:24 UTC (permalink / raw)
  To: Eric Auger
  Cc: eric.auger.pro, christoffer.dall, andre.przywara, vijayak,
	Vijaya.Kumar, peter.maydell, linux-arm-kernel, kvmarm, kvm,
	Prasun.Kapoor, drjones, pbonzini, dgilbert, quintela

On Mon, Mar 27 2017 at 10:30:56 AM, Eric Auger <eric.auger@redhat.com> wrote:
> This patch implements vgic_its_has_attr_regs and vgic_its_attr_regs_access
> upon the MMIO framework. VGIC ITS KVM device KVM_DEV_ARM_VGIC_GRP_ITS_REGS
> group becomes functional.
>
> At least GITS_CREADR requires to differentiate a guest write action from a
> user access. As such let's introduce a new uaccess_its_write
> vgic_register_region callback.
>
> Signed-off-by: Eric Auger <eric.auger@redhat.com>
>
> ---
>
> v3 -> v4:
> - remove changes to the REGISTER_ITS_DESC macro. This will be handled in
>   subsequent patch with the introduction of a new REGISTER_ITS_DESC_UACCESS
>   macro
> - fix IIDR access and add a comment wrt full length access
> - handle endianness
> - add kvm lock and vcpus lock
> ---
>  virt/kvm/arm/vgic/vgic-its.c  | 78 +++++++++++++++++++++++++++++++++++++++++--
>  virt/kvm/arm/vgic/vgic-mmio.h |  9 +++--
>  2 files changed, 83 insertions(+), 4 deletions(-)
>
> diff --git a/virt/kvm/arm/vgic/vgic-its.c b/virt/kvm/arm/vgic/vgic-its.c
> index f687e91..9b9ea86 100644
> --- a/virt/kvm/arm/vgic/vgic-its.c
> +++ b/virt/kvm/arm/vgic/vgic-its.c
> @@ -1469,14 +1469,88 @@ static void vgic_its_destroy(struct kvm_device *kvm_dev)
>  int vgic_its_has_attr_regs(struct kvm_device *dev,
>  			   struct kvm_device_attr *attr)
>  {
> -	return -ENXIO;
> +	const struct vgic_register_region *region;
> +	struct vgic_io_device iodev = {
> +		.regions = its_registers,
> +		.nr_regions = ARRAY_SIZE(its_registers),
> +	};
> +	gpa_t offset = attr->attr;
> +
> +	region = vgic_find_mmio_region(iodev.regions,
> +				       iodev.nr_regions,
> +				       offset);
> +	if (!region)
> +		return -ENXIO;
> +
> +	return 0;
>  }
>  
>  int vgic_its_attr_regs_access(struct kvm_device *dev,
>  			      struct kvm_device_attr *attr,
>  			      u64 *reg, bool is_write)
>  {
> -	return -ENXIO;
> +	const struct vgic_register_region *region;
> +	struct vgic_io_device iodev = {
> +		.regions = its_registers,
> +		.nr_regions = ARRAY_SIZE(its_registers),
> +	};
> +	struct vgic_its *its = dev->private;
> +	gpa_t addr, offset = attr->attr;
> +	unsigned int len;
> +	unsigned long data = 0;
> +	int ret = 0;
> +
> +	/*
> +	 * Among supported registers, only GITS_CTLR (0x0) and GITS_IIDR (0x4)
> +	 * are 32 bits. Others are 64 bits.
> +	 */
> +	if ((offset < 0x8 && offset & 0x3) || (offset >= 0x8 && offset & 0x7))
> +		return -EINVAL;

Can you use the actual register names instead of raw offsets? It's
certainly be more readable.

> +
> +	mutex_lock(&dev->kvm->lock);
> +
> +	if (IS_VGIC_ADDR_UNDEF(its->vgic_its_base)) {
> +		ret = -ENXIO;
> +		goto out;
> +	}
> +
> +	region = vgic_find_mmio_region(iodev.regions,
> +				       iodev.nr_regions,
> +				       offset);
> +	if (!region) {
> +		ret = -ENXIO;
> +		goto out;
> +	}
> +
> +	if (!lock_all_vcpus(dev->kvm)) {
> +		ret = -EBUSY;
> +		goto out;
> +	}
> +
> +	addr = its->vgic_its_base + offset;
> +
> +	/*
> +	 * Only full length register accesses are supported although
> +	 * the architecture spec theoretically allows upper/lower 32
> +	 * bits to be accessed independently
> +	 */
> +	len = region->access_flags & VGIC_ACCESS_64bit ? 8 : 4;
> +
> +	if (is_write) {
> +		data = vgic_data_mmio_bus_to_host(reg, len);
> +		if (region->uaccess_its_write)
> +			region->uaccess_its_write(dev->kvm, its, addr,
> +						  len, data);
> +		else
> +			region->its_write(dev->kvm, its, addr, len, data);
> +	} else {
> +		data = region->its_read(dev->kvm, its, addr, len);
> +		vgic_data_host_to_mmio_bus(reg, len, data);
> +	}
> +	unlock_all_vcpus(dev->kvm);
> +out:
> +	mutex_unlock(&dev->kvm->lock);
> +	return ret;
>  }
>  
>  static int vgic_its_has_attr(struct kvm_device *dev,
> diff --git a/virt/kvm/arm/vgic/vgic-mmio.h b/virt/kvm/arm/vgic/vgic-mmio.h
> index 6eec91b..becc473 100644
> --- a/virt/kvm/arm/vgic/vgic-mmio.h
> +++ b/virt/kvm/arm/vgic/vgic-mmio.h
> @@ -36,8 +36,13 @@ struct vgic_register_region {
>  	};
>  	unsigned long (*uaccess_read)(struct kvm_vcpu *vcpu, gpa_t addr,
>  				      unsigned int len);
> -	void (*uaccess_write)(struct kvm_vcpu *vcpu, gpa_t addr,
> -			      unsigned int len, unsigned long val);
> +	union {
> +		void (*uaccess_write)(struct kvm_vcpu *vcpu, gpa_t addr,
> +				      unsigned int len, unsigned long val);
> +		void (*uaccess_its_write)(struct kvm *kvm, struct vgic_its *its,
> +					  gpa_t addr, unsigned int len,
> +					  unsigned long val);
> +	};
>  };
>  
>  extern struct kvm_io_device_ops kvm_io_gic_ops;

Other that that, looks good to me

Thanks,

	M.
-- 
Jazz is not dead. It just smells funny.

^ permalink raw reply	[flat|nested] 144+ messages in thread

* Re: [PATCH v4 06/22] KVM: arm64: ITS: Implement vgic_its_has_attr_regs and attr_regs_access
@ 2017-04-08 10:24     ` Marc Zyngier
  0 siblings, 0 replies; 144+ messages in thread
From: Marc Zyngier @ 2017-04-08 10:24 UTC (permalink / raw)
  To: Eric Auger
  Cc: eric.auger.pro, christoffer.dall, andre.przywara, vijayak,
	Vijaya.Kumar, peter.maydell, linux-arm-kernel, kvmarm, kvm,
	Prasun.Kapoor, drjones, pbonzini, dgilbert, quintela

On Mon, Mar 27 2017 at 10:30:56 AM, Eric Auger <eric.auger@redhat.com> wrote:
> This patch implements vgic_its_has_attr_regs and vgic_its_attr_regs_access
> upon the MMIO framework. VGIC ITS KVM device KVM_DEV_ARM_VGIC_GRP_ITS_REGS
> group becomes functional.
>
> At least GITS_CREADR requires to differentiate a guest write action from a
> user access. As such let's introduce a new uaccess_its_write
> vgic_register_region callback.
>
> Signed-off-by: Eric Auger <eric.auger@redhat.com>
>
> ---
>
> v3 -> v4:
> - remove changes to the REGISTER_ITS_DESC macro. This will be handled in
>   subsequent patch with the introduction of a new REGISTER_ITS_DESC_UACCESS
>   macro
> - fix IIDR access and add a comment wrt full length access
> - handle endianness
> - add kvm lock and vcpus lock
> ---
>  virt/kvm/arm/vgic/vgic-its.c  | 78 +++++++++++++++++++++++++++++++++++++++++--
>  virt/kvm/arm/vgic/vgic-mmio.h |  9 +++--
>  2 files changed, 83 insertions(+), 4 deletions(-)
>
> diff --git a/virt/kvm/arm/vgic/vgic-its.c b/virt/kvm/arm/vgic/vgic-its.c
> index f687e91..9b9ea86 100644
> --- a/virt/kvm/arm/vgic/vgic-its.c
> +++ b/virt/kvm/arm/vgic/vgic-its.c
> @@ -1469,14 +1469,88 @@ static void vgic_its_destroy(struct kvm_device *kvm_dev)
>  int vgic_its_has_attr_regs(struct kvm_device *dev,
>  			   struct kvm_device_attr *attr)
>  {
> -	return -ENXIO;
> +	const struct vgic_register_region *region;
> +	struct vgic_io_device iodev = {
> +		.regions = its_registers,
> +		.nr_regions = ARRAY_SIZE(its_registers),
> +	};
> +	gpa_t offset = attr->attr;
> +
> +	region = vgic_find_mmio_region(iodev.regions,
> +				       iodev.nr_regions,
> +				       offset);
> +	if (!region)
> +		return -ENXIO;
> +
> +	return 0;
>  }
>  
>  int vgic_its_attr_regs_access(struct kvm_device *dev,
>  			      struct kvm_device_attr *attr,
>  			      u64 *reg, bool is_write)
>  {
> -	return -ENXIO;
> +	const struct vgic_register_region *region;
> +	struct vgic_io_device iodev = {
> +		.regions = its_registers,
> +		.nr_regions = ARRAY_SIZE(its_registers),
> +	};
> +	struct vgic_its *its = dev->private;
> +	gpa_t addr, offset = attr->attr;
> +	unsigned int len;
> +	unsigned long data = 0;
> +	int ret = 0;
> +
> +	/*
> +	 * Among supported registers, only GITS_CTLR (0x0) and GITS_IIDR (0x4)
> +	 * are 32 bits. Others are 64 bits.
> +	 */
> +	if ((offset < 0x8 && offset & 0x3) || (offset >= 0x8 && offset & 0x7))
> +		return -EINVAL;

Can you use the actual register names instead of raw offsets? It's
certainly be more readable.

> +
> +	mutex_lock(&dev->kvm->lock);
> +
> +	if (IS_VGIC_ADDR_UNDEF(its->vgic_its_base)) {
> +		ret = -ENXIO;
> +		goto out;
> +	}
> +
> +	region = vgic_find_mmio_region(iodev.regions,
> +				       iodev.nr_regions,
> +				       offset);
> +	if (!region) {
> +		ret = -ENXIO;
> +		goto out;
> +	}
> +
> +	if (!lock_all_vcpus(dev->kvm)) {
> +		ret = -EBUSY;
> +		goto out;
> +	}
> +
> +	addr = its->vgic_its_base + offset;
> +
> +	/*
> +	 * Only full length register accesses are supported although
> +	 * the architecture spec theoretically allows upper/lower 32
> +	 * bits to be accessed independently
> +	 */
> +	len = region->access_flags & VGIC_ACCESS_64bit ? 8 : 4;
> +
> +	if (is_write) {
> +		data = vgic_data_mmio_bus_to_host(reg, len);
> +		if (region->uaccess_its_write)
> +			region->uaccess_its_write(dev->kvm, its, addr,
> +						  len, data);
> +		else
> +			region->its_write(dev->kvm, its, addr, len, data);
> +	} else {
> +		data = region->its_read(dev->kvm, its, addr, len);
> +		vgic_data_host_to_mmio_bus(reg, len, data);
> +	}
> +	unlock_all_vcpus(dev->kvm);
> +out:
> +	mutex_unlock(&dev->kvm->lock);
> +	return ret;
>  }
>  
>  static int vgic_its_has_attr(struct kvm_device *dev,
> diff --git a/virt/kvm/arm/vgic/vgic-mmio.h b/virt/kvm/arm/vgic/vgic-mmio.h
> index 6eec91b..becc473 100644
> --- a/virt/kvm/arm/vgic/vgic-mmio.h
> +++ b/virt/kvm/arm/vgic/vgic-mmio.h
> @@ -36,8 +36,13 @@ struct vgic_register_region {
>  	};
>  	unsigned long (*uaccess_read)(struct kvm_vcpu *vcpu, gpa_t addr,
>  				      unsigned int len);
> -	void (*uaccess_write)(struct kvm_vcpu *vcpu, gpa_t addr,
> -			      unsigned int len, unsigned long val);
> +	union {
> +		void (*uaccess_write)(struct kvm_vcpu *vcpu, gpa_t addr,
> +				      unsigned int len, unsigned long val);
> +		void (*uaccess_its_write)(struct kvm *kvm, struct vgic_its *its,
> +					  gpa_t addr, unsigned int len,
> +					  unsigned long val);
> +	};
>  };
>  
>  extern struct kvm_io_device_ops kvm_io_gic_ops;

Other that that, looks good to me

Thanks,

	M.
-- 
Jazz is not dead. It just smells funny.

^ permalink raw reply	[flat|nested] 144+ messages in thread

* [PATCH v4 06/22] KVM: arm64: ITS: Implement vgic_its_has_attr_regs and attr_regs_access
@ 2017-04-08 10:24     ` Marc Zyngier
  0 siblings, 0 replies; 144+ messages in thread
From: Marc Zyngier @ 2017-04-08 10:24 UTC (permalink / raw)
  To: linux-arm-kernel

On Mon, Mar 27 2017 at 10:30:56 AM, Eric Auger <eric.auger@redhat.com> wrote:
> This patch implements vgic_its_has_attr_regs and vgic_its_attr_regs_access
> upon the MMIO framework. VGIC ITS KVM device KVM_DEV_ARM_VGIC_GRP_ITS_REGS
> group becomes functional.
>
> At least GITS_CREADR requires to differentiate a guest write action from a
> user access. As such let's introduce a new uaccess_its_write
> vgic_register_region callback.
>
> Signed-off-by: Eric Auger <eric.auger@redhat.com>
>
> ---
>
> v3 -> v4:
> - remove changes to the REGISTER_ITS_DESC macro. This will be handled in
>   subsequent patch with the introduction of a new REGISTER_ITS_DESC_UACCESS
>   macro
> - fix IIDR access and add a comment wrt full length access
> - handle endianness
> - add kvm lock and vcpus lock
> ---
>  virt/kvm/arm/vgic/vgic-its.c  | 78 +++++++++++++++++++++++++++++++++++++++++--
>  virt/kvm/arm/vgic/vgic-mmio.h |  9 +++--
>  2 files changed, 83 insertions(+), 4 deletions(-)
>
> diff --git a/virt/kvm/arm/vgic/vgic-its.c b/virt/kvm/arm/vgic/vgic-its.c
> index f687e91..9b9ea86 100644
> --- a/virt/kvm/arm/vgic/vgic-its.c
> +++ b/virt/kvm/arm/vgic/vgic-its.c
> @@ -1469,14 +1469,88 @@ static void vgic_its_destroy(struct kvm_device *kvm_dev)
>  int vgic_its_has_attr_regs(struct kvm_device *dev,
>  			   struct kvm_device_attr *attr)
>  {
> -	return -ENXIO;
> +	const struct vgic_register_region *region;
> +	struct vgic_io_device iodev = {
> +		.regions = its_registers,
> +		.nr_regions = ARRAY_SIZE(its_registers),
> +	};
> +	gpa_t offset = attr->attr;
> +
> +	region = vgic_find_mmio_region(iodev.regions,
> +				       iodev.nr_regions,
> +				       offset);
> +	if (!region)
> +		return -ENXIO;
> +
> +	return 0;
>  }
>  
>  int vgic_its_attr_regs_access(struct kvm_device *dev,
>  			      struct kvm_device_attr *attr,
>  			      u64 *reg, bool is_write)
>  {
> -	return -ENXIO;
> +	const struct vgic_register_region *region;
> +	struct vgic_io_device iodev = {
> +		.regions = its_registers,
> +		.nr_regions = ARRAY_SIZE(its_registers),
> +	};
> +	struct vgic_its *its = dev->private;
> +	gpa_t addr, offset = attr->attr;
> +	unsigned int len;
> +	unsigned long data = 0;
> +	int ret = 0;
> +
> +	/*
> +	 * Among supported registers, only GITS_CTLR (0x0) and GITS_IIDR (0x4)
> +	 * are 32 bits. Others are 64 bits.
> +	 */
> +	if ((offset < 0x8 && offset & 0x3) || (offset >= 0x8 && offset & 0x7))
> +		return -EINVAL;

Can you use the actual register names instead of raw offsets? It's
certainly be more readable.

> +
> +	mutex_lock(&dev->kvm->lock);
> +
> +	if (IS_VGIC_ADDR_UNDEF(its->vgic_its_base)) {
> +		ret = -ENXIO;
> +		goto out;
> +	}
> +
> +	region = vgic_find_mmio_region(iodev.regions,
> +				       iodev.nr_regions,
> +				       offset);
> +	if (!region) {
> +		ret = -ENXIO;
> +		goto out;
> +	}
> +
> +	if (!lock_all_vcpus(dev->kvm)) {
> +		ret = -EBUSY;
> +		goto out;
> +	}
> +
> +	addr = its->vgic_its_base + offset;
> +
> +	/*
> +	 * Only full length register accesses are supported although
> +	 * the architecture spec theoretically allows upper/lower 32
> +	 * bits to be accessed independently
> +	 */
> +	len = region->access_flags & VGIC_ACCESS_64bit ? 8 : 4;
> +
> +	if (is_write) {
> +		data = vgic_data_mmio_bus_to_host(reg, len);
> +		if (region->uaccess_its_write)
> +			region->uaccess_its_write(dev->kvm, its, addr,
> +						  len, data);
> +		else
> +			region->its_write(dev->kvm, its, addr, len, data);
> +	} else {
> +		data = region->its_read(dev->kvm, its, addr, len);
> +		vgic_data_host_to_mmio_bus(reg, len, data);
> +	}
> +	unlock_all_vcpus(dev->kvm);
> +out:
> +	mutex_unlock(&dev->kvm->lock);
> +	return ret;
>  }
>  
>  static int vgic_its_has_attr(struct kvm_device *dev,
> diff --git a/virt/kvm/arm/vgic/vgic-mmio.h b/virt/kvm/arm/vgic/vgic-mmio.h
> index 6eec91b..becc473 100644
> --- a/virt/kvm/arm/vgic/vgic-mmio.h
> +++ b/virt/kvm/arm/vgic/vgic-mmio.h
> @@ -36,8 +36,13 @@ struct vgic_register_region {
>  	};
>  	unsigned long (*uaccess_read)(struct kvm_vcpu *vcpu, gpa_t addr,
>  				      unsigned int len);
> -	void (*uaccess_write)(struct kvm_vcpu *vcpu, gpa_t addr,
> -			      unsigned int len, unsigned long val);
> +	union {
> +		void (*uaccess_write)(struct kvm_vcpu *vcpu, gpa_t addr,
> +				      unsigned int len, unsigned long val);
> +		void (*uaccess_its_write)(struct kvm *kvm, struct vgic_its *its,
> +					  gpa_t addr, unsigned int len,
> +					  unsigned long val);
> +	};
>  };
>  
>  extern struct kvm_io_device_ops kvm_io_gic_ops;

Other that that, looks good to me

Thanks,

	M.
-- 
Jazz is not dead. It just smells funny.

^ permalink raw reply	[flat|nested] 144+ messages in thread

* Re: [PATCH v4 07/22] KVM: arm64: ITS: Implement vgic_mmio_uaccess_write_its_creadr
  2017-03-27  9:30   ` Eric Auger
  (?)
@ 2017-04-08 10:36     ` Marc Zyngier
  -1 siblings, 0 replies; 144+ messages in thread
From: Marc Zyngier @ 2017-04-08 10:36 UTC (permalink / raw)
  To: Eric Auger
  Cc: eric.auger.pro, christoffer.dall, andre.przywara, vijayak,
	Vijaya.Kumar, peter.maydell, linux-arm-kernel, kvmarm, kvm,
	Prasun.Kapoor, drjones, pbonzini, dgilbert, quintela

On Mon, Mar 27 2017 at 10:30:57 AM, Eric Auger <eric.auger@redhat.com> wrote:
> GITS_CREADR needs to be restored so let's implement the associated
> uaccess_write_its callback. The write only is allowed if the its
> is disabled.
>
> Signed-off-by: Eric Auger <eric.auger@redhat.com>
>
> ---
>
> v3 -> v4:
> - REGISTER_ITS_DESC_UACCESS now introduced in this patch
> - we now check the its is disabled
> ---
>  virt/kvm/arm/vgic/vgic-its.c | 37 +++++++++++++++++++++++++++++++++++--
>  1 file changed, 35 insertions(+), 2 deletions(-)
>
> diff --git a/virt/kvm/arm/vgic/vgic-its.c b/virt/kvm/arm/vgic/vgic-its.c
> index 9b9ea86..a5f3abe 100644
> --- a/virt/kvm/arm/vgic/vgic-its.c
> +++ b/virt/kvm/arm/vgic/vgic-its.c
> @@ -1213,6 +1213,28 @@ static unsigned long vgic_mmio_read_its_creadr(struct kvm *kvm,
>  	return extract_bytes(its->creadr, addr & 0x7, len);
>  }
>  
> +static void vgic_mmio_uaccess_write_its_creadr(struct kvm *kvm,
> +					       struct vgic_its *its,
> +					       gpa_t addr, unsigned int len,
> +					       unsigned long val)
> +{
> +	u32 reg;
> +
> +	mutex_lock(&its->cmd_lock);
> +
> +	if (its->enabled)
> +		goto out;
> + 
> +	reg = update_64bit_reg(its->creadr, addr & 7, len, val);
> +	reg = ITS_CMD_OFFSET(reg);
> +	if (reg >= ITS_CMD_BUFFER_SIZE(its->cbaser))
> +		goto out;
> +
> +	its->creadr = reg;

Careful. Here, you're loosing the "Stalled" bit. We do not implement
support for it yet, but I wonder if we should preserve it. If not, we
should at least document that we're purposely stripping that bit.

> +out:
> +	mutex_unlock(&its->cmd_lock);
> +}
> +
>  #define BASER_INDEX(addr) (((addr) / sizeof(u64)) & 0x7)
>  static unsigned long vgic_mmio_read_its_baser(struct kvm *kvm,
>  					      struct vgic_its *its,
> @@ -1317,6 +1339,16 @@ static void vgic_mmio_write_its_ctlr(struct kvm *kvm, struct vgic_its *its,
>  	.its_write = wr,					\
>  }
>  
> +#define REGISTER_ITS_DESC_UACCESS(off, rd, wr, uwr, length, acc)\
> +{								\
> +	.reg_offset = off,					\
> +	.len = length,						\
> +	.access_flags = acc,					\
> +	.its_read = rd,						\
> +	.its_write = wr,					\
> +	.uaccess_its_write = uwr,				\
> +}
> +
>  static void its_mmio_write_wi(struct kvm *kvm, struct vgic_its *its,
>  			      gpa_t addr, unsigned int len, unsigned long val)
>  {
> @@ -1339,8 +1371,9 @@ static struct vgic_register_region its_registers[] = {
>  	REGISTER_ITS_DESC(GITS_CWRITER,
>  		vgic_mmio_read_its_cwriter, vgic_mmio_write_its_cwriter, 8,
>  		VGIC_ACCESS_64bit | VGIC_ACCESS_32bit),
> -	REGISTER_ITS_DESC(GITS_CREADR,
> -		vgic_mmio_read_its_creadr, its_mmio_write_wi, 8,
> +	REGISTER_ITS_DESC_UACCESS(GITS_CREADR,
> +		vgic_mmio_read_its_creadr, its_mmio_write_wi,
> +		vgic_mmio_uaccess_write_its_creadr, 8,
>  		VGIC_ACCESS_64bit | VGIC_ACCESS_32bit),
>  	REGISTER_ITS_DESC(GITS_BASER,
>  		vgic_mmio_read_its_baser, vgic_mmio_write_its_baser, 0x40,

Thanks,

	M.
-- 
Jazz is not dead. It just smells funny.

^ permalink raw reply	[flat|nested] 144+ messages in thread

* Re: [PATCH v4 07/22] KVM: arm64: ITS: Implement vgic_mmio_uaccess_write_its_creadr
@ 2017-04-08 10:36     ` Marc Zyngier
  0 siblings, 0 replies; 144+ messages in thread
From: Marc Zyngier @ 2017-04-08 10:36 UTC (permalink / raw)
  To: Eric Auger
  Cc: eric.auger.pro, christoffer.dall, andre.przywara, vijayak,
	Vijaya.Kumar, peter.maydell, linux-arm-kernel, kvmarm, kvm,
	Prasun.Kapoor, drjones, pbonzini, dgilbert, quintela

On Mon, Mar 27 2017 at 10:30:57 AM, Eric Auger <eric.auger@redhat.com> wrote:
> GITS_CREADR needs to be restored so let's implement the associated
> uaccess_write_its callback. The write only is allowed if the its
> is disabled.
>
> Signed-off-by: Eric Auger <eric.auger@redhat.com>
>
> ---
>
> v3 -> v4:
> - REGISTER_ITS_DESC_UACCESS now introduced in this patch
> - we now check the its is disabled
> ---
>  virt/kvm/arm/vgic/vgic-its.c | 37 +++++++++++++++++++++++++++++++++++--
>  1 file changed, 35 insertions(+), 2 deletions(-)
>
> diff --git a/virt/kvm/arm/vgic/vgic-its.c b/virt/kvm/arm/vgic/vgic-its.c
> index 9b9ea86..a5f3abe 100644
> --- a/virt/kvm/arm/vgic/vgic-its.c
> +++ b/virt/kvm/arm/vgic/vgic-its.c
> @@ -1213,6 +1213,28 @@ static unsigned long vgic_mmio_read_its_creadr(struct kvm *kvm,
>  	return extract_bytes(its->creadr, addr & 0x7, len);
>  }
>  
> +static void vgic_mmio_uaccess_write_its_creadr(struct kvm *kvm,
> +					       struct vgic_its *its,
> +					       gpa_t addr, unsigned int len,
> +					       unsigned long val)
> +{
> +	u32 reg;
> +
> +	mutex_lock(&its->cmd_lock);
> +
> +	if (its->enabled)
> +		goto out;
> + 
> +	reg = update_64bit_reg(its->creadr, addr & 7, len, val);
> +	reg = ITS_CMD_OFFSET(reg);
> +	if (reg >= ITS_CMD_BUFFER_SIZE(its->cbaser))
> +		goto out;
> +
> +	its->creadr = reg;

Careful. Here, you're loosing the "Stalled" bit. We do not implement
support for it yet, but I wonder if we should preserve it. If not, we
should at least document that we're purposely stripping that bit.

> +out:
> +	mutex_unlock(&its->cmd_lock);
> +}
> +
>  #define BASER_INDEX(addr) (((addr) / sizeof(u64)) & 0x7)
>  static unsigned long vgic_mmio_read_its_baser(struct kvm *kvm,
>  					      struct vgic_its *its,
> @@ -1317,6 +1339,16 @@ static void vgic_mmio_write_its_ctlr(struct kvm *kvm, struct vgic_its *its,
>  	.its_write = wr,					\
>  }
>  
> +#define REGISTER_ITS_DESC_UACCESS(off, rd, wr, uwr, length, acc)\
> +{								\
> +	.reg_offset = off,					\
> +	.len = length,						\
> +	.access_flags = acc,					\
> +	.its_read = rd,						\
> +	.its_write = wr,					\
> +	.uaccess_its_write = uwr,				\
> +}
> +
>  static void its_mmio_write_wi(struct kvm *kvm, struct vgic_its *its,
>  			      gpa_t addr, unsigned int len, unsigned long val)
>  {
> @@ -1339,8 +1371,9 @@ static struct vgic_register_region its_registers[] = {
>  	REGISTER_ITS_DESC(GITS_CWRITER,
>  		vgic_mmio_read_its_cwriter, vgic_mmio_write_its_cwriter, 8,
>  		VGIC_ACCESS_64bit | VGIC_ACCESS_32bit),
> -	REGISTER_ITS_DESC(GITS_CREADR,
> -		vgic_mmio_read_its_creadr, its_mmio_write_wi, 8,
> +	REGISTER_ITS_DESC_UACCESS(GITS_CREADR,
> +		vgic_mmio_read_its_creadr, its_mmio_write_wi,
> +		vgic_mmio_uaccess_write_its_creadr, 8,
>  		VGIC_ACCESS_64bit | VGIC_ACCESS_32bit),
>  	REGISTER_ITS_DESC(GITS_BASER,
>  		vgic_mmio_read_its_baser, vgic_mmio_write_its_baser, 0x40,

Thanks,

	M.
-- 
Jazz is not dead. It just smells funny.

^ permalink raw reply	[flat|nested] 144+ messages in thread

* [PATCH v4 07/22] KVM: arm64: ITS: Implement vgic_mmio_uaccess_write_its_creadr
@ 2017-04-08 10:36     ` Marc Zyngier
  0 siblings, 0 replies; 144+ messages in thread
From: Marc Zyngier @ 2017-04-08 10:36 UTC (permalink / raw)
  To: linux-arm-kernel

On Mon, Mar 27 2017 at 10:30:57 AM, Eric Auger <eric.auger@redhat.com> wrote:
> GITS_CREADR needs to be restored so let's implement the associated
> uaccess_write_its callback. The write only is allowed if the its
> is disabled.
>
> Signed-off-by: Eric Auger <eric.auger@redhat.com>
>
> ---
>
> v3 -> v4:
> - REGISTER_ITS_DESC_UACCESS now introduced in this patch
> - we now check the its is disabled
> ---
>  virt/kvm/arm/vgic/vgic-its.c | 37 +++++++++++++++++++++++++++++++++++--
>  1 file changed, 35 insertions(+), 2 deletions(-)
>
> diff --git a/virt/kvm/arm/vgic/vgic-its.c b/virt/kvm/arm/vgic/vgic-its.c
> index 9b9ea86..a5f3abe 100644
> --- a/virt/kvm/arm/vgic/vgic-its.c
> +++ b/virt/kvm/arm/vgic/vgic-its.c
> @@ -1213,6 +1213,28 @@ static unsigned long vgic_mmio_read_its_creadr(struct kvm *kvm,
>  	return extract_bytes(its->creadr, addr & 0x7, len);
>  }
>  
> +static void vgic_mmio_uaccess_write_its_creadr(struct kvm *kvm,
> +					       struct vgic_its *its,
> +					       gpa_t addr, unsigned int len,
> +					       unsigned long val)
> +{
> +	u32 reg;
> +
> +	mutex_lock(&its->cmd_lock);
> +
> +	if (its->enabled)
> +		goto out;
> + 
> +	reg = update_64bit_reg(its->creadr, addr & 7, len, val);
> +	reg = ITS_CMD_OFFSET(reg);
> +	if (reg >= ITS_CMD_BUFFER_SIZE(its->cbaser))
> +		goto out;
> +
> +	its->creadr = reg;

Careful. Here, you're loosing the "Stalled" bit. We do not implement
support for it yet, but I wonder if we should preserve it. If not, we
should at least document that we're purposely stripping that bit.

> +out:
> +	mutex_unlock(&its->cmd_lock);
> +}
> +
>  #define BASER_INDEX(addr) (((addr) / sizeof(u64)) & 0x7)
>  static unsigned long vgic_mmio_read_its_baser(struct kvm *kvm,
>  					      struct vgic_its *its,
> @@ -1317,6 +1339,16 @@ static void vgic_mmio_write_its_ctlr(struct kvm *kvm, struct vgic_its *its,
>  	.its_write = wr,					\
>  }
>  
> +#define REGISTER_ITS_DESC_UACCESS(off, rd, wr, uwr, length, acc)\
> +{								\
> +	.reg_offset = off,					\
> +	.len = length,						\
> +	.access_flags = acc,					\
> +	.its_read = rd,						\
> +	.its_write = wr,					\
> +	.uaccess_its_write = uwr,				\
> +}
> +
>  static void its_mmio_write_wi(struct kvm *kvm, struct vgic_its *its,
>  			      gpa_t addr, unsigned int len, unsigned long val)
>  {
> @@ -1339,8 +1371,9 @@ static struct vgic_register_region its_registers[] = {
>  	REGISTER_ITS_DESC(GITS_CWRITER,
>  		vgic_mmio_read_its_cwriter, vgic_mmio_write_its_cwriter, 8,
>  		VGIC_ACCESS_64bit | VGIC_ACCESS_32bit),
> -	REGISTER_ITS_DESC(GITS_CREADR,
> -		vgic_mmio_read_its_creadr, its_mmio_write_wi, 8,
> +	REGISTER_ITS_DESC_UACCESS(GITS_CREADR,
> +		vgic_mmio_read_its_creadr, its_mmio_write_wi,
> +		vgic_mmio_uaccess_write_its_creadr, 8,
>  		VGIC_ACCESS_64bit | VGIC_ACCESS_32bit),
>  	REGISTER_ITS_DESC(GITS_BASER,
>  		vgic_mmio_read_its_baser, vgic_mmio_write_its_baser, 0x40,

Thanks,

	M.
-- 
Jazz is not dead. It just smells funny.

^ permalink raw reply	[flat|nested] 144+ messages in thread

* Re: [PATCH v4 08/22] KVM: arm64: ITS: Implement vgic_mmio_uaccess_write_its_iidr
  2017-03-27  9:30   ` Eric Auger
  (?)
@ 2017-04-08 10:42     ` Marc Zyngier
  -1 siblings, 0 replies; 144+ messages in thread
From: Marc Zyngier @ 2017-04-08 10:42 UTC (permalink / raw)
  To: Eric Auger
  Cc: eric.auger.pro, christoffer.dall, andre.przywara, vijayak,
	Vijaya.Kumar, peter.maydell, linux-arm-kernel, kvmarm, kvm,
	Prasun.Kapoor, drjones, pbonzini, dgilbert, quintela

On Mon, Mar 27 2017 at 10:30:58 AM, Eric Auger <eric.auger@redhat.com> wrote:
> The GITS_IIDR revision field is used to encode the version of the
> table layout (ABI). So we need to restore it to check the table
> layout to be restored is compatible with the destination vITS.
>
> The user selected revision is stored in the user_revision field.
> It will be compared against the REV num at table restoration time.

Why isn't it sufficient to keep it GITS_IIDR RO and let userspace find
out about the ABI revision that the kernel understands?

Or are we planning on supporting multiple ABIs in the kernel? If so, do
we have a deprecation policy/plan? I don't mind either way, but it would
be good to document it...

Maybe it is documented already and I missed it (which is perfectly
possible!).

Thanks,

	M.
-- 
Jazz is not dead. It just smells funny.

^ permalink raw reply	[flat|nested] 144+ messages in thread

* Re: [PATCH v4 08/22] KVM: arm64: ITS: Implement vgic_mmio_uaccess_write_its_iidr
@ 2017-04-08 10:42     ` Marc Zyngier
  0 siblings, 0 replies; 144+ messages in thread
From: Marc Zyngier @ 2017-04-08 10:42 UTC (permalink / raw)
  To: Eric Auger
  Cc: eric.auger.pro, christoffer.dall, andre.przywara, vijayak,
	Vijaya.Kumar, peter.maydell, linux-arm-kernel, kvmarm, kvm,
	Prasun.Kapoor, drjones, pbonzini, dgilbert, quintela

On Mon, Mar 27 2017 at 10:30:58 AM, Eric Auger <eric.auger@redhat.com> wrote:
> The GITS_IIDR revision field is used to encode the version of the
> table layout (ABI). So we need to restore it to check the table
> layout to be restored is compatible with the destination vITS.
>
> The user selected revision is stored in the user_revision field.
> It will be compared against the REV num at table restoration time.

Why isn't it sufficient to keep it GITS_IIDR RO and let userspace find
out about the ABI revision that the kernel understands?

Or are we planning on supporting multiple ABIs in the kernel? If so, do
we have a deprecation policy/plan? I don't mind either way, but it would
be good to document it...

Maybe it is documented already and I missed it (which is perfectly
possible!).

Thanks,

	M.
-- 
Jazz is not dead. It just smells funny.

^ permalink raw reply	[flat|nested] 144+ messages in thread

* [PATCH v4 08/22] KVM: arm64: ITS: Implement vgic_mmio_uaccess_write_its_iidr
@ 2017-04-08 10:42     ` Marc Zyngier
  0 siblings, 0 replies; 144+ messages in thread
From: Marc Zyngier @ 2017-04-08 10:42 UTC (permalink / raw)
  To: linux-arm-kernel

On Mon, Mar 27 2017 at 10:30:58 AM, Eric Auger <eric.auger@redhat.com> wrote:
> The GITS_IIDR revision field is used to encode the version of the
> table layout (ABI). So we need to restore it to check the table
> layout to be restored is compatible with the destination vITS.
>
> The user selected revision is stored in the user_revision field.
> It will be compared against the REV num at table restoration time.

Why isn't it sufficient to keep it GITS_IIDR RO and let userspace find
out about the ABI revision that the kernel understands?

Or are we planning on supporting multiple ABIs in the kernel? If so, do
we have a deprecation policy/plan? I don't mind either way, but it would
be good to document it...

Maybe it is documented already and I missed it (which is perfectly
possible!).

Thanks,

	M.
-- 
Jazz is not dead. It just smells funny.

^ permalink raw reply	[flat|nested] 144+ messages in thread

* Re: [PATCH v4 01/22] KVM: arm/arm64: Add vITS save/restore API documentation
  2017-04-08 10:03     ` Marc Zyngier
@ 2017-04-08 13:15       ` Christoffer Dall
  -1 siblings, 0 replies; 144+ messages in thread
From: Christoffer Dall @ 2017-04-08 13:15 UTC (permalink / raw)
  To: Marc Zyngier
  Cc: Eric Auger, eric.auger.pro, andre.przywara, vijayak,
	Vijaya.Kumar, peter.maydell, linux-arm-kernel, kvmarm, kvm,
	Prasun.Kapoor, drjones, pbonzini, dgilbert, quintela

On Sat, Apr 08, 2017 at 11:03:51AM +0100, Marc Zyngier wrote:
> On Mon, Mar 27 2017 at 10:30:51 AM, Eric Auger <eric.auger@redhat.com> wrote:
> > Add description for how to access vITS registers and how to flush/restore
> > vITS tables into/from memory
> >
> > Signed-off-by: Eric Auger <eric.auger@redhat.com>
> >
> > ---
> > v3 -> v4:
> > - take into account Peter's comments:
> >   - typos
> >   - KVM_DEV_ARM_VGIC_GRP_ITS_TABLES kvm_device_attr = 0
> >   - add a validity bit in DTE
> >   - document all fields in CTE and ITE
> >   - document ABI revision
> > - take into account Andre's comments:
> >   - document restrictions about GITS_CREADR writing and GITS_IIDR
> >   - document -EBUSY error if one or more VCPUS are runnning
> >   - document 64b registers only can be accessed with 64b access
> > - itt_addr field matches bits [51:8] of the itt_addr
> >
> > v1 -> v2:
> > - DTE and ITE now are 8 bytes
> > - DTE and ITE now indexed by deviceid/eventid
> > - use ITE name instead of ITTE
> > - mentions ITT_addr matches bits [51:8] of the actual address
> > - mentions LE layout
> > ---
> >  Documentation/virtual/kvm/devices/arm-vgic-its.txt | 118 +++++++++++++++++++++
> >  1 file changed, 118 insertions(+)
> >
> > diff --git a/Documentation/virtual/kvm/devices/arm-vgic-its.txt b/Documentation/virtual/kvm/devices/arm-vgic-its.txt
> > index 6081a5b..0902d20 100644
> > --- a/Documentation/virtual/kvm/devices/arm-vgic-its.txt
> > +++ b/Documentation/virtual/kvm/devices/arm-vgic-its.txt
> > @@ -36,3 +36,121 @@ Groups:
> >      -ENXIO:  ITS not properly configured as required prior to setting
> >               this attribute
> >      -ENOMEM: Memory shortage when allocating ITS internal data
> > +
> > +  KVM_DEV_ARM_VGIC_GRP_ITS_REGS
> > +  Attributes:
> > +      The attr field of kvm_device_attr encodes the offset of the
> > +      ITS register, relative to the ITS control frame base address
> > +      (ITS_base).
> > +
> > +      kvm_device_attr.addr points to a __u64 value whatever the width
> > +      of the addressed register (32/64 bits). 64 bit registers can only
> > +      be accessed with full length.
> > +
> > +      Writes to read-only registers are ignored by the kernel except for:
> > +      - GITS_READR. It needs to be restored otherwise commands in the queue
> > +        will be re-executed after CWRITER setting. Writing this register is
> > +        allowed if the ITS is not enabled (GITS_CTLR.enable = 0). Also it
> > +        needs to be restored after GITS_CBASER since a write to GITS_CBASER
> > +        resets GITS_CREADR.
> > +      - GITS_IIDR. Its Revision field encodes the table layout ABI revision.
> > +
> > +      For other registers, getting or setting a register has the same
> > +      effect as reading/writing the register on real hardware.
> > +  Errors:
> > +    -ENXIO: Offset does not correspond to any supported register
> > +    -EFAULT: Invalid user pointer for attr->addr
> > +    -EINVAL: Offset is not 64-bit aligned
> > +    -EBUSY: one or more VCPUS are running
> > +
> > +  KVM_DEV_ARM_VGIC_GRP_ITS_TABLES
> > +  Attributes
> > +       The attr field of kvm_device_attr must be zero.
> > +
> > +       request the flush-save/restore of the ITS tables, namely
> > +       the device table, the collection table, all the ITT tables,
> > +       the LPI pending tables. On save, the tables are flushed
> > +       into guest memory at the location provisioned by the guest
> > +       in GITS_BASER (device and collection tables), in the MAPD
> > +       command (ITT_addr), GICR_PENDBASERs (pending tables).
> 
> May I echo Andre's concern here? Seeing the GICR_PENDBASER registers
> here feels wrong. The pending table is a redistributor concept, and is
> local to it. Even more, it is perfectly possible to use the
> redistributors (and its pending tables) without an ITS by using the
> GICR_SETLPIR registers.
> 
> Granted, we do not support this (and I'm *not* looking forward to
> supporting it), but I would rather implement a redistributor flush than
> using the ITS to indirectly force it. That's not how the HW works, and I
> don't think we should deviate from it.
> 
> I appreciate this brings additional complexity to userspace (having to
> iterate over the vcpus or the redistributors is likely more costly than
> hitting the ITS which is likely to be unique), but sticking to the
> letter of the architecture is probably our best bet. Each time we tried
> to deviate from it, we've had to backtrack.

I agree.  I think the possibility of using LPIs without an ITS is the
winning argument.

However, I could see it being reasonable to have a single call that
userspace can make on the vgic device to ask it to flush all the
redistributors at the same time.  We defined the cpu sysreg interface
via the vgic device as well, so I don't think we're breaking anything,
and in fact, it may be good to have a single sync-point where the kernel
can atomically say "all redistributors are flushed correctly" or
"something bad happened".  Do we have any arguments for wanting to be
able flush redistributors independently?

Thanks,
-Christoffer

^ permalink raw reply	[flat|nested] 144+ messages in thread

* [PATCH v4 01/22] KVM: arm/arm64: Add vITS save/restore API documentation
@ 2017-04-08 13:15       ` Christoffer Dall
  0 siblings, 0 replies; 144+ messages in thread
From: Christoffer Dall @ 2017-04-08 13:15 UTC (permalink / raw)
  To: linux-arm-kernel

On Sat, Apr 08, 2017 at 11:03:51AM +0100, Marc Zyngier wrote:
> On Mon, Mar 27 2017 at 10:30:51 AM, Eric Auger <eric.auger@redhat.com> wrote:
> > Add description for how to access vITS registers and how to flush/restore
> > vITS tables into/from memory
> >
> > Signed-off-by: Eric Auger <eric.auger@redhat.com>
> >
> > ---
> > v3 -> v4:
> > - take into account Peter's comments:
> >   - typos
> >   - KVM_DEV_ARM_VGIC_GRP_ITS_TABLES kvm_device_attr = 0
> >   - add a validity bit in DTE
> >   - document all fields in CTE and ITE
> >   - document ABI revision
> > - take into account Andre's comments:
> >   - document restrictions about GITS_CREADR writing and GITS_IIDR
> >   - document -EBUSY error if one or more VCPUS are runnning
> >   - document 64b registers only can be accessed with 64b access
> > - itt_addr field matches bits [51:8] of the itt_addr
> >
> > v1 -> v2:
> > - DTE and ITE now are 8 bytes
> > - DTE and ITE now indexed by deviceid/eventid
> > - use ITE name instead of ITTE
> > - mentions ITT_addr matches bits [51:8] of the actual address
> > - mentions LE layout
> > ---
> >  Documentation/virtual/kvm/devices/arm-vgic-its.txt | 118 +++++++++++++++++++++
> >  1 file changed, 118 insertions(+)
> >
> > diff --git a/Documentation/virtual/kvm/devices/arm-vgic-its.txt b/Documentation/virtual/kvm/devices/arm-vgic-its.txt
> > index 6081a5b..0902d20 100644
> > --- a/Documentation/virtual/kvm/devices/arm-vgic-its.txt
> > +++ b/Documentation/virtual/kvm/devices/arm-vgic-its.txt
> > @@ -36,3 +36,121 @@ Groups:
> >      -ENXIO:  ITS not properly configured as required prior to setting
> >               this attribute
> >      -ENOMEM: Memory shortage when allocating ITS internal data
> > +
> > +  KVM_DEV_ARM_VGIC_GRP_ITS_REGS
> > +  Attributes:
> > +      The attr field of kvm_device_attr encodes the offset of the
> > +      ITS register, relative to the ITS control frame base address
> > +      (ITS_base).
> > +
> > +      kvm_device_attr.addr points to a __u64 value whatever the width
> > +      of the addressed register (32/64 bits). 64 bit registers can only
> > +      be accessed with full length.
> > +
> > +      Writes to read-only registers are ignored by the kernel except for:
> > +      - GITS_READR. It needs to be restored otherwise commands in the queue
> > +        will be re-executed after CWRITER setting. Writing this register is
> > +        allowed if the ITS is not enabled (GITS_CTLR.enable = 0). Also it
> > +        needs to be restored after GITS_CBASER since a write to GITS_CBASER
> > +        resets GITS_CREADR.
> > +      - GITS_IIDR. Its Revision field encodes the table layout ABI revision.
> > +
> > +      For other registers, getting or setting a register has the same
> > +      effect as reading/writing the register on real hardware.
> > +  Errors:
> > +    -ENXIO: Offset does not correspond to any supported register
> > +    -EFAULT: Invalid user pointer for attr->addr
> > +    -EINVAL: Offset is not 64-bit aligned
> > +    -EBUSY: one or more VCPUS are running
> > +
> > +  KVM_DEV_ARM_VGIC_GRP_ITS_TABLES
> > +  Attributes
> > +       The attr field of kvm_device_attr must be zero.
> > +
> > +       request the flush-save/restore of the ITS tables, namely
> > +       the device table, the collection table, all the ITT tables,
> > +       the LPI pending tables. On save, the tables are flushed
> > +       into guest memory at the location provisioned by the guest
> > +       in GITS_BASER (device and collection tables), in the MAPD
> > +       command (ITT_addr), GICR_PENDBASERs (pending tables).
> 
> May I echo Andre's concern here? Seeing the GICR_PENDBASER registers
> here feels wrong. The pending table is a redistributor concept, and is
> local to it. Even more, it is perfectly possible to use the
> redistributors (and its pending tables) without an ITS by using the
> GICR_SETLPIR registers.
> 
> Granted, we do not support this (and I'm *not* looking forward to
> supporting it), but I would rather implement a redistributor flush than
> using the ITS to indirectly force it. That's not how the HW works, and I
> don't think we should deviate from it.
> 
> I appreciate this brings additional complexity to userspace (having to
> iterate over the vcpus or the redistributors is likely more costly than
> hitting the ITS which is likely to be unique), but sticking to the
> letter of the architecture is probably our best bet. Each time we tried
> to deviate from it, we've had to backtrack.

I agree.  I think the possibility of using LPIs without an ITS is the
winning argument.

However, I could see it being reasonable to have a single call that
userspace can make on the vgic device to ask it to flush all the
redistributors at the same time.  We defined the cpu sysreg interface
via the vgic device as well, so I don't think we're breaking anything,
and in fact, it may be good to have a single sync-point where the kernel
can atomically say "all redistributors are flushed correctly" or
"something bad happened".  Do we have any arguments for wanting to be
able flush redistributors independently?

Thanks,
-Christoffer

^ permalink raw reply	[flat|nested] 144+ messages in thread

* Re: [PATCH v4 01/22] KVM: arm/arm64: Add vITS save/restore API documentation
  2017-04-08 13:15       ` Christoffer Dall
@ 2017-04-08 17:31         ` Marc Zyngier
  -1 siblings, 0 replies; 144+ messages in thread
From: Marc Zyngier @ 2017-04-08 17:31 UTC (permalink / raw)
  To: Christoffer Dall
  Cc: kvm, Prasun.Kapoor, vijayak, andre.przywara, quintela, dgilbert,
	Vijaya.Kumar, pbonzini, kvmarm, linux-arm-kernel, eric.auger.pro

On Sat, Apr 08 2017 at 02:15:52 PM, Christoffer Dall <christoffer.dall@linaro.org> wrote:
> On Sat, Apr 08, 2017 at 11:03:51AM +0100, Marc Zyngier wrote:
>> On Mon, Mar 27 2017 at 10:30:51 AM, Eric Auger <eric.auger@redhat.com> wrote:
>> > Add description for how to access vITS registers and how to flush/restore
>> > vITS tables into/from memory
>> >
>> > Signed-off-by: Eric Auger <eric.auger@redhat.com>
>> >
>> > ---
>> > v3 -> v4:
>> > - take into account Peter's comments:
>> >   - typos
>> >   - KVM_DEV_ARM_VGIC_GRP_ITS_TABLES kvm_device_attr = 0
>> >   - add a validity bit in DTE
>> >   - document all fields in CTE and ITE
>> >   - document ABI revision
>> > - take into account Andre's comments:
>> >   - document restrictions about GITS_CREADR writing and GITS_IIDR
>> >   - document -EBUSY error if one or more VCPUS are runnning
>> >   - document 64b registers only can be accessed with 64b access
>> > - itt_addr field matches bits [51:8] of the itt_addr
>> >
>> > v1 -> v2:
>> > - DTE and ITE now are 8 bytes
>> > - DTE and ITE now indexed by deviceid/eventid
>> > - use ITE name instead of ITTE
>> > - mentions ITT_addr matches bits [51:8] of the actual address
>> > - mentions LE layout
>> > ---
>> >  Documentation/virtual/kvm/devices/arm-vgic-its.txt | 118 +++++++++++++++++++++
>> >  1 file changed, 118 insertions(+)
>> >
>> > diff --git a/Documentation/virtual/kvm/devices/arm-vgic-its.txt b/Documentation/virtual/kvm/devices/arm-vgic-its.txt
>> > index 6081a5b..0902d20 100644
>> > --- a/Documentation/virtual/kvm/devices/arm-vgic-its.txt
>> > +++ b/Documentation/virtual/kvm/devices/arm-vgic-its.txt
>> > @@ -36,3 +36,121 @@ Groups:
>> >      -ENXIO:  ITS not properly configured as required prior to setting
>> >               this attribute
>> >      -ENOMEM: Memory shortage when allocating ITS internal data
>> > +
>> > +  KVM_DEV_ARM_VGIC_GRP_ITS_REGS
>> > +  Attributes:
>> > +      The attr field of kvm_device_attr encodes the offset of the
>> > +      ITS register, relative to the ITS control frame base address
>> > +      (ITS_base).
>> > +
>> > +      kvm_device_attr.addr points to a __u64 value whatever the width
>> > +      of the addressed register (32/64 bits). 64 bit registers can only
>> > +      be accessed with full length.
>> > +
>> > +      Writes to read-only registers are ignored by the kernel except for:
>> > +      - GITS_READR. It needs to be restored otherwise commands in the queue
>> > +        will be re-executed after CWRITER setting. Writing this register is
>> > +        allowed if the ITS is not enabled (GITS_CTLR.enable = 0). Also it
>> > +        needs to be restored after GITS_CBASER since a write to GITS_CBASER
>> > +        resets GITS_CREADR.
>> > +      - GITS_IIDR. Its Revision field encodes the table layout ABI revision.
>> > +
>> > +      For other registers, getting or setting a register has the same
>> > +      effect as reading/writing the register on real hardware.
>> > +  Errors:
>> > +    -ENXIO: Offset does not correspond to any supported register
>> > +    -EFAULT: Invalid user pointer for attr->addr
>> > +    -EINVAL: Offset is not 64-bit aligned
>> > +    -EBUSY: one or more VCPUS are running
>> > +
>> > +  KVM_DEV_ARM_VGIC_GRP_ITS_TABLES
>> > +  Attributes
>> > +       The attr field of kvm_device_attr must be zero.
>> > +
>> > +       request the flush-save/restore of the ITS tables, namely
>> > +       the device table, the collection table, all the ITT tables,
>> > +       the LPI pending tables. On save, the tables are flushed
>> > +       into guest memory at the location provisioned by the guest
>> > +       in GITS_BASER (device and collection tables), in the MAPD
>> > +       command (ITT_addr), GICR_PENDBASERs (pending tables).
>> 
>> May I echo Andre's concern here? Seeing the GICR_PENDBASER registers
>> here feels wrong. The pending table is a redistributor concept, and is
>> local to it. Even more, it is perfectly possible to use the
>> redistributors (and its pending tables) without an ITS by using the
>> GICR_SETLPIR registers.
>> 
>> Granted, we do not support this (and I'm *not* looking forward to
>> supporting it), but I would rather implement a redistributor flush than
>> using the ITS to indirectly force it. That's not how the HW works, and I
>> don't think we should deviate from it.
>> 
>> I appreciate this brings additional complexity to userspace (having to
>> iterate over the vcpus or the redistributors is likely more costly than
>> hitting the ITS which is likely to be unique), but sticking to the
>> letter of the architecture is probably our best bet. Each time we tried
>> to deviate from it, we've had to backtrack.
>
> I agree.  I think the possibility of using LPIs without an ITS is the
> winning argument.
>
> However, I could see it being reasonable to have a single call that
> userspace can make on the vgic device to ask it to flush all the
> redistributors at the same time.  We defined the cpu sysreg interface
> via the vgic device as well, so I don't think we're breaking anything,
> and in fact, it may be good to have a single sync-point where the kernel
> can atomically say "all redistributors are flushed correctly" or
> "something bad happened".  Do we have any arguments for wanting to be
> able flush redistributors independently?

Not as such. The redistributors may support implementation-specific ways
of ensuring synchronization with the PT (for power management purposes,
for example), but there is no architected way of ensuring it.

So I agree that having a single synchronization hook for all
redistributors in the system is probably the right thing to do. This is
simple enough for userspace, and we already have the required code in
this series -- we just need to tie it to an additional property on the
GICv3 group.

Eric: can you explore this and let us know if there is any issue we
haven't foreseen yet?

Thanks,

	M.
-- 
Jazz is not dead. It just smells funny.

^ permalink raw reply	[flat|nested] 144+ messages in thread

* [PATCH v4 01/22] KVM: arm/arm64: Add vITS save/restore API documentation
@ 2017-04-08 17:31         ` Marc Zyngier
  0 siblings, 0 replies; 144+ messages in thread
From: Marc Zyngier @ 2017-04-08 17:31 UTC (permalink / raw)
  To: linux-arm-kernel

On Sat, Apr 08 2017 at 02:15:52 PM, Christoffer Dall <christoffer.dall@linaro.org> wrote:
> On Sat, Apr 08, 2017 at 11:03:51AM +0100, Marc Zyngier wrote:
>> On Mon, Mar 27 2017 at 10:30:51 AM, Eric Auger <eric.auger@redhat.com> wrote:
>> > Add description for how to access vITS registers and how to flush/restore
>> > vITS tables into/from memory
>> >
>> > Signed-off-by: Eric Auger <eric.auger@redhat.com>
>> >
>> > ---
>> > v3 -> v4:
>> > - take into account Peter's comments:
>> >   - typos
>> >   - KVM_DEV_ARM_VGIC_GRP_ITS_TABLES kvm_device_attr = 0
>> >   - add a validity bit in DTE
>> >   - document all fields in CTE and ITE
>> >   - document ABI revision
>> > - take into account Andre's comments:
>> >   - document restrictions about GITS_CREADR writing and GITS_IIDR
>> >   - document -EBUSY error if one or more VCPUS are runnning
>> >   - document 64b registers only can be accessed with 64b access
>> > - itt_addr field matches bits [51:8] of the itt_addr
>> >
>> > v1 -> v2:
>> > - DTE and ITE now are 8 bytes
>> > - DTE and ITE now indexed by deviceid/eventid
>> > - use ITE name instead of ITTE
>> > - mentions ITT_addr matches bits [51:8] of the actual address
>> > - mentions LE layout
>> > ---
>> >  Documentation/virtual/kvm/devices/arm-vgic-its.txt | 118 +++++++++++++++++++++
>> >  1 file changed, 118 insertions(+)
>> >
>> > diff --git a/Documentation/virtual/kvm/devices/arm-vgic-its.txt b/Documentation/virtual/kvm/devices/arm-vgic-its.txt
>> > index 6081a5b..0902d20 100644
>> > --- a/Documentation/virtual/kvm/devices/arm-vgic-its.txt
>> > +++ b/Documentation/virtual/kvm/devices/arm-vgic-its.txt
>> > @@ -36,3 +36,121 @@ Groups:
>> >      -ENXIO:  ITS not properly configured as required prior to setting
>> >               this attribute
>> >      -ENOMEM: Memory shortage when allocating ITS internal data
>> > +
>> > +  KVM_DEV_ARM_VGIC_GRP_ITS_REGS
>> > +  Attributes:
>> > +      The attr field of kvm_device_attr encodes the offset of the
>> > +      ITS register, relative to the ITS control frame base address
>> > +      (ITS_base).
>> > +
>> > +      kvm_device_attr.addr points to a __u64 value whatever the width
>> > +      of the addressed register (32/64 bits). 64 bit registers can only
>> > +      be accessed with full length.
>> > +
>> > +      Writes to read-only registers are ignored by the kernel except for:
>> > +      - GITS_READR. It needs to be restored otherwise commands in the queue
>> > +        will be re-executed after CWRITER setting. Writing this register is
>> > +        allowed if the ITS is not enabled (GITS_CTLR.enable = 0). Also it
>> > +        needs to be restored after GITS_CBASER since a write to GITS_CBASER
>> > +        resets GITS_CREADR.
>> > +      - GITS_IIDR. Its Revision field encodes the table layout ABI revision.
>> > +
>> > +      For other registers, getting or setting a register has the same
>> > +      effect as reading/writing the register on real hardware.
>> > +  Errors:
>> > +    -ENXIO: Offset does not correspond to any supported register
>> > +    -EFAULT: Invalid user pointer for attr->addr
>> > +    -EINVAL: Offset is not 64-bit aligned
>> > +    -EBUSY: one or more VCPUS are running
>> > +
>> > +  KVM_DEV_ARM_VGIC_GRP_ITS_TABLES
>> > +  Attributes
>> > +       The attr field of kvm_device_attr must be zero.
>> > +
>> > +       request the flush-save/restore of the ITS tables, namely
>> > +       the device table, the collection table, all the ITT tables,
>> > +       the LPI pending tables. On save, the tables are flushed
>> > +       into guest memory at the location provisioned by the guest
>> > +       in GITS_BASER (device and collection tables), in the MAPD
>> > +       command (ITT_addr), GICR_PENDBASERs (pending tables).
>> 
>> May I echo Andre's concern here? Seeing the GICR_PENDBASER registers
>> here feels wrong. The pending table is a redistributor concept, and is
>> local to it. Even more, it is perfectly possible to use the
>> redistributors (and its pending tables) without an ITS by using the
>> GICR_SETLPIR registers.
>> 
>> Granted, we do not support this (and I'm *not* looking forward to
>> supporting it), but I would rather implement a redistributor flush than
>> using the ITS to indirectly force it. That's not how the HW works, and I
>> don't think we should deviate from it.
>> 
>> I appreciate this brings additional complexity to userspace (having to
>> iterate over the vcpus or the redistributors is likely more costly than
>> hitting the ITS which is likely to be unique), but sticking to the
>> letter of the architecture is probably our best bet. Each time we tried
>> to deviate from it, we've had to backtrack.
>
> I agree.  I think the possibility of using LPIs without an ITS is the
> winning argument.
>
> However, I could see it being reasonable to have a single call that
> userspace can make on the vgic device to ask it to flush all the
> redistributors at the same time.  We defined the cpu sysreg interface
> via the vgic device as well, so I don't think we're breaking anything,
> and in fact, it may be good to have a single sync-point where the kernel
> can atomically say "all redistributors are flushed correctly" or
> "something bad happened".  Do we have any arguments for wanting to be
> able flush redistributors independently?

Not as such. The redistributors may support implementation-specific ways
of ensuring synchronization with the PT (for power management purposes,
for example), but there is no architected way of ensuring it.

So I agree that having a single synchronization hook for all
redistributors in the system is probably the right thing to do. This is
simple enough for userspace, and we already have the required code in
this series -- we just need to tie it to an additional property on the
GICv3 group.

Eric: can you explore this and let us know if there is any issue we
haven't foreseen yet?

Thanks,

	M.
-- 
Jazz is not dead. It just smells funny.

^ permalink raw reply	[flat|nested] 144+ messages in thread

* Re: [PATCH v4 09/22] KVM: arm64: ITS: Report the ITE size in GITS_TYPER
  2017-03-27  9:30   ` Eric Auger
@ 2017-04-08 17:42     ` Marc Zyngier
  -1 siblings, 0 replies; 144+ messages in thread
From: Marc Zyngier @ 2017-04-08 17:42 UTC (permalink / raw)
  To: Eric Auger
  Cc: kvm, Prasun.Kapoor, vijayak, andre.przywara, quintela, dgilbert,
	Vijaya.Kumar, linux-arm-kernel, pbonzini, kvmarm, eric.auger.pro

On Mon, Mar 27 2017 at 10:30:59 AM, Eric Auger <eric.auger@redhat.com> wrote:
> An ITE size of 8 Bytes is reported to the guest. Combining this
> information with the number of event IDs the guest wants to support,
> this latter will be able to allocate each device's ITT with the
> right size.
>
> Signed-off-by: Eric Auger <eric.auger@redhat.com>
> Reviewed-by: Andre Przywara <andre.przywara@arm.com>
>
> ---
>
> v2 -> v3:
> - changed (u64)(VITS_ESZ - 1) to (VITS_ESZ - 1ULL) in
>   vgic_register_its_iodev
> - added Andre's R-b
>
> v1 -> v2:
> - correct ITT_ENTRY_SIZE field
> - remove ITE_SIZE since all entries become 8 bytes
> ---
>  include/linux/irqchip/arm-gic-v3.h | 1 +
>  virt/kvm/arm/vgic/vgic-its.c       | 5 ++++-
>  2 files changed, 5 insertions(+), 1 deletion(-)
>
> diff --git a/include/linux/irqchip/arm-gic-v3.h b/include/linux/irqchip/arm-gic-v3.h
> index 97cbca1..d86f963 100644
> --- a/include/linux/irqchip/arm-gic-v3.h
> +++ b/include/linux/irqchip/arm-gic-v3.h
> @@ -232,6 +232,7 @@
>  #define GITS_CTLR_QUIESCENT		(1U << 31)
>  
>  #define GITS_TYPER_PLPIS		(1UL << 0)
> +#define GITS_TYPER_ITT_ENTRY_SIZE_SHIFT	4
>  #define GITS_TYPER_IDBITS_SHIFT		8
>  #define GITS_TYPER_DEVBITS_SHIFT	13
>  #define GITS_TYPER_DEVBITS(r)		((((r) >> GITS_TYPER_DEVBITS_SHIFT) & 0x1f) + 1)
> diff --git a/virt/kvm/arm/vgic/vgic-its.c b/virt/kvm/arm/vgic/vgic-its.c
> index 169b486..fabcac1 100644
> --- a/virt/kvm/arm/vgic/vgic-its.c
> +++ b/virt/kvm/arm/vgic/vgic-its.c
> @@ -179,6 +179,8 @@ static struct its_ite *find_ite(struct vgic_its *its, u32 device_id,
>  
>  #define GIC_LPI_OFFSET 8192
>  
> +#define VITS_ESZ 8
> +
>  /*
>   * Finds and returns a collection in the ITS collection table.
>   * Must be called with the its_lock mutex held.
> @@ -379,6 +381,7 @@ static unsigned long vgic_mmio_read_its_typer(struct kvm *kvm,
>  	 */
>  	reg |= 0x0f << GITS_TYPER_DEVBITS_SHIFT;
>  	reg |= 0x0f << GITS_TYPER_IDBITS_SHIFT;
> +	reg |= (VITS_ESZ - 1) << GITS_TYPER_ITT_ENTRY_SIZE_SHIFT;
>  
>  	return extract_bytes(reg, addr & 7, len);
>  }
> @@ -1436,7 +1439,7 @@ static int vgic_register_its_iodev(struct kvm *kvm, struct vgic_its *its)
>  	(GIC_BASER_CACHEABILITY(GITS_BASER, INNER, RaWb)		| \
>  	 GIC_BASER_CACHEABILITY(GITS_BASER, OUTER, SameAsInner)		| \
>  	 GIC_BASER_SHAREABILITY(GITS_BASER, InnerShareable)		| \
> -	 ((8ULL - 1) << GITS_BASER_ENTRY_SIZE_SHIFT)			| \
> +	 ((VITS_ESZ - 1ULL) << GITS_BASER_ENTRY_SIZE_SHIFT)		| \
>  	 GITS_BASER_PAGE_SIZE_64K)
>  
>  #define INITIAL_PROPBASER_VALUE						  \

nit: since we're going to now encode a number of sizes in various
registers, I have the feeling that it would make sense to have a macro
that performs that encoding in a relatively generic way.

Something along the lines of

#define GIC_ENCODE_SZ(n,w) (((unsigned long)(n) - 1) & GENMASK_ULL(((w) - 1), 0))

where n is the value, and w is the number of bits required. Somehow, I'd
find it slightly more readable. Or do you think that it is completely
overkill?

Thanks,

	M.
-- 
Jazz is not dead. It just smells funny.

^ permalink raw reply	[flat|nested] 144+ messages in thread

* [PATCH v4 09/22] KVM: arm64: ITS: Report the ITE size in GITS_TYPER
@ 2017-04-08 17:42     ` Marc Zyngier
  0 siblings, 0 replies; 144+ messages in thread
From: Marc Zyngier @ 2017-04-08 17:42 UTC (permalink / raw)
  To: linux-arm-kernel

On Mon, Mar 27 2017 at 10:30:59 AM, Eric Auger <eric.auger@redhat.com> wrote:
> An ITE size of 8 Bytes is reported to the guest. Combining this
> information with the number of event IDs the guest wants to support,
> this latter will be able to allocate each device's ITT with the
> right size.
>
> Signed-off-by: Eric Auger <eric.auger@redhat.com>
> Reviewed-by: Andre Przywara <andre.przywara@arm.com>
>
> ---
>
> v2 -> v3:
> - changed (u64)(VITS_ESZ - 1) to (VITS_ESZ - 1ULL) in
>   vgic_register_its_iodev
> - added Andre's R-b
>
> v1 -> v2:
> - correct ITT_ENTRY_SIZE field
> - remove ITE_SIZE since all entries become 8 bytes
> ---
>  include/linux/irqchip/arm-gic-v3.h | 1 +
>  virt/kvm/arm/vgic/vgic-its.c       | 5 ++++-
>  2 files changed, 5 insertions(+), 1 deletion(-)
>
> diff --git a/include/linux/irqchip/arm-gic-v3.h b/include/linux/irqchip/arm-gic-v3.h
> index 97cbca1..d86f963 100644
> --- a/include/linux/irqchip/arm-gic-v3.h
> +++ b/include/linux/irqchip/arm-gic-v3.h
> @@ -232,6 +232,7 @@
>  #define GITS_CTLR_QUIESCENT		(1U << 31)
>  
>  #define GITS_TYPER_PLPIS		(1UL << 0)
> +#define GITS_TYPER_ITT_ENTRY_SIZE_SHIFT	4
>  #define GITS_TYPER_IDBITS_SHIFT		8
>  #define GITS_TYPER_DEVBITS_SHIFT	13
>  #define GITS_TYPER_DEVBITS(r)		((((r) >> GITS_TYPER_DEVBITS_SHIFT) & 0x1f) + 1)
> diff --git a/virt/kvm/arm/vgic/vgic-its.c b/virt/kvm/arm/vgic/vgic-its.c
> index 169b486..fabcac1 100644
> --- a/virt/kvm/arm/vgic/vgic-its.c
> +++ b/virt/kvm/arm/vgic/vgic-its.c
> @@ -179,6 +179,8 @@ static struct its_ite *find_ite(struct vgic_its *its, u32 device_id,
>  
>  #define GIC_LPI_OFFSET 8192
>  
> +#define VITS_ESZ 8
> +
>  /*
>   * Finds and returns a collection in the ITS collection table.
>   * Must be called with the its_lock mutex held.
> @@ -379,6 +381,7 @@ static unsigned long vgic_mmio_read_its_typer(struct kvm *kvm,
>  	 */
>  	reg |= 0x0f << GITS_TYPER_DEVBITS_SHIFT;
>  	reg |= 0x0f << GITS_TYPER_IDBITS_SHIFT;
> +	reg |= (VITS_ESZ - 1) << GITS_TYPER_ITT_ENTRY_SIZE_SHIFT;
>  
>  	return extract_bytes(reg, addr & 7, len);
>  }
> @@ -1436,7 +1439,7 @@ static int vgic_register_its_iodev(struct kvm *kvm, struct vgic_its *its)
>  	(GIC_BASER_CACHEABILITY(GITS_BASER, INNER, RaWb)		| \
>  	 GIC_BASER_CACHEABILITY(GITS_BASER, OUTER, SameAsInner)		| \
>  	 GIC_BASER_SHAREABILITY(GITS_BASER, InnerShareable)		| \
> -	 ((8ULL - 1) << GITS_BASER_ENTRY_SIZE_SHIFT)			| \
> +	 ((VITS_ESZ - 1ULL) << GITS_BASER_ENTRY_SIZE_SHIFT)		| \
>  	 GITS_BASER_PAGE_SIZE_64K)
>  
>  #define INITIAL_PROPBASER_VALUE						  \

nit: since we're going to now encode a number of sizes in various
registers, I have the feeling that it would make sense to have a macro
that performs that encoding in a relatively generic way.

Something along the lines of

#define GIC_ENCODE_SZ(n,w) (((unsigned long)(n) - 1) & GENMASK_ULL(((w) - 1), 0))

where n is the value, and w is the number of bits required. Somehow, I'd
find it slightly more readable. Or do you think that it is completely
overkill?

Thanks,

	M.
-- 
Jazz is not dead. It just smells funny.

^ permalink raw reply	[flat|nested] 144+ messages in thread

* Re: [PATCH v4 10/22] KVM: arm64: ITS: Interpret MAPD Size field and check related errors
  2017-03-27  9:31   ` Eric Auger
  (?)
@ 2017-04-08 17:59     ` Marc Zyngier
  -1 siblings, 0 replies; 144+ messages in thread
From: Marc Zyngier @ 2017-04-08 17:59 UTC (permalink / raw)
  To: Eric Auger
  Cc: eric.auger.pro, christoffer.dall, andre.przywara, vijayak,
	Vijaya.Kumar, peter.maydell, linux-arm-kernel, kvmarm, kvm,
	Prasun.Kapoor, drjones, pbonzini, dgilbert, quintela

On Mon, Mar 27 2017 at 10:31:00 AM, Eric Auger <eric.auger@redhat.com> wrote:
> Up to now the MAPD's ITT size field has been ignored. It encodes
> the number of eventid bit minus 1. It should be used to check
> the eventid when a MAPTI command is issued on a device. Let's
> store the number of eventid bits in the its_device and do the
> check on MAPTI. Also make sure the ITT size field does
> not exceed the GITS_TYPER IDBITS field.
>
> Signed-off-by: Eric Auger <eric.auger@redhat.com>
>
> ---
>
> v3 -> v4:
> - VITS_TYPER_IDBITS set to 16 to be homogeneous with VITS_ESZ definition
>   and correct users
> - nb_eventid_bits correspond to the actual number of eventid bits
> ---
>  include/linux/irqchip/arm-gic-v3.h |  2 ++
>  virt/kvm/arm/vgic/vgic-its.c       | 14 +++++++++++++-
>  2 files changed, 15 insertions(+), 1 deletion(-)
>
> diff --git a/include/linux/irqchip/arm-gic-v3.h b/include/linux/irqchip/arm-gic-v3.h
> index d86f963..dcbb3e0 100644
> --- a/include/linux/irqchip/arm-gic-v3.h
> +++ b/include/linux/irqchip/arm-gic-v3.h
> @@ -338,9 +338,11 @@
>  #define E_ITS_INT_UNMAPPED_INTERRUPT		0x010307
>  #define E_ITS_CLEAR_UNMAPPED_INTERRUPT		0x010507
>  #define E_ITS_MAPD_DEVICE_OOR			0x010801
> +#define E_ITS_MAPD_ITTSIZE_OOR			0x010802
>  #define E_ITS_MAPC_PROCNUM_OOR			0x010902
>  #define E_ITS_MAPC_COLLECTION_OOR		0x010903
>  #define E_ITS_MAPTI_UNMAPPED_DEVICE		0x010a04
> +#define E_ITS_MAPTI_ID_OOR			0x010a05
>  #define E_ITS_MAPTI_PHYSICALID_OOR		0x010a06
>  #define E_ITS_INV_UNMAPPED_INTERRUPT		0x010c07
>  #define E_ITS_INVALL_UNMAPPED_COLLECTION	0x010d09
> diff --git a/virt/kvm/arm/vgic/vgic-its.c b/virt/kvm/arm/vgic/vgic-its.c
> index fabcac1..ddd2780 100644
> --- a/virt/kvm/arm/vgic/vgic-its.c
> +++ b/virt/kvm/arm/vgic/vgic-its.c
> @@ -102,6 +102,7 @@ struct its_device {
>  
>  	/* the head for the list of ITTEs */
>  	struct list_head itt_head;
> +	u32 nb_eventid_bits;
>  	u32 device_id;
>  };
>  
> @@ -180,6 +181,7 @@ static struct its_ite *find_ite(struct vgic_its *its, u32 device_id,
>  #define GIC_LPI_OFFSET 8192
>  
>  #define VITS_ESZ 8
> +#define VITS_TYPER_IDBITS 16
>  
>  /*
>   * Finds and returns a collection in the ITS collection table.
> @@ -380,7 +382,7 @@ static unsigned long vgic_mmio_read_its_typer(struct kvm *kvm,
>  	 * DevBits low - as least for the time being.
>  	 */
>  	reg |= 0x0f << GITS_TYPER_DEVBITS_SHIFT;
> -	reg |= 0x0f << GITS_TYPER_IDBITS_SHIFT;
> +	reg |= (VITS_TYPER_IDBITS - 1) << GITS_TYPER_IDBITS_SHIFT;
>  	reg |= (VITS_ESZ - 1) << GITS_TYPER_ITT_ENTRY_SIZE_SHIFT;
>  
>  	return extract_bytes(reg, addr & 7, len);
> @@ -547,6 +549,7 @@ static u64 its_cmd_mask_field(u64 *its_cmd, int word, int shift, int size)
>  
>  #define its_cmd_get_command(cmd)	its_cmd_mask_field(cmd, 0,  0,  8)
>  #define its_cmd_get_deviceid(cmd)	its_cmd_mask_field(cmd, 0, 32, 32)
> +#define its_cmd_get_size(cmd)		its_cmd_mask_field(cmd, 1,  0,  5)
>  #define its_cmd_get_id(cmd)		its_cmd_mask_field(cmd, 1,  0, 32)
>  #define its_cmd_get_physical_id(cmd)	its_cmd_mask_field(cmd, 1, 32, 32)
>  #define its_cmd_get_collection(cmd)	its_cmd_mask_field(cmd, 2,  0, 16)
> @@ -737,6 +740,9 @@ static int vgic_its_cmd_handle_mapi(struct kvm *kvm, struct vgic_its *its,
>  	if (!device)
>  		return E_ITS_MAPTI_UNMAPPED_DEVICE;
>  
> +	if (event_id >= BIT_ULL(device->nb_eventid_bits))
> +		return E_ITS_MAPTI_ID_OOR;
> +
>  	if (its_cmd_get_command(its_cmd) == GITS_CMD_MAPTI)
>  		lpi_nr = its_cmd_get_physical_id(its_cmd);
>  	else
> @@ -817,11 +823,15 @@ static int vgic_its_cmd_handle_mapd(struct kvm *kvm, struct vgic_its *its,
>  {
>  	u32 device_id = its_cmd_get_deviceid(its_cmd);
>  	bool valid = its_cmd_get_validbit(its_cmd);
> +	u8 nb_eventid_bits = its_cmd_get_size(its_cmd) + 1;

I feel it would be clearer if we had its_cmd_get_size() return the
actual size, and not just the encoding of the size (i.e. put the +1 in
the macro instead of the caller).

>  	struct its_device *device;
>  
>  	if (!vgic_its_check_id(its, its->baser_device_table, device_id))
>  		return E_ITS_MAPD_DEVICE_OOR;
>  
> +	if (valid && nb_eventid_bits > VITS_TYPER_IDBITS)
> +		return E_ITS_MAPD_ITTSIZE_OOR;
> +
>  	device = find_its_device(its, device_id);
>  
>  	/*
> @@ -844,6 +854,8 @@ static int vgic_its_cmd_handle_mapd(struct kvm *kvm, struct vgic_its *its,
>  		return -ENOMEM;
>  
>  	device->device_id = device_id;
> +	device->nb_eventid_bits = nb_eventid_bits;
> +
>  	INIT_LIST_HEAD(&device->itt_head);
>  
>  	list_add_tail(&device->dev_list, &its->device_list);

Thanks,

	M.
-- 
Jazz is not dead. It just smells funny.

^ permalink raw reply	[flat|nested] 144+ messages in thread

* Re: [PATCH v4 10/22] KVM: arm64: ITS: Interpret MAPD Size field and check related errors
@ 2017-04-08 17:59     ` Marc Zyngier
  0 siblings, 0 replies; 144+ messages in thread
From: Marc Zyngier @ 2017-04-08 17:59 UTC (permalink / raw)
  To: Eric Auger
  Cc: eric.auger.pro, christoffer.dall, andre.przywara, vijayak,
	Vijaya.Kumar, peter.maydell, linux-arm-kernel, kvmarm, kvm,
	Prasun.Kapoor, drjones, pbonzini, dgilbert, quintela

On Mon, Mar 27 2017 at 10:31:00 AM, Eric Auger <eric.auger@redhat.com> wrote:
> Up to now the MAPD's ITT size field has been ignored. It encodes
> the number of eventid bit minus 1. It should be used to check
> the eventid when a MAPTI command is issued on a device. Let's
> store the number of eventid bits in the its_device and do the
> check on MAPTI. Also make sure the ITT size field does
> not exceed the GITS_TYPER IDBITS field.
>
> Signed-off-by: Eric Auger <eric.auger@redhat.com>
>
> ---
>
> v3 -> v4:
> - VITS_TYPER_IDBITS set to 16 to be homogeneous with VITS_ESZ definition
>   and correct users
> - nb_eventid_bits correspond to the actual number of eventid bits
> ---
>  include/linux/irqchip/arm-gic-v3.h |  2 ++
>  virt/kvm/arm/vgic/vgic-its.c       | 14 +++++++++++++-
>  2 files changed, 15 insertions(+), 1 deletion(-)
>
> diff --git a/include/linux/irqchip/arm-gic-v3.h b/include/linux/irqchip/arm-gic-v3.h
> index d86f963..dcbb3e0 100644
> --- a/include/linux/irqchip/arm-gic-v3.h
> +++ b/include/linux/irqchip/arm-gic-v3.h
> @@ -338,9 +338,11 @@
>  #define E_ITS_INT_UNMAPPED_INTERRUPT		0x010307
>  #define E_ITS_CLEAR_UNMAPPED_INTERRUPT		0x010507
>  #define E_ITS_MAPD_DEVICE_OOR			0x010801
> +#define E_ITS_MAPD_ITTSIZE_OOR			0x010802
>  #define E_ITS_MAPC_PROCNUM_OOR			0x010902
>  #define E_ITS_MAPC_COLLECTION_OOR		0x010903
>  #define E_ITS_MAPTI_UNMAPPED_DEVICE		0x010a04
> +#define E_ITS_MAPTI_ID_OOR			0x010a05
>  #define E_ITS_MAPTI_PHYSICALID_OOR		0x010a06
>  #define E_ITS_INV_UNMAPPED_INTERRUPT		0x010c07
>  #define E_ITS_INVALL_UNMAPPED_COLLECTION	0x010d09
> diff --git a/virt/kvm/arm/vgic/vgic-its.c b/virt/kvm/arm/vgic/vgic-its.c
> index fabcac1..ddd2780 100644
> --- a/virt/kvm/arm/vgic/vgic-its.c
> +++ b/virt/kvm/arm/vgic/vgic-its.c
> @@ -102,6 +102,7 @@ struct its_device {
>  
>  	/* the head for the list of ITTEs */
>  	struct list_head itt_head;
> +	u32 nb_eventid_bits;
>  	u32 device_id;
>  };
>  
> @@ -180,6 +181,7 @@ static struct its_ite *find_ite(struct vgic_its *its, u32 device_id,
>  #define GIC_LPI_OFFSET 8192
>  
>  #define VITS_ESZ 8
> +#define VITS_TYPER_IDBITS 16
>  
>  /*
>   * Finds and returns a collection in the ITS collection table.
> @@ -380,7 +382,7 @@ static unsigned long vgic_mmio_read_its_typer(struct kvm *kvm,
>  	 * DevBits low - as least for the time being.
>  	 */
>  	reg |= 0x0f << GITS_TYPER_DEVBITS_SHIFT;
> -	reg |= 0x0f << GITS_TYPER_IDBITS_SHIFT;
> +	reg |= (VITS_TYPER_IDBITS - 1) << GITS_TYPER_IDBITS_SHIFT;
>  	reg |= (VITS_ESZ - 1) << GITS_TYPER_ITT_ENTRY_SIZE_SHIFT;
>  
>  	return extract_bytes(reg, addr & 7, len);
> @@ -547,6 +549,7 @@ static u64 its_cmd_mask_field(u64 *its_cmd, int word, int shift, int size)
>  
>  #define its_cmd_get_command(cmd)	its_cmd_mask_field(cmd, 0,  0,  8)
>  #define its_cmd_get_deviceid(cmd)	its_cmd_mask_field(cmd, 0, 32, 32)
> +#define its_cmd_get_size(cmd)		its_cmd_mask_field(cmd, 1,  0,  5)
>  #define its_cmd_get_id(cmd)		its_cmd_mask_field(cmd, 1,  0, 32)
>  #define its_cmd_get_physical_id(cmd)	its_cmd_mask_field(cmd, 1, 32, 32)
>  #define its_cmd_get_collection(cmd)	its_cmd_mask_field(cmd, 2,  0, 16)
> @@ -737,6 +740,9 @@ static int vgic_its_cmd_handle_mapi(struct kvm *kvm, struct vgic_its *its,
>  	if (!device)
>  		return E_ITS_MAPTI_UNMAPPED_DEVICE;
>  
> +	if (event_id >= BIT_ULL(device->nb_eventid_bits))
> +		return E_ITS_MAPTI_ID_OOR;
> +
>  	if (its_cmd_get_command(its_cmd) == GITS_CMD_MAPTI)
>  		lpi_nr = its_cmd_get_physical_id(its_cmd);
>  	else
> @@ -817,11 +823,15 @@ static int vgic_its_cmd_handle_mapd(struct kvm *kvm, struct vgic_its *its,
>  {
>  	u32 device_id = its_cmd_get_deviceid(its_cmd);
>  	bool valid = its_cmd_get_validbit(its_cmd);
> +	u8 nb_eventid_bits = its_cmd_get_size(its_cmd) + 1;

I feel it would be clearer if we had its_cmd_get_size() return the
actual size, and not just the encoding of the size (i.e. put the +1 in
the macro instead of the caller).

>  	struct its_device *device;
>  
>  	if (!vgic_its_check_id(its, its->baser_device_table, device_id))
>  		return E_ITS_MAPD_DEVICE_OOR;
>  
> +	if (valid && nb_eventid_bits > VITS_TYPER_IDBITS)
> +		return E_ITS_MAPD_ITTSIZE_OOR;
> +
>  	device = find_its_device(its, device_id);
>  
>  	/*
> @@ -844,6 +854,8 @@ static int vgic_its_cmd_handle_mapd(struct kvm *kvm, struct vgic_its *its,
>  		return -ENOMEM;
>  
>  	device->device_id = device_id;
> +	device->nb_eventid_bits = nb_eventid_bits;
> +
>  	INIT_LIST_HEAD(&device->itt_head);
>  
>  	list_add_tail(&device->dev_list, &its->device_list);

Thanks,

	M.
-- 
Jazz is not dead. It just smells funny.

^ permalink raw reply	[flat|nested] 144+ messages in thread

* [PATCH v4 10/22] KVM: arm64: ITS: Interpret MAPD Size field and check related errors
@ 2017-04-08 17:59     ` Marc Zyngier
  0 siblings, 0 replies; 144+ messages in thread
From: Marc Zyngier @ 2017-04-08 17:59 UTC (permalink / raw)
  To: linux-arm-kernel

On Mon, Mar 27 2017 at 10:31:00 AM, Eric Auger <eric.auger@redhat.com> wrote:
> Up to now the MAPD's ITT size field has been ignored. It encodes
> the number of eventid bit minus 1. It should be used to check
> the eventid when a MAPTI command is issued on a device. Let's
> store the number of eventid bits in the its_device and do the
> check on MAPTI. Also make sure the ITT size field does
> not exceed the GITS_TYPER IDBITS field.
>
> Signed-off-by: Eric Auger <eric.auger@redhat.com>
>
> ---
>
> v3 -> v4:
> - VITS_TYPER_IDBITS set to 16 to be homogeneous with VITS_ESZ definition
>   and correct users
> - nb_eventid_bits correspond to the actual number of eventid bits
> ---
>  include/linux/irqchip/arm-gic-v3.h |  2 ++
>  virt/kvm/arm/vgic/vgic-its.c       | 14 +++++++++++++-
>  2 files changed, 15 insertions(+), 1 deletion(-)
>
> diff --git a/include/linux/irqchip/arm-gic-v3.h b/include/linux/irqchip/arm-gic-v3.h
> index d86f963..dcbb3e0 100644
> --- a/include/linux/irqchip/arm-gic-v3.h
> +++ b/include/linux/irqchip/arm-gic-v3.h
> @@ -338,9 +338,11 @@
>  #define E_ITS_INT_UNMAPPED_INTERRUPT		0x010307
>  #define E_ITS_CLEAR_UNMAPPED_INTERRUPT		0x010507
>  #define E_ITS_MAPD_DEVICE_OOR			0x010801
> +#define E_ITS_MAPD_ITTSIZE_OOR			0x010802
>  #define E_ITS_MAPC_PROCNUM_OOR			0x010902
>  #define E_ITS_MAPC_COLLECTION_OOR		0x010903
>  #define E_ITS_MAPTI_UNMAPPED_DEVICE		0x010a04
> +#define E_ITS_MAPTI_ID_OOR			0x010a05
>  #define E_ITS_MAPTI_PHYSICALID_OOR		0x010a06
>  #define E_ITS_INV_UNMAPPED_INTERRUPT		0x010c07
>  #define E_ITS_INVALL_UNMAPPED_COLLECTION	0x010d09
> diff --git a/virt/kvm/arm/vgic/vgic-its.c b/virt/kvm/arm/vgic/vgic-its.c
> index fabcac1..ddd2780 100644
> --- a/virt/kvm/arm/vgic/vgic-its.c
> +++ b/virt/kvm/arm/vgic/vgic-its.c
> @@ -102,6 +102,7 @@ struct its_device {
>  
>  	/* the head for the list of ITTEs */
>  	struct list_head itt_head;
> +	u32 nb_eventid_bits;
>  	u32 device_id;
>  };
>  
> @@ -180,6 +181,7 @@ static struct its_ite *find_ite(struct vgic_its *its, u32 device_id,
>  #define GIC_LPI_OFFSET 8192
>  
>  #define VITS_ESZ 8
> +#define VITS_TYPER_IDBITS 16
>  
>  /*
>   * Finds and returns a collection in the ITS collection table.
> @@ -380,7 +382,7 @@ static unsigned long vgic_mmio_read_its_typer(struct kvm *kvm,
>  	 * DevBits low - as least for the time being.
>  	 */
>  	reg |= 0x0f << GITS_TYPER_DEVBITS_SHIFT;
> -	reg |= 0x0f << GITS_TYPER_IDBITS_SHIFT;
> +	reg |= (VITS_TYPER_IDBITS - 1) << GITS_TYPER_IDBITS_SHIFT;
>  	reg |= (VITS_ESZ - 1) << GITS_TYPER_ITT_ENTRY_SIZE_SHIFT;
>  
>  	return extract_bytes(reg, addr & 7, len);
> @@ -547,6 +549,7 @@ static u64 its_cmd_mask_field(u64 *its_cmd, int word, int shift, int size)
>  
>  #define its_cmd_get_command(cmd)	its_cmd_mask_field(cmd, 0,  0,  8)
>  #define its_cmd_get_deviceid(cmd)	its_cmd_mask_field(cmd, 0, 32, 32)
> +#define its_cmd_get_size(cmd)		its_cmd_mask_field(cmd, 1,  0,  5)
>  #define its_cmd_get_id(cmd)		its_cmd_mask_field(cmd, 1,  0, 32)
>  #define its_cmd_get_physical_id(cmd)	its_cmd_mask_field(cmd, 1, 32, 32)
>  #define its_cmd_get_collection(cmd)	its_cmd_mask_field(cmd, 2,  0, 16)
> @@ -737,6 +740,9 @@ static int vgic_its_cmd_handle_mapi(struct kvm *kvm, struct vgic_its *its,
>  	if (!device)
>  		return E_ITS_MAPTI_UNMAPPED_DEVICE;
>  
> +	if (event_id >= BIT_ULL(device->nb_eventid_bits))
> +		return E_ITS_MAPTI_ID_OOR;
> +
>  	if (its_cmd_get_command(its_cmd) == GITS_CMD_MAPTI)
>  		lpi_nr = its_cmd_get_physical_id(its_cmd);
>  	else
> @@ -817,11 +823,15 @@ static int vgic_its_cmd_handle_mapd(struct kvm *kvm, struct vgic_its *its,
>  {
>  	u32 device_id = its_cmd_get_deviceid(its_cmd);
>  	bool valid = its_cmd_get_validbit(its_cmd);
> +	u8 nb_eventid_bits = its_cmd_get_size(its_cmd) + 1;

I feel it would be clearer if we had its_cmd_get_size() return the
actual size, and not just the encoding of the size (i.e. put the +1 in
the macro instead of the caller).

>  	struct its_device *device;
>  
>  	if (!vgic_its_check_id(its, its->baser_device_table, device_id))
>  		return E_ITS_MAPD_DEVICE_OOR;
>  
> +	if (valid && nb_eventid_bits > VITS_TYPER_IDBITS)
> +		return E_ITS_MAPD_ITTSIZE_OOR;
> +
>  	device = find_its_device(its, device_id);
>  
>  	/*
> @@ -844,6 +854,8 @@ static int vgic_its_cmd_handle_mapd(struct kvm *kvm, struct vgic_its *its,
>  		return -ENOMEM;
>  
>  	device->device_id = device_id;
> +	device->nb_eventid_bits = nb_eventid_bits;
> +
>  	INIT_LIST_HEAD(&device->itt_head);
>  
>  	list_add_tail(&device->dev_list, &its->device_list);

Thanks,

	M.
-- 
Jazz is not dead. It just smells funny.

^ permalink raw reply	[flat|nested] 144+ messages in thread

* Re: [PATCH v4 01/22] KVM: arm/arm64: Add vITS save/restore API documentation
  2017-03-27  9:30   ` Eric Auger
@ 2017-04-08 18:17     ` Christoffer Dall
  -1 siblings, 0 replies; 144+ messages in thread
From: Christoffer Dall @ 2017-04-08 18:17 UTC (permalink / raw)
  To: Eric Auger
  Cc: eric.auger.pro, marc.zyngier, andre.przywara, vijayak,
	Vijaya.Kumar, peter.maydell, linux-arm-kernel, kvmarm, kvm,
	Prasun.Kapoor, drjones, pbonzini, dgilbert, quintela

Hi Eric,

Most of my comments below are just me being picky about text when
defining a user space ABI, so I think this mainly looks good, but just
needs a bit of clarify, except the versioning aspect and exporting the
pending table vie the redistributor instead, as Marc and Andre have
pointed out.

On Mon, Mar 27, 2017 at 11:30:51AM +0200, Eric Auger wrote:
> Add description for how to access vITS registers and how to flush/restore
> vITS tables into/from memory
> 
> Signed-off-by: Eric Auger <eric.auger@redhat.com>
> 
> ---
> v3 -> v4:
> - take into account Peter's comments:
>   - typos
>   - KVM_DEV_ARM_VGIC_GRP_ITS_TABLES kvm_device_attr = 0
>   - add a validity bit in DTE
>   - document all fields in CTE and ITE
>   - document ABI revision
> - take into account Andre's comments:
>   - document restrictions about GITS_CREADR writing and GITS_IIDR
>   - document -EBUSY error if one or more VCPUS are runnning
>   - document 64b registers only can be accessed with 64b access
> - itt_addr field matches bits [51:8] of the itt_addr
> 
> v1 -> v2:
> - DTE and ITE now are 8 bytes
> - DTE and ITE now indexed by deviceid/eventid
> - use ITE name instead of ITTE
> - mentions ITT_addr matches bits [51:8] of the actual address
> - mentions LE layout
> ---
>  Documentation/virtual/kvm/devices/arm-vgic-its.txt | 118 +++++++++++++++++++++
>  1 file changed, 118 insertions(+)
> 
> diff --git a/Documentation/virtual/kvm/devices/arm-vgic-its.txt b/Documentation/virtual/kvm/devices/arm-vgic-its.txt
> index 6081a5b..0902d20 100644
> --- a/Documentation/virtual/kvm/devices/arm-vgic-its.txt
> +++ b/Documentation/virtual/kvm/devices/arm-vgic-its.txt
> @@ -36,3 +36,121 @@ Groups:
>      -ENXIO:  ITS not properly configured as required prior to setting
>               this attribute
>      -ENOMEM: Memory shortage when allocating ITS internal data
> +
> +  KVM_DEV_ARM_VGIC_GRP_ITS_REGS
> +  Attributes:
> +      The attr field of kvm_device_attr encodes the offset of the
> +      ITS register, relative to the ITS control frame base address
> +      (ITS_base).
> +
> +      kvm_device_attr.addr points to a __u64 value whatever the width
> +      of the addressed register (32/64 bits). 64 bit registers can only
> +      be accessed with full length.
> +
> +      Writes to read-only registers are ignored by the kernel except for:
> +      - GITS_READR. It needs to be restored otherwise commands in the queue
> +        will be re-executed after CWRITER setting. Writing this register is
                                     ^^^^^^^^^^^^^^^

"after restoring CWRITER." ?

> +        allowed if the ITS is not enabled (GITS_CTLR.enable = 0). Also it

Does that mean that you can only save/restore a disabled ITS or does it
mean that initially after creating the ITS it is disabled and userspace
should restore the CWRITER before restoring GITS_CTLR (which may enable
the ITS) ?

> +        needs to be restored after GITS_CBASER since a write to GITS_CBASER
> +        resets GITS_CREADR.
> +      - GITS_IIDR. Its Revision field encodes the table layout ABI revision.

How is this really going to work?  Your ABI here must be backwards
compatible for future revisions, so what is userspace supposed to do,
when it reads a newer revision than it was programmed for?

I think we need a more clear description of how the revision is going to
be used, such that each operation on the ITS here is described as
requiring a minimum revision X, and making sure that userspace can
safely ignore things that are of a higher revision number, while at the
same time userspace can decide not to use newer features with older
kernels.

> +
> +      For other registers, getting or setting a register has the same
> +      effect as reading/writing the register on real hardware.
> +  Errors:
> +    -ENXIO: Offset does not correspond to any supported register
> +    -EFAULT: Invalid user pointer for attr->addr
> +    -EINVAL: Offset is not 64-bit aligned
> +    -EBUSY: one or more VCPUS are running
> +
> +  KVM_DEV_ARM_VGIC_GRP_ITS_TABLES

Shouldn't this be called KVM_DEV_ARM_VGIC_GRP_FLUSH_ITS_TABLES ?

> +  Attributes
> +       The attr field of kvm_device_attr must be zero.
> +
> +       request the flush-save/restore of the ITS tables, namely

Nit: Request (upper case R)

what does flush-save/restore mean as opposed to just flush?

> +       the device table, the collection table, all the ITT tables,
> +       the LPI pending tables. On save, the tables are flushed

, and the LPI pending table.

> +       into guest memory at the location provisioned by the guest
> +       in GITS_BASER (device and collection tables), in the MAPD
> +       command (ITT_addr), GICR_PENDBASERs (pending tables).
> +
> +       This means the GIC should be restored before the ITS and all

should or must?  Is this enforced?

> +       ITS registers but the GITS_CTLR must be restored before
> +       restoring the ITS tables.
> +
> +       The GITS_READR and GITS_IIDR read-only registers must also
> +       be restored before the table restore. The IIDR revision field
> +       encodes the ABI revision of the table layout. If not set by
> +       user space, the restoration of the tables will fail.

consider rewording: ", restoring the ITS tables will fail."

> +
> +       Note the LPI configuration table is read-only for the

Note that

> +       in-kernel ITS and its save/restore goes through the standard

and saving/restoring it is done via the normal process to save/restore
guest RAM.

> +       RAM save/restore.
> +
> +       The layout of the tables in guest memory defines an ABI.
> +       The entries are laid in little endian format as follows;

s/;/:/

It's a bit weird to say "as follows:" and then proceed with the error
descriptions.  I would simply say "as described in the following
paragraph."

> +
> +  Errors:
> +    -EINVAL: kvm_device_attr not equal to 0, invalid table data
> +    -EFAULT: invalid guest ram access
> +    -EBUSY: one or more VCPUS are running
> +
> +    ITS Table ABI REV1:
> +    -------------------
> +
> +    The device table and ITE are respectively indexed by device id and

s/ITE/ITT/

are indexed by the device id and eventid, respectively.

> +    eventid. The collection table however is not indexed by collection id:

...by collection id, instead all the CTEs are written...

> +    CTE are written at the beginning of the buffer.

in any particular order, or?

> +
> +    Device Table Entry (DTE) layout: entry size = 8 bytes
> +
> +    bits:     | 63| 62 ... 49 | 48 ... 5 | 4 ... 0 |
> +    values:   | V |   next    | ITT_addr |  Size   |
> +
> +    where;
> +    - V indicates whether the entry is valid,
> +    - ITT_addr matches bits [51:8] of the ITT address (256B aligned),
> +    - next field is meaningful only if the entry is valid.

is the ITT_addr meaningful if the entry is not valid?

> +    It equals to 0 if this entry is the last one; otherwise it corresponds
> +    to the minimum between the offset to the next device id and 2^14 -1.

I don't easily understand this last paragraph and the indentation is
weird and makes it look like it's not explaining the next field.

You're missing a description of the size field.  Size in what unit?
Size of what?


> +
> +    Collection Table Entry (CTE) layout: entry size = 8 bytes
> +
> +    bits:     | 63| 62 ..  52  | 51 ... 16 | 15  ...   0 |
> +    values:   | V |    RES0    |  RDBase   |    ICID     |
> +
> +    where:
> +    - V indicates whether the entry is valid,

Do we explain anywhere what RES0 means?

> +    - RDBase matches the PE number (GICR_TYPER.Processor_Number),

is 'matches' the right verb to use here?

What exactly is the format of GICR_TYPER.Processor_Number ?

> +    - ICID matches the collection ID

again, is 'matches' the right verb to use here?

> +
> +    Interrupt Translation Entry (ITE) layout: entry size = 8 bytes
> +
> +    bits:     | 63 ... 48 | 47 ... 16 | 15 ... 0 |
> +    values:   |    next   |   pINTID  |  ICID    |
> +
> +    where:
> +    - pINTID is the physical LPI ID,
> +    - ICID is the collection ID,

here you use 'is' intead of 'matches'.  At leat be consistent.

> +    - next field is meaningful only if the entry is valid (pINTID != 0).
> +    It equals to 0 if this entry is the last one; otherwise it corresponds
> +    to the minimum between the eventid offset to the next ITE and 2^16 -1.

same comments, as above.

also, can you list the field in the order they appear?

> +
> +    LPI Pending Table layout:
> +
> +    As specified in the ARM Generic Interrupt Controller Architecture
> +    Specification GIC Architecture version 3.0 and version 4. The first

"...version 4, the first".  ("As specified in X." is not a sentence).

> +    1kB is not modified and therefore should contain zeroes.

should or must?  or always contains zeros?  Will you return an error if
userspace puts something non-zero in there?

> +
> +    Future evolutions of the ITS table layout:
> +
> +    At the moment the table layout is defined and optimized for physical
> +    LPI support.

This comment is a bit confusing, because this is all about virtual
interrupts really, so 'physical from the point of view of the VM', but I
think you should just drop this sentence.

> +
> +    In the future we might implement direct injection of virtual LPIS.

For nesting, yes?  (on the host this should not be visible here, should
it?)

> +    This will require an upgrade of the table layout and an evolution of
> +    the ABI. The ABI revision is encoded in the GITS_IIDR revision field.
> +    That register must be restored before the table restoration, otherwise
> +    the operation will fail.

Hmm, I thought we dealt with that before, feels a bit out of place.

> +
> +    ABI V1: GITS_IIDR.Revision = 1

I feel like this should go in the ITS register description of the IIDR.
Most likely, I think this particular line can be dropped, but all other
definitions in this file can be annoted with a minimum revision number
ensuring that future revisions implement this, plus potentially more
stuff.

Thanks,
-Christoffer

^ permalink raw reply	[flat|nested] 144+ messages in thread

* [PATCH v4 01/22] KVM: arm/arm64: Add vITS save/restore API documentation
@ 2017-04-08 18:17     ` Christoffer Dall
  0 siblings, 0 replies; 144+ messages in thread
From: Christoffer Dall @ 2017-04-08 18:17 UTC (permalink / raw)
  To: linux-arm-kernel

Hi Eric,

Most of my comments below are just me being picky about text when
defining a user space ABI, so I think this mainly looks good, but just
needs a bit of clarify, except the versioning aspect and exporting the
pending table vie the redistributor instead, as Marc and Andre have
pointed out.

On Mon, Mar 27, 2017 at 11:30:51AM +0200, Eric Auger wrote:
> Add description for how to access vITS registers and how to flush/restore
> vITS tables into/from memory
> 
> Signed-off-by: Eric Auger <eric.auger@redhat.com>
> 
> ---
> v3 -> v4:
> - take into account Peter's comments:
>   - typos
>   - KVM_DEV_ARM_VGIC_GRP_ITS_TABLES kvm_device_attr = 0
>   - add a validity bit in DTE
>   - document all fields in CTE and ITE
>   - document ABI revision
> - take into account Andre's comments:
>   - document restrictions about GITS_CREADR writing and GITS_IIDR
>   - document -EBUSY error if one or more VCPUS are runnning
>   - document 64b registers only can be accessed with 64b access
> - itt_addr field matches bits [51:8] of the itt_addr
> 
> v1 -> v2:
> - DTE and ITE now are 8 bytes
> - DTE and ITE now indexed by deviceid/eventid
> - use ITE name instead of ITTE
> - mentions ITT_addr matches bits [51:8] of the actual address
> - mentions LE layout
> ---
>  Documentation/virtual/kvm/devices/arm-vgic-its.txt | 118 +++++++++++++++++++++
>  1 file changed, 118 insertions(+)
> 
> diff --git a/Documentation/virtual/kvm/devices/arm-vgic-its.txt b/Documentation/virtual/kvm/devices/arm-vgic-its.txt
> index 6081a5b..0902d20 100644
> --- a/Documentation/virtual/kvm/devices/arm-vgic-its.txt
> +++ b/Documentation/virtual/kvm/devices/arm-vgic-its.txt
> @@ -36,3 +36,121 @@ Groups:
>      -ENXIO:  ITS not properly configured as required prior to setting
>               this attribute
>      -ENOMEM: Memory shortage when allocating ITS internal data
> +
> +  KVM_DEV_ARM_VGIC_GRP_ITS_REGS
> +  Attributes:
> +      The attr field of kvm_device_attr encodes the offset of the
> +      ITS register, relative to the ITS control frame base address
> +      (ITS_base).
> +
> +      kvm_device_attr.addr points to a __u64 value whatever the width
> +      of the addressed register (32/64 bits). 64 bit registers can only
> +      be accessed with full length.
> +
> +      Writes to read-only registers are ignored by the kernel except for:
> +      - GITS_READR. It needs to be restored otherwise commands in the queue
> +        will be re-executed after CWRITER setting. Writing this register is
                                     ^^^^^^^^^^^^^^^

"after restoring CWRITER." ?

> +        allowed if the ITS is not enabled (GITS_CTLR.enable = 0). Also it

Does that mean that you can only save/restore a disabled ITS or does it
mean that initially after creating the ITS it is disabled and userspace
should restore the CWRITER before restoring GITS_CTLR (which may enable
the ITS) ?

> +        needs to be restored after GITS_CBASER since a write to GITS_CBASER
> +        resets GITS_CREADR.
> +      - GITS_IIDR. Its Revision field encodes the table layout ABI revision.

How is this really going to work?  Your ABI here must be backwards
compatible for future revisions, so what is userspace supposed to do,
when it reads a newer revision than it was programmed for?

I think we need a more clear description of how the revision is going to
be used, such that each operation on the ITS here is described as
requiring a minimum revision X, and making sure that userspace can
safely ignore things that are of a higher revision number, while at the
same time userspace can decide not to use newer features with older
kernels.

> +
> +      For other registers, getting or setting a register has the same
> +      effect as reading/writing the register on real hardware.
> +  Errors:
> +    -ENXIO: Offset does not correspond to any supported register
> +    -EFAULT: Invalid user pointer for attr->addr
> +    -EINVAL: Offset is not 64-bit aligned
> +    -EBUSY: one or more VCPUS are running
> +
> +  KVM_DEV_ARM_VGIC_GRP_ITS_TABLES

Shouldn't this be called KVM_DEV_ARM_VGIC_GRP_FLUSH_ITS_TABLES ?

> +  Attributes
> +       The attr field of kvm_device_attr must be zero.
> +
> +       request the flush-save/restore of the ITS tables, namely

Nit: Request (upper case R)

what does flush-save/restore mean as opposed to just flush?

> +       the device table, the collection table, all the ITT tables,
> +       the LPI pending tables. On save, the tables are flushed

, and the LPI pending table.

> +       into guest memory at the location provisioned by the guest
> +       in GITS_BASER (device and collection tables), in the MAPD
> +       command (ITT_addr), GICR_PENDBASERs (pending tables).
> +
> +       This means the GIC should be restored before the ITS and all

should or must?  Is this enforced?

> +       ITS registers but the GITS_CTLR must be restored before
> +       restoring the ITS tables.
> +
> +       The GITS_READR and GITS_IIDR read-only registers must also
> +       be restored before the table restore. The IIDR revision field
> +       encodes the ABI revision of the table layout. If not set by
> +       user space, the restoration of the tables will fail.

consider rewording: ", restoring the ITS tables will fail."

> +
> +       Note the LPI configuration table is read-only for the

Note that

> +       in-kernel ITS and its save/restore goes through the standard

and saving/restoring it is done via the normal process to save/restore
guest RAM.

> +       RAM save/restore.
> +
> +       The layout of the tables in guest memory defines an ABI.
> +       The entries are laid in little endian format as follows;

s/;/:/

It's a bit weird to say "as follows:" and then proceed with the error
descriptions.  I would simply say "as described in the following
paragraph."

> +
> +  Errors:
> +    -EINVAL: kvm_device_attr not equal to 0, invalid table data
> +    -EFAULT: invalid guest ram access
> +    -EBUSY: one or more VCPUS are running
> +
> +    ITS Table ABI REV1:
> +    -------------------
> +
> +    The device table and ITE are respectively indexed by device id and

s/ITE/ITT/

are indexed by the device id and eventid, respectively.

> +    eventid. The collection table however is not indexed by collection id:

...by collection id, instead all the CTEs are written...

> +    CTE are written at the beginning of the buffer.

in any particular order, or?

> +
> +    Device Table Entry (DTE) layout: entry size = 8 bytes
> +
> +    bits:     | 63| 62 ... 49 | 48 ... 5 | 4 ... 0 |
> +    values:   | V |   next    | ITT_addr |  Size   |
> +
> +    where;
> +    - V indicates whether the entry is valid,
> +    - ITT_addr matches bits [51:8] of the ITT address (256B aligned),
> +    - next field is meaningful only if the entry is valid.

is the ITT_addr meaningful if the entry is not valid?

> +    It equals to 0 if this entry is the last one; otherwise it corresponds
> +    to the minimum between the offset to the next device id and 2^14 -1.

I don't easily understand this last paragraph and the indentation is
weird and makes it look like it's not explaining the next field.

You're missing a description of the size field.  Size in what unit?
Size of what?


> +
> +    Collection Table Entry (CTE) layout: entry size = 8 bytes
> +
> +    bits:     | 63| 62 ..  52  | 51 ... 16 | 15  ...   0 |
> +    values:   | V |    RES0    |  RDBase   |    ICID     |
> +
> +    where:
> +    - V indicates whether the entry is valid,

Do we explain anywhere what RES0 means?

> +    - RDBase matches the PE number (GICR_TYPER.Processor_Number),

is 'matches' the right verb to use here?

What exactly is the format of GICR_TYPER.Processor_Number ?

> +    - ICID matches the collection ID

again, is 'matches' the right verb to use here?

> +
> +    Interrupt Translation Entry (ITE) layout: entry size = 8 bytes
> +
> +    bits:     | 63 ... 48 | 47 ... 16 | 15 ... 0 |
> +    values:   |    next   |   pINTID  |  ICID    |
> +
> +    where:
> +    - pINTID is the physical LPI ID,
> +    - ICID is the collection ID,

here you use 'is' intead of 'matches'.  At leat be consistent.

> +    - next field is meaningful only if the entry is valid (pINTID != 0).
> +    It equals to 0 if this entry is the last one; otherwise it corresponds
> +    to the minimum between the eventid offset to the next ITE and 2^16 -1.

same comments, as above.

also, can you list the field in the order they appear?

> +
> +    LPI Pending Table layout:
> +
> +    As specified in the ARM Generic Interrupt Controller Architecture
> +    Specification GIC Architecture version 3.0 and version 4. The first

"...version 4, the first".  ("As specified in X." is not a sentence).

> +    1kB is not modified and therefore should contain zeroes.

should or must?  or always contains zeros?  Will you return an error if
userspace puts something non-zero in there?

> +
> +    Future evolutions of the ITS table layout:
> +
> +    At the moment the table layout is defined and optimized for physical
> +    LPI support.

This comment is a bit confusing, because this is all about virtual
interrupts really, so 'physical from the point of view of the VM', but I
think you should just drop this sentence.

> +
> +    In the future we might implement direct injection of virtual LPIS.

For nesting, yes?  (on the host this should not be visible here, should
it?)

> +    This will require an upgrade of the table layout and an evolution of
> +    the ABI. The ABI revision is encoded in the GITS_IIDR revision field.
> +    That register must be restored before the table restoration, otherwise
> +    the operation will fail.

Hmm, I thought we dealt with that before, feels a bit out of place.

> +
> +    ABI V1: GITS_IIDR.Revision = 1

I feel like this should go in the ITS register description of the IIDR.
Most likely, I think this particular line can be dropped, but all other
definitions in this file can be annoted with a minimum revision number
ensuring that future revisions implement this, plus potentially more
stuff.

Thanks,
-Christoffer

^ permalink raw reply	[flat|nested] 144+ messages in thread

* Re: [PATCH v4 11/22] KVM: arm64: ITS: Interpret MAPD ITT_addr field
  2017-03-27  9:31   ` Eric Auger
  (?)
@ 2017-04-08 18:58     ` Marc Zyngier
  -1 siblings, 0 replies; 144+ messages in thread
From: Marc Zyngier @ 2017-04-08 18:58 UTC (permalink / raw)
  To: Eric Auger
  Cc: eric.auger.pro, christoffer.dall, andre.przywara, vijayak,
	Vijaya.Kumar, peter.maydell, linux-arm-kernel, kvmarm, kvm,
	Prasun.Kapoor, drjones, pbonzini, dgilbert, quintela

On Mon, Mar 27 2017 at 10:31:01 AM, Eric Auger <eric.auger@redhat.com> wrote:
> Up to now the MAPD ITT_addr had been ignored. We will need it
> for save/restore. Let's record it in the its_device struct.
>
> Signed-off-by: Eric Auger <eric.auger@redhat.com>
>
> ---
>
> v3 -> v4:
> - in vgic_its_cmd_handle_mapd, itt_addr directly is shifted
> - correct ittaddr bitmask to support 48bit GPA
> ---
>  virt/kvm/arm/vgic/vgic-its.c | 4 ++++
>  1 file changed, 4 insertions(+)
>
> diff --git a/virt/kvm/arm/vgic/vgic-its.c b/virt/kvm/arm/vgic/vgic-its.c
> index ddd2780..89a0db7 100644
> --- a/virt/kvm/arm/vgic/vgic-its.c
> +++ b/virt/kvm/arm/vgic/vgic-its.c
> @@ -103,6 +103,7 @@ struct its_device {
>  	/* the head for the list of ITTEs */
>  	struct list_head itt_head;
>  	u32 nb_eventid_bits;
> +	gpa_t itt_addr;
>  	u32 device_id;
>  };
>  
> @@ -553,6 +554,7 @@ static u64 its_cmd_mask_field(u64 *its_cmd, int word, int shift, int size)
>  #define its_cmd_get_id(cmd)		its_cmd_mask_field(cmd, 1,  0, 32)
>  #define its_cmd_get_physical_id(cmd)	its_cmd_mask_field(cmd, 1, 32, 32)
>  #define its_cmd_get_collection(cmd)	its_cmd_mask_field(cmd, 2,  0, 16)
> +#define its_cmd_get_ittaddr(cmd)	its_cmd_mask_field(cmd, 2,  8, 47)
>  #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)
>  
> @@ -824,6 +826,7 @@ static int vgic_its_cmd_handle_mapd(struct kvm *kvm, struct vgic_its *its,
>  	u32 device_id = its_cmd_get_deviceid(its_cmd);
>  	bool valid = its_cmd_get_validbit(its_cmd);
>  	u8 nb_eventid_bits = its_cmd_get_size(its_cmd) + 1;
> +	gpa_t itt_addr = its_cmd_get_ittaddr(its_cmd) << 8;

Same remark as previously. I'd rather have the macro returning something
that is directly useful rather than having to shift afterwards.

>  	struct its_device *device;
>  
>  	if (!vgic_its_check_id(its, its->baser_device_table, device_id))
> @@ -855,6 +858,7 @@ static int vgic_its_cmd_handle_mapd(struct kvm *kvm, struct vgic_its *its,
>  
>  	device->device_id = device_id;
>  	device->nb_eventid_bits = nb_eventid_bits;
> +	device->itt_addr = itt_addr;
>  
>  	INIT_LIST_HEAD(&device->itt_head);

Thanks,

	M.
-- 
Jazz is not dead. It just smells funny.

^ permalink raw reply	[flat|nested] 144+ messages in thread

* Re: [PATCH v4 11/22] KVM: arm64: ITS: Interpret MAPD ITT_addr field
@ 2017-04-08 18:58     ` Marc Zyngier
  0 siblings, 0 replies; 144+ messages in thread
From: Marc Zyngier @ 2017-04-08 18:58 UTC (permalink / raw)
  To: Eric Auger
  Cc: eric.auger.pro, christoffer.dall, andre.przywara, vijayak,
	Vijaya.Kumar, peter.maydell, linux-arm-kernel, kvmarm, kvm,
	Prasun.Kapoor, drjones, pbonzini, dgilbert, quintela

On Mon, Mar 27 2017 at 10:31:01 AM, Eric Auger <eric.auger@redhat.com> wrote:
> Up to now the MAPD ITT_addr had been ignored. We will need it
> for save/restore. Let's record it in the its_device struct.
>
> Signed-off-by: Eric Auger <eric.auger@redhat.com>
>
> ---
>
> v3 -> v4:
> - in vgic_its_cmd_handle_mapd, itt_addr directly is shifted
> - correct ittaddr bitmask to support 48bit GPA
> ---
>  virt/kvm/arm/vgic/vgic-its.c | 4 ++++
>  1 file changed, 4 insertions(+)
>
> diff --git a/virt/kvm/arm/vgic/vgic-its.c b/virt/kvm/arm/vgic/vgic-its.c
> index ddd2780..89a0db7 100644
> --- a/virt/kvm/arm/vgic/vgic-its.c
> +++ b/virt/kvm/arm/vgic/vgic-its.c
> @@ -103,6 +103,7 @@ struct its_device {
>  	/* the head for the list of ITTEs */
>  	struct list_head itt_head;
>  	u32 nb_eventid_bits;
> +	gpa_t itt_addr;
>  	u32 device_id;
>  };
>  
> @@ -553,6 +554,7 @@ static u64 its_cmd_mask_field(u64 *its_cmd, int word, int shift, int size)
>  #define its_cmd_get_id(cmd)		its_cmd_mask_field(cmd, 1,  0, 32)
>  #define its_cmd_get_physical_id(cmd)	its_cmd_mask_field(cmd, 1, 32, 32)
>  #define its_cmd_get_collection(cmd)	its_cmd_mask_field(cmd, 2,  0, 16)
> +#define its_cmd_get_ittaddr(cmd)	its_cmd_mask_field(cmd, 2,  8, 47)
>  #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)
>  
> @@ -824,6 +826,7 @@ static int vgic_its_cmd_handle_mapd(struct kvm *kvm, struct vgic_its *its,
>  	u32 device_id = its_cmd_get_deviceid(its_cmd);
>  	bool valid = its_cmd_get_validbit(its_cmd);
>  	u8 nb_eventid_bits = its_cmd_get_size(its_cmd) + 1;
> +	gpa_t itt_addr = its_cmd_get_ittaddr(its_cmd) << 8;

Same remark as previously. I'd rather have the macro returning something
that is directly useful rather than having to shift afterwards.

>  	struct its_device *device;
>  
>  	if (!vgic_its_check_id(its, its->baser_device_table, device_id))
> @@ -855,6 +858,7 @@ static int vgic_its_cmd_handle_mapd(struct kvm *kvm, struct vgic_its *its,
>  
>  	device->device_id = device_id;
>  	device->nb_eventid_bits = nb_eventid_bits;
> +	device->itt_addr = itt_addr;
>  
>  	INIT_LIST_HEAD(&device->itt_head);

Thanks,

	M.
-- 
Jazz is not dead. It just smells funny.

^ permalink raw reply	[flat|nested] 144+ messages in thread

* [PATCH v4 11/22] KVM: arm64: ITS: Interpret MAPD ITT_addr field
@ 2017-04-08 18:58     ` Marc Zyngier
  0 siblings, 0 replies; 144+ messages in thread
From: Marc Zyngier @ 2017-04-08 18:58 UTC (permalink / raw)
  To: linux-arm-kernel

On Mon, Mar 27 2017 at 10:31:01 AM, Eric Auger <eric.auger@redhat.com> wrote:
> Up to now the MAPD ITT_addr had been ignored. We will need it
> for save/restore. Let's record it in the its_device struct.
>
> Signed-off-by: Eric Auger <eric.auger@redhat.com>
>
> ---
>
> v3 -> v4:
> - in vgic_its_cmd_handle_mapd, itt_addr directly is shifted
> - correct ittaddr bitmask to support 48bit GPA
> ---
>  virt/kvm/arm/vgic/vgic-its.c | 4 ++++
>  1 file changed, 4 insertions(+)
>
> diff --git a/virt/kvm/arm/vgic/vgic-its.c b/virt/kvm/arm/vgic/vgic-its.c
> index ddd2780..89a0db7 100644
> --- a/virt/kvm/arm/vgic/vgic-its.c
> +++ b/virt/kvm/arm/vgic/vgic-its.c
> @@ -103,6 +103,7 @@ struct its_device {
>  	/* the head for the list of ITTEs */
>  	struct list_head itt_head;
>  	u32 nb_eventid_bits;
> +	gpa_t itt_addr;
>  	u32 device_id;
>  };
>  
> @@ -553,6 +554,7 @@ static u64 its_cmd_mask_field(u64 *its_cmd, int word, int shift, int size)
>  #define its_cmd_get_id(cmd)		its_cmd_mask_field(cmd, 1,  0, 32)
>  #define its_cmd_get_physical_id(cmd)	its_cmd_mask_field(cmd, 1, 32, 32)
>  #define its_cmd_get_collection(cmd)	its_cmd_mask_field(cmd, 2,  0, 16)
> +#define its_cmd_get_ittaddr(cmd)	its_cmd_mask_field(cmd, 2,  8, 47)
>  #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)
>  
> @@ -824,6 +826,7 @@ static int vgic_its_cmd_handle_mapd(struct kvm *kvm, struct vgic_its *its,
>  	u32 device_id = its_cmd_get_deviceid(its_cmd);
>  	bool valid = its_cmd_get_validbit(its_cmd);
>  	u8 nb_eventid_bits = its_cmd_get_size(its_cmd) + 1;
> +	gpa_t itt_addr = its_cmd_get_ittaddr(its_cmd) << 8;

Same remark as previously. I'd rather have the macro returning something
that is directly useful rather than having to shift afterwards.

>  	struct its_device *device;
>  
>  	if (!vgic_its_check_id(its, its->baser_device_table, device_id))
> @@ -855,6 +858,7 @@ static int vgic_its_cmd_handle_mapd(struct kvm *kvm, struct vgic_its *its,
>  
>  	device->device_id = device_id;
>  	device->nb_eventid_bits = nb_eventid_bits;
> +	device->itt_addr = itt_addr;
>  
>  	INIT_LIST_HEAD(&device->itt_head);

Thanks,

	M.
-- 
Jazz is not dead. It just smells funny.

^ permalink raw reply	[flat|nested] 144+ messages in thread

* Re: [PATCH v4 13/22] KVM: arm64: ITS: KVM_DEV_ARM_VGIC_GRP_ITS_TABLES group
  2017-03-27  9:31   ` Eric Auger
@ 2017-04-09 10:09     ` Marc Zyngier
  -1 siblings, 0 replies; 144+ messages in thread
From: Marc Zyngier @ 2017-04-09 10:09 UTC (permalink / raw)
  To: Eric Auger
  Cc: kvm, Prasun.Kapoor, vijayak, andre.przywara, quintela, dgilbert,
	Vijaya.Kumar, linux-arm-kernel, pbonzini, kvmarm, eric.auger.pro

On Mon, Mar 27 2017 at 10:31:03 AM, Eric Auger <eric.auger@redhat.com> wrote:
> Introduce a new group aiming at saving/restoring the ITS
> tables to/from the guest memory.
>
> We hold the vcpus lock during the save and restore to make
> sure no vcpu is running.
>
> At this stage the functionality is not yet implemented. Only
> the skeleton is put in place.
>
> The ABI revision supposed to have been set through IIDR user
> write is checked before the table restoration. This guarantees
> this vITS knows how to restore the saved tables.

This last point hints at the kernel side being able to deal with
multiple versions of the ABI. As I mentioned before, this requires some
clarification on what we plan to support, and whether or not we are able
to deprecate ABIs in the long run

One thing that is not clear to me is that although you want to be able
to restore the vITS using a given ABI, should you be able to save it
using that same ABI? Or does a restore/save cycle act as an ABI upgrade
for this VM?

I'd also like to see some infrastructure in the code to support this, in
the form of a per-ABI array of support functions (even if we only have
one ABI for the time being). Although that's not required ATM, it would
certainly halp me understanding what is ABI-specific and what's not.

Thanks,

	M.
-- 
Jazz is not dead. It just smells funny.

^ permalink raw reply	[flat|nested] 144+ messages in thread

* [PATCH v4 13/22] KVM: arm64: ITS: KVM_DEV_ARM_VGIC_GRP_ITS_TABLES group
@ 2017-04-09 10:09     ` Marc Zyngier
  0 siblings, 0 replies; 144+ messages in thread
From: Marc Zyngier @ 2017-04-09 10:09 UTC (permalink / raw)
  To: linux-arm-kernel

On Mon, Mar 27 2017 at 10:31:03 AM, Eric Auger <eric.auger@redhat.com> wrote:
> Introduce a new group aiming at saving/restoring the ITS
> tables to/from the guest memory.
>
> We hold the vcpus lock during the save and restore to make
> sure no vcpu is running.
>
> At this stage the functionality is not yet implemented. Only
> the skeleton is put in place.
>
> The ABI revision supposed to have been set through IIDR user
> write is checked before the table restoration. This guarantees
> this vITS knows how to restore the saved tables.

This last point hints at the kernel side being able to deal with
multiple versions of the ABI. As I mentioned before, this requires some
clarification on what we plan to support, and whether or not we are able
to deprecate ABIs in the long run

One thing that is not clear to me is that although you want to be able
to restore the vITS using a given ABI, should you be able to save it
using that same ABI? Or does a restore/save cycle act as an ABI upgrade
for this VM?

I'd also like to see some infrastructure in the code to support this, in
the form of a per-ABI array of support functions (even if we only have
one ABI for the time being). Although that's not required ATM, it would
certainly halp me understanding what is ABI-specific and what's not.

Thanks,

	M.
-- 
Jazz is not dead. It just smells funny.

^ permalink raw reply	[flat|nested] 144+ messages in thread

* Re: [PATCH v4 14/22] KVM: arm64: ITS: vgic_its_alloc_ite/device
  2017-03-27  9:31   ` Eric Auger
@ 2017-04-09 10:13     ` Marc Zyngier
  -1 siblings, 0 replies; 144+ messages in thread
From: Marc Zyngier @ 2017-04-09 10:13 UTC (permalink / raw)
  To: Eric Auger
  Cc: kvm, Prasun.Kapoor, vijayak, andre.przywara, quintela, dgilbert,
	Vijaya.Kumar, linux-arm-kernel, pbonzini, kvmarm, eric.auger.pro

On Mon, Mar 27 2017 at 10:31:04 AM, Eric Auger <eric.auger@redhat.com> wrote:
> Add two new helpers to allocate an its ite and an its device.
> This will avoid duplication on restore path.
>
> Signed-off-by: Eric Auger <eric.auger@redhat.com>

Acked-by: Marc Zyngier <marc.zyngier@arm.com>

	M.
-- 
Jazz is not dead. It just smells funny.

^ permalink raw reply	[flat|nested] 144+ messages in thread

* [PATCH v4 14/22] KVM: arm64: ITS: vgic_its_alloc_ite/device
@ 2017-04-09 10:13     ` Marc Zyngier
  0 siblings, 0 replies; 144+ messages in thread
From: Marc Zyngier @ 2017-04-09 10:13 UTC (permalink / raw)
  To: linux-arm-kernel

On Mon, Mar 27 2017 at 10:31:04 AM, Eric Auger <eric.auger@redhat.com> wrote:
> Add two new helpers to allocate an its ite and an its device.
> This will avoid duplication on restore path.
>
> Signed-off-by: Eric Auger <eric.auger@redhat.com>

Acked-by: Marc Zyngier <marc.zyngier@arm.com>

	M.
-- 
Jazz is not dead. It just smells funny.

^ permalink raw reply	[flat|nested] 144+ messages in thread

* Re: [PATCH v4 15/22] KVM: arm64: ITS: Sort the device and ITE lists
  2017-03-27  9:31   ` Eric Auger
@ 2017-04-09 10:18     ` Marc Zyngier
  -1 siblings, 0 replies; 144+ messages in thread
From: Marc Zyngier @ 2017-04-09 10:18 UTC (permalink / raw)
  To: Eric Auger
  Cc: kvm, Prasun.Kapoor, vijayak, andre.przywara, quintela, dgilbert,
	Vijaya.Kumar, linux-arm-kernel, pbonzini, kvmarm, eric.auger.pro

On Mon, Mar 27 2017 at 10:31:05 AM, Eric Auger <eric.auger@redhat.com> wrote:
> Natively sort the device and ITE lists in ascending
> deviceId/eventid order. This paves the way to optimized
> DTE and ITE scan in guest RAM table where entries are chained
> together using a next ID offset.
>
> Signed-off-by: Eric Auger <eric.auger@redhat.com>
> Reviewed-by: Andre Przywara <andre.przywara@arm.com>
>
> ---
>
> v3 -> v4:
> - added Andre's R-b
> ---
>  virt/kvm/arm/vgic/vgic-its.c | 36 ++++++++++++++++++++++++++++++++++--
>  1 file changed, 34 insertions(+), 2 deletions(-)
>
> diff --git a/virt/kvm/arm/vgic/vgic-its.c b/virt/kvm/arm/vgic/vgic-its.c
> index 2a1ccbf..7364b7d 100644
> --- a/virt/kvm/arm/vgic/vgic-its.c
> +++ b/virt/kvm/arm/vgic/vgic-its.c
> @@ -726,6 +726,21 @@ static void vgic_its_free_collection(struct vgic_its *its, u32 coll_id)
>  	kfree(collection);
>  }
>  
> +static void ite_list_insert_sorted(struct list_head *h, struct its_ite *ite)
> +{
> +	struct list_head *pos = h->next;
> +	u32 id = ite->event_id;
> +
> +	while (pos != h) {
> +		struct its_ite *iter =
> +			list_entry(pos, struct its_ite, ite_list);
> +		if (id < iter->event_id)
> +			break;
> +		pos = pos->next;
> +	}
> +	list_add_tail(&ite->ite_list, pos);
> +}
> +
>  /* Must be called with its_lock mutex held */
>  static int vgic_its_alloc_ite(struct its_device *device,
>  			       struct its_ite **itep,
> @@ -742,7 +757,7 @@ static int vgic_its_alloc_ite(struct its_device *device,
>  	ite->collection = collection;
>  	ite->lpi = lpi_id;
>  
> -	list_add_tail(&ite->ite_list, &device->itt_head);
> +	ite_list_insert_sorted(&device->itt_head, ite);
>  	*itep = ite;
>  	return 0;
>  }
> @@ -835,6 +850,22 @@ static void vgic_its_unmap_device(struct kvm *kvm, struct its_device *device)
>  	kfree(device);
>  }
>  
> +static void device_list_insert_sorted(struct list_head *h,
> +				      struct its_device *dev)
> +{
> +	struct list_head *pos = h->next;
> +	u32 id = dev->device_id;
> +
> +	while (pos != h) {
> +		struct its_device *iter =
> +			list_entry(pos, struct its_device, dev_list);
> +		if (id < iter->device_id)
> +			break;
> +		pos = pos->next;
> +	}
> +	list_add_tail(&dev->dev_list, pos);
> +}
> +
>  /* Must be called with its_lock mutex held */
>  static int vgic_its_alloc_device(struct vgic_its *its,
>  				 struct its_device **devp,
> @@ -852,7 +883,8 @@ static int vgic_its_alloc_device(struct vgic_its *its,
>  	device->nb_eventid_bits = nb_eventid_bits;
>  	INIT_LIST_HEAD(&device->itt_head);
>  
> -	list_add_tail(&device->dev_list, &its->device_list);
> +	device_list_insert_sorted(&its->device_list, device);
> +
>  	*devp = device;
>  
>  	return 0;

What is the actual gain for sorting the list at runtime, vs sorting it
at save time? A save/restore operation is a very rare event compared to
the normal use of the ITS, so I'd rather put the overhead on the rarest
event if possible.

Thanks,

	M.
-- 
Jazz is not dead. It just smells funny.

^ permalink raw reply	[flat|nested] 144+ messages in thread

* [PATCH v4 15/22] KVM: arm64: ITS: Sort the device and ITE lists
@ 2017-04-09 10:18     ` Marc Zyngier
  0 siblings, 0 replies; 144+ messages in thread
From: Marc Zyngier @ 2017-04-09 10:18 UTC (permalink / raw)
  To: linux-arm-kernel

On Mon, Mar 27 2017 at 10:31:05 AM, Eric Auger <eric.auger@redhat.com> wrote:
> Natively sort the device and ITE lists in ascending
> deviceId/eventid order. This paves the way to optimized
> DTE and ITE scan in guest RAM table where entries are chained
> together using a next ID offset.
>
> Signed-off-by: Eric Auger <eric.auger@redhat.com>
> Reviewed-by: Andre Przywara <andre.przywara@arm.com>
>
> ---
>
> v3 -> v4:
> - added Andre's R-b
> ---
>  virt/kvm/arm/vgic/vgic-its.c | 36 ++++++++++++++++++++++++++++++++++--
>  1 file changed, 34 insertions(+), 2 deletions(-)
>
> diff --git a/virt/kvm/arm/vgic/vgic-its.c b/virt/kvm/arm/vgic/vgic-its.c
> index 2a1ccbf..7364b7d 100644
> --- a/virt/kvm/arm/vgic/vgic-its.c
> +++ b/virt/kvm/arm/vgic/vgic-its.c
> @@ -726,6 +726,21 @@ static void vgic_its_free_collection(struct vgic_its *its, u32 coll_id)
>  	kfree(collection);
>  }
>  
> +static void ite_list_insert_sorted(struct list_head *h, struct its_ite *ite)
> +{
> +	struct list_head *pos = h->next;
> +	u32 id = ite->event_id;
> +
> +	while (pos != h) {
> +		struct its_ite *iter =
> +			list_entry(pos, struct its_ite, ite_list);
> +		if (id < iter->event_id)
> +			break;
> +		pos = pos->next;
> +	}
> +	list_add_tail(&ite->ite_list, pos);
> +}
> +
>  /* Must be called with its_lock mutex held */
>  static int vgic_its_alloc_ite(struct its_device *device,
>  			       struct its_ite **itep,
> @@ -742,7 +757,7 @@ static int vgic_its_alloc_ite(struct its_device *device,
>  	ite->collection = collection;
>  	ite->lpi = lpi_id;
>  
> -	list_add_tail(&ite->ite_list, &device->itt_head);
> +	ite_list_insert_sorted(&device->itt_head, ite);
>  	*itep = ite;
>  	return 0;
>  }
> @@ -835,6 +850,22 @@ static void vgic_its_unmap_device(struct kvm *kvm, struct its_device *device)
>  	kfree(device);
>  }
>  
> +static void device_list_insert_sorted(struct list_head *h,
> +				      struct its_device *dev)
> +{
> +	struct list_head *pos = h->next;
> +	u32 id = dev->device_id;
> +
> +	while (pos != h) {
> +		struct its_device *iter =
> +			list_entry(pos, struct its_device, dev_list);
> +		if (id < iter->device_id)
> +			break;
> +		pos = pos->next;
> +	}
> +	list_add_tail(&dev->dev_list, pos);
> +}
> +
>  /* Must be called with its_lock mutex held */
>  static int vgic_its_alloc_device(struct vgic_its *its,
>  				 struct its_device **devp,
> @@ -852,7 +883,8 @@ static int vgic_its_alloc_device(struct vgic_its *its,
>  	device->nb_eventid_bits = nb_eventid_bits;
>  	INIT_LIST_HEAD(&device->itt_head);
>  
> -	list_add_tail(&device->dev_list, &its->device_list);
> +	device_list_insert_sorted(&its->device_list, device);
> +
>  	*devp = device;
>  
>  	return 0;

What is the actual gain for sorting the list at runtime, vs sorting it
at save time? A save/restore operation is a very rare event compared to
the normal use of the ITS, so I'd rather put the overhead on the rarest
event if possible.

Thanks,

	M.
-- 
Jazz is not dead. It just smells funny.

^ permalink raw reply	[flat|nested] 144+ messages in thread

* Re: [PATCH v4 17/22] KVM: arm64: ITS: Add infrastructure for table lookup
  2017-03-27  9:31   ` Eric Auger
@ 2017-04-09 10:36     ` Marc Zyngier
  -1 siblings, 0 replies; 144+ messages in thread
From: Marc Zyngier @ 2017-04-09 10:36 UTC (permalink / raw)
  To: Eric Auger
  Cc: kvm, Prasun.Kapoor, vijayak, andre.przywara, quintela, dgilbert,
	Vijaya.Kumar, linux-arm-kernel, pbonzini, kvmarm, eric.auger.pro

On Mon, Mar 27 2017 at 10:31:07 AM, Eric Auger <eric.auger@redhat.com> wrote:
> Add a generic lookup_table() helper whose role consists in
> scanning a contiguous table located in guest RAM and applying
> a callback on each entry. Entries can be handled as linked lists
> since the callback may return an offset to the next entry and
> also tell that an entry is the last one.
>
> Helper functions also are added to compute the device/event ID
> offset to the next DTE/ITE.
>
> compute_next_devid_offset, compute_next_eventid_offset and
> lookup_table will become static in subsequent patches
>
> Signed-off-by: Eric Auger <eric.auger@redhat.com>
>
> ---
>
> v3 -> v4:
> - remove static to avoid compilation warning
> - correct size computation in looup_table()
> - defines now encode the number of bits used for devid and eventid offsets
> - use BIT() - 1 to encode the max offets
> ---
>  virt/kvm/arm/vgic/vgic-its.c | 107 +++++++++++++++++++++++++++++++++++++++++++
>  1 file changed, 107 insertions(+)
>
> diff --git a/virt/kvm/arm/vgic/vgic-its.c b/virt/kvm/arm/vgic/vgic-its.c
> index 7364b7d..8eaeba4 100644
> --- a/virt/kvm/arm/vgic/vgic-its.c
> +++ b/virt/kvm/arm/vgic/vgic-its.c
> @@ -184,6 +184,8 @@ static struct its_ite *find_ite(struct vgic_its *its, u32 device_id,
>  #define VITS_ESZ 8
>  #define VITS_TYPER_IDBITS 16
>  #define VITS_TYPER_DEVBITS 16
> +#define VITS_DTE_MAX_DEVID_OFFSET	(BIT(14) - 1)
> +#define VITS_ITE_MAX_EVENTID_OFFSET	(BIT(16) - 1)
>  
>  /*
>   * Finds and returns a collection in the ITS collection table.
> @@ -1686,6 +1688,111 @@ 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)
> +{
> +	struct list_head *e = &dev->dev_list;
> +	struct its_device *next;
> +	u32 next_offset;
> +
> +	if (e->next == h)
> +		return 0;
> +	next = list_entry(e->next, struct its_device, dev_list);
> +	next_offset = next->device_id - dev->device_id;
> +
> +	return min_t(u32, next_offset, VITS_DTE_MAX_DEVID_OFFSET);
> +}
> +
> +u32 compute_next_eventid_offset(struct list_head *h, struct its_ite *ite)
> +{
> +	struct list_head *e = &ite->ite_list;
> +	struct its_ite *next;
> +	u32 next_offset;
> +
> +	if (e->next == h)
> +		return 0;
> +	next = list_entry(e->next, struct its_ite, ite_list);
> +	next_offset = next->event_id - ite->event_id;
> +
> +	return min_t(u32, next_offset, VITS_ITE_MAX_EVENTID_OFFSET);
> +}
> +
> +/**
> + * entry_fn_t - Callback called on a table entry restore path
> + * @its: its handle
> + * @id: id of the entry
> + * @addr: kernel VA of the entry
> + * @opaque: pointer to an opaque data
> + * @next_offset: minimal ID offset to the next entry. 0 if this
> + * entry is the last one, 1 if the entry is invalid, >= 1 if an
> + * entry's next_offset field was truly decoded
> + *
> + * Return: < 0 on error, 0 otherwise
> + */
> +typedef int (*entry_fn_t)(struct vgic_its *its, u32 id, void *addr,
> +			  void *opaque, u32 *next_offset);
> +
> +/**
> + * lookup_table - scans a contiguous table in guest RAM and applies a function
> + * to each entry
> + *
> + * @its: its handle
> + * @base: base gpa of the table
> + * @size: size of the table in bytes
> + * @esz: entry size in bytes
> + * @start_id: first entry's ID
> + * @fn: function to apply on each entry
> + *
> + * Return: < 0 on error, 1 if last element identified, 0 otherwise
> + */
> +int lookup_table(struct vgic_its *its, gpa_t base, int size, int esz,
> +		 int start_id, entry_fn_t fn, void *opaque)
> +{
> +	gpa_t gpa = base, top = base + size - 1;
> +	unsigned long len = size;
> +	int ret, seg, offset = offset_in_page(gpa);
> +	gfn_t gfn = gpa >> PAGE_SHIFT;
> +	u32 id = start_id + (gpa - base)/esz;
> +	struct kvm *kvm = its->dev->kvm;
> +	kvm_pfn_t pfn;
> +
> +	while ((seg = next_segment(len, offset)) != 0) {
> +		u32 next_offset;
> +		bool writeable;
> +		void *addr;
> +
> +		pfn = gfn_to_pfn_prot(kvm, gfn, true, &writeable);
> +		if (is_error_noslot_pfn(pfn))
> +			return -EINVAL;
> +		addr = phys_to_virt((u64)pfn << PAGE_SHIFT);
> +		addr += offset;

Why do we use the kernel mapping here? I'd have expected the use of
kvm_read_guest and co rather than directly accessing the memory. What
locks do we hold to ensure that the page cannot be evicted behind our
back?

> +
> +		while (seg > 0) {
> +			size_t byte_offset;
> +
> +			ret = fn(its, id, addr, opaque, &next_offset);
> +			if (ret < 0 || (!ret && !next_offset))
> +				goto out;
> +
> +			byte_offset = next_offset * esz;
> +
> +			id += next_offset;
> +			gpa += byte_offset;
> +			addr += byte_offset;
> +			seg -= byte_offset;
> +		}
> +		kvm_release_pfn_clean(pfn);
> +
> +		len = top - gpa + 1;
> +		offset = offset_in_page(gpa);
> +		gfn = gpa >> PAGE_SHIFT;
> +		id = start_id + (gpa - base)/esz;
> +	}
> +	return 0;
> +out:
> +	kvm_release_pfn_clean(pfn);
> +	return (ret < 0 ? ret : 1);
> +}
> +
>  /**
>   * vgic_its_flush_pending_tables - Flush the pending tables into guest RAM
>   */

Thanks,

	M.
-- 
Jazz is not dead. It just smells funny.

^ permalink raw reply	[flat|nested] 144+ messages in thread

* [PATCH v4 17/22] KVM: arm64: ITS: Add infrastructure for table lookup
@ 2017-04-09 10:36     ` Marc Zyngier
  0 siblings, 0 replies; 144+ messages in thread
From: Marc Zyngier @ 2017-04-09 10:36 UTC (permalink / raw)
  To: linux-arm-kernel

On Mon, Mar 27 2017 at 10:31:07 AM, Eric Auger <eric.auger@redhat.com> wrote:
> Add a generic lookup_table() helper whose role consists in
> scanning a contiguous table located in guest RAM and applying
> a callback on each entry. Entries can be handled as linked lists
> since the callback may return an offset to the next entry and
> also tell that an entry is the last one.
>
> Helper functions also are added to compute the device/event ID
> offset to the next DTE/ITE.
>
> compute_next_devid_offset, compute_next_eventid_offset and
> lookup_table will become static in subsequent patches
>
> Signed-off-by: Eric Auger <eric.auger@redhat.com>
>
> ---
>
> v3 -> v4:
> - remove static to avoid compilation warning
> - correct size computation in looup_table()
> - defines now encode the number of bits used for devid and eventid offsets
> - use BIT() - 1 to encode the max offets
> ---
>  virt/kvm/arm/vgic/vgic-its.c | 107 +++++++++++++++++++++++++++++++++++++++++++
>  1 file changed, 107 insertions(+)
>
> diff --git a/virt/kvm/arm/vgic/vgic-its.c b/virt/kvm/arm/vgic/vgic-its.c
> index 7364b7d..8eaeba4 100644
> --- a/virt/kvm/arm/vgic/vgic-its.c
> +++ b/virt/kvm/arm/vgic/vgic-its.c
> @@ -184,6 +184,8 @@ static struct its_ite *find_ite(struct vgic_its *its, u32 device_id,
>  #define VITS_ESZ 8
>  #define VITS_TYPER_IDBITS 16
>  #define VITS_TYPER_DEVBITS 16
> +#define VITS_DTE_MAX_DEVID_OFFSET	(BIT(14) - 1)
> +#define VITS_ITE_MAX_EVENTID_OFFSET	(BIT(16) - 1)
>  
>  /*
>   * Finds and returns a collection in the ITS collection table.
> @@ -1686,6 +1688,111 @@ 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)
> +{
> +	struct list_head *e = &dev->dev_list;
> +	struct its_device *next;
> +	u32 next_offset;
> +
> +	if (e->next == h)
> +		return 0;
> +	next = list_entry(e->next, struct its_device, dev_list);
> +	next_offset = next->device_id - dev->device_id;
> +
> +	return min_t(u32, next_offset, VITS_DTE_MAX_DEVID_OFFSET);
> +}
> +
> +u32 compute_next_eventid_offset(struct list_head *h, struct its_ite *ite)
> +{
> +	struct list_head *e = &ite->ite_list;
> +	struct its_ite *next;
> +	u32 next_offset;
> +
> +	if (e->next == h)
> +		return 0;
> +	next = list_entry(e->next, struct its_ite, ite_list);
> +	next_offset = next->event_id - ite->event_id;
> +
> +	return min_t(u32, next_offset, VITS_ITE_MAX_EVENTID_OFFSET);
> +}
> +
> +/**
> + * entry_fn_t - Callback called on a table entry restore path
> + * @its: its handle
> + * @id: id of the entry
> + * @addr: kernel VA of the entry
> + * @opaque: pointer to an opaque data
> + * @next_offset: minimal ID offset to the next entry. 0 if this
> + * entry is the last one, 1 if the entry is invalid, >= 1 if an
> + * entry's next_offset field was truly decoded
> + *
> + * Return: < 0 on error, 0 otherwise
> + */
> +typedef int (*entry_fn_t)(struct vgic_its *its, u32 id, void *addr,
> +			  void *opaque, u32 *next_offset);
> +
> +/**
> + * lookup_table - scans a contiguous table in guest RAM and applies a function
> + * to each entry
> + *
> + * @its: its handle
> + * @base: base gpa of the table
> + * @size: size of the table in bytes
> + * @esz: entry size in bytes
> + * @start_id: first entry's ID
> + * @fn: function to apply on each entry
> + *
> + * Return: < 0 on error, 1 if last element identified, 0 otherwise
> + */
> +int lookup_table(struct vgic_its *its, gpa_t base, int size, int esz,
> +		 int start_id, entry_fn_t fn, void *opaque)
> +{
> +	gpa_t gpa = base, top = base + size - 1;
> +	unsigned long len = size;
> +	int ret, seg, offset = offset_in_page(gpa);
> +	gfn_t gfn = gpa >> PAGE_SHIFT;
> +	u32 id = start_id + (gpa - base)/esz;
> +	struct kvm *kvm = its->dev->kvm;
> +	kvm_pfn_t pfn;
> +
> +	while ((seg = next_segment(len, offset)) != 0) {
> +		u32 next_offset;
> +		bool writeable;
> +		void *addr;
> +
> +		pfn = gfn_to_pfn_prot(kvm, gfn, true, &writeable);
> +		if (is_error_noslot_pfn(pfn))
> +			return -EINVAL;
> +		addr = phys_to_virt((u64)pfn << PAGE_SHIFT);
> +		addr += offset;

Why do we use the kernel mapping here? I'd have expected the use of
kvm_read_guest and co rather than directly accessing the memory. What
locks do we hold to ensure that the page cannot be evicted behind our
back?

> +
> +		while (seg > 0) {
> +			size_t byte_offset;
> +
> +			ret = fn(its, id, addr, opaque, &next_offset);
> +			if (ret < 0 || (!ret && !next_offset))
> +				goto out;
> +
> +			byte_offset = next_offset * esz;
> +
> +			id += next_offset;
> +			gpa += byte_offset;
> +			addr += byte_offset;
> +			seg -= byte_offset;
> +		}
> +		kvm_release_pfn_clean(pfn);
> +
> +		len = top - gpa + 1;
> +		offset = offset_in_page(gpa);
> +		gfn = gpa >> PAGE_SHIFT;
> +		id = start_id + (gpa - base)/esz;
> +	}
> +	return 0;
> +out:
> +	kvm_release_pfn_clean(pfn);
> +	return (ret < 0 ? ret : 1);
> +}
> +
>  /**
>   * vgic_its_flush_pending_tables - Flush the pending tables into guest RAM
>   */

Thanks,

	M.
-- 
Jazz is not dead. It just smells funny.

^ permalink raw reply	[flat|nested] 144+ messages in thread

* Re: [PATCH v4 18/22] KVM: arm64: ITS: Collection table save/restore
  2017-03-27  9:31   ` Eric Auger
@ 2017-04-10  9:55     ` Marc Zyngier
  -1 siblings, 0 replies; 144+ messages in thread
From: Marc Zyngier @ 2017-04-10  9:55 UTC (permalink / raw)
  To: Eric Auger, eric.auger.pro, christoffer.dall, andre.przywara,
	vijayak, Vijaya.Kumar, peter.maydell, linux-arm-kernel, kvmarm,
	kvm
  Cc: Prasun.Kapoor, drjones, pbonzini, dgilbert, quintela

On 27/03/17 10:31, Eric Auger wrote:
> The flush path copies the collection entries into guest RAM
> at the GPA specified in the BASER register. This obviously
> requires the BASER to be set. The last written element
> is a dummy collection table entry.
> 
> We do not index by collection ID as the collection entry
> can fit into 8 bytes while containing the collection ID.
> 
> On restore path we re-allocate the collection objects.
> 
> Signed-off-by: Eric Auger <eric.auger@redhat.com>
> 
> ---
> 
> v3 -> v4:
> - replaced u64 *ptr by gpa_t gpa
> - check the collection does not exist before allocating it
> 
> v1 -> v2:
> - reword commit message and directly use 8 as entry size
> - no kvm parameter anymore
> - add helper for flush/restore cte
> - table size computed here
> - add le64/cpu conversions
> ---
>  virt/kvm/arm/vgic/vgic-its.c | 99 +++++++++++++++++++++++++++++++++++++++++++-
>  1 file changed, 97 insertions(+), 2 deletions(-)
> 
> diff --git a/virt/kvm/arm/vgic/vgic-its.c b/virt/kvm/arm/vgic/vgic-its.c
> index 8eaeba4..df984b6 100644
> --- a/virt/kvm/arm/vgic/vgic-its.c
> +++ b/virt/kvm/arm/vgic/vgic-its.c
> @@ -1828,13 +1828,89 @@ static int vgic_its_restore_device_tables(struct vgic_its *its)
>  	return -ENXIO;
>  }
>  
> +static int vgic_its_flush_cte(struct vgic_its *its,
> +			      struct its_collection *collection, gpa_t gpa)

Given that the pendent of this function is name ..._restore_..., should
this be called ..._save_... ?

> +{
> +	u64 val;
> +	int ret;
> +
> +	val = ((u64)1 << 63 | ((u64)collection->target_addr << 16) |
> +	       collection->collection_id);

Please provide some #defines that describe the encoding. This will be
specially useful if we need to export this to userspace (KVM/TCG
interoperability?).

> +	val = cpu_to_le64(val);
> +	ret = kvm_write_guest(its->dev->kvm, gpa, &val, 8);
> +	return ret;
> +}
> +
> +static int vgic_its_restore_cte(struct vgic_its *its, gpa_t gpa, bool *valid)
> +{
> +	struct its_collection *collection;
> +	u32 target_addr;
> +	u32 coll_id;
> +	u64 val;
> +	int ret;
> +
> +	*valid = false;
> +
> +	ret = kvm_read_guest(its->dev->kvm, gpa, &val, 8);
> +	if (ret)
> +		return ret;
> +	val = le64_to_cpu(val);
> +	*valid = val & BIT_ULL(63);
> +
> +	if (!*valid)
> +		return 0;
> +
> +	target_addr = (u32)(val >> 16);

u32?

> +	coll_id = val & 0xFFFF;

Same comment about the various shifts/masks.

> +
> +	collection = find_collection(its, coll_id);
> +	if (collection)
> +		return -EEXIST;
> +	ret = vgic_its_alloc_collection(its, &collection, coll_id);
> +	if (ret)
> +		return ret;
> +	collection->target_addr = target_addr;
> +	return 0;
> +}
> +
>  /**
>   * vgic_its_flush_collection_table - flush the collection table into
>   * guest RAM
>   */
>  static int vgic_its_flush_collection_table(struct vgic_its *its)
>  {
> -	return -ENXIO;
> +	struct its_collection *collection;
> +	u64 val;
> +	gpa_t gpa;
> +	size_t max_size, filled = 0;
> +	int ret;
> +
> +	gpa = BASER_ADDRESS(its->baser_coll_table);
> +	if (!gpa)
> +		return 0;
> +
> +	max_size = GITS_BASER_NR_PAGES(its->baser_coll_table) * SZ_64K;
> +
> +	list_for_each_entry(collection, &its->collection_list, coll_list) {
> +		if (filled == max_size)
> +			return -ENOSPC;
> +		ret = vgic_its_flush_cte(its, collection, gpa);
> +		if (ret)
> +			return ret;
> +		gpa += 8;
> +		filled += 8;

This "8" should be extracted from the BASER register itself (Entry_Size).

> +	}
> +
> +	if (filled == max_size)
> +		return 0;
> +
> +	/*
> +	 * table is not fully filled, add a last dummy element
> +	 * with valid bit unset
> +	 */
> +	val = 0;
> +	ret = kvm_write_guest(its->dev->kvm, gpa, &val, 8);
> +	return ret;
>  }
>  
>  /**
> @@ -1844,7 +1920,26 @@ static int vgic_its_flush_collection_table(struct vgic_its *its)
>   */
>  static int vgic_its_restore_collection_table(struct vgic_its *its)
>  {
> -	return -ENXIO;
> +	size_t max_size, read = 0;
> +	gpa_t gpa;
> +	int ret;
> +
> +	gpa = BASER_ADDRESS(its->baser_coll_table);
> +	if (!gpa)
> +		return 0;
> +
> +	max_size = GITS_BASER_NR_PAGES(its->baser_coll_table) * SZ_64K;
> +
> +	while (read < max_size) {
> +		bool valid;
> +
> +		ret = vgic_its_restore_cte(its, gpa, &valid);
> +		if (!valid || ret)
> +			break;
> +		gpa += 8;
> +		read += 8;
> +	}
> +	return ret;
>  }
>  
>  /**
> 

Thanks,

	M.
-- 
Jazz is not dead. It just smells funny...

^ permalink raw reply	[flat|nested] 144+ messages in thread

* [PATCH v4 18/22] KVM: arm64: ITS: Collection table save/restore
@ 2017-04-10  9:55     ` Marc Zyngier
  0 siblings, 0 replies; 144+ messages in thread
From: Marc Zyngier @ 2017-04-10  9:55 UTC (permalink / raw)
  To: linux-arm-kernel

On 27/03/17 10:31, Eric Auger wrote:
> The flush path copies the collection entries into guest RAM
> at the GPA specified in the BASER register. This obviously
> requires the BASER to be set. The last written element
> is a dummy collection table entry.
> 
> We do not index by collection ID as the collection entry
> can fit into 8 bytes while containing the collection ID.
> 
> On restore path we re-allocate the collection objects.
> 
> Signed-off-by: Eric Auger <eric.auger@redhat.com>
> 
> ---
> 
> v3 -> v4:
> - replaced u64 *ptr by gpa_t gpa
> - check the collection does not exist before allocating it
> 
> v1 -> v2:
> - reword commit message and directly use 8 as entry size
> - no kvm parameter anymore
> - add helper for flush/restore cte
> - table size computed here
> - add le64/cpu conversions
> ---
>  virt/kvm/arm/vgic/vgic-its.c | 99 +++++++++++++++++++++++++++++++++++++++++++-
>  1 file changed, 97 insertions(+), 2 deletions(-)
> 
> diff --git a/virt/kvm/arm/vgic/vgic-its.c b/virt/kvm/arm/vgic/vgic-its.c
> index 8eaeba4..df984b6 100644
> --- a/virt/kvm/arm/vgic/vgic-its.c
> +++ b/virt/kvm/arm/vgic/vgic-its.c
> @@ -1828,13 +1828,89 @@ static int vgic_its_restore_device_tables(struct vgic_its *its)
>  	return -ENXIO;
>  }
>  
> +static int vgic_its_flush_cte(struct vgic_its *its,
> +			      struct its_collection *collection, gpa_t gpa)

Given that the pendent of this function is name ..._restore_..., should
this be called ..._save_... ?

> +{
> +	u64 val;
> +	int ret;
> +
> +	val = ((u64)1 << 63 | ((u64)collection->target_addr << 16) |
> +	       collection->collection_id);

Please provide some #defines that describe the encoding. This will be
specially useful if we need to export this to userspace (KVM/TCG
interoperability?).

> +	val = cpu_to_le64(val);
> +	ret = kvm_write_guest(its->dev->kvm, gpa, &val, 8);
> +	return ret;
> +}
> +
> +static int vgic_its_restore_cte(struct vgic_its *its, gpa_t gpa, bool *valid)
> +{
> +	struct its_collection *collection;
> +	u32 target_addr;
> +	u32 coll_id;
> +	u64 val;
> +	int ret;
> +
> +	*valid = false;
> +
> +	ret = kvm_read_guest(its->dev->kvm, gpa, &val, 8);
> +	if (ret)
> +		return ret;
> +	val = le64_to_cpu(val);
> +	*valid = val & BIT_ULL(63);
> +
> +	if (!*valid)
> +		return 0;
> +
> +	target_addr = (u32)(val >> 16);

u32?

> +	coll_id = val & 0xFFFF;

Same comment about the various shifts/masks.

> +
> +	collection = find_collection(its, coll_id);
> +	if (collection)
> +		return -EEXIST;
> +	ret = vgic_its_alloc_collection(its, &collection, coll_id);
> +	if (ret)
> +		return ret;
> +	collection->target_addr = target_addr;
> +	return 0;
> +}
> +
>  /**
>   * vgic_its_flush_collection_table - flush the collection table into
>   * guest RAM
>   */
>  static int vgic_its_flush_collection_table(struct vgic_its *its)
>  {
> -	return -ENXIO;
> +	struct its_collection *collection;
> +	u64 val;
> +	gpa_t gpa;
> +	size_t max_size, filled = 0;
> +	int ret;
> +
> +	gpa = BASER_ADDRESS(its->baser_coll_table);
> +	if (!gpa)
> +		return 0;
> +
> +	max_size = GITS_BASER_NR_PAGES(its->baser_coll_table) * SZ_64K;
> +
> +	list_for_each_entry(collection, &its->collection_list, coll_list) {
> +		if (filled == max_size)
> +			return -ENOSPC;
> +		ret = vgic_its_flush_cte(its, collection, gpa);
> +		if (ret)
> +			return ret;
> +		gpa += 8;
> +		filled += 8;

This "8" should be extracted from the BASER register itself (Entry_Size).

> +	}
> +
> +	if (filled == max_size)
> +		return 0;
> +
> +	/*
> +	 * table is not fully filled, add a last dummy element
> +	 * with valid bit unset
> +	 */
> +	val = 0;
> +	ret = kvm_write_guest(its->dev->kvm, gpa, &val, 8);
> +	return ret;
>  }
>  
>  /**
> @@ -1844,7 +1920,26 @@ static int vgic_its_flush_collection_table(struct vgic_its *its)
>   */
>  static int vgic_its_restore_collection_table(struct vgic_its *its)
>  {
> -	return -ENXIO;
> +	size_t max_size, read = 0;
> +	gpa_t gpa;
> +	int ret;
> +
> +	gpa = BASER_ADDRESS(its->baser_coll_table);
> +	if (!gpa)
> +		return 0;
> +
> +	max_size = GITS_BASER_NR_PAGES(its->baser_coll_table) * SZ_64K;
> +
> +	while (read < max_size) {
> +		bool valid;
> +
> +		ret = vgic_its_restore_cte(its, gpa, &valid);
> +		if (!valid || ret)
> +			break;
> +		gpa += 8;
> +		read += 8;
> +	}
> +	return ret;
>  }
>  
>  /**
> 

Thanks,

	M.
-- 
Jazz is not dead. It just smells funny...

^ permalink raw reply	[flat|nested] 144+ messages in thread

* Re: [PATCH v4 01/22] KVM: arm/arm64: Add vITS save/restore API documentation
  2017-04-08 17:31         ` Marc Zyngier
@ 2017-04-10 10:18           ` Auger Eric
  -1 siblings, 0 replies; 144+ messages in thread
From: Auger Eric @ 2017-04-10 10:18 UTC (permalink / raw)
  To: Marc Zyngier, Christoffer Dall
  Cc: eric.auger.pro, andre.przywara, vijayak, Vijaya.Kumar,
	peter.maydell, linux-arm-kernel, kvmarm, kvm, Prasun.Kapoor,
	drjones, pbonzini, dgilbert, quintela

Hi Marc, Christoffer,

On 08/04/2017 19:31, Marc Zyngier wrote:
> On Sat, Apr 08 2017 at 02:15:52 PM, Christoffer Dall <christoffer.dall@linaro.org> wrote:
>> On Sat, Apr 08, 2017 at 11:03:51AM +0100, Marc Zyngier wrote:
>>> On Mon, Mar 27 2017 at 10:30:51 AM, Eric Auger <eric.auger@redhat.com> wrote:
>>>> Add description for how to access vITS registers and how to flush/restore
>>>> vITS tables into/from memory
>>>>
>>>> Signed-off-by: Eric Auger <eric.auger@redhat.com>
>>>>
>>>> ---
>>>> v3 -> v4:
>>>> - take into account Peter's comments:
>>>>   - typos
>>>>   - KVM_DEV_ARM_VGIC_GRP_ITS_TABLES kvm_device_attr = 0
>>>>   - add a validity bit in DTE
>>>>   - document all fields in CTE and ITE
>>>>   - document ABI revision
>>>> - take into account Andre's comments:
>>>>   - document restrictions about GITS_CREADR writing and GITS_IIDR
>>>>   - document -EBUSY error if one or more VCPUS are runnning
>>>>   - document 64b registers only can be accessed with 64b access
>>>> - itt_addr field matches bits [51:8] of the itt_addr
>>>>
>>>> v1 -> v2:
>>>> - DTE and ITE now are 8 bytes
>>>> - DTE and ITE now indexed by deviceid/eventid
>>>> - use ITE name instead of ITTE
>>>> - mentions ITT_addr matches bits [51:8] of the actual address
>>>> - mentions LE layout
>>>> ---
>>>>  Documentation/virtual/kvm/devices/arm-vgic-its.txt | 118 +++++++++++++++++++++
>>>>  1 file changed, 118 insertions(+)
>>>>
>>>> diff --git a/Documentation/virtual/kvm/devices/arm-vgic-its.txt b/Documentation/virtual/kvm/devices/arm-vgic-its.txt
>>>> index 6081a5b..0902d20 100644
>>>> --- a/Documentation/virtual/kvm/devices/arm-vgic-its.txt
>>>> +++ b/Documentation/virtual/kvm/devices/arm-vgic-its.txt
>>>> @@ -36,3 +36,121 @@ Groups:
>>>>      -ENXIO:  ITS not properly configured as required prior to setting
>>>>               this attribute
>>>>      -ENOMEM: Memory shortage when allocating ITS internal data
>>>> +
>>>> +  KVM_DEV_ARM_VGIC_GRP_ITS_REGS
>>>> +  Attributes:
>>>> +      The attr field of kvm_device_attr encodes the offset of the
>>>> +      ITS register, relative to the ITS control frame base address
>>>> +      (ITS_base).
>>>> +
>>>> +      kvm_device_attr.addr points to a __u64 value whatever the width
>>>> +      of the addressed register (32/64 bits). 64 bit registers can only
>>>> +      be accessed with full length.
>>>> +
>>>> +      Writes to read-only registers are ignored by the kernel except for:
>>>> +      - GITS_READR. It needs to be restored otherwise commands in the queue
>>>> +        will be re-executed after CWRITER setting. Writing this register is
>>>> +        allowed if the ITS is not enabled (GITS_CTLR.enable = 0). Also it
>>>> +        needs to be restored after GITS_CBASER since a write to GITS_CBASER
>>>> +        resets GITS_CREADR.
>>>> +      - GITS_IIDR. Its Revision field encodes the table layout ABI revision.
>>>> +
>>>> +      For other registers, getting or setting a register has the same
>>>> +      effect as reading/writing the register on real hardware.
>>>> +  Errors:
>>>> +    -ENXIO: Offset does not correspond to any supported register
>>>> +    -EFAULT: Invalid user pointer for attr->addr
>>>> +    -EINVAL: Offset is not 64-bit aligned
>>>> +    -EBUSY: one or more VCPUS are running
>>>> +
>>>> +  KVM_DEV_ARM_VGIC_GRP_ITS_TABLES
>>>> +  Attributes
>>>> +       The attr field of kvm_device_attr must be zero.
>>>> +
>>>> +       request the flush-save/restore of the ITS tables, namely
>>>> +       the device table, the collection table, all the ITT tables,
>>>> +       the LPI pending tables. On save, the tables are flushed
>>>> +       into guest memory at the location provisioned by the guest
>>>> +       in GITS_BASER (device and collection tables), in the MAPD
>>>> +       command (ITT_addr), GICR_PENDBASERs (pending tables).
>>>
>>> May I echo Andre's concern here? Seeing the GICR_PENDBASER registers
>>> here feels wrong. The pending table is a redistributor concept, and is
>>> local to it. Even more, it is perfectly possible to use the
>>> redistributors (and its pending tables) without an ITS by using the
>>> GICR_SETLPIR registers.
>>>
>>> Granted, we do not support this (and I'm *not* looking forward to
>>> supporting it), but I would rather implement a redistributor flush than
>>> using the ITS to indirectly force it. That's not how the HW works, and I
>>> don't think we should deviate from it.
>>>
>>> I appreciate this brings additional complexity to userspace (having to
>>> iterate over the vcpus or the redistributors is likely more costly than
>>> hitting the ITS which is likely to be unique), but sticking to the
>>> letter of the architecture is probably our best bet. Each time we tried
>>> to deviate from it, we've had to backtrack.
>>
>> I agree.  I think the possibility of using LPIs without an ITS is the
>> winning argument.
>>
>> However, I could see it being reasonable to have a single call that
>> userspace can make on the vgic device to ask it to flush all the
>> redistributors at the same time.  We defined the cpu sysreg interface
>> via the vgic device as well, so I don't think we're breaking anything,
>> and in fact, it may be good to have a single sync-point where the kernel
>> can atomically say "all redistributors are flushed correctly" or
>> "something bad happened".  Do we have any arguments for wanting to be
>> able flush redistributors independently?
> 
> Not as such. The redistributors may support implementation-specific ways
> of ensuring synchronization with the PT (for power management purposes,
> for example), but there is no architected way of ensuring it.
> 
> So I agree that having a single synchronization hook for all
> redistributors in the system is probably the right thing to do. This is
> simple enough for userspace, and we already have the required code in
> this series -- we just need to tie it to an additional property on the
> GICv3 group.
> 
> Eric: can you explore this and let us know if there is any issue we
> haven't foreseen yet?
Yes I am going to investigate this. The extra complexity I foresee is
that I need to implement coarse mapping in the first kB of the pending
table to guess what LPI is pending and thus become independent on the
restoration of the ITS - which is the goal -.

Thanks

Eric
> 
> Thanks,
> 
> 	M.
> 

^ permalink raw reply	[flat|nested] 144+ messages in thread

* [PATCH v4 01/22] KVM: arm/arm64: Add vITS save/restore API documentation
@ 2017-04-10 10:18           ` Auger Eric
  0 siblings, 0 replies; 144+ messages in thread
From: Auger Eric @ 2017-04-10 10:18 UTC (permalink / raw)
  To: linux-arm-kernel

Hi Marc, Christoffer,

On 08/04/2017 19:31, Marc Zyngier wrote:
> On Sat, Apr 08 2017 at 02:15:52 PM, Christoffer Dall <christoffer.dall@linaro.org> wrote:
>> On Sat, Apr 08, 2017 at 11:03:51AM +0100, Marc Zyngier wrote:
>>> On Mon, Mar 27 2017 at 10:30:51 AM, Eric Auger <eric.auger@redhat.com> wrote:
>>>> Add description for how to access vITS registers and how to flush/restore
>>>> vITS tables into/from memory
>>>>
>>>> Signed-off-by: Eric Auger <eric.auger@redhat.com>
>>>>
>>>> ---
>>>> v3 -> v4:
>>>> - take into account Peter's comments:
>>>>   - typos
>>>>   - KVM_DEV_ARM_VGIC_GRP_ITS_TABLES kvm_device_attr = 0
>>>>   - add a validity bit in DTE
>>>>   - document all fields in CTE and ITE
>>>>   - document ABI revision
>>>> - take into account Andre's comments:
>>>>   - document restrictions about GITS_CREADR writing and GITS_IIDR
>>>>   - document -EBUSY error if one or more VCPUS are runnning
>>>>   - document 64b registers only can be accessed with 64b access
>>>> - itt_addr field matches bits [51:8] of the itt_addr
>>>>
>>>> v1 -> v2:
>>>> - DTE and ITE now are 8 bytes
>>>> - DTE and ITE now indexed by deviceid/eventid
>>>> - use ITE name instead of ITTE
>>>> - mentions ITT_addr matches bits [51:8] of the actual address
>>>> - mentions LE layout
>>>> ---
>>>>  Documentation/virtual/kvm/devices/arm-vgic-its.txt | 118 +++++++++++++++++++++
>>>>  1 file changed, 118 insertions(+)
>>>>
>>>> diff --git a/Documentation/virtual/kvm/devices/arm-vgic-its.txt b/Documentation/virtual/kvm/devices/arm-vgic-its.txt
>>>> index 6081a5b..0902d20 100644
>>>> --- a/Documentation/virtual/kvm/devices/arm-vgic-its.txt
>>>> +++ b/Documentation/virtual/kvm/devices/arm-vgic-its.txt
>>>> @@ -36,3 +36,121 @@ Groups:
>>>>      -ENXIO:  ITS not properly configured as required prior to setting
>>>>               this attribute
>>>>      -ENOMEM: Memory shortage when allocating ITS internal data
>>>> +
>>>> +  KVM_DEV_ARM_VGIC_GRP_ITS_REGS
>>>> +  Attributes:
>>>> +      The attr field of kvm_device_attr encodes the offset of the
>>>> +      ITS register, relative to the ITS control frame base address
>>>> +      (ITS_base).
>>>> +
>>>> +      kvm_device_attr.addr points to a __u64 value whatever the width
>>>> +      of the addressed register (32/64 bits). 64 bit registers can only
>>>> +      be accessed with full length.
>>>> +
>>>> +      Writes to read-only registers are ignored by the kernel except for:
>>>> +      - GITS_READR. It needs to be restored otherwise commands in the queue
>>>> +        will be re-executed after CWRITER setting. Writing this register is
>>>> +        allowed if the ITS is not enabled (GITS_CTLR.enable = 0). Also it
>>>> +        needs to be restored after GITS_CBASER since a write to GITS_CBASER
>>>> +        resets GITS_CREADR.
>>>> +      - GITS_IIDR. Its Revision field encodes the table layout ABI revision.
>>>> +
>>>> +      For other registers, getting or setting a register has the same
>>>> +      effect as reading/writing the register on real hardware.
>>>> +  Errors:
>>>> +    -ENXIO: Offset does not correspond to any supported register
>>>> +    -EFAULT: Invalid user pointer for attr->addr
>>>> +    -EINVAL: Offset is not 64-bit aligned
>>>> +    -EBUSY: one or more VCPUS are running
>>>> +
>>>> +  KVM_DEV_ARM_VGIC_GRP_ITS_TABLES
>>>> +  Attributes
>>>> +       The attr field of kvm_device_attr must be zero.
>>>> +
>>>> +       request the flush-save/restore of the ITS tables, namely
>>>> +       the device table, the collection table, all the ITT tables,
>>>> +       the LPI pending tables. On save, the tables are flushed
>>>> +       into guest memory at the location provisioned by the guest
>>>> +       in GITS_BASER (device and collection tables), in the MAPD
>>>> +       command (ITT_addr), GICR_PENDBASERs (pending tables).
>>>
>>> May I echo Andre's concern here? Seeing the GICR_PENDBASER registers
>>> here feels wrong. The pending table is a redistributor concept, and is
>>> local to it. Even more, it is perfectly possible to use the
>>> redistributors (and its pending tables) without an ITS by using the
>>> GICR_SETLPIR registers.
>>>
>>> Granted, we do not support this (and I'm *not* looking forward to
>>> supporting it), but I would rather implement a redistributor flush than
>>> using the ITS to indirectly force it. That's not how the HW works, and I
>>> don't think we should deviate from it.
>>>
>>> I appreciate this brings additional complexity to userspace (having to
>>> iterate over the vcpus or the redistributors is likely more costly than
>>> hitting the ITS which is likely to be unique), but sticking to the
>>> letter of the architecture is probably our best bet. Each time we tried
>>> to deviate from it, we've had to backtrack.
>>
>> I agree.  I think the possibility of using LPIs without an ITS is the
>> winning argument.
>>
>> However, I could see it being reasonable to have a single call that
>> userspace can make on the vgic device to ask it to flush all the
>> redistributors at the same time.  We defined the cpu sysreg interface
>> via the vgic device as well, so I don't think we're breaking anything,
>> and in fact, it may be good to have a single sync-point where the kernel
>> can atomically say "all redistributors are flushed correctly" or
>> "something bad happened".  Do we have any arguments for wanting to be
>> able flush redistributors independently?
> 
> Not as such. The redistributors may support implementation-specific ways
> of ensuring synchronization with the PT (for power management purposes,
> for example), but there is no architected way of ensuring it.
> 
> So I agree that having a single synchronization hook for all
> redistributors in the system is probably the right thing to do. This is
> simple enough for userspace, and we already have the required code in
> this series -- we just need to tie it to an additional property on the
> GICv3 group.
> 
> Eric: can you explore this and let us know if there is any issue we
> haven't foreseen yet?
Yes I am going to investigate this. The extra complexity I foresee is
that I need to implement coarse mapping in the first kB of the pending
table to guess what LPI is pending and thus become independent on the
restoration of the ITS - which is the goal -.

Thanks

Eric
> 
> Thanks,
> 
> 	M.
> 

^ permalink raw reply	[flat|nested] 144+ messages in thread

* Re: [PATCH v4 01/22] KVM: arm/arm64: Add vITS save/restore API documentation
  2017-04-10 10:18           ` Auger Eric
@ 2017-04-10 10:42             ` Marc Zyngier
  -1 siblings, 0 replies; 144+ messages in thread
From: Marc Zyngier @ 2017-04-10 10:42 UTC (permalink / raw)
  To: Auger Eric, Christoffer Dall
  Cc: eric.auger.pro, andre.przywara, vijayak, Vijaya.Kumar,
	peter.maydell, linux-arm-kernel, kvmarm, kvm, Prasun.Kapoor,
	drjones, pbonzini, dgilbert, quintela

On 10/04/17 11:18, Auger Eric wrote:
> Hi Marc, Christoffer,
> 
> On 08/04/2017 19:31, Marc Zyngier wrote:
>> On Sat, Apr 08 2017 at 02:15:52 PM, Christoffer Dall <christoffer.dall@linaro.org> wrote:
>>> On Sat, Apr 08, 2017 at 11:03:51AM +0100, Marc Zyngier wrote:
>>>> On Mon, Mar 27 2017 at 10:30:51 AM, Eric Auger <eric.auger@redhat.com> wrote:
>>>>> Add description for how to access vITS registers and how to flush/restore
>>>>> vITS tables into/from memory
>>>>>
>>>>> Signed-off-by: Eric Auger <eric.auger@redhat.com>
>>>>>
>>>>> ---
>>>>> v3 -> v4:
>>>>> - take into account Peter's comments:
>>>>>   - typos
>>>>>   - KVM_DEV_ARM_VGIC_GRP_ITS_TABLES kvm_device_attr = 0
>>>>>   - add a validity bit in DTE
>>>>>   - document all fields in CTE and ITE
>>>>>   - document ABI revision
>>>>> - take into account Andre's comments:
>>>>>   - document restrictions about GITS_CREADR writing and GITS_IIDR
>>>>>   - document -EBUSY error if one or more VCPUS are runnning
>>>>>   - document 64b registers only can be accessed with 64b access
>>>>> - itt_addr field matches bits [51:8] of the itt_addr
>>>>>
>>>>> v1 -> v2:
>>>>> - DTE and ITE now are 8 bytes
>>>>> - DTE and ITE now indexed by deviceid/eventid
>>>>> - use ITE name instead of ITTE
>>>>> - mentions ITT_addr matches bits [51:8] of the actual address
>>>>> - mentions LE layout
>>>>> ---
>>>>>  Documentation/virtual/kvm/devices/arm-vgic-its.txt | 118 +++++++++++++++++++++
>>>>>  1 file changed, 118 insertions(+)
>>>>>
>>>>> diff --git a/Documentation/virtual/kvm/devices/arm-vgic-its.txt b/Documentation/virtual/kvm/devices/arm-vgic-its.txt
>>>>> index 6081a5b..0902d20 100644
>>>>> --- a/Documentation/virtual/kvm/devices/arm-vgic-its.txt
>>>>> +++ b/Documentation/virtual/kvm/devices/arm-vgic-its.txt
>>>>> @@ -36,3 +36,121 @@ Groups:
>>>>>      -ENXIO:  ITS not properly configured as required prior to setting
>>>>>               this attribute
>>>>>      -ENOMEM: Memory shortage when allocating ITS internal data
>>>>> +
>>>>> +  KVM_DEV_ARM_VGIC_GRP_ITS_REGS
>>>>> +  Attributes:
>>>>> +      The attr field of kvm_device_attr encodes the offset of the
>>>>> +      ITS register, relative to the ITS control frame base address
>>>>> +      (ITS_base).
>>>>> +
>>>>> +      kvm_device_attr.addr points to a __u64 value whatever the width
>>>>> +      of the addressed register (32/64 bits). 64 bit registers can only
>>>>> +      be accessed with full length.
>>>>> +
>>>>> +      Writes to read-only registers are ignored by the kernel except for:
>>>>> +      - GITS_READR. It needs to be restored otherwise commands in the queue
>>>>> +        will be re-executed after CWRITER setting. Writing this register is
>>>>> +        allowed if the ITS is not enabled (GITS_CTLR.enable = 0). Also it
>>>>> +        needs to be restored after GITS_CBASER since a write to GITS_CBASER
>>>>> +        resets GITS_CREADR.
>>>>> +      - GITS_IIDR. Its Revision field encodes the table layout ABI revision.
>>>>> +
>>>>> +      For other registers, getting or setting a register has the same
>>>>> +      effect as reading/writing the register on real hardware.
>>>>> +  Errors:
>>>>> +    -ENXIO: Offset does not correspond to any supported register
>>>>> +    -EFAULT: Invalid user pointer for attr->addr
>>>>> +    -EINVAL: Offset is not 64-bit aligned
>>>>> +    -EBUSY: one or more VCPUS are running
>>>>> +
>>>>> +  KVM_DEV_ARM_VGIC_GRP_ITS_TABLES
>>>>> +  Attributes
>>>>> +       The attr field of kvm_device_attr must be zero.
>>>>> +
>>>>> +       request the flush-save/restore of the ITS tables, namely
>>>>> +       the device table, the collection table, all the ITT tables,
>>>>> +       the LPI pending tables. On save, the tables are flushed
>>>>> +       into guest memory at the location provisioned by the guest
>>>>> +       in GITS_BASER (device and collection tables), in the MAPD
>>>>> +       command (ITT_addr), GICR_PENDBASERs (pending tables).
>>>>
>>>> May I echo Andre's concern here? Seeing the GICR_PENDBASER registers
>>>> here feels wrong. The pending table is a redistributor concept, and is
>>>> local to it. Even more, it is perfectly possible to use the
>>>> redistributors (and its pending tables) without an ITS by using the
>>>> GICR_SETLPIR registers.
>>>>
>>>> Granted, we do not support this (and I'm *not* looking forward to
>>>> supporting it), but I would rather implement a redistributor flush than
>>>> using the ITS to indirectly force it. That's not how the HW works, and I
>>>> don't think we should deviate from it.
>>>>
>>>> I appreciate this brings additional complexity to userspace (having to
>>>> iterate over the vcpus or the redistributors is likely more costly than
>>>> hitting the ITS which is likely to be unique), but sticking to the
>>>> letter of the architecture is probably our best bet. Each time we tried
>>>> to deviate from it, we've had to backtrack.
>>>
>>> I agree.  I think the possibility of using LPIs without an ITS is the
>>> winning argument.
>>>
>>> However, I could see it being reasonable to have a single call that
>>> userspace can make on the vgic device to ask it to flush all the
>>> redistributors at the same time.  We defined the cpu sysreg interface
>>> via the vgic device as well, so I don't think we're breaking anything,
>>> and in fact, it may be good to have a single sync-point where the kernel
>>> can atomically say "all redistributors are flushed correctly" or
>>> "something bad happened".  Do we have any arguments for wanting to be
>>> able flush redistributors independently?
>>
>> Not as such. The redistributors may support implementation-specific ways
>> of ensuring synchronization with the PT (for power management purposes,
>> for example), but there is no architected way of ensuring it.
>>
>> So I agree that having a single synchronization hook for all
>> redistributors in the system is probably the right thing to do. This is
>> simple enough for userspace, and we already have the required code in
>> this series -- we just need to tie it to an additional property on the
>> GICv3 group.
>>
>> Eric: can you explore this and let us know if there is any issue we
>> haven't foreseen yet?
> Yes I am going to investigate this. The extra complexity I foresee is
> that I need to implement coarse mapping in the first kB of the pending
> table to guess what LPI is pending and thus become independent on the
> restoration of the ITS - which is the goal -.

I don't think you necessarily need a coarse map. When restoring the ITS
tables, you can always read the pending bit when creating the LPI
structure (it has been written to RAM at save time). Note that we
already do something like this in vgic_enable_lpis().

If that proves to be too slow (because you have so many mapped
interrupts that doing bit access is a huge waste of time), then you can
implement a coarse map and reload the pending state independently of the
LPI mapping creation.

In short, don't optimize prematurely! ;-)

Thanks,

	M.
-- 
Jazz is not dead. It just smells funny...

^ permalink raw reply	[flat|nested] 144+ messages in thread

* [PATCH v4 01/22] KVM: arm/arm64: Add vITS save/restore API documentation
@ 2017-04-10 10:42             ` Marc Zyngier
  0 siblings, 0 replies; 144+ messages in thread
From: Marc Zyngier @ 2017-04-10 10:42 UTC (permalink / raw)
  To: linux-arm-kernel

On 10/04/17 11:18, Auger Eric wrote:
> Hi Marc, Christoffer,
> 
> On 08/04/2017 19:31, Marc Zyngier wrote:
>> On Sat, Apr 08 2017 at 02:15:52 PM, Christoffer Dall <christoffer.dall@linaro.org> wrote:
>>> On Sat, Apr 08, 2017 at 11:03:51AM +0100, Marc Zyngier wrote:
>>>> On Mon, Mar 27 2017 at 10:30:51 AM, Eric Auger <eric.auger@redhat.com> wrote:
>>>>> Add description for how to access vITS registers and how to flush/restore
>>>>> vITS tables into/from memory
>>>>>
>>>>> Signed-off-by: Eric Auger <eric.auger@redhat.com>
>>>>>
>>>>> ---
>>>>> v3 -> v4:
>>>>> - take into account Peter's comments:
>>>>>   - typos
>>>>>   - KVM_DEV_ARM_VGIC_GRP_ITS_TABLES kvm_device_attr = 0
>>>>>   - add a validity bit in DTE
>>>>>   - document all fields in CTE and ITE
>>>>>   - document ABI revision
>>>>> - take into account Andre's comments:
>>>>>   - document restrictions about GITS_CREADR writing and GITS_IIDR
>>>>>   - document -EBUSY error if one or more VCPUS are runnning
>>>>>   - document 64b registers only can be accessed with 64b access
>>>>> - itt_addr field matches bits [51:8] of the itt_addr
>>>>>
>>>>> v1 -> v2:
>>>>> - DTE and ITE now are 8 bytes
>>>>> - DTE and ITE now indexed by deviceid/eventid
>>>>> - use ITE name instead of ITTE
>>>>> - mentions ITT_addr matches bits [51:8] of the actual address
>>>>> - mentions LE layout
>>>>> ---
>>>>>  Documentation/virtual/kvm/devices/arm-vgic-its.txt | 118 +++++++++++++++++++++
>>>>>  1 file changed, 118 insertions(+)
>>>>>
>>>>> diff --git a/Documentation/virtual/kvm/devices/arm-vgic-its.txt b/Documentation/virtual/kvm/devices/arm-vgic-its.txt
>>>>> index 6081a5b..0902d20 100644
>>>>> --- a/Documentation/virtual/kvm/devices/arm-vgic-its.txt
>>>>> +++ b/Documentation/virtual/kvm/devices/arm-vgic-its.txt
>>>>> @@ -36,3 +36,121 @@ Groups:
>>>>>      -ENXIO:  ITS not properly configured as required prior to setting
>>>>>               this attribute
>>>>>      -ENOMEM: Memory shortage when allocating ITS internal data
>>>>> +
>>>>> +  KVM_DEV_ARM_VGIC_GRP_ITS_REGS
>>>>> +  Attributes:
>>>>> +      The attr field of kvm_device_attr encodes the offset of the
>>>>> +      ITS register, relative to the ITS control frame base address
>>>>> +      (ITS_base).
>>>>> +
>>>>> +      kvm_device_attr.addr points to a __u64 value whatever the width
>>>>> +      of the addressed register (32/64 bits). 64 bit registers can only
>>>>> +      be accessed with full length.
>>>>> +
>>>>> +      Writes to read-only registers are ignored by the kernel except for:
>>>>> +      - GITS_READR. It needs to be restored otherwise commands in the queue
>>>>> +        will be re-executed after CWRITER setting. Writing this register is
>>>>> +        allowed if the ITS is not enabled (GITS_CTLR.enable = 0). Also it
>>>>> +        needs to be restored after GITS_CBASER since a write to GITS_CBASER
>>>>> +        resets GITS_CREADR.
>>>>> +      - GITS_IIDR. Its Revision field encodes the table layout ABI revision.
>>>>> +
>>>>> +      For other registers, getting or setting a register has the same
>>>>> +      effect as reading/writing the register on real hardware.
>>>>> +  Errors:
>>>>> +    -ENXIO: Offset does not correspond to any supported register
>>>>> +    -EFAULT: Invalid user pointer for attr->addr
>>>>> +    -EINVAL: Offset is not 64-bit aligned
>>>>> +    -EBUSY: one or more VCPUS are running
>>>>> +
>>>>> +  KVM_DEV_ARM_VGIC_GRP_ITS_TABLES
>>>>> +  Attributes
>>>>> +       The attr field of kvm_device_attr must be zero.
>>>>> +
>>>>> +       request the flush-save/restore of the ITS tables, namely
>>>>> +       the device table, the collection table, all the ITT tables,
>>>>> +       the LPI pending tables. On save, the tables are flushed
>>>>> +       into guest memory at the location provisioned by the guest
>>>>> +       in GITS_BASER (device and collection tables), in the MAPD
>>>>> +       command (ITT_addr), GICR_PENDBASERs (pending tables).
>>>>
>>>> May I echo Andre's concern here? Seeing the GICR_PENDBASER registers
>>>> here feels wrong. The pending table is a redistributor concept, and is
>>>> local to it. Even more, it is perfectly possible to use the
>>>> redistributors (and its pending tables) without an ITS by using the
>>>> GICR_SETLPIR registers.
>>>>
>>>> Granted, we do not support this (and I'm *not* looking forward to
>>>> supporting it), but I would rather implement a redistributor flush than
>>>> using the ITS to indirectly force it. That's not how the HW works, and I
>>>> don't think we should deviate from it.
>>>>
>>>> I appreciate this brings additional complexity to userspace (having to
>>>> iterate over the vcpus or the redistributors is likely more costly than
>>>> hitting the ITS which is likely to be unique), but sticking to the
>>>> letter of the architecture is probably our best bet. Each time we tried
>>>> to deviate from it, we've had to backtrack.
>>>
>>> I agree.  I think the possibility of using LPIs without an ITS is the
>>> winning argument.
>>>
>>> However, I could see it being reasonable to have a single call that
>>> userspace can make on the vgic device to ask it to flush all the
>>> redistributors at the same time.  We defined the cpu sysreg interface
>>> via the vgic device as well, so I don't think we're breaking anything,
>>> and in fact, it may be good to have a single sync-point where the kernel
>>> can atomically say "all redistributors are flushed correctly" or
>>> "something bad happened".  Do we have any arguments for wanting to be
>>> able flush redistributors independently?
>>
>> Not as such. The redistributors may support implementation-specific ways
>> of ensuring synchronization with the PT (for power management purposes,
>> for example), but there is no architected way of ensuring it.
>>
>> So I agree that having a single synchronization hook for all
>> redistributors in the system is probably the right thing to do. This is
>> simple enough for userspace, and we already have the required code in
>> this series -- we just need to tie it to an additional property on the
>> GICv3 group.
>>
>> Eric: can you explore this and let us know if there is any issue we
>> haven't foreseen yet?
> Yes I am going to investigate this. The extra complexity I foresee is
> that I need to implement coarse mapping in the first kB of the pending
> table to guess what LPI is pending and thus become independent on the
> restoration of the ITS - which is the goal -.

I don't think you necessarily need a coarse map. When restoring the ITS
tables, you can always read the pending bit when creating the LPI
structure (it has been written to RAM at save time). Note that we
already do something like this in vgic_enable_lpis().

If that proves to be too slow (because you have so many mapped
interrupts that doing bit access is a huge waste of time), then you can
implement a coarse map and reload the pending state independently of the
LPI mapping creation.

In short, don't optimize prematurely! ;-)

Thanks,

	M.
-- 
Jazz is not dead. It just smells funny...

^ permalink raw reply	[flat|nested] 144+ messages in thread

* Re: [PATCH v4 20/22] KVM: arm64: ITS: ITT flush and restore
  2017-03-27  9:31   ` Eric Auger
@ 2017-04-10 12:39     ` Marc Zyngier
  -1 siblings, 0 replies; 144+ messages in thread
From: Marc Zyngier @ 2017-04-10 12:39 UTC (permalink / raw)
  To: Eric Auger, eric.auger.pro, christoffer.dall, andre.przywara,
	vijayak, Vijaya.Kumar, peter.maydell, linux-arm-kernel, kvmarm,
	kvm
  Cc: Prasun.Kapoor, drjones, pbonzini, dgilbert, quintela

On 27/03/17 10:31, Eric Auger wrote:
> Introduce routines to flush and restore device ITT and their
> interrupt table entries (ITE).
> 
> The routines will be called on device table flush and
> restore. They will become static in subsequent patches.
> 
> Signed-off-by: Eric Auger <eric.auger@redhat.com>
> 
> ---
> 
> v3 -> v4:
> - lookup_table and compute_next_eventid_offset become static in this
>   patch
> - remove static along with vgic_its_flush/restore_itt to avoid
>   compilation warnings
> - next field only computed with a shift (mask removed)
> - handle the case where the last element has not been found
> 
> v2 -> v3:
> - add return 0 in vgic_its_restore_ite (was in subsequent patch)
> 
> v2: creation
> ---
>  virt/kvm/arm/vgic/vgic-its.c | 107 +++++++++++++++++++++++++++++++++++++++++--
>  1 file changed, 104 insertions(+), 3 deletions(-)
> 
> diff --git a/virt/kvm/arm/vgic/vgic-its.c b/virt/kvm/arm/vgic/vgic-its.c
> index b907e3c..02c0694 100644
> --- a/virt/kvm/arm/vgic/vgic-its.c
> +++ b/virt/kvm/arm/vgic/vgic-its.c
> @@ -1707,7 +1707,7 @@ u32 compute_next_devid_offset(struct list_head *h, struct its_device *dev)
>  	return min_t(u32, next_offset, VITS_DTE_MAX_DEVID_OFFSET);
>  }
>  
> -u32 compute_next_eventid_offset(struct list_head *h, struct its_ite *ite)
> +static u32 compute_next_eventid_offset(struct list_head *h, struct its_ite *ite)
>  {
>  	struct list_head *e = &ite->ite_list;
>  	struct its_ite *next;
> @@ -1749,8 +1749,8 @@ typedef int (*entry_fn_t)(struct vgic_its *its, u32 id, void *addr,
>   *
>   * Return: < 0 on error, 1 if last element identified, 0 otherwise
>   */
> -int lookup_table(struct vgic_its *its, gpa_t base, int size, int esz,
> -		 int start_id, entry_fn_t fn, void *opaque)
> +static int lookup_table(struct vgic_its *its, gpa_t base, int size, int esz,
> +			int start_id, entry_fn_t fn, void *opaque)
>  {
>  	gpa_t gpa = base, top = base + size - 1;
>  	unsigned long len = size;
> @@ -1815,6 +1815,107 @@ static int vgic_its_restore_pending_tables(struct kvm *kvm)
>  	return -ENXIO;
>  }
>  
> +static int vgic_its_flush_ite(struct vgic_its *its, struct its_device *dev,
> +			      struct its_ite *ite, gpa_t gpa)
> +{
> +	struct kvm *kvm = its->dev->kvm;
> +	u32 next_offset;
> +	u64 val;
> +
> +	next_offset = compute_next_eventid_offset(&dev->itt_head, ite);
> +	val = ((u64)next_offset << 48) | ((u64)ite->lpi << 16) |
> +		ite->collection->collection_id;

Same remark as before concerning the #define-ing of the encoding and the
name of the function.

> +	val = cpu_to_le64(val);
> +	return kvm_write_guest(kvm, gpa, &val, VITS_ESZ);
> +}
> +
> +/**
> + * vgic_its_restore_ite - restore an interrupt translation entry
> + * @event_id: id used for indexing
> + * @ptr: kernel VA where the 8 byte ITE is located
> + * @opaque: pointer to the its_device
> + * @next: id offset to the next entry
> + */
> +static int vgic_its_restore_ite(struct vgic_its *its, u32 event_id,
> +				void *ptr, void *opaque, u32 *next)
> +{
> +	struct its_device *dev = (struct its_device *)opaque;
> +	struct its_collection *collection;
> +	struct kvm *kvm = its->dev->kvm;
> +	u64 val, *p = (u64 *)ptr;
> +	struct vgic_irq *irq;
> +	u32 coll_id, lpi_id;
> +	struct its_ite *ite;
> +	int ret;
> +
> +	val = *p;
> +	*next = 1;
> +
> +	val = le64_to_cpu(val);
> +
> +	coll_id = val & GENMASK_ULL(15, 0);
> +	lpi_id = (val & GENMASK_ULL(47, 16)) >> 16;
> +
> +	if (!lpi_id)
> +		return 0;
> +
> +	*next = val >> 48;
> +
> +	collection = find_collection(its, coll_id);
> +	if (!collection)
> +		return -EINVAL;
> +
> +	ret = vgic_its_alloc_ite(dev, &ite, collection,
> +				  lpi_id, event_id);
> +	if (ret)
> +		return ret;
> +
> +	irq = vgic_add_lpi(kvm, lpi_id);
> +	if (IS_ERR(irq))
> +		return PTR_ERR(irq);
> +	ite->irq = irq;
> +
> +	/* restore the configuration of the LPI */
> +	ret = update_lpi_config(kvm, irq, NULL);
> +	if (ret)
> +		return ret;
> +
> +	update_affinity_ite(kvm, ite);
> +	return 0;
> +}
> +
> +int vgic_its_flush_itt(struct vgic_its *its, struct its_device *device)
> +{
> +	gpa_t base = device->itt_addr;
> +	struct its_ite *ite;
> +	int ret;
> +
> +	list_for_each_entry(ite, &device->itt_head, ite_list) {
> +		gpa_t gpa = base + ite->event_id * VITS_ESZ;
> +
> +		ret = vgic_its_flush_ite(its, device, ite, gpa);
> +		if (ret)
> +			return ret;
> +	}
> +	return 0;
> +}
> +
> +int vgic_its_restore_itt(struct vgic_its *its, struct its_device *dev)
> +{
> +	size_t max_size = BIT_ULL(dev->nb_eventid_bits) * VITS_ESZ;
> +	gpa_t base = dev->itt_addr;
> +	int ret;
> +
> +	ret =  lookup_table(its, base, max_size, VITS_ESZ, 0,
> +			    vgic_its_restore_ite, dev);
> +
> +	if (ret < 0)
> +		return ret;
> +
> +	/* if the last element has not been found we are in trouble */
> +	return ret ? 0 : -EINVAL;

This makes me wonder. Can't lookup_table perform that check on its own
and always return an error when something went wrong?

> +}
> +
>  /**
>   * vgic_its_flush_device_tables - flush the device table and all ITT
>   * into guest RAM
> 

Thanks,

	M.
-- 
Jazz is not dead. It just smells funny...

^ permalink raw reply	[flat|nested] 144+ messages in thread

* [PATCH v4 20/22] KVM: arm64: ITS: ITT flush and restore
@ 2017-04-10 12:39     ` Marc Zyngier
  0 siblings, 0 replies; 144+ messages in thread
From: Marc Zyngier @ 2017-04-10 12:39 UTC (permalink / raw)
  To: linux-arm-kernel

On 27/03/17 10:31, Eric Auger wrote:
> Introduce routines to flush and restore device ITT and their
> interrupt table entries (ITE).
> 
> The routines will be called on device table flush and
> restore. They will become static in subsequent patches.
> 
> Signed-off-by: Eric Auger <eric.auger@redhat.com>
> 
> ---
> 
> v3 -> v4:
> - lookup_table and compute_next_eventid_offset become static in this
>   patch
> - remove static along with vgic_its_flush/restore_itt to avoid
>   compilation warnings
> - next field only computed with a shift (mask removed)
> - handle the case where the last element has not been found
> 
> v2 -> v3:
> - add return 0 in vgic_its_restore_ite (was in subsequent patch)
> 
> v2: creation
> ---
>  virt/kvm/arm/vgic/vgic-its.c | 107 +++++++++++++++++++++++++++++++++++++++++--
>  1 file changed, 104 insertions(+), 3 deletions(-)
> 
> diff --git a/virt/kvm/arm/vgic/vgic-its.c b/virt/kvm/arm/vgic/vgic-its.c
> index b907e3c..02c0694 100644
> --- a/virt/kvm/arm/vgic/vgic-its.c
> +++ b/virt/kvm/arm/vgic/vgic-its.c
> @@ -1707,7 +1707,7 @@ u32 compute_next_devid_offset(struct list_head *h, struct its_device *dev)
>  	return min_t(u32, next_offset, VITS_DTE_MAX_DEVID_OFFSET);
>  }
>  
> -u32 compute_next_eventid_offset(struct list_head *h, struct its_ite *ite)
> +static u32 compute_next_eventid_offset(struct list_head *h, struct its_ite *ite)
>  {
>  	struct list_head *e = &ite->ite_list;
>  	struct its_ite *next;
> @@ -1749,8 +1749,8 @@ typedef int (*entry_fn_t)(struct vgic_its *its, u32 id, void *addr,
>   *
>   * Return: < 0 on error, 1 if last element identified, 0 otherwise
>   */
> -int lookup_table(struct vgic_its *its, gpa_t base, int size, int esz,
> -		 int start_id, entry_fn_t fn, void *opaque)
> +static int lookup_table(struct vgic_its *its, gpa_t base, int size, int esz,
> +			int start_id, entry_fn_t fn, void *opaque)
>  {
>  	gpa_t gpa = base, top = base + size - 1;
>  	unsigned long len = size;
> @@ -1815,6 +1815,107 @@ static int vgic_its_restore_pending_tables(struct kvm *kvm)
>  	return -ENXIO;
>  }
>  
> +static int vgic_its_flush_ite(struct vgic_its *its, struct its_device *dev,
> +			      struct its_ite *ite, gpa_t gpa)
> +{
> +	struct kvm *kvm = its->dev->kvm;
> +	u32 next_offset;
> +	u64 val;
> +
> +	next_offset = compute_next_eventid_offset(&dev->itt_head, ite);
> +	val = ((u64)next_offset << 48) | ((u64)ite->lpi << 16) |
> +		ite->collection->collection_id;

Same remark as before concerning the #define-ing of the encoding and the
name of the function.

> +	val = cpu_to_le64(val);
> +	return kvm_write_guest(kvm, gpa, &val, VITS_ESZ);
> +}
> +
> +/**
> + * vgic_its_restore_ite - restore an interrupt translation entry
> + * @event_id: id used for indexing
> + * @ptr: kernel VA where the 8 byte ITE is located
> + * @opaque: pointer to the its_device
> + * @next: id offset to the next entry
> + */
> +static int vgic_its_restore_ite(struct vgic_its *its, u32 event_id,
> +				void *ptr, void *opaque, u32 *next)
> +{
> +	struct its_device *dev = (struct its_device *)opaque;
> +	struct its_collection *collection;
> +	struct kvm *kvm = its->dev->kvm;
> +	u64 val, *p = (u64 *)ptr;
> +	struct vgic_irq *irq;
> +	u32 coll_id, lpi_id;
> +	struct its_ite *ite;
> +	int ret;
> +
> +	val = *p;
> +	*next = 1;
> +
> +	val = le64_to_cpu(val);
> +
> +	coll_id = val & GENMASK_ULL(15, 0);
> +	lpi_id = (val & GENMASK_ULL(47, 16)) >> 16;
> +
> +	if (!lpi_id)
> +		return 0;
> +
> +	*next = val >> 48;
> +
> +	collection = find_collection(its, coll_id);
> +	if (!collection)
> +		return -EINVAL;
> +
> +	ret = vgic_its_alloc_ite(dev, &ite, collection,
> +				  lpi_id, event_id);
> +	if (ret)
> +		return ret;
> +
> +	irq = vgic_add_lpi(kvm, lpi_id);
> +	if (IS_ERR(irq))
> +		return PTR_ERR(irq);
> +	ite->irq = irq;
> +
> +	/* restore the configuration of the LPI */
> +	ret = update_lpi_config(kvm, irq, NULL);
> +	if (ret)
> +		return ret;
> +
> +	update_affinity_ite(kvm, ite);
> +	return 0;
> +}
> +
> +int vgic_its_flush_itt(struct vgic_its *its, struct its_device *device)
> +{
> +	gpa_t base = device->itt_addr;
> +	struct its_ite *ite;
> +	int ret;
> +
> +	list_for_each_entry(ite, &device->itt_head, ite_list) {
> +		gpa_t gpa = base + ite->event_id * VITS_ESZ;
> +
> +		ret = vgic_its_flush_ite(its, device, ite, gpa);
> +		if (ret)
> +			return ret;
> +	}
> +	return 0;
> +}
> +
> +int vgic_its_restore_itt(struct vgic_its *its, struct its_device *dev)
> +{
> +	size_t max_size = BIT_ULL(dev->nb_eventid_bits) * VITS_ESZ;
> +	gpa_t base = dev->itt_addr;
> +	int ret;
> +
> +	ret =  lookup_table(its, base, max_size, VITS_ESZ, 0,
> +			    vgic_its_restore_ite, dev);
> +
> +	if (ret < 0)
> +		return ret;
> +
> +	/* if the last element has not been found we are in trouble */
> +	return ret ? 0 : -EINVAL;

This makes me wonder. Can't lookup_table perform that check on its own
and always return an error when something went wrong?

> +}
> +
>  /**
>   * vgic_its_flush_device_tables - flush the device table and all ITT
>   * into guest RAM
> 

Thanks,

	M.
-- 
Jazz is not dead. It just smells funny...

^ permalink raw reply	[flat|nested] 144+ messages in thread

* Re: [PATCH v4 21/22] KVM: arm64: ITS: Device table save/restore
  2017-03-27  9:31   ` Eric Auger
@ 2017-04-10 12:42     ` Marc Zyngier
  -1 siblings, 0 replies; 144+ messages in thread
From: Marc Zyngier @ 2017-04-10 12:42 UTC (permalink / raw)
  To: Eric Auger, eric.auger.pro, christoffer.dall, andre.przywara,
	vijayak, Vijaya.Kumar, peter.maydell, linux-arm-kernel, kvmarm,
	kvm
  Cc: Prasun.Kapoor, drjones, pbonzini, dgilbert, quintela

On 27/03/17 10:31, Eric Auger wrote:
> This patch flushes 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 flush
> the translation table using the vgic_its_flush/restore_itt
> routines.
> 
> On restore, devices are re-allocated and their itte are
> re-built.
> 
> Signed-off-by: Eric Auger <eric.auger@redhat.com>
> 
> ---
> 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 | 161 +++++++++++++++++++++++++++++++++++++++++--
>  1 file changed, 156 insertions(+), 5 deletions(-)
> 
> diff --git a/virt/kvm/arm/vgic/vgic-its.c b/virt/kvm/arm/vgic/vgic-its.c
> index 02c0694..a516bbb 100644
> --- a/virt/kvm/arm/vgic/vgic-its.c
> +++ b/virt/kvm/arm/vgic/vgic-its.c
> @@ -1693,7 +1693,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;
> @@ -1884,7 +1885,7 @@ static int vgic_its_restore_ite(struct vgic_its *its, u32 event_id,
>  	return 0;
>  }
>  
> -int vgic_its_flush_itt(struct vgic_its *its, struct its_device *device)
> +static int vgic_its_flush_itt(struct vgic_its *its, struct its_device *device)
>  {
>  	gpa_t base = device->itt_addr;
>  	struct its_ite *ite;
> @@ -1900,7 +1901,7 @@ int vgic_its_flush_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)
>  {
>  	size_t max_size = BIT_ULL(dev->nb_eventid_bits) * VITS_ESZ;
>  	gpa_t base = dev->itt_addr;
> @@ -1917,12 +1918,141 @@ int vgic_its_restore_itt(struct vgic_its *its, struct its_device *dev)
>  }
>  
>  /**
> + * vgic_its_flush_dte - Flush a device table entry at a given GPA
> + *
> + * @its: ITS handle
> + * @dev: ITS device
> + * @ptr: GPA
> + */
> +static int vgic_its_flush_dte(struct vgic_its *its,
> +			      struct its_device *dev, gpa_t ptr)
> +{
> +	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 << 63 | ((u64)next_offset << 49) | (itt_addr_field << 5) |
> +		(dev->nb_eventid_bits - 1));
> +	val = cpu_to_le64(val);
> +	ret = kvm_write_guest(kvm, ptr, &val, 8);
> +	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 >> 63;
> +	nb_eventid_bits = (entry & GENMASK_ULL(4, 0)) + 1;
> +	itt_addr = ((entry & GENMASK_ULL(48, 5)) >> 5) << 8;
> +	*next = 1;
> +
> +	if (!valid)
> +		return 0;
> +
> +	/* dte entry is valid */
> +	*next = (entry & GENMASK_ULL(62, 49)) >> 49;
> +
> +	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;
> +}
> +
> +/**
>   * vgic_its_flush_device_tables - flush 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_flush_device_tables(struct vgic_its *its)
>  {
> -	return -ENXIO;
> +	struct its_device *dev;
> +	u64 baser;
> +
> +	baser = its->baser_device_table;
> +
> +	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_flush_itt(its, dev);
> +		if (ret)
> +			return ret;
> +
> +		ret = vgic_its_flush_dte(its, dev, eaddr);
> +		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)
> +{
> +	int l2_start_id = id * (SZ_64K / GITS_LVL1_ENTRY_SIZE);
> +	u64 entry = *(u64 *)addr;
> +	gpa_t gpa;
> +	int ret;
> +
> +	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, 8,
> +			    l2_start_id, vgic_its_restore_dte, NULL);
> +
> +	if (ret == 1) {
> +		/* last entry was found in this L2 table */
> +		*next_offset = 0;
> +		ret = 0;
> +	}

Ah, that's why you have this complicated return convention.

> +
> +	return ret;
>  }
>  
>  /**
> @@ -1931,7 +2061,28 @@ static int vgic_its_flush_device_tables(struct vgic_its *its)
>   */
>  static int vgic_its_restore_device_tables(struct vgic_its *its)
>  {
> -	return -ENXIO;
> +	u64 baser = its->baser_device_table;
> +	int l1_tbl_size = GITS_BASER_NR_PAGES(baser) * SZ_64K;
> +	int l1_esz = GITS_BASER_ENTRY_SIZE(baser);
> +	gpa_t l1_gpa;
> +	int ret;
> +
> +	l1_gpa = BASER_ADDRESS(baser);
> +	if (!l1_gpa)
> +		return 0;
> +
> +	if (baser & GITS_BASER_INDIRECT)
> +		ret = lookup_table(its, l1_gpa, l1_tbl_size, 8, 0,
> +			    	   handle_l1_entry, NULL);

I wonder if you shouldn't make this a different function (maybe using
the same core helper) to parse L1 tables.

> +	else
> +		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_flush_cte(struct vgic_its *its,
> 

The previous comments about the the encoding still apply... ;-)

Thanks,

	M.
-- 
Jazz is not dead. It just smells funny...

^ permalink raw reply	[flat|nested] 144+ messages in thread

* [PATCH v4 21/22] KVM: arm64: ITS: Device table save/restore
@ 2017-04-10 12:42     ` Marc Zyngier
  0 siblings, 0 replies; 144+ messages in thread
From: Marc Zyngier @ 2017-04-10 12:42 UTC (permalink / raw)
  To: linux-arm-kernel

On 27/03/17 10:31, Eric Auger wrote:
> This patch flushes 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 flush
> the translation table using the vgic_its_flush/restore_itt
> routines.
> 
> On restore, devices are re-allocated and their itte are
> re-built.
> 
> Signed-off-by: Eric Auger <eric.auger@redhat.com>
> 
> ---
> 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 | 161 +++++++++++++++++++++++++++++++++++++++++--
>  1 file changed, 156 insertions(+), 5 deletions(-)
> 
> diff --git a/virt/kvm/arm/vgic/vgic-its.c b/virt/kvm/arm/vgic/vgic-its.c
> index 02c0694..a516bbb 100644
> --- a/virt/kvm/arm/vgic/vgic-its.c
> +++ b/virt/kvm/arm/vgic/vgic-its.c
> @@ -1693,7 +1693,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;
> @@ -1884,7 +1885,7 @@ static int vgic_its_restore_ite(struct vgic_its *its, u32 event_id,
>  	return 0;
>  }
>  
> -int vgic_its_flush_itt(struct vgic_its *its, struct its_device *device)
> +static int vgic_its_flush_itt(struct vgic_its *its, struct its_device *device)
>  {
>  	gpa_t base = device->itt_addr;
>  	struct its_ite *ite;
> @@ -1900,7 +1901,7 @@ int vgic_its_flush_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)
>  {
>  	size_t max_size = BIT_ULL(dev->nb_eventid_bits) * VITS_ESZ;
>  	gpa_t base = dev->itt_addr;
> @@ -1917,12 +1918,141 @@ int vgic_its_restore_itt(struct vgic_its *its, struct its_device *dev)
>  }
>  
>  /**
> + * vgic_its_flush_dte - Flush a device table entry at a given GPA
> + *
> + * @its: ITS handle
> + * @dev: ITS device
> + * @ptr: GPA
> + */
> +static int vgic_its_flush_dte(struct vgic_its *its,
> +			      struct its_device *dev, gpa_t ptr)
> +{
> +	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 << 63 | ((u64)next_offset << 49) | (itt_addr_field << 5) |
> +		(dev->nb_eventid_bits - 1));
> +	val = cpu_to_le64(val);
> +	ret = kvm_write_guest(kvm, ptr, &val, 8);
> +	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 >> 63;
> +	nb_eventid_bits = (entry & GENMASK_ULL(4, 0)) + 1;
> +	itt_addr = ((entry & GENMASK_ULL(48, 5)) >> 5) << 8;
> +	*next = 1;
> +
> +	if (!valid)
> +		return 0;
> +
> +	/* dte entry is valid */
> +	*next = (entry & GENMASK_ULL(62, 49)) >> 49;
> +
> +	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;
> +}
> +
> +/**
>   * vgic_its_flush_device_tables - flush 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_flush_device_tables(struct vgic_its *its)
>  {
> -	return -ENXIO;
> +	struct its_device *dev;
> +	u64 baser;
> +
> +	baser = its->baser_device_table;
> +
> +	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_flush_itt(its, dev);
> +		if (ret)
> +			return ret;
> +
> +		ret = vgic_its_flush_dte(its, dev, eaddr);
> +		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)
> +{
> +	int l2_start_id = id * (SZ_64K / GITS_LVL1_ENTRY_SIZE);
> +	u64 entry = *(u64 *)addr;
> +	gpa_t gpa;
> +	int ret;
> +
> +	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, 8,
> +			    l2_start_id, vgic_its_restore_dte, NULL);
> +
> +	if (ret == 1) {
> +		/* last entry was found in this L2 table */
> +		*next_offset = 0;
> +		ret = 0;
> +	}

Ah, that's why you have this complicated return convention.

> +
> +	return ret;
>  }
>  
>  /**
> @@ -1931,7 +2061,28 @@ static int vgic_its_flush_device_tables(struct vgic_its *its)
>   */
>  static int vgic_its_restore_device_tables(struct vgic_its *its)
>  {
> -	return -ENXIO;
> +	u64 baser = its->baser_device_table;
> +	int l1_tbl_size = GITS_BASER_NR_PAGES(baser) * SZ_64K;
> +	int l1_esz = GITS_BASER_ENTRY_SIZE(baser);
> +	gpa_t l1_gpa;
> +	int ret;
> +
> +	l1_gpa = BASER_ADDRESS(baser);
> +	if (!l1_gpa)
> +		return 0;
> +
> +	if (baser & GITS_BASER_INDIRECT)
> +		ret = lookup_table(its, l1_gpa, l1_tbl_size, 8, 0,
> +			    	   handle_l1_entry, NULL);

I wonder if you shouldn't make this a different function (maybe using
the same core helper) to parse L1 tables.

> +	else
> +		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_flush_cte(struct vgic_its *its,
> 

The previous comments about the the encoding still apply... ;-)

Thanks,

	M.
-- 
Jazz is not dead. It just smells funny...

^ permalink raw reply	[flat|nested] 144+ messages in thread

* Re: [PATCH v4 22/22] KVM: arm64: ITS: Pending table save/restore
  2017-03-27  9:31   ` Eric Auger
@ 2017-04-10 12:50     ` Marc Zyngier
  -1 siblings, 0 replies; 144+ messages in thread
From: Marc Zyngier @ 2017-04-10 12:50 UTC (permalink / raw)
  To: Eric Auger, eric.auger.pro, christoffer.dall, andre.przywara,
	vijayak, Vijaya.Kumar, peter.maydell, linux-arm-kernel, kvmarm,
	kvm
  Cc: Prasun.Kapoor, drjones, pbonzini, dgilbert, quintela

On 27/03/17 10:31, Eric Auger wrote:
> Save and restore the pending tables.
> 
> Pending table restore obviously requires the pendbaser to be
> already set.
> 
> Signed-off-by: Eric Auger <eric.auger@redhat.com>
> 
> ---
> 
> v3 -> v4:
> - remove the wrong comment about locking
> - pass kvm struct instead of its handle
> - add comment about restore method
> - remove GITR_PENDABASER.PTZ check
> - continue if target_vcpu == NULL
> - new locking strategy
> 
> v1 -> v2:
> - do not care about the 1st KB which should be zeroed according to
>   the spec.
> ---
>  virt/kvm/arm/vgic/vgic-its.c | 66 ++++++++++++++++++++++++++++++++++++++++++--
>  1 file changed, 64 insertions(+), 2 deletions(-)
> 
> diff --git a/virt/kvm/arm/vgic/vgic-its.c b/virt/kvm/arm/vgic/vgic-its.c
> index a516bbb..e10aa81 100644
> --- a/virt/kvm/arm/vgic/vgic-its.c
> +++ b/virt/kvm/arm/vgic/vgic-its.c
> @@ -1804,16 +1804,78 @@ static int lookup_table(struct vgic_its *its, gpa_t base, int size, int esz,
>   */
>  static int vgic_its_flush_pending_tables(struct kvm *kvm)
>  {
> -	return -ENXIO;
> +	struct vgic_dist *dist = &kvm->arch.vgic;
> +	struct vgic_irq *irq;
> +	int ret;
> +
> +	list_for_each_entry(irq, &dist->lpi_list_head, lpi_list) {
> +		struct kvm_vcpu *vcpu;
> +		gpa_t pendbase, ptr;
> +		bool stored;
> +		u8 val;
> +
> +		vcpu = irq->target_vcpu;
> +		if (!vcpu)
> +			continue;
> +
> +		pendbase = PENDBASER_ADDRESS(vcpu->arch.vgic_cpu.pendbaser);
> +
> +		ptr = pendbase + (irq->intid / BITS_PER_BYTE);
> +
> +		ret = kvm_read_guest(kvm, (gpa_t)ptr, &val, 1);

ptr is already a gpa_t...

> +		if (ret)
> +			return ret;
> +
> +		stored = val & (irq->intid % BITS_PER_BYTE);
> +		if (stored == irq->pending_latch)
> +			continue;
> +
> +		if (irq->pending_latch)
> +			val |= 1 << (irq->intid % BITS_PER_BYTE);
> +		else
> +			val &= ~(1 << (irq->intid % BITS_PER_BYTE));
> +
> +		ret = kvm_write_guest(kvm, (gpa_t)ptr, &val, 1);
> +		if (ret)
> +			return ret;

Consider the optimization used in its_sync_lpi_pending_table(), where
consecutive LPIs stored in the same byte are set in a single access.

> +	}
> +
> +	return 0;
>  }
>  
>  /**
>   * vgic_its_restore_pending_tables - Restore the pending tables from guest
>   * RAM to internal data structs
> + *
> + * Does not scan the whole pending tables but just loop on all registered
> + * LPIS and scan their associated pending bit. This obviously requires
> + * the ITEs to be restored before.
>   */
>  static int vgic_its_restore_pending_tables(struct kvm *kvm)
>  {
> -	return -ENXIO;
> +	struct vgic_dist *dist = &kvm->arch.vgic;
> +	struct vgic_irq *irq;
> +	int ret;
> +
> +	list_for_each_entry(irq, &dist->lpi_list_head, lpi_list) {
> +		struct kvm_vcpu *vcpu;
> +		gpa_t pendbase, ptr;
> +		u8 val;
> +
> +		vcpu = irq->target_vcpu;
> +		if (!vcpu)
> +			continue;
> +
> +		pendbase = PENDBASER_ADDRESS(vcpu->arch.vgic_cpu.pendbaser);
> +
> +		ptr = pendbase + (irq->intid / BITS_PER_BYTE);
> +
> +		ret = kvm_read_guest(kvm, (gpa_t)ptr, &val, 1);
> +		if (ret)
> +			return ret;
> +		irq->pending_latch = val & (1 << (irq->intid % BITS_PER_BYTE));
> +	}
> +	return 0;

Again, this feels very similar to what its_sync_lpi_pending_table is
doing. We should be able to have some common code here.

>  }
>  
>  static int vgic_its_flush_ite(struct vgic_its *its, struct its_device *dev,
> 

Thanks,

	M.
-- 
Jazz is not dead. It just smells funny...

^ permalink raw reply	[flat|nested] 144+ messages in thread

* [PATCH v4 22/22] KVM: arm64: ITS: Pending table save/restore
@ 2017-04-10 12:50     ` Marc Zyngier
  0 siblings, 0 replies; 144+ messages in thread
From: Marc Zyngier @ 2017-04-10 12:50 UTC (permalink / raw)
  To: linux-arm-kernel

On 27/03/17 10:31, Eric Auger wrote:
> Save and restore the pending tables.
> 
> Pending table restore obviously requires the pendbaser to be
> already set.
> 
> Signed-off-by: Eric Auger <eric.auger@redhat.com>
> 
> ---
> 
> v3 -> v4:
> - remove the wrong comment about locking
> - pass kvm struct instead of its handle
> - add comment about restore method
> - remove GITR_PENDABASER.PTZ check
> - continue if target_vcpu == NULL
> - new locking strategy
> 
> v1 -> v2:
> - do not care about the 1st KB which should be zeroed according to
>   the spec.
> ---
>  virt/kvm/arm/vgic/vgic-its.c | 66 ++++++++++++++++++++++++++++++++++++++++++--
>  1 file changed, 64 insertions(+), 2 deletions(-)
> 
> diff --git a/virt/kvm/arm/vgic/vgic-its.c b/virt/kvm/arm/vgic/vgic-its.c
> index a516bbb..e10aa81 100644
> --- a/virt/kvm/arm/vgic/vgic-its.c
> +++ b/virt/kvm/arm/vgic/vgic-its.c
> @@ -1804,16 +1804,78 @@ static int lookup_table(struct vgic_its *its, gpa_t base, int size, int esz,
>   */
>  static int vgic_its_flush_pending_tables(struct kvm *kvm)
>  {
> -	return -ENXIO;
> +	struct vgic_dist *dist = &kvm->arch.vgic;
> +	struct vgic_irq *irq;
> +	int ret;
> +
> +	list_for_each_entry(irq, &dist->lpi_list_head, lpi_list) {
> +		struct kvm_vcpu *vcpu;
> +		gpa_t pendbase, ptr;
> +		bool stored;
> +		u8 val;
> +
> +		vcpu = irq->target_vcpu;
> +		if (!vcpu)
> +			continue;
> +
> +		pendbase = PENDBASER_ADDRESS(vcpu->arch.vgic_cpu.pendbaser);
> +
> +		ptr = pendbase + (irq->intid / BITS_PER_BYTE);
> +
> +		ret = kvm_read_guest(kvm, (gpa_t)ptr, &val, 1);

ptr is already a gpa_t...

> +		if (ret)
> +			return ret;
> +
> +		stored = val & (irq->intid % BITS_PER_BYTE);
> +		if (stored == irq->pending_latch)
> +			continue;
> +
> +		if (irq->pending_latch)
> +			val |= 1 << (irq->intid % BITS_PER_BYTE);
> +		else
> +			val &= ~(1 << (irq->intid % BITS_PER_BYTE));
> +
> +		ret = kvm_write_guest(kvm, (gpa_t)ptr, &val, 1);
> +		if (ret)
> +			return ret;

Consider the optimization used in its_sync_lpi_pending_table(), where
consecutive LPIs stored in the same byte are set in a single access.

> +	}
> +
> +	return 0;
>  }
>  
>  /**
>   * vgic_its_restore_pending_tables - Restore the pending tables from guest
>   * RAM to internal data structs
> + *
> + * Does not scan the whole pending tables but just loop on all registered
> + * LPIS and scan their associated pending bit. This obviously requires
> + * the ITEs to be restored before.
>   */
>  static int vgic_its_restore_pending_tables(struct kvm *kvm)
>  {
> -	return -ENXIO;
> +	struct vgic_dist *dist = &kvm->arch.vgic;
> +	struct vgic_irq *irq;
> +	int ret;
> +
> +	list_for_each_entry(irq, &dist->lpi_list_head, lpi_list) {
> +		struct kvm_vcpu *vcpu;
> +		gpa_t pendbase, ptr;
> +		u8 val;
> +
> +		vcpu = irq->target_vcpu;
> +		if (!vcpu)
> +			continue;
> +
> +		pendbase = PENDBASER_ADDRESS(vcpu->arch.vgic_cpu.pendbaser);
> +
> +		ptr = pendbase + (irq->intid / BITS_PER_BYTE);
> +
> +		ret = kvm_read_guest(kvm, (gpa_t)ptr, &val, 1);
> +		if (ret)
> +			return ret;
> +		irq->pending_latch = val & (1 << (irq->intid % BITS_PER_BYTE));
> +	}
> +	return 0;

Again, this feels very similar to what its_sync_lpi_pending_table is
doing. We should be able to have some common code here.

>  }
>  
>  static int vgic_its_flush_ite(struct vgic_its *its, struct its_device *dev,
> 

Thanks,

	M.
-- 
Jazz is not dead. It just smells funny...

^ permalink raw reply	[flat|nested] 144+ messages in thread

* Re: [PATCH v4 00/22] vITS save/restore
  2017-03-27  9:30 ` Eric Auger
@ 2017-04-10 12:54   ` Marc Zyngier
  -1 siblings, 0 replies; 144+ messages in thread
From: Marc Zyngier @ 2017-04-10 12:54 UTC (permalink / raw)
  To: Eric Auger, eric.auger.pro, christoffer.dall, andre.przywara,
	vijayak, Vijaya.Kumar, peter.maydell, linux-arm-kernel, kvmarm,
	kvm
  Cc: Prasun.Kapoor, drjones, pbonzini, dgilbert, quintela

Hi Eric,

On 27/03/17 10:30, Eric Auger wrote:
> This series specifies and implements an API aimed at saving and restoring
> the state of the in-kernel emulated ITS device.
> 
> The ITS is programmed through registers and tables. Those latter
> are allocated by the guest. Their base address is programmed in
> registers or table entries before the ITS is enabled.
> 
> The ITS is free to use some of them to flush its internal caches. This
> is likely to be used when entering low power state.
> 
> Therefore, for save/restore use case, it looks natural to use this
> guest RAM allocated space to save the table related data. However,
> currently, The ITS in-kernel emulated device does not use all of those
> tables and for those it uses, it does not always sync them with its
> cached data. Additional sync must happen for:
> - the collection table
> - the device table
> - the per-device translation tables
> - the LPI pending tables.
> 
> The LPI configation table and the command queues do not need extra
> syncs.
> 
> An alternative to flushing the tables into guest RAM could have been
> to flush them into a separate user-space buffer. However the drawback
> of this alternative is that the virtualizer would allocate dedicated
> buffers to store the data that should normally be laid out in guest
> RAM. It would also be obliged to re-compute their size from
> register/table content.
> 
> So saving the tables in guest RAM better fit the ITS programming
> model and optimizes the memory usage. The drawback of this solution
> is it brings additional challenges at user-space level to make sure
> the guest RAM is frozen after table sync.

I think this series is on the right track. What it needs is some
clarification in the spec (as outlined by Christoffer), some tidying up
around the encoding, and various nits that need addressing all over the map.

The only architectural issue is really the ITS/GICR split, but I don't
think this is a big deal.

Thanks,

	M.
-- 
Jazz is not dead. It just smells funny...

^ permalink raw reply	[flat|nested] 144+ messages in thread

* [PATCH v4 00/22] vITS save/restore
@ 2017-04-10 12:54   ` Marc Zyngier
  0 siblings, 0 replies; 144+ messages in thread
From: Marc Zyngier @ 2017-04-10 12:54 UTC (permalink / raw)
  To: linux-arm-kernel

Hi Eric,

On 27/03/17 10:30, Eric Auger wrote:
> This series specifies and implements an API aimed at saving and restoring
> the state of the in-kernel emulated ITS device.
> 
> The ITS is programmed through registers and tables. Those latter
> are allocated by the guest. Their base address is programmed in
> registers or table entries before the ITS is enabled.
> 
> The ITS is free to use some of them to flush its internal caches. This
> is likely to be used when entering low power state.
> 
> Therefore, for save/restore use case, it looks natural to use this
> guest RAM allocated space to save the table related data. However,
> currently, The ITS in-kernel emulated device does not use all of those
> tables and for those it uses, it does not always sync them with its
> cached data. Additional sync must happen for:
> - the collection table
> - the device table
> - the per-device translation tables
> - the LPI pending tables.
> 
> The LPI configation table and the command queues do not need extra
> syncs.
> 
> An alternative to flushing the tables into guest RAM could have been
> to flush them into a separate user-space buffer. However the drawback
> of this alternative is that the virtualizer would allocate dedicated
> buffers to store the data that should normally be laid out in guest
> RAM. It would also be obliged to re-compute their size from
> register/table content.
> 
> So saving the tables in guest RAM better fit the ITS programming
> model and optimizes the memory usage. The drawback of this solution
> is it brings additional challenges at user-space level to make sure
> the guest RAM is frozen after table sync.

I think this series is on the right track. What it needs is some
clarification in the spec (as outlined by Christoffer), some tidying up
around the encoding, and various nits that need addressing all over the map.

The only architectural issue is really the ITS/GICR split, but I don't
think this is a big deal.

Thanks,

	M.
-- 
Jazz is not dead. It just smells funny...

^ permalink raw reply	[flat|nested] 144+ messages in thread

* Re: [PATCH v4 01/22] KVM: arm/arm64: Add vITS save/restore API documentation
  2017-04-08 18:17     ` Christoffer Dall
@ 2017-04-10 14:26       ` Auger Eric
  -1 siblings, 0 replies; 144+ messages in thread
From: Auger Eric @ 2017-04-10 14:26 UTC (permalink / raw)
  To: Christoffer Dall
  Cc: peter.maydell, drjones, kvm, Prasun.Kapoor, marc.zyngier,
	andre.przywara, quintela, dgilbert, Vijaya.Kumar, vijayak,
	pbonzini, kvmarm, linux-arm-kernel, eric.auger.pro

Hi Christoffer,

On 08/04/2017 20:17, Christoffer Dall wrote:
> Hi Eric,
> 
> Most of my comments below are just me being picky about text when
> defining a user space ABI, so I think this mainly looks good, but just
> needs a bit of clarify, except the versioning aspect and exporting the
> pending table vie the redistributor instead, as Marc and Andre have
> pointed out.
> 
> On Mon, Mar 27, 2017 at 11:30:51AM +0200, Eric Auger wrote:
>> Add description for how to access vITS registers and how to flush/restore
>> vITS tables into/from memory
>>
>> Signed-off-by: Eric Auger <eric.auger@redhat.com>
>>
>> ---
>> v3 -> v4:
>> - take into account Peter's comments:
>>   - typos
>>   - KVM_DEV_ARM_VGIC_GRP_ITS_TABLES kvm_device_attr = 0
>>   - add a validity bit in DTE
>>   - document all fields in CTE and ITE
>>   - document ABI revision
>> - take into account Andre's comments:
>>   - document restrictions about GITS_CREADR writing and GITS_IIDR
>>   - document -EBUSY error if one or more VCPUS are runnning
>>   - document 64b registers only can be accessed with 64b access
>> - itt_addr field matches bits [51:8] of the itt_addr
>>
>> v1 -> v2:
>> - DTE and ITE now are 8 bytes
>> - DTE and ITE now indexed by deviceid/eventid
>> - use ITE name instead of ITTE
>> - mentions ITT_addr matches bits [51:8] of the actual address
>> - mentions LE layout
>> ---
>>  Documentation/virtual/kvm/devices/arm-vgic-its.txt | 118 +++++++++++++++++++++
>>  1 file changed, 118 insertions(+)
>>
>> diff --git a/Documentation/virtual/kvm/devices/arm-vgic-its.txt b/Documentation/virtual/kvm/devices/arm-vgic-its.txt
>> index 6081a5b..0902d20 100644
>> --- a/Documentation/virtual/kvm/devices/arm-vgic-its.txt
>> +++ b/Documentation/virtual/kvm/devices/arm-vgic-its.txt
>> @@ -36,3 +36,121 @@ Groups:
>>      -ENXIO:  ITS not properly configured as required prior to setting
>>               this attribute
>>      -ENOMEM: Memory shortage when allocating ITS internal data
>> +
>> +  KVM_DEV_ARM_VGIC_GRP_ITS_REGS
>> +  Attributes:
>> +      The attr field of kvm_device_attr encodes the offset of the
>> +      ITS register, relative to the ITS control frame base address
>> +      (ITS_base).
>> +
>> +      kvm_device_attr.addr points to a __u64 value whatever the width
>> +      of the addressed register (32/64 bits). 64 bit registers can only
>> +      be accessed with full length.
>> +
>> +      Writes to read-only registers are ignored by the kernel except for:
>> +      - GITS_READR. It needs to be restored otherwise commands in the queue
>> +        will be re-executed after CWRITER setting. Writing this register is
>                                      ^^^^^^^^^^^^^^^
> 
> "after restoring CWRITER." ?
OK
> 
>> +        allowed if the ITS is not enabled (GITS_CTLR.enable = 0). Also it
> 
> Does that mean that you can only save/restore a disabled ITS or does it
> mean that initially after creating the ITS it is disabled and userspace
> should restore the CWRITER before restoring GITS_CTLR (which may enable
> the ITS) ?
No I meant the second. As normally the ITS is responsible for updating
the GITS_READR, if the userspace plays with it while the ITS is enabled
this can mess everything. So the userspace is supposed to restore the
GITS_READR *before* restoring the GITS_CTLR which is likely to enable
the ITS.
> 
>> +        needs to be restored after GITS_CBASER since a write to GITS_CBASER
>> +        resets GITS_CREADR.
>> +      - GITS_IIDR. Its Revision field encodes the table layout ABI revision.
> 
> How is this really going to work?  Your ABI here must be backwards
> compatible for future revisions, so what is userspace supposed to do,
> when it reads a newer revision than it was programmed for?
destination ABI revision must be >= source ABI revision
By restoring the IIDR value on the destination side, the userspace
informs destination KVM about the layout of the table. If the
destination KVM does not support this ABI revision, the restoration of
the ITS table fails. Is that wrong?

> 
> I think we need a more clear description of how the revision is going to
> be used, such that each operation on the ITS here is described as
> requiring a minimum revision X, and making sure that userspace can
> safely ignore things that are of a higher revision number, while at the
> same time userspace can decide not to use newer features with older
> kernels.

At the moment I did not plan to implement any way for the userspace to
force the ITS state save in a specified ABI revision. Today it uses the
higher revision. Let's say that ABI V2 supports GICv4, save of source
ITS with be done in v2 layout. A destination only supporting GICv3 (ABI
v1) won't be able to read that format. Does it make sense?

> 
>> +
>> +      For other registers, getting or setting a register has the same
>> +      effect as reading/writing the register on real hardware.
>> +  Errors:
>> +    -ENXIO: Offset does not correspond to any supported register
>> +    -EFAULT: Invalid user pointer for attr->addr
>> +    -EINVAL: Offset is not 64-bit aligned
>> +    -EBUSY: one or more VCPUS are running
>> +
>> +  KVM_DEV_ARM_VGIC_GRP_ITS_TABLES
> 
> Shouldn't this be called KVM_DEV_ARM_VGIC_GRP_FLUSH_ITS_TABLES ?
At the moment this group is used for flush and restore. But as you have
the same remark as Andre I guess it is worth having separate commands in
KVM_DEV_ARM_VGIC_GRP_CTRL then.
> 
>> +  Attributes
>> +       The attr field of kvm_device_attr must be zero.
>> +
>> +       request the flush-save/restore of the ITS tables, namely
> 
> Nit: Request (upper case R)
OK
> 
> what does flush-save/restore mean as opposed to just flush?
meant flush/restore
> 
>> +       the device table, the collection table, all the ITT tables,
>> +       the LPI pending tables. On save, the tables are flushed
> 
> , and the LPI pending table.
OK
> 
>> +       into guest memory at the location provisioned by the guest
>> +       in GITS_BASER (device and collection tables), in the MAPD
>> +       command (ITT_addr), GICR_PENDBASERs (pending tables).
>> +
>> +       This means the GIC should be restored before the ITS and all
> 
> should or must?  Is this enforced?
must. yes it is.
> 
>> +       ITS registers but the GITS_CTLR must be restored before
>> +       restoring the ITS tables.
>> +
>> +       The GITS_READR and GITS_IIDR read-only registers must also
>> +       be restored before the table restore. The IIDR revision field
>> +       encodes the ABI revision of the table layout. If not set by
>> +       user space, the restoration of the tables will fail.
> 
> consider rewording: ", restoring the ITS tables will fail."
OK
> 
>> +
>> +       Note the LPI configuration table is read-only for the
> 
> Note that
OK
> 
>> +       in-kernel ITS and its save/restore goes through the standard
> 
> and saving/restoring it is done via the normal process to save/restore
> guest RAM.
OK
> 
>> +       RAM save/restore.
>> +
>> +       The layout of the tables in guest memory defines an ABI.
>> +       The entries are laid in little endian format as follows;
> 
> s/;/:/
OK
> 
> It's a bit weird to say "as follows:" and then proceed with the error
> descriptions.  I would simply say "as described in the following
> paragraph."
OK
> 
>> +
>> +  Errors:
>> +    -EINVAL: kvm_device_attr not equal to 0, invalid table data
>> +    -EFAULT: invalid guest ram access
>> +    -EBUSY: one or more VCPUS are running
>> +
>> +    ITS Table ABI REV1:
>> +    -------------------
>> +
>> +    The device table and ITE are respectively indexed by device id and
> 
> s/ITE/ITT/
right
> 
> are indexed by the device id and eventid, respectively.
> 
>> +    eventid. The collection table however is not indexed by collection id:
> 
> ...by collection id, instead all the CTEs are written...
> 
>> +    CTE are written at the beginning of the buffer.
> 
> in any particular order, or?
no order or creation
> 
>> +
>> +    Device Table Entry (DTE) layout: entry size = 8 bytes
>> +
>> +    bits:     | 63| 62 ... 49 | 48 ... 5 | 4 ... 0 |
>> +    values:   | V |   next    | ITT_addr |  Size   |
>> +
>> +    where;
>> +    - V indicates whether the entry is valid,
>> +    - ITT_addr matches bits [51:8] of the ITT address (256B aligned),
>> +    - next field is meaningful only if the entry is valid.
> 
> is the ITT_addr meaningful if the entry is not valid?
no, I will add this detail.
> 
>> +    It equals to 0 if this entry is the last one; otherwise it corresponds
>> +    to the minimum between the offset to the next device id and 2^14 -1.
> 
> I don't easily understand this last paragraph and the indentation is
> weird and makes it look like it's not explaining the next field.

reworded:
It equals to 0 if this entry is the last one; otherwise it corresponds
to the the deviceid offset to the next DTE, capped by 2^14 -1.
> 
> You're missing a description of the size field.  Size in what unit?
> Size of what?
right, added "size matches the MAPD Size semantic."
> 
> 
>> +
>> +    Collection Table Entry (CTE) layout: entry size = 8 bytes
>> +
>> +    bits:     | 63| 62 ..  52  | 51 ... 16 | 15  ...   0 |
>> +    values:   | V |    RES0    |  RDBase   |    ICID     |
>> +
>> +    where:
>> +    - V indicates whether the entry is valid,
> 
> Do we explain anywhere what RES0 means?
Added RES0: reserved field with Should-Be-Zero-or-Preserved behavior.
> 
>> +    - RDBase matches the PE number (GICR_TYPER.Processor_Number),
> 
> is 'matches' the right verb to use here?
is
> 
> What exactly is the format of GICR_TYPER.Processor_Number ?
> 
>> +    - ICID matches the collection ID
> 
> again, is 'matches' the right verb to use here?
is
> 
>> +
>> +    Interrupt Translation Entry (ITE) layout: entry size = 8 bytes
>> +
>> +    bits:     | 63 ... 48 | 47 ... 16 | 15 ... 0 |
>> +    values:   |    next   |   pINTID  |  ICID    |
>> +
>> +    where:
>> +    - pINTID is the physical LPI ID,
>> +    - ICID is the collection ID,
> 
> here you use 'is' intead of 'matches'.  At leat be consistent.
is
> 
>> +    - next field is meaningful only if the entry is valid (pINTID != 0).
>> +    It equals to 0 if this entry is the last one; otherwise it corresponds
>> +    to the minimum between the eventid offset to the next ITE and 2^16 -1.
> 
> same comments, as above.
ok
> 
> also, can you list the field in the order they appear?
ok
> 
>> +
>> +    LPI Pending Table layout:
>> +
>> +    As specified in the ARM Generic Interrupt Controller Architecture
>> +    Specification GIC Architecture version 3.0 and version 4. The first
> 
> "...version 4, the first".  ("As specified in X." is not a sentence).
> 
>> +    1kB is not modified and therefore should contain zeroes.
> 
> should or must?  or always contains zeros?  Will you return an error if
> userspace puts something non-zero in there?
no I don't. Spec says it should initialized to zero. $
> 
>> +
>> +    Future evolutions of the ITS table layout:
>> +
>> +    At the moment the table layout is defined and optimized for physical
>> +    LPI support.
> 
> This comment is a bit confusing, because this is all about virtual
> interrupts really, so 'physical from the point of view of the VM', but I
> think you should just drop this sentence.
OK
> 
>> +
>> +    In the future we might implement direct injection of virtual LPIS.
> 
> For nesting, yes?  (on the host this should not be visible here, should
> it?)
yes for nesting.
> 
>> +    This will require an upgrade of the table layout and an evolution of
>> +    the ABI. The ABI revision is encoded in the GITS_IIDR revision field.
>> +    That register must be restored before the table restoration, otherwise
>> +    the operation will fail.
> 
> Hmm, I thought we dealt with that before, feels a bit out of place.

OK moved to the register description.
> 
>> +
>> +    ABI V1: GITS_IIDR.Revision = 1
> 
> I feel like this should go in the ITS register description of the IIDR.
> Most likely, I think this particular line can be dropped, but all other
> definitions in this file can be annoted with a minimum revision number
> ensuring that future revisions implement this, plus potentially more
> stuff.
I already put the following title, "ITS Table ABI REV1" for the table
layout description. My intent was to create a new chapter per revision.
Is it OK?

Thanks

Eric

> 
> Thanks,
> -Christoffer
> 
> _______________________________________________
> linux-arm-kernel mailing list
> linux-arm-kernel@lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
> 

^ permalink raw reply	[flat|nested] 144+ messages in thread

* [PATCH v4 01/22] KVM: arm/arm64: Add vITS save/restore API documentation
@ 2017-04-10 14:26       ` Auger Eric
  0 siblings, 0 replies; 144+ messages in thread
From: Auger Eric @ 2017-04-10 14:26 UTC (permalink / raw)
  To: linux-arm-kernel

Hi Christoffer,

On 08/04/2017 20:17, Christoffer Dall wrote:
> Hi Eric,
> 
> Most of my comments below are just me being picky about text when
> defining a user space ABI, so I think this mainly looks good, but just
> needs a bit of clarify, except the versioning aspect and exporting the
> pending table vie the redistributor instead, as Marc and Andre have
> pointed out.
> 
> On Mon, Mar 27, 2017 at 11:30:51AM +0200, Eric Auger wrote:
>> Add description for how to access vITS registers and how to flush/restore
>> vITS tables into/from memory
>>
>> Signed-off-by: Eric Auger <eric.auger@redhat.com>
>>
>> ---
>> v3 -> v4:
>> - take into account Peter's comments:
>>   - typos
>>   - KVM_DEV_ARM_VGIC_GRP_ITS_TABLES kvm_device_attr = 0
>>   - add a validity bit in DTE
>>   - document all fields in CTE and ITE
>>   - document ABI revision
>> - take into account Andre's comments:
>>   - document restrictions about GITS_CREADR writing and GITS_IIDR
>>   - document -EBUSY error if one or more VCPUS are runnning
>>   - document 64b registers only can be accessed with 64b access
>> - itt_addr field matches bits [51:8] of the itt_addr
>>
>> v1 -> v2:
>> - DTE and ITE now are 8 bytes
>> - DTE and ITE now indexed by deviceid/eventid
>> - use ITE name instead of ITTE
>> - mentions ITT_addr matches bits [51:8] of the actual address
>> - mentions LE layout
>> ---
>>  Documentation/virtual/kvm/devices/arm-vgic-its.txt | 118 +++++++++++++++++++++
>>  1 file changed, 118 insertions(+)
>>
>> diff --git a/Documentation/virtual/kvm/devices/arm-vgic-its.txt b/Documentation/virtual/kvm/devices/arm-vgic-its.txt
>> index 6081a5b..0902d20 100644
>> --- a/Documentation/virtual/kvm/devices/arm-vgic-its.txt
>> +++ b/Documentation/virtual/kvm/devices/arm-vgic-its.txt
>> @@ -36,3 +36,121 @@ Groups:
>>      -ENXIO:  ITS not properly configured as required prior to setting
>>               this attribute
>>      -ENOMEM: Memory shortage when allocating ITS internal data
>> +
>> +  KVM_DEV_ARM_VGIC_GRP_ITS_REGS
>> +  Attributes:
>> +      The attr field of kvm_device_attr encodes the offset of the
>> +      ITS register, relative to the ITS control frame base address
>> +      (ITS_base).
>> +
>> +      kvm_device_attr.addr points to a __u64 value whatever the width
>> +      of the addressed register (32/64 bits). 64 bit registers can only
>> +      be accessed with full length.
>> +
>> +      Writes to read-only registers are ignored by the kernel except for:
>> +      - GITS_READR. It needs to be restored otherwise commands in the queue
>> +        will be re-executed after CWRITER setting. Writing this register is
>                                      ^^^^^^^^^^^^^^^
> 
> "after restoring CWRITER." ?
OK
> 
>> +        allowed if the ITS is not enabled (GITS_CTLR.enable = 0). Also it
> 
> Does that mean that you can only save/restore a disabled ITS or does it
> mean that initially after creating the ITS it is disabled and userspace
> should restore the CWRITER before restoring GITS_CTLR (which may enable
> the ITS) ?
No I meant the second. As normally the ITS is responsible for updating
the GITS_READR, if the userspace plays with it while the ITS is enabled
this can mess everything. So the userspace is supposed to restore the
GITS_READR *before* restoring the GITS_CTLR which is likely to enable
the ITS.
> 
>> +        needs to be restored after GITS_CBASER since a write to GITS_CBASER
>> +        resets GITS_CREADR.
>> +      - GITS_IIDR. Its Revision field encodes the table layout ABI revision.
> 
> How is this really going to work?  Your ABI here must be backwards
> compatible for future revisions, so what is userspace supposed to do,
> when it reads a newer revision than it was programmed for?
destination ABI revision must be >= source ABI revision
By restoring the IIDR value on the destination side, the userspace
informs destination KVM about the layout of the table. If the
destination KVM does not support this ABI revision, the restoration of
the ITS table fails. Is that wrong?

> 
> I think we need a more clear description of how the revision is going to
> be used, such that each operation on the ITS here is described as
> requiring a minimum revision X, and making sure that userspace can
> safely ignore things that are of a higher revision number, while at the
> same time userspace can decide not to use newer features with older
> kernels.

At the moment I did not plan to implement any way for the userspace to
force the ITS state save in a specified ABI revision. Today it uses the
higher revision. Let's say that ABI V2 supports GICv4, save of source
ITS with be done in v2 layout. A destination only supporting GICv3 (ABI
v1) won't be able to read that format. Does it make sense?

> 
>> +
>> +      For other registers, getting or setting a register has the same
>> +      effect as reading/writing the register on real hardware.
>> +  Errors:
>> +    -ENXIO: Offset does not correspond to any supported register
>> +    -EFAULT: Invalid user pointer for attr->addr
>> +    -EINVAL: Offset is not 64-bit aligned
>> +    -EBUSY: one or more VCPUS are running
>> +
>> +  KVM_DEV_ARM_VGIC_GRP_ITS_TABLES
> 
> Shouldn't this be called KVM_DEV_ARM_VGIC_GRP_FLUSH_ITS_TABLES ?
At the moment this group is used for flush and restore. But as you have
the same remark as Andre I guess it is worth having separate commands in
KVM_DEV_ARM_VGIC_GRP_CTRL then.
> 
>> +  Attributes
>> +       The attr field of kvm_device_attr must be zero.
>> +
>> +       request the flush-save/restore of the ITS tables, namely
> 
> Nit: Request (upper case R)
OK
> 
> what does flush-save/restore mean as opposed to just flush?
meant flush/restore
> 
>> +       the device table, the collection table, all the ITT tables,
>> +       the LPI pending tables. On save, the tables are flushed
> 
> , and the LPI pending table.
OK
> 
>> +       into guest memory at the location provisioned by the guest
>> +       in GITS_BASER (device and collection tables), in the MAPD
>> +       command (ITT_addr), GICR_PENDBASERs (pending tables).
>> +
>> +       This means the GIC should be restored before the ITS and all
> 
> should or must?  Is this enforced?
must. yes it is.
> 
>> +       ITS registers but the GITS_CTLR must be restored before
>> +       restoring the ITS tables.
>> +
>> +       The GITS_READR and GITS_IIDR read-only registers must also
>> +       be restored before the table restore. The IIDR revision field
>> +       encodes the ABI revision of the table layout. If not set by
>> +       user space, the restoration of the tables will fail.
> 
> consider rewording: ", restoring the ITS tables will fail."
OK
> 
>> +
>> +       Note the LPI configuration table is read-only for the
> 
> Note that
OK
> 
>> +       in-kernel ITS and its save/restore goes through the standard
> 
> and saving/restoring it is done via the normal process to save/restore
> guest RAM.
OK
> 
>> +       RAM save/restore.
>> +
>> +       The layout of the tables in guest memory defines an ABI.
>> +       The entries are laid in little endian format as follows;
> 
> s/;/:/
OK
> 
> It's a bit weird to say "as follows:" and then proceed with the error
> descriptions.  I would simply say "as described in the following
> paragraph."
OK
> 
>> +
>> +  Errors:
>> +    -EINVAL: kvm_device_attr not equal to 0, invalid table data
>> +    -EFAULT: invalid guest ram access
>> +    -EBUSY: one or more VCPUS are running
>> +
>> +    ITS Table ABI REV1:
>> +    -------------------
>> +
>> +    The device table and ITE are respectively indexed by device id and
> 
> s/ITE/ITT/
right
> 
> are indexed by the device id and eventid, respectively.
> 
>> +    eventid. The collection table however is not indexed by collection id:
> 
> ...by collection id, instead all the CTEs are written...
> 
>> +    CTE are written at the beginning of the buffer.
> 
> in any particular order, or?
no order or creation
> 
>> +
>> +    Device Table Entry (DTE) layout: entry size = 8 bytes
>> +
>> +    bits:     | 63| 62 ... 49 | 48 ... 5 | 4 ... 0 |
>> +    values:   | V |   next    | ITT_addr |  Size   |
>> +
>> +    where;
>> +    - V indicates whether the entry is valid,
>> +    - ITT_addr matches bits [51:8] of the ITT address (256B aligned),
>> +    - next field is meaningful only if the entry is valid.
> 
> is the ITT_addr meaningful if the entry is not valid?
no, I will add this detail.
> 
>> +    It equals to 0 if this entry is the last one; otherwise it corresponds
>> +    to the minimum between the offset to the next device id and 2^14 -1.
> 
> I don't easily understand this last paragraph and the indentation is
> weird and makes it look like it's not explaining the next field.

reworded:
It equals to 0 if this entry is the last one; otherwise it corresponds
to the the deviceid offset to the next DTE, capped by 2^14 -1.
> 
> You're missing a description of the size field.  Size in what unit?
> Size of what?
right, added "size matches the MAPD Size semantic."
> 
> 
>> +
>> +    Collection Table Entry (CTE) layout: entry size = 8 bytes
>> +
>> +    bits:     | 63| 62 ..  52  | 51 ... 16 | 15  ...   0 |
>> +    values:   | V |    RES0    |  RDBase   |    ICID     |
>> +
>> +    where:
>> +    - V indicates whether the entry is valid,
> 
> Do we explain anywhere what RES0 means?
Added RES0: reserved field with Should-Be-Zero-or-Preserved behavior.
> 
>> +    - RDBase matches the PE number (GICR_TYPER.Processor_Number),
> 
> is 'matches' the right verb to use here?
is
> 
> What exactly is the format of GICR_TYPER.Processor_Number ?
> 
>> +    - ICID matches the collection ID
> 
> again, is 'matches' the right verb to use here?
is
> 
>> +
>> +    Interrupt Translation Entry (ITE) layout: entry size = 8 bytes
>> +
>> +    bits:     | 63 ... 48 | 47 ... 16 | 15 ... 0 |
>> +    values:   |    next   |   pINTID  |  ICID    |
>> +
>> +    where:
>> +    - pINTID is the physical LPI ID,
>> +    - ICID is the collection ID,
> 
> here you use 'is' intead of 'matches'.  At leat be consistent.
is
> 
>> +    - next field is meaningful only if the entry is valid (pINTID != 0).
>> +    It equals to 0 if this entry is the last one; otherwise it corresponds
>> +    to the minimum between the eventid offset to the next ITE and 2^16 -1.
> 
> same comments, as above.
ok
> 
> also, can you list the field in the order they appear?
ok
> 
>> +
>> +    LPI Pending Table layout:
>> +
>> +    As specified in the ARM Generic Interrupt Controller Architecture
>> +    Specification GIC Architecture version 3.0 and version 4. The first
> 
> "...version 4, the first".  ("As specified in X." is not a sentence).
> 
>> +    1kB is not modified and therefore should contain zeroes.
> 
> should or must?  or always contains zeros?  Will you return an error if
> userspace puts something non-zero in there?
no I don't. Spec says it should initialized to zero. $
> 
>> +
>> +    Future evolutions of the ITS table layout:
>> +
>> +    At the moment the table layout is defined and optimized for physical
>> +    LPI support.
> 
> This comment is a bit confusing, because this is all about virtual
> interrupts really, so 'physical from the point of view of the VM', but I
> think you should just drop this sentence.
OK
> 
>> +
>> +    In the future we might implement direct injection of virtual LPIS.
> 
> For nesting, yes?  (on the host this should not be visible here, should
> it?)
yes for nesting.
> 
>> +    This will require an upgrade of the table layout and an evolution of
>> +    the ABI. The ABI revision is encoded in the GITS_IIDR revision field.
>> +    That register must be restored before the table restoration, otherwise
>> +    the operation will fail.
> 
> Hmm, I thought we dealt with that before, feels a bit out of place.

OK moved to the register description.
> 
>> +
>> +    ABI V1: GITS_IIDR.Revision = 1
> 
> I feel like this should go in the ITS register description of the IIDR.
> Most likely, I think this particular line can be dropped, but all other
> definitions in this file can be annoted with a minimum revision number
> ensuring that future revisions implement this, plus potentially more
> stuff.
I already put the following title, "ITS Table ABI REV1" for the table
layout description. My intent was to create a new chapter per revision.
Is it OK?

Thanks

Eric

> 
> Thanks,
> -Christoffer
> 
> _______________________________________________
> linux-arm-kernel mailing list
> linux-arm-kernel at lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
> 

^ permalink raw reply	[flat|nested] 144+ messages in thread

* Re: [PATCH v4 08/22] KVM: arm64: ITS: Implement vgic_mmio_uaccess_write_its_iidr
  2017-04-08 10:42     ` Marc Zyngier
@ 2017-04-10 14:32       ` Auger Eric
  -1 siblings, 0 replies; 144+ messages in thread
From: Auger Eric @ 2017-04-10 14:32 UTC (permalink / raw)
  To: Marc Zyngier
  Cc: peter.maydell, drjones, kvm, Prasun.Kapoor, vijayak,
	andre.przywara, quintela, dgilbert, Vijaya.Kumar,
	linux-arm-kernel, pbonzini, kvmarm, christoffer.dall,
	eric.auger.pro

Hi Marc,

On 08/04/2017 12:42, Marc Zyngier wrote:
> On Mon, Mar 27 2017 at 10:30:58 AM, Eric Auger <eric.auger@redhat.com> wrote:
>> The GITS_IIDR revision field is used to encode the version of the
>> table layout (ABI). So we need to restore it to check the table
>> layout to be restored is compatible with the destination vITS.
>>
>> The user selected revision is stored in the user_revision field.
>> It will be compared against the REV num at table restoration time.
> 
> Why isn't it sufficient to keep it GITS_IIDR RO and let userspace find
> out about the ABI revision that the kernel understands?
> 
> Or are we planning on supporting multiple ABIs in the kernel?
Yes as discussed with Peter, the plan is to allow several ABIs. So the
userspace informs the destination about the ABI revision of the stored
tables (contained by the GITS_IIDR). If the destination KVM does not
support this ABI revision, table restore will fail.
 If so, do
> we have a deprecation policy/plan? I don't mind either way, but it would
> be good to document it...
> 
> Maybe it is documented already and I missed it (which is perfectly
> possible!).
Well this is partly documented in
Documentation/virtual/kvm/devices/arm-vgic-its.txt. No plan to
deprecate. migration from KVM supporting v1 to KVM supporting V2 would
be possible but not the contrary.

Does it make sense?

Thanks

Eric
> 
> Thanks,
> 
> 	M.
> 

^ permalink raw reply	[flat|nested] 144+ messages in thread

* [PATCH v4 08/22] KVM: arm64: ITS: Implement vgic_mmio_uaccess_write_its_iidr
@ 2017-04-10 14:32       ` Auger Eric
  0 siblings, 0 replies; 144+ messages in thread
From: Auger Eric @ 2017-04-10 14:32 UTC (permalink / raw)
  To: linux-arm-kernel

Hi Marc,

On 08/04/2017 12:42, Marc Zyngier wrote:
> On Mon, Mar 27 2017 at 10:30:58 AM, Eric Auger <eric.auger@redhat.com> wrote:
>> The GITS_IIDR revision field is used to encode the version of the
>> table layout (ABI). So we need to restore it to check the table
>> layout to be restored is compatible with the destination vITS.
>>
>> The user selected revision is stored in the user_revision field.
>> It will be compared against the REV num at table restoration time.
> 
> Why isn't it sufficient to keep it GITS_IIDR RO and let userspace find
> out about the ABI revision that the kernel understands?
> 
> Or are we planning on supporting multiple ABIs in the kernel?
Yes as discussed with Peter, the plan is to allow several ABIs. So the
userspace informs the destination about the ABI revision of the stored
tables (contained by the GITS_IIDR). If the destination KVM does not
support this ABI revision, table restore will fail.
 If so, do
> we have a deprecation policy/plan? I don't mind either way, but it would
> be good to document it...
> 
> Maybe it is documented already and I missed it (which is perfectly
> possible!).
Well this is partly documented in
Documentation/virtual/kvm/devices/arm-vgic-its.txt. No plan to
deprecate. migration from KVM supporting v1 to KVM supporting V2 would
be possible but not the contrary.

Does it make sense?

Thanks

Eric
> 
> Thanks,
> 
> 	M.
> 

^ permalink raw reply	[flat|nested] 144+ messages in thread

* Re: [PATCH v4 08/22] KVM: arm64: ITS: Implement vgic_mmio_uaccess_write_its_iidr
  2017-04-10 14:32       ` Auger Eric
@ 2017-04-10 14:57         ` Marc Zyngier
  -1 siblings, 0 replies; 144+ messages in thread
From: Marc Zyngier @ 2017-04-10 14:57 UTC (permalink / raw)
  To: Auger Eric
  Cc: kvm, Prasun.Kapoor, vijayak, andre.przywara, quintela, dgilbert,
	Vijaya.Kumar, pbonzini, kvmarm, linux-arm-kernel, eric.auger.pro

On 10/04/17 15:32, Auger Eric wrote:
> Hi Marc,
> 
> On 08/04/2017 12:42, Marc Zyngier wrote:
>> On Mon, Mar 27 2017 at 10:30:58 AM, Eric Auger <eric.auger@redhat.com> wrote:
>>> The GITS_IIDR revision field is used to encode the version of the
>>> table layout (ABI). So we need to restore it to check the table
>>> layout to be restored is compatible with the destination vITS.
>>>
>>> The user selected revision is stored in the user_revision field.
>>> It will be compared against the REV num at table restoration time.
>>
>> Why isn't it sufficient to keep it GITS_IIDR RO and let userspace find
>> out about the ABI revision that the kernel understands?
>>
>> Or are we planning on supporting multiple ABIs in the kernel?
> Yes as discussed with Peter, the plan is to allow several ABIs. So the
> userspace informs the destination about the ABI revision of the stored
> tables (contained by the GITS_IIDR). If the destination KVM does not
> support this ABI revision, table restore will fail.
>  If so, do
>> we have a deprecation policy/plan? I don't mind either way, but it would
>> be good to document it...
>>
>> Maybe it is documented already and I missed it (which is perfectly
>> possible!).
> Well this is partly documented in
> Documentation/virtual/kvm/devices/arm-vgic-its.txt. No plan to
> deprecate. migration from KVM supporting v1 to KVM supporting V2 would
> be possible but not the contrary.
> 
> Does it make sense?

Sort of. Say you have three systems: A and C, which only supports v1; B,
which supports v1 and v2. Let's say you migrate from A to B, and from B
to C. Is B mandated to be able to export the tables as v1 and v2? Or can
it restrict what it can export?

Thanks,

	M.
-- 
Jazz is not dead. It just smells funny...

^ permalink raw reply	[flat|nested] 144+ messages in thread

* [PATCH v4 08/22] KVM: arm64: ITS: Implement vgic_mmio_uaccess_write_its_iidr
@ 2017-04-10 14:57         ` Marc Zyngier
  0 siblings, 0 replies; 144+ messages in thread
From: Marc Zyngier @ 2017-04-10 14:57 UTC (permalink / raw)
  To: linux-arm-kernel

On 10/04/17 15:32, Auger Eric wrote:
> Hi Marc,
> 
> On 08/04/2017 12:42, Marc Zyngier wrote:
>> On Mon, Mar 27 2017 at 10:30:58 AM, Eric Auger <eric.auger@redhat.com> wrote:
>>> The GITS_IIDR revision field is used to encode the version of the
>>> table layout (ABI). So we need to restore it to check the table
>>> layout to be restored is compatible with the destination vITS.
>>>
>>> The user selected revision is stored in the user_revision field.
>>> It will be compared against the REV num at table restoration time.
>>
>> Why isn't it sufficient to keep it GITS_IIDR RO and let userspace find
>> out about the ABI revision that the kernel understands?
>>
>> Or are we planning on supporting multiple ABIs in the kernel?
> Yes as discussed with Peter, the plan is to allow several ABIs. So the
> userspace informs the destination about the ABI revision of the stored
> tables (contained by the GITS_IIDR). If the destination KVM does not
> support this ABI revision, table restore will fail.
>  If so, do
>> we have a deprecation policy/plan? I don't mind either way, but it would
>> be good to document it...
>>
>> Maybe it is documented already and I missed it (which is perfectly
>> possible!).
> Well this is partly documented in
> Documentation/virtual/kvm/devices/arm-vgic-its.txt. No plan to
> deprecate. migration from KVM supporting v1 to KVM supporting V2 would
> be possible but not the contrary.
> 
> Does it make sense?

Sort of. Say you have three systems: A and C, which only supports v1; B,
which supports v1 and v2. Let's say you migrate from A to B, and from B
to C. Is B mandated to be able to export the tables as v1 and v2? Or can
it restrict what it can export?

Thanks,

	M.
-- 
Jazz is not dead. It just smells funny...

^ permalink raw reply	[flat|nested] 144+ messages in thread

* Re: [PATCH v4 08/22] KVM: arm64: ITS: Implement vgic_mmio_uaccess_write_its_iidr
  2017-04-10 14:57         ` Marc Zyngier
@ 2017-04-10 15:07           ` Peter Maydell
  -1 siblings, 0 replies; 144+ messages in thread
From: Peter Maydell @ 2017-04-10 15:07 UTC (permalink / raw)
  To: Marc Zyngier
  Cc: prasun.kapoor, kvm-devel, Juan Quintela, Vijaya Kumar K,
	Andre Przywara, Dr. David Alan Gilbert, Kumar, Vijaya,
	Paolo Bonzini, kvmarm, arm-mail-list, eric.auger.pro

On 10 April 2017 at 15:57, Marc Zyngier <marc.zyngier@arm.com> wrote:
> On 10/04/17 15:32, Auger Eric wrote:
>> Well this is partly documented in
>> Documentation/virtual/kvm/devices/arm-vgic-its.txt. No plan to
>> deprecate. migration from KVM supporting v1 to KVM supporting V2 would
>> be possible but not the contrary.
>>
>> Does it make sense?
>
> Sort of. Say you have three systems: A and C, which only supports v1; B,
> which supports v1 and v2. Let's say you migrate from A to B, and from B
> to C. Is B mandated to be able to export the tables as v1 and v2? Or can
> it restrict what it can export?

Generally for QEMU we only require forwards-compatibility (so
in this case old-kernel to new-kernel has to work but new-kernel
to old-kernel need not). Export-as-old-format if the in-kernel
data can be represented in the old format would be a nice to have
property only (and depending what the unanticipated future need
is, might not be possible at all).

The idea here is not that we expect to need this, but to give
ourselves an escape hatch for future use if we do find we need
to add something which won't fit in the currently defined format.

thanks
-- PMM

^ permalink raw reply	[flat|nested] 144+ messages in thread

* [PATCH v4 08/22] KVM: arm64: ITS: Implement vgic_mmio_uaccess_write_its_iidr
@ 2017-04-10 15:07           ` Peter Maydell
  0 siblings, 0 replies; 144+ messages in thread
From: Peter Maydell @ 2017-04-10 15:07 UTC (permalink / raw)
  To: linux-arm-kernel

On 10 April 2017 at 15:57, Marc Zyngier <marc.zyngier@arm.com> wrote:
> On 10/04/17 15:32, Auger Eric wrote:
>> Well this is partly documented in
>> Documentation/virtual/kvm/devices/arm-vgic-its.txt. No plan to
>> deprecate. migration from KVM supporting v1 to KVM supporting V2 would
>> be possible but not the contrary.
>>
>> Does it make sense?
>
> Sort of. Say you have three systems: A and C, which only supports v1; B,
> which supports v1 and v2. Let's say you migrate from A to B, and from B
> to C. Is B mandated to be able to export the tables as v1 and v2? Or can
> it restrict what it can export?

Generally for QEMU we only require forwards-compatibility (so
in this case old-kernel to new-kernel has to work but new-kernel
to old-kernel need not). Export-as-old-format if the in-kernel
data can be represented in the old format would be a nice to have
property only (and depending what the unanticipated future need
is, might not be possible at all).

The idea here is not that we expect to need this, but to give
ourselves an escape hatch for future use if we do find we need
to add something which won't fit in the currently defined format.

thanks
-- PMM

^ permalink raw reply	[flat|nested] 144+ messages in thread

* Re: [PATCH v4 08/22] KVM: arm64: ITS: Implement vgic_mmio_uaccess_write_its_iidr
  2017-04-10 14:57         ` Marc Zyngier
@ 2017-04-10 15:17           ` Auger Eric
  -1 siblings, 0 replies; 144+ messages in thread
From: Auger Eric @ 2017-04-10 15:17 UTC (permalink / raw)
  To: Marc Zyngier
  Cc: peter.maydell, drjones, kvm, Prasun.Kapoor, vijayak,
	andre.przywara, quintela, dgilbert, Vijaya.Kumar,
	christoffer.dall, pbonzini, kvmarm, linux-arm-kernel,
	eric.auger.pro

Hi Marc,

On 10/04/2017 16:57, Marc Zyngier wrote:
> On 10/04/17 15:32, Auger Eric wrote:
>> Hi Marc,
>>
>> On 08/04/2017 12:42, Marc Zyngier wrote:
>>> On Mon, Mar 27 2017 at 10:30:58 AM, Eric Auger <eric.auger@redhat.com> wrote:
>>>> The GITS_IIDR revision field is used to encode the version of the
>>>> table layout (ABI). So we need to restore it to check the table
>>>> layout to be restored is compatible with the destination vITS.
>>>>
>>>> The user selected revision is stored in the user_revision field.
>>>> It will be compared against the REV num at table restoration time.
>>>
>>> Why isn't it sufficient to keep it GITS_IIDR RO and let userspace find
>>> out about the ABI revision that the kernel understands?
>>>
>>> Or are we planning on supporting multiple ABIs in the kernel?
>> Yes as discussed with Peter, the plan is to allow several ABIs. So the
>> userspace informs the destination about the ABI revision of the stored
>> tables (contained by the GITS_IIDR). If the destination KVM does not
>> support this ABI revision, table restore will fail.
>>  If so, do
>>> we have a deprecation policy/plan? I don't mind either way, but it would
>>> be good to document it...
>>>
>>> Maybe it is documented already and I missed it (which is perfectly
>>> possible!).
>> Well this is partly documented in
>> Documentation/virtual/kvm/devices/arm-vgic-its.txt. No plan to
>> deprecate. migration from KVM supporting v1 to KVM supporting V2 would
>> be possible but not the contrary.
>>
>> Does it make sense?
> 
> Sort of. Say you have three systems: A and C, which only supports v1; B,
> which supports v1 and v2. Let's say you migrate from A to B, and from B
> to C. Is B mandated to be able to export the tables as v1 and v2? Or can
> it restrict what it can export?
At the moment migration from B to C will fail because source ABI rev =
v2 > destination support ABI = v1.

A (v1) -> B (v1 & v2): migration OK
B (v1 & v2) -> C (v1): migration NOK

What could be done if we want something clever is source KVM detects
which ABI is sufficient and choose the lowest revision for the save. for
instance if no vLPI choose rev1, otherwise rev2. rev2 typically is
needed for vLPI support for nested as we need to save/restore vPE table
and vLPIs in ITE (2x8 byte entries).

The problem is that once you have migrated to B and you start playing
with vLPIs and C do not know the table layout for vPE/vLPIs, you can't
migrate anymore.

Thanks

Eric
> 
> Thanks,
> 
> 	M.
> 

^ permalink raw reply	[flat|nested] 144+ messages in thread

* [PATCH v4 08/22] KVM: arm64: ITS: Implement vgic_mmio_uaccess_write_its_iidr
@ 2017-04-10 15:17           ` Auger Eric
  0 siblings, 0 replies; 144+ messages in thread
From: Auger Eric @ 2017-04-10 15:17 UTC (permalink / raw)
  To: linux-arm-kernel

Hi Marc,

On 10/04/2017 16:57, Marc Zyngier wrote:
> On 10/04/17 15:32, Auger Eric wrote:
>> Hi Marc,
>>
>> On 08/04/2017 12:42, Marc Zyngier wrote:
>>> On Mon, Mar 27 2017 at 10:30:58 AM, Eric Auger <eric.auger@redhat.com> wrote:
>>>> The GITS_IIDR revision field is used to encode the version of the
>>>> table layout (ABI). So we need to restore it to check the table
>>>> layout to be restored is compatible with the destination vITS.
>>>>
>>>> The user selected revision is stored in the user_revision field.
>>>> It will be compared against the REV num at table restoration time.
>>>
>>> Why isn't it sufficient to keep it GITS_IIDR RO and let userspace find
>>> out about the ABI revision that the kernel understands?
>>>
>>> Or are we planning on supporting multiple ABIs in the kernel?
>> Yes as discussed with Peter, the plan is to allow several ABIs. So the
>> userspace informs the destination about the ABI revision of the stored
>> tables (contained by the GITS_IIDR). If the destination KVM does not
>> support this ABI revision, table restore will fail.
>>  If so, do
>>> we have a deprecation policy/plan? I don't mind either way, but it would
>>> be good to document it...
>>>
>>> Maybe it is documented already and I missed it (which is perfectly
>>> possible!).
>> Well this is partly documented in
>> Documentation/virtual/kvm/devices/arm-vgic-its.txt. No plan to
>> deprecate. migration from KVM supporting v1 to KVM supporting V2 would
>> be possible but not the contrary.
>>
>> Does it make sense?
> 
> Sort of. Say you have three systems: A and C, which only supports v1; B,
> which supports v1 and v2. Let's say you migrate from A to B, and from B
> to C. Is B mandated to be able to export the tables as v1 and v2? Or can
> it restrict what it can export?
At the moment migration from B to C will fail because source ABI rev =
v2 > destination support ABI = v1.

A (v1) -> B (v1 & v2): migration OK
B (v1 & v2) -> C (v1): migration NOK

What could be done if we want something clever is source KVM detects
which ABI is sufficient and choose the lowest revision for the save. for
instance if no vLPI choose rev1, otherwise rev2. rev2 typically is
needed for vLPI support for nested as we need to save/restore vPE table
and vLPIs in ITE (2x8 byte entries).

The problem is that once you have migrated to B and you start playing
with vLPIs and C do not know the table layout for vPE/vLPIs, you can't
migrate anymore.

Thanks

Eric
> 
> Thanks,
> 
> 	M.
> 

^ permalink raw reply	[flat|nested] 144+ messages in thread

* Re: [PATCH v4 18/22] KVM: arm64: ITS: Collection table save/restore
  2017-04-10  9:55     ` Marc Zyngier
@ 2017-04-11  9:57       ` Auger Eric
  -1 siblings, 0 replies; 144+ messages in thread
From: Auger Eric @ 2017-04-11  9:57 UTC (permalink / raw)
  To: Marc Zyngier, eric.auger.pro, christoffer.dall, andre.przywara,
	vijayak, Vijaya.Kumar, peter.maydell, linux-arm-kernel, kvmarm,
	kvm
  Cc: Prasun.Kapoor, drjones, pbonzini, dgilbert, quintela

Hi Marc,

On 10/04/2017 11:55, Marc Zyngier wrote:
> On 27/03/17 10:31, Eric Auger wrote:
>> The flush path copies the collection entries into guest RAM
>> at the GPA specified in the BASER register. This obviously
>> requires the BASER to be set. The last written element
>> is a dummy collection table entry.
>>
>> We do not index by collection ID as the collection entry
>> can fit into 8 bytes while containing the collection ID.
>>
>> On restore path we re-allocate the collection objects.
>>
>> Signed-off-by: Eric Auger <eric.auger@redhat.com>
>>
>> ---
>>
>> v3 -> v4:
>> - replaced u64 *ptr by gpa_t gpa
>> - check the collection does not exist before allocating it
>>
>> v1 -> v2:
>> - reword commit message and directly use 8 as entry size
>> - no kvm parameter anymore
>> - add helper for flush/restore cte
>> - table size computed here
>> - add le64/cpu conversions
>> ---
>>  virt/kvm/arm/vgic/vgic-its.c | 99 +++++++++++++++++++++++++++++++++++++++++++-
>>  1 file changed, 97 insertions(+), 2 deletions(-)
>>
>> diff --git a/virt/kvm/arm/vgic/vgic-its.c b/virt/kvm/arm/vgic/vgic-its.c
>> index 8eaeba4..df984b6 100644
>> --- a/virt/kvm/arm/vgic/vgic-its.c
>> +++ b/virt/kvm/arm/vgic/vgic-its.c
>> @@ -1828,13 +1828,89 @@ static int vgic_its_restore_device_tables(struct vgic_its *its)
>>  	return -ENXIO;
>>  }
>>  
>> +static int vgic_its_flush_cte(struct vgic_its *its,
>> +			      struct its_collection *collection, gpa_t gpa)
> 
> Given that the pendent of this function is name ..._restore_..., should
> this be called ..._save_... ?
> 
>> +{
>> +	u64 val;
>> +	int ret;
>> +
>> +	val = ((u64)1 << 63 | ((u64)collection->target_addr << 16) |
>> +	       collection->collection_id);
> 
> Please provide some #defines that describe the encoding. This will be
> specially useful if we need to export this to userspace (KVM/TCG
> interoperability?).
> 
>> +	val = cpu_to_le64(val);
>> +	ret = kvm_write_guest(its->dev->kvm, gpa, &val, 8);
>> +	return ret;
>> +}
>> +
>> +static int vgic_its_restore_cte(struct vgic_its *its, gpa_t gpa, bool *valid)
>> +{
>> +	struct its_collection *collection;
>> +	u32 target_addr;
>> +	u32 coll_id;
>> +	u64 val;
>> +	int ret;
>> +
>> +	*valid = false;
>> +
>> +	ret = kvm_read_guest(its->dev->kvm, gpa, &val, 8);
>> +	if (ret)
>> +		return ret;
>> +	val = le64_to_cpu(val);
>> +	*valid = val & BIT_ULL(63);
>> +
>> +	if (!*valid)
>> +		return 0;
>> +
>> +	target_addr = (u32)(val >> 16);
> 
> u32?
At the moment its_collection.target_addr is u32 and corresponds to the
PE number. Only GITS_TYPER.PTA = 0 is supported.

Or do I miss something?

Thanks

Eric
> 
>> +	coll_id = val & 0xFFFF;
> 
> Same comment about the various shifts/masks.
> 
>> +
>> +	collection = find_collection(its, coll_id);
>> +	if (collection)
>> +		return -EEXIST;
>> +	ret = vgic_its_alloc_collection(its, &collection, coll_id);
>> +	if (ret)
>> +		return ret;
>> +	collection->target_addr = target_addr;
>> +	return 0;
>> +}
>> +
>>  /**
>>   * vgic_its_flush_collection_table - flush the collection table into
>>   * guest RAM
>>   */
>>  static int vgic_its_flush_collection_table(struct vgic_its *its)
>>  {
>> -	return -ENXIO;
>> +	struct its_collection *collection;
>> +	u64 val;
>> +	gpa_t gpa;
>> +	size_t max_size, filled = 0;
>> +	int ret;
>> +
>> +	gpa = BASER_ADDRESS(its->baser_coll_table);
>> +	if (!gpa)
>> +		return 0;
>> +
>> +	max_size = GITS_BASER_NR_PAGES(its->baser_coll_table) * SZ_64K;
>> +
>> +	list_for_each_entry(collection, &its->collection_list, coll_list) {
>> +		if (filled == max_size)
>> +			return -ENOSPC;
>> +		ret = vgic_its_flush_cte(its, collection, gpa);
>> +		if (ret)
>> +			return ret;
>> +		gpa += 8;
>> +		filled += 8;
> 
> This "8" should be extracted from the BASER register itself (Entry_Size).
> 
>> +	}
>> +
>> +	if (filled == max_size)
>> +		return 0;
>> +
>> +	/*
>> +	 * table is not fully filled, add a last dummy element
>> +	 * with valid bit unset
>> +	 */
>> +	val = 0;
>> +	ret = kvm_write_guest(its->dev->kvm, gpa, &val, 8);
>> +	return ret;
>>  }
>>  
>>  /**
>> @@ -1844,7 +1920,26 @@ static int vgic_its_flush_collection_table(struct vgic_its *its)
>>   */
>>  static int vgic_its_restore_collection_table(struct vgic_its *its)
>>  {
>> -	return -ENXIO;
>> +	size_t max_size, read = 0;
>> +	gpa_t gpa;
>> +	int ret;
>> +
>> +	gpa = BASER_ADDRESS(its->baser_coll_table);
>> +	if (!gpa)
>> +		return 0;
>> +
>> +	max_size = GITS_BASER_NR_PAGES(its->baser_coll_table) * SZ_64K;
>> +
>> +	while (read < max_size) {
>> +		bool valid;
>> +
>> +		ret = vgic_its_restore_cte(its, gpa, &valid);
>> +		if (!valid || ret)
>> +			break;
>> +		gpa += 8;
>> +		read += 8;
>> +	}
>> +	return ret;
>>  }
>>  
>>  /**
>>
> 
> Thanks,
> 
> 	M.
> 

^ permalink raw reply	[flat|nested] 144+ messages in thread

* [PATCH v4 18/22] KVM: arm64: ITS: Collection table save/restore
@ 2017-04-11  9:57       ` Auger Eric
  0 siblings, 0 replies; 144+ messages in thread
From: Auger Eric @ 2017-04-11  9:57 UTC (permalink / raw)
  To: linux-arm-kernel

Hi Marc,

On 10/04/2017 11:55, Marc Zyngier wrote:
> On 27/03/17 10:31, Eric Auger wrote:
>> The flush path copies the collection entries into guest RAM
>> at the GPA specified in the BASER register. This obviously
>> requires the BASER to be set. The last written element
>> is a dummy collection table entry.
>>
>> We do not index by collection ID as the collection entry
>> can fit into 8 bytes while containing the collection ID.
>>
>> On restore path we re-allocate the collection objects.
>>
>> Signed-off-by: Eric Auger <eric.auger@redhat.com>
>>
>> ---
>>
>> v3 -> v4:
>> - replaced u64 *ptr by gpa_t gpa
>> - check the collection does not exist before allocating it
>>
>> v1 -> v2:
>> - reword commit message and directly use 8 as entry size
>> - no kvm parameter anymore
>> - add helper for flush/restore cte
>> - table size computed here
>> - add le64/cpu conversions
>> ---
>>  virt/kvm/arm/vgic/vgic-its.c | 99 +++++++++++++++++++++++++++++++++++++++++++-
>>  1 file changed, 97 insertions(+), 2 deletions(-)
>>
>> diff --git a/virt/kvm/arm/vgic/vgic-its.c b/virt/kvm/arm/vgic/vgic-its.c
>> index 8eaeba4..df984b6 100644
>> --- a/virt/kvm/arm/vgic/vgic-its.c
>> +++ b/virt/kvm/arm/vgic/vgic-its.c
>> @@ -1828,13 +1828,89 @@ static int vgic_its_restore_device_tables(struct vgic_its *its)
>>  	return -ENXIO;
>>  }
>>  
>> +static int vgic_its_flush_cte(struct vgic_its *its,
>> +			      struct its_collection *collection, gpa_t gpa)
> 
> Given that the pendent of this function is name ..._restore_..., should
> this be called ..._save_... ?
> 
>> +{
>> +	u64 val;
>> +	int ret;
>> +
>> +	val = ((u64)1 << 63 | ((u64)collection->target_addr << 16) |
>> +	       collection->collection_id);
> 
> Please provide some #defines that describe the encoding. This will be
> specially useful if we need to export this to userspace (KVM/TCG
> interoperability?).
> 
>> +	val = cpu_to_le64(val);
>> +	ret = kvm_write_guest(its->dev->kvm, gpa, &val, 8);
>> +	return ret;
>> +}
>> +
>> +static int vgic_its_restore_cte(struct vgic_its *its, gpa_t gpa, bool *valid)
>> +{
>> +	struct its_collection *collection;
>> +	u32 target_addr;
>> +	u32 coll_id;
>> +	u64 val;
>> +	int ret;
>> +
>> +	*valid = false;
>> +
>> +	ret = kvm_read_guest(its->dev->kvm, gpa, &val, 8);
>> +	if (ret)
>> +		return ret;
>> +	val = le64_to_cpu(val);
>> +	*valid = val & BIT_ULL(63);
>> +
>> +	if (!*valid)
>> +		return 0;
>> +
>> +	target_addr = (u32)(val >> 16);
> 
> u32?
At the moment its_collection.target_addr is u32 and corresponds to the
PE number. Only GITS_TYPER.PTA = 0 is supported.

Or do I miss something?

Thanks

Eric
> 
>> +	coll_id = val & 0xFFFF;
> 
> Same comment about the various shifts/masks.
> 
>> +
>> +	collection = find_collection(its, coll_id);
>> +	if (collection)
>> +		return -EEXIST;
>> +	ret = vgic_its_alloc_collection(its, &collection, coll_id);
>> +	if (ret)
>> +		return ret;
>> +	collection->target_addr = target_addr;
>> +	return 0;
>> +}
>> +
>>  /**
>>   * vgic_its_flush_collection_table - flush the collection table into
>>   * guest RAM
>>   */
>>  static int vgic_its_flush_collection_table(struct vgic_its *its)
>>  {
>> -	return -ENXIO;
>> +	struct its_collection *collection;
>> +	u64 val;
>> +	gpa_t gpa;
>> +	size_t max_size, filled = 0;
>> +	int ret;
>> +
>> +	gpa = BASER_ADDRESS(its->baser_coll_table);
>> +	if (!gpa)
>> +		return 0;
>> +
>> +	max_size = GITS_BASER_NR_PAGES(its->baser_coll_table) * SZ_64K;
>> +
>> +	list_for_each_entry(collection, &its->collection_list, coll_list) {
>> +		if (filled == max_size)
>> +			return -ENOSPC;
>> +		ret = vgic_its_flush_cte(its, collection, gpa);
>> +		if (ret)
>> +			return ret;
>> +		gpa += 8;
>> +		filled += 8;
> 
> This "8" should be extracted from the BASER register itself (Entry_Size).
> 
>> +	}
>> +
>> +	if (filled == max_size)
>> +		return 0;
>> +
>> +	/*
>> +	 * table is not fully filled, add a last dummy element
>> +	 * with valid bit unset
>> +	 */
>> +	val = 0;
>> +	ret = kvm_write_guest(its->dev->kvm, gpa, &val, 8);
>> +	return ret;
>>  }
>>  
>>  /**
>> @@ -1844,7 +1920,26 @@ static int vgic_its_flush_collection_table(struct vgic_its *its)
>>   */
>>  static int vgic_its_restore_collection_table(struct vgic_its *its)
>>  {
>> -	return -ENXIO;
>> +	size_t max_size, read = 0;
>> +	gpa_t gpa;
>> +	int ret;
>> +
>> +	gpa = BASER_ADDRESS(its->baser_coll_table);
>> +	if (!gpa)
>> +		return 0;
>> +
>> +	max_size = GITS_BASER_NR_PAGES(its->baser_coll_table) * SZ_64K;
>> +
>> +	while (read < max_size) {
>> +		bool valid;
>> +
>> +		ret = vgic_its_restore_cte(its, gpa, &valid);
>> +		if (!valid || ret)
>> +			break;
>> +		gpa += 8;
>> +		read += 8;
>> +	}
>> +	return ret;
>>  }
>>  
>>  /**
>>
> 
> Thanks,
> 
> 	M.
> 

^ permalink raw reply	[flat|nested] 144+ messages in thread

* Re: [PATCH v4 18/22] KVM: arm64: ITS: Collection table save/restore
  2017-04-11  9:57       ` Auger Eric
@ 2017-04-11 10:03         ` Marc Zyngier
  -1 siblings, 0 replies; 144+ messages in thread
From: Marc Zyngier @ 2017-04-11 10:03 UTC (permalink / raw)
  To: Auger Eric, eric.auger.pro, christoffer.dall, andre.przywara,
	vijayak, Vijaya.Kumar, peter.maydell, linux-arm-kernel, kvmarm,
	kvm
  Cc: Prasun.Kapoor, quintela, dgilbert, pbonzini

On 11/04/17 10:57, Auger Eric wrote:
> Hi Marc,
> 
> On 10/04/2017 11:55, Marc Zyngier wrote:
>> On 27/03/17 10:31, Eric Auger wrote:
>>> The flush path copies the collection entries into guest RAM
>>> at the GPA specified in the BASER register. This obviously
>>> requires the BASER to be set. The last written element
>>> is a dummy collection table entry.
>>>
>>> We do not index by collection ID as the collection entry
>>> can fit into 8 bytes while containing the collection ID.
>>>
>>> On restore path we re-allocate the collection objects.
>>>
>>> Signed-off-by: Eric Auger <eric.auger@redhat.com>
>>>
>>> ---
>>>
>>> v3 -> v4:
>>> - replaced u64 *ptr by gpa_t gpa
>>> - check the collection does not exist before allocating it
>>>
>>> v1 -> v2:
>>> - reword commit message and directly use 8 as entry size
>>> - no kvm parameter anymore
>>> - add helper for flush/restore cte
>>> - table size computed here
>>> - add le64/cpu conversions
>>> ---
>>>  virt/kvm/arm/vgic/vgic-its.c | 99 +++++++++++++++++++++++++++++++++++++++++++-
>>>  1 file changed, 97 insertions(+), 2 deletions(-)
>>>
>>> diff --git a/virt/kvm/arm/vgic/vgic-its.c b/virt/kvm/arm/vgic/vgic-its.c
>>> index 8eaeba4..df984b6 100644
>>> --- a/virt/kvm/arm/vgic/vgic-its.c
>>> +++ b/virt/kvm/arm/vgic/vgic-its.c
>>> @@ -1828,13 +1828,89 @@ static int vgic_its_restore_device_tables(struct vgic_its *its)
>>>  	return -ENXIO;
>>>  }
>>>  
>>> +static int vgic_its_flush_cte(struct vgic_its *its,
>>> +			      struct its_collection *collection, gpa_t gpa)
>>
>> Given that the pendent of this function is name ..._restore_..., should
>> this be called ..._save_... ?
>>
>>> +{
>>> +	u64 val;
>>> +	int ret;
>>> +
>>> +	val = ((u64)1 << 63 | ((u64)collection->target_addr << 16) |
>>> +	       collection->collection_id);
>>
>> Please provide some #defines that describe the encoding. This will be
>> specially useful if we need to export this to userspace (KVM/TCG
>> interoperability?).
>>
>>> +	val = cpu_to_le64(val);
>>> +	ret = kvm_write_guest(its->dev->kvm, gpa, &val, 8);
>>> +	return ret;
>>> +}
>>> +
>>> +static int vgic_its_restore_cte(struct vgic_its *its, gpa_t gpa, bool *valid)
>>> +{
>>> +	struct its_collection *collection;
>>> +	u32 target_addr;
>>> +	u32 coll_id;
>>> +	u64 val;
>>> +	int ret;
>>> +
>>> +	*valid = false;
>>> +
>>> +	ret = kvm_read_guest(its->dev->kvm, gpa, &val, 8);
>>> +	if (ret)
>>> +		return ret;
>>> +	val = le64_to_cpu(val);
>>> +	*valid = val & BIT_ULL(63);
>>> +
>>> +	if (!*valid)
>>> +		return 0;
>>> +
>>> +	target_addr = (u32)(val >> 16);
>>
>> u32?
> At the moment its_collection.target_addr is u32 and corresponds to the
> PE number. Only GITS_TYPER.PTA = 0 is supported.
> 
> Or do I miss something?

No, you're right. I'm getting confused between the model I'm working
with and the ITS emulation... Ignore me.

Thanks,

	M.
-- 
Jazz is not dead. It just smells funny...

^ permalink raw reply	[flat|nested] 144+ messages in thread

* [PATCH v4 18/22] KVM: arm64: ITS: Collection table save/restore
@ 2017-04-11 10:03         ` Marc Zyngier
  0 siblings, 0 replies; 144+ messages in thread
From: Marc Zyngier @ 2017-04-11 10:03 UTC (permalink / raw)
  To: linux-arm-kernel

On 11/04/17 10:57, Auger Eric wrote:
> Hi Marc,
> 
> On 10/04/2017 11:55, Marc Zyngier wrote:
>> On 27/03/17 10:31, Eric Auger wrote:
>>> The flush path copies the collection entries into guest RAM
>>> at the GPA specified in the BASER register. This obviously
>>> requires the BASER to be set. The last written element
>>> is a dummy collection table entry.
>>>
>>> We do not index by collection ID as the collection entry
>>> can fit into 8 bytes while containing the collection ID.
>>>
>>> On restore path we re-allocate the collection objects.
>>>
>>> Signed-off-by: Eric Auger <eric.auger@redhat.com>
>>>
>>> ---
>>>
>>> v3 -> v4:
>>> - replaced u64 *ptr by gpa_t gpa
>>> - check the collection does not exist before allocating it
>>>
>>> v1 -> v2:
>>> - reword commit message and directly use 8 as entry size
>>> - no kvm parameter anymore
>>> - add helper for flush/restore cte
>>> - table size computed here
>>> - add le64/cpu conversions
>>> ---
>>>  virt/kvm/arm/vgic/vgic-its.c | 99 +++++++++++++++++++++++++++++++++++++++++++-
>>>  1 file changed, 97 insertions(+), 2 deletions(-)
>>>
>>> diff --git a/virt/kvm/arm/vgic/vgic-its.c b/virt/kvm/arm/vgic/vgic-its.c
>>> index 8eaeba4..df984b6 100644
>>> --- a/virt/kvm/arm/vgic/vgic-its.c
>>> +++ b/virt/kvm/arm/vgic/vgic-its.c
>>> @@ -1828,13 +1828,89 @@ static int vgic_its_restore_device_tables(struct vgic_its *its)
>>>  	return -ENXIO;
>>>  }
>>>  
>>> +static int vgic_its_flush_cte(struct vgic_its *its,
>>> +			      struct its_collection *collection, gpa_t gpa)
>>
>> Given that the pendent of this function is name ..._restore_..., should
>> this be called ..._save_... ?
>>
>>> +{
>>> +	u64 val;
>>> +	int ret;
>>> +
>>> +	val = ((u64)1 << 63 | ((u64)collection->target_addr << 16) |
>>> +	       collection->collection_id);
>>
>> Please provide some #defines that describe the encoding. This will be
>> specially useful if we need to export this to userspace (KVM/TCG
>> interoperability?).
>>
>>> +	val = cpu_to_le64(val);
>>> +	ret = kvm_write_guest(its->dev->kvm, gpa, &val, 8);
>>> +	return ret;
>>> +}
>>> +
>>> +static int vgic_its_restore_cte(struct vgic_its *its, gpa_t gpa, bool *valid)
>>> +{
>>> +	struct its_collection *collection;
>>> +	u32 target_addr;
>>> +	u32 coll_id;
>>> +	u64 val;
>>> +	int ret;
>>> +
>>> +	*valid = false;
>>> +
>>> +	ret = kvm_read_guest(its->dev->kvm, gpa, &val, 8);
>>> +	if (ret)
>>> +		return ret;
>>> +	val = le64_to_cpu(val);
>>> +	*valid = val & BIT_ULL(63);
>>> +
>>> +	if (!*valid)
>>> +		return 0;
>>> +
>>> +	target_addr = (u32)(val >> 16);
>>
>> u32?
> At the moment its_collection.target_addr is u32 and corresponds to the
> PE number. Only GITS_TYPER.PTA = 0 is supported.
> 
> Or do I miss something?

No, you're right. I'm getting confused between the model I'm working
with and the ITS emulation... Ignore me.

Thanks,

	M.
-- 
Jazz is not dead. It just smells funny...

^ permalink raw reply	[flat|nested] 144+ messages in thread

* Re: [PATCH v4 08/22] KVM: arm64: ITS: Implement vgic_mmio_uaccess_write_its_iidr
  2017-04-10 15:17           ` Auger Eric
@ 2017-04-11 10:05             ` Marc Zyngier
  -1 siblings, 0 replies; 144+ messages in thread
From: Marc Zyngier @ 2017-04-11 10:05 UTC (permalink / raw)
  To: Auger Eric
  Cc: kvm, Prasun.Kapoor, vijayak, andre.przywara, quintela, dgilbert,
	Vijaya.Kumar, linux-arm-kernel, pbonzini, kvmarm, eric.auger.pro

On 10/04/17 16:17, Auger Eric wrote:
> Hi Marc,
> 
> On 10/04/2017 16:57, Marc Zyngier wrote:
>> On 10/04/17 15:32, Auger Eric wrote:
>>> Hi Marc,
>>>
>>> On 08/04/2017 12:42, Marc Zyngier wrote:
>>>> On Mon, Mar 27 2017 at 10:30:58 AM, Eric Auger <eric.auger@redhat.com> wrote:
>>>>> The GITS_IIDR revision field is used to encode the version of the
>>>>> table layout (ABI). So we need to restore it to check the table
>>>>> layout to be restored is compatible with the destination vITS.
>>>>>
>>>>> The user selected revision is stored in the user_revision field.
>>>>> It will be compared against the REV num at table restoration time.
>>>>
>>>> Why isn't it sufficient to keep it GITS_IIDR RO and let userspace find
>>>> out about the ABI revision that the kernel understands?
>>>>
>>>> Or are we planning on supporting multiple ABIs in the kernel?
>>> Yes as discussed with Peter, the plan is to allow several ABIs. So the
>>> userspace informs the destination about the ABI revision of the stored
>>> tables (contained by the GITS_IIDR). If the destination KVM does not
>>> support this ABI revision, table restore will fail.
>>>  If so, do
>>>> we have a deprecation policy/plan? I don't mind either way, but it would
>>>> be good to document it...
>>>>
>>>> Maybe it is documented already and I missed it (which is perfectly
>>>> possible!).
>>> Well this is partly documented in
>>> Documentation/virtual/kvm/devices/arm-vgic-its.txt. No plan to
>>> deprecate. migration from KVM supporting v1 to KVM supporting V2 would
>>> be possible but not the contrary.
>>>
>>> Does it make sense?
>>
>> Sort of. Say you have three systems: A and C, which only supports v1; B,
>> which supports v1 and v2. Let's say you migrate from A to B, and from B
>> to C. Is B mandated to be able to export the tables as v1 and v2? Or can
>> it restrict what it can export?
> At the moment migration from B to C will fail because source ABI rev =
> v2 > destination support ABI = v1.
> 
> A (v1) -> B (v1 & v2): migration OK
> B (v1 & v2) -> C (v1): migration NOK

So what does IIDR report on B once the A->B migration has taken place?
Does it report v2?

Thanks,

	M.
-- 
Jazz is not dead. It just smells funny...

^ permalink raw reply	[flat|nested] 144+ messages in thread

* [PATCH v4 08/22] KVM: arm64: ITS: Implement vgic_mmio_uaccess_write_its_iidr
@ 2017-04-11 10:05             ` Marc Zyngier
  0 siblings, 0 replies; 144+ messages in thread
From: Marc Zyngier @ 2017-04-11 10:05 UTC (permalink / raw)
  To: linux-arm-kernel

On 10/04/17 16:17, Auger Eric wrote:
> Hi Marc,
> 
> On 10/04/2017 16:57, Marc Zyngier wrote:
>> On 10/04/17 15:32, Auger Eric wrote:
>>> Hi Marc,
>>>
>>> On 08/04/2017 12:42, Marc Zyngier wrote:
>>>> On Mon, Mar 27 2017 at 10:30:58 AM, Eric Auger <eric.auger@redhat.com> wrote:
>>>>> The GITS_IIDR revision field is used to encode the version of the
>>>>> table layout (ABI). So we need to restore it to check the table
>>>>> layout to be restored is compatible with the destination vITS.
>>>>>
>>>>> The user selected revision is stored in the user_revision field.
>>>>> It will be compared against the REV num at table restoration time.
>>>>
>>>> Why isn't it sufficient to keep it GITS_IIDR RO and let userspace find
>>>> out about the ABI revision that the kernel understands?
>>>>
>>>> Or are we planning on supporting multiple ABIs in the kernel?
>>> Yes as discussed with Peter, the plan is to allow several ABIs. So the
>>> userspace informs the destination about the ABI revision of the stored
>>> tables (contained by the GITS_IIDR). If the destination KVM does not
>>> support this ABI revision, table restore will fail.
>>>  If so, do
>>>> we have a deprecation policy/plan? I don't mind either way, but it would
>>>> be good to document it...
>>>>
>>>> Maybe it is documented already and I missed it (which is perfectly
>>>> possible!).
>>> Well this is partly documented in
>>> Documentation/virtual/kvm/devices/arm-vgic-its.txt. No plan to
>>> deprecate. migration from KVM supporting v1 to KVM supporting V2 would
>>> be possible but not the contrary.
>>>
>>> Does it make sense?
>>
>> Sort of. Say you have three systems: A and C, which only supports v1; B,
>> which supports v1 and v2. Let's say you migrate from A to B, and from B
>> to C. Is B mandated to be able to export the tables as v1 and v2? Or can
>> it restrict what it can export?
> At the moment migration from B to C will fail because source ABI rev =
> v2 > destination support ABI = v1.
> 
> A (v1) -> B (v1 & v2): migration OK
> B (v1 & v2) -> C (v1): migration NOK

So what does IIDR report on B once the A->B migration has taken place?
Does it report v2?

Thanks,

	M.
-- 
Jazz is not dead. It just smells funny...

^ permalink raw reply	[flat|nested] 144+ messages in thread

* Re: [PATCH v4 08/22] KVM: arm64: ITS: Implement vgic_mmio_uaccess_write_its_iidr
  2017-04-11 10:05             ` Marc Zyngier
@ 2017-04-11 10:08               ` Auger Eric
  -1 siblings, 0 replies; 144+ messages in thread
From: Auger Eric @ 2017-04-11 10:08 UTC (permalink / raw)
  To: Marc Zyngier
  Cc: kvm, Prasun.Kapoor, vijayak, andre.przywara, quintela, dgilbert,
	Vijaya.Kumar, linux-arm-kernel, pbonzini, kvmarm, eric.auger.pro

Marc,

On 11/04/2017 12:05, Marc Zyngier wrote:
> On 10/04/17 16:17, Auger Eric wrote:
>> Hi Marc,
>>
>> On 10/04/2017 16:57, Marc Zyngier wrote:
>>> On 10/04/17 15:32, Auger Eric wrote:
>>>> Hi Marc,
>>>>
>>>> On 08/04/2017 12:42, Marc Zyngier wrote:
>>>>> On Mon, Mar 27 2017 at 10:30:58 AM, Eric Auger <eric.auger@redhat.com> wrote:
>>>>>> The GITS_IIDR revision field is used to encode the version of the
>>>>>> table layout (ABI). So we need to restore it to check the table
>>>>>> layout to be restored is compatible with the destination vITS.
>>>>>>
>>>>>> The user selected revision is stored in the user_revision field.
>>>>>> It will be compared against the REV num at table restoration time.
>>>>>
>>>>> Why isn't it sufficient to keep it GITS_IIDR RO and let userspace find
>>>>> out about the ABI revision that the kernel understands?
>>>>>
>>>>> Or are we planning on supporting multiple ABIs in the kernel?
>>>> Yes as discussed with Peter, the plan is to allow several ABIs. So the
>>>> userspace informs the destination about the ABI revision of the stored
>>>> tables (contained by the GITS_IIDR). If the destination KVM does not
>>>> support this ABI revision, table restore will fail.
>>>>  If so, do
>>>>> we have a deprecation policy/plan? I don't mind either way, but it would
>>>>> be good to document it...
>>>>>
>>>>> Maybe it is documented already and I missed it (which is perfectly
>>>>> possible!).
>>>> Well this is partly documented in
>>>> Documentation/virtual/kvm/devices/arm-vgic-its.txt. No plan to
>>>> deprecate. migration from KVM supporting v1 to KVM supporting V2 would
>>>> be possible but not the contrary.
>>>>
>>>> Does it make sense?
>>>
>>> Sort of. Say you have three systems: A and C, which only supports v1; B,
>>> which supports v1 and v2. Let's say you migrate from A to B, and from B
>>> to C. Is B mandated to be able to export the tables as v1 and v2? Or can
>>> it restrict what it can export?
>> At the moment migration from B to C will fail because source ABI rev =
>> v2 > destination support ABI = v1.
>>
>> A (v1) -> B (v1 & v2): migration OK
>> B (v1 & v2) -> C (v1): migration NOK
> 
> So what does IIDR report on B once the A->B migration has taken place?
> Does it report v2?

yes that was the plan

Thanks

Eric
> 
> Thanks,
> 
> 	M.
> 

^ permalink raw reply	[flat|nested] 144+ messages in thread

* [PATCH v4 08/22] KVM: arm64: ITS: Implement vgic_mmio_uaccess_write_its_iidr
@ 2017-04-11 10:08               ` Auger Eric
  0 siblings, 0 replies; 144+ messages in thread
From: Auger Eric @ 2017-04-11 10:08 UTC (permalink / raw)
  To: linux-arm-kernel

Marc,

On 11/04/2017 12:05, Marc Zyngier wrote:
> On 10/04/17 16:17, Auger Eric wrote:
>> Hi Marc,
>>
>> On 10/04/2017 16:57, Marc Zyngier wrote:
>>> On 10/04/17 15:32, Auger Eric wrote:
>>>> Hi Marc,
>>>>
>>>> On 08/04/2017 12:42, Marc Zyngier wrote:
>>>>> On Mon, Mar 27 2017 at 10:30:58 AM, Eric Auger <eric.auger@redhat.com> wrote:
>>>>>> The GITS_IIDR revision field is used to encode the version of the
>>>>>> table layout (ABI). So we need to restore it to check the table
>>>>>> layout to be restored is compatible with the destination vITS.
>>>>>>
>>>>>> The user selected revision is stored in the user_revision field.
>>>>>> It will be compared against the REV num at table restoration time.
>>>>>
>>>>> Why isn't it sufficient to keep it GITS_IIDR RO and let userspace find
>>>>> out about the ABI revision that the kernel understands?
>>>>>
>>>>> Or are we planning on supporting multiple ABIs in the kernel?
>>>> Yes as discussed with Peter, the plan is to allow several ABIs. So the
>>>> userspace informs the destination about the ABI revision of the stored
>>>> tables (contained by the GITS_IIDR). If the destination KVM does not
>>>> support this ABI revision, table restore will fail.
>>>>  If so, do
>>>>> we have a deprecation policy/plan? I don't mind either way, but it would
>>>>> be good to document it...
>>>>>
>>>>> Maybe it is documented already and I missed it (which is perfectly
>>>>> possible!).
>>>> Well this is partly documented in
>>>> Documentation/virtual/kvm/devices/arm-vgic-its.txt. No plan to
>>>> deprecate. migration from KVM supporting v1 to KVM supporting V2 would
>>>> be possible but not the contrary.
>>>>
>>>> Does it make sense?
>>>
>>> Sort of. Say you have three systems: A and C, which only supports v1; B,
>>> which supports v1 and v2. Let's say you migrate from A to B, and from B
>>> to C. Is B mandated to be able to export the tables as v1 and v2? Or can
>>> it restrict what it can export?
>> At the moment migration from B to C will fail because source ABI rev =
>> v2 > destination support ABI = v1.
>>
>> A (v1) -> B (v1 & v2): migration OK
>> B (v1 & v2) -> C (v1): migration NOK
> 
> So what does IIDR report on B once the A->B migration has taken place?
> Does it report v2?

yes that was the plan

Thanks

Eric
> 
> Thanks,
> 
> 	M.
> 

^ permalink raw reply	[flat|nested] 144+ messages in thread

* Re: [PATCH v4 08/22] KVM: arm64: ITS: Implement vgic_mmio_uaccess_write_its_iidr
  2017-04-11 10:08               ` Auger Eric
@ 2017-04-11 10:16                 ` Peter Maydell
  -1 siblings, 0 replies; 144+ messages in thread
From: Peter Maydell @ 2017-04-11 10:16 UTC (permalink / raw)
  To: Auger Eric
  Cc: prasun.kapoor, kvm-devel, Juan Quintela, Marc Zyngier,
	Andre Przywara, Dr. David Alan Gilbert, Kumar, Vijaya,
	Vijaya Kumar K, arm-mail-list, Paolo Bonzini, kvmarm,
	eric.auger.pro

On 11 April 2017 at 11:08, Auger Eric <eric.auger@redhat.com> wrote:
> On 11/04/2017 12:05, Marc Zyngier wrote:
>> On 10/04/17 16:17, Auger Eric wrote:
>>> A (v1) -> B (v1 & v2): migration OK
>>> B (v1 & v2) -> C (v1): migration NOK
>>
>> So what does IIDR report on B once the A->B migration has taken place?
>> Does it report v2?
>
> yes that was the plan

Hmm, the IIDR value shouldn't change across a migration I think.
It's guest visible so the guest should see it still the same
value even after migration.

thanks
-- PMM

^ permalink raw reply	[flat|nested] 144+ messages in thread

* [PATCH v4 08/22] KVM: arm64: ITS: Implement vgic_mmio_uaccess_write_its_iidr
@ 2017-04-11 10:16                 ` Peter Maydell
  0 siblings, 0 replies; 144+ messages in thread
From: Peter Maydell @ 2017-04-11 10:16 UTC (permalink / raw)
  To: linux-arm-kernel

On 11 April 2017 at 11:08, Auger Eric <eric.auger@redhat.com> wrote:
> On 11/04/2017 12:05, Marc Zyngier wrote:
>> On 10/04/17 16:17, Auger Eric wrote:
>>> A (v1) -> B (v1 & v2): migration OK
>>> B (v1 & v2) -> C (v1): migration NOK
>>
>> So what does IIDR report on B once the A->B migration has taken place?
>> Does it report v2?
>
> yes that was the plan

Hmm, the IIDR value shouldn't change across a migration I think.
It's guest visible so the guest should see it still the same
value even after migration.

thanks
-- PMM

^ permalink raw reply	[flat|nested] 144+ messages in thread

* Re: [PATCH v4 20/22] KVM: arm64: ITS: ITT flush and restore
  2017-04-10 12:39     ` Marc Zyngier
@ 2017-04-11 10:19       ` Auger Eric
  -1 siblings, 0 replies; 144+ messages in thread
From: Auger Eric @ 2017-04-11 10:19 UTC (permalink / raw)
  To: Marc Zyngier, eric.auger.pro, christoffer.dall, andre.przywara,
	vijayak, Vijaya.Kumar, peter.maydell, linux-arm-kernel, kvmarm,
	kvm
  Cc: Prasun.Kapoor, quintela, dgilbert, pbonzini

Hi Marc,
On 10/04/2017 14:39, Marc Zyngier wrote:
> On 27/03/17 10:31, Eric Auger wrote:
>> Introduce routines to flush and restore device ITT and their
>> interrupt table entries (ITE).
>>
>> The routines will be called on device table flush and
>> restore. They will become static in subsequent patches.
>>
>> Signed-off-by: Eric Auger <eric.auger@redhat.com>
>>
>> ---
>>
>> v3 -> v4:
>> - lookup_table and compute_next_eventid_offset become static in this
>>   patch
>> - remove static along with vgic_its_flush/restore_itt to avoid
>>   compilation warnings
>> - next field only computed with a shift (mask removed)
>> - handle the case where the last element has not been found
>>
>> v2 -> v3:
>> - add return 0 in vgic_its_restore_ite (was in subsequent patch)
>>
>> v2: creation
>> ---
>>  virt/kvm/arm/vgic/vgic-its.c | 107 +++++++++++++++++++++++++++++++++++++++++--
>>  1 file changed, 104 insertions(+), 3 deletions(-)
>>
>> diff --git a/virt/kvm/arm/vgic/vgic-its.c b/virt/kvm/arm/vgic/vgic-its.c
>> index b907e3c..02c0694 100644
>> --- a/virt/kvm/arm/vgic/vgic-its.c
>> +++ b/virt/kvm/arm/vgic/vgic-its.c
>> @@ -1707,7 +1707,7 @@ u32 compute_next_devid_offset(struct list_head *h, struct its_device *dev)
>>  	return min_t(u32, next_offset, VITS_DTE_MAX_DEVID_OFFSET);
>>  }
>>  
>> -u32 compute_next_eventid_offset(struct list_head *h, struct its_ite *ite)
>> +static u32 compute_next_eventid_offset(struct list_head *h, struct its_ite *ite)
>>  {
>>  	struct list_head *e = &ite->ite_list;
>>  	struct its_ite *next;
>> @@ -1749,8 +1749,8 @@ typedef int (*entry_fn_t)(struct vgic_its *its, u32 id, void *addr,
>>   *
>>   * Return: < 0 on error, 1 if last element identified, 0 otherwise
>>   */
>> -int lookup_table(struct vgic_its *its, gpa_t base, int size, int esz,
>> -		 int start_id, entry_fn_t fn, void *opaque)
>> +static int lookup_table(struct vgic_its *its, gpa_t base, int size, int esz,
>> +			int start_id, entry_fn_t fn, void *opaque)
>>  {
>>  	gpa_t gpa = base, top = base + size - 1;
>>  	unsigned long len = size;
>> @@ -1815,6 +1815,107 @@ static int vgic_its_restore_pending_tables(struct kvm *kvm)
>>  	return -ENXIO;
>>  }
>>  
>> +static int vgic_its_flush_ite(struct vgic_its *its, struct its_device *dev,
>> +			      struct its_ite *ite, gpa_t gpa)
>> +{
>> +	struct kvm *kvm = its->dev->kvm;
>> +	u32 next_offset;
>> +	u64 val;
>> +
>> +	next_offset = compute_next_eventid_offset(&dev->itt_head, ite);
>> +	val = ((u64)next_offset << 48) | ((u64)ite->lpi << 16) |
>> +		ite->collection->collection_id;
> 
> Same remark as before concerning the #define-ing of the encoding and the
> name of the function.
> 
>> +	val = cpu_to_le64(val);
>> +	return kvm_write_guest(kvm, gpa, &val, VITS_ESZ);
>> +}
>> +
>> +/**
>> + * vgic_its_restore_ite - restore an interrupt translation entry
>> + * @event_id: id used for indexing
>> + * @ptr: kernel VA where the 8 byte ITE is located
>> + * @opaque: pointer to the its_device
>> + * @next: id offset to the next entry
>> + */
>> +static int vgic_its_restore_ite(struct vgic_its *its, u32 event_id,
>> +				void *ptr, void *opaque, u32 *next)
>> +{
>> +	struct its_device *dev = (struct its_device *)opaque;
>> +	struct its_collection *collection;
>> +	struct kvm *kvm = its->dev->kvm;
>> +	u64 val, *p = (u64 *)ptr;
>> +	struct vgic_irq *irq;
>> +	u32 coll_id, lpi_id;
>> +	struct its_ite *ite;
>> +	int ret;
>> +
>> +	val = *p;
>> +	*next = 1;
>> +
>> +	val = le64_to_cpu(val);
>> +
>> +	coll_id = val & GENMASK_ULL(15, 0);
>> +	lpi_id = (val & GENMASK_ULL(47, 16)) >> 16;
>> +
>> +	if (!lpi_id)
>> +		return 0;
>> +
>> +	*next = val >> 48;
>> +
>> +	collection = find_collection(its, coll_id);
>> +	if (!collection)
>> +		return -EINVAL;
>> +
>> +	ret = vgic_its_alloc_ite(dev, &ite, collection,
>> +				  lpi_id, event_id);
>> +	if (ret)
>> +		return ret;
>> +
>> +	irq = vgic_add_lpi(kvm, lpi_id);
>> +	if (IS_ERR(irq))
>> +		return PTR_ERR(irq);
>> +	ite->irq = irq;
>> +
>> +	/* restore the configuration of the LPI */
>> +	ret = update_lpi_config(kvm, irq, NULL);
>> +	if (ret)
>> +		return ret;
>> +
>> +	update_affinity_ite(kvm, ite);
>> +	return 0;
>> +}
>> +
>> +int vgic_its_flush_itt(struct vgic_its *its, struct its_device *device)
>> +{
>> +	gpa_t base = device->itt_addr;
>> +	struct its_ite *ite;
>> +	int ret;
>> +
>> +	list_for_each_entry(ite, &device->itt_head, ite_list) {
>> +		gpa_t gpa = base + ite->event_id * VITS_ESZ;
>> +
>> +		ret = vgic_its_flush_ite(its, device, ite, gpa);
>> +		if (ret)
>> +			return ret;
>> +	}
>> +	return 0;
>> +}
>> +
>> +int vgic_its_restore_itt(struct vgic_its *its, struct its_device *dev)
>> +{
>> +	size_t max_size = BIT_ULL(dev->nb_eventid_bits) * VITS_ESZ;
>> +	gpa_t base = dev->itt_addr;
>> +	int ret;
>> +
>> +	ret =  lookup_table(its, base, max_size, VITS_ESZ, 0,
>> +			    vgic_its_restore_ite, dev);
>> +
>> +	if (ret < 0)
>> +		return ret;
>> +
>> +	/* if the last element has not been found we are in trouble */
>> +	return ret ? 0 : -EINVAL;
> 
> This makes me wonder. Can't lookup_table perform that check on its own
> and always return an error when something went wrong?
No I don't think this is possible due to the fact we have 2 levels of
tables for the device tables. If a second level table lookup does not
find the last entry, this is not an issue.

Thanks

Eric
> 
>> +}
>> +
>>  /**
>>   * vgic_its_flush_device_tables - flush the device table and all ITT
>>   * into guest RAM
>>
> 
> Thanks,
> 
> 	M.
> 

^ permalink raw reply	[flat|nested] 144+ messages in thread

* [PATCH v4 20/22] KVM: arm64: ITS: ITT flush and restore
@ 2017-04-11 10:19       ` Auger Eric
  0 siblings, 0 replies; 144+ messages in thread
From: Auger Eric @ 2017-04-11 10:19 UTC (permalink / raw)
  To: linux-arm-kernel

Hi Marc,
On 10/04/2017 14:39, Marc Zyngier wrote:
> On 27/03/17 10:31, Eric Auger wrote:
>> Introduce routines to flush and restore device ITT and their
>> interrupt table entries (ITE).
>>
>> The routines will be called on device table flush and
>> restore. They will become static in subsequent patches.
>>
>> Signed-off-by: Eric Auger <eric.auger@redhat.com>
>>
>> ---
>>
>> v3 -> v4:
>> - lookup_table and compute_next_eventid_offset become static in this
>>   patch
>> - remove static along with vgic_its_flush/restore_itt to avoid
>>   compilation warnings
>> - next field only computed with a shift (mask removed)
>> - handle the case where the last element has not been found
>>
>> v2 -> v3:
>> - add return 0 in vgic_its_restore_ite (was in subsequent patch)
>>
>> v2: creation
>> ---
>>  virt/kvm/arm/vgic/vgic-its.c | 107 +++++++++++++++++++++++++++++++++++++++++--
>>  1 file changed, 104 insertions(+), 3 deletions(-)
>>
>> diff --git a/virt/kvm/arm/vgic/vgic-its.c b/virt/kvm/arm/vgic/vgic-its.c
>> index b907e3c..02c0694 100644
>> --- a/virt/kvm/arm/vgic/vgic-its.c
>> +++ b/virt/kvm/arm/vgic/vgic-its.c
>> @@ -1707,7 +1707,7 @@ u32 compute_next_devid_offset(struct list_head *h, struct its_device *dev)
>>  	return min_t(u32, next_offset, VITS_DTE_MAX_DEVID_OFFSET);
>>  }
>>  
>> -u32 compute_next_eventid_offset(struct list_head *h, struct its_ite *ite)
>> +static u32 compute_next_eventid_offset(struct list_head *h, struct its_ite *ite)
>>  {
>>  	struct list_head *e = &ite->ite_list;
>>  	struct its_ite *next;
>> @@ -1749,8 +1749,8 @@ typedef int (*entry_fn_t)(struct vgic_its *its, u32 id, void *addr,
>>   *
>>   * Return: < 0 on error, 1 if last element identified, 0 otherwise
>>   */
>> -int lookup_table(struct vgic_its *its, gpa_t base, int size, int esz,
>> -		 int start_id, entry_fn_t fn, void *opaque)
>> +static int lookup_table(struct vgic_its *its, gpa_t base, int size, int esz,
>> +			int start_id, entry_fn_t fn, void *opaque)
>>  {
>>  	gpa_t gpa = base, top = base + size - 1;
>>  	unsigned long len = size;
>> @@ -1815,6 +1815,107 @@ static int vgic_its_restore_pending_tables(struct kvm *kvm)
>>  	return -ENXIO;
>>  }
>>  
>> +static int vgic_its_flush_ite(struct vgic_its *its, struct its_device *dev,
>> +			      struct its_ite *ite, gpa_t gpa)
>> +{
>> +	struct kvm *kvm = its->dev->kvm;
>> +	u32 next_offset;
>> +	u64 val;
>> +
>> +	next_offset = compute_next_eventid_offset(&dev->itt_head, ite);
>> +	val = ((u64)next_offset << 48) | ((u64)ite->lpi << 16) |
>> +		ite->collection->collection_id;
> 
> Same remark as before concerning the #define-ing of the encoding and the
> name of the function.
> 
>> +	val = cpu_to_le64(val);
>> +	return kvm_write_guest(kvm, gpa, &val, VITS_ESZ);
>> +}
>> +
>> +/**
>> + * vgic_its_restore_ite - restore an interrupt translation entry
>> + * @event_id: id used for indexing
>> + * @ptr: kernel VA where the 8 byte ITE is located
>> + * @opaque: pointer to the its_device
>> + * @next: id offset to the next entry
>> + */
>> +static int vgic_its_restore_ite(struct vgic_its *its, u32 event_id,
>> +				void *ptr, void *opaque, u32 *next)
>> +{
>> +	struct its_device *dev = (struct its_device *)opaque;
>> +	struct its_collection *collection;
>> +	struct kvm *kvm = its->dev->kvm;
>> +	u64 val, *p = (u64 *)ptr;
>> +	struct vgic_irq *irq;
>> +	u32 coll_id, lpi_id;
>> +	struct its_ite *ite;
>> +	int ret;
>> +
>> +	val = *p;
>> +	*next = 1;
>> +
>> +	val = le64_to_cpu(val);
>> +
>> +	coll_id = val & GENMASK_ULL(15, 0);
>> +	lpi_id = (val & GENMASK_ULL(47, 16)) >> 16;
>> +
>> +	if (!lpi_id)
>> +		return 0;
>> +
>> +	*next = val >> 48;
>> +
>> +	collection = find_collection(its, coll_id);
>> +	if (!collection)
>> +		return -EINVAL;
>> +
>> +	ret = vgic_its_alloc_ite(dev, &ite, collection,
>> +				  lpi_id, event_id);
>> +	if (ret)
>> +		return ret;
>> +
>> +	irq = vgic_add_lpi(kvm, lpi_id);
>> +	if (IS_ERR(irq))
>> +		return PTR_ERR(irq);
>> +	ite->irq = irq;
>> +
>> +	/* restore the configuration of the LPI */
>> +	ret = update_lpi_config(kvm, irq, NULL);
>> +	if (ret)
>> +		return ret;
>> +
>> +	update_affinity_ite(kvm, ite);
>> +	return 0;
>> +}
>> +
>> +int vgic_its_flush_itt(struct vgic_its *its, struct its_device *device)
>> +{
>> +	gpa_t base = device->itt_addr;
>> +	struct its_ite *ite;
>> +	int ret;
>> +
>> +	list_for_each_entry(ite, &device->itt_head, ite_list) {
>> +		gpa_t gpa = base + ite->event_id * VITS_ESZ;
>> +
>> +		ret = vgic_its_flush_ite(its, device, ite, gpa);
>> +		if (ret)
>> +			return ret;
>> +	}
>> +	return 0;
>> +}
>> +
>> +int vgic_its_restore_itt(struct vgic_its *its, struct its_device *dev)
>> +{
>> +	size_t max_size = BIT_ULL(dev->nb_eventid_bits) * VITS_ESZ;
>> +	gpa_t base = dev->itt_addr;
>> +	int ret;
>> +
>> +	ret =  lookup_table(its, base, max_size, VITS_ESZ, 0,
>> +			    vgic_its_restore_ite, dev);
>> +
>> +	if (ret < 0)
>> +		return ret;
>> +
>> +	/* if the last element has not been found we are in trouble */
>> +	return ret ? 0 : -EINVAL;
> 
> This makes me wonder. Can't lookup_table perform that check on its own
> and always return an error when something went wrong?
No I don't think this is possible due to the fact we have 2 levels of
tables for the device tables. If a second level table lookup does not
find the last entry, this is not an issue.

Thanks

Eric
> 
>> +}
>> +
>>  /**
>>   * vgic_its_flush_device_tables - flush the device table and all ITT
>>   * into guest RAM
>>
> 
> Thanks,
> 
> 	M.
> 

^ permalink raw reply	[flat|nested] 144+ messages in thread

* Re: [PATCH v4 08/22] KVM: arm64: ITS: Implement vgic_mmio_uaccess_write_its_iidr
  2017-04-11 10:16                 ` Peter Maydell
@ 2017-04-11 10:29                   ` Marc Zyngier
  -1 siblings, 0 replies; 144+ messages in thread
From: Marc Zyngier @ 2017-04-11 10:29 UTC (permalink / raw)
  To: Peter Maydell, Auger Eric
  Cc: prasun.kapoor, kvm-devel, Juan Quintela, Vijaya Kumar K,
	Andre Przywara, Dr. David Alan Gilbert, Kumar, Vijaya,
	arm-mail-list, Paolo Bonzini, kvmarm, eric.auger.pro

On 11/04/17 11:16, Peter Maydell wrote:
> On 11 April 2017 at 11:08, Auger Eric <eric.auger@redhat.com> wrote:
>> On 11/04/2017 12:05, Marc Zyngier wrote:
>>> On 10/04/17 16:17, Auger Eric wrote:
>>>> A (v1) -> B (v1 & v2): migration OK
>>>> B (v1 & v2) -> C (v1): migration NOK
>>>
>>> So what does IIDR report on B once the A->B migration has taken place?
>>> Does it report v2?
>>
>> yes that was the plan
> 
> Hmm, the IIDR value shouldn't change across a migration I think.
> It's guest visible so the guest should see it still the same
> value even after migration.

That's my worry. But we then have a problem when this VM migrates again.
How does userspace find out which ABI to use then?

Thanks,

	M.
-- 
Jazz is not dead. It just smells funny...

^ permalink raw reply	[flat|nested] 144+ messages in thread

* [PATCH v4 08/22] KVM: arm64: ITS: Implement vgic_mmio_uaccess_write_its_iidr
@ 2017-04-11 10:29                   ` Marc Zyngier
  0 siblings, 0 replies; 144+ messages in thread
From: Marc Zyngier @ 2017-04-11 10:29 UTC (permalink / raw)
  To: linux-arm-kernel

On 11/04/17 11:16, Peter Maydell wrote:
> On 11 April 2017 at 11:08, Auger Eric <eric.auger@redhat.com> wrote:
>> On 11/04/2017 12:05, Marc Zyngier wrote:
>>> On 10/04/17 16:17, Auger Eric wrote:
>>>> A (v1) -> B (v1 & v2): migration OK
>>>> B (v1 & v2) -> C (v1): migration NOK
>>>
>>> So what does IIDR report on B once the A->B migration has taken place?
>>> Does it report v2?
>>
>> yes that was the plan
> 
> Hmm, the IIDR value shouldn't change across a migration I think.
> It's guest visible so the guest should see it still the same
> value even after migration.

That's my worry. But we then have a problem when this VM migrates again.
How does userspace find out which ABI to use then?

Thanks,

	M.
-- 
Jazz is not dead. It just smells funny...

^ permalink raw reply	[flat|nested] 144+ messages in thread

* Re: [PATCH v4 08/22] KVM: arm64: ITS: Implement vgic_mmio_uaccess_write_its_iidr
  2017-04-11 10:29                   ` Marc Zyngier
@ 2017-04-11 10:43                     ` Peter Maydell
  -1 siblings, 0 replies; 144+ messages in thread
From: Peter Maydell @ 2017-04-11 10:43 UTC (permalink / raw)
  To: Marc Zyngier
  Cc: prasun.kapoor, kvm-devel, Juan Quintela, Vijaya Kumar K,
	Andre Przywara, Dr. David Alan Gilbert, Kumar, Vijaya,
	arm-mail-list, Paolo Bonzini, kvmarm, eric.auger.pro

On 11 April 2017 at 11:29, Marc Zyngier <marc.zyngier@arm.com> wrote:
> On 11/04/17 11:16, Peter Maydell wrote:
>> On 11 April 2017 at 11:08, Auger Eric <eric.auger@redhat.com> wrote:
>>> On 11/04/2017 12:05, Marc Zyngier wrote:
>>>> On 10/04/17 16:17, Auger Eric wrote:
>>>>> A (v1) -> B (v1 & v2): migration OK
>>>>> B (v1 & v2) -> C (v1): migration NOK
>>>>
>>>> So what does IIDR report on B once the A->B migration has taken place?
>>>> Does it report v2?
>>>
>>> yes that was the plan
>>
>> Hmm, the IIDR value shouldn't change across a migration I think.
>> It's guest visible so the guest should see it still the same
>> value even after migration.
>
> That's my worry. But we then have a problem when this VM migrates again.
> How does userspace find out which ABI to use then?

Userspace shouldn't need to care; the idea of this scheme is
that if the kernel has to change its ABI then the kernel
is what has to deal with the change.

I think that means that if you can read the v1 format on input
you have to output it too, though.

thanks
-- PMM

^ permalink raw reply	[flat|nested] 144+ messages in thread

* [PATCH v4 08/22] KVM: arm64: ITS: Implement vgic_mmio_uaccess_write_its_iidr
@ 2017-04-11 10:43                     ` Peter Maydell
  0 siblings, 0 replies; 144+ messages in thread
From: Peter Maydell @ 2017-04-11 10:43 UTC (permalink / raw)
  To: linux-arm-kernel

On 11 April 2017 at 11:29, Marc Zyngier <marc.zyngier@arm.com> wrote:
> On 11/04/17 11:16, Peter Maydell wrote:
>> On 11 April 2017 at 11:08, Auger Eric <eric.auger@redhat.com> wrote:
>>> On 11/04/2017 12:05, Marc Zyngier wrote:
>>>> On 10/04/17 16:17, Auger Eric wrote:
>>>>> A (v1) -> B (v1 & v2): migration OK
>>>>> B (v1 & v2) -> C (v1): migration NOK
>>>>
>>>> So what does IIDR report on B once the A->B migration has taken place?
>>>> Does it report v2?
>>>
>>> yes that was the plan
>>
>> Hmm, the IIDR value shouldn't change across a migration I think.
>> It's guest visible so the guest should see it still the same
>> value even after migration.
>
> That's my worry. But we then have a problem when this VM migrates again.
> How does userspace find out which ABI to use then?

Userspace shouldn't need to care; the idea of this scheme is
that if the kernel has to change its ABI then the kernel
is what has to deal with the change.

I think that means that if you can read the v1 format on input
you have to output it too, though.

thanks
-- PMM

^ permalink raw reply	[flat|nested] 144+ messages in thread

* Re: [PATCH v4 08/22] KVM: arm64: ITS: Implement vgic_mmio_uaccess_write_its_iidr
  2017-04-11 10:29                   ` Marc Zyngier
@ 2017-04-11 10:56                     ` Auger Eric
  -1 siblings, 0 replies; 144+ messages in thread
From: Auger Eric @ 2017-04-11 10:56 UTC (permalink / raw)
  To: Marc Zyngier, Peter Maydell
  Cc: Andrew Jones, kvm-devel, prasun.kapoor, Vijaya Kumar K,
	Andre Przywara, Juan Quintela, Dr. David Alan Gilbert, Kumar,
	Vijaya, Christoffer Dall, Paolo Bonzini, kvmarm, arm-mail-list,
	eric.auger.pro

Hi,

On 11/04/2017 12:29, Marc Zyngier wrote:
> On 11/04/17 11:16, Peter Maydell wrote:
>> On 11 April 2017 at 11:08, Auger Eric <eric.auger@redhat.com> wrote:
>>> On 11/04/2017 12:05, Marc Zyngier wrote:
>>>> On 10/04/17 16:17, Auger Eric wrote:
>>>>> A (v1) -> B (v1 & v2): migration OK
>>>>> B (v1 & v2) -> C (v1): migration NOK
>>>>
>>>> So what does IIDR report on B once the A->B migration has taken place?
>>>> Does it report v2?
>>>
>>> yes that was the plan
>>
>> Hmm, the IIDR value shouldn't change across a migration I think.
>> It's guest visible so the guest should see it still the same
>> value even after migration.
> 
> That's my worry. But we then have a problem when this VM migrates again.
> How does userspace find out which ABI to use then?

Today the userspace just conveys the information from source kernel to
destination kernel through the IIDR value. This allows the destination
kernel to know what was the table layout used during the migration.

If we report the source ABI revision value on the destination, what is
the strategy we should adopt:
- limit the features to those that will be migratable through this ABI
- allow the functionalities (GICv4 for instance) but reject save?

Thanks

Eric
> 
> Thanks,
> 
> 	M.
> 

^ permalink raw reply	[flat|nested] 144+ messages in thread

* [PATCH v4 08/22] KVM: arm64: ITS: Implement vgic_mmio_uaccess_write_its_iidr
@ 2017-04-11 10:56                     ` Auger Eric
  0 siblings, 0 replies; 144+ messages in thread
From: Auger Eric @ 2017-04-11 10:56 UTC (permalink / raw)
  To: linux-arm-kernel

Hi,

On 11/04/2017 12:29, Marc Zyngier wrote:
> On 11/04/17 11:16, Peter Maydell wrote:
>> On 11 April 2017 at 11:08, Auger Eric <eric.auger@redhat.com> wrote:
>>> On 11/04/2017 12:05, Marc Zyngier wrote:
>>>> On 10/04/17 16:17, Auger Eric wrote:
>>>>> A (v1) -> B (v1 & v2): migration OK
>>>>> B (v1 & v2) -> C (v1): migration NOK
>>>>
>>>> So what does IIDR report on B once the A->B migration has taken place?
>>>> Does it report v2?
>>>
>>> yes that was the plan
>>
>> Hmm, the IIDR value shouldn't change across a migration I think.
>> It's guest visible so the guest should see it still the same
>> value even after migration.
> 
> That's my worry. But we then have a problem when this VM migrates again.
> How does userspace find out which ABI to use then?

Today the userspace just conveys the information from source kernel to
destination kernel through the IIDR value. This allows the destination
kernel to know what was the table layout used during the migration.

If we report the source ABI revision value on the destination, what is
the strategy we should adopt:
- limit the features to those that will be migratable through this ABI
- allow the functionalities (GICv4 for instance) but reject save?

Thanks

Eric
> 
> Thanks,
> 
> 	M.
> 

^ permalink raw reply	[flat|nested] 144+ messages in thread

* Re: [PATCH v4 01/22] KVM: arm/arm64: Add vITS save/restore API documentation
  2017-04-10 14:26       ` Auger Eric
@ 2017-04-21  9:12         ` Christoffer Dall
  -1 siblings, 0 replies; 144+ messages in thread
From: Christoffer Dall @ 2017-04-21  9:12 UTC (permalink / raw)
  To: Auger Eric
  Cc: Christoffer Dall, peter.maydell, drjones, kvm, Prasun.Kapoor,
	marc.zyngier, andre.przywara, quintela, dgilbert, Vijaya.Kumar,
	vijayak, pbonzini, kvmarm, linux-arm-kernel, eric.auger.pro

On Mon, Apr 10, 2017 at 04:26:14PM +0200, Auger Eric wrote:
> Hi Christoffer,
> 
> On 08/04/2017 20:17, Christoffer Dall wrote:
> > Hi Eric,
> > 
> > Most of my comments below are just me being picky about text when
> > defining a user space ABI, so I think this mainly looks good, but just
> > needs a bit of clarify, except the versioning aspect and exporting the
> > pending table vie the redistributor instead, as Marc and Andre have
> > pointed out.
> > 
> > On Mon, Mar 27, 2017 at 11:30:51AM +0200, Eric Auger wrote:
> >> Add description for how to access vITS registers and how to flush/restore
> >> vITS tables into/from memory
> >>
> >> Signed-off-by: Eric Auger <eric.auger@redhat.com>
> >>
> >> ---
> >> v3 -> v4:
> >> - take into account Peter's comments:
> >>   - typos
> >>   - KVM_DEV_ARM_VGIC_GRP_ITS_TABLES kvm_device_attr = 0
> >>   - add a validity bit in DTE
> >>   - document all fields in CTE and ITE
> >>   - document ABI revision
> >> - take into account Andre's comments:
> >>   - document restrictions about GITS_CREADR writing and GITS_IIDR
> >>   - document -EBUSY error if one or more VCPUS are runnning
> >>   - document 64b registers only can be accessed with 64b access
> >> - itt_addr field matches bits [51:8] of the itt_addr
> >>
> >> v1 -> v2:
> >> - DTE and ITE now are 8 bytes
> >> - DTE and ITE now indexed by deviceid/eventid
> >> - use ITE name instead of ITTE
> >> - mentions ITT_addr matches bits [51:8] of the actual address
> >> - mentions LE layout
> >> ---
> >>  Documentation/virtual/kvm/devices/arm-vgic-its.txt | 118 +++++++++++++++++++++
> >>  1 file changed, 118 insertions(+)
> >>
> >> diff --git a/Documentation/virtual/kvm/devices/arm-vgic-its.txt b/Documentation/virtual/kvm/devices/arm-vgic-its.txt
> >> index 6081a5b..0902d20 100644
> >> --- a/Documentation/virtual/kvm/devices/arm-vgic-its.txt
> >> +++ b/Documentation/virtual/kvm/devices/arm-vgic-its.txt
> >> @@ -36,3 +36,121 @@ Groups:
> >>      -ENXIO:  ITS not properly configured as required prior to setting
> >>               this attribute
> >>      -ENOMEM: Memory shortage when allocating ITS internal data
> >> +
> >> +  KVM_DEV_ARM_VGIC_GRP_ITS_REGS
> >> +  Attributes:
> >> +      The attr field of kvm_device_attr encodes the offset of the
> >> +      ITS register, relative to the ITS control frame base address
> >> +      (ITS_base).
> >> +
> >> +      kvm_device_attr.addr points to a __u64 value whatever the width
> >> +      of the addressed register (32/64 bits). 64 bit registers can only
> >> +      be accessed with full length.
> >> +
> >> +      Writes to read-only registers are ignored by the kernel except for:
> >> +      - GITS_READR. It needs to be restored otherwise commands in the queue
> >> +        will be re-executed after CWRITER setting. Writing this register is
> >                                      ^^^^^^^^^^^^^^^
> > 
> > "after restoring CWRITER." ?
> OK
> > 
> >> +        allowed if the ITS is not enabled (GITS_CTLR.enable = 0). Also it
> > 
> > Does that mean that you can only save/restore a disabled ITS or does it
> > mean that initially after creating the ITS it is disabled and userspace
> > should restore the CWRITER before restoring GITS_CTLR (which may enable
> > the ITS) ?
> No I meant the second. As normally the ITS is responsible for updating
> the GITS_READR, if the userspace plays with it while the ITS is enabled
> this can mess everything. So the userspace is supposed to restore the
> GITS_READR *before* restoring the GITS_CTLR which is likely to enable
> the ITS.
> > 
> >> +        needs to be restored after GITS_CBASER since a write to GITS_CBASER
> >> +        resets GITS_CREADR.
> >> +      - GITS_IIDR. Its Revision field encodes the table layout ABI revision.
> > 
> > How is this really going to work?  Your ABI here must be backwards
> > compatible for future revisions, so what is userspace supposed to do,
> > when it reads a newer revision than it was programmed for?
> destination ABI revision must be >= source ABI revision
> By restoring the IIDR value on the destination side, the userspace
> informs destination KVM about the layout of the table. If the
> destination KVM does not support this ABI revision, the restoration of
> the ITS table fails. Is that wrong?
> 

No, that's fine.  I think my confusion was that I didn't appreciate that
the revision thing is for the table layouts only, and not the other
calls here.

> > 
> > I think we need a more clear description of how the revision is going to
> > be used, such that each operation on the ITS here is described as
> > requiring a minimum revision X, and making sure that userspace can
> > safely ignore things that are of a higher revision number, while at the
> > same time userspace can decide not to use newer features with older
> > kernels.
> 
> At the moment I did not plan to implement any way for the userspace to
> force the ITS state save in a specified ABI revision. Today it uses the
> higher revision. Let's say that ABI V2 supports GICv4, save of source
> ITS with be done in v2 layout. A destination only supporting GICv3 (ABI
> v1) won't be able to read that format. Does it make sense?
> 

That makes sense, yes.

> > 
> >> +
> >> +      For other registers, getting or setting a register has the same
> >> +      effect as reading/writing the register on real hardware.
> >> +  Errors:
> >> +    -ENXIO: Offset does not correspond to any supported register
> >> +    -EFAULT: Invalid user pointer for attr->addr
> >> +    -EINVAL: Offset is not 64-bit aligned
> >> +    -EBUSY: one or more VCPUS are running
> >> +
> >> +  KVM_DEV_ARM_VGIC_GRP_ITS_TABLES
> > 
> > Shouldn't this be called KVM_DEV_ARM_VGIC_GRP_FLUSH_ITS_TABLES ?
> At the moment this group is used for flush and restore. But as you have
> the same remark as Andre I guess it is worth having separate commands in
> KVM_DEV_ARM_VGIC_GRP_CTRL then.
> > 
> >> +  Attributes
> >> +       The attr field of kvm_device_attr must be zero.
> >> +
> >> +       request the flush-save/restore of the ITS tables, namely
> > 
> > Nit: Request (upper case R)
> OK
> > 
> > what does flush-save/restore mean as opposed to just flush?
> meant flush/restore
> > 
> >> +       the device table, the collection table, all the ITT tables,
> >> +       the LPI pending tables. On save, the tables are flushed
> > 
> > , and the LPI pending table.
> OK
> > 
> >> +       into guest memory at the location provisioned by the guest
> >> +       in GITS_BASER (device and collection tables), in the MAPD
> >> +       command (ITT_addr), GICR_PENDBASERs (pending tables).
> >> +
> >> +       This means the GIC should be restored before the ITS and all
> > 
> > should or must?  Is this enforced?
> must. yes it is.
> > 
> >> +       ITS registers but the GITS_CTLR must be restored before
> >> +       restoring the ITS tables.
> >> +
> >> +       The GITS_READR and GITS_IIDR read-only registers must also
> >> +       be restored before the table restore. The IIDR revision field
> >> +       encodes the ABI revision of the table layout. If not set by
> >> +       user space, the restoration of the tables will fail.
> > 
> > consider rewording: ", restoring the ITS tables will fail."
> OK
> > 
> >> +
> >> +       Note the LPI configuration table is read-only for the
> > 
> > Note that
> OK
> > 
> >> +       in-kernel ITS and its save/restore goes through the standard
> > 
> > and saving/restoring it is done via the normal process to save/restore
> > guest RAM.
> OK
> > 
> >> +       RAM save/restore.
> >> +
> >> +       The layout of the tables in guest memory defines an ABI.
> >> +       The entries are laid in little endian format as follows;
> > 
> > s/;/:/
> OK
> > 
> > It's a bit weird to say "as follows:" and then proceed with the error
> > descriptions.  I would simply say "as described in the following
> > paragraph."
> OK
> > 
> >> +
> >> +  Errors:
> >> +    -EINVAL: kvm_device_attr not equal to 0, invalid table data
> >> +    -EFAULT: invalid guest ram access
> >> +    -EBUSY: one or more VCPUS are running
> >> +
> >> +    ITS Table ABI REV1:
> >> +    -------------------
> >> +
> >> +    The device table and ITE are respectively indexed by device id and
> > 
> > s/ITE/ITT/
> right
> > 
> > are indexed by the device id and eventid, respectively.
> > 
> >> +    eventid. The collection table however is not indexed by collection id:
> > 
> > ...by collection id, instead all the CTEs are written...
> > 
> >> +    CTE are written at the beginning of the buffer.
> > 
> > in any particular order, or?
> no order or creation

Probably good to point that out.

> > 
> >> +
> >> +    Device Table Entry (DTE) layout: entry size = 8 bytes
> >> +
> >> +    bits:     | 63| 62 ... 49 | 48 ... 5 | 4 ... 0 |
> >> +    values:   | V |   next    | ITT_addr |  Size   |
> >> +
> >> +    where;
> >> +    - V indicates whether the entry is valid,
> >> +    - ITT_addr matches bits [51:8] of the ITT address (256B aligned),
> >> +    - next field is meaningful only if the entry is valid.
> > 
> > is the ITT_addr meaningful if the entry is not valid?
> no, I will add this detail.
> > 
> >> +    It equals to 0 if this entry is the last one; otherwise it corresponds
> >> +    to the minimum between the offset to the next device id and 2^14 -1.
> > 
> > I don't easily understand this last paragraph and the indentation is
> > weird and makes it look like it's not explaining the next field.
> 
> reworded:
> It equals to 0 if this entry is the last one; otherwise it corresponds
> to the the deviceid offset to the next DTE, capped by 2^14 -1.
> > 
> > You're missing a description of the size field.  Size in what unit?
> > Size of what?
> right, added "size matches the MAPD Size semantic."
> > 
> > 
> >> +
> >> +    Collection Table Entry (CTE) layout: entry size = 8 bytes
> >> +
> >> +    bits:     | 63| 62 ..  52  | 51 ... 16 | 15  ...   0 |
> >> +    values:   | V |    RES0    |  RDBase   |    ICID     |
> >> +
> >> +    where:
> >> +    - V indicates whether the entry is valid,
> > 
> > Do we explain anywhere what RES0 means?
> Added RES0: reserved field with Should-Be-Zero-or-Preserved behavior.
> > 
> >> +    - RDBase matches the PE number (GICR_TYPER.Processor_Number),
> > 
> > is 'matches' the right verb to use here?
> is
> > 
> > What exactly is the format of GICR_TYPER.Processor_Number ?
> > 
> >> +    - ICID matches the collection ID
> > 
> > again, is 'matches' the right verb to use here?
> is
> > 
> >> +
> >> +    Interrupt Translation Entry (ITE) layout: entry size = 8 bytes
> >> +
> >> +    bits:     | 63 ... 48 | 47 ... 16 | 15 ... 0 |
> >> +    values:   |    next   |   pINTID  |  ICID    |
> >> +
> >> +    where:
> >> +    - pINTID is the physical LPI ID,
> >> +    - ICID is the collection ID,
> > 
> > here you use 'is' intead of 'matches'.  At leat be consistent.
> is
> > 
> >> +    - next field is meaningful only if the entry is valid (pINTID != 0).
> >> +    It equals to 0 if this entry is the last one; otherwise it corresponds
> >> +    to the minimum between the eventid offset to the next ITE and 2^16 -1.
> > 
> > same comments, as above.
> ok
> > 
> > also, can you list the field in the order they appear?
> ok
> > 
> >> +
> >> +    LPI Pending Table layout:
> >> +
> >> +    As specified in the ARM Generic Interrupt Controller Architecture
> >> +    Specification GIC Architecture version 3.0 and version 4. The first
> > 
> > "...version 4, the first".  ("As specified in X." is not a sentence).
> > 
> >> +    1kB is not modified and therefore should contain zeroes.
> > 
> > should or must?  or always contains zeros?  Will you return an error if
> > userspace puts something non-zero in there?
> no I don't. Spec says it should initialized to zero. $
> > 
> >> +
> >> +    Future evolutions of the ITS table layout:
> >> +
> >> +    At the moment the table layout is defined and optimized for physical
> >> +    LPI support.
> > 
> > This comment is a bit confusing, because this is all about virtual
> > interrupts really, so 'physical from the point of view of the VM', but I
> > think you should just drop this sentence.
> OK
> > 
> >> +
> >> +    In the future we might implement direct injection of virtual LPIS.
> > 
> > For nesting, yes?  (on the host this should not be visible here, should
> > it?)
> yes for nesting.
> > 
> >> +    This will require an upgrade of the table layout and an evolution of
> >> +    the ABI. The ABI revision is encoded in the GITS_IIDR revision field.
> >> +    That register must be restored before the table restoration, otherwise
> >> +    the operation will fail.
> > 
> > Hmm, I thought we dealt with that before, feels a bit out of place.
> 
> OK moved to the register description.
> > 
> >> +
> >> +    ABI V1: GITS_IIDR.Revision = 1
> > 
> > I feel like this should go in the ITS register description of the IIDR.
> > Most likely, I think this particular line can be dropped, but all other
> > definitions in this file can be annoted with a minimum revision number
> > ensuring that future revisions implement this, plus potentially more
> > stuff.
> I already put the following title, "ITS Table ABI REV1" for the table
> layout description. My intent was to create a new chapter per revision.
> Is it OK?
> 

I'll have a look at the next revision.

Thanks for responding to all my comments.

-Christoffer

^ permalink raw reply	[flat|nested] 144+ messages in thread

* [PATCH v4 01/22] KVM: arm/arm64: Add vITS save/restore API documentation
@ 2017-04-21  9:12         ` Christoffer Dall
  0 siblings, 0 replies; 144+ messages in thread
From: Christoffer Dall @ 2017-04-21  9:12 UTC (permalink / raw)
  To: linux-arm-kernel

On Mon, Apr 10, 2017 at 04:26:14PM +0200, Auger Eric wrote:
> Hi Christoffer,
> 
> On 08/04/2017 20:17, Christoffer Dall wrote:
> > Hi Eric,
> > 
> > Most of my comments below are just me being picky about text when
> > defining a user space ABI, so I think this mainly looks good, but just
> > needs a bit of clarify, except the versioning aspect and exporting the
> > pending table vie the redistributor instead, as Marc and Andre have
> > pointed out.
> > 
> > On Mon, Mar 27, 2017 at 11:30:51AM +0200, Eric Auger wrote:
> >> Add description for how to access vITS registers and how to flush/restore
> >> vITS tables into/from memory
> >>
> >> Signed-off-by: Eric Auger <eric.auger@redhat.com>
> >>
> >> ---
> >> v3 -> v4:
> >> - take into account Peter's comments:
> >>   - typos
> >>   - KVM_DEV_ARM_VGIC_GRP_ITS_TABLES kvm_device_attr = 0
> >>   - add a validity bit in DTE
> >>   - document all fields in CTE and ITE
> >>   - document ABI revision
> >> - take into account Andre's comments:
> >>   - document restrictions about GITS_CREADR writing and GITS_IIDR
> >>   - document -EBUSY error if one or more VCPUS are runnning
> >>   - document 64b registers only can be accessed with 64b access
> >> - itt_addr field matches bits [51:8] of the itt_addr
> >>
> >> v1 -> v2:
> >> - DTE and ITE now are 8 bytes
> >> - DTE and ITE now indexed by deviceid/eventid
> >> - use ITE name instead of ITTE
> >> - mentions ITT_addr matches bits [51:8] of the actual address
> >> - mentions LE layout
> >> ---
> >>  Documentation/virtual/kvm/devices/arm-vgic-its.txt | 118 +++++++++++++++++++++
> >>  1 file changed, 118 insertions(+)
> >>
> >> diff --git a/Documentation/virtual/kvm/devices/arm-vgic-its.txt b/Documentation/virtual/kvm/devices/arm-vgic-its.txt
> >> index 6081a5b..0902d20 100644
> >> --- a/Documentation/virtual/kvm/devices/arm-vgic-its.txt
> >> +++ b/Documentation/virtual/kvm/devices/arm-vgic-its.txt
> >> @@ -36,3 +36,121 @@ Groups:
> >>      -ENXIO:  ITS not properly configured as required prior to setting
> >>               this attribute
> >>      -ENOMEM: Memory shortage when allocating ITS internal data
> >> +
> >> +  KVM_DEV_ARM_VGIC_GRP_ITS_REGS
> >> +  Attributes:
> >> +      The attr field of kvm_device_attr encodes the offset of the
> >> +      ITS register, relative to the ITS control frame base address
> >> +      (ITS_base).
> >> +
> >> +      kvm_device_attr.addr points to a __u64 value whatever the width
> >> +      of the addressed register (32/64 bits). 64 bit registers can only
> >> +      be accessed with full length.
> >> +
> >> +      Writes to read-only registers are ignored by the kernel except for:
> >> +      - GITS_READR. It needs to be restored otherwise commands in the queue
> >> +        will be re-executed after CWRITER setting. Writing this register is
> >                                      ^^^^^^^^^^^^^^^
> > 
> > "after restoring CWRITER." ?
> OK
> > 
> >> +        allowed if the ITS is not enabled (GITS_CTLR.enable = 0). Also it
> > 
> > Does that mean that you can only save/restore a disabled ITS or does it
> > mean that initially after creating the ITS it is disabled and userspace
> > should restore the CWRITER before restoring GITS_CTLR (which may enable
> > the ITS) ?
> No I meant the second. As normally the ITS is responsible for updating
> the GITS_READR, if the userspace plays with it while the ITS is enabled
> this can mess everything. So the userspace is supposed to restore the
> GITS_READR *before* restoring the GITS_CTLR which is likely to enable
> the ITS.
> > 
> >> +        needs to be restored after GITS_CBASER since a write to GITS_CBASER
> >> +        resets GITS_CREADR.
> >> +      - GITS_IIDR. Its Revision field encodes the table layout ABI revision.
> > 
> > How is this really going to work?  Your ABI here must be backwards
> > compatible for future revisions, so what is userspace supposed to do,
> > when it reads a newer revision than it was programmed for?
> destination ABI revision must be >= source ABI revision
> By restoring the IIDR value on the destination side, the userspace
> informs destination KVM about the layout of the table. If the
> destination KVM does not support this ABI revision, the restoration of
> the ITS table fails. Is that wrong?
> 

No, that's fine.  I think my confusion was that I didn't appreciate that
the revision thing is for the table layouts only, and not the other
calls here.

> > 
> > I think we need a more clear description of how the revision is going to
> > be used, such that each operation on the ITS here is described as
> > requiring a minimum revision X, and making sure that userspace can
> > safely ignore things that are of a higher revision number, while at the
> > same time userspace can decide not to use newer features with older
> > kernels.
> 
> At the moment I did not plan to implement any way for the userspace to
> force the ITS state save in a specified ABI revision. Today it uses the
> higher revision. Let's say that ABI V2 supports GICv4, save of source
> ITS with be done in v2 layout. A destination only supporting GICv3 (ABI
> v1) won't be able to read that format. Does it make sense?
> 

That makes sense, yes.

> > 
> >> +
> >> +      For other registers, getting or setting a register has the same
> >> +      effect as reading/writing the register on real hardware.
> >> +  Errors:
> >> +    -ENXIO: Offset does not correspond to any supported register
> >> +    -EFAULT: Invalid user pointer for attr->addr
> >> +    -EINVAL: Offset is not 64-bit aligned
> >> +    -EBUSY: one or more VCPUS are running
> >> +
> >> +  KVM_DEV_ARM_VGIC_GRP_ITS_TABLES
> > 
> > Shouldn't this be called KVM_DEV_ARM_VGIC_GRP_FLUSH_ITS_TABLES ?
> At the moment this group is used for flush and restore. But as you have
> the same remark as Andre I guess it is worth having separate commands in
> KVM_DEV_ARM_VGIC_GRP_CTRL then.
> > 
> >> +  Attributes
> >> +       The attr field of kvm_device_attr must be zero.
> >> +
> >> +       request the flush-save/restore of the ITS tables, namely
> > 
> > Nit: Request (upper case R)
> OK
> > 
> > what does flush-save/restore mean as opposed to just flush?
> meant flush/restore
> > 
> >> +       the device table, the collection table, all the ITT tables,
> >> +       the LPI pending tables. On save, the tables are flushed
> > 
> > , and the LPI pending table.
> OK
> > 
> >> +       into guest memory at the location provisioned by the guest
> >> +       in GITS_BASER (device and collection tables), in the MAPD
> >> +       command (ITT_addr), GICR_PENDBASERs (pending tables).
> >> +
> >> +       This means the GIC should be restored before the ITS and all
> > 
> > should or must?  Is this enforced?
> must. yes it is.
> > 
> >> +       ITS registers but the GITS_CTLR must be restored before
> >> +       restoring the ITS tables.
> >> +
> >> +       The GITS_READR and GITS_IIDR read-only registers must also
> >> +       be restored before the table restore. The IIDR revision field
> >> +       encodes the ABI revision of the table layout. If not set by
> >> +       user space, the restoration of the tables will fail.
> > 
> > consider rewording: ", restoring the ITS tables will fail."
> OK
> > 
> >> +
> >> +       Note the LPI configuration table is read-only for the
> > 
> > Note that
> OK
> > 
> >> +       in-kernel ITS and its save/restore goes through the standard
> > 
> > and saving/restoring it is done via the normal process to save/restore
> > guest RAM.
> OK
> > 
> >> +       RAM save/restore.
> >> +
> >> +       The layout of the tables in guest memory defines an ABI.
> >> +       The entries are laid in little endian format as follows;
> > 
> > s/;/:/
> OK
> > 
> > It's a bit weird to say "as follows:" and then proceed with the error
> > descriptions.  I would simply say "as described in the following
> > paragraph."
> OK
> > 
> >> +
> >> +  Errors:
> >> +    -EINVAL: kvm_device_attr not equal to 0, invalid table data
> >> +    -EFAULT: invalid guest ram access
> >> +    -EBUSY: one or more VCPUS are running
> >> +
> >> +    ITS Table ABI REV1:
> >> +    -------------------
> >> +
> >> +    The device table and ITE are respectively indexed by device id and
> > 
> > s/ITE/ITT/
> right
> > 
> > are indexed by the device id and eventid, respectively.
> > 
> >> +    eventid. The collection table however is not indexed by collection id:
> > 
> > ...by collection id, instead all the CTEs are written...
> > 
> >> +    CTE are written at the beginning of the buffer.
> > 
> > in any particular order, or?
> no order or creation

Probably good to point that out.

> > 
> >> +
> >> +    Device Table Entry (DTE) layout: entry size = 8 bytes
> >> +
> >> +    bits:     | 63| 62 ... 49 | 48 ... 5 | 4 ... 0 |
> >> +    values:   | V |   next    | ITT_addr |  Size   |
> >> +
> >> +    where;
> >> +    - V indicates whether the entry is valid,
> >> +    - ITT_addr matches bits [51:8] of the ITT address (256B aligned),
> >> +    - next field is meaningful only if the entry is valid.
> > 
> > is the ITT_addr meaningful if the entry is not valid?
> no, I will add this detail.
> > 
> >> +    It equals to 0 if this entry is the last one; otherwise it corresponds
> >> +    to the minimum between the offset to the next device id and 2^14 -1.
> > 
> > I don't easily understand this last paragraph and the indentation is
> > weird and makes it look like it's not explaining the next field.
> 
> reworded:
> It equals to 0 if this entry is the last one; otherwise it corresponds
> to the the deviceid offset to the next DTE, capped by 2^14 -1.
> > 
> > You're missing a description of the size field.  Size in what unit?
> > Size of what?
> right, added "size matches the MAPD Size semantic."
> > 
> > 
> >> +
> >> +    Collection Table Entry (CTE) layout: entry size = 8 bytes
> >> +
> >> +    bits:     | 63| 62 ..  52  | 51 ... 16 | 15  ...   0 |
> >> +    values:   | V |    RES0    |  RDBase   |    ICID     |
> >> +
> >> +    where:
> >> +    - V indicates whether the entry is valid,
> > 
> > Do we explain anywhere what RES0 means?
> Added RES0: reserved field with Should-Be-Zero-or-Preserved behavior.
> > 
> >> +    - RDBase matches the PE number (GICR_TYPER.Processor_Number),
> > 
> > is 'matches' the right verb to use here?
> is
> > 
> > What exactly is the format of GICR_TYPER.Processor_Number ?
> > 
> >> +    - ICID matches the collection ID
> > 
> > again, is 'matches' the right verb to use here?
> is
> > 
> >> +
> >> +    Interrupt Translation Entry (ITE) layout: entry size = 8 bytes
> >> +
> >> +    bits:     | 63 ... 48 | 47 ... 16 | 15 ... 0 |
> >> +    values:   |    next   |   pINTID  |  ICID    |
> >> +
> >> +    where:
> >> +    - pINTID is the physical LPI ID,
> >> +    - ICID is the collection ID,
> > 
> > here you use 'is' intead of 'matches'.  At leat be consistent.
> is
> > 
> >> +    - next field is meaningful only if the entry is valid (pINTID != 0).
> >> +    It equals to 0 if this entry is the last one; otherwise it corresponds
> >> +    to the minimum between the eventid offset to the next ITE and 2^16 -1.
> > 
> > same comments, as above.
> ok
> > 
> > also, can you list the field in the order they appear?
> ok
> > 
> >> +
> >> +    LPI Pending Table layout:
> >> +
> >> +    As specified in the ARM Generic Interrupt Controller Architecture
> >> +    Specification GIC Architecture version 3.0 and version 4. The first
> > 
> > "...version 4, the first".  ("As specified in X." is not a sentence).
> > 
> >> +    1kB is not modified and therefore should contain zeroes.
> > 
> > should or must?  or always contains zeros?  Will you return an error if
> > userspace puts something non-zero in there?
> no I don't. Spec says it should initialized to zero. $
> > 
> >> +
> >> +    Future evolutions of the ITS table layout:
> >> +
> >> +    At the moment the table layout is defined and optimized for physical
> >> +    LPI support.
> > 
> > This comment is a bit confusing, because this is all about virtual
> > interrupts really, so 'physical from the point of view of the VM', but I
> > think you should just drop this sentence.
> OK
> > 
> >> +
> >> +    In the future we might implement direct injection of virtual LPIS.
> > 
> > For nesting, yes?  (on the host this should not be visible here, should
> > it?)
> yes for nesting.
> > 
> >> +    This will require an upgrade of the table layout and an evolution of
> >> +    the ABI. The ABI revision is encoded in the GITS_IIDR revision field.
> >> +    That register must be restored before the table restoration, otherwise
> >> +    the operation will fail.
> > 
> > Hmm, I thought we dealt with that before, feels a bit out of place.
> 
> OK moved to the register description.
> > 
> >> +
> >> +    ABI V1: GITS_IIDR.Revision = 1
> > 
> > I feel like this should go in the ITS register description of the IIDR.
> > Most likely, I think this particular line can be dropped, but all other
> > definitions in this file can be annoted with a minimum revision number
> > ensuring that future revisions implement this, plus potentially more
> > stuff.
> I already put the following title, "ITS Table ABI REV1" for the table
> layout description. My intent was to create a new chapter per revision.
> Is it OK?
> 

I'll have a look at the next revision.

Thanks for responding to all my comments.

-Christoffer

^ permalink raw reply	[flat|nested] 144+ messages in thread

end of thread, other threads:[~2017-04-21  9:12 UTC | newest]

Thread overview: 144+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2017-03-27  9:30 [PATCH v4 00/22] vITS save/restore Eric Auger
2017-03-27  9:30 ` Eric Auger
2017-03-27  9:30 ` [PATCH v4 01/22] KVM: arm/arm64: Add vITS save/restore API documentation Eric Auger
2017-03-27  9:30   ` Eric Auger
2017-04-08 10:03   ` Marc Zyngier
2017-04-08 10:03     ` Marc Zyngier
2017-04-08 13:15     ` Christoffer Dall
2017-04-08 13:15       ` Christoffer Dall
2017-04-08 17:31       ` Marc Zyngier
2017-04-08 17:31         ` Marc Zyngier
2017-04-10 10:18         ` Auger Eric
2017-04-10 10:18           ` Auger Eric
2017-04-10 10:42           ` Marc Zyngier
2017-04-10 10:42             ` Marc Zyngier
2017-04-08 18:17   ` Christoffer Dall
2017-04-08 18:17     ` Christoffer Dall
2017-04-10 14:26     ` Auger Eric
2017-04-10 14:26       ` Auger Eric
2017-04-21  9:12       ` Christoffer Dall
2017-04-21  9:12         ` Christoffer Dall
2017-03-27  9:30 ` [PATCH v4 02/22] KVM: arm/arm64: rename itte into ite Eric Auger
2017-03-27  9:30   ` Eric Auger
2017-04-08 10:04   ` Marc Zyngier
2017-04-08 10:04     ` Marc Zyngier
2017-03-27  9:30 ` [PATCH v4 03/22] arm/arm64: vgic: turn vgic_find_mmio_region into public Eric Auger
2017-03-27  9:30   ` Eric Auger
2017-04-08 10:06   ` Marc Zyngier
2017-04-08 10:06     ` Marc Zyngier
2017-04-08 10:06     ` Marc Zyngier
2017-03-27  9:30 ` [PATCH v4 04/22] KVM: arm64: ITS: KVM_DEV_ARM_VGIC_GRP_ITS_REGS group Eric Auger
2017-03-27  9:30   ` Eric Auger
2017-04-08 10:07   ` Marc Zyngier
2017-04-08 10:07     ` Marc Zyngier
2017-03-27  9:30 ` [PATCH v4 05/22] KVM: arm/arm64: vgic: expose (un)lock_all_vcpus Eric Auger
2017-03-27  9:30   ` Eric Auger
2017-04-08 10:09   ` Marc Zyngier
2017-04-08 10:09     ` Marc Zyngier
2017-03-27  9:30 ` [PATCH v4 06/22] KVM: arm64: ITS: Implement vgic_its_has_attr_regs and attr_regs_access Eric Auger
2017-03-27  9:30   ` Eric Auger
2017-04-08 10:24   ` Marc Zyngier
2017-04-08 10:24     ` Marc Zyngier
2017-04-08 10:24     ` Marc Zyngier
2017-03-27  9:30 ` [PATCH v4 07/22] KVM: arm64: ITS: Implement vgic_mmio_uaccess_write_its_creadr Eric Auger
2017-03-27  9:30   ` Eric Auger
2017-04-08 10:36   ` Marc Zyngier
2017-04-08 10:36     ` Marc Zyngier
2017-04-08 10:36     ` Marc Zyngier
2017-03-27  9:30 ` [PATCH v4 08/22] KVM: arm64: ITS: Implement vgic_mmio_uaccess_write_its_iidr Eric Auger
2017-03-27  9:30   ` Eric Auger
2017-04-08 10:42   ` Marc Zyngier
2017-04-08 10:42     ` Marc Zyngier
2017-04-08 10:42     ` Marc Zyngier
2017-04-10 14:32     ` Auger Eric
2017-04-10 14:32       ` Auger Eric
2017-04-10 14:57       ` Marc Zyngier
2017-04-10 14:57         ` Marc Zyngier
2017-04-10 15:07         ` Peter Maydell
2017-04-10 15:07           ` Peter Maydell
2017-04-10 15:17         ` Auger Eric
2017-04-10 15:17           ` Auger Eric
2017-04-11 10:05           ` Marc Zyngier
2017-04-11 10:05             ` Marc Zyngier
2017-04-11 10:08             ` Auger Eric
2017-04-11 10:08               ` Auger Eric
2017-04-11 10:16               ` Peter Maydell
2017-04-11 10:16                 ` Peter Maydell
2017-04-11 10:29                 ` Marc Zyngier
2017-04-11 10:29                   ` Marc Zyngier
2017-04-11 10:43                   ` Peter Maydell
2017-04-11 10:43                     ` Peter Maydell
2017-04-11 10:56                   ` Auger Eric
2017-04-11 10:56                     ` Auger Eric
2017-03-27  9:30 ` [PATCH v4 09/22] KVM: arm64: ITS: Report the ITE size in GITS_TYPER Eric Auger
2017-03-27  9:30   ` Eric Auger
2017-04-08 17:42   ` Marc Zyngier
2017-04-08 17:42     ` Marc Zyngier
2017-03-27  9:31 ` [PATCH v4 10/22] KVM: arm64: ITS: Interpret MAPD Size field and check related errors Eric Auger
2017-03-27  9:31   ` Eric Auger
2017-04-08 17:59   ` Marc Zyngier
2017-04-08 17:59     ` Marc Zyngier
2017-04-08 17:59     ` Marc Zyngier
2017-03-27  9:31 ` [PATCH v4 11/22] KVM: arm64: ITS: Interpret MAPD ITT_addr field Eric Auger
2017-03-27  9:31   ` Eric Auger
2017-04-08 18:58   ` Marc Zyngier
2017-04-08 18:58     ` Marc Zyngier
2017-04-08 18:58     ` Marc Zyngier
2017-03-27  9:31 ` [PATCH v4 12/22] KVM: arm64: ITS: Check the device id matches TYPER DEVBITS range Eric Auger
2017-03-27  9:31   ` Eric Auger
2017-03-27  9:31 ` [PATCH v4 13/22] KVM: arm64: ITS: KVM_DEV_ARM_VGIC_GRP_ITS_TABLES group Eric Auger
2017-03-27  9:31   ` Eric Auger
2017-03-27 15:04   ` kbuild test robot
2017-03-27 15:04     ` kbuild test robot
2017-03-27 18:29     ` Auger Eric
2017-03-27 18:29       ` Auger Eric
2017-03-30  2:21       ` [kbuild-all] " Ye Xiaolong
2017-03-30  2:21         ` Ye Xiaolong
2017-03-30  6:46         ` Auger Eric
2017-03-30  6:46           ` Auger Eric
2017-03-30  7:29           ` Ye Xiaolong
2017-03-30  7:29             ` Ye Xiaolong
2017-03-30  8:29             ` Auger Eric
2017-03-30  8:29               ` Auger Eric
2017-04-09 10:09   ` Marc Zyngier
2017-04-09 10:09     ` Marc Zyngier
2017-03-27  9:31 ` [PATCH v4 14/22] KVM: arm64: ITS: vgic_its_alloc_ite/device Eric Auger
2017-03-27  9:31   ` Eric Auger
2017-04-09 10:13   ` Marc Zyngier
2017-04-09 10:13     ` Marc Zyngier
2017-03-27  9:31 ` [PATCH v4 15/22] KVM: arm64: ITS: Sort the device and ITE lists Eric Auger
2017-03-27  9:31   ` Eric Auger
2017-04-09 10:18   ` Marc Zyngier
2017-04-09 10:18     ` Marc Zyngier
2017-03-27  9:31 ` [PATCH v4 16/22] KVM: expose next_segment() Eric Auger
2017-03-27  9:31   ` Eric Auger
2017-03-27  9:31 ` [PATCH v4 17/22] KVM: arm64: ITS: Add infrastructure for table lookup Eric Auger
2017-03-27  9:31   ` Eric Auger
2017-04-09 10:36   ` Marc Zyngier
2017-04-09 10:36     ` Marc Zyngier
2017-03-27  9:31 ` [PATCH v4 18/22] KVM: arm64: ITS: Collection table save/restore Eric Auger
2017-03-27  9:31   ` Eric Auger
2017-04-10  9:55   ` Marc Zyngier
2017-04-10  9:55     ` Marc Zyngier
2017-04-11  9:57     ` Auger Eric
2017-04-11  9:57       ` Auger Eric
2017-04-11 10:03       ` Marc Zyngier
2017-04-11 10:03         ` Marc Zyngier
2017-03-27  9:31 ` [PATCH v4 19/22] KVM: arm64: ITS: vgic_its_check_id returns the entry's GPA Eric Auger
2017-03-27  9:31   ` Eric Auger
2017-03-27  9:31 ` [PATCH v4 20/22] KVM: arm64: ITS: ITT flush and restore Eric Auger
2017-03-27  9:31   ` Eric Auger
2017-04-10 12:39   ` Marc Zyngier
2017-04-10 12:39     ` Marc Zyngier
2017-04-11 10:19     ` Auger Eric
2017-04-11 10:19       ` Auger Eric
2017-03-27  9:31 ` [PATCH v4 21/22] KVM: arm64: ITS: Device table save/restore Eric Auger
2017-03-27  9:31   ` Eric Auger
2017-04-10 12:42   ` Marc Zyngier
2017-04-10 12:42     ` Marc Zyngier
2017-03-27  9:31 ` [PATCH v4 22/22] KVM: arm64: ITS: Pending " Eric Auger
2017-03-27  9:31   ` Eric Auger
2017-04-10 12:50   ` Marc Zyngier
2017-04-10 12:50     ` Marc Zyngier
2017-04-10 12:54 ` [PATCH v4 00/22] vITS save/restore Marc Zyngier
2017-04-10 12:54   ` Marc Zyngier

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.