Skip to content

Commit 6b6ca05

Browse files
Add support for Systems with effective HCR_EL2.E2H = 1
- Implemented logic to detect the effective value of HCR_EL2.E2H. - Updated code to conditionally access appropriate system registers based on whether Virtualization Host Extensions (VHE) are enabled. - Ensures correct behavior in systems running with E2H set. Signed-off-by: Rajat Goyal <Rajat.Goyal@arm.com> Co-authored-by: Nick Graves <nicholasgraves@google.com>
1 parent 10b9bd4 commit 6b6ca05

3 files changed

Lines changed: 166 additions & 15 deletions

File tree

val/include/acs_timer_support.h

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -139,4 +139,25 @@ void ArmWriteCnthvTval (uint64_t Val);
139139
void ArmGenericTimerEnableTimer (ARM_ARCH_TIMER_REGS reg);
140140
void ArmGenericTimerDisableTimer (ARM_ARCH_TIMER_REGS reg);
141141

142+
uint64_t ArmReadHcrEl2(void);
143+
uint64_t ArmReadAA64MMFR1EL1(void);
144+
uint64_t ArmReadAA64MMFR4EL1(void);
145+
146+
uint64_t ArmReadCntpCtl02(void);
147+
uint64_t ArmReadCntpTval02(void);
148+
uint64_t ArmReadCntpCval02(void);
149+
void ArmWriteCntpCtl02(uint64_t val);
150+
void ArmWriteCntpTval02(uint64_t val);
151+
void ArmWriteCntpCval02(uint64_t val);
152+
153+
uint64_t ArmReadCntvTval02(void);
154+
uint64_t ArmReadCntvCtl02(void);
155+
uint64_t ArmReadCntvCval02(void);
156+
void ArmWriteCntvTval02(uint64_t val);
157+
void ArmWriteCntvCtl02(uint64_t val);
158+
void ArmWriteCntvCval02(uint64_t val);
159+
160+
uint64_t ArmReadCntkCtl12(void);
161+
void ArmWriteCntkCtl12(uint64_t val);
162+
142163
#endif // __ARM_ARCH_TIMER_H__

val/src/AArch64/ArchTimerSupport.S

Lines changed: 84 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -39,22 +39,38 @@
3939
.text
4040
.align 2
4141

42+
GCC_ASM_EXPORT(ArmReadHcrEl2)
43+
GCC_ASM_EXPORT(ArmReadAA64MMFR1EL1)
44+
GCC_ASM_EXPORT(ArmReadAA64MMFR4EL1)
4245
GCC_ASM_EXPORT(ArmReadCntFrq)
4346
GCC_ASM_EXPORT(ArmReadCntPct)
4447
GCC_ASM_EXPORT(ArmReadCntkCtl)
4548
GCC_ASM_EXPORT(ArmWriteCntkCtl)
49+
GCC_ASM_EXPORT(ArmReadCntkCtl12)
50+
GCC_ASM_EXPORT(ArmWriteCntkCtl12)
4651
GCC_ASM_EXPORT(ArmReadCntpTval)
4752
GCC_ASM_EXPORT(ArmWriteCntpTval)
53+
GCC_ASM_EXPORT(ArmReadCntpTval02)
54+
GCC_ASM_EXPORT(ArmWriteCntpTval02)
4855
GCC_ASM_EXPORT(ArmReadCntpCtl)
56+
GCC_ASM_EXPORT(ArmReadCntpCtl02)
4957
GCC_ASM_EXPORT(ArmReadCntvTval)
5058
GCC_ASM_EXPORT(ArmWriteCntvTval)
59+
GCC_ASM_EXPORT(ArmReadCntvTval02)
60+
GCC_ASM_EXPORT(ArmWriteCntvTval02)
5161
GCC_ASM_EXPORT(ArmReadCntvCtl)
5262
GCC_ASM_EXPORT(ArmWriteCntvCtl)
63+
GCC_ASM_EXPORT(ArmReadCntvCtl02)
64+
GCC_ASM_EXPORT(ArmWriteCntvCtl02)
5365
GCC_ASM_EXPORT(ArmReadCntvCt)
5466
GCC_ASM_EXPORT(ArmReadCntpCval)
5567
GCC_ASM_EXPORT(ArmWriteCntpCval)
68+
GCC_ASM_EXPORT(ArmReadCntpCval02)
69+
GCC_ASM_EXPORT(ArmWriteCntpCval02)
5670
GCC_ASM_EXPORT(ArmReadCntvCval)
5771
GCC_ASM_EXPORT(ArmWriteCntvCval)
72+
GCC_ASM_EXPORT(ArmReadCntvCval02)
73+
GCC_ASM_EXPORT(ArmWriteCntvCval02)
5874
GCC_ASM_EXPORT(ArmReadCntvOff)
5975
GCC_ASM_EXPORT(ArmWriteCntvOff)
6076
GCC_ASM_EXPORT(ArmReadCnthpCtl)
@@ -66,6 +82,20 @@ GCC_ASM_EXPORT(ArmWriteCnthvCtl)
6682
GCC_ASM_EXPORT(ArmReadCnthvTval)
6783
GCC_ASM_EXPORT(ArmWriteCnthvTval)
6884
GCC_ASM_EXPORT(ArmWriteCntpCtl)
85+
GCC_ASM_EXPORT(ArmWriteCntpCtl02)
86+
87+
ASM_PFX(ArmReadHcrEl2):
88+
mrs x0, hcr_el2 // Read HCR_EL2
89+
ret
90+
91+
ASM_PFX(ArmReadAA64MMFR1EL1):
92+
mrs x0, id_aa64mmfr1_el1 // Read ID_AA64MMFR1_EL1
93+
ret
94+
95+
ASM_PFX(ArmReadAA64MMFR4EL1):
96+
//mrs x0, id_aa64mmfr4_el1 // Read ID_AA64MMFR4_EL1
97+
mrs x0, s3_0_c0_c7_4
98+
ret
6999

70100
ASM_PFX(ArmReadCntFrq):
71101
mrs x0, cntfrq_el0 // Read CNTFRQ
@@ -81,55 +111,92 @@ ASM_PFX(ArmReadCntkCtl):
81111
mrs x0, cntkctl_el1 // Read CNTK_CTL (Timer PL1 Control Register)
82112
ret
83113

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

85118
ASM_PFX(ArmWriteCntkCtl):
86119
msr cntkctl_el1, x0 // Write to CNTK_CTL (Timer PL1 Control Register)
87120
isb
88121
ret
89122

123+
ASM_PFX(ArmWriteCntkCtl12):
124+
msr cntkctl_el12, x0 // Write to CNTK_CTL (Timer PL1 Control Register) when EL2 Host
125+
isb
126+
ret
90127

91128
ASM_PFX(ArmReadCntpTval):
92-
mrs x0, cntp_tval_el0 // Read CNTP_TVAL (PL1 physical timer value register)
129+
mrs x0, cntp_tval_el0 // Read CNTP_TVAL (PL1 physical timer value register)
130+
ret
131+
132+
ASM_PFX(ArmReadCntpTval02):
133+
mrs x0, cntp_tval_el02 // Read CNTP_TVAL (PL1 physical timer value register) when EL2 Host
93134
ret
94135

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

141+
ASM_PFX(ArmWriteCntpTval02):
142+
msr cntp_tval_el02, x0 // Write to CNTP_TVAL (PL1 physical timer value register) EL2 Host
143+
isb
144+
ret
100145

101146
ASM_PFX(ArmReadCntpCtl):
102-
mrs x0, cntp_ctl_el0 // Read CNTP_CTL (PL1 Physical Timer Control Register)
147+
mrs x0, cntp_ctl_el0 // Read CNTP_CTL (PL1 Physical Timer Control Register)
148+
ret
149+
150+
ASM_PFX(ArmReadCntpCtl02):
151+
mrs x0, cntp_ctl_el02 // Read CNTP_CTL (PL1 Physical Timer Control Register) when EL2 Host
103152
ret
104153

105154

106155
ASM_PFX(ArmWriteCntpCtl):
107-
msr cntp_ctl_el0, x0 // Write to CNTP_CTL (PL1 Physical Timer Control Register)
156+
msr cntp_ctl_el0, x0 // Write CNTP_CTL (PL1 Physical Timer Control Register)
108157
isb
109158
ret
110159

160+
ASM_PFX(ArmWriteCntpCtl02):
161+
msr cntp_ctl_el02, x0 // Write CNTP_CTL (PL1 Physical Timer Control Register) when EL2 Host
162+
isb
163+
ret
111164

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

169+
ASM_PFX(ArmReadCntvTval02):
170+
mrs x0, cntv_tval_el02 // Read CNTV_TVAL_EL02 (Virtual Timer Value register)
171+
ret
116172

117173
ASM_PFX(ArmWriteCntvTval):
118174
msr cntv_tval_el0, x0 // Write to CNTV_TVAL (Virtual Timer Value register)
119175
isb
120176
ret
121177

178+
ASM_PFX(ArmWriteCntvTval02):
179+
msr cntv_tval_el02, x0 // Write to CNTV_TVAL_EL02 (Virtual Timer Value register)
180+
isb
181+
ret
122182

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

187+
ASM_PFX(ArmReadCntvCtl02):
188+
mrs x0, cntv_ctl_el02 // Read CNTV_CTL_EL02 (Virtual Timer Control Register)
189+
ret
127190

128191
ASM_PFX(ArmWriteCntvCtl):
129192
msr cntv_ctl_el0, x0 // Write to CNTV_CTL (Virtual Timer Control Register)
130193
isb
131194
ret
132195

196+
ASM_PFX(ArmWriteCntvCtl02):
197+
msr cntv_ctl_el02, x0 // Write to CNTV_CTL_EL02 (Virtual Timer Control Register)
198+
isb
199+
ret
133200

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

210+
ASM_PFX(ArmReadCntpCval02):
211+
mrs x0, cntp_cval_el02 // Read CNTP_CTVAL_EL02 (Physical Timer Compare Value Register)
212+
ret
143213

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

219+
ASM_PFX(ArmWriteCntpCval02):
220+
msr cntp_cval_el02, x0 // Write to CNTP_CTVAL_EL02 (Physical Timer Compare Value Register)
221+
isb
222+
ret
149223

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

228+
ASM_PFX(ArmReadCntvCval02):
229+
mrs x0, cntv_cval_el02 // Read CNTV_CTVAL_EL02 (Virtual Timer Compare Value Register)
230+
ret
154231

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

237+
ASM_PFX(ArmWriteCntvCval02):
238+
msr cntv_cval_el02, x0 // write to CNTV_CTVAL_EL02 (Virtual Timer Compare Value Register)
239+
isb
240+
ret
160241

161242
ASM_PFX(ArmReadCntvOff):
162243
mrs x0, cntvoff_el2 // Read CNTVOFF (virtual Offset register)

val/src/acs_timer_support.c

Lines changed: 61 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,31 @@
1919
#include "include/acs_timer_support.h"
2020
#include "include/acs_common.h"
2121

22+
/**
23+
@brief This API is used to get the effective HCR_EL2.E2H
24+
**/
25+
uint8_t get_effective_e2h(void)
26+
{
27+
uint32_t effective_e2h;
28+
uint32_t hcr_e2h = VAL_EXTRACT_BITS(ArmReadHcrEl2(), 34, 34);
29+
uint32_t feat_vhe = VAL_EXTRACT_BITS(ArmReadAA64MMFR1EL1(), 8, 11);
30+
uint32_t e2h0 = VAL_EXTRACT_BITS(ArmReadAA64MMFR4EL1(), 24, 27);
31+
32+
val_print(ACS_PRINT_DEBUG, "\n hcr_e2h : 0x%x", hcr_e2h);
33+
val_print(ACS_PRINT_DEBUG, "\n feat_vhe : 0x%x", feat_vhe);
34+
val_print(ACS_PRINT_DEBUG, "\n e2h0 : 0x%x", e2h0);
35+
36+
if (feat_vhe == 0x0) //ID_AA64MMFR1_EL1.VH
37+
effective_e2h = 0;
38+
else if (e2h0 != 0x0) //E2H0 = 0 means implemented
39+
effective_e2h = 1;
40+
else
41+
effective_e2h = hcr_e2h;
42+
43+
val_print(ACS_PRINT_DEBUG, "\n effective e2h : 0x%x", effective_e2h);
44+
return effective_e2h;
45+
}
46+
2247
/**
2348
@brief This API is used to read Timer related registers
2449
@@ -31,6 +56,9 @@ ArmArchTimerReadReg (
3156
ARM_ARCH_TIMER_REGS Reg
3257
)
3358
{
59+
static uint8_t effective_e2h = 0xFF;
60+
if (effective_e2h == 0xFF)
61+
effective_e2h = get_effective_e2h();
3462

3563
switch (Reg) {
3664

@@ -41,28 +69,30 @@ ArmArchTimerReadReg (
4169
return ArmReadCntPct();
4270

4371
case CntkCtl:
44-
return ArmReadCntkCtl();
72+
return effective_e2h ? ArmReadCntkCtl12() : ArmReadCntkCtl();
4573

4674
case CntpTval:
47-
return ArmReadCntpTval();
75+
/* Check For E2H, If EL2 Host then access to cntp_tval_el02 */
76+
return effective_e2h ? ArmReadCntpTval02() : ArmReadCntpTval();
4877

4978
case CntpCtl:
50-
return ArmReadCntpCtl();
79+
/* Check For E2H, If EL2 Host then access to cntp_ctl_el02 */
80+
return effective_e2h ? ArmReadCntpCtl02() : ArmReadCntpCtl();
5181

5282
case CntvTval:
53-
return ArmReadCntvTval();
83+
return effective_e2h ? ArmReadCntvTval02() : ArmReadCntvTval();
5484

5585
case CntvCtl:
56-
return ArmReadCntvCtl();
86+
return effective_e2h ? ArmReadCntvCtl02() : ArmReadCntvCtl();
5787

5888
case CntvCt:
5989
return ArmReadCntvCt();
6090

6191
case CntpCval:
62-
return ArmReadCntpCval();
92+
return effective_e2h ? ArmReadCntpCval02() : ArmReadCntpCval();
6393

6494
case CntvCval:
65-
return ArmReadCntvCval();
95+
return effective_e2h ? ArmReadCntvCval02() : ArmReadCntvCval();
6696

6797
case CntvOff:
6898
return ArmReadCntvOff();
@@ -103,30 +133,49 @@ ArmArchTimerWriteReg (
103133
)
104134
{
105135

136+
static uint8_t effective_e2h = 0xFF;
137+
if (effective_e2h == 0xFF)
138+
effective_e2h = get_effective_e2h();
139+
106140
switch(Reg) {
107141

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

112146
case CntkCtl:
113-
ArmWriteCntkCtl(*data_buf);
147+
if (effective_e2h)
148+
ArmWriteCntkCtl12(*data_buf);
149+
else
150+
ArmWriteCntkCtl(*data_buf);
114151
break;
115152

116153
case CntpTval:
117-
ArmWriteCntpTval(*data_buf);
154+
if (effective_e2h)
155+
ArmWriteCntpTval02(*data_buf);
156+
else
157+
ArmWriteCntpTval(*data_buf);
118158
break;
119159

120160
case CntpCtl:
121-
ArmWriteCntpCtl(*data_buf);
161+
if (effective_e2h)
162+
ArmWriteCntpCtl02(*data_buf);
163+
else
164+
ArmWriteCntpCtl(*data_buf);
122165
break;
123166

124167
case CntvTval:
125-
ArmWriteCntvTval(*data_buf);
168+
if (effective_e2h)
169+
ArmWriteCntvTval02(*data_buf);
170+
else
171+
ArmWriteCntvTval(*data_buf);
126172
break;
127173

128174
case CntvCtl:
129-
ArmWriteCntvCtl(*data_buf);
175+
if (effective_e2h)
176+
ArmWriteCntvCtl02(*data_buf);
177+
else
178+
ArmWriteCntvCtl(*data_buf);
130179
break;
131180

132181
case CntvCt:

0 commit comments

Comments
 (0)