diff options
author | cinap_lenrek <cinap_lenrek@felloff.net> | 2020-11-02 01:14:30 +0100 |
---|---|---|
committer | cinap_lenrek <cinap_lenrek@felloff.net> | 2020-11-02 01:14:30 +0100 |
commit | a4c6dc1d3d3a2ef3ec4d4ac49b16ec039c353cd7 (patch) | |
tree | c6ce89a62f6b016eae117709a53648ff5a453b80 /sys/src | |
parent | 2063019560c6a3154e6ef0e6e9f24d70c8ba09da (diff) |
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.
Diffstat (limited to 'sys/src')
-rw-r--r-- | sys/src/cmd/aux/realemu/dat.h | 8 | ||||
-rw-r--r-- | sys/src/cmd/aux/realemu/fns.h | 9 | ||||
-rw-r--r-- | sys/src/cmd/aux/realemu/main.c | 40 | ||||
-rw-r--r-- | sys/src/cmd/aux/realemu/mkfile | 2 | ||||
-rw-r--r-- | sys/src/cmd/aux/realemu/pci.c | 45 |
5 files changed, 102 insertions, 2 deletions
diff --git a/sys/src/cmd/aux/realemu/dat.h b/sys/src/cmd/aux/realemu/dat.h index 8a2bb4643..3255681b8 100644 --- a/sys/src/cmd/aux/realemu/dat.h +++ b/sys/src/cmd/aux/realemu/dat.h @@ -3,6 +3,7 @@ typedef struct Inst Inst; typedef struct Bus Bus; typedef struct Cpu Cpu; typedef struct Pit Pit; +typedef struct Pcidev Pcidev; enum { RAX, @@ -105,6 +106,13 @@ struct Cpu Iarg abuf[0x80]; }; +struct Pcidev +{ + Pcidev *next; + int bdf; + int fd; +}; + struct Pit { ulong count; diff --git a/sys/src/cmd/aux/realemu/fns.h b/sys/src/cmd/aux/realemu/fns.h index a25f6955a..11b7e8cdb 100644 --- a/sys/src/cmd/aux/realemu/fns.h +++ b/sys/src/cmd/aux/realemu/fns.h @@ -29,3 +29,12 @@ void clockpit(Pit *pit, vlong cycles); 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) diff --git a/sys/src/cmd/aux/realemu/main.c b/sys/src/cmd/aux/realemu/main.c index 31043e889..53dc91f6f 100644 --- a/sys/src/cmd/aux/realemu/main.c +++ b/sys/src/cmd/aux/realemu/main.c @@ -29,6 +29,7 @@ static int realmemfd; static int cputrace; static int porttrace; static Pit pit[3]; +static ulong pcicfgaddr; static uchar rtcaddr; static vlong pitclock; @@ -155,8 +156,9 @@ wrealmem(void *, ulong off, ulong w, int len) 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 @@ rport(void *, ulong p, int len) 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 @@ rport(void *, ulong p, int len) 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 @@ wport(void *, ulong p, ulong w, int len) 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){ diff --git a/sys/src/cmd/aux/realemu/mkfile b/sys/src/cmd/aux/realemu/mkfile index dd6d1d5a6..0a533ce04 100644 --- 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 diff --git a/sys/src/cmd/aux/realemu/pci.c b/sys/src/cmd/aux/realemu/pci.c new file mode 100644 index 000000000..fda24cb8e --- /dev/null +++ b/sys/src/cmd/aux/realemu/pci.c @@ -0,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); +} |