Commit b2477596 authored by Linus Torvalds's avatar Linus Torvalds

Merge branch 'parisc-for-3.11' of git://git.kernel.org/pub/scm/linux/kernel/git/deller/parisc-linux

Pull parisc updates from Helge Deller:
 "The PA-RISC updates for v3.11 include a gcc miscompilation fix,
  gzip-compressed vmlinuz support, a fix in the PCI code for ATI FireGL
  support on c8000 machines, a fix to prevent that %sr1 is being
  clobbered and a few smaller optimizations and documentation updates"

* 'parisc-for-3.11' of git://git.kernel.org/pub/scm/linux/kernel/git/deller/parisc-linux:
  parisc: Fix gcc miscompilation in pa_memcpy()
  parisc: Ensure volatile space register %sr1 is not clobbered
  parisc: optimize mtsp(0,sr) inline assembly
  parisc: switch to gzip-compressed vmlinuz kernel
  parisc: document the shadow registers
  parisc: more capabilities info in /proc/cpuinfo
  parisc: fix LMMIO mismatch between PAT length and MASK register
parents 61e31291 5b879d78
...@@ -77,6 +77,14 @@ PSW default E value 0 ...@@ -77,6 +77,14 @@ PSW default E value 0
Shadow Registers used by interruption handler code Shadow Registers used by interruption handler code
TOC enable bit 1 TOC enable bit 1
=========================================================================
The PA-RISC architecture defines 7 registers as "shadow registers".
Those are used in RETURN FROM INTERRUPTION AND RESTORE instruction to reduce
the state save and restore time by eliminating the need for general register
(GR) saves and restores in interruption handlers.
Shadow registers are the GRs 1, 8, 9, 16, 17, 24, and 25.
========================================================================= =========================================================================
Register usage notes, originally from John Marvin, with some additional Register usage notes, originally from John Marvin, with some additional
notes from Randolph Chung. notes from Randolph Chung.
......
...@@ -17,6 +17,8 @@ ...@@ -17,6 +17,8 @@
# Mike Shaver, Helge Deller and Martin K. Petersen # Mike Shaver, Helge Deller and Martin K. Petersen
# #
KBUILD_IMAGE := vmlinuz
KBUILD_DEFCONFIG := default_defconfig KBUILD_DEFCONFIG := default_defconfig
NM = sh $(srctree)/arch/parisc/nm NM = sh $(srctree)/arch/parisc/nm
...@@ -92,7 +94,7 @@ PALOCONF := $(shell if [ -f $(src)/palo.conf ]; then echo $(src)/palo.conf; \ ...@@ -92,7 +94,7 @@ PALOCONF := $(shell if [ -f $(src)/palo.conf ]; then echo $(src)/palo.conf; \
else echo $(obj)/palo.conf; \ else echo $(obj)/palo.conf; \
fi) fi)
palo: vmlinux palo: vmlinuz
@if test ! -x "$(PALO)"; then \ @if test ! -x "$(PALO)"; then \
echo 'ERROR: Please install palo first (apt-get install palo)';\ echo 'ERROR: Please install palo first (apt-get install palo)';\
echo 'or build it from source and install it somewhere in your $$PATH';\ echo 'or build it from source and install it somewhere in your $$PATH';\
...@@ -107,10 +109,14 @@ palo: vmlinux ...@@ -107,10 +109,14 @@ palo: vmlinux
fi fi
$(PALO) -f $(PALOCONF) $(PALO) -f $(PALOCONF)
# Shorthands for known targets not supported by parisc, use vmlinux as default # Shorthands for known targets not supported by parisc, use vmlinux/vmlinuz as default
Image zImage bzImage: vmlinux Image: vmlinux
zImage bzImage: vmlinuz
vmlinuz: vmlinux
@gzip -cf -9 $< > $@
install: vmlinux install: vmlinuz
sh $(src)/arch/parisc/install.sh \ sh $(src)/arch/parisc/install.sh \
$(KERNELRELEASE) $< System.map "$(INSTALL_PATH)" $(KERNELRELEASE) $< System.map "$(INSTALL_PATH)"
...@@ -119,6 +125,7 @@ MRPROPER_FILES += palo.conf ...@@ -119,6 +125,7 @@ MRPROPER_FILES += palo.conf
define archhelp define archhelp
@echo '* vmlinux - Uncompressed kernel image (./vmlinux)' @echo '* vmlinux - Uncompressed kernel image (./vmlinux)'
@echo ' vmlinuz - Compressed kernel image (./vmlinuz)'
@echo ' palo - Bootable image (./lifimage)' @echo ' palo - Bootable image (./lifimage)'
@echo ' install - Install kernel using' @echo ' install - Install kernel using'
@echo ' (your) ~/bin/$(INSTALLKERNEL) or' @echo ' (your) ~/bin/$(INSTALLKERNEL) or'
......
...@@ -4,7 +4,7 @@ ...@@ -4,7 +4,7 @@
# Most people using 'make palo' want a bootable file, usable for # Most people using 'make palo' want a bootable file, usable for
# network or tape booting for example. # network or tape booting for example.
--init-tape=lifimage --init-tape=lifimage
--recoverykernel=vmlinux --recoverykernel=vmlinuz
########## Pick your ROOT here! ########## ########## Pick your ROOT here! ##########
# You need at least one 'root='! # You need at least one 'root='!
...@@ -12,10 +12,10 @@ ...@@ -12,10 +12,10 @@
# If you want a root ramdisk, use the next 2 lines # If you want a root ramdisk, use the next 2 lines
# (Edit the ramdisk image name!!!!) # (Edit the ramdisk image name!!!!)
--ramdisk=ram-disk-image-file --ramdisk=ram-disk-image-file
--commandline=0/vmlinux HOME=/ root=/dev/ram initrd=0/ramdisk --commandline=0/vmlinuz HOME=/ root=/dev/ram initrd=0/ramdisk panic_timeout=60 panic=-1
# If you want NFS root, use the following command line (Edit the HOSTNAME!!!) # If you want NFS root, use the following command line (Edit the HOSTNAME!!!)
#--commandline=0/vmlinux HOME=/ root=/dev/nfs nfsroot=HOSTNAME ip=bootp #--commandline=0/vmlinuz HOME=/ root=/dev/nfs nfsroot=HOSTNAME ip=bootp
# If you have root on a disk partition, use this (Edit the partition name!!!) # If you have root on a disk partition, use this (Edit the partition name!!!)
#--commandline=0/vmlinux HOME=/ root=/dev/sda1 #--commandline=0/vmlinuz HOME=/ root=/dev/sda1
...@@ -32,9 +32,12 @@ static inline void set_eiem(unsigned long val) ...@@ -32,9 +32,12 @@ static inline void set_eiem(unsigned long val)
cr; \ cr; \
}) })
#define mtsp(gr, cr) \ #define mtsp(val, cr) \
{ if (__builtin_constant_p(val) && ((val) == 0)) \
__asm__ __volatile__("mtsp %%r0,%0" : : "i" (cr) : "memory"); \
else \
__asm__ __volatile__("mtsp %0,%1" \ __asm__ __volatile__("mtsp %0,%1" \
: /* no outputs */ \ : /* no outputs */ \
: "r" (gr), "i" (cr) : "memory") : "r" (val), "i" (cr) : "memory"); }
#endif /* __PARISC_SPECIAL_INSNS_H */ #endif /* __PARISC_SPECIAL_INSNS_H */
...@@ -63,13 +63,14 @@ static inline void flush_tlb_mm(struct mm_struct *mm) ...@@ -63,13 +63,14 @@ static inline void flush_tlb_mm(struct mm_struct *mm)
static inline void flush_tlb_page(struct vm_area_struct *vma, static inline void flush_tlb_page(struct vm_area_struct *vma,
unsigned long addr) unsigned long addr)
{ {
unsigned long flags; unsigned long flags, sid;
/* For one page, it's not worth testing the split_tlb variable */ /* For one page, it's not worth testing the split_tlb variable */
mb(); mb();
mtsp(vma->vm_mm->context,1); sid = vma->vm_mm->context;
purge_tlb_start(flags); purge_tlb_start(flags);
mtsp(sid, 1);
pdtlb(addr); pdtlb(addr);
pitlb(addr); pitlb(addr);
purge_tlb_end(flags); purge_tlb_end(flags);
......
...@@ -26,13 +26,13 @@ if [ -x /sbin/${INSTALLKERNEL} ]; then exec /sbin/${INSTALLKERNEL} "$@"; fi ...@@ -26,13 +26,13 @@ if [ -x /sbin/${INSTALLKERNEL} ]; then exec /sbin/${INSTALLKERNEL} "$@"; fi
# Default install # Default install
if [ -f $4/vmlinux ]; then if [ -f $4/vmlinuz ]; then
mv $4/vmlinux $4/vmlinux.old mv $4/vmlinuz $4/vmlinuz.old
fi fi
if [ -f $4/System.map ]; then if [ -f $4/System.map ]; then
mv $4/System.map $4/System.old mv $4/System.map $4/System.old
fi fi
cat $2 > $4/vmlinux cat $2 > $4/vmlinuz
cp $3 $4/System.map cp $3 $4/System.map
...@@ -440,8 +440,8 @@ void __flush_tlb_range(unsigned long sid, unsigned long start, ...@@ -440,8 +440,8 @@ void __flush_tlb_range(unsigned long sid, unsigned long start,
else { else {
unsigned long flags; unsigned long flags;
mtsp(sid, 1);
purge_tlb_start(flags); purge_tlb_start(flags);
mtsp(sid, 1);
if (split_tlb) { if (split_tlb) {
while (npages--) { while (npages--) {
pdtlb(start); pdtlb(start);
......
...@@ -371,10 +371,23 @@ show_cpuinfo (struct seq_file *m, void *v) ...@@ -371,10 +371,23 @@ show_cpuinfo (struct seq_file *m, void *v)
seq_printf(m, "capabilities\t:"); seq_printf(m, "capabilities\t:");
if (boot_cpu_data.pdc.capabilities & PDC_MODEL_OS32) if (boot_cpu_data.pdc.capabilities & PDC_MODEL_OS32)
seq_printf(m, " os32"); seq_puts(m, " os32");
if (boot_cpu_data.pdc.capabilities & PDC_MODEL_OS64) if (boot_cpu_data.pdc.capabilities & PDC_MODEL_OS64)
seq_printf(m, " os64"); seq_puts(m, " os64");
seq_printf(m, "\n"); if (boot_cpu_data.pdc.capabilities & PDC_MODEL_IOPDIR_FDC)
seq_puts(m, " iopdir_fdc");
switch (boot_cpu_data.pdc.capabilities & PDC_MODEL_NVA_MASK) {
case PDC_MODEL_NVA_SUPPORTED:
seq_puts(m, " nva_supported");
break;
case PDC_MODEL_NVA_SLOW:
seq_puts(m, " nva_slow");
break;
case PDC_MODEL_NVA_UNSUPPORTED:
seq_puts(m, " needs_equivalent_aliasing");
break;
}
seq_printf(m, " (0x%02lx)\n", boot_cpu_data.pdc.capabilities);
seq_printf(m, "model\t\t: %s\n" seq_printf(m, "model\t\t: %s\n"
"model name\t: %s\n", "model name\t: %s\n",
......
...@@ -2,6 +2,7 @@ ...@@ -2,6 +2,7 @@
* Optimized memory copy routines. * Optimized memory copy routines.
* *
* Copyright (C) 2004 Randolph Chung <tausq@debian.org> * Copyright (C) 2004 Randolph Chung <tausq@debian.org>
* Copyright (C) 2013 Helge Deller <deller@gmx.de>
* *
* This program is free software; you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
...@@ -153,17 +154,21 @@ static inline void prefetch_dst(const void *addr) ...@@ -153,17 +154,21 @@ static inline void prefetch_dst(const void *addr)
#define prefetch_dst(addr) do { } while(0) #define prefetch_dst(addr) do { } while(0)
#endif #endif
#define PA_MEMCPY_OK 0
#define PA_MEMCPY_LOAD_ERROR 1
#define PA_MEMCPY_STORE_ERROR 2
/* Copy from a not-aligned src to an aligned dst, using shifts. Handles 4 words /* Copy from a not-aligned src to an aligned dst, using shifts. Handles 4 words
* per loop. This code is derived from glibc. * per loop. This code is derived from glibc.
*/ */
static inline unsigned long copy_dstaligned(unsigned long dst, unsigned long src, unsigned long len, unsigned long o_dst, unsigned long o_src, unsigned long o_len) static inline unsigned long copy_dstaligned(unsigned long dst,
unsigned long src, unsigned long len)
{ {
/* gcc complains that a2 and a3 may be uninitialized, but actually /* gcc complains that a2 and a3 may be uninitialized, but actually
* they cannot be. Initialize a2/a3 to shut gcc up. * they cannot be. Initialize a2/a3 to shut gcc up.
*/ */
register unsigned int a0, a1, a2 = 0, a3 = 0; register unsigned int a0, a1, a2 = 0, a3 = 0;
int sh_1, sh_2; int sh_1, sh_2;
struct exception_data *d;
/* prefetch_src((const void *)src); */ /* prefetch_src((const void *)src); */
...@@ -197,7 +202,7 @@ static inline unsigned long copy_dstaligned(unsigned long dst, unsigned long src ...@@ -197,7 +202,7 @@ static inline unsigned long copy_dstaligned(unsigned long dst, unsigned long src
goto do2; goto do2;
case 0: case 0:
if (len == 0) if (len == 0)
return 0; return PA_MEMCPY_OK;
/* a3 = ((unsigned int *) src)[0]; /* a3 = ((unsigned int *) src)[0];
a0 = ((unsigned int *) src)[1]; */ a0 = ((unsigned int *) src)[1]; */
ldw(s_space, 0, src, a3, cda_ldw_exc); ldw(s_space, 0, src, a3, cda_ldw_exc);
...@@ -256,42 +261,35 @@ static inline unsigned long copy_dstaligned(unsigned long dst, unsigned long src ...@@ -256,42 +261,35 @@ static inline unsigned long copy_dstaligned(unsigned long dst, unsigned long src
preserve_branch(handle_load_error); preserve_branch(handle_load_error);
preserve_branch(handle_store_error); preserve_branch(handle_store_error);
return 0; return PA_MEMCPY_OK;
handle_load_error: handle_load_error:
__asm__ __volatile__ ("cda_ldw_exc:\n"); __asm__ __volatile__ ("cda_ldw_exc:\n");
d = &__get_cpu_var(exception_data); return PA_MEMCPY_LOAD_ERROR;
DPRINTF("cda_ldw_exc: o_len=%lu fault_addr=%lu o_src=%lu ret=%lu\n",
o_len, d->fault_addr, o_src, o_len - d->fault_addr + o_src);
return o_len * 4 - d->fault_addr + o_src;
handle_store_error: handle_store_error:
__asm__ __volatile__ ("cda_stw_exc:\n"); __asm__ __volatile__ ("cda_stw_exc:\n");
d = &__get_cpu_var(exception_data); return PA_MEMCPY_STORE_ERROR;
DPRINTF("cda_stw_exc: o_len=%lu fault_addr=%lu o_dst=%lu ret=%lu\n",
o_len, d->fault_addr, o_dst, o_len - d->fault_addr + o_dst);
return o_len * 4 - d->fault_addr + o_dst;
} }
/* Returns 0 for success, otherwise, returns number of bytes not transferred. */ /* Returns PA_MEMCPY_OK, PA_MEMCPY_LOAD_ERROR or PA_MEMCPY_STORE_ERROR.
static unsigned long pa_memcpy(void *dstp, const void *srcp, unsigned long len) * In case of an access fault the faulty address can be read from the per_cpu
* exception data struct. */
static unsigned long pa_memcpy_internal(void *dstp, const void *srcp,
unsigned long len)
{ {
register unsigned long src, dst, t1, t2, t3; register unsigned long src, dst, t1, t2, t3;
register unsigned char *pcs, *pcd; register unsigned char *pcs, *pcd;
register unsigned int *pws, *pwd; register unsigned int *pws, *pwd;
register double *pds, *pdd; register double *pds, *pdd;
unsigned long ret = 0; unsigned long ret;
unsigned long o_dst, o_src, o_len;
struct exception_data *d;
src = (unsigned long)srcp; src = (unsigned long)srcp;
dst = (unsigned long)dstp; dst = (unsigned long)dstp;
pcs = (unsigned char *)srcp; pcs = (unsigned char *)srcp;
pcd = (unsigned char *)dstp; pcd = (unsigned char *)dstp;
o_dst = dst; o_src = src; o_len = len;
/* prefetch_src((const void *)srcp); */ /* prefetch_src((const void *)srcp); */
if (len < THRESHOLD) if (len < THRESHOLD)
...@@ -401,7 +399,7 @@ static unsigned long pa_memcpy(void *dstp, const void *srcp, unsigned long len) ...@@ -401,7 +399,7 @@ static unsigned long pa_memcpy(void *dstp, const void *srcp, unsigned long len)
len--; len--;
} }
return 0; return PA_MEMCPY_OK;
unaligned_copy: unaligned_copy:
/* possibly we are aligned on a word, but not on a double... */ /* possibly we are aligned on a word, but not on a double... */
...@@ -438,8 +436,7 @@ static unsigned long pa_memcpy(void *dstp, const void *srcp, unsigned long len) ...@@ -438,8 +436,7 @@ static unsigned long pa_memcpy(void *dstp, const void *srcp, unsigned long len)
src = (unsigned long)pcs; src = (unsigned long)pcs;
} }
ret = copy_dstaligned(dst, src, len / sizeof(unsigned int), ret = copy_dstaligned(dst, src, len / sizeof(unsigned int));
o_dst, o_src, o_len);
if (ret) if (ret)
return ret; return ret;
...@@ -454,17 +451,41 @@ static unsigned long pa_memcpy(void *dstp, const void *srcp, unsigned long len) ...@@ -454,17 +451,41 @@ static unsigned long pa_memcpy(void *dstp, const void *srcp, unsigned long len)
handle_load_error: handle_load_error:
__asm__ __volatile__ ("pmc_load_exc:\n"); __asm__ __volatile__ ("pmc_load_exc:\n");
d = &__get_cpu_var(exception_data); return PA_MEMCPY_LOAD_ERROR;
DPRINTF("pmc_load_exc: o_len=%lu fault_addr=%lu o_src=%lu ret=%lu\n",
o_len, d->fault_addr, o_src, o_len - d->fault_addr + o_src);
return o_len - d->fault_addr + o_src;
handle_store_error: handle_store_error:
__asm__ __volatile__ ("pmc_store_exc:\n"); __asm__ __volatile__ ("pmc_store_exc:\n");
return PA_MEMCPY_STORE_ERROR;
}
/* Returns 0 for success, otherwise, returns number of bytes not transferred. */
static unsigned long pa_memcpy(void *dstp, const void *srcp, unsigned long len)
{
unsigned long ret, fault_addr, reference;
struct exception_data *d;
ret = pa_memcpy_internal(dstp, srcp, len);
if (likely(ret == PA_MEMCPY_OK))
return 0;
/* if a load or store fault occured we can get the faulty addr */
d = &__get_cpu_var(exception_data); d = &__get_cpu_var(exception_data);
DPRINTF("pmc_store_exc: o_len=%lu fault_addr=%lu o_dst=%lu ret=%lu\n", fault_addr = d->fault_addr;
o_len, d->fault_addr, o_dst, o_len - d->fault_addr + o_dst);
return o_len - d->fault_addr + o_dst; /* error in load or store? */
if (ret == PA_MEMCPY_LOAD_ERROR)
reference = (unsigned long) srcp;
else
reference = (unsigned long) dstp;
DPRINTF("pa_memcpy: fault type = %lu, len=%lu fault_addr=%lu ref=%lu\n",
ret, len, fault_addr, reference);
if (fault_addr >= reference)
return len - (fault_addr - reference);
else
return len;
} }
#ifdef __KERNEL__ #ifdef __KERNEL__
......
...@@ -613,6 +613,54 @@ truncate_pat_collision(struct resource *root, struct resource *new) ...@@ -613,6 +613,54 @@ truncate_pat_collision(struct resource *root, struct resource *new)
return 0; /* truncation successful */ return 0; /* truncation successful */
} }
/*
* extend_lmmio_len: extend lmmio range to maximum length
*
* This is needed at least on C8000 systems to get the ATI FireGL card
* working. On other systems we will currently not extend the lmmio space.
*/
static unsigned long
extend_lmmio_len(unsigned long start, unsigned long end, unsigned long lba_len)
{
struct resource *tmp;
pr_debug("LMMIO mismatch: PAT length = 0x%lx, MASK register = 0x%lx\n",
end - start, lba_len);
lba_len = min(lba_len+1, 256UL*1024*1024); /* limit to 256 MB */
pr_debug("LBA: lmmio_space [0x%lx-0x%lx] - original\n", start, end);
if (boot_cpu_data.cpu_type < mako) {
pr_info("LBA: Not a C8000 system - not extending LMMIO range.\n");
return end;
}
end += lba_len;
if (end < start) /* fix overflow */
end = -1ULL;
pr_debug("LBA: lmmio_space [0x%lx-0x%lx] - current\n", start, end);
/* first overlap */
for (tmp = iomem_resource.child; tmp; tmp = tmp->sibling) {
pr_debug("LBA: testing %pR\n", tmp);
if (tmp->start == start)
continue; /* ignore ourself */
if (tmp->end < start)
continue;
if (tmp->start > end)
continue;
if (end >= tmp->start)
end = tmp->start - 1;
}
pr_info("LBA: lmmio_space [0x%lx-0x%lx] - new\n", start, end);
/* return new end */
return end;
}
#else #else
#define truncate_pat_collision(r,n) (0) #define truncate_pat_collision(r,n) (0)
#endif #endif
...@@ -994,6 +1042,14 @@ lba_pat_resources(struct parisc_device *pa_dev, struct lba_device *lba_dev) ...@@ -994,6 +1042,14 @@ lba_pat_resources(struct parisc_device *pa_dev, struct lba_device *lba_dev)
case PAT_LMMIO: case PAT_LMMIO:
/* used to fix up pre-initialized MEM BARs */ /* used to fix up pre-initialized MEM BARs */
if (!lba_dev->hba.lmmio_space.flags) { if (!lba_dev->hba.lmmio_space.flags) {
unsigned long lba_len;
lba_len = ~READ_REG32(lba_dev->hba.base_addr
+ LBA_LMMIO_MASK);
if ((p->end - p->start) != lba_len)
p->end = extend_lmmio_len(p->start,
p->end, lba_len);
sprintf(lba_dev->hba.lmmio_name, sprintf(lba_dev->hba.lmmio_name,
"PCI%02x LMMIO", "PCI%02x LMMIO",
(int)lba_dev->hba.bus_num.start); (int)lba_dev->hba.bus_num.start);
......
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