shithub: riscv

Download patch

ref: 98dba9a4a311dd7b7435a5a5d66619f2a2b4b6cf
parent: 055f8370432d2c128ce8fd28b059320181d8f3ef
author: cinap_lenrek <[email protected]>
date: Sun Oct 23 00:09:27 EDT 2016

pc/archacpi: don't do acpi initialization in the kernel, provide generic acpimem routines

get rid of _INI and _REG method calls, this is not full acpi environment
anyway and all we really want todo at kernel boot time is figuring out
the interrupt routing. aux/acpi can try to enable more stuff if it needs
to later when battery status desired.

dont snoop memory space regions in amlmapio(), this is just wrong as
amlmapio() is *lazily* mapping regions as they are accessed, so the
range table would never be really complete. instead, we provide generic
access to the physical address space, excluding kernel and user memory
with acpimem file.

--- a/sys/src/9/pc/archacpi.c
+++ b/sys/src/9/pc/archacpi.c
@@ -4,20 +4,15 @@
 #include "dat.h"
 #include "fns.h"
 #include "io.h"
+#include "../port/error.h"
 
 #include "mp.h"
 
 #include <aml.h>
 
-typedef struct Memreg Memreg;
 typedef struct Rsd Rsd;
 typedef struct Tbl Tbl;
 
-struct Memreg {
-	uintptr	addr;
-	int		size;
-};
-
 struct Rsd {
 	uchar	sig[8];
 	uchar	csum;
@@ -57,9 +52,6 @@
 static int ntblmap;
 static Tbl *tblmap[64];
 
-static int nmemregs;
-static Memreg memregs[16];
-
 static ushort
 get16(uchar *p){
 	return p[1]<<8 | p[0];
@@ -83,6 +75,34 @@
 	return get32(t->len) - Tblsz;
 }
 
+static long
+memcheck(uintptr pa, long len)
+{
+	int i;
+	uintptr pe;
+	Confmem *cm;
+
+	if(len <= 0)
+		return len;
+	pe = pa + len-1;
+	if(pe < pa){
+		len = -pa;
+		pe = pa + len-1;
+	}
+	if(pa < PADDR(CPU0END))
+		return 0;
+	if(pe >= PADDR(KTZERO) && pa < PADDR(end))
+		return PADDR(KTZERO) - pa;
+	for(i=0; i<nelem(conf.mem); i++){
+		cm = &conf.mem[i];
+		if(cm->npage == 0)
+			continue;
+		if(pe >= cm->base && pa <= cm->base + cm->npage*BY2PG - 1)
+			return cm->base - pa;
+	}
+	return len;
+}
+
 static void
 maptable(uvlong xpa)
 {
@@ -111,7 +131,14 @@
 		vunmap(t, 8);
 		return;
 	}
+	if(memcheck(pa, l) != l){
+		print("maptable: ignoring %.4s at [%#p-%#p); overlaps usable memory\n",
+			(char*)t->sig, pa, pa+l);
+		vunmap(t, 8);
+		return;
+	}
 	vunmap(t, 8);
+
 	if((t = vmap(pa, l)) == nil)
 		return;
 	if(checksum(t, l)){
@@ -467,29 +494,6 @@
 }
 
 static int
-enumini(void *dot, void *)
-{
-	void *p, *r;
-	int s;
-
-	/*
-	 * If there is no _STA (or it fails), device should be
-	 * considered present and enabled.
-	 */
-	s = 0xff;
-	if((p = amlwalk(dot, "^_STA")) != nil){
-		if(amleval(p, "", &r) >= 0)
-			s = amlint(r);
-		if((s & 1) == 0) /* return if not present */
-				return 1;
-	}
-	if(s & 1) /* initialize everything present */
-		amleval(dot, "", nil);
-	/* recurse if present, enabled and "ok" */
-	return (s & 11) == 11 ? 0 : 1;
-}
-
-static int
 enumec(void *dot, void *)
 {
 	int cmdport, dataport;
@@ -509,8 +513,6 @@
 		return 1;
 	dataport = b[0+2] | b[0+3]<<8;
 	cmdport = b[8+2] | b[8+3]<<8;
-	if((x = amlwalk(dot, "^_REG")) != nil)
-		amleval(x, "ii", 3, 1, nil);
 	ecinit(cmdport, dataport);
 	return 1;
 }
@@ -518,51 +520,41 @@
 static long
 readmem(Chan*, void *v, long n, vlong o)
 {
-	int i;
-	uchar *t;
-	uintptr start, end;
-	Memreg *mr;
+	uintptr pa = (uintptr)o;
+	void *t;
 
-	start = o;
-	end = start + n;
-	for(i = 0; n > 0 && i < nmemregs; i++){
-		mr = &memregs[i];
-		if(start >= mr->addr && start < mr->addr+mr->size){
-			if(end > mr->addr+mr->size)
-				end = mr->addr+mr->size;
-			n = end - start;
-			t = vmap(mr->addr, n);
-			memmove(v, start - mr->addr + t, n);
-			vunmap(t, n);
-			return n;
-		}
+	if((n = memcheck(pa, n)) <= 0)
+		return 0;
+	if((t = vmap(pa, n)) == nil)
+		error(Enovmem);
+	if(waserror()){
+		vunmap(t, n);
+		nexterror();
 	}
-	return 0;
+	memmove(v, t, n);
+	vunmap(t, n);
+	poperror();
+	return n;
 }
 
 static long
 writemem(Chan*, void *v, long n, vlong o)
 {
-	int i;
-	uchar *t;
-	uintptr start, end;
-	Memreg *mr;
+	uintptr pa = (uintptr)o;
+	void *t;
 
-	start = o;
-	end = start + n;
-	for(i = 0; n > 0 && i < nmemregs; i++){
-		mr = &memregs[i];
-		if(start >= mr->addr && start < mr->addr+mr->size){
-			if(end > mr->addr+mr->size)
-				end = mr->addr+mr->size;
-			n = end - start;
-			t = vmap(mr->addr, n);
-			memmove(start - mr->addr + t, v, n);
-			vunmap(t, n);
-			return n;
-		}
+	if(memcheck(pa, n) != n)
+		error(Eio);
+	if((t = vmap(pa, n)) == nil)
+		error(Enovmem);
+	if(waserror()){
+		vunmap(t, n);
+		nexterror();
 	}
-	return 0;
+	memmove(t, v, n);
+	vunmap(t, n);
+	poperror();
+	return n;
 }
 
 static void
@@ -579,9 +571,6 @@
 
 	amlinit();
 
-	if(getconf("*acpimem") != nil)
-		addarchfile("acpimem", 0660, readmem, writemem);
-
 	/* load DSDT */
 	for(i=0; i<ntblmap; i++){
 		t = tblmap[i];
@@ -701,9 +690,6 @@
 	/* find embedded controller */
 	amlenum(amlroot, "_HID", enumec, nil);
 
-	/* init */
-	amlenum(amlroot, "_INI", enumini, nil);
-
 	/* look for PCI interrupt mappings */
 	amlenum(amlroot, "_PRT", enumprt, nil);
 
@@ -810,6 +796,7 @@
 	if(checksum(rsd, 20) && checksum(rsd, 36))
 		return 1;
 	addarchfile("acpitbls", 0444, readtbls, nil);
+	addarchfile("acpimem", 0600, readmem, writemem);
 	if(strcmp(cp, "0") == 0)
 		return 1;
 	if((cp = getconf("*nomp")) != nil && strcmp(cp, "0") != 0)
@@ -983,14 +970,14 @@
 		print("amlmapio: address space %x not implemented\n", io->space);
 		break;
 	case MemSpace:
+		if(memcheck(io->off, io->len) != io->len){
+			print("amlmapio: [%#p-%#p) overlaps usable memory\n",
+				(uintptr)io->off, (uintptr)io->off+io->len);
+			break;
+		}
 		if((io->va = vmap(io->off, io->len)) == nil){
 			print("amlmapio: vmap failed\n");
 			break;
-		}
-		if(nmemregs < nelem(memregs)){
-			memregs[nmemregs].addr = io->off;
-			memregs[nmemregs].size = io->len;
-			nmemregs++;
 		}
 		return 0;
 	case IoSpace: