Commit 4d3ce21f authored by Linus Torvalds's avatar Linus Torvalds

Merge master.kernel.org:/pub/scm/linux/kernel/git/kyle/parisc-2.6

* 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
  ...
parents b026188e c1a7a755
......@@ -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
......
......@@ -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)
......
......@@ -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
......
......@@ -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.
......
......@@ -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",
......
/*
* 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
......@@ -16,6 +16,10 @@
* 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
......@@ -30,15 +34,16 @@
#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 */
......@@ -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)
......
......@@ -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
......
......@@ -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",
......
......@@ -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
......
......@@ -29,18 +29,6 @@
.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 */
......
......@@ -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;
}
......
......@@ -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);
......
......@@ -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
......
......@@ -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
......
......@@ -28,8 +28,15 @@
* 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
......@@ -64,15 +71,18 @@
#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 */
......
......@@ -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");
......
......@@ -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
......
......@@ -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 */
......@@ -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 */
......@@ -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
......
......@@ -26,14 +26,12 @@
* 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)
......
......@@ -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
......
......@@ -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__ ( \
......
......@@ -797,11 +797,6 @@
#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
......
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