* [PATCH v4 07/16] powerpc/mm/32s: use _PAGE_EXEC in setbat()
From: Christophe Leroy @ 2019-02-21 8:04 UTC (permalink / raw)
To: Benjamin Herrenschmidt, Paul Mackerras, Michael Ellerman,
j.neuschaefer
Cc: linuxppc-dev, linux-kernel
In-Reply-To: <cover.1550692943.git.christophe.leroy@c-s.fr>
Do not set IBAT when setbat() is called without _PAGE_EXEC
Signed-off-by: Christophe Leroy <christophe.leroy@c-s.fr>
---
arch/powerpc/mm/ppc_mmu_32.c | 10 ++++++----
1 file changed, 6 insertions(+), 4 deletions(-)
diff --git a/arch/powerpc/mm/ppc_mmu_32.c b/arch/powerpc/mm/ppc_mmu_32.c
index 5fc59b195fef..ff8580c6ab11 100644
--- a/arch/powerpc/mm/ppc_mmu_32.c
+++ b/arch/powerpc/mm/ppc_mmu_32.c
@@ -131,6 +131,7 @@ unsigned long __init mmu_mapin_ram(unsigned long base, unsigned long top)
* Set up one of the I/D BAT (block address translation) register pairs.
* The parameters are not checked; in particular size must be a power
* of 2 between 128k and 256M.
+ * On 603+, only set IBAT when _PAGE_EXEC is set
*/
void __init setbat(int index, unsigned long virt, phys_addr_t phys,
unsigned int size, pgprot_t prot)
@@ -157,11 +158,12 @@ void __init setbat(int index, unsigned long virt, phys_addr_t phys,
bat[1].batu |= 1; /* Vp = 1 */
if (flags & _PAGE_GUARDED) {
/* G bit must be zero in IBATs */
- bat[0].batu = bat[0].batl = 0;
- } else {
- /* make IBAT same as DBAT */
- bat[0] = bat[1];
+ flags &= ~_PAGE_EXEC;
}
+ if (flags & _PAGE_EXEC)
+ bat[0] = bat[1];
+ else
+ bat[0].batu = bat[0].batl = 0;
} else {
/* 601 cpu */
if (bl > BL_8M)
--
2.13.3
^ permalink raw reply related
* [PATCH v4 08/16] powerpc/32: add helper to write into segment registers
From: Christophe Leroy @ 2019-02-21 8:04 UTC (permalink / raw)
To: Benjamin Herrenschmidt, Paul Mackerras, Michael Ellerman,
j.neuschaefer
Cc: linuxppc-dev, linux-kernel
In-Reply-To: <cover.1550692943.git.christophe.leroy@c-s.fr>
This patch add an helper which wraps 'mtsrin' instruction
to write into segment registers.
Signed-off-by: Christophe Leroy <christophe.leroy@c-s.fr>
---
arch/powerpc/include/asm/reg.h | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/arch/powerpc/include/asm/reg.h b/arch/powerpc/include/asm/reg.h
index 1c98ef1f2d5b..a70cbaf5c26f 100644
--- a/arch/powerpc/include/asm/reg.h
+++ b/arch/powerpc/include/asm/reg.h
@@ -1425,6 +1425,11 @@ static inline void msr_check_and_clear(unsigned long bits)
#define mfsrin(v) ({unsigned int rval; \
asm volatile("mfsrin %0,%1" : "=r" (rval) : "r" (v)); \
rval;})
+
+static inline void mtsrin(u32 val, u32 idx)
+{
+ asm volatile("mtsrin %0, %1" : : "r" (val), "r" (idx));
+}
#endif
#define proc_trap() asm volatile("trap")
--
2.13.3
^ permalink raw reply related
* [PATCH v4 09/16] powerpc/mmu: add is_strict_kernel_rwx() helper
From: Christophe Leroy @ 2019-02-21 8:04 UTC (permalink / raw)
To: Benjamin Herrenschmidt, Paul Mackerras, Michael Ellerman,
j.neuschaefer
Cc: linuxppc-dev, linux-kernel
In-Reply-To: <cover.1550692943.git.christophe.leroy@c-s.fr>
Add a helper to know whether STRICT_KERNEL_RWX is enabled.
This is based on rodata_enabled flag which is defined only
when CONFIG_STRICT_KERNEL_RWX is selected.
Signed-off-by: Christophe Leroy <christophe.leroy@c-s.fr>
---
arch/powerpc/include/asm/mmu.h | 11 +++++++++++
arch/powerpc/mm/init_32.c | 4 +---
2 files changed, 12 insertions(+), 3 deletions(-)
diff --git a/arch/powerpc/include/asm/mmu.h b/arch/powerpc/include/asm/mmu.h
index 25607604a7a5..f5e27f4a0c29 100644
--- a/arch/powerpc/include/asm/mmu.h
+++ b/arch/powerpc/include/asm/mmu.h
@@ -289,6 +289,17 @@ static inline u16 get_mm_addr_key(struct mm_struct *mm, unsigned long address)
}
#endif /* CONFIG_PPC_MEM_KEYS */
+#ifdef CONFIG_STRICT_KERNEL_RWX
+static inline bool strict_kernel_rwx_enabled(void)
+{
+ return rodata_enabled;
+}
+#else
+static inline bool strict_kernel_rwx_enabled(void)
+{
+ return false;
+}
+#endif
#endif /* !__ASSEMBLY__ */
/* The kernel use the constants below to index in the page sizes array.
diff --git a/arch/powerpc/mm/init_32.c b/arch/powerpc/mm/init_32.c
index 3e59e5d64b01..ee5a430b9a18 100644
--- a/arch/powerpc/mm/init_32.c
+++ b/arch/powerpc/mm/init_32.c
@@ -108,12 +108,10 @@ static void __init MMU_setup(void)
__map_without_bats = 1;
__map_without_ltlbs = 1;
}
-#ifdef CONFIG_STRICT_KERNEL_RWX
- if (rodata_enabled) {
+ if (strict_kernel_rwx_enabled()) {
__map_without_bats = 1;
__map_without_ltlbs = 1;
}
-#endif
}
/*
--
2.13.3
^ permalink raw reply related
* [PATCH v4 11/16] powerpc/kconfig: define CONFIG_DATA_SHIFT and CONFIG_ETEXT_SHIFT
From: Christophe Leroy @ 2019-02-21 8:04 UTC (permalink / raw)
To: Benjamin Herrenschmidt, Paul Mackerras, Michael Ellerman,
j.neuschaefer
Cc: linuxppc-dev, linux-kernel
In-Reply-To: <cover.1550692943.git.christophe.leroy@c-s.fr>
CONFIG_STRICT_KERNEL_RWX requires a special alignment
for DATA for some subarches. Today it is just defined
as an #ifdef in vmlinux.lds.S
In order to get more flexibility, this patch moves the
definition of this alignment in Kconfig
On some subarches, CONFIG_STRICT_KERNEL_RWX will
require a special alignment of _etext.
This patch also adds a configuration item for it in Kconfig
Signed-off-by: Christophe Leroy <christophe.leroy@c-s.fr>
---
arch/powerpc/Kconfig | 9 +++++++++
arch/powerpc/kernel/vmlinux.lds.S | 9 +++------
2 files changed, 12 insertions(+), 6 deletions(-)
diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig
index 01ac44d5d4b4..79a50276437c 100644
--- a/arch/powerpc/Kconfig
+++ b/arch/powerpc/Kconfig
@@ -728,6 +728,15 @@ config THREAD_SHIFT
Used to define the stack size. The default is almost always what you
want. Only change this if you know what you are doing.
+config ETEXT_SHIFT
+ int
+ default PPC_PAGE_SHIFT
+
+config DATA_SHIFT
+ int
+ default 24 if STRICT_KERNEL_RWX && PPC64
+ default PPC_PAGE_SHIFT
+
config FORCE_MAX_ZONEORDER
int "Maximum zone order"
range 8 9 if PPC64 && PPC_64K_PAGES
diff --git a/arch/powerpc/kernel/vmlinux.lds.S b/arch/powerpc/kernel/vmlinux.lds.S
index c3efb972c8c1..060a1acd7c6d 100644
--- a/arch/powerpc/kernel/vmlinux.lds.S
+++ b/arch/powerpc/kernel/vmlinux.lds.S
@@ -12,11 +12,8 @@
#include <asm/cache.h>
#include <asm/thread_info.h>
-#if defined(CONFIG_STRICT_KERNEL_RWX) && !defined(CONFIG_PPC32)
-#define STRICT_ALIGN_SIZE (1 << 24)
-#else
-#define STRICT_ALIGN_SIZE PAGE_SIZE
-#endif
+#define STRICT_ALIGN_SIZE (1 << CONFIG_DATA_SHIFT)
+#define ETEXT_ALIGN_SIZE (1 << CONFIG_ETEXT_SHIFT)
ENTRY(_stext)
@@ -131,7 +128,7 @@ SECTIONS
} :kernel
- . = ALIGN(PAGE_SIZE);
+ . = ALIGN(ETEXT_ALIGN_SIZE);
_etext = .;
PROVIDE32 (etext = .);
--
2.13.3
^ permalink raw reply related
* [PATCH v4 12/16] powerpc/mm/32s: add setibat() clearibat() and update_bats()
From: Christophe Leroy @ 2019-02-21 8:05 UTC (permalink / raw)
To: Benjamin Herrenschmidt, Paul Mackerras, Michael Ellerman,
j.neuschaefer
Cc: linuxppc-dev, linux-kernel
In-Reply-To: <cover.1550692943.git.christophe.leroy@c-s.fr>
setibat() and clearibat() allows to manipulate IBATs independently
of DBATs.
update_bats() allows to update bats after init. This is done
with MMU off.
Signed-off-by: Christophe Leroy <christophe.leroy@c-s.fr>
---
arch/powerpc/include/asm/book3s/32/mmu-hash.h | 2 ++
arch/powerpc/kernel/head_32.S | 35 +++++++++++++++++++++++++++
arch/powerpc/mm/ppc_mmu_32.c | 32 ++++++++++++++++++++++++
3 files changed, 69 insertions(+)
diff --git a/arch/powerpc/include/asm/book3s/32/mmu-hash.h b/arch/powerpc/include/asm/book3s/32/mmu-hash.h
index 0c261ba2c826..5cb588395fdc 100644
--- a/arch/powerpc/include/asm/book3s/32/mmu-hash.h
+++ b/arch/powerpc/include/asm/book3s/32/mmu-hash.h
@@ -92,6 +92,8 @@ typedef struct {
unsigned long vdso_base;
} mm_context_t;
+void update_bats(void);
+
/* patch sites */
extern s32 patch__hash_page_A0, patch__hash_page_A1, patch__hash_page_A2;
extern s32 patch__hash_page_B, patch__hash_page_C;
diff --git a/arch/powerpc/kernel/head_32.S b/arch/powerpc/kernel/head_32.S
index 05b08db3901d..51cc40a632e0 100644
--- a/arch/powerpc/kernel/head_32.S
+++ b/arch/powerpc/kernel/head_32.S
@@ -1105,6 +1105,41 @@ BEGIN_MMU_FTR_SECTION
END_MMU_FTR_SECTION_IFSET(MMU_FTR_USE_HIGH_BATS)
blr
+_ENTRY(update_bats)
+ lis r4, 1f@h
+ ori r4, r4, 1f@l
+ tophys(r4, r4)
+ mfmsr r6
+ mflr r7
+ li r3, MSR_KERNEL & ~(MSR_IR | MSR_DR)
+ rlwinm r0, r6, 0, ~MSR_RI
+ rlwinm r0, r0, 0, ~MSR_EE
+ mtmsr r0
+ mtspr SPRN_SRR0, r4
+ mtspr SPRN_SRR1, r3
+ SYNC
+ RFI
+1: bl clear_bats
+ lis r3, BATS@ha
+ addi r3, r3, BATS@l
+ tophys(r3, r3)
+ LOAD_BAT(0, r3, r4, r5)
+ LOAD_BAT(1, r3, r4, r5)
+ LOAD_BAT(2, r3, r4, r5)
+ LOAD_BAT(3, r3, r4, r5)
+BEGIN_MMU_FTR_SECTION
+ LOAD_BAT(4, r3, r4, r5)
+ LOAD_BAT(5, r3, r4, r5)
+ LOAD_BAT(6, r3, r4, r5)
+ LOAD_BAT(7, r3, r4, r5)
+END_MMU_FTR_SECTION_IFSET(MMU_FTR_USE_HIGH_BATS)
+ li r3, MSR_KERNEL & ~(MSR_IR | MSR_DR | MSR_RI)
+ mtmsr r3
+ mtspr SPRN_SRR0, r7
+ mtspr SPRN_SRR1, r6
+ SYNC
+ RFI
+
flush_tlbs:
lis r10, 0x40
1: addic. r10, r10, -0x1000
diff --git a/arch/powerpc/mm/ppc_mmu_32.c b/arch/powerpc/mm/ppc_mmu_32.c
index ff8580c6ab11..66f1319e8e20 100644
--- a/arch/powerpc/mm/ppc_mmu_32.c
+++ b/arch/powerpc/mm/ppc_mmu_32.c
@@ -106,6 +106,38 @@ static unsigned int block_size(unsigned long base, unsigned long top)
return min3(max_size, 1U << base_shift, 1U << block_shift);
}
+/*
+ * Set up one of the IBAT (block address translation) register pairs.
+ * The parameters are not checked; in particular size must be a power
+ * of 2 between 128k and 256M.
+ * Only for 603+ ...
+ */
+static void setibat(int index, unsigned long virt, phys_addr_t phys,
+ unsigned int size, pgprot_t prot)
+{
+ unsigned int bl = (size >> 17) - 1;
+ int wimgxpp;
+ struct ppc_bat *bat = BATS[index];
+ unsigned long flags = pgprot_val(prot);
+
+ if (!cpu_has_feature(CPU_FTR_NEED_COHERENT))
+ flags &= ~_PAGE_COHERENT;
+
+ wimgxpp = (flags & _PAGE_COHERENT) | (_PAGE_EXEC ? BPP_RX : BPP_XX);
+ bat[0].batu = virt | (bl << 2) | 2; /* Vs=1, Vp=0 */
+ bat[0].batl = BAT_PHYS_ADDR(phys) | wimgxpp;
+ if (flags & _PAGE_USER)
+ bat[0].batu |= 1; /* Vp = 1 */
+}
+
+static void clearibat(int index)
+{
+ struct ppc_bat *bat = BATS[index];
+
+ bat[0].batu = 0;
+ bat[0].batl = 0;
+}
+
unsigned long __init mmu_mapin_ram(unsigned long base, unsigned long top)
{
int idx;
--
2.13.3
^ permalink raw reply related
* [PATCH v4 10/16] powerpc/kconfig: define PAGE_SHIFT inside Kconfig
From: Christophe Leroy @ 2019-02-21 8:04 UTC (permalink / raw)
To: Benjamin Herrenschmidt, Paul Mackerras, Michael Ellerman,
j.neuschaefer
Cc: linuxppc-dev, linux-kernel
In-Reply-To: <cover.1550692943.git.christophe.leroy@c-s.fr>
This patch defined CONFIG_PPC_PAGE_SHIFT in order
to be able to use PAGE_SHIFT value inside Kconfig.
Signed-off-by: Christophe Leroy <christophe.leroy@c-s.fr>
---
arch/powerpc/Kconfig | 7 +++++++
arch/powerpc/include/asm/page.h | 13 ++-----------
2 files changed, 9 insertions(+), 11 deletions(-)
diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig
index 08908219fba9..01ac44d5d4b4 100644
--- a/arch/powerpc/Kconfig
+++ b/arch/powerpc/Kconfig
@@ -711,6 +711,13 @@ config PPC_256K_PAGES
endchoice
+config PPC_PAGE_SHIFT
+ int
+ default 18 if PPC_256K_PAGES
+ default 16 if PPC_64K_PAGES
+ default 14 if PPC_16K_PAGES
+ default 12
+
config THREAD_SHIFT
int "Thread shift" if EXPERT
range 13 15
diff --git a/arch/powerpc/include/asm/page.h b/arch/powerpc/include/asm/page.h
index aa4497175bd3..ed870468ef6f 100644
--- a/arch/powerpc/include/asm/page.h
+++ b/arch/powerpc/include/asm/page.h
@@ -20,20 +20,11 @@
/*
* On regular PPC32 page size is 4K (but we support 4K/16K/64K/256K pages
- * on PPC44x). For PPC64 we support either 4K or 64K software
+ * on PPC44x and 4K/16K on 8xx). For PPC64 we support either 4K or 64K software
* page size. When using 64K pages however, whether we are really supporting
* 64K pages in HW or not is irrelevant to those definitions.
*/
-#if defined(CONFIG_PPC_256K_PAGES)
-#define PAGE_SHIFT 18
-#elif defined(CONFIG_PPC_64K_PAGES)
-#define PAGE_SHIFT 16
-#elif defined(CONFIG_PPC_16K_PAGES)
-#define PAGE_SHIFT 14
-#else
-#define PAGE_SHIFT 12
-#endif
-
+#define PAGE_SHIFT CONFIG_PPC_PAGE_SHIFT
#define PAGE_SIZE (ASM_CONST(1) << PAGE_SHIFT)
#ifndef __ASSEMBLY__
--
2.13.3
^ permalink raw reply related
* [PATCH v4 13/16] powerpc/mm/32s: Use BATs for STRICT_KERNEL_RWX
From: Christophe Leroy @ 2019-02-21 8:05 UTC (permalink / raw)
To: Benjamin Herrenschmidt, Paul Mackerras, Michael Ellerman,
j.neuschaefer
Cc: linuxppc-dev, linux-kernel
In-Reply-To: <cover.1550692943.git.christophe.leroy@c-s.fr>
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: Christophe Leroy <christophe.leroy@c-s.fr>
Signed-off-by: Christophe Leroy <christophe.leroy@c-s.fr>
---
arch/powerpc/Kconfig | 2 +
arch/powerpc/include/asm/book3s/32/pgtable.h | 11 ++++
arch/powerpc/mm/init_32.c | 4 +-
arch/powerpc/mm/mmu_decl.h | 8 +++
arch/powerpc/mm/pgtable_32.c | 10 +++-
arch/powerpc/mm/ppc_mmu_32.c | 87 ++++++++++++++++++++++++++--
6 files changed, 112 insertions(+), 10 deletions(-)
diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig
index 79a50276437c..26ddea487d72 100644
--- a/arch/powerpc/Kconfig
+++ b/arch/powerpc/Kconfig
@@ -730,11 +730,13 @@ config THREAD_SHIFT
config ETEXT_SHIFT
int
+ default 17 if STRICT_KERNEL_RWX && PPC_BOOK3S_32
default PPC_PAGE_SHIFT
config DATA_SHIFT
int
default 24 if STRICT_KERNEL_RWX && PPC64
+ default 22 if STRICT_KERNEL_RWX && PPC_BOOK3S_32
default PPC_PAGE_SHIFT
config FORCE_MAX_ZONEORDER
diff --git a/arch/powerpc/include/asm/book3s/32/pgtable.h b/arch/powerpc/include/asm/book3s/32/pgtable.h
index 49d76adb9bc5..aa8406b8f7ba 100644
--- a/arch/powerpc/include/asm/book3s/32/pgtable.h
+++ b/arch/powerpc/include/asm/book3s/32/pgtable.h
@@ -174,7 +174,18 @@ static inline bool pte_user(pte_t pte)
* of RAM. -- Cort
*/
#define VMALLOC_OFFSET (0x1000000) /* 16M */
+
+/*
+ * With CONFIG_STRICT_KERNEL_RWX, kernel segments are set NX. But when modules
+ * are used, NX cannot be set on VMALLOC space. So vmalloc VM space and linear
+ * memory shall not share segments.
+ */
+#if defined(CONFIG_STRICT_KERNEL_RWX) && defined(CONFIG_MODULES)
+#define VMALLOC_START ((_ALIGN((long)high_memory, 256L << 20) + VMALLOC_OFFSET) & \
+ ~(VMALLOC_OFFSET - 1))
+#else
#define VMALLOC_START ((((long)high_memory + VMALLOC_OFFSET) & ~(VMALLOC_OFFSET-1)))
+#endif
#define VMALLOC_END ioremap_bot
#ifndef __ASSEMBLY__
diff --git a/arch/powerpc/mm/init_32.c b/arch/powerpc/mm/init_32.c
index ee5a430b9a18..bc28995a37ea 100644
--- a/arch/powerpc/mm/init_32.c
+++ b/arch/powerpc/mm/init_32.c
@@ -108,10 +108,8 @@ static void __init MMU_setup(void)
__map_without_bats = 1;
__map_without_ltlbs = 1;
}
- if (strict_kernel_rwx_enabled()) {
- __map_without_bats = 1;
+ if (strict_kernel_rwx_enabled())
__map_without_ltlbs = 1;
- }
}
/*
diff --git a/arch/powerpc/mm/mmu_decl.h b/arch/powerpc/mm/mmu_decl.h
index 61730023dde3..98fc94affc29 100644
--- a/arch/powerpc/mm/mmu_decl.h
+++ b/arch/powerpc/mm/mmu_decl.h
@@ -165,3 +165,11 @@ unsigned long p_block_mapped(phys_addr_t pa);
static inline phys_addr_t v_block_mapped(unsigned long va) { return 0; }
static inline unsigned long p_block_mapped(phys_addr_t pa) { return 0; }
#endif
+
+#if defined(CONFIG_PPC_BOOK3S_32)
+void mmu_mark_initmem_nx(void);
+void mmu_mark_rodata_ro(void);
+#else
+static inline void mmu_mark_initmem_nx(void) { }
+static inline void mmu_mark_rodata_ro(void) { }
+#endif
diff --git a/arch/powerpc/mm/pgtable_32.c b/arch/powerpc/mm/pgtable_32.c
index f54922f0d792..0ec1b1bcbaf6 100644
--- a/arch/powerpc/mm/pgtable_32.c
+++ b/arch/powerpc/mm/pgtable_32.c
@@ -353,7 +353,10 @@ void mark_initmem_nx(void)
unsigned long numpages = PFN_UP((unsigned long)_einittext) -
PFN_DOWN((unsigned long)_sinittext);
- change_page_attr(page, numpages, PAGE_KERNEL);
+ if (v_block_mapped((unsigned long)_stext) + 1)
+ mmu_mark_initmem_nx();
+ else
+ change_page_attr(page, numpages, PAGE_KERNEL);
}
#ifdef CONFIG_STRICT_KERNEL_RWX
@@ -362,6 +365,11 @@ void mark_rodata_ro(void)
struct page *page;
unsigned long numpages;
+ if (v_block_mapped((unsigned long)_sinittext)) {
+ mmu_mark_rodata_ro();
+ return;
+ }
+
page = virt_to_page(_stext);
numpages = PFN_UP((unsigned long)_etext) -
PFN_DOWN((unsigned long)_stext);
diff --git a/arch/powerpc/mm/ppc_mmu_32.c b/arch/powerpc/mm/ppc_mmu_32.c
index 66f1319e8e20..d80622dccfa0 100644
--- a/arch/powerpc/mm/ppc_mmu_32.c
+++ b/arch/powerpc/mm/ppc_mmu_32.c
@@ -32,6 +32,7 @@
#include <asm/mmu.h>
#include <asm/machdep.h>
#include <asm/code-patching.h>
+#include <asm/sections.h>
#include "mmu_decl.h"
@@ -138,15 +139,10 @@ static void clearibat(int index)
bat[0].batl = 0;
}
-unsigned long __init mmu_mapin_ram(unsigned long base, unsigned long top)
+static unsigned long __init __mmu_mapin_ram(unsigned long base, unsigned long top)
{
int idx;
- if (__map_without_bats) {
- printk(KERN_DEBUG "RAM mapped without BATs\n");
- return base;
- }
-
while ((idx = find_free_bat()) != -1 && base != top) {
unsigned int size = block_size(base, top);
@@ -159,6 +155,85 @@ unsigned long __init mmu_mapin_ram(unsigned long base, unsigned long top)
return base;
}
+unsigned long __init mmu_mapin_ram(unsigned long base, unsigned long top)
+{
+ int done;
+ unsigned long border = (unsigned long)__init_begin - PAGE_OFFSET;
+
+ if (__map_without_bats) {
+ pr_debug("RAM mapped without BATs\n");
+ return base;
+ }
+
+ if (!strict_kernel_rwx_enabled() || base >= border || top <= border)
+ return __mmu_mapin_ram(base, top);
+
+ done = __mmu_mapin_ram(base, border);
+ if (done != border - base)
+ return done;
+
+ return done + __mmu_mapin_ram(border, top);
+}
+
+void mmu_mark_initmem_nx(void)
+{
+ int nb = mmu_has_feature(MMU_FTR_USE_HIGH_BATS) ? 8 : 4;
+ int i;
+ unsigned long base = (unsigned long)_stext - PAGE_OFFSET;
+ unsigned long top = (unsigned long)_etext - PAGE_OFFSET;
+ unsigned long size;
+
+ if (cpu_has_feature(CPU_FTR_601))
+ return;
+
+ for (i = 0; i < nb - 1 && base < top && top - base > (128 << 10);) {
+ size = block_size(base, top);
+ setibat(i++, PAGE_OFFSET + base, base, size, PAGE_KERNEL_TEXT);
+ base += size;
+ }
+ if (base < top) {
+ size = block_size(base, top);
+ size = max(size, 128UL << 10);
+ if ((top - base) > size) {
+ if (strict_kernel_rwx_enabled())
+ pr_warn("Kernel _etext not properly aligned\n");
+ size <<= 1;
+ }
+ setibat(i++, PAGE_OFFSET + base, base, size, PAGE_KERNEL_TEXT);
+ base += size;
+ }
+ for (; i < nb; i++)
+ clearibat(i);
+
+ update_bats();
+
+ for (i = TASK_SIZE >> 28; i < 16; i++) {
+ /* Do not set NX on VM space for modules */
+ if (IS_ENABLED(CONFIG_MODULES) &&
+ (VMALLOC_START & 0xf0000000) == i << 28)
+ break;
+ mtsrin(mfsrin(i << 28) | 0x10000000, i << 28);
+ }
+}
+
+void mmu_mark_rodata_ro(void)
+{
+ int nb = mmu_has_feature(MMU_FTR_USE_HIGH_BATS) ? 8 : 4;
+ int i;
+
+ if (cpu_has_feature(CPU_FTR_601))
+ return;
+
+ for (i = 0; i < nb; i++) {
+ struct ppc_bat *bat = BATS[i];
+
+ if (bat_addrs[i].start < (unsigned long)__init_begin)
+ bat[1].batl = (bat[1].batl & ~BPP_RW) | BPP_RX;
+ }
+
+ update_bats();
+}
+
/*
* Set up one of the I/D BAT (block address translation) register pairs.
* The parameters are not checked; in particular size must be a power
--
2.13.3
^ permalink raw reply related
* [PATCH v4 14/16] powerpc/kconfig: make _etext and data areas alignment configurable on Book3s 32
From: Christophe Leroy @ 2019-02-21 8:05 UTC (permalink / raw)
To: Benjamin Herrenschmidt, Paul Mackerras, Michael Ellerman,
j.neuschaefer
Cc: linuxppc-dev, linux-kernel
In-Reply-To: <cover.1550692943.git.christophe.leroy@c-s.fr>
Depending on the number of available BATs for mapping the different
kernel areas, it might be needed to increase the alignment of _etext
and/or of data areas.
This patchs allows the user to do it via Kconfig.
Signed-off-by: Christophe Leroy <christophe.leroy@c-s.fr>
---
arch/powerpc/Kconfig | 32 ++++++++++++++++++++++++++++++--
1 file changed, 30 insertions(+), 2 deletions(-)
diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig
index 26ddea487d72..127259179b4d 100644
--- a/arch/powerpc/Kconfig
+++ b/arch/powerpc/Kconfig
@@ -728,16 +728,44 @@ config THREAD_SHIFT
Used to define the stack size. The default is almost always what you
want. Only change this if you know what you are doing.
+config ETEXT_SHIFT_BOOL
+ bool "Set custom etext alignment" if STRICT_KERNEL_RWX && PPC_BOOK3S_32
+ depends on ADVANCED_OPTIONS
+ help
+ This option allows you to set the kernel end of text alignment. When
+ RAM is mapped by blocks, the alignment needs to fit the size and
+ number of possible blocks. The default should be OK for most configs.
+
+ Say N here unless you know what you are doing.
+
config ETEXT_SHIFT
- int
+ int "_etext shift" if ETEXT_SHIFT_BOOL
+ range 17 28 if STRICT_KERNEL_RWX && PPC_BOOK3S_32
default 17 if STRICT_KERNEL_RWX && PPC_BOOK3S_32
default PPC_PAGE_SHIFT
+ help
+ On Book3S 32 (603+), IBATs are used to map kernel text.
+ Smaller is the alignment, greater is the number of necessary IBATs.
+
+config DATA_SHIFT_BOOL
+ bool "Set custom data alignment" if STRICT_KERNEL_RWX && PPC_BOOK3S_32
+ depends on ADVANCED_OPTIONS
+ help
+ This option allows you to set the kernel data alignment. When
+ RAM is mapped by blocks, the alignment needs to fit the size and
+ number of possible blocks. The default should be OK for most configs.
+
+ Say N here unless you know what you are doing.
config DATA_SHIFT
- int
+ int "Data shift" if DATA_SHIFT_BOOL
default 24 if STRICT_KERNEL_RWX && PPC64
+ range 17 28 if STRICT_KERNEL_RWX && PPC_BOOK3S_32
default 22 if STRICT_KERNEL_RWX && PPC_BOOK3S_32
default PPC_PAGE_SHIFT
+ help
+ On Book3S 32 (603+), DBATs are used to map kernel text and rodata RO.
+ Smaller is the alignment, greater is the number of necessary DBATs.
config FORCE_MAX_ZONEORDER
int "Maximum zone order"
--
2.13.3
^ permalink raw reply related
* [PATCH v4 15/16] powerpc/8xx: don't disable large TLBs with CONFIG_STRICT_KERNEL_RWX
From: Christophe Leroy @ 2019-02-21 8:05 UTC (permalink / raw)
To: Benjamin Herrenschmidt, Paul Mackerras, Michael Ellerman,
j.neuschaefer
Cc: linuxppc-dev, linux-kernel
In-Reply-To: <cover.1550692943.git.christophe.leroy@c-s.fr>
This patch implements handling of STRICT_KERNEL_RWX with
large TLBs directly in the TLB miss handlers.
To do so, etext and sinittext are aligned on 512kB boundaries
and the miss handlers use 512kB pages instead of 8Mb pages for
addresses close to the boundaries.
It sets RO PP flags for addresses under sinittext.
Signed-off-by: Christophe Leroy <christophe.leroy@c-s.fr>
---
arch/powerpc/Kconfig | 2 ++
arch/powerpc/include/asm/nohash/32/mmu-8xx.h | 3 +-
arch/powerpc/kernel/head_8xx.S | 54 +++++++++++++++++++++-------
arch/powerpc/mm/8xx_mmu.c | 31 +++++++++++++++-
arch/powerpc/mm/init_32.c | 2 +-
arch/powerpc/mm/mmu_decl.h | 2 +-
6 files changed, 78 insertions(+), 16 deletions(-)
diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig
index 127259179b4d..271f13ac23d4 100644
--- a/arch/powerpc/Kconfig
+++ b/arch/powerpc/Kconfig
@@ -742,6 +742,7 @@ config ETEXT_SHIFT
int "_etext shift" if ETEXT_SHIFT_BOOL
range 17 28 if STRICT_KERNEL_RWX && PPC_BOOK3S_32
default 17 if STRICT_KERNEL_RWX && PPC_BOOK3S_32
+ default 19 if STRICT_KERNEL_RWX && PPC_8xx
default PPC_PAGE_SHIFT
help
On Book3S 32 (603+), IBATs are used to map kernel text.
@@ -762,6 +763,7 @@ config DATA_SHIFT
default 24 if STRICT_KERNEL_RWX && PPC64
range 17 28 if STRICT_KERNEL_RWX && PPC_BOOK3S_32
default 22 if STRICT_KERNEL_RWX && PPC_BOOK3S_32
+ default 19 if STRICT_KERNEL_RWX && PPC_8xx
default PPC_PAGE_SHIFT
help
On Book3S 32 (603+), DBATs are used to map kernel text and rodata RO.
diff --git a/arch/powerpc/include/asm/nohash/32/mmu-8xx.h b/arch/powerpc/include/asm/nohash/32/mmu-8xx.h
index b0f764c827c0..0a1a3fc54e54 100644
--- a/arch/powerpc/include/asm/nohash/32/mmu-8xx.h
+++ b/arch/powerpc/include/asm/nohash/32/mmu-8xx.h
@@ -231,9 +231,10 @@ static inline unsigned int mmu_psize_to_shift(unsigned int mmu_psize)
}
/* patch sites */
-extern s32 patch__itlbmiss_linmem_top;
+extern s32 patch__itlbmiss_linmem_top, patch__itlbmiss_linmem_top8;
extern s32 patch__dtlbmiss_linmem_top, patch__dtlbmiss_immr_jmp;
extern s32 patch__fixupdar_linmem_top;
+extern s32 patch__dtlbmiss_romem_top, patch__dtlbmiss_romem_top8;
extern s32 patch__itlbmiss_exit_1, patch__itlbmiss_exit_2;
extern s32 patch__dtlbmiss_exit_1, patch__dtlbmiss_exit_2, patch__dtlbmiss_exit_3;
diff --git a/arch/powerpc/kernel/head_8xx.S b/arch/powerpc/kernel/head_8xx.S
index 20cc816b3508..29c9289bc1d4 100644
--- a/arch/powerpc/kernel/head_8xx.S
+++ b/arch/powerpc/kernel/head_8xx.S
@@ -292,6 +292,17 @@ SystemCall:
*/
EXCEPTION(0x1000, SoftEmu, program_check_exception, EXC_XFER_STD)
+/* Called from DataStoreTLBMiss when perf TLB misses events are activated */
+#ifdef CONFIG_PERF_EVENTS
+ patch_site 0f, patch__dtlbmiss_perf
+0: lwz r10, (dtlb_miss_counter - PAGE_OFFSET)@l(0)
+ addi r10, r10, 1
+ stw r10, (dtlb_miss_counter - PAGE_OFFSET)@l(0)
+ mfspr r10, SPRN_SPRG_SCRATCH0
+ mfspr r11, SPRN_SPRG_SCRATCH1
+ rfi
+#endif
+
. = 0x1100
/*
* For the MPC8xx, this is a software tablewalk to load the instruction
@@ -405,10 +416,20 @@ InstructionTLBMiss:
#ifndef CONFIG_PIN_TLB_TEXT
ITLBMissLinear:
mtcr r11
+#ifdef CONFIG_STRICT_KERNEL_RWX
+ patch_site 0f, patch__itlbmiss_linmem_top8
+
+ mfspr r10, SPRN_SRR0
+0: subis r11, r10, (PAGE_OFFSET - 0x80000000)@ha
+ rlwinm r11, r11, 4, MI_PS8MEG ^ MI_PS512K
+ ori r11, r11, MI_PS512K | MI_SVALID
+ rlwinm r10, r10, 0, 0x0ff80000 /* 8xx supports max 256Mb RAM */
+#else
/* Set 8M byte page and mark it valid */
li r11, MI_PS8MEG | MI_SVALID
- mtspr SPRN_MI_TWC, r11
rlwinm r10, r10, 20, 0x0f800000 /* 8xx supports max 256Mb RAM */
+#endif
+ mtspr SPRN_MI_TWC, r11
ori r10, r10, 0xf0 | MI_SPS16K | _PAGE_SH | _PAGE_DIRTY | \
_PAGE_PRESENT
mtspr SPRN_MI_RPN, r10 /* Update TLB entry */
@@ -494,16 +515,6 @@ DataStoreTLBMiss:
rfi
patch_site 0b, patch__dtlbmiss_exit_1
-#ifdef CONFIG_PERF_EVENTS
- patch_site 0f, patch__dtlbmiss_perf
-0: lwz r10, (dtlb_miss_counter - PAGE_OFFSET)@l(0)
- addi r10, r10, 1
- stw r10, (dtlb_miss_counter - PAGE_OFFSET)@l(0)
- mfspr r10, SPRN_SPRG_SCRATCH0
- mfspr r11, SPRN_SPRG_SCRATCH1
- rfi
-#endif
-
DTLBMissIMMR:
mtcr r11
/* Set 512k byte guarded page and mark it valid */
@@ -525,10 +536,29 @@ DTLBMissIMMR:
DTLBMissLinear:
mtcr r11
+ rlwinm r10, r10, 20, 0x0f800000 /* 8xx supports max 256Mb RAM */
+#ifdef CONFIG_STRICT_KERNEL_RWX
+ patch_site 0f, patch__dtlbmiss_romem_top8
+
+0: subis r11, r10, (PAGE_OFFSET - 0x80000000)@ha
+ rlwinm r11, r11, 0, 0xff800000
+ neg r10, r11
+ or r11, r11, r10
+ rlwinm r11, r11, 4, MI_PS8MEG ^ MI_PS512K
+ ori r11, r11, MI_PS512K | MI_SVALID
+ mfspr r10, SPRN_MD_EPN
+ rlwinm r10, r10, 0, 0x0ff80000 /* 8xx supports max 256Mb RAM */
+#else
/* Set 8M byte page and mark it valid */
li r11, MD_PS8MEG | MD_SVALID
+#endif
mtspr SPRN_MD_TWC, r11
- rlwinm r10, r10, 20, 0x0f800000 /* 8xx supports max 256Mb RAM */
+#ifdef CONFIG_STRICT_KERNEL_RWX
+ patch_site 0f, patch__dtlbmiss_romem_top
+
+0: subis r11, r10, 0
+ rlwimi r10, r11, 11, _PAGE_RO
+#endif
ori r10, r10, 0xf0 | MD_SPS16K | _PAGE_SH | _PAGE_DIRTY | \
_PAGE_PRESENT
mtspr SPRN_MD_RPN, r10 /* Update TLB entry */
diff --git a/arch/powerpc/mm/8xx_mmu.c b/arch/powerpc/mm/8xx_mmu.c
index 92ae7f40ccb1..c63af3400c8d 100644
--- a/arch/powerpc/mm/8xx_mmu.c
+++ b/arch/powerpc/mm/8xx_mmu.c
@@ -98,11 +98,20 @@ static void __init mmu_mapin_immr(void)
map_kernel_page(v + offset, p + offset, PAGE_KERNEL_NCG);
}
-static void __init mmu_patch_cmp_limit(s32 *site, unsigned long mapped)
+static void mmu_patch_cmp_limit(s32 *site, unsigned long mapped)
{
modify_instruction_site(site, 0xffff, (unsigned long)__va(mapped) >> 16);
}
+static void mmu_patch_addis(s32 *site, long simm)
+{
+ unsigned int instr = *(unsigned int *)patch_site_addr(site);
+
+ instr &= 0xffff0000;
+ instr |= ((unsigned long)simm) >> 16;
+ patch_instruction_site(site, instr);
+}
+
unsigned long __init mmu_mapin_ram(unsigned long base, unsigned long top)
{
unsigned long mapped;
@@ -138,6 +147,26 @@ unsigned long __init mmu_mapin_ram(unsigned long base, unsigned long top)
return mapped;
}
+void mmu_mark_initmem_nx(void)
+{
+ if (IS_ENABLED(CONFIG_STRICT_KERNEL_RWX) && CONFIG_ETEXT_SHIFT < 23)
+ mmu_patch_addis(&patch__itlbmiss_linmem_top8,
+ -((long)_etext & ~(LARGE_PAGE_SIZE_8M - 1)));
+ if (!IS_ENABLED(CONFIG_PIN_TLB_TEXT))
+ mmu_patch_cmp_limit(&patch__itlbmiss_linmem_top, __pa(_etext));
+}
+
+#ifdef CONFIG_STRICT_KERNEL_RWX
+void mmu_mark_rodata_ro(void)
+{
+ if (CONFIG_DATA_SHIFT < 23)
+ mmu_patch_addis(&patch__dtlbmiss_romem_top8,
+ -__pa(((unsigned long)_sinittext) &
+ ~(LARGE_PAGE_SIZE_8M - 1)));
+ mmu_patch_addis(&patch__dtlbmiss_romem_top, -__pa(_sinittext));
+}
+#endif
+
void __init setup_initial_memory_limit(phys_addr_t first_memblock_base,
phys_addr_t first_memblock_size)
{
diff --git a/arch/powerpc/mm/init_32.c b/arch/powerpc/mm/init_32.c
index bc28995a37ea..41a3513cadc9 100644
--- a/arch/powerpc/mm/init_32.c
+++ b/arch/powerpc/mm/init_32.c
@@ -108,7 +108,7 @@ static void __init MMU_setup(void)
__map_without_bats = 1;
__map_without_ltlbs = 1;
}
- if (strict_kernel_rwx_enabled())
+ if (strict_kernel_rwx_enabled() && !IS_ENABLED(CONFIG_PPC_8xx))
__map_without_ltlbs = 1;
}
diff --git a/arch/powerpc/mm/mmu_decl.h b/arch/powerpc/mm/mmu_decl.h
index 98fc94affc29..74ff61dabcb1 100644
--- a/arch/powerpc/mm/mmu_decl.h
+++ b/arch/powerpc/mm/mmu_decl.h
@@ -166,7 +166,7 @@ static inline phys_addr_t v_block_mapped(unsigned long va) { return 0; }
static inline unsigned long p_block_mapped(phys_addr_t pa) { return 0; }
#endif
-#if defined(CONFIG_PPC_BOOK3S_32)
+#if defined(CONFIG_PPC_BOOK3S_32) || defined(CONFIG_PPC_8xx)
void mmu_mark_initmem_nx(void);
void mmu_mark_rodata_ro(void);
#else
--
2.13.3
^ permalink raw reply related
* [PATCH v4 16/16] powerpc/kconfig: make _etext and data areas alignment configurable on 8xx
From: Christophe Leroy @ 2019-02-21 8:05 UTC (permalink / raw)
To: Benjamin Herrenschmidt, Paul Mackerras, Michael Ellerman,
j.neuschaefer
Cc: linuxppc-dev, linux-kernel
In-Reply-To: <cover.1550692943.git.christophe.leroy@c-s.fr>
On 8xx, large pages (512kb or 8M) are used to map kernel linear
memory. Aligning to 8M reduces TLB misses as only 8M pages are used
in that case. We make 8M the default for data.
This patchs allows the user to do it via Kconfig.
Signed-off-by: Christophe Leroy <christophe.leroy@c-s.fr>
---
arch/powerpc/Kconfig | 18 +++++++++++++++---
arch/powerpc/kernel/head_8xx.S | 4 ++--
2 files changed, 17 insertions(+), 5 deletions(-)
diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig
index 271f13ac23d4..447b86ea4815 100644
--- a/arch/powerpc/Kconfig
+++ b/arch/powerpc/Kconfig
@@ -729,7 +729,8 @@ config THREAD_SHIFT
want. Only change this if you know what you are doing.
config ETEXT_SHIFT_BOOL
- bool "Set custom etext alignment" if STRICT_KERNEL_RWX && PPC_BOOK3S_32
+ bool "Set custom etext alignment" if STRICT_KERNEL_RWX && \
+ (PPC_BOOK3S_32 || PPC_8xx)
depends on ADVANCED_OPTIONS
help
This option allows you to set the kernel end of text alignment. When
@@ -741,6 +742,7 @@ config ETEXT_SHIFT_BOOL
config ETEXT_SHIFT
int "_etext shift" if ETEXT_SHIFT_BOOL
range 17 28 if STRICT_KERNEL_RWX && PPC_BOOK3S_32
+ range 19 23 if STRICT_KERNEL_RWX && PPC_8xx
default 17 if STRICT_KERNEL_RWX && PPC_BOOK3S_32
default 19 if STRICT_KERNEL_RWX && PPC_8xx
default PPC_PAGE_SHIFT
@@ -748,8 +750,13 @@ config ETEXT_SHIFT
On Book3S 32 (603+), IBATs are used to map kernel text.
Smaller is the alignment, greater is the number of necessary IBATs.
+ On 8xx, large pages (512kb or 8M) are used to map kernel linear
+ memory. Aligning to 8M reduces TLB misses as only 8M pages are used
+ in that case.
+
config DATA_SHIFT_BOOL
- bool "Set custom data alignment" if STRICT_KERNEL_RWX && PPC_BOOK3S_32
+ bool "Set custom data alignment" if STRICT_KERNEL_RWX && \
+ (PPC_BOOK3S_32 || PPC_8xx)
depends on ADVANCED_OPTIONS
help
This option allows you to set the kernel data alignment. When
@@ -762,13 +769,18 @@ config DATA_SHIFT
int "Data shift" if DATA_SHIFT_BOOL
default 24 if STRICT_KERNEL_RWX && PPC64
range 17 28 if STRICT_KERNEL_RWX && PPC_BOOK3S_32
+ range 19 23 if STRICT_KERNEL_RWX && PPC_8xx
default 22 if STRICT_KERNEL_RWX && PPC_BOOK3S_32
- default 19 if STRICT_KERNEL_RWX && PPC_8xx
+ default 23 if STRICT_KERNEL_RWX && PPC_8xx
default PPC_PAGE_SHIFT
help
On Book3S 32 (603+), DBATs are used to map kernel text and rodata RO.
Smaller is the alignment, greater is the number of necessary DBATs.
+ On 8xx, large pages (512kb or 8M) are used to map kernel linear
+ memory. Aligning to 8M reduces TLB misses as only 8M pages are used
+ in that case.
+
config FORCE_MAX_ZONEORDER
int "Maximum zone order"
range 8 9 if PPC64 && PPC_64K_PAGES
diff --git a/arch/powerpc/kernel/head_8xx.S b/arch/powerpc/kernel/head_8xx.S
index 29c9289bc1d4..b10dc01690fc 100644
--- a/arch/powerpc/kernel/head_8xx.S
+++ b/arch/powerpc/kernel/head_8xx.S
@@ -416,7 +416,7 @@ InstructionTLBMiss:
#ifndef CONFIG_PIN_TLB_TEXT
ITLBMissLinear:
mtcr r11
-#ifdef CONFIG_STRICT_KERNEL_RWX
+#if defined(CONFIG_STRICT_KERNEL_RWX) && CONFIG_ETEXT_SHIFT < 23
patch_site 0f, patch__itlbmiss_linmem_top8
mfspr r10, SPRN_SRR0
@@ -537,7 +537,7 @@ DTLBMissIMMR:
DTLBMissLinear:
mtcr r11
rlwinm r10, r10, 20, 0x0f800000 /* 8xx supports max 256Mb RAM */
-#ifdef CONFIG_STRICT_KERNEL_RWX
+#if defined(CONFIG_STRICT_KERNEL_RWX) && CONFIG_DATA_SHIFT < 23
patch_site 0f, patch__dtlbmiss_romem_top8
0: subis r11, r10, (PAGE_OFFSET - 0x80000000)@ha
--
2.13.3
^ permalink raw reply related
* Re: Kernel panic when loading the IDE controller driver
From: sgosavi1 @ 2019-02-21 8:18 UTC (permalink / raw)
To: linuxppc-dev
In-Reply-To: <1550230073842-0.post@n7.nabble.com>
Hi All,
I finally got the FLASH controller driver working and it is now successfully
reporting the presence of 2GB Flash in the board. I used the new "libata"
driver code present in the new kernel source under drivers/ata/. Also did
the required additions in the device tree to provide the IO port, IRQ and
PIO mode details to the driver.
However now I am getting the below errors.
[ 4.200145] scsi host0: pata_of_platform
[ 4.236999] ata1: PATA max PIO4 mmio cmd 0xe0000000 ctl 0xe200000c irq 63
[ 4.439985] ata1.01: ATA-7: 2GB ATA Flash Disk, C A254G4, max UDMA/133
[ 4.463419] ata1.01: 3571344 sectors, multi 0: LBA48
[ 4.483384] ata1.01: configured for PIO
[ 4.512936] scsi 0:0:1:0: Direct-Access ATA 2GB ATA Flash Di
54G4 PQ: 0 ANSI: 5
[ 4.555994] sd 0:0:1:0: [sda] 3571344 512-byte logical blocks: (1.83
GB/1.70 GiB)
[ 4.591975] sd 0:0:1:0: [sda] Write Protect is off
[ 4.611307] sd 0:0:1:0: [sda] Mode Sense: 00 3a 00 00
[ 4.629733] sd 0:0:1:0: [sda] Write cache: disabled, read cache: enabled,
doesn't support DPO or FUA
[ 4.823702]
[ 4.823702] AT THE START OF CPU_STARTUP_ENTRY FUNCTION
[ 4.823734]
[ 4.823734] *****INSIDE IDLE LOOP********
[ 36.163139] ata1: drained 65536 bytes to clear DRQ
[ 36.185451] ata1.01: exception Emask 0x0 SAct 0x0 SErr 0x0 action 0x6
frozen
[ 36.199598] ata1.01: cmd 20/00:08:00:00:00/00:00:00:00:00/f0 tag 0 pio
4096 in
[ 36.199598] res 40/00:00:00:00:00/00:00:00:00:00/00 Emask 0x4
(timeout)
[ 36.229002] ata1: soft resetting link
[ 36.559637] ata1.01: configured for PIO
[ 36.567563] ata1.01: device reported invalid CHS sector 0
[ 36.578396] ata1: EH complete
[ 68.919134] ata1: drained 65536 bytes to clear DRQ
[ 68.928530] ata1.01: limiting speed to UDMA7:PIO5
[ 68.937856] ata1.01: exception Emask 0x0 SAct 0x0 SErr 0x0 action 0x6
frozen
[ 68.952487] ata1.01: cmd 20/00:08:00:00:00/00:00:00:00:00/f0 tag 0 pio
4096 in
[ 68.952487] res 40/00:00:00:00:00/00:00:00:00:00/00 Emask 0x4
(timeout)
[ 68.981876] ata1: soft resetting link
[ 69.311683] ata1.01: configured for PIO
[ 69.319304] ata1.01: device reported invalid CHS sector 0
[ 69.330274] ata1: EH complete
[ 101.687134] ata1: drained 65536 bytes to clear DRQ
[ 101.696646] ata1.01: limiting speed to PIO0
[ 101.704921] ata1.01: exception Emask 0x0 SAct 0x0 SErr 0x0 action 0x6
frozen
[ 101.719288] ata1.01: cmd 20/00:08:00:00:00/00:00:00:00:00/f0 tag 0 pio
4096 in
[ 101.719288] res 40/00:00:00:00:00/00:00:00:00:00/00 Emask 0x4
(timeout)
[ 101.748593] ata1: soft resetting link
[ 102.079594] ata1.01: configured for PIO
[ 102.087204] ata1.01: device reported invalid CHS sector 0
[ 102.098144] ata1: EH complete
[ 132.407134] ata1: drained 65536 bytes to clear DRQ
[ 132.416687] ata1.01: exception Emask 0x0 SAct 0x0 SErr 0x0 action 0x6
frozen
[ 132.430752] ata1.01: cmd 20/00:08:00:00:00/00:00:00:00:00/f0 tag 0 pio
4096 in
[ 132.430752] res 40/00:00:00:00:00/00:00:00:00:00/00 Emask 0x4
(timeout)
[ 132.460168] ata1: soft resetting link
[ 132.791594] ata1.01: configured for PIO
[ 132.799048] ata1.01: device reported invalid CHS sector 0
[ 132.810076] ata1: EH complete
[ 165.175163] ata1: drained 65536 bytes to clear DRQ
[ 165.186023] ata1.01: exception Emask 0x0 SAct 0x0 SErr 0x0 action 0x6
frozen
[ 165.200192] ata1.01: cmd 20/00:08:00:00:00/00:00:00:00:00/f0 tag 0 pio
4096 in
[ 165.200192] res 40/00:00:00:00:00/00:00:00:00:00/00 Emask 0x4
(timeout)
[ 165.229531] ata1: soft resetting link
Can anyone suggest why I am getting the above errors?
Thanks,
Sachin.
--
Sent from: http://linuxppc.10917.n7.nabble.com/linuxppc-dev-f3.html
^ permalink raw reply
* Re: [PATCH 5/8] iio/counter: add FlexTimer Module Quadrature decoder counter driver
From: William Breathitt Gray @ 2019-02-21 8:28 UTC (permalink / raw)
To: Patrick Havelange
Cc: Mark Rutland, devicetree, Lars-Peter Clausen, linux-pwm,
linux-iio, linuxppc-dev, Linus Walleij, Daniel Lezcano,
linux-kernel, Li Yang, Rob Herring, Thierry Reding,
Esben Haabendal, Peter Meerwald-Stadler, Hartmut Knaack,
Thomas Gleixner, Shawn Guo, Jonathan Cameron, linux-arm-kernel
In-Reply-To: <20190221010931.GA3471@icarus>
On Thu, Feb 21, 2019 at 10:09:54AM +0900, William Breathitt Gray wrote:
> On Wed, Feb 20, 2019 at 04:41:54PM +0000, Jonathan Cameron wrote:
> > On Mon, 18 Feb 2019 15:03:18 +0100
> > Patrick Havelange <patrick.havelange@essensium.com> wrote:
> >
> > > This driver exposes the counter for the quadrature decoder of the
> > > FlexTimer Module, present in the LS1021A soc.
> > >
> > > Signed-off-by: Patrick Havelange <patrick.havelange@essensium.com>
> > > Reviewed-by: Esben Haabendal <esben@haabendal.dk>
> > Given you cc'd William, I'm guessing you know about the counter
> > subsystem effort. I would really rather not take any drivers
> > into IIO if we have any hope of getting that upstreamed soon
> > (which I personally think we do and should!). The reason is
> > we end up having to maintain old ABI just because someone might be using
> > it and it makes the drivers very messy.
> >
> > I'll review as is though as may be there are some elements that will
> > cross over.
> >
> > Comments inline. William: Looks like a straight forward conversion if
> > it makes sense to get this lined up as part of your initial submission?
> > You have quite a few drivers so I wouldn't have said it needs to be there
> > at the start, but good to have it soon after.
> >
> > Jonathan
>
> I agree, we should try to merge this as part of Counter subsystem
> introduction rather than as another IIO Counter driver. As we determined
> when adding support for the STM32 timers, the existing IIO Counter API
> is fundamentally unsuitable for representing counter devices. So
> regardless of how a new Counter API is merged, the existing IIO Counter
> API must be deprecated.
>
> Patrick, I apologize for the confusion this has caused. Would you be
> able to convert this driver to use the proposed Counter subsystem API
> from this patchset that I believe you encountered before:
> https://marc.info/?l=linux-arm-kernel&m=153229982404051
>
> Although it was last updated in October, I believe you should be able to
> rebase that Counter subsystem introduction patchset cleanly on top of
> the IIO tree (if there are any merge conflicts send me an email). Take a
> look at the generic-counter.rst file under the Documentation/driver-api/
> directory for an overview of the API; the counter drivers under the
> drivers/counter/ directory also make good references.
>
> If you have any difficulties understanding the API, or any other
> troubles, don't hesitate to ask. Hopefully, I've made the documentation
> clear enough to make the conversion of this driver quick and easy -- and
> if not, then it's something I need to fix, so let me know. :-)
>
> William Breathitt Gray
Patrick,
It looks like there were some minor conflicts with the v9 patchset, so
I've rebased it on top of the latest iio tree testing branch and
resolved the conflicts in my personal repository. Please pull from my
personal repository at https://gitlab.com/vilhelmgray/iio.git and base
your patches on top of the generic_counter_v10 branch.
William Breathitt Gray
^ permalink raw reply
* Re: [PATCH v3 1/7] dump_stack: Support adding to the dump stack arch description
From: Petr Mladek @ 2019-02-21 8:38 UTC (permalink / raw)
To: Andrea Parri
Cc: linux-arch, sergey.senozhatsky, linux-kernel, Steven Rostedt,
linuxppc-dev, tj, akpm, dyoung
In-Reply-To: <20190220134433.GA4932@andrea>
On Wed 2019-02-20 14:44:33, Andrea Parri wrote:
> > >> > > + * Order the stores above in vsnprintf() vs the store of the
> > >> > > + * space below which joins the two strings. Note this doesn't
> > >> > > + * make the code truly race free because there is no barrier on
> > >> > > + * the read side. ie. Another CPU might load the uninitialised
> > >> > > + * tail of the buffer first and then the space below (rather
> > >> > > + * than the NULL that was there previously), and so print the
> > >> > > + * uninitialised tail. But the whole string lives in BSS so in
> > >> > > + * practice it should just see NULLs.
> > >> >
> > It is not my intention to support concurrent updates of the string. The
> > idea is you setup the string early in boot.
>
> Understood, thanks for the clarification.
> >
> > The concern with a concurrent reader is simply that the string is dumped
> > in the panic path, and you never really know when you're going to panic.
> > Even if you only write to the string before doing SMP bringup you might
> > still have another CPU go rogue and panic before then.
> >
> > But I probably should have just not added the barrier, it's over
> > paranoid and will almost certainly never matter in practice.
>
> Oh, well, I can only echo you: if you don't care about the stores being
> _observed_ out of order, you could simply remove the barrier; if you do
> care, then you need "more paranoid" on the readers side. ;-)
Hmm, the barrier might be fine and actually useful. The
purpose is to make sure that the later '\0' is written before
the existing one is replaced by ' '.
The reader does not need the barrier as long as it reads the string
sequentially. I would expect that it is always the case. But who
knows with all the speculation-related CPU bugs around.
In each case, any race could never crash the kernel.
The dump_stack_arch_desc_str is zeroed out of box and
the very last '\0' is never rewritten.
Best Regards,
Petr
^ permalink raw reply
* Re: [PATCH] powerpc: Move page table dump files in a dedicated subdirectory
From: Michael Ellerman @ 2019-02-21 9:12 UTC (permalink / raw)
To: Christophe Leroy, Benjamin Herrenschmidt, Paul Mackerras
Cc: linuxppc-dev, linux-kernel
In-Reply-To: <0f371616-0ab6-fe96-852a-323159c58572@c-s.fr>
Christophe Leroy <christophe.leroy@c-s.fr> writes:
> Le 20/02/2019 à 14:37, Michael Ellerman a écrit :
>> Christophe Leroy <christophe.leroy@c-s.fr> writes:
>>
>>> This patch moves the files related to page table dump in a
>>> dedicated subdirectory.
>>>
>>> The purpose is to clean a bit arch/powerpc/mm by regrouping
>>> multiple files handling a dedicated function.
>>>
>>> Signed-off-by: Christophe Leroy <christophe.leroy@c-s.fr>
>>> ---
>>> arch/powerpc/Kconfig.debug | 4 ----
>>> arch/powerpc/mm/Makefile | 10 +---------
>>> arch/powerpc/mm/ptdump/Makefile | 9 +++++++++
>>> arch/powerpc/mm/{ => ptdump}/dump_bats.c | 0
>>> arch/powerpc/mm/{ => ptdump}/dump_hashpagetable.c | 0
>>> arch/powerpc/mm/{ => ptdump}/dump_linuxpagetables-8xx.c | 0
>>> arch/powerpc/mm/{ => ptdump}/dump_linuxpagetables-book3s64.c | 0
>>> arch/powerpc/mm/{ => ptdump}/dump_linuxpagetables-generic.c | 0
>>> arch/powerpc/mm/{ => ptdump}/dump_linuxpagetables.c | 0
>>> arch/powerpc/mm/{ => ptdump}/dump_linuxpagetables.h | 0
>>> arch/powerpc/mm/{ => ptdump}/dump_sr.c | 0
>>> 11 files changed, 10 insertions(+), 13 deletions(-)
>>> create mode 100644 arch/powerpc/mm/ptdump/Makefile
>>> rename arch/powerpc/mm/{ => ptdump}/dump_bats.c (100%)
>>> rename arch/powerpc/mm/{ => ptdump}/dump_hashpagetable.c (100%)
>>> rename arch/powerpc/mm/{ => ptdump}/dump_linuxpagetables-8xx.c (100%)
>>> rename arch/powerpc/mm/{ => ptdump}/dump_linuxpagetables-book3s64.c (100%)
>>> rename arch/powerpc/mm/{ => ptdump}/dump_linuxpagetables-generic.c (100%)
>>> rename arch/powerpc/mm/{ => ptdump}/dump_linuxpagetables.c (100%)
>>> rename arch/powerpc/mm/{ => ptdump}/dump_linuxpagetables.h (100%)
>>> rename arch/powerpc/mm/{ => ptdump}/dump_sr.c (100%)
>>
>> I'd like to shorten the file names as well, now that they're namespaced
>> in the ptdump directory, how about:
>>
>> arch/powerpc/Kconfig.debug | 4 ----
>> arch/powerpc/mm/Makefile | 10 +---------
>> arch/powerpc/mm/{dump_linuxpagetables-8xx.c => ptdump/8xx.c} | 2 +-
>> arch/powerpc/mm/ptdump/Makefile | 9 +++++++++
>> arch/powerpc/mm/{dump_bats.c => ptdump/bats.c} | 0
>> arch/powerpc/mm/{dump_linuxpagetables-book3s64.c => ptdump/book3s64.c} | 2 +-
>> arch/powerpc/mm/{dump_hashpagetable.c => ptdump/hashpagetable.c} | 0
>> arch/powerpc/mm/{dump_linuxpagetables.c => ptdump/ptdump.c} | 2 +-
>> arch/powerpc/mm/{dump_linuxpagetables.h => ptdump/ptdump.h} | 0
>> arch/powerpc/mm/{dump_sr.c => ptdump/segment_regs.c} | 0
>> arch/powerpc/mm/{dump_linuxpagetables-generic.c => ptdump/shared.c} | 2 +-
>
> Yes good idea. Do you want a v2 or will you do it ?
I'll do it, thanks.
cheers
^ permalink raw reply
* [PATCH 0/7] Kernel Userspace Protection for radix
From: Russell Currey @ 2019-02-21 9:35 UTC (permalink / raw)
To: linuxppc-dev; +Cc: Russell Currey, npiggin, kernel-hardening
The first three patches of these series are from Christophe's work and are
the bare minimum framework needed to implement the support for radix.
In patch 3, I have removed from Christophe's patch my implementation of
the 64-bit exception handling code, since we don't have an answer for
making nested exceptions work yet. This is mentioned in the final KUAP
patch. Regardless, this is still a significant security improvement
and greatly narrows the attack surface.
Here are patches you will want if you want this to work:
http://patchwork.ozlabs.org/patch/1045215/
http://patchwork.ozlabs.org/patch/1045049/
http://patchwork.ozlabs.org/patch/1038568/
(or subsequent revisions, which the latter two will need)
I wouldn't expect this series to be merged without those fixes.
Thanks to Christophe for his great work and to Michael Ellerman for a
ton of feedback as I've worked on this.
Christophe Leroy (3):
powerpc: Add framework for Kernel Userspace Protection
powerpc: Add skeleton for Kernel Userspace Execution Prevention
powerpc/mm: Add a framework for Kernel Userspace Access Protection
Russell Currey (4):
powerpc/64: Setup KUP on secondary CPUs
powerpc/mm/radix: Use KUEP API for Radix MMU
powerpc/lib: Refactor __patch_instruction() to use __put_user_asm()
powerpc/64s: Implement KUAP for Radix MMU
.../admin-guide/kernel-parameters.txt | 4 +-
.../powerpc/include/asm/book3s/64/kup-radix.h | 36 ++++++++++++++++
arch/powerpc/include/asm/exception-64e.h | 3 ++
arch/powerpc/include/asm/exception-64s.h | 3 ++
arch/powerpc/include/asm/futex.h | 4 ++
arch/powerpc/include/asm/kup.h | 42 +++++++++++++++++++
arch/powerpc/include/asm/mmu.h | 9 +++-
arch/powerpc/include/asm/paca.h | 3 ++
arch/powerpc/include/asm/processor.h | 3 ++
arch/powerpc/include/asm/ptrace.h | 3 ++
arch/powerpc/include/asm/reg.h | 1 +
arch/powerpc/include/asm/uaccess.h | 38 +++++++++++++----
arch/powerpc/kernel/asm-offsets.c | 7 ++++
arch/powerpc/kernel/entry_32.S | 8 +++-
arch/powerpc/kernel/process.c | 3 ++
arch/powerpc/kernel/setup_64.c | 10 +++++
arch/powerpc/lib/checksum_wrappers.c | 4 ++
arch/powerpc/lib/code-patching.c | 4 +-
arch/powerpc/mm/fault.c | 20 ++++++---
arch/powerpc/mm/init-common.c | 26 ++++++++++++
arch/powerpc/mm/init_32.c | 3 ++
arch/powerpc/mm/pgtable-radix.c | 28 +++++++++++--
arch/powerpc/mm/pkeys.c | 7 +++-
arch/powerpc/platforms/Kconfig.cputype | 26 ++++++++++++
24 files changed, 271 insertions(+), 24 deletions(-)
create mode 100644 arch/powerpc/include/asm/book3s/64/kup-radix.h
create mode 100644 arch/powerpc/include/asm/kup.h
--
2.20.1
^ permalink raw reply
* [PATCH 1/7] powerpc: Add framework for Kernel Userspace Protection
From: Russell Currey @ 2019-02-21 9:35 UTC (permalink / raw)
To: linuxppc-dev; +Cc: Russell Currey, npiggin, kernel-hardening
In-Reply-To: <20190221093601.27920-1-ruscur@russell.cc>
From: Christophe Leroy <christophe.leroy@c-s.fr>
This patch adds a skeleton for Kernel Userspace Protection
functionnalities like Kernel Userspace Access Protection and
Kernel Userspace Execution Prevention
The subsequent implementation of KUAP for radix makes use of a MMU
feature in order to patch out assembly when KUAP is disabled or
unsupported. This won't work unless there's an entry point for
KUP support before the feature magic happens, so for PPC64
setup_kup() is called early in setup.
On PPC32, feature_fixup is done too early to allow the same.
Suggested-by: Russell Currey <ruscur@russell.cc>
Signed-off-by: Christophe Leroy <christophe.leroy@c-s.fr>
---
arch/powerpc/include/asm/kup.h | 11 +++++++++++
arch/powerpc/kernel/setup_64.c | 7 +++++++
arch/powerpc/mm/init-common.c | 5 +++++
arch/powerpc/mm/init_32.c | 3 +++
4 files changed, 26 insertions(+)
create mode 100644 arch/powerpc/include/asm/kup.h
diff --git a/arch/powerpc/include/asm/kup.h b/arch/powerpc/include/asm/kup.h
new file mode 100644
index 000000000000..7a88b8b9b54d
--- /dev/null
+++ b/arch/powerpc/include/asm/kup.h
@@ -0,0 +1,11 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef _ASM_POWERPC_KUP_H_
+#define _ASM_POWERPC_KUP_H_
+
+#ifndef __ASSEMBLY__
+
+void setup_kup(void);
+
+#endif /* !__ASSEMBLY__ */
+
+#endif /* _ASM_POWERPC_KUP_H_ */
diff --git a/arch/powerpc/kernel/setup_64.c b/arch/powerpc/kernel/setup_64.c
index 236c1151a3a7..771f280a6bf6 100644
--- a/arch/powerpc/kernel/setup_64.c
+++ b/arch/powerpc/kernel/setup_64.c
@@ -68,6 +68,7 @@
#include <asm/cputhreads.h>
#include <asm/hw_irq.h>
#include <asm/feature-fixups.h>
+#include <asm/kup.h>
#include "setup.h"
@@ -331,6 +332,12 @@ void __init early_setup(unsigned long dt_ptr)
*/
configure_exceptions();
+ /*
+ * Configure Kernel Userspace Protection. This needs to happen before
+ * feature fixups for platforms that implement this using features.
+ */
+ setup_kup();
+
/* Apply all the dynamic patching */
apply_feature_fixups();
setup_feature_keys();
diff --git a/arch/powerpc/mm/init-common.c b/arch/powerpc/mm/init-common.c
index 1e6910eb70ed..36d28e872289 100644
--- a/arch/powerpc/mm/init-common.c
+++ b/arch/powerpc/mm/init-common.c
@@ -24,6 +24,11 @@
#include <linux/string.h>
#include <asm/pgalloc.h>
#include <asm/pgtable.h>
+#include <asm/kup.h>
+
+void __init setup_kup(void)
+{
+}
#define CTOR(shift) static void ctor_##shift(void *addr) \
{ \
diff --git a/arch/powerpc/mm/init_32.c b/arch/powerpc/mm/init_32.c
index 3e59e5d64b01..93cfa8cf015d 100644
--- a/arch/powerpc/mm/init_32.c
+++ b/arch/powerpc/mm/init_32.c
@@ -45,6 +45,7 @@
#include <asm/tlb.h>
#include <asm/sections.h>
#include <asm/hugetlb.h>
+#include <asm/kup.h>
#include "mmu_decl.h"
@@ -182,6 +183,8 @@ void __init MMU_init(void)
btext_unmap();
#endif
+ setup_kup();
+
/* Shortly after that, the entire linear mapping will be available */
memblock_set_current_limit(lowmem_end_addr);
}
--
2.20.1
^ permalink raw reply related
* [PATCH 2/7] powerpc: Add skeleton for Kernel Userspace Execution Prevention
From: Russell Currey @ 2019-02-21 9:35 UTC (permalink / raw)
To: linuxppc-dev; +Cc: npiggin, kernel-hardening
In-Reply-To: <20190221093601.27920-1-ruscur@russell.cc>
From: Christophe Leroy <christophe.leroy@c-s.fr>
This patch adds a skeleton for Kernel Userspace Execution Prevention.
Then subarches implementing it have to define CONFIG_PPC_HAVE_KUEP
and provide setup_kuep() function.
Signed-off-by: Christophe Leroy <christophe.leroy@c-s.fr>
---
Documentation/admin-guide/kernel-parameters.txt | 2 +-
arch/powerpc/include/asm/kup.h | 6 ++++++
arch/powerpc/mm/fault.c | 3 ++-
arch/powerpc/mm/init-common.c | 11 +++++++++++
arch/powerpc/platforms/Kconfig.cputype | 12 ++++++++++++
5 files changed, 32 insertions(+), 2 deletions(-)
diff --git a/Documentation/admin-guide/kernel-parameters.txt b/Documentation/admin-guide/kernel-parameters.txt
index 858b6c0b9a15..8448a56a9eb9 100644
--- a/Documentation/admin-guide/kernel-parameters.txt
+++ b/Documentation/admin-guide/kernel-parameters.txt
@@ -2812,7 +2812,7 @@
Disable SMAP (Supervisor Mode Access Prevention)
even if it is supported by processor.
- nosmep [X86]
+ nosmep [X86,PPC]
Disable SMEP (Supervisor Mode Execution Prevention)
even if it is supported by processor.
diff --git a/arch/powerpc/include/asm/kup.h b/arch/powerpc/include/asm/kup.h
index 7a88b8b9b54d..af4b5f854ca4 100644
--- a/arch/powerpc/include/asm/kup.h
+++ b/arch/powerpc/include/asm/kup.h
@@ -6,6 +6,12 @@
void setup_kup(void);
+#ifdef CONFIG_PPC_KUEP
+void setup_kuep(bool disabled);
+#else
+static inline void setup_kuep(bool disabled) { }
+#endif
+
#endif /* !__ASSEMBLY__ */
#endif /* _ASM_POWERPC_KUP_H_ */
diff --git a/arch/powerpc/mm/fault.c b/arch/powerpc/mm/fault.c
index 887f11bcf330..ad65e336721a 100644
--- a/arch/powerpc/mm/fault.c
+++ b/arch/powerpc/mm/fault.c
@@ -230,8 +230,9 @@ static bool bad_kernel_fault(bool is_exec, unsigned long error_code,
if (is_exec && (error_code & (DSISR_NOEXEC_OR_G | DSISR_KEYFAULT |
DSISR_PROTFAULT))) {
printk_ratelimited(KERN_CRIT "kernel tried to execute"
- " exec-protected page (%lx) -"
+ " %s page (%lx) -"
"exploit attempt? (uid: %d)\n",
+ address >= TASK_SIZE ? "exec-protected" : "user",
address, from_kuid(&init_user_ns,
current_uid()));
}
diff --git a/arch/powerpc/mm/init-common.c b/arch/powerpc/mm/init-common.c
index 36d28e872289..83f95a5565d6 100644
--- a/arch/powerpc/mm/init-common.c
+++ b/arch/powerpc/mm/init-common.c
@@ -26,8 +26,19 @@
#include <asm/pgtable.h>
#include <asm/kup.h>
+static bool disable_kuep = !IS_ENABLED(CONFIG_PPC_KUEP);
+
+static int __init parse_nosmep(char *p)
+{
+ disable_kuep = true;
+ pr_warn("Disabling Kernel Userspace Execution Prevention\n");
+ return 0;
+}
+early_param("nosmep", parse_nosmep);
+
void __init setup_kup(void)
{
+ setup_kuep(disable_kuep);
}
#define CTOR(shift) static void ctor_##shift(void *addr) \
diff --git a/arch/powerpc/platforms/Kconfig.cputype b/arch/powerpc/platforms/Kconfig.cputype
index 8c7464c3f27f..410c3443652c 100644
--- a/arch/powerpc/platforms/Kconfig.cputype
+++ b/arch/powerpc/platforms/Kconfig.cputype
@@ -339,6 +339,18 @@ config PPC_RADIX_MMU_DEFAULT
If you're unsure, say Y.
+config PPC_HAVE_KUEP
+ bool
+
+config PPC_KUEP
+ bool "Kernel Userspace Execution Prevention"
+ depends on PPC_HAVE_KUEP
+ default y
+ help
+ Enable support for Kernel Userspace Execution Prevention (KUEP)
+
+ If you're unsure, say Y.
+
config ARCH_ENABLE_HUGEPAGE_MIGRATION
def_bool y
depends on PPC_BOOK3S_64 && HUGETLB_PAGE && MIGRATION
--
2.20.1
^ permalink raw reply related
* [PATCH 3/7] powerpc/mm: Add a framework for Kernel Userspace Access Protection
From: Russell Currey @ 2019-02-21 9:35 UTC (permalink / raw)
To: linuxppc-dev; +Cc: Russell Currey, npiggin, kernel-hardening
In-Reply-To: <20190221093601.27920-1-ruscur@russell.cc>
From: Christophe Leroy <christophe.leroy@c-s.fr>
This patch implements a framework for Kernel Userspace Access
Protection.
Then subarches will have to possibility to provide their own
implementation by providing setup_kuap() and lock/unlock_user_access()
Some platform will need to know the area accessed and whether it is
accessed from read, write or both. Therefore source, destination and
size and handed over to the two functions.
Signed-off-by: Christophe Leroy <christophe.leroy@c-s.fr>
[ruscur: remove 64-bit exception handling code]
Signed-off-by: Russell Currey <ruscur@russell.cc>
---
.../admin-guide/kernel-parameters.txt | 2 +-
arch/powerpc/include/asm/exception-64e.h | 3 ++
arch/powerpc/include/asm/exception-64s.h | 3 ++
arch/powerpc/include/asm/futex.h | 4 ++
arch/powerpc/include/asm/kup.h | 21 ++++++++++
arch/powerpc/include/asm/paca.h | 3 ++
arch/powerpc/include/asm/processor.h | 3 ++
arch/powerpc/include/asm/ptrace.h | 3 ++
arch/powerpc/include/asm/uaccess.h | 38 +++++++++++++++----
arch/powerpc/kernel/asm-offsets.c | 7 ++++
arch/powerpc/kernel/entry_32.S | 8 +++-
arch/powerpc/kernel/process.c | 3 ++
arch/powerpc/lib/checksum_wrappers.c | 4 ++
arch/powerpc/mm/fault.c | 17 +++++++--
arch/powerpc/mm/init-common.c | 10 +++++
arch/powerpc/platforms/Kconfig.cputype | 12 ++++++
16 files changed, 127 insertions(+), 14 deletions(-)
diff --git a/Documentation/admin-guide/kernel-parameters.txt b/Documentation/admin-guide/kernel-parameters.txt
index 8448a56a9eb9..0a76dbb39011 100644
--- a/Documentation/admin-guide/kernel-parameters.txt
+++ b/Documentation/admin-guide/kernel-parameters.txt
@@ -2808,7 +2808,7 @@
noexec=on: enable non-executable mappings (default)
noexec=off: disable non-executable mappings
- nosmap [X86]
+ nosmap [X86,PPC]
Disable SMAP (Supervisor Mode Access Prevention)
even if it is supported by processor.
diff --git a/arch/powerpc/include/asm/exception-64e.h b/arch/powerpc/include/asm/exception-64e.h
index 555e22d5e07f..bf25015834ee 100644
--- a/arch/powerpc/include/asm/exception-64e.h
+++ b/arch/powerpc/include/asm/exception-64e.h
@@ -215,5 +215,8 @@ exc_##label##_book3e:
#define RFI_TO_USER \
rfi
+#define UNLOCK_USER_ACCESS(reg)
+#define LOCK_USER_ACCESS(reg)
+
#endif /* _ASM_POWERPC_EXCEPTION_64E_H */
diff --git a/arch/powerpc/include/asm/exception-64s.h b/arch/powerpc/include/asm/exception-64s.h
index 3b4767ed3ec5..8ae2d7855cfe 100644
--- a/arch/powerpc/include/asm/exception-64s.h
+++ b/arch/powerpc/include/asm/exception-64s.h
@@ -264,6 +264,9 @@ BEGIN_FTR_SECTION_NESTED(943) \
std ra,offset(r13); \
END_FTR_SECTION_NESTED(ftr,ftr,943)
+#define UNLOCK_USER_ACCESS(reg)
+#define LOCK_USER_ACCESS(reg)
+
#define EXCEPTION_PROLOG_0(area) \
GET_PACA(r13); \
std r9,area+EX_R9(r13); /* save r9 */ \
diff --git a/arch/powerpc/include/asm/futex.h b/arch/powerpc/include/asm/futex.h
index 88b38b37c21b..f85facf3739b 100644
--- a/arch/powerpc/include/asm/futex.h
+++ b/arch/powerpc/include/asm/futex.h
@@ -35,6 +35,7 @@ static inline int arch_futex_atomic_op_inuser(int op, int oparg, int *oval,
{
int oldval = 0, ret;
+ unlock_user_access(uaddr, NULL, sizeof(*uaddr));
pagefault_disable();
switch (op) {
@@ -62,6 +63,7 @@ static inline int arch_futex_atomic_op_inuser(int op, int oparg, int *oval,
if (!ret)
*oval = oldval;
+ lock_user_access(uaddr, NULL, sizeof(*uaddr));
return ret;
}
@@ -75,6 +77,7 @@ futex_atomic_cmpxchg_inatomic(u32 *uval, u32 __user *uaddr,
if (!access_ok(uaddr, sizeof(u32)))
return -EFAULT;
+ unlock_user_access(uaddr, NULL, sizeof(*uaddr));
__asm__ __volatile__ (
PPC_ATOMIC_ENTRY_BARRIER
"1: lwarx %1,0,%3 # futex_atomic_cmpxchg_inatomic\n\
@@ -95,6 +98,7 @@ futex_atomic_cmpxchg_inatomic(u32 *uval, u32 __user *uaddr,
: "cc", "memory");
*uval = prev;
+ lock_user_access(uaddr, NULL, sizeof(*uaddr));
return ret;
}
diff --git a/arch/powerpc/include/asm/kup.h b/arch/powerpc/include/asm/kup.h
index af4b5f854ca4..2ac540fb488f 100644
--- a/arch/powerpc/include/asm/kup.h
+++ b/arch/powerpc/include/asm/kup.h
@@ -4,6 +4,8 @@
#ifndef __ASSEMBLY__
+#include <asm/pgtable.h>
+
void setup_kup(void);
#ifdef CONFIG_PPC_KUEP
@@ -12,6 +14,25 @@ void setup_kuep(bool disabled);
static inline void setup_kuep(bool disabled) { }
#endif
+#ifdef CONFIG_PPC_KUAP
+void setup_kuap(bool disabled);
+#else
+static inline void setup_kuap(bool disabled) { }
+static inline void unlock_user_access(void __user *to, const void __user *from,
+ unsigned long size) { }
+static inline void lock_user_access(void __user *to, const void __user *from,
+ unsigned long size) { }
+#endif
+
#endif /* !__ASSEMBLY__ */
+#ifndef CONFIG_PPC_KUAP
+
+#ifdef CONFIG_PPC32
+#define LOCK_USER_ACCESS(val, sp, sr, srmax, curr)
+#define REST_USER_ACCESS(val, sp, sr, srmax, curr)
+#endif
+
+#endif
+
#endif /* _ASM_POWERPC_KUP_H_ */
diff --git a/arch/powerpc/include/asm/paca.h b/arch/powerpc/include/asm/paca.h
index e843bc5d1a0f..56236f6d8c89 100644
--- a/arch/powerpc/include/asm/paca.h
+++ b/arch/powerpc/include/asm/paca.h
@@ -169,6 +169,9 @@ struct paca_struct {
u64 saved_r1; /* r1 save for RTAS calls or PM or EE=0 */
u64 saved_msr; /* MSR saved here by enter_rtas */
u16 trap_save; /* Used when bad stack is encountered */
+#ifdef CONFIG_PPC_KUAP
+ u8 user_access_allowed; /* can the kernel access user memory? */
+#endif
u8 irq_soft_mask; /* mask for irq soft masking */
u8 irq_happened; /* irq happened while soft-disabled */
u8 io_sync; /* writel() needs spin_unlock sync */
diff --git a/arch/powerpc/include/asm/processor.h b/arch/powerpc/include/asm/processor.h
index ee58526cb6c2..4a9a10e86828 100644
--- a/arch/powerpc/include/asm/processor.h
+++ b/arch/powerpc/include/asm/processor.h
@@ -250,6 +250,9 @@ struct thread_struct {
#ifdef CONFIG_PPC32
void *pgdir; /* root of page-table tree */
unsigned long ksp_limit; /* if ksp <= ksp_limit stack overflow */
+#ifdef CONFIG_PPC_KUAP
+ unsigned long kuap; /* state of user access protection */
+#endif
#endif
/* Debug Registers */
struct debug_reg debug;
diff --git a/arch/powerpc/include/asm/ptrace.h b/arch/powerpc/include/asm/ptrace.h
index 0b8a735b6d85..0321ba5b3d12 100644
--- a/arch/powerpc/include/asm/ptrace.h
+++ b/arch/powerpc/include/asm/ptrace.h
@@ -55,6 +55,9 @@ struct pt_regs
#ifdef CONFIG_PPC64
unsigned long ppr;
unsigned long __pad; /* Maintain 16 byte interrupt stack alignment */
+#elif defined(CONFIG_PPC_KUAP)
+ unsigned long kuap;
+ unsigned long __pad[3]; /* Maintain 16 byte interrupt stack alignment */
#endif
};
#endif
diff --git a/arch/powerpc/include/asm/uaccess.h b/arch/powerpc/include/asm/uaccess.h
index e3a731793ea2..9db6a4c7c058 100644
--- a/arch/powerpc/include/asm/uaccess.h
+++ b/arch/powerpc/include/asm/uaccess.h
@@ -6,6 +6,7 @@
#include <asm/processor.h>
#include <asm/page.h>
#include <asm/extable.h>
+#include <asm/kup.h>
/*
* The fs value determines whether argument validity checking should be
@@ -141,6 +142,7 @@ extern long __put_user_bad(void);
#define __put_user_size(x, ptr, size, retval) \
do { \
retval = 0; \
+ unlock_user_access(ptr, NULL, size); \
switch (size) { \
case 1: __put_user_asm(x, ptr, retval, "stb"); break; \
case 2: __put_user_asm(x, ptr, retval, "sth"); break; \
@@ -148,6 +150,7 @@ do { \
case 8: __put_user_asm2(x, ptr, retval); break; \
default: __put_user_bad(); \
} \
+ lock_user_access(ptr, NULL, size); \
} while (0)
#define __put_user_nocheck(x, ptr, size) \
@@ -240,6 +243,7 @@ do { \
__chk_user_ptr(ptr); \
if (size > sizeof(x)) \
(x) = __get_user_bad(); \
+ unlock_user_access(NULL, ptr, size); \
switch (size) { \
case 1: __get_user_asm(x, ptr, retval, "lbz"); break; \
case 2: __get_user_asm(x, ptr, retval, "lhz"); break; \
@@ -247,6 +251,7 @@ do { \
case 8: __get_user_asm2(x, ptr, retval); break; \
default: (x) = __get_user_bad(); \
} \
+ lock_user_access(NULL, ptr, size); \
} while (0)
/*
@@ -306,15 +311,21 @@ extern unsigned long __copy_tofrom_user(void __user *to,
static inline unsigned long
raw_copy_in_user(void __user *to, const void __user *from, unsigned long n)
{
- return __copy_tofrom_user(to, from, n);
+ unsigned long ret;
+
+ unlock_user_access(to, from, n);
+ ret = __copy_tofrom_user(to, from, n);
+ lock_user_access(to, from, n);
+ return ret;
}
#endif /* __powerpc64__ */
static inline unsigned long raw_copy_from_user(void *to,
const void __user *from, unsigned long n)
{
+ unsigned long ret;
if (__builtin_constant_p(n) && (n <= 8)) {
- unsigned long ret = 1;
+ ret = 1;
switch (n) {
case 1:
@@ -339,14 +350,18 @@ static inline unsigned long raw_copy_from_user(void *to,
}
barrier_nospec();
- return __copy_tofrom_user((__force void __user *)to, from, n);
+ unlock_user_access(NULL, from, n);
+ ret = __copy_tofrom_user((__force void __user *)to, from, n);
+ lock_user_access(NULL, from, n);
+ return ret;
}
static inline unsigned long raw_copy_to_user(void __user *to,
const void *from, unsigned long n)
{
+ unsigned long ret;
if (__builtin_constant_p(n) && (n <= 8)) {
- unsigned long ret = 1;
+ ret = 1;
switch (n) {
case 1:
@@ -366,17 +381,24 @@ static inline unsigned long raw_copy_to_user(void __user *to,
return 0;
}
- return __copy_tofrom_user(to, (__force const void __user *)from, n);
+ unlock_user_access(to, NULL, n);
+ ret = __copy_tofrom_user(to, (__force const void __user *)from, n);
+ lock_user_access(to, NULL, n);
+ return ret;
}
extern unsigned long __clear_user(void __user *addr, unsigned long size);
static inline unsigned long clear_user(void __user *addr, unsigned long size)
{
+ unsigned long ret = size;
might_fault();
- if (likely(access_ok(addr, size)))
- return __clear_user(addr, size);
- return size;
+ if (likely(access_ok(addr, size))) {
+ unlock_user_access(addr, NULL, size);
+ ret = __clear_user(addr, size);
+ lock_user_access(addr, NULL, size);
+ }
+ return ret;
}
extern long strncpy_from_user(char *dst, const char __user *src, long count);
diff --git a/arch/powerpc/kernel/asm-offsets.c b/arch/powerpc/kernel/asm-offsets.c
index 9ffc72ded73a..98e94299e728 100644
--- a/arch/powerpc/kernel/asm-offsets.c
+++ b/arch/powerpc/kernel/asm-offsets.c
@@ -93,6 +93,9 @@ int main(void)
OFFSET(THREAD_INFO, task_struct, stack);
DEFINE(THREAD_INFO_GAP, _ALIGN_UP(sizeof(struct thread_info), 16));
OFFSET(KSP_LIMIT, thread_struct, ksp_limit);
+#ifdef CONFIG_PPC_KUAP
+ OFFSET(KUAP, thread_struct, kuap);
+#endif
#endif /* CONFIG_PPC64 */
#ifdef CONFIG_LIVEPATCH
@@ -260,6 +263,7 @@ int main(void)
OFFSET(ACCOUNT_STARTTIME_USER, paca_struct, accounting.starttime_user);
OFFSET(ACCOUNT_USER_TIME, paca_struct, accounting.utime);
OFFSET(ACCOUNT_SYSTEM_TIME, paca_struct, accounting.stime);
+ OFFSET(PACA_USER_ACCESS_ALLOWED, paca_struct, user_access_allowed);
OFFSET(PACA_TRAP_SAVE, paca_struct, trap_save);
OFFSET(PACA_NAPSTATELOST, paca_struct, nap_state_lost);
OFFSET(PACA_SPRG_VDSO, paca_struct, sprg_vdso);
@@ -320,6 +324,9 @@ int main(void)
*/
STACK_PT_REGS_OFFSET(_DEAR, dar);
STACK_PT_REGS_OFFSET(_ESR, dsisr);
+#ifdef CONFIG_PPC_KUAP
+ STACK_PT_REGS_OFFSET(_KUAP, kuap);
+#endif
#else /* CONFIG_PPC64 */
STACK_PT_REGS_OFFSET(SOFTE, softe);
STACK_PT_REGS_OFFSET(_PPR, ppr);
diff --git a/arch/powerpc/kernel/entry_32.S b/arch/powerpc/kernel/entry_32.S
index 0768dfd8a64e..f8f2268f8b12 100644
--- a/arch/powerpc/kernel/entry_32.S
+++ b/arch/powerpc/kernel/entry_32.S
@@ -36,6 +36,7 @@
#include <asm/asm-405.h>
#include <asm/feature-fixups.h>
#include <asm/barrier.h>
+#include <asm/kup.h>
/*
* MSR_KERNEL is > 0x10000 on 4xx/Book-E since it include MSR_CE.
@@ -156,6 +157,7 @@ transfer_to_handler:
stw r12,_CTR(r11)
stw r2,_XER(r11)
mfspr r12,SPRN_SPRG_THREAD
+ LOCK_USER_ACCESS(r2, r11, r9, r0, r12)
addi r2,r12,-THREAD
tovirt(r2,r2) /* set r2 to current */
beq 2f /* if from user, fix up THREAD.regs */
@@ -442,6 +444,7 @@ END_FTR_SECTION_IFSET(CPU_FTR_NEED_PAIRED_STWCX)
ACCOUNT_CPU_USER_EXIT(r4, r5, r7)
3:
#endif
+ REST_USER_ACCESS(r7, r1, r4, r5, r2)
lwz r4,_LINK(r1)
lwz r5,_CCR(r1)
mtlr r4
@@ -739,7 +742,8 @@ fast_exception_return:
beq 1f /* if not, we've got problems */
#endif
-2: REST_4GPRS(3, r11)
+2: REST_USER_ACCESS(r3, r11, r4, r5, r2)
+ REST_4GPRS(3, r11)
lwz r10,_CCR(r11)
REST_GPR(1, r11)
mtcr r10
@@ -957,6 +961,8 @@ END_MMU_FTR_SECTION_IFSET(MMU_FTR_TYPE_47x)
1:
#endif /* CONFIG_TRACE_IRQFLAGS */
+ REST_USER_ACCESS(r3, r1, r4, r5, r2)
+
lwz r0,GPR0(r1)
lwz r2,GPR2(r1)
REST_4GPRS(3, r1)
diff --git a/arch/powerpc/kernel/process.c b/arch/powerpc/kernel/process.c
index ce393df243aa..995ef82a583d 100644
--- a/arch/powerpc/kernel/process.c
+++ b/arch/powerpc/kernel/process.c
@@ -1771,6 +1771,9 @@ void start_thread(struct pt_regs *regs, unsigned long start, unsigned long sp)
regs->mq = 0;
regs->nip = start;
regs->msr = MSR_USER;
+#ifdef CONFIG_PPC_KUAP
+ regs->kuap = KUAP_START;
+#endif
#else
if (!is_32bit_task()) {
unsigned long entry;
diff --git a/arch/powerpc/lib/checksum_wrappers.c b/arch/powerpc/lib/checksum_wrappers.c
index 890d4ddd91d6..48e0c91e0083 100644
--- a/arch/powerpc/lib/checksum_wrappers.c
+++ b/arch/powerpc/lib/checksum_wrappers.c
@@ -28,6 +28,7 @@ __wsum csum_and_copy_from_user(const void __user *src, void *dst,
{
unsigned int csum;
+ unlock_user_access(NULL, src, len);
might_sleep();
*err_ptr = 0;
@@ -60,6 +61,7 @@ __wsum csum_and_copy_from_user(const void __user *src, void *dst,
}
out:
+ lock_user_access(NULL, src, len);
return (__force __wsum)csum;
}
EXPORT_SYMBOL(csum_and_copy_from_user);
@@ -69,6 +71,7 @@ __wsum csum_and_copy_to_user(const void *src, void __user *dst, int len,
{
unsigned int csum;
+ unlock_user_access(dst, NULL, len);
might_sleep();
*err_ptr = 0;
@@ -97,6 +100,7 @@ __wsum csum_and_copy_to_user(const void *src, void __user *dst, int len,
}
out:
+ lock_user_access(dst, NULL, len);
return (__force __wsum)csum;
}
EXPORT_SYMBOL(csum_and_copy_to_user);
diff --git a/arch/powerpc/mm/fault.c b/arch/powerpc/mm/fault.c
index ad65e336721a..5f4a5391f41e 100644
--- a/arch/powerpc/mm/fault.c
+++ b/arch/powerpc/mm/fault.c
@@ -223,9 +223,11 @@ static int mm_fault_error(struct pt_regs *regs, unsigned long addr,
}
/* Is this a bad kernel fault ? */
-static bool bad_kernel_fault(bool is_exec, unsigned long error_code,
+static bool bad_kernel_fault(struct pt_regs *regs, unsigned long error_code,
unsigned long address)
{
+ int is_exec = TRAP(regs) == 0x400;
+
/* NX faults set DSISR_PROTFAULT on the 8xx, DSISR_NOEXEC_OR_G on others */
if (is_exec && (error_code & (DSISR_NOEXEC_OR_G | DSISR_KEYFAULT |
DSISR_PROTFAULT))) {
@@ -236,7 +238,13 @@ static bool bad_kernel_fault(bool is_exec, unsigned long error_code,
address, from_kuid(&init_user_ns,
current_uid()));
}
- return is_exec || (address >= TASK_SIZE);
+ if (!is_exec && address < TASK_SIZE && (error_code & DSISR_PROTFAULT) &&
+ !search_exception_tables(regs->nip))
+ printk_ratelimited(KERN_CRIT "Kernel attempted to access user"
+ " page (%lx) - exploit attempt? (uid: %d)\n",
+ address, from_kuid(&init_user_ns,
+ current_uid()));
+ return is_exec || (address >= TASK_SIZE) || !search_exception_tables(regs->nip);
}
static bool bad_stack_expansion(struct pt_regs *regs, unsigned long address,
@@ -456,9 +464,10 @@ static int __do_page_fault(struct pt_regs *regs, unsigned long address,
/*
* The kernel should never take an execute fault nor should it
- * take a page fault to a kernel address.
+ * take a page fault to a kernel address or a page fault to a user
+ * address outside of dedicated places
*/
- if (unlikely(!is_user && bad_kernel_fault(is_exec, error_code, address)))
+ if (unlikely(!is_user && bad_kernel_fault(regs, error_code, address)))
return SIGSEGV;
/*
diff --git a/arch/powerpc/mm/init-common.c b/arch/powerpc/mm/init-common.c
index 83f95a5565d6..ecaedfff9992 100644
--- a/arch/powerpc/mm/init-common.c
+++ b/arch/powerpc/mm/init-common.c
@@ -27,6 +27,7 @@
#include <asm/kup.h>
static bool disable_kuep = !IS_ENABLED(CONFIG_PPC_KUEP);
+static bool disable_kuap = !IS_ENABLED(CONFIG_PPC_KUAP);
static int __init parse_nosmep(char *p)
{
@@ -36,9 +37,18 @@ static int __init parse_nosmep(char *p)
}
early_param("nosmep", parse_nosmep);
+static int __init parse_nosmap(char *p)
+{
+ disable_kuap = true;
+ pr_warn("Disabling Kernel Userspace Access Protection\n");
+ return 0;
+}
+early_param("nosmap", parse_nosmap);
+
void __init setup_kup(void)
{
setup_kuep(disable_kuep);
+ setup_kuap(disable_kuap);
}
#define CTOR(shift) static void ctor_##shift(void *addr) \
diff --git a/arch/powerpc/platforms/Kconfig.cputype b/arch/powerpc/platforms/Kconfig.cputype
index 410c3443652c..7fa5ddbdce12 100644
--- a/arch/powerpc/platforms/Kconfig.cputype
+++ b/arch/powerpc/platforms/Kconfig.cputype
@@ -351,6 +351,18 @@ config PPC_KUEP
If you're unsure, say Y.
+config PPC_HAVE_KUAP
+ bool
+
+config PPC_KUAP
+ bool "Kernel Userspace Access Protection"
+ depends on PPC_HAVE_KUAP
+ default y
+ help
+ Enable support for Kernel Userspace Access Protection (KUAP)
+
+ If you're unsure, say Y.
+
config ARCH_ENABLE_HUGEPAGE_MIGRATION
def_bool y
depends on PPC_BOOK3S_64 && HUGETLB_PAGE && MIGRATION
--
2.20.1
^ permalink raw reply related
* [PATCH 4/7] powerpc/64: Setup KUP on secondary CPUs
From: Russell Currey @ 2019-02-21 9:35 UTC (permalink / raw)
To: linuxppc-dev; +Cc: Russell Currey, npiggin, kernel-hardening
In-Reply-To: <20190221093601.27920-1-ruscur@russell.cc>
Some platforms (i.e. Radix MMU) need per-CPU initialisation for KUP.
Any platforms that only want to do KUP initialisation once
globally can just check to see if they're running on the boot CPU, or
check if whatever setup they need has already been performed.
Note that this is only for 64-bit.
Signed-off-by: Russell Currey <ruscur@russell.cc>
---
arch/powerpc/kernel/setup_64.c | 3 +++
1 file changed, 3 insertions(+)
diff --git a/arch/powerpc/kernel/setup_64.c b/arch/powerpc/kernel/setup_64.c
index 771f280a6bf6..17921ee7f3a0 100644
--- a/arch/powerpc/kernel/setup_64.c
+++ b/arch/powerpc/kernel/setup_64.c
@@ -390,6 +390,9 @@ void early_setup_secondary(void)
/* Initialize the hash table or TLB handling */
early_init_mmu_secondary();
+ /* Perform any KUP setup that is per-cpu */
+ setup_kup();
+
/*
* At this point, we can let interrupts switch to virtual mode
* (the MMU has been setup), so adjust the MSR in the PACA to
--
2.20.1
^ permalink raw reply related
* [PATCH 5/7] powerpc/mm/radix: Use KUEP API for Radix MMU
From: Russell Currey @ 2019-02-21 9:35 UTC (permalink / raw)
To: linuxppc-dev; +Cc: Russell Currey, npiggin, kernel-hardening
In-Reply-To: <20190221093601.27920-1-ruscur@russell.cc>
Execution protection already exists on radix, this just refactors
the radix init to provide the KUEP setup function instead.
Thus, the only functional change is that it can now be disabled.
Signed-off-by: Russell Currey <ruscur@russell.cc>
---
arch/powerpc/mm/pgtable-radix.c | 12 +++++++++---
arch/powerpc/platforms/Kconfig.cputype | 1 +
2 files changed, 10 insertions(+), 3 deletions(-)
diff --git a/arch/powerpc/mm/pgtable-radix.c b/arch/powerpc/mm/pgtable-radix.c
index 931156069a81..224bcd4be5ae 100644
--- a/arch/powerpc/mm/pgtable-radix.c
+++ b/arch/powerpc/mm/pgtable-radix.c
@@ -535,8 +535,15 @@ static void radix_init_amor(void)
mtspr(SPRN_AMOR, (3ul << 62));
}
-static void radix_init_iamr(void)
+#ifdef CONFIG_PPC_KUEP
+void __init setup_kuep(bool disabled)
{
+ if (disabled || !early_radix_enabled())
+ return;
+
+ if (smp_processor_id() == boot_cpuid)
+ pr_info("Activating Kernel Userspace Execution Prevention\n");
+
/*
* Radix always uses key0 of the IAMR to determine if an access is
* allowed. We set bit 0 (IBM bit 1) of key0, to prevent instruction
@@ -544,6 +551,7 @@ static void radix_init_iamr(void)
*/
mtspr(SPRN_IAMR, (1ul << 62));
}
+#endif
void __init radix__early_init_mmu(void)
{
@@ -605,7 +613,6 @@ void __init radix__early_init_mmu(void)
memblock_set_current_limit(MEMBLOCK_ALLOC_ANYWHERE);
- radix_init_iamr();
radix_init_pgtable();
/* Switch to the guard PID before turning on MMU */
radix__switch_mmu_context(NULL, &init_mm);
@@ -627,7 +634,6 @@ void radix__early_init_mmu_secondary(void)
__pa(partition_tb) | (PATB_SIZE_SHIFT - 12));
radix_init_amor();
}
- radix_init_iamr();
radix__switch_mmu_context(NULL, &init_mm);
if (cpu_has_feature(CPU_FTR_HVMODE))
diff --git a/arch/powerpc/platforms/Kconfig.cputype b/arch/powerpc/platforms/Kconfig.cputype
index 7fa5ddbdce12..25cc7d36b27d 100644
--- a/arch/powerpc/platforms/Kconfig.cputype
+++ b/arch/powerpc/platforms/Kconfig.cputype
@@ -320,6 +320,7 @@ config PPC_RADIX_MMU
bool "Radix MMU Support"
depends on PPC_BOOK3S_64
select ARCH_HAS_GIGANTIC_PAGE if (MEMORY_ISOLATION && COMPACTION) || CMA
+ select PPC_HAVE_KUEP
default y
help
Enable support for the Power ISA 3.0 Radix style MMU. Currently this
--
2.20.1
^ permalink raw reply related
* [PATCH 6/7] powerpc/lib: Refactor __patch_instruction() to use __put_user_asm()
From: Russell Currey @ 2019-02-21 9:36 UTC (permalink / raw)
To: linuxppc-dev; +Cc: Russell Currey, npiggin, kernel-hardening
In-Reply-To: <20190221093601.27920-1-ruscur@russell.cc>
__patch_instruction() is called in early boot, and uses
__put_user_size(), which includes the locks and unlocks for KUAP,
which could either be called too early, or in the Radix case, forced to
use "early_" versions of functions just to safely handle this one case.
__put_user_asm() does not do this, and thus is safe to use both in early
boot, and later on since in this case it should only ever be touching
kernel memory.
__patch_instruction() was previously refactored to use __put_user_size()
in order to be able to return -EFAULT, which would allow the kernel to
patch instructions in userspace, which should never happen. This has
the functional change of causing faults on userspace addresses if KUAP
is turned on, which should never happen in practice.
A future enhancement could be to double check the patch address is
definitely allowed to be tampered with by the kernel.
Signed-off-by: Russell Currey <ruscur@russell.cc>
---
arch/powerpc/lib/code-patching.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/arch/powerpc/lib/code-patching.c b/arch/powerpc/lib/code-patching.c
index 506413a2c25e..42fdadac6587 100644
--- a/arch/powerpc/lib/code-patching.c
+++ b/arch/powerpc/lib/code-patching.c
@@ -26,9 +26,9 @@
static int __patch_instruction(unsigned int *exec_addr, unsigned int instr,
unsigned int *patch_addr)
{
- int err;
+ int err = 0;
- __put_user_size(instr, patch_addr, 4, err);
+ __put_user_asm(instr, patch_addr, err, "stw");
if (err)
return err;
--
2.20.1
^ permalink raw reply related
* [PATCH 7/7] powerpc/64s: Implement KUAP for Radix MMU
From: Russell Currey @ 2019-02-21 9:36 UTC (permalink / raw)
To: linuxppc-dev; +Cc: Russell Currey, npiggin, kernel-hardening
In-Reply-To: <20190221093601.27920-1-ruscur@russell.cc>
Kernel Userspace Access Prevention utilises a feature of the Radix MMU
which disallows read and write access to userspace addresses. By
utilising this, the kernel is prevented from accessing user data from
outside of trusted paths that perform proper safety checks, such as
copy_{to/from}_user() and friends.
Userspace access is disabled from early boot and is only enabled when
performing an operation like copy_{to/from}_user(). The register that
controls this (AMR) does not prevent userspace from accessing other
userspace, so there is no need to save and restore when entering and
exiting userspace.
This feature has a slight performance impact which I roughly measured
to be 3% slower in the worst case (performing 1GB of 1 byte
read()/write() syscalls), and is gated behind the CONFIG_PPC_KUAP
option for performance-critical builds.
This feature can be tested by using the lkdtm driver (CONFIG_LKDTM=y)
and performing the following:
# (echo ACCESS_USERSPACE) > [debugfs]/provoke-crash/DIRECT
If enabled, this should send SIGSEGV to the thread.
A big limitation of the current implementation is that user access
is left unlocked if an exception is taken while user access is unlocked
(i.e. if an interrupt is taken during copy_to_user()). This should be
resolved in future, and is why the state is tracked in the PACA even
though nothing currently uses it.
Signed-off-by: Russell Currey <ruscur@russell.cc>
---
.../powerpc/include/asm/book3s/64/kup-radix.h | 36 +++++++++++++++++++
arch/powerpc/include/asm/kup.h | 4 +++
arch/powerpc/include/asm/mmu.h | 9 ++++-
arch/powerpc/include/asm/reg.h | 1 +
arch/powerpc/mm/pgtable-radix.c | 16 +++++++++
arch/powerpc/mm/pkeys.c | 7 ++--
arch/powerpc/platforms/Kconfig.cputype | 1 +
7 files changed, 71 insertions(+), 3 deletions(-)
create mode 100644 arch/powerpc/include/asm/book3s/64/kup-radix.h
diff --git a/arch/powerpc/include/asm/book3s/64/kup-radix.h b/arch/powerpc/include/asm/book3s/64/kup-radix.h
new file mode 100644
index 000000000000..5cfdea954418
--- /dev/null
+++ b/arch/powerpc/include/asm/book3s/64/kup-radix.h
@@ -0,0 +1,36 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef _ASM_POWERPC_KUP_RADIX_H
+#define _ASM_POWERPC_KUP_RADIX_H
+
+#ifndef __ASSEMBLY__
+#ifdef CONFIG_PPC_KUAP
+#include <asm/reg.h>
+/*
+ * We do have the ability to individually lock/unlock reads and writes rather
+ * than both at once, however it's a significant performance hit due to needing
+ * to do a read-modify-write, which adds a mfspr, which is slow. As a result,
+ * locking/unlocking both at once is preferred.
+ */
+static inline void unlock_user_access(void __user *to, const void __user *from,
+ unsigned long size)
+{
+ if (!mmu_has_feature(MMU_FTR_RADIX_KUAP))
+ return;
+
+ mtspr(SPRN_AMR, 0);
+ isync();
+ get_paca()->user_access_allowed = 1;
+}
+
+static inline void lock_user_access(void __user *to, const void __user *from,
+ unsigned long size)
+{
+ if (!mmu_has_feature(MMU_FTR_RADIX_KUAP))
+ return;
+
+ mtspr(SPRN_AMR, RADIX_AMR_LOCKED);
+ get_paca()->user_access_allowed = 0;
+}
+#endif /* CONFIG_PPC_KUAP */
+#endif /* __ASSEMBLY__ */
+#endif
diff --git a/arch/powerpc/include/asm/kup.h b/arch/powerpc/include/asm/kup.h
index 2ac540fb488f..af583fd5a027 100644
--- a/arch/powerpc/include/asm/kup.h
+++ b/arch/powerpc/include/asm/kup.h
@@ -2,6 +2,10 @@
#ifndef _ASM_POWERPC_KUP_H_
#define _ASM_POWERPC_KUP_H_
+#ifdef CONFIG_PPC_BOOK3S_64
+#include <asm/book3s/64/kup-radix.h>
+#endif
+
#ifndef __ASSEMBLY__
#include <asm/pgtable.h>
diff --git a/arch/powerpc/include/asm/mmu.h b/arch/powerpc/include/asm/mmu.h
index 25607604a7a5..ea703de9be9b 100644
--- a/arch/powerpc/include/asm/mmu.h
+++ b/arch/powerpc/include/asm/mmu.h
@@ -107,6 +107,10 @@
*/
#define MMU_FTR_1T_SEGMENT ASM_CONST(0x40000000)
+/* Supports KUAP (key 0 controlling userspace addresses) on radix
+ */
+#define MMU_FTR_RADIX_KUAP ASM_CONST(0x80000000)
+
/* MMU feature bit sets for various CPUs */
#define MMU_FTRS_DEFAULT_HPTE_ARCH_V2 \
MMU_FTR_HPTE_TABLE | MMU_FTR_PPCAS_ARCH_V2
@@ -164,7 +168,10 @@ enum {
#endif
#ifdef CONFIG_PPC_RADIX_MMU
MMU_FTR_TYPE_RADIX |
-#endif
+#ifdef CONFIG_PPC_KUAP
+ MMU_FTR_RADIX_KUAP |
+#endif /* CONFIG_PPC_KUAP */
+#endif /* CONFIG_PPC_RADIX_MMU */
0,
};
diff --git a/arch/powerpc/include/asm/reg.h b/arch/powerpc/include/asm/reg.h
index 1c98ef1f2d5b..0e789e2c5bc3 100644
--- a/arch/powerpc/include/asm/reg.h
+++ b/arch/powerpc/include/asm/reg.h
@@ -246,6 +246,7 @@
#define SPRN_DSCR 0x11
#define SPRN_CFAR 0x1c /* Come From Address Register */
#define SPRN_AMR 0x1d /* Authority Mask Register */
+#define RADIX_AMR_LOCKED 0xC000000000000000UL /* Read & Write disabled */
#define SPRN_UAMOR 0x9d /* User Authority Mask Override Register */
#define SPRN_AMOR 0x15d /* Authority Mask Override Register */
#define SPRN_ACOP 0x1F /* Available Coprocessor Register */
diff --git a/arch/powerpc/mm/pgtable-radix.c b/arch/powerpc/mm/pgtable-radix.c
index 224bcd4be5ae..b621cef4825e 100644
--- a/arch/powerpc/mm/pgtable-radix.c
+++ b/arch/powerpc/mm/pgtable-radix.c
@@ -29,6 +29,7 @@
#include <asm/powernv.h>
#include <asm/sections.h>
#include <asm/trace.h>
+#include <asm/uaccess.h>
#include <trace/events/thp.h>
@@ -553,6 +554,21 @@ void __init setup_kuep(bool disabled)
}
#endif
+#ifdef CONFIG_PPC_KUAP
+void __init setup_kuap(bool disabled)
+{
+ if (disabled || !early_radix_enabled())
+ return;
+
+ if (smp_processor_id() == boot_cpuid) {
+ pr_info("Activating Kernel Userspace Access Prevention\n");
+ cur_cpu_spec->mmu_features |= MMU_FTR_RADIX_KUAP;
+ }
+
+ mtspr(SPRN_AMR, RADIX_AMR_LOCKED);
+}
+#endif
+
void __init radix__early_init_mmu(void)
{
unsigned long lpcr;
diff --git a/arch/powerpc/mm/pkeys.c b/arch/powerpc/mm/pkeys.c
index 587807763737..2223f4b4b1bf 100644
--- a/arch/powerpc/mm/pkeys.c
+++ b/arch/powerpc/mm/pkeys.c
@@ -7,6 +7,7 @@
#include <asm/mman.h>
#include <asm/mmu_context.h>
+#include <asm/mmu.h>
#include <asm/setup.h>
#include <linux/pkeys.h>
#include <linux/of_device.h>
@@ -267,7 +268,8 @@ int __arch_set_user_pkey_access(struct task_struct *tsk, int pkey,
void thread_pkey_regs_save(struct thread_struct *thread)
{
- if (static_branch_likely(&pkey_disabled))
+ if (static_branch_likely(&pkey_disabled) &&
+ !mmu_has_feature(MMU_FTR_RADIX_KUAP))
return;
/*
@@ -281,7 +283,8 @@ void thread_pkey_regs_save(struct thread_struct *thread)
void thread_pkey_regs_restore(struct thread_struct *new_thread,
struct thread_struct *old_thread)
{
- if (static_branch_likely(&pkey_disabled))
+ if (static_branch_likely(&pkey_disabled) &&
+ !mmu_has_feature(MMU_FTR_RADIX_KUAP))
return;
if (old_thread->amr != new_thread->amr)
diff --git a/arch/powerpc/platforms/Kconfig.cputype b/arch/powerpc/platforms/Kconfig.cputype
index 25cc7d36b27d..67b2ed9bb9f3 100644
--- a/arch/powerpc/platforms/Kconfig.cputype
+++ b/arch/powerpc/platforms/Kconfig.cputype
@@ -321,6 +321,7 @@ config PPC_RADIX_MMU
depends on PPC_BOOK3S_64
select ARCH_HAS_GIGANTIC_PAGE if (MEMORY_ISOLATION && COMPACTION) || CMA
select PPC_HAVE_KUEP
+ select PPC_HAVE_KUAP
default y
help
Enable support for the Power ISA 3.0 Radix style MMU. Currently this
--
2.20.1
^ permalink raw reply related
* [PATCH] ASoC: fsl_esai: fix channel swap issue when stream starts
From: S.j. Wang @ 2019-02-21 9:53 UTC (permalink / raw)
To: timur@kernel.org, nicoleotsuka@gmail.com, Xiubo.Lee@gmail.com,
festevam@gmail.com, broonie@kernel.org,
alsa-devel@alsa-project.org
Cc: linuxppc-dev@lists.ozlabs.org
From: Shengjiu Wang <shengjiu.wang@freescale.com>
There is very low possibility ( < 0.1% ) that channel swap happened
in beginning when multi output/input pin is enabled. The issue is
that hardware can't send data to correct pin in the begginning with
the normal enable flow.
This is hardware issue, the workaround flow is that: Each time
playback/recording, firstly clear the xSMA/xSMB, then enable TE/RE,
then enable xSMB and xSMA (xSMB must be enabled before xSMA).
Which is to use the xSMA as the trigger start register, previously
the xCR_TE or xCR_RE is the bit for starting
Signed-off-by: Shengjiu Wang <shengjiu.wang@freescale.com>
---
sound/soc/fsl/fsl_esai.c | 32 ++++++++++++++++++++++----------
1 file changed, 22 insertions(+), 10 deletions(-)
diff --git a/sound/soc/fsl/fsl_esai.c b/sound/soc/fsl/fsl_esai.c
index afe67c865330..23bd0ad4ac31 100644
--- a/sound/soc/fsl/fsl_esai.c
+++ b/sound/soc/fsl/fsl_esai.c
@@ -54,6 +54,8 @@ struct fsl_esai {
u32 fifo_depth;
u32 slot_width;
u32 slots;
+ u32 tx_mask;
+ u32 rx_mask;
u32 hck_rate[2];
u32 sck_rate[2];
bool hck_dir[2];
@@ -361,21 +363,13 @@ static int fsl_esai_set_dai_tdm_slot(struct snd_soc_dai *dai, u32 tx_mask,
regmap_update_bits(esai_priv->regmap, REG_ESAI_TCCR,
ESAI_xCCR_xDC_MASK, ESAI_xCCR_xDC(slots));
- regmap_update_bits(esai_priv->regmap, REG_ESAI_TSMA,
- ESAI_xSMA_xS_MASK, ESAI_xSMA_xS(tx_mask));
- regmap_update_bits(esai_priv->regmap, REG_ESAI_TSMB,
- ESAI_xSMB_xS_MASK, ESAI_xSMB_xS(tx_mask));
-
regmap_update_bits(esai_priv->regmap, REG_ESAI_RCCR,
ESAI_xCCR_xDC_MASK, ESAI_xCCR_xDC(slots));
- regmap_update_bits(esai_priv->regmap, REG_ESAI_RSMA,
- ESAI_xSMA_xS_MASK, ESAI_xSMA_xS(rx_mask));
- regmap_update_bits(esai_priv->regmap, REG_ESAI_RSMB,
- ESAI_xSMB_xS_MASK, ESAI_xSMB_xS(rx_mask));
-
esai_priv->slot_width = slot_width;
esai_priv->slots = slots;
+ esai_priv->tx_mask = tx_mask;
+ esai_priv->rx_mask = rx_mask;
return 0;
}
@@ -596,6 +590,7 @@ static int fsl_esai_trigger(struct snd_pcm_substream *substream, int cmd,
bool tx = substream->stream == SNDRV_PCM_STREAM_PLAYBACK;
u8 i, channels = substream->runtime->channels;
u32 pins = DIV_ROUND_UP(channels, esai_priv->slots);
+ u32 mask;
switch (cmd) {
case SNDRV_PCM_TRIGGER_START:
@@ -611,12 +606,23 @@ static int fsl_esai_trigger(struct snd_pcm_substream *substream, int cmd,
regmap_update_bits(esai_priv->regmap, REG_ESAI_xCR(tx),
tx ? ESAI_xCR_TE_MASK : ESAI_xCR_RE_MASK,
tx ? ESAI_xCR_TE(pins) : ESAI_xCR_RE(pins));
+ mask = tx ? esai_priv->tx_mask : esai_priv->rx_mask;
+
+ regmap_update_bits(esai_priv->regmap, REG_ESAI_xSMB(tx),
+ ESAI_xSMB_xS_MASK, ESAI_xSMB_xS(mask));
+ regmap_update_bits(esai_priv->regmap, REG_ESAI_xSMA(tx),
+ ESAI_xSMA_xS_MASK, ESAI_xSMA_xS(mask));
+
break;
case SNDRV_PCM_TRIGGER_SUSPEND:
case SNDRV_PCM_TRIGGER_STOP:
case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
regmap_update_bits(esai_priv->regmap, REG_ESAI_xCR(tx),
tx ? ESAI_xCR_TE_MASK : ESAI_xCR_RE_MASK, 0);
+ regmap_update_bits(esai_priv->regmap, REG_ESAI_xSMA(tx),
+ ESAI_xSMA_xS_MASK, 0);
+ regmap_update_bits(esai_priv->regmap, REG_ESAI_xSMB(tx),
+ ESAI_xSMB_xS_MASK, 0);
/* Disable and reset FIFO */
regmap_update_bits(esai_priv->regmap, REG_ESAI_xFCR(tx),
@@ -906,6 +912,12 @@ static int fsl_esai_probe(struct platform_device *pdev)
return ret;
}
+ /* Clear the TSMA, TSMB, RSMA, RSMB */
+ regmap_write(esai_priv->regmap, REG_ESAI_TSMA, 0);
+ regmap_write(esai_priv->regmap, REG_ESAI_TSMB, 0);
+ regmap_write(esai_priv->regmap, REG_ESAI_RSMA, 0);
+ regmap_write(esai_priv->regmap, REG_ESAI_RSMB, 0);
+
ret = devm_snd_soc_register_component(&pdev->dev, &fsl_esai_component,
&fsl_esai_dai, 1);
if (ret) {
--
1.9.1
^ permalink raw reply related
* Re: [PATCH 1/4] powerpc/64s: Fix HV NMI vs HV interrupt recoverability test
From: Michael Ellerman @ 2019-02-21 10:05 UTC (permalink / raw)
To: Nicholas Piggin, linuxppc-dev
In-Reply-To: <1550672893.su6y10x0gg.astroid@bobo.none>
Nicholas Piggin <npiggin@gmail.com> writes:
> Nicholas Piggin's on January 22, 2019 4:46 pm:
>> HV interrupts that use HSRR registers do not clear MSR[RI], but
>> NMI entry code is not recoverable early on due to both using HSPRG
>> for a scratch register.
>>
>> This bug means that a system reset or machine check can cause silent
>> data corruption (due to loss of r13 register) if it hits in a small
>> window when taking an HV interrupt.
>>
>> Fix this by marking NMIs non-recoverable if they land in HV interrupt
>> ranges.
>
> Hum, I had a v2 that I didn't send properly with a small compile fix,
> but I've also just noticed this:
>
>> +void hv_nmi_check_nonrecoverable(struct pt_regs *regs)
>> +{
>> +#ifdef CONFIG_POWERNV
>> + unsigned long kbase = (unsigned long)_stext;
>> + unsigned long nip = regs->nip;
>> +
>> + if (!(regs->msr & MSR_RI))
>> + return;
>> + if (!(regs->msr & MSR_HV))
>> + return;
>> + if (regs->msr & MSR_PR)
>> + return;
>> +again:
>> + if (nip >= 0x500 && nip < 0x600)
>> + goto nonrecoverable;
>> + if (nip >= 0x980 && nip < 0xa00)
>> + goto nonrecoverable;
>> + if (nip >= 0xe00 && nip < 0xec0)
>> + goto nonrecoverable;
>> + if (nip >= 0xf80 && nip < 0xfa0)
>> + goto nonrecoverable;
>> + /* Trampolines are not relocated. */
>> + if (nip >= real_trampolines_start - kbase &&
>> + nip < real_trampolines_end - kbase)
>> + goto nonrecoverable;
>> + if (nip >= virt_trampolines_start - kbase &&
>> + nip < virt_trampolines_end - kbase)
>> + goto nonrecoverable;
>> + if (nip >= 0xc000000000000000ULL) {
>> + nip -= 0xc000000000000000ULL;
>> + goto again;
>
> Tried to be a bit too clever here. The 0xc... vectors also have a
> +0x4000 offset so this won't catch them properly. I'll respin.
Thanks.
I'm seeing the same build error as the kbuild robot too.
cheers
^ permalink raw reply
* Re: [PATCH] ASoC: fsl_esai: fix channel swap issue when stream starts
From: Fabio Estevam @ 2019-02-21 10:29 UTC (permalink / raw)
To: S.j. Wang
Cc: alsa-devel@alsa-project.org, timur@kernel.org,
Xiubo.Lee@gmail.com, nicoleotsuka@gmail.com, broonie@kernel.org,
linuxppc-dev@lists.ozlabs.org
In-Reply-To: <1550742787-3268-1-git-send-email-shengjiu.wang@nxp.com>
Hi Shengjiu.
On Thu, Feb 21, 2019 at 6:53 AM S.j. Wang <shengjiu.wang@nxp.com> wrote:
>
> From: Shengjiu Wang <shengjiu.wang@freescale.com>
Better use your nxp.com address as the freescale.com domain is gone
for a long time.
> There is very low possibility ( < 0.1% ) that channel swap happened
> in beginning when multi output/input pin is enabled. The issue is
> that hardware can't send data to correct pin in the begginning with
s/begginning/beginning
> the normal enable flow.
>
> This is hardware issue, the workaround flow is that: Each time
Is there an erratum reference for this issue? If so, please add it here.
> playback/recording, firstly clear the xSMA/xSMB, then enable TE/RE,
> then enable xSMB and xSMA (xSMB must be enabled before xSMA).
> Which is to use the xSMA as the trigger start register, previously
> the xCR_TE or xCR_RE is the bit for starting
Please add a Fixes tag and Cc stable.
> Signed-off-by: Shengjiu Wang <shengjiu.wang@freescale.com>
Reviewed-by: Fabio Estevam <festevam@gmail.com>
Thanks
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox