The branch main has been updated by markj:

URL: 
https://cgit.FreeBSD.org/src/commit/?id=fbec1f91951fe01c1c590bab5e6c16a30884f352

commit fbec1f91951fe01c1c590bab5e6c16a30884f352
Author:     Mark Johnston <[email protected]>
AuthorDate: 2023-06-28 20:12:47 +0000
Commit:     Mark Johnston <[email protected]>
CommitDate: 2023-06-28 20:29:49 +0000

    arm64: Add a masked get_kernel_reg()
    
    This lets consumers fetch the value of a system register and apply a
    mask over individual fields.  That is, each field in the returned value
    will be the "smaller" of the two provided by "mask" and the value saved
    in kern_cpu_desc.  This will be used by vmm to sanitize host system
    register fields.
    
    Reviewed by:    andrew
    MFC after:      2 weeks
    Sponsored by:   The FreeBSD Foundation
    Sponsored by:   Klara, Inc. (hardware)
    Differential Revision:  https://reviews.freebsd.org/D40500
---
 sys/arm64/arm64/identcpu.c | 90 +++++++++++++++++++++++++++++-----------------
 sys/arm64/include/cpu.h    |  1 +
 2 files changed, 59 insertions(+), 32 deletions(-)

diff --git a/sys/arm64/arm64/identcpu.c b/sys/arm64/arm64/identcpu.c
index e96f0a089784..01e663ff47c2 100644
--- a/sys/arm64/arm64/identcpu.c
+++ b/sys/arm64/arm64/identcpu.c
@@ -1721,38 +1721,6 @@ user_mrs_handler(vm_offset_t va, uint32_t insn, struct 
trapframe *frame,
        return (1);
 }
 
-bool
-extract_user_id_field(u_int reg, u_int field_shift, uint8_t *val)
-{
-       uint64_t value;
-       int i;
-
-       for (i = 0; i < nitems(user_regs); i++) {
-               if (user_regs[i].reg == reg) {
-                       value = CPU_DESC_FIELD(user_cpu_desc, i);
-                       *val = value >> field_shift;
-                       return (true);
-               }
-       }
-
-       return (false);
-}
-
-bool
-get_kernel_reg(u_int reg, uint64_t *val)
-{
-       int i;
-
-       for (i = 0; i < nitems(user_regs); i++) {
-               if (user_regs[i].reg == reg) {
-                       *val = CPU_DESC_FIELD(kern_cpu_desc, i);
-                       return (true);
-               }
-       }
-
-       return (false);
-}
-
 /*
  * Compares two field values that may be signed or unsigned.
  * Returns:
@@ -1808,6 +1776,64 @@ update_lower_register(uint64_t val, uint64_t new_val, 
u_int shift,
        return (val);
 }
 
+bool
+extract_user_id_field(u_int reg, u_int field_shift, uint8_t *val)
+{
+       uint64_t value;
+       int i;
+
+       for (i = 0; i < nitems(user_regs); i++) {
+               if (user_regs[i].reg == reg) {
+                       value = CPU_DESC_FIELD(user_cpu_desc, i);
+                       *val = value >> field_shift;
+                       return (true);
+               }
+       }
+
+       return (false);
+}
+
+bool
+get_kernel_reg(u_int reg, uint64_t *val)
+{
+       int i;
+
+       for (i = 0; i < nitems(user_regs); i++) {
+               if (user_regs[i].reg == reg) {
+                       *val = CPU_DESC_FIELD(kern_cpu_desc, i);
+                       return (true);
+               }
+       }
+
+       return (false);
+}
+
+/*
+ * Fetch the specified register's value, ensuring that individual field values
+ * do not exceed those in the mask.
+ */
+bool
+get_kernel_reg_masked(u_int reg, uint64_t *valp, uint64_t mask)
+{
+       struct mrs_field *fields;
+       uint64_t val;
+
+       for (int i = 0; i < nitems(user_regs); i++) {
+               if (user_regs[i].reg == reg) {
+                       val = CPU_DESC_FIELD(kern_cpu_desc, i);
+                       *valp = 0;
+                       fields = user_regs[i].fields;
+                       for (int j = 0; fields[j].type != 0; j++) {
+                               *valp |= update_lower_register(mask, val,
+                                   fields[j].shift, 4, fields[j].sign);
+                       }
+                       return (true);
+               }
+       }
+
+       return (false);
+}
+
 void
 update_special_regs(u_int cpu)
 {
diff --git a/sys/arm64/include/cpu.h b/sys/arm64/include/cpu.h
index 1ea497756698..0bb320f2e0a0 100644
--- a/sys/arm64/include/cpu.h
+++ b/sys/arm64/include/cpu.h
@@ -213,6 +213,7 @@ void        ptrauth_mp_start(uint64_t);
 void   update_special_regs(u_int);
 bool   extract_user_id_field(u_int, u_int, uint8_t *);
 bool   get_kernel_reg(u_int, uint64_t *);
+bool   get_kernel_reg_masked(u_int, uint64_t *, uint64_t);
 
 void   cpu_desc_init(void);
 

Reply via email to