Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 5d31a96e authored by Michael Ellerman's avatar Michael Ellerman
Browse files

powerpc/livepatch: Add livepatch stack to struct thread_info



In order to support live patching we need to maintain an alternate
stack of TOC & LR values. We use the base of the stack for this, and
store the "live patch stack pointer" in struct thread_info.

Unlike the other fields of thread_info, we can not statically initialise
that value, so it must be done at run time.

This patch just adds the code to support that, it is not enabled until
the next patch which actually adds live patch support.

Signed-off-by: default avatarMichael Ellerman <mpe@ellerman.id.au>
Acked-by: default avatarBalbir Singh <bsingharora@gmail.com>
parent f63e6d89
Loading
Loading
Loading
Loading
+8 −0
Original line number Original line Diff line number Diff line
@@ -49,6 +49,14 @@ static inline unsigned long klp_get_ftrace_location(unsigned long faddr)
	 */
	 */
	return ftrace_location_range(faddr, faddr + 16);
	return ftrace_location_range(faddr, faddr + 16);
}
}

static inline void klp_init_thread_info(struct thread_info *ti)
{
	/* + 1 to account for STACK_END_MAGIC */
	ti->livepatch_sp = (unsigned long *)(ti + 1) + 1;
}
#else
static void klp_init_thread_info(struct thread_info *ti) { }
#endif /* CONFIG_LIVEPATCH */
#endif /* CONFIG_LIVEPATCH */


#endif /* _ASM_POWERPC_LIVEPATCH_H */
#endif /* _ASM_POWERPC_LIVEPATCH_H */
+3 −1
Original line number Original line Diff line number Diff line
@@ -43,7 +43,9 @@ struct thread_info {
	int		preempt_count;		/* 0 => preemptable,
	int		preempt_count;		/* 0 => preemptable,
						   <0 => BUG */
						   <0 => BUG */
	unsigned long	local_flags;		/* private flags for thread */
	unsigned long	local_flags;		/* private flags for thread */

#ifdef CONFIG_LIVEPATCH
	unsigned long *livepatch_sp;
#endif
	/* low level flags - has atomic operations done on it */
	/* low level flags - has atomic operations done on it */
	unsigned long	flags ____cacheline_aligned_in_smp;
	unsigned long	flags ____cacheline_aligned_in_smp;
};
};
+3 −0
Original line number Original line Diff line number Diff line
@@ -66,6 +66,7 @@
#include <asm/udbg.h>
#include <asm/udbg.h>
#include <asm/smp.h>
#include <asm/smp.h>
#include <asm/debug.h>
#include <asm/debug.h>
#include <asm/livepatch.h>


#ifdef CONFIG_PPC64
#ifdef CONFIG_PPC64
#include <asm/paca.h>
#include <asm/paca.h>
@@ -607,10 +608,12 @@ void irq_ctx_init(void)
		memset((void *)softirq_ctx[i], 0, THREAD_SIZE);
		memset((void *)softirq_ctx[i], 0, THREAD_SIZE);
		tp = softirq_ctx[i];
		tp = softirq_ctx[i];
		tp->cpu = i;
		tp->cpu = i;
		klp_init_thread_info(tp);


		memset((void *)hardirq_ctx[i], 0, THREAD_SIZE);
		memset((void *)hardirq_ctx[i], 0, THREAD_SIZE);
		tp = hardirq_ctx[i];
		tp = hardirq_ctx[i];
		tp->cpu = i;
		tp->cpu = i;
		klp_init_thread_info(tp);
	}
	}
}
}


+5 −1
Original line number Original line Diff line number Diff line
@@ -55,6 +55,8 @@
#include <asm/firmware.h>
#include <asm/firmware.h>
#endif
#endif
#include <asm/code-patching.h>
#include <asm/code-patching.h>
#include <asm/livepatch.h>

#include <linux/kprobes.h>
#include <linux/kprobes.h>
#include <linux/kdebug.h>
#include <linux/kdebug.h>


@@ -1267,13 +1269,15 @@ int copy_thread(unsigned long clone_flags, unsigned long usp,
	extern void ret_from_kernel_thread(void);
	extern void ret_from_kernel_thread(void);
	void (*f)(void);
	void (*f)(void);
	unsigned long sp = (unsigned long)task_stack_page(p) + THREAD_SIZE;
	unsigned long sp = (unsigned long)task_stack_page(p) + THREAD_SIZE;
	struct thread_info *ti = task_thread_info(p);

	klp_init_thread_info(ti);


	/* Copy registers */
	/* Copy registers */
	sp -= sizeof(struct pt_regs);
	sp -= sizeof(struct pt_regs);
	childregs = (struct pt_regs *) sp;
	childregs = (struct pt_regs *) sp;
	if (unlikely(p->flags & PF_KTHREAD)) {
	if (unlikely(p->flags & PF_KTHREAD)) {
		/* kernel thread */
		/* kernel thread */
		struct thread_info *ti = (void *)task_stack_page(p);
		memset(childregs, 0, sizeof(struct pt_regs));
		memset(childregs, 0, sizeof(struct pt_regs));
		childregs->gpr[1] = sp + sizeof(struct pt_regs);
		childregs->gpr[1] = sp + sizeof(struct pt_regs);
		/* function */
		/* function */
+10 −7
Original line number Original line Diff line number Diff line
@@ -69,6 +69,7 @@
#include <asm/kvm_ppc.h>
#include <asm/kvm_ppc.h>
#include <asm/hugetlb.h>
#include <asm/hugetlb.h>
#include <asm/epapr_hcalls.h>
#include <asm/epapr_hcalls.h>
#include <asm/livepatch.h>


#ifdef DEBUG
#ifdef DEBUG
#define DBG(fmt...) udbg_printf(fmt)
#define DBG(fmt...) udbg_printf(fmt)
@@ -670,16 +671,16 @@ static void __init emergency_stack_init(void)
	limit = min(safe_stack_limit(), ppc64_rma_size);
	limit = min(safe_stack_limit(), ppc64_rma_size);


	for_each_possible_cpu(i) {
	for_each_possible_cpu(i) {
		unsigned long sp;
		struct thread_info *ti;
		sp  = memblock_alloc_base(THREAD_SIZE, THREAD_SIZE, limit);
		ti = __va(memblock_alloc_base(THREAD_SIZE, THREAD_SIZE, limit));
		sp += THREAD_SIZE;
		klp_init_thread_info(ti);
		paca[i].emergency_sp = __va(sp);
		paca[i].emergency_sp = (void *)ti + THREAD_SIZE;


#ifdef CONFIG_PPC_BOOK3S_64
#ifdef CONFIG_PPC_BOOK3S_64
		/* emergency stack for machine check exception handling. */
		/* emergency stack for machine check exception handling. */
		sp  = memblock_alloc_base(THREAD_SIZE, THREAD_SIZE, limit);
		ti = __va(memblock_alloc_base(THREAD_SIZE, THREAD_SIZE, limit));
		sp += THREAD_SIZE;
		klp_init_thread_info(ti);
		paca[i].mc_emergency_sp = __va(sp);
		paca[i].mc_emergency_sp = (void *)ti + THREAD_SIZE;
#endif
#endif
	}
	}
}
}
@@ -703,6 +704,8 @@ void __init setup_arch(char **cmdline_p)
	if (ppc_md.panic)
	if (ppc_md.panic)
		setup_panic();
		setup_panic();


	klp_init_thread_info(&init_thread_info);

	init_mm.start_code = (unsigned long)_stext;
	init_mm.start_code = (unsigned long)_stext;
	init_mm.end_code = (unsigned long) _etext;
	init_mm.end_code = (unsigned long) _etext;
	init_mm.end_data = (unsigned long) _edata;
	init_mm.end_data = (unsigned long) _edata;