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