Merge master.kernel.org:/pub/scm/linux/kernel/git/kyle/parisc-2.6
authorLinus Torvalds <torvalds@g5.osdl.org>
Thu, 29 Jun 2006 18:30:45 +0000 (11:30 -0700)
committerLinus Torvalds <torvalds@g5.osdl.org>
Thu, 29 Jun 2006 18:30:45 +0000 (11:30 -0700)
* master.kernel.org:/pub/scm/linux/kernel/git/kyle/parisc-2.6: (23 commits)
  [PARISC] Move os_id_to_string() inside #ifndef __ASSEMBLY__
  [PARISC] Fix do_gettimeofday() hang
  [PARISC] Fix PCREL22F relocation problem for most modules
  [PARISC] Refactor show_regs in traps.c
  [PARISC] Add os_id_to_string helper
  [PARISC] OS_ID_LINUX == 0x0006
  [PARISC] Ensure Space ID hashing is turned off
  [PARISC] Match show_cache_info with reality
  [PARISC] Remove unused macro fixup_branch in syscall.S
  [PARISC] Add is_compat_task() helper
  [PARISC] Update Thibaut Varene's CREDITS entry
  [PARISC] Reduce data footprint in pdc_stable.c
  [PARISC] pdc_stable version 0.30
  [PARISC] Work around machines which do not support chassis warnings
  [PARISC] PDC_CHASSIS is implemented on all machines
  [PARISC] Remove unconditional #define PIC in syscall macros
  [PARISC] Use MFIA in current_text_addr on pa2.0 processors
  [PARISC] Remove dead function pc_in_user_space
  [PARISC] Test ioc_needs_fdc variable instead of open coding
  [PARISC] Fix gcc 4.1 warnings in sba_iommu.c
  ...

25 files changed:
CREDITS
arch/parisc/kernel/cache.c
arch/parisc/kernel/entry.S
arch/parisc/kernel/firmware.c
arch/parisc/kernel/module.c
arch/parisc/kernel/pdc_chassis.c
arch/parisc/kernel/ptrace.c
arch/parisc/kernel/real2.S
arch/parisc/kernel/setup.c
arch/parisc/kernel/signal.c
arch/parisc/kernel/syscall.S
arch/parisc/kernel/time.c
arch/parisc/kernel/traps.c
arch/parisc/kernel/unaligned.c
drivers/parisc/Kconfig
drivers/parisc/pdc_stable.c
drivers/parisc/sba_iommu.c
include/asm-parisc/assembly.h
include/asm-parisc/compat.h
include/asm-parisc/pdc.h
include/asm-parisc/pgtable.h
include/asm-parisc/processor.h
include/asm-parisc/system.h
include/asm-parisc/uaccess.h
include/asm-parisc/unistd.h

diff --git a/CREDITS b/CREDITS
index 85c7c70..66b9e7a 100644 (file)
--- a/CREDITS
+++ b/CREDITS
@@ -3401,10 +3401,10 @@ S: Czech Republic
 
 N: Thibaut Varene
 E: T-Bone@parisc-linux.org
-W: http://www.parisc-linux.org/
+W: http://www.parisc-linux.org/~varenet/
 P: 1024D/B7D2F063 E67C 0D43 A75E 12A5 BB1C  FA2F 1E32 C3DA B7D2 F063
 D: PA-RISC port minion, PDC and GSCPS2 drivers, debuglocks and other bits
-D: Some bits in an ARM port, S1D13XXX FB driver, random patches here and there
+D: Some ARM at91rm9200 bits, S1D13XXX FB driver, random patches here and there
 D: AD1889 sound driver
 S: Paris, France
 
index c057ad7..bc7c4a4 100644 (file)
@@ -97,15 +97,17 @@ update_mmu_cache(struct vm_area_struct *vma, unsigned long address, pte_t pte)
 void
 show_cache_info(struct seq_file *m)
 {
+       char buf[32];
+
        seq_printf(m, "I-cache\t\t: %ld KB\n", 
                cache_info.ic_size/1024 );
-       seq_printf(m, "D-cache\t\t: %ld KB (%s%s, %d-way associative)\n", 
+       if (cache_info.dc_loop == 1)
+               snprintf(buf, 32, "%lu-way associative", cache_info.dc_loop);
+       seq_printf(m, "D-cache\t\t: %ld KB (%s%s, %s)\n",
                cache_info.dc_size/1024,
                (cache_info.dc_conf.cc_wt ? "WT":"WB"),
                (cache_info.dc_conf.cc_sh ? ", shared I/D":""),
-               (cache_info.dc_conf.cc_assoc)
-       );
-
+               ((cache_info.dc_loop == 1) ? "direct mapped" : buf));
        seq_printf(m, "ITLB entries\t: %ld\n" "DTLB entries\t: %ld%s\n",
                cache_info.it_size,
                cache_info.dt_size,
@@ -158,11 +160,11 @@ parisc_cache_init(void)
                cache_info.dc_conf.cc_block,
                cache_info.dc_conf.cc_line,
                cache_info.dc_conf.cc_shift);
-       printk("        wt %d sh %d cst %d assoc %d\n",
+       printk("        wt %d sh %d cst %d hv %d\n",
                cache_info.dc_conf.cc_wt,
                cache_info.dc_conf.cc_sh,
                cache_info.dc_conf.cc_cst,
-               cache_info.dc_conf.cc_assoc);
+               cache_info.dc_conf.cc_hv);
 
        printk("IC  base 0x%lx stride 0x%lx count 0x%lx loop 0x%lx\n",
                cache_info.ic_base,
@@ -176,11 +178,11 @@ parisc_cache_init(void)
                cache_info.ic_conf.cc_block,
                cache_info.ic_conf.cc_line,
                cache_info.ic_conf.cc_shift);
-       printk("        wt %d sh %d cst %d assoc %d\n",
+       printk("        wt %d sh %d cst %d hv %d\n",
                cache_info.ic_conf.cc_wt,
                cache_info.ic_conf.cc_sh,
                cache_info.ic_conf.cc_cst,
-               cache_info.ic_conf.cc_assoc);
+               cache_info.ic_conf.cc_hv);
 
        printk("D-TLB conf: sh %d page %d cst %d aid %d pad1 %d \n",
                cache_info.dt_conf.tc_sh,
@@ -234,7 +236,8 @@ parisc_cache_init(void)
 
 void disable_sr_hashing(void)
 {
-       int srhash_type;
+       int srhash_type, retval;
+       unsigned long space_bits;
 
        switch (boot_cpu_data.cpu_type) {
        case pcx: /* We shouldn't get this far.  setup.c should prevent it. */
@@ -260,6 +263,13 @@ void disable_sr_hashing(void)
        }
 
        disable_sr_hashing_asm(srhash_type);
+
+       retval = pdc_spaceid_bits(&space_bits);
+       /* If this procedure isn't implemented, don't panic. */
+       if (retval < 0 && retval != PDC_BAD_OPTION)
+               panic("pdc_spaceid_bits call failed.\n");
+       if (space_bits != 0)
+               panic("SpaceID hashing is still on!\n");
 }
 
 void flush_dcache_page(struct page *page)
index d9e53cf..630730c 100644 (file)
@@ -1638,7 +1638,7 @@ dbit_trap_20w:
        load32          PA(pa_dbit_lock),t0
 
 dbit_spin_20w:
-       ldcw            0(t0),t1
+       LDCW            0(t0),t1
        cmpib,=         0,t1,dbit_spin_20w
        nop
 
@@ -1674,7 +1674,7 @@ dbit_trap_11:
        load32          PA(pa_dbit_lock),t0
 
 dbit_spin_11:
-       ldcw            0(t0),t1
+       LDCW            0(t0),t1
        cmpib,=         0,t1,dbit_spin_11
        nop
 
@@ -1714,7 +1714,7 @@ dbit_trap_20:
        load32          PA(pa_dbit_lock),t0
 
 dbit_spin_20:
-       ldcw            0(t0),t1
+       LDCW            0(t0),t1
        cmpib,=         0,t1,dbit_spin_20
        nop
 
index 2dc06b8..4398d2a 100644 (file)
@@ -11,7 +11,7 @@
  * Copyright 1999 The Puffin Group, (Alex deVries, David Kennedy)
  * Copyright 2003 Grant Grundler <grundler parisc-linux org>
  * Copyright 2003,2004 Ryan Bradetich <rbrad@parisc-linux.org>
- * Copyright 2004 Thibaut VARENE <varenet@parisc-linux.org>
+ * Copyright 2004,2006 Thibaut VARENE <varenet@parisc-linux.org>
  *
  *    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
@@ -252,10 +252,8 @@ int pdc_pat_chassis_send_log(unsigned long state, unsigned long data)
 #endif
 
 /**
- * pdc_chassis_disp - Updates display
+ * pdc_chassis_disp - Updates chassis code
  * @retval: -1 on error, 0 on success
- *
- * Works on old PDC only (E class, others?)
  */
 int pdc_chassis_disp(unsigned long disp)
 {
@@ -268,6 +266,22 @@ int pdc_chassis_disp(unsigned long disp)
        return retval;
 }
 
+/**
+ * pdc_chassis_warn - Fetches chassis warnings
+ * @retval: -1 on error, 0 on success
+ */
+int pdc_chassis_warn(unsigned long *warn)
+{
+       int retval = 0;
+
+       spin_lock_irq(&pdc_lock);
+       retval = mem_pdc_call(PDC_CHASSIS, PDC_CHASSIS_WARN, __pa(pdc_result));
+       *warn = pdc_result[0];
+       spin_unlock_irq(&pdc_lock);
+
+       return retval;
+}
+
 /**
  * pdc_coproc_cfg - To identify coprocessors attached to the processor.
  * @pdc_coproc_info: Return buffer address.
@@ -393,7 +407,9 @@ int pdc_model_info(struct pdc_model *model)
  * pdc_model_sysmodel - Get the system model name.
  * @name: A char array of at least 81 characters.
  *
- * Get system model name from PDC ROM (e.g. 9000/715 or 9000/778/B160L)
+ * Get system model name from PDC ROM (e.g. 9000/715 or 9000/778/B160L).
+ * Using OS_ID_HPUX will return the equivalent of the 'modelname' command
+ * on HP/UX.
  */
 int pdc_model_sysmodel(char *name)
 {
@@ -498,6 +514,26 @@ int pdc_cache_info(struct pdc_cache_info *cache_info)
         return retval;
 }
 
+/**
+ * pdc_spaceid_bits - Return whether Space ID hashing is turned on.
+ * @space_bits: Should be 0, if not, bad mojo!
+ *
+ * Returns information about Space ID hashing.
+ */
+int pdc_spaceid_bits(unsigned long *space_bits)
+{
+       int retval;
+
+       spin_lock_irq(&pdc_lock);
+       pdc_result[0] = 0;
+       retval = mem_pdc_call(PDC_CACHE, PDC_CACHE_RET_SPID, __pa(pdc_result), 0);
+       convert_to_wide(pdc_result);
+       *space_bits = pdc_result[0];
+       spin_unlock_irq(&pdc_lock);
+
+       return retval;
+}
+
 #ifndef CONFIG_PA20
 /**
  * pdc_btlb_info - Return block TLB information.
index f27cfe4..aee3118 100644 (file)
@@ -89,6 +89,12 @@ static inline int is_local(struct module *me, void *loc)
        return is_init(me, loc) || is_core(me, loc);
 }
 
+static inline int is_local_section(struct module *me, void *loc, void *dot)
+{
+       return (is_init(me, loc) && is_init(me, dot)) ||
+               (is_core(me, loc) && is_core(me, dot));
+}
+
 
 #ifndef __LP64__
 struct got_entry {
@@ -364,8 +370,14 @@ static Elf_Addr get_fdesc(struct module *me, unsigned long value)
 }
 #endif /* __LP64__ */
 
+enum elf_stub_type {
+       ELF_STUB_GOT,
+       ELF_STUB_MILLI,
+       ELF_STUB_DIRECT,
+};
+
 static Elf_Addr get_stub(struct module *me, unsigned long value, long addend,
-       int millicode, int init_section)
+       enum elf_stub_type stub_type, int init_section)
 {
        unsigned long i;
        struct stub_entry *stub;
@@ -396,7 +408,7 @@ static Elf_Addr get_stub(struct module *me, unsigned long value, long addend,
        stub->insns[1] |= reassemble_17(rrsel(value, addend) / 4);
 
 #else
-/* for 64-bit we have two kinds of stubs:
+/* for 64-bit we have three kinds of stubs:
  * for normal function calls:
  *     ldd 0(%dp),%dp
  *     ldd 10(%dp), %r1
@@ -408,18 +420,23 @@ static Elf_Addr get_stub(struct module *me, unsigned long value, long addend,
  *     ldo 0(%r1), %r1
  *     ldd 10(%r1), %r1
  *     bve,n (%r1)
+ *
+ * for direct branches (jumps between different section of the
+ * same module):
+ *     ldil 0, %r1
+ *     ldo 0(%r1), %r1
+ *     bve,n (%r1)
  */
-       if (!millicode)
-       {
+       switch (stub_type) {
+       case ELF_STUB_GOT:
                stub->insns[0] = 0x537b0000;    /* ldd 0(%dp),%dp       */
                stub->insns[1] = 0x53610020;    /* ldd 10(%dp),%r1      */
                stub->insns[2] = 0xe820d000;    /* bve (%r1)            */
                stub->insns[3] = 0x537b0030;    /* ldd 18(%dp),%dp      */
 
                stub->insns[0] |= reassemble_14(get_got(me, value, addend) & 0x3fff);
-       }
-       else
-       {
+               break;
+       case ELF_STUB_MILLI:
                stub->insns[0] = 0x20200000;    /* ldil 0,%r1           */
                stub->insns[1] = 0x34210000;    /* ldo 0(%r1), %r1      */
                stub->insns[2] = 0x50210020;    /* ldd 10(%r1),%r1      */
@@ -427,7 +444,17 @@ static Elf_Addr get_stub(struct module *me, unsigned long value, long addend,
 
                stub->insns[0] |= reassemble_21(lrsel(value, addend));
                stub->insns[1] |= reassemble_14(rrsel(value, addend));
+               break;
+       case ELF_STUB_DIRECT:
+               stub->insns[0] = 0x20200000;    /* ldil 0,%r1           */
+               stub->insns[1] = 0x34210000;    /* ldo 0(%r1), %r1      */
+               stub->insns[2] = 0xe820d002;    /* bve,n (%r1)          */
+
+               stub->insns[0] |= reassemble_21(lrsel(value, addend));
+               stub->insns[1] |= reassemble_14(rrsel(value, addend));
+               break;
        }
+
 #endif
 
        return (Elf_Addr)stub;
@@ -539,14 +566,14 @@ int apply_relocate_add(Elf_Shdr *sechdrs,
                        break;
                case R_PARISC_PCREL17F:
                        /* 17-bit PC relative address */
-                       val = get_stub(me, val, addend, 0, is_init(me, loc));
+                       val = get_stub(me, val, addend, ELF_STUB_GOT, is_init(me, loc));
                        val = (val - dot - 8)/4;
                        CHECK_RELOC(val, 17)
                        *loc = (*loc & ~0x1f1ffd) | reassemble_17(val);
                        break;
                case R_PARISC_PCREL22F:
                        /* 22-bit PC relative address; only defined for pa20 */
-                       val = get_stub(me, val, addend, 0, is_init(me, loc));
+                       val = get_stub(me, val, addend, ELF_STUB_GOT, is_init(me, loc));
                        DEBUGP("STUB FOR %s loc %lx+%lx at %lx\n", 
                               strtab + sym->st_name, (unsigned long)loc, addend, 
                               val)
@@ -643,13 +670,23 @@ int apply_relocate_add(Elf_Shdr *sechdrs,
                               strtab + sym->st_name,
                               loc, val);
                        /* can we reach it locally? */
-                       if(!is_local(me, (void *)val)) {
-                               if (strncmp(strtab + sym->st_name, "$$", 2)
+                       if(!is_local_section(me, (void *)val, (void *)dot)) {
+
+                               if (is_local(me, (void *)val))
+                                       /* this is the case where the
+                                        * symbol is local to the
+                                        * module, but in a different
+                                        * section, so stub the jump
+                                        * in case it's more than 22
+                                        * bits away */
+                                       val = get_stub(me, val, addend, ELF_STUB_DIRECT,
+                                                      is_init(me, loc));
+                               else if (strncmp(strtab + sym->st_name, "$$", 2)
                                    == 0)
-                                       val = get_stub(me, val, addend, 1,
+                                       val = get_stub(me, val, addend, ELF_STUB_MILLI,
                                                       is_init(me, loc));
                                else
-                                       val = get_stub(me, val, addend, 0,
+                                       val = get_stub(me, val, addend, ELF_STUB_GOT,
                                                       is_init(me, loc));
                        }
                        DEBUGP("STUB FOR %s loc %lx, val %lx+%lx at %lx\n", 
index a45e2e2..d47ba1a 100644 (file)
@@ -1,8 +1,8 @@
 /* 
- *    interfaces to log Chassis Codes via PDC (firmware)
+ *    interfaces to Chassis Codes via PDC (firmware)
  *
  *    Copyright (C) 2002 Laurent Canet <canetl@esiee.fr>
- *    Copyright (C) 2002-2004 Thibaut VARENE <varenet@parisc-linux.org>
+ *    Copyright (C) 2002-2006 Thibaut VARENE <varenet@parisc-linux.org>
  *
  *    This program is free software; you can redistribute it and/or modify
  *    it under the terms of the GNU General Public License, version 2, as
  *    You should have received a copy of the GNU General Public License
  *    along with this program; if not, write to the Free Software
  *    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ *    TODO: poll chassis warns, trigger (configurable) machine shutdown when
+ *             needed.
+ *         Find out how to get Chassis warnings out of PAT boxes?
  */
 
 #undef PDC_CHASSIS_DEBUG
 #include <linux/reboot.h>
 #include <linux/notifier.h>
 #include <linux/cache.h>
+#include <linux/proc_fs.h>
 
 #include <asm/pdc_chassis.h>
 #include <asm/processor.h>
 #include <asm/pdc.h>
 #include <asm/pdcpat.h>
 
+#define PDC_CHASSIS_VER        "0.05"
 
 #ifdef CONFIG_PDC_CHASSIS
-static int pdc_chassis_old __read_mostly = 0;  
 static unsigned int pdc_chassis_enabled __read_mostly = 1;
 
 
@@ -64,7 +69,7 @@ __setup("pdcchassis=", pdc_chassis_setup);
  * Currently, only E class and A180 are known to work with this.
  * Inspired by Christoph Plattner
  */
-
+#if 0
 static void __init pdc_chassis_checkold(void)
 {
        switch(CPU_HVERSION) {
@@ -73,7 +78,6 @@ static void __init pdc_chassis_checkold(void)
                case 0x482:             /* E45 */
                case 0x483:             /* E55 */
                case 0x516:             /* A180 */
-                       pdc_chassis_old = 1;
                        break;
 
                default:
@@ -81,7 +85,7 @@ static void __init pdc_chassis_checkold(void)
        }
        DPRINTK(KERN_DEBUG "%s: pdc_chassis_checkold(); pdc_chassis_old = %d\n", __FILE__, pdc_chassis_old);
 }
-
+#endif
 
 /**
  * pdc_chassis_panic_event() - Called by the panic handler.
@@ -131,30 +135,20 @@ static struct notifier_block pdc_chassis_reboot_block = {
 void __init parisc_pdc_chassis_init(void)
 {
 #ifdef CONFIG_PDC_CHASSIS
-       int handle = 0;
        if (likely(pdc_chassis_enabled)) {
                DPRINTK(KERN_DEBUG "%s: parisc_pdc_chassis_init()\n", __FILE__);
 
                /* Let see if we have something to handle... */
-               /* Check for PDC_PAT or old LED Panel */
-               pdc_chassis_checkold();
-               if (is_pdc_pat()) {
-                       printk(KERN_INFO "Enabling PDC_PAT chassis codes support.\n");
-                       handle = 1;
-               }
-               else if (unlikely(pdc_chassis_old)) {
-                       printk(KERN_INFO "Enabling old style chassis LED panel support.\n");
-                       handle = 1;
-               }
-
-               if (handle) {
-                       /* initialize panic notifier chain */
-                       atomic_notifier_chain_register(&panic_notifier_list,
-                                       &pdc_chassis_panic_block);
-
-                       /* initialize reboot notifier chain */
-                       register_reboot_notifier(&pdc_chassis_reboot_block);
-               }
+               printk(KERN_INFO "Enabling %s chassis codes support v%s\n",
+                               is_pdc_pat() ? "PDC_PAT" : "regular",
+                               PDC_CHASSIS_VER);
+
+               /* initialize panic notifier chain */
+               atomic_notifier_chain_register(&panic_notifier_list,
+                               &pdc_chassis_panic_block);
+
+               /* initialize reboot notifier chain */
+               register_reboot_notifier(&pdc_chassis_reboot_block);
        }
 #endif /* CONFIG_PDC_CHASSIS */
 }
@@ -215,9 +209,12 @@ int pdc_chassis_send_status(int message)
                        }
                } else retval = -1;
 #else
-               if (unlikely(pdc_chassis_old)) {
+               if (1) {
                        switch (message) {
                                case PDC_CHASSIS_DIRECT_BSTART:
+                                       retval = pdc_chassis_disp(PDC_CHASSIS_DISP_DATA(OSTAT_INIT));
+                                       break;
+
                                case PDC_CHASSIS_DIRECT_BCOMPLETE:
                                        retval = pdc_chassis_disp(PDC_CHASSIS_DISP_DATA(OSTAT_RUN));
                                        break;
@@ -244,3 +241,61 @@ int pdc_chassis_send_status(int message)
 #endif /* CONFIG_PDC_CHASSIS */
        return retval;
 }
+
+#ifdef CONFIG_PDC_CHASSIS_WARN
+#ifdef CONFIG_PROC_FS
+static int pdc_chassis_warn_pread(char *page, char **start, off_t off,
+               int count, int *eof, void *data)
+{
+       char *out = page;
+       int len, ret;
+       unsigned long warn;
+       u32 warnreg;
+
+       ret = pdc_chassis_warn(&warn);
+       if (ret != PDC_OK)
+               return -EIO;
+
+       warnreg = (warn & 0xFFFFFFFF);
+
+       if ((warnreg >> 24) & 0xFF)
+               out += sprintf(out, "Chassis component failure! (eg fan or PSU): 0x%.2x\n", ((warnreg >> 24) & 0xFF));
+
+       out += sprintf(out, "Battery: %s\n", (warnreg & 0x04) ? "Low!" : "OK");
+       out += sprintf(out, "Temp low: %s\n", (warnreg & 0x02) ? "Exceeded!" : "OK");
+       out += sprintf(out, "Temp mid: %s\n", (warnreg & 0x01) ? "Exceeded!" : "OK");
+
+       len = out - page - off;
+       if (len < count) {
+               *eof = 1;
+               if (len <= 0) return 0;
+       } else {
+               len = count;
+       }
+       *start = page + off;
+       return len;
+}
+
+static int __init pdc_chassis_create_procfs(void)
+{
+       unsigned long test;
+       int ret;
+
+       ret = pdc_chassis_warn(&test);
+       if ((ret == PDC_BAD_PROC) || (ret == PDC_BAD_OPTION)) {
+               /* seems that some boxes (eg L1000) do not implement this */
+               printk(KERN_INFO "Chassis warnings not supported.\n");
+               return 0;
+       }
+
+       printk(KERN_INFO "Enabling PDC chassis warnings support v%s\n",
+                       PDC_CHASSIS_VER);
+       create_proc_read_entry("chassis", 0400, NULL, pdc_chassis_warn_pread,
+                               NULL);
+       return 0;
+}
+
+__initcall(pdc_chassis_create_procfs);
+
+#endif /* CONFIG_PROC_FS */
+#endif /* CONFIG_PDC_CHASSIS_WARN */
index 413292f..3f28de9 100644 (file)
@@ -91,7 +91,7 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
                int copied;
 
 #ifdef __LP64__
-               if (personality(child->personality) == PER_LINUX32) {
+               if (__is_compat_task(child)) {
                        unsigned int tmp;
 
                        addr &= 0xffffffffL;
@@ -123,7 +123,7 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
        case PTRACE_POKEDATA:
                ret = 0;
 #ifdef __LP64__
-               if (personality(child->personality) == PER_LINUX32) {
+               if (__is_compat_task(child)) {
                        unsigned int tmp = (unsigned int)data;
                        DBG("sys_ptrace(POKE%s, %d, %lx, %lx)\n",
                                request == PTRACE_POKETEXT ? "TEXT" : "DATA",
@@ -146,7 +146,7 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
        case PTRACE_PEEKUSR: {
                ret = -EIO;
 #ifdef __LP64__
-               if (personality(child->personality) == PER_LINUX32) {
+               if (__is_compat_task(child)) {
                        unsigned int tmp;
 
                        if (addr & (sizeof(int)-1))
@@ -205,7 +205,7 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
                        goto out_tsk;
                }
 #ifdef __LP64__
-               if (personality(child->personality) == PER_LINUX32) {
+               if (__is_compat_task(child)) {
                        if (addr & (sizeof(int)-1))
                                goto out_tsk;
                        if ((addr = translate_usr_offset(addr)) < 0)
index 8c2859c..453d01a 100644 (file)
@@ -276,15 +276,6 @@ r64_ret:
 
 #endif
 
-       .export pc_in_user_space
-       .text
-       /* Doesn't belong here but I couldn't find a nicer spot. */
-       /* Should never get called, only used by profile stuff in time.c */
-pc_in_user_space:
-       bv,n    0(%rp)
-       nop
-
-
        .export __canonicalize_funcptr_for_compare
        .text
        /* http://lists.parisc-linux.org/hypermail/parisc-linux/10916.html
index 4a36ec3..278f4b9 100644 (file)
@@ -303,6 +303,8 @@ extern void eisa_init(void);
 
 static int __init parisc_init(void)
 {
+       u32 osid = (OS_ID_LINUX << 16);
+
        parisc_proc_mkdir();
        parisc_init_resources();
        do_device_inventory();                  /* probe for hardware */
@@ -311,6 +313,9 @@ static int __init parisc_init(void)
        
        /* set up a new led state on systems shipped LED State panel */
        pdc_chassis_send_status(PDC_CHASSIS_DIRECT_BSTART);
+
+       /* tell PDC we're Linux. Nevermind failure. */
+       pdc_stable_write(0x40, &osid, sizeof(osid));
        
        processor_init();
        printk(KERN_INFO "CPU(s): %d x %s at %d.%06d MHz\n",
index cc38edf..bb83880 100644 (file)
@@ -76,7 +76,7 @@ sys_rt_sigsuspend(sigset_t __user *unewset, size_t sigsetsize, struct pt_regs *r
 #ifdef __LP64__
        compat_sigset_t newset32;
 
-       if(personality(current->personality) == PER_LINUX32){
+       if (is_compat_task()) {
                /* XXX: Don't preclude handling different sized sigset_t's.  */
                if (sigsetsize != sizeof(compat_sigset_t))
                        return -EINVAL;
@@ -153,7 +153,7 @@ sys_rt_sigreturn(struct pt_regs *regs, int in_syscall)
        compat_sigset_t compat_set;
        struct compat_rt_sigframe __user * compat_frame;
        
-       if(personality(current->personality) == PER_LINUX32)
+       if (is_compat_task())
                sigframe_size = PARISC_RT_SIGFRAME_SIZE32;
 #endif
 
@@ -166,7 +166,7 @@ sys_rt_sigreturn(struct pt_regs *regs, int in_syscall)
 #ifdef __LP64__
        compat_frame = (struct compat_rt_sigframe __user *)frame;
        
-       if(personality(current->personality) == PER_LINUX32){
+       if (is_compat_task()) {
                DBG(2,"sys_rt_sigreturn: ELF32 process.\n");
                if (__copy_from_user(&compat_set, &compat_frame->uc.uc_sigmask, sizeof(compat_set)))
                        goto give_sigsegv;
@@ -186,7 +186,7 @@ sys_rt_sigreturn(struct pt_regs *regs, int in_syscall)
 
        /* Good thing we saved the old gr[30], eh? */
 #ifdef __LP64__
-       if(personality(current->personality) == PER_LINUX32){
+       if (is_compat_task()) {
                DBG(1,"sys_rt_sigreturn: compat_frame->uc.uc_mcontext 0x%p\n",
                                &compat_frame->uc.uc_mcontext);
 // FIXME: Load upper half from register file
@@ -315,7 +315,7 @@ setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
 
        compat_frame = (struct compat_rt_sigframe __user *)frame;
        
-       if(personality(current->personality) == PER_LINUX32) {
+       if (is_compat_task()) {
                DBG(1,"setup_rt_frame: frame->info = 0x%p\n", &compat_frame->info);
                err |= copy_siginfo_to_user32(&compat_frame->info, info);
                DBG(1,"SETUP_RT_FRAME: 1\n");
@@ -392,7 +392,7 @@ setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
        haddr = A(ka->sa.sa_handler);
        /* The sa_handler may be a pointer to a function descriptor */
 #ifdef __LP64__
-       if(personality(current->personality) == PER_LINUX32) {
+       if (is_compat_task()) {
 #endif
                if (haddr & PA_PLABEL_FDESC) {
                        Elf32_Fdesc fdesc;
@@ -427,19 +427,19 @@ setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
         */
        sigframe_size = PARISC_RT_SIGFRAME_SIZE;
 #ifdef __LP64__
-       if(personality(current->personality) == PER_LINUX32)
+       if (is_compat_task())
                sigframe_size = PARISC_RT_SIGFRAME_SIZE32;
 #endif
        if (in_syscall) {
                regs->gr[31] = haddr;
 #ifdef __LP64__
-               if(personality(current->personality) == PER_LINUX)
+               if (personality(current->personality) == PER_LINUX)
                        sigframe_size |= 1;
 #endif
        } else {
                unsigned long psw = USER_PSW;
 #ifdef __LP64__
-               if(personality(current->personality) == PER_LINUX)
+               if (personality(current->personality) == PER_LINUX)
                        psw |= PSW_W;
 #endif
 
@@ -464,7 +464,7 @@ setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
        regs->gr[26] = sig;               /* signal number */
        
 #ifdef __LP64__
-       if(personality(current->personality) == PER_LINUX32){
+       if (is_compat_task()) {
                regs->gr[25] = A(&compat_frame->info); /* siginfo pointer */
                regs->gr[24] = A(&compat_frame->uc);   /* ucontext pointer */
        } else
index 479d9a0..9670a89 100644 (file)
        .level          1.1
 #endif
 
-#ifndef CONFIG_64BIT
-       .macro fixup_branch,lbl
-       b           \lbl
-       .endm
-#else
-       .macro fixup_branch,lbl
-       ldil        L%\lbl, %r1
-       ldo         R%\lbl(%r1), %r1
-       bv,n        %r0(%r1)
-       .endm
-#endif
-
        .text
 
        .import syscall_exit,code
@@ -541,7 +529,7 @@ cas_nocontend:
 # endif
 /* ENABLE_LWS_DEBUG */
 
-       ldcw    0(%sr2,%r20), %r28                      /* Try to acquire the lock */
+       LDCW    0(%sr2,%r20), %r28                      /* Try to acquire the lock */
        cmpb,<>,n       %r0, %r28, cas_action           /* Did we get it? */
 cas_wouldblock:
        ldo     2(%r0), %r28                            /* 2nd case */
index 594930b..eb35e1c 100644 (file)
@@ -157,8 +157,22 @@ do_gettimeofday (struct timeval *tv)
                usec += (xtime.tv_nsec / 1000);
        } while (read_seqretry_irqrestore(&xtime_lock, seq, flags));
 
-       while (usec >= 1000000) {
-               usec -= 1000000;
+       if (unlikely(usec > LONG_MAX)) {
+               /* This can happen if the gettimeoffset adjustment is
+                * negative and xtime.tv_nsec is smaller than the
+                * adjustment */
+               printk(KERN_ERR "do_gettimeofday() spurious xtime.tv_nsec of %ld\n", usec);
+               usec += USEC_PER_SEC;
+               --sec;
+               /* This should never happen, it means the negative
+                * time adjustment was more than a second, so there's
+                * something seriously wrong */
+               BUG_ON(usec > LONG_MAX);
+       }
+
+
+       while (usec >= USEC_PER_SEC) {
+               usec -= USEC_PER_SEC;
                ++sec;
        }
 
index ff20060..348344a 100644 (file)
@@ -66,57 +66,42 @@ int printbinary(char *buf, unsigned long x, int nbits)
 #else
 #define RFMT "%08lx"
 #endif
+#define FFMT "%016llx" /* fpregs are 64-bit always */
 
-void show_regs(struct pt_regs *regs)
+#define PRINTREGS(lvl,r,f,fmt,x)       \
+       printk("%s%s%02d-%02d  " fmt " " fmt " " fmt " " fmt "\n",      \
+               lvl, f, (x), (x+3), (r)[(x)+0], (r)[(x)+1],             \
+               (r)[(x)+2], (r)[(x)+3])
+
+static void print_gr(char *level, struct pt_regs *regs)
 {
        int i;
-       char buf[128], *p;
-       char *level;
-       unsigned long cr30;
-       unsigned long cr31;
-       /* carlos says that gcc understands better memory in a struct,
-        * and it makes our life easier with fpregs -- T-Bone */
-       struct { u32 sw[2]; } s;
-       
-       level = user_mode(regs) ? KERN_DEBUG : KERN_CRIT;
-
-       printk("%s\n", level); /* don't want to have that pretty register dump messed up */
+       char buf[64];
 
+       printk("%s\n", level);
        printk("%s     YZrvWESTHLNXBCVMcbcbcbcbOGFRQPDI\n", level);
        printbinary(buf, regs->gr[0], 32);
        printk("%sPSW: %s %s\n", level, buf, print_tainted());
 
-       for (i = 0; i < 32; i += 4) {
-               int j;
-               p = buf;
-               p += sprintf(p, "%sr%02d-%02d ", level, i, i + 3);
-               for (j = 0; j < 4; j++) {
-                       p += sprintf(p, " " RFMT, (i+j) == 0 ? 0 : regs->gr[i + j]);
-               }
-               printk("%s\n", buf);
-       }
+       for (i = 0; i < 32; i += 4)
+               PRINTREGS(level, regs->gr, "r", RFMT, i);
+}
 
-       for (i = 0; i < 8; i += 4) {
-               int j;
-               p = buf;
-               p += sprintf(p, "%ssr%d-%d  ", level, i, i + 3);
-               for (j = 0; j < 4; j++) {
-                       p += sprintf(p, " " RFMT, regs->sr[i + j]);
-               }
-               printk("%s\n", buf);
-       }
+static void print_fr(char *level, struct pt_regs *regs)
+{
+       int i;
+       char buf[64];
+       struct { u32 sw[2]; } s;
 
        /* FR are 64bit everywhere. Need to use asm to get the content
         * of fpsr/fper1, and we assume that we won't have a FP Identify
         * in our way, otherwise we're screwed.
         * The fldd is used to restore the T-bit if there was one, as the
         * store clears it anyway.
-        * BTW, PA2.0 book says "thou shall not use fstw on FPSR/FPERs". */ 
-       __asm__ (
-               "fstd %%fr0,0(%1)       \n\t"
-               "fldd 0(%1),%%fr0       \n\t"
-               : "=m" (s) : "r" (&s) : "%r0"
-               );
+        * PA2.0 book says "thou shall not use fstw on FPSR/FPERs" - T-Bone */
+       asm volatile ("fstd %%fr0,0(%1) \n\t"
+                     "fldd 0(%1),%%fr0 \n\t"
+                     : "=m" (s) : "r" (&s) : "r0");
 
        printk("%s\n", level);
        printk("%s      VZOUICununcqcqcqcqcqcrmunTDVZOUI\n", level);
@@ -125,14 +110,25 @@ void show_regs(struct pt_regs *regs)
        printk("%sFPER1: %08x\n", level, s.sw[1]);
 
        /* here we'll print fr0 again, tho it'll be meaningless */
-       for (i = 0; i < 32; i += 4) {
-               int j;
-               p = buf;
-               p += sprintf(p, "%sfr%02d-%02d ", level, i, i + 3);
-               for (j = 0; j < 4; j++)
-                       p += sprintf(p, " %016llx", (i+j) == 0 ? 0 : regs->fr[i+j]);
-               printk("%s\n", buf);
-       }
+       for (i = 0; i < 32; i += 4)
+               PRINTREGS(level, regs->fr, "fr", FFMT, i);
+}
+
+void show_regs(struct pt_regs *regs)
+{
+       int i;
+       char *level;
+       unsigned long cr30, cr31;
+
+       level = user_mode(regs) ? KERN_DEBUG : KERN_CRIT;
+
+       print_gr(level, regs);
+
+       for (i = 0; i < 8; i += 4)
+               PRINTREGS(level, regs->sr, "sr", RFMT, i);
+
+       if (user_mode(regs))
+               print_fr(level, regs);
 
        cr30 = mfctl(30);
        cr31 = mfctl(31);
index de0a1b2..92328fb 100644 (file)
@@ -43,6 +43,8 @@
        "\tldil L%%" #lbl ", %%r1\n"                    \
        "\tldo R%%" #lbl "(%%r1), %%r1\n"               \
        "\tbv,n %%r0(%%r1)\n"
+/* If you use FIXUP_BRANCH, then you must list this clobber */
+#define FIXUP_BRANCH_CLOBBER "r1"
 
 /* 1111 1100 0000 0000 0001 0011 1100 0000 */
 #define OPCODE1(a,b,c) ((a)<<26|(b)<<12|(c)<<6) 
@@ -157,7 +159,7 @@ static int emulate_ldh(struct pt_regs *regs, int toreg)
 "      .previous\n"
        : "=r" (val), "=r" (ret)
        : "0" (val), "r" (saddr), "r" (regs->isr)
-       : "r20" );
+       : "r20", FIXUP_BRANCH_CLOBBER );
 
        DPRINTF("val = 0x" RFMT "\n", val);
 
@@ -202,7 +204,7 @@ static int emulate_ldw(struct pt_regs *regs, int toreg, int flop)
 "      .previous\n"
        : "=r" (val), "=r" (ret)
        : "0" (val), "r" (saddr), "r" (regs->isr)
-       : "r19", "r20" );
+       : "r19", "r20", FIXUP_BRANCH_CLOBBER );
 
        DPRINTF("val = 0x" RFMT "\n", val);
 
@@ -253,7 +255,7 @@ static int emulate_ldd(struct pt_regs *regs, int toreg, int flop)
 "      .previous\n"
        : "=r" (val), "=r" (ret)
        : "0" (val), "r" (saddr), "r" (regs->isr)
-       : "r19", "r20" );
+       : "r19", "r20", FIXUP_BRANCH_CLOBBER );
 #else
     {
        unsigned long valh=0,vall=0;
@@ -287,7 +289,7 @@ static int emulate_ldd(struct pt_regs *regs, int toreg, int flop)
 "      .previous\n"
        : "=r" (valh), "=r" (vall), "=r" (ret)
        : "0" (valh), "1" (vall), "r" (saddr), "r" (regs->isr)
-       : "r19", "r20" );
+       : "r19", "r20", FIXUP_BRANCH_CLOBBER );
        val=((__u64)valh<<32)|(__u64)vall;
     }
 #endif
@@ -335,7 +337,7 @@ static int emulate_sth(struct pt_regs *regs, int frreg)
 "      .previous\n"
        : "=r" (ret)
        : "r" (val), "r" (regs->ior), "r" (regs->isr)
-       : "r19" );
+       : "r19", FIXUP_BRANCH_CLOBBER );
 
        return ret;
 }
@@ -389,7 +391,7 @@ static int emulate_stw(struct pt_regs *regs, int frreg, int flop)
 "      .previous\n"
        : "=r" (ret)
        : "r" (val), "r" (regs->ior), "r" (regs->isr)
-       : "r19", "r20", "r21", "r22", "r1" );
+       : "r19", "r20", "r21", "r22", "r1", FIXUP_BRANCH_CLOBBER );
 
        return 0;
 }
@@ -450,7 +452,7 @@ static int emulate_std(struct pt_regs *regs, int frreg, int flop)
 "      .previous\n"
        : "=r" (ret)
        : "r" (val), "r" (regs->ior), "r" (regs->isr)
-       : "r19", "r20", "r21", "r22", "r1" );
+       : "r19", "r20", "r21", "r22", "r1", FIXUP_BRANCH_CLOBBER );
 #else
     {
        unsigned long valh=(val>>32),vall=(val&0xffffffffl);
@@ -495,7 +497,7 @@ static int emulate_std(struct pt_regs *regs, int frreg, int flop)
 "      .previous\n"
        : "=r" (ret)
        : "r" (valh), "r" (vall), "r" (regs->ior), "r" (regs->isr)
-       : "r19", "r20", "r21", "r1" );
+       : "r19", "r20", "r21", "r1", FIXUP_BRANCH_CLOBBER );
     }
 #endif
 
index 3f5de86..1d3b84b 100644 (file)
@@ -140,18 +140,37 @@ config CHASSIS_LCD_LED
          If unsure, say Y.
 
 config PDC_CHASSIS
-       bool "PDC chassis State Panel support"
+       bool "PDC chassis state codes support"
        default y
        help
-         Say Y here if you want to enable support for the LED State front
-         panel as found on E class, and support for the GSP Virtual Front
-         Panel (LED State and message logging)  as found on high end
-         servers such as A, L and N-class.
-         
-         This has nothing to do with Chassis LCD and LED support.
+         Say Y here if you want to enable support for Chassis codes.
+         That includes support for LED State front panel as found on E
+         class, and support for the GSP Virtual Front Panel (LED State and
+         message logging)  as found on high end servers such as A, L and
+         N-class.
+         This driver will also display progress messages on LCD display,
+         such as "INI", "RUN" and "FLT", and might thus clobber messages
+         shown by the LED/LCD driver.
+         This driver updates the state panel (LED and/or LCD) upon system
+         state change (eg: boot, shutdown or panic).
          
          If unsure, say Y.
 
+
+config PDC_CHASSIS_WARN
+       bool "PDC chassis warnings support"
+       depends on PROC_FS
+       default y
+       help
+         Say Y here if you want to enable support for Chassis warnings.
+         This will add a proc entry '/proc/chassis' giving some information
+         about the overall health state of the system.
+         This includes NVRAM battery level, overtemp or failures such as
+         fans or power units.
+
+         If unsure, say Y.
+
+
 config PDC_STABLE
        tristate "PDC Stable Storage support"
        depends on SYSFS
index bbeabe3..ea1b7a6 100644 (file)
  *    following code can deal with just 96 bytes of Stable Storage, and all
  *    sizes between 96 and 192 bytes (provided they are multiple of struct
  *    device_path size, eg: 128, 160 and 192) to provide full information.
- *    The code makes no use of data above 192 bytes. One last word: there's one
- *    path we can always count on: the primary path.
+ *    One last word: there's one path we can always count on: the primary path.
+ *    Anything above 224 bytes is used for 'osdep2' OS-dependent storage area.
+ *
+ *    The first OS-dependent area should always be available. Obviously, this is
+ *    not true for the other one. Also bear in mind that reading/writing from/to
+ *    osdep2 is much more expensive than from/to osdep1.
+ *    NOTE: We do not handle the 2 bytes OS-dep area at 0x5D, nor the first
+ *    2 bytes of storage available right after OSID. That's a total of 4 bytes
+ *    sacrificed: -ETOOLAZY :P
  *
  *    The current policy wrt file permissions is:
  *     - write: root only
 #include <asm/uaccess.h>
 #include <asm/hardware.h>
 
-#define PDCS_VERSION   "0.22"
+#define PDCS_VERSION   "0.30"
 #define PDCS_PREFIX    "PDC Stable Storage"
 
 #define PDCS_ADDR_PPRI 0x00
 #define PDCS_ADDR_OSID 0x40
+#define PDCS_ADDR_OSD1 0x48
+#define PDCS_ADDR_DIAG 0x58
 #define PDCS_ADDR_FSIZ 0x5C
 #define PDCS_ADDR_PCON 0x60
 #define PDCS_ADDR_PALT 0x80
 #define PDCS_ADDR_PKBD 0xA0
+#define PDCS_ADDR_OSD2 0xE0
 
 MODULE_AUTHOR("Thibaut VARENE <varenet@parisc-linux.org>");
 MODULE_DESCRIPTION("sysfs interface to HP PDC Stable Storage data");
@@ -82,6 +92,9 @@ MODULE_VERSION(PDCS_VERSION);
 /* holds Stable Storage size. Initialized once and for all, no lock needed */
 static unsigned long pdcs_size __read_mostly;
 
+/* holds OS ID. Initialized once and for all, hopefully to 0x0006 */
+static u16 pdcs_osid __read_mostly;
+
 /* This struct defines what we need to deal with a parisc pdc path entry */
 struct pdcspath_entry {
        rwlock_t rw_lock;               /* to protect path entry access */
@@ -609,27 +622,64 @@ static ssize_t
 pdcs_osid_read(struct subsystem *entry, char *buf)
 {
        char *out = buf;
-       __u32 result;
-       char *tmpstr = NULL;
 
        if (!entry || !buf)
                return -EINVAL;
 
-       /* get OSID */
-       if (pdc_stable_read(PDCS_ADDR_OSID, &result, sizeof(result)) != PDC_OK)
+       out += sprintf(out, "%s dependent data (0x%.4x)\n",
+               os_id_to_string(pdcs_osid), pdcs_osid);
+
+       return out - buf;
+}
+
+/**
+ * pdcs_osdep1_read - Stable Storage OS-Dependent data area 1 output.
+ * @entry: An allocated and populated subsytem struct. We don't use it tho.
+ * @buf: The output buffer to write to.
+ *
+ * This can hold 16 bytes of OS-Dependent data.
+ */
+static ssize_t
+pdcs_osdep1_read(struct subsystem *entry, char *buf)
+{
+       char *out = buf;
+       u32 result[4];
+
+       if (!entry || !buf)
+               return -EINVAL;
+
+       if (pdc_stable_read(PDCS_ADDR_OSD1, &result, sizeof(result)) != PDC_OK)
                return -EIO;
 
-       /* the actual result is 16 bits away */
-       switch (result >> 16) {
-               case 0x0000:    tmpstr = "No OS-dependent data"; break;
-               case 0x0001:    tmpstr = "HP-UX dependent data"; break;
-               case 0x0002:    tmpstr = "MPE-iX dependent data"; break;
-               case 0x0003:    tmpstr = "OSF dependent data"; break;
-               case 0x0004:    tmpstr = "HP-RT dependent data"; break;
-               case 0x0005:    tmpstr = "Novell Netware dependent data"; break;
-               default:        tmpstr = "Unknown"; break;
-       }
-       out += sprintf(out, "%s (0x%.4x)\n", tmpstr, (result >> 16));
+       out += sprintf(out, "0x%.8x\n", result[0]);
+       out += sprintf(out, "0x%.8x\n", result[1]);
+       out += sprintf(out, "0x%.8x\n", result[2]);
+       out += sprintf(out, "0x%.8x\n", result[3]);
+
+       return out - buf;
+}
+
+/**
+ * pdcs_diagnostic_read - Stable Storage Diagnostic register output.
+ * @entry: An allocated and populated subsytem struct. We don't use it tho.
+ * @buf: The output buffer to write to.
+ *
+ * I have NFC how to interpret the content of that register ;-).
+ */
+static ssize_t
+pdcs_diagnostic_read(struct subsystem *entry, char *buf)
+{
+       char *out = buf;
+       u32 result;
+
+       if (!entry || !buf)
+               return -EINVAL;
+
+       /* get diagnostic */
+       if (pdc_stable_read(PDCS_ADDR_DIAG, &result, sizeof(result)) != PDC_OK)
+               return -EIO;
+
+       out += sprintf(out, "0x%.4x\n", (result >> 16));
 
        return out - buf;
 }
@@ -645,7 +695,7 @@ static ssize_t
 pdcs_fastsize_read(struct subsystem *entry, char *buf)
 {
        char *out = buf;
-       __u32 result;
+       u32 result;
 
        if (!entry || !buf)
                return -EINVAL;
@@ -663,6 +713,39 @@ pdcs_fastsize_read(struct subsystem *entry, char *buf)
        return out - buf;
 }
 
+/**
+ * pdcs_osdep2_read - Stable Storage OS-Dependent data area 2 output.
+ * @entry: An allocated and populated subsytem struct. We don't use it tho.
+ * @buf: The output buffer to write to.
+ *
+ * This can hold pdcs_size - 224 bytes of OS-Dependent data, when available.
+ */
+static ssize_t
+pdcs_osdep2_read(struct subsystem *entry, char *buf)
+{
+       char *out = buf;
+       unsigned long size;
+       unsigned short i;
+       u32 result;
+
+       if (unlikely(pdcs_size <= 224))
+               return -ENODATA;
+
+       size = pdcs_size - 224;
+
+       if (!entry || !buf)
+               return -EINVAL;
+
+       for (i=0; i<size; i+=4) {
+               if (unlikely(pdc_stable_read(PDCS_ADDR_OSD2 + i, &result,
+                                       sizeof(result)) != PDC_OK))
+                       return -EIO;
+               out += sprintf(out, "0x%.8x\n", result);
+       }
+
+       return out - buf;
+}
+
 /**
  * pdcs_auto_write - This function handles autoboot/search flag modifying.
  * @entry: An allocated and populated subsytem struct. We don't use it tho.
@@ -770,13 +853,100 @@ pdcs_autosearch_write(struct subsystem *entry, const char *buf, size_t count)
        return pdcs_auto_write(entry, buf, count, PF_AUTOSEARCH);
 }
 
+/**
+ * pdcs_osdep1_write - Stable Storage OS-Dependent data area 1 input.
+ * @entry: An allocated and populated subsytem struct. We don't use it tho.
+ * @buf: The input buffer to read from.
+ * @count: The number of bytes to be read.
+ *
+ * This can store 16 bytes of OS-Dependent data. We use a byte-by-byte
+ * write approach. It's up to userspace to deal with it when constructing
+ * its input buffer.
+ */
+static ssize_t
+pdcs_osdep1_write(struct subsystem *entry, const char *buf, size_t count)
+{
+       u8 in[16];
+
+       if (!capable(CAP_SYS_ADMIN))
+               return -EACCES;
+
+       if (!entry || !buf || !count)
+               return -EINVAL;
+
+       if (unlikely(pdcs_osid != OS_ID_LINUX))
+               return -EPERM;
+
+       if (count > 16)
+               return -EMSGSIZE;
+
+       /* We'll use a local copy of buf */
+       memset(in, 0, 16);
+       memcpy(in, buf, count);
+
+       if (pdc_stable_write(PDCS_ADDR_OSD1, &in, sizeof(in)) != PDC_OK)
+               return -EIO;
+
+       return count;
+}
+
+/**
+ * pdcs_osdep2_write - Stable Storage OS-Dependent data area 2 input.
+ * @entry: An allocated and populated subsytem struct. We don't use it tho.
+ * @buf: The input buffer to read from.
+ * @count: The number of bytes to be read.
+ *
+ * This can store pdcs_size - 224 bytes of OS-Dependent data. We use a
+ * byte-by-byte write approach. It's up to userspace to deal with it when
+ * constructing its input buffer.
+ */
+static ssize_t
+pdcs_osdep2_write(struct subsystem *entry, const char *buf, size_t count)
+{
+       unsigned long size;
+       unsigned short i;
+       u8 in[4];
+
+       if (!capable(CAP_SYS_ADMIN))
+               return -EACCES;
+
+       if (!entry || !buf || !count)
+               return -EINVAL;
+
+       if (unlikely(pdcs_size <= 224))
+               return -ENOSYS;
+
+       if (unlikely(pdcs_osid != OS_ID_LINUX))
+               return -EPERM;
+
+       size = pdcs_size - 224;
+
+       if (count > size)
+               return -EMSGSIZE;
+
+       /* We'll use a local copy of buf */
+
+       for (i=0; i<count; i+=4) {
+               memset(in, 0, 4);
+               memcpy(in, buf+i, (count-i < 4) ? count-i : 4);
+               if (unlikely(pdc_stable_write(PDCS_ADDR_OSD2 + i, &in,
+                                       sizeof(in)) != PDC_OK))
+                       return -EIO;
+       }
+
+       return count;
+}
+
 /* The remaining attributes. */
 static PDCS_ATTR(size, 0444, pdcs_size_read, NULL);
 static PDCS_ATTR(autoboot, 0644, pdcs_autoboot_read, pdcs_autoboot_write);
 static PDCS_ATTR(autosearch, 0644, pdcs_autosearch_read, pdcs_autosearch_write);
 static PDCS_ATTR(timer, 0444, pdcs_timer_read, NULL);
-static PDCS_ATTR(osid, 0400, pdcs_osid_read, NULL);
+static PDCS_ATTR(osid, 0444, pdcs_osid_read, NULL);
+static PDCS_ATTR(osdep1, 0600, pdcs_osdep1_read, pdcs_osdep1_write);
+static PDCS_ATTR(diagnostic, 0400, pdcs_diagnostic_read, NULL);
 static PDCS_ATTR(fastsize, 0400, pdcs_fastsize_read, NULL);
+static PDCS_ATTR(osdep2, 0600, pdcs_osdep2_read, pdcs_osdep2_write);
 
 static struct subsys_attribute *pdcs_subsys_attrs[] = {
        &pdcs_attr_size,
@@ -784,7 +954,10 @@ static struct subsys_attribute *pdcs_subsys_attrs[] = {
        &pdcs_attr_autosearch,
        &pdcs_attr_timer,
        &pdcs_attr_osid,
+       &pdcs_attr_osdep1,
+       &pdcs_attr_diagnostic,
        &pdcs_attr_fastsize,
+       &pdcs_attr_osdep2,
        NULL,
 };
 
@@ -865,6 +1038,7 @@ pdc_stable_init(void)
 {
        struct subsys_attribute *attr;
        int i, rc = 0, error = 0;
+       u32 result;
 
        /* find the size of the stable storage */
        if (pdc_stable_get_size(&pdcs_size) != PDC_OK) 
@@ -876,6 +1050,13 @@ pdc_stable_init(void)
 
        printk(KERN_INFO PDCS_PREFIX " facility v%s\n", PDCS_VERSION);
 
+       /* get OSID */
+       if (pdc_stable_read(PDCS_ADDR_OSID, &result, sizeof(result)) != PDC_OK)
+               return -EIO;
+
+       /* the actual result is 16 bits away */
+       pdcs_osid = (u16)(result >> 16);
+
        /* For now we'll register the stable subsys within this driver */
        if ((rc = firmware_register(&stable_subsys)))
                goto fail_firmreg;
@@ -887,7 +1068,7 @@ pdc_stable_init(void)
        
        /* register the paths subsys as a subsystem of stable subsys */
        kset_set_kset_s(&paths_subsys, stable_subsys);
-       if ((rc= subsystem_register(&paths_subsys)))
+       if ((rc = subsystem_register(&paths_subsys)))
                goto fail_subsysreg;
 
        /* now we create all "files" for the paths subsys */
index 278f325..d09e39e 100644 (file)
@@ -316,10 +316,10 @@ static int reserve_sba_gart = 1;
 **
 ** Superdome (in particular, REO) allows only 64-bit CSR accesses.
 */
-#define READ_REG32(addr)        le32_to_cpu(__raw_readl(addr))
-#define READ_REG64(addr)        le64_to_cpu(__raw_readq(addr))
-#define WRITE_REG32(val, addr) __raw_writel(cpu_to_le32(val), addr)
-#define WRITE_REG64(val, addr) __raw_writeq(cpu_to_le64(val), addr)
+#define READ_REG32(addr)       readl(addr)
+#define READ_REG64(addr)       readq(addr)
+#define WRITE_REG32(val, addr) writel((val), (addr))
+#define WRITE_REG64(val, addr) writeq((val), (addr))
 
 #ifdef CONFIG_64BIT
 #define READ_REG(addr)         READ_REG64(addr)
@@ -1427,7 +1427,7 @@ sba_ioc_init_pluto(struct parisc_device *sba, struct ioc *ioc, int ioc_num)
        iov_order = get_order(iova_space_size >> (IOVP_SHIFT - PAGE_SHIFT));
        ioc->pdir_size = (iova_space_size / IOVP_SIZE) * sizeof(u64);
 
-       DBG_INIT("%s() hpa 0x%lx IOV %dMB (%d bits)\n",
+       DBG_INIT("%s() hpa 0x%p IOV %dMB (%d bits)\n",
                __FUNCTION__, ioc->ioc_hpa, iova_space_size >> 20,
                iov_order + PAGE_SHIFT);
 
@@ -1764,7 +1764,7 @@ printk("sba_hw_init(): mem_boot 0x%x 0x%x 0x%x 0x%x\n", PAGE0->mem_boot.hpa,
 
        sba_dev->num_ioc = num_ioc;
        for (i = 0; i < num_ioc; i++) {
-               unsigned long ioc_hpa = sba_dev->ioc[i].ioc_hpa;
+               void __iomem *ioc_hpa = sba_dev->ioc[i].ioc_hpa;
                unsigned int j;
 
                for (j=0; j < sizeof(u64) * ROPES_PER_IOC; j+=sizeof(u64)) {
@@ -1776,7 +1776,8 @@ printk("sba_hw_init(): mem_boot 0x%x 0x%x 0x%x 0x%x\n", PAGE0->mem_boot.hpa,
                         * Improves netperf UDP_STREAM by ~10% for bcm5701.
                         */
                        if (IS_PLUTO(sba_dev->iodc)) {
-                               unsigned long rope_cfg, cfg_val;
+                               void __iomem *rope_cfg;
+                               unsigned long cfg_val;
 
                                rope_cfg = ioc_hpa + IOC_ROPE0_CFG + j;
                                cfg_val = READ_REG(rope_cfg);
@@ -1902,7 +1903,7 @@ sba_common_init(struct sba_device *sba_dev)
         * (bit #61, big endian), we have to flush and sync every time
         * IO-PDIR is changed in Ike/Astro.
         */
-       if (boot_cpu_data.pdc.capabilities & PDC_MODEL_IOPDIR_FDC) {
+       if (ioc_needs_fdc) {
                printk(KERN_INFO MODULE_NAME " FDC/SYNC required.\n");
        } else {
                printk(KERN_INFO MODULE_NAME " IOC has cache coherent PDIR.\n");
index 3ce3440..1a7bfe6 100644 (file)
@@ -48,6 +48,7 @@
 #define CALLEE_SAVE_FRAME_SIZE (CALLEE_REG_FRAME_SIZE + CALLEE_FLOAT_FRAME_SIZE)
 
 #ifdef CONFIG_PA20
+#define LDCW           ldcw,co
 #define BL             b,l
 # ifdef CONFIG_64BIT
 #  define LEVEL                2.0w
@@ -55,6 +56,7 @@
 #  define LEVEL                2.0
 # endif
 #else
+#define LDCW           ldcw
 #define BL             bl
 #define LEVEL          1.1
 #endif
index 289624d..71b4eee 100644 (file)
@@ -5,6 +5,7 @@
  */
 #include <linux/types.h>
 #include <linux/sched.h>
+#include <linux/personality.h>
 
 #define COMPAT_USER_HZ 100
 
@@ -149,4 +150,14 @@ static __inline__ void __user *compat_alloc_user_space(long len)
        return (void __user *)regs->gr[30];
 }
 
+static inline int __is_compat_task(struct task_struct *t)
+{
+       return personality(t->personality) == PER_LINUX32;
+}
+
+static inline int is_compat_task(void)
+{
+       return __is_compat_task(current);
+}
+
 #endif /* _ASM_PARISC_COMPAT_H */
index 08364f9..c9b2e35 100644 (file)
@@ -278,12 +278,11 @@ typedef struct {
 /* constants for OS (NVM...) */
 #define OS_ID_NONE             0       /* Undefined OS ID      */
 #define OS_ID_HPUX             1       /* HP-UX OS             */
-#define OS_ID_LINUX            OS_ID_HPUX /* just use the same value as hpux */
 #define OS_ID_MPEXL            2       /* MPE XL OS            */
 #define OS_ID_OSF              3       /* OSF OS               */
 #define OS_ID_HPRT             4       /* HP-RT OS             */
 #define OS_ID_NOVEL            5       /* NOVELL OS            */
-#define OS_ID_NT               6       /* NT OS                */
+#define OS_ID_LINUX            6       /* Linux                */
 
 
 /* constants for PDC_CHASSIS */
@@ -352,8 +351,8 @@ struct pdc_cache_cf {               /* for PDC_CACHE  (I/D-caches) */
                cc_wt   : 1,    /* 0 = WT-Dcache, 1 = WB-Dcache */
                cc_sh   : 2,    /* 0 = separate I/D-cache, else shared I/D-cache */
                cc_cst  : 3,    /* 0 = incoherent D-cache, 1=coherent D-cache */
-               cc_pad1 : 5,    /* reserved */
-               cc_assoc: 8;    /* associativity of I/D-cache */
+               cc_pad1 : 10,   /* reserved */
+               cc_hv   : 3;    /* hversion dependent */
 };
 
 struct pdc_tlb_cf {            /* for PDC_CACHE (I/D-TLB's) */
@@ -719,6 +718,7 @@ void setup_pdc(void);               /* in inventory.c */
 int pdc_add_valid(unsigned long address);
 int pdc_chassis_info(struct pdc_chassis_info *chassis_info, void *led_info, unsigned long len);
 int pdc_chassis_disp(unsigned long disp);
+int pdc_chassis_warn(unsigned long *warn);
 int pdc_coproc_cfg(struct pdc_coproc_cfg *pdc_coproc_info);
 int pdc_iodc_read(unsigned long *actcnt, unsigned long hpa, unsigned int index,
                  void *iodc_data, unsigned int iodc_data_size);
@@ -732,6 +732,7 @@ int pdc_model_cpuid(unsigned long *cpu_id);
 int pdc_model_versions(unsigned long *versions, int id);
 int pdc_model_capabilities(unsigned long *capabilities);
 int pdc_cache_info(struct pdc_cache_info *cache);
+int pdc_spaceid_bits(unsigned long *space_bits);
 #ifndef CONFIG_PA20
 int pdc_btlb_info(struct pdc_btlb_info *btlb);
 int pdc_mem_map_hpa(struct pdc_memory_map *r_addr, struct pdc_module_path *mod_path);
@@ -775,6 +776,18 @@ int pdc_sti_call(unsigned long func, unsigned long flags,
 
 extern void pdc_init(void);
 
+static inline char * os_id_to_string(u16 os_id) {
+       switch(os_id) {
+       case OS_ID_NONE:        return "No OS";
+       case OS_ID_HPUX:        return "HP-UX";
+       case OS_ID_MPEXL:       return "MPE-iX";
+       case OS_ID_OSF:         return "OSF";
+       case OS_ID_HPRT:        return "HP-RT";
+       case OS_ID_NOVEL:       return "Novell Netware";
+       case OS_ID_LINUX:       return "Linux";
+       default:        return "Unknown";
+       }
+}
 #endif /* __ASSEMBLY__ */
 
 #endif /* _PARISC_PDC_H */
index b6bcc67..5066c54 100644 (file)
@@ -506,13 +506,13 @@ static inline void ptep_set_wrprotect(struct mm_struct *mm, unsigned long addr,
 
 /* TLB page size encoding - see table 3-1 in parisc20.pdf */
 #define _PAGE_SIZE_ENCODING_4K         0
-#define _PAGE_SIZE_ENCODING_16K        1
-#define _PAGE_SIZE_ENCODING_64K        2
+#define _PAGE_SIZE_ENCODING_16K                1
+#define _PAGE_SIZE_ENCODING_64K                2
 #define _PAGE_SIZE_ENCODING_256K       3
 #define _PAGE_SIZE_ENCODING_1M         4
 #define _PAGE_SIZE_ENCODING_4M         5
-#define _PAGE_SIZE_ENCODING_16M        6
-#define _PAGE_SIZE_ENCODING_64M        7
+#define _PAGE_SIZE_ENCODING_16M                6
+#define _PAGE_SIZE_ENCODING_64M                7
 
 #if defined(CONFIG_PARISC_PAGE_SIZE_4KB)
 # define _PAGE_SIZE_ENCODING_DEFAULT _PAGE_SIZE_ENCODING_4K
index ca49dc9..b73626f 100644 (file)
  * Default implementation of macro that returns current
  * instruction pointer ("program counter").
  */
-
-/* We cannot use MFIA as it was added for PA2.0 - prumpf
-
-   At one point there were no "0f/0b" type local symbols in gas for
-   PA-RISC.  This is no longer true, but this still seems like the
-   nicest way to implement this. */
-
-#define current_text_addr() ({ void *pc; __asm__("\n\tblr 0,%0\n\tnop":"=r" (pc)); pc; })
+#ifdef CONFIG_PA20
+#define current_ia(x)  __asm__("mfia %0" : "=r"(x))
+#else /* mfia added in pa2.0 */
+#define current_ia(x)  __asm__("blr 0,%0\n\tnop" : "=r"(x))
+#endif
+#define current_text_addr() ({ void *pc; current_ia(pc); pc; })
 
 #define TASK_SIZE               (current->thread.task_size)
 #define TASK_UNMAPPED_BASE      (current->thread.map_base)
index 8638761..5fe2d23 100644 (file)
@@ -155,13 +155,14 @@ static inline void set_eiem(unsigned long val)
    type and dynamically select the 16-byte aligned int from the array
    for the semaphore.  */
 
-#define __PA_LDCW_ALIGNMENT 16
-#define __ldcw_align(a) ({ \
-  unsigned long __ret = (unsigned long) &(a)->lock[0];                 \
-  __ret = (__ret + __PA_LDCW_ALIGNMENT - 1) & ~(__PA_LDCW_ALIGNMENT - 1); \
-  (volatile unsigned int *) __ret;                                      \
+#define __PA_LDCW_ALIGNMENT    16
+#define __ldcw_align(a) ({                                     \
+       unsigned long __ret = (unsigned long) &(a)->lock[0];    \
+       __ret = (__ret + __PA_LDCW_ALIGNMENT - 1)               \
+               & ~(__PA_LDCW_ALIGNMENT - 1);                   \
+       (volatile unsigned int *) __ret;                        \
 })
-#define LDCW   "ldcw"
+#define __LDCW "ldcw"
 
 #else /*CONFIG_PA20*/
 /* From: "Jim Hull" <jim.hull of hp.com>
@@ -171,17 +172,18 @@ static inline void set_eiem(unsigned long val)
    they only require "natural" alignment (4-byte for ldcw, 8-byte for
    ldcd). */
 
-#define __PA_LDCW_ALIGNMENT 4
+#define __PA_LDCW_ALIGNMENT    4
 #define __ldcw_align(a) ((volatile unsigned int *)a)
-#define LDCW   "ldcw,co"
+#define __LDCW "ldcw,co"
 
 #endif /*!CONFIG_PA20*/
 
 /* LDCW, the only atomic read-write operation PA-RISC has. *sigh*.  */
-#define __ldcw(a) ({ \
-       unsigned __ret; \
-       __asm__ __volatile__(LDCW " 0(%1),%0" : "=r" (__ret) : "r" (a)); \
-       __ret; \
+#define __ldcw(a) ({                                           \
+       unsigned __ret;                                         \
+       __asm__ __volatile__(__LDCW " 0(%1),%0"                 \
+               : "=r" (__ret) : "r" (a));                      \
+       __ret;                                                  \
 })
 
 #ifdef CONFIG_SMP
index f6c417c..d973e8b 100644 (file)
@@ -172,7 +172,11 @@ struct exception_data {
 /*
  * The "__put_user/kernel_asm()" macros tell gcc they read from memory
  * instead of writing. This is because they do not write to any memory
- * gcc knows about, so there are no aliasing issues.
+ * gcc knows about, so there are no aliasing issues. These macros must
+ * also be aware that "fixup_put_user_skip_[12]" are executed in the
+ * context of the fault, and any registers used there must be listed
+ * as clobbers. In this case only "r1" is used by the current routines.
+ * r8/r9 are already listed as err/val.
  */
 
 #ifdef __LP64__
@@ -183,7 +187,8 @@ struct exception_data {
                "\t.dword\t1b,fixup_put_user_skip_1\n"      \
                "\t.previous"                               \
                : "=r"(__pu_err)                            \
-               : "r"(ptr), "r"(x), "0"(__pu_err))
+               : "r"(ptr), "r"(x), "0"(__pu_err)           \
+               : "r1")
 
 #define __put_user_asm(stx,x,ptr)                           \
        __asm__ __volatile__ (                              \
index 12b8672..27bcfad 100644 (file)
 
 #define SYS_ify(syscall_name)   __NR_##syscall_name
 
-/* Assume all syscalls are done from PIC code just to be
- * safe. The worst case scenario is that you lose a register
- * and save/restore r19 across the syscall. */
-#define PIC
-
 #ifndef ASM_LINE_SEP
 # define ASM_LINE_SEP ;
 #endif