the adr map in technicolor. add the color (numa memory domain) to the adr map. this will consolidate the tracking of physical memory into a single structure, instead of using the Srat structure as an adjunct. there's one issue with the current implementation. memory is colored after the initial maps are laid down, so adrsetcolor() is more complicated than it should be, and could fail if an address range needs to be split that's already in use. Reference: /n/atom/patch/applied2013/adrcolor Date: Tue Oct 8 19:29:06 CES 2013 Signed-off-by: quanstro@quanstro.net --- /sys/man/9nix/adr Tue Oct 8 19:25:52 2013 +++ /sys/man/9nix/adr Tue Oct 8 19:25:52 2013 @@ -35,6 +35,11 @@ Mlast = Mvmap, }; .PB +enum { + Cnone = -1, + Cmax = 32767, +}; +.PB .PD 0 .ta +\w'\fL 'u +\w'\fL 'u +6n +4n uintmem adralloc(uintmem base, uintmem len, int align, @@ -45,13 +50,13 @@ void adrinit(void) .PB void adrmapck(uintmem base, uintmem len, - int type, int use) + int type, int use, int color) .PB int adrmapenc(uintmem *base, uintmem *len, int type, int use) .PB void adrmapinit(uintmem base, uintmem len, - int type, int use) + int type, int use, int color) .PB uint adrmemflags(uintmem pa) .PB @@ -59,17 +64,20 @@ .PB uintmem adrmemtype(uintmem pa, uintmem *len, int *type, int *use) +.PB +void adrsetcolor(uintmem pa, uintmem len, int color) .SH DESCRIPTION The physical address map is managed by .IR adr . Map entries consist of a base, length address type -(e.g. memory, mmio, etc.), current use and +(e.g. memory, mmio, etc.), current use, color (NUMA domain), and caching flags. The map is initlialized from the .B *e820 configuration variable (see .IR plan9.ini (8)), PCI mappings, ACPI and other memory-mapped -devices such as I/O APICs and LAPICs. Address ranges may +devices such as I/O APICs and LAPICs. Additional information +may come from the ACPI SRAT table, etc. Address ranges may be allocated by address type; .I adr splits address ranges as necessary. Allocated maps @@ -97,13 +105,13 @@ Set up the address map. This is called early in .BR main . .TP -.BI adrmapinit( base\fP,\fP\ len\fP,\fP\ type\fP,\fP\ use ) +.BI adrmapinit( base\fP,\fP\ len\fP,\fP\ type\fP,\fP\ use\fP,\fP color ) Enter a new physical mapping to be entered into the .I adr map. The map must not overlap existing maps. .TP -.BI adrmapck( base\fP,\fP\ len\fP,\fP\ type\fP,\fP\ use ) +.BI adrmapck( base\fP,\fP\ len\fP,\fP\ type\fP,\fP\ use\fP,\fP\ color ) Ensure that the given map exists and is the correct type. Correct the map if necessary. This is useful to work around machines that do not reserve memory for I/O @@ -126,6 +134,9 @@ is used by .IR vmap (9nix) to maintain consistent caching flags. +.TP +.BI adrsetcolor( pa\fP,\fP\ len\fP,\fP\ color ) +Set the color for a range of memory. .SH SOURCE .B /sys/src/nix/k10/adr.c .SH "SEE ALSO" --- /sys/src/nix/port/portfns.h Tue Oct 8 19:25:52 2013 +++ /sys/src/nix/port/portfns.h Tue Oct 8 19:25:52 2013 @@ -229,7 +229,7 @@ uintmem physalloc(u64int, int*, void*); void physdump(void); void physfree(uintmem, u64int); -void physinit(uintmem, u64int); +void physinit(uintmem, u64int, int); void* phystag(uintmem); void pio(Segment*, uintptr, usize, Page**, int); #define poperror() up->nerrlab-- --- /sys/src/nix/k10/adr.c Tue Oct 8 19:25:52 2013 +++ /sys/src/nix/k10/adr.c Tue Oct 8 19:25:52 2013 @@ -11,8 +11,9 @@ struct Adrmap { uintmem base; uintmem len; - uint type; - uint use; + uchar type; + uchar use; + short color; uint memflags; }; @@ -59,8 +60,8 @@ Adrmap *a; a = va_arg(f->args, Adrmap*); - return fmtprint(f, "%.8s %.8s %#ux %#.16P %#.16P", - uname[a->use], tname[a->type], a->memflags, a->base, a->base+a->len); + return fmtprint(f, "%.8s %.8s %#ux %d %#.16P %#.16P", + uname[a->use], tname[a->type], a->memflags, a->color, a->base, a->base+a->len); } #pragma varargck type "a" Adrmap* @@ -102,7 +103,7 @@ } static void -insert(uintmem base, uintmem len, int type, int use, uint memflags) +insert(uintmem base, uintmem len, int type, int use, int color, uint memflags) { int i, n; Adrmap a; @@ -115,7 +116,7 @@ lock(&adr); - a = (Adrmap){base, len, type, use, memflags}; + a = (Adrmap){base, len, type, use, color, memflags}; n = npages(&a); if(0 && n <= 0){ unlock(&adr); @@ -196,7 +197,7 @@ * subject to change. system text map should be handled elsewhere. */ void -adrmapinit(uintmem base, uintmem len, int type, int use) +adrmapinit(uintmem base, uintmem len, int type, int use, int color) { switch(type){ case Amemory: @@ -210,12 +211,6 @@ * and how much of it is occupied, might need to be known * for setting up allocators later. */ -// if(base < 1*MiB || base+len < sys->pmstart) -// break; -// if(base < sys->pmstart){ -// len -= sys->pmstart - base; -// base = sys->pmstart; -// } if(base >= 1*MiB && base+len < sys->pmstart) break; if(base >= 1*MiB && base < sys->pmstart){ @@ -226,7 +221,7 @@ if(base+len > sys->pmend) sys->pmend = base+len; default: - insert(base, len, type, use, 0); + insert(base, len, type, use, color, 0); break; } } @@ -236,6 +231,7 @@ { if(a->type == b->type) if(a->use == b->use) + if(a->color == b->color) if(a->base+a->len == b->base){ a->len += b->len; memmove(b, b+1, (adr.nmap-- - (b+1 - adr.map))*sizeof(Adrmap)); @@ -244,15 +240,13 @@ return 0; } -uintmem -adralloc(uintmem base, uintmem len, int align, int type, int use, uint flags) +static uintmem +intadralloc(uintmem base, uintmem len, int align, int type, int use, int color, uint memflags) { uintmem slop, adjlen, l; int i; Adrmap *a; - DBG("adralloc: %#P:%#P, %s flags %#ux\n", base, len, tnam(type), flags); - lock(&adr); for(i = 0; i < adr.nmap; i++){ a = adr.map+i; if((type != -1 && a->type != type) || a->use != Mfree) @@ -289,19 +283,30 @@ trymerge(a+1, a+2); } a->use = use; - a->memflags = flags; + a->memflags = memflags; + if(color != Cnone) + a->color = color; if(0 && use == Mfree && i>0) trymerge(a-1, a); - unlock(&adr); return base; } - unlock(&adr); + return 0; +} - print("adralloc: fail %#P len %#P type %s use %s align %d flags %#ux from %#p\n", - base, len, tnam(type), uname[use], align, flags, getcallerpc(&base)); - adrdump(); +uintmem +adralloc(uintmem base, uintmem len, int align, int type, int use, uint memflags) +{ + DBG("adralloc: %#P:%#P, %s flags %#ux\n", base, len, tnam(type), memflags); + lock(&adr); + base = intadralloc(base, len, align, type, use, Cnone, memflags); + unlock(&adr); - return 0; + if(base == 0){ + print("adralloc: fail %#P len %#P type %s use %s align %d flags %#ux from %#p\n", + base, len, tnam(type), uname[use], align, memflags, getcallerpc(&base)); + adrdump(); + } + return base; } void @@ -328,11 +333,12 @@ } int -adrmatch(int i, int type, int use, uintmem *base, uintmem *sz) +adrmatch(int i, int type, int use, int color, uintmem *base, uintmem *sz) { lock(&adr); for(; ++i < adr.nmap;){ + if(adr.map[i].color == color || color == -1) if(adr.map[i].type == type) if(adr.map[i].use == use){ *base = adr.map[i].base; @@ -346,12 +352,44 @@ return -1; } +void +adrsetcolor(uintmem base, uintmem len, int color) +{ + int i; + uintmem b, e, end, aend; + Adrmap *a; + + print("adrsetcolor: %#P:%#P color %d\n", base, base+len, color); + end = base + len; + lock(&adr); + for(i = 0; i < adr.nmap; i++){ + a = adr.map+i; + aend = a->base + a->len; + if(base <= a->base && aend <= end){ + /* fully enclosed; may already be allocated, so cheat */ + a->color = color; + continue; + } + b = MAX(base, a->base); + e = MIN(end, aend); + if(b >= e) + continue; + + print("adrsetcolor: split range [%#P %#P) ⊂ [%#P %#P)\n", + b, e, a->base, aend); + if(intadralloc(b, e-b, 0, a->type, a->use, color, a->memflags) == 0) + print("adrsetcolor: no such memory [%#P %#P) ⊂ [%#P %#P)\n", + b, e, a->base, aend); + } + unlock(&adr); +} + /* * apics and i/o apics should be, but aren't always reserved memory. * insure that we've got an appropriate adr entry for such a beast. */ void -adrmapck(uintmem base, uintmem len, int type, int use) +adrmapck(uintmem base, uintmem len, int type, int use, int color) { Adrmap *m; @@ -359,7 +397,7 @@ m = adrlook(base, len); if(m == nil){ unlock(&adr); - insert(base, len, type, use, 0); + insert(base, len, type, use, color, 0); } else{ m->type = type; @@ -401,7 +439,7 @@ // sys->pmstart = ROUNDUP(PADDR(end), BIGPGSZ); sys->pmstart = 0+INIMAP; sys->pmend = sys->pmstart; - insert(1*MiB, sys->pmstart - 1*MiB, Amemory, Mktext, 0); /* botch; hardcoded */ + insert(1*MiB, sys->pmstart - 1*MiB, Amemory, Mktext, 0, 0); /* botch; hardcoded */ addarchfile("adr", 0444, adrread, nil); } @@ -516,7 +554,7 @@ adr.pagecnt[a->use] -= npages(a); a->use = Mupage; adr.pagecnt[Mupage] += npages(a); - physinit(a->base, a->len); + physinit(a->base, a->len, a->color); } physallocdump(); } --- /sys/src/nix/k10/adr.h Tue Oct 8 19:25:52 2013 +++ /sys/src/nix/k10/adr.h Tue Oct 8 19:25:52 2013 @@ -22,13 +22,19 @@ Mlast = Mvmap, }; +enum { + Cnone = -1, + Cmax = 65535, +}; + uintmem adralloc(uintmem, uintmem, int, int, int, uint); +void adrsetcolor(uintmem, uintmem, int); void adrdump(void); void adrinit(void); -void adrmapck(uintmem, uintmem, int, int); +void adrmapck(uintmem, uintmem, int, int, int); int adrmapenc(uintmem*, uintmem*, int, int); -void adrmapinit(uintmem, uintmem, int, int); +void adrmapinit(uintmem, uintmem, int, int, int); uint adrmemflags(uintmem); void adrfree(uintmem base, uintmem len); -int adrmatch(int, int, int, uintmem*, uintmem*); /* not currently used */ +int adrmatch(int, int, int, int, uintmem*, uintmem*); /* not currently used */ uintmem adrmemtype(uintmem, uintmem*, int*, int*); --- /sys/src/nix/k10/options.c Tue Oct 8 19:25:52 2013 +++ /sys/src/nix/k10/options.c Tue Oct 8 19:25:52 2013 @@ -124,7 +124,7 @@ break; if(type >= nelem(typemap)) continue; - adrmapinit(base, len, typemap[type], Mfree); + adrmapinit(base, len, typemap[type], Mfree, 0); } } --- /sys/src/nix/k10/lapic.c Tue Oct 8 19:25:52 2013 +++ /sys/src/nix/k10/lapic.c Tue Oct 8 19:25:52 2013 @@ -163,12 +163,8 @@ Apic *apic; /* - * Mark the LAPIC useable if it has a good ID - * and the registers can be mapped. - * The LAPIC Extended Broadcast and ID bits in the HyperTransport - * Transaction Control register determine whether 4 or 8 bits - * are used for the LAPIC ID. There is also xLAPIC and x2LAPIC - * to be dealt with sometime. + * Mark the LAPIC useable if it has a good ID, and the registers can + * be mapped. There is x2LAPIC to be dealt with at some point. */ DBG("lapicinit: lapicno %d pa %#P isbp %d caller %#p\n", lapicno, pa, isbp, getcallerpc(&lapicno)); addarchfile("lapic", 0444, lapicread, nil); @@ -182,7 +178,7 @@ return; } if(lapicbase == nil){ - adrmapck(pa, 1024, Aapic, Mfree); + adrmapck(pa, 1024, Ammio, Mfree, Cnone); if((lapicbase = vmap(pa, 1024)) == nil){ panic("lapicinit%d: can't map lapicbase %#P", lapicno, pa); return; --- /sys/src/nix/k10/hpet.c Tue Oct 8 19:25:52 2013 +++ /sys/src/nix/k10/hpet.c Tue Oct 8 19:25:52 2013 @@ -42,7 +42,7 @@ print("hpet: seqno %d pa %#p minticks %d\n", seqno, pa, minticks); if(seqno >= nelem(etb)) return; - adrmapck(pa, 1024, Ammio, Mfree); + adrmapck(pa, 1024, Ammio, Mfree, Cnone); if((hpet = vmap(pa, 1024)) == nil) return; etb[seqno] = hpet; --- /sys/src/nix/k10/ioapic.c Tue Oct 8 19:25:52 2013 +++ /sys/src/nix/k10/ioapic.c Tue Oct 8 19:25:52 2013 @@ -222,7 +222,7 @@ apic->addr = p->addr; } else{ - adrmapck(pa, 1024, Aapic, Mfree); /* not in adr? */ + adrmapck(pa, 1024, Ammio, Mfree, Cnone); /* not in adr? */ if((apic->addr = vmap(pa, 1024)) == nil){ print("ioapic%d: can't vmap %#P\n", id, pa); return nil; --- /sys/src/nix/k10/physalloc.c Tue Oct 8 19:25:52 2013 +++ /sys/src/nix/k10/physalloc.c Tue Oct 8 19:25:52 2013 @@ -427,7 +427,7 @@ * Called from umeminit to initialize user memory allocators. */ void -physinit(uintmem a, u64int size) +physinit(uintmem a, u64int size, int /*color*/) { uintmem dtsz; Bal *b;