• Christophe Leroy's avatar
    powerpc/mm/32s: Use BATs for STRICT_KERNEL_RWX · 63b2bc61
    Christophe Leroy authored
    Today, STRICT_KERNEL_RWX is based on the use of regular pages
    to map kernel pages.
    
    On Book3s 32, it has three consequences:
    - Using pages instead of BAT for mapping kernel linear memory severely
    impacts performance.
    - Exec protection is not effective because no-execute cannot be set at
    page level (except on 603 which doesn't have hash tables)
    - Write protection is not effective because PP bits do not provide RO
    mode for kernel-only pages (except on 603 which handles it in software
    via PAGE_DIRTY)
    
    On the 603+, we have:
    - Independent IBAT and DBAT allowing limitation of exec parts.
    - NX bit can be set in segment registers to forbit execution on memory
    mapped by pages.
    - RO mode on DBATs even for kernel-only blocks.
    
    On the 601, there is nothing much we can do other than warn the user
    about it, because:
    - BATs are common to instructions and data.
    - BAT do not provide RO mode for kernel-only blocks.
    - segment registers don't have the NX bit.
    
    In order to use IBAT for exec protection, this patch:
    - Aligns _etext to BAT block sizes (128kb)
    - Set NX bit in kernel segment register (Except on vmalloc area when
    CONFIG_MODULES is selected)
    - Maps kernel text with IBATs.
    
    In order to use DBAT for exec protection, this patch:
    - Aligns RW DATA to BAT block sizes (4M)
    - Maps kernel RO area with write prohibited DBATs
    - Maps remaining memory with remaining DBATs
    
    Here is what we get with this patch on a 832x when activating
    STRICT_KERNEL_RWX:
    
    Symbols:
    c0000000 T _stext
    c0680000 R __start_rodata
    c0680000 R _etext
    c0800000 T __init_begin
    c0800000 T _sinittext
    
    ~# cat /sys/kernel/debug/block_address_translation
    ---[ Instruction Block Address Translation ]---
    0: 0xc0000000-0xc03fffff 0x00000000 Kernel EXEC coherent
    1: 0xc0400000-0xc05fffff 0x00400000 Kernel EXEC coherent
    2: 0xc0600000-0xc067ffff 0x00600000 Kernel EXEC coherent
    3:         -
    4:         -
    5:         -
    6:         -
    7:         -
    
    ---[ Data Block Address Translation ]---
    0: 0xc0000000-0xc07fffff 0x00000000 Kernel RO coherent
    1: 0xc0800000-0xc0ffffff 0x00800000 Kernel RW coherent
    2: 0xc1000000-0xc1ffffff 0x01000000 Kernel RW coherent
    3: 0xc2000000-0xc3ffffff 0x02000000 Kernel RW coherent
    4: 0xc4000000-0xc7ffffff 0x04000000 Kernel RW coherent
    5: 0xc8000000-0xcfffffff 0x08000000 Kernel RW coherent
    6: 0xd0000000-0xdfffffff 0x10000000 Kernel RW coherent
    7:         -
    
    ~# cat /sys/kernel/debug/segment_registers
    ---[ User Segments ]---
    0x00000000-0x0fffffff Kern key 1 User key 1 VSID 0xa085d0
    0x10000000-0x1fffffff Kern key 1 User key 1 VSID 0xa086e1
    0x20000000-0x2fffffff Kern key 1 User key 1 VSID 0xa087f2
    0x30000000-0x3fffffff Kern key 1 User key 1 VSID 0xa08903
    0x40000000-0x4fffffff Kern key 1 User key 1 VSID 0xa08a14
    0x50000000-0x5fffffff Kern key 1 User key 1 VSID 0xa08b25
    0x60000000-0x6fffffff Kern key 1 User key 1 VSID 0xa08c36
    0x70000000-0x7fffffff Kern key 1 User key 1 VSID 0xa08d47
    0x80000000-0x8fffffff Kern key 1 User key 1 VSID 0xa08e58
    0x90000000-0x9fffffff Kern key 1 User key 1 VSID 0xa08f69
    0xa0000000-0xafffffff Kern key 1 User key 1 VSID 0xa0907a
    0xb0000000-0xbfffffff Kern key 1 User key 1 VSID 0xa0918b
    
    ---[ Kernel Segments ]---
    0xc0000000-0xcfffffff Kern key 0 User key 1 No Exec VSID 0x000ccc
    0xd0000000-0xdfffffff Kern key 0 User key 1 No Exec VSID 0x000ddd
    0xe0000000-0xefffffff Kern key 0 User key 1 No Exec VSID 0x000eee
    0xf0000000-0xffffffff Kern key 0 User key 1 No Exec VSID 0x000fff
    
    Aligning _etext to 128kb allows to map up to 32Mb text with 8 IBATs:
    16Mb + 8Mb + 4Mb + 2Mb + 1Mb + 512kb + 256kb + 128kb (+ 128kb) = 32Mb
    (A 9th IBAT is unneeded as 32Mb would need only a single 32Mb block)
    
    Aligning data to 4M allows to map up to 512Mb data with 8 DBATs:
    16Mb + 8Mb + 4Mb + 4Mb + 32Mb + 64Mb + 128Mb + 256Mb = 512Mb
    
    Because some processors only have 4 BATs and because some targets need
    DBATs for mapping other areas, the following patch will allow to
    modify _etext and data alignment.
    Signed-off-by: default avatarChristophe Leroy <christophe.leroy@c-s.fr>
    Signed-off-by: default avatarChristophe Leroy <christophe.leroy@c-s.fr>
    Signed-off-by: default avatarMichael Ellerman <mpe@ellerman.id.au>
    63b2bc61
init_32.c 4.67 KB