* [PATCH v16 05/21] powerpc: prep stack walkers for THREAD_INFO_IN_TASK
From: Michael Ellerman @ 2019-02-05 11:32 UTC (permalink / raw)
To: linuxppc-dev; +Cc: npiggin
In-Reply-To: <20190205113219.17903-1-mpe@ellerman.id.au>
From: Christophe Leroy <christophe.leroy@c-s.fr>
[text copied from commit 9bbd4c56b0b6
("arm64: prep stack walkers for THREAD_INFO_IN_TASK")]
When CONFIG_THREAD_INFO_IN_TASK is selected, task stacks may be freed
before a task is destroyed. To account for this, the stacks are
refcounted, and when manipulating the stack of another task, it is
necessary to get/put the stack to ensure it isn't freed and/or re-used
while we do so.
This patch reworks the powerpc stack walking code to account for this.
When CONFIG_THREAD_INFO_IN_TASK is not selected these perform no
refcounting, and this should only be a structural change that does not
affect behaviour.
Acked-by: Mark Rutland <mark.rutland@arm.com>
Signed-off-by: Christophe Leroy <christophe.leroy@c-s.fr>
Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
---
arch/powerpc/kernel/process.c | 23 +++++++++++++++++++++--
arch/powerpc/kernel/stacktrace.c | 29 ++++++++++++++++++++++++++---
2 files changed, 47 insertions(+), 5 deletions(-)
diff --git a/arch/powerpc/kernel/process.c b/arch/powerpc/kernel/process.c
index ce393df243aa..4ffbb677c9f5 100644
--- a/arch/powerpc/kernel/process.c
+++ b/arch/powerpc/kernel/process.c
@@ -2027,7 +2027,7 @@ int validate_sp(unsigned long sp, struct task_struct *p,
EXPORT_SYMBOL(validate_sp);
-unsigned long get_wchan(struct task_struct *p)
+static unsigned long __get_wchan(struct task_struct *p)
{
unsigned long ip, sp;
int count = 0;
@@ -2053,6 +2053,20 @@ unsigned long get_wchan(struct task_struct *p)
return 0;
}
+unsigned long get_wchan(struct task_struct *p)
+{
+ unsigned long ret;
+
+ if (!try_get_task_stack(p))
+ return 0;
+
+ ret = __get_wchan(p);
+
+ put_task_stack(p);
+
+ return ret;
+}
+
static int kstack_depth_to_print = CONFIG_PRINT_STACK_DEPTH;
void show_stack(struct task_struct *tsk, unsigned long *stack)
@@ -2067,6 +2081,9 @@ void show_stack(struct task_struct *tsk, unsigned long *stack)
int curr_frame = 0;
#endif
+ if (!try_get_task_stack(tsk))
+ return;
+
sp = (unsigned long) stack;
if (tsk == NULL)
tsk = current;
@@ -2081,7 +2098,7 @@ void show_stack(struct task_struct *tsk, unsigned long *stack)
printk("Call Trace:\n");
do {
if (!validate_sp(sp, tsk, STACK_FRAME_OVERHEAD))
- return;
+ break;
stack = (unsigned long *) sp;
newsp = stack[0];
@@ -2121,6 +2138,8 @@ void show_stack(struct task_struct *tsk, unsigned long *stack)
sp = newsp;
} while (count++ < kstack_depth_to_print);
+
+ put_task_stack(tsk);
}
#ifdef CONFIG_PPC64
diff --git a/arch/powerpc/kernel/stacktrace.c b/arch/powerpc/kernel/stacktrace.c
index cf31ce6c1f53..f958f3bcba04 100644
--- a/arch/powerpc/kernel/stacktrace.c
+++ b/arch/powerpc/kernel/stacktrace.c
@@ -67,12 +67,17 @@ void save_stack_trace_tsk(struct task_struct *tsk, struct stack_trace *trace)
{
unsigned long sp;
+ if (!try_get_task_stack(tsk))
+ return;
+
if (tsk == current)
sp = current_stack_pointer();
else
sp = tsk->thread.ksp;
save_context_stack(trace, sp, tsk, 0);
+
+ put_task_stack(tsk);
}
EXPORT_SYMBOL_GPL(save_stack_trace_tsk);
@@ -90,9 +95,8 @@ EXPORT_SYMBOL_GPL(save_stack_trace_regs);
*
* If the task is not 'current', the caller *must* ensure the task is inactive.
*/
-int
-save_stack_trace_tsk_reliable(struct task_struct *tsk,
- struct stack_trace *trace)
+static int __save_stack_trace_tsk_reliable(struct task_struct *tsk,
+ struct stack_trace *trace)
{
unsigned long sp;
unsigned long newsp;
@@ -197,6 +201,25 @@ save_stack_trace_tsk_reliable(struct task_struct *tsk,
}
return 0;
}
+
+int save_stack_trace_tsk_reliable(struct task_struct *tsk,
+ struct stack_trace *trace)
+{
+ int ret;
+
+ /*
+ * If the task doesn't have a stack (e.g., a zombie), the stack is
+ * "reliably" empty.
+ */
+ if (!try_get_task_stack(tsk))
+ return 0;
+
+ ret = __save_stack_trace_tsk_reliable(tsk, trace);
+
+ put_task_stack(tsk);
+
+ return ret;
+}
EXPORT_SYMBOL_GPL(save_stack_trace_tsk_reliable);
#endif /* CONFIG_HAVE_RELIABLE_STACKTRACE */
--
2.20.1
^ permalink raw reply related
* [PATCH v16 04/21] powerpc: Only use task_struct 'cpu' field on SMP
From: Michael Ellerman @ 2019-02-05 11:32 UTC (permalink / raw)
To: linuxppc-dev; +Cc: npiggin
In-Reply-To: <20190205113219.17903-1-mpe@ellerman.id.au>
From: Christophe Leroy <christophe.leroy@c-s.fr>
When moving to CONFIG_THREAD_INFO_IN_TASK, the thread_info 'cpu' field
gets moved into task_struct and only defined when CONFIG_SMP is set.
This patch ensures that TI_CPU is only used when CONFIG_SMP is set and
that task_struct 'cpu' field is not used directly out of SMP code.
Signed-off-by: Christophe Leroy <christophe.leroy@c-s.fr>
Reviewed-by: Nicholas Piggin <npiggin@gmail.com>
Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
---
arch/powerpc/kernel/head_fsl_booke.S | 2 ++
arch/powerpc/kernel/misc_32.S | 4 ++++
arch/powerpc/xmon/xmon.c | 2 +-
3 files changed, 7 insertions(+), 1 deletion(-)
diff --git a/arch/powerpc/kernel/head_fsl_booke.S b/arch/powerpc/kernel/head_fsl_booke.S
index 2386ce2a9c6e..2c21e8642a00 100644
--- a/arch/powerpc/kernel/head_fsl_booke.S
+++ b/arch/powerpc/kernel/head_fsl_booke.S
@@ -243,8 +243,10 @@ _ENTRY(__early_start)
li r0,0
stwu r0,THREAD_SIZE-STACK_FRAME_OVERHEAD(r1)
+#ifdef CONFIG_SMP
CURRENT_THREAD_INFO(r22, r1)
stw r24, TI_CPU(r22)
+#endif
bl early_init
diff --git a/arch/powerpc/kernel/misc_32.S b/arch/powerpc/kernel/misc_32.S
index 57d2ffb2d45c..02b8cdd73792 100644
--- a/arch/powerpc/kernel/misc_32.S
+++ b/arch/powerpc/kernel/misc_32.S
@@ -183,10 +183,14 @@ _GLOBAL(low_choose_750fx_pll)
or r4,r4,r5
mtspr SPRN_HID1,r4
+#ifdef CONFIG_SMP
/* Store new HID1 image */
CURRENT_THREAD_INFO(r6, r1)
lwz r6,TI_CPU(r6)
slwi r6,r6,2
+#else
+ li r6, 0
+#endif
addis r6,r6,nap_save_hid1@ha
stw r4,nap_save_hid1@l(r6)
diff --git a/arch/powerpc/xmon/xmon.c b/arch/powerpc/xmon/xmon.c
index 757b8499aba2..a0f44f992360 100644
--- a/arch/powerpc/xmon/xmon.c
+++ b/arch/powerpc/xmon/xmon.c
@@ -2997,7 +2997,7 @@ static void show_task(struct task_struct *tsk)
printf("%px %016lx %6d %6d %c %2d %s\n", tsk,
tsk->thread.ksp,
tsk->pid, rcu_dereference(tsk->parent)->pid,
- state, task_thread_info(tsk)->cpu,
+ state, task_cpu(tsk),
tsk->comm);
}
--
2.20.1
^ permalink raw reply related
* [PATCH v16 03/21] powerpc: Avoid circular header inclusion in mmu-hash.h
From: Michael Ellerman @ 2019-02-05 11:32 UTC (permalink / raw)
To: linuxppc-dev; +Cc: npiggin
In-Reply-To: <20190205113219.17903-1-mpe@ellerman.id.au>
From: Christophe Leroy <christophe.leroy@c-s.fr>
When activating CONFIG_THREAD_INFO_IN_TASK, linux/sched.h includes
asm/current.h. This generates a circular dependency. To avoid that,
asm/processor.h shall not be included in mmu-hash.h.
In order to do that, this patch moves into a new header called
asm/task_size_64/32.h all the TASK_SIZE related constants, which can
then be included in mmu-hash.h directly.
Signed-off-by: Christophe Leroy <christophe.leroy@c-s.fr>
Reviewed-by: Nicholas Piggin <npiggin@gmail.com>
[mpe: Split out all the TASK_SIZE constants not just 64-bit ones]
Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
---
arch/powerpc/include/asm/book3s/64/mmu-hash.h | 2 +-
arch/powerpc/include/asm/processor.h | 100 +-----------------
arch/powerpc/include/asm/task_size_32.h | 21 ++++
arch/powerpc/include/asm/task_size_64.h | 79 ++++++++++++++
arch/powerpc/kvm/book3s_hv_hmi.c | 1 +
5 files changed, 107 insertions(+), 96 deletions(-)
create mode 100644 arch/powerpc/include/asm/task_size_32.h
create mode 100644 arch/powerpc/include/asm/task_size_64.h
diff --git a/arch/powerpc/include/asm/book3s/64/mmu-hash.h b/arch/powerpc/include/asm/book3s/64/mmu-hash.h
index 12e522807f9f..a28a28079edb 100644
--- a/arch/powerpc/include/asm/book3s/64/mmu-hash.h
+++ b/arch/powerpc/include/asm/book3s/64/mmu-hash.h
@@ -23,7 +23,7 @@
*/
#include <asm/book3s/64/pgtable.h>
#include <asm/bug.h>
-#include <asm/processor.h>
+#include <asm/task_size_64.h>
#include <asm/cpu_has_feature.h>
/*
diff --git a/arch/powerpc/include/asm/processor.h b/arch/powerpc/include/asm/processor.h
index ee58526cb6c2..d9b1503ba0f0 100644
--- a/arch/powerpc/include/asm/processor.h
+++ b/arch/powerpc/include/asm/processor.h
@@ -77,105 +77,15 @@ extern int _chrp_type;
#ifdef __KERNEL__
-struct task_struct;
-void start_thread(struct pt_regs *regs, unsigned long fdptr, unsigned long sp);
-void release_thread(struct task_struct *);
-
-#ifdef CONFIG_PPC32
-
-#if CONFIG_TASK_SIZE > CONFIG_KERNEL_START
-#error User TASK_SIZE overlaps with KERNEL_START address
-#endif
-#define TASK_SIZE (CONFIG_TASK_SIZE)
-
-/* This decides where the kernel will search for a free chunk of vm
- * space during mmap's.
- */
-#define TASK_UNMAPPED_BASE (TASK_SIZE / 8 * 3)
-#endif
-
#ifdef CONFIG_PPC64
-/*
- * 64-bit user address space can have multiple limits
- * For now supported values are:
- */
-#define TASK_SIZE_64TB (0x0000400000000000UL)
-#define TASK_SIZE_128TB (0x0000800000000000UL)
-#define TASK_SIZE_512TB (0x0002000000000000UL)
-#define TASK_SIZE_1PB (0x0004000000000000UL)
-#define TASK_SIZE_2PB (0x0008000000000000UL)
-/*
- * With 52 bits in the address we can support
- * upto 4PB of range.
- */
-#define TASK_SIZE_4PB (0x0010000000000000UL)
-
-/*
- * For now 512TB is only supported with book3s and 64K linux page size.
- */
-#if defined(CONFIG_PPC_BOOK3S_64) && defined(CONFIG_PPC_64K_PAGES)
-/*
- * Max value currently used:
- */
-#define TASK_SIZE_USER64 TASK_SIZE_4PB
-#define DEFAULT_MAP_WINDOW_USER64 TASK_SIZE_128TB
-#define TASK_CONTEXT_SIZE TASK_SIZE_512TB
-#else
-#define TASK_SIZE_USER64 TASK_SIZE_64TB
-#define DEFAULT_MAP_WINDOW_USER64 TASK_SIZE_64TB
-/*
- * We don't need to allocate extended context ids for 4K page size, because
- * we limit the max effective address on this config to 64TB.
- */
-#define TASK_CONTEXT_SIZE TASK_SIZE_64TB
-#endif
-
-/*
- * 32-bit user address space is 4GB - 1 page
- * (this 1 page is needed so referencing of 0xFFFFFFFF generates EFAULT
- */
-#define TASK_SIZE_USER32 (0x0000000100000000UL - (1*PAGE_SIZE))
-
-#define TASK_SIZE_OF(tsk) (test_tsk_thread_flag(tsk, TIF_32BIT) ? \
- TASK_SIZE_USER32 : TASK_SIZE_USER64)
-#define TASK_SIZE TASK_SIZE_OF(current)
-/* This decides where the kernel will search for a free chunk of vm
- * space during mmap's.
- */
-#define TASK_UNMAPPED_BASE_USER32 (PAGE_ALIGN(TASK_SIZE_USER32 / 4))
-#define TASK_UNMAPPED_BASE_USER64 (PAGE_ALIGN(DEFAULT_MAP_WINDOW_USER64 / 4))
-
-#define TASK_UNMAPPED_BASE ((is_32bit_task()) ? \
- TASK_UNMAPPED_BASE_USER32 : TASK_UNMAPPED_BASE_USER64 )
-#endif
-
-/*
- * Initial task size value for user applications. For book3s 64 we start
- * with 128TB and conditionally enable upto 512TB
- */
-#ifdef CONFIG_PPC_BOOK3S_64
-#define DEFAULT_MAP_WINDOW ((is_32bit_task()) ? \
- TASK_SIZE_USER32 : DEFAULT_MAP_WINDOW_USER64)
+#include <asm/task_size_64.h>
#else
-#define DEFAULT_MAP_WINDOW TASK_SIZE
+#include <asm/task_size_32.h>
#endif
-#ifdef __powerpc64__
-
-#define STACK_TOP_USER64 DEFAULT_MAP_WINDOW_USER64
-#define STACK_TOP_USER32 TASK_SIZE_USER32
-
-#define STACK_TOP (is_32bit_task() ? \
- STACK_TOP_USER32 : STACK_TOP_USER64)
-
-#define STACK_TOP_MAX TASK_SIZE_USER64
-
-#else /* __powerpc64__ */
-
-#define STACK_TOP TASK_SIZE
-#define STACK_TOP_MAX STACK_TOP
-
-#endif /* __powerpc64__ */
+struct task_struct;
+void start_thread(struct pt_regs *regs, unsigned long fdptr, unsigned long sp);
+void release_thread(struct task_struct *);
typedef struct {
unsigned long seg;
diff --git a/arch/powerpc/include/asm/task_size_32.h b/arch/powerpc/include/asm/task_size_32.h
new file mode 100644
index 000000000000..de7290ee770f
--- /dev/null
+++ b/arch/powerpc/include/asm/task_size_32.h
@@ -0,0 +1,21 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef _ASM_POWERPC_TASK_SIZE_32_H
+#define _ASM_POWERPC_TASK_SIZE_32_H
+
+#if CONFIG_TASK_SIZE > CONFIG_KERNEL_START
+#error User TASK_SIZE overlaps with KERNEL_START address
+#endif
+
+#define TASK_SIZE (CONFIG_TASK_SIZE)
+
+/*
+ * This decides where the kernel will search for a free chunk of vm space during
+ * mmap's.
+ */
+#define TASK_UNMAPPED_BASE (TASK_SIZE / 8 * 3)
+
+#define DEFAULT_MAP_WINDOW TASK_SIZE
+#define STACK_TOP TASK_SIZE
+#define STACK_TOP_MAX STACK_TOP
+
+#endif /* _ASM_POWERPC_TASK_SIZE_32_H */
diff --git a/arch/powerpc/include/asm/task_size_64.h b/arch/powerpc/include/asm/task_size_64.h
new file mode 100644
index 000000000000..eab4779f6b84
--- /dev/null
+++ b/arch/powerpc/include/asm/task_size_64.h
@@ -0,0 +1,79 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef _ASM_POWERPC_TASK_SIZE_64_H
+#define _ASM_POWERPC_TASK_SIZE_64_H
+
+/*
+ * 64-bit user address space can have multiple limits
+ * For now supported values are:
+ */
+#define TASK_SIZE_64TB (0x0000400000000000UL)
+#define TASK_SIZE_128TB (0x0000800000000000UL)
+#define TASK_SIZE_512TB (0x0002000000000000UL)
+#define TASK_SIZE_1PB (0x0004000000000000UL)
+#define TASK_SIZE_2PB (0x0008000000000000UL)
+
+/*
+ * With 52 bits in the address we can support up to 4PB of range.
+ */
+#define TASK_SIZE_4PB (0x0010000000000000UL)
+
+/*
+ * For now 512TB is only supported with book3s and 64K linux page size.
+ */
+#if defined(CONFIG_PPC_BOOK3S_64) && defined(CONFIG_PPC_64K_PAGES)
+/*
+ * Max value currently used:
+ */
+#define TASK_SIZE_USER64 TASK_SIZE_4PB
+#define DEFAULT_MAP_WINDOW_USER64 TASK_SIZE_128TB
+#define TASK_CONTEXT_SIZE TASK_SIZE_512TB
+#else
+#define TASK_SIZE_USER64 TASK_SIZE_64TB
+#define DEFAULT_MAP_WINDOW_USER64 TASK_SIZE_64TB
+
+/*
+ * We don't need to allocate extended context ids for 4K page size, because we
+ * limit the max effective address on this config to 64TB.
+ */
+#define TASK_CONTEXT_SIZE TASK_SIZE_64TB
+#endif
+
+/*
+ * 32-bit user address space is 4GB - 1 page
+ * (this 1 page is needed so referencing of 0xFFFFFFFF generates EFAULT
+ */
+#define TASK_SIZE_USER32 (0x0000000100000000UL - (1 * PAGE_SIZE))
+
+#define TASK_SIZE_OF(tsk) \
+ (test_tsk_thread_flag(tsk, TIF_32BIT) ? TASK_SIZE_USER32 : \
+ TASK_SIZE_USER64)
+
+#define TASK_SIZE TASK_SIZE_OF(current)
+
+#define TASK_UNMAPPED_BASE_USER32 (PAGE_ALIGN(TASK_SIZE_USER32 / 4))
+#define TASK_UNMAPPED_BASE_USER64 (PAGE_ALIGN(DEFAULT_MAP_WINDOW_USER64 / 4))
+
+/*
+ * This decides where the kernel will search for a free chunk of vm space during
+ * mmap's.
+ */
+#define TASK_UNMAPPED_BASE \
+ ((is_32bit_task()) ? TASK_UNMAPPED_BASE_USER32 : TASK_UNMAPPED_BASE_USER64)
+
+/*
+ * Initial task size value for user applications. For book3s 64 we start
+ * with 128TB and conditionally enable upto 512TB
+ */
+#ifdef CONFIG_PPC_BOOK3S_64
+#define DEFAULT_MAP_WINDOW \
+ ((is_32bit_task()) ? TASK_SIZE_USER32 : DEFAULT_MAP_WINDOW_USER64)
+#else
+#define DEFAULT_MAP_WINDOW TASK_SIZE
+#endif
+
+#define STACK_TOP_USER64 DEFAULT_MAP_WINDOW_USER64
+#define STACK_TOP_USER32 TASK_SIZE_USER32
+#define STACK_TOP_MAX TASK_SIZE_USER64
+#define STACK_TOP (is_32bit_task() ? STACK_TOP_USER32 : STACK_TOP_USER64)
+
+#endif /* _ASM_POWERPC_TASK_SIZE_64_H */
diff --git a/arch/powerpc/kvm/book3s_hv_hmi.c b/arch/powerpc/kvm/book3s_hv_hmi.c
index e3f738eb1cac..64b5011475c7 100644
--- a/arch/powerpc/kvm/book3s_hv_hmi.c
+++ b/arch/powerpc/kvm/book3s_hv_hmi.c
@@ -24,6 +24,7 @@
#include <linux/compiler.h>
#include <asm/paca.h>
#include <asm/hmi.h>
+#include <asm/processor.h>
void wait_for_subcore_guest_exit(void)
{
--
2.20.1
^ permalink raw reply related
* [PATCH v16 02/21] powerpc/32: Fix CONFIG_VIRT_CPU_ACCOUNTING_NATIVE for 40x/booke
From: Michael Ellerman @ 2019-02-05 11:32 UTC (permalink / raw)
To: linuxppc-dev; +Cc: npiggin
In-Reply-To: <20190205113219.17903-1-mpe@ellerman.id.au>
From: Christophe Leroy <christophe.leroy@c-s.fr>
40x/booke have another path to reach 3f from transfer_to_handler,
make sure it also calls ACCOUNT_CPU_USER_ENTRY() when
CONFIG_VIRT_CPU_ACCOUNTING_NATIVE is selected.
Signed-off-by: Christophe Leroy <christophe.leroy@c-s.fr>
Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
---
arch/powerpc/kernel/entry_32.S | 12 +++++++-----
1 file changed, 7 insertions(+), 5 deletions(-)
diff --git a/arch/powerpc/kernel/entry_32.S b/arch/powerpc/kernel/entry_32.S
index 0768dfd8a64e..d4c6186aa7e8 100644
--- a/arch/powerpc/kernel/entry_32.S
+++ b/arch/powerpc/kernel/entry_32.S
@@ -166,6 +166,13 @@
internal debug mode bit to do this. */
lwz r12,THREAD_DBCR0(r12)
andis. r12,r12,DBCR0_IDM@h
+#endif
+#ifdef CONFIG_VIRT_CPU_ACCOUNTING_NATIVE
+ CURRENT_THREAD_INFO(r9, r1)
+ tophys(r9, r9)
+ ACCOUNT_CPU_USER_ENTRY(r9, r11, r12)
+#endif
+#if defined(CONFIG_40x) || defined(CONFIG_BOOKE)
beq+ 3f
/* From user and task is ptraced - load up global dbcr0 */
li r12,-1 /* clear all pending debug events */
@@ -185,11 +192,6 @@
addi r12,r12,-1
stw r12,4(r11)
#endif
-#ifdef CONFIG_VIRT_CPU_ACCOUNTING_NATIVE
- CURRENT_THREAD_INFO(r9, r1)
- tophys(r9, r9)
- ACCOUNT_CPU_USER_ENTRY(r9, r11, r12)
-#endif
b 3f
--
2.20.1
^ permalink raw reply related
* [PATCH v16 01/21] powerpc/irq: use memblock functions returning virtual address
From: Michael Ellerman @ 2019-02-05 11:31 UTC (permalink / raw)
To: linuxppc-dev; +Cc: npiggin
In-Reply-To: <20190205113219.17903-1-mpe@ellerman.id.au>
From: Christophe Leroy <christophe.leroy@c-s.fr>
Since only the virtual address of allocated blocks is used,
lets use functions returning directly virtual address.
Those functions have the advantage of also zeroing the block.
Suggested-by: Mike Rapoport <rppt@linux.ibm.com>
Acked-by: Mike Rapoport <rppt@linux.ibm.com>
Signed-off-by: Christophe Leroy <christophe.leroy@c-s.fr>
Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
---
arch/powerpc/kernel/irq.c | 5 -----
arch/powerpc/kernel/setup_32.c | 26 ++++++++++++++++----------
arch/powerpc/kernel/setup_64.c | 19 +++++++------------
3 files changed, 23 insertions(+), 27 deletions(-)
diff --git a/arch/powerpc/kernel/irq.c b/arch/powerpc/kernel/irq.c
index bb299613a462..4a5dd8800946 100644
--- a/arch/powerpc/kernel/irq.c
+++ b/arch/powerpc/kernel/irq.c
@@ -725,18 +725,15 @@ void exc_lvl_ctx_init(void)
#endif
#endif
- memset((void *)critirq_ctx[cpu_nr], 0, THREAD_SIZE);
tp = critirq_ctx[cpu_nr];
tp->cpu = cpu_nr;
tp->preempt_count = 0;
#ifdef CONFIG_BOOKE
- memset((void *)dbgirq_ctx[cpu_nr], 0, THREAD_SIZE);
tp = dbgirq_ctx[cpu_nr];
tp->cpu = cpu_nr;
tp->preempt_count = 0;
- memset((void *)mcheckirq_ctx[cpu_nr], 0, THREAD_SIZE);
tp = mcheckirq_ctx[cpu_nr];
tp->cpu = cpu_nr;
tp->preempt_count = HARDIRQ_OFFSET;
@@ -754,12 +751,10 @@ void irq_ctx_init(void)
int i;
for_each_possible_cpu(i) {
- memset((void *)softirq_ctx[i], 0, THREAD_SIZE);
tp = softirq_ctx[i];
tp->cpu = i;
klp_init_thread_info(tp);
- memset((void *)hardirq_ctx[i], 0, THREAD_SIZE);
tp = hardirq_ctx[i];
tp->cpu = i;
klp_init_thread_info(tp);
diff --git a/arch/powerpc/kernel/setup_32.c b/arch/powerpc/kernel/setup_32.c
index 947f904688b0..1f0b7629c1a6 100644
--- a/arch/powerpc/kernel/setup_32.c
+++ b/arch/powerpc/kernel/setup_32.c
@@ -196,6 +196,17 @@ static int __init ppc_init(void)
}
arch_initcall(ppc_init);
+static void *__init alloc_stack(void)
+{
+ void *ptr = memblock_alloc(THREAD_SIZE, THREAD_SIZE);
+
+ if (!ptr)
+ panic("cannot allocate %d bytes for stack at %pS\n",
+ THREAD_SIZE, (void *)_RET_IP_);
+
+ return ptr;
+}
+
void __init irqstack_early_init(void)
{
unsigned int i;
@@ -203,10 +214,8 @@ void __init irqstack_early_init(void)
/* interrupt stacks must be in lowmem, we get that for free on ppc32
* as the memblock is limited to lowmem by default */
for_each_possible_cpu(i) {
- softirq_ctx[i] = (struct thread_info *)
- __va(memblock_phys_alloc(THREAD_SIZE, THREAD_SIZE));
- hardirq_ctx[i] = (struct thread_info *)
- __va(memblock_phys_alloc(THREAD_SIZE, THREAD_SIZE));
+ softirq_ctx[i] = alloc_stack();
+ hardirq_ctx[i] = alloc_stack();
}
}
@@ -224,13 +233,10 @@ void __init exc_lvl_early_init(void)
hw_cpu = 0;
#endif
- critirq_ctx[hw_cpu] = (struct thread_info *)
- __va(memblock_phys_alloc(THREAD_SIZE, THREAD_SIZE));
+ critirq_ctx[hw_cpu] = alloc_stack();
#ifdef CONFIG_BOOKE
- dbgirq_ctx[hw_cpu] = (struct thread_info *)
- __va(memblock_phys_alloc(THREAD_SIZE, THREAD_SIZE));
- mcheckirq_ctx[hw_cpu] = (struct thread_info *)
- __va(memblock_phys_alloc(THREAD_SIZE, THREAD_SIZE));
+ dbgirq_ctx[hw_cpu] = alloc_stack();
+ mcheckirq_ctx[hw_cpu] = alloc_stack();
#endif
}
}
diff --git a/arch/powerpc/kernel/setup_64.c b/arch/powerpc/kernel/setup_64.c
index 236c1151a3a7..080dd515d587 100644
--- a/arch/powerpc/kernel/setup_64.c
+++ b/arch/powerpc/kernel/setup_64.c
@@ -634,19 +634,17 @@ __init u64 ppc64_bolted_size(void)
static void *__init alloc_stack(unsigned long limit, int cpu)
{
- unsigned long pa;
+ void *ptr;
BUILD_BUG_ON(STACK_INT_FRAME_SIZE % 16);
- pa = memblock_alloc_base_nid(THREAD_SIZE, THREAD_SIZE, limit,
- early_cpu_to_node(cpu), MEMBLOCK_NONE);
- if (!pa) {
- pa = memblock_alloc_base(THREAD_SIZE, THREAD_SIZE, limit);
- if (!pa)
- panic("cannot allocate stacks");
- }
+ ptr = memblock_alloc_try_nid(THREAD_SIZE, THREAD_SIZE,
+ MEMBLOCK_LOW_LIMIT, limit,
+ early_cpu_to_node(cpu));
+ if (!ptr)
+ panic("cannot allocate stacks");
- return __va(pa);
+ return ptr;
}
void __init irqstack_early_init(void)
@@ -739,20 +737,17 @@ void __init emergency_stack_init(void)
struct thread_info *ti;
ti = alloc_stack(limit, i);
- memset(ti, 0, THREAD_SIZE);
emerg_stack_init_thread_info(ti, i);
paca_ptrs[i]->emergency_sp = (void *)ti + THREAD_SIZE;
#ifdef CONFIG_PPC_BOOK3S_64
/* emergency stack for NMI exception handling. */
ti = alloc_stack(limit, i);
- memset(ti, 0, THREAD_SIZE);
emerg_stack_init_thread_info(ti, i);
paca_ptrs[i]->nmi_emergency_sp = (void *)ti + THREAD_SIZE;
/* emergency stack for machine check exception handling. */
ti = alloc_stack(limit, i);
- memset(ti, 0, THREAD_SIZE);
emerg_stack_init_thread_info(ti, i);
paca_ptrs[i]->mc_emergency_sp = (void *)ti + THREAD_SIZE;
#endif
--
2.20.1
^ permalink raw reply related
* [PATCH v16 00/21] powerpc: Switch to CONFIG_THREAD_INFO_IN_TASK
From: Michael Ellerman @ 2019-02-05 11:31 UTC (permalink / raw)
To: linuxppc-dev; +Cc: npiggin
The purpose of this series is to activate CONFIG_THREAD_INFO_IN_TASK which
moves the thread_info into task_struct.
Moving thread_info into task_struct has the following advantages:
- It protects thread_info from corruption in the case of stack
overflows.
- Its address is harder to determine if stack addresses are leaked,
making a number of attacks more difficult.
Changes in v16 (mpe):
- split the prepartion patches out into smaller pieces.
- move all TASK_SIZE related contents out of processor.h
- fix build failures with livepatching enabled (include sched/task_stack.h)
- Use PACA_CURRENT_TI for the offset of the thread info in paca->current.
Changes in v15:
- switched patch 1 and 2.
- resync patch 1 with linux/next. As memblock modifications are now fully merged in
linux-mm tree, this patch voids as soon as linux-mm gets merged into powerpc/merge branch
- Fixed build failure on 64le due to call to __save_stack_trace_tsk_reliable() (patch 5)
- Taken the renaming of THREAD_INFO to TASK_STACK out of the preparation patch to ease review (hence new patch 6)
- Fixed one place where r11 (physical address of stack) was used instead of r1 to locate
thread_info, inducing a bug when switching to r2 which is virtual address of current (patch 7)
- Keeping physical address of current in r2 until MMU translation is reactivated (patch 11)
Changes in v14 (ie since v13):
- Added in front a fixup patch which conflicts with this serie
- Added a patch for using try_get_task_stack()/put_task_stack() in stack walkers.
- Fixed compilation failure in the preparation patch (by moving the modification
of klp_init_thread_info() to the following patch)
Changes since v12:
- Patch 1: Taken comment from Mike (re-introduced the 'panic' in case memblock allocation fails in setup_64.c
- Patch 1: Added alloc_stack() function in setup_32.c to also panic in case of allocation failure.
Changes since v11:
- Rebased on 81775f5563fa ("Automatic merge of branches 'master', 'next' and 'fixes' into merge")
- Added a first patch to change memblock allocs to functions returning virtual addrs. This removes
the memset() which were the only remaining stuff in irq_ctx_init() and exc_lvl_ctx_init() at the end.
- dropping irq_ctx_init() and exc_lvl_ctx_init() in patch 5 (powerpc: Activate CONFIG_THREAD_INFO_IN_TASK)
- A few cosmetic changes in commit log and code.
Changes since v10:
- Rebased on 21622a0d2023 ("Automatic merge of branches 'master', 'next' and 'fixes' into merge")
==> Fixed conflict in setup_32.S
Changes since v9:
- Rebased on 183cbf93be88 ("Automatic merge of branches 'master', 'next' and 'fixes' into merge")
==> Fixed conflict on xmon
Changes since v8:
- Rebased on e589b79e40d9 ("Automatic merge of branches 'master', 'next' and 'fixes' into merge")
==> Main impact was conflicts due to commit 9a8dd708d547 ("memblock: rename memblock_alloc{_nid,_try_nid} to memblock_phys_alloc*")
Changes since v7:
- Rebased on fb6c6ce7907d ("Automatic merge of branches 'master', 'next' and 'fixes' into merge")
Changes since v6:
- Fixed validate_sp() to exclude NULL sp in 'regain entire stack space' patch (early crash with CONFIG_KMEMLEAK)
Changes since v5:
- Fixed livepatch_sp setup by using end_of_stack() instead of hardcoding
- Fixed PPC_BPF_LOAD_CPU() macro
Changes since v4:
- Fixed a build failure on 32bits SMP when include/generated/asm-offsets.h is not
already existing, was due to spaces instead of a tab in the Makefile
Changes since RFC v3: (based on Nick's review)
- Renamed task_size.h to task_size_user64.h to better relate to what it contains.
- Handling of the isolation of thread_info cpu field inside CONFIG_SMP #ifdefs moved to a separate patch.
- Removed CURRENT_THREAD_INFO macro completely.
- Added a guard in asm/smp.h to avoid build failure before _TASK_CPU is defined.
- Added a patch at the end to rename 'tp' pointers to 'sp' pointers
- Renamed 'tp' into 'sp' pointers in preparation patch when relevant
- Fixed a few commit logs
- Fixed checkpatch report.
Changes since RFC v2:
- Removed the modification of names in asm-offsets
- Created a rule in arch/powerpc/Makefile to append the offset of current->cpu in CFLAGS
- Modified asm/smp.h to use the offset set in CFLAGS
- Squashed the renaming of THREAD_INFO to TASK_STACK in the preparation patch
- Moved the modification of current_pt_regs in the patch activating CONFIG_THREAD_INFO_IN_TASK
Changes since RFC v1:
- Removed the first patch which was modifying header inclusion order in timer
- Modified some names in asm-offsets to avoid conflicts when including asm-offsets in C files
- Modified asm/smp.h to avoid having to include linux/sched.h (using asm-offsets instead)
- Moved some changes from the activation patch to the preparation patch.
Christophe Leroy (21):
powerpc/irq: use memblock functions returning virtual address
powerpc/32: Fix CONFIG_VIRT_CPU_ACCOUNTING_NATIVE for 40x/booke
powerpc: Avoid circular header inclusion in mmu-hash.h
powerpc: Only use task_struct 'cpu' field on SMP
powerpc: prep stack walkers for THREAD_INFO_IN_TASK
powerpc: Rename THREAD_INFO to TASK_STACK
powerpc: call_do_[soft]irq() takes a pointer to the stack
powerpc: Don't use CURRENT_THREAD_INFO to find the stack
powerpc: Replace current_thread_info()->task with current
powerpc: Update comments in preparation for THREAD_INFO_IN_TASK
powerpc/64: Use task_stack_page() to initialise paca->kstack
powerpc: Use sizeof(struct thread_info) in INIT_SP_LIMIT
powerpc: Use linux/thread_info.h in processor.h
powerpc: Use task_stack_page() in current_pt_regs()
powerpc/idle/6xx: Use r1 with CURRENT_THREAD_INFO()
powerpc: Activate CONFIG_THREAD_INFO_IN_TASK
powerpc: regain entire stack space
powerpc: 'current_set' is now a table of task_struct pointers
powerpc/32: Remove CURRENT_THREAD_INFO and rename TI_CPU
powerpc/64: Replace CURRENT_THREAD_INFO with PACA_CURRENT_TI
powerpc: clean stack pointers naming
arch/powerpc/Kconfig | 1 +
arch/powerpc/Makefile | 7 ++
arch/powerpc/include/asm/asm-prototypes.h | 4 +-
arch/powerpc/include/asm/book3s/64/mmu-hash.h | 2 +-
arch/powerpc/include/asm/exception-64s.h | 4 +-
arch/powerpc/include/asm/irq.h | 18 ++-
arch/powerpc/include/asm/livepatch.h | 7 +-
arch/powerpc/include/asm/processor.h | 105 ++--------------
arch/powerpc/include/asm/ptrace.h | 2 +-
arch/powerpc/include/asm/reg.h | 2 +-
arch/powerpc/include/asm/smp.h | 17 ++-
arch/powerpc/include/asm/task_size_32.h | 21 ++++
arch/powerpc/include/asm/task_size_64.h | 79 ++++++++++++
arch/powerpc/include/asm/thread_info.h | 19 ---
arch/powerpc/kernel/asm-offsets.c | 12 +-
arch/powerpc/kernel/entry_32.S | 80 +++++-------
arch/powerpc/kernel/entry_64.S | 12 +-
arch/powerpc/kernel/epapr_hcalls.S | 5 +-
arch/powerpc/kernel/exceptions-64e.S | 13 +-
arch/powerpc/kernel/exceptions-64s.S | 2 +-
arch/powerpc/kernel/head_32.S | 14 +--
arch/powerpc/kernel/head_40x.S | 4 +-
arch/powerpc/kernel/head_44x.S | 8 +-
arch/powerpc/kernel/head_64.S | 1 +
arch/powerpc/kernel/head_8xx.S | 2 +-
arch/powerpc/kernel/head_booke.h | 12 +-
arch/powerpc/kernel/head_fsl_booke.S | 16 +--
arch/powerpc/kernel/idle_6xx.S | 8 +-
arch/powerpc/kernel/idle_book3e.S | 2 +-
arch/powerpc/kernel/idle_e500.S | 8 +-
arch/powerpc/kernel/idle_power4.S | 2 +-
arch/powerpc/kernel/irq.c | 114 +++---------------
arch/powerpc/kernel/kgdb.c | 28 -----
arch/powerpc/kernel/machine_kexec_64.c | 6 +-
arch/powerpc/kernel/misc_32.S | 17 +--
arch/powerpc/kernel/process.c | 63 ++++++----
arch/powerpc/kernel/setup-common.c | 2 +-
arch/powerpc/kernel/setup_32.c | 26 ++--
arch/powerpc/kernel/setup_64.c | 51 ++------
arch/powerpc/kernel/smp.c | 16 +--
arch/powerpc/kernel/stacktrace.c | 29 ++++-
.../powerpc/kernel/trace/ftrace_64_mprofile.S | 6 +-
arch/powerpc/kvm/book3s_hv_hmi.c | 1 +
arch/powerpc/mm/hash_low_32.S | 14 +--
arch/powerpc/net/bpf_jit32.h | 5 +-
arch/powerpc/sysdev/6xx-suspend.S | 5 +-
arch/powerpc/xmon/xmon.c | 2 +-
47 files changed, 367 insertions(+), 507 deletions(-)
create mode 100644 arch/powerpc/include/asm/task_size_32.h
create mode 100644 arch/powerpc/include/asm/task_size_64.h
--
2.20.1
^ permalink raw reply
* Re: [PATCH 00/19] KVM: PPC: Book3S HV: add XIVE native exploitation mode
From: Cédric Le Goater @ 2019-02-05 11:31 UTC (permalink / raw)
To: David Gibson; +Cc: kvm, kvm-ppc, linuxppc-dev
In-Reply-To: <20190204053610.GK1927@umbus.fritz.box>
>>> As for nesting, I suggest for the foreseeable future we stick to XICS
>>> emulation in nested guests.
>>
>> ok. so no kernel_irqchip at all. hmm.
I was confused with what Paul calls 'XICS emulation'. It's not the QEMU
XICS emulated device but the XICS-over-XIVE KVM device, the KVM XICS
device KVM uses when under a P9 processor.
> That would certainly be step 0, making sure the capability advertises
> this correctly. I think we do want to make XICs-on-XIVE emulation
> work in a KVM L1 (so we'd need to have it make XIVE hcalls to the L0
> instead of OPAL calls).
With the latest patch of Paul, the KVM XICS device is available for L2
and it works quite well.
I also want to test it when L1 runs in KVM XIVE native mode, with the
current patchset, to see how it behaves.
> XIVE-on-XIVE for L1 would be nice too, which would mean implementing
> the XIVE hcalls from the L2 in terms of XIVE hcalls to the L0. I
> think it's ok to delay this indefinitely as long as the caps advertise
> correctly so that qemu will use userspace emulation until its ready.
ok. I need to fix this in the current patchset.
Thanks,
C.
^ permalink raw reply
* Re: powerpc/papr_scm: Use the correct bind address
From: Michael Ellerman @ 2019-02-05 11:25 UTC (permalink / raw)
To: Oliver O'Halloran, linuxppc-dev; +Cc: Oliver O'Halloran, stable
In-Reply-To: <20190131015347.21674-1-oohall@gmail.com>
On Thu, 2019-01-31 at 01:53:47 UTC, Oliver O'Halloran wrote:
> When binding an SCM volume to a physical address the hypervisor has the
> option to return early with a continue token with the expectation that
> the guest will resume the bind operation until it completes. A quirk of
> this interface is that the bind address will only be returned by the
> first bind h-call and the subsequent calls will return
> 0xFFFF_FFFF_FFFF_FFFF for the bind address.
>
> We currently do not save the address returned by the first h-call. As a
> result we will use the junk address as the base of the bound region if
> the hypervisor decides to split the bind across multiple h-calls. This
> bug was found when testing with very large SCM volumes where the bind
> process would take more time than they hypervisor's internal h-call time
> limit would allow. This patch fixes the issue by saving the bind address
> from the first call.
>
> Cc: stable@vger.kernel.org
> Fixes: b5beae5e224f ("powerpc/pseries: Add driver for PAPR SCM regions")
> Signed-off-by: Oliver O'Halloran <oohall@gmail.com>
Applied to powerpc fixes, thanks.
https://git.kernel.org/powerpc/c/5a3840a470c41ec0b85cd36ca8037033
cheers
^ permalink raw reply
* Re: arch/powerpc/radix: Fix kernel crash with mremap
From: Michael Ellerman @ 2019-02-05 11:25 UTC (permalink / raw)
To: Aneesh Kumar K.V, npiggin, benh, paulus; +Cc: Aneesh Kumar K.V, linuxppc-dev
In-Reply-To: <20190123062138.22644-1-aneesh.kumar@linux.ibm.com>
On Wed, 2019-01-23 at 06:21:38 UTC, "Aneesh Kumar K.V" wrote:
> With support for split pmd lock, we use pmd page pmd_huge_pte pointer to store
> the deposited page table. In those config when we move page tables we need to
> make sure we move the depoisted page table to the right pmd page. Otherwise this
> can result in crash when we withdraw of deposited page table because we can find
> the pmd_huge_pte NULL.
>
> c0000000004a1230 __split_huge_pmd+0x1070/0x1940
> c0000000004a0ff4 __split_huge_pmd+0xe34/0x1940 (unreliable)
> c0000000004a4000 vma_adjust_trans_huge+0x110/0x1c0
> c00000000042fe04 __vma_adjust+0x2b4/0x9b0
> c0000000004316e8 __split_vma+0x1b8/0x280
> c00000000043192c __do_munmap+0x13c/0x550
> c000000000439390 sys_mremap+0x220/0x7e0
> c00000000000b488 system_call+0x5c/0x70
>
> Fixes: 675d995297d4 ("powerpc/book3s64: Enable split pmd ptlock.")
> Signed-off-by: Aneesh Kumar K.V <aneesh.kumar@linux.ibm.com>
> Signed-off-by: Aneesh Kumar K.V <aneesh.kumar@linux.ibm.com>
Applied to powerpc fixes, thanks.
https://git.kernel.org/powerpc/c/579b9239c1f38665b21e8d0e6ee83ecc
cheers
^ permalink raw reply
* Re: [PATCH 1/4] powerpc/64s: Clear on-stack exception marker upon exception return
From: Michael Ellerman @ 2019-02-05 11:24 UTC (permalink / raw)
To: Balbir Singh, Joe Lawrence
Cc: Nicolai Stange, Jiri Kosina, linux-kernel@vger.kernel.org,
Torsten Duwe, Josh Poimboeuf, live-patching,
open list:LINUX FOR POWERPC (32-BIT AND 64-BIT)
In-Reply-To: <CAKTCnzmWCxPRSBdc8T_phtmoBftNZLV3BdFp3Dee5Lc8VGzFYg@mail.gmail.com>
Balbir Singh <bsingharora@gmail.com> writes:
> On Sat, Feb 2, 2019 at 12:14 PM Balbir Singh <bsingharora@gmail.com> wrote:
>>
>> On Tue, Jan 22, 2019 at 10:57:21AM -0500, Joe Lawrence wrote:
>> > From: Nicolai Stange <nstange@suse.de>
>> >
>> > The ppc64 specific implementation of the reliable stacktracer,
>> > save_stack_trace_tsk_reliable(), bails out and reports an "unreliable
>> > trace" whenever it finds an exception frame on the stack. Stack frames
>> > are classified as exception frames if the STACK_FRAME_REGS_MARKER magic,
>> > as written by exception prologues, is found at a particular location.
>> >
>> > However, as observed by Joe Lawrence, it is possible in practice that
>> > non-exception stack frames can alias with prior exception frames and thus,
>> > that the reliable stacktracer can find a stale STACK_FRAME_REGS_MARKER on
>> > the stack. It in turn falsely reports an unreliable stacktrace and blocks
>> > any live patching transition to finish. Said condition lasts until the
>> > stack frame is overwritten/initialized by function call or other means.
>> >
>> > In principle, we could mitigate this by making the exception frame
>> > classification condition in save_stack_trace_tsk_reliable() stronger:
>> > in addition to testing for STACK_FRAME_REGS_MARKER, we could also take into
>> > account that for all exceptions executing on the kernel stack
>> > - their stack frames's backlink pointers always match what is saved
>> > in their pt_regs instance's ->gpr[1] slot and that
>> > - their exception frame size equals STACK_INT_FRAME_SIZE, a value
>> > uncommonly large for non-exception frames.
>> >
>> > However, while these are currently true, relying on them would make the
>> > reliable stacktrace implementation more sensitive towards future changes in
>> > the exception entry code. Note that false negatives, i.e. not detecting
>> > exception frames, would silently break the live patching consistency model.
>> >
>> > Furthermore, certain other places (diagnostic stacktraces, perf, xmon)
>> > rely on STACK_FRAME_REGS_MARKER as well.
>> >
>> > Make the exception exit code clear the on-stack STACK_FRAME_REGS_MARKER
>> > for those exceptions running on the "normal" kernel stack and returning
>> > to kernelspace: because the topmost frame is ignored by the reliable stack
>> > tracer anyway, returns to userspace don't need to take care of clearing
>> > the marker.
>> >
>> > Furthermore, as I don't have the ability to test this on Book 3E or
>> > 32 bits, limit the change to Book 3S and 64 bits.
>> >
>> > Finally, make the HAVE_RELIABLE_STACKTRACE Kconfig option depend on
>> > PPC_BOOK3S_64 for documentation purposes. Before this patch, it depended
>> > on PPC64 && CPU_LITTLE_ENDIAN and because CPU_LITTLE_ENDIAN implies
>> > PPC_BOOK3S_64, there's no functional change here.
>> >
>> > Fixes: df78d3f61480 ("powerpc/livepatch: Implement reliable stack tracing for the consistency model")
>> > Reported-by: Joe Lawrence <joe.lawrence@redhat.com>
>> > Signed-off-by: Nicolai Stange <nstange@suse.de>
>> > Signed-off-by: Joe Lawrence <joe.lawrence@redhat.com>
>> > ---
>> > arch/powerpc/Kconfig | 2 +-
>> > arch/powerpc/kernel/entry_64.S | 7 +++++++
>> > 2 files changed, 8 insertions(+), 1 deletion(-)
>> >
>> > diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig
>> > index 2890d36eb531..73bf87b1d274 100644
>> > --- a/arch/powerpc/Kconfig
>> > +++ b/arch/powerpc/Kconfig
>> > @@ -220,7 +220,7 @@ config PPC
>> > select HAVE_PERF_USER_STACK_DUMP
>> > select HAVE_RCU_TABLE_FREE if SMP
>> > select HAVE_REGS_AND_STACK_ACCESS_API
>> > - select HAVE_RELIABLE_STACKTRACE if PPC64 && CPU_LITTLE_ENDIAN
>> > + select HAVE_RELIABLE_STACKTRACE if PPC_BOOK3S_64 && CPU_LITTLE_ENDIAN
>> > select HAVE_SYSCALL_TRACEPOINTS
>> > select HAVE_VIRT_CPU_ACCOUNTING
>> > select HAVE_IRQ_TIME_ACCOUNTING
>> > diff --git a/arch/powerpc/kernel/entry_64.S b/arch/powerpc/kernel/entry_64.S
>> > index 435927f549c4..a2c168b395d2 100644
>> > --- a/arch/powerpc/kernel/entry_64.S
>> > +++ b/arch/powerpc/kernel/entry_64.S
>> > @@ -1002,6 +1002,13 @@ END_FTR_SECTION_IFSET(CPU_FTR_HAS_PPR)
>> > ld r2,_NIP(r1)
>> > mtspr SPRN_SRR0,r2
>> >
>> > + /*
>> > + * Leaving a stale exception_marker on the stack can confuse
>> > + * the reliable stack unwinder later on. Clear it.
>> > + */
>> > + li r2,0
>> > + std r2,STACK_FRAME_OVERHEAD-16(r1)
>> > +
>>
>> Could you please double check, r4 is already 0 at this point
>> IIUC. So the change might be a simple
>>
>> std r4,STACK_FRAME_OVERHEAD-16(r1)
>>
>
> r4 is not 0, sorry for the noise
Isn't it?
cheers
^ permalink raw reply
* Re: [PATCH] hugetlb: allow to free gigantic pages regardless of the configuration
From: Michael Ellerman @ 2019-02-05 11:23 UTC (permalink / raw)
To: Alexandre Ghiti, Catalin Marinas, Will Deacon,
Benjamin Herrenschmidt, Paul Mackerras, Martin Schwidefsky,
Heiko Carstens, Thomas Gleixner, Ingo Molnar, Borislav Petkov,
H . Peter Anvin, x86, Alexander Viro, Mike Kravetz,
linux-arm-kernel, linux-kernel, linuxppc-dev, linux-s390,
linux-fsdevel, linux-mm
Cc: hch, linux-riscv, Alexandre Ghiti
In-Reply-To: <20190117183953.5990-1-aghiti@upmem.com>
Alexandre Ghiti <aghiti@upmem.com> writes:
> From: Alexandre Ghiti <alex@ghiti.fr>
>
> On systems without CMA or (MEMORY_ISOLATION && COMPACTION) activated but
> that support gigantic pages, boottime reserved gigantic pages can not be
> freed at all. This patchs simply enables the possibility to hand back
> those pages to memory allocator.
>
> This commit then renames gigantic_page_supported and
> ARCH_HAS_GIGANTIC_PAGE to make them more accurate. Indeed, those values
> being false does not mean that the system cannot use gigantic pages: it
> just means that runtime allocation of gigantic pages is not supported,
> one can still allocate boottime gigantic pages if the architecture supports
> it.
>
> Signed-off-by: Alexandre Ghiti <alex@ghiti.fr>
> ---
>
> - Compiled on all architectures
> - Tested on riscv architecture
>
> arch/arm64/Kconfig | 2 +-
> arch/arm64/include/asm/hugetlb.h | 7 +++--
> arch/powerpc/include/asm/book3s/64/hugetlb.h | 4 +--
> arch/powerpc/platforms/Kconfig.cputype | 2 +-
The powerpc parts look fine.
Acked-by: Michael Ellerman <mpe@ellerman.id.au> (powerpc)
cheers
> arch/s390/Kconfig | 2 +-
> arch/s390/include/asm/hugetlb.h | 7 +++--
> arch/x86/Kconfig | 2 +-
> arch/x86/include/asm/hugetlb.h | 7 +++--
> fs/Kconfig | 2 +-
> include/linux/gfp.h | 2 +-
> mm/hugetlb.c | 43 +++++++++++++++-------------
> mm/page_alloc.c | 4 +--
> 12 files changed, 48 insertions(+), 36 deletions(-)
>
> diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
> index a4168d366127..18239cbd7fcd 100644
> --- a/arch/arm64/Kconfig
> +++ b/arch/arm64/Kconfig
> @@ -18,7 +18,7 @@ config ARM64
> select ARCH_HAS_FAST_MULTIPLIER
> select ARCH_HAS_FORTIFY_SOURCE
> select ARCH_HAS_GCOV_PROFILE_ALL
> - select ARCH_HAS_GIGANTIC_PAGE if (MEMORY_ISOLATION && COMPACTION) || CMA
> + select ARCH_HAS_GIGANTIC_PAGE_RUNTIME_ALLOCATION if (MEMORY_ISOLATION && COMPACTION) || CMA
> select ARCH_HAS_KCOV
> select ARCH_HAS_MEMBARRIER_SYNC_CORE
> select ARCH_HAS_PTE_SPECIAL
> diff --git a/arch/arm64/include/asm/hugetlb.h b/arch/arm64/include/asm/hugetlb.h
> index fb6609875455..797fc77eabcd 100644
> --- a/arch/arm64/include/asm/hugetlb.h
> +++ b/arch/arm64/include/asm/hugetlb.h
> @@ -65,8 +65,11 @@ extern void set_huge_swap_pte_at(struct mm_struct *mm, unsigned long addr,
>
> #include <asm-generic/hugetlb.h>
>
> -#ifdef CONFIG_ARCH_HAS_GIGANTIC_PAGE
> -static inline bool gigantic_page_supported(void) { return true; }
> +#ifdef CONFIG_ARCH_HAS_GIGANTIC_PAGE_RUNTIME_ALLOCATION
> +static inline bool gigantic_page_runtime_allocation_supported(void)
> +{
> + return true;
> +}
> #endif
>
> #endif /* __ASM_HUGETLB_H */
> diff --git a/arch/powerpc/include/asm/book3s/64/hugetlb.h b/arch/powerpc/include/asm/book3s/64/hugetlb.h
> index 5b0177733994..7711f0e2c7e5 100644
> --- a/arch/powerpc/include/asm/book3s/64/hugetlb.h
> +++ b/arch/powerpc/include/asm/book3s/64/hugetlb.h
> @@ -32,8 +32,8 @@ static inline int hstate_get_psize(struct hstate *hstate)
> }
> }
>
> -#ifdef CONFIG_ARCH_HAS_GIGANTIC_PAGE
> -static inline bool gigantic_page_supported(void)
> +#ifdef CONFIG_ARCH_HAS_GIGANTIC_PAGE_RUNTIME_ALLOCATION
> +static inline bool gigantic_page_runtime_allocation_supported(void)
> {
> return true;
> }
> diff --git a/arch/powerpc/platforms/Kconfig.cputype b/arch/powerpc/platforms/Kconfig.cputype
> index 8c7464c3f27f..779e06bac697 100644
> --- a/arch/powerpc/platforms/Kconfig.cputype
> +++ b/arch/powerpc/platforms/Kconfig.cputype
> @@ -319,7 +319,7 @@ config ARCH_ENABLE_SPLIT_PMD_PTLOCK
> config PPC_RADIX_MMU
> bool "Radix MMU Support"
> depends on PPC_BOOK3S_64
> - select ARCH_HAS_GIGANTIC_PAGE if (MEMORY_ISOLATION && COMPACTION) || CMA
> + select ARCH_HAS_GIGANTIC_PAGE_RUNTIME_ALLOCATION if (MEMORY_ISOLATION && COMPACTION) || CMA
> default y
> help
> Enable support for the Power ISA 3.0 Radix style MMU. Currently this
> diff --git a/arch/s390/Kconfig b/arch/s390/Kconfig
> index ed554b09eb3f..6776eef6a9ae 100644
> --- a/arch/s390/Kconfig
> +++ b/arch/s390/Kconfig
> @@ -69,7 +69,7 @@ config S390
> select ARCH_HAS_ELF_RANDOMIZE
> select ARCH_HAS_FORTIFY_SOURCE
> select ARCH_HAS_GCOV_PROFILE_ALL
> - select ARCH_HAS_GIGANTIC_PAGE if (MEMORY_ISOLATION && COMPACTION) || CMA
> + select ARCH_HAS_GIGANTIC_PAGE_RUNTIME_ALLOCATION if (MEMORY_ISOLATION && COMPACTION) || CMA
> select ARCH_HAS_KCOV
> select ARCH_HAS_PTE_SPECIAL
> select ARCH_HAS_SET_MEMORY
> diff --git a/arch/s390/include/asm/hugetlb.h b/arch/s390/include/asm/hugetlb.h
> index 2d1afa58a4b6..57c952f5388e 100644
> --- a/arch/s390/include/asm/hugetlb.h
> +++ b/arch/s390/include/asm/hugetlb.h
> @@ -116,7 +116,10 @@ static inline pte_t huge_pte_modify(pte_t pte, pgprot_t newprot)
> return pte_modify(pte, newprot);
> }
>
> -#ifdef CONFIG_ARCH_HAS_GIGANTIC_PAGE
> -static inline bool gigantic_page_supported(void) { return true; }
> +#ifdef CONFIG_ARCH_HAS_GIGANTIC_PAGE_RUNTIME_ALLOCATION
> +static inline bool gigantic_page_runtime_allocation_supported(void)
> +{
> + return true;
> +}
> #endif
> #endif /* _ASM_S390_HUGETLB_H */
> diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig
> index 6185d4f33296..a88f5a4311c9 100644
> --- a/arch/x86/Kconfig
> +++ b/arch/x86/Kconfig
> @@ -23,7 +23,7 @@ config X86_64
> def_bool y
> depends on 64BIT
> # Options that are inherently 64-bit kernel only:
> - select ARCH_HAS_GIGANTIC_PAGE if (MEMORY_ISOLATION && COMPACTION) || CMA
> + select ARCH_HAS_GIGANTIC_PAGE_RUNTIME_ALLOCATION if (MEMORY_ISOLATION && COMPACTION) || CMA
> select ARCH_SUPPORTS_INT128
> select ARCH_USE_CMPXCHG_LOCKREF
> select HAVE_ARCH_SOFT_DIRTY
> diff --git a/arch/x86/include/asm/hugetlb.h b/arch/x86/include/asm/hugetlb.h
> index 7469d321f072..5a5e7119ced4 100644
> --- a/arch/x86/include/asm/hugetlb.h
> +++ b/arch/x86/include/asm/hugetlb.h
> @@ -17,8 +17,11 @@ static inline void arch_clear_hugepage_flags(struct page *page)
> {
> }
>
> -#ifdef CONFIG_ARCH_HAS_GIGANTIC_PAGE
> -static inline bool gigantic_page_supported(void) { return true; }
> +#ifdef CONFIG_ARCH_HAS_GIGANTIC_PAGE_RUNTIME_ALLOCATION
> +static inline bool gigantic_page_runtime_allocation_supported(void)
> +{
> + return true;
> +}
> #endif
>
> #endif /* _ASM_X86_HUGETLB_H */
> diff --git a/fs/Kconfig b/fs/Kconfig
> index ac474a61be37..4192d1fde0f0 100644
> --- a/fs/Kconfig
> +++ b/fs/Kconfig
> @@ -207,7 +207,7 @@ config HUGETLB_PAGE
> config MEMFD_CREATE
> def_bool TMPFS || HUGETLBFS
>
> -config ARCH_HAS_GIGANTIC_PAGE
> +config ARCH_HAS_GIGANTIC_PAGE_RUNTIME_ALLOCATION
> bool
>
> source "fs/configfs/Kconfig"
> diff --git a/include/linux/gfp.h b/include/linux/gfp.h
> index 5f5e25fd6149..79ff86fabd42 100644
> --- a/include/linux/gfp.h
> +++ b/include/linux/gfp.h
> @@ -589,8 +589,8 @@ static inline bool pm_suspended_storage(void)
> /* The below functions must be run on a range from a single zone. */
> extern int alloc_contig_range(unsigned long start, unsigned long end,
> unsigned migratetype, gfp_t gfp_mask);
> -extern void free_contig_range(unsigned long pfn, unsigned nr_pages);
> #endif
> +extern void free_contig_range(unsigned long pfn, unsigned int nr_pages);
>
> #ifdef CONFIG_CMA
> /* CMA stuff */
> diff --git a/mm/hugetlb.c b/mm/hugetlb.c
> index 745088810965..9893ba26b3b8 100644
> --- a/mm/hugetlb.c
> +++ b/mm/hugetlb.c
> @@ -1035,7 +1035,6 @@ static int hstate_next_node_to_free(struct hstate *h, nodemask_t *nodes_allowed)
> ((node = hstate_next_node_to_free(hs, mask)) || 1); \
> nr_nodes--)
>
> -#ifdef CONFIG_ARCH_HAS_GIGANTIC_PAGE
> static void destroy_compound_gigantic_page(struct page *page,
> unsigned int order)
> {
> @@ -1058,6 +1057,7 @@ static void free_gigantic_page(struct page *page, unsigned int order)
> free_contig_range(page_to_pfn(page), 1 << order);
> }
>
> +#ifdef CONFIG_ARCH_HAS_GIGANTIC_PAGE_RUNTIME_ALLOCATION
> static int __alloc_gigantic_page(unsigned long start_pfn,
> unsigned long nr_pages, gfp_t gfp_mask)
> {
> @@ -1143,22 +1143,19 @@ static struct page *alloc_gigantic_page(struct hstate *h, gfp_t gfp_mask,
> static void prep_new_huge_page(struct hstate *h, struct page *page, int nid);
> static void prep_compound_gigantic_page(struct page *page, unsigned int order);
>
> -#else /* !CONFIG_ARCH_HAS_GIGANTIC_PAGE */
> -static inline bool gigantic_page_supported(void) { return false; }
> +#else /* !CONFIG_ARCH_HAS_GIGANTIC_PAGE_RUNTIME_ALLOCATION */
> +static inline bool gigantic_page_runtime_allocation_supported(void)
> +{
> + return false;
> +}
> static struct page *alloc_gigantic_page(struct hstate *h, gfp_t gfp_mask,
> int nid, nodemask_t *nodemask) { return NULL; }
> -static inline void free_gigantic_page(struct page *page, unsigned int order) { }
> -static inline void destroy_compound_gigantic_page(struct page *page,
> - unsigned int order) { }
> #endif
>
> static void update_and_free_page(struct hstate *h, struct page *page)
> {
> int i;
>
> - if (hstate_is_gigantic(h) && !gigantic_page_supported())
> - return;
> -
> h->nr_huge_pages--;
> h->nr_huge_pages_node[page_to_nid(page)]--;
> for (i = 0; i < pages_per_huge_page(h); i++) {
> @@ -2276,13 +2273,20 @@ static int adjust_pool_surplus(struct hstate *h, nodemask_t *nodes_allowed,
> }
>
> #define persistent_huge_pages(h) (h->nr_huge_pages - h->surplus_huge_pages)
> -static unsigned long set_max_huge_pages(struct hstate *h, unsigned long count,
> +static int set_max_huge_pages(struct hstate *h, unsigned long count,
> nodemask_t *nodes_allowed)
> {
> unsigned long min_count, ret;
>
> - if (hstate_is_gigantic(h) && !gigantic_page_supported())
> - return h->max_huge_pages;
> + if (hstate_is_gigantic(h) &&
> + !gigantic_page_runtime_allocation_supported()) {
> + spin_lock(&hugetlb_lock);
> + if (count > persistent_huge_pages(h)) {
> + spin_unlock(&hugetlb_lock);
> + return -EINVAL;
> + }
> + goto decrease_pool;
> + }
>
> /*
> * Increase the pool size
> @@ -2322,6 +2326,7 @@ static unsigned long set_max_huge_pages(struct hstate *h, unsigned long count,
> goto out;
> }
>
> +decrease_pool:
> /*
> * Decrease the pool size
> * First return free pages to the buddy allocator (being careful
> @@ -2350,9 +2355,10 @@ static unsigned long set_max_huge_pages(struct hstate *h, unsigned long count,
> break;
> }
> out:
> - ret = persistent_huge_pages(h);
> + h->max_huge_pages = persistent_huge_pages(h);
> spin_unlock(&hugetlb_lock);
> - return ret;
> +
> + return 0;
> }
>
> #define HSTATE_ATTR_RO(_name) \
> @@ -2404,11 +2410,6 @@ static ssize_t __nr_hugepages_store_common(bool obey_mempolicy,
> int err;
> NODEMASK_ALLOC(nodemask_t, nodes_allowed, GFP_KERNEL | __GFP_NORETRY);
>
> - if (hstate_is_gigantic(h) && !gigantic_page_supported()) {
> - err = -EINVAL;
> - goto out;
> - }
> -
> if (nid == NUMA_NO_NODE) {
> /*
> * global hstate attribute
> @@ -2428,7 +2429,9 @@ static ssize_t __nr_hugepages_store_common(bool obey_mempolicy,
> } else
> nodes_allowed = &node_states[N_MEMORY];
>
> - h->max_huge_pages = set_max_huge_pages(h, count, nodes_allowed);
> + err = set_max_huge_pages(h, count, nodes_allowed);
> + if (err)
> + goto out;
>
> if (nodes_allowed != &node_states[N_MEMORY])
> NODEMASK_FREE(nodes_allowed);
> diff --git a/mm/page_alloc.c b/mm/page_alloc.c
> index cde5dac6229a..81b931db85a1 100644
> --- a/mm/page_alloc.c
> +++ b/mm/page_alloc.c
> @@ -8241,8 +8241,9 @@ int alloc_contig_range(unsigned long start, unsigned long end,
> pfn_max_align_up(end), migratetype);
> return ret;
> }
> +#endif
>
> -void free_contig_range(unsigned long pfn, unsigned nr_pages)
> +void free_contig_range(unsigned long pfn, unsigned int nr_pages)
> {
> unsigned int count = 0;
>
> @@ -8254,7 +8255,6 @@ void free_contig_range(unsigned long pfn, unsigned nr_pages)
> }
> WARN(count != 0, "%d pages are still in use!\n", count);
> }
> -#endif
>
> #ifdef CONFIG_MEMORY_HOTPLUG
> /*
> --
> 2.16.2
^ permalink raw reply
* Re: [RFC PATCH] powerpc: fix get_arch_dma_ops() for NTB devices
From: Michael Ellerman @ 2019-02-05 11:20 UTC (permalink / raw)
To: Christoph Hellwig
Cc: linuxppc-dev, Christoph Hellwig, Alexander Fomichev, linux
In-Reply-To: <20190204081752.GA5730@lst.de>
Christoph Hellwig <hch@lst.de> writes:
> On Wed, Jan 30, 2019 at 11:58:40PM +1100, Michael Ellerman wrote:
>> Alexander Fomichev <fomichev.ru@gmail.com> writes:
>>
>> > get_dma_ops() falls into arch-dependant get_arch_dma_ops(), which
>> > historically returns NULL on PowerPC. Therefore dma_set_mask() fails.
>> > This affects Switchtec (and probably other) NTB devices, that they fail
>> > to initialize.
>>
>> What's an NTB device?
>>
>> drivers/ntb I assume?
>>
>> So it's a PCI device of some sort, but presumably the device you're
>> calling dma_set_mask() on is an NTB device not a PCI device?
>>
>> But then it works if you tell it to use the PCI DMA ops?
>>
>> At the very least the code should be checking for the NTB bus type and
>> only returning the PCI ops in that specific case, not for all devices.
>
> Can you provide the context? E.g. the patch and the rest of the commit
> log. This all looks rather odd to me.
Sorry, here it is.
Or on lore: https://lore.kernel.org/linuxppc-dev/20190128133203.mon4a3nkrzijn43g@alfbook-pro.local/
Subject: [RFC PATCH] powerpc: fix get_arch_dma_ops() for NTB devices
get_dma_ops() falls into arch-dependant get_arch_dma_ops(), which
historically returns NULL on PowerPC. Therefore dma_set_mask() fails.
This affects Switchtec (and probably other) NTB devices, that they fail
to initialize.
The proposed patch should fix the issue.
---
arch/powerpc/include/asm/dma-mapping.h | 9 +++------
1 file changed, 3 insertions(+), 6 deletions(-)
diff --git a/arch/powerpc/include/asm/dma-mapping.h b/arch/powerpc/include/asm/dma-mapping.h
index ebf6680..cb6ac96 100644
--- a/arch/powerpc/include/asm/dma-mapping.h
+++ b/arch/powerpc/include/asm/dma-mapping.h
@@ -70,14 +70,11 @@ extern struct dma_map_ops dma_iommu_ops;
#endif
extern const struct dma_map_ops dma_nommu_ops;
+extern const struct dma_map_ops *get_pci_dma_ops(void);
+
static inline const struct dma_map_ops *get_arch_dma_ops(struct bus_type *bus)
{
- /* We don't handle the NULL dev case for ISA for now. We could
- * do it via an out of line call but it is not needed for now. The
- * only ISA DMA device we support is the floppy and we have a hack
- * in the floppy driver directly to get a device for us.
- */
- return NULL;
+ return get_pci_dma_ops();
}
/*
^ permalink raw reply related
* Re: [PATCH] powerpc/prom_init: add __init markers to all functions
From: Michael Ellerman @ 2019-02-05 10:28 UTC (permalink / raw)
To: Masahiro Yamada, linuxppc-dev
Cc: Mathieu Malaterre, Aneesh Kumar K.V, linux-kernel,
Masahiro Yamada, Paul Mackerras
In-Reply-To: <1548903199-32695-1-git-send-email-yamada.masahiro@socionext.com>
Masahiro Yamada <yamada.masahiro@socionext.com> writes:
> It is fragile to rely on the compiler's optimization to avoid the
> section mismatch. Some functions may not be necessarily inlined
> when the compiler's inlining heuristic changes.
>
> Add __init markers consistently.
>
> As for prom_getprop() and prom_getproplen(), they are marked as
> 'inline', so inlining is guaranteed because PowerPC never enables
> CONFIG_OPTIMIZE_INLINING. However, it would be better to leave the
> inlining decision to the compiler. I replaced 'inline' with __init.
I'm going to drop that part because it breaks the build in some
configurations (as reported by the build robot).
> diff --git a/arch/powerpc/kernel/prom_init.c b/arch/powerpc/kernel/prom_init.c
> index f33ff41..85b0719 100644
> --- a/arch/powerpc/kernel/prom_init.c
> +++ b/arch/powerpc/kernel/prom_init.c
> @@ -501,19 +501,19 @@ static int __init prom_next_node(phandle *nodep)
> }
> }
>
> -static inline int prom_getprop(phandle node, const char *pname,
> +static int __init prom_getprop(phandle node, const char *pname,
> void *value, size_t valuelen)
> {
> return call_prom("getprop", 4, 1, node, ADDR(pname),
> (u32)(unsigned long) value, (u32) valuelen);
> }
>
> -static inline int prom_getproplen(phandle node, const char *pname)
> +static int __init prom_getproplen(phandle node, const char *pname)
> {
> return call_prom("getproplen", 2, 1, node, ADDR(pname));
> }
>
> -static void add_string(char **str, const char *q)
> +static void __init add_string(char **str, const char *q)
> {
> char *p = *str;
>
> @@ -523,7 +523,7 @@ static void add_string(char **str, const char *q)
> *str = p;
> }
>
> -static char *tohex(unsigned int x)
> +static char __init *tohex(unsigned int x)
> {
> static const char digits[] __initconst = "0123456789abcdef";
> static char result[9] __prombss;
> @@ -570,7 +570,7 @@ static int __init prom_setprop(phandle node, const char *nodename,
> #define islower(c) ('a' <= (c) && (c) <= 'z')
> #define toupper(c) (islower(c) ? ((c) - 'a' + 'A') : (c))
>
> -static unsigned long prom_strtoul(const char *cp, const char **endp)
> +static unsigned long __init prom_strtoul(const char *cp, const char **endp)
> {
> unsigned long result = 0, base = 10, value;
>
> @@ -595,7 +595,7 @@ static unsigned long prom_strtoul(const char *cp, const char **endp)
> return result;
> }
>
> -static unsigned long prom_memparse(const char *ptr, const char **retptr)
> +static unsigned long __init prom_memparse(const char *ptr, const char **retptr)
> {
> unsigned long ret = prom_strtoul(ptr, retptr);
> int shift = 0;
> @@ -2924,7 +2924,7 @@ static void __init fixup_device_tree_pasemi(void)
> prom_setprop(iob, name, "device_type", "isa", sizeof("isa"));
> }
> #else /* !CONFIG_PPC_PASEMI_NEMO */
> -static inline void fixup_device_tree_pasemi(void) { }
> +static inline void __init fixup_device_tree_pasemi(void) { }
I don't think we need __init for an empty static inline.
> #endif
>
> static void __init fixup_device_tree(void)
> @@ -2986,15 +2986,15 @@ static void __init prom_check_initrd(unsigned long r3, unsigned long r4)
>
> #ifdef CONFIG_PPC64
> #ifdef CONFIG_RELOCATABLE
> -static void reloc_toc(void)
> +static void __init reloc_toc(void)
> {
> }
>
> -static void unreloc_toc(void)
> +static void __init unreloc_toc(void)
> {
> }
Those should be empty static inlines, I'll fix them up.
> #else
> -static void __reloc_toc(unsigned long offset, unsigned long nr_entries)
> +static void __init __reloc_toc(unsigned long offset, unsigned long nr_entries)
> {
> unsigned long i;
> unsigned long *toc_entry;
> @@ -3008,7 +3008,7 @@ static void __reloc_toc(unsigned long offset, unsigned long nr_entries)
> }
> }
>
> -static void reloc_toc(void)
> +static void __init reloc_toc(void)
> {
> unsigned long offset = reloc_offset();
> unsigned long nr_entries =
> @@ -3019,7 +3019,7 @@ static void reloc_toc(void)
> mb();
> }
>
> -static void unreloc_toc(void)
> +static void __init unreloc_toc(void)
> {
> unsigned long offset = reloc_offset();
> unsigned long nr_entries =
cheers
^ permalink raw reply
* Re: [PATCH v02] powerpc/pseries: Check for ceded CPU's during LPAR migration
From: Michael Ellerman @ 2019-02-05 10:24 UTC (permalink / raw)
To: Michael Bringmann, linuxppc-dev, Juliet Kim, Tyrel Datwyler,
Thomas Falcon, Nathan Lynch, Gustavo Walbon, Pete Heyrman
In-Reply-To: <e94ed583-a4d9-b03a-cd44-be990b6cfa19@linux.vnet.ibm.com>
Michael Bringmann <mwb@linux.vnet.ibm.com> writes:
> See below.
>
> On 1/31/19 3:53 PM, Michael Bringmann wrote:
>> On 1/30/19 11:38 PM, Michael Ellerman wrote:
>>> Michael Bringmann <mwb@linux.vnet.ibm.com> writes:
>>>> This patch is to check for cede'ed CPUs during LPM. Some extreme
>>>> tests encountered a problem ehere Linux has put some threads to
>>>> sleep (possibly to save energy or something), LPM was attempted,
>>>> and the Linux kernel didn't awaken the sleeping threads, but issued
>>>> the H_JOIN for the active threads. Since the sleeping threads
>>>> are not awake, they can not issue the expected H_JOIN, and the
>>>> partition would never suspend. This patch wakes the sleeping
>>>> threads back up.
>>>
>>> I'm don't think this is the right solution.
>>>
>>> Just after your for loop we do an on_each_cpu() call, which sends an IPI
>>> to every CPU, and that should wake all CPUs up from CEDE.
>>>
>>> If that's not happening then there is a bug somewhere, and we need to
>>> work out where.
>
> From Pete Heyrman:
> Both sending IPI or H_PROD will awaken a logical processors that has ceded.
> When you have logical proc doing cede and one logical proc doing prod or IPI
> you have a race condition that the prod/IPI can proceed the cede request.
> If you use prod, the hypervisor takes care of the synchronization by ignoring
> a cede request if it was preceeded by a prod. With IPI the interrupt is
> delivered which could then be followed by a cede so OS would need to provide
> synchronization.
>
> Shouldn't this answer your concerns about race conditions and the suitability
> of using H_PROD?
No sorry it doesn't.
Assuming the other CPU is idle it will just continually do CEDE in a
loop, sending it a PROD will just wake it up once and then it will CEDE
again. That first CEDE might return immediately on seeing the PROD, but
then the kernel will just CEDE again because it has nothing to do.
In contrast the IPI we send wakes up the other CPU and tells it to run a
function, rtas_percpu_suspend_me(), which does the H_JOIN directly.
I still don't understand how the original bug ever even happened. That's
what I want to know.
The way we do the joining and suspend seems like it could be simpler,
there's a bunch of atomic flags and __rtas_suspend_last_cpu() seems to
duplicate much of __rtas_suspend_cpu(). It seems more likely we have a
bug in there somewhere.
cheers
^ permalink raw reply
* [PATCH v4 2/2] drivers: soc: fsl: add qixis driver
From: Pankaj Bansal @ 2019-02-05 10:14 UTC (permalink / raw)
To: Leo Li, Rob Herring, Mark Rutland
Cc: open list : OPEN FIRMWARE AND FLATTENED DEVICE TREE BINDINGS,
Pankaj Bansal, linuxppc-dev@lists.ozlabs.org, Wang Dongsheng,
linux-arm-kernel@lists.infradead.org
In-Reply-To: <20190205153924.7204-1-pankaj.bansal@nxp.com>
FPGA on LX2160AQDS/LX2160ARDB connected on I2C bus, so add qixis
driver which is basically an i2c client driver to control FPGA.
Also added platform driver for MMIO based FPGA, like the one available
on LS2088ARDB/LS2088AQDS.
Signed-off-by: Wang Dongsheng <dongsheng.wang@freescale.com>
Signed-off-by: Pankaj Bansal <pankaj.bansal@nxp.com>
---
Notes:
V4:
- Fix compilation error when qixis_ctrl is built as standalone module.
V3:
- Add MMIO based FPGA driver
V2:
- Modify the driver to not create platform devices corresponding to subnodes.
because the subnodes are not actual devices.
- Use mdio_mux_regmap_init/mdio_mux_regmap_uninit
- Remove header file from include folder, as no qixis api is called from outside
- Add regmap_exit in driver's remove function
Dendencies:
- https://www.mail-archive.com/netdev@vger.kernel.org/msg281274.html
drivers/soc/fsl/Kconfig | 11 ++
drivers/soc/fsl/Makefile | 1 +
drivers/soc/fsl/qixis_ctrl.c | 222 +++++++++++++++++++++++++++++++++
3 files changed, 234 insertions(+)
diff --git a/drivers/soc/fsl/Kconfig b/drivers/soc/fsl/Kconfig
index 8f80e8bbf29e..75993be04e42 100644
--- a/drivers/soc/fsl/Kconfig
+++ b/drivers/soc/fsl/Kconfig
@@ -28,4 +28,15 @@ config FSL_MC_DPIO
other DPAA2 objects. This driver does not expose the DPIO
objects individually, but groups them under a service layer
API.
+
+config FSL_QIXIS
+ tristate "QIXIS system controller driver"
+ depends on OF
+ select REGMAP_I2C
+ select REGMAP_MMIO
+ default n
+ help
+ Say y here to enable QIXIS system controller api. The qixis driver
+ provides FPGA functions to control system.
+
endmenu
diff --git a/drivers/soc/fsl/Makefile b/drivers/soc/fsl/Makefile
index 803ef1bfb5ff..47e0cfc66ca4 100644
--- a/drivers/soc/fsl/Makefile
+++ b/drivers/soc/fsl/Makefile
@@ -5,5 +5,6 @@
obj-$(CONFIG_FSL_DPAA) += qbman/
obj-$(CONFIG_QUICC_ENGINE) += qe/
obj-$(CONFIG_CPM) += qe/
+obj-$(CONFIG_FSL_QIXIS) += qixis_ctrl.o
obj-$(CONFIG_FSL_GUTS) += guts.o
obj-$(CONFIG_FSL_MC_DPIO) += dpio/
diff --git a/drivers/soc/fsl/qixis_ctrl.c b/drivers/soc/fsl/qixis_ctrl.c
new file mode 100644
index 000000000000..a8108bfd5195
--- /dev/null
+++ b/drivers/soc/fsl/qixis_ctrl.c
@@ -0,0 +1,222 @@
+// SPDX-License-Identifier: GPL-2.0+
+
+/* Freescale QIXIS system controller driver.
+ *
+ * Copyright 2015 Freescale Semiconductor, Inc.
+ * Copyright 2018-2019 NXP
+ */
+
+#include <linux/device.h>
+#include <linux/err.h>
+#include <linux/io.h>
+#include <linux/i2c.h>
+#include <linux/module.h>
+#include <linux/of_address.h>
+#include <linux/of_platform.h>
+#include <linux/platform_device.h>
+#include <linux/regmap.h>
+#include <linux/mdio-mux.h>
+
+/* QIXIS MAP */
+struct fsl_qixis_regs {
+ u8 id; /* Identification Registers */
+ u8 version; /* Version Register */
+ u8 qixis_ver; /* QIXIS Version Register */
+ u8 reserved1[0x1f];
+};
+
+struct mdio_mux_data {
+ void *data;
+ struct list_head link;
+};
+
+struct qixis_priv {
+ struct regmap *regmap;
+ struct list_head mdio_mux_list;
+};
+
+static struct regmap_config qixis_regmap_config = {
+ .reg_bits = 8,
+ .val_bits = 8,
+};
+
+static int fsl_qixis_mdio_mux_init(struct device *dev, struct qixis_priv *priv)
+{
+ struct device_node *child;
+ struct mdio_mux_data *mux_data;
+ int ret;
+
+ INIT_LIST_HEAD(&priv->mdio_mux_list);
+ for_each_child_of_node(dev->of_node, child) {
+ if (!of_node_name_prefix(child, "mdio-mux"))
+ continue;
+
+ mux_data = devm_kzalloc(dev, sizeof(struct mdio_mux_data),
+ GFP_KERNEL);
+ if (!mux_data)
+ return -ENOMEM;
+ ret = mdio_mux_regmap_init(dev, child, &mux_data->data);
+ if (ret)
+ return ret;
+ list_add(&mux_data->link, &priv->mdio_mux_list);
+ }
+
+ return 0;
+}
+
+static int fsl_qixis_mdio_mux_uninit(struct qixis_priv *priv)
+{
+ struct list_head *pos;
+ struct mdio_mux_data *mux_data;
+
+ list_for_each(pos, &priv->mdio_mux_list) {
+ mux_data = list_entry(pos, struct mdio_mux_data, link);
+ mdio_mux_regmap_uninit(mux_data->data);
+ }
+
+ return 0;
+}
+
+static int fsl_qixis_probe(struct platform_device *pdev)
+{
+ static struct fsl_qixis_regs __iomem *qixis;
+ struct qixis_priv *priv;
+ int ret;
+ u32 qver;
+
+ qixis = of_iomap(pdev->dev.of_node, 0);
+ if (IS_ERR_OR_NULL(qixis)) {
+ pr_err("%s: Could not map qixis registers\n", __func__);
+ return -ENODEV;
+ }
+
+ priv = devm_kzalloc(&pdev->dev, sizeof(struct qixis_priv), GFP_KERNEL);
+ if (!priv)
+ return -ENOMEM;
+
+ priv->regmap = devm_regmap_init_mmio(&pdev->dev, qixis,
+ &qixis_regmap_config);
+ regmap_read(priv->regmap, offsetof(struct fsl_qixis_regs, qixis_ver),
+ &qver);
+ pr_info("Freescale QIXIS Version: 0x%08x\n", qver);
+
+ ret = fsl_qixis_mdio_mux_init(&pdev->dev, priv);
+ if (ret)
+ goto error;
+
+ platform_set_drvdata(pdev, priv);
+
+ return 0;
+error:
+ regmap_exit(priv->regmap);
+
+ return ret;
+}
+
+static int fsl_qixis_remove(struct platform_device *pdev)
+{
+ struct qixis_priv *priv;
+
+ priv = platform_get_drvdata(pdev);
+ fsl_qixis_mdio_mux_uninit(priv);
+ regmap_exit(priv->regmap);
+
+ return 0;
+}
+
+static const struct of_device_id fsl_qixis_of_match[] = {
+ { .compatible = "fsl,fpga-qixis", },
+ {},
+};
+MODULE_DEVICE_TABLE(of, fsl_qixis_of_match);
+
+static struct platform_driver fsl_qixis_driver = {
+ .driver = {
+ .name = "qixis_ctrl",
+ .owner = THIS_MODULE,
+ .of_match_table = of_match_ptr(fsl_qixis_of_match),
+ },
+ .probe = fsl_qixis_probe,
+ .remove = fsl_qixis_remove,
+};
+
+static int fsl_qixis_i2c_probe(struct i2c_client *client)
+{
+ struct qixis_priv *priv;
+ int ret;
+ u32 qver;
+
+ if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA))
+ return -EOPNOTSUPP;
+
+ priv = devm_kzalloc(&client->dev, sizeof(struct qixis_priv),
+ GFP_KERNEL);
+ if (!priv)
+ return -ENOMEM;
+
+ priv->regmap = regmap_init_i2c(client, &qixis_regmap_config);
+ regmap_read(priv->regmap, offsetof(struct fsl_qixis_regs, qixis_ver),
+ &qver);
+ pr_info("Freescale QIXIS Version: 0x%08x\n", qver);
+
+ ret = fsl_qixis_mdio_mux_init(&client->dev, priv);
+ if (ret)
+ goto error;
+
+ i2c_set_clientdata(client, priv);
+
+ return 0;
+error:
+ regmap_exit(priv->regmap);
+
+ return ret;
+}
+
+static int fsl_qixis_i2c_remove(struct i2c_client *client)
+{
+ struct qixis_priv *priv;
+
+ priv = i2c_get_clientdata(client);
+ fsl_qixis_mdio_mux_uninit(priv);
+ regmap_exit(priv->regmap);
+
+ return 0;
+}
+
+static const struct of_device_id fsl_qixis_i2c_of_match[] = {
+ { .compatible = "fsl,fpga-qixis-i2c" },
+ {}
+};
+MODULE_DEVICE_TABLE(of, fsl_qixis_i2c_of_match);
+
+static struct i2c_driver fsl_qixis_i2c_driver = {
+ .driver = {
+ .name = "qixis_ctrl_i2c",
+ .owner = THIS_MODULE,
+ .of_match_table = of_match_ptr(fsl_qixis_i2c_of_match),
+ },
+ .probe_new = fsl_qixis_i2c_probe,
+ .remove = fsl_qixis_i2c_remove,
+};
+
+static int __init fsl_qixis_init(void)
+{
+ pr_info("FSL: Qixis Control driver\n");
+
+ if (platform_driver_register(&fsl_qixis_driver))
+ pr_warn("could not register Qixis Control platform driver\n");
+ return i2c_add_driver(&fsl_qixis_i2c_driver);
+}
+module_init(fsl_qixis_init);
+
+static void __exit fsl_qixis_exit(void)
+{
+ platform_driver_unregister(&fsl_qixis_driver);
+ i2c_del_driver(&fsl_qixis_i2c_driver);
+}
+module_exit(fsl_qixis_exit);
+
+MODULE_AUTHOR("Wang Dongsheng <dongsheng.wang@freescale.com>");
+MODULE_DESCRIPTION("Freescale QIXIS system controller driver");
+MODULE_LICENSE("GPL");
+
--
2.17.1
^ permalink raw reply related
* [PATCH v4 1/2] dt-bindings: soc: fsl: Document Qixis FPGA usage
From: Pankaj Bansal @ 2019-02-05 10:14 UTC (permalink / raw)
To: Leo Li, Rob Herring, Mark Rutland
Cc: open list : OPEN FIRMWARE AND FLATTENED DEVICE TREE BINDINGS,
Pankaj Bansal, linuxppc-dev@lists.ozlabs.org,
linux-arm-kernel@lists.infradead.org
In-Reply-To: <20190205153924.7204-1-pankaj.bansal@nxp.com>
an FPGA-based system controller, called “Qixis”, which
manages several critical system features, including:
• Reset sequencing
• Power supply configuration
• Board configuration
• hardware configuration
The qixis registers are accessible over one or more system-specific
interfaces, typically I2C, JTAG or an embedded processor.
Signed-off-by: Pankaj Bansal <pankaj.bansal@nxp.com>
---
Notes:
V4:
- No Change
V3:
- Added boardname based compatible field in bindings
- Added bindings for MMIO based FPGA
V2:
- No change
.../bindings/soc/fsl/qixis_ctrl.txt | 53 ++++++++++++++++++
1 file changed, 53 insertions(+)
diff --git a/Documentation/devicetree/bindings/soc/fsl/qixis_ctrl.txt b/Documentation/devicetree/bindings/soc/fsl/qixis_ctrl.txt
new file mode 100644
index 000000000000..5d510df14be8
--- /dev/null
+++ b/Documentation/devicetree/bindings/soc/fsl/qixis_ctrl.txt
@@ -0,0 +1,53 @@
+* QIXIS FPGA block
+
+an FPGA-based system controller, called “Qixis”, which
+manages several critical system features, including:
+• Configuration switch monitoring
+• Power on/off sequencing
+• Reset sequencing
+• Power supply configuration
+• Board configuration
+• hardware configuration
+• Background power data collection (DCM)
+• Fault monitoring
+• RCW bypass SRAM (replace flash RCW with internal RCW) (NOR only)
+• Dedicated functional validation blocks (POSt/IRS, triggered event, and so on)
+• I2C master for remote board control even with no DUT available
+
+The qixis registers are accessible over one or more system-specific interfaces,
+typically I2C, JTAG or an embedded processor.
+
+FPGA connected to I2C:
+Required properties:
+
+ - compatible: should be a board-specific string followed by a string
+ indicating the type of FPGA. Example:
+ "fsl,<board>-fpga", "fsl,fpga-qixis-i2c"
+ - reg : i2c address of the qixis device.
+
+Example (LX2160A-QDS):
+ /* The FPGA node */
+ fpga@66 {
+ compatible = "fsl,lx2160aqds-fpga", "fsl,fpga-qixis-i2c";
+ reg = <0x66>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ }
+
+* Freescale on-board FPGA
+
+This is the memory-mapped registers for on board FPGA.
+
+Required properties:
+- compatible: should be a board-specific string followed by a string
+ indicating the type of FPGA. Example:
+ "fsl,<board>-fpga", "fsl,fpga-qixis"
+- reg: should contain the address and the length of the FPGA register set.
+
+Example (LS2080A-RDB):
+
+ cpld@3,0 {
+ compatible = "fsl,ls2080ardb-fpga", "fsl,fpga-qixis";
+ reg = <0x3 0 0x10000>;
+ };
+
--
2.17.1
^ permalink raw reply related
* [PATCH v4 0/2] add qixis driver
From: Pankaj Bansal @ 2019-02-05 10:14 UTC (permalink / raw)
To: Leo Li, Rob Herring, Mark Rutland
Cc: open list : OPEN FIRMWARE AND FLATTENED DEVICE TREE BINDINGS,
Pankaj Bansal, linuxppc-dev@lists.ozlabs.org, Varun Sethi,
linux-arm-kernel@lists.infradead.org
FPGA on LX2160AQDS/LX2160ARDB connected on I2C bus, so add qixis driver which is basically an i2c client driver to control FPGA.
Also added platform driver for MMIO based FPGA, like the one available on LS2088ARDB/LS2088AQDS.
This driver is essential to control MDIO mux multiplexing.
This driver is dependent on below patches:
https://www.mail-archive.com/netdev@vger.kernel.org/msg281274.html
Cc: Varun Sethi <V.Sethi@nxp.com>
---
Notes:
V3:
- https://patchwork.kernel.org/cover/10795195/
V2:
- https://patchwork.kernel.org/cover/10788341/
V1:
- https://patchwork.kernel.org/cover/10627297/
Pankaj Bansal (2):
dt-bindings: soc: fsl: Document Qixis FPGA usage
drivers: soc: fsl: add qixis driver
.../bindings/soc/fsl/qixis_ctrl.txt | 53 +++++
drivers/soc/fsl/Kconfig | 11 +
drivers/soc/fsl/Makefile | 1 +
drivers/soc/fsl/qixis_ctrl.c | 222 ++++++++++++++++++
4 files changed, 287 insertions(+)
create mode 100644 Documentation/devicetree/bindings/soc/fsl/qixis_ctrl.txt
create mode 100644 drivers/soc/fsl/qixis_ctrl.c
--
2.17.1
^ permalink raw reply
* Re: [RFC/WIP] powerpc: Fix 32-bit handling of MSR_EE on exceptions
From: Michael Ellerman @ 2019-02-05 10:10 UTC (permalink / raw)
To: Christophe Leroy, Benjamin Herrenschmidt,
linuxppc-dev@lists.ozlabs.org
Cc: Diana Craciun, Scott Wood, Nick Piggin, Laurentiu Tudor
In-Reply-To: <5a97253c-0ec4-d61f-fa9e-ea5da8590f32@c-s.fr>
Christophe Leroy <christophe.leroy@c-s.fr> writes:
> Le 20/12/2018 à 23:35, Benjamin Herrenschmidt a écrit :
>>
>>>> /*
>>>> * MSR_KERNEL is > 0x10000 on 4xx/Book-E since it include MSR_CE.
>>>> @@ -205,20 +208,46 @@ transfer_to_handler_cont:
>>>> mflr r9
>>>> lwz r11,0(r9) /* virtual address of handler */
>>>> lwz r9,4(r9) /* where to go when done */
>>>> +#if defined(CONFIG_PPC_8xx) && defined(CONFIG_PERF_EVENTS)
>>>> + mtspr SPRN_NRI, r0
>>>> +#endif
>>>
>>> That's not part of your patch, it's already in the tree.
>>
>> Yup rebase glitch.
>>
>> .../...
>>
>>> I tested it on the 8xx with the below changes in addition. No issue seen
>>> so far.
>>
>> Thanks !
>>
>> I'll merge that in.
>
> I'm currently working on a refactorisation and simplification of
> exception and syscall entry on ppc32.
>
> I plan to take your patch in my serie as it helps quite a bit. I hope
> you don't mind. I expect to come out with a series this week.
Ben's AFK so go ahead and pull it in to your series if that helps you.
>> The main obscure area is that business with the irqsoff tracer and thus
>> the need to create stack frames around calls to trace_hardirqs_* ... we
>> do it in some places and not others, but I've not managed to make it
>> crash either. I need to get to the bottom of that, and possibly provide
>> proper macro helpers like ppc64 has to do it.
>
> I can't see anything special around this in ppc32 code. As far as I
> understand, a stack frame is put in place when there is a need to
> save and restore some volatile registers. At the places where nothing
> needs to be saved, nothing is done. I think that's the normal way for
> any function call, isn't it ?
The concern was that the irqsoff tracer was doing
__builtin_return_address(1) (or some number > 0) and that crashes if
there aren't sufficiently many stack frames available.
See ftrace_return_address.
Possibly the answer is that we don't have CONFIG_FRAME_POINTER and so we
get the empty version of that.
cheers
^ permalink raw reply
* Re: [PATCH v02] powerpc/pseries: Check for ceded CPU's during LPAR migration
From: Michael Ellerman @ 2019-02-05 10:05 UTC (permalink / raw)
To: Tyrel Datwyler, Michael Bringmann, linuxppc-dev, Juliet Kim,
Thomas Falcon, Nathan Lynch, Gustavo Walbon, Pete Heyrman
In-Reply-To: <25fbcee4-b1c1-de1e-efc0-6bb4bf081d45@linux.vnet.ibm.com>
Tyrel Datwyler <tyreld@linux.vnet.ibm.com> writes:
> On 01/31/2019 02:21 PM, Tyrel Datwyler wrote:
>> On 01/31/2019 01:53 PM, Michael Bringmann wrote:
>>> On 1/30/19 11:38 PM, Michael Ellerman wrote:
>>>> Michael Bringmann <mwb@linux.vnet.ibm.com> writes:
>>>>> This patch is to check for cede'ed CPUs during LPM. Some extreme
>>>>> tests encountered a problem ehere Linux has put some threads to
>>>>> sleep (possibly to save energy or something), LPM was attempted,
>>>>> and the Linux kernel didn't awaken the sleeping threads, but issued
>>>>> the H_JOIN for the active threads. Since the sleeping threads
>>>>> are not awake, they can not issue the expected H_JOIN, and the
>>>>> partition would never suspend. This patch wakes the sleeping
>>>>> threads back up.
>>>>
>>>> I'm don't think this is the right solution.
>>>>
>>>> Just after your for loop we do an on_each_cpu() call, which sends an IPI
>>>> to every CPU, and that should wake all CPUs up from CEDE.
>>>>
>>>> If that's not happening then there is a bug somewhere, and we need to
>>>> work out where.
>>>
>>> Let me explain the scenario of the LPM case that Pete Heyrman found, and
>>> that Nathan F. was working upon, previously.
>>>
>>> In the scenario, the partition has 5 dedicated processors each with 8 threads
>>> running.
>>
>> Do we CEDE processors when running dedicated? I thought H_CEDE was part of the
>> Shared Processor LPAR option.
>
> Looks like the cpuidle-pseries driver uses CEDE with dedicated processors as
> long as firmware supports SPLPAR option.
>
>>
>>>
>>> From the PHYP data we can see that on VP 0, threads 3, 4, 5, 6 and 7 issued
>>> a H_CEDE requesting to save energy by putting the requesting thread into
>>> sleep mode. In this state, the thread will only be awakened by H_PROD from
>>> another running thread or from an external user action (power off, reboot
>>> and such). Timers and external interrupts are disabled in this mode.
>>
>> Not according to PAPR. A CEDE'd processor should awaken if signaled by external
>> interrupt such as decrementer or IPI as well.
>
> This statement should still apply though. From PAPR:
>
> 14.11.3.3 H_CEDE
> The architectural intent of this hcall() is to have the virtual processor, which
> has no useful work to do, enter a wait state ceding its processor capacity to
> other virtual processors until some useful work appears, signaled either through
> an interrupt or a prod hcall(). To help the caller reduce race conditions, this
> call may be made with interrupts disabled but the semantics of the hcall()
> enable the virtual processor’s interrupts so that it may always receive wake up
> interrupt signals.
Thanks for digging that out of PAPR.
H_CEDE must respond to IPIs, we have no logic to H_PROD CPUs that are
idle in order to wake them up.
There must be something else going on here.
cheers
^ permalink raw reply
* Re: [PATCH v2] powerpc: drop page_is_ram() and walk_system_ram_range()
From: Michael Ellerman @ 2019-02-05 10:04 UTC (permalink / raw)
To: Christophe Leroy, Benjamin Herrenschmidt, Paul Mackerras
Cc: linuxppc-dev, linux-kernel
In-Reply-To: <248f8aa2-10c2-2728-6f94-a56816a989e1@c-s.fr>
Christophe Leroy <christophe.leroy@c-s.fr> writes:
> Le 04/02/2019 à 11:24, Michael Ellerman a écrit :
>> Christophe Leroy <christophe.leroy@c-s.fr> writes:
>>
>>> Since commit c40dd2f76644 ("powerpc: Add System RAM to /proc/iomem")
>>> it is possible to use the generic walk_system_ram_range() and
>>> the generic page_is_ram().
>>>
>>> To enable the use of walk_system_ram_range() by the IBM EHEA
>>> ethernet driver, the generic function has to be exported.
>>
>> I'm not sure if we have a policy on that, but I suspect we'd rather not
>> add a new export on all arches unless we need to. Especially seeing as
>> the only user is the EHEA code which is heavily in maintenance mode.
>
> If you take the exemple of function walk_iomem_res_desc(), that's
> similar. It is only used by x86 it seems and exported for nvdimm/e820
> driver only.
>
> See commit d76401ade0bb6ab0a7 ("libnvdimm, e820: Register all pmem
> resources")
OK. Which begs the question whether we need both exported. It looks like
you could probably use walk_iomem_res_desc() with the right flags to do
the same thing as walk_system_ram_range().
>> I'll put the export in powerpc code and make sure that builds.
>
> I thought there was a rule that EXPORT_SYMBOL has to immediately follow
> the function it exports. At least checkpatch checks for that.
Yeah that is a rule. But rules are made to be broken :)
I'll merge it for now with the export in powerpc code, if we want to we
can do a separate patch to move that export into generic code and get
acks for that.
cheers
^ permalink raw reply
* Re: [RFC/WIP] powerpc: Fix 32-bit handling of MSR_EE on exceptions
From: Christophe Leroy @ 2019-02-05 9:45 UTC (permalink / raw)
To: Benjamin Herrenschmidt, linuxppc-dev@lists.ozlabs.org
Cc: Diana Craciun, Scott Wood, Nick Piggin, Laurentiu Tudor
In-Reply-To: <ab9139902a64f8d0b187f7db0f8a16a5b85791ac.camel@kernel.crashing.org>
Le 20/12/2018 à 23:35, Benjamin Herrenschmidt a écrit :
>
>>> /*
>>> * MSR_KERNEL is > 0x10000 on 4xx/Book-E since it include MSR_CE.
>>> @@ -205,20 +208,46 @@ transfer_to_handler_cont:
>>> mflr r9
>>> lwz r11,0(r9) /* virtual address of handler */
>>> lwz r9,4(r9) /* where to go when done */
>>> +#if defined(CONFIG_PPC_8xx) && defined(CONFIG_PERF_EVENTS)
>>> + mtspr SPRN_NRI, r0
>>> +#endif
>>
>> That's not part of your patch, it's already in the tree.
>
> Yup rebase glitch.
>
> .../...
>
>> I tested it on the 8xx with the below changes in addition. No issue seen
>> so far.
>
> Thanks !
>
> I'll merge that in.
I'm currently working on a refactorisation and simplification of
exception and syscall entry on ppc32.
I plan to take your patch in my serie as it helps quite a bit. I hope
you don't mind. I expect to come out with a series this week.
>
> The main obscure area is that business with the irqsoff tracer and thus
> the need to create stack frames around calls to trace_hardirqs_* ... we
> do it in some places and not others, but I've not managed to make it
> crash either. I need to get to the bottom of that, and possibly provide
> proper macro helpers like ppc64 has to do it.
I can't see anything special around this in ppc32 code. As far as I
understand, a stack frame is put in place when there is a need to
save and restore some volatile registers. At the places where nothing
needs to be saved, nothing is done. I think that's the normal way for
any function call, isn't it ?
Christophe
^ permalink raw reply
* Re: [RFC PATCH] virtio_ring: Use DMA API if guest memory is encrypted
From: Christoph Hellwig @ 2019-02-05 7:24 UTC (permalink / raw)
To: Michael S. Tsirkin
Cc: Jean-Philippe Brucker, Jason Wang, Alexey Kardashevskiy, Ram Pai,
linux-kernel, virtualization, iommu, linuxppc-dev,
Christoph Hellwig, Thiago Jung Bauermann, David Gibson
In-Reply-To: <20190204152416-mutt-send-email-mst@kernel.org>
On Mon, Feb 04, 2019 at 04:38:21PM -0500, Michael S. Tsirkin wrote:
> It was designed to make, when set, as many guests as we can work
> correctly, and it seems to be successful in doing exactly that.
>
> Unfortunately there could be legacy guests that do work correctly but
> become slow. Whether trying to somehow work around that
> can paint us into a corner where things again don't
> work for some people is a question worth discussing.
The other problem is that some qemu machines just throw passthrough
devices and virtio devices on the same virtual PCI(e) bus, and have a
common IOMMU setup for the whole bus / root port / domain. I think
this is completely bogus, but unfortunately it is out in the field.
Given that power is one of these examples I suspect that is what
Thiago referes to. But in this case the answer can't be that we
pile on hack ontop of another, but instead introduce a new qemu
machine that separates these clearly, and make that mandatory for
the secure guest support.
^ permalink raw reply
* Re: [PATCH v2] powerpc: drop page_is_ram() and walk_system_ram_range()
From: Christophe Leroy @ 2019-02-05 6:48 UTC (permalink / raw)
To: Michael Ellerman, Benjamin Herrenschmidt, Paul Mackerras
Cc: linuxppc-dev, linux-kernel
In-Reply-To: <875ztzonqd.fsf@concordia.ellerman.id.au>
Le 04/02/2019 à 11:24, Michael Ellerman a écrit :
> Christophe Leroy <christophe.leroy@c-s.fr> writes:
>
>> Since commit c40dd2f76644 ("powerpc: Add System RAM to /proc/iomem")
>> it is possible to use the generic walk_system_ram_range() and
>> the generic page_is_ram().
>>
>> To enable the use of walk_system_ram_range() by the IBM EHEA
>> ethernet driver, the generic function has to be exported.
>
> I'm not sure if we have a policy on that, but I suspect we'd rather not
> add a new export on all arches unless we need to. Especially seeing as
> the only user is the EHEA code which is heavily in maintenance mode.
If you take the exemple of function walk_iomem_res_desc(), that's
similar. It is only used by x86 it seems and exported for nvdimm/e820
driver only.
See commit d76401ade0bb6ab0a7 ("libnvdimm, e820: Register all pmem
resources")
>
> I'll put the export in powerpc code and make sure that builds.
I thought there was a rule that EXPORT_SYMBOL has to immediately follow
the function it exports. At least checkpatch checks for that.
Christophe
>
>> As powerpc was the only (last?) user of CONFIG_ARCH_HAS_WALK_MEMORY,
>> the #ifdef around the generic walk_system_ram_range() has become
>> useless and can be dropped.
>
> Yes it was the only user:
>
> a99824f327c7 ("[POWERPC] Add arch-specific walk_memory_remove() for 64-bit powerpc")
>
> I'll update the changelog.
>
> cheers
>
>
>> Fixes: c40dd2f76644 ("powerpc: Add System RAM to /proc/iomem")
>> Signed-off-by: Christophe Leroy <christophe.leroy@c-s.fr>
>> ---
>> arch/powerpc/Kconfig | 3 ---
>> arch/powerpc/include/asm/page.h | 1 -
>> arch/powerpc/mm/mem.c | 33 ---------------------------------
>> kernel/resource.c | 5 +----
>> 4 files changed, 1 insertion(+), 41 deletions(-)
>>
>> diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig
>> index 2890d36eb531..f92e6754edf1 100644
>> --- a/arch/powerpc/Kconfig
>> +++ b/arch/powerpc/Kconfig
>> @@ -478,9 +478,6 @@ config ARCH_CPU_PROBE_RELEASE
>> config ARCH_ENABLE_MEMORY_HOTPLUG
>> def_bool y
>>
>> -config ARCH_HAS_WALK_MEMORY
>> - def_bool y
>> -
>> config ARCH_ENABLE_MEMORY_HOTREMOVE
>> def_bool y
>>
>> diff --git a/arch/powerpc/include/asm/page.h b/arch/powerpc/include/asm/page.h
>> index 5c5ea2413413..aa4497175bd3 100644
>> --- a/arch/powerpc/include/asm/page.h
>> +++ b/arch/powerpc/include/asm/page.h
>> @@ -326,7 +326,6 @@ struct page;
>> extern void clear_user_page(void *page, unsigned long vaddr, struct page *pg);
>> extern void copy_user_page(void *to, void *from, unsigned long vaddr,
>> struct page *p);
>> -extern int page_is_ram(unsigned long pfn);
>> extern int devmem_is_allowed(unsigned long pfn);
>>
>> #ifdef CONFIG_PPC_SMLPAR
>> diff --git a/arch/powerpc/mm/mem.c b/arch/powerpc/mm/mem.c
>> index 33cc6f676fa6..fa9916c2c662 100644
>> --- a/arch/powerpc/mm/mem.c
>> +++ b/arch/powerpc/mm/mem.c
>> @@ -80,11 +80,6 @@ static inline pte_t *virt_to_kpte(unsigned long vaddr)
>> #define TOP_ZONE ZONE_NORMAL
>> #endif
>>
>> -int page_is_ram(unsigned long pfn)
>> -{
>> - return memblock_is_memory(__pfn_to_phys(pfn));
>> -}
>> -
>> pgprot_t phys_mem_access_prot(struct file *file, unsigned long pfn,
>> unsigned long size, pgprot_t vma_prot)
>> {
>> @@ -176,34 +171,6 @@ int __meminit arch_remove_memory(int nid, u64 start, u64 size,
>> #endif
>> #endif /* CONFIG_MEMORY_HOTPLUG */
>>
>> -/*
>> - * walk_memory_resource() needs to make sure there is no holes in a given
>> - * memory range. PPC64 does not maintain the memory layout in /proc/iomem.
>> - * Instead it maintains it in memblock.memory structures. Walk through the
>> - * memory regions, find holes and callback for contiguous regions.
>> - */
>> -int
>> -walk_system_ram_range(unsigned long start_pfn, unsigned long nr_pages,
>> - void *arg, int (*func)(unsigned long, unsigned long, void *))
>> -{
>> - struct memblock_region *reg;
>> - unsigned long end_pfn = start_pfn + nr_pages;
>> - unsigned long tstart, tend;
>> - int ret = -1;
>> -
>> - for_each_memblock(memory, reg) {
>> - tstart = max(start_pfn, memblock_region_memory_base_pfn(reg));
>> - tend = min(end_pfn, memblock_region_memory_end_pfn(reg));
>> - if (tstart >= tend)
>> - continue;
>> - ret = (*func)(tstart, tend - tstart, arg);
>> - if (ret)
>> - break;
>> - }
>> - return ret;
>> -}
>> -EXPORT_SYMBOL_GPL(walk_system_ram_range);
>> -
>> #ifndef CONFIG_NEED_MULTIPLE_NODES
>> void __init mem_topology_setup(void)
>> {
>> diff --git a/kernel/resource.c b/kernel/resource.c
>> index 915c02e8e5dd..2e1636041508 100644
>> --- a/kernel/resource.c
>> +++ b/kernel/resource.c
>> @@ -448,8 +448,6 @@ int walk_mem_res(u64 start, u64 end, void *arg,
>> arg, func);
>> }
>>
>> -#if !defined(CONFIG_ARCH_HAS_WALK_MEMORY)
>> -
>> /*
>> * This function calls the @func callback against all memory ranges of type
>> * System RAM which are marked as IORESOURCE_SYSTEM_RAM and IORESOUCE_BUSY.
>> @@ -480,8 +478,7 @@ int walk_system_ram_range(unsigned long start_pfn, unsigned long nr_pages,
>> }
>> return ret;
>> }
>> -
>> -#endif
>> +EXPORT_SYMBOL_GPL(walk_system_ram_range);
>>
>> static int __is_ram(unsigned long pfn, unsigned long nr_pages, void *arg)
>> {
>> --
>> 2.13.3
^ permalink raw reply
* Re: [PATCH 15/19] KVM: PPC: Book3S HV: add get/set accessors for the source configuration
From: David Gibson @ 2019-02-05 5:32 UTC (permalink / raw)
To: Cédric Le Goater; +Cc: kvm, kvm-ppc, Paul Mackerras, linuxppc-dev
In-Reply-To: <02ee0470-3c6a-5c5c-a903-44e172ce1ed5@kaod.org>
[-- Attachment #1: Type: text/plain, Size: 3391 bytes --]
On Mon, Feb 04, 2019 at 05:07:28PM +0100, Cédric Le Goater wrote:
> On 2/4/19 6:21 AM, David Gibson wrote:
> > On Mon, Jan 07, 2019 at 07:43:27PM +0100, Cédric Le Goater wrote:
> >> Theses are use to capure the XIVE EAS table of the KVM device, the
> >> configuration of the source targets.
> >>
> >> Signed-off-by: Cédric Le Goater <clg@kaod.org>
> >> ---
> >> arch/powerpc/include/uapi/asm/kvm.h | 11 ++++
> >> arch/powerpc/kvm/book3s_xive_native.c | 87 +++++++++++++++++++++++++++
> >> 2 files changed, 98 insertions(+)
> >>
> >> diff --git a/arch/powerpc/include/uapi/asm/kvm.h b/arch/powerpc/include/uapi/asm/kvm.h
> >> index 1a8740629acf..faf024f39858 100644
> >> --- a/arch/powerpc/include/uapi/asm/kvm.h
> >> +++ b/arch/powerpc/include/uapi/asm/kvm.h
> >> @@ -683,9 +683,20 @@ struct kvm_ppc_cpu_char {
> >> #define KVM_DEV_XIVE_SAVE_EQ_PAGES 4
> >> #define KVM_DEV_XIVE_GRP_SOURCES 2 /* 64-bit source attributes */
> >> #define KVM_DEV_XIVE_GRP_SYNC 3 /* 64-bit source attributes */
> >> +#define KVM_DEV_XIVE_GRP_EAS 4 /* 64-bit eas attributes */
> >>
> >> /* Layout of 64-bit XIVE source attribute values */
> >> #define KVM_XIVE_LEVEL_SENSITIVE (1ULL << 0)
> >> #define KVM_XIVE_LEVEL_ASSERTED (1ULL << 1)
> >>
> >> +/* Layout of 64-bit eas attribute values */
> >> +#define KVM_XIVE_EAS_PRIORITY_SHIFT 0
> >> +#define KVM_XIVE_EAS_PRIORITY_MASK 0x7
> >> +#define KVM_XIVE_EAS_SERVER_SHIFT 3
> >> +#define KVM_XIVE_EAS_SERVER_MASK 0xfffffff8ULL
> >> +#define KVM_XIVE_EAS_MASK_SHIFT 32
> >> +#define KVM_XIVE_EAS_MASK_MASK 0x100000000ULL
> >> +#define KVM_XIVE_EAS_EISN_SHIFT 33
> >> +#define KVM_XIVE_EAS_EISN_MASK 0xfffffffe00000000ULL
> >> +
> >> #endif /* __LINUX_KVM_POWERPC_H */
> >> diff --git a/arch/powerpc/kvm/book3s_xive_native.c b/arch/powerpc/kvm/book3s_xive_native.c
> >> index f2de1bcf3b35..0468b605baa7 100644
> >> --- a/arch/powerpc/kvm/book3s_xive_native.c
> >> +++ b/arch/powerpc/kvm/book3s_xive_native.c
> >> @@ -525,6 +525,88 @@ static int kvmppc_xive_native_sync(struct kvmppc_xive *xive, long irq, u64 addr)
> >> return 0;
> >> }
> >>
> >> +static int kvmppc_xive_native_set_eas(struct kvmppc_xive *xive, long irq,
> >> + u64 addr)
> >
> > I'd prefer to avoid the name "EAS" here. IIUC these aren't "raw" EAS
> > values, but rather essentially the "source config" in the terminology
> > of the PAPR hcalls. Which, yes, is basically implemented by setting
> > the EAS, but since it's the PAPR architected state that we need to
> > preserve across migration, I'd prefer to stick as close as we can to
> > the PAPR terminology.
>
> But we don't have an equivalent name in the PAPR specs for the tuple
> (prio, server). We could use the generic 'target' name may be ? even
> if this is usually referring to a CPU number.
Um.. what? That's about terminology for one of the fields in this
thing, not about the name for the thing itself.
> Or, IVE (Interrupt Vector Entry) ? which makes some sense.
> This is was the former name in HW. I think we recycle it for KVM.
That's a terrible idea, which will make a confusing situation even
more confusing.
--
David Gibson | I'll have my music baroque, and my code
david AT gibson.dropbear.id.au | minimalist, thank you. NOT _the_ _other_
| _way_ _around_!
http://www.ozlabs.org/~dgibson
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]
^ permalink raw reply
* Re: [PATCH 05/19] KVM: PPC: Book3S HV: add a new KVM device for the XIVE native exploitation mode
From: David Gibson @ 2019-02-05 5:26 UTC (permalink / raw)
To: Cédric Le Goater; +Cc: kvm, kvm-ppc, Paul Mackerras, linuxppc-dev
In-Reply-To: <a4355ddf-462e-57d0-c225-7cd7d02a5482@kaod.org>
[-- Attachment #1: Type: text/plain, Size: 19688 bytes --]
On Mon, Feb 04, 2019 at 12:19:07PM +0100, Cédric Le Goater wrote:
> On 2/4/19 5:25 AM, David Gibson wrote:
> > On Mon, Jan 07, 2019 at 07:43:17PM +0100, Cédric Le Goater wrote:
> >> This is the basic framework for the new KVM device supporting the XIVE
> >> native exploitation mode. The user interface exposes a new capability
> >> and a new KVM device to be used by QEMU.
> >>
> >> Internally, the interface to the new KVM device is protected with a
> >> new interrupt mode: KVMPPC_IRQ_XIVE.
> >>
> >> Signed-off-by: Cédric Le Goater <clg@kaod.org>
> >> ---
> >> arch/powerpc/include/asm/kvm_host.h | 2 +
> >> arch/powerpc/include/asm/kvm_ppc.h | 21 ++
> >> arch/powerpc/kvm/book3s_xive.h | 3 +
> >> include/uapi/linux/kvm.h | 3 +
> >> arch/powerpc/kvm/book3s.c | 7 +-
> >> arch/powerpc/kvm/book3s_xive_native.c | 332 ++++++++++++++++++++++++++
> >> arch/powerpc/kvm/powerpc.c | 30 +++
> >> arch/powerpc/kvm/Makefile | 2 +-
> >> 8 files changed, 398 insertions(+), 2 deletions(-)
> >> create mode 100644 arch/powerpc/kvm/book3s_xive_native.c
> >>
> >> diff --git a/arch/powerpc/include/asm/kvm_host.h b/arch/powerpc/include/asm/kvm_host.h
> >> index 0f98f00da2ea..c522e8274ad9 100644
> >> --- a/arch/powerpc/include/asm/kvm_host.h
> >> +++ b/arch/powerpc/include/asm/kvm_host.h
> >> @@ -220,6 +220,7 @@ extern struct kvm_device_ops kvm_xics_ops;
> >> struct kvmppc_xive;
> >> struct kvmppc_xive_vcpu;
> >> extern struct kvm_device_ops kvm_xive_ops;
> >> +extern struct kvm_device_ops kvm_xive_native_ops;
> >>
> >> struct kvmppc_passthru_irqmap;
> >>
> >> @@ -446,6 +447,7 @@ struct kvmppc_passthru_irqmap {
> >> #define KVMPPC_IRQ_DEFAULT 0
> >> #define KVMPPC_IRQ_MPIC 1
> >> #define KVMPPC_IRQ_XICS 2 /* Includes a XIVE option */
> >> +#define KVMPPC_IRQ_XIVE 3 /* XIVE native exploitation mode */
> >>
> >> #define MMIO_HPTE_CACHE_SIZE 4
> >>
> >> diff --git a/arch/powerpc/include/asm/kvm_ppc.h b/arch/powerpc/include/asm/kvm_ppc.h
> >> index eb0d79f0ca45..1bb313f238fe 100644
> >> --- a/arch/powerpc/include/asm/kvm_ppc.h
> >> +++ b/arch/powerpc/include/asm/kvm_ppc.h
> >> @@ -591,6 +591,18 @@ extern int kvmppc_xive_set_icp(struct kvm_vcpu *vcpu, u64 icpval);
> >> extern int kvmppc_xive_set_irq(struct kvm *kvm, int irq_source_id, u32 irq,
> >> int level, bool line_status);
> >> extern void kvmppc_xive_push_vcpu(struct kvm_vcpu *vcpu);
> >> +
> >> +static inline int kvmppc_xive_enabled(struct kvm_vcpu *vcpu)
> >> +{
> >> + return vcpu->arch.irq_type == KVMPPC_IRQ_XIVE;
> >> +}
> >> +
> >> +extern int kvmppc_xive_native_connect_vcpu(struct kvm_device *dev,
> >> + struct kvm_vcpu *vcpu, u32 cpu);
> >> +extern void kvmppc_xive_native_cleanup_vcpu(struct kvm_vcpu *vcpu);
> >> +extern void kvmppc_xive_native_init_module(void);
> >> +extern void kvmppc_xive_native_exit_module(void);
> >> +
> >> #else
> >> static inline int kvmppc_xive_set_xive(struct kvm *kvm, u32 irq, u32 server,
> >> u32 priority) { return -1; }
> >> @@ -614,6 +626,15 @@ static inline int kvmppc_xive_set_icp(struct kvm_vcpu *vcpu, u64 icpval) { retur
> >> static inline int kvmppc_xive_set_irq(struct kvm *kvm, int irq_source_id, u32 irq,
> >> int level, bool line_status) { return -ENODEV; }
> >> static inline void kvmppc_xive_push_vcpu(struct kvm_vcpu *vcpu) { }
> >> +
> >> +static inline int kvmppc_xive_enabled(struct kvm_vcpu *vcpu)
> >> + { return 0; }
> >> +static inline int kvmppc_xive_native_connect_vcpu(struct kvm_device *dev,
> >> + struct kvm_vcpu *vcpu, u32 cpu) { return -EBUSY; }
> >> +static inline void kvmppc_xive_native_cleanup_vcpu(struct kvm_vcpu *vcpu) { }
> >> +static inline void kvmppc_xive_native_init_module(void) { }
> >> +static inline void kvmppc_xive_native_exit_module(void) { }
> >> +
> >> #endif /* CONFIG_KVM_XIVE */
> >>
> >> /*
> >> diff --git a/arch/powerpc/kvm/book3s_xive.h b/arch/powerpc/kvm/book3s_xive.h
> >> index 10c4aa5cd010..5f22415520b4 100644
> >> --- a/arch/powerpc/kvm/book3s_xive.h
> >> +++ b/arch/powerpc/kvm/book3s_xive.h
> >> @@ -12,6 +12,9 @@
> >> #ifdef CONFIG_KVM_XICS
> >> #include "book3s_xics.h"
> >>
> >> +#define KVMPPC_XIVE_FIRST_IRQ 0
> >> +#define KVMPPC_XIVE_NR_IRQS KVMPPC_XICS_NR_IRQS
> >> +
> >> /*
> >> * State for one guest irq source.
> >> *
> >> diff --git a/include/uapi/linux/kvm.h b/include/uapi/linux/kvm.h
> >> index 6d4ea4b6c922..52bf74a1616e 100644
> >> --- a/include/uapi/linux/kvm.h
> >> +++ b/include/uapi/linux/kvm.h
> >> @@ -988,6 +988,7 @@ struct kvm_ppc_resize_hpt {
> >> #define KVM_CAP_ARM_VM_IPA_SIZE 165
> >> #define KVM_CAP_MANUAL_DIRTY_LOG_PROTECT 166
> >> #define KVM_CAP_HYPERV_CPUID 167
> >> +#define KVM_CAP_PPC_IRQ_XIVE 168
> >>
> >> #ifdef KVM_CAP_IRQ_ROUTING
> >>
> >> @@ -1211,6 +1212,8 @@ enum kvm_device_type {
> >> #define KVM_DEV_TYPE_ARM_VGIC_V3 KVM_DEV_TYPE_ARM_VGIC_V3
> >> KVM_DEV_TYPE_ARM_VGIC_ITS,
> >> #define KVM_DEV_TYPE_ARM_VGIC_ITS KVM_DEV_TYPE_ARM_VGIC_ITS
> >> + KVM_DEV_TYPE_XIVE,
> >> +#define KVM_DEV_TYPE_XIVE KVM_DEV_TYPE_XIVE
> >> KVM_DEV_TYPE_MAX,
> >> };
> >>
> >> diff --git a/arch/powerpc/kvm/book3s.c b/arch/powerpc/kvm/book3s.c
> >> index bd1a677dd9e4..de7eed191107 100644
> >> --- a/arch/powerpc/kvm/book3s.c
> >> +++ b/arch/powerpc/kvm/book3s.c
> >> @@ -1039,7 +1039,10 @@ static int kvmppc_book3s_init(void)
> >> #ifdef CONFIG_KVM_XIVE
> >> if (xive_enabled()) {
> >> kvmppc_xive_init_module();
> >> + kvmppc_xive_native_init_module();
> >> kvm_register_device_ops(&kvm_xive_ops, KVM_DEV_TYPE_XICS);
> >> + kvm_register_device_ops(&kvm_xive_native_ops,
> >> + KVM_DEV_TYPE_XIVE);
> >> } else
> >> #endif
> >> kvm_register_device_ops(&kvm_xics_ops, KVM_DEV_TYPE_XICS);
> >> @@ -1050,8 +1053,10 @@ static int kvmppc_book3s_init(void)
> >> static void kvmppc_book3s_exit(void)
> >> {
> >> #ifdef CONFIG_KVM_XICS
> >> - if (xive_enabled())
> >> + if (xive_enabled()) {
> >> kvmppc_xive_exit_module();
> >> + kvmppc_xive_native_exit_module();
> >> + }
> >> #endif
> >> #ifdef CONFIG_KVM_BOOK3S_32_HANDLER
> >> kvmppc_book3s_exit_pr();
> >> diff --git a/arch/powerpc/kvm/book3s_xive_native.c b/arch/powerpc/kvm/book3s_xive_native.c
> >> new file mode 100644
> >> index 000000000000..115143e76c45
> >> --- /dev/null
> >> +++ b/arch/powerpc/kvm/book3s_xive_native.c
> >> @@ -0,0 +1,332 @@
> >> +// SPDX-License-Identifier: GPL-2.0
> >> +/*
> >> + * Copyright (c) 2017-2019, IBM Corporation.
> >> + */
> >> +
> >> +#define pr_fmt(fmt) "xive-kvm: " fmt
> >> +
> >> +#include <linux/anon_inodes.h>
> >> +#include <linux/kernel.h>
> >> +#include <linux/kvm_host.h>
> >> +#include <linux/err.h>
> >> +#include <linux/gfp.h>
> >> +#include <linux/spinlock.h>
> >> +#include <linux/delay.h>
> >> +#include <linux/percpu.h>
> >> +#include <linux/cpumask.h>
> >> +#include <asm/uaccess.h>
> >> +#include <asm/kvm_book3s.h>
> >> +#include <asm/kvm_ppc.h>
> >> +#include <asm/hvcall.h>
> >> +#include <asm/xics.h>
> >> +#include <asm/xive.h>
> >> +#include <asm/xive-regs.h>
> >> +#include <asm/debug.h>
> >> +#include <asm/debugfs.h>
> >> +#include <asm/time.h>
> >> +#include <asm/opal.h>
> >> +
> >> +#include <linux/debugfs.h>
> >> +#include <linux/seq_file.h>
> >> +
> >> +#include "book3s_xive.h"
> >> +
> >> +static void xive_native_cleanup_queue(struct kvm_vcpu *vcpu, int prio)
> >> +{
> >> + struct kvmppc_xive_vcpu *xc = vcpu->arch.xive_vcpu;
> >> + struct xive_q *q = &xc->queues[prio];
> >> +
> >> + xive_native_disable_queue(xc->vp_id, q, prio);
> >> + if (q->qpage) {
> >> + put_page(virt_to_page(q->qpage));
> >> + q->qpage = NULL;
> >> + }
> >> +}
> >> +
> >> +void kvmppc_xive_native_cleanup_vcpu(struct kvm_vcpu *vcpu)
> >> +{
> >> + struct kvmppc_xive_vcpu *xc = vcpu->arch.xive_vcpu;
> >> + int i;
> >> +
> >> + if (!kvmppc_xive_enabled(vcpu))
> >> + return;
> >> +
> >> + if (!xc)
> >> + return;
> >> +
> >> + pr_devel("native_cleanup_vcpu(cpu=%d)\n", xc->server_num);
> >> +
> >> + /* Ensure no interrupt is still routed to that VP */
> >> + xc->valid = false;
> >> + kvmppc_xive_disable_vcpu_interrupts(vcpu);
> >> +
> >> + /* Disable the VP */
> >> + xive_native_disable_vp(xc->vp_id);
> >> +
> >> + /* Free the queues & associated interrupts */
> >> + for (i = 0; i < KVMPPC_XIVE_Q_COUNT; i++) {
> >> + /* Free the escalation irq */
> >> + if (xc->esc_virq[i]) {
> >> + free_irq(xc->esc_virq[i], vcpu);
> >> + irq_dispose_mapping(xc->esc_virq[i]);
> >> + kfree(xc->esc_virq_names[i]);
> >> + xc->esc_virq[i] = 0;
> >> + }
> >> +
> >> + /* Free the queue */
> >> + xive_native_cleanup_queue(vcpu, i);
> >> + }
> >> +
> >> + /* Free the VP */
> >> + kfree(xc);
> >> +
> >> + /* Cleanup the vcpu */
> >> + vcpu->arch.irq_type = KVMPPC_IRQ_DEFAULT;
> >> + vcpu->arch.xive_vcpu = NULL;
> >> +}
> >> +
> >> +int kvmppc_xive_native_connect_vcpu(struct kvm_device *dev,
> >> + struct kvm_vcpu *vcpu, u32 cpu)
> >
> > Why do we need both a *vcpu and a cpu number as an integer?
>
> To be in sync with the other similar routines : kvmppc_xics_connect_vcpu()
> and kvmppc_xive_connect_vcpu().
>
> But if we consider that this 'cpu' parameter is always in sync with
> vcpu->vcpu_id, we could remove it from the KVM ioctl call I suppose.
>
> Should we do the same for the other routines ?
Well.. I don't know why they are that way. Is that int parameter the
XICS server number, which need not be the same as the vcpu_id ? Can
we set that arbitrarily in XIVE as well?
It looks like these parameters need a name change at least to make it
clearer what the distinction is.
> >> +{
> >> + struct kvmppc_xive *xive = dev->private;
> >> + struct kvmppc_xive_vcpu *xc;
> >> + int rc;
> >> +
> >> + pr_devel("native_connect_vcpu(cpu=%d)\n", cpu);
> >> +
> >> + if (dev->ops != &kvm_xive_native_ops) {
> >> + pr_devel("Wrong ops !\n");
> >> + return -EPERM;
> >> + }
> >> + if (xive->kvm != vcpu->kvm)
> >> + return -EPERM;
> >> + if (vcpu->arch.irq_type)
> >
> > Please use an explicit == / != here so we don't have to remember which
> > symbolic value corresponds to 0.
>
> ok. I agree.
>
> Thanks,
>
> C.
>
>
> >
> >> + return -EBUSY;
> >> + if (kvmppc_xive_find_server(vcpu->kvm, cpu)) {
> >> + pr_devel("Duplicate !\n");
> >> + return -EEXIST;
> >> + }
> >> + if (cpu >= KVM_MAX_VCPUS) {
> >> + pr_devel("Out of bounds !\n");
> >> + return -EINVAL;
> >> + }
> >> + xc = kzalloc(sizeof(*xc), GFP_KERNEL);
> >> + if (!xc)
> >> + return -ENOMEM;
> >> +
> >> + mutex_lock(&vcpu->kvm->lock);
> >> + vcpu->arch.xive_vcpu = xc;
> >> + xc->xive = xive;
> >> + xc->vcpu = vcpu;
> >> + xc->server_num = cpu;
> >> + xc->vp_id = xive->vp_base + cpu;
> >> + xc->valid = true;
> >> +
> >> + rc = xive_native_get_vp_info(xc->vp_id, &xc->vp_cam, &xc->vp_chip_id);
> >> + if (rc) {
> >> + pr_err("Failed to get VP info from OPAL: %d\n", rc);
> >> + goto bail;
> >> + }
> >> +
> >> + /*
> >> + * Enable the VP first as the single escalation mode will
> >> + * affect escalation interrupts numbering
> >> + */
> >> + rc = xive_native_enable_vp(xc->vp_id, xive->single_escalation);
> >> + if (rc) {
> >> + pr_err("Failed to enable VP in OPAL: %d\n", rc);
> >> + goto bail;
> >> + }
> >> +
> >> + /* Configure VCPU fields for use by assembly push/pull */
> >> + vcpu->arch.xive_saved_state.w01 = cpu_to_be64(0xff000000);
> >> + vcpu->arch.xive_cam_word = cpu_to_be32(xc->vp_cam | TM_QW1W2_VO);
> >> +
> >> + /* TODO: initialize queues ? */
> >> +
> >> +bail:
> >> + vcpu->arch.irq_type = KVMPPC_IRQ_XIVE;
> >> + mutex_unlock(&vcpu->kvm->lock);
> >> + if (rc)
> >> + kvmppc_xive_native_cleanup_vcpu(vcpu);
> >> +
> >> + return rc;
> >> +}
> >> +
> >> +static int kvmppc_xive_native_set_attr(struct kvm_device *dev,
> >> + struct kvm_device_attr *attr)
> >> +{
> >> + return -ENXIO;
> >> +}
> >> +
> >> +static int kvmppc_xive_native_get_attr(struct kvm_device *dev,
> >> + struct kvm_device_attr *attr)
> >> +{
> >> + return -ENXIO;
> >> +}
> >> +
> >> +static int kvmppc_xive_native_has_attr(struct kvm_device *dev,
> >> + struct kvm_device_attr *attr)
> >> +{
> >> + return -ENXIO;
> >> +}
> >> +
> >> +static void kvmppc_xive_native_free(struct kvm_device *dev)
> >> +{
> >> + struct kvmppc_xive *xive = dev->private;
> >> + struct kvm *kvm = xive->kvm;
> >> + int i;
> >> +
> >> + debugfs_remove(xive->dentry);
> >> +
> >> + pr_devel("Destroying xive native for partition\n");
> >> +
> >> + if (kvm)
> >> + kvm->arch.xive = NULL;
> >> +
> >> + /* Mask and free interrupts */
> >> + for (i = 0; i <= xive->max_sbid; i++) {
> >> + if (xive->src_blocks[i])
> >> + kvmppc_xive_free_sources(xive->src_blocks[i]);
> >> + kfree(xive->src_blocks[i]);
> >> + xive->src_blocks[i] = NULL;
> >> + }
> >> +
> >> + if (xive->vp_base != XIVE_INVALID_VP)
> >> + xive_native_free_vp_block(xive->vp_base);
> >> +
> >> + kfree(xive);
> >> + kfree(dev);
> >> +}
> >> +
> >> +static int kvmppc_xive_native_create(struct kvm_device *dev, u32 type)
> >> +{
> >> + struct kvmppc_xive *xive;
> >> + struct kvm *kvm = dev->kvm;
> >> + int ret = 0;
> >> +
> >> + pr_devel("Creating xive native for partition\n");
> >> +
> >> + if (kvm->arch.xive)
> >> + return -EEXIST;
> >> +
> >> + xive = kzalloc(sizeof(*xive), GFP_KERNEL);
> >> + if (!xive)
> >> + return -ENOMEM;
> >> +
> >> + dev->private = xive;
> >> + xive->dev = dev;
> >> + xive->kvm = kvm;
> >> + kvm->arch.xive = xive;
> >> +
> >> + /* We use the default queue size set by the host */
> >> + xive->q_order = xive_native_default_eq_shift();
> >> + if (xive->q_order < PAGE_SHIFT)
> >> + xive->q_page_order = 0;
> >> + else
> >> + xive->q_page_order = xive->q_order - PAGE_SHIFT;
> >> +
> >> + /* Allocate a bunch of VPs */
> >> + xive->vp_base = xive_native_alloc_vp_block(KVM_MAX_VCPUS);
> >> + pr_devel("VP_Base=%x\n", xive->vp_base);
> >> +
> >> + if (xive->vp_base == XIVE_INVALID_VP)
> >> + ret = -ENOMEM;
> >> +
> >> + xive->single_escalation = xive_native_has_single_escalation();
> >> +
> >> + if (ret)
> >> + kfree(xive);
> >> +
> >> + return ret;
> >> +}
> >> +
> >> +static int xive_native_debug_show(struct seq_file *m, void *private)
> >> +{
> >> + struct kvmppc_xive *xive = m->private;
> >> + struct kvm *kvm = xive->kvm;
> >> + struct kvm_vcpu *vcpu;
> >> + unsigned int i;
> >> +
> >> + if (!kvm)
> >> + return 0;
> >> +
> >> + seq_puts(m, "=========\nVCPU state\n=========\n");
> >> +
> >> + kvm_for_each_vcpu(i, vcpu, kvm) {
> >> + struct kvmppc_xive_vcpu *xc = vcpu->arch.xive_vcpu;
> >> +
> >> + if (!xc)
> >> + continue;
> >> +
> >> + seq_printf(m, "cpu server %#x NSR=%02x CPPR=%02x IBP=%02x PIPR=%02x w01=%016llx w2=%08x\n",
> >> + xc->server_num,
> >> + vcpu->arch.xive_saved_state.nsr,
> >> + vcpu->arch.xive_saved_state.cppr,
> >> + vcpu->arch.xive_saved_state.ipb,
> >> + vcpu->arch.xive_saved_state.pipr,
> >> + vcpu->arch.xive_saved_state.w01,
> >> + (u32) vcpu->arch.xive_cam_word);
> >> +
> >> + kvmppc_xive_debug_show_queues(m, vcpu);
> >> + }
> >> +
> >> + return 0;
> >> +}
> >> +
> >> +static int xive_native_debug_open(struct inode *inode, struct file *file)
> >> +{
> >> + return single_open(file, xive_native_debug_show, inode->i_private);
> >> +}
> >> +
> >> +static const struct file_operations xive_native_debug_fops = {
> >> + .open = xive_native_debug_open,
> >> + .read = seq_read,
> >> + .llseek = seq_lseek,
> >> + .release = single_release,
> >> +};
> >> +
> >> +static void xive_native_debugfs_init(struct kvmppc_xive *xive)
> >> +{
> >> + char *name;
> >> +
> >> + name = kasprintf(GFP_KERNEL, "kvm-xive-%p", xive);
> >> + if (!name) {
> >> + pr_err("%s: no memory for name\n", __func__);
> >> + return;
> >> + }
> >> +
> >> + xive->dentry = debugfs_create_file(name, 0444, powerpc_debugfs_root,
> >> + xive, &xive_native_debug_fops);
> >> +
> >> + pr_debug("%s: created %s\n", __func__, name);
> >> + kfree(name);
> >> +}
> >> +
> >> +static void kvmppc_xive_native_init(struct kvm_device *dev)
> >> +{
> >> + struct kvmppc_xive *xive = (struct kvmppc_xive *)dev->private;
> >> +
> >> + /* Register some debug interfaces */
> >> + xive_native_debugfs_init(xive);
> >> +}
> >> +
> >> +struct kvm_device_ops kvm_xive_native_ops = {
> >> + .name = "kvm-xive-native",
> >> + .create = kvmppc_xive_native_create,
> >> + .init = kvmppc_xive_native_init,
> >> + .destroy = kvmppc_xive_native_free,
> >> + .set_attr = kvmppc_xive_native_set_attr,
> >> + .get_attr = kvmppc_xive_native_get_attr,
> >> + .has_attr = kvmppc_xive_native_has_attr,
> >> +};
> >> +
> >> +void kvmppc_xive_native_init_module(void)
> >> +{
> >> + ;
> >> +}
> >> +
> >> +void kvmppc_xive_native_exit_module(void)
> >> +{
> >> + ;
> >> +}
> >> diff --git a/arch/powerpc/kvm/powerpc.c b/arch/powerpc/kvm/powerpc.c
> >> index b90a7d154180..01d526e15e9d 100644
> >> --- a/arch/powerpc/kvm/powerpc.c
> >> +++ b/arch/powerpc/kvm/powerpc.c
> >> @@ -566,6 +566,9 @@ int kvm_vm_ioctl_check_extension(struct kvm *kvm, long ext)
> >> case KVM_CAP_PPC_ENABLE_HCALL:
> >> #ifdef CONFIG_KVM_XICS
> >> case KVM_CAP_IRQ_XICS:
> >> +#endif
> >> +#ifdef CONFIG_KVM_XIVE
> >> + case KVM_CAP_PPC_IRQ_XIVE:
> >> #endif
> >> case KVM_CAP_PPC_GET_CPU_CHAR:
> >> r = 1;
> >> @@ -753,6 +756,9 @@ void kvm_arch_vcpu_free(struct kvm_vcpu *vcpu)
> >> else
> >> kvmppc_xics_free_icp(vcpu);
> >> break;
> >> + case KVMPPC_IRQ_XIVE:
> >> + kvmppc_xive_native_cleanup_vcpu(vcpu);
> >> + break;
> >> }
> >>
> >> kvmppc_core_vcpu_free(vcpu);
> >> @@ -1941,6 +1947,30 @@ static int kvm_vcpu_ioctl_enable_cap(struct kvm_vcpu *vcpu,
> >> break;
> >> }
> >> #endif /* CONFIG_KVM_XICS */
> >> +#ifdef CONFIG_KVM_XIVE
> >> + case KVM_CAP_PPC_IRQ_XIVE: {
> >> + struct fd f;
> >> + struct kvm_device *dev;
> >> +
> >> + r = -EBADF;
> >> + f = fdget(cap->args[0]);
> >> + if (!f.file)
> >> + break;
> >> +
> >> + r = -ENXIO;
> >> + if (!xive_enabled())
> >> + break;
> >> +
> >> + r = -EPERM;
> >> + dev = kvm_device_from_filp(f.file);
> >> + if (dev)
> >> + r = kvmppc_xive_native_connect_vcpu(dev, vcpu,
> >> + cap->args[1]);
> >> +
> >> + fdput(f);
> >> + break;
> >> + }
> >> +#endif /* CONFIG_KVM_XIVE */
> >> #ifdef CONFIG_KVM_BOOK3S_HV_POSSIBLE
> >> case KVM_CAP_PPC_FWNMI:
> >> r = -EINVAL;
> >> diff --git a/arch/powerpc/kvm/Makefile b/arch/powerpc/kvm/Makefile
> >> index 64f1135e7732..806cbe488410 100644
> >> --- a/arch/powerpc/kvm/Makefile
> >> +++ b/arch/powerpc/kvm/Makefile
> >> @@ -99,7 +99,7 @@ endif
> >> kvm-book3s_64-objs-$(CONFIG_KVM_XICS) += \
> >> book3s_xics.o
> >>
> >> -kvm-book3s_64-objs-$(CONFIG_KVM_XIVE) += book3s_xive.o
> >> +kvm-book3s_64-objs-$(CONFIG_KVM_XIVE) += book3s_xive.o book3s_xive_native.o
> >> kvm-book3s_64-objs-$(CONFIG_SPAPR_TCE_IOMMU) += book3s_64_vio.o
> >>
> >> kvm-book3s_64-module-objs := \
> >
>
--
David Gibson | I'll have my music baroque, and my code
david AT gibson.dropbear.id.au | minimalist, thank you. NOT _the_ _other_
| _way_ _around_!
http://www.ozlabs.org/~dgibson
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]
^ 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