ref: 2c9eeaf3cfd204ee49d676e8716445bb563249cd
parent: a3cfb13960d937a0ecaad3ea738fd55bf7c14105
author: glenda <glenda@fileserver>
date: Mon Dec 29 23:06:24 EST 2025
code cleanup, pci improvement, proper shutdown
--- a/README
+++ b/README
@@ -1,3 +1,51 @@
+** INSTALL **
+
+-> cp devvmx.c /sys/src/9/pc/devvmx.c
+-> Recompile the kernel and reboot:
+
+cd /sys/src/9/pc64
+mk clean
+mk
+mk install
+bind -a '#S' /dev
+9fs 9fat
+cp /n/9fat/9pc64 /n/9fat/oldpc64 # backup
+cp /amd64/9pc64 /n/9fat/9pc64
+fshalt -r
+
+-> Build vmx:
+
+mk
+mk install
+
+-> Install alpine linux,
+
+./runvm alpineinstall
+
+You should see 4 cores in /proc/cpuinfo
+
+-> Use alpine linux,
+
+./runvm alpinerun
+
+-> These scripts assume the existence of /net/ether0
+
+** NEW FEATURES **
+
+-> SMP, to specify number cores use -x option in vmx, by default 4 cores.
+
+-> Faster vioblk, on my laptop I can get up to 240Mb/s vs the
+previous 180Mb/s . Presumably vionet is also faster.
+
+** BUGS **
+
+-> OpenBSD is slow
+-> 9front is slow when two disks are attached
+-> Mouse is slow
+-> Cannot boot with more than 4G (trivial to fix though)
+
+** (PREVIOUS) NOTES **
+
-> In devvmx.c we add two features, setting the tsc offset and VMX PREEMPT. Therefore,
**Running this requires recompiling the kernel with the provided devvmx.c file**
--- a/acpi.c
+++ b/acpi.c
@@ -429,8 +429,7 @@
memcpy(p + 36, aml, aml_len);
p[9] = acpi_checksum(p, len);
- if (debug)
- fprint(2, "build_dsdt: aml_len=%d total=%d\n", aml_len, len);
+ dprint("build_dsdt: aml_len=%d total=%d\n", aml_len, len);return len;
}
@@ -679,13 +678,13 @@
rsdt_len = build_rsdt(rsdt);
rsdp_len = build_rsdp(rsdp);
- vmerror("ACPI tables created:");- vmerror(" RSDP at %#x (%d bytes)", RSDP_ADDR, rsdp_len);- vmerror(" RSDT at %#x (%d bytes)", RSDT_ADDR, rsdt_len);- vmerror(" MADT at %#x (%d bytes) - %d CPUs", MADT_ADDR, madt_len, nvcpu);- vmerror(" FADT at %#x (%d bytes)", FADT_ADDR, fadt_len);- vmerror(" FACS at %#x (%d bytes)", FACS_ADDR, facs_len);- vmerror(" DSDT at %#x (%d bytes)", DSDT_ADDR, dsdt_len);- vmerror(" HPET at %#x (%d bytes)", HPET_ADDR, hpet_len);+ dprint("ACPI tables created:");+ dprint(" RSDP at %#x (%d bytes)", RSDP_ADDR, rsdp_len);+ dprint(" RSDT at %#x (%d bytes)", RSDT_ADDR, rsdt_len);+ dprint(" MADT at %#x (%d bytes) - %d CPUs", MADT_ADDR, madt_len, nvcpu);+ dprint(" FADT at %#x (%d bytes)", FADT_ADDR, fadt_len);+ dprint(" FACS at %#x (%d bytes)", FACS_ADDR, facs_len);+ dprint(" DSDT at %#x (%d bytes)", DSDT_ADDR, dsdt_len);+ dprint(" HPET at %#x (%d bytes)", HPET_ADDR, hpet_len);}
--- /dev/null
+++ b/cleanup.c
@@ -1,0 +1,213 @@
+/* cleanup.c - VMX SMP cleanup handling */
+
+#include <u.h>
+#include <libc.h>
+#include <thread.h>
+#include "dat.h"
+#include "fns.h"
+
+static int parent_pid;
+static int child_pids[MAXVCPU];
+static int nchildren;
+
+extern int ctlfd, regsfd, mapfd, waitfd;
+extern int kbdpipe[2];
+extern int mousepipe[2];
+extern int uartpipe[2][2];
+extern int uarttxpipe[2][2];
+extern int wakepipe[MAXVCPU][2];
+extern int hltpipe[MAXVCPU][2];
+
+/*
+ * Stop and release VMX context - each process does this for its own
+ */
+static void
+cleanup_vmx(void)
+{+
+ extern IOApic *ioapic;
+ extern IpiQueue *ipiqueue;
+ extern PciShared *pcishared;
+ extern VIOShared *vioshared;
+
+ /* Detach shared segments first */
+ if(ioapic != nil){ segdetach(ioapic); ioapic = nil; }+ if(ipiqueue != nil){ segdetach(ipiqueue); ipiqueue = nil; }+ if(pcishared != nil){ segdetach(pcishared); pcishared = nil; }+ if(vioshared != nil){ segdetach(vioshared); vioshared = nil; }+
+ if(ctlfd >= 0){+ write(ctlfd, "stop", 4);
+ write(ctlfd, "quit", 4);
+ }
+
+ if(waitfd >= 0){ close(waitfd); waitfd = -1; }+ if(mapfd >= 0){ close(mapfd); mapfd = -1; }+ if(regsfd >= 0){ close(regsfd); regsfd = -1; }+ if(ctlfd >= 0){ close(ctlfd); ctlfd = -1; }+
+ extern char name[128];
+
+ char buf[128];
+ snprint(buf, sizeof(buf), "#X/%s/ctl", name);
+ remove(buf);
+ snprint(buf, sizeof(buf), "#X/%s", name);
+ remove(buf);
+
+}
+
+/*
+ * Remove shared segments - parent only
+ */
+static void
+cleanup_shared(void)
+{+ if(vmx_segprefix == nil)
+ return;
+
+ rmseg("ioapic");+ rmseg("ipi");+ rmseg("pci");+ rmseg("vio");+
+ free(vmx_segprefix);
+ vmx_segprefix = nil;
+}
+
+/*
+ * Close all pipes - parent only
+ */
+static void
+cleanup_pipes(void)
+{+ int i;
+
+ for(i = 0; i < MAXVCPU; i++){+ if(wakepipe[i][0] >= 0) close(wakepipe[i][0]);
+ if(wakepipe[i][1] >= 0) close(wakepipe[i][1]);
+ if(hltpipe[i][0] >= 0) close(hltpipe[i][0]);
+ if(hltpipe[i][1] >= 0) close(hltpipe[i][1]);
+ wakepipe[i][0] = wakepipe[i][1] = -1;
+ hltpipe[i][0] = hltpipe[i][1] = -1;
+ }
+
+ if(kbdpipe[0] >= 0) close(kbdpipe[0]);
+ if(kbdpipe[1] >= 0) close(kbdpipe[1]);
+ kbdpipe[0] = kbdpipe[1] = -1;
+
+ if(mousepipe[0] >= 0) close(mousepipe[0]);
+ if(mousepipe[1] >= 0) close(mousepipe[1]);
+ mousepipe[0] = mousepipe[1] = -1;
+
+ for(i = 0; i < 2; i++){+ if(uartpipe[i][0] >= 0) close(uartpipe[i][0]);
+ if(uartpipe[i][1] >= 0) close(uartpipe[i][1]);
+ if(uarttxpipe[i][0] >= 0) close(uarttxpipe[i][0]);
+ if(uarttxpipe[i][1] >= 0) close(uarttxpipe[i][1]);
+ uartpipe[i][0] = uartpipe[i][1] = -1;
+ uarttxpipe[i][0] = uarttxpipe[i][1] = -1;
+ }
+}
+
+/*
+ * Kill all child CPU processes
+ */
+static void
+killchildren(void)
+{+ int i;
+ Waitmsg *w;
+
+ for(i = 0; i < nchildren; i++){+ if(child_pids[i] > 0)
+ postnote(PNPROC, child_pids[i], "kill");
+ }
+
+ /* Actually wait for them to exit */
+ for(i = 0; i < nchildren; i++){+ if(child_pids[i] > 0){+ w = wait();
+ if(w != nil)
+ free(w);
+ }
+ }
+}
+
+/*
+ * Full cleanup - called on exit
+ */
+
+void
+vmx_cleanup(void)
+{+ int isparent = (getpid() == parent_pid);
+
+ dprint("vmx_cleanup: pid=%d isparent=%d\n", getpid(), isparent);+
+ if(isparent)
+ killchildren(); /* This should sleep(100) internally */
+
+ cleanup_vmx();
+
+ if(isparent){+ sleep(200); /* Extra wait for children to fully exit */
+ cleanup_pipes();
+ cleanup_shared();
+
+ }
+}
+
+/*
+ * atexit handler
+ */
+static void
+vmx_atexit(void)
+{+ vmx_cleanup();
+}
+
+/*
+ * Note handler - catch Del, kill, hangup
+ */
+int
+vmx_notehandler(void *, char *note)
+{+ dprint("NOTE: %s (pid %d)\n", note, getpid());+
+ if(strcmp(note, "interrupt") == 0 ||
+ strcmp(note, "kill") == 0 ||
+ strcmp(note, "hangup") == 0){+
+ vmx_cleanup();
+
+
+
+ }
+ return 0; /* Note not handled, pass to default */
+}
+
+/*
+ * Register cleanup handlers - call early in threadmain()
+ */
+void
+vmx_cleanup_init(void)
+{+
+ parent_pid = getpid();
+ nchildren = 0;
+ memset(child_pids, 0, sizeof(child_pids));
+ /* Use threadnotify for libthread programs */
+ threadnotify(vmx_notehandler, 1);
+
+ atexit(vmx_atexit);
+}
+
+/*
+ * Register a child process - call from forkcpu() in parent
+ */
+void
+vmx_register_child(int pid)
+{+ if(nchildren < MAXVCPU)
+ child_pids[nchildren++] = pid;
+}
--- a/dat.h
+++ b/dat.h
@@ -6,6 +6,9 @@
#define BACKSTOP_NS 50000000LL /* 10ms */
+extern void dprint(char *fmt, ...);
+
+extern char *vmx_segprefix;
#define MOUSE_PKT_BUF_SIZE 256
@@ -357,6 +360,14 @@
struct VIOShared {u8int data[32768];
uintptr alloc;
+ u8int isrstat;
+
+ int devpipes[8][2];
+ int ndevpipes;
+ void *blkdevs[8]; /* ADD: VIODev pointers for block devices */
+ int nblkdevs; /* ADD */
+ void *netdevs[8]; /* ADD: VIODev pointers for net devices */
+ int nnetdevs; /* ADD */
};
extern VIOShared *vioshared;
--- a/exith.c
+++ b/exith.c
@@ -358,8 +358,7 @@
u8int *ip = gptr(phys, 16);
if(ip == nil){- if (debug)
- fprint(2, "setmovdest: gptr failed rip=%#llx phys=%#llx\n", rip, phys);
+ dprint("setmovdest: gptr failed rip=%#llx phys=%#llx\n", rip, phys);rset(RAX, val);
return 0;
}
@@ -366,8 +365,7 @@
/* Debug: show what we're decoding */
if(ip[0] == 0 && ip[1] == 0 && ip[2] == 0 && ip[3] == 0){- if (debug)
- fprint(2, "setmovdest: zero opcodes! rip=%#llx phys=%#llx\n", rip, phys);
+ dprint("setmovdest: zero opcodes! rip=%#llx phys=%#llx\n", rip, phys);}
int i = 0;
@@ -639,9 +637,7 @@
}
/* Fallback - log and try to handle common patterns */
- if (debug)
- fprint(2, "setmovdest: unhandled opcode %02x %02x %02x %02x (rex=%02x has66=%d) val=%#llx\n",
- ip[i], ip[i+1], ip[i+2], ip[i+3], rex, has66, val); /* Changed %#x to %#llx */
+ dprint("setmovdest: unhandled opcode %02x %02x %02x %02x (rex=%02x has66=%d) val=%#llx\n", ip[i], ip[i+1], ip[i+2], ip[i+3], rex, has66, val); /* Changed %#x to %#llx *//*
* For unhandled read instructions, try to determine destination from ModRM.
@@ -653,8 +649,7 @@
int modrm = ip[i+1];
int reg = (modrm >> 3) & 7;
if(rex & 4) reg |= 8;
- if (debug)
- fprint(2, "setmovdest: fallback using reg %d (%s)\n", reg, x86reg[reg]);
+ dprint("setmovdest: fallback using reg %d (%s)\n", reg, x86reg[reg]);rset(x86reg[reg], val);
return 1;
}
@@ -673,38 +668,12 @@
void
ipiqueueinit(void)
{- int fd;
- char buf[64];
-
- remove("#g/vmx.ipi/ctl");- remove("#g/vmx.ipi");-
- /* Create shared segment */
- fd = create("#g/vmx.ipi", OREAD, DMDIR | 0777);- if(fd >= 0) close(fd);
-
- fd = open("#g/vmx.ipi/ctl", OWRITE);- if(fd < 0){- fprint(2, "ipiqueueinit: cannot open ctl: %r\n");
- return;
- }
-
- snprint(buf, sizeof buf, "va 0x300001000 0x1000 sticky");
-
- write(fd, buf, strlen(buf));
- close(fd);
-
- ipiqueue = segattach(0, "vmx.ipi", nil, 0x1000);
- if(ipiqueue == (void*)-1){- fprint(2, "ipiqueueinit: segattach failed: %r\n");
- ipiqueue = nil;
- return;
- }
-
- memset(ipiqueue, 0, sizeof(IpiQueue));
+ ipiqueue = mkseg("ipi", 0x300001000, 0x1000);+ memset(ipiqueue, 0, sizeof(IpiQueue));
+
ipiqueue->pids[0] = getpid();
- fprint(2, "IPI queue initialized\n");
+ dprint("IPI queue initialized\n");}
/*
@@ -782,9 +751,7 @@
if(ioapic == nil)
return;
- if(debug)
- fprint(2, "ioapic_eoi(%d): pending before=%#x\n", vector,
- ioapic->irq_pending);
+ dprint("ioapic_eoi(%d): pending before=%#x\n", vector, ioapic->irq_pending);lock(&ioapic->lock);
for(i = 0; i < 24; i++){@@ -796,9 +763,7 @@
int level_triggered = (redir >> 15) & 1;
int masked = (redir >> 16) & 1;
- if(debug)
- fprint(2, "ioapic_eoi: IRQ %d redir=%#llx level_trig=%d irq_level=%#x masked=%d\n",
- i, redir, level_triggered, ioapic->irq_level, masked);
+ dprint("ioapic_eoi: IRQ %d redir=%#llx level_trig=%d irq_level=%#x masked=%d\n", i, redir, level_triggered, ioapic->irq_level, masked);/* If level-triggered and line still high, handle re-delivery */
if(level_triggered && (ioapic->irq_level & (1 << i))){@@ -814,9 +779,7 @@
}
}
- if(debug)
- fprint(2, "ioapic_eoi: cleared IRQ %d, pending now=%#x\n",
- i, ioapic->irq_pending);
+ dprint("ioapic_eoi: cleared IRQ %d, pending now=%#x\n", i, ioapic->irq_pending);break;
}
}
@@ -829,37 +792,13 @@
void
ioapic_init(){- int fd;
- char buf[64];
- int i;
-
- /* Create shared segment */
- fd = create("#g/vmx.ioapic", OREAD, DMDIR | 0777);- if(fd >= 0) close(fd);
-
- fd = open("#g/vmx.ioapic/ctl", OWRITE);- if(fd < 0) sysfatal("open vmx.ioapic/ctl: %r");- snprint(buf, sizeof buf, "va 0x300000000 0x1000 sticky");
- if(write(fd, buf, strlen(buf)) < 0)
- fprint(2, "write vmx.ioapic/ctl: %r");
- close(fd);
-
- ioapic = segattach(0, "vmx.ioapic", nil, 0x1000);
- if(ioapic == (void*)-1)
- sysfatal("segattach vmx.ioapic: %r");-
+ ioapic = mkseg("ioapic", 0x300000000, 0x1000);memset(ioapic, 0, sizeof(IOApic));
-
- /*
- * CRITICAL: Set I/O APIC ID to match what MP table declares!
- * MP table sets I/O APIC ID = nvcpu (after the CPU APIC IDs)
- * The ID register format is: bits 24-27 = APIC ID
- */
ioapic->id = nvcpu << 24; /* ID in bits 24-27 */
- for(i = 0; i < 24; i++){+ for(int i = 0; i < 24; i++){ if(i >= 16 && i <= 19){/* PCI interrupt pins: level-triggered, unmasked */
ioapic->redir[i] = (1 << 15) | (48 + (i - 16));
@@ -869,8 +808,7 @@
}
}
- fprint(2, "IOAPIC initialized: id=%#ux (APIC ID %d)\n",
- ioapic->id, ioapic->id >> 24);
+ dprint("IOAPIC initialized: id=%#ux (APIC ID %d)\n", ioapic->id, ioapic->id >> 24);}
@@ -888,12 +826,12 @@
switch(off){case 0x00: /* IOREGSEL */
ioapic->reg_sel[curcpuid] = val;
- if(debug) fprint(2, "IOAPIC: IOREGSEL = %#x\n", val);
+ dprint("IOAPIC: IOREGSEL = %#x\n", val);break;
case 0x10: /* IOWIN */
sel = ioapic->reg_sel[curcpuid];
- if(debug) fprint(2, "IOAPIC: IOWIN write reg=%#x val=%#x\n", sel, val);
+ dprint("IOAPIC: IOWIN write reg=%#x val=%#x\n", sel, val); switch(sel){case 0x00: /* ID */
@@ -920,9 +858,9 @@
if (debug)
if(idx == 2){if(val & 0x10000)
- fprint(2, "IOAPIC: IRQ 2 MASKED! val=%#x\n", val);
+ dprint("IOAPIC: IRQ 2 MASKED! val=%#x\n", val);else
- fprint(2, "IOAPIC: IRQ 2 UNMASKED val=%#x vector=%d\n", val, val & 0xFF);
+ dprint("IOAPIC: IRQ 2 UNMASKED val=%#x vector=%d\n", val, val & 0xFF);}
/* Check if unmasking with pending interrupt OR line high */
@@ -951,8 +889,7 @@
unlock(&ioapic->lock);
}
- if(debug) fprint(2, "IOAPIC: redir[%d] %s = %#llx\n",
- idx, (sel & 1) ? "hi" : "lo", ioapic->redir[idx]);
+ dprint("IOAPIC: redir[%d] %s = %#llx\n", idx, (sel & 1) ? "hi" : "lo", ioapic->redir[idx]);}
break;
}
@@ -959,7 +896,7 @@
done_ioapic_write:
break;
default:
- if(debug) fprint(2, "IOAPIC: write to unknown offset %#x\n", off);
+ dprint("IOAPIC: write to unknown offset %#x\n", off);}
} else { switch(off){@@ -996,7 +933,7 @@
}
}
- if(debug) fprint(2, "IOAPIC: read off=%#x val=%#x\n", off, val);
+ dprint("IOAPIC: read off=%#x val=%#x\n", off, val);setmovdest(val);
}
}
@@ -1081,21 +1018,24 @@
int pid = fork();
- if (debug)
- fprint(2, "CPU0: tscoff = %llud\n", ioapic->tsc_base);
+ dprint("CPU0: tscoff = %llud\n", ioapic->tsc_base);if(pid < 0)
sysfatal("fork failed: %r"); if(pid > 0){+ vmx_register_child(pid);
nactivecpu += 1;
return;
}
+// vmx_cleanup_init();
+
+ atnotify(vmx_notehandler, 1);
+
/* Child process */
curcpuid = nactivecpu + 1;
- if (debug)
- fprint(2, "CPU%d: child started (pid %d)\n", curcpuid, getpid());
+ dprint("CPU%d: child started (pid %d)\n", curcpuid, getpid());if(ipiqueue != nil)
ipiqueue->pids[curcpuid] = getpid();
@@ -1108,8 +1048,7 @@
for(r = mmap; r != nil; r = r->next){modregion(r);
- fprint(2, "CPU%d: mapped regions, first region v=%p segname=%s\n",
- curcpuid, r->v, r->segname);
+ dprint("CPU%d: mapped regions, first region v=%p segname=%s\n", curcpuid, r->v, r->segname);}
/* Clear register cache - must reload for new context */
@@ -1245,12 +1184,15 @@
if(waitch == nil || notifch == nil)
sysfatal("CPU%d: chancreate failed: %r", curcpuid);- fprint(2, "CPU%d: starting at %#x:0000 (linear %#x)\n",
- curcpuid, sipi << 8, sipi << 12);
+ dprint("CPU%d: starting at %#x:0000 (linear %#x)\n", curcpuid, sipi << 8, sipi << 12); rset("tscoff", 0);cached_tscoff = 0;
+
+ virtio_start_workers(); /* Start workers for CPU0 */
+
+
runloop();
/* Should never return */
@@ -1476,7 +1418,7 @@
lapic_write_tpr(u32int val)
{lapic_tpr[curcpuid] = val & 0xFF;
- if(debug) fprint(2, "CPU%d: TPR = %#x\n", curcpuid, val);
+ dprint("CPU%d: TPR = %#x\n", curcpuid, val);}
static void
@@ -1500,7 +1442,7 @@
}
}
- if(debug) fprint(2, "CPU%d: EOI vec=%d\n", curcpuid, vec);
+ dprint("CPU%d: EOI vec=%d\n", curcpuid, vec); if(vec >= 0){isr_bitmap[vec >> 5] &= ~(1 << (vec & 31));
@@ -1513,7 +1455,7 @@
static void
lapic_write_ldr(u32int val)
{- if(debug) fprint(2, "CPU%d: LDR = %#x\n", curcpuid, val);
+ dprint("CPU%d: LDR = %#x\n", curcpuid, val);if(ioapic != nil)
ioapic->ldr[curcpuid] = val & 0xFF000000; /* Only bits 31:24 are writable */
}
@@ -1521,7 +1463,7 @@
static void
lapic_write_dfr(u32int val)
{- if(debug) fprint(2, "CPU%d: DFR = %#x\n", curcpuid, val);
+ dprint("CPU%d: DFR = %#x\n", curcpuid, val);}
static void
@@ -1528,8 +1470,7 @@
lapic_write_svr(u32int val)
{lapic_svr[curcpuid] = val;
- if(debug) fprint(2, "CPU%d: SVR = %#x (LAPIC %s)\n",
- curcpuid, val, (val & 0x100) ? "enabled" : "disabled");
+ dprint("CPU%d: SVR = %#x (LAPIC %s)\n", curcpuid, val, (val & 0x100) ? "enabled" : "disabled");}
/*
@@ -1558,9 +1499,7 @@
USED(trigger);
/* Always log ICR writes - critical for debugging SMP issues */
- if (debug)
- fprint(2, "CPU%d: ICR_LO = %#x (vec=%d del=%d dest=%d short=%d)\n",
- curcpuid, val, vec, delmode, dest, shorthand);
+ dprint("CPU%d: ICR_LO = %#x (vec=%d del=%d dest=%d short=%d)\n", curcpuid, val, vec, delmode, dest, shorthand); switch(shorthand){case 0: /* No shorthand - use destination field */
@@ -1570,8 +1509,7 @@
case 0: /* Fixed */
case 1: /* Lowest priority */
if(vec == 0){- if (debug)
- fprint(2, "CPU%d: ignoring IPI with vector 0\n", curcpuid);
+ dprint("CPU%d: ignoring IPI with vector 0\n", curcpuid);break;
}
ipi_queue(target, vec);
@@ -1578,8 +1516,7 @@
break;
case 4: /* NMI */
- if (debug)
- fprint(2, "CPU%d: NMI to CPU%d\n", curcpuid, target);
+ dprint("CPU%d: NMI to CPU%d\n", curcpuid, target);if(target < nvcpu)
ipi_queue(target, 2);
break;
@@ -1586,31 +1523,29 @@
case 5: /* INIT */
- fprint(2, "CPU%d: INIT to CPU%d (init_sent was %d)\n",
- curcpuid, target, target < MAXVCPU ? init_sent[target] : -1);
+ dprint("CPU%d: INIT to CPU%d (init_sent was %d)\n", curcpuid, target, target < MAXVCPU ? init_sent[target] : -1); if(target > 0 && target < nvcpu){init_sent[target] = 1;
- fprint(2, "CPU%d: marked init_sent[%d] = 1\n", curcpuid, target);
+ dprint("CPU%d: marked init_sent[%d] = 1\n", curcpuid, target);}
break;
case 6: /* Startup IPI */
- if (debug)
- fprint(2, "CPU%d: SIPI to CPU%d at %#x (init_sent=%d)\n",
+ dprint("CPU%d: SIPI to CPU%d at %#x (init_sent=%d)\n",curcpuid, target, vec << 12,
target < MAXVCPU ? init_sent[target] : -1);
+
if(target > 0 && target < nvcpu && init_sent[target] == 1){init_sent[target] = 2;
- fprint(2, "CPU%d: forking CPU%d now\n", curcpuid, target);
+ dprint("CPU%d: forking CPU%d now\n", curcpuid, target);forkcpu(vec);
- /* Wake self - might HLT soon and need kick */
+
coherence();
- fprint(2, "CPU%d: forkcpu returned\n", curcpuid);
+ dprint("CPU%d: forkcpu returned\n", curcpuid); } else {- if (debug)
- fprint(2, "CPU%d: SIPI ignored (target=%d nvcpu=%d init_sent=%d)\n",
+ dprint("CPU%d: SIPI ignored (target=%d nvcpu=%d init_sent=%d)\n",curcpuid, target, nvcpu,
target < MAXVCPU ? init_sent[target] : -1);
}
@@ -1620,15 +1555,13 @@
case 1: /* Self */
if((delmode == 0 || delmode == 1) && vec != 0){- if (debug)
- fprint(2, "CPU%d: self-IPI (shorthand=1) vector %d (DEFERRED)\n", curcpuid, vec);
+ dprint("CPU%d: self-IPI (shorthand=1) vector %d (DEFERRED)\n", curcpuid, vec);ipi_queue(curcpuid, vec);
}
break;
case 2: /* All including self */
- if (debug)
- fprint(2, "CPU%d: IPI to ALL (including self) vec=%d del=%d\n", curcpuid, vec, delmode);
+ dprint("CPU%d: IPI to ALL (including self) vec=%d del=%d\n", curcpuid, vec, delmode); if((delmode == 0 || delmode == 1) && vec != 0){ for(i = 0; i < nvcpu; i++){ipi_queue(i, vec);
@@ -1635,13 +1568,12 @@
}
}
if(delmode == 5){- fprint(2, "CPU%d: INIT broadcast\n", curcpuid);
+ dprint("CPU%d: INIT broadcast\n", curcpuid);}
break;
case 3: /* All excluding self */
- if (debug)
- fprint(2, "CPU%d: IPI to ALL (excluding self) vec=%d del=%d\n", curcpuid, vec, delmode);
+ dprint("CPU%d: IPI to ALL (excluding self) vec=%d del=%d\n", curcpuid, vec, delmode); if((delmode == 0 || delmode == 1) && vec != 0){ for(i = 0; i < nvcpu; i++){if(i != curcpuid)
@@ -1656,8 +1588,7 @@
lapic_write_icr_hi(u32int val)
{icr_hi_saved = val;
- if(debug) fprint(2, "CPU%d: ICR_HI = %#x (dest=%d)\n",
- curcpuid, val, val >> 24);
+ dprint("CPU%d: ICR_HI = %#x (dest=%d)\n", curcpuid, val, val >> 24);}
@@ -1683,7 +1614,7 @@
{int vec = val & 0xFF;
if(vec != 0){- if(debug) fprint(2, "CPU%d: SELF_IPI register vec=%d\n", curcpuid, vec);
+ dprint("CPU%d: SELF_IPI register vec=%d\n", curcpuid, vec);ipi_queue(curcpuid, vec);
}
}
@@ -1698,7 +1629,7 @@
int iswrite = (ei->qual & 2) != 0;
u32int val;
- if(debug) fprint(2, "LAPIC: off=%#x %s\n", off, iswrite ? "write" : "read");
+ dprint("LAPIC: off=%#x %s\n", off, iswrite ? "write" : "read"); if(iswrite){val = getmovval();
@@ -1716,7 +1647,7 @@
case LAPIC_TIMER_DCR: lapic_write_divide_config(val); break;
case LAPIC_SELF_IPI: lapic_write_self_ipi(val); break;
default:
- if(debug) fprint(2, "LAPIC: write to %#x ignored\n", off);
+ dprint("LAPIC: write to %#x ignored\n", off);}
} else { switch(off){@@ -1751,7 +1682,7 @@
default:
val = 0;
- if(debug) fprint(2, "LAPIC: read from %#x returning 0\n", off);
+ dprint("LAPIC: read from %#x returning 0\n", off);}
setmovdest(val);
@@ -1793,8 +1724,7 @@
eptfault_count++;
/* Always log EPT faults to help debug SMP issues */
- if (debug)
- fprint(2, "CPU%d EPT[%lld]: pa=%#llux va=%#llux qual=%#llux\n",
+ dprint("CPU%d EPT[%lld]: pa=%#llux va=%#llux qual=%#llux\n",curcpuid, eptfault_count, ei->pa, ei->va, ei->qual);
/* I/O APIC MMIO */
@@ -1818,10 +1748,10 @@
/* Other EPT faults - log and continue */
if(ei->pa < 0x1000){u32int val = getmovval();
- fprint(2, "CPU%d LOW MEM WRITE: pa=%#llx val=%#x\n", curcpuid, ei->pa, val);
+ dprint("CPU%d LOW MEM WRITE: pa=%#llx val=%#x\n", curcpuid, ei->pa, val); } else {/* Unexpected EPT fault - could indicate memory mapping issue */
- fprint(2, "CPU%d UNEXPECTED EPT: pa=%#llx va=%#llx qual=%#llx\n",
+ dprint("CPU%d UNEXPECTED EPT: pa=%#llx va=%#llx qual=%#llx\n",curcpuid, ei->pa, ei->va, ei->qual);
}
@@ -2147,7 +2077,7 @@
ax = rget(RAX);
cx = rget(RCX);
- if(debug) fprint(2, "CPU%d: CPUID eax=%#x ecx=%#x\n", curcpuid, ax, cx);
+ dprint("CPU%d: CPUID eax=%#x ecx=%#x\n", curcpuid, ax, cx);bx = dx = 0;
cp = getcpuid(ax, cx);
@@ -2272,7 +2202,7 @@
bx = 0;
cx = 0;
dx = (1 << 8); /* Invariant TSC */
- fprint(2, "CPUID[80000007]: returning dx=%#x (InvariantTSC=%d)\n", dx, (dx >> 8) & 1);
+ dprint("CPUID[80000007]: returning dx=%#x (InvariantTSC=%d)\n", dx, (dx >> 8) & 1);break;
case 0x80000008: goto literal;
literal:
@@ -2307,7 +2237,7 @@
cx = rget(RCX);
val = (uvlong)rget(RDX) << 32 | rget(RAX);
- if(debug) fprint(2, "CPU%d: MSR %s cx=%#x\n", curcpuid, rd?"read":"write", cx);
+ dprint("CPU%d: MSR %s cx=%#x\n", curcpuid, rd?"read":"write", cx); switch(cx){case 0x10: /* IA32_TIME_STAMP_COUNTER */
@@ -2347,8 +2277,7 @@
if(rd)
val = lapic_read_tsc_deadline();
else {- if (debug)
- fprint(2, "CPU%d: TSC_DEADLINE=%llud\n", curcpuid, val);
+ dprint("CPU%d: TSC_DEADLINE=%llud\n", curcpuid, val);lapic_write_tsc_deadline(val);
pvclock_update(curcpuid); /* Keep kvmclock in sync */
@@ -2453,7 +2382,7 @@
exit_count++;
vlong now = nanosec();
if(now - last_report > 1000000000LL) { // Every 1 second- fprint(2, "EXIT RATE: %llud/sec\n", exit_count);
+ dprint("EXIT RATE: %llud/sec\n", exit_count);exit_count = 0;
last_report = now;
}
@@ -2460,16 +2389,15 @@
static vlong lastpreempt;
+ dprint("EXIT: %s\n", msg);- if (debug) {- fprint(2, "EXIT: %s\n", msg);
-
if(strncmp(msg, "preempt", 7) == 0){if(lastpreempt != 0)
- fprint(2, "PREEMPT CPU%d: delta=%lldms\n", curcpuid, (now - lastpreempt)/1000000);
+ dprint("PREEMPT CPU%d: delta=%lldms\n", curcpuid, (now - lastpreempt)/1000000);lastpreempt = now;
}
- }
+
+
strcpy(msgc, msg);
nf = tokenize(msgc, f, nelem(f));
--- a/fns.h
+++ b/fns.h
@@ -1,8 +1,12 @@
#define MIN(a,b) ((a)<(b)?(a):(b))
#define MAX(a,b) ((a)>(b)?(a):(b))
-
+void virtio_start_workers(void);
int irr_pending(void);
-
+void *mkseg(char *name, uintptr va, ulong size);
+void rmseg(char *name);
+extern int vmx_notehandler(void *, char *);
+extern void vmx_cleanup_init(void);
+extern void vmx_register_child(int pid);
void lapic_timer_init(void);
void ipi_send(int, int);
u32int lapic_divide_value(u32int);
--- a/hpet.c
+++ b/hpet.c
@@ -170,15 +170,10 @@
/* Fire interrupts outside lock */
for(i = 0; i < 3; i++){ if(should_fire[i]){- if(debug)
- fprint(2, "HPET: timer %d fired! irq=%d periodic=%d\n",
+ dprint("HPET: timer %d fired! irq=%d periodic=%d\n", i, irqs[i], is_periodic[i]);
ioapic_irqline_smp(irqs[i], 1);
-// ioapic_set_irq(irqs[i], 1);
-
-// if(state == VMHALT)
-// state = VMRUNNING;
}
}
}
@@ -223,8 +218,7 @@
int timer;
int state_changed = 0; /* Track if we need to kick CPU0 */
- if(debug)
- fprint(2, "HPET write: offset=%#x val=%#x size=%d\n", offset, val, size);
+ dprint("HPET write: offset=%#x val=%#x size=%d\n", offset, val, size);lock(&hpet->lock);
@@ -242,8 +236,7 @@
if(was_enabled && !new_enabled){/* Stopping: save current counter value */
hpet->counter_offset = hpet_counter_unlocked();
- if(debug)
- fprint(2, "HPET: DISABLED counter=%#llx\n", hpet->counter_offset);
+ dprint("HPET: DISABLED counter=%#llx\n", hpet->counter_offset);}
if(size == 4)
@@ -256,9 +249,8 @@
if(!was_enabled && new_enabled){/* Starting: record real host time */
hpet->time_at_enable = nanosec();
- if(debug)
- fprint(2, "HPET: ENABLED time=%llud counter_offset=%#llx legacy=%d\n",
- hpet->time_at_enable, hpet->counter_offset, (hpet->cfg >> 1) & 1);
+ dprint("HPET: ENABLED time=%llud counter_offset=%#llx legacy=%d\n", + hpet->time_at_enable, hpet->counter_offset, (hpet->cfg >> 1) & 1);
}
state_changed = 1;
@@ -294,8 +286,7 @@
hpet->counter_offset = (hpet->counter_offset & 0xFFFFFFFF00000000ULL) | val;
else
hpet->counter_offset = val;
- if(debug)
- fprint(2, "HPET: counter set to %#llx\n", hpet->counter_offset);
+ dprint("HPET: counter set to %#llx\n", hpet->counter_offset);}
break;
@@ -302,8 +293,7 @@
case HPET_COUNTER + 4:
if(!hpet->enabled){hpet->counter_offset = (hpet->counter_offset & 0xFFFFFFFF) | ((u64int)val << 32);
- if(debug)
- fprint(2, "HPET: counter set to %#llx\n", hpet->counter_offset);
+ dprint("HPET: counter set to %#llx\n", hpet->counter_offset);}
break;
@@ -311,8 +301,7 @@
case HPET_T0_CFG:
hpet->timer[0].cfg = (size == 4) ?
(hpet->timer[0].cfg & 0xFFFFFFFF00000000ULL) | val : val;
- if(debug)
- fprint(2, "HPET: T0 cfg=%#llx int_enb=%d periodic=%d\n",
+ dprint("HPET: T0 cfg=%#llx int_enb=%d periodic=%d\n", hpet->timer[0].cfg,
(hpet->timer[0].cfg >> 2) & 1,
(hpet->timer[0].cfg >> 3) & 1);
@@ -329,12 +318,10 @@
/* If VAL_SET bit is set in periodic mode, this also sets the period */
if((hpet->timer[0].cfg & TN_TYPE) && (hpet->timer[0].cfg & TN_VAL_SET)){hpet->timer[0].period = hpet->timer[0].cmp;
- if(debug)
- fprint(2, "HPET: T0 period set to %#llx\n", hpet->timer[0].period);
+ dprint("HPET: T0 period set to %#llx\n", hpet->timer[0].period);}
hpet->timer[0].active = 1;
- if(debug)
- fprint(2, "HPET: T0 cmp=%#llx counter=%#llx active=1 int_enb=%d\n",
+ dprint("HPET: T0 cmp=%#llx counter=%#llx active=1 int_enb=%d\n", hpet->timer[0].cmp, hpet_counter_unlocked(),
(hpet->timer[0].cfg & TN_INT_ENB) ? 1 : 0);
state_changed = 1;
@@ -416,5 +403,5 @@
hpet->counter_offset = 0;
hpet->time_at_enable = 0;
- fprint(2, "HPET: init (shared via vioalloc)\n");
+ dprint("HPET: init (shared via vioalloc)\n");}
--- a/io.c
+++ b/io.c
@@ -267,13 +267,11 @@
continue;
lock(&kbdshared->lk);
- if (debug)
- fprint(2, "IOBUF: kbdreader WRITE r=%d w=%d char=%#x\n",
+ dprint("IOBUF: kbdreader WRITE r=%d w=%d char=%#x\n",(int)kbdshared->r, (int)kbdshared->w, c);
kbdshared->buf[kbdshared->w & (KBD_BUF_SIZE - 1)] = c;
kbdshared->w += 1;
- if (debug)
- fprint(2, "IOBUF: kbdreader AFTER r=%d w=%d\n", (int)kbdshared->r, (int)kbdshared->w);
+ dprint("IOBUF: kbdreader AFTER r=%d w=%d\n", (int)kbdshared->r, (int)kbdshared->w);unlock(&kbdshared->lk);
sendnotif(i8042kick, nil);
@@ -688,8 +686,7 @@
mouse->state = MOUSESTREAM | MOUSEREP;
mouse->res = 2;
mouse->rate = 100;
- if (debug)
- fprint(2, "MOUSE: mouseps2init done, mouse=%p\n", mouse);
+ dprint("MOUSE: mouseps2init done, mouse=%p\n", mouse);}
static void
@@ -878,8 +875,7 @@
mousecmd(u8int val)
{/* incmd is already set and buffer is flushed by caller (i8042io 0xd4 case) */
- if (debug)
- fprint(2, "MOUSE: cmd %#x state=%#x bufr=%d bufw=%d\n",
+ dprint("MOUSE: cmd %#x state=%#x bufr=%d bufw=%d\n", val, mouse->state, mouse->bufr, mouse->bufw);
if((mouse->state & MOUSEWRAP) != 0 && val != 0xec && val != 0xff){@@ -931,8 +927,7 @@
case 0xf2:
mousecmdputc(0xfa);
mousecmdputc(mouse->id);
- if (debug)
- fprint(2, "MOUSE: F2 sent ACK+ID - cmdbuf[0]=%#x cmdbuf[1]=%#x cmdr=%d cmdw=%d\n",
+ dprint("MOUSE: F2 sent ACK+ID - cmdbuf[0]=%#x cmdbuf[1]=%#x cmdr=%d cmdw=%d\n",mouse->cmdbuf[0], mouse->cmdbuf[1], mouse->cmdr, mouse->cmdw);
clearmouse(); break; /* report device id */
@@ -965,8 +960,7 @@
lock(&i8042->lk);
if(mouse->cmdr != mouse->cmdw && i8042->buf == 0){u8int c = mouse->cmdbuf[mouse->cmdr++ & 7];
- if (debug)
- fprint(2, "MOUSE: cmd delivering response 0x%x\n", c);
+ dprint("MOUSE: cmd delivering response 0x%x\n", c);i8042->buf = 0x200 | c;
i8042->stat |= 0x21;
i8042->oport |= 0x20;
@@ -1015,7 +1009,7 @@
if(i8042->buf != 0){bufstuck++;
if(bufstuck == 10000)
- fprint(2, "STUCK: buf=%#x stuck for 10000 kicks, cfg=%#x stat=%#x\n",
+ dprint("STUCK: buf=%#x stuck for 10000 kicks, cfg=%#x stat=%#x\n",i8042->buf, i8042->cfg, i8042->stat);
} else {bufstuck = 0;
@@ -1022,8 +1016,7 @@
}
if((kickcount % 5000) == 0){- if (debug)
- fprint(2, "KICK[%d]: mouse=%p buf=%#x cfg=%#x incmd=%d bufr=%d bufw=%d cmdr=%d cmdw=%d irq12=%d\n",
+ dprint("KICK[%d]: mouse=%p buf=%#x cfg=%#x incmd=%d bufr=%d bufw=%d cmdr=%d cmdw=%d irq12=%d\n",kickcount, mouse, i8042->buf, i8042->cfg,
mouse ? mouse->incmd : -1,
mouse ? mouse->bufr : -1,
@@ -1116,8 +1109,7 @@
if(i8042->cmd == 0){i8042->mouseactive = 1;
i8042->cmd = -1;
- if (debug)
- fprint(2, "MOUSE: init mouseactive=1\n");
+ dprint("MOUSE: init mouseactive=1\n");}
unlock(&i8042->lk);
@@ -1124,8 +1116,7 @@
val = (u8int)val;
switch(isin << 16 | port){case 0x60:
- if (debug)
- fprint(2, "I8042: port 0x60 WRITE val=%#x cmd=%d\n", val, i8042->cmd);
+ dprint("I8042: port 0x60 WRITE val=%#x cmd=%d\n", val, i8042->cmd);lock(&i8042->lk);
i8042->stat &= ~8;
switch(i8042->cmd){@@ -1134,8 +1125,7 @@
/* Don't let config byte disable mouse - only A7/A8 commands do that.
* Guests without psmouse driver write 0x65 (bit 5 set) at end of probe,
* which would disable our mouse even though we want it active. */
- if (debug)
- fprint(2, "MOUSE: cfg=%#x mouseactive=%d (unchanged)\n", val, i8042->mouseactive);
+ dprint("MOUSE: cfg=%#x mouseactive=%d (unchanged)\n", val, i8042->mouseactive);break;
case 0xd1:
i8042->oport = val;
@@ -1156,8 +1146,7 @@
lock(&i8042->lk);
break;
case 0xd4:
- if (debug)
- fprint(2, "MOUSE: forwarding %#x to mouse, cfg=%#x buf=%#x\n", val, i8042->cfg, i8042->buf);
+ dprint("MOUSE: forwarding %#x to mouse, cfg=%#x buf=%#x\n", val, i8042->cfg, i8042->buf);/* Set incmd BEFORE unlocking to prevent race with i8042kick */
mouse->incmd = 1;
/* Clear any unread mouse data from i8042->buf and flush cmdbuf */
@@ -1171,19 +1160,16 @@
/* mousecmd may have already delivered first byte */
/* Only deliver here if buffer is still empty */
lock(&i8042->lk);
- if (debug)
- fprint(2, "MOUSE: after mousecmd, buf=%#x cmdr=%d cmdw=%d\n", i8042->buf, mouse->cmdr, mouse->cmdw);
+ dprint("MOUSE: after mousecmd, buf=%#x cmdr=%d cmdw=%d\n", i8042->buf, mouse->cmdr, mouse->cmdw); if(i8042->buf == 0 && mouse->cmdr != mouse->cmdw){uchar c = mouse->cmdbuf[mouse->cmdr++ & 7];
- if (debug)
- fprint(2, "MOUSE: D4 delivering response %#x\n", c);
+ dprint("MOUSE: D4 delivering response %#x\n", c);i8042->buf = 0x200 | c;
i8042->stat |= 0x21; /* OBF (bit 0) + aux data flag (bit 5) */
i8042->oport |= 0x20;
if((i8042->cfg & 2) != 0){unlock(&i8042->lk);
- if (debug)
- fprint(2, "MOUSE: firing IRQ 12 for response %#x\n", c);
+ dprint("MOUSE: firing IRQ 12 for response %#x\n", c);ioapic_irqline_smp(12, 1);
lock(&i8042->lk);
}
@@ -1203,8 +1189,7 @@
case 0x10060:
i8042kick(nil);
lock(&i8042->lk);
- if (debug)
- fprint(2, "I8042: i8042io READ buf=%#x stat=%#x\n", i8042->buf, i8042->stat);
+ dprint("I8042: i8042io READ buf=%#x stat=%#x\n", i8042->buf, i8042->stat);rc = i8042->buf;
unlock(&i8042->lk);
i8042putbuf(0);
@@ -1211,8 +1196,7 @@
return rc;
case 0x64:
- if (debug)
- fprint(2, "I8042: port 0x64 WRITE cmd=%#x\n", val);
+ dprint("I8042: port 0x64 WRITE cmd=%#x\n", val);lock(&i8042->lk);
i8042->stat |= 8;
switch(val){@@ -1236,8 +1220,7 @@
unlock(&i8042->lk);
return 0;
case 0xa9:
- if (debug)
- fprint(2, "I8042: test aux port (0xA9)\n");
+ dprint("I8042: test aux port (0xA9)\n");unlock(&i8042->lk);
i8042putbuf(0x400); // was 0x400 ?
return 0;
@@ -1263,8 +1246,7 @@
i8042putbuf(0x400 | oport);
return 0;
case 0x60: case 0xd1: case 0xd2: case 0xd3: case 0xd4:
- if (debug)
- fprint(2, "I8042: aux write cmd=0xD4, data will follow\n");
+ dprint("I8042: aux write cmd=0xD4, data will follow\n");i8042->cmd = val;
unlock(&i8042->lk);
return 0;
@@ -1285,8 +1267,7 @@
i8042kick(nil);
lock(&i8042->lk);
rc = i8042->stat | i8042->cfg & 4;
- if (debug)
- fprint(2, "I8042: port 0x64 READ stat=%#x\n", rc);
+ dprint("I8042: port 0x64 READ stat=%#x\n", rc);unlock(&i8042->lk);
return rc;
}
@@ -1657,7 +1638,7 @@
proccreate(uarttxproc, (void*)(uintptr)n, 4096);
}
- fprint(2, "UART%d: initialized infd=%d outfd=%d\n", n, uart[n].infd, uart[n].outfd);
+ dprint("UART%d: initialized infd=%d outfd=%d\n", n, uart[n].infd, uart[n].outfd);}
--- a/io_timer.c
+++ b/io_timer.c
@@ -272,7 +272,7 @@
pitshared = vioalloc(sizeof(PitShared));
memset(pitshared, 0, sizeof(PitShared));
pitshared->ch[0].state = 1;
- fprint(2, "PIT: initialized (shared)\n");
+ dprint("PIT: initialized (shared)\n");}
/* ============================================================
@@ -489,5 +489,5 @@
rtcshared->rtcnext = -1;
rtcshared->cmosinit = 0;
- fprint(2, "RTC: initialized (shared)\n");
+ dprint("RTC: initialized (shared)\n");}
--- a/mkfile
+++ b/mkfile
@@ -22,6 +22,7 @@
hpet.$O \
pvclock.$O \
io_timer.$O \
+ cleanup.$O \
</sys/src/cmd/mkone
--- a/mptable.c
+++ b/mptable.c
@@ -298,7 +298,7 @@
cfg[7] = -mpchecksum(cfg, tbllen);
/* Debug: print what we created */
- vmerror("mpmktable: created MP table at 0xF0000");- vmerror(" %d CPUs, %d entries, %d bytes", ncpu, entries, tbllen);- vmerror(" PCI bus ID=%d, ISA bus ID=%d", BUS_PCI, BUS_ISA);+ dprint("mpmktable: created MP table at 0xF0000");+ dprint(" %d CPUs, %d entries, %d bytes", ncpu, entries, tbllen);+ dprint(" PCI bus ID=%d, ISA bus ID=%d", BUS_PCI, BUS_ISA);}
--- a/pci.c
+++ b/pci.c
@@ -7,6 +7,9 @@
PCIDev *pcidevs;
PCIBar membars, iobars;
+
+static PCIDev *pcidevtab[32];
+
PciShared *pcishared;
static int
@@ -65,6 +68,10 @@
d->capalloc = 64;
pcidevs = d;
+ int dev = 0;
+ dev = (bdf >> 11) & 0x1f;
+ pcidevtab[dev] = d;
+
pciregister(d);
return d;
@@ -76,7 +83,7 @@
{static int dev = 1;
u32int bdf = BDF(0, dev, 0);
- fprint(2, "allocbdf: dev=%d BDF=%#x\n", dev, bdf);
+ dprint("allocbdf: dev=%d BDF=%#x\n", dev, bdf);dev++;
return bdf;
}
@@ -201,22 +208,20 @@
*p = c;
return c;
}
+
static PCIDev *
findpcidev(u32int bdf)
{- PCIDev *d;
- if (debug)
- fprint(2, "findpcidev: looking for bdf=%#x\n", bdf);
- for(d = pcidevs; d != nil; d = d->next) {- if (debug)
- fprint(2, " checking d->bdf=%#x\n", d->bdf);
- if(d->bdf == bdf)
- return d;
- }
- if (debug)
- fprint(2, " not found!\n");
- return nil;
+ int dev;
+
+ if((bdf & 0xff0000) != 0) /* bus != 0 */
+ return nil;
+ if((bdf & 0x700) != 0) /* function != 0 */
+ return nil;
+
+ dev = (bdf >> 11) & 0x1f;
+ return pcidevtab[dev];
}
static PCICap *
@@ -238,7 +243,7 @@
int n, idx;
/* Lock and sync from shared memory */
- if(pcishared != nil){+ if(pcishared != nil && d->cache_gen != pcishared->generation){lock(&pcishared->lock);
idx = d->sharedidx;
if(idx >= 0){@@ -247,15 +252,14 @@
for(n = 0; n < 6; n++)
d->bar[n].addr = pcishared->dev[idx].bar_addr[n];
}
+ d->cache_gen = pcishared->generation;
unlock(&pcishared->lock);
}
- if (debug)
- fprint(2, "pciread: d=%p bdf=%#x addr=%#x\n", d, d->bdf, addr);
+ dprint("pciread: d=%p bdf=%#x addr=%#x\n", d, d->bdf, addr); switch(addr){case 0x00:
- if (debug)
- fprint(2, "pciread: returning viddid=%#x\n", d->viddid);
+ dprint("pciread: returning viddid=%#x\n", d->viddid);return d->viddid;
case 0x04: return 0xa00000 | (d->cap != nil ? 1<<20 : 0) | d->ctrl;
case 0x08: return d->clrev;
@@ -292,7 +296,7 @@
int n, idx;
/* Lock and sync from shared memory */
- if(pcishared != nil){+ if(pcishared != nil && d->cache_gen != pcishared->generation){//lock(&pcishared->lock);
idx = d->sharedidx;
if(idx >= 0){@@ -301,15 +305,14 @@
for(n = 0; n < 6; n++)
d->bar[n].addr = pcishared->dev[idx].bar_addr[n];
}
+ d->cache_gen = pcishared->generation;
//unlock(&pcishared->lock);
}
- if (debug)
- fprint(2, "pciread: d=%p bdf=%#x addr=%#x\n", d, d->bdf, addr);
+ dprint("pciread: d=%p bdf=%#x addr=%#x\n", d, d->bdf, addr); switch(addr){case 0x00:
- if (debug)
- fprint(2, "pciread: returning viddid=%#x\n", d->viddid);
+ dprint("pciread: returning viddid=%#x\n", d->viddid);return d->viddid;
case 0x04: return 0xa00000 | (d->cap != nil ? 1<<20 : 0) | d->ctrl;
case 0x08: return d->clrev;
@@ -390,6 +393,7 @@
pcishared->dev[idx].irqno = d->irqno;
for(n = 0; n < 6; n++)
pcishared->dev[idx].bar_addr[n] = d->bar[n].addr;
+ pcishared->generation++;
}
unlock(&pcishared->lock);
}
@@ -527,23 +531,19 @@
d->irqactive = status != 0;
devno = (d->bdf >> 11) & 0x1f;
pin = 16 + (devno % 4);
- if (debug)
- fprint(2, "pciirq: bdf=%#x devno=%d irqno=%d status=%d pin=%d ioapic=%p\n",
+ dprint("pciirq: bdf=%#x devno=%d irqno=%d status=%d pin=%d ioapic=%p\n",d->bdf, devno, d->irqno, status, pin, ioapic);
if(ioapic != nil){- if (debug)
- fprint(2, "pciirq: using IOAPIC path, calling ioapic_set_irq(%d, %d)\n",
+ dprint("pciirq: using IOAPIC path, calling ioapic_set_irq(%d, %d)\n", pin, d->irqactive);
ioapic_irqline_smp(pin, d->irqactive);
} else if(d->irqno < 16){- if (debug)
- fprint(2, "pciirq: using legacy PIC path, irqline(%d, %d)\n",
+ dprint("pciirq: using legacy PIC path, irqline(%d, %d)\n",d->irqno, d->irqactive ? 0 : 1);
ioapic_irqline_smp(d->irqno, d->irqactive ? 0 : 1);
} else {- if (debug)
- fprint(2, "pciirq: NO PATH TAKEN - ioapic=%p irqno=%d\n",
+ dprint("pciirq: NO PATH TAKEN - ioapic=%p irqno=%d\n", ioapic, d->irqno);
}
}
@@ -627,6 +627,7 @@
pcishared->dev[idx].bar_addr[i] = d->bar[i].addr;
}
}
+ pcishared->generation++;
unlock(&pcishared->lock);
}
@@ -641,21 +642,21 @@
extern IOApic *ioapic;
extern u32int lapic_svr[];
- fprint(2, "=== PCI Dump ===\n");
- fprint(2, "ioapic=%p, lapic_svr[0]=%#ux (APIC %s)\n",
+ dprint("=== PCI Dump ===\n");+ dprint("ioapic=%p, lapic_svr[0]=%#ux (APIC %s)\n", ioapic, lapic_svr[0], (lapic_svr[0] & 0x100) ? "enabled" : "disabled");
for(d = pcidevs, i = 0; d != nil; d = d->next, i++){- fprint(2, "[%d] bdf=%#ux viddid=%#ux class=%#ux irqno=%d irqactive=%d ctrl=%#ux\n",
+ dprint("[%d] bdf=%#ux viddid=%#ux class=%#ux irqno=%d irqactive=%d ctrl=%#ux\n",i, d->bdf, d->viddid, d->clrev >> 8, d->irqno, d->irqactive, d->ctrl);
for(j = 0; j < 6; j++){b = &d->bar[j];
if(b->length > 0)
- fprint(2, " BAR%d: type=%#ux addr=%#ux len=%#ux io=%p\n",
+ dprint(" BAR%d: type=%#ux addr=%#ux len=%#ux io=%p\n",j, b->type, b->addr, b->length, b->io);
}
}
- fprint(2, "================\n");
+ dprint("================\n");}
PciShared *pcishared;
@@ -663,30 +664,7 @@
void
pcisharedinit(void)
{- int fd;
- char buf[128];
-
- remove("#g/vmx.pci/ctl");- remove("#g/vmx.pci");-
- snprint(buf, sizeof(buf), "#g/vmx.pci");
- fd = create(buf, OREAD, DMDIR | 0777);
- if(fd >= 0) close(fd);
-
- snprint(buf, sizeof(buf), "#g/vmx.pci/ctl");
- fd = open(buf, OWRITE|OTRUNC);
- if(fd < 0) {- fprint(2, "pcisharedinit: cannot open ctl: %r\n");
- return;
- }
- snprint(buf, sizeof(buf), "va 0x300002000 0x1000 sticky");
- write(fd, buf, strlen(buf));
- close(fd);
-
- pcishared = segattach(0, "vmx.pci", nil, 0x1000);
- if(pcishared == (void*)-1)
- sysfatal("segattach vmx.pci: %r");-
+ pcishared = mkseg("pci", 0x300002000, 0x1000);memset(pcishared, 0, sizeof(PciShared));
}
--- a/pvclock.c
+++ b/pvclock.c
@@ -78,7 +78,7 @@
tsc_mul = (u32int)mul64;
- fprint(2, "pvclock: tsc_freq=%llud mul=%ud shift=%d\n",
+ dprint("pvclock: tsc_freq=%llud mul=%ud shift=%d\n",tsc_freq, tsc_mul, tsc_shift);
}
@@ -87,7 +87,7 @@
{compute_tsc_params();
boot_ns = nanosec();
- fprint(2, "pvclock: boot_ns=%llud\n", boot_ns);
+ dprint("pvclock: boot_ns=%llud\n", boot_ns);}
/*
@@ -137,7 +137,7 @@
static void
pvclock_setup(int cpu)
{- fprint(2, "CPU%d: pvclock setup gpa=%#llux tscoff=%lld\n",
+ dprint("CPU%d: pvclock setup gpa=%#llux tscoff=%lld\n",cpu, pvclock_gpa[cpu], (vlong)cached_tscoff);
pvclock_update(cpu);
}
@@ -169,7 +169,7 @@
coherence();
wc->version = 2;
- fprint(2, "wallclock: sec=%lld at boot\n", wall_sec);
+ dprint("wallclock: sec=%lld at boot\n", wall_sec);}
int
@@ -184,7 +184,7 @@
pvclock_gpa[cpu] = *val & ~1ULL;
pvclock_enabled[cpu] = *val & 1;
- fprint(2, "CPU%d: pvclock MSR write gpa=%#llux enabled=%d\n",
+ dprint("CPU%d: pvclock MSR write gpa=%#llux enabled=%d\n",cpu, pvclock_gpa[cpu], pvclock_enabled[cpu]);
if(pvclock_enabled[cpu])
@@ -197,7 +197,7 @@
case MSR_KVM_WALL_CLOCK_NEW:
if(write){wallclock_gpa = *val;
- fprint(2, "wallclock: GPA set to %#llux\n", wallclock_gpa);
+ dprint("wallclock: GPA set to %#llux\n", wallclock_gpa);wallclock_update();
} else {*val = wallclock_gpa;
--- a/timer.c
+++ b/timer.c
@@ -332,8 +332,7 @@
timer_initialized = 1;
- fprint(2, "CPU%d: timer_init tsc_freq=%llud preempt_shift=%d backstop=%lldms\n",
- curcpuid, tsc_freq, preempt_shift, BACKSTOP_NS_FIXED / 1000000);
+ dprint("CPU%d: timer_init tsc_freq=%llud preempt_shift=%d backstop=%lldms\n", curcpuid, tsc_freq, preempt_shift, BACKSTOP_NS_FIXED / 1000000);}
/*
@@ -459,9 +458,7 @@
la->timer_active = 1;
la->timer_current = initial;
- if(debug)
- fprint(2, "LAPIC%d: timer started, initial=%ud divide=%ud period=%lldns deadline=%lld\n",
- curcpuid, initial, divide, period_ns, la->timer_deadline);
+ dprint("LAPIC%d: timer started, initial=%ud divide=%ud period=%lldns deadline=%lld\n", curcpuid, initial, divide, period_ns, la->timer_deadline);/* Only arm if not masked */
if(!(la->lvt_timer & (1<<16)))
@@ -489,9 +486,7 @@
vector = la->lvt_timer & 0xFF;
periodic = (la->lvt_timer >> 17) & 1;
- if(debug)
- fprint(2, "LAPIC%d: FIRING timer! now=%lld deadline=%lld vec=%d\n",
- curcpuid, now, la->timer_deadline, vector);
+ dprint("LAPIC%d: FIRING timer! now=%lld deadline=%lld vec=%d\n", curcpuid, now, la->timer_deadline, vector);/* Fire the interrupt if not masked and vector is valid */
if(vector != 0 && (la->lvt_timer & (1<<16)) == 0)
@@ -534,8 +529,7 @@
{LApic *la = &lapic;
- if(debug)
- fprint(2, "LAPIC%d: TIMER_INIT = %ud\n", curcpuid, val);
+ dprint("LAPIC%d: TIMER_INIT = %ud\n", curcpuid, val);la->timer_initial = val;
lapic_timer_start();
@@ -563,9 +557,7 @@
timer_cancel(TIMER_DEADLINE);
}
- if(debug)
- fprint(2, "LAPIC%d: LVT_TIMER = %#x (vec=%d mode=%d mask=%d)\n",
- curcpuid, val, val & 0xFF, new_mode, (val >> 16) & 1);
+ dprint("LAPIC%d: LVT_TIMER = %#x (vec=%d mode=%d mask=%d)\n", curcpuid, val, val & 0xFF, new_mode, (val >> 16) & 1);/* Only start counter-based timer if not in deadline mode */
if(new_mode != MODE_DEADLINE && !(val & (1<<16)) && la->timer_initial > 0)
@@ -603,8 +595,7 @@
{LApic *la = &lapic;
- if(debug)
- fprint(2, "CPU%d: TSC_DEADLINE=%llud\n", curcpuid, val);
+ dprint("CPU%d: TSC_DEADLINE=%llud\n", curcpuid, val);la->tsc_deadline = val;
@@ -662,8 +653,7 @@
if(guest_tsc >= la->tsc_deadline){vector = la->lvt_timer & 0xFF;
- if(debug)
- fprint(2, "LAPIC%d: TSC deadline fired! vec=%d\n", curcpuid, vector);
+ dprint("LAPIC%d: TSC deadline fired! vec=%d\n", curcpuid, vector);la->tsc_deadline = 0;
la->tsc_deadline_armed = 0;
@@ -718,7 +708,7 @@
vmtime_init(void)
{vmtime_initialized = 1;
- fprint(2, "vmtime_init: using nanosec() directly\n");
+ dprint("vmtime_init: using nanosec() directly\n");}
uvlong
--- a/virtio.c
+++ b/virtio.c
@@ -7,8 +7,10 @@
#include <ip.h> /* parseether() */
#include <libsec.h> /* genrandom() */
+static int local_devpipes[8][2] = {{-1,-1},{-1,-1},{-1,-1},{-1,-1},{-1,-1},{-1,-1},{-1,-1},{-1,-1}};+
+
-
typedef struct VIODev VIODev;
typedef struct VIOQueue VIOQueue;
@@ -73,9 +75,10 @@
struct VIODev {PCIDev *pci;
+ int isrstat ; /* per-CPU instead of single */
u32int devfeat, guestfeat;
u16int qsel;
- u8int devstat, isrstat;
+ u8int devstat ;
VIOQueue *qu;
int nqu, allocqu;
u32int (*io)(int, u16int, u32int, int, VIODev *);
@@ -119,28 +122,8 @@
void
viosharedinit(void)
{- int fd;
- char buf[64];
-
- remove("#g/vmx.vio/ctl");- remove("#g/vmx.vio");-
- fd = create("#g/vmx.vio", OREAD, DMDIR | 0777);- if(fd >= 0) close(fd);
-
- fd = open("#g/vmx.vio/ctl", OWRITE);- if(fd < 0)
- sysfatal("viosharedinit: %r");-
- snprint(buf, sizeof buf, "va 0x300004000 0x10000 sticky");
- write(fd, buf, strlen(buf));
- close(fd);
-
- vioshared = segattach(0, "vmx.vio", nil, 0x10000);
- if(vioshared == (void*)-1)
- sysfatal("viosharedinit segattach: %r");-
- memset(vioshared, 0, sizeof(VIOShared));
+ vioshared = mkseg("vio", 0x300004000, 0x10000);+ memset(vioshared, 0, sizeof(VIOShared));
ndevpipes = 0;
/* Allocate shared keyboard buffer */
@@ -180,7 +163,7 @@
static void
vioirq(VIODev *d, int val)
{- int newstat;
+ int idx = d->devidx;
lock(&d->isrlk);
if(val != 0)
@@ -187,10 +170,13 @@
d->isrstat |= val;
else
d->isrstat = 0;
- newstat = d->isrstat;
- unlock(&d->isrlk);
+
+ unlock(&d->isrlk);
+
+
+ pciirq(d->pci, val != 0);
- pciirq(d->pci, newstat != 0);
+// pciirq(d->pci, val != 0);
}
static void *
@@ -319,8 +305,7 @@
coherence();
}
- if(debug)
- fprint(2, "VIOPUTBUF: usedidx=%d id=%d len=%d avail_flags=%#x\n",
+ dprint("VIOPUTBUF: usedidx=%d id=%d len=%d avail_flags=%#x\n",q->usedidx, b->idx, b->wptr, GET16(q->avail, 0));
int need_irq = (q->avail != nil && (GET16(q->avail, 0) & USEDNOIRQ) == 0);
@@ -420,15 +405,20 @@
return rc;
}
+
+static int local_ackpipes[8][2]; /* worker completion */
+
static void
viowakeup(VIOQueue *q)
{- char c = 1;
- int idx;
-
- idx = q->d->devidx;
- if(idx >= 0 && idx < ndevpipes && devpipes[idx][1] >= 0)
- write(devpipes[idx][1], &c, 1);
+ char c = 1;
+ int idx = q->d->devidx;
+
+ if(idx >= 0 && idx < 8 && vioshared->devpipes[idx][1] > 0){+ write(vioshared->devpipes[idx][1], &c, 1);
+
+ //read(local_ackpipes[idx][0], &c, 1);
+ }
}
static void
@@ -535,17 +525,14 @@
case 0x10012: return v->devstat;
case 0x10013: /* ISR read - atomic read and clear */
- lock(&v->isrlk);
- rc = v->isrstat;
- v->isrstat = 0;
- /* CRITICAL FIX: Call pciirq() while holding lock to prevent race
- * with vioirq_() that could set isrstat and call pciirq() between
- * our unlock and our pciirq(0) call. */
- pciirq(v->pci, 0);
- unlock(&v->isrlk);
- if (debug)
- fprint(2, "VIRTIO: ISR read, was %#x\n", rc);
- return rc;
+ lock(&v->isrlk);
+ rc = v->isrstat;
+ v->isrstat = 0;
+ unlock(&v->isrlk);
+
+ pciirq(v->pci, 0);
+ dprint("VIRTIO: ISR read, was %#x\n", rc);+ return rc;
}
if(port >= 20 && v->io != nil)
return v->io(isin, port - 20, val, sz, v);
@@ -560,9 +547,9 @@
mkviodev_alloc(int nqu)
{VIODev *d;
- int i;
+ int i, idx;
- if(ndevpipes >= MAXVIODEV)
+ if(vioshared->ndevpipes >= MAXVIODEV)
sysfatal("mkviodev: too many virtio devices");d = vioalloc(sizeof(VIODev));
@@ -576,10 +563,11 @@
d->qu[i].qidx = i;
}
- d->devidx = ndevpipes;
- if(pipe(devpipes[ndevpipes]) < 0)
+ idx = vioshared->ndevpipes;
+ d->devidx = idx;
+ if(pipe(vioshared->devpipes[idx]) < 0)
sysfatal("mkviodev pipe: %r");- ndevpipes++;
+ vioshared->ndevpipes++;
return d;
}
@@ -602,28 +590,19 @@
static VIOBuf *
viogetbuf_smp(VIOQueue *q, int wait)
{- VIOBuf *b;
- char c;
- int idx;
-
- idx = q->d->devidx;
- for(;;) {- b = viogetbuf(q, 0);
- if(b != nil)
- return b;
- if(!wait)
- return nil;
-
- /* Debug: show we're about to block */
- if(q->avail != nil)
- if (debug)
- fprint(2, "VIOBLK: blocking, availidx=%d guest_idx=%d livebuf=%d\n",
- q->availidx, GET16(q->avail, 2), q->livebuf);
-
- if(idx >= 0 && idx < ndevpipes && devpipes[idx][0] >= 0)
- read(devpipes[idx][0], &c, 1);
-
- }
+ VIOBuf *b;
+ char c;
+ int idx = q->d->devidx;
+
+ for(;;) {+ b = viogetbuf(q, 0);
+ if(b != nil)
+ return b;
+ if(!wait)
+ return nil;
+ if(idx >= 0 && idx < 8 && vioshared->devpipes[idx][0] > 0)
+ read(vioshared->devpipes[idx][0], &c, 1);
+ }
}
VIOQueue *
@@ -945,8 +924,10 @@
mkviodev_register(d, 0x1000, 0x020000, 1);
- proccreate(vionetrproc, d, 8192);
- proccreate(vionetwproc, d, 8192);
+ vioshared->netdevs[vioshared->nnetdevs++] = d;
+
+// proccreate(vionetrproc, d, 8192);
+// proccreate(vionetwproc, d, 8192);
return 0;
}
@@ -1002,9 +983,9 @@
int rc, m;
ulong n;
vlong offset;
- static Lock reqlock;
- static uvlong reqcount = 0;
+ static Lock reqlock;
static uvlong writecount = 0;
+ static uvlong reqcount = 0;
static uvlong readcount = 0;
uvlong myreq, mywrite;
@@ -1012,13 +993,17 @@
v = vp;
q = &v->qu[0];
- fprint(2, "VIOBLK: started fd=%d size=%llud sectors (%llud bytes)\n",
+ dprint( "VIOBLK: started fd=%d size=%llud sectors (%llud bytes)\n",
v->blk.fd, v->blk.size, v->blk.size * 512ULL);
if(v->blk.size == 0)
fprint(2, "VIOBLK: WARNING: disk size is 0!\n");
+ int idx = v->devidx;
+ char c = 'w';
+
for(;;){- b = viogetbuf_smp(q, 1);
+
+ b = viogetbuf_smp(q, 1);
if(b == nil){ vmerror("vioblkproc: viogetbuf: %r"); threadexits("vioblkproc: viogetbuf: %r");@@ -1034,30 +1019,25 @@
VIOBuf *tb;
int i = 0;
ulong total_rd = 0, total_wr = 0;
- if (debug)
- fprint(2, "VIOBLK[%llud]: descriptor chain:\n", myreq);
+ dprint("VIOBLK[%llud]: descriptor chain:\n", myreq); for(tb = b; tb != nil; tb = tb->next, i++){- if (debug)
- fprint(2, " desc[%d]: addr=%#llux len=%ud flags=%#ux",
+ dprint(" desc[%d]: addr=%#llux len=%ud flags=%#ux", i, tb->addr, tb->len, tb->flags);
- if(tb->flags & BUFCHAIN) fprint(2, " NEXT");
+ if(tb->flags & BUFCHAIN) dprint(" NEXT"); if(tb->flags & BUFWR) {- fprint(2, " WRITE");
+ dprint(" WRITE");total_wr += tb->len;
} else {total_rd += tb->len;
}
- fprint(2, "\n");
+ dprint("\n");}
- if (debug)
- fprint(2, " totals: readable=%lud writable=%lud\n", total_rd, total_wr);
+ dprint(" totals: readable=%lud writable=%lud\n", total_rd, total_wr);}
ulong hdr_read = vioqread(b, cmd, sizeof(cmd));
if(hdr_read < sizeof(cmd)){- if (debug)
- fprint(2, "VIOBLK[%llud]: ERROR: header read failed: got %lud, need 16\n",
- myreq, hdr_read);
+ dprint("VIOBLK[%llud]: ERROR: header read failed: got %lud, need 16\n", myreq, hdr_read);goto nope;
}
@@ -1066,8 +1046,7 @@
addr = GET64(cmd, 8);
if(debug || myreq <= 5)
- fprint(2, "VIOBLK[%llud]: type=%ud reserved=%#ux sector=%llud rptr_after_hdr=%ud\n",
- myreq, type, reserved, addr, b->rptr);
+ dprint("VIOBLK[%llud]: type=%ud reserved=%#ux sector=%llud rptr_after_hdr=%ud\n", myreq, type, reserved, addr, b->rptr); switch(type){case 0: /* READ */
@@ -1076,21 +1055,19 @@
unlock(&reqlock);
n = vioqrem(b, 1);
- if(debug) fprint(2, "VIOBLK[%llud]: READ vioqrem(wr=1)=%lud\n", myreq, n);
+ dprint("VIOBLK[%llud]: READ vioqrem(wr=1)=%lud\n", myreq, n); if(n == 0){- if (debug)
- fprint(2, "VIOBLK[%llud]: ERROR: READ no writable space\n", myreq);
+ dprint("VIOBLK[%llud]: ERROR: READ no writable space\n", myreq);ack = 1;
break;
}
n -= 1;
- if(debug) fprint(2, "VIOBLK[%llud]: READ %lud bytes from sector %llud\n", myreq, n, addr);
+ dprint("VIOBLK[%llud]: READ %lud bytes from sector %llud\n", myreq, n, addr); if(addr * 512 + n > v->blk.size * 512){- if (debug)
- fprint(2, "VIOBLK[%llud]: ERROR: READ bounds failed\n", myreq);
+ dprint("VIOBLK[%llud]: ERROR: READ bounds failed\n", myreq);ack = 1;
break;
}
@@ -1101,14 +1078,12 @@
if(n < rc) rc = n;
rc = pread(v->blk.fd, buf, rc, offset);
if(rc < 0){- if (debug)
- fprint(2, "VIOBLK[%llud]: ERROR: pread failed: %r\n", myreq);
+ dprint("VIOBLK[%llud]: ERROR: pread failed: %r\n", myreq);ack = 1;
break;
}
if(rc == 0){- if (debug)
- fprint(2, "VIOBLK[%llud]: ERROR: pread EOF\n", myreq);
+ dprint("VIOBLK[%llud]: ERROR: pread EOF\n", myreq);ack = 1;
break;
}
@@ -1124,18 +1099,15 @@
n = vioqrem(b, 0);
if(debug || myreq <= 5)
- fprint(2, "VIOBLK[%llud]: WRITE #%llud vioqrem(wr=0)=%lud sector=%llud\n",
- myreq, mywrite, n, addr);
+ dprint("VIOBLK[%llud]: WRITE #%llud vioqrem(wr=0)=%lud sector=%llud\n", myreq, mywrite, n, addr); if(n == 0){- if (debug)
- fprint(2, "VIOBLK[%llud]: WARNING: WRITE with no data\n", myreq);
+ dprint("VIOBLK[%llud]: WARNING: WRITE with no data\n", myreq);break;
}
if(addr * 512 + n > v->blk.size * 512){- if (debug)
- fprint(2, "VIOBLK[%llud]: ERROR: WRITE bounds failed\n", myreq);
+ dprint("VIOBLK[%llud]: ERROR: WRITE bounds failed\n", myreq);ack = 1;
break;
}
@@ -1149,14 +1121,12 @@
rc = pwrite(v->blk.fd, buf, m, offset);
if(rc < 0){- if (debug)
- fprint(2, "VIOBLK[%llud]: ERROR: pwrite failed: %r\n", myreq);
+ dprint("VIOBLK[%llud]: ERROR: pwrite failed: %r\n", myreq);ack = 1;
break;
}
if(rc < m){- if (debug)
- fprint(2, "VIOBLK[%llud]: ERROR: short write %d < %d\n", myreq, rc, m);
+ dprint("VIOBLK[%llud]: ERROR: short write %d < %d\n", myreq, rc, m);ack = 1;
break;
}
@@ -1165,7 +1135,7 @@
break;
case 4: /* FLUSH */
- if(debug) fprint(2, "VIOBLK[%llud]: FLUSH\n", myreq);
+ dprint("VIOBLK[%llud]: FLUSH\n", myreq);ack = 0;
break;
@@ -1187,19 +1157,53 @@
vioqwrite(b, &ack, 1);
if(debug || myreq <= 5)
- fprint(2, "VIOBLK[%llud]: completing, ack=%d\n", myreq, ack);
+ dprint("VIOBLK[%llud]: completing, ack=%d\n", myreq, ack);if(myreq % 1000 == 0)
- fprint(2, "REQ %llud\n", myreq);
+ dprint("REQ %llud\n", myreq);vioputbuf(b);
if(myreq % 1000 == 0)
- if (debug)
- fprint(2, "VIOBLK: %llud requests (%llud reads, %llud writes)\n",
- myreq, readcount, writecount);
+ dprint("VIOBLK: %llud requests (%llud reads, %llud writes)\n", myreq, readcount, writecount);+
+ extern int wakepipe[MAXVCPU][2];
+ extern int hltpipe[MAXVCPU][2];
+
+ // vioirq(v, 1); /* set ISR here after all work done */
+ // write(local_ackpipes[idx][1], &c, 1); /* signal done */
+// for(int i = 0; i < nvcpu; i++)
+// write(wakepipe[i][1], &c, 1);
+
}
}
+
+
+
+void
+virtio_start_workers(void)
+{+ int i;
+
+ /* Create LOCAL pipes for this process */
+ for(i = 0; i < vioshared->nblkdevs; i++){+
+ if(pipe(local_devpipes[i]) < 0)
+ sysfatal("virtio pipe: %r");+ if(pipe(local_ackpipes[i]) < 0)
+ sysfatal("virtio pipe: %r");+ proccreate(vioblkproc, vioshared->blkdevs[i], 131072);
+ }
+
+ for(i = 0; i < vioshared->nnetdevs; i++){+ if(pipe(local_devpipes[vioshared->nblkdevs + i]) < 0)
+ sysfatal("virtio pipe: %r");+ proccreate(vionetrproc, vioshared->netdevs[i], 8192);
+ proccreate(vionetwproc, vioshared->netdevs[i], 8192);
+ }
+}
+
+
int
mkvioblk(char *fn)
{@@ -1230,7 +1234,7 @@
size = filesize >> 9;
- fprint(2, "VIOBLK: opened '%s' fd=%d filesize=%lld size=%llud sectors\n",
+ dprint("VIOBLK: opened '%s' fd=%d filesize=%lld size=%llud sectors\n",fn, fd, filesize, size);
if(size == 0){@@ -1254,8 +1258,10 @@
mkviodev_register(d, 0x1001, 0x018000, 2);
- for(int i = 0; i < 1; i++)
- proccreate(vioblkproc, d, 131072);
+ vioshared->blkdevs[vioshared->nblkdevs++] = d;
+
+// for(int i = 0; i < 1; i++)
+// proccreate(vioblkproc, d, 131072);
return 0;
}
--- a/vmx.c
+++ b/vmx.c
@@ -6,11 +6,76 @@
#include "dat.h"
#include "fns.h"
+char *vmx_segprefix;
+
static char *uartcfg[2];
/* Saved UART config from -c/-C options */
extern MouseShared *mouseshared;
+void *
+mkseg(char *name, uintptr va, ulong size)
+{+ char path[64];
+ char buf[64];
+ int fd;
+ void *p;
+
+ /* Remove old segment if exists */
+ snprint(path, sizeof path, "#g/%s.%s/ctl", vmx_segprefix, name);
+ remove(path);
+ snprint(path, sizeof path, "#g/%s.%s", vmx_segprefix, name);
+ remove(path);
+
+ /* Create directory */
+ fd = create(path, OREAD|ORCLOSE, DMDIR | 0777);
+ //if(fd >= 0) close(fd);
+
+ /* Configure segment */
+ snprint(path, sizeof path, "#g/%s.%s/ctl", vmx_segprefix, name);
+ fd = open(path, OWRITE);
+ if(fd < 0)
+ sysfatal("mkseg %s: open ctl: %r", name);+
+ snprint(buf, sizeof buf, "va %#p %#lux sticky", va, size);
+ if(write(fd, buf, strlen(buf)) < 0)
+ sysfatal("mkseg %s: write ctl: %r", name);+ close(fd);
+
+ /* Attach */
+ snprint(path, sizeof path, "%s.%s", vmx_segprefix, name);
+ p = segattach(0, path, nil, size);
+ if(p == (void*)-1)
+ sysfatal("mkseg %s: segattach: %r", name);+
+ return p;
+}
+
+void
+rmseg(char *name)
+{+ char path[64];
+
+ snprint(path, sizeof path, "#g/%s.%s/ctl", vmx_segprefix, name);
+ remove(path);
+ snprint(path, sizeof path, "#g/%s.%s", vmx_segprefix, name);
+ remove(path);
+}
+
+void
+dprint(char *fmt, ...)
+{+ va_list arg;
+
+ if(!debug)
+ return;
+
+ fprint(2, "CPU%d: ", curcpuid);
+ va_start(arg, fmt);
+ vfprint(2, fmt, arg);
+ va_end(arg);
+}
+
void
mousesharedinit(void)
{@@ -113,13 +178,15 @@
u32int preempt_shift;
int timerid;
+char name[128];
+
void
vmxsetup(void)
{static char buf[128];
- static char name[128];
- int rc;
+ int rc;
+ close(ctlfd); // When forking
ctlfd = open("#X/clone", ORDWR|ORCLOSE); if(ctlfd < 0) sysfatal("open: %r");rc = read(ctlfd, name, sizeof(name) - 1);
@@ -126,8 +193,8 @@
if(rc < 0) sysfatal("read: %r");name[rc] = 0;
if(segname == nil){- segname = smprint("vm.%s", name);- segrclose = ORCLOSE;
+ segname = smprint("vm.%d.%s", getpid(), name);+ segrclose = ORCLOSE;
}
snprint(buf, sizeof(buf), "#X/%s/regs", name);
@@ -147,8 +214,11 @@
preempt_shift = (u32int)rget("preemptshift");/* DEBUG - always print these */
- fprint(2, "VMX: preempt_shift=%d tsc_freq=%llud\n", preempt_shift, _tos->cyclefreq);
+ dprint("VMX: preempt_shift=%d tsc_freq=%llud\n", preempt_shift, _tos->cyclefreq);+ snprint(buf, sizeof(buf), "#X/%s/ctl", name);
+ open(buf, OREAD|ORCLOSE); // remove ctl when process exits
+
}
enum { RCENT = 256 };@@ -636,11 +706,15 @@
timers_advance();
launch();
+ /* Drain garbage from before VM started */
+ kbdshared->r = kbdshared->w;
+
/* Set channel pointers once */
a[AWAIT].c = waitch;
a[ANOTIF].c = notifch;
static int count = 0;
+
for(;;){@@ -837,6 +911,10 @@
int newwin = 0;
int i;
+
+
+ vmx_segprefix = smprint("vmx.%d", getpid());+
quotefmtinstall();
mainid = threadid();
cpuidinit();
@@ -919,6 +997,8 @@
mkregion(fbaddr, fbaddr+fbsz, REGALLOC|REGRWX);
}
+
+
vmxsetup();
vmtime_init();
@@ -1000,6 +1080,11 @@
if(srvname != nil) init9p(srvname);
if(kconfig != nil) kconfig();
+ virtio_start_workers(); /* Start workers for CPU0 */
+
+ vmx_cleanup_init();
+
runloop();
+
exits(nil);
}
--
⑨