ref: a4c6dc1d3d3a2ef3ec4d4ac49b16ec039c353cd7
parent: 2063019560c6a3154e6ef0e6e9f24d70c8ba09da
author: cinap_lenrek <[email protected]>
date: Sun Nov 1 20:14:30 EST 2020
aux/realemu: use #$/pci/B.D.Fraw to access pci config space This prevents VESA bios from accessing the pci CONFIG_ADDRESS/CONFIG_DATA registers (0xCF8/0xCFC) directly to access pci config space. This makes sure the access to pci config space is properly serialized by the kernel.
--- a/sys/src/cmd/aux/realemu/dat.h
+++ b/sys/src/cmd/aux/realemu/dat.h
@@ -3,6 +3,7 @@
typedef struct Bus Bus;
typedef struct Cpu Cpu;
typedef struct Pit Pit;
+typedef struct Pcidev Pcidev;
enum {
RAX,
@@ -103,6 +104,13 @@
/* argument buffers */
ulong iabuf;
Iarg abuf[0x80];
+};
+
+struct Pcidev
+{
+ Pcidev *next;
+ int bdf;
+ int fd;
};
struct Pit
--- a/sys/src/cmd/aux/realemu/fns.h
+++ b/sys/src/cmd/aux/realemu/fns.h
@@ -29,3 +29,12 @@
void setgate(Pit *ch, uchar gate);
uchar rpit(Pit *pit, uchar addr);
void wpit(Pit *pit, uchar addr, uchar data);
+
+/* pci */
+Pcidev *pciopen(int bdf);
+int pcicfgr(Pcidev *pci, void *data, int len, int addr);
+int pcicfgw(Pcidev *pci, void *data, int len, int addr);
+
+#define BDFBNO(bdf) (((int)bdf >> 16) & 0xFF)
+#define BDFDNO(bdf) (((int)bdf >> 11) & 0x1F)
+#define BDFFNO(bdf) (((int)bdf >> 8) & 0x07)
--- a/sys/src/cmd/aux/realemu/main.c
+++ b/sys/src/cmd/aux/realemu/main.c
@@ -29,6 +29,7 @@
static int cputrace;
static int porttrace;
static Pit pit[3];
+static ulong pcicfgaddr;
static uchar rtcaddr;
static vlong pitclock;
@@ -155,8 +156,9 @@
static ulong
rport(void *, ulong p, int len)
{
+ Pcidev *pci;
uchar data[4];
- ulong w;
+ ulong w, addr;
switch(p){
case 0x20: /* PIC 1 */
@@ -210,6 +212,24 @@
case 0xa1:
w = 0;
break;
+ case 0xcf8:
+ w = pcicfgaddr & ~0x7F000003;
+ break;
+ case 0xcfc: case 0xcfd: case 0xcfe: case 0xcff:
+ w = -1;
+ if((pcicfgaddr & (1<<31)) == 0)
+ break;
+ addr = (pcicfgaddr & 0xFC) | (p & 3);
+ if((pci = pciopen(pcicfgaddr & 0xFFFF00)) == nil)
+ break;
+ if(pcicfgr(pci, data, len, addr) != len)
+ break;
+ w = gw[len](data);
+ if(porttrace)
+ fprint(2, "pcicfgr %d.%d.%d %.2lux %.*lux\n",
+ BDFBNO(pcicfgaddr), BDFDNO(pcicfgaddr), BDFFNO(pcicfgaddr),
+ addr, len<<1, w);
+ break;
default:
if(pread(portfd[len], data, len, p) != len){
fprint(2, "bad %d bit port read %.4lux: %r\n", len*8, p);
@@ -225,7 +245,9 @@
static void
wport(void *, ulong p, ulong w, int len)
{
+ Pcidev *pci;
uchar data[4];
+ ulong addr;
if(porttrace)
fprint(2, "wport %.4lux %.*lux\n", p, len<<1, w);
@@ -274,6 +296,22 @@
case 0xA1:
break;
+ case 0xcf8:
+ pcicfgaddr = w;
+ break;
+ case 0xcfc: case 0xcfd: case 0xcfe: case 0xcff:
+ if((pcicfgaddr & (1<<31)) == 0)
+ break;
+ addr = (pcicfgaddr & 0xFC) | (p & 3);
+ if(porttrace)
+ fprint(2, "pcicfgw %d.%d.%d %.2lux %.*lux\n",
+ BDFBNO(pcicfgaddr), BDFDNO(pcicfgaddr), BDFFNO(pcicfgaddr),
+ addr, len<<1, w);
+ if((pci = pciopen(pcicfgaddr & 0xFFFF00)) == nil)
+ break;
+ pw[len](data, w);
+ pcicfgw(pci, data, len, addr);
+ break;
default:
pw[len](data, w);
if(pwrite(portfd[len], data, len, p) != len){
--- a/sys/src/cmd/aux/realemu/mkfile
+++ b/sys/src/cmd/aux/realemu/mkfile
@@ -3,7 +3,7 @@
BIN=/$objtype/bin/aux
TARG=realemu
-OFILES=decode.$O arg.$O xec.$O fmt.$O pit.$O main.$O
+OFILES=decode.$O arg.$O xec.$O fmt.$O pci.$O pit.$O main.$O
HFILES=dat.h fns.h
</sys/src/cmd/mkone
--- /dev/null
+++ b/sys/src/cmd/aux/realemu/pci.c
@@ -1,0 +1,45 @@
+#include <u.h>
+#include <libc.h>
+#include "dat.h"
+#include "fns.h"
+
+static Pcidev *devs;
+
+Pcidev*
+pciopen(int bdf)
+{
+ char path[64];
+ Pcidev *pci;
+
+ for(pci = devs; pci != nil; pci = pci->next){
+ if(pci->bdf == bdf){
+ if(pci->fd < 0)
+ return nil;
+ return pci;
+ }
+ }
+
+ pci = malloc(sizeof(Pcidev));
+ pci->bdf = bdf;
+
+ snprint(path, sizeof(path), "#$/pci/%d.%d.%draw",
+ BDFBNO(bdf), BDFDNO(bdf), BDFFNO(bdf));
+ pci->fd = open(path, ORDWR);
+
+ pci->next = devs;
+ devs = pci;
+
+ return pci;
+}
+
+int
+pcicfgr(Pcidev *pci, void *data, int len, int addr)
+{
+ return pread(pci->fd, data, len, addr);
+}
+
+int
+pcicfgw(Pcidev *pci, void *data, int len, int addr)
+{
+ return pwrite(pci->fd, data, len, addr);
+}