summaryrefslogtreecommitdiff
path: root/sys/src/cmd/vmx/vmx.c
diff options
context:
space:
mode:
authoraiju <devnull@localhost>2017-06-27 09:21:30 +0000
committeraiju <devnull@localhost>2017-06-27 09:21:30 +0000
commitdffbc1e45d61bb928ea6a9d0b1206d641daf24fe (patch)
tree8a80a3a2c7e964fc89b8776a6dd8326f545a53dc /sys/src/cmd/vmx/vmx.c
parentb5a6dc7849cbd9f1fd23183ba46f0d5deb24e81d (diff)
vmx(1): I/O string instructions, incomplete support for IDE disks, misc fixes
Diffstat (limited to 'sys/src/cmd/vmx/vmx.c')
-rw-r--r--sys/src/cmd/vmx/vmx.c93
1 files changed, 86 insertions, 7 deletions
diff --git a/sys/src/cmd/vmx/vmx.c b/sys/src/cmd/vmx/vmx.c
index 481424935..faa684521 100644
--- a/sys/src/cmd/vmx/vmx.c
+++ b/sys/src/cmd/vmx/vmx.c
@@ -223,19 +223,52 @@ goti:
rcdirty[i>>6] |= 1ULL<<(i&63);
}
+uvlong
+rgetsz(char *reg, int sz)
+{
+ switch(sz){
+ case 1: return (u8int)rget(reg);
+ case 2: return (u16int)rget(reg);
+ case 4: return (u32int)rget(reg);
+ case 8: return rget(reg);
+ default:
+ vmerror("invalid size operand for rgetsz");
+ assert(0);
+ return 0;
+ }
+}
+
+void
+rsetsz(char *reg, uvlong val, int sz)
+{
+ switch(sz){
+ case 1: rset(reg, (u8int)val | rget(reg) & ~0xffULL); break;
+ case 2: rset(reg, (u16int)val | rget(reg) & ~0xffffULL); break;
+ case 4: rset(reg, (u32int)val); break;
+ case 8: rset(reg, val); break;
+ default:
+ vmerror("invalid size operand for rsetsz");
+ assert(0);
+ }
+}
+
Region *
mkregion(u64int pa, u64int end, int type)
{
- Region *r, **rp;
+ Region *r, *s, **rp;
r = emalloc(sizeof(Region));
- if(end < pa) sysfatal("end of region %p before start of region %p", (void*)end, (void*)pa);
- if((pa & BY2PG-1) != 0 || (end & BY2PG-1) != 0) sysfatal("address %p not page aligned", (void*)pa);
+ if(end < pa) sysfatal("end of region %p before start of region %#p", (void*)end, (void*)pa);
+ if((pa & BY2PG-1) != 0 || (end & BY2PG-1) != 0) sysfatal("address %#p not page aligned", (void*)pa);
r->start = pa;
r->end = end;
r->type = type;
- for(rp = &mmap; *rp != nil; rp = &(*rp)->next)
+ for(s = mmap; s != nil; s = s->next)
+ if(!(pa < s->start && end < s->end || pa >= s->start && pa >= s->end))
+ sysfatal("region %#p-%#p overlaps region %#p-%#p", pa, end, s->start, s->end);
+ for(rp = &mmap; (*rp) != nil && (*rp)->start < end; rp = &(*rp)->next)
;
+ r->next = *rp;
*rp = r;
return r;
}
@@ -487,6 +520,39 @@ siparse(char *s)
}
static void
+setiodebug(char *s)
+{
+ char *p;
+ int n, m, neg;
+ extern u32int iodebug[32];
+
+ do{
+ if(neg = *s == '!')
+ s++;
+ n = strtoul(s, &p, 0);
+ if(s == p)
+no: sysfatal("invalid iodebug argument (error at %#q)", s);
+ if(n >= sizeof(iodebug)*8)
+range: sysfatal("out of iodebug range (0-%#ux)", sizeof(iodebug)*8-1);
+ s = p + 1;
+ if(*p == '-'){
+ m = strtoul(s, &p, 0);
+ if(m >= sizeof(iodebug)*8)
+ goto range;
+ if(s == p || m < n) goto no;
+ s = p + 1;
+ }else
+ m = n;
+ for(; n <= m; n++)
+ if(neg)
+ iodebug[n>>5] &= ~(1<<(n&31));
+ else
+ iodebug[n>>5] |= 1<<(n&31);
+ }while(*p == ',');
+ if(*p != 0) goto no;
+}
+
+static void
usage(void)
{
char *blanks, *p;
@@ -499,6 +565,8 @@ usage(void)
threadexitsall("usage");
}
+void (*kconfig)(void);
+
void
threadmain(int argc, char **argv)
{
@@ -537,9 +605,16 @@ threadmain(int argc, char **argv)
break;
case 'd':
assert(edevn < nelem(edev));
- edev[edevn] = mkvioblk;
- edevt[edevn] = "virtio block";
- edevaux[edevn++] = strdup(EARGF(usage()));
+ edevaux[edevn] = strdup(EARGF(usage()));
+ if(strncmp(edevaux[edevn], "ide:", 4) == 0){
+ edevaux[edevn] += 4;
+ edev[edevn] = mkideblk;
+ edevt[edevn] = "ide block";
+ }else{
+ edev[edevn] = mkvioblk;
+ edevt[edevn] = "virtio block";
+ }
+ edevn++;
break;
case 'M':
gmemsz = siparse(EARGF(usage()));
@@ -552,6 +627,9 @@ threadmain(int argc, char **argv)
if(srvname != nil) usage();
srvname = EARGF(usage());
break;
+ case L'ι':
+ setiodebug(EARGF(usage()));
+ break;
default:
usage();
} ARGEND;
@@ -586,6 +664,7 @@ threadmain(int argc, char **argv)
pcibusmap();
if(srvname != nil) init9p(srvname);
+ if(kconfig != nil) kconfig();
runloop();
exits(nil);
}