Message ID | 20250418144758.2633-2-ziyao@disroot.org |
---|---|
State | New |
Headers | show |
Series | Register Zicntr in FDT when emulating is possible | expand |
在 2025-04-18五的 14:47 +0000,Yao Zi写道: > Zicntr extension specifies three read-only CSRs, time, cycle and > instret. It isn't sufficient to report Zicntr is fully supported with > only time CSR detected. > > This patch introduces a bitmap to sbi_hart_features to record > availability of these CSRs, which are detected using traps. Zicntr is > reported as present if and only if three CSRs are all available on the > HARTs. > > Suggested-by: Anup Patel <anup@brainfault.org> > Signed-off-by: Yao Zi <ziyao@disroot.org> > --- > include/sbi/sbi_hart.h | 9 +++++++++ > lib/sbi/sbi_hart.c | 35 ++++++++++++++++++++++++++++------- > 2 files changed, 37 insertions(+), 7 deletions(-) > > diff --git a/include/sbi/sbi_hart.h b/include/sbi/sbi_hart.h > index c3a7feb..48edafe 100644 > --- a/include/sbi/sbi_hart.h > +++ b/include/sbi/sbi_hart.h > @@ -91,6 +91,13 @@ struct sbi_hart_ext_data { > > extern const struct sbi_hart_ext_data sbi_hart_ext[]; > > +/** CSRs should be detected by access and trapping */ > +enum sbi_hart_csrs { > + SBI_HART_CSR_CYCLE = 0, > + SBI_HART_CSR_TIME, > + SBI_HART_CSR_INSTRET, add SBI_HART_CSR_MAX > +}; > + > /* > * Smepmp enforces access boundaries between M-mode and > * S/U-mode. When it is enabled, the PMPs are programmed > @@ -110,6 +117,7 @@ struct sbi_hart_features { > bool detected; > int priv_version; > unsigned long extensions[BITS_TO_LONGS(SBI_HART_EXT_MAX)]; > + unsigned long csrs; change to unsigned long csrs[BITS_TO_LONGS(SBI_HART_CSR_MAX)]; To make the code more flexible, it is recommended to add the above modification Regards, Xiang W > unsigned int pmp_count; > unsigned int pmp_addr_bits; > unsigned int pmp_log2gran; > @@ -148,6 +156,7 @@ bool sbi_hart_has_extension(struct sbi_scratch *scratch, > enum sbi_hart_extensions ext); > void sbi_hart_get_extensions_str(struct sbi_scratch *scratch, > char *extension_str, int nestr); > +bool sbi_hart_has_csr(struct sbi_scratch *scratch, enum sbi_hart_csrs csr); > > void __attribute__((noreturn)) sbi_hart_hang(void); > > diff --git a/lib/sbi/sbi_hart.c b/lib/sbi/sbi_hart.c > index c343805..f98b6b0 100644 > --- a/lib/sbi/sbi_hart.c > +++ b/lib/sbi/sbi_hart.c > @@ -733,6 +733,20 @@ void sbi_hart_get_extensions_str(struct sbi_scratch *scratch, > sbi_strncpy(extensions_str, "none", nestr); > } > > +/** > + * Check whether a particular CSR is present on the HART > + * > + * @param scratch pointer to the HART scratch space > + * @param csr the CSR number to check > + */ > +bool sbi_hart_has_csr(struct sbi_scratch *scratch, enum sbi_hart_csrs csr) > +{ > + struct sbi_hart_features *hfeatures = > + sbi_scratch_offset_ptr(scratch, hart_features_offset); > + > + return (hfeatures->csrs >> csr) & 1UL; > +} > + > static unsigned long hart_pmp_get_allowed_addr(void) > { > unsigned long val = 0; > @@ -789,7 +803,6 @@ static int hart_detect_features(struct sbi_scratch *scratch) > struct sbi_hart_features *hfeatures = > sbi_scratch_offset_ptr(scratch, hart_features_offset); > unsigned long val, oldval; > - bool has_zicntr = false; > int rc; > > /* If hart features already detected then do nothing */ > @@ -798,6 +811,7 @@ static int hart_detect_features(struct sbi_scratch *scratch) > > /* Clear hart features */ > sbi_memset(hfeatures->extensions, 0, sizeof(hfeatures->extensions)); > + hfeatures->csrs = 0; > hfeatures->pmp_count = 0; > hfeatures->mhpm_mask = 0; > hfeatures->priv_version = SBI_HART_PRIV_VER_UNKNOWN; > @@ -924,9 +938,6 @@ __pmp_skip: > /* Detect if hart supports sscofpmf */ > __check_ext_csr(SBI_HART_PRIV_VER_1_11, > CSR_SCOUNTOVF, SBI_HART_EXT_SSCOFPMF); > - /* Detect if hart supports time CSR */ > - __check_ext_csr(SBI_HART_PRIV_VER_UNKNOWN, > - CSR_TIME, SBI_HART_EXT_ZICNTR); > /* Detect if hart has AIA local interrupt CSRs */ > __check_ext_csr(SBI_HART_PRIV_VER_UNKNOWN, > CSR_MTOPI, SBI_HART_EXT_SMAIA); > @@ -945,8 +956,16 @@ __pmp_skip: > > #undef __check_ext_csr > > - /* Save trap based detection of Zicntr */ > - has_zicntr = sbi_hart_has_extension(scratch, SBI_HART_EXT_ZICNTR); > +#define __check_csr_existence(__csr, __csr_id) \ > + csr_read_allowed(__csr, &trap); \ > + if (!trap.cause) \ > + hfeatures->csrs |= 1 << __csr_id; > + > + __check_csr_existence(CSR_CYCLE, SBI_HART_CSR_CYCLE); > + __check_csr_existence(CSR_TIME, SBI_HART_CSR_TIME); > + __check_csr_existence(CSR_INSTRET, SBI_HART_CSR_INSTRET); > + > +#undef __check_csr_existence > > /* Let platform populate extensions */ > rc = sbi_platform_extensions_init(sbi_platform_thishart_ptr(), > @@ -956,7 +975,9 @@ __pmp_skip: > > /* Zicntr should only be detected using traps */ > __sbi_hart_update_extension(hfeatures, SBI_HART_EXT_ZICNTR, > - has_zicntr); > + (hfeatures->csrs & BIT(SBI_HART_CSR_CYCLE)) && > + (hfeatures->csrs & BIT(SBI_HART_CSR_TIME)) && > + (hfeatures->csrs & BIT(SBI_HART_CSR_INSTRET))); > > /* Extensions implied by other extensions and features */ > if (hfeatures->mhpm_mask) > -- > 2.49.0 >
diff --git a/include/sbi/sbi_hart.h b/include/sbi/sbi_hart.h index c3a7feb..48edafe 100644 --- a/include/sbi/sbi_hart.h +++ b/include/sbi/sbi_hart.h @@ -91,6 +91,13 @@ struct sbi_hart_ext_data { extern const struct sbi_hart_ext_data sbi_hart_ext[]; +/** CSRs should be detected by access and trapping */ +enum sbi_hart_csrs { + SBI_HART_CSR_CYCLE = 0, + SBI_HART_CSR_TIME, + SBI_HART_CSR_INSTRET, +}; + /* * Smepmp enforces access boundaries between M-mode and * S/U-mode. When it is enabled, the PMPs are programmed @@ -110,6 +117,7 @@ struct sbi_hart_features { bool detected; int priv_version; unsigned long extensions[BITS_TO_LONGS(SBI_HART_EXT_MAX)]; + unsigned long csrs; unsigned int pmp_count; unsigned int pmp_addr_bits; unsigned int pmp_log2gran; @@ -148,6 +156,7 @@ bool sbi_hart_has_extension(struct sbi_scratch *scratch, enum sbi_hart_extensions ext); void sbi_hart_get_extensions_str(struct sbi_scratch *scratch, char *extension_str, int nestr); +bool sbi_hart_has_csr(struct sbi_scratch *scratch, enum sbi_hart_csrs csr); void __attribute__((noreturn)) sbi_hart_hang(void); diff --git a/lib/sbi/sbi_hart.c b/lib/sbi/sbi_hart.c index c343805..f98b6b0 100644 --- a/lib/sbi/sbi_hart.c +++ b/lib/sbi/sbi_hart.c @@ -733,6 +733,20 @@ void sbi_hart_get_extensions_str(struct sbi_scratch *scratch, sbi_strncpy(extensions_str, "none", nestr); } +/** + * Check whether a particular CSR is present on the HART + * + * @param scratch pointer to the HART scratch space + * @param csr the CSR number to check + */ +bool sbi_hart_has_csr(struct sbi_scratch *scratch, enum sbi_hart_csrs csr) +{ + struct sbi_hart_features *hfeatures = + sbi_scratch_offset_ptr(scratch, hart_features_offset); + + return (hfeatures->csrs >> csr) & 1UL; +} + static unsigned long hart_pmp_get_allowed_addr(void) { unsigned long val = 0; @@ -789,7 +803,6 @@ static int hart_detect_features(struct sbi_scratch *scratch) struct sbi_hart_features *hfeatures = sbi_scratch_offset_ptr(scratch, hart_features_offset); unsigned long val, oldval; - bool has_zicntr = false; int rc; /* If hart features already detected then do nothing */ @@ -798,6 +811,7 @@ static int hart_detect_features(struct sbi_scratch *scratch) /* Clear hart features */ sbi_memset(hfeatures->extensions, 0, sizeof(hfeatures->extensions)); + hfeatures->csrs = 0; hfeatures->pmp_count = 0; hfeatures->mhpm_mask = 0; hfeatures->priv_version = SBI_HART_PRIV_VER_UNKNOWN; @@ -924,9 +938,6 @@ __pmp_skip: /* Detect if hart supports sscofpmf */ __check_ext_csr(SBI_HART_PRIV_VER_1_11, CSR_SCOUNTOVF, SBI_HART_EXT_SSCOFPMF); - /* Detect if hart supports time CSR */ - __check_ext_csr(SBI_HART_PRIV_VER_UNKNOWN, - CSR_TIME, SBI_HART_EXT_ZICNTR); /* Detect if hart has AIA local interrupt CSRs */ __check_ext_csr(SBI_HART_PRIV_VER_UNKNOWN, CSR_MTOPI, SBI_HART_EXT_SMAIA); @@ -945,8 +956,16 @@ __pmp_skip: #undef __check_ext_csr - /* Save trap based detection of Zicntr */ - has_zicntr = sbi_hart_has_extension(scratch, SBI_HART_EXT_ZICNTR); +#define __check_csr_existence(__csr, __csr_id) \ + csr_read_allowed(__csr, &trap); \ + if (!trap.cause) \ + hfeatures->csrs |= 1 << __csr_id; + + __check_csr_existence(CSR_CYCLE, SBI_HART_CSR_CYCLE); + __check_csr_existence(CSR_TIME, SBI_HART_CSR_TIME); + __check_csr_existence(CSR_INSTRET, SBI_HART_CSR_INSTRET); + +#undef __check_csr_existence /* Let platform populate extensions */ rc = sbi_platform_extensions_init(sbi_platform_thishart_ptr(), @@ -956,7 +975,9 @@ __pmp_skip: /* Zicntr should only be detected using traps */ __sbi_hart_update_extension(hfeatures, SBI_HART_EXT_ZICNTR, - has_zicntr); + (hfeatures->csrs & BIT(SBI_HART_CSR_CYCLE)) && + (hfeatures->csrs & BIT(SBI_HART_CSR_TIME)) && + (hfeatures->csrs & BIT(SBI_HART_CSR_INSTRET))); /* Extensions implied by other extensions and features */ if (hfeatures->mhpm_mask)
Zicntr extension specifies three read-only CSRs, time, cycle and instret. It isn't sufficient to report Zicntr is fully supported with only time CSR detected. This patch introduces a bitmap to sbi_hart_features to record availability of these CSRs, which are detected using traps. Zicntr is reported as present if and only if three CSRs are all available on the HARTs. Suggested-by: Anup Patel <anup@brainfault.org> Signed-off-by: Yao Zi <ziyao@disroot.org> --- include/sbi/sbi_hart.h | 9 +++++++++ lib/sbi/sbi_hart.c | 35 ++++++++++++++++++++++++++++------- 2 files changed, 37 insertions(+), 7 deletions(-)