kernel: fix physical segment handling
ignore physical segments in mcountseg() and mfreeseg(). physical segments are not backed by user pages, and doing putpage() on physical segment pages in mfreeseg() is an error. do now allow physical segemnts to be resized. the segment size is only checked in segattach() to be within the physical segment! ignore physical segments in portcountpagerefs() as pagenumber() does not work on the malloced page structures of a physical segment. get rid of Physseg.pgalloc() and Physseg.pgfree() indirection as this was never used and if theres a need to do more efficient allocation, it should be done in a portable way.
This commit is contained in:
parent
2259f3fb9a
commit
eaf91d0f8e
5 changed files with 23 additions and 34 deletions
|
@ -200,7 +200,6 @@ fixfault(Segment *s, uintptr addr, int read, int doputmmu)
|
|||
Pte **p, *etp;
|
||||
uintptr soff, mmuphys=0;
|
||||
Page **pg, *old, *new;
|
||||
Page *(*fn)(Segment*, uintptr);
|
||||
|
||||
addr &= ~(BY2PG-1);
|
||||
soff = addr-s->base;
|
||||
|
@ -274,19 +273,13 @@ fixfault(Segment *s, uintptr addr, int read, int doputmmu)
|
|||
break;
|
||||
|
||||
case SG_PHYSICAL:
|
||||
if(*pg == nil) {
|
||||
fn = s->pseg->pgalloc;
|
||||
if(fn)
|
||||
*pg = (*fn)(s, addr);
|
||||
else {
|
||||
new = smalloc(sizeof(Page));
|
||||
new->va = addr;
|
||||
new->pa = s->pseg->pa+(addr-s->base);
|
||||
new->ref = 1;
|
||||
*pg = new;
|
||||
}
|
||||
if(*pg == nil){
|
||||
new = smalloc(sizeof(Page));
|
||||
new->va = addr;
|
||||
new->pa = s->pseg->pa+(addr-s->base);
|
||||
new->ref = 1;
|
||||
*pg = new;
|
||||
}
|
||||
|
||||
if (checkaddr && addr == addr2check)
|
||||
(*checkaddr)(addr, s, *pg);
|
||||
mmuphys = PPN((*pg)->pa) |PTEWRITE|PTEUNCACHED|PTEVALID;
|
||||
|
|
|
@ -384,23 +384,11 @@ ptealloc(void)
|
|||
void
|
||||
freepte(Segment *s, Pte *p)
|
||||
{
|
||||
void (*fn)(Page*);
|
||||
Page **pg, **ptop;
|
||||
Page **pg;
|
||||
|
||||
switch(s->type&SG_TYPE) {
|
||||
case SG_PHYSICAL:
|
||||
fn = s->pseg->pgfree;
|
||||
ptop = &p->pages[PTEPERTAB];
|
||||
if(fn != nil) {
|
||||
for(pg = p->pages; pg < ptop; pg++) {
|
||||
if(*pg == nil)
|
||||
continue;
|
||||
(*fn)(*pg);
|
||||
*pg = nil;
|
||||
}
|
||||
break;
|
||||
}
|
||||
for(pg = p->pages; pg < ptop; pg++) {
|
||||
for(pg = p->first; pg <= p->last; pg++) {
|
||||
if(*pg != nil) {
|
||||
if(decref(*pg) == 0)
|
||||
free(*pg);
|
||||
|
@ -409,11 +397,12 @@ freepte(Segment *s, Pte *p)
|
|||
}
|
||||
break;
|
||||
default:
|
||||
for(pg = p->first; pg <= p->last; pg++)
|
||||
for(pg = p->first; pg <= p->last; pg++) {
|
||||
if(*pg != nil) {
|
||||
putpage(*pg);
|
||||
*pg = nil;
|
||||
}
|
||||
}
|
||||
}
|
||||
free(p);
|
||||
}
|
||||
|
@ -483,7 +472,7 @@ portcountpagerefs(ulong *ref, int print)
|
|||
p = proctab(i);
|
||||
for(j=0; j<NSEG; j++){
|
||||
s = p->seg[j];
|
||||
if(s)
|
||||
if(s != nil)
|
||||
s->mark = 0;
|
||||
}
|
||||
}
|
||||
|
@ -493,6 +482,8 @@ portcountpagerefs(ulong *ref, int print)
|
|||
s = p->seg[j];
|
||||
if(s == nil || s->mark++)
|
||||
continue;
|
||||
if((s->type&SG_TYPE) == SG_PHYSICAL)
|
||||
continue;
|
||||
ns++;
|
||||
for(k=0; k<s->mapsize; k++){
|
||||
pte = s->map[k];
|
||||
|
|
|
@ -359,8 +359,6 @@ struct Physseg
|
|||
char *name; /* Attach name */
|
||||
uintptr pa; /* Physical address */
|
||||
uintptr size; /* Maximum segment size in bytes */
|
||||
Page *(*pgalloc)(Segment*, uintptr); /* Allocation if we need it */
|
||||
void (*pgfree)(Page*);
|
||||
};
|
||||
|
||||
struct Sema
|
||||
|
|
|
@ -11,9 +11,9 @@ int imagereclaim(int);
|
|||
* Attachable segment types
|
||||
*/
|
||||
static Physseg physseg[10] = {
|
||||
{ SG_SHARED, "shared", 0, SEGMAXSIZE, 0, 0 },
|
||||
{ SG_BSS, "memory", 0, SEGMAXSIZE, 0, 0 },
|
||||
{ 0, 0, 0, 0, 0, 0 },
|
||||
{ SG_SHARED, "shared", 0, SEGMAXSIZE },
|
||||
{ SG_BSS, "memory", 0, SEGMAXSIZE },
|
||||
{ 0, 0, 0, 0 },
|
||||
};
|
||||
|
||||
static Lock physseglock;
|
||||
|
@ -459,6 +459,9 @@ mcountseg(Segment *s)
|
|||
int i, j;
|
||||
Page *pg;
|
||||
|
||||
if((s->type&SG_TYPE) == SG_PHYSICAL)
|
||||
return 0;
|
||||
|
||||
pages = 0;
|
||||
for(i = 0; i < s->mapsize; i++){
|
||||
if(s->map[i] == nil)
|
||||
|
@ -482,6 +485,9 @@ mfreeseg(Segment *s, uintptr start, int pages)
|
|||
uintptr soff;
|
||||
Page *pg;
|
||||
|
||||
if((s->type&SG_TYPE) == SG_PHYSICAL)
|
||||
return;
|
||||
|
||||
/*
|
||||
* We want to zero s->map[i]->page[j] and putpage(pg),
|
||||
* but we have to make sure other processors flush the
|
||||
|
|
|
@ -745,6 +745,7 @@ syssegbrk(va_list list)
|
|||
case SG_TEXT:
|
||||
case SG_DATA:
|
||||
case SG_STACK:
|
||||
case SG_PHYSICAL:
|
||||
error(Ebadarg);
|
||||
default:
|
||||
return (uintptr)ibrk(va_arg(list, uintptr), i);
|
||||
|
|
Loading…
Reference in a new issue