Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/sys/arch There is an issue in the way the fillkpt macro sets...



details:   https://anonhg.NetBSD.org/src/rev/33fec94fc349
branches:  trunk
changeset: 345424:33fec94fc349
user:      maxv <maxv%NetBSD.org@localhost>
date:      Thu May 26 07:24:55 2016 +0000

description:
There is an issue in the way the fillkpt macro sets up pages on both
amd64 and i386.

The fillkpt loop is equivalent to the following:

        do {
                /* fill in the slot */
                /* increment %ebx to the next slot */
                /* increment %eax to the next pa */
        } while (%ecx > 0)

The issue here is that if %ecx = 0 (i.e., the chunk we are trying to
map is zero-sized), there is still one entry created in the page table.
The kernel expects the va<->pa translation to be linear in low memory.
If there is a zero-sized chunk, the dead entry creates a +4096 offset in
the virtual space, with two consecutive entries that point to the same
physical address. In other words, the mappings are not linear anymore,
which causes the kernel to die.

Before my recent changes, there were only two big chunks that were
mapped, and neither of these could be zero-sized. Now, with multiple,
fine-grained chunks, it is possible that the [SYMS]+[PRELOADED_MODULES]
chunk could be zero-sized.

[PRELOADED_MODULES] is almost never here, and [SYMS] is always here on
default kernels. Except for floppies, where the bootloader does not load
[SYMS].

Should fix PR 51148.

diffstat:

 sys/arch/amd64/amd64/locore.S |  12 +++++++++---
 sys/arch/i386/i386/locore.S   |  14 ++++++++++----
 2 files changed, 19 insertions(+), 7 deletions(-)

diffs (93 lines):

diff -r cf5d08c56575 -r 33fec94fc349 sys/arch/amd64/amd64/locore.S
--- a/sys/arch/amd64/amd64/locore.S     Thu May 26 05:04:46 2016 +0000
+++ b/sys/arch/amd64/amd64/locore.S     Thu May 26 07:24:55 2016 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: locore.S,v 1.93 2016/05/22 10:11:55 maxv Exp $ */
+/*     $NetBSD: locore.S,v 1.94 2016/05/26 07:24:55 maxv Exp $ */
 
 /*
  * Copyright-o-rama!
@@ -220,16 +220,21 @@
  * Each entry is 8 (PDE_SIZE) bytes long: we must set the 4 upper bytes to 0.
  */
 #define fillkpt        \
+       cmpl    $0,%ecx                 ;       /* zero-sized? */       \
+       je      2f                      ; \
 1:     movl    $0,(PDE_SIZE-4)(%ebx)   ;       /* upper 32 bits: 0 */  \
        movl    %eax,(%ebx)             ;       /* store phys addr */   \
        addl    $PDE_SIZE,%ebx          ;       /* next PTE/PDE */      \
        addl    $PAGE_SIZE,%eax         ;       /* next phys page */    \
-       loop    1b                      ;
+       loop    1b                      ; \
+2:                                     ;
 
 /*
  * fillkpt_nox - Same as fillkpt, but sets the NX/XD bit.
  */
 #define fillkpt_nox \
+       cmpl    $0,%ecx                 ;       /* zero-sized? */       \
+       je      2f                      ; \
        pushl   %ebp                    ; \
        movl    RELOC(nox_flag),%ebp    ; \
 1:     movl    %ebp,(PDE_SIZE-4)(%ebx) ;       /* upper 32 bits: NX */ \
@@ -237,7 +242,8 @@
        addl    $PDE_SIZE,%ebx          ;       /* next PTE/PDE */      \
        addl    $PAGE_SIZE,%eax         ;       /* next phys page */    \
        loop    1b                      ; \
-       popl    %ebp                    ;
+       popl    %ebp                    ; \
+2:                                     ;
 
 /*
  * killkpt - Destroy a kernel page table (long mode)
diff -r cf5d08c56575 -r 33fec94fc349 sys/arch/i386/i386/locore.S
--- a/sys/arch/i386/i386/locore.S       Thu May 26 05:04:46 2016 +0000
+++ b/sys/arch/i386/i386/locore.S       Thu May 26 07:24:55 2016 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: locore.S,v 1.124 2016/05/15 07:17:53 maxv Exp $        */
+/*     $NetBSD: locore.S,v 1.125 2016/05/26 07:24:55 maxv Exp $        */
 
 /*
  * Copyright-o-rama!
@@ -128,7 +128,7 @@
  */
 
 #include <machine/asm.h>
-__KERNEL_RCSID(0, "$NetBSD: locore.S,v 1.124 2016/05/15 07:17:53 maxv Exp $");
+__KERNEL_RCSID(0, "$NetBSD: locore.S,v 1.125 2016/05/26 07:24:55 maxv Exp $");
 
 #include "opt_compat_oldboot.h"
 #include "opt_copy_symtab.h"
@@ -192,16 +192,21 @@
  * instruction just clears the page table entry.
  */
 #define fillkpt        \
+       cmpl    $0,%ecx                 ;       /* zero-sized? */       \
+       je      2f                      ; \
 1:     movl    $0,(PDE_SIZE-4)(%ebx)   ;       /* upper 32 bits: 0 */  \
        movl    %eax,(%ebx)             ;       /* store phys addr */   \
        addl    $PDE_SIZE,%ebx          ;       /* next PTE/PDE */      \
        addl    $PAGE_SIZE,%eax         ;       /* next phys page */    \
-       loop    1b                      ;
+       loop    1b                      ; \
+2:                                     ;
 
 /*
  * fillkpt_nox - Same as fillkpt, but sets the NX/XD bit.
  */
 #define fillkpt_nox \
+       cmpl    $0,%ecx                 ;       /* zero-sized? */       \
+       je      2f                      ; \
        pushl   %ebp                    ; \
        movl    RELOC(nox_flag),%ebp    ; \
 1:     movl    %ebp,(PDE_SIZE-4)(%ebx) ;       /* upper 32 bits: NX */ \
@@ -209,7 +214,8 @@
        addl    $PDE_SIZE,%ebx          ;       /* next PTE/PDE */      \
        addl    $PAGE_SIZE,%eax         ;       /* next phys page */    \
        loop    1b                      ; \
-       popl    %ebp                    ;
+       popl    %ebp                    ; \
+2:                                     ;
 
 /*
  * killkpt - Destroy a kernel page table



Home | Main Index | Thread Index | Old Index