kernel: support large 64-bit pci membars, increase pc64 VMAPSIZE to 1TB

This makes vmap()/vunmap() take a vlong size argument,
and change the type of Pci.mem[].size to vlong as well.

Even if vmap() wont support large mappings, it is nice to
get the original unruncated value for error checking.

pc64 needs a bigger VMAP window, as system76 pangolin
puts the framebuffer at a physical address > 512GB.
This commit is contained in:
cinap_lenrek 2021-11-26 20:51:45 +00:00
parent add3a0a4da
commit 20ea113790
23 changed files with 119 additions and 99 deletions

View file

@ -67,8 +67,8 @@ extern void kmapinval(void);
extern KMap *kmap(Page*);
extern void kunmap(KMap*);
extern uintptr mmukmap(uintptr, uintptr, usize);
extern void* vmap(uvlong, int);
extern void vunmap(void*, int);
extern void* vmap(uvlong, vlong);
extern void vunmap(void*, vlong);
extern void mmu0init(uintptr*);
extern void mmu0clear(uintptr*);

View file

@ -324,7 +324,7 @@ mmukmap(uintptr va, uintptr pa, usize size)
}
void*
vmap(uvlong pa, int size)
vmap(uvlong pa, vlong size)
{
static uintptr base = VMAP;
uvlong pe = pa + size;
@ -337,7 +337,7 @@ vmap(uvlong pa, int size)
}
void
vunmap(void *, int)
vunmap(void *, vlong)
{
}

View file

@ -1266,11 +1266,11 @@ pccardread(Chan *c, void *a, long n, vlong offset)
for (i = 0; i < nelem(pci->mem); i++)
if (pci->mem[i].size)
p = seprint(p, e,
"\tmem[%d] %.8ullX (%.8uX)\n",
"\tmem[%d] %.8ullX (%.8ullX)\n",
i, pci->mem[i].bar,
pci->mem[i].size);
if (pci->rom.size)
p = seprint(p, e, "\tROM %.8ullX (%.8uX)\n",
p = seprint(p, e, "\tROM %.8ullX (%.8ullX)\n",
pci->rom.bar, pci->rom.size);
pci = pci->link;
}

View file

@ -113,7 +113,7 @@ wavelanpciscan(void)
* On the Prism, bar[0] is the memory-mapped register address (4KB),
*/
if((p->mem[0].bar & 1) != 0 || p->mem[0].size != 4096){
print("wavelanpci: %.4ux %.4ux: unlikely mmio bar %llux size %d\n",
print("wavelanpci: %.4ux %.4ux: unlikely mmio bar %llux size %lld\n",
p->vid, p->did, p->mem[0].bar, p->mem[0].size);
continue;
}
@ -126,7 +126,7 @@ wavelanpciscan(void)
ctlr->pcidev = p;
mem = vmap(p->mem[0].bar&~0xF, p->mem[0].size);
if(mem == nil){
print("wavelanpci: %.4ux %.4ux: vmap %llux %d failed\n",
print("wavelanpci: %.4ux %.4ux: vmap %llux %lld failed\n",
p->vid, p->did, p->mem[0].bar&~0xF, p->mem[0].size);
free(ctlr);
continue;

View file

@ -159,15 +159,15 @@ int tas(void*);
uvlong tscticks(uvlong*);
ulong umballoc(ulong, ulong, ulong);
void umbfree(ulong, ulong);
uvlong upaalloc(uvlong, ulong, ulong);
uvlong upaallocwin(uvlong, ulong, ulong, ulong);
void upafree(uvlong, ulong);
uvlong upaalloc(uvlong, uvlong, uvlong);
uvlong upaallocwin(uvlong, uvlong, uvlong, uvlong);
void upafree(uvlong, uvlong);
void vectortable(void);
void* vmap(uvlong, int);
void* vmap(uvlong, vlong);
int vmapsync(ulong);
void vmxprocrestore(Proc *);
void vmxshutdown(void);
void vunmap(void*, int);
void vunmap(void*, vlong);
void wbinvd(void);
void writeconf(void);
int wrmsr(int, vlong);

View file

@ -245,13 +245,13 @@ rsdsearch(void)
* Call vmap to do that.
*/
uvlong
upaalloc(uvlong pa, ulong size, ulong align)
upaalloc(uvlong pa, uvlong size, uvlong align)
{
return memmapalloc(pa, size, align, MemUPA);
}
uvlong
upaallocwin(uvlong pa, ulong win, ulong size, ulong align)
upaallocwin(uvlong pa, uvlong win, uvlong size, uvlong align)
{
uvlong a, base, top = pa + win;
@ -269,7 +269,7 @@ upaallocwin(uvlong pa, ulong win, ulong size, ulong align)
}
void
upafree(uvlong pa, ulong size)
upafree(uvlong pa, uvlong size)
{
memmapfree(pa, size, MemUPA);
}

View file

@ -530,13 +530,13 @@ static void pdbunmap(ulong*, ulong, int);
* Add a device mapping to the vmap range.
*/
void*
vmap(uvlong pa, int size)
vmap(uvlong pa, vlong size)
{
int osize;
vlong osize;
ulong o, va;
if(pa < BY2PG || size <= 0 || ((pa+size) >> 32) != 0 || size > VMAPSIZE){
print("vmap pa=%llux size=%d pc=%#p\n", pa, size, getcallerpc(&pa));
print("vmap pa=%llux size=%lld pc=%#p\n", pa, size, getcallerpc(&pa));
return nil;
}
@ -560,7 +560,7 @@ vmap(uvlong pa, int size)
vmapsync(va+i);
*/
USED(osize);
// print(" vmap %#.8lux %d => %#.8lux\n", pa+o, osize, va+o);
// print(" vmap %#.8lux %lld => %#.8lux\n", pa+o, osize, va+o);
return (void*)(va + o);
}
@ -621,7 +621,7 @@ vmapalloc(ulong size)
* the call need not be interlocked with vmap.
*/
void
vunmap(void *v, int size)
vunmap(void *v, vlong size)
{
ulong va, o;
@ -635,7 +635,7 @@ vunmap(void *v, int size)
size = ROUND(size, BY2PG);
if(size < 0 || va < VMAP || va+size > VMAP+VMAPSIZE)
panic("vunmap va=%#.8lux size=%#x pc=%#.8lux",
panic("vunmap va=%#.8lux size=%lld pc=%#.8lux",
va, size, getcallerpc(&v));
pdbunmap(MACHP(0)->pdb, va, size);

View file

@ -603,7 +603,7 @@ pcireserve(void)
p->mem[i].bar |= pa;
}
pcisetbar(p, PciBAR0 + i*4, p->mem[i].bar);
DBG("%s: bar%d: fixed %.8lluX %d\n", tag, i, p->mem[i].bar, p->mem[i].size);
DBG("%s: bar%d: fixed %.8lluX %lld\n", tag, i, p->mem[i].bar, p->mem[i].size);
}
}
}

View file

@ -563,9 +563,10 @@ blankscreen(int blank)
}
static char*
vgalinearaddr0(VGAscr *scr, uvlong paddr, int size)
vgalinearaddr0(VGAscr *scr, uvlong paddr, vlong size)
{
int x, nsize;
int x;
vlong nsize;
uvlong npaddr;
/*
@ -603,7 +604,7 @@ vgalinearaddr0(VGAscr *scr, uvlong paddr, int size)
scr->vaddr = (char*)scr->vaddr+x;
scr->paddr = paddr;
scr->apsize = nsize;
scr->apsize = (int)nsize;
mtrr(npaddr, nsize, "wc");
@ -613,8 +614,7 @@ vgalinearaddr0(VGAscr *scr, uvlong paddr, int size)
static char*
vgalinearpci0(VGAscr *scr)
{
int i, size, best;
uvlong paddr;
int i, best;
Pcidev *p;
p = scr->pci;
@ -645,12 +645,9 @@ vgalinearpci0(VGAscr *scr)
&& !(p->mem[best].bar&8)))
best = i;
}
if(best >= 0){
paddr = p->mem[best].bar & ~0x0F;
size = p->mem[best].size;
return vgalinearaddr0(scr, paddr, size);
}
return "no video memory found on pci card";
if(best < 0)
return "no video memory found on pci card";
return vgalinearaddr0(scr, p->mem[best].bar&~0xF, p->mem[best].size);
}
void
@ -665,7 +662,7 @@ vgalinearpci(VGAscr *scr)
}
void
vgalinearaddr(VGAscr *scr, uvlong paddr, int size)
vgalinearaddr(VGAscr *scr, uvlong paddr, vlong size)
{
char *err;

View file

@ -136,7 +136,7 @@ extern char *tiltstr[4];
extern Rectangle actualscreensize(VGAscr*);
extern void setactualsize(VGAscr*, Rectangle);
extern void setscreensize(VGAscr*, int, int, int, ulong, int);
extern void addvgaseg(char*, uvlong, ulong);
extern void addvgaseg(char*, uvlong, vlong);
extern Memdata* attachscreen(Rectangle*, ulong*, int*, int*, int*);
extern void flushmemscreen(Rectangle);
extern void cursoron(void);
@ -159,7 +159,7 @@ extern QLock drawlock;
extern void vgascreenwin(VGAscr*);
extern void vgaimageinit(ulong);
extern void vgalinearpci(VGAscr*);
extern void vgalinearaddr(VGAscr*, uvlong, int);
extern void vgalinearaddr(VGAscr*, uvlong, vlong);
extern void vgablank(VGAscr*, int);
extern Lock vgascreenlock;

View file

@ -184,7 +184,7 @@ scanpci(void)
if(io == 0)
continue;
print("usbehci: %#x %#x: port %llux size %d irq %d\n",
print("usbehci: %#x %#x: port %llux size %lld irq %d\n",
p->vid, p->did, io, p->mem[0].size, p->intl);
ctlr = malloc(sizeof(Ctlr));

View file

@ -2401,7 +2401,7 @@ scanpci(void)
io = p->mem[0].bar & ~0xFULL;
if(io == 0)
continue;
print("usbohci: %#x %#x: port %llux size %#x irq %d\n",
print("usbohci: %#x %#x: port %llux size %lld irq %d\n",
p->vid, p->did, io, p->mem[0].size, p->intl);
ctlr = malloc(sizeof(Ctlr));
if(ctlr == nil){

View file

@ -2146,7 +2146,7 @@ scanpci(void)
continue;
}
print("uhci: %#x %#x: port %#ux size %#x irq %d\n",
print("uhci: %#x %#x: port %#ux size %lld irq %d\n",
p->vid, p->did, io, p->mem[4].size, p->intl);
ctlr = malloc(sizeof(Ctlr));

View file

@ -252,11 +252,11 @@ vgablank(VGAscr*, int blank)
}
void
addvgaseg(char *name, uvlong pa, ulong size)
addvgaseg(char *name, uvlong pa, vlong size)
{
Physseg seg;
if((uintptr)pa != pa || size == 0 || -(uintptr)pa < size){
if((uintptr)pa != pa || size <= 0 || -(uintptr)pa < size){
print("addvgaseg %s: bad address %llux-%llux pc %#p\n",
name, pa, pa+size, getcallerpc(&name));
return;

View file

@ -29,7 +29,7 @@ neomagicenable(VGAscr* scr)
Pcidev *p;
int bar, curoff, vmsize;
uvlong ioaddr;
ulong iosize;
vlong iosize;
/*
* scr->mmio holds the virtual address of the cursor registers
@ -78,7 +78,7 @@ neomagicenable(VGAscr* scr)
default:
return;
}
if(p->mem[bar].bar & 1)
if(p->mem[bar].bar & 1 || p->mem[bar].size == 0)
return;
ioaddr = p->mem[bar].bar & ~0x0F;
iosize = p->mem[bar].size;

View file

@ -162,14 +162,14 @@ int tas(void*);
uvlong tscticks(uvlong*);
ulong umballoc(ulong, ulong, ulong);
void umbfree(ulong, ulong);
uvlong upaalloc(uvlong, ulong, ulong);
uvlong upaallocwin(uvlong, ulong, ulong, ulong);
void upafree(uvlong, ulong);
uvlong upaalloc(uvlong, uvlong, uvlong);
uvlong upaallocwin(uvlong, uvlong, uvlong, uvlong);
void upafree(uvlong, uvlong);
void vectortable(void);
void vmxprocrestore(Proc *);
void vmxshutdown(void);
void* vmap(uvlong, int);
void vunmap(void*, int);
void* vmap(uvlong, vlong);
void vunmap(void*, vlong);
void wbinvd(void);
void writeconf(void);
int wrmsr(int, vlong);

View file

@ -53,10 +53,10 @@
#define KZERO (0xffffffff80000000ull)
#define KTZERO (KZERO+1*MiB+64*KiB)
#define VMAP (0xffffff0000000000ull)
#define VMAPSIZE (512ull*GiB)
#define VMAP (0xfffffe8000000000ull)
#define VMAPSIZE (1024ull*GiB)
#define KMAP (0xfffffe8000000000ull)
#define KMAP (0xfffffe0000000000ull)
#define KMAPSIZE (2*MiB)
/*

View file

@ -584,13 +584,13 @@ kunmap(KMap *k)
* synchronization is being done.
*/
void*
vmap(uvlong pa, int size)
vmap(uvlong pa, vlong size)
{
uintptr va;
int o;
if(pa < BY2PG || size <= 0 || -pa < size || pa+size > VMAPSIZE){
print("vmap pa=%llux size=%d pc=%#p\n", pa, size, getcallerpc(&pa));
print("vmap pa=%llux size=%lld pc=%#p\n", pa, size, getcallerpc(&pa));
return nil;
}
va = pa+VMAP;
@ -607,7 +607,7 @@ vmap(uvlong pa, int size)
}
void
vunmap(void *v, int)
vunmap(void *v, vlong)
{
paddr(v); /* will panic on error */
}

View file

@ -32,7 +32,7 @@ squidboy(Apic* apic)
void
mpstartap(Apic* apic)
{
uintptr *apbootp, *pml4, *pdp0;
uintptr *apbootp, *pml4, *pdp0, v;
Segdesc *gdt;
Mach *mach;
uchar *p;
@ -65,8 +65,11 @@ mpstartap(Apic* apic)
* map KZERO (note that we share the KZERO (and VMAP)
* PDP between processors.
*/
pml4[PTLX(KZERO, 3)] = MACHP(0)->pml4[PTLX(KZERO, 3)];
pml4[PTLX(VMAP, 3)] = MACHP(0)->pml4[PTLX(VMAP, 3)];
*mmuwalk(pml4, KZERO, 3, 0) = *mmuwalk(m->pml4, KZERO, 3, 0);
for(v = VMAP; v < VMAP+VMAPSIZE; v += PGLSZ(3)){
mmuwalk(m->pml4, v, 2, 1); /* force create */
*mmuwalk(pml4, v, 3, 0) = *mmuwalk(m->pml4, v, 3, 0);
}
/* double map */
pml4[0] = PADDR(pdp0) | PTEWRITE|PTEVALID;

View file

@ -545,7 +545,8 @@ pnpread(Chan *c, void *va, long n, vlong offset)
for(i=0; i<nelem(p->mem); i++){
if(p->mem[i].size == 0)
continue;
w = seprint(w, ebuf, " %d:%.8llux %d", i, (uvlong)p->mem[i].bar, p->mem[i].size);
w = seprint(w, ebuf, " %d:%.8llux %lld", i,
p->mem[i].bar, p->mem[i].size);
}
*w++ = '\n';
*w = '\0';

View file

@ -10,7 +10,7 @@ typedef struct Pcisiz Pcisiz;
struct Pcisiz
{
Pcidev* dev;
int siz;
vlong siz;
int bar;
int typ;
};
@ -162,25 +162,41 @@ pcicfgw32(Pcidev* p, int rno, int data)
iunlock(&pcicfglock);
}
int
vlong
pcibarsize(Pcidev *p, int rno)
{
int v, size;
vlong size;
int v;
ilock(&pcicfglock);
v = pcicfgrw32(p->tbdf, rno, 0, 1);
pcicfgrw32(p->tbdf, rno, -1, 0);
size = pcicfgrw32(p->tbdf, rno, 0, 1);
size = (int)pcicfgrw32(p->tbdf, rno, 0, 1);
pcicfgrw32(p->tbdf, rno, v, 0);
if(rno == PciEBAR0 || rno == PciEBAR1)
size &= ~0x7FFLL;
else if(v & 1)
size = (short)size & ~0x3LL;
else {
size &= ~0xFLL;
if(size >= 0 && (v&7)==4 && rno < PciBAR0+4*(nelem(p->mem)-1)){
rno += 4;
v = pcicfgrw32(p->tbdf, rno, 0, 1);
pcicfgrw32(p->tbdf, rno, -1, 0);
size |= (vlong)pcicfgrw32(p->tbdf, rno, 0, 1)<<32;
pcicfgrw32(p->tbdf, rno, v, 0);
}
}
iunlock(&pcicfglock);
if(rno == PciEBAR0 || rno == PciEBAR1){
size &= ~0x7FF;
} else if(v & 1){
size = (short)size;
size &= ~3;
} else {
size &= ~0xF;
if(size > 0){
print("pcibarsize: %T invalid bar rno %x mask %llux\n",
p->tbdf, rno, (uvlong)size);
return 0;
}
return -size;
@ -216,39 +232,41 @@ pcisetwin(Pcidev *p, uvlong base, uvlong limit)
static int
pcisizcmp(void *a, void *b)
{
Pcisiz *aa, *bb;
Pcisiz *aa = a, *bb = b;
aa = a;
bb = b;
return aa->siz - bb->siz;
if(aa->siz > bb->siz)
return 1;
if(aa->siz < bb->siz)
return -1;
return 0;
}
static ulong
pcimask(ulong v)
static vlong
pcimask(vlong v)
{
ulong m;
uvlong m;
m = BI2BY*sizeof(v);
for(m = 1<<(m-1); m != 0; m >>= 1) {
for(m = 1ULL<<63; m != 0; m >>= 1) {
if(m & v)
break;
}
m--;
if((v & m) == 0)
return v;
v |= m;
return v+1;
if(v & m){
v |= m;
v++;
}
return v;
}
void
pcibusmap(Pcidev *root, uvlong *pmema, ulong *pioa, int wrreg)
{
Pcidev *p;
int ntb, i, size, rno, hole;
int ntb, i, rno;
uvlong mema, smema;
ulong ioa, sioa, v;
vlong hole, size;
Pcisiz *table, *tptr, *mtb, *itb;
ioa = *pioa;
@ -348,7 +366,7 @@ pcibusmap(Pcidev *root, uvlong *pmema, ulong *pioa, int wrreg)
mtb->bar = i;
mtb->siz = size;
mtb->typ = v & 7;
if(mtb->typ & 4)
if(mtb->typ == 4)
i++;
mtb++;
}
@ -478,7 +496,7 @@ pcivalidwin(Pcidev *p, uvlong base, uvlong limit)
}
static int
pcivalidbar(Pcidev *p, uvlong bar, int size)
pcivalidbar(Pcidev *p, uvlong bar, vlong size)
{
if(bar & 1){
bar &= ~3;
@ -572,7 +590,8 @@ pciscan(int bno, Pcidev** list, Pcidev *parent)
p->mem[i].size = pcibarsize(p, rno);
if((p->mem[i].bar & 7) == 4 && i < nelem(p->mem)-1){
rno += 4;
p->mem[i++].bar |= (uvlong)pcicfgr32(p, rno) << 32;
p->mem[i].bar |= (uvlong)pcicfgr32(p, rno) << 32;
i++;
p->mem[i].bar = 0;
p->mem[i].size = 0;
}
@ -827,16 +846,16 @@ pcilhinv(Pcidev* p)
for(i = 0; i < nelem(p->mem); i++) {
if(t->mem[i].size == 0)
continue;
print("%d:%.8llux %d ", i, t->mem[i].bar, t->mem[i].size);
print("%d:%.8llux %lld ", i, t->mem[i].bar, t->mem[i].size);
}
if(t->rom.bar || t->rom.size)
print("rom:%.8llux %d ", t->rom.bar, t->rom.size);
print("rom:%.8llux %lld ", t->rom.bar, t->rom.size);
if(t->ioa.bar || t->ioa.size)
print("ioa:%.8llux-%.8llux %d ", t->ioa.bar, t->ioa.bar+t->ioa.size, t->ioa.size);
print("ioa:%.8llux-%.8llux %lld ", t->ioa.bar, t->ioa.bar+t->ioa.size, t->ioa.size);
if(t->mema.bar || t->mema.size)
print("mema:%.8llux-%.8llux %d ", t->mema.bar, t->mema.bar+t->mema.size, t->mema.size);
print("mema:%.8llux-%.8llux %lld ", t->mema.bar, t->mema.bar+t->mema.size, t->mema.size);
if(t->prefa.bar || t->prefa.size)
print("prefa:%.8llux-%.8llux %llud ", t->prefa.bar, t->prefa.bar+t->prefa.size, t->prefa.size);
print("prefa:%.8llux-%.8llux %lld ", t->prefa.bar, t->prefa.bar+t->prefa.size, t->prefa.size);
if(t->bridge)
print("->%d", BUSBNO(t->bridge->tbdf));
print("\n");

View file

@ -177,22 +177,22 @@ struct Pcidev
struct {
uvlong bar; /* base address */
int size;
vlong size;
} mem[6];
struct { /* expansion rom bar */
uvlong bar;
int size;
vlong size;
} rom;
struct { /* 32-bit io and memory windows */
uvlong bar;
int size;
vlong size;
} ioa, mema;
struct { /* 64-bit prefechable memory window */
uvlong bar;
uvlong size;
vlong size;
} prefa;
Pcidev* list;
@ -240,7 +240,7 @@ extern void pcibussize(Pcidev *root, uvlong *msize, ulong *iosize);
extern Pcidev* pcimatch(Pcidev* prev, int vid, int did);
extern Pcidev* pcimatchtbdf(int tbdf);
extern int pcibarsize(Pcidev *, int rno);
extern vlong pcibarsize(Pcidev *, int rno);
extern void pcisetbar(Pcidev *, int, uvlong);
extern uchar pciipin(Pcidev *pci, uchar pin);

View file

@ -1814,7 +1814,7 @@ scanpci(void)
io = p->mem[0].bar & ~0x0f;
if(io == 0)
continue;
print("usbxhci: %#x %#x: port %llux size %d irq %d\n",
print("usbxhci: %#x %#x: port %llux size %lld irq %d\n",
p->vid, p->did, io, p->mem[0].size, p->intl);
mmio = vmap(io, p->mem[0].size);
if(mmio == nil){