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:
cinap_lenrek 2020-11-02 01:14:30 +01:00
parent 2063019560
commit a4c6dc1d3d
5 changed files with 102 additions and 2 deletions

View file

@ -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;

View file

@ -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)

View file

@ -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){

View file

@ -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

View 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);
}