diff options
author | aiju <devnull@localhost> | 2017-06-20 15:10:08 +0000 |
---|---|---|
committer | aiju <devnull@localhost> | 2017-06-20 15:10:08 +0000 |
commit | becb89bae53e01785bfd843478737eeb77a9419f (patch) | |
tree | 11450e95827d5356c4e8c845124cca0d80ca326c /sys/src | |
parent | 9fb2001658fb59fa0c7437f856491ef5f4214ebe (diff) |
pc, pc64: adapt devvmx to work on pc64
Diffstat (limited to 'sys/src')
-rw-r--r-- | sys/src/9/pc/dat.h | 12 | ||||
-rw-r--r-- | sys/src/9/pc/devvmx.c | 233 | ||||
-rw-r--r-- | sys/src/9/pc/fns.h | 1 | ||||
-rw-r--r-- | sys/src/9/pc/l.s | 13 | ||||
-rw-r--r-- | sys/src/9/pc/main.c | 2 | ||||
-rw-r--r-- | sys/src/9/pc64/fns.h | 4 | ||||
-rw-r--r-- | sys/src/9/pc64/l.s | 130 | ||||
-rw-r--r-- | sys/src/9/pc64/main.c | 35 | ||||
-rw-r--r-- | sys/src/9/pc64/mem.h | 1 | ||||
-rw-r--r-- | sys/src/9/pc64/pc64 | 3 |
10 files changed, 365 insertions, 69 deletions
diff --git a/sys/src/9/pc/dat.h b/sys/src/9/pc/dat.h index 452b613da..07f45bf5f 100644 --- a/sys/src/9/pc/dat.h +++ b/sys/src/9/pc/dat.h @@ -332,6 +332,18 @@ enum { Rdrnd = 1<<30, /* RDRAND support bit */ }; +/* model-specific registers, for compatibility with pc64 code */ +enum { + Efer = 0xc0000080, /* Extended Feature Enable */ + Star = 0xc0000081, /* Legacy Target IP and [CS]S */ + Lstar = 0xc0000082, /* Long Mode Target IP */ + Cstar = 0xc0000083, /* Compatibility Target IP */ + Sfmask = 0xc0000084, /* SYSCALL Flags Mask */ + FSbase = 0xc0000100, /* 64-bit FS Base Address */ + GSbase = 0xc0000101, /* 64-bit GS Base Address */ + KernelGSbase = 0xc0000102, /* SWAPGS instruction */ +}; + /* * a parsed plan9.ini line */ diff --git a/sys/src/9/pc/devvmx.c b/sys/src/9/pc/devvmx.c index 77074a5a8..8ab687ee5 100644 --- a/sys/src/9/pc/devvmx.c +++ b/sys/src/9/pc/devvmx.c @@ -55,6 +55,7 @@ enum { PROCB_EXITMOVDR = 1<<23, PROCB_EXITIO = 1<<24, PROCB_MONTRAP = 1<<27, + PROCB_MSRBITMAP = 1<<28, PROCB_EXITMONITOR = 1<<29, PROCB_EXITPAUSE = 1<<30, PROCB_USECTLS2 = 1<<31, @@ -69,6 +70,7 @@ enum { PFAULT_MASK = 0x4006, PFAULT_MATCH = 0x4008, CR3_TARGCNT = 0x400a, + MSR_BITMAP = 0x2004, VMEXIT_CTLS = 0x400c, VMEXIT_ST_DEBUG = 1<<2, @@ -81,6 +83,9 @@ enum { VMEXIT_MSRSTCNT = 0x400e, VMEXIT_MSRLDCNT = 0x4010, + VMEXIT_MSRSTADDR = 0x2006, + VMEXIT_MSRLDADDR = 0x2008, + VMENTRY_MSRLDADDR = 0x200A, VMENTRY_CTLS = 0x4012, VMENTRY_LD_DEBUG = 1<<2, @@ -204,10 +209,14 @@ enum { CR4SMXE = 1<<14, CR4PKE = 1<<22, - CR0KERNEL = CR0RSVD | (uintptr)0xFFFFFFFF00000000ULL, + CR0KERNEL = CR0RSVD | 0x30 | (uintptr)0xFFFFFFFF00000000ULL, CR4KERNEL = CR4RSVD | CR4VMXE | CR4SMXE | CR4MCE | CR4PKE | (uintptr)0xFFFFFFFF00000000ULL }; +enum { + MAXMSR = 512, +}; + typedef struct Vmx Vmx; typedef struct VmCmd VmCmd; typedef struct VmMem VmMem; @@ -237,9 +246,11 @@ struct Vmx { } state; char errstr[ERRMAX]; Ureg ureg; + uintptr cr2; uintptr dr[8]; /* DR7 is also kept in VMCS */ FPsave *fp; u8int launched; + u8int on; u8int vpid; enum { FLUSHVPID = 1, @@ -264,6 +275,10 @@ struct Vmx { } got; VmMem *stepmap; VmIntr exc, irq, irqack; + + u64int *msrhost, *msrguest; + u32int *msrbits; + int nmsr; }; struct VmCmd { @@ -330,14 +345,13 @@ vmcswrite(u32int addr, u64int val) } static uvlong -parseval(char *s, int sz) +parseval(char *s) { uvlong v; char *p; - - if(sz == 0) sz = sizeof(uintptr); + v = strtoull(s, &p, 0); - if(p == s || *p != 0 || v >> sz * 8 != 0) error("invalid value"); + if(p == s || *p != 0) error("invalid value"); return v; } @@ -363,13 +377,30 @@ cr4fakeread(char *p, char *e) return seprint(p, e, "%#.*ullx", sizeof(uintptr) * 2, guest & ~mask | shadow & mask); } +static void +updatelma(void) +{ + uvlong cr0, efer, nefer, ectrl; + + if(sizeof(uintptr) != 8) return; + cr0 = vmcsread(GUEST_CR0); + efer = vmcsread(GUEST_IA32_EFER); + nefer = efer & ~0x400 | efer << 2 & cr0 >> 21 & 0x400; + if(efer == nefer) return; + vmcswrite(GUEST_IA32_EFER, nefer); + ectrl = vmcsread(VMENTRY_CTLS); + ectrl = ectrl & ~0x200 | nefer >> 1 & 0x200; + vmcswrite(VMENTRY_CTLS, ectrl); +} + static int cr0realwrite(char *s) { uvlong v; - v = parseval(s, 8); + v = parseval(s); vmcswrite(GUEST_CR0, vmcsread(GUEST_CR0) & CR0KERNEL | v & ~CR0KERNEL); + updatelma(); return 0; } @@ -378,8 +409,19 @@ cr0maskwrite(char *s) { uvlong v; - v = parseval(s, 8); - vmcswrite(GUEST_CR0MASK, vmcsread(GUEST_CR0MASK) | CR0KERNEL); + v = parseval(s); + vmcswrite(GUEST_CR0MASK, v | CR0KERNEL); + return 0; +} + +static int +eferwrite(char *s) +{ + uvlong v; + + v = parseval(s); + vmcswrite(GUEST_IA32_EFER, v); + updatelma(); return 0; } @@ -388,7 +430,7 @@ cr4realwrite(char *s) { uvlong v; - v = parseval(s, 8); + v = parseval(s); vmcswrite(GUEST_CR4, vmcsread(GUEST_CR4) & CR4KERNEL | v & ~CR4KERNEL); return 0; } @@ -398,8 +440,8 @@ cr4maskwrite(char *s) { uvlong v; - v = parseval(s, 8); - vmcswrite(GUEST_CR4MASK, vmcsread(GUEST_CR4MASK) | CR4KERNEL); + v = parseval(s); + vmcswrite(GUEST_CR4MASK, v | CR4KERNEL); return 0; } @@ -408,7 +450,7 @@ dr7write(char *s) { uvlong v; - v = (u32int) parseval(s, 8); + v = (u32int) parseval(s); vmcswrite(GUEST_DR7, vmx.dr[7] = (u32int) v); return 0; } @@ -424,7 +466,7 @@ dr6write(char *s) { uvlong v; - v = parseval(s, 8); + v = parseval(s); vmx.dr[6] = (u32int) v; return 0; } @@ -450,6 +492,16 @@ static GuestReg guestregs[] = { {UREG(bp), 0, "bp"}, {UREG(si), 0, "si"}, {UREG(di), 0, "di"}, +#ifdef RMACH + {UREG(r8), 0, "r8"}, + {UREG(r9), 0, "r9"}, + {UREG(r10), 0, "r10"}, + {UREG(r11), 0, "r11"}, + {UREG(r12), 0, "r12"}, + {UREG(r13), 0, "r13"}, + {UREG(r14), 0, "r14"}, + {UREG(r15), 0, "r15"}, +#endif {GUEST_GDTRBASE, 0, "gdtrbase"}, {GUEST_GDTRLIMIT, 4, "gdtrlimit"}, {GUEST_IDTRBASE, 0, "idtrbase"}, @@ -489,13 +541,13 @@ static GuestReg guestregs[] = { {GUEST_CR0, 0, "cr0real", nil, cr0realwrite}, {GUEST_CR0SHADOW, 0, "cr0fake", cr0fakeread}, {GUEST_CR0MASK, 0, "cr0mask", nil, cr0maskwrite}, - {UREG(trap), 0, "cr2"}, + {VMXVAR(cr2), 0, "cr2"}, {GUEST_CR3, 0, "cr3"}, {GUEST_CR4, 0, "cr4real", nil, cr4realwrite}, {GUEST_CR4SHADOW, 0, "cr4fake", cr4fakeread}, {GUEST_CR4MASK, 0, "cr4mask", nil, cr4maskwrite}, {GUEST_IA32_PAT, 8, "pat"}, - {GUEST_IA32_EFER, 8, "efer"}, + {GUEST_IA32_EFER, 8, "efer", nil, eferwrite}, {VMXVAR(dr[0]), 0, "dr0"}, {VMXVAR(dr[1]), 0, "dr1"}, {VMXVAR(dr[2]), 0, "dr2"}, @@ -529,6 +581,7 @@ eptwalk(uvlong addr) int i; tab = vmx.pml4; + if(tab == nil) error(Egreg); for(i = 3; i >= 1; i--){ tab += addr >> 12 + 9 * i & 0x1ff; v = *tab; @@ -550,6 +603,7 @@ eptfree(uvlong *tab, int level) int i; uvlong v, *t; + if(tab == nil) error(Egreg); if(level < 3){ for(i = 0; i < 512; i++){ v = tab[i]; @@ -611,7 +665,7 @@ static int cmdclearmeminfo(VmCmd *, va_list) { VmMem *mp, *mn; - + eptfree(vmx.pml4, 0); for(mp = vmx.mem.next; mp != &vmx.mem; mp = mn){ mn = mp->next; @@ -633,7 +687,9 @@ cmdsetmeminfo(VmCmd *, va_list va) char *f[10]; VmMem *mp; int rc; - + + if(vmx.pml4 == nil) + error(Egreg); p0 = va_arg(va, char *); p = p0; mp = nil; @@ -725,8 +781,46 @@ vmxreset(void) static void vmxshutdown(void) { - if(vmx.state != NOVMX && vmx.state != VMXINACTIVE) + if(vmx.on){ vmxoff(); + vmx.on = 0; + } +} + +static void +vmxaddmsr(u32int msr, u64int gval) +{ + int i; + + if(vmx.nmsr >= MAXMSR) + error("too many MSRs"); + i = 2 * vmx.nmsr++; + vmx.msrhost[i] = msr; + rdmsr(msr, (vlong *) &vmx.msrhost[i+1]); + vmx.msrguest[i] = msr; + vmx.msrguest[i+1] = gval; + vmcswrite(VMENTRY_MSRLDCNT, vmx.nmsr); + vmcswrite(VMEXIT_MSRSTCNT, vmx.nmsr); + vmcswrite(VMEXIT_MSRLDCNT, vmx.nmsr); +} + +static void +vmxtrapmsr(u32int msr, enum { TRAPRD = 1, TRAPWR = 2 } state) +{ + u32int m; + + if(msr >= 0x2000 && (u32int)(msr - 0xc0000000) >= 0x2000) + return; + msr = msr & 0x1fff | msr >> 18 & 0x2000; + m = 1<<(msr & 31); + if((state & TRAPRD) != 0) + vmx.msrbits[msr / 32] |= m; + else + vmx.msrbits[msr / 32] &= ~m; + if((state & TRAPWR) != 0) + vmx.msrbits[msr / 32 + 512] |= m; + else + vmx.msrbits[msr / 32 + 512] &= ~m; } static void @@ -737,7 +831,7 @@ vmcsinit(void) memset(&vmx.ureg, 0, sizeof(vmx.ureg)); vmx.launched = 0; - vmx.onentry = 0; + vmx.onentry = 0; if(rdmsr(VMX_BASIC_MSR, &msr) < 0) error("rdmsr(VMX_BASIC_MSR) failed"); if((msr & 1ULL<<55) != 0){ @@ -757,7 +851,7 @@ vmcsinit(void) if(rdmsr(VMX_PROCB_CTLS_MSR, &msr) < 0) error("rdmsr(VMX_PROCB_CTLS_MSR failed"); x = (u32int)procb_ctls | 1<<1 | 7<<4 | 1<<8 | 1<<13 | 1<<14 | 1<<26; /* currently reserved default1 bits */ x |= PROCB_EXITHLT | PROCB_EXITMWAIT; - x |= PROCB_EXITMOVDR | PROCB_EXITIO | PROCB_EXITMONITOR; + x |= PROCB_EXITMOVDR | PROCB_EXITIO | PROCB_EXITMONITOR | PROCB_MSRBITMAP; x |= PROCB_USECTLS2; x &= msr >> 32; vmcswrite(PROCB_CTLS, x); @@ -770,21 +864,17 @@ vmcsinit(void) if(rdmsr(VMX_VMEXIT_CTLS_MSR, &msr) < 0) error("rdmsr(VMX_VMEXIT_CTLS_MSR failed"); x = (u32int)msr; if(sizeof(uintptr) == 8) x |= VMEXIT_HOST64; - x |= VMEXIT_LD_IA32_PAT | VMEXIT_LD_IA32_EFER | VMEXIT_ST_DEBUG; + x |= VMEXIT_LD_IA32_PAT | VMEXIT_LD_IA32_EFER | VMEXIT_ST_DEBUG | VMEXIT_ST_IA32_EFER; x &= msr >> 32; vmcswrite(VMEXIT_CTLS, x); if(rdmsr(VMX_VMENTRY_CTLS_MSR, &msr) < 0) error("rdmsr(VMX_VMENTRY_CTLS_MSR failed"); x = (u32int)msr; - if(sizeof(uintptr) == 8) x |= VMENTRY_GUEST64; x |= VMENTRY_LD_IA32_PAT | VMENTRY_LD_IA32_EFER | VMENTRY_LD_DEBUG; x &= msr >> 32; vmcswrite(VMENTRY_CTLS, x); vmcswrite(CR3_TARGCNT, 0); - vmcswrite(VMEXIT_MSRLDCNT, 0); - vmcswrite(VMEXIT_MSRSTCNT, 0); - vmcswrite(VMENTRY_MSRLDCNT, 0); vmcswrite(VMENTRY_INTRINFO, 0); vmcswrite(VMCS_LINK, -1); @@ -798,16 +888,16 @@ vmcsinit(void) vmcswrite(HOST_CR0, getcr0() & ~0xe); vmcswrite(HOST_CR3, getcr3()); vmcswrite(HOST_CR4, getcr4()); - rdmsr(0xc0000100, &msr); + rdmsr(FSbase, &msr); vmcswrite(HOST_FSBASE, msr); - rdmsr(0xc0000101, &msr); + rdmsr(GSbase, &msr); vmcswrite(HOST_GSBASE, msr); vmcswrite(HOST_TRBASE, (uintptr) m->tss); vmcswrite(HOST_GDTR, (uintptr) m->gdt); vmcswrite(HOST_IDTR, IDTADDR); if(rdmsr(0x277, &msr) < 0) error("rdmsr(IA32_PAT) failed"); vmcswrite(HOST_IA32_PAT, msr); - if(rdmsr(0xc0000080, &msr) < 0) error("rdmsr(IA32_EFER) failed"); + if(rdmsr(Efer, &msr) < 0) error("rdmsr(IA32_EFER) failed"); vmcswrite(HOST_IA32_EFER, msr); vmcswrite(EXC_BITMAP, 1<<18|1<<1); @@ -836,16 +926,16 @@ vmcsinit(void) vmcswrite(GUEST_CR0MASK, CR0KERNEL); vmcswrite(GUEST_CR4MASK, CR4KERNEL); - vmcswrite(GUEST_CR0, getcr0() & ~(1<<31)); + vmcswrite(GUEST_CR0, getcr0() & CR0KERNEL | 0x31); vmcswrite(GUEST_CR3, 0); - vmcswrite(GUEST_CR4, getcr4()); - vmcswrite(GUEST_CR0SHADOW, getcr0()); - vmcswrite(GUEST_CR4SHADOW, getcr4() & ~CR4VMXE); + vmcswrite(GUEST_CR4, getcr4() & CR4KERNEL); + vmcswrite(GUEST_CR0SHADOW, getcr0() & CR0KERNEL | 0x31); + vmcswrite(GUEST_CR4SHADOW, getcr4() & ~CR4VMXE & CR4KERNEL); vmcswrite(GUEST_IA32_PAT, 0x0007040600070406ULL); vmcswrite(GUEST_IA32_EFER, 0); - vmcswrite(GUEST_TRBASE, (uintptr) m->tss); + vmcswrite(GUEST_TRBASE, 0); vmcswrite(GUEST_TRLIMIT, 0xffff); vmcswrite(GUEST_TRPERM, (SEGTSS|SEGPL(0)|SEGP) >> 8 | 2); @@ -864,15 +954,53 @@ vmcsinit(void) error(Enomem); fpinit(); fpsave(vmx.fp); + + vmx.msrhost = mallocalign(MAXMSR*16, 16, 0, 0); + vmx.msrguest = mallocalign(MAXMSR*16, 16, 0, 0); + vmx.msrbits = mallocalign(4096, 4096, 0, 0); + if(vmx.msrhost == nil || vmx.msrguest == nil || vmx.msrbits == nil) + error(Enomem); + memset(vmx.msrbits, -1, 4096); + vmxtrapmsr(Efer, 0); + vmcswrite(VMENTRY_MSRLDADDR, PADDR(vmx.msrguest)); + vmcswrite(VMEXIT_MSRSTADDR, PADDR(vmx.msrguest)); + vmcswrite(VMEXIT_MSRLDADDR, PADDR(vmx.msrhost)); + vmcswrite(MSR_BITMAP, PADDR(vmx.msrbits)); + + if(sizeof(uintptr) == 8){ + vmxaddmsr(Star, 0); + vmxaddmsr(Lstar, 0); + vmxaddmsr(Cstar, 0); + vmxaddmsr(Sfmask, 0); + vmxaddmsr(KernelGSbase, 0); + vmxtrapmsr(Star, 0); + vmxtrapmsr(Lstar, 0); + vmxtrapmsr(Cstar, 0); + vmxtrapmsr(Sfmask, 0); + vmxtrapmsr(FSbase, 0); + vmxtrapmsr(GSbase, 0); + vmxtrapmsr(KernelGSbase, 0); + } } static void vmxstart(void) { static uchar *vmcs; /* also vmxon region */ + vlong msr, msr2; + uintptr cr; vlong x; - putcr4(getcr4() | 0x2000); + putcr4(getcr4() | 0x2000); /* set VMXE */ + putcr0(getcr0() | 0x20); /* set NE */ + cr = getcr0(); + if(rdmsr(VMX_CR0_FIXED0, &msr) < 0) error("rdmsr(VMX_CR0_FIXED0) failed"); + if(rdmsr(VMX_CR0_FIXED1, &msr2) < 0) error("rdmsr(VMX_CR0_FIXED1) failed"); + if((cr & ~msr & ~msr2 | ~cr & msr & msr2) != 0) error("invalid CR0 value"); + cr = getcr4(); + if(rdmsr(VMX_CR4_FIXED0, &msr) < 0) error("rdmsr(VMX_CR4_FIXED0) failed"); + if(rdmsr(VMX_CR4_FIXED1, &msr2) < 0) error("rdmsr(VMX_CR4_FIXED1) failed"); + if((cr & ~msr & ~msr2 | ~cr & msr & msr2) != 0) error("invalid CR4 value"); if(vmcs == nil){ vmcs = mallocalign(8192, 4096, 0, 0); @@ -885,6 +1013,7 @@ vmxstart(void) *(ulong*)&vmcs[4096] = x; if(vmxon(PADDR(vmcs + 4096)) < 0) error("vmxon failed"); + vmx.on = 1; if(vmclear(PADDR(vmcs)) < 0) error("vmclear failed"); if(vmptrld(PADDR(vmcs)) < 0) @@ -931,16 +1060,25 @@ static int cmdquit(VmCmd *p, va_list va) { vmx.state = VMXENDING; - cmdclearmeminfo(p, va); killcmds(p); - free(vmx.pml4); - vmx.pml4 = nil; + if(vmx.pml4 != nil){ + cmdclearmeminfo(p, va); + free(vmx.pml4); + vmx.pml4 = nil; + } vmx.got = 0; vmx.onentry = 0; vmx.stepmap = nil; + + free(vmx.msrhost); + free(vmx.msrguest); + vmx.msrhost = nil; + vmx.msrguest = nil; + vmx.nmsr = 0; - vmxoff(); + if(vmx.on) + vmxoff(); vmx.state = VMXINACTIVE; cmdrelease(p, 0); pexit(Equit, 1); @@ -973,7 +1111,7 @@ processexit(void) break; } if((vmx.onentry & STEP) != 0){ - iprint("VMX: exit reason %#x when expected step...\n", reason & 0xffff); + print("VMX: exit reason %#x when expected step...\n", reason & 0xffff); vmx.onentry &= ~STEP; vmx.got |= GOTSTEP|GOTSTEPERR; } @@ -1042,7 +1180,7 @@ setregs(char *p0, char rs, char *fs) val = strtoull(f[1], &rp, 0); sz = r->size; if(sz == 0) sz = sizeof(uintptr); - if(rp == f[1] || *rp != 0 || val >> 8 * sz != 0) error("invalid value"); + if(rp == f[1] || *rp != 0) error("invalid value"); if(r->offset >= 0) vmcswrite(r->offset, val); else{ @@ -1192,7 +1330,7 @@ cmdstep(VmCmd *cp, va_list va) if((vmx.got & GOTSTEP) != 0 || (vmx.onentry & STEP) != 0) error(Einuse); if(vmx.state != VMXREADY){ - iprint("pre-step in state %s\n", statenames[vmx.state]); + print("pre-step in state %s\n", statenames[vmx.state]); error("not ready"); } vmx.stepmap = va_arg(va, VmMem *); @@ -1202,7 +1340,7 @@ cmdstep(VmCmd *cp, va_list va) return 1; case 1: if(vmx.state != VMXREADY){ - iprint("post-step in state %s\n", statenames[vmx.state]); + print("post-step in state %s\n", statenames[vmx.state]); vmx.onentry &= ~STEP; vmx.got &= ~(GOTSTEP|GOTSTEPERR); error("not ready"); @@ -1404,6 +1542,7 @@ vmxproc(void *) { int init, rc, x; u32int procbctls, defprocbctls; + vlong v; procwired(up, 0); sched(); @@ -1462,11 +1601,17 @@ vmxproc(void *) vmx.got &= ~GOTEXIT; x = splhi(); + if(sizeof(uintptr) == 8){ + rdmsr(FSbase, &v); + vmwrite(HOST_FSBASE, v); + } if((vmx.dr[7] & ~0xd400) != 0) putdr01236(vmx.dr); - fpsserestore0(vmx.fp); + fpsserestore(vmx.fp); + putcr2(vmx.cr2); rc = vmlaunch(&vmx.ureg, vmx.launched); - fpssesave0(vmx.fp); + vmx.cr2 = getcr2(); + fpssesave(vmx.fp); splx(x); if(rc < 0) error("vmlaunch failed"); diff --git a/sys/src/9/pc/fns.h b/sys/src/9/pc/fns.h index cf2e20576..594d2f553 100644 --- a/sys/src/9/pc/fns.h +++ b/sys/src/9/pc/fns.h @@ -164,6 +164,7 @@ void procsave(Proc*); void procsetup(Proc*); void procfork(Proc*); void putcr0(ulong); +void putcr2(ulong); void putcr3(ulong); void putcr4(ulong); void putdr(u32int*); diff --git a/sys/src/9/pc/l.s b/sys/src/9/pc/l.s index 955c0fd93..c2c283793 100644 --- a/sys/src/9/pc/l.s +++ b/sys/src/9/pc/l.s @@ -437,6 +437,11 @@ TEXT getcr2(SB), $0 /* CR2 - page fault linear address */ MOVL CR2, AX RET +TEXT putcr2(SB), $0 + MOVL cr2+0(FP), AX + MOVL AX, CR2 + RET + TEXT getcr3(SB), $0 /* CR3 - page directory base */ MOVL CR3, AX RET @@ -910,8 +915,6 @@ TEXT vmlaunch(SB), $0 MOVL resume+4(FP), AX TESTL AX, AX MOVL ureg+0(FP), DI - MOVL 32(DI), AX - MOVL AX, CR2 MOVL 4(DI), SI MOVL 8(DI), BP MOVL 16(DI), BX @@ -920,10 +923,10 @@ TEXT vmlaunch(SB), $0 MOVL 28(DI), AX MOVL 0(DI), DI JNE _vmresume - BYTE $0x0f; BYTE $0x01; BYTE $0xc2 /* VMLAUNCH */ + BYTE $0x0f; BYTE $0x01; BYTE $0xc2 /* VMLAUNCH */ JMP _vmout _vmresume: - BYTE $0x0f; BYTE $0x01; BYTE $0xc3 /* VMRESUME */ + BYTE $0x0f; BYTE $0x01; BYTE $0xc3 /* VMRESUME */ JMP _vmout TEXT vmrestore(SB), $0 @@ -936,8 +939,6 @@ TEXT vmrestore(SB), $0 MOVL DX, 20(DI) MOVL CX, 24(DI) MOVL AX, 28(DI) - MOVL CR2, AX - MOVL AX, 32(DI) XORL AX, AX RET diff --git a/sys/src/9/pc/main.c b/sys/src/9/pc/main.c index e9ee24acc..1e9ec8bb6 100644 --- a/sys/src/9/pc/main.c +++ b/sys/src/9/pc/main.c @@ -54,7 +54,7 @@ multibootargs(void) if((multiboot[0] & (1<<6)) != 0 && (l = multiboot[11]) >= 24){ cp = seprint(cp, ep, "*e820="); m = KADDR(multiboot[12]); - while(m[0] >= 20 && m[0] <= l-4){ + while(m[0] >= 20 && m[0]+4 <= l){ uvlong base, size; m++; base = ((uvlong)m[0] | (uvlong)m[1]<<32); diff --git a/sys/src/9/pc64/fns.h b/sys/src/9/pc64/fns.h index 6db652674..f51d21fe6 100644 --- a/sys/src/9/pc64/fns.h +++ b/sys/src/9/pc64/fns.h @@ -34,6 +34,7 @@ int ecinit(int cmdport, int dataport); int ecread(uchar addr); int ecwrite(uchar addr, uchar val); #define evenaddr(x) /* x86 doesn't care */ +void fpinit(void); void (*fprestore)(FPsave*); void (*fpsave)(FPsave*); void fpsserestore(FPsave*); @@ -108,6 +109,7 @@ char* mtrr(uvlong, uvlong, char *); void mtrrclock(void); int mtrrprint(char *, long); void mtrrsync(void); +void netconsole(void); void noteret(void); uchar nvramread(int); void nvramwrite(int, uchar); @@ -157,9 +159,11 @@ void procsave(Proc*); void procsetup(Proc*); void procfork(Proc*); void putcr0(u64int); +void putcr2(u64int); void putcr3(u64int); void putcr4(u64int); void putdr(u64int*); +void putdr01236(u64int*); void putdr6(u64int); void putdr7(u64int); void* rampage(void); diff --git a/sys/src/9/pc64/l.s b/sys/src/9/pc64/l.s index c5b95dd3e..715e5f432 100644 --- a/sys/src/9/pc64/l.s +++ b/sys/src/9/pc64/l.s @@ -379,6 +379,10 @@ TEXT getcr2(SB), 1, $-4 /* #PF Linear Address */ MOVQ CR2, AX RET +TEXT putcr2(SB), 1, $-4 + MOVQ BP, CR2 + RET + TEXT getcr3(SB), 1, $-4 /* PML4 Base */ MOVQ CR3, AX RET @@ -694,9 +698,11 @@ f3: /* debug register access */ -TEXT putdr(SB), $0 +TEXT putdr(SB), 1, $-4 MOVQ 56(BP), AX MOVQ AX, DR7 + /* wet floor */ +TEXT putdr01236(SB), 1, $-4 MOVQ 0(BP), AX MOVQ AX, DR0 MOVQ 8(BP), AX @@ -709,18 +715,134 @@ TEXT putdr(SB), $0 MOVQ AX, DR6 RET -TEXT getdr6(SB), $0 +TEXT getdr6(SB), 1, $-4 MOVQ DR6, AX RET -TEXT putdr6(SB), $0 +TEXT putdr6(SB), 1, $-4 MOVQ BP, DR6 RET -TEXT putdr7(SB), $0 +TEXT putdr7(SB), 1, $-4 MOVQ BP, DR7 RET +/* VMX instructions */ +TEXT vmxon(SB), 1, $-4 + MOVQ BP, 8(SP) + /* VMXON 8(SP) */ + BYTE $0xf3; BYTE $0x0f; BYTE $0xc7; BYTE $0x74; BYTE $0x24; BYTE $0x08 + JMP _vmout + +TEXT vmxoff(SB), 1, $-4 + BYTE $0x0f; BYTE $0x01; BYTE $0xc4 + JMP _vmout + +TEXT vmclear(SB), 1, $-4 + MOVQ BP, 8(SP) + /* VMCLEAR 8(SP) */ + BYTE $0x66; BYTE $0x0f; BYTE $0xc7; BYTE $0x74; BYTE $0x24; BYTE $0x08 + JMP _vmout + +TEXT vmlaunch(SB), 1, $-4 + MOVL $0x6C14, DI + MOVQ SP, DX + BYTE $0x0f; BYTE $0x79; BYTE $0xfa /* VMWRITE DX, DI */ + JBE _vmout + MOVL $0x6C16, DI + MOVQ $vmrestore(SB), DX + BYTE $0x0f; BYTE $0x79; BYTE $0xfa /* VMWRITE DX, DI */ + JBE _vmout + + MOVQ BP, ureg+0(FP) + MOVL resume+8(FP), AX + TESTL AX, AX + MOVQ 0x00(BP), AX + MOVQ 0x08(BP), BX + MOVQ 0x10(BP), CX + MOVQ 0x18(BP), DX + MOVQ 0x20(BP), SI + MOVQ 0x28(BP), DI + MOVQ 0x38(BP), R8 + MOVQ 0x40(BP), R9 + MOVQ 0x48(BP), R10 + MOVQ 0x50(BP), R11 + MOVQ 0x58(BP), R12 + MOVQ 0x60(BP), R13 + MOVQ 0x68(BP), R14 + MOVQ 0x70(BP), R15 + MOVQ 0x30(BP), BP + JNE _vmresume + BYTE $0x0f; BYTE $0x01; BYTE $0xc2 /* VMLAUNCH */ + JMP _vmout +_vmresume: + BYTE $0x0f; BYTE $0x01; BYTE $0xc3 /* VMRESUME */ + JMP _vmout + +TEXT vmrestore(SB), 1, $-4 + PUSHQ BP + MOVQ ureg+0(FP), BP + MOVQ AX, 0x00(BP) + MOVQ BX, 0x08(BP) + MOVQ CX, 0x10(BP) + MOVQ DX, 0x18(BP) + MOVQ SI, 0x20(BP) + MOVQ DI, 0x28(BP) + POPQ 0x30(BP) + MOVQ R8, 0x38(BP) + MOVQ R9, 0x40(BP) + MOVQ R10, 0x48(BP) + MOVQ R11, 0x50(BP) + MOVQ R12, 0x58(BP) + MOVQ R13, 0x60(BP) + MOVQ R14, 0x68(BP) + MOVQ R15, 0x70(BP) + + BYTE $0x65; MOVQ 0, RMACH /* MOVQ GS:(0), RMACH */ + MOVQ 16(RMACH), RUSER + XORL AX, AX + RET + +TEXT vmptrld(SB), 1, $-4 + MOVQ BP, 8(SP) + /* VMMPTRLD 8(SP) */ + BYTE $0x0f; BYTE $0xc7; BYTE $0x74; BYTE $0x24; BYTE $0x08 + JMP _vmout + +TEXT vmwrite(SB), 1, $-4 + MOVQ val+8(FP), DX + /* VMWRITE DX, BP */ + BYTE $0x0f; BYTE $0x79; BYTE $0xea + JMP _vmout + +TEXT vmread(SB), 1, $-4 + MOVQ valp+8(FP), DI + /* VMREAD BP, (DI) */ + BYTE $0x0f; BYTE $0x78; BYTE $0x2f + JMP _vmout + +TEXT invept(SB), 1, $-4 + /* INVEPT BP, 16(SP) */ + BYTE $0x66; BYTE $0x0f; BYTE $0x38; BYTE $0x80; BYTE $0x6c; BYTE $0x24; BYTE $0x10 + JMP _vmout + +TEXT invvpid(SB), 1, $-4 + /* INVVPID BP, 16(SP) */ + BYTE $0x66; BYTE $0x0f; BYTE $0x38; BYTE $0x81; BYTE $0x6c; BYTE $0x24; BYTE $0x10 + JMP _vmout + +_vmout: + JC _vmout1 + JZ _vmout2 + XORL AX, AX + RET +_vmout1: + MOVQ $-1, AX + RET +_vmout2: + MOVQ $-2, AX + RET + /* */ TEXT touser(SB), 1, $-4 diff --git a/sys/src/9/pc64/main.c b/sys/src/9/pc64/main.c index 24bb0d073..24d99eea6 100644 --- a/sys/src/9/pc64/main.c +++ b/sys/src/9/pc64/main.c @@ -57,7 +57,7 @@ multibootargs(void) if((multiboot[0] & (1<<6)) != 0 && (l = multiboot[11]) >= 24){ cp = seprint(cp, ep, "*e820="); m = KADDR(multiboot[12]); - while(m[0] >= 20 && m[0] <= l-4){ + while(m[0] >= 20 && m[0]+4 <= l){ uvlong base, size; m++; base = ((uvlong)m[0] | (uvlong)m[1]<<32); @@ -514,6 +514,7 @@ main() }else links(); chandevreset(); + netconsole(); preallocpages(); pageinit(); swapinit(); @@ -688,6 +689,24 @@ simderror(Ureg *ureg, void*) mathnote(up->fpsave.mxcsr & 0x3f, ureg->pc); } +void +fpinit(void) +{ + /* + * A process tries to use the FPU for the + * first time and generates a 'device not available' + * exception. + * Turn the FPU on and initialise it for use. + * Set the precision and mask the exceptions + * we don't care about from the generic Mach value. + */ + _clts(); + _fninit(); + _fwait(); + _fldcw(0x0232); + _ldmxcsr(0x1900); +} + /* * math coprocessor emulation fault */ @@ -703,19 +722,7 @@ mathemu(Ureg *ureg, void*) } switch(up->fpstate){ case FPinit: - /* - * A process tries to use the FPU for the - * first time and generates a 'device not available' - * exception. - * Turn the FPU on and initialise it for use. - * Set the precision and mask the exceptions - * we don't care about from the generic Mach value. - */ - _clts(); - _fninit(); - _fwait(); - _fldcw(0x0232); - _ldmxcsr(0x1900); + fpinit(); up->fpstate = FPactive; break; case FPinactive: diff --git a/sys/src/9/pc64/mem.h b/sys/src/9/pc64/mem.h index e7d815e7d..a5d1aa368 100644 --- a/sys/src/9/pc64/mem.h +++ b/sys/src/9/pc64/mem.h @@ -99,6 +99,7 @@ #define SELECTOR(i, t, p) (((i)<<3) | (t) | (p)) #define NULLSEL SELECTOR(NULLSEG, SELGDT, 0) +#define KDSEL NULLSEL #define KESEL SELECTOR(KESEG, SELGDT, 0) #define UE32SEL SELECTOR(UE32SEG, SELGDT, 3) #define UDSEL SELECTOR(UDSEG, SELGDT, 3) diff --git a/sys/src/9/pc64/pc64 b/sys/src/9/pc64/pc64 index ba51d7ccd..5bc03031b 100644 --- a/sys/src/9/pc64/pc64 +++ b/sys/src/9/pc64/pc64 @@ -36,6 +36,9 @@ dev # i82365 cis uart usb + + segment + vmx link # devpccard |