Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 21 additions & 0 deletions val/include/acs_timer_support.h
Original file line number Diff line number Diff line change
Expand Up @@ -139,4 +139,25 @@ void ArmWriteCnthvTval (uint64_t Val);
void ArmGenericTimerEnableTimer (ARM_ARCH_TIMER_REGS reg);
void ArmGenericTimerDisableTimer (ARM_ARCH_TIMER_REGS reg);

uint64_t ArmReadHcrEl2(void);
uint64_t ArmReadAA64MMFR1EL1(void);
uint64_t ArmReadAA64MMFR4EL1(void);

uint64_t ArmReadCntpCtl02(void);
uint64_t ArmReadCntpTval02(void);
uint64_t ArmReadCntpCval02(void);
void ArmWriteCntpCtl02(uint64_t val);
void ArmWriteCntpTval02(uint64_t val);
void ArmWriteCntpCval02(uint64_t val);

uint64_t ArmReadCntvTval02(void);
uint64_t ArmReadCntvCtl02(void);
uint64_t ArmReadCntvCval02(void);
void ArmWriteCntvTval02(uint64_t val);
void ArmWriteCntvCtl02(uint64_t val);
void ArmWriteCntvCval02(uint64_t val);

uint64_t ArmReadCntkCtl12(void);
void ArmWriteCntkCtl12(uint64_t val);

#endif // __ARM_ARCH_TIMER_H__
87 changes: 84 additions & 3 deletions val/src/AArch64/ArchTimerSupport.S
Original file line number Diff line number Diff line change
Expand Up @@ -39,22 +39,38 @@
.text
.align 2

GCC_ASM_EXPORT(ArmReadHcrEl2)
GCC_ASM_EXPORT(ArmReadAA64MMFR1EL1)
GCC_ASM_EXPORT(ArmReadAA64MMFR4EL1)
GCC_ASM_EXPORT(ArmReadCntFrq)
GCC_ASM_EXPORT(ArmReadCntPct)
GCC_ASM_EXPORT(ArmReadCntkCtl)
GCC_ASM_EXPORT(ArmWriteCntkCtl)
GCC_ASM_EXPORT(ArmReadCntkCtl12)
GCC_ASM_EXPORT(ArmWriteCntkCtl12)
GCC_ASM_EXPORT(ArmReadCntpTval)
GCC_ASM_EXPORT(ArmWriteCntpTval)
GCC_ASM_EXPORT(ArmReadCntpTval02)
GCC_ASM_EXPORT(ArmWriteCntpTval02)
GCC_ASM_EXPORT(ArmReadCntpCtl)
GCC_ASM_EXPORT(ArmReadCntpCtl02)
GCC_ASM_EXPORT(ArmReadCntvTval)
GCC_ASM_EXPORT(ArmWriteCntvTval)
GCC_ASM_EXPORT(ArmReadCntvTval02)
GCC_ASM_EXPORT(ArmWriteCntvTval02)
GCC_ASM_EXPORT(ArmReadCntvCtl)
GCC_ASM_EXPORT(ArmWriteCntvCtl)
GCC_ASM_EXPORT(ArmReadCntvCtl02)
GCC_ASM_EXPORT(ArmWriteCntvCtl02)
GCC_ASM_EXPORT(ArmReadCntvCt)
GCC_ASM_EXPORT(ArmReadCntpCval)
GCC_ASM_EXPORT(ArmWriteCntpCval)
GCC_ASM_EXPORT(ArmReadCntpCval02)
GCC_ASM_EXPORT(ArmWriteCntpCval02)
GCC_ASM_EXPORT(ArmReadCntvCval)
GCC_ASM_EXPORT(ArmWriteCntvCval)
GCC_ASM_EXPORT(ArmReadCntvCval02)
GCC_ASM_EXPORT(ArmWriteCntvCval02)
GCC_ASM_EXPORT(ArmReadCntvOff)
GCC_ASM_EXPORT(ArmWriteCntvOff)
GCC_ASM_EXPORT(ArmReadCnthpCtl)
Expand All @@ -66,6 +82,20 @@ GCC_ASM_EXPORT(ArmWriteCnthvCtl)
GCC_ASM_EXPORT(ArmReadCnthvTval)
GCC_ASM_EXPORT(ArmWriteCnthvTval)
GCC_ASM_EXPORT(ArmWriteCntpCtl)
GCC_ASM_EXPORT(ArmWriteCntpCtl02)

ASM_PFX(ArmReadHcrEl2):
mrs x0, hcr_el2 // Read HCR_EL2
ret

ASM_PFX(ArmReadAA64MMFR1EL1):
mrs x0, id_aa64mmfr1_el1 // Read ID_AA64MMFR1_EL1
ret

ASM_PFX(ArmReadAA64MMFR4EL1):
//mrs x0, id_aa64mmfr4_el1 // Read ID_AA64MMFR4_EL1
mrs x0, s3_0_c0_c7_4
ret

ASM_PFX(ArmReadCntFrq):
mrs x0, cntfrq_el0 // Read CNTFRQ
Expand All @@ -81,55 +111,92 @@ ASM_PFX(ArmReadCntkCtl):
mrs x0, cntkctl_el1 // Read CNTK_CTL (Timer PL1 Control Register)
ret

ASM_PFX(ArmReadCntkCtl12):
mrs x0, cntkctl_el12 // Read CNTK_CTL (Timer PL1 Control Register) when EL2 Host
ret

ASM_PFX(ArmWriteCntkCtl):
msr cntkctl_el1, x0 // Write to CNTK_CTL (Timer PL1 Control Register)
isb
ret

ASM_PFX(ArmWriteCntkCtl12):
msr cntkctl_el12, x0 // Write to CNTK_CTL (Timer PL1 Control Register) when EL2 Host
isb
ret

ASM_PFX(ArmReadCntpTval):
mrs x0, cntp_tval_el0 // Read CNTP_TVAL (PL1 physical timer value register)
mrs x0, cntp_tval_el0 // Read CNTP_TVAL (PL1 physical timer value register)
ret

ASM_PFX(ArmReadCntpTval02):
mrs x0, cntp_tval_el02 // Read CNTP_TVAL (PL1 physical timer value register) when EL2 Host
ret

ASM_PFX(ArmWriteCntpTval):
msr cntp_tval_el0, x0 // Write to CNTP_TVAL (PL1 physical timer value register)
isb
ret

ASM_PFX(ArmWriteCntpTval02):
msr cntp_tval_el02, x0 // Write to CNTP_TVAL (PL1 physical timer value register) EL2 Host
isb
ret

ASM_PFX(ArmReadCntpCtl):
mrs x0, cntp_ctl_el0 // Read CNTP_CTL (PL1 Physical Timer Control Register)
mrs x0, cntp_ctl_el0 // Read CNTP_CTL (PL1 Physical Timer Control Register)
ret

ASM_PFX(ArmReadCntpCtl02):
mrs x0, cntp_ctl_el02 // Read CNTP_CTL (PL1 Physical Timer Control Register) when EL2 Host
ret


ASM_PFX(ArmWriteCntpCtl):
msr cntp_ctl_el0, x0 // Write to CNTP_CTL (PL1 Physical Timer Control Register)
msr cntp_ctl_el0, x0 // Write CNTP_CTL (PL1 Physical Timer Control Register)
isb
ret

ASM_PFX(ArmWriteCntpCtl02):
msr cntp_ctl_el02, x0 // Write CNTP_CTL (PL1 Physical Timer Control Register) when EL2 Host
isb
ret

ASM_PFX(ArmReadCntvTval):
mrs x0, cntv_tval_el0 // Read CNTV_TVAL (Virtual Timer Value register)
ret

ASM_PFX(ArmReadCntvTval02):
mrs x0, cntv_tval_el02 // Read CNTV_TVAL_EL02 (Virtual Timer Value register)
ret

ASM_PFX(ArmWriteCntvTval):
msr cntv_tval_el0, x0 // Write to CNTV_TVAL (Virtual Timer Value register)
isb
ret

ASM_PFX(ArmWriteCntvTval02):
msr cntv_tval_el02, x0 // Write to CNTV_TVAL_EL02 (Virtual Timer Value register)
isb
ret

ASM_PFX(ArmReadCntvCtl):
mrs x0, cntv_ctl_el0 // Read CNTV_CTL (Virtual Timer Control Register)
ret

ASM_PFX(ArmReadCntvCtl02):
mrs x0, cntv_ctl_el02 // Read CNTV_CTL_EL02 (Virtual Timer Control Register)
ret

ASM_PFX(ArmWriteCntvCtl):
msr cntv_ctl_el0, x0 // Write to CNTV_CTL (Virtual Timer Control Register)
isb
ret

ASM_PFX(ArmWriteCntvCtl02):
msr cntv_ctl_el02, x0 // Write to CNTV_CTL_EL02 (Virtual Timer Control Register)
isb
ret

ASM_PFX(ArmReadCntvCt):
mrs x0, cntvct_el0 // Read CNTVCT (Virtual Count Register)
Expand All @@ -140,23 +207,37 @@ ASM_PFX(ArmReadCntpCval):
mrs x0, cntp_cval_el0 // Read CNTP_CTVAL (Physical Timer Compare Value Register)
ret

ASM_PFX(ArmReadCntpCval02):
mrs x0, cntp_cval_el02 // Read CNTP_CTVAL_EL02 (Physical Timer Compare Value Register)
ret

ASM_PFX(ArmWriteCntpCval):
msr cntp_cval_el0, x0 // Write to CNTP_CTVAL (Physical Timer Compare Value Register)
isb
ret

ASM_PFX(ArmWriteCntpCval02):
msr cntp_cval_el02, x0 // Write to CNTP_CTVAL_EL02 (Physical Timer Compare Value Register)
isb
ret

ASM_PFX(ArmReadCntvCval):
mrs x0, cntv_cval_el0 // Read CNTV_CTVAL (Virtual Timer Compare Value Register)
ret

ASM_PFX(ArmReadCntvCval02):
mrs x0, cntv_cval_el02 // Read CNTV_CTVAL_EL02 (Virtual Timer Compare Value Register)
ret

ASM_PFX(ArmWriteCntvCval):
msr cntv_cval_el0, x0 // write to CNTV_CTVAL (Virtual Timer Compare Value Register)
isb
ret

ASM_PFX(ArmWriteCntvCval02):
msr cntv_cval_el02, x0 // write to CNTV_CTVAL_EL02 (Virtual Timer Compare Value Register)
isb
ret

ASM_PFX(ArmReadCntvOff):
mrs x0, cntvoff_el2 // Read CNTVOFF (virtual Offset register)
Expand Down
73 changes: 61 additions & 12 deletions val/src/acs_timer_support.c
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,31 @@
#include "include/acs_timer_support.h"
#include "include/acs_common.h"

/**
@brief This API is used to get the effective HCR_EL2.E2H
**/
uint8_t get_effective_e2h(void)
{
uint32_t effective_e2h;
uint32_t hcr_e2h = VAL_EXTRACT_BITS(ArmReadHcrEl2(), 34, 34);
uint32_t feat_vhe = VAL_EXTRACT_BITS(ArmReadAA64MMFR1EL1(), 8, 11);
uint32_t e2h0 = VAL_EXTRACT_BITS(ArmReadAA64MMFR4EL1(), 24, 27);

val_print(ACS_PRINT_DEBUG, "\n hcr_e2h : 0x%x", hcr_e2h);
val_print(ACS_PRINT_DEBUG, "\n feat_vhe : 0x%x", feat_vhe);
val_print(ACS_PRINT_DEBUG, "\n e2h0 : 0x%x", e2h0);

if (feat_vhe == 0x0) //ID_AA64MMFR1_EL1.VH
effective_e2h = 0;
else if (e2h0 != 0x0) //E2H0 = 0 means implemented
effective_e2h = 1;
else
effective_e2h = hcr_e2h;

val_print(ACS_PRINT_DEBUG, "\n effective e2h : 0x%x", effective_e2h);
return effective_e2h;
}

/**
@brief This API is used to read Timer related registers

Expand All @@ -31,6 +56,9 @@ ArmArchTimerReadReg (
ARM_ARCH_TIMER_REGS Reg
)
{
static uint8_t effective_e2h = 0xFF;
if (effective_e2h == 0xFF)
effective_e2h = get_effective_e2h();

switch (Reg) {

Expand All @@ -41,28 +69,30 @@ ArmArchTimerReadReg (
return ArmReadCntPct();

case CntkCtl:
return ArmReadCntkCtl();
return effective_e2h ? ArmReadCntkCtl12() : ArmReadCntkCtl();

case CntpTval:
return ArmReadCntpTval();
/* Check For E2H, If EL2 Host then access to cntp_tval_el02 */
return effective_e2h ? ArmReadCntpTval02() : ArmReadCntpTval();

case CntpCtl:
return ArmReadCntpCtl();
/* Check For E2H, If EL2 Host then access to cntp_ctl_el02 */
return effective_e2h ? ArmReadCntpCtl02() : ArmReadCntpCtl();

case CntvTval:
return ArmReadCntvTval();
return effective_e2h ? ArmReadCntvTval02() : ArmReadCntvTval();

case CntvCtl:
return ArmReadCntvCtl();
return effective_e2h ? ArmReadCntvCtl02() : ArmReadCntvCtl();

case CntvCt:
return ArmReadCntvCt();

case CntpCval:
return ArmReadCntpCval();
return effective_e2h ? ArmReadCntpCval02() : ArmReadCntpCval();

case CntvCval:
return ArmReadCntvCval();
return effective_e2h ? ArmReadCntvCval02() : ArmReadCntvCval();

case CntvOff:
return ArmReadCntvOff();
Expand Down Expand Up @@ -103,30 +133,49 @@ ArmArchTimerWriteReg (
)
{

static uint8_t effective_e2h = 0xFF;
if (effective_e2h == 0xFF)
effective_e2h = get_effective_e2h();

switch(Reg) {

case CntPct:
val_print(ACS_PRINT_TEST, "Can't write to Read Only Register: CNTPCT\n", 0);
break;

case CntkCtl:
ArmWriteCntkCtl(*data_buf);
if (effective_e2h)
ArmWriteCntkCtl12(*data_buf);
else
ArmWriteCntkCtl(*data_buf);
break;

case CntpTval:
ArmWriteCntpTval(*data_buf);
if (effective_e2h)
ArmWriteCntpTval02(*data_buf);
else
ArmWriteCntpTval(*data_buf);
break;

case CntpCtl:
ArmWriteCntpCtl(*data_buf);
if (effective_e2h)
ArmWriteCntpCtl02(*data_buf);
else
ArmWriteCntpCtl(*data_buf);
break;

case CntvTval:
ArmWriteCntvTval(*data_buf);
if (effective_e2h)
ArmWriteCntvTval02(*data_buf);
else
ArmWriteCntvTval(*data_buf);
break;

case CntvCtl:
ArmWriteCntvCtl(*data_buf);
if (effective_e2h)
ArmWriteCntvCtl02(*data_buf);
else
ArmWriteCntvCtl(*data_buf);
break;

case CntvCt:
Expand Down