Allow the userspace ID register fields to be read from the kernel
To allow consistent values to be used in both the kernel and userspace create a function for these to be read from the kernel. They use a newly created macro with the name of the ID register to read. For now there is redundant information in the user_regs array as it still holds the CRm and Op2 values, however this will be fixed in a later change. This will be used by ptrace to allow hardware breakpoints in userspace. Sponsored by: DARPA, AFRL
This commit is contained in:
parent
fc232b89ad
commit
e68508e172
@ -710,6 +710,7 @@ static struct mrs_field id_aa64pfr1_fields[] = {
|
||||
};
|
||||
|
||||
struct mrs_user_reg {
|
||||
u_int reg;
|
||||
u_int CRm;
|
||||
u_int Op2;
|
||||
size_t offset;
|
||||
@ -718,24 +719,28 @@ struct mrs_user_reg {
|
||||
|
||||
static struct mrs_user_reg user_regs[] = {
|
||||
{ /* id_aa64isar0_el1 */
|
||||
.reg = ID_AA64ISAR0_EL1,
|
||||
.CRm = 6,
|
||||
.Op2 = 0,
|
||||
.offset = __offsetof(struct cpu_desc, id_aa64isar0),
|
||||
.fields = id_aa64isar0_fields,
|
||||
},
|
||||
{ /* id_aa64isar1_el1 */
|
||||
.reg = ID_AA64ISAR1_EL1,
|
||||
.CRm = 6,
|
||||
.Op2 = 1,
|
||||
.offset = __offsetof(struct cpu_desc, id_aa64isar1),
|
||||
.fields = id_aa64isar1_fields,
|
||||
},
|
||||
{ /* id_aa64pfr0_el1 */
|
||||
.reg = ID_AA64PFR0_EL1,
|
||||
.CRm = 4,
|
||||
.Op2 = 0,
|
||||
.offset = __offsetof(struct cpu_desc, id_aa64pfr0),
|
||||
.fields = id_aa64pfr0_fields,
|
||||
},
|
||||
{ /* id_aa64dfr0_el1 */
|
||||
.reg = ID_AA64DFR0_EL1,
|
||||
.CRm = 5,
|
||||
.Op2 = 0,
|
||||
.offset = __offsetof(struct cpu_desc, id_aa64dfr0),
|
||||
@ -818,6 +823,23 @@ 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);
|
||||
}
|
||||
|
||||
static void
|
||||
update_user_regs(u_int cpu)
|
||||
{
|
||||
|
@ -51,6 +51,10 @@
|
||||
#define MRS_Op2_MASK 0x000000e0
|
||||
#define MRS_Rt_SHIFT 0
|
||||
#define MRS_Rt_MASK 0x0000001f
|
||||
#define MRS_REG(op0, op1, crn, crm, op2) \
|
||||
(((op0) << MRS_Op0_SHIFT) | ((op1) << MRS_Op1_SHIFT) | \
|
||||
((crn) << MRS_CRn_SHIFT) | ((crm) << MRS_CRm_SHIFT) | \
|
||||
((op2) << MRS_Op2_SHIFT))
|
||||
|
||||
#define READ_SPECIALREG(reg) \
|
||||
({ uint64_t _val; \
|
||||
@ -193,6 +197,7 @@
|
||||
#define ICC_SRE_EL2_EN (1U << 3)
|
||||
|
||||
/* ID_AA64DFR0_EL1 */
|
||||
#define ID_AA64DFR0_EL1 MRS_REG(3, 0, 0, 5, 0)
|
||||
#define ID_AA64DFR0_DebugVer_SHIFT 0
|
||||
#define ID_AA64DFR0_DebugVer_MASK (UL(0xf) << ID_AA64DFR0_DebugVer_SHIFT)
|
||||
#define ID_AA64DFR0_DebugVer_VAL(x) ((x) & ID_AA64DFR0_DebugVer_MASK)
|
||||
@ -230,6 +235,7 @@
|
||||
#define ID_AA64DFR0_PMSVer_V1 (UL(0x1) << ID_AA64DFR0_PMSVer_SHIFT)
|
||||
|
||||
/* ID_AA64ISAR0_EL1 */
|
||||
#define ID_AA64ISAR0_EL1 MRS_REG(3, 0, 0, 6, 0)
|
||||
#define ID_AA64ISAR0_AES_SHIFT 4
|
||||
#define ID_AA64ISAR0_AES_MASK (UL(0xf) << ID_AA64ISAR0_AES_SHIFT)
|
||||
#define ID_AA64ISAR0_AES_VAL(x) ((x) & ID_AA64ISAR0_AES_MASK)
|
||||
@ -284,6 +290,7 @@
|
||||
#define ID_AA64ISAR0_DP_IMPL (UL(0x1) << ID_AA64ISAR0_DP_SHIFT)
|
||||
|
||||
/* ID_AA64ISAR1_EL1 */
|
||||
#define ID_AA64ISAR1_EL1 MRS_REG(3, 0, 0, 6, 1)
|
||||
#define ID_AA64ISAR1_DPB_SHIFT 0
|
||||
#define ID_AA64ISAR1_DPB_MASK (UL(0xf) << ID_AA64ISAR1_DPB_SHIFT)
|
||||
#define ID_AA64ISAR1_DPB_VAL(x) ((x) & ID_AA64ISAR1_DPB_MASK)
|
||||
@ -326,6 +333,7 @@
|
||||
#define ID_AA64ISAR1_GPI_IMPL (UL(0x1) << ID_AA64ISAR1_GPI_SHIFT)
|
||||
|
||||
/* ID_AA64MMFR0_EL1 */
|
||||
#define ID_AA64MMFR0_EL1 MRS_REG(3, 0, 0, 7, 0)
|
||||
#define ID_AA64MMFR0_PARange_SHIFT 0
|
||||
#define ID_AA64MMFR0_PARange_MASK (UL(0xf) << ID_AA64MMFR0_PARange_SHIFT)
|
||||
#define ID_AA64MMFR0_PARange_VAL(x) ((x) & ID_AA64MMFR0_PARange_MASK)
|
||||
@ -373,6 +381,7 @@
|
||||
#define ID_AA64MMFR0_TGran4_NONE (UL(0xf) << ID_AA64MMFR0_TGran4_SHIFT)
|
||||
|
||||
/* ID_AA64MMFR1_EL1 */
|
||||
#define ID_AA64MMFR1_EL1 MRS_REG(3, 0, 0, 7, 1)
|
||||
#define ID_AA64MMFR1_HAFDBS_SHIFT 0
|
||||
#define ID_AA64MMFR1_HAFDBS_MASK (UL(0xf) << ID_AA64MMFR1_HAFDBS_SHIFT)
|
||||
#define ID_AA64MMFR1_HAFDBS_VAL(x) ((x) & ID_AA64MMFR1_HAFDBS_MASK)
|
||||
@ -418,7 +427,7 @@
|
||||
#define ID_AA64MMFR1_XNX_IMPL (UL(0x1) << ID_AA64MMFR1_XNX_SHIFT)
|
||||
|
||||
/* ID_AA64MMFR2_EL1 */
|
||||
#define ID_AA64MMFR2_EL1 S3_0_C0_C7_2
|
||||
#define ID_AA64MMFR2_EL1 MRS_REG(3, 0, 0, 7, 2)
|
||||
#define ID_AA64MMFR2_CnP_SHIFT 0
|
||||
#define ID_AA64MMFR2_CnP_MASK (UL(0xf) << ID_AA64MMFR2_CnP_SHIFT)
|
||||
#define ID_AA64MMFR2_CnP_VAL(x) ((x) & ID_AA64MMFR2_CnP_MASK)
|
||||
@ -456,6 +465,7 @@
|
||||
#define ID_AA64MMFR2_NV_IMPL (UL(0x1) << ID_AA64MMFR2_NV_SHIFT)
|
||||
|
||||
/* ID_AA64PFR0_EL1 */
|
||||
#define ID_AA64PFR0_EL1 MRS_REG(3, 0, 0, 4, 0)
|
||||
#define ID_AA64PFR0_EL0_SHIFT 0
|
||||
#define ID_AA64PFR0_EL0_MASK (UL(0xf) << ID_AA64PFR0_EL0_SHIFT)
|
||||
#define ID_AA64PFR0_EL0_VAL(x) ((x) & ID_AA64PFR0_EL0_MASK)
|
||||
|
@ -33,6 +33,8 @@
|
||||
#ifndef _MACHINE__UNDEFINED_H_
|
||||
#define _MACHINE__UNDEFINED_H_
|
||||
|
||||
#ifdef _KERNEL
|
||||
|
||||
typedef int (*undef_handler_t)(vm_offset_t, uint32_t, struct trapframe *,
|
||||
uint32_t);
|
||||
|
||||
@ -60,5 +62,8 @@ void undef_init(void);
|
||||
void *install_undef_handler(bool, undef_handler_t);
|
||||
void remove_undef_handler(void *);
|
||||
int undef_insn(u_int, struct trapframe *);
|
||||
bool extract_user_id_field(u_int, u_int, uint8_t *);
|
||||
|
||||
#endif /* _KERNEL */
|
||||
|
||||
#endif
|
||||
|
Loading…
x
Reference in New Issue
Block a user