Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F150016063
D25463.id73691.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
4 KB
Referenced Files
None
Subscribers
None
D25463.id73691.diff
View Options
Index: sys/arm64/arm64/identcpu.c
===================================================================
--- sys/arm64/arm64/identcpu.c
+++ sys/arm64/arm64/identcpu.c
@@ -134,6 +134,7 @@
};
static struct cpu_desc cpu_desc[MAXCPU];
+static struct cpu_desc kern_cpu_desc;
static struct cpu_desc user_cpu_desc;
static u_int cpu_print_regs;
#define PRINT_ID_AA64_AFR0 0x00000001
@@ -936,46 +937,109 @@
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);
+}
+
+static uint64_t
+update_lower_register(uint64_t val, uint64_t new_val, u_int shift,
+ int width, bool sign)
+{
+ uint64_t mask;
+ uint64_t new_field, old_field;
+ bool update;
+
+ KASSERT(width > 0 && width < 64, ("%s: Invalid width %d", __func__,
+ width));
+
+ mask = (1ul << width) - 1;
+ new_field = (new_val >> shift) & mask;
+ old_field = (val >> shift) & mask;
+
+ update = false;
+ if (sign) {
+ /*
+ * The field is signed. Toggle the upper bit so the comparison
+ * works on unsigned values as this makes positive numbers,
+ * i.e. those with a 0 bit, larger than negative numbers,
+ * i.e. those with a 1 bit, in an unsigned comparison.
+ */
+ if ((new_field ^ (1ul << (width - 1))) <
+ (old_field ^ (1ul << (width - 1))))
+ update = true;
+ } else {
+ if (new_field < old_field)
+ update = true;
+ }
+
+ if (update) {
+ val &= ~(mask << shift);
+ val |= new_field << shift;
+ }
+
+ return (val);
+}
+
static void
-update_user_regs(u_int cpu)
+update_special_regs(u_int cpu)
{
struct mrs_field *fields;
- uint64_t cur, value;
- int i, j, cur_field, new_field;
+ uint64_t user_reg, kern_reg, value;
+ int i, j;
+
+ if (cpu == 0) {
+ /* Create a user visible cpu description with safe values */
+ memset(&user_cpu_desc, 0, sizeof(user_cpu_desc));
+ /* Safe values for these registers */
+ user_cpu_desc.id_aa64pfr0 = ID_AA64PFR0_AdvSIMD_NONE |
+ ID_AA64PFR0_FP_NONE | ID_AA64PFR0_EL1_64 |
+ ID_AA64PFR0_EL0_64;
+ user_cpu_desc.id_aa64dfr0 = ID_AA64DFR0_DebugVer_8;
+ }
for (i = 0; i < nitems(user_regs); i++) {
value = CPU_DESC_FIELD(cpu_desc[cpu], i);
- if (cpu == 0)
- cur = value;
- else
- cur = CPU_DESC_FIELD(user_cpu_desc, i);
+ if (cpu == 0) {
+ kern_reg = value;
+ user_reg = value;
+ } else {
+ kern_reg = CPU_DESC_FIELD(kern_cpu_desc, i);
+ user_reg = CPU_DESC_FIELD(user_cpu_desc, i);
+ }
fields = user_regs[i].fields;
for (j = 0; fields[j].type != 0; j++) {
switch (fields[j].type & MRS_TYPE_MASK) {
case MRS_EXACT:
- cur &= ~(0xfu << fields[j].shift);
- cur |=
+ user_reg &= ~(0xfu << fields[j].shift);
+ user_reg |=
(uint64_t)MRS_EXACT_FIELD(fields[j].type) <<
fields[j].shift;
break;
case MRS_LOWER:
- new_field = (value >> fields[j].shift) & 0xf;
- cur_field = (cur >> fields[j].shift) & 0xf;
- if ((fields[j].sign &&
- (int)new_field < (int)cur_field) ||
- (!fields[j].sign &&
- (u_int)new_field < (u_int)cur_field)) {
- cur &= ~(0xfu << fields[j].shift);
- cur |= new_field << fields[j].shift;
- }
+ user_reg = update_lower_register(user_reg,
+ value, fields[j].shift, 4, fields[j].sign);
break;
default:
panic("Invalid field type: %d", fields[j].type);
}
+ kern_reg = update_lower_register(kern_reg, value,
+ fields[j].shift, 4, fields[j].sign);
}
- CPU_DESC_FIELD(user_cpu_desc, i) = cur;
+ CPU_DESC_FIELD(kern_cpu_desc, i) = kern_reg;
+ CPU_DESC_FIELD(user_cpu_desc, i) = user_reg;
}
}
@@ -997,13 +1061,6 @@
u_long hwcap;
bool dic, idc;
- /* Create a user visible cpu description with safe values */
- memset(&user_cpu_desc, 0, sizeof(user_cpu_desc));
- /* Safe values for these registers */
- user_cpu_desc.id_aa64pfr0 = ID_AA64PFR0_AdvSIMD_NONE |
- ID_AA64PFR0_FP_NONE | ID_AA64PFR0_EL1_64 | ID_AA64PFR0_EL0_64;
- user_cpu_desc.id_aa64dfr0 = ID_AA64DFR0_DebugVer_8;
-
dic = (allow_dic != 0);
idc = (allow_idc != 0);
CPU_FOREACH(cpu) {
@@ -1013,7 +1070,7 @@
elf_hwcap = hwcap;
else
elf_hwcap &= hwcap;
- update_user_regs(cpu);
+ update_special_regs(cpu);
if (CTR_DIC_VAL(cpu_desc[cpu].ctr) == 0)
dic = false;
Index: sys/arm64/include/undefined.h
===================================================================
--- sys/arm64/include/undefined.h
+++ sys/arm64/include/undefined.h
@@ -62,7 +62,10 @@
void *install_undef_handler(bool, undef_handler_t);
void remove_undef_handler(void *);
int undef_insn(u_int, struct trapframe *);
+
+/* Functions to read the sanitised view of the special registers */
bool extract_user_id_field(u_int, u_int, uint8_t *);
+bool get_kernel_reg(u_int, uint64_t *);
#endif /* _KERNEL */
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Sun, Mar 29, 6:55 PM (13 h, 51 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
30547750
Default Alt Text
D25463.id73691.diff (4 KB)
Attached To
Mode
D25463: Create a kernel arm64 ID register view
Attached
Detach File
Event Timeline
Log In to Comment