diff options
Diffstat (limited to 'arch/ia64/kernel')
-rw-r--r-- | arch/ia64/kernel/Makefile | 1 | ||||
-rw-r--r-- | arch/ia64/kernel/acpi-processor.c | 2 | ||||
-rw-r--r-- | arch/ia64/kernel/entry.S | 6 | ||||
-rw-r--r-- | arch/ia64/kernel/irq_ia64.c | 22 | ||||
-rw-r--r-- | arch/ia64/kernel/kprobes.c | 98 | ||||
-rw-r--r-- | arch/ia64/kernel/msi_ia64.c | 143 | ||||
-rw-r--r-- | arch/ia64/kernel/numa.c | 1 | ||||
-rw-r--r-- | arch/ia64/kernel/process.c | 2 | ||||
-rw-r--r-- | arch/ia64/kernel/setup.c | 1 |
9 files changed, 222 insertions, 54 deletions
diff --git a/arch/ia64/kernel/Makefile b/arch/ia64/kernel/Makefile index 31497496eb4bf2..cfa099b04cda9d 100644 --- a/arch/ia64/kernel/Makefile +++ b/arch/ia64/kernel/Makefile @@ -30,6 +30,7 @@ obj-$(CONFIG_IA64_MCA_RECOVERY) += mca_recovery.o obj-$(CONFIG_KPROBES) += kprobes.o jprobes.o obj-$(CONFIG_IA64_UNCACHED_ALLOCATOR) += uncached.o obj-$(CONFIG_AUDIT) += audit.o +obj-$(CONFIG_PCI_MSI) += msi_ia64.o mca_recovery-y += mca_drv.o mca_drv_asm.o obj-$(CONFIG_IA64_ESI) += esi.o diff --git a/arch/ia64/kernel/acpi-processor.c b/arch/ia64/kernel/acpi-processor.c index e683630c8ce293..4d4993a47e559f 100644 --- a/arch/ia64/kernel/acpi-processor.c +++ b/arch/ia64/kernel/acpi-processor.c @@ -1,5 +1,5 @@ /* - * arch/ia64/kernel/cpufreq/processor.c + * arch/ia64/kernel/acpi-processor.c * * Copyright (C) 2005 Intel Corporation * Venkatesh Pallipadi <venkatesh.pallipadi@intel.com> diff --git a/arch/ia64/kernel/entry.S b/arch/ia64/kernel/entry.S index 12701cf32d9944..3390b7c5a63fab 100644 --- a/arch/ia64/kernel/entry.S +++ b/arch/ia64/kernel/entry.S @@ -1,5 +1,5 @@ /* - * ia64/kernel/entry.S + * arch/ia64/kernel/entry.S * * Kernel entry points. * @@ -492,11 +492,11 @@ GLOBAL_ENTRY(prefetch_stack) br.ret.sptk.many rp END(prefetch_stack) -GLOBAL_ENTRY(execve) +GLOBAL_ENTRY(kernel_execve) mov r15=__NR_execve // put syscall number in place break __BREAK_SYSCALL br.ret.sptk.many rp -END(execve) +END(kernel_execve) GLOBAL_ENTRY(clone) mov r15=__NR_clone // put syscall number in place diff --git a/arch/ia64/kernel/irq_ia64.c b/arch/ia64/kernel/irq_ia64.c index a041367f043bb8..ab2d19c3661f0c 100644 --- a/arch/ia64/kernel/irq_ia64.c +++ b/arch/ia64/kernel/irq_ia64.c @@ -1,5 +1,5 @@ /* - * linux/arch/ia64/kernel/irq.c + * linux/arch/ia64/kernel/irq_ia64.c * * Copyright (C) 1998-2001 Hewlett-Packard Co * Stephane Eranian <eranian@hpl.hp.com> @@ -30,6 +30,7 @@ #include <linux/smp_lock.h> #include <linux/threads.h> #include <linux/bitops.h> +#include <linux/irq.h> #include <asm/delay.h> #include <asm/intrinsics.h> @@ -105,6 +106,25 @@ reserve_irq_vector (int vector) return test_and_set_bit(pos, ia64_vector_mask); } +/* + * Dynamic irq allocate and deallocation for MSI + */ +int create_irq(void) +{ + int vector = assign_irq_vector(AUTO_ASSIGN); + + if (vector >= 0) + dynamic_irq_init(vector); + + return vector; +} + +void destroy_irq(unsigned int irq) +{ + dynamic_irq_cleanup(irq); + free_irq_vector(irq); +} + #ifdef CONFIG_SMP # define IS_RESCHEDULE(vec) (vec == IA64_IPI_RESCHEDULE) #else diff --git a/arch/ia64/kernel/kprobes.c b/arch/ia64/kernel/kprobes.c index 169ec3a7156ce4..51217d63285ea3 100644 --- a/arch/ia64/kernel/kprobes.c +++ b/arch/ia64/kernel/kprobes.c @@ -90,7 +90,7 @@ static void __kprobes update_kprobe_inst_flag(uint template, uint slot, p->ainsn.target_br_reg = 0; /* Check for Break instruction - * Bits 37:40 Major opcode to be zero + * Bits 37:40 Major opcode to be zero * Bits 27:32 X6 to be zero * Bits 32:35 X3 to be zero */ @@ -104,19 +104,19 @@ static void __kprobes update_kprobe_inst_flag(uint template, uint slot, switch (major_opcode) { case INDIRECT_CALL_OPCODE: p->ainsn.inst_flag |= INST_FLAG_FIX_BRANCH_REG; - p->ainsn.target_br_reg = ((kprobe_inst >> 6) & 0x7); - break; + p->ainsn.target_br_reg = ((kprobe_inst >> 6) & 0x7); + break; case IP_RELATIVE_PREDICT_OPCODE: case IP_RELATIVE_BRANCH_OPCODE: p->ainsn.inst_flag |= INST_FLAG_FIX_RELATIVE_IP_ADDR; - break; + break; case IP_RELATIVE_CALL_OPCODE: - p->ainsn.inst_flag |= INST_FLAG_FIX_RELATIVE_IP_ADDR; - p->ainsn.inst_flag |= INST_FLAG_FIX_BRANCH_REG; - p->ainsn.target_br_reg = ((kprobe_inst >> 6) & 0x7); - break; + p->ainsn.inst_flag |= INST_FLAG_FIX_RELATIVE_IP_ADDR; + p->ainsn.inst_flag |= INST_FLAG_FIX_BRANCH_REG; + p->ainsn.target_br_reg = ((kprobe_inst >> 6) & 0x7); + break; } - } else if (bundle_encoding[template][slot] == X) { + } else if (bundle_encoding[template][slot] == X) { switch (major_opcode) { case LONG_CALL_OPCODE: p->ainsn.inst_flag |= INST_FLAG_FIX_BRANCH_REG; @@ -258,18 +258,18 @@ static void __kprobes get_kprobe_inst(bundle_t *bundle, uint slot, switch (slot) { case 0: - *major_opcode = (bundle->quad0.slot0 >> SLOT0_OPCODE_SHIFT); - *kprobe_inst = bundle->quad0.slot0; - break; + *major_opcode = (bundle->quad0.slot0 >> SLOT0_OPCODE_SHIFT); + *kprobe_inst = bundle->quad0.slot0; + break; case 1: - *major_opcode = (bundle->quad1.slot1_p1 >> SLOT1_p1_OPCODE_SHIFT); - kprobe_inst_p0 = bundle->quad0.slot1_p0; - kprobe_inst_p1 = bundle->quad1.slot1_p1; - *kprobe_inst = kprobe_inst_p0 | (kprobe_inst_p1 << (64-46)); + *major_opcode = (bundle->quad1.slot1_p1 >> SLOT1_p1_OPCODE_SHIFT); + kprobe_inst_p0 = bundle->quad0.slot1_p0; + kprobe_inst_p1 = bundle->quad1.slot1_p1; + *kprobe_inst = kprobe_inst_p0 | (kprobe_inst_p1 << (64-46)); break; case 2: - *major_opcode = (bundle->quad1.slot2 >> SLOT2_OPCODE_SHIFT); - *kprobe_inst = bundle->quad1.slot2; + *major_opcode = (bundle->quad1.slot2 >> SLOT2_OPCODE_SHIFT); + *kprobe_inst = bundle->quad1.slot2; break; } } @@ -290,11 +290,11 @@ static int __kprobes valid_kprobe_addr(int template, int slot, return -EINVAL; } - if (in_ivt_functions(addr)) { - printk(KERN_WARNING "Kprobes can't be inserted inside " + if (in_ivt_functions(addr)) { + printk(KERN_WARNING "Kprobes can't be inserted inside " "IVT functions at 0x%lx\n", addr); - return -EINVAL; - } + return -EINVAL; + } if (slot == 1 && bundle_encoding[template][1] != L) { printk(KERN_WARNING "Inserting kprobes on slot #1 " @@ -338,12 +338,13 @@ static void kretprobe_trampoline(void) int __kprobes trampoline_probe_handler(struct kprobe *p, struct pt_regs *regs) { struct kretprobe_instance *ri = NULL; - struct hlist_head *head; + struct hlist_head *head, empty_rp; struct hlist_node *node, *tmp; unsigned long flags, orig_ret_address = 0; unsigned long trampoline_address = ((struct fnptr *)kretprobe_trampoline)->ip; + INIT_HLIST_HEAD(&empty_rp); spin_lock_irqsave(&kretprobe_lock, flags); head = kretprobe_inst_table_head(current); @@ -369,7 +370,7 @@ int __kprobes trampoline_probe_handler(struct kprobe *p, struct pt_regs *regs) ri->rp->handler(ri, regs); orig_ret_address = (unsigned long)ri->ret_addr; - recycle_rp_inst(ri); + recycle_rp_inst(ri, &empty_rp); if (orig_ret_address != trampoline_address) /* @@ -387,6 +388,10 @@ int __kprobes trampoline_probe_handler(struct kprobe *p, struct pt_regs *regs) spin_unlock_irqrestore(&kretprobe_lock, flags); preempt_enable_no_resched(); + hlist_for_each_entry_safe(ri, node, tmp, &empty_rp, hlist) { + hlist_del(&ri->hlist); + kfree(ri); + } /* * By returning a non-zero value, we are telling * kprobe_handler() that we don't want the post_handler @@ -424,14 +429,14 @@ int __kprobes arch_prepare_kprobe(struct kprobe *p) bundle_t *bundle; bundle = &((kprobe_opcode_t *)kprobe_addr)->bundle; - template = bundle->quad0.template; + template = bundle->quad0.template; if(valid_kprobe_addr(template, slot, addr)) return -EINVAL; /* Move to slot 2, if bundle is MLX type and kprobe slot is 1 */ - if (slot == 1 && bundle_encoding[template][1] == L) - slot++; + if (slot == 1 && bundle_encoding[template][1] == L) + slot++; /* Get kprobe_inst and major_opcode from the bundle */ get_kprobe_inst(bundle, slot, &kprobe_inst, &major_opcode); @@ -489,21 +494,22 @@ void __kprobes arch_remove_kprobe(struct kprobe *p) */ static void __kprobes resume_execution(struct kprobe *p, struct pt_regs *regs) { - unsigned long bundle_addr = (unsigned long) (&p->ainsn.insn->bundle); - unsigned long resume_addr = (unsigned long)p->addr & ~0xFULL; - unsigned long template; - int slot = ((unsigned long)p->addr & 0xf); + unsigned long bundle_addr = (unsigned long) (&p->ainsn.insn->bundle); + unsigned long resume_addr = (unsigned long)p->addr & ~0xFULL; + unsigned long template; + int slot = ((unsigned long)p->addr & 0xf); template = p->ainsn.insn->bundle.quad0.template; - if (slot == 1 && bundle_encoding[template][1] == L) - slot = 2; + if (slot == 1 && bundle_encoding[template][1] == L) + slot = 2; if (p->ainsn.inst_flag) { if (p->ainsn.inst_flag & INST_FLAG_FIX_RELATIVE_IP_ADDR) { /* Fix relative IP address */ - regs->cr_iip = (regs->cr_iip - bundle_addr) + resume_addr; + regs->cr_iip = (regs->cr_iip - bundle_addr) + + resume_addr; } if (p->ainsn.inst_flag & INST_FLAG_FIX_BRANCH_REG) { @@ -540,18 +546,18 @@ static void __kprobes resume_execution(struct kprobe *p, struct pt_regs *regs) } if (slot == 2) { - if (regs->cr_iip == bundle_addr + 0x10) { - regs->cr_iip = resume_addr + 0x10; - } - } else { - if (regs->cr_iip == bundle_addr) { - regs->cr_iip = resume_addr; - } + if (regs->cr_iip == bundle_addr + 0x10) { + regs->cr_iip = resume_addr + 0x10; + } + } else { + if (regs->cr_iip == bundle_addr) { + regs->cr_iip = resume_addr; + } } turn_ss_off: - /* Turn off Single Step bit */ - ia64_psr(regs)->ss = 0; + /* Turn off Single Step bit */ + ia64_psr(regs)->ss = 0; } static void __kprobes prepare_ss(struct kprobe *p, struct pt_regs *regs) @@ -587,7 +593,7 @@ static int __kprobes is_ia64_break_inst(struct pt_regs *regs) /* Move to slot 2, if bundle is MLX type and kprobe slot is 1 */ if (slot == 1 && bundle_encoding[template][1] == L) - slot++; + slot++; /* Get Kprobe probe instruction at given slot*/ get_kprobe_inst(&bundle, slot, &kprobe_inst, &major_opcode); @@ -627,7 +633,7 @@ static int __kprobes pre_kprobes_handler(struct die_args *args) if (p) { if ((kcb->kprobe_status == KPROBE_HIT_SS) && (p->ainsn.inst_flag == INST_FLAG_BREAK_INST)) { - ia64_psr(regs)->ss = 0; + ia64_psr(regs)->ss = 0; goto no_kprobe; } /* We have reentered the pre_kprobe_handler(), since @@ -887,7 +893,7 @@ int __kprobes setjmp_pre_handler(struct kprobe *p, struct pt_regs *regs) * fix the return address to our jprobe_inst_return() function * in the jprobes.S file */ - regs->b0 = ((struct fnptr *)(jprobe_inst_return))->ip; + regs->b0 = ((struct fnptr *)(jprobe_inst_return))->ip; return 1; } diff --git a/arch/ia64/kernel/msi_ia64.c b/arch/ia64/kernel/msi_ia64.c new file mode 100644 index 00000000000000..822e59a1b822fd --- /dev/null +++ b/arch/ia64/kernel/msi_ia64.c @@ -0,0 +1,143 @@ +/* + * MSI hooks for standard x86 apic + */ + +#include <linux/pci.h> +#include <linux/irq.h> +#include <linux/msi.h> +#include <asm/smp.h> + +/* + * Shifts for APIC-based data + */ + +#define MSI_DATA_VECTOR_SHIFT 0 +#define MSI_DATA_VECTOR(v) (((u8)v) << MSI_DATA_VECTOR_SHIFT) + +#define MSI_DATA_DELIVERY_SHIFT 8 +#define MSI_DATA_DELIVERY_FIXED (0 << MSI_DATA_DELIVERY_SHIFT) +#define MSI_DATA_DELIVERY_LOWPRI (1 << MSI_DATA_DELIVERY_SHIFT) + +#define MSI_DATA_LEVEL_SHIFT 14 +#define MSI_DATA_LEVEL_DEASSERT (0 << MSI_DATA_LEVEL_SHIFT) +#define MSI_DATA_LEVEL_ASSERT (1 << MSI_DATA_LEVEL_SHIFT) + +#define MSI_DATA_TRIGGER_SHIFT 15 +#define MSI_DATA_TRIGGER_EDGE (0 << MSI_DATA_TRIGGER_SHIFT) +#define MSI_DATA_TRIGGER_LEVEL (1 << MSI_DATA_TRIGGER_SHIFT) + +/* + * Shift/mask fields for APIC-based bus address + */ + +#define MSI_TARGET_CPU_SHIFT 4 +#define MSI_ADDR_HEADER 0xfee00000 + +#define MSI_ADDR_DESTID_MASK 0xfff0000f +#define MSI_ADDR_DESTID_CPU(cpu) ((cpu) << MSI_TARGET_CPU_SHIFT) + +#define MSI_ADDR_DESTMODE_SHIFT 2 +#define MSI_ADDR_DESTMODE_PHYS (0 << MSI_ADDR_DESTMODE_SHIFT) +#define MSI_ADDR_DESTMODE_LOGIC (1 << MSI_ADDR_DESTMODE_SHIFT) + +#define MSI_ADDR_REDIRECTION_SHIFT 3 +#define MSI_ADDR_REDIRECTION_CPU (0 << MSI_ADDR_REDIRECTION_SHIFT) +#define MSI_ADDR_REDIRECTION_LOWPRI (1 << MSI_ADDR_REDIRECTION_SHIFT) + +static struct irq_chip ia64_msi_chip; + +#ifdef CONFIG_SMP +static void ia64_set_msi_irq_affinity(unsigned int irq, cpumask_t cpu_mask) +{ + struct msi_msg msg; + u32 addr; + + read_msi_msg(irq, &msg); + + addr = msg.address_lo; + addr &= MSI_ADDR_DESTID_MASK; + addr |= MSI_ADDR_DESTID_CPU(cpu_physical_id(first_cpu(cpu_mask))); + msg.address_lo = addr; + + write_msi_msg(irq, &msg); + set_native_irq_info(irq, cpu_mask); +} +#endif /* CONFIG_SMP */ + +int ia64_setup_msi_irq(unsigned int irq, struct pci_dev *pdev) +{ + struct msi_msg msg; + unsigned long dest_phys_id; + unsigned int vector; + + dest_phys_id = cpu_physical_id(first_cpu(cpu_online_map)); + vector = irq; + + msg.address_hi = 0; + msg.address_lo = + MSI_ADDR_HEADER | + MSI_ADDR_DESTMODE_PHYS | + MSI_ADDR_REDIRECTION_CPU | + MSI_ADDR_DESTID_CPU(dest_phys_id); + + msg.data = + MSI_DATA_TRIGGER_EDGE | + MSI_DATA_LEVEL_ASSERT | + MSI_DATA_DELIVERY_FIXED | + MSI_DATA_VECTOR(vector); + + write_msi_msg(irq, &msg); + set_irq_chip_and_handler(irq, &ia64_msi_chip, handle_edge_irq); + + return 0; +} + +void ia64_teardown_msi_irq(unsigned int irq) +{ + return; /* no-op */ +} + +static void ia64_ack_msi_irq(unsigned int irq) +{ + move_native_irq(irq); + ia64_eoi(); +} + +static int ia64_msi_retrigger_irq(unsigned int irq) +{ + unsigned int vector = irq; + ia64_resend_irq(vector); + + return 1; +} + +/* + * Generic ops used on most IA64 platforms. + */ +static struct irq_chip ia64_msi_chip = { + .name = "PCI-MSI", + .mask = mask_msi_irq, + .unmask = unmask_msi_irq, + .ack = ia64_ack_msi_irq, +#ifdef CONFIG_SMP + .set_affinity = ia64_set_msi_irq_affinity, +#endif + .retrigger = ia64_msi_retrigger_irq, +}; + + +int arch_setup_msi_irq(unsigned int irq, struct pci_dev *pdev) +{ + if (platform_setup_msi_irq) + return platform_setup_msi_irq(irq, pdev); + + return ia64_setup_msi_irq(irq, pdev); +} + +void arch_teardown_msi_irq(unsigned int irq) +{ + if (platform_teardown_msi_irq) + return platform_teardown_msi_irq(irq); + + return ia64_teardown_msi_irq(irq); +} diff --git a/arch/ia64/kernel/numa.c b/arch/ia64/kernel/numa.c index 20340631179f66..a78b45f5fe2f9d 100644 --- a/arch/ia64/kernel/numa.c +++ b/arch/ia64/kernel/numa.c @@ -28,6 +28,7 @@ u16 cpu_to_node_map[NR_CPUS] __cacheline_aligned; EXPORT_SYMBOL(cpu_to_node_map); cpumask_t node_to_cpu_mask[MAX_NUMNODES] __cacheline_aligned; +EXPORT_SYMBOL(node_to_cpu_mask); void __cpuinit map_cpu_to_node(int cpu, int nid) { diff --git a/arch/ia64/kernel/process.c b/arch/ia64/kernel/process.c index ea914cc6812a0a..51922b98086afb 100644 --- a/arch/ia64/kernel/process.c +++ b/arch/ia64/kernel/process.c @@ -8,8 +8,6 @@ * 2005-10-07 Keith Owens <kaos@sgi.com> * Add notify_die() hooks. */ -#define __KERNEL_SYSCALLS__ /* see <asm/unistd.h> */ - #include <linux/cpu.h> #include <linux/pm.h> #include <linux/elf.h> diff --git a/arch/ia64/kernel/setup.c b/arch/ia64/kernel/setup.c index 84f93c0f2c666b..c4caa800349220 100644 --- a/arch/ia64/kernel/setup.c +++ b/arch/ia64/kernel/setup.c @@ -54,7 +54,6 @@ #include <asm/processor.h> #include <asm/sal.h> #include <asm/sections.h> -#include <asm/serial.h> #include <asm/setup.h> #include <asm/smp.h> #include <asm/system.h> |