Merge remote-tracking branch 'anton/abiv2' into next
This series adds support for building the powerpc 64-bit LE kernel using the new ABI v2. We already supported running ABI v2 userspace programs but this adds support for building the kernel itself using the new ABI.hifive-unleashed-5.1
commit
f6869e7fe6
|
@ -113,8 +113,13 @@ else
|
|||
endif
|
||||
endif
|
||||
|
||||
CFLAGS-$(CONFIG_PPC64) := -mtraceback=no -mcall-aixdesc
|
||||
CFLAGS-$(CONFIG_PPC64) += $(call cc-option,-mabi=elfv1)
|
||||
CFLAGS-$(CONFIG_PPC64) := -mtraceback=no
|
||||
ifeq ($(CONFIG_CPU_LITTLE_ENDIAN),y)
|
||||
CFLAGS-$(CONFIG_PPC64) += $(call cc-option,-mabi=elfv2,-mcall-aixdesc)
|
||||
AFLAGS-$(CONFIG_PPC64) += $(call cc-option,-mabi=elfv2)
|
||||
else
|
||||
CFLAGS-$(CONFIG_PPC64) += -mcall-aixdesc
|
||||
endif
|
||||
CFLAGS-$(CONFIG_PPC64) += $(call cc-option,-mcmodel=medium,-mminimal-toc)
|
||||
CFLAGS-$(CONFIG_PPC64) += $(call cc-option,-mno-pointers-to-nested-functions)
|
||||
CFLAGS-$(CONFIG_PPC32) := -ffixed-r2 $(MULTIPLEWORD)
|
||||
|
@ -151,7 +156,7 @@ endif
|
|||
CFLAGS-$(CONFIG_TUNE_CELL) += $(call cc-option,-mtune=cell)
|
||||
|
||||
KBUILD_CPPFLAGS += -Iarch/$(ARCH)
|
||||
KBUILD_AFLAGS += -Iarch/$(ARCH)
|
||||
KBUILD_AFLAGS += -Iarch/$(ARCH) $(AFLAGS-y)
|
||||
KBUILD_CFLAGS += -msoft-float -pipe -Iarch/$(ARCH) $(CFLAGS-y)
|
||||
CPP = $(CC) -E $(KBUILD_CFLAGS)
|
||||
|
||||
|
|
|
@ -45,7 +45,7 @@ udelay:
|
|||
mfspr r4,SPRN_PVR
|
||||
srwi r4,r4,16
|
||||
cmpwi 0,r4,1 /* 601 ? */
|
||||
bne .udelay_not_601
|
||||
bne .Ludelay_not_601
|
||||
00: li r0,86 /* Instructions / microsecond? */
|
||||
mtctr r0
|
||||
10: addi r0,r0,0 /* NOP */
|
||||
|
@ -54,7 +54,7 @@ udelay:
|
|||
bne 00b
|
||||
blr
|
||||
|
||||
.udelay_not_601:
|
||||
.Ludelay_not_601:
|
||||
mulli r4,r3,1000 /* nanoseconds */
|
||||
/* Change r4 to be the number of ticks using:
|
||||
* (nanoseconds + (timebase_period_ns - 1 )) / timebase_period_ns
|
||||
|
|
|
@ -42,15 +42,47 @@ void __patch_exception(int exc, unsigned long addr);
|
|||
} while (0)
|
||||
#endif
|
||||
|
||||
#define OP_RT_RA_MASK 0xffff0000UL
|
||||
#define LIS_R2 0x3c020000UL
|
||||
#define ADDIS_R2_R12 0x3c4c0000UL
|
||||
#define ADDI_R2_R2 0x38420000UL
|
||||
|
||||
static inline unsigned long ppc_function_entry(void *func)
|
||||
{
|
||||
#ifdef CONFIG_PPC64
|
||||
#if defined(CONFIG_PPC64)
|
||||
#if defined(_CALL_ELF) && _CALL_ELF == 2
|
||||
u32 *insn = func;
|
||||
|
||||
/*
|
||||
* On PPC64 the function pointer actually points to the function's
|
||||
* descriptor. The first entry in the descriptor is the address
|
||||
* of the function text.
|
||||
* A PPC64 ABIv2 function may have a local and a global entry
|
||||
* point. We need to use the local entry point when patching
|
||||
* functions, so identify and step over the global entry point
|
||||
* sequence.
|
||||
*
|
||||
* The global entry point sequence is always of the form:
|
||||
*
|
||||
* addis r2,r12,XXXX
|
||||
* addi r2,r2,XXXX
|
||||
*
|
||||
* A linker optimisation may convert the addis to lis:
|
||||
*
|
||||
* lis r2,XXXX
|
||||
* addi r2,r2,XXXX
|
||||
*/
|
||||
if ((((*insn & OP_RT_RA_MASK) == ADDIS_R2_R12) ||
|
||||
((*insn & OP_RT_RA_MASK) == LIS_R2)) &&
|
||||
((*(insn+1) & OP_RT_RA_MASK) == ADDI_R2_R2))
|
||||
return (unsigned long)(insn + 2);
|
||||
else
|
||||
return (unsigned long)func;
|
||||
#else
|
||||
/*
|
||||
* On PPC64 ABIv1 the function pointer actually points to the
|
||||
* function's descriptor. The first entry in the descriptor is the
|
||||
* address of the function text.
|
||||
*/
|
||||
return ((func_descr_t *)func)->entry;
|
||||
#endif
|
||||
#else
|
||||
return (unsigned long)func;
|
||||
#endif
|
||||
|
|
|
@ -2,9 +2,9 @@
|
|||
#define _ASM_POWERPC_CONTEXT_TRACKING_H
|
||||
|
||||
#ifdef CONFIG_CONTEXT_TRACKING
|
||||
#define SCHEDULE_USER bl .schedule_user
|
||||
#define SCHEDULE_USER bl schedule_user
|
||||
#else
|
||||
#define SCHEDULE_USER bl .schedule
|
||||
#define SCHEDULE_USER bl schedule
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
|
|
@ -174,10 +174,10 @@ exc_##label##_book3e:
|
|||
mtlr r16;
|
||||
#define TLB_MISS_STATS_D(name) \
|
||||
addi r9,r13,MMSTAT_DSTATS+name; \
|
||||
bl .tlb_stat_inc;
|
||||
bl tlb_stat_inc;
|
||||
#define TLB_MISS_STATS_I(name) \
|
||||
addi r9,r13,MMSTAT_ISTATS+name; \
|
||||
bl .tlb_stat_inc;
|
||||
bl tlb_stat_inc;
|
||||
#define TLB_MISS_STATS_X(name) \
|
||||
ld r8,PACA_EXTLB+EX_TLB_ESR(r13); \
|
||||
cmpdi cr2,r8,-1; \
|
||||
|
@ -185,7 +185,7 @@ exc_##label##_book3e:
|
|||
addi r9,r13,MMSTAT_DSTATS+name; \
|
||||
b 62f; \
|
||||
61: addi r9,r13,MMSTAT_ISTATS+name; \
|
||||
62: bl .tlb_stat_inc;
|
||||
62: bl tlb_stat_inc;
|
||||
#define TLB_MISS_STATS_SAVE_INFO \
|
||||
std r14,EX_TLB_ESR(r12); /* save ESR */
|
||||
#define TLB_MISS_STATS_SAVE_INFO_BOLTED \
|
||||
|
|
|
@ -517,7 +517,7 @@ label##_relon_hv: \
|
|||
#define DISABLE_INTS RECONCILE_IRQ_STATE(r10,r11)
|
||||
|
||||
#define ADD_NVGPRS \
|
||||
bl .save_nvgprs
|
||||
bl save_nvgprs
|
||||
|
||||
#define RUNLATCH_ON \
|
||||
BEGIN_FTR_SECTION \
|
||||
|
|
|
@ -61,6 +61,7 @@ struct dyn_arch_ftrace {
|
|||
#endif
|
||||
|
||||
#if defined(CONFIG_FTRACE_SYSCALLS) && defined(CONFIG_PPC64) && !defined(__ASSEMBLY__)
|
||||
#if !defined(_CALL_ELF) || _CALL_ELF != 2
|
||||
#define ARCH_HAS_SYSCALL_MATCH_SYM_NAME
|
||||
static inline bool arch_syscall_match_sym_name(const char *sym, const char *name)
|
||||
{
|
||||
|
@ -72,6 +73,7 @@ static inline bool arch_syscall_match_sym_name(const char *sym, const char *name
|
|||
*/
|
||||
return !strcmp(sym + 4, name + 3);
|
||||
}
|
||||
#endif
|
||||
#endif /* CONFIG_FTRACE_SYSCALLS && CONFIG_PPC64 && !__ASSEMBLY__ */
|
||||
|
||||
#endif /* _ASM_POWERPC_FTRACE */
|
||||
|
|
|
@ -20,9 +20,9 @@
|
|||
*/
|
||||
#define TRACE_WITH_FRAME_BUFFER(func) \
|
||||
mflr r0; \
|
||||
stdu r1, -32(r1); \
|
||||
stdu r1, -STACK_FRAME_OVERHEAD(r1); \
|
||||
std r0, 16(r1); \
|
||||
stdu r1, -32(r1); \
|
||||
stdu r1, -STACK_FRAME_OVERHEAD(r1); \
|
||||
bl func; \
|
||||
ld r1, 0(r1); \
|
||||
ld r1, 0(r1);
|
||||
|
@ -36,8 +36,8 @@
|
|||
* have to call a C function so call a wrapper that saves all the
|
||||
* C-clobbered registers.
|
||||
*/
|
||||
#define TRACE_ENABLE_INTS TRACE_WITH_FRAME_BUFFER(.trace_hardirqs_on)
|
||||
#define TRACE_DISABLE_INTS TRACE_WITH_FRAME_BUFFER(.trace_hardirqs_off)
|
||||
#define TRACE_ENABLE_INTS TRACE_WITH_FRAME_BUFFER(trace_hardirqs_on)
|
||||
#define TRACE_DISABLE_INTS TRACE_WITH_FRAME_BUFFER(trace_hardirqs_off)
|
||||
|
||||
/*
|
||||
* This is used by assembly code to soft-disable interrupts first and
|
||||
|
|
|
@ -30,6 +30,7 @@
|
|||
#include <linux/ptrace.h>
|
||||
#include <linux/percpu.h>
|
||||
#include <asm/probes.h>
|
||||
#include <asm/code-patching.h>
|
||||
|
||||
#define __ARCH_WANT_KPROBES_INSN_SLOT
|
||||
|
||||
|
@ -56,9 +57,9 @@ typedef ppc_opcode_t kprobe_opcode_t;
|
|||
if ((colon = strchr(name, ':')) != NULL) { \
|
||||
colon++; \
|
||||
if (*colon != '\0' && *colon != '.') \
|
||||
addr = *(kprobe_opcode_t **)addr; \
|
||||
addr = (kprobe_opcode_t *)ppc_function_entry(addr); \
|
||||
} else if (name[0] != '.') \
|
||||
addr = *(kprobe_opcode_t **)addr; \
|
||||
addr = (kprobe_opcode_t *)ppc_function_entry(addr); \
|
||||
} else { \
|
||||
char dot_name[KSYM_NAME_LEN]; \
|
||||
dot_name[0] = '.'; \
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
#define _ASM_POWERPC_LINKAGE_H
|
||||
|
||||
#ifdef CONFIG_PPC64
|
||||
#if !defined(_CALL_ELF) || _CALL_ELF != 2
|
||||
#define cond_syscall(x) \
|
||||
asm ("\t.weak " #x "\n\t.set " #x ", sys_ni_syscall\n" \
|
||||
"\t.weak ." #x "\n\t.set ." #x ", .sys_ni_syscall\n")
|
||||
|
@ -9,5 +10,6 @@
|
|||
asm ("\t.globl " #alias "\n\t.set " #alias ", " #name "\n" \
|
||||
"\t.globl ." #alias "\n\t.set ." #alias ", ." #name)
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#endif /* _ASM_POWERPC_LINKAGE_H */
|
||||
|
|
|
@ -35,6 +35,7 @@ struct mod_arch_specific {
|
|||
#ifdef __powerpc64__
|
||||
unsigned int stubs_section; /* Index of stubs section in module */
|
||||
unsigned int toc_section; /* What section is the TOC? */
|
||||
bool toc_fixed; /* Have we fixed up .TOC.? */
|
||||
#ifdef CONFIG_DYNAMIC_FTRACE
|
||||
unsigned long toc;
|
||||
unsigned long tramp;
|
||||
|
@ -77,6 +78,9 @@ struct mod_arch_specific {
|
|||
# endif /* MODULE */
|
||||
#endif
|
||||
|
||||
bool is_module_trampoline(u32 *insns);
|
||||
int module_trampoline_target(struct module *mod, u32 *trampoline,
|
||||
unsigned long *target);
|
||||
|
||||
struct exception_table_entry;
|
||||
void sort_ex_table(struct exception_table_entry *start,
|
||||
|
|
|
@ -57,7 +57,7 @@ BEGIN_FW_FTR_SECTION; \
|
|||
LDX_BE r10,0,r10; /* get log write index */ \
|
||||
cmpd cr1,r11,r10; \
|
||||
beq+ cr1,33f; \
|
||||
bl .accumulate_stolen_time; \
|
||||
bl accumulate_stolen_time; \
|
||||
ld r12,_MSR(r1); \
|
||||
andi. r10,r12,MSR_PR; /* Restore cr0 (coming from user) */ \
|
||||
33: \
|
||||
|
@ -189,9 +189,45 @@ END_FW_FTR_SECTION_IFSET(FW_FEATURE_SPLPAR)
|
|||
#define __STK_REG(i) (112 + ((i)-14)*8)
|
||||
#define STK_REG(i) __STK_REG(__REG_##i)
|
||||
|
||||
#if defined(_CALL_ELF) && _CALL_ELF == 2
|
||||
#define STK_GOT 24
|
||||
#define __STK_PARAM(i) (32 + ((i)-3)*8)
|
||||
#else
|
||||
#define STK_GOT 40
|
||||
#define __STK_PARAM(i) (48 + ((i)-3)*8)
|
||||
#endif
|
||||
#define STK_PARAM(i) __STK_PARAM(__REG_##i)
|
||||
|
||||
#if defined(_CALL_ELF) && _CALL_ELF == 2
|
||||
|
||||
#define _GLOBAL(name) \
|
||||
.section ".text"; \
|
||||
.align 2 ; \
|
||||
.type name,@function; \
|
||||
.globl name; \
|
||||
name:
|
||||
|
||||
#define _GLOBAL_TOC(name) \
|
||||
.section ".text"; \
|
||||
.align 2 ; \
|
||||
.type name,@function; \
|
||||
.globl name; \
|
||||
name: \
|
||||
0: addis r2,r12,(.TOC.-0b)@ha; \
|
||||
addi r2,r2,(.TOC.-0b)@l; \
|
||||
.localentry name,.-name
|
||||
|
||||
#define _KPROBE(name) \
|
||||
.section ".kprobes.text","a"; \
|
||||
.align 2 ; \
|
||||
.type name,@function; \
|
||||
.globl name; \
|
||||
name:
|
||||
|
||||
#define DOTSYM(a) a
|
||||
|
||||
#else
|
||||
|
||||
#define XGLUE(a,b) a##b
|
||||
#define GLUE(a,b) XGLUE(a,b)
|
||||
|
||||
|
@ -209,19 +245,7 @@ name: \
|
|||
.type GLUE(.,name),@function; \
|
||||
GLUE(.,name):
|
||||
|
||||
#define _INIT_GLOBAL(name) \
|
||||
__REF; \
|
||||
.align 2 ; \
|
||||
.globl name; \
|
||||
.globl GLUE(.,name); \
|
||||
.section ".opd","aw"; \
|
||||
name: \
|
||||
.quad GLUE(.,name); \
|
||||
.quad .TOC.@tocbase; \
|
||||
.quad 0; \
|
||||
.previous; \
|
||||
.type GLUE(.,name),@function; \
|
||||
GLUE(.,name):
|
||||
#define _GLOBAL_TOC(name) _GLOBAL(name)
|
||||
|
||||
#define _KPROBE(name) \
|
||||
.section ".kprobes.text","a"; \
|
||||
|
@ -237,29 +261,9 @@ name: \
|
|||
.type GLUE(.,name),@function; \
|
||||
GLUE(.,name):
|
||||
|
||||
#define _STATIC(name) \
|
||||
.section ".text"; \
|
||||
.align 2 ; \
|
||||
.section ".opd","aw"; \
|
||||
name: \
|
||||
.quad GLUE(.,name); \
|
||||
.quad .TOC.@tocbase; \
|
||||
.quad 0; \
|
||||
.previous; \
|
||||
.type GLUE(.,name),@function; \
|
||||
GLUE(.,name):
|
||||
#define DOTSYM(a) GLUE(.,a)
|
||||
|
||||
#define _INIT_STATIC(name) \
|
||||
__REF; \
|
||||
.align 2 ; \
|
||||
.section ".opd","aw"; \
|
||||
name: \
|
||||
.quad GLUE(.,name); \
|
||||
.quad .TOC.@tocbase; \
|
||||
.quad 0; \
|
||||
.previous; \
|
||||
.type GLUE(.,name),@function; \
|
||||
GLUE(.,name):
|
||||
#endif
|
||||
|
||||
#else /* 32-bit */
|
||||
|
||||
|
|
|
@ -39,6 +39,7 @@ static inline int overlaps_kernel_text(unsigned long start, unsigned long end)
|
|||
(unsigned long)_stext < end;
|
||||
}
|
||||
|
||||
#if !defined(_CALL_ELF) || _CALL_ELF != 2
|
||||
#undef dereference_function_descriptor
|
||||
static inline void *dereference_function_descriptor(void *ptr)
|
||||
{
|
||||
|
@ -49,6 +50,7 @@ static inline void *dereference_function_descriptor(void *ptr)
|
|||
ptr = p;
|
||||
return ptr;
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
|
|
|
@ -62,7 +62,7 @@ COMPAT_SYS_SPU(fcntl)
|
|||
SYSCALL(ni_syscall)
|
||||
SYSCALL_SPU(setpgid)
|
||||
SYSCALL(ni_syscall)
|
||||
SYSX(sys_ni_syscall,sys_olduname, sys_olduname)
|
||||
SYSX(sys_ni_syscall,sys_olduname,sys_olduname)
|
||||
SYSCALL_SPU(umask)
|
||||
SYSCALL_SPU(chroot)
|
||||
COMPAT_SYS(ustat)
|
||||
|
@ -258,7 +258,7 @@ SYSCALL_SPU(tgkill)
|
|||
COMPAT_SYS_SPU(utimes)
|
||||
COMPAT_SYS_SPU(statfs64)
|
||||
COMPAT_SYS_SPU(fstatfs64)
|
||||
SYSX(sys_ni_syscall, ppc_fadvise64_64, ppc_fadvise64_64)
|
||||
SYSX(sys_ni_syscall,ppc_fadvise64_64,ppc_fadvise64_64)
|
||||
PPC_SYS_SPU(rtas)
|
||||
OLDSYS(debug_setcontext)
|
||||
SYSCALL(ni_syscall)
|
||||
|
@ -295,7 +295,7 @@ SYSCALL_SPU(mkdirat)
|
|||
SYSCALL_SPU(mknodat)
|
||||
SYSCALL_SPU(fchownat)
|
||||
COMPAT_SYS_SPU(futimesat)
|
||||
SYSX_SPU(sys_newfstatat, sys_fstatat64, sys_fstatat64)
|
||||
SYSX_SPU(sys_newfstatat,sys_fstatat64,sys_fstatat64)
|
||||
SYSCALL_SPU(unlinkat)
|
||||
SYSCALL_SPU(renameat)
|
||||
SYSCALL_SPU(linkat)
|
||||
|
|
|
@ -291,9 +291,17 @@ do { \
|
|||
#define R_PPC64_DTPREL16_HIGHERA 104 /* half16 (sym+add)@dtprel@highera */
|
||||
#define R_PPC64_DTPREL16_HIGHEST 105 /* half16 (sym+add)@dtprel@highest */
|
||||
#define R_PPC64_DTPREL16_HIGHESTA 106 /* half16 (sym+add)@dtprel@highesta */
|
||||
#define R_PPC64_TLSGD 107
|
||||
#define R_PPC64_TLSLD 108
|
||||
#define R_PPC64_TOCSAVE 109
|
||||
|
||||
#define R_PPC64_REL16 249
|
||||
#define R_PPC64_REL16_LO 250
|
||||
#define R_PPC64_REL16_HI 251
|
||||
#define R_PPC64_REL16_HA 252
|
||||
|
||||
/* Keep this the last entry. */
|
||||
#define R_PPC64_NUM 107
|
||||
#define R_PPC64_NUM 253
|
||||
|
||||
/* There's actually a third entry here, but it's unused */
|
||||
struct ppc64_opd_entry
|
||||
|
|
|
@ -94,12 +94,12 @@ _GLOBAL(setup_altivec_idle)
|
|||
_GLOBAL(__setup_cpu_e6500)
|
||||
mflr r6
|
||||
#ifdef CONFIG_PPC64
|
||||
bl .setup_altivec_ivors
|
||||
bl setup_altivec_ivors
|
||||
/* Touch IVOR42 only if the CPU supports E.HV category */
|
||||
mfspr r10,SPRN_MMUCFG
|
||||
rlwinm. r10,r10,0,MMUCFG_LPIDSIZE
|
||||
beq 1f
|
||||
bl .setup_lrat_ivor
|
||||
bl setup_lrat_ivor
|
||||
1:
|
||||
#endif
|
||||
bl setup_pw20_idle
|
||||
|
@ -164,15 +164,15 @@ _GLOBAL(__setup_cpu_e5500)
|
|||
#ifdef CONFIG_PPC_BOOK3E_64
|
||||
_GLOBAL(__restore_cpu_e6500)
|
||||
mflr r5
|
||||
bl .setup_altivec_ivors
|
||||
bl setup_altivec_ivors
|
||||
/* Touch IVOR42 only if the CPU supports E.HV category */
|
||||
mfspr r10,SPRN_MMUCFG
|
||||
rlwinm. r10,r10,0,MMUCFG_LPIDSIZE
|
||||
beq 1f
|
||||
bl .setup_lrat_ivor
|
||||
bl setup_lrat_ivor
|
||||
1:
|
||||
bl .setup_pw20_idle
|
||||
bl .setup_altivec_idle
|
||||
bl setup_pw20_idle
|
||||
bl setup_altivec_idle
|
||||
bl __restore_cpu_e5500
|
||||
mtlr r5
|
||||
blr
|
||||
|
@ -181,9 +181,9 @@ _GLOBAL(__restore_cpu_e5500)
|
|||
mflr r4
|
||||
bl __e500_icache_setup
|
||||
bl __e500_dcache_setup
|
||||
bl .__setup_base_ivors
|
||||
bl .setup_perfmon_ivor
|
||||
bl .setup_doorbell_ivors
|
||||
bl __setup_base_ivors
|
||||
bl setup_perfmon_ivor
|
||||
bl setup_doorbell_ivors
|
||||
/*
|
||||
* We only want to touch IVOR38-41 if we're running on hardware
|
||||
* that supports category E.HV. The architectural way to determine
|
||||
|
@ -192,7 +192,7 @@ _GLOBAL(__restore_cpu_e5500)
|
|||
mfspr r10,SPRN_MMUCFG
|
||||
rlwinm. r10,r10,0,MMUCFG_LPIDSIZE
|
||||
beq 1f
|
||||
bl .setup_ehv_ivors
|
||||
bl setup_ehv_ivors
|
||||
1:
|
||||
mtlr r4
|
||||
blr
|
||||
|
@ -201,9 +201,9 @@ _GLOBAL(__setup_cpu_e5500)
|
|||
mflr r5
|
||||
bl __e500_icache_setup
|
||||
bl __e500_dcache_setup
|
||||
bl .__setup_base_ivors
|
||||
bl .setup_perfmon_ivor
|
||||
bl .setup_doorbell_ivors
|
||||
bl __setup_base_ivors
|
||||
bl setup_perfmon_ivor
|
||||
bl setup_doorbell_ivors
|
||||
/*
|
||||
* We only want to touch IVOR38-41 if we're running on hardware
|
||||
* that supports category E.HV. The architectural way to determine
|
||||
|
@ -212,7 +212,7 @@ _GLOBAL(__setup_cpu_e5500)
|
|||
mfspr r10,SPRN_MMUCFG
|
||||
rlwinm. r10,r10,0,MMUCFG_LPIDSIZE
|
||||
beq 1f
|
||||
bl .setup_ehv_ivors
|
||||
bl setup_ehv_ivors
|
||||
b 2f
|
||||
1:
|
||||
ld r10,CPU_SPEC_FEATURES(r4)
|
||||
|
|
|
@ -39,8 +39,8 @@
|
|||
* System calls.
|
||||
*/
|
||||
.section ".toc","aw"
|
||||
.SYS_CALL_TABLE:
|
||||
.tc .sys_call_table[TC],.sys_call_table
|
||||
SYS_CALL_TABLE:
|
||||
.tc sys_call_table[TC],sys_call_table
|
||||
|
||||
/* This value is used to mark exception frames on the stack. */
|
||||
exception_marker:
|
||||
|
@ -106,7 +106,7 @@ BEGIN_FW_FTR_SECTION
|
|||
LDX_BE r10,0,r10 /* get log write index */
|
||||
cmpd cr1,r11,r10
|
||||
beq+ cr1,33f
|
||||
bl .accumulate_stolen_time
|
||||
bl accumulate_stolen_time
|
||||
REST_GPR(0,r1)
|
||||
REST_4GPRS(3,r1)
|
||||
REST_2GPRS(7,r1)
|
||||
|
@ -143,7 +143,7 @@ END_FW_FTR_SECTION_IFSET(FW_FEATURE_SPLPAR)
|
|||
std r10,SOFTE(r1)
|
||||
|
||||
#ifdef SHOW_SYSCALLS
|
||||
bl .do_show_syscall
|
||||
bl do_show_syscall
|
||||
REST_GPR(0,r1)
|
||||
REST_4GPRS(3,r1)
|
||||
REST_2GPRS(7,r1)
|
||||
|
@ -162,7 +162,7 @@ system_call: /* label this so stack traces look sane */
|
|||
* Need to vector to 32 Bit or default sys_call_table here,
|
||||
* based on caller's run-mode / personality.
|
||||
*/
|
||||
ld r11,.SYS_CALL_TABLE@toc(2)
|
||||
ld r11,SYS_CALL_TABLE@toc(2)
|
||||
andi. r10,r10,_TIF_32BIT
|
||||
beq 15f
|
||||
addi r11,r11,8 /* use 32-bit syscall entries */
|
||||
|
@ -174,14 +174,14 @@ system_call: /* label this so stack traces look sane */
|
|||
clrldi r8,r8,32
|
||||
15:
|
||||
slwi r0,r0,4
|
||||
ldx r10,r11,r0 /* Fetch system call handler [ptr] */
|
||||
mtctr r10
|
||||
ldx r12,r11,r0 /* Fetch system call handler [ptr] */
|
||||
mtctr r12
|
||||
bctrl /* Call handler */
|
||||
|
||||
syscall_exit:
|
||||
std r3,RESULT(r1)
|
||||
#ifdef SHOW_SYSCALLS
|
||||
bl .do_show_syscall_exit
|
||||
bl do_show_syscall_exit
|
||||
ld r3,RESULT(r1)
|
||||
#endif
|
||||
CURRENT_THREAD_INFO(r12, r1)
|
||||
|
@ -248,9 +248,9 @@ syscall_error:
|
|||
|
||||
/* Traced system call support */
|
||||
syscall_dotrace:
|
||||
bl .save_nvgprs
|
||||
bl save_nvgprs
|
||||
addi r3,r1,STACK_FRAME_OVERHEAD
|
||||
bl .do_syscall_trace_enter
|
||||
bl do_syscall_trace_enter
|
||||
/*
|
||||
* Restore argument registers possibly just changed.
|
||||
* We use the return value of do_syscall_trace_enter
|
||||
|
@ -308,7 +308,7 @@ syscall_exit_work:
|
|||
4: /* Anything else left to do? */
|
||||
SET_DEFAULT_THREAD_PPR(r3, r10) /* Set thread.ppr = 3 */
|
||||
andi. r0,r9,(_TIF_SYSCALL_T_OR_A|_TIF_SINGLESTEP)
|
||||
beq .ret_from_except_lite
|
||||
beq ret_from_except_lite
|
||||
|
||||
/* Re-enable interrupts */
|
||||
#ifdef CONFIG_PPC_BOOK3E
|
||||
|
@ -319,10 +319,10 @@ syscall_exit_work:
|
|||
mtmsrd r10,1
|
||||
#endif /* CONFIG_PPC_BOOK3E */
|
||||
|
||||
bl .save_nvgprs
|
||||
bl save_nvgprs
|
||||
addi r3,r1,STACK_FRAME_OVERHEAD
|
||||
bl .do_syscall_trace_leave
|
||||
b .ret_from_except
|
||||
bl do_syscall_trace_leave
|
||||
b ret_from_except
|
||||
|
||||
/* Save non-volatile GPRs, if not already saved. */
|
||||
_GLOBAL(save_nvgprs)
|
||||
|
@ -345,42 +345,44 @@ _GLOBAL(save_nvgprs)
|
|||
*/
|
||||
|
||||
_GLOBAL(ppc_fork)
|
||||
bl .save_nvgprs
|
||||
bl .sys_fork
|
||||
bl save_nvgprs
|
||||
bl sys_fork
|
||||
b syscall_exit
|
||||
|
||||
_GLOBAL(ppc_vfork)
|
||||
bl .save_nvgprs
|
||||
bl .sys_vfork
|
||||
bl save_nvgprs
|
||||
bl sys_vfork
|
||||
b syscall_exit
|
||||
|
||||
_GLOBAL(ppc_clone)
|
||||
bl .save_nvgprs
|
||||
bl .sys_clone
|
||||
bl save_nvgprs
|
||||
bl sys_clone
|
||||
b syscall_exit
|
||||
|
||||
_GLOBAL(ppc32_swapcontext)
|
||||
bl .save_nvgprs
|
||||
bl .compat_sys_swapcontext
|
||||
bl save_nvgprs
|
||||
bl compat_sys_swapcontext
|
||||
b syscall_exit
|
||||
|
||||
_GLOBAL(ppc64_swapcontext)
|
||||
bl .save_nvgprs
|
||||
bl .sys_swapcontext
|
||||
bl save_nvgprs
|
||||
bl sys_swapcontext
|
||||
b syscall_exit
|
||||
|
||||
_GLOBAL(ret_from_fork)
|
||||
bl .schedule_tail
|
||||
bl schedule_tail
|
||||
REST_NVGPRS(r1)
|
||||
li r3,0
|
||||
b syscall_exit
|
||||
|
||||
_GLOBAL(ret_from_kernel_thread)
|
||||
bl .schedule_tail
|
||||
bl schedule_tail
|
||||
REST_NVGPRS(r1)
|
||||
ld r14, 0(r14)
|
||||
mtlr r14
|
||||
mr r3,r15
|
||||
#if defined(_CALL_ELF) && _CALL_ELF == 2
|
||||
mr r12,r14
|
||||
#endif
|
||||
blrl
|
||||
li r3,0
|
||||
b syscall_exit
|
||||
|
@ -611,7 +613,7 @@ END_FTR_SECTION_IFSET(CPU_FTR_DSCR)
|
|||
_GLOBAL(ret_from_except)
|
||||
ld r11,_TRAP(r1)
|
||||
andi. r0,r11,1
|
||||
bne .ret_from_except_lite
|
||||
bne ret_from_except_lite
|
||||
REST_NVGPRS(r1)
|
||||
|
||||
_GLOBAL(ret_from_except_lite)
|
||||
|
@ -661,23 +663,23 @@ _GLOBAL(ret_from_except_lite)
|
|||
#endif
|
||||
1: andi. r0,r4,_TIF_NEED_RESCHED
|
||||
beq 2f
|
||||
bl .restore_interrupts
|
||||
bl restore_interrupts
|
||||
SCHEDULE_USER
|
||||
b .ret_from_except_lite
|
||||
b ret_from_except_lite
|
||||
2:
|
||||
#ifdef CONFIG_PPC_TRANSACTIONAL_MEM
|
||||
andi. r0,r4,_TIF_USER_WORK_MASK & ~_TIF_RESTORE_TM
|
||||
bne 3f /* only restore TM if nothing else to do */
|
||||
addi r3,r1,STACK_FRAME_OVERHEAD
|
||||
bl .restore_tm_state
|
||||
bl restore_tm_state
|
||||
b restore
|
||||
3:
|
||||
#endif
|
||||
bl .save_nvgprs
|
||||
bl .restore_interrupts
|
||||
bl save_nvgprs
|
||||
bl restore_interrupts
|
||||
addi r3,r1,STACK_FRAME_OVERHEAD
|
||||
bl .do_notify_resume
|
||||
b .ret_from_except
|
||||
bl do_notify_resume
|
||||
b ret_from_except
|
||||
|
||||
resume_kernel:
|
||||
/* check current_thread_info, _TIF_EMULATE_STACK_STORE */
|
||||
|
@ -730,7 +732,7 @@ resume_kernel:
|
|||
* sure we are soft-disabled first and reconcile irq state.
|
||||
*/
|
||||
RECONCILE_IRQ_STATE(r3,r4)
|
||||
1: bl .preempt_schedule_irq
|
||||
1: bl preempt_schedule_irq
|
||||
|
||||
/* Re-test flags and eventually loop */
|
||||
CURRENT_THREAD_INFO(r9, r1)
|
||||
|
@ -792,7 +794,7 @@ restore_no_replay:
|
|||
*/
|
||||
do_restore:
|
||||
#ifdef CONFIG_PPC_BOOK3E
|
||||
b .exception_return_book3e
|
||||
b exception_return_book3e
|
||||
#else
|
||||
/*
|
||||
* Clear the reservation. If we know the CPU tracks the address of
|
||||
|
@ -907,7 +909,7 @@ restore_check_irq_replay:
|
|||
*
|
||||
* Still, this might be useful for things like hash_page
|
||||
*/
|
||||
bl .__check_irq_replay
|
||||
bl __check_irq_replay
|
||||
cmpwi cr0,r3,0
|
||||
beq restore_no_replay
|
||||
|
||||
|
@ -928,13 +930,13 @@ restore_check_irq_replay:
|
|||
cmpwi cr0,r3,0x500
|
||||
bne 1f
|
||||
addi r3,r1,STACK_FRAME_OVERHEAD;
|
||||
bl .do_IRQ
|
||||
b .ret_from_except
|
||||
bl do_IRQ
|
||||
b ret_from_except
|
||||
1: cmpwi cr0,r3,0x900
|
||||
bne 1f
|
||||
addi r3,r1,STACK_FRAME_OVERHEAD;
|
||||
bl .timer_interrupt
|
||||
b .ret_from_except
|
||||
bl timer_interrupt
|
||||
b ret_from_except
|
||||
#ifdef CONFIG_PPC_DOORBELL
|
||||
1:
|
||||
#ifdef CONFIG_PPC_BOOK3E
|
||||
|
@ -948,14 +950,14 @@ restore_check_irq_replay:
|
|||
#endif /* CONFIG_PPC_BOOK3E */
|
||||
bne 1f
|
||||
addi r3,r1,STACK_FRAME_OVERHEAD;
|
||||
bl .doorbell_exception
|
||||
b .ret_from_except
|
||||
bl doorbell_exception
|
||||
b ret_from_except
|
||||
#endif /* CONFIG_PPC_DOORBELL */
|
||||
1: b .ret_from_except /* What else to do here ? */
|
||||
1: b ret_from_except /* What else to do here ? */
|
||||
|
||||
unrecov_restore:
|
||||
addi r3,r1,STACK_FRAME_OVERHEAD
|
||||
bl .unrecoverable_exception
|
||||
bl unrecoverable_exception
|
||||
b unrecov_restore
|
||||
|
||||
#ifdef CONFIG_PPC_RTAS
|
||||
|
@ -1021,7 +1023,7 @@ _GLOBAL(enter_rtas)
|
|||
std r6,PACASAVEDMSR(r13)
|
||||
|
||||
/* Setup our real return addr */
|
||||
LOAD_REG_ADDR(r4,.rtas_return_loc)
|
||||
LOAD_REG_ADDR(r4,rtas_return_loc)
|
||||
clrldi r4,r4,2 /* convert to realmode address */
|
||||
mtlr r4
|
||||
|
||||
|
@ -1045,7 +1047,7 @@ _GLOBAL(enter_rtas)
|
|||
rfid
|
||||
b . /* prevent speculative execution */
|
||||
|
||||
_STATIC(rtas_return_loc)
|
||||
rtas_return_loc:
|
||||
FIXUP_ENDIAN
|
||||
|
||||
/* relocation is off at this point */
|
||||
|
@ -1054,7 +1056,7 @@ _STATIC(rtas_return_loc)
|
|||
|
||||
bcl 20,31,$+4
|
||||
0: mflr r3
|
||||
ld r3,(1f-0b)(r3) /* get &.rtas_restore_regs */
|
||||
ld r3,(1f-0b)(r3) /* get &rtas_restore_regs */
|
||||
|
||||
mfmsr r6
|
||||
li r0,MSR_RI
|
||||
|
@ -1071,9 +1073,9 @@ _STATIC(rtas_return_loc)
|
|||
b . /* prevent speculative execution */
|
||||
|
||||
.align 3
|
||||
1: .llong .rtas_restore_regs
|
||||
1: .llong rtas_restore_regs
|
||||
|
||||
_STATIC(rtas_restore_regs)
|
||||
rtas_restore_regs:
|
||||
/* relocation is on at this point */
|
||||
REST_GPR(2, r1) /* Restore the TOC */
|
||||
REST_GPR(13, r1) /* Restore paca */
|
||||
|
@ -1173,7 +1175,7 @@ _GLOBAL(mcount)
|
|||
_GLOBAL(_mcount)
|
||||
blr
|
||||
|
||||
_GLOBAL(ftrace_caller)
|
||||
_GLOBAL_TOC(ftrace_caller)
|
||||
/* Taken from output of objdump from lib64/glibc */
|
||||
mflr r3
|
||||
ld r11, 0(r1)
|
||||
|
@ -1197,10 +1199,7 @@ _GLOBAL(ftrace_graph_stub)
|
|||
_GLOBAL(ftrace_stub)
|
||||
blr
|
||||
#else
|
||||
_GLOBAL(mcount)
|
||||
blr
|
||||
|
||||
_GLOBAL(_mcount)
|
||||
_GLOBAL_TOC(_mcount)
|
||||
/* Taken from output of objdump from lib64/glibc */
|
||||
mflr r3
|
||||
ld r11, 0(r1)
|
||||
|
@ -1238,7 +1237,7 @@ _GLOBAL(ftrace_graph_caller)
|
|||
ld r11, 112(r1)
|
||||
addi r3, r11, 16
|
||||
|
||||
bl .prepare_ftrace_return
|
||||
bl prepare_ftrace_return
|
||||
nop
|
||||
|
||||
ld r0, 128(r1)
|
||||
|
@ -1254,7 +1253,7 @@ _GLOBAL(return_to_handler)
|
|||
mr r31, r1
|
||||
stdu r1, -112(r1)
|
||||
|
||||
bl .ftrace_return_to_handler
|
||||
bl ftrace_return_to_handler
|
||||
nop
|
||||
|
||||
/* return value has real return address */
|
||||
|
@ -1284,7 +1283,7 @@ _GLOBAL(mod_return_to_handler)
|
|||
*/
|
||||
ld r2, PACATOC(r13)
|
||||
|
||||
bl .ftrace_return_to_handler
|
||||
bl ftrace_return_to_handler
|
||||
nop
|
||||
|
||||
/* return value has real return address */
|
||||
|
|
|
@ -499,7 +499,7 @@ exc_##n##_bad_stack: \
|
|||
CHECK_NAPPING(); \
|
||||
addi r3,r1,STACK_FRAME_OVERHEAD; \
|
||||
bl hdlr; \
|
||||
b .ret_from_except_lite;
|
||||
b ret_from_except_lite;
|
||||
|
||||
/* This value is used to mark exception frames on the stack. */
|
||||
.section ".toc","aw"
|
||||
|
@ -550,11 +550,11 @@ interrupt_end_book3e:
|
|||
CRIT_EXCEPTION_PROLOG(0x100, BOOKE_INTERRUPT_CRITICAL,
|
||||
PROLOG_ADDITION_NONE)
|
||||
EXCEPTION_COMMON_CRIT(0x100)
|
||||
bl .save_nvgprs
|
||||
bl save_nvgprs
|
||||
bl special_reg_save
|
||||
CHECK_NAPPING();
|
||||
addi r3,r1,STACK_FRAME_OVERHEAD
|
||||
bl .unknown_exception
|
||||
bl unknown_exception
|
||||
b ret_from_crit_except
|
||||
|
||||
/* Machine Check Interrupt */
|
||||
|
@ -562,11 +562,11 @@ interrupt_end_book3e:
|
|||
MC_EXCEPTION_PROLOG(0x000, BOOKE_INTERRUPT_MACHINE_CHECK,
|
||||
PROLOG_ADDITION_NONE)
|
||||
EXCEPTION_COMMON_MC(0x000)
|
||||
bl .save_nvgprs
|
||||
bl save_nvgprs
|
||||
bl special_reg_save
|
||||
CHECK_NAPPING();
|
||||
addi r3,r1,STACK_FRAME_OVERHEAD
|
||||
bl .machine_check_exception
|
||||
bl machine_check_exception
|
||||
b ret_from_mc_except
|
||||
|
||||
/* Data Storage Interrupt */
|
||||
|
@ -591,7 +591,7 @@ interrupt_end_book3e:
|
|||
|
||||
/* External Input Interrupt */
|
||||
MASKABLE_EXCEPTION(0x500, BOOKE_INTERRUPT_EXTERNAL,
|
||||
external_input, .do_IRQ, ACK_NONE)
|
||||
external_input, do_IRQ, ACK_NONE)
|
||||
|
||||
/* Alignment */
|
||||
START_EXCEPTION(alignment);
|
||||
|
@ -612,9 +612,9 @@ interrupt_end_book3e:
|
|||
std r14,_DSISR(r1)
|
||||
addi r3,r1,STACK_FRAME_OVERHEAD
|
||||
ld r14,PACA_EXGEN+EX_R14(r13)
|
||||
bl .save_nvgprs
|
||||
bl .program_check_exception
|
||||
b .ret_from_except
|
||||
bl save_nvgprs
|
||||
bl program_check_exception
|
||||
b ret_from_except
|
||||
|
||||
/* Floating Point Unavailable Interrupt */
|
||||
START_EXCEPTION(fp_unavailable);
|
||||
|
@ -625,13 +625,13 @@ interrupt_end_book3e:
|
|||
ld r12,_MSR(r1)
|
||||
andi. r0,r12,MSR_PR;
|
||||
beq- 1f
|
||||
bl .load_up_fpu
|
||||
bl load_up_fpu
|
||||
b fast_exception_return
|
||||
1: INTS_DISABLE
|
||||
bl .save_nvgprs
|
||||
bl save_nvgprs
|
||||
addi r3,r1,STACK_FRAME_OVERHEAD
|
||||
bl .kernel_fp_unavailable_exception
|
||||
b .ret_from_except
|
||||
bl kernel_fp_unavailable_exception
|
||||
b ret_from_except
|
||||
|
||||
/* Altivec Unavailable Interrupt */
|
||||
START_EXCEPTION(altivec_unavailable);
|
||||
|
@ -644,16 +644,16 @@ BEGIN_FTR_SECTION
|
|||
ld r12,_MSR(r1)
|
||||
andi. r0,r12,MSR_PR;
|
||||
beq- 1f
|
||||
bl .load_up_altivec
|
||||
bl load_up_altivec
|
||||
b fast_exception_return
|
||||
1:
|
||||
END_FTR_SECTION_IFSET(CPU_FTR_ALTIVEC)
|
||||
#endif
|
||||
INTS_DISABLE
|
||||
bl .save_nvgprs
|
||||
bl save_nvgprs
|
||||
addi r3,r1,STACK_FRAME_OVERHEAD
|
||||
bl .altivec_unavailable_exception
|
||||
b .ret_from_except
|
||||
bl altivec_unavailable_exception
|
||||
b ret_from_except
|
||||
|
||||
/* AltiVec Assist */
|
||||
START_EXCEPTION(altivec_assist);
|
||||
|
@ -662,39 +662,39 @@ END_FTR_SECTION_IFSET(CPU_FTR_ALTIVEC)
|
|||
PROLOG_ADDITION_NONE)
|
||||
EXCEPTION_COMMON(0x220)
|
||||
INTS_DISABLE
|
||||
bl .save_nvgprs
|
||||
bl save_nvgprs
|
||||
addi r3,r1,STACK_FRAME_OVERHEAD
|
||||
#ifdef CONFIG_ALTIVEC
|
||||
BEGIN_FTR_SECTION
|
||||
bl .altivec_assist_exception
|
||||
bl altivec_assist_exception
|
||||
END_FTR_SECTION_IFSET(CPU_FTR_ALTIVEC)
|
||||
#else
|
||||
bl .unknown_exception
|
||||
bl unknown_exception
|
||||
#endif
|
||||
b .ret_from_except
|
||||
b ret_from_except
|
||||
|
||||
|
||||
/* Decrementer Interrupt */
|
||||
MASKABLE_EXCEPTION(0x900, BOOKE_INTERRUPT_DECREMENTER,
|
||||
decrementer, .timer_interrupt, ACK_DEC)
|
||||
decrementer, timer_interrupt, ACK_DEC)
|
||||
|
||||
/* Fixed Interval Timer Interrupt */
|
||||
MASKABLE_EXCEPTION(0x980, BOOKE_INTERRUPT_FIT,
|
||||
fixed_interval, .unknown_exception, ACK_FIT)
|
||||
fixed_interval, unknown_exception, ACK_FIT)
|
||||
|
||||
/* Watchdog Timer Interrupt */
|
||||
START_EXCEPTION(watchdog);
|
||||
CRIT_EXCEPTION_PROLOG(0x9f0, BOOKE_INTERRUPT_WATCHDOG,
|
||||
PROLOG_ADDITION_NONE)
|
||||
EXCEPTION_COMMON_CRIT(0x9f0)
|
||||
bl .save_nvgprs
|
||||
bl save_nvgprs
|
||||
bl special_reg_save
|
||||
CHECK_NAPPING();
|
||||
addi r3,r1,STACK_FRAME_OVERHEAD
|
||||
#ifdef CONFIG_BOOKE_WDT
|
||||
bl .WatchdogException
|
||||
bl WatchdogException
|
||||
#else
|
||||
bl .unknown_exception
|
||||
bl unknown_exception
|
||||
#endif
|
||||
b ret_from_crit_except
|
||||
|
||||
|
@ -712,10 +712,10 @@ END_FTR_SECTION_IFSET(CPU_FTR_ALTIVEC)
|
|||
PROLOG_ADDITION_NONE)
|
||||
EXCEPTION_COMMON(0xf20)
|
||||
INTS_DISABLE
|
||||
bl .save_nvgprs
|
||||
bl save_nvgprs
|
||||
addi r3,r1,STACK_FRAME_OVERHEAD
|
||||
bl .unknown_exception
|
||||
b .ret_from_except
|
||||
bl unknown_exception
|
||||
b ret_from_except
|
||||
|
||||
/* Debug exception as a critical interrupt*/
|
||||
START_EXCEPTION(debug_crit);
|
||||
|
@ -774,9 +774,9 @@ END_FTR_SECTION_IFSET(CPU_FTR_ALTIVEC)
|
|||
mr r4,r14
|
||||
ld r14,PACA_EXCRIT+EX_R14(r13)
|
||||
ld r15,PACA_EXCRIT+EX_R15(r13)
|
||||
bl .save_nvgprs
|
||||
bl .DebugException
|
||||
b .ret_from_except
|
||||
bl save_nvgprs
|
||||
bl DebugException
|
||||
b ret_from_except
|
||||
|
||||
kernel_dbg_exc:
|
||||
b . /* NYI */
|
||||
|
@ -839,9 +839,9 @@ kernel_dbg_exc:
|
|||
mr r4,r14
|
||||
ld r14,PACA_EXDBG+EX_R14(r13)
|
||||
ld r15,PACA_EXDBG+EX_R15(r13)
|
||||
bl .save_nvgprs
|
||||
bl .DebugException
|
||||
b .ret_from_except
|
||||
bl save_nvgprs
|
||||
bl DebugException
|
||||
b ret_from_except
|
||||
|
||||
START_EXCEPTION(perfmon);
|
||||
NORMAL_EXCEPTION_PROLOG(0x260, BOOKE_INTERRUPT_PERFORMANCE_MONITOR,
|
||||
|
@ -850,23 +850,23 @@ kernel_dbg_exc:
|
|||
INTS_DISABLE
|
||||
CHECK_NAPPING()
|
||||
addi r3,r1,STACK_FRAME_OVERHEAD
|
||||
bl .performance_monitor_exception
|
||||
b .ret_from_except_lite
|
||||
bl performance_monitor_exception
|
||||
b ret_from_except_lite
|
||||
|
||||
/* Doorbell interrupt */
|
||||
MASKABLE_EXCEPTION(0x280, BOOKE_INTERRUPT_DOORBELL,
|
||||
doorbell, .doorbell_exception, ACK_NONE)
|
||||
doorbell, doorbell_exception, ACK_NONE)
|
||||
|
||||
/* Doorbell critical Interrupt */
|
||||
START_EXCEPTION(doorbell_crit);
|
||||
CRIT_EXCEPTION_PROLOG(0x2a0, BOOKE_INTERRUPT_DOORBELL_CRITICAL,
|
||||
PROLOG_ADDITION_NONE)
|
||||
EXCEPTION_COMMON_CRIT(0x2a0)
|
||||
bl .save_nvgprs
|
||||
bl save_nvgprs
|
||||
bl special_reg_save
|
||||
CHECK_NAPPING();
|
||||
addi r3,r1,STACK_FRAME_OVERHEAD
|
||||
bl .unknown_exception
|
||||
bl unknown_exception
|
||||
b ret_from_crit_except
|
||||
|
||||
/*
|
||||
|
@ -878,21 +878,21 @@ kernel_dbg_exc:
|
|||
PROLOG_ADDITION_NONE)
|
||||
EXCEPTION_COMMON(0x2c0)
|
||||
addi r3,r1,STACK_FRAME_OVERHEAD
|
||||
bl .save_nvgprs
|
||||
bl save_nvgprs
|
||||
INTS_RESTORE_HARD
|
||||
bl .unknown_exception
|
||||
b .ret_from_except
|
||||
bl unknown_exception
|
||||
b ret_from_except
|
||||
|
||||
/* Guest Doorbell critical Interrupt */
|
||||
START_EXCEPTION(guest_doorbell_crit);
|
||||
CRIT_EXCEPTION_PROLOG(0x2e0, BOOKE_INTERRUPT_GUEST_DBELL_CRIT,
|
||||
PROLOG_ADDITION_NONE)
|
||||
EXCEPTION_COMMON_CRIT(0x2e0)
|
||||
bl .save_nvgprs
|
||||
bl save_nvgprs
|
||||
bl special_reg_save
|
||||
CHECK_NAPPING();
|
||||
addi r3,r1,STACK_FRAME_OVERHEAD
|
||||
bl .unknown_exception
|
||||
bl unknown_exception
|
||||
b ret_from_crit_except
|
||||
|
||||
/* Hypervisor call */
|
||||
|
@ -901,10 +901,10 @@ kernel_dbg_exc:
|
|||
PROLOG_ADDITION_NONE)
|
||||
EXCEPTION_COMMON(0x310)
|
||||
addi r3,r1,STACK_FRAME_OVERHEAD
|
||||
bl .save_nvgprs
|
||||
bl save_nvgprs
|
||||
INTS_RESTORE_HARD
|
||||
bl .unknown_exception
|
||||
b .ret_from_except
|
||||
bl unknown_exception
|
||||
b ret_from_except
|
||||
|
||||
/* Embedded Hypervisor priviledged */
|
||||
START_EXCEPTION(ehpriv);
|
||||
|
@ -912,10 +912,10 @@ kernel_dbg_exc:
|
|||
PROLOG_ADDITION_NONE)
|
||||
EXCEPTION_COMMON(0x320)
|
||||
addi r3,r1,STACK_FRAME_OVERHEAD
|
||||
bl .save_nvgprs
|
||||
bl save_nvgprs
|
||||
INTS_RESTORE_HARD
|
||||
bl .unknown_exception
|
||||
b .ret_from_except
|
||||
bl unknown_exception
|
||||
b ret_from_except
|
||||
|
||||
/* LRAT Error interrupt */
|
||||
START_EXCEPTION(lrat_error);
|
||||
|
@ -1014,16 +1014,16 @@ storage_fault_common:
|
|||
mr r5,r15
|
||||
ld r14,PACA_EXGEN+EX_R14(r13)
|
||||
ld r15,PACA_EXGEN+EX_R15(r13)
|
||||
bl .do_page_fault
|
||||
bl do_page_fault
|
||||
cmpdi r3,0
|
||||
bne- 1f
|
||||
b .ret_from_except_lite
|
||||
1: bl .save_nvgprs
|
||||
b ret_from_except_lite
|
||||
1: bl save_nvgprs
|
||||
mr r5,r3
|
||||
addi r3,r1,STACK_FRAME_OVERHEAD
|
||||
ld r4,_DAR(r1)
|
||||
bl .bad_page_fault
|
||||
b .ret_from_except
|
||||
bl bad_page_fault
|
||||
b ret_from_except
|
||||
|
||||
/*
|
||||
* Alignment exception doesn't fit entirely in the 0x100 bytes so it
|
||||
|
@ -1035,10 +1035,10 @@ alignment_more:
|
|||
addi r3,r1,STACK_FRAME_OVERHEAD
|
||||
ld r14,PACA_EXGEN+EX_R14(r13)
|
||||
ld r15,PACA_EXGEN+EX_R15(r13)
|
||||
bl .save_nvgprs
|
||||
bl save_nvgprs
|
||||
INTS_RESTORE_HARD
|
||||
bl .alignment_exception
|
||||
b .ret_from_except
|
||||
bl alignment_exception
|
||||
b ret_from_except
|
||||
|
||||
/*
|
||||
* We branch here from entry_64.S for the last stage of the exception
|
||||
|
@ -1172,7 +1172,7 @@ bad_stack_book3e:
|
|||
std r12,0(r11)
|
||||
ld r2,PACATOC(r13)
|
||||
1: addi r3,r1,STACK_FRAME_OVERHEAD
|
||||
bl .kernel_bad_stack
|
||||
bl kernel_bad_stack
|
||||
b 1b
|
||||
|
||||
/*
|
||||
|
@ -1521,13 +1521,13 @@ _GLOBAL(start_initialization_book3e)
|
|||
* and always use AS 0, so we just set it up to match our link
|
||||
* address and never use 0 based addresses.
|
||||
*/
|
||||
bl .initial_tlb_book3e
|
||||
bl initial_tlb_book3e
|
||||
|
||||
/* Init global core bits */
|
||||
bl .init_core_book3e
|
||||
bl init_core_book3e
|
||||
|
||||
/* Init per-thread bits */
|
||||
bl .init_thread_book3e
|
||||
bl init_thread_book3e
|
||||
|
||||
/* Return to common init code */
|
||||
tovirt(r28,r28)
|
||||
|
@ -1548,7 +1548,7 @@ _GLOBAL(start_initialization_book3e)
|
|||
*/
|
||||
_GLOBAL(book3e_secondary_core_init_tlb_set)
|
||||
li r4,1
|
||||
b .generic_secondary_smp_init
|
||||
b generic_secondary_smp_init
|
||||
|
||||
_GLOBAL(book3e_secondary_core_init)
|
||||
mflr r28
|
||||
|
@ -1558,18 +1558,18 @@ _GLOBAL(book3e_secondary_core_init)
|
|||
bne 2f
|
||||
|
||||
/* Setup TLB for this core */
|
||||
bl .initial_tlb_book3e
|
||||
bl initial_tlb_book3e
|
||||
|
||||
/* We can return from the above running at a different
|
||||
* address, so recalculate r2 (TOC)
|
||||
*/
|
||||
bl .relative_toc
|
||||
bl relative_toc
|
||||
|
||||
/* Init global core bits */
|
||||
2: bl .init_core_book3e
|
||||
2: bl init_core_book3e
|
||||
|
||||
/* Init per-thread bits */
|
||||
3: bl .init_thread_book3e
|
||||
3: bl init_thread_book3e
|
||||
|
||||
/* Return to common init code at proper virtual address.
|
||||
*
|
||||
|
@ -1596,14 +1596,14 @@ _GLOBAL(book3e_secondary_thread_init)
|
|||
mflr r28
|
||||
b 3b
|
||||
|
||||
_STATIC(init_core_book3e)
|
||||
init_core_book3e:
|
||||
/* Establish the interrupt vector base */
|
||||
LOAD_REG_IMMEDIATE(r3, interrupt_base_book3e)
|
||||
mtspr SPRN_IVPR,r3
|
||||
sync
|
||||
blr
|
||||
|
||||
_STATIC(init_thread_book3e)
|
||||
init_thread_book3e:
|
||||
lis r3,(SPRN_EPCR_ICM | SPRN_EPCR_GICM)@h
|
||||
mtspr SPRN_EPCR,r3
|
||||
|
||||
|
|
|
@ -132,12 +132,12 @@ BEGIN_FTR_SECTION
|
|||
#endif
|
||||
|
||||
beq cr1,2f
|
||||
b .power7_wakeup_noloss
|
||||
2: b .power7_wakeup_loss
|
||||
b power7_wakeup_noloss
|
||||
2: b power7_wakeup_loss
|
||||
|
||||
/* Fast Sleep wakeup on PowerNV */
|
||||
8: GET_PACA(r13)
|
||||
b .power7_wakeup_tb_loss
|
||||
b power7_wakeup_tb_loss
|
||||
|
||||
9:
|
||||
END_FTR_SECTION_IFSET(CPU_FTR_HVMODE | CPU_FTR_ARCH_206)
|
||||
|
@ -211,16 +211,16 @@ data_access_slb_pSeries:
|
|||
#endif /* __DISABLED__ */
|
||||
mfspr r12,SPRN_SRR1
|
||||
#ifndef CONFIG_RELOCATABLE
|
||||
b .slb_miss_realmode
|
||||
b slb_miss_realmode
|
||||
#else
|
||||
/*
|
||||
* We can't just use a direct branch to .slb_miss_realmode
|
||||
* We can't just use a direct branch to slb_miss_realmode
|
||||
* because the distance from here to there depends on where
|
||||
* the kernel ends up being put.
|
||||
*/
|
||||
mfctr r11
|
||||
ld r10,PACAKBASE(r13)
|
||||
LOAD_HANDLER(r10, .slb_miss_realmode)
|
||||
LOAD_HANDLER(r10, slb_miss_realmode)
|
||||
mtctr r10
|
||||
bctr
|
||||
#endif
|
||||
|
@ -243,11 +243,11 @@ instruction_access_slb_pSeries:
|
|||
#endif /* __DISABLED__ */
|
||||
mfspr r12,SPRN_SRR1
|
||||
#ifndef CONFIG_RELOCATABLE
|
||||
b .slb_miss_realmode
|
||||
b slb_miss_realmode
|
||||
#else
|
||||
mfctr r11
|
||||
ld r10,PACAKBASE(r13)
|
||||
LOAD_HANDLER(r10, .slb_miss_realmode)
|
||||
LOAD_HANDLER(r10, slb_miss_realmode)
|
||||
mtctr r10
|
||||
bctr
|
||||
#endif
|
||||
|
@ -524,7 +524,7 @@ do_stab_bolted_pSeries:
|
|||
std r12,PACA_EXSLB+EX_R12(r13)
|
||||
GET_SCRATCH0(r10)
|
||||
std r10,PACA_EXSLB+EX_R13(r13)
|
||||
EXCEPTION_PROLOG_PSERIES_1(.do_stab_bolted, EXC_STD)
|
||||
EXCEPTION_PROLOG_PSERIES_1(do_stab_bolted, EXC_STD)
|
||||
|
||||
KVM_HANDLER_SKIP(PACA_EXGEN, EXC_STD, 0x300)
|
||||
KVM_HANDLER_SKIP(PACA_EXSLB, EXC_STD, 0x380)
|
||||
|
@ -769,38 +769,38 @@ kvmppc_skip_Hinterrupt:
|
|||
|
||||
/*** Common interrupt handlers ***/
|
||||
|
||||
STD_EXCEPTION_COMMON(0x100, system_reset, .system_reset_exception)
|
||||
STD_EXCEPTION_COMMON(0x100, system_reset, system_reset_exception)
|
||||
|
||||
STD_EXCEPTION_COMMON_ASYNC(0x500, hardware_interrupt, do_IRQ)
|
||||
STD_EXCEPTION_COMMON_ASYNC(0x900, decrementer, .timer_interrupt)
|
||||
STD_EXCEPTION_COMMON(0x980, hdecrementer, .hdec_interrupt)
|
||||
STD_EXCEPTION_COMMON_ASYNC(0x900, decrementer, timer_interrupt)
|
||||
STD_EXCEPTION_COMMON(0x980, hdecrementer, hdec_interrupt)
|
||||
#ifdef CONFIG_PPC_DOORBELL
|
||||
STD_EXCEPTION_COMMON_ASYNC(0xa00, doorbell_super, .doorbell_exception)
|
||||
STD_EXCEPTION_COMMON_ASYNC(0xa00, doorbell_super, doorbell_exception)
|
||||
#else
|
||||
STD_EXCEPTION_COMMON_ASYNC(0xa00, doorbell_super, .unknown_exception)
|
||||
STD_EXCEPTION_COMMON_ASYNC(0xa00, doorbell_super, unknown_exception)
|
||||
#endif
|
||||
STD_EXCEPTION_COMMON(0xb00, trap_0b, .unknown_exception)
|
||||
STD_EXCEPTION_COMMON(0xd00, single_step, .single_step_exception)
|
||||
STD_EXCEPTION_COMMON(0xe00, trap_0e, .unknown_exception)
|
||||
STD_EXCEPTION_COMMON(0xe40, emulation_assist, .emulation_assist_interrupt)
|
||||
STD_EXCEPTION_COMMON(0xe60, hmi_exception, .unknown_exception)
|
||||
STD_EXCEPTION_COMMON(0xb00, trap_0b, unknown_exception)
|
||||
STD_EXCEPTION_COMMON(0xd00, single_step, single_step_exception)
|
||||
STD_EXCEPTION_COMMON(0xe00, trap_0e, unknown_exception)
|
||||
STD_EXCEPTION_COMMON(0xe40, emulation_assist, emulation_assist_interrupt)
|
||||
STD_EXCEPTION_COMMON(0xe60, hmi_exception, unknown_exception)
|
||||
#ifdef CONFIG_PPC_DOORBELL
|
||||
STD_EXCEPTION_COMMON_ASYNC(0xe80, h_doorbell, .doorbell_exception)
|
||||
STD_EXCEPTION_COMMON_ASYNC(0xe80, h_doorbell, doorbell_exception)
|
||||
#else
|
||||
STD_EXCEPTION_COMMON_ASYNC(0xe80, h_doorbell, .unknown_exception)
|
||||
STD_EXCEPTION_COMMON_ASYNC(0xe80, h_doorbell, unknown_exception)
|
||||
#endif
|
||||
STD_EXCEPTION_COMMON_ASYNC(0xf00, performance_monitor, .performance_monitor_exception)
|
||||
STD_EXCEPTION_COMMON(0x1300, instruction_breakpoint, .instruction_breakpoint_exception)
|
||||
STD_EXCEPTION_COMMON(0x1502, denorm, .unknown_exception)
|
||||
STD_EXCEPTION_COMMON_ASYNC(0xf00, performance_monitor, performance_monitor_exception)
|
||||
STD_EXCEPTION_COMMON(0x1300, instruction_breakpoint, instruction_breakpoint_exception)
|
||||
STD_EXCEPTION_COMMON(0x1502, denorm, unknown_exception)
|
||||
#ifdef CONFIG_ALTIVEC
|
||||
STD_EXCEPTION_COMMON(0x1700, altivec_assist, .altivec_assist_exception)
|
||||
STD_EXCEPTION_COMMON(0x1700, altivec_assist, altivec_assist_exception)
|
||||
#else
|
||||
STD_EXCEPTION_COMMON(0x1700, altivec_assist, .unknown_exception)
|
||||
STD_EXCEPTION_COMMON(0x1700, altivec_assist, unknown_exception)
|
||||
#endif
|
||||
#ifdef CONFIG_CBE_RAS
|
||||
STD_EXCEPTION_COMMON(0x1200, cbe_system_error, .cbe_system_error_exception)
|
||||
STD_EXCEPTION_COMMON(0x1600, cbe_maintenance, .cbe_maintenance_exception)
|
||||
STD_EXCEPTION_COMMON(0x1800, cbe_thermal, .cbe_thermal_exception)
|
||||
STD_EXCEPTION_COMMON(0x1200, cbe_system_error, cbe_system_error_exception)
|
||||
STD_EXCEPTION_COMMON(0x1600, cbe_maintenance, cbe_maintenance_exception)
|
||||
STD_EXCEPTION_COMMON(0x1800, cbe_thermal, cbe_thermal_exception)
|
||||
#endif /* CONFIG_CBE_RAS */
|
||||
|
||||
/*
|
||||
|
@ -829,16 +829,16 @@ data_access_slb_relon_pSeries:
|
|||
mfspr r3,SPRN_DAR
|
||||
mfspr r12,SPRN_SRR1
|
||||
#ifndef CONFIG_RELOCATABLE
|
||||
b .slb_miss_realmode
|
||||
b slb_miss_realmode
|
||||
#else
|
||||
/*
|
||||
* We can't just use a direct branch to .slb_miss_realmode
|
||||
* We can't just use a direct branch to slb_miss_realmode
|
||||
* because the distance from here to there depends on where
|
||||
* the kernel ends up being put.
|
||||
*/
|
||||
mfctr r11
|
||||
ld r10,PACAKBASE(r13)
|
||||
LOAD_HANDLER(r10, .slb_miss_realmode)
|
||||
LOAD_HANDLER(r10, slb_miss_realmode)
|
||||
mtctr r10
|
||||
bctr
|
||||
#endif
|
||||
|
@ -854,11 +854,11 @@ instruction_access_slb_relon_pSeries:
|
|||
mfspr r3,SPRN_SRR0 /* SRR0 is faulting address */
|
||||
mfspr r12,SPRN_SRR1
|
||||
#ifndef CONFIG_RELOCATABLE
|
||||
b .slb_miss_realmode
|
||||
b slb_miss_realmode
|
||||
#else
|
||||
mfctr r11
|
||||
ld r10,PACAKBASE(r13)
|
||||
LOAD_HANDLER(r10, .slb_miss_realmode)
|
||||
LOAD_HANDLER(r10, slb_miss_realmode)
|
||||
mtctr r10
|
||||
bctr
|
||||
#endif
|
||||
|
@ -966,7 +966,7 @@ system_call_entry:
|
|||
b system_call_common
|
||||
|
||||
ppc64_runlatch_on_trampoline:
|
||||
b .__ppc64_runlatch_on
|
||||
b __ppc64_runlatch_on
|
||||
|
||||
/*
|
||||
* Here we have detected that the kernel stack pointer is bad.
|
||||
|
@ -1025,7 +1025,7 @@ END_FTR_SECTION_IFSET(CPU_FTR_CFAR)
|
|||
std r12,RESULT(r1)
|
||||
std r11,STACK_FRAME_OVERHEAD-16(r1)
|
||||
1: addi r3,r1,STACK_FRAME_OVERHEAD
|
||||
bl .kernel_bad_stack
|
||||
bl kernel_bad_stack
|
||||
b 1b
|
||||
|
||||
/*
|
||||
|
@ -1046,7 +1046,7 @@ data_access_common:
|
|||
ld r3,PACA_EXGEN+EX_DAR(r13)
|
||||
lwz r4,PACA_EXGEN+EX_DSISR(r13)
|
||||
li r5,0x300
|
||||
b .do_hash_page /* Try to handle as hpte fault */
|
||||
b do_hash_page /* Try to handle as hpte fault */
|
||||
|
||||
.align 7
|
||||
.globl h_data_storage_common
|
||||
|
@ -1056,11 +1056,11 @@ h_data_storage_common:
|
|||
mfspr r10,SPRN_HDSISR
|
||||
stw r10,PACA_EXGEN+EX_DSISR(r13)
|
||||
EXCEPTION_PROLOG_COMMON(0xe00, PACA_EXGEN)
|
||||
bl .save_nvgprs
|
||||
bl save_nvgprs
|
||||
DISABLE_INTS
|
||||
addi r3,r1,STACK_FRAME_OVERHEAD
|
||||
bl .unknown_exception
|
||||
b .ret_from_except
|
||||
bl unknown_exception
|
||||
b ret_from_except
|
||||
|
||||
.align 7
|
||||
.globl instruction_access_common
|
||||
|
@ -1071,9 +1071,9 @@ instruction_access_common:
|
|||
ld r3,_NIP(r1)
|
||||
andis. r4,r12,0x5820
|
||||
li r5,0x400
|
||||
b .do_hash_page /* Try to handle as hpte fault */
|
||||
b do_hash_page /* Try to handle as hpte fault */
|
||||
|
||||
STD_EXCEPTION_COMMON(0xe20, h_instr_storage, .unknown_exception)
|
||||
STD_EXCEPTION_COMMON(0xe20, h_instr_storage, unknown_exception)
|
||||
|
||||
/*
|
||||
* Here is the common SLB miss user that is used when going to virtual
|
||||
|
@ -1088,7 +1088,7 @@ slb_miss_user_common:
|
|||
stw r9,PACA_EXGEN+EX_CCR(r13)
|
||||
std r10,PACA_EXGEN+EX_LR(r13)
|
||||
std r11,PACA_EXGEN+EX_SRR0(r13)
|
||||
bl .slb_allocate_user
|
||||
bl slb_allocate_user
|
||||
|
||||
ld r10,PACA_EXGEN+EX_LR(r13)
|
||||
ld r3,PACA_EXGEN+EX_R3(r13)
|
||||
|
@ -1131,9 +1131,9 @@ slb_miss_fault:
|
|||
unrecov_user_slb:
|
||||
EXCEPTION_PROLOG_COMMON(0x4200, PACA_EXGEN)
|
||||
DISABLE_INTS
|
||||
bl .save_nvgprs
|
||||
bl save_nvgprs
|
||||
1: addi r3,r1,STACK_FRAME_OVERHEAD
|
||||
bl .unrecoverable_exception
|
||||
bl unrecoverable_exception
|
||||
b 1b
|
||||
|
||||
#endif /* __DISABLED__ */
|
||||
|
@ -1158,10 +1158,10 @@ machine_check_common:
|
|||
lwz r4,PACA_EXGEN+EX_DSISR(r13)
|
||||
std r3,_DAR(r1)
|
||||
std r4,_DSISR(r1)
|
||||
bl .save_nvgprs
|
||||
bl save_nvgprs
|
||||
addi r3,r1,STACK_FRAME_OVERHEAD
|
||||
bl .machine_check_exception
|
||||
b .ret_from_except
|
||||
bl machine_check_exception
|
||||
b ret_from_except
|
||||
|
||||
.align 7
|
||||
.globl alignment_common
|
||||
|
@ -1175,31 +1175,31 @@ alignment_common:
|
|||
lwz r4,PACA_EXGEN+EX_DSISR(r13)
|
||||
std r3,_DAR(r1)
|
||||
std r4,_DSISR(r1)
|
||||
bl .save_nvgprs
|
||||
bl save_nvgprs
|
||||
DISABLE_INTS
|
||||
addi r3,r1,STACK_FRAME_OVERHEAD
|
||||
bl .alignment_exception
|
||||
b .ret_from_except
|
||||
bl alignment_exception
|
||||
b ret_from_except
|
||||
|
||||
.align 7
|
||||
.globl program_check_common
|
||||
program_check_common:
|
||||
EXCEPTION_PROLOG_COMMON(0x700, PACA_EXGEN)
|
||||
bl .save_nvgprs
|
||||
bl save_nvgprs
|
||||
DISABLE_INTS
|
||||
addi r3,r1,STACK_FRAME_OVERHEAD
|
||||
bl .program_check_exception
|
||||
b .ret_from_except
|
||||
bl program_check_exception
|
||||
b ret_from_except
|
||||
|
||||
.align 7
|
||||
.globl fp_unavailable_common
|
||||
fp_unavailable_common:
|
||||
EXCEPTION_PROLOG_COMMON(0x800, PACA_EXGEN)
|
||||
bne 1f /* if from user, just load it up */
|
||||
bl .save_nvgprs
|
||||
bl save_nvgprs
|
||||
DISABLE_INTS
|
||||
addi r3,r1,STACK_FRAME_OVERHEAD
|
||||
bl .kernel_fp_unavailable_exception
|
||||
bl kernel_fp_unavailable_exception
|
||||
BUG_OPCODE
|
||||
1:
|
||||
#ifdef CONFIG_PPC_TRANSACTIONAL_MEM
|
||||
|
@ -1211,15 +1211,15 @@ BEGIN_FTR_SECTION
|
|||
bne- 2f
|
||||
END_FTR_SECTION_IFSET(CPU_FTR_TM)
|
||||
#endif
|
||||
bl .load_up_fpu
|
||||
bl load_up_fpu
|
||||
b fast_exception_return
|
||||
#ifdef CONFIG_PPC_TRANSACTIONAL_MEM
|
||||
2: /* User process was in a transaction */
|
||||
bl .save_nvgprs
|
||||
bl save_nvgprs
|
||||
DISABLE_INTS
|
||||
addi r3,r1,STACK_FRAME_OVERHEAD
|
||||
bl .fp_unavailable_tm
|
||||
b .ret_from_except
|
||||
bl fp_unavailable_tm
|
||||
b ret_from_except
|
||||
#endif
|
||||
.align 7
|
||||
.globl altivec_unavailable_common
|
||||
|
@ -1237,24 +1237,24 @@ BEGIN_FTR_SECTION
|
|||
bne- 2f
|
||||
END_FTR_SECTION_NESTED(CPU_FTR_TM, CPU_FTR_TM, 69)
|
||||
#endif
|
||||
bl .load_up_altivec
|
||||
bl load_up_altivec
|
||||
b fast_exception_return
|
||||
#ifdef CONFIG_PPC_TRANSACTIONAL_MEM
|
||||
2: /* User process was in a transaction */
|
||||
bl .save_nvgprs
|
||||
bl save_nvgprs
|
||||
DISABLE_INTS
|
||||
addi r3,r1,STACK_FRAME_OVERHEAD
|
||||
bl .altivec_unavailable_tm
|
||||
b .ret_from_except
|
||||
bl altivec_unavailable_tm
|
||||
b ret_from_except
|
||||
#endif
|
||||
1:
|
||||
END_FTR_SECTION_IFSET(CPU_FTR_ALTIVEC)
|
||||
#endif
|
||||
bl .save_nvgprs
|
||||
bl save_nvgprs
|
||||
DISABLE_INTS
|
||||
addi r3,r1,STACK_FRAME_OVERHEAD
|
||||
bl .altivec_unavailable_exception
|
||||
b .ret_from_except
|
||||
bl altivec_unavailable_exception
|
||||
b ret_from_except
|
||||
|
||||
.align 7
|
||||
.globl vsx_unavailable_common
|
||||
|
@ -1272,26 +1272,26 @@ BEGIN_FTR_SECTION
|
|||
bne- 2f
|
||||
END_FTR_SECTION_NESTED(CPU_FTR_TM, CPU_FTR_TM, 69)
|
||||
#endif
|
||||
b .load_up_vsx
|
||||
b load_up_vsx
|
||||
#ifdef CONFIG_PPC_TRANSACTIONAL_MEM
|
||||
2: /* User process was in a transaction */
|
||||
bl .save_nvgprs
|
||||
bl save_nvgprs
|
||||
DISABLE_INTS
|
||||
addi r3,r1,STACK_FRAME_OVERHEAD
|
||||
bl .vsx_unavailable_tm
|
||||
b .ret_from_except
|
||||
bl vsx_unavailable_tm
|
||||
b ret_from_except
|
||||
#endif
|
||||
1:
|
||||
END_FTR_SECTION_IFSET(CPU_FTR_VSX)
|
||||
#endif
|
||||
bl .save_nvgprs
|
||||
bl save_nvgprs
|
||||
DISABLE_INTS
|
||||
addi r3,r1,STACK_FRAME_OVERHEAD
|
||||
bl .vsx_unavailable_exception
|
||||
b .ret_from_except
|
||||
bl vsx_unavailable_exception
|
||||
b ret_from_except
|
||||
|
||||
STD_EXCEPTION_COMMON(0xf60, facility_unavailable, .facility_unavailable_exception)
|
||||
STD_EXCEPTION_COMMON(0xf80, hv_facility_unavailable, .facility_unavailable_exception)
|
||||
STD_EXCEPTION_COMMON(0xf60, facility_unavailable, facility_unavailable_exception)
|
||||
STD_EXCEPTION_COMMON(0xf80, hv_facility_unavailable, facility_unavailable_exception)
|
||||
|
||||
.align 7
|
||||
.globl __end_handlers
|
||||
|
@ -1386,9 +1386,9 @@ _GLOBAL(opal_mc_secondary_handler)
|
|||
machine_check_handle_early:
|
||||
std r0,GPR0(r1) /* Save r0 */
|
||||
EXCEPTION_PROLOG_COMMON_3(0x200)
|
||||
bl .save_nvgprs
|
||||
bl save_nvgprs
|
||||
addi r3,r1,STACK_FRAME_OVERHEAD
|
||||
bl .machine_check_early
|
||||
bl machine_check_early
|
||||
ld r12,_MSR(r1)
|
||||
#ifdef CONFIG_PPC_P7_NAP
|
||||
/*
|
||||
|
@ -1408,11 +1408,11 @@ machine_check_handle_early:
|
|||
/* Supervisor state loss */
|
||||
li r0,1
|
||||
stb r0,PACA_NAPSTATELOST(r13)
|
||||
3: bl .machine_check_queue_event
|
||||
3: bl machine_check_queue_event
|
||||
MACHINE_CHECK_HANDLER_WINDUP
|
||||
GET_PACA(r13)
|
||||
ld r1,PACAR1(r13)
|
||||
b .power7_enter_nap_mode
|
||||
b power7_enter_nap_mode
|
||||
4:
|
||||
#endif
|
||||
/*
|
||||
|
@ -1444,7 +1444,7 @@ machine_check_handle_early:
|
|||
andi. r11,r12,MSR_RI
|
||||
bne 2f
|
||||
1: addi r3,r1,STACK_FRAME_OVERHEAD
|
||||
bl .unrecoverable_exception
|
||||
bl unrecoverable_exception
|
||||
b 1b
|
||||
2:
|
||||
/*
|
||||
|
@ -1452,7 +1452,7 @@ machine_check_handle_early:
|
|||
* Queue up the MCE event so that we can log it later, while
|
||||
* returning from kernel or opal call.
|
||||
*/
|
||||
bl .machine_check_queue_event
|
||||
bl machine_check_queue_event
|
||||
MACHINE_CHECK_HANDLER_WINDUP
|
||||
rfid
|
||||
9:
|
||||
|
@ -1468,7 +1468,7 @@ machine_check_handle_early:
|
|||
* r3 is saved in paca->slb_r3
|
||||
* We assume we aren't going to take any exceptions during this procedure.
|
||||
*/
|
||||
_GLOBAL(slb_miss_realmode)
|
||||
slb_miss_realmode:
|
||||
mflr r10
|
||||
#ifdef CONFIG_RELOCATABLE
|
||||
mtctr r11
|
||||
|
@ -1477,7 +1477,7 @@ _GLOBAL(slb_miss_realmode)
|
|||
stw r9,PACA_EXSLB+EX_CCR(r13) /* save CR in exc. frame */
|
||||
std r10,PACA_EXSLB+EX_LR(r13) /* save LR */
|
||||
|
||||
bl .slb_allocate_realmode
|
||||
bl slb_allocate_realmode
|
||||
|
||||
/* All done -- return from exception. */
|
||||
|
||||
|
@ -1517,9 +1517,9 @@ _GLOBAL(slb_miss_realmode)
|
|||
unrecov_slb:
|
||||
EXCEPTION_PROLOG_COMMON(0x4100, PACA_EXSLB)
|
||||
DISABLE_INTS
|
||||
bl .save_nvgprs
|
||||
bl save_nvgprs
|
||||
1: addi r3,r1,STACK_FRAME_OVERHEAD
|
||||
bl .unrecoverable_exception
|
||||
bl unrecoverable_exception
|
||||
b 1b
|
||||
|
||||
|
||||
|
@ -1536,7 +1536,7 @@ power4_fixup_nap:
|
|||
* Hash table stuff
|
||||
*/
|
||||
.align 7
|
||||
_STATIC(do_hash_page)
|
||||
do_hash_page:
|
||||
std r3,_DAR(r1)
|
||||
std r4,_DSISR(r1)
|
||||
|
||||
|
@ -1573,7 +1573,7 @@ END_MMU_FTR_SECTION_IFCLR(MMU_FTR_SLB)
|
|||
*
|
||||
* at return r3 = 0 for success, 1 for page fault, negative for error
|
||||
*/
|
||||
bl .hash_page /* build HPTE if possible */
|
||||
bl hash_page /* build HPTE if possible */
|
||||
cmpdi r3,0 /* see if hash_page succeeded */
|
||||
|
||||
/* Success */
|
||||
|
@ -1587,35 +1587,35 @@ handle_page_fault:
|
|||
11: ld r4,_DAR(r1)
|
||||
ld r5,_DSISR(r1)
|
||||
addi r3,r1,STACK_FRAME_OVERHEAD
|
||||
bl .do_page_fault
|
||||
bl do_page_fault
|
||||
cmpdi r3,0
|
||||
beq+ 12f
|
||||
bl .save_nvgprs
|
||||
bl save_nvgprs
|
||||
mr r5,r3
|
||||
addi r3,r1,STACK_FRAME_OVERHEAD
|
||||
lwz r4,_DAR(r1)
|
||||
bl .bad_page_fault
|
||||
b .ret_from_except
|
||||
bl bad_page_fault
|
||||
b ret_from_except
|
||||
|
||||
/* We have a data breakpoint exception - handle it */
|
||||
handle_dabr_fault:
|
||||
bl .save_nvgprs
|
||||
bl save_nvgprs
|
||||
ld r4,_DAR(r1)
|
||||
ld r5,_DSISR(r1)
|
||||
addi r3,r1,STACK_FRAME_OVERHEAD
|
||||
bl .do_break
|
||||
12: b .ret_from_except_lite
|
||||
bl do_break
|
||||
12: b ret_from_except_lite
|
||||
|
||||
|
||||
/* We have a page fault that hash_page could handle but HV refused
|
||||
* the PTE insertion
|
||||
*/
|
||||
13: bl .save_nvgprs
|
||||
13: bl save_nvgprs
|
||||
mr r5,r3
|
||||
addi r3,r1,STACK_FRAME_OVERHEAD
|
||||
ld r4,_DAR(r1)
|
||||
bl .low_hash_fault
|
||||
b .ret_from_except
|
||||
bl low_hash_fault
|
||||
b ret_from_except
|
||||
|
||||
/*
|
||||
* We come here as a result of a DSI at a point where we don't want
|
||||
|
@ -1624,16 +1624,16 @@ handle_dabr_fault:
|
|||
* were soft-disabled. We want to invoke the exception handler for
|
||||
* the access, or panic if there isn't a handler.
|
||||
*/
|
||||
77: bl .save_nvgprs
|
||||
77: bl save_nvgprs
|
||||
mr r4,r3
|
||||
addi r3,r1,STACK_FRAME_OVERHEAD
|
||||
li r5,SIGSEGV
|
||||
bl .bad_page_fault
|
||||
b .ret_from_except
|
||||
bl bad_page_fault
|
||||
b ret_from_except
|
||||
|
||||
/* here we have a segment miss */
|
||||
do_ste_alloc:
|
||||
bl .ste_allocate /* try to insert stab entry */
|
||||
bl ste_allocate /* try to insert stab entry */
|
||||
cmpdi r3,0
|
||||
bne- handle_page_fault
|
||||
b fast_exception_return
|
||||
|
@ -1646,7 +1646,7 @@ do_ste_alloc:
|
|||
* We assume (DAR >> 60) == 0xc.
|
||||
*/
|
||||
.align 7
|
||||
_GLOBAL(do_stab_bolted)
|
||||
do_stab_bolted:
|
||||
stw r9,PACA_EXSLB+EX_CCR(r13) /* save CR in exc. frame */
|
||||
std r11,PACA_EXSLB+EX_SRR0(r13) /* save SRR0 in exc. frame */
|
||||
mfspr r11,SPRN_DAR /* ea */
|
||||
|
|
|
@ -105,11 +105,9 @@ __ftrace_make_nop(struct module *mod,
|
|||
struct dyn_ftrace *rec, unsigned long addr)
|
||||
{
|
||||
unsigned int op;
|
||||
unsigned int jmp[5];
|
||||
unsigned long ptr;
|
||||
unsigned long ip = rec->ip;
|
||||
unsigned long tramp;
|
||||
int offset;
|
||||
void *tramp;
|
||||
|
||||
/* read where this goes */
|
||||
if (probe_kernel_read(&op, (void *)ip, sizeof(int)))
|
||||
|
@ -122,96 +120,41 @@ __ftrace_make_nop(struct module *mod,
|
|||
}
|
||||
|
||||
/* lets find where the pointer goes */
|
||||
tramp = find_bl_target(ip, op);
|
||||
tramp = (void *)find_bl_target(ip, op);
|
||||
|
||||
/*
|
||||
* On PPC64 the trampoline looks like:
|
||||
* 0x3d, 0x82, 0x00, 0x00, addis r12,r2, <high>
|
||||
* 0x39, 0x8c, 0x00, 0x00, addi r12,r12, <low>
|
||||
* Where the bytes 2,3,6 and 7 make up the 32bit offset
|
||||
* to the TOC that holds the pointer.
|
||||
* to jump to.
|
||||
* 0xf8, 0x41, 0x00, 0x28, std r2,40(r1)
|
||||
* 0xe9, 0x6c, 0x00, 0x20, ld r11,32(r12)
|
||||
* The actually address is 32 bytes from the offset
|
||||
* into the TOC.
|
||||
* 0xe8, 0x4c, 0x00, 0x28, ld r2,40(r12)
|
||||
*/
|
||||
pr_devel("ip:%lx jumps to %p", ip, tramp);
|
||||
|
||||
pr_devel("ip:%lx jumps to %lx r2: %lx", ip, tramp, mod->arch.toc);
|
||||
|
||||
/* Find where the trampoline jumps to */
|
||||
if (probe_kernel_read(jmp, (void *)tramp, sizeof(jmp))) {
|
||||
printk(KERN_ERR "Failed to read %lx\n", tramp);
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
pr_devel(" %08x %08x", jmp[0], jmp[1]);
|
||||
|
||||
/* verify that this is what we expect it to be */
|
||||
if (((jmp[0] & 0xffff0000) != 0x3d820000) ||
|
||||
((jmp[1] & 0xffff0000) != 0x398c0000) ||
|
||||
(jmp[2] != 0xf8410028) ||
|
||||
(jmp[3] != 0xe96c0020) ||
|
||||
(jmp[4] != 0xe84c0028)) {
|
||||
if (!is_module_trampoline(tramp)) {
|
||||
printk(KERN_ERR "Not a trampoline\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* The bottom half is signed extended */
|
||||
offset = ((unsigned)((unsigned short)jmp[0]) << 16) +
|
||||
(int)((short)jmp[1]);
|
||||
|
||||
pr_devel(" %x ", offset);
|
||||
|
||||
/* get the address this jumps too */
|
||||
tramp = mod->arch.toc + offset + 32;
|
||||
pr_devel("toc: %lx", tramp);
|
||||
|
||||
if (probe_kernel_read(jmp, (void *)tramp, 8)) {
|
||||
printk(KERN_ERR "Failed to read %lx\n", tramp);
|
||||
if (module_trampoline_target(mod, tramp, &ptr)) {
|
||||
printk(KERN_ERR "Failed to get trampoline target\n");
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
pr_devel(" %08x %08x\n", jmp[0], jmp[1]);
|
||||
|
||||
#ifdef __LITTLE_ENDIAN__
|
||||
ptr = ((unsigned long)jmp[1] << 32) + jmp[0];
|
||||
#else
|
||||
ptr = ((unsigned long)jmp[0] << 32) + jmp[1];
|
||||
#endif
|
||||
pr_devel("trampoline target %lx", ptr);
|
||||
|
||||
/* This should match what was called */
|
||||
if (ptr != ppc_function_entry((void *)addr)) {
|
||||
printk(KERN_ERR "addr does not match %lx\n", ptr);
|
||||
printk(KERN_ERR "addr %lx does not match expected %lx\n",
|
||||
ptr, ppc_function_entry((void *)addr));
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/*
|
||||
* We want to nop the line, but the next line is
|
||||
* 0xe8, 0x41, 0x00, 0x28 ld r2,40(r1)
|
||||
* This needs to be turned to a nop too.
|
||||
*/
|
||||
if (probe_kernel_read(&op, (void *)(ip+4), MCOUNT_INSN_SIZE))
|
||||
return -EFAULT;
|
||||
|
||||
if (op != 0xe8410028) {
|
||||
printk(KERN_ERR "Next line is not ld! (%08x)\n", op);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/*
|
||||
* Milton Miller pointed out that we can not blindly do nops.
|
||||
* If a task was preempted when calling a trace function,
|
||||
* the nops will remove the way to restore the TOC in r2
|
||||
* and the r2 TOC will get corrupted.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Replace:
|
||||
* bl <tramp> <==== will be replaced with "b 1f"
|
||||
* ld r2,40(r1)
|
||||
* 1:
|
||||
* Our original call site looks like:
|
||||
*
|
||||
* bl <tramp>
|
||||
* ld r2,XX(r1)
|
||||
*
|
||||
* Milton Miller pointed out that we can not simply nop the branch.
|
||||
* If a task was preempted when calling a trace function, the nops
|
||||
* will remove the way to restore the TOC in r2 and the r2 TOC will
|
||||
* get corrupted.
|
||||
*
|
||||
* Use a b +8 to jump over the load.
|
||||
*/
|
||||
op = 0x48000008; /* b +8 */
|
||||
|
||||
|
@ -349,19 +292,24 @@ static int
|
|||
__ftrace_make_call(struct dyn_ftrace *rec, unsigned long addr)
|
||||
{
|
||||
unsigned int op[2];
|
||||
unsigned long ip = rec->ip;
|
||||
void *ip = (void *)rec->ip;
|
||||
|
||||
/* read where this goes */
|
||||
if (probe_kernel_read(op, (void *)ip, MCOUNT_INSN_SIZE * 2))
|
||||
if (probe_kernel_read(op, ip, sizeof(op)))
|
||||
return -EFAULT;
|
||||
|
||||
/*
|
||||
* It should be pointing to two nops or
|
||||
* b +8; ld r2,40(r1)
|
||||
* We expect to see:
|
||||
*
|
||||
* b +8
|
||||
* ld r2,XX(r1)
|
||||
*
|
||||
* The load offset is different depending on the ABI. For simplicity
|
||||
* just mask it out when doing the compare.
|
||||
*/
|
||||
if (((op[0] != 0x48000008) || (op[1] != 0xe8410028)) &&
|
||||
((op[0] != PPC_INST_NOP) || (op[1] != PPC_INST_NOP))) {
|
||||
printk(KERN_ERR "Expected NOPs but have %x %x\n", op[0], op[1]);
|
||||
if ((op[0] != 0x48000008) || ((op[1] & 0xffff00000) != 0xe8410000)) {
|
||||
printk(KERN_ERR "Unexpected call sequence: %x %x\n",
|
||||
op[0], op[1]);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
|
@ -371,23 +319,16 @@ __ftrace_make_call(struct dyn_ftrace *rec, unsigned long addr)
|
|||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* create the branch to the trampoline */
|
||||
op[0] = create_branch((unsigned int *)ip,
|
||||
rec->arch.mod->arch.tramp, BRANCH_SET_LINK);
|
||||
if (!op[0]) {
|
||||
printk(KERN_ERR "REL24 out of range!\n");
|
||||
/* Ensure branch is within 24 bits */
|
||||
if (create_branch(ip, rec->arch.mod->arch.tramp, BRANCH_SET_LINK)) {
|
||||
printk(KERN_ERR "Branch out of range");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* ld r2,40(r1) */
|
||||
op[1] = 0xe8410028;
|
||||
|
||||
pr_devel("write to %lx\n", rec->ip);
|
||||
|
||||
if (probe_kernel_write((void *)ip, op, MCOUNT_INSN_SIZE * 2))
|
||||
return -EPERM;
|
||||
|
||||
flush_icache_range(ip, ip + 8);
|
||||
if (patch_branch(ip, rec->arch.mod->arch.tramp, BRANCH_SET_LINK)) {
|
||||
printk(KERN_ERR "REL24 out of range!\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -70,16 +70,15 @@ _GLOBAL(__start)
|
|||
/* NOP this out unconditionally */
|
||||
BEGIN_FTR_SECTION
|
||||
FIXUP_ENDIAN
|
||||
b .__start_initialization_multiplatform
|
||||
b __start_initialization_multiplatform
|
||||
END_FTR_SECTION(0, 1)
|
||||
|
||||
/* Catch branch to 0 in real mode */
|
||||
trap
|
||||
|
||||
/* Secondary processors spin on this value until it becomes nonzero.
|
||||
* When it does it contains the real address of the descriptor
|
||||
* of the function that the cpu should jump to to continue
|
||||
* initialization.
|
||||
/* Secondary processors spin on this value until it becomes non-zero.
|
||||
* When non-zero, it contains the real address of the function the cpu
|
||||
* should jump to.
|
||||
*/
|
||||
.balign 8
|
||||
.globl __secondary_hold_spinloop
|
||||
|
@ -140,16 +139,15 @@ __secondary_hold:
|
|||
tovirt(r26,r26)
|
||||
#endif
|
||||
/* All secondary cpus wait here until told to start. */
|
||||
100: ld r4,__secondary_hold_spinloop-_stext(r26)
|
||||
cmpdi 0,r4,0
|
||||
100: ld r12,__secondary_hold_spinloop-_stext(r26)
|
||||
cmpdi 0,r12,0
|
||||
beq 100b
|
||||
|
||||
#if defined(CONFIG_SMP) || defined(CONFIG_KEXEC)
|
||||
#ifdef CONFIG_PPC_BOOK3E
|
||||
tovirt(r4,r4)
|
||||
tovirt(r12,r12)
|
||||
#endif
|
||||
ld r4,0(r4) /* deref function descriptor */
|
||||
mtctr r4
|
||||
mtctr r12
|
||||
mr r3,r24
|
||||
/*
|
||||
* it may be the case that other platforms have r4 right to
|
||||
|
@ -186,16 +184,16 @@ _GLOBAL(generic_secondary_thread_init)
|
|||
mr r24,r3
|
||||
|
||||
/* turn on 64-bit mode */
|
||||
bl .enable_64b_mode
|
||||
bl enable_64b_mode
|
||||
|
||||
/* get a valid TOC pointer, wherever we're mapped at */
|
||||
bl .relative_toc
|
||||
bl relative_toc
|
||||
tovirt(r2,r2)
|
||||
|
||||
#ifdef CONFIG_PPC_BOOK3E
|
||||
/* Book3E initialization */
|
||||
mr r3,r24
|
||||
bl .book3e_secondary_thread_init
|
||||
bl book3e_secondary_thread_init
|
||||
#endif
|
||||
b generic_secondary_common_init
|
||||
|
||||
|
@ -214,17 +212,17 @@ _GLOBAL(generic_secondary_smp_init)
|
|||
mr r25,r4
|
||||
|
||||
/* turn on 64-bit mode */
|
||||
bl .enable_64b_mode
|
||||
bl enable_64b_mode
|
||||
|
||||
/* get a valid TOC pointer, wherever we're mapped at */
|
||||
bl .relative_toc
|
||||
bl relative_toc
|
||||
tovirt(r2,r2)
|
||||
|
||||
#ifdef CONFIG_PPC_BOOK3E
|
||||
/* Book3E initialization */
|
||||
mr r3,r24
|
||||
mr r4,r25
|
||||
bl .book3e_secondary_core_init
|
||||
bl book3e_secondary_core_init
|
||||
#endif
|
||||
|
||||
generic_secondary_common_init:
|
||||
|
@ -236,7 +234,7 @@ generic_secondary_common_init:
|
|||
ld r13,0(r13) /* Get base vaddr of paca array */
|
||||
#ifndef CONFIG_SMP
|
||||
addi r13,r13,PACA_SIZE /* know r13 if used accidentally */
|
||||
b .kexec_wait /* wait for next kernel if !SMP */
|
||||
b kexec_wait /* wait for next kernel if !SMP */
|
||||
#else
|
||||
LOAD_REG_ADDR(r7, nr_cpu_ids) /* Load nr_cpu_ids address */
|
||||
lwz r7,0(r7) /* also the max paca allocated */
|
||||
|
@ -250,7 +248,7 @@ generic_secondary_common_init:
|
|||
blt 1b
|
||||
|
||||
mr r3,r24 /* not found, copy phys to r3 */
|
||||
b .kexec_wait /* next kernel might do better */
|
||||
b kexec_wait /* next kernel might do better */
|
||||
|
||||
2: SET_PACA(r13)
|
||||
#ifdef CONFIG_PPC_BOOK3E
|
||||
|
@ -264,11 +262,13 @@ generic_secondary_common_init:
|
|||
/* See if we need to call a cpu state restore handler */
|
||||
LOAD_REG_ADDR(r23, cur_cpu_spec)
|
||||
ld r23,0(r23)
|
||||
ld r23,CPU_SPEC_RESTORE(r23)
|
||||
cmpdi 0,r23,0
|
||||
ld r12,CPU_SPEC_RESTORE(r23)
|
||||
cmpdi 0,r12,0
|
||||
beq 3f
|
||||
ld r23,0(r23)
|
||||
mtctr r23
|
||||
#if !defined(_CALL_ELF) || _CALL_ELF != 2
|
||||
ld r12,0(r12)
|
||||
#endif
|
||||
mtctr r12
|
||||
bctrl
|
||||
|
||||
3: LOAD_REG_ADDR(r3, spinning_secondaries) /* Decrement spinning_secondaries */
|
||||
|
@ -299,7 +299,7 @@ generic_secondary_common_init:
|
|||
* Assumes we're mapped EA == RA if the MMU is on.
|
||||
*/
|
||||
#ifdef CONFIG_PPC_BOOK3S
|
||||
_STATIC(__mmu_off)
|
||||
__mmu_off:
|
||||
mfmsr r3
|
||||
andi. r0,r3,MSR_IR|MSR_DR
|
||||
beqlr
|
||||
|
@ -324,12 +324,12 @@ _STATIC(__mmu_off)
|
|||
* DT block, r4 is a physical pointer to the kernel itself
|
||||
*
|
||||
*/
|
||||
_GLOBAL(__start_initialization_multiplatform)
|
||||
__start_initialization_multiplatform:
|
||||
/* Make sure we are running in 64 bits mode */
|
||||
bl .enable_64b_mode
|
||||
bl enable_64b_mode
|
||||
|
||||
/* Get TOC pointer (current runtime address) */
|
||||
bl .relative_toc
|
||||
bl relative_toc
|
||||
|
||||
/* find out where we are now */
|
||||
bcl 20,31,$+4
|
||||
|
@ -342,7 +342,7 @@ _GLOBAL(__start_initialization_multiplatform)
|
|||
*/
|
||||
cmpldi cr0,r5,0
|
||||
beq 1f
|
||||
b .__boot_from_prom /* yes -> prom */
|
||||
b __boot_from_prom /* yes -> prom */
|
||||
1:
|
||||
/* Save parameters */
|
||||
mr r31,r3
|
||||
|
@ -354,8 +354,8 @@ _GLOBAL(__start_initialization_multiplatform)
|
|||
#endif
|
||||
|
||||
#ifdef CONFIG_PPC_BOOK3E
|
||||
bl .start_initialization_book3e
|
||||
b .__after_prom_start
|
||||
bl start_initialization_book3e
|
||||
b __after_prom_start
|
||||
#else
|
||||
/* Setup some critical 970 SPRs before switching MMU off */
|
||||
mfspr r0,SPRN_PVR
|
||||
|
@ -368,15 +368,15 @@ _GLOBAL(__start_initialization_multiplatform)
|
|||
beq 1f
|
||||
cmpwi r0,0x45 /* 970GX */
|
||||
bne 2f
|
||||
1: bl .__cpu_preinit_ppc970
|
||||
1: bl __cpu_preinit_ppc970
|
||||
2:
|
||||
|
||||
/* Switch off MMU if not already off */
|
||||
bl .__mmu_off
|
||||
b .__after_prom_start
|
||||
bl __mmu_off
|
||||
b __after_prom_start
|
||||
#endif /* CONFIG_PPC_BOOK3E */
|
||||
|
||||
_INIT_STATIC(__boot_from_prom)
|
||||
__boot_from_prom:
|
||||
#ifdef CONFIG_PPC_OF_BOOT_TRAMPOLINE
|
||||
/* Save parameters */
|
||||
mr r31,r3
|
||||
|
@ -395,7 +395,7 @@ _INIT_STATIC(__boot_from_prom)
|
|||
#ifdef CONFIG_RELOCATABLE
|
||||
/* Relocate code for where we are now */
|
||||
mr r3,r26
|
||||
bl .relocate
|
||||
bl relocate
|
||||
#endif
|
||||
|
||||
/* Restore parameters */
|
||||
|
@ -407,14 +407,14 @@ _INIT_STATIC(__boot_from_prom)
|
|||
|
||||
/* Do all of the interaction with OF client interface */
|
||||
mr r8,r26
|
||||
bl .prom_init
|
||||
bl prom_init
|
||||
#endif /* #CONFIG_PPC_OF_BOOT_TRAMPOLINE */
|
||||
|
||||
/* We never return. We also hit that trap if trying to boot
|
||||
* from OF while CONFIG_PPC_OF_BOOT_TRAMPOLINE isn't selected */
|
||||
trap
|
||||
|
||||
_STATIC(__after_prom_start)
|
||||
__after_prom_start:
|
||||
#ifdef CONFIG_RELOCATABLE
|
||||
/* process relocations for the final address of the kernel */
|
||||
lis r25,PAGE_OFFSET@highest /* compute virtual base of kernel */
|
||||
|
@ -424,7 +424,7 @@ _STATIC(__after_prom_start)
|
|||
bne 1f
|
||||
add r25,r25,r26
|
||||
1: mr r3,r25
|
||||
bl .relocate
|
||||
bl relocate
|
||||
#endif
|
||||
|
||||
/*
|
||||
|
@ -464,12 +464,12 @@ _STATIC(__after_prom_start)
|
|||
lis r5,(copy_to_here - _stext)@ha
|
||||
addi r5,r5,(copy_to_here - _stext)@l /* # bytes of memory to copy */
|
||||
|
||||
bl .copy_and_flush /* copy the first n bytes */
|
||||
bl copy_and_flush /* copy the first n bytes */
|
||||
/* this includes the code being */
|
||||
/* executed here. */
|
||||
addis r8,r3,(4f - _stext)@ha /* Jump to the copy of this code */
|
||||
addi r8,r8,(4f - _stext)@l /* that we just made */
|
||||
mtctr r8
|
||||
addi r12,r8,(4f - _stext)@l /* that we just made */
|
||||
mtctr r12
|
||||
bctr
|
||||
|
||||
.balign 8
|
||||
|
@ -478,9 +478,9 @@ p_end: .llong _end - _stext
|
|||
4: /* Now copy the rest of the kernel up to _end */
|
||||
addis r5,r26,(p_end - _stext)@ha
|
||||
ld r5,(p_end - _stext)@l(r5) /* get _end */
|
||||
5: bl .copy_and_flush /* copy the rest */
|
||||
5: bl copy_and_flush /* copy the rest */
|
||||
|
||||
9: b .start_here_multiplatform
|
||||
9: b start_here_multiplatform
|
||||
|
||||
/*
|
||||
* Copy routine used to copy the kernel to start at physical address 0
|
||||
|
@ -544,7 +544,7 @@ __secondary_start_pmac_0:
|
|||
|
||||
_GLOBAL(pmac_secondary_start)
|
||||
/* turn on 64-bit mode */
|
||||
bl .enable_64b_mode
|
||||
bl enable_64b_mode
|
||||
|
||||
li r0,0
|
||||
mfspr r3,SPRN_HID4
|
||||
|
@ -556,11 +556,11 @@ _GLOBAL(pmac_secondary_start)
|
|||
slbia
|
||||
|
||||
/* get TOC pointer (real address) */
|
||||
bl .relative_toc
|
||||
bl relative_toc
|
||||
tovirt(r2,r2)
|
||||
|
||||
/* Copy some CPU settings from CPU 0 */
|
||||
bl .__restore_cpu_ppc970
|
||||
bl __restore_cpu_ppc970
|
||||
|
||||
/* pSeries do that early though I don't think we really need it */
|
||||
mfmsr r3
|
||||
|
@ -619,7 +619,7 @@ __secondary_start:
|
|||
std r14,PACAKSAVE(r13)
|
||||
|
||||
/* Do early setup for that CPU (stab, slb, hash table pointer) */
|
||||
bl .early_setup_secondary
|
||||
bl early_setup_secondary
|
||||
|
||||
/*
|
||||
* setup the new stack pointer, but *don't* use this until
|
||||
|
@ -639,7 +639,7 @@ __secondary_start:
|
|||
stb r0,PACAIRQHAPPENED(r13)
|
||||
|
||||
/* enable MMU and jump to start_secondary */
|
||||
LOAD_REG_ADDR(r3, .start_secondary_prolog)
|
||||
LOAD_REG_ADDR(r3, start_secondary_prolog)
|
||||
LOAD_REG_IMMEDIATE(r4, MSR_KERNEL)
|
||||
|
||||
mtspr SPRN_SRR0,r3
|
||||
|
@ -652,11 +652,11 @@ __secondary_start:
|
|||
* zero the stack back-chain pointer and get the TOC virtual address
|
||||
* before going into C code.
|
||||
*/
|
||||
_GLOBAL(start_secondary_prolog)
|
||||
start_secondary_prolog:
|
||||
ld r2,PACATOC(r13)
|
||||
li r3,0
|
||||
std r3,0(r1) /* Zero the stack frame pointer */
|
||||
bl .start_secondary
|
||||
bl start_secondary
|
||||
b .
|
||||
/*
|
||||
* Reset stack pointer and call start_secondary
|
||||
|
@ -667,14 +667,14 @@ _GLOBAL(start_secondary_resume)
|
|||
ld r1,PACAKSAVE(r13) /* Reload kernel stack pointer */
|
||||
li r3,0
|
||||
std r3,0(r1) /* Zero the stack frame pointer */
|
||||
bl .start_secondary
|
||||
bl start_secondary
|
||||
b .
|
||||
#endif
|
||||
|
||||
/*
|
||||
* This subroutine clobbers r11 and r12
|
||||
*/
|
||||
_GLOBAL(enable_64b_mode)
|
||||
enable_64b_mode:
|
||||
mfmsr r11 /* grab the current MSR */
|
||||
#ifdef CONFIG_PPC_BOOK3E
|
||||
oris r11,r11,0x8000 /* CM bit set, we'll set ICM later */
|
||||
|
@ -715,9 +715,9 @@ p_toc: .llong __toc_start + 0x8000 - 0b
|
|||
/*
|
||||
* This is where the main kernel code starts.
|
||||
*/
|
||||
_INIT_STATIC(start_here_multiplatform)
|
||||
start_here_multiplatform:
|
||||
/* set up the TOC */
|
||||
bl .relative_toc
|
||||
bl relative_toc
|
||||
tovirt(r2,r2)
|
||||
|
||||
/* Clear out the BSS. It may have been done in prom_init,
|
||||
|
@ -776,9 +776,9 @@ _INIT_STATIC(start_here_multiplatform)
|
|||
|
||||
/* Restore parameters passed from prom_init/kexec */
|
||||
mr r3,r31
|
||||
bl .early_setup /* also sets r13 and SPRG_PACA */
|
||||
bl early_setup /* also sets r13 and SPRG_PACA */
|
||||
|
||||
LOAD_REG_ADDR(r3, .start_here_common)
|
||||
LOAD_REG_ADDR(r3, start_here_common)
|
||||
ld r4,PACAKMSR(r13)
|
||||
mtspr SPRN_SRR0,r3
|
||||
mtspr SPRN_SRR1,r4
|
||||
|
@ -786,7 +786,8 @@ _INIT_STATIC(start_here_multiplatform)
|
|||
b . /* prevent speculative execution */
|
||||
|
||||
/* This is where all platforms converge execution */
|
||||
_INIT_GLOBAL(start_here_common)
|
||||
|
||||
start_here_common:
|
||||
/* relocation is on at this point */
|
||||
std r1,PACAKSAVE(r13)
|
||||
|
||||
|
@ -794,7 +795,7 @@ _INIT_GLOBAL(start_here_common)
|
|||
ld r2,PACATOC(r13)
|
||||
|
||||
/* Do more system initializations in virtual mode */
|
||||
bl .setup_system
|
||||
bl setup_system
|
||||
|
||||
/* Mark interrupts soft and hard disabled (they might be enabled
|
||||
* in the PACA when doing hotplug)
|
||||
|
@ -805,7 +806,7 @@ _INIT_GLOBAL(start_here_common)
|
|||
stb r0,PACAIRQHAPPENED(r13)
|
||||
|
||||
/* Generic kernel entry */
|
||||
bl .start_kernel
|
||||
bl start_kernel
|
||||
|
||||
/* Not reached */
|
||||
BUG_OPCODE
|
||||
|
|
|
@ -43,7 +43,7 @@ _GLOBAL(\name)
|
|||
*/
|
||||
#ifdef CONFIG_TRACE_IRQFLAGS
|
||||
stdu r1,-128(r1)
|
||||
bl .trace_hardirqs_on
|
||||
bl trace_hardirqs_on
|
||||
addi r1,r1,128
|
||||
#endif
|
||||
li r0,1
|
||||
|
|
|
@ -46,7 +46,7 @@ END_FTR_SECTION_IFCLR(CPU_FTR_CAN_NAP)
|
|||
mflr r0
|
||||
std r0,16(r1)
|
||||
stdu r1,-128(r1)
|
||||
bl .trace_hardirqs_on
|
||||
bl trace_hardirqs_on
|
||||
addi r1,r1,128
|
||||
ld r0,16(r1)
|
||||
mtlr r0
|
||||
|
|
|
@ -58,7 +58,7 @@ _GLOBAL(power7_powersave_common)
|
|||
/* Make sure FPU, VSX etc... are flushed as we may lose
|
||||
* state when going to nap mode
|
||||
*/
|
||||
bl .discard_lazy_cpu_state
|
||||
bl discard_lazy_cpu_state
|
||||
#endif /* CONFIG_SMP */
|
||||
|
||||
/* Hard disable interrupts */
|
||||
|
@ -168,7 +168,7 @@ _GLOBAL(power7_wakeup_loss)
|
|||
_GLOBAL(power7_wakeup_noloss)
|
||||
lbz r0,PACA_NAPSTATELOST(r13)
|
||||
cmpwi r0,0
|
||||
bne .power7_wakeup_loss
|
||||
bne power7_wakeup_loss
|
||||
ld r1,PACAR1(r13)
|
||||
ld r4,_MSR(r1)
|
||||
ld r5,_NIP(r1)
|
||||
|
|
|
@ -34,7 +34,7 @@ _GLOBAL(call_do_softirq)
|
|||
std r0,16(r1)
|
||||
stdu r1,THREAD_SIZE-STACK_FRAME_OVERHEAD(r3)
|
||||
mr r1,r3
|
||||
bl .__do_softirq
|
||||
bl __do_softirq
|
||||
ld r1,0(r1)
|
||||
ld r0,16(r1)
|
||||
mtlr r0
|
||||
|
@ -45,7 +45,7 @@ _GLOBAL(call_do_irq)
|
|||
std r0,16(r1)
|
||||
stdu r1,THREAD_SIZE-STACK_FRAME_OVERHEAD(r4)
|
||||
mr r1,r4
|
||||
bl .__do_irq
|
||||
bl __do_irq
|
||||
ld r1,0(r1)
|
||||
ld r0,16(r1)
|
||||
mtlr r0
|
||||
|
@ -506,7 +506,7 @@ _GLOBAL(kexec_smp_wait)
|
|||
stb r4,PACAKEXECSTATE(r13)
|
||||
SYNC
|
||||
|
||||
b .kexec_wait
|
||||
b kexec_wait
|
||||
|
||||
/*
|
||||
* switch to real mode (turn mmu off)
|
||||
|
@ -576,7 +576,7 @@ _GLOBAL(kexec_sequence)
|
|||
|
||||
/* copy dest pages, flush whole dest image */
|
||||
mr r3,r29
|
||||
bl .kexec_copy_flush /* (image) */
|
||||
bl kexec_copy_flush /* (image) */
|
||||
|
||||
/* turn off mmu */
|
||||
bl real_mode
|
||||
|
@ -586,7 +586,7 @@ _GLOBAL(kexec_sequence)
|
|||
mr r4,r30 /* start, aka phys mem offset */
|
||||
li r5,0x100
|
||||
li r6,0
|
||||
bl .copy_and_flush /* (dest, src, copy limit, start offset) */
|
||||
bl copy_and_flush /* (dest, src, copy limit, start offset) */
|
||||
1: /* assume normal blr return */
|
||||
|
||||
/* release other cpus to the new kernel secondary start at 0x60 */
|
||||
|
@ -595,8 +595,12 @@ _GLOBAL(kexec_sequence)
|
|||
stw r6,kexec_flag-1b(5)
|
||||
|
||||
/* clear out hardware hash page table and tlb */
|
||||
ld r5,0(r27) /* deref function descriptor */
|
||||
mtctr r5
|
||||
#if !defined(_CALL_ELF) || _CALL_ELF != 2
|
||||
ld r12,0(r27) /* deref function descriptor */
|
||||
#else
|
||||
mr r12,r27
|
||||
#endif
|
||||
mtctr r12
|
||||
bctrl /* ppc_md.hpte_clear_all(void); */
|
||||
|
||||
/*
|
||||
|
@ -630,3 +634,31 @@ _GLOBAL(kexec_sequence)
|
|||
li r5,0
|
||||
blr /* image->start(physid, image->start, 0); */
|
||||
#endif /* CONFIG_KEXEC */
|
||||
|
||||
#ifdef CONFIG_MODULES
|
||||
#if defined(_CALL_ELF) && _CALL_ELF == 2
|
||||
|
||||
#ifdef CONFIG_MODVERSIONS
|
||||
.weak __crc_TOC.
|
||||
.section "___kcrctab+TOC.","a"
|
||||
.globl __kcrctab_TOC.
|
||||
__kcrctab_TOC.:
|
||||
.llong __crc_TOC.
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Export a fake .TOC. since both modpost and depmod will complain otherwise.
|
||||
* Both modpost and depmod strip the leading . so we do the same here.
|
||||
*/
|
||||
.section "__ksymtab_strings","a"
|
||||
__kstrtab_TOC.:
|
||||
.asciz "TOC."
|
||||
|
||||
.section "___ksymtab+TOC.","a"
|
||||
/* This symbol name is important: it's used by modpost to find exported syms */
|
||||
.globl __ksymtab_TOC.
|
||||
__ksymtab_TOC.:
|
||||
.llong 0 /* .value */
|
||||
.llong __kstrtab_TOC.
|
||||
#endif /* ELFv2 */
|
||||
#endif /* MODULES */
|
||||
|
|
|
@ -22,6 +22,7 @@
|
|||
#include <linux/vmalloc.h>
|
||||
#include <linux/ftrace.h>
|
||||
#include <linux/bug.h>
|
||||
#include <linux/uaccess.h>
|
||||
#include <asm/module.h>
|
||||
#include <asm/firmware.h>
|
||||
#include <asm/code-patching.h>
|
||||
|
@ -41,46 +42,170 @@
|
|||
#define DEBUGP(fmt , ...)
|
||||
#endif
|
||||
|
||||
#if defined(_CALL_ELF) && _CALL_ELF == 2
|
||||
#define R2_STACK_OFFSET 24
|
||||
|
||||
/* An address is simply the address of the function. */
|
||||
typedef unsigned long func_desc_t;
|
||||
|
||||
static func_desc_t func_desc(unsigned long addr)
|
||||
{
|
||||
return addr;
|
||||
}
|
||||
static unsigned long func_addr(unsigned long addr)
|
||||
{
|
||||
return addr;
|
||||
}
|
||||
static unsigned long stub_func_addr(func_desc_t func)
|
||||
{
|
||||
return func;
|
||||
}
|
||||
|
||||
/* PowerPC64 specific values for the Elf64_Sym st_other field. */
|
||||
#define STO_PPC64_LOCAL_BIT 5
|
||||
#define STO_PPC64_LOCAL_MASK (7 << STO_PPC64_LOCAL_BIT)
|
||||
#define PPC64_LOCAL_ENTRY_OFFSET(other) \
|
||||
(((1 << (((other) & STO_PPC64_LOCAL_MASK) >> STO_PPC64_LOCAL_BIT)) >> 2) << 2)
|
||||
|
||||
static unsigned int local_entry_offset(const Elf64_Sym *sym)
|
||||
{
|
||||
/* sym->st_other indicates offset to local entry point
|
||||
* (otherwise it will assume r12 is the address of the start
|
||||
* of function and try to derive r2 from it). */
|
||||
return PPC64_LOCAL_ENTRY_OFFSET(sym->st_other);
|
||||
}
|
||||
#else
|
||||
#define R2_STACK_OFFSET 40
|
||||
|
||||
/* An address is address of the OPD entry, which contains address of fn. */
|
||||
typedef struct ppc64_opd_entry func_desc_t;
|
||||
|
||||
static func_desc_t func_desc(unsigned long addr)
|
||||
{
|
||||
return *(struct ppc64_opd_entry *)addr;
|
||||
}
|
||||
static unsigned long func_addr(unsigned long addr)
|
||||
{
|
||||
return func_desc(addr).funcaddr;
|
||||
}
|
||||
static unsigned long stub_func_addr(func_desc_t func)
|
||||
{
|
||||
return func.funcaddr;
|
||||
}
|
||||
static unsigned int local_entry_offset(const Elf64_Sym *sym)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Like PPC32, we need little trampolines to do > 24-bit jumps (into
|
||||
the kernel itself). But on PPC64, these need to be used for every
|
||||
jump, actually, to reset r2 (TOC+0x8000). */
|
||||
struct ppc64_stub_entry
|
||||
{
|
||||
/* 28 byte jump instruction sequence (7 instructions) */
|
||||
unsigned char jump[28];
|
||||
unsigned char unused[4];
|
||||
/* 28 byte jump instruction sequence (7 instructions). We only
|
||||
* need 6 instructions on ABIv2 but we always allocate 7 so
|
||||
* so we don't have to modify the trampoline load instruction. */
|
||||
u32 jump[7];
|
||||
u32 unused;
|
||||
/* Data for the above code */
|
||||
struct ppc64_opd_entry opd;
|
||||
func_desc_t funcdata;
|
||||
};
|
||||
|
||||
/* We use a stub to fix up r2 (TOC ptr) and to jump to the (external)
|
||||
function which may be more than 24-bits away. We could simply
|
||||
patch the new r2 value and function pointer into the stub, but it's
|
||||
significantly shorter to put these values at the end of the stub
|
||||
code, and patch the stub address (32-bits relative to the TOC ptr,
|
||||
r2) into the stub. */
|
||||
static struct ppc64_stub_entry ppc64_stub =
|
||||
{ .jump = {
|
||||
#ifdef __LITTLE_ENDIAN__
|
||||
0x00, 0x00, 0x82, 0x3d, /* addis r12,r2, <high> */
|
||||
0x00, 0x00, 0x8c, 0x39, /* addi r12,r12, <low> */
|
||||
/*
|
||||
* PPC64 uses 24 bit jumps, but we need to jump into other modules or
|
||||
* the kernel which may be further. So we jump to a stub.
|
||||
*
|
||||
* For ELFv1 we need to use this to set up the new r2 value (aka TOC
|
||||
* pointer). For ELFv2 it's the callee's responsibility to set up the
|
||||
* new r2, but for both we need to save the old r2.
|
||||
*
|
||||
* We could simply patch the new r2 value and function pointer into
|
||||
* the stub, but it's significantly shorter to put these values at the
|
||||
* end of the stub code, and patch the stub address (32-bits relative
|
||||
* to the TOC ptr, r2) into the stub.
|
||||
*/
|
||||
|
||||
static u32 ppc64_stub_insns[] = {
|
||||
0x3d620000, /* addis r11,r2, <high> */
|
||||
0x396b0000, /* addi r11,r11, <low> */
|
||||
/* Save current r2 value in magic place on the stack. */
|
||||
0x28, 0x00, 0x41, 0xf8, /* std r2,40(r1) */
|
||||
0x20, 0x00, 0x6c, 0xe9, /* ld r11,32(r12) */
|
||||
0x28, 0x00, 0x4c, 0xe8, /* ld r2,40(r12) */
|
||||
0xa6, 0x03, 0x69, 0x7d, /* mtctr r11 */
|
||||
0x20, 0x04, 0x80, 0x4e /* bctr */
|
||||
#else
|
||||
0x3d, 0x82, 0x00, 0x00, /* addis r12,r2, <high> */
|
||||
0x39, 0x8c, 0x00, 0x00, /* addi r12,r12, <low> */
|
||||
/* Save current r2 value in magic place on the stack. */
|
||||
0xf8, 0x41, 0x00, 0x28, /* std r2,40(r1) */
|
||||
0xe9, 0x6c, 0x00, 0x20, /* ld r11,32(r12) */
|
||||
0xe8, 0x4c, 0x00, 0x28, /* ld r2,40(r12) */
|
||||
0x7d, 0x69, 0x03, 0xa6, /* mtctr r11 */
|
||||
0x4e, 0x80, 0x04, 0x20 /* bctr */
|
||||
0xf8410000|R2_STACK_OFFSET, /* std r2,R2_STACK_OFFSET(r1) */
|
||||
0xe98b0020, /* ld r12,32(r11) */
|
||||
#if !defined(_CALL_ELF) || _CALL_ELF != 2
|
||||
/* Set up new r2 from function descriptor */
|
||||
0xe84b0026, /* ld r2,40(r11) */
|
||||
#endif
|
||||
0x7d8903a6, /* mtctr r12 */
|
||||
0x4e800420 /* bctr */
|
||||
};
|
||||
|
||||
#ifdef CONFIG_DYNAMIC_FTRACE
|
||||
|
||||
static u32 ppc64_stub_mask[] = {
|
||||
0xffff0000,
|
||||
0xffff0000,
|
||||
0xffffffff,
|
||||
0xffffffff,
|
||||
#if !defined(_CALL_ELF) || _CALL_ELF != 2
|
||||
0xffffffff,
|
||||
#endif
|
||||
0xffffffff,
|
||||
0xffffffff
|
||||
};
|
||||
|
||||
bool is_module_trampoline(u32 *p)
|
||||
{
|
||||
unsigned int i;
|
||||
u32 insns[ARRAY_SIZE(ppc64_stub_insns)];
|
||||
|
||||
BUILD_BUG_ON(sizeof(ppc64_stub_insns) != sizeof(ppc64_stub_mask));
|
||||
|
||||
if (probe_kernel_read(insns, p, sizeof(insns)))
|
||||
return -EFAULT;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(ppc64_stub_insns); i++) {
|
||||
u32 insna = insns[i];
|
||||
u32 insnb = ppc64_stub_insns[i];
|
||||
u32 mask = ppc64_stub_mask[i];
|
||||
|
||||
if ((insna & mask) != (insnb & mask))
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
int module_trampoline_target(struct module *mod, u32 *trampoline,
|
||||
unsigned long *target)
|
||||
{
|
||||
u32 buf[2];
|
||||
u16 upper, lower;
|
||||
long offset;
|
||||
void *toc_entry;
|
||||
|
||||
if (probe_kernel_read(buf, trampoline, sizeof(buf)))
|
||||
return -EFAULT;
|
||||
|
||||
upper = buf[0] & 0xffff;
|
||||
lower = buf[1] & 0xffff;
|
||||
|
||||
/* perform the addis/addi, both signed */
|
||||
offset = ((short)upper << 16) + (short)lower;
|
||||
|
||||
/*
|
||||
* Now get the address this trampoline jumps to. This
|
||||
* is always 32 bytes into our trampoline stub.
|
||||
*/
|
||||
toc_entry = (void *)mod->arch.toc + offset + 32;
|
||||
|
||||
if (probe_kernel_read(target, toc_entry, sizeof(*target)))
|
||||
return -EFAULT;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif
|
||||
} };
|
||||
|
||||
/* Count how many different 24-bit relocations (different symbol,
|
||||
different addend) */
|
||||
|
@ -183,6 +308,7 @@ static unsigned long get_stubs_size(const Elf64_Ehdr *hdr,
|
|||
return relocs * sizeof(struct ppc64_stub_entry);
|
||||
}
|
||||
|
||||
/* Still needed for ELFv2, for .TOC. */
|
||||
static void dedotify_versions(struct modversion_info *vers,
|
||||
unsigned long size)
|
||||
{
|
||||
|
@ -193,7 +319,7 @@ static void dedotify_versions(struct modversion_info *vers,
|
|||
memmove(vers->name, vers->name+1, strlen(vers->name));
|
||||
}
|
||||
|
||||
/* Undefined symbols which refer to .funcname, hack to funcname */
|
||||
/* Undefined symbols which refer to .funcname, hack to funcname (or .TOC.) */
|
||||
static void dedotify(Elf64_Sym *syms, unsigned int numsyms, char *strtab)
|
||||
{
|
||||
unsigned int i;
|
||||
|
@ -207,6 +333,24 @@ static void dedotify(Elf64_Sym *syms, unsigned int numsyms, char *strtab)
|
|||
}
|
||||
}
|
||||
|
||||
static Elf64_Sym *find_dot_toc(Elf64_Shdr *sechdrs,
|
||||
const char *strtab,
|
||||
unsigned int symindex)
|
||||
{
|
||||
unsigned int i, numsyms;
|
||||
Elf64_Sym *syms;
|
||||
|
||||
syms = (Elf64_Sym *)sechdrs[symindex].sh_addr;
|
||||
numsyms = sechdrs[symindex].sh_size / sizeof(Elf64_Sym);
|
||||
|
||||
for (i = 1; i < numsyms; i++) {
|
||||
if (syms[i].st_shndx == SHN_UNDEF
|
||||
&& strcmp(strtab + syms[i].st_name, "TOC.") == 0)
|
||||
return &syms[i];
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int module_frob_arch_sections(Elf64_Ehdr *hdr,
|
||||
Elf64_Shdr *sechdrs,
|
||||
char *secstrings,
|
||||
|
@ -271,21 +415,12 @@ static inline unsigned long my_r2(Elf64_Shdr *sechdrs, struct module *me)
|
|||
/* Patch stub to reference function and correct r2 value. */
|
||||
static inline int create_stub(Elf64_Shdr *sechdrs,
|
||||
struct ppc64_stub_entry *entry,
|
||||
struct ppc64_opd_entry *opd,
|
||||
unsigned long addr,
|
||||
struct module *me)
|
||||
{
|
||||
Elf64_Half *loc1, *loc2;
|
||||
long reladdr;
|
||||
|
||||
*entry = ppc64_stub;
|
||||
|
||||
#ifdef __LITTLE_ENDIAN__
|
||||
loc1 = (Elf64_Half *)&entry->jump[0];
|
||||
loc2 = (Elf64_Half *)&entry->jump[4];
|
||||
#else
|
||||
loc1 = (Elf64_Half *)&entry->jump[2];
|
||||
loc2 = (Elf64_Half *)&entry->jump[6];
|
||||
#endif
|
||||
memcpy(entry->jump, ppc64_stub_insns, sizeof(ppc64_stub_insns));
|
||||
|
||||
/* Stub uses address relative to r2. */
|
||||
reladdr = (unsigned long)entry - my_r2(sechdrs, me);
|
||||
|
@ -296,35 +431,33 @@ static inline int create_stub(Elf64_Shdr *sechdrs,
|
|||
}
|
||||
DEBUGP("Stub %p get data from reladdr %li\n", entry, reladdr);
|
||||
|
||||
*loc1 = PPC_HA(reladdr);
|
||||
*loc2 = PPC_LO(reladdr);
|
||||
entry->opd.funcaddr = opd->funcaddr;
|
||||
entry->opd.r2 = opd->r2;
|
||||
entry->jump[0] |= PPC_HA(reladdr);
|
||||
entry->jump[1] |= PPC_LO(reladdr);
|
||||
entry->funcdata = func_desc(addr);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Create stub to jump to function described in this OPD: we need the
|
||||
/* Create stub to jump to function described in this OPD/ptr: we need the
|
||||
stub to set up the TOC ptr (r2) for the function. */
|
||||
static unsigned long stub_for_addr(Elf64_Shdr *sechdrs,
|
||||
unsigned long opdaddr,
|
||||
unsigned long addr,
|
||||
struct module *me)
|
||||
{
|
||||
struct ppc64_stub_entry *stubs;
|
||||
struct ppc64_opd_entry *opd = (void *)opdaddr;
|
||||
unsigned int i, num_stubs;
|
||||
|
||||
num_stubs = sechdrs[me->arch.stubs_section].sh_size / sizeof(*stubs);
|
||||
|
||||
/* Find this stub, or if that fails, the next avail. entry */
|
||||
stubs = (void *)sechdrs[me->arch.stubs_section].sh_addr;
|
||||
for (i = 0; stubs[i].opd.funcaddr; i++) {
|
||||
for (i = 0; stub_func_addr(stubs[i].funcdata); i++) {
|
||||
BUG_ON(i >= num_stubs);
|
||||
|
||||
if (stubs[i].opd.funcaddr == opd->funcaddr)
|
||||
if (stub_func_addr(stubs[i].funcdata) == func_addr(addr))
|
||||
return (unsigned long)&stubs[i];
|
||||
}
|
||||
|
||||
if (!create_stub(sechdrs, &stubs[i], opd, me))
|
||||
if (!create_stub(sechdrs, &stubs[i], addr, me))
|
||||
return 0;
|
||||
|
||||
return (unsigned long)&stubs[i];
|
||||
|
@ -339,7 +472,8 @@ static int restore_r2(u32 *instruction, struct module *me)
|
|||
me->name, *instruction);
|
||||
return 0;
|
||||
}
|
||||
*instruction = 0xe8410028; /* ld r2,40(r1) */
|
||||
/* ld r2,R2_STACK_OFFSET(r1) */
|
||||
*instruction = 0xe8410000 | R2_STACK_OFFSET;
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
@ -357,6 +491,17 @@ int apply_relocate_add(Elf64_Shdr *sechdrs,
|
|||
|
||||
DEBUGP("Applying ADD relocate section %u to %u\n", relsec,
|
||||
sechdrs[relsec].sh_info);
|
||||
|
||||
/* First time we're called, we can fix up .TOC. */
|
||||
if (!me->arch.toc_fixed) {
|
||||
sym = find_dot_toc(sechdrs, strtab, symindex);
|
||||
/* It's theoretically possible that a module doesn't want a
|
||||
* .TOC. so don't fail it just for that. */
|
||||
if (sym)
|
||||
sym->st_value = my_r2(sechdrs, me);
|
||||
me->arch.toc_fixed = true;
|
||||
}
|
||||
|
||||
for (i = 0; i < sechdrs[relsec].sh_size / sizeof(*rela); i++) {
|
||||
/* This is where to make the change */
|
||||
location = (void *)sechdrs[sechdrs[relsec].sh_info].sh_addr
|
||||
|
@ -453,7 +598,8 @@ int apply_relocate_add(Elf64_Shdr *sechdrs,
|
|||
return -ENOENT;
|
||||
if (!restore_r2((u32 *)location + 1, me))
|
||||
return -ENOEXEC;
|
||||
}
|
||||
} else
|
||||
value += local_entry_offset(sym);
|
||||
|
||||
/* Convert value to relative */
|
||||
value -= (unsigned long)location;
|
||||
|
@ -474,6 +620,31 @@ int apply_relocate_add(Elf64_Shdr *sechdrs,
|
|||
*location = value - (unsigned long)location;
|
||||
break;
|
||||
|
||||
case R_PPC64_TOCSAVE:
|
||||
/*
|
||||
* Marker reloc indicates we don't have to save r2.
|
||||
* That would only save us one instruction, so ignore
|
||||
* it.
|
||||
*/
|
||||
break;
|
||||
|
||||
case R_PPC64_REL16_HA:
|
||||
/* Subtract location pointer */
|
||||
value -= (unsigned long)location;
|
||||
value = ((value + 0x8000) >> 16);
|
||||
*((uint16_t *) location)
|
||||
= (*((uint16_t *) location) & ~0xffff)
|
||||
| (value & 0xffff);
|
||||
break;
|
||||
|
||||
case R_PPC64_REL16_LO:
|
||||
/* Subtract location pointer */
|
||||
value -= (unsigned long)location;
|
||||
*((uint16_t *) location)
|
||||
= (*((uint16_t *) location) & ~0xffff)
|
||||
| (value & 0xffff);
|
||||
break;
|
||||
|
||||
default:
|
||||
printk("%s: Unknown ADD relocation: %lu\n",
|
||||
me->name,
|
||||
|
|
|
@ -54,6 +54,7 @@
|
|||
#ifdef CONFIG_PPC64
|
||||
#include <asm/firmware.h>
|
||||
#endif
|
||||
#include <asm/code-patching.h>
|
||||
#include <linux/kprobes.h>
|
||||
#include <linux/kdebug.h>
|
||||
|
||||
|
@ -1108,7 +1109,9 @@ int copy_thread(unsigned long clone_flags, unsigned long usp,
|
|||
struct thread_info *ti = (void *)task_stack_page(p);
|
||||
memset(childregs, 0, sizeof(struct pt_regs));
|
||||
childregs->gpr[1] = sp + sizeof(struct pt_regs);
|
||||
childregs->gpr[14] = usp; /* function */
|
||||
/* function */
|
||||
if (usp)
|
||||
childregs->gpr[14] = ppc_function_entry((void *)usp);
|
||||
#ifdef CONFIG_PPC64
|
||||
clear_tsk_thread_flag(p, TIF_32BIT);
|
||||
childregs->softe = 1;
|
||||
|
@ -1187,17 +1190,7 @@ int copy_thread(unsigned long clone_flags, unsigned long usp,
|
|||
if (cpu_has_feature(CPU_FTR_HAS_PPR))
|
||||
p->thread.ppr = INIT_PPR;
|
||||
#endif
|
||||
/*
|
||||
* The PPC64 ABI makes use of a TOC to contain function
|
||||
* pointers. The function (ret_from_except) is actually a pointer
|
||||
* to the TOC entry. The first entry is a pointer to the actual
|
||||
* function.
|
||||
*/
|
||||
#ifdef CONFIG_PPC64
|
||||
kregs->nip = *((unsigned long *)f);
|
||||
#else
|
||||
kregs->nip = (unsigned long)f;
|
||||
#endif
|
||||
kregs->nip = ppc_function_entry(f);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -23,7 +23,7 @@ strcmp strcpy strlcpy strlen strncmp strstr logo_linux_clut224
|
|||
reloc_got2 kernstart_addr memstart_addr linux_banner _stext
|
||||
opal_query_takeover opal_do_takeover opal_enter_rtas opal_secondary_entry
|
||||
boot_command_line __prom_init_toc_start __prom_init_toc_end
|
||||
btext_setup_display"
|
||||
btext_setup_display TOC."
|
||||
|
||||
NM="$1"
|
||||
OBJ="$2"
|
||||
|
|
|
@ -341,7 +341,7 @@ void smp_release_cpus(void)
|
|||
|
||||
ptr = (unsigned long *)((unsigned long)&__secondary_hold_spinloop
|
||||
- PHYSICAL_START);
|
||||
*ptr = __pa(generic_secondary_smp_init);
|
||||
*ptr = ppc_function_entry(generic_secondary_smp_init);
|
||||
|
||||
/* And wait a bit for them to catch up */
|
||||
for (i = 0; i < 100000; i++) {
|
||||
|
|
|
@ -17,12 +17,12 @@
|
|||
#include <asm/ppc_asm.h>
|
||||
|
||||
#ifdef CONFIG_PPC64
|
||||
#define SYSCALL(func) .llong .sys_##func,.sys_##func
|
||||
#define COMPAT_SYS(func) .llong .sys_##func,.compat_sys_##func
|
||||
#define PPC_SYS(func) .llong .ppc_##func,.ppc_##func
|
||||
#define OLDSYS(func) .llong .sys_ni_syscall,.sys_ni_syscall
|
||||
#define SYS32ONLY(func) .llong .sys_ni_syscall,.compat_sys_##func
|
||||
#define SYSX(f, f3264, f32) .llong .f,.f3264
|
||||
#define SYSCALL(func) .llong DOTSYM(sys_##func),DOTSYM(sys_##func)
|
||||
#define COMPAT_SYS(func) .llong DOTSYM(sys_##func),DOTSYM(compat_sys_##func)
|
||||
#define PPC_SYS(func) .llong DOTSYM(ppc_##func),DOTSYM(ppc_##func)
|
||||
#define OLDSYS(func) .llong DOTSYM(sys_ni_syscall),DOTSYM(sys_ni_syscall)
|
||||
#define SYS32ONLY(func) .llong DOTSYM(sys_ni_syscall),DOTSYM(compat_sys_##func)
|
||||
#define SYSX(f, f3264, f32) .llong DOTSYM(f),DOTSYM(f3264)
|
||||
#else
|
||||
#define SYSCALL(func) .long sys_##func
|
||||
#define COMPAT_SYS(func) .long sys_##func
|
||||
|
@ -36,6 +36,8 @@
|
|||
#define PPC_SYS_SPU(func) PPC_SYS(func)
|
||||
#define SYSX_SPU(f, f3264, f32) SYSX(f, f3264, f32)
|
||||
|
||||
.section .rodata,"a"
|
||||
|
||||
#ifdef CONFIG_PPC64
|
||||
#define sys_sigpending sys_ni_syscall
|
||||
#define sys_old_getrlimit sys_ni_syscall
|
||||
|
@ -43,5 +45,7 @@
|
|||
.p2align 3
|
||||
#endif
|
||||
|
||||
_GLOBAL(sys_call_table)
|
||||
.globl sys_call_table
|
||||
sys_call_table:
|
||||
|
||||
#include <asm/systbl.h>
|
||||
|
|
|
@ -42,7 +42,6 @@ END_FTR_SECTION_IFSET(CPU_FTR_VSX); \
|
|||
/* Stack frame offsets for local variables. */
|
||||
#define TM_FRAME_L0 TM_FRAME_SIZE-16
|
||||
#define TM_FRAME_L1 TM_FRAME_SIZE-8
|
||||
#define STACK_PARAM(x) (48+((x)*8))
|
||||
|
||||
|
||||
/* In order to access the TM SPRs, TM must be enabled. So, do so: */
|
||||
|
@ -109,12 +108,12 @@ _GLOBAL(tm_reclaim)
|
|||
mflr r0
|
||||
stw r6, 8(r1)
|
||||
std r0, 16(r1)
|
||||
std r2, 40(r1)
|
||||
std r2, STK_GOT(r1)
|
||||
stdu r1, -TM_FRAME_SIZE(r1)
|
||||
|
||||
/* We've a struct pt_regs at [r1+STACK_FRAME_OVERHEAD]. */
|
||||
|
||||
std r3, STACK_PARAM(0)(r1)
|
||||
std r3, STK_PARAM(R3)(r1)
|
||||
SAVE_NVGPRS(r1)
|
||||
|
||||
/* We need to setup MSR for VSX register save instructions. Here we
|
||||
|
@ -210,7 +209,7 @@ dont_backup_fp:
|
|||
/* Now get some more GPRS free */
|
||||
std r7, GPR7(r1) /* Temporary stash */
|
||||
std r12, GPR12(r1) /* '' '' '' */
|
||||
ld r12, STACK_PARAM(0)(r1) /* Param 0, thread_struct * */
|
||||
ld r12, STK_PARAM(R3)(r1) /* Param 0, thread_struct * */
|
||||
|
||||
std r11, THREAD_TM_PPR(r12) /* Store PPR and free r11 */
|
||||
|
||||
|
@ -297,7 +296,7 @@ dont_backup_fp:
|
|||
ld r0, 16(r1)
|
||||
mtcr r4
|
||||
mtlr r0
|
||||
ld r2, 40(r1)
|
||||
ld r2, STK_GOT(r1)
|
||||
|
||||
/* Load system default DSCR */
|
||||
ld r4, DSCR_DEFAULT@toc(r2)
|
||||
|
@ -320,7 +319,7 @@ _GLOBAL(__tm_recheckpoint)
|
|||
mflr r0
|
||||
stw r5, 8(r1)
|
||||
std r0, 16(r1)
|
||||
std r2, 40(r1)
|
||||
std r2, STK_GOT(r1)
|
||||
stdu r1, -TM_FRAME_SIZE(r1)
|
||||
|
||||
/* We've a struct pt_regs at [r1+STACK_FRAME_OVERHEAD].
|
||||
|
@ -478,7 +477,7 @@ restore_gprs:
|
|||
ld r0, 16(r1)
|
||||
mtcr r4
|
||||
mtlr r0
|
||||
ld r2, 40(r1)
|
||||
ld r2, STK_GOT(r1)
|
||||
|
||||
/* Load system default DSCR */
|
||||
ld r4, DSCR_DEFAULT@toc(r2)
|
||||
|
|
|
@ -171,7 +171,7 @@ END_FTR_SECTION_IFSET(CPU_FTR_ARCH_201)
|
|||
#endif /* CONFIG_SMP */
|
||||
|
||||
/* Jump to partition switch code */
|
||||
bl .kvmppc_hv_entry_trampoline
|
||||
bl kvmppc_hv_entry_trampoline
|
||||
nop
|
||||
|
||||
/*
|
||||
|
|
|
@ -1658,7 +1658,7 @@ kvmppc_hdsi:
|
|||
/* Search the hash table. */
|
||||
mr r3, r9 /* vcpu pointer */
|
||||
li r7, 1 /* data fault */
|
||||
bl .kvmppc_hpte_hv_fault
|
||||
bl kvmppc_hpte_hv_fault
|
||||
ld r9, HSTATE_KVM_VCPU(r13)
|
||||
ld r10, VCPU_PC(r9)
|
||||
ld r11, VCPU_MSR(r9)
|
||||
|
@ -1732,7 +1732,7 @@ kvmppc_hisi:
|
|||
mr r4, r10
|
||||
mr r6, r11
|
||||
li r7, 0 /* instruction fault */
|
||||
bl .kvmppc_hpte_hv_fault
|
||||
bl kvmppc_hpte_hv_fault
|
||||
ld r9, HSTATE_KVM_VCPU(r13)
|
||||
ld r10, VCPU_PC(r9)
|
||||
ld r11, VCPU_MSR(r9)
|
||||
|
@ -1806,16 +1806,16 @@ hcall_real_fallback:
|
|||
.globl hcall_real_table
|
||||
hcall_real_table:
|
||||
.long 0 /* 0 - unused */
|
||||
.long .kvmppc_h_remove - hcall_real_table
|
||||
.long .kvmppc_h_enter - hcall_real_table
|
||||
.long .kvmppc_h_read - hcall_real_table
|
||||
.long DOTSYM(kvmppc_h_remove) - hcall_real_table
|
||||
.long DOTSYM(kvmppc_h_enter) - hcall_real_table
|
||||
.long DOTSYM(kvmppc_h_read) - hcall_real_table
|
||||
.long 0 /* 0x10 - H_CLEAR_MOD */
|
||||
.long 0 /* 0x14 - H_CLEAR_REF */
|
||||
.long .kvmppc_h_protect - hcall_real_table
|
||||
.long .kvmppc_h_get_tce - hcall_real_table
|
||||
.long .kvmppc_h_put_tce - hcall_real_table
|
||||
.long DOTSYM(kvmppc_h_protect) - hcall_real_table
|
||||
.long DOTSYM(kvmppc_h_get_tce) - hcall_real_table
|
||||
.long DOTSYM(kvmppc_h_put_tce) - hcall_real_table
|
||||
.long 0 /* 0x24 - H_SET_SPRG0 */
|
||||
.long .kvmppc_h_set_dabr - hcall_real_table
|
||||
.long DOTSYM(kvmppc_h_set_dabr) - hcall_real_table
|
||||
.long 0 /* 0x2c */
|
||||
.long 0 /* 0x30 */
|
||||
.long 0 /* 0x34 */
|
||||
|
@ -1831,11 +1831,11 @@ hcall_real_table:
|
|||
.long 0 /* 0x5c */
|
||||
.long 0 /* 0x60 */
|
||||
#ifdef CONFIG_KVM_XICS
|
||||
.long .kvmppc_rm_h_eoi - hcall_real_table
|
||||
.long .kvmppc_rm_h_cppr - hcall_real_table
|
||||
.long .kvmppc_rm_h_ipi - hcall_real_table
|
||||
.long DOTSYM(kvmppc_rm_h_eoi) - hcall_real_table
|
||||
.long DOTSYM(kvmppc_rm_h_cppr) - hcall_real_table
|
||||
.long DOTSYM(kvmppc_rm_h_ipi) - hcall_real_table
|
||||
.long 0 /* 0x70 - H_IPOLL */
|
||||
.long .kvmppc_rm_h_xirr - hcall_real_table
|
||||
.long DOTSYM(kvmppc_rm_h_xirr) - hcall_real_table
|
||||
#else
|
||||
.long 0 /* 0x64 - H_EOI */
|
||||
.long 0 /* 0x68 - H_CPPR */
|
||||
|
@ -1869,7 +1869,7 @@ hcall_real_table:
|
|||
.long 0 /* 0xd4 */
|
||||
.long 0 /* 0xd8 */
|
||||
.long 0 /* 0xdc */
|
||||
.long .kvmppc_h_cede - hcall_real_table
|
||||
.long DOTSYM(kvmppc_h_cede) - hcall_real_table
|
||||
.long 0 /* 0xe4 */
|
||||
.long 0 /* 0xe8 */
|
||||
.long 0 /* 0xec */
|
||||
|
@ -1886,11 +1886,11 @@ hcall_real_table:
|
|||
.long 0 /* 0x118 */
|
||||
.long 0 /* 0x11c */
|
||||
.long 0 /* 0x120 */
|
||||
.long .kvmppc_h_bulk_remove - hcall_real_table
|
||||
.long DOTSYM(kvmppc_h_bulk_remove) - hcall_real_table
|
||||
.long 0 /* 0x128 */
|
||||
.long 0 /* 0x12c */
|
||||
.long 0 /* 0x130 */
|
||||
.long .kvmppc_h_set_xdabr - hcall_real_table
|
||||
.long DOTSYM(kvmppc_h_set_xdabr) - hcall_real_table
|
||||
hcall_real_table_end:
|
||||
|
||||
ignore_hdec:
|
||||
|
@ -2115,7 +2115,7 @@ kvm_cede_exit:
|
|||
/* Try to handle a machine check in real mode */
|
||||
machine_check_realmode:
|
||||
mr r3, r9 /* get vcpu pointer */
|
||||
bl .kvmppc_realmode_machine_check
|
||||
bl kvmppc_realmode_machine_check
|
||||
nop
|
||||
cmpdi r3, 0 /* continue exiting from guest? */
|
||||
ld r9, HSTATE_KVM_VCPU(r13)
|
||||
|
|
|
@ -20,7 +20,7 @@ _GLOBAL(copy_page)
|
|||
BEGIN_FTR_SECTION
|
||||
lis r5,PAGE_SIZE@h
|
||||
FTR_SECTION_ELSE
|
||||
b .copypage_power7
|
||||
b copypage_power7
|
||||
ALT_FTR_SECTION_END_IFCLR(CPU_FTR_VMX_COPY)
|
||||
ori r5,r5,PAGE_SIZE@l
|
||||
BEGIN_FTR_SECTION
|
||||
|
|
|
@ -56,15 +56,15 @@ _GLOBAL(copypage_power7)
|
|||
|
||||
#ifdef CONFIG_ALTIVEC
|
||||
mflr r0
|
||||
std r3,48(r1)
|
||||
std r4,56(r1)
|
||||
std r3,-STACKFRAMESIZE+STK_REG(R31)(r1)
|
||||
std r4,-STACKFRAMESIZE+STK_REG(R30)(r1)
|
||||
std r0,16(r1)
|
||||
stdu r1,-STACKFRAMESIZE(r1)
|
||||
bl .enter_vmx_copy
|
||||
bl enter_vmx_copy
|
||||
cmpwi r3,0
|
||||
ld r0,STACKFRAMESIZE+16(r1)
|
||||
ld r3,STACKFRAMESIZE+48(r1)
|
||||
ld r4,STACKFRAMESIZE+56(r1)
|
||||
ld r3,STK_REG(R31)(r1)
|
||||
ld r4,STK_REG(R30)(r1)
|
||||
mtlr r0
|
||||
|
||||
li r0,(PAGE_SIZE/128)
|
||||
|
@ -103,7 +103,7 @@ _GLOBAL(copypage_power7)
|
|||
addi r3,r3,128
|
||||
bdnz 1b
|
||||
|
||||
b .exit_vmx_copy /* tail call optimise */
|
||||
b exit_vmx_copy /* tail call optimise */
|
||||
|
||||
#else
|
||||
li r0,(PAGE_SIZE/128)
|
||||
|
|
|
@ -18,7 +18,7 @@
|
|||
#endif
|
||||
|
||||
.align 7
|
||||
_GLOBAL(__copy_tofrom_user)
|
||||
_GLOBAL_TOC(__copy_tofrom_user)
|
||||
BEGIN_FTR_SECTION
|
||||
nop
|
||||
FTR_SECTION_ELSE
|
||||
|
|
|
@ -66,7 +66,7 @@
|
|||
ld r15,STK_REG(R15)(r1)
|
||||
ld r14,STK_REG(R14)(r1)
|
||||
.Ldo_err3:
|
||||
bl .exit_vmx_usercopy
|
||||
bl exit_vmx_usercopy
|
||||
ld r0,STACKFRAMESIZE+16(r1)
|
||||
mtlr r0
|
||||
b .Lexit
|
||||
|
@ -85,9 +85,9 @@
|
|||
.Lexit:
|
||||
addi r1,r1,STACKFRAMESIZE
|
||||
.Ldo_err1:
|
||||
ld r3,48(r1)
|
||||
ld r4,56(r1)
|
||||
ld r5,64(r1)
|
||||
ld r3,-STACKFRAMESIZE+STK_REG(R31)(r1)
|
||||
ld r4,-STACKFRAMESIZE+STK_REG(R30)(r1)
|
||||
ld r5,-STACKFRAMESIZE+STK_REG(R29)(r1)
|
||||
b __copy_tofrom_user_base
|
||||
|
||||
|
||||
|
@ -96,18 +96,18 @@ _GLOBAL(__copy_tofrom_user_power7)
|
|||
cmpldi r5,16
|
||||
cmpldi cr1,r5,4096
|
||||
|
||||
std r3,48(r1)
|
||||
std r4,56(r1)
|
||||
std r5,64(r1)
|
||||
std r3,-STACKFRAMESIZE+STK_REG(R31)(r1)
|
||||
std r4,-STACKFRAMESIZE+STK_REG(R30)(r1)
|
||||
std r5,-STACKFRAMESIZE+STK_REG(R29)(r1)
|
||||
|
||||
blt .Lshort_copy
|
||||
bgt cr1,.Lvmx_copy
|
||||
#else
|
||||
cmpldi r5,16
|
||||
|
||||
std r3,48(r1)
|
||||
std r4,56(r1)
|
||||
std r5,64(r1)
|
||||
std r3,-STACKFRAMESIZE+STK_REG(R31)(r1)
|
||||
std r4,-STACKFRAMESIZE+STK_REG(R30)(r1)
|
||||
std r5,-STACKFRAMESIZE+STK_REG(R29)(r1)
|
||||
|
||||
blt .Lshort_copy
|
||||
#endif
|
||||
|
@ -295,12 +295,12 @@ err1; stb r0,0(r3)
|
|||
mflr r0
|
||||
std r0,16(r1)
|
||||
stdu r1,-STACKFRAMESIZE(r1)
|
||||
bl .enter_vmx_usercopy
|
||||
bl enter_vmx_usercopy
|
||||
cmpwi cr1,r3,0
|
||||
ld r0,STACKFRAMESIZE+16(r1)
|
||||
ld r3,STACKFRAMESIZE+48(r1)
|
||||
ld r4,STACKFRAMESIZE+56(r1)
|
||||
ld r5,STACKFRAMESIZE+64(r1)
|
||||
ld r3,STK_REG(R31)(r1)
|
||||
ld r4,STK_REG(R30)(r1)
|
||||
ld r5,STK_REG(R29)(r1)
|
||||
mtlr r0
|
||||
|
||||
/*
|
||||
|
@ -514,7 +514,7 @@ err3; lbz r0,0(r4)
|
|||
err3; stb r0,0(r3)
|
||||
|
||||
15: addi r1,r1,STACKFRAMESIZE
|
||||
b .exit_vmx_usercopy /* tail call optimise */
|
||||
b exit_vmx_usercopy /* tail call optimise */
|
||||
|
||||
.Lvmx_unaligned_copy:
|
||||
/* Get the destination 16B aligned */
|
||||
|
@ -717,5 +717,5 @@ err3; lbz r0,0(r4)
|
|||
err3; stb r0,0(r3)
|
||||
|
||||
15: addi r1,r1,STACKFRAMESIZE
|
||||
b .exit_vmx_usercopy /* tail call optimise */
|
||||
b exit_vmx_usercopy /* tail call optimise */
|
||||
#endif /* CONFiG_ALTIVEC */
|
||||
|
|
|
@ -24,7 +24,7 @@
|
|||
|
||||
_GLOBAL(__arch_hweight8)
|
||||
BEGIN_FTR_SECTION
|
||||
b .__sw_hweight8
|
||||
b __sw_hweight8
|
||||
nop
|
||||
nop
|
||||
FTR_SECTION_ELSE
|
||||
|
@ -35,7 +35,7 @@ ALT_FTR_SECTION_END_IFCLR(CPU_FTR_POPCNTB)
|
|||
|
||||
_GLOBAL(__arch_hweight16)
|
||||
BEGIN_FTR_SECTION
|
||||
b .__sw_hweight16
|
||||
b __sw_hweight16
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
|
@ -57,7 +57,7 @@ ALT_FTR_SECTION_END_IFCLR(CPU_FTR_POPCNTB)
|
|||
|
||||
_GLOBAL(__arch_hweight32)
|
||||
BEGIN_FTR_SECTION
|
||||
b .__sw_hweight32
|
||||
b __sw_hweight32
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
|
@ -82,7 +82,7 @@ ALT_FTR_SECTION_END_IFCLR(CPU_FTR_POPCNTB)
|
|||
|
||||
_GLOBAL(__arch_hweight64)
|
||||
BEGIN_FTR_SECTION
|
||||
b .__sw_hweight64
|
||||
b __sw_hweight64
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
|
|
|
@ -79,8 +79,8 @@ _GLOBAL(memset)
|
|||
|
||||
_GLOBAL(memmove)
|
||||
cmplw 0,r3,r4
|
||||
bgt .backwards_memcpy
|
||||
b .memcpy
|
||||
bgt backwards_memcpy
|
||||
b memcpy
|
||||
|
||||
_GLOBAL(backwards_memcpy)
|
||||
rlwinm. r7,r5,32-3,3,31 /* r0 = r5 >> 3 */
|
||||
|
|
|
@ -10,12 +10,12 @@
|
|||
#include <asm/ppc_asm.h>
|
||||
|
||||
.align 7
|
||||
_GLOBAL(memcpy)
|
||||
_GLOBAL_TOC(memcpy)
|
||||
BEGIN_FTR_SECTION
|
||||
#ifdef __LITTLE_ENDIAN__
|
||||
cmpdi cr7,r5,0
|
||||
#else
|
||||
std r3,48(r1) /* save destination pointer for return value */
|
||||
std r3,-STACKFRAMESIZE+STK_REG(R31)(r1) /* save destination pointer for return value */
|
||||
#endif
|
||||
FTR_SECTION_ELSE
|
||||
#ifndef SELFTEST
|
||||
|
@ -88,7 +88,7 @@ END_FTR_SECTION_IFCLR(CPU_FTR_UNALIGNED_LD_STD)
|
|||
2: bf cr7*4+3,3f
|
||||
lbz r9,8(r4)
|
||||
stb r9,0(r3)
|
||||
3: ld r3,48(r1) /* return dest pointer */
|
||||
3: ld r3,-STACKFRAMESIZE+STK_REG(R31)(r1) /* return dest pointer */
|
||||
blr
|
||||
|
||||
.Lsrc_unaligned:
|
||||
|
@ -171,7 +171,7 @@ END_FTR_SECTION_IFCLR(CPU_FTR_UNALIGNED_LD_STD)
|
|||
2: bf cr7*4+3,3f
|
||||
rotldi r9,r9,8
|
||||
stb r9,0(r3)
|
||||
3: ld r3,48(r1) /* return dest pointer */
|
||||
3: ld r3,-STACKFRAMESIZE+STK_REG(R31)(r1) /* return dest pointer */
|
||||
blr
|
||||
|
||||
.Ldst_unaligned:
|
||||
|
@ -216,6 +216,6 @@ END_FTR_SECTION_IFCLR(CPU_FTR_UNALIGNED_LD_STD)
|
|||
3: bf cr7*4+3,4f
|
||||
lbz r0,0(r4)
|
||||
stb r0,0(r3)
|
||||
4: ld r3,48(r1) /* return dest pointer */
|
||||
4: ld r3,-STACKFRAMESIZE+STK_REG(R31)(r1) /* return dest pointer */
|
||||
blr
|
||||
#endif
|
||||
|
|
|
@ -33,14 +33,14 @@ _GLOBAL(memcpy_power7)
|
|||
cmpldi r5,16
|
||||
cmpldi cr1,r5,4096
|
||||
|
||||
std r3,48(r1)
|
||||
std r3,-STACKFRAMESIZE+STK_REG(R31)(r1)
|
||||
|
||||
blt .Lshort_copy
|
||||
bgt cr1,.Lvmx_copy
|
||||
#else
|
||||
cmpldi r5,16
|
||||
|
||||
std r3,48(r1)
|
||||
std r3,-STACKFRAMESIZE+STK_REG(R31)(r1)
|
||||
|
||||
blt .Lshort_copy
|
||||
#endif
|
||||
|
@ -216,7 +216,7 @@ _GLOBAL(memcpy_power7)
|
|||
lbz r0,0(r4)
|
||||
stb r0,0(r3)
|
||||
|
||||
15: ld r3,48(r1)
|
||||
15: ld r3,-STACKFRAMESIZE+STK_REG(R31)(r1)
|
||||
blr
|
||||
|
||||
.Lunwind_stack_nonvmx_copy:
|
||||
|
@ -226,16 +226,16 @@ _GLOBAL(memcpy_power7)
|
|||
#ifdef CONFIG_ALTIVEC
|
||||
.Lvmx_copy:
|
||||
mflr r0
|
||||
std r4,56(r1)
|
||||
std r5,64(r1)
|
||||
std r4,-STACKFRAMESIZE+STK_REG(R30)(r1)
|
||||
std r5,-STACKFRAMESIZE+STK_REG(R29)(r1)
|
||||
std r0,16(r1)
|
||||
stdu r1,-STACKFRAMESIZE(r1)
|
||||
bl .enter_vmx_copy
|
||||
bl enter_vmx_copy
|
||||
cmpwi cr1,r3,0
|
||||
ld r0,STACKFRAMESIZE+16(r1)
|
||||
ld r3,STACKFRAMESIZE+48(r1)
|
||||
ld r4,STACKFRAMESIZE+56(r1)
|
||||
ld r5,STACKFRAMESIZE+64(r1)
|
||||
ld r3,STK_REG(R31)(r1)
|
||||
ld r4,STK_REG(R30)(r1)
|
||||
ld r5,STK_REG(R29)(r1)
|
||||
mtlr r0
|
||||
|
||||
/*
|
||||
|
@ -447,8 +447,8 @@ _GLOBAL(memcpy_power7)
|
|||
stb r0,0(r3)
|
||||
|
||||
15: addi r1,r1,STACKFRAMESIZE
|
||||
ld r3,48(r1)
|
||||
b .exit_vmx_copy /* tail call optimise */
|
||||
ld r3,-STACKFRAMESIZE+STK_REG(R31)(r1)
|
||||
b exit_vmx_copy /* tail call optimise */
|
||||
|
||||
.Lvmx_unaligned_copy:
|
||||
/* Get the destination 16B aligned */
|
||||
|
@ -651,6 +651,6 @@ _GLOBAL(memcpy_power7)
|
|||
stb r0,0(r3)
|
||||
|
||||
15: addi r1,r1,STACKFRAMESIZE
|
||||
ld r3,48(r1)
|
||||
b .exit_vmx_copy /* tail call optimise */
|
||||
ld r3,-STACKFRAMESIZE+STK_REG(R31)(r1)
|
||||
b exit_vmx_copy /* tail call optimise */
|
||||
#endif /* CONFiG_ALTIVEC */
|
||||
|
|
|
@ -159,7 +159,7 @@ END_MMU_FTR_SECTION_IFSET(MMU_FTR_1T_SEGMENT)
|
|||
BEGIN_FTR_SECTION
|
||||
mr r4,r30
|
||||
mr r5,r7
|
||||
bl .hash_page_do_lazy_icache
|
||||
bl hash_page_do_lazy_icache
|
||||
END_FTR_SECTION(CPU_FTR_NOEXECUTE|CPU_FTR_COHERENT_ICACHE, CPU_FTR_NOEXECUTE)
|
||||
|
||||
/* At this point, r3 contains new PP bits, save them in
|
||||
|
@ -201,7 +201,8 @@ htab_insert_pte:
|
|||
li r8,MMU_PAGE_4K /* page size */
|
||||
li r9,MMU_PAGE_4K /* actual page size */
|
||||
ld r10,STK_PARAM(R9)(r1) /* segment size */
|
||||
_GLOBAL(htab_call_hpte_insert1)
|
||||
.globl htab_call_hpte_insert1
|
||||
htab_call_hpte_insert1:
|
||||
bl . /* Patched by htab_finish_init() */
|
||||
cmpdi 0,r3,0
|
||||
bge htab_pte_insert_ok /* Insertion successful */
|
||||
|
@ -225,7 +226,8 @@ _GLOBAL(htab_call_hpte_insert1)
|
|||
li r8,MMU_PAGE_4K /* page size */
|
||||
li r9,MMU_PAGE_4K /* actual page size */
|
||||
ld r10,STK_PARAM(R9)(r1) /* segment size */
|
||||
_GLOBAL(htab_call_hpte_insert2)
|
||||
.globl htab_call_hpte_insert2
|
||||
htab_call_hpte_insert2:
|
||||
bl . /* Patched by htab_finish_init() */
|
||||
cmpdi 0,r3,0
|
||||
bge+ htab_pte_insert_ok /* Insertion successful */
|
||||
|
@ -242,7 +244,8 @@ _GLOBAL(htab_call_hpte_insert2)
|
|||
2: and r0,r5,r27
|
||||
rldicr r3,r0,3,63-3 /* r0 = (hash & mask) << 3 */
|
||||
/* Call ppc_md.hpte_remove */
|
||||
_GLOBAL(htab_call_hpte_remove)
|
||||
.globl htab_call_hpte_remove
|
||||
htab_call_hpte_remove:
|
||||
bl . /* Patched by htab_finish_init() */
|
||||
|
||||
/* Try all again */
|
||||
|
@ -296,7 +299,8 @@ htab_modify_pte:
|
|||
li r7,MMU_PAGE_4K /* actual page size */
|
||||
ld r8,STK_PARAM(R9)(r1) /* segment size */
|
||||
ld r9,STK_PARAM(R8)(r1) /* get "local" param */
|
||||
_GLOBAL(htab_call_hpte_updatepp)
|
||||
.globl htab_call_hpte_updatepp
|
||||
htab_call_hpte_updatepp:
|
||||
bl . /* Patched by htab_finish_init() */
|
||||
|
||||
/* if we failed because typically the HPTE wasn't really here
|
||||
|
@ -471,7 +475,7 @@ END_MMU_FTR_SECTION_IFSET(MMU_FTR_1T_SEGMENT)
|
|||
BEGIN_FTR_SECTION
|
||||
mr r4,r30
|
||||
mr r5,r7
|
||||
bl .hash_page_do_lazy_icache
|
||||
bl hash_page_do_lazy_icache
|
||||
END_FTR_SECTION(CPU_FTR_NOEXECUTE|CPU_FTR_COHERENT_ICACHE, CPU_FTR_NOEXECUTE)
|
||||
|
||||
/* At this point, r3 contains new PP bits, save them in
|
||||
|
@ -526,7 +530,8 @@ htab_special_pfn:
|
|||
li r8,MMU_PAGE_4K /* page size */
|
||||
li r9,MMU_PAGE_4K /* actual page size */
|
||||
ld r10,STK_PARAM(R9)(r1) /* segment size */
|
||||
_GLOBAL(htab_call_hpte_insert1)
|
||||
.globl htab_call_hpte_insert1
|
||||
htab_call_hpte_insert1:
|
||||
bl . /* patched by htab_finish_init() */
|
||||
cmpdi 0,r3,0
|
||||
bge htab_pte_insert_ok /* Insertion successful */
|
||||
|
@ -554,7 +559,8 @@ _GLOBAL(htab_call_hpte_insert1)
|
|||
li r8,MMU_PAGE_4K /* page size */
|
||||
li r9,MMU_PAGE_4K /* actual page size */
|
||||
ld r10,STK_PARAM(R9)(r1) /* segment size */
|
||||
_GLOBAL(htab_call_hpte_insert2)
|
||||
.globl htab_call_hpte_insert2
|
||||
htab_call_hpte_insert2:
|
||||
bl . /* patched by htab_finish_init() */
|
||||
cmpdi 0,r3,0
|
||||
bge+ htab_pte_insert_ok /* Insertion successful */
|
||||
|
@ -571,7 +577,8 @@ _GLOBAL(htab_call_hpte_insert2)
|
|||
2: and r0,r5,r27
|
||||
rldicr r3,r0,3,63-3 /* r0 = (hash & mask) << 3 */
|
||||
/* Call ppc_md.hpte_remove */
|
||||
_GLOBAL(htab_call_hpte_remove)
|
||||
.globl htab_call_hpte_remove
|
||||
htab_call_hpte_remove:
|
||||
bl . /* patched by htab_finish_init() */
|
||||
|
||||
/* Try all again */
|
||||
|
@ -588,7 +595,7 @@ htab_inval_old_hpte:
|
|||
li r6,MMU_PAGE_64K /* psize */
|
||||
ld r7,STK_PARAM(R9)(r1) /* ssize */
|
||||
ld r8,STK_PARAM(R8)(r1) /* local */
|
||||
bl .flush_hash_page
|
||||
bl flush_hash_page
|
||||
/* Clear out _PAGE_HPTE_SUB bits in the new linux PTE */
|
||||
lis r0,_PAGE_HPTE_SUB@h
|
||||
ori r0,r0,_PAGE_HPTE_SUB@l
|
||||
|
@ -660,7 +667,8 @@ htab_modify_pte:
|
|||
li r7,MMU_PAGE_4K /* actual page size */
|
||||
ld r8,STK_PARAM(R9)(r1) /* segment size */
|
||||
ld r9,STK_PARAM(R8)(r1) /* get "local" param */
|
||||
_GLOBAL(htab_call_hpte_updatepp)
|
||||
.globl htab_call_hpte_updatepp
|
||||
htab_call_hpte_updatepp:
|
||||
bl . /* patched by htab_finish_init() */
|
||||
|
||||
/* if we failed because typically the HPTE wasn't really here
|
||||
|
@ -812,7 +820,7 @@ END_MMU_FTR_SECTION_IFSET(MMU_FTR_1T_SEGMENT)
|
|||
BEGIN_FTR_SECTION
|
||||
mr r4,r30
|
||||
mr r5,r7
|
||||
bl .hash_page_do_lazy_icache
|
||||
bl hash_page_do_lazy_icache
|
||||
END_FTR_SECTION(CPU_FTR_NOEXECUTE|CPU_FTR_COHERENT_ICACHE, CPU_FTR_NOEXECUTE)
|
||||
|
||||
/* At this point, r3 contains new PP bits, save them in
|
||||
|
@ -857,7 +865,8 @@ ht64_insert_pte:
|
|||
li r8,MMU_PAGE_64K
|
||||
li r9,MMU_PAGE_64K /* actual page size */
|
||||
ld r10,STK_PARAM(R9)(r1) /* segment size */
|
||||
_GLOBAL(ht64_call_hpte_insert1)
|
||||
.globl ht64_call_hpte_insert1
|
||||
ht64_call_hpte_insert1:
|
||||
bl . /* patched by htab_finish_init() */
|
||||
cmpdi 0,r3,0
|
||||
bge ht64_pte_insert_ok /* Insertion successful */
|
||||
|
@ -881,7 +890,8 @@ _GLOBAL(ht64_call_hpte_insert1)
|
|||
li r8,MMU_PAGE_64K
|
||||
li r9,MMU_PAGE_64K /* actual page size */
|
||||
ld r10,STK_PARAM(R9)(r1) /* segment size */
|
||||
_GLOBAL(ht64_call_hpte_insert2)
|
||||
.globl ht64_call_hpte_insert2
|
||||
ht64_call_hpte_insert2:
|
||||
bl . /* patched by htab_finish_init() */
|
||||
cmpdi 0,r3,0
|
||||
bge+ ht64_pte_insert_ok /* Insertion successful */
|
||||
|
@ -898,7 +908,8 @@ _GLOBAL(ht64_call_hpte_insert2)
|
|||
2: and r0,r5,r27
|
||||
rldicr r3,r0,3,63-3 /* r0 = (hash & mask) << 3 */
|
||||
/* Call ppc_md.hpte_remove */
|
||||
_GLOBAL(ht64_call_hpte_remove)
|
||||
.globl ht64_call_hpte_remove
|
||||
ht64_call_hpte_remove:
|
||||
bl . /* patched by htab_finish_init() */
|
||||
|
||||
/* Try all again */
|
||||
|
@ -952,7 +963,8 @@ ht64_modify_pte:
|
|||
li r7,MMU_PAGE_64K /* actual page size */
|
||||
ld r8,STK_PARAM(R9)(r1) /* segment size */
|
||||
ld r9,STK_PARAM(R8)(r1) /* get "local" param */
|
||||
_GLOBAL(ht64_call_hpte_updatepp)
|
||||
.globl ht64_call_hpte_updatepp
|
||||
ht64_call_hpte_updatepp:
|
||||
bl . /* patched by htab_finish_init() */
|
||||
|
||||
/* if we failed because typically the HPTE wasn't really here
|
||||
|
|
|
@ -622,47 +622,43 @@ int remove_section_mapping(unsigned long start, unsigned long end)
|
|||
}
|
||||
#endif /* CONFIG_MEMORY_HOTPLUG */
|
||||
|
||||
#define FUNCTION_TEXT(A) ((*(unsigned long *)(A)))
|
||||
extern u32 htab_call_hpte_insert1[];
|
||||
extern u32 htab_call_hpte_insert2[];
|
||||
extern u32 htab_call_hpte_remove[];
|
||||
extern u32 htab_call_hpte_updatepp[];
|
||||
extern u32 ht64_call_hpte_insert1[];
|
||||
extern u32 ht64_call_hpte_insert2[];
|
||||
extern u32 ht64_call_hpte_remove[];
|
||||
extern u32 ht64_call_hpte_updatepp[];
|
||||
|
||||
static void __init htab_finish_init(void)
|
||||
{
|
||||
extern unsigned int *htab_call_hpte_insert1;
|
||||
extern unsigned int *htab_call_hpte_insert2;
|
||||
extern unsigned int *htab_call_hpte_remove;
|
||||
extern unsigned int *htab_call_hpte_updatepp;
|
||||
|
||||
#ifdef CONFIG_PPC_HAS_HASH_64K
|
||||
extern unsigned int *ht64_call_hpte_insert1;
|
||||
extern unsigned int *ht64_call_hpte_insert2;
|
||||
extern unsigned int *ht64_call_hpte_remove;
|
||||
extern unsigned int *ht64_call_hpte_updatepp;
|
||||
|
||||
patch_branch(ht64_call_hpte_insert1,
|
||||
FUNCTION_TEXT(ppc_md.hpte_insert),
|
||||
ppc_function_entry(ppc_md.hpte_insert),
|
||||
BRANCH_SET_LINK);
|
||||
patch_branch(ht64_call_hpte_insert2,
|
||||
FUNCTION_TEXT(ppc_md.hpte_insert),
|
||||
ppc_function_entry(ppc_md.hpte_insert),
|
||||
BRANCH_SET_LINK);
|
||||
patch_branch(ht64_call_hpte_remove,
|
||||
FUNCTION_TEXT(ppc_md.hpte_remove),
|
||||
ppc_function_entry(ppc_md.hpte_remove),
|
||||
BRANCH_SET_LINK);
|
||||
patch_branch(ht64_call_hpte_updatepp,
|
||||
FUNCTION_TEXT(ppc_md.hpte_updatepp),
|
||||
ppc_function_entry(ppc_md.hpte_updatepp),
|
||||
BRANCH_SET_LINK);
|
||||
|
||||
#endif /* CONFIG_PPC_HAS_HASH_64K */
|
||||
|
||||
patch_branch(htab_call_hpte_insert1,
|
||||
FUNCTION_TEXT(ppc_md.hpte_insert),
|
||||
ppc_function_entry(ppc_md.hpte_insert),
|
||||
BRANCH_SET_LINK);
|
||||
patch_branch(htab_call_hpte_insert2,
|
||||
FUNCTION_TEXT(ppc_md.hpte_insert),
|
||||
ppc_function_entry(ppc_md.hpte_insert),
|
||||
BRANCH_SET_LINK);
|
||||
patch_branch(htab_call_hpte_remove,
|
||||
FUNCTION_TEXT(ppc_md.hpte_remove),
|
||||
ppc_function_entry(ppc_md.hpte_remove),
|
||||
BRANCH_SET_LINK);
|
||||
patch_branch(htab_call_hpte_updatepp,
|
||||
FUNCTION_TEXT(ppc_md.hpte_updatepp),
|
||||
ppc_function_entry(ppc_md.hpte_updatepp),
|
||||
BRANCH_SET_LINK);
|
||||
}
|
||||
|
||||
|
|
|
@ -256,10 +256,14 @@ static inline void patch_slb_encoding(unsigned int *insn_addr,
|
|||
patch_instruction(insn_addr, insn);
|
||||
}
|
||||
|
||||
extern u32 slb_compare_rr_to_size[];
|
||||
extern u32 slb_miss_kernel_load_linear[];
|
||||
extern u32 slb_miss_kernel_load_io[];
|
||||
extern u32 slb_compare_rr_to_size[];
|
||||
extern u32 slb_miss_kernel_load_vmemmap[];
|
||||
|
||||
void slb_set_size(u16 size)
|
||||
{
|
||||
extern unsigned int *slb_compare_rr_to_size;
|
||||
|
||||
if (mmu_slb_size == size)
|
||||
return;
|
||||
|
||||
|
@ -272,11 +276,7 @@ void slb_initialize(void)
|
|||
unsigned long linear_llp, vmalloc_llp, io_llp;
|
||||
unsigned long lflags, vflags;
|
||||
static int slb_encoding_inited;
|
||||
extern unsigned int *slb_miss_kernel_load_linear;
|
||||
extern unsigned int *slb_miss_kernel_load_io;
|
||||
extern unsigned int *slb_compare_rr_to_size;
|
||||
#ifdef CONFIG_SPARSEMEM_VMEMMAP
|
||||
extern unsigned int *slb_miss_kernel_load_vmemmap;
|
||||
unsigned long vmemmap_llp;
|
||||
#endif
|
||||
|
||||
|
|
|
@ -59,7 +59,8 @@ _GLOBAL(slb_allocate_realmode)
|
|||
/* Linear mapping encoding bits, the "li" instruction below will
|
||||
* be patched by the kernel at boot
|
||||
*/
|
||||
_GLOBAL(slb_miss_kernel_load_linear)
|
||||
.globl slb_miss_kernel_load_linear
|
||||
slb_miss_kernel_load_linear:
|
||||
li r11,0
|
||||
/*
|
||||
* context = (MAX_USER_CONTEXT) + ((ea >> 60) - 0xc) + 1
|
||||
|
@ -79,7 +80,8 @@ END_MMU_FTR_SECTION_IFCLR(MMU_FTR_1T_SEGMENT)
|
|||
/* Check virtual memmap region. To be patches at kernel boot */
|
||||
cmpldi cr0,r9,0xf
|
||||
bne 1f
|
||||
_GLOBAL(slb_miss_kernel_load_vmemmap)
|
||||
.globl slb_miss_kernel_load_vmemmap
|
||||
slb_miss_kernel_load_vmemmap:
|
||||
li r11,0
|
||||
b 6f
|
||||
1:
|
||||
|
@ -95,7 +97,8 @@ _GLOBAL(slb_miss_kernel_load_vmemmap)
|
|||
b 6f
|
||||
5:
|
||||
/* IO mapping */
|
||||
_GLOBAL(slb_miss_kernel_load_io)
|
||||
.globl slb_miss_kernel_load_io
|
||||
slb_miss_kernel_load_io:
|
||||
li r11,0
|
||||
6:
|
||||
/*
|
||||
|
@ -250,7 +253,8 @@ slb_finish_load:
|
|||
7: ld r10,PACASTABRR(r13)
|
||||
addi r10,r10,1
|
||||
/* This gets soft patched on boot. */
|
||||
_GLOBAL(slb_compare_rr_to_size)
|
||||
.globl slb_compare_rr_to_size
|
||||
slb_compare_rr_to_size:
|
||||
cmpldi r10,0
|
||||
|
||||
blt+ 4f
|
||||
|
|
|
@ -27,6 +27,7 @@
|
|||
#include <asm/cacheflush.h>
|
||||
#include <asm/dbell.h>
|
||||
#include <asm/fsl_guts.h>
|
||||
#include <asm/code-patching.h>
|
||||
|
||||
#include <sysdev/fsl_soc.h>
|
||||
#include <sysdev/mpic.h>
|
||||
|
@ -267,7 +268,7 @@ out:
|
|||
flush_spin_table(spin_table);
|
||||
out_be32(&spin_table->pir, hw_cpu);
|
||||
out_be64((u64 *)(&spin_table->addr_h),
|
||||
__pa((u64)*((unsigned long long *)generic_secondary_smp_init)));
|
||||
__pa(ppc_function_entry(generic_secondary_smp_init)));
|
||||
flush_spin_table(spin_table);
|
||||
#endif
|
||||
|
||||
|
|
|
@ -40,6 +40,7 @@
|
|||
#include <asm/firmware.h>
|
||||
#include <asm/rtas.h>
|
||||
#include <asm/cputhreads.h>
|
||||
#include <asm/code-patching.h>
|
||||
|
||||
#include "interrupt.h"
|
||||
#include <asm/udbg.h>
|
||||
|
@ -70,8 +71,8 @@ static cpumask_t of_spin_map;
|
|||
static inline int smp_startup_cpu(unsigned int lcpu)
|
||||
{
|
||||
int status;
|
||||
unsigned long start_here = __pa((u32)*((unsigned long *)
|
||||
generic_secondary_smp_init));
|
||||
unsigned long start_here =
|
||||
__pa(ppc_function_entry(generic_secondary_smp_init));
|
||||
unsigned int pcpu;
|
||||
int start_cpu;
|
||||
|
||||
|
|
|
@ -66,7 +66,7 @@ sleep_common:
|
|||
std r3, 48(r1)
|
||||
|
||||
/* Only do power savings when in astate 0 */
|
||||
bl .check_astate
|
||||
bl check_astate
|
||||
cmpwi r3,0
|
||||
bne 1f
|
||||
|
||||
|
|
|
@ -21,11 +21,13 @@
|
|||
_GLOBAL(opal_query_takeover)
|
||||
mfcr r0
|
||||
stw r0,8(r1)
|
||||
stdu r1,-STACKFRAMESIZE(r1)
|
||||
std r3,STK_PARAM(R3)(r1)
|
||||
std r4,STK_PARAM(R4)(r1)
|
||||
li r3,H_HAL_TAKEOVER
|
||||
li r4,H_HAL_TAKEOVER_QUERY_MAGIC
|
||||
HVSC
|
||||
addi r1,r1,STACKFRAMESIZE
|
||||
ld r10,STK_PARAM(R3)(r1)
|
||||
std r4,0(r10)
|
||||
ld r10,STK_PARAM(R4)(r1)
|
||||
|
|
|
@ -32,7 +32,7 @@
|
|||
std r12,PACASAVEDMSR(r13); \
|
||||
andc r12,r12,r0; \
|
||||
mtmsrd r12,1; \
|
||||
LOAD_REG_ADDR(r0,.opal_return); \
|
||||
LOAD_REG_ADDR(r0,opal_return); \
|
||||
mtlr r0; \
|
||||
li r0,MSR_DR|MSR_IR|MSR_LE;\
|
||||
andc r12,r12,r0; \
|
||||
|
@ -44,7 +44,7 @@
|
|||
mtspr SPRN_HSRR0,r12; \
|
||||
hrfid
|
||||
|
||||
_STATIC(opal_return)
|
||||
opal_return:
|
||||
/*
|
||||
* Fixup endian on OPAL return... we should be able to simplify
|
||||
* this by instead converting the below trampoline to a set of
|
||||
|
|
|
@ -31,6 +31,7 @@
|
|||
#include <asm/xics.h>
|
||||
#include <asm/opal.h>
|
||||
#include <asm/runlatch.h>
|
||||
#include <asm/code-patching.h>
|
||||
|
||||
#include "powernv.h"
|
||||
|
||||
|
@ -50,8 +51,8 @@ static void pnv_smp_setup_cpu(int cpu)
|
|||
int pnv_smp_kick_cpu(int nr)
|
||||
{
|
||||
unsigned int pcpu = get_hard_smp_processor_id(nr);
|
||||
unsigned long start_here = __pa(*((unsigned long *)
|
||||
generic_secondary_smp_init));
|
||||
unsigned long start_here =
|
||||
__pa(ppc_function_entry(generic_secondary_smp_init));
|
||||
long rc;
|
||||
|
||||
BUG_ON(nr < 0 || nr >= NR_CPUS);
|
||||
|
|
|
@ -49,7 +49,7 @@ END_FTR_SECTION(0, 1); \
|
|||
std r0,16(r1); \
|
||||
addi r4,r1,STK_PARAM(FIRST_REG); \
|
||||
stdu r1,-STACK_FRAME_OVERHEAD(r1); \
|
||||
bl .__trace_hcall_entry; \
|
||||
bl __trace_hcall_entry; \
|
||||
addi r1,r1,STACK_FRAME_OVERHEAD; \
|
||||
ld r0,16(r1); \
|
||||
ld r3,STK_PARAM(R3)(r1); \
|
||||
|
@ -83,7 +83,7 @@ END_FTR_SECTION(0, 1); \
|
|||
mr r3,r6; \
|
||||
std r0,16(r1); \
|
||||
stdu r1,-STACK_FRAME_OVERHEAD(r1); \
|
||||
bl .__trace_hcall_exit; \
|
||||
bl __trace_hcall_exit; \
|
||||
addi r1,r1,STACK_FRAME_OVERHEAD; \
|
||||
ld r0,16(r1); \
|
||||
ld r3,STK_PARAM(R3)(r1); \
|
||||
|
|
|
@ -44,6 +44,7 @@
|
|||
#include <asm/xics.h>
|
||||
#include <asm/dbell.h>
|
||||
#include <asm/plpar_wrappers.h>
|
||||
#include <asm/code-patching.h>
|
||||
|
||||
#include "pseries.h"
|
||||
#include "offline_states.h"
|
||||
|
@ -96,8 +97,8 @@ int smp_query_cpu_stopped(unsigned int pcpu)
|
|||
static inline int smp_startup_cpu(unsigned int lcpu)
|
||||
{
|
||||
int status;
|
||||
unsigned long start_here = __pa((u32)*((unsigned long *)
|
||||
generic_secondary_smp_init));
|
||||
unsigned long start_here =
|
||||
__pa(ppc_function_entry(generic_secondary_smp_init));
|
||||
unsigned int pcpu;
|
||||
int start_cpu;
|
||||
|
||||
|
|
|
@ -20,6 +20,7 @@
|
|||
#include <asm/reg_a2.h>
|
||||
#include <asm/scom.h>
|
||||
#include <asm/udbg.h>
|
||||
#include <asm/code-patching.h>
|
||||
|
||||
#include "wsp.h"
|
||||
|
||||
|
@ -405,7 +406,7 @@ int a2_scom_startup_cpu(unsigned int lcpu, int thr_idx, struct device_node *np)
|
|||
goto fail;
|
||||
}
|
||||
|
||||
start_here = *(unsigned long *)(core_setup ? generic_secondary_smp_init
|
||||
start_here = ppc_function_entry(core_setup ? generic_secondary_smp_init
|
||||
: generic_secondary_thread_init);
|
||||
pr_devel("CPU%d entry point at 0x%lx...\n", lcpu, start_here);
|
||||
|
||||
|
|
|
@ -46,12 +46,15 @@
|
|||
#define R20 r20
|
||||
#define R21 r21
|
||||
#define R22 r22
|
||||
#define R29 r29
|
||||
#define R30 r30
|
||||
#define R31 r31
|
||||
|
||||
#define STACKFRAMESIZE 256
|
||||
#define STK_PARAM(i) (48 + ((i)-3)*8)
|
||||
#define STK_REG(i) (112 + ((i)-14)*8)
|
||||
|
||||
#define _GLOBAL(A) FUNC_START(test_ ## A)
|
||||
#define _GLOBAL_TOC(A) _GLOBAL(A)
|
||||
|
||||
#define PPC_MTOCRF(A, B) mtocrf A, B
|
||||
|
||||
|
|
Loading…
Reference in New Issue