All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v5 00/26] KVM: arm64: SVE guest support
@ 2019-02-18 19:52 ` Dave Martin
  0 siblings, 0 replies; 205+ messages in thread
From: Dave Martin @ 2019-02-18 19:52 UTC (permalink / raw)
  To: kvmarm
  Cc: Peter Maydell, Okamoto Takayuki, Christoffer Dall,
	Ard Biesheuvel, Marc Zyngier, Catalin Marinas, Will Deacon,
	Zhang Lei, Julien Grall, Alex Bennée, linux-arm-kernel

This series implements support for allowing KVM guests to use the Arm
Scalable Vector Extension (SVE), superseding the previous v4 series [1].

The patches are also available on a branch for reviewer convenience. [2]

The patches are based on v5.0-rc6.

They depend on another small series currently under review [3] that does
a bit of relevant refactoring (as well as fixing an anomaly not directly
related to this series).  A base branch [4] is provided so that
reviewers don't need to hunt down both series independently.

This series contains no major update except for the removal of multiple
register slice support in the user register access ioctls.  The ABI is
kept as-is so that this functionality can be added back in later on
if/when needed.  ioctl access to nonexistent slices now yields ENOENT,
which is more consistent with the notion of an absent register.

For a description of minor updates, see the individual patches.


Functionality testing and stress-testing has been done, using a
hacked-up kvmtool [5]:

 * Arm Fast Model: full testing of arm64 defconfig, including running
   non-SVE and SVE guests with mixtures of vector lengths.  limited
   testing of other configurations.

 * ThunderX2: basic testing of arm64 defconfig, including booting guests
   (no SVE support on this hardware).

 * Full build-bisect testing and sparse testing of every commit done
   for arm64 (defconfig, CONFIG_ARM64_SVE=n, CONFIG_KVM=n) and arm
   (multi_v7_defconfig, CONFIG_KVM=y).  One new sparse warning,
   probably spurious (see note in patch 22).


AArch32 host testing is pending.  I will ping this series with a reply
to the cover letter when that testing has been completed.

   
Known issues:

 * **Possible bug**

   SVE state corruption has been in the host when running on the Arm
   Fast Model.

   After some investigation with the model engineers, it appears that
   there may be a model bug in this area.  I have also obtained detailed
   trace of failure cases, which is also suggestive of a model bug.  No
   clear evidence has been obtained to show that there is a bug in
   Linux, so far.

   All available evidence suggests that this bug will not affect non-SVE
   hardware: the symptom is unexpected zeroing of bits 128 and above of
   the vector registers (which don't exist prior to SVE).

 * kvmtool support is not mature


[1] [RFC PATCH v4 00/24] KVM: arm64: SVE guest support
https://lists.cs.columbia.edu/pipermail/kvmarm/2019-January/034134.html

[2] This series in git:
http://linux-arm.org/git?p=linux-dm.git;a=shortlog;h=refs/heads/sve-kvm/v5/head
git://linux-arm.org/linux-dm.git sve-kvm/v5/head

[3] [PATCH v2 0/2] Fix KVM_GET_REG_LIST invalid register ID regression
https://lists.cs.columbia.edu/pipermail/kvmarm/2018-December/033810.html

[4] Base of this series in git:
http://linux-arm.org/git?p=linux-dm.git;a=shortlog;h=refs/heads/sve-kvm/v5/base
git://linux-arm.org/linux-dm.git sve-kvm/v5/base

[5] [RFC PATCH 00/12] arm64: SVE guest support test hacks
https://lists.cs.columbia.edu/pipermail/kvmarm/2019-January/034162.html


Dave Martin (26):
  KVM: Documentation: Document arm64 core registers in detail
  arm64: fpsimd: Always set TIF_FOREIGN_FPSTATE on task state flush
  KVM: arm64: Delete orphaned declaration for __fpsimd_enabled()
  KVM: arm64: Refactor kvm_arm_num_regs() for easier maintenance
  KVM: arm64: Add missing #include of <linux/bitmap.h> to kvm_host.h
  arm64/sve: Check SVE virtualisability
  arm64/sve: Clarify role of the VQ map maintenance functions
  arm64/sve: Enable SVE state tracking for non-task contexts
  KVM: arm64: Add a vcpu flag to control SVE visibility for the guest
  KVM: arm64: Propagate vcpu into read_id_reg()
  KVM: arm64: Extend reset_unknown() to handle mixed RES0/UNKNOWN
    registers
  KVM: arm64: Support runtime sysreg visibility filtering
  KVM: arm64/sve: System register context switch and access support
  KVM: arm64/sve: Context switch the SVE registers
  KVM: Allow 2048-bit register access via ioctl interface
  KVM: arm64: Add missing #include of <linux/string.h> in guest.c
  KVM: arm64: Reject ioctl access to FPSIMD V-regs on SVE vcpus
  KVM: arm64/sve: Add SVE support to register access ioctl interface
  KVM: arm64: Enumerate SVE register indices for KVM_GET_REG_LIST
  arm64/sve: In-kernel vector length availability query interface
  KVM: arm/arm64: Add hook to finalize the vcpu configuration
  KVM: arm64/sve: Add pseudo-register for the guest's vector lengths
  KVM: arm64/sve: Allow userspace to enable SVE for vcpus
  KVM: arm64: Add a capabillity to advertise SVE support
  KVM: Document errors for KVM_GET_ONE_REG and KVM_SET_ONE_REG
  KVM: arm64/sve: Document KVM API extensions for SVE

 Documentation/virtual/kvm/api.txt |  93 ++++++++++
 arch/arm/include/asm/kvm_host.h   |   4 +
 arch/arm64/include/asm/fpsimd.h   |  33 +++-
 arch/arm64/include/asm/kvm_host.h |  35 +++-
 arch/arm64/include/asm/kvm_hyp.h  |   1 -
 arch/arm64/include/asm/sysreg.h   |   3 +
 arch/arm64/include/uapi/asm/kvm.h |  22 +++
 arch/arm64/kernel/cpufeature.c    |   2 +-
 arch/arm64/kernel/fpsimd.c        | 172 +++++++++++++------
 arch/arm64/kernel/signal.c        |   5 -
 arch/arm64/kvm/fpsimd.c           |  17 +-
 arch/arm64/kvm/guest.c            | 348 +++++++++++++++++++++++++++++++++++---
 arch/arm64/kvm/hyp/switch.c       |  69 ++++++--
 arch/arm64/kvm/reset.c            |  87 +++++++++-
 arch/arm64/kvm/sys_regs.c         | 144 ++++++++++++++--
 arch/arm64/kvm/sys_regs.h         |  24 ++-
 include/uapi/linux/kvm.h          |   2 +
 virt/kvm/arm/arm.c                |   8 +
 18 files changed, 944 insertions(+), 125 deletions(-)

-- 
2.1.4

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

* [PATCH v5 00/26] KVM: arm64: SVE guest support
@ 2019-02-18 19:52 ` Dave Martin
  0 siblings, 0 replies; 205+ messages in thread
From: Dave Martin @ 2019-02-18 19:52 UTC (permalink / raw)
  To: kvmarm
  Cc: Peter Maydell, Okamoto Takayuki, Christoffer Dall,
	Ard Biesheuvel, Marc Zyngier, Catalin Marinas, Will Deacon,
	Zhang Lei, Julien Grall, Alex Bennée, linux-arm-kernel

This series implements support for allowing KVM guests to use the Arm
Scalable Vector Extension (SVE), superseding the previous v4 series [1].

The patches are also available on a branch for reviewer convenience. [2]

The patches are based on v5.0-rc6.

They depend on another small series currently under review [3] that does
a bit of relevant refactoring (as well as fixing an anomaly not directly
related to this series).  A base branch [4] is provided so that
reviewers don't need to hunt down both series independently.

This series contains no major update except for the removal of multiple
register slice support in the user register access ioctls.  The ABI is
kept as-is so that this functionality can be added back in later on
if/when needed.  ioctl access to nonexistent slices now yields ENOENT,
which is more consistent with the notion of an absent register.

For a description of minor updates, see the individual patches.


Functionality testing and stress-testing has been done, using a
hacked-up kvmtool [5]:

 * Arm Fast Model: full testing of arm64 defconfig, including running
   non-SVE and SVE guests with mixtures of vector lengths.  limited
   testing of other configurations.

 * ThunderX2: basic testing of arm64 defconfig, including booting guests
   (no SVE support on this hardware).

 * Full build-bisect testing and sparse testing of every commit done
   for arm64 (defconfig, CONFIG_ARM64_SVE=n, CONFIG_KVM=n) and arm
   (multi_v7_defconfig, CONFIG_KVM=y).  One new sparse warning,
   probably spurious (see note in patch 22).


AArch32 host testing is pending.  I will ping this series with a reply
to the cover letter when that testing has been completed.

   
Known issues:

 * **Possible bug**

   SVE state corruption has been in the host when running on the Arm
   Fast Model.

   After some investigation with the model engineers, it appears that
   there may be a model bug in this area.  I have also obtained detailed
   trace of failure cases, which is also suggestive of a model bug.  No
   clear evidence has been obtained to show that there is a bug in
   Linux, so far.

   All available evidence suggests that this bug will not affect non-SVE
   hardware: the symptom is unexpected zeroing of bits 128 and above of
   the vector registers (which don't exist prior to SVE).

 * kvmtool support is not mature


[1] [RFC PATCH v4 00/24] KVM: arm64: SVE guest support
https://lists.cs.columbia.edu/pipermail/kvmarm/2019-January/034134.html

[2] This series in git:
http://linux-arm.org/git?p=linux-dm.git;a=shortlog;h=refs/heads/sve-kvm/v5/head
git://linux-arm.org/linux-dm.git sve-kvm/v5/head

[3] [PATCH v2 0/2] Fix KVM_GET_REG_LIST invalid register ID regression
https://lists.cs.columbia.edu/pipermail/kvmarm/2018-December/033810.html

[4] Base of this series in git:
http://linux-arm.org/git?p=linux-dm.git;a=shortlog;h=refs/heads/sve-kvm/v5/base
git://linux-arm.org/linux-dm.git sve-kvm/v5/base

[5] [RFC PATCH 00/12] arm64: SVE guest support test hacks
https://lists.cs.columbia.edu/pipermail/kvmarm/2019-January/034162.html


Dave Martin (26):
  KVM: Documentation: Document arm64 core registers in detail
  arm64: fpsimd: Always set TIF_FOREIGN_FPSTATE on task state flush
  KVM: arm64: Delete orphaned declaration for __fpsimd_enabled()
  KVM: arm64: Refactor kvm_arm_num_regs() for easier maintenance
  KVM: arm64: Add missing #include of <linux/bitmap.h> to kvm_host.h
  arm64/sve: Check SVE virtualisability
  arm64/sve: Clarify role of the VQ map maintenance functions
  arm64/sve: Enable SVE state tracking for non-task contexts
  KVM: arm64: Add a vcpu flag to control SVE visibility for the guest
  KVM: arm64: Propagate vcpu into read_id_reg()
  KVM: arm64: Extend reset_unknown() to handle mixed RES0/UNKNOWN
    registers
  KVM: arm64: Support runtime sysreg visibility filtering
  KVM: arm64/sve: System register context switch and access support
  KVM: arm64/sve: Context switch the SVE registers
  KVM: Allow 2048-bit register access via ioctl interface
  KVM: arm64: Add missing #include of <linux/string.h> in guest.c
  KVM: arm64: Reject ioctl access to FPSIMD V-regs on SVE vcpus
  KVM: arm64/sve: Add SVE support to register access ioctl interface
  KVM: arm64: Enumerate SVE register indices for KVM_GET_REG_LIST
  arm64/sve: In-kernel vector length availability query interface
  KVM: arm/arm64: Add hook to finalize the vcpu configuration
  KVM: arm64/sve: Add pseudo-register for the guest's vector lengths
  KVM: arm64/sve: Allow userspace to enable SVE for vcpus
  KVM: arm64: Add a capabillity to advertise SVE support
  KVM: Document errors for KVM_GET_ONE_REG and KVM_SET_ONE_REG
  KVM: arm64/sve: Document KVM API extensions for SVE

 Documentation/virtual/kvm/api.txt |  93 ++++++++++
 arch/arm/include/asm/kvm_host.h   |   4 +
 arch/arm64/include/asm/fpsimd.h   |  33 +++-
 arch/arm64/include/asm/kvm_host.h |  35 +++-
 arch/arm64/include/asm/kvm_hyp.h  |   1 -
 arch/arm64/include/asm/sysreg.h   |   3 +
 arch/arm64/include/uapi/asm/kvm.h |  22 +++
 arch/arm64/kernel/cpufeature.c    |   2 +-
 arch/arm64/kernel/fpsimd.c        | 172 +++++++++++++------
 arch/arm64/kernel/signal.c        |   5 -
 arch/arm64/kvm/fpsimd.c           |  17 +-
 arch/arm64/kvm/guest.c            | 348 +++++++++++++++++++++++++++++++++++---
 arch/arm64/kvm/hyp/switch.c       |  69 ++++++--
 arch/arm64/kvm/reset.c            |  87 +++++++++-
 arch/arm64/kvm/sys_regs.c         | 144 ++++++++++++++--
 arch/arm64/kvm/sys_regs.h         |  24 ++-
 include/uapi/linux/kvm.h          |   2 +
 virt/kvm/arm/arm.c                |   8 +
 18 files changed, 944 insertions(+), 125 deletions(-)

-- 
2.1.4


_______________________________________________
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] 205+ messages in thread

* [PATCH v5 01/26] KVM: Documentation: Document arm64 core registers in detail
  2019-02-18 19:52 ` Dave Martin
@ 2019-02-18 19:52   ` Dave Martin
  -1 siblings, 0 replies; 205+ messages in thread
From: Dave Martin @ 2019-02-18 19:52 UTC (permalink / raw)
  To: kvmarm
  Cc: Okamoto Takayuki, Christoffer Dall, Ard Biesheuvel, Marc Zyngier,
	Catalin Marinas, Will Deacon, Zhang Lei, linux-arm-kernel

Since the the sizes of individual members of the core arm64
registers vary, the list of register encodings that make sense is
not a simple linear sequence.

To clarify which encodings to use, this patch adds a brief list
to the documentation.

Signed-off-by: Dave Martin <Dave.Martin@arm.com>
---
 Documentation/virtual/kvm/api.txt | 24 ++++++++++++++++++++++++
 1 file changed, 24 insertions(+)

diff --git a/Documentation/virtual/kvm/api.txt b/Documentation/virtual/kvm/api.txt
index 356156f..097b8ba 100644
--- a/Documentation/virtual/kvm/api.txt
+++ b/Documentation/virtual/kvm/api.txt
@@ -2090,6 +2090,30 @@ contains elements ranging from 32 to 128 bits. The index is a 32bit
 value in the kvm_regs structure seen as a 32bit array.
   0x60x0 0000 0010 <index into the kvm_regs struct:16>
 
+Specifically:
+    Encoding            Register  Bits  kvm_regs member
+----------------------------------------------------------------
+  0x6030 0000 0010 0000 X0          64  regs.regs[0]
+  0x6030 0000 0010 0002 X1          64  regs.regs[1]
+    ...
+  0x6030 0000 0010 003c X30         64  regs.regs[30]
+  0x6030 0000 0010 003e SP          64  regs.sp
+  0x6030 0000 0010 0040 PC          64  regs.pc
+  0x6030 0000 0010 0042 PSTATE      64  regs.pstate
+  0x6030 0000 0010 0044 SP_EL1      64  sp_el1
+  0x6030 0000 0010 0046 ELR_EL1     64  elr_el1
+  0x6030 0000 0010 0048 SPSR_EL1    64  spsr[KVM_SPSR_EL1] (alias SPSR_SVC)
+  0x6030 0000 0010 004a SPSR_ABT    64  spsr[KVM_SPSR_ABT]
+  0x6030 0000 0010 004c SPSR_UND    64  spsr[KVM_SPSR_UND]
+  0x6030 0000 0010 004e SPSR_IRQ    64  spsr[KVM_SPSR_IRQ]
+  0x6060 0000 0010 0050 SPSR_FIQ    64  spsr[KVM_SPSR_FIQ]
+  0x6040 0000 0010 0054 V0         128  fp_regs.vregs[0]
+  0x6040 0000 0010 0058 V1         128  fp_regs.vregs[1]
+    ...
+  0x6040 0000 0010 00d0 V31        128  fp_regs.vregs[31]
+  0x6020 0000 0010 00d4 FPSR        32  fp_regs.fpsr
+  0x6020 0000 0010 00d5 FPCR        32  fp_regs.fpcr
+
 arm64 CCSIDR registers are demultiplexed by CSSELR value:
   0x6020 0000 0011 00 <csselr:8>
 
-- 
2.1.4

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

* [PATCH v5 01/26] KVM: Documentation: Document arm64 core registers in detail
@ 2019-02-18 19:52   ` Dave Martin
  0 siblings, 0 replies; 205+ messages in thread
From: Dave Martin @ 2019-02-18 19:52 UTC (permalink / raw)
  To: kvmarm
  Cc: Peter Maydell, Okamoto Takayuki, Christoffer Dall,
	Ard Biesheuvel, Marc Zyngier, Catalin Marinas, Will Deacon,
	Zhang Lei, Julien Grall, Alex Bennée, linux-arm-kernel

Since the the sizes of individual members of the core arm64
registers vary, the list of register encodings that make sense is
not a simple linear sequence.

To clarify which encodings to use, this patch adds a brief list
to the documentation.

Signed-off-by: Dave Martin <Dave.Martin@arm.com>
---
 Documentation/virtual/kvm/api.txt | 24 ++++++++++++++++++++++++
 1 file changed, 24 insertions(+)

diff --git a/Documentation/virtual/kvm/api.txt b/Documentation/virtual/kvm/api.txt
index 356156f..097b8ba 100644
--- a/Documentation/virtual/kvm/api.txt
+++ b/Documentation/virtual/kvm/api.txt
@@ -2090,6 +2090,30 @@ contains elements ranging from 32 to 128 bits. The index is a 32bit
 value in the kvm_regs structure seen as a 32bit array.
   0x60x0 0000 0010 <index into the kvm_regs struct:16>
 
+Specifically:
+    Encoding            Register  Bits  kvm_regs member
+----------------------------------------------------------------
+  0x6030 0000 0010 0000 X0          64  regs.regs[0]
+  0x6030 0000 0010 0002 X1          64  regs.regs[1]
+    ...
+  0x6030 0000 0010 003c X30         64  regs.regs[30]
+  0x6030 0000 0010 003e SP          64  regs.sp
+  0x6030 0000 0010 0040 PC          64  regs.pc
+  0x6030 0000 0010 0042 PSTATE      64  regs.pstate
+  0x6030 0000 0010 0044 SP_EL1      64  sp_el1
+  0x6030 0000 0010 0046 ELR_EL1     64  elr_el1
+  0x6030 0000 0010 0048 SPSR_EL1    64  spsr[KVM_SPSR_EL1] (alias SPSR_SVC)
+  0x6030 0000 0010 004a SPSR_ABT    64  spsr[KVM_SPSR_ABT]
+  0x6030 0000 0010 004c SPSR_UND    64  spsr[KVM_SPSR_UND]
+  0x6030 0000 0010 004e SPSR_IRQ    64  spsr[KVM_SPSR_IRQ]
+  0x6060 0000 0010 0050 SPSR_FIQ    64  spsr[KVM_SPSR_FIQ]
+  0x6040 0000 0010 0054 V0         128  fp_regs.vregs[0]
+  0x6040 0000 0010 0058 V1         128  fp_regs.vregs[1]
+    ...
+  0x6040 0000 0010 00d0 V31        128  fp_regs.vregs[31]
+  0x6020 0000 0010 00d4 FPSR        32  fp_regs.fpsr
+  0x6020 0000 0010 00d5 FPCR        32  fp_regs.fpcr
+
 arm64 CCSIDR registers are demultiplexed by CSSELR value:
   0x6020 0000 0011 00 <csselr:8>
 
-- 
2.1.4


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* [PATCH v5 02/26] arm64: fpsimd: Always set TIF_FOREIGN_FPSTATE on task state flush
  2019-02-18 19:52 ` Dave Martin
@ 2019-02-18 19:52   ` Dave Martin
  -1 siblings, 0 replies; 205+ messages in thread
From: Dave Martin @ 2019-02-18 19:52 UTC (permalink / raw)
  To: kvmarm
  Cc: Okamoto Takayuki, Christoffer Dall, Ard Biesheuvel, Marc Zyngier,
	Catalin Marinas, Will Deacon, Zhang Lei, linux-arm-kernel

This patch updates fpsimd_flush_task_state() to mirror the new
semantics of fpsimd_flush_cpu_state() introduced by commit
d8ad71fa38a9 ("arm64: fpsimd: Fix TIF_FOREIGN_FPSTATE after
invalidating cpu regs").  Both functions now implicitly set
TIF_FOREIGN_FPSTATE to indicate that the task's FPSIMD state is not
loaded into the cpu.

As a side-effect, fpsimd_flush_task_state() now sets
TIF_FOREIGN_FPSTATE even for non-running tasks.  In the case of
non-running tasks this is not useful but also harmless, because the
flag is live only while the corresponding task is running.  This
function is not called from fast paths, so special-casing this for
the task == current case is not really worth it.

Compiler barriers previously present in restore_sve_fpsimd_context()
are pulled into fpsimd_flush_task_state() so that it can be safely
called with preemption enabled if necessary.

Explicit calls to set TIF_FOREIGN_FPSTATE that accompany
fpsimd_flush_task_state() calls and are now redundant are removed
as appropriate.

fpsimd_flush_task_state() is used to get exclusive access to the
representation of the task's state via task_struct, for the purpose
of replacing the state.  Thus, the call to this function should
happen before manipulating fpsimd_state or sve_state etc. in
task_struct.  Anomalous cases are reordered appropriately in order
to make the code more consistent, although there should be no
functional difference since these cases are protected by
local_bh_disable() anyway.

Signed-off-by: Dave Martin <Dave.Martin@arm.com>
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
---
 arch/arm64/kernel/fpsimd.c | 25 +++++++++++++++++++------
 arch/arm64/kernel/signal.c |  5 -----
 2 files changed, 19 insertions(+), 11 deletions(-)

diff --git a/arch/arm64/kernel/fpsimd.c b/arch/arm64/kernel/fpsimd.c
index 5ebe73b..62c37f0 100644
--- a/arch/arm64/kernel/fpsimd.c
+++ b/arch/arm64/kernel/fpsimd.c
@@ -550,7 +550,6 @@ int sve_set_vector_length(struct task_struct *task,
 		local_bh_disable();
 
 		fpsimd_save();
-		set_thread_flag(TIF_FOREIGN_FPSTATE);
 	}
 
 	fpsimd_flush_task_state(task);
@@ -816,12 +815,11 @@ asmlinkage void do_sve_acc(unsigned int esr, struct pt_regs *regs)
 	local_bh_disable();
 
 	fpsimd_save();
-	fpsimd_to_sve(current);
 
 	/* Force ret_to_user to reload the registers: */
 	fpsimd_flush_task_state(current);
-	set_thread_flag(TIF_FOREIGN_FPSTATE);
 
+	fpsimd_to_sve(current);
 	if (test_and_set_thread_flag(TIF_SVE))
 		WARN_ON(1); /* SVE access shouldn't have trapped */
 
@@ -894,9 +892,9 @@ void fpsimd_flush_thread(void)
 
 	local_bh_disable();
 
+	fpsimd_flush_task_state(current);
 	memset(&current->thread.uw.fpsimd_state, 0,
 	       sizeof(current->thread.uw.fpsimd_state));
-	fpsimd_flush_task_state(current);
 
 	if (system_supports_sve()) {
 		clear_thread_flag(TIF_SVE);
@@ -933,8 +931,6 @@ void fpsimd_flush_thread(void)
 			current->thread.sve_vl_onexec = 0;
 	}
 
-	set_thread_flag(TIF_FOREIGN_FPSTATE);
-
 	local_bh_enable();
 }
 
@@ -1043,12 +1039,29 @@ void fpsimd_update_current_state(struct user_fpsimd_state const *state)
 
 /*
  * Invalidate live CPU copies of task t's FPSIMD state
+ *
+ * This function may be called with preemption enabled.  The barrier()
+ * ensures that the assignment to fpsimd_cpu is visible to any
+ * preemption/softirq that could race with set_tsk_thread_flag(), so
+ * that TIF_FOREIGN_FPSTATE cannot be spuriously re-cleared.
+ *
+ * The final barrier ensures that TIF_FOREIGN_FPSTATE is seen set by any
+ * subsequent code.
  */
 void fpsimd_flush_task_state(struct task_struct *t)
 {
 	t->thread.fpsimd_cpu = NR_CPUS;
+
+	barrier();
+	set_tsk_thread_flag(t, TIF_FOREIGN_FPSTATE);
+
+	barrier();
 }
 
+/*
+ * Invalidate any task's FPSIMD state that is present on this cpu.
+ * This function must be called with softirqs disabled.
+ */
 void fpsimd_flush_cpu_state(void)
 {
 	__this_cpu_write(fpsimd_last_state.st, NULL);
diff --git a/arch/arm64/kernel/signal.c b/arch/arm64/kernel/signal.c
index 867a7ce..a9b0485 100644
--- a/arch/arm64/kernel/signal.c
+++ b/arch/arm64/kernel/signal.c
@@ -296,11 +296,6 @@ static int restore_sve_fpsimd_context(struct user_ctxs *user)
 	 */
 
 	fpsimd_flush_task_state(current);
-	barrier();
-	/* From now, fpsimd_thread_switch() won't clear TIF_FOREIGN_FPSTATE */
-
-	set_thread_flag(TIF_FOREIGN_FPSTATE);
-	barrier();
 	/* From now, fpsimd_thread_switch() won't touch thread.sve_state */
 
 	sve_alloc(current);
-- 
2.1.4

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

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

* [PATCH v5 02/26] arm64: fpsimd: Always set TIF_FOREIGN_FPSTATE on task state flush
@ 2019-02-18 19:52   ` Dave Martin
  0 siblings, 0 replies; 205+ messages in thread
From: Dave Martin @ 2019-02-18 19:52 UTC (permalink / raw)
  To: kvmarm
  Cc: Peter Maydell, Okamoto Takayuki, Christoffer Dall,
	Ard Biesheuvel, Marc Zyngier, Catalin Marinas, Will Deacon,
	Zhang Lei, Julien Grall, Alex Bennée, linux-arm-kernel

This patch updates fpsimd_flush_task_state() to mirror the new
semantics of fpsimd_flush_cpu_state() introduced by commit
d8ad71fa38a9 ("arm64: fpsimd: Fix TIF_FOREIGN_FPSTATE after
invalidating cpu regs").  Both functions now implicitly set
TIF_FOREIGN_FPSTATE to indicate that the task's FPSIMD state is not
loaded into the cpu.

As a side-effect, fpsimd_flush_task_state() now sets
TIF_FOREIGN_FPSTATE even for non-running tasks.  In the case of
non-running tasks this is not useful but also harmless, because the
flag is live only while the corresponding task is running.  This
function is not called from fast paths, so special-casing this for
the task == current case is not really worth it.

Compiler barriers previously present in restore_sve_fpsimd_context()
are pulled into fpsimd_flush_task_state() so that it can be safely
called with preemption enabled if necessary.

Explicit calls to set TIF_FOREIGN_FPSTATE that accompany
fpsimd_flush_task_state() calls and are now redundant are removed
as appropriate.

fpsimd_flush_task_state() is used to get exclusive access to the
representation of the task's state via task_struct, for the purpose
of replacing the state.  Thus, the call to this function should
happen before manipulating fpsimd_state or sve_state etc. in
task_struct.  Anomalous cases are reordered appropriately in order
to make the code more consistent, although there should be no
functional difference since these cases are protected by
local_bh_disable() anyway.

Signed-off-by: Dave Martin <Dave.Martin@arm.com>
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
---
 arch/arm64/kernel/fpsimd.c | 25 +++++++++++++++++++------
 arch/arm64/kernel/signal.c |  5 -----
 2 files changed, 19 insertions(+), 11 deletions(-)

diff --git a/arch/arm64/kernel/fpsimd.c b/arch/arm64/kernel/fpsimd.c
index 5ebe73b..62c37f0 100644
--- a/arch/arm64/kernel/fpsimd.c
+++ b/arch/arm64/kernel/fpsimd.c
@@ -550,7 +550,6 @@ int sve_set_vector_length(struct task_struct *task,
 		local_bh_disable();
 
 		fpsimd_save();
-		set_thread_flag(TIF_FOREIGN_FPSTATE);
 	}
 
 	fpsimd_flush_task_state(task);
@@ -816,12 +815,11 @@ asmlinkage void do_sve_acc(unsigned int esr, struct pt_regs *regs)
 	local_bh_disable();
 
 	fpsimd_save();
-	fpsimd_to_sve(current);
 
 	/* Force ret_to_user to reload the registers: */
 	fpsimd_flush_task_state(current);
-	set_thread_flag(TIF_FOREIGN_FPSTATE);
 
+	fpsimd_to_sve(current);
 	if (test_and_set_thread_flag(TIF_SVE))
 		WARN_ON(1); /* SVE access shouldn't have trapped */
 
@@ -894,9 +892,9 @@ void fpsimd_flush_thread(void)
 
 	local_bh_disable();
 
+	fpsimd_flush_task_state(current);
 	memset(&current->thread.uw.fpsimd_state, 0,
 	       sizeof(current->thread.uw.fpsimd_state));
-	fpsimd_flush_task_state(current);
 
 	if (system_supports_sve()) {
 		clear_thread_flag(TIF_SVE);
@@ -933,8 +931,6 @@ void fpsimd_flush_thread(void)
 			current->thread.sve_vl_onexec = 0;
 	}
 
-	set_thread_flag(TIF_FOREIGN_FPSTATE);
-
 	local_bh_enable();
 }
 
@@ -1043,12 +1039,29 @@ void fpsimd_update_current_state(struct user_fpsimd_state const *state)
 
 /*
  * Invalidate live CPU copies of task t's FPSIMD state
+ *
+ * This function may be called with preemption enabled.  The barrier()
+ * ensures that the assignment to fpsimd_cpu is visible to any
+ * preemption/softirq that could race with set_tsk_thread_flag(), so
+ * that TIF_FOREIGN_FPSTATE cannot be spuriously re-cleared.
+ *
+ * The final barrier ensures that TIF_FOREIGN_FPSTATE is seen set by any
+ * subsequent code.
  */
 void fpsimd_flush_task_state(struct task_struct *t)
 {
 	t->thread.fpsimd_cpu = NR_CPUS;
+
+	barrier();
+	set_tsk_thread_flag(t, TIF_FOREIGN_FPSTATE);
+
+	barrier();
 }
 
+/*
+ * Invalidate any task's FPSIMD state that is present on this cpu.
+ * This function must be called with softirqs disabled.
+ */
 void fpsimd_flush_cpu_state(void)
 {
 	__this_cpu_write(fpsimd_last_state.st, NULL);
diff --git a/arch/arm64/kernel/signal.c b/arch/arm64/kernel/signal.c
index 867a7ce..a9b0485 100644
--- a/arch/arm64/kernel/signal.c
+++ b/arch/arm64/kernel/signal.c
@@ -296,11 +296,6 @@ static int restore_sve_fpsimd_context(struct user_ctxs *user)
 	 */
 
 	fpsimd_flush_task_state(current);
-	barrier();
-	/* From now, fpsimd_thread_switch() won't clear TIF_FOREIGN_FPSTATE */
-
-	set_thread_flag(TIF_FOREIGN_FPSTATE);
-	barrier();
 	/* From now, fpsimd_thread_switch() won't touch thread.sve_state */
 
 	sve_alloc(current);
-- 
2.1.4


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* [PATCH v5 03/26] KVM: arm64: Delete orphaned declaration for __fpsimd_enabled()
  2019-02-18 19:52 ` Dave Martin
@ 2019-02-18 19:52   ` Dave Martin
  -1 siblings, 0 replies; 205+ messages in thread
From: Dave Martin @ 2019-02-18 19:52 UTC (permalink / raw)
  To: kvmarm
  Cc: Okamoto Takayuki, Christoffer Dall, Ard Biesheuvel, Marc Zyngier,
	Catalin Marinas, Will Deacon, Zhang Lei, linux-arm-kernel

__fpsimd_enabled() no longer exists, but a dangling declaration has
survived in kvm_hyp.h.

This patch gets rid of it.

Signed-off-by: Dave Martin <Dave.Martin@arm.com>
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
---
 arch/arm64/include/asm/kvm_hyp.h | 1 -
 1 file changed, 1 deletion(-)

diff --git a/arch/arm64/include/asm/kvm_hyp.h b/arch/arm64/include/asm/kvm_hyp.h
index a80a7ef..bd7a055 100644
--- a/arch/arm64/include/asm/kvm_hyp.h
+++ b/arch/arm64/include/asm/kvm_hyp.h
@@ -148,7 +148,6 @@ void __debug_switch_to_host(struct kvm_vcpu *vcpu);
 
 void __fpsimd_save_state(struct user_fpsimd_state *fp_regs);
 void __fpsimd_restore_state(struct user_fpsimd_state *fp_regs);
-bool __fpsimd_enabled(void);
 
 void activate_traps_vhe_load(struct kvm_vcpu *vcpu);
 void deactivate_traps_vhe_put(void);
-- 
2.1.4

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

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

* [PATCH v5 03/26] KVM: arm64: Delete orphaned declaration for __fpsimd_enabled()
@ 2019-02-18 19:52   ` Dave Martin
  0 siblings, 0 replies; 205+ messages in thread
From: Dave Martin @ 2019-02-18 19:52 UTC (permalink / raw)
  To: kvmarm
  Cc: Peter Maydell, Okamoto Takayuki, Christoffer Dall,
	Ard Biesheuvel, Marc Zyngier, Catalin Marinas, Will Deacon,
	Zhang Lei, Julien Grall, Alex Bennée, linux-arm-kernel

__fpsimd_enabled() no longer exists, but a dangling declaration has
survived in kvm_hyp.h.

This patch gets rid of it.

Signed-off-by: Dave Martin <Dave.Martin@arm.com>
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
---
 arch/arm64/include/asm/kvm_hyp.h | 1 -
 1 file changed, 1 deletion(-)

diff --git a/arch/arm64/include/asm/kvm_hyp.h b/arch/arm64/include/asm/kvm_hyp.h
index a80a7ef..bd7a055 100644
--- a/arch/arm64/include/asm/kvm_hyp.h
+++ b/arch/arm64/include/asm/kvm_hyp.h
@@ -148,7 +148,6 @@ void __debug_switch_to_host(struct kvm_vcpu *vcpu);
 
 void __fpsimd_save_state(struct user_fpsimd_state *fp_regs);
 void __fpsimd_restore_state(struct user_fpsimd_state *fp_regs);
-bool __fpsimd_enabled(void);
 
 void activate_traps_vhe_load(struct kvm_vcpu *vcpu);
 void deactivate_traps_vhe_put(void);
-- 
2.1.4


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* [PATCH v5 04/26] KVM: arm64: Refactor kvm_arm_num_regs() for easier maintenance
  2019-02-18 19:52 ` Dave Martin
@ 2019-02-18 19:52   ` Dave Martin
  -1 siblings, 0 replies; 205+ messages in thread
From: Dave Martin @ 2019-02-18 19:52 UTC (permalink / raw)
  To: kvmarm
  Cc: Okamoto Takayuki, Christoffer Dall, Ard Biesheuvel, Marc Zyngier,
	Catalin Marinas, Will Deacon, Zhang Lei, linux-arm-kernel

kvm_arm_num_regs() adds together various partial register counts in
a freeform sum expression, which makes it harder than necessary to
read diffs that add, modify or remove a single term in the sum
(which is expected to the common case under maintenance).

This patch refactors the code to add the term one per line, for
maximum readability.

Signed-off-by: Dave Martin <Dave.Martin@arm.com>
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
---
 arch/arm64/kvm/guest.c | 10 ++++++++--
 1 file changed, 8 insertions(+), 2 deletions(-)

diff --git a/arch/arm64/kvm/guest.c b/arch/arm64/kvm/guest.c
index 46eb867..65f4338 100644
--- a/arch/arm64/kvm/guest.c
+++ b/arch/arm64/kvm/guest.c
@@ -312,8 +312,14 @@ static int get_timer_reg(struct kvm_vcpu *vcpu, const struct kvm_one_reg *reg)
  */
 unsigned long kvm_arm_num_regs(struct kvm_vcpu *vcpu)
 {
-	return num_core_regs() + kvm_arm_num_sys_reg_descs(vcpu)
-		+ kvm_arm_get_fw_num_regs(vcpu)	+ NUM_TIMER_REGS;
+	unsigned long res = 0;
+
+	res += num_core_regs();
+	res += kvm_arm_num_sys_reg_descs(vcpu);
+	res += kvm_arm_get_fw_num_regs(vcpu);
+	res += NUM_TIMER_REGS;
+
+	return res;
 }
 
 /**
-- 
2.1.4

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

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

* [PATCH v5 04/26] KVM: arm64: Refactor kvm_arm_num_regs() for easier maintenance
@ 2019-02-18 19:52   ` Dave Martin
  0 siblings, 0 replies; 205+ messages in thread
From: Dave Martin @ 2019-02-18 19:52 UTC (permalink / raw)
  To: kvmarm
  Cc: Peter Maydell, Okamoto Takayuki, Christoffer Dall,
	Ard Biesheuvel, Marc Zyngier, Catalin Marinas, Will Deacon,
	Zhang Lei, Julien Grall, Alex Bennée, linux-arm-kernel

kvm_arm_num_regs() adds together various partial register counts in
a freeform sum expression, which makes it harder than necessary to
read diffs that add, modify or remove a single term in the sum
(which is expected to the common case under maintenance).

This patch refactors the code to add the term one per line, for
maximum readability.

Signed-off-by: Dave Martin <Dave.Martin@arm.com>
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
---
 arch/arm64/kvm/guest.c | 10 ++++++++--
 1 file changed, 8 insertions(+), 2 deletions(-)

diff --git a/arch/arm64/kvm/guest.c b/arch/arm64/kvm/guest.c
index 46eb867..65f4338 100644
--- a/arch/arm64/kvm/guest.c
+++ b/arch/arm64/kvm/guest.c
@@ -312,8 +312,14 @@ static int get_timer_reg(struct kvm_vcpu *vcpu, const struct kvm_one_reg *reg)
  */
 unsigned long kvm_arm_num_regs(struct kvm_vcpu *vcpu)
 {
-	return num_core_regs() + kvm_arm_num_sys_reg_descs(vcpu)
-		+ kvm_arm_get_fw_num_regs(vcpu)	+ NUM_TIMER_REGS;
+	unsigned long res = 0;
+
+	res += num_core_regs();
+	res += kvm_arm_num_sys_reg_descs(vcpu);
+	res += kvm_arm_get_fw_num_regs(vcpu);
+	res += NUM_TIMER_REGS;
+
+	return res;
 }
 
 /**
-- 
2.1.4


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* [PATCH v5 05/26] KVM: arm64: Add missing #include of <linux/bitmap.h> to kvm_host.h
  2019-02-18 19:52 ` Dave Martin
@ 2019-02-18 19:52   ` Dave Martin
  -1 siblings, 0 replies; 205+ messages in thread
From: Dave Martin @ 2019-02-18 19:52 UTC (permalink / raw)
  To: kvmarm
  Cc: Okamoto Takayuki, Christoffer Dall, Ard Biesheuvel, Marc Zyngier,
	Catalin Marinas, Will Deacon, Zhang Lei, linux-arm-kernel

kvm_host.h uses DECLARE_BITMAP() to declare the features member of
struct vcpu_arch, but the corresponding #include for this is
missing.

This patch adds a suitable #include for <linux/bitmap.h>.  Although
the header builds without it today, this should help to avoid
future surprises.

Signed-off-by: Dave Martin <Dave.Martin@arm.com>
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
---
 arch/arm64/include/asm/kvm_host.h | 1 +
 1 file changed, 1 insertion(+)

diff --git a/arch/arm64/include/asm/kvm_host.h b/arch/arm64/include/asm/kvm_host.h
index 7732d0b..84056a4 100644
--- a/arch/arm64/include/asm/kvm_host.h
+++ b/arch/arm64/include/asm/kvm_host.h
@@ -22,6 +22,7 @@
 #ifndef __ARM64_KVM_HOST_H__
 #define __ARM64_KVM_HOST_H__
 
+#include <linux/bitmap.h>
 #include <linux/types.h>
 #include <linux/kvm_types.h>
 #include <asm/cpufeature.h>
-- 
2.1.4

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

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

* [PATCH v5 05/26] KVM: arm64: Add missing #include of <linux/bitmap.h> to kvm_host.h
@ 2019-02-18 19:52   ` Dave Martin
  0 siblings, 0 replies; 205+ messages in thread
From: Dave Martin @ 2019-02-18 19:52 UTC (permalink / raw)
  To: kvmarm
  Cc: Peter Maydell, Okamoto Takayuki, Christoffer Dall,
	Ard Biesheuvel, Marc Zyngier, Catalin Marinas, Will Deacon,
	Zhang Lei, Julien Grall, Alex Bennée, linux-arm-kernel

kvm_host.h uses DECLARE_BITMAP() to declare the features member of
struct vcpu_arch, but the corresponding #include for this is
missing.

This patch adds a suitable #include for <linux/bitmap.h>.  Although
the header builds without it today, this should help to avoid
future surprises.

Signed-off-by: Dave Martin <Dave.Martin@arm.com>
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
---
 arch/arm64/include/asm/kvm_host.h | 1 +
 1 file changed, 1 insertion(+)

diff --git a/arch/arm64/include/asm/kvm_host.h b/arch/arm64/include/asm/kvm_host.h
index 7732d0b..84056a4 100644
--- a/arch/arm64/include/asm/kvm_host.h
+++ b/arch/arm64/include/asm/kvm_host.h
@@ -22,6 +22,7 @@
 #ifndef __ARM64_KVM_HOST_H__
 #define __ARM64_KVM_HOST_H__
 
+#include <linux/bitmap.h>
 #include <linux/types.h>
 #include <linux/kvm_types.h>
 #include <asm/cpufeature.h>
-- 
2.1.4


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* [PATCH v5 06/26] arm64/sve: Check SVE virtualisability
  2019-02-18 19:52 ` Dave Martin
@ 2019-02-18 19:52   ` Dave Martin
  -1 siblings, 0 replies; 205+ messages in thread
From: Dave Martin @ 2019-02-18 19:52 UTC (permalink / raw)
  To: kvmarm
  Cc: Okamoto Takayuki, Christoffer Dall, Ard Biesheuvel, Marc Zyngier,
	Catalin Marinas, Will Deacon, Zhang Lei, linux-arm-kernel

Due to the way the effective SVE vector length is controlled and
trapped at different exception levels, certain mismatches in the
sets of vector lengths supported by different physical CPUs in the
system may prevent straightforward virtualisation of SVE at parity
with the host.

This patch analyses the extent to which SVE can be virtualised
safely without interfering with migration of vcpus between physical
CPUs, and rejects late secondary CPUs that would erode the
situation further.

It is left up to KVM to decide what to do with this information.

Signed-off-by: Dave Martin <Dave.Martin@arm.com>
---
 arch/arm64/include/asm/fpsimd.h |  1 +
 arch/arm64/kernel/cpufeature.c  |  2 +-
 arch/arm64/kernel/fpsimd.c      | 86 ++++++++++++++++++++++++++++++++++-------
 3 files changed, 73 insertions(+), 16 deletions(-)

diff --git a/arch/arm64/include/asm/fpsimd.h b/arch/arm64/include/asm/fpsimd.h
index dd1ad39..964adc9 100644
--- a/arch/arm64/include/asm/fpsimd.h
+++ b/arch/arm64/include/asm/fpsimd.h
@@ -87,6 +87,7 @@ extern void sve_kernel_enable(const struct arm64_cpu_capabilities *__unused);
 extern u64 read_zcr_features(void);
 
 extern int __ro_after_init sve_max_vl;
+extern int __ro_after_init sve_max_virtualisable_vl;
 
 #ifdef CONFIG_ARM64_SVE
 
diff --git a/arch/arm64/kernel/cpufeature.c b/arch/arm64/kernel/cpufeature.c
index f6d84e2..5eaacb4 100644
--- a/arch/arm64/kernel/cpufeature.c
+++ b/arch/arm64/kernel/cpufeature.c
@@ -1825,7 +1825,7 @@ static void verify_sve_features(void)
 	unsigned int len = zcr & ZCR_ELx_LEN_MASK;
 
 	if (len < safe_len || sve_verify_vq_map()) {
-		pr_crit("CPU%d: SVE: required vector length(s) missing\n",
+		pr_crit("CPU%d: SVE: vector length support mismatch\n",
 			smp_processor_id());
 		cpu_die_early();
 	}
diff --git a/arch/arm64/kernel/fpsimd.c b/arch/arm64/kernel/fpsimd.c
index 62c37f0..64729e2 100644
--- a/arch/arm64/kernel/fpsimd.c
+++ b/arch/arm64/kernel/fpsimd.c
@@ -18,6 +18,7 @@
  */
 
 #include <linux/bitmap.h>
+#include <linux/bitops.h>
 #include <linux/bottom_half.h>
 #include <linux/bug.h>
 #include <linux/cache.h>
@@ -48,6 +49,7 @@
 #include <asm/sigcontext.h>
 #include <asm/sysreg.h>
 #include <asm/traps.h>
+#include <asm/virt.h>
 
 #define FPEXC_IOF	(1 << 0)
 #define FPEXC_DZF	(1 << 1)
@@ -130,14 +132,18 @@ static int sve_default_vl = -1;
 
 /* Maximum supported vector length across all CPUs (initially poisoned) */
 int __ro_after_init sve_max_vl = SVE_VL_MIN;
+int __ro_after_init sve_max_virtualisable_vl = SVE_VL_MIN;
 /* Set of available vector lengths, as vq_to_bit(vq): */
 static __ro_after_init DECLARE_BITMAP(sve_vq_map, SVE_VQ_MAX);
+/* Set of vector lengths present on at least one cpu: */
+static __ro_after_init DECLARE_BITMAP(sve_vq_partial_map, SVE_VQ_MAX);
 static void __percpu *efi_sve_state;
 
 #else /* ! CONFIG_ARM64_SVE */
 
 /* Dummy declaration for code that will be optimised out: */
 extern __ro_after_init DECLARE_BITMAP(sve_vq_map, SVE_VQ_MAX);
+extern __ro_after_init DECLARE_BITMAP(sve_vq_partial_map, SVE_VQ_MAX);
 extern void __percpu *efi_sve_state;
 
 #endif /* ! CONFIG_ARM64_SVE */
@@ -623,12 +629,6 @@ int sve_get_current_vl(void)
 	return sve_prctl_status(0);
 }
 
-/*
- * Bitmap for temporary storage of the per-CPU set of supported vector lengths
- * during secondary boot.
- */
-static DECLARE_BITMAP(sve_secondary_vq_map, SVE_VQ_MAX);
-
 static void sve_probe_vqs(DECLARE_BITMAP(map, SVE_VQ_MAX))
 {
 	unsigned int vq, vl;
@@ -650,6 +650,7 @@ static void sve_probe_vqs(DECLARE_BITMAP(map, SVE_VQ_MAX))
 void __init sve_init_vq_map(void)
 {
 	sve_probe_vqs(sve_vq_map);
+	bitmap_copy(sve_vq_partial_map, sve_vq_map, SVE_VQ_MAX);
 }
 
 /*
@@ -658,25 +659,58 @@ void __init sve_init_vq_map(void)
  */
 void sve_update_vq_map(void)
 {
-	sve_probe_vqs(sve_secondary_vq_map);
-	bitmap_and(sve_vq_map, sve_vq_map, sve_secondary_vq_map, SVE_VQ_MAX);
+	DECLARE_BITMAP(tmp_map, SVE_VQ_MAX);
+
+	sve_probe_vqs(tmp_map);
+	bitmap_and(sve_vq_map, sve_vq_map, tmp_map, SVE_VQ_MAX);
+	bitmap_or(sve_vq_partial_map, sve_vq_partial_map, tmp_map, SVE_VQ_MAX);
 }
 
 /* Check whether the current CPU supports all VQs in the committed set */
 int sve_verify_vq_map(void)
 {
-	int ret = 0;
+	DECLARE_BITMAP(tmp_map, SVE_VQ_MAX);
+	unsigned long b;
 
-	sve_probe_vqs(sve_secondary_vq_map);
-	bitmap_andnot(sve_secondary_vq_map, sve_vq_map, sve_secondary_vq_map,
-		      SVE_VQ_MAX);
-	if (!bitmap_empty(sve_secondary_vq_map, SVE_VQ_MAX)) {
+	sve_probe_vqs(tmp_map);
+
+	bitmap_complement(tmp_map, tmp_map, SVE_VQ_MAX);
+	if (bitmap_intersects(tmp_map, sve_vq_map, SVE_VQ_MAX)) {
 		pr_warn("SVE: cpu%d: Required vector length(s) missing\n",
 			smp_processor_id());
-		ret = -EINVAL;
+		return -EINVAL;
 	}
 
-	return ret;
+	if (!IS_ENABLED(CONFIG_KVM) || !is_hyp_mode_available())
+		return 0;
+
+	/*
+	 * For KVM, it is necessary to ensure that this CPU doesn't
+	 * support any vector length that guests may have probed as
+	 * unsupported.
+	 */
+
+	/* Recover the set of supported VQs: */
+	bitmap_complement(tmp_map, tmp_map, SVE_VQ_MAX);
+	/* Find VQs supported that are not globally supported: */
+	bitmap_andnot(tmp_map, tmp_map, sve_vq_map, SVE_VQ_MAX);
+
+	/* Find the lowest such VQ, if any: */
+	b = find_last_bit(tmp_map, SVE_VQ_MAX);
+	if (b >= SVE_VQ_MAX)
+		return 0; /* no mismatches */
+
+	/*
+	 * Mismatches above sve_max_virtualisable_vl are fine, since
+	 * no guest is allowed to configure ZCR_EL2.LEN to exceed this:
+	 */
+	if (sve_vl_from_vq(bit_to_vq(b)) <= sve_max_virtualisable_vl) {
+		pr_warn("SVE: cpu%d: Unsupported vector length(s) present\n",
+			smp_processor_id());
+		return -EINVAL;
+	}
+
+	return 0;
 }
 
 static void __init sve_efi_setup(void)
@@ -743,6 +777,8 @@ u64 read_zcr_features(void)
 void __init sve_setup(void)
 {
 	u64 zcr;
+	DECLARE_BITMAP(tmp_map, SVE_VQ_MAX);
+	unsigned long b;
 
 	if (!system_supports_sve())
 		return;
@@ -771,11 +807,31 @@ void __init sve_setup(void)
 	 */
 	sve_default_vl = find_supported_vector_length(64);
 
+	bitmap_andnot(tmp_map, sve_vq_partial_map, sve_vq_map,
+		      SVE_VQ_MAX);
+
+	b = find_last_bit(tmp_map, SVE_VQ_MAX);
+	if (b >= SVE_VQ_MAX)
+		/* No non-virtualisable VLs found */
+		sve_max_virtualisable_vl = SVE_VQ_MAX;
+	else if (WARN_ON(b == SVE_VQ_MAX - 1))
+		/* No virtualisable VLs?  This is architecturally forbidden. */
+		sve_max_virtualisable_vl = SVE_VQ_MIN;
+	else /* b + 1 < SVE_VQ_MAX */
+		sve_max_virtualisable_vl = sve_vl_from_vq(bit_to_vq(b + 1));
+
+	if (sve_max_virtualisable_vl > sve_max_vl)
+		sve_max_virtualisable_vl = sve_max_vl;
+
 	pr_info("SVE: maximum available vector length %u bytes per vector\n",
 		sve_max_vl);
 	pr_info("SVE: default vector length %u bytes per vector\n",
 		sve_default_vl);
 
+	/* KVM decides whether to support mismatched systems. Just warn here: */
+	if (sve_max_virtualisable_vl < sve_max_vl)
+		pr_info("SVE: unvirtualisable vector lengths present\n");
+
 	sve_efi_setup();
 }
 
-- 
2.1.4

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

* [PATCH v5 06/26] arm64/sve: Check SVE virtualisability
@ 2019-02-18 19:52   ` Dave Martin
  0 siblings, 0 replies; 205+ messages in thread
From: Dave Martin @ 2019-02-18 19:52 UTC (permalink / raw)
  To: kvmarm
  Cc: Peter Maydell, Okamoto Takayuki, Christoffer Dall,
	Ard Biesheuvel, Marc Zyngier, Catalin Marinas, Will Deacon,
	Zhang Lei, Julien Grall, Alex Bennée, linux-arm-kernel

Due to the way the effective SVE vector length is controlled and
trapped at different exception levels, certain mismatches in the
sets of vector lengths supported by different physical CPUs in the
system may prevent straightforward virtualisation of SVE at parity
with the host.

This patch analyses the extent to which SVE can be virtualised
safely without interfering with migration of vcpus between physical
CPUs, and rejects late secondary CPUs that would erode the
situation further.

It is left up to KVM to decide what to do with this information.

Signed-off-by: Dave Martin <Dave.Martin@arm.com>
---
 arch/arm64/include/asm/fpsimd.h |  1 +
 arch/arm64/kernel/cpufeature.c  |  2 +-
 arch/arm64/kernel/fpsimd.c      | 86 ++++++++++++++++++++++++++++++++++-------
 3 files changed, 73 insertions(+), 16 deletions(-)

diff --git a/arch/arm64/include/asm/fpsimd.h b/arch/arm64/include/asm/fpsimd.h
index dd1ad39..964adc9 100644
--- a/arch/arm64/include/asm/fpsimd.h
+++ b/arch/arm64/include/asm/fpsimd.h
@@ -87,6 +87,7 @@ extern void sve_kernel_enable(const struct arm64_cpu_capabilities *__unused);
 extern u64 read_zcr_features(void);
 
 extern int __ro_after_init sve_max_vl;
+extern int __ro_after_init sve_max_virtualisable_vl;
 
 #ifdef CONFIG_ARM64_SVE
 
diff --git a/arch/arm64/kernel/cpufeature.c b/arch/arm64/kernel/cpufeature.c
index f6d84e2..5eaacb4 100644
--- a/arch/arm64/kernel/cpufeature.c
+++ b/arch/arm64/kernel/cpufeature.c
@@ -1825,7 +1825,7 @@ static void verify_sve_features(void)
 	unsigned int len = zcr & ZCR_ELx_LEN_MASK;
 
 	if (len < safe_len || sve_verify_vq_map()) {
-		pr_crit("CPU%d: SVE: required vector length(s) missing\n",
+		pr_crit("CPU%d: SVE: vector length support mismatch\n",
 			smp_processor_id());
 		cpu_die_early();
 	}
diff --git a/arch/arm64/kernel/fpsimd.c b/arch/arm64/kernel/fpsimd.c
index 62c37f0..64729e2 100644
--- a/arch/arm64/kernel/fpsimd.c
+++ b/arch/arm64/kernel/fpsimd.c
@@ -18,6 +18,7 @@
  */
 
 #include <linux/bitmap.h>
+#include <linux/bitops.h>
 #include <linux/bottom_half.h>
 #include <linux/bug.h>
 #include <linux/cache.h>
@@ -48,6 +49,7 @@
 #include <asm/sigcontext.h>
 #include <asm/sysreg.h>
 #include <asm/traps.h>
+#include <asm/virt.h>
 
 #define FPEXC_IOF	(1 << 0)
 #define FPEXC_DZF	(1 << 1)
@@ -130,14 +132,18 @@ static int sve_default_vl = -1;
 
 /* Maximum supported vector length across all CPUs (initially poisoned) */
 int __ro_after_init sve_max_vl = SVE_VL_MIN;
+int __ro_after_init sve_max_virtualisable_vl = SVE_VL_MIN;
 /* Set of available vector lengths, as vq_to_bit(vq): */
 static __ro_after_init DECLARE_BITMAP(sve_vq_map, SVE_VQ_MAX);
+/* Set of vector lengths present on at least one cpu: */
+static __ro_after_init DECLARE_BITMAP(sve_vq_partial_map, SVE_VQ_MAX);
 static void __percpu *efi_sve_state;
 
 #else /* ! CONFIG_ARM64_SVE */
 
 /* Dummy declaration for code that will be optimised out: */
 extern __ro_after_init DECLARE_BITMAP(sve_vq_map, SVE_VQ_MAX);
+extern __ro_after_init DECLARE_BITMAP(sve_vq_partial_map, SVE_VQ_MAX);
 extern void __percpu *efi_sve_state;
 
 #endif /* ! CONFIG_ARM64_SVE */
@@ -623,12 +629,6 @@ int sve_get_current_vl(void)
 	return sve_prctl_status(0);
 }
 
-/*
- * Bitmap for temporary storage of the per-CPU set of supported vector lengths
- * during secondary boot.
- */
-static DECLARE_BITMAP(sve_secondary_vq_map, SVE_VQ_MAX);
-
 static void sve_probe_vqs(DECLARE_BITMAP(map, SVE_VQ_MAX))
 {
 	unsigned int vq, vl;
@@ -650,6 +650,7 @@ static void sve_probe_vqs(DECLARE_BITMAP(map, SVE_VQ_MAX))
 void __init sve_init_vq_map(void)
 {
 	sve_probe_vqs(sve_vq_map);
+	bitmap_copy(sve_vq_partial_map, sve_vq_map, SVE_VQ_MAX);
 }
 
 /*
@@ -658,25 +659,58 @@ void __init sve_init_vq_map(void)
  */
 void sve_update_vq_map(void)
 {
-	sve_probe_vqs(sve_secondary_vq_map);
-	bitmap_and(sve_vq_map, sve_vq_map, sve_secondary_vq_map, SVE_VQ_MAX);
+	DECLARE_BITMAP(tmp_map, SVE_VQ_MAX);
+
+	sve_probe_vqs(tmp_map);
+	bitmap_and(sve_vq_map, sve_vq_map, tmp_map, SVE_VQ_MAX);
+	bitmap_or(sve_vq_partial_map, sve_vq_partial_map, tmp_map, SVE_VQ_MAX);
 }
 
 /* Check whether the current CPU supports all VQs in the committed set */
 int sve_verify_vq_map(void)
 {
-	int ret = 0;
+	DECLARE_BITMAP(tmp_map, SVE_VQ_MAX);
+	unsigned long b;
 
-	sve_probe_vqs(sve_secondary_vq_map);
-	bitmap_andnot(sve_secondary_vq_map, sve_vq_map, sve_secondary_vq_map,
-		      SVE_VQ_MAX);
-	if (!bitmap_empty(sve_secondary_vq_map, SVE_VQ_MAX)) {
+	sve_probe_vqs(tmp_map);
+
+	bitmap_complement(tmp_map, tmp_map, SVE_VQ_MAX);
+	if (bitmap_intersects(tmp_map, sve_vq_map, SVE_VQ_MAX)) {
 		pr_warn("SVE: cpu%d: Required vector length(s) missing\n",
 			smp_processor_id());
-		ret = -EINVAL;
+		return -EINVAL;
 	}
 
-	return ret;
+	if (!IS_ENABLED(CONFIG_KVM) || !is_hyp_mode_available())
+		return 0;
+
+	/*
+	 * For KVM, it is necessary to ensure that this CPU doesn't
+	 * support any vector length that guests may have probed as
+	 * unsupported.
+	 */
+
+	/* Recover the set of supported VQs: */
+	bitmap_complement(tmp_map, tmp_map, SVE_VQ_MAX);
+	/* Find VQs supported that are not globally supported: */
+	bitmap_andnot(tmp_map, tmp_map, sve_vq_map, SVE_VQ_MAX);
+
+	/* Find the lowest such VQ, if any: */
+	b = find_last_bit(tmp_map, SVE_VQ_MAX);
+	if (b >= SVE_VQ_MAX)
+		return 0; /* no mismatches */
+
+	/*
+	 * Mismatches above sve_max_virtualisable_vl are fine, since
+	 * no guest is allowed to configure ZCR_EL2.LEN to exceed this:
+	 */
+	if (sve_vl_from_vq(bit_to_vq(b)) <= sve_max_virtualisable_vl) {
+		pr_warn("SVE: cpu%d: Unsupported vector length(s) present\n",
+			smp_processor_id());
+		return -EINVAL;
+	}
+
+	return 0;
 }
 
 static void __init sve_efi_setup(void)
@@ -743,6 +777,8 @@ u64 read_zcr_features(void)
 void __init sve_setup(void)
 {
 	u64 zcr;
+	DECLARE_BITMAP(tmp_map, SVE_VQ_MAX);
+	unsigned long b;
 
 	if (!system_supports_sve())
 		return;
@@ -771,11 +807,31 @@ void __init sve_setup(void)
 	 */
 	sve_default_vl = find_supported_vector_length(64);
 
+	bitmap_andnot(tmp_map, sve_vq_partial_map, sve_vq_map,
+		      SVE_VQ_MAX);
+
+	b = find_last_bit(tmp_map, SVE_VQ_MAX);
+	if (b >= SVE_VQ_MAX)
+		/* No non-virtualisable VLs found */
+		sve_max_virtualisable_vl = SVE_VQ_MAX;
+	else if (WARN_ON(b == SVE_VQ_MAX - 1))
+		/* No virtualisable VLs?  This is architecturally forbidden. */
+		sve_max_virtualisable_vl = SVE_VQ_MIN;
+	else /* b + 1 < SVE_VQ_MAX */
+		sve_max_virtualisable_vl = sve_vl_from_vq(bit_to_vq(b + 1));
+
+	if (sve_max_virtualisable_vl > sve_max_vl)
+		sve_max_virtualisable_vl = sve_max_vl;
+
 	pr_info("SVE: maximum available vector length %u bytes per vector\n",
 		sve_max_vl);
 	pr_info("SVE: default vector length %u bytes per vector\n",
 		sve_default_vl);
 
+	/* KVM decides whether to support mismatched systems. Just warn here: */
+	if (sve_max_virtualisable_vl < sve_max_vl)
+		pr_info("SVE: unvirtualisable vector lengths present\n");
+
 	sve_efi_setup();
 }
 
-- 
2.1.4


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* [PATCH v5 07/26] arm64/sve: Clarify role of the VQ map maintenance functions
  2019-02-18 19:52 ` Dave Martin
@ 2019-02-18 19:52   ` Dave Martin
  -1 siblings, 0 replies; 205+ messages in thread
From: Dave Martin @ 2019-02-18 19:52 UTC (permalink / raw)
  To: kvmarm
  Cc: Okamoto Takayuki, Christoffer Dall, Ard Biesheuvel, Marc Zyngier,
	Catalin Marinas, Will Deacon, Zhang Lei, linux-arm-kernel

The roles of sve_init_vq_map(), sve_update_vq_map() and
sve_verify_vq_map() are highly non-obvious to anyone who has not dug
through cpufeatures.c in detail.

Since the way these functions interact with each other is more
important here than a full understanding of the cpufeatures code, this
patch adds comments to make the functions' roles clearer.

No functional change.

Signed-off-by: Dave Martin <Dave.Martin@arm.com>
---
 arch/arm64/kernel/fpsimd.c | 10 +++++++++-
 1 file changed, 9 insertions(+), 1 deletion(-)

diff --git a/arch/arm64/kernel/fpsimd.c b/arch/arm64/kernel/fpsimd.c
index 64729e2..92c2331 100644
--- a/arch/arm64/kernel/fpsimd.c
+++ b/arch/arm64/kernel/fpsimd.c
@@ -647,6 +647,10 @@ static void sve_probe_vqs(DECLARE_BITMAP(map, SVE_VQ_MAX))
 	}
 }
 
+/*
+ * Initialise the set of known supported VQs for the boot CPU.
+ * This is called during kernel boot, before secondary CPUs are brought up.
+ */
 void __init sve_init_vq_map(void)
 {
 	sve_probe_vqs(sve_vq_map);
@@ -656,6 +660,7 @@ void __init sve_init_vq_map(void)
 /*
  * If we haven't committed to the set of supported VQs yet, filter out
  * those not supported by the current CPU.
+ * This function is called during the bring-up of early secondary CPUs only.
  */
 void sve_update_vq_map(void)
 {
@@ -666,7 +671,10 @@ void sve_update_vq_map(void)
 	bitmap_or(sve_vq_partial_map, sve_vq_partial_map, tmp_map, SVE_VQ_MAX);
 }
 
-/* Check whether the current CPU supports all VQs in the committed set */
+/*
+ * Check whether the current CPU supports all VQs in the committed set.
+ * This function is called during the bring-up of late secondary CPUs only.
+ */
 int sve_verify_vq_map(void)
 {
 	DECLARE_BITMAP(tmp_map, SVE_VQ_MAX);
-- 
2.1.4

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

* [PATCH v5 07/26] arm64/sve: Clarify role of the VQ map maintenance functions
@ 2019-02-18 19:52   ` Dave Martin
  0 siblings, 0 replies; 205+ messages in thread
From: Dave Martin @ 2019-02-18 19:52 UTC (permalink / raw)
  To: kvmarm
  Cc: Peter Maydell, Okamoto Takayuki, Christoffer Dall,
	Ard Biesheuvel, Marc Zyngier, Catalin Marinas, Will Deacon,
	Zhang Lei, Julien Grall, Alex Bennée, linux-arm-kernel

The roles of sve_init_vq_map(), sve_update_vq_map() and
sve_verify_vq_map() are highly non-obvious to anyone who has not dug
through cpufeatures.c in detail.

Since the way these functions interact with each other is more
important here than a full understanding of the cpufeatures code, this
patch adds comments to make the functions' roles clearer.

No functional change.

Signed-off-by: Dave Martin <Dave.Martin@arm.com>
---
 arch/arm64/kernel/fpsimd.c | 10 +++++++++-
 1 file changed, 9 insertions(+), 1 deletion(-)

diff --git a/arch/arm64/kernel/fpsimd.c b/arch/arm64/kernel/fpsimd.c
index 64729e2..92c2331 100644
--- a/arch/arm64/kernel/fpsimd.c
+++ b/arch/arm64/kernel/fpsimd.c
@@ -647,6 +647,10 @@ static void sve_probe_vqs(DECLARE_BITMAP(map, SVE_VQ_MAX))
 	}
 }
 
+/*
+ * Initialise the set of known supported VQs for the boot CPU.
+ * This is called during kernel boot, before secondary CPUs are brought up.
+ */
 void __init sve_init_vq_map(void)
 {
 	sve_probe_vqs(sve_vq_map);
@@ -656,6 +660,7 @@ void __init sve_init_vq_map(void)
 /*
  * If we haven't committed to the set of supported VQs yet, filter out
  * those not supported by the current CPU.
+ * This function is called during the bring-up of early secondary CPUs only.
  */
 void sve_update_vq_map(void)
 {
@@ -666,7 +671,10 @@ void sve_update_vq_map(void)
 	bitmap_or(sve_vq_partial_map, sve_vq_partial_map, tmp_map, SVE_VQ_MAX);
 }
 
-/* Check whether the current CPU supports all VQs in the committed set */
+/*
+ * Check whether the current CPU supports all VQs in the committed set.
+ * This function is called during the bring-up of late secondary CPUs only.
+ */
 int sve_verify_vq_map(void)
 {
 	DECLARE_BITMAP(tmp_map, SVE_VQ_MAX);
-- 
2.1.4


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* [PATCH v5 08/26] arm64/sve: Enable SVE state tracking for non-task contexts
  2019-02-18 19:52 ` Dave Martin
@ 2019-02-18 19:52   ` Dave Martin
  -1 siblings, 0 replies; 205+ messages in thread
From: Dave Martin @ 2019-02-18 19:52 UTC (permalink / raw)
  To: kvmarm
  Cc: Okamoto Takayuki, Christoffer Dall, Ard Biesheuvel, Marc Zyngier,
	Catalin Marinas, Will Deacon, Zhang Lei, linux-arm-kernel

The current FPSIMD/SVE context handling support for non-task (i.e.,
KVM vcpu) contexts does not take SVE into account.  This means that
only task contexts can safely use SVE at present.

In preparation for enabling KVM guests to use SVE, it is necessary
to keep track of SVE state for non-task contexts too.

This patch adds the necessary support, removing assumptions from
the context switch code about the location of the SVE context
storage.

When binding a vcpu context, its vector length is arbitrarily
specified as SVE_VL_MIN for now.  In any case, because TIF_SVE is
presently cleared at vcpu context bind time, the specified vector
length will not be used for anything yet.  In later patches TIF_SVE
will be set here as appropriate, and the appropriate maximum vector
length for the vcpu will be passed when binding.

Signed-off-by: Dave Martin <Dave.Martin@arm.com>
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
---
 arch/arm64/include/asm/fpsimd.h |  3 ++-
 arch/arm64/kernel/fpsimd.c      | 20 +++++++++++++++-----
 arch/arm64/kvm/fpsimd.c         |  5 ++++-
 3 files changed, 21 insertions(+), 7 deletions(-)

diff --git a/arch/arm64/include/asm/fpsimd.h b/arch/arm64/include/asm/fpsimd.h
index 964adc9..df7a143 100644
--- a/arch/arm64/include/asm/fpsimd.h
+++ b/arch/arm64/include/asm/fpsimd.h
@@ -56,7 +56,8 @@ extern void fpsimd_restore_current_state(void);
 extern void fpsimd_update_current_state(struct user_fpsimd_state const *state);
 
 extern void fpsimd_bind_task_to_cpu(void);
-extern void fpsimd_bind_state_to_cpu(struct user_fpsimd_state *state);
+extern void fpsimd_bind_state_to_cpu(struct user_fpsimd_state *state,
+				     void *sve_state, unsigned int sve_vl);
 
 extern void fpsimd_flush_task_state(struct task_struct *target);
 extern void fpsimd_flush_cpu_state(void);
diff --git a/arch/arm64/kernel/fpsimd.c b/arch/arm64/kernel/fpsimd.c
index 92c2331..09ee264 100644
--- a/arch/arm64/kernel/fpsimd.c
+++ b/arch/arm64/kernel/fpsimd.c
@@ -121,6 +121,8 @@
  */
 struct fpsimd_last_state_struct {
 	struct user_fpsimd_state *st;
+	void *sve_state;
+	unsigned int sve_vl;
 };
 
 static DEFINE_PER_CPU(struct fpsimd_last_state_struct, fpsimd_last_state);
@@ -241,14 +243,15 @@ static void task_fpsimd_load(void)
  */
 void fpsimd_save(void)
 {
-	struct user_fpsimd_state *st = __this_cpu_read(fpsimd_last_state.st);
+	struct fpsimd_last_state_struct const *last =
+		this_cpu_ptr(&fpsimd_last_state);
 	/* set by fpsimd_bind_task_to_cpu() or fpsimd_bind_state_to_cpu() */
 
 	WARN_ON(!in_softirq() && !irqs_disabled());
 
 	if (!test_thread_flag(TIF_FOREIGN_FPSTATE)) {
 		if (system_supports_sve() && test_thread_flag(TIF_SVE)) {
-			if (WARN_ON(sve_get_vl() != current->thread.sve_vl)) {
+			if (WARN_ON(sve_get_vl() != last->sve_vl)) {
 				/*
 				 * Can't save the user regs, so current would
 				 * re-enter user with corrupt state.
@@ -258,9 +261,11 @@ void fpsimd_save(void)
 				return;
 			}
 
-			sve_save_state(sve_pffr(&current->thread), &st->fpsr);
+			sve_save_state((char *)last->sve_state +
+						sve_ffr_offset(last->sve_vl),
+				       &last->st->fpsr);
 		} else
-			fpsimd_save_state(st);
+			fpsimd_save_state(last->st);
 	}
 }
 
@@ -1034,6 +1039,8 @@ void fpsimd_bind_task_to_cpu(void)
 		this_cpu_ptr(&fpsimd_last_state);
 
 	last->st = &current->thread.uw.fpsimd_state;
+	last->sve_state = current->thread.sve_state;
+	last->sve_vl = current->thread.sve_vl;
 	current->thread.fpsimd_cpu = smp_processor_id();
 
 	if (system_supports_sve()) {
@@ -1047,7 +1054,8 @@ void fpsimd_bind_task_to_cpu(void)
 	}
 }
 
-void fpsimd_bind_state_to_cpu(struct user_fpsimd_state *st)
+void fpsimd_bind_state_to_cpu(struct user_fpsimd_state *st, void *sve_state,
+			      unsigned int sve_vl)
 {
 	struct fpsimd_last_state_struct *last =
 		this_cpu_ptr(&fpsimd_last_state);
@@ -1055,6 +1063,8 @@ void fpsimd_bind_state_to_cpu(struct user_fpsimd_state *st)
 	WARN_ON(!in_softirq() && !irqs_disabled());
 
 	last->st = st;
+	last->sve_state = sve_state;
+	last->sve_vl = sve_vl;
 }
 
 /*
diff --git a/arch/arm64/kvm/fpsimd.c b/arch/arm64/kvm/fpsimd.c
index aac7808..1cf4f02 100644
--- a/arch/arm64/kvm/fpsimd.c
+++ b/arch/arm64/kvm/fpsimd.c
@@ -9,6 +9,7 @@
 #include <linux/sched.h>
 #include <linux/thread_info.h>
 #include <linux/kvm_host.h>
+#include <asm/fpsimd.h>
 #include <asm/kvm_asm.h>
 #include <asm/kvm_host.h>
 #include <asm/kvm_mmu.h>
@@ -85,7 +86,9 @@ void kvm_arch_vcpu_ctxsync_fp(struct kvm_vcpu *vcpu)
 	WARN_ON_ONCE(!irqs_disabled());
 
 	if (vcpu->arch.flags & KVM_ARM64_FP_ENABLED) {
-		fpsimd_bind_state_to_cpu(&vcpu->arch.ctxt.gp_regs.fp_regs);
+		fpsimd_bind_state_to_cpu(&vcpu->arch.ctxt.gp_regs.fp_regs,
+					 NULL, SVE_VL_MIN);
+
 		clear_thread_flag(TIF_FOREIGN_FPSTATE);
 		clear_thread_flag(TIF_SVE);
 	}
-- 
2.1.4

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

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

* [PATCH v5 08/26] arm64/sve: Enable SVE state tracking for non-task contexts
@ 2019-02-18 19:52   ` Dave Martin
  0 siblings, 0 replies; 205+ messages in thread
From: Dave Martin @ 2019-02-18 19:52 UTC (permalink / raw)
  To: kvmarm
  Cc: Peter Maydell, Okamoto Takayuki, Christoffer Dall,
	Ard Biesheuvel, Marc Zyngier, Catalin Marinas, Will Deacon,
	Zhang Lei, Julien Grall, Alex Bennée, linux-arm-kernel

The current FPSIMD/SVE context handling support for non-task (i.e.,
KVM vcpu) contexts does not take SVE into account.  This means that
only task contexts can safely use SVE at present.

In preparation for enabling KVM guests to use SVE, it is necessary
to keep track of SVE state for non-task contexts too.

This patch adds the necessary support, removing assumptions from
the context switch code about the location of the SVE context
storage.

When binding a vcpu context, its vector length is arbitrarily
specified as SVE_VL_MIN for now.  In any case, because TIF_SVE is
presently cleared at vcpu context bind time, the specified vector
length will not be used for anything yet.  In later patches TIF_SVE
will be set here as appropriate, and the appropriate maximum vector
length for the vcpu will be passed when binding.

Signed-off-by: Dave Martin <Dave.Martin@arm.com>
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
---
 arch/arm64/include/asm/fpsimd.h |  3 ++-
 arch/arm64/kernel/fpsimd.c      | 20 +++++++++++++++-----
 arch/arm64/kvm/fpsimd.c         |  5 ++++-
 3 files changed, 21 insertions(+), 7 deletions(-)

diff --git a/arch/arm64/include/asm/fpsimd.h b/arch/arm64/include/asm/fpsimd.h
index 964adc9..df7a143 100644
--- a/arch/arm64/include/asm/fpsimd.h
+++ b/arch/arm64/include/asm/fpsimd.h
@@ -56,7 +56,8 @@ extern void fpsimd_restore_current_state(void);
 extern void fpsimd_update_current_state(struct user_fpsimd_state const *state);
 
 extern void fpsimd_bind_task_to_cpu(void);
-extern void fpsimd_bind_state_to_cpu(struct user_fpsimd_state *state);
+extern void fpsimd_bind_state_to_cpu(struct user_fpsimd_state *state,
+				     void *sve_state, unsigned int sve_vl);
 
 extern void fpsimd_flush_task_state(struct task_struct *target);
 extern void fpsimd_flush_cpu_state(void);
diff --git a/arch/arm64/kernel/fpsimd.c b/arch/arm64/kernel/fpsimd.c
index 92c2331..09ee264 100644
--- a/arch/arm64/kernel/fpsimd.c
+++ b/arch/arm64/kernel/fpsimd.c
@@ -121,6 +121,8 @@
  */
 struct fpsimd_last_state_struct {
 	struct user_fpsimd_state *st;
+	void *sve_state;
+	unsigned int sve_vl;
 };
 
 static DEFINE_PER_CPU(struct fpsimd_last_state_struct, fpsimd_last_state);
@@ -241,14 +243,15 @@ static void task_fpsimd_load(void)
  */
 void fpsimd_save(void)
 {
-	struct user_fpsimd_state *st = __this_cpu_read(fpsimd_last_state.st);
+	struct fpsimd_last_state_struct const *last =
+		this_cpu_ptr(&fpsimd_last_state);
 	/* set by fpsimd_bind_task_to_cpu() or fpsimd_bind_state_to_cpu() */
 
 	WARN_ON(!in_softirq() && !irqs_disabled());
 
 	if (!test_thread_flag(TIF_FOREIGN_FPSTATE)) {
 		if (system_supports_sve() && test_thread_flag(TIF_SVE)) {
-			if (WARN_ON(sve_get_vl() != current->thread.sve_vl)) {
+			if (WARN_ON(sve_get_vl() != last->sve_vl)) {
 				/*
 				 * Can't save the user regs, so current would
 				 * re-enter user with corrupt state.
@@ -258,9 +261,11 @@ void fpsimd_save(void)
 				return;
 			}
 
-			sve_save_state(sve_pffr(&current->thread), &st->fpsr);
+			sve_save_state((char *)last->sve_state +
+						sve_ffr_offset(last->sve_vl),
+				       &last->st->fpsr);
 		} else
-			fpsimd_save_state(st);
+			fpsimd_save_state(last->st);
 	}
 }
 
@@ -1034,6 +1039,8 @@ void fpsimd_bind_task_to_cpu(void)
 		this_cpu_ptr(&fpsimd_last_state);
 
 	last->st = &current->thread.uw.fpsimd_state;
+	last->sve_state = current->thread.sve_state;
+	last->sve_vl = current->thread.sve_vl;
 	current->thread.fpsimd_cpu = smp_processor_id();
 
 	if (system_supports_sve()) {
@@ -1047,7 +1054,8 @@ void fpsimd_bind_task_to_cpu(void)
 	}
 }
 
-void fpsimd_bind_state_to_cpu(struct user_fpsimd_state *st)
+void fpsimd_bind_state_to_cpu(struct user_fpsimd_state *st, void *sve_state,
+			      unsigned int sve_vl)
 {
 	struct fpsimd_last_state_struct *last =
 		this_cpu_ptr(&fpsimd_last_state);
@@ -1055,6 +1063,8 @@ void fpsimd_bind_state_to_cpu(struct user_fpsimd_state *st)
 	WARN_ON(!in_softirq() && !irqs_disabled());
 
 	last->st = st;
+	last->sve_state = sve_state;
+	last->sve_vl = sve_vl;
 }
 
 /*
diff --git a/arch/arm64/kvm/fpsimd.c b/arch/arm64/kvm/fpsimd.c
index aac7808..1cf4f02 100644
--- a/arch/arm64/kvm/fpsimd.c
+++ b/arch/arm64/kvm/fpsimd.c
@@ -9,6 +9,7 @@
 #include <linux/sched.h>
 #include <linux/thread_info.h>
 #include <linux/kvm_host.h>
+#include <asm/fpsimd.h>
 #include <asm/kvm_asm.h>
 #include <asm/kvm_host.h>
 #include <asm/kvm_mmu.h>
@@ -85,7 +86,9 @@ void kvm_arch_vcpu_ctxsync_fp(struct kvm_vcpu *vcpu)
 	WARN_ON_ONCE(!irqs_disabled());
 
 	if (vcpu->arch.flags & KVM_ARM64_FP_ENABLED) {
-		fpsimd_bind_state_to_cpu(&vcpu->arch.ctxt.gp_regs.fp_regs);
+		fpsimd_bind_state_to_cpu(&vcpu->arch.ctxt.gp_regs.fp_regs,
+					 NULL, SVE_VL_MIN);
+
 		clear_thread_flag(TIF_FOREIGN_FPSTATE);
 		clear_thread_flag(TIF_SVE);
 	}
-- 
2.1.4


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* [PATCH v5 09/26] KVM: arm64: Add a vcpu flag to control SVE visibility for the guest
  2019-02-18 19:52 ` Dave Martin
@ 2019-02-18 19:52   ` Dave Martin
  -1 siblings, 0 replies; 205+ messages in thread
From: Dave Martin @ 2019-02-18 19:52 UTC (permalink / raw)
  To: kvmarm
  Cc: Okamoto Takayuki, Christoffer Dall, Ard Biesheuvel, Marc Zyngier,
	Catalin Marinas, Will Deacon, Zhang Lei, linux-arm-kernel

Since SVE will be enabled or disabled on a per-vcpu basis, a flag
is needed in order to track which vcpus have it enabled.

This patch adds a suitable flag and a helper for checking it.

Signed-off-by: Dave Martin <Dave.Martin@arm.com>
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
---
 arch/arm64/include/asm/kvm_host.h | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/arch/arm64/include/asm/kvm_host.h b/arch/arm64/include/asm/kvm_host.h
index 84056a4..af625a8 100644
--- a/arch/arm64/include/asm/kvm_host.h
+++ b/arch/arm64/include/asm/kvm_host.h
@@ -309,6 +309,10 @@ struct kvm_vcpu_arch {
 #define KVM_ARM64_FP_HOST		(1 << 2) /* host FP regs loaded */
 #define KVM_ARM64_HOST_SVE_IN_USE	(1 << 3) /* backup for host TIF_SVE */
 #define KVM_ARM64_HOST_SVE_ENABLED	(1 << 4) /* SVE enabled for EL0 */
+#define KVM_ARM64_GUEST_HAS_SVE		(1 << 5) /* SVE exposed to guest */
+
+#define vcpu_has_sve(vcpu) (system_supports_sve() && \
+			    ((vcpu)->arch.flags & KVM_ARM64_GUEST_HAS_SVE))
 
 #define vcpu_gp_regs(v)		(&(v)->arch.ctxt.gp_regs)
 
-- 
2.1.4

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

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

* [PATCH v5 09/26] KVM: arm64: Add a vcpu flag to control SVE visibility for the guest
@ 2019-02-18 19:52   ` Dave Martin
  0 siblings, 0 replies; 205+ messages in thread
From: Dave Martin @ 2019-02-18 19:52 UTC (permalink / raw)
  To: kvmarm
  Cc: Peter Maydell, Okamoto Takayuki, Christoffer Dall,
	Ard Biesheuvel, Marc Zyngier, Catalin Marinas, Will Deacon,
	Zhang Lei, Julien Grall, Alex Bennée, linux-arm-kernel

Since SVE will be enabled or disabled on a per-vcpu basis, a flag
is needed in order to track which vcpus have it enabled.

This patch adds a suitable flag and a helper for checking it.

Signed-off-by: Dave Martin <Dave.Martin@arm.com>
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
---
 arch/arm64/include/asm/kvm_host.h | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/arch/arm64/include/asm/kvm_host.h b/arch/arm64/include/asm/kvm_host.h
index 84056a4..af625a8 100644
--- a/arch/arm64/include/asm/kvm_host.h
+++ b/arch/arm64/include/asm/kvm_host.h
@@ -309,6 +309,10 @@ struct kvm_vcpu_arch {
 #define KVM_ARM64_FP_HOST		(1 << 2) /* host FP regs loaded */
 #define KVM_ARM64_HOST_SVE_IN_USE	(1 << 3) /* backup for host TIF_SVE */
 #define KVM_ARM64_HOST_SVE_ENABLED	(1 << 4) /* SVE enabled for EL0 */
+#define KVM_ARM64_GUEST_HAS_SVE		(1 << 5) /* SVE exposed to guest */
+
+#define vcpu_has_sve(vcpu) (system_supports_sve() && \
+			    ((vcpu)->arch.flags & KVM_ARM64_GUEST_HAS_SVE))
 
 #define vcpu_gp_regs(v)		(&(v)->arch.ctxt.gp_regs)
 
-- 
2.1.4


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* [PATCH v5 10/26] KVM: arm64: Propagate vcpu into read_id_reg()
  2019-02-18 19:52 ` Dave Martin
@ 2019-02-18 19:52   ` Dave Martin
  -1 siblings, 0 replies; 205+ messages in thread
From: Dave Martin @ 2019-02-18 19:52 UTC (permalink / raw)
  To: kvmarm
  Cc: Okamoto Takayuki, Christoffer Dall, Ard Biesheuvel, Marc Zyngier,
	Catalin Marinas, Will Deacon, Zhang Lei, linux-arm-kernel

Architecture features that are conditionally visible to the guest
will require run-time checks in the ID register accessor functions.
In particular, read_id_reg() will need to perform checks in order
to generate the correct emulated value for certain ID register
fields such as ID_AA64PFR0_EL1.SVE for example.

This patch propagates vcpu into read_id_reg() so that future
patches can add run-time checks on the guest configuration here.

For now, there is no functional change.

Signed-off-by: Dave Martin <Dave.Martin@arm.com>
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
---
 arch/arm64/kvm/sys_regs.c | 23 +++++++++++++----------
 1 file changed, 13 insertions(+), 10 deletions(-)

diff --git a/arch/arm64/kvm/sys_regs.c b/arch/arm64/kvm/sys_regs.c
index e3e3722..71c5825 100644
--- a/arch/arm64/kvm/sys_regs.c
+++ b/arch/arm64/kvm/sys_regs.c
@@ -1029,7 +1029,8 @@ static bool access_cntp_cval(struct kvm_vcpu *vcpu,
 }
 
 /* Read a sanitised cpufeature ID register by sys_reg_desc */
-static u64 read_id_reg(struct sys_reg_desc const *r, bool raz)
+static u64 read_id_reg(const struct kvm_vcpu *vcpu,
+		struct sys_reg_desc const *r, bool raz)
 {
 	u32 id = sys_reg((u32)r->Op0, (u32)r->Op1,
 			 (u32)r->CRn, (u32)r->CRm, (u32)r->Op2);
@@ -1068,7 +1069,7 @@ static bool __access_id_reg(struct kvm_vcpu *vcpu,
 	if (p->is_write)
 		return write_to_read_only(vcpu, p, r);
 
-	p->regval = read_id_reg(r, raz);
+	p->regval = read_id_reg(vcpu, r, raz);
 	return true;
 }
 
@@ -1097,16 +1098,18 @@ static u64 sys_reg_to_index(const struct sys_reg_desc *reg);
  * are stored, and for set_id_reg() we don't allow the effective value
  * to be changed.
  */
-static int __get_id_reg(const struct sys_reg_desc *rd, void __user *uaddr,
+static int __get_id_reg(const struct kvm_vcpu *vcpu,
+			const struct sys_reg_desc *rd, void __user *uaddr,
 			bool raz)
 {
 	const u64 id = sys_reg_to_index(rd);
-	const u64 val = read_id_reg(rd, raz);
+	const u64 val = read_id_reg(vcpu, rd, raz);
 
 	return reg_to_user(uaddr, &val, id);
 }
 
-static int __set_id_reg(const struct sys_reg_desc *rd, void __user *uaddr,
+static int __set_id_reg(const struct kvm_vcpu *vcpu,
+			const struct sys_reg_desc *rd, void __user *uaddr,
 			bool raz)
 {
 	const u64 id = sys_reg_to_index(rd);
@@ -1118,7 +1121,7 @@ static int __set_id_reg(const struct sys_reg_desc *rd, void __user *uaddr,
 		return err;
 
 	/* This is what we mean by invariant: you can't change it. */
-	if (val != read_id_reg(rd, raz))
+	if (val != read_id_reg(vcpu, rd, raz))
 		return -EINVAL;
 
 	return 0;
@@ -1127,25 +1130,25 @@ static int __set_id_reg(const struct sys_reg_desc *rd, void __user *uaddr,
 static int get_id_reg(struct kvm_vcpu *vcpu, const struct sys_reg_desc *rd,
 		      const struct kvm_one_reg *reg, void __user *uaddr)
 {
-	return __get_id_reg(rd, uaddr, false);
+	return __get_id_reg(vcpu, rd, uaddr, false);
 }
 
 static int set_id_reg(struct kvm_vcpu *vcpu, const struct sys_reg_desc *rd,
 		      const struct kvm_one_reg *reg, void __user *uaddr)
 {
-	return __set_id_reg(rd, uaddr, false);
+	return __set_id_reg(vcpu, rd, uaddr, false);
 }
 
 static int get_raz_id_reg(struct kvm_vcpu *vcpu, const struct sys_reg_desc *rd,
 			  const struct kvm_one_reg *reg, void __user *uaddr)
 {
-	return __get_id_reg(rd, uaddr, true);
+	return __get_id_reg(vcpu, rd, uaddr, true);
 }
 
 static int set_raz_id_reg(struct kvm_vcpu *vcpu, const struct sys_reg_desc *rd,
 			  const struct kvm_one_reg *reg, void __user *uaddr)
 {
-	return __set_id_reg(rd, uaddr, true);
+	return __set_id_reg(vcpu, rd, uaddr, true);
 }
 
 /* sys_reg_desc initialiser for known cpufeature ID registers */
-- 
2.1.4

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

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

* [PATCH v5 10/26] KVM: arm64: Propagate vcpu into read_id_reg()
@ 2019-02-18 19:52   ` Dave Martin
  0 siblings, 0 replies; 205+ messages in thread
From: Dave Martin @ 2019-02-18 19:52 UTC (permalink / raw)
  To: kvmarm
  Cc: Peter Maydell, Okamoto Takayuki, Christoffer Dall,
	Ard Biesheuvel, Marc Zyngier, Catalin Marinas, Will Deacon,
	Zhang Lei, Julien Grall, Alex Bennée, linux-arm-kernel

Architecture features that are conditionally visible to the guest
will require run-time checks in the ID register accessor functions.
In particular, read_id_reg() will need to perform checks in order
to generate the correct emulated value for certain ID register
fields such as ID_AA64PFR0_EL1.SVE for example.

This patch propagates vcpu into read_id_reg() so that future
patches can add run-time checks on the guest configuration here.

For now, there is no functional change.

Signed-off-by: Dave Martin <Dave.Martin@arm.com>
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
---
 arch/arm64/kvm/sys_regs.c | 23 +++++++++++++----------
 1 file changed, 13 insertions(+), 10 deletions(-)

diff --git a/arch/arm64/kvm/sys_regs.c b/arch/arm64/kvm/sys_regs.c
index e3e3722..71c5825 100644
--- a/arch/arm64/kvm/sys_regs.c
+++ b/arch/arm64/kvm/sys_regs.c
@@ -1029,7 +1029,8 @@ static bool access_cntp_cval(struct kvm_vcpu *vcpu,
 }
 
 /* Read a sanitised cpufeature ID register by sys_reg_desc */
-static u64 read_id_reg(struct sys_reg_desc const *r, bool raz)
+static u64 read_id_reg(const struct kvm_vcpu *vcpu,
+		struct sys_reg_desc const *r, bool raz)
 {
 	u32 id = sys_reg((u32)r->Op0, (u32)r->Op1,
 			 (u32)r->CRn, (u32)r->CRm, (u32)r->Op2);
@@ -1068,7 +1069,7 @@ static bool __access_id_reg(struct kvm_vcpu *vcpu,
 	if (p->is_write)
 		return write_to_read_only(vcpu, p, r);
 
-	p->regval = read_id_reg(r, raz);
+	p->regval = read_id_reg(vcpu, r, raz);
 	return true;
 }
 
@@ -1097,16 +1098,18 @@ static u64 sys_reg_to_index(const struct sys_reg_desc *reg);
  * are stored, and for set_id_reg() we don't allow the effective value
  * to be changed.
  */
-static int __get_id_reg(const struct sys_reg_desc *rd, void __user *uaddr,
+static int __get_id_reg(const struct kvm_vcpu *vcpu,
+			const struct sys_reg_desc *rd, void __user *uaddr,
 			bool raz)
 {
 	const u64 id = sys_reg_to_index(rd);
-	const u64 val = read_id_reg(rd, raz);
+	const u64 val = read_id_reg(vcpu, rd, raz);
 
 	return reg_to_user(uaddr, &val, id);
 }
 
-static int __set_id_reg(const struct sys_reg_desc *rd, void __user *uaddr,
+static int __set_id_reg(const struct kvm_vcpu *vcpu,
+			const struct sys_reg_desc *rd, void __user *uaddr,
 			bool raz)
 {
 	const u64 id = sys_reg_to_index(rd);
@@ -1118,7 +1121,7 @@ static int __set_id_reg(const struct sys_reg_desc *rd, void __user *uaddr,
 		return err;
 
 	/* This is what we mean by invariant: you can't change it. */
-	if (val != read_id_reg(rd, raz))
+	if (val != read_id_reg(vcpu, rd, raz))
 		return -EINVAL;
 
 	return 0;
@@ -1127,25 +1130,25 @@ static int __set_id_reg(const struct sys_reg_desc *rd, void __user *uaddr,
 static int get_id_reg(struct kvm_vcpu *vcpu, const struct sys_reg_desc *rd,
 		      const struct kvm_one_reg *reg, void __user *uaddr)
 {
-	return __get_id_reg(rd, uaddr, false);
+	return __get_id_reg(vcpu, rd, uaddr, false);
 }
 
 static int set_id_reg(struct kvm_vcpu *vcpu, const struct sys_reg_desc *rd,
 		      const struct kvm_one_reg *reg, void __user *uaddr)
 {
-	return __set_id_reg(rd, uaddr, false);
+	return __set_id_reg(vcpu, rd, uaddr, false);
 }
 
 static int get_raz_id_reg(struct kvm_vcpu *vcpu, const struct sys_reg_desc *rd,
 			  const struct kvm_one_reg *reg, void __user *uaddr)
 {
-	return __get_id_reg(rd, uaddr, true);
+	return __get_id_reg(vcpu, rd, uaddr, true);
 }
 
 static int set_raz_id_reg(struct kvm_vcpu *vcpu, const struct sys_reg_desc *rd,
 			  const struct kvm_one_reg *reg, void __user *uaddr)
 {
-	return __set_id_reg(rd, uaddr, true);
+	return __set_id_reg(vcpu, rd, uaddr, true);
 }
 
 /* sys_reg_desc initialiser for known cpufeature ID registers */
-- 
2.1.4


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* [PATCH v5 11/26] KVM: arm64: Extend reset_unknown() to handle mixed RES0/UNKNOWN registers
  2019-02-18 19:52 ` Dave Martin
@ 2019-02-18 19:52   ` Dave Martin
  -1 siblings, 0 replies; 205+ messages in thread
From: Dave Martin @ 2019-02-18 19:52 UTC (permalink / raw)
  To: kvmarm
  Cc: Okamoto Takayuki, Christoffer Dall, Ard Biesheuvel, Marc Zyngier,
	Catalin Marinas, Will Deacon, Zhang Lei, linux-arm-kernel

The reset_unknown() system register helper initialises a guest
register to a distinctive junk value on vcpu reset, to help expose
and debug deficient register initialisation within the guest.

Some registers such as the SVE control register ZCR_EL1 contain a
mixture of UNKNOWN fields and RES0 bits.  For these,
reset_unknown() does not work at present, since it sets all bits to
junk values instead of just the wanted bits.

There is no need to craft another special helper just for that,
since reset_unknown() almost does the appropriate thing anyway.
This patch takes advantage of the unused val field in struct
sys_reg_desc to specify a mask of bits that should be initialised
to zero instead of junk.

All existing users of reset_unknown() do not (and should not)
define a value for val, so they will implicitly set it to zero,
resulting in all bits being made UNKNOWN by this function: thus,
this patch makes no functional change for currently defined
registers.

Future patches will make use of non-zero val.

Signed-off-by: Dave Martin <Dave.Martin@arm.com>
---
 arch/arm64/kvm/sys_regs.h | 11 +++++++++--
 1 file changed, 9 insertions(+), 2 deletions(-)

diff --git a/arch/arm64/kvm/sys_regs.h b/arch/arm64/kvm/sys_regs.h
index 3b1bc7f..174ffc0 100644
--- a/arch/arm64/kvm/sys_regs.h
+++ b/arch/arm64/kvm/sys_regs.h
@@ -56,7 +56,12 @@ struct sys_reg_desc {
 	/* Index into sys_reg[], or 0 if we don't need to save it. */
 	int reg;
 
-	/* Value (usually reset value) */
+	/*
+	 * Value (usually reset value)
+	 * For reset_unknown, each bit set to 1 in val is treated as
+	 * RES0 in the register: the corresponding register bit is
+	 * reset to 0 instead of "unknown".
+	 */
 	u64 val;
 
 	/* Custom get/set_user functions, fallback to generic if NULL */
@@ -92,7 +97,9 @@ static inline void reset_unknown(struct kvm_vcpu *vcpu,
 {
 	BUG_ON(!r->reg);
 	BUG_ON(r->reg >= NR_SYS_REGS);
-	__vcpu_sys_reg(vcpu, r->reg) = 0x1de7ec7edbadc0deULL;
+
+	/* If non-zero, r->val specifies which register bits are RES0: */
+	__vcpu_sys_reg(vcpu, r->reg) = 0x1de7ec7edbadc0deULL & ~r->val;
 }
 
 static inline void reset_val(struct kvm_vcpu *vcpu, const struct sys_reg_desc *r)
-- 
2.1.4

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

* [PATCH v5 11/26] KVM: arm64: Extend reset_unknown() to handle mixed RES0/UNKNOWN registers
@ 2019-02-18 19:52   ` Dave Martin
  0 siblings, 0 replies; 205+ messages in thread
From: Dave Martin @ 2019-02-18 19:52 UTC (permalink / raw)
  To: kvmarm
  Cc: Peter Maydell, Okamoto Takayuki, Christoffer Dall,
	Ard Biesheuvel, Marc Zyngier, Catalin Marinas, Will Deacon,
	Zhang Lei, Julien Grall, Alex Bennée, linux-arm-kernel

The reset_unknown() system register helper initialises a guest
register to a distinctive junk value on vcpu reset, to help expose
and debug deficient register initialisation within the guest.

Some registers such as the SVE control register ZCR_EL1 contain a
mixture of UNKNOWN fields and RES0 bits.  For these,
reset_unknown() does not work at present, since it sets all bits to
junk values instead of just the wanted bits.

There is no need to craft another special helper just for that,
since reset_unknown() almost does the appropriate thing anyway.
This patch takes advantage of the unused val field in struct
sys_reg_desc to specify a mask of bits that should be initialised
to zero instead of junk.

All existing users of reset_unknown() do not (and should not)
define a value for val, so they will implicitly set it to zero,
resulting in all bits being made UNKNOWN by this function: thus,
this patch makes no functional change for currently defined
registers.

Future patches will make use of non-zero val.

Signed-off-by: Dave Martin <Dave.Martin@arm.com>
---
 arch/arm64/kvm/sys_regs.h | 11 +++++++++--
 1 file changed, 9 insertions(+), 2 deletions(-)

diff --git a/arch/arm64/kvm/sys_regs.h b/arch/arm64/kvm/sys_regs.h
index 3b1bc7f..174ffc0 100644
--- a/arch/arm64/kvm/sys_regs.h
+++ b/arch/arm64/kvm/sys_regs.h
@@ -56,7 +56,12 @@ struct sys_reg_desc {
 	/* Index into sys_reg[], or 0 if we don't need to save it. */
 	int reg;
 
-	/* Value (usually reset value) */
+	/*
+	 * Value (usually reset value)
+	 * For reset_unknown, each bit set to 1 in val is treated as
+	 * RES0 in the register: the corresponding register bit is
+	 * reset to 0 instead of "unknown".
+	 */
 	u64 val;
 
 	/* Custom get/set_user functions, fallback to generic if NULL */
@@ -92,7 +97,9 @@ static inline void reset_unknown(struct kvm_vcpu *vcpu,
 {
 	BUG_ON(!r->reg);
 	BUG_ON(r->reg >= NR_SYS_REGS);
-	__vcpu_sys_reg(vcpu, r->reg) = 0x1de7ec7edbadc0deULL;
+
+	/* If non-zero, r->val specifies which register bits are RES0: */
+	__vcpu_sys_reg(vcpu, r->reg) = 0x1de7ec7edbadc0deULL & ~r->val;
 }
 
 static inline void reset_val(struct kvm_vcpu *vcpu, const struct sys_reg_desc *r)
-- 
2.1.4


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* [PATCH v5 12/26] KVM: arm64: Support runtime sysreg visibility filtering
  2019-02-18 19:52 ` Dave Martin
@ 2019-02-18 19:52   ` Dave Martin
  -1 siblings, 0 replies; 205+ messages in thread
From: Dave Martin @ 2019-02-18 19:52 UTC (permalink / raw)
  To: kvmarm
  Cc: Okamoto Takayuki, Christoffer Dall, Ard Biesheuvel, Marc Zyngier,
	Catalin Marinas, Will Deacon, Zhang Lei, linux-arm-kernel

Some optional features of the Arm architecture add new system
registers that are not present in the base architecture.

Where these features are optional for the guest, the visibility of
these registers may need to depend on some runtime configuration,
such as a flag passed to KVM_ARM_VCPU_INIT.

For example, ZCR_EL1 and ID_AA64ZFR0_EL1 need to be hidden if SVE
is not enabled for the guest, even though these registers may be
present in the hardware and visible to the host at EL2.

Adding special-case checks all over the place for individual
registers is going to get messy as the number of conditionally-
visible registers grows.

In order to help solve this problem, this patch adds a new sysreg
method restrictions() that can be used to hook in any needed
runtime visibility checks.  This method can currently return
REG_NO_USER to inhibit enumeration and ioctl access to the register
for userspace, and REG_NO_GUEST to inhibit runtime access by the
guest using MSR/MRS.

This allows a conditionally modified view of individual system
registers such as the CPU ID registers, in addition to completely
hiding register where appropriate.

Signed-off-by: Dave Martin <Dave.Martin@arm.com>

---

Changes since v4:

 * Move from a boolean sysreg property that just suppresses register
   enumeration via KVM_GET_REG_LIST, to a multi-flag property that
   allows independent runtime control of MRS/MSR and user ioctl access.

   This allows registers to be either hidden completely, or to have
   hybrid behaviours (such as the not-enumerated, RAZ, WAZ behaviour of
   "non-present" CPU ID regs).
---
 arch/arm64/kvm/sys_regs.c | 24 +++++++++++++++++++++---
 arch/arm64/kvm/sys_regs.h | 13 +++++++++++++
 2 files changed, 34 insertions(+), 3 deletions(-)

diff --git a/arch/arm64/kvm/sys_regs.c b/arch/arm64/kvm/sys_regs.c
index 71c5825..3f1243e 100644
--- a/arch/arm64/kvm/sys_regs.c
+++ b/arch/arm64/kvm/sys_regs.c
@@ -1863,6 +1863,12 @@ static void perform_access(struct kvm_vcpu *vcpu,
 {
 	trace_kvm_sys_access(*vcpu_pc(vcpu), params, r);
 
+	/* Check for regs disabled by runtime config */
+	if (restrictions(vcpu, r) & REG_NO_GUEST) {
+		kvm_inject_undefined(vcpu);
+		return;
+	}
+
 	/*
 	 * Not having an accessor means that we have configured a trap
 	 * that we don't know how to handle. This certainly qualifies
@@ -2370,6 +2376,10 @@ int kvm_arm_sys_reg_get_reg(struct kvm_vcpu *vcpu, const struct kvm_one_reg *reg
 	if (!r)
 		return get_invariant_sys_reg(reg->id, uaddr);
 
+	/* Check for regs disabled by runtime config */
+	if (restrictions(vcpu, r) & REG_NO_USER)
+		return -ENOENT;
+
 	if (r->get_user)
 		return (r->get_user)(vcpu, r, reg, uaddr);
 
@@ -2391,6 +2401,10 @@ int kvm_arm_sys_reg_set_reg(struct kvm_vcpu *vcpu, const struct kvm_one_reg *reg
 	if (!r)
 		return set_invariant_sys_reg(reg->id, uaddr);
 
+	/* Check for regs disabled by runtime config */
+	if (restrictions(vcpu, r) & REG_NO_USER)
+		return -ENOENT;
+
 	if (r->set_user)
 		return (r->set_user)(vcpu, r, reg, uaddr);
 
@@ -2447,7 +2461,8 @@ static bool copy_reg_to_user(const struct sys_reg_desc *reg, u64 __user **uind)
 	return true;
 }
 
-static int walk_one_sys_reg(const struct sys_reg_desc *rd,
+static int walk_one_sys_reg(const struct kvm_vcpu *vcpu,
+			    const struct sys_reg_desc *rd,
 			    u64 __user **uind,
 			    unsigned int *total)
 {
@@ -2458,6 +2473,9 @@ static int walk_one_sys_reg(const struct sys_reg_desc *rd,
 	if (!(rd->reg || rd->get_user))
 		return 0;
 
+	if (restrictions(vcpu, rd) & REG_NO_USER)
+		return 0;
+
 	if (!copy_reg_to_user(rd, uind))
 		return -EFAULT;
 
@@ -2486,9 +2504,9 @@ static int walk_sys_regs(struct kvm_vcpu *vcpu, u64 __user *uind)
 		int cmp = cmp_sys_reg(i1, i2);
 		/* target-specific overrides generic entry. */
 		if (cmp <= 0)
-			err = walk_one_sys_reg(i1, &uind, &total);
+			err = walk_one_sys_reg(vcpu, i1, &uind, &total);
 		else
-			err = walk_one_sys_reg(i2, &uind, &total);
+			err = walk_one_sys_reg(vcpu, i2, &uind, &total);
 
 		if (err)
 			return err;
diff --git a/arch/arm64/kvm/sys_regs.h b/arch/arm64/kvm/sys_regs.h
index 174ffc0..12f196f 100644
--- a/arch/arm64/kvm/sys_regs.h
+++ b/arch/arm64/kvm/sys_regs.h
@@ -69,8 +69,15 @@ struct sys_reg_desc {
 			const struct kvm_one_reg *reg, void __user *uaddr);
 	int (*set_user)(struct kvm_vcpu *vcpu, const struct sys_reg_desc *rd,
 			const struct kvm_one_reg *reg, void __user *uaddr);
+
+	/* Return mask of REG_* runtime restriction flags */
+	unsigned int (*restrictions)(const struct kvm_vcpu *vcpu,
+				     const struct sys_reg_desc *rd);
 };
 
+#define REG_NO_USER	(1 << 0) /* hidden from userspace ioctl interface */
+#define REG_NO_GUEST	(1 << 1) /* hidden from guest */
+
 static inline void print_sys_reg_instr(const struct sys_reg_params *p)
 {
 	/* Look, we even formatted it for you to paste into the table! */
@@ -109,6 +116,12 @@ static inline void reset_val(struct kvm_vcpu *vcpu, const struct sys_reg_desc *r
 	__vcpu_sys_reg(vcpu, r->reg) = r->val;
 }
 
+static inline unsigned int restrictions(const struct kvm_vcpu *vcpu,
+					const struct sys_reg_desc *r)
+{
+	return unlikely(r->restrictions) ? r->restrictions(vcpu, r) : 0;
+}
+
 static inline int cmp_sys_reg(const struct sys_reg_desc *i1,
 			      const struct sys_reg_desc *i2)
 {
-- 
2.1.4

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

* [PATCH v5 12/26] KVM: arm64: Support runtime sysreg visibility filtering
@ 2019-02-18 19:52   ` Dave Martin
  0 siblings, 0 replies; 205+ messages in thread
From: Dave Martin @ 2019-02-18 19:52 UTC (permalink / raw)
  To: kvmarm
  Cc: Peter Maydell, Okamoto Takayuki, Christoffer Dall,
	Ard Biesheuvel, Marc Zyngier, Catalin Marinas, Will Deacon,
	Zhang Lei, Julien Grall, Alex Bennée, linux-arm-kernel

Some optional features of the Arm architecture add new system
registers that are not present in the base architecture.

Where these features are optional for the guest, the visibility of
these registers may need to depend on some runtime configuration,
such as a flag passed to KVM_ARM_VCPU_INIT.

For example, ZCR_EL1 and ID_AA64ZFR0_EL1 need to be hidden if SVE
is not enabled for the guest, even though these registers may be
present in the hardware and visible to the host at EL2.

Adding special-case checks all over the place for individual
registers is going to get messy as the number of conditionally-
visible registers grows.

In order to help solve this problem, this patch adds a new sysreg
method restrictions() that can be used to hook in any needed
runtime visibility checks.  This method can currently return
REG_NO_USER to inhibit enumeration and ioctl access to the register
for userspace, and REG_NO_GUEST to inhibit runtime access by the
guest using MSR/MRS.

This allows a conditionally modified view of individual system
registers such as the CPU ID registers, in addition to completely
hiding register where appropriate.

Signed-off-by: Dave Martin <Dave.Martin@arm.com>

---

Changes since v4:

 * Move from a boolean sysreg property that just suppresses register
   enumeration via KVM_GET_REG_LIST, to a multi-flag property that
   allows independent runtime control of MRS/MSR and user ioctl access.

   This allows registers to be either hidden completely, or to have
   hybrid behaviours (such as the not-enumerated, RAZ, WAZ behaviour of
   "non-present" CPU ID regs).
---
 arch/arm64/kvm/sys_regs.c | 24 +++++++++++++++++++++---
 arch/arm64/kvm/sys_regs.h | 13 +++++++++++++
 2 files changed, 34 insertions(+), 3 deletions(-)

diff --git a/arch/arm64/kvm/sys_regs.c b/arch/arm64/kvm/sys_regs.c
index 71c5825..3f1243e 100644
--- a/arch/arm64/kvm/sys_regs.c
+++ b/arch/arm64/kvm/sys_regs.c
@@ -1863,6 +1863,12 @@ static void perform_access(struct kvm_vcpu *vcpu,
 {
 	trace_kvm_sys_access(*vcpu_pc(vcpu), params, r);
 
+	/* Check for regs disabled by runtime config */
+	if (restrictions(vcpu, r) & REG_NO_GUEST) {
+		kvm_inject_undefined(vcpu);
+		return;
+	}
+
 	/*
 	 * Not having an accessor means that we have configured a trap
 	 * that we don't know how to handle. This certainly qualifies
@@ -2370,6 +2376,10 @@ int kvm_arm_sys_reg_get_reg(struct kvm_vcpu *vcpu, const struct kvm_one_reg *reg
 	if (!r)
 		return get_invariant_sys_reg(reg->id, uaddr);
 
+	/* Check for regs disabled by runtime config */
+	if (restrictions(vcpu, r) & REG_NO_USER)
+		return -ENOENT;
+
 	if (r->get_user)
 		return (r->get_user)(vcpu, r, reg, uaddr);
 
@@ -2391,6 +2401,10 @@ int kvm_arm_sys_reg_set_reg(struct kvm_vcpu *vcpu, const struct kvm_one_reg *reg
 	if (!r)
 		return set_invariant_sys_reg(reg->id, uaddr);
 
+	/* Check for regs disabled by runtime config */
+	if (restrictions(vcpu, r) & REG_NO_USER)
+		return -ENOENT;
+
 	if (r->set_user)
 		return (r->set_user)(vcpu, r, reg, uaddr);
 
@@ -2447,7 +2461,8 @@ static bool copy_reg_to_user(const struct sys_reg_desc *reg, u64 __user **uind)
 	return true;
 }
 
-static int walk_one_sys_reg(const struct sys_reg_desc *rd,
+static int walk_one_sys_reg(const struct kvm_vcpu *vcpu,
+			    const struct sys_reg_desc *rd,
 			    u64 __user **uind,
 			    unsigned int *total)
 {
@@ -2458,6 +2473,9 @@ static int walk_one_sys_reg(const struct sys_reg_desc *rd,
 	if (!(rd->reg || rd->get_user))
 		return 0;
 
+	if (restrictions(vcpu, rd) & REG_NO_USER)
+		return 0;
+
 	if (!copy_reg_to_user(rd, uind))
 		return -EFAULT;
 
@@ -2486,9 +2504,9 @@ static int walk_sys_regs(struct kvm_vcpu *vcpu, u64 __user *uind)
 		int cmp = cmp_sys_reg(i1, i2);
 		/* target-specific overrides generic entry. */
 		if (cmp <= 0)
-			err = walk_one_sys_reg(i1, &uind, &total);
+			err = walk_one_sys_reg(vcpu, i1, &uind, &total);
 		else
-			err = walk_one_sys_reg(i2, &uind, &total);
+			err = walk_one_sys_reg(vcpu, i2, &uind, &total);
 
 		if (err)
 			return err;
diff --git a/arch/arm64/kvm/sys_regs.h b/arch/arm64/kvm/sys_regs.h
index 174ffc0..12f196f 100644
--- a/arch/arm64/kvm/sys_regs.h
+++ b/arch/arm64/kvm/sys_regs.h
@@ -69,8 +69,15 @@ struct sys_reg_desc {
 			const struct kvm_one_reg *reg, void __user *uaddr);
 	int (*set_user)(struct kvm_vcpu *vcpu, const struct sys_reg_desc *rd,
 			const struct kvm_one_reg *reg, void __user *uaddr);
+
+	/* Return mask of REG_* runtime restriction flags */
+	unsigned int (*restrictions)(const struct kvm_vcpu *vcpu,
+				     const struct sys_reg_desc *rd);
 };
 
+#define REG_NO_USER	(1 << 0) /* hidden from userspace ioctl interface */
+#define REG_NO_GUEST	(1 << 1) /* hidden from guest */
+
 static inline void print_sys_reg_instr(const struct sys_reg_params *p)
 {
 	/* Look, we even formatted it for you to paste into the table! */
@@ -109,6 +116,12 @@ static inline void reset_val(struct kvm_vcpu *vcpu, const struct sys_reg_desc *r
 	__vcpu_sys_reg(vcpu, r->reg) = r->val;
 }
 
+static inline unsigned int restrictions(const struct kvm_vcpu *vcpu,
+					const struct sys_reg_desc *r)
+{
+	return unlikely(r->restrictions) ? r->restrictions(vcpu, r) : 0;
+}
+
 static inline int cmp_sys_reg(const struct sys_reg_desc *i1,
 			      const struct sys_reg_desc *i2)
 {
-- 
2.1.4


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* [PATCH v5 13/26] KVM: arm64/sve: System register context switch and access support
  2019-02-18 19:52 ` Dave Martin
@ 2019-02-18 19:52   ` Dave Martin
  -1 siblings, 0 replies; 205+ messages in thread
From: Dave Martin @ 2019-02-18 19:52 UTC (permalink / raw)
  To: kvmarm
  Cc: Okamoto Takayuki, Christoffer Dall, Ard Biesheuvel, Marc Zyngier,
	Catalin Marinas, Will Deacon, Zhang Lei, linux-arm-kernel

This patch adds the necessary support for context switching ZCR_EL1
for each vcpu.

ZCR_EL1 is trapped alongside the FPSIMD/SVE registers, so it makes
sense for it to be handled as part of the guest FPSIMD/SVE context
for context switch purposes instead of handling it as a general
system register.  This means that it can be switched in lazily at
the appropriate time.  No effort is made to track host context for
this register, since SVE requires VHE: thus the hosts's value for
this register lives permanently in ZCR_EL2 and does not alias the
guest's value at any time.

The Hyp switch and fpsimd context handling code is extended
appropriately.

Accessors are added in sys_regs.c to expose the SVE system
registers and ID register fields.  Because these need to be
conditionally visible based on the guest configuration, they are
implemented separately for now rather than by use of the generic
system register helpers.  This may be abstracted better later on
when/if there are more features requiring this model.

ID_AA64ZFR0_EL1 is RO-RAZ for MRS/MSR when SVE is disabled for the
guest, but for compatibility with non-SVE aware KVM implementations
the register should not be enumerated at all for KVM_GET_REG_LIST
in this case.  For consistency we also reject ioctl access to the
register.  This ensures that a non-SVE-enabled guest looks the same
to userspace, irrespective of whether the kernel KVM implementation
supports SVE.

Signed-off-by: Dave Martin <Dave.Martin@arm.com>

---

Changes since v4:

 * Remove annoying linebreak in assignment.

 * Remove #ifdef clutter and migrate to using the new sysreg
   restrictions() framework to control register visibility.
---
 arch/arm64/include/asm/kvm_host.h |  1 +
 arch/arm64/include/asm/sysreg.h   |  3 ++
 arch/arm64/kvm/fpsimd.c           |  9 +++-
 arch/arm64/kvm/hyp/switch.c       |  3 ++
 arch/arm64/kvm/sys_regs.c         | 97 +++++++++++++++++++++++++++++++++++++--
 5 files changed, 107 insertions(+), 6 deletions(-)

diff --git a/arch/arm64/include/asm/kvm_host.h b/arch/arm64/include/asm/kvm_host.h
index af625a8..c32f195 100644
--- a/arch/arm64/include/asm/kvm_host.h
+++ b/arch/arm64/include/asm/kvm_host.h
@@ -112,6 +112,7 @@ enum vcpu_sysreg {
 	SCTLR_EL1,	/* System Control Register */
 	ACTLR_EL1,	/* Auxiliary Control Register */
 	CPACR_EL1,	/* Coprocessor Access Control */
+	ZCR_EL1,	/* SVE Control */
 	TTBR0_EL1,	/* Translation Table Base Register 0 */
 	TTBR1_EL1,	/* Translation Table Base Register 1 */
 	TCR_EL1,	/* Translation Control Register */
diff --git a/arch/arm64/include/asm/sysreg.h b/arch/arm64/include/asm/sysreg.h
index 72dc4c0..da38491 100644
--- a/arch/arm64/include/asm/sysreg.h
+++ b/arch/arm64/include/asm/sysreg.h
@@ -449,6 +449,9 @@
 #define SYS_ICH_LR14_EL2		__SYS__LR8_EL2(6)
 #define SYS_ICH_LR15_EL2		__SYS__LR8_EL2(7)
 
+/* VHE encodings for architectural EL0/1 system registers */
+#define SYS_ZCR_EL12			sys_reg(3, 5, 1, 2, 0)
+
 /* Common SCTLR_ELx flags. */
 #define SCTLR_ELx_DSSBS	(_BITUL(44))
 #define SCTLR_ELx_ENIA	(_BITUL(31))
diff --git a/arch/arm64/kvm/fpsimd.c b/arch/arm64/kvm/fpsimd.c
index 1cf4f02..7053bf4 100644
--- a/arch/arm64/kvm/fpsimd.c
+++ b/arch/arm64/kvm/fpsimd.c
@@ -103,14 +103,21 @@ void kvm_arch_vcpu_ctxsync_fp(struct kvm_vcpu *vcpu)
 void kvm_arch_vcpu_put_fp(struct kvm_vcpu *vcpu)
 {
 	unsigned long flags;
+	bool host_has_sve = system_supports_sve();
+	bool guest_has_sve = vcpu_has_sve(vcpu);
 
 	local_irq_save(flags);
 
 	if (vcpu->arch.flags & KVM_ARM64_FP_ENABLED) {
+		u64 *guest_zcr = &vcpu->arch.ctxt.sys_regs[ZCR_EL1];
+
 		/* Clean guest FP state to memory and invalidate cpu view */
 		fpsimd_save();
 		fpsimd_flush_cpu_state();
-	} else if (system_supports_sve()) {
+
+		if (guest_has_sve)
+			*guest_zcr = read_sysreg_s(SYS_ZCR_EL12);
+	} else if (host_has_sve) {
 		/*
 		 * The FPSIMD/SVE state in the CPU has not been touched, and we
 		 * have SVE (and VHE): CPACR_EL1 (alias CPTR_EL2) has been
diff --git a/arch/arm64/kvm/hyp/switch.c b/arch/arm64/kvm/hyp/switch.c
index b0b1478..9f07403 100644
--- a/arch/arm64/kvm/hyp/switch.c
+++ b/arch/arm64/kvm/hyp/switch.c
@@ -347,6 +347,9 @@ static bool __hyp_text __hyp_switch_fpsimd(struct kvm_vcpu *vcpu)
 
 	__fpsimd_restore_state(&vcpu->arch.ctxt.gp_regs.fp_regs);
 
+	if (vcpu_has_sve(vcpu))
+		write_sysreg_s(vcpu->arch.ctxt.sys_regs[ZCR_EL1], SYS_ZCR_EL12);
+
 	/* Skip restoring fpexc32 for AArch64 guests */
 	if (!(read_sysreg(hcr_el2) & HCR_RW))
 		write_sysreg(vcpu->arch.ctxt.sys_regs[FPEXC32_EL2],
diff --git a/arch/arm64/kvm/sys_regs.c b/arch/arm64/kvm/sys_regs.c
index 3f1243e..28b1bad 100644
--- a/arch/arm64/kvm/sys_regs.c
+++ b/arch/arm64/kvm/sys_regs.c
@@ -1036,10 +1036,7 @@ static u64 read_id_reg(const struct kvm_vcpu *vcpu,
 			 (u32)r->CRn, (u32)r->CRm, (u32)r->Op2);
 	u64 val = raz ? 0 : read_sanitised_ftr_reg(id);
 
-	if (id == SYS_ID_AA64PFR0_EL1) {
-		if (val & (0xfUL << ID_AA64PFR0_SVE_SHIFT))
-			kvm_debug("SVE unsupported for guests, suppressing\n");
-
+	if (id == SYS_ID_AA64PFR0_EL1 && !vcpu_has_sve(vcpu)) {
 		val &= ~(0xfUL << ID_AA64PFR0_SVE_SHIFT);
 	} else if (id == SYS_ID_AA64ISAR1_EL1) {
 		const u64 ptrauth_mask = (0xfUL << ID_AA64ISAR1_APA_SHIFT) |
@@ -1091,6 +1088,95 @@ static int reg_from_user(u64 *val, const void __user *uaddr, u64 id);
 static int reg_to_user(void __user *uaddr, const u64 *val, u64 id);
 static u64 sys_reg_to_index(const struct sys_reg_desc *reg);
 
+static unsigned int sve_restrictions(const struct kvm_vcpu *vcpu,
+				     const struct sys_reg_desc *rd)
+{
+	return vcpu_has_sve(vcpu) ? 0 : REG_NO_USER | REG_NO_GUEST;
+}
+
+static unsigned int sve_id_restrictions(const struct kvm_vcpu *vcpu,
+					const struct sys_reg_desc *rd)
+{
+	return vcpu_has_sve(vcpu) ? 0 : REG_NO_USER;
+}
+
+static int get_zcr_el1(struct kvm_vcpu *vcpu,
+		       const struct sys_reg_desc *rd,
+		       const struct kvm_one_reg *reg, void __user *uaddr)
+{
+	if (WARN_ON(!vcpu_has_sve(vcpu)))
+		return -ENOENT;
+
+	return reg_to_user(uaddr, &vcpu->arch.ctxt.sys_regs[ZCR_EL1],
+			   reg->id);
+}
+
+static int set_zcr_el1(struct kvm_vcpu *vcpu,
+		       const struct sys_reg_desc *rd,
+		       const struct kvm_one_reg *reg, void __user *uaddr)
+{
+	if (WARN_ON(!vcpu_has_sve(vcpu)))
+		return -ENOENT;
+
+	return reg_from_user(&vcpu->arch.ctxt.sys_regs[ZCR_EL1], uaddr,
+			     reg->id);
+}
+
+/* Generate the emulated ID_AA64ZFR0_EL1 value exposed to the guest */
+static u64 guest_id_aa64zfr0_el1(const struct kvm_vcpu *vcpu)
+{
+	if (!vcpu_has_sve(vcpu))
+		return 0;
+
+	return read_sanitised_ftr_reg(SYS_ID_AA64ZFR0_EL1);
+}
+
+static bool access_id_aa64zfr0_el1(struct kvm_vcpu *vcpu,
+				   struct sys_reg_params *p,
+				   const struct sys_reg_desc *rd)
+{
+	if (p->is_write)
+		return write_to_read_only(vcpu, p, rd);
+
+	p->regval = guest_id_aa64zfr0_el1(vcpu);
+	return true;
+}
+
+static int get_id_aa64zfr0_el1(struct kvm_vcpu *vcpu,
+		const struct sys_reg_desc *rd,
+		const struct kvm_one_reg *reg, void __user *uaddr)
+{
+	u64 val;
+
+	if (!vcpu_has_sve(vcpu))
+		return -ENOENT;
+
+	val = guest_id_aa64zfr0_el1(vcpu);
+	return reg_to_user(uaddr, &val, reg->id);
+}
+
+static int set_id_aa64zfr0_el1(struct kvm_vcpu *vcpu,
+		const struct sys_reg_desc *rd,
+		const struct kvm_one_reg *reg, void __user *uaddr)
+{
+	const u64 id = sys_reg_to_index(rd);
+	int err;
+	u64 val;
+
+	if (!vcpu_has_sve(vcpu))
+		return -ENOENT;
+
+	err = reg_from_user(&val, uaddr, id);
+	if (err)
+		return err;
+
+	/* This is what we mean by invariant: you can't change it. */
+	if (val != guest_id_aa64zfr0_el1(vcpu))
+		return -EINVAL;
+
+	return 0;
+}
+
 /*
  * cpufeature ID register user accessors
  *
@@ -1278,7 +1364,7 @@ static const struct sys_reg_desc sys_reg_descs[] = {
 	ID_SANITISED(ID_AA64PFR1_EL1),
 	ID_UNALLOCATED(4,2),
 	ID_UNALLOCATED(4,3),
-	ID_UNALLOCATED(4,4),
+	{ SYS_DESC(SYS_ID_AA64ZFR0_EL1), access_id_aa64zfr0_el1, .get_user = get_id_aa64zfr0_el1, .set_user = set_id_aa64zfr0_el1, .restrictions = sve_id_restrictions },
 	ID_UNALLOCATED(4,5),
 	ID_UNALLOCATED(4,6),
 	ID_UNALLOCATED(4,7),
@@ -1315,6 +1401,7 @@ static const struct sys_reg_desc sys_reg_descs[] = {
 
 	{ SYS_DESC(SYS_SCTLR_EL1), access_vm_reg, reset_val, SCTLR_EL1, 0x00C50078 },
 	{ SYS_DESC(SYS_CPACR_EL1), NULL, reset_val, CPACR_EL1, 0 },
+	{ SYS_DESC(SYS_ZCR_EL1), NULL, reset_unknown, ZCR_EL1, ~0xfUL, .get_user = get_zcr_el1, .set_user = set_zcr_el1, .restrictions = sve_restrictions },
 	{ SYS_DESC(SYS_TTBR0_EL1), access_vm_reg, reset_unknown, TTBR0_EL1 },
 	{ SYS_DESC(SYS_TTBR1_EL1), access_vm_reg, reset_unknown, TTBR1_EL1 },
 	{ SYS_DESC(SYS_TCR_EL1), access_vm_reg, reset_val, TCR_EL1, 0 },
-- 
2.1.4

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

* [PATCH v5 13/26] KVM: arm64/sve: System register context switch and access support
@ 2019-02-18 19:52   ` Dave Martin
  0 siblings, 0 replies; 205+ messages in thread
From: Dave Martin @ 2019-02-18 19:52 UTC (permalink / raw)
  To: kvmarm
  Cc: Peter Maydell, Okamoto Takayuki, Christoffer Dall,
	Ard Biesheuvel, Marc Zyngier, Catalin Marinas, Will Deacon,
	Zhang Lei, Julien Grall, Alex Bennée, linux-arm-kernel

This patch adds the necessary support for context switching ZCR_EL1
for each vcpu.

ZCR_EL1 is trapped alongside the FPSIMD/SVE registers, so it makes
sense for it to be handled as part of the guest FPSIMD/SVE context
for context switch purposes instead of handling it as a general
system register.  This means that it can be switched in lazily at
the appropriate time.  No effort is made to track host context for
this register, since SVE requires VHE: thus the hosts's value for
this register lives permanently in ZCR_EL2 and does not alias the
guest's value at any time.

The Hyp switch and fpsimd context handling code is extended
appropriately.

Accessors are added in sys_regs.c to expose the SVE system
registers and ID register fields.  Because these need to be
conditionally visible based on the guest configuration, they are
implemented separately for now rather than by use of the generic
system register helpers.  This may be abstracted better later on
when/if there are more features requiring this model.

ID_AA64ZFR0_EL1 is RO-RAZ for MRS/MSR when SVE is disabled for the
guest, but for compatibility with non-SVE aware KVM implementations
the register should not be enumerated at all for KVM_GET_REG_LIST
in this case.  For consistency we also reject ioctl access to the
register.  This ensures that a non-SVE-enabled guest looks the same
to userspace, irrespective of whether the kernel KVM implementation
supports SVE.

Signed-off-by: Dave Martin <Dave.Martin@arm.com>

---

Changes since v4:

 * Remove annoying linebreak in assignment.

 * Remove #ifdef clutter and migrate to using the new sysreg
   restrictions() framework to control register visibility.
---
 arch/arm64/include/asm/kvm_host.h |  1 +
 arch/arm64/include/asm/sysreg.h   |  3 ++
 arch/arm64/kvm/fpsimd.c           |  9 +++-
 arch/arm64/kvm/hyp/switch.c       |  3 ++
 arch/arm64/kvm/sys_regs.c         | 97 +++++++++++++++++++++++++++++++++++++--
 5 files changed, 107 insertions(+), 6 deletions(-)

diff --git a/arch/arm64/include/asm/kvm_host.h b/arch/arm64/include/asm/kvm_host.h
index af625a8..c32f195 100644
--- a/arch/arm64/include/asm/kvm_host.h
+++ b/arch/arm64/include/asm/kvm_host.h
@@ -112,6 +112,7 @@ enum vcpu_sysreg {
 	SCTLR_EL1,	/* System Control Register */
 	ACTLR_EL1,	/* Auxiliary Control Register */
 	CPACR_EL1,	/* Coprocessor Access Control */
+	ZCR_EL1,	/* SVE Control */
 	TTBR0_EL1,	/* Translation Table Base Register 0 */
 	TTBR1_EL1,	/* Translation Table Base Register 1 */
 	TCR_EL1,	/* Translation Control Register */
diff --git a/arch/arm64/include/asm/sysreg.h b/arch/arm64/include/asm/sysreg.h
index 72dc4c0..da38491 100644
--- a/arch/arm64/include/asm/sysreg.h
+++ b/arch/arm64/include/asm/sysreg.h
@@ -449,6 +449,9 @@
 #define SYS_ICH_LR14_EL2		__SYS__LR8_EL2(6)
 #define SYS_ICH_LR15_EL2		__SYS__LR8_EL2(7)
 
+/* VHE encodings for architectural EL0/1 system registers */
+#define SYS_ZCR_EL12			sys_reg(3, 5, 1, 2, 0)
+
 /* Common SCTLR_ELx flags. */
 #define SCTLR_ELx_DSSBS	(_BITUL(44))
 #define SCTLR_ELx_ENIA	(_BITUL(31))
diff --git a/arch/arm64/kvm/fpsimd.c b/arch/arm64/kvm/fpsimd.c
index 1cf4f02..7053bf4 100644
--- a/arch/arm64/kvm/fpsimd.c
+++ b/arch/arm64/kvm/fpsimd.c
@@ -103,14 +103,21 @@ void kvm_arch_vcpu_ctxsync_fp(struct kvm_vcpu *vcpu)
 void kvm_arch_vcpu_put_fp(struct kvm_vcpu *vcpu)
 {
 	unsigned long flags;
+	bool host_has_sve = system_supports_sve();
+	bool guest_has_sve = vcpu_has_sve(vcpu);
 
 	local_irq_save(flags);
 
 	if (vcpu->arch.flags & KVM_ARM64_FP_ENABLED) {
+		u64 *guest_zcr = &vcpu->arch.ctxt.sys_regs[ZCR_EL1];
+
 		/* Clean guest FP state to memory and invalidate cpu view */
 		fpsimd_save();
 		fpsimd_flush_cpu_state();
-	} else if (system_supports_sve()) {
+
+		if (guest_has_sve)
+			*guest_zcr = read_sysreg_s(SYS_ZCR_EL12);
+	} else if (host_has_sve) {
 		/*
 		 * The FPSIMD/SVE state in the CPU has not been touched, and we
 		 * have SVE (and VHE): CPACR_EL1 (alias CPTR_EL2) has been
diff --git a/arch/arm64/kvm/hyp/switch.c b/arch/arm64/kvm/hyp/switch.c
index b0b1478..9f07403 100644
--- a/arch/arm64/kvm/hyp/switch.c
+++ b/arch/arm64/kvm/hyp/switch.c
@@ -347,6 +347,9 @@ static bool __hyp_text __hyp_switch_fpsimd(struct kvm_vcpu *vcpu)
 
 	__fpsimd_restore_state(&vcpu->arch.ctxt.gp_regs.fp_regs);
 
+	if (vcpu_has_sve(vcpu))
+		write_sysreg_s(vcpu->arch.ctxt.sys_regs[ZCR_EL1], SYS_ZCR_EL12);
+
 	/* Skip restoring fpexc32 for AArch64 guests */
 	if (!(read_sysreg(hcr_el2) & HCR_RW))
 		write_sysreg(vcpu->arch.ctxt.sys_regs[FPEXC32_EL2],
diff --git a/arch/arm64/kvm/sys_regs.c b/arch/arm64/kvm/sys_regs.c
index 3f1243e..28b1bad 100644
--- a/arch/arm64/kvm/sys_regs.c
+++ b/arch/arm64/kvm/sys_regs.c
@@ -1036,10 +1036,7 @@ static u64 read_id_reg(const struct kvm_vcpu *vcpu,
 			 (u32)r->CRn, (u32)r->CRm, (u32)r->Op2);
 	u64 val = raz ? 0 : read_sanitised_ftr_reg(id);
 
-	if (id == SYS_ID_AA64PFR0_EL1) {
-		if (val & (0xfUL << ID_AA64PFR0_SVE_SHIFT))
-			kvm_debug("SVE unsupported for guests, suppressing\n");
-
+	if (id == SYS_ID_AA64PFR0_EL1 && !vcpu_has_sve(vcpu)) {
 		val &= ~(0xfUL << ID_AA64PFR0_SVE_SHIFT);
 	} else if (id == SYS_ID_AA64ISAR1_EL1) {
 		const u64 ptrauth_mask = (0xfUL << ID_AA64ISAR1_APA_SHIFT) |
@@ -1091,6 +1088,95 @@ static int reg_from_user(u64 *val, const void __user *uaddr, u64 id);
 static int reg_to_user(void __user *uaddr, const u64 *val, u64 id);
 static u64 sys_reg_to_index(const struct sys_reg_desc *reg);
 
+static unsigned int sve_restrictions(const struct kvm_vcpu *vcpu,
+				     const struct sys_reg_desc *rd)
+{
+	return vcpu_has_sve(vcpu) ? 0 : REG_NO_USER | REG_NO_GUEST;
+}
+
+static unsigned int sve_id_restrictions(const struct kvm_vcpu *vcpu,
+					const struct sys_reg_desc *rd)
+{
+	return vcpu_has_sve(vcpu) ? 0 : REG_NO_USER;
+}
+
+static int get_zcr_el1(struct kvm_vcpu *vcpu,
+		       const struct sys_reg_desc *rd,
+		       const struct kvm_one_reg *reg, void __user *uaddr)
+{
+	if (WARN_ON(!vcpu_has_sve(vcpu)))
+		return -ENOENT;
+
+	return reg_to_user(uaddr, &vcpu->arch.ctxt.sys_regs[ZCR_EL1],
+			   reg->id);
+}
+
+static int set_zcr_el1(struct kvm_vcpu *vcpu,
+		       const struct sys_reg_desc *rd,
+		       const struct kvm_one_reg *reg, void __user *uaddr)
+{
+	if (WARN_ON(!vcpu_has_sve(vcpu)))
+		return -ENOENT;
+
+	return reg_from_user(&vcpu->arch.ctxt.sys_regs[ZCR_EL1], uaddr,
+			     reg->id);
+}
+
+/* Generate the emulated ID_AA64ZFR0_EL1 value exposed to the guest */
+static u64 guest_id_aa64zfr0_el1(const struct kvm_vcpu *vcpu)
+{
+	if (!vcpu_has_sve(vcpu))
+		return 0;
+
+	return read_sanitised_ftr_reg(SYS_ID_AA64ZFR0_EL1);
+}
+
+static bool access_id_aa64zfr0_el1(struct kvm_vcpu *vcpu,
+				   struct sys_reg_params *p,
+				   const struct sys_reg_desc *rd)
+{
+	if (p->is_write)
+		return write_to_read_only(vcpu, p, rd);
+
+	p->regval = guest_id_aa64zfr0_el1(vcpu);
+	return true;
+}
+
+static int get_id_aa64zfr0_el1(struct kvm_vcpu *vcpu,
+		const struct sys_reg_desc *rd,
+		const struct kvm_one_reg *reg, void __user *uaddr)
+{
+	u64 val;
+
+	if (!vcpu_has_sve(vcpu))
+		return -ENOENT;
+
+	val = guest_id_aa64zfr0_el1(vcpu);
+	return reg_to_user(uaddr, &val, reg->id);
+}
+
+static int set_id_aa64zfr0_el1(struct kvm_vcpu *vcpu,
+		const struct sys_reg_desc *rd,
+		const struct kvm_one_reg *reg, void __user *uaddr)
+{
+	const u64 id = sys_reg_to_index(rd);
+	int err;
+	u64 val;
+
+	if (!vcpu_has_sve(vcpu))
+		return -ENOENT;
+
+	err = reg_from_user(&val, uaddr, id);
+	if (err)
+		return err;
+
+	/* This is what we mean by invariant: you can't change it. */
+	if (val != guest_id_aa64zfr0_el1(vcpu))
+		return -EINVAL;
+
+	return 0;
+}
+
 /*
  * cpufeature ID register user accessors
  *
@@ -1278,7 +1364,7 @@ static const struct sys_reg_desc sys_reg_descs[] = {
 	ID_SANITISED(ID_AA64PFR1_EL1),
 	ID_UNALLOCATED(4,2),
 	ID_UNALLOCATED(4,3),
-	ID_UNALLOCATED(4,4),
+	{ SYS_DESC(SYS_ID_AA64ZFR0_EL1), access_id_aa64zfr0_el1, .get_user = get_id_aa64zfr0_el1, .set_user = set_id_aa64zfr0_el1, .restrictions = sve_id_restrictions },
 	ID_UNALLOCATED(4,5),
 	ID_UNALLOCATED(4,6),
 	ID_UNALLOCATED(4,7),
@@ -1315,6 +1401,7 @@ static const struct sys_reg_desc sys_reg_descs[] = {
 
 	{ SYS_DESC(SYS_SCTLR_EL1), access_vm_reg, reset_val, SCTLR_EL1, 0x00C50078 },
 	{ SYS_DESC(SYS_CPACR_EL1), NULL, reset_val, CPACR_EL1, 0 },
+	{ SYS_DESC(SYS_ZCR_EL1), NULL, reset_unknown, ZCR_EL1, ~0xfUL, .get_user = get_zcr_el1, .set_user = set_zcr_el1, .restrictions = sve_restrictions },
 	{ SYS_DESC(SYS_TTBR0_EL1), access_vm_reg, reset_unknown, TTBR0_EL1 },
 	{ SYS_DESC(SYS_TTBR1_EL1), access_vm_reg, reset_unknown, TTBR1_EL1 },
 	{ SYS_DESC(SYS_TCR_EL1), access_vm_reg, reset_val, TCR_EL1, 0 },
-- 
2.1.4


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* [PATCH v5 14/26] KVM: arm64/sve: Context switch the SVE registers
  2019-02-18 19:52 ` Dave Martin
@ 2019-02-18 19:52   ` Dave Martin
  -1 siblings, 0 replies; 205+ messages in thread
From: Dave Martin @ 2019-02-18 19:52 UTC (permalink / raw)
  To: kvmarm
  Cc: Okamoto Takayuki, Christoffer Dall, Ard Biesheuvel, Marc Zyngier,
	Catalin Marinas, Will Deacon, Zhang Lei, linux-arm-kernel

In order to give each vcpu its own view of the SVE registers, this
patch adds context storage via a new sve_state pointer in struct
vcpu_arch.  An additional member sve_max_vl is also added for each
vcpu, to determine the maximum vector length visible to the guest
and thus the value to be configured in ZCR_EL2.LEN while the is
active.  This also determines the layout and size of the storage in
sve_state, which is read and written by the same backend functions
that are used for context-switching the SVE state for host tasks.

On SVE-enabled vcpus, SVE access traps are now handled by switching
in the vcpu's SVE context and disabling the trap before returning
to the guest.  On other vcpus, the trap is not handled and an exit
back to the host occurs, where the handle_sve() fallback path
reflects an undefined instruction exception back to the guest,
consistently with the behaviour of non-SVE-capable hardware (as was
done unconditionally prior to this patch).

No SVE handling is added on non-VHE-only paths, since VHE is an
architectural and Kconfig prerequisite of SVE.

Signed-off-by: Dave Martin <Dave.Martin@arm.com>

---

Changes since v4:

 * Remove if_sve() helper in favour of open-coded static key checks.

 * Explicitly merge static key checks and other condition checks to
   reduce overhead and maximise const-folding and specialisation
   opportunities in the compiler.
---
 arch/arm64/include/asm/kvm_host.h |  6 ++++
 arch/arm64/kvm/fpsimd.c           |  5 +--
 arch/arm64/kvm/hyp/switch.c       | 70 +++++++++++++++++++++++++++++----------
 3 files changed, 61 insertions(+), 20 deletions(-)

diff --git a/arch/arm64/include/asm/kvm_host.h b/arch/arm64/include/asm/kvm_host.h
index c32f195..77b6f3e 100644
--- a/arch/arm64/include/asm/kvm_host.h
+++ b/arch/arm64/include/asm/kvm_host.h
@@ -212,6 +212,8 @@ typedef struct kvm_cpu_context kvm_cpu_context_t;
 
 struct kvm_vcpu_arch {
 	struct kvm_cpu_context ctxt;
+	void *sve_state;
+	unsigned int sve_max_vl;
 
 	/* HYP configuration */
 	u64 hcr_el2;
@@ -304,6 +306,10 @@ struct kvm_vcpu_arch {
 	bool sysregs_loaded_on_cpu;
 };
 
+/* Pointer to the vcpu's SVE FFR for sve_{save,load}_state() */
+#define vcpu_sve_pffr(vcpu) ((void *)((char *)((vcpu)->arch.sve_state) + \
+				      sve_ffr_offset((vcpu)->arch.sve_max_vl)))
+
 /* vcpu_arch flags field values: */
 #define KVM_ARM64_DEBUG_DIRTY		(1 << 0)
 #define KVM_ARM64_FP_ENABLED		(1 << 1) /* guest FP regs loaded */
diff --git a/arch/arm64/kvm/fpsimd.c b/arch/arm64/kvm/fpsimd.c
index 7053bf4..6e3c9c8 100644
--- a/arch/arm64/kvm/fpsimd.c
+++ b/arch/arm64/kvm/fpsimd.c
@@ -87,10 +87,11 @@ void kvm_arch_vcpu_ctxsync_fp(struct kvm_vcpu *vcpu)
 
 	if (vcpu->arch.flags & KVM_ARM64_FP_ENABLED) {
 		fpsimd_bind_state_to_cpu(&vcpu->arch.ctxt.gp_regs.fp_regs,
-					 NULL, SVE_VL_MIN);
+					 vcpu->arch.sve_state,
+					 vcpu->arch.sve_max_vl);
 
 		clear_thread_flag(TIF_FOREIGN_FPSTATE);
-		clear_thread_flag(TIF_SVE);
+		update_thread_flag(TIF_SVE, vcpu_has_sve(vcpu));
 	}
 }
 
diff --git a/arch/arm64/kvm/hyp/switch.c b/arch/arm64/kvm/hyp/switch.c
index 9f07403..cdc9063 100644
--- a/arch/arm64/kvm/hyp/switch.c
+++ b/arch/arm64/kvm/hyp/switch.c
@@ -98,7 +98,10 @@ static void activate_traps_vhe(struct kvm_vcpu *vcpu)
 	val = read_sysreg(cpacr_el1);
 	val |= CPACR_EL1_TTA;
 	val &= ~CPACR_EL1_ZEN;
-	if (!update_fp_enabled(vcpu)) {
+	if (update_fp_enabled(vcpu)) {
+		if (vcpu_has_sve(vcpu))
+			val |= CPACR_EL1_ZEN;
+	} else {
 		val &= ~CPACR_EL1_FPEN;
 		__activate_traps_fpsimd32(vcpu);
 	}
@@ -313,16 +316,43 @@ static bool __hyp_text __populate_fault_info(struct kvm_vcpu *vcpu)
 	return true;
 }
 
-static bool __hyp_text __hyp_switch_fpsimd(struct kvm_vcpu *vcpu)
+/* Check for an FPSIMD/SVE trap and handle as appropriate */
+static bool __hyp_text __hyp_handle_fpsimd(struct kvm_vcpu *vcpu)
 {
-	struct user_fpsimd_state *host_fpsimd = vcpu->arch.host_fpsimd_state;
+	bool vhe, sve_guest, sve_host;
+	u8 trap_class;
 
-	if (has_vhe())
-		write_sysreg(read_sysreg(cpacr_el1) | CPACR_EL1_FPEN,
-			     cpacr_el1);
-	else
+	if (!system_supports_fpsimd())
+		return false;
+
+	if (system_supports_sve()) {
+		sve_guest = vcpu_has_sve(vcpu);
+		sve_host = vcpu->arch.flags & KVM_ARM64_HOST_SVE_IN_USE;
+		vhe = true;
+	} else {
+		sve_guest = false;
+		sve_host = false;
+		vhe = has_vhe();
+	}
+
+	trap_class = kvm_vcpu_trap_get_class(vcpu);
+	if (trap_class != ESR_ELx_EC_FP_ASIMD &&
+	    (!sve_guest || trap_class != ESR_ELx_EC_SVE))
+		return false;
+
+	/* The trap is an FPSIMD/SVE trap: switch the context */
+
+	if (vhe) {
+		u64 reg = read_sysreg(cpacr_el1) | CPACR_EL1_FPEN;
+
+		if (sve_guest)
+			reg |= CPACR_EL1_ZEN;
+
+		write_sysreg(reg, cpacr_el1);
+	} else {
 		write_sysreg(read_sysreg(cptr_el2) & ~(u64)CPTR_EL2_TFP,
 			     cptr_el2);
+	}
 
 	isb();
 
@@ -331,24 +361,28 @@ static bool __hyp_text __hyp_switch_fpsimd(struct kvm_vcpu *vcpu)
 		 * In the SVE case, VHE is assumed: it is enforced by
 		 * Kconfig and kvm_arch_init().
 		 */
-		if (system_supports_sve() &&
-		    (vcpu->arch.flags & KVM_ARM64_HOST_SVE_IN_USE)) {
+		if (sve_host) {
 			struct thread_struct *thread = container_of(
-				host_fpsimd,
+				vcpu->arch.host_fpsimd_state,
 				struct thread_struct, uw.fpsimd_state);
 
-			sve_save_state(sve_pffr(thread), &host_fpsimd->fpsr);
+			sve_save_state(sve_pffr(thread),
+				       &vcpu->arch.host_fpsimd_state->fpsr);
 		} else {
-			__fpsimd_save_state(host_fpsimd);
+			__fpsimd_save_state(vcpu->arch.host_fpsimd_state);
 		}
 
 		vcpu->arch.flags &= ~KVM_ARM64_FP_HOST;
 	}
 
-	__fpsimd_restore_state(&vcpu->arch.ctxt.gp_regs.fp_regs);
-
-	if (vcpu_has_sve(vcpu))
+	if (sve_guest) {
+		sve_load_state(vcpu_sve_pffr(vcpu),
+			       &vcpu->arch.ctxt.gp_regs.fp_regs.fpsr,
+			       sve_vq_from_vl(vcpu->arch.sve_max_vl) - 1);
 		write_sysreg_s(vcpu->arch.ctxt.sys_regs[ZCR_EL1], SYS_ZCR_EL12);
+	} else {
+		__fpsimd_restore_state(&vcpu->arch.ctxt.gp_regs.fp_regs);
+	}
 
 	/* Skip restoring fpexc32 for AArch64 guests */
 	if (!(read_sysreg(hcr_el2) & HCR_RW))
@@ -384,10 +418,10 @@ static bool __hyp_text fixup_guest_exit(struct kvm_vcpu *vcpu, u64 *exit_code)
 	 * and restore the guest context lazily.
 	 * If FP/SIMD is not implemented, handle the trap and inject an
 	 * undefined instruction exception to the guest.
+	 * Similarly for trapped SVE accesses.
 	 */
-	if (system_supports_fpsimd() &&
-	    kvm_vcpu_trap_get_class(vcpu) == ESR_ELx_EC_FP_ASIMD)
-		return __hyp_switch_fpsimd(vcpu);
+	if (__hyp_handle_fpsimd(vcpu))
+		return true;
 
 	if (!__populate_fault_info(vcpu))
 		return true;
-- 
2.1.4

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

* [PATCH v5 14/26] KVM: arm64/sve: Context switch the SVE registers
@ 2019-02-18 19:52   ` Dave Martin
  0 siblings, 0 replies; 205+ messages in thread
From: Dave Martin @ 2019-02-18 19:52 UTC (permalink / raw)
  To: kvmarm
  Cc: Peter Maydell, Okamoto Takayuki, Christoffer Dall,
	Ard Biesheuvel, Marc Zyngier, Catalin Marinas, Will Deacon,
	Zhang Lei, Julien Grall, Alex Bennée, linux-arm-kernel

In order to give each vcpu its own view of the SVE registers, this
patch adds context storage via a new sve_state pointer in struct
vcpu_arch.  An additional member sve_max_vl is also added for each
vcpu, to determine the maximum vector length visible to the guest
and thus the value to be configured in ZCR_EL2.LEN while the is
active.  This also determines the layout and size of the storage in
sve_state, which is read and written by the same backend functions
that are used for context-switching the SVE state for host tasks.

On SVE-enabled vcpus, SVE access traps are now handled by switching
in the vcpu's SVE context and disabling the trap before returning
to the guest.  On other vcpus, the trap is not handled and an exit
back to the host occurs, where the handle_sve() fallback path
reflects an undefined instruction exception back to the guest,
consistently with the behaviour of non-SVE-capable hardware (as was
done unconditionally prior to this patch).

No SVE handling is added on non-VHE-only paths, since VHE is an
architectural and Kconfig prerequisite of SVE.

Signed-off-by: Dave Martin <Dave.Martin@arm.com>

---

Changes since v4:

 * Remove if_sve() helper in favour of open-coded static key checks.

 * Explicitly merge static key checks and other condition checks to
   reduce overhead and maximise const-folding and specialisation
   opportunities in the compiler.
---
 arch/arm64/include/asm/kvm_host.h |  6 ++++
 arch/arm64/kvm/fpsimd.c           |  5 +--
 arch/arm64/kvm/hyp/switch.c       | 70 +++++++++++++++++++++++++++++----------
 3 files changed, 61 insertions(+), 20 deletions(-)

diff --git a/arch/arm64/include/asm/kvm_host.h b/arch/arm64/include/asm/kvm_host.h
index c32f195..77b6f3e 100644
--- a/arch/arm64/include/asm/kvm_host.h
+++ b/arch/arm64/include/asm/kvm_host.h
@@ -212,6 +212,8 @@ typedef struct kvm_cpu_context kvm_cpu_context_t;
 
 struct kvm_vcpu_arch {
 	struct kvm_cpu_context ctxt;
+	void *sve_state;
+	unsigned int sve_max_vl;
 
 	/* HYP configuration */
 	u64 hcr_el2;
@@ -304,6 +306,10 @@ struct kvm_vcpu_arch {
 	bool sysregs_loaded_on_cpu;
 };
 
+/* Pointer to the vcpu's SVE FFR for sve_{save,load}_state() */
+#define vcpu_sve_pffr(vcpu) ((void *)((char *)((vcpu)->arch.sve_state) + \
+				      sve_ffr_offset((vcpu)->arch.sve_max_vl)))
+
 /* vcpu_arch flags field values: */
 #define KVM_ARM64_DEBUG_DIRTY		(1 << 0)
 #define KVM_ARM64_FP_ENABLED		(1 << 1) /* guest FP regs loaded */
diff --git a/arch/arm64/kvm/fpsimd.c b/arch/arm64/kvm/fpsimd.c
index 7053bf4..6e3c9c8 100644
--- a/arch/arm64/kvm/fpsimd.c
+++ b/arch/arm64/kvm/fpsimd.c
@@ -87,10 +87,11 @@ void kvm_arch_vcpu_ctxsync_fp(struct kvm_vcpu *vcpu)
 
 	if (vcpu->arch.flags & KVM_ARM64_FP_ENABLED) {
 		fpsimd_bind_state_to_cpu(&vcpu->arch.ctxt.gp_regs.fp_regs,
-					 NULL, SVE_VL_MIN);
+					 vcpu->arch.sve_state,
+					 vcpu->arch.sve_max_vl);
 
 		clear_thread_flag(TIF_FOREIGN_FPSTATE);
-		clear_thread_flag(TIF_SVE);
+		update_thread_flag(TIF_SVE, vcpu_has_sve(vcpu));
 	}
 }
 
diff --git a/arch/arm64/kvm/hyp/switch.c b/arch/arm64/kvm/hyp/switch.c
index 9f07403..cdc9063 100644
--- a/arch/arm64/kvm/hyp/switch.c
+++ b/arch/arm64/kvm/hyp/switch.c
@@ -98,7 +98,10 @@ static void activate_traps_vhe(struct kvm_vcpu *vcpu)
 	val = read_sysreg(cpacr_el1);
 	val |= CPACR_EL1_TTA;
 	val &= ~CPACR_EL1_ZEN;
-	if (!update_fp_enabled(vcpu)) {
+	if (update_fp_enabled(vcpu)) {
+		if (vcpu_has_sve(vcpu))
+			val |= CPACR_EL1_ZEN;
+	} else {
 		val &= ~CPACR_EL1_FPEN;
 		__activate_traps_fpsimd32(vcpu);
 	}
@@ -313,16 +316,43 @@ static bool __hyp_text __populate_fault_info(struct kvm_vcpu *vcpu)
 	return true;
 }
 
-static bool __hyp_text __hyp_switch_fpsimd(struct kvm_vcpu *vcpu)
+/* Check for an FPSIMD/SVE trap and handle as appropriate */
+static bool __hyp_text __hyp_handle_fpsimd(struct kvm_vcpu *vcpu)
 {
-	struct user_fpsimd_state *host_fpsimd = vcpu->arch.host_fpsimd_state;
+	bool vhe, sve_guest, sve_host;
+	u8 trap_class;
 
-	if (has_vhe())
-		write_sysreg(read_sysreg(cpacr_el1) | CPACR_EL1_FPEN,
-			     cpacr_el1);
-	else
+	if (!system_supports_fpsimd())
+		return false;
+
+	if (system_supports_sve()) {
+		sve_guest = vcpu_has_sve(vcpu);
+		sve_host = vcpu->arch.flags & KVM_ARM64_HOST_SVE_IN_USE;
+		vhe = true;
+	} else {
+		sve_guest = false;
+		sve_host = false;
+		vhe = has_vhe();
+	}
+
+	trap_class = kvm_vcpu_trap_get_class(vcpu);
+	if (trap_class != ESR_ELx_EC_FP_ASIMD &&
+	    (!sve_guest || trap_class != ESR_ELx_EC_SVE))
+		return false;
+
+	/* The trap is an FPSIMD/SVE trap: switch the context */
+
+	if (vhe) {
+		u64 reg = read_sysreg(cpacr_el1) | CPACR_EL1_FPEN;
+
+		if (sve_guest)
+			reg |= CPACR_EL1_ZEN;
+
+		write_sysreg(reg, cpacr_el1);
+	} else {
 		write_sysreg(read_sysreg(cptr_el2) & ~(u64)CPTR_EL2_TFP,
 			     cptr_el2);
+	}
 
 	isb();
 
@@ -331,24 +361,28 @@ static bool __hyp_text __hyp_switch_fpsimd(struct kvm_vcpu *vcpu)
 		 * In the SVE case, VHE is assumed: it is enforced by
 		 * Kconfig and kvm_arch_init().
 		 */
-		if (system_supports_sve() &&
-		    (vcpu->arch.flags & KVM_ARM64_HOST_SVE_IN_USE)) {
+		if (sve_host) {
 			struct thread_struct *thread = container_of(
-				host_fpsimd,
+				vcpu->arch.host_fpsimd_state,
 				struct thread_struct, uw.fpsimd_state);
 
-			sve_save_state(sve_pffr(thread), &host_fpsimd->fpsr);
+			sve_save_state(sve_pffr(thread),
+				       &vcpu->arch.host_fpsimd_state->fpsr);
 		} else {
-			__fpsimd_save_state(host_fpsimd);
+			__fpsimd_save_state(vcpu->arch.host_fpsimd_state);
 		}
 
 		vcpu->arch.flags &= ~KVM_ARM64_FP_HOST;
 	}
 
-	__fpsimd_restore_state(&vcpu->arch.ctxt.gp_regs.fp_regs);
-
-	if (vcpu_has_sve(vcpu))
+	if (sve_guest) {
+		sve_load_state(vcpu_sve_pffr(vcpu),
+			       &vcpu->arch.ctxt.gp_regs.fp_regs.fpsr,
+			       sve_vq_from_vl(vcpu->arch.sve_max_vl) - 1);
 		write_sysreg_s(vcpu->arch.ctxt.sys_regs[ZCR_EL1], SYS_ZCR_EL12);
+	} else {
+		__fpsimd_restore_state(&vcpu->arch.ctxt.gp_regs.fp_regs);
+	}
 
 	/* Skip restoring fpexc32 for AArch64 guests */
 	if (!(read_sysreg(hcr_el2) & HCR_RW))
@@ -384,10 +418,10 @@ static bool __hyp_text fixup_guest_exit(struct kvm_vcpu *vcpu, u64 *exit_code)
 	 * and restore the guest context lazily.
 	 * If FP/SIMD is not implemented, handle the trap and inject an
 	 * undefined instruction exception to the guest.
+	 * Similarly for trapped SVE accesses.
 	 */
-	if (system_supports_fpsimd() &&
-	    kvm_vcpu_trap_get_class(vcpu) == ESR_ELx_EC_FP_ASIMD)
-		return __hyp_switch_fpsimd(vcpu);
+	if (__hyp_handle_fpsimd(vcpu))
+		return true;
 
 	if (!__populate_fault_info(vcpu))
 		return true;
-- 
2.1.4


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* [PATCH v5 15/26] KVM: Allow 2048-bit register access via ioctl interface
  2019-02-18 19:52 ` Dave Martin
@ 2019-02-18 19:52   ` Dave Martin
  -1 siblings, 0 replies; 205+ messages in thread
From: Dave Martin @ 2019-02-18 19:52 UTC (permalink / raw)
  To: kvmarm
  Cc: Okamoto Takayuki, Christoffer Dall, Ard Biesheuvel, Marc Zyngier,
	Catalin Marinas, Will Deacon, Zhang Lei, linux-arm-kernel

The Arm SVE architecture defines registers that are up to 2048 bits
in size (with some possibility of further future expansion).

In order to avoid the need for an excessively large number of
ioctls when saving and restoring a vcpu's registers, this patch
adds a #define to make support for individual 2048-bit registers
through the KVM_{GET,SET}_ONE_REG ioctl interface official.  This
will allow each SVE register to be accessed in a single call.

There are sufficient spare bits in the register id size field for
this change, so there is no ABI impact providing that
KVM_GET_REG_LIST does not enumerate any 2048-bit register unless
userspace explicitly opts in to the relevant architecture-specific
features.

Signed-off-by: Dave Martin <Dave.Martin@arm.com>
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
---
 include/uapi/linux/kvm.h | 1 +
 1 file changed, 1 insertion(+)

diff --git a/include/uapi/linux/kvm.h b/include/uapi/linux/kvm.h
index 6d4ea4b..dc77a5a 100644
--- a/include/uapi/linux/kvm.h
+++ b/include/uapi/linux/kvm.h
@@ -1145,6 +1145,7 @@ struct kvm_dirty_tlb {
 #define KVM_REG_SIZE_U256	0x0050000000000000ULL
 #define KVM_REG_SIZE_U512	0x0060000000000000ULL
 #define KVM_REG_SIZE_U1024	0x0070000000000000ULL
+#define KVM_REG_SIZE_U2048	0x0080000000000000ULL
 
 struct kvm_reg_list {
 	__u64 n; /* number of regs */
-- 
2.1.4

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

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

* [PATCH v5 15/26] KVM: Allow 2048-bit register access via ioctl interface
@ 2019-02-18 19:52   ` Dave Martin
  0 siblings, 0 replies; 205+ messages in thread
From: Dave Martin @ 2019-02-18 19:52 UTC (permalink / raw)
  To: kvmarm
  Cc: Peter Maydell, Okamoto Takayuki, Christoffer Dall,
	Ard Biesheuvel, Marc Zyngier, Catalin Marinas, Will Deacon,
	Zhang Lei, Julien Grall, Alex Bennée, linux-arm-kernel

The Arm SVE architecture defines registers that are up to 2048 bits
in size (with some possibility of further future expansion).

In order to avoid the need for an excessively large number of
ioctls when saving and restoring a vcpu's registers, this patch
adds a #define to make support for individual 2048-bit registers
through the KVM_{GET,SET}_ONE_REG ioctl interface official.  This
will allow each SVE register to be accessed in a single call.

There are sufficient spare bits in the register id size field for
this change, so there is no ABI impact providing that
KVM_GET_REG_LIST does not enumerate any 2048-bit register unless
userspace explicitly opts in to the relevant architecture-specific
features.

Signed-off-by: Dave Martin <Dave.Martin@arm.com>
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
---
 include/uapi/linux/kvm.h | 1 +
 1 file changed, 1 insertion(+)

diff --git a/include/uapi/linux/kvm.h b/include/uapi/linux/kvm.h
index 6d4ea4b..dc77a5a 100644
--- a/include/uapi/linux/kvm.h
+++ b/include/uapi/linux/kvm.h
@@ -1145,6 +1145,7 @@ struct kvm_dirty_tlb {
 #define KVM_REG_SIZE_U256	0x0050000000000000ULL
 #define KVM_REG_SIZE_U512	0x0060000000000000ULL
 #define KVM_REG_SIZE_U1024	0x0070000000000000ULL
+#define KVM_REG_SIZE_U2048	0x0080000000000000ULL
 
 struct kvm_reg_list {
 	__u64 n; /* number of regs */
-- 
2.1.4


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* [PATCH v5 16/26] KVM: arm64: Add missing #include of <linux/string.h> in guest.c
  2019-02-18 19:52 ` Dave Martin
@ 2019-02-18 19:52   ` Dave Martin
  -1 siblings, 0 replies; 205+ messages in thread
From: Dave Martin @ 2019-02-18 19:52 UTC (permalink / raw)
  To: kvmarm
  Cc: Okamoto Takayuki, Christoffer Dall, Ard Biesheuvel, Marc Zyngier,
	Catalin Marinas, Will Deacon, Zhang Lei, linux-arm-kernel

arch/arm64/kvm/guest.c uses the string functions, but the
corresponding header is not included.

We seem to get away with this for now, but for completeness this
patch adds the #include, in preparation for adding yet more
memset() calls.

Signed-off-by: Dave Martin <Dave.Martin@arm.com>
---
 arch/arm64/kvm/guest.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/arch/arm64/kvm/guest.c b/arch/arm64/kvm/guest.c
index 65f4338..f83fe22 100644
--- a/arch/arm64/kvm/guest.c
+++ b/arch/arm64/kvm/guest.c
@@ -23,6 +23,7 @@
 #include <linux/err.h>
 #include <linux/kvm_host.h>
 #include <linux/module.h>
+#include <linux/string.h>
 #include <linux/vmalloc.h>
 #include <linux/fs.h>
 #include <kvm/arm_psci.h>
-- 
2.1.4

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

* [PATCH v5 16/26] KVM: arm64: Add missing #include of <linux/string.h> in guest.c
@ 2019-02-18 19:52   ` Dave Martin
  0 siblings, 0 replies; 205+ messages in thread
From: Dave Martin @ 2019-02-18 19:52 UTC (permalink / raw)
  To: kvmarm
  Cc: Peter Maydell, Okamoto Takayuki, Christoffer Dall,
	Ard Biesheuvel, Marc Zyngier, Catalin Marinas, Will Deacon,
	Zhang Lei, Julien Grall, Alex Bennée, linux-arm-kernel

arch/arm64/kvm/guest.c uses the string functions, but the
corresponding header is not included.

We seem to get away with this for now, but for completeness this
patch adds the #include, in preparation for adding yet more
memset() calls.

Signed-off-by: Dave Martin <Dave.Martin@arm.com>
---
 arch/arm64/kvm/guest.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/arch/arm64/kvm/guest.c b/arch/arm64/kvm/guest.c
index 65f4338..f83fe22 100644
--- a/arch/arm64/kvm/guest.c
+++ b/arch/arm64/kvm/guest.c
@@ -23,6 +23,7 @@
 #include <linux/err.h>
 #include <linux/kvm_host.h>
 #include <linux/module.h>
+#include <linux/string.h>
 #include <linux/vmalloc.h>
 #include <linux/fs.h>
 #include <kvm/arm_psci.h>
-- 
2.1.4


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* [PATCH v5 17/26] KVM: arm64: Reject ioctl access to FPSIMD V-regs on SVE vcpus
  2019-02-18 19:52 ` Dave Martin
@ 2019-02-18 19:52   ` Dave Martin
  -1 siblings, 0 replies; 205+ messages in thread
From: Dave Martin @ 2019-02-18 19:52 UTC (permalink / raw)
  To: kvmarm
  Cc: Okamoto Takayuki, Christoffer Dall, Ard Biesheuvel, Marc Zyngier,
	Catalin Marinas, Will Deacon, Zhang Lei, linux-arm-kernel

In order to avoid the pointless complexity of maintaining two ioctl
register access views of the same data, this patch blocks ioctl
access to the FPSIMD V-registers on vcpus that support SVE.

This will make it more straightforward to add SVE register access
support.

Since SVE is an opt-in feature for userspace, this will not affect
existing users.

Signed-off-by: Dave Martin <Dave.Martin@arm.com>
---
 arch/arm64/kvm/guest.c | 38 +++++++++++++++++++++++++++-----------
 1 file changed, 27 insertions(+), 11 deletions(-)

diff --git a/arch/arm64/kvm/guest.c b/arch/arm64/kvm/guest.c
index f83fe22..f491456 100644
--- a/arch/arm64/kvm/guest.c
+++ b/arch/arm64/kvm/guest.c
@@ -95,7 +95,14 @@ static int core_reg_size_from_offset(u64 off)
 	return -EINVAL;
 }
 
-static int validate_core_offset(const struct kvm_one_reg *reg)
+static bool core_reg_offset_is_vreg(u64 off)
+{
+	return off >= KVM_REG_ARM_CORE_REG(fp_regs.vregs) &&
+		off < KVM_REG_ARM_CORE_REG(fp_regs.fpsr);
+}
+
+static int validate_core_offset(const struct kvm_vcpu *vcpu,
+				const struct kvm_one_reg *reg)
 {
 	u64 off = core_reg_offset_from_id(reg->id);
 	int size = core_reg_size_from_offset(off);
@@ -103,10 +110,18 @@ static int validate_core_offset(const struct kvm_one_reg *reg)
 	if (size < 0)
 		return -EINVAL;
 
-	if (KVM_REG_SIZE(reg->id) == size)
-		return 0;
+	if (KVM_REG_SIZE(reg->id) != size)
+		return -EINVAL;
 
-	return -EINVAL;
+	/*
+	 * The KVM_REG_ARM64_SVE regs must be used instead of
+	 * KVM_REG_ARM_CORE for accessing the FPSIMD V-registers on
+	 * SVE-enabled vcpus:
+	 */
+	if (vcpu_has_sve(vcpu) && core_reg_offset_is_vreg(off))
+		return -EINVAL;
+
+	return 0;
 }
 
 static int get_core_reg(struct kvm_vcpu *vcpu, const struct kvm_one_reg *reg)
@@ -128,7 +143,7 @@ static int get_core_reg(struct kvm_vcpu *vcpu, const struct kvm_one_reg *reg)
 	    (off + (KVM_REG_SIZE(reg->id) / sizeof(__u32))) >= nr_regs)
 		return -ENOENT;
 
-	if (validate_core_offset(reg))
+	if (validate_core_offset(vcpu, reg))
 		return -EINVAL;
 
 	if (copy_to_user(uaddr, ((u32 *)regs) + off, KVM_REG_SIZE(reg->id)))
@@ -153,7 +168,7 @@ static int set_core_reg(struct kvm_vcpu *vcpu, const struct kvm_one_reg *reg)
 	    (off + (KVM_REG_SIZE(reg->id) / sizeof(__u32))) >= nr_regs)
 		return -ENOENT;
 
-	if (validate_core_offset(reg))
+	if (validate_core_offset(vcpu, reg))
 		return -EINVAL;
 
 	if (KVM_REG_SIZE(reg->id) > sizeof(tmp))
@@ -206,7 +221,8 @@ int kvm_arch_vcpu_ioctl_set_regs(struct kvm_vcpu *vcpu, struct kvm_regs *regs)
 	return -EINVAL;
 }
 
-static int copy_core_reg_indices(u64 __user **uind)
+static int copy_core_reg_indices(const struct kvm_vcpu *vcpu,
+				 u64 __user **uind)
 {
 	unsigned int i;
 	int n = 0;
@@ -248,9 +264,9 @@ static int copy_core_reg_indices(u64 __user **uind)
 	return n;
 }
 
-static unsigned long num_core_regs(void)
+static unsigned long num_core_regs(const struct kvm_vcpu *vcpu)
 {
-	return copy_core_reg_indices(NULL);
+	return copy_core_reg_indices(vcpu, NULL);
 }
 
 /**
@@ -315,7 +331,7 @@ unsigned long kvm_arm_num_regs(struct kvm_vcpu *vcpu)
 {
 	unsigned long res = 0;
 
-	res += num_core_regs();
+	res += num_core_regs(vcpu);
 	res += kvm_arm_num_sys_reg_descs(vcpu);
 	res += kvm_arm_get_fw_num_regs(vcpu);
 	res += NUM_TIMER_REGS;
@@ -332,7 +348,7 @@ int kvm_arm_copy_reg_indices(struct kvm_vcpu *vcpu, u64 __user *uindices)
 {
 	int ret;
 
-	ret = copy_core_reg_indices(&uindices);
+	ret = copy_core_reg_indices(vcpu, &uindices);
 	if (ret < 0)
 		return ret;
 
-- 
2.1.4

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

* [PATCH v5 17/26] KVM: arm64: Reject ioctl access to FPSIMD V-regs on SVE vcpus
@ 2019-02-18 19:52   ` Dave Martin
  0 siblings, 0 replies; 205+ messages in thread
From: Dave Martin @ 2019-02-18 19:52 UTC (permalink / raw)
  To: kvmarm
  Cc: Peter Maydell, Okamoto Takayuki, Christoffer Dall,
	Ard Biesheuvel, Marc Zyngier, Catalin Marinas, Will Deacon,
	Zhang Lei, Julien Grall, Alex Bennée, linux-arm-kernel

In order to avoid the pointless complexity of maintaining two ioctl
register access views of the same data, this patch blocks ioctl
access to the FPSIMD V-registers on vcpus that support SVE.

This will make it more straightforward to add SVE register access
support.

Since SVE is an opt-in feature for userspace, this will not affect
existing users.

Signed-off-by: Dave Martin <Dave.Martin@arm.com>
---
 arch/arm64/kvm/guest.c | 38 +++++++++++++++++++++++++++-----------
 1 file changed, 27 insertions(+), 11 deletions(-)

diff --git a/arch/arm64/kvm/guest.c b/arch/arm64/kvm/guest.c
index f83fe22..f491456 100644
--- a/arch/arm64/kvm/guest.c
+++ b/arch/arm64/kvm/guest.c
@@ -95,7 +95,14 @@ static int core_reg_size_from_offset(u64 off)
 	return -EINVAL;
 }
 
-static int validate_core_offset(const struct kvm_one_reg *reg)
+static bool core_reg_offset_is_vreg(u64 off)
+{
+	return off >= KVM_REG_ARM_CORE_REG(fp_regs.vregs) &&
+		off < KVM_REG_ARM_CORE_REG(fp_regs.fpsr);
+}
+
+static int validate_core_offset(const struct kvm_vcpu *vcpu,
+				const struct kvm_one_reg *reg)
 {
 	u64 off = core_reg_offset_from_id(reg->id);
 	int size = core_reg_size_from_offset(off);
@@ -103,10 +110,18 @@ static int validate_core_offset(const struct kvm_one_reg *reg)
 	if (size < 0)
 		return -EINVAL;
 
-	if (KVM_REG_SIZE(reg->id) == size)
-		return 0;
+	if (KVM_REG_SIZE(reg->id) != size)
+		return -EINVAL;
 
-	return -EINVAL;
+	/*
+	 * The KVM_REG_ARM64_SVE regs must be used instead of
+	 * KVM_REG_ARM_CORE for accessing the FPSIMD V-registers on
+	 * SVE-enabled vcpus:
+	 */
+	if (vcpu_has_sve(vcpu) && core_reg_offset_is_vreg(off))
+		return -EINVAL;
+
+	return 0;
 }
 
 static int get_core_reg(struct kvm_vcpu *vcpu, const struct kvm_one_reg *reg)
@@ -128,7 +143,7 @@ static int get_core_reg(struct kvm_vcpu *vcpu, const struct kvm_one_reg *reg)
 	    (off + (KVM_REG_SIZE(reg->id) / sizeof(__u32))) >= nr_regs)
 		return -ENOENT;
 
-	if (validate_core_offset(reg))
+	if (validate_core_offset(vcpu, reg))
 		return -EINVAL;
 
 	if (copy_to_user(uaddr, ((u32 *)regs) + off, KVM_REG_SIZE(reg->id)))
@@ -153,7 +168,7 @@ static int set_core_reg(struct kvm_vcpu *vcpu, const struct kvm_one_reg *reg)
 	    (off + (KVM_REG_SIZE(reg->id) / sizeof(__u32))) >= nr_regs)
 		return -ENOENT;
 
-	if (validate_core_offset(reg))
+	if (validate_core_offset(vcpu, reg))
 		return -EINVAL;
 
 	if (KVM_REG_SIZE(reg->id) > sizeof(tmp))
@@ -206,7 +221,8 @@ int kvm_arch_vcpu_ioctl_set_regs(struct kvm_vcpu *vcpu, struct kvm_regs *regs)
 	return -EINVAL;
 }
 
-static int copy_core_reg_indices(u64 __user **uind)
+static int copy_core_reg_indices(const struct kvm_vcpu *vcpu,
+				 u64 __user **uind)
 {
 	unsigned int i;
 	int n = 0;
@@ -248,9 +264,9 @@ static int copy_core_reg_indices(u64 __user **uind)
 	return n;
 }
 
-static unsigned long num_core_regs(void)
+static unsigned long num_core_regs(const struct kvm_vcpu *vcpu)
 {
-	return copy_core_reg_indices(NULL);
+	return copy_core_reg_indices(vcpu, NULL);
 }
 
 /**
@@ -315,7 +331,7 @@ unsigned long kvm_arm_num_regs(struct kvm_vcpu *vcpu)
 {
 	unsigned long res = 0;
 
-	res += num_core_regs();
+	res += num_core_regs(vcpu);
 	res += kvm_arm_num_sys_reg_descs(vcpu);
 	res += kvm_arm_get_fw_num_regs(vcpu);
 	res += NUM_TIMER_REGS;
@@ -332,7 +348,7 @@ int kvm_arm_copy_reg_indices(struct kvm_vcpu *vcpu, u64 __user *uindices)
 {
 	int ret;
 
-	ret = copy_core_reg_indices(&uindices);
+	ret = copy_core_reg_indices(vcpu, &uindices);
 	if (ret < 0)
 		return ret;
 
-- 
2.1.4


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* [PATCH v5 18/26] KVM: arm64/sve: Add SVE support to register access ioctl interface
  2019-02-18 19:52 ` Dave Martin
@ 2019-02-18 19:52   ` Dave Martin
  -1 siblings, 0 replies; 205+ messages in thread
From: Dave Martin @ 2019-02-18 19:52 UTC (permalink / raw)
  To: kvmarm
  Cc: Okamoto Takayuki, Christoffer Dall, Ard Biesheuvel, Marc Zyngier,
	Catalin Marinas, Will Deacon, Zhang Lei, linux-arm-kernel

This patch adds the following registers for access via the
KVM_{GET,SET}_ONE_REG interface:

 * KVM_REG_ARM64_SVE_ZREG(n, i) (n = 0..31) (in 2048-bit slices)
 * KVM_REG_ARM64_SVE_PREG(n, i) (n = 0..15) (in 256-bit slices)
 * KVM_REG_ARM64_SVE_FFR(i) (in 256-bit slices)

In order to adapt gracefully to future architectural extensions,
the registers are logically divided up into slices as noted above:
the i parameter denotes the slice index.

This allows us to reserve space in the ABI for future expansion of
these registers.  However, as of today the architecture does not
permit registers to be larger than a single slice, so no code is
needed in the kernel to expose additional slices, for now.  The
code can be extended later as needed to expose them up to a maximum
of 32 slices (as carved out in the architecture itself) if they
really exist someday.

The registers are only visible for vcpus that have SVE enabled.
They are not enumerated by KVM_GET_REG_LIST on vcpus that do not
have SVE.

Accesses to the FPSIMD registers via KVM_REG_ARM_CORE is not
allowed for SVE-enabled vcpus: SVE-aware userspace can use the
KVM_REG_ARM64_SVE_ZREG() interface instead to access the same
register state.  This avoids some complex and pointless emulation
in the kernel to convert between the two views of these aliased
registers.

Signed-off-by: Dave Martin <Dave.Martin@arm.com>

---

Changes since v4:

 * Add "BASE" #defines for the Z-reg and P-reg ranges in the KVM
   register ID space, to make the 0x400 magic number a little less
   cryptic.

 * Pull KVM_SVE_{Z,P}REG_SIZE defines from "KVM: arm64: Enumerate SVE
   register indices for KVM_GET_REG_LIST", since we now use them here.

 * Simplify sve_reg_region(), and give up on the attempt to make
   kreg_region a general thing: nothing else will use it for now,
   anyway, so let's keep it as simple as possible.

 * Drop support for multiple slices per register.  This functionality
   can be added back in later if needed, without ABI breaks.

 * Pull vcpu_sve_state_size() into kvm_host.h, from "KVM: arm64/sve:
   Allow userspace to enable SVE for vcpus".  This is needed for use
   with array_index_nospec() to determine the applicable buffer bounds.
   To avoid circular header deependency issues, the function is also
   converted into a macro, but is otherwise equivalent to the original
   version.

 * Guard sve_state base offset in kernel memory with
   array_index_nospec(), since it is generated from user data that can
   put it out of range.

   (sve_state will get allocated with the corresponding size later in
   the series.  For now, this code is dormant since no means is
   provided for userspace to create SVE-enabled vcpus yet.)
---
 arch/arm64/include/asm/kvm_host.h |  14 ++++
 arch/arm64/include/uapi/asm/kvm.h |  17 +++++
 arch/arm64/kvm/guest.c            | 138 ++++++++++++++++++++++++++++++++++----
 3 files changed, 157 insertions(+), 12 deletions(-)

diff --git a/arch/arm64/include/asm/kvm_host.h b/arch/arm64/include/asm/kvm_host.h
index 77b6f3e..d233855 100644
--- a/arch/arm64/include/asm/kvm_host.h
+++ b/arch/arm64/include/asm/kvm_host.h
@@ -310,6 +310,20 @@ struct kvm_vcpu_arch {
 #define vcpu_sve_pffr(vcpu) ((void *)((char *)((vcpu)->arch.sve_state) + \
 				      sve_ffr_offset((vcpu)->arch.sve_max_vl)))
 
+#define vcpu_sve_state_size(vcpu) ({					\
+	size_t __size_ret;						\
+	unsigned int __vcpu_vq;						\
+									\
+	if (WARN_ON(!sve_vl_valid((vcpu)->arch.sve_max_vl))) {		\
+		__size_ret = 0;						\
+	} else {							\
+		__vcpu_vq = sve_vq_from_vl((vcpu)->arch.sve_max_vl);	\
+		__size_ret = SVE_SIG_REGS_SIZE(__vcpu_vq);		\
+	}								\
+									\
+	__size_ret;							\
+})
+
 /* vcpu_arch flags field values: */
 #define KVM_ARM64_DEBUG_DIRTY		(1 << 0)
 #define KVM_ARM64_FP_ENABLED		(1 << 1) /* guest FP regs loaded */
diff --git a/arch/arm64/include/uapi/asm/kvm.h b/arch/arm64/include/uapi/asm/kvm.h
index 97c3478..ced760c 100644
--- a/arch/arm64/include/uapi/asm/kvm.h
+++ b/arch/arm64/include/uapi/asm/kvm.h
@@ -226,6 +226,23 @@ struct kvm_vcpu_events {
 					 KVM_REG_ARM_FW | ((r) & 0xffff))
 #define KVM_REG_ARM_PSCI_VERSION	KVM_REG_ARM_FW_REG(0)
 
+/* SVE registers */
+#define KVM_REG_ARM64_SVE		(0x15 << KVM_REG_ARM_COPROC_SHIFT)
+
+/* Z- and P-regs occupy blocks at the following offsets within this range: */
+#define KVM_REG_ARM64_SVE_ZREG_BASE	0
+#define KVM_REG_ARM64_SVE_PREG_BASE	0x400
+
+#define KVM_REG_ARM64_SVE_ZREG(n, i)	(KVM_REG_ARM64 | KVM_REG_ARM64_SVE | \
+					 KVM_REG_ARM64_SVE_ZREG_BASE |	\
+					 KVM_REG_SIZE_U2048 |		\
+					 ((n) << 5) | (i))
+#define KVM_REG_ARM64_SVE_PREG(n, i)	(KVM_REG_ARM64 | KVM_REG_ARM64_SVE | \
+					 KVM_REG_ARM64_SVE_PREG_BASE |	\
+					 KVM_REG_SIZE_U256 |		\
+					 ((n) << 5) | (i))
+#define KVM_REG_ARM64_SVE_FFR(i)	KVM_REG_ARM64_SVE_PREG(16, i)
+
 /* Device Control API: ARM VGIC */
 #define KVM_DEV_ARM_VGIC_GRP_ADDR	0
 #define KVM_DEV_ARM_VGIC_GRP_DIST_REGS	1
diff --git a/arch/arm64/kvm/guest.c b/arch/arm64/kvm/guest.c
index f491456..8cfa889 100644
--- a/arch/arm64/kvm/guest.c
+++ b/arch/arm64/kvm/guest.c
@@ -19,8 +19,11 @@
  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
  */
 
+#include <linux/bits.h>
 #include <linux/errno.h>
 #include <linux/err.h>
+#include <linux/nospec.h>
+#include <linux/kernel.h>
 #include <linux/kvm_host.h>
 #include <linux/module.h>
 #include <linux/string.h>
@@ -29,9 +32,12 @@
 #include <kvm/arm_psci.h>
 #include <asm/cputype.h>
 #include <linux/uaccess.h>
+#include <asm/fpsimd.h>
 #include <asm/kvm.h>
 #include <asm/kvm_emulate.h>
 #include <asm/kvm_coproc.h>
+#include <asm/kvm_host.h>
+#include <asm/sigcontext.h>
 
 #include "trace.h"
 
@@ -211,6 +217,114 @@ static int set_core_reg(struct kvm_vcpu *vcpu, const struct kvm_one_reg *reg)
 	return err;
 }
 
+#define SVE_REG_SLICE_SHIFT	0
+#define SVE_REG_SLICE_BITS	5
+#define SVE_REG_ID_SHIFT	(SVE_REG_SLICE_SHIFT + SVE_REG_SLICE_BITS)
+#define SVE_REG_ID_BITS		5
+
+#define SVE_REG_SLICE_MASK					\
+	GENMASK(SVE_REG_SLICE_SHIFT + SVE_REG_SLICE_BITS - 1,	\
+		SVE_REG_SLICE_SHIFT)
+#define SVE_REG_ID_MASK							\
+	GENMASK(SVE_REG_ID_SHIFT + SVE_REG_ID_BITS - 1, SVE_REG_ID_SHIFT)
+
+#define SVE_NUM_SLICES (1 << SVE_REG_SLICE_BITS)
+
+#define KVM_SVE_ZREG_SIZE KVM_REG_SIZE(KVM_REG_ARM64_SVE_ZREG(0, 0))
+#define KVM_SVE_PREG_SIZE KVM_REG_SIZE(KVM_REG_ARM64_SVE_PREG(0, 0))
+
+struct sve_state_region {
+	unsigned int koffset;	/* offset into sve_state in kernel memory */
+	unsigned int klen;	/* length in kernel memory */
+	unsigned int upad;	/* extra trailing padding in user memory */
+};
+
+/* Get sanitised bounds for user/kernel SVE register copy */
+static int sve_reg_region(struct sve_state_region *region,
+			  struct kvm_vcpu *vcpu,
+			  const struct kvm_one_reg *reg)
+{
+	/* reg ID ranges for Z- registers */
+	const u64 zreg_id_min = KVM_REG_ARM64_SVE_ZREG(0, 0);
+	const u64 zreg_id_max = KVM_REG_ARM64_SVE_ZREG(SVE_NUM_ZREGS - 1,
+						       SVE_NUM_SLICES - 1);
+
+	/* reg ID ranges for P- registers and FFR (which are contiguous) */
+	const u64 preg_id_min = KVM_REG_ARM64_SVE_PREG(0, 0);
+	const u64 preg_id_max = KVM_REG_ARM64_SVE_FFR(SVE_NUM_SLICES - 1);
+
+	unsigned int vq;
+	unsigned int reg_num;
+
+	unsigned int reqoffset, reqlen; /* User-requested offset and length */
+	unsigned int maxlen; /* Maxmimum permitted length */
+
+	size_t sve_state_size;
+
+	/* Only the first slice ever exists, for now: */
+	if ((reg->id & SVE_REG_SLICE_MASK) != 0)
+		return -ENOENT;
+
+	vq = sve_vq_from_vl(vcpu->arch.sve_max_vl);
+
+	reg_num = (reg->id & SVE_REG_ID_MASK) >> SVE_REG_ID_SHIFT;
+
+	if (reg->id >= zreg_id_min && reg->id <= zreg_id_max) {
+		reqoffset = SVE_SIG_ZREG_OFFSET(vq, reg_num) -
+				SVE_SIG_REGS_OFFSET;
+		reqlen = KVM_SVE_ZREG_SIZE;
+		maxlen = SVE_SIG_ZREG_SIZE(vq);
+	} else if (reg->id >= preg_id_min && reg->id <= preg_id_max) {
+		reqoffset = SVE_SIG_PREG_OFFSET(vq, reg_num) -
+				SVE_SIG_REGS_OFFSET;
+		reqlen = KVM_SVE_PREG_SIZE;
+		maxlen = SVE_SIG_PREG_SIZE(vq);
+	} else {
+		return -ENOENT;
+	}
+
+	sve_state_size = vcpu_sve_state_size(vcpu);
+	if (!sve_state_size)
+		return -EINVAL;
+
+	region->koffset = array_index_nospec(reqoffset, sve_state_size);
+	region->klen = min(maxlen, reqlen);
+	region->upad = reqlen - region->klen;
+
+	return 0;
+}
+
+static int get_sve_reg(struct kvm_vcpu *vcpu, const struct kvm_one_reg *reg)
+{
+	struct sve_state_region region;
+	char __user *uptr = (char __user *)reg->addr;
+
+	if (!vcpu_has_sve(vcpu) || sve_reg_region(&region, vcpu, reg))
+		return -ENOENT;
+
+	if (copy_to_user(uptr, vcpu->arch.sve_state + region.koffset,
+			 region.klen) ||
+	    clear_user(uptr + region.klen, region.upad))
+		return -EFAULT;
+
+	return 0;
+}
+
+static int set_sve_reg(struct kvm_vcpu *vcpu, const struct kvm_one_reg *reg)
+{
+	struct sve_state_region region;
+	const char __user *uptr = (const char __user *)reg->addr;
+
+	if (!vcpu_has_sve(vcpu) || sve_reg_region(&region, vcpu, reg))
+		return -ENOENT;
+
+	if (copy_from_user(vcpu->arch.sve_state + region.koffset, uptr,
+			   region.klen))
+		return -EFAULT;
+
+	return 0;
+}
+
 int kvm_arch_vcpu_ioctl_get_regs(struct kvm_vcpu *vcpu, struct kvm_regs *regs)
 {
 	return -EINVAL;
@@ -371,12 +485,12 @@ int kvm_arm_get_reg(struct kvm_vcpu *vcpu, const struct kvm_one_reg *reg)
 	if ((reg->id & ~KVM_REG_SIZE_MASK) >> 32 != KVM_REG_ARM64 >> 32)
 		return -EINVAL;
 
-	/* Register group 16 means we want a core register. */
-	if ((reg->id & KVM_REG_ARM_COPROC_MASK) == KVM_REG_ARM_CORE)
-		return get_core_reg(vcpu, reg);
-
-	if ((reg->id & KVM_REG_ARM_COPROC_MASK) == KVM_REG_ARM_FW)
-		return kvm_arm_get_fw_reg(vcpu, reg);
+	switch (reg->id & KVM_REG_ARM_COPROC_MASK) {
+	case KVM_REG_ARM_CORE:	return get_core_reg(vcpu, reg);
+	case KVM_REG_ARM_FW:	return kvm_arm_get_fw_reg(vcpu, reg);
+	case KVM_REG_ARM64_SVE:	return get_sve_reg(vcpu, reg);
+	default: break; /* fall through */
+	}
 
 	if (is_timer_reg(reg->id))
 		return get_timer_reg(vcpu, reg);
@@ -390,12 +504,12 @@ int kvm_arm_set_reg(struct kvm_vcpu *vcpu, const struct kvm_one_reg *reg)
 	if ((reg->id & ~KVM_REG_SIZE_MASK) >> 32 != KVM_REG_ARM64 >> 32)
 		return -EINVAL;
 
-	/* Register group 16 means we set a core register. */
-	if ((reg->id & KVM_REG_ARM_COPROC_MASK) == KVM_REG_ARM_CORE)
-		return set_core_reg(vcpu, reg);
-
-	if ((reg->id & KVM_REG_ARM_COPROC_MASK) == KVM_REG_ARM_FW)
-		return kvm_arm_set_fw_reg(vcpu, reg);
+	switch (reg->id & KVM_REG_ARM_COPROC_MASK) {
+	case KVM_REG_ARM_CORE:	return set_core_reg(vcpu, reg);
+	case KVM_REG_ARM_FW:	return kvm_arm_set_fw_reg(vcpu, reg);
+	case KVM_REG_ARM64_SVE:	return set_sve_reg(vcpu, reg);
+	default: break; /* fall through */
+	}
 
 	if (is_timer_reg(reg->id))
 		return set_timer_reg(vcpu, reg);
-- 
2.1.4

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

* [PATCH v5 18/26] KVM: arm64/sve: Add SVE support to register access ioctl interface
@ 2019-02-18 19:52   ` Dave Martin
  0 siblings, 0 replies; 205+ messages in thread
From: Dave Martin @ 2019-02-18 19:52 UTC (permalink / raw)
  To: kvmarm
  Cc: Peter Maydell, Okamoto Takayuki, Christoffer Dall,
	Ard Biesheuvel, Marc Zyngier, Catalin Marinas, Will Deacon,
	Zhang Lei, Julien Grall, Alex Bennée, linux-arm-kernel

This patch adds the following registers for access via the
KVM_{GET,SET}_ONE_REG interface:

 * KVM_REG_ARM64_SVE_ZREG(n, i) (n = 0..31) (in 2048-bit slices)
 * KVM_REG_ARM64_SVE_PREG(n, i) (n = 0..15) (in 256-bit slices)
 * KVM_REG_ARM64_SVE_FFR(i) (in 256-bit slices)

In order to adapt gracefully to future architectural extensions,
the registers are logically divided up into slices as noted above:
the i parameter denotes the slice index.

This allows us to reserve space in the ABI for future expansion of
these registers.  However, as of today the architecture does not
permit registers to be larger than a single slice, so no code is
needed in the kernel to expose additional slices, for now.  The
code can be extended later as needed to expose them up to a maximum
of 32 slices (as carved out in the architecture itself) if they
really exist someday.

The registers are only visible for vcpus that have SVE enabled.
They are not enumerated by KVM_GET_REG_LIST on vcpus that do not
have SVE.

Accesses to the FPSIMD registers via KVM_REG_ARM_CORE is not
allowed for SVE-enabled vcpus: SVE-aware userspace can use the
KVM_REG_ARM64_SVE_ZREG() interface instead to access the same
register state.  This avoids some complex and pointless emulation
in the kernel to convert between the two views of these aliased
registers.

Signed-off-by: Dave Martin <Dave.Martin@arm.com>

---

Changes since v4:

 * Add "BASE" #defines for the Z-reg and P-reg ranges in the KVM
   register ID space, to make the 0x400 magic number a little less
   cryptic.

 * Pull KVM_SVE_{Z,P}REG_SIZE defines from "KVM: arm64: Enumerate SVE
   register indices for KVM_GET_REG_LIST", since we now use them here.

 * Simplify sve_reg_region(), and give up on the attempt to make
   kreg_region a general thing: nothing else will use it for now,
   anyway, so let's keep it as simple as possible.

 * Drop support for multiple slices per register.  This functionality
   can be added back in later if needed, without ABI breaks.

 * Pull vcpu_sve_state_size() into kvm_host.h, from "KVM: arm64/sve:
   Allow userspace to enable SVE for vcpus".  This is needed for use
   with array_index_nospec() to determine the applicable buffer bounds.
   To avoid circular header deependency issues, the function is also
   converted into a macro, but is otherwise equivalent to the original
   version.

 * Guard sve_state base offset in kernel memory with
   array_index_nospec(), since it is generated from user data that can
   put it out of range.

   (sve_state will get allocated with the corresponding size later in
   the series.  For now, this code is dormant since no means is
   provided for userspace to create SVE-enabled vcpus yet.)
---
 arch/arm64/include/asm/kvm_host.h |  14 ++++
 arch/arm64/include/uapi/asm/kvm.h |  17 +++++
 arch/arm64/kvm/guest.c            | 138 ++++++++++++++++++++++++++++++++++----
 3 files changed, 157 insertions(+), 12 deletions(-)

diff --git a/arch/arm64/include/asm/kvm_host.h b/arch/arm64/include/asm/kvm_host.h
index 77b6f3e..d233855 100644
--- a/arch/arm64/include/asm/kvm_host.h
+++ b/arch/arm64/include/asm/kvm_host.h
@@ -310,6 +310,20 @@ struct kvm_vcpu_arch {
 #define vcpu_sve_pffr(vcpu) ((void *)((char *)((vcpu)->arch.sve_state) + \
 				      sve_ffr_offset((vcpu)->arch.sve_max_vl)))
 
+#define vcpu_sve_state_size(vcpu) ({					\
+	size_t __size_ret;						\
+	unsigned int __vcpu_vq;						\
+									\
+	if (WARN_ON(!sve_vl_valid((vcpu)->arch.sve_max_vl))) {		\
+		__size_ret = 0;						\
+	} else {							\
+		__vcpu_vq = sve_vq_from_vl((vcpu)->arch.sve_max_vl);	\
+		__size_ret = SVE_SIG_REGS_SIZE(__vcpu_vq);		\
+	}								\
+									\
+	__size_ret;							\
+})
+
 /* vcpu_arch flags field values: */
 #define KVM_ARM64_DEBUG_DIRTY		(1 << 0)
 #define KVM_ARM64_FP_ENABLED		(1 << 1) /* guest FP regs loaded */
diff --git a/arch/arm64/include/uapi/asm/kvm.h b/arch/arm64/include/uapi/asm/kvm.h
index 97c3478..ced760c 100644
--- a/arch/arm64/include/uapi/asm/kvm.h
+++ b/arch/arm64/include/uapi/asm/kvm.h
@@ -226,6 +226,23 @@ struct kvm_vcpu_events {
 					 KVM_REG_ARM_FW | ((r) & 0xffff))
 #define KVM_REG_ARM_PSCI_VERSION	KVM_REG_ARM_FW_REG(0)
 
+/* SVE registers */
+#define KVM_REG_ARM64_SVE		(0x15 << KVM_REG_ARM_COPROC_SHIFT)
+
+/* Z- and P-regs occupy blocks at the following offsets within this range: */
+#define KVM_REG_ARM64_SVE_ZREG_BASE	0
+#define KVM_REG_ARM64_SVE_PREG_BASE	0x400
+
+#define KVM_REG_ARM64_SVE_ZREG(n, i)	(KVM_REG_ARM64 | KVM_REG_ARM64_SVE | \
+					 KVM_REG_ARM64_SVE_ZREG_BASE |	\
+					 KVM_REG_SIZE_U2048 |		\
+					 ((n) << 5) | (i))
+#define KVM_REG_ARM64_SVE_PREG(n, i)	(KVM_REG_ARM64 | KVM_REG_ARM64_SVE | \
+					 KVM_REG_ARM64_SVE_PREG_BASE |	\
+					 KVM_REG_SIZE_U256 |		\
+					 ((n) << 5) | (i))
+#define KVM_REG_ARM64_SVE_FFR(i)	KVM_REG_ARM64_SVE_PREG(16, i)
+
 /* Device Control API: ARM VGIC */
 #define KVM_DEV_ARM_VGIC_GRP_ADDR	0
 #define KVM_DEV_ARM_VGIC_GRP_DIST_REGS	1
diff --git a/arch/arm64/kvm/guest.c b/arch/arm64/kvm/guest.c
index f491456..8cfa889 100644
--- a/arch/arm64/kvm/guest.c
+++ b/arch/arm64/kvm/guest.c
@@ -19,8 +19,11 @@
  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
  */
 
+#include <linux/bits.h>
 #include <linux/errno.h>
 #include <linux/err.h>
+#include <linux/nospec.h>
+#include <linux/kernel.h>
 #include <linux/kvm_host.h>
 #include <linux/module.h>
 #include <linux/string.h>
@@ -29,9 +32,12 @@
 #include <kvm/arm_psci.h>
 #include <asm/cputype.h>
 #include <linux/uaccess.h>
+#include <asm/fpsimd.h>
 #include <asm/kvm.h>
 #include <asm/kvm_emulate.h>
 #include <asm/kvm_coproc.h>
+#include <asm/kvm_host.h>
+#include <asm/sigcontext.h>
 
 #include "trace.h"
 
@@ -211,6 +217,114 @@ static int set_core_reg(struct kvm_vcpu *vcpu, const struct kvm_one_reg *reg)
 	return err;
 }
 
+#define SVE_REG_SLICE_SHIFT	0
+#define SVE_REG_SLICE_BITS	5
+#define SVE_REG_ID_SHIFT	(SVE_REG_SLICE_SHIFT + SVE_REG_SLICE_BITS)
+#define SVE_REG_ID_BITS		5
+
+#define SVE_REG_SLICE_MASK					\
+	GENMASK(SVE_REG_SLICE_SHIFT + SVE_REG_SLICE_BITS - 1,	\
+		SVE_REG_SLICE_SHIFT)
+#define SVE_REG_ID_MASK							\
+	GENMASK(SVE_REG_ID_SHIFT + SVE_REG_ID_BITS - 1, SVE_REG_ID_SHIFT)
+
+#define SVE_NUM_SLICES (1 << SVE_REG_SLICE_BITS)
+
+#define KVM_SVE_ZREG_SIZE KVM_REG_SIZE(KVM_REG_ARM64_SVE_ZREG(0, 0))
+#define KVM_SVE_PREG_SIZE KVM_REG_SIZE(KVM_REG_ARM64_SVE_PREG(0, 0))
+
+struct sve_state_region {
+	unsigned int koffset;	/* offset into sve_state in kernel memory */
+	unsigned int klen;	/* length in kernel memory */
+	unsigned int upad;	/* extra trailing padding in user memory */
+};
+
+/* Get sanitised bounds for user/kernel SVE register copy */
+static int sve_reg_region(struct sve_state_region *region,
+			  struct kvm_vcpu *vcpu,
+			  const struct kvm_one_reg *reg)
+{
+	/* reg ID ranges for Z- registers */
+	const u64 zreg_id_min = KVM_REG_ARM64_SVE_ZREG(0, 0);
+	const u64 zreg_id_max = KVM_REG_ARM64_SVE_ZREG(SVE_NUM_ZREGS - 1,
+						       SVE_NUM_SLICES - 1);
+
+	/* reg ID ranges for P- registers and FFR (which are contiguous) */
+	const u64 preg_id_min = KVM_REG_ARM64_SVE_PREG(0, 0);
+	const u64 preg_id_max = KVM_REG_ARM64_SVE_FFR(SVE_NUM_SLICES - 1);
+
+	unsigned int vq;
+	unsigned int reg_num;
+
+	unsigned int reqoffset, reqlen; /* User-requested offset and length */
+	unsigned int maxlen; /* Maxmimum permitted length */
+
+	size_t sve_state_size;
+
+	/* Only the first slice ever exists, for now: */
+	if ((reg->id & SVE_REG_SLICE_MASK) != 0)
+		return -ENOENT;
+
+	vq = sve_vq_from_vl(vcpu->arch.sve_max_vl);
+
+	reg_num = (reg->id & SVE_REG_ID_MASK) >> SVE_REG_ID_SHIFT;
+
+	if (reg->id >= zreg_id_min && reg->id <= zreg_id_max) {
+		reqoffset = SVE_SIG_ZREG_OFFSET(vq, reg_num) -
+				SVE_SIG_REGS_OFFSET;
+		reqlen = KVM_SVE_ZREG_SIZE;
+		maxlen = SVE_SIG_ZREG_SIZE(vq);
+	} else if (reg->id >= preg_id_min && reg->id <= preg_id_max) {
+		reqoffset = SVE_SIG_PREG_OFFSET(vq, reg_num) -
+				SVE_SIG_REGS_OFFSET;
+		reqlen = KVM_SVE_PREG_SIZE;
+		maxlen = SVE_SIG_PREG_SIZE(vq);
+	} else {
+		return -ENOENT;
+	}
+
+	sve_state_size = vcpu_sve_state_size(vcpu);
+	if (!sve_state_size)
+		return -EINVAL;
+
+	region->koffset = array_index_nospec(reqoffset, sve_state_size);
+	region->klen = min(maxlen, reqlen);
+	region->upad = reqlen - region->klen;
+
+	return 0;
+}
+
+static int get_sve_reg(struct kvm_vcpu *vcpu, const struct kvm_one_reg *reg)
+{
+	struct sve_state_region region;
+	char __user *uptr = (char __user *)reg->addr;
+
+	if (!vcpu_has_sve(vcpu) || sve_reg_region(&region, vcpu, reg))
+		return -ENOENT;
+
+	if (copy_to_user(uptr, vcpu->arch.sve_state + region.koffset,
+			 region.klen) ||
+	    clear_user(uptr + region.klen, region.upad))
+		return -EFAULT;
+
+	return 0;
+}
+
+static int set_sve_reg(struct kvm_vcpu *vcpu, const struct kvm_one_reg *reg)
+{
+	struct sve_state_region region;
+	const char __user *uptr = (const char __user *)reg->addr;
+
+	if (!vcpu_has_sve(vcpu) || sve_reg_region(&region, vcpu, reg))
+		return -ENOENT;
+
+	if (copy_from_user(vcpu->arch.sve_state + region.koffset, uptr,
+			   region.klen))
+		return -EFAULT;
+
+	return 0;
+}
+
 int kvm_arch_vcpu_ioctl_get_regs(struct kvm_vcpu *vcpu, struct kvm_regs *regs)
 {
 	return -EINVAL;
@@ -371,12 +485,12 @@ int kvm_arm_get_reg(struct kvm_vcpu *vcpu, const struct kvm_one_reg *reg)
 	if ((reg->id & ~KVM_REG_SIZE_MASK) >> 32 != KVM_REG_ARM64 >> 32)
 		return -EINVAL;
 
-	/* Register group 16 means we want a core register. */
-	if ((reg->id & KVM_REG_ARM_COPROC_MASK) == KVM_REG_ARM_CORE)
-		return get_core_reg(vcpu, reg);
-
-	if ((reg->id & KVM_REG_ARM_COPROC_MASK) == KVM_REG_ARM_FW)
-		return kvm_arm_get_fw_reg(vcpu, reg);
+	switch (reg->id & KVM_REG_ARM_COPROC_MASK) {
+	case KVM_REG_ARM_CORE:	return get_core_reg(vcpu, reg);
+	case KVM_REG_ARM_FW:	return kvm_arm_get_fw_reg(vcpu, reg);
+	case KVM_REG_ARM64_SVE:	return get_sve_reg(vcpu, reg);
+	default: break; /* fall through */
+	}
 
 	if (is_timer_reg(reg->id))
 		return get_timer_reg(vcpu, reg);
@@ -390,12 +504,12 @@ int kvm_arm_set_reg(struct kvm_vcpu *vcpu, const struct kvm_one_reg *reg)
 	if ((reg->id & ~KVM_REG_SIZE_MASK) >> 32 != KVM_REG_ARM64 >> 32)
 		return -EINVAL;
 
-	/* Register group 16 means we set a core register. */
-	if ((reg->id & KVM_REG_ARM_COPROC_MASK) == KVM_REG_ARM_CORE)
-		return set_core_reg(vcpu, reg);
-
-	if ((reg->id & KVM_REG_ARM_COPROC_MASK) == KVM_REG_ARM_FW)
-		return kvm_arm_set_fw_reg(vcpu, reg);
+	switch (reg->id & KVM_REG_ARM_COPROC_MASK) {
+	case KVM_REG_ARM_CORE:	return set_core_reg(vcpu, reg);
+	case KVM_REG_ARM_FW:	return kvm_arm_set_fw_reg(vcpu, reg);
+	case KVM_REG_ARM64_SVE:	return set_sve_reg(vcpu, reg);
+	default: break; /* fall through */
+	}
 
 	if (is_timer_reg(reg->id))
 		return set_timer_reg(vcpu, reg);
-- 
2.1.4


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* [PATCH v5 19/26] KVM: arm64: Enumerate SVE register indices for KVM_GET_REG_LIST
  2019-02-18 19:52 ` Dave Martin
@ 2019-02-18 19:52   ` Dave Martin
  -1 siblings, 0 replies; 205+ messages in thread
From: Dave Martin @ 2019-02-18 19:52 UTC (permalink / raw)
  To: kvmarm
  Cc: Okamoto Takayuki, Christoffer Dall, Ard Biesheuvel, Marc Zyngier,
	Catalin Marinas, Will Deacon, Zhang Lei, linux-arm-kernel

This patch includes the SVE register IDs in the list returned by
KVM_GET_REG_LIST, as appropriate.

On a non-SVE-enabled vcpu, no new IDs are added.

On an SVE-enabled vcpu, IDs for the FPSIMD V-registers are removed
from the list, since userspace is required to access the Z-
registers instead to access their context.  For the variably-sized
SVE registers, the appropriate set of slice IDs are enumerated,
depending on the maximum vector length for the vcpu.

Signed-off-by: Dave Martin <Dave.Martin@arm.com>

---

Changes since v4:

 * Drop KVM_SVE_SLICES(), which is no longer used due to the dropping of
   register multi-slice support from the series.

 * Drop register multi-slice support.
---
 arch/arm64/kvm/guest.c | 51 ++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 51 insertions(+)

diff --git a/arch/arm64/kvm/guest.c b/arch/arm64/kvm/guest.c
index 8cfa889..4a2ad60 100644
--- a/arch/arm64/kvm/guest.c
+++ b/arch/arm64/kvm/guest.c
@@ -366,6 +366,14 @@ static int copy_core_reg_indices(const struct kvm_vcpu *vcpu,
 			continue;
 		}
 
+		/*
+		 * The KVM_REG_ARM64_SVE regs must be used instead of
+		 * KVM_REG_ARM_CORE for accessing the FPSIMD V-registers on
+		 * SVE-enabled vcpus:
+		 */
+		if (vcpu_has_sve(vcpu) && core_reg_offset_is_vreg(i))
+			continue;
+
 		if (uind) {
 			if (put_user(reg, *uind))
 				return -EFAULT;
@@ -436,6 +444,44 @@ static int get_timer_reg(struct kvm_vcpu *vcpu, const struct kvm_one_reg *reg)
 	return copy_to_user(uaddr, &val, KVM_REG_SIZE(reg->id)) ? -EFAULT : 0;
 }
 
+static unsigned long num_sve_regs(const struct kvm_vcpu *vcpu)
+{
+	/* Only the first slice ever exists, for now */
+	const unsigned int slices = 1;
+
+	if (!vcpu_has_sve(vcpu))
+		return 0;
+
+	return slices * (SVE_NUM_PREGS + SVE_NUM_ZREGS + 1 /* FFR */);
+}
+
+static int copy_sve_reg_indices(const struct kvm_vcpu *vcpu, u64 __user **uind)
+{
+	/* Only the first slice ever exists, for now */
+	const unsigned int slices = 1;
+	unsigned int i, n;
+
+	if (!vcpu_has_sve(vcpu))
+		return 0;
+
+	for (i = 0; i < slices; i++) {
+		for (n = 0; n < SVE_NUM_ZREGS; n++) {
+			if (put_user(KVM_REG_ARM64_SVE_ZREG(n, i), (*uind)++))
+				return -EFAULT;
+		}
+
+		for (n = 0; n < SVE_NUM_PREGS; n++) {
+			if (put_user(KVM_REG_ARM64_SVE_PREG(n, i), (*uind)++))
+				return -EFAULT;
+		}
+
+		if (put_user(KVM_REG_ARM64_SVE_FFR(i), (*uind)++))
+			return -EFAULT;
+	}
+
+	return 0;
+}
+
 /**
  * kvm_arm_num_regs - how many registers do we present via KVM_GET_ONE_REG
  *
@@ -446,6 +492,7 @@ unsigned long kvm_arm_num_regs(struct kvm_vcpu *vcpu)
 	unsigned long res = 0;
 
 	res += num_core_regs(vcpu);
+	res += num_sve_regs(vcpu);
 	res += kvm_arm_num_sys_reg_descs(vcpu);
 	res += kvm_arm_get_fw_num_regs(vcpu);
 	res += NUM_TIMER_REGS;
@@ -466,6 +513,10 @@ int kvm_arm_copy_reg_indices(struct kvm_vcpu *vcpu, u64 __user *uindices)
 	if (ret < 0)
 		return ret;
 
+	ret = copy_sve_reg_indices(vcpu, &uindices);
+	if (ret)
+		return ret;
+
 	ret = kvm_arm_copy_fw_reg_indices(vcpu, uindices);
 	if (ret)
 		return ret;
-- 
2.1.4

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

* [PATCH v5 19/26] KVM: arm64: Enumerate SVE register indices for KVM_GET_REG_LIST
@ 2019-02-18 19:52   ` Dave Martin
  0 siblings, 0 replies; 205+ messages in thread
From: Dave Martin @ 2019-02-18 19:52 UTC (permalink / raw)
  To: kvmarm
  Cc: Peter Maydell, Okamoto Takayuki, Christoffer Dall,
	Ard Biesheuvel, Marc Zyngier, Catalin Marinas, Will Deacon,
	Zhang Lei, Julien Grall, Alex Bennée, linux-arm-kernel

This patch includes the SVE register IDs in the list returned by
KVM_GET_REG_LIST, as appropriate.

On a non-SVE-enabled vcpu, no new IDs are added.

On an SVE-enabled vcpu, IDs for the FPSIMD V-registers are removed
from the list, since userspace is required to access the Z-
registers instead to access their context.  For the variably-sized
SVE registers, the appropriate set of slice IDs are enumerated,
depending on the maximum vector length for the vcpu.

Signed-off-by: Dave Martin <Dave.Martin@arm.com>

---

Changes since v4:

 * Drop KVM_SVE_SLICES(), which is no longer used due to the dropping of
   register multi-slice support from the series.

 * Drop register multi-slice support.
---
 arch/arm64/kvm/guest.c | 51 ++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 51 insertions(+)

diff --git a/arch/arm64/kvm/guest.c b/arch/arm64/kvm/guest.c
index 8cfa889..4a2ad60 100644
--- a/arch/arm64/kvm/guest.c
+++ b/arch/arm64/kvm/guest.c
@@ -366,6 +366,14 @@ static int copy_core_reg_indices(const struct kvm_vcpu *vcpu,
 			continue;
 		}
 
+		/*
+		 * The KVM_REG_ARM64_SVE regs must be used instead of
+		 * KVM_REG_ARM_CORE for accessing the FPSIMD V-registers on
+		 * SVE-enabled vcpus:
+		 */
+		if (vcpu_has_sve(vcpu) && core_reg_offset_is_vreg(i))
+			continue;
+
 		if (uind) {
 			if (put_user(reg, *uind))
 				return -EFAULT;
@@ -436,6 +444,44 @@ static int get_timer_reg(struct kvm_vcpu *vcpu, const struct kvm_one_reg *reg)
 	return copy_to_user(uaddr, &val, KVM_REG_SIZE(reg->id)) ? -EFAULT : 0;
 }
 
+static unsigned long num_sve_regs(const struct kvm_vcpu *vcpu)
+{
+	/* Only the first slice ever exists, for now */
+	const unsigned int slices = 1;
+
+	if (!vcpu_has_sve(vcpu))
+		return 0;
+
+	return slices * (SVE_NUM_PREGS + SVE_NUM_ZREGS + 1 /* FFR */);
+}
+
+static int copy_sve_reg_indices(const struct kvm_vcpu *vcpu, u64 __user **uind)
+{
+	/* Only the first slice ever exists, for now */
+	const unsigned int slices = 1;
+	unsigned int i, n;
+
+	if (!vcpu_has_sve(vcpu))
+		return 0;
+
+	for (i = 0; i < slices; i++) {
+		for (n = 0; n < SVE_NUM_ZREGS; n++) {
+			if (put_user(KVM_REG_ARM64_SVE_ZREG(n, i), (*uind)++))
+				return -EFAULT;
+		}
+
+		for (n = 0; n < SVE_NUM_PREGS; n++) {
+			if (put_user(KVM_REG_ARM64_SVE_PREG(n, i), (*uind)++))
+				return -EFAULT;
+		}
+
+		if (put_user(KVM_REG_ARM64_SVE_FFR(i), (*uind)++))
+			return -EFAULT;
+	}
+
+	return 0;
+}
+
 /**
  * kvm_arm_num_regs - how many registers do we present via KVM_GET_ONE_REG
  *
@@ -446,6 +492,7 @@ unsigned long kvm_arm_num_regs(struct kvm_vcpu *vcpu)
 	unsigned long res = 0;
 
 	res += num_core_regs(vcpu);
+	res += num_sve_regs(vcpu);
 	res += kvm_arm_num_sys_reg_descs(vcpu);
 	res += kvm_arm_get_fw_num_regs(vcpu);
 	res += NUM_TIMER_REGS;
@@ -466,6 +513,10 @@ int kvm_arm_copy_reg_indices(struct kvm_vcpu *vcpu, u64 __user *uindices)
 	if (ret < 0)
 		return ret;
 
+	ret = copy_sve_reg_indices(vcpu, &uindices);
+	if (ret)
+		return ret;
+
 	ret = kvm_arm_copy_fw_reg_indices(vcpu, uindices);
 	if (ret)
 		return ret;
-- 
2.1.4


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* [PATCH v5 20/26] arm64/sve: In-kernel vector length availability query interface
  2019-02-18 19:52 ` Dave Martin
@ 2019-02-18 19:52   ` Dave Martin
  -1 siblings, 0 replies; 205+ messages in thread
From: Dave Martin @ 2019-02-18 19:52 UTC (permalink / raw)
  To: kvmarm
  Cc: Okamoto Takayuki, Christoffer Dall, Ard Biesheuvel, Marc Zyngier,
	Catalin Marinas, Will Deacon, Zhang Lei, linux-arm-kernel

KVM will need to interrogate the set of SVE vector lengths
available on the system.

This patch exposes the relevant bits to the kernel, along with a
sve_vq_available() helper to check whether a particular vector
length is supported.

vq_to_bit() and bit_to_vq() are not intended for use outside these
functions.

Signed-off-by: Dave Martin <Dave.Martin@arm.com>
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
---
 arch/arm64/include/asm/fpsimd.h | 29 +++++++++++++++++++++++++++++
 arch/arm64/kernel/fpsimd.c      | 35 ++++++++---------------------------
 2 files changed, 37 insertions(+), 27 deletions(-)

diff --git a/arch/arm64/include/asm/fpsimd.h b/arch/arm64/include/asm/fpsimd.h
index df7a143..ad6d2e4 100644
--- a/arch/arm64/include/asm/fpsimd.h
+++ b/arch/arm64/include/asm/fpsimd.h
@@ -24,10 +24,13 @@
 
 #ifndef __ASSEMBLY__
 
+#include <linux/bitmap.h>
 #include <linux/build_bug.h>
+#include <linux/bug.h>
 #include <linux/cache.h>
 #include <linux/init.h>
 #include <linux/stddef.h>
+#include <linux/types.h>
 
 #if defined(__KERNEL__) && defined(CONFIG_COMPAT)
 /* Masks for extracting the FPSR and FPCR from the FPSCR */
@@ -89,6 +92,32 @@ extern u64 read_zcr_features(void);
 
 extern int __ro_after_init sve_max_vl;
 extern int __ro_after_init sve_max_virtualisable_vl;
+/* Set of available vector lengths, as vq_to_bit(vq): */
+extern __ro_after_init DECLARE_BITMAP(sve_vq_map, SVE_VQ_MAX);
+
+/*
+ * Helpers to translate bit indices in sve_vq_map to VQ values (and
+ * vice versa).  This allows find_next_bit() to be used to find the
+ * _maximum_ VQ not exceeding a certain value.
+ */
+static inline unsigned int __vq_to_bit(unsigned int vq)
+{
+	return SVE_VQ_MAX - vq;
+}
+
+static inline unsigned int __bit_to_vq(unsigned int bit)
+{
+	if (WARN_ON(bit >= SVE_VQ_MAX))
+		bit = SVE_VQ_MAX - 1;
+
+	return SVE_VQ_MAX - bit;
+}
+
+/* Ensure vq >= SVE_VQ_MIN && vq <= SVE_VQ_MAX before calling this function */
+static inline bool sve_vq_available(unsigned int vq)
+{
+	return test_bit(__vq_to_bit(vq), sve_vq_map);
+}
 
 #ifdef CONFIG_ARM64_SVE
 
diff --git a/arch/arm64/kernel/fpsimd.c b/arch/arm64/kernel/fpsimd.c
index 09ee264..ac003cb 100644
--- a/arch/arm64/kernel/fpsimd.c
+++ b/arch/arm64/kernel/fpsimd.c
@@ -136,7 +136,7 @@ static int sve_default_vl = -1;
 int __ro_after_init sve_max_vl = SVE_VL_MIN;
 int __ro_after_init sve_max_virtualisable_vl = SVE_VL_MIN;
 /* Set of available vector lengths, as vq_to_bit(vq): */
-static __ro_after_init DECLARE_BITMAP(sve_vq_map, SVE_VQ_MAX);
+__ro_after_init DECLARE_BITMAP(sve_vq_map, SVE_VQ_MAX);
 /* Set of vector lengths present on at least one cpu: */
 static __ro_after_init DECLARE_BITMAP(sve_vq_partial_map, SVE_VQ_MAX);
 static void __percpu *efi_sve_state;
@@ -270,25 +270,6 @@ void fpsimd_save(void)
 }
 
 /*
- * Helpers to translate bit indices in sve_vq_map to VQ values (and
- * vice versa).  This allows find_next_bit() to be used to find the
- * _maximum_ VQ not exceeding a certain value.
- */
-
-static unsigned int vq_to_bit(unsigned int vq)
-{
-	return SVE_VQ_MAX - vq;
-}
-
-static unsigned int bit_to_vq(unsigned int bit)
-{
-	if (WARN_ON(bit >= SVE_VQ_MAX))
-		bit = SVE_VQ_MAX - 1;
-
-	return SVE_VQ_MAX - bit;
-}
-
-/*
  * All vector length selection from userspace comes through here.
  * We're on a slow path, so some sanity-checks are included.
  * If things go wrong there's a bug somewhere, but try to fall back to a
@@ -309,8 +290,8 @@ static unsigned int find_supported_vector_length(unsigned int vl)
 		vl = max_vl;
 
 	bit = find_next_bit(sve_vq_map, SVE_VQ_MAX,
-			    vq_to_bit(sve_vq_from_vl(vl)));
-	return sve_vl_from_vq(bit_to_vq(bit));
+			    __vq_to_bit(sve_vq_from_vl(vl)));
+	return sve_vl_from_vq(__bit_to_vq(bit));
 }
 
 #ifdef CONFIG_SYSCTL
@@ -648,7 +629,7 @@ static void sve_probe_vqs(DECLARE_BITMAP(map, SVE_VQ_MAX))
 		write_sysreg_s(zcr | (vq - 1), SYS_ZCR_EL1); /* self-syncing */
 		vl = sve_get_vl();
 		vq = sve_vq_from_vl(vl); /* skip intervening lengths */
-		set_bit(vq_to_bit(vq), map);
+		set_bit(__vq_to_bit(vq), map);
 	}
 }
 
@@ -717,7 +698,7 @@ int sve_verify_vq_map(void)
 	 * Mismatches above sve_max_virtualisable_vl are fine, since
 	 * no guest is allowed to configure ZCR_EL2.LEN to exceed this:
 	 */
-	if (sve_vl_from_vq(bit_to_vq(b)) <= sve_max_virtualisable_vl) {
+	if (sve_vl_from_vq(__bit_to_vq(b)) <= sve_max_virtualisable_vl) {
 		pr_warn("SVE: cpu%d: Unsupported vector length(s) present\n",
 			smp_processor_id());
 		return -EINVAL;
@@ -801,8 +782,8 @@ void __init sve_setup(void)
 	 * so sve_vq_map must have at least SVE_VQ_MIN set.
 	 * If something went wrong, at least try to patch it up:
 	 */
-	if (WARN_ON(!test_bit(vq_to_bit(SVE_VQ_MIN), sve_vq_map)))
-		set_bit(vq_to_bit(SVE_VQ_MIN), sve_vq_map);
+	if (WARN_ON(!test_bit(__vq_to_bit(SVE_VQ_MIN), sve_vq_map)))
+		set_bit(__vq_to_bit(SVE_VQ_MIN), sve_vq_map);
 
 	zcr = read_sanitised_ftr_reg(SYS_ZCR_EL1);
 	sve_max_vl = sve_vl_from_vq((zcr & ZCR_ELx_LEN_MASK) + 1);
@@ -831,7 +812,7 @@ void __init sve_setup(void)
 		/* No virtualisable VLs?  This is architecturally forbidden. */
 		sve_max_virtualisable_vl = SVE_VQ_MIN;
 	else /* b + 1 < SVE_VQ_MAX */
-		sve_max_virtualisable_vl = sve_vl_from_vq(bit_to_vq(b + 1));
+		sve_max_virtualisable_vl = sve_vl_from_vq(__bit_to_vq(b + 1));
 
 	if (sve_max_virtualisable_vl > sve_max_vl)
 		sve_max_virtualisable_vl = sve_max_vl;
-- 
2.1.4

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

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

* [PATCH v5 20/26] arm64/sve: In-kernel vector length availability query interface
@ 2019-02-18 19:52   ` Dave Martin
  0 siblings, 0 replies; 205+ messages in thread
From: Dave Martin @ 2019-02-18 19:52 UTC (permalink / raw)
  To: kvmarm
  Cc: Peter Maydell, Okamoto Takayuki, Christoffer Dall,
	Ard Biesheuvel, Marc Zyngier, Catalin Marinas, Will Deacon,
	Zhang Lei, Julien Grall, Alex Bennée, linux-arm-kernel

KVM will need to interrogate the set of SVE vector lengths
available on the system.

This patch exposes the relevant bits to the kernel, along with a
sve_vq_available() helper to check whether a particular vector
length is supported.

vq_to_bit() and bit_to_vq() are not intended for use outside these
functions.

Signed-off-by: Dave Martin <Dave.Martin@arm.com>
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
---
 arch/arm64/include/asm/fpsimd.h | 29 +++++++++++++++++++++++++++++
 arch/arm64/kernel/fpsimd.c      | 35 ++++++++---------------------------
 2 files changed, 37 insertions(+), 27 deletions(-)

diff --git a/arch/arm64/include/asm/fpsimd.h b/arch/arm64/include/asm/fpsimd.h
index df7a143..ad6d2e4 100644
--- a/arch/arm64/include/asm/fpsimd.h
+++ b/arch/arm64/include/asm/fpsimd.h
@@ -24,10 +24,13 @@
 
 #ifndef __ASSEMBLY__
 
+#include <linux/bitmap.h>
 #include <linux/build_bug.h>
+#include <linux/bug.h>
 #include <linux/cache.h>
 #include <linux/init.h>
 #include <linux/stddef.h>
+#include <linux/types.h>
 
 #if defined(__KERNEL__) && defined(CONFIG_COMPAT)
 /* Masks for extracting the FPSR and FPCR from the FPSCR */
@@ -89,6 +92,32 @@ extern u64 read_zcr_features(void);
 
 extern int __ro_after_init sve_max_vl;
 extern int __ro_after_init sve_max_virtualisable_vl;
+/* Set of available vector lengths, as vq_to_bit(vq): */
+extern __ro_after_init DECLARE_BITMAP(sve_vq_map, SVE_VQ_MAX);
+
+/*
+ * Helpers to translate bit indices in sve_vq_map to VQ values (and
+ * vice versa).  This allows find_next_bit() to be used to find the
+ * _maximum_ VQ not exceeding a certain value.
+ */
+static inline unsigned int __vq_to_bit(unsigned int vq)
+{
+	return SVE_VQ_MAX - vq;
+}
+
+static inline unsigned int __bit_to_vq(unsigned int bit)
+{
+	if (WARN_ON(bit >= SVE_VQ_MAX))
+		bit = SVE_VQ_MAX - 1;
+
+	return SVE_VQ_MAX - bit;
+}
+
+/* Ensure vq >= SVE_VQ_MIN && vq <= SVE_VQ_MAX before calling this function */
+static inline bool sve_vq_available(unsigned int vq)
+{
+	return test_bit(__vq_to_bit(vq), sve_vq_map);
+}
 
 #ifdef CONFIG_ARM64_SVE
 
diff --git a/arch/arm64/kernel/fpsimd.c b/arch/arm64/kernel/fpsimd.c
index 09ee264..ac003cb 100644
--- a/arch/arm64/kernel/fpsimd.c
+++ b/arch/arm64/kernel/fpsimd.c
@@ -136,7 +136,7 @@ static int sve_default_vl = -1;
 int __ro_after_init sve_max_vl = SVE_VL_MIN;
 int __ro_after_init sve_max_virtualisable_vl = SVE_VL_MIN;
 /* Set of available vector lengths, as vq_to_bit(vq): */
-static __ro_after_init DECLARE_BITMAP(sve_vq_map, SVE_VQ_MAX);
+__ro_after_init DECLARE_BITMAP(sve_vq_map, SVE_VQ_MAX);
 /* Set of vector lengths present on at least one cpu: */
 static __ro_after_init DECLARE_BITMAP(sve_vq_partial_map, SVE_VQ_MAX);
 static void __percpu *efi_sve_state;
@@ -270,25 +270,6 @@ void fpsimd_save(void)
 }
 
 /*
- * Helpers to translate bit indices in sve_vq_map to VQ values (and
- * vice versa).  This allows find_next_bit() to be used to find the
- * _maximum_ VQ not exceeding a certain value.
- */
-
-static unsigned int vq_to_bit(unsigned int vq)
-{
-	return SVE_VQ_MAX - vq;
-}
-
-static unsigned int bit_to_vq(unsigned int bit)
-{
-	if (WARN_ON(bit >= SVE_VQ_MAX))
-		bit = SVE_VQ_MAX - 1;
-
-	return SVE_VQ_MAX - bit;
-}
-
-/*
  * All vector length selection from userspace comes through here.
  * We're on a slow path, so some sanity-checks are included.
  * If things go wrong there's a bug somewhere, but try to fall back to a
@@ -309,8 +290,8 @@ static unsigned int find_supported_vector_length(unsigned int vl)
 		vl = max_vl;
 
 	bit = find_next_bit(sve_vq_map, SVE_VQ_MAX,
-			    vq_to_bit(sve_vq_from_vl(vl)));
-	return sve_vl_from_vq(bit_to_vq(bit));
+			    __vq_to_bit(sve_vq_from_vl(vl)));
+	return sve_vl_from_vq(__bit_to_vq(bit));
 }
 
 #ifdef CONFIG_SYSCTL
@@ -648,7 +629,7 @@ static void sve_probe_vqs(DECLARE_BITMAP(map, SVE_VQ_MAX))
 		write_sysreg_s(zcr | (vq - 1), SYS_ZCR_EL1); /* self-syncing */
 		vl = sve_get_vl();
 		vq = sve_vq_from_vl(vl); /* skip intervening lengths */
-		set_bit(vq_to_bit(vq), map);
+		set_bit(__vq_to_bit(vq), map);
 	}
 }
 
@@ -717,7 +698,7 @@ int sve_verify_vq_map(void)
 	 * Mismatches above sve_max_virtualisable_vl are fine, since
 	 * no guest is allowed to configure ZCR_EL2.LEN to exceed this:
 	 */
-	if (sve_vl_from_vq(bit_to_vq(b)) <= sve_max_virtualisable_vl) {
+	if (sve_vl_from_vq(__bit_to_vq(b)) <= sve_max_virtualisable_vl) {
 		pr_warn("SVE: cpu%d: Unsupported vector length(s) present\n",
 			smp_processor_id());
 		return -EINVAL;
@@ -801,8 +782,8 @@ void __init sve_setup(void)
 	 * so sve_vq_map must have at least SVE_VQ_MIN set.
 	 * If something went wrong, at least try to patch it up:
 	 */
-	if (WARN_ON(!test_bit(vq_to_bit(SVE_VQ_MIN), sve_vq_map)))
-		set_bit(vq_to_bit(SVE_VQ_MIN), sve_vq_map);
+	if (WARN_ON(!test_bit(__vq_to_bit(SVE_VQ_MIN), sve_vq_map)))
+		set_bit(__vq_to_bit(SVE_VQ_MIN), sve_vq_map);
 
 	zcr = read_sanitised_ftr_reg(SYS_ZCR_EL1);
 	sve_max_vl = sve_vl_from_vq((zcr & ZCR_ELx_LEN_MASK) + 1);
@@ -831,7 +812,7 @@ void __init sve_setup(void)
 		/* No virtualisable VLs?  This is architecturally forbidden. */
 		sve_max_virtualisable_vl = SVE_VQ_MIN;
 	else /* b + 1 < SVE_VQ_MAX */
-		sve_max_virtualisable_vl = sve_vl_from_vq(bit_to_vq(b + 1));
+		sve_max_virtualisable_vl = sve_vl_from_vq(__bit_to_vq(b + 1));
 
 	if (sve_max_virtualisable_vl > sve_max_vl)
 		sve_max_virtualisable_vl = sve_max_vl;
-- 
2.1.4


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* [PATCH v5 21/26] KVM: arm/arm64: Add hook to finalize the vcpu configuration
  2019-02-18 19:52 ` Dave Martin
@ 2019-02-18 19:52   ` Dave Martin
  -1 siblings, 0 replies; 205+ messages in thread
From: Dave Martin @ 2019-02-18 19:52 UTC (permalink / raw)
  To: kvmarm
  Cc: Okamoto Takayuki, Christoffer Dall, Ard Biesheuvel, Marc Zyngier,
	Catalin Marinas, Will Deacon, Zhang Lei, linux-arm-kernel

Some aspects of vcpu configuration can't be completed inside
KVM_VCPU_INIT, but still change API behaviour visible to userspace.

Where such configuration choices affect the register list visible
to userspace, we will need to track whether we have made a
commitment to userspace regarding the list of vcpu registers.

This patch adds a new hook kvm_arm_vcpu_finalize() to capture this
commitment, along with a corresponding check
kvm_arm_vcpu_finalized().  We commit to the register list when
userspace reads it via KVM_GET_REG_LIST, or when the vcpu is fired
up via KVM_RUN.

kvm_arm_vcpu_finalize() is currently a no-op, but future patches
will amend this to handle SVE on arm64.

Signed-off-by: Dave Martin <Dave.Martin@arm.com>
---
 arch/arm/include/asm/kvm_host.h   | 4 ++++
 arch/arm64/include/asm/kvm_host.h | 4 ++++
 virt/kvm/arm/arm.c                | 8 ++++++++
 3 files changed, 16 insertions(+)

diff --git a/arch/arm/include/asm/kvm_host.h b/arch/arm/include/asm/kvm_host.h
index ca56537..ab7c76b 100644
--- a/arch/arm/include/asm/kvm_host.h
+++ b/arch/arm/include/asm/kvm_host.h
@@ -360,4 +360,8 @@ static inline int kvm_arm_setup_stage2(struct kvm *kvm, unsigned long type)
 	return 0;
 }
 
+/* Commit to the set of vcpu registers currently configured: */
+static inline int kvm_arm_vcpu_finalize(struct kvm_vcpu *vcpu) { return 0; }
+#define kvm_arm_vcpu_finalized(vcpu) true
+
 #endif /* __ARM_KVM_HOST_H__ */
diff --git a/arch/arm64/include/asm/kvm_host.h b/arch/arm64/include/asm/kvm_host.h
index d233855..015c2578 100644
--- a/arch/arm64/include/asm/kvm_host.h
+++ b/arch/arm64/include/asm/kvm_host.h
@@ -553,4 +553,8 @@ void kvm_arch_free_vm(struct kvm *kvm);
 
 int kvm_arm_setup_stage2(struct kvm *kvm, unsigned long type);
 
+/* Commit to the set of vcpu registers currently configured: */
+static inline int kvm_arm_vcpu_finalize(struct kvm_vcpu *vcpu) { return 0; }
+#define kvm_arm_vcpu_finalized(vcpu) true
+
 #endif /* __ARM64_KVM_HOST_H__ */
diff --git a/virt/kvm/arm/arm.c b/virt/kvm/arm/arm.c
index 9e350fd3..12f9dc2 100644
--- a/virt/kvm/arm/arm.c
+++ b/virt/kvm/arm/arm.c
@@ -560,6 +560,10 @@ static int kvm_vcpu_first_run_init(struct kvm_vcpu *vcpu)
 	if (likely(vcpu->arch.has_run_once))
 		return 0;
 
+	ret = kvm_arm_vcpu_finalize(vcpu);
+	if (ret)
+		return ret;
+
 	vcpu->arch.has_run_once = true;
 
 	if (likely(irqchip_in_kernel(kvm))) {
@@ -1121,6 +1125,10 @@ long kvm_arch_vcpu_ioctl(struct file *filp,
 		if (unlikely(!kvm_vcpu_initialized(vcpu)))
 			break;
 
+		r = kvm_arm_vcpu_finalize(vcpu);
+		if (r)
+			break;
+
 		r = -EFAULT;
 		if (copy_from_user(&reg_list, user_list, sizeof(reg_list)))
 			break;
-- 
2.1.4

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

* [PATCH v5 21/26] KVM: arm/arm64: Add hook to finalize the vcpu configuration
@ 2019-02-18 19:52   ` Dave Martin
  0 siblings, 0 replies; 205+ messages in thread
From: Dave Martin @ 2019-02-18 19:52 UTC (permalink / raw)
  To: kvmarm
  Cc: Peter Maydell, Okamoto Takayuki, Christoffer Dall,
	Ard Biesheuvel, Marc Zyngier, Catalin Marinas, Will Deacon,
	Zhang Lei, Julien Grall, Alex Bennée, linux-arm-kernel

Some aspects of vcpu configuration can't be completed inside
KVM_VCPU_INIT, but still change API behaviour visible to userspace.

Where such configuration choices affect the register list visible
to userspace, we will need to track whether we have made a
commitment to userspace regarding the list of vcpu registers.

This patch adds a new hook kvm_arm_vcpu_finalize() to capture this
commitment, along with a corresponding check
kvm_arm_vcpu_finalized().  We commit to the register list when
userspace reads it via KVM_GET_REG_LIST, or when the vcpu is fired
up via KVM_RUN.

kvm_arm_vcpu_finalize() is currently a no-op, but future patches
will amend this to handle SVE on arm64.

Signed-off-by: Dave Martin <Dave.Martin@arm.com>
---
 arch/arm/include/asm/kvm_host.h   | 4 ++++
 arch/arm64/include/asm/kvm_host.h | 4 ++++
 virt/kvm/arm/arm.c                | 8 ++++++++
 3 files changed, 16 insertions(+)

diff --git a/arch/arm/include/asm/kvm_host.h b/arch/arm/include/asm/kvm_host.h
index ca56537..ab7c76b 100644
--- a/arch/arm/include/asm/kvm_host.h
+++ b/arch/arm/include/asm/kvm_host.h
@@ -360,4 +360,8 @@ static inline int kvm_arm_setup_stage2(struct kvm *kvm, unsigned long type)
 	return 0;
 }
 
+/* Commit to the set of vcpu registers currently configured: */
+static inline int kvm_arm_vcpu_finalize(struct kvm_vcpu *vcpu) { return 0; }
+#define kvm_arm_vcpu_finalized(vcpu) true
+
 #endif /* __ARM_KVM_HOST_H__ */
diff --git a/arch/arm64/include/asm/kvm_host.h b/arch/arm64/include/asm/kvm_host.h
index d233855..015c2578 100644
--- a/arch/arm64/include/asm/kvm_host.h
+++ b/arch/arm64/include/asm/kvm_host.h
@@ -553,4 +553,8 @@ void kvm_arch_free_vm(struct kvm *kvm);
 
 int kvm_arm_setup_stage2(struct kvm *kvm, unsigned long type);
 
+/* Commit to the set of vcpu registers currently configured: */
+static inline int kvm_arm_vcpu_finalize(struct kvm_vcpu *vcpu) { return 0; }
+#define kvm_arm_vcpu_finalized(vcpu) true
+
 #endif /* __ARM64_KVM_HOST_H__ */
diff --git a/virt/kvm/arm/arm.c b/virt/kvm/arm/arm.c
index 9e350fd3..12f9dc2 100644
--- a/virt/kvm/arm/arm.c
+++ b/virt/kvm/arm/arm.c
@@ -560,6 +560,10 @@ static int kvm_vcpu_first_run_init(struct kvm_vcpu *vcpu)
 	if (likely(vcpu->arch.has_run_once))
 		return 0;
 
+	ret = kvm_arm_vcpu_finalize(vcpu);
+	if (ret)
+		return ret;
+
 	vcpu->arch.has_run_once = true;
 
 	if (likely(irqchip_in_kernel(kvm))) {
@@ -1121,6 +1125,10 @@ long kvm_arch_vcpu_ioctl(struct file *filp,
 		if (unlikely(!kvm_vcpu_initialized(vcpu)))
 			break;
 
+		r = kvm_arm_vcpu_finalize(vcpu);
+		if (r)
+			break;
+
 		r = -EFAULT;
 		if (copy_from_user(&reg_list, user_list, sizeof(reg_list)))
 			break;
-- 
2.1.4


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* [PATCH v5 22/26] KVM: arm64/sve: Add pseudo-register for the guest's vector lengths
  2019-02-18 19:52 ` Dave Martin
@ 2019-02-18 19:52   ` Dave Martin
  -1 siblings, 0 replies; 205+ messages in thread
From: Dave Martin @ 2019-02-18 19:52 UTC (permalink / raw)
  To: kvmarm
  Cc: Okamoto Takayuki, Christoffer Dall, Ard Biesheuvel, Marc Zyngier,
	Catalin Marinas, Will Deacon, Zhang Lei, linux-arm-kernel

This patch adds a new pseudo-register KVM_REG_ARM64_SVE_VLS to
allow userspace to set and query the set of vector lengths visible
to the guest, along with corresponding storage in struct
kvm_vcpu_arch.

In the future, multiple register slices per SVE register may be
visible through the ioctl interface.  Once the set of slices has
been determined we would not be able to allow the vector length set
to be changed any more, in order to avoid userspace seeing
inconsistent sets of registers.  For this reason, this patch adds
support to track vcpu finalization explicitly, and enforce proper
sequencing of ioctls.

The new pseudo-register is not exposed yet.  Subsequent patches
will allow SVE to be turned on for guest vcpus, making it visible.

Signed-off-by: Dave Martin <Dave.Martin@arm.com>

---

Changes since v4:

 * Add a UAPI header comment indicating the pseudo-register status of
   KVM_REG_ARM64_SVE_VLS.

 * Get rid of the sve_vqs[] array from struct kvm_vcpu_arch.  This
   array is pointless, because its contents must match the host's
   internal sve_vq_map anyway, up to vcpu->arch.sve_max_vl.

   The ioctl register accessors are slow-path code, so we can decode
   or reconstruct sve_vqs[] on demand instead, for exchange with
   userspace.

 * For compatibility with potential future architecture extensions,
   enabling vector lengths above 256 bytes for the guest is explicitly
   disallowed now (because the code for exposing additional bits
   through ioctl is currently missing).  This can be addressed later
   if/when needed.

Note:

 * I defensively pass an array by pointer here, to help avoid
   accidentally breaking assumptions during future maintenance.

   Due to (over?)zealous constification, this causes the following
   sparse warning.  I think this is sparse getting confused: I am not
   relying on any kernel-specific semantics here, and GCC generates no
   warning.

+arch/arm64/kvm/guest.c:33: warning: incorrect type in argument 1 (different modifiers)
+arch/arm64/kvm/guest.c:33:    expected unsigned long long const [usertype] ( *const vqs )[8]
+arch/arm64/kvm/guest.c:33:    got unsigned long long [usertype] ( * )[8]

---
 arch/arm64/include/asm/kvm_host.h |   7 ++-
 arch/arm64/include/uapi/asm/kvm.h |   4 ++
 arch/arm64/kvm/guest.c            | 124 ++++++++++++++++++++++++++++++++++++--
 arch/arm64/kvm/reset.c            |   9 +++
 4 files changed, 136 insertions(+), 8 deletions(-)

diff --git a/arch/arm64/include/asm/kvm_host.h b/arch/arm64/include/asm/kvm_host.h
index 015c2578..e53119a 100644
--- a/arch/arm64/include/asm/kvm_host.h
+++ b/arch/arm64/include/asm/kvm_host.h
@@ -24,6 +24,7 @@
 
 #include <linux/bitmap.h>
 #include <linux/types.h>
+#include <linux/kernel.h>
 #include <linux/kvm_types.h>
 #include <asm/cpufeature.h>
 #include <asm/daifflags.h>
@@ -331,6 +332,7 @@ struct kvm_vcpu_arch {
 #define KVM_ARM64_HOST_SVE_IN_USE	(1 << 3) /* backup for host TIF_SVE */
 #define KVM_ARM64_HOST_SVE_ENABLED	(1 << 4) /* SVE enabled for EL0 */
 #define KVM_ARM64_GUEST_HAS_SVE		(1 << 5) /* SVE exposed to guest */
+#define KVM_ARM64_VCPU_FINALIZED	(1 << 6) /* vcpu config completed */
 
 #define vcpu_has_sve(vcpu) (system_supports_sve() && \
 			    ((vcpu)->arch.flags & KVM_ARM64_GUEST_HAS_SVE))
@@ -554,7 +556,8 @@ void kvm_arch_free_vm(struct kvm *kvm);
 int kvm_arm_setup_stage2(struct kvm *kvm, unsigned long type);
 
 /* Commit to the set of vcpu registers currently configured: */
-static inline int kvm_arm_vcpu_finalize(struct kvm_vcpu *vcpu) { return 0; }
-#define kvm_arm_vcpu_finalized(vcpu) true
+int kvm_arm_vcpu_finalize(struct kvm_vcpu *vcpu);
+#define kvm_arm_vcpu_finalized(vcpu) \
+	((vcpu)->arch.flags & KVM_ARM64_VCPU_FINALIZED)
 
 #endif /* __ARM64_KVM_HOST_H__ */
diff --git a/arch/arm64/include/uapi/asm/kvm.h b/arch/arm64/include/uapi/asm/kvm.h
index ced760c..7ff1bd4 100644
--- a/arch/arm64/include/uapi/asm/kvm.h
+++ b/arch/arm64/include/uapi/asm/kvm.h
@@ -243,6 +243,10 @@ struct kvm_vcpu_events {
 					 ((n) << 5) | (i))
 #define KVM_REG_ARM64_SVE_FFR(i)	KVM_REG_ARM64_SVE_PREG(16, i)
 
+/* Vector lengths pseudo-register: */
+#define KVM_REG_ARM64_SVE_VLS		(KVM_REG_ARM64 | KVM_REG_ARM64_SVE | \
+					 KVM_REG_SIZE_U512 | 0xffff)
+
 /* Device Control API: ARM VGIC */
 #define KVM_DEV_ARM_VGIC_GRP_ADDR	0
 #define KVM_DEV_ARM_VGIC_GRP_DIST_REGS	1
diff --git a/arch/arm64/kvm/guest.c b/arch/arm64/kvm/guest.c
index 4a2ad60..5f48c17 100644
--- a/arch/arm64/kvm/guest.c
+++ b/arch/arm64/kvm/guest.c
@@ -217,6 +217,81 @@ static int set_core_reg(struct kvm_vcpu *vcpu, const struct kvm_one_reg *reg)
 	return err;
 }
 
+#define vq_word(vq) (((vq) - SVE_VQ_MIN) / 64)
+#define vq_mask(vq) ((u64)1 << ((vq) - SVE_VQ_MIN) % 64)
+
+static bool vq_present(
+	const u64 (*const vqs)[DIV_ROUND_UP(SVE_VQ_MAX - SVE_VQ_MIN + 1, 64)],
+	unsigned int vq)
+{
+	return (*vqs)[vq_word(vq)] & vq_mask(vq);
+}
+
+static int get_sve_vls(struct kvm_vcpu *vcpu, const struct kvm_one_reg *reg)
+{
+	unsigned int max_vq, vq;
+	u64 vqs[DIV_ROUND_UP(SVE_VQ_MAX - SVE_VQ_MIN + 1, 64)];
+
+	if (WARN_ON(!sve_vl_valid(vcpu->arch.sve_max_vl)))
+		return -EINVAL;
+
+	memset(vqs, 0, sizeof(vqs));
+
+	max_vq = sve_vq_from_vl(vcpu->arch.sve_max_vl);
+	for (vq = SVE_VQ_MIN; vq <= max_vq; ++vq)
+		if (sve_vq_available(vq))
+			vqs[vq_word(vq)] |= vq_mask(vq);
+
+	BUILD_BUG_ON(sizeof(vqs) != KVM_REG_SIZE(reg->id));
+	if (copy_to_user((void __user *)reg->addr, vqs, sizeof(vqs)))
+		return -EFAULT;
+
+	return 0;
+}
+
+static int set_sve_vls(struct kvm_vcpu *vcpu, const struct kvm_one_reg *reg)
+{
+	unsigned int max_vq, vq;
+	u64 vqs[DIV_ROUND_UP(SVE_VQ_MAX - SVE_VQ_MIN + 1, 64)];
+
+	if (kvm_arm_vcpu_finalized(vcpu))
+		return -EPERM; /* too late! */
+
+	if (WARN_ON(vcpu->arch.sve_state))
+		return -EINVAL;
+
+	BUILD_BUG_ON(sizeof(vqs) != KVM_REG_SIZE(reg->id));
+	if (copy_from_user(vqs, (const void __user *)reg->addr, sizeof(vqs)))
+		return -EFAULT;
+
+	max_vq = 0;
+	for (vq = SVE_VQ_MIN; vq <= SVE_VQ_MAX; ++vq)
+		if (vq_present(&vqs, vq))
+			max_vq = vq;
+
+	/*
+	 * The get_sve_reg()/set_sve_reg() ioctl interface will need
+	 * to be extended with multiple register slice support in
+	 * order to support vector lengths greater than
+	 * SVE_VL_ARCH_MAX:
+	 */
+	if (WARN_ONCE(sve_vl_from_vq(max_vq) > SVE_VL_ARCH_MAX,
+		      "KVM: Requested vector length not supported yet\n"))
+		return -EINVAL;
+
+	for (vq = SVE_VQ_MIN; vq <= max_vq; ++vq)
+		if (vq_present(&vqs, vq) != sve_vq_available(vq))
+			return -EINVAL;
+
+	/* Can't run with no vector lengths at all: */
+	if (max_vq < SVE_VQ_MIN)
+		return -EINVAL;
+
+	vcpu->arch.sve_max_vl = sve_vl_from_vq(max_vq);
+
+	return 0;
+}
+
 #define SVE_REG_SLICE_SHIFT	0
 #define SVE_REG_SLICE_BITS	5
 #define SVE_REG_ID_SHIFT	(SVE_REG_SLICE_SHIFT + SVE_REG_SLICE_BITS)
@@ -297,9 +372,21 @@ static int sve_reg_region(struct sve_state_region *region,
 static int get_sve_reg(struct kvm_vcpu *vcpu, const struct kvm_one_reg *reg)
 {
 	struct sve_state_region region;
+	int ret;
 	char __user *uptr = (char __user *)reg->addr;
 
-	if (!vcpu_has_sve(vcpu) || sve_reg_region(&region, vcpu, reg))
+	if (!vcpu_has_sve(vcpu))
+		return -ENOENT;
+
+	if (reg->id == KVM_REG_ARM64_SVE_VLS)
+		return get_sve_vls(vcpu, reg);
+
+	/* Finalize the number of slices per SVE register: */
+	ret = kvm_arm_vcpu_finalize(vcpu);
+	if (ret)
+		return ret;
+
+	if (sve_reg_region(&region, vcpu, reg))
 		return -ENOENT;
 
 	if (copy_to_user(uptr, vcpu->arch.sve_state + region.koffset,
@@ -313,9 +400,21 @@ static int get_sve_reg(struct kvm_vcpu *vcpu, const struct kvm_one_reg *reg)
 static int set_sve_reg(struct kvm_vcpu *vcpu, const struct kvm_one_reg *reg)
 {
 	struct sve_state_region region;
+	int ret;
 	const char __user *uptr = (const char __user *)reg->addr;
 
-	if (!vcpu_has_sve(vcpu) || sve_reg_region(&region, vcpu, reg))
+	if (!vcpu_has_sve(vcpu))
+		return -ENOENT;
+
+	if (reg->id == KVM_REG_ARM64_SVE_VLS)
+		return set_sve_vls(vcpu, reg);
+
+	/* Finalize the number of slices per SVE register: */
+	ret = kvm_arm_vcpu_finalize(vcpu);
+	if (ret)
+		return ret;
+
+	if (sve_reg_region(&region, vcpu, reg))
 		return -ENOENT;
 
 	if (copy_from_user(vcpu->arch.sve_state + region.koffset, uptr,
@@ -452,30 +551,43 @@ static unsigned long num_sve_regs(const struct kvm_vcpu *vcpu)
 	if (!vcpu_has_sve(vcpu))
 		return 0;
 
-	return slices * (SVE_NUM_PREGS + SVE_NUM_ZREGS + 1 /* FFR */);
+	return slices * (SVE_NUM_PREGS + SVE_NUM_ZREGS + 1 /* FFR */)
+		+ 1; /* KVM_REG_ARM64_SVE_VLS */
 }
 
 static int copy_sve_reg_indices(const struct kvm_vcpu *vcpu, u64 __user **uind)
 {
 	/* Only the first slice ever exists, for now */
 	const unsigned int slices = 1;
+	u64 reg;
 	unsigned int i, n;
 
 	if (!vcpu_has_sve(vcpu))
 		return 0;
 
+	/*
+	 * Enumerate this first, so that userspace can save/restore in
+	 * the order reported by KVM_GET_REG_LIST:
+	 */
+	reg = KVM_REG_ARM64_SVE_VLS;
+	if (put_user(reg, (*uind)++))
+		return -EFAULT;
+
 	for (i = 0; i < slices; i++) {
 		for (n = 0; n < SVE_NUM_ZREGS; n++) {
-			if (put_user(KVM_REG_ARM64_SVE_ZREG(n, i), (*uind)++))
+			reg = KVM_REG_ARM64_SVE_ZREG(n, i);
+			if (put_user(reg, (*uind)++))
 				return -EFAULT;
 		}
 
 		for (n = 0; n < SVE_NUM_PREGS; n++) {
-			if (put_user(KVM_REG_ARM64_SVE_PREG(n, i), (*uind)++))
+			reg = KVM_REG_ARM64_SVE_PREG(n, i);
+			if (put_user(reg, (*uind)++))
 				return -EFAULT;
 		}
 
-		if (put_user(KVM_REG_ARM64_SVE_FFR(i), (*uind)++))
+		reg = KVM_REG_ARM64_SVE_FFR(i);
+		if (put_user(reg, (*uind)++))
 			return -EFAULT;
 	}
 
diff --git a/arch/arm64/kvm/reset.c b/arch/arm64/kvm/reset.c
index b72a3dd..1379fb2 100644
--- a/arch/arm64/kvm/reset.c
+++ b/arch/arm64/kvm/reset.c
@@ -98,6 +98,15 @@ int kvm_arch_vm_ioctl_check_extension(struct kvm *kvm, long ext)
 	return r;
 }
 
+int kvm_arm_vcpu_finalize(struct kvm_vcpu *vcpu)
+{
+	if (likely(kvm_arm_vcpu_finalized(vcpu)))
+		return 0;
+
+	vcpu->arch.flags |= KVM_ARM64_VCPU_FINALIZED;
+	return 0;
+}
+
 /**
  * kvm_reset_vcpu - sets core registers and sys_regs to reset value
  * @vcpu: The VCPU pointer
-- 
2.1.4

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

* [PATCH v5 22/26] KVM: arm64/sve: Add pseudo-register for the guest's vector lengths
@ 2019-02-18 19:52   ` Dave Martin
  0 siblings, 0 replies; 205+ messages in thread
From: Dave Martin @ 2019-02-18 19:52 UTC (permalink / raw)
  To: kvmarm
  Cc: Peter Maydell, Okamoto Takayuki, Christoffer Dall,
	Ard Biesheuvel, Marc Zyngier, Catalin Marinas, Will Deacon,
	Zhang Lei, Julien Grall, Alex Bennée, linux-arm-kernel

This patch adds a new pseudo-register KVM_REG_ARM64_SVE_VLS to
allow userspace to set and query the set of vector lengths visible
to the guest, along with corresponding storage in struct
kvm_vcpu_arch.

In the future, multiple register slices per SVE register may be
visible through the ioctl interface.  Once the set of slices has
been determined we would not be able to allow the vector length set
to be changed any more, in order to avoid userspace seeing
inconsistent sets of registers.  For this reason, this patch adds
support to track vcpu finalization explicitly, and enforce proper
sequencing of ioctls.

The new pseudo-register is not exposed yet.  Subsequent patches
will allow SVE to be turned on for guest vcpus, making it visible.

Signed-off-by: Dave Martin <Dave.Martin@arm.com>

---

Changes since v4:

 * Add a UAPI header comment indicating the pseudo-register status of
   KVM_REG_ARM64_SVE_VLS.

 * Get rid of the sve_vqs[] array from struct kvm_vcpu_arch.  This
   array is pointless, because its contents must match the host's
   internal sve_vq_map anyway, up to vcpu->arch.sve_max_vl.

   The ioctl register accessors are slow-path code, so we can decode
   or reconstruct sve_vqs[] on demand instead, for exchange with
   userspace.

 * For compatibility with potential future architecture extensions,
   enabling vector lengths above 256 bytes for the guest is explicitly
   disallowed now (because the code for exposing additional bits
   through ioctl is currently missing).  This can be addressed later
   if/when needed.

Note:

 * I defensively pass an array by pointer here, to help avoid
   accidentally breaking assumptions during future maintenance.

   Due to (over?)zealous constification, this causes the following
   sparse warning.  I think this is sparse getting confused: I am not
   relying on any kernel-specific semantics here, and GCC generates no
   warning.

+arch/arm64/kvm/guest.c:33: warning: incorrect type in argument 1 (different modifiers)
+arch/arm64/kvm/guest.c:33:    expected unsigned long long const [usertype] ( *const vqs )[8]
+arch/arm64/kvm/guest.c:33:    got unsigned long long [usertype] ( * )[8]

---
 arch/arm64/include/asm/kvm_host.h |   7 ++-
 arch/arm64/include/uapi/asm/kvm.h |   4 ++
 arch/arm64/kvm/guest.c            | 124 ++++++++++++++++++++++++++++++++++++--
 arch/arm64/kvm/reset.c            |   9 +++
 4 files changed, 136 insertions(+), 8 deletions(-)

diff --git a/arch/arm64/include/asm/kvm_host.h b/arch/arm64/include/asm/kvm_host.h
index 015c2578..e53119a 100644
--- a/arch/arm64/include/asm/kvm_host.h
+++ b/arch/arm64/include/asm/kvm_host.h
@@ -24,6 +24,7 @@
 
 #include <linux/bitmap.h>
 #include <linux/types.h>
+#include <linux/kernel.h>
 #include <linux/kvm_types.h>
 #include <asm/cpufeature.h>
 #include <asm/daifflags.h>
@@ -331,6 +332,7 @@ struct kvm_vcpu_arch {
 #define KVM_ARM64_HOST_SVE_IN_USE	(1 << 3) /* backup for host TIF_SVE */
 #define KVM_ARM64_HOST_SVE_ENABLED	(1 << 4) /* SVE enabled for EL0 */
 #define KVM_ARM64_GUEST_HAS_SVE		(1 << 5) /* SVE exposed to guest */
+#define KVM_ARM64_VCPU_FINALIZED	(1 << 6) /* vcpu config completed */
 
 #define vcpu_has_sve(vcpu) (system_supports_sve() && \
 			    ((vcpu)->arch.flags & KVM_ARM64_GUEST_HAS_SVE))
@@ -554,7 +556,8 @@ void kvm_arch_free_vm(struct kvm *kvm);
 int kvm_arm_setup_stage2(struct kvm *kvm, unsigned long type);
 
 /* Commit to the set of vcpu registers currently configured: */
-static inline int kvm_arm_vcpu_finalize(struct kvm_vcpu *vcpu) { return 0; }
-#define kvm_arm_vcpu_finalized(vcpu) true
+int kvm_arm_vcpu_finalize(struct kvm_vcpu *vcpu);
+#define kvm_arm_vcpu_finalized(vcpu) \
+	((vcpu)->arch.flags & KVM_ARM64_VCPU_FINALIZED)
 
 #endif /* __ARM64_KVM_HOST_H__ */
diff --git a/arch/arm64/include/uapi/asm/kvm.h b/arch/arm64/include/uapi/asm/kvm.h
index ced760c..7ff1bd4 100644
--- a/arch/arm64/include/uapi/asm/kvm.h
+++ b/arch/arm64/include/uapi/asm/kvm.h
@@ -243,6 +243,10 @@ struct kvm_vcpu_events {
 					 ((n) << 5) | (i))
 #define KVM_REG_ARM64_SVE_FFR(i)	KVM_REG_ARM64_SVE_PREG(16, i)
 
+/* Vector lengths pseudo-register: */
+#define KVM_REG_ARM64_SVE_VLS		(KVM_REG_ARM64 | KVM_REG_ARM64_SVE | \
+					 KVM_REG_SIZE_U512 | 0xffff)
+
 /* Device Control API: ARM VGIC */
 #define KVM_DEV_ARM_VGIC_GRP_ADDR	0
 #define KVM_DEV_ARM_VGIC_GRP_DIST_REGS	1
diff --git a/arch/arm64/kvm/guest.c b/arch/arm64/kvm/guest.c
index 4a2ad60..5f48c17 100644
--- a/arch/arm64/kvm/guest.c
+++ b/arch/arm64/kvm/guest.c
@@ -217,6 +217,81 @@ static int set_core_reg(struct kvm_vcpu *vcpu, const struct kvm_one_reg *reg)
 	return err;
 }
 
+#define vq_word(vq) (((vq) - SVE_VQ_MIN) / 64)
+#define vq_mask(vq) ((u64)1 << ((vq) - SVE_VQ_MIN) % 64)
+
+static bool vq_present(
+	const u64 (*const vqs)[DIV_ROUND_UP(SVE_VQ_MAX - SVE_VQ_MIN + 1, 64)],
+	unsigned int vq)
+{
+	return (*vqs)[vq_word(vq)] & vq_mask(vq);
+}
+
+static int get_sve_vls(struct kvm_vcpu *vcpu, const struct kvm_one_reg *reg)
+{
+	unsigned int max_vq, vq;
+	u64 vqs[DIV_ROUND_UP(SVE_VQ_MAX - SVE_VQ_MIN + 1, 64)];
+
+	if (WARN_ON(!sve_vl_valid(vcpu->arch.sve_max_vl)))
+		return -EINVAL;
+
+	memset(vqs, 0, sizeof(vqs));
+
+	max_vq = sve_vq_from_vl(vcpu->arch.sve_max_vl);
+	for (vq = SVE_VQ_MIN; vq <= max_vq; ++vq)
+		if (sve_vq_available(vq))
+			vqs[vq_word(vq)] |= vq_mask(vq);
+
+	BUILD_BUG_ON(sizeof(vqs) != KVM_REG_SIZE(reg->id));
+	if (copy_to_user((void __user *)reg->addr, vqs, sizeof(vqs)))
+		return -EFAULT;
+
+	return 0;
+}
+
+static int set_sve_vls(struct kvm_vcpu *vcpu, const struct kvm_one_reg *reg)
+{
+	unsigned int max_vq, vq;
+	u64 vqs[DIV_ROUND_UP(SVE_VQ_MAX - SVE_VQ_MIN + 1, 64)];
+
+	if (kvm_arm_vcpu_finalized(vcpu))
+		return -EPERM; /* too late! */
+
+	if (WARN_ON(vcpu->arch.sve_state))
+		return -EINVAL;
+
+	BUILD_BUG_ON(sizeof(vqs) != KVM_REG_SIZE(reg->id));
+	if (copy_from_user(vqs, (const void __user *)reg->addr, sizeof(vqs)))
+		return -EFAULT;
+
+	max_vq = 0;
+	for (vq = SVE_VQ_MIN; vq <= SVE_VQ_MAX; ++vq)
+		if (vq_present(&vqs, vq))
+			max_vq = vq;
+
+	/*
+	 * The get_sve_reg()/set_sve_reg() ioctl interface will need
+	 * to be extended with multiple register slice support in
+	 * order to support vector lengths greater than
+	 * SVE_VL_ARCH_MAX:
+	 */
+	if (WARN_ONCE(sve_vl_from_vq(max_vq) > SVE_VL_ARCH_MAX,
+		      "KVM: Requested vector length not supported yet\n"))
+		return -EINVAL;
+
+	for (vq = SVE_VQ_MIN; vq <= max_vq; ++vq)
+		if (vq_present(&vqs, vq) != sve_vq_available(vq))
+			return -EINVAL;
+
+	/* Can't run with no vector lengths at all: */
+	if (max_vq < SVE_VQ_MIN)
+		return -EINVAL;
+
+	vcpu->arch.sve_max_vl = sve_vl_from_vq(max_vq);
+
+	return 0;
+}
+
 #define SVE_REG_SLICE_SHIFT	0
 #define SVE_REG_SLICE_BITS	5
 #define SVE_REG_ID_SHIFT	(SVE_REG_SLICE_SHIFT + SVE_REG_SLICE_BITS)
@@ -297,9 +372,21 @@ static int sve_reg_region(struct sve_state_region *region,
 static int get_sve_reg(struct kvm_vcpu *vcpu, const struct kvm_one_reg *reg)
 {
 	struct sve_state_region region;
+	int ret;
 	char __user *uptr = (char __user *)reg->addr;
 
-	if (!vcpu_has_sve(vcpu) || sve_reg_region(&region, vcpu, reg))
+	if (!vcpu_has_sve(vcpu))
+		return -ENOENT;
+
+	if (reg->id == KVM_REG_ARM64_SVE_VLS)
+		return get_sve_vls(vcpu, reg);
+
+	/* Finalize the number of slices per SVE register: */
+	ret = kvm_arm_vcpu_finalize(vcpu);
+	if (ret)
+		return ret;
+
+	if (sve_reg_region(&region, vcpu, reg))
 		return -ENOENT;
 
 	if (copy_to_user(uptr, vcpu->arch.sve_state + region.koffset,
@@ -313,9 +400,21 @@ static int get_sve_reg(struct kvm_vcpu *vcpu, const struct kvm_one_reg *reg)
 static int set_sve_reg(struct kvm_vcpu *vcpu, const struct kvm_one_reg *reg)
 {
 	struct sve_state_region region;
+	int ret;
 	const char __user *uptr = (const char __user *)reg->addr;
 
-	if (!vcpu_has_sve(vcpu) || sve_reg_region(&region, vcpu, reg))
+	if (!vcpu_has_sve(vcpu))
+		return -ENOENT;
+
+	if (reg->id == KVM_REG_ARM64_SVE_VLS)
+		return set_sve_vls(vcpu, reg);
+
+	/* Finalize the number of slices per SVE register: */
+	ret = kvm_arm_vcpu_finalize(vcpu);
+	if (ret)
+		return ret;
+
+	if (sve_reg_region(&region, vcpu, reg))
 		return -ENOENT;
 
 	if (copy_from_user(vcpu->arch.sve_state + region.koffset, uptr,
@@ -452,30 +551,43 @@ static unsigned long num_sve_regs(const struct kvm_vcpu *vcpu)
 	if (!vcpu_has_sve(vcpu))
 		return 0;
 
-	return slices * (SVE_NUM_PREGS + SVE_NUM_ZREGS + 1 /* FFR */);
+	return slices * (SVE_NUM_PREGS + SVE_NUM_ZREGS + 1 /* FFR */)
+		+ 1; /* KVM_REG_ARM64_SVE_VLS */
 }
 
 static int copy_sve_reg_indices(const struct kvm_vcpu *vcpu, u64 __user **uind)
 {
 	/* Only the first slice ever exists, for now */
 	const unsigned int slices = 1;
+	u64 reg;
 	unsigned int i, n;
 
 	if (!vcpu_has_sve(vcpu))
 		return 0;
 
+	/*
+	 * Enumerate this first, so that userspace can save/restore in
+	 * the order reported by KVM_GET_REG_LIST:
+	 */
+	reg = KVM_REG_ARM64_SVE_VLS;
+	if (put_user(reg, (*uind)++))
+		return -EFAULT;
+
 	for (i = 0; i < slices; i++) {
 		for (n = 0; n < SVE_NUM_ZREGS; n++) {
-			if (put_user(KVM_REG_ARM64_SVE_ZREG(n, i), (*uind)++))
+			reg = KVM_REG_ARM64_SVE_ZREG(n, i);
+			if (put_user(reg, (*uind)++))
 				return -EFAULT;
 		}
 
 		for (n = 0; n < SVE_NUM_PREGS; n++) {
-			if (put_user(KVM_REG_ARM64_SVE_PREG(n, i), (*uind)++))
+			reg = KVM_REG_ARM64_SVE_PREG(n, i);
+			if (put_user(reg, (*uind)++))
 				return -EFAULT;
 		}
 
-		if (put_user(KVM_REG_ARM64_SVE_FFR(i), (*uind)++))
+		reg = KVM_REG_ARM64_SVE_FFR(i);
+		if (put_user(reg, (*uind)++))
 			return -EFAULT;
 	}
 
diff --git a/arch/arm64/kvm/reset.c b/arch/arm64/kvm/reset.c
index b72a3dd..1379fb2 100644
--- a/arch/arm64/kvm/reset.c
+++ b/arch/arm64/kvm/reset.c
@@ -98,6 +98,15 @@ int kvm_arch_vm_ioctl_check_extension(struct kvm *kvm, long ext)
 	return r;
 }
 
+int kvm_arm_vcpu_finalize(struct kvm_vcpu *vcpu)
+{
+	if (likely(kvm_arm_vcpu_finalized(vcpu)))
+		return 0;
+
+	vcpu->arch.flags |= KVM_ARM64_VCPU_FINALIZED;
+	return 0;
+}
+
 /**
  * kvm_reset_vcpu - sets core registers and sys_regs to reset value
  * @vcpu: The VCPU pointer
-- 
2.1.4


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* [PATCH v5 23/26] KVM: arm64/sve: Allow userspace to enable SVE for vcpus
  2019-02-18 19:52 ` Dave Martin
@ 2019-02-18 19:52   ` Dave Martin
  -1 siblings, 0 replies; 205+ messages in thread
From: Dave Martin @ 2019-02-18 19:52 UTC (permalink / raw)
  To: kvmarm
  Cc: Okamoto Takayuki, Christoffer Dall, Ard Biesheuvel, Marc Zyngier,
	Catalin Marinas, Will Deacon, Zhang Lei, linux-arm-kernel

Now that all the pieces are in place, this patch offers a new flag
KVM_ARM_VCPU_SVE that userspace can pass to KVM_ARM_VCPU_INIT to
turn on SVE for the guest, on a per-vcpu basis.

As part of this, support for initialisation and reset of the SVE
vector length set and registers is added in the appropriate places.
Allocation SVE registers is deferred until kvm_arm_vcpu_finalize(),
by which time the size of the registers is known.

Setting the vector lengths supported by the vcpu is considered
configuration of the emulated hardware rather than runtime
configuration, so no support is offered for changing the vector
lengths of an existing vcpu across reset.

Signed-off-by: Dave Martin <Dave.Martin@arm.com>

---

Changes since v4:

 * Pull out vcpu_sve_state_size(), for use earlier in the series.

 * Remove unnecessary vcpu->arch.sve_vqs[], and clamp maximum guest
   vector length to 256 bytes for forwards compatibility.

   (See "KVM: arm64/sve: Add pseudo-register for the guest's vector
   lengths".)

 * Minor tidyups to make some checks less verbose.
---
 arch/arm64/include/asm/kvm_host.h |  2 +-
 arch/arm64/include/uapi/asm/kvm.h |  1 +
 arch/arm64/kvm/reset.c            | 70 ++++++++++++++++++++++++++++++++++++++-
 3 files changed, 71 insertions(+), 2 deletions(-)

diff --git a/arch/arm64/include/asm/kvm_host.h b/arch/arm64/include/asm/kvm_host.h
index e53119a..3277a39 100644
--- a/arch/arm64/include/asm/kvm_host.h
+++ b/arch/arm64/include/asm/kvm_host.h
@@ -45,7 +45,7 @@
 
 #define KVM_MAX_VCPUS VGIC_V3_MAX_CPUS
 
-#define KVM_VCPU_MAX_FEATURES 4
+#define KVM_VCPU_MAX_FEATURES 5
 
 #define KVM_REQ_SLEEP \
 	KVM_ARCH_REQ_FLAGS(0, KVM_REQUEST_WAIT | KVM_REQUEST_NO_WAKEUP)
diff --git a/arch/arm64/include/uapi/asm/kvm.h b/arch/arm64/include/uapi/asm/kvm.h
index 7ff1bd4..6963b7e 100644
--- a/arch/arm64/include/uapi/asm/kvm.h
+++ b/arch/arm64/include/uapi/asm/kvm.h
@@ -102,6 +102,7 @@ struct kvm_regs {
 #define KVM_ARM_VCPU_EL1_32BIT		1 /* CPU running a 32bit VM */
 #define KVM_ARM_VCPU_PSCI_0_2		2 /* CPU uses PSCI v0.2 */
 #define KVM_ARM_VCPU_PMU_V3		3 /* Support guest PMUv3 */
+#define KVM_ARM_VCPU_SVE		4 /* enable SVE for this CPU */
 
 struct kvm_vcpu_init {
 	__u32 target;
diff --git a/arch/arm64/kvm/reset.c b/arch/arm64/kvm/reset.c
index 1379fb2..e67cd2e 100644
--- a/arch/arm64/kvm/reset.c
+++ b/arch/arm64/kvm/reset.c
@@ -23,11 +23,13 @@
 #include <linux/kvm_host.h>
 #include <linux/kvm.h>
 #include <linux/hw_breakpoint.h>
+#include <linux/slab.h>
 
 #include <kvm/arm_arch_timer.h>
 
 #include <asm/cpufeature.h>
 #include <asm/cputype.h>
+#include <asm/fpsimd.h>
 #include <asm/ptrace.h>
 #include <asm/kvm_arm.h>
 #include <asm/kvm_asm.h>
@@ -98,11 +100,69 @@ int kvm_arch_vm_ioctl_check_extension(struct kvm *kvm, long ext)
 	return r;
 }
 
+static int kvm_reset_sve(struct kvm_vcpu *vcpu)
+{
+	if (!system_supports_sve())
+		return -EINVAL;
+
+	/* If resetting an already-configured vcpu, just zero the SVE regs: */
+	if (vcpu->arch.sve_state) {
+		size_t size = vcpu_sve_state_size(vcpu);
+
+		if (!size || WARN_ON(!vcpu_has_sve(vcpu)))
+			return -EINVAL;
+
+		memset(vcpu->arch.sve_state, 0, size);
+		return 0;
+	}
+
+	if (WARN_ON(!sve_vl_valid(sve_max_vl)))
+		return -EINVAL;
+
+	/* If the full set of host vector lengths cannot be used, give up: */
+	if (sve_max_virtualisable_vl < sve_max_vl)
+		return -EINVAL;
+
+	/* Default to the set of vector lengths supported by the host */
+	vcpu->arch.sve_max_vl = sve_max_vl;
+
+	/*
+	 * The get_sve_reg()/set_sve_reg() ioctl interface will need
+	 * to be extended with multiple register slice support in
+	 * order to support vector lengths greater than
+	 * SVE_VL_ARCH_MAX:
+	 */
+	if (WARN_ONCE(vcpu->arch.sve_max_vl > SVE_VL_ARCH_MAX,
+		      "KVM: SVE vector length for guests limited to %d bytes\n",
+		      SVE_VL_ARCH_MAX))
+		vcpu->arch.sve_max_vl = SVE_VL_ARCH_MAX;
+
+	/*
+	 * Userspace can still customize the vector lengths by writing
+	 * KVM_REG_ARM64_SVE_VLS.  Allocation is deferred until
+	 * kvm_arm_vcpu_finalize(), which freezes the configuration.
+	 */
+	vcpu->arch.flags |= KVM_ARM64_GUEST_HAS_SVE;
+
+	return 0;
+}
+
 int kvm_arm_vcpu_finalize(struct kvm_vcpu *vcpu)
 {
 	if (likely(kvm_arm_vcpu_finalized(vcpu)))
 		return 0;
 
+	if (vcpu_has_sve(vcpu)) {
+		size_t size = vcpu_sve_state_size(vcpu);
+
+		if (!size)
+			return -EINVAL;
+
+		vcpu->arch.sve_state = kzalloc(size, GFP_KERNEL);
+		if (!vcpu->arch.sve_state)
+			return -ENOMEM;
+	}
+
 	vcpu->arch.flags |= KVM_ARM64_VCPU_FINALIZED;
 	return 0;
 }
@@ -113,12 +173,20 @@ int kvm_arm_vcpu_finalize(struct kvm_vcpu *vcpu)
  *
  * This function finds the right table above and sets the registers on
  * the virtual CPU struct to their architecturally defined reset
- * values.
+ * values, except for registers whose reset is deferred until
+ * kvm_arm_vcpu_finalize().
  */
 int kvm_reset_vcpu(struct kvm_vcpu *vcpu)
 {
+	int ret;
 	const struct kvm_regs *cpu_reset;
 
+	if (test_bit(KVM_ARM_VCPU_SVE, vcpu->arch.features)) {
+		ret = kvm_reset_sve(vcpu);
+		if (ret)
+			return ret;
+	}
+
 	switch (vcpu->arch.target) {
 	default:
 		if (test_bit(KVM_ARM_VCPU_EL1_32BIT, vcpu->arch.features)) {
-- 
2.1.4

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

* [PATCH v5 23/26] KVM: arm64/sve: Allow userspace to enable SVE for vcpus
@ 2019-02-18 19:52   ` Dave Martin
  0 siblings, 0 replies; 205+ messages in thread
From: Dave Martin @ 2019-02-18 19:52 UTC (permalink / raw)
  To: kvmarm
  Cc: Peter Maydell, Okamoto Takayuki, Christoffer Dall,
	Ard Biesheuvel, Marc Zyngier, Catalin Marinas, Will Deacon,
	Zhang Lei, Julien Grall, Alex Bennée, linux-arm-kernel

Now that all the pieces are in place, this patch offers a new flag
KVM_ARM_VCPU_SVE that userspace can pass to KVM_ARM_VCPU_INIT to
turn on SVE for the guest, on a per-vcpu basis.

As part of this, support for initialisation and reset of the SVE
vector length set and registers is added in the appropriate places.
Allocation SVE registers is deferred until kvm_arm_vcpu_finalize(),
by which time the size of the registers is known.

Setting the vector lengths supported by the vcpu is considered
configuration of the emulated hardware rather than runtime
configuration, so no support is offered for changing the vector
lengths of an existing vcpu across reset.

Signed-off-by: Dave Martin <Dave.Martin@arm.com>

---

Changes since v4:

 * Pull out vcpu_sve_state_size(), for use earlier in the series.

 * Remove unnecessary vcpu->arch.sve_vqs[], and clamp maximum guest
   vector length to 256 bytes for forwards compatibility.

   (See "KVM: arm64/sve: Add pseudo-register for the guest's vector
   lengths".)

 * Minor tidyups to make some checks less verbose.
---
 arch/arm64/include/asm/kvm_host.h |  2 +-
 arch/arm64/include/uapi/asm/kvm.h |  1 +
 arch/arm64/kvm/reset.c            | 70 ++++++++++++++++++++++++++++++++++++++-
 3 files changed, 71 insertions(+), 2 deletions(-)

diff --git a/arch/arm64/include/asm/kvm_host.h b/arch/arm64/include/asm/kvm_host.h
index e53119a..3277a39 100644
--- a/arch/arm64/include/asm/kvm_host.h
+++ b/arch/arm64/include/asm/kvm_host.h
@@ -45,7 +45,7 @@
 
 #define KVM_MAX_VCPUS VGIC_V3_MAX_CPUS
 
-#define KVM_VCPU_MAX_FEATURES 4
+#define KVM_VCPU_MAX_FEATURES 5
 
 #define KVM_REQ_SLEEP \
 	KVM_ARCH_REQ_FLAGS(0, KVM_REQUEST_WAIT | KVM_REQUEST_NO_WAKEUP)
diff --git a/arch/arm64/include/uapi/asm/kvm.h b/arch/arm64/include/uapi/asm/kvm.h
index 7ff1bd4..6963b7e 100644
--- a/arch/arm64/include/uapi/asm/kvm.h
+++ b/arch/arm64/include/uapi/asm/kvm.h
@@ -102,6 +102,7 @@ struct kvm_regs {
 #define KVM_ARM_VCPU_EL1_32BIT		1 /* CPU running a 32bit VM */
 #define KVM_ARM_VCPU_PSCI_0_2		2 /* CPU uses PSCI v0.2 */
 #define KVM_ARM_VCPU_PMU_V3		3 /* Support guest PMUv3 */
+#define KVM_ARM_VCPU_SVE		4 /* enable SVE for this CPU */
 
 struct kvm_vcpu_init {
 	__u32 target;
diff --git a/arch/arm64/kvm/reset.c b/arch/arm64/kvm/reset.c
index 1379fb2..e67cd2e 100644
--- a/arch/arm64/kvm/reset.c
+++ b/arch/arm64/kvm/reset.c
@@ -23,11 +23,13 @@
 #include <linux/kvm_host.h>
 #include <linux/kvm.h>
 #include <linux/hw_breakpoint.h>
+#include <linux/slab.h>
 
 #include <kvm/arm_arch_timer.h>
 
 #include <asm/cpufeature.h>
 #include <asm/cputype.h>
+#include <asm/fpsimd.h>
 #include <asm/ptrace.h>
 #include <asm/kvm_arm.h>
 #include <asm/kvm_asm.h>
@@ -98,11 +100,69 @@ int kvm_arch_vm_ioctl_check_extension(struct kvm *kvm, long ext)
 	return r;
 }
 
+static int kvm_reset_sve(struct kvm_vcpu *vcpu)
+{
+	if (!system_supports_sve())
+		return -EINVAL;
+
+	/* If resetting an already-configured vcpu, just zero the SVE regs: */
+	if (vcpu->arch.sve_state) {
+		size_t size = vcpu_sve_state_size(vcpu);
+
+		if (!size || WARN_ON(!vcpu_has_sve(vcpu)))
+			return -EINVAL;
+
+		memset(vcpu->arch.sve_state, 0, size);
+		return 0;
+	}
+
+	if (WARN_ON(!sve_vl_valid(sve_max_vl)))
+		return -EINVAL;
+
+	/* If the full set of host vector lengths cannot be used, give up: */
+	if (sve_max_virtualisable_vl < sve_max_vl)
+		return -EINVAL;
+
+	/* Default to the set of vector lengths supported by the host */
+	vcpu->arch.sve_max_vl = sve_max_vl;
+
+	/*
+	 * The get_sve_reg()/set_sve_reg() ioctl interface will need
+	 * to be extended with multiple register slice support in
+	 * order to support vector lengths greater than
+	 * SVE_VL_ARCH_MAX:
+	 */
+	if (WARN_ONCE(vcpu->arch.sve_max_vl > SVE_VL_ARCH_MAX,
+		      "KVM: SVE vector length for guests limited to %d bytes\n",
+		      SVE_VL_ARCH_MAX))
+		vcpu->arch.sve_max_vl = SVE_VL_ARCH_MAX;
+
+	/*
+	 * Userspace can still customize the vector lengths by writing
+	 * KVM_REG_ARM64_SVE_VLS.  Allocation is deferred until
+	 * kvm_arm_vcpu_finalize(), which freezes the configuration.
+	 */
+	vcpu->arch.flags |= KVM_ARM64_GUEST_HAS_SVE;
+
+	return 0;
+}
+
 int kvm_arm_vcpu_finalize(struct kvm_vcpu *vcpu)
 {
 	if (likely(kvm_arm_vcpu_finalized(vcpu)))
 		return 0;
 
+	if (vcpu_has_sve(vcpu)) {
+		size_t size = vcpu_sve_state_size(vcpu);
+
+		if (!size)
+			return -EINVAL;
+
+		vcpu->arch.sve_state = kzalloc(size, GFP_KERNEL);
+		if (!vcpu->arch.sve_state)
+			return -ENOMEM;
+	}
+
 	vcpu->arch.flags |= KVM_ARM64_VCPU_FINALIZED;
 	return 0;
 }
@@ -113,12 +173,20 @@ int kvm_arm_vcpu_finalize(struct kvm_vcpu *vcpu)
  *
  * This function finds the right table above and sets the registers on
  * the virtual CPU struct to their architecturally defined reset
- * values.
+ * values, except for registers whose reset is deferred until
+ * kvm_arm_vcpu_finalize().
  */
 int kvm_reset_vcpu(struct kvm_vcpu *vcpu)
 {
+	int ret;
 	const struct kvm_regs *cpu_reset;
 
+	if (test_bit(KVM_ARM_VCPU_SVE, vcpu->arch.features)) {
+		ret = kvm_reset_sve(vcpu);
+		if (ret)
+			return ret;
+	}
+
 	switch (vcpu->arch.target) {
 	default:
 		if (test_bit(KVM_ARM_VCPU_EL1_32BIT, vcpu->arch.features)) {
-- 
2.1.4


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* [PATCH v5 24/26] KVM: arm64: Add a capabillity to advertise SVE support
  2019-02-18 19:52 ` Dave Martin
@ 2019-02-18 19:52   ` Dave Martin
  -1 siblings, 0 replies; 205+ messages in thread
From: Dave Martin @ 2019-02-18 19:52 UTC (permalink / raw)
  To: kvmarm
  Cc: Okamoto Takayuki, Christoffer Dall, Ard Biesheuvel, Marc Zyngier,
	Catalin Marinas, Will Deacon, Zhang Lei, linux-arm-kernel

To provide a uniform way to check for KVM SVE support amongst other
features, this patch adds a suitable capability KVM_CAP_ARM_SVE,
and reports it as present when SVE is available.

Signed-off-by: Dave Martin <Dave.Martin@arm.com>
---
 arch/arm64/kvm/reset.c   | 8 ++++++++
 include/uapi/linux/kvm.h | 1 +
 2 files changed, 9 insertions(+)

diff --git a/arch/arm64/kvm/reset.c b/arch/arm64/kvm/reset.c
index e67cd2e..f636b34 100644
--- a/arch/arm64/kvm/reset.c
+++ b/arch/arm64/kvm/reset.c
@@ -35,6 +35,7 @@
 #include <asm/kvm_asm.h>
 #include <asm/kvm_coproc.h>
 #include <asm/kvm_mmu.h>
+#include <asm/virt.h>
 
 /* Maximum phys_shift supported for any VM on this host */
 static u32 kvm_ipa_limit;
@@ -93,6 +94,9 @@ int kvm_arch_vm_ioctl_check_extension(struct kvm *kvm, long ext)
 	case KVM_CAP_ARM_VM_IPA_SIZE:
 		r = kvm_ipa_limit;
 		break;
+	case KVM_CAP_ARM_SVE:
+		r = system_supports_sve();
+		break;
 	default:
 		r = 0;
 	}
@@ -105,6 +109,10 @@ static int kvm_reset_sve(struct kvm_vcpu *vcpu)
 	if (!system_supports_sve())
 		return -EINVAL;
 
+	/* Verify that KVM startup enforced this when SVE was detected: */
+	if (WARN_ON(!has_vhe()))
+		return -EINVAL;
+
 	/* If resetting an already-configured vcpu, just zero the SVE regs: */
 	if (vcpu->arch.sve_state) {
 		size_t size = vcpu_sve_state_size(vcpu);
diff --git a/include/uapi/linux/kvm.h b/include/uapi/linux/kvm.h
index dc77a5a..4ea0d92 100644
--- a/include/uapi/linux/kvm.h
+++ b/include/uapi/linux/kvm.h
@@ -988,6 +988,7 @@ struct kvm_ppc_resize_hpt {
 #define KVM_CAP_ARM_VM_IPA_SIZE 165
 #define KVM_CAP_MANUAL_DIRTY_LOG_PROTECT 166
 #define KVM_CAP_HYPERV_CPUID 167
+#define KVM_CAP_ARM_SVE 168
 
 #ifdef KVM_CAP_IRQ_ROUTING
 
-- 
2.1.4

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

* [PATCH v5 24/26] KVM: arm64: Add a capabillity to advertise SVE support
@ 2019-02-18 19:52   ` Dave Martin
  0 siblings, 0 replies; 205+ messages in thread
From: Dave Martin @ 2019-02-18 19:52 UTC (permalink / raw)
  To: kvmarm
  Cc: Peter Maydell, Okamoto Takayuki, Christoffer Dall,
	Ard Biesheuvel, Marc Zyngier, Catalin Marinas, Will Deacon,
	Zhang Lei, Julien Grall, Alex Bennée, linux-arm-kernel

To provide a uniform way to check for KVM SVE support amongst other
features, this patch adds a suitable capability KVM_CAP_ARM_SVE,
and reports it as present when SVE is available.

Signed-off-by: Dave Martin <Dave.Martin@arm.com>
---
 arch/arm64/kvm/reset.c   | 8 ++++++++
 include/uapi/linux/kvm.h | 1 +
 2 files changed, 9 insertions(+)

diff --git a/arch/arm64/kvm/reset.c b/arch/arm64/kvm/reset.c
index e67cd2e..f636b34 100644
--- a/arch/arm64/kvm/reset.c
+++ b/arch/arm64/kvm/reset.c
@@ -35,6 +35,7 @@
 #include <asm/kvm_asm.h>
 #include <asm/kvm_coproc.h>
 #include <asm/kvm_mmu.h>
+#include <asm/virt.h>
 
 /* Maximum phys_shift supported for any VM on this host */
 static u32 kvm_ipa_limit;
@@ -93,6 +94,9 @@ int kvm_arch_vm_ioctl_check_extension(struct kvm *kvm, long ext)
 	case KVM_CAP_ARM_VM_IPA_SIZE:
 		r = kvm_ipa_limit;
 		break;
+	case KVM_CAP_ARM_SVE:
+		r = system_supports_sve();
+		break;
 	default:
 		r = 0;
 	}
@@ -105,6 +109,10 @@ static int kvm_reset_sve(struct kvm_vcpu *vcpu)
 	if (!system_supports_sve())
 		return -EINVAL;
 
+	/* Verify that KVM startup enforced this when SVE was detected: */
+	if (WARN_ON(!has_vhe()))
+		return -EINVAL;
+
 	/* If resetting an already-configured vcpu, just zero the SVE regs: */
 	if (vcpu->arch.sve_state) {
 		size_t size = vcpu_sve_state_size(vcpu);
diff --git a/include/uapi/linux/kvm.h b/include/uapi/linux/kvm.h
index dc77a5a..4ea0d92 100644
--- a/include/uapi/linux/kvm.h
+++ b/include/uapi/linux/kvm.h
@@ -988,6 +988,7 @@ struct kvm_ppc_resize_hpt {
 #define KVM_CAP_ARM_VM_IPA_SIZE 165
 #define KVM_CAP_MANUAL_DIRTY_LOG_PROTECT 166
 #define KVM_CAP_HYPERV_CPUID 167
+#define KVM_CAP_ARM_SVE 168
 
 #ifdef KVM_CAP_IRQ_ROUTING
 
-- 
2.1.4


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* [PATCH v5 25/26] KVM: Document errors for KVM_GET_ONE_REG and KVM_SET_ONE_REG
  2019-02-18 19:52 ` Dave Martin
@ 2019-02-18 19:52   ` Dave Martin
  -1 siblings, 0 replies; 205+ messages in thread
From: Dave Martin @ 2019-02-18 19:52 UTC (permalink / raw)
  To: kvmarm
  Cc: Okamoto Takayuki, Christoffer Dall, Ard Biesheuvel, Marc Zyngier,
	Catalin Marinas, Will Deacon, Zhang Lei, linux-arm-kernel

KVM_GET_ONE_REG and KVM_SET_ONE_REG return some error codes that
are not documented (but hopefully not surprising either).  To give
an indication of what these may mean, this patch adds brief
documentation.

Signed-off-by: Dave Martin <Dave.Martin@arm.com>
---
 Documentation/virtual/kvm/api.txt | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/Documentation/virtual/kvm/api.txt b/Documentation/virtual/kvm/api.txt
index 097b8ba..cb15f2a 100644
--- a/Documentation/virtual/kvm/api.txt
+++ b/Documentation/virtual/kvm/api.txt
@@ -1854,6 +1854,9 @@ Architectures: all
 Type: vcpu ioctl
 Parameters: struct kvm_one_reg (in)
 Returns: 0 on success, negative value on failure
+Errors:
+  ENOENT:   no such register
+  EINVAL:   other errors, such as bad size encoding for a known register
 
 struct kvm_one_reg {
        __u64 id;
@@ -2175,6 +2178,9 @@ Architectures: all
 Type: vcpu ioctl
 Parameters: struct kvm_one_reg (in and out)
 Returns: 0 on success, negative value on failure
+Errors:
+  ENOENT:   no such register
+  EINVAL:   other errors, such as bad size encoding for a known register
 
 This ioctl allows to receive the value of a single register implemented
 in a vcpu. The register to read is indicated by the "id" field of the
-- 
2.1.4

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

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

* [PATCH v5 25/26] KVM: Document errors for KVM_GET_ONE_REG and KVM_SET_ONE_REG
@ 2019-02-18 19:52   ` Dave Martin
  0 siblings, 0 replies; 205+ messages in thread
From: Dave Martin @ 2019-02-18 19:52 UTC (permalink / raw)
  To: kvmarm
  Cc: Peter Maydell, Okamoto Takayuki, Christoffer Dall,
	Ard Biesheuvel, Marc Zyngier, Catalin Marinas, Will Deacon,
	Zhang Lei, Julien Grall, Alex Bennée, linux-arm-kernel

KVM_GET_ONE_REG and KVM_SET_ONE_REG return some error codes that
are not documented (but hopefully not surprising either).  To give
an indication of what these may mean, this patch adds brief
documentation.

Signed-off-by: Dave Martin <Dave.Martin@arm.com>
---
 Documentation/virtual/kvm/api.txt | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/Documentation/virtual/kvm/api.txt b/Documentation/virtual/kvm/api.txt
index 097b8ba..cb15f2a 100644
--- a/Documentation/virtual/kvm/api.txt
+++ b/Documentation/virtual/kvm/api.txt
@@ -1854,6 +1854,9 @@ Architectures: all
 Type: vcpu ioctl
 Parameters: struct kvm_one_reg (in)
 Returns: 0 on success, negative value on failure
+Errors:
+  ENOENT:   no such register
+  EINVAL:   other errors, such as bad size encoding for a known register
 
 struct kvm_one_reg {
        __u64 id;
@@ -2175,6 +2178,9 @@ Architectures: all
 Type: vcpu ioctl
 Parameters: struct kvm_one_reg (in and out)
 Returns: 0 on success, negative value on failure
+Errors:
+  ENOENT:   no such register
+  EINVAL:   other errors, such as bad size encoding for a known register
 
 This ioctl allows to receive the value of a single register implemented
 in a vcpu. The register to read is indicated by the "id" field of the
-- 
2.1.4


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* [PATCH v5 26/26] KVM: arm64/sve: Document KVM API extensions for SVE
  2019-02-18 19:52 ` Dave Martin
@ 2019-02-18 19:52   ` Dave Martin
  -1 siblings, 0 replies; 205+ messages in thread
From: Dave Martin @ 2019-02-18 19:52 UTC (permalink / raw)
  To: kvmarm
  Cc: Okamoto Takayuki, Christoffer Dall, Ard Biesheuvel, Marc Zyngier,
	Catalin Marinas, Will Deacon, Zhang Lei, linux-arm-kernel

This patch adds sections to the KVM API documentation describing
the extensions for supporting the Scalable Vector Extension (SVE)
in guests.

Signed-off-by: Dave Martin <Dave.Martin@arm.com>

---

Changes since v4:

 * Add note about which SVE register slices are visible, and the
   behaviour of non-visible slices.
---
 Documentation/virtual/kvm/api.txt | 69 +++++++++++++++++++++++++++++++++++++--
 1 file changed, 66 insertions(+), 3 deletions(-)

diff --git a/Documentation/virtual/kvm/api.txt b/Documentation/virtual/kvm/api.txt
index cb15f2a..6a6e029 100644
--- a/Documentation/virtual/kvm/api.txt
+++ b/Documentation/virtual/kvm/api.txt
@@ -1856,6 +1856,7 @@ Parameters: struct kvm_one_reg (in)
 Returns: 0 on success, negative value on failure
 Errors:
   ENOENT:   no such register
+  EPERM:    register access forbidden for architecture-dependent reasons
   EINVAL:   other errors, such as bad size encoding for a known register
 
 struct kvm_one_reg {
@@ -2110,13 +2111,20 @@ Specifically:
   0x6030 0000 0010 004c SPSR_UND    64  spsr[KVM_SPSR_UND]
   0x6030 0000 0010 004e SPSR_IRQ    64  spsr[KVM_SPSR_IRQ]
   0x6060 0000 0010 0050 SPSR_FIQ    64  spsr[KVM_SPSR_FIQ]
-  0x6040 0000 0010 0054 V0         128  fp_regs.vregs[0]
-  0x6040 0000 0010 0058 V1         128  fp_regs.vregs[1]
+  0x6040 0000 0010 0054 V0         128  fp_regs.vregs[0]    (*)
+  0x6040 0000 0010 0058 V1         128  fp_regs.vregs[1]    (*)
     ...
-  0x6040 0000 0010 00d0 V31        128  fp_regs.vregs[31]
+  0x6040 0000 0010 00d0 V31        128  fp_regs.vregs[31]   (*)
   0x6020 0000 0010 00d4 FPSR        32  fp_regs.fpsr
   0x6020 0000 0010 00d5 FPCR        32  fp_regs.fpcr
 
+(*) These encodings are not accepted for SVE-enabled vcpus.  See
+    KVM_ARM_VCPU_INIT.
+
+    The equivalent register content can be accessed via bits [127:0] of
+    the corresponding SVE Zn registers instead for vcpus that have SVE
+    enabled (see below).
+
 arm64 CCSIDR registers are demultiplexed by CSSELR value:
   0x6020 0000 0011 00 <csselr:8>
 
@@ -2126,6 +2134,58 @@ arm64 system registers have the following id bit patterns:
 arm64 firmware pseudo-registers have the following bit pattern:
   0x6030 0000 0014 <regno:16>
 
+arm64 SVE registers have the following bit patterns:
+  0x6080 0000 0015 00 <n:5> <slice:5>   Zn bits[2048*slice + 2047 : 2048*slice]
+  0x6050 0000 0015 04 <n:4> <slice:5>   Pn bits[256*slice + 255 : 256*slice]
+  0x6050 0000 0015 060 <slice:5>        FFR bits[256*slice + 255 : 256*slice]
+  0x6060 0000 0015 ffff                 KVM_REG_ARM64_SVE_VLS pseudo-register
+
+Access to slices beyond the maximum vector length configured for the
+vcpu (i.e., where 16 * slice >= max_vq (**)) will fail with ENOENT.
+
+These registers are only accessible on vcpus for which SVE is enabled.
+See KVM_ARM_VCPU_INIT for details.
+
+KVM_REG_ARM64_SVE_VLS is a pseudo-register that allows the set of vector
+lengths supported by the vcpu to be discovered and configured by
+userspace.  When transferred to or from user memory via KVM_GET_ONE_REG
+or KVM_SET_ONE_REG, the value of this register is of type __u64[8], and
+encodes the set of vector lengths as follows:
+
+__u64 vector_lengths[8];
+
+if (vq >= SVE_VQ_MIN && vq <= SVE_VQ_MAX &&
+    ((vector_lengths[(vq - 1) / 64] >> ((vq - 1) % 64)) & 1))
+	/* Vector length vq * 16 bytes supported */
+else
+	/* Vector length vq * 16 bytes not supported */
+
+(**) The maximum value vq for which the above condition is true is
+max_vq.  This is the maximum vector length available to the guest on
+this vcpu, and determines which register slices are visible through
+this ioctl interface.
+
+(See Documentation/arm64/sve.txt for an explanation of the "vq"
+nomenclature.)
+
+KVM_REG_ARM64_SVE_VLS is only accessible after KVM_ARM_VCPU_INIT.
+KVM_ARM_VCPU_INIT initialises it to the best set of vector lengths that
+the host supports.
+
+Userspace may subsequently modify it if desired until the vcpu
+configuration is finalized by accessing the guest's SVE registers, or
+enumerating them via KVM_GET_REG_LIST, or setting the cpu running via
+KVM_RUN.
+
+Apart from simply removing all vector lengths from the host set that
+exceed some value, support for arbitrarily chosen sets of vector lengths
+is hardware-dependent and may not be available.  Attempting to configure
+an invalid set of vector lengths via KVM_SET_ONE_REG will fail with
+EINVAL.
+
+After the vcpu's configuration is finalized, further attempts to write
+this register will fail with EPERM.
+
 
 MIPS registers are mapped using the lower 32 bits.  The upper 16 of that is
 the register group type:
@@ -2180,6 +2240,7 @@ Parameters: struct kvm_one_reg (in and out)
 Returns: 0 on success, negative value on failure
 Errors:
   ENOENT:   no such register
+  EPERM:    register access forbidden for architecture-dependent reasons
   EINVAL:   other errors, such as bad size encoding for a known register
 
 This ioctl allows to receive the value of a single register implemented
@@ -2672,6 +2733,8 @@ Possible features:
 	  Depends on KVM_CAP_ARM_PSCI_0_2.
 	- KVM_ARM_VCPU_PMU_V3: Emulate PMUv3 for the CPU.
 	  Depends on KVM_CAP_ARM_PMU_V3.
+	- KVM_ARM_VCPU_SVE: Enables SVE for the CPU (arm64 only).
+	  Depends on KVM_CAP_ARM_SVE.
 
 
 4.83 KVM_ARM_PREFERRED_TARGET
-- 
2.1.4

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

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

* [PATCH v5 26/26] KVM: arm64/sve: Document KVM API extensions for SVE
@ 2019-02-18 19:52   ` Dave Martin
  0 siblings, 0 replies; 205+ messages in thread
From: Dave Martin @ 2019-02-18 19:52 UTC (permalink / raw)
  To: kvmarm
  Cc: Peter Maydell, Okamoto Takayuki, Christoffer Dall,
	Ard Biesheuvel, Marc Zyngier, Catalin Marinas, Will Deacon,
	Zhang Lei, Julien Grall, Alex Bennée, linux-arm-kernel

This patch adds sections to the KVM API documentation describing
the extensions for supporting the Scalable Vector Extension (SVE)
in guests.

Signed-off-by: Dave Martin <Dave.Martin@arm.com>

---

Changes since v4:

 * Add note about which SVE register slices are visible, and the
   behaviour of non-visible slices.
---
 Documentation/virtual/kvm/api.txt | 69 +++++++++++++++++++++++++++++++++++++--
 1 file changed, 66 insertions(+), 3 deletions(-)

diff --git a/Documentation/virtual/kvm/api.txt b/Documentation/virtual/kvm/api.txt
index cb15f2a..6a6e029 100644
--- a/Documentation/virtual/kvm/api.txt
+++ b/Documentation/virtual/kvm/api.txt
@@ -1856,6 +1856,7 @@ Parameters: struct kvm_one_reg (in)
 Returns: 0 on success, negative value on failure
 Errors:
   ENOENT:   no such register
+  EPERM:    register access forbidden for architecture-dependent reasons
   EINVAL:   other errors, such as bad size encoding for a known register
 
 struct kvm_one_reg {
@@ -2110,13 +2111,20 @@ Specifically:
   0x6030 0000 0010 004c SPSR_UND    64  spsr[KVM_SPSR_UND]
   0x6030 0000 0010 004e SPSR_IRQ    64  spsr[KVM_SPSR_IRQ]
   0x6060 0000 0010 0050 SPSR_FIQ    64  spsr[KVM_SPSR_FIQ]
-  0x6040 0000 0010 0054 V0         128  fp_regs.vregs[0]
-  0x6040 0000 0010 0058 V1         128  fp_regs.vregs[1]
+  0x6040 0000 0010 0054 V0         128  fp_regs.vregs[0]    (*)
+  0x6040 0000 0010 0058 V1         128  fp_regs.vregs[1]    (*)
     ...
-  0x6040 0000 0010 00d0 V31        128  fp_regs.vregs[31]
+  0x6040 0000 0010 00d0 V31        128  fp_regs.vregs[31]   (*)
   0x6020 0000 0010 00d4 FPSR        32  fp_regs.fpsr
   0x6020 0000 0010 00d5 FPCR        32  fp_regs.fpcr
 
+(*) These encodings are not accepted for SVE-enabled vcpus.  See
+    KVM_ARM_VCPU_INIT.
+
+    The equivalent register content can be accessed via bits [127:0] of
+    the corresponding SVE Zn registers instead for vcpus that have SVE
+    enabled (see below).
+
 arm64 CCSIDR registers are demultiplexed by CSSELR value:
   0x6020 0000 0011 00 <csselr:8>
 
@@ -2126,6 +2134,58 @@ arm64 system registers have the following id bit patterns:
 arm64 firmware pseudo-registers have the following bit pattern:
   0x6030 0000 0014 <regno:16>
 
+arm64 SVE registers have the following bit patterns:
+  0x6080 0000 0015 00 <n:5> <slice:5>   Zn bits[2048*slice + 2047 : 2048*slice]
+  0x6050 0000 0015 04 <n:4> <slice:5>   Pn bits[256*slice + 255 : 256*slice]
+  0x6050 0000 0015 060 <slice:5>        FFR bits[256*slice + 255 : 256*slice]
+  0x6060 0000 0015 ffff                 KVM_REG_ARM64_SVE_VLS pseudo-register
+
+Access to slices beyond the maximum vector length configured for the
+vcpu (i.e., where 16 * slice >= max_vq (**)) will fail with ENOENT.
+
+These registers are only accessible on vcpus for which SVE is enabled.
+See KVM_ARM_VCPU_INIT for details.
+
+KVM_REG_ARM64_SVE_VLS is a pseudo-register that allows the set of vector
+lengths supported by the vcpu to be discovered and configured by
+userspace.  When transferred to or from user memory via KVM_GET_ONE_REG
+or KVM_SET_ONE_REG, the value of this register is of type __u64[8], and
+encodes the set of vector lengths as follows:
+
+__u64 vector_lengths[8];
+
+if (vq >= SVE_VQ_MIN && vq <= SVE_VQ_MAX &&
+    ((vector_lengths[(vq - 1) / 64] >> ((vq - 1) % 64)) & 1))
+	/* Vector length vq * 16 bytes supported */
+else
+	/* Vector length vq * 16 bytes not supported */
+
+(**) The maximum value vq for which the above condition is true is
+max_vq.  This is the maximum vector length available to the guest on
+this vcpu, and determines which register slices are visible through
+this ioctl interface.
+
+(See Documentation/arm64/sve.txt for an explanation of the "vq"
+nomenclature.)
+
+KVM_REG_ARM64_SVE_VLS is only accessible after KVM_ARM_VCPU_INIT.
+KVM_ARM_VCPU_INIT initialises it to the best set of vector lengths that
+the host supports.
+
+Userspace may subsequently modify it if desired until the vcpu
+configuration is finalized by accessing the guest's SVE registers, or
+enumerating them via KVM_GET_REG_LIST, or setting the cpu running via
+KVM_RUN.
+
+Apart from simply removing all vector lengths from the host set that
+exceed some value, support for arbitrarily chosen sets of vector lengths
+is hardware-dependent and may not be available.  Attempting to configure
+an invalid set of vector lengths via KVM_SET_ONE_REG will fail with
+EINVAL.
+
+After the vcpu's configuration is finalized, further attempts to write
+this register will fail with EPERM.
+
 
 MIPS registers are mapped using the lower 32 bits.  The upper 16 of that is
 the register group type:
@@ -2180,6 +2240,7 @@ Parameters: struct kvm_one_reg (in and out)
 Returns: 0 on success, negative value on failure
 Errors:
   ENOENT:   no such register
+  EPERM:    register access forbidden for architecture-dependent reasons
   EINVAL:   other errors, such as bad size encoding for a known register
 
 This ioctl allows to receive the value of a single register implemented
@@ -2672,6 +2733,8 @@ Possible features:
 	  Depends on KVM_CAP_ARM_PSCI_0_2.
 	- KVM_ARM_VCPU_PMU_V3: Emulate PMUv3 for the CPU.
 	  Depends on KVM_CAP_ARM_PMU_V3.
+	- KVM_ARM_VCPU_SVE: Enables SVE for the CPU (arm64 only).
+	  Depends on KVM_CAP_ARM_SVE.
 
 
 4.83 KVM_ARM_PREFERRED_TARGET
-- 
2.1.4


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* Re: [PATCH v5 06/26] arm64/sve: Check SVE virtualisability
  2019-02-18 19:52   ` Dave Martin
@ 2019-02-20 11:12     ` Julien Thierry
  -1 siblings, 0 replies; 205+ messages in thread
From: Julien Thierry @ 2019-02-20 11:12 UTC (permalink / raw)
  To: Dave Martin, kvmarm
  Cc: Okamoto Takayuki, Christoffer Dall, Ard Biesheuvel, Marc Zyngier,
	Catalin Marinas, Will Deacon, Zhang Lei, linux-arm-kernel

Hi Dave,

On 18/02/2019 19:52, Dave Martin wrote:
> Due to the way the effective SVE vector length is controlled and
> trapped at different exception levels, certain mismatches in the
> sets of vector lengths supported by different physical CPUs in the
> system may prevent straightforward virtualisation of SVE at parity
> with the host.
> 
> This patch analyses the extent to which SVE can be virtualised
> safely without interfering with migration of vcpus between physical
> CPUs, and rejects late secondary CPUs that would erode the
> situation further.
> 
> It is left up to KVM to decide what to do with this information.
> 
> Signed-off-by: Dave Martin <Dave.Martin@arm.com>
> ---
>  arch/arm64/include/asm/fpsimd.h |  1 +
>  arch/arm64/kernel/cpufeature.c  |  2 +-
>  arch/arm64/kernel/fpsimd.c      | 86 ++++++++++++++++++++++++++++++++++-------
>  3 files changed, 73 insertions(+), 16 deletions(-)
> 
> diff --git a/arch/arm64/include/asm/fpsimd.h b/arch/arm64/include/asm/fpsimd.h
> index dd1ad39..964adc9 100644
> --- a/arch/arm64/include/asm/fpsimd.h
> +++ b/arch/arm64/include/asm/fpsimd.h
> @@ -87,6 +87,7 @@ extern void sve_kernel_enable(const struct arm64_cpu_capabilities *__unused);
>  extern u64 read_zcr_features(void);
>  
>  extern int __ro_after_init sve_max_vl;
> +extern int __ro_after_init sve_max_virtualisable_vl;
>  
>  #ifdef CONFIG_ARM64_SVE
>  
> diff --git a/arch/arm64/kernel/cpufeature.c b/arch/arm64/kernel/cpufeature.c
> index f6d84e2..5eaacb4 100644
> --- a/arch/arm64/kernel/cpufeature.c
> +++ b/arch/arm64/kernel/cpufeature.c
> @@ -1825,7 +1825,7 @@ static void verify_sve_features(void)
>  	unsigned int len = zcr & ZCR_ELx_LEN_MASK;
>  
>  	if (len < safe_len || sve_verify_vq_map()) {
> -		pr_crit("CPU%d: SVE: required vector length(s) missing\n",
> +		pr_crit("CPU%d: SVE: vector length support mismatch\n",
>  			smp_processor_id());
>  		cpu_die_early();
>  	}
> diff --git a/arch/arm64/kernel/fpsimd.c b/arch/arm64/kernel/fpsimd.c
> index 62c37f0..64729e2 100644
> --- a/arch/arm64/kernel/fpsimd.c
> +++ b/arch/arm64/kernel/fpsimd.c
> @@ -18,6 +18,7 @@
>   */
>  
>  #include <linux/bitmap.h>
> +#include <linux/bitops.h>
>  #include <linux/bottom_half.h>
>  #include <linux/bug.h>
>  #include <linux/cache.h>
> @@ -48,6 +49,7 @@
>  #include <asm/sigcontext.h>
>  #include <asm/sysreg.h>
>  #include <asm/traps.h>
> +#include <asm/virt.h>
>  
>  #define FPEXC_IOF	(1 << 0)
>  #define FPEXC_DZF	(1 << 1)
> @@ -130,14 +132,18 @@ static int sve_default_vl = -1;
>  
>  /* Maximum supported vector length across all CPUs (initially poisoned) */
>  int __ro_after_init sve_max_vl = SVE_VL_MIN;
> +int __ro_after_init sve_max_virtualisable_vl = SVE_VL_MIN;
>  /* Set of available vector lengths, as vq_to_bit(vq): */
>  static __ro_after_init DECLARE_BITMAP(sve_vq_map, SVE_VQ_MAX);
> +/* Set of vector lengths present on at least one cpu: */
> +static __ro_after_init DECLARE_BITMAP(sve_vq_partial_map, SVE_VQ_MAX);
>  static void __percpu *efi_sve_state;
>  
>  #else /* ! CONFIG_ARM64_SVE */
>  
>  /* Dummy declaration for code that will be optimised out: */
>  extern __ro_after_init DECLARE_BITMAP(sve_vq_map, SVE_VQ_MAX);
> +extern __ro_after_init DECLARE_BITMAP(sve_vq_partial_map, SVE_VQ_MAX);
>  extern void __percpu *efi_sve_state;
>  
>  #endif /* ! CONFIG_ARM64_SVE */
> @@ -623,12 +629,6 @@ int sve_get_current_vl(void)
>  	return sve_prctl_status(0);
>  }
>  
> -/*
> - * Bitmap for temporary storage of the per-CPU set of supported vector lengths
> - * during secondary boot.
> - */
> -static DECLARE_BITMAP(sve_secondary_vq_map, SVE_VQ_MAX);
> -
>  static void sve_probe_vqs(DECLARE_BITMAP(map, SVE_VQ_MAX))
>  {
>  	unsigned int vq, vl;
> @@ -650,6 +650,7 @@ static void sve_probe_vqs(DECLARE_BITMAP(map, SVE_VQ_MAX))
>  void __init sve_init_vq_map(void)
>  {
>  	sve_probe_vqs(sve_vq_map);
> +	bitmap_copy(sve_vq_partial_map, sve_vq_map, SVE_VQ_MAX);
>  }
>  
>  /*
> @@ -658,25 +659,58 @@ void __init sve_init_vq_map(void)
>   */
>  void sve_update_vq_map(void)
>  {
> -	sve_probe_vqs(sve_secondary_vq_map);
> -	bitmap_and(sve_vq_map, sve_vq_map, sve_secondary_vq_map, SVE_VQ_MAX);
> +	DECLARE_BITMAP(tmp_map, SVE_VQ_MAX);
> +
> +	sve_probe_vqs(tmp_map);
> +	bitmap_and(sve_vq_map, sve_vq_map, tmp_map, SVE_VQ_MAX);
> +	bitmap_or(sve_vq_partial_map, sve_vq_partial_map, tmp_map, SVE_VQ_MAX);
>  }
>  
>  /* Check whether the current CPU supports all VQs in the committed set */
>  int sve_verify_vq_map(void)
>  {
> -	int ret = 0;
> +	DECLARE_BITMAP(tmp_map, SVE_VQ_MAX);
> +	unsigned long b;
>  
> -	sve_probe_vqs(sve_secondary_vq_map);
> -	bitmap_andnot(sve_secondary_vq_map, sve_vq_map, sve_secondary_vq_map,
> -		      SVE_VQ_MAX);
> -	if (!bitmap_empty(sve_secondary_vq_map, SVE_VQ_MAX)) {
> +	sve_probe_vqs(tmp_map);
> +
> +	bitmap_complement(tmp_map, tmp_map, SVE_VQ_MAX);
> +	if (bitmap_intersects(tmp_map, sve_vq_map, SVE_VQ_MAX)) {
>  		pr_warn("SVE: cpu%d: Required vector length(s) missing\n",
>  			smp_processor_id());
> -		ret = -EINVAL;
> +		return -EINVAL;
>  	}
>  
> -	return ret;
> +	if (!IS_ENABLED(CONFIG_KVM) || !is_hyp_mode_available())
> +		return 0;
> +
> +	/*
> +	 * For KVM, it is necessary to ensure that this CPU doesn't
> +	 * support any vector length that guests may have probed as
> +	 * unsupported.
> +	 */
> +
> +	/* Recover the set of supported VQs: */
> +	bitmap_complement(tmp_map, tmp_map, SVE_VQ_MAX);
> +	/* Find VQs supported that are not globally supported: */
> +	bitmap_andnot(tmp_map, tmp_map, sve_vq_map, SVE_VQ_MAX);
> +
> +	/* Find the lowest such VQ, if any: */
> +	b = find_last_bit(tmp_map, SVE_VQ_MAX);
> +	if (b >= SVE_VQ_MAX)
> +		return 0; /* no mismatches */
> +
> +	/*
> +	 * Mismatches above sve_max_virtualisable_vl are fine, since
> +	 * no guest is allowed to configure ZCR_EL2.LEN to exceed this:
> +	 */
> +	if (sve_vl_from_vq(bit_to_vq(b)) <= sve_max_virtualisable_vl) {
> +		pr_warn("SVE: cpu%d: Unsupported vector length(s) present\n",

Nit: might be good to specify that the vector length is unsupported for
virtualisation.

Also, since KVM is the one deciding what to do with the information,
should we have a warning here? But I can understand that knowing which
CPUs are introducing unsupported vector length, maybe using pr_devel()
instead of pr_warn()


In any case, the logic looks good to me:

Reviewed-by: Julien Thierry <julien.thierry@arm.com>

Cheers,

-- 
Julien Thierry

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

* Re: [PATCH v5 06/26] arm64/sve: Check SVE virtualisability
@ 2019-02-20 11:12     ` Julien Thierry
  0 siblings, 0 replies; 205+ messages in thread
From: Julien Thierry @ 2019-02-20 11:12 UTC (permalink / raw)
  To: Dave Martin, kvmarm
  Cc: Okamoto Takayuki, Christoffer Dall, Ard Biesheuvel, Marc Zyngier,
	Catalin Marinas, Will Deacon, Zhang Lei, linux-arm-kernel

Hi Dave,

On 18/02/2019 19:52, Dave Martin wrote:
> Due to the way the effective SVE vector length is controlled and
> trapped at different exception levels, certain mismatches in the
> sets of vector lengths supported by different physical CPUs in the
> system may prevent straightforward virtualisation of SVE at parity
> with the host.
> 
> This patch analyses the extent to which SVE can be virtualised
> safely without interfering with migration of vcpus between physical
> CPUs, and rejects late secondary CPUs that would erode the
> situation further.
> 
> It is left up to KVM to decide what to do with this information.
> 
> Signed-off-by: Dave Martin <Dave.Martin@arm.com>
> ---
>  arch/arm64/include/asm/fpsimd.h |  1 +
>  arch/arm64/kernel/cpufeature.c  |  2 +-
>  arch/arm64/kernel/fpsimd.c      | 86 ++++++++++++++++++++++++++++++++++-------
>  3 files changed, 73 insertions(+), 16 deletions(-)
> 
> diff --git a/arch/arm64/include/asm/fpsimd.h b/arch/arm64/include/asm/fpsimd.h
> index dd1ad39..964adc9 100644
> --- a/arch/arm64/include/asm/fpsimd.h
> +++ b/arch/arm64/include/asm/fpsimd.h
> @@ -87,6 +87,7 @@ extern void sve_kernel_enable(const struct arm64_cpu_capabilities *__unused);
>  extern u64 read_zcr_features(void);
>  
>  extern int __ro_after_init sve_max_vl;
> +extern int __ro_after_init sve_max_virtualisable_vl;
>  
>  #ifdef CONFIG_ARM64_SVE
>  
> diff --git a/arch/arm64/kernel/cpufeature.c b/arch/arm64/kernel/cpufeature.c
> index f6d84e2..5eaacb4 100644
> --- a/arch/arm64/kernel/cpufeature.c
> +++ b/arch/arm64/kernel/cpufeature.c
> @@ -1825,7 +1825,7 @@ static void verify_sve_features(void)
>  	unsigned int len = zcr & ZCR_ELx_LEN_MASK;
>  
>  	if (len < safe_len || sve_verify_vq_map()) {
> -		pr_crit("CPU%d: SVE: required vector length(s) missing\n",
> +		pr_crit("CPU%d: SVE: vector length support mismatch\n",
>  			smp_processor_id());
>  		cpu_die_early();
>  	}
> diff --git a/arch/arm64/kernel/fpsimd.c b/arch/arm64/kernel/fpsimd.c
> index 62c37f0..64729e2 100644
> --- a/arch/arm64/kernel/fpsimd.c
> +++ b/arch/arm64/kernel/fpsimd.c
> @@ -18,6 +18,7 @@
>   */
>  
>  #include <linux/bitmap.h>
> +#include <linux/bitops.h>
>  #include <linux/bottom_half.h>
>  #include <linux/bug.h>
>  #include <linux/cache.h>
> @@ -48,6 +49,7 @@
>  #include <asm/sigcontext.h>
>  #include <asm/sysreg.h>
>  #include <asm/traps.h>
> +#include <asm/virt.h>
>  
>  #define FPEXC_IOF	(1 << 0)
>  #define FPEXC_DZF	(1 << 1)
> @@ -130,14 +132,18 @@ static int sve_default_vl = -1;
>  
>  /* Maximum supported vector length across all CPUs (initially poisoned) */
>  int __ro_after_init sve_max_vl = SVE_VL_MIN;
> +int __ro_after_init sve_max_virtualisable_vl = SVE_VL_MIN;
>  /* Set of available vector lengths, as vq_to_bit(vq): */
>  static __ro_after_init DECLARE_BITMAP(sve_vq_map, SVE_VQ_MAX);
> +/* Set of vector lengths present on at least one cpu: */
> +static __ro_after_init DECLARE_BITMAP(sve_vq_partial_map, SVE_VQ_MAX);
>  static void __percpu *efi_sve_state;
>  
>  #else /* ! CONFIG_ARM64_SVE */
>  
>  /* Dummy declaration for code that will be optimised out: */
>  extern __ro_after_init DECLARE_BITMAP(sve_vq_map, SVE_VQ_MAX);
> +extern __ro_after_init DECLARE_BITMAP(sve_vq_partial_map, SVE_VQ_MAX);
>  extern void __percpu *efi_sve_state;
>  
>  #endif /* ! CONFIG_ARM64_SVE */
> @@ -623,12 +629,6 @@ int sve_get_current_vl(void)
>  	return sve_prctl_status(0);
>  }
>  
> -/*
> - * Bitmap for temporary storage of the per-CPU set of supported vector lengths
> - * during secondary boot.
> - */
> -static DECLARE_BITMAP(sve_secondary_vq_map, SVE_VQ_MAX);
> -
>  static void sve_probe_vqs(DECLARE_BITMAP(map, SVE_VQ_MAX))
>  {
>  	unsigned int vq, vl;
> @@ -650,6 +650,7 @@ static void sve_probe_vqs(DECLARE_BITMAP(map, SVE_VQ_MAX))
>  void __init sve_init_vq_map(void)
>  {
>  	sve_probe_vqs(sve_vq_map);
> +	bitmap_copy(sve_vq_partial_map, sve_vq_map, SVE_VQ_MAX);
>  }
>  
>  /*
> @@ -658,25 +659,58 @@ void __init sve_init_vq_map(void)
>   */
>  void sve_update_vq_map(void)
>  {
> -	sve_probe_vqs(sve_secondary_vq_map);
> -	bitmap_and(sve_vq_map, sve_vq_map, sve_secondary_vq_map, SVE_VQ_MAX);
> +	DECLARE_BITMAP(tmp_map, SVE_VQ_MAX);
> +
> +	sve_probe_vqs(tmp_map);
> +	bitmap_and(sve_vq_map, sve_vq_map, tmp_map, SVE_VQ_MAX);
> +	bitmap_or(sve_vq_partial_map, sve_vq_partial_map, tmp_map, SVE_VQ_MAX);
>  }
>  
>  /* Check whether the current CPU supports all VQs in the committed set */
>  int sve_verify_vq_map(void)
>  {
> -	int ret = 0;
> +	DECLARE_BITMAP(tmp_map, SVE_VQ_MAX);
> +	unsigned long b;
>  
> -	sve_probe_vqs(sve_secondary_vq_map);
> -	bitmap_andnot(sve_secondary_vq_map, sve_vq_map, sve_secondary_vq_map,
> -		      SVE_VQ_MAX);
> -	if (!bitmap_empty(sve_secondary_vq_map, SVE_VQ_MAX)) {
> +	sve_probe_vqs(tmp_map);
> +
> +	bitmap_complement(tmp_map, tmp_map, SVE_VQ_MAX);
> +	if (bitmap_intersects(tmp_map, sve_vq_map, SVE_VQ_MAX)) {
>  		pr_warn("SVE: cpu%d: Required vector length(s) missing\n",
>  			smp_processor_id());
> -		ret = -EINVAL;
> +		return -EINVAL;
>  	}
>  
> -	return ret;
> +	if (!IS_ENABLED(CONFIG_KVM) || !is_hyp_mode_available())
> +		return 0;
> +
> +	/*
> +	 * For KVM, it is necessary to ensure that this CPU doesn't
> +	 * support any vector length that guests may have probed as
> +	 * unsupported.
> +	 */
> +
> +	/* Recover the set of supported VQs: */
> +	bitmap_complement(tmp_map, tmp_map, SVE_VQ_MAX);
> +	/* Find VQs supported that are not globally supported: */
> +	bitmap_andnot(tmp_map, tmp_map, sve_vq_map, SVE_VQ_MAX);
> +
> +	/* Find the lowest such VQ, if any: */
> +	b = find_last_bit(tmp_map, SVE_VQ_MAX);
> +	if (b >= SVE_VQ_MAX)
> +		return 0; /* no mismatches */
> +
> +	/*
> +	 * Mismatches above sve_max_virtualisable_vl are fine, since
> +	 * no guest is allowed to configure ZCR_EL2.LEN to exceed this:
> +	 */
> +	if (sve_vl_from_vq(bit_to_vq(b)) <= sve_max_virtualisable_vl) {
> +		pr_warn("SVE: cpu%d: Unsupported vector length(s) present\n",

Nit: might be good to specify that the vector length is unsupported for
virtualisation.

Also, since KVM is the one deciding what to do with the information,
should we have a warning here? But I can understand that knowing which
CPUs are introducing unsupported vector length, maybe using pr_devel()
instead of pr_warn()


In any case, the logic looks good to me:

Reviewed-by: Julien Thierry <julien.thierry@arm.com>

Cheers,

-- 
Julien Thierry

_______________________________________________
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] 205+ messages in thread

* Re: [PATCH v5 07/26] arm64/sve: Clarify role of the VQ map maintenance functions
  2019-02-18 19:52   ` Dave Martin
@ 2019-02-20 11:43     ` Julien Thierry
  -1 siblings, 0 replies; 205+ messages in thread
From: Julien Thierry @ 2019-02-20 11:43 UTC (permalink / raw)
  To: Dave Martin, kvmarm
  Cc: Okamoto Takayuki, Christoffer Dall, Ard Biesheuvel, Marc Zyngier,
	Catalin Marinas, Will Deacon, Zhang Lei, linux-arm-kernel



On 18/02/2019 19:52, Dave Martin wrote:
> The roles of sve_init_vq_map(), sve_update_vq_map() and
> sve_verify_vq_map() are highly non-obvious to anyone who has not dug
> through cpufeatures.c in detail.
> 
> Since the way these functions interact with each other is more
> important here than a full understanding of the cpufeatures code, this
> patch adds comments to make the functions' roles clearer.
> 
> No functional change.
> 
> Signed-off-by: Dave Martin <Dave.Martin@arm.com>
> ---
>  arch/arm64/kernel/fpsimd.c | 10 +++++++++-
>  1 file changed, 9 insertions(+), 1 deletion(-)
> 
> diff --git a/arch/arm64/kernel/fpsimd.c b/arch/arm64/kernel/fpsimd.c
> index 64729e2..92c2331 100644
> --- a/arch/arm64/kernel/fpsimd.c
> +++ b/arch/arm64/kernel/fpsimd.c
> @@ -647,6 +647,10 @@ static void sve_probe_vqs(DECLARE_BITMAP(map, SVE_VQ_MAX))
>  	}
>  }
>  
> +/*
> + * Initialise the set of known supported VQs for the boot CPU.
> + * This is called during kernel boot, before secondary CPUs are brought up.
> + */
>  void __init sve_init_vq_map(void)
>  {
>  	sve_probe_vqs(sve_vq_map);
> @@ -656,6 +660,7 @@ void __init sve_init_vq_map(void)
>  /*
>   * If we haven't committed to the set of supported VQs yet, filter out
>   * those not supported by the current CPU.
> + * This function is called during the bring-up of early secondary CPUs only.
>   */
>  void sve_update_vq_map(void)
>  {
> @@ -666,7 +671,10 @@ void sve_update_vq_map(void)
>  	bitmap_or(sve_vq_partial_map, sve_vq_partial_map, tmp_map, SVE_VQ_MAX);
>  }
>  
> -/* Check whether the current CPU supports all VQs in the committed set */
> +/*
> + * Check whether the current CPU supports all VQs in the committed set.
> + * This function is called during the bring-up of late secondary CPUs only.

Oh I see, this is for late CPUs. So you can probably disregard my
comment on the warning in the previous patch.

If you respin this series, I feel it would be more useful to have this
patch before the current patch 6.

Reviewed-by: Julien Thierry <julien.thierry@arm.com>

-- 
Julien Thierry

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

* Re: [PATCH v5 07/26] arm64/sve: Clarify role of the VQ map maintenance functions
@ 2019-02-20 11:43     ` Julien Thierry
  0 siblings, 0 replies; 205+ messages in thread
From: Julien Thierry @ 2019-02-20 11:43 UTC (permalink / raw)
  To: Dave Martin, kvmarm
  Cc: Okamoto Takayuki, Christoffer Dall, Ard Biesheuvel, Marc Zyngier,
	Catalin Marinas, Will Deacon, Zhang Lei, linux-arm-kernel



On 18/02/2019 19:52, Dave Martin wrote:
> The roles of sve_init_vq_map(), sve_update_vq_map() and
> sve_verify_vq_map() are highly non-obvious to anyone who has not dug
> through cpufeatures.c in detail.
> 
> Since the way these functions interact with each other is more
> important here than a full understanding of the cpufeatures code, this
> patch adds comments to make the functions' roles clearer.
> 
> No functional change.
> 
> Signed-off-by: Dave Martin <Dave.Martin@arm.com>
> ---
>  arch/arm64/kernel/fpsimd.c | 10 +++++++++-
>  1 file changed, 9 insertions(+), 1 deletion(-)
> 
> diff --git a/arch/arm64/kernel/fpsimd.c b/arch/arm64/kernel/fpsimd.c
> index 64729e2..92c2331 100644
> --- a/arch/arm64/kernel/fpsimd.c
> +++ b/arch/arm64/kernel/fpsimd.c
> @@ -647,6 +647,10 @@ static void sve_probe_vqs(DECLARE_BITMAP(map, SVE_VQ_MAX))
>  	}
>  }
>  
> +/*
> + * Initialise the set of known supported VQs for the boot CPU.
> + * This is called during kernel boot, before secondary CPUs are brought up.
> + */
>  void __init sve_init_vq_map(void)
>  {
>  	sve_probe_vqs(sve_vq_map);
> @@ -656,6 +660,7 @@ void __init sve_init_vq_map(void)
>  /*
>   * If we haven't committed to the set of supported VQs yet, filter out
>   * those not supported by the current CPU.
> + * This function is called during the bring-up of early secondary CPUs only.
>   */
>  void sve_update_vq_map(void)
>  {
> @@ -666,7 +671,10 @@ void sve_update_vq_map(void)
>  	bitmap_or(sve_vq_partial_map, sve_vq_partial_map, tmp_map, SVE_VQ_MAX);
>  }
>  
> -/* Check whether the current CPU supports all VQs in the committed set */
> +/*
> + * Check whether the current CPU supports all VQs in the committed set.
> + * This function is called during the bring-up of late secondary CPUs only.

Oh I see, this is for late CPUs. So you can probably disregard my
comment on the warning in the previous patch.

If you respin this series, I feel it would be more useful to have this
patch before the current patch 6.

Reviewed-by: Julien Thierry <julien.thierry@arm.com>

-- 
Julien Thierry

_______________________________________________
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] 205+ messages in thread

* Re: [PATCH v5 11/26] KVM: arm64: Extend reset_unknown() to handle mixed RES0/UNKNOWN registers
  2019-02-18 19:52   ` Dave Martin
@ 2019-02-20 13:33     ` Julien Thierry
  -1 siblings, 0 replies; 205+ messages in thread
From: Julien Thierry @ 2019-02-20 13:33 UTC (permalink / raw)
  To: Dave Martin, kvmarm
  Cc: Okamoto Takayuki, Christoffer Dall, Ard Biesheuvel, Marc Zyngier,
	Catalin Marinas, Will Deacon, Zhang Lei, linux-arm-kernel

Hi Dave,

On 18/02/2019 19:52, Dave Martin wrote:
> The reset_unknown() system register helper initialises a guest
> register to a distinctive junk value on vcpu reset, to help expose
> and debug deficient register initialisation within the guest.
> 
> Some registers such as the SVE control register ZCR_EL1 contain a
> mixture of UNKNOWN fields and RES0 bits.  For these,
> reset_unknown() does not work at present, since it sets all bits to
> junk values instead of just the wanted bits.
> 
> There is no need to craft another special helper just for that,
> since reset_unknown() almost does the appropriate thing anyway.
> This patch takes advantage of the unused val field in struct
> sys_reg_desc to specify a mask of bits that should be initialised
> to zero instead of junk.
> 
> All existing users of reset_unknown() do not (and should not)
> define a value for val, so they will implicitly set it to zero,
> resulting in all bits being made UNKNOWN by this function: thus,
> this patch makes no functional change for currently defined
> registers.
> 
> Future patches will make use of non-zero val.
> 
> Signed-off-by: Dave Martin <Dave.Martin@arm.com>
> ---
>  arch/arm64/kvm/sys_regs.h | 11 +++++++++--
>  1 file changed, 9 insertions(+), 2 deletions(-)
> 
> diff --git a/arch/arm64/kvm/sys_regs.h b/arch/arm64/kvm/sys_regs.h
> index 3b1bc7f..174ffc0 100644
> --- a/arch/arm64/kvm/sys_regs.h
> +++ b/arch/arm64/kvm/sys_regs.h
> @@ -56,7 +56,12 @@ struct sys_reg_desc {
>  	/* Index into sys_reg[], or 0 if we don't need to save it. */
>  	int reg;
>  
> -	/* Value (usually reset value) */
> +	/*
> +	 * Value (usually reset value)
> +	 * For reset_unknown, each bit set to 1 in val is treated as
> +	 * RES0 in the register: the corresponding register bit is
> +	 * reset to 0 instead of "unknown".
> +	 */

Seeing there are users of this field, I find this a bit fragile. Is
there a reason not to add a separate "u64 res0_mask;" ?

The sys_reg_desc structures are instantiated once as constants for the
whole system rather than per VM/VCPU. Would it be really bad to add a
64bit field there?

>  	u64 val;
>  
>  	/* Custom get/set_user functions, fallback to generic if NULL */
> @@ -92,7 +97,9 @@ static inline void reset_unknown(struct kvm_vcpu *vcpu,
>  {
>  	BUG_ON(!r->reg);
>  	BUG_ON(r->reg >= NR_SYS_REGS);
> -	__vcpu_sys_reg(vcpu, r->reg) = 0x1de7ec7edbadc0deULL;
> +
> +	/* If non-zero, r->val specifies which register bits are RES0: */
> +	__vcpu_sys_reg(vcpu, r->reg) = 0x1de7ec7edbadc0deULL & ~r->val;
>  }
>  
>  static inline void reset_val(struct kvm_vcpu *vcpu, const struct sys_reg_desc *r)
> 

Cheers,

-- 
Julien Thierry

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

* Re: [PATCH v5 11/26] KVM: arm64: Extend reset_unknown() to handle mixed RES0/UNKNOWN registers
@ 2019-02-20 13:33     ` Julien Thierry
  0 siblings, 0 replies; 205+ messages in thread
From: Julien Thierry @ 2019-02-20 13:33 UTC (permalink / raw)
  To: Dave Martin, kvmarm
  Cc: Okamoto Takayuki, Christoffer Dall, Ard Biesheuvel, Marc Zyngier,
	Catalin Marinas, Will Deacon, Zhang Lei, linux-arm-kernel

Hi Dave,

On 18/02/2019 19:52, Dave Martin wrote:
> The reset_unknown() system register helper initialises a guest
> register to a distinctive junk value on vcpu reset, to help expose
> and debug deficient register initialisation within the guest.
> 
> Some registers such as the SVE control register ZCR_EL1 contain a
> mixture of UNKNOWN fields and RES0 bits.  For these,
> reset_unknown() does not work at present, since it sets all bits to
> junk values instead of just the wanted bits.
> 
> There is no need to craft another special helper just for that,
> since reset_unknown() almost does the appropriate thing anyway.
> This patch takes advantage of the unused val field in struct
> sys_reg_desc to specify a mask of bits that should be initialised
> to zero instead of junk.
> 
> All existing users of reset_unknown() do not (and should not)
> define a value for val, so they will implicitly set it to zero,
> resulting in all bits being made UNKNOWN by this function: thus,
> this patch makes no functional change for currently defined
> registers.
> 
> Future patches will make use of non-zero val.
> 
> Signed-off-by: Dave Martin <Dave.Martin@arm.com>
> ---
>  arch/arm64/kvm/sys_regs.h | 11 +++++++++--
>  1 file changed, 9 insertions(+), 2 deletions(-)
> 
> diff --git a/arch/arm64/kvm/sys_regs.h b/arch/arm64/kvm/sys_regs.h
> index 3b1bc7f..174ffc0 100644
> --- a/arch/arm64/kvm/sys_regs.h
> +++ b/arch/arm64/kvm/sys_regs.h
> @@ -56,7 +56,12 @@ struct sys_reg_desc {
>  	/* Index into sys_reg[], or 0 if we don't need to save it. */
>  	int reg;
>  
> -	/* Value (usually reset value) */
> +	/*
> +	 * Value (usually reset value)
> +	 * For reset_unknown, each bit set to 1 in val is treated as
> +	 * RES0 in the register: the corresponding register bit is
> +	 * reset to 0 instead of "unknown".
> +	 */

Seeing there are users of this field, I find this a bit fragile. Is
there a reason not to add a separate "u64 res0_mask;" ?

The sys_reg_desc structures are instantiated once as constants for the
whole system rather than per VM/VCPU. Would it be really bad to add a
64bit field there?

>  	u64 val;
>  
>  	/* Custom get/set_user functions, fallback to generic if NULL */
> @@ -92,7 +97,9 @@ static inline void reset_unknown(struct kvm_vcpu *vcpu,
>  {
>  	BUG_ON(!r->reg);
>  	BUG_ON(r->reg >= NR_SYS_REGS);
> -	__vcpu_sys_reg(vcpu, r->reg) = 0x1de7ec7edbadc0deULL;
> +
> +	/* If non-zero, r->val specifies which register bits are RES0: */
> +	__vcpu_sys_reg(vcpu, r->reg) = 0x1de7ec7edbadc0deULL & ~r->val;
>  }
>  
>  static inline void reset_val(struct kvm_vcpu *vcpu, const struct sys_reg_desc *r)
> 

Cheers,

-- 
Julien Thierry

_______________________________________________
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] 205+ messages in thread

* Re: [PATCH v5 12/26] KVM: arm64: Support runtime sysreg visibility filtering
  2019-02-18 19:52   ` Dave Martin
@ 2019-02-20 14:33     ` Julien Thierry
  -1 siblings, 0 replies; 205+ messages in thread
From: Julien Thierry @ 2019-02-20 14:33 UTC (permalink / raw)
  To: Dave Martin, kvmarm
  Cc: Okamoto Takayuki, Christoffer Dall, Ard Biesheuvel, Marc Zyngier,
	Catalin Marinas, Will Deacon, Zhang Lei, linux-arm-kernel



On 18/02/2019 19:52, Dave Martin wrote:
> Some optional features of the Arm architecture add new system
> registers that are not present in the base architecture.
> 
> Where these features are optional for the guest, the visibility of
> these registers may need to depend on some runtime configuration,
> such as a flag passed to KVM_ARM_VCPU_INIT.
> 
> For example, ZCR_EL1 and ID_AA64ZFR0_EL1 need to be hidden if SVE
> is not enabled for the guest, even though these registers may be
> present in the hardware and visible to the host at EL2.
> 
> Adding special-case checks all over the place for individual
> registers is going to get messy as the number of conditionally-
> visible registers grows.
> 
> In order to help solve this problem, this patch adds a new sysreg
> method restrictions() that can be used to hook in any needed
> runtime visibility checks.  This method can currently return
> REG_NO_USER to inhibit enumeration and ioctl access to the register
> for userspace, and REG_NO_GUEST to inhibit runtime access by the
> guest using MSR/MRS.
> 
> This allows a conditionally modified view of individual system
> registers such as the CPU ID registers, in addition to completely
> hiding register where appropriate.
> 
> Signed-off-by: Dave Martin <Dave.Martin@arm.com>

Reviewed-by: Julien Thierry <julien.thierry@arm.com>

> 
> ---
> 
> Changes since v4:
> 
>  * Move from a boolean sysreg property that just suppresses register
>    enumeration via KVM_GET_REG_LIST, to a multi-flag property that
>    allows independent runtime control of MRS/MSR and user ioctl access.
> 
>    This allows registers to be either hidden completely, or to have
>    hybrid behaviours (such as the not-enumerated, RAZ, WAZ behaviour of
>    "non-present" CPU ID regs).
> ---
>  arch/arm64/kvm/sys_regs.c | 24 +++++++++++++++++++++---
>  arch/arm64/kvm/sys_regs.h | 13 +++++++++++++
>  2 files changed, 34 insertions(+), 3 deletions(-)
> 
> diff --git a/arch/arm64/kvm/sys_regs.c b/arch/arm64/kvm/sys_regs.c
> index 71c5825..3f1243e 100644
> --- a/arch/arm64/kvm/sys_regs.c
> +++ b/arch/arm64/kvm/sys_regs.c
> @@ -1863,6 +1863,12 @@ static void perform_access(struct kvm_vcpu *vcpu,
>  {
>  	trace_kvm_sys_access(*vcpu_pc(vcpu), params, r);
>  
> +	/* Check for regs disabled by runtime config */
> +	if (restrictions(vcpu, r) & REG_NO_GUEST) {
> +		kvm_inject_undefined(vcpu);
> +		return;
> +	}
> +
>  	/*
>  	 * Not having an accessor means that we have configured a trap
>  	 * that we don't know how to handle. This certainly qualifies
> @@ -2370,6 +2376,10 @@ int kvm_arm_sys_reg_get_reg(struct kvm_vcpu *vcpu, const struct kvm_one_reg *reg
>  	if (!r)
>  		return get_invariant_sys_reg(reg->id, uaddr);
>  
> +	/* Check for regs disabled by runtime config */
> +	if (restrictions(vcpu, r) & REG_NO_USER)
> +		return -ENOENT;
> +
>  	if (r->get_user)
>  		return (r->get_user)(vcpu, r, reg, uaddr);
>  
> @@ -2391,6 +2401,10 @@ int kvm_arm_sys_reg_set_reg(struct kvm_vcpu *vcpu, const struct kvm_one_reg *reg
>  	if (!r)
>  		return set_invariant_sys_reg(reg->id, uaddr);
>  
> +	/* Check for regs disabled by runtime config */
> +	if (restrictions(vcpu, r) & REG_NO_USER)
> +		return -ENOENT;
> +
>  	if (r->set_user)
>  		return (r->set_user)(vcpu, r, reg, uaddr);
>  
> @@ -2447,7 +2461,8 @@ static bool copy_reg_to_user(const struct sys_reg_desc *reg, u64 __user **uind)
>  	return true;
>  }
>  
> -static int walk_one_sys_reg(const struct sys_reg_desc *rd,
> +static int walk_one_sys_reg(const struct kvm_vcpu *vcpu,
> +			    const struct sys_reg_desc *rd,
>  			    u64 __user **uind,
>  			    unsigned int *total)
>  {
> @@ -2458,6 +2473,9 @@ static int walk_one_sys_reg(const struct sys_reg_desc *rd,
>  	if (!(rd->reg || rd->get_user))
>  		return 0;
>  
> +	if (restrictions(vcpu, rd) & REG_NO_USER)
> +		return 0;
> +
>  	if (!copy_reg_to_user(rd, uind))
>  		return -EFAULT;
>  
> @@ -2486,9 +2504,9 @@ static int walk_sys_regs(struct kvm_vcpu *vcpu, u64 __user *uind)
>  		int cmp = cmp_sys_reg(i1, i2);
>  		/* target-specific overrides generic entry. */
>  		if (cmp <= 0)
> -			err = walk_one_sys_reg(i1, &uind, &total);
> +			err = walk_one_sys_reg(vcpu, i1, &uind, &total);
>  		else
> -			err = walk_one_sys_reg(i2, &uind, &total);
> +			err = walk_one_sys_reg(vcpu, i2, &uind, &total);
>  
>  		if (err)
>  			return err;
> diff --git a/arch/arm64/kvm/sys_regs.h b/arch/arm64/kvm/sys_regs.h
> index 174ffc0..12f196f 100644
> --- a/arch/arm64/kvm/sys_regs.h
> +++ b/arch/arm64/kvm/sys_regs.h
> @@ -69,8 +69,15 @@ struct sys_reg_desc {
>  			const struct kvm_one_reg *reg, void __user *uaddr);
>  	int (*set_user)(struct kvm_vcpu *vcpu, const struct sys_reg_desc *rd,
>  			const struct kvm_one_reg *reg, void __user *uaddr);
> +
> +	/* Return mask of REG_* runtime restriction flags */
> +	unsigned int (*restrictions)(const struct kvm_vcpu *vcpu,
> +				     const struct sys_reg_desc *rd);
>  };
>  
> +#define REG_NO_USER	(1 << 0) /* hidden from userspace ioctl interface */
> +#define REG_NO_GUEST	(1 << 1) /* hidden from guest */
> +
>  static inline void print_sys_reg_instr(const struct sys_reg_params *p)
>  {
>  	/* Look, we even formatted it for you to paste into the table! */
> @@ -109,6 +116,12 @@ static inline void reset_val(struct kvm_vcpu *vcpu, const struct sys_reg_desc *r
>  	__vcpu_sys_reg(vcpu, r->reg) = r->val;
>  }
>  
> +static inline unsigned int restrictions(const struct kvm_vcpu *vcpu,
> +					const struct sys_reg_desc *r)
> +{
> +	return unlikely(r->restrictions) ? r->restrictions(vcpu, r) : 0;
> +}
> +
>  static inline int cmp_sys_reg(const struct sys_reg_desc *i1,
>  			      const struct sys_reg_desc *i2)
>  {
> 

-- 
Julien Thierry

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

* Re: [PATCH v5 12/26] KVM: arm64: Support runtime sysreg visibility filtering
@ 2019-02-20 14:33     ` Julien Thierry
  0 siblings, 0 replies; 205+ messages in thread
From: Julien Thierry @ 2019-02-20 14:33 UTC (permalink / raw)
  To: Dave Martin, kvmarm
  Cc: Okamoto Takayuki, Christoffer Dall, Ard Biesheuvel, Marc Zyngier,
	Catalin Marinas, Will Deacon, Zhang Lei, linux-arm-kernel



On 18/02/2019 19:52, Dave Martin wrote:
> Some optional features of the Arm architecture add new system
> registers that are not present in the base architecture.
> 
> Where these features are optional for the guest, the visibility of
> these registers may need to depend on some runtime configuration,
> such as a flag passed to KVM_ARM_VCPU_INIT.
> 
> For example, ZCR_EL1 and ID_AA64ZFR0_EL1 need to be hidden if SVE
> is not enabled for the guest, even though these registers may be
> present in the hardware and visible to the host at EL2.
> 
> Adding special-case checks all over the place for individual
> registers is going to get messy as the number of conditionally-
> visible registers grows.
> 
> In order to help solve this problem, this patch adds a new sysreg
> method restrictions() that can be used to hook in any needed
> runtime visibility checks.  This method can currently return
> REG_NO_USER to inhibit enumeration and ioctl access to the register
> for userspace, and REG_NO_GUEST to inhibit runtime access by the
> guest using MSR/MRS.
> 
> This allows a conditionally modified view of individual system
> registers such as the CPU ID registers, in addition to completely
> hiding register where appropriate.
> 
> Signed-off-by: Dave Martin <Dave.Martin@arm.com>

Reviewed-by: Julien Thierry <julien.thierry@arm.com>

> 
> ---
> 
> Changes since v4:
> 
>  * Move from a boolean sysreg property that just suppresses register
>    enumeration via KVM_GET_REG_LIST, to a multi-flag property that
>    allows independent runtime control of MRS/MSR and user ioctl access.
> 
>    This allows registers to be either hidden completely, or to have
>    hybrid behaviours (such as the not-enumerated, RAZ, WAZ behaviour of
>    "non-present" CPU ID regs).
> ---
>  arch/arm64/kvm/sys_regs.c | 24 +++++++++++++++++++++---
>  arch/arm64/kvm/sys_regs.h | 13 +++++++++++++
>  2 files changed, 34 insertions(+), 3 deletions(-)
> 
> diff --git a/arch/arm64/kvm/sys_regs.c b/arch/arm64/kvm/sys_regs.c
> index 71c5825..3f1243e 100644
> --- a/arch/arm64/kvm/sys_regs.c
> +++ b/arch/arm64/kvm/sys_regs.c
> @@ -1863,6 +1863,12 @@ static void perform_access(struct kvm_vcpu *vcpu,
>  {
>  	trace_kvm_sys_access(*vcpu_pc(vcpu), params, r);
>  
> +	/* Check for regs disabled by runtime config */
> +	if (restrictions(vcpu, r) & REG_NO_GUEST) {
> +		kvm_inject_undefined(vcpu);
> +		return;
> +	}
> +
>  	/*
>  	 * Not having an accessor means that we have configured a trap
>  	 * that we don't know how to handle. This certainly qualifies
> @@ -2370,6 +2376,10 @@ int kvm_arm_sys_reg_get_reg(struct kvm_vcpu *vcpu, const struct kvm_one_reg *reg
>  	if (!r)
>  		return get_invariant_sys_reg(reg->id, uaddr);
>  
> +	/* Check for regs disabled by runtime config */
> +	if (restrictions(vcpu, r) & REG_NO_USER)
> +		return -ENOENT;
> +
>  	if (r->get_user)
>  		return (r->get_user)(vcpu, r, reg, uaddr);
>  
> @@ -2391,6 +2401,10 @@ int kvm_arm_sys_reg_set_reg(struct kvm_vcpu *vcpu, const struct kvm_one_reg *reg
>  	if (!r)
>  		return set_invariant_sys_reg(reg->id, uaddr);
>  
> +	/* Check for regs disabled by runtime config */
> +	if (restrictions(vcpu, r) & REG_NO_USER)
> +		return -ENOENT;
> +
>  	if (r->set_user)
>  		return (r->set_user)(vcpu, r, reg, uaddr);
>  
> @@ -2447,7 +2461,8 @@ static bool copy_reg_to_user(const struct sys_reg_desc *reg, u64 __user **uind)
>  	return true;
>  }
>  
> -static int walk_one_sys_reg(const struct sys_reg_desc *rd,
> +static int walk_one_sys_reg(const struct kvm_vcpu *vcpu,
> +			    const struct sys_reg_desc *rd,
>  			    u64 __user **uind,
>  			    unsigned int *total)
>  {
> @@ -2458,6 +2473,9 @@ static int walk_one_sys_reg(const struct sys_reg_desc *rd,
>  	if (!(rd->reg || rd->get_user))
>  		return 0;
>  
> +	if (restrictions(vcpu, rd) & REG_NO_USER)
> +		return 0;
> +
>  	if (!copy_reg_to_user(rd, uind))
>  		return -EFAULT;
>  
> @@ -2486,9 +2504,9 @@ static int walk_sys_regs(struct kvm_vcpu *vcpu, u64 __user *uind)
>  		int cmp = cmp_sys_reg(i1, i2);
>  		/* target-specific overrides generic entry. */
>  		if (cmp <= 0)
> -			err = walk_one_sys_reg(i1, &uind, &total);
> +			err = walk_one_sys_reg(vcpu, i1, &uind, &total);
>  		else
> -			err = walk_one_sys_reg(i2, &uind, &total);
> +			err = walk_one_sys_reg(vcpu, i2, &uind, &total);
>  
>  		if (err)
>  			return err;
> diff --git a/arch/arm64/kvm/sys_regs.h b/arch/arm64/kvm/sys_regs.h
> index 174ffc0..12f196f 100644
> --- a/arch/arm64/kvm/sys_regs.h
> +++ b/arch/arm64/kvm/sys_regs.h
> @@ -69,8 +69,15 @@ struct sys_reg_desc {
>  			const struct kvm_one_reg *reg, void __user *uaddr);
>  	int (*set_user)(struct kvm_vcpu *vcpu, const struct sys_reg_desc *rd,
>  			const struct kvm_one_reg *reg, void __user *uaddr);
> +
> +	/* Return mask of REG_* runtime restriction flags */
> +	unsigned int (*restrictions)(const struct kvm_vcpu *vcpu,
> +				     const struct sys_reg_desc *rd);
>  };
>  
> +#define REG_NO_USER	(1 << 0) /* hidden from userspace ioctl interface */
> +#define REG_NO_GUEST	(1 << 1) /* hidden from guest */
> +
>  static inline void print_sys_reg_instr(const struct sys_reg_params *p)
>  {
>  	/* Look, we even formatted it for you to paste into the table! */
> @@ -109,6 +116,12 @@ static inline void reset_val(struct kvm_vcpu *vcpu, const struct sys_reg_desc *r
>  	__vcpu_sys_reg(vcpu, r->reg) = r->val;
>  }
>  
> +static inline unsigned int restrictions(const struct kvm_vcpu *vcpu,
> +					const struct sys_reg_desc *r)
> +{
> +	return unlikely(r->restrictions) ? r->restrictions(vcpu, r) : 0;
> +}
> +
>  static inline int cmp_sys_reg(const struct sys_reg_desc *i1,
>  			      const struct sys_reg_desc *i2)
>  {
> 

-- 
Julien Thierry

_______________________________________________
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] 205+ messages in thread

* Re: [PATCH v5 05/26] KVM: arm64: Add missing #include of <linux/bitmap.h> to kvm_host.h
  2019-02-18 19:52   ` Dave Martin
@ 2019-02-20 15:23     ` Mark Rutland
  -1 siblings, 0 replies; 205+ messages in thread
From: Mark Rutland @ 2019-02-20 15:23 UTC (permalink / raw)
  To: Dave Martin
  Cc: Okamoto Takayuki, Christoffer Dall, Ard Biesheuvel, Marc Zyngier,
	Catalin Marinas, Will Deacon, Zhang Lei, kvmarm,
	linux-arm-kernel

On Mon, Feb 18, 2019 at 07:52:18PM +0000, Dave Martin wrote:
> kvm_host.h uses DECLARE_BITMAP() to declare the features member of
> struct vcpu_arch, but the corresponding #include for this is
> missing.
> 
> This patch adds a suitable #include for <linux/bitmap.h>.  Although
> the header builds without it today, this should help to avoid
> future surprises.
> 
> Signed-off-by: Dave Martin <Dave.Martin@arm.com>
> Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
> ---
>  arch/arm64/include/asm/kvm_host.h | 1 +
>  1 file changed, 1 insertion(+)
> 
> diff --git a/arch/arm64/include/asm/kvm_host.h b/arch/arm64/include/asm/kvm_host.h
> index 7732d0b..84056a4 100644
> --- a/arch/arm64/include/asm/kvm_host.h
> +++ b/arch/arm64/include/asm/kvm_host.h
> @@ -22,6 +22,7 @@
>  #ifndef __ARM64_KVM_HOST_H__
>  #define __ARM64_KVM_HOST_H__
>  
> +#include <linux/bitmap.h>
>  #include <linux/types.h>
>  #include <linux/kvm_types.h>
>  #include <asm/cpufeature.h>

From a quick scan of the file, we're also missing:

#include <linux/jump_label.h>
#include <linux/percpu.h>
#include <linux/thread_info.h>

#include <asm/barrier.h>

... which might be worth adding at the same time.

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

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

* Re: [PATCH v5 05/26] KVM: arm64: Add missing #include of <linux/bitmap.h> to kvm_host.h
@ 2019-02-20 15:23     ` Mark Rutland
  0 siblings, 0 replies; 205+ messages in thread
From: Mark Rutland @ 2019-02-20 15:23 UTC (permalink / raw)
  To: Dave Martin
  Cc: Okamoto Takayuki, Christoffer Dall, Ard Biesheuvel, Marc Zyngier,
	Catalin Marinas, Will Deacon, Zhang Lei, kvmarm,
	linux-arm-kernel

On Mon, Feb 18, 2019 at 07:52:18PM +0000, Dave Martin wrote:
> kvm_host.h uses DECLARE_BITMAP() to declare the features member of
> struct vcpu_arch, but the corresponding #include for this is
> missing.
> 
> This patch adds a suitable #include for <linux/bitmap.h>.  Although
> the header builds without it today, this should help to avoid
> future surprises.
> 
> Signed-off-by: Dave Martin <Dave.Martin@arm.com>
> Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
> ---
>  arch/arm64/include/asm/kvm_host.h | 1 +
>  1 file changed, 1 insertion(+)
> 
> diff --git a/arch/arm64/include/asm/kvm_host.h b/arch/arm64/include/asm/kvm_host.h
> index 7732d0b..84056a4 100644
> --- a/arch/arm64/include/asm/kvm_host.h
> +++ b/arch/arm64/include/asm/kvm_host.h
> @@ -22,6 +22,7 @@
>  #ifndef __ARM64_KVM_HOST_H__
>  #define __ARM64_KVM_HOST_H__
>  
> +#include <linux/bitmap.h>
>  #include <linux/types.h>
>  #include <linux/kvm_types.h>
>  #include <asm/cpufeature.h>

From a quick scan of the file, we're also missing:

#include <linux/jump_label.h>
#include <linux/percpu.h>
#include <linux/thread_info.h>

#include <asm/barrier.h>

... which might be worth adding at the same time.

Thanks,
Mark.

_______________________________________________
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] 205+ messages in thread

* Re: [PATCH v5 12/26] KVM: arm64: Support runtime sysreg visibility filtering
  2019-02-18 19:52   ` Dave Martin
@ 2019-02-20 15:37     ` Mark Rutland
  -1 siblings, 0 replies; 205+ messages in thread
From: Mark Rutland @ 2019-02-20 15:37 UTC (permalink / raw)
  To: Dave Martin
  Cc: Okamoto Takayuki, Christoffer Dall, Ard Biesheuvel, Marc Zyngier,
	Catalin Marinas, Will Deacon, Zhang Lei, kvmarm,
	linux-arm-kernel

On Mon, Feb 18, 2019 at 07:52:25PM +0000, Dave Martin wrote:
> Some optional features of the Arm architecture add new system
> registers that are not present in the base architecture.
> 
> Where these features are optional for the guest, the visibility of
> these registers may need to depend on some runtime configuration,
> such as a flag passed to KVM_ARM_VCPU_INIT.
> 
> For example, ZCR_EL1 and ID_AA64ZFR0_EL1 need to be hidden if SVE
> is not enabled for the guest, even though these registers may be
> present in the hardware and visible to the host at EL2.
> 
> Adding special-case checks all over the place for individual
> registers is going to get messy as the number of conditionally-
> visible registers grows.
> 
> In order to help solve this problem, this patch adds a new sysreg
> method restrictions() that can be used to hook in any needed
> runtime visibility checks.  This method can currently return
> REG_NO_USER to inhibit enumeration and ioctl access to the register
> for userspace, and REG_NO_GUEST to inhibit runtime access by the
> guest using MSR/MRS.
> 
> This allows a conditionally modified view of individual system
> registers such as the CPU ID registers, in addition to completely
> hiding register where appropriate.
> 
> Signed-off-by: Dave Martin <Dave.Martin@arm.com>
> 
> ---
> 
> Changes since v4:
> 
>  * Move from a boolean sysreg property that just suppresses register
>    enumeration via KVM_GET_REG_LIST, to a multi-flag property that
>    allows independent runtime control of MRS/MSR and user ioctl access.
> 
>    This allows registers to be either hidden completely, or to have
>    hybrid behaviours (such as the not-enumerated, RAZ, WAZ behaviour of
>    "non-present" CPU ID regs).

Sorry for bikeshedding...

> +	/* Check for regs disabled by runtime config */
> +	if (restrictions(vcpu, r) & REG_NO_GUEST) {

Maybe it's worth wrapping this as something like

	reg_runtime_hidden_from_guest(vcpu, r)

... and avoid exposing the raw flags to all the places we have to check?

[...]

> +#define REG_NO_USER	(1 << 0) /* hidden from userspace ioctl interface */
> +#define REG_NO_GUEST	(1 << 1) /* hidden from guest */

Perhaps REG_USER_HIDDEN and REG_GUEST_HIDDEN?

Thanks,
Mark.

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

* Re: [PATCH v5 12/26] KVM: arm64: Support runtime sysreg visibility filtering
@ 2019-02-20 15:37     ` Mark Rutland
  0 siblings, 0 replies; 205+ messages in thread
From: Mark Rutland @ 2019-02-20 15:37 UTC (permalink / raw)
  To: Dave Martin
  Cc: Okamoto Takayuki, Christoffer Dall, Ard Biesheuvel, Marc Zyngier,
	Catalin Marinas, Will Deacon, Zhang Lei, kvmarm,
	linux-arm-kernel

On Mon, Feb 18, 2019 at 07:52:25PM +0000, Dave Martin wrote:
> Some optional features of the Arm architecture add new system
> registers that are not present in the base architecture.
> 
> Where these features are optional for the guest, the visibility of
> these registers may need to depend on some runtime configuration,
> such as a flag passed to KVM_ARM_VCPU_INIT.
> 
> For example, ZCR_EL1 and ID_AA64ZFR0_EL1 need to be hidden if SVE
> is not enabled for the guest, even though these registers may be
> present in the hardware and visible to the host at EL2.
> 
> Adding special-case checks all over the place for individual
> registers is going to get messy as the number of conditionally-
> visible registers grows.
> 
> In order to help solve this problem, this patch adds a new sysreg
> method restrictions() that can be used to hook in any needed
> runtime visibility checks.  This method can currently return
> REG_NO_USER to inhibit enumeration and ioctl access to the register
> for userspace, and REG_NO_GUEST to inhibit runtime access by the
> guest using MSR/MRS.
> 
> This allows a conditionally modified view of individual system
> registers such as the CPU ID registers, in addition to completely
> hiding register where appropriate.
> 
> Signed-off-by: Dave Martin <Dave.Martin@arm.com>
> 
> ---
> 
> Changes since v4:
> 
>  * Move from a boolean sysreg property that just suppresses register
>    enumeration via KVM_GET_REG_LIST, to a multi-flag property that
>    allows independent runtime control of MRS/MSR and user ioctl access.
> 
>    This allows registers to be either hidden completely, or to have
>    hybrid behaviours (such as the not-enumerated, RAZ, WAZ behaviour of
>    "non-present" CPU ID regs).

Sorry for bikeshedding...

> +	/* Check for regs disabled by runtime config */
> +	if (restrictions(vcpu, r) & REG_NO_GUEST) {

Maybe it's worth wrapping this as something like

	reg_runtime_hidden_from_guest(vcpu, r)

... and avoid exposing the raw flags to all the places we have to check?

[...]

> +#define REG_NO_USER	(1 << 0) /* hidden from userspace ioctl interface */
> +#define REG_NO_GUEST	(1 << 1) /* hidden from guest */

Perhaps REG_USER_HIDDEN and REG_GUEST_HIDDEN?

Thanks,
Mark.

_______________________________________________
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] 205+ messages in thread

* Re: [PATCH v5 00/26] KVM: arm64: SVE guest support
  2019-02-18 19:52 ` Dave Martin
@ 2019-02-20 15:47   ` Dave Martin
  -1 siblings, 0 replies; 205+ messages in thread
From: Dave Martin @ 2019-02-20 15:47 UTC (permalink / raw)
  To: kvmarm
  Cc: Okamoto Takayuki, Christoffer Dall, Ard Biesheuvel, Marc Zyngier,
	Catalin Marinas, Will Deacon, Zhang Lei, linux-arm-kernel

On Mon, Feb 18, 2019 at 07:52:13PM +0000, Dave Martin wrote:

[...]

> AArch32 host testing is pending.  I will ping this series with a reply
> to the cover letter when that testing has been completed.

AArch32 host testing now done on Arm TC2: 15 guests were able to boot
and execute "find /" concurrently without error.

Due to the trivial nature of the changes in the common code, this is
probably sufficient testing, but if anyone thinks I should run
something else (or wants to give it a try), let me know.

Cheers
---Dave

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

* Re: [PATCH v5 00/26] KVM: arm64: SVE guest support
@ 2019-02-20 15:47   ` Dave Martin
  0 siblings, 0 replies; 205+ messages in thread
From: Dave Martin @ 2019-02-20 15:47 UTC (permalink / raw)
  To: kvmarm
  Cc: Okamoto Takayuki, Christoffer Dall, Ard Biesheuvel, Marc Zyngier,
	Catalin Marinas, Will Deacon, Zhang Lei, linux-arm-kernel

On Mon, Feb 18, 2019 at 07:52:13PM +0000, Dave Martin wrote:

[...]

> AArch32 host testing is pending.  I will ping this series with a reply
> to the cover letter when that testing has been completed.

AArch32 host testing now done on Arm TC2: 15 guests were able to boot
and execute "find /" concurrently without error.

Due to the trivial nature of the changes in the common code, this is
probably sufficient testing, but if anyone thinks I should run
something else (or wants to give it a try), let me know.

Cheers
---Dave

_______________________________________________
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] 205+ messages in thread

* Re: [PATCH v5 14/26] KVM: arm64/sve: Context switch the SVE registers
  2019-02-18 19:52   ` Dave Martin
@ 2019-02-20 16:19     ` Mark Rutland
  -1 siblings, 0 replies; 205+ messages in thread
From: Mark Rutland @ 2019-02-20 16:19 UTC (permalink / raw)
  To: Dave Martin
  Cc: Okamoto Takayuki, Christoffer Dall, Ard Biesheuvel, Marc Zyngier,
	Catalin Marinas, Will Deacon, Zhang Lei, kvmarm,
	linux-arm-kernel

On Mon, Feb 18, 2019 at 07:52:27PM +0000, Dave Martin wrote:
> -static bool __hyp_text __hyp_switch_fpsimd(struct kvm_vcpu *vcpu)
> +/* Check for an FPSIMD/SVE trap and handle as appropriate */
> +static bool __hyp_text __hyp_handle_fpsimd(struct kvm_vcpu *vcpu)
>  {
> -	struct user_fpsimd_state *host_fpsimd = vcpu->arch.host_fpsimd_state;
> +	bool vhe, sve_guest, sve_host;
> +	u8 trap_class;

Nit: elsewhere in kvm, this gets called hsr_ec. Can we use the same name
here?

>  
> -	if (has_vhe())
> -		write_sysreg(read_sysreg(cpacr_el1) | CPACR_EL1_FPEN,
> -			     cpacr_el1);
> -	else
> +	if (!system_supports_fpsimd())
> +		return false;
> +
> +	if (system_supports_sve()) {
> +		sve_guest = vcpu_has_sve(vcpu);
> +		sve_host = vcpu->arch.flags & KVM_ARM64_HOST_SVE_IN_USE;
> +		vhe = true;
> +	} else {
> +		sve_guest = false;
> +		sve_host = false;
> +		vhe = has_vhe();
> +	}
> +
> +	trap_class = kvm_vcpu_trap_get_class(vcpu);
> +	if (trap_class != ESR_ELx_EC_FP_ASIMD &&
> +	    (!sve_guest || trap_class != ESR_ELx_EC_SVE))
> +		return false;

This is somewhat painful to decipher, but I couldn't come up with
something that was both succint and legible.

Maybe it's worth duplicating the SVE check, i.e.

	if (hsr_ec != ESR_ELx_EC_FP_ASIMD &&
	    hsr_ec != ESR_ELx_EC_SVE)
		return false;

	if (!sve_guest && hsr_ec == ESR_ELx_EC_SVE)
		return false;

... ?

Thanks,
Mark.

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

* Re: [PATCH v5 14/26] KVM: arm64/sve: Context switch the SVE registers
@ 2019-02-20 16:19     ` Mark Rutland
  0 siblings, 0 replies; 205+ messages in thread
From: Mark Rutland @ 2019-02-20 16:19 UTC (permalink / raw)
  To: Dave Martin
  Cc: Okamoto Takayuki, Christoffer Dall, Ard Biesheuvel, Marc Zyngier,
	Catalin Marinas, Will Deacon, Zhang Lei, kvmarm,
	linux-arm-kernel

On Mon, Feb 18, 2019 at 07:52:27PM +0000, Dave Martin wrote:
> -static bool __hyp_text __hyp_switch_fpsimd(struct kvm_vcpu *vcpu)
> +/* Check for an FPSIMD/SVE trap and handle as appropriate */
> +static bool __hyp_text __hyp_handle_fpsimd(struct kvm_vcpu *vcpu)
>  {
> -	struct user_fpsimd_state *host_fpsimd = vcpu->arch.host_fpsimd_state;
> +	bool vhe, sve_guest, sve_host;
> +	u8 trap_class;

Nit: elsewhere in kvm, this gets called hsr_ec. Can we use the same name
here?

>  
> -	if (has_vhe())
> -		write_sysreg(read_sysreg(cpacr_el1) | CPACR_EL1_FPEN,
> -			     cpacr_el1);
> -	else
> +	if (!system_supports_fpsimd())
> +		return false;
> +
> +	if (system_supports_sve()) {
> +		sve_guest = vcpu_has_sve(vcpu);
> +		sve_host = vcpu->arch.flags & KVM_ARM64_HOST_SVE_IN_USE;
> +		vhe = true;
> +	} else {
> +		sve_guest = false;
> +		sve_host = false;
> +		vhe = has_vhe();
> +	}
> +
> +	trap_class = kvm_vcpu_trap_get_class(vcpu);
> +	if (trap_class != ESR_ELx_EC_FP_ASIMD &&
> +	    (!sve_guest || trap_class != ESR_ELx_EC_SVE))
> +		return false;

This is somewhat painful to decipher, but I couldn't come up with
something that was both succint and legible.

Maybe it's worth duplicating the SVE check, i.e.

	if (hsr_ec != ESR_ELx_EC_FP_ASIMD &&
	    hsr_ec != ESR_ELx_EC_SVE)
		return false;

	if (!sve_guest && hsr_ec == ESR_ELx_EC_SVE)
		return false;

... ?

Thanks,
Mark.

_______________________________________________
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] 205+ messages in thread

* Re: [PATCH v5 14/26] KVM: arm64/sve: Context switch the SVE registers
  2019-02-18 19:52   ` Dave Martin
@ 2019-02-20 16:46     ` Julien Thierry
  -1 siblings, 0 replies; 205+ messages in thread
From: Julien Thierry @ 2019-02-20 16:46 UTC (permalink / raw)
  To: Dave Martin, kvmarm
  Cc: Okamoto Takayuki, Christoffer Dall, Ard Biesheuvel, Marc Zyngier,
	Catalin Marinas, Will Deacon, Zhang Lei, linux-arm-kernel



On 18/02/2019 19:52, Dave Martin wrote:
> In order to give each vcpu its own view of the SVE registers, this
> patch adds context storage via a new sve_state pointer in struct
> vcpu_arch.  An additional member sve_max_vl is also added for each
> vcpu, to determine the maximum vector length visible to the guest
> and thus the value to be configured in ZCR_EL2.LEN while the is

"While the <guest> is active"?

> active.  This also determines the layout and size of the storage in
> sve_state, which is read and written by the same backend functions
> that are used for context-switching the SVE state for host tasks.
> 
> On SVE-enabled vcpus, SVE access traps are now handled by switching
> in the vcpu's SVE context and disabling the trap before returning
> to the guest.  On other vcpus, the trap is not handled and an exit
> back to the host occurs, where the handle_sve() fallback path
> reflects an undefined instruction exception back to the guest,
> consistently with the behaviour of non-SVE-capable hardware (as was
> done unconditionally prior to this patch).
> 
> No SVE handling is added on non-VHE-only paths, since VHE is an
> architectural and Kconfig prerequisite of SVE.
> 
> Signed-off-by: Dave Martin <Dave.Martin@arm.com>
> 

Otherwise:

Reviewed-by: Julien Thierry <julien.thierry@arm.com>

> ---
> 
> Changes since v4:
> 
>  * Remove if_sve() helper in favour of open-coded static key checks.
> 
>  * Explicitly merge static key checks and other condition checks to
>    reduce overhead and maximise const-folding and specialisation
>    opportunities in the compiler.
> ---
>  arch/arm64/include/asm/kvm_host.h |  6 ++++
>  arch/arm64/kvm/fpsimd.c           |  5 +--
>  arch/arm64/kvm/hyp/switch.c       | 70 +++++++++++++++++++++++++++++----------
>  3 files changed, 61 insertions(+), 20 deletions(-)
> 
> diff --git a/arch/arm64/include/asm/kvm_host.h b/arch/arm64/include/asm/kvm_host.h
> index c32f195..77b6f3e 100644
> --- a/arch/arm64/include/asm/kvm_host.h
> +++ b/arch/arm64/include/asm/kvm_host.h
> @@ -212,6 +212,8 @@ typedef struct kvm_cpu_context kvm_cpu_context_t;
>  
>  struct kvm_vcpu_arch {
>  	struct kvm_cpu_context ctxt;
> +	void *sve_state;
> +	unsigned int sve_max_vl;
>  
>  	/* HYP configuration */
>  	u64 hcr_el2;
> @@ -304,6 +306,10 @@ struct kvm_vcpu_arch {
>  	bool sysregs_loaded_on_cpu;
>  };
>  
> +/* Pointer to the vcpu's SVE FFR for sve_{save,load}_state() */
> +#define vcpu_sve_pffr(vcpu) ((void *)((char *)((vcpu)->arch.sve_state) + \
> +				      sve_ffr_offset((vcpu)->arch.sve_max_vl)))
> +
>  /* vcpu_arch flags field values: */
>  #define KVM_ARM64_DEBUG_DIRTY		(1 << 0)
>  #define KVM_ARM64_FP_ENABLED		(1 << 1) /* guest FP regs loaded */
> diff --git a/arch/arm64/kvm/fpsimd.c b/arch/arm64/kvm/fpsimd.c
> index 7053bf4..6e3c9c8 100644
> --- a/arch/arm64/kvm/fpsimd.c
> +++ b/arch/arm64/kvm/fpsimd.c
> @@ -87,10 +87,11 @@ void kvm_arch_vcpu_ctxsync_fp(struct kvm_vcpu *vcpu)
>  
>  	if (vcpu->arch.flags & KVM_ARM64_FP_ENABLED) {
>  		fpsimd_bind_state_to_cpu(&vcpu->arch.ctxt.gp_regs.fp_regs,
> -					 NULL, SVE_VL_MIN);
> +					 vcpu->arch.sve_state,
> +					 vcpu->arch.sve_max_vl);
>  
>  		clear_thread_flag(TIF_FOREIGN_FPSTATE);
> -		clear_thread_flag(TIF_SVE);
> +		update_thread_flag(TIF_SVE, vcpu_has_sve(vcpu));
>  	}
>  }
>  
> diff --git a/arch/arm64/kvm/hyp/switch.c b/arch/arm64/kvm/hyp/switch.c
> index 9f07403..cdc9063 100644
> --- a/arch/arm64/kvm/hyp/switch.c
> +++ b/arch/arm64/kvm/hyp/switch.c
> @@ -98,7 +98,10 @@ static void activate_traps_vhe(struct kvm_vcpu *vcpu)
>  	val = read_sysreg(cpacr_el1);
>  	val |= CPACR_EL1_TTA;
>  	val &= ~CPACR_EL1_ZEN;
> -	if (!update_fp_enabled(vcpu)) {
> +	if (update_fp_enabled(vcpu)) {
> +		if (vcpu_has_sve(vcpu))
> +			val |= CPACR_EL1_ZEN;
> +	} else {
>  		val &= ~CPACR_EL1_FPEN;
>  		__activate_traps_fpsimd32(vcpu);
>  	}
> @@ -313,16 +316,43 @@ static bool __hyp_text __populate_fault_info(struct kvm_vcpu *vcpu)
>  	return true;
>  }
>  
> -static bool __hyp_text __hyp_switch_fpsimd(struct kvm_vcpu *vcpu)
> +/* Check for an FPSIMD/SVE trap and handle as appropriate */
> +static bool __hyp_text __hyp_handle_fpsimd(struct kvm_vcpu *vcpu)
>  {
> -	struct user_fpsimd_state *host_fpsimd = vcpu->arch.host_fpsimd_state;
> +	bool vhe, sve_guest, sve_host;
> +	u8 trap_class;
>  
> -	if (has_vhe())
> -		write_sysreg(read_sysreg(cpacr_el1) | CPACR_EL1_FPEN,
> -			     cpacr_el1);
> -	else
> +	if (!system_supports_fpsimd())
> +		return false;
> +
> +	if (system_supports_sve()) {
> +		sve_guest = vcpu_has_sve(vcpu);
> +		sve_host = vcpu->arch.flags & KVM_ARM64_HOST_SVE_IN_USE;
> +		vhe = true;
> +	} else {
> +		sve_guest = false;
> +		sve_host = false;
> +		vhe = has_vhe();
> +	}
> +
> +	trap_class = kvm_vcpu_trap_get_class(vcpu);
> +	if (trap_class != ESR_ELx_EC_FP_ASIMD &&
> +	    (!sve_guest || trap_class != ESR_ELx_EC_SVE))
> +		return false;
> +
> +	/* The trap is an FPSIMD/SVE trap: switch the context */
> +
> +	if (vhe) {
> +		u64 reg = read_sysreg(cpacr_el1) | CPACR_EL1_FPEN;
> +
> +		if (sve_guest)
> +			reg |= CPACR_EL1_ZEN;
> +
> +		write_sysreg(reg, cpacr_el1);
> +	} else {
>  		write_sysreg(read_sysreg(cptr_el2) & ~(u64)CPTR_EL2_TFP,
>  			     cptr_el2);
> +	}
>  
>  	isb();
>  
> @@ -331,24 +361,28 @@ static bool __hyp_text __hyp_switch_fpsimd(struct kvm_vcpu *vcpu)
>  		 * In the SVE case, VHE is assumed: it is enforced by
>  		 * Kconfig and kvm_arch_init().
>  		 */
> -		if (system_supports_sve() &&
> -		    (vcpu->arch.flags & KVM_ARM64_HOST_SVE_IN_USE)) {
> +		if (sve_host) {
>  			struct thread_struct *thread = container_of(
> -				host_fpsimd,
> +				vcpu->arch.host_fpsimd_state,
>  				struct thread_struct, uw.fpsimd_state);
>  
> -			sve_save_state(sve_pffr(thread), &host_fpsimd->fpsr);
> +			sve_save_state(sve_pffr(thread),
> +				       &vcpu->arch.host_fpsimd_state->fpsr);
>  		} else {
> -			__fpsimd_save_state(host_fpsimd);
> +			__fpsimd_save_state(vcpu->arch.host_fpsimd_state);
>  		}
>  
>  		vcpu->arch.flags &= ~KVM_ARM64_FP_HOST;
>  	}
>  
> -	__fpsimd_restore_state(&vcpu->arch.ctxt.gp_regs.fp_regs);
> -
> -	if (vcpu_has_sve(vcpu))
> +	if (sve_guest) {
> +		sve_load_state(vcpu_sve_pffr(vcpu),
> +			       &vcpu->arch.ctxt.gp_regs.fp_regs.fpsr,
> +			       sve_vq_from_vl(vcpu->arch.sve_max_vl) - 1);
>  		write_sysreg_s(vcpu->arch.ctxt.sys_regs[ZCR_EL1], SYS_ZCR_EL12);
> +	} else {
> +		__fpsimd_restore_state(&vcpu->arch.ctxt.gp_regs.fp_regs);
> +	}
>  
>  	/* Skip restoring fpexc32 for AArch64 guests */
>  	if (!(read_sysreg(hcr_el2) & HCR_RW))
> @@ -384,10 +418,10 @@ static bool __hyp_text fixup_guest_exit(struct kvm_vcpu *vcpu, u64 *exit_code)
>  	 * and restore the guest context lazily.
>  	 * If FP/SIMD is not implemented, handle the trap and inject an
>  	 * undefined instruction exception to the guest.
> +	 * Similarly for trapped SVE accesses.
>  	 */
> -	if (system_supports_fpsimd() &&
> -	    kvm_vcpu_trap_get_class(vcpu) == ESR_ELx_EC_FP_ASIMD)
> -		return __hyp_switch_fpsimd(vcpu);
> +	if (__hyp_handle_fpsimd(vcpu))
> +		return true;
>  
>  	if (!__populate_fault_info(vcpu))
>  		return true;
> 

-- 
Julien Thierry

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

* Re: [PATCH v5 14/26] KVM: arm64/sve: Context switch the SVE registers
@ 2019-02-20 16:46     ` Julien Thierry
  0 siblings, 0 replies; 205+ messages in thread
From: Julien Thierry @ 2019-02-20 16:46 UTC (permalink / raw)
  To: Dave Martin, kvmarm
  Cc: Okamoto Takayuki, Christoffer Dall, Ard Biesheuvel, Marc Zyngier,
	Catalin Marinas, Will Deacon, Zhang Lei, linux-arm-kernel



On 18/02/2019 19:52, Dave Martin wrote:
> In order to give each vcpu its own view of the SVE registers, this
> patch adds context storage via a new sve_state pointer in struct
> vcpu_arch.  An additional member sve_max_vl is also added for each
> vcpu, to determine the maximum vector length visible to the guest
> and thus the value to be configured in ZCR_EL2.LEN while the is

"While the <guest> is active"?

> active.  This also determines the layout and size of the storage in
> sve_state, which is read and written by the same backend functions
> that are used for context-switching the SVE state for host tasks.
> 
> On SVE-enabled vcpus, SVE access traps are now handled by switching
> in the vcpu's SVE context and disabling the trap before returning
> to the guest.  On other vcpus, the trap is not handled and an exit
> back to the host occurs, where the handle_sve() fallback path
> reflects an undefined instruction exception back to the guest,
> consistently with the behaviour of non-SVE-capable hardware (as was
> done unconditionally prior to this patch).
> 
> No SVE handling is added on non-VHE-only paths, since VHE is an
> architectural and Kconfig prerequisite of SVE.
> 
> Signed-off-by: Dave Martin <Dave.Martin@arm.com>
> 

Otherwise:

Reviewed-by: Julien Thierry <julien.thierry@arm.com>

> ---
> 
> Changes since v4:
> 
>  * Remove if_sve() helper in favour of open-coded static key checks.
> 
>  * Explicitly merge static key checks and other condition checks to
>    reduce overhead and maximise const-folding and specialisation
>    opportunities in the compiler.
> ---
>  arch/arm64/include/asm/kvm_host.h |  6 ++++
>  arch/arm64/kvm/fpsimd.c           |  5 +--
>  arch/arm64/kvm/hyp/switch.c       | 70 +++++++++++++++++++++++++++++----------
>  3 files changed, 61 insertions(+), 20 deletions(-)
> 
> diff --git a/arch/arm64/include/asm/kvm_host.h b/arch/arm64/include/asm/kvm_host.h
> index c32f195..77b6f3e 100644
> --- a/arch/arm64/include/asm/kvm_host.h
> +++ b/arch/arm64/include/asm/kvm_host.h
> @@ -212,6 +212,8 @@ typedef struct kvm_cpu_context kvm_cpu_context_t;
>  
>  struct kvm_vcpu_arch {
>  	struct kvm_cpu_context ctxt;
> +	void *sve_state;
> +	unsigned int sve_max_vl;
>  
>  	/* HYP configuration */
>  	u64 hcr_el2;
> @@ -304,6 +306,10 @@ struct kvm_vcpu_arch {
>  	bool sysregs_loaded_on_cpu;
>  };
>  
> +/* Pointer to the vcpu's SVE FFR for sve_{save,load}_state() */
> +#define vcpu_sve_pffr(vcpu) ((void *)((char *)((vcpu)->arch.sve_state) + \
> +				      sve_ffr_offset((vcpu)->arch.sve_max_vl)))
> +
>  /* vcpu_arch flags field values: */
>  #define KVM_ARM64_DEBUG_DIRTY		(1 << 0)
>  #define KVM_ARM64_FP_ENABLED		(1 << 1) /* guest FP regs loaded */
> diff --git a/arch/arm64/kvm/fpsimd.c b/arch/arm64/kvm/fpsimd.c
> index 7053bf4..6e3c9c8 100644
> --- a/arch/arm64/kvm/fpsimd.c
> +++ b/arch/arm64/kvm/fpsimd.c
> @@ -87,10 +87,11 @@ void kvm_arch_vcpu_ctxsync_fp(struct kvm_vcpu *vcpu)
>  
>  	if (vcpu->arch.flags & KVM_ARM64_FP_ENABLED) {
>  		fpsimd_bind_state_to_cpu(&vcpu->arch.ctxt.gp_regs.fp_regs,
> -					 NULL, SVE_VL_MIN);
> +					 vcpu->arch.sve_state,
> +					 vcpu->arch.sve_max_vl);
>  
>  		clear_thread_flag(TIF_FOREIGN_FPSTATE);
> -		clear_thread_flag(TIF_SVE);
> +		update_thread_flag(TIF_SVE, vcpu_has_sve(vcpu));
>  	}
>  }
>  
> diff --git a/arch/arm64/kvm/hyp/switch.c b/arch/arm64/kvm/hyp/switch.c
> index 9f07403..cdc9063 100644
> --- a/arch/arm64/kvm/hyp/switch.c
> +++ b/arch/arm64/kvm/hyp/switch.c
> @@ -98,7 +98,10 @@ static void activate_traps_vhe(struct kvm_vcpu *vcpu)
>  	val = read_sysreg(cpacr_el1);
>  	val |= CPACR_EL1_TTA;
>  	val &= ~CPACR_EL1_ZEN;
> -	if (!update_fp_enabled(vcpu)) {
> +	if (update_fp_enabled(vcpu)) {
> +		if (vcpu_has_sve(vcpu))
> +			val |= CPACR_EL1_ZEN;
> +	} else {
>  		val &= ~CPACR_EL1_FPEN;
>  		__activate_traps_fpsimd32(vcpu);
>  	}
> @@ -313,16 +316,43 @@ static bool __hyp_text __populate_fault_info(struct kvm_vcpu *vcpu)
>  	return true;
>  }
>  
> -static bool __hyp_text __hyp_switch_fpsimd(struct kvm_vcpu *vcpu)
> +/* Check for an FPSIMD/SVE trap and handle as appropriate */
> +static bool __hyp_text __hyp_handle_fpsimd(struct kvm_vcpu *vcpu)
>  {
> -	struct user_fpsimd_state *host_fpsimd = vcpu->arch.host_fpsimd_state;
> +	bool vhe, sve_guest, sve_host;
> +	u8 trap_class;
>  
> -	if (has_vhe())
> -		write_sysreg(read_sysreg(cpacr_el1) | CPACR_EL1_FPEN,
> -			     cpacr_el1);
> -	else
> +	if (!system_supports_fpsimd())
> +		return false;
> +
> +	if (system_supports_sve()) {
> +		sve_guest = vcpu_has_sve(vcpu);
> +		sve_host = vcpu->arch.flags & KVM_ARM64_HOST_SVE_IN_USE;
> +		vhe = true;
> +	} else {
> +		sve_guest = false;
> +		sve_host = false;
> +		vhe = has_vhe();
> +	}
> +
> +	trap_class = kvm_vcpu_trap_get_class(vcpu);
> +	if (trap_class != ESR_ELx_EC_FP_ASIMD &&
> +	    (!sve_guest || trap_class != ESR_ELx_EC_SVE))
> +		return false;
> +
> +	/* The trap is an FPSIMD/SVE trap: switch the context */
> +
> +	if (vhe) {
> +		u64 reg = read_sysreg(cpacr_el1) | CPACR_EL1_FPEN;
> +
> +		if (sve_guest)
> +			reg |= CPACR_EL1_ZEN;
> +
> +		write_sysreg(reg, cpacr_el1);
> +	} else {
>  		write_sysreg(read_sysreg(cptr_el2) & ~(u64)CPTR_EL2_TFP,
>  			     cptr_el2);
> +	}
>  
>  	isb();
>  
> @@ -331,24 +361,28 @@ static bool __hyp_text __hyp_switch_fpsimd(struct kvm_vcpu *vcpu)
>  		 * In the SVE case, VHE is assumed: it is enforced by
>  		 * Kconfig and kvm_arch_init().
>  		 */
> -		if (system_supports_sve() &&
> -		    (vcpu->arch.flags & KVM_ARM64_HOST_SVE_IN_USE)) {
> +		if (sve_host) {
>  			struct thread_struct *thread = container_of(
> -				host_fpsimd,
> +				vcpu->arch.host_fpsimd_state,
>  				struct thread_struct, uw.fpsimd_state);
>  
> -			sve_save_state(sve_pffr(thread), &host_fpsimd->fpsr);
> +			sve_save_state(sve_pffr(thread),
> +				       &vcpu->arch.host_fpsimd_state->fpsr);
>  		} else {
> -			__fpsimd_save_state(host_fpsimd);
> +			__fpsimd_save_state(vcpu->arch.host_fpsimd_state);
>  		}
>  
>  		vcpu->arch.flags &= ~KVM_ARM64_FP_HOST;
>  	}
>  
> -	__fpsimd_restore_state(&vcpu->arch.ctxt.gp_regs.fp_regs);
> -
> -	if (vcpu_has_sve(vcpu))
> +	if (sve_guest) {
> +		sve_load_state(vcpu_sve_pffr(vcpu),
> +			       &vcpu->arch.ctxt.gp_regs.fp_regs.fpsr,
> +			       sve_vq_from_vl(vcpu->arch.sve_max_vl) - 1);
>  		write_sysreg_s(vcpu->arch.ctxt.sys_regs[ZCR_EL1], SYS_ZCR_EL12);
> +	} else {
> +		__fpsimd_restore_state(&vcpu->arch.ctxt.gp_regs.fp_regs);
> +	}
>  
>  	/* Skip restoring fpexc32 for AArch64 guests */
>  	if (!(read_sysreg(hcr_el2) & HCR_RW))
> @@ -384,10 +418,10 @@ static bool __hyp_text fixup_guest_exit(struct kvm_vcpu *vcpu, u64 *exit_code)
>  	 * and restore the guest context lazily.
>  	 * If FP/SIMD is not implemented, handle the trap and inject an
>  	 * undefined instruction exception to the guest.
> +	 * Similarly for trapped SVE accesses.
>  	 */
> -	if (system_supports_fpsimd() &&
> -	    kvm_vcpu_trap_get_class(vcpu) == ESR_ELx_EC_FP_ASIMD)
> -		return __hyp_switch_fpsimd(vcpu);
> +	if (__hyp_handle_fpsimd(vcpu))
> +		return true;
>  
>  	if (!__populate_fault_info(vcpu))
>  		return true;
> 

-- 
Julien Thierry

_______________________________________________
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] 205+ messages in thread

* Re: [PATCH v5 13/26] KVM: arm64/sve: System register context switch and access support
  2019-02-18 19:52   ` Dave Martin
@ 2019-02-20 16:48     ` Julien Thierry
  -1 siblings, 0 replies; 205+ messages in thread
From: Julien Thierry @ 2019-02-20 16:48 UTC (permalink / raw)
  To: Dave Martin, kvmarm
  Cc: Okamoto Takayuki, Christoffer Dall, Ard Biesheuvel, Marc Zyngier,
	Catalin Marinas, Will Deacon, Zhang Lei, linux-arm-kernel



On 18/02/2019 19:52, Dave Martin wrote:
> This patch adds the necessary support for context switching ZCR_EL1
> for each vcpu.
> 
> ZCR_EL1 is trapped alongside the FPSIMD/SVE registers, so it makes
> sense for it to be handled as part of the guest FPSIMD/SVE context
> for context switch purposes instead of handling it as a general
> system register.  This means that it can be switched in lazily at
> the appropriate time.  No effort is made to track host context for
> this register, since SVE requires VHE: thus the hosts's value for
> this register lives permanently in ZCR_EL2 and does not alias the
> guest's value at any time.
> 
> The Hyp switch and fpsimd context handling code is extended
> appropriately.
> 
> Accessors are added in sys_regs.c to expose the SVE system
> registers and ID register fields.  Because these need to be
> conditionally visible based on the guest configuration, they are
> implemented separately for now rather than by use of the generic
> system register helpers.  This may be abstracted better later on
> when/if there are more features requiring this model.
> 
> ID_AA64ZFR0_EL1 is RO-RAZ for MRS/MSR when SVE is disabled for the
> guest, but for compatibility with non-SVE aware KVM implementations
> the register should not be enumerated at all for KVM_GET_REG_LIST
> in this case.  For consistency we also reject ioctl access to the
> register.  This ensures that a non-SVE-enabled guest looks the same
> to userspace, irrespective of whether the kernel KVM implementation
> supports SVE.
> 
> Signed-off-by: Dave Martin <Dave.Martin@arm.com>
> 

Reviewed-by: Julien Thierry <julien.thierry@arm.com>

> ---
> 
> Changes since v4:
> 
>  * Remove annoying linebreak in assignment.
> 
>  * Remove #ifdef clutter and migrate to using the new sysreg
>    restrictions() framework to control register visibility.
> ---
>  arch/arm64/include/asm/kvm_host.h |  1 +
>  arch/arm64/include/asm/sysreg.h   |  3 ++
>  arch/arm64/kvm/fpsimd.c           |  9 +++-
>  arch/arm64/kvm/hyp/switch.c       |  3 ++
>  arch/arm64/kvm/sys_regs.c         | 97 +++++++++++++++++++++++++++++++++++++--
>  5 files changed, 107 insertions(+), 6 deletions(-)
> 
> diff --git a/arch/arm64/include/asm/kvm_host.h b/arch/arm64/include/asm/kvm_host.h
> index af625a8..c32f195 100644
> --- a/arch/arm64/include/asm/kvm_host.h
> +++ b/arch/arm64/include/asm/kvm_host.h
> @@ -112,6 +112,7 @@ enum vcpu_sysreg {
>  	SCTLR_EL1,	/* System Control Register */
>  	ACTLR_EL1,	/* Auxiliary Control Register */
>  	CPACR_EL1,	/* Coprocessor Access Control */
> +	ZCR_EL1,	/* SVE Control */
>  	TTBR0_EL1,	/* Translation Table Base Register 0 */
>  	TTBR1_EL1,	/* Translation Table Base Register 1 */
>  	TCR_EL1,	/* Translation Control Register */
> diff --git a/arch/arm64/include/asm/sysreg.h b/arch/arm64/include/asm/sysreg.h
> index 72dc4c0..da38491 100644
> --- a/arch/arm64/include/asm/sysreg.h
> +++ b/arch/arm64/include/asm/sysreg.h
> @@ -449,6 +449,9 @@
>  #define SYS_ICH_LR14_EL2		__SYS__LR8_EL2(6)
>  #define SYS_ICH_LR15_EL2		__SYS__LR8_EL2(7)
>  
> +/* VHE encodings for architectural EL0/1 system registers */
> +#define SYS_ZCR_EL12			sys_reg(3, 5, 1, 2, 0)
> +
>  /* Common SCTLR_ELx flags. */
>  #define SCTLR_ELx_DSSBS	(_BITUL(44))
>  #define SCTLR_ELx_ENIA	(_BITUL(31))
> diff --git a/arch/arm64/kvm/fpsimd.c b/arch/arm64/kvm/fpsimd.c
> index 1cf4f02..7053bf4 100644
> --- a/arch/arm64/kvm/fpsimd.c
> +++ b/arch/arm64/kvm/fpsimd.c
> @@ -103,14 +103,21 @@ void kvm_arch_vcpu_ctxsync_fp(struct kvm_vcpu *vcpu)
>  void kvm_arch_vcpu_put_fp(struct kvm_vcpu *vcpu)
>  {
>  	unsigned long flags;
> +	bool host_has_sve = system_supports_sve();
> +	bool guest_has_sve = vcpu_has_sve(vcpu);
>  
>  	local_irq_save(flags);
>  
>  	if (vcpu->arch.flags & KVM_ARM64_FP_ENABLED) {
> +		u64 *guest_zcr = &vcpu->arch.ctxt.sys_regs[ZCR_EL1];
> +
>  		/* Clean guest FP state to memory and invalidate cpu view */
>  		fpsimd_save();
>  		fpsimd_flush_cpu_state();
> -	} else if (system_supports_sve()) {
> +
> +		if (guest_has_sve)
> +			*guest_zcr = read_sysreg_s(SYS_ZCR_EL12);
> +	} else if (host_has_sve) {
>  		/*
>  		 * The FPSIMD/SVE state in the CPU has not been touched, and we
>  		 * have SVE (and VHE): CPACR_EL1 (alias CPTR_EL2) has been
> diff --git a/arch/arm64/kvm/hyp/switch.c b/arch/arm64/kvm/hyp/switch.c
> index b0b1478..9f07403 100644
> --- a/arch/arm64/kvm/hyp/switch.c
> +++ b/arch/arm64/kvm/hyp/switch.c
> @@ -347,6 +347,9 @@ static bool __hyp_text __hyp_switch_fpsimd(struct kvm_vcpu *vcpu)
>  
>  	__fpsimd_restore_state(&vcpu->arch.ctxt.gp_regs.fp_regs);
>  
> +	if (vcpu_has_sve(vcpu))
> +		write_sysreg_s(vcpu->arch.ctxt.sys_regs[ZCR_EL1], SYS_ZCR_EL12);
> +
>  	/* Skip restoring fpexc32 for AArch64 guests */
>  	if (!(read_sysreg(hcr_el2) & HCR_RW))
>  		write_sysreg(vcpu->arch.ctxt.sys_regs[FPEXC32_EL2],
> diff --git a/arch/arm64/kvm/sys_regs.c b/arch/arm64/kvm/sys_regs.c
> index 3f1243e..28b1bad 100644
> --- a/arch/arm64/kvm/sys_regs.c
> +++ b/arch/arm64/kvm/sys_regs.c
> @@ -1036,10 +1036,7 @@ static u64 read_id_reg(const struct kvm_vcpu *vcpu,
>  			 (u32)r->CRn, (u32)r->CRm, (u32)r->Op2);
>  	u64 val = raz ? 0 : read_sanitised_ftr_reg(id);
>  
> -	if (id == SYS_ID_AA64PFR0_EL1) {
> -		if (val & (0xfUL << ID_AA64PFR0_SVE_SHIFT))
> -			kvm_debug("SVE unsupported for guests, suppressing\n");
> -
> +	if (id == SYS_ID_AA64PFR0_EL1 && !vcpu_has_sve(vcpu)) {
>  		val &= ~(0xfUL << ID_AA64PFR0_SVE_SHIFT);
>  	} else if (id == SYS_ID_AA64ISAR1_EL1) {
>  		const u64 ptrauth_mask = (0xfUL << ID_AA64ISAR1_APA_SHIFT) |
> @@ -1091,6 +1088,95 @@ static int reg_from_user(u64 *val, const void __user *uaddr, u64 id);
>  static int reg_to_user(void __user *uaddr, const u64 *val, u64 id);
>  static u64 sys_reg_to_index(const struct sys_reg_desc *reg);
>  
> +static unsigned int sve_restrictions(const struct kvm_vcpu *vcpu,
> +				     const struct sys_reg_desc *rd)
> +{
> +	return vcpu_has_sve(vcpu) ? 0 : REG_NO_USER | REG_NO_GUEST;
> +}
> +
> +static unsigned int sve_id_restrictions(const struct kvm_vcpu *vcpu,
> +					const struct sys_reg_desc *rd)
> +{
> +	return vcpu_has_sve(vcpu) ? 0 : REG_NO_USER;
> +}
> +
> +static int get_zcr_el1(struct kvm_vcpu *vcpu,
> +		       const struct sys_reg_desc *rd,
> +		       const struct kvm_one_reg *reg, void __user *uaddr)
> +{
> +	if (WARN_ON(!vcpu_has_sve(vcpu)))
> +		return -ENOENT;
> +
> +	return reg_to_user(uaddr, &vcpu->arch.ctxt.sys_regs[ZCR_EL1],
> +			   reg->id);
> +}
> +
> +static int set_zcr_el1(struct kvm_vcpu *vcpu,
> +		       const struct sys_reg_desc *rd,
> +		       const struct kvm_one_reg *reg, void __user *uaddr)
> +{
> +	if (WARN_ON(!vcpu_has_sve(vcpu)))
> +		return -ENOENT;
> +
> +	return reg_from_user(&vcpu->arch.ctxt.sys_regs[ZCR_EL1], uaddr,
> +			     reg->id);
> +}
> +
> +/* Generate the emulated ID_AA64ZFR0_EL1 value exposed to the guest */
> +static u64 guest_id_aa64zfr0_el1(const struct kvm_vcpu *vcpu)
> +{
> +	if (!vcpu_has_sve(vcpu))
> +		return 0;
> +
> +	return read_sanitised_ftr_reg(SYS_ID_AA64ZFR0_EL1);
> +}
> +
> +static bool access_id_aa64zfr0_el1(struct kvm_vcpu *vcpu,
> +				   struct sys_reg_params *p,
> +				   const struct sys_reg_desc *rd)
> +{
> +	if (p->is_write)
> +		return write_to_read_only(vcpu, p, rd);
> +
> +	p->regval = guest_id_aa64zfr0_el1(vcpu);
> +	return true;
> +}
> +
> +static int get_id_aa64zfr0_el1(struct kvm_vcpu *vcpu,
> +		const struct sys_reg_desc *rd,
> +		const struct kvm_one_reg *reg, void __user *uaddr)
> +{
> +	u64 val;
> +
> +	if (!vcpu_has_sve(vcpu))
> +		return -ENOENT;
> +
> +	val = guest_id_aa64zfr0_el1(vcpu);
> +	return reg_to_user(uaddr, &val, reg->id);
> +}
> +
> +static int set_id_aa64zfr0_el1(struct kvm_vcpu *vcpu,
> +		const struct sys_reg_desc *rd,
> +		const struct kvm_one_reg *reg, void __user *uaddr)
> +{
> +	const u64 id = sys_reg_to_index(rd);
> +	int err;
> +	u64 val;
> +
> +	if (!vcpu_has_sve(vcpu))
> +		return -ENOENT;
> +
> +	err = reg_from_user(&val, uaddr, id);
> +	if (err)
> +		return err;
> +
> +	/* This is what we mean by invariant: you can't change it. */
> +	if (val != guest_id_aa64zfr0_el1(vcpu))
> +		return -EINVAL;
> +
> +	return 0;
> +}
> +
>  /*
>   * cpufeature ID register user accessors
>   *
> @@ -1278,7 +1364,7 @@ static const struct sys_reg_desc sys_reg_descs[] = {
>  	ID_SANITISED(ID_AA64PFR1_EL1),
>  	ID_UNALLOCATED(4,2),
>  	ID_UNALLOCATED(4,3),
> -	ID_UNALLOCATED(4,4),
> +	{ SYS_DESC(SYS_ID_AA64ZFR0_EL1), access_id_aa64zfr0_el1, .get_user = get_id_aa64zfr0_el1, .set_user = set_id_aa64zfr0_el1, .restrictions = sve_id_restrictions },
>  	ID_UNALLOCATED(4,5),
>  	ID_UNALLOCATED(4,6),
>  	ID_UNALLOCATED(4,7),
> @@ -1315,6 +1401,7 @@ static const struct sys_reg_desc sys_reg_descs[] = {
>  
>  	{ SYS_DESC(SYS_SCTLR_EL1), access_vm_reg, reset_val, SCTLR_EL1, 0x00C50078 },
>  	{ SYS_DESC(SYS_CPACR_EL1), NULL, reset_val, CPACR_EL1, 0 },
> +	{ SYS_DESC(SYS_ZCR_EL1), NULL, reset_unknown, ZCR_EL1, ~0xfUL, .get_user = get_zcr_el1, .set_user = set_zcr_el1, .restrictions = sve_restrictions },
>  	{ SYS_DESC(SYS_TTBR0_EL1), access_vm_reg, reset_unknown, TTBR0_EL1 },
>  	{ SYS_DESC(SYS_TTBR1_EL1), access_vm_reg, reset_unknown, TTBR1_EL1 },
>  	{ SYS_DESC(SYS_TCR_EL1), access_vm_reg, reset_val, TCR_EL1, 0 },
> 

-- 
Julien Thierry

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

* Re: [PATCH v5 13/26] KVM: arm64/sve: System register context switch and access support
@ 2019-02-20 16:48     ` Julien Thierry
  0 siblings, 0 replies; 205+ messages in thread
From: Julien Thierry @ 2019-02-20 16:48 UTC (permalink / raw)
  To: Dave Martin, kvmarm
  Cc: Okamoto Takayuki, Christoffer Dall, Ard Biesheuvel, Marc Zyngier,
	Catalin Marinas, Will Deacon, Zhang Lei, linux-arm-kernel



On 18/02/2019 19:52, Dave Martin wrote:
> This patch adds the necessary support for context switching ZCR_EL1
> for each vcpu.
> 
> ZCR_EL1 is trapped alongside the FPSIMD/SVE registers, so it makes
> sense for it to be handled as part of the guest FPSIMD/SVE context
> for context switch purposes instead of handling it as a general
> system register.  This means that it can be switched in lazily at
> the appropriate time.  No effort is made to track host context for
> this register, since SVE requires VHE: thus the hosts's value for
> this register lives permanently in ZCR_EL2 and does not alias the
> guest's value at any time.
> 
> The Hyp switch and fpsimd context handling code is extended
> appropriately.
> 
> Accessors are added in sys_regs.c to expose the SVE system
> registers and ID register fields.  Because these need to be
> conditionally visible based on the guest configuration, they are
> implemented separately for now rather than by use of the generic
> system register helpers.  This may be abstracted better later on
> when/if there are more features requiring this model.
> 
> ID_AA64ZFR0_EL1 is RO-RAZ for MRS/MSR when SVE is disabled for the
> guest, but for compatibility with non-SVE aware KVM implementations
> the register should not be enumerated at all for KVM_GET_REG_LIST
> in this case.  For consistency we also reject ioctl access to the
> register.  This ensures that a non-SVE-enabled guest looks the same
> to userspace, irrespective of whether the kernel KVM implementation
> supports SVE.
> 
> Signed-off-by: Dave Martin <Dave.Martin@arm.com>
> 

Reviewed-by: Julien Thierry <julien.thierry@arm.com>

> ---
> 
> Changes since v4:
> 
>  * Remove annoying linebreak in assignment.
> 
>  * Remove #ifdef clutter and migrate to using the new sysreg
>    restrictions() framework to control register visibility.
> ---
>  arch/arm64/include/asm/kvm_host.h |  1 +
>  arch/arm64/include/asm/sysreg.h   |  3 ++
>  arch/arm64/kvm/fpsimd.c           |  9 +++-
>  arch/arm64/kvm/hyp/switch.c       |  3 ++
>  arch/arm64/kvm/sys_regs.c         | 97 +++++++++++++++++++++++++++++++++++++--
>  5 files changed, 107 insertions(+), 6 deletions(-)
> 
> diff --git a/arch/arm64/include/asm/kvm_host.h b/arch/arm64/include/asm/kvm_host.h
> index af625a8..c32f195 100644
> --- a/arch/arm64/include/asm/kvm_host.h
> +++ b/arch/arm64/include/asm/kvm_host.h
> @@ -112,6 +112,7 @@ enum vcpu_sysreg {
>  	SCTLR_EL1,	/* System Control Register */
>  	ACTLR_EL1,	/* Auxiliary Control Register */
>  	CPACR_EL1,	/* Coprocessor Access Control */
> +	ZCR_EL1,	/* SVE Control */
>  	TTBR0_EL1,	/* Translation Table Base Register 0 */
>  	TTBR1_EL1,	/* Translation Table Base Register 1 */
>  	TCR_EL1,	/* Translation Control Register */
> diff --git a/arch/arm64/include/asm/sysreg.h b/arch/arm64/include/asm/sysreg.h
> index 72dc4c0..da38491 100644
> --- a/arch/arm64/include/asm/sysreg.h
> +++ b/arch/arm64/include/asm/sysreg.h
> @@ -449,6 +449,9 @@
>  #define SYS_ICH_LR14_EL2		__SYS__LR8_EL2(6)
>  #define SYS_ICH_LR15_EL2		__SYS__LR8_EL2(7)
>  
> +/* VHE encodings for architectural EL0/1 system registers */
> +#define SYS_ZCR_EL12			sys_reg(3, 5, 1, 2, 0)
> +
>  /* Common SCTLR_ELx flags. */
>  #define SCTLR_ELx_DSSBS	(_BITUL(44))
>  #define SCTLR_ELx_ENIA	(_BITUL(31))
> diff --git a/arch/arm64/kvm/fpsimd.c b/arch/arm64/kvm/fpsimd.c
> index 1cf4f02..7053bf4 100644
> --- a/arch/arm64/kvm/fpsimd.c
> +++ b/arch/arm64/kvm/fpsimd.c
> @@ -103,14 +103,21 @@ void kvm_arch_vcpu_ctxsync_fp(struct kvm_vcpu *vcpu)
>  void kvm_arch_vcpu_put_fp(struct kvm_vcpu *vcpu)
>  {
>  	unsigned long flags;
> +	bool host_has_sve = system_supports_sve();
> +	bool guest_has_sve = vcpu_has_sve(vcpu);
>  
>  	local_irq_save(flags);
>  
>  	if (vcpu->arch.flags & KVM_ARM64_FP_ENABLED) {
> +		u64 *guest_zcr = &vcpu->arch.ctxt.sys_regs[ZCR_EL1];
> +
>  		/* Clean guest FP state to memory and invalidate cpu view */
>  		fpsimd_save();
>  		fpsimd_flush_cpu_state();
> -	} else if (system_supports_sve()) {
> +
> +		if (guest_has_sve)
> +			*guest_zcr = read_sysreg_s(SYS_ZCR_EL12);
> +	} else if (host_has_sve) {
>  		/*
>  		 * The FPSIMD/SVE state in the CPU has not been touched, and we
>  		 * have SVE (and VHE): CPACR_EL1 (alias CPTR_EL2) has been
> diff --git a/arch/arm64/kvm/hyp/switch.c b/arch/arm64/kvm/hyp/switch.c
> index b0b1478..9f07403 100644
> --- a/arch/arm64/kvm/hyp/switch.c
> +++ b/arch/arm64/kvm/hyp/switch.c
> @@ -347,6 +347,9 @@ static bool __hyp_text __hyp_switch_fpsimd(struct kvm_vcpu *vcpu)
>  
>  	__fpsimd_restore_state(&vcpu->arch.ctxt.gp_regs.fp_regs);
>  
> +	if (vcpu_has_sve(vcpu))
> +		write_sysreg_s(vcpu->arch.ctxt.sys_regs[ZCR_EL1], SYS_ZCR_EL12);
> +
>  	/* Skip restoring fpexc32 for AArch64 guests */
>  	if (!(read_sysreg(hcr_el2) & HCR_RW))
>  		write_sysreg(vcpu->arch.ctxt.sys_regs[FPEXC32_EL2],
> diff --git a/arch/arm64/kvm/sys_regs.c b/arch/arm64/kvm/sys_regs.c
> index 3f1243e..28b1bad 100644
> --- a/arch/arm64/kvm/sys_regs.c
> +++ b/arch/arm64/kvm/sys_regs.c
> @@ -1036,10 +1036,7 @@ static u64 read_id_reg(const struct kvm_vcpu *vcpu,
>  			 (u32)r->CRn, (u32)r->CRm, (u32)r->Op2);
>  	u64 val = raz ? 0 : read_sanitised_ftr_reg(id);
>  
> -	if (id == SYS_ID_AA64PFR0_EL1) {
> -		if (val & (0xfUL << ID_AA64PFR0_SVE_SHIFT))
> -			kvm_debug("SVE unsupported for guests, suppressing\n");
> -
> +	if (id == SYS_ID_AA64PFR0_EL1 && !vcpu_has_sve(vcpu)) {
>  		val &= ~(0xfUL << ID_AA64PFR0_SVE_SHIFT);
>  	} else if (id == SYS_ID_AA64ISAR1_EL1) {
>  		const u64 ptrauth_mask = (0xfUL << ID_AA64ISAR1_APA_SHIFT) |
> @@ -1091,6 +1088,95 @@ static int reg_from_user(u64 *val, const void __user *uaddr, u64 id);
>  static int reg_to_user(void __user *uaddr, const u64 *val, u64 id);
>  static u64 sys_reg_to_index(const struct sys_reg_desc *reg);
>  
> +static unsigned int sve_restrictions(const struct kvm_vcpu *vcpu,
> +				     const struct sys_reg_desc *rd)
> +{
> +	return vcpu_has_sve(vcpu) ? 0 : REG_NO_USER | REG_NO_GUEST;
> +}
> +
> +static unsigned int sve_id_restrictions(const struct kvm_vcpu *vcpu,
> +					const struct sys_reg_desc *rd)
> +{
> +	return vcpu_has_sve(vcpu) ? 0 : REG_NO_USER;
> +}
> +
> +static int get_zcr_el1(struct kvm_vcpu *vcpu,
> +		       const struct sys_reg_desc *rd,
> +		       const struct kvm_one_reg *reg, void __user *uaddr)
> +{
> +	if (WARN_ON(!vcpu_has_sve(vcpu)))
> +		return -ENOENT;
> +
> +	return reg_to_user(uaddr, &vcpu->arch.ctxt.sys_regs[ZCR_EL1],
> +			   reg->id);
> +}
> +
> +static int set_zcr_el1(struct kvm_vcpu *vcpu,
> +		       const struct sys_reg_desc *rd,
> +		       const struct kvm_one_reg *reg, void __user *uaddr)
> +{
> +	if (WARN_ON(!vcpu_has_sve(vcpu)))
> +		return -ENOENT;
> +
> +	return reg_from_user(&vcpu->arch.ctxt.sys_regs[ZCR_EL1], uaddr,
> +			     reg->id);
> +}
> +
> +/* Generate the emulated ID_AA64ZFR0_EL1 value exposed to the guest */
> +static u64 guest_id_aa64zfr0_el1(const struct kvm_vcpu *vcpu)
> +{
> +	if (!vcpu_has_sve(vcpu))
> +		return 0;
> +
> +	return read_sanitised_ftr_reg(SYS_ID_AA64ZFR0_EL1);
> +}
> +
> +static bool access_id_aa64zfr0_el1(struct kvm_vcpu *vcpu,
> +				   struct sys_reg_params *p,
> +				   const struct sys_reg_desc *rd)
> +{
> +	if (p->is_write)
> +		return write_to_read_only(vcpu, p, rd);
> +
> +	p->regval = guest_id_aa64zfr0_el1(vcpu);
> +	return true;
> +}
> +
> +static int get_id_aa64zfr0_el1(struct kvm_vcpu *vcpu,
> +		const struct sys_reg_desc *rd,
> +		const struct kvm_one_reg *reg, void __user *uaddr)
> +{
> +	u64 val;
> +
> +	if (!vcpu_has_sve(vcpu))
> +		return -ENOENT;
> +
> +	val = guest_id_aa64zfr0_el1(vcpu);
> +	return reg_to_user(uaddr, &val, reg->id);
> +}
> +
> +static int set_id_aa64zfr0_el1(struct kvm_vcpu *vcpu,
> +		const struct sys_reg_desc *rd,
> +		const struct kvm_one_reg *reg, void __user *uaddr)
> +{
> +	const u64 id = sys_reg_to_index(rd);
> +	int err;
> +	u64 val;
> +
> +	if (!vcpu_has_sve(vcpu))
> +		return -ENOENT;
> +
> +	err = reg_from_user(&val, uaddr, id);
> +	if (err)
> +		return err;
> +
> +	/* This is what we mean by invariant: you can't change it. */
> +	if (val != guest_id_aa64zfr0_el1(vcpu))
> +		return -EINVAL;
> +
> +	return 0;
> +}
> +
>  /*
>   * cpufeature ID register user accessors
>   *
> @@ -1278,7 +1364,7 @@ static const struct sys_reg_desc sys_reg_descs[] = {
>  	ID_SANITISED(ID_AA64PFR1_EL1),
>  	ID_UNALLOCATED(4,2),
>  	ID_UNALLOCATED(4,3),
> -	ID_UNALLOCATED(4,4),
> +	{ SYS_DESC(SYS_ID_AA64ZFR0_EL1), access_id_aa64zfr0_el1, .get_user = get_id_aa64zfr0_el1, .set_user = set_id_aa64zfr0_el1, .restrictions = sve_id_restrictions },
>  	ID_UNALLOCATED(4,5),
>  	ID_UNALLOCATED(4,6),
>  	ID_UNALLOCATED(4,7),
> @@ -1315,6 +1401,7 @@ static const struct sys_reg_desc sys_reg_descs[] = {
>  
>  	{ SYS_DESC(SYS_SCTLR_EL1), access_vm_reg, reset_val, SCTLR_EL1, 0x00C50078 },
>  	{ SYS_DESC(SYS_CPACR_EL1), NULL, reset_val, CPACR_EL1, 0 },
> +	{ SYS_DESC(SYS_ZCR_EL1), NULL, reset_unknown, ZCR_EL1, ~0xfUL, .get_user = get_zcr_el1, .set_user = set_zcr_el1, .restrictions = sve_restrictions },
>  	{ SYS_DESC(SYS_TTBR0_EL1), access_vm_reg, reset_unknown, TTBR0_EL1 },
>  	{ SYS_DESC(SYS_TTBR1_EL1), access_vm_reg, reset_unknown, TTBR1_EL1 },
>  	{ SYS_DESC(SYS_TCR_EL1), access_vm_reg, reset_val, TCR_EL1, 0 },
> 

-- 
Julien Thierry

_______________________________________________
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] 205+ messages in thread

* Re: [PATCH v5 01/26] KVM: Documentation: Document arm64 core registers in detail
  2019-02-18 19:52   ` Dave Martin
@ 2019-02-21 11:48     ` Julien Grall
  -1 siblings, 0 replies; 205+ messages in thread
From: Julien Grall @ 2019-02-21 11:48 UTC (permalink / raw)
  To: Dave Martin, kvmarm
  Cc: Okamoto Takayuki, Christoffer Dall, Ard Biesheuvel, Marc Zyngier,
	Catalin Marinas, Will Deacon, Zhang Lei, linux-arm-kernel

Hi Dave,

On 18/02/2019 19:52, Dave Martin wrote:
> Since the the sizes of individual members of the core arm64
> registers vary, the list of register encodings that make sense is
> not a simple linear sequence.
> 
> To clarify which encodings to use, this patch adds a brief list
> to the documentation.
> 
> Signed-off-by: Dave Martin <Dave.Martin@arm.com>

Reviewed-by: Julien Grall <julien.grall@arm.com>

Cheers,

-- 
Julien Grall

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

* Re: [PATCH v5 01/26] KVM: Documentation: Document arm64 core registers in detail
@ 2019-02-21 11:48     ` Julien Grall
  0 siblings, 0 replies; 205+ messages in thread
From: Julien Grall @ 2019-02-21 11:48 UTC (permalink / raw)
  To: Dave Martin, kvmarm
  Cc: Peter Maydell, Okamoto Takayuki, Christoffer Dall,
	Ard Biesheuvel, Marc Zyngier, Catalin Marinas, Will Deacon,
	Zhang Lei, Alex Bennée, linux-arm-kernel

Hi Dave,

On 18/02/2019 19:52, Dave Martin wrote:
> Since the the sizes of individual members of the core arm64
> registers vary, the list of register encodings that make sense is
> not a simple linear sequence.
> 
> To clarify which encodings to use, this patch adds a brief list
> to the documentation.
> 
> Signed-off-by: Dave Martin <Dave.Martin@arm.com>

Reviewed-by: Julien Grall <julien.grall@arm.com>

Cheers,

-- 
Julien Grall

_______________________________________________
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] 205+ messages in thread

* Re: [PATCH v5 01/26] KVM: Documentation: Document arm64 core registers in detail
  2019-02-18 19:52   ` Dave Martin
@ 2019-02-21 11:57     ` Peter Maydell
  -1 siblings, 0 replies; 205+ messages in thread
From: Peter Maydell @ 2019-02-21 11:57 UTC (permalink / raw)
  To: Dave Martin
  Cc: Okamoto Takayuki, Christoffer Dall, Ard Biesheuvel, Marc Zyngier,
	Catalin Marinas, Will Deacon, Zhang Lei, kvmarm, arm-mail-list

On Mon, 18 Feb 2019 at 19:54, Dave Martin <Dave.Martin@arm.com> wrote:
>
> Since the the sizes of individual members of the core arm64
> registers vary, the list of register encodings that make sense is
> not a simple linear sequence.
>
> To clarify which encodings to use, this patch adds a brief list
> to the documentation.
>
> Signed-off-by: Dave Martin <Dave.Martin@arm.com>
> ---
>  Documentation/virtual/kvm/api.txt | 24 ++++++++++++++++++++++++
>  1 file changed, 24 insertions(+)
>
> diff --git a/Documentation/virtual/kvm/api.txt b/Documentation/virtual/kvm/api.txt
> index 356156f..097b8ba 100644
> --- a/Documentation/virtual/kvm/api.txt
> +++ b/Documentation/virtual/kvm/api.txt
> @@ -2090,6 +2090,30 @@ contains elements ranging from 32 to 128 bits. The index is a 32bit
>  value in the kvm_regs structure seen as a 32bit array.
>    0x60x0 0000 0010 <index into the kvm_regs struct:16>
>
> +Specifically:
> +    Encoding            Register  Bits  kvm_regs member
> +----------------------------------------------------------------
> +  0x6030 0000 0010 0000 X0          64  regs.regs[0]
> +  0x6030 0000 0010 0002 X1          64  regs.regs[1]
> +    ...
> +  0x6030 0000 0010 003c X30         64  regs.regs[30]
> +  0x6030 0000 0010 003e SP          64  regs.sp
> +  0x6030 0000 0010 0040 PC          64  regs.pc
> +  0x6030 0000 0010 0042 PSTATE      64  regs.pstate
> +  0x6030 0000 0010 0044 SP_EL1      64  sp_el1
> +  0x6030 0000 0010 0046 ELR_EL1     64  elr_el1
> +  0x6030 0000 0010 0048 SPSR_EL1    64  spsr[KVM_SPSR_EL1] (alias SPSR_SVC)
> +  0x6030 0000 0010 004a SPSR_ABT    64  spsr[KVM_SPSR_ABT]
> +  0x6030 0000 0010 004c SPSR_UND    64  spsr[KVM_SPSR_UND]
> +  0x6030 0000 0010 004e SPSR_IRQ    64  spsr[KVM_SPSR_IRQ]
> +  0x6060 0000 0010 0050 SPSR_FIQ    64  spsr[KVM_SPSR_FIQ]
> +  0x6040 0000 0010 0054 V0         128  fp_regs.vregs[0]
> +  0x6040 0000 0010 0058 V1         128  fp_regs.vregs[1]
> +    ...
> +  0x6040 0000 0010 00d0 V31        128  fp_regs.vregs[31]
> +  0x6020 0000 0010 00d4 FPSR        32  fp_regs.fpsr
> +  0x6020 0000 0010 00d5 FPCR        32  fp_regs.fpcr
> +
>  arm64 CCSIDR registers are demultiplexed by CSSELR value:
>    0x6020 0000 0011 00 <csselr:8>

Reviewed-by: Peter Maydell <peter.maydell@linaro.org>

It is weird that we document these in terms of apparently
arbitrary hex digits in the encoding, but the headers
exposed to userspace define helpful #defines for the various
subfields. So nobody really wants to use these hex
digits and they need to then go hunting in the headers
to confirm that if they use KVM_REG_ARM64 | KVM_REG_SIZE_U32 |
KVM_REG_ARM_CORE | KVM_REG_ARM_CORE_REG(fp_regs.fpsr)
they are getting the officially approved working encoding.
But it is how we're documenting everything else in this
section, so that's a separate issue.

thanks
-- PMM

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

* Re: [PATCH v5 01/26] KVM: Documentation: Document arm64 core registers in detail
@ 2019-02-21 11:57     ` Peter Maydell
  0 siblings, 0 replies; 205+ messages in thread
From: Peter Maydell @ 2019-02-21 11:57 UTC (permalink / raw)
  To: Dave Martin
  Cc: Okamoto Takayuki, Christoffer Dall, Ard Biesheuvel, Marc Zyngier,
	Catalin Marinas, Will Deacon, Zhang Lei, Julien Grall,
	Alex Bennée, kvmarm, arm-mail-list

On Mon, 18 Feb 2019 at 19:54, Dave Martin <Dave.Martin@arm.com> wrote:
>
> Since the the sizes of individual members of the core arm64
> registers vary, the list of register encodings that make sense is
> not a simple linear sequence.
>
> To clarify which encodings to use, this patch adds a brief list
> to the documentation.
>
> Signed-off-by: Dave Martin <Dave.Martin@arm.com>
> ---
>  Documentation/virtual/kvm/api.txt | 24 ++++++++++++++++++++++++
>  1 file changed, 24 insertions(+)
>
> diff --git a/Documentation/virtual/kvm/api.txt b/Documentation/virtual/kvm/api.txt
> index 356156f..097b8ba 100644
> --- a/Documentation/virtual/kvm/api.txt
> +++ b/Documentation/virtual/kvm/api.txt
> @@ -2090,6 +2090,30 @@ contains elements ranging from 32 to 128 bits. The index is a 32bit
>  value in the kvm_regs structure seen as a 32bit array.
>    0x60x0 0000 0010 <index into the kvm_regs struct:16>
>
> +Specifically:
> +    Encoding            Register  Bits  kvm_regs member
> +----------------------------------------------------------------
> +  0x6030 0000 0010 0000 X0          64  regs.regs[0]
> +  0x6030 0000 0010 0002 X1          64  regs.regs[1]
> +    ...
> +  0x6030 0000 0010 003c X30         64  regs.regs[30]
> +  0x6030 0000 0010 003e SP          64  regs.sp
> +  0x6030 0000 0010 0040 PC          64  regs.pc
> +  0x6030 0000 0010 0042 PSTATE      64  regs.pstate
> +  0x6030 0000 0010 0044 SP_EL1      64  sp_el1
> +  0x6030 0000 0010 0046 ELR_EL1     64  elr_el1
> +  0x6030 0000 0010 0048 SPSR_EL1    64  spsr[KVM_SPSR_EL1] (alias SPSR_SVC)
> +  0x6030 0000 0010 004a SPSR_ABT    64  spsr[KVM_SPSR_ABT]
> +  0x6030 0000 0010 004c SPSR_UND    64  spsr[KVM_SPSR_UND]
> +  0x6030 0000 0010 004e SPSR_IRQ    64  spsr[KVM_SPSR_IRQ]
> +  0x6060 0000 0010 0050 SPSR_FIQ    64  spsr[KVM_SPSR_FIQ]
> +  0x6040 0000 0010 0054 V0         128  fp_regs.vregs[0]
> +  0x6040 0000 0010 0058 V1         128  fp_regs.vregs[1]
> +    ...
> +  0x6040 0000 0010 00d0 V31        128  fp_regs.vregs[31]
> +  0x6020 0000 0010 00d4 FPSR        32  fp_regs.fpsr
> +  0x6020 0000 0010 00d5 FPCR        32  fp_regs.fpcr
> +
>  arm64 CCSIDR registers are demultiplexed by CSSELR value:
>    0x6020 0000 0011 00 <csselr:8>

Reviewed-by: Peter Maydell <peter.maydell@linaro.org>

It is weird that we document these in terms of apparently
arbitrary hex digits in the encoding, but the headers
exposed to userspace define helpful #defines for the various
subfields. So nobody really wants to use these hex
digits and they need to then go hunting in the headers
to confirm that if they use KVM_REG_ARM64 | KVM_REG_SIZE_U32 |
KVM_REG_ARM_CORE | KVM_REG_ARM_CORE_REG(fp_regs.fpsr)
they are getting the officially approved working encoding.
But it is how we're documenting everything else in this
section, so that's a separate issue.

thanks
-- PMM

_______________________________________________
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] 205+ messages in thread

* Re: [PATCH v5 17/26] KVM: arm64: Reject ioctl access to FPSIMD V-regs on SVE vcpus
  2019-02-18 19:52   ` Dave Martin
@ 2019-02-21 12:06     ` Julien Thierry
  -1 siblings, 0 replies; 205+ messages in thread
From: Julien Thierry @ 2019-02-21 12:06 UTC (permalink / raw)
  To: Dave Martin, kvmarm
  Cc: Okamoto Takayuki, Christoffer Dall, Ard Biesheuvel, Marc Zyngier,
	Catalin Marinas, Will Deacon, Zhang Lei, linux-arm-kernel



On 18/02/2019 19:52, Dave Martin wrote:
> In order to avoid the pointless complexity of maintaining two ioctl
> register access views of the same data, this patch blocks ioctl
> access to the FPSIMD V-registers on vcpus that support SVE.
> 
> This will make it more straightforward to add SVE register access
> support.
> 
> Since SVE is an opt-in feature for userspace, this will not affect
> existing users.
> 
> Signed-off-by: Dave Martin <Dave.Martin@arm.com>

Reviewed-by: Julien Thierry <julien.thierry@arm.com>

> ---
>  arch/arm64/kvm/guest.c | 38 +++++++++++++++++++++++++++-----------
>  1 file changed, 27 insertions(+), 11 deletions(-)
> 
> diff --git a/arch/arm64/kvm/guest.c b/arch/arm64/kvm/guest.c
> index f83fe22..f491456 100644
> --- a/arch/arm64/kvm/guest.c
> +++ b/arch/arm64/kvm/guest.c
> @@ -95,7 +95,14 @@ static int core_reg_size_from_offset(u64 off)
>  	return -EINVAL;
>  }
>  
> -static int validate_core_offset(const struct kvm_one_reg *reg)
> +static bool core_reg_offset_is_vreg(u64 off)
> +{
> +	return off >= KVM_REG_ARM_CORE_REG(fp_regs.vregs) &&
> +		off < KVM_REG_ARM_CORE_REG(fp_regs.fpsr);
> +}
> +
> +static int validate_core_offset(const struct kvm_vcpu *vcpu,
> +				const struct kvm_one_reg *reg)
>  {
>  	u64 off = core_reg_offset_from_id(reg->id);
>  	int size = core_reg_size_from_offset(off);
> @@ -103,10 +110,18 @@ static int validate_core_offset(const struct kvm_one_reg *reg)
>  	if (size < 0)
>  		return -EINVAL;
>  
> -	if (KVM_REG_SIZE(reg->id) == size)
> -		return 0;
> +	if (KVM_REG_SIZE(reg->id) != size)
> +		return -EINVAL;
>  
> -	return -EINVAL;
> +	/*
> +	 * The KVM_REG_ARM64_SVE regs must be used instead of
> +	 * KVM_REG_ARM_CORE for accessing the FPSIMD V-registers on
> +	 * SVE-enabled vcpus:
> +	 */
> +	if (vcpu_has_sve(vcpu) && core_reg_offset_is_vreg(off))
> +		return -EINVAL;
> +
> +	return 0;
>  }
>  
>  static int get_core_reg(struct kvm_vcpu *vcpu, const struct kvm_one_reg *reg)
> @@ -128,7 +143,7 @@ static int get_core_reg(struct kvm_vcpu *vcpu, const struct kvm_one_reg *reg)
>  	    (off + (KVM_REG_SIZE(reg->id) / sizeof(__u32))) >= nr_regs)
>  		return -ENOENT;
>  
> -	if (validate_core_offset(reg))
> +	if (validate_core_offset(vcpu, reg))
>  		return -EINVAL;
>  
>  	if (copy_to_user(uaddr, ((u32 *)regs) + off, KVM_REG_SIZE(reg->id)))
> @@ -153,7 +168,7 @@ static int set_core_reg(struct kvm_vcpu *vcpu, const struct kvm_one_reg *reg)
>  	    (off + (KVM_REG_SIZE(reg->id) / sizeof(__u32))) >= nr_regs)
>  		return -ENOENT;
>  
> -	if (validate_core_offset(reg))
> +	if (validate_core_offset(vcpu, reg))
>  		return -EINVAL;
>  
>  	if (KVM_REG_SIZE(reg->id) > sizeof(tmp))
> @@ -206,7 +221,8 @@ int kvm_arch_vcpu_ioctl_set_regs(struct kvm_vcpu *vcpu, struct kvm_regs *regs)
>  	return -EINVAL;
>  }
>  
> -static int copy_core_reg_indices(u64 __user **uind)
> +static int copy_core_reg_indices(const struct kvm_vcpu *vcpu,
> +				 u64 __user **uind)
>  {
>  	unsigned int i;
>  	int n = 0;
> @@ -248,9 +264,9 @@ static int copy_core_reg_indices(u64 __user **uind)
>  	return n;
>  }
>  
> -static unsigned long num_core_regs(void)
> +static unsigned long num_core_regs(const struct kvm_vcpu *vcpu)
>  {
> -	return copy_core_reg_indices(NULL);
> +	return copy_core_reg_indices(vcpu, NULL);
>  }
>  
>  /**
> @@ -315,7 +331,7 @@ unsigned long kvm_arm_num_regs(struct kvm_vcpu *vcpu)
>  {
>  	unsigned long res = 0;
>  
> -	res += num_core_regs();
> +	res += num_core_regs(vcpu);
>  	res += kvm_arm_num_sys_reg_descs(vcpu);
>  	res += kvm_arm_get_fw_num_regs(vcpu);
>  	res += NUM_TIMER_REGS;
> @@ -332,7 +348,7 @@ int kvm_arm_copy_reg_indices(struct kvm_vcpu *vcpu, u64 __user *uindices)
>  {
>  	int ret;
>  
> -	ret = copy_core_reg_indices(&uindices);
> +	ret = copy_core_reg_indices(vcpu, &uindices);
>  	if (ret < 0)
>  		return ret;
>  
> 

-- 
Julien Thierry

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

* Re: [PATCH v5 17/26] KVM: arm64: Reject ioctl access to FPSIMD V-regs on SVE vcpus
@ 2019-02-21 12:06     ` Julien Thierry
  0 siblings, 0 replies; 205+ messages in thread
From: Julien Thierry @ 2019-02-21 12:06 UTC (permalink / raw)
  To: Dave Martin, kvmarm
  Cc: Okamoto Takayuki, Christoffer Dall, Ard Biesheuvel, Marc Zyngier,
	Catalin Marinas, Will Deacon, Zhang Lei, linux-arm-kernel



On 18/02/2019 19:52, Dave Martin wrote:
> In order to avoid the pointless complexity of maintaining two ioctl
> register access views of the same data, this patch blocks ioctl
> access to the FPSIMD V-registers on vcpus that support SVE.
> 
> This will make it more straightforward to add SVE register access
> support.
> 
> Since SVE is an opt-in feature for userspace, this will not affect
> existing users.
> 
> Signed-off-by: Dave Martin <Dave.Martin@arm.com>

Reviewed-by: Julien Thierry <julien.thierry@arm.com>

> ---
>  arch/arm64/kvm/guest.c | 38 +++++++++++++++++++++++++++-----------
>  1 file changed, 27 insertions(+), 11 deletions(-)
> 
> diff --git a/arch/arm64/kvm/guest.c b/arch/arm64/kvm/guest.c
> index f83fe22..f491456 100644
> --- a/arch/arm64/kvm/guest.c
> +++ b/arch/arm64/kvm/guest.c
> @@ -95,7 +95,14 @@ static int core_reg_size_from_offset(u64 off)
>  	return -EINVAL;
>  }
>  
> -static int validate_core_offset(const struct kvm_one_reg *reg)
> +static bool core_reg_offset_is_vreg(u64 off)
> +{
> +	return off >= KVM_REG_ARM_CORE_REG(fp_regs.vregs) &&
> +		off < KVM_REG_ARM_CORE_REG(fp_regs.fpsr);
> +}
> +
> +static int validate_core_offset(const struct kvm_vcpu *vcpu,
> +				const struct kvm_one_reg *reg)
>  {
>  	u64 off = core_reg_offset_from_id(reg->id);
>  	int size = core_reg_size_from_offset(off);
> @@ -103,10 +110,18 @@ static int validate_core_offset(const struct kvm_one_reg *reg)
>  	if (size < 0)
>  		return -EINVAL;
>  
> -	if (KVM_REG_SIZE(reg->id) == size)
> -		return 0;
> +	if (KVM_REG_SIZE(reg->id) != size)
> +		return -EINVAL;
>  
> -	return -EINVAL;
> +	/*
> +	 * The KVM_REG_ARM64_SVE regs must be used instead of
> +	 * KVM_REG_ARM_CORE for accessing the FPSIMD V-registers on
> +	 * SVE-enabled vcpus:
> +	 */
> +	if (vcpu_has_sve(vcpu) && core_reg_offset_is_vreg(off))
> +		return -EINVAL;
> +
> +	return 0;
>  }
>  
>  static int get_core_reg(struct kvm_vcpu *vcpu, const struct kvm_one_reg *reg)
> @@ -128,7 +143,7 @@ static int get_core_reg(struct kvm_vcpu *vcpu, const struct kvm_one_reg *reg)
>  	    (off + (KVM_REG_SIZE(reg->id) / sizeof(__u32))) >= nr_regs)
>  		return -ENOENT;
>  
> -	if (validate_core_offset(reg))
> +	if (validate_core_offset(vcpu, reg))
>  		return -EINVAL;
>  
>  	if (copy_to_user(uaddr, ((u32 *)regs) + off, KVM_REG_SIZE(reg->id)))
> @@ -153,7 +168,7 @@ static int set_core_reg(struct kvm_vcpu *vcpu, const struct kvm_one_reg *reg)
>  	    (off + (KVM_REG_SIZE(reg->id) / sizeof(__u32))) >= nr_regs)
>  		return -ENOENT;
>  
> -	if (validate_core_offset(reg))
> +	if (validate_core_offset(vcpu, reg))
>  		return -EINVAL;
>  
>  	if (KVM_REG_SIZE(reg->id) > sizeof(tmp))
> @@ -206,7 +221,8 @@ int kvm_arch_vcpu_ioctl_set_regs(struct kvm_vcpu *vcpu, struct kvm_regs *regs)
>  	return -EINVAL;
>  }
>  
> -static int copy_core_reg_indices(u64 __user **uind)
> +static int copy_core_reg_indices(const struct kvm_vcpu *vcpu,
> +				 u64 __user **uind)
>  {
>  	unsigned int i;
>  	int n = 0;
> @@ -248,9 +264,9 @@ static int copy_core_reg_indices(u64 __user **uind)
>  	return n;
>  }
>  
> -static unsigned long num_core_regs(void)
> +static unsigned long num_core_regs(const struct kvm_vcpu *vcpu)
>  {
> -	return copy_core_reg_indices(NULL);
> +	return copy_core_reg_indices(vcpu, NULL);
>  }
>  
>  /**
> @@ -315,7 +331,7 @@ unsigned long kvm_arm_num_regs(struct kvm_vcpu *vcpu)
>  {
>  	unsigned long res = 0;
>  
> -	res += num_core_regs();
> +	res += num_core_regs(vcpu);
>  	res += kvm_arm_num_sys_reg_descs(vcpu);
>  	res += kvm_arm_get_fw_num_regs(vcpu);
>  	res += NUM_TIMER_REGS;
> @@ -332,7 +348,7 @@ int kvm_arm_copy_reg_indices(struct kvm_vcpu *vcpu, u64 __user *uindices)
>  {
>  	int ret;
>  
> -	ret = copy_core_reg_indices(&uindices);
> +	ret = copy_core_reg_indices(vcpu, &uindices);
>  	if (ret < 0)
>  		return ret;
>  
> 

-- 
Julien Thierry

_______________________________________________
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] 205+ messages in thread

* Re: [PATCH v5 02/26] arm64: fpsimd: Always set TIF_FOREIGN_FPSTATE on task state flush
  2019-02-18 19:52   ` Dave Martin
  (?)
@ 2019-02-21 12:39   ` Julien Grall
  2019-02-26 12:06       ` Dave Martin
  -1 siblings, 1 reply; 205+ messages in thread
From: Julien Grall @ 2019-02-21 12:39 UTC (permalink / raw)
  To: Dave Martin, kvmarm
  Cc: Peter Maydell, Okamoto Takayuki, Christoffer Dall,
	Ard Biesheuvel, Marc Zyngier, Catalin Marinas, Will Deacon,
	Zhang Lei, Alex Bennée, linux-arm-kernel

Hi Dave,

On 18/02/2019 19:52, Dave Martin wrote:
> This patch updates fpsimd_flush_task_state() to mirror the new
> semantics of fpsimd_flush_cpu_state() introduced by commit
> d8ad71fa38a9 ("arm64: fpsimd: Fix TIF_FOREIGN_FPSTATE after
> invalidating cpu regs").  Both functions now implicitly set

NIT: Double-space before "Both"

> TIF_FOREIGN_FPSTATE to indicate that the task's FPSIMD state is not
> loaded into the cpu.
> 
> As a side-effect, fpsimd_flush_task_state() now sets
> TIF_FOREIGN_FPSTATE even for non-running tasks.  In the case of

NIT: Double sppace before "In".

> non-running tasks this is not useful but also harmless, because the
> flag is live only while the corresponding task is running.  This
> function is not called from fast paths, so special-casing this for
> the task == current case is not really worth it.
> 
> Compiler barriers previously present in restore_sve_fpsimd_context()
> are pulled into fpsimd_flush_task_state() so that it can be safely
> called with preemption enabled if necessary.
> 
> Explicit calls to set TIF_FOREIGN_FPSTATE that accompany
> fpsimd_flush_task_state() calls and are now redundant are removed
> as appropriate.
> 
> fpsimd_flush_task_state() is used to get exclusive access to the
> representation of the task's state via task_struct, for the purpose
> of replacing the state.  Thus, the call to this function should

NIT: Double-space before "Thus".

> happen before manipulating fpsimd_state or sve_state etc. in
> task_struct.  Anomalous cases are reordered appropriately in order

NIT: Double-space before "Anomalous".

> to make the code more consistent, although there should be no
> functional difference since these cases are protected by
> local_bh_disable() anyway.
> 
> Signed-off-by: Dave Martin <Dave.Martin@arm.com>
> Reviewed-by: Alex Bennée <alex.bennee@linaro.org>

Reviewed-by: Julien Grall <julien.grall@arm.com>

Cheers,

-- 
Julien Grall

_______________________________________________
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] 205+ messages in thread

* Re: [PATCH v5 06/26] arm64/sve: Check SVE virtualisability
  2019-02-18 19:52   ` Dave Martin
@ 2019-02-21 13:36     ` Julien Grall
  -1 siblings, 0 replies; 205+ messages in thread
From: Julien Grall @ 2019-02-21 13:36 UTC (permalink / raw)
  To: Dave Martin, kvmarm
  Cc: Okamoto Takayuki, Christoffer Dall, Ard Biesheuvel, Marc Zyngier,
	Catalin Marinas, Will Deacon, Zhang Lei, linux-arm-kernel

Hi Dave,

On 18/02/2019 19:52, Dave Martin wrote:
> +	/*
> +	 * Mismatches above sve_max_virtualisable_vl are fine, since
> +	 * no guest is allowed to configure ZCR_EL2.LEN to exceed this:
> +	 */
> +	if (sve_vl_from_vq(bit_to_vq(b)) <= sve_max_virtualisable_vl) {
> +		pr_warn("SVE: cpu%d: Unsupported vector length(s) present\n",
> +			smp_processor_id());

Would it be worth to print the unsupported vector length?

Cheers,

-- 
Julien Grall

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

* Re: [PATCH v5 06/26] arm64/sve: Check SVE virtualisability
@ 2019-02-21 13:36     ` Julien Grall
  0 siblings, 0 replies; 205+ messages in thread
From: Julien Grall @ 2019-02-21 13:36 UTC (permalink / raw)
  To: Dave Martin, kvmarm
  Cc: Peter Maydell, Okamoto Takayuki, Christoffer Dall,
	Ard Biesheuvel, Marc Zyngier, Catalin Marinas, Will Deacon,
	Zhang Lei, Alex Bennée, linux-arm-kernel

Hi Dave,

On 18/02/2019 19:52, Dave Martin wrote:
> +	/*
> +	 * Mismatches above sve_max_virtualisable_vl are fine, since
> +	 * no guest is allowed to configure ZCR_EL2.LEN to exceed this:
> +	 */
> +	if (sve_vl_from_vq(bit_to_vq(b)) <= sve_max_virtualisable_vl) {
> +		pr_warn("SVE: cpu%d: Unsupported vector length(s) present\n",
> +			smp_processor_id());

Would it be worth to print the unsupported vector length?

Cheers,

-- 
Julien Grall

_______________________________________________
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] 205+ messages in thread

* Re: [PATCH v5 07/26] arm64/sve: Clarify role of the VQ map maintenance functions
  2019-02-18 19:52   ` Dave Martin
@ 2019-02-21 13:46     ` Julien Grall
  -1 siblings, 0 replies; 205+ messages in thread
From: Julien Grall @ 2019-02-21 13:46 UTC (permalink / raw)
  To: Dave Martin, kvmarm
  Cc: Okamoto Takayuki, Christoffer Dall, Ard Biesheuvel, Marc Zyngier,
	Catalin Marinas, Will Deacon, Zhang Lei, linux-arm-kernel

Hi Dave,

On 18/02/2019 19:52, Dave Martin wrote:
> The roles of sve_init_vq_map(), sve_update_vq_map() and
> sve_verify_vq_map() are highly non-obvious to anyone who has not dug
> through cpufeatures.c in detail.
> 
> Since the way these functions interact with each other is more
> important here than a full understanding of the cpufeatures code, this
> patch adds comments to make the functions' roles clearer.
> 
> No functional change.
> 
> Signed-off-by: Dave Martin <Dave.Martin@arm.com>

Reviewed-by: Julien Grall <julien.grall@arm.com>

Cheers,

-- 
Julien Grall

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

* Re: [PATCH v5 07/26] arm64/sve: Clarify role of the VQ map maintenance functions
@ 2019-02-21 13:46     ` Julien Grall
  0 siblings, 0 replies; 205+ messages in thread
From: Julien Grall @ 2019-02-21 13:46 UTC (permalink / raw)
  To: Dave Martin, kvmarm
  Cc: Peter Maydell, Okamoto Takayuki, Christoffer Dall,
	Ard Biesheuvel, Marc Zyngier, Catalin Marinas, Will Deacon,
	Zhang Lei, Alex Bennée, linux-arm-kernel

Hi Dave,

On 18/02/2019 19:52, Dave Martin wrote:
> The roles of sve_init_vq_map(), sve_update_vq_map() and
> sve_verify_vq_map() are highly non-obvious to anyone who has not dug
> through cpufeatures.c in detail.
> 
> Since the way these functions interact with each other is more
> important here than a full understanding of the cpufeatures code, this
> patch adds comments to make the functions' roles clearer.
> 
> No functional change.
> 
> Signed-off-by: Dave Martin <Dave.Martin@arm.com>

Reviewed-by: Julien Grall <julien.grall@arm.com>

Cheers,

-- 
Julien Grall

_______________________________________________
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] 205+ messages in thread

* Re: [PATCH v5 18/26] KVM: arm64/sve: Add SVE support to register access ioctl interface
  2019-02-18 19:52   ` Dave Martin
@ 2019-02-21 15:23     ` Julien Thierry
  -1 siblings, 0 replies; 205+ messages in thread
From: Julien Thierry @ 2019-02-21 15:23 UTC (permalink / raw)
  To: Dave Martin, kvmarm
  Cc: Okamoto Takayuki, Christoffer Dall, Ard Biesheuvel, Marc Zyngier,
	Catalin Marinas, Will Deacon, Zhang Lei, linux-arm-kernel

Hi Dave,

On 18/02/2019 19:52, Dave Martin wrote:
> This patch adds the following registers for access via the
> KVM_{GET,SET}_ONE_REG interface:
> 
>  * KVM_REG_ARM64_SVE_ZREG(n, i) (n = 0..31) (in 2048-bit slices)
>  * KVM_REG_ARM64_SVE_PREG(n, i) (n = 0..15) (in 256-bit slices)
>  * KVM_REG_ARM64_SVE_FFR(i) (in 256-bit slices)
> 
> In order to adapt gracefully to future architectural extensions,
> the registers are logically divided up into slices as noted above:
> the i parameter denotes the slice index.
> 
> This allows us to reserve space in the ABI for future expansion of
> these registers.  However, as of today the architecture does not
> permit registers to be larger than a single slice, so no code is
> needed in the kernel to expose additional slices, for now.  The
> code can be extended later as needed to expose them up to a maximum
> of 32 slices (as carved out in the architecture itself) if they
> really exist someday.
> 
> The registers are only visible for vcpus that have SVE enabled.
> They are not enumerated by KVM_GET_REG_LIST on vcpus that do not
> have SVE.
> 
> Accesses to the FPSIMD registers via KVM_REG_ARM_CORE is not
> allowed for SVE-enabled vcpus: SVE-aware userspace can use the
> KVM_REG_ARM64_SVE_ZREG() interface instead to access the same
> register state.  This avoids some complex and pointless emulation
> in the kernel to convert between the two views of these aliased
> registers.
> 
> Signed-off-by: Dave Martin <Dave.Martin@arm.com>
> 
> ---
> 
> Changes since v4:
> 
>  * Add "BASE" #defines for the Z-reg and P-reg ranges in the KVM
>    register ID space, to make the 0x400 magic number a little less
>    cryptic.
> 
>  * Pull KVM_SVE_{Z,P}REG_SIZE defines from "KVM: arm64: Enumerate SVE
>    register indices for KVM_GET_REG_LIST", since we now use them here.
> 
>  * Simplify sve_reg_region(), and give up on the attempt to make
>    kreg_region a general thing: nothing else will use it for now,
>    anyway, so let's keep it as simple as possible.
> 
>  * Drop support for multiple slices per register.  This functionality
>    can be added back in later if needed, without ABI breaks.
> 
>  * Pull vcpu_sve_state_size() into kvm_host.h, from "KVM: arm64/sve:
>    Allow userspace to enable SVE for vcpus".  This is needed for use
>    with array_index_nospec() to determine the applicable buffer bounds.
>    To avoid circular header deependency issues, the function is also
>    converted into a macro, but is otherwise equivalent to the original
>    version.
> 
>  * Guard sve_state base offset in kernel memory with
>    array_index_nospec(), since it is generated from user data that can
>    put it out of range.
> 
>    (sve_state will get allocated with the corresponding size later in
>    the series.  For now, this code is dormant since no means is
>    provided for userspace to create SVE-enabled vcpus yet.)
> ---
>  arch/arm64/include/asm/kvm_host.h |  14 ++++
>  arch/arm64/include/uapi/asm/kvm.h |  17 +++++
>  arch/arm64/kvm/guest.c            | 138 ++++++++++++++++++++++++++++++++++----
>  3 files changed, 157 insertions(+), 12 deletions(-)
> 

[...]

> diff --git a/arch/arm64/kvm/guest.c b/arch/arm64/kvm/guest.c
> index f491456..8cfa889 100644
> --- a/arch/arm64/kvm/guest.c
> +++ b/arch/arm64/kvm/guest.c

[...]

> @@ -211,6 +217,114 @@ static int set_core_reg(struct kvm_vcpu *vcpu, const struct kvm_one_reg *reg)
>  	return err;
>  }
>  
> +#define SVE_REG_SLICE_SHIFT	0
> +#define SVE_REG_SLICE_BITS	5
> +#define SVE_REG_ID_SHIFT	(SVE_REG_SLICE_SHIFT + SVE_REG_SLICE_BITS)
> +#define SVE_REG_ID_BITS		5
> +
> +#define SVE_REG_SLICE_MASK					\
> +	GENMASK(SVE_REG_SLICE_SHIFT + SVE_REG_SLICE_BITS - 1,	\
> +		SVE_REG_SLICE_SHIFT)
> +#define SVE_REG_ID_MASK							\
> +	GENMASK(SVE_REG_ID_SHIFT + SVE_REG_ID_BITS - 1, SVE_REG_ID_SHIFT)
> +
> +#define SVE_NUM_SLICES (1 << SVE_REG_SLICE_BITS)
> +
> +#define KVM_SVE_ZREG_SIZE KVM_REG_SIZE(KVM_REG_ARM64_SVE_ZREG(0, 0))
> +#define KVM_SVE_PREG_SIZE KVM_REG_SIZE(KVM_REG_ARM64_SVE_PREG(0, 0))
> +
> +struct sve_state_region {

This sve_state_region feels a bit too generic too me.

So far it is only used to access a single (slice of a) register at a
time. Is there a plan to use it for more?

Otherwise I'd suggest at least naming it something like sve_reg_region,
sve_reg_mem_region or sve_reg_mem_desc.


> +	unsigned int koffset;	/* offset into sve_state in kernel memory */
> +	unsigned int klen;	/* length in kernel memory */
> +	unsigned int upad;	/* extra trailing padding in user memory */
> +};
> +
> +/* Get sanitised bounds for user/kernel SVE register copy */
> +static int sve_reg_region(struct sve_state_region *region,

I feel that sve_reg_to_region or sve_reg_get_region would be a clearer name.

Cheers,

Julien

> +			  struct kvm_vcpu *vcpu,
> +			  const struct kvm_one_reg *reg)
> +{
> +	/* reg ID ranges for Z- registers */
> +	const u64 zreg_id_min = KVM_REG_ARM64_SVE_ZREG(0, 0);
> +	const u64 zreg_id_max = KVM_REG_ARM64_SVE_ZREG(SVE_NUM_ZREGS - 1,
> +						       SVE_NUM_SLICES - 1);
> +
> +	/* reg ID ranges for P- registers and FFR (which are contiguous) */
> +	const u64 preg_id_min = KVM_REG_ARM64_SVE_PREG(0, 0);
> +	const u64 preg_id_max = KVM_REG_ARM64_SVE_FFR(SVE_NUM_SLICES - 1);
> +
> +	unsigned int vq;
> +	unsigned int reg_num;
> +
> +	unsigned int reqoffset, reqlen; /* User-requested offset and length */
> +	unsigned int maxlen; /* Maxmimum permitted length */
> +
> +	size_t sve_state_size;
> +
> +	/* Only the first slice ever exists, for now: */
> +	if ((reg->id & SVE_REG_SLICE_MASK) != 0)
> +		return -ENOENT;
> +
> +	vq = sve_vq_from_vl(vcpu->arch.sve_max_vl);
> +
> +	reg_num = (reg->id & SVE_REG_ID_MASK) >> SVE_REG_ID_SHIFT;
> +
> +	if (reg->id >= zreg_id_min && reg->id <= zreg_id_max) {
> +		reqoffset = SVE_SIG_ZREG_OFFSET(vq, reg_num) -
> +				SVE_SIG_REGS_OFFSET;
> +		reqlen = KVM_SVE_ZREG_SIZE;
> +		maxlen = SVE_SIG_ZREG_SIZE(vq);
> +	} else if (reg->id >= preg_id_min && reg->id <= preg_id_max) {
> +		reqoffset = SVE_SIG_PREG_OFFSET(vq, reg_num) -
> +				SVE_SIG_REGS_OFFSET;
> +		reqlen = KVM_SVE_PREG_SIZE;
> +		maxlen = SVE_SIG_PREG_SIZE(vq);
> +	} else {
> +		return -ENOENT;
> +	}
> +
> +	sve_state_size = vcpu_sve_state_size(vcpu);
> +	if (!sve_state_size)
> +		return -EINVAL;
> +
> +	region->koffset = array_index_nospec(reqoffset, sve_state_size);
> +	region->klen = min(maxlen, reqlen);
> +	region->upad = reqlen - region->klen;
> +
> +	return 0;
> +}
> +
> +static int get_sve_reg(struct kvm_vcpu *vcpu, const struct kvm_one_reg *reg)
> +{
> +	struct sve_state_region region;
> +	char __user *uptr = (char __user *)reg->addr;
> +
> +	if (!vcpu_has_sve(vcpu) || sve_reg_region(&region, vcpu, reg))
> +		return -ENOENT;
> +
> +	if (copy_to_user(uptr, vcpu->arch.sve_state + region.koffset,
> +			 region.klen) ||
> +	    clear_user(uptr + region.klen, region.upad))
> +		return -EFAULT;
> +
> +	return 0;
> +}
> +
> +static int set_sve_reg(struct kvm_vcpu *vcpu, const struct kvm_one_reg *reg)
> +{
> +	struct sve_state_region region;
> +	const char __user *uptr = (const char __user *)reg->addr;
> +
> +	if (!vcpu_has_sve(vcpu) || sve_reg_region(&region, vcpu, reg))
> +		return -ENOENT;
> +
> +	if (copy_from_user(vcpu->arch.sve_state + region.koffset, uptr,
> +			   region.klen))
> +		return -EFAULT;
> +
> +	return 0;
> +}
> +
>  int kvm_arch_vcpu_ioctl_get_regs(struct kvm_vcpu *vcpu, struct kvm_regs *regs)
>  {
>  	return -EINVAL;
> @@ -371,12 +485,12 @@ int kvm_arm_get_reg(struct kvm_vcpu *vcpu, const struct kvm_one_reg *reg)
>  	if ((reg->id & ~KVM_REG_SIZE_MASK) >> 32 != KVM_REG_ARM64 >> 32)
>  		return -EINVAL;
>  
> -	/* Register group 16 means we want a core register. */
> -	if ((reg->id & KVM_REG_ARM_COPROC_MASK) == KVM_REG_ARM_CORE)
> -		return get_core_reg(vcpu, reg);
> -
> -	if ((reg->id & KVM_REG_ARM_COPROC_MASK) == KVM_REG_ARM_FW)
> -		return kvm_arm_get_fw_reg(vcpu, reg);
> +	switch (reg->id & KVM_REG_ARM_COPROC_MASK) {
> +	case KVM_REG_ARM_CORE:	return get_core_reg(vcpu, reg);
> +	case KVM_REG_ARM_FW:	return kvm_arm_get_fw_reg(vcpu, reg);
> +	case KVM_REG_ARM64_SVE:	return get_sve_reg(vcpu, reg);
> +	default: break; /* fall through */
> +	}
>  
>  	if (is_timer_reg(reg->id))
>  		return get_timer_reg(vcpu, reg);
> @@ -390,12 +504,12 @@ int kvm_arm_set_reg(struct kvm_vcpu *vcpu, const struct kvm_one_reg *reg)
>  	if ((reg->id & ~KVM_REG_SIZE_MASK) >> 32 != KVM_REG_ARM64 >> 32)
>  		return -EINVAL;
>  
> -	/* Register group 16 means we set a core register. */
> -	if ((reg->id & KVM_REG_ARM_COPROC_MASK) == KVM_REG_ARM_CORE)
> -		return set_core_reg(vcpu, reg);
> -
> -	if ((reg->id & KVM_REG_ARM_COPROC_MASK) == KVM_REG_ARM_FW)
> -		return kvm_arm_set_fw_reg(vcpu, reg);
> +	switch (reg->id & KVM_REG_ARM_COPROC_MASK) {
> +	case KVM_REG_ARM_CORE:	return set_core_reg(vcpu, reg);
> +	case KVM_REG_ARM_FW:	return kvm_arm_set_fw_reg(vcpu, reg);
> +	case KVM_REG_ARM64_SVE:	return set_sve_reg(vcpu, reg);
> +	default: break; /* fall through */
> +	}
>  
>  	if (is_timer_reg(reg->id))
>  		return set_timer_reg(vcpu, reg);
> 

-- 
Julien Thierry

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

* Re: [PATCH v5 18/26] KVM: arm64/sve: Add SVE support to register access ioctl interface
@ 2019-02-21 15:23     ` Julien Thierry
  0 siblings, 0 replies; 205+ messages in thread
From: Julien Thierry @ 2019-02-21 15:23 UTC (permalink / raw)
  To: Dave Martin, kvmarm
  Cc: Okamoto Takayuki, Christoffer Dall, Ard Biesheuvel, Marc Zyngier,
	Catalin Marinas, Will Deacon, Zhang Lei, linux-arm-kernel

Hi Dave,

On 18/02/2019 19:52, Dave Martin wrote:
> This patch adds the following registers for access via the
> KVM_{GET,SET}_ONE_REG interface:
> 
>  * KVM_REG_ARM64_SVE_ZREG(n, i) (n = 0..31) (in 2048-bit slices)
>  * KVM_REG_ARM64_SVE_PREG(n, i) (n = 0..15) (in 256-bit slices)
>  * KVM_REG_ARM64_SVE_FFR(i) (in 256-bit slices)
> 
> In order to adapt gracefully to future architectural extensions,
> the registers are logically divided up into slices as noted above:
> the i parameter denotes the slice index.
> 
> This allows us to reserve space in the ABI for future expansion of
> these registers.  However, as of today the architecture does not
> permit registers to be larger than a single slice, so no code is
> needed in the kernel to expose additional slices, for now.  The
> code can be extended later as needed to expose them up to a maximum
> of 32 slices (as carved out in the architecture itself) if they
> really exist someday.
> 
> The registers are only visible for vcpus that have SVE enabled.
> They are not enumerated by KVM_GET_REG_LIST on vcpus that do not
> have SVE.
> 
> Accesses to the FPSIMD registers via KVM_REG_ARM_CORE is not
> allowed for SVE-enabled vcpus: SVE-aware userspace can use the
> KVM_REG_ARM64_SVE_ZREG() interface instead to access the same
> register state.  This avoids some complex and pointless emulation
> in the kernel to convert between the two views of these aliased
> registers.
> 
> Signed-off-by: Dave Martin <Dave.Martin@arm.com>
> 
> ---
> 
> Changes since v4:
> 
>  * Add "BASE" #defines for the Z-reg and P-reg ranges in the KVM
>    register ID space, to make the 0x400 magic number a little less
>    cryptic.
> 
>  * Pull KVM_SVE_{Z,P}REG_SIZE defines from "KVM: arm64: Enumerate SVE
>    register indices for KVM_GET_REG_LIST", since we now use them here.
> 
>  * Simplify sve_reg_region(), and give up on the attempt to make
>    kreg_region a general thing: nothing else will use it for now,
>    anyway, so let's keep it as simple as possible.
> 
>  * Drop support for multiple slices per register.  This functionality
>    can be added back in later if needed, without ABI breaks.
> 
>  * Pull vcpu_sve_state_size() into kvm_host.h, from "KVM: arm64/sve:
>    Allow userspace to enable SVE for vcpus".  This is needed for use
>    with array_index_nospec() to determine the applicable buffer bounds.
>    To avoid circular header deependency issues, the function is also
>    converted into a macro, but is otherwise equivalent to the original
>    version.
> 
>  * Guard sve_state base offset in kernel memory with
>    array_index_nospec(), since it is generated from user data that can
>    put it out of range.
> 
>    (sve_state will get allocated with the corresponding size later in
>    the series.  For now, this code is dormant since no means is
>    provided for userspace to create SVE-enabled vcpus yet.)
> ---
>  arch/arm64/include/asm/kvm_host.h |  14 ++++
>  arch/arm64/include/uapi/asm/kvm.h |  17 +++++
>  arch/arm64/kvm/guest.c            | 138 ++++++++++++++++++++++++++++++++++----
>  3 files changed, 157 insertions(+), 12 deletions(-)
> 

[...]

> diff --git a/arch/arm64/kvm/guest.c b/arch/arm64/kvm/guest.c
> index f491456..8cfa889 100644
> --- a/arch/arm64/kvm/guest.c
> +++ b/arch/arm64/kvm/guest.c

[...]

> @@ -211,6 +217,114 @@ static int set_core_reg(struct kvm_vcpu *vcpu, const struct kvm_one_reg *reg)
>  	return err;
>  }
>  
> +#define SVE_REG_SLICE_SHIFT	0
> +#define SVE_REG_SLICE_BITS	5
> +#define SVE_REG_ID_SHIFT	(SVE_REG_SLICE_SHIFT + SVE_REG_SLICE_BITS)
> +#define SVE_REG_ID_BITS		5
> +
> +#define SVE_REG_SLICE_MASK					\
> +	GENMASK(SVE_REG_SLICE_SHIFT + SVE_REG_SLICE_BITS - 1,	\
> +		SVE_REG_SLICE_SHIFT)
> +#define SVE_REG_ID_MASK							\
> +	GENMASK(SVE_REG_ID_SHIFT + SVE_REG_ID_BITS - 1, SVE_REG_ID_SHIFT)
> +
> +#define SVE_NUM_SLICES (1 << SVE_REG_SLICE_BITS)
> +
> +#define KVM_SVE_ZREG_SIZE KVM_REG_SIZE(KVM_REG_ARM64_SVE_ZREG(0, 0))
> +#define KVM_SVE_PREG_SIZE KVM_REG_SIZE(KVM_REG_ARM64_SVE_PREG(0, 0))
> +
> +struct sve_state_region {

This sve_state_region feels a bit too generic too me.

So far it is only used to access a single (slice of a) register at a
time. Is there a plan to use it for more?

Otherwise I'd suggest at least naming it something like sve_reg_region,
sve_reg_mem_region or sve_reg_mem_desc.


> +	unsigned int koffset;	/* offset into sve_state in kernel memory */
> +	unsigned int klen;	/* length in kernel memory */
> +	unsigned int upad;	/* extra trailing padding in user memory */
> +};
> +
> +/* Get sanitised bounds for user/kernel SVE register copy */
> +static int sve_reg_region(struct sve_state_region *region,

I feel that sve_reg_to_region or sve_reg_get_region would be a clearer name.

Cheers,

Julien

> +			  struct kvm_vcpu *vcpu,
> +			  const struct kvm_one_reg *reg)
> +{
> +	/* reg ID ranges for Z- registers */
> +	const u64 zreg_id_min = KVM_REG_ARM64_SVE_ZREG(0, 0);
> +	const u64 zreg_id_max = KVM_REG_ARM64_SVE_ZREG(SVE_NUM_ZREGS - 1,
> +						       SVE_NUM_SLICES - 1);
> +
> +	/* reg ID ranges for P- registers and FFR (which are contiguous) */
> +	const u64 preg_id_min = KVM_REG_ARM64_SVE_PREG(0, 0);
> +	const u64 preg_id_max = KVM_REG_ARM64_SVE_FFR(SVE_NUM_SLICES - 1);
> +
> +	unsigned int vq;
> +	unsigned int reg_num;
> +
> +	unsigned int reqoffset, reqlen; /* User-requested offset and length */
> +	unsigned int maxlen; /* Maxmimum permitted length */
> +
> +	size_t sve_state_size;
> +
> +	/* Only the first slice ever exists, for now: */
> +	if ((reg->id & SVE_REG_SLICE_MASK) != 0)
> +		return -ENOENT;
> +
> +	vq = sve_vq_from_vl(vcpu->arch.sve_max_vl);
> +
> +	reg_num = (reg->id & SVE_REG_ID_MASK) >> SVE_REG_ID_SHIFT;
> +
> +	if (reg->id >= zreg_id_min && reg->id <= zreg_id_max) {
> +		reqoffset = SVE_SIG_ZREG_OFFSET(vq, reg_num) -
> +				SVE_SIG_REGS_OFFSET;
> +		reqlen = KVM_SVE_ZREG_SIZE;
> +		maxlen = SVE_SIG_ZREG_SIZE(vq);
> +	} else if (reg->id >= preg_id_min && reg->id <= preg_id_max) {
> +		reqoffset = SVE_SIG_PREG_OFFSET(vq, reg_num) -
> +				SVE_SIG_REGS_OFFSET;
> +		reqlen = KVM_SVE_PREG_SIZE;
> +		maxlen = SVE_SIG_PREG_SIZE(vq);
> +	} else {
> +		return -ENOENT;
> +	}
> +
> +	sve_state_size = vcpu_sve_state_size(vcpu);
> +	if (!sve_state_size)
> +		return -EINVAL;
> +
> +	region->koffset = array_index_nospec(reqoffset, sve_state_size);
> +	region->klen = min(maxlen, reqlen);
> +	region->upad = reqlen - region->klen;
> +
> +	return 0;
> +}
> +
> +static int get_sve_reg(struct kvm_vcpu *vcpu, const struct kvm_one_reg *reg)
> +{
> +	struct sve_state_region region;
> +	char __user *uptr = (char __user *)reg->addr;
> +
> +	if (!vcpu_has_sve(vcpu) || sve_reg_region(&region, vcpu, reg))
> +		return -ENOENT;
> +
> +	if (copy_to_user(uptr, vcpu->arch.sve_state + region.koffset,
> +			 region.klen) ||
> +	    clear_user(uptr + region.klen, region.upad))
> +		return -EFAULT;
> +
> +	return 0;
> +}
> +
> +static int set_sve_reg(struct kvm_vcpu *vcpu, const struct kvm_one_reg *reg)
> +{
> +	struct sve_state_region region;
> +	const char __user *uptr = (const char __user *)reg->addr;
> +
> +	if (!vcpu_has_sve(vcpu) || sve_reg_region(&region, vcpu, reg))
> +		return -ENOENT;
> +
> +	if (copy_from_user(vcpu->arch.sve_state + region.koffset, uptr,
> +			   region.klen))
> +		return -EFAULT;
> +
> +	return 0;
> +}
> +
>  int kvm_arch_vcpu_ioctl_get_regs(struct kvm_vcpu *vcpu, struct kvm_regs *regs)
>  {
>  	return -EINVAL;
> @@ -371,12 +485,12 @@ int kvm_arm_get_reg(struct kvm_vcpu *vcpu, const struct kvm_one_reg *reg)
>  	if ((reg->id & ~KVM_REG_SIZE_MASK) >> 32 != KVM_REG_ARM64 >> 32)
>  		return -EINVAL;
>  
> -	/* Register group 16 means we want a core register. */
> -	if ((reg->id & KVM_REG_ARM_COPROC_MASK) == KVM_REG_ARM_CORE)
> -		return get_core_reg(vcpu, reg);
> -
> -	if ((reg->id & KVM_REG_ARM_COPROC_MASK) == KVM_REG_ARM_FW)
> -		return kvm_arm_get_fw_reg(vcpu, reg);
> +	switch (reg->id & KVM_REG_ARM_COPROC_MASK) {
> +	case KVM_REG_ARM_CORE:	return get_core_reg(vcpu, reg);
> +	case KVM_REG_ARM_FW:	return kvm_arm_get_fw_reg(vcpu, reg);
> +	case KVM_REG_ARM64_SVE:	return get_sve_reg(vcpu, reg);
> +	default: break; /* fall through */
> +	}
>  
>  	if (is_timer_reg(reg->id))
>  		return get_timer_reg(vcpu, reg);
> @@ -390,12 +504,12 @@ int kvm_arm_set_reg(struct kvm_vcpu *vcpu, const struct kvm_one_reg *reg)
>  	if ((reg->id & ~KVM_REG_SIZE_MASK) >> 32 != KVM_REG_ARM64 >> 32)
>  		return -EINVAL;
>  
> -	/* Register group 16 means we set a core register. */
> -	if ((reg->id & KVM_REG_ARM_COPROC_MASK) == KVM_REG_ARM_CORE)
> -		return set_core_reg(vcpu, reg);
> -
> -	if ((reg->id & KVM_REG_ARM_COPROC_MASK) == KVM_REG_ARM_FW)
> -		return kvm_arm_set_fw_reg(vcpu, reg);
> +	switch (reg->id & KVM_REG_ARM_COPROC_MASK) {
> +	case KVM_REG_ARM_CORE:	return set_core_reg(vcpu, reg);
> +	case KVM_REG_ARM_FW:	return kvm_arm_set_fw_reg(vcpu, reg);
> +	case KVM_REG_ARM64_SVE:	return set_sve_reg(vcpu, reg);
> +	default: break; /* fall through */
> +	}
>  
>  	if (is_timer_reg(reg->id))
>  		return set_timer_reg(vcpu, reg);
> 

-- 
Julien Thierry

_______________________________________________
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] 205+ messages in thread

* Re: [PATCH v5 19/26] KVM: arm64: Enumerate SVE register indices for KVM_GET_REG_LIST
  2019-02-18 19:52   ` Dave Martin
@ 2019-02-21 16:28     ` Julien Thierry
  -1 siblings, 0 replies; 205+ messages in thread
From: Julien Thierry @ 2019-02-21 16:28 UTC (permalink / raw)
  To: Dave Martin, kvmarm
  Cc: Okamoto Takayuki, Christoffer Dall, Ard Biesheuvel, Marc Zyngier,
	Catalin Marinas, Will Deacon, Zhang Lei, linux-arm-kernel



On 18/02/2019 19:52, Dave Martin wrote:
> This patch includes the SVE register IDs in the list returned by
> KVM_GET_REG_LIST, as appropriate.
> 
> On a non-SVE-enabled vcpu, no new IDs are added.
> 
> On an SVE-enabled vcpu, IDs for the FPSIMD V-registers are removed
> from the list, since userspace is required to access the Z-
> registers instead to access their context.  For the variably-sized
> SVE registers, the appropriate set of slice IDs are enumerated,
> depending on the maximum vector length for the vcpu.
> 
> Signed-off-by: Dave Martin <Dave.Martin@arm.com>

Reviewed-by: Julien Thierry <julien.thiery@arm.com>

> 
> ---
> 
> Changes since v4:
> 
>  * Drop KVM_SVE_SLICES(), which is no longer used due to the dropping of
>    register multi-slice support from the series.
> 
>  * Drop register multi-slice support.
> ---
>  arch/arm64/kvm/guest.c | 51 ++++++++++++++++++++++++++++++++++++++++++++++++++
>  1 file changed, 51 insertions(+)
> 
> diff --git a/arch/arm64/kvm/guest.c b/arch/arm64/kvm/guest.c
> index 8cfa889..4a2ad60 100644
> --- a/arch/arm64/kvm/guest.c
> +++ b/arch/arm64/kvm/guest.c
> @@ -366,6 +366,14 @@ static int copy_core_reg_indices(const struct kvm_vcpu *vcpu,
>  			continue;
>  		}
>  
> +		/*
> +		 * The KVM_REG_ARM64_SVE regs must be used instead of
> +		 * KVM_REG_ARM_CORE for accessing the FPSIMD V-registers on
> +		 * SVE-enabled vcpus:
> +		 */
> +		if (vcpu_has_sve(vcpu) && core_reg_offset_is_vreg(i))
> +			continue;
> +
>  		if (uind) {
>  			if (put_user(reg, *uind))
>  				return -EFAULT;
> @@ -436,6 +444,44 @@ static int get_timer_reg(struct kvm_vcpu *vcpu, const struct kvm_one_reg *reg)
>  	return copy_to_user(uaddr, &val, KVM_REG_SIZE(reg->id)) ? -EFAULT : 0;
>  }
>  
> +static unsigned long num_sve_regs(const struct kvm_vcpu *vcpu)
> +{
> +	/* Only the first slice ever exists, for now */
> +	const unsigned int slices = 1;
> +
> +	if (!vcpu_has_sve(vcpu))
> +		return 0;
> +
> +	return slices * (SVE_NUM_PREGS + SVE_NUM_ZREGS + 1 /* FFR */);
> +}
> +
> +static int copy_sve_reg_indices(const struct kvm_vcpu *vcpu, u64 __user **uind)
> +{
> +	/* Only the first slice ever exists, for now */
> +	const unsigned int slices = 1;
> +	unsigned int i, n;
> +
> +	if (!vcpu_has_sve(vcpu))
> +		return 0;
> +
> +	for (i = 0; i < slices; i++) {
> +		for (n = 0; n < SVE_NUM_ZREGS; n++) {
> +			if (put_user(KVM_REG_ARM64_SVE_ZREG(n, i), (*uind)++))
> +				return -EFAULT;
> +		}
> +
> +		for (n = 0; n < SVE_NUM_PREGS; n++) {
> +			if (put_user(KVM_REG_ARM64_SVE_PREG(n, i), (*uind)++))
> +				return -EFAULT;
> +		}
> +
> +		if (put_user(KVM_REG_ARM64_SVE_FFR(i), (*uind)++))
> +			return -EFAULT;
> +	}
> +
> +	return 0;
> +}
> +
>  /**
>   * kvm_arm_num_regs - how many registers do we present via KVM_GET_ONE_REG
>   *
> @@ -446,6 +492,7 @@ unsigned long kvm_arm_num_regs(struct kvm_vcpu *vcpu)
>  	unsigned long res = 0;
>  
>  	res += num_core_regs(vcpu);
> +	res += num_sve_regs(vcpu);
>  	res += kvm_arm_num_sys_reg_descs(vcpu);
>  	res += kvm_arm_get_fw_num_regs(vcpu);
>  	res += NUM_TIMER_REGS;
> @@ -466,6 +513,10 @@ int kvm_arm_copy_reg_indices(struct kvm_vcpu *vcpu, u64 __user *uindices)
>  	if (ret < 0)
>  		return ret;
>  
> +	ret = copy_sve_reg_indices(vcpu, &uindices);
> +	if (ret)
> +		return ret;
> +
>  	ret = kvm_arm_copy_fw_reg_indices(vcpu, uindices);
>  	if (ret)
>  		return ret;
> 

-- 
Julien Thierry

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

* Re: [PATCH v5 19/26] KVM: arm64: Enumerate SVE register indices for KVM_GET_REG_LIST
@ 2019-02-21 16:28     ` Julien Thierry
  0 siblings, 0 replies; 205+ messages in thread
From: Julien Thierry @ 2019-02-21 16:28 UTC (permalink / raw)
  To: Dave Martin, kvmarm
  Cc: Okamoto Takayuki, Christoffer Dall, Ard Biesheuvel, Marc Zyngier,
	Catalin Marinas, Will Deacon, Zhang Lei, linux-arm-kernel



On 18/02/2019 19:52, Dave Martin wrote:
> This patch includes the SVE register IDs in the list returned by
> KVM_GET_REG_LIST, as appropriate.
> 
> On a non-SVE-enabled vcpu, no new IDs are added.
> 
> On an SVE-enabled vcpu, IDs for the FPSIMD V-registers are removed
> from the list, since userspace is required to access the Z-
> registers instead to access their context.  For the variably-sized
> SVE registers, the appropriate set of slice IDs are enumerated,
> depending on the maximum vector length for the vcpu.
> 
> Signed-off-by: Dave Martin <Dave.Martin@arm.com>

Reviewed-by: Julien Thierry <julien.thiery@arm.com>

> 
> ---
> 
> Changes since v4:
> 
>  * Drop KVM_SVE_SLICES(), which is no longer used due to the dropping of
>    register multi-slice support from the series.
> 
>  * Drop register multi-slice support.
> ---
>  arch/arm64/kvm/guest.c | 51 ++++++++++++++++++++++++++++++++++++++++++++++++++
>  1 file changed, 51 insertions(+)
> 
> diff --git a/arch/arm64/kvm/guest.c b/arch/arm64/kvm/guest.c
> index 8cfa889..4a2ad60 100644
> --- a/arch/arm64/kvm/guest.c
> +++ b/arch/arm64/kvm/guest.c
> @@ -366,6 +366,14 @@ static int copy_core_reg_indices(const struct kvm_vcpu *vcpu,
>  			continue;
>  		}
>  
> +		/*
> +		 * The KVM_REG_ARM64_SVE regs must be used instead of
> +		 * KVM_REG_ARM_CORE for accessing the FPSIMD V-registers on
> +		 * SVE-enabled vcpus:
> +		 */
> +		if (vcpu_has_sve(vcpu) && core_reg_offset_is_vreg(i))
> +			continue;
> +
>  		if (uind) {
>  			if (put_user(reg, *uind))
>  				return -EFAULT;
> @@ -436,6 +444,44 @@ static int get_timer_reg(struct kvm_vcpu *vcpu, const struct kvm_one_reg *reg)
>  	return copy_to_user(uaddr, &val, KVM_REG_SIZE(reg->id)) ? -EFAULT : 0;
>  }
>  
> +static unsigned long num_sve_regs(const struct kvm_vcpu *vcpu)
> +{
> +	/* Only the first slice ever exists, for now */
> +	const unsigned int slices = 1;
> +
> +	if (!vcpu_has_sve(vcpu))
> +		return 0;
> +
> +	return slices * (SVE_NUM_PREGS + SVE_NUM_ZREGS + 1 /* FFR */);
> +}
> +
> +static int copy_sve_reg_indices(const struct kvm_vcpu *vcpu, u64 __user **uind)
> +{
> +	/* Only the first slice ever exists, for now */
> +	const unsigned int slices = 1;
> +	unsigned int i, n;
> +
> +	if (!vcpu_has_sve(vcpu))
> +		return 0;
> +
> +	for (i = 0; i < slices; i++) {
> +		for (n = 0; n < SVE_NUM_ZREGS; n++) {
> +			if (put_user(KVM_REG_ARM64_SVE_ZREG(n, i), (*uind)++))
> +				return -EFAULT;
> +		}
> +
> +		for (n = 0; n < SVE_NUM_PREGS; n++) {
> +			if (put_user(KVM_REG_ARM64_SVE_PREG(n, i), (*uind)++))
> +				return -EFAULT;
> +		}
> +
> +		if (put_user(KVM_REG_ARM64_SVE_FFR(i), (*uind)++))
> +			return -EFAULT;
> +	}
> +
> +	return 0;
> +}
> +
>  /**
>   * kvm_arm_num_regs - how many registers do we present via KVM_GET_ONE_REG
>   *
> @@ -446,6 +492,7 @@ unsigned long kvm_arm_num_regs(struct kvm_vcpu *vcpu)
>  	unsigned long res = 0;
>  
>  	res += num_core_regs(vcpu);
> +	res += num_sve_regs(vcpu);
>  	res += kvm_arm_num_sys_reg_descs(vcpu);
>  	res += kvm_arm_get_fw_num_regs(vcpu);
>  	res += NUM_TIMER_REGS;
> @@ -466,6 +513,10 @@ int kvm_arm_copy_reg_indices(struct kvm_vcpu *vcpu, u64 __user *uindices)
>  	if (ret < 0)
>  		return ret;
>  
> +	ret = copy_sve_reg_indices(vcpu, &uindices);
> +	if (ret)
> +		return ret;
> +
>  	ret = kvm_arm_copy_fw_reg_indices(vcpu, uindices);
>  	if (ret)
>  		return ret;
> 

-- 
Julien Thierry

_______________________________________________
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] 205+ messages in thread

* Re: [PATCH v5 22/26] KVM: arm64/sve: Add pseudo-register for the guest's vector lengths
  2019-02-18 19:52   ` Dave Martin
@ 2019-02-21 17:48     ` Julien Thierry
  -1 siblings, 0 replies; 205+ messages in thread
From: Julien Thierry @ 2019-02-21 17:48 UTC (permalink / raw)
  To: Dave Martin, kvmarm
  Cc: Okamoto Takayuki, Christoffer Dall, Ard Biesheuvel, Marc Zyngier,
	Catalin Marinas, Will Deacon, Zhang Lei, linux-arm-kernel

Hi Dave,

On 18/02/2019 19:52, Dave Martin wrote:
> This patch adds a new pseudo-register KVM_REG_ARM64_SVE_VLS to
> allow userspace to set and query the set of vector lengths visible
> to the guest, along with corresponding storage in struct
> kvm_vcpu_arch.
> 
> In the future, multiple register slices per SVE register may be
> visible through the ioctl interface.  Once the set of slices has
> been determined we would not be able to allow the vector length set
> to be changed any more, in order to avoid userspace seeing
> inconsistent sets of registers.  For this reason, this patch adds
> support to track vcpu finalization explicitly, and enforce proper
> sequencing of ioctls.
> 
> The new pseudo-register is not exposed yet.  Subsequent patches
> will allow SVE to be turned on for guest vcpus, making it visible.
> 
> Signed-off-by: Dave Martin <Dave.Martin@arm.com>
> 
> ---
> 
> Changes since v4:
> 
>  * Add a UAPI header comment indicating the pseudo-register status of
>    KVM_REG_ARM64_SVE_VLS.
> 
>  * Get rid of the sve_vqs[] array from struct kvm_vcpu_arch.  This
>    array is pointless, because its contents must match the host's
>    internal sve_vq_map anyway, up to vcpu->arch.sve_max_vl.
> 
>    The ioctl register accessors are slow-path code, so we can decode
>    or reconstruct sve_vqs[] on demand instead, for exchange with
>    userspace.
> 
>  * For compatibility with potential future architecture extensions,
>    enabling vector lengths above 256 bytes for the guest is explicitly
>    disallowed now (because the code for exposing additional bits
>    through ioctl is currently missing).  This can be addressed later
>    if/when needed.
> 
> Note:
> 
>  * I defensively pass an array by pointer here, to help avoid
>    accidentally breaking assumptions during future maintenance.
> 
>    Due to (over?)zealous constification, this causes the following
>    sparse warning.  I think this is sparse getting confused: I am not
>    relying on any kernel-specific semantics here, and GCC generates no
>    warning.
> 
> +arch/arm64/kvm/guest.c:33: warning: incorrect type in argument 1 (different modifiers)
> +arch/arm64/kvm/guest.c:33:    expected unsigned long long const [usertype] ( *const vqs )[8]
> +arch/arm64/kvm/guest.c:33:    got unsigned long long [usertype] ( * )[8]
> 
> ---
>  arch/arm64/include/asm/kvm_host.h |   7 ++-
>  arch/arm64/include/uapi/asm/kvm.h |   4 ++
>  arch/arm64/kvm/guest.c            | 124 ++++++++++++++++++++++++++++++++++++--
>  arch/arm64/kvm/reset.c            |   9 +++
>  4 files changed, 136 insertions(+), 8 deletions(-)
> 
> diff --git a/arch/arm64/include/asm/kvm_host.h b/arch/arm64/include/asm/kvm_host.h
> index 015c2578..e53119a 100644
> --- a/arch/arm64/include/asm/kvm_host.h
> +++ b/arch/arm64/include/asm/kvm_host.h
> @@ -24,6 +24,7 @@
>  
>  #include <linux/bitmap.h>
>  #include <linux/types.h>
> +#include <linux/kernel.h>
>  #include <linux/kvm_types.h>
>  #include <asm/cpufeature.h>
>  #include <asm/daifflags.h>
> @@ -331,6 +332,7 @@ struct kvm_vcpu_arch {
>  #define KVM_ARM64_HOST_SVE_IN_USE	(1 << 3) /* backup for host TIF_SVE */
>  #define KVM_ARM64_HOST_SVE_ENABLED	(1 << 4) /* SVE enabled for EL0 */
>  #define KVM_ARM64_GUEST_HAS_SVE		(1 << 5) /* SVE exposed to guest */
> +#define KVM_ARM64_VCPU_FINALIZED	(1 << 6) /* vcpu config completed */
>  
>  #define vcpu_has_sve(vcpu) (system_supports_sve() && \
>  			    ((vcpu)->arch.flags & KVM_ARM64_GUEST_HAS_SVE))
> @@ -554,7 +556,8 @@ void kvm_arch_free_vm(struct kvm *kvm);
>  int kvm_arm_setup_stage2(struct kvm *kvm, unsigned long type);
>  
>  /* Commit to the set of vcpu registers currently configured: */
> -static inline int kvm_arm_vcpu_finalize(struct kvm_vcpu *vcpu) { return 0; }
> -#define kvm_arm_vcpu_finalized(vcpu) true
> +int kvm_arm_vcpu_finalize(struct kvm_vcpu *vcpu);
> +#define kvm_arm_vcpu_finalized(vcpu) \
> +	((vcpu)->arch.flags & KVM_ARM64_VCPU_FINALIZED)
>  
>  #endif /* __ARM64_KVM_HOST_H__ */
> diff --git a/arch/arm64/include/uapi/asm/kvm.h b/arch/arm64/include/uapi/asm/kvm.h
> index ced760c..7ff1bd4 100644
> --- a/arch/arm64/include/uapi/asm/kvm.h
> +++ b/arch/arm64/include/uapi/asm/kvm.h
> @@ -243,6 +243,10 @@ struct kvm_vcpu_events {
>  					 ((n) << 5) | (i))
>  #define KVM_REG_ARM64_SVE_FFR(i)	KVM_REG_ARM64_SVE_PREG(16, i)
>  
> +/* Vector lengths pseudo-register: */
> +#define KVM_REG_ARM64_SVE_VLS		(KVM_REG_ARM64 | KVM_REG_ARM64_SVE | \
> +					 KVM_REG_SIZE_U512 | 0xffff)
> +
>  /* Device Control API: ARM VGIC */
>  #define KVM_DEV_ARM_VGIC_GRP_ADDR	0
>  #define KVM_DEV_ARM_VGIC_GRP_DIST_REGS	1
> diff --git a/arch/arm64/kvm/guest.c b/arch/arm64/kvm/guest.c
> index 4a2ad60..5f48c17 100644
> --- a/arch/arm64/kvm/guest.c
> +++ b/arch/arm64/kvm/guest.c
> @@ -217,6 +217,81 @@ static int set_core_reg(struct kvm_vcpu *vcpu, const struct kvm_one_reg *reg)
>  	return err;
>  }
>  
> +#define vq_word(vq) (((vq) - SVE_VQ_MIN) / 64)
> +#define vq_mask(vq) ((u64)1 << ((vq) - SVE_VQ_MIN) % 64)
> +
> +static bool vq_present(
> +	const u64 (*const vqs)[DIV_ROUND_UP(SVE_VQ_MAX - SVE_VQ_MIN + 1, 64)],
> +	unsigned int vq)
> +{
> +	return (*vqs)[vq_word(vq)] & vq_mask(vq);
> +}
> +
> +static int get_sve_vls(struct kvm_vcpu *vcpu, const struct kvm_one_reg *reg)
> +{
> +	unsigned int max_vq, vq;
> +	u64 vqs[DIV_ROUND_UP(SVE_VQ_MAX - SVE_VQ_MIN + 1, 64)];
> +
> +	if (WARN_ON(!sve_vl_valid(vcpu->arch.sve_max_vl)))
> +		return -EINVAL;
> +
> +	memset(vqs, 0, sizeof(vqs));
> +
> +	max_vq = sve_vq_from_vl(vcpu->arch.sve_max_vl);
> +	for (vq = SVE_VQ_MIN; vq <= max_vq; ++vq)
> +		if (sve_vq_available(vq))
> +			vqs[vq_word(vq)] |= vq_mask(vq);
> +
> +	BUILD_BUG_ON(sizeof(vqs) != KVM_REG_SIZE(reg->id));

reg->id is not know at build time. From my understanding of
BUILD_BUG_ON(), things actually ends up evaluated at runtime but I'm not
sure what happens when doing sizeof(char[1- 2*0]) at runtime.

Anyway, I don't think this is intended.

> +	if (copy_to_user((void __user *)reg->addr, vqs, sizeof(vqs)))
> +		return -EFAULT;
> +
> +	return 0;
> +}
> +
> +static int set_sve_vls(struct kvm_vcpu *vcpu, const struct kvm_one_reg *reg)
> +{
> +	unsigned int max_vq, vq;
> +	u64 vqs[DIV_ROUND_UP(SVE_VQ_MAX - SVE_VQ_MIN + 1, 64)];
> +
> +	if (kvm_arm_vcpu_finalized(vcpu))
> +		return -EPERM; /* too late! */
> +
> +	if (WARN_ON(vcpu->arch.sve_state))
> +		return -EINVAL;
> +
> +	BUILD_BUG_ON(sizeof(vqs) != KVM_REG_SIZE(reg->id));

Same as above.

> +	if (copy_from_user(vqs, (const void __user *)reg->addr, sizeof(vqs)))
> +		return -EFAULT;
> +
> +	max_vq = 0;
> +	for (vq = SVE_VQ_MIN; vq <= SVE_VQ_MAX; ++vq)
> +		if (vq_present(&vqs, vq))
> +			max_vq = vq;
> +
> +	/*
> +	 * The get_sve_reg()/set_sve_reg() ioctl interface will need
> +	 * to be extended with multiple register slice support in
> +	 * order to support vector lengths greater than
> +	 * SVE_VL_ARCH_MAX:
> +	 */
> +	if (WARN_ONCE(sve_vl_from_vq(max_vq) > SVE_VL_ARCH_MAX,
> +		      "KVM: Requested vector length not supported yet\n"))
> +		return -EINVAL;
> +
> +	for (vq = SVE_VQ_MIN; vq <= max_vq; ++vq)
> +		if (vq_present(&vqs, vq) != sve_vq_available(vq))
> +			return -EINVAL;
> +
> +	/* Can't run with no vector lengths at all: */
> +	if (max_vq < SVE_VQ_MIN)
> +		return -EINVAL;
> +
> +	vcpu->arch.sve_max_vl = sve_vl_from_vq(max_vq);
> +
> +	return 0;
> +}
> +
>  #define SVE_REG_SLICE_SHIFT	0
>  #define SVE_REG_SLICE_BITS	5
>  #define SVE_REG_ID_SHIFT	(SVE_REG_SLICE_SHIFT + SVE_REG_SLICE_BITS)
> @@ -297,9 +372,21 @@ static int sve_reg_region(struct sve_state_region *region,
>  static int get_sve_reg(struct kvm_vcpu *vcpu, const struct kvm_one_reg *reg)
>  {
>  	struct sve_state_region region;
> +	int ret;
>  	char __user *uptr = (char __user *)reg->addr;
>  
> -	if (!vcpu_has_sve(vcpu) || sve_reg_region(&region, vcpu, reg))
> +	if (!vcpu_has_sve(vcpu))
> +		return -ENOENT;
> +
> +	if (reg->id == KVM_REG_ARM64_SVE_VLS)
> +		return get_sve_vls(vcpu, reg);
> +
> +	/* Finalize the number of slices per SVE register: */
> +	ret = kvm_arm_vcpu_finalize(vcpu);

Having this here feels a bit random...

I'd suggest considering the pseudo-register outside of the SVE co-proc,
as part of a set of registers that do not finalize a vcpu when accessed.
All other registers (even non-sve ones) would finalize the vcpu when
accessed from userland.

Does that make sense?


> +	if (ret)
> +		return ret;
> +
> +	if (sve_reg_region(&region, vcpu, reg))
>  		return -ENOENT;
>  
>  	if (copy_to_user(uptr, vcpu->arch.sve_state + region.koffset,
> @@ -313,9 +400,21 @@ static int get_sve_reg(struct kvm_vcpu *vcpu, const struct kvm_one_reg *reg)
>  static int set_sve_reg(struct kvm_vcpu *vcpu, const struct kvm_one_reg *reg)
>  {
>  	struct sve_state_region region;
> +	int ret;
>  	const char __user *uptr = (const char __user *)reg->addr;
>  
> -	if (!vcpu_has_sve(vcpu) || sve_reg_region(&region, vcpu, reg))
> +	if (!vcpu_has_sve(vcpu))
> +		return -ENOENT;
> +
> +	if (reg->id == KVM_REG_ARM64_SVE_VLS)
> +		return set_sve_vls(vcpu, reg);
> +
> +	/* Finalize the number of slices per SVE register: */
> +	ret = kvm_arm_vcpu_finalize(vcpu);
> +	if (ret)
> +		return ret;
> +
> +	if (sve_reg_region(&region, vcpu, reg))
>  		return -ENOENT;
>  
>  	if (copy_from_user(vcpu->arch.sve_state + region.koffset, uptr,
> @@ -452,30 +551,43 @@ static unsigned long num_sve_regs(const struct kvm_vcpu *vcpu)
>  	if (!vcpu_has_sve(vcpu))
>  		return 0;
>  
> -	return slices * (SVE_NUM_PREGS + SVE_NUM_ZREGS + 1 /* FFR */);
> +	return slices * (SVE_NUM_PREGS + SVE_NUM_ZREGS + 1 /* FFR */)
> +		+ 1; /* KVM_REG_ARM64_SVE_VLS */
>  }
>  
>  static int copy_sve_reg_indices(const struct kvm_vcpu *vcpu, u64 __user **uind)
>  {
>  	/* Only the first slice ever exists, for now */
>  	const unsigned int slices = 1;
> +	u64 reg;
>  	unsigned int i, n;
>  
>  	if (!vcpu_has_sve(vcpu))
>  		return 0;
>  
> +	/*
> +	 * Enumerate this first, so that userspace can save/restore in
> +	 * the order reported by KVM_GET_REG_LIST:
> +	 */
> +	reg = KVM_REG_ARM64_SVE_VLS;
> +	if (put_user(reg, (*uind)++))
> +		return -EFAULT;
> +
>  	for (i = 0; i < slices; i++) {
>  		for (n = 0; n < SVE_NUM_ZREGS; n++) {
> -			if (put_user(KVM_REG_ARM64_SVE_ZREG(n, i), (*uind)++))
> +			reg = KVM_REG_ARM64_SVE_ZREG(n, i);
> +			if (put_user(reg, (*uind)++))
>  				return -EFAULT;
>  		}
>  
>  		for (n = 0; n < SVE_NUM_PREGS; n++) {
> -			if (put_user(KVM_REG_ARM64_SVE_PREG(n, i), (*uind)++))
> +			reg = KVM_REG_ARM64_SVE_PREG(n, i);
> +			if (put_user(reg, (*uind)++))
>  				return -EFAULT;
>  		}
>  
> -		if (put_user(KVM_REG_ARM64_SVE_FFR(i), (*uind)++))
> +		reg = KVM_REG_ARM64_SVE_FFR(i);
> +		if (put_user(reg, (*uind)++))
>  			return -EFAULT;
>  	}
>  
> diff --git a/arch/arm64/kvm/reset.c b/arch/arm64/kvm/reset.c
> index b72a3dd..1379fb2 100644
> --- a/arch/arm64/kvm/reset.c
> +++ b/arch/arm64/kvm/reset.c
> @@ -98,6 +98,15 @@ int kvm_arch_vm_ioctl_check_extension(struct kvm *kvm, long ext)
>  	return r;
>  }
>  
> +int kvm_arm_vcpu_finalize(struct kvm_vcpu *vcpu)
> +{
> +	if (likely(kvm_arm_vcpu_finalized(vcpu)))
> +		return 0;
> +
> +	vcpu->arch.flags |= KVM_ARM64_VCPU_FINALIZED;
> +	return 0;
> +}
> +

I think that the introduction of this flag and setting it should be part
of the previous patch.

Cheers,

-- 
Julien Thierry

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

* Re: [PATCH v5 22/26] KVM: arm64/sve: Add pseudo-register for the guest's vector lengths
@ 2019-02-21 17:48     ` Julien Thierry
  0 siblings, 0 replies; 205+ messages in thread
From: Julien Thierry @ 2019-02-21 17:48 UTC (permalink / raw)
  To: Dave Martin, kvmarm
  Cc: Okamoto Takayuki, Christoffer Dall, Ard Biesheuvel, Marc Zyngier,
	Catalin Marinas, Will Deacon, Zhang Lei, linux-arm-kernel

Hi Dave,

On 18/02/2019 19:52, Dave Martin wrote:
> This patch adds a new pseudo-register KVM_REG_ARM64_SVE_VLS to
> allow userspace to set and query the set of vector lengths visible
> to the guest, along with corresponding storage in struct
> kvm_vcpu_arch.
> 
> In the future, multiple register slices per SVE register may be
> visible through the ioctl interface.  Once the set of slices has
> been determined we would not be able to allow the vector length set
> to be changed any more, in order to avoid userspace seeing
> inconsistent sets of registers.  For this reason, this patch adds
> support to track vcpu finalization explicitly, and enforce proper
> sequencing of ioctls.
> 
> The new pseudo-register is not exposed yet.  Subsequent patches
> will allow SVE to be turned on for guest vcpus, making it visible.
> 
> Signed-off-by: Dave Martin <Dave.Martin@arm.com>
> 
> ---
> 
> Changes since v4:
> 
>  * Add a UAPI header comment indicating the pseudo-register status of
>    KVM_REG_ARM64_SVE_VLS.
> 
>  * Get rid of the sve_vqs[] array from struct kvm_vcpu_arch.  This
>    array is pointless, because its contents must match the host's
>    internal sve_vq_map anyway, up to vcpu->arch.sve_max_vl.
> 
>    The ioctl register accessors are slow-path code, so we can decode
>    or reconstruct sve_vqs[] on demand instead, for exchange with
>    userspace.
> 
>  * For compatibility with potential future architecture extensions,
>    enabling vector lengths above 256 bytes for the guest is explicitly
>    disallowed now (because the code for exposing additional bits
>    through ioctl is currently missing).  This can be addressed later
>    if/when needed.
> 
> Note:
> 
>  * I defensively pass an array by pointer here, to help avoid
>    accidentally breaking assumptions during future maintenance.
> 
>    Due to (over?)zealous constification, this causes the following
>    sparse warning.  I think this is sparse getting confused: I am not
>    relying on any kernel-specific semantics here, and GCC generates no
>    warning.
> 
> +arch/arm64/kvm/guest.c:33: warning: incorrect type in argument 1 (different modifiers)
> +arch/arm64/kvm/guest.c:33:    expected unsigned long long const [usertype] ( *const vqs )[8]
> +arch/arm64/kvm/guest.c:33:    got unsigned long long [usertype] ( * )[8]
> 
> ---
>  arch/arm64/include/asm/kvm_host.h |   7 ++-
>  arch/arm64/include/uapi/asm/kvm.h |   4 ++
>  arch/arm64/kvm/guest.c            | 124 ++++++++++++++++++++++++++++++++++++--
>  arch/arm64/kvm/reset.c            |   9 +++
>  4 files changed, 136 insertions(+), 8 deletions(-)
> 
> diff --git a/arch/arm64/include/asm/kvm_host.h b/arch/arm64/include/asm/kvm_host.h
> index 015c2578..e53119a 100644
> --- a/arch/arm64/include/asm/kvm_host.h
> +++ b/arch/arm64/include/asm/kvm_host.h
> @@ -24,6 +24,7 @@
>  
>  #include <linux/bitmap.h>
>  #include <linux/types.h>
> +#include <linux/kernel.h>
>  #include <linux/kvm_types.h>
>  #include <asm/cpufeature.h>
>  #include <asm/daifflags.h>
> @@ -331,6 +332,7 @@ struct kvm_vcpu_arch {
>  #define KVM_ARM64_HOST_SVE_IN_USE	(1 << 3) /* backup for host TIF_SVE */
>  #define KVM_ARM64_HOST_SVE_ENABLED	(1 << 4) /* SVE enabled for EL0 */
>  #define KVM_ARM64_GUEST_HAS_SVE		(1 << 5) /* SVE exposed to guest */
> +#define KVM_ARM64_VCPU_FINALIZED	(1 << 6) /* vcpu config completed */
>  
>  #define vcpu_has_sve(vcpu) (system_supports_sve() && \
>  			    ((vcpu)->arch.flags & KVM_ARM64_GUEST_HAS_SVE))
> @@ -554,7 +556,8 @@ void kvm_arch_free_vm(struct kvm *kvm);
>  int kvm_arm_setup_stage2(struct kvm *kvm, unsigned long type);
>  
>  /* Commit to the set of vcpu registers currently configured: */
> -static inline int kvm_arm_vcpu_finalize(struct kvm_vcpu *vcpu) { return 0; }
> -#define kvm_arm_vcpu_finalized(vcpu) true
> +int kvm_arm_vcpu_finalize(struct kvm_vcpu *vcpu);
> +#define kvm_arm_vcpu_finalized(vcpu) \
> +	((vcpu)->arch.flags & KVM_ARM64_VCPU_FINALIZED)
>  
>  #endif /* __ARM64_KVM_HOST_H__ */
> diff --git a/arch/arm64/include/uapi/asm/kvm.h b/arch/arm64/include/uapi/asm/kvm.h
> index ced760c..7ff1bd4 100644
> --- a/arch/arm64/include/uapi/asm/kvm.h
> +++ b/arch/arm64/include/uapi/asm/kvm.h
> @@ -243,6 +243,10 @@ struct kvm_vcpu_events {
>  					 ((n) << 5) | (i))
>  #define KVM_REG_ARM64_SVE_FFR(i)	KVM_REG_ARM64_SVE_PREG(16, i)
>  
> +/* Vector lengths pseudo-register: */
> +#define KVM_REG_ARM64_SVE_VLS		(KVM_REG_ARM64 | KVM_REG_ARM64_SVE | \
> +					 KVM_REG_SIZE_U512 | 0xffff)
> +
>  /* Device Control API: ARM VGIC */
>  #define KVM_DEV_ARM_VGIC_GRP_ADDR	0
>  #define KVM_DEV_ARM_VGIC_GRP_DIST_REGS	1
> diff --git a/arch/arm64/kvm/guest.c b/arch/arm64/kvm/guest.c
> index 4a2ad60..5f48c17 100644
> --- a/arch/arm64/kvm/guest.c
> +++ b/arch/arm64/kvm/guest.c
> @@ -217,6 +217,81 @@ static int set_core_reg(struct kvm_vcpu *vcpu, const struct kvm_one_reg *reg)
>  	return err;
>  }
>  
> +#define vq_word(vq) (((vq) - SVE_VQ_MIN) / 64)
> +#define vq_mask(vq) ((u64)1 << ((vq) - SVE_VQ_MIN) % 64)
> +
> +static bool vq_present(
> +	const u64 (*const vqs)[DIV_ROUND_UP(SVE_VQ_MAX - SVE_VQ_MIN + 1, 64)],
> +	unsigned int vq)
> +{
> +	return (*vqs)[vq_word(vq)] & vq_mask(vq);
> +}
> +
> +static int get_sve_vls(struct kvm_vcpu *vcpu, const struct kvm_one_reg *reg)
> +{
> +	unsigned int max_vq, vq;
> +	u64 vqs[DIV_ROUND_UP(SVE_VQ_MAX - SVE_VQ_MIN + 1, 64)];
> +
> +	if (WARN_ON(!sve_vl_valid(vcpu->arch.sve_max_vl)))
> +		return -EINVAL;
> +
> +	memset(vqs, 0, sizeof(vqs));
> +
> +	max_vq = sve_vq_from_vl(vcpu->arch.sve_max_vl);
> +	for (vq = SVE_VQ_MIN; vq <= max_vq; ++vq)
> +		if (sve_vq_available(vq))
> +			vqs[vq_word(vq)] |= vq_mask(vq);
> +
> +	BUILD_BUG_ON(sizeof(vqs) != KVM_REG_SIZE(reg->id));

reg->id is not know at build time. From my understanding of
BUILD_BUG_ON(), things actually ends up evaluated at runtime but I'm not
sure what happens when doing sizeof(char[1- 2*0]) at runtime.

Anyway, I don't think this is intended.

> +	if (copy_to_user((void __user *)reg->addr, vqs, sizeof(vqs)))
> +		return -EFAULT;
> +
> +	return 0;
> +}
> +
> +static int set_sve_vls(struct kvm_vcpu *vcpu, const struct kvm_one_reg *reg)
> +{
> +	unsigned int max_vq, vq;
> +	u64 vqs[DIV_ROUND_UP(SVE_VQ_MAX - SVE_VQ_MIN + 1, 64)];
> +
> +	if (kvm_arm_vcpu_finalized(vcpu))
> +		return -EPERM; /* too late! */
> +
> +	if (WARN_ON(vcpu->arch.sve_state))
> +		return -EINVAL;
> +
> +	BUILD_BUG_ON(sizeof(vqs) != KVM_REG_SIZE(reg->id));

Same as above.

> +	if (copy_from_user(vqs, (const void __user *)reg->addr, sizeof(vqs)))
> +		return -EFAULT;
> +
> +	max_vq = 0;
> +	for (vq = SVE_VQ_MIN; vq <= SVE_VQ_MAX; ++vq)
> +		if (vq_present(&vqs, vq))
> +			max_vq = vq;
> +
> +	/*
> +	 * The get_sve_reg()/set_sve_reg() ioctl interface will need
> +	 * to be extended with multiple register slice support in
> +	 * order to support vector lengths greater than
> +	 * SVE_VL_ARCH_MAX:
> +	 */
> +	if (WARN_ONCE(sve_vl_from_vq(max_vq) > SVE_VL_ARCH_MAX,
> +		      "KVM: Requested vector length not supported yet\n"))
> +		return -EINVAL;
> +
> +	for (vq = SVE_VQ_MIN; vq <= max_vq; ++vq)
> +		if (vq_present(&vqs, vq) != sve_vq_available(vq))
> +			return -EINVAL;
> +
> +	/* Can't run with no vector lengths at all: */
> +	if (max_vq < SVE_VQ_MIN)
> +		return -EINVAL;
> +
> +	vcpu->arch.sve_max_vl = sve_vl_from_vq(max_vq);
> +
> +	return 0;
> +}
> +
>  #define SVE_REG_SLICE_SHIFT	0
>  #define SVE_REG_SLICE_BITS	5
>  #define SVE_REG_ID_SHIFT	(SVE_REG_SLICE_SHIFT + SVE_REG_SLICE_BITS)
> @@ -297,9 +372,21 @@ static int sve_reg_region(struct sve_state_region *region,
>  static int get_sve_reg(struct kvm_vcpu *vcpu, const struct kvm_one_reg *reg)
>  {
>  	struct sve_state_region region;
> +	int ret;
>  	char __user *uptr = (char __user *)reg->addr;
>  
> -	if (!vcpu_has_sve(vcpu) || sve_reg_region(&region, vcpu, reg))
> +	if (!vcpu_has_sve(vcpu))
> +		return -ENOENT;
> +
> +	if (reg->id == KVM_REG_ARM64_SVE_VLS)
> +		return get_sve_vls(vcpu, reg);
> +
> +	/* Finalize the number of slices per SVE register: */
> +	ret = kvm_arm_vcpu_finalize(vcpu);

Having this here feels a bit random...

I'd suggest considering the pseudo-register outside of the SVE co-proc,
as part of a set of registers that do not finalize a vcpu when accessed.
All other registers (even non-sve ones) would finalize the vcpu when
accessed from userland.

Does that make sense?


> +	if (ret)
> +		return ret;
> +
> +	if (sve_reg_region(&region, vcpu, reg))
>  		return -ENOENT;
>  
>  	if (copy_to_user(uptr, vcpu->arch.sve_state + region.koffset,
> @@ -313,9 +400,21 @@ static int get_sve_reg(struct kvm_vcpu *vcpu, const struct kvm_one_reg *reg)
>  static int set_sve_reg(struct kvm_vcpu *vcpu, const struct kvm_one_reg *reg)
>  {
>  	struct sve_state_region region;
> +	int ret;
>  	const char __user *uptr = (const char __user *)reg->addr;
>  
> -	if (!vcpu_has_sve(vcpu) || sve_reg_region(&region, vcpu, reg))
> +	if (!vcpu_has_sve(vcpu))
> +		return -ENOENT;
> +
> +	if (reg->id == KVM_REG_ARM64_SVE_VLS)
> +		return set_sve_vls(vcpu, reg);
> +
> +	/* Finalize the number of slices per SVE register: */
> +	ret = kvm_arm_vcpu_finalize(vcpu);
> +	if (ret)
> +		return ret;
> +
> +	if (sve_reg_region(&region, vcpu, reg))
>  		return -ENOENT;
>  
>  	if (copy_from_user(vcpu->arch.sve_state + region.koffset, uptr,
> @@ -452,30 +551,43 @@ static unsigned long num_sve_regs(const struct kvm_vcpu *vcpu)
>  	if (!vcpu_has_sve(vcpu))
>  		return 0;
>  
> -	return slices * (SVE_NUM_PREGS + SVE_NUM_ZREGS + 1 /* FFR */);
> +	return slices * (SVE_NUM_PREGS + SVE_NUM_ZREGS + 1 /* FFR */)
> +		+ 1; /* KVM_REG_ARM64_SVE_VLS */
>  }
>  
>  static int copy_sve_reg_indices(const struct kvm_vcpu *vcpu, u64 __user **uind)
>  {
>  	/* Only the first slice ever exists, for now */
>  	const unsigned int slices = 1;
> +	u64 reg;
>  	unsigned int i, n;
>  
>  	if (!vcpu_has_sve(vcpu))
>  		return 0;
>  
> +	/*
> +	 * Enumerate this first, so that userspace can save/restore in
> +	 * the order reported by KVM_GET_REG_LIST:
> +	 */
> +	reg = KVM_REG_ARM64_SVE_VLS;
> +	if (put_user(reg, (*uind)++))
> +		return -EFAULT;
> +
>  	for (i = 0; i < slices; i++) {
>  		for (n = 0; n < SVE_NUM_ZREGS; n++) {
> -			if (put_user(KVM_REG_ARM64_SVE_ZREG(n, i), (*uind)++))
> +			reg = KVM_REG_ARM64_SVE_ZREG(n, i);
> +			if (put_user(reg, (*uind)++))
>  				return -EFAULT;
>  		}
>  
>  		for (n = 0; n < SVE_NUM_PREGS; n++) {
> -			if (put_user(KVM_REG_ARM64_SVE_PREG(n, i), (*uind)++))
> +			reg = KVM_REG_ARM64_SVE_PREG(n, i);
> +			if (put_user(reg, (*uind)++))
>  				return -EFAULT;
>  		}
>  
> -		if (put_user(KVM_REG_ARM64_SVE_FFR(i), (*uind)++))
> +		reg = KVM_REG_ARM64_SVE_FFR(i);
> +		if (put_user(reg, (*uind)++))
>  			return -EFAULT;
>  	}
>  
> diff --git a/arch/arm64/kvm/reset.c b/arch/arm64/kvm/reset.c
> index b72a3dd..1379fb2 100644
> --- a/arch/arm64/kvm/reset.c
> +++ b/arch/arm64/kvm/reset.c
> @@ -98,6 +98,15 @@ int kvm_arch_vm_ioctl_check_extension(struct kvm *kvm, long ext)
>  	return r;
>  }
>  
> +int kvm_arm_vcpu_finalize(struct kvm_vcpu *vcpu)
> +{
> +	if (likely(kvm_arm_vcpu_finalized(vcpu)))
> +		return 0;
> +
> +	vcpu->arch.flags |= KVM_ARM64_VCPU_FINALIZED;
> +	return 0;
> +}
> +

I think that the introduction of this flag and setting it should be part
of the previous patch.

Cheers,

-- 
Julien Thierry

_______________________________________________
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] 205+ messages in thread

* Re: [PATCH v5 23/26] KVM: arm64/sve: Allow userspace to enable SVE for vcpus
  2019-02-18 19:52   ` Dave Martin
@ 2019-02-22  9:05     ` Julien Thierry
  -1 siblings, 0 replies; 205+ messages in thread
From: Julien Thierry @ 2019-02-22  9:05 UTC (permalink / raw)
  To: Dave Martin, kvmarm
  Cc: Okamoto Takayuki, Christoffer Dall, Ard Biesheuvel, Marc Zyngier,
	Catalin Marinas, Will Deacon, Zhang Lei, linux-arm-kernel

Hi Dave,

On 18/02/2019 19:52, Dave Martin wrote:
> Now that all the pieces are in place, this patch offers a new flag
> KVM_ARM_VCPU_SVE that userspace can pass to KVM_ARM_VCPU_INIT to
> turn on SVE for the guest, on a per-vcpu basis.
> 
> As part of this, support for initialisation and reset of the SVE
> vector length set and registers is added in the appropriate places.
> Allocation SVE registers is deferred until kvm_arm_vcpu_finalize(),
> by which time the size of the registers is known.
> 
> Setting the vector lengths supported by the vcpu is considered
> configuration of the emulated hardware rather than runtime
> configuration, so no support is offered for changing the vector
> lengths of an existing vcpu across reset.
> 
> Signed-off-by: Dave Martin <Dave.Martin@arm.com>
> 
> ---
> 
> Changes since v4:
> 
>  * Pull out vcpu_sve_state_size(), for use earlier in the series.
> 
>  * Remove unnecessary vcpu->arch.sve_vqs[], and clamp maximum guest
>    vector length to 256 bytes for forwards compatibility.
> 
>    (See "KVM: arm64/sve: Add pseudo-register for the guest's vector
>    lengths".)
> 
>  * Minor tidyups to make some checks less verbose.
> ---
>  arch/arm64/include/asm/kvm_host.h |  2 +-
>  arch/arm64/include/uapi/asm/kvm.h |  1 +
>  arch/arm64/kvm/reset.c            | 70 ++++++++++++++++++++++++++++++++++++++-
>  3 files changed, 71 insertions(+), 2 deletions(-)
> 

[...]

> diff --git a/arch/arm64/include/uapi/asm/kvm.h b/arch/arm64/include/uapi/asm/kvm.h
> index 7ff1bd4..6963b7e 100644
> --- a/arch/arm64/include/uapi/asm/kvm.h
> +++ b/arch/arm64/include/uapi/asm/kvm.h
> @@ -102,6 +102,7 @@ struct kvm_regs {
>  #define KVM_ARM_VCPU_EL1_32BIT		1 /* CPU running a 32bit VM */
>  #define KVM_ARM_VCPU_PSCI_0_2		2 /* CPU uses PSCI v0.2 */
>  #define KVM_ARM_VCPU_PMU_V3		3 /* Support guest PMUv3 */
> +#define KVM_ARM_VCPU_SVE		4 /* enable SVE for this CPU */
>  
>  struct kvm_vcpu_init {
>  	__u32 target;
> diff --git a/arch/arm64/kvm/reset.c b/arch/arm64/kvm/reset.c
> index 1379fb2..e67cd2e 100644
> --- a/arch/arm64/kvm/reset.c
> +++ b/arch/arm64/kvm/reset.c

[...]

> @@ -98,11 +100,69 @@ int kvm_arch_vm_ioctl_check_extension(struct kvm *kvm, long ext)
>  	return r;
>  }
>  
> +static int kvm_reset_sve(struct kvm_vcpu *vcpu)
> +{
> +	if (!system_supports_sve())
> +		return -EINVAL;
> +
> +	/* If resetting an already-configured vcpu, just zero the SVE regs: */
> +	if (vcpu->arch.sve_state) {
> +		size_t size = vcpu_sve_state_size(vcpu);
> +
> +		if (!size || WARN_ON(!vcpu_has_sve(vcpu)))
> +			return -EINVAL;
> +
> +		memset(vcpu->arch.sve_state, 0, size);
> +		return 0;
> +	}
> +
> +	if (WARN_ON(!sve_vl_valid(sve_max_vl)))
> +		return -EINVAL;
> +
> +	/* If the full set of host vector lengths cannot be used, give up: */
> +	if (sve_max_virtualisable_vl < sve_max_vl)
> +		return -EINVAL;
> +
> +	/* Default to the set of vector lengths supported by the host */
> +	vcpu->arch.sve_max_vl = sve_max_vl;
> +
> +	/*
> +	 * The get_sve_reg()/set_sve_reg() ioctl interface will need
> +	 * to be extended with multiple register slice support in
> +	 * order to support vector lengths greater than
> +	 * SVE_VL_ARCH_MAX:
> +	 */
> +	if (WARN_ONCE(vcpu->arch.sve_max_vl > SVE_VL_ARCH_MAX,
> +		      "KVM: SVE vector length for guests limited to %d bytes\n",
> +		      SVE_VL_ARCH_MAX))
> +		vcpu->arch.sve_max_vl = SVE_VL_ARCH_MAX;
> +
> +	/*
> +	 * Userspace can still customize the vector lengths by writing
> +	 * KVM_REG_ARM64_SVE_VLS.  Allocation is deferred until
> +	 * kvm_arm_vcpu_finalize(), which freezes the configuration.
> +	 */
> +	vcpu->arch.flags |= KVM_ARM64_GUEST_HAS_SVE;
> +
> +	return 0;
> +}
> +
>  int kvm_arm_vcpu_finalize(struct kvm_vcpu *vcpu)
>  {
>  	if (likely(kvm_arm_vcpu_finalized(vcpu)))
>  		return 0;
>  
> +	if (vcpu_has_sve(vcpu)) {
> +		size_t size = vcpu_sve_state_size(vcpu);
> +
> +		if (!size)
> +			return -EINVAL;
> +
> +		vcpu->arch.sve_state = kzalloc(size, GFP_KERNEL);

We should probably free this in kvm_arch_vcpu_free().

Cheers,

-- 
Julien Thierry

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

* Re: [PATCH v5 23/26] KVM: arm64/sve: Allow userspace to enable SVE for vcpus
@ 2019-02-22  9:05     ` Julien Thierry
  0 siblings, 0 replies; 205+ messages in thread
From: Julien Thierry @ 2019-02-22  9:05 UTC (permalink / raw)
  To: Dave Martin, kvmarm
  Cc: Okamoto Takayuki, Christoffer Dall, Ard Biesheuvel, Marc Zyngier,
	Catalin Marinas, Will Deacon, Zhang Lei, linux-arm-kernel

Hi Dave,

On 18/02/2019 19:52, Dave Martin wrote:
> Now that all the pieces are in place, this patch offers a new flag
> KVM_ARM_VCPU_SVE that userspace can pass to KVM_ARM_VCPU_INIT to
> turn on SVE for the guest, on a per-vcpu basis.
> 
> As part of this, support for initialisation and reset of the SVE
> vector length set and registers is added in the appropriate places.
> Allocation SVE registers is deferred until kvm_arm_vcpu_finalize(),
> by which time the size of the registers is known.
> 
> Setting the vector lengths supported by the vcpu is considered
> configuration of the emulated hardware rather than runtime
> configuration, so no support is offered for changing the vector
> lengths of an existing vcpu across reset.
> 
> Signed-off-by: Dave Martin <Dave.Martin@arm.com>
> 
> ---
> 
> Changes since v4:
> 
>  * Pull out vcpu_sve_state_size(), for use earlier in the series.
> 
>  * Remove unnecessary vcpu->arch.sve_vqs[], and clamp maximum guest
>    vector length to 256 bytes for forwards compatibility.
> 
>    (See "KVM: arm64/sve: Add pseudo-register for the guest's vector
>    lengths".)
> 
>  * Minor tidyups to make some checks less verbose.
> ---
>  arch/arm64/include/asm/kvm_host.h |  2 +-
>  arch/arm64/include/uapi/asm/kvm.h |  1 +
>  arch/arm64/kvm/reset.c            | 70 ++++++++++++++++++++++++++++++++++++++-
>  3 files changed, 71 insertions(+), 2 deletions(-)
> 

[...]

> diff --git a/arch/arm64/include/uapi/asm/kvm.h b/arch/arm64/include/uapi/asm/kvm.h
> index 7ff1bd4..6963b7e 100644
> --- a/arch/arm64/include/uapi/asm/kvm.h
> +++ b/arch/arm64/include/uapi/asm/kvm.h
> @@ -102,6 +102,7 @@ struct kvm_regs {
>  #define KVM_ARM_VCPU_EL1_32BIT		1 /* CPU running a 32bit VM */
>  #define KVM_ARM_VCPU_PSCI_0_2		2 /* CPU uses PSCI v0.2 */
>  #define KVM_ARM_VCPU_PMU_V3		3 /* Support guest PMUv3 */
> +#define KVM_ARM_VCPU_SVE		4 /* enable SVE for this CPU */
>  
>  struct kvm_vcpu_init {
>  	__u32 target;
> diff --git a/arch/arm64/kvm/reset.c b/arch/arm64/kvm/reset.c
> index 1379fb2..e67cd2e 100644
> --- a/arch/arm64/kvm/reset.c
> +++ b/arch/arm64/kvm/reset.c

[...]

> @@ -98,11 +100,69 @@ int kvm_arch_vm_ioctl_check_extension(struct kvm *kvm, long ext)
>  	return r;
>  }
>  
> +static int kvm_reset_sve(struct kvm_vcpu *vcpu)
> +{
> +	if (!system_supports_sve())
> +		return -EINVAL;
> +
> +	/* If resetting an already-configured vcpu, just zero the SVE regs: */
> +	if (vcpu->arch.sve_state) {
> +		size_t size = vcpu_sve_state_size(vcpu);
> +
> +		if (!size || WARN_ON(!vcpu_has_sve(vcpu)))
> +			return -EINVAL;
> +
> +		memset(vcpu->arch.sve_state, 0, size);
> +		return 0;
> +	}
> +
> +	if (WARN_ON(!sve_vl_valid(sve_max_vl)))
> +		return -EINVAL;
> +
> +	/* If the full set of host vector lengths cannot be used, give up: */
> +	if (sve_max_virtualisable_vl < sve_max_vl)
> +		return -EINVAL;
> +
> +	/* Default to the set of vector lengths supported by the host */
> +	vcpu->arch.sve_max_vl = sve_max_vl;
> +
> +	/*
> +	 * The get_sve_reg()/set_sve_reg() ioctl interface will need
> +	 * to be extended with multiple register slice support in
> +	 * order to support vector lengths greater than
> +	 * SVE_VL_ARCH_MAX:
> +	 */
> +	if (WARN_ONCE(vcpu->arch.sve_max_vl > SVE_VL_ARCH_MAX,
> +		      "KVM: SVE vector length for guests limited to %d bytes\n",
> +		      SVE_VL_ARCH_MAX))
> +		vcpu->arch.sve_max_vl = SVE_VL_ARCH_MAX;
> +
> +	/*
> +	 * Userspace can still customize the vector lengths by writing
> +	 * KVM_REG_ARM64_SVE_VLS.  Allocation is deferred until
> +	 * kvm_arm_vcpu_finalize(), which freezes the configuration.
> +	 */
> +	vcpu->arch.flags |= KVM_ARM64_GUEST_HAS_SVE;
> +
> +	return 0;
> +}
> +
>  int kvm_arm_vcpu_finalize(struct kvm_vcpu *vcpu)
>  {
>  	if (likely(kvm_arm_vcpu_finalized(vcpu)))
>  		return 0;
>  
> +	if (vcpu_has_sve(vcpu)) {
> +		size_t size = vcpu_sve_state_size(vcpu);
> +
> +		if (!size)
> +			return -EINVAL;
> +
> +		vcpu->arch.sve_state = kzalloc(size, GFP_KERNEL);

We should probably free this in kvm_arch_vcpu_free().

Cheers,

-- 
Julien Thierry

_______________________________________________
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] 205+ messages in thread

* Re: [PATCH v5 24/26] KVM: arm64: Add a capabillity to advertise SVE support
  2019-02-18 19:52   ` Dave Martin
@ 2019-02-22  9:10     ` Julien Thierry
  -1 siblings, 0 replies; 205+ messages in thread
From: Julien Thierry @ 2019-02-22  9:10 UTC (permalink / raw)
  To: Dave Martin, kvmarm
  Cc: Okamoto Takayuki, Christoffer Dall, Ard Biesheuvel, Marc Zyngier,
	Catalin Marinas, Will Deacon, Zhang Lei, linux-arm-kernel

Hi Dave,

On 18/02/2019 19:52, Dave Martin wrote:
> To provide a uniform way to check for KVM SVE support amongst other
> features, this patch adds a suitable capability KVM_CAP_ARM_SVE,
> and reports it as present when SVE is available.
> 
> Signed-off-by: Dave Martin <Dave.Martin@arm.com>
> ---
>  arch/arm64/kvm/reset.c   | 8 ++++++++
>  include/uapi/linux/kvm.h | 1 +
>  2 files changed, 9 insertions(+)
> 
> diff --git a/arch/arm64/kvm/reset.c b/arch/arm64/kvm/reset.c
> index e67cd2e..f636b34 100644
> --- a/arch/arm64/kvm/reset.c
> +++ b/arch/arm64/kvm/reset.c
> @@ -35,6 +35,7 @@
>  #include <asm/kvm_asm.h>
>  #include <asm/kvm_coproc.h>
>  #include <asm/kvm_mmu.h>
> +#include <asm/virt.h>
>  
>  /* Maximum phys_shift supported for any VM on this host */
>  static u32 kvm_ipa_limit;
> @@ -93,6 +94,9 @@ int kvm_arch_vm_ioctl_check_extension(struct kvm *kvm, long ext)
>  	case KVM_CAP_ARM_VM_IPA_SIZE:
>  		r = kvm_ipa_limit;
>  		break;
> +	case KVM_CAP_ARM_SVE:
> +		r = system_supports_sve();
> +		break;
>  	default:
>  		r = 0;
>  	}
> @@ -105,6 +109,10 @@ static int kvm_reset_sve(struct kvm_vcpu *vcpu)
>  	if (!system_supports_sve())
>  		return -EINVAL;
>  
> +	/* Verify that KVM startup enforced this when SVE was detected: */
> +	if (WARN_ON(!has_vhe()))
> +		return -EINVAL;

I'm wondering, wouldn't it make more sense to check for this when
userland tries to set KVM_ARM_VCPU_SVE?

Otherwise:

Reviewed-by: Julien Thierry <julien.thierry@arm.com>

Cheers,

-- 
Julien Thierry

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

* Re: [PATCH v5 24/26] KVM: arm64: Add a capabillity to advertise SVE support
@ 2019-02-22  9:10     ` Julien Thierry
  0 siblings, 0 replies; 205+ messages in thread
From: Julien Thierry @ 2019-02-22  9:10 UTC (permalink / raw)
  To: Dave Martin, kvmarm
  Cc: Okamoto Takayuki, Christoffer Dall, Ard Biesheuvel, Marc Zyngier,
	Catalin Marinas, Will Deacon, Zhang Lei, linux-arm-kernel

Hi Dave,

On 18/02/2019 19:52, Dave Martin wrote:
> To provide a uniform way to check for KVM SVE support amongst other
> features, this patch adds a suitable capability KVM_CAP_ARM_SVE,
> and reports it as present when SVE is available.
> 
> Signed-off-by: Dave Martin <Dave.Martin@arm.com>
> ---
>  arch/arm64/kvm/reset.c   | 8 ++++++++
>  include/uapi/linux/kvm.h | 1 +
>  2 files changed, 9 insertions(+)
> 
> diff --git a/arch/arm64/kvm/reset.c b/arch/arm64/kvm/reset.c
> index e67cd2e..f636b34 100644
> --- a/arch/arm64/kvm/reset.c
> +++ b/arch/arm64/kvm/reset.c
> @@ -35,6 +35,7 @@
>  #include <asm/kvm_asm.h>
>  #include <asm/kvm_coproc.h>
>  #include <asm/kvm_mmu.h>
> +#include <asm/virt.h>
>  
>  /* Maximum phys_shift supported for any VM on this host */
>  static u32 kvm_ipa_limit;
> @@ -93,6 +94,9 @@ int kvm_arch_vm_ioctl_check_extension(struct kvm *kvm, long ext)
>  	case KVM_CAP_ARM_VM_IPA_SIZE:
>  		r = kvm_ipa_limit;
>  		break;
> +	case KVM_CAP_ARM_SVE:
> +		r = system_supports_sve();
> +		break;
>  	default:
>  		r = 0;
>  	}
> @@ -105,6 +109,10 @@ static int kvm_reset_sve(struct kvm_vcpu *vcpu)
>  	if (!system_supports_sve())
>  		return -EINVAL;
>  
> +	/* Verify that KVM startup enforced this when SVE was detected: */
> +	if (WARN_ON(!has_vhe()))
> +		return -EINVAL;

I'm wondering, wouldn't it make more sense to check for this when
userland tries to set KVM_ARM_VCPU_SVE?

Otherwise:

Reviewed-by: Julien Thierry <julien.thierry@arm.com>

Cheers,

-- 
Julien Thierry

_______________________________________________
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] 205+ messages in thread

* Re: [PATCH v5 08/26] arm64/sve: Enable SVE state tracking for non-task contexts
  2019-02-18 19:52   ` Dave Martin
@ 2019-02-22 15:26     ` Julien Grall
  -1 siblings, 0 replies; 205+ messages in thread
From: Julien Grall @ 2019-02-22 15:26 UTC (permalink / raw)
  To: Dave Martin, kvmarm
  Cc: Peter Maydell, Okamoto Takayuki, Christoffer Dall,
	Ard Biesheuvel, Marc Zyngier, Catalin Marinas, Will Deacon,
	Zhang Lei, Alex Bennée, linux-arm-kernel

Hi Dave,

On 18/02/2019 19:52, Dave Martin wrote:
> The current FPSIMD/SVE context handling support for non-task (i.e.,
> KVM vcpu) contexts does not take SVE into account.  This means that

NIT: Double-space before "This".

> only task contexts can safely use SVE at present.
> 
> In preparation for enabling KVM guests to use SVE, it is necessary
> to keep track of SVE state for non-task contexts too.
> 
> This patch adds the necessary support, removing assumptions from
> the context switch code about the location of the SVE context
> storage.
> 
> When binding a vcpu context, its vector length is arbitrarily
> specified as SVE_VL_MIN for now.  In any case, because TIF_SVE is

NIT: Double-space before "In".

> presently cleared at vcpu context bind time, the specified vector
> length will not be used for anything yet.  In later patches TIF_SVE

NIT: Double-space before "In".

> will be set here as appropriate, and the appropriate maximum vector
> length for the vcpu will be passed when binding.

Cheers,

-- 
Julien Grall

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

* Re: [PATCH v5 08/26] arm64/sve: Enable SVE state tracking for non-task contexts
@ 2019-02-22 15:26     ` Julien Grall
  0 siblings, 0 replies; 205+ messages in thread
From: Julien Grall @ 2019-02-22 15:26 UTC (permalink / raw)
  To: Dave Martin, kvmarm
  Cc: Peter Maydell, Okamoto Takayuki, Christoffer Dall,
	Ard Biesheuvel, Marc Zyngier, Catalin Marinas, Will Deacon,
	Zhang Lei, Alex Bennée, linux-arm-kernel

Hi Dave,

On 18/02/2019 19:52, Dave Martin wrote:
> The current FPSIMD/SVE context handling support for non-task (i.e.,
> KVM vcpu) contexts does not take SVE into account.  This means that

NIT: Double-space before "This".

> only task contexts can safely use SVE at present.
> 
> In preparation for enabling KVM guests to use SVE, it is necessary
> to keep track of SVE state for non-task contexts too.
> 
> This patch adds the necessary support, removing assumptions from
> the context switch code about the location of the SVE context
> storage.
> 
> When binding a vcpu context, its vector length is arbitrarily
> specified as SVE_VL_MIN for now.  In any case, because TIF_SVE is

NIT: Double-space before "In".

> presently cleared at vcpu context bind time, the specified vector
> length will not be used for anything yet.  In later patches TIF_SVE

NIT: Double-space before "In".

> will be set here as appropriate, and the appropriate maximum vector
> length for the vcpu will be passed when binding.

Cheers,

-- 
Julien Grall

_______________________________________________
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] 205+ messages in thread

* Re: [PATCH v5 11/26] KVM: arm64: Extend reset_unknown() to handle mixed RES0/UNKNOWN registers
  2019-02-18 19:52   ` Dave Martin
@ 2019-02-22 16:04     ` Julien Grall
  -1 siblings, 0 replies; 205+ messages in thread
From: Julien Grall @ 2019-02-22 16:04 UTC (permalink / raw)
  To: Dave Martin, kvmarm
  Cc: Peter Maydell, Okamoto Takayuki, Christoffer Dall,
	Ard Biesheuvel, Marc Zyngier, Catalin Marinas, Will Deacon,
	Zhang Lei, Alex Bennée, linux-arm-kernel

Hi Dave,

On 18/02/2019 19:52, Dave Martin wrote:
> The reset_unknown() system register helper initialises a guest
> register to a distinctive junk value on vcpu reset, to help expose
> and debug deficient register initialisation within the guest.
> 
> Some registers such as the SVE control register ZCR_EL1 contain a
> mixture of UNKNOWN fields and RES0 bits.  For these,
> reset_unknown() does not work at present, since it sets all bits to
> junk values instead of just the wanted bits.
> 
> There is no need to craft another special helper just for that,
> since reset_unknown() almost does the appropriate thing anyway.
> This patch takes advantage of the unused val field in struct
> sys_reg_desc to specify a mask of bits that should be initialised
> to zero instead of junk.
> 
> All existing users of reset_unknown() do not (and should not)
> define a value for val, so they will implicitly set it to zero,
> resulting in all bits being made UNKNOWN by this function: thus,
> this patch makes no functional change for currently defined
> registers.
> 
> Future patches will make use of non-zero val.
> 
> Signed-off-by: Dave Martin <Dave.Martin@arm.com>

Reviewed-by: Julien Grall <julien.grall@arm.com>

Cheers,

> ---
>   arch/arm64/kvm/sys_regs.h | 11 +++++++++--
>   1 file changed, 9 insertions(+), 2 deletions(-)
> 
> diff --git a/arch/arm64/kvm/sys_regs.h b/arch/arm64/kvm/sys_regs.h
> index 3b1bc7f..174ffc0 100644
> --- a/arch/arm64/kvm/sys_regs.h
> +++ b/arch/arm64/kvm/sys_regs.h
> @@ -56,7 +56,12 @@ struct sys_reg_desc {
>   	/* Index into sys_reg[], or 0 if we don't need to save it. */
>   	int reg;
>   
> -	/* Value (usually reset value) */
> +	/*
> +	 * Value (usually reset value)
> +	 * For reset_unknown, each bit set to 1 in val is treated as
> +	 * RES0 in the register: the corresponding register bit is
> +	 * reset to 0 instead of "unknown".
> +	 */
>   	u64 val;
>   
>   	/* Custom get/set_user functions, fallback to generic if NULL */
> @@ -92,7 +97,9 @@ static inline void reset_unknown(struct kvm_vcpu *vcpu,
>   {
>   	BUG_ON(!r->reg);
>   	BUG_ON(r->reg >= NR_SYS_REGS);
> -	__vcpu_sys_reg(vcpu, r->reg) = 0x1de7ec7edbadc0deULL;
> +
> +	/* If non-zero, r->val specifies which register bits are RES0: */
> +	__vcpu_sys_reg(vcpu, r->reg) = 0x1de7ec7edbadc0deULL & ~r->val;
>   }
>   
>   static inline void reset_val(struct kvm_vcpu *vcpu, const struct sys_reg_desc *r)
> 

-- 
Julien Grall

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

* Re: [PATCH v5 11/26] KVM: arm64: Extend reset_unknown() to handle mixed RES0/UNKNOWN registers
@ 2019-02-22 16:04     ` Julien Grall
  0 siblings, 0 replies; 205+ messages in thread
From: Julien Grall @ 2019-02-22 16:04 UTC (permalink / raw)
  To: Dave Martin, kvmarm
  Cc: Peter Maydell, Okamoto Takayuki, Christoffer Dall,
	Ard Biesheuvel, Marc Zyngier, Catalin Marinas, Will Deacon,
	Zhang Lei, Alex Bennée, linux-arm-kernel

Hi Dave,

On 18/02/2019 19:52, Dave Martin wrote:
> The reset_unknown() system register helper initialises a guest
> register to a distinctive junk value on vcpu reset, to help expose
> and debug deficient register initialisation within the guest.
> 
> Some registers such as the SVE control register ZCR_EL1 contain a
> mixture of UNKNOWN fields and RES0 bits.  For these,
> reset_unknown() does not work at present, since it sets all bits to
> junk values instead of just the wanted bits.
> 
> There is no need to craft another special helper just for that,
> since reset_unknown() almost does the appropriate thing anyway.
> This patch takes advantage of the unused val field in struct
> sys_reg_desc to specify a mask of bits that should be initialised
> to zero instead of junk.
> 
> All existing users of reset_unknown() do not (and should not)
> define a value for val, so they will implicitly set it to zero,
> resulting in all bits being made UNKNOWN by this function: thus,
> this patch makes no functional change for currently defined
> registers.
> 
> Future patches will make use of non-zero val.
> 
> Signed-off-by: Dave Martin <Dave.Martin@arm.com>

Reviewed-by: Julien Grall <julien.grall@arm.com>

Cheers,

> ---
>   arch/arm64/kvm/sys_regs.h | 11 +++++++++--
>   1 file changed, 9 insertions(+), 2 deletions(-)
> 
> diff --git a/arch/arm64/kvm/sys_regs.h b/arch/arm64/kvm/sys_regs.h
> index 3b1bc7f..174ffc0 100644
> --- a/arch/arm64/kvm/sys_regs.h
> +++ b/arch/arm64/kvm/sys_regs.h
> @@ -56,7 +56,12 @@ struct sys_reg_desc {
>   	/* Index into sys_reg[], or 0 if we don't need to save it. */
>   	int reg;
>   
> -	/* Value (usually reset value) */
> +	/*
> +	 * Value (usually reset value)
> +	 * For reset_unknown, each bit set to 1 in val is treated as
> +	 * RES0 in the register: the corresponding register bit is
> +	 * reset to 0 instead of "unknown".
> +	 */
>   	u64 val;
>   
>   	/* Custom get/set_user functions, fallback to generic if NULL */
> @@ -92,7 +97,9 @@ static inline void reset_unknown(struct kvm_vcpu *vcpu,
>   {
>   	BUG_ON(!r->reg);
>   	BUG_ON(r->reg >= NR_SYS_REGS);
> -	__vcpu_sys_reg(vcpu, r->reg) = 0x1de7ec7edbadc0deULL;
> +
> +	/* If non-zero, r->val specifies which register bits are RES0: */
> +	__vcpu_sys_reg(vcpu, r->reg) = 0x1de7ec7edbadc0deULL & ~r->val;
>   }
>   
>   static inline void reset_val(struct kvm_vcpu *vcpu, const struct sys_reg_desc *r)
> 

-- 
Julien Grall

_______________________________________________
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] 205+ messages in thread

* Re: [PATCH v5 01/26] KVM: Documentation: Document arm64 core registers in detail
  2019-02-21 11:48     ` Julien Grall
@ 2019-02-26 12:05       ` Dave Martin
  -1 siblings, 0 replies; 205+ messages in thread
From: Dave Martin @ 2019-02-26 12:05 UTC (permalink / raw)
  To: Julien Grall
  Cc: Okamoto Takayuki, Christoffer Dall, Ard Biesheuvel, Marc Zyngier,
	Catalin Marinas, Will Deacon, Zhang Lei, kvmarm,
	linux-arm-kernel

On Thu, Feb 21, 2019 at 11:48:30AM +0000, Julien Grall wrote:
> Hi Dave,
> 
> On 18/02/2019 19:52, Dave Martin wrote:
> >Since the the sizes of individual members of the core arm64
> >registers vary, the list of register encodings that make sense is
> >not a simple linear sequence.
> >
> >To clarify which encodings to use, this patch adds a brief list
> >to the documentation.
> >
> >Signed-off-by: Dave Martin <Dave.Martin@arm.com>
> 
> Reviewed-by: Julien Grall <julien.grall@arm.com>

Thanks
---Dave

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

* Re: [PATCH v5 01/26] KVM: Documentation: Document arm64 core registers in detail
@ 2019-02-26 12:05       ` Dave Martin
  0 siblings, 0 replies; 205+ messages in thread
From: Dave Martin @ 2019-02-26 12:05 UTC (permalink / raw)
  To: Julien Grall
  Cc: Okamoto Takayuki, Christoffer Dall, Ard Biesheuvel, Marc Zyngier,
	Catalin Marinas, Will Deacon, Zhang Lei, kvmarm,
	linux-arm-kernel

On Thu, Feb 21, 2019 at 11:48:30AM +0000, Julien Grall wrote:
> Hi Dave,
> 
> On 18/02/2019 19:52, Dave Martin wrote:
> >Since the the sizes of individual members of the core arm64
> >registers vary, the list of register encodings that make sense is
> >not a simple linear sequence.
> >
> >To clarify which encodings to use, this patch adds a brief list
> >to the documentation.
> >
> >Signed-off-by: Dave Martin <Dave.Martin@arm.com>
> 
> Reviewed-by: Julien Grall <julien.grall@arm.com>

Thanks
---Dave

_______________________________________________
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] 205+ messages in thread

* Re: [PATCH v5 02/26] arm64: fpsimd: Always set TIF_FOREIGN_FPSTATE on task state flush
  2019-02-21 12:39   ` Julien Grall
@ 2019-02-26 12:06       ` Dave Martin
  0 siblings, 0 replies; 205+ messages in thread
From: Dave Martin @ 2019-02-26 12:06 UTC (permalink / raw)
  To: Julien Grall
  Cc: Okamoto Takayuki, Christoffer Dall, Ard Biesheuvel, Marc Zyngier,
	Catalin Marinas, Will Deacon, Zhang Lei, kvmarm,
	linux-arm-kernel

On Thu, Feb 21, 2019 at 12:39:39PM +0000, Julien Grall wrote:
> Hi Dave,
> 
> On 18/02/2019 19:52, Dave Martin wrote:
> >This patch updates fpsimd_flush_task_state() to mirror the new
> >semantics of fpsimd_flush_cpu_state() introduced by commit
> >d8ad71fa38a9 ("arm64: fpsimd: Fix TIF_FOREIGN_FPSTATE after
> >invalidating cpu regs").  Both functions now implicitly set
> 
> NIT: Double-space before "Both"
> 
> >TIF_FOREIGN_FPSTATE to indicate that the task's FPSIMD state is not
> >loaded into the cpu.
> >
> >As a side-effect, fpsimd_flush_task_state() now sets
> >TIF_FOREIGN_FPSTATE even for non-running tasks.  In the case of
> 
> NIT: Double sppace before "In".
> 
> >non-running tasks this is not useful but also harmless, because the
> >flag is live only while the corresponding task is running.  This
> >function is not called from fast paths, so special-casing this for
> >the task == current case is not really worth it.
> >
> >Compiler barriers previously present in restore_sve_fpsimd_context()
> >are pulled into fpsimd_flush_task_state() so that it can be safely
> >called with preemption enabled if necessary.
> >
> >Explicit calls to set TIF_FOREIGN_FPSTATE that accompany
> >fpsimd_flush_task_state() calls and are now redundant are removed
> >as appropriate.
> >
> >fpsimd_flush_task_state() is used to get exclusive access to the
> >representation of the task's state via task_struct, for the purpose
> >of replacing the state.  Thus, the call to this function should
> 
> NIT: Double-space before "Thus".
> 
> >happen before manipulating fpsimd_state or sve_state etc. in
> >task_struct.  Anomalous cases are reordered appropriately in order
> 
> NIT: Double-space before "Anomalous".

A habit rather than a mistake [1], and I don't propose to change it ;)


> >to make the code more consistent, although there should be no
> >functional difference since these cases are protected by
> >local_bh_disable() anyway.
> >
> >Signed-off-by: Dave Martin <Dave.Martin@arm.com>
> >Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
> 
> Reviewed-by: Julien Grall <julien.grall@arm.com>

Thanks for the review
--Dave


[1] https://en.wikipedia.org/wiki/Sentence_spacing

Interestingly around 11% of commits in mainline appear to follow the
two-space convention for their commit messages.  I won't speculate as
to why...

$ git log --oneline --grep='[a-z]\.  [A-Z]' | wc -l
94638
$ git log --oneline | wc -l
812542

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

* Re: [PATCH v5 02/26] arm64: fpsimd: Always set TIF_FOREIGN_FPSTATE on task state flush
@ 2019-02-26 12:06       ` Dave Martin
  0 siblings, 0 replies; 205+ messages in thread
From: Dave Martin @ 2019-02-26 12:06 UTC (permalink / raw)
  To: Julien Grall
  Cc: Okamoto Takayuki, Christoffer Dall, Ard Biesheuvel, Marc Zyngier,
	Catalin Marinas, Will Deacon, Zhang Lei, kvmarm,
	linux-arm-kernel

On Thu, Feb 21, 2019 at 12:39:39PM +0000, Julien Grall wrote:
> Hi Dave,
> 
> On 18/02/2019 19:52, Dave Martin wrote:
> >This patch updates fpsimd_flush_task_state() to mirror the new
> >semantics of fpsimd_flush_cpu_state() introduced by commit
> >d8ad71fa38a9 ("arm64: fpsimd: Fix TIF_FOREIGN_FPSTATE after
> >invalidating cpu regs").  Both functions now implicitly set
> 
> NIT: Double-space before "Both"
> 
> >TIF_FOREIGN_FPSTATE to indicate that the task's FPSIMD state is not
> >loaded into the cpu.
> >
> >As a side-effect, fpsimd_flush_task_state() now sets
> >TIF_FOREIGN_FPSTATE even for non-running tasks.  In the case of
> 
> NIT: Double sppace before "In".
> 
> >non-running tasks this is not useful but also harmless, because the
> >flag is live only while the corresponding task is running.  This
> >function is not called from fast paths, so special-casing this for
> >the task == current case is not really worth it.
> >
> >Compiler barriers previously present in restore_sve_fpsimd_context()
> >are pulled into fpsimd_flush_task_state() so that it can be safely
> >called with preemption enabled if necessary.
> >
> >Explicit calls to set TIF_FOREIGN_FPSTATE that accompany
> >fpsimd_flush_task_state() calls and are now redundant are removed
> >as appropriate.
> >
> >fpsimd_flush_task_state() is used to get exclusive access to the
> >representation of the task's state via task_struct, for the purpose
> >of replacing the state.  Thus, the call to this function should
> 
> NIT: Double-space before "Thus".
> 
> >happen before manipulating fpsimd_state or sve_state etc. in
> >task_struct.  Anomalous cases are reordered appropriately in order
> 
> NIT: Double-space before "Anomalous".

A habit rather than a mistake [1], and I don't propose to change it ;)


> >to make the code more consistent, although there should be no
> >functional difference since these cases are protected by
> >local_bh_disable() anyway.
> >
> >Signed-off-by: Dave Martin <Dave.Martin@arm.com>
> >Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
> 
> Reviewed-by: Julien Grall <julien.grall@arm.com>

Thanks for the review
--Dave


[1] https://en.wikipedia.org/wiki/Sentence_spacing

Interestingly around 11% of commits in mainline appear to follow the
two-space convention for their commit messages.  I won't speculate as
to why...

$ git log --oneline --grep='[a-z]\.  [A-Z]' | wc -l
94638
$ git log --oneline | wc -l
812542

_______________________________________________
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] 205+ messages in thread

* Re: [PATCH v5 05/26] KVM: arm64: Add missing #include of <linux/bitmap.h> to kvm_host.h
  2019-02-20 15:23     ` Mark Rutland
@ 2019-02-26 12:06       ` Dave Martin
  -1 siblings, 0 replies; 205+ messages in thread
From: Dave Martin @ 2019-02-26 12:06 UTC (permalink / raw)
  To: Mark Rutland
  Cc: Okamoto Takayuki, Christoffer Dall, Ard Biesheuvel, Marc Zyngier,
	Catalin Marinas, Will Deacon, Zhang Lei, kvmarm,
	linux-arm-kernel

On Wed, Feb 20, 2019 at 03:23:50PM +0000, Mark Rutland wrote:
> On Mon, Feb 18, 2019 at 07:52:18PM +0000, Dave Martin wrote:
> > kvm_host.h uses DECLARE_BITMAP() to declare the features member of
> > struct vcpu_arch, but the corresponding #include for this is
> > missing.
> > 
> > This patch adds a suitable #include for <linux/bitmap.h>.  Although
> > the header builds without it today, this should help to avoid
> > future surprises.
> > 
> > Signed-off-by: Dave Martin <Dave.Martin@arm.com>
> > Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
> > ---
> >  arch/arm64/include/asm/kvm_host.h | 1 +
> >  1 file changed, 1 insertion(+)
> > 
> > diff --git a/arch/arm64/include/asm/kvm_host.h b/arch/arm64/include/asm/kvm_host.h
> > index 7732d0b..84056a4 100644
> > --- a/arch/arm64/include/asm/kvm_host.h
> > +++ b/arch/arm64/include/asm/kvm_host.h
> > @@ -22,6 +22,7 @@
> >  #ifndef __ARM64_KVM_HOST_H__
> >  #define __ARM64_KVM_HOST_H__
> >  
> > +#include <linux/bitmap.h>
> >  #include <linux/types.h>
> >  #include <linux/kvm_types.h>
> >  #include <asm/cpufeature.h>
> 
> From a quick scan of the file, we're also missing:
> 
> #include <asm/barrier.h>

[...]

> #include <linux/jump_label.h>
> #include <linux/percpu.h>

Done for those three.


> #include <linux/thread_info.h>

Since commit e6b673b741ea ("KVM: arm64: Optimise FPSIMD handling to
reduce guest/host thrashing", we do have <asm/thread_info.h>.

Since this header is not generic, this seems reasonable.  Is there
something from <linux/thread_info.h> used here that I'm missing?

Cheers
---Dave

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

* Re: [PATCH v5 05/26] KVM: arm64: Add missing #include of <linux/bitmap.h> to kvm_host.h
@ 2019-02-26 12:06       ` Dave Martin
  0 siblings, 0 replies; 205+ messages in thread
From: Dave Martin @ 2019-02-26 12:06 UTC (permalink / raw)
  To: Mark Rutland
  Cc: Okamoto Takayuki, Christoffer Dall, Ard Biesheuvel, Marc Zyngier,
	Catalin Marinas, Will Deacon, Zhang Lei, kvmarm,
	linux-arm-kernel

On Wed, Feb 20, 2019 at 03:23:50PM +0000, Mark Rutland wrote:
> On Mon, Feb 18, 2019 at 07:52:18PM +0000, Dave Martin wrote:
> > kvm_host.h uses DECLARE_BITMAP() to declare the features member of
> > struct vcpu_arch, but the corresponding #include for this is
> > missing.
> > 
> > This patch adds a suitable #include for <linux/bitmap.h>.  Although
> > the header builds without it today, this should help to avoid
> > future surprises.
> > 
> > Signed-off-by: Dave Martin <Dave.Martin@arm.com>
> > Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
> > ---
> >  arch/arm64/include/asm/kvm_host.h | 1 +
> >  1 file changed, 1 insertion(+)
> > 
> > diff --git a/arch/arm64/include/asm/kvm_host.h b/arch/arm64/include/asm/kvm_host.h
> > index 7732d0b..84056a4 100644
> > --- a/arch/arm64/include/asm/kvm_host.h
> > +++ b/arch/arm64/include/asm/kvm_host.h
> > @@ -22,6 +22,7 @@
> >  #ifndef __ARM64_KVM_HOST_H__
> >  #define __ARM64_KVM_HOST_H__
> >  
> > +#include <linux/bitmap.h>
> >  #include <linux/types.h>
> >  #include <linux/kvm_types.h>
> >  #include <asm/cpufeature.h>
> 
> From a quick scan of the file, we're also missing:
> 
> #include <asm/barrier.h>

[...]

> #include <linux/jump_label.h>
> #include <linux/percpu.h>

Done for those three.


> #include <linux/thread_info.h>

Since commit e6b673b741ea ("KVM: arm64: Optimise FPSIMD handling to
reduce guest/host thrashing", we do have <asm/thread_info.h>.

Since this header is not generic, this seems reasonable.  Is there
something from <linux/thread_info.h> used here that I'm missing?

Cheers
---Dave

_______________________________________________
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] 205+ messages in thread

* Re: [PATCH v5 06/26] arm64/sve: Check SVE virtualisability
  2019-02-20 11:12     ` Julien Thierry
@ 2019-02-26 12:06       ` Dave Martin
  -1 siblings, 0 replies; 205+ messages in thread
From: Dave Martin @ 2019-02-26 12:06 UTC (permalink / raw)
  To: Julien Thierry
  Cc: Okamoto Takayuki, Christoffer Dall, Ard Biesheuvel, Marc Zyngier,
	Catalin Marinas, Will Deacon, Zhang Lei, kvmarm,
	linux-arm-kernel

On Wed, Feb 20, 2019 at 11:12:49AM +0000, Julien Thierry wrote:
> Hi Dave,
> 
> On 18/02/2019 19:52, Dave Martin wrote:
> > Due to the way the effective SVE vector length is controlled and
> > trapped at different exception levels, certain mismatches in the
> > sets of vector lengths supported by different physical CPUs in the
> > system may prevent straightforward virtualisation of SVE at parity
> > with the host.
> > 
> > This patch analyses the extent to which SVE can be virtualised
> > safely without interfering with migration of vcpus between physical
> > CPUs, and rejects late secondary CPUs that would erode the
> > situation further.
> > 
> > It is left up to KVM to decide what to do with this information.
> > 
> > Signed-off-by: Dave Martin <Dave.Martin@arm.com>
> > ---
> >  arch/arm64/include/asm/fpsimd.h |  1 +
> >  arch/arm64/kernel/cpufeature.c  |  2 +-
> >  arch/arm64/kernel/fpsimd.c      | 86 ++++++++++++++++++++++++++++++++++-------
> >  3 files changed, 73 insertions(+), 16 deletions(-)
> > 
> > diff --git a/arch/arm64/include/asm/fpsimd.h b/arch/arm64/include/asm/fpsimd.h
> > index dd1ad39..964adc9 100644
> > --- a/arch/arm64/include/asm/fpsimd.h
> > +++ b/arch/arm64/include/asm/fpsimd.h
> > @@ -87,6 +87,7 @@ extern void sve_kernel_enable(const struct arm64_cpu_capabilities *__unused);
> >  extern u64 read_zcr_features(void);
> >  
> >  extern int __ro_after_init sve_max_vl;
> > +extern int __ro_after_init sve_max_virtualisable_vl;
> >  
> >  #ifdef CONFIG_ARM64_SVE
> >  
> > diff --git a/arch/arm64/kernel/cpufeature.c b/arch/arm64/kernel/cpufeature.c
> > index f6d84e2..5eaacb4 100644
> > --- a/arch/arm64/kernel/cpufeature.c
> > +++ b/arch/arm64/kernel/cpufeature.c
> > @@ -1825,7 +1825,7 @@ static void verify_sve_features(void)
> >  	unsigned int len = zcr & ZCR_ELx_LEN_MASK;
> >  
> >  	if (len < safe_len || sve_verify_vq_map()) {
> > -		pr_crit("CPU%d: SVE: required vector length(s) missing\n",
> > +		pr_crit("CPU%d: SVE: vector length support mismatch\n",
> >  			smp_processor_id());
> >  		cpu_die_early();
> >  	}
> > diff --git a/arch/arm64/kernel/fpsimd.c b/arch/arm64/kernel/fpsimd.c
> > index 62c37f0..64729e2 100644
> > --- a/arch/arm64/kernel/fpsimd.c
> > +++ b/arch/arm64/kernel/fpsimd.c
> > @@ -18,6 +18,7 @@
> >   */
> >  
> >  #include <linux/bitmap.h>
> > +#include <linux/bitops.h>
> >  #include <linux/bottom_half.h>
> >  #include <linux/bug.h>
> >  #include <linux/cache.h>
> > @@ -48,6 +49,7 @@
> >  #include <asm/sigcontext.h>
> >  #include <asm/sysreg.h>
> >  #include <asm/traps.h>
> > +#include <asm/virt.h>
> >  
> >  #define FPEXC_IOF	(1 << 0)
> >  #define FPEXC_DZF	(1 << 1)
> > @@ -130,14 +132,18 @@ static int sve_default_vl = -1;
> >  
> >  /* Maximum supported vector length across all CPUs (initially poisoned) */
> >  int __ro_after_init sve_max_vl = SVE_VL_MIN;
> > +int __ro_after_init sve_max_virtualisable_vl = SVE_VL_MIN;
> >  /* Set of available vector lengths, as vq_to_bit(vq): */
> >  static __ro_after_init DECLARE_BITMAP(sve_vq_map, SVE_VQ_MAX);
> > +/* Set of vector lengths present on at least one cpu: */
> > +static __ro_after_init DECLARE_BITMAP(sve_vq_partial_map, SVE_VQ_MAX);
> >  static void __percpu *efi_sve_state;
> >  
> >  #else /* ! CONFIG_ARM64_SVE */
> >  
> >  /* Dummy declaration for code that will be optimised out: */
> >  extern __ro_after_init DECLARE_BITMAP(sve_vq_map, SVE_VQ_MAX);
> > +extern __ro_after_init DECLARE_BITMAP(sve_vq_partial_map, SVE_VQ_MAX);
> >  extern void __percpu *efi_sve_state;
> >  
> >  #endif /* ! CONFIG_ARM64_SVE */
> > @@ -623,12 +629,6 @@ int sve_get_current_vl(void)
> >  	return sve_prctl_status(0);
> >  }
> >  
> > -/*
> > - * Bitmap for temporary storage of the per-CPU set of supported vector lengths
> > - * during secondary boot.
> > - */
> > -static DECLARE_BITMAP(sve_secondary_vq_map, SVE_VQ_MAX);
> > -
> >  static void sve_probe_vqs(DECLARE_BITMAP(map, SVE_VQ_MAX))
> >  {
> >  	unsigned int vq, vl;
> > @@ -650,6 +650,7 @@ static void sve_probe_vqs(DECLARE_BITMAP(map, SVE_VQ_MAX))
> >  void __init sve_init_vq_map(void)
> >  {
> >  	sve_probe_vqs(sve_vq_map);
> > +	bitmap_copy(sve_vq_partial_map, sve_vq_map, SVE_VQ_MAX);
> >  }
> >  
> >  /*
> > @@ -658,25 +659,58 @@ void __init sve_init_vq_map(void)
> >   */
> >  void sve_update_vq_map(void)
> >  {
> > -	sve_probe_vqs(sve_secondary_vq_map);
> > -	bitmap_and(sve_vq_map, sve_vq_map, sve_secondary_vq_map, SVE_VQ_MAX);
> > +	DECLARE_BITMAP(tmp_map, SVE_VQ_MAX);
> > +
> > +	sve_probe_vqs(tmp_map);
> > +	bitmap_and(sve_vq_map, sve_vq_map, tmp_map, SVE_VQ_MAX);
> > +	bitmap_or(sve_vq_partial_map, sve_vq_partial_map, tmp_map, SVE_VQ_MAX);
> >  }
> >  
> >  /* Check whether the current CPU supports all VQs in the committed set */
> >  int sve_verify_vq_map(void)
> >  {
> > -	int ret = 0;
> > +	DECLARE_BITMAP(tmp_map, SVE_VQ_MAX);
> > +	unsigned long b;
> >  
> > -	sve_probe_vqs(sve_secondary_vq_map);
> > -	bitmap_andnot(sve_secondary_vq_map, sve_vq_map, sve_secondary_vq_map,
> > -		      SVE_VQ_MAX);
> > -	if (!bitmap_empty(sve_secondary_vq_map, SVE_VQ_MAX)) {
> > +	sve_probe_vqs(tmp_map);
> > +
> > +	bitmap_complement(tmp_map, tmp_map, SVE_VQ_MAX);
> > +	if (bitmap_intersects(tmp_map, sve_vq_map, SVE_VQ_MAX)) {
> >  		pr_warn("SVE: cpu%d: Required vector length(s) missing\n",
> >  			smp_processor_id());
> > -		ret = -EINVAL;
> > +		return -EINVAL;
> >  	}
> >  
> > -	return ret;
> > +	if (!IS_ENABLED(CONFIG_KVM) || !is_hyp_mode_available())
> > +		return 0;
> > +
> > +	/*
> > +	 * For KVM, it is necessary to ensure that this CPU doesn't
> > +	 * support any vector length that guests may have probed as
> > +	 * unsupported.
> > +	 */
> > +
> > +	/* Recover the set of supported VQs: */
> > +	bitmap_complement(tmp_map, tmp_map, SVE_VQ_MAX);
> > +	/* Find VQs supported that are not globally supported: */
> > +	bitmap_andnot(tmp_map, tmp_map, sve_vq_map, SVE_VQ_MAX);
> > +
> > +	/* Find the lowest such VQ, if any: */
> > +	b = find_last_bit(tmp_map, SVE_VQ_MAX);
> > +	if (b >= SVE_VQ_MAX)
> > +		return 0; /* no mismatches */
> > +
> > +	/*
> > +	 * Mismatches above sve_max_virtualisable_vl are fine, since
> > +	 * no guest is allowed to configure ZCR_EL2.LEN to exceed this:
> > +	 */
> > +	if (sve_vl_from_vq(bit_to_vq(b)) <= sve_max_virtualisable_vl) {
> > +		pr_warn("SVE: cpu%d: Unsupported vector length(s) present\n",
> 
> Nit: might be good to specify that the vector length is unsupported for
> virtualisation.
> 
> Also, since KVM is the one deciding what to do with the information,
> should we have a warning here? But I can understand that knowing which
> CPUs are introducing unsupported vector length, maybe using pr_devel()
> instead of pr_warn()

These warnings are really for consumption by SoC vendors, not users:
my aim is to flag up systems that we consider broken (or at least,
unsuitable for running KVM).

So I prefer to make this noisy and limit the amount of "useful"
information people might be tempted to programmatically scrape from
dmesg.

cpufeatures uses pr_warn("SANITY CHECK: [...]") here.  Maybe I should
stick "SANITY CHECK" in here too?  I will also try to make the commit
message more explicit and/or add comments to make the intent of the code
clearer.

It may also make sense to make this noise even if KVM isn't enabled
(which is a rare case anyhow).

Thoughts?

> In any case, the logic looks good to me:
> 
> Reviewed-by: Julien Thierry <julien.thierry@arm.com>

Thanks
---Dave

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

* Re: [PATCH v5 06/26] arm64/sve: Check SVE virtualisability
@ 2019-02-26 12:06       ` Dave Martin
  0 siblings, 0 replies; 205+ messages in thread
From: Dave Martin @ 2019-02-26 12:06 UTC (permalink / raw)
  To: Julien Thierry
  Cc: Okamoto Takayuki, Christoffer Dall, Ard Biesheuvel, Marc Zyngier,
	Catalin Marinas, Will Deacon, Zhang Lei, kvmarm,
	linux-arm-kernel

On Wed, Feb 20, 2019 at 11:12:49AM +0000, Julien Thierry wrote:
> Hi Dave,
> 
> On 18/02/2019 19:52, Dave Martin wrote:
> > Due to the way the effective SVE vector length is controlled and
> > trapped at different exception levels, certain mismatches in the
> > sets of vector lengths supported by different physical CPUs in the
> > system may prevent straightforward virtualisation of SVE at parity
> > with the host.
> > 
> > This patch analyses the extent to which SVE can be virtualised
> > safely without interfering with migration of vcpus between physical
> > CPUs, and rejects late secondary CPUs that would erode the
> > situation further.
> > 
> > It is left up to KVM to decide what to do with this information.
> > 
> > Signed-off-by: Dave Martin <Dave.Martin@arm.com>
> > ---
> >  arch/arm64/include/asm/fpsimd.h |  1 +
> >  arch/arm64/kernel/cpufeature.c  |  2 +-
> >  arch/arm64/kernel/fpsimd.c      | 86 ++++++++++++++++++++++++++++++++++-------
> >  3 files changed, 73 insertions(+), 16 deletions(-)
> > 
> > diff --git a/arch/arm64/include/asm/fpsimd.h b/arch/arm64/include/asm/fpsimd.h
> > index dd1ad39..964adc9 100644
> > --- a/arch/arm64/include/asm/fpsimd.h
> > +++ b/arch/arm64/include/asm/fpsimd.h
> > @@ -87,6 +87,7 @@ extern void sve_kernel_enable(const struct arm64_cpu_capabilities *__unused);
> >  extern u64 read_zcr_features(void);
> >  
> >  extern int __ro_after_init sve_max_vl;
> > +extern int __ro_after_init sve_max_virtualisable_vl;
> >  
> >  #ifdef CONFIG_ARM64_SVE
> >  
> > diff --git a/arch/arm64/kernel/cpufeature.c b/arch/arm64/kernel/cpufeature.c
> > index f6d84e2..5eaacb4 100644
> > --- a/arch/arm64/kernel/cpufeature.c
> > +++ b/arch/arm64/kernel/cpufeature.c
> > @@ -1825,7 +1825,7 @@ static void verify_sve_features(void)
> >  	unsigned int len = zcr & ZCR_ELx_LEN_MASK;
> >  
> >  	if (len < safe_len || sve_verify_vq_map()) {
> > -		pr_crit("CPU%d: SVE: required vector length(s) missing\n",
> > +		pr_crit("CPU%d: SVE: vector length support mismatch\n",
> >  			smp_processor_id());
> >  		cpu_die_early();
> >  	}
> > diff --git a/arch/arm64/kernel/fpsimd.c b/arch/arm64/kernel/fpsimd.c
> > index 62c37f0..64729e2 100644
> > --- a/arch/arm64/kernel/fpsimd.c
> > +++ b/arch/arm64/kernel/fpsimd.c
> > @@ -18,6 +18,7 @@
> >   */
> >  
> >  #include <linux/bitmap.h>
> > +#include <linux/bitops.h>
> >  #include <linux/bottom_half.h>
> >  #include <linux/bug.h>
> >  #include <linux/cache.h>
> > @@ -48,6 +49,7 @@
> >  #include <asm/sigcontext.h>
> >  #include <asm/sysreg.h>
> >  #include <asm/traps.h>
> > +#include <asm/virt.h>
> >  
> >  #define FPEXC_IOF	(1 << 0)
> >  #define FPEXC_DZF	(1 << 1)
> > @@ -130,14 +132,18 @@ static int sve_default_vl = -1;
> >  
> >  /* Maximum supported vector length across all CPUs (initially poisoned) */
> >  int __ro_after_init sve_max_vl = SVE_VL_MIN;
> > +int __ro_after_init sve_max_virtualisable_vl = SVE_VL_MIN;
> >  /* Set of available vector lengths, as vq_to_bit(vq): */
> >  static __ro_after_init DECLARE_BITMAP(sve_vq_map, SVE_VQ_MAX);
> > +/* Set of vector lengths present on at least one cpu: */
> > +static __ro_after_init DECLARE_BITMAP(sve_vq_partial_map, SVE_VQ_MAX);
> >  static void __percpu *efi_sve_state;
> >  
> >  #else /* ! CONFIG_ARM64_SVE */
> >  
> >  /* Dummy declaration for code that will be optimised out: */
> >  extern __ro_after_init DECLARE_BITMAP(sve_vq_map, SVE_VQ_MAX);
> > +extern __ro_after_init DECLARE_BITMAP(sve_vq_partial_map, SVE_VQ_MAX);
> >  extern void __percpu *efi_sve_state;
> >  
> >  #endif /* ! CONFIG_ARM64_SVE */
> > @@ -623,12 +629,6 @@ int sve_get_current_vl(void)
> >  	return sve_prctl_status(0);
> >  }
> >  
> > -/*
> > - * Bitmap for temporary storage of the per-CPU set of supported vector lengths
> > - * during secondary boot.
> > - */
> > -static DECLARE_BITMAP(sve_secondary_vq_map, SVE_VQ_MAX);
> > -
> >  static void sve_probe_vqs(DECLARE_BITMAP(map, SVE_VQ_MAX))
> >  {
> >  	unsigned int vq, vl;
> > @@ -650,6 +650,7 @@ static void sve_probe_vqs(DECLARE_BITMAP(map, SVE_VQ_MAX))
> >  void __init sve_init_vq_map(void)
> >  {
> >  	sve_probe_vqs(sve_vq_map);
> > +	bitmap_copy(sve_vq_partial_map, sve_vq_map, SVE_VQ_MAX);
> >  }
> >  
> >  /*
> > @@ -658,25 +659,58 @@ void __init sve_init_vq_map(void)
> >   */
> >  void sve_update_vq_map(void)
> >  {
> > -	sve_probe_vqs(sve_secondary_vq_map);
> > -	bitmap_and(sve_vq_map, sve_vq_map, sve_secondary_vq_map, SVE_VQ_MAX);
> > +	DECLARE_BITMAP(tmp_map, SVE_VQ_MAX);
> > +
> > +	sve_probe_vqs(tmp_map);
> > +	bitmap_and(sve_vq_map, sve_vq_map, tmp_map, SVE_VQ_MAX);
> > +	bitmap_or(sve_vq_partial_map, sve_vq_partial_map, tmp_map, SVE_VQ_MAX);
> >  }
> >  
> >  /* Check whether the current CPU supports all VQs in the committed set */
> >  int sve_verify_vq_map(void)
> >  {
> > -	int ret = 0;
> > +	DECLARE_BITMAP(tmp_map, SVE_VQ_MAX);
> > +	unsigned long b;
> >  
> > -	sve_probe_vqs(sve_secondary_vq_map);
> > -	bitmap_andnot(sve_secondary_vq_map, sve_vq_map, sve_secondary_vq_map,
> > -		      SVE_VQ_MAX);
> > -	if (!bitmap_empty(sve_secondary_vq_map, SVE_VQ_MAX)) {
> > +	sve_probe_vqs(tmp_map);
> > +
> > +	bitmap_complement(tmp_map, tmp_map, SVE_VQ_MAX);
> > +	if (bitmap_intersects(tmp_map, sve_vq_map, SVE_VQ_MAX)) {
> >  		pr_warn("SVE: cpu%d: Required vector length(s) missing\n",
> >  			smp_processor_id());
> > -		ret = -EINVAL;
> > +		return -EINVAL;
> >  	}
> >  
> > -	return ret;
> > +	if (!IS_ENABLED(CONFIG_KVM) || !is_hyp_mode_available())
> > +		return 0;
> > +
> > +	/*
> > +	 * For KVM, it is necessary to ensure that this CPU doesn't
> > +	 * support any vector length that guests may have probed as
> > +	 * unsupported.
> > +	 */
> > +
> > +	/* Recover the set of supported VQs: */
> > +	bitmap_complement(tmp_map, tmp_map, SVE_VQ_MAX);
> > +	/* Find VQs supported that are not globally supported: */
> > +	bitmap_andnot(tmp_map, tmp_map, sve_vq_map, SVE_VQ_MAX);
> > +
> > +	/* Find the lowest such VQ, if any: */
> > +	b = find_last_bit(tmp_map, SVE_VQ_MAX);
> > +	if (b >= SVE_VQ_MAX)
> > +		return 0; /* no mismatches */
> > +
> > +	/*
> > +	 * Mismatches above sve_max_virtualisable_vl are fine, since
> > +	 * no guest is allowed to configure ZCR_EL2.LEN to exceed this:
> > +	 */
> > +	if (sve_vl_from_vq(bit_to_vq(b)) <= sve_max_virtualisable_vl) {
> > +		pr_warn("SVE: cpu%d: Unsupported vector length(s) present\n",
> 
> Nit: might be good to specify that the vector length is unsupported for
> virtualisation.
> 
> Also, since KVM is the one deciding what to do with the information,
> should we have a warning here? But I can understand that knowing which
> CPUs are introducing unsupported vector length, maybe using pr_devel()
> instead of pr_warn()

These warnings are really for consumption by SoC vendors, not users:
my aim is to flag up systems that we consider broken (or at least,
unsuitable for running KVM).

So I prefer to make this noisy and limit the amount of "useful"
information people might be tempted to programmatically scrape from
dmesg.

cpufeatures uses pr_warn("SANITY CHECK: [...]") here.  Maybe I should
stick "SANITY CHECK" in here too?  I will also try to make the commit
message more explicit and/or add comments to make the intent of the code
clearer.

It may also make sense to make this noise even if KVM isn't enabled
(which is a rare case anyhow).

Thoughts?

> In any case, the logic looks good to me:
> 
> Reviewed-by: Julien Thierry <julien.thierry@arm.com>

Thanks
---Dave

_______________________________________________
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] 205+ messages in thread

* Re: [PATCH v5 06/26] arm64/sve: Check SVE virtualisability
  2019-02-21 13:36     ` Julien Grall
@ 2019-02-26 12:06       ` Dave Martin
  -1 siblings, 0 replies; 205+ messages in thread
From: Dave Martin @ 2019-02-26 12:06 UTC (permalink / raw)
  To: Julien Grall
  Cc: Okamoto Takayuki, Christoffer Dall, Ard Biesheuvel, Marc Zyngier,
	Catalin Marinas, Will Deacon, Zhang Lei, kvmarm,
	linux-arm-kernel

On Thu, Feb 21, 2019 at 01:36:26PM +0000, Julien Grall wrote:
> Hi Dave,
> 
> On 18/02/2019 19:52, Dave Martin wrote:
> >+	/*
> >+	 * Mismatches above sve_max_virtualisable_vl are fine, since
> >+	 * no guest is allowed to configure ZCR_EL2.LEN to exceed this:
> >+	 */
> >+	if (sve_vl_from_vq(bit_to_vq(b)) <= sve_max_virtualisable_vl) {
> >+		pr_warn("SVE: cpu%d: Unsupported vector length(s) present\n",
> >+			smp_processor_id());
> 
> Would it be worth to print the unsupported vector length?

Possibly not, but admittedly the intent is a bit unclear in this patch.

See my reply to Julien Thierry (and respond on that subthread if you
have comments, so that we don't end up with two subthreads discussing
the same thing...)

Thanks
---Dave

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

* Re: [PATCH v5 06/26] arm64/sve: Check SVE virtualisability
@ 2019-02-26 12:06       ` Dave Martin
  0 siblings, 0 replies; 205+ messages in thread
From: Dave Martin @ 2019-02-26 12:06 UTC (permalink / raw)
  To: Julien Grall
  Cc: Okamoto Takayuki, Christoffer Dall, Ard Biesheuvel, Marc Zyngier,
	Catalin Marinas, Will Deacon, Zhang Lei, kvmarm,
	linux-arm-kernel

On Thu, Feb 21, 2019 at 01:36:26PM +0000, Julien Grall wrote:
> Hi Dave,
> 
> On 18/02/2019 19:52, Dave Martin wrote:
> >+	/*
> >+	 * Mismatches above sve_max_virtualisable_vl are fine, since
> >+	 * no guest is allowed to configure ZCR_EL2.LEN to exceed this:
> >+	 */
> >+	if (sve_vl_from_vq(bit_to_vq(b)) <= sve_max_virtualisable_vl) {
> >+		pr_warn("SVE: cpu%d: Unsupported vector length(s) present\n",
> >+			smp_processor_id());
> 
> Would it be worth to print the unsupported vector length?

Possibly not, but admittedly the intent is a bit unclear in this patch.

See my reply to Julien Thierry (and respond on that subthread if you
have comments, so that we don't end up with two subthreads discussing
the same thing...)

Thanks
---Dave

_______________________________________________
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] 205+ messages in thread

* Re: [PATCH v5 07/26] arm64/sve: Clarify role of the VQ map maintenance functions
  2019-02-20 11:43     ` Julien Thierry
@ 2019-02-26 12:06       ` Dave Martin
  -1 siblings, 0 replies; 205+ messages in thread
From: Dave Martin @ 2019-02-26 12:06 UTC (permalink / raw)
  To: Julien Thierry
  Cc: Okamoto Takayuki, Christoffer Dall, Ard Biesheuvel, Marc Zyngier,
	Catalin Marinas, Will Deacon, Zhang Lei, kvmarm,
	linux-arm-kernel

On Wed, Feb 20, 2019 at 11:43:24AM +0000, Julien Thierry wrote:
> 
> 
> On 18/02/2019 19:52, Dave Martin wrote:
> > The roles of sve_init_vq_map(), sve_update_vq_map() and
> > sve_verify_vq_map() are highly non-obvious to anyone who has not dug
> > through cpufeatures.c in detail.
> > 
> > Since the way these functions interact with each other is more
> > important here than a full understanding of the cpufeatures code, this
> > patch adds comments to make the functions' roles clearer.
> > 
> > No functional change.
> > 
> > Signed-off-by: Dave Martin <Dave.Martin@arm.com>
> > ---
> >  arch/arm64/kernel/fpsimd.c | 10 +++++++++-
> >  1 file changed, 9 insertions(+), 1 deletion(-)
> > 
> > diff --git a/arch/arm64/kernel/fpsimd.c b/arch/arm64/kernel/fpsimd.c
> > index 64729e2..92c2331 100644
> > --- a/arch/arm64/kernel/fpsimd.c
> > +++ b/arch/arm64/kernel/fpsimd.c
> > @@ -647,6 +647,10 @@ static void sve_probe_vqs(DECLARE_BITMAP(map, SVE_VQ_MAX))
> >  	}
> >  }
> >  
> > +/*
> > + * Initialise the set of known supported VQs for the boot CPU.
> > + * This is called during kernel boot, before secondary CPUs are brought up.
> > + */
> >  void __init sve_init_vq_map(void)
> >  {
> >  	sve_probe_vqs(sve_vq_map);
> > @@ -656,6 +660,7 @@ void __init sve_init_vq_map(void)
> >  /*
> >   * If we haven't committed to the set of supported VQs yet, filter out
> >   * those not supported by the current CPU.
> > + * This function is called during the bring-up of early secondary CPUs only.
> >   */
> >  void sve_update_vq_map(void)
> >  {
> > @@ -666,7 +671,10 @@ void sve_update_vq_map(void)
> >  	bitmap_or(sve_vq_partial_map, sve_vq_partial_map, tmp_map, SVE_VQ_MAX);
> >  }
> >  
> > -/* Check whether the current CPU supports all VQs in the committed set */
> > +/*
> > + * Check whether the current CPU supports all VQs in the committed set.
> > + * This function is called during the bring-up of late secondary CPUs only.
> 
> Oh I see, this is for late CPUs. So you can probably disregard my
> comment on the warning in the previous patch.
> 
> If you respin this series, I feel it would be more useful to have this
> patch before the current patch 6.

Agreed, I'll swap them over.  Looking at the two patches, I'm not sure
how they ended up this way round.  It may have been an unintended side-
effect of a previous rebase.

> Reviewed-by: Julien Thierry <julien.thierry@arm.com>

Thanks
---Dave

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

* Re: [PATCH v5 07/26] arm64/sve: Clarify role of the VQ map maintenance functions
@ 2019-02-26 12:06       ` Dave Martin
  0 siblings, 0 replies; 205+ messages in thread
From: Dave Martin @ 2019-02-26 12:06 UTC (permalink / raw)
  To: Julien Thierry
  Cc: Okamoto Takayuki, Christoffer Dall, Ard Biesheuvel, Marc Zyngier,
	Catalin Marinas, Will Deacon, Zhang Lei, kvmarm,
	linux-arm-kernel

On Wed, Feb 20, 2019 at 11:43:24AM +0000, Julien Thierry wrote:
> 
> 
> On 18/02/2019 19:52, Dave Martin wrote:
> > The roles of sve_init_vq_map(), sve_update_vq_map() and
> > sve_verify_vq_map() are highly non-obvious to anyone who has not dug
> > through cpufeatures.c in detail.
> > 
> > Since the way these functions interact with each other is more
> > important here than a full understanding of the cpufeatures code, this
> > patch adds comments to make the functions' roles clearer.
> > 
> > No functional change.
> > 
> > Signed-off-by: Dave Martin <Dave.Martin@arm.com>
> > ---
> >  arch/arm64/kernel/fpsimd.c | 10 +++++++++-
> >  1 file changed, 9 insertions(+), 1 deletion(-)
> > 
> > diff --git a/arch/arm64/kernel/fpsimd.c b/arch/arm64/kernel/fpsimd.c
> > index 64729e2..92c2331 100644
> > --- a/arch/arm64/kernel/fpsimd.c
> > +++ b/arch/arm64/kernel/fpsimd.c
> > @@ -647,6 +647,10 @@ static void sve_probe_vqs(DECLARE_BITMAP(map, SVE_VQ_MAX))
> >  	}
> >  }
> >  
> > +/*
> > + * Initialise the set of known supported VQs for the boot CPU.
> > + * This is called during kernel boot, before secondary CPUs are brought up.
> > + */
> >  void __init sve_init_vq_map(void)
> >  {
> >  	sve_probe_vqs(sve_vq_map);
> > @@ -656,6 +660,7 @@ void __init sve_init_vq_map(void)
> >  /*
> >   * If we haven't committed to the set of supported VQs yet, filter out
> >   * those not supported by the current CPU.
> > + * This function is called during the bring-up of early secondary CPUs only.
> >   */
> >  void sve_update_vq_map(void)
> >  {
> > @@ -666,7 +671,10 @@ void sve_update_vq_map(void)
> >  	bitmap_or(sve_vq_partial_map, sve_vq_partial_map, tmp_map, SVE_VQ_MAX);
> >  }
> >  
> > -/* Check whether the current CPU supports all VQs in the committed set */
> > +/*
> > + * Check whether the current CPU supports all VQs in the committed set.
> > + * This function is called during the bring-up of late secondary CPUs only.
> 
> Oh I see, this is for late CPUs. So you can probably disregard my
> comment on the warning in the previous patch.
> 
> If you respin this series, I feel it would be more useful to have this
> patch before the current patch 6.

Agreed, I'll swap them over.  Looking at the two patches, I'm not sure
how they ended up this way round.  It may have been an unintended side-
effect of a previous rebase.

> Reviewed-by: Julien Thierry <julien.thierry@arm.com>

Thanks
---Dave

_______________________________________________
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] 205+ messages in thread

* Re: [PATCH v5 07/26] arm64/sve: Clarify role of the VQ map maintenance functions
  2019-02-21 13:46     ` Julien Grall
@ 2019-02-26 12:07       ` Dave Martin
  -1 siblings, 0 replies; 205+ messages in thread
From: Dave Martin @ 2019-02-26 12:07 UTC (permalink / raw)
  To: Julien Grall
  Cc: Okamoto Takayuki, Christoffer Dall, Ard Biesheuvel, Marc Zyngier,
	Catalin Marinas, Will Deacon, Zhang Lei, kvmarm,
	linux-arm-kernel

On Thu, Feb 21, 2019 at 01:46:46PM +0000, Julien Grall wrote:
> Hi Dave,
> 
> On 18/02/2019 19:52, Dave Martin wrote:
> >The roles of sve_init_vq_map(), sve_update_vq_map() and
> >sve_verify_vq_map() are highly non-obvious to anyone who has not dug
> >through cpufeatures.c in detail.
> >
> >Since the way these functions interact with each other is more
> >important here than a full understanding of the cpufeatures code, this
> >patch adds comments to make the functions' roles clearer.
> >
> >No functional change.
> >
> >Signed-off-by: Dave Martin <Dave.Martin@arm.com>
> 
> Reviewed-by: Julien Grall <julien.grall@arm.com>

Thanks
---Dave

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

* Re: [PATCH v5 07/26] arm64/sve: Clarify role of the VQ map maintenance functions
@ 2019-02-26 12:07       ` Dave Martin
  0 siblings, 0 replies; 205+ messages in thread
From: Dave Martin @ 2019-02-26 12:07 UTC (permalink / raw)
  To: Julien Grall
  Cc: Okamoto Takayuki, Christoffer Dall, Ard Biesheuvel, Marc Zyngier,
	Catalin Marinas, Will Deacon, Zhang Lei, kvmarm,
	linux-arm-kernel

On Thu, Feb 21, 2019 at 01:46:46PM +0000, Julien Grall wrote:
> Hi Dave,
> 
> On 18/02/2019 19:52, Dave Martin wrote:
> >The roles of sve_init_vq_map(), sve_update_vq_map() and
> >sve_verify_vq_map() are highly non-obvious to anyone who has not dug
> >through cpufeatures.c in detail.
> >
> >Since the way these functions interact with each other is more
> >important here than a full understanding of the cpufeatures code, this
> >patch adds comments to make the functions' roles clearer.
> >
> >No functional change.
> >
> >Signed-off-by: Dave Martin <Dave.Martin@arm.com>
> 
> Reviewed-by: Julien Grall <julien.grall@arm.com>

Thanks
---Dave

_______________________________________________
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] 205+ messages in thread

* Re: [PATCH v5 08/26] arm64/sve: Enable SVE state tracking for non-task contexts
  2019-02-22 15:26     ` Julien Grall
@ 2019-02-26 12:07       ` Dave Martin
  -1 siblings, 0 replies; 205+ messages in thread
From: Dave Martin @ 2019-02-26 12:07 UTC (permalink / raw)
  To: Julien Grall
  Cc: Okamoto Takayuki, Christoffer Dall, Ard Biesheuvel, Marc Zyngier,
	Catalin Marinas, Will Deacon, Zhang Lei, kvmarm,
	linux-arm-kernel

On Fri, Feb 22, 2019 at 03:26:51PM +0000, Julien Grall wrote:
> Hi Dave,
> 
> On 18/02/2019 19:52, Dave Martin wrote:
> >The current FPSIMD/SVE context handling support for non-task (i.e.,
> >KVM vcpu) contexts does not take SVE into account.  This means that
> 
> NIT: Double-space before "This".

See patch 2...

[...]

Does the code look reasonable to you?  This interacts with FPSIMD/SVE
context switch in the host, so it would be good to have your view on it.

Cheers
---Dave

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

* Re: [PATCH v5 08/26] arm64/sve: Enable SVE state tracking for non-task contexts
@ 2019-02-26 12:07       ` Dave Martin
  0 siblings, 0 replies; 205+ messages in thread
From: Dave Martin @ 2019-02-26 12:07 UTC (permalink / raw)
  To: Julien Grall
  Cc: Okamoto Takayuki, Christoffer Dall, Ard Biesheuvel, Marc Zyngier,
	Catalin Marinas, Will Deacon, Zhang Lei, kvmarm,
	linux-arm-kernel

On Fri, Feb 22, 2019 at 03:26:51PM +0000, Julien Grall wrote:
> Hi Dave,
> 
> On 18/02/2019 19:52, Dave Martin wrote:
> >The current FPSIMD/SVE context handling support for non-task (i.e.,
> >KVM vcpu) contexts does not take SVE into account.  This means that
> 
> NIT: Double-space before "This".

See patch 2...

[...]

Does the code look reasonable to you?  This interacts with FPSIMD/SVE
context switch in the host, so it would be good to have your view on it.

Cheers
---Dave

_______________________________________________
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] 205+ messages in thread

* Re: [PATCH v5 11/26] KVM: arm64: Extend reset_unknown() to handle mixed RES0/UNKNOWN registers
  2019-02-20 13:33     ` Julien Thierry
@ 2019-02-26 12:07       ` Dave Martin
  -1 siblings, 0 replies; 205+ messages in thread
From: Dave Martin @ 2019-02-26 12:07 UTC (permalink / raw)
  To: Julien Thierry
  Cc: Okamoto Takayuki, Christoffer Dall, Ard Biesheuvel, Marc Zyngier,
	Catalin Marinas, Will Deacon, Zhang Lei, kvmarm,
	linux-arm-kernel

On Wed, Feb 20, 2019 at 01:33:28PM +0000, Julien Thierry wrote:
> Hi Dave,
> 
> On 18/02/2019 19:52, Dave Martin wrote:
> > The reset_unknown() system register helper initialises a guest
> > register to a distinctive junk value on vcpu reset, to help expose
> > and debug deficient register initialisation within the guest.
> > 
> > Some registers such as the SVE control register ZCR_EL1 contain a
> > mixture of UNKNOWN fields and RES0 bits.  For these,
> > reset_unknown() does not work at present, since it sets all bits to
> > junk values instead of just the wanted bits.
> > 
> > There is no need to craft another special helper just for that,
> > since reset_unknown() almost does the appropriate thing anyway.
> > This patch takes advantage of the unused val field in struct
> > sys_reg_desc to specify a mask of bits that should be initialised
> > to zero instead of junk.
> > 
> > All existing users of reset_unknown() do not (and should not)
> > define a value for val, so they will implicitly set it to zero,
> > resulting in all bits being made UNKNOWN by this function: thus,
> > this patch makes no functional change for currently defined
> > registers.
> > 
> > Future patches will make use of non-zero val.
> > 
> > Signed-off-by: Dave Martin <Dave.Martin@arm.com>
> > ---
> >  arch/arm64/kvm/sys_regs.h | 11 +++++++++--
> >  1 file changed, 9 insertions(+), 2 deletions(-)
> > 
> > diff --git a/arch/arm64/kvm/sys_regs.h b/arch/arm64/kvm/sys_regs.h
> > index 3b1bc7f..174ffc0 100644
> > --- a/arch/arm64/kvm/sys_regs.h
> > +++ b/arch/arm64/kvm/sys_regs.h
> > @@ -56,7 +56,12 @@ struct sys_reg_desc {
> >  	/* Index into sys_reg[], or 0 if we don't need to save it. */
> >  	int reg;
> >  
> > -	/* Value (usually reset value) */
> > +	/*
> > +	 * Value (usually reset value)
> > +	 * For reset_unknown, each bit set to 1 in val is treated as
> > +	 * RES0 in the register: the corresponding register bit is
> > +	 * reset to 0 instead of "unknown".
> > +	 */
> 
> Seeing there are users of this field, I find this a bit fragile. Is

In fact, I only see reset_val(), and the reset_val workalikes
reset_bcr(), reset_bvr() etc., using this field.

So, when used, this is always the reset value right now.

We could water the comment down to "data used by the reset method."


> there a reason not to add a separate "u64 res0_mask;" ?
> 
> The sys_reg_desc structures are instantiated once as constants for the
> whole system rather than per VM/VCPU. Would it be really bad to add a
> 64bit field there?

Not really.  I was trying to avoid overengineering something that will
probably only ever be used in one or two places.

With that in mind, I'm feeling this patch may be premature factoring
and can be dropped.  Initialising ZCR_EL1 with 0, or a fixed value
based on 0x1de7ec7edbadc0deULL would be good enough for this currently
unique case.  

Thoughts?

[...]

Cheers
---Dave

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

* Re: [PATCH v5 11/26] KVM: arm64: Extend reset_unknown() to handle mixed RES0/UNKNOWN registers
@ 2019-02-26 12:07       ` Dave Martin
  0 siblings, 0 replies; 205+ messages in thread
From: Dave Martin @ 2019-02-26 12:07 UTC (permalink / raw)
  To: Julien Thierry
  Cc: Okamoto Takayuki, Christoffer Dall, Ard Biesheuvel, Marc Zyngier,
	Catalin Marinas, Will Deacon, Zhang Lei, kvmarm,
	linux-arm-kernel

On Wed, Feb 20, 2019 at 01:33:28PM +0000, Julien Thierry wrote:
> Hi Dave,
> 
> On 18/02/2019 19:52, Dave Martin wrote:
> > The reset_unknown() system register helper initialises a guest
> > register to a distinctive junk value on vcpu reset, to help expose
> > and debug deficient register initialisation within the guest.
> > 
> > Some registers such as the SVE control register ZCR_EL1 contain a
> > mixture of UNKNOWN fields and RES0 bits.  For these,
> > reset_unknown() does not work at present, since it sets all bits to
> > junk values instead of just the wanted bits.
> > 
> > There is no need to craft another special helper just for that,
> > since reset_unknown() almost does the appropriate thing anyway.
> > This patch takes advantage of the unused val field in struct
> > sys_reg_desc to specify a mask of bits that should be initialised
> > to zero instead of junk.
> > 
> > All existing users of reset_unknown() do not (and should not)
> > define a value for val, so they will implicitly set it to zero,
> > resulting in all bits being made UNKNOWN by this function: thus,
> > this patch makes no functional change for currently defined
> > registers.
> > 
> > Future patches will make use of non-zero val.
> > 
> > Signed-off-by: Dave Martin <Dave.Martin@arm.com>
> > ---
> >  arch/arm64/kvm/sys_regs.h | 11 +++++++++--
> >  1 file changed, 9 insertions(+), 2 deletions(-)
> > 
> > diff --git a/arch/arm64/kvm/sys_regs.h b/arch/arm64/kvm/sys_regs.h
> > index 3b1bc7f..174ffc0 100644
> > --- a/arch/arm64/kvm/sys_regs.h
> > +++ b/arch/arm64/kvm/sys_regs.h
> > @@ -56,7 +56,12 @@ struct sys_reg_desc {
> >  	/* Index into sys_reg[], or 0 if we don't need to save it. */
> >  	int reg;
> >  
> > -	/* Value (usually reset value) */
> > +	/*
> > +	 * Value (usually reset value)
> > +	 * For reset_unknown, each bit set to 1 in val is treated as
> > +	 * RES0 in the register: the corresponding register bit is
> > +	 * reset to 0 instead of "unknown".
> > +	 */
> 
> Seeing there are users of this field, I find this a bit fragile. Is

In fact, I only see reset_val(), and the reset_val workalikes
reset_bcr(), reset_bvr() etc., using this field.

So, when used, this is always the reset value right now.

We could water the comment down to "data used by the reset method."


> there a reason not to add a separate "u64 res0_mask;" ?
> 
> The sys_reg_desc structures are instantiated once as constants for the
> whole system rather than per VM/VCPU. Would it be really bad to add a
> 64bit field there?

Not really.  I was trying to avoid overengineering something that will
probably only ever be used in one or two places.

With that in mind, I'm feeling this patch may be premature factoring
and can be dropped.  Initialising ZCR_EL1 with 0, or a fixed value
based on 0x1de7ec7edbadc0deULL would be good enough for this currently
unique case.  

Thoughts?

[...]

Cheers
---Dave

_______________________________________________
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] 205+ messages in thread

* Re: [PATCH v5 12/26] KVM: arm64: Support runtime sysreg visibility filtering
  2019-02-20 14:33     ` Julien Thierry
@ 2019-02-26 12:07       ` Dave Martin
  -1 siblings, 0 replies; 205+ messages in thread
From: Dave Martin @ 2019-02-26 12:07 UTC (permalink / raw)
  To: Julien Thierry
  Cc: Okamoto Takayuki, Christoffer Dall, Ard Biesheuvel, Marc Zyngier,
	Catalin Marinas, Will Deacon, Zhang Lei, kvmarm,
	linux-arm-kernel

On Wed, Feb 20, 2019 at 02:33:44PM +0000, Julien Thierry wrote:
> 
> 
> On 18/02/2019 19:52, Dave Martin wrote:
> > Some optional features of the Arm architecture add new system
> > registers that are not present in the base architecture.
> > 
> > Where these features are optional for the guest, the visibility of
> > these registers may need to depend on some runtime configuration,
> > such as a flag passed to KVM_ARM_VCPU_INIT.
> > 
> > For example, ZCR_EL1 and ID_AA64ZFR0_EL1 need to be hidden if SVE
> > is not enabled for the guest, even though these registers may be
> > present in the hardware and visible to the host at EL2.
> > 
> > Adding special-case checks all over the place for individual
> > registers is going to get messy as the number of conditionally-
> > visible registers grows.
> > 
> > In order to help solve this problem, this patch adds a new sysreg
> > method restrictions() that can be used to hook in any needed
> > runtime visibility checks.  This method can currently return
> > REG_NO_USER to inhibit enumeration and ioctl access to the register
> > for userspace, and REG_NO_GUEST to inhibit runtime access by the
> > guest using MSR/MRS.
> > 
> > This allows a conditionally modified view of individual system
> > registers such as the CPU ID registers, in addition to completely
> > hiding register where appropriate.
> > 
> > Signed-off-by: Dave Martin <Dave.Martin@arm.com>
> 
> Reviewed-by: Julien Thierry <julien.thierry@arm.com>

Thanks
---Dave

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

* Re: [PATCH v5 12/26] KVM: arm64: Support runtime sysreg visibility filtering
@ 2019-02-26 12:07       ` Dave Martin
  0 siblings, 0 replies; 205+ messages in thread
From: Dave Martin @ 2019-02-26 12:07 UTC (permalink / raw)
  To: Julien Thierry
  Cc: Okamoto Takayuki, Christoffer Dall, Ard Biesheuvel, Marc Zyngier,
	Catalin Marinas, Will Deacon, Zhang Lei, kvmarm,
	linux-arm-kernel

On Wed, Feb 20, 2019 at 02:33:44PM +0000, Julien Thierry wrote:
> 
> 
> On 18/02/2019 19:52, Dave Martin wrote:
> > Some optional features of the Arm architecture add new system
> > registers that are not present in the base architecture.
> > 
> > Where these features are optional for the guest, the visibility of
> > these registers may need to depend on some runtime configuration,
> > such as a flag passed to KVM_ARM_VCPU_INIT.
> > 
> > For example, ZCR_EL1 and ID_AA64ZFR0_EL1 need to be hidden if SVE
> > is not enabled for the guest, even though these registers may be
> > present in the hardware and visible to the host at EL2.
> > 
> > Adding special-case checks all over the place for individual
> > registers is going to get messy as the number of conditionally-
> > visible registers grows.
> > 
> > In order to help solve this problem, this patch adds a new sysreg
> > method restrictions() that can be used to hook in any needed
> > runtime visibility checks.  This method can currently return
> > REG_NO_USER to inhibit enumeration and ioctl access to the register
> > for userspace, and REG_NO_GUEST to inhibit runtime access by the
> > guest using MSR/MRS.
> > 
> > This allows a conditionally modified view of individual system
> > registers such as the CPU ID registers, in addition to completely
> > hiding register where appropriate.
> > 
> > Signed-off-by: Dave Martin <Dave.Martin@arm.com>
> 
> Reviewed-by: Julien Thierry <julien.thierry@arm.com>

Thanks
---Dave

_______________________________________________
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] 205+ messages in thread

* Re: [PATCH v5 12/26] KVM: arm64: Support runtime sysreg visibility filtering
  2019-02-20 15:37     ` Mark Rutland
@ 2019-02-26 12:12       ` Dave Martin
  -1 siblings, 0 replies; 205+ messages in thread
From: Dave Martin @ 2019-02-26 12:12 UTC (permalink / raw)
  To: Mark Rutland
  Cc: Okamoto Takayuki, Christoffer Dall, Ard Biesheuvel, Marc Zyngier,
	Catalin Marinas, Will Deacon, Zhang Lei, kvmarm,
	linux-arm-kernel

On Wed, Feb 20, 2019 at 03:37:26PM +0000, Mark Rutland wrote:
> On Mon, Feb 18, 2019 at 07:52:25PM +0000, Dave Martin wrote:
> > Some optional features of the Arm architecture add new system
> > registers that are not present in the base architecture.
> > 
> > Where these features are optional for the guest, the visibility of
> > these registers may need to depend on some runtime configuration,
> > such as a flag passed to KVM_ARM_VCPU_INIT.
> > 
> > For example, ZCR_EL1 and ID_AA64ZFR0_EL1 need to be hidden if SVE
> > is not enabled for the guest, even though these registers may be
> > present in the hardware and visible to the host at EL2.
> > 
> > Adding special-case checks all over the place for individual
> > registers is going to get messy as the number of conditionally-
> > visible registers grows.
> > 
> > In order to help solve this problem, this patch adds a new sysreg
> > method restrictions() that can be used to hook in any needed
> > runtime visibility checks.  This method can currently return
> > REG_NO_USER to inhibit enumeration and ioctl access to the register
> > for userspace, and REG_NO_GUEST to inhibit runtime access by the
> > guest using MSR/MRS.
> > 
> > This allows a conditionally modified view of individual system
> > registers such as the CPU ID registers, in addition to completely
> > hiding register where appropriate.
> > 
> > Signed-off-by: Dave Martin <Dave.Martin@arm.com>
> > 
> > ---
> > 
> > Changes since v4:
> > 
> >  * Move from a boolean sysreg property that just suppresses register
> >    enumeration via KVM_GET_REG_LIST, to a multi-flag property that
> >    allows independent runtime control of MRS/MSR and user ioctl access.
> > 
> >    This allows registers to be either hidden completely, or to have
> >    hybrid behaviours (such as the not-enumerated, RAZ, WAZ behaviour of
> >    "non-present" CPU ID regs).
> 
> Sorry for bikeshedding...
> 
> > +	/* Check for regs disabled by runtime config */
> > +	if (restrictions(vcpu, r) & REG_NO_GUEST) {
> 
> Maybe it's worth wrapping this as something like
> 
> 	reg_runtime_hidden_from_guest(vcpu, r)
> 
> ... and avoid exposing the raw flags to all the places we have to check?
> 
> [...]
> 
> > +#define REG_NO_USER	(1 << 0) /* hidden from userspace ioctl interface */
> > +#define REG_NO_GUEST	(1 << 1) /* hidden from guest */
> 
> Perhaps REG_USER_HIDDEN and REG_GUEST_HIDDEN?

I'm not attached to any particular naming, so I'm not opposed to making
changes similar to those you suggest.

There are some anomalies right now:

1) Currently, we can express REG_NO_GUEST by itself, which is a of an
odd thing to have.  I'm not sure whether that's a problem or not.
Keeping the flags as-is at least keeps the code simple.

2) These flags do not quite have the obvious semantics: these are
overrides rather than determining precisely when a reg is/isn't
accessible.

So, REG_NO_USER means "don't even call this reg's get/set_user(): forbid
user access unconditionally", whereas lack of this flag means "call the
appropriate get/set_user() function to find out what to do, which may
or may not result in forbidding the access".

Maybe this subtlety is just a question of clear commenting.  I can't
think of obviously-correct names that won't be stupidly verbose...

Thoughts?

Cheers
---Dave

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

* Re: [PATCH v5 12/26] KVM: arm64: Support runtime sysreg visibility filtering
@ 2019-02-26 12:12       ` Dave Martin
  0 siblings, 0 replies; 205+ messages in thread
From: Dave Martin @ 2019-02-26 12:12 UTC (permalink / raw)
  To: Mark Rutland
  Cc: Okamoto Takayuki, Christoffer Dall, Ard Biesheuvel, Marc Zyngier,
	Catalin Marinas, Will Deacon, Zhang Lei, kvmarm,
	linux-arm-kernel

On Wed, Feb 20, 2019 at 03:37:26PM +0000, Mark Rutland wrote:
> On Mon, Feb 18, 2019 at 07:52:25PM +0000, Dave Martin wrote:
> > Some optional features of the Arm architecture add new system
> > registers that are not present in the base architecture.
> > 
> > Where these features are optional for the guest, the visibility of
> > these registers may need to depend on some runtime configuration,
> > such as a flag passed to KVM_ARM_VCPU_INIT.
> > 
> > For example, ZCR_EL1 and ID_AA64ZFR0_EL1 need to be hidden if SVE
> > is not enabled for the guest, even though these registers may be
> > present in the hardware and visible to the host at EL2.
> > 
> > Adding special-case checks all over the place for individual
> > registers is going to get messy as the number of conditionally-
> > visible registers grows.
> > 
> > In order to help solve this problem, this patch adds a new sysreg
> > method restrictions() that can be used to hook in any needed
> > runtime visibility checks.  This method can currently return
> > REG_NO_USER to inhibit enumeration and ioctl access to the register
> > for userspace, and REG_NO_GUEST to inhibit runtime access by the
> > guest using MSR/MRS.
> > 
> > This allows a conditionally modified view of individual system
> > registers such as the CPU ID registers, in addition to completely
> > hiding register where appropriate.
> > 
> > Signed-off-by: Dave Martin <Dave.Martin@arm.com>
> > 
> > ---
> > 
> > Changes since v4:
> > 
> >  * Move from a boolean sysreg property that just suppresses register
> >    enumeration via KVM_GET_REG_LIST, to a multi-flag property that
> >    allows independent runtime control of MRS/MSR and user ioctl access.
> > 
> >    This allows registers to be either hidden completely, or to have
> >    hybrid behaviours (such as the not-enumerated, RAZ, WAZ behaviour of
> >    "non-present" CPU ID regs).
> 
> Sorry for bikeshedding...
> 
> > +	/* Check for regs disabled by runtime config */
> > +	if (restrictions(vcpu, r) & REG_NO_GUEST) {
> 
> Maybe it's worth wrapping this as something like
> 
> 	reg_runtime_hidden_from_guest(vcpu, r)
> 
> ... and avoid exposing the raw flags to all the places we have to check?
> 
> [...]
> 
> > +#define REG_NO_USER	(1 << 0) /* hidden from userspace ioctl interface */
> > +#define REG_NO_GUEST	(1 << 1) /* hidden from guest */
> 
> Perhaps REG_USER_HIDDEN and REG_GUEST_HIDDEN?

I'm not attached to any particular naming, so I'm not opposed to making
changes similar to those you suggest.

There are some anomalies right now:

1) Currently, we can express REG_NO_GUEST by itself, which is a of an
odd thing to have.  I'm not sure whether that's a problem or not.
Keeping the flags as-is at least keeps the code simple.

2) These flags do not quite have the obvious semantics: these are
overrides rather than determining precisely when a reg is/isn't
accessible.

So, REG_NO_USER means "don't even call this reg's get/set_user(): forbid
user access unconditionally", whereas lack of this flag means "call the
appropriate get/set_user() function to find out what to do, which may
or may not result in forbidding the access".

Maybe this subtlety is just a question of clear commenting.  I can't
think of obviously-correct names that won't be stupidly verbose...

Thoughts?

Cheers
---Dave

_______________________________________________
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] 205+ messages in thread

* Re: [PATCH v5 14/26] KVM: arm64/sve: Context switch the SVE registers
  2019-02-20 16:19     ` Mark Rutland
@ 2019-02-26 12:13       ` Dave Martin
  -1 siblings, 0 replies; 205+ messages in thread
From: Dave Martin @ 2019-02-26 12:13 UTC (permalink / raw)
  To: Mark Rutland
  Cc: Okamoto Takayuki, Christoffer Dall, Ard Biesheuvel, Marc Zyngier,
	Catalin Marinas, Will Deacon, Zhang Lei, kvmarm,
	linux-arm-kernel

On Wed, Feb 20, 2019 at 04:19:18PM +0000, Mark Rutland wrote:
> On Mon, Feb 18, 2019 at 07:52:27PM +0000, Dave Martin wrote:
> > -static bool __hyp_text __hyp_switch_fpsimd(struct kvm_vcpu *vcpu)
> > +/* Check for an FPSIMD/SVE trap and handle as appropriate */
> > +static bool __hyp_text __hyp_handle_fpsimd(struct kvm_vcpu *vcpu)
> >  {
> > -	struct user_fpsimd_state *host_fpsimd = vcpu->arch.host_fpsimd_state;
> > +	bool vhe, sve_guest, sve_host;
> > +	u8 trap_class;
> 
> Nit: elsewhere in kvm, this gets called hsr_ec. Can we use the same name
> here?

Done.

(This name is not used in hyp/switch.c yet, and I was sort of trying to
conform to the naming of kvm_vcpu_trap_get_class().  But hsr_ec is used
elsewhere, and more self-describing, so it makes sense.)

> 
> >  
> > -	if (has_vhe())
> > -		write_sysreg(read_sysreg(cpacr_el1) | CPACR_EL1_FPEN,
> > -			     cpacr_el1);
> > -	else
> > +	if (!system_supports_fpsimd())
> > +		return false;
> > +
> > +	if (system_supports_sve()) {
> > +		sve_guest = vcpu_has_sve(vcpu);
> > +		sve_host = vcpu->arch.flags & KVM_ARM64_HOST_SVE_IN_USE;
> > +		vhe = true;
> > +	} else {
> > +		sve_guest = false;
> > +		sve_host = false;
> > +		vhe = has_vhe();
> > +	}
> > +
> > +	trap_class = kvm_vcpu_trap_get_class(vcpu);
> > +	if (trap_class != ESR_ELx_EC_FP_ASIMD &&
> > +	    (!sve_guest || trap_class != ESR_ELx_EC_SVE))
> > +		return false;
> 
> This is somewhat painful to decipher, but I couldn't come up with
> something that was both succint and legible.
> 
> Maybe it's worth duplicating the SVE check, i.e.
> 
> 	if (hsr_ec != ESR_ELx_EC_FP_ASIMD &&
> 	    hsr_ec != ESR_ELx_EC_SVE)
> 		return false;
> 
> 	if (!sve_guest && hsr_ec == ESR_ELx_EC_SVE)
> 		return false;
> 
> ... ?

There were previously some static_key checks in here that I didn't want
to duplicate, which is part of the reason for trying to merge related
if-conditions together explicitly.

This is no longer relevant now that the static_key checks have been
hoisted out explicitly.  Something along the lines of your version
would definitely be clearer.  gcc also seems to merge the conditions
competently, so I'll pick up your suggestion for now.

Thanks
---Dave

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

* Re: [PATCH v5 14/26] KVM: arm64/sve: Context switch the SVE registers
@ 2019-02-26 12:13       ` Dave Martin
  0 siblings, 0 replies; 205+ messages in thread
From: Dave Martin @ 2019-02-26 12:13 UTC (permalink / raw)
  To: Mark Rutland
  Cc: Okamoto Takayuki, Christoffer Dall, Ard Biesheuvel, Marc Zyngier,
	Catalin Marinas, Will Deacon, Zhang Lei, kvmarm,
	linux-arm-kernel

On Wed, Feb 20, 2019 at 04:19:18PM +0000, Mark Rutland wrote:
> On Mon, Feb 18, 2019 at 07:52:27PM +0000, Dave Martin wrote:
> > -static bool __hyp_text __hyp_switch_fpsimd(struct kvm_vcpu *vcpu)
> > +/* Check for an FPSIMD/SVE trap and handle as appropriate */
> > +static bool __hyp_text __hyp_handle_fpsimd(struct kvm_vcpu *vcpu)
> >  {
> > -	struct user_fpsimd_state *host_fpsimd = vcpu->arch.host_fpsimd_state;
> > +	bool vhe, sve_guest, sve_host;
> > +	u8 trap_class;
> 
> Nit: elsewhere in kvm, this gets called hsr_ec. Can we use the same name
> here?

Done.

(This name is not used in hyp/switch.c yet, and I was sort of trying to
conform to the naming of kvm_vcpu_trap_get_class().  But hsr_ec is used
elsewhere, and more self-describing, so it makes sense.)

> 
> >  
> > -	if (has_vhe())
> > -		write_sysreg(read_sysreg(cpacr_el1) | CPACR_EL1_FPEN,
> > -			     cpacr_el1);
> > -	else
> > +	if (!system_supports_fpsimd())
> > +		return false;
> > +
> > +	if (system_supports_sve()) {
> > +		sve_guest = vcpu_has_sve(vcpu);
> > +		sve_host = vcpu->arch.flags & KVM_ARM64_HOST_SVE_IN_USE;
> > +		vhe = true;
> > +	} else {
> > +		sve_guest = false;
> > +		sve_host = false;
> > +		vhe = has_vhe();
> > +	}
> > +
> > +	trap_class = kvm_vcpu_trap_get_class(vcpu);
> > +	if (trap_class != ESR_ELx_EC_FP_ASIMD &&
> > +	    (!sve_guest || trap_class != ESR_ELx_EC_SVE))
> > +		return false;
> 
> This is somewhat painful to decipher, but I couldn't come up with
> something that was both succint and legible.
> 
> Maybe it's worth duplicating the SVE check, i.e.
> 
> 	if (hsr_ec != ESR_ELx_EC_FP_ASIMD &&
> 	    hsr_ec != ESR_ELx_EC_SVE)
> 		return false;
> 
> 	if (!sve_guest && hsr_ec == ESR_ELx_EC_SVE)
> 		return false;
> 
> ... ?

There were previously some static_key checks in here that I didn't want
to duplicate, which is part of the reason for trying to merge related
if-conditions together explicitly.

This is no longer relevant now that the static_key checks have been
hoisted out explicitly.  Something along the lines of your version
would definitely be clearer.  gcc also seems to merge the conditions
competently, so I'll pick up your suggestion for now.

Thanks
---Dave

_______________________________________________
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] 205+ messages in thread

* Re: [PATCH v5 14/26] KVM: arm64/sve: Context switch the SVE registers
  2019-02-20 16:46     ` Julien Thierry
@ 2019-02-26 12:13       ` Dave Martin
  -1 siblings, 0 replies; 205+ messages in thread
From: Dave Martin @ 2019-02-26 12:13 UTC (permalink / raw)
  To: Julien Thierry
  Cc: Okamoto Takayuki, Christoffer Dall, Ard Biesheuvel, Marc Zyngier,
	Catalin Marinas, Will Deacon, Zhang Lei, kvmarm,
	linux-arm-kernel

On Wed, Feb 20, 2019 at 04:46:57PM +0000, Julien Thierry wrote:
> 
> 
> On 18/02/2019 19:52, Dave Martin wrote:
> > In order to give each vcpu its own view of the SVE registers, this
> > patch adds context storage via a new sve_state pointer in struct
> > vcpu_arch.  An additional member sve_max_vl is also added for each
> > vcpu, to determine the maximum vector length visible to the guest
> > and thus the value to be configured in ZCR_EL2.LEN while the is
> 
> "While the <guest> is active"?

Hmmm, yes.  Thanks for deciphering that.  Done.

> > active.  This also determines the layout and size of the storage in
> > sve_state, which is read and written by the same backend functions
> > that are used for context-switching the SVE state for host tasks.
> > 
> > On SVE-enabled vcpus, SVE access traps are now handled by switching
> > in the vcpu's SVE context and disabling the trap before returning
> > to the guest.  On other vcpus, the trap is not handled and an exit
> > back to the host occurs, where the handle_sve() fallback path
> > reflects an undefined instruction exception back to the guest,
> > consistently with the behaviour of non-SVE-capable hardware (as was
> > done unconditionally prior to this patch).
> > 
> > No SVE handling is added on non-VHE-only paths, since VHE is an
> > architectural and Kconfig prerequisite of SVE.
> > 
> > Signed-off-by: Dave Martin <Dave.Martin@arm.com>
> > 
> 
> Otherwise:
> 
> Reviewed-by: Julien Thierry <julien.thierry@arm.com>

Thanks
---Dave

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

* Re: [PATCH v5 14/26] KVM: arm64/sve: Context switch the SVE registers
@ 2019-02-26 12:13       ` Dave Martin
  0 siblings, 0 replies; 205+ messages in thread
From: Dave Martin @ 2019-02-26 12:13 UTC (permalink / raw)
  To: Julien Thierry
  Cc: Okamoto Takayuki, Christoffer Dall, Ard Biesheuvel, Marc Zyngier,
	Catalin Marinas, Will Deacon, Zhang Lei, kvmarm,
	linux-arm-kernel

On Wed, Feb 20, 2019 at 04:46:57PM +0000, Julien Thierry wrote:
> 
> 
> On 18/02/2019 19:52, Dave Martin wrote:
> > In order to give each vcpu its own view of the SVE registers, this
> > patch adds context storage via a new sve_state pointer in struct
> > vcpu_arch.  An additional member sve_max_vl is also added for each
> > vcpu, to determine the maximum vector length visible to the guest
> > and thus the value to be configured in ZCR_EL2.LEN while the is
> 
> "While the <guest> is active"?

Hmmm, yes.  Thanks for deciphering that.  Done.

> > active.  This also determines the layout and size of the storage in
> > sve_state, which is read and written by the same backend functions
> > that are used for context-switching the SVE state for host tasks.
> > 
> > On SVE-enabled vcpus, SVE access traps are now handled by switching
> > in the vcpu's SVE context and disabling the trap before returning
> > to the guest.  On other vcpus, the trap is not handled and an exit
> > back to the host occurs, where the handle_sve() fallback path
> > reflects an undefined instruction exception back to the guest,
> > consistently with the behaviour of non-SVE-capable hardware (as was
> > done unconditionally prior to this patch).
> > 
> > No SVE handling is added on non-VHE-only paths, since VHE is an
> > architectural and Kconfig prerequisite of SVE.
> > 
> > Signed-off-by: Dave Martin <Dave.Martin@arm.com>
> > 
> 
> Otherwise:
> 
> Reviewed-by: Julien Thierry <julien.thierry@arm.com>

Thanks
---Dave

_______________________________________________
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] 205+ messages in thread

* Re: [PATCH v5 17/26] KVM: arm64: Reject ioctl access to FPSIMD V-regs on SVE vcpus
  2019-02-21 12:06     ` Julien Thierry
@ 2019-02-26 12:13       ` Dave Martin
  -1 siblings, 0 replies; 205+ messages in thread
From: Dave Martin @ 2019-02-26 12:13 UTC (permalink / raw)
  To: Julien Thierry
  Cc: Okamoto Takayuki, Christoffer Dall, Ard Biesheuvel, Marc Zyngier,
	Catalin Marinas, Will Deacon, Zhang Lei, kvmarm,
	linux-arm-kernel

On Thu, Feb 21, 2019 at 12:06:23PM +0000, Julien Thierry wrote:
> 
> 
> On 18/02/2019 19:52, Dave Martin wrote:
> > In order to avoid the pointless complexity of maintaining two ioctl
> > register access views of the same data, this patch blocks ioctl
> > access to the FPSIMD V-registers on vcpus that support SVE.
> > 
> > This will make it more straightforward to add SVE register access
> > support.
> > 
> > Since SVE is an opt-in feature for userspace, this will not affect
> > existing users.
> > 
> > Signed-off-by: Dave Martin <Dave.Martin@arm.com>
> 
> Reviewed-by: Julien Thierry <julien.thierry@arm.com>

Thanks
---Dave

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

* Re: [PATCH v5 17/26] KVM: arm64: Reject ioctl access to FPSIMD V-regs on SVE vcpus
@ 2019-02-26 12:13       ` Dave Martin
  0 siblings, 0 replies; 205+ messages in thread
From: Dave Martin @ 2019-02-26 12:13 UTC (permalink / raw)
  To: Julien Thierry
  Cc: Okamoto Takayuki, Christoffer Dall, Ard Biesheuvel, Marc Zyngier,
	Catalin Marinas, Will Deacon, Zhang Lei, kvmarm,
	linux-arm-kernel

On Thu, Feb 21, 2019 at 12:06:23PM +0000, Julien Thierry wrote:
> 
> 
> On 18/02/2019 19:52, Dave Martin wrote:
> > In order to avoid the pointless complexity of maintaining two ioctl
> > register access views of the same data, this patch blocks ioctl
> > access to the FPSIMD V-registers on vcpus that support SVE.
> > 
> > This will make it more straightforward to add SVE register access
> > support.
> > 
> > Since SVE is an opt-in feature for userspace, this will not affect
> > existing users.
> > 
> > Signed-off-by: Dave Martin <Dave.Martin@arm.com>
> 
> Reviewed-by: Julien Thierry <julien.thierry@arm.com>

Thanks
---Dave

_______________________________________________
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] 205+ messages in thread

* Re: [PATCH v5 18/26] KVM: arm64/sve: Add SVE support to register access ioctl interface
  2019-02-21 15:23     ` Julien Thierry
@ 2019-02-26 12:13       ` Dave Martin
  -1 siblings, 0 replies; 205+ messages in thread
From: Dave Martin @ 2019-02-26 12:13 UTC (permalink / raw)
  To: Julien Thierry
  Cc: Okamoto Takayuki, Christoffer Dall, Ard Biesheuvel, Marc Zyngier,
	Catalin Marinas, Will Deacon, Zhang Lei, kvmarm,
	linux-arm-kernel

On Thu, Feb 21, 2019 at 03:23:37PM +0000, Julien Thierry wrote:
> Hi Dave,
> 
> On 18/02/2019 19:52, Dave Martin wrote:
> > This patch adds the following registers for access via the
> > KVM_{GET,SET}_ONE_REG interface:
> > 
> >  * KVM_REG_ARM64_SVE_ZREG(n, i) (n = 0..31) (in 2048-bit slices)
> >  * KVM_REG_ARM64_SVE_PREG(n, i) (n = 0..15) (in 256-bit slices)
> >  * KVM_REG_ARM64_SVE_FFR(i) (in 256-bit slices)
> > 
> > In order to adapt gracefully to future architectural extensions,
> > the registers are logically divided up into slices as noted above:
> > the i parameter denotes the slice index.
> > 
> > This allows us to reserve space in the ABI for future expansion of
> > these registers.  However, as of today the architecture does not
> > permit registers to be larger than a single slice, so no code is
> > needed in the kernel to expose additional slices, for now.  The
> > code can be extended later as needed to expose them up to a maximum
> > of 32 slices (as carved out in the architecture itself) if they
> > really exist someday.
> > 
> > The registers are only visible for vcpus that have SVE enabled.
> > They are not enumerated by KVM_GET_REG_LIST on vcpus that do not
> > have SVE.
> > 
> > Accesses to the FPSIMD registers via KVM_REG_ARM_CORE is not
> > allowed for SVE-enabled vcpus: SVE-aware userspace can use the
> > KVM_REG_ARM64_SVE_ZREG() interface instead to access the same
> > register state.  This avoids some complex and pointless emulation
> > in the kernel to convert between the two views of these aliased
> > registers.
> > 
> > Signed-off-by: Dave Martin <Dave.Martin@arm.com>
> > 
> > ---
> > 
> > Changes since v4:
> > 
> >  * Add "BASE" #defines for the Z-reg and P-reg ranges in the KVM
> >    register ID space, to make the 0x400 magic number a little less
> >    cryptic.
> > 
> >  * Pull KVM_SVE_{Z,P}REG_SIZE defines from "KVM: arm64: Enumerate SVE
> >    register indices for KVM_GET_REG_LIST", since we now use them here.
> > 
> >  * Simplify sve_reg_region(), and give up on the attempt to make
> >    kreg_region a general thing: nothing else will use it for now,
> >    anyway, so let's keep it as simple as possible.
> > 
> >  * Drop support for multiple slices per register.  This functionality
> >    can be added back in later if needed, without ABI breaks.
> > 
> >  * Pull vcpu_sve_state_size() into kvm_host.h, from "KVM: arm64/sve:
> >    Allow userspace to enable SVE for vcpus".  This is needed for use
> >    with array_index_nospec() to determine the applicable buffer bounds.
> >    To avoid circular header deependency issues, the function is also
> >    converted into a macro, but is otherwise equivalent to the original
> >    version.
> > 
> >  * Guard sve_state base offset in kernel memory with
> >    array_index_nospec(), since it is generated from user data that can
> >    put it out of range.
> > 
> >    (sve_state will get allocated with the corresponding size later in
> >    the series.  For now, this code is dormant since no means is
> >    provided for userspace to create SVE-enabled vcpus yet.)
> > ---
> >  arch/arm64/include/asm/kvm_host.h |  14 ++++
> >  arch/arm64/include/uapi/asm/kvm.h |  17 +++++
> >  arch/arm64/kvm/guest.c            | 138 ++++++++++++++++++++++++++++++++++----
> >  3 files changed, 157 insertions(+), 12 deletions(-)
> > 
> 
> [...]
> 
> > diff --git a/arch/arm64/kvm/guest.c b/arch/arm64/kvm/guest.c
> > index f491456..8cfa889 100644
> > --- a/arch/arm64/kvm/guest.c
> > +++ b/arch/arm64/kvm/guest.c
> 
> [...]
> 
> > @@ -211,6 +217,114 @@ static int set_core_reg(struct kvm_vcpu *vcpu, const struct kvm_one_reg *reg)
> >  	return err;
> >  }
> >  
> > +#define SVE_REG_SLICE_SHIFT	0
> > +#define SVE_REG_SLICE_BITS	5
> > +#define SVE_REG_ID_SHIFT	(SVE_REG_SLICE_SHIFT + SVE_REG_SLICE_BITS)
> > +#define SVE_REG_ID_BITS		5
> > +
> > +#define SVE_REG_SLICE_MASK					\
> > +	GENMASK(SVE_REG_SLICE_SHIFT + SVE_REG_SLICE_BITS - 1,	\
> > +		SVE_REG_SLICE_SHIFT)
> > +#define SVE_REG_ID_MASK							\
> > +	GENMASK(SVE_REG_ID_SHIFT + SVE_REG_ID_BITS - 1, SVE_REG_ID_SHIFT)
> > +
> > +#define SVE_NUM_SLICES (1 << SVE_REG_SLICE_BITS)
> > +
> > +#define KVM_SVE_ZREG_SIZE KVM_REG_SIZE(KVM_REG_ARM64_SVE_ZREG(0, 0))
> > +#define KVM_SVE_PREG_SIZE KVM_REG_SIZE(KVM_REG_ARM64_SVE_PREG(0, 0))
> > +
> > +struct sve_state_region {
> 
> This sve_state_region feels a bit too generic too me.
> 
> So far it is only used to access a single (slice of a) register at a
> time. Is there a plan to use it for more?

It's there as a way to factor out security-sensitive range computations
that we otherwise have to do twice -- I'd rather have the (potential)
bugs in one place.  sve_state is particularly awkward because it is
heterogeneous, with variably sized members for which no C declaration
is avaiable (or possible).

Previously it was used in four places, because I tried to emulate the
VFP get/set functions for SVE vcpus.  Now that functionality has been
dropped I agree that this function looks like a bit like overkill.  But
I didn't come up with a good way to split it without duplicating an
undesirable amount of fiddly logic.

"sve_state" in the name comes from the naming of the kernel field(s)
that this computes ranges on: vcpu->arch.sve_state (and thread->
sve_state, which we don't operate on here, but which has the same
format).

So, this struct describes a slice of "sve_state", hence the name.  But
you're right, it is only ever supposed to span a single SVE register
within there.

> Otherwise I'd suggest at least naming it something like sve_reg_region,
> sve_reg_mem_region or sve_reg_mem_desc.

It used to be called struct kreg_region.  The name "sve_state_region"
was an attempt to make it look less generic, which doesn't appear to
have worked too well.

Maybe "sve_state_reg_region" would narrow the apparent scope of this a
little further.

Thoughts?

I'll take a look, and at least add a comment explaining what this
struct is supposed to represent.

> 
> 
> > +	unsigned int koffset;	/* offset into sve_state in kernel memory */
> > +	unsigned int klen;	/* length in kernel memory */
> > +	unsigned int upad;	/* extra trailing padding in user memory */
> > +};
> > +
> > +/* Get sanitised bounds for user/kernel SVE register copy */
> > +static int sve_reg_region(struct sve_state_region *region,
> 
> I feel that sve_reg_to_region or sve_reg_get_region would be a clearer name.

..._reg_to_region() seems a good name.  I'll pick that up, modulo other
changes.

Cheers
---Dave

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

* Re: [PATCH v5 18/26] KVM: arm64/sve: Add SVE support to register access ioctl interface
@ 2019-02-26 12:13       ` Dave Martin
  0 siblings, 0 replies; 205+ messages in thread
From: Dave Martin @ 2019-02-26 12:13 UTC (permalink / raw)
  To: Julien Thierry
  Cc: Okamoto Takayuki, Christoffer Dall, Ard Biesheuvel, Marc Zyngier,
	Catalin Marinas, Will Deacon, Zhang Lei, kvmarm,
	linux-arm-kernel

On Thu, Feb 21, 2019 at 03:23:37PM +0000, Julien Thierry wrote:
> Hi Dave,
> 
> On 18/02/2019 19:52, Dave Martin wrote:
> > This patch adds the following registers for access via the
> > KVM_{GET,SET}_ONE_REG interface:
> > 
> >  * KVM_REG_ARM64_SVE_ZREG(n, i) (n = 0..31) (in 2048-bit slices)
> >  * KVM_REG_ARM64_SVE_PREG(n, i) (n = 0..15) (in 256-bit slices)
> >  * KVM_REG_ARM64_SVE_FFR(i) (in 256-bit slices)
> > 
> > In order to adapt gracefully to future architectural extensions,
> > the registers are logically divided up into slices as noted above:
> > the i parameter denotes the slice index.
> > 
> > This allows us to reserve space in the ABI for future expansion of
> > these registers.  However, as of today the architecture does not
> > permit registers to be larger than a single slice, so no code is
> > needed in the kernel to expose additional slices, for now.  The
> > code can be extended later as needed to expose them up to a maximum
> > of 32 slices (as carved out in the architecture itself) if they
> > really exist someday.
> > 
> > The registers are only visible for vcpus that have SVE enabled.
> > They are not enumerated by KVM_GET_REG_LIST on vcpus that do not
> > have SVE.
> > 
> > Accesses to the FPSIMD registers via KVM_REG_ARM_CORE is not
> > allowed for SVE-enabled vcpus: SVE-aware userspace can use the
> > KVM_REG_ARM64_SVE_ZREG() interface instead to access the same
> > register state.  This avoids some complex and pointless emulation
> > in the kernel to convert between the two views of these aliased
> > registers.
> > 
> > Signed-off-by: Dave Martin <Dave.Martin@arm.com>
> > 
> > ---
> > 
> > Changes since v4:
> > 
> >  * Add "BASE" #defines for the Z-reg and P-reg ranges in the KVM
> >    register ID space, to make the 0x400 magic number a little less
> >    cryptic.
> > 
> >  * Pull KVM_SVE_{Z,P}REG_SIZE defines from "KVM: arm64: Enumerate SVE
> >    register indices for KVM_GET_REG_LIST", since we now use them here.
> > 
> >  * Simplify sve_reg_region(), and give up on the attempt to make
> >    kreg_region a general thing: nothing else will use it for now,
> >    anyway, so let's keep it as simple as possible.
> > 
> >  * Drop support for multiple slices per register.  This functionality
> >    can be added back in later if needed, without ABI breaks.
> > 
> >  * Pull vcpu_sve_state_size() into kvm_host.h, from "KVM: arm64/sve:
> >    Allow userspace to enable SVE for vcpus".  This is needed for use
> >    with array_index_nospec() to determine the applicable buffer bounds.
> >    To avoid circular header deependency issues, the function is also
> >    converted into a macro, but is otherwise equivalent to the original
> >    version.
> > 
> >  * Guard sve_state base offset in kernel memory with
> >    array_index_nospec(), since it is generated from user data that can
> >    put it out of range.
> > 
> >    (sve_state will get allocated with the corresponding size later in
> >    the series.  For now, this code is dormant since no means is
> >    provided for userspace to create SVE-enabled vcpus yet.)
> > ---
> >  arch/arm64/include/asm/kvm_host.h |  14 ++++
> >  arch/arm64/include/uapi/asm/kvm.h |  17 +++++
> >  arch/arm64/kvm/guest.c            | 138 ++++++++++++++++++++++++++++++++++----
> >  3 files changed, 157 insertions(+), 12 deletions(-)
> > 
> 
> [...]
> 
> > diff --git a/arch/arm64/kvm/guest.c b/arch/arm64/kvm/guest.c
> > index f491456..8cfa889 100644
> > --- a/arch/arm64/kvm/guest.c
> > +++ b/arch/arm64/kvm/guest.c
> 
> [...]
> 
> > @@ -211,6 +217,114 @@ static int set_core_reg(struct kvm_vcpu *vcpu, const struct kvm_one_reg *reg)
> >  	return err;
> >  }
> >  
> > +#define SVE_REG_SLICE_SHIFT	0
> > +#define SVE_REG_SLICE_BITS	5
> > +#define SVE_REG_ID_SHIFT	(SVE_REG_SLICE_SHIFT + SVE_REG_SLICE_BITS)
> > +#define SVE_REG_ID_BITS		5
> > +
> > +#define SVE_REG_SLICE_MASK					\
> > +	GENMASK(SVE_REG_SLICE_SHIFT + SVE_REG_SLICE_BITS - 1,	\
> > +		SVE_REG_SLICE_SHIFT)
> > +#define SVE_REG_ID_MASK							\
> > +	GENMASK(SVE_REG_ID_SHIFT + SVE_REG_ID_BITS - 1, SVE_REG_ID_SHIFT)
> > +
> > +#define SVE_NUM_SLICES (1 << SVE_REG_SLICE_BITS)
> > +
> > +#define KVM_SVE_ZREG_SIZE KVM_REG_SIZE(KVM_REG_ARM64_SVE_ZREG(0, 0))
> > +#define KVM_SVE_PREG_SIZE KVM_REG_SIZE(KVM_REG_ARM64_SVE_PREG(0, 0))
> > +
> > +struct sve_state_region {
> 
> This sve_state_region feels a bit too generic too me.
> 
> So far it is only used to access a single (slice of a) register at a
> time. Is there a plan to use it for more?

It's there as a way to factor out security-sensitive range computations
that we otherwise have to do twice -- I'd rather have the (potential)
bugs in one place.  sve_state is particularly awkward because it is
heterogeneous, with variably sized members for which no C declaration
is avaiable (or possible).

Previously it was used in four places, because I tried to emulate the
VFP get/set functions for SVE vcpus.  Now that functionality has been
dropped I agree that this function looks like a bit like overkill.  But
I didn't come up with a good way to split it without duplicating an
undesirable amount of fiddly logic.

"sve_state" in the name comes from the naming of the kernel field(s)
that this computes ranges on: vcpu->arch.sve_state (and thread->
sve_state, which we don't operate on here, but which has the same
format).

So, this struct describes a slice of "sve_state", hence the name.  But
you're right, it is only ever supposed to span a single SVE register
within there.

> Otherwise I'd suggest at least naming it something like sve_reg_region,
> sve_reg_mem_region or sve_reg_mem_desc.

It used to be called struct kreg_region.  The name "sve_state_region"
was an attempt to make it look less generic, which doesn't appear to
have worked too well.

Maybe "sve_state_reg_region" would narrow the apparent scope of this a
little further.

Thoughts?

I'll take a look, and at least add a comment explaining what this
struct is supposed to represent.

> 
> 
> > +	unsigned int koffset;	/* offset into sve_state in kernel memory */
> > +	unsigned int klen;	/* length in kernel memory */
> > +	unsigned int upad;	/* extra trailing padding in user memory */
> > +};
> > +
> > +/* Get sanitised bounds for user/kernel SVE register copy */
> > +static int sve_reg_region(struct sve_state_region *region,
> 
> I feel that sve_reg_to_region or sve_reg_get_region would be a clearer name.

..._reg_to_region() seems a good name.  I'll pick that up, modulo other
changes.

Cheers
---Dave

_______________________________________________
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] 205+ messages in thread

* Re: [PATCH v5 22/26] KVM: arm64/sve: Add pseudo-register for the guest's vector lengths
  2019-02-21 17:48     ` Julien Thierry
@ 2019-02-26 12:13       ` Dave Martin
  -1 siblings, 0 replies; 205+ messages in thread
From: Dave Martin @ 2019-02-26 12:13 UTC (permalink / raw)
  To: Julien Thierry
  Cc: Okamoto Takayuki, Christoffer Dall, Ard Biesheuvel, Marc Zyngier,
	Catalin Marinas, Will Deacon, Zhang Lei, kvmarm,
	linux-arm-kernel

On Thu, Feb 21, 2019 at 05:48:59PM +0000, Julien Thierry wrote:
> Hi Dave,
> 
> On 18/02/2019 19:52, Dave Martin wrote:
> > This patch adds a new pseudo-register KVM_REG_ARM64_SVE_VLS to
> > allow userspace to set and query the set of vector lengths visible
> > to the guest, along with corresponding storage in struct
> > kvm_vcpu_arch.
> > 
> > In the future, multiple register slices per SVE register may be
> > visible through the ioctl interface.  Once the set of slices has
> > been determined we would not be able to allow the vector length set
> > to be changed any more, in order to avoid userspace seeing
> > inconsistent sets of registers.  For this reason, this patch adds
> > support to track vcpu finalization explicitly, and enforce proper
> > sequencing of ioctls.
> > 
> > The new pseudo-register is not exposed yet.  Subsequent patches
> > will allow SVE to be turned on for guest vcpus, making it visible.
> > 
> > Signed-off-by: Dave Martin <Dave.Martin@arm.com>
> > 
> > ---
> > 
> > Changes since v4:
> > 
> >  * Add a UAPI header comment indicating the pseudo-register status of
> >    KVM_REG_ARM64_SVE_VLS.
> > 
> >  * Get rid of the sve_vqs[] array from struct kvm_vcpu_arch.  This
> >    array is pointless, because its contents must match the host's
> >    internal sve_vq_map anyway, up to vcpu->arch.sve_max_vl.
> > 
> >    The ioctl register accessors are slow-path code, so we can decode
> >    or reconstruct sve_vqs[] on demand instead, for exchange with
> >    userspace.
> > 
> >  * For compatibility with potential future architecture extensions,
> >    enabling vector lengths above 256 bytes for the guest is explicitly
> >    disallowed now (because the code for exposing additional bits
> >    through ioctl is currently missing).  This can be addressed later
> >    if/when needed.
> > 
> > Note:
> > 
> >  * I defensively pass an array by pointer here, to help avoid
> >    accidentally breaking assumptions during future maintenance.
> > 
> >    Due to (over?)zealous constification, this causes the following
> >    sparse warning.  I think this is sparse getting confused: I am not
> >    relying on any kernel-specific semantics here, and GCC generates no
> >    warning.
> > 
> > +arch/arm64/kvm/guest.c:33: warning: incorrect type in argument 1 (different modifiers)
> > +arch/arm64/kvm/guest.c:33:    expected unsigned long long const [usertype] ( *const vqs )[8]
> > +arch/arm64/kvm/guest.c:33:    got unsigned long long [usertype] ( * )[8]
> > 
> > ---

[...]

> > diff --git a/arch/arm64/include/uapi/asm/kvm.h b/arch/arm64/include/uapi/asm/kvm.h

[...]

> > +static int get_sve_vls(struct kvm_vcpu *vcpu, const struct kvm_one_reg *reg)
> > +{
> > +	unsigned int max_vq, vq;
> > +	u64 vqs[DIV_ROUND_UP(SVE_VQ_MAX - SVE_VQ_MIN + 1, 64)];
> > +
> > +	if (WARN_ON(!sve_vl_valid(vcpu->arch.sve_max_vl)))
> > +		return -EINVAL;
> > +
> > +	memset(vqs, 0, sizeof(vqs));
> > +
> > +	max_vq = sve_vq_from_vl(vcpu->arch.sve_max_vl);
> > +	for (vq = SVE_VQ_MIN; vq <= max_vq; ++vq)
> > +		if (sve_vq_available(vq))
> > +			vqs[vq_word(vq)] |= vq_mask(vq);
> > +
> > +	BUILD_BUG_ON(sizeof(vqs) != KVM_REG_SIZE(reg->id));
> 
> reg->id is not know at build time. From my understanding of
> BUILD_BUG_ON(), things actually ends up evaluated at runtime but I'm not
> sure what happens when doing sizeof(char[1- 2*0]) at runtime.
>
> Anyway, I don't think this is intended.

There's no runtime check: BUILD_BUG_ON() will cause compilation to fail
if the required condition doesn't fall out from optimisation.

Because of the way this function is called, reg->id is always
KVM_REG_ARM64_SVE_VLS, so inlining and constant propagation will make
this check pass (and compile to nothing).

We can assume a certain amount of inlining: the kernel officially can't
be built without optimisation.  But the precise build configuration can
sometimes have an effect here -- so it may not be better to rely on this
working for this slow-path code.

I'll convert these to if (WARN_ON()) return -EIO or something, or drop
them if I can get rid of them in other refactoring.

The fact that struct kvm_one_reg lacks any "size" field is rather
unfortunate, since it provides no explicit way for userspace to tell us
the size of its buffer.

> > +	if (copy_to_user((void __user *)reg->addr, vqs, sizeof(vqs)))
> > +		return -EFAULT;
> > +
> > +	return 0;
> > +}
> > +
> > +static int set_sve_vls(struct kvm_vcpu *vcpu, const struct kvm_one_reg *reg)
> > +{
> > +	unsigned int max_vq, vq;
> > +	u64 vqs[DIV_ROUND_UP(SVE_VQ_MAX - SVE_VQ_MIN + 1, 64)];
> > +
> > +	if (kvm_arm_vcpu_finalized(vcpu))
> > +		return -EPERM; /* too late! */
> > +
> > +	if (WARN_ON(vcpu->arch.sve_state))
> > +		return -EINVAL;
> > +
> > +	BUILD_BUG_ON(sizeof(vqs) != KVM_REG_SIZE(reg->id));
> 
> Same as above.
> 
> > +	if (copy_from_user(vqs, (const void __user *)reg->addr, sizeof(vqs)))
> > +		return -EFAULT;
> > +
> > +	max_vq = 0;
> > +	for (vq = SVE_VQ_MIN; vq <= SVE_VQ_MAX; ++vq)
> > +		if (vq_present(&vqs, vq))
> > +			max_vq = vq;
> > +
> > +	/*
> > +	 * The get_sve_reg()/set_sve_reg() ioctl interface will need
> > +	 * to be extended with multiple register slice support in
> > +	 * order to support vector lengths greater than
> > +	 * SVE_VL_ARCH_MAX:
> > +	 */
> > +	if (WARN_ONCE(sve_vl_from_vq(max_vq) > SVE_VL_ARCH_MAX,
> > +		      "KVM: Requested vector length not supported yet\n"))
> > +		return -EINVAL;
> > +
> > +	for (vq = SVE_VQ_MIN; vq <= max_vq; ++vq)
> > +		if (vq_present(&vqs, vq) != sve_vq_available(vq))
> > +			return -EINVAL;
> > +
> > +	/* Can't run with no vector lengths at all: */
> > +	if (max_vq < SVE_VQ_MIN)
> > +		return -EINVAL;
> > +
> > +	vcpu->arch.sve_max_vl = sve_vl_from_vq(max_vq);
> > +
> > +	return 0;
> > +}
> > +
> >  #define SVE_REG_SLICE_SHIFT	0
> >  #define SVE_REG_SLICE_BITS	5
> >  #define SVE_REG_ID_SHIFT	(SVE_REG_SLICE_SHIFT + SVE_REG_SLICE_BITS)
> > @@ -297,9 +372,21 @@ static int sve_reg_region(struct sve_state_region *region,
> >  static int get_sve_reg(struct kvm_vcpu *vcpu, const struct kvm_one_reg *reg)
> >  {
> >  	struct sve_state_region region;
> > +	int ret;
> >  	char __user *uptr = (char __user *)reg->addr;
> >  
> > -	if (!vcpu_has_sve(vcpu) || sve_reg_region(&region, vcpu, reg))
> > +	if (!vcpu_has_sve(vcpu))
> > +		return -ENOENT;
> > +
> > +	if (reg->id == KVM_REG_ARM64_SVE_VLS)
> > +		return get_sve_vls(vcpu, reg);
> > +
> > +	/* Finalize the number of slices per SVE register: */
> > +	ret = kvm_arm_vcpu_finalize(vcpu);
> 
> Having this here feels a bit random...

I'll have another think about this.

KVM_REG_ARM64_SVE_VLS certainly has nothing to do with anything except
SVE, and putting it in the SVE coproc space allows us to demux SVE-
related stuff from everything else neatly.

The whole "coprocessor" concept is nonsense for arm64 anyway except
for the sysregs (where the reg ID encodings map directly onto the
architecture and also align with AArch32).  So, the copro number is
pretty meaningless except as a demux key for related groups of
registers, which is how I use it here.

There's also no well-defined distinction between real and fake
registers, and no natural home for miscellaneous fakes -- all existing
blocks are for specific purposes such as recording the state of emulated
firmware APIs etc.  The SVE registers as exposed here already have no
direct equivalent in the architecture either, due to the padding up to
2048 bits, and the presentation of FFR as addressable P-register etc.

> I'd suggest considering the pseudo-register outside of the SVE co-proc,
> as part of a set of registers that do not finalize a vcpu when accessed.

(Also, the dependency is not one-way:  _SVE_VLS is not independent
of finalization: quite the reverse -- it can only be written _before_
finalization.)

> All other registers (even non-sve ones) would finalize the vcpu when
> accessed from userland.

So, we could consider register to be in two classes as you suggest:

 * early registers
 * regular registers (i.e., everything else)

where early registers can only be written until the first access to a
regular register, or the first KVM_GET_REG_LIST or KVM_RUN.

This is a stricter rule than I have today: i.e., _SVE_VLS would really
need to be written before touching anything else.  But that may be a
good thing for avoiding future ABI drift.

This may be premature factoring though.  It's not clear whether many new
registers like KVM_REG_ARM64_SVE_VLS will exist, or that they would have
compatible sequencing requirements.

Thoughts?


Independently of this, I'll have a look at whether there's
a straightforward way to simplify the code flow.

Cheers
---Dave

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

* Re: [PATCH v5 22/26] KVM: arm64/sve: Add pseudo-register for the guest's vector lengths
@ 2019-02-26 12:13       ` Dave Martin
  0 siblings, 0 replies; 205+ messages in thread
From: Dave Martin @ 2019-02-26 12:13 UTC (permalink / raw)
  To: Julien Thierry
  Cc: Okamoto Takayuki, Christoffer Dall, Ard Biesheuvel, Marc Zyngier,
	Catalin Marinas, Will Deacon, Zhang Lei, kvmarm,
	linux-arm-kernel

On Thu, Feb 21, 2019 at 05:48:59PM +0000, Julien Thierry wrote:
> Hi Dave,
> 
> On 18/02/2019 19:52, Dave Martin wrote:
> > This patch adds a new pseudo-register KVM_REG_ARM64_SVE_VLS to
> > allow userspace to set and query the set of vector lengths visible
> > to the guest, along with corresponding storage in struct
> > kvm_vcpu_arch.
> > 
> > In the future, multiple register slices per SVE register may be
> > visible through the ioctl interface.  Once the set of slices has
> > been determined we would not be able to allow the vector length set
> > to be changed any more, in order to avoid userspace seeing
> > inconsistent sets of registers.  For this reason, this patch adds
> > support to track vcpu finalization explicitly, and enforce proper
> > sequencing of ioctls.
> > 
> > The new pseudo-register is not exposed yet.  Subsequent patches
> > will allow SVE to be turned on for guest vcpus, making it visible.
> > 
> > Signed-off-by: Dave Martin <Dave.Martin@arm.com>
> > 
> > ---
> > 
> > Changes since v4:
> > 
> >  * Add a UAPI header comment indicating the pseudo-register status of
> >    KVM_REG_ARM64_SVE_VLS.
> > 
> >  * Get rid of the sve_vqs[] array from struct kvm_vcpu_arch.  This
> >    array is pointless, because its contents must match the host's
> >    internal sve_vq_map anyway, up to vcpu->arch.sve_max_vl.
> > 
> >    The ioctl register accessors are slow-path code, so we can decode
> >    or reconstruct sve_vqs[] on demand instead, for exchange with
> >    userspace.
> > 
> >  * For compatibility with potential future architecture extensions,
> >    enabling vector lengths above 256 bytes for the guest is explicitly
> >    disallowed now (because the code for exposing additional bits
> >    through ioctl is currently missing).  This can be addressed later
> >    if/when needed.
> > 
> > Note:
> > 
> >  * I defensively pass an array by pointer here, to help avoid
> >    accidentally breaking assumptions during future maintenance.
> > 
> >    Due to (over?)zealous constification, this causes the following
> >    sparse warning.  I think this is sparse getting confused: I am not
> >    relying on any kernel-specific semantics here, and GCC generates no
> >    warning.
> > 
> > +arch/arm64/kvm/guest.c:33: warning: incorrect type in argument 1 (different modifiers)
> > +arch/arm64/kvm/guest.c:33:    expected unsigned long long const [usertype] ( *const vqs )[8]
> > +arch/arm64/kvm/guest.c:33:    got unsigned long long [usertype] ( * )[8]
> > 
> > ---

[...]

> > diff --git a/arch/arm64/include/uapi/asm/kvm.h b/arch/arm64/include/uapi/asm/kvm.h

[...]

> > +static int get_sve_vls(struct kvm_vcpu *vcpu, const struct kvm_one_reg *reg)
> > +{
> > +	unsigned int max_vq, vq;
> > +	u64 vqs[DIV_ROUND_UP(SVE_VQ_MAX - SVE_VQ_MIN + 1, 64)];
> > +
> > +	if (WARN_ON(!sve_vl_valid(vcpu->arch.sve_max_vl)))
> > +		return -EINVAL;
> > +
> > +	memset(vqs, 0, sizeof(vqs));
> > +
> > +	max_vq = sve_vq_from_vl(vcpu->arch.sve_max_vl);
> > +	for (vq = SVE_VQ_MIN; vq <= max_vq; ++vq)
> > +		if (sve_vq_available(vq))
> > +			vqs[vq_word(vq)] |= vq_mask(vq);
> > +
> > +	BUILD_BUG_ON(sizeof(vqs) != KVM_REG_SIZE(reg->id));
> 
> reg->id is not know at build time. From my understanding of
> BUILD_BUG_ON(), things actually ends up evaluated at runtime but I'm not
> sure what happens when doing sizeof(char[1- 2*0]) at runtime.
>
> Anyway, I don't think this is intended.

There's no runtime check: BUILD_BUG_ON() will cause compilation to fail
if the required condition doesn't fall out from optimisation.

Because of the way this function is called, reg->id is always
KVM_REG_ARM64_SVE_VLS, so inlining and constant propagation will make
this check pass (and compile to nothing).

We can assume a certain amount of inlining: the kernel officially can't
be built without optimisation.  But the precise build configuration can
sometimes have an effect here -- so it may not be better to rely on this
working for this slow-path code.

I'll convert these to if (WARN_ON()) return -EIO or something, or drop
them if I can get rid of them in other refactoring.

The fact that struct kvm_one_reg lacks any "size" field is rather
unfortunate, since it provides no explicit way for userspace to tell us
the size of its buffer.

> > +	if (copy_to_user((void __user *)reg->addr, vqs, sizeof(vqs)))
> > +		return -EFAULT;
> > +
> > +	return 0;
> > +}
> > +
> > +static int set_sve_vls(struct kvm_vcpu *vcpu, const struct kvm_one_reg *reg)
> > +{
> > +	unsigned int max_vq, vq;
> > +	u64 vqs[DIV_ROUND_UP(SVE_VQ_MAX - SVE_VQ_MIN + 1, 64)];
> > +
> > +	if (kvm_arm_vcpu_finalized(vcpu))
> > +		return -EPERM; /* too late! */
> > +
> > +	if (WARN_ON(vcpu->arch.sve_state))
> > +		return -EINVAL;
> > +
> > +	BUILD_BUG_ON(sizeof(vqs) != KVM_REG_SIZE(reg->id));
> 
> Same as above.
> 
> > +	if (copy_from_user(vqs, (const void __user *)reg->addr, sizeof(vqs)))
> > +		return -EFAULT;
> > +
> > +	max_vq = 0;
> > +	for (vq = SVE_VQ_MIN; vq <= SVE_VQ_MAX; ++vq)
> > +		if (vq_present(&vqs, vq))
> > +			max_vq = vq;
> > +
> > +	/*
> > +	 * The get_sve_reg()/set_sve_reg() ioctl interface will need
> > +	 * to be extended with multiple register slice support in
> > +	 * order to support vector lengths greater than
> > +	 * SVE_VL_ARCH_MAX:
> > +	 */
> > +	if (WARN_ONCE(sve_vl_from_vq(max_vq) > SVE_VL_ARCH_MAX,
> > +		      "KVM: Requested vector length not supported yet\n"))
> > +		return -EINVAL;
> > +
> > +	for (vq = SVE_VQ_MIN; vq <= max_vq; ++vq)
> > +		if (vq_present(&vqs, vq) != sve_vq_available(vq))
> > +			return -EINVAL;
> > +
> > +	/* Can't run with no vector lengths at all: */
> > +	if (max_vq < SVE_VQ_MIN)
> > +		return -EINVAL;
> > +
> > +	vcpu->arch.sve_max_vl = sve_vl_from_vq(max_vq);
> > +
> > +	return 0;
> > +}
> > +
> >  #define SVE_REG_SLICE_SHIFT	0
> >  #define SVE_REG_SLICE_BITS	5
> >  #define SVE_REG_ID_SHIFT	(SVE_REG_SLICE_SHIFT + SVE_REG_SLICE_BITS)
> > @@ -297,9 +372,21 @@ static int sve_reg_region(struct sve_state_region *region,
> >  static int get_sve_reg(struct kvm_vcpu *vcpu, const struct kvm_one_reg *reg)
> >  {
> >  	struct sve_state_region region;
> > +	int ret;
> >  	char __user *uptr = (char __user *)reg->addr;
> >  
> > -	if (!vcpu_has_sve(vcpu) || sve_reg_region(&region, vcpu, reg))
> > +	if (!vcpu_has_sve(vcpu))
> > +		return -ENOENT;
> > +
> > +	if (reg->id == KVM_REG_ARM64_SVE_VLS)
> > +		return get_sve_vls(vcpu, reg);
> > +
> > +	/* Finalize the number of slices per SVE register: */
> > +	ret = kvm_arm_vcpu_finalize(vcpu);
> 
> Having this here feels a bit random...

I'll have another think about this.

KVM_REG_ARM64_SVE_VLS certainly has nothing to do with anything except
SVE, and putting it in the SVE coproc space allows us to demux SVE-
related stuff from everything else neatly.

The whole "coprocessor" concept is nonsense for arm64 anyway except
for the sysregs (where the reg ID encodings map directly onto the
architecture and also align with AArch32).  So, the copro number is
pretty meaningless except as a demux key for related groups of
registers, which is how I use it here.

There's also no well-defined distinction between real and fake
registers, and no natural home for miscellaneous fakes -- all existing
blocks are for specific purposes such as recording the state of emulated
firmware APIs etc.  The SVE registers as exposed here already have no
direct equivalent in the architecture either, due to the padding up to
2048 bits, and the presentation of FFR as addressable P-register etc.

> I'd suggest considering the pseudo-register outside of the SVE co-proc,
> as part of a set of registers that do not finalize a vcpu when accessed.

(Also, the dependency is not one-way:  _SVE_VLS is not independent
of finalization: quite the reverse -- it can only be written _before_
finalization.)

> All other registers (even non-sve ones) would finalize the vcpu when
> accessed from userland.

So, we could consider register to be in two classes as you suggest:

 * early registers
 * regular registers (i.e., everything else)

where early registers can only be written until the first access to a
regular register, or the first KVM_GET_REG_LIST or KVM_RUN.

This is a stricter rule than I have today: i.e., _SVE_VLS would really
need to be written before touching anything else.  But that may be a
good thing for avoiding future ABI drift.

This may be premature factoring though.  It's not clear whether many new
registers like KVM_REG_ARM64_SVE_VLS will exist, or that they would have
compatible sequencing requirements.

Thoughts?


Independently of this, I'll have a look at whether there's
a straightforward way to simplify the code flow.

Cheers
---Dave

_______________________________________________
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] 205+ messages in thread

* Re: [PATCH v5 23/26] KVM: arm64/sve: Allow userspace to enable SVE for vcpus
  2019-02-22  9:05     ` Julien Thierry
@ 2019-02-26 12:13       ` Dave Martin
  -1 siblings, 0 replies; 205+ messages in thread
From: Dave Martin @ 2019-02-26 12:13 UTC (permalink / raw)
  To: Julien Thierry
  Cc: Okamoto Takayuki, Christoffer Dall, Ard Biesheuvel, Marc Zyngier,
	Catalin Marinas, Will Deacon, Zhang Lei, kvmarm,
	linux-arm-kernel

On Fri, Feb 22, 2019 at 09:05:16AM +0000, Julien Thierry wrote:
> Hi Dave,
> 
> On 18/02/2019 19:52, Dave Martin wrote:
> > Now that all the pieces are in place, this patch offers a new flag
> > KVM_ARM_VCPU_SVE that userspace can pass to KVM_ARM_VCPU_INIT to
> > turn on SVE for the guest, on a per-vcpu basis.
> > 
> > As part of this, support for initialisation and reset of the SVE
> > vector length set and registers is added in the appropriate places.
> > Allocation SVE registers is deferred until kvm_arm_vcpu_finalize(),
> > by which time the size of the registers is known.
> > 
> > Setting the vector lengths supported by the vcpu is considered
> > configuration of the emulated hardware rather than runtime
> > configuration, so no support is offered for changing the vector
> > lengths of an existing vcpu across reset.
> > 
> > Signed-off-by: Dave Martin <Dave.Martin@arm.com>
> > 
> > ---
> > 
> > Changes since v4:
> > 
> >  * Pull out vcpu_sve_state_size(), for use earlier in the series.
> > 
> >  * Remove unnecessary vcpu->arch.sve_vqs[], and clamp maximum guest
> >    vector length to 256 bytes for forwards compatibility.
> > 
> >    (See "KVM: arm64/sve: Add pseudo-register for the guest's vector
> >    lengths".)
> > 
> >  * Minor tidyups to make some checks less verbose.
> > ---
> >  arch/arm64/include/asm/kvm_host.h |  2 +-
> >  arch/arm64/include/uapi/asm/kvm.h |  1 +
> >  arch/arm64/kvm/reset.c            | 70 ++++++++++++++++++++++++++++++++++++++-
> >  3 files changed, 71 insertions(+), 2 deletions(-)

[...]

> > diff --git a/arch/arm64/kvm/reset.c b/arch/arm64/kvm/reset.c

[...]

> >  int kvm_arm_vcpu_finalize(struct kvm_vcpu *vcpu)
> >  {
> >  	if (likely(kvm_arm_vcpu_finalized(vcpu)))
> >  		return 0;
> >  
> > +	if (vcpu_has_sve(vcpu)) {
> > +		size_t size = vcpu_sve_state_size(vcpu);
> > +
> > +		if (!size)
> > +			return -EINVAL;
> > +
> > +		vcpu->arch.sve_state = kzalloc(size, GFP_KERNEL);
> 
> We should probably free this in kvm_arch_vcpu_free().

Hmmm, good spot!

Looks like I lost that during a previous rebase.

Cheers
---Dave

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

* Re: [PATCH v5 23/26] KVM: arm64/sve: Allow userspace to enable SVE for vcpus
@ 2019-02-26 12:13       ` Dave Martin
  0 siblings, 0 replies; 205+ messages in thread
From: Dave Martin @ 2019-02-26 12:13 UTC (permalink / raw)
  To: Julien Thierry
  Cc: Okamoto Takayuki, Christoffer Dall, Ard Biesheuvel, Marc Zyngier,
	Catalin Marinas, Will Deacon, Zhang Lei, kvmarm,
	linux-arm-kernel

On Fri, Feb 22, 2019 at 09:05:16AM +0000, Julien Thierry wrote:
> Hi Dave,
> 
> On 18/02/2019 19:52, Dave Martin wrote:
> > Now that all the pieces are in place, this patch offers a new flag
> > KVM_ARM_VCPU_SVE that userspace can pass to KVM_ARM_VCPU_INIT to
> > turn on SVE for the guest, on a per-vcpu basis.
> > 
> > As part of this, support for initialisation and reset of the SVE
> > vector length set and registers is added in the appropriate places.
> > Allocation SVE registers is deferred until kvm_arm_vcpu_finalize(),
> > by which time the size of the registers is known.
> > 
> > Setting the vector lengths supported by the vcpu is considered
> > configuration of the emulated hardware rather than runtime
> > configuration, so no support is offered for changing the vector
> > lengths of an existing vcpu across reset.
> > 
> > Signed-off-by: Dave Martin <Dave.Martin@arm.com>
> > 
> > ---
> > 
> > Changes since v4:
> > 
> >  * Pull out vcpu_sve_state_size(), for use earlier in the series.
> > 
> >  * Remove unnecessary vcpu->arch.sve_vqs[], and clamp maximum guest
> >    vector length to 256 bytes for forwards compatibility.
> > 
> >    (See "KVM: arm64/sve: Add pseudo-register for the guest's vector
> >    lengths".)
> > 
> >  * Minor tidyups to make some checks less verbose.
> > ---
> >  arch/arm64/include/asm/kvm_host.h |  2 +-
> >  arch/arm64/include/uapi/asm/kvm.h |  1 +
> >  arch/arm64/kvm/reset.c            | 70 ++++++++++++++++++++++++++++++++++++++-
> >  3 files changed, 71 insertions(+), 2 deletions(-)

[...]

> > diff --git a/arch/arm64/kvm/reset.c b/arch/arm64/kvm/reset.c

[...]

> >  int kvm_arm_vcpu_finalize(struct kvm_vcpu *vcpu)
> >  {
> >  	if (likely(kvm_arm_vcpu_finalized(vcpu)))
> >  		return 0;
> >  
> > +	if (vcpu_has_sve(vcpu)) {
> > +		size_t size = vcpu_sve_state_size(vcpu);
> > +
> > +		if (!size)
> > +			return -EINVAL;
> > +
> > +		vcpu->arch.sve_state = kzalloc(size, GFP_KERNEL);
> 
> We should probably free this in kvm_arch_vcpu_free().

Hmmm, good spot!

Looks like I lost that during a previous rebase.

Cheers
---Dave

_______________________________________________
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] 205+ messages in thread

* Re: [PATCH v5 24/26] KVM: arm64: Add a capabillity to advertise SVE support
  2019-02-22  9:10     ` Julien Thierry
@ 2019-02-26 12:14       ` Dave Martin
  -1 siblings, 0 replies; 205+ messages in thread
From: Dave Martin @ 2019-02-26 12:14 UTC (permalink / raw)
  To: Julien Thierry
  Cc: Okamoto Takayuki, Christoffer Dall, Ard Biesheuvel, Marc Zyngier,
	Catalin Marinas, Will Deacon, Zhang Lei, kvmarm,
	linux-arm-kernel

On Fri, Feb 22, 2019 at 09:10:46AM +0000, Julien Thierry wrote:
> Hi Dave,
> 
> On 18/02/2019 19:52, Dave Martin wrote:
> > To provide a uniform way to check for KVM SVE support amongst other
> > features, this patch adds a suitable capability KVM_CAP_ARM_SVE,
> > and reports it as present when SVE is available.
> > 
> > Signed-off-by: Dave Martin <Dave.Martin@arm.com>
> > ---
> >  arch/arm64/kvm/reset.c   | 8 ++++++++
> >  include/uapi/linux/kvm.h | 1 +
> >  2 files changed, 9 insertions(+)
> > 
> > diff --git a/arch/arm64/kvm/reset.c b/arch/arm64/kvm/reset.c
> > index e67cd2e..f636b34 100644
> > --- a/arch/arm64/kvm/reset.c
> > +++ b/arch/arm64/kvm/reset.c
> > @@ -35,6 +35,7 @@
> >  #include <asm/kvm_asm.h>
> >  #include <asm/kvm_coproc.h>
> >  #include <asm/kvm_mmu.h>
> > +#include <asm/virt.h>
> >  
> >  /* Maximum phys_shift supported for any VM on this host */
> >  static u32 kvm_ipa_limit;
> > @@ -93,6 +94,9 @@ int kvm_arch_vm_ioctl_check_extension(struct kvm *kvm, long ext)
> >  	case KVM_CAP_ARM_VM_IPA_SIZE:
> >  		r = kvm_ipa_limit;
> >  		break;
> > +	case KVM_CAP_ARM_SVE:
> > +		r = system_supports_sve();
> > +		break;
> >  	default:
> >  		r = 0;
> >  	}
> > @@ -105,6 +109,10 @@ static int kvm_reset_sve(struct kvm_vcpu *vcpu)
> >  	if (!system_supports_sve())
> >  		return -EINVAL;
> >  
> > +	/* Verify that KVM startup enforced this when SVE was detected: */
> > +	if (WARN_ON(!has_vhe()))
> > +		return -EINVAL;
> 
> I'm wondering, wouldn't it make more sense to check for this when
> userland tries to set KVM_ARM_VCPU_SVE?
> 
> Reviewed-by: Julien Thierry <julien.thierry@arm.com>

I have a vague memory of these being some sort of reason for this, but
looking at the code now I can't see why the check can't be moved to
kvm_reset_vcpu().

How does the following look?  The effective is no different, but the
code arrangement may be a bit less surprising this way:

int kvm_reset_vcpu(struct kvm_vcpu *vcpu)
{
[...]
        if (test_bit(KVM_ARM_VCPU_SVE, vcpu->arch.features)) {
		if (!system_supports_sve())
			return -EINVAL;

		if (WARN_ON(!has_vhe()))
			return -EINVAL;

		/* KVM statup should enforce this on SVE hardware: */
                ret = kvm_reset_sve(vcpu);
                if (ret)
                        return ret;
        }


This function is bascially the arch backend for KVM_ARM_VCPU_INIT, so I
don't see a better place to do this right now.  Adding an extra hook
just for this kind of thing feels like overkill...

Cheers
---Dave

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

* Re: [PATCH v5 24/26] KVM: arm64: Add a capabillity to advertise SVE support
@ 2019-02-26 12:14       ` Dave Martin
  0 siblings, 0 replies; 205+ messages in thread
From: Dave Martin @ 2019-02-26 12:14 UTC (permalink / raw)
  To: Julien Thierry
  Cc: Okamoto Takayuki, Christoffer Dall, Ard Biesheuvel, Marc Zyngier,
	Catalin Marinas, Will Deacon, Zhang Lei, kvmarm,
	linux-arm-kernel

On Fri, Feb 22, 2019 at 09:10:46AM +0000, Julien Thierry wrote:
> Hi Dave,
> 
> On 18/02/2019 19:52, Dave Martin wrote:
> > To provide a uniform way to check for KVM SVE support amongst other
> > features, this patch adds a suitable capability KVM_CAP_ARM_SVE,
> > and reports it as present when SVE is available.
> > 
> > Signed-off-by: Dave Martin <Dave.Martin@arm.com>
> > ---
> >  arch/arm64/kvm/reset.c   | 8 ++++++++
> >  include/uapi/linux/kvm.h | 1 +
> >  2 files changed, 9 insertions(+)
> > 
> > diff --git a/arch/arm64/kvm/reset.c b/arch/arm64/kvm/reset.c
> > index e67cd2e..f636b34 100644
> > --- a/arch/arm64/kvm/reset.c
> > +++ b/arch/arm64/kvm/reset.c
> > @@ -35,6 +35,7 @@
> >  #include <asm/kvm_asm.h>
> >  #include <asm/kvm_coproc.h>
> >  #include <asm/kvm_mmu.h>
> > +#include <asm/virt.h>
> >  
> >  /* Maximum phys_shift supported for any VM on this host */
> >  static u32 kvm_ipa_limit;
> > @@ -93,6 +94,9 @@ int kvm_arch_vm_ioctl_check_extension(struct kvm *kvm, long ext)
> >  	case KVM_CAP_ARM_VM_IPA_SIZE:
> >  		r = kvm_ipa_limit;
> >  		break;
> > +	case KVM_CAP_ARM_SVE:
> > +		r = system_supports_sve();
> > +		break;
> >  	default:
> >  		r = 0;
> >  	}
> > @@ -105,6 +109,10 @@ static int kvm_reset_sve(struct kvm_vcpu *vcpu)
> >  	if (!system_supports_sve())
> >  		return -EINVAL;
> >  
> > +	/* Verify that KVM startup enforced this when SVE was detected: */
> > +	if (WARN_ON(!has_vhe()))
> > +		return -EINVAL;
> 
> I'm wondering, wouldn't it make more sense to check for this when
> userland tries to set KVM_ARM_VCPU_SVE?
> 
> Reviewed-by: Julien Thierry <julien.thierry@arm.com>

I have a vague memory of these being some sort of reason for this, but
looking at the code now I can't see why the check can't be moved to
kvm_reset_vcpu().

How does the following look?  The effective is no different, but the
code arrangement may be a bit less surprising this way:

int kvm_reset_vcpu(struct kvm_vcpu *vcpu)
{
[...]
        if (test_bit(KVM_ARM_VCPU_SVE, vcpu->arch.features)) {
		if (!system_supports_sve())
			return -EINVAL;

		if (WARN_ON(!has_vhe()))
			return -EINVAL;

		/* KVM statup should enforce this on SVE hardware: */
                ret = kvm_reset_sve(vcpu);
                if (ret)
                        return ret;
        }


This function is bascially the arch backend for KVM_ARM_VCPU_INIT, so I
don't see a better place to do this right now.  Adding an extra hook
just for this kind of thing feels like overkill...

Cheers
---Dave

_______________________________________________
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] 205+ messages in thread

* Re: [PATCH v5 05/26] KVM: arm64: Add missing #include of <linux/bitmap.h> to kvm_host.h
  2019-02-26 12:06       ` Dave Martin
  (?)
@ 2019-02-26 12:31       ` Mark Rutland
  2019-02-26 12:33           ` Dave Martin
  -1 siblings, 1 reply; 205+ messages in thread
From: Mark Rutland @ 2019-02-26 12:31 UTC (permalink / raw)
  To: Dave Martin
  Cc: Okamoto Takayuki, Christoffer Dall, Ard Biesheuvel, Marc Zyngier,
	Catalin Marinas, Will Deacon, Zhang Lei, kvmarm,
	linux-arm-kernel

On Tue, Feb 26, 2019 at 12:06:16PM +0000, Dave Martin wrote:
> On Wed, Feb 20, 2019 at 03:23:50PM +0000, Mark Rutland wrote:
> > On Mon, Feb 18, 2019 at 07:52:18PM +0000, Dave Martin wrote:
> > > kvm_host.h uses DECLARE_BITMAP() to declare the features member of
> > > struct vcpu_arch, but the corresponding #include for this is
> > > missing.
> > > 
> > > This patch adds a suitable #include for <linux/bitmap.h>.  Although
> > > the header builds without it today, this should help to avoid
> > > future surprises.
> > > 
> > > Signed-off-by: Dave Martin <Dave.Martin@arm.com>
> > > Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
> > > ---
> > >  arch/arm64/include/asm/kvm_host.h | 1 +
> > >  1 file changed, 1 insertion(+)
> > > 
> > > diff --git a/arch/arm64/include/asm/kvm_host.h b/arch/arm64/include/asm/kvm_host.h
> > > index 7732d0b..84056a4 100644
> > > --- a/arch/arm64/include/asm/kvm_host.h
> > > +++ b/arch/arm64/include/asm/kvm_host.h
> > > @@ -22,6 +22,7 @@
> > >  #ifndef __ARM64_KVM_HOST_H__
> > >  #define __ARM64_KVM_HOST_H__
> > >  
> > > +#include <linux/bitmap.h>
> > >  #include <linux/types.h>
> > >  #include <linux/kvm_types.h>
> > >  #include <asm/cpufeature.h>
> > 
> > From a quick scan of the file, we're also missing:
> > 
> > #include <asm/barrier.h>
> 
> [...]
> 
> > #include <linux/jump_label.h>
> > #include <linux/percpu.h>
> 
> Done for those three.

Great.

> > #include <linux/thread_info.h>
> 
> Since commit e6b673b741ea ("KVM: arm64: Optimise FPSIMD handling to
> reduce guest/host thrashing", we do have <asm/thread_info.h>.
> 
> Since this header is not generic, this seems reasonable.  Is there
> something from <linux/thread_info.h> used here that I'm missing?

I think I just confused myself; <asm/thread_info.h> seems sufficient.

Thanks,
Mark.

_______________________________________________
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] 205+ messages in thread

* Re: [PATCH v5 05/26] KVM: arm64: Add missing #include of <linux/bitmap.h> to kvm_host.h
  2019-02-26 12:31       ` Mark Rutland
@ 2019-02-26 12:33           ` Dave Martin
  0 siblings, 0 replies; 205+ messages in thread
From: Dave Martin @ 2019-02-26 12:33 UTC (permalink / raw)
  To: Mark Rutland
  Cc: Okamoto Takayuki, Christoffer Dall, Ard Biesheuvel, Marc Zyngier,
	Catalin Marinas, Will Deacon, Zhang Lei, kvmarm,
	linux-arm-kernel

On Tue, Feb 26, 2019 at 12:31:45PM +0000, Mark Rutland wrote:
> On Tue, Feb 26, 2019 at 12:06:16PM +0000, Dave Martin wrote:
> > On Wed, Feb 20, 2019 at 03:23:50PM +0000, Mark Rutland wrote:

[...]

> > > #include <asm/barrier.h>
> > 
> > [...]
> > 
> > > #include <linux/jump_label.h>
> > > #include <linux/percpu.h>
> > 
> > Done for those three.
> 
> Great.
> 
> > > #include <linux/thread_info.h>
> > 
> > Since commit e6b673b741ea ("KVM: arm64: Optimise FPSIMD handling to
> > reduce guest/host thrashing", we do have <asm/thread_info.h>.
> > 
> > Since this header is not generic, this seems reasonable.  Is there
> > something from <linux/thread_info.h> used here that I'm missing?
> 
> I think I just confused myself; <asm/thread_info.h> seems sufficient.

OK, I shan't worry about that one, then.

Cheers
---Dave

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

* Re: [PATCH v5 05/26] KVM: arm64: Add missing #include of <linux/bitmap.h> to kvm_host.h
@ 2019-02-26 12:33           ` Dave Martin
  0 siblings, 0 replies; 205+ messages in thread
From: Dave Martin @ 2019-02-26 12:33 UTC (permalink / raw)
  To: Mark Rutland
  Cc: Okamoto Takayuki, Christoffer Dall, Ard Biesheuvel, Marc Zyngier,
	Catalin Marinas, Will Deacon, Zhang Lei, kvmarm,
	linux-arm-kernel

On Tue, Feb 26, 2019 at 12:31:45PM +0000, Mark Rutland wrote:
> On Tue, Feb 26, 2019 at 12:06:16PM +0000, Dave Martin wrote:
> > On Wed, Feb 20, 2019 at 03:23:50PM +0000, Mark Rutland wrote:

[...]

> > > #include <asm/barrier.h>
> > 
> > [...]
> > 
> > > #include <linux/jump_label.h>
> > > #include <linux/percpu.h>
> > 
> > Done for those three.
> 
> Great.
> 
> > > #include <linux/thread_info.h>
> > 
> > Since commit e6b673b741ea ("KVM: arm64: Optimise FPSIMD handling to
> > reduce guest/host thrashing", we do have <asm/thread_info.h>.
> > 
> > Since this header is not generic, this seems reasonable.  Is there
> > something from <linux/thread_info.h> used here that I'm missing?
> 
> I think I just confused myself; <asm/thread_info.h> seems sufficient.

OK, I shan't worry about that one, then.

Cheers
---Dave

_______________________________________________
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] 205+ messages in thread

* Re: [PATCH v5 02/26] arm64: fpsimd: Always set TIF_FOREIGN_FPSTATE on task state flush
  2019-02-26 12:06       ` Dave Martin
@ 2019-02-26 12:35         ` Julien Grall
  -1 siblings, 0 replies; 205+ messages in thread
From: Julien Grall @ 2019-02-26 12:35 UTC (permalink / raw)
  To: Dave Martin
  Cc: Okamoto Takayuki, Christoffer Dall, Ard Biesheuvel, Marc Zyngier,
	Catalin Marinas, Will Deacon, Zhang Lei, kvmarm,
	linux-arm-kernel



On 26/02/2019 12:06, Dave Martin wrote:
> On Thu, Feb 21, 2019 at 12:39:39PM +0000, Julien Grall wrote:
>> Hi Dave,
>>
>> On 18/02/2019 19:52, Dave Martin wrote:
>>> This patch updates fpsimd_flush_task_state() to mirror the new
>>> semantics of fpsimd_flush_cpu_state() introduced by commit
>>> d8ad71fa38a9 ("arm64: fpsimd: Fix TIF_FOREIGN_FPSTATE after
>>> invalidating cpu regs").  Both functions now implicitly set
>>
>> NIT: Double-space before "Both"
>>
>>> TIF_FOREIGN_FPSTATE to indicate that the task's FPSIMD state is not
>>> loaded into the cpu.
>>>
>>> As a side-effect, fpsimd_flush_task_state() now sets
>>> TIF_FOREIGN_FPSTATE even for non-running tasks.  In the case of
>>
>> NIT: Double sppace before "In".
>>
>>> non-running tasks this is not useful but also harmless, because the
>>> flag is live only while the corresponding task is running.  This
>>> function is not called from fast paths, so special-casing this for
>>> the task == current case is not really worth it.
>>>
>>> Compiler barriers previously present in restore_sve_fpsimd_context()
>>> are pulled into fpsimd_flush_task_state() so that it can be safely
>>> called with preemption enabled if necessary.
>>>
>>> Explicit calls to set TIF_FOREIGN_FPSTATE that accompany
>>> fpsimd_flush_task_state() calls and are now redundant are removed
>>> as appropriate.
>>>
>>> fpsimd_flush_task_state() is used to get exclusive access to the
>>> representation of the task's state via task_struct, for the purpose
>>> of replacing the state.  Thus, the call to this function should
>>
>> NIT: Double-space before "Thus".
>>
>>> happen before manipulating fpsimd_state or sve_state etc. in
>>> task_struct.  Anomalous cases are reordered appropriately in order
>>
>> NIT: Double-space before "Anomalous".
> 
> A habit rather than a mistake [1], and I don't propose to change it ;)

I wasn't aware of this. Thank you for the pointer! Please ignore the comments on 
it :).


Cheers,

-- 
Julien Grall

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

* Re: [PATCH v5 02/26] arm64: fpsimd: Always set TIF_FOREIGN_FPSTATE on task state flush
@ 2019-02-26 12:35         ` Julien Grall
  0 siblings, 0 replies; 205+ messages in thread
From: Julien Grall @ 2019-02-26 12:35 UTC (permalink / raw)
  To: Dave Martin
  Cc: Okamoto Takayuki, Christoffer Dall, Ard Biesheuvel, Marc Zyngier,
	Catalin Marinas, Will Deacon, Zhang Lei, kvmarm,
	linux-arm-kernel



On 26/02/2019 12:06, Dave Martin wrote:
> On Thu, Feb 21, 2019 at 12:39:39PM +0000, Julien Grall wrote:
>> Hi Dave,
>>
>> On 18/02/2019 19:52, Dave Martin wrote:
>>> This patch updates fpsimd_flush_task_state() to mirror the new
>>> semantics of fpsimd_flush_cpu_state() introduced by commit
>>> d8ad71fa38a9 ("arm64: fpsimd: Fix TIF_FOREIGN_FPSTATE after
>>> invalidating cpu regs").  Both functions now implicitly set
>>
>> NIT: Double-space before "Both"
>>
>>> TIF_FOREIGN_FPSTATE to indicate that the task's FPSIMD state is not
>>> loaded into the cpu.
>>>
>>> As a side-effect, fpsimd_flush_task_state() now sets
>>> TIF_FOREIGN_FPSTATE even for non-running tasks.  In the case of
>>
>> NIT: Double sppace before "In".
>>
>>> non-running tasks this is not useful but also harmless, because the
>>> flag is live only while the corresponding task is running.  This
>>> function is not called from fast paths, so special-casing this for
>>> the task == current case is not really worth it.
>>>
>>> Compiler barriers previously present in restore_sve_fpsimd_context()
>>> are pulled into fpsimd_flush_task_state() so that it can be safely
>>> called with preemption enabled if necessary.
>>>
>>> Explicit calls to set TIF_FOREIGN_FPSTATE that accompany
>>> fpsimd_flush_task_state() calls and are now redundant are removed
>>> as appropriate.
>>>
>>> fpsimd_flush_task_state() is used to get exclusive access to the
>>> representation of the task's state via task_struct, for the purpose
>>> of replacing the state.  Thus, the call to this function should
>>
>> NIT: Double-space before "Thus".
>>
>>> happen before manipulating fpsimd_state or sve_state etc. in
>>> task_struct.  Anomalous cases are reordered appropriately in order
>>
>> NIT: Double-space before "Anomalous".
> 
> A habit rather than a mistake [1], and I don't propose to change it ;)

I wasn't aware of this. Thank you for the pointer! Please ignore the comments on 
it :).


Cheers,

-- 
Julien Grall

_______________________________________________
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] 205+ messages in thread

* Re: [PATCH v5 05/26] KVM: arm64: Add missing #include of <linux/bitmap.h> to kvm_host.h
  2019-02-26 12:33           ` Dave Martin
@ 2019-02-26 12:40             ` Mark Rutland
  -1 siblings, 0 replies; 205+ messages in thread
From: Mark Rutland @ 2019-02-26 12:40 UTC (permalink / raw)
  To: Dave Martin
  Cc: Okamoto Takayuki, Christoffer Dall, Ard Biesheuvel, Marc Zyngier,
	Catalin Marinas, Will Deacon, Zhang Lei, kvmarm,
	linux-arm-kernel

On Tue, Feb 26, 2019 at 12:33:22PM +0000, Dave Martin wrote:
> On Tue, Feb 26, 2019 at 12:31:45PM +0000, Mark Rutland wrote:
> > On Tue, Feb 26, 2019 at 12:06:16PM +0000, Dave Martin wrote:
> > > On Wed, Feb 20, 2019 at 03:23:50PM +0000, Mark Rutland wrote:
> 
> [...]
> 
> > > > #include <asm/barrier.h>
> > > 
> > > [...]
> > > 
> > > > #include <linux/jump_label.h>
> > > > #include <linux/percpu.h>
> > > 
> > > Done for those three.
> > 
> > Great.
> > 
> > > > #include <linux/thread_info.h>
> > > 
> > > Since commit e6b673b741ea ("KVM: arm64: Optimise FPSIMD handling to
> > > reduce guest/host thrashing", we do have <asm/thread_info.h>.
> > > 
> > > Since this header is not generic, this seems reasonable.  Is there
> > > something from <linux/thread_info.h> used here that I'm missing?
> > 
> > I think I just confused myself; <asm/thread_info.h> seems sufficient.
> 
> OK, I shan't worry about that one, then.

Cool.

FWIW, feel free to add:

Acked-by: Mark Rutland <mark.rutland@arm.com>

... to that fixed-up commmit.

Thanks,
Mark.

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

* Re: [PATCH v5 05/26] KVM: arm64: Add missing #include of <linux/bitmap.h> to kvm_host.h
@ 2019-02-26 12:40             ` Mark Rutland
  0 siblings, 0 replies; 205+ messages in thread
From: Mark Rutland @ 2019-02-26 12:40 UTC (permalink / raw)
  To: Dave Martin
  Cc: Okamoto Takayuki, Christoffer Dall, Ard Biesheuvel, Marc Zyngier,
	Catalin Marinas, Will Deacon, Zhang Lei, kvmarm,
	linux-arm-kernel

On Tue, Feb 26, 2019 at 12:33:22PM +0000, Dave Martin wrote:
> On Tue, Feb 26, 2019 at 12:31:45PM +0000, Mark Rutland wrote:
> > On Tue, Feb 26, 2019 at 12:06:16PM +0000, Dave Martin wrote:
> > > On Wed, Feb 20, 2019 at 03:23:50PM +0000, Mark Rutland wrote:
> 
> [...]
> 
> > > > #include <asm/barrier.h>
> > > 
> > > [...]
> > > 
> > > > #include <linux/jump_label.h>
> > > > #include <linux/percpu.h>
> > > 
> > > Done for those three.
> > 
> > Great.
> > 
> > > > #include <linux/thread_info.h>
> > > 
> > > Since commit e6b673b741ea ("KVM: arm64: Optimise FPSIMD handling to
> > > reduce guest/host thrashing", we do have <asm/thread_info.h>.
> > > 
> > > Since this header is not generic, this seems reasonable.  Is there
> > > something from <linux/thread_info.h> used here that I'm missing?
> > 
> > I think I just confused myself; <asm/thread_info.h> seems sufficient.
> 
> OK, I shan't worry about that one, then.

Cool.

FWIW, feel free to add:

Acked-by: Mark Rutland <mark.rutland@arm.com>

... to that fixed-up commmit.

Thanks,
Mark.

_______________________________________________
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] 205+ messages in thread

* Re: [PATCH v5 06/26] arm64/sve: Check SVE virtualisability
  2019-02-26 12:06       ` Dave Martin
@ 2019-02-26 15:43         ` Julien Grall
  -1 siblings, 0 replies; 205+ messages in thread
From: Julien Grall @ 2019-02-26 15:43 UTC (permalink / raw)
  To: Dave Martin
  Cc: Okamoto Takayuki, Christoffer Dall, Ard Biesheuvel, Marc Zyngier,
	Catalin Marinas, Will Deacon, Zhang Lei, kvmarm,
	linux-arm-kernel

Hi Dave,

On 26/02/2019 12:06, Dave Martin wrote:
> On Thu, Feb 21, 2019 at 01:36:26PM +0000, Julien Grall wrote:
>> Hi Dave,
>>
>> On 18/02/2019 19:52, Dave Martin wrote:
>>> +	/*
>>> +	 * Mismatches above sve_max_virtualisable_vl are fine, since
>>> +	 * no guest is allowed to configure ZCR_EL2.LEN to exceed this:
>>> +	 */
>>> +	if (sve_vl_from_vq(bit_to_vq(b)) <= sve_max_virtualisable_vl) {
>>> +		pr_warn("SVE: cpu%d: Unsupported vector length(s) present\n",
>>> +			smp_processor_id());
>>
>> Would it be worth to print the unsupported vector length?
> 
> Possibly not, but admittedly the intent is a bit unclear in this patch.
> 
> See my reply to Julien Thierry (and respond on that subthread if you
> have comments, so that we don't end up with two subthreads discussing
> the same thing...)

I will have a look at the thread.

Cheers,

-- 
Julien Grall

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

* Re: [PATCH v5 06/26] arm64/sve: Check SVE virtualisability
@ 2019-02-26 15:43         ` Julien Grall
  0 siblings, 0 replies; 205+ messages in thread
From: Julien Grall @ 2019-02-26 15:43 UTC (permalink / raw)
  To: Dave Martin
  Cc: Okamoto Takayuki, Christoffer Dall, Ard Biesheuvel, Marc Zyngier,
	Catalin Marinas, Will Deacon, Zhang Lei, kvmarm,
	linux-arm-kernel

Hi Dave,

On 26/02/2019 12:06, Dave Martin wrote:
> On Thu, Feb 21, 2019 at 01:36:26PM +0000, Julien Grall wrote:
>> Hi Dave,
>>
>> On 18/02/2019 19:52, Dave Martin wrote:
>>> +	/*
>>> +	 * Mismatches above sve_max_virtualisable_vl are fine, since
>>> +	 * no guest is allowed to configure ZCR_EL2.LEN to exceed this:
>>> +	 */
>>> +	if (sve_vl_from_vq(bit_to_vq(b)) <= sve_max_virtualisable_vl) {
>>> +		pr_warn("SVE: cpu%d: Unsupported vector length(s) present\n",
>>> +			smp_processor_id());
>>
>> Would it be worth to print the unsupported vector length?
> 
> Possibly not, but admittedly the intent is a bit unclear in this patch.
> 
> See my reply to Julien Thierry (and respond on that subthread if you
> have comments, so that we don't end up with two subthreads discussing
> the same thing...)

I will have a look at the thread.

Cheers,

-- 
Julien Grall

_______________________________________________
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] 205+ messages in thread

* Re: [PATCH v5 08/26] arm64/sve: Enable SVE state tracking for non-task contexts
  2019-02-26 12:07       ` Dave Martin
@ 2019-02-26 15:49         ` Julien Grall
  -1 siblings, 0 replies; 205+ messages in thread
From: Julien Grall @ 2019-02-26 15:49 UTC (permalink / raw)
  To: Dave Martin
  Cc: Okamoto Takayuki, Christoffer Dall, Ard Biesheuvel, Marc Zyngier,
	Catalin Marinas, Will Deacon, Zhang Lei, kvmarm,
	linux-arm-kernel

Hi Dave,

On 26/02/2019 12:07, Dave Martin wrote:
> On Fri, Feb 22, 2019 at 03:26:51PM +0000, Julien Grall wrote:
>> Hi Dave,
>>
>> On 18/02/2019 19:52, Dave Martin wrote:
>>> The current FPSIMD/SVE context handling support for non-task (i.e.,
>>> KVM vcpu) contexts does not take SVE into account.  This means that
>>
>> NIT: Double-space before "This".
> 
> See patch 2...
> 
> [...]
> 
> Does the code look reasonable to you?  This interacts with FPSIMD/SVE
> context switch in the host, so it would be good to have your view on it.

I wanted to look at the rest before giving my reviewed-by tag.
FWIW, this patch looks reasonable to me.

Cheers,

-- 
Julien Grall

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

* Re: [PATCH v5 08/26] arm64/sve: Enable SVE state tracking for non-task contexts
@ 2019-02-26 15:49         ` Julien Grall
  0 siblings, 0 replies; 205+ messages in thread
From: Julien Grall @ 2019-02-26 15:49 UTC (permalink / raw)
  To: Dave Martin
  Cc: Okamoto Takayuki, Christoffer Dall, Ard Biesheuvel, Marc Zyngier,
	Catalin Marinas, Will Deacon, Zhang Lei, kvmarm,
	linux-arm-kernel

Hi Dave,

On 26/02/2019 12:07, Dave Martin wrote:
> On Fri, Feb 22, 2019 at 03:26:51PM +0000, Julien Grall wrote:
>> Hi Dave,
>>
>> On 18/02/2019 19:52, Dave Martin wrote:
>>> The current FPSIMD/SVE context handling support for non-task (i.e.,
>>> KVM vcpu) contexts does not take SVE into account.  This means that
>>
>> NIT: Double-space before "This".
> 
> See patch 2...
> 
> [...]
> 
> Does the code look reasonable to you?  This interacts with FPSIMD/SVE
> context switch in the host, so it would be good to have your view on it.

I wanted to look at the rest before giving my reviewed-by tag.
FWIW, this patch looks reasonable to me.

Cheers,

-- 
Julien Grall

_______________________________________________
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] 205+ messages in thread

* Re: [PATCH v5 08/26] arm64/sve: Enable SVE state tracking for non-task contexts
  2019-02-26 15:49         ` Julien Grall
@ 2019-02-26 15:58           ` Dave Martin
  -1 siblings, 0 replies; 205+ messages in thread
From: Dave Martin @ 2019-02-26 15:58 UTC (permalink / raw)
  To: Julien Grall
  Cc: Okamoto Takayuki, Christoffer Dall, Ard Biesheuvel, Marc Zyngier,
	Catalin Marinas, Will Deacon, Zhang Lei, kvmarm,
	linux-arm-kernel

On Tue, Feb 26, 2019 at 03:49:00PM +0000, Julien Grall wrote:
> Hi Dave,
> 
> On 26/02/2019 12:07, Dave Martin wrote:
> >On Fri, Feb 22, 2019 at 03:26:51PM +0000, Julien Grall wrote:
> >>Hi Dave,
> >>
> >>On 18/02/2019 19:52, Dave Martin wrote:
> >>>The current FPSIMD/SVE context handling support for non-task (i.e.,
> >>>KVM vcpu) contexts does not take SVE into account.  This means that
> >>
> >>NIT: Double-space before "This".
> >
> >See patch 2...
> >
> >[...]
> >
> >Does the code look reasonable to you?  This interacts with FPSIMD/SVE
> >context switch in the host, so it would be good to have your view on it.
> 
> I wanted to look at the rest before giving my reviewed-by tag.
> FWIW, this patch looks reasonable to me.

OK, does that amount to a Reviewed-by, or do you have other comments?

Cheers
---Dave

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

* Re: [PATCH v5 08/26] arm64/sve: Enable SVE state tracking for non-task contexts
@ 2019-02-26 15:58           ` Dave Martin
  0 siblings, 0 replies; 205+ messages in thread
From: Dave Martin @ 2019-02-26 15:58 UTC (permalink / raw)
  To: Julien Grall
  Cc: Okamoto Takayuki, Christoffer Dall, Ard Biesheuvel, Marc Zyngier,
	Catalin Marinas, Will Deacon, Zhang Lei, kvmarm,
	linux-arm-kernel

On Tue, Feb 26, 2019 at 03:49:00PM +0000, Julien Grall wrote:
> Hi Dave,
> 
> On 26/02/2019 12:07, Dave Martin wrote:
> >On Fri, Feb 22, 2019 at 03:26:51PM +0000, Julien Grall wrote:
> >>Hi Dave,
> >>
> >>On 18/02/2019 19:52, Dave Martin wrote:
> >>>The current FPSIMD/SVE context handling support for non-task (i.e.,
> >>>KVM vcpu) contexts does not take SVE into account.  This means that
> >>
> >>NIT: Double-space before "This".
> >
> >See patch 2...
> >
> >[...]
> >
> >Does the code look reasonable to you?  This interacts with FPSIMD/SVE
> >context switch in the host, so it would be good to have your view on it.
> 
> I wanted to look at the rest before giving my reviewed-by tag.
> FWIW, this patch looks reasonable to me.

OK, does that amount to a Reviewed-by, or do you have other comments?

Cheers
---Dave

_______________________________________________
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] 205+ messages in thread

* Re: [PATCH v5 08/26] arm64/sve: Enable SVE state tracking for non-task contexts
  2019-02-26 15:58           ` Dave Martin
@ 2019-02-26 15:59             ` Julien Grall
  -1 siblings, 0 replies; 205+ messages in thread
From: Julien Grall @ 2019-02-26 15:59 UTC (permalink / raw)
  To: Dave Martin
  Cc: Okamoto Takayuki, Christoffer Dall, Ard Biesheuvel, Marc Zyngier,
	Catalin Marinas, Will Deacon, Zhang Lei, kvmarm,
	linux-arm-kernel

Hi Dave,

On 26/02/2019 15:58, Dave Martin wrote:
> On Tue, Feb 26, 2019 at 03:49:00PM +0000, Julien Grall wrote:
>> Hi Dave,
>>
>> On 26/02/2019 12:07, Dave Martin wrote:
>>> On Fri, Feb 22, 2019 at 03:26:51PM +0000, Julien Grall wrote:
>>>> Hi Dave,
>>>>
>>>> On 18/02/2019 19:52, Dave Martin wrote:
>>>>> The current FPSIMD/SVE context handling support for non-task (i.e.,
>>>>> KVM vcpu) contexts does not take SVE into account.  This means that
>>>>
>>>> NIT: Double-space before "This".
>>>
>>> See patch 2...
>>>
>>> [...]
>>>
>>> Does the code look reasonable to you?  This interacts with FPSIMD/SVE
>>> context switch in the host, so it would be good to have your view on it.
>>
>> I wanted to look at the rest before giving my reviewed-by tag.
>> FWIW, this patch looks reasonable to me.
> 
> OK, does that amount to a Reviewed-by, or do you have other comments?

I have no further comments on this patch.

Reviewed-by: Julien Grall <julien.grall@arm.com>

Cheers,

-- 
Julien Grall

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

* Re: [PATCH v5 08/26] arm64/sve: Enable SVE state tracking for non-task contexts
@ 2019-02-26 15:59             ` Julien Grall
  0 siblings, 0 replies; 205+ messages in thread
From: Julien Grall @ 2019-02-26 15:59 UTC (permalink / raw)
  To: Dave Martin
  Cc: Okamoto Takayuki, Christoffer Dall, Ard Biesheuvel, Marc Zyngier,
	Catalin Marinas, Will Deacon, Zhang Lei, kvmarm,
	linux-arm-kernel

Hi Dave,

On 26/02/2019 15:58, Dave Martin wrote:
> On Tue, Feb 26, 2019 at 03:49:00PM +0000, Julien Grall wrote:
>> Hi Dave,
>>
>> On 26/02/2019 12:07, Dave Martin wrote:
>>> On Fri, Feb 22, 2019 at 03:26:51PM +0000, Julien Grall wrote:
>>>> Hi Dave,
>>>>
>>>> On 18/02/2019 19:52, Dave Martin wrote:
>>>>> The current FPSIMD/SVE context handling support for non-task (i.e.,
>>>>> KVM vcpu) contexts does not take SVE into account.  This means that
>>>>
>>>> NIT: Double-space before "This".
>>>
>>> See patch 2...
>>>
>>> [...]
>>>
>>> Does the code look reasonable to you?  This interacts with FPSIMD/SVE
>>> context switch in the host, so it would be good to have your view on it.
>>
>> I wanted to look at the rest before giving my reviewed-by tag.
>> FWIW, this patch looks reasonable to me.
> 
> OK, does that amount to a Reviewed-by, or do you have other comments?

I have no further comments on this patch.

Reviewed-by: Julien Grall <julien.grall@arm.com>

Cheers,

-- 
Julien Grall

_______________________________________________
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] 205+ messages in thread

* Re: [PATCH v5 08/26] arm64/sve: Enable SVE state tracking for non-task contexts
  2019-02-26 15:59             ` Julien Grall
@ 2019-02-26 16:03               ` Dave Martin
  -1 siblings, 0 replies; 205+ messages in thread
From: Dave Martin @ 2019-02-26 16:03 UTC (permalink / raw)
  To: Julien Grall
  Cc: Okamoto Takayuki, Christoffer Dall, Ard Biesheuvel, Marc Zyngier,
	Catalin Marinas, Will Deacon, Zhang Lei, kvmarm,
	linux-arm-kernel

On Tue, Feb 26, 2019 at 03:59:40PM +0000, Julien Grall wrote:
> Hi Dave,
> 
> On 26/02/2019 15:58, Dave Martin wrote:
> >On Tue, Feb 26, 2019 at 03:49:00PM +0000, Julien Grall wrote:
> >>Hi Dave,
> >>
> >>On 26/02/2019 12:07, Dave Martin wrote:

[...]

> >>>Does the code look reasonable to you?  This interacts with FPSIMD/SVE
> >>>context switch in the host, so it would be good to have your view on it.
> >>
> >>I wanted to look at the rest before giving my reviewed-by tag.
> >>FWIW, this patch looks reasonable to me.
> >
> >OK, does that amount to a Reviewed-by, or do you have other comments?
> 
> I have no further comments on this patch.
> 
> Reviewed-by: Julien Grall <julien.grall@arm.com>

Thanks
---Dave

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

* Re: [PATCH v5 08/26] arm64/sve: Enable SVE state tracking for non-task contexts
@ 2019-02-26 16:03               ` Dave Martin
  0 siblings, 0 replies; 205+ messages in thread
From: Dave Martin @ 2019-02-26 16:03 UTC (permalink / raw)
  To: Julien Grall
  Cc: Okamoto Takayuki, Christoffer Dall, Ard Biesheuvel, Marc Zyngier,
	Catalin Marinas, Will Deacon, Zhang Lei, kvmarm,
	linux-arm-kernel

On Tue, Feb 26, 2019 at 03:59:40PM +0000, Julien Grall wrote:
> Hi Dave,
> 
> On 26/02/2019 15:58, Dave Martin wrote:
> >On Tue, Feb 26, 2019 at 03:49:00PM +0000, Julien Grall wrote:
> >>Hi Dave,
> >>
> >>On 26/02/2019 12:07, Dave Martin wrote:

[...]

> >>>Does the code look reasonable to you?  This interacts with FPSIMD/SVE
> >>>context switch in the host, so it would be good to have your view on it.
> >>
> >>I wanted to look at the rest before giving my reviewed-by tag.
> >>FWIW, this patch looks reasonable to me.
> >
> >OK, does that amount to a Reviewed-by, or do you have other comments?
> 
> I have no further comments on this patch.
> 
> Reviewed-by: Julien Grall <julien.grall@arm.com>

Thanks
---Dave

_______________________________________________
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] 205+ messages in thread

* Re: [PATCH v5 13/26] KVM: arm64/sve: System register context switch and access support
  2019-02-18 19:52   ` Dave Martin
@ 2019-02-26 16:32     ` Julien Grall
  -1 siblings, 0 replies; 205+ messages in thread
From: Julien Grall @ 2019-02-26 16:32 UTC (permalink / raw)
  To: Dave Martin, kvmarm
  Cc: Okamoto Takayuki, Christoffer Dall, Ard Biesheuvel, Marc Zyngier,
	Catalin Marinas, Will Deacon, Zhang Lei, linux-arm-kernel

Hi Dave,

On 18/02/2019 19:52, Dave Martin wrote:
> @@ -1091,6 +1088,95 @@ static int reg_from_user(u64 *val, const void __user *uaddr, u64 id);
>   static int reg_to_user(void __user *uaddr, const u64 *val, u64 id);
>   static u64 sys_reg_to_index(const struct sys_reg_desc *reg);
>   
> +static unsigned int sve_restrictions(const struct kvm_vcpu *vcpu,
> +				     const struct sys_reg_desc *rd)
> +{
> +	return vcpu_has_sve(vcpu) ? 0 : REG_NO_USER | REG_NO_GUEST;
> +}
> +
> +static unsigned int sve_id_restrictions(const struct kvm_vcpu *vcpu,
> +					const struct sys_reg_desc *rd)
> +{
> +	return vcpu_has_sve(vcpu) ? 0 : REG_NO_USER;
> +}
> +
> +static int get_zcr_el1(struct kvm_vcpu *vcpu,
> +		       const struct sys_reg_desc *rd,
> +		       const struct kvm_one_reg *reg, void __user *uaddr)
> +{
> +	if (WARN_ON(!vcpu_has_sve(vcpu)))
> +		return -ENOENT;
> +
> +	return reg_to_user(uaddr, &vcpu->arch.ctxt.sys_regs[ZCR_EL1],
> +			   reg->id);
> +}
> +
> +static int set_zcr_el1(struct kvm_vcpu *vcpu,
> +		       const struct sys_reg_desc *rd,
> +		       const struct kvm_one_reg *reg, void __user *uaddr)
> +{
> +	if (WARN_ON(!vcpu_has_sve(vcpu)))
> +		return -ENOENT;
> +
> +	return reg_from_user(&vcpu->arch.ctxt.sys_regs[ZCR_EL1], uaddr,
> +			     reg->id);
> +}
> +
> +/* Generate the emulated ID_AA64ZFR0_EL1 value exposed to the guest */
> +static u64 guest_id_aa64zfr0_el1(const struct kvm_vcpu *vcpu)
> +{
> +	if (!vcpu_has_sve(vcpu))
> +		return 0;
> +
> +	return read_sanitised_ftr_reg(SYS_ID_AA64ZFR0_EL1);
> +}
> +
> +static bool access_id_aa64zfr0_el1(struct kvm_vcpu *vcpu,
> +				   struct sys_reg_params *p,
> +				   const struct sys_reg_desc *rd)
> +{
> +	if (p->is_write)
> +		return write_to_read_only(vcpu, p, rd);
> +
> +	p->regval = guest_id_aa64zfr0_el1(vcpu);
> +	return true;
> +}
> +
> +static int get_id_aa64zfr0_el1(struct kvm_vcpu *vcpu,
> +		const struct sys_reg_desc *rd,
> +		const struct kvm_one_reg *reg, void __user *uaddr)
> +{
> +	u64 val;
> +
> +	if (!vcpu_has_sve(vcpu))
> +		return -ENOENT;
> +
> +	val = guest_id_aa64zfr0_el1(vcpu);
> +	return reg_to_user(uaddr, &val, reg->id);
> +}
> +
> +static int set_id_aa64zfr0_el1(struct kvm_vcpu *vcpu,
> +		const struct sys_reg_desc *rd,
> +		const struct kvm_one_reg *reg, void __user *uaddr)
> +{
> +	const u64 id = sys_reg_to_index(rd);
> +	int err;
> +	u64 val;
> +
> +	if (!vcpu_has_sve(vcpu))
> +		return -ENOENT;
> +
> +	err = reg_from_user(&val, uaddr, id);
> +	if (err)
> +		return err;
> +
> +	/* This is what we mean by invariant: you can't change it. */
> +	if (val != guest_id_aa64zfr0_el1(vcpu))
> +		return -EINVAL;
> +
> +	return 0;
> +}

We seem to already have code for handling invariant registers as well as reading 
ID register. I guess the only reason you can't use them is because of the check 
the vcpu is using SVE.

However, AFAICT the restrictions callback would prevent you to enter the {get, 
set}_id if the vCPU does not support SVE. So the check should not be reachable.

Did I miss anything?

Cheers,

-- 
Julien Grall

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

* Re: [PATCH v5 13/26] KVM: arm64/sve: System register context switch and access support
@ 2019-02-26 16:32     ` Julien Grall
  0 siblings, 0 replies; 205+ messages in thread
From: Julien Grall @ 2019-02-26 16:32 UTC (permalink / raw)
  To: Dave Martin, kvmarm
  Cc: Peter Maydell, Okamoto Takayuki, Christoffer Dall,
	Ard Biesheuvel, Marc Zyngier, Catalin Marinas, Will Deacon,
	Zhang Lei, Alex Bennée, linux-arm-kernel

Hi Dave,

On 18/02/2019 19:52, Dave Martin wrote:
> @@ -1091,6 +1088,95 @@ static int reg_from_user(u64 *val, const void __user *uaddr, u64 id);
>   static int reg_to_user(void __user *uaddr, const u64 *val, u64 id);
>   static u64 sys_reg_to_index(const struct sys_reg_desc *reg);
>   
> +static unsigned int sve_restrictions(const struct kvm_vcpu *vcpu,
> +				     const struct sys_reg_desc *rd)
> +{
> +	return vcpu_has_sve(vcpu) ? 0 : REG_NO_USER | REG_NO_GUEST;
> +}
> +
> +static unsigned int sve_id_restrictions(const struct kvm_vcpu *vcpu,
> +					const struct sys_reg_desc *rd)
> +{
> +	return vcpu_has_sve(vcpu) ? 0 : REG_NO_USER;
> +}
> +
> +static int get_zcr_el1(struct kvm_vcpu *vcpu,
> +		       const struct sys_reg_desc *rd,
> +		       const struct kvm_one_reg *reg, void __user *uaddr)
> +{
> +	if (WARN_ON(!vcpu_has_sve(vcpu)))
> +		return -ENOENT;
> +
> +	return reg_to_user(uaddr, &vcpu->arch.ctxt.sys_regs[ZCR_EL1],
> +			   reg->id);
> +}
> +
> +static int set_zcr_el1(struct kvm_vcpu *vcpu,
> +		       const struct sys_reg_desc *rd,
> +		       const struct kvm_one_reg *reg, void __user *uaddr)
> +{
> +	if (WARN_ON(!vcpu_has_sve(vcpu)))
> +		return -ENOENT;
> +
> +	return reg_from_user(&vcpu->arch.ctxt.sys_regs[ZCR_EL1], uaddr,
> +			     reg->id);
> +}
> +
> +/* Generate the emulated ID_AA64ZFR0_EL1 value exposed to the guest */
> +static u64 guest_id_aa64zfr0_el1(const struct kvm_vcpu *vcpu)
> +{
> +	if (!vcpu_has_sve(vcpu))
> +		return 0;
> +
> +	return read_sanitised_ftr_reg(SYS_ID_AA64ZFR0_EL1);
> +}
> +
> +static bool access_id_aa64zfr0_el1(struct kvm_vcpu *vcpu,
> +				   struct sys_reg_params *p,
> +				   const struct sys_reg_desc *rd)
> +{
> +	if (p->is_write)
> +		return write_to_read_only(vcpu, p, rd);
> +
> +	p->regval = guest_id_aa64zfr0_el1(vcpu);
> +	return true;
> +}
> +
> +static int get_id_aa64zfr0_el1(struct kvm_vcpu *vcpu,
> +		const struct sys_reg_desc *rd,
> +		const struct kvm_one_reg *reg, void __user *uaddr)
> +{
> +	u64 val;
> +
> +	if (!vcpu_has_sve(vcpu))
> +		return -ENOENT;
> +
> +	val = guest_id_aa64zfr0_el1(vcpu);
> +	return reg_to_user(uaddr, &val, reg->id);
> +}
> +
> +static int set_id_aa64zfr0_el1(struct kvm_vcpu *vcpu,
> +		const struct sys_reg_desc *rd,
> +		const struct kvm_one_reg *reg, void __user *uaddr)
> +{
> +	const u64 id = sys_reg_to_index(rd);
> +	int err;
> +	u64 val;
> +
> +	if (!vcpu_has_sve(vcpu))
> +		return -ENOENT;
> +
> +	err = reg_from_user(&val, uaddr, id);
> +	if (err)
> +		return err;
> +
> +	/* This is what we mean by invariant: you can't change it. */
> +	if (val != guest_id_aa64zfr0_el1(vcpu))
> +		return -EINVAL;
> +
> +	return 0;
> +}

We seem to already have code for handling invariant registers as well as reading 
ID register. I guess the only reason you can't use them is because of the check 
the vcpu is using SVE.

However, AFAICT the restrictions callback would prevent you to enter the {get, 
set}_id if the vCPU does not support SVE. So the check should not be reachable.

Did I miss anything?

Cheers,

-- 
Julien Grall

_______________________________________________
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] 205+ messages in thread

* Re: [PATCH v5 14/26] KVM: arm64/sve: Context switch the SVE registers
  2019-02-26 12:13       ` Dave Martin
@ 2019-02-26 16:56         ` Julien Grall
  -1 siblings, 0 replies; 205+ messages in thread
From: Julien Grall @ 2019-02-26 16:56 UTC (permalink / raw)
  To: Dave Martin, Julien Thierry
  Cc: Okamoto Takayuki, Christoffer Dall, Ard Biesheuvel, Marc Zyngier,
	Catalin Marinas, Will Deacon, Zhang Lei, kvmarm,
	linux-arm-kernel

Hi Dave,

On 26/02/2019 12:13, Dave Martin wrote:
> On Wed, Feb 20, 2019 at 04:46:57PM +0000, Julien Thierry wrote:
>>
>>
>> On 18/02/2019 19:52, Dave Martin wrote:
>>> In order to give each vcpu its own view of the SVE registers, this
>>> patch adds context storage via a new sve_state pointer in struct
>>> vcpu_arch.  An additional member sve_max_vl is also added for each
>>> vcpu, to determine the maximum vector length visible to the guest
>>> and thus the value to be configured in ZCR_EL2.LEN while the is
>>
>> "While the <guest> is active"?
> 
> Hmmm, yes.  Thanks for deciphering that.  Done.
I think it would be more consistent if you use "vcpu" over "guest". After all 
ZCR_EL2.LEN is per vCPU.

Cheers,

-- 
Julien Grall

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

* Re: [PATCH v5 14/26] KVM: arm64/sve: Context switch the SVE registers
@ 2019-02-26 16:56         ` Julien Grall
  0 siblings, 0 replies; 205+ messages in thread
From: Julien Grall @ 2019-02-26 16:56 UTC (permalink / raw)
  To: Dave Martin, Julien Thierry
  Cc: Okamoto Takayuki, Christoffer Dall, Ard Biesheuvel, Marc Zyngier,
	Catalin Marinas, Will Deacon, Zhang Lei, kvmarm,
	linux-arm-kernel

Hi Dave,

On 26/02/2019 12:13, Dave Martin wrote:
> On Wed, Feb 20, 2019 at 04:46:57PM +0000, Julien Thierry wrote:
>>
>>
>> On 18/02/2019 19:52, Dave Martin wrote:
>>> In order to give each vcpu its own view of the SVE registers, this
>>> patch adds context storage via a new sve_state pointer in struct
>>> vcpu_arch.  An additional member sve_max_vl is also added for each
>>> vcpu, to determine the maximum vector length visible to the guest
>>> and thus the value to be configured in ZCR_EL2.LEN while the is
>>
>> "While the <guest> is active"?
> 
> Hmmm, yes.  Thanks for deciphering that.  Done.
I think it would be more consistent if you use "vcpu" over "guest". After all 
ZCR_EL2.LEN is per vCPU.

Cheers,

-- 
Julien Grall

_______________________________________________
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] 205+ messages in thread

* Re: [PATCH v5 13/26] KVM: arm64/sve: System register context switch and access support
  2019-02-26 16:32     ` Julien Grall
@ 2019-02-26 17:01       ` Dave Martin
  -1 siblings, 0 replies; 205+ messages in thread
From: Dave Martin @ 2019-02-26 17:01 UTC (permalink / raw)
  To: Julien Grall
  Cc: Okamoto Takayuki, Christoffer Dall, Ard Biesheuvel, Marc Zyngier,
	Catalin Marinas, Will Deacon, Zhang Lei, kvmarm,
	linux-arm-kernel

On Tue, Feb 26, 2019 at 04:32:30PM +0000, Julien Grall wrote:
> Hi Dave,
> 
> On 18/02/2019 19:52, Dave Martin wrote:
> >@@ -1091,6 +1088,95 @@ static int reg_from_user(u64 *val, const void __user *uaddr, u64 id);
> >  static int reg_to_user(void __user *uaddr, const u64 *val, u64 id);
> >  static u64 sys_reg_to_index(const struct sys_reg_desc *reg);
> >+static unsigned int sve_restrictions(const struct kvm_vcpu *vcpu,
> >+				     const struct sys_reg_desc *rd)
> >+{
> >+	return vcpu_has_sve(vcpu) ? 0 : REG_NO_USER | REG_NO_GUEST;
> >+}
> >+
> >+static unsigned int sve_id_restrictions(const struct kvm_vcpu *vcpu,
> >+					const struct sys_reg_desc *rd)
> >+{
> >+	return vcpu_has_sve(vcpu) ? 0 : REG_NO_USER;
> >+}
> >+
> >+static int get_zcr_el1(struct kvm_vcpu *vcpu,
> >+		       const struct sys_reg_desc *rd,
> >+		       const struct kvm_one_reg *reg, void __user *uaddr)
> >+{
> >+	if (WARN_ON(!vcpu_has_sve(vcpu)))
> >+		return -ENOENT;
> >+
> >+	return reg_to_user(uaddr, &vcpu->arch.ctxt.sys_regs[ZCR_EL1],
> >+			   reg->id);
> >+}
> >+
> >+static int set_zcr_el1(struct kvm_vcpu *vcpu,
> >+		       const struct sys_reg_desc *rd,
> >+		       const struct kvm_one_reg *reg, void __user *uaddr)
> >+{
> >+	if (WARN_ON(!vcpu_has_sve(vcpu)))
> >+		return -ENOENT;
> >+
> >+	return reg_from_user(&vcpu->arch.ctxt.sys_regs[ZCR_EL1], uaddr,
> >+			     reg->id);
> >+}
> >+
> >+/* Generate the emulated ID_AA64ZFR0_EL1 value exposed to the guest */
> >+static u64 guest_id_aa64zfr0_el1(const struct kvm_vcpu *vcpu)
> >+{
> >+	if (!vcpu_has_sve(vcpu))
> >+		return 0;
> >+
> >+	return read_sanitised_ftr_reg(SYS_ID_AA64ZFR0_EL1);
> >+}
> >+
> >+static bool access_id_aa64zfr0_el1(struct kvm_vcpu *vcpu,
> >+				   struct sys_reg_params *p,
> >+				   const struct sys_reg_desc *rd)
> >+{
> >+	if (p->is_write)
> >+		return write_to_read_only(vcpu, p, rd);
> >+
> >+	p->regval = guest_id_aa64zfr0_el1(vcpu);
> >+	return true;
> >+}
> >+
> >+static int get_id_aa64zfr0_el1(struct kvm_vcpu *vcpu,
> >+		const struct sys_reg_desc *rd,
> >+		const struct kvm_one_reg *reg, void __user *uaddr)
> >+{
> >+	u64 val;
> >+
> >+	if (!vcpu_has_sve(vcpu))
> >+		return -ENOENT;
> >+
> >+	val = guest_id_aa64zfr0_el1(vcpu);
> >+	return reg_to_user(uaddr, &val, reg->id);
> >+}
> >+
> >+static int set_id_aa64zfr0_el1(struct kvm_vcpu *vcpu,
> >+		const struct sys_reg_desc *rd,
> >+		const struct kvm_one_reg *reg, void __user *uaddr)
> >+{
> >+	const u64 id = sys_reg_to_index(rd);
> >+	int err;
> >+	u64 val;
> >+
> >+	if (!vcpu_has_sve(vcpu))
> >+		return -ENOENT;
> >+
> >+	err = reg_from_user(&val, uaddr, id);
> >+	if (err)
> >+		return err;
> >+
> >+	/* This is what we mean by invariant: you can't change it. */
> >+	if (val != guest_id_aa64zfr0_el1(vcpu))
> >+		return -EINVAL;
> >+
> >+	return 0;
> >+}
> 
> We seem to already have code for handling invariant registers as well as
> reading ID register. I guess the only reason you can't use them is because
> of the check the vcpu is using SVE.
> 
> However, AFAICT the restrictions callback would prevent you to enter the
> {get, set}_id if the vCPU does not support SVE. So the check should not be
> reachable.

Hmmm, those checks were inherited from before this refactoring.

You're right: the checks are now done a common place, so the checks in
the actual accessors should be redundant.

I could demote them to WARN(), but it may make sense simply to delete
them.

The access_id_aa64zfr0_el1() should still be reachable, since we don't
have REG_NO_GUEST for this.

Does that make sense?

Cheers
---Dave

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

* Re: [PATCH v5 13/26] KVM: arm64/sve: System register context switch and access support
@ 2019-02-26 17:01       ` Dave Martin
  0 siblings, 0 replies; 205+ messages in thread
From: Dave Martin @ 2019-02-26 17:01 UTC (permalink / raw)
  To: Julien Grall
  Cc: Okamoto Takayuki, Christoffer Dall, Ard Biesheuvel, Marc Zyngier,
	Catalin Marinas, Will Deacon, Zhang Lei, kvmarm,
	linux-arm-kernel

On Tue, Feb 26, 2019 at 04:32:30PM +0000, Julien Grall wrote:
> Hi Dave,
> 
> On 18/02/2019 19:52, Dave Martin wrote:
> >@@ -1091,6 +1088,95 @@ static int reg_from_user(u64 *val, const void __user *uaddr, u64 id);
> >  static int reg_to_user(void __user *uaddr, const u64 *val, u64 id);
> >  static u64 sys_reg_to_index(const struct sys_reg_desc *reg);
> >+static unsigned int sve_restrictions(const struct kvm_vcpu *vcpu,
> >+				     const struct sys_reg_desc *rd)
> >+{
> >+	return vcpu_has_sve(vcpu) ? 0 : REG_NO_USER | REG_NO_GUEST;
> >+}
> >+
> >+static unsigned int sve_id_restrictions(const struct kvm_vcpu *vcpu,
> >+					const struct sys_reg_desc *rd)
> >+{
> >+	return vcpu_has_sve(vcpu) ? 0 : REG_NO_USER;
> >+}
> >+
> >+static int get_zcr_el1(struct kvm_vcpu *vcpu,
> >+		       const struct sys_reg_desc *rd,
> >+		       const struct kvm_one_reg *reg, void __user *uaddr)
> >+{
> >+	if (WARN_ON(!vcpu_has_sve(vcpu)))
> >+		return -ENOENT;
> >+
> >+	return reg_to_user(uaddr, &vcpu->arch.ctxt.sys_regs[ZCR_EL1],
> >+			   reg->id);
> >+}
> >+
> >+static int set_zcr_el1(struct kvm_vcpu *vcpu,
> >+		       const struct sys_reg_desc *rd,
> >+		       const struct kvm_one_reg *reg, void __user *uaddr)
> >+{
> >+	if (WARN_ON(!vcpu_has_sve(vcpu)))
> >+		return -ENOENT;
> >+
> >+	return reg_from_user(&vcpu->arch.ctxt.sys_regs[ZCR_EL1], uaddr,
> >+			     reg->id);
> >+}
> >+
> >+/* Generate the emulated ID_AA64ZFR0_EL1 value exposed to the guest */
> >+static u64 guest_id_aa64zfr0_el1(const struct kvm_vcpu *vcpu)
> >+{
> >+	if (!vcpu_has_sve(vcpu))
> >+		return 0;
> >+
> >+	return read_sanitised_ftr_reg(SYS_ID_AA64ZFR0_EL1);
> >+}
> >+
> >+static bool access_id_aa64zfr0_el1(struct kvm_vcpu *vcpu,
> >+				   struct sys_reg_params *p,
> >+				   const struct sys_reg_desc *rd)
> >+{
> >+	if (p->is_write)
> >+		return write_to_read_only(vcpu, p, rd);
> >+
> >+	p->regval = guest_id_aa64zfr0_el1(vcpu);
> >+	return true;
> >+}
> >+
> >+static int get_id_aa64zfr0_el1(struct kvm_vcpu *vcpu,
> >+		const struct sys_reg_desc *rd,
> >+		const struct kvm_one_reg *reg, void __user *uaddr)
> >+{
> >+	u64 val;
> >+
> >+	if (!vcpu_has_sve(vcpu))
> >+		return -ENOENT;
> >+
> >+	val = guest_id_aa64zfr0_el1(vcpu);
> >+	return reg_to_user(uaddr, &val, reg->id);
> >+}
> >+
> >+static int set_id_aa64zfr0_el1(struct kvm_vcpu *vcpu,
> >+		const struct sys_reg_desc *rd,
> >+		const struct kvm_one_reg *reg, void __user *uaddr)
> >+{
> >+	const u64 id = sys_reg_to_index(rd);
> >+	int err;
> >+	u64 val;
> >+
> >+	if (!vcpu_has_sve(vcpu))
> >+		return -ENOENT;
> >+
> >+	err = reg_from_user(&val, uaddr, id);
> >+	if (err)
> >+		return err;
> >+
> >+	/* This is what we mean by invariant: you can't change it. */
> >+	if (val != guest_id_aa64zfr0_el1(vcpu))
> >+		return -EINVAL;
> >+
> >+	return 0;
> >+}
> 
> We seem to already have code for handling invariant registers as well as
> reading ID register. I guess the only reason you can't use them is because
> of the check the vcpu is using SVE.
> 
> However, AFAICT the restrictions callback would prevent you to enter the
> {get, set}_id if the vCPU does not support SVE. So the check should not be
> reachable.

Hmmm, those checks were inherited from before this refactoring.

You're right: the checks are now done a common place, so the checks in
the actual accessors should be redundant.

I could demote them to WARN(), but it may make sense simply to delete
them.

The access_id_aa64zfr0_el1() should still be reachable, since we don't
have REG_NO_GUEST for this.

Does that make sense?

Cheers
---Dave

_______________________________________________
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] 205+ messages in thread

* Re: [PATCH v5 13/26] KVM: arm64/sve: System register context switch and access support
  2019-02-26 17:01       ` Dave Martin
@ 2019-02-27 12:02         ` Julien Grall
  -1 siblings, 0 replies; 205+ messages in thread
From: Julien Grall @ 2019-02-27 12:02 UTC (permalink / raw)
  To: Dave Martin
  Cc: Okamoto Takayuki, Christoffer Dall, Ard Biesheuvel, Marc Zyngier,
	Catalin Marinas, Will Deacon, Zhang Lei, kvmarm,
	linux-arm-kernel

Hi Dave,

On 2/26/19 5:01 PM, Dave Martin wrote:
> On Tue, Feb 26, 2019 at 04:32:30PM +0000, Julien Grall wrote:
>> On 18/02/2019 19:52, Dave Martin wrote:
>> We seem to already have code for handling invariant registers as well as
>> reading ID register. I guess the only reason you can't use them is because
>> of the check the vcpu is using SVE.
>>
>> However, AFAICT the restrictions callback would prevent you to enter the
>> {get, set}_id if the vCPU does not support SVE. So the check should not be
>> reachable.
> 
> Hmmm, those checks were inherited from before this refactoring.
> 
> You're right: the checks are now done a common place, so the checks in
> the actual accessors should be redundant.
> 
> I could demote them to WARN(), but it may make sense simply to delete
> them.

I think removing the WARN() would be best as it would avoid to introduce 
most of the wrappers for the registers.

> 
> The access_id_aa64zfr0_el1() should still be reachable, since we don't
> have REG_NO_GUEST for this.

__access_id_reg is taking a boolean to tell whether the register is RAZ 
or not. So you probably could re-use it passing !vcpu_has_sve(vcpu).

It feels to me we would introduce a new restriction to tell whether the 
register should be RAZ. Anyway, the new restriction is probably for a 
follow-up patch.

Cheers,

-- 
Julien Grall

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

* Re: [PATCH v5 13/26] KVM: arm64/sve: System register context switch and access support
@ 2019-02-27 12:02         ` Julien Grall
  0 siblings, 0 replies; 205+ messages in thread
From: Julien Grall @ 2019-02-27 12:02 UTC (permalink / raw)
  To: Dave Martin
  Cc: Okamoto Takayuki, Christoffer Dall, Ard Biesheuvel, Marc Zyngier,
	Catalin Marinas, Will Deacon, Zhang Lei, kvmarm,
	linux-arm-kernel

Hi Dave,

On 2/26/19 5:01 PM, Dave Martin wrote:
> On Tue, Feb 26, 2019 at 04:32:30PM +0000, Julien Grall wrote:
>> On 18/02/2019 19:52, Dave Martin wrote:
>> We seem to already have code for handling invariant registers as well as
>> reading ID register. I guess the only reason you can't use them is because
>> of the check the vcpu is using SVE.
>>
>> However, AFAICT the restrictions callback would prevent you to enter the
>> {get, set}_id if the vCPU does not support SVE. So the check should not be
>> reachable.
> 
> Hmmm, those checks were inherited from before this refactoring.
> 
> You're right: the checks are now done a common place, so the checks in
> the actual accessors should be redundant.
> 
> I could demote them to WARN(), but it may make sense simply to delete
> them.

I think removing the WARN() would be best as it would avoid to introduce 
most of the wrappers for the registers.

> 
> The access_id_aa64zfr0_el1() should still be reachable, since we don't
> have REG_NO_GUEST for this.

__access_id_reg is taking a boolean to tell whether the register is RAZ 
or not. So you probably could re-use it passing !vcpu_has_sve(vcpu).

It feels to me we would introduce a new restriction to tell whether the 
register should be RAZ. Anyway, the new restriction is probably for a 
follow-up patch.

Cheers,

-- 
Julien Grall

_______________________________________________
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] 205+ messages in thread

* Re: [PATCH v5 14/26] KVM: arm64/sve: Context switch the SVE registers
  2019-02-26 16:56         ` Julien Grall
@ 2019-02-27 13:37           ` Dave Martin
  -1 siblings, 0 replies; 205+ messages in thread
From: Dave Martin @ 2019-02-27 13:37 UTC (permalink / raw)
  To: Julien Grall
  Cc: Okamoto Takayuki, Christoffer Dall, Ard Biesheuvel, Marc Zyngier,
	Catalin Marinas, Will Deacon, Zhang Lei, kvmarm,
	linux-arm-kernel

On Tue, Feb 26, 2019 at 04:56:36PM +0000, Julien Grall wrote:
> Hi Dave,
> 
> On 26/02/2019 12:13, Dave Martin wrote:
> >On Wed, Feb 20, 2019 at 04:46:57PM +0000, Julien Thierry wrote:
> >>
> >>
> >>On 18/02/2019 19:52, Dave Martin wrote:
> >>>In order to give each vcpu its own view of the SVE registers, this
> >>>patch adds context storage via a new sve_state pointer in struct
> >>>vcpu_arch.  An additional member sve_max_vl is also added for each
> >>>vcpu, to determine the maximum vector length visible to the guest
> >>>and thus the value to be configured in ZCR_EL2.LEN while the is
> >>
> >>"While the <guest> is active"?
> >
> >Hmmm, yes.  Thanks for deciphering that.  Done.
> I think it would be more consistent if you use "vcpu" over "guest". After
> all ZCR_EL2.LEN is per vCPU.

Yes, that makes sense.  Done.

Cheers
---Dave

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

* Re: [PATCH v5 14/26] KVM: arm64/sve: Context switch the SVE registers
@ 2019-02-27 13:37           ` Dave Martin
  0 siblings, 0 replies; 205+ messages in thread
From: Dave Martin @ 2019-02-27 13:37 UTC (permalink / raw)
  To: Julien Grall
  Cc: Okamoto Takayuki, Christoffer Dall, Ard Biesheuvel, Marc Zyngier,
	Catalin Marinas, Julien Thierry, Will Deacon, Zhang Lei, kvmarm,
	linux-arm-kernel

On Tue, Feb 26, 2019 at 04:56:36PM +0000, Julien Grall wrote:
> Hi Dave,
> 
> On 26/02/2019 12:13, Dave Martin wrote:
> >On Wed, Feb 20, 2019 at 04:46:57PM +0000, Julien Thierry wrote:
> >>
> >>
> >>On 18/02/2019 19:52, Dave Martin wrote:
> >>>In order to give each vcpu its own view of the SVE registers, this
> >>>patch adds context storage via a new sve_state pointer in struct
> >>>vcpu_arch.  An additional member sve_max_vl is also added for each
> >>>vcpu, to determine the maximum vector length visible to the guest
> >>>and thus the value to be configured in ZCR_EL2.LEN while the is
> >>
> >>"While the <guest> is active"?
> >
> >Hmmm, yes.  Thanks for deciphering that.  Done.
> I think it would be more consistent if you use "vcpu" over "guest". After
> all ZCR_EL2.LEN is per vCPU.

Yes, that makes sense.  Done.

Cheers
---Dave

_______________________________________________
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] 205+ messages in thread

* Re: [PATCH v5 13/26] KVM: arm64/sve: System register context switch and access support
  2019-02-27 12:02         ` Julien Grall
@ 2019-02-27 13:50           ` Dave Martin
  -1 siblings, 0 replies; 205+ messages in thread
From: Dave Martin @ 2019-02-27 13:50 UTC (permalink / raw)
  To: Julien Grall
  Cc: Okamoto Takayuki, Christoffer Dall, Ard Biesheuvel, Marc Zyngier,
	Catalin Marinas, Will Deacon, Zhang Lei, kvmarm,
	linux-arm-kernel

On Wed, Feb 27, 2019 at 12:02:46PM +0000, Julien Grall wrote:
> Hi Dave,
> 
> On 2/26/19 5:01 PM, Dave Martin wrote:
> >On Tue, Feb 26, 2019 at 04:32:30PM +0000, Julien Grall wrote:
> >>On 18/02/2019 19:52, Dave Martin wrote:
> >>We seem to already have code for handling invariant registers as well as
> >>reading ID register. I guess the only reason you can't use them is because
> >>of the check the vcpu is using SVE.
> >>
> >>However, AFAICT the restrictions callback would prevent you to enter the
> >>{get, set}_id if the vCPU does not support SVE. So the check should not be
> >>reachable.
> >
> >Hmmm, those checks were inherited from before this refactoring.
> >
> >You're right: the checks are now done a common place, so the checks in
> >the actual accessors should be redundant.
> >
> >I could demote them to WARN(), but it may make sense simply to delete
> >them.
> 
> I think removing the WARN() would be best as it would avoid to introduce
> most of the wrappers for the registers.
> 
> >
> >The access_id_aa64zfr0_el1() should still be reachable, since we don't
> >have REG_NO_GUEST for this.
> 
> __access_id_reg is taking a boolean to tell whether the register is RAZ or
> not. So you probably could re-use it passing !vcpu_has_sve(vcpu).
> 
> It feels to me we would introduce a new restriction to tell whether the
> register should be RAZ. Anyway, the new restriction is probably for a
> follow-up patch.

It's true that we should be able to handle these as regular ID regs in
the get()/set() case, when SVE is enabled for the vcpu.  I'll have a
think about how to reduce the amount of special-case code here maybe
we can indeed get of some of these accessors entitely now that access
is rejected earlier, in a more generic way.

The access() case for this register still has to be custom though; I
don't see a trivial solution for that.

Cheers
---Dave

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

* Re: [PATCH v5 13/26] KVM: arm64/sve: System register context switch and access support
@ 2019-02-27 13:50           ` Dave Martin
  0 siblings, 0 replies; 205+ messages in thread
From: Dave Martin @ 2019-02-27 13:50 UTC (permalink / raw)
  To: Julien Grall
  Cc: Okamoto Takayuki, Christoffer Dall, Ard Biesheuvel, Marc Zyngier,
	Catalin Marinas, Will Deacon, Zhang Lei, kvmarm,
	linux-arm-kernel

On Wed, Feb 27, 2019 at 12:02:46PM +0000, Julien Grall wrote:
> Hi Dave,
> 
> On 2/26/19 5:01 PM, Dave Martin wrote:
> >On Tue, Feb 26, 2019 at 04:32:30PM +0000, Julien Grall wrote:
> >>On 18/02/2019 19:52, Dave Martin wrote:
> >>We seem to already have code for handling invariant registers as well as
> >>reading ID register. I guess the only reason you can't use them is because
> >>of the check the vcpu is using SVE.
> >>
> >>However, AFAICT the restrictions callback would prevent you to enter the
> >>{get, set}_id if the vCPU does not support SVE. So the check should not be
> >>reachable.
> >
> >Hmmm, those checks were inherited from before this refactoring.
> >
> >You're right: the checks are now done a common place, so the checks in
> >the actual accessors should be redundant.
> >
> >I could demote them to WARN(), but it may make sense simply to delete
> >them.
> 
> I think removing the WARN() would be best as it would avoid to introduce
> most of the wrappers for the registers.
> 
> >
> >The access_id_aa64zfr0_el1() should still be reachable, since we don't
> >have REG_NO_GUEST for this.
> 
> __access_id_reg is taking a boolean to tell whether the register is RAZ or
> not. So you probably could re-use it passing !vcpu_has_sve(vcpu).
> 
> It feels to me we would introduce a new restriction to tell whether the
> register should be RAZ. Anyway, the new restriction is probably for a
> follow-up patch.

It's true that we should be able to handle these as regular ID regs in
the get()/set() case, when SVE is enabled for the vcpu.  I'll have a
think about how to reduce the amount of special-case code here maybe
we can indeed get of some of these accessors entitely now that access
is rejected earlier, in a more generic way.

The access() case for this register still has to be custom though; I
don't see a trivial solution for that.

Cheers
---Dave

_______________________________________________
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] 205+ messages in thread

* Re: [PATCH v5 13/26] KVM: arm64/sve: System register context switch and access support
  2019-02-27 13:50           ` Dave Martin
@ 2019-02-27 14:17             ` Julien Grall
  -1 siblings, 0 replies; 205+ messages in thread
From: Julien Grall @ 2019-02-27 14:17 UTC (permalink / raw)
  To: Dave Martin
  Cc: Okamoto Takayuki, Christoffer Dall, Ard Biesheuvel, Marc Zyngier,
	Catalin Marinas, Will Deacon, Zhang Lei, kvmarm,
	linux-arm-kernel

Hi Dave,

On 2/27/19 1:50 PM, Dave Martin wrote:
> On Wed, Feb 27, 2019 at 12:02:46PM +0000, Julien Grall wrote:
>> Hi Dave,
>>
>> On 2/26/19 5:01 PM, Dave Martin wrote:
>>> On Tue, Feb 26, 2019 at 04:32:30PM +0000, Julien Grall wrote:
>>>> On 18/02/2019 19:52, Dave Martin wrote:
>>>> We seem to already have code for handling invariant registers as well as
>>>> reading ID register. I guess the only reason you can't use them is because
>>>> of the check the vcpu is using SVE.
>>>>
>>>> However, AFAICT the restrictions callback would prevent you to enter the
>>>> {get, set}_id if the vCPU does not support SVE. So the check should not be
>>>> reachable.
>>>
>>> Hmmm, those checks were inherited from before this refactoring.
>>>
>>> You're right: the checks are now done a common place, so the checks in
>>> the actual accessors should be redundant.
>>>
>>> I could demote them to WARN(), but it may make sense simply to delete
>>> them.
>>
>> I think removing the WARN() would be best as it would avoid to introduce
>> most of the wrappers for the registers.
>>
>>>
>>> The access_id_aa64zfr0_el1() should still be reachable, since we don't
>>> have REG_NO_GUEST for this.
>>
>> __access_id_reg is taking a boolean to tell whether the register is RAZ or
>> not. So you probably could re-use it passing !vcpu_has_sve(vcpu).
>>
>> It feels to me we would introduce a new restriction to tell whether the
>> register should be RAZ. Anyway, the new restriction is probably for a
>> follow-up patch.
> 
> It's true that we should be able to handle these as regular ID regs in
> the get()/set() case, when SVE is enabled for the vcpu.  I'll have a
> think about how to reduce the amount of special-case code here maybe
> we can indeed get of some of these accessors entitely now that access
> is rejected earlier, in a more generic way.
> 
> The access() case for this register still has to be custom though; I
> don't see a trivial solution for that.

I believe you can implement access_id_aa64zfr0_el1 in one line:

return __access_id_reg(vcpu, p, r, !vcpu_has_sve(vcpu));

Another possibility is to introduce REG_GUEST_RAZ and use the 
restrictions callback to set it when the vCPU is not using SVE.

Cheers,

-- 
Julien Grall

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

* Re: [PATCH v5 13/26] KVM: arm64/sve: System register context switch and access support
@ 2019-02-27 14:17             ` Julien Grall
  0 siblings, 0 replies; 205+ messages in thread
From: Julien Grall @ 2019-02-27 14:17 UTC (permalink / raw)
  To: Dave Martin
  Cc: Okamoto Takayuki, Christoffer Dall, Ard Biesheuvel, Marc Zyngier,
	Catalin Marinas, Will Deacon, Zhang Lei, kvmarm,
	linux-arm-kernel

Hi Dave,

On 2/27/19 1:50 PM, Dave Martin wrote:
> On Wed, Feb 27, 2019 at 12:02:46PM +0000, Julien Grall wrote:
>> Hi Dave,
>>
>> On 2/26/19 5:01 PM, Dave Martin wrote:
>>> On Tue, Feb 26, 2019 at 04:32:30PM +0000, Julien Grall wrote:
>>>> On 18/02/2019 19:52, Dave Martin wrote:
>>>> We seem to already have code for handling invariant registers as well as
>>>> reading ID register. I guess the only reason you can't use them is because
>>>> of the check the vcpu is using SVE.
>>>>
>>>> However, AFAICT the restrictions callback would prevent you to enter the
>>>> {get, set}_id if the vCPU does not support SVE. So the check should not be
>>>> reachable.
>>>
>>> Hmmm, those checks were inherited from before this refactoring.
>>>
>>> You're right: the checks are now done a common place, so the checks in
>>> the actual accessors should be redundant.
>>>
>>> I could demote them to WARN(), but it may make sense simply to delete
>>> them.
>>
>> I think removing the WARN() would be best as it would avoid to introduce
>> most of the wrappers for the registers.
>>
>>>
>>> The access_id_aa64zfr0_el1() should still be reachable, since we don't
>>> have REG_NO_GUEST for this.
>>
>> __access_id_reg is taking a boolean to tell whether the register is RAZ or
>> not. So you probably could re-use it passing !vcpu_has_sve(vcpu).
>>
>> It feels to me we would introduce a new restriction to tell whether the
>> register should be RAZ. Anyway, the new restriction is probably for a
>> follow-up patch.
> 
> It's true that we should be able to handle these as regular ID regs in
> the get()/set() case, when SVE is enabled for the vcpu.  I'll have a
> think about how to reduce the amount of special-case code here maybe
> we can indeed get of some of these accessors entitely now that access
> is rejected earlier, in a more generic way.
> 
> The access() case for this register still has to be custom though; I
> don't see a trivial solution for that.

I believe you can implement access_id_aa64zfr0_el1 in one line:

return __access_id_reg(vcpu, p, r, !vcpu_has_sve(vcpu));

Another possibility is to introduce REG_GUEST_RAZ and use the 
restrictions callback to set it when the vCPU is not using SVE.

Cheers,

-- 
Julien Grall

_______________________________________________
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] 205+ messages in thread

* Re: [PATCH v5 13/26] KVM: arm64/sve: System register context switch and access support
  2019-02-27 14:17             ` Julien Grall
@ 2019-02-27 14:38               ` Dave Martin
  -1 siblings, 0 replies; 205+ messages in thread
From: Dave Martin @ 2019-02-27 14:38 UTC (permalink / raw)
  To: Julien Grall
  Cc: Okamoto Takayuki, Christoffer Dall, Ard Biesheuvel, Marc Zyngier,
	Catalin Marinas, Will Deacon, Zhang Lei, kvmarm,
	linux-arm-kernel

On Wed, Feb 27, 2019 at 02:17:06PM +0000, Julien Grall wrote:
> Hi Dave,
> 
> On 2/27/19 1:50 PM, Dave Martin wrote:
> >On Wed, Feb 27, 2019 at 12:02:46PM +0000, Julien Grall wrote:
> >>Hi Dave,
> >>
> >>On 2/26/19 5:01 PM, Dave Martin wrote:

[...]

> >>>The access_id_aa64zfr0_el1() should still be reachable, since we don't
> >>>have REG_NO_GUEST for this.
> >>
> >>__access_id_reg is taking a boolean to tell whether the register is RAZ or
> >>not. So you probably could re-use it passing !vcpu_has_sve(vcpu).
> >>
> >>It feels to me we would introduce a new restriction to tell whether the
> >>register should be RAZ. Anyway, the new restriction is probably for a
> >>follow-up patch.
> >
> >It's true that we should be able to handle these as regular ID regs in
> >the get()/set() case, when SVE is enabled for the vcpu.  I'll have a
> >think about how to reduce the amount of special-case code here maybe
> >we can indeed get of some of these accessors entitely now that access
> >is rejected earlier, in a more generic way.
> >
> >The access() case for this register still has to be custom though; I
> >don't see a trivial solution for that.
> 
> I believe you can implement access_id_aa64zfr0_el1 in one line:
> 
> return __access_id_reg(vcpu, p, r, !vcpu_has_sve(vcpu));

Could maybe do that -- I'll take a look.

> Another possibility is to introduce REG_GUEST_RAZ and use the restrictions
> callback to set it when the vCPU is not using SVE.

This is possible, though I'm reluctant to introduce this for a one-off
special case.

Depending on how many registers follow the same pattern in the future,
we could add it later on.

Cheers
---Dave

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

* Re: [PATCH v5 13/26] KVM: arm64/sve: System register context switch and access support
@ 2019-02-27 14:38               ` Dave Martin
  0 siblings, 0 replies; 205+ messages in thread
From: Dave Martin @ 2019-02-27 14:38 UTC (permalink / raw)
  To: Julien Grall
  Cc: Okamoto Takayuki, Christoffer Dall, Ard Biesheuvel, Marc Zyngier,
	Catalin Marinas, Will Deacon, Zhang Lei, kvmarm,
	linux-arm-kernel

On Wed, Feb 27, 2019 at 02:17:06PM +0000, Julien Grall wrote:
> Hi Dave,
> 
> On 2/27/19 1:50 PM, Dave Martin wrote:
> >On Wed, Feb 27, 2019 at 12:02:46PM +0000, Julien Grall wrote:
> >>Hi Dave,
> >>
> >>On 2/26/19 5:01 PM, Dave Martin wrote:

[...]

> >>>The access_id_aa64zfr0_el1() should still be reachable, since we don't
> >>>have REG_NO_GUEST for this.
> >>
> >>__access_id_reg is taking a boolean to tell whether the register is RAZ or
> >>not. So you probably could re-use it passing !vcpu_has_sve(vcpu).
> >>
> >>It feels to me we would introduce a new restriction to tell whether the
> >>register should be RAZ. Anyway, the new restriction is probably for a
> >>follow-up patch.
> >
> >It's true that we should be able to handle these as regular ID regs in
> >the get()/set() case, when SVE is enabled for the vcpu.  I'll have a
> >think about how to reduce the amount of special-case code here maybe
> >we can indeed get of some of these accessors entitely now that access
> >is rejected earlier, in a more generic way.
> >
> >The access() case for this register still has to be custom though; I
> >don't see a trivial solution for that.
> 
> I believe you can implement access_id_aa64zfr0_el1 in one line:
> 
> return __access_id_reg(vcpu, p, r, !vcpu_has_sve(vcpu));

Could maybe do that -- I'll take a look.

> Another possibility is to introduce REG_GUEST_RAZ and use the restrictions
> callback to set it when the vCPU is not using SVE.

This is possible, though I'm reluctant to introduce this for a one-off
special case.

Depending on how many registers follow the same pattern in the future,
we could add it later on.

Cheers
---Dave

_______________________________________________
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] 205+ messages in thread

* Re: [PATCH v5 06/26] arm64/sve: Check SVE virtualisability
  2019-02-26 12:06       ` Dave Martin
@ 2019-03-01 12:39         ` Julien Thierry
  -1 siblings, 0 replies; 205+ messages in thread
From: Julien Thierry @ 2019-03-01 12:39 UTC (permalink / raw)
  To: Dave Martin
  Cc: Okamoto Takayuki, Christoffer Dall, Ard Biesheuvel, Marc Zyngier,
	Catalin Marinas, Will Deacon, Zhang Lei, kvmarm,
	linux-arm-kernel



On 26/02/2019 12:06, Dave Martin wrote:
> On Wed, Feb 20, 2019 at 11:12:49AM +0000, Julien Thierry wrote:
>> Hi Dave,
>>
>> On 18/02/2019 19:52, Dave Martin wrote:
>>> Due to the way the effective SVE vector length is controlled and
>>> trapped at different exception levels, certain mismatches in the
>>> sets of vector lengths supported by different physical CPUs in the
>>> system may prevent straightforward virtualisation of SVE at parity
>>> with the host.
>>>
>>> This patch analyses the extent to which SVE can be virtualised
>>> safely without interfering with migration of vcpus between physical
>>> CPUs, and rejects late secondary CPUs that would erode the
>>> situation further.
>>>
>>> It is left up to KVM to decide what to do with this information.
>>>
>>> Signed-off-by: Dave Martin <Dave.Martin@arm.com>
>>> ---
>>>  arch/arm64/include/asm/fpsimd.h |  1 +
>>>  arch/arm64/kernel/cpufeature.c  |  2 +-
>>>  arch/arm64/kernel/fpsimd.c      | 86 ++++++++++++++++++++++++++++++++++-------
>>>  3 files changed, 73 insertions(+), 16 deletions(-)
>>>
>>> diff --git a/arch/arm64/include/asm/fpsimd.h b/arch/arm64/include/asm/fpsimd.h
>>> index dd1ad39..964adc9 100644
>>> --- a/arch/arm64/include/asm/fpsimd.h
>>> +++ b/arch/arm64/include/asm/fpsimd.h
>>> @@ -87,6 +87,7 @@ extern void sve_kernel_enable(const struct arm64_cpu_capabilities *__unused);
>>>  extern u64 read_zcr_features(void);
>>>  
>>>  extern int __ro_after_init sve_max_vl;
>>> +extern int __ro_after_init sve_max_virtualisable_vl;
>>>  
>>>  #ifdef CONFIG_ARM64_SVE
>>>  
>>> diff --git a/arch/arm64/kernel/cpufeature.c b/arch/arm64/kernel/cpufeature.c
>>> index f6d84e2..5eaacb4 100644
>>> --- a/arch/arm64/kernel/cpufeature.c
>>> +++ b/arch/arm64/kernel/cpufeature.c
>>> @@ -1825,7 +1825,7 @@ static void verify_sve_features(void)
>>>  	unsigned int len = zcr & ZCR_ELx_LEN_MASK;
>>>  
>>>  	if (len < safe_len || sve_verify_vq_map()) {
>>> -		pr_crit("CPU%d: SVE: required vector length(s) missing\n",
>>> +		pr_crit("CPU%d: SVE: vector length support mismatch\n",
>>>  			smp_processor_id());
>>>  		cpu_die_early();
>>>  	}
>>> diff --git a/arch/arm64/kernel/fpsimd.c b/arch/arm64/kernel/fpsimd.c
>>> index 62c37f0..64729e2 100644
>>> --- a/arch/arm64/kernel/fpsimd.c
>>> +++ b/arch/arm64/kernel/fpsimd.c
>>> @@ -18,6 +18,7 @@
>>>   */
>>>  
>>>  #include <linux/bitmap.h>
>>> +#include <linux/bitops.h>
>>>  #include <linux/bottom_half.h>
>>>  #include <linux/bug.h>
>>>  #include <linux/cache.h>
>>> @@ -48,6 +49,7 @@
>>>  #include <asm/sigcontext.h>
>>>  #include <asm/sysreg.h>
>>>  #include <asm/traps.h>
>>> +#include <asm/virt.h>
>>>  
>>>  #define FPEXC_IOF	(1 << 0)
>>>  #define FPEXC_DZF	(1 << 1)
>>> @@ -130,14 +132,18 @@ static int sve_default_vl = -1;
>>>  
>>>  /* Maximum supported vector length across all CPUs (initially poisoned) */
>>>  int __ro_after_init sve_max_vl = SVE_VL_MIN;
>>> +int __ro_after_init sve_max_virtualisable_vl = SVE_VL_MIN;
>>>  /* Set of available vector lengths, as vq_to_bit(vq): */
>>>  static __ro_after_init DECLARE_BITMAP(sve_vq_map, SVE_VQ_MAX);
>>> +/* Set of vector lengths present on at least one cpu: */
>>> +static __ro_after_init DECLARE_BITMAP(sve_vq_partial_map, SVE_VQ_MAX);
>>>  static void __percpu *efi_sve_state;
>>>  
>>>  #else /* ! CONFIG_ARM64_SVE */
>>>  
>>>  /* Dummy declaration for code that will be optimised out: */
>>>  extern __ro_after_init DECLARE_BITMAP(sve_vq_map, SVE_VQ_MAX);
>>> +extern __ro_after_init DECLARE_BITMAP(sve_vq_partial_map, SVE_VQ_MAX);
>>>  extern void __percpu *efi_sve_state;
>>>  
>>>  #endif /* ! CONFIG_ARM64_SVE */
>>> @@ -623,12 +629,6 @@ int sve_get_current_vl(void)
>>>  	return sve_prctl_status(0);
>>>  }
>>>  
>>> -/*
>>> - * Bitmap for temporary storage of the per-CPU set of supported vector lengths
>>> - * during secondary boot.
>>> - */
>>> -static DECLARE_BITMAP(sve_secondary_vq_map, SVE_VQ_MAX);
>>> -
>>>  static void sve_probe_vqs(DECLARE_BITMAP(map, SVE_VQ_MAX))
>>>  {
>>>  	unsigned int vq, vl;
>>> @@ -650,6 +650,7 @@ static void sve_probe_vqs(DECLARE_BITMAP(map, SVE_VQ_MAX))
>>>  void __init sve_init_vq_map(void)
>>>  {
>>>  	sve_probe_vqs(sve_vq_map);
>>> +	bitmap_copy(sve_vq_partial_map, sve_vq_map, SVE_VQ_MAX);
>>>  }
>>>  
>>>  /*
>>> @@ -658,25 +659,58 @@ void __init sve_init_vq_map(void)
>>>   */
>>>  void sve_update_vq_map(void)
>>>  {
>>> -	sve_probe_vqs(sve_secondary_vq_map);
>>> -	bitmap_and(sve_vq_map, sve_vq_map, sve_secondary_vq_map, SVE_VQ_MAX);
>>> +	DECLARE_BITMAP(tmp_map, SVE_VQ_MAX);
>>> +
>>> +	sve_probe_vqs(tmp_map);
>>> +	bitmap_and(sve_vq_map, sve_vq_map, tmp_map, SVE_VQ_MAX);
>>> +	bitmap_or(sve_vq_partial_map, sve_vq_partial_map, tmp_map, SVE_VQ_MAX);
>>>  }
>>>  
>>>  /* Check whether the current CPU supports all VQs in the committed set */
>>>  int sve_verify_vq_map(void)
>>>  {
>>> -	int ret = 0;
>>> +	DECLARE_BITMAP(tmp_map, SVE_VQ_MAX);
>>> +	unsigned long b;
>>>  
>>> -	sve_probe_vqs(sve_secondary_vq_map);
>>> -	bitmap_andnot(sve_secondary_vq_map, sve_vq_map, sve_secondary_vq_map,
>>> -		      SVE_VQ_MAX);
>>> -	if (!bitmap_empty(sve_secondary_vq_map, SVE_VQ_MAX)) {
>>> +	sve_probe_vqs(tmp_map);
>>> +
>>> +	bitmap_complement(tmp_map, tmp_map, SVE_VQ_MAX);
>>> +	if (bitmap_intersects(tmp_map, sve_vq_map, SVE_VQ_MAX)) {
>>>  		pr_warn("SVE: cpu%d: Required vector length(s) missing\n",
>>>  			smp_processor_id());
>>> -		ret = -EINVAL;
>>> +		return -EINVAL;
>>>  	}
>>>  
>>> -	return ret;
>>> +	if (!IS_ENABLED(CONFIG_KVM) || !is_hyp_mode_available())
>>> +		return 0;
>>> +
>>> +	/*
>>> +	 * For KVM, it is necessary to ensure that this CPU doesn't
>>> +	 * support any vector length that guests may have probed as
>>> +	 * unsupported.
>>> +	 */
>>> +
>>> +	/* Recover the set of supported VQs: */
>>> +	bitmap_complement(tmp_map, tmp_map, SVE_VQ_MAX);
>>> +	/* Find VQs supported that are not globally supported: */
>>> +	bitmap_andnot(tmp_map, tmp_map, sve_vq_map, SVE_VQ_MAX);
>>> +
>>> +	/* Find the lowest such VQ, if any: */
>>> +	b = find_last_bit(tmp_map, SVE_VQ_MAX);
>>> +	if (b >= SVE_VQ_MAX)
>>> +		return 0; /* no mismatches */
>>> +
>>> +	/*
>>> +	 * Mismatches above sve_max_virtualisable_vl are fine, since
>>> +	 * no guest is allowed to configure ZCR_EL2.LEN to exceed this:
>>> +	 */
>>> +	if (sve_vl_from_vq(bit_to_vq(b)) <= sve_max_virtualisable_vl) {
>>> +		pr_warn("SVE: cpu%d: Unsupported vector length(s) present\n",
>>
>> Nit: might be good to specify that the vector length is unsupported for
>> virtualisation.
>>
>> Also, since KVM is the one deciding what to do with the information,
>> should we have a warning here? But I can understand that knowing which
>> CPUs are introducing unsupported vector length, maybe using pr_devel()
>> instead of pr_warn()
> 
> These warnings are really for consumption by SoC vendors, not users:
> my aim is to flag up systems that we consider broken (or at least,
> unsuitable for running KVM).
> 
> So I prefer to make this noisy and limit the amount of "useful"
> information people might be tempted to programmatically scrape from
> dmesg.
> 
> cpufeatures uses pr_warn("SANITY CHECK: [...]") here.  Maybe I should
> stick "SANITY CHECK" in here too?  I will also try to make the commit
> message more explicit and/or add comments to make the intent of the code
> clearer.
> 
> It may also make sense to make this noise even if KVM isn't enabled
> (which is a rare case anyhow).
> 
> Thoughts?

As I explained later in the patch series, I missed the fact that this
function was for late secondary CPUs. I think things are fine like this
(just add the bit about the vector lenght not being supported for
virtualisation).

Cheers,

-- 
Julien Thierry

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

* Re: [PATCH v5 06/26] arm64/sve: Check SVE virtualisability
@ 2019-03-01 12:39         ` Julien Thierry
  0 siblings, 0 replies; 205+ messages in thread
From: Julien Thierry @ 2019-03-01 12:39 UTC (permalink / raw)
  To: Dave Martin
  Cc: Okamoto Takayuki, Christoffer Dall, Ard Biesheuvel, Marc Zyngier,
	Catalin Marinas, Will Deacon, Zhang Lei, kvmarm,
	linux-arm-kernel



On 26/02/2019 12:06, Dave Martin wrote:
> On Wed, Feb 20, 2019 at 11:12:49AM +0000, Julien Thierry wrote:
>> Hi Dave,
>>
>> On 18/02/2019 19:52, Dave Martin wrote:
>>> Due to the way the effective SVE vector length is controlled and
>>> trapped at different exception levels, certain mismatches in the
>>> sets of vector lengths supported by different physical CPUs in the
>>> system may prevent straightforward virtualisation of SVE at parity
>>> with the host.
>>>
>>> This patch analyses the extent to which SVE can be virtualised
>>> safely without interfering with migration of vcpus between physical
>>> CPUs, and rejects late secondary CPUs that would erode the
>>> situation further.
>>>
>>> It is left up to KVM to decide what to do with this information.
>>>
>>> Signed-off-by: Dave Martin <Dave.Martin@arm.com>
>>> ---
>>>  arch/arm64/include/asm/fpsimd.h |  1 +
>>>  arch/arm64/kernel/cpufeature.c  |  2 +-
>>>  arch/arm64/kernel/fpsimd.c      | 86 ++++++++++++++++++++++++++++++++++-------
>>>  3 files changed, 73 insertions(+), 16 deletions(-)
>>>
>>> diff --git a/arch/arm64/include/asm/fpsimd.h b/arch/arm64/include/asm/fpsimd.h
>>> index dd1ad39..964adc9 100644
>>> --- a/arch/arm64/include/asm/fpsimd.h
>>> +++ b/arch/arm64/include/asm/fpsimd.h
>>> @@ -87,6 +87,7 @@ extern void sve_kernel_enable(const struct arm64_cpu_capabilities *__unused);
>>>  extern u64 read_zcr_features(void);
>>>  
>>>  extern int __ro_after_init sve_max_vl;
>>> +extern int __ro_after_init sve_max_virtualisable_vl;
>>>  
>>>  #ifdef CONFIG_ARM64_SVE
>>>  
>>> diff --git a/arch/arm64/kernel/cpufeature.c b/arch/arm64/kernel/cpufeature.c
>>> index f6d84e2..5eaacb4 100644
>>> --- a/arch/arm64/kernel/cpufeature.c
>>> +++ b/arch/arm64/kernel/cpufeature.c
>>> @@ -1825,7 +1825,7 @@ static void verify_sve_features(void)
>>>  	unsigned int len = zcr & ZCR_ELx_LEN_MASK;
>>>  
>>>  	if (len < safe_len || sve_verify_vq_map()) {
>>> -		pr_crit("CPU%d: SVE: required vector length(s) missing\n",
>>> +		pr_crit("CPU%d: SVE: vector length support mismatch\n",
>>>  			smp_processor_id());
>>>  		cpu_die_early();
>>>  	}
>>> diff --git a/arch/arm64/kernel/fpsimd.c b/arch/arm64/kernel/fpsimd.c
>>> index 62c37f0..64729e2 100644
>>> --- a/arch/arm64/kernel/fpsimd.c
>>> +++ b/arch/arm64/kernel/fpsimd.c
>>> @@ -18,6 +18,7 @@
>>>   */
>>>  
>>>  #include <linux/bitmap.h>
>>> +#include <linux/bitops.h>
>>>  #include <linux/bottom_half.h>
>>>  #include <linux/bug.h>
>>>  #include <linux/cache.h>
>>> @@ -48,6 +49,7 @@
>>>  #include <asm/sigcontext.h>
>>>  #include <asm/sysreg.h>
>>>  #include <asm/traps.h>
>>> +#include <asm/virt.h>
>>>  
>>>  #define FPEXC_IOF	(1 << 0)
>>>  #define FPEXC_DZF	(1 << 1)
>>> @@ -130,14 +132,18 @@ static int sve_default_vl = -1;
>>>  
>>>  /* Maximum supported vector length across all CPUs (initially poisoned) */
>>>  int __ro_after_init sve_max_vl = SVE_VL_MIN;
>>> +int __ro_after_init sve_max_virtualisable_vl = SVE_VL_MIN;
>>>  /* Set of available vector lengths, as vq_to_bit(vq): */
>>>  static __ro_after_init DECLARE_BITMAP(sve_vq_map, SVE_VQ_MAX);
>>> +/* Set of vector lengths present on at least one cpu: */
>>> +static __ro_after_init DECLARE_BITMAP(sve_vq_partial_map, SVE_VQ_MAX);
>>>  static void __percpu *efi_sve_state;
>>>  
>>>  #else /* ! CONFIG_ARM64_SVE */
>>>  
>>>  /* Dummy declaration for code that will be optimised out: */
>>>  extern __ro_after_init DECLARE_BITMAP(sve_vq_map, SVE_VQ_MAX);
>>> +extern __ro_after_init DECLARE_BITMAP(sve_vq_partial_map, SVE_VQ_MAX);
>>>  extern void __percpu *efi_sve_state;
>>>  
>>>  #endif /* ! CONFIG_ARM64_SVE */
>>> @@ -623,12 +629,6 @@ int sve_get_current_vl(void)
>>>  	return sve_prctl_status(0);
>>>  }
>>>  
>>> -/*
>>> - * Bitmap for temporary storage of the per-CPU set of supported vector lengths
>>> - * during secondary boot.
>>> - */
>>> -static DECLARE_BITMAP(sve_secondary_vq_map, SVE_VQ_MAX);
>>> -
>>>  static void sve_probe_vqs(DECLARE_BITMAP(map, SVE_VQ_MAX))
>>>  {
>>>  	unsigned int vq, vl;
>>> @@ -650,6 +650,7 @@ static void sve_probe_vqs(DECLARE_BITMAP(map, SVE_VQ_MAX))
>>>  void __init sve_init_vq_map(void)
>>>  {
>>>  	sve_probe_vqs(sve_vq_map);
>>> +	bitmap_copy(sve_vq_partial_map, sve_vq_map, SVE_VQ_MAX);
>>>  }
>>>  
>>>  /*
>>> @@ -658,25 +659,58 @@ void __init sve_init_vq_map(void)
>>>   */
>>>  void sve_update_vq_map(void)
>>>  {
>>> -	sve_probe_vqs(sve_secondary_vq_map);
>>> -	bitmap_and(sve_vq_map, sve_vq_map, sve_secondary_vq_map, SVE_VQ_MAX);
>>> +	DECLARE_BITMAP(tmp_map, SVE_VQ_MAX);
>>> +
>>> +	sve_probe_vqs(tmp_map);
>>> +	bitmap_and(sve_vq_map, sve_vq_map, tmp_map, SVE_VQ_MAX);
>>> +	bitmap_or(sve_vq_partial_map, sve_vq_partial_map, tmp_map, SVE_VQ_MAX);
>>>  }
>>>  
>>>  /* Check whether the current CPU supports all VQs in the committed set */
>>>  int sve_verify_vq_map(void)
>>>  {
>>> -	int ret = 0;
>>> +	DECLARE_BITMAP(tmp_map, SVE_VQ_MAX);
>>> +	unsigned long b;
>>>  
>>> -	sve_probe_vqs(sve_secondary_vq_map);
>>> -	bitmap_andnot(sve_secondary_vq_map, sve_vq_map, sve_secondary_vq_map,
>>> -		      SVE_VQ_MAX);
>>> -	if (!bitmap_empty(sve_secondary_vq_map, SVE_VQ_MAX)) {
>>> +	sve_probe_vqs(tmp_map);
>>> +
>>> +	bitmap_complement(tmp_map, tmp_map, SVE_VQ_MAX);
>>> +	if (bitmap_intersects(tmp_map, sve_vq_map, SVE_VQ_MAX)) {
>>>  		pr_warn("SVE: cpu%d: Required vector length(s) missing\n",
>>>  			smp_processor_id());
>>> -		ret = -EINVAL;
>>> +		return -EINVAL;
>>>  	}
>>>  
>>> -	return ret;
>>> +	if (!IS_ENABLED(CONFIG_KVM) || !is_hyp_mode_available())
>>> +		return 0;
>>> +
>>> +	/*
>>> +	 * For KVM, it is necessary to ensure that this CPU doesn't
>>> +	 * support any vector length that guests may have probed as
>>> +	 * unsupported.
>>> +	 */
>>> +
>>> +	/* Recover the set of supported VQs: */
>>> +	bitmap_complement(tmp_map, tmp_map, SVE_VQ_MAX);
>>> +	/* Find VQs supported that are not globally supported: */
>>> +	bitmap_andnot(tmp_map, tmp_map, sve_vq_map, SVE_VQ_MAX);
>>> +
>>> +	/* Find the lowest such VQ, if any: */
>>> +	b = find_last_bit(tmp_map, SVE_VQ_MAX);
>>> +	if (b >= SVE_VQ_MAX)
>>> +		return 0; /* no mismatches */
>>> +
>>> +	/*
>>> +	 * Mismatches above sve_max_virtualisable_vl are fine, since
>>> +	 * no guest is allowed to configure ZCR_EL2.LEN to exceed this:
>>> +	 */
>>> +	if (sve_vl_from_vq(bit_to_vq(b)) <= sve_max_virtualisable_vl) {
>>> +		pr_warn("SVE: cpu%d: Unsupported vector length(s) present\n",
>>
>> Nit: might be good to specify that the vector length is unsupported for
>> virtualisation.
>>
>> Also, since KVM is the one deciding what to do with the information,
>> should we have a warning here? But I can understand that knowing which
>> CPUs are introducing unsupported vector length, maybe using pr_devel()
>> instead of pr_warn()
> 
> These warnings are really for consumption by SoC vendors, not users:
> my aim is to flag up systems that we consider broken (or at least,
> unsuitable for running KVM).
> 
> So I prefer to make this noisy and limit the amount of "useful"
> information people might be tempted to programmatically scrape from
> dmesg.
> 
> cpufeatures uses pr_warn("SANITY CHECK: [...]") here.  Maybe I should
> stick "SANITY CHECK" in here too?  I will also try to make the commit
> message more explicit and/or add comments to make the intent of the code
> clearer.
> 
> It may also make sense to make this noise even if KVM isn't enabled
> (which is a rare case anyhow).
> 
> Thoughts?

As I explained later in the patch series, I missed the fact that this
function was for late secondary CPUs. I think things are fine like this
(just add the bit about the vector lenght not being supported for
virtualisation).

Cheers,

-- 
Julien Thierry

_______________________________________________
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] 205+ messages in thread

* Re: [PATCH v5 18/26] KVM: arm64/sve: Add SVE support to register access ioctl interface
  2019-02-26 12:13       ` Dave Martin
@ 2019-03-01 13:03         ` Julien Thierry
  -1 siblings, 0 replies; 205+ messages in thread
From: Julien Thierry @ 2019-03-01 13:03 UTC (permalink / raw)
  To: Dave Martin
  Cc: Okamoto Takayuki, Christoffer Dall, Ard Biesheuvel, Marc Zyngier,
	Catalin Marinas, Will Deacon, Zhang Lei, kvmarm,
	linux-arm-kernel



On 26/02/2019 12:13, Dave Martin wrote:
> On Thu, Feb 21, 2019 at 03:23:37PM +0000, Julien Thierry wrote:
>> Hi Dave,
>>
>> On 18/02/2019 19:52, Dave Martin wrote:
>>> This patch adds the following registers for access via the
>>> KVM_{GET,SET}_ONE_REG interface:
>>>
>>>  * KVM_REG_ARM64_SVE_ZREG(n, i) (n = 0..31) (in 2048-bit slices)
>>>  * KVM_REG_ARM64_SVE_PREG(n, i) (n = 0..15) (in 256-bit slices)
>>>  * KVM_REG_ARM64_SVE_FFR(i) (in 256-bit slices)
>>>
>>> In order to adapt gracefully to future architectural extensions,
>>> the registers are logically divided up into slices as noted above:
>>> the i parameter denotes the slice index.
>>>
>>> This allows us to reserve space in the ABI for future expansion of
>>> these registers.  However, as of today the architecture does not
>>> permit registers to be larger than a single slice, so no code is
>>> needed in the kernel to expose additional slices, for now.  The
>>> code can be extended later as needed to expose them up to a maximum
>>> of 32 slices (as carved out in the architecture itself) if they
>>> really exist someday.
>>>
>>> The registers are only visible for vcpus that have SVE enabled.
>>> They are not enumerated by KVM_GET_REG_LIST on vcpus that do not
>>> have SVE.
>>>
>>> Accesses to the FPSIMD registers via KVM_REG_ARM_CORE is not
>>> allowed for SVE-enabled vcpus: SVE-aware userspace can use the
>>> KVM_REG_ARM64_SVE_ZREG() interface instead to access the same
>>> register state.  This avoids some complex and pointless emulation
>>> in the kernel to convert between the two views of these aliased
>>> registers.
>>>
>>> Signed-off-by: Dave Martin <Dave.Martin@arm.com>
>>>
>>> ---
>>>
>>> Changes since v4:
>>>
>>>  * Add "BASE" #defines for the Z-reg and P-reg ranges in the KVM
>>>    register ID space, to make the 0x400 magic number a little less
>>>    cryptic.
>>>
>>>  * Pull KVM_SVE_{Z,P}REG_SIZE defines from "KVM: arm64: Enumerate SVE
>>>    register indices for KVM_GET_REG_LIST", since we now use them here.
>>>
>>>  * Simplify sve_reg_region(), and give up on the attempt to make
>>>    kreg_region a general thing: nothing else will use it for now,
>>>    anyway, so let's keep it as simple as possible.
>>>
>>>  * Drop support for multiple slices per register.  This functionality
>>>    can be added back in later if needed, without ABI breaks.
>>>
>>>  * Pull vcpu_sve_state_size() into kvm_host.h, from "KVM: arm64/sve:
>>>    Allow userspace to enable SVE for vcpus".  This is needed for use
>>>    with array_index_nospec() to determine the applicable buffer bounds.
>>>    To avoid circular header deependency issues, the function is also
>>>    converted into a macro, but is otherwise equivalent to the original
>>>    version.
>>>
>>>  * Guard sve_state base offset in kernel memory with
>>>    array_index_nospec(), since it is generated from user data that can
>>>    put it out of range.
>>>
>>>    (sve_state will get allocated with the corresponding size later in
>>>    the series.  For now, this code is dormant since no means is
>>>    provided for userspace to create SVE-enabled vcpus yet.)
>>> ---
>>>  arch/arm64/include/asm/kvm_host.h |  14 ++++
>>>  arch/arm64/include/uapi/asm/kvm.h |  17 +++++
>>>  arch/arm64/kvm/guest.c            | 138 ++++++++++++++++++++++++++++++++++----
>>>  3 files changed, 157 insertions(+), 12 deletions(-)
>>>
>>
>> [...]
>>
>>> diff --git a/arch/arm64/kvm/guest.c b/arch/arm64/kvm/guest.c
>>> index f491456..8cfa889 100644
>>> --- a/arch/arm64/kvm/guest.c
>>> +++ b/arch/arm64/kvm/guest.c
>>
>> [...]
>>
>>> @@ -211,6 +217,114 @@ static int set_core_reg(struct kvm_vcpu *vcpu, const struct kvm_one_reg *reg)
>>>  	return err;
>>>  }
>>>  
>>> +#define SVE_REG_SLICE_SHIFT	0
>>> +#define SVE_REG_SLICE_BITS	5
>>> +#define SVE_REG_ID_SHIFT	(SVE_REG_SLICE_SHIFT + SVE_REG_SLICE_BITS)
>>> +#define SVE_REG_ID_BITS		5
>>> +
>>> +#define SVE_REG_SLICE_MASK					\
>>> +	GENMASK(SVE_REG_SLICE_SHIFT + SVE_REG_SLICE_BITS - 1,	\
>>> +		SVE_REG_SLICE_SHIFT)
>>> +#define SVE_REG_ID_MASK							\
>>> +	GENMASK(SVE_REG_ID_SHIFT + SVE_REG_ID_BITS - 1, SVE_REG_ID_SHIFT)
>>> +
>>> +#define SVE_NUM_SLICES (1 << SVE_REG_SLICE_BITS)
>>> +
>>> +#define KVM_SVE_ZREG_SIZE KVM_REG_SIZE(KVM_REG_ARM64_SVE_ZREG(0, 0))
>>> +#define KVM_SVE_PREG_SIZE KVM_REG_SIZE(KVM_REG_ARM64_SVE_PREG(0, 0))
>>> +
>>> +struct sve_state_region {
>>
>> This sve_state_region feels a bit too generic too me.
>>
>> So far it is only used to access a single (slice of a) register at a
>> time. Is there a plan to use it for more?
> 
> It's there as a way to factor out security-sensitive range computations
> that we otherwise have to do twice -- I'd rather have the (potential)
> bugs in one place.  sve_state is particularly awkward because it is
> heterogeneous, with variably sized members for which no C declaration
> is avaiable (or possible).
> 
> Previously it was used in four places, because I tried to emulate the
> VFP get/set functions for SVE vcpus.  Now that functionality has been
> dropped I agree that this function looks like a bit like overkill.  But
> I didn't come up with a good way to split it without duplicating an
> undesirable amount of fiddly logic.
> 
> "sve_state" in the name comes from the naming of the kernel field(s)
> that this computes ranges on: vcpu->arch.sve_state (and thread->
> sve_state, which we don't operate on here, but which has the same
> format).
> 
> So, this struct describes a slice of "sve_state", hence the name.  But
> you're right, it is only ever supposed to span a single SVE register
> within there.
> 
>> Otherwise I'd suggest at least naming it something like sve_reg_region,
>> sve_reg_mem_region or sve_reg_mem_desc.
> 
> It used to be called struct kreg_region.  The name "sve_state_region"
> was an attempt to make it look less generic, which doesn't appear to
> have worked too well.
> 
> Maybe "sve_state_reg_region" would narrow the apparent scope of this a
> little further.
> 
> Thoughts?
> 

Yes, I think that the name fits better. That + the comment you suggested
would set things clear.

> I'll take a look, and at least add a comment explaining what this
> struct is supposed to represent.
> 

Yes, that might prevent people looking into to much possibilities of its
usage.

Thanks,

-- 
Julien Thierry

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

* Re: [PATCH v5 18/26] KVM: arm64/sve: Add SVE support to register access ioctl interface
@ 2019-03-01 13:03         ` Julien Thierry
  0 siblings, 0 replies; 205+ messages in thread
From: Julien Thierry @ 2019-03-01 13:03 UTC (permalink / raw)
  To: Dave Martin
  Cc: Okamoto Takayuki, Christoffer Dall, Ard Biesheuvel, Marc Zyngier,
	Catalin Marinas, Will Deacon, Zhang Lei, kvmarm,
	linux-arm-kernel



On 26/02/2019 12:13, Dave Martin wrote:
> On Thu, Feb 21, 2019 at 03:23:37PM +0000, Julien Thierry wrote:
>> Hi Dave,
>>
>> On 18/02/2019 19:52, Dave Martin wrote:
>>> This patch adds the following registers for access via the
>>> KVM_{GET,SET}_ONE_REG interface:
>>>
>>>  * KVM_REG_ARM64_SVE_ZREG(n, i) (n = 0..31) (in 2048-bit slices)
>>>  * KVM_REG_ARM64_SVE_PREG(n, i) (n = 0..15) (in 256-bit slices)
>>>  * KVM_REG_ARM64_SVE_FFR(i) (in 256-bit slices)
>>>
>>> In order to adapt gracefully to future architectural extensions,
>>> the registers are logically divided up into slices as noted above:
>>> the i parameter denotes the slice index.
>>>
>>> This allows us to reserve space in the ABI for future expansion of
>>> these registers.  However, as of today the architecture does not
>>> permit registers to be larger than a single slice, so no code is
>>> needed in the kernel to expose additional slices, for now.  The
>>> code can be extended later as needed to expose them up to a maximum
>>> of 32 slices (as carved out in the architecture itself) if they
>>> really exist someday.
>>>
>>> The registers are only visible for vcpus that have SVE enabled.
>>> They are not enumerated by KVM_GET_REG_LIST on vcpus that do not
>>> have SVE.
>>>
>>> Accesses to the FPSIMD registers via KVM_REG_ARM_CORE is not
>>> allowed for SVE-enabled vcpus: SVE-aware userspace can use the
>>> KVM_REG_ARM64_SVE_ZREG() interface instead to access the same
>>> register state.  This avoids some complex and pointless emulation
>>> in the kernel to convert between the two views of these aliased
>>> registers.
>>>
>>> Signed-off-by: Dave Martin <Dave.Martin@arm.com>
>>>
>>> ---
>>>
>>> Changes since v4:
>>>
>>>  * Add "BASE" #defines for the Z-reg and P-reg ranges in the KVM
>>>    register ID space, to make the 0x400 magic number a little less
>>>    cryptic.
>>>
>>>  * Pull KVM_SVE_{Z,P}REG_SIZE defines from "KVM: arm64: Enumerate SVE
>>>    register indices for KVM_GET_REG_LIST", since we now use them here.
>>>
>>>  * Simplify sve_reg_region(), and give up on the attempt to make
>>>    kreg_region a general thing: nothing else will use it for now,
>>>    anyway, so let's keep it as simple as possible.
>>>
>>>  * Drop support for multiple slices per register.  This functionality
>>>    can be added back in later if needed, without ABI breaks.
>>>
>>>  * Pull vcpu_sve_state_size() into kvm_host.h, from "KVM: arm64/sve:
>>>    Allow userspace to enable SVE for vcpus".  This is needed for use
>>>    with array_index_nospec() to determine the applicable buffer bounds.
>>>    To avoid circular header deependency issues, the function is also
>>>    converted into a macro, but is otherwise equivalent to the original
>>>    version.
>>>
>>>  * Guard sve_state base offset in kernel memory with
>>>    array_index_nospec(), since it is generated from user data that can
>>>    put it out of range.
>>>
>>>    (sve_state will get allocated with the corresponding size later in
>>>    the series.  For now, this code is dormant since no means is
>>>    provided for userspace to create SVE-enabled vcpus yet.)
>>> ---
>>>  arch/arm64/include/asm/kvm_host.h |  14 ++++
>>>  arch/arm64/include/uapi/asm/kvm.h |  17 +++++
>>>  arch/arm64/kvm/guest.c            | 138 ++++++++++++++++++++++++++++++++++----
>>>  3 files changed, 157 insertions(+), 12 deletions(-)
>>>
>>
>> [...]
>>
>>> diff --git a/arch/arm64/kvm/guest.c b/arch/arm64/kvm/guest.c
>>> index f491456..8cfa889 100644
>>> --- a/arch/arm64/kvm/guest.c
>>> +++ b/arch/arm64/kvm/guest.c
>>
>> [...]
>>
>>> @@ -211,6 +217,114 @@ static int set_core_reg(struct kvm_vcpu *vcpu, const struct kvm_one_reg *reg)
>>>  	return err;
>>>  }
>>>  
>>> +#define SVE_REG_SLICE_SHIFT	0
>>> +#define SVE_REG_SLICE_BITS	5
>>> +#define SVE_REG_ID_SHIFT	(SVE_REG_SLICE_SHIFT + SVE_REG_SLICE_BITS)
>>> +#define SVE_REG_ID_BITS		5
>>> +
>>> +#define SVE_REG_SLICE_MASK					\
>>> +	GENMASK(SVE_REG_SLICE_SHIFT + SVE_REG_SLICE_BITS - 1,	\
>>> +		SVE_REG_SLICE_SHIFT)
>>> +#define SVE_REG_ID_MASK							\
>>> +	GENMASK(SVE_REG_ID_SHIFT + SVE_REG_ID_BITS - 1, SVE_REG_ID_SHIFT)
>>> +
>>> +#define SVE_NUM_SLICES (1 << SVE_REG_SLICE_BITS)
>>> +
>>> +#define KVM_SVE_ZREG_SIZE KVM_REG_SIZE(KVM_REG_ARM64_SVE_ZREG(0, 0))
>>> +#define KVM_SVE_PREG_SIZE KVM_REG_SIZE(KVM_REG_ARM64_SVE_PREG(0, 0))
>>> +
>>> +struct sve_state_region {
>>
>> This sve_state_region feels a bit too generic too me.
>>
>> So far it is only used to access a single (slice of a) register at a
>> time. Is there a plan to use it for more?
> 
> It's there as a way to factor out security-sensitive range computations
> that we otherwise have to do twice -- I'd rather have the (potential)
> bugs in one place.  sve_state is particularly awkward because it is
> heterogeneous, with variably sized members for which no C declaration
> is avaiable (or possible).
> 
> Previously it was used in four places, because I tried to emulate the
> VFP get/set functions for SVE vcpus.  Now that functionality has been
> dropped I agree that this function looks like a bit like overkill.  But
> I didn't come up with a good way to split it without duplicating an
> undesirable amount of fiddly logic.
> 
> "sve_state" in the name comes from the naming of the kernel field(s)
> that this computes ranges on: vcpu->arch.sve_state (and thread->
> sve_state, which we don't operate on here, but which has the same
> format).
> 
> So, this struct describes a slice of "sve_state", hence the name.  But
> you're right, it is only ever supposed to span a single SVE register
> within there.
> 
>> Otherwise I'd suggest at least naming it something like sve_reg_region,
>> sve_reg_mem_region or sve_reg_mem_desc.
> 
> It used to be called struct kreg_region.  The name "sve_state_region"
> was an attempt to make it look less generic, which doesn't appear to
> have worked too well.
> 
> Maybe "sve_state_reg_region" would narrow the apparent scope of this a
> little further.
> 
> Thoughts?
> 

Yes, I think that the name fits better. That + the comment you suggested
would set things clear.

> I'll take a look, and at least add a comment explaining what this
> struct is supposed to represent.
> 

Yes, that might prevent people looking into to much possibilities of its
usage.

Thanks,

-- 
Julien Thierry

_______________________________________________
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] 205+ messages in thread

* Re: [PATCH v5 22/26] KVM: arm64/sve: Add pseudo-register for the guest's vector lengths
  2019-02-26 12:13       ` Dave Martin
@ 2019-03-01 13:28         ` Julien Thierry
  -1 siblings, 0 replies; 205+ messages in thread
From: Julien Thierry @ 2019-03-01 13:28 UTC (permalink / raw)
  To: Dave Martin
  Cc: Okamoto Takayuki, Christoffer Dall, Ard Biesheuvel, Marc Zyngier,
	Catalin Marinas, Will Deacon, Zhang Lei, kvmarm,
	linux-arm-kernel



On 26/02/2019 12:13, Dave Martin wrote:
> On Thu, Feb 21, 2019 at 05:48:59PM +0000, Julien Thierry wrote:
>> Hi Dave,
>>
>> On 18/02/2019 19:52, Dave Martin wrote:
>>> This patch adds a new pseudo-register KVM_REG_ARM64_SVE_VLS to
>>> allow userspace to set and query the set of vector lengths visible
>>> to the guest, along with corresponding storage in struct
>>> kvm_vcpu_arch.
>>>
>>> In the future, multiple register slices per SVE register may be
>>> visible through the ioctl interface.  Once the set of slices has
>>> been determined we would not be able to allow the vector length set
>>> to be changed any more, in order to avoid userspace seeing
>>> inconsistent sets of registers.  For this reason, this patch adds
>>> support to track vcpu finalization explicitly, and enforce proper
>>> sequencing of ioctls.
>>>
>>> The new pseudo-register is not exposed yet.  Subsequent patches
>>> will allow SVE to be turned on for guest vcpus, making it visible.
>>>
>>> Signed-off-by: Dave Martin <Dave.Martin@arm.com>
>>>
>>> ---
>>>
>>> Changes since v4:
>>>
>>>  * Add a UAPI header comment indicating the pseudo-register status of
>>>    KVM_REG_ARM64_SVE_VLS.
>>>
>>>  * Get rid of the sve_vqs[] array from struct kvm_vcpu_arch.  This
>>>    array is pointless, because its contents must match the host's
>>>    internal sve_vq_map anyway, up to vcpu->arch.sve_max_vl.
>>>
>>>    The ioctl register accessors are slow-path code, so we can decode
>>>    or reconstruct sve_vqs[] on demand instead, for exchange with
>>>    userspace.
>>>
>>>  * For compatibility with potential future architecture extensions,
>>>    enabling vector lengths above 256 bytes for the guest is explicitly
>>>    disallowed now (because the code for exposing additional bits
>>>    through ioctl is currently missing).  This can be addressed later
>>>    if/when needed.
>>>
>>> Note:
>>>
>>>  * I defensively pass an array by pointer here, to help avoid
>>>    accidentally breaking assumptions during future maintenance.
>>>
>>>    Due to (over?)zealous constification, this causes the following
>>>    sparse warning.  I think this is sparse getting confused: I am not
>>>    relying on any kernel-specific semantics here, and GCC generates no
>>>    warning.
>>>
>>> +arch/arm64/kvm/guest.c:33: warning: incorrect type in argument 1 (different modifiers)
>>> +arch/arm64/kvm/guest.c:33:    expected unsigned long long const [usertype] ( *const vqs )[8]
>>> +arch/arm64/kvm/guest.c:33:    got unsigned long long [usertype] ( * )[8]
>>>
>>> ---
> 
> [...]
> 
>>> diff --git a/arch/arm64/include/uapi/asm/kvm.h b/arch/arm64/include/uapi/asm/kvm.h
> 
> [...]
> 
>>> +static int get_sve_vls(struct kvm_vcpu *vcpu, const struct kvm_one_reg *reg)
>>> +{
>>> +	unsigned int max_vq, vq;
>>> +	u64 vqs[DIV_ROUND_UP(SVE_VQ_MAX - SVE_VQ_MIN + 1, 64)];
>>> +
>>> +	if (WARN_ON(!sve_vl_valid(vcpu->arch.sve_max_vl)))
>>> +		return -EINVAL;
>>> +
>>> +	memset(vqs, 0, sizeof(vqs));
>>> +
>>> +	max_vq = sve_vq_from_vl(vcpu->arch.sve_max_vl);
>>> +	for (vq = SVE_VQ_MIN; vq <= max_vq; ++vq)
>>> +		if (sve_vq_available(vq))
>>> +			vqs[vq_word(vq)] |= vq_mask(vq);
>>> +
>>> +	BUILD_BUG_ON(sizeof(vqs) != KVM_REG_SIZE(reg->id));
>>
>> reg->id is not know at build time. From my understanding of
>> BUILD_BUG_ON(), things actually ends up evaluated at runtime but I'm not
>> sure what happens when doing sizeof(char[1- 2*0]) at runtime.
>>
>> Anyway, I don't think this is intended.
> 
> There's no runtime check: BUILD_BUG_ON() will cause compilation to fail
> if the required condition doesn't fall out from optimisation.
> 
> Because of the way this function is called, reg->id is always
> KVM_REG_ARM64_SVE_VLS, so inlining and constant propagation will make
> this check pass (and compile to nothing).
> 
> We can assume a certain amount of inlining: the kernel officially can't
> be built without optimisation.  But the precise build configuration can
> sometimes have an effect here -- so it may not be better to rely on this
> working for this slow-path code.
> 
> I'll convert these to if (WARN_ON()) return -EIO or something, or drop
> them if I can get rid of them in other refactoring.
> 
> The fact that struct kvm_one_reg lacks any "size" field is rather
> unfortunate, since it provides no explicit way for userspace to tell us
> the size of its buffer.
> 
>>> +	if (copy_to_user((void __user *)reg->addr, vqs, sizeof(vqs)))
>>> +		return -EFAULT;
>>> +
>>> +	return 0;
>>> +}
>>> +
>>> +static int set_sve_vls(struct kvm_vcpu *vcpu, const struct kvm_one_reg *reg)
>>> +{
>>> +	unsigned int max_vq, vq;
>>> +	u64 vqs[DIV_ROUND_UP(SVE_VQ_MAX - SVE_VQ_MIN + 1, 64)];
>>> +
>>> +	if (kvm_arm_vcpu_finalized(vcpu))
>>> +		return -EPERM; /* too late! */
>>> +
>>> +	if (WARN_ON(vcpu->arch.sve_state))
>>> +		return -EINVAL;
>>> +
>>> +	BUILD_BUG_ON(sizeof(vqs) != KVM_REG_SIZE(reg->id));
>>
>> Same as above.
>>
>>> +	if (copy_from_user(vqs, (const void __user *)reg->addr, sizeof(vqs)))
>>> +		return -EFAULT;
>>> +
>>> +	max_vq = 0;
>>> +	for (vq = SVE_VQ_MIN; vq <= SVE_VQ_MAX; ++vq)
>>> +		if (vq_present(&vqs, vq))
>>> +			max_vq = vq;
>>> +
>>> +	/*
>>> +	 * The get_sve_reg()/set_sve_reg() ioctl interface will need
>>> +	 * to be extended with multiple register slice support in
>>> +	 * order to support vector lengths greater than
>>> +	 * SVE_VL_ARCH_MAX:
>>> +	 */
>>> +	if (WARN_ONCE(sve_vl_from_vq(max_vq) > SVE_VL_ARCH_MAX,
>>> +		      "KVM: Requested vector length not supported yet\n"))
>>> +		return -EINVAL;
>>> +
>>> +	for (vq = SVE_VQ_MIN; vq <= max_vq; ++vq)
>>> +		if (vq_present(&vqs, vq) != sve_vq_available(vq))
>>> +			return -EINVAL;
>>> +
>>> +	/* Can't run with no vector lengths at all: */
>>> +	if (max_vq < SVE_VQ_MIN)
>>> +		return -EINVAL;
>>> +
>>> +	vcpu->arch.sve_max_vl = sve_vl_from_vq(max_vq);
>>> +
>>> +	return 0;
>>> +}
>>> +
>>>  #define SVE_REG_SLICE_SHIFT	0
>>>  #define SVE_REG_SLICE_BITS	5
>>>  #define SVE_REG_ID_SHIFT	(SVE_REG_SLICE_SHIFT + SVE_REG_SLICE_BITS)
>>> @@ -297,9 +372,21 @@ static int sve_reg_region(struct sve_state_region *region,
>>>  static int get_sve_reg(struct kvm_vcpu *vcpu, const struct kvm_one_reg *reg)
>>>  {
>>>  	struct sve_state_region region;
>>> +	int ret;
>>>  	char __user *uptr = (char __user *)reg->addr;
>>>  
>>> -	if (!vcpu_has_sve(vcpu) || sve_reg_region(&region, vcpu, reg))
>>> +	if (!vcpu_has_sve(vcpu))
>>> +		return -ENOENT;
>>> +
>>> +	if (reg->id == KVM_REG_ARM64_SVE_VLS)
>>> +		return get_sve_vls(vcpu, reg);
>>> +
>>> +	/* Finalize the number of slices per SVE register: */
>>> +	ret = kvm_arm_vcpu_finalize(vcpu);
>>
>> Having this here feels a bit random...
> 
> I'll have another think about this.
> 
> KVM_REG_ARM64_SVE_VLS certainly has nothing to do with anything except
> SVE, and putting it in the SVE coproc space allows us to demux SVE-
> related stuff from everything else neatly.
> 
> The whole "coprocessor" concept is nonsense for arm64 anyway except
> for the sysregs (where the reg ID encodings map directly onto the
> architecture and also align with AArch32).  So, the copro number is
> pretty meaningless except as a demux key for related groups of
> registers, which is how I use it here.
> 
> There's also no well-defined distinction between real and fake
> registers, and no natural home for miscellaneous fakes -- all existing
> blocks are for specific purposes such as recording the state of emulated
> firmware APIs etc.  The SVE registers as exposed here already have no
> direct equivalent in the architecture either, due to the padding up to
> 2048 bits, and the presentation of FFR as addressable P-register etc.
> 
>> I'd suggest considering the pseudo-register outside of the SVE co-proc,
>> as part of a set of registers that do not finalize a vcpu when accessed.
> 
> (Also, the dependency is not one-way:  _SVE_VLS is not independent
> of finalization: quite the reverse -- it can only be written _before_
> finalization.)
> 
>> All other registers (even non-sve ones) would finalize the vcpu when
>> accessed from userland.
> 
> So, we could consider register to be in two classes as you suggest:
> 
>  * early registers
>  * regular registers (i.e., everything else)
> 
> where early registers can only be written until the first access to a
> regular register, or the first KVM_GET_REG_LIST or KVM_RUN.
> 

That would be my personal preference, yes.

> This is a stricter rule than I have today: i.e., _SVE_VLS would really
> need to be written before touching anything else.  But that may be a
> good thing for avoiding future ABI drift.
> 

I did notice this would be more restrictive, but I don't believe this
should introduce shortcoming in ways to set up a VCPU. I might have
missed some case of course.

> This may be premature factoring though.  It's not clear whether many new
> registers like KVM_REG_ARM64_SVE_VLS will exist, or that they would have
> compatible sequencing requirements.
> 
> Thoughts?
> 

It might be premature, but I really don't like seeing this
"vcpu_finalize" in the middle of SVE code. I think it is very easy to
miss that touching some "sve" register suddenly finalizes the vcpu.

I fear that some other feature/extention might need early vcpu
finalization and that it might somehow conflict with sve depending on
which triggers finalization first.

> 
> Independently of this, I'll have a look at whether there's
> a straightforward way to simplify the code flow.
> 

I might be over-thinking it, but if there is a way to move that
finalization call I'd prefer that.

Thanks,

-- 
Julien Thierry

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

* Re: [PATCH v5 22/26] KVM: arm64/sve: Add pseudo-register for the guest's vector lengths
@ 2019-03-01 13:28         ` Julien Thierry
  0 siblings, 0 replies; 205+ messages in thread
From: Julien Thierry @ 2019-03-01 13:28 UTC (permalink / raw)
  To: Dave Martin
  Cc: Okamoto Takayuki, Christoffer Dall, Ard Biesheuvel, Marc Zyngier,
	Catalin Marinas, Will Deacon, Zhang Lei, kvmarm,
	linux-arm-kernel



On 26/02/2019 12:13, Dave Martin wrote:
> On Thu, Feb 21, 2019 at 05:48:59PM +0000, Julien Thierry wrote:
>> Hi Dave,
>>
>> On 18/02/2019 19:52, Dave Martin wrote:
>>> This patch adds a new pseudo-register KVM_REG_ARM64_SVE_VLS to
>>> allow userspace to set and query the set of vector lengths visible
>>> to the guest, along with corresponding storage in struct
>>> kvm_vcpu_arch.
>>>
>>> In the future, multiple register slices per SVE register may be
>>> visible through the ioctl interface.  Once the set of slices has
>>> been determined we would not be able to allow the vector length set
>>> to be changed any more, in order to avoid userspace seeing
>>> inconsistent sets of registers.  For this reason, this patch adds
>>> support to track vcpu finalization explicitly, and enforce proper
>>> sequencing of ioctls.
>>>
>>> The new pseudo-register is not exposed yet.  Subsequent patches
>>> will allow SVE to be turned on for guest vcpus, making it visible.
>>>
>>> Signed-off-by: Dave Martin <Dave.Martin@arm.com>
>>>
>>> ---
>>>
>>> Changes since v4:
>>>
>>>  * Add a UAPI header comment indicating the pseudo-register status of
>>>    KVM_REG_ARM64_SVE_VLS.
>>>
>>>  * Get rid of the sve_vqs[] array from struct kvm_vcpu_arch.  This
>>>    array is pointless, because its contents must match the host's
>>>    internal sve_vq_map anyway, up to vcpu->arch.sve_max_vl.
>>>
>>>    The ioctl register accessors are slow-path code, so we can decode
>>>    or reconstruct sve_vqs[] on demand instead, for exchange with
>>>    userspace.
>>>
>>>  * For compatibility with potential future architecture extensions,
>>>    enabling vector lengths above 256 bytes for the guest is explicitly
>>>    disallowed now (because the code for exposing additional bits
>>>    through ioctl is currently missing).  This can be addressed later
>>>    if/when needed.
>>>
>>> Note:
>>>
>>>  * I defensively pass an array by pointer here, to help avoid
>>>    accidentally breaking assumptions during future maintenance.
>>>
>>>    Due to (over?)zealous constification, this causes the following
>>>    sparse warning.  I think this is sparse getting confused: I am not
>>>    relying on any kernel-specific semantics here, and GCC generates no
>>>    warning.
>>>
>>> +arch/arm64/kvm/guest.c:33: warning: incorrect type in argument 1 (different modifiers)
>>> +arch/arm64/kvm/guest.c:33:    expected unsigned long long const [usertype] ( *const vqs )[8]
>>> +arch/arm64/kvm/guest.c:33:    got unsigned long long [usertype] ( * )[8]
>>>
>>> ---
> 
> [...]
> 
>>> diff --git a/arch/arm64/include/uapi/asm/kvm.h b/arch/arm64/include/uapi/asm/kvm.h
> 
> [...]
> 
>>> +static int get_sve_vls(struct kvm_vcpu *vcpu, const struct kvm_one_reg *reg)
>>> +{
>>> +	unsigned int max_vq, vq;
>>> +	u64 vqs[DIV_ROUND_UP(SVE_VQ_MAX - SVE_VQ_MIN + 1, 64)];
>>> +
>>> +	if (WARN_ON(!sve_vl_valid(vcpu->arch.sve_max_vl)))
>>> +		return -EINVAL;
>>> +
>>> +	memset(vqs, 0, sizeof(vqs));
>>> +
>>> +	max_vq = sve_vq_from_vl(vcpu->arch.sve_max_vl);
>>> +	for (vq = SVE_VQ_MIN; vq <= max_vq; ++vq)
>>> +		if (sve_vq_available(vq))
>>> +			vqs[vq_word(vq)] |= vq_mask(vq);
>>> +
>>> +	BUILD_BUG_ON(sizeof(vqs) != KVM_REG_SIZE(reg->id));
>>
>> reg->id is not know at build time. From my understanding of
>> BUILD_BUG_ON(), things actually ends up evaluated at runtime but I'm not
>> sure what happens when doing sizeof(char[1- 2*0]) at runtime.
>>
>> Anyway, I don't think this is intended.
> 
> There's no runtime check: BUILD_BUG_ON() will cause compilation to fail
> if the required condition doesn't fall out from optimisation.
> 
> Because of the way this function is called, reg->id is always
> KVM_REG_ARM64_SVE_VLS, so inlining and constant propagation will make
> this check pass (and compile to nothing).
> 
> We can assume a certain amount of inlining: the kernel officially can't
> be built without optimisation.  But the precise build configuration can
> sometimes have an effect here -- so it may not be better to rely on this
> working for this slow-path code.
> 
> I'll convert these to if (WARN_ON()) return -EIO or something, or drop
> them if I can get rid of them in other refactoring.
> 
> The fact that struct kvm_one_reg lacks any "size" field is rather
> unfortunate, since it provides no explicit way for userspace to tell us
> the size of its buffer.
> 
>>> +	if (copy_to_user((void __user *)reg->addr, vqs, sizeof(vqs)))
>>> +		return -EFAULT;
>>> +
>>> +	return 0;
>>> +}
>>> +
>>> +static int set_sve_vls(struct kvm_vcpu *vcpu, const struct kvm_one_reg *reg)
>>> +{
>>> +	unsigned int max_vq, vq;
>>> +	u64 vqs[DIV_ROUND_UP(SVE_VQ_MAX - SVE_VQ_MIN + 1, 64)];
>>> +
>>> +	if (kvm_arm_vcpu_finalized(vcpu))
>>> +		return -EPERM; /* too late! */
>>> +
>>> +	if (WARN_ON(vcpu->arch.sve_state))
>>> +		return -EINVAL;
>>> +
>>> +	BUILD_BUG_ON(sizeof(vqs) != KVM_REG_SIZE(reg->id));
>>
>> Same as above.
>>
>>> +	if (copy_from_user(vqs, (const void __user *)reg->addr, sizeof(vqs)))
>>> +		return -EFAULT;
>>> +
>>> +	max_vq = 0;
>>> +	for (vq = SVE_VQ_MIN; vq <= SVE_VQ_MAX; ++vq)
>>> +		if (vq_present(&vqs, vq))
>>> +			max_vq = vq;
>>> +
>>> +	/*
>>> +	 * The get_sve_reg()/set_sve_reg() ioctl interface will need
>>> +	 * to be extended with multiple register slice support in
>>> +	 * order to support vector lengths greater than
>>> +	 * SVE_VL_ARCH_MAX:
>>> +	 */
>>> +	if (WARN_ONCE(sve_vl_from_vq(max_vq) > SVE_VL_ARCH_MAX,
>>> +		      "KVM: Requested vector length not supported yet\n"))
>>> +		return -EINVAL;
>>> +
>>> +	for (vq = SVE_VQ_MIN; vq <= max_vq; ++vq)
>>> +		if (vq_present(&vqs, vq) != sve_vq_available(vq))
>>> +			return -EINVAL;
>>> +
>>> +	/* Can't run with no vector lengths at all: */
>>> +	if (max_vq < SVE_VQ_MIN)
>>> +		return -EINVAL;
>>> +
>>> +	vcpu->arch.sve_max_vl = sve_vl_from_vq(max_vq);
>>> +
>>> +	return 0;
>>> +}
>>> +
>>>  #define SVE_REG_SLICE_SHIFT	0
>>>  #define SVE_REG_SLICE_BITS	5
>>>  #define SVE_REG_ID_SHIFT	(SVE_REG_SLICE_SHIFT + SVE_REG_SLICE_BITS)
>>> @@ -297,9 +372,21 @@ static int sve_reg_region(struct sve_state_region *region,
>>>  static int get_sve_reg(struct kvm_vcpu *vcpu, const struct kvm_one_reg *reg)
>>>  {
>>>  	struct sve_state_region region;
>>> +	int ret;
>>>  	char __user *uptr = (char __user *)reg->addr;
>>>  
>>> -	if (!vcpu_has_sve(vcpu) || sve_reg_region(&region, vcpu, reg))
>>> +	if (!vcpu_has_sve(vcpu))
>>> +		return -ENOENT;
>>> +
>>> +	if (reg->id == KVM_REG_ARM64_SVE_VLS)
>>> +		return get_sve_vls(vcpu, reg);
>>> +
>>> +	/* Finalize the number of slices per SVE register: */
>>> +	ret = kvm_arm_vcpu_finalize(vcpu);
>>
>> Having this here feels a bit random...
> 
> I'll have another think about this.
> 
> KVM_REG_ARM64_SVE_VLS certainly has nothing to do with anything except
> SVE, and putting it in the SVE coproc space allows us to demux SVE-
> related stuff from everything else neatly.
> 
> The whole "coprocessor" concept is nonsense for arm64 anyway except
> for the sysregs (where the reg ID encodings map directly onto the
> architecture and also align with AArch32).  So, the copro number is
> pretty meaningless except as a demux key for related groups of
> registers, which is how I use it here.
> 
> There's also no well-defined distinction between real and fake
> registers, and no natural home for miscellaneous fakes -- all existing
> blocks are for specific purposes such as recording the state of emulated
> firmware APIs etc.  The SVE registers as exposed here already have no
> direct equivalent in the architecture either, due to the padding up to
> 2048 bits, and the presentation of FFR as addressable P-register etc.
> 
>> I'd suggest considering the pseudo-register outside of the SVE co-proc,
>> as part of a set of registers that do not finalize a vcpu when accessed.
> 
> (Also, the dependency is not one-way:  _SVE_VLS is not independent
> of finalization: quite the reverse -- it can only be written _before_
> finalization.)
> 
>> All other registers (even non-sve ones) would finalize the vcpu when
>> accessed from userland.
> 
> So, we could consider register to be in two classes as you suggest:
> 
>  * early registers
>  * regular registers (i.e., everything else)
> 
> where early registers can only be written until the first access to a
> regular register, or the first KVM_GET_REG_LIST or KVM_RUN.
> 

That would be my personal preference, yes.

> This is a stricter rule than I have today: i.e., _SVE_VLS would really
> need to be written before touching anything else.  But that may be a
> good thing for avoiding future ABI drift.
> 

I did notice this would be more restrictive, but I don't believe this
should introduce shortcoming in ways to set up a VCPU. I might have
missed some case of course.

> This may be premature factoring though.  It's not clear whether many new
> registers like KVM_REG_ARM64_SVE_VLS will exist, or that they would have
> compatible sequencing requirements.
> 
> Thoughts?
> 

It might be premature, but I really don't like seeing this
"vcpu_finalize" in the middle of SVE code. I think it is very easy to
miss that touching some "sve" register suddenly finalizes the vcpu.

I fear that some other feature/extention might need early vcpu
finalization and that it might somehow conflict with sve depending on
which triggers finalization first.

> 
> Independently of this, I'll have a look at whether there's
> a straightforward way to simplify the code flow.
> 

I might be over-thinking it, but if there is a way to move that
finalization call I'd prefer that.

Thanks,

-- 
Julien Thierry

_______________________________________________
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] 205+ messages in thread

* Re: [PATCH v5 06/26] arm64/sve: Check SVE virtualisability
  2019-03-01 12:39         ` Julien Thierry
@ 2019-03-01 14:44           ` Dave Martin
  -1 siblings, 0 replies; 205+ messages in thread
From: Dave Martin @ 2019-03-01 14:44 UTC (permalink / raw)
  To: Julien Thierry
  Cc: Okamoto Takayuki, Christoffer Dall, Ard Biesheuvel, Marc Zyngier,
	Catalin Marinas, Will Deacon, Zhang Lei, kvmarm,
	linux-arm-kernel

On Fri, Mar 01, 2019 at 12:39:52PM +0000, Julien Thierry wrote:
> 
> 
> On 26/02/2019 12:06, Dave Martin wrote:
> > On Wed, Feb 20, 2019 at 11:12:49AM +0000, Julien Thierry wrote:
> >> Hi Dave,
> >>
> >> On 18/02/2019 19:52, Dave Martin wrote:

[...]

> >>> +	/*
> >>> +	 * Mismatches above sve_max_virtualisable_vl are fine, since
> >>> +	 * no guest is allowed to configure ZCR_EL2.LEN to exceed this:
> >>> +	 */
> >>> +	if (sve_vl_from_vq(bit_to_vq(b)) <= sve_max_virtualisable_vl) {
> >>> +		pr_warn("SVE: cpu%d: Unsupported vector length(s) present\n",
> >>
> >> Nit: might be good to specify that the vector length is unsupported for
> >> virtualisation.
> >>
> >> Also, since KVM is the one deciding what to do with the information,
> >> should we have a warning here? But I can understand that knowing which
> >> CPUs are introducing unsupported vector length, maybe using pr_devel()
> >> instead of pr_warn()
> > 
> > These warnings are really for consumption by SoC vendors, not users:
> > my aim is to flag up systems that we consider broken (or at least,
> > unsuitable for running KVM).
> > 
> > So I prefer to make this noisy and limit the amount of "useful"
> > information people might be tempted to programmatically scrape from
> > dmesg.
> > 
> > cpufeatures uses pr_warn("SANITY CHECK: [...]") here.  Maybe I should
> > stick "SANITY CHECK" in here too?  I will also try to make the commit
> > message more explicit and/or add comments to make the intent of the code
> > clearer.
> > 
> > It may also make sense to make this noise even if KVM isn't enabled
> > (which is a rare case anyhow).
> > 
> > Thoughts?
> 
> As I explained later in the patch series, I missed the fact that this
> function was for late secondary CPUs. I think things are fine like this
> (just add the bit about the vector lenght not being supported for
> virtualisation).

I've now reworked all this a bit: I probe for the largest vector length
than be offered to guests, and if this is less than the host's maximum
vector length then I print a one-off warning saying what limit KVM is
clamping guests' vector length to.

Elsewhere, I now just use the probed value as the maximum vector length,
rather than duplicating the bounds checking logic.

This approach seems simpler, and is hoepfully a bit more self-
explanatory -- so please take a look when I repost :)

Cheers
---Dave

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

* Re: [PATCH v5 06/26] arm64/sve: Check SVE virtualisability
@ 2019-03-01 14:44           ` Dave Martin
  0 siblings, 0 replies; 205+ messages in thread
From: Dave Martin @ 2019-03-01 14:44 UTC (permalink / raw)
  To: Julien Thierry
  Cc: Okamoto Takayuki, Christoffer Dall, Ard Biesheuvel, Marc Zyngier,
	Catalin Marinas, Will Deacon, Zhang Lei, kvmarm,
	linux-arm-kernel

On Fri, Mar 01, 2019 at 12:39:52PM +0000, Julien Thierry wrote:
> 
> 
> On 26/02/2019 12:06, Dave Martin wrote:
> > On Wed, Feb 20, 2019 at 11:12:49AM +0000, Julien Thierry wrote:
> >> Hi Dave,
> >>
> >> On 18/02/2019 19:52, Dave Martin wrote:

[...]

> >>> +	/*
> >>> +	 * Mismatches above sve_max_virtualisable_vl are fine, since
> >>> +	 * no guest is allowed to configure ZCR_EL2.LEN to exceed this:
> >>> +	 */
> >>> +	if (sve_vl_from_vq(bit_to_vq(b)) <= sve_max_virtualisable_vl) {
> >>> +		pr_warn("SVE: cpu%d: Unsupported vector length(s) present\n",
> >>
> >> Nit: might be good to specify that the vector length is unsupported for
> >> virtualisation.
> >>
> >> Also, since KVM is the one deciding what to do with the information,
> >> should we have a warning here? But I can understand that knowing which
> >> CPUs are introducing unsupported vector length, maybe using pr_devel()
> >> instead of pr_warn()
> > 
> > These warnings are really for consumption by SoC vendors, not users:
> > my aim is to flag up systems that we consider broken (or at least,
> > unsuitable for running KVM).
> > 
> > So I prefer to make this noisy and limit the amount of "useful"
> > information people might be tempted to programmatically scrape from
> > dmesg.
> > 
> > cpufeatures uses pr_warn("SANITY CHECK: [...]") here.  Maybe I should
> > stick "SANITY CHECK" in here too?  I will also try to make the commit
> > message more explicit and/or add comments to make the intent of the code
> > clearer.
> > 
> > It may also make sense to make this noise even if KVM isn't enabled
> > (which is a rare case anyhow).
> > 
> > Thoughts?
> 
> As I explained later in the patch series, I missed the fact that this
> function was for late secondary CPUs. I think things are fine like this
> (just add the bit about the vector lenght not being supported for
> virtualisation).

I've now reworked all this a bit: I probe for the largest vector length
than be offered to guests, and if this is less than the host's maximum
vector length then I print a one-off warning saying what limit KVM is
clamping guests' vector length to.

Elsewhere, I now just use the probed value as the maximum vector length,
rather than duplicating the bounds checking logic.

This approach seems simpler, and is hoepfully a bit more self-
explanatory -- so please take a look when I repost :)

Cheers
---Dave

_______________________________________________
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] 205+ messages in thread

* Re: [PATCH v5 18/26] KVM: arm64/sve: Add SVE support to register access ioctl interface
  2019-03-01 13:03         ` Julien Thierry
@ 2019-03-01 14:45           ` Dave Martin
  -1 siblings, 0 replies; 205+ messages in thread
From: Dave Martin @ 2019-03-01 14:45 UTC (permalink / raw)
  To: Julien Thierry
  Cc: Okamoto Takayuki, Christoffer Dall, Ard Biesheuvel, Marc Zyngier,
	Catalin Marinas, Will Deacon, Zhang Lei, kvmarm,
	linux-arm-kernel

On Fri, Mar 01, 2019 at 01:03:36PM +0000, Julien Thierry wrote:
> 
> 
> On 26/02/2019 12:13, Dave Martin wrote:
> > On Thu, Feb 21, 2019 at 03:23:37PM +0000, Julien Thierry wrote:
> >> Hi Dave,
> >>
> >> On 18/02/2019 19:52, Dave Martin wrote:
> >>> This patch adds the following registers for access via the
> >>> KVM_{GET,SET}_ONE_REG interface:
> >>>
> >>>  * KVM_REG_ARM64_SVE_ZREG(n, i) (n = 0..31) (in 2048-bit slices)
> >>>  * KVM_REG_ARM64_SVE_PREG(n, i) (n = 0..15) (in 256-bit slices)
> >>>  * KVM_REG_ARM64_SVE_FFR(i) (in 256-bit slices)
> >>>
> >>> In order to adapt gracefully to future architectural extensions,
> >>> the registers are logically divided up into slices as noted above:
> >>> the i parameter denotes the slice index.
> >>>
> >>> This allows us to reserve space in the ABI for future expansion of
> >>> these registers.  However, as of today the architecture does not
> >>> permit registers to be larger than a single slice, so no code is
> >>> needed in the kernel to expose additional slices, for now.  The
> >>> code can be extended later as needed to expose them up to a maximum
> >>> of 32 slices (as carved out in the architecture itself) if they
> >>> really exist someday.
> >>>
> >>> The registers are only visible for vcpus that have SVE enabled.
> >>> They are not enumerated by KVM_GET_REG_LIST on vcpus that do not
> >>> have SVE.
> >>>
> >>> Accesses to the FPSIMD registers via KVM_REG_ARM_CORE is not
> >>> allowed for SVE-enabled vcpus: SVE-aware userspace can use the
> >>> KVM_REG_ARM64_SVE_ZREG() interface instead to access the same
> >>> register state.  This avoids some complex and pointless emulation
> >>> in the kernel to convert between the two views of these aliased
> >>> registers.
> >>>
> >>> Signed-off-by: Dave Martin <Dave.Martin@arm.com>

[...]

> >>> diff --git a/arch/arm64/kvm/guest.c b/arch/arm64/kvm/guest.c
> >>> index f491456..8cfa889 100644
> >>> --- a/arch/arm64/kvm/guest.c
> >>> +++ b/arch/arm64/kvm/guest.c

[...]

> >>> +struct sve_state_region {
> >>
> >> This sve_state_region feels a bit too generic too me.
> >>
> >> So far it is only used to access a single (slice of a) register at a
> >> time. Is there a plan to use it for more?
> > 
> > It's there as a way to factor out security-sensitive range computations
> > that we otherwise have to do twice -- I'd rather have the (potential)
> > bugs in one place.  sve_state is particularly awkward because it is
> > heterogeneous, with variably sized members for which no C declaration
> > is avaiable (or possible).
> > 
> > Previously it was used in four places, because I tried to emulate the
> > VFP get/set functions for SVE vcpus.  Now that functionality has been
> > dropped I agree that this function looks like a bit like overkill.  But
> > I didn't come up with a good way to split it without duplicating an
> > undesirable amount of fiddly logic.
> > 
> > "sve_state" in the name comes from the naming of the kernel field(s)
> > that this computes ranges on: vcpu->arch.sve_state (and thread->
> > sve_state, which we don't operate on here, but which has the same
> > format).
> > 
> > So, this struct describes a slice of "sve_state", hence the name.  But
> > you're right, it is only ever supposed to span a single SVE register
> > within there.
> > 
> >> Otherwise I'd suggest at least naming it something like sve_reg_region,
> >> sve_reg_mem_region or sve_reg_mem_desc.
> > 
> > It used to be called struct kreg_region.  The name "sve_state_region"
> > was an attempt to make it look less generic, which doesn't appear to
> > have worked too well.
> > 
> > Maybe "sve_state_reg_region" would narrow the apparent scope of this a
> > little further.
> > 
> > Thoughts?
> > 
> 
> Yes, I think that the name fits better. That + the comment you suggested
> would set things clear.
> 
> > I'll take a look, and at least add a comment explaining what this
> > struct is supposed to represent.
> > 
> 
> Yes, that might prevent people looking into to much possibilities of its
> usage.

OK, both done.

Cheers
---Dave

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

* Re: [PATCH v5 18/26] KVM: arm64/sve: Add SVE support to register access ioctl interface
@ 2019-03-01 14:45           ` Dave Martin
  0 siblings, 0 replies; 205+ messages in thread
From: Dave Martin @ 2019-03-01 14:45 UTC (permalink / raw)
  To: Julien Thierry
  Cc: Okamoto Takayuki, Christoffer Dall, Ard Biesheuvel, Marc Zyngier,
	Catalin Marinas, Will Deacon, Zhang Lei, kvmarm,
	linux-arm-kernel

On Fri, Mar 01, 2019 at 01:03:36PM +0000, Julien Thierry wrote:
> 
> 
> On 26/02/2019 12:13, Dave Martin wrote:
> > On Thu, Feb 21, 2019 at 03:23:37PM +0000, Julien Thierry wrote:
> >> Hi Dave,
> >>
> >> On 18/02/2019 19:52, Dave Martin wrote:
> >>> This patch adds the following registers for access via the
> >>> KVM_{GET,SET}_ONE_REG interface:
> >>>
> >>>  * KVM_REG_ARM64_SVE_ZREG(n, i) (n = 0..31) (in 2048-bit slices)
> >>>  * KVM_REG_ARM64_SVE_PREG(n, i) (n = 0..15) (in 256-bit slices)
> >>>  * KVM_REG_ARM64_SVE_FFR(i) (in 256-bit slices)
> >>>
> >>> In order to adapt gracefully to future architectural extensions,
> >>> the registers are logically divided up into slices as noted above:
> >>> the i parameter denotes the slice index.
> >>>
> >>> This allows us to reserve space in the ABI for future expansion of
> >>> these registers.  However, as of today the architecture does not
> >>> permit registers to be larger than a single slice, so no code is
> >>> needed in the kernel to expose additional slices, for now.  The
> >>> code can be extended later as needed to expose them up to a maximum
> >>> of 32 slices (as carved out in the architecture itself) if they
> >>> really exist someday.
> >>>
> >>> The registers are only visible for vcpus that have SVE enabled.
> >>> They are not enumerated by KVM_GET_REG_LIST on vcpus that do not
> >>> have SVE.
> >>>
> >>> Accesses to the FPSIMD registers via KVM_REG_ARM_CORE is not
> >>> allowed for SVE-enabled vcpus: SVE-aware userspace can use the
> >>> KVM_REG_ARM64_SVE_ZREG() interface instead to access the same
> >>> register state.  This avoids some complex and pointless emulation
> >>> in the kernel to convert between the two views of these aliased
> >>> registers.
> >>>
> >>> Signed-off-by: Dave Martin <Dave.Martin@arm.com>

[...]

> >>> diff --git a/arch/arm64/kvm/guest.c b/arch/arm64/kvm/guest.c
> >>> index f491456..8cfa889 100644
> >>> --- a/arch/arm64/kvm/guest.c
> >>> +++ b/arch/arm64/kvm/guest.c

[...]

> >>> +struct sve_state_region {
> >>
> >> This sve_state_region feels a bit too generic too me.
> >>
> >> So far it is only used to access a single (slice of a) register at a
> >> time. Is there a plan to use it for more?
> > 
> > It's there as a way to factor out security-sensitive range computations
> > that we otherwise have to do twice -- I'd rather have the (potential)
> > bugs in one place.  sve_state is particularly awkward because it is
> > heterogeneous, with variably sized members for which no C declaration
> > is avaiable (or possible).
> > 
> > Previously it was used in four places, because I tried to emulate the
> > VFP get/set functions for SVE vcpus.  Now that functionality has been
> > dropped I agree that this function looks like a bit like overkill.  But
> > I didn't come up with a good way to split it without duplicating an
> > undesirable amount of fiddly logic.
> > 
> > "sve_state" in the name comes from the naming of the kernel field(s)
> > that this computes ranges on: vcpu->arch.sve_state (and thread->
> > sve_state, which we don't operate on here, but which has the same
> > format).
> > 
> > So, this struct describes a slice of "sve_state", hence the name.  But
> > you're right, it is only ever supposed to span a single SVE register
> > within there.
> > 
> >> Otherwise I'd suggest at least naming it something like sve_reg_region,
> >> sve_reg_mem_region or sve_reg_mem_desc.
> > 
> > It used to be called struct kreg_region.  The name "sve_state_region"
> > was an attempt to make it look less generic, which doesn't appear to
> > have worked too well.
> > 
> > Maybe "sve_state_reg_region" would narrow the apparent scope of this a
> > little further.
> > 
> > Thoughts?
> > 
> 
> Yes, I think that the name fits better. That + the comment you suggested
> would set things clear.
> 
> > I'll take a look, and at least add a comment explaining what this
> > struct is supposed to represent.
> > 
> 
> Yes, that might prevent people looking into to much possibilities of its
> usage.

OK, both done.

Cheers
---Dave

_______________________________________________
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] 205+ messages in thread

* Re: [PATCH v5 22/26] KVM: arm64/sve: Add pseudo-register for the guest's vector lengths
  2019-03-01 13:28         ` Julien Thierry
@ 2019-03-01 14:55           ` Dave Martin
  -1 siblings, 0 replies; 205+ messages in thread
From: Dave Martin @ 2019-03-01 14:55 UTC (permalink / raw)
  To: Julien Thierry
  Cc: Okamoto Takayuki, Christoffer Dall, Ard Biesheuvel, Marc Zyngier,
	Catalin Marinas, Will Deacon, Zhang Lei, kvmarm,
	linux-arm-kernel

[FYI Peter, your views on the proposal outlined torward the end of the
mail would be appreciated.]

On Fri, Mar 01, 2019 at 01:28:19PM +0000, Julien Thierry wrote:
> 
> 
> On 26/02/2019 12:13, Dave Martin wrote:
> > On Thu, Feb 21, 2019 at 05:48:59PM +0000, Julien Thierry wrote:
> >> Hi Dave,
> >>
> >> On 18/02/2019 19:52, Dave Martin wrote:
> >>> This patch adds a new pseudo-register KVM_REG_ARM64_SVE_VLS to
> >>> allow userspace to set and query the set of vector lengths visible
> >>> to the guest, along with corresponding storage in struct
> >>> kvm_vcpu_arch.
> >>>
> >>> In the future, multiple register slices per SVE register may be
> >>> visible through the ioctl interface.  Once the set of slices has
> >>> been determined we would not be able to allow the vector length set
> >>> to be changed any more, in order to avoid userspace seeing
> >>> inconsistent sets of registers.  For this reason, this patch adds
> >>> support to track vcpu finalization explicitly, and enforce proper
> >>> sequencing of ioctls.
> >>>
> >>> The new pseudo-register is not exposed yet.  Subsequent patches
> >>> will allow SVE to be turned on for guest vcpus, making it visible.
> >>>
> >>> Signed-off-by: Dave Martin <Dave.Martin@arm.com>
> >>>
> >>> ---
> >>>
> >>> Changes since v4:
> >>>
> >>>  * Add a UAPI header comment indicating the pseudo-register status of
> >>>    KVM_REG_ARM64_SVE_VLS.
> >>>
> >>>  * Get rid of the sve_vqs[] array from struct kvm_vcpu_arch.  This
> >>>    array is pointless, because its contents must match the host's
> >>>    internal sve_vq_map anyway, up to vcpu->arch.sve_max_vl.
> >>>
> >>>    The ioctl register accessors are slow-path code, so we can decode
> >>>    or reconstruct sve_vqs[] on demand instead, for exchange with
> >>>    userspace.
> >>>
> >>>  * For compatibility with potential future architecture extensions,
> >>>    enabling vector lengths above 256 bytes for the guest is explicitly
> >>>    disallowed now (because the code for exposing additional bits
> >>>    through ioctl is currently missing).  This can be addressed later
> >>>    if/when needed.
> >>>
> >>> Note:
> >>>
> >>>  * I defensively pass an array by pointer here, to help avoid
> >>>    accidentally breaking assumptions during future maintenance.
> >>>
> >>>    Due to (over?)zealous constification, this causes the following
> >>>    sparse warning.  I think this is sparse getting confused: I am not
> >>>    relying on any kernel-specific semantics here, and GCC generates no
> >>>    warning.
> >>>
> >>> +arch/arm64/kvm/guest.c:33: warning: incorrect type in argument 1 (different modifiers)
> >>> +arch/arm64/kvm/guest.c:33:    expected unsigned long long const [usertype] ( *const vqs )[8]
> >>> +arch/arm64/kvm/guest.c:33:    got unsigned long long [usertype] ( * )[8]
> >>>
> >>> ---
> > 
> > [...]
> > 
> >>> diff --git a/arch/arm64/include/uapi/asm/kvm.h b/arch/arm64/include/uapi/asm/kvm.h
> > 
> > [...]
> > 
> >>> +static int get_sve_vls(struct kvm_vcpu *vcpu, const struct kvm_one_reg *reg)
> >>> +{
> >>> +	unsigned int max_vq, vq;
> >>> +	u64 vqs[DIV_ROUND_UP(SVE_VQ_MAX - SVE_VQ_MIN + 1, 64)];
> >>> +
> >>> +	if (WARN_ON(!sve_vl_valid(vcpu->arch.sve_max_vl)))
> >>> +		return -EINVAL;
> >>> +
> >>> +	memset(vqs, 0, sizeof(vqs));
> >>> +
> >>> +	max_vq = sve_vq_from_vl(vcpu->arch.sve_max_vl);
> >>> +	for (vq = SVE_VQ_MIN; vq <= max_vq; ++vq)
> >>> +		if (sve_vq_available(vq))
> >>> +			vqs[vq_word(vq)] |= vq_mask(vq);
> >>> +
> >>> +	BUILD_BUG_ON(sizeof(vqs) != KVM_REG_SIZE(reg->id));
> >>
> >> reg->id is not know at build time. From my understanding of
> >> BUILD_BUG_ON(), things actually ends up evaluated at runtime but I'm not
> >> sure what happens when doing sizeof(char[1- 2*0]) at runtime.
> >>
> >> Anyway, I don't think this is intended.
> > 
> > There's no runtime check: BUILD_BUG_ON() will cause compilation to fail
> > if the required condition doesn't fall out from optimisation.
> > 
> > Because of the way this function is called, reg->id is always
> > KVM_REG_ARM64_SVE_VLS, so inlining and constant propagation will make
> > this check pass (and compile to nothing).
> > 
> > We can assume a certain amount of inlining: the kernel officially can't
> > be built without optimisation.  But the precise build configuration can
> > sometimes have an effect here -- so it may not be better to rely on this
> > working for this slow-path code.
> > 
> > I'll convert these to if (WARN_ON()) return -EIO or something, or drop
> > them if I can get rid of them in other refactoring.
> > 
> > The fact that struct kvm_one_reg lacks any "size" field is rather
> > unfortunate, since it provides no explicit way for userspace to tell us
> > the size of its buffer.

I dropped the checks completely now, since they seem rather
unnecessary.

[...]

> >>>  #define SVE_REG_SLICE_SHIFT	0
> >>>  #define SVE_REG_SLICE_BITS	5
> >>>  #define SVE_REG_ID_SHIFT	(SVE_REG_SLICE_SHIFT + SVE_REG_SLICE_BITS)
> >>> @@ -297,9 +372,21 @@ static int sve_reg_region(struct sve_state_region *region,
> >>>  static int get_sve_reg(struct kvm_vcpu *vcpu, const struct kvm_one_reg *reg)
> >>>  {
> >>>  	struct sve_state_region region;
> >>> +	int ret;
> >>>  	char __user *uptr = (char __user *)reg->addr;
> >>>  
> >>> -	if (!vcpu_has_sve(vcpu) || sve_reg_region(&region, vcpu, reg))
> >>> +	if (!vcpu_has_sve(vcpu))
> >>> +		return -ENOENT;
> >>> +
> >>> +	if (reg->id == KVM_REG_ARM64_SVE_VLS)
> >>> +		return get_sve_vls(vcpu, reg);
> >>> +
> >>> +	/* Finalize the number of slices per SVE register: */
> >>> +	ret = kvm_arm_vcpu_finalize(vcpu);
> >>
> >> Having this here feels a bit random...
> > 
> > I'll have another think about this.
> > 
> > KVM_REG_ARM64_SVE_VLS certainly has nothing to do with anything except
> > SVE, and putting it in the SVE coproc space allows us to demux SVE-
> > related stuff from everything else neatly.
> > 
> > The whole "coprocessor" concept is nonsense for arm64 anyway except
> > for the sysregs (where the reg ID encodings map directly onto the
> > architecture and also align with AArch32).  So, the copro number is
> > pretty meaningless except as a demux key for related groups of
> > registers, which is how I use it here.
> > 
> > There's also no well-defined distinction between real and fake
> > registers, and no natural home for miscellaneous fakes -- all existing
> > blocks are for specific purposes such as recording the state of emulated
> > firmware APIs etc.  The SVE registers as exposed here already have no
> > direct equivalent in the architecture either, due to the padding up to
> > 2048 bits, and the presentation of FFR as addressable P-register etc.
> > 
> >> I'd suggest considering the pseudo-register outside of the SVE co-proc,
> >> as part of a set of registers that do not finalize a vcpu when accessed.

(Without a compelling alternative, I've kept KVM_ARM_ARM64_SVE_VLS in the
SVE copro for now, though this could still be changed if people feel
strongly about it.)

> > (Also, the dependency is not one-way:  _SVE_VLS is not independent
> > of finalization: quite the reverse -- it can only be written _before_
> > finalization.)
> > 
> >> All other registers (even non-sve ones) would finalize the vcpu when
> >> accessed from userland.
> > 
> > So, we could consider register to be in two classes as you suggest:
> > 
> >  * early registers
> >  * regular registers (i.e., everything else)
> > 
> > where early registers can only be written until the first access to a
> > regular register, or the first KVM_GET_REG_LIST or KVM_RUN.
> > 
> 
> That would be my personal preference, yes.

For comparison, we currently have

 * early registers (currently KVM_REG_ARM64_SVE_VLS)
 * late registers (currently KVM_REG_ARM64_SVE_{Z,P,FFR}*)
 * relaxed registers (everything else)

plus a couple of "late ioctls" that implcitly finalize (KVM_RUN,
KVM_GET_REG_LIST).

A write to an early register cannot follow a late ioctl or any access to
a late register.

I'm not convinced that's worse, but it's different.

> > This is a stricter rule than I have today: i.e., _SVE_VLS would really
> > need to be written before touching anything else.  But that may be a
> > good thing for avoiding future ABI drift.
> > 
> 
> I did notice this would be more restrictive, but I don't believe this
> should introduce shortcoming in ways to set up a VCPU. I might have
> missed some case of course.
> 
> > This may be premature factoring though.  It's not clear whether many new
> > registers like KVM_REG_ARM64_SVE_VLS will exist, or that they would have
> > compatible sequencing requirements.
> > 
> > Thoughts?
> > 
> 
> It might be premature, but I really don't like seeing this
> "vcpu_finalize" in the middle of SVE code. I think it is very easy to
> miss that touching some "sve" register suddenly finalizes the vcpu.
> I fear that some other feature/extention might need early vcpu
> finalization and that it might somehow conflict with sve depending on
> which triggers finalization first.
> 
> > 
> > Independently of this, I'll have a look at whether there's
> > a straightforward way to simplify the code flow.
> > 
> 
> I might be over-thinking it, but if there is a way to move that
> finalization call I'd prefer that.

I know what you mean, but there's not really another clear place to put
it either, right now.  Making finalization a side-effect of only KVM_RUN
and KVM_GET_REG_LIST would mean that if userspace is squirting in the
state of a migrated vcpu, a dummy KVM_GET_REG_LIST call would need to be
inserted between setting KVM_REG_ARM64_SVE_VLS and setting the other SVE
regs.

One thing we could to is get rid of the implicit finalization behaviour
completely, and require an explicit ioctl KVM_ARM_VCPU_FINALIZE to do
this.  This makes a clear barrier between reg writes that manipulate the
"physical" configuration of the vcpu, and reg reads/writes that merely
manipulate the vcpu's runtime state.  Say:

	KVM_ARM_VCPU_INIT(features[] = KVM_ARM_VCPU_SVE) -> ok
	KVM_RUN -> -EPERM (too early)
	KVM_GET_REG_LIST -> -EPERM (too early)
	...
	KVM_SET_ONE_REG(KVM_REG_ARM64_SVE_VLS) -> ok
	KVM_SET_ONE_REG(KVM_REG_ARM64_SVE_ZREG(0, 0)) -> -EPERM (too early)
	...
	KVM_RUN -> -EPERM (too early)
	...
	KVM_ARM_VCPU_FINALIZE -> ok
	KVM_ARM_VCPU_FINALIZE -> -EPERM (too late)
	...
	KVM_REG_REG_LIST -> ok
	KVM_SET_ONE_REG(KVM_REG_ARM64_SVE_VLS) -> -EPERM (too late)
	KVM_SET_ONE_REG(KVM_REG_ARM64_SVE_ZREG(0, 0)) -> ok
	KVM_RUN -> ok
	KVM_ARM_VCPU_FINALIZE -> -EPERM (too late)

This would change all existing kvm_arm_vcpu_finalize() calls to

	if (!kvm_arm_vcpu_finalized())
		return -EPERM;

(or similar).
	
Without an affected vcpu feature enabled, for backwards compatibility
we would not require the KVM_ARM_VCPU_FINALIZE call (or perhaps even
forbid it, since userspace that wants to backwards compatible cannot
use the new ioctl anyway.  I'm in two minds about this.  Either way,
calling _FINALIZE on an old kvm is harmless, so long as userspace knows
to ignore this failure case.)

The backwards-compatible flow would be:

	KVM_ARM_VCPU_INIT(features[] = 0) -> ok
	...
	KVM_ARM_VCPU_FINALIZE -> ok (or -EPERM)
	...
	KVM_RUN -> ok
	KVM_ARM_VCPU_FINALIZE -> -EPERM (too late)


Thoughts?

I may not have time to rework this for -rc1, and being a late ABI
change I'd like to get others' views on it before heading too far into
the tunnel.

Cheers
---Dave

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

* Re: [PATCH v5 22/26] KVM: arm64/sve: Add pseudo-register for the guest's vector lengths
@ 2019-03-01 14:55           ` Dave Martin
  0 siblings, 0 replies; 205+ messages in thread
From: Dave Martin @ 2019-03-01 14:55 UTC (permalink / raw)
  To: Julien Thierry
  Cc: Peter Maydell, Okamoto Takayuki, Christoffer Dall,
	Ard Biesheuvel, Marc Zyngier, Catalin Marinas, Will Deacon,
	Zhang Lei, kvmarm, linux-arm-kernel

[FYI Peter, your views on the proposal outlined torward the end of the
mail would be appreciated.]

On Fri, Mar 01, 2019 at 01:28:19PM +0000, Julien Thierry wrote:
> 
> 
> On 26/02/2019 12:13, Dave Martin wrote:
> > On Thu, Feb 21, 2019 at 05:48:59PM +0000, Julien Thierry wrote:
> >> Hi Dave,
> >>
> >> On 18/02/2019 19:52, Dave Martin wrote:
> >>> This patch adds a new pseudo-register KVM_REG_ARM64_SVE_VLS to
> >>> allow userspace to set and query the set of vector lengths visible
> >>> to the guest, along with corresponding storage in struct
> >>> kvm_vcpu_arch.
> >>>
> >>> In the future, multiple register slices per SVE register may be
> >>> visible through the ioctl interface.  Once the set of slices has
> >>> been determined we would not be able to allow the vector length set
> >>> to be changed any more, in order to avoid userspace seeing
> >>> inconsistent sets of registers.  For this reason, this patch adds
> >>> support to track vcpu finalization explicitly, and enforce proper
> >>> sequencing of ioctls.
> >>>
> >>> The new pseudo-register is not exposed yet.  Subsequent patches
> >>> will allow SVE to be turned on for guest vcpus, making it visible.
> >>>
> >>> Signed-off-by: Dave Martin <Dave.Martin@arm.com>
> >>>
> >>> ---
> >>>
> >>> Changes since v4:
> >>>
> >>>  * Add a UAPI header comment indicating the pseudo-register status of
> >>>    KVM_REG_ARM64_SVE_VLS.
> >>>
> >>>  * Get rid of the sve_vqs[] array from struct kvm_vcpu_arch.  This
> >>>    array is pointless, because its contents must match the host's
> >>>    internal sve_vq_map anyway, up to vcpu->arch.sve_max_vl.
> >>>
> >>>    The ioctl register accessors are slow-path code, so we can decode
> >>>    or reconstruct sve_vqs[] on demand instead, for exchange with
> >>>    userspace.
> >>>
> >>>  * For compatibility with potential future architecture extensions,
> >>>    enabling vector lengths above 256 bytes for the guest is explicitly
> >>>    disallowed now (because the code for exposing additional bits
> >>>    through ioctl is currently missing).  This can be addressed later
> >>>    if/when needed.
> >>>
> >>> Note:
> >>>
> >>>  * I defensively pass an array by pointer here, to help avoid
> >>>    accidentally breaking assumptions during future maintenance.
> >>>
> >>>    Due to (over?)zealous constification, this causes the following
> >>>    sparse warning.  I think this is sparse getting confused: I am not
> >>>    relying on any kernel-specific semantics here, and GCC generates no
> >>>    warning.
> >>>
> >>> +arch/arm64/kvm/guest.c:33: warning: incorrect type in argument 1 (different modifiers)
> >>> +arch/arm64/kvm/guest.c:33:    expected unsigned long long const [usertype] ( *const vqs )[8]
> >>> +arch/arm64/kvm/guest.c:33:    got unsigned long long [usertype] ( * )[8]
> >>>
> >>> ---
> > 
> > [...]
> > 
> >>> diff --git a/arch/arm64/include/uapi/asm/kvm.h b/arch/arm64/include/uapi/asm/kvm.h
> > 
> > [...]
> > 
> >>> +static int get_sve_vls(struct kvm_vcpu *vcpu, const struct kvm_one_reg *reg)
> >>> +{
> >>> +	unsigned int max_vq, vq;
> >>> +	u64 vqs[DIV_ROUND_UP(SVE_VQ_MAX - SVE_VQ_MIN + 1, 64)];
> >>> +
> >>> +	if (WARN_ON(!sve_vl_valid(vcpu->arch.sve_max_vl)))
> >>> +		return -EINVAL;
> >>> +
> >>> +	memset(vqs, 0, sizeof(vqs));
> >>> +
> >>> +	max_vq = sve_vq_from_vl(vcpu->arch.sve_max_vl);
> >>> +	for (vq = SVE_VQ_MIN; vq <= max_vq; ++vq)
> >>> +		if (sve_vq_available(vq))
> >>> +			vqs[vq_word(vq)] |= vq_mask(vq);
> >>> +
> >>> +	BUILD_BUG_ON(sizeof(vqs) != KVM_REG_SIZE(reg->id));
> >>
> >> reg->id is not know at build time. From my understanding of
> >> BUILD_BUG_ON(), things actually ends up evaluated at runtime but I'm not
> >> sure what happens when doing sizeof(char[1- 2*0]) at runtime.
> >>
> >> Anyway, I don't think this is intended.
> > 
> > There's no runtime check: BUILD_BUG_ON() will cause compilation to fail
> > if the required condition doesn't fall out from optimisation.
> > 
> > Because of the way this function is called, reg->id is always
> > KVM_REG_ARM64_SVE_VLS, so inlining and constant propagation will make
> > this check pass (and compile to nothing).
> > 
> > We can assume a certain amount of inlining: the kernel officially can't
> > be built without optimisation.  But the precise build configuration can
> > sometimes have an effect here -- so it may not be better to rely on this
> > working for this slow-path code.
> > 
> > I'll convert these to if (WARN_ON()) return -EIO or something, or drop
> > them if I can get rid of them in other refactoring.
> > 
> > The fact that struct kvm_one_reg lacks any "size" field is rather
> > unfortunate, since it provides no explicit way for userspace to tell us
> > the size of its buffer.

I dropped the checks completely now, since they seem rather
unnecessary.

[...]

> >>>  #define SVE_REG_SLICE_SHIFT	0
> >>>  #define SVE_REG_SLICE_BITS	5
> >>>  #define SVE_REG_ID_SHIFT	(SVE_REG_SLICE_SHIFT + SVE_REG_SLICE_BITS)
> >>> @@ -297,9 +372,21 @@ static int sve_reg_region(struct sve_state_region *region,
> >>>  static int get_sve_reg(struct kvm_vcpu *vcpu, const struct kvm_one_reg *reg)
> >>>  {
> >>>  	struct sve_state_region region;
> >>> +	int ret;
> >>>  	char __user *uptr = (char __user *)reg->addr;
> >>>  
> >>> -	if (!vcpu_has_sve(vcpu) || sve_reg_region(&region, vcpu, reg))
> >>> +	if (!vcpu_has_sve(vcpu))
> >>> +		return -ENOENT;
> >>> +
> >>> +	if (reg->id == KVM_REG_ARM64_SVE_VLS)
> >>> +		return get_sve_vls(vcpu, reg);
> >>> +
> >>> +	/* Finalize the number of slices per SVE register: */
> >>> +	ret = kvm_arm_vcpu_finalize(vcpu);
> >>
> >> Having this here feels a bit random...
> > 
> > I'll have another think about this.
> > 
> > KVM_REG_ARM64_SVE_VLS certainly has nothing to do with anything except
> > SVE, and putting it in the SVE coproc space allows us to demux SVE-
> > related stuff from everything else neatly.
> > 
> > The whole "coprocessor" concept is nonsense for arm64 anyway except
> > for the sysregs (where the reg ID encodings map directly onto the
> > architecture and also align with AArch32).  So, the copro number is
> > pretty meaningless except as a demux key for related groups of
> > registers, which is how I use it here.
> > 
> > There's also no well-defined distinction between real and fake
> > registers, and no natural home for miscellaneous fakes -- all existing
> > blocks are for specific purposes such as recording the state of emulated
> > firmware APIs etc.  The SVE registers as exposed here already have no
> > direct equivalent in the architecture either, due to the padding up to
> > 2048 bits, and the presentation of FFR as addressable P-register etc.
> > 
> >> I'd suggest considering the pseudo-register outside of the SVE co-proc,
> >> as part of a set of registers that do not finalize a vcpu when accessed.

(Without a compelling alternative, I've kept KVM_ARM_ARM64_SVE_VLS in the
SVE copro for now, though this could still be changed if people feel
strongly about it.)

> > (Also, the dependency is not one-way:  _SVE_VLS is not independent
> > of finalization: quite the reverse -- it can only be written _before_
> > finalization.)
> > 
> >> All other registers (even non-sve ones) would finalize the vcpu when
> >> accessed from userland.
> > 
> > So, we could consider register to be in two classes as you suggest:
> > 
> >  * early registers
> >  * regular registers (i.e., everything else)
> > 
> > where early registers can only be written until the first access to a
> > regular register, or the first KVM_GET_REG_LIST or KVM_RUN.
> > 
> 
> That would be my personal preference, yes.

For comparison, we currently have

 * early registers (currently KVM_REG_ARM64_SVE_VLS)
 * late registers (currently KVM_REG_ARM64_SVE_{Z,P,FFR}*)
 * relaxed registers (everything else)

plus a couple of "late ioctls" that implcitly finalize (KVM_RUN,
KVM_GET_REG_LIST).

A write to an early register cannot follow a late ioctl or any access to
a late register.

I'm not convinced that's worse, but it's different.

> > This is a stricter rule than I have today: i.e., _SVE_VLS would really
> > need to be written before touching anything else.  But that may be a
> > good thing for avoiding future ABI drift.
> > 
> 
> I did notice this would be more restrictive, but I don't believe this
> should introduce shortcoming in ways to set up a VCPU. I might have
> missed some case of course.
> 
> > This may be premature factoring though.  It's not clear whether many new
> > registers like KVM_REG_ARM64_SVE_VLS will exist, or that they would have
> > compatible sequencing requirements.
> > 
> > Thoughts?
> > 
> 
> It might be premature, but I really don't like seeing this
> "vcpu_finalize" in the middle of SVE code. I think it is very easy to
> miss that touching some "sve" register suddenly finalizes the vcpu.
> I fear that some other feature/extention might need early vcpu
> finalization and that it might somehow conflict with sve depending on
> which triggers finalization first.
> 
> > 
> > Independently of this, I'll have a look at whether there's
> > a straightforward way to simplify the code flow.
> > 
> 
> I might be over-thinking it, but if there is a way to move that
> finalization call I'd prefer that.

I know what you mean, but there's not really another clear place to put
it either, right now.  Making finalization a side-effect of only KVM_RUN
and KVM_GET_REG_LIST would mean that if userspace is squirting in the
state of a migrated vcpu, a dummy KVM_GET_REG_LIST call would need to be
inserted between setting KVM_REG_ARM64_SVE_VLS and setting the other SVE
regs.

One thing we could to is get rid of the implicit finalization behaviour
completely, and require an explicit ioctl KVM_ARM_VCPU_FINALIZE to do
this.  This makes a clear barrier between reg writes that manipulate the
"physical" configuration of the vcpu, and reg reads/writes that merely
manipulate the vcpu's runtime state.  Say:

	KVM_ARM_VCPU_INIT(features[] = KVM_ARM_VCPU_SVE) -> ok
	KVM_RUN -> -EPERM (too early)
	KVM_GET_REG_LIST -> -EPERM (too early)
	...
	KVM_SET_ONE_REG(KVM_REG_ARM64_SVE_VLS) -> ok
	KVM_SET_ONE_REG(KVM_REG_ARM64_SVE_ZREG(0, 0)) -> -EPERM (too early)
	...
	KVM_RUN -> -EPERM (too early)
	...
	KVM_ARM_VCPU_FINALIZE -> ok
	KVM_ARM_VCPU_FINALIZE -> -EPERM (too late)
	...
	KVM_REG_REG_LIST -> ok
	KVM_SET_ONE_REG(KVM_REG_ARM64_SVE_VLS) -> -EPERM (too late)
	KVM_SET_ONE_REG(KVM_REG_ARM64_SVE_ZREG(0, 0)) -> ok
	KVM_RUN -> ok
	KVM_ARM_VCPU_FINALIZE -> -EPERM (too late)

This would change all existing kvm_arm_vcpu_finalize() calls to

	if (!kvm_arm_vcpu_finalized())
		return -EPERM;

(or similar).
	
Without an affected vcpu feature enabled, for backwards compatibility
we would not require the KVM_ARM_VCPU_FINALIZE call (or perhaps even
forbid it, since userspace that wants to backwards compatible cannot
use the new ioctl anyway.  I'm in two minds about this.  Either way,
calling _FINALIZE on an old kvm is harmless, so long as userspace knows
to ignore this failure case.)

The backwards-compatible flow would be:

	KVM_ARM_VCPU_INIT(features[] = 0) -> ok
	...
	KVM_ARM_VCPU_FINALIZE -> ok (or -EPERM)
	...
	KVM_RUN -> ok
	KVM_ARM_VCPU_FINALIZE -> -EPERM (too late)


Thoughts?

I may not have time to rework this for -rc1, and being a late ABI
change I'd like to get others' views on it before heading too far into
the tunnel.

Cheers
---Dave

_______________________________________________
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] 205+ messages in thread

* RE: [PATCH v5 00/26] KVM: arm64: SVE guest support
  2019-02-18 19:52 ` Dave Martin
                   ` (27 preceding siblings ...)
  (?)
@ 2019-03-03  2:40 ` Zhang, Lei
  2019-03-05  9:47     ` Dave Martin
  -1 siblings, 1 reply; 205+ messages in thread
From: Zhang, Lei @ 2019-03-03  2:40 UTC (permalink / raw)
  To: 'Dave Martin', kvmarm
  Cc: Peter Maydell, Okamoto, Takayuki, Christoffer Dall,
	Ard Biesheuvel, Marc Zyngier, Catalin Marinas, Will Deacon,
	Julien Grall, Alex Bennée, linux-arm-kernel

[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #1: Type: text/plain; charset="gb2312", Size: 7230 bytes --]

Hi Dave,

> -----Original Message-----
> From: linux-arm-kernel <linux-arm-kernel-bounces@lists.infradead.org> On
> Behalf Of Dave Martin
> Sent: Tuesday, February 19, 2019 4:52 AM
> To: kvmarm@lists.cs.columbia.edu
> Cc: Peter Maydell <peter.maydell@linaro.org>; Okamoto, Takayuki/Œù±¾ ¸ßÐÒ
> <tokamoto@jp.fujitsu.com>; Christoffer Dall <cdall@kernel.org>; Ard
> Biesheuvel <ard.biesheuvel@linaro.org>; Marc Zyngier
> <marc.zyngier@arm.com>; Catalin Marinas <catalin.marinas@arm.com>; Will
> Deacon <will.deacon@arm.com>; Zhang, Lei/ˆ À×
> <zhang.lei@jp.fujitsu.com>; Julien Grall <julien.grall@arm.com>; Alex Benn¨¦e
> <alex.bennee@linaro.org>; linux-arm-kernel@lists.infradead.org
> Subject: [PATCH v5 00/26] KVM: arm64: SVE guest support
> 
> This series implements support for allowing KVM guests to use the Arm
> Scalable Vector Extension (SVE), superseding the previous v4 series [1].
> 
> The patches are also available on a branch for reviewer convenience. [2]
> 
> The patches are based on v5.0-rc6.
> 
> They depend on another small series currently under review [3] that does a bit
> of relevant refactoring (as well as fixing an anomaly not directly related to this
> series).  A base branch [4] is provided so that reviewers don't need to hunt
> down both series independently.
[>] 
I tested the patch on A64FX chip which SVE feature had been implemented.
All of tests have been passed.
Please add follows :
Tested-by: zhang.lei <zhang.lei@jp.fujitsu.com>

> 
> This series contains no major update except for the removal of multiple register
> slice support in the user register access ioctls.  The ABI is kept as-is so that
> this functionality can be added back in later on if/when needed.  ioctl access
> to nonexistent slices now yields ENOENT, which is more consistent with the
> notion of an absent register.
> 
> For a description of minor updates, see the individual patches.
> 
> 
> Functionality testing and stress-testing has been done, using a hacked-up
> kvmtool [5]:
> 
>  * Arm Fast Model: full testing of arm64 defconfig, including running
>    non-SVE and SVE guests with mixtures of vector lengths.  limited
>    testing of other configurations.
> 
>  * ThunderX2: basic testing of arm64 defconfig, including booting guests
>    (no SVE support on this hardware).
> 
>  * Full build-bisect testing and sparse testing of every commit done
>    for arm64 (defconfig, CONFIG_ARM64_SVE=n, CONFIG_KVM=n) and arm
>    (multi_v7_defconfig, CONFIG_KVM=y).  One new sparse warning,
>    probably spurious (see note in patch 22).
> 
> 
> AArch32 host testing is pending.  I will ping this series with a reply to the cover
> letter when that testing has been completed.
> 
> 
> Known issues:
> 
>  * **Possible bug**
> 
>    SVE state corruption has been in the host when running on the Arm
>    Fast Model.
> 
>    After some investigation with the model engineers, it appears that
>    there may be a model bug in this area.  I have also obtained detailed
>    trace of failure cases, which is also suggestive of a model bug.  No
>    clear evidence has been obtained to show that there is a bug in
>    Linux, so far.
> 
>    All available evidence suggests that this bug will not affect non-SVE
>    hardware: the symptom is unexpected zeroing of bits 128 and above of
>    the vector registers (which don't exist prior to SVE).
> 
>  * kvmtool support is not mature
> 
> 
> [1] [RFC PATCH v4 00/24] KVM: arm64: SVE guest support
> https://lists.cs.columbia.edu/pipermail/kvmarm/2019-January/034134.html
> 
> [2] This series in git:
> http://linux-arm.org/git?p=linux-dm.git;a=shortlog;h=refs/heads/sve-kvm/v5
> /head
> git://linux-arm.org/linux-dm.git sve-kvm/v5/head
> 
> [3] [PATCH v2 0/2] Fix KVM_GET_REG_LIST invalid register ID regression
> https://lists.cs.columbia.edu/pipermail/kvmarm/2018-December/033810.htm
> l
> 
> [4] Base of this series in git:
> http://linux-arm.org/git?p=linux-dm.git;a=shortlog;h=refs/heads/sve-kvm/v5
> /base
> git://linux-arm.org/linux-dm.git sve-kvm/v5/base
> 
> [5] [RFC PATCH 00/12] arm64: SVE guest support test hacks
> https://lists.cs.columbia.edu/pipermail/kvmarm/2019-January/034162.html
> 
> 
> Dave Martin (26):
>   KVM: Documentation: Document arm64 core registers in detail
>   arm64: fpsimd: Always set TIF_FOREIGN_FPSTATE on task state flush
>   KVM: arm64: Delete orphaned declaration for __fpsimd_enabled()
>   KVM: arm64: Refactor kvm_arm_num_regs() for easier maintenance
>   KVM: arm64: Add missing #include of <linux/bitmap.h> to kvm_host.h
>   arm64/sve: Check SVE virtualisability
>   arm64/sve: Clarify role of the VQ map maintenance functions
>   arm64/sve: Enable SVE state tracking for non-task contexts
>   KVM: arm64: Add a vcpu flag to control SVE visibility for the guest
>   KVM: arm64: Propagate vcpu into read_id_reg()
>   KVM: arm64: Extend reset_unknown() to handle mixed RES0/UNKNOWN
>     registers
>   KVM: arm64: Support runtime sysreg visibility filtering
>   KVM: arm64/sve: System register context switch and access support
>   KVM: arm64/sve: Context switch the SVE registers
>   KVM: Allow 2048-bit register access via ioctl interface
>   KVM: arm64: Add missing #include of <linux/string.h> in guest.c
>   KVM: arm64: Reject ioctl access to FPSIMD V-regs on SVE vcpus
>   KVM: arm64/sve: Add SVE support to register access ioctl interface
>   KVM: arm64: Enumerate SVE register indices for KVM_GET_REG_LIST
>   arm64/sve: In-kernel vector length availability query interface
>   KVM: arm/arm64: Add hook to finalize the vcpu configuration
>   KVM: arm64/sve: Add pseudo-register for the guest's vector lengths
>   KVM: arm64/sve: Allow userspace to enable SVE for vcpus
>   KVM: arm64: Add a capabillity to advertise SVE support
>   KVM: Document errors for KVM_GET_ONE_REG and KVM_SET_ONE_REG
>   KVM: arm64/sve: Document KVM API extensions for SVE
> 
>  Documentation/virtual/kvm/api.txt |  93 ++++++++++
>  arch/arm/include/asm/kvm_host.h   |   4 +
>  arch/arm64/include/asm/fpsimd.h   |  33 +++-
>  arch/arm64/include/asm/kvm_host.h |  35 +++-
>  arch/arm64/include/asm/kvm_hyp.h  |   1 -
>  arch/arm64/include/asm/sysreg.h   |   3 +
>  arch/arm64/include/uapi/asm/kvm.h |  22 +++
>  arch/arm64/kernel/cpufeature.c    |   2 +-
>  arch/arm64/kernel/fpsimd.c        | 172 +++++++++++++------
>  arch/arm64/kernel/signal.c        |   5 -
>  arch/arm64/kvm/fpsimd.c           |  17 +-
>  arch/arm64/kvm/guest.c            | 348
> +++++++++++++++++++++++++++++++++++---
>  arch/arm64/kvm/hyp/switch.c       |  69 ++++++--
>  arch/arm64/kvm/reset.c            |  87 +++++++++-
>  arch/arm64/kvm/sys_regs.c         | 144 ++++++++++++++--
>  arch/arm64/kvm/sys_regs.h         |  24 ++-
>  include/uapi/linux/kvm.h          |   2 +
>  virt/kvm/arm/arm.c                |   8 +
>  18 files changed, 944 insertions(+), 125 deletions(-)
> 
> --
> 2.1.4
> 
> 
> _______________________________________________
> linux-arm-kernel mailing list
> linux-arm-kernel@lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel


Thanks,
Zhang Lei

[-- Attachment #2: Type: text/plain, Size: 176 bytes --]

_______________________________________________
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] 205+ messages in thread

* Re: [PATCH v5 00/26] KVM: arm64: SVE guest support
  2019-03-03  2:40 ` Zhang, Lei
@ 2019-03-05  9:47     ` Dave Martin
  0 siblings, 0 replies; 205+ messages in thread
From: Dave Martin @ 2019-03-05  9:47 UTC (permalink / raw)
  To: Zhang, Lei
  Cc: Okamoto, Takayuki, Christoffer Dall, Ard Biesheuvel,
	Marc Zyngier, Catalin Marinas, Will Deacon, Julien Grall, kvmarm,
	linux-arm-kernel

On Sun, Mar 03, 2019 at 02:40:57AM +0000, Zhang, Lei wrote:
> Hi Dave,
> 
> > -----Original Message-----
> > From: linux-arm-kernel <linux-arm-kernel-bounces@lists.infradead.org> On
> > Behalf Of Dave Martin
> > Sent: Tuesday, February 19, 2019 4:52 AM
> > To: kvmarm@lists.cs.columbia.edu
> > Cc: Peter Maydell <peter.maydell@linaro.org>; Okamoto, Takayuki/岡本 高幸
> > <tokamoto@jp.fujitsu.com>; Christoffer Dall <cdall@kernel.org>; Ard
> > Biesheuvel <ard.biesheuvel@linaro.org>; Marc Zyngier
> > <marc.zyngier@arm.com>; Catalin Marinas <catalin.marinas@arm.com>; Will
> > Deacon <will.deacon@arm.com>; Zhang, Lei/張 雷
> > <zhang.lei@jp.fujitsu.com>; Julien Grall <julien.grall@arm.com>; Alex Bennée
> > <alex.bennee@linaro.org>; linux-arm-kernel@lists.infradead.org
> > Subject: [PATCH v5 00/26] KVM: arm64: SVE guest support
> > 
> > This series implements support for allowing KVM guests to use the Arm
> > Scalable Vector Extension (SVE), superseding the previous v4 series [1].
> > 
> > The patches are also available on a branch for reviewer convenience. [2]
> > 
> > The patches are based on v5.0-rc6.
> > 
> > They depend on another small series currently under review [3] that does a bit
> > of relevant refactoring (as well as fixing an anomaly not directly related to this
> > series).  A base branch [4] is provided so that reviewers don't need to hunt
> > down both series independently.
> [>] 
> I tested the patch on A64FX chip which SVE feature had been implemented.
> All of tests have been passed.
> Please add follows :
> Tested-by: zhang.lei <zhang.lei@jp.fujitsu.com>

Thanks for this!

There will be at least one more iteration of this series before it is
final, so it would be good if you can test again when I repost.

I'll make sure that you are on Cc.

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

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

* Re: [PATCH v5 00/26] KVM: arm64: SVE guest support
@ 2019-03-05  9:47     ` Dave Martin
  0 siblings, 0 replies; 205+ messages in thread
From: Dave Martin @ 2019-03-05  9:47 UTC (permalink / raw)
  To: Zhang, Lei
  Cc: Peter Maydell, Okamoto, Takayuki, Christoffer Dall,
	Ard Biesheuvel, Marc Zyngier, Catalin Marinas, Will Deacon,
	Julien Grall, Alex Bennée, kvmarm, linux-arm-kernel

On Sun, Mar 03, 2019 at 02:40:57AM +0000, Zhang, Lei wrote:
> Hi Dave,
> 
> > -----Original Message-----
> > From: linux-arm-kernel <linux-arm-kernel-bounces@lists.infradead.org> On
> > Behalf Of Dave Martin
> > Sent: Tuesday, February 19, 2019 4:52 AM
> > To: kvmarm@lists.cs.columbia.edu
> > Cc: Peter Maydell <peter.maydell@linaro.org>; Okamoto, Takayuki/岡本 高幸
> > <tokamoto@jp.fujitsu.com>; Christoffer Dall <cdall@kernel.org>; Ard
> > Biesheuvel <ard.biesheuvel@linaro.org>; Marc Zyngier
> > <marc.zyngier@arm.com>; Catalin Marinas <catalin.marinas@arm.com>; Will
> > Deacon <will.deacon@arm.com>; Zhang, Lei/張 雷
> > <zhang.lei@jp.fujitsu.com>; Julien Grall <julien.grall@arm.com>; Alex Bennée
> > <alex.bennee@linaro.org>; linux-arm-kernel@lists.infradead.org
> > Subject: [PATCH v5 00/26] KVM: arm64: SVE guest support
> > 
> > This series implements support for allowing KVM guests to use the Arm
> > Scalable Vector Extension (SVE), superseding the previous v4 series [1].
> > 
> > The patches are also available on a branch for reviewer convenience. [2]
> > 
> > The patches are based on v5.0-rc6.
> > 
> > They depend on another small series currently under review [3] that does a bit
> > of relevant refactoring (as well as fixing an anomaly not directly related to this
> > series).  A base branch [4] is provided so that reviewers don't need to hunt
> > down both series independently.
> [>] 
> I tested the patch on A64FX chip which SVE feature had been implemented.
> All of tests have been passed.
> Please add follows :
> Tested-by: zhang.lei <zhang.lei@jp.fujitsu.com>

Thanks for this!

There will be at least one more iteration of this series before it is
final, so it would be good if you can test again when I repost.

I'll make sure that you are on Cc.

Cheers
---Dave

_______________________________________________
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] 205+ messages in thread

* Re: [PATCH v5 22/26] KVM: arm64/sve: Add pseudo-register for the guest's vector lengths
  2019-03-01 14:55           ` Dave Martin
@ 2019-03-07 13:47             ` Marc Zyngier
  -1 siblings, 0 replies; 205+ messages in thread
From: Marc Zyngier @ 2019-03-07 13:47 UTC (permalink / raw)
  To: Dave Martin, Julien Thierry
  Cc: Okamoto Takayuki, Christoffer Dall, Ard Biesheuvel,
	Catalin Marinas, Will Deacon, Zhang Lei, kvmarm,
	linux-arm-kernel

Hi Dave,

On 01/03/2019 14:55, Dave Martin wrote:
> [FYI Peter, your views on the proposal outlined torward the end of the
> mail would be appreciated.]
> 
> On Fri, Mar 01, 2019 at 01:28:19PM +0000, Julien Thierry wrote:

[...]

>> I might be over-thinking it, but if there is a way to move that
>> finalization call I'd prefer that.
> 
> I know what you mean, but there's not really another clear place to put
> it either, right now.  Making finalization a side-effect of only KVM_RUN
> and KVM_GET_REG_LIST would mean that if userspace is squirting in the
> state of a migrated vcpu, a dummy KVM_GET_REG_LIST call would need to be
> inserted between setting KVM_REG_ARM64_SVE_VLS and setting the other SVE
> regs.
> 
> One thing we could to is get rid of the implicit finalization behaviour
> completely, and require an explicit ioctl KVM_ARM_VCPU_FINALIZE to do

+1. In the past, implicit finalization has been a major pain, and the
"implicit GICv2 configuration" has been an absolute disaster.

> this.  This makes a clear barrier between reg writes that manipulate the
> "physical" configuration of the vcpu, and reg reads/writes that merely
> manipulate the vcpu's runtime state.  Say:
> 
> 	KVM_ARM_VCPU_INIT(features[] = KVM_ARM_VCPU_SVE) -> ok
> 	KVM_RUN -> -EPERM (too early)
> 	KVM_GET_REG_LIST -> -EPERM (too early)
> 	...
> 	KVM_SET_ONE_REG(KVM_REG_ARM64_SVE_VLS) -> ok
> 	KVM_SET_ONE_REG(KVM_REG_ARM64_SVE_ZREG(0, 0)) -> -EPERM (too early)
> 	...
> 	KVM_RUN -> -EPERM (too early)
> 	...
> 	KVM_ARM_VCPU_FINALIZE -> ok
> 	KVM_ARM_VCPU_FINALIZE -> -EPERM (too late)
> 	...
> 	KVM_REG_REG_LIST -> ok
> 	KVM_SET_ONE_REG(KVM_REG_ARM64_SVE_VLS) -> -EPERM (too late)
> 	KVM_SET_ONE_REG(KVM_REG_ARM64_SVE_ZREG(0, 0)) -> ok
> 	KVM_RUN -> ok
> 	KVM_ARM_VCPU_FINALIZE -> -EPERM (too late)
> 
> This would change all existing kvm_arm_vcpu_finalize() calls to
> 
> 	if (!kvm_arm_vcpu_finalized())
> 		return -EPERM;
> 
> (or similar).

I find this rather compelling, assuming we can easily map features that
are associated to finalization.

> 	
> Without an affected vcpu feature enabled, for backwards compatibility
> we would not require the KVM_ARM_VCPU_FINALIZE call (or perhaps even
> forbid it, since userspace that wants to backwards compatible cannot
> use the new ioctl anyway.  I'm in two minds about this.  Either way,
> calling _FINALIZE on an old kvm is harmless, so long as userspace knows
> to ignore this failure case.)
> 
> The backwards-compatible flow would be:
> 
> 	KVM_ARM_VCPU_INIT(features[] = 0) -> ok
> 	...
> 	KVM_ARM_VCPU_FINALIZE -> ok (or -EPERM)
> 	...
> 	KVM_RUN -> ok
> 	KVM_ARM_VCPU_FINALIZE -> -EPERM (too late)
> 
> 
> Thoughts?

This goes back to the above question: how do we ensure that userspace
knows which features are subject to being finalized. As it is currently
described, KVM_ARM_VCPU_FINALIZE isn't qualified by a feature set, nor
can the kernel report what feature flags requires being finalized. It is
also unclear to me whether all "finalizable" features would have the
same init cycle.

So either we take the simplest approach and make KVM_ARM_VCPU_FINALIZE
strictly SVE specific (renaming it in the process), or it takes some
argument that allow specifying the feature set it applies to. Maybe we
can get away with the kernel not reporting which features require to be
finalized as long that it is clearly documented.

> I may not have time to rework this for -rc1, and being a late ABI
> change I'd like to get others' views on it before heading too far into
> the tunnel.

Please do your best to have something as close as possible to the final
version for -rc1. From that point on, I'd expect changes to be mostly
cosmetic.

Thanks,

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

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

* Re: [PATCH v5 22/26] KVM: arm64/sve: Add pseudo-register for the guest's vector lengths
@ 2019-03-07 13:47             ` Marc Zyngier
  0 siblings, 0 replies; 205+ messages in thread
From: Marc Zyngier @ 2019-03-07 13:47 UTC (permalink / raw)
  To: Dave Martin, Julien Thierry
  Cc: Peter Maydell, Okamoto Takayuki, Christoffer Dall,
	Ard Biesheuvel, Catalin Marinas, Will Deacon, Zhang Lei, kvmarm,
	linux-arm-kernel

Hi Dave,

On 01/03/2019 14:55, Dave Martin wrote:
> [FYI Peter, your views on the proposal outlined torward the end of the
> mail would be appreciated.]
> 
> On Fri, Mar 01, 2019 at 01:28:19PM +0000, Julien Thierry wrote:

[...]

>> I might be over-thinking it, but if there is a way to move that
>> finalization call I'd prefer that.
> 
> I know what you mean, but there's not really another clear place to put
> it either, right now.  Making finalization a side-effect of only KVM_RUN
> and KVM_GET_REG_LIST would mean that if userspace is squirting in the
> state of a migrated vcpu, a dummy KVM_GET_REG_LIST call would need to be
> inserted between setting KVM_REG_ARM64_SVE_VLS and setting the other SVE
> regs.
> 
> One thing we could to is get rid of the implicit finalization behaviour
> completely, and require an explicit ioctl KVM_ARM_VCPU_FINALIZE to do

+1. In the past, implicit finalization has been a major pain, and the
"implicit GICv2 configuration" has been an absolute disaster.

> this.  This makes a clear barrier between reg writes that manipulate the
> "physical" configuration of the vcpu, and reg reads/writes that merely
> manipulate the vcpu's runtime state.  Say:
> 
> 	KVM_ARM_VCPU_INIT(features[] = KVM_ARM_VCPU_SVE) -> ok
> 	KVM_RUN -> -EPERM (too early)
> 	KVM_GET_REG_LIST -> -EPERM (too early)
> 	...
> 	KVM_SET_ONE_REG(KVM_REG_ARM64_SVE_VLS) -> ok
> 	KVM_SET_ONE_REG(KVM_REG_ARM64_SVE_ZREG(0, 0)) -> -EPERM (too early)
> 	...
> 	KVM_RUN -> -EPERM (too early)
> 	...
> 	KVM_ARM_VCPU_FINALIZE -> ok
> 	KVM_ARM_VCPU_FINALIZE -> -EPERM (too late)
> 	...
> 	KVM_REG_REG_LIST -> ok
> 	KVM_SET_ONE_REG(KVM_REG_ARM64_SVE_VLS) -> -EPERM (too late)
> 	KVM_SET_ONE_REG(KVM_REG_ARM64_SVE_ZREG(0, 0)) -> ok
> 	KVM_RUN -> ok
> 	KVM_ARM_VCPU_FINALIZE -> -EPERM (too late)
> 
> This would change all existing kvm_arm_vcpu_finalize() calls to
> 
> 	if (!kvm_arm_vcpu_finalized())
> 		return -EPERM;
> 
> (or similar).

I find this rather compelling, assuming we can easily map features that
are associated to finalization.

> 	
> Without an affected vcpu feature enabled, for backwards compatibility
> we would not require the KVM_ARM_VCPU_FINALIZE call (or perhaps even
> forbid it, since userspace that wants to backwards compatible cannot
> use the new ioctl anyway.  I'm in two minds about this.  Either way,
> calling _FINALIZE on an old kvm is harmless, so long as userspace knows
> to ignore this failure case.)
> 
> The backwards-compatible flow would be:
> 
> 	KVM_ARM_VCPU_INIT(features[] = 0) -> ok
> 	...
> 	KVM_ARM_VCPU_FINALIZE -> ok (or -EPERM)
> 	...
> 	KVM_RUN -> ok
> 	KVM_ARM_VCPU_FINALIZE -> -EPERM (too late)
> 
> 
> Thoughts?

This goes back to the above question: how do we ensure that userspace
knows which features are subject to being finalized. As it is currently
described, KVM_ARM_VCPU_FINALIZE isn't qualified by a feature set, nor
can the kernel report what feature flags requires being finalized. It is
also unclear to me whether all "finalizable" features would have the
same init cycle.

So either we take the simplest approach and make KVM_ARM_VCPU_FINALIZE
strictly SVE specific (renaming it in the process), or it takes some
argument that allow specifying the feature set it applies to. Maybe we
can get away with the kernel not reporting which features require to be
finalized as long that it is clearly documented.

> I may not have time to rework this for -rc1, and being a late ABI
> change I'd like to get others' views on it before heading too far into
> the tunnel.

Please do your best to have something as close as possible to the final
version for -rc1. From that point on, I'd expect changes to be mostly
cosmetic.

Thanks,

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

_______________________________________________
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] 205+ messages in thread

* Re: [PATCH v5 22/26] KVM: arm64/sve: Add pseudo-register for the guest's vector lengths
  2019-03-07 13:47             ` Marc Zyngier
@ 2019-03-07 15:30               ` Dave Martin
  -1 siblings, 0 replies; 205+ messages in thread
From: Dave Martin @ 2019-03-07 15:30 UTC (permalink / raw)
  To: Marc Zyngier
  Cc: Okamoto Takayuki, Christoffer Dall, Ard Biesheuvel,
	Catalin Marinas, Will Deacon, Zhang Lei, kvmarm,
	linux-arm-kernel

On Thu, Mar 07, 2019 at 01:47:09PM +0000, Marc Zyngier wrote:
> Hi Dave,
> 
> On 01/03/2019 14:55, Dave Martin wrote:
> > [FYI Peter, your views on the proposal outlined torward the end of the
> > mail would be appreciated.]
> > 
> > On Fri, Mar 01, 2019 at 01:28:19PM +0000, Julien Thierry wrote:
> 
> [...]
> 
> >> I might be over-thinking it, but if there is a way to move that
> >> finalization call I'd prefer that.
> > 
> > I know what you mean, but there's not really another clear place to put
> > it either, right now.  Making finalization a side-effect of only KVM_RUN
> > and KVM_GET_REG_LIST would mean that if userspace is squirting in the
> > state of a migrated vcpu, a dummy KVM_GET_REG_LIST call would need to be
> > inserted between setting KVM_REG_ARM64_SVE_VLS and setting the other SVE
> > regs.
> > 
> > One thing we could to is get rid of the implicit finalization behaviour
> > completely, and require an explicit ioctl KVM_ARM_VCPU_FINALIZE to do
> 
> +1. In the past, implicit finalization has been a major pain, and the
> "implicit GICv2 configuration" has been an absolute disaster.
> 
> > this.  This makes a clear barrier between reg writes that manipulate the
> > "physical" configuration of the vcpu, and reg reads/writes that merely
> > manipulate the vcpu's runtime state.  Say:
> > 
> > 	KVM_ARM_VCPU_INIT(features[] = KVM_ARM_VCPU_SVE) -> ok
> > 	KVM_RUN -> -EPERM (too early)
> > 	KVM_GET_REG_LIST -> -EPERM (too early)
> > 	...
> > 	KVM_SET_ONE_REG(KVM_REG_ARM64_SVE_VLS) -> ok
> > 	KVM_SET_ONE_REG(KVM_REG_ARM64_SVE_ZREG(0, 0)) -> -EPERM (too early)
> > 	...
> > 	KVM_RUN -> -EPERM (too early)
> > 	...
> > 	KVM_ARM_VCPU_FINALIZE -> ok
> > 	KVM_ARM_VCPU_FINALIZE -> -EPERM (too late)
> > 	...
> > 	KVM_REG_REG_LIST -> ok
> > 	KVM_SET_ONE_REG(KVM_REG_ARM64_SVE_VLS) -> -EPERM (too late)
> > 	KVM_SET_ONE_REG(KVM_REG_ARM64_SVE_ZREG(0, 0)) -> ok
> > 	KVM_RUN -> ok
> > 	KVM_ARM_VCPU_FINALIZE -> -EPERM (too late)
> > 
> > This would change all existing kvm_arm_vcpu_finalize() calls to
> > 
> > 	if (!kvm_arm_vcpu_finalized())
> > 		return -EPERM;
> > 
> > (or similar).
> 
> I find this rather compelling, assuming we can easily map features that
> are associated to finalization.

OK ... thanks for taking a look.

> > Without an affected vcpu feature enabled, for backwards compatibility
> > we would not require the KVM_ARM_VCPU_FINALIZE call (or perhaps even
> > forbid it, since userspace that wants to backwards compatible cannot
> > use the new ioctl anyway.  I'm in two minds about this.  Either way,
> > calling _FINALIZE on an old kvm is harmless, so long as userspace knows
> > to ignore this failure case.)
> > 
> > The backwards-compatible flow would be:
> > 
> > 	KVM_ARM_VCPU_INIT(features[] = 0) -> ok
> > 	...
> > 	KVM_ARM_VCPU_FINALIZE -> ok (or -EPERM)
> > 	...
> > 	KVM_RUN -> ok
> > 	KVM_ARM_VCPU_FINALIZE -> -EPERM (too late)
> > 
> > 
> > Thoughts?
> 
> This goes back to the above question: how do we ensure that userspace
> knows which features are subject to being finalized. As it is currently
> described, KVM_ARM_VCPU_FINALIZE isn't qualified by a feature set, nor
> can the kernel report what feature flags requires being finalized. It is
> also unclear to me whether all "finalizable" features would have the
> same init cycle.

So, it's not clear whether any other features will ever need
finalization, and even if they do there's a fair chance they won't be
interdependent with SVE in such a way as to require multiple
finalization steps.

For now, it's seems reasonable to make the finalization call a no-op
when no finalization is required.

Where finalization is required, KVM_ARM_VCPU_FINALIZE becomes mandatory,
but the requirement is a) strictly opt-in, and b) userspace will quickly
discover if it gets this wrong.

For this reason I'd rather not have any explicit reporting of whether
finalization is needed or not (or why): we just document and enforce at
run-time.

> So either we take the simplest approach and make KVM_ARM_VCPU_FINALIZE
> strictly SVE specific (renaming it in the process), or it takes some
> argument that allow specifying the feature set it applies to. Maybe we
> can get away with the kernel not reporting which features require to be
> finalized as long that it is clearly documented.

OK, what about:

 * Userspace treats KVM_ARM_VCPU_FINALIZE() -> EINVAL as no error
   (so that userspace can simply insert this into its init sequence,
   even on old kernels).

 * We add an argument, so that KVM_ARM_VCPU_FINALIZE(0) means
   "finalize default stuff, including SVE".  We can add explicit flags
   later if needed to finalize individual features separately.

   I don't know whether any features ever will have interdependent
   finalization requirements, but this should help get us off the
   hook if so.


Question:

 * KVM_REG_ARM64_SVE_VLS is a weird register because of its special
   sequencing requirements.

   The main reason for this is to make it easier to detect migration
   to a mismatched destination node.  But userspace needs some explicit
   code to make all this work anyway, so should we just have a couple
   of ioctls to get/set it instead?

   If there's no strong view either way, I'll leave it as-is, to
   minimise churn.

[...]

> Please do your best to have something as close as possible to the final
> version for -rc1. From that point on, I'd expect changes to be mostly
> cosmetic.

This ought to be feasible.  The changes being discussed so far are non-
invasive.

Cheers
---Dave

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

* Re: [PATCH v5 22/26] KVM: arm64/sve: Add pseudo-register for the guest's vector lengths
@ 2019-03-07 15:30               ` Dave Martin
  0 siblings, 0 replies; 205+ messages in thread
From: Dave Martin @ 2019-03-07 15:30 UTC (permalink / raw)
  To: Marc Zyngier
  Cc: Okamoto Takayuki, Christoffer Dall, Ard Biesheuvel,
	Catalin Marinas, Julien Thierry, Will Deacon, Zhang Lei, kvmarm,
	linux-arm-kernel

On Thu, Mar 07, 2019 at 01:47:09PM +0000, Marc Zyngier wrote:
> Hi Dave,
> 
> On 01/03/2019 14:55, Dave Martin wrote:
> > [FYI Peter, your views on the proposal outlined torward the end of the
> > mail would be appreciated.]
> > 
> > On Fri, Mar 01, 2019 at 01:28:19PM +0000, Julien Thierry wrote:
> 
> [...]
> 
> >> I might be over-thinking it, but if there is a way to move that
> >> finalization call I'd prefer that.
> > 
> > I know what you mean, but there's not really another clear place to put
> > it either, right now.  Making finalization a side-effect of only KVM_RUN
> > and KVM_GET_REG_LIST would mean that if userspace is squirting in the
> > state of a migrated vcpu, a dummy KVM_GET_REG_LIST call would need to be
> > inserted between setting KVM_REG_ARM64_SVE_VLS and setting the other SVE
> > regs.
> > 
> > One thing we could to is get rid of the implicit finalization behaviour
> > completely, and require an explicit ioctl KVM_ARM_VCPU_FINALIZE to do
> 
> +1. In the past, implicit finalization has been a major pain, and the
> "implicit GICv2 configuration" has been an absolute disaster.
> 
> > this.  This makes a clear barrier between reg writes that manipulate the
> > "physical" configuration of the vcpu, and reg reads/writes that merely
> > manipulate the vcpu's runtime state.  Say:
> > 
> > 	KVM_ARM_VCPU_INIT(features[] = KVM_ARM_VCPU_SVE) -> ok
> > 	KVM_RUN -> -EPERM (too early)
> > 	KVM_GET_REG_LIST -> -EPERM (too early)
> > 	...
> > 	KVM_SET_ONE_REG(KVM_REG_ARM64_SVE_VLS) -> ok
> > 	KVM_SET_ONE_REG(KVM_REG_ARM64_SVE_ZREG(0, 0)) -> -EPERM (too early)
> > 	...
> > 	KVM_RUN -> -EPERM (too early)
> > 	...
> > 	KVM_ARM_VCPU_FINALIZE -> ok
> > 	KVM_ARM_VCPU_FINALIZE -> -EPERM (too late)
> > 	...
> > 	KVM_REG_REG_LIST -> ok
> > 	KVM_SET_ONE_REG(KVM_REG_ARM64_SVE_VLS) -> -EPERM (too late)
> > 	KVM_SET_ONE_REG(KVM_REG_ARM64_SVE_ZREG(0, 0)) -> ok
> > 	KVM_RUN -> ok
> > 	KVM_ARM_VCPU_FINALIZE -> -EPERM (too late)
> > 
> > This would change all existing kvm_arm_vcpu_finalize() calls to
> > 
> > 	if (!kvm_arm_vcpu_finalized())
> > 		return -EPERM;
> > 
> > (or similar).
> 
> I find this rather compelling, assuming we can easily map features that
> are associated to finalization.

OK ... thanks for taking a look.

> > Without an affected vcpu feature enabled, for backwards compatibility
> > we would not require the KVM_ARM_VCPU_FINALIZE call (or perhaps even
> > forbid it, since userspace that wants to backwards compatible cannot
> > use the new ioctl anyway.  I'm in two minds about this.  Either way,
> > calling _FINALIZE on an old kvm is harmless, so long as userspace knows
> > to ignore this failure case.)
> > 
> > The backwards-compatible flow would be:
> > 
> > 	KVM_ARM_VCPU_INIT(features[] = 0) -> ok
> > 	...
> > 	KVM_ARM_VCPU_FINALIZE -> ok (or -EPERM)
> > 	...
> > 	KVM_RUN -> ok
> > 	KVM_ARM_VCPU_FINALIZE -> -EPERM (too late)
> > 
> > 
> > Thoughts?
> 
> This goes back to the above question: how do we ensure that userspace
> knows which features are subject to being finalized. As it is currently
> described, KVM_ARM_VCPU_FINALIZE isn't qualified by a feature set, nor
> can the kernel report what feature flags requires being finalized. It is
> also unclear to me whether all "finalizable" features would have the
> same init cycle.

So, it's not clear whether any other features will ever need
finalization, and even if they do there's a fair chance they won't be
interdependent with SVE in such a way as to require multiple
finalization steps.

For now, it's seems reasonable to make the finalization call a no-op
when no finalization is required.

Where finalization is required, KVM_ARM_VCPU_FINALIZE becomes mandatory,
but the requirement is a) strictly opt-in, and b) userspace will quickly
discover if it gets this wrong.

For this reason I'd rather not have any explicit reporting of whether
finalization is needed or not (or why): we just document and enforce at
run-time.

> So either we take the simplest approach and make KVM_ARM_VCPU_FINALIZE
> strictly SVE specific (renaming it in the process), or it takes some
> argument that allow specifying the feature set it applies to. Maybe we
> can get away with the kernel not reporting which features require to be
> finalized as long that it is clearly documented.

OK, what about:

 * Userspace treats KVM_ARM_VCPU_FINALIZE() -> EINVAL as no error
   (so that userspace can simply insert this into its init sequence,
   even on old kernels).

 * We add an argument, so that KVM_ARM_VCPU_FINALIZE(0) means
   "finalize default stuff, including SVE".  We can add explicit flags
   later if needed to finalize individual features separately.

   I don't know whether any features ever will have interdependent
   finalization requirements, but this should help get us off the
   hook if so.


Question:

 * KVM_REG_ARM64_SVE_VLS is a weird register because of its special
   sequencing requirements.

   The main reason for this is to make it easier to detect migration
   to a mismatched destination node.  But userspace needs some explicit
   code to make all this work anyway, so should we just have a couple
   of ioctls to get/set it instead?

   If there's no strong view either way, I'll leave it as-is, to
   minimise churn.

[...]

> Please do your best to have something as close as possible to the final
> version for -rc1. From that point on, I'd expect changes to be mostly
> cosmetic.

This ought to be feasible.  The changes being discussed so far are non-
invasive.

Cheers
---Dave

_______________________________________________
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] 205+ messages in thread

* RE: [PATCH v5 00/26] KVM: arm64: SVE guest support
  2019-03-05  9:47     ` Dave Martin
@ 2019-03-08  7:06       ` Zhang, Lei
  -1 siblings, 0 replies; 205+ messages in thread
From: Zhang, Lei @ 2019-03-08  7:06 UTC (permalink / raw)
  To: 'Dave Martin'
  Cc: Okamoto, Takayuki, Christoffer Dall, Ard Biesheuvel,
	Marc Zyngier, Catalin Marinas, Will Deacon, Julien Grall, kvmarm,
	linux-arm-kernel

Hi Dave,

riginal Message-----
> From: Dave Martin <Dave.Martin@arm.com>
> Sent: Tuesday, March 05, 2019 6:48 PM
> To: Zhang, Lei/張 雷 <zhang.lei@jp.fujitsu.com>
> Cc: kvmarm@lists.cs.columbia.edu; Peter Maydell
> <peter.maydell@linaro.org>; Okamoto, Takayuki/岡本 高幸
> <tokamoto@jp.fujitsu.com>; Christoffer Dall <cdall@kernel.org>; Ard
> Biesheuvel <ard.biesheuvel@linaro.org>; Marc Zyngier
> <marc.zyngier@arm.com>; Catalin Marinas <catalin.marinas@arm.com>; Will
> Deacon <will.deacon@arm.com>; Julien Grall <julien.grall@arm.com>; Alex
> Bennée <alex.bennee@linaro.org>; linux-arm-kernel@lists.infradead.org
> Subject: Re: [PATCH v5 00/26] KVM: arm64: SVE guest support
> 
> On Sun, Mar 03, 2019 at 02:40:57AM +0000, Zhang, Lei wrote:
> > Hi Dave,
> >
> > > -----Original Message-----
> > > From: linux-arm-kernel
> > > <linux-arm-kernel-bounces@lists.infradead.org> On Behalf Of Dave
> > > Martin
> > > Sent: Tuesday, February 19, 2019 4:52 AM
> > > To: kvmarm@lists.cs.columbia.edu
> > > Cc: Peter Maydell <peter.maydell@linaro.org>; Okamoto, Takayuki/岡本
> > > 高幸
> > > <tokamoto@jp.fujitsu.com>; Christoffer Dall <cdall@kernel.org>; Ard
> > > Biesheuvel <ard.biesheuvel@linaro.org>; Marc Zyngier
> > > <marc.zyngier@arm.com>; Catalin Marinas <catalin.marinas@arm.com>;
> > > Will Deacon <will.deacon@arm.com>; Zhang, Lei/張 雷
> > > <zhang.lei@jp.fujitsu.com>; Julien Grall <julien.grall@arm.com>;
> > > Alex Bennée <alex.bennee@linaro.org>;
> > > linux-arm-kernel@lists.infradead.org
> > > Subject: [PATCH v5 00/26] KVM: arm64: SVE guest support
> > >
> > > This series implements support for allowing KVM guests to use the
> > > Arm Scalable Vector Extension (SVE), superseding the previous v4 series
> [1].
> > >
> > > The patches are also available on a branch for reviewer convenience.
> > > [2]
> > >
> > > The patches are based on v5.0-rc6.
> > >
> > > They depend on another small series currently under review [3] that
> > > does a bit of relevant refactoring (as well as fixing an anomaly not
> > > directly related to this series).  A base branch [4] is provided so
> > > that reviewers don't need to hunt down both series independently.
> > [>]
> > I tested the patch on A64FX chip which SVE feature had been implemented.
> > All of tests have been passed.
> > Please add follows :
> > Tested-by: zhang.lei <zhang.lei@jp.fujitsu.com>
> 
> Thanks for this!
> 
> There will be at least one more iteration of this series before it is final, so it
> would be good if you can test again when I repost.
[>] 
Of course I will do the test on A64FX, when you repost patch.

Best Reagards,
Zhang Lei

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

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

* RE: [PATCH v5 00/26] KVM: arm64: SVE guest support
@ 2019-03-08  7:06       ` Zhang, Lei
  0 siblings, 0 replies; 205+ messages in thread
From: Zhang, Lei @ 2019-03-08  7:06 UTC (permalink / raw)
  To: 'Dave Martin'
  Cc: Peter Maydell, Okamoto, Takayuki, Christoffer Dall,
	Ard Biesheuvel, Marc Zyngier, Catalin Marinas, Will Deacon,
	Julien Grall, Alex Bennée, kvmarm, linux-arm-kernel

Hi Dave,

riginal Message-----
> From: Dave Martin <Dave.Martin@arm.com>
> Sent: Tuesday, March 05, 2019 6:48 PM
> To: Zhang, Lei/張 雷 <zhang.lei@jp.fujitsu.com>
> Cc: kvmarm@lists.cs.columbia.edu; Peter Maydell
> <peter.maydell@linaro.org>; Okamoto, Takayuki/岡本 高幸
> <tokamoto@jp.fujitsu.com>; Christoffer Dall <cdall@kernel.org>; Ard
> Biesheuvel <ard.biesheuvel@linaro.org>; Marc Zyngier
> <marc.zyngier@arm.com>; Catalin Marinas <catalin.marinas@arm.com>; Will
> Deacon <will.deacon@arm.com>; Julien Grall <julien.grall@arm.com>; Alex
> Bennée <alex.bennee@linaro.org>; linux-arm-kernel@lists.infradead.org
> Subject: Re: [PATCH v5 00/26] KVM: arm64: SVE guest support
> 
> On Sun, Mar 03, 2019 at 02:40:57AM +0000, Zhang, Lei wrote:
> > Hi Dave,
> >
> > > -----Original Message-----
> > > From: linux-arm-kernel
> > > <linux-arm-kernel-bounces@lists.infradead.org> On Behalf Of Dave
> > > Martin
> > > Sent: Tuesday, February 19, 2019 4:52 AM
> > > To: kvmarm@lists.cs.columbia.edu
> > > Cc: Peter Maydell <peter.maydell@linaro.org>; Okamoto, Takayuki/岡本
> > > 高幸
> > > <tokamoto@jp.fujitsu.com>; Christoffer Dall <cdall@kernel.org>; Ard
> > > Biesheuvel <ard.biesheuvel@linaro.org>; Marc Zyngier
> > > <marc.zyngier@arm.com>; Catalin Marinas <catalin.marinas@arm.com>;
> > > Will Deacon <will.deacon@arm.com>; Zhang, Lei/張 雷
> > > <zhang.lei@jp.fujitsu.com>; Julien Grall <julien.grall@arm.com>;
> > > Alex Bennée <alex.bennee@linaro.org>;
> > > linux-arm-kernel@lists.infradead.org
> > > Subject: [PATCH v5 00/26] KVM: arm64: SVE guest support
> > >
> > > This series implements support for allowing KVM guests to use the
> > > Arm Scalable Vector Extension (SVE), superseding the previous v4 series
> [1].
> > >
> > > The patches are also available on a branch for reviewer convenience.
> > > [2]
> > >
> > > The patches are based on v5.0-rc6.
> > >
> > > They depend on another small series currently under review [3] that
> > > does a bit of relevant refactoring (as well as fixing an anomaly not
> > > directly related to this series).  A base branch [4] is provided so
> > > that reviewers don't need to hunt down both series independently.
> > [>]
> > I tested the patch on A64FX chip which SVE feature had been implemented.
> > All of tests have been passed.
> > Please add follows :
> > Tested-by: zhang.lei <zhang.lei@jp.fujitsu.com>
> 
> Thanks for this!
> 
> There will be at least one more iteration of this series before it is final, so it
> would be good if you can test again when I repost.
[>] 
Of course I will do the test on A64FX, when you repost patch.

Best Reagards,
Zhang Lei

_______________________________________________
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] 205+ messages in thread

* RE: [PATCH v5 00/26] KVM: arm64: SVE guest support
  2019-03-19 17:58   ` Dave Martin
@ 2019-03-27  5:51     ` Zhang, Lei
  -1 siblings, 0 replies; 205+ messages in thread
From: Zhang, Lei @ 2019-03-27  5:51 UTC (permalink / raw)
  To: 'Dave Martin', kvmarm
  Cc: Matsuyama, Yoshihiro, Okamoto, Takayuki, Christoffer Dall,
	Ard Biesheuvel, Marc Zyngier, Catalin Marinas, Will Deacon,
	Zhang, Lei, Julien Grall, linux-arm-kernel

[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #1: Type: text/plain; charset="gb2312", Size: 1183 bytes --]

Hi guys,


> -----Original Message-----
> From: linux-arm-kernel <linux-arm-kernel-bounces@lists.infradead.org> On
> Behalf Of Dave Martin
> Sent: Wednesday, March 20, 2019 2:59 AM
> To: kvmarm@lists.cs.columbia.edu
> Cc: Peter Maydell <peter.maydell@linaro.org>; Okamoto, Takayuki/Œù±¾ ¸ßÐÒ
> <tokamoto@jp.fujitsu.com>; Christoffer Dall <cdall@kernel.org>; Ard
> Biesheuvel <ard.biesheuvel@linaro.org>; Marc Zyngier
> <marc.zyngier@arm.com>; Catalin Marinas <catalin.marinas@arm.com>; Will
> Deacon <will.deacon@arm.com>; Zhang, Lei/ˆ À×
> <zhang.lei@jp.fujitsu.com>; Julien Grall <julien.grall@arm.com>; Alex
> Benn¨¦e <alex.bennee@linaro.org>; linux-arm-kernel@lists.infradead.org
> Subject: Re: [PATCH v5 00/26] KVM: arm64: SVE guest support
> 
> On Tue, Mar 19, 2019 at 05:51:51PM +0000, Dave Martin wrote:
> 
> [...]
> 
> Yes, I messed up the subject line in the cover letter :P
> 
> The prefix should read "[PATCH v6 00/27]"

[>] 
I have tested patch v6 on Fujitsu A64FX chip which SVE feature had been implemented.
All of tests have been passed.
Please add follows:
Tested-by: zhang.lei <zhang.lei@jp.fujitsu.com>


Best Regards,
Zhang Lei

[-- Attachment #2: 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] 205+ messages in thread

* RE: [PATCH v5 00/26] KVM: arm64: SVE guest support
@ 2019-03-27  5:51     ` Zhang, Lei
  0 siblings, 0 replies; 205+ messages in thread
From: Zhang, Lei @ 2019-03-27  5:51 UTC (permalink / raw)
  To: 'Dave Martin', kvmarm
  Cc: Matsuyama, Yoshihiro, Peter Maydell, Okamoto, Takayuki,
	Christoffer Dall, Ard Biesheuvel, Marc Zyngier, Catalin Marinas,
	Will Deacon, Zhang, Lei, Julien Grall, Alex Bennée,
	linux-arm-kernel

[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #1: Type: text/plain; charset="gb2312", Size: 1183 bytes --]

Hi guys,


> -----Original Message-----
> From: linux-arm-kernel <linux-arm-kernel-bounces@lists.infradead.org> On
> Behalf Of Dave Martin
> Sent: Wednesday, March 20, 2019 2:59 AM
> To: kvmarm@lists.cs.columbia.edu
> Cc: Peter Maydell <peter.maydell@linaro.org>; Okamoto, Takayuki/Œù±¾ ¸ßÐÒ
> <tokamoto@jp.fujitsu.com>; Christoffer Dall <cdall@kernel.org>; Ard
> Biesheuvel <ard.biesheuvel@linaro.org>; Marc Zyngier
> <marc.zyngier@arm.com>; Catalin Marinas <catalin.marinas@arm.com>; Will
> Deacon <will.deacon@arm.com>; Zhang, Lei/ˆ À×
> <zhang.lei@jp.fujitsu.com>; Julien Grall <julien.grall@arm.com>; Alex
> Benn¨¦e <alex.bennee@linaro.org>; linux-arm-kernel@lists.infradead.org
> Subject: Re: [PATCH v5 00/26] KVM: arm64: SVE guest support
> 
> On Tue, Mar 19, 2019 at 05:51:51PM +0000, Dave Martin wrote:
> 
> [...]
> 
> Yes, I messed up the subject line in the cover letter :P
> 
> The prefix should read "[PATCH v6 00/27]"

[>] 
I have tested patch v6 on Fujitsu A64FX chip which SVE feature had been implemented.
All of tests have been passed.
Please add follows:
Tested-by: zhang.lei <zhang.lei@jp.fujitsu.com>


Best Regards,
Zhang Lei

[-- Attachment #2: Type: text/plain, Size: 176 bytes --]

_______________________________________________
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] 205+ messages in thread

* Re: [PATCH v5 00/26] KVM: arm64: SVE guest support
  2019-03-25 16:49       ` Andrew Jones
@ 2019-03-26 11:28         ` Dave Martin
  -1 siblings, 0 replies; 205+ messages in thread
From: Dave Martin @ 2019-03-26 11:28 UTC (permalink / raw)
  To: Andrew Jones
  Cc: Okamoto Takayuki, Christoffer Dall, Ard Biesheuvel, Marc Zyngier,
	Catalin Marinas, Will Deacon, Zhang Lei, Julien Grall, kvmarm,
	arm-mail-list

On Mon, Mar 25, 2019 at 05:49:56PM +0100, Andrew Jones wrote:
> On Mon, Mar 25, 2019 at 04:38:03PM +0000, Peter Maydell wrote:
> > On Mon, 25 Mar 2019 at 16:33, Andrew Jones <drjones@redhat.com> wrote:
> > >
> > > On Tue, Mar 19, 2019 at 05:51:51PM +0000, Dave Martin wrote:
> > > > This series implements support for allowing KVM guests to use the Arm
> > > > Scalable Vector Extension (SVE), superseding the previous v5 series [1].
> > 
> > > Hi Dave and Peter,
> > >
> > > Do either of you know if anyone has picked up the QEMU side of this?
> > > If not, then I'll take it.
> > 
> > Nobody has yet, so feel free.
> >
> 
> OK, hopefully I'll get something sent by the end of next week.

If one of you guys can review the patches with QEMU in mind in the
meantime, that would be very helpful.

Just looking at the documentation updates would be a good place to
start.

Cheers
---Dave

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

* Re: [PATCH v5 00/26] KVM: arm64: SVE guest support
@ 2019-03-26 11:28         ` Dave Martin
  0 siblings, 0 replies; 205+ messages in thread
From: Dave Martin @ 2019-03-26 11:28 UTC (permalink / raw)
  To: Andrew Jones
  Cc: Peter Maydell, Okamoto Takayuki, Christoffer Dall,
	Ard Biesheuvel, Marc Zyngier, Catalin Marinas, Will Deacon,
	Zhang Lei, Julien Grall, kvmarm, arm-mail-list

On Mon, Mar 25, 2019 at 05:49:56PM +0100, Andrew Jones wrote:
> On Mon, Mar 25, 2019 at 04:38:03PM +0000, Peter Maydell wrote:
> > On Mon, 25 Mar 2019 at 16:33, Andrew Jones <drjones@redhat.com> wrote:
> > >
> > > On Tue, Mar 19, 2019 at 05:51:51PM +0000, Dave Martin wrote:
> > > > This series implements support for allowing KVM guests to use the Arm
> > > > Scalable Vector Extension (SVE), superseding the previous v5 series [1].
> > 
> > > Hi Dave and Peter,
> > >
> > > Do either of you know if anyone has picked up the QEMU side of this?
> > > If not, then I'll take it.
> > 
> > Nobody has yet, so feel free.
> >
> 
> OK, hopefully I'll get something sent by the end of next week.

If one of you guys can review the patches with QEMU in mind in the
meantime, that would be very helpful.

Just looking at the documentation updates would be a good place to
start.

Cheers
---Dave

_______________________________________________
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] 205+ messages in thread

* Re: [PATCH v5 00/26] KVM: arm64: SVE guest support
  2019-03-25 16:38     ` Peter Maydell
@ 2019-03-25 16:49       ` Andrew Jones
  -1 siblings, 0 replies; 205+ messages in thread
From: Andrew Jones @ 2019-03-25 16:49 UTC (permalink / raw)
  To: Peter Maydell
  Cc: Okamoto Takayuki, Christoffer Dall, Ard Biesheuvel, Marc Zyngier,
	Catalin Marinas, Will Deacon, kvmarm, Julien Grall, Zhang Lei,
	Dave Martin, arm-mail-list

On Mon, Mar 25, 2019 at 04:38:03PM +0000, Peter Maydell wrote:
> On Mon, 25 Mar 2019 at 16:33, Andrew Jones <drjones@redhat.com> wrote:
> >
> > On Tue, Mar 19, 2019 at 05:51:51PM +0000, Dave Martin wrote:
> > > This series implements support for allowing KVM guests to use the Arm
> > > Scalable Vector Extension (SVE), superseding the previous v5 series [1].
> 
> > Hi Dave and Peter,
> >
> > Do either of you know if anyone has picked up the QEMU side of this?
> > If not, then I'll take it.
> 
> Nobody has yet, so feel free.
>

OK, hopefully I'll get something sent by the end of next week.

Thanks,
drew

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

* Re: [PATCH v5 00/26] KVM: arm64: SVE guest support
@ 2019-03-25 16:49       ` Andrew Jones
  0 siblings, 0 replies; 205+ messages in thread
From: Andrew Jones @ 2019-03-25 16:49 UTC (permalink / raw)
  To: Peter Maydell
  Cc: Okamoto Takayuki, Christoffer Dall, Ard Biesheuvel, Marc Zyngier,
	Catalin Marinas, Will Deacon, kvmarm, Julien Grall, Zhang Lei,
	Dave Martin, arm-mail-list

On Mon, Mar 25, 2019 at 04:38:03PM +0000, Peter Maydell wrote:
> On Mon, 25 Mar 2019 at 16:33, Andrew Jones <drjones@redhat.com> wrote:
> >
> > On Tue, Mar 19, 2019 at 05:51:51PM +0000, Dave Martin wrote:
> > > This series implements support for allowing KVM guests to use the Arm
> > > Scalable Vector Extension (SVE), superseding the previous v5 series [1].
> 
> > Hi Dave and Peter,
> >
> > Do either of you know if anyone has picked up the QEMU side of this?
> > If not, then I'll take it.
> 
> Nobody has yet, so feel free.
>

OK, hopefully I'll get something sent by the end of next week.

Thanks,
drew

_______________________________________________
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] 205+ messages in thread

* Re: [PATCH v5 00/26] KVM: arm64: SVE guest support
  2019-03-25 16:32   ` Andrew Jones
@ 2019-03-25 16:38     ` Peter Maydell
  -1 siblings, 0 replies; 205+ messages in thread
From: Peter Maydell @ 2019-03-25 16:38 UTC (permalink / raw)
  To: Andrew Jones
  Cc: Okamoto Takayuki, Christoffer Dall, Ard Biesheuvel, Marc Zyngier,
	Catalin Marinas, Will Deacon, kvmarm, Julien Grall, Zhang Lei,
	Dave Martin, arm-mail-list

On Mon, 25 Mar 2019 at 16:33, Andrew Jones <drjones@redhat.com> wrote:
>
> On Tue, Mar 19, 2019 at 05:51:51PM +0000, Dave Martin wrote:
> > This series implements support for allowing KVM guests to use the Arm
> > Scalable Vector Extension (SVE), superseding the previous v5 series [1].

> Hi Dave and Peter,
>
> Do either of you know if anyone has picked up the QEMU side of this?
> If not, then I'll take it.

Nobody has yet, so feel free.

thanks
-- PMM

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

* Re: [PATCH v5 00/26] KVM: arm64: SVE guest support
@ 2019-03-25 16:38     ` Peter Maydell
  0 siblings, 0 replies; 205+ messages in thread
From: Peter Maydell @ 2019-03-25 16:38 UTC (permalink / raw)
  To: Andrew Jones
  Cc: Okamoto Takayuki, Christoffer Dall, Ard Biesheuvel, Marc Zyngier,
	Catalin Marinas, Will Deacon, kvmarm, Julien Grall, Zhang Lei,
	Dave Martin, arm-mail-list

On Mon, 25 Mar 2019 at 16:33, Andrew Jones <drjones@redhat.com> wrote:
>
> On Tue, Mar 19, 2019 at 05:51:51PM +0000, Dave Martin wrote:
> > This series implements support for allowing KVM guests to use the Arm
> > Scalable Vector Extension (SVE), superseding the previous v5 series [1].

> Hi Dave and Peter,
>
> Do either of you know if anyone has picked up the QEMU side of this?
> If not, then I'll take it.

Nobody has yet, so feel free.

thanks
-- PMM

_______________________________________________
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] 205+ messages in thread

* Re: [PATCH v5 00/26] KVM: arm64: SVE guest support
  2019-03-19 17:51 ` Dave Martin
@ 2019-03-25 16:32   ` Andrew Jones
  -1 siblings, 0 replies; 205+ messages in thread
From: Andrew Jones @ 2019-03-25 16:32 UTC (permalink / raw)
  To: Dave Martin, peter.maydell
  Cc: Okamoto Takayuki, Christoffer Dall, Ard Biesheuvel, Marc Zyngier,
	Catalin Marinas, Will Deacon, Zhang Lei, Julien Grall, kvmarm,
	linux-arm-kernel

On Tue, Mar 19, 2019 at 05:51:51PM +0000, Dave Martin wrote:
> This series implements support for allowing KVM guests to use the Arm
> Scalable Vector Extension (SVE), superseding the previous v5 series [1].
> 
> The patches are also available on a branch for reviewer convenience. [2]
> 
> The patches are based on v5.1-rc1.
> 
> The series has been reworked to remove the dependency on [3],
> eliminating the ABI "fixes" but keeping the relevant cleanup/
> refactoring.  (See patch 16.)
> 
> This series addresses review comments received on v5, and contains one
> significant change:
> 
>  * A new ioctl KVM_ARM_VCPU_FINALIZE is added to replace the implicit
>    finalization behaviour in v5.  If userspace enables SVE, it must now
>    use this ioctl to finalize the vcpu configuration before KVM_RUN
>    etc. or SVE register access are permitted.
> 
> For a description of minor updates, see the individual patches.
> 
> 
> Known issues:
> 
>  * This update requires modifications to kvmtool that are not published
>    yet.  I will reply to this cover letter with a link when those are
>    available (hopefully within 24 hours of this posting).
>

Hi Dave and Peter,

Do either of you know if anyone has picked up the QEMU side of this?
If not, then I'll take it.

Thanks,
drew

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

* Re: [PATCH v5 00/26] KVM: arm64: SVE guest support
@ 2019-03-25 16:32   ` Andrew Jones
  0 siblings, 0 replies; 205+ messages in thread
From: Andrew Jones @ 2019-03-25 16:32 UTC (permalink / raw)
  To: Dave Martin, peter.maydell
  Cc: Okamoto Takayuki, Christoffer Dall, Ard Biesheuvel, Marc Zyngier,
	Catalin Marinas, Will Deacon, Zhang Lei, Julien Grall, kvmarm,
	linux-arm-kernel

On Tue, Mar 19, 2019 at 05:51:51PM +0000, Dave Martin wrote:
> This series implements support for allowing KVM guests to use the Arm
> Scalable Vector Extension (SVE), superseding the previous v5 series [1].
> 
> The patches are also available on a branch for reviewer convenience. [2]
> 
> The patches are based on v5.1-rc1.
> 
> The series has been reworked to remove the dependency on [3],
> eliminating the ABI "fixes" but keeping the relevant cleanup/
> refactoring.  (See patch 16.)
> 
> This series addresses review comments received on v5, and contains one
> significant change:
> 
>  * A new ioctl KVM_ARM_VCPU_FINALIZE is added to replace the implicit
>    finalization behaviour in v5.  If userspace enables SVE, it must now
>    use this ioctl to finalize the vcpu configuration before KVM_RUN
>    etc. or SVE register access are permitted.
> 
> For a description of minor updates, see the individual patches.
> 
> 
> Known issues:
> 
>  * This update requires modifications to kvmtool that are not published
>    yet.  I will reply to this cover letter with a link when those are
>    available (hopefully within 24 hours of this posting).
>

Hi Dave and Peter,

Do either of you know if anyone has picked up the QEMU side of this?
If not, then I'll take it.

Thanks,
drew

_______________________________________________
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] 205+ messages in thread

* Re: [PATCH v5 00/26] KVM: arm64: SVE guest support
  2019-03-19 17:51 ` Dave Martin
@ 2019-03-20 12:30   ` Dave Martin
  -1 siblings, 0 replies; 205+ messages in thread
From: Dave Martin @ 2019-03-20 12:30 UTC (permalink / raw)
  To: kvmarm
  Cc: Peter Maydell, Okamoto Takayuki, Christoffer Dall,
	Ard Biesheuvel, Marc Zyngier, Catalin Marinas, Will Deacon,
	Zhang Lei, Julien Grall, Alex Bennée, linux-arm-kernel

On Tue, Mar 19, 2019 at 05:51:51PM +0000, Dave Martin wrote:

[...]

> Known issues:
> 
>  * This update requires modifications to kvmtool that are not published
>    yet.  I will reply to this cover letter with a link when those are
>    available (hopefully within 24 hours of this posting).
> 
>    The kvmtool branch referenced by the v5 cover letter **will not
>    work** with v6...  Please be patient :)

I've now posted the updated kvmtool series [1].

I've also pushed the series to git for convenience [2].

Testing/comments welcome, as always.


[1] [PATCH kvmtool v2 0/3] arm64: Basic SVE guest support
https://lists.cs.columbia.edu/pipermail/kvmarm/2019-March/035198.html

[2]
git://linux-arm.org/kvmtool-dm.git sve-linuxv6/v2/head
http://linux-arm.org/git?p=kvmtool-dm.git;a=shortlog;h=refs/heads/sve-linuxv6/v2/head

Cheers
---Dave

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

* Re: [PATCH v5 00/26] KVM: arm64: SVE guest support
@ 2019-03-20 12:30   ` Dave Martin
  0 siblings, 0 replies; 205+ messages in thread
From: Dave Martin @ 2019-03-20 12:30 UTC (permalink / raw)
  To: kvmarm
  Cc: Peter Maydell, Okamoto Takayuki, Christoffer Dall,
	Ard Biesheuvel, Marc Zyngier, Catalin Marinas, Will Deacon,
	Zhang Lei, Julien Grall, Alex Bennée, linux-arm-kernel

On Tue, Mar 19, 2019 at 05:51:51PM +0000, Dave Martin wrote:

[...]

> Known issues:
> 
>  * This update requires modifications to kvmtool that are not published
>    yet.  I will reply to this cover letter with a link when those are
>    available (hopefully within 24 hours of this posting).
> 
>    The kvmtool branch referenced by the v5 cover letter **will not
>    work** with v6...  Please be patient :)

I've now posted the updated kvmtool series [1].

I've also pushed the series to git for convenience [2].

Testing/comments welcome, as always.


[1] [PATCH kvmtool v2 0/3] arm64: Basic SVE guest support
https://lists.cs.columbia.edu/pipermail/kvmarm/2019-March/035198.html

[2]
git://linux-arm.org/kvmtool-dm.git sve-linuxv6/v2/head
http://linux-arm.org/git?p=kvmtool-dm.git;a=shortlog;h=refs/heads/sve-linuxv6/v2/head

Cheers
---Dave

_______________________________________________
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] 205+ messages in thread

* Re: [PATCH v5 00/26] KVM: arm64: SVE guest support
  2019-03-19 17:51 ` Dave Martin
@ 2019-03-19 17:58   ` Dave Martin
  -1 siblings, 0 replies; 205+ messages in thread
From: Dave Martin @ 2019-03-19 17:58 UTC (permalink / raw)
  To: kvmarm
  Cc: Okamoto Takayuki, Christoffer Dall, Ard Biesheuvel, Marc Zyngier,
	Catalin Marinas, Will Deacon, Zhang Lei, Julien Grall,
	linux-arm-kernel

On Tue, Mar 19, 2019 at 05:51:51PM +0000, Dave Martin wrote:

[...]

Yes, I messed up the subject line in the cover letter :P

The prefix should read "[PATCH v6 00/27]"

Cheers
---Dave

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

* Re: [PATCH v5 00/26] KVM: arm64: SVE guest support
@ 2019-03-19 17:58   ` Dave Martin
  0 siblings, 0 replies; 205+ messages in thread
From: Dave Martin @ 2019-03-19 17:58 UTC (permalink / raw)
  To: kvmarm
  Cc: Peter Maydell, Okamoto Takayuki, Christoffer Dall,
	Ard Biesheuvel, Marc Zyngier, Catalin Marinas, Will Deacon,
	Zhang Lei, Julien Grall, Alex Bennée, linux-arm-kernel

On Tue, Mar 19, 2019 at 05:51:51PM +0000, Dave Martin wrote:

[...]

Yes, I messed up the subject line in the cover letter :P

The prefix should read "[PATCH v6 00/27]"

Cheers
---Dave

_______________________________________________
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] 205+ messages in thread

* [PATCH v5 00/26] KVM: arm64: SVE guest support
@ 2019-03-19 17:51 ` Dave Martin
  0 siblings, 0 replies; 205+ messages in thread
From: Dave Martin @ 2019-03-19 17:51 UTC (permalink / raw)
  To: kvmarm
  Cc: Peter Maydell, Okamoto Takayuki, Christoffer Dall,
	Ard Biesheuvel, Marc Zyngier, Catalin Marinas, Will Deacon,
	Zhang Lei, Julien Grall, Alex Bennée, linux-arm-kernel

This series implements support for allowing KVM guests to use the Arm
Scalable Vector Extension (SVE), superseding the previous v5 series [1].

The patches are also available on a branch for reviewer convenience. [2]

The patches are based on v5.1-rc1.

The series has been reworked to remove the dependency on [3],
eliminating the ABI "fixes" but keeping the relevant cleanup/
refactoring.  (See patch 16.)

This series addresses review comments received on v5, and contains one
significant change:

 * A new ioctl KVM_ARM_VCPU_FINALIZE is added to replace the implicit
   finalization behaviour in v5.  If userspace enables SVE, it must now
   use this ioctl to finalize the vcpu configuration before KVM_RUN
   etc. or SVE register access are permitted.

For a description of minor updates, see the individual patches.


Known issues:

 * This update requires modifications to kvmtool that are not published
   yet.  I will reply to this cover letter with a link when those are
   available (hopefully within 24 hours of this posting).

   The kvmtool branch referenced by the v5 cover letter **will not
   work** with v6...  Please be patient :)


Testing status:

 * Lightweight testing on the Arm Fast Model, primarily to exercise the
   new vcpu finalization API.

   I plan to re-run stress testing once v6 is posted.  The low-level
   context switch internals in the series remain unchanged since v5, so
   it is "relatively unlikely" that new problems will crop up since the
   v5 testing.

 * ThunderX2: basic testing of arm64 defconfig, including booting guests
   (no SVE support on this hardware).

   (This was done on an interim release candidate of v6: I will redo it
   after this posting.)

 * aarch32 host testing has only been done in v5 so far.  arch/arm
   changes between v5 and v6 are minimal.  I plan to redo sanity-check
   testing after this posting.

I will reply to this cover letter when I have v6 test outcomes to
report.

   
Resolved issues:

 * The register zeroing bug observed when testing v5 has been tracked
   down to architecture noncompliance in the Arm Fast Model, which led
   to lanes of SVE registers being zeroed in some inappropriate
   situations.


[1] Previous series:
[PATCH v5 00/26] KVM: arm64: SVE guest support
https://lists.cs.columbia.edu/pipermail/kvmarm/2019-February/034695.html

[2] This series in git:
http://linux-arm.org/git?p=linux-dm.git;a=shortlog;h=refs/heads/sve-kvm/v6/head
git://linux-arm.org/linux-dm.git sve-kvm/v6/head

[3] [PATCH v2 0/2] Fix KVM_GET_REG_LIST invalid register ID regression
https://lists.cs.columbia.edu/pipermail/kvmarm/2018-December/033810.html


Dave Martin (27):
  KVM: Documentation: Document arm64 core registers in detail
  arm64: fpsimd: Always set TIF_FOREIGN_FPSTATE on task state flush
  KVM: arm64: Delete orphaned declaration for __fpsimd_enabled()
  KVM: arm64: Refactor kvm_arm_num_regs() for easier maintenance
  KVM: arm64: Add missing #includes to kvm_host.h
  arm64/sve: Clarify role of the VQ map maintenance functions
  arm64/sve: Check SVE virtualisability
  arm64/sve: Enable SVE state tracking for non-task contexts
  KVM: arm64: Add a vcpu flag to control SVE visibility for the guest
  KVM: arm64: Propagate vcpu into read_id_reg()
  KVM: arm64: Support runtime sysreg visibility filtering
  KVM: arm64/sve: System register context switch and access support
  KVM: arm64/sve: Context switch the SVE registers
  KVM: Allow 2048-bit register access via ioctl interface
  KVM: arm64: Add missing #include of <linux/string.h> in guest.c
  KVM: arm64: Factor out core register ID enumeration
  KVM: arm64: Reject ioctl access to FPSIMD V-regs on SVE vcpus
  KVM: arm64/sve: Add SVE support to register access ioctl interface
  KVM: arm64: Enumerate SVE register indices for KVM_GET_REG_LIST
  arm64/sve: In-kernel vector length availability query interface
  KVM: arm/arm64: Add hook for arch-specific KVM initialisation
  KVM: arm/arm64: Add KVM_ARM_VCPU_FINALIZE ioctl
  KVM: arm64/sve: Add pseudo-register for the guest's vector lengths
  KVM: arm64/sve: Allow userspace to enable SVE for vcpus
  KVM: arm64: Add a capability to advertise SVE support
  KVM: Document errors for KVM_GET_ONE_REG and KVM_SET_ONE_REG
  KVM: arm64/sve: Document KVM API extensions for SVE

 Documentation/virtual/kvm/api.txt | 156 +++++++++++++++
 arch/arm/include/asm/kvm_host.h   |   6 +
 arch/arm64/include/asm/fpsimd.h   |  33 +++-
 arch/arm64/include/asm/kvm_host.h |  43 ++++-
 arch/arm64/include/asm/kvm_hyp.h  |   1 -
 arch/arm64/include/asm/sysreg.h   |   3 +
 arch/arm64/include/uapi/asm/kvm.h |  22 +++
 arch/arm64/kernel/cpufeature.c    |   2 +-
 arch/arm64/kernel/fpsimd.c        | 172 ++++++++++++-----
 arch/arm64/kernel/signal.c        |   5 -
 arch/arm64/kvm/fpsimd.c           |  17 +-
 arch/arm64/kvm/guest.c            | 387 +++++++++++++++++++++++++++++++++++---
 arch/arm64/kvm/hyp/switch.c       |  74 ++++++--
 arch/arm64/kvm/reset.c            | 137 +++++++++++++-
 arch/arm64/kvm/sys_regs.c         | 130 +++++++++++--
 arch/arm64/kvm/sys_regs.h         |  25 +++
 include/uapi/linux/kvm.h          |   5 +
 virt/kvm/arm/arm.c                |  22 +++
 18 files changed, 1110 insertions(+), 130 deletions(-)

-- 
2.1.4

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

* [PATCH v5 00/26] KVM: arm64: SVE guest support
@ 2019-03-19 17:51 ` Dave Martin
  0 siblings, 0 replies; 205+ messages in thread
From: Dave Martin @ 2019-03-19 17:51 UTC (permalink / raw)
  To: kvmarm
  Cc: Peter Maydell, Okamoto Takayuki, Christoffer Dall,
	Ard Biesheuvel, Marc Zyngier, Catalin Marinas, Will Deacon,
	Zhang Lei, Julien Grall, Alex Bennée, linux-arm-kernel

This series implements support for allowing KVM guests to use the Arm
Scalable Vector Extension (SVE), superseding the previous v5 series [1].

The patches are also available on a branch for reviewer convenience. [2]

The patches are based on v5.1-rc1.

The series has been reworked to remove the dependency on [3],
eliminating the ABI "fixes" but keeping the relevant cleanup/
refactoring.  (See patch 16.)

This series addresses review comments received on v5, and contains one
significant change:

 * A new ioctl KVM_ARM_VCPU_FINALIZE is added to replace the implicit
   finalization behaviour in v5.  If userspace enables SVE, it must now
   use this ioctl to finalize the vcpu configuration before KVM_RUN
   etc. or SVE register access are permitted.

For a description of minor updates, see the individual patches.


Known issues:

 * This update requires modifications to kvmtool that are not published
   yet.  I will reply to this cover letter with a link when those are
   available (hopefully within 24 hours of this posting).

   The kvmtool branch referenced by the v5 cover letter **will not
   work** with v6...  Please be patient :)


Testing status:

 * Lightweight testing on the Arm Fast Model, primarily to exercise the
   new vcpu finalization API.

   I plan to re-run stress testing once v6 is posted.  The low-level
   context switch internals in the series remain unchanged since v5, so
   it is "relatively unlikely" that new problems will crop up since the
   v5 testing.

 * ThunderX2: basic testing of arm64 defconfig, including booting guests
   (no SVE support on this hardware).

   (This was done on an interim release candidate of v6: I will redo it
   after this posting.)

 * aarch32 host testing has only been done in v5 so far.  arch/arm
   changes between v5 and v6 are minimal.  I plan to redo sanity-check
   testing after this posting.

I will reply to this cover letter when I have v6 test outcomes to
report.

   
Resolved issues:

 * The register zeroing bug observed when testing v5 has been tracked
   down to architecture noncompliance in the Arm Fast Model, which led
   to lanes of SVE registers being zeroed in some inappropriate
   situations.


[1] Previous series:
[PATCH v5 00/26] KVM: arm64: SVE guest support
https://lists.cs.columbia.edu/pipermail/kvmarm/2019-February/034695.html

[2] This series in git:
http://linux-arm.org/git?p=linux-dm.git;a=shortlog;h=refs/heads/sve-kvm/v6/head
git://linux-arm.org/linux-dm.git sve-kvm/v6/head

[3] [PATCH v2 0/2] Fix KVM_GET_REG_LIST invalid register ID regression
https://lists.cs.columbia.edu/pipermail/kvmarm/2018-December/033810.html


Dave Martin (27):
  KVM: Documentation: Document arm64 core registers in detail
  arm64: fpsimd: Always set TIF_FOREIGN_FPSTATE on task state flush
  KVM: arm64: Delete orphaned declaration for __fpsimd_enabled()
  KVM: arm64: Refactor kvm_arm_num_regs() for easier maintenance
  KVM: arm64: Add missing #includes to kvm_host.h
  arm64/sve: Clarify role of the VQ map maintenance functions
  arm64/sve: Check SVE virtualisability
  arm64/sve: Enable SVE state tracking for non-task contexts
  KVM: arm64: Add a vcpu flag to control SVE visibility for the guest
  KVM: arm64: Propagate vcpu into read_id_reg()
  KVM: arm64: Support runtime sysreg visibility filtering
  KVM: arm64/sve: System register context switch and access support
  KVM: arm64/sve: Context switch the SVE registers
  KVM: Allow 2048-bit register access via ioctl interface
  KVM: arm64: Add missing #include of <linux/string.h> in guest.c
  KVM: arm64: Factor out core register ID enumeration
  KVM: arm64: Reject ioctl access to FPSIMD V-regs on SVE vcpus
  KVM: arm64/sve: Add SVE support to register access ioctl interface
  KVM: arm64: Enumerate SVE register indices for KVM_GET_REG_LIST
  arm64/sve: In-kernel vector length availability query interface
  KVM: arm/arm64: Add hook for arch-specific KVM initialisation
  KVM: arm/arm64: Add KVM_ARM_VCPU_FINALIZE ioctl
  KVM: arm64/sve: Add pseudo-register for the guest's vector lengths
  KVM: arm64/sve: Allow userspace to enable SVE for vcpus
  KVM: arm64: Add a capability to advertise SVE support
  KVM: Document errors for KVM_GET_ONE_REG and KVM_SET_ONE_REG
  KVM: arm64/sve: Document KVM API extensions for SVE

 Documentation/virtual/kvm/api.txt | 156 +++++++++++++++
 arch/arm/include/asm/kvm_host.h   |   6 +
 arch/arm64/include/asm/fpsimd.h   |  33 +++-
 arch/arm64/include/asm/kvm_host.h |  43 ++++-
 arch/arm64/include/asm/kvm_hyp.h  |   1 -
 arch/arm64/include/asm/sysreg.h   |   3 +
 arch/arm64/include/uapi/asm/kvm.h |  22 +++
 arch/arm64/kernel/cpufeature.c    |   2 +-
 arch/arm64/kernel/fpsimd.c        | 172 ++++++++++++-----
 arch/arm64/kernel/signal.c        |   5 -
 arch/arm64/kvm/fpsimd.c           |  17 +-
 arch/arm64/kvm/guest.c            | 387 +++++++++++++++++++++++++++++++++++---
 arch/arm64/kvm/hyp/switch.c       |  74 ++++++--
 arch/arm64/kvm/reset.c            | 137 +++++++++++++-
 arch/arm64/kvm/sys_regs.c         | 130 +++++++++++--
 arch/arm64/kvm/sys_regs.h         |  25 +++
 include/uapi/linux/kvm.h          |   5 +
 virt/kvm/arm/arm.c                |  22 +++
 18 files changed, 1110 insertions(+), 130 deletions(-)

-- 
2.1.4


_______________________________________________
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] 205+ messages in thread

end of thread, other threads:[~2019-03-27  5:52 UTC | newest]

Thread overview: 205+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2019-02-18 19:52 [PATCH v5 00/26] KVM: arm64: SVE guest support Dave Martin
2019-02-18 19:52 ` Dave Martin
2019-02-18 19:52 ` [PATCH v5 01/26] KVM: Documentation: Document arm64 core registers in detail Dave Martin
2019-02-18 19:52   ` Dave Martin
2019-02-21 11:48   ` Julien Grall
2019-02-21 11:48     ` Julien Grall
2019-02-26 12:05     ` Dave Martin
2019-02-26 12:05       ` Dave Martin
2019-02-21 11:57   ` Peter Maydell
2019-02-21 11:57     ` Peter Maydell
2019-02-18 19:52 ` [PATCH v5 02/26] arm64: fpsimd: Always set TIF_FOREIGN_FPSTATE on task state flush Dave Martin
2019-02-18 19:52   ` Dave Martin
2019-02-21 12:39   ` Julien Grall
2019-02-26 12:06     ` Dave Martin
2019-02-26 12:06       ` Dave Martin
2019-02-26 12:35       ` Julien Grall
2019-02-26 12:35         ` Julien Grall
2019-02-18 19:52 ` [PATCH v5 03/26] KVM: arm64: Delete orphaned declaration for __fpsimd_enabled() Dave Martin
2019-02-18 19:52   ` Dave Martin
2019-02-18 19:52 ` [PATCH v5 04/26] KVM: arm64: Refactor kvm_arm_num_regs() for easier maintenance Dave Martin
2019-02-18 19:52   ` Dave Martin
2019-02-18 19:52 ` [PATCH v5 05/26] KVM: arm64: Add missing #include of <linux/bitmap.h> to kvm_host.h Dave Martin
2019-02-18 19:52   ` Dave Martin
2019-02-20 15:23   ` Mark Rutland
2019-02-20 15:23     ` Mark Rutland
2019-02-26 12:06     ` Dave Martin
2019-02-26 12:06       ` Dave Martin
2019-02-26 12:31       ` Mark Rutland
2019-02-26 12:33         ` Dave Martin
2019-02-26 12:33           ` Dave Martin
2019-02-26 12:40           ` Mark Rutland
2019-02-26 12:40             ` Mark Rutland
2019-02-18 19:52 ` [PATCH v5 06/26] arm64/sve: Check SVE virtualisability Dave Martin
2019-02-18 19:52   ` Dave Martin
2019-02-20 11:12   ` Julien Thierry
2019-02-20 11:12     ` Julien Thierry
2019-02-26 12:06     ` Dave Martin
2019-02-26 12:06       ` Dave Martin
2019-03-01 12:39       ` Julien Thierry
2019-03-01 12:39         ` Julien Thierry
2019-03-01 14:44         ` Dave Martin
2019-03-01 14:44           ` Dave Martin
2019-02-21 13:36   ` Julien Grall
2019-02-21 13:36     ` Julien Grall
2019-02-26 12:06     ` Dave Martin
2019-02-26 12:06       ` Dave Martin
2019-02-26 15:43       ` Julien Grall
2019-02-26 15:43         ` Julien Grall
2019-02-18 19:52 ` [PATCH v5 07/26] arm64/sve: Clarify role of the VQ map maintenance functions Dave Martin
2019-02-18 19:52   ` Dave Martin
2019-02-20 11:43   ` Julien Thierry
2019-02-20 11:43     ` Julien Thierry
2019-02-26 12:06     ` Dave Martin
2019-02-26 12:06       ` Dave Martin
2019-02-21 13:46   ` Julien Grall
2019-02-21 13:46     ` Julien Grall
2019-02-26 12:07     ` Dave Martin
2019-02-26 12:07       ` Dave Martin
2019-02-18 19:52 ` [PATCH v5 08/26] arm64/sve: Enable SVE state tracking for non-task contexts Dave Martin
2019-02-18 19:52   ` Dave Martin
2019-02-22 15:26   ` Julien Grall
2019-02-22 15:26     ` Julien Grall
2019-02-26 12:07     ` Dave Martin
2019-02-26 12:07       ` Dave Martin
2019-02-26 15:49       ` Julien Grall
2019-02-26 15:49         ` Julien Grall
2019-02-26 15:58         ` Dave Martin
2019-02-26 15:58           ` Dave Martin
2019-02-26 15:59           ` Julien Grall
2019-02-26 15:59             ` Julien Grall
2019-02-26 16:03             ` Dave Martin
2019-02-26 16:03               ` Dave Martin
2019-02-18 19:52 ` [PATCH v5 09/26] KVM: arm64: Add a vcpu flag to control SVE visibility for the guest Dave Martin
2019-02-18 19:52   ` Dave Martin
2019-02-18 19:52 ` [PATCH v5 10/26] KVM: arm64: Propagate vcpu into read_id_reg() Dave Martin
2019-02-18 19:52   ` Dave Martin
2019-02-18 19:52 ` [PATCH v5 11/26] KVM: arm64: Extend reset_unknown() to handle mixed RES0/UNKNOWN registers Dave Martin
2019-02-18 19:52   ` Dave Martin
2019-02-20 13:33   ` Julien Thierry
2019-02-20 13:33     ` Julien Thierry
2019-02-26 12:07     ` Dave Martin
2019-02-26 12:07       ` Dave Martin
2019-02-22 16:04   ` Julien Grall
2019-02-22 16:04     ` Julien Grall
2019-02-18 19:52 ` [PATCH v5 12/26] KVM: arm64: Support runtime sysreg visibility filtering Dave Martin
2019-02-18 19:52   ` Dave Martin
2019-02-20 14:33   ` Julien Thierry
2019-02-20 14:33     ` Julien Thierry
2019-02-26 12:07     ` Dave Martin
2019-02-26 12:07       ` Dave Martin
2019-02-20 15:37   ` Mark Rutland
2019-02-20 15:37     ` Mark Rutland
2019-02-26 12:12     ` Dave Martin
2019-02-26 12:12       ` Dave Martin
2019-02-18 19:52 ` [PATCH v5 13/26] KVM: arm64/sve: System register context switch and access support Dave Martin
2019-02-18 19:52   ` Dave Martin
2019-02-20 16:48   ` Julien Thierry
2019-02-20 16:48     ` Julien Thierry
2019-02-26 16:32   ` Julien Grall
2019-02-26 16:32     ` Julien Grall
2019-02-26 17:01     ` Dave Martin
2019-02-26 17:01       ` Dave Martin
2019-02-27 12:02       ` Julien Grall
2019-02-27 12:02         ` Julien Grall
2019-02-27 13:50         ` Dave Martin
2019-02-27 13:50           ` Dave Martin
2019-02-27 14:17           ` Julien Grall
2019-02-27 14:17             ` Julien Grall
2019-02-27 14:38             ` Dave Martin
2019-02-27 14:38               ` Dave Martin
2019-02-18 19:52 ` [PATCH v5 14/26] KVM: arm64/sve: Context switch the SVE registers Dave Martin
2019-02-18 19:52   ` Dave Martin
2019-02-20 16:19   ` Mark Rutland
2019-02-20 16:19     ` Mark Rutland
2019-02-26 12:13     ` Dave Martin
2019-02-26 12:13       ` Dave Martin
2019-02-20 16:46   ` Julien Thierry
2019-02-20 16:46     ` Julien Thierry
2019-02-26 12:13     ` Dave Martin
2019-02-26 12:13       ` Dave Martin
2019-02-26 16:56       ` Julien Grall
2019-02-26 16:56         ` Julien Grall
2019-02-27 13:37         ` Dave Martin
2019-02-27 13:37           ` Dave Martin
2019-02-18 19:52 ` [PATCH v5 15/26] KVM: Allow 2048-bit register access via ioctl interface Dave Martin
2019-02-18 19:52   ` Dave Martin
2019-02-18 19:52 ` [PATCH v5 16/26] KVM: arm64: Add missing #include of <linux/string.h> in guest.c Dave Martin
2019-02-18 19:52   ` Dave Martin
2019-02-18 19:52 ` [PATCH v5 17/26] KVM: arm64: Reject ioctl access to FPSIMD V-regs on SVE vcpus Dave Martin
2019-02-18 19:52   ` Dave Martin
2019-02-21 12:06   ` Julien Thierry
2019-02-21 12:06     ` Julien Thierry
2019-02-26 12:13     ` Dave Martin
2019-02-26 12:13       ` Dave Martin
2019-02-18 19:52 ` [PATCH v5 18/26] KVM: arm64/sve: Add SVE support to register access ioctl interface Dave Martin
2019-02-18 19:52   ` Dave Martin
2019-02-21 15:23   ` Julien Thierry
2019-02-21 15:23     ` Julien Thierry
2019-02-26 12:13     ` Dave Martin
2019-02-26 12:13       ` Dave Martin
2019-03-01 13:03       ` Julien Thierry
2019-03-01 13:03         ` Julien Thierry
2019-03-01 14:45         ` Dave Martin
2019-03-01 14:45           ` Dave Martin
2019-02-18 19:52 ` [PATCH v5 19/26] KVM: arm64: Enumerate SVE register indices for KVM_GET_REG_LIST Dave Martin
2019-02-18 19:52   ` Dave Martin
2019-02-21 16:28   ` Julien Thierry
2019-02-21 16:28     ` Julien Thierry
2019-02-18 19:52 ` [PATCH v5 20/26] arm64/sve: In-kernel vector length availability query interface Dave Martin
2019-02-18 19:52   ` Dave Martin
2019-02-18 19:52 ` [PATCH v5 21/26] KVM: arm/arm64: Add hook to finalize the vcpu configuration Dave Martin
2019-02-18 19:52   ` Dave Martin
2019-02-18 19:52 ` [PATCH v5 22/26] KVM: arm64/sve: Add pseudo-register for the guest's vector lengths Dave Martin
2019-02-18 19:52   ` Dave Martin
2019-02-21 17:48   ` Julien Thierry
2019-02-21 17:48     ` Julien Thierry
2019-02-26 12:13     ` Dave Martin
2019-02-26 12:13       ` Dave Martin
2019-03-01 13:28       ` Julien Thierry
2019-03-01 13:28         ` Julien Thierry
2019-03-01 14:55         ` Dave Martin
2019-03-01 14:55           ` Dave Martin
2019-03-07 13:47           ` Marc Zyngier
2019-03-07 13:47             ` Marc Zyngier
2019-03-07 15:30             ` Dave Martin
2019-03-07 15:30               ` Dave Martin
2019-02-18 19:52 ` [PATCH v5 23/26] KVM: arm64/sve: Allow userspace to enable SVE for vcpus Dave Martin
2019-02-18 19:52   ` Dave Martin
2019-02-22  9:05   ` Julien Thierry
2019-02-22  9:05     ` Julien Thierry
2019-02-26 12:13     ` Dave Martin
2019-02-26 12:13       ` Dave Martin
2019-02-18 19:52 ` [PATCH v5 24/26] KVM: arm64: Add a capabillity to advertise SVE support Dave Martin
2019-02-18 19:52   ` Dave Martin
2019-02-22  9:10   ` Julien Thierry
2019-02-22  9:10     ` Julien Thierry
2019-02-26 12:14     ` Dave Martin
2019-02-26 12:14       ` Dave Martin
2019-02-18 19:52 ` [PATCH v5 25/26] KVM: Document errors for KVM_GET_ONE_REG and KVM_SET_ONE_REG Dave Martin
2019-02-18 19:52   ` Dave Martin
2019-02-18 19:52 ` [PATCH v5 26/26] KVM: arm64/sve: Document KVM API extensions for SVE Dave Martin
2019-02-18 19:52   ` Dave Martin
2019-02-20 15:47 ` [PATCH v5 00/26] KVM: arm64: SVE guest support Dave Martin
2019-02-20 15:47   ` Dave Martin
2019-03-03  2:40 ` Zhang, Lei
2019-03-05  9:47   ` Dave Martin
2019-03-05  9:47     ` Dave Martin
2019-03-08  7:06     ` Zhang, Lei
2019-03-08  7:06       ` Zhang, Lei
2019-03-19 17:51 Dave Martin
2019-03-19 17:51 ` Dave Martin
2019-03-19 17:58 ` Dave Martin
2019-03-19 17:58   ` Dave Martin
2019-03-27  5:51   ` Zhang, Lei
2019-03-27  5:51     ` Zhang, Lei
2019-03-20 12:30 ` Dave Martin
2019-03-20 12:30   ` Dave Martin
2019-03-25 16:32 ` Andrew Jones
2019-03-25 16:32   ` Andrew Jones
2019-03-25 16:38   ` Peter Maydell
2019-03-25 16:38     ` Peter Maydell
2019-03-25 16:49     ` Andrew Jones
2019-03-25 16:49       ` Andrew Jones
2019-03-26 11:28       ` Dave Martin
2019-03-26 11:28         ` Dave Martin

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.