diff options
author | aiju <devnull@localhost> | 2017-06-21 22:18:26 +0000 |
---|---|---|
committer | aiju <devnull@localhost> | 2017-06-21 22:18:26 +0000 |
commit | 5c0bff4ba204cfad7aedb8c1c20f1c29265dcb01 (patch) | |
tree | 055fa5e6319b94d0f2992480a0e6ed0271179fb6 /sys/src/cmd/vmx/x86.c | |
parent | 37b9ab5a043e45a68979632c177e11af7a439027 (diff) |
vmx(1): add support for (so far) crude 9p debugging fs; add gdb stub; clean up linux gdt code
Diffstat (limited to 'sys/src/cmd/vmx/x86.c')
-rw-r--r-- | sys/src/cmd/vmx/x86.c | 124 |
1 files changed, 124 insertions, 0 deletions
diff --git a/sys/src/cmd/vmx/x86.c b/sys/src/cmd/vmx/x86.c new file mode 100644 index 000000000..f7d60617b --- /dev/null +++ b/sys/src/cmd/vmx/x86.c @@ -0,0 +1,124 @@ +#include <u.h> +#include <libc.h> +#include <thread.h> +#include "dat.h" +#include "fns.h" +#include "x86.h" + +typedef struct VMemReq VMemReq; +struct VMemReq { + QLock; + uintptr va, len; + void *buf; + uintptr rc; +}; + +static uintptr +translateflat(uintptr va, uintptr *pa, uintptr) +{ + *pa = va; + if(va == 0) + return -1; + return 0; +} + +static uintptr +translate32(uintptr va, uintptr *pa, uintptr cr4) +{ + void *pd, *pt; + u32int pde, pte; + + if(sizeof(uintptr) != 4 && va >> 32 != 0) return -1; + pd = gptr(rget("cr3") & ~0xfff, 4096); + if(pd == nil) return 0; + pde = GET32(pd, (va >> 22) * 4); + if((pde & 1) == 0) return 0; + if((pde & 0x80) != 0 && (cr4 & Cr4Pse) != 0){ + *pa = pde & (1<<22) - 1 | (uintptr)(pde & 0xfe000) << 19; + return (1<<22) - (va & (1<<22)-1); + } + pt = gptr(pde & ~0xfff, 4096); + if(pt == nil) return 0; + pte = GET32(pt, va >> 10 & 0xffc); + if((pte & 1) == 0) return 0; + *pa = pte & ~0xfff | va & 0xfff; + return 0x1000 - (va & 0xfff); +} + +static uintptr +translatepae(uintptr, uintptr *, uintptr) +{ + vmerror("PAE translation not implemented"); + return 0; +} + +static uintptr +translate64(uintptr, uintptr *, uintptr) +{ + vmerror("long mode translation not implemented"); + return 0; +} + +static uintptr (* +translator(uintptr *cr4p))(uintptr, uintptr *, uintptr) +{ + uintptr cr0, cr4, efer; + + cr0 = rget("cr0real"); + if((cr0 & Cr0Pg) == 0) + return translateflat; + efer = rget("efer"); + if((efer & EferLme) != 0) + return translate64; + cr4 = rget("cr4real"); + *cr4p = cr4; + if((cr4 & Cr4Pae) != 0) + return translatepae; + return translate32; +} + +static void +vmemread0(void *aux) +{ + VMemReq *req; + uintptr va, pa, n, ok, pok, cr4; + void *v; + uintptr (*trans)(uintptr, uintptr *, uintptr); + uchar *p; + + req = aux; + va = req->va; + n = req->len; + p = req->buf; + trans = translator(&cr4); + while(n > 0){ + ok = trans(va, &pa, cr4); + if(ok == 0) break; + if(ok > n) ok = n; + v = gptr(pa, 1); + if(v == nil) break; + pok = gavail(v); + if(ok > pok) ok = pok; + memmove(p, v, ok); + n -= ok; + p += ok; + va += ok; + } + req->rc = req->len - n; + qunlock(req); +} + +uintptr +vmemread(void *buf, uintptr len, uintptr va) +{ + VMemReq req; + + memset(&req, 0, sizeof(VMemReq)); + req.buf = buf; + req.len = len; + req.va = va; + qlock(&req); + sendnotif(vmemread0, &req); + qlock(&req); + return req.rc; +} |