shithub: plan9front

Download patch

ref: 67eac97a81a2adf46507030a28a036ff75331f31
parent: 014197f8d362c4644bdf07931dc695e789054838
author: cinap_lenrek <cinap_lenrek@felloff.net>
date: Wed May 12 12:00:46 EDT 2021

vmx: implement long mode page table translation

This allows vmx to translate virtual addresses to physical
when the gues runs in long mode.

--- a/sys/src/cmd/vmx/x86.c	Sun May  9 09:19:05 2021
+++ b/sys/src/cmd/vmx/x86.c	Wed May 12 12:00:46 2021
@@ -60,10 +60,44 @@
 }
 
 static uintptr
-translate64(uintptr, uintptr *, int *)
+translate64(uintptr va, uintptr *pa, int *perm)
 {
-	vmerror("long mode translation not implemented");
-	return 0;	
+	void *pml4, *pdp, *pd, *pt;
+	u64int pml4e, pdpe, pde, pte;
+
+	pml4 = gptr(rget("cr3") & 0xffffffffff000ULL, 4096);
+	if(pml4 == nil) return 0;
+	pml4e = GET64(pml4, (va & (511ULL<<39)) >> (39-3));
+	if(perm != nil) *perm = pml4e & 15;
+	if((pml4e & 1) == 0) return 0;
+
+	pdp = gptr(pml4e & 0xffffffffff000ULL, 4096);
+	if(pdp == nil) return 0;
+	pdpe = GET64(pdp, (va & (511ULL<<30)) >> (30-3));
+	if((pdpe & 1) == 0) return 0;
+	if(perm != nil) *perm &= pdpe;
+	if((pdpe & 0x80) != 0){
+		*pa = (pdpe & 0xfffffc0000000ULL) | (va & 0x3fffffffULL);
+		return 0x40000000ULL - (va & 0x3fffffffULL);
+	}
+
+	pd = gptr(pdpe & 0xffffffffff000ULL, 4096);
+	if(pd == nil) return 0;
+	pde = GET64(pd, (va & (511ULL<<21)) >> (21-3));
+	if((pde & 1) == 0) return 0;
+	if(perm != nil) *perm &= pde;
+	if((pde & 0x80) != 0){
+		*pa = (pde & 0xfffffffe00000ULL) | (va & 0x1fffffULL);
+		return 0x200000ULL - (va & 0x1fffffULL);
+	}
+
+	pt = gptr(pde & 0xffffffffff000ULL, 4096);
+	if(pt == nil) return 0;
+	pte = GET64(pt, (va & (511ULL<<12)) >> (12-3));
+	if((pte & 1) == 0) return 0;
+	if(perm != nil) *perm &= pte;
+	*pa = (pte & 0xffffffffff000ULL) | (va & 0xfffULL);
+	return 0x1000ULL - (va & 0xfffULL);
 }
 
 static uintptr (*
@@ -229,6 +263,7 @@
 	cpl = rget("cs") & 3;
 	wp = (rget("cr0real") & 1<<16) != 0;
 	for(i = 0; i < sz; ){
+		pperm = 0;
 		l = translator()(addr+i, &pav, &pperm);
 		if(l == 0){
 		pf: