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 Bus Bus;
|
||||||
typedef struct Cpu Cpu;
|
typedef struct Cpu Cpu;
|
||||||
typedef struct Pit Pit;
|
typedef struct Pit Pit;
|
||||||
|
typedef struct Pcidev Pcidev;
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
RAX,
|
RAX,
|
||||||
|
@ -105,6 +106,13 @@ struct Cpu
|
||||||
Iarg abuf[0x80];
|
Iarg abuf[0x80];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct Pcidev
|
||||||
|
{
|
||||||
|
Pcidev *next;
|
||||||
|
int bdf;
|
||||||
|
int fd;
|
||||||
|
};
|
||||||
|
|
||||||
struct Pit
|
struct Pit
|
||||||
{
|
{
|
||||||
ulong count;
|
ulong count;
|
||||||
|
|
|
@ -29,3 +29,12 @@ void clockpit(Pit *pit, vlong cycles);
|
||||||
void setgate(Pit *ch, uchar gate);
|
void setgate(Pit *ch, uchar gate);
|
||||||
uchar rpit(Pit *pit, uchar addr);
|
uchar rpit(Pit *pit, uchar addr);
|
||||||
void wpit(Pit *pit, uchar addr, uchar data);
|
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 cputrace;
|
||||||
static int porttrace;
|
static int porttrace;
|
||||||
static Pit pit[3];
|
static Pit pit[3];
|
||||||
|
static ulong pcicfgaddr;
|
||||||
static uchar rtcaddr;
|
static uchar rtcaddr;
|
||||||
|
|
||||||
static vlong pitclock;
|
static vlong pitclock;
|
||||||
|
@ -155,8 +156,9 @@ wrealmem(void *, ulong off, ulong w, int len)
|
||||||
static ulong
|
static ulong
|
||||||
rport(void *, ulong p, int len)
|
rport(void *, ulong p, int len)
|
||||||
{
|
{
|
||||||
|
Pcidev *pci;
|
||||||
uchar data[4];
|
uchar data[4];
|
||||||
ulong w;
|
ulong w, addr;
|
||||||
|
|
||||||
switch(p){
|
switch(p){
|
||||||
case 0x20: /* PIC 1 */
|
case 0x20: /* PIC 1 */
|
||||||
|
@ -210,6 +212,24 @@ rport(void *, ulong p, int len)
|
||||||
case 0xa1:
|
case 0xa1:
|
||||||
w = 0;
|
w = 0;
|
||||||
break;
|
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:
|
default:
|
||||||
if(pread(portfd[len], data, len, p) != len){
|
if(pread(portfd[len], data, len, p) != len){
|
||||||
fprint(2, "bad %d bit port read %.4lux: %r\n", len*8, p);
|
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
|
static void
|
||||||
wport(void *, ulong p, ulong w, int len)
|
wport(void *, ulong p, ulong w, int len)
|
||||||
{
|
{
|
||||||
|
Pcidev *pci;
|
||||||
uchar data[4];
|
uchar data[4];
|
||||||
|
ulong addr;
|
||||||
|
|
||||||
if(porttrace)
|
if(porttrace)
|
||||||
fprint(2, "wport %.4lux %.*lux\n", p, len<<1, w);
|
fprint(2, "wport %.4lux %.*lux\n", p, len<<1, w);
|
||||||
|
@ -274,6 +296,22 @@ wport(void *, ulong p, ulong w, int len)
|
||||||
case 0xA1:
|
case 0xA1:
|
||||||
break;
|
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:
|
default:
|
||||||
pw[len](data, w);
|
pw[len](data, w);
|
||||||
if(pwrite(portfd[len], data, len, p) != len){
|
if(pwrite(portfd[len], data, len, p) != len){
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
BIN=/$objtype/bin/aux
|
BIN=/$objtype/bin/aux
|
||||||
|
|
||||||
TARG=realemu
|
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
|
HFILES=dat.h fns.h
|
||||||
|
|
||||||
</sys/src/cmd/mkone
|
</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