summaryrefslogtreecommitdiffstats
path: root/tools
diff options
context:
space:
mode:
Diffstat (limited to 'tools')
-rwxr-xr-xtools/guest-diag/launch_qemu_rootport.sh2
-rw-r--r--tools/test/gpage_test.c110
2 files changed, 111 insertions, 1 deletions
diff --git a/tools/guest-diag/launch_qemu_rootport.sh b/tools/guest-diag/launch_qemu_rootport.sh
index 52728bd..963496a 100755
--- a/tools/guest-diag/launch_qemu_rootport.sh
+++ b/tools/guest-diag/launch_qemu_rootport.sh
@@ -1,2 +1,2 @@
#!/bin/bash
-exec /bin/qemu-system-x86_64 -D /home/rmcore/.local/libvf.io/logs/qemu/e726ba0b-204f-4ec9-91da-983ed7f41d06-session.txt -no-hpet -mem-prealloc -qmp unix:/tmp/qemu-qmp.sock,server,nowait -chardev socket,path=/tmp/qemu-guest-agent.sock,server=on,wait=off,id=qga0 -device virtio-serial-pci -device virtserialport,chardev=qga0,name=org.qemu.guest_agent.0 -serial file:/tmp/vgpu-guest-serial.log -gdb tcp::1234 -display none -device ivshmem-plain,id=shmem0,memdev=ivshmem_kvmfr -object memory-backend-file,id=ivshmem_kvmfr,mem-path=/dev/shm/kvmfr-e726ba0b-204f-4ec9-91da-983ed7f41d06,size=128M,share=yes -device ivshmem-plain,id=shmem1,memdev=ivshmem_kvmsr -object memory-backend-file,id=ivshmem_kvmsr,mem-path=/dev/shm/kvmsr-e726ba0b-204f-4ec9-91da-983ed7f41d06,size=2M,share=yes -uuid e726ba0b-204f-4ec9-91da-983ed7f41d06 -machine pc-q35-4.2,accel=kvm,usb=off,vmport=off,dump-guest-core=off -cpu host,ss=on,vmx=on,pcid=on,hypervisor=on,arat=on,tsc-adjust=on,umip=on,md-clear=on,stibp=on,arch-capabilities=on,ssbd=on,xsaveopt=on,pdpe1gb=on,ibpb=on,amd-stibp=on,amd-ssbd=on,skip-l1dfl-vmentry=on,pschange-mc-no=on,hv-vapic,hv_time,hv-spinlocks=0x1fff,hv-vendor-id=null,kvm=on,topoext=on -rtc clock=host,base=localtime -m 4096 -smp cores=4,threads=1,sockets=1 -hda /home/rmcore/.local/libvf.io/kernel/linux.qcow2 --enable-kvm -device pcie-root-port,id=rp0,chassis=1,slot=30,bus=pcie.0 -device vfio-pci,id=hostdev0,bus=rp0,sysfsdev=/sys/bus/mdev/devices/<MDEV-UUID>,display=off -device rtl8139,netdev=net0 -netdev user,id=net0,hostfwd=tcp::2222-:22 -net user -net nic -device vhost-vsock-pci,guest-cid=50718 -qmp unix:/tmp/sockets/e726ba0b-204f-4ec9-91da-983ed7f41d06/main.sock,server,nowait -qmp unix:/tmp/sockets/e726ba0b-204f-4ec9-91da-983ed7f41d06/master.sock,server,nowait
+exec /bin/qemu-system-x86_64 -D /home/rmcore/.local/libvf.io/logs/qemu/e726ba0b-204f-4ec9-91da-983ed7f41d06-session.txt -no-hpet -mem-prealloc -qmp unix:/tmp/qemu-qmp.sock,server,nowait -chardev socket,path=/tmp/qemu-guest-agent.sock,server=on,wait=off,id=qga0 -device virtio-serial-pci -device virtserialport,chardev=qga0,name=org.qemu.guest_agent.0 -serial file:/tmp/vgpu-guest-serial.log -gdb tcp::1234 -display none -device ivshmem-plain,id=shmem0,memdev=ivshmem_kvmfr -object memory-backend-file,id=ivshmem_kvmfr,mem-path=/dev/shm/kvmfr-e726ba0b-204f-4ec9-91da-983ed7f41d06,size=128M,share=yes -device ivshmem-plain,id=shmem1,memdev=ivshmem_kvmsr -object memory-backend-file,id=ivshmem_kvmsr,mem-path=/dev/shm/kvmsr-e726ba0b-204f-4ec9-91da-983ed7f41d06,size=2M,share=yes -object memory-backend-file,id=pc.ram,size=4096M,mem-path=/dev/shm/vgpu-guest-ram,share=yes,prealloc=on -uuid e726ba0b-204f-4ec9-91da-983ed7f41d06 -machine pc-q35-4.2,accel=kvm,usb=off,vmport=off,dump-guest-core=off,memory-backend=pc.ram -cpu host,ss=on,vmx=on,pcid=on,hypervisor=on,arat=on,tsc-adjust=on,umip=on,md-clear=on,stibp=on,arch-capabilities=on,ssbd=on,xsaveopt=on,pdpe1gb=on,ibpb=on,amd-stibp=on,amd-ssbd=on,skip-l1dfl-vmentry=on,pschange-mc-no=on,hv-vapic,hv_time,hv-spinlocks=0x1fff,hv-vendor-id=null,kvm=on,topoext=on -rtc clock=host,base=localtime -m 4096 -smp cores=4,threads=1,sockets=1 -hda /home/rmcore/.local/libvf.io/kernel/linux.qcow2 --enable-kvm -device pcie-root-port,id=rp0,chassis=1,slot=30,bus=pcie.0 -device vfio-pci,id=hostdev0,bus=rp0,sysfsdev=/sys/bus/mdev/devices/<MDEV-UUID>,display=off -device rtl8139,netdev=net0 -netdev user,id=net0,hostfwd=tcp::2222-:22 -net user -net nic -device vhost-vsock-pci,guest-cid=50718 -qmp unix:/tmp/sockets/e726ba0b-204f-4ec9-91da-983ed7f41d06/main.sock,server,nowait -qmp unix:/tmp/sockets/e726ba0b-204f-4ec9-91da-983ed7f41d06/master.sock,server,nowait
diff --git a/tools/test/gpage_test.c b/tools/test/gpage_test.c
new file mode 100644
index 0000000..33d0c8d
--- /dev/null
+++ b/tools/test/gpage_test.c
@@ -0,0 +1,110 @@
+/* gpage_test.c - guest-page GPA probe for the physical-backend guest-memory path.
+ *
+ * Run as root inside the guest (plain gcc on Ubuntu 24.04, no CUDA).
+ *
+ * mmap+mlock one 4 KiB anonymous page, fill it with the 0xa5 ^ (i & 0xff)
+ * pattern, resolve its guest-physical address from /proc/self/pagemap and
+ * print
+ * GPAGE gpa=0x<hex>
+ * to stdout (flushed) so the host harness can hand the GPA to the module via
+ * the gsp-phys-guest-gpa debugfs file.
+ *
+ * The page is then polled every 100 ms for up to 120 s. The host-side W2G
+ * trigger copies the module SRC over this page, so byte 0 becomes 0x5a
+ * (0xa5 ^ (0 & 0xff) = 0xa5 -> 0x5a). On seeing p[0] == 0x5a print
+ * "GPAGE SEEN_W2G" and exit 0; on timeout print "GPAGE TIMEOUT" and exit 1.
+ * If the PFN cannot be resolved or is zero, print "GPAGE NO_PFN" and exit 2.
+ *
+ * Build (guest): gcc -O2 -o /tmp/gpage /tmp/gpage.c
+ */
+#define _GNU_SOURCE
+#include <errno.h>
+#include <fcntl.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <string.h>
+#include <sys/mman.h>
+#include <time.h>
+#include <unistd.h>
+
+#define PAGE_SIZE 4096u
+#define POLL_INTERVAL_MS 100
+#define POLL_TIMEOUT_MS 120000
+
+static int resolve_gpa(const void *addr, uint64_t *gpa)
+{
+ size_t offset = ((uintptr_t)addr / PAGE_SIZE) * sizeof(uint64_t);
+ uint64_t entry = 0;
+ ssize_t n;
+ int fd = open("/proc/self/pagemap", O_RDONLY);
+ if (fd < 0) {
+ fprintf(stderr, "open pagemap: %s\n", strerror(errno));
+ return -1;
+ }
+ n = pread(fd, &entry, sizeof(entry), (off_t)offset);
+ close(fd);
+ if (n != (ssize_t)sizeof(entry)) {
+ fprintf(stderr, "read pagemap: %s\n", n < 0 ? strerror(errno) : "short read");
+ return -1;
+ }
+ if (!(entry & (1ULL << 63))) {
+ fprintf(stderr, "pagemap: page not present\n");
+ return -1;
+ }
+ {
+ uint64_t pfn = entry & ((1ULL << 55) - 1);
+ if (pfn == 0) {
+ fprintf(stderr, "pagemap: pfn is zero\n");
+ return -1;
+ }
+ *gpa = pfn * PAGE_SIZE;
+ }
+ return 0;
+}
+
+int main(void)
+{
+ struct timespec ts = { .tv_sec = 0, .tv_nsec = POLL_INTERVAL_MS * 1000000L };
+ unsigned char *p;
+ uint64_t gpa = 0;
+ size_t i;
+ int waited = 0;
+
+ setvbuf(stdout, NULL, _IONBF, 0);
+
+ p = mmap(NULL, PAGE_SIZE, PROT_READ | PROT_WRITE,
+ MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
+ if (p == MAP_FAILED) {
+ printf("GPAGE MMAP_FAILED\n");
+ return 2;
+ }
+ if (mlock(p, PAGE_SIZE) != 0) {
+ printf("GPAGE MLOCK_FAILED\n");
+ return 2;
+ }
+
+ for (i = 0; i < PAGE_SIZE; i++)
+ p[i] = (unsigned char)(0xa5 ^ (i & 0xff));
+
+ if (resolve_gpa(p, &gpa) != 0) {
+ printf("GPAGE NO_PFN\n");
+ return 2;
+ }
+
+ printf("GPAGE gpa=0x%llx\n", (unsigned long long)gpa);
+ fflush(stdout);
+
+ while (waited < POLL_TIMEOUT_MS) {
+ if (*(volatile unsigned char *)p == 0x5a) {
+ printf("GPAGE SEEN_W2G\n");
+ fflush(stdout);
+ return 0;
+ }
+ nanosleep(&ts, NULL);
+ waited += POLL_INTERVAL_MS;
+ }
+
+ printf("GPAGE TIMEOUT\n");
+ fflush(stdout);
+ return 1;
+}