diff options
author | cinap_lenrek <cinap_lenrek@felloff.net> | 2019-08-26 22:34:38 +0200 |
---|---|---|
committer | cinap_lenrek <cinap_lenrek@felloff.net> | 2019-08-26 22:34:38 +0200 |
commit | 128ea44a89c7905612ad2fa5a61a9325ddfb5e1e (patch) | |
tree | c8d115acc86fb2e50e38af952741b725bd4366ae | |
parent | 91a8d03040a3533e27f51d33bbbfed33d84b5043 (diff) |
kernel: expose no execute bit to portable mmu code as SG_NOEXEC / PTENOEXEC, add PTECACHED bits
a portable SG_NOEXEC segment attribute was added to allow
non-executable (physical) segments. which will set the
PTENOEXEC bits for putmmu().
in the future, this can be used to make non-executable
stack / bss segments.
the SG_DEVICE attribute was added to distinguish between
mmio regions and uncached memory. only matterns on arm64.
on arm, theres the issue that PTEUNCACHED would have
no bits set when using the hardware bit definitions.
this is the reason bcm, kw, teg2 and omap kernels use
arteficial PTE constants. on zynq, the XN bit was used
as a hack to give PTEUNCACHED a non-zero value and when
the bit is clear then cache attributes where added to
the pte.
to fix this, PTECACHED constant was added.
the portable mmu code in fault.c will now explicitely set
PTECACHED bits for cached memory and PTEUNCACHED for
uncached memory. that way the hardware bit definitions
can be used everywhere.
-rw-r--r-- | sys/src/9/bcm/arm.h | 1 | ||||
-rw-r--r-- | sys/src/9/bcm/gpio.c | 2 | ||||
-rw-r--r-- | sys/src/9/bcm/mem.h | 4 | ||||
-rw-r--r-- | sys/src/9/bcm/mmu.c | 2 | ||||
-rw-r--r-- | sys/src/9/bcm64/mem.h | 6 | ||||
-rw-r--r-- | sys/src/9/bcm64/mmu.c | 3 | ||||
-rw-r--r-- | sys/src/9/kw/mem.h | 3 | ||||
-rw-r--r-- | sys/src/9/mtx/mem.h | 1 | ||||
-rw-r--r-- | sys/src/9/omap/mem.h | 3 | ||||
-rw-r--r-- | sys/src/9/pc/devlml.c | 2 | ||||
-rw-r--r-- | sys/src/9/pc/mem.h | 1 | ||||
-rw-r--r-- | sys/src/9/pc/vga.c | 2 | ||||
-rw-r--r-- | sys/src/9/pc64/mem.h | 1 | ||||
-rw-r--r-- | sys/src/9/port/fault.c | 22 | ||||
-rw-r--r-- | sys/src/9/port/portdat.h | 4 | ||||
-rw-r--r-- | sys/src/9/port/sdram.c | 4 | ||||
-rw-r--r-- | sys/src/9/ppc/m8260.c | 2 | ||||
-rw-r--r-- | sys/src/9/ppc/ucu.h | 1 | ||||
-rw-r--r-- | sys/src/9/sgi/mem.h | 4 | ||||
-rw-r--r-- | sys/src/9/sgi/mmu.c | 11 | ||||
-rw-r--r-- | sys/src/9/teg2/mem.h | 3 | ||||
-rw-r--r-- | sys/src/9/xen/mem.h | 1 | ||||
-rw-r--r-- | sys/src/9/zynq/devarch.c | 2 | ||||
-rw-r--r-- | sys/src/9/zynq/l.s | 2 | ||||
-rw-r--r-- | sys/src/9/zynq/mem.h | 5 | ||||
-rw-r--r-- | sys/src/9/zynq/mmu.c | 4 |
26 files changed, 63 insertions, 33 deletions
diff --git a/sys/src/9/bcm/arm.h b/sys/src/9/bcm/arm.h index 45f47f2ab..cc032cccd 100644 --- a/sys/src/9/bcm/arm.h +++ b/sys/src/9/bcm/arm.h @@ -293,6 +293,7 @@ #define L1noexec (1<<4) #define L2wralloc (1<<6) /* L2 TEX (small pages) */ #define L2sharable (1<<10) +#define L2noexec (1<<0) /* L2 XN (small pages) */ /* attributes for memory containing locks -- differs between armv6 and armv7 */ //#define L1ptedramattrs (Cached | Buffered | L1wralloc | L1sharable) diff --git a/sys/src/9/bcm/gpio.c b/sys/src/9/bcm/gpio.c index 0e4ddcb0c..d05295c1b 100644 --- a/sys/src/9/bcm/gpio.c +++ b/sys/src/9/bcm/gpio.c @@ -130,7 +130,7 @@ gpiomeminit(void) Physseg seg; memset(&seg, 0, sizeof seg); - seg.attr = SG_PHYSICAL; + seg.attr = SG_PHYSICAL | SG_DEVICE | SG_NOEXEC; seg.name = "gpio"; seg.pa = (GPIOREGS - soc.virtio) + soc.physio; seg.size = BY2PG; diff --git a/sys/src/9/bcm/mem.h b/sys/src/9/bcm/mem.h index 6471e9b83..5d0b9a1c5 100644 --- a/sys/src/9/bcm/mem.h +++ b/sys/src/9/bcm/mem.h @@ -79,13 +79,15 @@ #define PPN(x) ((x)&~(BY2PG-1)) /* + * These bits are completely artificial. * With a little work these move to port. */ #define PTEVALID (1<<0) #define PTERONLY 0 #define PTEWRITE (1<<1) +#define PTECACHED 0 #define PTEUNCACHED (1<<2) -#define PTEKERNEL (1<<3) +#define PTENOEXEC (1<<4) /* * Physical machine information from here on. diff --git a/sys/src/9/bcm/mmu.c b/sys/src/9/bcm/mmu.c index 851cb6c5e..7de489456 100644 --- a/sys/src/9/bcm/mmu.c +++ b/sys/src/9/bcm/mmu.c @@ -255,6 +255,8 @@ putmmu(uintptr va, uintptr pa, Page* page) x |= L2AP(Urw); else x |= L2AP(Uro); + if(pa & PTENOEXEC) + x |= L2noexec; pte[L2X(va)] = PPN(pa)|x; cachedwbtlb(&pte[L2X(va)], sizeof(PTE)); diff --git a/sys/src/9/bcm64/mem.h b/sys/src/9/bcm64/mem.h index ba8bef451..450dba012 100644 --- a/sys/src/9/bcm64/mem.h +++ b/sys/src/9/bcm64/mem.h @@ -124,10 +124,12 @@ #define PTEUSER PTEAP(1) #define PTEWRITE PTEAP(0) #define PTERONLY PTEAP(2) +#define PTENOEXEC (PTEPXN|PTEUXN) +#define PTECACHED PTEMA(MA_MEM_WB) #define PTEWT PTEMA(MA_MEM_WT) -#define PTEUNCACHED PTEMA(MA_MEM_UC) -#define PTEDEVICE PTEMA(MA_DEV_nGnRE) +#define PTEUNCACHED PTEMA(MA_MEM_UC) +#define PTEDEVICE PTEMA(MA_DEV_nGnRE) /* * Physical machine information from here on. diff --git a/sys/src/9/bcm64/mmu.c b/sys/src/9/bcm64/mmu.c index 2fbe19747..ca8186322 100644 --- a/sys/src/9/bcm64/mmu.c +++ b/sys/src/9/bcm64/mmu.c @@ -453,7 +453,8 @@ putmmu(uintptr va, uintptr pa, Page *pg) flushasidvall((uvlong)up->asid<<48 | va>>12); else flushasidva((uvlong)up->asid<<48 | va>>12); - *pte = pa | PTEPAGE | PTEUSER | PTEPXN | PTENG | PTEAF | PTESH(SHARE_INNER); + *pte = pa | PTEPAGE | PTEUSER | PTEPXN | PTENG | PTEAF | + (((pa & PTEMA(7)) == PTECACHED)? PTESH(SHARE_INNER): PTESH(SHARE_OUTER)); if(pg->txtflush & (1UL<<m->machno)){ /* pio() sets PG_TXTFLUSH whenever a text pg has been written */ cachedwbinvse(kmap(pg), BY2PG); diff --git a/sys/src/9/kw/mem.h b/sys/src/9/kw/mem.h index 36c4f1c1e..6bd97d087 100644 --- a/sys/src/9/kw/mem.h +++ b/sys/src/9/kw/mem.h @@ -108,13 +108,14 @@ #define PPN(x) ((x)&~(BY2PG-1)) /* + * These bits are completely artificial. * With a little work these move to port. */ #define PTEVALID (1<<0) #define PTERONLY 0 #define PTEWRITE (1<<1) +#define PTECACHED 0 #define PTEUNCACHED (1<<2) -#define PTEKERNEL (1<<3) /* * Physical machine information from here on. diff --git a/sys/src/9/mtx/mem.h b/sys/src/9/mtx/mem.h index 587df9919..3b84511d4 100644 --- a/sys/src/9/mtx/mem.h +++ b/sys/src/9/mtx/mem.h @@ -163,6 +163,7 @@ #define PTEWRITE PTE1_RW #define PTERONLY PTE1_RO #define PTEUNCACHED PTE1_I +#define PTECACHED 0 /* * Address spaces diff --git a/sys/src/9/omap/mem.h b/sys/src/9/omap/mem.h index 2eed0e114..435f47c47 100644 --- a/sys/src/9/omap/mem.h +++ b/sys/src/9/omap/mem.h @@ -97,13 +97,14 @@ #define PPN(x) ((x)&~(BY2PG-1)) /* pure page number? */ /* + * These bits are completely artificial. * With a little work these move to port. */ #define PTEVALID (1<<0) #define PTERONLY 0 #define PTEWRITE (1<<1) +#define PTECACHED 0 #define PTEUNCACHED (1<<2) -#define PTEKERNEL (1<<3) /* * Physical machine information from here on. diff --git a/sys/src/9/pc/devlml.c b/sys/src/9/pc/devlml.c index 8aba39836..f15542922 100644 --- a/sys/src/9/pc/devlml.c +++ b/sys/src/9/pc/devlml.c @@ -185,7 +185,7 @@ lmlreset(void) } memset(&segbuf, 0, sizeof(segbuf)); - segbuf.attr = SG_PHYSICAL; + segbuf.attr = SG_PHYSICAL | SG_DEVICE | SG_NOEXEC; sprint(name, "lml%d.regs", nlml); kstrdup(&segbuf.name, name); segbuf.pa = (ulong)regpa; diff --git a/sys/src/9/pc/mem.h b/sys/src/9/pc/mem.h index 79ed4347b..417430a90 100644 --- a/sys/src/9/pc/mem.h +++ b/sys/src/9/pc/mem.h @@ -156,6 +156,7 @@ #define PTEVALID (1<<0) #define PTEWT (1<<3) #define PTEUNCACHED (1<<4) +#define PTECACHED (0<<4) #define PTEWRITE (1<<1) #define PTERONLY (0<<1) #define PTEKERNEL (0<<2) diff --git a/sys/src/9/pc/vga.c b/sys/src/9/pc/vga.c index e88937730..2cfbd8078 100644 --- a/sys/src/9/pc/vga.c +++ b/sys/src/9/pc/vga.c @@ -257,7 +257,7 @@ addvgaseg(char *name, ulong pa, ulong size) Physseg seg; memset(&seg, 0, sizeof seg); - seg.attr = SG_PHYSICAL; + seg.attr = SG_PHYSICAL | SG_DEVICE | SG_NOEXEC; seg.name = name; seg.pa = pa; seg.size = size; diff --git a/sys/src/9/pc64/mem.h b/sys/src/9/pc64/mem.h index 42a3a119a..f105b78cb 100644 --- a/sys/src/9/pc64/mem.h +++ b/sys/src/9/pc64/mem.h @@ -151,6 +151,7 @@ #define PTEVALID (1ull<<0) #define PTEWT (1ull<<3) #define PTEUNCACHED (1ull<<4) +#define PTECACHED (0ull<<4) #define PTEWRITE (1ull<<1) #define PTERONLY (0ull<<1) #define PTEKERNEL (0ull<<2) diff --git a/sys/src/9/port/fault.c b/sys/src/9/port/fault.c index eaa1d5bd1..f7732bbc3 100644 --- a/sys/src/9/port/fault.c +++ b/sys/src/9/port/fault.c @@ -169,7 +169,7 @@ fixfault(Segment *s, uintptr addr, int read) if(pagedout(*pg)) pio(s, addr, soff, pg); - mmuphys = PPN((*pg)->pa) | PTERONLY|PTEVALID; + mmuphys = PPN((*pg)->pa) | PTERONLY | PTECACHED | PTEVALID; (*pg)->modref = PG_REF; break; @@ -192,7 +192,7 @@ fixfault(Segment *s, uintptr addr, int read) * we're the only user of the segment. */ if(read && conf.copymode == 0 && s->ref == 1) { - mmuphys = PPN((*pg)->pa)|PTERONLY|PTEVALID; + mmuphys = PPN((*pg)->pa) | PTERONLY | PTECACHED | PTEVALID; (*pg)->modref |= PG_REF; break; } @@ -212,7 +212,7 @@ fixfault(Segment *s, uintptr addr, int read) } /* wet floor */ case SG_STICKY: /* Never paged out */ - mmuphys = PPN((*pg)->pa) | PTEWRITE | PTEVALID; + mmuphys = PPN((*pg)->pa) | PTEWRITE | PTECACHED | PTEVALID; (*pg)->modref = PG_MOD|PG_REF; break; @@ -242,8 +242,24 @@ mapphys(Segment *s, uintptr addr, int attr) mmuphys = PPN(pg.pa) | PTEVALID; if((attr & SG_RONLY) == 0) mmuphys |= PTEWRITE; + else + mmuphys |= PTERONLY; + +#ifdef PTENOEXEC + if((attr & SG_NOEXEC) == SG_NOEXEC) + mmuphys |= PTENOEXEC; +#endif + +#ifdef PTEDEVICE + if((attr & SG_DEVICE) == SG_DEVICE) + mmuphys |= PTEDEVICE; + else +#endif if((attr & SG_CACHED) == 0) mmuphys |= PTEUNCACHED; + else + mmuphys |= PTECACHED; + qunlock(s); putmmu(addr, mmuphys, &pg); diff --git a/sys/src/9/port/portdat.h b/sys/src/9/port/portdat.h index 3f4ec4e75..bfa310db4 100644 --- a/sys/src/9/port/portdat.h +++ b/sys/src/9/port/portdat.h @@ -373,7 +373,9 @@ enum SG_RONLY = 0040, /* Segment is read only */ SG_CEXEC = 0100, /* Detach at exec */ SG_FAULT = 0200, /* Fault on access */ - SG_CACHED = 0400, + SG_CACHED = 0400, /* Normal cached memory */ + SG_DEVICE = 01000, /* Memory mapped device */ + SG_NOEXEC = 02000, /* No execute */ }; #define PG_ONSWAP 1 diff --git a/sys/src/9/port/sdram.c b/sys/src/9/port/sdram.c index ce779a03a..4c3ddfec3 100644 --- a/sys/src/9/port/sdram.c +++ b/sys/src/9/port/sdram.c @@ -104,7 +104,7 @@ ramdiskinit0(Ramdisk *rd, uvlong base, uvlong size, ulong ss) rd->pa = base; rd->size = size; - rd->attr = SG_CACHED; + rd->attr = SG_PHYSICAL | SG_CACHED | SG_NOEXEC; } static vlong @@ -204,7 +204,7 @@ ramonline(SDunit *unit) if(unit->sectors != 0) return 1; - rd->seg = newseg(SG_PHYSICAL, UTZERO, rd->size/BY2PG); + rd->seg = newseg(rd->attr, UTZERO, rd->size/BY2PG); if(rd->seg == nil) return 0; rd->seg->pseg = rd; diff --git a/sys/src/9/ppc/m8260.c b/sys/src/9/ppc/m8260.c index 4b283266a..60b62ca5f 100644 --- a/sys/src/9/ppc/m8260.c +++ b/sys/src/9/ppc/m8260.c @@ -441,7 +441,7 @@ addseg(char *name, ulong start, ulong length) Physseg segbuf; memset(&segbuf, 0, sizeof(segbuf)); - segbuf.attr = SG_PHYSICAL; + segbuf.attr = SG_PHYSICAL | SG_DEVICE | SG_NOEXEC; kstrdup(&segbuf.name, name); segbuf.pa = start; segbuf.size = length; diff --git a/sys/src/9/ppc/ucu.h b/sys/src/9/ppc/ucu.h index 91653bc42..7cd427fe9 100644 --- a/sys/src/9/ppc/ucu.h +++ b/sys/src/9/ppc/ucu.h @@ -19,3 +19,4 @@ #define PTEWRITE (PTE1_RW|PTE1_C) #define PTERONLY PTE1_RO #define PTEUNCACHED PTE1_I +#define PTECACHED 0 diff --git a/sys/src/9/sgi/mem.h b/sys/src/9/sgi/mem.h index 11f34b423..d1dec7334 100644 --- a/sys/src/9/sgi/mem.h +++ b/sys/src/9/sgi/mem.h @@ -241,8 +241,8 @@ #define PTECOHERUPDW (6<<3) /* how much faster is it? mflops goes from about .206 (WT) to .37 (WB) */ -// #define PTECACHABILITY PTENONCOHERWT /* 24k erratum 48 disallows WB */ -#define PTECACHABILITY PTENONCOHERWB +// #define PTECACHED PTENONCOHERWT /* 24k erratum 48 disallows WB */ +#define PTECACHED PTENONCOHERWB #define PTEPID(n) (n) #define PTEMAPMEM (1024*1024) diff --git a/sys/src/9/sgi/mmu.c b/sys/src/9/sgi/mmu.c index 3d7e9f569..84330f9c3 100644 --- a/sys/src/9/sgi/mmu.c +++ b/sys/src/9/sgi/mmu.c @@ -180,14 +180,14 @@ retry: virt |= KMAPADDR | ((k-kpte)<<KMAPSHIFT); k->virt = virt; - pte = PPN(pg->pa)|PTECACHABILITY|PTEGLOBL|PTEWRITE|PTEVALID; + pte = PPN(pg->pa)|PTECACHED|PTEGLOBL|PTEWRITE|PTEVALID; if(virt & BY2PG) { - k->phys0 = PTEGLOBL | PTECACHABILITY; + k->phys0 = PTEGLOBL | PTECACHED; k->phys1 = pte; } else { k->phys0 = pte; - k->phys1 = PTEGLOBL | PTECACHABILITY; + k->phys1 = PTEGLOBL | PTECACHED; } putktlb(k); @@ -385,11 +385,6 @@ putmmu(ulong tlbvirt, ulong tlbphys, Page *pg) tp = newtlbpid(up); tlbvirt |= PTEPID(tp); - if((tlbphys & PTEALGMASK) != PTEUNCACHED) { - tlbphys &= ~PTEALGMASK; - tlbphys |= PTECACHABILITY; - } - entry = putstlb(tlbvirt, tlbphys); x = gettlbp(tlbvirt, tlbent); if(x < 0) x = getrandom(); diff --git a/sys/src/9/teg2/mem.h b/sys/src/9/teg2/mem.h index 08bdefdb9..81544cfd8 100644 --- a/sys/src/9/teg2/mem.h +++ b/sys/src/9/teg2/mem.h @@ -114,13 +114,14 @@ #define PPN(x) ((x)&~(BY2PG-1)) /* pure page number? */ /* + * These bits are completely artificial. * With a little work these move to port. */ #define PTEVALID (1<<0) #define PTERONLY 0 #define PTEWRITE (1<<1) +#define PTECACHED 0 #define PTEUNCACHED (1<<2) -#define PTEKERNEL (1<<3) /* * Physical machine information from here on. diff --git a/sys/src/9/xen/mem.h b/sys/src/9/xen/mem.h index 702d0ee87..aabb5cec0 100644 --- a/sys/src/9/xen/mem.h +++ b/sys/src/9/xen/mem.h @@ -86,6 +86,7 @@ #define PTEVALID (1<<0) #define PTEWT (1<<3) #define PTEUNCACHED (1<<4) +#define PTECACHED (0<<4) #define PTEWRITE (1<<1) #define PTERONLY (0<<1) #define PTEKERNEL (0<<2) diff --git a/sys/src/9/zynq/devarch.c b/sys/src/9/zynq/devarch.c index 85b54c97e..00a368fd6 100644 --- a/sys/src/9/zynq/devarch.c +++ b/sys/src/9/zynq/devarch.c @@ -181,7 +181,7 @@ plinit(void) Physseg seg; memset(&seg, 0, sizeof seg); - seg.attr = SG_PHYSICAL | SG_FAULT; + seg.attr = SG_PHYSICAL | SG_DEVICE | SG_NOEXEC | SG_FAULT; seg.name = "axi"; seg.pa = 0x40000000; seg.size = 0x8000000; diff --git a/sys/src/9/zynq/l.s b/sys/src/9/zynq/l.s index cdeebc140..9a7e6e151 100644 --- a/sys/src/9/zynq/l.s +++ b/sys/src/9/zynq/l.s @@ -41,7 +41,7 @@ _start2: CMP.S R2, R3 BGE _start2 - MOVW $(UART_BASE|L2VALID|L2DEVICE|L2KERRW), R0 + MOVW $(UART_BASE|L2VALID|L2DEVICE|L2NOEXEC|L2KERRW), R0 MOVW $(VMAPL2-KZERO), R1 MOVW R0, (R1) diff --git a/sys/src/9/zynq/mem.h b/sys/src/9/zynq/mem.h index 26f5f1d5f..0634265c7 100644 --- a/sys/src/9/zynq/mem.h +++ b/sys/src/9/zynq/mem.h @@ -62,6 +62,8 @@ #define PTEVALID L2VALID #define PTERONLY L2RONLY #define PTEWRITE L2WRITE +#define PTENOEXEC L2NOEXEC +#define PTECACHED L2CACHED #define PTEUNCACHED L2DEVICE #define PPN(x) ((x)&~(BY2PG-1)) @@ -114,7 +116,8 @@ #define L2VALID (2|1<<4) #define L2CACHED (1<<10|1<<8|1<<6|1<<2) -#define L2DEVICE (1<<0) +#define L2DEVICE 0 +#define L2NOEXEC (1<<0) #define L2KERRW L2KERNEL #define L2KERNEL 0 #define L2USER (1<<5) diff --git a/sys/src/9/zynq/mmu.c b/sys/src/9/zynq/mmu.c index 918f930b5..ed6412e70 100644 --- a/sys/src/9/zynq/mmu.c +++ b/sys/src/9/zynq/mmu.c @@ -147,8 +147,6 @@ putmmu(uintptr va, uintptr pa, Page *pg) if(up->l1 == nil) upallocl1(); - if((pa & PTEUNCACHED) == 0) - pa |= L2CACHED; e = &up->l1->va[L1RX(va)]; if((*e & 3) == 0){ p = up->mmufree; @@ -400,7 +398,7 @@ vmap(uintptr pa, ulong sz) while(np-- != 0){ if(vp == ve) panic("vmap: out of vmap space (pa=%#.8lux)", pa); - *vp++ = pa | L2VALID | L2DEVICE | L2KERRW; + *vp++ = pa | L2VALID | L2DEVICE | L2NOEXEC | L2KERRW; pa += BY2PG; } coherence(); |