merge
This commit is contained in:
commit
f5352eb501
|
@ -120,7 +120,7 @@ extern int fpuemu(Ureg*);
|
|||
/*
|
||||
* Things called from port.
|
||||
*/
|
||||
extern void delay(int); /* only scheddump() */
|
||||
extern void delay(int);
|
||||
extern int islo(void);
|
||||
extern void microdelay(int); /* only edf.c */
|
||||
extern void evenaddr(uintptr);
|
||||
|
|
|
@ -118,7 +118,7 @@ extern Block* uciallocb(int);
|
|||
/*
|
||||
* Things called from port.
|
||||
*/
|
||||
extern void delay(int); /* only scheddump() */
|
||||
extern void delay(int);
|
||||
extern int islo(void);
|
||||
extern void microdelay(int); /* only edf.c */
|
||||
extern void evenaddr(uintptr);
|
||||
|
|
|
@ -85,10 +85,11 @@ mmusweep(void*)
|
|||
|
||||
sweepcolor = m->sweepcolor;
|
||||
x = splhi();
|
||||
p = proctab(0);
|
||||
for(i = 0; i < conf.nproc; i++, p++)
|
||||
for(i = 0; i < conf.nproc; i++) {
|
||||
p = proctab(i);
|
||||
if(PIDCOLOR(p->mmupid) == sweepcolor)
|
||||
p->mmupid = 0;
|
||||
}
|
||||
splx(x);
|
||||
|
||||
ptab = (ulong*)m->ptabbase;
|
||||
|
|
|
@ -133,7 +133,7 @@ extern void ucfreeb(Block*);
|
|||
/*
|
||||
* Things called from port.
|
||||
*/
|
||||
extern void delay(int); /* only scheddump() */
|
||||
extern void delay(int);
|
||||
extern int islo(void);
|
||||
extern void microdelay(int); /* only edf.c */
|
||||
extern void evenaddr(uintptr);
|
||||
|
|
|
@ -113,8 +113,9 @@ maptable(uvlong xpa)
|
|||
int i;
|
||||
|
||||
pa = xpa;
|
||||
if((uvlong)pa != xpa || pa == 0)
|
||||
if((uvlong)pa != xpa || pa == 0 || pa+7 < pa)
|
||||
return;
|
||||
|
||||
if(ntblpa >= nelem(tblpa) || ntblmap >= nelem(tblmap))
|
||||
return;
|
||||
|
||||
|
@ -124,21 +125,18 @@ maptable(uvlong xpa)
|
|||
}
|
||||
tblpa[ntblpa++] = pa;
|
||||
|
||||
memreserve(pa, 8);
|
||||
if((t = vmap(pa, 8)) == nil)
|
||||
return;
|
||||
l = get32(t->len);
|
||||
if(l < Tblsz){
|
||||
vunmap(t, 8);
|
||||
return;
|
||||
}
|
||||
if(memcheck(pa, l) != l){
|
||||
print("maptable: ignoring %.4s at [%#p-%#p); overlaps usable memory\n",
|
||||
(char*)t->sig, pa, pa+l);
|
||||
if(l < Tblsz
|
||||
|| l >= 0x10000000
|
||||
|| pa+l-1 < pa){
|
||||
vunmap(t, 8);
|
||||
return;
|
||||
}
|
||||
memreserve(pa, l);
|
||||
vunmap(t, 8);
|
||||
|
||||
if((t = vmap(pa, l)) == nil)
|
||||
return;
|
||||
if(checksum(t, l)){
|
||||
|
@ -177,9 +175,10 @@ maptables(void)
|
|||
return;
|
||||
if(!checksum(rsd, 20))
|
||||
maptable(get32(rsd->raddr));
|
||||
if(rsd->rev >= 2)
|
||||
if(rsd->rev >= 2){
|
||||
if(!checksum(rsd, 36))
|
||||
maptable(get64(rsd->xaddr));
|
||||
}
|
||||
}
|
||||
|
||||
static Apic*
|
||||
|
@ -567,8 +566,6 @@ acpiinit(void)
|
|||
ulong lapicbase;
|
||||
int machno, i, c;
|
||||
|
||||
maptables();
|
||||
|
||||
amlinit();
|
||||
|
||||
/* load DSDT */
|
||||
|
@ -789,14 +786,15 @@ identify(void)
|
|||
pa = (uintptr)strtoull(cp, nil, 16);
|
||||
if(pa <= 1)
|
||||
rsd = rsdsearch();
|
||||
else if(pa < MemMin)
|
||||
rsd = KADDR(pa);
|
||||
else
|
||||
else {
|
||||
memreserve(pa, sizeof(Rsd));
|
||||
rsd = vmap(pa, sizeof(Rsd));
|
||||
}
|
||||
if(rsd == nil)
|
||||
return 1;
|
||||
if(checksum(rsd, 20) && checksum(rsd, 36))
|
||||
return 1;
|
||||
maptables();
|
||||
addarchfile("acpitbls", 0444, readtbls, nil);
|
||||
addarchfile("acpimem", 0600, readmem, writemem);
|
||||
if(strcmp(cp, "0") == 0)
|
||||
|
|
|
@ -383,7 +383,7 @@ identify(void)
|
|||
{
|
||||
char *cp;
|
||||
_MP_ *_mp_;
|
||||
ulong len;
|
||||
ulong pa, len;
|
||||
|
||||
if((cp = getconf("*nomp")) != nil && strcmp(cp, "0") != 0)
|
||||
return 1;
|
||||
|
@ -399,26 +399,28 @@ identify(void)
|
|||
return 1;
|
||||
|
||||
len = PCMPsz;
|
||||
if(_mp_->physaddr < MemMin)
|
||||
pcmp = KADDR(_mp_->physaddr);
|
||||
else if((pcmp = vmap(_mp_->physaddr, len)) == nil)
|
||||
pa = _mp_->physaddr;
|
||||
if(pa + len-1 < pa)
|
||||
return 1;
|
||||
if(pcmp->length < len
|
||||
|
||||
memreserve(pa, len);
|
||||
if((pcmp = vmap(pa, len)) == nil)
|
||||
return 1;
|
||||
if(pcmp->length < PCMPsz
|
||||
|| pa + pcmp->length-1 < pa
|
||||
|| memcmp(pcmp, "PCMP", 4) != 0
|
||||
|| (pcmp->version != 1 && pcmp->version != 4)){
|
||||
Bad:
|
||||
if((uintptr)pcmp < KZERO)
|
||||
vunmap(pcmp, len);
|
||||
vunmap(pcmp, len);
|
||||
pcmp = nil;
|
||||
return 1;
|
||||
}
|
||||
len = pcmp->length;
|
||||
if((uintptr)pcmp < KZERO)
|
||||
vunmap(pcmp, PCMPsz);
|
||||
if(_mp_->physaddr < MemMin)
|
||||
pcmp = KADDR(_mp_->physaddr);
|
||||
else if((pcmp = vmap(_mp_->physaddr, len)) == nil)
|
||||
memreserve(pa, len);
|
||||
vunmap(pcmp, PCMPsz);
|
||||
if((pcmp = vmap(pa, len)) == nil)
|
||||
return 1;
|
||||
|
||||
if(checksum(pcmp, len) != 0)
|
||||
goto Bad;
|
||||
|
||||
|
|
|
@ -24,7 +24,7 @@ multibootargs(void)
|
|||
ulong *m, l;
|
||||
int i, n;
|
||||
|
||||
if(multibootptr == 0)
|
||||
if(multibootptr == 0 || multibootptr >= MemMin)
|
||||
return;
|
||||
|
||||
multiboot = (ulong*)KADDR(multibootptr);
|
||||
|
|
|
@ -268,7 +268,6 @@ pcmmap(int slotno, ulong offset, int len, int attr)
|
|||
if((we & bit))
|
||||
if(m->attr == attr)
|
||||
if(offset >= m->ca && e <= m->cea){
|
||||
|
||||
m->ref++;
|
||||
unlock(&pp->mlock);
|
||||
return m;
|
||||
|
@ -285,12 +284,13 @@ pcmmap(int slotno, ulong offset, int len, int attr)
|
|||
|
||||
/* if isa space isn't big enough, free it and get more */
|
||||
if(m->len < len){
|
||||
if(m->isa){
|
||||
if(m->len){
|
||||
umbfree(m->isa, m->len);
|
||||
m->len = 0;
|
||||
}
|
||||
m->isa = PADDR(umbmalloc(0, len, Mgran));
|
||||
if(m->isa == 0){
|
||||
m->isa = umballoc(-1, len, Mgran);
|
||||
if(m->isa == -1){
|
||||
m->isa = 0;
|
||||
print("pcmmap: out of isa space\n");
|
||||
unlock(&pp->mlock);
|
||||
return 0;
|
||||
|
|
|
@ -521,7 +521,6 @@ devpccardlink(void)
|
|||
int i;
|
||||
uchar intl;
|
||||
char *p;
|
||||
void *baddrva;
|
||||
|
||||
if (initialized)
|
||||
return;
|
||||
|
@ -543,7 +542,6 @@ devpccardlink(void)
|
|||
while ((pci = pcimatch(pci, 0, 0)) != nil) {
|
||||
ulong baddr;
|
||||
Cardbus *cb;
|
||||
int slot;
|
||||
uchar pin;
|
||||
|
||||
if(pci->ccrb != 6 || pci->ccru != 7)
|
||||
|
@ -555,8 +553,7 @@ devpccardlink(void)
|
|||
continue;
|
||||
|
||||
/* initialize this slot */
|
||||
slot = nslots++;
|
||||
cb = &cbslots[slot];
|
||||
cb = &cbslots[nslots];
|
||||
|
||||
cb->pci = pci;
|
||||
cb->variant = &variant[i];
|
||||
|
@ -635,27 +632,30 @@ devpccardlink(void)
|
|||
pcicfgw8(cb->pci, 0xD4, 0xCA);
|
||||
}
|
||||
|
||||
if (intl != 0xff && intl != pci->intl)
|
||||
intrenable(pci->intl, cbinterrupt, cb, pci->tbdf, "cardbus");
|
||||
intl = pci->intl;
|
||||
|
||||
if ((baddr = pcicfgr32(cb->pci, PciBAR0)) == 0) {
|
||||
int size = (pci->did == Ricoh_478_did)? 0x10000: 0x1000;
|
||||
|
||||
baddr = upaalloc(size, size);
|
||||
baddrva = vmap(baddr, size);
|
||||
baddr = upaalloc(-1, size, size);
|
||||
if(baddr == -1)
|
||||
continue;
|
||||
pcicfgw32(cb->pci, PciBAR0, baddr);
|
||||
cb->regs = (ulong *)baddrva;
|
||||
cb->regs = (ulong *)vmap(baddr, size);
|
||||
}
|
||||
else
|
||||
cb->regs = (ulong *)vmap(baddr, 4096);
|
||||
if(cb->regs == nil)
|
||||
continue;
|
||||
cb->state = SlotEmpty;
|
||||
|
||||
if (intl != 0xff && intl != pci->intl)
|
||||
intrenable(pci->intl, cbinterrupt, cb, pci->tbdf, "cardbus");
|
||||
|
||||
/* Don't really know what to do with this... */
|
||||
i82365probe(cb, LegacyAddr, LegacyAddr + 1);
|
||||
|
||||
print("#Y%ld: %s, %.8ulX intl %d\n", cb - cbslots,
|
||||
variant[i].name, baddr, pci->intl);
|
||||
|
||||
nslots++;
|
||||
}
|
||||
|
||||
if (nslots == 0){
|
||||
|
@ -815,16 +815,22 @@ configure(Cardbus *cb)
|
|||
if(iolen < 512)
|
||||
iolen = 512;
|
||||
iobase = ioreserve(~0, iolen, 0, "cardbus");
|
||||
pcicfgw32(cb->pci, PciCBIBR0, iobase);
|
||||
pcicfgw32(cb->pci, PciCBILR0, iobase + iolen-1);
|
||||
pcicfgw32(cb->pci, PciCBIBR1, 0);
|
||||
pcicfgw32(cb->pci, PciCBILR1, 0);
|
||||
if(iobase == -1)
|
||||
return;
|
||||
|
||||
rombase = memlen;
|
||||
memlen += romlen;
|
||||
if(memlen < 1*1024*1024)
|
||||
memlen = 1*1024*1024;
|
||||
membase = upaalloc(memlen, 4*1024*1024); /* TO DO: better alignment */
|
||||
membase = upaalloc(-1, memlen, 4*1024*1024); /* TO DO: better alignment */
|
||||
if(membase == -1)
|
||||
return;
|
||||
|
||||
pcicfgw32(cb->pci, PciCBIBR0, iobase);
|
||||
pcicfgw32(cb->pci, PciCBILR0, iobase + iolen-1);
|
||||
pcicfgw32(cb->pci, PciCBIBR1, 0);
|
||||
pcicfgw32(cb->pci, PciCBILR1, 0);
|
||||
|
||||
pcicfgw32(cb->pci, PciCBMBR0, membase);
|
||||
pcicfgw32(cb->pci, PciCBMLR0, membase + memlen-1);
|
||||
pcicfgw32(cb->pci, PciCBMBR1, 0);
|
||||
|
@ -1451,7 +1457,6 @@ isamap(Cardbus *cb, ulong offset, int len, int attr)
|
|||
if((we & bit))
|
||||
if(m->attr == attr)
|
||||
if(offset >= m->ca && e <= m->cea){
|
||||
|
||||
m->ref++;
|
||||
return m;
|
||||
}
|
||||
|
@ -1465,12 +1470,13 @@ isamap(Cardbus *cb, ulong offset, int len, int attr)
|
|||
|
||||
/* if isa space isn't big enough, free it and get more */
|
||||
if(m->len < len){
|
||||
if(m->isa){
|
||||
if(m->len){
|
||||
umbfree(m->isa, m->len);
|
||||
m->len = 0;
|
||||
}
|
||||
m->isa = PADDR(umbmalloc(0, len, Mgran));
|
||||
if(m->isa == 0){
|
||||
m->isa = umballoc(-1, len, Mgran);
|
||||
if(m->isa == -1){
|
||||
m->isa = 0;
|
||||
print("isamap: out of isa space\n");
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -88,7 +88,7 @@ reset8003(Ether* ether, uchar ea[Eaddrlen], uchar ic[8])
|
|||
*/
|
||||
if(memcmp(&ea[1], &ic[1], 5) == 0){
|
||||
memset(ic, 0, sizeof(ic));
|
||||
ic[Msr] = (((ulong)ether->mem)>>13) & 0x3F;
|
||||
ic[Msr] = (ether->mem>>13) & 0x3F;
|
||||
}
|
||||
else{
|
||||
/*
|
||||
|
@ -100,7 +100,7 @@ reset8003(Ether* ether, uchar ea[Eaddrlen], uchar ic[8])
|
|||
inb(port+Msr); /* wiggle bus */
|
||||
if(inb(port+Gp2) != 0xAA){
|
||||
memset(ic, 0, sizeof(ic));
|
||||
ic[Msr] = (((ulong)ether->mem)>>13) & 0x3F;
|
||||
ic[Msr] = (ether->mem>>13) & 0x3F;
|
||||
}
|
||||
else
|
||||
ether->irq = irq8003[((ic[Irr]>>5) & 0x3)|(ic[Icr] & 0x4)];
|
||||
|
@ -122,7 +122,7 @@ reset8003(Ether* ether, uchar ea[Eaddrlen], uchar ic[8])
|
|||
ctlr->width = 1;
|
||||
}
|
||||
|
||||
ether->mem = (ulong)KADDR((ic[Msr] & 0x3F)<<13);
|
||||
ether->mem = (ic[Msr] & 0x3F)<<13;
|
||||
if(ctlr->width == 2)
|
||||
ether->mem |= (ic[Laar] & 0x1F)<<19;
|
||||
else
|
||||
|
@ -163,7 +163,7 @@ reset8216(Ether* ether, uchar[8])
|
|||
irq = inb(port+0x0D);
|
||||
outb(port+Hcr, hcr);
|
||||
|
||||
ether->mem = (ulong)KADDR(0xC0000+((((addr>>2) & 0x30)|(addr & 0x0F))<<13));
|
||||
ether->mem = 0xC0000+((((addr>>2) & 0x30)|(addr & 0x0F))<<13);
|
||||
ether->size = 8192*(1<<((addr>>4) & 0x03));
|
||||
ether->irq = irq8216[((irq>>4) & 0x04)|((irq>>2) & 0x03)];
|
||||
|
||||
|
@ -262,9 +262,8 @@ reset(Ether* ether)
|
|||
}
|
||||
dp8390setea(ether);
|
||||
|
||||
if(umbrwmalloc(PADDR(ether->mem), ether->size, 0) == 0)
|
||||
print("ether8003: warning - 0x%luX unavailable\n",
|
||||
PADDR(ether->mem));
|
||||
if(umballoc(ether->mem, ether->size, 0) == -1)
|
||||
print("ether8003: warning - 0x%luX unavailable\n", ether->mem);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -377,7 +377,7 @@ receive(Ether* ether)
|
|||
for(curr = getcurr(ctlr); ctlr->nxtpkt != curr; curr = getcurr(ctlr)){
|
||||
data = ctlr->nxtpkt*Dp8390BufSz;
|
||||
if(ctlr->ram)
|
||||
memmove(&hdr, (void*)(ether->mem+data), sizeof(Hdr));
|
||||
memmove(&hdr, (uchar*)KADDR(ether->mem) + data, sizeof(Hdr));
|
||||
else
|
||||
_dp8390read(ctlr, &hdr, data, sizeof(Hdr));
|
||||
|
||||
|
@ -422,7 +422,7 @@ receive(Ether* ether)
|
|||
if((data+len) >= ctlr->pstop*Dp8390BufSz){
|
||||
count = ctlr->pstop*Dp8390BufSz - data;
|
||||
if(ctlr->ram)
|
||||
memmove(p, (void*)(ether->mem+data), count);
|
||||
memmove(p, (uchar*)KADDR(ether->mem) + data, count);
|
||||
else
|
||||
_dp8390read(ctlr, p, data, count);
|
||||
p += count;
|
||||
|
@ -431,7 +431,7 @@ receive(Ether* ether)
|
|||
}
|
||||
if(len){
|
||||
if(ctlr->ram)
|
||||
memmove(p, (void*)(ether->mem+data), len);
|
||||
memmove(p, (uchar*)KADDR(ether->mem) + data, len);
|
||||
else
|
||||
_dp8390read(ctlr, p, data, len);
|
||||
}
|
||||
|
@ -461,7 +461,6 @@ txstart(Ether* ether)
|
|||
int len;
|
||||
Dp8390 *ctlr;
|
||||
Block *bp;
|
||||
uchar minpkt[ETHERMINTU], *rp;
|
||||
|
||||
ctlr = ether->ctlr;
|
||||
|
||||
|
@ -476,23 +475,14 @@ txstart(Ether* ether)
|
|||
return;
|
||||
|
||||
/*
|
||||
* Make sure the packet is of minimum length;
|
||||
* copy it to the card's memory by the appropriate means;
|
||||
* start the transmission.
|
||||
*/
|
||||
len = BLEN(bp);
|
||||
rp = bp->rp;
|
||||
if(len < ETHERMINTU){
|
||||
rp = minpkt;
|
||||
memmove(rp, bp->rp, len);
|
||||
memset(rp+len, 0, ETHERMINTU-len);
|
||||
len = ETHERMINTU;
|
||||
}
|
||||
|
||||
if(ctlr->ram)
|
||||
memmove((void*)(ether->mem+ctlr->tstart*Dp8390BufSz), rp, len);
|
||||
memmove((uchar*)KADDR(ether->mem) + ctlr->tstart*Dp8390BufSz, bp->rp, len);
|
||||
else
|
||||
dp8390write(ctlr, ctlr->tstart*Dp8390BufSz, rp, len);
|
||||
dp8390write(ctlr, ctlr->tstart*Dp8390BufSz, bp->rp, len);
|
||||
freeb(bp);
|
||||
|
||||
regw(ctlr, Tbcr0, len & 0xFF);
|
||||
|
|
|
@ -105,7 +105,8 @@ void mathinit(void);
|
|||
void mb386(void);
|
||||
void mb586(void);
|
||||
void meminit(void);
|
||||
void memorysummary(void);
|
||||
void meminit0(void);
|
||||
void memreserve(uintptr, uintptr);
|
||||
void mfence(void);
|
||||
#define mmuflushtlb(pdb) putcr3(pdb)
|
||||
void mmuinit(void);
|
||||
|
@ -158,7 +159,8 @@ int (*_pcmspecial)(char *, ISAConf *);
|
|||
void pcmspecialclose(int);
|
||||
void (*_pcmspecialclose)(int);
|
||||
void pcmunmap(int, PCMmap*);
|
||||
int pdbmap(ulong*, ulong, ulong, int);
|
||||
void pmap(ulong, ulong, int);
|
||||
void punmap(ulong, int);
|
||||
void procrestore(Proc*);
|
||||
void procsave(Proc*);
|
||||
void procsetup(Proc*);
|
||||
|
@ -188,13 +190,10 @@ void trapinit(void);
|
|||
void trapinit0(void);
|
||||
int tas(void*);
|
||||
uvlong tscticks(uvlong*);
|
||||
ulong umbmalloc(ulong, int, int);
|
||||
void umbfree(ulong, int);
|
||||
ulong umbrwmalloc(ulong, int, int);
|
||||
void umbrwfree(ulong, int);
|
||||
ulong upaalloc(int, int);
|
||||
void upafree(ulong, int);
|
||||
void upareserve(ulong, int);
|
||||
ulong umballoc(ulong, ulong, ulong);
|
||||
void umbfree(ulong, ulong);
|
||||
ulong upaalloc(ulong, ulong, ulong);
|
||||
void upafree(ulong, ulong);
|
||||
void vectortable(void);
|
||||
void* vmap(ulong, int);
|
||||
int vmapsync(ulong);
|
||||
|
|
|
@ -34,11 +34,12 @@ main(void)
|
|||
trapinit0();
|
||||
i8253init();
|
||||
cpuidentify();
|
||||
meminit0();
|
||||
archinit();
|
||||
meminit();
|
||||
ramdiskinit();
|
||||
confinit();
|
||||
xinit();
|
||||
archinit();
|
||||
bootscreeninit();
|
||||
if(i8237alloc != nil)
|
||||
i8237alloc();
|
||||
|
|
|
@ -54,7 +54,7 @@
|
|||
#define USTKSIZE (16*1024*1024) /* size of user stack */
|
||||
|
||||
/*
|
||||
* Fundamental addresses - bottom 64kB saved for return to real mode
|
||||
* Fundamental addresses
|
||||
*/
|
||||
#define CONFADDR (KZERO+0x1200) /* info passed from boot loader */
|
||||
#define APBOOTSTRAP (KZERO+0x7000) /* AP bootstrap code (overlaps CONFADDR) */
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -35,6 +35,7 @@ PORT=\
|
|||
random.$O\
|
||||
rdb.$O\
|
||||
rebootcmd.$O\
|
||||
memmap.$O\
|
||||
segment.$O\
|
||||
syscallfmt.$O\
|
||||
sysfile.$O\
|
||||
|
|
|
@ -544,6 +544,7 @@ static Lock vmaplock;
|
|||
|
||||
static int findhole(ulong *a, int n, int count);
|
||||
static ulong vmapalloc(ulong size);
|
||||
static int pdbmap(ulong *, ulong, ulong, int);
|
||||
static void pdbunmap(ulong*, ulong, int);
|
||||
|
||||
/*
|
||||
|
@ -679,7 +680,7 @@ vunmap(void *v, int size)
|
|||
/*
|
||||
* Add kernel mappings for pa -> va for a section of size bytes.
|
||||
*/
|
||||
int
|
||||
static int
|
||||
pdbmap(ulong *pdb, ulong pa, ulong va, int size)
|
||||
{
|
||||
int pse;
|
||||
|
@ -749,6 +750,19 @@ pdbunmap(ulong *pdb, ulong va, int size)
|
|||
}
|
||||
}
|
||||
|
||||
void
|
||||
pmap(ulong pa, ulong va, int size)
|
||||
{
|
||||
pdbmap(MACHP(0)->pdb, pa, va, size);
|
||||
}
|
||||
|
||||
void
|
||||
punmap(ulong va, int size)
|
||||
{
|
||||
pdbunmap(MACHP(0)->pdb, va, size);
|
||||
mmuflushtlb(PADDR(m->pdb));
|
||||
}
|
||||
|
||||
/*
|
||||
* Handle a fault by bringing vmap up to date.
|
||||
* Only copy pdb entries and they never go away,
|
||||
|
|
|
@ -1084,7 +1084,7 @@ pcireservemem(void)
|
|||
for(p=pciroot; p; p=p->list)
|
||||
for(i=0; i<nelem(p->mem); i++)
|
||||
if((p->mem[i].bar&~4) != 0 && (p->mem[i].bar&1) == 0)
|
||||
upareserve(p->mem[i].bar&~0x0F, p->mem[i].size);
|
||||
upaalloc(p->mem[i].bar&~0x0F, p->mem[i].size, 0);
|
||||
}
|
||||
|
||||
static int
|
||||
|
|
|
@ -94,6 +94,7 @@ int
|
|||
screenaperture(int size, int align)
|
||||
{
|
||||
VGAscr *scr;
|
||||
ulong pa;
|
||||
|
||||
scr = &vgascreen[0];
|
||||
|
||||
|
@ -113,10 +114,11 @@ screenaperture(int size, int align)
|
|||
* The driver will tell the card to use it.
|
||||
*/
|
||||
size = PGROUND(size);
|
||||
scr->paddr = upaalloc(size, align);
|
||||
if(scr->paddr == 0)
|
||||
pa = upaalloc(-1, size, align);
|
||||
if(pa == -1)
|
||||
return -1;
|
||||
scr->vaddr = vmap(scr->paddr, size);
|
||||
scr->paddr = pa;
|
||||
scr->vaddr = vmap(pa, size);
|
||||
if(scr->vaddr == nil)
|
||||
return -1;
|
||||
scr->apsize = size;
|
||||
|
@ -482,8 +484,8 @@ vgalinearaddr0(VGAscr *scr, ulong paddr, int size)
|
|||
if(nsize > 64*MB)
|
||||
nsize = 64*MB;
|
||||
scr->vaddr = vmap(npaddr, nsize);
|
||||
if(scr->vaddr == 0)
|
||||
return "cannot allocate vga frame buffer";
|
||||
if(scr->vaddr == nil)
|
||||
return "cannot map vga frame buffer";
|
||||
|
||||
patwc(scr->vaddr, nsize);
|
||||
|
||||
|
@ -576,6 +578,7 @@ bootmapfb(VGAscr *scr, ulong pa, ulong sz)
|
|||
}
|
||||
}
|
||||
}
|
||||
upaalloc(pa, sz, 0);
|
||||
return vgalinearaddr0(scr, pa, sz);
|
||||
}
|
||||
|
||||
|
|
|
@ -103,7 +103,8 @@ void mathinit(void);
|
|||
void mb386(void);
|
||||
void mb586(void);
|
||||
void meminit(void);
|
||||
void memorysummary(void);
|
||||
void meminit0(void);
|
||||
void memreserve(uintptr, uintptr);
|
||||
void mfence(void);
|
||||
#define mmuflushtlb() putcr3(getcr3())
|
||||
void mmuinit(void);
|
||||
|
@ -157,7 +158,8 @@ int (*_pcmspecial)(char *, ISAConf *);
|
|||
void pcmspecialclose(int);
|
||||
void (*_pcmspecialclose)(int);
|
||||
void pcmunmap(int, PCMmap*);
|
||||
void pmap(uintptr *, uintptr, uintptr, vlong);
|
||||
void pmap(uintptr, uintptr, vlong);
|
||||
void punmap(uintptr, vlong);
|
||||
void preallocpages(void);
|
||||
void procrestore(Proc*);
|
||||
void procsave(Proc*);
|
||||
|
@ -187,13 +189,10 @@ void trapinit(void);
|
|||
void trapinit0(void);
|
||||
int tas(void*);
|
||||
uvlong tscticks(uvlong*);
|
||||
uintptr umbmalloc(uintptr, int, int);
|
||||
void umbfree(uintptr, int);
|
||||
uintptr umbrwmalloc(uintptr, int, int);
|
||||
void umbrwfree(uintptr, int);
|
||||
uintptr upaalloc(int, int);
|
||||
void upafree(uintptr, int);
|
||||
void upareserve(uintptr, int);
|
||||
ulong umballoc(ulong, ulong, ulong);
|
||||
void umbfree(ulong, ulong);
|
||||
ulong upaalloc(ulong, ulong, ulong);
|
||||
void upafree(ulong, ulong);
|
||||
void vectortable(void);
|
||||
void vmxprocrestore(Proc *);
|
||||
void vmxshutdown(void);
|
||||
|
|
|
@ -184,11 +184,12 @@ main(void)
|
|||
trapinit0();
|
||||
i8253init();
|
||||
cpuidentify();
|
||||
meminit0();
|
||||
archinit();
|
||||
meminit();
|
||||
ramdiskinit();
|
||||
confinit();
|
||||
xinit();
|
||||
archinit();
|
||||
bootscreeninit();
|
||||
if(i8237alloc != nil)
|
||||
i8237alloc();
|
||||
|
|
|
@ -60,7 +60,7 @@
|
|||
#define KMAPSIZE (2*MiB)
|
||||
|
||||
/*
|
||||
* Fundamental addresses - bottom 64kB saved for return to real mode
|
||||
* Fundamental addresses
|
||||
*/
|
||||
#define CONFADDR (KZERO+0x1200ull) /* info passed from boot loader */
|
||||
#define APBOOTSTRAP (KZERO+0x7000ull) /* AP bootstrap code */
|
||||
|
|
|
@ -1,802 +0,0 @@
|
|||
/*
|
||||
* Size memory and create the kernel page-tables on the fly while doing so.
|
||||
* Called from main(), this code should only be run by the bootstrap processor.
|
||||
*
|
||||
* MemMin is what the bootstrap code in l.s has already mapped;
|
||||
*/
|
||||
#include "u.h"
|
||||
#include "../port/lib.h"
|
||||
#include "mem.h"
|
||||
#include "dat.h"
|
||||
#include "fns.h"
|
||||
#include "io.h"
|
||||
#include "ureg.h"
|
||||
|
||||
u32int MemMin; /* set by l.s */
|
||||
|
||||
#define MEMDEBUG 0
|
||||
|
||||
enum {
|
||||
MemUPA = 0, /* unbacked physical address */
|
||||
MemRAM = 1, /* physical memory */
|
||||
MemUMB = 2, /* upper memory block (<16MB) */
|
||||
MemACPI = 3, /* ACPI tables */
|
||||
MemReserved = 4,
|
||||
NMemType = 5,
|
||||
|
||||
KB = 1024,
|
||||
};
|
||||
|
||||
typedef struct Map Map;
|
||||
struct Map {
|
||||
uintptr size;
|
||||
uintptr addr;
|
||||
};
|
||||
|
||||
typedef struct RMap RMap;
|
||||
struct RMap {
|
||||
char* name;
|
||||
Map* map;
|
||||
Map* mapend;
|
||||
|
||||
Lock;
|
||||
};
|
||||
|
||||
/*
|
||||
* Memory allocation tracking.
|
||||
*/
|
||||
static Map mapupa[64];
|
||||
static RMap rmapupa = {
|
||||
"unallocated unbacked physical memory",
|
||||
mapupa,
|
||||
&mapupa[nelem(mapupa)-1],
|
||||
};
|
||||
|
||||
static Map mapram[16];
|
||||
static RMap rmapram = {
|
||||
"physical memory",
|
||||
mapram,
|
||||
&mapram[nelem(mapram)-1],
|
||||
};
|
||||
|
||||
static Map mapumb[64];
|
||||
static RMap rmapumb = {
|
||||
"upper memory block",
|
||||
mapumb,
|
||||
&mapumb[nelem(mapumb)-1],
|
||||
};
|
||||
|
||||
static Map mapumbrw[16];
|
||||
static RMap rmapumbrw = {
|
||||
"UMB device memory",
|
||||
mapumbrw,
|
||||
&mapumbrw[nelem(mapumbrw)-1],
|
||||
};
|
||||
|
||||
static Map mapacpi[16];
|
||||
static RMap rmapacpi = {
|
||||
"ACPI tables",
|
||||
mapacpi,
|
||||
&mapacpi[nelem(mapacpi)-1],
|
||||
};
|
||||
|
||||
void
|
||||
mapprint(RMap *rmap)
|
||||
{
|
||||
Map *mp;
|
||||
|
||||
print("%s\n", rmap->name);
|
||||
for(mp = rmap->map; mp->size; mp++)
|
||||
print("\t%#p %#p (%#p)\n", mp->addr, mp->addr+mp->size, mp->size);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
memdebug(void)
|
||||
{
|
||||
ulong maxpa, maxpa1, maxpa2;
|
||||
|
||||
maxpa = (nvramread(0x18)<<8)|nvramread(0x17);
|
||||
maxpa1 = (nvramread(0x31)<<8)|nvramread(0x30);
|
||||
maxpa2 = (nvramread(0x16)<<8)|nvramread(0x15);
|
||||
print("maxpa = %luX -> %luX, maxpa1 = %luX maxpa2 = %luX\n",
|
||||
maxpa, MB+maxpa*KB, maxpa1, maxpa2);
|
||||
|
||||
mapprint(&rmapram);
|
||||
mapprint(&rmapumb);
|
||||
mapprint(&rmapumbrw);
|
||||
mapprint(&rmapupa);
|
||||
mapprint(&rmapacpi);
|
||||
}
|
||||
|
||||
static void
|
||||
mapfree(RMap* rmap, uintptr addr, uintptr size)
|
||||
{
|
||||
Map *mp;
|
||||
uintptr t;
|
||||
|
||||
if(size <= 0)
|
||||
return;
|
||||
|
||||
lock(rmap);
|
||||
for(mp = rmap->map; mp->addr <= addr && mp->size; mp++)
|
||||
;
|
||||
|
||||
if(mp > rmap->map && (mp-1)->addr+(mp-1)->size == addr){
|
||||
(mp-1)->size += size;
|
||||
if(addr+size == mp->addr){
|
||||
(mp-1)->size += mp->size;
|
||||
while(mp->size){
|
||||
mp++;
|
||||
(mp-1)->addr = mp->addr;
|
||||
(mp-1)->size = mp->size;
|
||||
}
|
||||
}
|
||||
}
|
||||
else{
|
||||
if(addr+size == mp->addr && mp->size){
|
||||
mp->addr -= size;
|
||||
mp->size += size;
|
||||
}
|
||||
else do{
|
||||
if(mp >= rmap->mapend){
|
||||
print("mapfree: %s: losing %#p, %#p\n",
|
||||
rmap->name, addr, size);
|
||||
break;
|
||||
}
|
||||
t = mp->addr;
|
||||
mp->addr = addr;
|
||||
addr = t;
|
||||
t = mp->size;
|
||||
mp->size = size;
|
||||
mp++;
|
||||
}while(size = t);
|
||||
}
|
||||
unlock(rmap);
|
||||
}
|
||||
|
||||
static uintptr
|
||||
mapalloc(RMap* rmap, uintptr addr, int size, int align)
|
||||
{
|
||||
Map *mp;
|
||||
uintptr maddr, oaddr;
|
||||
|
||||
lock(rmap);
|
||||
for(mp = rmap->map; mp->size; mp++){
|
||||
maddr = mp->addr;
|
||||
|
||||
if(addr){
|
||||
/*
|
||||
* A specific address range has been given:
|
||||
* if the current map entry is greater then
|
||||
* the address is not in the map;
|
||||
* if the current map entry does not overlap
|
||||
* the beginning of the requested range then
|
||||
* continue on to the next map entry;
|
||||
* if the current map entry does not entirely
|
||||
* contain the requested range then the range
|
||||
* is not in the map.
|
||||
*/
|
||||
if(maddr > addr)
|
||||
break;
|
||||
if(mp->size < addr - maddr) /* maddr+mp->size < addr, but no overflow */
|
||||
continue;
|
||||
if(addr - maddr > mp->size - size) /* addr+size > maddr+mp->size, but no overflow */
|
||||
break;
|
||||
maddr = addr;
|
||||
}
|
||||
|
||||
if(align > 0)
|
||||
maddr = ((maddr+align-1)/align)*align;
|
||||
if(mp->addr+mp->size-maddr < size)
|
||||
continue;
|
||||
|
||||
oaddr = mp->addr;
|
||||
mp->addr = maddr+size;
|
||||
mp->size -= maddr-oaddr+size;
|
||||
if(mp->size == 0){
|
||||
do{
|
||||
mp++;
|
||||
(mp-1)->addr = mp->addr;
|
||||
}while((mp-1)->size = mp->size);
|
||||
}
|
||||
|
||||
unlock(rmap);
|
||||
if(oaddr != maddr)
|
||||
mapfree(rmap, oaddr, maddr-oaddr);
|
||||
|
||||
return maddr;
|
||||
}
|
||||
unlock(rmap);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Allocate from the ram map directly to make page tables.
|
||||
* Called by mmuwalk during e820scan.
|
||||
*/
|
||||
void*
|
||||
rampage(void)
|
||||
{
|
||||
uintptr m;
|
||||
|
||||
if(conf.mem[0].npage != 0)
|
||||
return xspanalloc(BY2PG, BY2PG, 0);
|
||||
m = mapalloc(&rmapram, 0, BY2PG, BY2PG);
|
||||
if(m == 0)
|
||||
return nil;
|
||||
return KADDR(m);
|
||||
}
|
||||
|
||||
static void
|
||||
umbexclude(void)
|
||||
{
|
||||
int size;
|
||||
ulong addr;
|
||||
char *op, *p, *rptr;
|
||||
|
||||
if((p = getconf("umbexclude")) == nil)
|
||||
return;
|
||||
|
||||
while(p && *p != '\0' && *p != '\n'){
|
||||
op = p;
|
||||
addr = strtoul(p, &rptr, 0);
|
||||
if(rptr == nil || rptr == p || *rptr != '-'){
|
||||
print("umbexclude: invalid argument <%s>\n", op);
|
||||
break;
|
||||
}
|
||||
p = rptr+1;
|
||||
|
||||
size = strtoul(p, &rptr, 0) - addr + 1;
|
||||
if(size <= 0){
|
||||
print("umbexclude: bad range <%s>\n", op);
|
||||
break;
|
||||
}
|
||||
if(rptr != nil && *rptr == ',')
|
||||
*rptr++ = '\0';
|
||||
p = rptr;
|
||||
|
||||
mapalloc(&rmapumb, addr, size, 0);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
umbscan(void)
|
||||
{
|
||||
uchar *p;
|
||||
|
||||
/*
|
||||
* Scan the Upper Memory Blocks (0xA0000->0xF0000) for pieces
|
||||
* which aren't used; they can be used later for devices which
|
||||
* want to allocate some virtual address space.
|
||||
* Check for two things:
|
||||
* 1) device BIOS ROM. This should start with a two-byte header
|
||||
* of 0x55 0xAA, followed by a byte giving the size of the ROM
|
||||
* in 512-byte chunks. These ROM's must start on a 2KB boundary.
|
||||
* 2) device memory. This is read-write.
|
||||
* There are some assumptions: there's VGA memory at 0xA0000 and
|
||||
* the VGA BIOS ROM is at 0xC0000. Also, if there's no ROM signature
|
||||
* at 0xE0000 then the whole 64KB up to 0xF0000 is theoretically up
|
||||
* for grabs; check anyway.
|
||||
*/
|
||||
p = KADDR(0xD0000);
|
||||
while(p < (uchar*)KADDR(0xE0000)){
|
||||
/*
|
||||
* Test for 0x55 0xAA before poking obtrusively,
|
||||
* some machines (e.g. Thinkpad X20) seem to map
|
||||
* something dynamic here (cardbus?) causing weird
|
||||
* problems if it is changed.
|
||||
*/
|
||||
if(p[0] == 0x55 && p[1] == 0xAA){
|
||||
p += p[2]*512;
|
||||
continue;
|
||||
}
|
||||
|
||||
p[0] = 0xCC;
|
||||
p[2*KB-1] = 0xCC;
|
||||
if(p[0] != 0xCC || p[2*KB-1] != 0xCC){
|
||||
p[0] = 0x55;
|
||||
p[1] = 0xAA;
|
||||
p[2] = 4;
|
||||
if(p[0] == 0x55 && p[1] == 0xAA){
|
||||
p += p[2]*512;
|
||||
continue;
|
||||
}
|
||||
if(p[0] == 0xFF && p[1] == 0xFF)
|
||||
mapfree(&rmapumb, PADDR(p), 2*KB);
|
||||
}
|
||||
else
|
||||
mapfree(&rmapumbrw, PADDR(p), 2*KB);
|
||||
p += 2*KB;
|
||||
}
|
||||
|
||||
p = KADDR(0xE0000);
|
||||
if(p[0] != 0x55 || p[1] != 0xAA){
|
||||
p[0] = 0xCC;
|
||||
p[64*KB-1] = 0xCC;
|
||||
if(p[0] != 0xCC && p[64*KB-1] != 0xCC)
|
||||
mapfree(&rmapumb, PADDR(p), 64*KB);
|
||||
}
|
||||
|
||||
umbexclude();
|
||||
}
|
||||
|
||||
int
|
||||
checksum(void *v, int n)
|
||||
{
|
||||
uchar *p, s;
|
||||
|
||||
s = 0;
|
||||
p = v;
|
||||
while(n-- > 0)
|
||||
s += *p++;
|
||||
return s;
|
||||
}
|
||||
|
||||
static void*
|
||||
sigscan(uchar *addr, int len, char *sig, int size, int step)
|
||||
{
|
||||
uchar *e, *p;
|
||||
int sl;
|
||||
|
||||
sl = strlen(sig);
|
||||
e = addr+len-(size > sl ? size : sl);
|
||||
for(p = addr; p <= e; p += step){
|
||||
if(memcmp(p, sig, sl) != 0)
|
||||
continue;
|
||||
if(size && checksum(p, size) != 0)
|
||||
continue;
|
||||
return p;
|
||||
}
|
||||
return nil;
|
||||
}
|
||||
|
||||
static uintptr
|
||||
convmemsize(void)
|
||||
{
|
||||
uintptr top;
|
||||
uchar *bda;
|
||||
|
||||
bda = KADDR(0x400);
|
||||
top = ((bda[0x14]<<8) | bda[0x13])*KB;
|
||||
|
||||
if(top < 64*KB || top > 640*KB)
|
||||
top = 640*KB; /* sanity */
|
||||
|
||||
/* reserved for bios tables (EBDA) */
|
||||
top -= 1*KB;
|
||||
|
||||
return top;
|
||||
}
|
||||
|
||||
void*
|
||||
sigsearch(char* signature, int size)
|
||||
{
|
||||
uintptr p;
|
||||
uchar *bda;
|
||||
void *r;
|
||||
|
||||
/*
|
||||
* Search for the data structure:
|
||||
* 1) within the first KiB of the Extended BIOS Data Area (EBDA), or
|
||||
* 2) within the last KiB of system base memory if the EBDA segment
|
||||
* is undefined, or
|
||||
* 3) within the BIOS ROM address space between 0xf0000 and 0xfffff
|
||||
* (but will actually check 0xe0000 to 0xfffff).
|
||||
*/
|
||||
bda = KADDR(0x400);
|
||||
if(memcmp(KADDR(0xfffd9), "EISA", 4) == 0){
|
||||
if((p = (bda[0x0f]<<8)|bda[0x0e]) != 0){
|
||||
if((r = sigscan(KADDR(p<<4), 1024, signature, size, 16)) != nil)
|
||||
return r;
|
||||
}
|
||||
}
|
||||
if((r = sigscan(KADDR(convmemsize()), 1024, signature, size, 16)) != nil)
|
||||
return r;
|
||||
|
||||
/* hack for virtualbox: look in KiB below 0xa0000 */
|
||||
if((r = sigscan(KADDR(0xa0000-1024), 1024, signature, size, 16)) != nil)
|
||||
return r;
|
||||
|
||||
return sigscan(KADDR(0xe0000), 0x20000, signature, size, 16);
|
||||
}
|
||||
|
||||
void*
|
||||
rsdsearch(void)
|
||||
{
|
||||
static char signature[] = "RSD PTR ";
|
||||
uchar *v, *p;
|
||||
Map *m;
|
||||
|
||||
if((p = sigsearch(signature, 36)) != nil)
|
||||
return p;
|
||||
if((p = sigsearch(signature, 20)) != nil)
|
||||
return p;
|
||||
for(m = rmapacpi.map; m < rmapacpi.mapend && m->size; m++){
|
||||
if(m->size > 0x7FFFFFFF)
|
||||
continue;
|
||||
if((v = vmap(m->addr, m->size)) != nil){
|
||||
p = sigscan(v, m->size, signature, 36, 4);
|
||||
if(p == nil)
|
||||
p = sigscan(v, m->size, signature, 20, 4);
|
||||
vunmap(v, m->size);
|
||||
if(p != nil)
|
||||
return vmap(m->addr + (p - v), 64);
|
||||
}
|
||||
}
|
||||
return nil;
|
||||
}
|
||||
|
||||
static void
|
||||
lowraminit(void)
|
||||
{
|
||||
uintptr pa, x;
|
||||
|
||||
/*
|
||||
* Initialise the memory bank information for conventional memory
|
||||
* (i.e. less than 640KB). The base is the first location after the
|
||||
* bootstrap processor MMU information and the limit is obtained from
|
||||
* the BIOS data area.
|
||||
*/
|
||||
x = PADDR(CPU0END);
|
||||
pa = convmemsize();
|
||||
if(x < pa){
|
||||
mapfree(&rmapram, x, pa-x);
|
||||
memset(KADDR(x), 0, pa-x); /* keep us honest */
|
||||
}
|
||||
|
||||
x = PADDR(PGROUND((uintptr)end));
|
||||
pa = MemMin;
|
||||
if(x > pa)
|
||||
panic("kernel too big");
|
||||
mapfree(&rmapram, x, pa-x);
|
||||
memset(KADDR(x), 0, pa-x); /* keep us honest */
|
||||
}
|
||||
|
||||
static void
|
||||
map(uintptr base, uintptr len, int type)
|
||||
{
|
||||
uintptr n, flags, maxkpa;
|
||||
|
||||
/*
|
||||
* Split any call crossing MemMin to make below simpler.
|
||||
*/
|
||||
if(base < MemMin && len > MemMin-base){
|
||||
n = MemMin - base;
|
||||
map(base, n, type);
|
||||
map(MemMin, len-n, type);
|
||||
}
|
||||
|
||||
/*
|
||||
* Let umbscan hash out the low MemMin.
|
||||
*/
|
||||
if(base < MemMin)
|
||||
return;
|
||||
|
||||
/*
|
||||
* Any non-memory below 16*MB is used as upper mem blocks.
|
||||
*/
|
||||
if(type == MemUPA && base < 16*MB && len > 16*MB-base){
|
||||
map(base, 16*MB-base, MemUMB);
|
||||
map(16*MB, len-(16*MB-base), MemUPA);
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* Memory below CPU0END is reserved for the kernel
|
||||
* and already mapped.
|
||||
*/
|
||||
if(base < PADDR(CPU0END)){
|
||||
n = PADDR(CPU0END) - base;
|
||||
if(len <= n)
|
||||
return;
|
||||
map(PADDR(CPU0END), len-n, type);
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* Memory between KTZERO and end is the kernel itself
|
||||
* and is already mapped.
|
||||
*/
|
||||
if(base < PADDR(KTZERO) && len > PADDR(KTZERO)-base){
|
||||
map(base, PADDR(KTZERO)-base, type);
|
||||
return;
|
||||
}
|
||||
if(PADDR(KTZERO) < base && base < PADDR(PGROUND((uintptr)end))){
|
||||
n = PADDR(PGROUND((uintptr)end));
|
||||
if(len <= n)
|
||||
return;
|
||||
map(PADDR(PGROUND((uintptr)end)), len-n, type);
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* Now we have a simple case.
|
||||
*/
|
||||
switch(type){
|
||||
case MemRAM:
|
||||
mapfree(&rmapram, base, len);
|
||||
flags = PTEWRITE|PTENOEXEC|PTEVALID;
|
||||
break;
|
||||
case MemUMB:
|
||||
mapfree(&rmapumb, base, len);
|
||||
flags = PTEWRITE|PTEUNCACHED|PTENOEXEC|PTEVALID;
|
||||
break;
|
||||
case MemUPA:
|
||||
mapfree(&rmapupa, base, len);
|
||||
flags = 0;
|
||||
break;
|
||||
case MemACPI:
|
||||
mapfree(&rmapacpi, base, len);
|
||||
flags = 0;
|
||||
break;
|
||||
case MemReserved:
|
||||
default:
|
||||
flags = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
if(flags){
|
||||
maxkpa = -KZERO;
|
||||
if(base >= maxkpa)
|
||||
return;
|
||||
if(len > maxkpa-base)
|
||||
len = maxkpa - base;
|
||||
pmap(m->pml4, base|flags, base+KZERO, len);
|
||||
}
|
||||
}
|
||||
|
||||
typedef struct Emap Emap;
|
||||
struct Emap
|
||||
{
|
||||
int type;
|
||||
uvlong base;
|
||||
uvlong top;
|
||||
};
|
||||
static Emap emap[128];
|
||||
static int nemap;
|
||||
|
||||
static int
|
||||
emapcmp(const void *va, const void *vb)
|
||||
{
|
||||
Emap *a, *b;
|
||||
|
||||
a = (Emap*)va;
|
||||
b = (Emap*)vb;
|
||||
if(a->top < b->top)
|
||||
return -1;
|
||||
if(a->top > b->top)
|
||||
return 1;
|
||||
if(a->base < b->base)
|
||||
return -1;
|
||||
if(a->base > b->base)
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
e820clean(void)
|
||||
{
|
||||
Emap *e;
|
||||
int i, j;
|
||||
|
||||
qsort(emap, nemap, sizeof emap[0], emapcmp);
|
||||
for(i=j=0; i<nemap; i++){
|
||||
e = &emap[i];
|
||||
|
||||
/* merge adjacent entries of the same type */
|
||||
if(i+1 < nemap && e[0].top == e[1].base && e[0].type == e[1].type){
|
||||
e[1].base = e[0].base;
|
||||
continue;
|
||||
}
|
||||
|
||||
memmove(&emap[j++], e, sizeof *e);
|
||||
}
|
||||
nemap = j;
|
||||
}
|
||||
|
||||
static int
|
||||
e820scan(void)
|
||||
{
|
||||
uintptr base, len, last;
|
||||
Emap *e;
|
||||
char *s;
|
||||
int i;
|
||||
|
||||
/* passed by bootloader */
|
||||
if((s = getconf("*e820")) == nil)
|
||||
if((s = getconf("e820")) == nil)
|
||||
return -1;
|
||||
nemap = 0;
|
||||
while(nemap < nelem(emap)){
|
||||
while(*s == ' ')
|
||||
s++;
|
||||
if(*s == 0)
|
||||
break;
|
||||
e = emap + nemap;
|
||||
e->type = 1;
|
||||
if(s[1] == ' '){ /* new format */
|
||||
e->type = s[0] - '0';
|
||||
s += 2;
|
||||
}
|
||||
e->base = strtoull(s, &s, 16);
|
||||
if(*s != ' ')
|
||||
break;
|
||||
e->top = strtoull(s, &s, 16);
|
||||
if(*s != ' ' && *s != 0)
|
||||
break;
|
||||
if(e->base >= e->top)
|
||||
continue;
|
||||
if(++nemap == nelem(emap))
|
||||
e820clean();
|
||||
}
|
||||
e820clean();
|
||||
if(nemap == 0)
|
||||
return -1;
|
||||
last = 0;
|
||||
for(i=0; i<nemap; i++){
|
||||
e = &emap[i];
|
||||
if(e->top <= last)
|
||||
continue;
|
||||
if(e->base < last)
|
||||
base = last;
|
||||
else
|
||||
base = e->base;
|
||||
len = e->top - base;
|
||||
/*
|
||||
* If the map skips addresses, mark them available.
|
||||
*/
|
||||
if(last < base)
|
||||
map(last, base-last, MemUPA);
|
||||
switch(e->type){
|
||||
case 1:
|
||||
map(base, len, MemRAM);
|
||||
break;
|
||||
case 3:
|
||||
map(base, len, MemACPI);
|
||||
break;
|
||||
default:
|
||||
map(base, len, MemReserved);
|
||||
}
|
||||
last = base + len;
|
||||
if(last == 0)
|
||||
break;
|
||||
}
|
||||
if(last != 0)
|
||||
map(last, -last, MemUPA);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
meminit(void)
|
||||
{
|
||||
int i;
|
||||
Map *mp;
|
||||
Confmem *cm;
|
||||
uintptr lost;
|
||||
|
||||
umbscan();
|
||||
lowraminit();
|
||||
e820scan();
|
||||
|
||||
/*
|
||||
* Set the conf entries describing banks of allocatable memory.
|
||||
*/
|
||||
for(i=0; i<nelem(mapram) && i<nelem(conf.mem); i++){
|
||||
mp = &rmapram.map[i];
|
||||
cm = &conf.mem[i];
|
||||
cm->base = mp->addr;
|
||||
cm->npage = mp->size/BY2PG;
|
||||
}
|
||||
|
||||
lost = 0;
|
||||
for(; i<nelem(mapram); i++)
|
||||
lost += rmapram.map[i].size;
|
||||
if(lost)
|
||||
print("meminit - lost %llud bytes\n", lost);
|
||||
|
||||
if(MEMDEBUG)
|
||||
memdebug();
|
||||
}
|
||||
|
||||
/*
|
||||
* Allocate memory from the upper memory blocks.
|
||||
*/
|
||||
uintptr
|
||||
umbmalloc(uintptr addr, int size, int align)
|
||||
{
|
||||
uintptr a;
|
||||
|
||||
if(a = mapalloc(&rmapumb, addr, size, align))
|
||||
return (uintptr)KADDR(a);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
umbfree(uintptr addr, int size)
|
||||
{
|
||||
mapfree(&rmapumb, PADDR(addr), size);
|
||||
}
|
||||
|
||||
uintptr
|
||||
umbrwmalloc(uintptr addr, int size, int align)
|
||||
{
|
||||
uintptr a;
|
||||
uchar *p;
|
||||
|
||||
if(a = mapalloc(&rmapumbrw, addr, size, align))
|
||||
return (uintptr)KADDR(a);
|
||||
|
||||
/*
|
||||
* Perhaps the memory wasn't visible before
|
||||
* the interface is initialised, so try again.
|
||||
*/
|
||||
if((a = umbmalloc(addr, size, align)) == 0)
|
||||
return 0;
|
||||
p = (uchar*)a;
|
||||
p[0] = 0xCC;
|
||||
p[size-1] = 0xCC;
|
||||
if(p[0] == 0xCC && p[size-1] == 0xCC)
|
||||
return a;
|
||||
umbfree(a, size);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
umbrwfree(uintptr addr, int size)
|
||||
{
|
||||
mapfree(&rmapumbrw, PADDR(addr), size);
|
||||
}
|
||||
|
||||
/*
|
||||
* Give out otherwise-unused physical address space
|
||||
* for use in configuring devices. Note that upaalloc
|
||||
* does not map the physical address into virtual memory.
|
||||
* Call vmap to do that.
|
||||
*/
|
||||
uintptr
|
||||
upaalloc(int size, int align)
|
||||
{
|
||||
uintptr a;
|
||||
|
||||
a = mapalloc(&rmapupa, 0, size, align);
|
||||
if(a == 0){
|
||||
print("out of physical address space allocating %d\n", size);
|
||||
mapprint(&rmapupa);
|
||||
}
|
||||
return a;
|
||||
}
|
||||
|
||||
void
|
||||
upafree(uintptr pa, int size)
|
||||
{
|
||||
mapfree(&rmapupa, pa, size);
|
||||
}
|
||||
|
||||
void
|
||||
upareserve(uintptr pa, int size)
|
||||
{
|
||||
uintptr a;
|
||||
|
||||
a = mapalloc(&rmapupa, pa, size, 0);
|
||||
if(a != pa){
|
||||
/*
|
||||
* This can happen when we're using the E820
|
||||
* map, which might have already reserved some
|
||||
* of the regions claimed by the pci devices.
|
||||
*/
|
||||
// print("upareserve: cannot reserve pa=%#p size=%d\n", pa, size);
|
||||
if(a != 0)
|
||||
mapfree(&rmapupa, a, size);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
memorysummary(void)
|
||||
{
|
||||
memdebug();
|
||||
}
|
||||
|
|
@ -22,6 +22,7 @@ PORT=\
|
|||
dev.$O\
|
||||
edf.$O\
|
||||
fault.$O\
|
||||
memmap.$O\
|
||||
page.$O\
|
||||
parse.$O\
|
||||
pgrp.$O\
|
||||
|
|
|
@ -344,7 +344,7 @@ kernelro(void)
|
|||
}
|
||||
|
||||
void
|
||||
pmap(uintptr *pml4, uintptr pa, uintptr va, vlong size)
|
||||
pmap(uintptr pa, uintptr va, vlong size)
|
||||
{
|
||||
uintptr *pte, *ptee, flags;
|
||||
int z, l;
|
||||
|
@ -361,9 +361,9 @@ pmap(uintptr *pml4, uintptr pa, uintptr va, vlong size)
|
|||
flags |= PTESIZE;
|
||||
l = (flags & PTESIZE) != 0;
|
||||
z = PGLSZ(l);
|
||||
pte = mmuwalk(pml4, va, l, 1);
|
||||
if(pte == 0){
|
||||
pte = mmuwalk(pml4, va, ++l, 0);
|
||||
pte = mmuwalk(m->pml4, va, l, 1);
|
||||
if(pte == nil){
|
||||
pte = mmuwalk(m->pml4, va, ++l, 0);
|
||||
if(pte && (*pte & PTESIZE)){
|
||||
flags |= PTESIZE;
|
||||
z = va & (PGLSZ(l)-1);
|
||||
|
@ -384,6 +384,29 @@ pmap(uintptr *pml4, uintptr pa, uintptr va, vlong size)
|
|||
}
|
||||
}
|
||||
|
||||
void
|
||||
punmap(uintptr va, vlong size)
|
||||
{
|
||||
uintptr *pte;
|
||||
int l;
|
||||
|
||||
va = PPN(va);
|
||||
while(size > 0){
|
||||
if((va % PGLSZ(1)) != 0 || size < PGLSZ(1))
|
||||
ptesplit(m->pml4, va);
|
||||
l = 0;
|
||||
pte = mmuwalk(m->pml4, va, l, 0);
|
||||
if(pte == nil && (va % PGLSZ(1)) == 0 && size >= PGLSZ(1))
|
||||
pte = mmuwalk(m->pml4, va, ++l, 0);
|
||||
if(pte){
|
||||
*pte = 0;
|
||||
invlpg(va);
|
||||
}
|
||||
va += PGLSZ(l);
|
||||
size -= PGLSZ(l);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
mmuzap(void)
|
||||
{
|
||||
|
@ -584,7 +607,7 @@ vmap(uintptr pa, int size)
|
|||
pa -= o;
|
||||
va -= o;
|
||||
size += o;
|
||||
pmap(m->pml4, pa | PTEUNCACHED|PTEWRITE|PTENOEXEC|PTEVALID, va, size);
|
||||
pmap(pa | PTEUNCACHED|PTEWRITE|PTENOEXEC|PTEVALID, va, size);
|
||||
return (void*)(va+o);
|
||||
}
|
||||
|
||||
|
@ -667,7 +690,7 @@ preallocpages(void)
|
|||
pm->npage = (top - pm->base)/BY2PG;
|
||||
|
||||
va = base + VMAP;
|
||||
pmap(m->pml4, base | PTEGLOBAL|PTEWRITE|PTENOEXEC|PTEVALID, va, psize);
|
||||
pmap(base | PTEGLOBAL|PTEWRITE|PTENOEXEC|PTEVALID, va, psize);
|
||||
|
||||
palloc.pages = (void*)(va + tsize);
|
||||
|
||||
|
|
271
sys/src/9/port/memmap.c
Normal file
271
sys/src/9/port/memmap.c
Normal file
|
@ -0,0 +1,271 @@
|
|||
#include "u.h"
|
||||
#include "../port/lib.h"
|
||||
#include "mem.h"
|
||||
#include "dat.h"
|
||||
#include "fns.h"
|
||||
|
||||
enum {
|
||||
Allocated = 1UL<<31,
|
||||
};
|
||||
|
||||
typedef struct Mapent Mapent;
|
||||
struct Mapent
|
||||
{
|
||||
ulong type;
|
||||
uvlong addr;
|
||||
uvlong size;
|
||||
};
|
||||
|
||||
static struct {
|
||||
Lock;
|
||||
int n;
|
||||
int m;
|
||||
Mapent a[256];
|
||||
} mapalloc;
|
||||
|
||||
static void
|
||||
dump1(Mapent *e)
|
||||
{
|
||||
print("%.16llux-%.16llux %lux\n", e->addr, e->addr + e->size, e->type);
|
||||
}
|
||||
|
||||
static int
|
||||
insert(uvlong addr, uvlong size, ulong type)
|
||||
{
|
||||
Mapent *e;
|
||||
|
||||
if(size == 0 || addr == -1 || addr + size-1 < addr)
|
||||
return 0;
|
||||
|
||||
if(mapalloc.n+mapalloc.m >= nelem(mapalloc.a))
|
||||
return 0;
|
||||
|
||||
e = &mapalloc.a[mapalloc.n + mapalloc.m++];
|
||||
e->type = type;
|
||||
e->addr = addr;
|
||||
e->size = size;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static Mapent*
|
||||
lookup(uvlong addr)
|
||||
{
|
||||
Mapent *i, *e;
|
||||
|
||||
if(addr == -1)
|
||||
return nil;
|
||||
for(i = mapalloc.a, e = i + mapalloc.n; i < e; i++){
|
||||
if(i->addr > addr)
|
||||
break;
|
||||
if(addr - i->addr < i->size)
|
||||
return i;
|
||||
}
|
||||
return nil;
|
||||
}
|
||||
|
||||
static int
|
||||
compare(void *a, void *b)
|
||||
{
|
||||
Mapent *ma = a, *mb = b;
|
||||
|
||||
if(ma->addr < mb->addr)
|
||||
return -1;
|
||||
if(ma->addr > mb->addr)
|
||||
return 1;
|
||||
|
||||
if(ma->type < mb->type)
|
||||
return -1;
|
||||
if(ma->type > mb->type)
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
sort(void)
|
||||
{
|
||||
Mapent *d, *i, *j, *e;
|
||||
|
||||
Again:
|
||||
if(mapalloc.m == 0)
|
||||
return;
|
||||
mapalloc.n += mapalloc.m;
|
||||
mapalloc.m = 0;
|
||||
|
||||
qsort(mapalloc.a, mapalloc.n, sizeof(*e), compare);
|
||||
|
||||
d = i = mapalloc.a;
|
||||
e = i + mapalloc.n;
|
||||
while(i < e){
|
||||
if(i->size == 0)
|
||||
goto Skip;
|
||||
for(j = i+1; j < e; j++){
|
||||
if(j->size == 0)
|
||||
continue;
|
||||
if(j->addr - i->addr >= i->size)
|
||||
break;
|
||||
if(j->type <= i->type){
|
||||
if(j->addr - i->addr + j->size <= i->size)
|
||||
j->size = 0;
|
||||
else {
|
||||
j->size -= i->addr + i->size - j->addr;
|
||||
j->addr = i->addr + i->size;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
if(j->addr - i->addr + j->size < i->size)
|
||||
if(!insert(j->addr + j->size, i->size - (j->addr + j->size - i->addr), i->type))
|
||||
continue;
|
||||
i->size = j->addr - i->addr;
|
||||
if(i->size == 0)
|
||||
goto Skip;
|
||||
}
|
||||
if(d > mapalloc.a){
|
||||
j = d-1;
|
||||
if(i->addr - j->addr == j->size && i->type == j->type){
|
||||
j->size += i->size;
|
||||
i->size = 0;
|
||||
goto Skip;
|
||||
}
|
||||
}
|
||||
memmove(d, i, sizeof(*i));
|
||||
d++;
|
||||
Skip:
|
||||
i++;
|
||||
}
|
||||
if(mapalloc.m > 0)
|
||||
memmove(d, e, mapalloc.m*sizeof(*e));
|
||||
mapalloc.n = d - mapalloc.a;
|
||||
goto Again;
|
||||
}
|
||||
|
||||
void
|
||||
memmapdump(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
lock(&mapalloc);
|
||||
sort();
|
||||
for(i = 0; i < mapalloc.n; i++)
|
||||
dump1(&mapalloc.a[i]);
|
||||
unlock(&mapalloc);
|
||||
}
|
||||
|
||||
uvlong
|
||||
memmapnext(uvlong addr, ulong type)
|
||||
{
|
||||
Mapent *i, *e;
|
||||
|
||||
lock(&mapalloc);
|
||||
sort();
|
||||
for(i = mapalloc.a, e = i+mapalloc.n; i < e; i++){
|
||||
if(((i->type ^ type) & ~Allocated) == 0
|
||||
&& (addr == -1 || i->addr > addr)){
|
||||
addr = i->addr;
|
||||
unlock(&mapalloc);
|
||||
return addr;
|
||||
}
|
||||
}
|
||||
unlock(&mapalloc);
|
||||
return -1;
|
||||
}
|
||||
|
||||
uvlong
|
||||
memmapsize(uvlong addr, uvlong align)
|
||||
{
|
||||
Mapent *i;
|
||||
uvlong size;
|
||||
|
||||
size = 0;
|
||||
lock(&mapalloc);
|
||||
sort();
|
||||
if((i = lookup(addr)) != nil){
|
||||
if(align){
|
||||
addr += align-1;
|
||||
addr &= ~(align-1);
|
||||
}
|
||||
if(addr - i->addr < i->size)
|
||||
size = i->size - (addr - i->addr);
|
||||
}
|
||||
unlock(&mapalloc);
|
||||
return size;
|
||||
}
|
||||
|
||||
void
|
||||
memmapadd(uvlong addr, uvlong size, ulong type)
|
||||
{
|
||||
type &= ~Allocated;
|
||||
lock(&mapalloc);
|
||||
if(insert(addr, size, type))
|
||||
if(mapalloc.n+mapalloc.m >= nelem(mapalloc.a)-1)
|
||||
sort();
|
||||
unlock(&mapalloc);
|
||||
}
|
||||
|
||||
uvlong
|
||||
memmapalloc(uvlong addr, uvlong size, uvlong align, ulong type)
|
||||
{
|
||||
Mapent *i, *e;
|
||||
|
||||
type &= ~Allocated;
|
||||
lock(&mapalloc);
|
||||
sort();
|
||||
if(addr != -1){
|
||||
i = lookup(addr);
|
||||
if(i == nil || i->type != type)
|
||||
goto Fail;
|
||||
if(align){
|
||||
addr += align-1;
|
||||
addr &= ~(align-1);
|
||||
if(addr - i->addr >= i->size)
|
||||
goto Fail;
|
||||
}
|
||||
if(addr - i->addr + size > i->size)
|
||||
goto Fail;
|
||||
Alloc:
|
||||
if(size > 0 && !insert(addr, size, type|Allocated))
|
||||
goto Fail;
|
||||
unlock(&mapalloc);
|
||||
return addr;
|
||||
}
|
||||
e = mapalloc.a + mapalloc.n;
|
||||
for(i = mapalloc.a; i < e; i++){
|
||||
if(i->type != type)
|
||||
continue;
|
||||
addr = i->addr;
|
||||
if(align){
|
||||
addr += align-1;
|
||||
addr &= ~(align-1);
|
||||
if(addr - i->addr >= i->size)
|
||||
continue;
|
||||
}
|
||||
if(addr - i->addr + size <= i->size)
|
||||
goto Alloc;
|
||||
}
|
||||
Fail:
|
||||
unlock(&mapalloc);
|
||||
return -1;
|
||||
}
|
||||
|
||||
void
|
||||
memmapfree(uvlong addr, uvlong size, ulong type)
|
||||
{
|
||||
Mapent *i;
|
||||
|
||||
lock(&mapalloc);
|
||||
sort();
|
||||
i = lookup(addr);
|
||||
if(i == nil
|
||||
|| i->type != (type|Allocated)
|
||||
|| addr - i->addr + size > i->size){
|
||||
unlock(&mapalloc);
|
||||
return;
|
||||
}
|
||||
if(i->addr < addr)
|
||||
insert(i->addr, addr - i->addr, i->type);
|
||||
if(addr - i->addr + size < i->size)
|
||||
insert(addr+size, addr - i->addr + i->size - size, i->type);
|
||||
i->type &= ~Allocated;
|
||||
unlock(&mapalloc);
|
||||
}
|
|
@ -168,6 +168,12 @@ void* malloc(ulong);
|
|||
void* mallocalign(ulong, ulong, long, ulong);
|
||||
void mallocsummary(void);
|
||||
Block* mem2bl(uchar*, int);
|
||||
void memmapdump(void);
|
||||
uvlong memmapnext(uvlong, ulong);
|
||||
uvlong memmapsize(uvlong, uvlong);
|
||||
void memmapadd(uvlong, uvlong, ulong);
|
||||
uvlong memmapalloc(uvlong, uvlong, uvlong, ulong);
|
||||
void memmapfree(uvlong, uvlong, ulong);
|
||||
ulong mcountseg(Segment*);
|
||||
void mfreeseg(Segment*, uintptr, ulong);
|
||||
void microdelay(int);
|
||||
|
|
|
@ -89,10 +89,11 @@ mmusweep(void*)
|
|||
|
||||
sweepcolor = m->sweepcolor;
|
||||
x = splhi();
|
||||
p = proctab(0);
|
||||
for(i = 0; i < conf.nproc; i++, p++)
|
||||
for(i = 0; i < conf.nproc; i++){
|
||||
p = proctab(i);
|
||||
if(PIDCOLOR(p->mmupid) == sweepcolor)
|
||||
p->mmupid = 0;
|
||||
}
|
||||
splx(x);
|
||||
|
||||
ptab = (ulong*)m->ptabbase;
|
||||
|
@ -125,9 +126,10 @@ newmmupid(void)
|
|||
m->mmupid = PIDBASE;
|
||||
x = splhi();
|
||||
tlbflushall();
|
||||
p = proctab(0);
|
||||
for(i = 0; i < conf.nproc; i++, p++)
|
||||
for(i = 0; i < conf.nproc; i++){
|
||||
p = proctab(i);
|
||||
p->mmupid = 0;
|
||||
}
|
||||
splx(x);
|
||||
wakeup(&m->sweepr);
|
||||
}
|
||||
|
|
|
@ -190,7 +190,7 @@ extern void ucfreeb(Block*);
|
|||
/*
|
||||
* Things called from port.
|
||||
*/
|
||||
extern void delay(int); /* only scheddump() */
|
||||
extern void delay(int);
|
||||
extern int islo(void);
|
||||
extern void microdelay(int); /* only edf.c */
|
||||
extern void evenaddr(uintptr);
|
||||
|
|
Loading…
Reference in a new issue