Hi Chengyu, On 12/03/2014 02:12 AM, Chengyu Song wrote: > In AA64 mode, certain system registers are access through MSR/MRS > instructions instead of MCR/MRC. This patch added more such registers:
If you don't mind sharing, I'm curious what motivated this patch. I have a particular interest in having `perf stat -e instructions:u echo` inside qemu-system-aarch64 function correctly, and this looks like a good step in that direction. > /* ARMv8 manual, D8.4.10 */ > PMINTENCLR_EL1 It'd probably good to mention the version of the document. > /* ARMv8 manual, D8.4.11 */ > PMINTENSET_EL1 > > /* ARMv8 manual, D8.4.12 */ > PMOVSCLR_EL0 > > /* ARMv8 manual, D8.4.14 */ > PMSELR_EL0 > > /* ARMv8 manual, D8.4.15 */ > PMSWINC_EL0 > > /* ARMv8 manual, D8.4.16 */ > PMUSERENR_EL0 > > /* ARMv8 manual, D8.4.17 */ > PMXEVCNTR_EL0 > > /* ARMv8 manual, D8.4.18 */ > PMXEVTYPER_EL0 > > Signed-off-by: Chengyu Song <cson...@gatech.edu> > --- > target-arm/helper.c | 40 ++++++++++++++++++++++++++++++++++++++++ > 1 file changed, 40 insertions(+) > > diff --git a/target-arm/helper.c b/target-arm/helper.c > index b74d348..43b5b06 100644 > --- a/target-arm/helper.c > +++ b/target-arm/helper.c > @@ -843,15 +843,28 @@ static const ARMCPRegInfo v7_cp_reginfo[] = { > .accessfn = pmreg_access, > .writefn = pmovsr_write, > .raw_writefn = raw_write }, > + { .name = "PMOVSCLR_EL0", .state = ARM_CP_STATE_AA64, > + .opc0 = 3, .crn = 9, .crm = 12, .opc1 = 3, .opc2 = 3, It might be helpful to order the fields opc0, opc1, crn, crm, opc2 to match the documentation and some (most?) of the other A64 QEMU code. > + .access = PL0_RW, .fieldoffset = offsetof(CPUARMState, cp15.c9_pmovsr), > + .accessfn = pmreg_access, > + .writefn = pmovsr_write, > + .raw_writefn = raw_write }, Should this contain .type = ARM_CP_NO_MIGRATE, if PMOVSCLR_EL0, PMOVSSET_EL0, and PMOVSR all refer to the same underlying variable? Should PMOVSSET_EL0 also be added? > /* Unimplemented so WI. */ > { .name = "PMSWINC", .cp = 15, .crn = 9, .crm = 12, .opc1 = 0, .opc2 = 4, > .access = PL0_W, .accessfn = pmreg_access, .type = ARM_CP_NOP }, > + { .name = "PMSWINC_EL0", .state = ARM_CP_STATE_AA64, > + .opc0 = 3, .crn = 9, .crm = 12, .opc1 = 3, .opc2 = 4, > + .access = PL0_W, .accessfn = pmreg_access, .type = ARM_CP_NOP }, > /* Since we don't implement any events, writing to PMSELR is > UNPREDICTABLE. > * We choose to RAZ/WI. > */ > { .name = "PMSELR", .cp = 15, .crn = 9, .crm = 12, .opc1 = 0, .opc2 = 5, > .access = PL0_RW, .type = ARM_CP_CONST, .resetvalue = 0, > .accessfn = pmreg_access }, > + { .name = "PMSELR_EL0", .state = ARM_CP_STATE_AA64, > + .opc0 = 3, .crn = 9, .crm = 12, .opc1 = 3, .opc2 = 5, > + .access = PL0_RW, .type = ARM_CP_CONST, .resetvalue = 0, > + .accessfn = pmreg_access }, > #ifndef CONFIG_USER_ONLY > { .name = "PMCCNTR", .cp = 15, .crn = 9, .crm = 13, .opc1 = 0, .opc2 = 0, > .access = PL0_RW, .resetvalue = 0, .type = ARM_CP_IO, > @@ -875,24 +888,51 @@ static const ARMCPRegInfo v7_cp_reginfo[] = { > .fieldoffset = offsetof(CPUARMState, cp15.c9_pmxevtyper), > .accessfn = pmreg_access, .writefn = pmxevtyper_write, > .raw_writefn = raw_write }, > + { .name = "PMXEVTYPER_EL0", .state = ARM_CP_STATE_AA64, > + .opc0 = 3, .crn = 9, .crm = 13, .opc1 = 3, .opc2 = 1, > + .access = PL0_RW, > + .fieldoffset = offsetof(CPUARMState, cp15.c9_pmxevtyper), > + .accessfn = pmreg_access, .writefn = pmxevtyper_write, > + .raw_writefn = raw_write }, > /* Unimplemented, RAZ/WI. */ > { .name = "PMXEVCNTR", .cp = 15, .crn = 9, .crm = 13, .opc1 = 0, .opc2 = > 2, > .access = PL0_RW, .type = ARM_CP_CONST, .resetvalue = 0, > .accessfn = pmreg_access }, > + { .name = "PMXEVCNTR_EL0", .state = ARM_CP_STATE_AA64, > + .opc0 = 3, .crn = 9, .crm = 13, .opc1 = 3, .opc2 = 2, > + .access = PL0_RW, .type = ARM_CP_CONST, .resetvalue = 0, > + .accessfn = pmreg_access }, > { .name = "PMUSERENR", .cp = 15, .crn = 9, .crm = 14, .opc1 = 0, .opc2 = > 0, > .access = PL0_R | PL1_RW, > .fieldoffset = offsetof(CPUARMState, cp15.c9_pmuserenr), > .resetvalue = 0, > .writefn = pmuserenr_write, .raw_writefn = raw_write }, > + { .name = "PMUSERENR_EL0", .state = ARM_CP_STATE_AA64, > + .opc0 = 3, .crn = 9, .crm = 14, .opc1 = 3, .opc2 = 0, > + .access = PL0_R | PL1_RW, > + .fieldoffset = offsetof(CPUARMState, cp15.c9_pmuserenr), > + .resetvalue = 0, > + .writefn = pmuserenr_write, .raw_writefn = raw_write }, Again, should .type = ARM_CP_NO_MIGRATE be used as this shares a variable with PMUSERENR? > { .name = "PMINTENSET", .cp = 15, .crn = 9, .crm = 14, .opc1 = 0, .opc2 > = 1, > .access = PL1_RW, > .fieldoffset = offsetof(CPUARMState, cp15.c9_pminten), > .resetvalue = 0, > .writefn = pmintenset_write, .raw_writefn = raw_write }, > + { .name = "PMINTENSET_EL1", .state = ARM_CP_STATE_AA64, > + .opc0 = 3, .crn = 9, .crm = 14, .opc1 = 0, .opc2 = 1, > + .access = PL1_RW, > + .fieldoffset = offsetof(CPUARMState, cp15.c9_pminten), > + .resetvalue = 0, > + .writefn = pmintenset_write, .raw_writefn = raw_write }, Again, should .type = ARM_CP_NO_MIGRATE be used as this shares a variable with PMINTSET? > { .name = "PMINTENCLR", .cp = 15, .crn = 9, .crm = 14, .opc1 = 0, .opc2 > = 2, > .access = PL1_RW, .type = ARM_CP_NO_MIGRATE, > .fieldoffset = offsetof(CPUARMState, cp15.c9_pminten), > .resetvalue = 0, .writefn = pmintenclr_write, }, > + { .name = "PMINTENCLR_EL1", .state = ARM_CP_STATE_AA64, > + .opc0 = 3, .crn = 9, .crm = 14, .opc1 = 0, .opc2 = 2, > + .access = PL1_RW, .type = ARM_CP_NO_MIGRATE, > + .fieldoffset = offsetof(CPUARMState, cp15.c9_pminten), > + .resetvalue = 0, .writefn = pmintenclr_write, }, > { .name = "VBAR", .state = ARM_CP_STATE_BOTH, > .opc0 = 3, .crn = 12, .crm = 0, .opc1 = 0, .opc2 = 0, > .access = PL1_RW, .writefn = vbar_write, Thanks, Chris -- Qualcomm Innovation Center, Inc. The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum, a Linux Foundation Collaborative Project