* [PATCH v10 0/5] hw/riscv: Server Platform Reference Board
@ 2026-09-04 19:56 Daniel Henrique Barboza
2026-09-04 19:56 ` [PATCH v10 1/5] target/riscv/cpu.c: remove 'bare' condition for .profile Daniel Henrique Barboza
` (4 more replies)
0 siblings, 5 replies; 19+ messages in thread
From: Daniel Henrique Barboza @ 2026-09-04 19:56 UTC (permalink / raw)
To: qemu-devel
Cc: qemu-riscv, alistair.francis, liwei1518, zhiwei_liu, chao.liu,
andrew.jones, leif.lindholm, Daniel Henrique Barboza
Greetings,
The latest RISC-V PR merged in trunk introduced changes that conflicts
with the v9 version. This version is a trivial rebase on top of it.
No other changes made. Patches based on master.
All patches acked.
Please bear in mind that we need
[PATCH v7 0/7] riscv: add initial sdext support
To land before this series.
Changes from v9:
- fixed conflicts after changes in QAPI and aia/mtimer APIs that landed
in master.
- v9 link: https://lore.kernel.org/qemu-devel/20260903183125.682865-1-daniel.barboza@oss.qualcomm.com/
Based-on: <20260831141007.353854-1-daniel.barboza@oss.qualcomm.com>
([PATCH v7 0/7] riscv: add initial sdext support)
Daniel Henrique Barboza (5):
target/riscv/cpu.c: remove 'bare' condition for .profile
target/riscv: add riscv-server-ref CPU
hw/riscv: server platform reference machine
tests/functional/riscv64: add riscv-server-ref tests
docs: add riscv-server-ref.rst
configs/devices/riscv64-softmmu/default.mak | 1 +
docs/system/riscv/riscv-server-ref.rst | 62 ++
docs/system/target-riscv.rst | 1 +
hw/riscv/Kconfig | 16 +
hw/riscv/meson.build | 1 +
hw/riscv/server_platform_ref.c | 769 ++++++++++++++++++++
target/riscv/cpu-qom.h | 1 +
target/riscv/cpu.c | 32 +-
tests/functional/riscv64/meson.build | 2 +
tests/functional/riscv64/test_opensbi.py | 4 +
tests/functional/riscv64/test_server_ref.py | 88 +++
11 files changed, 976 insertions(+), 1 deletion(-)
create mode 100644 docs/system/riscv/riscv-server-ref.rst
create mode 100644 hw/riscv/server_platform_ref.c
create mode 100755 tests/functional/riscv64/test_server_ref.py
--
2.43.0
^ permalink raw reply [flat|nested] 19+ messages in thread* [PATCH v10 1/5] target/riscv/cpu.c: remove 'bare' condition for .profile 2026-09-04 19:56 [PATCH v10 0/5] hw/riscv: Server Platform Reference Board Daniel Henrique Barboza @ 2026-09-04 19:56 ` Daniel Henrique Barboza 2026-09-08 3:26 ` Sunil V L 2026-09-04 19:56 ` [PATCH v10 2/5] target/riscv: add riscv-server-ref CPU Daniel Henrique Barboza ` (3 subsequent siblings) 4 siblings, 1 reply; 19+ messages in thread From: Daniel Henrique Barboza @ 2026-09-04 19:56 UTC (permalink / raw) To: qemu-devel Cc: qemu-riscv, alistair.francis, liwei1518, zhiwei_liu, chao.liu, andrew.jones, leif.lindholm, Daniel Henrique Barboza, Palmer Dabbelt We want to configure other CPU types to use profiles as an alternative to adding every profile extension explicitly, i.e. a profile is nothing more than an extension bundle. This means that a vendor CPU can set .profile=rva23s64 while having the same handling as any other vendor CPU. Same thing with all other CPU types. Signed-off-by: Daniel Henrique Barboza <daniel.barboza@oss.qualcomm.com> Reviewed-by: Andrew Jones <andrew.jones@oss.qualcomm.com> Reviewed-by: Alistair Francis <alistair.francis@wdc.com> Reviewed-by: Chao Liu <chao.liu@processmission.com> --- target/riscv/cpu.c | 1 - 1 file changed, 1 deletion(-) diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c index 652311ddef..185474a8cf 100644 --- a/target/riscv/cpu.c +++ b/target/riscv/cpu.c @@ -3096,7 +3096,6 @@ static void riscv_cpu_class_base_init(ObjectClass *c, const void *data) mcc->def->bare |= def->bare; if (def->profile) { assert(profile_extends(def->profile, mcc->def->profile)); - assert(mcc->def->bare); mcc->def->profile = def->profile; } if (def->misa_mxl_max) { -- 2.43.0 ^ permalink raw reply related [flat|nested] 19+ messages in thread
* Re: [PATCH v10 1/5] target/riscv/cpu.c: remove 'bare' condition for .profile 2026-09-04 19:56 ` [PATCH v10 1/5] target/riscv/cpu.c: remove 'bare' condition for .profile Daniel Henrique Barboza @ 2026-09-08 3:26 ` Sunil V L 0 siblings, 0 replies; 19+ messages in thread From: Sunil V L @ 2026-09-08 3:26 UTC (permalink / raw) To: Daniel Henrique Barboza Cc: qemu-devel, qemu-riscv, alistair.francis, liwei1518, zhiwei_liu, chao.liu, andrew.jones, leif.lindholm, Palmer Dabbelt On Sat, Sep 5, 2026 at 1:27 AM Daniel Henrique Barboza <daniel.barboza@oss.qualcomm.com> wrote: > > We want to configure other CPU types to use profiles as an alternative > to adding every profile extension explicitly, i.e. a profile is nothing > more than an extension bundle. > > This means that a vendor CPU can set .profile=rva23s64 while having the > same handling as any other vendor CPU. Same thing with all other CPU > types. > > Signed-off-by: Daniel Henrique Barboza <daniel.barboza@oss.qualcomm.com> > Reviewed-by: Andrew Jones <andrew.jones@oss.qualcomm.com> > Reviewed-by: Alistair Francis <alistair.francis@wdc.com> > Reviewed-by: Chao Liu <chao.liu@processmission.com> > --- > target/riscv/cpu.c | 1 - > 1 file changed, 1 deletion(-) > > diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c > index 652311ddef..185474a8cf 100644 > --- a/target/riscv/cpu.c > +++ b/target/riscv/cpu.c > @@ -3096,7 +3096,6 @@ static void riscv_cpu_class_base_init(ObjectClass *c, const void *data) > mcc->def->bare |= def->bare; > if (def->profile) { > assert(profile_extends(def->profile, mcc->def->profile)); > - assert(mcc->def->bare); > mcc->def->profile = def->profile; > } > if (def->misa_mxl_max) { > -- > 2.43.0 > Reviewed-by: Sunil V L <sunilvl@oss.qualcomm.com> ^ permalink raw reply [flat|nested] 19+ messages in thread
* [PATCH v10 2/5] target/riscv: add riscv-server-ref CPU 2026-09-04 19:56 [PATCH v10 0/5] hw/riscv: Server Platform Reference Board Daniel Henrique Barboza 2026-09-04 19:56 ` [PATCH v10 1/5] target/riscv/cpu.c: remove 'bare' condition for .profile Daniel Henrique Barboza @ 2026-09-04 19:56 ` Daniel Henrique Barboza 2026-09-08 7:30 ` Sunil V L 2026-09-08 9:08 ` Andrew Jones 2026-09-04 19:56 ` [PATCH v10 3/5] hw/riscv: server platform reference machine Daniel Henrique Barboza ` (2 subsequent siblings) 4 siblings, 2 replies; 19+ messages in thread From: Daniel Henrique Barboza @ 2026-09-04 19:56 UTC (permalink / raw) To: qemu-devel Cc: qemu-riscv, alistair.francis, liwei1518, zhiwei_liu, chao.liu, andrew.jones, leif.lindholm, Daniel Henrique Barboza, Icenowy Zheng, Matheus Ferst, Palmer Dabbelt The harts requirements of RISC-V server platform [1] require RVA23 ISA profile support and others. We're going for a profile-based implementation, instead of a regular CPU that can inherit RVA23, to allow future CPUs to use it internally as a starting base for their own extension sets. There's also a new 'rvserver-ref-1.0' flag that can be used to set the extensions in the command line for other CPUs, which can be used for testing/debugging purposes. Note that for all intents and purposes "riscv-server-ref" is a regular CPU and no, we're not trying to set a precedent of calling the riscv server platform spec a profile. [1] defines in rule SEE_020 that we must support at least 11 debug triggers (4 for insn address, 4 for insn load/store, 1 for icount, one for int, one for excp). We're going for the minimum. If more triggers are needed users can set any trigger amount with: -cpu riscv-server-ref,trigger-count=N Note that N must be <= 128. [1] https://github.com/riscv-non-isa/riscv-server-platform/blob/main/server_platform_requirements.adoc Suggested-by: Icenowy Zheng <uwu@icenowy.me> Signed-off-by: Daniel Henrique Barboza <daniel.barboza@oss.qualcomm.com> Reviewed-by: Alistair Francis <alistair.francis@wdc.com> Reviewed-by: Matheus Ferst <matheus.ferst@eldorado.org.br> Reviewed-by: Chao Liu <chao.liu@processmission.com> --- target/riscv/cpu-qom.h | 1 + target/riscv/cpu.c | 31 +++++++++++++++++++++++++++++++ 2 files changed, 32 insertions(+) diff --git a/target/riscv/cpu-qom.h b/target/riscv/cpu-qom.h index 1a28f1369c..61234842e3 100644 --- a/target/riscv/cpu-qom.h +++ b/target/riscv/cpu-qom.h @@ -42,6 +42,7 @@ #define TYPE_RISCV_CPU_RVA22S64 RISCV_CPU_TYPE_NAME("rva22s64") #define TYPE_RISCV_CPU_RVA23U64 RISCV_CPU_TYPE_NAME("rva23u64") #define TYPE_RISCV_CPU_RVA23S64 RISCV_CPU_TYPE_NAME("rva23s64") +#define TYPE_RISCV_CPU_RVSERVER_REF RISCV_CPU_TYPE_NAME("riscv-server-ref") #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_E RISCV_CPU_TYPE_NAME("sifive-e") diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c index 185474a8cf..b5a75fbc1c 100644 --- a/target/riscv/cpu.c +++ b/target/riscv/cpu.c @@ -2417,11 +2417,35 @@ static RISCVCPUProfile RVA23S64 = { } }; +/* + * The riscv-server-ref spec isn't a profile per se but its + * CPU definition can be modelled as a profile that extends + * RVA23, with additional things on top of it, and allowing + * future CPUs to derive from it via + * ".profile = &RVServerRef1_0;". + */ +static RISCVCPUProfile RVServerRef1_0 = { + .s_parent = &RVA23S64, + .name = "rvserver-ref-1.0", + .satp_mode = VM_1_10_SV48, + .ext_offsets = { + CPU_CFG_OFFSET(ext_zkr), + CPU_CFG_OFFSET(ext_sdtrig), + CPU_CFG_OFFSET(ext_ssaia), + CPU_CFG_OFFSET(ext_ssccfg), + /* ssstrict is always enabled for PRIV_VER_1_12 */ + + RISCV_PROFILE_EXT_LIST_END + } +}; + + RISCVCPUProfile *riscv_profiles[] = { &RVA22U64, &RVA22S64, &RVA23U64, &RVA23S64, + &RVServerRef1_0, NULL, }; @@ -3759,6 +3783,13 @@ static const TypeInfo riscv_cpu_type_infos[] = { #endif ), + DEFINE_RISCV_CPU(TYPE_RISCV_CPU_RVSERVER_REF, TYPE_RISCV_BARE_CPU, + .profile = &RVServerRef1_0, + .misa_mxl_max = MXL_RV64, + .cfg.max_satp_mode = VM_1_10_SV57, + .num_triggers = 11, + ), + #if defined(CONFIG_TCG) && !defined(CONFIG_USER_ONLY) DEFINE_RISCV_CPU(TYPE_RISCV_CPU_BASE128, TYPE_RISCV_DYNAMIC_CPU, .cfg.max_satp_mode = VM_1_10_SV57, -- 2.43.0 ^ permalink raw reply related [flat|nested] 19+ messages in thread
* Re: [PATCH v10 2/5] target/riscv: add riscv-server-ref CPU 2026-09-04 19:56 ` [PATCH v10 2/5] target/riscv: add riscv-server-ref CPU Daniel Henrique Barboza @ 2026-09-08 7:30 ` Sunil V L 2026-09-08 9:08 ` Andrew Jones 1 sibling, 0 replies; 19+ messages in thread From: Sunil V L @ 2026-09-08 7:30 UTC (permalink / raw) To: Daniel Henrique Barboza Cc: qemu-devel, qemu-riscv, alistair.francis, liwei1518, zhiwei_liu, chao.liu, andrew.jones, leif.lindholm, Icenowy Zheng, Matheus Ferst, Palmer Dabbelt On Sat, Sep 5, 2026 at 1:27 AM Daniel Henrique Barboza <daniel.barboza@oss.qualcomm.com> wrote: > > The harts requirements of RISC-V server platform [1] require RVA23 ISA > profile support and others. > > We're going for a profile-based implementation, instead of a regular CPU > that can inherit RVA23, to allow future CPUs to use it internally as a > starting base for their own extension sets. There's also a new > 'rvserver-ref-1.0' flag that can be used to set the extensions in the > command line for other CPUs, which can be used for testing/debugging > purposes. > > Note that for all intents and purposes "riscv-server-ref" is a regular > CPU and no, we're not trying to set a precedent of calling the riscv > server platform spec a profile. > > [1] defines in rule SEE_020 that we must support at least 11 debug > triggers (4 for insn address, 4 for insn load/store, 1 for icount, > one for int, one for excp). We're going for the minimum. If more > triggers are needed users can set any trigger amount with: > > -cpu riscv-server-ref,trigger-count=N > > Note that N must be <= 128. > > [1] https://github.com/riscv-non-isa/riscv-server-platform/blob/main/server_platform_requirements.adoc > > Suggested-by: Icenowy Zheng <uwu@icenowy.me> > Signed-off-by: Daniel Henrique Barboza <daniel.barboza@oss.qualcomm.com> > Reviewed-by: Alistair Francis <alistair.francis@wdc.com> > Reviewed-by: Matheus Ferst <matheus.ferst@eldorado.org.br> > Reviewed-by: Chao Liu <chao.liu@processmission.com> > --- > target/riscv/cpu-qom.h | 1 + > target/riscv/cpu.c | 31 +++++++++++++++++++++++++++++++ > 2 files changed, 32 insertions(+) > Reviewed-by: Sunil V L <sunilvl@oss.qualcomm.com> ^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: [PATCH v10 2/5] target/riscv: add riscv-server-ref CPU 2026-09-04 19:56 ` [PATCH v10 2/5] target/riscv: add riscv-server-ref CPU Daniel Henrique Barboza 2026-09-08 7:30 ` Sunil V L @ 2026-09-08 9:08 ` Andrew Jones 2026-09-08 18:40 ` Daniel Henrique Barboza 1 sibling, 1 reply; 19+ messages in thread From: Andrew Jones @ 2026-09-08 9:08 UTC (permalink / raw) To: Daniel Henrique Barboza Cc: qemu-devel, qemu-riscv, alistair.francis, liwei1518, zhiwei_liu, chao.liu, leif.lindholm, Icenowy Zheng, Matheus Ferst, Palmer Dabbelt On Fri, Sep 04, 2026 at 04:56:07PM -0300, Daniel Henrique Barboza wrote: > The harts requirements of RISC-V server platform [1] require RVA23 ISA > profile support and others. > > We're going for a profile-based implementation, instead of a regular CPU > that can inherit RVA23, to allow future CPUs to use it internally as a > starting base for their own extension sets. There's also a new > 'rvserver-ref-1.0' flag that can be used to set the extensions in the > command line for other CPUs, which can be used for testing/debugging > purposes. > > Note that for all intents and purposes "riscv-server-ref" is a regular > CPU and no, we're not trying to set a precedent of calling the riscv > server platform spec a profile. > > [1] defines in rule SEE_020 that we must support at least 11 debug > triggers (4 for insn address, 4 for insn load/store, 1 for icount, > one for int, one for excp). We're going for the minimum. If more > triggers are needed users can set any trigger amount with: > > -cpu riscv-server-ref,trigger-count=N > > Note that N must be <= 128. > > [1] https://github.com/riscv-non-isa/riscv-server-platform/blob/main/server_platform_requirements.adoc > > Suggested-by: Icenowy Zheng <uwu@icenowy.me> > Signed-off-by: Daniel Henrique Barboza <daniel.barboza@oss.qualcomm.com> > Reviewed-by: Alistair Francis <alistair.francis@wdc.com> > Reviewed-by: Matheus Ferst <matheus.ferst@eldorado.org.br> > Reviewed-by: Chao Liu <chao.liu@processmission.com> > --- > target/riscv/cpu-qom.h | 1 + > target/riscv/cpu.c | 31 +++++++++++++++++++++++++++++++ > 2 files changed, 32 insertions(+) > > diff --git a/target/riscv/cpu-qom.h b/target/riscv/cpu-qom.h > index 1a28f1369c..61234842e3 100644 > --- a/target/riscv/cpu-qom.h > +++ b/target/riscv/cpu-qom.h > @@ -42,6 +42,7 @@ > #define TYPE_RISCV_CPU_RVA22S64 RISCV_CPU_TYPE_NAME("rva22s64") > #define TYPE_RISCV_CPU_RVA23U64 RISCV_CPU_TYPE_NAME("rva23u64") > #define TYPE_RISCV_CPU_RVA23S64 RISCV_CPU_TYPE_NAME("rva23s64") > +#define TYPE_RISCV_CPU_RVSERVER_REF RISCV_CPU_TYPE_NAME("riscv-server-ref") > #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_E RISCV_CPU_TYPE_NAME("sifive-e") > diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c > index 185474a8cf..b5a75fbc1c 100644 > --- a/target/riscv/cpu.c > +++ b/target/riscv/cpu.c > @@ -2417,11 +2417,35 @@ static RISCVCPUProfile RVA23S64 = { > } > }; > > +/* > + * The riscv-server-ref spec isn't a profile per se but its spec? > + * CPU definition can be modelled as a profile that extends > + * RVA23, with additional things on top of it, and allowing > + * future CPUs to derive from it via > + * ".profile = &RVServerRef1_0;". > + */ > +static RISCVCPUProfile RVServerRef1_0 = { > + .s_parent = &RVA23S64, > + .name = "rvserver-ref-1.0", The commit message and comment call this "riscv-server-ref" > + .satp_mode = VM_1_10_SV48, > + .ext_offsets = { > + CPU_CFG_OFFSET(ext_zkr), > + CPU_CFG_OFFSET(ext_sdtrig), > + CPU_CFG_OFFSET(ext_ssaia), > + CPU_CFG_OFFSET(ext_ssccfg), The cover letter says that the sdext patches need to be merged first. Don't we need to configure it here? > + /* ssstrict is always enabled for PRIV_VER_1_12 */ > + > + RISCV_PROFILE_EXT_LIST_END > + } > +}; > + > + > RISCVCPUProfile *riscv_profiles[] = { > &RVA22U64, > &RVA22S64, > &RVA23U64, > &RVA23S64, > + &RVServerRef1_0, > NULL, > }; > > @@ -3759,6 +3783,13 @@ static const TypeInfo riscv_cpu_type_infos[] = { > #endif > ), > > + DEFINE_RISCV_CPU(TYPE_RISCV_CPU_RVSERVER_REF, TYPE_RISCV_BARE_CPU, > + .profile = &RVServerRef1_0, > + .misa_mxl_max = MXL_RV64, > + .cfg.max_satp_mode = VM_1_10_SV57, > + .num_triggers = 11, > + ), > + > #if defined(CONFIG_TCG) && !defined(CONFIG_USER_ONLY) > DEFINE_RISCV_CPU(TYPE_RISCV_CPU_BASE128, TYPE_RISCV_DYNAMIC_CPU, > .cfg.max_satp_mode = VM_1_10_SV57, > -- > 2.43.0 > Thanks, drew ^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: [PATCH v10 2/5] target/riscv: add riscv-server-ref CPU 2026-09-08 9:08 ` Andrew Jones @ 2026-09-08 18:40 ` Daniel Henrique Barboza 0 siblings, 0 replies; 19+ messages in thread From: Daniel Henrique Barboza @ 2026-09-08 18:40 UTC (permalink / raw) To: Andrew Jones Cc: qemu-devel, qemu-riscv, alistair.francis, liwei1518, zhiwei_liu, chao.liu, leif.lindholm, Icenowy Zheng, Matheus Ferst, Palmer Dabbelt On 9/8/2026 6:08 AM, Andrew Jones wrote: > On Fri, Sep 04, 2026 at 04:56:07PM -0300, Daniel Henrique Barboza wrote: >> The harts requirements of RISC-V server platform [1] require RVA23 ISA >> profile support and others. >> >> We're going for a profile-based implementation, instead of a regular CPU >> that can inherit RVA23, to allow future CPUs to use it internally as a >> starting base for their own extension sets. There's also a new >> 'rvserver-ref-1.0' flag that can be used to set the extensions in the >> command line for other CPUs, which can be used for testing/debugging >> purposes. >> >> Note that for all intents and purposes "riscv-server-ref" is a regular >> CPU and no, we're not trying to set a precedent of calling the riscv >> server platform spec a profile. >> >> [1] defines in rule SEE_020 that we must support at least 11 debug >> triggers (4 for insn address, 4 for insn load/store, 1 for icount, >> one for int, one for excp). We're going for the minimum. If more >> triggers are needed users can set any trigger amount with: >> >> -cpu riscv-server-ref,trigger-count=N >> >> Note that N must be <= 128. >> >> [1] https://github.com/riscv-non-isa/riscv-server-platform/blob/main/server_platform_requirements.adoc >> >> Suggested-by: Icenowy Zheng <uwu@icenowy.me> >> Signed-off-by: Daniel Henrique Barboza <daniel.barboza@oss.qualcomm.com> >> Reviewed-by: Alistair Francis <alistair.francis@wdc.com> >> Reviewed-by: Matheus Ferst <matheus.ferst@eldorado.org.br> >> Reviewed-by: Chao Liu <chao.liu@processmission.com> >> --- >> target/riscv/cpu-qom.h | 1 + >> target/riscv/cpu.c | 31 +++++++++++++++++++++++++++++++ >> 2 files changed, 32 insertions(+) >> >> diff --git a/target/riscv/cpu-qom.h b/target/riscv/cpu-qom.h >> index 1a28f1369c..61234842e3 100644 >> --- a/target/riscv/cpu-qom.h >> +++ b/target/riscv/cpu-qom.h >> @@ -42,6 +42,7 @@ >> #define TYPE_RISCV_CPU_RVA22S64 RISCV_CPU_TYPE_NAME("rva22s64") >> #define TYPE_RISCV_CPU_RVA23U64 RISCV_CPU_TYPE_NAME("rva23u64") >> #define TYPE_RISCV_CPU_RVA23S64 RISCV_CPU_TYPE_NAME("rva23s64") >> +#define TYPE_RISCV_CPU_RVSERVER_REF RISCV_CPU_TYPE_NAME("riscv-server-ref") >> #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_E RISCV_CPU_TYPE_NAME("sifive-e") >> diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c >> index 185474a8cf..b5a75fbc1c 100644 >> --- a/target/riscv/cpu.c >> +++ b/target/riscv/cpu.c >> @@ -2417,11 +2417,35 @@ static RISCVCPUProfile RVA23S64 = { >> } >> }; >> >> +/* >> + * The riscv-server-ref spec isn't a profile per se but its > > spec? I'll replace this comment with: "This riscv-server-ref entry isn't a profile per se but ..." > >> + * CPU definition can be modelled as a profile that extends >> + * RVA23, with additional things on top of it, and allowing >> + * future CPUs to derive from it via >> + * ".profile = &RVServerRef1_0;". >> + */ >> +static RISCVCPUProfile RVServerRef1_0 = { >> + .s_parent = &RVA23S64, >> + .name = "rvserver-ref-1.0", > > The commit message and comment call this "riscv-server-ref" The CPU is called riscv-server-ref: #define TYPE_RISCV_CPU_RVSERVER_REF RISCV_CPU_TYPE_NAME("riscv-server-ref") "rvserver-ref-1.0" is the CPU profile name I came up with as a placeholder. I believe we can rename it to "riscv-server-ref-1.0" to avoid confusion. > >> + .satp_mode = VM_1_10_SV48, >> + .ext_offsets = { >> + CPU_CFG_OFFSET(ext_zkr), >> + CPU_CFG_OFFSET(ext_sdtrig), >> + CPU_CFG_OFFSET(ext_ssaia), >> + CPU_CFG_OFFSET(ext_ssccfg), > > The cover letter says that the sdext patches need to be merged first. > Don't we need to configure it here? Yeah ... we had a very earlier version where enabling sdtrig implied enabling sdext. That's not the case for some time now and forgot to manually add 'sdext' here. I'll do that. Thanks, Daniel > >> + /* ssstrict is always enabled for PRIV_VER_1_12 */ >> + >> + RISCV_PROFILE_EXT_LIST_END >> + } >> +}; >> + >> + >> RISCVCPUProfile *riscv_profiles[] = { >> &RVA22U64, >> &RVA22S64, >> &RVA23U64, >> &RVA23S64, >> + &RVServerRef1_0, >> NULL, >> }; >> >> @@ -3759,6 +3783,13 @@ static const TypeInfo riscv_cpu_type_infos[] = { >> #endif >> ), >> >> + DEFINE_RISCV_CPU(TYPE_RISCV_CPU_RVSERVER_REF, TYPE_RISCV_BARE_CPU, >> + .profile = &RVServerRef1_0, >> + .misa_mxl_max = MXL_RV64, >> + .cfg.max_satp_mode = VM_1_10_SV57, >> + .num_triggers = 11, >> + ), >> + >> #if defined(CONFIG_TCG) && !defined(CONFIG_USER_ONLY) >> DEFINE_RISCV_CPU(TYPE_RISCV_CPU_BASE128, TYPE_RISCV_DYNAMIC_CPU, >> .cfg.max_satp_mode = VM_1_10_SV57, >> -- >> 2.43.0 >> > > Thanks, > drew ^ permalink raw reply [flat|nested] 19+ messages in thread
* [PATCH v10 3/5] hw/riscv: server platform reference machine 2026-09-04 19:56 [PATCH v10 0/5] hw/riscv: Server Platform Reference Board Daniel Henrique Barboza 2026-09-04 19:56 ` [PATCH v10 1/5] target/riscv/cpu.c: remove 'bare' condition for .profile Daniel Henrique Barboza 2026-09-04 19:56 ` [PATCH v10 2/5] target/riscv: add riscv-server-ref CPU Daniel Henrique Barboza @ 2026-09-04 19:56 ` Daniel Henrique Barboza 2026-09-08 3:25 ` Sunil V L 2026-09-08 10:40 ` Andrew Jones 2026-09-04 19:56 ` [PATCH v10 4/5] tests/functional/riscv64: add riscv-server-ref tests Daniel Henrique Barboza 2026-09-04 19:56 ` [PATCH v10 5/5] docs: add riscv-server-ref.rst Daniel Henrique Barboza 4 siblings, 2 replies; 19+ messages in thread From: Daniel Henrique Barboza @ 2026-09-04 19:56 UTC (permalink / raw) To: qemu-devel Cc: qemu-riscv, alistair.francis, liwei1518, zhiwei_liu, chao.liu, andrew.jones, leif.lindholm, Daniel Henrique Barboza, Nutty Liu, Paolo Bonzini, Palmer Dabbelt The RISC-V Server Platform specification [1] defines a standardized set of hardware and software capabilities, that portable system software, such as OS and hypervisors can rely on being present in a RISC-V server platform. The main features included in this emulation are: - Based on riscv virt machine type; - A new memory map as close as virt machine as possible; - An always present IOMMU platform device (riscv-iommu-sys) that uses IRQs 36 to 39, one IRQ for queue, similar to the 'virt' board; - AIA; - PCIe AHCI; - PCIe NIC; - No virtio device; - No fw_cfg device; - No ACPI table provided; - Only minimal device tree nodes; - a platform bus for TPM support. A note about TPM support: TPM devices in QEMU comes usually in two flavors - emulated or passthrough. A passthrough device requires a host TPM device that the QEMU process can borrow and it's usually coupled with KVM acceleration. To use the TPM emulator we'll need help from an external TPM emulator called swtpm. More info can be found in [2]. For our purposes this is a process that, if running Ubuntu, can be installed via 'swtpm' package. We'll go back to it shortly. For now, adding support for the emulated TPM device 'tpm-tis' (other TPM flavors might work as well, 'tpm-tis' is the one tested with this work) requires a platform bus. Adding a platform bus will open the door for more devices to be added in the board. This is ok - a reference board isn't a restricted board and users are free to add devices at their leisure. Here's how to use tpm-tis with the riscv-server-ref board: - in a separated shell/term run 'swtpm' (--log is optional): $ mkdir /tmp/mytpm1 $ swtpm socket --tpmstate dir=/tmp/mytpm1 \ --ctrl type=unixio,path=/tmp/mytpm1/swtpm-sock \ --tpm2 \ --log level=20 Then start QEMU with: $ qemu-system-riscv64 -M riscv-server-ref (...) \ -chardev socket,id=chrtpm,path=/tmp/mytpm1/swtpm-sock \ -tpmdev emulator,id=tpm0,chardev=chrtpm\ -device tpm-tis-device,tpmdev=tpm0 [1] https://github.com/riscv-non-isa/riscv-server-platform [2] https://qemu-project.gitlab.io/qemu/specs/tpm.html Signed-off-by: Daniel Henrique Barboza <daniel.barboza@oss.qualcomm.com> Reviewed-by: Nutty Liu <nutty.liu@hotmail.com> Reviewed-by: Chao Liu <chao.liu@processmission.com> --- configs/devices/riscv64-softmmu/default.mak | 1 + hw/riscv/Kconfig | 16 + hw/riscv/meson.build | 1 + hw/riscv/server_platform_ref.c | 769 ++++++++++++++++++++ 4 files changed, 787 insertions(+) create mode 100644 hw/riscv/server_platform_ref.c diff --git a/configs/devices/riscv64-softmmu/default.mak b/configs/devices/riscv64-softmmu/default.mak index a8e4d0ab33..ae3f62e2d4 100644 --- a/configs/devices/riscv64-softmmu/default.mak +++ b/configs/devices/riscv64-softmmu/default.mak @@ -9,6 +9,7 @@ # CONFIG_SIFIVE_E=n # CONFIG_SIFIVE_U=n # CONFIG_RISCV_VIRT=n +# CONFIG_RISCV_SERVER_PLATFORM_REF=n # CONFIG_MICROCHIP_PFSOC=n # CONFIG_SHAKTI_C=n # CONFIG_XIANGSHAN_KUNMINGHU=n diff --git a/hw/riscv/Kconfig b/hw/riscv/Kconfig index d06ac26648..da59eb2155 100644 --- a/hw/riscv/Kconfig +++ b/hw/riscv/Kconfig @@ -69,6 +69,22 @@ config RISCV_VIRT select ACPI select ACPI_PCI +config RISCV_SERVER_PLATFORM_REF + bool + default y + depends on RISCV64 + imply TPM_TIS_SYSBUS + select RISCV_NUMA + select GOLDFISH_RTC + select PCI + select PCI_EXPRESS_GENERIC_BRIDGE + select PFLASH_CFI01 + select SERIAL + select RISCV_ACLINT + select RISCV_APLIC + select RISCV_IMSIC + select RISCV_IOMMU + config SHAKTI_C bool default y diff --git a/hw/riscv/meson.build b/hw/riscv/meson.build index 7aa3c1578d..cc5a019f7c 100644 --- a/hw/riscv/meson.build +++ b/hw/riscv/meson.build @@ -7,6 +7,7 @@ riscv_ss.add(when: 'CONFIG_RISCV_NUMA', if_true: files('numa.c')) riscv_ss.add(files('riscv_hart.c')) riscv_ss.add(when: 'CONFIG_OPENTITAN', if_true: files('opentitan.c')) riscv_ss.add(when: 'CONFIG_RISCV_VIRT', if_true: files('virt.c')) +riscv_ss.add(when: 'CONFIG_RISCV_SERVER_PLATFORM_REF', if_true: files('server_platform_ref.c')) riscv_ss.add(when: 'CONFIG_SHAKTI_C', if_true: files('shakti_c.c')) riscv_ss.add(when: 'CONFIG_SIFIVE_E', if_true: files('sifive_e.c')) riscv_ss.add(when: 'CONFIG_SIFIVE_U', if_true: files('sifive_u.c')) diff --git a/hw/riscv/server_platform_ref.c b/hw/riscv/server_platform_ref.c new file mode 100644 index 0000000000..cc74bf06a1 --- /dev/null +++ b/hw/riscv/server_platform_ref.c @@ -0,0 +1,769 @@ +/* + * QEMU RISC-V Server Platform Reference Board (riscv-server-ref) + * + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ + +#include "qemu/osdep.h" +#include "qemu/units.h" +#include "qemu/error-report.h" +#include "qemu/guest-random.h" +#include "qapi/error.h" +#include "qapi/qapi-visit-common.h" +#include "hw/core/boards.h" +#include "hw/core/platform-bus.h" +#include "hw/core/loader.h" +#include "hw/core/sysbus.h" +#include "hw/core/qdev-properties.h" +#include "hw/char/serial.h" +#include "hw/block/flash.h" +#include "hw/ide/pci.h" +#include "hw/ide/ahci-pci.h" +#include "hw/pci/pci.h" +#include "hw/pci-host/gpex.h" +#include "hw/core/sysbus-fdt.h" +#include "hw/riscv/riscv_hart.h" +#include "hw/riscv/boot.h" +#include "hw/riscv/device-common.h" +#include "hw/riscv/fdt-common.h" +#include "hw/riscv/numa.h" +#include "hw/riscv/iommu.h" +#include "hw/riscv/riscv-iommu.h" +#include "hw/riscv/riscv-iommu-bits.h" +#include "hw/intc/riscv_aclint.h" +#include "hw/intc/riscv_aplic.h" +#include "hw/intc/riscv_imsic.h" +#include "chardev/char.h" +#include "hw/char/serial-mm.h" +#include "system/device_tree.h" +#include "system/runstate.h" +#include "system/system.h" +#include "system/kvm.h" +#include "system/tcg.h" +#include "kvm/kvm_riscv.h" +#include "system/tpm.h" +#include "system/qtest.h" +#include "target/riscv/cpu.h" +#include "net/net.h" + +#include "aia.h" + +#define RVSERVER_CPUS_MAX_BITS 9 +#define RVSERVER_CPUS_MAX (1 << RVSERVER_CPUS_MAX_BITS) +#define RVSERVER_SOCKETS_MAX_BITS 2 +#define RVSERVER_SOCKETS_MAX (1 << RVSERVER_SOCKETS_MAX_BITS) + +#define RVSERVER_IRQCHIP_NUM_MSIS 255 +#define RVSERVER_IRQCHIP_NUM_SOURCES 96 +#define RVSERVER_IRQCHIP_NUM_PRIO_BITS 3 +#define RVSERVER_IRQCHIP_MAX_GUESTS_BITS 3 +#define RVSERVER_IRQCHIP_MAX_GUESTS \ + ((1U << RVSERVER_IRQCHIP_MAX_GUESTS_BITS) - 1U) + +#define NUM_SATA_PORTS 6 + +#define SYSCON_RESET 0x1 +#define SYSCON_POWEROFF 0x2 + +#define RVSERVER_PLATFORM_BUS_NUM_IRQS 8 + +#define TYPE_RISCV_SERVER_REF_MACHINE MACHINE_TYPE_NAME("riscv-server-ref") +OBJECT_DECLARE_SIMPLE_TYPE(RISCVServerRefMachineState, RISCV_SERVER_REF_MACHINE) + +struct RISCVServerRefMachineState { + /*< private >*/ + MachineState parent; + + /*< public >*/ + Notifier machine_done; + RISCVHartArrayState soc[RVSERVER_SOCKETS_MAX]; + DeviceState *irqchip[RVSERVER_SOCKETS_MAX]; + PFlashCFI01 *flash[2]; + + int fdt_size; + int aia_guests; + const MemMapEntry *memmap; + + DeviceState *platform_bus_dev; +}; + +enum { + RVSERVER_DEBUG, + RVSERVER_MROM, + RVSERVER_RESET_SYSCON, + RVSERVER_RTC, + RVSERVER_IOMMU_SYS, + RVSERVER_ACLINT, + RVSERVER_APLIC_M, + RVSERVER_APLIC_S, + RVSERVER_UART0, + RVSERVER_IMSIC_M, + RVSERVER_IMSIC_S, + RVSERVER_FLASH, + RVSERVER_DRAM, + RVSERVER_PCIE_MMIO, + RVSERVER_PCIE_PIO, + RVSERVER_PLATFORM_BUS, + RVSERVER_PCIE_ECAM, + RVSERVER_PCIE_MMIO_HIGH +}; + +enum { + RVSERVER_UART0_IRQ = 10, + RVSERVER_RTC_IRQ = 11, + RVSERVER_PCIE_IRQ = 32, /* 32 to 35 */ + IOMMU_SYS_IRQ = 36, /* 36 to 39 */ + RVSERVER_PLATFORM_BUS_IRQ = 40, /* 40 to 48 */ +}; + +/* + * The server soc reference machine physical address space used by some of the + * devices namely ACLINT, APLIC and IMSIC depend on number of Sockets, number + * of CPUs, and number of IMSIC guest files. + * + * Various limits defined by RVSERVER_SOCKETS_MAX_BITS, RVSERVER_CPUS_MAX_BITS, + * and RVSERVER_IRQCHIP_MAX_GUESTS_BITS are tuned for maximum utilization of + * server reference machine physical address space. + */ + +#define RVSERVER_IMSIC_GROUP_MAX_SIZE (1U << IMSIC_MMIO_GROUP_MIN_SHIFT) +#if RVSERVER_IMSIC_GROUP_MAX_SIZE < \ + IMSIC_GROUP_SIZE(RVSERVER_CPUS_MAX_BITS, RVSERVER_IRQCHIP_MAX_GUESTS_BITS) +#error "Can't accomodate single IMSIC group in address space" +#endif + +#define RVSERVER_IMSIC_MAX_SIZE (RVSERVER_SOCKETS_MAX * \ + RVSERVER_IMSIC_GROUP_MAX_SIZE) +#if 0x4000000 < RVSERVER_IMSIC_MAX_SIZE +#error "Can't accomodate all IMSIC groups in address space" +#endif + +static const MemMapEntry rvserver_ref_memmap[] = { + [RVSERVER_DEBUG] = { 0x0, 0x100 }, + [RVSERVER_MROM] = { 0x1000, 0xf000 }, + [RVSERVER_RESET_SYSCON] = { 0x100000, 0x1000 }, + [RVSERVER_RTC] = { 0x101000, 0x1000 }, + [RVSERVER_IOMMU_SYS] = { 0x102000, 0x1000 }, + [RVSERVER_ACLINT] = { 0x2000000, 0x10000 }, + [RVSERVER_PCIE_PIO] = { 0x3000000, 0x10000 }, + [RVSERVER_PLATFORM_BUS] = { 0x4000000, 0x2000000 }, + [RVSERVER_APLIC_M] = { 0xc000000, APLIC_SIZE(RVSERVER_CPUS_MAX) }, + [RVSERVER_APLIC_S] = { 0xd000000, APLIC_SIZE(RVSERVER_CPUS_MAX) }, + [RVSERVER_UART0] = { 0x10000000, 0x100 }, + [RVSERVER_FLASH] = { 0x20000000, 0x4000000 }, + [RVSERVER_IMSIC_M] = { 0x24000000, RVSERVER_IMSIC_MAX_SIZE }, + [RVSERVER_IMSIC_S] = { 0x28000000, RVSERVER_IMSIC_MAX_SIZE }, + [RVSERVER_PCIE_ECAM] = { 0x30000000, 0x10000000 }, + [RVSERVER_PCIE_MMIO] = { 0x40000000, 0x40000000 }, + [RVSERVER_DRAM] = { 0x80000000, 0xff80000000ull }, + [RVSERVER_PCIE_MMIO_HIGH] = { 0x10000000000ull, 0x10000000000ull }, +}; + +#define RVSERVER_FLASH_SECTOR_SIZE (256 * KiB) + +static void rvserver_flash_maps(RISCVServerRefMachineState *s, + MemoryRegion *sysmem) +{ + hwaddr flashsize = rvserver_ref_memmap[RVSERVER_FLASH].size / 2; + hwaddr flashbase = rvserver_ref_memmap[RVSERVER_FLASH].base; + + riscv_init_flash_map(s->flash[0], flashbase, flashsize, + sysmem, RVSERVER_FLASH_SECTOR_SIZE); + riscv_init_flash_map(s->flash[1], flashbase + flashsize, flashsize, + sysmem, RVSERVER_FLASH_SECTOR_SIZE); +} + +static void create_fdt_pmu(RISCVServerRefMachineState *s) +{ + g_autofree char *pmu_name = g_strdup_printf("/pmu"); + MachineState *ms = MACHINE(s); + RISCVCPU *hart = &s->soc[0].harts[0]; + + qemu_fdt_add_subnode(ms->fdt, pmu_name); + qemu_fdt_setprop_string(ms->fdt, pmu_name, "compatible", "riscv,pmu"); + riscv_pmu_generate_fdt_node(ms->fdt, hart->pmu_avail_ctrs, pmu_name); +} + +static void create_fdt_sockets(RISCVServerRefMachineState *s, + const MemMapEntry *memmap, + uint32_t *phandle, + uint32_t *irq_mmio_phandle, + uint32_t *irq_pcie_phandle, + uint32_t *msi_pcie_phandle) +{ + int socket, phandle_pos; + MachineState *ms = MACHINE(s); + uint32_t msi_m_phandle = 0, msi_s_phandle = 0; + uint32_t xplic_phandles[MAX_NODES]; + g_autofree uint32_t *intc_phandles = NULL; + int socket_count = riscv_socket_count(ms); + bool numa_enabled = riscv_numa_enabled(ms); + bool is_32_bit = riscv_is_32bit(&s->soc[0]); + IMSICFdtProps imsic_fdt_props; + APLICFdtProps aplic_fdt_props; + ACLINTFdtProps aclint_props; + + riscv_fdt_create_cpu_socket_subnode(ms->fdt, + kvm_enabled() ? kvm_riscv_get_timebase_frequency(&s->soc->harts[0]) + : RISCV_ACLINT_DEFAULT_TIMEBASE_FREQ); + + intc_phandles = g_new0(uint32_t, ms->smp.cpus); + + aclint_props.clint = &memmap[RVSERVER_ACLINT]; + aclint_props.aia_type = AIA_TYPE_APLIC_IMSIC; + aclint_props.numa_enabled = numa_enabled; + + phandle_pos = ms->smp.cpus; + for (socket = (socket_count - 1); socket >= 0; socket--) { + hwaddr memaddr = s->memmap[RVSERVER_DRAM].base + + riscv_socket_mem_offset(ms, socket); + uint64_t memsize = riscv_socket_mem_size(ms, socket); + + phandle_pos -= s->soc[socket].num_harts; + + riscv_create_fdt_socket_cpus(ms->fdt, (&s->soc[socket])->harts, socket, + s->soc[socket].num_harts, + s->soc[socket].hartid_base, + phandle, &intc_phandles[phandle_pos], + numa_enabled, is_32_bit); + + riscv_create_fdt_socket_memory(ms->fdt, memaddr, memsize, + socket, riscv_numa_enabled(ms)); + + aclint_props.socket = socket; + aclint_props.num_harts = s->soc[socket].num_harts; + riscv_create_fdt_socket_aclint(ms->fdt, &aclint_props, + &intc_phandles[phandle_pos]); + } + + imsic_fdt_props.soc = &s->soc; + imsic_fdt_props.socket_count = socket_count; + imsic_fdt_props.smp_cpus = ms->smp.cpus; + imsic_fdt_props.imsic_m_base = memmap[RVSERVER_IMSIC_M].base; + imsic_fdt_props.imsic_s_base = memmap[RVSERVER_IMSIC_S].base; + imsic_fdt_props.imsic_group_max_size = RVSERVER_IMSIC_GROUP_MAX_SIZE; + imsic_fdt_props.irqchip_num_msis = RVSERVER_IRQCHIP_NUM_MSIS; + imsic_fdt_props.aia_guests = s->aia_guests; + + riscv_create_fdt_imsic(ms->fdt, &imsic_fdt_props, phandle, intc_phandles, + &msi_m_phandle, &msi_s_phandle); + *msi_pcie_phandle = msi_s_phandle; + + aplic_fdt_props.aplic_m = !kvm_enabled() + ? &memmap[RVSERVER_APLIC_M] : NULL; + aplic_fdt_props.aplic_s = &memmap[RVSERVER_APLIC_S]; + aplic_fdt_props.platform_bus = &memmap[RVSERVER_PLATFORM_BUS]; + aplic_fdt_props.platform_bus_irq = RVSERVER_PLATFORM_BUS_IRQ; + aplic_fdt_props.num_harts = ms->smp.cpus; + aplic_fdt_props.numa_enabled = numa_enabled; + aplic_fdt_props.irqchip_num_sources = RVSERVER_IRQCHIP_NUM_SOURCES; + aplic_fdt_props.aia_type = AIA_TYPE_APLIC_IMSIC; + + phandle_pos = ms->smp.cpus; + for (socket = (socket_count - 1); socket >= 0; socket--) { + phandle_pos -= s->soc[socket].num_harts; + + aplic_fdt_props.socket = socket; + aplic_fdt_props.num_harts = s->soc[socket].num_harts; + riscv_create_fdt_socket_aplic(ms->fdt, &aplic_fdt_props, + msi_m_phandle, msi_s_phandle, phandle, + &intc_phandles[phandle_pos], + xplic_phandles); + } + + for (socket = 0; socket < socket_count; socket++) { + if (socket == 0) { + *irq_mmio_phandle = xplic_phandles[socket]; + *irq_pcie_phandle = xplic_phandles[socket]; + } + if (socket == 1) { + *irq_pcie_phandle = xplic_phandles[socket]; + } + } + + riscv_socket_fdt_write_distance_matrix(ms); +} + +static void finalize_fdt(RISCVServerRefMachineState *s) +{ + uint32_t phandle = 1, irq_mmio_phandle = 1, msi_pcie_phandle = 1; + uint32_t irq_pcie_phandle = 1, iommu_sys_phandle; + g_autofree char *name = NULL; + MachineState *ms = MACHINE(s); + + create_fdt_sockets(s, rvserver_ref_memmap, &phandle, &irq_mmio_phandle, + &irq_pcie_phandle, &msi_pcie_phandle); + + iommu_sys_phandle = riscv_create_fdt_riscv_iommu_sys(ms->fdt, + s->memmap[RVSERVER_IOMMU_SYS].base, + s->memmap[RVSERVER_IOMMU_SYS].size, + &phandle, irq_mmio_phandle, + msi_pcie_phandle, IOMMU_SYS_IRQ); + + riscv_create_fdt_pcie(ms->fdt, AIA_TYPE_APLIC_IMSIC, true, + &s->memmap[RVSERVER_PCIE_ECAM], + &s->memmap[RVSERVER_PCIE_PIO], + &s->memmap[RVSERVER_PCIE_MMIO], + &s->memmap[RVSERVER_PCIE_MMIO_HIGH], + irq_pcie_phandle, msi_pcie_phandle, + iommu_sys_phandle, RVSERVER_PCIE_IRQ); + + riscv_create_fdt_syscon(ms->fdt, &phandle, + rvserver_ref_memmap[RVSERVER_RESET_SYSCON].base, + rvserver_ref_memmap[RVSERVER_RESET_SYSCON].size, + SYSCON_RESET, SYSCON_POWEROFF, false); + + riscv_create_fdt_uart(ms->fdt, &rvserver_ref_memmap[RVSERVER_UART0], + RVSERVER_UART0_IRQ, AIA_TYPE_APLIC_IMSIC, + irq_mmio_phandle); + name = riscv_fdt_get_uart_nodename(rvserver_ref_memmap[RVSERVER_UART0].base); + qemu_fdt_setprop_string(ms->fdt, "/chosen", "stdout-path", name); + qemu_fdt_setprop_string(ms->fdt, "/aliases", "serial0", name); + + riscv_create_fdt_rtc(ms->fdt, &rvserver_ref_memmap[RVSERVER_RTC], + RVSERVER_RTC_IRQ, AIA_TYPE_APLIC_IMSIC, + irq_mmio_phandle); +} + +static void create_fdt(RISCVServerRefMachineState *s, + const MemMapEntry *memmap) +{ + MachineState *ms = MACHINE(s); + uint8_t rng_seed[32]; + g_autofree char *name = NULL; + + ms->fdt = riscv_create_board_device_tree(MACHINE_GET_CLASS(s)->desc, + "qemu,riscv-server-ref", + &s->fdt_size); + + /* + * This versioning scheme is for informing platform fw only. It is neither: + * - A QEMU versioned machine type; a given version of QEMU will emulate + * a given version of the platform. + * - A reflection of level of server platform support provided. + * + * machine-version-major: updated when changes breaking fw compatibility + * are introduced. + * machine-version-minor: updated when features are added that don't break + * fw compatibility. + * + * It's the same as the scheme in arm sbsa-ref. + */ + qemu_fdt_setprop_cell(ms->fdt, "/", "machine-version-major", 0); + qemu_fdt_setprop_cell(ms->fdt, "/", "machine-version-minor", 0); + + /* + * The "/soc/pci@..." node is needed for PCIE hotplugs + * that might happen before finalize_fdt(). + */ + name = g_strdup_printf("/soc/pci@%"HWADDR_PRIx, + s->memmap[RVSERVER_PCIE_ECAM].base); + qemu_fdt_add_subnode(ms->fdt, name); + + qemu_fdt_add_subnode(ms->fdt, "/chosen"); + qemu_fdt_add_subnode(ms->fdt, "/aliases"); + + /* Pass seed to RNG */ + qemu_guest_getrandom_nofail(rng_seed, sizeof(rng_seed)); + qemu_fdt_setprop(ms->fdt, "/chosen", "rng-seed", + rng_seed, sizeof(rng_seed)); + + riscv_create_fdt_flash(ms->fdt, rvserver_ref_memmap[RVSERVER_FLASH].base, + rvserver_ref_memmap[RVSERVER_FLASH].size / 2); + create_fdt_pmu(s); + +} + +static void rvserver_init_pci_devices(RISCVServerRefMachineState *s, + DeviceState *gpex_host) +{ + MachineClass *mc = MACHINE_GET_CLASS(s); + PCIHostState *pci = PCI_HOST_BRIDGE(gpex_host); + PCIDevice *pdev_ahci; + AHCIPCIState *ich9; + DriveInfo *hd[NUM_SATA_PORTS]; + + pci_init_nic_devices(pci->bus, mc->default_nic); + + /* IDE disk setup. */ + pdev_ahci = pci_create_simple(pci->bus, -1, TYPE_ICH9_AHCI); + ich9 = ICH9_AHCI(pdev_ahci); + g_assert(ARRAY_SIZE(hd) == ich9->ahci.ports); + ide_drive_get(hd, ich9->ahci.ports); + ahci_ide_create_devs(&ich9->ahci, hd); +} + +static uint64_t rvserver_reset_syscon_read(void *opaque, hwaddr addr, + unsigned size) +{ + return 0; +} + +static void rvserver_reset_syscon_write(void *opaque, hwaddr addr, + uint64_t val64, unsigned int size) +{ + switch (val64) { + case SYSCON_POWEROFF: + qemu_system_shutdown_request(SHUTDOWN_CAUSE_GUEST_SHUTDOWN); + return; + case SYSCON_RESET: + qemu_system_reset_request(SHUTDOWN_CAUSE_GUEST_RESET); + return; + default: + break; + } +} + +static const MemoryRegionOps rvserver_reset_syscon_ops = { + .read = rvserver_reset_syscon_read, + .write = rvserver_reset_syscon_write, + .endianness = DEVICE_LITTLE_ENDIAN +}; + +static void rvserver_ref_machine_done(Notifier *notifier, void *data) +{ + RISCVServerRefMachineState *s = container_of( + notifier, RISCVServerRefMachineState, machine_done); + const MemMapEntry *memmap = rvserver_ref_memmap; + MachineState *machine = MACHINE(s); + hwaddr start_addr = memmap[RVSERVER_DRAM].base; + target_ulong firmware_end_addr, kernel_start_addr; + const char *firmware_name = riscv_default_firmware_name(&s->soc[0]); + uint64_t fdt_load_addr; + uint64_t kernel_entry = 0; + BlockBackend *pflash_blk0; + RISCVBootInfo boot_info; + + /* + * An user provided dtb must include everything, including + * dynamic sysbus devices. Our FDT needs to be finalized. + */ + if (machine->dtb == NULL) { + finalize_fdt(s); + } + + riscv_boot_info_init(&boot_info, &s->soc[0]); + + firmware_end_addr = riscv_find_and_load_firmware(machine, &boot_info, + firmware_name, + &start_addr, NULL); + + pflash_blk0 = pflash_cfi01_get_blk(s->flash[0]); + if (pflash_blk0) { + if (machine->firmware && !strcmp(machine->firmware, "none")) { + /* + * Pflash was supplied but bios is none and not KVM guest, + * let's overwrite the address we jump to after reset to + * the base of the flash. + */ + start_addr = rvserver_ref_memmap[RVSERVER_FLASH].base; + } else { + /* + * Pflash was supplied but either KVM guest or bios is not none. + * In this case, base of the flash would contain S-mode payload. + */ + riscv_setup_firmware_boot(machine); + kernel_entry = rvserver_ref_memmap[RVSERVER_FLASH].base; + } + } + + if (machine->kernel_filename && !kernel_entry) { + kernel_start_addr = riscv_calc_kernel_start_addr(&boot_info, + firmware_end_addr); + riscv_load_kernel(machine, &boot_info, kernel_start_addr, true, NULL); + kernel_entry = boot_info.image_low_addr; + } + + fdt_load_addr = riscv_compute_fdt_addr(memmap[RVSERVER_DRAM].base, + memmap[RVSERVER_DRAM].size, + machine, &boot_info); + + riscv_load_fdt(fdt_load_addr, machine->fdt); + + /* load the reset vector */ + riscv_setup_rom_reset_vec(machine, &s->soc[0], start_addr, + rvserver_ref_memmap[RVSERVER_MROM].base, + rvserver_ref_memmap[RVSERVER_MROM].size, + kernel_entry, + fdt_load_addr); + +} + +static bool rvserver_aclint_allowed(void) +{ + return tcg_enabled() || qtest_enabled(); +} + +static void rvserver_ref_machine_init(MachineState *machine) +{ + const MemMapEntry *memmap = rvserver_ref_memmap; + RISCVServerRefMachineState *s = RISCV_SERVER_REF_MACHINE(machine); + MemoryRegion *system_memory = get_system_memory(); + MemoryRegion *mask_rom = g_new(MemoryRegion, 1); + MemoryRegion *reset_syscon_io = g_new(MemoryRegion, 1); + DeviceState *mmio_irqchip, *pcie_irqchip, *gpex_host; + int i, base_hartid, hart_count; + int socket_count = riscv_socket_count(machine); + int imsic_bits = imsic_num_bits(s->aia_guests + 1); + + /* Check socket count limit */ + if (RVSERVER_SOCKETS_MAX < socket_count) { + error_report("number of sockets/nodes should be less than %d", + RVSERVER_SOCKETS_MAX); + exit(1); + } + + if (!rvserver_aclint_allowed()) { + error_report("'aclint' is only available with TCG acceleration"); + exit(1); + } + + s->memmap = rvserver_ref_memmap; + + /* Initialize sockets */ + mmio_irqchip = pcie_irqchip = NULL; + for (i = 0; i < socket_count; i++) { + g_autofree char *soc_name = g_strdup_printf("soc%d", i); + + if (!riscv_socket_check_hartids(machine, i)) { + error_report("discontinuous hartids in socket%d", i); + exit(1); + } + + base_hartid = riscv_socket_first_hartid(machine, i); + if (base_hartid < 0) { + error_report("can't find hartid base for socket%d", i); + exit(1); + } + + hart_count = riscv_socket_hart_count(machine, i); + if (hart_count < 0) { + error_report("can't find hart count for socket%d", i); + exit(1); + } + + object_initialize_child(OBJECT(machine), soc_name, &s->soc[i], + TYPE_RISCV_HART_ARRAY); + object_property_set_str(OBJECT(&s->soc[i]), "cpu-type", + machine->cpu_type, &error_abort); + object_property_set_int(OBJECT(&s->soc[i]), "hartid-base", + base_hartid, &error_abort); + object_property_set_int(OBJECT(&s->soc[i]), "num-harts", + hart_count, &error_abort); + sysbus_realize(SYS_BUS_DEVICE(&s->soc[i]), &error_fatal); + + /* Per-socket ACLINT MTIMER */ + riscv_aclint_mtimer_create(system_memory, + memmap[RVSERVER_ACLINT].base + i * RISCV_ACLINT_DEFAULT_MTIMER_SIZE, + RISCV_ACLINT_DEFAULT_MTIMER_SIZE, + base_hartid, hart_count, + RISCV_ACLINT_DEFAULT_MTIMECMP, + RISCV_ACLINT_DEFAULT_MTIME, + RISCV_ACLINT_DEFAULT_TIMEBASE_FREQ, true); + + /* Per-socket interrupt controller */ + s->irqchip[i] = riscv_create_aia(system_memory, true, s->aia_guests, + IMSIC_HART_SIZE(0), + IMSIC_HART_SIZE(imsic_bits), + RVSERVER_IRQCHIP_NUM_SOURCES, + &s->memmap[RVSERVER_APLIC_M], + &s->memmap[RVSERVER_APLIC_S], + &s->memmap[RVSERVER_IMSIC_M], + &s->memmap[RVSERVER_IMSIC_S], + i, base_hartid, hart_count, + RVSERVER_IRQCHIP_NUM_MSIS, + RVSERVER_IRQCHIP_NUM_PRIO_BITS); + + /* Try to use different IRQCHIP instance based device type */ + if (i == 0) { + mmio_irqchip = s->irqchip[i]; + pcie_irqchip = s->irqchip[i]; + } + if (i == 1) { + pcie_irqchip = s->irqchip[i]; + } + } + + /* register system main memory (actual RAM) */ + memory_region_add_subregion(system_memory, memmap[RVSERVER_DRAM].base, + machine->ram); + + /* boot rom */ + memory_region_init_rom(mask_rom, NULL, "riscv_rvserver_ref_board.mrom", + memmap[RVSERVER_MROM].size, &error_fatal); + memory_region_add_subregion(system_memory, memmap[RVSERVER_MROM].base, + mask_rom); + + memory_region_init_io(reset_syscon_io, NULL, &rvserver_reset_syscon_ops, + NULL, "reset_syscon_io", + memmap[RVSERVER_RESET_SYSCON].size); + memory_region_add_subregion(system_memory, + memmap[RVSERVER_RESET_SYSCON].base, + reset_syscon_io); + + gpex_host = riscv_gpex_pcie_init(system_memory, pcie_irqchip, + &rvserver_ref_memmap[RVSERVER_PCIE_ECAM], + &rvserver_ref_memmap[RVSERVER_PCIE_MMIO], + &rvserver_ref_memmap[RVSERVER_PCIE_MMIO_HIGH], + &rvserver_ref_memmap[RVSERVER_PCIE_PIO], + RVSERVER_PCIE_IRQ); + + /* Init nic devices and ICH9 AHCI */ + rvserver_init_pci_devices(s, gpex_host); + + s->platform_bus_dev = riscv_create_platform_bus(mmio_irqchip, + &s->memmap[RVSERVER_PLATFORM_BUS], + RVSERVER_PLATFORM_BUS_IRQ, + RVSERVER_PLATFORM_BUS_NUM_IRQS); + + serial_mm_init(system_memory, memmap[RVSERVER_UART0].base, + 0, qdev_get_gpio_in(mmio_irqchip, RVSERVER_UART0_IRQ), 399193, + serial_hd(0), DEVICE_LITTLE_ENDIAN); + + sysbus_create_simple("goldfish_rtc", memmap[RVSERVER_RTC].base, + qdev_get_gpio_in(mmio_irqchip, RVSERVER_RTC_IRQ)); + + for (i = 0; i < ARRAY_SIZE(s->flash); i++) { + /* Map legacy -drive if=pflash to machine properties */ + pflash_cfi01_legacy_drive(s->flash[i], + drive_get(IF_PFLASH, 0, i)); + } + rvserver_flash_maps(s, system_memory); + + /* load/create device tree */ + if (machine->dtb) { + machine->fdt = load_device_tree(machine->dtb, &s->fdt_size); + if (!machine->fdt) { + error_report("load_device_tree() failed"); + exit(1); + } + } else { + create_fdt(s, memmap); + } + + riscv_create_iommu_sys(mmio_irqchip, s->memmap[RVSERVER_IOMMU_SYS].base, + IOMMU_SYS_IRQ, false); + + s->machine_done.notify = rvserver_ref_machine_done; + qemu_add_machine_init_done_notifier(&s->machine_done); +} + +static void rvserver_ref_machine_instance_init(Object *obj) +{ + RISCVServerRefMachineState *s = RISCV_SERVER_REF_MACHINE(obj); + + s->flash[0] = riscv_flash_create(OBJECT(s), "riscv-server-ref.flash0", + "pflash0", RVSERVER_FLASH_SECTOR_SIZE); + s->flash[1] = riscv_flash_create(OBJECT(s), "riscv-server-ref.flash1", + "pflash1", RVSERVER_FLASH_SECTOR_SIZE); +} + +static char *rvserver_ref_get_aia_guests(Object *obj, Error **errp) +{ + RISCVServerRefMachineState *s = RISCV_SERVER_REF_MACHINE(obj); + char val[32]; + + sprintf(val, "%d", s->aia_guests); + return g_strdup(val); +} + +static void rvserver_ref_set_aia_guests(Object *obj, const char *val, + Error **errp) +{ + RISCVServerRefMachineState *s = RISCV_SERVER_REF_MACHINE(obj); + + s->aia_guests = atoi(val); + if (s->aia_guests < 0 || s->aia_guests > RVSERVER_IRQCHIP_MAX_GUESTS) { + error_setg(errp, "Invalid number of AIA IMSIC guests"); + error_append_hint(errp, "Valid values be between 0 and %d.\n", + RVSERVER_IRQCHIP_MAX_GUESTS); + } +} + +static HotplugHandler *rvserver_machine_get_hotplug_handler(MachineState *ms, + DeviceState *dev) +{ + MachineClass *mc = MACHINE_GET_CLASS(ms); + + if (device_is_dynamic_sysbus(mc, dev)) { + return HOTPLUG_HANDLER(ms); + } + + return NULL; +} + +static void rvserver_machine_device_plug_cb(HotplugHandler *hotplug_dev, + DeviceState *dev, Error **errp) +{ + RISCVServerRefMachineState *s = RISCV_SERVER_REF_MACHINE(hotplug_dev); + + if (s->platform_bus_dev) { + MachineClass *mc = MACHINE_GET_CLASS(s); + + if (device_is_dynamic_sysbus(mc, dev)) { + platform_bus_link_device(PLATFORM_BUS_DEVICE(s->platform_bus_dev), + SYS_BUS_DEVICE(dev)); + } + } +} + +static void rvserver_ref_machine_class_init(ObjectClass *oc, const void *data) +{ + char str[128]; + MachineClass *mc = MACHINE_CLASS(oc); + HotplugHandlerClass *hc = HOTPLUG_HANDLER_CLASS(oc); + static const char * const valid_cpu_types[] = { + TYPE_RISCV_CPU_RVSERVER_REF, + }; + + /* Note: this is used as /model in the FDT. */ + mc->desc = "RISC-V Server Platform Reference Board v1.0"; + mc->init = rvserver_ref_machine_init; + mc->max_cpus = RVSERVER_CPUS_MAX; + mc->default_cpu_type = TYPE_RISCV_CPU_RVSERVER_REF; + mc->valid_cpu_types = valid_cpu_types; + mc->pci_allow_0_address = true; + mc->default_nic = "e1000e"; + mc->possible_cpu_arch_ids = riscv_numa_possible_cpu_arch_ids; + mc->cpu_index_to_instance_props = riscv_numa_cpu_index_to_props; + mc->get_default_cpu_node_id = riscv_numa_get_default_cpu_node_id; + mc->numa_mem_supported = true; + /* platform instead of architectural choice */ + mc->cpu_cluster_has_numa_boundary = true; + mc->default_ram_id = "riscv_rvserver_ref_board.ram"; + + object_class_property_add_str(oc, "aia-guests", + rvserver_ref_get_aia_guests, + rvserver_ref_set_aia_guests); + sprintf(str, "Set number of guest MMIO pages for AIA IMSIC. Valid value " + "should be between 0 and %d.", RVSERVER_IRQCHIP_MAX_GUESTS); + object_class_property_set_description(oc, "aia-guests", str); + + assert(!mc->get_hotplug_handler); + mc->get_hotplug_handler = rvserver_machine_get_hotplug_handler; + hc->plug = rvserver_machine_device_plug_cb; +#ifdef CONFIG_TPM + machine_class_allow_dynamic_sysbus_dev(mc, TYPE_TPM_TIS_SYSBUS); +#endif +} + +static const TypeInfo rvserver_ref_typeinfo = { + .name = TYPE_RISCV_SERVER_REF_MACHINE, + .parent = TYPE_MACHINE, + .class_init = rvserver_ref_machine_class_init, + .instance_init = rvserver_ref_machine_instance_init, + .instance_size = sizeof(RISCVServerRefMachineState), + .interfaces = (const InterfaceInfo[]) { + { TYPE_HOTPLUG_HANDLER }, + { } + }, +}; + +static void rvserver_ref_init_register_types(void) +{ + type_register_static(&rvserver_ref_typeinfo); +} + +type_init(rvserver_ref_init_register_types) -- 2.43.0 ^ permalink raw reply related [flat|nested] 19+ messages in thread
* Re: [PATCH v10 3/5] hw/riscv: server platform reference machine 2026-09-04 19:56 ` [PATCH v10 3/5] hw/riscv: server platform reference machine Daniel Henrique Barboza @ 2026-09-08 3:25 ` Sunil V L 2026-09-08 10:40 ` Andrew Jones 1 sibling, 0 replies; 19+ messages in thread From: Sunil V L @ 2026-09-08 3:25 UTC (permalink / raw) To: Daniel Henrique Barboza Cc: qemu-devel, qemu-riscv, alistair.francis, liwei1518, zhiwei_liu, chao.liu, andrew.jones, leif.lindholm, Nutty Liu, Paolo Bonzini, Palmer Dabbelt On Sat, Sep 5, 2026 at 1:27 AM Daniel Henrique Barboza <daniel.barboza@oss.qualcomm.com> wrote: > > The RISC-V Server Platform specification [1] defines a standardized set > of hardware and software capabilities, that portable system software, > such as OS and hypervisors can rely on being present in a RISC-V server > platform. > > The main features included in this emulation are: > > - Based on riscv virt machine type; > - A new memory map as close as virt machine as possible; > - An always present IOMMU platform device (riscv-iommu-sys) that uses > IRQs 36 to 39, one IRQ for queue, similar to the 'virt' board; > - AIA; > - PCIe AHCI; > - PCIe NIC; > - No virtio device; > - No fw_cfg device; > - No ACPI table provided; > - Only minimal device tree nodes; > - a platform bus for TPM support. > > A note about TPM support: TPM devices in QEMU comes usually in two > flavors - emulated or passthrough. A passthrough device requires a host > TPM device that the QEMU process can borrow and it's usually coupled > with KVM acceleration. > > To use the TPM emulator we'll need help from an external TPM emulator > called swtpm. More info can be found in [2]. For our purposes this is > a process that, if running Ubuntu, can be installed via 'swtpm' package. > We'll go back to it shortly. > > For now, adding support for the emulated TPM device 'tpm-tis' (other TPM > flavors might work as well, 'tpm-tis' is the one tested with this work) > requires a platform bus. Adding a platform bus will open the door for > more devices to be added in the board. This is ok - a reference board > isn't a restricted board and users are free to add devices at their > leisure. > > Here's how to use tpm-tis with the riscv-server-ref board: > > - in a separated shell/term run 'swtpm' (--log is optional): > > $ mkdir /tmp/mytpm1 > $ swtpm socket --tpmstate dir=/tmp/mytpm1 \ > --ctrl type=unixio,path=/tmp/mytpm1/swtpm-sock \ > --tpm2 \ > --log level=20 > > Then start QEMU with: > > $ qemu-system-riscv64 -M riscv-server-ref (...) \ > -chardev socket,id=chrtpm,path=/tmp/mytpm1/swtpm-sock \ > -tpmdev emulator,id=tpm0,chardev=chrtpm\ > -device tpm-tis-device,tpmdev=tpm0 > > [1] https://github.com/riscv-non-isa/riscv-server-platform > [2] https://qemu-project.gitlab.io/qemu/specs/tpm.html > > Signed-off-by: Daniel Henrique Barboza <daniel.barboza@oss.qualcomm.com> > Reviewed-by: Nutty Liu <nutty.liu@hotmail.com> > Reviewed-by: Chao Liu <chao.liu@processmission.com> > --- > configs/devices/riscv64-softmmu/default.mak | 1 + > hw/riscv/Kconfig | 16 + > hw/riscv/meson.build | 1 + > hw/riscv/server_platform_ref.c | 769 ++++++++++++++++++++ > 4 files changed, 787 insertions(+) > create mode 100644 hw/riscv/server_platform_ref.c > LGTM. Reviewed-by: Sunil V L <sunilvl@oss.qualcomm.com> ^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: [PATCH v10 3/5] hw/riscv: server platform reference machine 2026-09-04 19:56 ` [PATCH v10 3/5] hw/riscv: server platform reference machine Daniel Henrique Barboza 2026-09-08 3:25 ` Sunil V L @ 2026-09-08 10:40 ` Andrew Jones 2026-09-08 18:44 ` Daniel Henrique Barboza 1 sibling, 1 reply; 19+ messages in thread From: Andrew Jones @ 2026-09-08 10:40 UTC (permalink / raw) To: Daniel Henrique Barboza Cc: qemu-devel, qemu-riscv, alistair.francis, liwei1518, zhiwei_liu, chao.liu, leif.lindholm, Nutty Liu, Paolo Bonzini, Palmer Dabbelt On Fri, Sep 04, 2026 at 04:56:08PM -0300, Daniel Henrique Barboza wrote: > The RISC-V Server Platform specification [1] defines a standardized set > of hardware and software capabilities, that portable system software, > such as OS and hypervisors can rely on being present in a RISC-V server > platform. > > The main features included in this emulation are: > > - Based on riscv virt machine type; > - A new memory map as close as virt machine as possible; > - An always present IOMMU platform device (riscv-iommu-sys) that uses > IRQs 36 to 39, one IRQ for queue, similar to the 'virt' board; > - AIA; > - PCIe AHCI; > - PCIe NIC; > - No virtio device; > - No fw_cfg device; > - No ACPI table provided; > - Only minimal device tree nodes; > - a platform bus for TPM support. > > A note about TPM support: TPM devices in QEMU comes usually in two > flavors - emulated or passthrough. A passthrough device requires a host > TPM device that the QEMU process can borrow and it's usually coupled > with KVM acceleration. > > To use the TPM emulator we'll need help from an external TPM emulator > called swtpm. More info can be found in [2]. For our purposes this is > a process that, if running Ubuntu, can be installed via 'swtpm' package. > We'll go back to it shortly. > > For now, adding support for the emulated TPM device 'tpm-tis' (other TPM > flavors might work as well, 'tpm-tis' is the one tested with this work) > requires a platform bus. Adding a platform bus will open the door for > more devices to be added in the board. This is ok - a reference board > isn't a restricted board and users are free to add devices at their > leisure. > > Here's how to use tpm-tis with the riscv-server-ref board: > > - in a separated shell/term run 'swtpm' (--log is optional): > > $ mkdir /tmp/mytpm1 > $ swtpm socket --tpmstate dir=/tmp/mytpm1 \ > --ctrl type=unixio,path=/tmp/mytpm1/swtpm-sock \ > --tpm2 \ > --log level=20 > > Then start QEMU with: > > $ qemu-system-riscv64 -M riscv-server-ref (...) \ > -chardev socket,id=chrtpm,path=/tmp/mytpm1/swtpm-sock \ > -tpmdev emulator,id=tpm0,chardev=chrtpm\ > -device tpm-tis-device,tpmdev=tpm0 > > [1] https://github.com/riscv-non-isa/riscv-server-platform > [2] https://qemu-project.gitlab.io/qemu/specs/tpm.html > > Signed-off-by: Daniel Henrique Barboza <daniel.barboza@oss.qualcomm.com> > Reviewed-by: Nutty Liu <nutty.liu@hotmail.com> > Reviewed-by: Chao Liu <chao.liu@processmission.com> > --- > configs/devices/riscv64-softmmu/default.mak | 1 + > hw/riscv/Kconfig | 16 + > hw/riscv/meson.build | 1 + > hw/riscv/server_platform_ref.c | 769 ++++++++++++++++++++ > 4 files changed, 787 insertions(+) > create mode 100644 hw/riscv/server_platform_ref.c > > diff --git a/configs/devices/riscv64-softmmu/default.mak b/configs/devices/riscv64-softmmu/default.mak > index a8e4d0ab33..ae3f62e2d4 100644 > --- a/configs/devices/riscv64-softmmu/default.mak > +++ b/configs/devices/riscv64-softmmu/default.mak > @@ -9,6 +9,7 @@ > # CONFIG_SIFIVE_E=n > # CONFIG_SIFIVE_U=n > # CONFIG_RISCV_VIRT=n > +# CONFIG_RISCV_SERVER_PLATFORM_REF=n > # CONFIG_MICROCHIP_PFSOC=n > # CONFIG_SHAKTI_C=n > # CONFIG_XIANGSHAN_KUNMINGHU=n > diff --git a/hw/riscv/Kconfig b/hw/riscv/Kconfig > index d06ac26648..da59eb2155 100644 > --- a/hw/riscv/Kconfig > +++ b/hw/riscv/Kconfig > @@ -69,6 +69,22 @@ config RISCV_VIRT > select ACPI > select ACPI_PCI > > +config RISCV_SERVER_PLATFORM_REF > + bool > + default y > + depends on RISCV64 > + imply TPM_TIS_SYSBUS > + select RISCV_NUMA > + select GOLDFISH_RTC > + select PCI > + select PCI_EXPRESS_GENERIC_BRIDGE > + select PFLASH_CFI01 > + select SERIAL > + select RISCV_ACLINT > + select RISCV_APLIC > + select RISCV_IMSIC > + select RISCV_IOMMU > + > config SHAKTI_C > bool > default y > diff --git a/hw/riscv/meson.build b/hw/riscv/meson.build > index 7aa3c1578d..cc5a019f7c 100644 > --- a/hw/riscv/meson.build > +++ b/hw/riscv/meson.build > @@ -7,6 +7,7 @@ riscv_ss.add(when: 'CONFIG_RISCV_NUMA', if_true: files('numa.c')) > riscv_ss.add(files('riscv_hart.c')) > riscv_ss.add(when: 'CONFIG_OPENTITAN', if_true: files('opentitan.c')) > riscv_ss.add(when: 'CONFIG_RISCV_VIRT', if_true: files('virt.c')) > +riscv_ss.add(when: 'CONFIG_RISCV_SERVER_PLATFORM_REF', if_true: files('server_platform_ref.c')) > riscv_ss.add(when: 'CONFIG_SHAKTI_C', if_true: files('shakti_c.c')) > riscv_ss.add(when: 'CONFIG_SIFIVE_E', if_true: files('sifive_e.c')) > riscv_ss.add(when: 'CONFIG_SIFIVE_U', if_true: files('sifive_u.c')) > diff --git a/hw/riscv/server_platform_ref.c b/hw/riscv/server_platform_ref.c > new file mode 100644 > index 0000000000..cc74bf06a1 > --- /dev/null > +++ b/hw/riscv/server_platform_ref.c > @@ -0,0 +1,769 @@ > +/* > + * QEMU RISC-V Server Platform Reference Board (riscv-server-ref) > + * > + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. > + * > + * SPDX-License-Identifier: GPL-2.0-or-later > + */ > + > +#include "qemu/osdep.h" > +#include "qemu/units.h" > +#include "qemu/error-report.h" > +#include "qemu/guest-random.h" > +#include "qapi/error.h" > +#include "qapi/qapi-visit-common.h" > +#include "hw/core/boards.h" > +#include "hw/core/platform-bus.h" > +#include "hw/core/loader.h" > +#include "hw/core/sysbus.h" > +#include "hw/core/qdev-properties.h" > +#include "hw/char/serial.h" > +#include "hw/block/flash.h" > +#include "hw/ide/pci.h" > +#include "hw/ide/ahci-pci.h" > +#include "hw/pci/pci.h" > +#include "hw/pci-host/gpex.h" > +#include "hw/core/sysbus-fdt.h" > +#include "hw/riscv/riscv_hart.h" > +#include "hw/riscv/boot.h" > +#include "hw/riscv/device-common.h" > +#include "hw/riscv/fdt-common.h" > +#include "hw/riscv/numa.h" > +#include "hw/riscv/iommu.h" > +#include "hw/riscv/riscv-iommu.h" > +#include "hw/riscv/riscv-iommu-bits.h" > +#include "hw/intc/riscv_aclint.h" > +#include "hw/intc/riscv_aplic.h" > +#include "hw/intc/riscv_imsic.h" > +#include "chardev/char.h" > +#include "hw/char/serial-mm.h" > +#include "system/device_tree.h" > +#include "system/runstate.h" > +#include "system/system.h" > +#include "system/kvm.h" > +#include "system/tcg.h" > +#include "kvm/kvm_riscv.h" > +#include "system/tpm.h" > +#include "system/qtest.h" > +#include "target/riscv/cpu.h" > +#include "net/net.h" > + > +#include "aia.h" > + > +#define RVSERVER_CPUS_MAX_BITS 9 > +#define RVSERVER_CPUS_MAX (1 << RVSERVER_CPUS_MAX_BITS) > +#define RVSERVER_SOCKETS_MAX_BITS 2 > +#define RVSERVER_SOCKETS_MAX (1 << RVSERVER_SOCKETS_MAX_BITS) > + > +#define RVSERVER_IRQCHIP_NUM_MSIS 255 > +#define RVSERVER_IRQCHIP_NUM_SOURCES 96 > +#define RVSERVER_IRQCHIP_NUM_PRIO_BITS 3 > +#define RVSERVER_IRQCHIP_MAX_GUESTS_BITS 3 > +#define RVSERVER_IRQCHIP_MAX_GUESTS \ > + ((1U << RVSERVER_IRQCHIP_MAX_GUESTS_BITS) - 1U) The server-soc spec (which the server platform spec depends on) says we need a minimum of 5 VS-mode interrupt files (IIC_040). That does require three bits, but we could set RVSERVER_IRQCHIP_MAX_GUESTS to 5 in order to set the minimum (which is our usual approach). Doing that would both keep our config minimized and allow testing of sparse imsic topologies by default. And aia_guests is still configurable on the command line for those that want to configure more. > + > +#define NUM_SATA_PORTS 6 > + > +#define SYSCON_RESET 0x1 > +#define SYSCON_POWEROFF 0x2 > + > +#define RVSERVER_PLATFORM_BUS_NUM_IRQS 8 > + > +#define TYPE_RISCV_SERVER_REF_MACHINE MACHINE_TYPE_NAME("riscv-server-ref") > +OBJECT_DECLARE_SIMPLE_TYPE(RISCVServerRefMachineState, RISCV_SERVER_REF_MACHINE) > + > +struct RISCVServerRefMachineState { > + /*< private >*/ > + MachineState parent; > + > + /*< public >*/ > + Notifier machine_done; > + RISCVHartArrayState soc[RVSERVER_SOCKETS_MAX]; > + DeviceState *irqchip[RVSERVER_SOCKETS_MAX]; > + PFlashCFI01 *flash[2]; > + > + int fdt_size; > + int aia_guests; > + const MemMapEntry *memmap; > + > + DeviceState *platform_bus_dev; > +}; > + > +enum { > + RVSERVER_DEBUG, > + RVSERVER_MROM, > + RVSERVER_RESET_SYSCON, > + RVSERVER_RTC, > + RVSERVER_IOMMU_SYS, > + RVSERVER_ACLINT, > + RVSERVER_APLIC_M, > + RVSERVER_APLIC_S, > + RVSERVER_UART0, > + RVSERVER_IMSIC_M, > + RVSERVER_IMSIC_S, > + RVSERVER_FLASH, > + RVSERVER_DRAM, > + RVSERVER_PCIE_MMIO, > + RVSERVER_PCIE_PIO, > + RVSERVER_PLATFORM_BUS, > + RVSERVER_PCIE_ECAM, > + RVSERVER_PCIE_MMIO_HIGH > +}; > + > +enum { > + RVSERVER_UART0_IRQ = 10, > + RVSERVER_RTC_IRQ = 11, > + RVSERVER_PCIE_IRQ = 32, /* 32 to 35 */ > + IOMMU_SYS_IRQ = 36, /* 36 to 39 */ > + RVSERVER_PLATFORM_BUS_IRQ = 40, /* 40 to 48 */ > +}; > + > +/* > + * The server soc reference machine physical address space used by some of the > + * devices namely ACLINT, APLIC and IMSIC depend on number of Sockets, number > + * of CPUs, and number of IMSIC guest files. > + * > + * Various limits defined by RVSERVER_SOCKETS_MAX_BITS, RVSERVER_CPUS_MAX_BITS, > + * and RVSERVER_IRQCHIP_MAX_GUESTS_BITS are tuned for maximum utilization of > + * server reference machine physical address space. > + */ > + > +#define RVSERVER_IMSIC_GROUP_MAX_SIZE (1U << IMSIC_MMIO_GROUP_MIN_SHIFT) > +#if RVSERVER_IMSIC_GROUP_MAX_SIZE < \ > + IMSIC_GROUP_SIZE(RVSERVER_CPUS_MAX_BITS, RVSERVER_IRQCHIP_MAX_GUESTS_BITS) > +#error "Can't accomodate single IMSIC group in address space" > +#endif > + > +#define RVSERVER_IMSIC_MAX_SIZE (RVSERVER_SOCKETS_MAX * \ > + RVSERVER_IMSIC_GROUP_MAX_SIZE) > +#if 0x4000000 < RVSERVER_IMSIC_MAX_SIZE > +#error "Can't accomodate all IMSIC groups in address space" > +#endif > + > +static const MemMapEntry rvserver_ref_memmap[] = { > + [RVSERVER_DEBUG] = { 0x0, 0x100 }, > + [RVSERVER_MROM] = { 0x1000, 0xf000 }, > + [RVSERVER_RESET_SYSCON] = { 0x100000, 0x1000 }, > + [RVSERVER_RTC] = { 0x101000, 0x1000 }, > + [RVSERVER_IOMMU_SYS] = { 0x102000, 0x1000 }, > + [RVSERVER_ACLINT] = { 0x2000000, 0x10000 }, > + [RVSERVER_PCIE_PIO] = { 0x3000000, 0x10000 }, > + [RVSERVER_PLATFORM_BUS] = { 0x4000000, 0x2000000 }, > + [RVSERVER_APLIC_M] = { 0xc000000, APLIC_SIZE(RVSERVER_CPUS_MAX) }, > + [RVSERVER_APLIC_S] = { 0xd000000, APLIC_SIZE(RVSERVER_CPUS_MAX) }, > + [RVSERVER_UART0] = { 0x10000000, 0x100 }, > + [RVSERVER_FLASH] = { 0x20000000, 0x4000000 }, > + [RVSERVER_IMSIC_M] = { 0x24000000, RVSERVER_IMSIC_MAX_SIZE }, > + [RVSERVER_IMSIC_S] = { 0x28000000, RVSERVER_IMSIC_MAX_SIZE }, > + [RVSERVER_PCIE_ECAM] = { 0x30000000, 0x10000000 }, > + [RVSERVER_PCIE_MMIO] = { 0x40000000, 0x40000000 }, > + [RVSERVER_DRAM] = { 0x80000000, 0xff80000000ull }, > + [RVSERVER_PCIE_MMIO_HIGH] = { 0x10000000000ull, 0x10000000000ull }, > +}; > + > +#define RVSERVER_FLASH_SECTOR_SIZE (256 * KiB) > + > +static void rvserver_flash_maps(RISCVServerRefMachineState *s, > + MemoryRegion *sysmem) > +{ > + hwaddr flashsize = rvserver_ref_memmap[RVSERVER_FLASH].size / 2; > + hwaddr flashbase = rvserver_ref_memmap[RVSERVER_FLASH].base; > + > + riscv_init_flash_map(s->flash[0], flashbase, flashsize, > + sysmem, RVSERVER_FLASH_SECTOR_SIZE); > + riscv_init_flash_map(s->flash[1], flashbase + flashsize, flashsize, > + sysmem, RVSERVER_FLASH_SECTOR_SIZE); > +} > + > +static void create_fdt_pmu(RISCVServerRefMachineState *s) > +{ > + g_autofree char *pmu_name = g_strdup_printf("/pmu"); > + MachineState *ms = MACHINE(s); > + RISCVCPU *hart = &s->soc[0].harts[0]; > + > + qemu_fdt_add_subnode(ms->fdt, pmu_name); > + qemu_fdt_setprop_string(ms->fdt, pmu_name, "compatible", "riscv,pmu"); > + riscv_pmu_generate_fdt_node(ms->fdt, hart->pmu_avail_ctrs, pmu_name); > +} > + > +static void create_fdt_sockets(RISCVServerRefMachineState *s, > + const MemMapEntry *memmap, > + uint32_t *phandle, > + uint32_t *irq_mmio_phandle, > + uint32_t *irq_pcie_phandle, > + uint32_t *msi_pcie_phandle) > +{ > + int socket, phandle_pos; > + MachineState *ms = MACHINE(s); > + uint32_t msi_m_phandle = 0, msi_s_phandle = 0; > + uint32_t xplic_phandles[MAX_NODES]; > + g_autofree uint32_t *intc_phandles = NULL; > + int socket_count = riscv_socket_count(ms); > + bool numa_enabled = riscv_numa_enabled(ms); > + bool is_32_bit = riscv_is_32bit(&s->soc[0]); > + IMSICFdtProps imsic_fdt_props; > + APLICFdtProps aplic_fdt_props; > + ACLINTFdtProps aclint_props; > + > + riscv_fdt_create_cpu_socket_subnode(ms->fdt, > + kvm_enabled() ? kvm_riscv_get_timebase_frequency(&s->soc->harts[0]) > + : RISCV_ACLINT_DEFAULT_TIMEBASE_FREQ); > + > + intc_phandles = g_new0(uint32_t, ms->smp.cpus); > + > + aclint_props.clint = &memmap[RVSERVER_ACLINT]; > + aclint_props.aia_type = AIA_TYPE_APLIC_IMSIC; > + aclint_props.numa_enabled = numa_enabled; > + > + phandle_pos = ms->smp.cpus; > + for (socket = (socket_count - 1); socket >= 0; socket--) { > + hwaddr memaddr = s->memmap[RVSERVER_DRAM].base + > + riscv_socket_mem_offset(ms, socket); > + uint64_t memsize = riscv_socket_mem_size(ms, socket); > + > + phandle_pos -= s->soc[socket].num_harts; > + > + riscv_create_fdt_socket_cpus(ms->fdt, (&s->soc[socket])->harts, socket, > + s->soc[socket].num_harts, > + s->soc[socket].hartid_base, > + phandle, &intc_phandles[phandle_pos], > + numa_enabled, is_32_bit); > + > + riscv_create_fdt_socket_memory(ms->fdt, memaddr, memsize, > + socket, riscv_numa_enabled(ms)); > + > + aclint_props.socket = socket; > + aclint_props.num_harts = s->soc[socket].num_harts; > + riscv_create_fdt_socket_aclint(ms->fdt, &aclint_props, > + &intc_phandles[phandle_pos]); > + } > + > + imsic_fdt_props.soc = &s->soc; > + imsic_fdt_props.socket_count = socket_count; > + imsic_fdt_props.smp_cpus = ms->smp.cpus; > + imsic_fdt_props.imsic_m_base = memmap[RVSERVER_IMSIC_M].base; > + imsic_fdt_props.imsic_s_base = memmap[RVSERVER_IMSIC_S].base; > + imsic_fdt_props.imsic_group_max_size = RVSERVER_IMSIC_GROUP_MAX_SIZE; > + imsic_fdt_props.irqchip_num_msis = RVSERVER_IRQCHIP_NUM_MSIS; > + imsic_fdt_props.aia_guests = s->aia_guests; > + > + riscv_create_fdt_imsic(ms->fdt, &imsic_fdt_props, phandle, intc_phandles, > + &msi_m_phandle, &msi_s_phandle); > + *msi_pcie_phandle = msi_s_phandle; > + > + aplic_fdt_props.aplic_m = !kvm_enabled() > + ? &memmap[RVSERVER_APLIC_M] : NULL; > + aplic_fdt_props.aplic_s = &memmap[RVSERVER_APLIC_S]; > + aplic_fdt_props.platform_bus = &memmap[RVSERVER_PLATFORM_BUS]; > + aplic_fdt_props.platform_bus_irq = RVSERVER_PLATFORM_BUS_IRQ; > + aplic_fdt_props.num_harts = ms->smp.cpus; > + aplic_fdt_props.numa_enabled = numa_enabled; > + aplic_fdt_props.irqchip_num_sources = RVSERVER_IRQCHIP_NUM_SOURCES; > + aplic_fdt_props.aia_type = AIA_TYPE_APLIC_IMSIC; > + > + phandle_pos = ms->smp.cpus; > + for (socket = (socket_count - 1); socket >= 0; socket--) { > + phandle_pos -= s->soc[socket].num_harts; > + > + aplic_fdt_props.socket = socket; > + aplic_fdt_props.num_harts = s->soc[socket].num_harts; > + riscv_create_fdt_socket_aplic(ms->fdt, &aplic_fdt_props, > + msi_m_phandle, msi_s_phandle, phandle, > + &intc_phandles[phandle_pos], > + xplic_phandles); > + } > + > + for (socket = 0; socket < socket_count; socket++) { > + if (socket == 0) { > + *irq_mmio_phandle = xplic_phandles[socket]; > + *irq_pcie_phandle = xplic_phandles[socket]; > + } > + if (socket == 1) { > + *irq_pcie_phandle = xplic_phandles[socket]; > + } > + } > + > + riscv_socket_fdt_write_distance_matrix(ms); > +} > + > +static void finalize_fdt(RISCVServerRefMachineState *s) > +{ > + uint32_t phandle = 1, irq_mmio_phandle = 1, msi_pcie_phandle = 1; > + uint32_t irq_pcie_phandle = 1, iommu_sys_phandle; > + g_autofree char *name = NULL; > + MachineState *ms = MACHINE(s); > + > + create_fdt_sockets(s, rvserver_ref_memmap, &phandle, &irq_mmio_phandle, > + &irq_pcie_phandle, &msi_pcie_phandle); > + > + iommu_sys_phandle = riscv_create_fdt_riscv_iommu_sys(ms->fdt, > + s->memmap[RVSERVER_IOMMU_SYS].base, > + s->memmap[RVSERVER_IOMMU_SYS].size, > + &phandle, irq_mmio_phandle, > + msi_pcie_phandle, IOMMU_SYS_IRQ); > + > + riscv_create_fdt_pcie(ms->fdt, AIA_TYPE_APLIC_IMSIC, true, > + &s->memmap[RVSERVER_PCIE_ECAM], > + &s->memmap[RVSERVER_PCIE_PIO], > + &s->memmap[RVSERVER_PCIE_MMIO], > + &s->memmap[RVSERVER_PCIE_MMIO_HIGH], > + irq_pcie_phandle, msi_pcie_phandle, > + iommu_sys_phandle, RVSERVER_PCIE_IRQ); > + > + riscv_create_fdt_syscon(ms->fdt, &phandle, > + rvserver_ref_memmap[RVSERVER_RESET_SYSCON].base, > + rvserver_ref_memmap[RVSERVER_RESET_SYSCON].size, > + SYSCON_RESET, SYSCON_POWEROFF, false); > + > + riscv_create_fdt_uart(ms->fdt, &rvserver_ref_memmap[RVSERVER_UART0], > + RVSERVER_UART0_IRQ, AIA_TYPE_APLIC_IMSIC, > + irq_mmio_phandle); > + name = riscv_fdt_get_uart_nodename(rvserver_ref_memmap[RVSERVER_UART0].base); > + qemu_fdt_setprop_string(ms->fdt, "/chosen", "stdout-path", name); > + qemu_fdt_setprop_string(ms->fdt, "/aliases", "serial0", name); > + > + riscv_create_fdt_rtc(ms->fdt, &rvserver_ref_memmap[RVSERVER_RTC], > + RVSERVER_RTC_IRQ, AIA_TYPE_APLIC_IMSIC, > + irq_mmio_phandle); > +} > + > +static void create_fdt(RISCVServerRefMachineState *s, > + const MemMapEntry *memmap) > +{ > + MachineState *ms = MACHINE(s); > + uint8_t rng_seed[32]; > + g_autofree char *name = NULL; > + > + ms->fdt = riscv_create_board_device_tree(MACHINE_GET_CLASS(s)->desc, > + "qemu,riscv-server-ref", > + &s->fdt_size); > + > + /* > + * This versioning scheme is for informing platform fw only. It is neither: > + * - A QEMU versioned machine type; a given version of QEMU will emulate > + * a given version of the platform. > + * - A reflection of level of server platform support provided. > + * > + * machine-version-major: updated when changes breaking fw compatibility > + * are introduced. > + * machine-version-minor: updated when features are added that don't break > + * fw compatibility. > + * > + * It's the same as the scheme in arm sbsa-ref. > + */ > + qemu_fdt_setprop_cell(ms->fdt, "/", "machine-version-major", 0); > + qemu_fdt_setprop_cell(ms->fdt, "/", "machine-version-minor", 0); > + > + /* > + * The "/soc/pci@..." node is needed for PCIE hotplugs > + * that might happen before finalize_fdt(). > + */ > + name = g_strdup_printf("/soc/pci@%"HWADDR_PRIx, > + s->memmap[RVSERVER_PCIE_ECAM].base); > + qemu_fdt_add_subnode(ms->fdt, name); > + > + qemu_fdt_add_subnode(ms->fdt, "/chosen"); > + qemu_fdt_add_subnode(ms->fdt, "/aliases"); > + > + /* Pass seed to RNG */ > + qemu_guest_getrandom_nofail(rng_seed, sizeof(rng_seed)); > + qemu_fdt_setprop(ms->fdt, "/chosen", "rng-seed", > + rng_seed, sizeof(rng_seed)); > + > + riscv_create_fdt_flash(ms->fdt, rvserver_ref_memmap[RVSERVER_FLASH].base, > + rvserver_ref_memmap[RVSERVER_FLASH].size / 2); > + create_fdt_pmu(s); > + > +} > + > +static void rvserver_init_pci_devices(RISCVServerRefMachineState *s, > + DeviceState *gpex_host) > +{ > + MachineClass *mc = MACHINE_GET_CLASS(s); > + PCIHostState *pci = PCI_HOST_BRIDGE(gpex_host); > + PCIDevice *pdev_ahci; > + AHCIPCIState *ich9; > + DriveInfo *hd[NUM_SATA_PORTS]; > + > + pci_init_nic_devices(pci->bus, mc->default_nic); > + > + /* IDE disk setup. */ > + pdev_ahci = pci_create_simple(pci->bus, -1, TYPE_ICH9_AHCI); > + ich9 = ICH9_AHCI(pdev_ahci); > + g_assert(ARRAY_SIZE(hd) == ich9->ahci.ports); > + ide_drive_get(hd, ich9->ahci.ports); > + ahci_ide_create_devs(&ich9->ahci, hd); > +} > + > +static uint64_t rvserver_reset_syscon_read(void *opaque, hwaddr addr, > + unsigned size) > +{ > + return 0; > +} > + > +static void rvserver_reset_syscon_write(void *opaque, hwaddr addr, > + uint64_t val64, unsigned int size) > +{ > + switch (val64) { > + case SYSCON_POWEROFF: > + qemu_system_shutdown_request(SHUTDOWN_CAUSE_GUEST_SHUTDOWN); > + return; > + case SYSCON_RESET: > + qemu_system_reset_request(SHUTDOWN_CAUSE_GUEST_RESET); > + return; > + default: > + break; > + } > +} > + > +static const MemoryRegionOps rvserver_reset_syscon_ops = { > + .read = rvserver_reset_syscon_read, > + .write = rvserver_reset_syscon_write, > + .endianness = DEVICE_LITTLE_ENDIAN > +}; > + > +static void rvserver_ref_machine_done(Notifier *notifier, void *data) > +{ > + RISCVServerRefMachineState *s = container_of( > + notifier, RISCVServerRefMachineState, machine_done); > + const MemMapEntry *memmap = rvserver_ref_memmap; > + MachineState *machine = MACHINE(s); > + hwaddr start_addr = memmap[RVSERVER_DRAM].base; > + target_ulong firmware_end_addr, kernel_start_addr; > + const char *firmware_name = riscv_default_firmware_name(&s->soc[0]); > + uint64_t fdt_load_addr; > + uint64_t kernel_entry = 0; > + BlockBackend *pflash_blk0; > + RISCVBootInfo boot_info; > + > + /* > + * An user provided dtb must include everything, including > + * dynamic sysbus devices. Our FDT needs to be finalized. > + */ > + if (machine->dtb == NULL) { > + finalize_fdt(s); > + } > + > + riscv_boot_info_init(&boot_info, &s->soc[0]); > + > + firmware_end_addr = riscv_find_and_load_firmware(machine, &boot_info, > + firmware_name, > + &start_addr, NULL); Looks like there might be some whitespace issue here with the parameters > + > + pflash_blk0 = pflash_cfi01_get_blk(s->flash[0]); > + if (pflash_blk0) { > + if (machine->firmware && !strcmp(machine->firmware, "none")) { > + /* > + * Pflash was supplied but bios is none and not KVM guest, > + * let's overwrite the address we jump to after reset to > + * the base of the flash. > + */ > + start_addr = rvserver_ref_memmap[RVSERVER_FLASH].base; > + } else { > + /* > + * Pflash was supplied but either KVM guest or bios is not none. > + * In this case, base of the flash would contain S-mode payload. > + */ > + riscv_setup_firmware_boot(machine); > + kernel_entry = rvserver_ref_memmap[RVSERVER_FLASH].base; > + } > + } > + > + if (machine->kernel_filename && !kernel_entry) { > + kernel_start_addr = riscv_calc_kernel_start_addr(&boot_info, > + firmware_end_addr); > + riscv_load_kernel(machine, &boot_info, kernel_start_addr, true, NULL); > + kernel_entry = boot_info.image_low_addr; > + } > + > + fdt_load_addr = riscv_compute_fdt_addr(memmap[RVSERVER_DRAM].base, > + memmap[RVSERVER_DRAM].size, > + machine, &boot_info); > + > + riscv_load_fdt(fdt_load_addr, machine->fdt); > + > + /* load the reset vector */ > + riscv_setup_rom_reset_vec(machine, &s->soc[0], start_addr, > + rvserver_ref_memmap[RVSERVER_MROM].base, > + rvserver_ref_memmap[RVSERVER_MROM].size, > + kernel_entry, > + fdt_load_addr); > + > +} > + > +static bool rvserver_aclint_allowed(void) > +{ > + return tcg_enabled() || qtest_enabled(); > +} > + > +static void rvserver_ref_machine_init(MachineState *machine) > +{ > + const MemMapEntry *memmap = rvserver_ref_memmap; > + RISCVServerRefMachineState *s = RISCV_SERVER_REF_MACHINE(machine); > + MemoryRegion *system_memory = get_system_memory(); > + MemoryRegion *mask_rom = g_new(MemoryRegion, 1); > + MemoryRegion *reset_syscon_io = g_new(MemoryRegion, 1); > + DeviceState *mmio_irqchip, *pcie_irqchip, *gpex_host; > + int i, base_hartid, hart_count; > + int socket_count = riscv_socket_count(machine); > + int imsic_bits = imsic_num_bits(s->aia_guests + 1); > + > + /* Check socket count limit */ > + if (RVSERVER_SOCKETS_MAX < socket_count) { > + error_report("number of sockets/nodes should be less than %d", > + RVSERVER_SOCKETS_MAX); > + exit(1); > + } > + > + if (!rvserver_aclint_allowed()) { > + error_report("'aclint' is only available with TCG acceleration"); > + exit(1); > + } > + > + s->memmap = rvserver_ref_memmap; > + > + /* Initialize sockets */ > + mmio_irqchip = pcie_irqchip = NULL; > + for (i = 0; i < socket_count; i++) { > + g_autofree char *soc_name = g_strdup_printf("soc%d", i); > + > + if (!riscv_socket_check_hartids(machine, i)) { > + error_report("discontinuous hartids in socket%d", i); > + exit(1); > + } > + > + base_hartid = riscv_socket_first_hartid(machine, i); > + if (base_hartid < 0) { > + error_report("can't find hartid base for socket%d", i); > + exit(1); > + } > + > + hart_count = riscv_socket_hart_count(machine, i); > + if (hart_count < 0) { > + error_report("can't find hart count for socket%d", i); > + exit(1); > + } > + > + object_initialize_child(OBJECT(machine), soc_name, &s->soc[i], > + TYPE_RISCV_HART_ARRAY); > + object_property_set_str(OBJECT(&s->soc[i]), "cpu-type", > + machine->cpu_type, &error_abort); > + object_property_set_int(OBJECT(&s->soc[i]), "hartid-base", > + base_hartid, &error_abort); > + object_property_set_int(OBJECT(&s->soc[i]), "num-harts", > + hart_count, &error_abort); > + sysbus_realize(SYS_BUS_DEVICE(&s->soc[i]), &error_fatal); > + > + /* Per-socket ACLINT MTIMER */ > + riscv_aclint_mtimer_create(system_memory, > + memmap[RVSERVER_ACLINT].base + i * RISCV_ACLINT_DEFAULT_MTIMER_SIZE, > + RISCV_ACLINT_DEFAULT_MTIMER_SIZE, > + base_hartid, hart_count, > + RISCV_ACLINT_DEFAULT_MTIMECMP, > + RISCV_ACLINT_DEFAULT_MTIME, > + RISCV_ACLINT_DEFAULT_TIMEBASE_FREQ, true); > + > + /* Per-socket interrupt controller */ > + s->irqchip[i] = riscv_create_aia(system_memory, true, s->aia_guests, > + IMSIC_HART_SIZE(0), > + IMSIC_HART_SIZE(imsic_bits), > + RVSERVER_IRQCHIP_NUM_SOURCES, > + &s->memmap[RVSERVER_APLIC_M], > + &s->memmap[RVSERVER_APLIC_S], > + &s->memmap[RVSERVER_IMSIC_M], > + &s->memmap[RVSERVER_IMSIC_S], > + i, base_hartid, hart_count, > + RVSERVER_IRQCHIP_NUM_MSIS, > + RVSERVER_IRQCHIP_NUM_PRIO_BITS); > + > + /* Try to use different IRQCHIP instance based device type */ > + if (i == 0) { > + mmio_irqchip = s->irqchip[i]; > + pcie_irqchip = s->irqchip[i]; > + } > + if (i == 1) { > + pcie_irqchip = s->irqchip[i]; > + } > + } > + > + /* register system main memory (actual RAM) */ > + memory_region_add_subregion(system_memory, memmap[RVSERVER_DRAM].base, > + machine->ram); > + > + /* boot rom */ > + memory_region_init_rom(mask_rom, NULL, "riscv_rvserver_ref_board.mrom", > + memmap[RVSERVER_MROM].size, &error_fatal); > + memory_region_add_subregion(system_memory, memmap[RVSERVER_MROM].base, > + mask_rom); > + > + memory_region_init_io(reset_syscon_io, NULL, &rvserver_reset_syscon_ops, > + NULL, "reset_syscon_io", > + memmap[RVSERVER_RESET_SYSCON].size); > + memory_region_add_subregion(system_memory, > + memmap[RVSERVER_RESET_SYSCON].base, > + reset_syscon_io); > + > + gpex_host = riscv_gpex_pcie_init(system_memory, pcie_irqchip, > + &rvserver_ref_memmap[RVSERVER_PCIE_ECAM], > + &rvserver_ref_memmap[RVSERVER_PCIE_MMIO], > + &rvserver_ref_memmap[RVSERVER_PCIE_MMIO_HIGH], > + &rvserver_ref_memmap[RVSERVER_PCIE_PIO], > + RVSERVER_PCIE_IRQ); > + > + /* Init nic devices and ICH9 AHCI */ > + rvserver_init_pci_devices(s, gpex_host); > + > + s->platform_bus_dev = riscv_create_platform_bus(mmio_irqchip, > + &s->memmap[RVSERVER_PLATFORM_BUS], > + RVSERVER_PLATFORM_BUS_IRQ, > + RVSERVER_PLATFORM_BUS_NUM_IRQS); > + > + serial_mm_init(system_memory, memmap[RVSERVER_UART0].base, > + 0, qdev_get_gpio_in(mmio_irqchip, RVSERVER_UART0_IRQ), 399193, > + serial_hd(0), DEVICE_LITTLE_ENDIAN); > + > + sysbus_create_simple("goldfish_rtc", memmap[RVSERVER_RTC].base, > + qdev_get_gpio_in(mmio_irqchip, RVSERVER_RTC_IRQ)); > + > + for (i = 0; i < ARRAY_SIZE(s->flash); i++) { > + /* Map legacy -drive if=pflash to machine properties */ > + pflash_cfi01_legacy_drive(s->flash[i], > + drive_get(IF_PFLASH, 0, i)); > + } > + rvserver_flash_maps(s, system_memory); > + > + /* load/create device tree */ > + if (machine->dtb) { > + machine->fdt = load_device_tree(machine->dtb, &s->fdt_size); > + if (!machine->fdt) { > + error_report("load_device_tree() failed"); > + exit(1); > + } > + } else { > + create_fdt(s, memmap); > + } > + > + riscv_create_iommu_sys(mmio_irqchip, s->memmap[RVSERVER_IOMMU_SYS].base, > + IOMMU_SYS_IRQ, false); > + > + s->machine_done.notify = rvserver_ref_machine_done; > + qemu_add_machine_init_done_notifier(&s->machine_done); > +} > + > +static void rvserver_ref_machine_instance_init(Object *obj) > +{ > + RISCVServerRefMachineState *s = RISCV_SERVER_REF_MACHINE(obj); > + > + s->flash[0] = riscv_flash_create(OBJECT(s), "riscv-server-ref.flash0", > + "pflash0", RVSERVER_FLASH_SECTOR_SIZE); > + s->flash[1] = riscv_flash_create(OBJECT(s), "riscv-server-ref.flash1", > + "pflash1", RVSERVER_FLASH_SECTOR_SIZE); More whitespace issues here. Might want to double check whole file with some tool. > +} > + > +static char *rvserver_ref_get_aia_guests(Object *obj, Error **errp) > +{ > + RISCVServerRefMachineState *s = RISCV_SERVER_REF_MACHINE(obj); > + char val[32]; > + > + sprintf(val, "%d", s->aia_guests); > + return g_strdup(val); > +} > + > +static void rvserver_ref_set_aia_guests(Object *obj, const char *val, > + Error **errp) > +{ > + RISCVServerRefMachineState *s = RISCV_SERVER_REF_MACHINE(obj); > + > + s->aia_guests = atoi(val); > + if (s->aia_guests < 0 || s->aia_guests > RVSERVER_IRQCHIP_MAX_GUESTS) { > + error_setg(errp, "Invalid number of AIA IMSIC guests"); > + error_append_hint(errp, "Valid values be between 0 and %d.\n", > + RVSERVER_IRQCHIP_MAX_GUESTS); > + } > +} > + > +static HotplugHandler *rvserver_machine_get_hotplug_handler(MachineState *ms, > + DeviceState *dev) > +{ > + MachineClass *mc = MACHINE_GET_CLASS(ms); > + > + if (device_is_dynamic_sysbus(mc, dev)) { > + return HOTPLUG_HANDLER(ms); > + } > + > + return NULL; > +} > + > +static void rvserver_machine_device_plug_cb(HotplugHandler *hotplug_dev, > + DeviceState *dev, Error **errp) > +{ > + RISCVServerRefMachineState *s = RISCV_SERVER_REF_MACHINE(hotplug_dev); > + > + if (s->platform_bus_dev) { > + MachineClass *mc = MACHINE_GET_CLASS(s); > + > + if (device_is_dynamic_sysbus(mc, dev)) { > + platform_bus_link_device(PLATFORM_BUS_DEVICE(s->platform_bus_dev), > + SYS_BUS_DEVICE(dev)); > + } > + } > +} > + > +static void rvserver_ref_machine_class_init(ObjectClass *oc, const void *data) > +{ > + char str[128]; > + MachineClass *mc = MACHINE_CLASS(oc); > + HotplugHandlerClass *hc = HOTPLUG_HANDLER_CLASS(oc); > + static const char * const valid_cpu_types[] = { > + TYPE_RISCV_CPU_RVSERVER_REF, > + }; > + > + /* Note: this is used as /model in the FDT. */ > + mc->desc = "RISC-V Server Platform Reference Board v1.0"; > + mc->init = rvserver_ref_machine_init; > + mc->max_cpus = RVSERVER_CPUS_MAX; > + mc->default_cpu_type = TYPE_RISCV_CPU_RVSERVER_REF; > + mc->valid_cpu_types = valid_cpu_types; > + mc->pci_allow_0_address = true; > + mc->default_nic = "e1000e"; > + mc->possible_cpu_arch_ids = riscv_numa_possible_cpu_arch_ids; > + mc->cpu_index_to_instance_props = riscv_numa_cpu_index_to_props; > + mc->get_default_cpu_node_id = riscv_numa_get_default_cpu_node_id; > + mc->numa_mem_supported = true; > + /* platform instead of architectural choice */ > + mc->cpu_cluster_has_numa_boundary = true; > + mc->default_ram_id = "riscv_rvserver_ref_board.ram"; > + > + object_class_property_add_str(oc, "aia-guests", > + rvserver_ref_get_aia_guests, > + rvserver_ref_set_aia_guests); > + sprintf(str, "Set number of guest MMIO pages for AIA IMSIC. Valid value " > + "should be between 0 and %d.", RVSERVER_IRQCHIP_MAX_GUESTS); > + object_class_property_set_description(oc, "aia-guests", str); > + > + assert(!mc->get_hotplug_handler); > + mc->get_hotplug_handler = rvserver_machine_get_hotplug_handler; > + hc->plug = rvserver_machine_device_plug_cb; > +#ifdef CONFIG_TPM > + machine_class_allow_dynamic_sysbus_dev(mc, TYPE_TPM_TIS_SYSBUS); > +#endif > +} > + > +static const TypeInfo rvserver_ref_typeinfo = { > + .name = TYPE_RISCV_SERVER_REF_MACHINE, > + .parent = TYPE_MACHINE, > + .class_init = rvserver_ref_machine_class_init, > + .instance_init = rvserver_ref_machine_instance_init, > + .instance_size = sizeof(RISCVServerRefMachineState), > + .interfaces = (const InterfaceInfo[]) { > + { TYPE_HOTPLUG_HANDLER }, > + { } > + }, > +}; > + > +static void rvserver_ref_init_register_types(void) > +{ > + type_register_static(&rvserver_ref_typeinfo); > +} > + > +type_init(rvserver_ref_init_register_types) > -- > 2.43.0 > Thanks, drew ^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: [PATCH v10 3/5] hw/riscv: server platform reference machine 2026-09-08 10:40 ` Andrew Jones @ 2026-09-08 18:44 ` Daniel Henrique Barboza 0 siblings, 0 replies; 19+ messages in thread From: Daniel Henrique Barboza @ 2026-09-08 18:44 UTC (permalink / raw) To: Andrew Jones Cc: qemu-devel, qemu-riscv, alistair.francis, liwei1518, zhiwei_liu, chao.liu, leif.lindholm, Nutty Liu, Paolo Bonzini, Palmer Dabbelt On 9/8/2026 7:40 AM, Andrew Jones wrote: > On Fri, Sep 04, 2026 at 04:56:08PM -0300, Daniel Henrique Barboza wrote: >> The RISC-V Server Platform specification [1] defines a standardized set >> of hardware and software capabilities, that portable system software, >> such as OS and hypervisors can rely on being present in a RISC-V server >> platform. >> >> The main features included in this emulation are: >> >> - Based on riscv virt machine type; >> - A new memory map as close as virt machine as possible; >> - An always present IOMMU platform device (riscv-iommu-sys) that uses >> IRQs 36 to 39, one IRQ for queue, similar to the 'virt' board; >> - AIA; >> - PCIe AHCI; >> - PCIe NIC; >> - No virtio device; >> - No fw_cfg device; >> - No ACPI table provided; >> - Only minimal device tree nodes; >> - a platform bus for TPM support. >> >> A note about TPM support: TPM devices in QEMU comes usually in two >> flavors - emulated or passthrough. A passthrough device requires a host >> TPM device that the QEMU process can borrow and it's usually coupled >> with KVM acceleration. >> >> To use the TPM emulator we'll need help from an external TPM emulator >> called swtpm. More info can be found in [2]. For our purposes this is >> a process that, if running Ubuntu, can be installed via 'swtpm' package. >> We'll go back to it shortly. >> >> For now, adding support for the emulated TPM device 'tpm-tis' (other TPM >> flavors might work as well, 'tpm-tis' is the one tested with this work) >> requires a platform bus. Adding a platform bus will open the door for >> more devices to be added in the board. This is ok - a reference board >> isn't a restricted board and users are free to add devices at their >> leisure. >> >> Here's how to use tpm-tis with the riscv-server-ref board: >> >> - in a separated shell/term run 'swtpm' (--log is optional): >> >> $ mkdir /tmp/mytpm1 >> $ swtpm socket --tpmstate dir=/tmp/mytpm1 \ >> --ctrl type=unixio,path=/tmp/mytpm1/swtpm-sock \ >> --tpm2 \ >> --log level=20 >> >> Then start QEMU with: >> >> $ qemu-system-riscv64 -M riscv-server-ref (...) \ >> -chardev socket,id=chrtpm,path=/tmp/mytpm1/swtpm-sock \ >> -tpmdev emulator,id=tpm0,chardev=chrtpm\ >> -device tpm-tis-device,tpmdev=tpm0 >> >> [1] https://github.com/riscv-non-isa/riscv-server-platform >> [2] https://qemu-project.gitlab.io/qemu/specs/tpm.html >> >> Signed-off-by: Daniel Henrique Barboza <daniel.barboza@oss.qualcomm.com> >> Reviewed-by: Nutty Liu <nutty.liu@hotmail.com> >> Reviewed-by: Chao Liu <chao.liu@processmission.com> >> --- >> configs/devices/riscv64-softmmu/default.mak | 1 + >> hw/riscv/Kconfig | 16 + >> hw/riscv/meson.build | 1 + >> hw/riscv/server_platform_ref.c | 769 ++++++++++++++++++++ >> 4 files changed, 787 insertions(+) >> create mode 100644 hw/riscv/server_platform_ref.c >> >> diff --git a/configs/devices/riscv64-softmmu/default.mak b/configs/devices/riscv64-softmmu/default.mak >> index a8e4d0ab33..ae3f62e2d4 100644 >> --- a/configs/devices/riscv64-softmmu/default.mak >> +++ b/configs/devices/riscv64-softmmu/default.mak >> @@ -9,6 +9,7 @@ >> # CONFIG_SIFIVE_E=n >> # CONFIG_SIFIVE_U=n >> # CONFIG_RISCV_VIRT=n >> +# CONFIG_RISCV_SERVER_PLATFORM_REF=n >> # CONFIG_MICROCHIP_PFSOC=n >> # CONFIG_SHAKTI_C=n >> # CONFIG_XIANGSHAN_KUNMINGHU=n >> diff --git a/hw/riscv/Kconfig b/hw/riscv/Kconfig >> index d06ac26648..da59eb2155 100644 >> --- a/hw/riscv/Kconfig >> +++ b/hw/riscv/Kconfig >> @@ -69,6 +69,22 @@ config RISCV_VIRT >> select ACPI >> select ACPI_PCI >> >> +config RISCV_SERVER_PLATFORM_REF >> + bool >> + default y >> + depends on RISCV64 >> + imply TPM_TIS_SYSBUS >> + select RISCV_NUMA >> + select GOLDFISH_RTC >> + select PCI >> + select PCI_EXPRESS_GENERIC_BRIDGE >> + select PFLASH_CFI01 >> + select SERIAL >> + select RISCV_ACLINT >> + select RISCV_APLIC >> + select RISCV_IMSIC >> + select RISCV_IOMMU >> + >> config SHAKTI_C >> bool >> default y >> diff --git a/hw/riscv/meson.build b/hw/riscv/meson.build >> index 7aa3c1578d..cc5a019f7c 100644 >> --- a/hw/riscv/meson.build >> +++ b/hw/riscv/meson.build >> @@ -7,6 +7,7 @@ riscv_ss.add(when: 'CONFIG_RISCV_NUMA', if_true: files('numa.c')) >> riscv_ss.add(files('riscv_hart.c')) >> riscv_ss.add(when: 'CONFIG_OPENTITAN', if_true: files('opentitan.c')) >> riscv_ss.add(when: 'CONFIG_RISCV_VIRT', if_true: files('virt.c')) >> +riscv_ss.add(when: 'CONFIG_RISCV_SERVER_PLATFORM_REF', if_true: files('server_platform_ref.c')) >> riscv_ss.add(when: 'CONFIG_SHAKTI_C', if_true: files('shakti_c.c')) >> riscv_ss.add(when: 'CONFIG_SIFIVE_E', if_true: files('sifive_e.c')) >> riscv_ss.add(when: 'CONFIG_SIFIVE_U', if_true: files('sifive_u.c')) >> diff --git a/hw/riscv/server_platform_ref.c b/hw/riscv/server_platform_ref.c >> new file mode 100644 >> index 0000000000..cc74bf06a1 >> --- /dev/null >> +++ b/hw/riscv/server_platform_ref.c >> @@ -0,0 +1,769 @@ >> +/* >> + * QEMU RISC-V Server Platform Reference Board (riscv-server-ref) >> + * >> + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. >> + * >> + * SPDX-License-Identifier: GPL-2.0-or-later >> + */ >> + >> +#include "qemu/osdep.h" >> +#include "qemu/units.h" >> +#include "qemu/error-report.h" >> +#include "qemu/guest-random.h" >> +#include "qapi/error.h" >> +#include "qapi/qapi-visit-common.h" >> +#include "hw/core/boards.h" >> +#include "hw/core/platform-bus.h" >> +#include "hw/core/loader.h" >> +#include "hw/core/sysbus.h" >> +#include "hw/core/qdev-properties.h" >> +#include "hw/char/serial.h" >> +#include "hw/block/flash.h" >> +#include "hw/ide/pci.h" >> +#include "hw/ide/ahci-pci.h" >> +#include "hw/pci/pci.h" >> +#include "hw/pci-host/gpex.h" >> +#include "hw/core/sysbus-fdt.h" >> +#include "hw/riscv/riscv_hart.h" >> +#include "hw/riscv/boot.h" >> +#include "hw/riscv/device-common.h" >> +#include "hw/riscv/fdt-common.h" >> +#include "hw/riscv/numa.h" >> +#include "hw/riscv/iommu.h" >> +#include "hw/riscv/riscv-iommu.h" >> +#include "hw/riscv/riscv-iommu-bits.h" >> +#include "hw/intc/riscv_aclint.h" >> +#include "hw/intc/riscv_aplic.h" >> +#include "hw/intc/riscv_imsic.h" >> +#include "chardev/char.h" >> +#include "hw/char/serial-mm.h" >> +#include "system/device_tree.h" >> +#include "system/runstate.h" >> +#include "system/system.h" >> +#include "system/kvm.h" >> +#include "system/tcg.h" >> +#include "kvm/kvm_riscv.h" >> +#include "system/tpm.h" >> +#include "system/qtest.h" >> +#include "target/riscv/cpu.h" >> +#include "net/net.h" >> + >> +#include "aia.h" >> + >> +#define RVSERVER_CPUS_MAX_BITS 9 >> +#define RVSERVER_CPUS_MAX (1 << RVSERVER_CPUS_MAX_BITS) >> +#define RVSERVER_SOCKETS_MAX_BITS 2 >> +#define RVSERVER_SOCKETS_MAX (1 << RVSERVER_SOCKETS_MAX_BITS) >> + >> +#define RVSERVER_IRQCHIP_NUM_MSIS 255 >> +#define RVSERVER_IRQCHIP_NUM_SOURCES 96 >> +#define RVSERVER_IRQCHIP_NUM_PRIO_BITS 3 >> +#define RVSERVER_IRQCHIP_MAX_GUESTS_BITS 3 >> +#define RVSERVER_IRQCHIP_MAX_GUESTS \ >> + ((1U << RVSERVER_IRQCHIP_MAX_GUESTS_BITS) - 1U) > > The server-soc spec (which the server platform spec depends on) says we > need a minimum of 5 VS-mode interrupt files (IIC_040). That does require > three bits, but we could set RVSERVER_IRQCHIP_MAX_GUESTS to 5 in order > to set the minimum (which is our usual approach). Doing that would both > keep our config minimized and allow testing of sparse imsic topologies > by default. And aia_guests is still configurable on the command line for > those that want to configure more. Fair enough. I'll set RVSERVER_IRQCHIP_MAX_GUESTS to 5. > >> + >> +#define NUM_SATA_PORTS 6 [...] >> +static void rvserver_ref_machine_instance_init(Object *obj) >> +{ >> + RISCVServerRefMachineState *s = RISCV_SERVER_REF_MACHINE(obj); >> + >> + s->flash[0] = riscv_flash_create(OBJECT(s), "riscv-server-ref.flash0", >> + "pflash0", RVSERVER_FLASH_SECTOR_SIZE); >> + s->flash[1] = riscv_flash_create(OBJECT(s), "riscv-server-ref.flash1", >> + "pflash1", RVSERVER_FLASH_SECTOR_SIZE); > > More whitespace issues here. Might want to double check whole file with > some tool. I believe you caugh every single one of them. Would be nice to have a 'lint' like script to check for this kind of stuff though. Thanks, Daniel ^ permalink raw reply [flat|nested] 19+ messages in thread
* [PATCH v10 4/5] tests/functional/riscv64: add riscv-server-ref tests 2026-09-04 19:56 [PATCH v10 0/5] hw/riscv: Server Platform Reference Board Daniel Henrique Barboza ` (2 preceding siblings ...) 2026-09-04 19:56 ` [PATCH v10 3/5] hw/riscv: server platform reference machine Daniel Henrique Barboza @ 2026-09-04 19:56 ` Daniel Henrique Barboza 2026-09-08 7:34 ` Sunil V L 2026-09-08 9:11 ` Andrew Jones 2026-09-04 19:56 ` [PATCH v10 5/5] docs: add riscv-server-ref.rst Daniel Henrique Barboza 4 siblings, 2 replies; 19+ messages in thread From: Daniel Henrique Barboza @ 2026-09-04 19:56 UTC (permalink / raw) To: qemu-devel Cc: qemu-riscv, alistair.francis, liwei1518, zhiwei_liu, chao.liu, andrew.jones, leif.lindholm, Daniel Henrique Barboza, Chao Liu, Nutty Liu, Palmer Dabbelt Add tests for the recently added riscv-server-ref machine: - a new test_opensbi.py test. The idea is to have a quick test that can catch trivial regressions that would prevent OpenSBI to finish; - a new Linux boot "thorough" test that will boot the machine up to the buildroot prompt. - a TPM specific selftest for the riscv-server-ref board. The test will be skipped if there's no 'swtpm' in the host. Signed-off-by: Daniel Henrique Barboza <daniel.barboza@oss.qualcomm.com> Reviewed-by: Chao Liu <chao.liu.zevorn@gmail.com> Reviewed-by: Nutty Liu <nutty.liu@hotmail.com> Reviewed-by: Alistair Francis <alistair.francis@wdc.com> --- tests/functional/riscv64/meson.build | 2 + tests/functional/riscv64/test_opensbi.py | 4 + tests/functional/riscv64/test_server_ref.py | 88 +++++++++++++++++++++ 3 files changed, 94 insertions(+) create mode 100755 tests/functional/riscv64/test_server_ref.py diff --git a/tests/functional/riscv64/meson.build b/tests/functional/riscv64/meson.build index d1a3e6c2bf..2d22e49efd 100644 --- a/tests/functional/riscv64/meson.build +++ b/tests/functional/riscv64/meson.build @@ -3,6 +3,7 @@ test_riscv64_timeouts = { 'boston' : 120, 'k230' : 120, + 'server_ref' : 120, 'tuxrun' : 120, } @@ -15,6 +16,7 @@ tests_riscv64_system_thorough = [ 'endianness', 'boston', 'k230', + 'server_ref', 'sifive_u', 'tt_atlantis', 'tuxrun', diff --git a/tests/functional/riscv64/test_opensbi.py b/tests/functional/riscv64/test_opensbi.py index 0f8beb7e7a..367e131164 100755 --- a/tests/functional/riscv64/test_opensbi.py +++ b/tests/functional/riscv64/test_opensbi.py @@ -36,5 +36,9 @@ def test_riscv_virt(self): self.set_machine('virt') self.boot_opensbi() + def test_riscv_server_ref(self): + self.set_machine('riscv-server-ref') + self.boot_opensbi() + if __name__ == '__main__': QemuSystemTest.main() diff --git a/tests/functional/riscv64/test_server_ref.py b/tests/functional/riscv64/test_server_ref.py new file mode 100755 index 0000000000..db3371fafd --- /dev/null +++ b/tests/functional/riscv64/test_server_ref.py @@ -0,0 +1,88 @@ +#!/usr/bin/env python3 +# +# Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. +# +# SPDX-License-Identifier: GPL-2.0-or-later +# +""" +riscv-server-ref board test +""" + +import os +import tempfile +import subprocess + +from qemu_test import QemuSystemTest, Asset +from qemu_test import wait_for_console_pattern +from qemu_test import skipIfMissingCommands + +class RiscvServerRefTest(QemuSystemTest): + """ + Test the riscv-server-ref board + """ + + ASSET_KERNEL = Asset( + ('https://github.com/danielhb/qemu-machine-boot/raw/refs/heads/' + 'master/riscv/images/virt64/buildroot/Image'), + '6bacc876c769c1bb6057d2bf549eba67fbe83916e8223f9fe21c8e8fff665a36') + + ASSET_ROOTFS = Asset( + ('https://github.com/danielhb/qemu-machine-boot/raw/refs/heads/' + 'master/riscv/images/virt64/buildroot/rootfs.ext2'), + 'f00bb88749f945d80675540a1338bd1ccb226574685a5b6c65ab44027d0411a8') + + def do_test_boot_linux_test(self, tpmstate_dir=None): + self.set_machine('riscv-server-ref') + kernel_path = self.ASSET_KERNEL.fetch() + rootfs_path = self.ASSET_ROOTFS.fetch() + + self.vm.add_args('-kernel', kernel_path) + self.vm.add_args('-append', 'rw rootwait root=/dev/sda') + self.vm.add_args('-drive', + f'file={rootfs_path},format=raw,id=hd0,snapshot=on,if=none') + self.vm.add_args('-device', 'ahci,id=ahci') + self.vm.add_args('-device', 'ide-hd,drive=hd0,bus=ahci.0') + + if tpmstate_dir is not None: + # Note: code taken verbatim from + # tests/functional/arm/test_aspeed_ast2600_buildroot_tpm.py + + # We must put the TPM state dir in /tmp/, not the build dir, + # because some distros use AppArmor to lock down swtpm and + # restrict the set of locations it can access files in. + socket = os.path.join(tpmstate_dir, 'swtpm-socket') + subprocess.run(['swtpm', 'socket', '-d', '--tpm2', + '--tpmstate', f'dir={tpmstate_dir}', + '--ctrl', f'type=unixio,path={socket}'], + check=True) + self.vm.add_args('-chardev', f'socket,id=chrtpm,path={socket}') + self.vm.add_args('-tpmdev', 'emulator,id=tpm0,chardev=chrtpm') + self.vm.add_args('-device', 'tpm-tis-device,tpmdev=tpm0') + + self.vm.set_console() + self.vm.launch() + + # Wait for OpenSBI + wait_for_console_pattern(self, 'OpenSBI') + + # Wait for Linux kernel boot + wait_for_console_pattern(self, 'Linux version') + wait_for_console_pattern(self, 'Machine model: RISC-V Server Platform') + + # Test e1000e network card functionality + wait_for_console_pattern(self, 'e1000e') + wait_for_console_pattern(self, 'Network Connection') + + # Wait for boot to complete - system reaches login prompt + wait_for_console_pattern(self, 'Run /sbin/init as init process') + + def test_boot_linux_test(self): + self.do_test_boot_linux_test() + + @skipIfMissingCommands('swtpm') + def test_boot_linux_test_tpm(self): + with tempfile.TemporaryDirectory(prefix="qemu_") as tpmstate_dir: + self.do_test_boot_linux_test(tpmstate_dir) + +if __name__ == '__main__': + QemuSystemTest.main() -- 2.43.0 ^ permalink raw reply related [flat|nested] 19+ messages in thread
* Re: [PATCH v10 4/5] tests/functional/riscv64: add riscv-server-ref tests 2026-09-04 19:56 ` [PATCH v10 4/5] tests/functional/riscv64: add riscv-server-ref tests Daniel Henrique Barboza @ 2026-09-08 7:34 ` Sunil V L 2026-09-08 9:11 ` Andrew Jones 1 sibling, 0 replies; 19+ messages in thread From: Sunil V L @ 2026-09-08 7:34 UTC (permalink / raw) To: Daniel Henrique Barboza Cc: qemu-devel, qemu-riscv, alistair.francis, liwei1518, zhiwei_liu, chao.liu, andrew.jones, leif.lindholm, Chao Liu, Nutty Liu, Palmer Dabbelt On Sat, Sep 5, 2026 at 1:27 AM Daniel Henrique Barboza <daniel.barboza@oss.qualcomm.com> wrote: > > Add tests for the recently added riscv-server-ref machine: > > - a new test_opensbi.py test. The idea is to have a quick test that can > catch trivial regressions that would prevent OpenSBI to finish; > - a new Linux boot "thorough" test that will boot the machine up to the > buildroot prompt. > - a TPM specific selftest for the riscv-server-ref board. The test > will be skipped if there's no 'swtpm' in the host. > > Signed-off-by: Daniel Henrique Barboza <daniel.barboza@oss.qualcomm.com> > Reviewed-by: Chao Liu <chao.liu.zevorn@gmail.com> > Reviewed-by: Nutty Liu <nutty.liu@hotmail.com> > Reviewed-by: Alistair Francis <alistair.francis@wdc.com> > --- > tests/functional/riscv64/meson.build | 2 + > tests/functional/riscv64/test_opensbi.py | 4 + > tests/functional/riscv64/test_server_ref.py | 88 +++++++++++++++++++++ > 3 files changed, 94 insertions(+) > create mode 100755 tests/functional/riscv64/test_server_ref.py > Reviewed-by: Sunil V L <sunilvl@oss.qualcomm.com> ^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: [PATCH v10 4/5] tests/functional/riscv64: add riscv-server-ref tests 2026-09-04 19:56 ` [PATCH v10 4/5] tests/functional/riscv64: add riscv-server-ref tests Daniel Henrique Barboza 2026-09-08 7:34 ` Sunil V L @ 2026-09-08 9:11 ` Andrew Jones 2026-09-08 10:17 ` Andrew Jones 1 sibling, 1 reply; 19+ messages in thread From: Andrew Jones @ 2026-09-08 9:11 UTC (permalink / raw) To: Daniel Henrique Barboza Cc: qemu-devel, qemu-riscv, alistair.francis, liwei1518, zhiwei_liu, chao.liu, leif.lindholm, Chao Liu, Nutty Liu, Palmer Dabbelt On Fri, Sep 04, 2026 at 04:56:09PM -0300, Daniel Henrique Barboza wrote: > Add tests for the recently added riscv-server-ref machine: This commit uses 'riscv-server-ref' instead of 'rvserver-ref' for the name. Thanks, drew ^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: [PATCH v10 4/5] tests/functional/riscv64: add riscv-server-ref tests 2026-09-08 9:11 ` Andrew Jones @ 2026-09-08 10:17 ` Andrew Jones 0 siblings, 0 replies; 19+ messages in thread From: Andrew Jones @ 2026-09-08 10:17 UTC (permalink / raw) To: Daniel Henrique Barboza Cc: qemu-devel, qemu-riscv, alistair.francis, liwei1518, zhiwei_liu, chao.liu, leif.lindholm, Chao Liu, Nutty Liu, Palmer Dabbelt On Tue, Sep 08, 2026 at 11:11:49AM +0200, Andrew Jones wrote: > On Fri, Sep 04, 2026 at 04:56:09PM -0300, Daniel Henrique Barboza wrote: > > Add tests for the recently added riscv-server-ref machine: > > This commit uses 'riscv-server-ref' instead of 'rvserver-ref' for the > name. Ignore this. The machine name is 'riscv-server-ref'. I was thinking of the cpu name. Thanks, drew ^ permalink raw reply [flat|nested] 19+ messages in thread
* [PATCH v10 5/5] docs: add riscv-server-ref.rst 2026-09-04 19:56 [PATCH v10 0/5] hw/riscv: Server Platform Reference Board Daniel Henrique Barboza ` (3 preceding siblings ...) 2026-09-04 19:56 ` [PATCH v10 4/5] tests/functional/riscv64: add riscv-server-ref tests Daniel Henrique Barboza @ 2026-09-04 19:56 ` Daniel Henrique Barboza 2026-09-08 7:32 ` Sunil V L 2026-09-08 10:05 ` Andrew Jones 4 siblings, 2 replies; 19+ messages in thread From: Daniel Henrique Barboza @ 2026-09-04 19:56 UTC (permalink / raw) To: qemu-devel Cc: qemu-riscv, alistair.francis, liwei1518, zhiwei_liu, chao.liu, andrew.jones, leif.lindholm, Daniel Henrique Barboza, Pierrick Bouvier, Palmer Dabbelt Add documentation for the new riscv-server-ref board. Signed-off-by: Daniel Henrique Barboza <daniel.barboza@oss.qualcomm.com> Reviewed-by: Alistair Francis <alistair.francis@wdc.com> Reviewed-by: Chao Liu <chao.liu@processmission.com> --- docs/system/riscv/riscv-server-ref.rst | 62 ++++++++++++++++++++++++++ docs/system/target-riscv.rst | 1 + 2 files changed, 63 insertions(+) create mode 100644 docs/system/riscv/riscv-server-ref.rst diff --git a/docs/system/riscv/riscv-server-ref.rst b/docs/system/riscv/riscv-server-ref.rst new file mode 100644 index 0000000000..0573b4e07c --- /dev/null +++ b/docs/system/riscv/riscv-server-ref.rst @@ -0,0 +1,62 @@ +.. SPDX-License-Identifier: GPL-2.0-or-later + +RISC-V Server Platform Reference board (``riscv-server-ref``) +============================================================= + +The RISC-V Server Platform specification `spec`_ defines a standardized +set of hardware and software capabilities that portable system software, +such as OS and hypervisors, can rely on being present in a RISC-V server +platform. This machine aims to emulate this specification, providing +an environment for firmware/OS development and testing. + +`spec`_ is version 1.0 at the introduction of this board. New spec versions +might trigger a revision of the emulation itself, which will strive to always +match the latest version available. In case the emulation changes aren't +backwards compatible we'll introduce a versioning scheme, probably via +a machine property, to allow older SW to run with older spec versions. + +The main features included in the riscv-server-ref board are: + +* IOMMU platform device (riscv-iommu-sys) +* AIA +* PCIe AHCI +* PCIe NIC +* No virtio mmio bus +* No fw_cfg device +* No ACPI table +* Minimal device tree nodes + +There are multiple ways of using this reference board. The spec compliant way +is using an EDK2 image and a TPM device. The board was tested with the TPM +device ``tpm-tis`` that uses the external ``swtpm`` emulator. More info on how +to use this device can be found in `tpm`_. + +To use this board coupled with the tpm-tis device, first start the ``swtpm`` +process in a shell (the ``log`` parameter is optional): + +.. code-block:: bash + + $ mkdir /tmp/mytpm1 + $ swtpm socket --tpmstate dir=/tmp/mytpm1 \ + --ctrl type=unixio,path=/tmp/mytpm1/swtpm-sock \ + --tpm2 \ + --log level=20 + +And then start QEMU with: + +.. code-block:: bash + + qemu-system-riscv64 -M riscv-server-ref \ + -bios fw_dynamic.bin \ + -kernel EDK2.fd \ + -drive file=nvme_disk.ext2,format=raw,id=hd0,if=none \ + -device ahci,id=ahci \ + -device ide-hd,drive=hd0,bus=ahci.0 \ + -chardev socket,id=chrtpm,path=/tmp/mytpm1/swtpm-sock \ + -tpmdev emulator,id=tpm0,chardev=chrtpm \ + -device tpm-tis-device,tpmdev=tpm0 \ + -nographic + + +.. _spec: https://github.com/riscv-non-isa/riscv-server-platform +.. _tpm: https://qemu-project.gitlab.io/qemu/specs/tpm.html diff --git a/docs/system/target-riscv.rst b/docs/system/target-riscv.rst index 2639866a3e..74e23fa64c 100644 --- a/docs/system/target-riscv.rst +++ b/docs/system/target-riscv.rst @@ -70,6 +70,7 @@ undocumented; you can get a complete list by running riscv/microblaze-v-generic riscv/microchip-icicle-kit riscv/mips + riscv/riscv-server-ref riscv/shakti-c riscv/sifive_u riscv/tt_atlantis -- 2.43.0 ^ permalink raw reply related [flat|nested] 19+ messages in thread
* Re: [PATCH v10 5/5] docs: add riscv-server-ref.rst 2026-09-04 19:56 ` [PATCH v10 5/5] docs: add riscv-server-ref.rst Daniel Henrique Barboza @ 2026-09-08 7:32 ` Sunil V L 2026-09-08 10:05 ` Andrew Jones 1 sibling, 0 replies; 19+ messages in thread From: Sunil V L @ 2026-09-08 7:32 UTC (permalink / raw) To: Daniel Henrique Barboza Cc: qemu-devel, qemu-riscv, alistair.francis, liwei1518, zhiwei_liu, chao.liu, andrew.jones, leif.lindholm, Pierrick Bouvier, Palmer Dabbelt On Sat, Sep 5, 2026 at 1:27 AM Daniel Henrique Barboza <daniel.barboza@oss.qualcomm.com> wrote: > > Add documentation for the new riscv-server-ref board. > > Signed-off-by: Daniel Henrique Barboza <daniel.barboza@oss.qualcomm.com> > Reviewed-by: Alistair Francis <alistair.francis@wdc.com> > Reviewed-by: Chao Liu <chao.liu@processmission.com> > --- > docs/system/riscv/riscv-server-ref.rst | 62 ++++++++++++++++++++++++++ > docs/system/target-riscv.rst | 1 + > 2 files changed, 63 insertions(+) > create mode 100644 docs/system/riscv/riscv-server-ref.rst > Reviewed-by: Sunil V L <sunilvl@oss.qualcomm.com> ^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: [PATCH v10 5/5] docs: add riscv-server-ref.rst 2026-09-04 19:56 ` [PATCH v10 5/5] docs: add riscv-server-ref.rst Daniel Henrique Barboza 2026-09-08 7:32 ` Sunil V L @ 2026-09-08 10:05 ` Andrew Jones 2026-09-08 18:50 ` Daniel Henrique Barboza 1 sibling, 1 reply; 19+ messages in thread From: Andrew Jones @ 2026-09-08 10:05 UTC (permalink / raw) To: Daniel Henrique Barboza Cc: qemu-devel, qemu-riscv, alistair.francis, liwei1518, zhiwei_liu, chao.liu, leif.lindholm, Pierrick Bouvier, Palmer Dabbelt On Fri, Sep 04, 2026 at 04:56:10PM -0300, Daniel Henrique Barboza wrote: > Add documentation for the new riscv-server-ref board. > > Signed-off-by: Daniel Henrique Barboza <daniel.barboza@oss.qualcomm.com> > Reviewed-by: Alistair Francis <alistair.francis@wdc.com> > Reviewed-by: Chao Liu <chao.liu@processmission.com> > --- > docs/system/riscv/riscv-server-ref.rst | 62 ++++++++++++++++++++++++++ > docs/system/target-riscv.rst | 1 + > 2 files changed, 63 insertions(+) > create mode 100644 docs/system/riscv/riscv-server-ref.rst > > diff --git a/docs/system/riscv/riscv-server-ref.rst b/docs/system/riscv/riscv-server-ref.rst > new file mode 100644 > index 0000000000..0573b4e07c > --- /dev/null > +++ b/docs/system/riscv/riscv-server-ref.rst > @@ -0,0 +1,62 @@ > +.. SPDX-License-Identifier: GPL-2.0-or-later > + > +RISC-V Server Platform Reference board (``riscv-server-ref``) > +============================================================= > + > +The RISC-V Server Platform specification `spec`_ defines a standardized > +set of hardware and software capabilities that portable system software, > +such as OS and hypervisors, can rely on being present in a RISC-V server > +platform. This machine aims to emulate this specification, providing > +an environment for firmware/OS development and testing. > + > +`spec`_ is version 1.0 at the introduction of this board. New spec versions > +might trigger a revision of the emulation itself, which will strive to always > +match the latest version available. In case the emulation changes aren't > +backwards compatible we'll introduce a versioning scheme, probably via > +a machine property, to allow older SW to run with older spec versions. We'll want a versioning scheme even if the new spec versions are backwards compatible because users will want to be able to test their software on strictly the older spec reference models, not just compatible later models. That allows them to be sure that the software isn't using anything provided by the later models which is not provided by the older. > + > +The main features included in the riscv-server-ref board are: > + > +* IOMMU platform device (riscv-iommu-sys) > +* AIA > +* PCIe AHCI > +* PCIe NIC > +* No virtio mmio bus > +* No fw_cfg device > +* No ACPI table > +* Minimal device tree nodes > + > +There are multiple ways of using this reference board. The spec compliant way > +is using an EDK2 image and a TPM device. The board was tested with the TPM > +device ``tpm-tis`` that uses the external ``swtpm`` emulator. More info on how > +to use this device can be found in `tpm`_. > + > +To use this board coupled with the tpm-tis device, first start the ``swtpm`` > +process in a shell (the ``log`` parameter is optional): > + > +.. code-block:: bash > + > + $ mkdir /tmp/mytpm1 > + $ swtpm socket --tpmstate dir=/tmp/mytpm1 \ > + --ctrl type=unixio,path=/tmp/mytpm1/swtpm-sock \ > + --tpm2 \ > + --log level=20 > + > +And then start QEMU with: > + > +.. code-block:: bash > + > + qemu-system-riscv64 -M riscv-server-ref \ > + -bios fw_dynamic.bin \ > + -kernel EDK2.fd \ > + -drive file=nvme_disk.ext2,format=raw,id=hd0,if=none \ > + -device ahci,id=ahci \ > + -device ide-hd,drive=hd0,bus=ahci.0 \ > + -chardev socket,id=chrtpm,path=/tmp/mytpm1/swtpm-sock \ > + -tpmdev emulator,id=tpm0,chardev=chrtpm \ > + -device tpm-tis-device,tpmdev=tpm0 \ > + -nographic > + > + > +.. _spec: https://github.com/riscv-non-isa/riscv-server-platform > +.. _tpm: https://qemu-project.gitlab.io/qemu/specs/tpm.html > diff --git a/docs/system/target-riscv.rst b/docs/system/target-riscv.rst > index 2639866a3e..74e23fa64c 100644 > --- a/docs/system/target-riscv.rst > +++ b/docs/system/target-riscv.rst > @@ -70,6 +70,7 @@ undocumented; you can get a complete list by running > riscv/microblaze-v-generic > riscv/microchip-icicle-kit > riscv/mips > + riscv/riscv-server-ref > riscv/shakti-c > riscv/sifive_u > riscv/tt_atlantis > -- > 2.43.0 > ^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: [PATCH v10 5/5] docs: add riscv-server-ref.rst 2026-09-08 10:05 ` Andrew Jones @ 2026-09-08 18:50 ` Daniel Henrique Barboza 0 siblings, 0 replies; 19+ messages in thread From: Daniel Henrique Barboza @ 2026-09-08 18:50 UTC (permalink / raw) To: Andrew Jones Cc: qemu-devel, qemu-riscv, alistair.francis, liwei1518, zhiwei_liu, chao.liu, leif.lindholm, Pierrick Bouvier, Palmer Dabbelt On 9/8/2026 7:05 AM, Andrew Jones wrote: > On Fri, Sep 04, 2026 at 04:56:10PM -0300, Daniel Henrique Barboza wrote: >> Add documentation for the new riscv-server-ref board. >> >> Signed-off-by: Daniel Henrique Barboza <daniel.barboza@oss.qualcomm.com> >> Reviewed-by: Alistair Francis <alistair.francis@wdc.com> >> Reviewed-by: Chao Liu <chao.liu@processmission.com> >> --- >> docs/system/riscv/riscv-server-ref.rst | 62 ++++++++++++++++++++++++++ >> docs/system/target-riscv.rst | 1 + >> 2 files changed, 63 insertions(+) >> create mode 100644 docs/system/riscv/riscv-server-ref.rst >> >> diff --git a/docs/system/riscv/riscv-server-ref.rst b/docs/system/riscv/riscv-server-ref.rst >> new file mode 100644 >> index 0000000000..0573b4e07c >> --- /dev/null >> +++ b/docs/system/riscv/riscv-server-ref.rst >> @@ -0,0 +1,62 @@ >> +.. SPDX-License-Identifier: GPL-2.0-or-later >> + >> +RISC-V Server Platform Reference board (``riscv-server-ref``) >> +============================================================= >> + >> +The RISC-V Server Platform specification `spec`_ defines a standardized >> +set of hardware and software capabilities that portable system software, >> +such as OS and hypervisors, can rely on being present in a RISC-V server >> +platform. This machine aims to emulate this specification, providing >> +an environment for firmware/OS development and testing. >> + >> +`spec`_ is version 1.0 at the introduction of this board. New spec versions >> +might trigger a revision of the emulation itself, which will strive to always >> +match the latest version available. In case the emulation changes aren't >> +backwards compatible we'll introduce a versioning scheme, probably via >> +a machine property, to allow older SW to run with older spec versions. > > We'll want a versioning scheme even if the new spec versions are backwards > compatible because users will want to be able to test their software on > strictly the older spec reference models, not just compatible later > models. That allows them to be sure that the software isn't using anything > provided by the later models which is not provided by the older. I'll change this to: `spec`_ is version 1.0 at the introduction of this board. For each new supported spec version a new versioned board will be added, keeping "riscv-server-ref" as an alias for the newest version supported. E.g. for spec version 2.0: * riscv-server-ref-1.0 - board that complies with spec version 1.0 * riscv-server-ref-2.0 - board that complies with spec version 2.0 * riscv-server-ref - alias for riscv-server-ref-2.0 Thanks, Daniel > >> + >> +The main features included in the riscv-server-ref board are: >> + >> +* IOMMU platform device (riscv-iommu-sys) >> +* AIA >> +* PCIe AHCI >> +* PCIe NIC >> +* No virtio mmio bus >> +* No fw_cfg device >> +* No ACPI table >> +* Minimal device tree nodes >> + >> +There are multiple ways of using this reference board. The spec compliant way >> +is using an EDK2 image and a TPM device. The board was tested with the TPM >> +device ``tpm-tis`` that uses the external ``swtpm`` emulator. More info on how >> +to use this device can be found in `tpm`_. >> + >> +To use this board coupled with the tpm-tis device, first start the ``swtpm`` >> +process in a shell (the ``log`` parameter is optional): >> + >> +.. code-block:: bash >> + >> + $ mkdir /tmp/mytpm1 >> + $ swtpm socket --tpmstate dir=/tmp/mytpm1 \ >> + --ctrl type=unixio,path=/tmp/mytpm1/swtpm-sock \ >> + --tpm2 \ >> + --log level=20 >> + >> +And then start QEMU with: >> + >> +.. code-block:: bash >> + >> + qemu-system-riscv64 -M riscv-server-ref \ >> + -bios fw_dynamic.bin \ >> + -kernel EDK2.fd \ >> + -drive file=nvme_disk.ext2,format=raw,id=hd0,if=none \ >> + -device ahci,id=ahci \ >> + -device ide-hd,drive=hd0,bus=ahci.0 \ >> + -chardev socket,id=chrtpm,path=/tmp/mytpm1/swtpm-sock \ >> + -tpmdev emulator,id=tpm0,chardev=chrtpm \ >> + -device tpm-tis-device,tpmdev=tpm0 \ >> + -nographic >> + >> + >> +.. _spec: https://github.com/riscv-non-isa/riscv-server-platform >> +.. _tpm: https://qemu-project.gitlab.io/qemu/specs/tpm.html >> diff --git a/docs/system/target-riscv.rst b/docs/system/target-riscv.rst >> index 2639866a3e..74e23fa64c 100644 >> --- a/docs/system/target-riscv.rst >> +++ b/docs/system/target-riscv.rst >> @@ -70,6 +70,7 @@ undocumented; you can get a complete list by running >> riscv/microblaze-v-generic >> riscv/microchip-icicle-kit >> riscv/mips >> + riscv/riscv-server-ref >> riscv/shakti-c >> riscv/sifive_u >> riscv/tt_atlantis >> -- >> 2.43.0 >> ^ permalink raw reply [flat|nested] 19+ messages in thread
end of thread, other threads:[~2026-09-08 18:51 UTC | newest] Thread overview: 19+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2026-09-04 19:56 [PATCH v10 0/5] hw/riscv: Server Platform Reference Board Daniel Henrique Barboza 2026-09-04 19:56 ` [PATCH v10 1/5] target/riscv/cpu.c: remove 'bare' condition for .profile Daniel Henrique Barboza 2026-09-08 3:26 ` Sunil V L 2026-09-04 19:56 ` [PATCH v10 2/5] target/riscv: add riscv-server-ref CPU Daniel Henrique Barboza 2026-09-08 7:30 ` Sunil V L 2026-09-08 9:08 ` Andrew Jones 2026-09-08 18:40 ` Daniel Henrique Barboza 2026-09-04 19:56 ` [PATCH v10 3/5] hw/riscv: server platform reference machine Daniel Henrique Barboza 2026-09-08 3:25 ` Sunil V L 2026-09-08 10:40 ` Andrew Jones 2026-09-08 18:44 ` Daniel Henrique Barboza 2026-09-04 19:56 ` [PATCH v10 4/5] tests/functional/riscv64: add riscv-server-ref tests Daniel Henrique Barboza 2026-09-08 7:34 ` Sunil V L 2026-09-08 9:11 ` Andrew Jones 2026-09-08 10:17 ` Andrew Jones 2026-09-04 19:56 ` [PATCH v10 5/5] docs: add riscv-server-ref.rst Daniel Henrique Barboza 2026-09-08 7:32 ` Sunil V L 2026-09-08 10:05 ` Andrew Jones 2026-09-08 18:50 ` Daniel Henrique Barboza
This is an external index of several public inboxes, see mirroring instructions on how to clone and mirror all data and code used by this external index.