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.
This commit is contained in:
parent
2063019560
commit
a4c6dc1d3d
5 changed files with 102 additions and 2 deletions
|
@ -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;
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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){
|
||||
|
|
|
@ -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
|
||||
|
|
45
sys/src/cmd/aux/realemu/pci.c
Normal file
45
sys/src/cmd/aux/realemu/pci.c
Normal file
|
@ -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);
|
||||
}
|
Loading…
Reference in a new issue