I can't set correctly shared memory for Qemu RISCV emulation.
My intention is to create a portion of shared memory between Qemu RISCV emulator and the host server. I need this because my intention will be then to interface Qemu with a FPGA and probably this is best method (for the best I have understood).
But anyway, I think I'm not able to do it.
This is the command I use for running the emulation:
qemu-system-riscv64 -M 'virt' \
-cpu 'rv64' -smp 4 -m 4096 \
-object memory-backend-file,size=1G,share=on,mem-path=/dev/shm,id=hostmem \
-device virtio-blk-device,drive=hd \
-drive file=/home/user/qemu/db-riscv64/image.qcow2,if=none,id=hd \
-device virtio-net-device,netdev=net \
-netdev user,id=net,hostfwd=tcp::2222-:22 \
-bios /usr/share/qemu/opensbi-riscv64-generic-fw_dynamic.bin \
-kernel /home/user/qemu/db-riscv64/kernel \
-initrd /home/user/qemu/db-riscv64/initrd \
-nographic -append "root=LABEL=rootfs console=ttyS0"
I'm trying to allocate 1G of shared memory on /dev/shm (RAM is faster). So my first step would be to make the host and Qemu communicate through /dev/shm, but I'm not able for instance to write something on the host and read from Qemu, and viceversa.
I tried with another folder with
-virtfs local,path=/home/user/qemu/db-riscv64 shared_memory,mount_tag=shared,security_model=none,id=hostshare and I was able to read and write from host to Qemu.
Could anyone kindly tell me what's wrong with these stuff?
I premise that it is the first time I use Qemu and it is not too clear to me how to use shared memory with that.
EDIT:
I solved by means of ivshmem as suggested, but now I have another problem.
The command for running qemu is now the following:
qemu-system-riscv64 -M 'virt' \
-cpu 'rv64' -smp 4 -m 4096 \
-object memory-backend-file,size=1G,share=on,mem-path=/dev/shm,id=hostmem \
-device ivshmem-plain,memdev=hostmem \
-device virtio-blk-device,drive=hd \
-drive file=/home/user/qemu/db-riscv64/image.qcow2,if=none,id=hd \
-device virtio-net-device,netdev=net \
-netdev user,id=net,hostfwd=tcp::2222-:22 \
-bios /usr/share/qemu/opensbi-riscv64-generic-fw_dynamic.bin \
-kernel /home/user/qemu/db-riscv64/kernel \
-initrd /home/user/qemu/db-riscv64/initrd \
-virtfs local,path=/home/user/qemu/db-riscv64/shared_folder,mount_tag=shared,security_model=none,id=hostshare \
-nographic -append "root=LABEL=rootfs console=ttyS0"
Using lspci -vv I obtain:
00:00.0 Host bridge: Red Hat, Inc. QEMU PCIe Host bridge
Subsystem: Red Hat, Inc. Device 1100
Control: I/O- Mem- BusMaster- SpecCycle- MemWINV- VGASnoop- ParErr- Stepping- SERR- FastB2B- DisINTx-
Status: Cap- 66MHz- UDF- FastB2B- ParErr- DEVSEL=fast >TAbort- <TAbort- <MAbort- >SERR- <PERR- INTx-
00:01.0 RAM memory: Red Hat, Inc. Inter-VM shared memory (rev 01)
Subsystem: Red Hat, Inc. QEMU Virtual Machine
Control: I/O- Mem+ BusMaster- SpecCycle- MemWINV- VGASnoop- ParErr- Stepping- SERR- FastB2B- DisINTx-
Status: Cap- 66MHz- UDF- FastB2B- ParErr- DEVSEL=fast >TAbort- <TAbort- <MAbort- >SERR- <PERR- INTx-
Region 0: Memory at 40001000 (32-bit, non-prefetchable) [size=256]
Region 2: Memory at 400000000 (64-bit, prefetchable) [size=1G]
00:02.0 Unclassified device [0002]: Red Hat, Inc. Virtio filesystem
Subsystem: Red Hat, Inc. Device 0009
Control: I/O+ Mem+ BusMaster+ SpecCycle- MemWINV- VGASnoop- ParErr- Stepping- SERR- FastB2B- DisINTx-
Status: Cap+ 66MHz- UDF- FastB2B- ParErr- DEVSEL=fast >TAbort- <TAbort- <MAbort- >SERR- <PERR- INTx-
Latency: 0
Interrupt: pin A routed to IRQ 12
Region 0: I/O ports at 0020 [size=32]
Region 1: Memory at 40000000 (32-bit, non-prefetchable) [size=4K]
Region 4: Memory at 440000000 (64-bit, prefetchable) [size=16K]
Capabilities: <access denied>
Kernel driver in use: virtio-pci
So now I want to execute this C code on the riscv VM:
#include <sys/mman.h>
#include <fcntl.h>
#include <stdio.h>
#include <unistd.h>
#include <stdint.h>
#define SHM_SIZE 4096 // size of the shared memory region to map
#define SHM_BAR 0x400000000 // BAR address of the ivshmem device (obtained from lspci)
void write_to_shared_memory(){
volatile uint32_t *shm = (volatile uint32_t *)SHM_BAR;
shm[0] = 1234;
printf("Written Data: %d\n", shm[0]);
}
int main() {
int fd = open("/dev/mem", O_RDWR); // open the /dev/mem device file
if (fd == -1) {
perror("open");
return -1;
}
void *shm = mmap(NULL, SHM_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, fd, SHM_BAR); // map the BAR address to shm
if (shm == MAP_FAILED) {
perror("mmap");
return -1;
}
// do something with shm, such as reading or writing data
write_to_shared_memory();
munmap(shm, SHM_SIZE); // unmap the shared memory region
close(fd); // close the /dev/mem device file
return 0;
}
But I get segmentation fault:
[11086.441459] memory_sharing[475]: unhandled signal 11 code 0x1 at 0x0000000400000000 in memory_sharing[5555571d8000+1000]
[11086.441834] CPU: 1 PID: 475 Comm: memory_sharing Not tainted 6.8.12-riscv64 #1 Debian 6.8.12-1
[11086.442040] Hardware name: riscv-virtio,qemu (DT)
[11086.442156] epc : 00005555571d87ee ra : 00005555571d8880 sp : 00007ffff7628a90
[11086.442324] gp : 00005555571da838 tp : 00007fff970193c0 t0 : 000000007c9ab170
[11086.442493] t1 : 00007fff96f6fae8 t2 : 0000000001f26ac5 s0 : 00007ffff7628ab0
[11086.442664] s1 : 0000000000000001 a0 : 00007fff9701b000 a1 : 0000000000001000
[11086.442833] a2 : 0000000000000003 a3 : 0000000000000001 a4 : 00000000000004d2
[11086.443004] a5 : 0000000400000000 a6 : 0000000000000000 a7 : 00000000000000de
[11086.443174] s2 : 0000000000000000 s3 : 00005555571d9de0 s4 : 00005555571d8810
[11086.443346] s5 : 00007ffff7628c68 s6 : 00005555571d9de0 s7 : 00007fff97040d20
[11086.443516] s8 : 00007fff97041000 s9 : 00007fffe9dd7420 s10: 0000000000000001
[11086.443680] s11: ffffffffffffffff t3 : 0000000000000030 t4 : 0000000000000000
[11086.443841] t5 : 00007fff97042270 t6 : 00007fff97018548
[11086.443966] status: 8000000200006020 badaddr: 0000000400000000 cause: 000000000000000f
[11086.444170] Code: e822 1000 4785 178a 3423 fef4 3783 fe84 0713 4d20 (c398) 3783
Segmentation fault
Does anyone know what's happening here?