ref: c2427c3e9fc0feeb33ae525b2fb3571da105c2cc
parent: 99b21266a37c052ec0ca323ec1a28e96eb0a2bc3
author: cinap_lenrek <cinap_lenrek@felloff.net>
date: Tue Mar 3 08:08:29 EST 2015
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.
--- a/sys/src/9/port/fault.c
+++ b/sys/src/9/port/fault.c
@@ -200,7 +200,6 @@
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 @@
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;
--- a/sys/src/9/port/page.c
+++ b/sys/src/9/port/page.c
@@ -384,23 +384,11 @@
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 @@
}
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 @@
p = proctab(i);
for(j=0; j<NSEG; j++){s = p->seg[j];
- if(s)
+ if(s != nil)
s->mark = 0;
}
}
@@ -492,6 +481,8 @@
for(j=0; j<NSEG; j++){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++){--- a/sys/src/9/port/portdat.h
+++ b/sys/src/9/port/portdat.h
@@ -359,8 +359,6 @@
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
--- a/sys/src/9/port/segment.c
+++ b/sys/src/9/port/segment.c
@@ -11,9 +11,9 @@
* 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 @@
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)
@@ -481,6 +484,9 @@
int i, j, size;
uintptr soff;
Page *pg;
+
+ if((s->type&SG_TYPE) == SG_PHYSICAL)
+ return;
/*
* We want to zero s->map[i]->page[j] and putpage(pg),
--- a/sys/src/9/port/sysproc.c
+++ b/sys/src/9/port/sysproc.c
@@ -745,6 +745,7 @@
case SG_TEXT:
case SG_DATA:
case SG_STACK:
+ case SG_PHYSICAL:
error(Ebadarg);
default:
return (uintptr)ibrk(va_arg(list, uintptr), i);
--
⑨