@ -2695,6 +2695,70 @@ static void gt_phys_ctl_write(CPUARMState *env, const ARMCPRegInfo *ri,
gt_ctl_write ( env , ri , GTIMER_PHYS , value ) ;
}
static int gt_phys_redir_timeridx ( CPUARMState * env )
{
switch ( arm_mmu_idx ( env ) ) {
case ARMMMUIdx_E20_0 :
case ARMMMUIdx_E20_2 :
return GTIMER_HYP ;
default :
return GTIMER_PHYS ;
}
}
static int gt_virt_redir_timeridx ( CPUARMState * env )
{
switch ( arm_mmu_idx ( env ) ) {
case ARMMMUIdx_E20_0 :
case ARMMMUIdx_E20_2 :
return GTIMER_HYPVIRT ;
default :
return GTIMER_VIRT ;
}
}
static uint64_t gt_phys_redir_cval_read ( CPUARMState * env ,
const ARMCPRegInfo * ri )
{
int timeridx = gt_phys_redir_timeridx ( env ) ;
return env - > cp15 . c14_timer [ timeridx ] . cval ;
}
static void gt_phys_redir_cval_write ( CPUARMState * env , const ARMCPRegInfo * ri ,
uint64_t value )
{
int timeridx = gt_phys_redir_timeridx ( env ) ;
gt_cval_write ( env , ri , timeridx , value ) ;
}
static uint64_t gt_phys_redir_tval_read ( CPUARMState * env ,
const ARMCPRegInfo * ri )
{
int timeridx = gt_phys_redir_timeridx ( env ) ;
return gt_tval_read ( env , ri , timeridx ) ;
}
static void gt_phys_redir_tval_write ( CPUARMState * env , const ARMCPRegInfo * ri ,
uint64_t value )
{
int timeridx = gt_phys_redir_timeridx ( env ) ;
gt_tval_write ( env , ri , timeridx , value ) ;
}
static uint64_t gt_phys_redir_ctl_read ( CPUARMState * env ,
const ARMCPRegInfo * ri )
{
int timeridx = gt_phys_redir_timeridx ( env ) ;
return env - > cp15 . c14_timer [ timeridx ] . ctl ;
}
static void gt_phys_redir_ctl_write ( CPUARMState * env , const ARMCPRegInfo * ri ,
uint64_t value )
{
int timeridx = gt_phys_redir_timeridx ( env ) ;
gt_ctl_write ( env , ri , timeridx , value ) ;
}
static void gt_virt_timer_reset ( CPUARMState * env , const ARMCPRegInfo * ri )
{
gt_timer_reset ( env , ri , GTIMER_VIRT ) ;
@ -2733,6 +2797,48 @@ static void gt_cntvoff_write(CPUARMState *env, const ARMCPRegInfo *ri,
gt_recalc_timer ( cpu , GTIMER_VIRT ) ;
}
static uint64_t gt_virt_redir_cval_read ( CPUARMState * env ,
const ARMCPRegInfo * ri )
{
int timeridx = gt_virt_redir_timeridx ( env ) ;
return env - > cp15 . c14_timer [ timeridx ] . cval ;
}
static void gt_virt_redir_cval_write ( CPUARMState * env , const ARMCPRegInfo * ri ,
uint64_t value )
{
int timeridx = gt_virt_redir_timeridx ( env ) ;
gt_cval_write ( env , ri , timeridx , value ) ;
}
static uint64_t gt_virt_redir_tval_read ( CPUARMState * env ,
const ARMCPRegInfo * ri )
{
int timeridx = gt_virt_redir_timeridx ( env ) ;
return gt_tval_read ( env , ri , timeridx ) ;
}
static void gt_virt_redir_tval_write ( CPUARMState * env , const ARMCPRegInfo * ri ,
uint64_t value )
{
int timeridx = gt_virt_redir_timeridx ( env ) ;
gt_tval_write ( env , ri , timeridx , value ) ;
}
static uint64_t gt_virt_redir_ctl_read ( CPUARMState * env ,
const ARMCPRegInfo * ri )
{
int timeridx = gt_virt_redir_timeridx ( env ) ;
return env - > cp15 . c14_timer [ timeridx ] . ctl ;
}
static void gt_virt_redir_ctl_write ( CPUARMState * env , const ARMCPRegInfo * ri ,
uint64_t value )
{
int timeridx = gt_virt_redir_timeridx ( env ) ;
gt_ctl_write ( env , ri , timeridx , value ) ;
}
static void gt_hyp_timer_reset ( CPUARMState * env , const ARMCPRegInfo * ri )
{
gt_timer_reset ( env , ri , GTIMER_HYP ) ;
@ -2889,7 +2995,8 @@ static const ARMCPRegInfo generic_timer_cp_reginfo[] = {
. accessfn = gt_ptimer_access ,
. fieldoffset = offsetoflow32 ( CPUARMState ,
cp15 . c14_timer [ GTIMER_PHYS ] . ctl ) ,
. writefn = gt_phys_ctl_write , . raw_writefn = raw_write ,
. readfn = gt_phys_redir_ctl_read , . raw_readfn = raw_read ,
. writefn = gt_phys_redir_ctl_write , . raw_writefn = raw_write ,
} ,
{ . name = " CNTP_CTL_S " ,
. cp = 15 , . crn = 14 , . crm = 2 , . opc1 = 0 , . opc2 = 1 ,
@ -2906,14 +3013,16 @@ static const ARMCPRegInfo generic_timer_cp_reginfo[] = {
. accessfn = gt_ptimer_access ,
. fieldoffset = offsetof ( CPUARMState , cp15 . c14_timer [ GTIMER_PHYS ] . ctl ) ,
. resetvalue = 0 ,
. writefn = gt_phys_ctl_write , . raw_writefn = raw_write ,
. readfn = gt_phys_redir_ctl_read , . raw_readfn = raw_read ,
. writefn = gt_phys_redir_ctl_write , . raw_writefn = raw_write ,
} ,
{ . name = " CNTV_CTL " , . cp = 15 , . crn = 14 , . crm = 3 , . opc1 = 0 , . opc2 = 1 ,
. type = ARM_CP_IO | ARM_CP_ALIAS , . access = PL0_RW ,
. accessfn = gt_vtimer_access ,
. fieldoffset = offsetoflow32 ( CPUARMState ,
cp15 . c14_timer [ GTIMER_VIRT ] . ctl ) ,
. writefn = gt_virt_ctl_write , . raw_writefn = raw_write ,
. readfn = gt_virt_redir_ctl_read , . raw_readfn = raw_read ,
. writefn = gt_virt_redir_ctl_write , . raw_writefn = raw_write ,
} ,
{ . name = " CNTV_CTL_EL0 " , . state = ARM_CP_STATE_AA64 ,
. opc0 = 3 , . opc1 = 3 , . crn = 14 , . crm = 3 , . opc2 = 1 ,
@ -2921,14 +3030,15 @@ static const ARMCPRegInfo generic_timer_cp_reginfo[] = {
. accessfn = gt_vtimer_access ,
. fieldoffset = offsetof ( CPUARMState , cp15 . c14_timer [ GTIMER_VIRT ] . ctl ) ,
. resetvalue = 0 ,
. writefn = gt_virt_ctl_write , . raw_writefn = raw_write ,
. readfn = gt_virt_redir_ctl_read , . raw_readfn = raw_read ,
. writefn = gt_virt_redir_ctl_write , . raw_writefn = raw_write ,
} ,
/* TimerValue views: a 32 bit downcounting view of the underlying state */
{ . name = " CNTP_TVAL " , . cp = 15 , . crn = 14 , . crm = 2 , . opc1 = 0 , . opc2 = 0 ,
. secure = ARM_CP_SECSTATE_NS ,
. type = ARM_CP_NO_RAW | ARM_CP_IO , . access = PL0_RW ,
. accessfn = gt_ptimer_access ,
. readfn = gt_phys_tval_read , . writefn = gt_phys_tval_write ,
. readfn = gt_phys_redir_ tval_read , . writefn = gt_phys_redir _tval_write ,
} ,
{ . name = " CNTP_TVAL_S " ,
. cp = 15 , . crn = 14 , . crm = 2 , . opc1 = 0 , . opc2 = 0 ,
@ -2941,18 +3051,18 @@ static const ARMCPRegInfo generic_timer_cp_reginfo[] = {
. opc0 = 3 , . opc1 = 3 , . crn = 14 , . crm = 2 , . opc2 = 0 ,
. type = ARM_CP_NO_RAW | ARM_CP_IO , . access = PL0_RW ,
. accessfn = gt_ptimer_access , . resetfn = gt_phys_timer_reset ,
. readfn = gt_phys_tval_read , . writefn = gt_phys_tval_write ,
. readfn = gt_phys_redir_ tval_read , . writefn = gt_phys_redir _tval_write ,
} ,
{ . name = " CNTV_TVAL " , . cp = 15 , . crn = 14 , . crm = 3 , . opc1 = 0 , . opc2 = 0 ,
. type = ARM_CP_NO_RAW | ARM_CP_IO , . access = PL0_RW ,
. accessfn = gt_vtimer_access ,
. readfn = gt_virt_tval_read , . writefn = gt_virt_tval_write ,
. readfn = gt_virt_redir_ tval_read , . writefn = gt_virt_redir _tval_write ,
} ,
{ . name = " CNTV_TVAL_EL0 " , . state = ARM_CP_STATE_AA64 ,
. opc0 = 3 , . opc1 = 3 , . crn = 14 , . crm = 3 , . opc2 = 0 ,
. type = ARM_CP_NO_RAW | ARM_CP_IO , . access = PL0_RW ,
. accessfn = gt_vtimer_access , . resetfn = gt_virt_timer_reset ,
. readfn = gt_virt_tval_read , . writefn = gt_virt_tval_write ,
. readfn = gt_virt_redir_ tval_read , . writefn = gt_virt_redir _tval_write ,
} ,
/* The counter itself */
{ . name = " CNTPCT " , . cp = 15 , . crm = 14 , . opc1 = 0 ,
@ -2982,7 +3092,8 @@ static const ARMCPRegInfo generic_timer_cp_reginfo[] = {
. type = ARM_CP_64BIT | ARM_CP_IO | ARM_CP_ALIAS ,
. fieldoffset = offsetof ( CPUARMState , cp15 . c14_timer [ GTIMER_PHYS ] . cval ) ,
. accessfn = gt_ptimer_access ,
. writefn = gt_phys_cval_write , . raw_writefn = raw_write ,
. readfn = gt_phys_redir_cval_read , . raw_readfn = raw_read ,
. writefn = gt_phys_redir_cval_write , . raw_writefn = raw_write ,
} ,
{ . name = " CNTP_CVAL_S " , . cp = 15 , . crm = 14 , . opc1 = 2 ,
. secure = ARM_CP_SECSTATE_S ,
@ -2998,14 +3109,16 @@ static const ARMCPRegInfo generic_timer_cp_reginfo[] = {
. type = ARM_CP_IO ,
. fieldoffset = offsetof ( CPUARMState , cp15 . c14_timer [ GTIMER_PHYS ] . cval ) ,
. resetvalue = 0 , . accessfn = gt_ptimer_access ,
. writefn = gt_phys_cval_write , . raw_writefn = raw_write ,
. readfn = gt_phys_redir_cval_read , . raw_readfn = raw_read ,
. writefn = gt_phys_redir_cval_write , . raw_writefn = raw_write ,
} ,
{ . name = " CNTV_CVAL " , . cp = 15 , . crm = 14 , . opc1 = 3 ,
. access = PL0_RW ,
. type = ARM_CP_64BIT | ARM_CP_IO | ARM_CP_ALIAS ,
. fieldoffset = offsetof ( CPUARMState , cp15 . c14_timer [ GTIMER_VIRT ] . cval ) ,
. accessfn = gt_vtimer_access ,
. writefn = gt_virt_cval_write , . raw_writefn = raw_write ,
. readfn = gt_virt_redir_cval_read , . raw_readfn = raw_read ,
. writefn = gt_virt_redir_cval_write , . raw_writefn = raw_write ,
} ,
{ . name = " CNTV_CVAL_EL0 " , . state = ARM_CP_STATE_AA64 ,
. opc0 = 3 , . opc1 = 3 , . crn = 14 , . crm = 3 , . opc2 = 2 ,
@ -3013,7 +3126,8 @@ static const ARMCPRegInfo generic_timer_cp_reginfo[] = {
. type = ARM_CP_IO ,
. fieldoffset = offsetof ( CPUARMState , cp15 . c14_timer [ GTIMER_VIRT ] . cval ) ,
. resetvalue = 0 , . accessfn = gt_vtimer_access ,
. writefn = gt_virt_cval_write , . raw_writefn = raw_write ,
. readfn = gt_virt_redir_cval_read , . raw_readfn = raw_read ,
. writefn = gt_virt_redir_cval_write , . raw_writefn = raw_write ,
} ,
/* Secure timer -- this is actually restricted to only EL3
* and configurably Secure - EL1 via the accessfn .
@ -3044,6 +3158,15 @@ static const ARMCPRegInfo generic_timer_cp_reginfo[] = {
REGINFO_SENTINEL
} ;
static CPAccessResult e2h_access ( CPUARMState * env , const ARMCPRegInfo * ri ,
bool isread )
{
if ( ! ( arm_hcr_el2_eff ( env ) & HCR_E2H ) ) {
return CP_ACCESS_TRAP ;
}
return CP_ACCESS_OK ;
}
# else
/* In user-mode most of the generic timer registers are inaccessible
@ -6431,6 +6554,40 @@ static const ARMCPRegInfo vhe_reginfo[] = {
. access = PL2_RW ,
. fieldoffset = offsetof ( CPUARMState , cp15 . c14_timer [ GTIMER_HYPVIRT ] . ctl ) ,
. writefn = gt_hv_ctl_write , . raw_writefn = raw_write } ,
{ . name = " CNTP_CTL_EL02 " , . state = ARM_CP_STATE_AA64 ,
. opc0 = 3 , . opc1 = 5 , . crn = 14 , . crm = 2 , . opc2 = 1 ,
. type = ARM_CP_IO | ARM_CP_ALIAS ,
. access = PL2_RW , . accessfn = e2h_access ,
. fieldoffset = offsetof ( CPUARMState , cp15 . c14_timer [ GTIMER_PHYS ] . ctl ) ,
. writefn = gt_phys_ctl_write , . raw_writefn = raw_write } ,
{ . name = " CNTV_CTL_EL02 " , . state = ARM_CP_STATE_AA64 ,
. opc0 = 3 , . opc1 = 5 , . crn = 14 , . crm = 3 , . opc2 = 1 ,
. type = ARM_CP_IO | ARM_CP_ALIAS ,
. access = PL2_RW , . accessfn = e2h_access ,
. fieldoffset = offsetof ( CPUARMState , cp15 . c14_timer [ GTIMER_VIRT ] . ctl ) ,
. writefn = gt_virt_ctl_write , . raw_writefn = raw_write } ,
{ . name = " CNTP_TVAL_EL02 " , . state = ARM_CP_STATE_AA64 ,
. opc0 = 3 , . opc1 = 5 , . crn = 14 , . crm = 2 , . opc2 = 0 ,
. type = ARM_CP_NO_RAW | ARM_CP_IO | ARM_CP_ALIAS ,
. access = PL2_RW , . accessfn = e2h_access ,
. readfn = gt_phys_tval_read , . writefn = gt_phys_tval_write } ,
{ . name = " CNTV_TVAL_EL02 " , . state = ARM_CP_STATE_AA64 ,
. opc0 = 3 , . opc1 = 5 , . crn = 14 , . crm = 3 , . opc2 = 0 ,
. type = ARM_CP_NO_RAW | ARM_CP_IO | ARM_CP_ALIAS ,
. access = PL2_RW , . accessfn = e2h_access ,
. readfn = gt_virt_tval_read , . writefn = gt_virt_tval_write } ,
{ . name = " CNTP_CVAL_EL02 " , . state = ARM_CP_STATE_AA64 ,
. opc0 = 3 , . opc1 = 5 , . crn = 14 , . crm = 2 , . opc2 = 2 ,
. type = ARM_CP_IO | ARM_CP_ALIAS ,
. fieldoffset = offsetof ( CPUARMState , cp15 . c14_timer [ GTIMER_PHYS ] . cval ) ,
. access = PL2_RW , . accessfn = e2h_access ,
. writefn = gt_phys_cval_write , . raw_writefn = raw_write } ,
{ . name = " CNTV_CVAL_EL02 " , . state = ARM_CP_STATE_AA64 ,
. opc0 = 3 , . opc1 = 5 , . crn = 14 , . crm = 3 , . opc2 = 2 ,
. type = ARM_CP_IO | ARM_CP_ALIAS ,
. fieldoffset = offsetof ( CPUARMState , cp15 . c14_timer [ GTIMER_VIRT ] . cval ) ,
. access = PL2_RW , . accessfn = e2h_access ,
. writefn = gt_virt_cval_write , . raw_writefn = raw_write } ,
# endif
REGINFO_SENTINEL
} ;