mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2024-11-25 21:24:08 +08:00
Merge branch 'merge' of git://git.kernel.org/pub/scm/linux/kernel/git/benh/powerpc
Pull powerpc fixes and cleanups from Ben Herrenschmidt: "Here are a handful or two of powerpc fixes and simple/trivial cleanups. A bunch of them fix ftrace with the new ABI v2 in Little Endian, the rest is a scattering of fairly simple things" * 'merge' of git://git.kernel.org/pub/scm/linux/kernel/git/benh/powerpc: powerpc: Don't skip ePAPR spin-table CPUs powerpc/module: Fix TOC symbol CRC powerpc/powernv: Remove OPAL v1 takeover powerpc/kmemleak: Do not scan the DART table selftests/powerpc: Use the test harness for the TM DSCR test powerpc/cell: cbe_thermal.c: Cleaning up a variable is of the wrong type powerpc/kprobes: Fix jprobes on ABI v2 (LE) powerpc/ftrace: Use pr_fmt() to namespace error messages powerpc/ftrace: Fix nop of modules on 64bit LE (ABIv2) powerpc/ftrace: Fix inverted check of create_branch() powerpc/ftrace: Fix typo in mask of opcode powerpc: Add ppc_global_function_entry() powerpc/macintosh/smu.c: Fix closing brace followed by if powerpc: Remove __arch_swab* powerpc: Remove ancient DEBUG_SIG code powerpc/kerenl: Enable EEH for IO accessors
This commit is contained in:
commit
d91d66e88e
@ -303,7 +303,6 @@ config PPC_EARLY_DEBUG_OPAL_VTERMNO
|
||||
This correspond to which /dev/hvcN you want to use for early
|
||||
debug.
|
||||
|
||||
On OPAL v1 (takeover) this should always be 0
|
||||
On OPAL v2, this will be 0 for network console and 1 or 2 for
|
||||
the machine built-in serial ports.
|
||||
|
||||
|
@ -88,4 +88,15 @@ static inline unsigned long ppc_function_entry(void *func)
|
||||
#endif
|
||||
}
|
||||
|
||||
static inline unsigned long ppc_global_function_entry(void *func)
|
||||
{
|
||||
#if defined(CONFIG_PPC64) && defined(_CALL_ELF) && _CALL_ELF == 2
|
||||
/* PPC64 ABIv2 the global entry point is at the address */
|
||||
return (unsigned long)func;
|
||||
#else
|
||||
/* All other cases there is no change vs ppc_function_entry() */
|
||||
return ppc_function_entry(func);
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif /* _ASM_POWERPC_CODE_PATCHING_H */
|
||||
|
@ -12,27 +12,7 @@
|
||||
#ifndef __OPAL_H
|
||||
#define __OPAL_H
|
||||
|
||||
/****** Takeover interface ********/
|
||||
|
||||
/* PAPR H-Call used to querty the HAL existence and/or instanciate
|
||||
* it from within pHyp (tech preview only).
|
||||
*
|
||||
* This is exclusively used in prom_init.c
|
||||
*/
|
||||
|
||||
#ifndef __ASSEMBLY__
|
||||
|
||||
struct opal_takeover_args {
|
||||
u64 k_image; /* r4 */
|
||||
u64 k_size; /* r5 */
|
||||
u64 k_entry; /* r6 */
|
||||
u64 k_entry2; /* r7 */
|
||||
u64 hal_addr; /* r8 */
|
||||
u64 rd_image; /* r9 */
|
||||
u64 rd_size; /* r10 */
|
||||
u64 rd_loc; /* r11 */
|
||||
};
|
||||
|
||||
/*
|
||||
* SG entry
|
||||
*
|
||||
@ -55,15 +35,6 @@ struct opal_sg_list {
|
||||
/* We calculate number of sg entries based on PAGE_SIZE */
|
||||
#define SG_ENTRIES_PER_NODE ((PAGE_SIZE - 16) / sizeof(struct opal_sg_entry))
|
||||
|
||||
extern long opal_query_takeover(u64 *hal_size, u64 *hal_align);
|
||||
|
||||
extern long opal_do_takeover(struct opal_takeover_args *args);
|
||||
|
||||
struct rtas_args;
|
||||
extern int opal_enter_rtas(struct rtas_args *args,
|
||||
unsigned long data,
|
||||
unsigned long entry);
|
||||
|
||||
#endif /* __ASSEMBLY__ */
|
||||
|
||||
/****** OPAL APIs ******/
|
||||
|
@ -9,10 +9,6 @@
|
||||
|
||||
#include <uapi/asm/swab.h>
|
||||
|
||||
#ifdef __GNUC__
|
||||
#ifndef __powerpc64__
|
||||
#endif /* __powerpc64__ */
|
||||
|
||||
static __inline__ __u16 ld_le16(const volatile __u16 *addr)
|
||||
{
|
||||
__u16 val;
|
||||
@ -20,19 +16,12 @@ static __inline__ __u16 ld_le16(const volatile __u16 *addr)
|
||||
__asm__ __volatile__ ("lhbrx %0,0,%1" : "=r" (val) : "r" (addr), "m" (*addr));
|
||||
return val;
|
||||
}
|
||||
#define __arch_swab16p ld_le16
|
||||
|
||||
static __inline__ void st_le16(volatile __u16 *addr, const __u16 val)
|
||||
{
|
||||
__asm__ __volatile__ ("sthbrx %1,0,%2" : "=m" (*addr) : "r" (val), "r" (addr));
|
||||
}
|
||||
|
||||
static inline void __arch_swab16s(__u16 *addr)
|
||||
{
|
||||
st_le16(addr, *addr);
|
||||
}
|
||||
#define __arch_swab16s __arch_swab16s
|
||||
|
||||
static __inline__ __u32 ld_le32(const volatile __u32 *addr)
|
||||
{
|
||||
__u32 val;
|
||||
@ -40,42 +29,10 @@ static __inline__ __u32 ld_le32(const volatile __u32 *addr)
|
||||
__asm__ __volatile__ ("lwbrx %0,0,%1" : "=r" (val) : "r" (addr), "m" (*addr));
|
||||
return val;
|
||||
}
|
||||
#define __arch_swab32p ld_le32
|
||||
|
||||
static __inline__ void st_le32(volatile __u32 *addr, const __u32 val)
|
||||
{
|
||||
__asm__ __volatile__ ("stwbrx %1,0,%2" : "=m" (*addr) : "r" (val), "r" (addr));
|
||||
}
|
||||
|
||||
static inline void __arch_swab32s(__u32 *addr)
|
||||
{
|
||||
st_le32(addr, *addr);
|
||||
}
|
||||
#define __arch_swab32s __arch_swab32s
|
||||
|
||||
static inline __attribute_const__ __u16 __arch_swab16(__u16 value)
|
||||
{
|
||||
__u16 result;
|
||||
|
||||
__asm__("rlwimi %0,%1,8,16,23"
|
||||
: "=r" (result)
|
||||
: "r" (value), "0" (value >> 8));
|
||||
return result;
|
||||
}
|
||||
#define __arch_swab16 __arch_swab16
|
||||
|
||||
static inline __attribute_const__ __u32 __arch_swab32(__u32 value)
|
||||
{
|
||||
__u32 result;
|
||||
|
||||
__asm__("rlwimi %0,%1,24,16,23\n\t"
|
||||
"rlwimi %0,%1,8,8,15\n\t"
|
||||
"rlwimi %0,%1,24,0,7"
|
||||
: "=r" (result)
|
||||
: "r" (value), "0" (value >> 24));
|
||||
return result;
|
||||
}
|
||||
#define __arch_swab32 __arch_swab32
|
||||
|
||||
#endif /* __GNUC__ */
|
||||
#endif /* _ASM_POWERPC_SWAB_H */
|
||||
|
@ -10,6 +10,8 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#define pr_fmt(fmt) "ftrace-powerpc: " fmt
|
||||
|
||||
#include <linux/spinlock.h>
|
||||
#include <linux/hardirq.h>
|
||||
#include <linux/uaccess.h>
|
||||
@ -105,7 +107,7 @@ __ftrace_make_nop(struct module *mod,
|
||||
struct dyn_ftrace *rec, unsigned long addr)
|
||||
{
|
||||
unsigned int op;
|
||||
unsigned long ptr;
|
||||
unsigned long entry, ptr;
|
||||
unsigned long ip = rec->ip;
|
||||
void *tramp;
|
||||
|
||||
@ -115,7 +117,7 @@ __ftrace_make_nop(struct module *mod,
|
||||
|
||||
/* Make sure that that this is still a 24bit jump */
|
||||
if (!is_bl_op(op)) {
|
||||
printk(KERN_ERR "Not expected bl: opcode is %x\n", op);
|
||||
pr_err("Not expected bl: opcode is %x\n", op);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
@ -125,21 +127,21 @@ __ftrace_make_nop(struct module *mod,
|
||||
pr_devel("ip:%lx jumps to %p", ip, tramp);
|
||||
|
||||
if (!is_module_trampoline(tramp)) {
|
||||
printk(KERN_ERR "Not a trampoline\n");
|
||||
pr_err("Not a trampoline\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (module_trampoline_target(mod, tramp, &ptr)) {
|
||||
printk(KERN_ERR "Failed to get trampoline target\n");
|
||||
pr_err("Failed to get trampoline target\n");
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
pr_devel("trampoline target %lx", ptr);
|
||||
|
||||
entry = ppc_global_function_entry((void *)addr);
|
||||
/* This should match what was called */
|
||||
if (ptr != ppc_function_entry((void *)addr)) {
|
||||
printk(KERN_ERR "addr %lx does not match expected %lx\n",
|
||||
ptr, ppc_function_entry((void *)addr));
|
||||
if (ptr != entry) {
|
||||
pr_err("addr %lx does not match expected %lx\n", ptr, entry);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
@ -179,7 +181,7 @@ __ftrace_make_nop(struct module *mod,
|
||||
|
||||
/* Make sure that that this is still a 24bit jump */
|
||||
if (!is_bl_op(op)) {
|
||||
printk(KERN_ERR "Not expected bl: opcode is %x\n", op);
|
||||
pr_err("Not expected bl: opcode is %x\n", op);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
@ -198,7 +200,7 @@ __ftrace_make_nop(struct module *mod,
|
||||
|
||||
/* Find where the trampoline jumps to */
|
||||
if (probe_kernel_read(jmp, (void *)tramp, sizeof(jmp))) {
|
||||
printk(KERN_ERR "Failed to read %lx\n", tramp);
|
||||
pr_err("Failed to read %lx\n", tramp);
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
@ -209,7 +211,7 @@ __ftrace_make_nop(struct module *mod,
|
||||
((jmp[1] & 0xffff0000) != 0x398c0000) ||
|
||||
(jmp[2] != 0x7d8903a6) ||
|
||||
(jmp[3] != 0x4e800420)) {
|
||||
printk(KERN_ERR "Not a trampoline\n");
|
||||
pr_err("Not a trampoline\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
@ -221,8 +223,7 @@ __ftrace_make_nop(struct module *mod,
|
||||
pr_devel(" %lx ", tramp);
|
||||
|
||||
if (tramp != addr) {
|
||||
printk(KERN_ERR
|
||||
"Trampoline location %08lx does not match addr\n",
|
||||
pr_err("Trampoline location %08lx does not match addr\n",
|
||||
tramp);
|
||||
return -EINVAL;
|
||||
}
|
||||
@ -263,15 +264,13 @@ int ftrace_make_nop(struct module *mod,
|
||||
*/
|
||||
if (!rec->arch.mod) {
|
||||
if (!mod) {
|
||||
printk(KERN_ERR "No module loaded addr=%lx\n",
|
||||
addr);
|
||||
pr_err("No module loaded addr=%lx\n", addr);
|
||||
return -EFAULT;
|
||||
}
|
||||
rec->arch.mod = mod;
|
||||
} else if (mod) {
|
||||
if (mod != rec->arch.mod) {
|
||||
printk(KERN_ERR
|
||||
"Record mod %p not equal to passed in mod %p\n",
|
||||
pr_err("Record mod %p not equal to passed in mod %p\n",
|
||||
rec->arch.mod, mod);
|
||||
return -EINVAL;
|
||||
}
|
||||
@ -307,26 +306,25 @@ __ftrace_make_call(struct dyn_ftrace *rec, unsigned long addr)
|
||||
* 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] & 0xffff00000) != 0xe8410000)) {
|
||||
printk(KERN_ERR "Unexpected call sequence: %x %x\n",
|
||||
op[0], op[1]);
|
||||
if ((op[0] != 0x48000008) || ((op[1] & 0xffff0000) != 0xe8410000)) {
|
||||
pr_err("Unexpected call sequence: %x %x\n", op[0], op[1]);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* If we never set up a trampoline to ftrace_caller, then bail */
|
||||
if (!rec->arch.mod->arch.tramp) {
|
||||
printk(KERN_ERR "No ftrace trampoline\n");
|
||||
pr_err("No ftrace trampoline\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* 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");
|
||||
if (!create_branch(ip, rec->arch.mod->arch.tramp, BRANCH_SET_LINK)) {
|
||||
pr_err("Branch out of range\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (patch_branch(ip, rec->arch.mod->arch.tramp, BRANCH_SET_LINK)) {
|
||||
printk(KERN_ERR "REL24 out of range!\n");
|
||||
pr_err("REL24 out of range!\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
@ -345,13 +343,13 @@ __ftrace_make_call(struct dyn_ftrace *rec, unsigned long addr)
|
||||
|
||||
/* It should be pointing to a nop */
|
||||
if (op != PPC_INST_NOP) {
|
||||
printk(KERN_ERR "Expected NOP but have %x\n", op);
|
||||
pr_err("Expected NOP but have %x\n", op);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* If we never set up a trampoline to ftrace_caller, then bail */
|
||||
if (!rec->arch.mod->arch.tramp) {
|
||||
printk(KERN_ERR "No ftrace trampoline\n");
|
||||
pr_err("No ftrace trampoline\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
@ -359,7 +357,7 @@ __ftrace_make_call(struct dyn_ftrace *rec, unsigned long addr)
|
||||
op = create_branch((unsigned int *)ip,
|
||||
rec->arch.mod->arch.tramp, BRANCH_SET_LINK);
|
||||
if (!op) {
|
||||
printk(KERN_ERR "REL24 out of range!\n");
|
||||
pr_err("REL24 out of range!\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
@ -397,7 +395,7 @@ int ftrace_make_call(struct dyn_ftrace *rec, unsigned long addr)
|
||||
* already have a module defined.
|
||||
*/
|
||||
if (!rec->arch.mod) {
|
||||
printk(KERN_ERR "No module loaded\n");
|
||||
pr_err("No module loaded\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
|
@ -23,7 +23,7 @@ unsigned int ioread16(void __iomem *addr)
|
||||
}
|
||||
unsigned int ioread16be(void __iomem *addr)
|
||||
{
|
||||
return in_be16(addr);
|
||||
return readw_be(addr);
|
||||
}
|
||||
unsigned int ioread32(void __iomem *addr)
|
||||
{
|
||||
@ -31,7 +31,7 @@ unsigned int ioread32(void __iomem *addr)
|
||||
}
|
||||
unsigned int ioread32be(void __iomem *addr)
|
||||
{
|
||||
return in_be32(addr);
|
||||
return readl_be(addr);
|
||||
}
|
||||
EXPORT_SYMBOL(ioread8);
|
||||
EXPORT_SYMBOL(ioread16);
|
||||
@ -49,7 +49,7 @@ void iowrite16(u16 val, void __iomem *addr)
|
||||
}
|
||||
void iowrite16be(u16 val, void __iomem *addr)
|
||||
{
|
||||
out_be16(addr, val);
|
||||
writew_be(val, addr);
|
||||
}
|
||||
void iowrite32(u32 val, void __iomem *addr)
|
||||
{
|
||||
@ -57,7 +57,7 @@ void iowrite32(u32 val, void __iomem *addr)
|
||||
}
|
||||
void iowrite32be(u32 val, void __iomem *addr)
|
||||
{
|
||||
out_be32(addr, val);
|
||||
writel_be(val, addr);
|
||||
}
|
||||
EXPORT_SYMBOL(iowrite8);
|
||||
EXPORT_SYMBOL(iowrite16);
|
||||
@ -75,15 +75,15 @@ EXPORT_SYMBOL(iowrite32be);
|
||||
*/
|
||||
void ioread8_rep(void __iomem *addr, void *dst, unsigned long count)
|
||||
{
|
||||
_insb((u8 __iomem *) addr, dst, count);
|
||||
readsb(addr, dst, count);
|
||||
}
|
||||
void ioread16_rep(void __iomem *addr, void *dst, unsigned long count)
|
||||
{
|
||||
_insw_ns((u16 __iomem *) addr, dst, count);
|
||||
readsw(addr, dst, count);
|
||||
}
|
||||
void ioread32_rep(void __iomem *addr, void *dst, unsigned long count)
|
||||
{
|
||||
_insl_ns((u32 __iomem *) addr, dst, count);
|
||||
readsl(addr, dst, count);
|
||||
}
|
||||
EXPORT_SYMBOL(ioread8_rep);
|
||||
EXPORT_SYMBOL(ioread16_rep);
|
||||
@ -91,15 +91,15 @@ EXPORT_SYMBOL(ioread32_rep);
|
||||
|
||||
void iowrite8_rep(void __iomem *addr, const void *src, unsigned long count)
|
||||
{
|
||||
_outsb((u8 __iomem *) addr, src, count);
|
||||
writesb(addr, src, count);
|
||||
}
|
||||
void iowrite16_rep(void __iomem *addr, const void *src, unsigned long count)
|
||||
{
|
||||
_outsw_ns((u16 __iomem *) addr, src, count);
|
||||
writesw(addr, src, count);
|
||||
}
|
||||
void iowrite32_rep(void __iomem *addr, const void *src, unsigned long count)
|
||||
{
|
||||
_outsl_ns((u32 __iomem *) addr, src, count);
|
||||
writesl(addr, src, count);
|
||||
}
|
||||
EXPORT_SYMBOL(iowrite8_rep);
|
||||
EXPORT_SYMBOL(iowrite16_rep);
|
||||
|
@ -32,6 +32,7 @@
|
||||
#include <linux/module.h>
|
||||
#include <linux/kdebug.h>
|
||||
#include <linux/slab.h>
|
||||
#include <asm/code-patching.h>
|
||||
#include <asm/cacheflush.h>
|
||||
#include <asm/sstep.h>
|
||||
#include <asm/uaccess.h>
|
||||
@ -491,12 +492,10 @@ int __kprobes kprobe_exceptions_notify(struct notifier_block *self,
|
||||
return ret;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PPC64
|
||||
unsigned long arch_deref_entry_point(void *entry)
|
||||
{
|
||||
return ((func_descr_t *)entry)->entry;
|
||||
return ppc_global_function_entry(entry);
|
||||
}
|
||||
#endif
|
||||
|
||||
int __kprobes setjmp_pre_handler(struct kprobe *p, struct pt_regs *regs)
|
||||
{
|
||||
@ -508,7 +507,11 @@ int __kprobes setjmp_pre_handler(struct kprobe *p, struct pt_regs *regs)
|
||||
/* setup return addr to the jprobe handler routine */
|
||||
regs->nip = arch_deref_entry_point(jp->entry);
|
||||
#ifdef CONFIG_PPC64
|
||||
#if defined(_CALL_ELF) && _CALL_ELF == 2
|
||||
regs->gpr[12] = (unsigned long)jp->entry;
|
||||
#else
|
||||
regs->gpr[2] = (unsigned long)(((func_descr_t *)jp->entry)->toc);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
return 1;
|
||||
|
@ -315,8 +315,17 @@ static void dedotify_versions(struct modversion_info *vers,
|
||||
struct modversion_info *end;
|
||||
|
||||
for (end = (void *)vers + size; vers < end; vers++)
|
||||
if (vers->name[0] == '.')
|
||||
if (vers->name[0] == '.') {
|
||||
memmove(vers->name, vers->name+1, strlen(vers->name));
|
||||
#ifdef ARCH_RELOCATES_KCRCTAB
|
||||
/* The TOC symbol has no CRC computed. To avoid CRC
|
||||
* check failing, we must force it to the expected
|
||||
* value (see CRC check in module.c).
|
||||
*/
|
||||
if (!strcmp(vers->name, "TOC."))
|
||||
vers->crc = -(unsigned long)reloc_start;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
/* Undefined symbols which refer to .funcname, hack to funcname (or .TOC.) */
|
||||
|
@ -662,13 +662,6 @@ void __init early_init_devtree(void *params)
|
||||
of_scan_flat_dt(early_init_dt_scan_fw_dump, NULL);
|
||||
#endif
|
||||
|
||||
/* Pre-initialize the cmd_line with the content of boot_commmand_line,
|
||||
* which will be empty except when the content of the variable has
|
||||
* been overriden by a bootloading mechanism. This happens typically
|
||||
* with HAL takeover
|
||||
*/
|
||||
strlcpy(cmd_line, boot_command_line, COMMAND_LINE_SIZE);
|
||||
|
||||
/* Retrieve various informations from the /chosen node of the
|
||||
* device-tree, including the platform type, initrd location and
|
||||
* size, TCE reserve, and more ...
|
||||
|
@ -1268,201 +1268,6 @@ static u64 __initdata prom_opal_base;
|
||||
static u64 __initdata prom_opal_entry;
|
||||
#endif
|
||||
|
||||
#ifdef __BIG_ENDIAN__
|
||||
/* XXX Don't change this structure without updating opal-takeover.S */
|
||||
static struct opal_secondary_data {
|
||||
s64 ack; /* 0 */
|
||||
u64 go; /* 8 */
|
||||
struct opal_takeover_args args; /* 16 */
|
||||
} opal_secondary_data;
|
||||
|
||||
static u64 __initdata prom_opal_align;
|
||||
static u64 __initdata prom_opal_size;
|
||||
static int __initdata prom_rtas_start_cpu;
|
||||
static u64 __initdata prom_rtas_data;
|
||||
static u64 __initdata prom_rtas_entry;
|
||||
|
||||
extern char opal_secondary_entry;
|
||||
|
||||
static void __init prom_query_opal(void)
|
||||
{
|
||||
long rc;
|
||||
|
||||
/* We must not query for OPAL presence on a machine that
|
||||
* supports TNK takeover (970 blades), as this uses the same
|
||||
* h-call with different arguments and will crash
|
||||
*/
|
||||
if (PHANDLE_VALID(call_prom("finddevice", 1, 1,
|
||||
ADDR("/tnk-memory-map")))) {
|
||||
prom_printf("TNK takeover detected, skipping OPAL check\n");
|
||||
return;
|
||||
}
|
||||
|
||||
prom_printf("Querying for OPAL presence... ");
|
||||
|
||||
rc = opal_query_takeover(&prom_opal_size,
|
||||
&prom_opal_align);
|
||||
prom_debug("(rc = %ld) ", rc);
|
||||
if (rc != 0) {
|
||||
prom_printf("not there.\n");
|
||||
return;
|
||||
}
|
||||
of_platform = PLATFORM_OPAL;
|
||||
prom_printf(" there !\n");
|
||||
prom_debug(" opal_size = 0x%lx\n", prom_opal_size);
|
||||
prom_debug(" opal_align = 0x%lx\n", prom_opal_align);
|
||||
if (prom_opal_align < 0x10000)
|
||||
prom_opal_align = 0x10000;
|
||||
}
|
||||
|
||||
static int __init prom_rtas_call(int token, int nargs, int nret,
|
||||
int *outputs, ...)
|
||||
{
|
||||
struct rtas_args rtas_args;
|
||||
va_list list;
|
||||
int i;
|
||||
|
||||
rtas_args.token = token;
|
||||
rtas_args.nargs = nargs;
|
||||
rtas_args.nret = nret;
|
||||
rtas_args.rets = (rtas_arg_t *)&(rtas_args.args[nargs]);
|
||||
va_start(list, outputs);
|
||||
for (i = 0; i < nargs; ++i)
|
||||
rtas_args.args[i] = va_arg(list, rtas_arg_t);
|
||||
va_end(list);
|
||||
|
||||
for (i = 0; i < nret; ++i)
|
||||
rtas_args.rets[i] = 0;
|
||||
|
||||
opal_enter_rtas(&rtas_args, prom_rtas_data,
|
||||
prom_rtas_entry);
|
||||
|
||||
if (nret > 1 && outputs != NULL)
|
||||
for (i = 0; i < nret-1; ++i)
|
||||
outputs[i] = rtas_args.rets[i+1];
|
||||
return (nret > 0)? rtas_args.rets[0]: 0;
|
||||
}
|
||||
|
||||
static void __init prom_opal_hold_cpus(void)
|
||||
{
|
||||
int i, cnt, cpu, rc;
|
||||
long j;
|
||||
phandle node;
|
||||
char type[64];
|
||||
u32 servers[8];
|
||||
void *entry = (unsigned long *)&opal_secondary_entry;
|
||||
struct opal_secondary_data *data = &opal_secondary_data;
|
||||
|
||||
prom_debug("prom_opal_hold_cpus: start...\n");
|
||||
prom_debug(" - entry = 0x%x\n", entry);
|
||||
prom_debug(" - data = 0x%x\n", data);
|
||||
|
||||
data->ack = -1;
|
||||
data->go = 0;
|
||||
|
||||
/* look for cpus */
|
||||
for (node = 0; prom_next_node(&node); ) {
|
||||
type[0] = 0;
|
||||
prom_getprop(node, "device_type", type, sizeof(type));
|
||||
if (strcmp(type, "cpu") != 0)
|
||||
continue;
|
||||
|
||||
/* Skip non-configured cpus. */
|
||||
if (prom_getprop(node, "status", type, sizeof(type)) > 0)
|
||||
if (strcmp(type, "okay") != 0)
|
||||
continue;
|
||||
|
||||
cnt = prom_getprop(node, "ibm,ppc-interrupt-server#s", servers,
|
||||
sizeof(servers));
|
||||
if (cnt == PROM_ERROR)
|
||||
break;
|
||||
cnt >>= 2;
|
||||
for (i = 0; i < cnt; i++) {
|
||||
cpu = servers[i];
|
||||
prom_debug("CPU %d ... ", cpu);
|
||||
if (cpu == prom.cpu) {
|
||||
prom_debug("booted !\n");
|
||||
continue;
|
||||
}
|
||||
prom_debug("starting ... ");
|
||||
|
||||
/* Init the acknowledge var which will be reset by
|
||||
* the secondary cpu when it awakens from its OF
|
||||
* spinloop.
|
||||
*/
|
||||
data->ack = -1;
|
||||
rc = prom_rtas_call(prom_rtas_start_cpu, 3, 1,
|
||||
NULL, cpu, entry, data);
|
||||
prom_debug("rtas rc=%d ...", rc);
|
||||
|
||||
for (j = 0; j < 100000000 && data->ack == -1; j++) {
|
||||
HMT_low();
|
||||
mb();
|
||||
}
|
||||
HMT_medium();
|
||||
if (data->ack != -1)
|
||||
prom_debug("done, PIR=0x%x\n", data->ack);
|
||||
else
|
||||
prom_debug("timeout !\n");
|
||||
}
|
||||
}
|
||||
prom_debug("prom_opal_hold_cpus: end...\n");
|
||||
}
|
||||
|
||||
static void __init prom_opal_takeover(void)
|
||||
{
|
||||
struct opal_secondary_data *data = &opal_secondary_data;
|
||||
struct opal_takeover_args *args = &data->args;
|
||||
u64 align = prom_opal_align;
|
||||
u64 top_addr, opal_addr;
|
||||
|
||||
args->k_image = (u64)_stext;
|
||||
args->k_size = _end - _stext;
|
||||
args->k_entry = 0;
|
||||
args->k_entry2 = 0x60;
|
||||
|
||||
top_addr = _ALIGN_UP(args->k_size, align);
|
||||
|
||||
if (prom_initrd_start != 0) {
|
||||
args->rd_image = prom_initrd_start;
|
||||
args->rd_size = prom_initrd_end - args->rd_image;
|
||||
args->rd_loc = top_addr;
|
||||
top_addr = _ALIGN_UP(args->rd_loc + args->rd_size, align);
|
||||
}
|
||||
|
||||
/* Pickup an address for the HAL. We want to go really high
|
||||
* up to avoid problem with future kexecs. On the other hand
|
||||
* we don't want to be all over the TCEs on P5IOC2 machines
|
||||
* which are going to be up there too. We assume the machine
|
||||
* has plenty of memory, and we ask for the HAL for now to
|
||||
* be just below the 1G point, or above the initrd
|
||||
*/
|
||||
opal_addr = _ALIGN_DOWN(0x40000000 - prom_opal_size, align);
|
||||
if (opal_addr < top_addr)
|
||||
opal_addr = top_addr;
|
||||
args->hal_addr = opal_addr;
|
||||
|
||||
/* Copy the command line to the kernel image */
|
||||
strlcpy(boot_command_line, prom_cmd_line,
|
||||
COMMAND_LINE_SIZE);
|
||||
|
||||
prom_debug(" k_image = 0x%lx\n", args->k_image);
|
||||
prom_debug(" k_size = 0x%lx\n", args->k_size);
|
||||
prom_debug(" k_entry = 0x%lx\n", args->k_entry);
|
||||
prom_debug(" k_entry2 = 0x%lx\n", args->k_entry2);
|
||||
prom_debug(" hal_addr = 0x%lx\n", args->hal_addr);
|
||||
prom_debug(" rd_image = 0x%lx\n", args->rd_image);
|
||||
prom_debug(" rd_size = 0x%lx\n", args->rd_size);
|
||||
prom_debug(" rd_loc = 0x%lx\n", args->rd_loc);
|
||||
prom_printf("Performing OPAL takeover,this can take a few minutes..\n");
|
||||
prom_close_stdin();
|
||||
mb();
|
||||
data->go = 1;
|
||||
for (;;)
|
||||
opal_do_takeover(args);
|
||||
}
|
||||
#endif /* __BIG_ENDIAN__ */
|
||||
|
||||
/*
|
||||
* Allocate room for and instantiate OPAL
|
||||
*/
|
||||
@ -1597,12 +1402,6 @@ static void __init prom_instantiate_rtas(void)
|
||||
&val, sizeof(val)) != PROM_ERROR)
|
||||
rtas_has_query_cpu_stopped = true;
|
||||
|
||||
#if defined(CONFIG_PPC_POWERNV) && defined(__BIG_ENDIAN__)
|
||||
/* PowerVN takeover hack */
|
||||
prom_rtas_data = base;
|
||||
prom_rtas_entry = entry;
|
||||
prom_getprop(rtas_node, "start-cpu", &prom_rtas_start_cpu, 4);
|
||||
#endif
|
||||
prom_debug("rtas base = 0x%x\n", base);
|
||||
prom_debug("rtas entry = 0x%x\n", entry);
|
||||
prom_debug("rtas size = 0x%x\n", (long)size);
|
||||
@ -3027,16 +2826,6 @@ unsigned long __init prom_init(unsigned long r3, unsigned long r4,
|
||||
prom_instantiate_rtas();
|
||||
|
||||
#ifdef CONFIG_PPC_POWERNV
|
||||
#ifdef __BIG_ENDIAN__
|
||||
/* Detect HAL and try instanciating it & doing takeover */
|
||||
if (of_platform == PLATFORM_PSERIES_LPAR) {
|
||||
prom_query_opal();
|
||||
if (of_platform == PLATFORM_OPAL) {
|
||||
prom_opal_hold_cpus();
|
||||
prom_opal_takeover();
|
||||
}
|
||||
} else
|
||||
#endif /* __BIG_ENDIAN__ */
|
||||
if (of_platform == PLATFORM_OPAL)
|
||||
prom_instantiate_opal();
|
||||
#endif /* CONFIG_PPC_POWERNV */
|
||||
|
@ -21,9 +21,7 @@ _end enter_prom memcpy memset reloc_offset __secondary_hold
|
||||
__secondary_hold_acknowledge __secondary_hold_spinloop __start
|
||||
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 TOC."
|
||||
__prom_init_toc_start __prom_init_toc_end btext_setup_display TOC."
|
||||
|
||||
NM="$1"
|
||||
OBJ="$2"
|
||||
|
@ -469,9 +469,17 @@ void __init smp_setup_cpu_maps(void)
|
||||
}
|
||||
|
||||
for (j = 0; j < nthreads && cpu < nr_cpu_ids; j++) {
|
||||
bool avail;
|
||||
|
||||
DBG(" thread %d -> cpu %d (hard id %d)\n",
|
||||
j, cpu, be32_to_cpu(intserv[j]));
|
||||
set_cpu_present(cpu, of_device_is_available(dn));
|
||||
|
||||
avail = of_device_is_available(dn);
|
||||
if (!avail)
|
||||
avail = !of_property_match_string(dn,
|
||||
"enable-method", "spin-table");
|
||||
|
||||
set_cpu_present(cpu, avail);
|
||||
set_hard_smp_processor_id(cpu, be32_to_cpu(intserv[j]));
|
||||
set_cpu_possible(cpu, true);
|
||||
cpu++;
|
||||
|
@ -54,7 +54,6 @@
|
||||
|
||||
#include "signal.h"
|
||||
|
||||
#undef DEBUG_SIG
|
||||
|
||||
#ifdef CONFIG_PPC64
|
||||
#define sys_rt_sigreturn compat_sys_rt_sigreturn
|
||||
@ -1063,10 +1062,6 @@ int handle_rt_signal32(unsigned long sig, struct k_sigaction *ka,
|
||||
return 1;
|
||||
|
||||
badframe:
|
||||
#ifdef DEBUG_SIG
|
||||
printk("badframe in handle_rt_signal, regs=%p frame=%p newsp=%lx\n",
|
||||
regs, frame, newsp);
|
||||
#endif
|
||||
if (show_unhandled_signals)
|
||||
printk_ratelimited(KERN_INFO
|
||||
"%s[%d]: bad frame in handle_rt_signal32: "
|
||||
@ -1484,10 +1479,6 @@ int handle_signal32(unsigned long sig, struct k_sigaction *ka,
|
||||
return 1;
|
||||
|
||||
badframe:
|
||||
#ifdef DEBUG_SIG
|
||||
printk("badframe in handle_signal, regs=%p frame=%p newsp=%lx\n",
|
||||
regs, frame, newsp);
|
||||
#endif
|
||||
if (show_unhandled_signals)
|
||||
printk_ratelimited(KERN_INFO
|
||||
"%s[%d]: bad frame in handle_signal32: "
|
||||
|
@ -38,7 +38,6 @@
|
||||
|
||||
#include "signal.h"
|
||||
|
||||
#define DEBUG_SIG 0
|
||||
|
||||
#define GP_REGS_SIZE min(sizeof(elf_gregset_t), sizeof(struct pt_regs))
|
||||
#define FP_REGS_SIZE sizeof(elf_fpregset_t)
|
||||
@ -700,10 +699,6 @@ int sys_rt_sigreturn(unsigned long r3, unsigned long r4, unsigned long r5,
|
||||
return 0;
|
||||
|
||||
badframe:
|
||||
#if DEBUG_SIG
|
||||
printk("badframe in sys_rt_sigreturn, regs=%p uc=%p &uc->uc_mcontext=%p\n",
|
||||
regs, uc, &uc->uc_mcontext);
|
||||
#endif
|
||||
if (show_unhandled_signals)
|
||||
printk_ratelimited(regs->msr & MSR_64BIT ? fmt64 : fmt32,
|
||||
current->comm, current->pid, "rt_sigreturn",
|
||||
@ -809,10 +804,6 @@ int handle_rt_signal64(int signr, struct k_sigaction *ka, siginfo_t *info,
|
||||
return 1;
|
||||
|
||||
badframe:
|
||||
#if DEBUG_SIG
|
||||
printk("badframe in setup_rt_frame, regs=%p frame=%p newsp=%lx\n",
|
||||
regs, frame, newsp);
|
||||
#endif
|
||||
if (show_unhandled_signals)
|
||||
printk_ratelimited(regs->msr & MSR_64BIT ? fmt64 : fmt32,
|
||||
current->comm, current->pid, "setup_rt_frame",
|
||||
|
@ -125,7 +125,7 @@ static ssize_t show_throttle(struct cbe_pmd_regs __iomem *pmd_regs, char *buf, i
|
||||
static ssize_t store_throttle(struct cbe_pmd_regs __iomem *pmd_regs, const char *buf, size_t size, int pos)
|
||||
{
|
||||
u64 reg_value;
|
||||
int temp;
|
||||
unsigned int temp;
|
||||
u64 new_value;
|
||||
int ret;
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
obj-y += setup.o opal-takeover.o opal-wrappers.o opal.o opal-async.o
|
||||
obj-y += setup.o opal-wrappers.o opal.o opal-async.o
|
||||
obj-y += opal-rtc.o opal-nvram.o opal-lpc.o opal-flash.o
|
||||
obj-y += rng.o opal-elog.o opal-dump.o opal-sysparam.o opal-sensor.o
|
||||
obj-y += opal-msglog.o
|
||||
|
@ -1,140 +0,0 @@
|
||||
/*
|
||||
* PowerNV OPAL takeover assembly code, for use by prom_init.c
|
||||
*
|
||||
* Copyright 2011 IBM Corp.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version
|
||||
* 2 of the License, or (at your option) any later version.
|
||||
*/
|
||||
|
||||
#include <asm/ppc_asm.h>
|
||||
#include <asm/hvcall.h>
|
||||
#include <asm/asm-offsets.h>
|
||||
#include <asm/opal.h>
|
||||
|
||||
#define H_HAL_TAKEOVER 0x5124
|
||||
#define H_HAL_TAKEOVER_QUERY_MAGIC -1
|
||||
|
||||
.text
|
||||
_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)
|
||||
std r5,0(r10)
|
||||
lwz r0,8(r1)
|
||||
mtcrf 0xff,r0
|
||||
blr
|
||||
|
||||
_GLOBAL(opal_do_takeover)
|
||||
mfcr r0
|
||||
stw r0,8(r1)
|
||||
mflr r0
|
||||
std r0,16(r1)
|
||||
bl __opal_do_takeover
|
||||
ld r0,16(r1)
|
||||
mtlr r0
|
||||
lwz r0,8(r1)
|
||||
mtcrf 0xff,r0
|
||||
blr
|
||||
|
||||
__opal_do_takeover:
|
||||
ld r4,0(r3)
|
||||
ld r5,0x8(r3)
|
||||
ld r6,0x10(r3)
|
||||
ld r7,0x18(r3)
|
||||
ld r8,0x20(r3)
|
||||
ld r9,0x28(r3)
|
||||
ld r10,0x30(r3)
|
||||
ld r11,0x38(r3)
|
||||
li r3,H_HAL_TAKEOVER
|
||||
HVSC
|
||||
blr
|
||||
|
||||
.globl opal_secondary_entry
|
||||
opal_secondary_entry:
|
||||
mr r31,r3
|
||||
mfmsr r11
|
||||
li r12,(MSR_SF | MSR_ISF)@highest
|
||||
sldi r12,r12,48
|
||||
or r11,r11,r12
|
||||
mtmsrd r11
|
||||
isync
|
||||
mfspr r4,SPRN_PIR
|
||||
std r4,0(r3)
|
||||
1: HMT_LOW
|
||||
ld r4,8(r3)
|
||||
cmpli cr0,r4,0
|
||||
beq 1b
|
||||
HMT_MEDIUM
|
||||
1: addi r3,r31,16
|
||||
bl __opal_do_takeover
|
||||
b 1b
|
||||
|
||||
_GLOBAL(opal_enter_rtas)
|
||||
mflr r0
|
||||
std r0,16(r1)
|
||||
stdu r1,-PROM_FRAME_SIZE(r1) /* Save SP and create stack space */
|
||||
|
||||
/* Because PROM is running in 32b mode, it clobbers the high order half
|
||||
* of all registers that it saves. We therefore save those registers
|
||||
* PROM might touch to the stack. (r0, r3-r13 are caller saved)
|
||||
*/
|
||||
SAVE_GPR(2, r1)
|
||||
SAVE_GPR(13, r1)
|
||||
SAVE_8GPRS(14, r1)
|
||||
SAVE_10GPRS(22, r1)
|
||||
mfcr r10
|
||||
mfmsr r11
|
||||
std r10,_CCR(r1)
|
||||
std r11,_MSR(r1)
|
||||
|
||||
/* Get the PROM entrypoint */
|
||||
mtlr r5
|
||||
|
||||
/* Switch MSR to 32 bits mode
|
||||
*/
|
||||
li r12,1
|
||||
rldicr r12,r12,MSR_SF_LG,(63-MSR_SF_LG)
|
||||
andc r11,r11,r12
|
||||
li r12,1
|
||||
rldicr r12,r12,MSR_ISF_LG,(63-MSR_ISF_LG)
|
||||
andc r11,r11,r12
|
||||
mtmsrd r11
|
||||
isync
|
||||
|
||||
/* Enter RTAS here... */
|
||||
blrl
|
||||
|
||||
/* Just make sure that r1 top 32 bits didn't get
|
||||
* corrupt by OF
|
||||
*/
|
||||
rldicl r1,r1,0,32
|
||||
|
||||
/* Restore the MSR (back to 64 bits) */
|
||||
ld r0,_MSR(r1)
|
||||
MTMSRD(r0)
|
||||
isync
|
||||
|
||||
/* Restore other registers */
|
||||
REST_GPR(2, r1)
|
||||
REST_GPR(13, r1)
|
||||
REST_8GPRS(14, r1)
|
||||
REST_10GPRS(22, r1)
|
||||
ld r4,_CCR(r1)
|
||||
mtcr r4
|
||||
|
||||
addi r1,r1,PROM_FRAME_SIZE
|
||||
ld r0,16(r1)
|
||||
mtlr r0
|
||||
blr
|
@ -476,6 +476,11 @@ void __init alloc_dart_table(void)
|
||||
*/
|
||||
dart_tablebase = (unsigned long)
|
||||
__va(memblock_alloc_base(1UL<<24, 1UL<<24, 0x80000000L));
|
||||
/*
|
||||
* The DART space is later unmapped from the kernel linear mapping and
|
||||
* accessing dart_tablebase during kmemleak scanning will fault.
|
||||
*/
|
||||
kmemleak_no_scan((void *)dart_tablebase);
|
||||
|
||||
printk(KERN_INFO "DART table allocated at: %lx\n", dart_tablebase);
|
||||
}
|
||||
|
@ -1257,7 +1257,8 @@ static unsigned int smu_fpoll(struct file *file, poll_table *wait)
|
||||
if (pp->busy && pp->cmd.status != 1)
|
||||
mask |= POLLIN;
|
||||
spin_unlock_irqrestore(&pp->lock, flags);
|
||||
} if (pp->mode == smu_file_events) {
|
||||
}
|
||||
if (pp->mode == smu_file_events) {
|
||||
/* Not yet implemented */
|
||||
}
|
||||
return mask;
|
||||
|
@ -2,7 +2,7 @@ PROGS := tm-resched-dscr
|
||||
|
||||
all: $(PROGS)
|
||||
|
||||
$(PROGS):
|
||||
$(PROGS): ../harness.c
|
||||
|
||||
run_tests: all
|
||||
@-for PROG in $(PROGS); do \
|
||||
|
@ -28,6 +28,8 @@
|
||||
#include <assert.h>
|
||||
#include <asm/tm.h>
|
||||
|
||||
#include "utils.h"
|
||||
|
||||
#define TBEGIN ".long 0x7C00051D ;"
|
||||
#define TEND ".long 0x7C00055D ;"
|
||||
#define TCHECK ".long 0x7C00059C ;"
|
||||
@ -36,7 +38,8 @@
|
||||
#define SPRN_TEXASR 0x82
|
||||
#define SPRN_DSCR 0x03
|
||||
|
||||
int main(void) {
|
||||
int test_body(void)
|
||||
{
|
||||
uint64_t rv, dscr1 = 1, dscr2, texasr;
|
||||
|
||||
printf("Check DSCR TM context switch: ");
|
||||
@ -81,10 +84,15 @@ int main(void) {
|
||||
}
|
||||
if (dscr2 != dscr1) {
|
||||
printf(" FAIL\n");
|
||||
exit(EXIT_FAILURE);
|
||||
return 1;
|
||||
} else {
|
||||
printf(" OK\n");
|
||||
exit(EXIT_SUCCESS);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int main(void)
|
||||
{
|
||||
return test_harness(test_body, "tm_resched_dscr");
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user