From 09b37bb062ecc78f4831173c6f58408c08714f27 Mon Sep 17 00:00:00 2001 From: maxv Date: Thu, 12 May 2016 06:45:16 +0000 Subject: [PATCH] Split the {text+rodata} chunk in two separate chunks on x86. The rodata segment now loses the large page optimization, gets mapped inside the data segment, and therefore becomes RWX. It may break the build on Xen. --- sys/arch/amd64/amd64/locore.S | 6 +++--- sys/arch/amd64/amd64/machdep.c | 5 +++-- sys/arch/amd64/conf/kern.ldscript | 14 +++++++------- sys/arch/i386/conf/kern.ldscript | 14 ++++++++------ sys/arch/i386/i386/locore.S | 8 ++++---- sys/arch/x86/x86/db_memrw.c | 10 ++++++---- sys/arch/x86/x86/pmap.c | 12 ++++++------ 7 files changed, 37 insertions(+), 32 deletions(-) diff --git a/sys/arch/amd64/amd64/locore.S b/sys/arch/amd64/amd64/locore.S index 82e39d5784cf..ac02991c9b19 100644 --- a/sys/arch/amd64/amd64/locore.S +++ b/sys/arch/amd64/amd64/locore.S @@ -1,4 +1,4 @@ -/* $NetBSD: locore.S,v 1.86 2016/05/11 19:35:08 maxv Exp $ */ +/* $NetBSD: locore.S,v 1.87 2016/05/12 06:45:16 maxv Exp $ */ /* * Copyright-o-rama! @@ -617,11 +617,11 @@ no_NOX: addl %ecx,%ebx /* - * Compute &__data_start - KERNBASE. This can't be > 4G, or we can't + * Compute &__rodata_start - KERNBASE. This can't be > 4G, or we can't * deal with it anyway, since we can't load it in 32 bit mode. So use * the bottom 32 bits. */ - movl $RELOC(__data_start),%edx + movl $RELOC(__rodata_start),%edx andl $~PGOFSET,%edx /* Map the kernel text read-only. */ diff --git a/sys/arch/amd64/amd64/machdep.c b/sys/arch/amd64/amd64/machdep.c index 3dd4fb132063..1a251bf359c8 100644 --- a/sys/arch/amd64/amd64/machdep.c +++ b/sys/arch/amd64/amd64/machdep.c @@ -1,4 +1,4 @@ -/* $NetBSD: machdep.c,v 1.215 2016/02/15 20:35:59 riastradh Exp $ */ +/* $NetBSD: machdep.c,v 1.216 2016/05/12 06:45:16 maxv Exp $ */ /*- * Copyright (c) 1996, 1997, 1998, 2000, 2006, 2007, 2008, 2011 @@ -111,7 +111,7 @@ */ #include -__KERNEL_RCSID(0, "$NetBSD: machdep.c,v 1.215 2016/02/15 20:35:59 riastradh Exp $"); +__KERNEL_RCSID(0, "$NetBSD: machdep.c,v 1.216 2016/05/12 06:45:16 maxv Exp $"); /* #define XENDEBUG_LOW */ @@ -2102,6 +2102,7 @@ mm_md_kernacc(void *ptr, vm_prot_t prot, bool *handled) if (v >= (vaddr_t)&start && v < (vaddr_t)kern_end) { *handled = true; + /* Either the text or rodata segment */ if (v < (vaddr_t)&__data_start && (prot & VM_PROT_WRITE)) return EFAULT; diff --git a/sys/arch/amd64/conf/kern.ldscript b/sys/arch/amd64/conf/kern.ldscript index c1fefae9797b..b2c11a4e19f5 100644 --- a/sys/arch/amd64/conf/kern.ldscript +++ b/sys/arch/amd64/conf/kern.ldscript @@ -1,4 +1,4 @@ -/* $NetBSD: kern.ldscript,v 1.18 2016/05/08 08:30:41 maxv Exp $ */ +/* $NetBSD: kern.ldscript,v 1.19 2016/05/12 06:45:16 maxv Exp $ */ #include "assym.h" @@ -23,6 +23,12 @@ SECTIONS _etext = . ; PROVIDE (etext = .) ; + /* + * Push the rodata segment up to the next large page boundary so that we + * can map the text segment with large pages. + */ + . = ALIGN(__LARGE_PAGE_SIZE); + __rodata_start = . ; .rodata : { @@ -30,12 +36,6 @@ SECTIONS *(.rodata.*) } - /* - * Push the data segment up to the next large page boundary so that we - * can map the text+rodata segments with large pages. - */ - . = ALIGN(__LARGE_PAGE_SIZE); - __data_start = . ; .data : { diff --git a/sys/arch/i386/conf/kern.ldscript b/sys/arch/i386/conf/kern.ldscript index 4beec296b07b..02fbd4a23c53 100644 --- a/sys/arch/i386/conf/kern.ldscript +++ b/sys/arch/i386/conf/kern.ldscript @@ -1,4 +1,4 @@ -/* $NetBSD: kern.ldscript,v 1.16 2015/11/28 18:08:40 maxv Exp $ */ +/* $NetBSD: kern.ldscript,v 1.17 2016/05/12 06:45:16 maxv Exp $ */ #include "assym.h" @@ -15,17 +15,19 @@ SECTIONS _etext = . ; PROVIDE (etext = .) ; + /* + * Adjust the address for the rodata segment. We want to adjust up to + * the same address within the page on the next page up. + */ + . = ALIGN(0x1000) + (. & (0x1000 - 1)); + + __rodata_start = . ; .rodata : { *(.rodata) *(.rodata.*) } - /* - * Adjust the address for the data segment. We want to adjust up to - * the same address within the page on the next page up. - */ - . = ALIGN(0x1000) + (. & (0x1000 - 1)); __data_start = . ; .data : { diff --git a/sys/arch/i386/i386/locore.S b/sys/arch/i386/i386/locore.S index c6d8d80ae8da..91f3593de794 100644 --- a/sys/arch/i386/i386/locore.S +++ b/sys/arch/i386/i386/locore.S @@ -1,4 +1,4 @@ -/* $NetBSD: locore.S,v 1.115 2016/05/11 17:48:05 maxv Exp $ */ +/* $NetBSD: locore.S,v 1.116 2016/05/12 06:45:16 maxv Exp $ */ /* * Copyright-o-rama! @@ -128,7 +128,7 @@ */ #include -__KERNEL_RCSID(0, "$NetBSD: locore.S,v 1.115 2016/05/11 17:48:05 maxv Exp $"); +__KERNEL_RCSID(0, "$NetBSD: locore.S,v 1.116 2016/05/12 06:45:16 maxv Exp $"); #include "opt_compat_oldboot.h" #include "opt_copy_symtab.h" @@ -613,11 +613,11 @@ try586: /* Use the `cpuid' instruction. */ * Build initial page tables. */ /* - * Compute &__data_start - KERNBASE. This can't be > 4G, + * Compute &__rodata_start - KERNBASE. This can't be > 4G, * or we can't deal with it anyway, since we can't load it in * 32 bit mode. So use the bottom 32 bits. */ - movl $RELOC(__data_start),%edx + movl $RELOC(__rodata_start),%edx andl $~PGOFSET,%edx /* diff --git a/sys/arch/x86/x86/db_memrw.c b/sys/arch/x86/x86/db_memrw.c index c6447a06043e..20309aa879c0 100644 --- a/sys/arch/x86/x86/db_memrw.c +++ b/sys/arch/x86/x86/db_memrw.c @@ -1,4 +1,4 @@ -/* $NetBSD: db_memrw.c,v 1.1 2012/05/07 17:45:29 jym Exp $ */ +/* $NetBSD: db_memrw.c,v 1.2 2016/05/12 06:45:16 maxv Exp $ */ /*- * Copyright (c) 1996, 2000 The NetBSD Foundation, Inc. @@ -53,7 +53,7 @@ */ #include -__KERNEL_RCSID(0, "$NetBSD: db_memrw.c,v 1.1 2012/05/07 17:45:29 jym Exp $"); +__KERNEL_RCSID(0, "$NetBSD: db_memrw.c,v 1.2 2016/05/12 06:45:16 maxv Exp $"); #include #include @@ -174,13 +174,15 @@ db_write_text(vaddr_t addr, size_t size, const char *data) void db_write_bytes(vaddr_t addr, size_t size, const char *data) { + extern int __rodata_start; extern int __data_start; char *dst; dst = (char *)addr; - /* If any part is in kernel text, use db_write_text() */ - if (addr >= KERNBASE && addr < (vaddr_t)&__data_start) { + /* If any part is in kernel text or rodata, use db_write_text() */ + if ((addr >= KERNBASE && addr < (vaddr_t)&__rodata_start) || + (addr >= (vaddr_t)&__rodata_start && addr < (vaddr_t)&__data_start)) { db_write_text(addr, size, data); return; } diff --git a/sys/arch/x86/x86/pmap.c b/sys/arch/x86/x86/pmap.c index da52c8754ceb..54f1b72d9db5 100644 --- a/sys/arch/x86/x86/pmap.c +++ b/sys/arch/x86/x86/pmap.c @@ -1,4 +1,4 @@ -/* $NetBSD: pmap.c,v 1.190 2016/01/26 14:34:50 hannken Exp $ */ +/* $NetBSD: pmap.c,v 1.191 2016/05/12 06:45:16 maxv Exp $ */ /*- * Copyright (c) 2008, 2010 The NetBSD Foundation, Inc. @@ -171,7 +171,7 @@ */ #include -__KERNEL_RCSID(0, "$NetBSD: pmap.c,v 1.190 2016/01/26 14:34:50 hannken Exp $"); +__KERNEL_RCSID(0, "$NetBSD: pmap.c,v 1.191 2016/05/12 06:45:16 maxv Exp $"); #include "opt_user_ldt.h" #include "opt_lockdebug.h" @@ -1301,7 +1301,7 @@ pmap_bootstrap(vaddr_t kva_start) if (cpu_feature[0] & CPUID_PSE) { paddr_t pa; - extern char __data_start; + extern char __rodata_start; lcr4(rcr4() | CR4_PSE); /* enable hardware (via %cr4) */ pmap_largepages = 1; /* enable software */ @@ -1317,9 +1317,9 @@ pmap_bootstrap(vaddr_t kva_start) /* * now, remap the kernel text using large pages. we * assume that the linker has properly aligned the - * .data segment to a NBPD_L2 boundary. + * .rodata segment to a NBPD_L2 boundary. */ - kva_end = rounddown((vaddr_t)&__data_start, NBPD_L1); + kva_end = rounddown((vaddr_t)&__rodata_start, NBPD_L1); for (pa = 0, kva = KERNBASE; kva + NBPD_L2 <= kva_end; kva += NBPD_L2, pa += NBPD_L2) { pde = &L2_BASE[pl2_i(kva)]; @@ -1331,7 +1331,7 @@ pmap_bootstrap(vaddr_t kva_start) aprint_normal("kernel text is mapped with %" PRIuPSIZE " large " "pages and %" PRIuPSIZE " normal pages\n", howmany(kva - KERNBASE, NBPD_L2), - howmany((vaddr_t)&__data_start - kva, NBPD_L1)); + howmany((vaddr_t)&__rodata_start - kva, NBPD_L1)); #endif /* defined(DEBUG) */ } #endif /* !XEN */