Revision f59df3f2
b/target-arm/cpu.h | ||
---|---|---|
811 | 811 |
|
812 | 812 |
typedef struct ARMCPRegInfo ARMCPRegInfo; |
813 | 813 |
|
814 |
/* Access functions for coprocessor registers. These should return |
|
815 |
* 0 on success, or one of the EXCP_* constants if access should cause |
|
816 |
* an exception (in which case *value is not written). |
|
817 |
*/ |
|
814 |
typedef enum CPAccessResult { |
|
815 |
/* Access is permitted */ |
|
816 |
CP_ACCESS_OK = 0, |
|
817 |
/* Access fails due to a configurable trap or enable which would |
|
818 |
* result in a categorized exception syndrome giving information about |
|
819 |
* the failing instruction (ie syndrome category 0x3, 0x4, 0x5, 0x6, |
|
820 |
* 0xc or 0x18). |
|
821 |
*/ |
|
822 |
CP_ACCESS_TRAP = 1, |
|
823 |
/* Access fails and results in an exception syndrome 0x0 ("uncategorized"). |
|
824 |
* Note that this is not a catch-all case -- the set of cases which may |
|
825 |
* result in this failure is specifically defined by the architecture. |
|
826 |
*/ |
|
827 |
CP_ACCESS_TRAP_UNCATEGORIZED = 2, |
|
828 |
} CPAccessResult; |
|
829 |
|
|
830 |
/* Access functions for coprocessor registers. These should always succeed. */ |
|
818 | 831 |
typedef int CPReadFn(CPUARMState *env, const ARMCPRegInfo *opaque, |
819 | 832 |
uint64_t *value); |
820 | 833 |
typedef int CPWriteFn(CPUARMState *env, const ARMCPRegInfo *opaque, |
821 | 834 |
uint64_t value); |
835 |
/* Access permission check functions for coprocessor registers. */ |
|
836 |
typedef CPAccessResult CPAccessFn(CPUARMState *env, const ARMCPRegInfo *opaque); |
|
822 | 837 |
/* Hook function for register reset */ |
823 | 838 |
typedef void CPResetFn(CPUARMState *env, const ARMCPRegInfo *opaque); |
824 | 839 |
|
... | ... | |
872 | 887 |
* 2. both readfn and writefn are specified |
873 | 888 |
*/ |
874 | 889 |
ptrdiff_t fieldoffset; /* offsetof(CPUARMState, field) */ |
890 |
/* Function for making any access checks for this register in addition to |
|
891 |
* those specified by the 'access' permissions bits. If NULL, no extra |
|
892 |
* checks required. The access check is performed at runtime, not at |
|
893 |
* translate time. |
|
894 |
*/ |
|
895 |
CPAccessFn *accessfn; |
|
875 | 896 |
/* Function for handling reads of this register. If NULL, then reads |
876 | 897 |
* will be done by loading from the offset into CPUARMState specified |
877 | 898 |
* by fieldoffset. |
b/target-arm/helper.h | ||
---|---|---|
57 | 57 |
DEF_HELPER_3(v7m_msr, void, env, i32, i32) |
58 | 58 |
DEF_HELPER_2(v7m_mrs, i32, env, i32) |
59 | 59 |
|
60 |
DEF_HELPER_2(access_check_cp_reg, void, env, ptr) |
|
60 | 61 |
DEF_HELPER_3(set_cp_reg, void, env, ptr, i32) |
61 | 62 |
DEF_HELPER_2(get_cp_reg, i32, env, ptr) |
62 | 63 |
DEF_HELPER_3(set_cp_reg64, void, env, ptr, i64) |
b/target-arm/op_helper.c | ||
---|---|---|
273 | 273 |
} |
274 | 274 |
} |
275 | 275 |
|
276 |
void HELPER(access_check_cp_reg)(CPUARMState *env, void *rip) |
|
277 |
{ |
|
278 |
const ARMCPRegInfo *ri = rip; |
|
279 |
switch (ri->accessfn(env, ri)) { |
|
280 |
case CP_ACCESS_OK: |
|
281 |
return; |
|
282 |
case CP_ACCESS_TRAP: |
|
283 |
case CP_ACCESS_TRAP_UNCATEGORIZED: |
|
284 |
/* These cases will eventually need to generate different |
|
285 |
* syndrome information. |
|
286 |
*/ |
|
287 |
break; |
|
288 |
default: |
|
289 |
g_assert_not_reached(); |
|
290 |
} |
|
291 |
raise_exception(env, EXCP_UDEF); |
|
292 |
} |
|
293 |
|
|
276 | 294 |
void HELPER(set_cp_reg)(CPUARMState *env, void *rip, uint32_t value) |
277 | 295 |
{ |
278 | 296 |
const ARMCPRegInfo *ri = rip; |
b/target-arm/translate-a64.c | ||
---|---|---|
1193 | 1193 |
return; |
1194 | 1194 |
} |
1195 | 1195 |
|
1196 |
if (ri->accessfn) { |
|
1197 |
/* Emit code to perform further access permissions checks at |
|
1198 |
* runtime; this may result in an exception. |
|
1199 |
*/ |
|
1200 |
TCGv_ptr tmpptr; |
|
1201 |
gen_a64_set_pc_im(s->pc - 4); |
|
1202 |
tmpptr = tcg_const_ptr(ri); |
|
1203 |
gen_helper_access_check_cp_reg(cpu_env, tmpptr); |
|
1204 |
tcg_temp_free_ptr(tmpptr); |
|
1205 |
} |
|
1206 |
|
|
1196 | 1207 |
/* Handle special cases first */ |
1197 | 1208 |
switch (ri->type & ~(ARM_CP_FLAG_MASK & ~ARM_CP_SPECIAL)) { |
1198 | 1209 |
case ARM_CP_NOP: |
b/target-arm/translate.c | ||
---|---|---|
6837 | 6837 |
return 1; |
6838 | 6838 |
} |
6839 | 6839 |
|
6840 |
if (ri->accessfn) { |
|
6841 |
/* Emit code to perform further access permissions checks at |
|
6842 |
* runtime; this may result in an exception. |
|
6843 |
*/ |
|
6844 |
TCGv_ptr tmpptr; |
|
6845 |
gen_set_pc_im(s, s->pc); |
|
6846 |
tmpptr = tcg_const_ptr(ri); |
|
6847 |
gen_helper_access_check_cp_reg(cpu_env, tmpptr); |
|
6848 |
tcg_temp_free_ptr(tmpptr); |
|
6849 |
} |
|
6850 |
|
|
6840 | 6851 |
/* Handle special cases first */ |
6841 | 6852 |
switch (ri->type & ~(ARM_CP_FLAG_MASK & ~ARM_CP_SPECIAL)) { |
6842 | 6853 |
case ARM_CP_NOP: |
Also available in: Unified diff