Commit a0adf3b1 authored by David S. Miller's avatar David S. Miller

Merge davem@nuts.davemloft.net:/disk1/BK/sparc-2.6

into kernel.bkbits.net:/home/davem/sparc-2.6
parents 6ce8ea8a 39e8d677
......@@ -74,7 +74,7 @@ sys_call_table:
/*260*/ .long sys_sched_getaffinity, sys_sched_setaffinity, sys_timer_settime, sys_timer_gettime, sys_timer_getoverrun
/*265*/ .long sys_timer_delete, sys_timer_create, sys_nis_syscall, sys_io_setup, sys_io_destroy
/*270*/ .long sys_io_submit, sys_io_cancel, sys_io_getevents, sys_mq_open, sys_mq_unlink
/*275*/ .long sys_mq_timedsend, sys_mq_timedreceive, sys_mq_notify, sys_mq_getsetattr, sys_ni_syscall
/*275*/ .long sys_mq_timedsend, sys_mq_timedreceive, sys_mq_notify, sys_mq_getsetattr, sys_waitid
/*280*/ .long sys_ni_syscall, sys_ni_syscall, sys_ni_syscall
#ifdef CONFIG_SUNOS_EMUL
......
......@@ -11,6 +11,16 @@ config DEBUG_STACK_USAGE
This option will slow down process creation somewhat.
config KPROBES
bool "Kprobes"
depends on DEBUG_KERNEL
help
Kprobes allows you to trap at almost any kernel address and
execute a callback function. register_kprobe() establishes
a probepoint and specifies the callback. Kprobes is useful
for kernel debugging, non-intrusive instrumentation and testing.
If in doubt, say "N".
config DEBUG_DCFLUSH
bool "D-cache flush debugging"
depends on DEBUG_KERNEL
......
#
# Automatically generated make config: don't edit
# Linux kernel version: 2.6.9-rc1
# Fri Aug 27 17:37:00 2004
# Wed Sep 1 17:54:49 2004
#
CONFIG_64BIT=y
CONFIG_MMU=y
......@@ -35,6 +35,8 @@ CONFIG_IOSCHED_AS=y
CONFIG_IOSCHED_DEADLINE=y
CONFIG_IOSCHED_CFQ=y
# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
CONFIG_SHMEM=y
# CONFIG_TINY_SHMEM is not set
#
# Loadable module support
......@@ -332,7 +334,8 @@ CONFIG_AIC79XX_RESET_DELAY_MS=15000
# CONFIG_AIC79XX_DEBUG_ENABLE is not set
CONFIG_AIC79XX_DEBUG_MASK=0
# CONFIG_AIC79XX_REG_PRETTY_PRINT is not set
# CONFIG_SCSI_MEGARAID is not set
# CONFIG_MEGARAID_NEWGEN is not set
# CONFIG_MEGARAID_LEGACY is not set
CONFIG_SCSI_SATA=y
CONFIG_SCSI_SATA_SVW=m
CONFIG_SCSI_ATA_PIIX=m
......@@ -357,9 +360,7 @@ CONFIG_SCSI_SYM53C8XX_DMA_ADDRESSING_MODE=1
CONFIG_SCSI_SYM53C8XX_DEFAULT_TAGS=16
CONFIG_SCSI_SYM53C8XX_MAX_TAGS=64
# CONFIG_SCSI_SYM53C8XX_IOMAPPED is not set
CONFIG_SCSI_IPR=m
# CONFIG_SCSI_IPR_TRACE is not set
# CONFIG_SCSI_IPR_DUMP is not set
# CONFIG_SCSI_IPR is not set
CONFIG_SCSI_QLOGIC_ISP=m
CONFIG_SCSI_QLOGIC_FC=y
CONFIG_SCSI_QLOGIC_FC_FIRMWARE=y
......@@ -417,7 +418,6 @@ CONFIG_DM_ZERO=m
#
CONFIG_FUSION=m
CONFIG_FUSION_MAX_SGE=40
CONFIG_FUSION_ISENSE=m
CONFIG_FUSION_CTL=m
CONFIG_FUSION_LAN=m
......@@ -1757,6 +1757,7 @@ CONFIG_MAGIC_SYSRQ=y
# CONFIG_DEBUG_BUGVERBOSE is not set
# CONFIG_DEBUG_INFO is not set
# CONFIG_DEBUG_STACK_USAGE is not set
CONFIG_KPROBES=y
# CONFIG_DEBUG_DCFLUSH is not set
# CONFIG_STACK_DEBUG is not set
# CONFIG_DEBUG_BOOTMEM is not set
......
......@@ -22,6 +22,7 @@ obj-$(CONFIG_BINFMT_AOUT32) += binfmt_aout32.o
obj-$(CONFIG_MODULES) += module.o
obj-$(CONFIG_US3_FREQ) += us3_cpufreq.o
obj-$(CONFIG_US2E_FREQ) += us2e_cpufreq.o
obj-$(CONFIG_KPROBES) += kprobes.o
ifdef CONFIG_SUNOS_EMUL
obj-y += sys_sunos32.o sunos_ioctl32.o
......
......@@ -791,16 +791,24 @@ void handler_irq(int irq, struct pt_regs *regs)
#endif
if ((flags & IBF_MULTI) == 0) {
struct irqaction *ap = bp->irq_info;
ap->handler(__irq(bp), ap->dev_id, regs);
random |= ap->flags & SA_SAMPLE_RANDOM;
int ret;
ret = ap->handler(__irq(bp), ap->dev_id, regs);
if (ret == IRQ_HANDLED)
random |= ap->flags;
} else {
void **vector = (void **)bp->irq_info;
int ent;
for (ent = 0; ent < 4; ent++) {
struct irqaction *ap = vector[ent];
if (ap != NULL) {
ap->handler(__irq(bp), ap->dev_id, regs);
random |= ap->flags & SA_SAMPLE_RANDOM;
int ret;
ret = ap->handler(__irq(bp),
ap->dev_id,
regs);
if (ret == IRQ_HANDLED)
random |= ap->flags;
}
}
}
......@@ -813,8 +821,9 @@ void handler_irq(int irq, struct pt_regs *regs)
}
#endif
upa_writel(ICLR_IDLE, bp->iclr);
/* Test and add entropy */
if (random)
if (random & SA_SAMPLE_RANDOM)
add_interrupt_randomness(irq);
}
} else
......
/* arch/sparc64/kernel/kprobes.c
*
* Copyright (C) 2004 David S. Miller <davem@davemloft.net>
*/
#include <linux/config.h>
#include <linux/kernel.h>
#include <linux/kprobes.h>
#include <asm/kdebug.h>
#include <asm/signal.h>
/* We do not have hardware single-stepping, so in order
* to implement post handlers correctly we use two breakpoint
* instructions.
*
* 1) ta 0x70 --> 0x91d02070
* 2) ta 0x71 --> 0x91d02071
*
* When these are hit, control is transferred to kprobe_trap()
* below. The arg 'level' tells us which of the two traps occurred.
*
* Initially, the instruction at p->addr gets set to "ta 0x70"
* by code in register_kprobe() by setting that memory address
* to BREAKPOINT_INSTRUCTION. When this breakpoint is hit
* the following happens:
*
* 1) We run the pre-handler
* 2) We replace p->addr with the original opcode
* 3) We set the instruction at "regs->npc" to "ta 0x71"
* 4) We mark that we are waiting for the second breakpoint
* to hit and return from the trap.
*
* At this point we wait for the second breakpoint to hit.
* When it does:
*
* 1) We run the post-handler
* 2) We re-install "ta 0x70" at p->addr
* 3) We restore the opcode at the "ta 0x71" breakpoint
* 4) We reset our "waiting for "ta 0x71" state
* 5) We return from the trap
*
* We could use the trick used by the i386 kprobe code but I
* think that scheme has problems with exception tables. On i386
* they single-step over the original instruction stored at
* kprobe->insn. So they set the processor to single step, and
* set the program counter to kprobe->insn.
*
* But that explodes if the original opcode is a user space
* access instruction and that faults. It will go wrong because
* since the location of the instruction being executed is
* different from that recorded in the exception tables, the
* kernel will not find it and this will cause an erroneous
* kernel OOPS.
*/
void arch_prepare_kprobe(struct kprobe *p)
{
p->insn[0] = *p->addr;
p->insn[1] = 0xdeadbeef;
}
static void prepare_singlestep(struct kprobe *p, struct pt_regs *regs)
{
u32 *insn2 = (u32 *) regs->tpc;
p->insn[1] = *insn2;
*insn2 = BREAKPOINT_INSTRUCTION_2;
flushi(insn2);
}
static void undo_singlestep(struct kprobe *p, struct pt_regs *regs)
{
u32 *insn2 = (u32 *) regs->tpc;
BUG_ON(p->insn[1] == 0xdeadbeef);
*insn2 = p->insn[1];
flushi(insn2);
p->insn[1] = 0xdeadbeef;
}
/* kprobe_status settings */
#define KPROBE_HIT_ACTIVE 0x00000001
#define KPROBE_HIT_SS 0x00000002
static struct kprobe *current_kprobe;
static unsigned int kprobe_status;
static int kprobe_handler(struct pt_regs *regs)
{
struct kprobe *p;
void *addr = (void *) regs->tpc;
int ret = 0;
preempt_disable();
if (kprobe_running()) {
p = get_kprobe(addr);
if (p) {
*p->addr = p->opcode;
flushi(p->addr);
ret = 1;
} else {
p = current_kprobe;
if (p->break_handler && p->break_handler(p, regs))
goto ss_probe;
}
goto no_kprobe;
}
lock_kprobes();
p = get_kprobe(addr);
if (!p) {
unlock_kprobes();
if (*(u32 *)addr != BREAKPOINT_INSTRUCTION)
ret = 1;
goto no_kprobe;
}
kprobe_status = KPROBE_HIT_ACTIVE;
current_kprobe = p;
if (p->pre_handler(p, regs))
return 1;
ss_probe:
prepare_singlestep(p, regs);
kprobe_status = KPROBE_HIT_SS;
return 1;
no_kprobe:
preempt_enable_no_resched();
return ret;
}
static int post_kprobe_handler(struct pt_regs *regs)
{
u32 *insn_p = (u32 *) regs->tpc;
if (!kprobe_running() || (*insn_p != BREAKPOINT_INSTRUCTION_2))
return 0;
if (current_kprobe->post_handler)
current_kprobe->post_handler(current_kprobe, regs, 0);
undo_singlestep(current_kprobe, regs);
unlock_kprobes();
preempt_enable_no_resched();
return 1;
}
/* Interrupts disabled, kprobe_lock held. */
static inline int kprobe_fault_handler(struct pt_regs *regs, int trapnr)
{
if (current_kprobe->fault_handler
&& current_kprobe->fault_handler(current_kprobe, regs, trapnr))
return 1;
if (kprobe_status & KPROBE_HIT_SS) {
undo_singlestep(current_kprobe, regs);
unlock_kprobes();
preempt_enable_no_resched();
}
return 0;
}
/*
* Wrapper routine to for handling exceptions.
*/
int kprobe_exceptions_notify(struct notifier_block *self, unsigned long val,
void *data)
{
struct die_args *args = (struct die_args *)data;
switch (val) {
case DIE_DEBUG:
if (kprobe_handler(args->regs))
return NOTIFY_OK;
break;
case DIE_DEBUG_2:
if (post_kprobe_handler(args->regs))
return NOTIFY_OK;
break;
case DIE_GPF:
if (kprobe_running() &&
kprobe_fault_handler(args->regs, args->trapnr))
return NOTIFY_OK;
break;
case DIE_PAGE_FAULT:
if (kprobe_running() &&
kprobe_fault_handler(args->regs, args->trapnr))
return NOTIFY_OK;
break;
default:
break;
}
return NOTIFY_BAD;
}
asmlinkage void kprobe_trap(unsigned long trap_level, struct pt_regs *regs)
{
BUG_ON(trap_level != 0x170 && trap_level != 0x171);
if (user_mode(regs)) {
local_irq_enable();
bad_trap(regs, trap_level);
return;
}
/* trap_level == 0x170 --> ta 0x70
* trap_level == 0x171 --> ta 0x71
*/
if (notify_die((trap_level == 0x170) ? DIE_DEBUG : DIE_DEBUG_2,
(trap_level == 0x170) ? "debug" : "debug_2",
regs, 0, trap_level, SIGTRAP) != NOTIFY_OK)
bad_trap(regs, trap_level);
}
/* Jprobes support. */
static struct pt_regs jprobe_saved_regs;
static struct sparc_stackf jprobe_saved_stack;
int setjmp_pre_handler(struct kprobe *p, struct pt_regs *regs)
{
struct jprobe *jp = container_of(p, struct jprobe, kp);
memcpy(&jprobe_saved_regs, regs, sizeof(*regs));
/* Save a whole stack frame, this gets arguments
* pushed onto the stack after using up all the
* arg registers.
*/
memcpy(&jprobe_saved_stack,
(char *) (regs->u_regs[UREG_FP] + STACK_BIAS),
sizeof(jprobe_saved_stack));
regs->tpc = (unsigned long) jp->entry;
regs->tnpc = ((unsigned long) jp->entry) + 0x4UL;
return 1;
}
void jprobe_return(void)
{
preempt_enable_no_resched();
__asm__ __volatile__(
".globl jprobe_return_trap_instruction\n"
"jprobe_return_trap_instruction:\n\t"
"ta 0x70");
}
extern void jprobe_return_trap_instruction(void);
int longjmp_break_handler(struct kprobe *p, struct pt_regs *regs)
{
u32 *addr = (u32 *) regs->tpc;
if (addr == (u32 *) jprobe_return_trap_instruction) {
/* Restore old register state. Do pt_regs
* first so that UREG_FP is the original one for
* the stack frame restore.
*/
memcpy(regs, &jprobe_saved_regs, sizeof(*regs));
memcpy((char *) (regs->u_regs[UREG_FP] + STACK_BIAS),
&jprobe_saved_stack,
sizeof(jprobe_saved_stack));
return 1;
}
return 0;
}
......@@ -41,7 +41,6 @@ asmlinkage int sys_pciconfig_write(unsigned long bus, unsigned long dfn,
#else
/* List of all PCI controllers found in the system. */
spinlock_t pci_controller_lock = SPIN_LOCK_UNLOCKED;
struct pci_controller_info *pci_controller_root = NULL;
/* Each PCI controller found gets a unique index. */
......@@ -298,12 +297,9 @@ static void __init pci_controller_probe(void)
static void __init pci_scan_each_controller_bus(void)
{
struct pci_controller_info *p;
unsigned long flags;
spin_lock_irqsave(&pci_controller_lock, flags);
for (p = pci_controller_root; p; p = p->next)
p->scan_bus(p);
spin_unlock_irqrestore(&pci_controller_lock, flags);
}
/* Reorder the pci_dev chain, so that onboard devices come first
......
......@@ -15,18 +15,13 @@
*/
void __init pci_fixup_host_bridge_self(struct pci_bus *pbus)
{
struct list_head *walk = &pbus->devices;
walk = walk->next;
while (walk != &pbus->devices) {
struct pci_dev *pdev = pci_dev_b(walk);
struct pci_dev *pdev;
list_for_each_entry(pdev, &pbus->devices, bus_list) {
if (pdev->class >> 8 == PCI_CLASS_BRIDGE_HOST) {
pbus->self = pdev;
return;
}
walk = walk->next;
}
prom_printf("PCI: Critical error, cannot find host bridge PDEV.\n");
......@@ -217,31 +212,18 @@ void __init pci_fill_in_pbm_cookies(struct pci_bus *pbus,
struct pci_pbm_info *pbm,
int prom_node)
{
struct list_head *walk = &pbus->devices;
/* This loop is coded like this because the cookie
* fillin routine can delete devices from the tree.
*/
walk = walk->next;
while (walk != &pbus->devices) {
struct pci_dev *pdev = pci_dev_b(walk);
struct list_head *walk_next = walk->next;
struct pci_dev *pdev, *pdev_next;
struct pci_bus *this_pbus, *pbus_next;
/* This must be _safe because the cookie fillin
routine can delete devices from the tree. */
list_for_each_entry_safe(pdev, pdev_next, &pbus->devices, bus_list)
pdev_cookie_fillin(pbm, pdev, prom_node);
walk = walk_next;
}
walk = &pbus->children;
walk = walk->next;
while (walk != &pbus->children) {
struct pci_bus *this_pbus = pci_bus_b(walk);
list_for_each_entry_safe(this_pbus, pbus_next, &pbus->children, node) {
struct pcidev_cookie *pcp = this_pbus->self->sysdata;
struct list_head *walk_next = walk->next;
pci_fill_in_pbm_cookies(this_pbus, pbm, pcp->prom_node);
walk = walk_next;
}
}
......@@ -431,14 +413,14 @@ static void __init pdev_record_assignments(struct pci_pbm_info *pbm,
void __init pci_record_assignments(struct pci_pbm_info *pbm,
struct pci_bus *pbus)
{
struct list_head *walk = &pbus->devices;
struct pci_dev *dev;
struct pci_bus *bus;
for (walk = walk->next; walk != &pbus->devices; walk = walk->next)
pdev_record_assignments(pbm, pci_dev_b(walk));
list_for_each_entry(dev, &pbus->devices, bus_list)
pdev_record_assignments(pbm, dev);
walk = &pbus->children;
for (walk = walk->next; walk != &pbus->children; walk = walk->next)
pci_record_assignments(pbm, pci_bus_b(walk));
list_for_each_entry(bus, &pbus->children, node)
pci_record_assignments(pbm, bus);
}
/* Return non-zero if PDEV has implicit I/O resources even
......@@ -549,14 +531,14 @@ static void __init pdev_assign_unassigned(struct pci_pbm_info *pbm,
void __init pci_assign_unassigned(struct pci_pbm_info *pbm,
struct pci_bus *pbus)
{
struct list_head *walk = &pbus->devices;
struct pci_dev *dev;
struct pci_bus *bus;
for (walk = walk->next; walk != &pbus->devices; walk = walk->next)
pdev_assign_unassigned(pbm, pci_dev_b(walk));
list_for_each_entry(dev, &pbus->devices, bus_list)
pdev_assign_unassigned(pbm, dev);
walk = &pbus->children;
for (walk = walk->next; walk != &pbus->children; walk = walk->next)
pci_assign_unassigned(pbm, pci_bus_b(walk));
list_for_each_entry(bus, &pbus->children, node)
pci_assign_unassigned(pbm, bus);
}
static int __init pci_intmap_match(struct pci_dev *pdev, unsigned int *interrupt)
......@@ -797,14 +779,14 @@ static void __init pdev_fixup_irq(struct pci_dev *pdev)
void __init pci_fixup_irq(struct pci_pbm_info *pbm,
struct pci_bus *pbus)
{
struct list_head *walk = &pbus->devices;
struct pci_dev *dev;
struct pci_bus *bus;
for (walk = walk->next; walk != &pbus->devices; walk = walk->next)
pdev_fixup_irq(pci_dev_b(walk));
list_for_each_entry(dev, &pbus->devices, bus_list)
pdev_fixup_irq(dev);
walk = &pbus->children;
for (walk = walk->next; walk != &pbus->children; walk = walk->next)
pci_fixup_irq(pbm, pci_bus_b(walk));
list_for_each_entry(bus, &pbus->children, node)
pci_fixup_irq(pbm, bus);
}
static void pdev_setup_busmastering(struct pci_dev *pdev, int is_66mhz)
......@@ -897,7 +879,7 @@ static void pdev_setup_busmastering(struct pci_dev *pdev, int is_66mhz)
void pci_determine_66mhz_disposition(struct pci_pbm_info *pbm,
struct pci_bus *pbus)
{
struct list_head *walk;
struct pci_dev *pdev;
int all_are_66mhz;
u16 status;
......@@ -906,11 +888,8 @@ void pci_determine_66mhz_disposition(struct pci_pbm_info *pbm,
goto out;
}
walk = &pbus->devices;
all_are_66mhz = 1;
for (walk = walk->next; walk != &pbus->devices; walk = walk->next) {
struct pci_dev *pdev = pci_dev_b(walk);
list_for_each_entry(pdev, &pbus->devices, bus_list) {
pci_read_config_word(pdev, PCI_STATUS, &status);
if (!(status & PCI_STATUS_66MHZ)) {
all_are_66mhz = 0;
......@@ -929,17 +908,17 @@ void pci_determine_66mhz_disposition(struct pci_pbm_info *pbm,
void pci_setup_busmastering(struct pci_pbm_info *pbm,
struct pci_bus *pbus)
{
struct list_head *walk = &pbus->devices;
struct pci_dev *dev;
struct pci_bus *bus;
int is_66mhz;
is_66mhz = pbm->is_66mhz_capable && pbm->all_devs_66mhz;
for (walk = walk->next; walk != &pbus->devices; walk = walk->next)
pdev_setup_busmastering(pci_dev_b(walk), is_66mhz);
list_for_each_entry(dev, &pbus->devices, bus_list)
pdev_setup_busmastering(dev, is_66mhz);
walk = &pbus->children;
for (walk = walk->next; walk != &pbus->children; walk = walk->next)
pci_setup_busmastering(pbm, pci_bus_b(walk));
list_for_each_entry(bus, &pbus->children, node)
pci_setup_busmastering(pbm, bus);
}
void pci_register_legacy_regions(struct resource *io_res,
......@@ -987,10 +966,10 @@ void pci_scan_for_target_abort(struct pci_controller_info *p,
struct pci_pbm_info *pbm,
struct pci_bus *pbus)
{
struct list_head *walk = &pbus->devices;
struct pci_dev *pdev;
struct pci_bus *bus;
for (walk = walk->next; walk != &pbus->devices; walk = walk->next) {
struct pci_dev *pdev = pci_dev_b(walk);
list_for_each_entry(pdev, &pbus->devices, bus_list) {
u16 status, error_bits;
pci_read_config_word(pdev, PCI_STATUS, &status);
......@@ -1005,19 +984,18 @@ void pci_scan_for_target_abort(struct pci_controller_info *p,
}
}
walk = &pbus->children;
for (walk = walk->next; walk != &pbus->children; walk = walk->next)
pci_scan_for_target_abort(p, pbm, pci_bus_b(walk));
list_for_each_entry(bus, &pbus->children, node)
pci_scan_for_target_abort(p, pbm, bus);
}
void pci_scan_for_master_abort(struct pci_controller_info *p,
struct pci_pbm_info *pbm,
struct pci_bus *pbus)
{
struct list_head *walk = &pbus->devices;
struct pci_dev *pdev;
struct pci_bus *bus;
for (walk = walk->next; walk != &pbus->devices; walk = walk->next) {
struct pci_dev *pdev = pci_dev_b(walk);
list_for_each_entry(pdev, &pbus->devices, bus_list) {
u16 status, error_bits;
pci_read_config_word(pdev, PCI_STATUS, &status);
......@@ -1031,19 +1009,18 @@ void pci_scan_for_master_abort(struct pci_controller_info *p,
}
}
walk = &pbus->children;
for (walk = walk->next; walk != &pbus->children; walk = walk->next)
pci_scan_for_master_abort(p, pbm, pci_bus_b(walk));
list_for_each_entry(bus, &pbus->children, node)
pci_scan_for_master_abort(p, pbm, bus);
}
void pci_scan_for_parity_error(struct pci_controller_info *p,
struct pci_pbm_info *pbm,
struct pci_bus *pbus)
{
struct list_head *walk = &pbus->devices;
struct pci_dev *pdev;
struct pci_bus *bus;
for (walk = walk->next; walk != &pbus->devices; walk = walk->next) {
struct pci_dev *pdev = pci_dev_b(walk);
list_for_each_entry(pdev, &pbus->devices, bus_list) {
u16 status, error_bits;
pci_read_config_word(pdev, PCI_STATUS, &status);
......@@ -1058,7 +1035,6 @@ void pci_scan_for_parity_error(struct pci_controller_info *p,
}
}
walk = &pbus->children;
for (walk = walk->next; walk != &pbus->children; walk = walk->next)
pci_scan_for_parity_error(p, pbm, pci_bus_b(walk));
list_for_each_entry(bus, &pbus->children, node)
pci_scan_for_parity_error(p, pbm, bus);
}
......@@ -11,7 +11,6 @@
#include <linux/spinlock.h>
#include <asm/io.h>
extern spinlock_t pci_controller_lock;
extern struct pci_controller_info *pci_controller_root;
extern int pci_num_controllers;
......
......@@ -1487,22 +1487,18 @@ void __init psycho_init(int node, char *model_name)
struct linux_prom64_registers pr_regs[3];
struct pci_controller_info *p;
struct pci_iommu *iommu;
unsigned long flags;
u32 upa_portid;
int is_pbm_a, err;
upa_portid = prom_getintdefault(node, "upa-portid", 0xff);
spin_lock_irqsave(&pci_controller_lock, flags);
for(p = pci_controller_root; p; p = p->next) {
if (p->pbm_A.portid == upa_portid) {
spin_unlock_irqrestore(&pci_controller_lock, flags);
is_pbm_a = (p->pbm_A.prom_node == 0);
psycho_pbm_init(p, node, is_pbm_a);
return;
}
}
spin_unlock_irqrestore(&pci_controller_lock, flags);
p = kmalloc(sizeof(struct pci_controller_info), GFP_ATOMIC);
if (!p) {
......@@ -1518,10 +1514,8 @@ void __init psycho_init(int node, char *model_name)
memset(iommu, 0, sizeof(*iommu));
p->pbm_A.iommu = p->pbm_B.iommu = iommu;
spin_lock_irqsave(&pci_controller_lock, flags);
p->next = pci_controller_root;
pci_controller_root = p;
spin_unlock_irqrestore(&pci_controller_lock, flags);
p->pbm_A.portid = upa_portid;
p->pbm_B.portid = upa_portid;
......
......@@ -1113,10 +1113,9 @@ static void __init sabre_base_address_update(struct pci_dev *pdev, int resource)
static void __init apb_init(struct pci_controller_info *p, struct pci_bus *sabre_bus)
{
struct list_head *walk = &sabre_bus->devices;
struct pci_dev *pdev;
for (walk = walk->next; walk != &sabre_bus->devices; walk = walk->next) {
struct pci_dev *pdev = pci_dev_b(walk);
list_for_each_entry(pdev, &sabre_bus->devices, bus_list) {
if (pdev->vendor == PCI_VENDOR_ID_SUN &&
pdev->device == PCI_DEVICE_ID_SUN_SIMBA) {
......@@ -1178,10 +1177,9 @@ static struct pcidev_cookie *alloc_bridge_cookie(struct pci_pbm_info *pbm)
static void __init sabre_scan_bus(struct pci_controller_info *p)
{
static int once;
struct pci_bus *sabre_bus;
struct pci_bus *sabre_bus, *pbus;
struct pci_pbm_info *pbm;
struct pcidev_cookie *cookie;
struct list_head *walk;
int sabres_scanned;
/* The APB bridge speaks to the Sabre host PCI bridge
......@@ -1217,9 +1215,7 @@ static void __init sabre_scan_bus(struct pci_controller_info *p)
sabres_scanned = 0;
walk = &sabre_bus->children;
for (walk = walk->next; walk != &sabre_bus->children; walk = walk->next) {
struct pci_bus *pbus = pci_bus_b(walk);
list_for_each_entry(pbus, &sabre_bus->children, node) {
if (pbus->number == p->pbm_A.pci_first_busno) {
pbm = &p->pbm_A;
......@@ -1554,7 +1550,6 @@ void __init sabre_init(int pnode, char *model_name)
struct linux_prom64_registers pr_regs[2];
struct pci_controller_info *p;
struct pci_iommu *iommu;
unsigned long flags;
int tsbsize, err;
u32 busrange[2];
u32 vdma[2];
......@@ -1602,10 +1597,8 @@ void __init sabre_init(int pnode, char *model_name)
upa_portid = prom_getintdefault(pnode, "upa-portid", 0xff);
spin_lock_irqsave(&pci_controller_lock, flags);
p->next = pci_controller_root;
pci_controller_root = p;
spin_unlock_irqrestore(&pci_controller_lock, flags);
p->pbm_A.portid = upa_portid;
p->pbm_B.portid = upa_portid;
......
......@@ -2081,13 +2081,11 @@ static void __init __schizo_init(int node, char *model_name, int chip_type)
{
struct pci_controller_info *p;
struct pci_iommu *iommu;
unsigned long flags;
int is_pbm_a;
u32 portid;
portid = prom_getintdefault(node, "portid", 0xff);
spin_lock_irqsave(&pci_controller_lock, flags);
for(p = pci_controller_root; p; p = p->next) {
struct pci_pbm_info *pbm;
......@@ -2099,13 +2097,11 @@ static void __init __schizo_init(int node, char *model_name, int chip_type)
&p->pbm_B);
if (portid_compare(pbm->portid, portid, chip_type)) {
spin_unlock_irqrestore(&pci_controller_lock, flags);
is_pbm_a = (p->pbm_A.prom_node == 0);
schizo_pbm_init(p, node, portid, chip_type);
return;
}
}
spin_unlock_irqrestore(&pci_controller_lock, flags);
p = kmalloc(sizeof(struct pci_controller_info), GFP_ATOMIC);
if (!p) {
......@@ -2130,10 +2126,8 @@ static void __init __schizo_init(int node, char *model_name, int chip_type)
memset(iommu, 0, sizeof(*iommu));
p->pbm_B.iommu = iommu;
spin_lock_irqsave(&pci_controller_lock, flags);
p->next = pci_controller_root;
pci_controller_root = p;
spin_unlock_irqrestore(&pci_controller_lock, flags);
p->index = pci_num_controllers++;
p->pbms_same_domain = 0;
......
......@@ -86,9 +86,62 @@ struct new_signal_frame32 {
__siginfo_fpu_t fpu_state;
};
struct siginfo32 {
int si_signo;
int si_errno;
int si_code;
union {
int _pad[SI_PAD_SIZE32];
/* kill() */
struct {
compat_pid_t _pid; /* sender's pid */
unsigned int _uid; /* sender's uid */
} _kill;
/* POSIX.1b timers */
struct {
timer_t _tid; /* timer id */
int _overrun; /* overrun count */
sigval_t32 _sigval; /* same as below */
int _sys_private; /* not to be passed to user */
} _timer;
/* POSIX.1b signals */
struct {
compat_pid_t _pid; /* sender's pid */
unsigned int _uid; /* sender's uid */
sigval_t32 _sigval;
} _rt;
/* SIGCHLD */
struct {
compat_pid_t _pid; /* which child */
unsigned int _uid; /* sender's uid */
int _status; /* exit code */
compat_clock_t _utime;
compat_clock_t _stime;
struct compat_rusage _rusage;
} _sigchld;
/* SIGILL, SIGFPE, SIGSEGV, SIGBUS, SIGEMT */
struct {
u32 _addr; /* faulting insn/memory ref. */
int _trapno;
} _sigfault;
/* SIGPOLL */
struct {
int _band; /* POLL_IN, POLL_OUT, POLL_MSG */
int _fd;
} _sigpoll;
} _sifields;
};
struct rt_signal_frame32 {
struct sparc_stackf32 ss;
siginfo_t32 info;
struct siginfo32 info;
struct pt_regs32 regs;
compat_sigset_t mask;
/* __siginfo_fpu32_t * */ u32 fpu_save;
......@@ -105,11 +158,11 @@ struct rt_signal_frame32 {
#define NF_ALIGNEDSZ (((sizeof(struct new_signal_frame32) + 7) & (~7)))
#define RT_ALIGNEDSZ (((sizeof(struct rt_signal_frame32) + 7) & (~7)))
int copy_siginfo_to_user32(siginfo_t32 __user *to, siginfo_t *from)
int copy_siginfo_to_user32(struct siginfo32 __user *to, siginfo_t *from)
{
int err;
if (!access_ok(VERIFY_WRITE, to, sizeof(siginfo_t32)))
if (!access_ok(VERIFY_WRITE, to, sizeof(struct siginfo32)))
return -EFAULT;
/* If you change siginfo_t structure, please be sure
......@@ -135,6 +188,8 @@ int copy_siginfo_to_user32(siginfo_t32 __user *to, siginfo_t *from)
err |= __put_user(from->si_utime, &to->si_utime);
err |= __put_user(from->si_stime, &to->si_stime);
err |= __put_user(from->si_status, &to->si_status);
err |= put_compat_rusage(&from->si_rusage,
&to->si_rusage);
default:
err |= __put_user(from->si_pid, &to->si_pid);
err |= __put_user(from->si_uid, &to->si_uid);
......@@ -155,6 +210,22 @@ int copy_siginfo_to_user32(siginfo_t32 __user *to, siginfo_t *from)
return err;
}
/* CAUTION: This is just a very minimalist implementation for the
* sake of compat_sys_rt_sigqueueinfo()
*/
int copy_siginfo_to_kernel32(siginfo_t *to, struct siginfo32 __user *from)
{
if (!access_ok(VERIFY_WRITE, from, sizeof(struct siginfo32)))
return -EFAULT;
if (copy_from_user(to, from, 3*sizeof(int)) ||
copy_from_user(to->_sifields._pad, from->_sifields._pad,
SI_PAD_SIZE))
return -EFAULT;
return 0;
}
/*
* atomically swap in the new signal mask, and wait for a signal.
* This is really tricky on the Sparc, watch out...
......
......@@ -1045,7 +1045,7 @@ asmlinkage long sys32_rt_sigpending(compat_sigset_t __user *set,
}
asmlinkage long sys32_rt_sigtimedwait(compat_sigset_t __user *uthese,
siginfo_t32 __user *uinfo,
struct siginfo32 __user *uinfo,
struct compat_timespec __user *uts,
compat_size_t sigsetsize)
{
......@@ -1130,15 +1130,15 @@ asmlinkage long sys32_rt_sigtimedwait(compat_sigset_t __user *uthese,
}
asmlinkage long compat_sys_rt_sigqueueinfo(int pid, int sig,
siginfo_t32 __user *uinfo)
struct siginfo32 __user *uinfo)
{
siginfo_t info;
int ret;
mm_segment_t old_fs = get_fs();
if (copy_from_user (&info, uinfo, 3*sizeof(int)) ||
copy_from_user (info._sifields._pad, uinfo->_sifields._pad, SI_PAD_SIZE))
if (copy_siginfo_to_kernel32(&info, uinfo))
return -EFAULT;
set_fs (KERNEL_DS);
ret = sys_rt_sigqueueinfo(pid, sig, (siginfo_t __user *) &info);
set_fs (old_fs);
......@@ -1736,3 +1736,23 @@ sys32_timer_create(u32 clock, struct sigevent32 __user *se32,
return err;
}
asmlinkage long compat_sys_waitid(u32 which, u32 pid,
struct siginfo32 __user *uinfo, u32 options)
{
siginfo_t info;
long ret;
mm_segment_t old_fs = get_fs();
memset(&info, 0, sizeof(info));
set_fs (KERNEL_DS);
ret = sys_waitid((int)which, (compat_pid_t) pid,
(siginfo_t __user *) &info, (int) options);
set_fs (old_fs);
if (ret < 0 || info.si_signo == 0)
return ret;
BUG_ON(info.si_code & __SI_MASK);
info.si_code |= __SI_CHLD;
return copy_siginfo_to_user32(uinfo, &info);
}
......@@ -75,7 +75,7 @@ sys_call_table32:
/*260*/ .word compat_sys_sched_getaffinity, compat_sys_sched_setaffinity, sys32_timer_settime, compat_timer_gettime, sys_timer_getoverrun
.word sys_timer_delete, sys32_timer_create, sys_ni_syscall, compat_sys_io_setup, sys_io_destroy
/*270*/ .word sys32_io_submit, sys_io_cancel, compat_sys_io_getevents, sys32_mq_open, sys_mq_unlink
.word sys_mq_timedsend, sys_mq_timedreceive, compat_sys_mq_notify, compat_sys_mq_getsetattr, sys_ni_syscall
.word sys_mq_timedsend, sys_mq_timedreceive, compat_sys_mq_notify, compat_sys_mq_getsetattr, compat_sys_waitid
/*280*/ .word sys_ni_syscall, sys_ni_syscall, sys_ni_syscall
#endif /* CONFIG_COMPAT */
......@@ -141,7 +141,7 @@ sys_call_table:
/*260*/ .word sys_sched_getaffinity, sys_sched_setaffinity, sys_timer_settime, sys_timer_gettime, sys_timer_getoverrun
.word sys_timer_delete, sys_timer_create, sys_ni_syscall, sys_io_setup, sys_io_destroy
/*270*/ .word sys_io_submit, sys_io_cancel, sys_io_getevents, sys_mq_open, sys_mq_unlink
.word sys_mq_timedsend, sys_mq_timedreceive, sys_mq_notify, sys_mq_getsetattr, sys_ni_syscall
.word sys_mq_timedsend, sys_mq_timedreceive, sys_mq_notify, sys_mq_getsetattr, sys_waitid
/*280*/ .word sys_ni_syscall, sys_ni_syscall, sys_ni_syscall
#if defined(CONFIG_SUNOS_EMUL) || defined(CONFIG_SOLARIS_EMUL) || \
......
......@@ -36,10 +36,24 @@
#include <asm/psrcompat.h>
#include <asm/processor.h>
#include <asm/timer.h>
#include <asm/kdebug.h>
#ifdef CONFIG_KMOD
#include <linux/kmod.h>
#endif
struct notifier_block *sparc64die_chain;
static spinlock_t die_notifier_lock = SPIN_LOCK_UNLOCKED;
int register_die_notifier(struct notifier_block *nb)
{
int err = 0;
unsigned long flags;
spin_lock_irqsave(&die_notifier_lock, flags);
err = notifier_chain_register(&sparc64die_chain, nb);
spin_unlock_irqrestore(&die_notifier_lock, flags);
return err;
}
/* When an irrecoverable trap occurs at tl > 0, the trap entry
* code logs the trap state registers at every level in the trap
* stack. It is found at (pt_regs + sizeof(pt_regs)) and the layout
......@@ -71,11 +85,20 @@ static void dump_tl1_traplog(struct tl1_traplog *p)
}
}
void bad_trap (struct pt_regs *regs, long lvl)
void do_call_debug(struct pt_regs *regs)
{
notify_die(DIE_CALL, "debug call", regs, 0, 255, SIGINT);
}
void bad_trap(struct pt_regs *regs, long lvl)
{
char buffer[32];
siginfo_t info;
if (notify_die(DIE_TRAP, "bad trap", regs,
0, lvl, SIGTRAP) == NOTIFY_OK)
return;
if (lvl < 0x100) {
sprintf(buffer, "Bad hw trap %lx at tl0\n", lvl);
die_if_kernel(buffer, regs);
......@@ -84,7 +107,7 @@ void bad_trap (struct pt_regs *regs, long lvl)
lvl -= 0x100;
if (regs->tstate & TSTATE_PRIV) {
sprintf(buffer, "Kernel bad sw trap %lx", lvl);
die_if_kernel (buffer, regs);
die_if_kernel(buffer, regs);
}
if (test_thread_flag(TIF_32BIT)) {
regs->tpc &= 0xffffffff;
......@@ -98,10 +121,14 @@ void bad_trap (struct pt_regs *regs, long lvl)
force_sig_info(SIGILL, &info, current);
}
void bad_trap_tl1 (struct pt_regs *regs, long lvl)
void bad_trap_tl1(struct pt_regs *regs, long lvl)
{
char buffer[32];
if (notify_die(DIE_TRAP_TL1, "bad trap tl1", regs,
0, lvl, SIGTRAP) == NOTIFY_OK)
return;
dump_tl1_traplog((struct tl1_traplog *)(regs + 1));
sprintf (buffer, "Bad trap %lx at tl>0", lvl);
......@@ -121,6 +148,10 @@ void instruction_access_exception(struct pt_regs *regs,
{
siginfo_t info;
if (notify_die(DIE_TRAP, "instruction access exception", regs,
0, 0x8, SIGTRAP) == NOTIFY_OK)
return;
if (regs->tstate & TSTATE_PRIV) {
printk("instruction_access_exception: SFSR[%016lx] SFAR[%016lx], going.\n",
sfsr, sfar);
......@@ -141,15 +172,23 @@ void instruction_access_exception(struct pt_regs *regs,
void instruction_access_exception_tl1(struct pt_regs *regs,
unsigned long sfsr, unsigned long sfar)
{
if (notify_die(DIE_TRAP_TL1, "instruction access exception tl1", regs,
0, 0x8, SIGTRAP) == NOTIFY_OK)
return;
dump_tl1_traplog((struct tl1_traplog *)(regs + 1));
instruction_access_exception(regs, sfsr, sfar);
}
void data_access_exception (struct pt_regs *regs,
unsigned long sfsr, unsigned long sfar)
void data_access_exception(struct pt_regs *regs,
unsigned long sfsr, unsigned long sfar)
{
siginfo_t info;
if (notify_die(DIE_TRAP, "data access exception", regs,
0, 0x30, SIGTRAP) == NOTIFY_OK)
return;
if (regs->tstate & TSTATE_PRIV) {
/* Test if this comes from uaccess places. */
unsigned long fixup;
......@@ -220,6 +259,10 @@ void do_iae(struct pt_regs *regs)
spitfire_clean_and_reenable_l1_caches();
if (notify_die(DIE_TRAP, "instruction access exception", regs,
0, 0x8, SIGTRAP) == NOTIFY_OK)
return;
info.si_signo = SIGBUS;
info.si_errno = 0;
info.si_code = BUS_OBJERR;
......@@ -230,6 +273,8 @@ void do_iae(struct pt_regs *regs)
void do_dae(struct pt_regs *regs)
{
siginfo_t info;
#ifdef CONFIG_PCI
if (pci_poke_in_progress && pci_poke_cpu == smp_processor_id()) {
spitfire_clean_and_reenable_l1_caches();
......@@ -244,7 +289,18 @@ void do_dae(struct pt_regs *regs)
return;
}
#endif
do_iae(regs);
spitfire_clean_and_reenable_l1_caches();
if (notify_die(DIE_TRAP, "data access exception", regs,
0, 0x30, SIGTRAP) == NOTIFY_OK)
return;
info.si_signo = SIGBUS;
info.si_errno = 0;
info.si_code = BUS_OBJERR;
info.si_addr = (void *)0;
info.si_trapno = 0;
force_sig_info(SIGBUS, &info, current);
}
static char ecc_syndrome_table[] = {
......@@ -1638,6 +1694,10 @@ void do_fpe_common(struct pt_regs *regs)
void do_fpieee(struct pt_regs *regs)
{
if (notify_die(DIE_TRAP, "fpu exception ieee", regs,
0, 0x24, SIGFPE) == NOTIFY_OK)
return;
do_fpe_common(regs);
}
......@@ -1648,6 +1708,10 @@ void do_fpother(struct pt_regs *regs)
struct fpustate *f = FPUSTATE;
int ret = 0;
if (notify_die(DIE_TRAP, "fpu exception other", regs,
0, 0x25, SIGFPE) == NOTIFY_OK)
return;
switch ((current_thread_info()->xfsr[0] & 0x1c000)) {
case (2 << 14): /* unfinished_FPop */
case (3 << 14): /* unimplemented_FPop */
......@@ -1663,6 +1727,10 @@ void do_tof(struct pt_regs *regs)
{
siginfo_t info;
if (notify_die(DIE_TRAP, "tagged arithmetic overflow", regs,
0, 0x26, SIGEMT) == NOTIFY_OK)
return;
if (regs->tstate & TSTATE_PRIV)
die_if_kernel("Penguin overflow trap from kernel mode", regs);
if (test_thread_flag(TIF_32BIT)) {
......@@ -1681,6 +1749,10 @@ void do_div0(struct pt_regs *regs)
{
siginfo_t info;
if (notify_die(DIE_TRAP, "integer division by zero", regs,
0, 0x28, SIGFPE) == NOTIFY_OK)
return;
if (regs->tstate & TSTATE_PRIV)
die_if_kernel("TL0: Kernel divide by zero.", regs);
if (test_thread_flag(TIF_32BIT)) {
......@@ -1786,6 +1858,7 @@ void die_if_kernel(char *str, struct pt_regs *regs)
" \\__U_/\n");
printk("%s(%d): %s [#%d]\n", current->comm, current->pid, str, ++die_counter);
notify_die(DIE_OOPS, str, regs, 0, 255, SIGSEGV);
__asm__ __volatile__("flushw");
__show_regs(regs);
if (regs->tstate & TSTATE_PRIV) {
......@@ -1834,6 +1907,10 @@ void do_illegal_instruction(struct pt_regs *regs)
u32 insn;
siginfo_t info;
if (notify_die(DIE_TRAP, "illegal instruction", regs,
0, 0x10, SIGILL) == NOTIFY_OK)
return;
if (tstate & TSTATE_PRIV)
die_if_kernel("Kernel illegal instruction", regs);
if (test_thread_flag(TIF_32BIT))
......@@ -1859,6 +1936,10 @@ void mem_address_unaligned(struct pt_regs *regs, unsigned long sfar, unsigned lo
{
siginfo_t info;
if (notify_die(DIE_TRAP, "memory address unaligned", regs,
0, 0x34, SIGSEGV) == NOTIFY_OK)
return;
if (regs->tstate & TSTATE_PRIV) {
extern void kernel_unaligned_trap(struct pt_regs *regs,
unsigned int insn,
......@@ -1881,6 +1962,10 @@ void do_privop(struct pt_regs *regs)
{
siginfo_t info;
if (notify_die(DIE_TRAP, "privileged operation", regs,
0, 0x11, SIGILL) == NOTIFY_OK)
return;
if (test_thread_flag(TIF_32BIT)) {
regs->tpc &= 0xffffffff;
regs->tnpc &= 0xffffffff;
......
......@@ -158,7 +158,7 @@ tl0_resv164: BTRAP(0x164) BTRAP(0x165) BTRAP(0x166) BTRAP(0x167) BTRAP(0x168)
tl0_resv169: BTRAP(0x169) BTRAP(0x16a) BTRAP(0x16b) BTRAP(0x16c)
tl0_linux64: LINUX_64BIT_SYSCALL_TRAP
tl0_gsctx: TRAP(sparc64_get_context) TRAP(sparc64_set_context)
tl0_resv170: BTRAP(0x170) BTRAP(0x171) BTRAP(0x172)
tl0_resv170: KPROBES_TRAP(0x170) KPROBES_TRAP(0x171) BTRAP(0x172)
tl0_resv173: BTRAP(0x173) BTRAP(0x174) BTRAP(0x175) BTRAP(0x176) BTRAP(0x177)
tl0_resv178: BTRAP(0x178) BTRAP(0x179) BTRAP(0x17a) BTRAP(0x17b) BTRAP(0x17c)
tl0_resv17d: BTRAP(0x17d) BTRAP(0x17e) BTRAP(0x17f)
......
......@@ -27,6 +27,7 @@
#include <asm/asi.h>
#include <asm/lsu.h>
#include <asm/sections.h>
#include <asm/kdebug.h>
#define ELEMENTS(arr) (sizeof (arr)/sizeof (arr[0]))
......@@ -147,6 +148,9 @@ static void unhandled_fault(unsigned long address, struct task_struct *tsk,
printk(KERN_ALERT "tsk->{mm,active_mm}->pgd = %016lx\n",
(tsk->mm ? (unsigned long) tsk->mm->pgd :
(unsigned long) tsk->active_mm->pgd));
if (notify_die(DIE_GPF, "general protection fault", regs,
0, 0, SIGSEGV) == NOTIFY_OK)
return;
die_if_kernel("Oops", regs);
}
......@@ -318,8 +322,13 @@ asmlinkage void do_sparc64_fault(struct pt_regs *regs)
int si_code, fault_code;
unsigned long address;
si_code = SEGV_MAPERR;
fault_code = get_thread_fault_code();
if (notify_die(DIE_PAGE_FAULT, "page_fault", regs,
fault_code, 0, SIGSEGV) == NOTIFY_OK)
return;
si_code = SEGV_MAPERR;
address = current_thread_info()->fault_address;
if ((fault_code & FAULT_CODE_ITLB) &&
......
......@@ -137,21 +137,34 @@ asmlinkage int solaris_brk(u32 brk)
return sunos_brk(brk);
}
#define set_utsfield(to, from, dotchop, countfrom) { \
char *p; \
int i, len = (countfrom) ? \
((sizeof(to) > sizeof(from) ? \
sizeof(from) : sizeof(to))) : sizeof(to); \
if (copy_to_user(to, from, len)) \
return -EFAULT; \
if (dotchop) \
for (p=from,i=0; *p && *p != '.' && --len; p++,i++); \
else \
i = len - 1; \
if (__put_user('\0', (char __user *)((to)+i))) \
return -EFAULT; \
static int __set_utsfield(char __user *to, int to_size,
const char *from, int from_size,
int dotchop, int countfrom)
{
int len = countfrom ? (to_size > from_size ?
from_size : to_size) : to_size;
int off;
if (copy_to_user(to, from, len))
return -EFAULT;
if (dotchop) {
off = (strnchr(from, len, '.') - from);
} else{
off = len - 1;
}
if (__put_user('\0', to + off))
return -EFAULT;
return 0;
}
#define set_utsfield(to, from, dotchop, countfrom) \
__set_utsfield((to), sizeof(to), \
(from), sizeof(from), \
(dotchop), (countfrom))
struct sol_uname {
char sysname[9];
char nodename[9];
......@@ -219,17 +232,20 @@ static char *serial(char *buffer)
asmlinkage int solaris_utssys(u32 buf, u32 flags, int which, u32 buf2)
{
struct sol_uname __user *v = A(buf);
int err;
switch (which) {
case 0: /* old uname */
/* Let's cheat */
set_utsfield(v->sysname, "SunOS", 1, 0);
err = set_utsfield(v->sysname, "SunOS", 1, 0);
down_read(&uts_sem);
set_utsfield(v->nodename, system_utsname.nodename, 1, 1);
err |= set_utsfield(v->nodename, system_utsname.nodename,
1, 1);
up_read(&uts_sem);
set_utsfield(v->release, "2.6", 0, 0);
set_utsfield(v->version, "Generic", 0, 0);
set_utsfield(v->machine, machine(), 0, 0);
return 0;
err |= set_utsfield(v->release, "2.6", 0, 0);
err |= set_utsfield(v->version, "Generic", 0, 0);
err |= set_utsfield(v->machine, machine(), 0, 0);
return (err ? -EFAULT : 0);
case 2: /* ustat */
return -ENOSYS;
case 3: /* fusers */
......@@ -242,15 +258,18 @@ asmlinkage int solaris_utssys(u32 buf, u32 flags, int which, u32 buf2)
asmlinkage int solaris_utsname(u32 buf)
{
struct sol_utsname __user *v = A(buf);
int err;
/* Why should we not lie a bit? */
down_read(&uts_sem);
set_utsfield(v->sysname, "SunOS", 0, 0);
set_utsfield(v->nodename, system_utsname.nodename, 1, 1);
set_utsfield(v->release, "5.6", 0, 0);
set_utsfield(v->version, "Generic", 0, 0);
set_utsfield(v->machine, machine(), 0, 0);
err = set_utsfield(v->sysname, "SunOS", 0, 0);
err |= set_utsfield(v->nodename, system_utsname.nodename, 1, 1);
err |= set_utsfield(v->release, "5.6", 0, 0);
err |= set_utsfield(v->version, "Generic", 0, 0);
err |= set_utsfield(v->machine, machine(), 0, 0);
up_read(&uts_sem);
return 0;
return (err ? -EFAULT : 0);
}
#define SI_SYSNAME 1 /* return name of operating system */
......
......@@ -290,11 +290,12 @@
#define __NR_io_cancel 271
#define __NR_io_getevents 272
#define __NR_mq_open 273
#define __NR_mq_unlink (__NR_mq_open+1)
#define __NR_mq_timedsend (__NR_mq_open+2)
#define __NR_mq_timedreceive (__NR_mq_open+3)
#define __NR_mq_notify (__NR_mq_open+4)
#define __NR_mq_getsetattr (__NR_mq_open+5)
#define __NR_mq_unlink 274
#define __NR_mq_timedsend 275
#define __NR_mq_timedreceive 276
#define __NR_mq_notify 277
#define __NR_mq_getsetattr 278
#define __NR_waitid 279
/* WARNING: You MAY NOT add syscall numbers larger than 282, since
* all of the syscall tables in the Sparc kernel are
......
#ifndef _SPARC64_KDEBUG_H
#define _SPARC64_KDEBUG_H
/*
* No kernel debugger on sparc64. Kept here because drivers/sbus/char/
* includes it for sparc32 sake.
/* Nearly identical to x86_64/i386 code. */
#include <linux/notifier.h>
struct pt_regs;
struct die_args {
struct pt_regs *regs;
const char *str;
long err;
int trapnr;
int signr;
};
/* Note - you should never unregister because that can race with NMIs.
* If you really want to do it first unregister - then synchronize_kernel
* - then free.
*/
int register_die_notifier(struct notifier_block *nb);
extern struct notifier_block *sparc64die_chain;
extern void bad_trap(struct pt_regs *, long);
/* Grossly misnamed. */
enum die_val {
DIE_OOPS = 1,
DIE_DEBUG, /* ta 0x70 */
DIE_DEBUG_2, /* ta 0x71 */
DIE_DIE,
DIE_TRAP,
DIE_TRAP_TL1,
DIE_GPF,
DIE_CALL,
DIE_PAGE_FAULT,
};
static inline int notify_die(enum die_val val,char *str, struct pt_regs *regs,
long err, int trap, int sig)
{
struct die_args args = { .regs = regs,
.str = str,
.err = err,
.trapnr = trap,
.signr = sig };
return notifier_call_chain(&sparc64die_chain, val, &args);
}
#endif
#ifndef _SPARC64_KPROBES_H
#define _SPARC64_KPROBES_H
#include <linux/config.h>
#include <linux/types.h>
typedef u32 kprobe_opcode_t;
#define BREAKPOINT_INSTRUCTION 0x91d02070 /* ta 0x70 */
#define BREAKPOINT_INSTRUCTION_2 0x91d02071 /* ta 0x71 */
#define MAX_INSN_SIZE 2
#ifdef CONFIG_KPROBES
extern int kprobe_exceptions_notify(struct notifier_block *self,
unsigned long val, void *data);
#else /* !CONFIG_KPROBES */
static inline int kprobe_exceptions_notify(struct notifier_block *self,
unsigned long val, void *data)
{
return 0;
}
#endif
#endif /* _SPARC64_KPROBES_H */
......@@ -24,57 +24,8 @@ typedef union sigval32 {
u32 sival_ptr;
} sigval_t32;
typedef struct siginfo32 {
int si_signo;
int si_errno;
int si_code;
struct siginfo32;
union {
int _pad[SI_PAD_SIZE32];
/* kill() */
struct {
compat_pid_t _pid; /* sender's pid */
unsigned int _uid; /* sender's uid */
} _kill;
/* POSIX.1b timers */
struct {
timer_t _tid; /* timer id */
int _overrun; /* overrun count */
sigval_t32 _sigval; /* same as below */
int _sys_private; /* not to be passed to user */
} _timer;
/* POSIX.1b signals */
struct {
compat_pid_t _pid; /* sender's pid */
unsigned int _uid; /* sender's uid */
sigval_t32 _sigval;
} _rt;
/* SIGCHLD */
struct {
compat_pid_t _pid; /* which child */
unsigned int _uid; /* sender's uid */
int _status; /* exit code */
compat_clock_t _utime;
compat_clock_t _stime;
} _sigchld;
/* SIGILL, SIGFPE, SIGSEGV, SIGBUS, SIGEMT */
struct {
u32 _addr; /* faulting insn/memory ref. */
int _trapno;
} _sigfault;
/* SIGPOLL */
struct {
int _band; /* POLL_IN, POLL_OUT, POLL_MSG */
int _fd;
} _sigpoll;
} _sifields;
} siginfo_t32;
#endif /* CONFIG_COMPAT */
#endif /* __KERNEL__ */
......@@ -105,7 +56,8 @@ typedef struct sigevent32 {
} _sigev_un;
} sigevent_t32;
extern int copy_siginfo_to_user32(siginfo_t32 __user *to, siginfo_t *from);
extern int copy_siginfo_to_user32(struct siginfo32 __user *to, siginfo_t *from);
extern int copy_siginfo_to_kernel32(siginfo_t *to, struct siginfo32 __user *from);
#endif /* CONFIG_COMPAT */
......
......@@ -176,6 +176,12 @@
ba,pt %xcc, rtrap_clr_l6; \
stx %l2, [%sp + PTREGS_OFF + PT_V9_TNPC];
#ifdef CONFIG_KPROBES
#define KPROBES_TRAP(lvl) TRAP_IRQ(kprobe_trap, lvl)
#else
#define KPROBES_TRAP(lvl) TRAP_ARG(bad_trap, lvl)
#endif
/* Before touching these macros, you owe it to yourself to go and
* see how arch/sparc64/kernel/winfixup.S works... -DaveM
*
......
......@@ -292,11 +292,13 @@
#define __NR_io_cancel 271
#define __NR_io_getevents 272
#define __NR_mq_open 273
#define __NR_mq_unlink (__NR_mq_open+1)
#define __NR_mq_timedsend (__NR_mq_open+2)
#define __NR_mq_timedreceive (__NR_mq_open+3)
#define __NR_mq_notify (__NR_mq_open+4)
#define __NR_mq_getsetattr (__NR_mq_open+5)
#define __NR_mq_unlink 274
#define __NR_mq_timedsend 275
#define __NR_mq_timedreceive 276
#define __NR_mq_notify 277
#define __NR_mq_getsetattr 278
#define __NR_waitid 279
/* WARNING: You MAY NOT add syscall numbers larger than 282, since
* all of the syscall tables in the Sparc kernel are
* sized to have 283 entries (starting at zero). Therefore
......
......@@ -88,7 +88,8 @@ int register_kprobe(struct kprobe *p)
arch_prepare_kprobe(p);
p->opcode = *p->addr;
*p->addr = BREAKPOINT_INSTRUCTION;
flush_icache_range(p->addr, p->addr + sizeof(kprobe_opcode_t));
flush_icache_range((unsigned long) p->addr,
(unsigned long) p->addr + sizeof(kprobe_opcode_t));
out:
spin_unlock_irqrestore(&kprobe_lock, flags);
return ret;
......@@ -100,7 +101,8 @@ void unregister_kprobe(struct kprobe *p)
spin_lock_irqsave(&kprobe_lock, flags);
*p->addr = p->opcode;
hlist_del(&p->hlist);
flush_icache_range(p->addr, p->addr + sizeof(kprobe_opcode_t));
flush_icache_range((unsigned long) p->addr,
(unsigned long) p->addr + sizeof(kprobe_opcode_t));
spin_unlock_irqrestore(&kprobe_lock, flags);
}
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment