[PATCH 00/11] Xvisor RISC-V SBI debug console support

35 views
Skip to first unread message

Anup Patel

unread,
Oct 30, 2023, 3:05:28 AM10/30/23
to xvisor...@googlegroups.com, Anup Patel
This series add SBI debug console support for both host and guest
in Xvisor RISC-V.

These patches can also be found in the riscv_sbi_dbcn_v1 branch at:
https://github.com/avpatel/xvisor-next.git

Anup Patel (11):
DOCS: Update qemu-system-riscv[64|32] usage in README files
RISC-V: Improve timer init and deinit function
RISC-V: Rename cpu_vcpu_fp_init() to cpu_vcpu_fp_reset()
RISC-V: Add option probe() callback for VCPU SBI extensions
RISC-V: Allow disabling SBI extensions based on Guest DT
RISC-V: Change the SBI specification version to v2.0 for guest
RISC-V: Add defines for SBI debug console extension
RISC-V: Add SBI_SPEC_MK_VERSION() helper macro
RISC-V: Use SBI debug console for defterm whenever available
RISC-V: Fix how guest vserial instance is located
RISC-V: Implement SBI debug console extension for Guest

arch/riscv/cpu/generic/cpu_sbi.c | 43 ++++++++--
arch/riscv/cpu/generic/cpu_vcpu_fp.c | 2 +-
arch/riscv/cpu/generic/cpu_vcpu_helper.c | 80 +++++++++----------
arch/riscv/cpu/generic/cpu_vcpu_sbi.c | 75 +++++++++++++++--
arch/riscv/cpu/generic/cpu_vcpu_sbi_base.c | 4 +-
arch/riscv/cpu/generic/cpu_vcpu_sbi_hsm.c | 1 +
arch/riscv/cpu/generic/cpu_vcpu_sbi_legacy.c | 1 +
arch/riscv/cpu/generic/cpu_vcpu_sbi_replace.c | 74 +++++++++++++++++
arch/riscv/cpu/generic/cpu_vcpu_sbi_xvisor.c | 1 +
arch/riscv/cpu/generic/cpu_vcpu_timer.c | 51 ++++++------
arch/riscv/cpu/generic/include/arch_regs.h | 3 +
.../cpu/generic/include/cpu_guest_serial.h | 4 +-
arch/riscv/cpu/generic/include/cpu_vcpu_fp.h | 4 +-
arch/riscv/cpu/generic/include/cpu_vcpu_sbi.h | 9 ++-
.../cpu/generic/include/cpu_vcpu_timer.h | 5 +-
arch/riscv/cpu/generic/include/riscv_sbi.h | 10 +++
docs/riscv/riscv32-nested-mmu-test-qemu.txt | 6 +-
docs/riscv/riscv32-qemu.txt | 4 +-
docs/riscv/riscv64-nested-mmu-test-qemu.txt | 6 +-
docs/riscv/riscv64-qemu.txt | 4 +-
tests/riscv/virt32/basic/README | 4 +-
tests/riscv/virt32/linux/README | 4 +-
tests/riscv/virt64/basic/README | 4 +-
tests/riscv/virt64/linux/README | 4 +-
24 files changed, 297 insertions(+), 106 deletions(-)

--
2.34.1

Anup Patel

unread,
Oct 30, 2023, 3:05:29 AM10/30/23
to xvisor...@googlegroups.com, Anup Patel
The H-extension is always enabled by default for latest QEMU so let
us update all README files.

Signed-off-by: Anup Patel <apa...@ventanamicro.com>
---
docs/riscv/riscv32-nested-mmu-test-qemu.txt | 6 +++---
docs/riscv/riscv32-qemu.txt | 4 ++--
docs/riscv/riscv64-nested-mmu-test-qemu.txt | 6 +++---
docs/riscv/riscv64-qemu.txt | 4 ++--
tests/riscv/virt32/basic/README | 4 ++--
tests/riscv/virt32/linux/README | 4 ++--
tests/riscv/virt64/basic/README | 4 ++--
tests/riscv/virt64/linux/README | 4 ++--
8 files changed, 18 insertions(+), 18 deletions(-)

diff --git a/docs/riscv/riscv32-nested-mmu-test-qemu.txt b/docs/riscv/riscv32-nested-mmu-test-qemu.txt
index 273d0ed2..425936f4 100644
--- a/docs/riscv/riscv32-nested-mmu-test-qemu.txt
+++ b/docs/riscv/riscv32-nested-mmu-test-qemu.txt
@@ -4,7 +4,7 @@ This section of readme explains how to build & run Xvisor RISC-V 32bit
nested MMU test-suite on Virt machine emulated by QEMU RISC-V.

Please follow the steps below for nested MMU test-suite on QEMU virt
-machine (v5.1 or higher):
+machine (v8 or higher):

[1. Build environment for Xvisor]
# CROSS_COMPILE=riscv64-unknown-linux-gnu-
@@ -32,9 +32,9 @@ machine (v5.1 or higher):
# cd <xvisor_source_directory>

[9. Run nested MMU test-suite]
- # qemu-system-riscv32 -cpu rv32,x-h=true -M virt -m 512M -nographic -bios <opensbi_source_directory>/build/platform/generic/firmware/fw_jump.bin -kernel ./build/vmm.bin -append 'vmm.bootcmd="wboxtest run_groups 1 nested_mmu"'
+ # qemu-system-riscv32 -M virt -m 512M -nographic -bios <opensbi_source_directory>/build/platform/generic/firmware/fw_jump.bin -kernel ./build/vmm.bin -append 'vmm.bootcmd="wboxtest run_groups 1 nested_mmu"'
OR
- # qemu-system-riscv32 -cpu rv32,x-h=true -M virt -m 512M -nographic -bios <opensbi_source_directory>/build/platform/generic/firmware/fw_jump.bin -kernel ./build/vmm.bin
+ # qemu-system-riscv32 -M virt -m 512M -nographic -bios <opensbi_source_directory>/build/platform/generic/firmware/fw_jump.bin -kernel ./build/vmm.bin
XVisor# wboxtest run_groups 1 nested_mmu

(Note: replace all <> brackets based on your workspace)
diff --git a/docs/riscv/riscv32-qemu.txt b/docs/riscv/riscv32-qemu.txt
index c9d4a14d..7156e0eb 100644
--- a/docs/riscv/riscv32-qemu.txt
+++ b/docs/riscv/riscv32-qemu.txt
@@ -5,7 +5,7 @@ Virt machine emulated by QEMU RISC-V.

Please follow the steps below to build & run Linux kernel with Busybox RootFS
on Virt32 (paravirtualized RISC-V 32bit) Guest with Xvisor RISC-V 32bit running
-on QEMU virt machine (v5.1 or higher):
+on QEMU virt machine (v8 or higher):

[1. Build environment for Xvisor]
# CROSS_COMPILE=riscv64-unknown-linux-gnu-
@@ -63,7 +63,7 @@ on QEMU virt machine (v5.1 or higher):
# genext2fs -B 1024 -b 32768 -d ./build/disk ./build/disk.img

[14. Launch QEMU]
- # qemu-system-riscv32 -cpu rv32,x-h=true -M virt -m 512M -nographic -bios <opensbi_source_directory>/build/platform/generic/firmware/fw_jump.bin -kernel ./build/vmm.bin -initrd ./build/disk.img -append 'vmm.bootcmd="vfs mount initrd /;vfs run /boot.xscript;vfs cat /system/banner.txt"'
+ # qemu-system-riscv32 -M virt -m 512M -nographic -bios <opensbi_source_directory>/build/platform/generic/firmware/fw_jump.bin -kernel ./build/vmm.bin -initrd ./build/disk.img -append 'vmm.bootcmd="vfs mount initrd /;vfs run /boot.xscript;vfs cat /system/banner.txt"'

[15. Kick Guest0 to start Basic Firmware]
XVisor# guest kick guest0
diff --git a/docs/riscv/riscv64-nested-mmu-test-qemu.txt b/docs/riscv/riscv64-nested-mmu-test-qemu.txt
index 5541db42..6e8688a1 100644
--- a/docs/riscv/riscv64-nested-mmu-test-qemu.txt
+++ b/docs/riscv/riscv64-nested-mmu-test-qemu.txt
@@ -4,7 +4,7 @@ This section of readme explains how to build & run Xvisor RISC-V 64bit
nested MMU test-suite on Virt machine emulated by QEMU RISC-V.

Please follow the steps below for nested MMU test-suite on QEMU virt
-machine (v5.1 or higher):
+machine (v8 or higher):

[1. Build environment for Xvisor]
# CROSS_COMPILE=riscv64-unknown-linux-gnu-
@@ -32,9 +32,9 @@ machine (v5.1 or higher):
# cd <xvisor_source_directory>

[9. Run nested MMU test-suite]
- # qemu-system-riscv64 -cpu rv64,x-h=true -M virt -m 512M -nographic -bios <opensbi_source_directory>/build/platform/generic/firmware/fw_jump.bin -kernel ./build/vmm.bin -append 'vmm.bootcmd="wboxtest run_groups 1 nested_mmu"'
+ # qemu-system-riscv64 -M virt -m 512M -nographic -bios <opensbi_source_directory>/build/platform/generic/firmware/fw_jump.bin -kernel ./build/vmm.bin -append 'vmm.bootcmd="wboxtest run_groups 1 nested_mmu"'
OR
- # qemu-system-riscv64 -cpu rv64,x-h=true -M virt -m 512M -nographic -bios <opensbi_source_directory>/build/platform/generic/firmware/fw_jump.bin -kernel ./build/vmm.bin
+ # qemu-system-riscv64 -M virt -m 512M -nographic -bios <opensbi_source_directory>/build/platform/generic/firmware/fw_jump.bin -kernel ./build/vmm.bin
XVisor# wboxtest run_groups 1 nested_mmu

(Note: replace all <> brackets based on your workspace)
diff --git a/docs/riscv/riscv64-qemu.txt b/docs/riscv/riscv64-qemu.txt
index 0ceb5cc7..ad0b740b 100644
--- a/docs/riscv/riscv64-qemu.txt
+++ b/docs/riscv/riscv64-qemu.txt
@@ -5,7 +5,7 @@ Virt machine emulated by QEMU RISC-V.

Please follow the steps below to build & run Linux kernel with Busybox RootFS
on Virt64 (paravirtualized RISC-V 64bit) Guest with Xvisor RISC-V 64bit running
-on QEMU virt machine (v5.1 or higher):
+on QEMU virt machine (v8 or higher):

[1. Build environment for Xvisor]
# CROSS_COMPILE=riscv64-unknown-linux-gnu-
@@ -63,7 +63,7 @@ on QEMU virt machine (v5.1 or higher):
# genext2fs -B 1024 -b 32768 -d ./build/disk ./build/disk.img

[14. Launch QEMU]
- # qemu-system-riscv64 -cpu rv64,x-h=true -M virt -m 512M -nographic -bios <opensbi_source_directory>/build/platform/generic/firmware/fw_jump.bin -kernel ./build/vmm.bin -initrd ./build/disk.img -append 'vmm.bootcmd="vfs mount initrd /;vfs run /boot.xscript;vfs cat /system/banner.txt"'
+ # qemu-system-riscv64 -M virt -m 512M -nographic -bios <opensbi_source_directory>/build/platform/generic/firmware/fw_jump.bin -kernel ./build/vmm.bin -initrd ./build/disk.img -append 'vmm.bootcmd="vfs mount initrd /;vfs run /boot.xscript;vfs cat /system/banner.txt"'

[15. Kick Guest0 to start Basic Firmware]
XVisor# guest kick guest0
diff --git a/tests/riscv/virt32/basic/README b/tests/riscv/virt32/basic/README
index 44250a33..7c0b80c1 100644
--- a/tests/riscv/virt32/basic/README
+++ b/tests/riscv/virt32/basic/README
@@ -4,7 +4,7 @@ The basic firmware currently sets up PIC, Timer, and UART and emulates
a dummy terminal which reponds to various commands.

Please follow the steps below to build & run Basic Firmware on Virt32
-Guest with Xvisor running on QEMU (v3.1.50 or higher):
+Guest with Xvisor running on QEMU (v8 or higher):

[1. Build environment for Xvisor]
# CROSS_COMPILE=riscv32-unknown-linux-gnu-
@@ -34,7 +34,7 @@ Guest with Xvisor running on QEMU (v3.1.50 or higher):
# genext2fs -B 1024 -b 32768 -d ./build/disk ./build/disk.img

[7. Launch QEMU]
- # qemu-system-riscv32 -cpu rv32,x-h=true -M virt -m 512M -display none -serial stdio -bios <opensbi_build_directory>/platform/qemu/virt/firmware/fw_jump.bin -kernel ./build/vmm.bin -initrd ./build/disk.img -append "vmm.bootcmd=\"vfs mount initrd /;vfs run /boot.xscript;vfs cat /system/banner.txt\""
+ # qemu-system-riscv32 -M virt -m 512M -display none -serial stdio -bios <opensbi_build_directory>/platform/qemu/virt/firmware/fw_jump.bin -kernel ./build/vmm.bin -initrd ./build/disk.img -append "vmm.bootcmd=\"vfs mount initrd /;vfs run /boot.xscript;vfs cat /system/banner.txt\""

[8. Kick Guest0 for starting Basic Firmware]
XVisor# guest kick guest0
diff --git a/tests/riscv/virt32/linux/README b/tests/riscv/virt32/linux/README
index c02233b8..d8b08ddd 100644
--- a/tests/riscv/virt32/linux/README
+++ b/tests/riscv/virt32/linux/README
@@ -13,7 +13,7 @@ following url: http://www.kernel.org

Please follow the steps below to build & run Linux kernel with Busybox
RootFS on Virt32 (paravirtualized RISC-V 32bit) Guest with Xvisor running
-on QEMU model (v5.1 or higher):
+on QEMU model (v8 or higher):

[1. Build environment for Xvisor]
# CROSS_COMPILE=riscv64-unknown-linux-gnu-
@@ -71,7 +71,7 @@ on QEMU model (v5.1 or higher):
# genext2fs -B 1024 -b 32768 -d ./build/disk ./build/disk.img

[14. Launch QEMU]
- # qemu-system-riscv32 -cpu rv32,x-h=true -M virt -m 512M -nographic -bios <opensbi_source_directory>/build/platform/qemu/virt32/firmware/fw_jump.bin -kernel ./build/vmm.bin -initrd ./build/disk.img -append 'vmm.bootcmd="vfs mount initrd /;vfs run /boot.xscript;vfs cat /system/banner.txt"'
+ # qemu-system-riscv32 -M virt -m 512M -nographic -bios <opensbi_source_directory>/build/platform/qemu/virt32/firmware/fw_jump.bin -kernel ./build/vmm.bin -initrd ./build/disk.img -append 'vmm.bootcmd="vfs mount initrd /;vfs run /boot.xscript;vfs cat /system/banner.txt"'

[15. Kick Guest0 to start Basic Firmware]
XVisor# guest kick guest0
diff --git a/tests/riscv/virt64/basic/README b/tests/riscv/virt64/basic/README
index ad710751..e1b44494 100644
--- a/tests/riscv/virt64/basic/README
+++ b/tests/riscv/virt64/basic/README
@@ -4,7 +4,7 @@ The basic firmware currently sets up PIC, Timer, and UART and emulates
a dummy terminal which reponds to various commands.

Please follow the steps below to build & run Basic Firmware on Virt64
-Guest with Xvisor running on QEMU (v3.1.50 or higher):
+Guest with Xvisor running on QEMU (v8 or higher):

[1. Build environment for Xvisor]
# CROSS_COMPILE=riscv64-unknown-linux-gnu-
@@ -34,7 +34,7 @@ Guest with Xvisor running on QEMU (v3.1.50 or higher):
# genext2fs -B 1024 -b 32768 -d ./build/disk ./build/disk.img

[7. Launch QEMU]
- # qemu-system-riscv64 -cpu rv64,x-h=true -M virt -m 512M -display none -serial stdio -bios <opensbi_build_directory>/platform/qemu/virt/firmware/fw_jump.bin -kernel ./build/vmm.bin -initrd ./build/disk.img -append "vmm.bootcmd=\"vfs mount initrd /;vfs run /boot.xscript;vfs cat /system/banner.txt\""
+ # qemu-system-riscv64 -M virt -m 512M -display none -serial stdio -bios <opensbi_build_directory>/platform/qemu/virt/firmware/fw_jump.bin -kernel ./build/vmm.bin -initrd ./build/disk.img -append "vmm.bootcmd=\"vfs mount initrd /;vfs run /boot.xscript;vfs cat /system/banner.txt\""

[8. Kick Guest0 for starting Basic Firmware]
XVisor# guest kick guest0
diff --git a/tests/riscv/virt64/linux/README b/tests/riscv/virt64/linux/README
index ea3386b8..16466a4b 100644
--- a/tests/riscv/virt64/linux/README
+++ b/tests/riscv/virt64/linux/README
@@ -13,7 +13,7 @@ following url: http://www.kernel.org

Please follow the steps below to build & run Linux kernel with Busybox
RootFS on Virt64 (paravirtualized RISC-V 64bit) Guest with Xvisor running
-on QEMU model (v5.1 or higher):
+on QEMU model (v8 or higher):

[1. Build environment for Xvisor]
# CROSS_COMPILE=riscv64-unknown-linux-gnu-
@@ -71,7 +71,7 @@ on QEMU model (v5.1 or higher):
# genext2fs -B 1024 -b 32768 -d ./build/disk ./build/disk.img

[14. Launch QEMU]
- # qemu-system-riscv64 -cpu rv64,x-h=true -M virt -m 512M -nographic -bios <opensbi_source_directory>/build/platform/qemu/virt64/firmware/fw_jump.bin -kernel ./build/vmm.bin -initrd ./build/disk.img -append 'vmm.bootcmd="vfs mount initrd /;vfs run /boot.xscript;vfs cat /system/banner.txt"'
+ # qemu-system-riscv64 -M virt -m 512M -nographic -bios <opensbi_source_directory>/build/platform/qemu/virt64/firmware/fw_jump.bin -kernel ./build/vmm.bin -initrd ./build/disk.img -append 'vmm.bootcmd="vfs mount initrd /;vfs run /boot.xscript;vfs cat /system/banner.txt"'

[15. Kick Guest0 to start Basic Firmware]
XVisor# guest kick guest0
--
2.34.1

Anup Patel

unread,
Oct 30, 2023, 3:05:31 AM10/30/23
to xvisor...@googlegroups.com, Anup Patel
Currently, the timer init function does both vcpu creation time
setup and vcpu reset handling. Instead, the timer init function
should only handle vcpu creation time setup and we should have
separate timer reset function.

Also, the timer deinit function should be able to cleanup timer
state without failing so it should not return any error.

Signed-off-by: Anup Patel <apa...@ventanamicro.com>
---
arch/riscv/cpu/generic/cpu_vcpu_helper.c | 17 ++++---
arch/riscv/cpu/generic/cpu_vcpu_timer.c | 51 ++++++++++---------
.../cpu/generic/include/cpu_vcpu_timer.h | 5 +-
3 files changed, 40 insertions(+), 33 deletions(-)

diff --git a/arch/riscv/cpu/generic/cpu_vcpu_helper.c b/arch/riscv/cpu/generic/cpu_vcpu_helper.c
index b4f8d256..731032a1 100644
--- a/arch/riscv/cpu/generic/cpu_vcpu_helper.c
+++ b/arch/riscv/cpu/generic/cpu_vcpu_helper.c
@@ -303,6 +303,12 @@ int arch_vcpu_init(struct vmm_vcpu *vcpu)
if (rc) {
goto fail_free_isa;
}
+
+ /* Initialize timer state */
+ rc = cpu_vcpu_timer_init(vcpu);
+ if (rc) {
+ goto fail_free_nested;
+ }
}

/* Set a0 to VCPU sub-id (i.e. virtual HARTID) */
@@ -342,11 +348,13 @@ int arch_vcpu_init(struct vmm_vcpu *vcpu)
/* Initialize FP state */
cpu_vcpu_fp_init(vcpu);

- /* Initialize timer */
- cpu_vcpu_timer_init(vcpu, &riscv_timer_priv(vcpu));
+ /* Reset timer */
+ cpu_vcpu_timer_reset(vcpu);

return VMM_OK;

+fail_free_nested:
+ cpu_vcpu_nested_deinit(vcpu);
fail_free_isa:
vmm_free(riscv_priv(vcpu)->isa);
riscv_priv(vcpu)->isa = NULL;
@@ -359,7 +367,6 @@ fail:

int arch_vcpu_deinit(struct vmm_vcpu *vcpu)
{
- int rc;
virtual_addr_t sp_exec;

/* Free-up exception stack for Orphan VCPU */
@@ -380,9 +387,7 @@ int arch_vcpu_deinit(struct vmm_vcpu *vcpu)
}

/* Cleanup timer */
- rc = cpu_vcpu_timer_deinit(vcpu, &riscv_timer_priv(vcpu));
- if (rc)
- return rc;
+ cpu_vcpu_timer_deinit(vcpu);

/* Cleanup nested state */
cpu_vcpu_nested_deinit(vcpu);
diff --git a/arch/riscv/cpu/generic/cpu_vcpu_timer.c b/arch/riscv/cpu/generic/cpu_vcpu_timer.c
index cb19aeed..58ce1072 100644
--- a/arch/riscv/cpu/generic/cpu_vcpu_timer.c
+++ b/arch/riscv/cpu/generic/cpu_vcpu_timer.c
@@ -297,26 +297,9 @@ void cpu_vcpu_timer_restore(struct vmm_vcpu *vcpu)
}
}

-int cpu_vcpu_timer_init(struct vmm_vcpu *vcpu, void **timer)
+void cpu_vcpu_timer_reset(struct vmm_vcpu *vcpu)
{
- struct cpu_vcpu_timer *t;
-
- if (!vcpu || !timer)
- return VMM_EINVALID;
-
- if (!(*timer)) {
- *timer = vmm_zalloc(sizeof(struct cpu_vcpu_timer));
- if (!(*timer))
- return VMM_ENOMEM;
- t = *timer;
- INIT_TIMER_EVENT(&t->vs_time_ev,
- cpu_vcpu_timer_vs_expired, vcpu);
- INIT_TIMER_EVENT(&t->time_nested_ev,
- cpu_vcpu_timer_nested_expired, vcpu);
- INIT_TIMER_EVENT(&t->time_ev, cpu_vcpu_timer_expired, vcpu);
- } else {
- t = *timer;
- }
+ struct cpu_vcpu_timer *t = riscv_timer_priv(vcpu);

t->vs_next_cycle = U64_MAX;
vmm_timer_event_stop(&t->vs_time_ev);
@@ -328,22 +311,40 @@ int cpu_vcpu_timer_init(struct vmm_vcpu *vcpu, void **timer)
if (riscv_isa_extension_available(riscv_priv(vcpu)->isa, SSTC)) {
riscv_priv(vcpu)->henvcfg |= ENVCFG_STCE;
}
+}
+
+int cpu_vcpu_timer_init(struct vmm_vcpu *vcpu)
+{
+ struct cpu_vcpu_timer *t;
+
+ if (!vcpu)
+ return VMM_EINVALID;
+
+ t = vmm_zalloc(sizeof(struct cpu_vcpu_timer));
+ if (!t)
+ return VMM_ENOMEM;
+
+ riscv_timer_priv(vcpu) = t;
+
+ INIT_TIMER_EVENT(&t->vs_time_ev,
+ cpu_vcpu_timer_vs_expired, vcpu);
+ INIT_TIMER_EVENT(&t->time_nested_ev,
+ cpu_vcpu_timer_nested_expired, vcpu);
+ INIT_TIMER_EVENT(&t->time_ev, cpu_vcpu_timer_expired, vcpu);

return VMM_OK;
}

-int cpu_vcpu_timer_deinit(struct vmm_vcpu *vcpu, void **timer)
+void cpu_vcpu_timer_deinit(struct vmm_vcpu *vcpu)
{
struct cpu_vcpu_timer *t;

- if (!vcpu || !timer || !(*timer))
- return VMM_EINVALID;
- t = *timer;
+ if (!vcpu)
+ return;
+ t = riscv_timer_priv(vcpu);

vmm_timer_event_stop(&t->vs_time_ev);
vmm_timer_event_stop(&t->time_nested_ev);
vmm_timer_event_stop(&t->time_ev);
vmm_free(t);
-
- return VMM_OK;
}
diff --git a/arch/riscv/cpu/generic/include/cpu_vcpu_timer.h b/arch/riscv/cpu/generic/include/cpu_vcpu_timer.h
index 84d00707..244d8bb2 100644
--- a/arch/riscv/cpu/generic/include/cpu_vcpu_timer.h
+++ b/arch/riscv/cpu/generic/include/cpu_vcpu_timer.h
@@ -37,7 +37,8 @@ void cpu_vcpu_timer_start(struct vmm_vcpu *vcpu, u64 next_cycle);
void cpu_vcpu_timer_delta_update(struct vmm_vcpu *vcpu, bool nested_virt);
void cpu_vcpu_timer_save(struct vmm_vcpu *vcpu);
void cpu_vcpu_timer_restore(struct vmm_vcpu *vcpu);
-int cpu_vcpu_timer_init(struct vmm_vcpu *vcpu, void **timer);
-int cpu_vcpu_timer_deinit(struct vmm_vcpu *vcpu, void **timer);
+void cpu_vcpu_timer_reset(struct vmm_vcpu *vcpu);
+int cpu_vcpu_timer_init(struct vmm_vcpu *vcpu);
+void cpu_vcpu_timer_deinit(struct vmm_vcpu *vcpu);

#endif
--
2.34.1

Anup Patel

unread,
Oct 30, 2023, 3:05:32 AM10/30/23
to xvisor...@googlegroups.com, Anup Patel
The cpu_vcpu_fp_init() function only reset the VCPU FP state so
let us rename it to cpu_vcpu_fp_reset().

Signed-off-by: Anup Patel <apa...@ventanamicro.com>
---
arch/riscv/cpu/generic/cpu_vcpu_fp.c | 2 +-
arch/riscv/cpu/generic/cpu_vcpu_helper.c | 4 ++--
arch/riscv/cpu/generic/include/cpu_vcpu_fp.h | 4 ++--
3 files changed, 5 insertions(+), 5 deletions(-)

diff --git a/arch/riscv/cpu/generic/cpu_vcpu_fp.c b/arch/riscv/cpu/generic/cpu_vcpu_fp.c
index 7a1f907a..0d48590e 100644
--- a/arch/riscv/cpu/generic/cpu_vcpu_fp.c
+++ b/arch/riscv/cpu/generic/cpu_vcpu_fp.c
@@ -28,7 +28,7 @@
#include <cpu_vcpu_switch.h>
#include <cpu_vcpu_fp.h>

-void cpu_vcpu_fp_init(struct vmm_vcpu *vcpu)
+void cpu_vcpu_fp_reset(struct vmm_vcpu *vcpu)
{
riscv_regs(vcpu)->sstatus &= ~SSTATUS_FS;
if (riscv_isa_extension_available(riscv_priv(vcpu)->isa, f) ||
diff --git a/arch/riscv/cpu/generic/cpu_vcpu_helper.c b/arch/riscv/cpu/generic/cpu_vcpu_helper.c
index 731032a1..a99bc178 100644
--- a/arch/riscv/cpu/generic/cpu_vcpu_helper.c
+++ b/arch/riscv/cpu/generic/cpu_vcpu_helper.c
@@ -345,8 +345,8 @@ int arch_vcpu_init(struct vmm_vcpu *vcpu)
/* Reset nested state */
cpu_vcpu_nested_reset(vcpu);

- /* Initialize FP state */
- cpu_vcpu_fp_init(vcpu);
+ /* Reset FP state */
+ cpu_vcpu_fp_reset(vcpu);

/* Reset timer */
cpu_vcpu_timer_reset(vcpu);
diff --git a/arch/riscv/cpu/generic/include/cpu_vcpu_fp.h b/arch/riscv/cpu/generic/include/cpu_vcpu_fp.h
index 38e1ac06..e53e2868 100644
--- a/arch/riscv/cpu/generic/include/cpu_vcpu_fp.h
+++ b/arch/riscv/cpu/generic/include/cpu_vcpu_fp.h
@@ -27,8 +27,8 @@
#include <vmm_types.h>
#include <vmm_manager.h>

-/** Function to initialize FP state */
-void cpu_vcpu_fp_init(struct vmm_vcpu *vcpu);
+/** Function to reset FP state */
+void cpu_vcpu_fp_reset(struct vmm_vcpu *vcpu);

/** Function to save FP registers */
void cpu_vcpu_fp_save(struct vmm_vcpu *vcpu, arch_regs_t *regs);
--
2.34.1

Anup Patel

unread,
Oct 30, 2023, 3:05:34 AM10/30/23
to xvisor...@googlegroups.com, Anup Patel
Let us extend the VCPU SBI extension framework to allow individual
extensions implement an optional probe() callback.

Signed-off-by: Anup Patel <apa...@ventanamicro.com>
---
arch/riscv/cpu/generic/cpu_vcpu_helper.c | 15 +++++
arch/riscv/cpu/generic/cpu_vcpu_sbi.c | 62 ++++++++++++++++---
arch/riscv/cpu/generic/cpu_vcpu_sbi_base.c | 3 +-
arch/riscv/cpu/generic/include/arch_regs.h | 3 +
arch/riscv/cpu/generic/include/cpu_vcpu_sbi.h | 6 ++
5 files changed, 81 insertions(+), 8 deletions(-)

diff --git a/arch/riscv/cpu/generic/cpu_vcpu_helper.c b/arch/riscv/cpu/generic/cpu_vcpu_helper.c
index a99bc178..dd82a255 100644
--- a/arch/riscv/cpu/generic/cpu_vcpu_helper.c
+++ b/arch/riscv/cpu/generic/cpu_vcpu_helper.c
@@ -39,6 +39,7 @@
#include <cpu_tlb.h>
#include <cpu_sbi.h>
#include <cpu_vcpu_fp.h>
+#include <cpu_vcpu_sbi.h>
#include <cpu_vcpu_trap.h>
#include <cpu_vcpu_nested.h>
#include <cpu_vcpu_helper.h>
@@ -309,6 +310,15 @@ int arch_vcpu_init(struct vmm_vcpu *vcpu)
if (rc) {
goto fail_free_nested;
}
+
+ /*
+ * Initialize SBI state
+ * NOTE: This must be the last thing to initialize.
+ */
+ rc = cpu_vcpu_sbi_init(vcpu);
+ if (rc) {
+ goto fail_free_timer;
+ }
}

/* Set a0 to VCPU sub-id (i.e. virtual HARTID) */
@@ -353,6 +363,8 @@ int arch_vcpu_init(struct vmm_vcpu *vcpu)

return VMM_OK;

+fail_free_timer:
+ cpu_vcpu_timer_deinit(vcpu);
fail_free_nested:
cpu_vcpu_nested_deinit(vcpu);
fail_free_isa:
@@ -386,6 +398,9 @@ int arch_vcpu_deinit(struct vmm_vcpu *vcpu)
return VMM_OK;
}

+ /* Cleanup SBI */
+ cpu_vcpu_sbi_deinit(vcpu);
+
/* Cleanup timer */
cpu_vcpu_timer_deinit(vcpu);

diff --git a/arch/riscv/cpu/generic/cpu_vcpu_sbi.c b/arch/riscv/cpu/generic/cpu_vcpu_sbi.c
index ebe34465..75440089 100644
--- a/arch/riscv/cpu/generic/cpu_vcpu_sbi.c
+++ b/arch/riscv/cpu/generic/cpu_vcpu_sbi.c
@@ -22,6 +22,7 @@
*/

#include <vmm_error.h>
+#include <vmm_heap.h>
#include <vmm_macros.h>
#include <vmm_manager.h>
#include <cpu_vcpu_sbi.h>
@@ -37,7 +38,7 @@ extern const struct cpu_vcpu_sbi_extension vcpu_sbi_srst;
extern const struct cpu_vcpu_sbi_extension vcpu_sbi_legacy;
extern const struct cpu_vcpu_sbi_extension vcpu_sbi_xvisor;

-static const struct cpu_vcpu_sbi_extension *vcpu_sbi[] = {
+static const struct cpu_vcpu_sbi_extension *sbi_exts[] = {
&vcpu_sbi_time,
&vcpu_sbi_rfence,
&vcpu_sbi_ipi,
@@ -48,15 +49,23 @@ static const struct cpu_vcpu_sbi_extension *vcpu_sbi[] = {
&vcpu_sbi_xvisor,
};

+struct cpu_vcpu_sbi {
+ const struct cpu_vcpu_sbi_extension **sbi_exts;
+};
+
const struct cpu_vcpu_sbi_extension *cpu_vcpu_sbi_find_extension(
+ struct vmm_vcpu *vcpu,
unsigned long ext_id)
{
int i;
-
- for (i = 0; i < array_size(vcpu_sbi); i++) {
- if (ext_id >= vcpu_sbi[i]->extid_start &&
- ext_id <= vcpu_sbi[i]->extid_end)
- return vcpu_sbi[i];
+ struct cpu_vcpu_sbi *s = riscv_sbi_priv(vcpu);
+
+ for (i = 0; i < array_size(sbi_exts); i++) {
+ if (!s->sbi_exts[i])
+ continue;
+ if (ext_id >= s->sbi_exts[i]->extid_start &&
+ ext_id <= s->sbi_exts[i]->extid_end)
+ return sbi_exts[i];
}

return NULL;
@@ -94,7 +103,7 @@ int cpu_vcpu_sbi_ecall(struct vmm_vcpu *vcpu, ulong cause,
args[4] = regs->a4;
args[5] = regs->a5;

- ext = cpu_vcpu_sbi_find_extension(extension_id);
+ ext = cpu_vcpu_sbi_find_extension(vcpu, extension_id);
if (ext && ext->handle) {
ret = ext->handle(vcpu, extension_id, func_id, args, &out);
if (extension_id >= SBI_EXT_0_1_SET_TIMER &&
@@ -124,6 +133,45 @@ int cpu_vcpu_sbi_ecall(struct vmm_vcpu *vcpu, ulong cause,
return 0;
}

+int cpu_vcpu_sbi_init(struct vmm_vcpu *vcpu)
+{
+ const struct cpu_vcpu_sbi_extension *ext;
+ struct cpu_vcpu_sbi *s;
+ int i;
+
+ s = vmm_zalloc(sizeof(*s));
+ if (!s)
+ return VMM_ENOMEM;
+
+ s->sbi_exts = vmm_calloc(array_size(sbi_exts),
+ sizeof(struct cpu_vcpu_sbi_extension *));
+ if (!s->sbi_exts) {
+ vmm_free(s);
+ return VMM_ENOMEM;
+ }
+
+ riscv_sbi_priv(vcpu) = s;
+
+ for (i = 0; i < array_size(sbi_exts); i++) {
+ ext = sbi_exts[i];
+
+ if (ext->probe && !ext->probe(vcpu))
+ continue;
+
+ s->sbi_exts[i] = ext;
+ }
+
+ return 0;
+}
+
+void cpu_vcpu_sbi_deinit(struct vmm_vcpu *vcpu)
+{
+ struct cpu_vcpu_sbi *s = riscv_sbi_priv(vcpu);
+
+ vmm_free(s->sbi_exts);
+ vmm_free(s);
+}
+
int cpu_vcpu_sbi_xlate_error(int xvisor_error)
{
switch (xvisor_error) {
diff --git a/arch/riscv/cpu/generic/cpu_vcpu_sbi_base.c b/arch/riscv/cpu/generic/cpu_vcpu_sbi_base.c
index e5b05da8..c7b1371e 100644
--- a/arch/riscv/cpu/generic/cpu_vcpu_sbi_base.c
+++ b/arch/riscv/cpu/generic/cpu_vcpu_sbi_base.c
@@ -58,7 +58,8 @@ static int vcpu_sbi_base_ecall(struct vmm_vcpu *vcpu, unsigned long ext_id,
out->value = hret.value;
break;
case SBI_EXT_BASE_PROBE_EXT:
- out->value = (cpu_vcpu_sbi_find_extension(args[0])) ? 1 : 0;
+ out->value = (cpu_vcpu_sbi_find_extension(vcpu, args[0])) ?
+ 1 : 0;
break;
default:
ret = SBI_ERR_NOT_SUPPORTED;
diff --git a/arch/riscv/cpu/generic/include/arch_regs.h b/arch/riscv/cpu/generic/include/arch_regs.h
index 3afa9faf..fa1973f7 100644
--- a/arch/riscv/cpu/generic/include/arch_regs.h
+++ b/arch/riscv/cpu/generic/include/arch_regs.h
@@ -232,6 +232,8 @@ struct riscv_priv {
union riscv_priv_fp fp;
/* Opaque pointer to timer data */
void *timer_priv;
+ /* Opaque pointer to SBI data */
+ void *sbi_priv;
};

struct riscv_guest_priv {
@@ -250,6 +252,7 @@ struct riscv_guest_priv {
#define riscv_nested_virt(vcpu) (riscv_nested_priv(vcpu)->virt)
#define riscv_fp_priv(vcpu) (&riscv_priv(vcpu)->fp)
#define riscv_timer_priv(vcpu) (riscv_priv(vcpu)->timer_priv)
+#define riscv_sbi_priv(vcpu) (riscv_priv(vcpu)->sbi_priv)
#define riscv_guest_priv(guest) ((struct riscv_guest_priv *)((guest)->arch_priv))
#define riscv_guest_serial(guest) (riscv_guest_priv(guest)->guest_serial)

diff --git a/arch/riscv/cpu/generic/include/cpu_vcpu_sbi.h b/arch/riscv/cpu/generic/include/cpu_vcpu_sbi.h
index 6802b5f6..002230c9 100644
--- a/arch/riscv/cpu/generic/include/cpu_vcpu_sbi.h
+++ b/arch/riscv/cpu/generic/include/cpu_vcpu_sbi.h
@@ -44,14 +44,20 @@ struct cpu_vcpu_sbi_extension {
int (*handle)(struct vmm_vcpu *vcpu, unsigned long ext_id,
unsigned long func_id, unsigned long *args,
struct cpu_vcpu_sbi_return *out);
+ unsigned long (*probe)(struct vmm_vcpu *vcpu);
};

const struct cpu_vcpu_sbi_extension *cpu_vcpu_sbi_find_extension(
+ struct vmm_vcpu *vcpu,
unsigned long ext_id);

int cpu_vcpu_sbi_ecall(struct vmm_vcpu *vcpu, ulong mcause,
arch_regs_t *regs);

+int cpu_vcpu_sbi_init(struct vmm_vcpu *vcpu);
+
+void cpu_vcpu_sbi_deinit(struct vmm_vcpu *vcpu);
+
int cpu_vcpu_sbi_xlate_error(int xvisor_error);

#endif
--
2.34.1

Anup Patel

unread,
Oct 30, 2023, 3:05:36 AM10/30/23
to xvisor...@googlegroups.com, Anup Patel
Users should have a way to diable SBI extensions (except the BASE
extension) for a particular Guest.

We extend the VCPU SBI emulation to disable SBI <xyz> extension
if "xvisor,disable-sbi-<xyz>" DT property is present in the
Guest VCPU DT node.

Signed-off-by: Anup Patel <apa...@ventanamicro.com>
---
arch/riscv/cpu/generic/cpu_vcpu_sbi.c | 11 +++++++++++
arch/riscv/cpu/generic/cpu_vcpu_sbi_base.c | 1 +
arch/riscv/cpu/generic/cpu_vcpu_sbi_hsm.c | 1 +
arch/riscv/cpu/generic/cpu_vcpu_sbi_legacy.c | 1 +
arch/riscv/cpu/generic/cpu_vcpu_sbi_replace.c | 4 ++++
arch/riscv/cpu/generic/cpu_vcpu_sbi_xvisor.c | 1 +
arch/riscv/cpu/generic/include/cpu_vcpu_sbi.h | 1 +
7 files changed, 20 insertions(+)

diff --git a/arch/riscv/cpu/generic/cpu_vcpu_sbi.c b/arch/riscv/cpu/generic/cpu_vcpu_sbi.c
index 75440089..6b350d77 100644
--- a/arch/riscv/cpu/generic/cpu_vcpu_sbi.c
+++ b/arch/riscv/cpu/generic/cpu_vcpu_sbi.c
@@ -25,6 +25,7 @@
#include <vmm_heap.h>
#include <vmm_macros.h>
#include <vmm_manager.h>
+#include <vmm_stdio.h>
#include <cpu_vcpu_sbi.h>
#include <cpu_vcpu_trap.h>
#include <riscv_sbi.h>
@@ -137,6 +138,7 @@ int cpu_vcpu_sbi_init(struct vmm_vcpu *vcpu)
{
const struct cpu_vcpu_sbi_extension *ext;
struct cpu_vcpu_sbi *s;
+ char aname[32];
int i;

s = vmm_zalloc(sizeof(*s));
@@ -158,6 +160,15 @@ int cpu_vcpu_sbi_init(struct vmm_vcpu *vcpu)
if (ext->probe && !ext->probe(vcpu))
continue;

+ /* Non-base extensions can be disabled via DT */
+ if (SBI_EXT_BASE < ext->extid_start ||
+ ext->extid_end < SBI_EXT_BASE) {
+ vmm_snprintf(aname, sizeof(aname),
+ "xvisor,disable-sbi-%s", ext->name);
+ if (vmm_devtree_getattr(vcpu->node, aname))
+ continue;
+ }
+
s->sbi_exts[i] = ext;
}

diff --git a/arch/riscv/cpu/generic/cpu_vcpu_sbi_base.c b/arch/riscv/cpu/generic/cpu_vcpu_sbi_base.c
index c7b1371e..d5d10a0a 100644
--- a/arch/riscv/cpu/generic/cpu_vcpu_sbi_base.c
+++ b/arch/riscv/cpu/generic/cpu_vcpu_sbi_base.c
@@ -69,6 +69,7 @@ static int vcpu_sbi_base_ecall(struct vmm_vcpu *vcpu, unsigned long ext_id,
}

const struct cpu_vcpu_sbi_extension vcpu_sbi_base = {
+ .name = "base",
.extid_start = SBI_EXT_BASE,
.extid_end = SBI_EXT_BASE,
.handle = vcpu_sbi_base_ecall,
diff --git a/arch/riscv/cpu/generic/cpu_vcpu_sbi_hsm.c b/arch/riscv/cpu/generic/cpu_vcpu_sbi_hsm.c
index f3e54d1c..f779a4e2 100644
--- a/arch/riscv/cpu/generic/cpu_vcpu_sbi_hsm.c
+++ b/arch/riscv/cpu/generic/cpu_vcpu_sbi_hsm.c
@@ -93,6 +93,7 @@ static int vcpu_sbi_hsm_ecall(struct vmm_vcpu *vcpu, unsigned long ext_id,
}

const struct cpu_vcpu_sbi_extension vcpu_sbi_hsm = {
+ .name = "hsm",
.extid_start = SBI_EXT_HSM,
.extid_end = SBI_EXT_HSM,
.handle = vcpu_sbi_hsm_ecall,
diff --git a/arch/riscv/cpu/generic/cpu_vcpu_sbi_legacy.c b/arch/riscv/cpu/generic/cpu_vcpu_sbi_legacy.c
index 42279718..96804781 100644
--- a/arch/riscv/cpu/generic/cpu_vcpu_sbi_legacy.c
+++ b/arch/riscv/cpu/generic/cpu_vcpu_sbi_legacy.c
@@ -134,6 +134,7 @@ static int vcpu_sbi_legacy_ecall(struct vmm_vcpu *vcpu, unsigned long ext_id,
}

const struct cpu_vcpu_sbi_extension vcpu_sbi_legacy = {
+ .name = "legacy",
.extid_start = SBI_EXT_0_1_SET_TIMER,
.extid_end = SBI_EXT_0_1_SHUTDOWN,
.handle = vcpu_sbi_legacy_ecall,
diff --git a/arch/riscv/cpu/generic/cpu_vcpu_sbi_replace.c b/arch/riscv/cpu/generic/cpu_vcpu_sbi_replace.c
index 6bdcdb22..37157109 100644
--- a/arch/riscv/cpu/generic/cpu_vcpu_sbi_replace.c
+++ b/arch/riscv/cpu/generic/cpu_vcpu_sbi_replace.c
@@ -50,6 +50,7 @@ static int vcpu_sbi_time_ecall(struct vmm_vcpu *vcpu, unsigned long ext_id,
}

const struct cpu_vcpu_sbi_extension vcpu_sbi_time = {
+ .name = "time",
.extid_start = SBI_EXT_TIME,
.extid_end = SBI_EXT_TIME,
.handle = vcpu_sbi_time_ecall,
@@ -156,6 +157,7 @@ static int vcpu_sbi_rfence_ecall(struct vmm_vcpu *vcpu, unsigned long ext_id,
}

const struct cpu_vcpu_sbi_extension vcpu_sbi_rfence = {
+ .name = "rfence",
.extid_start = SBI_EXT_RFENCE,
.extid_end = SBI_EXT_RFENCE,
.handle = vcpu_sbi_rfence_ecall,
@@ -189,6 +191,7 @@ static int vcpu_sbi_ipi_ecall(struct vmm_vcpu *vcpu, unsigned long ext_id,
}

const struct cpu_vcpu_sbi_extension vcpu_sbi_ipi = {
+ .name = "ipi",
.extid_start = SBI_EXT_IPI,
.extid_end = SBI_EXT_IPI,
.handle = vcpu_sbi_ipi_ecall,
@@ -234,6 +237,7 @@ static int vcpu_sbi_srst_ecall(struct vmm_vcpu *vcpu, unsigned long ext_id,
}

const struct cpu_vcpu_sbi_extension vcpu_sbi_srst = {
+ .name = "srst",
.extid_start = SBI_EXT_SRST,
.extid_end = SBI_EXT_SRST,
.handle = vcpu_sbi_srst_ecall,
diff --git a/arch/riscv/cpu/generic/cpu_vcpu_sbi_xvisor.c b/arch/riscv/cpu/generic/cpu_vcpu_sbi_xvisor.c
index 3a4b20e9..aebf5f8b 100644
--- a/arch/riscv/cpu/generic/cpu_vcpu_sbi_xvisor.c
+++ b/arch/riscv/cpu/generic/cpu_vcpu_sbi_xvisor.c
@@ -57,6 +57,7 @@ static int vcpu_sbi_xvisor_ecall(struct vmm_vcpu *vcpu, unsigned long ext_id,
}

const struct cpu_vcpu_sbi_extension vcpu_sbi_xvisor = {
+ .name = "xvisor",
.extid_start = SBI_EXT_XVISOR,
.extid_end = SBI_EXT_XVISOR,
.handle = vcpu_sbi_xvisor_ecall,
diff --git a/arch/riscv/cpu/generic/include/cpu_vcpu_sbi.h b/arch/riscv/cpu/generic/include/cpu_vcpu_sbi.h
index 002230c9..442ff01f 100644
--- a/arch/riscv/cpu/generic/include/cpu_vcpu_sbi.h
+++ b/arch/riscv/cpu/generic/include/cpu_vcpu_sbi.h
@@ -39,6 +39,7 @@ struct cpu_vcpu_sbi_return {
};

struct cpu_vcpu_sbi_extension {
+ const char name[16];
unsigned long extid_start;
unsigned long extid_end;
int (*handle)(struct vmm_vcpu *vcpu, unsigned long ext_id,
--
2.34.1

Anup Patel

unread,
Oct 30, 2023, 3:05:37 AM10/30/23
to xvisor...@googlegroups.com, Anup Patel
The SBI v2.0 specificaiton is frozen so let us change the SBI
specification version to v2.0 for guest.

Signed-off-by: Anup Patel <apa...@ventanamicro.com>
---
arch/riscv/cpu/generic/include/cpu_vcpu_sbi.h | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/arch/riscv/cpu/generic/include/cpu_vcpu_sbi.h b/arch/riscv/cpu/generic/include/cpu_vcpu_sbi.h
index 442ff01f..2a704bcd 100644
--- a/arch/riscv/cpu/generic/include/cpu_vcpu_sbi.h
+++ b/arch/riscv/cpu/generic/include/cpu_vcpu_sbi.h
@@ -28,7 +28,7 @@
struct vmm_vcpu;
struct cpu_vcpu_trap;

-#define CPU_VCPU_SBI_VERSION_MAJOR 1
+#define CPU_VCPU_SBI_VERSION_MAJOR 2
#define CPU_VCPU_SBI_VERSION_MINOR 0
#define CPU_VCPU_SBI_IMPID 2

--
2.34.1

Anup Patel

unread,
Oct 30, 2023, 3:05:38 AM10/30/23
to xvisor...@googlegroups.com, Anup Patel
Let us add SBI debug console extension related defines to the
riscv_sbi.h header.

Signed-off-by: Anup Patel <apa...@ventanamicro.com>
---
arch/riscv/cpu/generic/include/riscv_sbi.h | 6 ++++++
1 file changed, 6 insertions(+)

diff --git a/arch/riscv/cpu/generic/include/riscv_sbi.h b/arch/riscv/cpu/generic/include/riscv_sbi.h
index eadd6bc9..fd3f4425 100644
--- a/arch/riscv/cpu/generic/include/riscv_sbi.h
+++ b/arch/riscv/cpu/generic/include/riscv_sbi.h
@@ -43,6 +43,7 @@
#define SBI_EXT_HSM 0x48534D
#define SBI_EXT_SRST 0x53525354
#define SBI_EXT_PMU 0x504D55
+#define SBI_EXT_DBCN 0x4442434E

/* SBI function IDs for BASE extension */
#define SBI_EXT_BASE_GET_SPEC_VERSION 0x0
@@ -238,6 +239,11 @@ enum sbi_pmu_ctr_type {
/* Flags defined for counter stop function */
#define SBI_PMU_STOP_FLAG_RESET (1 << 0)

+/* SBI function IDs for PMU extension */
+#define SBI_EXT_DBCN_CONSOLE_WRITE 0x0
+#define SBI_EXT_DBCN_CONSOLE_READ 0x1
+#define SBI_EXT_DBCN_CONSOLE_WRITE_BYTE 0x2
+
/* SBI base specification related macros */
#define SBI_SPEC_VERSION_MAJOR_SHIFT 24
#define SBI_SPEC_VERSION_MAJOR_MASK 0x7f
--
2.34.1

Anup Patel

unread,
Oct 30, 2023, 3:05:40 AM10/30/23
to xvisor...@googlegroups.com, Anup Patel
We add SBI_SPEC_MK_VERSION() helper macro which can be used to
create encoded SBI spec version from major and minor number.

Signed-off-by: Anup Patel <apa...@ventanamicro.com>
---
arch/riscv/cpu/generic/include/riscv_sbi.h | 4 ++++
1 file changed, 4 insertions(+)

diff --git a/arch/riscv/cpu/generic/include/riscv_sbi.h b/arch/riscv/cpu/generic/include/riscv_sbi.h
index fd3f4425..fc621afb 100644
--- a/arch/riscv/cpu/generic/include/riscv_sbi.h
+++ b/arch/riscv/cpu/generic/include/riscv_sbi.h
@@ -253,6 +253,10 @@ enum sbi_pmu_ctr_type {
#define SBI_EXT_FIRMWARE_START 0x0A000000
#define SBI_EXT_FIRMWARE_END 0x0AFFFFFF

+#define SBI_SPEC_MK_VERSION(__major, __minor) \
+((((__major) & SBI_SPEC_VERSION_MAJOR_MASK) << \
+ SBI_SPEC_VERSION_MAJOR_SHIFT) | (__minor))
+
/* SBI return error codes */
#define SBI_SUCCESS 0
#define SBI_ERR_FAILED -1
--
2.34.1

Anup Patel

unread,
Oct 30, 2023, 3:05:43 AM10/30/23
to xvisor...@googlegroups.com, Anup Patel
The legacy SBI v0.1 console getchar() and putchar() will be deprecated
in-favor of SBI v2.0 debug console extension so let's use SBI debug
console whenever underlying SBI implementation provides it.

Signed-off-by: Anup Patel <apa...@ventanamicro.com>
---
arch/riscv/cpu/generic/cpu_sbi.c | 43 ++++++++++++++++++++++++++++----
1 file changed, 38 insertions(+), 5 deletions(-)

diff --git a/arch/riscv/cpu/generic/cpu_sbi.c b/arch/riscv/cpu/generic/cpu_sbi.c
index 36c1cc9b..140a587c 100644
--- a/arch/riscv/cpu/generic/cpu_sbi.c
+++ b/arch/riscv/cpu/generic/cpu_sbi.c
@@ -24,6 +24,7 @@
#include <vmm_error.h>
#include <vmm_compiler.h>
#include <vmm_cpumask.h>
+#include <vmm_host_aspace.h>
#include <vmm_smp.h>
#include <vmm_stdio.h>
#include <vmm_main.h>
@@ -98,18 +99,45 @@ void sbi_cpumask_to_hartmask(const struct vmm_cpumask *cmask,
}
}

+static bool sbi_dbcn_avail;
+static u8 sbi_dbcn_read_char;
+static physical_addr_t sbi_dbcn_read_pa;
+
void sbi_console_putchar(int ch)
{
- sbi_ecall(SBI_EXT_0_1_CONSOLE_PUTCHAR, 0, ch, 0, 0, 0, 0, 0);
+ if (!sbi_dbcn_avail) {
+ sbi_ecall(SBI_EXT_0_1_CONSOLE_PUTCHAR, 0, ch, 0, 0, 0, 0, 0);
+ return;
+ }
+
+ sbi_ecall(SBI_EXT_DBCN, SBI_EXT_DBCN_CONSOLE_WRITE_BYTE, ch,
+ 0, 0, 0, 0, 0);
}

int sbi_console_getchar(void)
{
struct sbiret ret;

- ret = sbi_ecall(SBI_EXT_0_1_CONSOLE_GETCHAR, 0, 0, 0, 0, 0, 0, 0);
+ if (!sbi_dbcn_avail) {
+ ret = sbi_ecall(SBI_EXT_0_1_CONSOLE_GETCHAR,
+ 0, 0, 0, 0, 0, 0, 0);
+ return ret.error;
+ }
+
+ sbi_dbcn_read_char = 0;
+ ret = sbi_ecall(SBI_EXT_DBCN, SBI_EXT_DBCN_CONSOLE_READ,
+#ifdef CONFIG_64BIT
+ sbi_dbcn_read_pa, 0,
+#else
+ (u64)sbi_dbcn_read_pa, ((u64)sbi_dbcn_read_pa) >> 32,
+#endif
+ 0, 0, 0, 0);
+ if (ret.error)
+ return sbi_err_map_xvisor_errno(ret.error);
+ if (!ret.value)
+ return VMM_ENOENT;

- return ret.error;
+ return sbi_dbcn_read_char;
}

int sbi_shutdown(void)
@@ -470,8 +498,8 @@ static int sbi_defterm_getc(u8 *ch)

static int sbi_defterm_init(struct vmm_devtree_node *node)
{
- /* Nothing to do here. */
- return VMM_OK;
+ return vmm_host_va2pa((virtual_addr_t)&sbi_dbcn_read_char,
+ &sbi_dbcn_read_pa);
}

static struct defterm_ops sbi_defterm_ops = {
@@ -535,6 +563,11 @@ int __init sbi_init(void)
vmm_register_system_reset(sbi_srst_reset);
vmm_init_printf("SBI SRST extension detected\n");
}
+ if (sbi_spec_version == SBI_SPEC_MK_VERSION(2, 0) &&
+ sbi_probe_extension(SBI_EXT_DBCN) > 0) {
+ sbi_dbcn_avail = TRUE;
+ vmm_init_printf("SBI DBCN extension detected\n");
+ }
} else {
vmm_register_system_shutdown(sbi_shutdown);
}
--
2.34.1

Anup Patel

unread,
Oct 30, 2023, 3:05:44 AM10/30/23
to xvisor...@googlegroups.com, Anup Patel
Currently, we try to locate guest vserial instance under the
guest DT chosen node. Unfortunately, there is no chosen node
in the guest DT so guest vserial instance is never found.

To fix the above issue, let us pick the first vserial instance
having guest name as prefix to it's name.

Signed-off-by: Anup Patel <apa...@ventanamicro.com>
---
arch/riscv/cpu/generic/cpu_vcpu_helper.c | 44 ++++---------------
.../cpu/generic/include/cpu_guest_serial.h | 4 +-
2 files changed, 12 insertions(+), 36 deletions(-)

diff --git a/arch/riscv/cpu/generic/cpu_vcpu_helper.c b/arch/riscv/cpu/generic/cpu_vcpu_helper.c
index dd82a255..2ca54fb3 100644
--- a/arch/riscv/cpu/generic/cpu_vcpu_helper.c
+++ b/arch/riscv/cpu/generic/cpu_vcpu_helper.c
@@ -58,43 +58,24 @@
riscv_isa_extension_mask(h) | \
riscv_isa_extension_mask(SSTC))

-static char *guest_fdt_find_serial_node(char *guest_name)
-{
- char *serial = NULL;
- char chosen_node_path[VMM_FIELD_NAME_SIZE];
- struct vmm_devtree_node *chosen_node;
-
- /* Process attributes in chosen node */
- vmm_snprintf(chosen_node_path, sizeof(chosen_node_path), "/%s/%s/%s",
- VMM_DEVTREE_GUESTINFO_NODE_NAME, guest_name,
- VMM_DEVTREE_CHOSEN_NODE_NAME);
- chosen_node = vmm_devtree_getnode(chosen_node_path);
- if (chosen_node) {
- /* Process console device passed via chosen node */
- vmm_devtree_read_string(chosen_node,
- VMM_DEVTREE_STDOUT_ATTR_NAME,
- (const char **)&serial);
- }
- vmm_devtree_dref_node(chosen_node);
-
- return serial;
-}
-
static int guest_vserial_notification(struct vmm_notifier_block *nb,
unsigned long evt, void *data)
{
int ret = NOTIFY_OK;
struct vmm_vserial_event *e = data;
- struct riscv_guest_serial *gserial = container_of(nb,
+ struct riscv_guest_serial *gs = container_of(nb,
struct riscv_guest_serial,
vser_client);
if (evt == VMM_VSERIAL_EVENT_CREATE) {
- if (!strcmp(e->vser->name, gserial->name)) {
- gserial->vserial = e->vser;
+ if (!gs->vserial &&
+ !strncmp(e->vser->name, gs->guest->name,
+ strlen(gs->guest->name))) {
+ gs->vserial = e->vser;
}
} else if (evt == VMM_VSERIAL_EVENT_DESTROY) {
- if (!strcmp(e->vser->name, gserial->name))
- gserial->vserial = NULL;
+ if (e->vser == gs->vserial) {
+ gs->vserial = NULL;
+ }
} else
ret = NOTIFY_DONE;
return ret;
@@ -105,7 +86,6 @@ int arch_guest_init(struct vmm_guest *guest)
struct riscv_guest_priv *priv;
struct riscv_guest_serial *gserial;
u32 pgtbl_attr, pgtbl_hw_tag;
- char *sname;
int rc;

if (!guest->reset_count) {
@@ -144,13 +124,7 @@ int arch_guest_init(struct vmm_guest *guest)
}

gserial = riscv_guest_serial(guest);
- sname = guest_fdt_find_serial_node(guest->name);
- if (sname) {
- strlcpy(gserial->name, guest->name,
- sizeof(gserial->name));
- strlcat(gserial->name, "/", sizeof(gserial->name));
- strlcat(gserial->name, sname, sizeof(gserial->name));
- }
+ gserial->guest = guest;
gserial->vser_client.notifier_call = &guest_vserial_notification;
gserial->vser_client.priority = 0;
rc = vmm_vserial_register_client(&gserial->vser_client);
diff --git a/arch/riscv/cpu/generic/include/cpu_guest_serial.h b/arch/riscv/cpu/generic/include/cpu_guest_serial.h
index 8d7acbee..743ccf93 100644
--- a/arch/riscv/cpu/generic/include/cpu_guest_serial.h
+++ b/arch/riscv/cpu/generic/include/cpu_guest_serial.h
@@ -27,8 +27,10 @@
#include <vio/vmm_vserial.h>
#include <vmm_notifier.h>

+struct vmm_guest;
+
struct riscv_guest_serial {
- char name[VMM_FIELD_NAME_SIZE];
+ struct vmm_guest *guest;
struct vmm_notifier_block vser_client;
struct vmm_vserial *vserial;
};
--
2.34.1

Anup Patel

unread,
Oct 30, 2023, 3:05:46 AM10/30/23
to xvisor...@googlegroups.com, Anup Patel
The frozen SBI v2.0 specification defines SBI debug console extension
which replaces the legacy SBI v0.1 getchar() and putchar() functions.

Let us implement SBI debug console extension for Guest.

Signed-off-by: Anup Patel <apa...@ventanamicro.com>
---
arch/riscv/cpu/generic/cpu_vcpu_sbi.c | 2 +
arch/riscv/cpu/generic/cpu_vcpu_sbi_replace.c | 70 +++++++++++++++++++
2 files changed, 72 insertions(+)

diff --git a/arch/riscv/cpu/generic/cpu_vcpu_sbi.c b/arch/riscv/cpu/generic/cpu_vcpu_sbi.c
index 6b350d77..c11cd9fe 100644
--- a/arch/riscv/cpu/generic/cpu_vcpu_sbi.c
+++ b/arch/riscv/cpu/generic/cpu_vcpu_sbi.c
@@ -35,6 +35,7 @@ extern const struct cpu_vcpu_sbi_extension vcpu_sbi_rfence;
extern const struct cpu_vcpu_sbi_extension vcpu_sbi_ipi;
extern const struct cpu_vcpu_sbi_extension vcpu_sbi_base;
extern const struct cpu_vcpu_sbi_extension vcpu_sbi_hsm;
+extern const struct cpu_vcpu_sbi_extension vcpu_sbi_dbcn;
extern const struct cpu_vcpu_sbi_extension vcpu_sbi_srst;
extern const struct cpu_vcpu_sbi_extension vcpu_sbi_legacy;
extern const struct cpu_vcpu_sbi_extension vcpu_sbi_xvisor;
@@ -45,6 +46,7 @@ static const struct cpu_vcpu_sbi_extension *sbi_exts[] = {
&vcpu_sbi_ipi,
&vcpu_sbi_base,
&vcpu_sbi_hsm,
+ &vcpu_sbi_dbcn,
&vcpu_sbi_srst,
&vcpu_sbi_legacy,
&vcpu_sbi_xvisor,
diff --git a/arch/riscv/cpu/generic/cpu_vcpu_sbi_replace.c b/arch/riscv/cpu/generic/cpu_vcpu_sbi_replace.c
index 37157109..caef5c26 100644
--- a/arch/riscv/cpu/generic/cpu_vcpu_sbi_replace.c
+++ b/arch/riscv/cpu/generic/cpu_vcpu_sbi_replace.c
@@ -22,10 +22,13 @@
*/

#include <vmm_error.h>
+#include <vmm_guest_aspace.h>
#include <vmm_macros.h>
#include <vmm_manager.h>
#include <vmm_stdio.h>
#include <vmm_vcpu_irq.h>
+#include <vio/vmm_vserial.h>
+#include <cpu_guest_serial.h>
#include <cpu_sbi.h>
#include <cpu_vcpu_sbi.h>
#include <cpu_vcpu_timer.h>
@@ -242,3 +245,70 @@ const struct cpu_vcpu_sbi_extension vcpu_sbi_srst = {
.extid_end = SBI_EXT_SRST,
.handle = vcpu_sbi_srst_ecall,
};
+
+#define DBCN_BUF_SIZE 256
+
+static int vcpu_sbi_dbcn_ecall(struct vmm_vcpu *vcpu, unsigned long ext_id,
+ unsigned long func_id, unsigned long *args,
+ struct cpu_vcpu_sbi_return *out)
+{
+ struct riscv_guest_serial *gs = riscv_guest_serial(vcpu->guest);
+ int ret = SBI_SUCCESS;
+ u8 buf[DBCN_BUF_SIZE];
+ unsigned long len;
+
+ switch (func_id) {
+ case SBI_EXT_DBCN_CONSOLE_WRITE:
+ case SBI_EXT_DBCN_CONSOLE_READ:
+ /*
+ * On RV32, the M-mode can only access the first 4GB of
+ * the physical address space because M-mode does not have
+ * MMU to access full 34-bit physical address space.
+ *
+ * Based on above, we simply fail if the upper 32bits of
+ * the physical address (i.e. a2 register) is non-zero on
+ * RV32.
+ *
+ * Analogously, we fail if the upper 64bit of the
+ * physical address (i.e. a2 register) is non-zero on
+ * RV64.
+ */
+ if (args[2]) {
+ ret = SBI_ERR_FAILED;
+ break;
+ }
+
+ len = (DBCN_BUF_SIZE < args[0]) ? DBCN_BUF_SIZE : args[0];
+ if (func_id == SBI_EXT_DBCN_CONSOLE_WRITE) {
+ len = vmm_guest_memory_read(vcpu->guest, args[1],
+ buf, len, TRUE);
+ out->value = vmm_vserial_receive(gs->vserial, buf, len);
+ } else {
+ /*
+ * We don't support read operation because Guest
+ * always has a proper console with read/write
+ * support.
+ */
+ ret = SBI_ERR_DENIED;
+ }
+ break;
+ case SBI_EXT_DBCN_CONSOLE_WRITE_BYTE:
+ buf[0] = (u8)args[0];
+ if (!vmm_vserial_receive(gs->vserial, buf, 1))
+ ret = SBI_ERR_FAILED;
+ out->value = 0;
+ break;
+ default:
+ ret = SBI_ERR_NOT_SUPPORTED;
+ break;
+ }
+
+ return ret;
+}
+
+const struct cpu_vcpu_sbi_extension vcpu_sbi_dbcn = {
+ .name = "dbcn",
+ .extid_start = SBI_EXT_DBCN,
+ .extid_end = SBI_EXT_DBCN,
+ .handle = vcpu_sbi_dbcn_ecall,
+};
--
2.34.1

Anup Patel

unread,
Nov 16, 2023, 6:59:44 AM11/16/23
to xvisor...@googlegroups.com, Anup Patel
On Mon, Oct 30, 2023 at 12:35 PM Anup Patel <apa...@ventanamicro.com> wrote:
>
> This series add SBI debug console support for both host and guest
> in Xvisor RISC-V.
>
> These patches can also be found in the riscv_sbi_dbcn_v1 branch at:
> https://github.com/avpatel/xvisor-next.git
>
> Anup Patel (11):
> DOCS: Update qemu-system-riscv[64|32] usage in README files
> RISC-V: Improve timer init and deinit function
> RISC-V: Rename cpu_vcpu_fp_init() to cpu_vcpu_fp_reset()
> RISC-V: Add option probe() callback for VCPU SBI extensions
> RISC-V: Allow disabling SBI extensions based on Guest DT
> RISC-V: Change the SBI specification version to v2.0 for guest
> RISC-V: Add defines for SBI debug console extension
> RISC-V: Add SBI_SPEC_MK_VERSION() helper macro
> RISC-V: Use SBI debug console for defterm whenever available
> RISC-V: Fix how guest vserial instance is located
> RISC-V: Implement SBI debug console extension for Guest

Applied this series to the xvisor-next repo.

Thanks,
Anup
> --
> You received this message because you are subscribed to the Google Groups "Xvisor Development" group.
> To unsubscribe from this group and stop receiving emails from it, send an email to xvisor-devel...@googlegroups.com.
> To view this discussion on the web visit https://groups.google.com/d/msgid/xvisor-devel/20231030070513.61766-1-apatel%40ventanamicro.com.
Reply all
Reply to author
Forward
0 new messages