Message ID | 20231031203916.197332-4-dbarboza@ventanamicro.com |
---|---|
State | New |
Headers | show |
Series | rv64i CPU, RVA22U64 profile support | expand |
On Tue, Oct 31, 2023 at 05:39:03PM -0300, Daniel Henrique Barboza wrote: > We don't have any form of a 'bare bones' CPU. rv64, our default CPUs, > comes with a lot of defaults. This is fine for most regular uses but > it's not suitable when more control of what is actually loaded in the > CPU is required. > > A bare-bones CPU would be annoying to deal with if not by profile > support, a way to load a multitude of extensions with a single flag. Profile > support is going to be implemented shortly, so let's add a CPU for it. > > The new 'rv64i' CPU will have only RVI loaded. It is inspired in the > profile specification that dictates, for RVA22U64 [1]: > > "RVA22U64 Mandatory Base > RV64I is the mandatory base ISA for RVA22U64" > > And so it seems that RV64I is the mandatory base ISA for all profiles > listed in [1], making it an ideal CPU to use with profile support. > > rv64i is a CPU of type TYPE_RISCV_BARE_CPU. It has a mix of features > from pre-existent CPUs: > > - it allows extensions to be enabled, like generic CPUs; > - it will not inherit extension defaults, like vendor CPUs. > > This is the minimum extension set to boot OpenSBI and buildroot using > rv64i: > > ./build/qemu-system-riscv64 -nographic -M virt \ > -cpu rv64i,g=true,c=true,s=true,u=true > > Our minimal riscv,isa in this case will be: > > # cat /proc/device-tree/cpus/cpu@0/riscv,isa > rv64imafdc_zicntr_zicsr_zifencei_zihpm_zca_zcd# > > [1] https://github.com/riscv/riscv-profiles/blob/main/profiles.adoc > > Signed-off-by: Daniel Henrique Barboza <dbarboza@ventanamicro.com> > --- > target/riscv/cpu-qom.h | 2 ++ > target/riscv/cpu.c | 25 +++++++++++++++++++++++++ > 2 files changed, 27 insertions(+) > > diff --git a/target/riscv/cpu-qom.h b/target/riscv/cpu-qom.h > index 7831e86d37..ea9a752280 100644 > --- a/target/riscv/cpu-qom.h > +++ b/target/riscv/cpu-qom.h > @@ -25,6 +25,7 @@ > #define TYPE_RISCV_CPU "riscv-cpu" > #define TYPE_RISCV_DYNAMIC_CPU "riscv-dynamic-cpu" > #define TYPE_RISCV_VENDOR_CPU "riscv-vendor-cpu" > +#define TYPE_RISCV_BARE_CPU "riscv-bare-cpu" > > #define RISCV_CPU_TYPE_SUFFIX "-" TYPE_RISCV_CPU > #define RISCV_CPU_TYPE_NAME(name) (name RISCV_CPU_TYPE_SUFFIX) > @@ -35,6 +36,7 @@ > #define TYPE_RISCV_CPU_BASE32 RISCV_CPU_TYPE_NAME("rv32") > #define TYPE_RISCV_CPU_BASE64 RISCV_CPU_TYPE_NAME("rv64") > #define TYPE_RISCV_CPU_BASE128 RISCV_CPU_TYPE_NAME("x-rv128") > +#define TYPE_RISCV_CPU_RV64I RISCV_CPU_TYPE_NAME("rv64i") > #define TYPE_RISCV_CPU_IBEX RISCV_CPU_TYPE_NAME("lowrisc-ibex") > #define TYPE_RISCV_CPU_SHAKTI_C RISCV_CPU_TYPE_NAME("shakti-c") > #define TYPE_RISCV_CPU_SIFIVE_E31 RISCV_CPU_TYPE_NAME("sifive-e31") > diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c > index 822970345c..98b2a4061a 100644 > --- a/target/riscv/cpu.c > +++ b/target/riscv/cpu.c > @@ -544,6 +544,18 @@ static void rv128_base_cpu_init(Object *obj) > set_satp_mode_max_supported(RISCV_CPU(obj), VM_1_10_SV57); > #endif > } > + > +static void rv64i_bare_cpu_init(Object *obj) > +{ > + CPURISCVState *env = &RISCV_CPU(obj)->env; > + riscv_cpu_set_misa(env, MXL_RV64, RVI); > + > + /* Set latest version of privileged specification */ > + env->priv_ver = PRIV_VERSION_LATEST; The beauty of rv64i is we'll finally know exactly what we're configuring when we select it and some set of extensions. With that in mind I think we should also be explicit about which version of the priv spec is implemented, but we can't just pick a version now, since we may need to update it later. I think we have the following options: 1. Expose priv version properties (v1_10_0, ...) and either require the user to select one or default to the latest. (Any versions we don't want to support for rv64i would error out if selected.) 2. Add multiple rv64i base cpu types where the version is also specified in the name, e.g. rv64i_1_12_0, and then maybe have an rv64i alias which always points at the latest. A nice thing about (1) is that we can expose the boolean version properties in cpu model expansion. A nice thing about (2) is that the user will either be forced to select an explicit version or, if we have the alias, libvirt will convert 'rv64i' into its full name when storing it in the XML. But, we can force the user to select a version with (1) too by not providing a default. While that adds a burden of always having to provide a version, it's not a big deal for a barebones cpu, since all extensions necessary to create a useful cpu are also required. And, profiles alleviate the burden. For example, rva22s64 mandates Ss1p12, so that profile will automatically set the v1_12_0 property. I think we should implement (1) without a default. > +#ifndef CONFIG_USER_ONLY > + set_satp_mode_max_supported(RISCV_CPU(obj), VM_1_10_SV57); I think we should require the user provide one of sv39, sv48, ... rather than have a default for this too. S-mode profiles will again automatically set this to what it mandates, relieving the burden. > +#endif > +} > #else > static void rv32_base_cpu_init(Object *obj) > { > @@ -1732,6 +1744,13 @@ void riscv_cpu_list(void) > .instance_init = initfn \ > } > > +#define DEFINE_BARE_CPU(type_name, initfn) \ > + { \ > + .name = type_name, \ > + .parent = TYPE_RISCV_BARE_CPU, \ > + .instance_init = initfn \ > + } > + > static const TypeInfo riscv_cpu_type_infos[] = { > { > .name = TYPE_RISCV_CPU, > @@ -1754,6 +1773,11 @@ static const TypeInfo riscv_cpu_type_infos[] = { > .parent = TYPE_RISCV_CPU, > .abstract = true, > }, > + { > + .name = TYPE_RISCV_BARE_CPU, > + .parent = TYPE_RISCV_CPU, > + .abstract = true, > + }, > DEFINE_DYNAMIC_CPU(TYPE_RISCV_CPU_ANY, riscv_any_cpu_init), > DEFINE_DYNAMIC_CPU(TYPE_RISCV_CPU_MAX, riscv_max_cpu_init), > #if defined(TARGET_RISCV32) > @@ -1770,6 +1794,7 @@ static const TypeInfo riscv_cpu_type_infos[] = { > DEFINE_VENDOR_CPU(TYPE_RISCV_CPU_THEAD_C906, rv64_thead_c906_cpu_init), > DEFINE_VENDOR_CPU(TYPE_RISCV_CPU_VEYRON_V1, rv64_veyron_v1_cpu_init), > DEFINE_DYNAMIC_CPU(TYPE_RISCV_CPU_BASE128, rv128_base_cpu_init), > + DEFINE_BARE_CPU(TYPE_RISCV_CPU_RV64I, rv64i_bare_cpu_init), > #endif > }; > > -- > 2.41.0 > Thanks, drew
On 11/1/23 06:02, Andrew Jones wrote: > On Tue, Oct 31, 2023 at 05:39:03PM -0300, Daniel Henrique Barboza wrote: >> We don't have any form of a 'bare bones' CPU. rv64, our default CPUs, >> comes with a lot of defaults. This is fine for most regular uses but >> it's not suitable when more control of what is actually loaded in the >> CPU is required. >> >> A bare-bones CPU would be annoying to deal with if not by profile >> support, a way to load a multitude of extensions with a single flag. Profile >> support is going to be implemented shortly, so let's add a CPU for it. >> >> The new 'rv64i' CPU will have only RVI loaded. It is inspired in the >> profile specification that dictates, for RVA22U64 [1]: >> >> "RVA22U64 Mandatory Base >> RV64I is the mandatory base ISA for RVA22U64" >> >> And so it seems that RV64I is the mandatory base ISA for all profiles >> listed in [1], making it an ideal CPU to use with profile support. >> >> rv64i is a CPU of type TYPE_RISCV_BARE_CPU. It has a mix of features >> from pre-existent CPUs: >> >> - it allows extensions to be enabled, like generic CPUs; >> - it will not inherit extension defaults, like vendor CPUs. >> >> This is the minimum extension set to boot OpenSBI and buildroot using >> rv64i: >> >> ./build/qemu-system-riscv64 -nographic -M virt \ >> -cpu rv64i,g=true,c=true,s=true,u=true >> >> Our minimal riscv,isa in this case will be: >> >> # cat /proc/device-tree/cpus/cpu@0/riscv,isa >> rv64imafdc_zicntr_zicsr_zifencei_zihpm_zca_zcd# >> >> [1] https://github.com/riscv/riscv-profiles/blob/main/profiles.adoc >> >> Signed-off-by: Daniel Henrique Barboza <dbarboza@ventanamicro.com> >> --- >> target/riscv/cpu-qom.h | 2 ++ >> target/riscv/cpu.c | 25 +++++++++++++++++++++++++ >> 2 files changed, 27 insertions(+) >> >> diff --git a/target/riscv/cpu-qom.h b/target/riscv/cpu-qom.h >> index 7831e86d37..ea9a752280 100644 >> --- a/target/riscv/cpu-qom.h >> +++ b/target/riscv/cpu-qom.h >> @@ -25,6 +25,7 @@ >> #define TYPE_RISCV_CPU "riscv-cpu" >> #define TYPE_RISCV_DYNAMIC_CPU "riscv-dynamic-cpu" >> #define TYPE_RISCV_VENDOR_CPU "riscv-vendor-cpu" >> +#define TYPE_RISCV_BARE_CPU "riscv-bare-cpu" >> >> #define RISCV_CPU_TYPE_SUFFIX "-" TYPE_RISCV_CPU >> #define RISCV_CPU_TYPE_NAME(name) (name RISCV_CPU_TYPE_SUFFIX) >> @@ -35,6 +36,7 @@ >> #define TYPE_RISCV_CPU_BASE32 RISCV_CPU_TYPE_NAME("rv32") >> #define TYPE_RISCV_CPU_BASE64 RISCV_CPU_TYPE_NAME("rv64") >> #define TYPE_RISCV_CPU_BASE128 RISCV_CPU_TYPE_NAME("x-rv128") >> +#define TYPE_RISCV_CPU_RV64I RISCV_CPU_TYPE_NAME("rv64i") >> #define TYPE_RISCV_CPU_IBEX RISCV_CPU_TYPE_NAME("lowrisc-ibex") >> #define TYPE_RISCV_CPU_SHAKTI_C RISCV_CPU_TYPE_NAME("shakti-c") >> #define TYPE_RISCV_CPU_SIFIVE_E31 RISCV_CPU_TYPE_NAME("sifive-e31") >> diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c >> index 822970345c..98b2a4061a 100644 >> --- a/target/riscv/cpu.c >> +++ b/target/riscv/cpu.c >> @@ -544,6 +544,18 @@ static void rv128_base_cpu_init(Object *obj) >> set_satp_mode_max_supported(RISCV_CPU(obj), VM_1_10_SV57); >> #endif >> } >> + >> +static void rv64i_bare_cpu_init(Object *obj) >> +{ >> + CPURISCVState *env = &RISCV_CPU(obj)->env; >> + riscv_cpu_set_misa(env, MXL_RV64, RVI); >> + >> + /* Set latest version of privileged specification */ >> + env->priv_ver = PRIV_VERSION_LATEST; > > The beauty of rv64i is we'll finally know exactly what we're configuring > when we select it and some set of extensions. With that in mind I think > we should also be explicit about which version of the priv spec is > implemented, but we can't just pick a version now, since we may need to > update it later. I think we have the following options: > > 1. Expose priv version properties (v1_10_0, ...) and either require the > user to select one or default to the latest. (Any versions we don't > want to support for rv64i would error out if selected.) This is already the case but it's a string property instead of booleans: $ ./build/qemu-system-riscv64 -M virt -cpu rv64i,priv_spec="v1.11.0" $ ./build/qemu-system-riscv64 -M virt -cpu rv64i,priv_spec="v1.10.0" $ ./build/qemu-system-riscv64 -M virt -cpu rv64i,priv_spec="not_valid" qemu-system-riscv64: Unsupported privilege spec version 'not_valid' If users set 'priv_spec' we'll use it, otherwise rv64i will default to 'latest'. In case we do not want string values (and yeah, it's extra work to parse it, check if it's the right val and so on) then we can add priv spec bools that users would set on or off. We would need to deprecate "priv_spec" as it is. This can be done outside of this work (we would need a RFC first probably). > > 2. Add multiple rv64i base cpu types where the version is also specified > in the name, e.g. rv64i_1_12_0, and then maybe have an rv64i alias > which always points at the latest. > > A nice thing about (1) is that we can expose the boolean version > properties in cpu model expansion. A nice thing about (2) is that the user > will either be forced to select an explicit version or, if we have the > alias, libvirt will convert 'rv64i' into its full name when storing it > in the XML. But, we can force the user to select a version with (1) too by > not providing a default. While that adds a burden of always having to > provide a version, it's not a big deal for a barebones cpu, since all > extensions necessary to create a useful cpu are also required. And, > profiles alleviate the burden. For example, rva22s64 mandates Ss1p12, so > that profile will automatically set the v1_12_0 property. > > I think we should implement (1) without a default. > >> +#ifndef CONFIG_USER_ONLY >> + set_satp_mode_max_supported(RISCV_CPU(obj), VM_1_10_SV57); > > I think we should require the user provide one of sv39, sv48, ... rather > than have a default for this too. S-mode profiles will again automatically > set this to what it mandates, relieving the burden. Makes sense. I'll remove this default. Thanks, Daniel > >> +#endif >> +} >> #else >> static void rv32_base_cpu_init(Object *obj) >> { >> @@ -1732,6 +1744,13 @@ void riscv_cpu_list(void) >> .instance_init = initfn \ >> } >> >> +#define DEFINE_BARE_CPU(type_name, initfn) \ >> + { \ >> + .name = type_name, \ >> + .parent = TYPE_RISCV_BARE_CPU, \ >> + .instance_init = initfn \ >> + } >> + >> static const TypeInfo riscv_cpu_type_infos[] = { >> { >> .name = TYPE_RISCV_CPU, >> @@ -1754,6 +1773,11 @@ static const TypeInfo riscv_cpu_type_infos[] = { >> .parent = TYPE_RISCV_CPU, >> .abstract = true, >> }, >> + { >> + .name = TYPE_RISCV_BARE_CPU, >> + .parent = TYPE_RISCV_CPU, >> + .abstract = true, >> + }, >> DEFINE_DYNAMIC_CPU(TYPE_RISCV_CPU_ANY, riscv_any_cpu_init), >> DEFINE_DYNAMIC_CPU(TYPE_RISCV_CPU_MAX, riscv_max_cpu_init), >> #if defined(TARGET_RISCV32) >> @@ -1770,6 +1794,7 @@ static const TypeInfo riscv_cpu_type_infos[] = { >> DEFINE_VENDOR_CPU(TYPE_RISCV_CPU_THEAD_C906, rv64_thead_c906_cpu_init), >> DEFINE_VENDOR_CPU(TYPE_RISCV_CPU_VEYRON_V1, rv64_veyron_v1_cpu_init), >> DEFINE_DYNAMIC_CPU(TYPE_RISCV_CPU_BASE128, rv128_base_cpu_init), >> + DEFINE_BARE_CPU(TYPE_RISCV_CPU_RV64I, rv64i_bare_cpu_init), >> #endif >> }; >> >> -- >> 2.41.0 >> > > Thanks, > drew
On Wed, Nov 01, 2023 at 06:27:02AM -0300, Daniel Henrique Barboza wrote: > > > On 11/1/23 06:02, Andrew Jones wrote: > > On Tue, Oct 31, 2023 at 05:39:03PM -0300, Daniel Henrique Barboza wrote: > > > We don't have any form of a 'bare bones' CPU. rv64, our default CPUs, > > > comes with a lot of defaults. This is fine for most regular uses but > > > it's not suitable when more control of what is actually loaded in the > > > CPU is required. > > > > > > A bare-bones CPU would be annoying to deal with if not by profile > > > support, a way to load a multitude of extensions with a single flag. Profile > > > support is going to be implemented shortly, so let's add a CPU for it. > > > > > > The new 'rv64i' CPU will have only RVI loaded. It is inspired in the > > > profile specification that dictates, for RVA22U64 [1]: > > > > > > "RVA22U64 Mandatory Base > > > RV64I is the mandatory base ISA for RVA22U64" > > > > > > And so it seems that RV64I is the mandatory base ISA for all profiles > > > listed in [1], making it an ideal CPU to use with profile support. > > > > > > rv64i is a CPU of type TYPE_RISCV_BARE_CPU. It has a mix of features > > > from pre-existent CPUs: > > > > > > - it allows extensions to be enabled, like generic CPUs; > > > - it will not inherit extension defaults, like vendor CPUs. > > > > > > This is the minimum extension set to boot OpenSBI and buildroot using > > > rv64i: > > > > > > ./build/qemu-system-riscv64 -nographic -M virt \ > > > -cpu rv64i,g=true,c=true,s=true,u=true > > > > > > Our minimal riscv,isa in this case will be: > > > > > > # cat /proc/device-tree/cpus/cpu@0/riscv,isa > > > rv64imafdc_zicntr_zicsr_zifencei_zihpm_zca_zcd# > > > > > > [1] https://github.com/riscv/riscv-profiles/blob/main/profiles.adoc > > > > > > Signed-off-by: Daniel Henrique Barboza <dbarboza@ventanamicro.com> > > > --- > > > target/riscv/cpu-qom.h | 2 ++ > > > target/riscv/cpu.c | 25 +++++++++++++++++++++++++ > > > 2 files changed, 27 insertions(+) > > > > > > diff --git a/target/riscv/cpu-qom.h b/target/riscv/cpu-qom.h > > > index 7831e86d37..ea9a752280 100644 > > > --- a/target/riscv/cpu-qom.h > > > +++ b/target/riscv/cpu-qom.h > > > @@ -25,6 +25,7 @@ > > > #define TYPE_RISCV_CPU "riscv-cpu" > > > #define TYPE_RISCV_DYNAMIC_CPU "riscv-dynamic-cpu" > > > #define TYPE_RISCV_VENDOR_CPU "riscv-vendor-cpu" > > > +#define TYPE_RISCV_BARE_CPU "riscv-bare-cpu" > > > #define RISCV_CPU_TYPE_SUFFIX "-" TYPE_RISCV_CPU > > > #define RISCV_CPU_TYPE_NAME(name) (name RISCV_CPU_TYPE_SUFFIX) > > > @@ -35,6 +36,7 @@ > > > #define TYPE_RISCV_CPU_BASE32 RISCV_CPU_TYPE_NAME("rv32") > > > #define TYPE_RISCV_CPU_BASE64 RISCV_CPU_TYPE_NAME("rv64") > > > #define TYPE_RISCV_CPU_BASE128 RISCV_CPU_TYPE_NAME("x-rv128") > > > +#define TYPE_RISCV_CPU_RV64I RISCV_CPU_TYPE_NAME("rv64i") > > > #define TYPE_RISCV_CPU_IBEX RISCV_CPU_TYPE_NAME("lowrisc-ibex") > > > #define TYPE_RISCV_CPU_SHAKTI_C RISCV_CPU_TYPE_NAME("shakti-c") > > > #define TYPE_RISCV_CPU_SIFIVE_E31 RISCV_CPU_TYPE_NAME("sifive-e31") > > > diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c > > > index 822970345c..98b2a4061a 100644 > > > --- a/target/riscv/cpu.c > > > +++ b/target/riscv/cpu.c > > > @@ -544,6 +544,18 @@ static void rv128_base_cpu_init(Object *obj) > > > set_satp_mode_max_supported(RISCV_CPU(obj), VM_1_10_SV57); > > > #endif > > > } > > > + > > > +static void rv64i_bare_cpu_init(Object *obj) > > > +{ > > > + CPURISCVState *env = &RISCV_CPU(obj)->env; > > > + riscv_cpu_set_misa(env, MXL_RV64, RVI); > > > + > > > + /* Set latest version of privileged specification */ > > > + env->priv_ver = PRIV_VERSION_LATEST; > > > > The beauty of rv64i is we'll finally know exactly what we're configuring > > when we select it and some set of extensions. With that in mind I think > > we should also be explicit about which version of the priv spec is > > implemented, but we can't just pick a version now, since we may need to > > update it later. I think we have the following options: > > > > 1. Expose priv version properties (v1_10_0, ...) and either require the > > user to select one or default to the latest. (Any versions we don't > > want to support for rv64i would error out if selected.) > > This is already the case but it's a string property instead of booleans: > > $ ./build/qemu-system-riscv64 -M virt -cpu rv64i,priv_spec="v1.11.0" > $ ./build/qemu-system-riscv64 -M virt -cpu rv64i,priv_spec="v1.10.0" > $ ./build/qemu-system-riscv64 -M virt -cpu rv64i,priv_spec="not_valid" > qemu-system-riscv64: Unsupported privilege spec version 'not_valid' > > If users set 'priv_spec' we'll use it, otherwise rv64i will default to 'latest'. I think I'd prefer we don't have a default, but maybe in practice it'll be OK, since once we have S-mode profiles (which will most likely always be used with rv64i) then they'll override the default anyway. > > In case we do not want string values (and yeah, it's extra work to parse it, check > if it's the right val and so on) then we can add priv spec bools that users would > set on or off. We would need to deprecate "priv_spec" as it is. Yes, we should switch to booleans for cpu-model-expansion. I suppose we should keep the priv_ver default until we switch to booleans, though, in order to avoid encouraging more deprecated priv_spec usage in the meantime. > > This can be done outside of this work (we would need a RFC first probably). I can live with that. Thanks, drew
diff --git a/target/riscv/cpu-qom.h b/target/riscv/cpu-qom.h index 7831e86d37..ea9a752280 100644 --- a/target/riscv/cpu-qom.h +++ b/target/riscv/cpu-qom.h @@ -25,6 +25,7 @@ #define TYPE_RISCV_CPU "riscv-cpu" #define TYPE_RISCV_DYNAMIC_CPU "riscv-dynamic-cpu" #define TYPE_RISCV_VENDOR_CPU "riscv-vendor-cpu" +#define TYPE_RISCV_BARE_CPU "riscv-bare-cpu" #define RISCV_CPU_TYPE_SUFFIX "-" TYPE_RISCV_CPU #define RISCV_CPU_TYPE_NAME(name) (name RISCV_CPU_TYPE_SUFFIX) @@ -35,6 +36,7 @@ #define TYPE_RISCV_CPU_BASE32 RISCV_CPU_TYPE_NAME("rv32") #define TYPE_RISCV_CPU_BASE64 RISCV_CPU_TYPE_NAME("rv64") #define TYPE_RISCV_CPU_BASE128 RISCV_CPU_TYPE_NAME("x-rv128") +#define TYPE_RISCV_CPU_RV64I RISCV_CPU_TYPE_NAME("rv64i") #define TYPE_RISCV_CPU_IBEX RISCV_CPU_TYPE_NAME("lowrisc-ibex") #define TYPE_RISCV_CPU_SHAKTI_C RISCV_CPU_TYPE_NAME("shakti-c") #define TYPE_RISCV_CPU_SIFIVE_E31 RISCV_CPU_TYPE_NAME("sifive-e31") diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c index 822970345c..98b2a4061a 100644 --- a/target/riscv/cpu.c +++ b/target/riscv/cpu.c @@ -544,6 +544,18 @@ static void rv128_base_cpu_init(Object *obj) set_satp_mode_max_supported(RISCV_CPU(obj), VM_1_10_SV57); #endif } + +static void rv64i_bare_cpu_init(Object *obj) +{ + CPURISCVState *env = &RISCV_CPU(obj)->env; + riscv_cpu_set_misa(env, MXL_RV64, RVI); + + /* Set latest version of privileged specification */ + env->priv_ver = PRIV_VERSION_LATEST; +#ifndef CONFIG_USER_ONLY + set_satp_mode_max_supported(RISCV_CPU(obj), VM_1_10_SV57); +#endif +} #else static void rv32_base_cpu_init(Object *obj) { @@ -1732,6 +1744,13 @@ void riscv_cpu_list(void) .instance_init = initfn \ } +#define DEFINE_BARE_CPU(type_name, initfn) \ + { \ + .name = type_name, \ + .parent = TYPE_RISCV_BARE_CPU, \ + .instance_init = initfn \ + } + static const TypeInfo riscv_cpu_type_infos[] = { { .name = TYPE_RISCV_CPU, @@ -1754,6 +1773,11 @@ static const TypeInfo riscv_cpu_type_infos[] = { .parent = TYPE_RISCV_CPU, .abstract = true, }, + { + .name = TYPE_RISCV_BARE_CPU, + .parent = TYPE_RISCV_CPU, + .abstract = true, + }, DEFINE_DYNAMIC_CPU(TYPE_RISCV_CPU_ANY, riscv_any_cpu_init), DEFINE_DYNAMIC_CPU(TYPE_RISCV_CPU_MAX, riscv_max_cpu_init), #if defined(TARGET_RISCV32) @@ -1770,6 +1794,7 @@ static const TypeInfo riscv_cpu_type_infos[] = { DEFINE_VENDOR_CPU(TYPE_RISCV_CPU_THEAD_C906, rv64_thead_c906_cpu_init), DEFINE_VENDOR_CPU(TYPE_RISCV_CPU_VEYRON_V1, rv64_veyron_v1_cpu_init), DEFINE_DYNAMIC_CPU(TYPE_RISCV_CPU_BASE128, rv128_base_cpu_init), + DEFINE_BARE_CPU(TYPE_RISCV_CPU_RV64I, rv64i_bare_cpu_init), #endif };
We don't have any form of a 'bare bones' CPU. rv64, our default CPUs, comes with a lot of defaults. This is fine for most regular uses but it's not suitable when more control of what is actually loaded in the CPU is required. A bare-bones CPU would be annoying to deal with if not by profile support, a way to load a multitude of extensions with a single flag. Profile support is going to be implemented shortly, so let's add a CPU for it. The new 'rv64i' CPU will have only RVI loaded. It is inspired in the profile specification that dictates, for RVA22U64 [1]: "RVA22U64 Mandatory Base RV64I is the mandatory base ISA for RVA22U64" And so it seems that RV64I is the mandatory base ISA for all profiles listed in [1], making it an ideal CPU to use with profile support. rv64i is a CPU of type TYPE_RISCV_BARE_CPU. It has a mix of features from pre-existent CPUs: - it allows extensions to be enabled, like generic CPUs; - it will not inherit extension defaults, like vendor CPUs. This is the minimum extension set to boot OpenSBI and buildroot using rv64i: ./build/qemu-system-riscv64 -nographic -M virt \ -cpu rv64i,g=true,c=true,s=true,u=true Our minimal riscv,isa in this case will be: # cat /proc/device-tree/cpus/cpu@0/riscv,isa rv64imafdc_zicntr_zicsr_zifencei_zihpm_zca_zcd# [1] https://github.com/riscv/riscv-profiles/blob/main/profiles.adoc Signed-off-by: Daniel Henrique Barboza <dbarboza@ventanamicro.com> --- target/riscv/cpu-qom.h | 2 ++ target/riscv/cpu.c | 25 +++++++++++++++++++++++++ 2 files changed, 27 insertions(+)