9front - general discussion about 9front
 help / color / mirror / Atom feed
* [9front] Fwd: Vmcall device
       [not found] <E32CB360-8FA7-492E-943C-7CD565D12EA3@me.com>
@ 2025-03-29  0:03 ` ron minnich
  2025-03-29  1:03   ` Jacob Moody
  0 siblings, 1 reply; 4+ messages in thread
From: ron minnich @ 2025-03-29  0:03 UTC (permalink / raw)
  To: 9front


[-- Attachment #1.1: Type: text/plain, Size: 827 bytes --]

---------- Forwarded message ---------
From: ronald minnich <rminnich@me.com>
Date: Fri, Mar 28, 2025 at 5:03 PM
Subject: Vmcall device
To: Ron Minnich <rminnich@gmail.com>


Attached are two files for review. The first, devvmcall, maps files in a vm
to vmcalls.

In my vm guest, I can bind '#Z' /mnt/vmproc, and, at that point, the name
space of the vmm is visible in the guest.

I don't include the mkfile yet, pending this device being acceptable.

Also included is vmcall.s. This is all of 4 bytes, and it might make most
sense to just put it in l.s

Note that there's no effort here to make this uber-efficient, it's mainly
reliability we're shooting for.

The vmcalls can be asynchronous; in this device only reads are at present.

As my talk in may will show, it's quite fast in spite of that.

[-- Attachment #1.2: Type: text/html, Size: 2108 bytes --]

[-- Attachment #2: vmcall.s --]
[-- Type: application/octet-stream, Size: 82 bytes --]

#include "mem.h"

TEXT vmcall(SB), $0
	BYTE $0xf; BYTE $0x1; BYTE $0xc1
	RET

[-- Attachment #3: devvmcall.c --]
[-- Type: text/x-c-code, Size: 10784 bytes --]

#include	"u.h"
#include	"../port/lib.h"
#include	"mem.h"
#include	"dat.h"
#include	"fns.h"
#include	"io.h"
#include	"../port/error.h"
#include "/sys/src/libc/9syscall/sys.h"

uvlong vmcall(uvlong, ...);

static int vvdebug = 0;
#define vmdebug if(!vvdebug) {} else print

static int vdebug = 0;

enum
{
	Qdir=		0x8000,
};

Dirtab vmcalldir[]={
	".",	{Qdir, 0, QTDIR},	0,	DMDIR|0555,
};

/* alloc and leak if it is too low.
 * Memory below 16M is reserved for the VMM.
 */
static void *valloc(char *who, int amt) {
	void *v;
	while(PADDR(v = malloc(amt)) < 0x1000000)
		;
	if (vdebug) print("%s:valloc(%d): %p\n", who, amt, v);
	return v;
}

static void *vallocz(char *who,int amt, int zero) {
	void *v;
	while(PADDR(v = mallocz(amt, zero)) < 0x1000000)
		;
	if (vdebug) print("%s:vallocz(%d, %d): %p\n", who,amt, zero, v);
	return v;
}

static void vfree(char *who, void *p)
{
	free(p);
	if (vdebug) print("%s:free %p\n", who, p);
}

/* Set up the args for a vmsyscall from the kernel.
 * Or'ing with 0x8000000000000000 tells the VMM that
 * this requests comes from the kernel, not a program.
 */
static uvlong vmcallargs(uvlong *vec, uvlong scallno, char *err, int nerr, int narg, ...)
{
	va_list ap;
	uvlong val;
	int i;

	vmdebug("vmcallargs: start vec %p, narg %d \n", vec, narg);
	va_start(ap, narg);
	vec[0] = scallno;
	vec[1] = PADDR(err);
	vec[2] = (uvlong)nerr;
	vmdebug("vmcallargs: scallno %#llx\n", scallno);
	for(i = 0; i < narg; i++) {
		val = va_arg(ap, uvlong);
		vmdebug("vmcallargs: add arg %d, val %p\n", i, val);
		vec[i+3] = val;
	}
	va_end(ap);
	vmdebug("vmcallargs: return %p\n", PADDR(vec) | 0x8000000000000000);
	return PADDR(vec) | 0x8000000000000000;
}

static Chan*
vmcallattach(char *spec)
{
	Chan *c;
	c = devattach('Z', spec);
	c->qid.path = Qdir;
	c->dev = -1;
	return c;
}

/* stateless walk.
 * We will only walk one component at a time, and let the code in chan.c pick
 * handle the details. This is the most complex function. */
static Walkqid*
vmcallwalk(Chan *c, Chan *nc, char **name, int nname)
{
	int alloc;
	Walkqid *wq;
	uchar *dp;
	Dir d;
	int nqid, j;
	int fullpathlen = 2;
	uvlong *vec = valloc("vmcallwrite vec", 8*sizeof(uvlong));
	char *err;
	char *p = c->aux ? c->aux : "/";
	vmdebug("vmcallwalk, c %p, c->aux %p, p %s nname %d:, name'", c, c->aux, p, nname);
	for (j = 0; j < nname; j++){
		vmdebug("/%s", name[j]);
		fullpathlen += strlen(name[j])+1;
	}
	vmdebug("'\n");
	dp = valloc("walk dp", 128);
	err = valloc("walk err", ERRMAX);
	if (waserror()) {
		free(dp);
		vmdebug("Walk returns nil after errors\n");
		kstrcpy(up->errstr, err, ERRMAX);
		vfree("walk err", err);
		vfree("vmcallwrite vec", vec);
		return nil;
	}
	if(nname > 0)
		isdir(c);

	vmdebug("c %p nc %p\n", c, nc);
	alloc = (nc == nil);
	vmdebug("alloc %d\n", alloc);
	wq = smalloc(sizeof(Walkqid)+nname*sizeof(Qid));
	if(waserror()){
		if(alloc && wq->clone != nil)
			cclose(wq->clone);
		free(wq);
		nexterror();
	}
	vmdebug("wq %p\n", wq);
	if(alloc){
		nc = devclone(c);
		nc->aux = nil; // we do not clone the name.
		nc->type = 0;	/* device doesn't know about this channel yet */
	}
	vmdebug("devcloned nname %d nc %p wq %p\n", nname, nc, wq);
	wq->clone = nc;
	vmdebug("before for\n");
	int sz = strlen(p) + 1 /* for / */ + fullpathlen + 2; // for null and fudge
	vmdebug("sz %d\n", sz);
	char *nm = vallocz("walk name", sz, 1);
	if (waserror()) {
		free(nm);
		nexterror();
	}
	if (nm == nil)
		panic("nm is nil?");
	if (p == nil)
		panic("p is nil?");
	vmdebug("nm is %p\n", nm);
	strcat(nm, p);
	strcat(nm, "/");
	vmdebug("before for nm %p %s\n", nm, nm);
	for(nqid = 0; nqid < nname; nqid++) {
		vmdebug("vmstat %s\n", name[nqid]);
		if (name[nqid] == nil)
			panic("nm %s name[%d] nil", nm, nqid);
			
		strcat(nm, name[nqid]);
		if (nqid < nname-1)
			strcat(nm, "/");
		vmdebug("nm %p %s\n", nm, nm);

		uvlong ret = vmcall(vmcallargs(vec, STAT, err, ERRMAX, 3, PADDR(nm), PADDR(dp), 128));
		if ((int)ret < 0) {
			vmdebug("%s: not found\n", nm);
			error(err);
		}
		vmdebug("convM2d?\n");
		convM2D(dp, 128, &d, nil);
		vmdebug("%s; qid %#llx %#lx %#x\n", nm, d.qid.path, d.qid.vers, d.qid.type);
		wq->qid[nqid] = d.qid;
	}
	vmdebug("after for nqid %d nnames %d\n", nqid, nname);

	if (nc && nqid == nname) {
		nc->aux = nm;
		if (nname > 0){
			nc->qid = wq->qid[nqid-1];
			nc->path = newpath(name[nname-1]);
		} else {
			incref(c->path);
			nc->path = c->path;
		}
		nc->dev = -1;
	}
	poperror();
	poperror();
	poperror();
	vmdebug("after poperror");
	vfree("walk err", err);
	vfree("walk dp", dp);
	vfree("vmcallwrite vec", vec);
	wq->nqid = nqid;
	if(wq->clone != nil){
		/* attach cloned channel to same device */
		wq->clone->type = c->type;
	}
	return wq;
}

/* This is the second most complex function */
static int
vmcallstat(Chan *c, uchar *dp, int n)
{
	char *err;
	char *p = c->aux;
	if (!c->aux)
		error("c->aux is nil");
	uvlong *vec = vallocz("vmcallstat vec", 8*sizeof(uvlong), 1);
	void *v = vallocz("vmcallstat err", n, 1);
	vmdebug("vmcallstat name %s addr %p dp %p\n", p, p, dp);
	err = valloc("vmcallread error", ERRMAX);
	if (waserror()) {
		kstrcpy(up->errstr, err, ERRMAX);
		vfree("vmcallstat", v);
		vfree("vmcallstat vec", vec);
		vfree("vmcallstat err", err);
	}
	uvlong ret = vmcall(vmcallargs(vec, STAT, err, ERRMAX, 3, PADDR(p), PADDR(v), n));
	vmdebug("vmcallstat %s returns %#llx, want %d\n", p, ret, n);
	if ((int)ret < 0)
		error("vmcallstat");
	poperror();
	memmove(dp, v, n);
	vfree("vmcallstat", v);
	vfree("vmcallstat vec", vec);
	vfree("vmcallstat err", err);
	return (int)ret;
}

static Chan*
vmcallopen(Chan *c, int omode)
{
	char *err;
	char *p = c->aux;
	uvlong *vec;
	if (! p)
		error("vmcallopen:no path");
	vec = valloc("vmcallopen vec", 8*sizeof(uvlong));
	vmdebug("Open '%s'\n", p);
	err = valloc("open err", ERRMAX);
	if (waserror()) {
		kstrcpy(up->errstr, err, ERRMAX);
		vfree("open err", err);
		vfree("vmcallwrite vec", vec);
		error(up->errstr);
	}
	uvlong ret = vmcall(vmcallargs(vec, OPEN, err, ERRMAX, 2, PADDR(p), (uvlong)omode));
	vmdebug("ret is %lld\n", ret);
	if ((int)ret == -1) {
		error("vmcallopen thread error");
	}
	while(!(vec[0] & (1ull << 62)))
		sched();

	if ((vlong)vec[0] == -1) {
		error("syscall error");
	}
	poperror();
	ret = (u32int) vec[0];
	vmdebug("ret is %d\n", (int)ret);
	c->dev = ret;
	c->mode = openmode(omode);
	c->flag |= COPEN;
	c->offset = 0;
	vfree("vmcallopen vec", vec);
	vmdebug("open: set c %p c->dev %ld c->mode %d\n", c, c->dev, c->mode);
	return c;
}

static Chan*
vmcallcreate(Chan*, char*, int, ulong)
{
	error(Eperm);
}

static void
vmcallclose(Chan *c)
{
	char *err;
	uvlong *vec = valloc("vmcallwrite vec", 8*sizeof(uvlong));
	/* this is called right before the channel is freed.
	 * freeing aux is safe. */
	err = valloc("close err", ERRMAX);
	vmdebug("vmcallclose c %p c->aux %p\n", c, c->aux);
	vfree("vmcallclose", c->aux);
	c->aux = nil;
	/* never opened? */
	if (c->dev == -1)
		return;

	vmdebug("vmcallclose fd %#ld name %s\n", c->dev, c->aux);
	int ret = (int)vmcall(vmcallargs(vec, CLOSE, err, ERRMAX, 1, c->dev));
	if (ret < 0) {
		kstrcpy(up->errstr, err, ERRMAX);
		vfree("close err", err);
		error("vmcall close");
	}
	vfree("close err", err);
	vfree("vmcallwrite vec", vec);
}

/* The IO functions, at present, use a bounce buffer.
 * Given that the average IO in Plan 9 is not that large (we measured this,
 * in 2008, while working on curried system calls), the bounce buffer may
 * be worth continuing to use. It greatly reduces the complexity of
 * the code, which (reminder) is asynchrous; we would need locks on
 * use pages, which in turn needs page table walks, ... it gets messy. */
long
vmcallreadfd(ulong fd, void *a, long n, vlong off)
{
	char *err;
	void *v;
	uvlong *vec = valloc("vmcallwrite vec", 8*sizeof(uvlong));
	vmdebug("vmcallreadfd fd %lud a %p n %ld off %lld\n", fd, a, n, off);
	v = valloc("vmcallread", n);
	err = valloc("vmcallread error", ERRMAX);
	if (waserror()) {
		vfree("vmcallread", v);
		kstrcpy(up->errstr, err, ERRMAX);
		vfree("vmcallread error", err);
		vfree("vmcallread vec", vec);
		return -1;
	}
	int ret = (int)vmcall(vmcallargs(vec, PREAD, err, ERRMAX, (uvlong)4, (uvlong)fd, PADDR(v), (uvlong)n, (uvlong)off));
	vmdebug("ret is %d\n", ret);
	if ((int)ret == -1) {
		error("read"); 
	}
	vmdebug("Spin on vec[0] %#llx\n", vec[0]);
	while(!(vec[0] & (1ull << 62)))
		sched();
	vmdebug(" done Spin on vec[0] %#llx\n", vec[0]);

	if ((vlong)vec[0] == -1) {
		error("read");
	}
	ret = (u32int) vec[0];
	vmdebug("ret is %d\n", (int)ret);
	memmove(a, v, n);
	poperror();
	vfree("vmcallread", v);
	vfree("vmcallread error", err);
	vfree("vmcallread vec", vec);
	return (long)ret;
}
static long
vmcallread(Chan *c, void *a, long n, vlong off)
{
	int fd = c->dev;
	vmdebug("vmcallread c %p fd %lud a %p n %ld off %lld\n", c, c->dev, a, n, off);
	return vmcallreadfd(fd, a, n, off);
}

/* vmcallwritefd can be used for, e.g., kernel console "uart". Currently,
 * this is not really needed: a vmcall with a "system call" of < 128 causes
 * the ascii character to be printed on fd 1. But, still, using this function to move
 * even 32 bytes of console data is hundreds of times more efficient than iob to port 0x3f8. */
long
vmcallwritefd(ulong fd, void *a, long n, vlong off)
{
	char *err;
	uvlong *vec = valloc("vmcallwrite vec", 8*sizeof(uvlong));
	void *v = valloc("vmcallwrite", n);
	err = valloc("vmcallwrite error", ERRMAX);
	vmdebug("vmcallwrite: fd %lud a %p n %ld off %lld\n", fd, a, n, off);
	if (waserror()) {
		vfree("vmcallread", v);
		kstrcpy(up->errstr, err, ERRMAX);
		vfree("vmcallwrite error", err);
		vfree("vmcallwrite vec", vec);
		return -1;
	}
	memmove(v, a, n);
	int ret = (int)vmcall(vmcallargs(vec, PWRITE, err, ERRMAX, 4, fd, PADDR(v), n, off));
	if (ret < 0)
		error(err);
	poperror();
	vfree("vmcallwrite", v);
	vfree("vmcallwrite error", err);
	vfree("vmcallwrite vec", vec);
	return (long)ret;
}

static long
vmcallwrite(Chan *c, void *a, long n, vlong off)
{
	ulong fd = c->dev;
	vmdebug("vmcallwrite: c %p fd %lud a %p n %ld off %lld\n", c, c->dev, a, n, off);
	return vmcallwritefd(fd, a, n, off);
}


Dev vmcalldevtab = {
	'Z',
	"vmcall",

	devreset,
	devinit,
	devshutdown,
	vmcallattach,
	vmcallwalk,
	vmcallstat,
	vmcallopen,
	vmcallcreate,
	vmcallclose,
	vmcallread,
	devbread,
	vmcallwrite,
	devbwrite,
	devremove,
	devwstat,
};

^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: [9front] Fwd: Vmcall device
  2025-03-29  0:03 ` [9front] Fwd: Vmcall device ron minnich
@ 2025-03-29  1:03   ` Jacob Moody
  2025-03-29  4:52     ` ron minnich
  0 siblings, 1 reply; 4+ messages in thread
From: Jacob Moody @ 2025-03-29  1:03 UTC (permalink / raw)
  To: 9front

On 3/28/25 19:03, ron minnich wrote:
> 
> 
> ---------- Forwarded message ---------
> From: *ronald minnich* <rminnich@me.com <mailto:rminnich@me.com>>
> Date: Fri, Mar 28, 2025 at 5:03 PM
> Subject: Vmcall device
> To: Ron Minnich <rminnich@gmail.com <mailto:rminnich@gmail.com>>
> 
> 
> Attached are two files for review. The first, devvmcall, maps files in a vm to vmcalls. 
> 
> In my vm guest, I can bind '#Z' /mnt/vmproc, and, at that point, the name space of the vmm is visible in the guest. 
> 
> I don't include the mkfile yet, pending this device being acceptable. 
> 
> Also included is vmcall.s. This is all of 4 bytes, and it might make most sense to just put it in l.s
> 
> Note that there's no effort here to make this uber-efficient, it's mainly reliability we're shooting for. 
> 
> The vmcalls can be asynchronous; in this device only reads are at present. 
> 
> As my talk in may will show, it's quite fast in spite of that. 
> 
> 

I'm not too familiar with this x86 interface and without the paper and/or some preexisting knowledge it's a bit
difficult to see how this can be used. From what I can see online this is what is used in linux to implement
"hypercalls", but the information is a bit sparse.

Could you share some more information (or point to some resources) that might explain what you could implement
with this? It's a nice patch but I don't quite see the "big picture" yet.


Thanks,
moody

^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: [9front] Fwd: Vmcall device
  2025-03-29  1:03   ` Jacob Moody
@ 2025-03-29  4:52     ` ron minnich
  2025-03-29 15:18       ` ron minnich
  0 siblings, 1 reply; 4+ messages in thread
From: ron minnich @ 2025-03-29  4:52 UTC (permalink / raw)
  To: 9front

[-- Attachment #1: Type: text/plain, Size: 3855 bytes --]

a vmcall is a lot like a system call: it's a switch from virtual machine
guest mode to kernel mode. All registers are left intact, and can be used
for arguments.

This driver is for the guest. Driver operations are translated to
dynamically allocated system call structs, a pointer to the block is put in
RARG, and vmcall is called.  Either the host virtual machine manager can
handle the vmcall, or it can not. A coming patch series from me will show
how to support those calls in the vmm.

Because RARG is at least 32 bits, I make a lot of use of those bits. If
RARG is < 128, then the VMM should just print the character. This is an
ultra-low-overhead serial console, better than trying to emulate an i8250.
Other ranges have other uses. Kernel system calls have bit 63 set. By
convention, when the vmm is done, it sets bit 62. This allows asynchronous
vmcalls.

IO uses a bounce buffer. John Floren and I measured a couple million system
calls on Plan 9 back in 2008, and, in most cases, IOs are pretty short. I
think the bounce buffers are not a big issue for now. Also, copying data
(file names, buffers, etc.) in to the driver, then doing the VMCALL,
protects against Time of Check/Time of Use (TOC/TOU) attacks. When I was at
Google we did a similar thing in gvisor.

How I use this driver: in bootrc, I bind #Z to /mnt/vmproc. I have another
script, bind.rc, that adds bind as a choice.
So in root is from, you can type bind!/mnt/vmproc

 If bind!/mnt/vmproc is chosen, then the bind.rc binds
a few things, such that programs in the guest have access to the namespace
of the virtual machine manager. For example, /net, and /dev, /acme, /bin,
and other things are visible in the guest.

The result is that programs in the guest run pretty fast. If you're trying
to debug guest programs, rather than trying to infer what the programs are
doing, by watching emulated IOs to disk devices and network devices, one
can have a very clear idea what the guest is doing. You can even run the
vmm under iostats, and can see what the guest does.

So that's what this simple driver does.

I'm expecting to have some discussion on this, so I appreciate the first
pass you gave it.

thanks!



On Fri, Mar 28, 2025 at 6:07 PM Jacob Moody <moody@posixcafe.org> wrote:

> On 3/28/25 19:03, ron minnich wrote:
> >
> >
> > ---------- Forwarded message ---------
> > From: *ronald minnich* <rminnich@me.com <mailto:rminnich@me.com>>
> > Date: Fri, Mar 28, 2025 at 5:03 PM
> > Subject: Vmcall device
> > To: Ron Minnich <rminnich@gmail.com <mailto:rminnich@gmail.com>>
> >
> >
> > Attached are two files for review. The first, devvmcall, maps files in a
> vm to vmcalls.
> >
> > In my vm guest, I can bind '#Z' /mnt/vmproc, and, at that point, the
> name space of the vmm is visible in the guest.
> >
> > I don't include the mkfile yet, pending this device being acceptable.
> >
> > Also included is vmcall.s. This is all of 4 bytes, and it might make
> most sense to just put it in l.s
> >
> > Note that there's no effort here to make this uber-efficient, it's
> mainly reliability we're shooting for.
> >
> > The vmcalls can be asynchronous; in this device only reads are at
> present.
> >
> > As my talk in may will show, it's quite fast in spite of that.
> >
> >
>
> I'm not too familiar with this x86 interface and without the paper and/or
> some preexisting knowledge it's a bit
> difficult to see how this can be used. From what I can see online this is
> what is used in linux to implement
> "hypercalls", but the information is a bit sparse.
>
> Could you share some more information (or point to some resources) that
> might explain what you could implement
> with this? It's a nice patch but I don't quite see the "big picture" yet.
>
>
> Thanks,
> moody
>

[-- Attachment #2: Type: text/html, Size: 4897 bytes --]

^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: [9front] Fwd: Vmcall device
  2025-03-29  4:52     ` ron minnich
@ 2025-03-29 15:18       ` ron minnich
  0 siblings, 0 replies; 4+ messages in thread
From: ron minnich @ 2025-03-29 15:18 UTC (permalink / raw)
  To: 9front

[-- Attachment #1: Type: text/plain, Size: 5773 bytes --]

Paul pointed out that my answer missed some supporting information.

Virtual machine guest kernels can communicate with the outside world, and
usually do so by using emulated hardware in the host virtual machine
manager. The VM guest does an Io or memory map or pci config space
operation, that traps out of the VM, and the virtual machine manager is
responsible for interpreting the instructions and vm state, and taking the
proper action, which can include ignoring the operation or causing a fault.
E.g., Io operations to an invalid region essentially end up being
ignored.Needless to say this can get pretty complicated, especially if
there is DMA involved.

This can be pretty complex and not very fast, which is why things like
IOMMU’s and bypass devices exist.

What my #Z Device does instead is provide direct access to the virtual
machine manager name space from the guest. It does so by converting driver
operations into VM calls, basically syscalls, for the most part, although,
given that we have a full 64 bits to work with as the argument we can add
additional capabilities besides just syscalls.

This takes advantage of the fact that, unlike UNIX, all program access to
resources in plan 9 is via file IO.  That greatly simplifies everything as
you can imagine. You don’t need the guest to have a full TCP/IP stack
driving emulated NE 2000 or E 1000 cards; rather, we just need to allow the
guest to do file IO  in the virtual machine managers name space.  You don’t
need to write code to emulate those cards or other hardware resources. The
code to support the # Z  device is very small. Nothing like the million
lines of code in QEMU.

Hope that helps.

On Fri, Mar 28, 2025 at 21:52 ron minnich <rminnich@gmail.com> wrote:

> a vmcall is a lot like a system call: it's a switch from virtual machine
> guest mode to kernel mode. All registers are left intact, and can be used
> for arguments.
>
> This driver is for the guest. Driver operations are translated to
> dynamically allocated system call structs, a pointer to the block is put in
> RARG, and vmcall is called.  Either the host virtual machine manager can
> handle the vmcall, or it can not. A coming patch series from me will show
> how to support those calls in the vmm.
>
> Because RARG is at least 32 bits, I make a lot of use of those bits. If
> RARG is < 128, then the VMM should just print the character. This is an
> ultra-low-overhead serial console, better than trying to emulate an i8250.
> Other ranges have other uses. Kernel system calls have bit 63 set. By
> convention, when the vmm is done, it sets bit 62. This allows asynchronous
> vmcalls.
>
> IO uses a bounce buffer. John Floren and I measured a couple million
> system calls on Plan 9 back in 2008, and, in most cases, IOs are pretty
> short. I think the bounce buffers are not a big issue for now. Also,
> copying data (file names, buffers, etc.) in to the driver, then doing the
> VMCALL, protects against Time of Check/Time of Use (TOC/TOU) attacks. When
> I was at Google we did a similar thing in gvisor.
>
> How I use this driver: in bootrc, I bind #Z to /mnt/vmproc. I have another
> script, bind.rc, that adds bind as a choice.
> So in root is from, you can type bind!/mnt/vmproc
>
>  If bind!/mnt/vmproc is chosen, then the bind.rc binds
> a few things, such that programs in the guest have access to the namespace
> of the virtual machine manager. For example, /net, and /dev, /acme, /bin,
> and other things are visible in the guest.
>
> The result is that programs in the guest run pretty fast. If you're trying
> to debug guest programs, rather than trying to infer what the programs are
> doing, by watching emulated IOs to disk devices and network devices, one
> can have a very clear idea what the guest is doing. You can even run the
> vmm under iostats, and can see what the guest does.
>
> So that's what this simple driver does.
>
> I'm expecting to have some discussion on this, so I appreciate the first
> pass you gave it.
>
> thanks!
>
>
>
> On Fri, Mar 28, 2025 at 6:07 PM Jacob Moody <moody@posixcafe.org> wrote:
>
>> On 3/28/25 19:03, ron minnich wrote:
>> >
>> >
>> > ---------- Forwarded message ---------
>> > From: *ronald minnich* <rminnich@me.com <mailto:rminnich@me.com>>
>> > Date: Fri, Mar 28, 2025 at 5:03 PM
>> > Subject: Vmcall device
>> > To: Ron Minnich <rminnich@gmail.com <mailto:rminnich@gmail.com>>
>> >
>> >
>> > Attached are two files for review. The first, devvmcall, maps files in
>> a vm to vmcalls.
>> >
>> > In my vm guest, I can bind '#Z' /mnt/vmproc, and, at that point, the
>> name space of the vmm is visible in the guest.
>> >
>> > I don't include the mkfile yet, pending this device being acceptable.
>> >
>> > Also included is vmcall.s. This is all of 4 bytes, and it might make
>> most sense to just put it in l.s
>> >
>> > Note that there's no effort here to make this uber-efficient, it's
>> mainly reliability we're shooting for.
>> >
>> > The vmcalls can be asynchronous; in this device only reads are at
>> present.
>> >
>> > As my talk in may will show, it's quite fast in spite of that.
>> >
>> >
>>
>> I'm not too familiar with this x86 interface and without the paper and/or
>> some preexisting knowledge it's a bit
>> difficult to see how this can be used. From what I can see online this is
>> what is used in linux to implement
>> "hypercalls", but the information is a bit sparse.
>>
>> Could you share some more information (or point to some resources) that
>> might explain what you could implement
>> with this? It's a nice patch but I don't quite see the "big picture" yet.
>>
>>
>> Thanks,
>> moody
>>
>

[-- Attachment #2: Type: text/html, Size: 7252 bytes --]

^ permalink raw reply	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2025-03-29 15:21 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
     [not found] <E32CB360-8FA7-492E-943C-7CD565D12EA3@me.com>
2025-03-29  0:03 ` [9front] Fwd: Vmcall device ron minnich
2025-03-29  1:03   ` Jacob Moody
2025-03-29  4:52     ` ron minnich
2025-03-29 15:18       ` ron minnich

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).