mirror of
https://github.com/torvalds/linux.git
synced 2024-11-24 05:02:12 +00:00
Merge branch 'release' of git://git.kernel.org/pub/scm/linux/kernel/git/aegl/linux-2.6
* 'release' of git://git.kernel.org/pub/scm/linux/kernel/git/aegl/linux-2.6: [IA64] kprobe clears qp bits for special instructions [IA64] enable trap code on slot 1 [IA64] Take defensive stance on ia64_pal_get_brand_info() [IA64] fix possible XPC deadlock when disconnecting [IA64] - Reduce overhead of FP exception logging messages [IA64] fix arch/ia64/mm/contig.c:235: warning: unused variable `nid' [IA64] s/termios/ktermios/ in simserial.c [IA64] kexec/kdump: tidy up declaration of relocate_new_kernel_t [IA64] Kexec/Kdump: honour non-zero crashkernel offset. [IA64] CONFIG_KEXEC/CONFIG_CRASH_DUMP permutations [IA64] Do not call SN_SAL_SET_CPU_NUMBER twice on cpu 0
This commit is contained in:
commit
445722f97a
@ -488,7 +488,7 @@ static int rs_ioctl(struct tty_struct *tty, struct file * file,
|
||||
|
||||
#define RELEVANT_IFLAG(iflag) (iflag & (IGNBRK|BRKINT|IGNPAR|PARMRK|INPCK))
|
||||
|
||||
static void rs_set_termios(struct tty_struct *tty, struct termios *old_termios)
|
||||
static void rs_set_termios(struct tty_struct *tty, struct ktermios *old_termios)
|
||||
{
|
||||
unsigned int cflag = tty->termios->c_cflag;
|
||||
|
||||
|
@ -29,6 +29,7 @@ obj-$(CONFIG_CPU_FREQ) += cpufreq/
|
||||
obj-$(CONFIG_IA64_MCA_RECOVERY) += mca_recovery.o
|
||||
obj-$(CONFIG_KPROBES) += kprobes.o jprobes.o
|
||||
obj-$(CONFIG_KEXEC) += machine_kexec.o relocate_kernel.o crash.o
|
||||
obj-$(CONFIG_CRASH_DUMP) += crash_dump.o
|
||||
obj-$(CONFIG_IA64_UNCACHED_ALLOCATOR) += uncached.o
|
||||
obj-$(CONFIG_AUDIT) += audit.o
|
||||
obj-$(CONFIG_PCI_MSI) += msi_ia64.o
|
||||
|
@ -19,29 +19,11 @@
|
||||
|
||||
#include <asm/kdebug.h>
|
||||
#include <asm/mca.h>
|
||||
#include <asm/uaccess.h>
|
||||
|
||||
int kdump_status[NR_CPUS];
|
||||
atomic_t kdump_cpu_freezed;
|
||||
atomic_t kdump_in_progress;
|
||||
int kdump_on_init = 1;
|
||||
ssize_t
|
||||
copy_oldmem_page(unsigned long pfn, char *buf,
|
||||
size_t csize, unsigned long offset, int userbuf)
|
||||
{
|
||||
void *vaddr;
|
||||
|
||||
if (!csize)
|
||||
return 0;
|
||||
vaddr = __va(pfn<<PAGE_SHIFT);
|
||||
if (userbuf) {
|
||||
if (copy_to_user(buf, (vaddr + offset), csize)) {
|
||||
return -EFAULT;
|
||||
}
|
||||
} else
|
||||
memcpy(buf, (vaddr + offset), csize);
|
||||
return csize;
|
||||
}
|
||||
|
||||
static inline Elf64_Word
|
||||
*append_elf_note(Elf64_Word *buf, char *name, unsigned type, void *data,
|
||||
@ -225,14 +207,10 @@ static ctl_table sys_table[] = {
|
||||
static int
|
||||
machine_crash_setup(void)
|
||||
{
|
||||
char *from = strstr(saved_command_line, "elfcorehdr=");
|
||||
static struct notifier_block kdump_init_notifier_nb = {
|
||||
.notifier_call = kdump_init_notifier,
|
||||
};
|
||||
int ret;
|
||||
if (from)
|
||||
elfcorehdr_addr = memparse(from+11, &from);
|
||||
saved_max_pfn = (unsigned long)-1;
|
||||
if((ret = register_die_notifier(&kdump_init_notifier_nb)) != 0)
|
||||
return ret;
|
||||
#ifdef CONFIG_SYSCTL
|
||||
|
48
arch/ia64/kernel/crash_dump.c
Normal file
48
arch/ia64/kernel/crash_dump.c
Normal file
@ -0,0 +1,48 @@
|
||||
/*
|
||||
* kernel/crash_dump.c - Memory preserving reboot related code.
|
||||
*
|
||||
* Created by: Simon Horman <horms@verge.net.au>
|
||||
* Original code moved from kernel/crash.c
|
||||
* Original code comment copied from the i386 version of this file
|
||||
*/
|
||||
|
||||
#include <linux/errno.h>
|
||||
#include <linux/types.h>
|
||||
|
||||
#include <linux/uaccess.h>
|
||||
|
||||
/**
|
||||
* copy_oldmem_page - copy one page from "oldmem"
|
||||
* @pfn: page frame number to be copied
|
||||
* @buf: target memory address for the copy; this can be in kernel address
|
||||
* space or user address space (see @userbuf)
|
||||
* @csize: number of bytes to copy
|
||||
* @offset: offset in bytes into the page (based on pfn) to begin the copy
|
||||
* @userbuf: if set, @buf is in user address space, use copy_to_user(),
|
||||
* otherwise @buf is in kernel address space, use memcpy().
|
||||
*
|
||||
* Copy a page from "oldmem". For this page, there is no pte mapped
|
||||
* in the current kernel. We stitch up a pte, similar to kmap_atomic.
|
||||
*
|
||||
* Calling copy_to_user() in atomic context is not desirable. Hence first
|
||||
* copying the data to a pre-allocated kernel page and then copying to user
|
||||
* space in non-atomic context.
|
||||
*/
|
||||
ssize_t
|
||||
copy_oldmem_page(unsigned long pfn, char *buf,
|
||||
size_t csize, unsigned long offset, int userbuf)
|
||||
{
|
||||
void *vaddr;
|
||||
|
||||
if (!csize)
|
||||
return 0;
|
||||
vaddr = __va(pfn<<PAGE_SHIFT);
|
||||
if (userbuf) {
|
||||
if (copy_to_user(buf, (vaddr + offset), csize)) {
|
||||
return -EFAULT;
|
||||
}
|
||||
} else
|
||||
memcpy(buf, (vaddr + offset), csize);
|
||||
return csize;
|
||||
}
|
||||
|
@ -45,13 +45,14 @@
|
||||
* to the correct location.
|
||||
*/
|
||||
#include <asm/asmmacro.h>
|
||||
#include <asm-ia64/break.h>
|
||||
|
||||
/*
|
||||
* void jprobe_break(void)
|
||||
*/
|
||||
.section .kprobes.text, "ax"
|
||||
ENTRY(jprobe_break)
|
||||
break.m 0x80300
|
||||
break.m __IA64_BREAK_JPROBE
|
||||
END(jprobe_break)
|
||||
|
||||
/*
|
||||
|
@ -88,6 +88,7 @@ static void __kprobes update_kprobe_inst_flag(uint template, uint slot,
|
||||
{
|
||||
p->ainsn.inst_flag = 0;
|
||||
p->ainsn.target_br_reg = 0;
|
||||
p->ainsn.slot = slot;
|
||||
|
||||
/* Check for Break instruction
|
||||
* Bits 37:40 Major opcode to be zero
|
||||
@ -127,48 +128,6 @@ static void __kprobes update_kprobe_inst_flag(uint template, uint slot,
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* In this function we check to see if the instruction
|
||||
* on which we are inserting kprobe is supported.
|
||||
* Returns 0 if supported
|
||||
* Returns -EINVAL if unsupported
|
||||
*/
|
||||
static int __kprobes unsupported_inst(uint template, uint slot,
|
||||
uint major_opcode,
|
||||
unsigned long kprobe_inst,
|
||||
unsigned long addr)
|
||||
{
|
||||
if (bundle_encoding[template][slot] == I) {
|
||||
switch (major_opcode) {
|
||||
case 0x0: //I_UNIT_MISC_OPCODE:
|
||||
/*
|
||||
* Check for Integer speculation instruction
|
||||
* - Bit 33-35 to be equal to 0x1
|
||||
*/
|
||||
if (((kprobe_inst >> 33) & 0x7) == 1) {
|
||||
printk(KERN_WARNING
|
||||
"Kprobes on speculation inst at <0x%lx> not supported\n",
|
||||
addr);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/*
|
||||
* IP relative mov instruction
|
||||
* - Bit 27-35 to be equal to 0x30
|
||||
*/
|
||||
if (((kprobe_inst >> 27) & 0x1FF) == 0x30) {
|
||||
printk(KERN_WARNING
|
||||
"Kprobes on \"mov r1=ip\" at <0x%lx> not supported\n",
|
||||
addr);
|
||||
return -EINVAL;
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* In this function we check to see if the instruction
|
||||
* (qp) cmpx.crel.ctype p1,p2=r2,r3
|
||||
@ -205,6 +164,119 @@ out:
|
||||
return ctype_unc;
|
||||
}
|
||||
|
||||
/*
|
||||
* In this function we check to see if the instruction
|
||||
* on which we are inserting kprobe is supported.
|
||||
* Returns qp value if supported
|
||||
* Returns -EINVAL if unsupported
|
||||
*/
|
||||
static int __kprobes unsupported_inst(uint template, uint slot,
|
||||
uint major_opcode,
|
||||
unsigned long kprobe_inst,
|
||||
unsigned long addr)
|
||||
{
|
||||
int qp;
|
||||
|
||||
qp = kprobe_inst & 0x3f;
|
||||
if (is_cmp_ctype_unc_inst(template, slot, major_opcode, kprobe_inst)) {
|
||||
if (slot == 1 && qp) {
|
||||
printk(KERN_WARNING "Kprobes on cmp unc"
|
||||
"instruction on slot 1 at <0x%lx>"
|
||||
"is not supported\n", addr);
|
||||
return -EINVAL;
|
||||
|
||||
}
|
||||
qp = 0;
|
||||
}
|
||||
else if (bundle_encoding[template][slot] == I) {
|
||||
if (major_opcode == 0) {
|
||||
/*
|
||||
* Check for Integer speculation instruction
|
||||
* - Bit 33-35 to be equal to 0x1
|
||||
*/
|
||||
if (((kprobe_inst >> 33) & 0x7) == 1) {
|
||||
printk(KERN_WARNING
|
||||
"Kprobes on speculation inst at <0x%lx> not supported\n",
|
||||
addr);
|
||||
return -EINVAL;
|
||||
}
|
||||
/*
|
||||
* IP relative mov instruction
|
||||
* - Bit 27-35 to be equal to 0x30
|
||||
*/
|
||||
if (((kprobe_inst >> 27) & 0x1FF) == 0x30) {
|
||||
printk(KERN_WARNING
|
||||
"Kprobes on \"mov r1=ip\" at <0x%lx> not supported\n",
|
||||
addr);
|
||||
return -EINVAL;
|
||||
|
||||
}
|
||||
}
|
||||
else if ((major_opcode == 5) && !(kprobe_inst & (0xFUl << 33)) &&
|
||||
(kprobe_inst & (0x1UL << 12))) {
|
||||
/* test bit instructions, tbit,tnat,tf
|
||||
* bit 33-36 to be equal to 0
|
||||
* bit 12 to be equal to 1
|
||||
*/
|
||||
if (slot == 1 && qp) {
|
||||
printk(KERN_WARNING "Kprobes on test bit"
|
||||
"instruction on slot at <0x%lx>"
|
||||
"is not supported\n", addr);
|
||||
return -EINVAL;
|
||||
}
|
||||
qp = 0;
|
||||
}
|
||||
}
|
||||
else if (bundle_encoding[template][slot] == B) {
|
||||
if (major_opcode == 7) {
|
||||
/* IP-Relative Predict major code is 7 */
|
||||
printk(KERN_WARNING "Kprobes on IP-Relative"
|
||||
"Predict is not supported\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
else if (major_opcode == 2) {
|
||||
/* Indirect Predict, major code is 2
|
||||
* bit 27-32 to be equal to 10 or 11
|
||||
*/
|
||||
int x6=(kprobe_inst >> 27) & 0x3F;
|
||||
if ((x6 == 0x10) || (x6 == 0x11)) {
|
||||
printk(KERN_WARNING "Kprobes on"
|
||||
"Indirect Predict is not supported\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
}
|
||||
/* kernel does not use float instruction, here for safety kprobe
|
||||
* will judge whether it is fcmp/flass/float approximation instruction
|
||||
*/
|
||||
else if (unlikely(bundle_encoding[template][slot] == F)) {
|
||||
if ((major_opcode == 4 || major_opcode == 5) &&
|
||||
(kprobe_inst & (0x1 << 12))) {
|
||||
/* fcmp/fclass unc instruction */
|
||||
if (slot == 1 && qp) {
|
||||
printk(KERN_WARNING "Kprobes on fcmp/fclass "
|
||||
"instruction on slot at <0x%lx> "
|
||||
"is not supported\n", addr);
|
||||
return -EINVAL;
|
||||
|
||||
}
|
||||
qp = 0;
|
||||
}
|
||||
if ((major_opcode == 0 || major_opcode == 1) &&
|
||||
(kprobe_inst & (0x1UL << 33))) {
|
||||
/* float Approximation instruction */
|
||||
if (slot == 1 && qp) {
|
||||
printk(KERN_WARNING "Kprobes on float Approx "
|
||||
"instr at <0x%lx> is not supported\n",
|
||||
addr);
|
||||
return -EINVAL;
|
||||
}
|
||||
qp = 0;
|
||||
}
|
||||
}
|
||||
return qp;
|
||||
}
|
||||
|
||||
/*
|
||||
* In this function we override the bundle with
|
||||
* the break instruction at the given slot.
|
||||
@ -212,20 +284,17 @@ out:
|
||||
static void __kprobes prepare_break_inst(uint template, uint slot,
|
||||
uint major_opcode,
|
||||
unsigned long kprobe_inst,
|
||||
struct kprobe *p)
|
||||
struct kprobe *p,
|
||||
int qp)
|
||||
{
|
||||
unsigned long break_inst = BREAK_INST;
|
||||
bundle_t *bundle = &p->opcode.bundle;
|
||||
|
||||
/*
|
||||
* Copy the original kprobe_inst qualifying predicate(qp)
|
||||
* to the break instruction iff !is_cmp_ctype_unc_inst
|
||||
* because for cmp instruction with ctype equal to unc,
|
||||
* which is a special instruction always needs to be
|
||||
* executed regradless of qp
|
||||
* to the break instruction
|
||||
*/
|
||||
if (!is_cmp_ctype_unc_inst(template, slot, major_opcode, kprobe_inst))
|
||||
break_inst |= (0x3f & kprobe_inst);
|
||||
break_inst |= qp;
|
||||
|
||||
switch (slot) {
|
||||
case 0:
|
||||
@ -296,12 +365,6 @@ static int __kprobes valid_kprobe_addr(int template, int slot,
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (slot == 1 && bundle_encoding[template][1] != L) {
|
||||
printk(KERN_WARNING "Inserting kprobes on slot #1 "
|
||||
"is not supported\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -427,6 +490,7 @@ int __kprobes arch_prepare_kprobe(struct kprobe *p)
|
||||
unsigned long kprobe_inst=0;
|
||||
unsigned int slot = addr & 0xf, template, major_opcode = 0;
|
||||
bundle_t *bundle;
|
||||
int qp;
|
||||
|
||||
bundle = &((kprobe_opcode_t *)kprobe_addr)->bundle;
|
||||
template = bundle->quad0.template;
|
||||
@ -441,9 +505,9 @@ int __kprobes arch_prepare_kprobe(struct kprobe *p)
|
||||
/* Get kprobe_inst and major_opcode from the bundle */
|
||||
get_kprobe_inst(bundle, slot, &kprobe_inst, &major_opcode);
|
||||
|
||||
if (unsupported_inst(template, slot, major_opcode, kprobe_inst, addr))
|
||||
return -EINVAL;
|
||||
|
||||
qp = unsupported_inst(template, slot, major_opcode, kprobe_inst, addr);
|
||||
if (qp < 0)
|
||||
return -EINVAL;
|
||||
|
||||
p->ainsn.insn = get_insn_slot();
|
||||
if (!p->ainsn.insn)
|
||||
@ -451,30 +515,56 @@ int __kprobes arch_prepare_kprobe(struct kprobe *p)
|
||||
memcpy(&p->opcode, kprobe_addr, sizeof(kprobe_opcode_t));
|
||||
memcpy(p->ainsn.insn, kprobe_addr, sizeof(kprobe_opcode_t));
|
||||
|
||||
prepare_break_inst(template, slot, major_opcode, kprobe_inst, p);
|
||||
prepare_break_inst(template, slot, major_opcode, kprobe_inst, p, qp);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void __kprobes arch_arm_kprobe(struct kprobe *p)
|
||||
{
|
||||
unsigned long addr = (unsigned long)p->addr;
|
||||
unsigned long arm_addr = addr & ~0xFULL;
|
||||
unsigned long arm_addr;
|
||||
bundle_t *src, *dest;
|
||||
|
||||
arm_addr = ((unsigned long)p->addr) & ~0xFUL;
|
||||
dest = &((kprobe_opcode_t *)arm_addr)->bundle;
|
||||
src = &p->opcode.bundle;
|
||||
|
||||
flush_icache_range((unsigned long)p->ainsn.insn,
|
||||
(unsigned long)p->ainsn.insn + sizeof(kprobe_opcode_t));
|
||||
memcpy((char *)arm_addr, &p->opcode, sizeof(kprobe_opcode_t));
|
||||
switch (p->ainsn.slot) {
|
||||
case 0:
|
||||
dest->quad0.slot0 = src->quad0.slot0;
|
||||
break;
|
||||
case 1:
|
||||
dest->quad1.slot1_p1 = src->quad1.slot1_p1;
|
||||
break;
|
||||
case 2:
|
||||
dest->quad1.slot2 = src->quad1.slot2;
|
||||
break;
|
||||
}
|
||||
flush_icache_range(arm_addr, arm_addr + sizeof(kprobe_opcode_t));
|
||||
}
|
||||
|
||||
void __kprobes arch_disarm_kprobe(struct kprobe *p)
|
||||
{
|
||||
unsigned long addr = (unsigned long)p->addr;
|
||||
unsigned long arm_addr = addr & ~0xFULL;
|
||||
unsigned long arm_addr;
|
||||
bundle_t *src, *dest;
|
||||
|
||||
arm_addr = ((unsigned long)p->addr) & ~0xFUL;
|
||||
dest = &((kprobe_opcode_t *)arm_addr)->bundle;
|
||||
/* p->ainsn.insn contains the original unaltered kprobe_opcode_t */
|
||||
memcpy((char *) arm_addr, (char *) p->ainsn.insn,
|
||||
sizeof(kprobe_opcode_t));
|
||||
src = &p->ainsn.insn->bundle;
|
||||
switch (p->ainsn.slot) {
|
||||
case 0:
|
||||
dest->quad0.slot0 = src->quad0.slot0;
|
||||
break;
|
||||
case 1:
|
||||
dest->quad1.slot1_p1 = src->quad1.slot1_p1;
|
||||
break;
|
||||
case 2:
|
||||
dest->quad1.slot2 = src->quad1.slot2;
|
||||
break;
|
||||
}
|
||||
flush_icache_range(arm_addr, arm_addr + sizeof(kprobe_opcode_t));
|
||||
}
|
||||
|
||||
@ -807,7 +897,9 @@ int __kprobes kprobe_exceptions_notify(struct notifier_block *self,
|
||||
switch(val) {
|
||||
case DIE_BREAK:
|
||||
/* err is break number from ia64_bad_break() */
|
||||
if (args->err == 0x80200 || args->err == 0x80300 || args->err == 0)
|
||||
if ((args->err >> 12) == (__IA64_BREAK_KPROBE >> 12)
|
||||
|| args->err == __IA64_BREAK_JPROBE
|
||||
|| args->err == 0)
|
||||
if (pre_kprobes_handler(args))
|
||||
ret = NOTIFY_STOP;
|
||||
break;
|
||||
|
@ -19,8 +19,11 @@
|
||||
#include <asm/delay.h>
|
||||
#include <asm/meminit.h>
|
||||
|
||||
typedef void (*relocate_new_kernel_t)(unsigned long, unsigned long,
|
||||
struct ia64_boot_param *, unsigned long);
|
||||
typedef NORET_TYPE void (*relocate_new_kernel_t)(
|
||||
unsigned long indirection_page,
|
||||
unsigned long start_address,
|
||||
struct ia64_boot_param *boot_param,
|
||||
unsigned long pal_addr) ATTRIB_NORET;
|
||||
|
||||
struct kimage *ia64_kimage;
|
||||
|
||||
|
@ -1239,7 +1239,7 @@ ia64_mca_handler(struct pt_regs *regs, struct switch_stack *sw,
|
||||
} else {
|
||||
/* Dump buffered message to console */
|
||||
ia64_mlogbuf_finish(1);
|
||||
#ifdef CONFIG_CRASH_DUMP
|
||||
#ifdef CONFIG_KEXEC
|
||||
atomic_set(&kdump_in_progress, 1);
|
||||
monarch_cpu = -1;
|
||||
#endif
|
||||
|
@ -256,7 +256,7 @@ reserve_memory (void)
|
||||
|
||||
#ifdef CONFIG_KEXEC
|
||||
/* crashkernel=size@offset specifies the size to reserve for a crash
|
||||
* kernel.(offset is ingored for keep compatibility with other archs)
|
||||
* kernel. If offset is 0, then it is determined automatically.
|
||||
* By reserving this memory we guarantee that linux never set's it
|
||||
* up as a DMA target.Useful for holding code to do something
|
||||
* appropriate after a kernel panic.
|
||||
@ -266,10 +266,16 @@ reserve_memory (void)
|
||||
unsigned long base, size;
|
||||
if (from) {
|
||||
size = memparse(from + 12, &from);
|
||||
if (*from == '@')
|
||||
base = memparse(from+1, &from);
|
||||
else
|
||||
base = 0;
|
||||
if (size) {
|
||||
sort_regions(rsvd_region, n);
|
||||
base = kdump_find_rsvd_region(size,
|
||||
rsvd_region, n);
|
||||
if (!base) {
|
||||
sort_regions(rsvd_region, n);
|
||||
base = kdump_find_rsvd_region(size,
|
||||
rsvd_region, n);
|
||||
}
|
||||
if (base != ~0UL) {
|
||||
rsvd_region[n].start =
|
||||
(unsigned long)__va(base);
|
||||
@ -434,6 +440,21 @@ static __init int setup_nomca(char *s)
|
||||
}
|
||||
early_param("nomca", setup_nomca);
|
||||
|
||||
#ifdef CONFIG_PROC_VMCORE
|
||||
/* elfcorehdr= specifies the location of elf core header
|
||||
* stored by the crashed kernel.
|
||||
*/
|
||||
static int __init parse_elfcorehdr(char *arg)
|
||||
{
|
||||
if (!arg)
|
||||
return -EINVAL;
|
||||
|
||||
elfcorehdr_addr = memparse(arg, &arg);
|
||||
return 0;
|
||||
}
|
||||
early_param("elfcorehdr", parse_elfcorehdr);
|
||||
#endif /* CONFIG_PROC_VMCORE */
|
||||
|
||||
void __init
|
||||
setup_arch (char **cmdline_p)
|
||||
{
|
||||
@ -653,6 +674,7 @@ get_model_name(__u8 family, __u8 model)
|
||||
{
|
||||
char brand[128];
|
||||
|
||||
memcpy(brand, "Unknown", 8);
|
||||
if (ia64_pal_get_brand_info(brand)) {
|
||||
if (family == 0x7)
|
||||
memcpy(brand, "Merced", 7);
|
||||
@ -660,8 +682,7 @@ get_model_name(__u8 family, __u8 model)
|
||||
case 0: memcpy(brand, "McKinley", 9); break;
|
||||
case 1: memcpy(brand, "Madison", 8); break;
|
||||
case 2: memcpy(brand, "Madison up to 9M cache", 23); break;
|
||||
} else
|
||||
memcpy(brand, "Unknown", 8);
|
||||
}
|
||||
}
|
||||
if (brandname[0] == '\0')
|
||||
return strcpy(brandname, brand);
|
||||
|
@ -157,7 +157,7 @@ handle_IPI (int irq, void *dev_id)
|
||||
case IPI_CPU_STOP:
|
||||
stop_this_cpu();
|
||||
break;
|
||||
#ifdef CONFIG_CRASH_DUMP
|
||||
#ifdef CONFIG_KEXEC
|
||||
case IPI_KDUMP_CPU_STOP:
|
||||
unw_init_running(kdump_cpu_freeze, NULL);
|
||||
break;
|
||||
@ -219,7 +219,7 @@ send_IPI_self (int op)
|
||||
send_IPI_single(smp_processor_id(), op);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_CRASH_DUMP
|
||||
#ifdef CONFIG_KEXEC
|
||||
void
|
||||
kdump_smp_send_stop()
|
||||
{
|
||||
|
@ -307,6 +307,15 @@ fp_emulate (int fp_fault, void *bundle, long *ipsr, long *fpsr, long *isr, long
|
||||
return ret.status;
|
||||
}
|
||||
|
||||
struct fpu_swa_msg {
|
||||
unsigned long count;
|
||||
unsigned long time;
|
||||
};
|
||||
static DEFINE_PER_CPU(struct fpu_swa_msg, cpulast);
|
||||
DECLARE_PER_CPU(struct fpu_swa_msg, cpulast);
|
||||
static struct fpu_swa_msg last __cacheline_aligned;
|
||||
|
||||
|
||||
/*
|
||||
* Handle floating-point assist faults and traps.
|
||||
*/
|
||||
@ -316,8 +325,6 @@ handle_fpu_swa (int fp_fault, struct pt_regs *regs, unsigned long isr)
|
||||
long exception, bundle[2];
|
||||
unsigned long fault_ip;
|
||||
struct siginfo siginfo;
|
||||
static int fpu_swa_count = 0;
|
||||
static unsigned long last_time;
|
||||
|
||||
fault_ip = regs->cr_iip;
|
||||
if (!fp_fault && (ia64_psr(regs)->ri == 0))
|
||||
@ -325,14 +332,37 @@ handle_fpu_swa (int fp_fault, struct pt_regs *regs, unsigned long isr)
|
||||
if (copy_from_user(bundle, (void __user *) fault_ip, sizeof(bundle)))
|
||||
return -1;
|
||||
|
||||
if (jiffies - last_time > 5*HZ)
|
||||
fpu_swa_count = 0;
|
||||
if ((fpu_swa_count < 4) && !(current->thread.flags & IA64_THREAD_FPEMU_NOPRINT)) {
|
||||
last_time = jiffies;
|
||||
++fpu_swa_count;
|
||||
printk(KERN_WARNING
|
||||
"%s(%d): floating-point assist fault at ip %016lx, isr %016lx\n",
|
||||
current->comm, current->pid, regs->cr_iip + ia64_psr(regs)->ri, isr);
|
||||
if (!(current->thread.flags & IA64_THREAD_FPEMU_NOPRINT)) {
|
||||
unsigned long count, current_jiffies = jiffies;
|
||||
struct fpu_swa_msg *cp = &__get_cpu_var(cpulast);
|
||||
|
||||
if (unlikely(current_jiffies > cp->time))
|
||||
cp->count = 0;
|
||||
if (unlikely(cp->count < 5)) {
|
||||
cp->count++;
|
||||
cp->time = current_jiffies + 5 * HZ;
|
||||
|
||||
/* minimize races by grabbing a copy of count BEFORE checking last.time. */
|
||||
count = last.count;
|
||||
barrier();
|
||||
|
||||
/*
|
||||
* Lower 4 bits are used as a count. Upper bits are a sequence
|
||||
* number that is updated when count is reset. The cmpxchg will
|
||||
* fail is seqno has changed. This minimizes mutiple cpus
|
||||
* reseting the count.
|
||||
*/
|
||||
if (current_jiffies > last.time)
|
||||
(void) cmpxchg_acq(&last.count, count, 16 + (count & ~15));
|
||||
|
||||
/* used fetchadd to atomically update the count */
|
||||
if ((last.count & 15) < 5 && (ia64_fetchadd(1, &last.count, acq) & 15) < 5) {
|
||||
last.time = current_jiffies + 5 * HZ;
|
||||
printk(KERN_WARNING
|
||||
"%s(%d): floating-point assist fault at ip %016lx, isr %016lx\n",
|
||||
current->comm, current->pid, regs->cr_iip + ia64_psr(regs)->ri, isr);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
exception = fp_emulate(fp_fault, bundle, ®s->cr_ipsr, ®s->ar_fpsr, &isr, ®s->pr,
|
||||
|
@ -174,6 +174,12 @@ find_memory (void)
|
||||
reserve_bootmem(bootmap_start, bootmap_size);
|
||||
|
||||
find_initrd();
|
||||
|
||||
#ifdef CONFIG_CRASH_DUMP
|
||||
/* If we are doing a crash dump, we still need to know the real mem
|
||||
* size before original memory map is * reset. */
|
||||
saved_max_pfn = max_pfn;
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef CONFIG_SMP
|
||||
@ -226,7 +232,6 @@ void __init
|
||||
paging_init (void)
|
||||
{
|
||||
unsigned long max_dma;
|
||||
unsigned long nid = 0;
|
||||
unsigned long max_zone_pfns[MAX_NR_ZONES];
|
||||
|
||||
num_physpages = 0;
|
||||
@ -238,7 +243,7 @@ paging_init (void)
|
||||
max_zone_pfns[ZONE_NORMAL] = max_low_pfn;
|
||||
|
||||
#ifdef CONFIG_VIRTUAL_MEM_MAP
|
||||
efi_memmap_walk(register_active_ranges, &nid);
|
||||
efi_memmap_walk(register_active_ranges, NULL);
|
||||
efi_memmap_walk(find_largest_hole, (u64 *)&max_gap);
|
||||
if (max_gap < LARGE_GAP) {
|
||||
vmem_map = (struct page *) 0;
|
||||
|
@ -595,14 +595,9 @@ find_largest_hole (u64 start, u64 end, void *arg)
|
||||
}
|
||||
|
||||
int __init
|
||||
register_active_ranges(u64 start, u64 end, void *nid)
|
||||
register_active_ranges(u64 start, u64 end, void *arg)
|
||||
{
|
||||
BUG_ON(nid == NULL);
|
||||
BUG_ON(*(unsigned long *)nid >= MAX_NUMNODES);
|
||||
|
||||
add_active_range(*(unsigned long *)nid,
|
||||
__pa(start) >> PAGE_SHIFT,
|
||||
__pa(end) >> PAGE_SHIFT);
|
||||
add_active_range(0, __pa(start) >> PAGE_SHIFT, __pa(end) >> PAGE_SHIFT);
|
||||
return 0;
|
||||
}
|
||||
#endif /* CONFIG_VIRTUAL_MEM_MAP */
|
||||
|
@ -580,7 +580,7 @@ void __cpuinit sn_cpu_init(void)
|
||||
int slice;
|
||||
int cnode;
|
||||
int i;
|
||||
static int wars_have_been_checked;
|
||||
static int wars_have_been_checked, set_cpu0_number;
|
||||
|
||||
cpuid = smp_processor_id();
|
||||
if (cpuid == 0 && IS_MEDUSA()) {
|
||||
@ -605,8 +605,16 @@ void __cpuinit sn_cpu_init(void)
|
||||
/*
|
||||
* Don't check status. The SAL call is not supported on all PROMs
|
||||
* but a failure is harmless.
|
||||
* Architechtuallly, cpu_init is always called twice on cpu 0. We
|
||||
* should set cpu_number on cpu 0 once.
|
||||
*/
|
||||
(void) ia64_sn_set_cpu_number(cpuid);
|
||||
if (cpuid == 0) {
|
||||
if (!set_cpu0_number) {
|
||||
(void) ia64_sn_set_cpu_number(cpuid);
|
||||
set_cpu0_number = 1;
|
||||
}
|
||||
} else
|
||||
(void) ia64_sn_set_cpu_number(cpuid);
|
||||
|
||||
/*
|
||||
* The boot cpu makes this call again after platform initialization is
|
||||
|
@ -632,7 +632,7 @@ xpc_process_connect(struct xpc_channel *ch, unsigned long *irq_flags)
|
||||
ch->number, ch->partid);
|
||||
|
||||
spin_unlock_irqrestore(&ch->lock, *irq_flags);
|
||||
xpc_create_kthreads(ch, 1);
|
||||
xpc_create_kthreads(ch, 1, 0);
|
||||
spin_lock_irqsave(&ch->lock, *irq_flags);
|
||||
}
|
||||
|
||||
@ -754,12 +754,12 @@ xpc_process_disconnect(struct xpc_channel *ch, unsigned long *irq_flags)
|
||||
|
||||
/* make sure all activity has settled down first */
|
||||
|
||||
if (atomic_read(&ch->references) > 0 ||
|
||||
((ch->flags & XPC_C_CONNECTEDCALLOUT_MADE) &&
|
||||
!(ch->flags & XPC_C_DISCONNECTINGCALLOUT_MADE))) {
|
||||
if (atomic_read(&ch->kthreads_assigned) > 0 ||
|
||||
atomic_read(&ch->references) > 0) {
|
||||
return;
|
||||
}
|
||||
DBUG_ON(atomic_read(&ch->kthreads_assigned) != 0);
|
||||
DBUG_ON((ch->flags & XPC_C_CONNECTEDCALLOUT_MADE) &&
|
||||
!(ch->flags & XPC_C_DISCONNECTINGCALLOUT_MADE));
|
||||
|
||||
if (part->act_state == XPC_P_DEACTIVATING) {
|
||||
/* can't proceed until the other side disengages from us */
|
||||
@ -1651,6 +1651,11 @@ xpc_disconnect_channel(const int line, struct xpc_channel *ch,
|
||||
/* wake all idle kthreads so they can exit */
|
||||
if (atomic_read(&ch->kthreads_idle) > 0) {
|
||||
wake_up_all(&ch->idle_wq);
|
||||
|
||||
} else if ((ch->flags & XPC_C_CONNECTEDCALLOUT_MADE) &&
|
||||
!(ch->flags & XPC_C_DISCONNECTINGCALLOUT)) {
|
||||
/* start a kthread that will do the xpcDisconnecting callout */
|
||||
xpc_create_kthreads(ch, 1, 1);
|
||||
}
|
||||
|
||||
/* wake those waiting to allocate an entry from the local msg queue */
|
||||
|
@ -681,7 +681,7 @@ xpc_activate_kthreads(struct xpc_channel *ch, int needed)
|
||||
dev_dbg(xpc_chan, "create %d new kthreads, partid=%d, channel=%d\n",
|
||||
needed, ch->partid, ch->number);
|
||||
|
||||
xpc_create_kthreads(ch, needed);
|
||||
xpc_create_kthreads(ch, needed, 0);
|
||||
}
|
||||
|
||||
|
||||
@ -775,26 +775,28 @@ xpc_daemonize_kthread(void *args)
|
||||
xpc_kthread_waitmsgs(part, ch);
|
||||
}
|
||||
|
||||
if (atomic_dec_return(&ch->kthreads_assigned) == 0) {
|
||||
spin_lock_irqsave(&ch->lock, irq_flags);
|
||||
if ((ch->flags & XPC_C_CONNECTEDCALLOUT_MADE) &&
|
||||
!(ch->flags & XPC_C_DISCONNECTINGCALLOUT)) {
|
||||
ch->flags |= XPC_C_DISCONNECTINGCALLOUT;
|
||||
spin_unlock_irqrestore(&ch->lock, irq_flags);
|
||||
/* let registerer know that connection is disconnecting */
|
||||
|
||||
xpc_disconnect_callout(ch, xpcDisconnecting);
|
||||
|
||||
spin_lock_irqsave(&ch->lock, irq_flags);
|
||||
ch->flags |= XPC_C_DISCONNECTINGCALLOUT_MADE;
|
||||
}
|
||||
spin_lock_irqsave(&ch->lock, irq_flags);
|
||||
if ((ch->flags & XPC_C_CONNECTEDCALLOUT_MADE) &&
|
||||
!(ch->flags & XPC_C_DISCONNECTINGCALLOUT)) {
|
||||
ch->flags |= XPC_C_DISCONNECTINGCALLOUT;
|
||||
spin_unlock_irqrestore(&ch->lock, irq_flags);
|
||||
|
||||
xpc_disconnect_callout(ch, xpcDisconnecting);
|
||||
|
||||
spin_lock_irqsave(&ch->lock, irq_flags);
|
||||
ch->flags |= XPC_C_DISCONNECTINGCALLOUT_MADE;
|
||||
}
|
||||
spin_unlock_irqrestore(&ch->lock, irq_flags);
|
||||
|
||||
if (atomic_dec_return(&ch->kthreads_assigned) == 0) {
|
||||
if (atomic_dec_return(&part->nchannels_engaged) == 0) {
|
||||
xpc_mark_partition_disengaged(part);
|
||||
xpc_IPI_send_disengage(part);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
xpc_msgqueue_deref(ch);
|
||||
|
||||
dev_dbg(xpc_chan, "kthread exiting, partid=%d, channel=%d\n",
|
||||
@ -818,7 +820,8 @@ xpc_daemonize_kthread(void *args)
|
||||
* partition.
|
||||
*/
|
||||
void
|
||||
xpc_create_kthreads(struct xpc_channel *ch, int needed)
|
||||
xpc_create_kthreads(struct xpc_channel *ch, int needed,
|
||||
int ignore_disconnecting)
|
||||
{
|
||||
unsigned long irq_flags;
|
||||
pid_t pid;
|
||||
@ -833,16 +836,38 @@ xpc_create_kthreads(struct xpc_channel *ch, int needed)
|
||||
* kthread. That kthread is responsible for doing the
|
||||
* counterpart to the following before it exits.
|
||||
*/
|
||||
if (ignore_disconnecting) {
|
||||
if (!atomic_inc_not_zero(&ch->kthreads_assigned)) {
|
||||
/* kthreads assigned had gone to zero */
|
||||
BUG_ON(!(ch->flags &
|
||||
XPC_C_DISCONNECTINGCALLOUT_MADE));
|
||||
break;
|
||||
}
|
||||
|
||||
} else if (ch->flags & XPC_C_DISCONNECTING) {
|
||||
break;
|
||||
|
||||
} else if (atomic_inc_return(&ch->kthreads_assigned) == 1) {
|
||||
if (atomic_inc_return(&part->nchannels_engaged) == 1)
|
||||
xpc_mark_partition_engaged(part);
|
||||
}
|
||||
(void) xpc_part_ref(part);
|
||||
xpc_msgqueue_ref(ch);
|
||||
if (atomic_inc_return(&ch->kthreads_assigned) == 1 &&
|
||||
atomic_inc_return(&part->nchannels_engaged) == 1) {
|
||||
xpc_mark_partition_engaged(part);
|
||||
}
|
||||
|
||||
pid = kernel_thread(xpc_daemonize_kthread, (void *) args, 0);
|
||||
if (pid < 0) {
|
||||
/* the fork failed */
|
||||
|
||||
/*
|
||||
* NOTE: if (ignore_disconnecting &&
|
||||
* !(ch->flags & XPC_C_DISCONNECTINGCALLOUT)) is true,
|
||||
* then we'll deadlock if all other kthreads assigned
|
||||
* to this channel are blocked in the channel's
|
||||
* registerer, because the only thing that will unblock
|
||||
* them is the xpcDisconnecting callout that this
|
||||
* failed kernel_thread would have made.
|
||||
*/
|
||||
|
||||
if (atomic_dec_return(&ch->kthreads_assigned) == 0 &&
|
||||
atomic_dec_return(&part->nchannels_engaged) == 0) {
|
||||
xpc_mark_partition_disengaged(part);
|
||||
@ -857,9 +882,6 @@ xpc_create_kthreads(struct xpc_channel *ch, int needed)
|
||||
* Flag this as an error only if we have an
|
||||
* insufficient #of kthreads for the channel
|
||||
* to function.
|
||||
*
|
||||
* No xpc_msgqueue_ref() is needed here since
|
||||
* the channel mgr is doing this.
|
||||
*/
|
||||
spin_lock_irqsave(&ch->lock, irq_flags);
|
||||
XPC_DISCONNECT_CHANNEL(ch, xpcLackOfResources,
|
||||
|
@ -12,8 +12,8 @@
|
||||
* OS-specific debug break numbers:
|
||||
*/
|
||||
#define __IA64_BREAK_KDB 0x80100
|
||||
#define __IA64_BREAK_KPROBE 0x80200
|
||||
#define __IA64_BREAK_JPROBE 0x80300
|
||||
#define __IA64_BREAK_KPROBE 0x81000 /* .. 0x81fff */
|
||||
#define __IA64_BREAK_JPROBE 0x82000
|
||||
|
||||
/*
|
||||
* OS-specific break numbers:
|
||||
|
@ -115,6 +115,7 @@ struct arch_specific_insn {
|
||||
#define INST_FLAG_BREAK_INST 4
|
||||
unsigned long inst_flag;
|
||||
unsigned short target_br_reg;
|
||||
unsigned short slot;
|
||||
};
|
||||
|
||||
extern int kprobe_exceptions_notify(struct notifier_block *self,
|
||||
|
@ -673,7 +673,7 @@ extern irqreturn_t xpc_notify_IRQ_handler(int, void *);
|
||||
extern void xpc_dropped_IPI_check(struct xpc_partition *);
|
||||
extern void xpc_activate_partition(struct xpc_partition *);
|
||||
extern void xpc_activate_kthreads(struct xpc_channel *, int);
|
||||
extern void xpc_create_kthreads(struct xpc_channel *, int);
|
||||
extern void xpc_create_kthreads(struct xpc_channel *, int, int);
|
||||
extern void xpc_disconnect_wait(int);
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user