aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDave Martin <Dave.Martin@arm.com>2019-04-05 12:17:08 -0400
committerMarc Zyngier <marc.zyngier@arm.com>2019-04-18 12:14:01 -0400
commit8ae6efdde451512e855be576dd0cdf4cb394c289 (patch)
treefa30f040fca83f35d6e98e1b8a776e66543e05ea
parent700698a8a9741063c9804c7bce2dbec6c8d69f3d (diff)
KVM: arm64/sve: Clean up UAPI register ID definitions
Currently, the SVE register ID macros are not all defined in the same way, and advertise the fact that FFR maps onto the nonexistent predicate register P16. This is really just for kernel convenience, and may lead userspace into bad habits. Instead, this patch masks the ID macro arguments so that architecturally invalid register numbers will not be passed through any more, and uses a literal KVM_REG_ARM64_SVE_FFR_BASE macro to define KVM_REG_ARM64_SVE_FFR(), similarly to the way the _ZREG() and _PREG() macros are defined. Rather than plugging in magic numbers for the number of Z- and P- registers and the maximum possible number of register slices, this patch provides definitions for those too. Userspace is going to need them in any case, and it makes sense for them to come from <uapi/asm/kvm.h>. sve_reg_to_region() uses convenience constants that are defined in a different way, and also makes use of the fact that the FFR IDs are really contiguous with the P15 IDs, so this patch retains the existing convenience constants in guest.c, supplemented with a couple of sanity checks to check for consistency with the UAPI header. Fixes: e1c9c98345b3 ("KVM: arm64/sve: Add SVE support to register access ioctl interface") Suggested-by: Andrew Jones <drjones@redhat.com> Signed-off-by: Dave Martin <Dave.Martin@arm.com> Reviewed-by: Andrew Jones <drjones@redhat.com> Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
-rw-r--r--arch/arm64/include/uapi/asm/kvm.h32
-rw-r--r--arch/arm64/kvm/guest.c9
2 files changed, 32 insertions, 9 deletions
diff --git a/arch/arm64/include/uapi/asm/kvm.h b/arch/arm64/include/uapi/asm/kvm.h
index 6963b7e8062b..2a04ef015469 100644
--- a/arch/arm64/include/uapi/asm/kvm.h
+++ b/arch/arm64/include/uapi/asm/kvm.h
@@ -35,6 +35,7 @@
35#include <linux/psci.h> 35#include <linux/psci.h>
36#include <linux/types.h> 36#include <linux/types.h>
37#include <asm/ptrace.h> 37#include <asm/ptrace.h>
38#include <asm/sve_context.h>
38 39
39#define __KVM_HAVE_GUEST_DEBUG 40#define __KVM_HAVE_GUEST_DEBUG
40#define __KVM_HAVE_IRQ_LINE 41#define __KVM_HAVE_IRQ_LINE
@@ -233,16 +234,29 @@ struct kvm_vcpu_events {
233/* Z- and P-regs occupy blocks at the following offsets within this range: */ 234/* Z- and P-regs occupy blocks at the following offsets within this range: */
234#define KVM_REG_ARM64_SVE_ZREG_BASE 0 235#define KVM_REG_ARM64_SVE_ZREG_BASE 0
235#define KVM_REG_ARM64_SVE_PREG_BASE 0x400 236#define KVM_REG_ARM64_SVE_PREG_BASE 0x400
237#define KVM_REG_ARM64_SVE_FFR_BASE 0x600
236 238
237#define KVM_REG_ARM64_SVE_ZREG(n, i) (KVM_REG_ARM64 | KVM_REG_ARM64_SVE | \ 239#define KVM_ARM64_SVE_NUM_ZREGS __SVE_NUM_ZREGS
238 KVM_REG_ARM64_SVE_ZREG_BASE | \ 240#define KVM_ARM64_SVE_NUM_PREGS __SVE_NUM_PREGS
239 KVM_REG_SIZE_U2048 | \ 241
240 ((n) << 5) | (i)) 242#define KVM_ARM64_SVE_MAX_SLICES 32
241#define KVM_REG_ARM64_SVE_PREG(n, i) (KVM_REG_ARM64 | KVM_REG_ARM64_SVE | \ 243
242 KVM_REG_ARM64_SVE_PREG_BASE | \ 244#define KVM_REG_ARM64_SVE_ZREG(n, i) \
243 KVM_REG_SIZE_U256 | \ 245 (KVM_REG_ARM64 | KVM_REG_ARM64_SVE | KVM_REG_ARM64_SVE_ZREG_BASE | \
244 ((n) << 5) | (i)) 246 KVM_REG_SIZE_U2048 | \
245#define KVM_REG_ARM64_SVE_FFR(i) KVM_REG_ARM64_SVE_PREG(16, i) 247 (((n) & (KVM_ARM64_SVE_NUM_ZREGS - 1)) << 5) | \
248 ((i) & (KVM_ARM64_SVE_MAX_SLICES - 1)))
249
250#define KVM_REG_ARM64_SVE_PREG(n, i) \
251 (KVM_REG_ARM64 | KVM_REG_ARM64_SVE | KVM_REG_ARM64_SVE_PREG_BASE | \
252 KVM_REG_SIZE_U256 | \
253 (((n) & (KVM_ARM64_SVE_NUM_PREGS - 1)) << 5) | \
254 ((i) & (KVM_ARM64_SVE_MAX_SLICES - 1)))
255
256#define KVM_REG_ARM64_SVE_FFR(i) \
257 (KVM_REG_ARM64 | KVM_REG_ARM64_SVE | KVM_REG_ARM64_SVE_FFR_BASE | \
258 KVM_REG_SIZE_U256 | \
259 ((i) & (KVM_ARM64_SVE_MAX_SLICES - 1)))
246 260
247/* Vector lengths pseudo-register: */ 261/* Vector lengths pseudo-register: */
248#define KVM_REG_ARM64_SVE_VLS (KVM_REG_ARM64 | KVM_REG_ARM64_SVE | \ 262#define KVM_REG_ARM64_SVE_VLS (KVM_REG_ARM64 | KVM_REG_ARM64_SVE | \
diff --git a/arch/arm64/kvm/guest.c b/arch/arm64/kvm/guest.c
index 4f7b26bbf671..2e449e1dea73 100644
--- a/arch/arm64/kvm/guest.c
+++ b/arch/arm64/kvm/guest.c
@@ -325,6 +325,15 @@ static int sve_reg_to_region(struct sve_state_reg_region *region,
325 325
326 size_t sve_state_size; 326 size_t sve_state_size;
327 327
328 const u64 last_preg_id = KVM_REG_ARM64_SVE_PREG(SVE_NUM_PREGS - 1,
329 SVE_NUM_SLICES - 1);
330
331 /* Verify that the P-regs and FFR really do have contiguous IDs: */
332 BUILD_BUG_ON(KVM_REG_ARM64_SVE_FFR(0) != last_preg_id + 1);
333
334 /* Verify that we match the UAPI header: */
335 BUILD_BUG_ON(SVE_NUM_SLICES != KVM_ARM64_SVE_MAX_SLICES);
336
328 /* Only the first slice ever exists, for now: */ 337 /* Only the first slice ever exists, for now: */
329 if ((reg->id & SVE_REG_SLICE_MASK) != 0) 338 if ((reg->id & SVE_REG_SLICE_MASK) != 0)
330 return -ENOENT; 339 return -ENOENT;