blob: 845a4fd5195d5e96ff306ab7dd7e00be57a34a18 [file] [log] [blame]
#include <stdio.h>
#include <err.h>
#include <string.h>
#include <stddef.h>
#include <stdint.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/ioctl.h>
#include <sys/mman.h>
#include <unistd.h>
#include <fcntl.h>
#include <linux/types.h>
#include <linux/kvm.h>
#include <linux/kcov.h>
#include <linux/ptrace.h>
#include <sys/sysinfo.h>
#include <sys/un.h>
#include <sys/wait.h>
#include <sys/socket.h>
#include <errno.h>
/* ++ uapi/pkvm_shmem.h */
#define KVM_SHMEM_ALLOC_TYPE 1
enum kvm_shmem_alloc_type {
KVM_SHMEM_ALLOCTYPE_VMALLOC,
KVM_SHMEM_ALLOCTYPE_PAGES_EXACT };
#define KVM_SHMEM_ALLOC(alloc) _IO(KVM_SHMEM_ALLOC_TYPE, alloc)
#define KVM_SHMEM_ALLOC_PAGES KVM_SHMEM_ALLOC(KVM_SHMEM_ALLOCTYPE_PAGES_EXACT)
#define KVM_SHMEM_VMALLOC KVM_SHMEM_ALLOC(KVM_SHMEM_ALLOCTYPE_VMALLOC)
// ioctl on the mmapable fd from the KVM_SHMEM_ALLOC ioctl
#define KVM_SHMEM_AREA_KADDR _IOR(1, 0, void *)
#define KVM_SHMEM_AREA_PHYS _IOR(1, 1, void *)
#define KVM_SHMEM_AREA_MAKE_READONLY _IO(1, 2)
/* -- uapi/pkvm_shmem.h */
#define PAGE_SHIFT 12
#define PAGE_SIZE (1 << PAGE_SHIFT)
struct shmem_area {
int size;
int fd;
void* mmap;
ulong kaddr;
ulong phys;
};
void shmem_area_getinfo(struct shmem_area *area)
{
if(ioctl(area->fd, KVM_SHMEM_AREA_KADDR, &area->kaddr))
err(1, "Can't get kernel area address");
printf("Allocated area at %lx of size 0x%x bytes\n",
area->kaddr, area->size);
if (ioctl(area->fd, KVM_SHMEM_AREA_PHYS, &area->phys))
err(1, "Can't get kernel area physical address");
}
void shmem_area_mmap(struct shmem_area *area)
{
printf("Try to mmap kernel address %lx fd %d\n", area->kaddr, area->fd);
area->mmap = mmap(NULL, area->size, PROT_READ | PROT_WRITE,
MAP_SHARED, area->fd, 0);
if ((void*)area->mmap == MAP_FAILED)
err(1, "Can't mmap kernel area");
}
static void recv_fd(int socket, int *fds, int n)
{
struct msghdr msg = {0};
struct cmsghdr *cmsg;
char buf[CMSG_SPACE(n * sizeof(int))], dup[256];
struct iovec io = { .iov_base = &dup, .iov_len = sizeof(dup) };
memset(buf, 0, sizeof(buf));
msg.msg_iov = &io;
msg.msg_iovlen = 1;
msg.msg_control = buf;
msg.msg_controllen = sizeof(buf);
if (recvmsg (socket, &msg, 0) < 0)
err(1, "Failed to receive message");
cmsg = CMSG_FIRSTHDR(&msg);
memcpy(fds, (int *)CMSG_DATA(cmsg), n * sizeof(int));
}
int mk_uds(const char *path)
{
int sfd;
struct sockaddr_un addr;
sfd = socket(AF_UNIX, SOCK_STREAM, 0);
if (sfd == -1)
err(1, "Failed to create socket");
memset(&addr, 0, sizeof(struct sockaddr_un));
addr.sun_family = AF_UNIX;
strncpy(addr.sun_path, path, sizeof(addr.sun_path) - 1);
if (connect(sfd, (struct sockaddr *)&addr, sizeof(struct sockaddr_un)) == -1)
err(1, "Failed to connect to socket");
return sfd;
}
int main(int argc, char** argv)
{
int sock_fd;
struct shmem_area area = { .size = PAGE_SIZE };
sock_fd = mk_uds("shmem.sock");
recv_fd(sock_fd, &area.fd, 1);
printf("Received FD %d\n", area.fd);
shmem_area_getinfo(&area);
shmem_area_mmap(&area);
printf("Area: ka=%lx pa=%lx va=%p size=%d\n",
area.kaddr, area.phys, area.mmap, area.size);
for (;;);
return 0;
}