Page MenuHomeFreeBSD

D42372.diff
No OneTemporary

D42372.diff

diff --git a/sys/arm64/arm64/elf_machdep.c b/sys/arm64/arm64/elf_machdep.c
--- a/sys/arm64/arm64/elf_machdep.c
+++ b/sys/arm64/arm64/elf_machdep.c
@@ -56,6 +56,9 @@
u_long __read_frequently elf_hwcap;
u_long __read_frequently elf_hwcap2;
+/* TODO: Move to a better location */
+u_long __read_frequently linux_elf_hwcap;
+u_long __read_frequently linux_elf_hwcap2;
struct arm64_addr_mask elf64_addr_mask;
diff --git a/sys/arm64/arm64/identcpu.c b/sys/arm64/arm64/identcpu.c
--- a/sys/arm64/arm64/identcpu.c
+++ b/sys/arm64/arm64/identcpu.c
@@ -33,10 +33,12 @@
#include <sys/param.h>
#include <sys/kernel.h>
#include <sys/malloc.h>
+#include <sys/proc.h>
#include <sys/pcpu.h>
#include <sys/sbuf.h>
#include <sys/smp.h>
#include <sys/sysctl.h>
+#include <sys/sysent.h>
#include <sys/systm.h>
#include <machine/atomic.h>
@@ -162,6 +164,7 @@
static struct cpu_desc *cpu_desc;
static struct cpu_desc kern_cpu_desc;
static struct cpu_desc user_cpu_desc;
+static struct cpu_desc l_user_cpu_desc;
static struct cpu_desc *
get_cpu_desc(u_int cpu)
@@ -275,10 +278,12 @@
};
#define MRS_TYPE_MASK 0xf
+#define MRS_TYPE_FBSD_SHIFT 0
+#define MRS_TYPE_LNX_SHIFT 8
#define MRS_INVALID 0
#define MRS_EXACT 1
#define MRS_EXACT_VAL(x) (MRS_EXACT | ((x) << 4))
-#define MRS_EXACT_FIELD(x) ((x) >> 4)
+#define MRS_EXACT_FIELD(x) (((x) >> 4) & 0xf)
#define MRS_LOWER 2
struct mrs_field_value {
@@ -341,17 +346,23 @@
u_int shift;
};
-#define MRS_FIELD_HWCAP(_register, _name, _sign, _type, _values, _hwcap) \
+#define MRS_FIELD_HWCAP_SPLIT(_register, _name, _sign, _fbsd_type, \
+ _lnx_type, _values, _hwcap) \
{ \
.name = #_name, \
.sign = (_sign), \
- .type = (_type), \
+ .type = ((_fbsd_type) << MRS_TYPE_FBSD_SHIFT) | \
+ ((_lnx_type) << MRS_TYPE_LNX_SHIFT), \
.shift = _register ## _ ## _name ## _SHIFT, \
.mask = _register ## _ ## _name ## _MASK, \
.values = (_values), \
.hwcaps = (_hwcap), \
}
+#define MRS_FIELD_HWCAP(_register, _name, _sign, _type, _values, _hwcap) \
+ MRS_FIELD_HWCAP_SPLIT(_register, _name, _sign, _type, _type, \
+ _values, _hwcap)
+
#define MRS_FIELD(_register, _name, _sign, _type, _values) \
MRS_FIELD_HWCAP(_register, _name, _sign, _type, _values, NULL)
@@ -1911,7 +1922,10 @@
for (i = 0; i < nitems(user_regs); i++) {
if (user_regs[i].CRm == CRm && user_regs[i].Op2 == Op2) {
- value = CPU_DESC_FIELD(user_cpu_desc, i);
+ if (SV_CURPROC_ABI() == SV_ABI_FREEBSD)
+ value = CPU_DESC_FIELD(user_cpu_desc, i);
+ else
+ value = CPU_DESC_FIELD(l_user_cpu_desc, i);
break;
}
}
@@ -2064,12 +2078,32 @@
return (false);
}
+static uint64_t
+update_special_reg_field(uint64_t user_reg, u_int type, uint64_t value,
+ u_int shift, bool sign)
+{
+ switch (type & MRS_TYPE_MASK) {
+ case MRS_EXACT:
+ user_reg &= ~(0xful << shift);
+ user_reg |= (uint64_t)MRS_EXACT_FIELD(type) << shift;
+ break;
+ case MRS_LOWER:
+ user_reg = update_lower_register(user_reg, value, shift, 4,
+ sign);
+ break;
+ default:
+ panic("Invalid field type: %d", type);
+ }
+
+ return (user_reg);
+}
+
void
update_special_regs(u_int cpu)
{
struct cpu_desc *desc;
const struct mrs_field *fields;
- uint64_t user_reg, kern_reg, value;
+ uint64_t l_user_reg, user_reg, kern_reg, value;
int i, j;
if (cpu == 0) {
@@ -2080,6 +2114,8 @@
ID_AA64PFR0_FP_NONE | ID_AA64PFR0_EL1_64 |
ID_AA64PFR0_EL0_64;
user_cpu_desc.id_aa64dfr0 = ID_AA64DFR0_DebugVer_8;
+ /* Create the Linux user visible cpu description */
+ memcpy(&l_user_cpu_desc, &user_cpu_desc, sizeof(user_cpu_desc));
}
desc = get_cpu_desc(cpu);
@@ -2088,33 +2124,33 @@
if (cpu == 0) {
kern_reg = value;
user_reg = value;
+ l_user_reg = value;
} else {
kern_reg = CPU_DESC_FIELD(kern_cpu_desc, i);
user_reg = CPU_DESC_FIELD(user_cpu_desc, i);
+ l_user_reg = CPU_DESC_FIELD(l_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:
- user_reg &= ~(0xful << fields[j].shift);
- user_reg |=
- (uint64_t)MRS_EXACT_FIELD(fields[j].type) <<
- fields[j].shift;
- break;
- case MRS_LOWER:
- 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);
- }
+ /* Update the FreeBSD userspace ID register view */
+ user_reg = update_special_reg_field(user_reg,
+ fields[j].type >> MRS_TYPE_FBSD_SHIFT, value,
+ fields[j].shift, fields[j].sign);
+
+ /* Update the Linux userspace ID register view */
+ l_user_reg = update_special_reg_field(l_user_reg,
+ fields[j].type >> MRS_TYPE_LNX_SHIFT, value,
+ fields[j].shift, fields[j].sign);
+
+ /* Update the kernel ID register view */
kern_reg = update_lower_register(kern_reg, value,
fields[j].shift, 4, fields[j].sign);
}
CPU_DESC_FIELD(kern_cpu_desc, i) = kern_reg;
CPU_DESC_FIELD(user_cpu_desc, i) = user_reg;
+ CPU_DESC_FIELD(l_user_cpu_desc, i) = l_user_reg;
}
}
@@ -2148,7 +2184,8 @@
* Find the values to export to userspace as AT_HWCAP and AT_HWCAP2.
*/
static void
-parse_cpu_features(bool is64bit, u_long *hwcap, u_long *hwcap2)
+parse_cpu_features(bool is64bit, struct cpu_desc *cpu_desc, u_long *hwcap,
+ u_long *hwcap2)
{
const struct mrs_field_hwcap *hwcaps;
const struct mrs_field *fields;
@@ -2160,7 +2197,7 @@
if (user_regs[i].is64bit != is64bit)
continue;
- reg = CPU_DESC_FIELD(user_cpu_desc, i);
+ reg = CPU_DESC_FIELD(*cpu_desc, i);
fields = user_regs[i].fields;
for (j = 0; fields[j].type != 0; j++) {
hwcaps = fields[j].hwcaps;
@@ -2216,13 +2253,16 @@
}
/* Find the values to export to userspace as AT_HWCAP and AT_HWCAP2 */
- parse_cpu_features(true, &elf_hwcap, &elf_hwcap2);
+ parse_cpu_features(true, &user_cpu_desc, &elf_hwcap, &elf_hwcap2);
+ parse_cpu_features(true, &l_user_cpu_desc, &linux_elf_hwcap,
+ &linux_elf_hwcap2);
#ifdef COMPAT_FREEBSD32
- parse_cpu_features(false, &elf32_hwcap, &elf32_hwcap2);
+ parse_cpu_features(false, &user_cpu_desc, &elf32_hwcap, &elf32_hwcap2);
#endif
/* We export the CPUID registers */
elf_hwcap |= HWCAP_CPUID;
+ linux_elf_hwcap |= HWCAP_CPUID;
#ifdef COMPAT_FREEBSD32
/* Set the default caps and any that need to check multiple fields */
diff --git a/sys/arm64/include/md_var.h b/sys/arm64/include/md_var.h
--- a/sys/arm64/include/md_var.h
+++ b/sys/arm64/include/md_var.h
@@ -37,6 +37,8 @@
extern int szsigcode;
extern u_long elf_hwcap;
extern u_long elf_hwcap2;
+extern u_long linux_elf_hwcap;
+extern u_long linux_elf_hwcap2;
#ifdef COMPAT_FREEBSD32
extern u_long elf32_hwcap;
extern u_long elf32_hwcap2;
diff --git a/sys/arm64/linux/linux_sysvec.c b/sys/arm64/linux/linux_sysvec.c
--- a/sys/arm64/linux/linux_sysvec.c
+++ b/sys/arm64/linux/linux_sysvec.c
@@ -456,8 +456,8 @@
.sv_schedtail = linux_schedtail,
.sv_thread_detach = linux_thread_detach,
.sv_trap = NULL,
- .sv_hwcap = &elf_hwcap,
- .sv_hwcap2 = &elf_hwcap2,
+ .sv_hwcap = &linux_elf_hwcap,
+ .sv_hwcap2 = &linux_elf_hwcap2,
.sv_onexec = linux_on_exec_vmspace,
.sv_onexit = linux_on_exit,
.sv_ontdexit = linux_thread_dtor,

File Metadata

Mime Type
text/plain
Expires
Wed, Jan 14, 8:06 AM (20 h, 40 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
27635539
Default Alt Text
D42372.diff (7 KB)

Event Timeline