diff options
58 files changed, 864 insertions, 638 deletions
diff --git a/Documentation/ABI/testing/pstore b/Documentation/ABI/testing/pstore index f1fb2a00426..ddf451ee2a0 100644 --- a/Documentation/ABI/testing/pstore +++ b/Documentation/ABI/testing/pstore @@ -1,6 +1,6 @@ Where: /dev/pstore/... -Date: January 2011 -Kernel Version: 2.6.38 +Date: March 2011 +Kernel Version: 2.6.39 Contact: tony.luck@intel.com Description: Generic interface to platform dependent persistent storage. @@ -11,7 +11,7 @@ Description: Generic interface to platform dependent persistent storage. of the console log is captured, but other interesting data can also be saved. - # mount -t pstore - /dev/pstore + # mount -t pstore -o kmsg_bytes=8000 - /dev/pstore $ ls -l /dev/pstore total 0 @@ -33,3 +33,9 @@ Description: Generic interface to platform dependent persistent storage. will be saved elsewhere and erased from persistent store soon after boot to free up space ready for the next catastrophe. + + The 'kmsg_bytes' mount option changes the target amount of + data saved on each oops/panic. Pstore saves (possibly + multiple) files based on the record size of the underlying + persistent storage until at least this amount is reached. + Default is 10 Kbytes. diff --git a/Documentation/ABI/testing/sysfs-fs-pstore b/Documentation/ABI/testing/sysfs-fs-pstore deleted file mode 100644 index 8e659d85480..00000000000 --- a/Documentation/ABI/testing/sysfs-fs-pstore +++ /dev/null @@ -1,7 +0,0 @@ -What: /sys/fs/pstore/kmsg_bytes -Date: January 2011 -Kernel Version: 2.6.38 -Contact: "Tony Luck" <tony.luck@intel.com> -Description: - Controls amount of console log that will be saved - to persistent store on oops/panic. diff --git a/Documentation/devicetree/bindings/open-pic.txt b/Documentation/devicetree/bindings/open-pic.txt new file mode 100644 index 00000000000..909a902dff8 --- /dev/null +++ b/Documentation/devicetree/bindings/open-pic.txt @@ -0,0 +1,98 @@ +* Open PIC Binding + +This binding specifies what properties must be available in the device tree +representation of an Open PIC compliant interrupt controller. This binding is +based on the binding defined for Open PIC in [1] and is a superset of that +binding. + +Required properties: + + NOTE: Many of these descriptions were paraphrased here from [1] to aid + readability. + + - compatible: Specifies the compatibility list for the PIC. The type + shall be <string> and the value shall include "open-pic". + + - reg: Specifies the base physical address(s) and size(s) of this + PIC's addressable register space. The type shall be <prop-encoded-array>. + + - interrupt-controller: The presence of this property identifies the node + as an Open PIC. No property value shall be defined. + + - #interrupt-cells: Specifies the number of cells needed to encode an + interrupt source. The type shall be a <u32> and the value shall be 2. + + - #address-cells: Specifies the number of cells needed to encode an + address. The type shall be <u32> and the value shall be 0. As such, + 'interrupt-map' nodes do not have to specify a parent unit address. + +Optional properties: + + - pic-no-reset: The presence of this property indicates that the PIC + shall not be reset during runtime initialization. No property value shall + be defined. The presence of this property also mandates that any + initialization related to interrupt sources shall be limited to sources + explicitly referenced in the device tree. + +* Interrupt Specifier Definition + + Interrupt specifiers consists of 2 cells encoded as + follows: + + - <1st-cell>: The interrupt-number that identifies the interrupt source. + + - <2nd-cell>: The level-sense information, encoded as follows: + 0 = low-to-high edge triggered + 1 = active low level-sensitive + 2 = active high level-sensitive + 3 = high-to-low edge triggered + +* Examples + +Example 1: + + /* + * An Open PIC interrupt controller + */ + mpic: pic@40000 { + // This is an interrupt controller node. + interrupt-controller; + + // No address cells so that 'interrupt-map' nodes which reference + // this Open PIC node do not need a parent address specifier. + #address-cells = <0>; + + // Two cells to encode interrupt sources. + #interrupt-cells = <2>; + + // Offset address of 0x40000 and size of 0x40000. + reg = <0x40000 0x40000>; + + // Compatible with Open PIC. + compatible = "open-pic"; + + // The PIC shall not be reset. + pic-no-reset; + }; + +Example 2: + + /* + * An interrupt generating device that is wired to an Open PIC. + */ + serial0: serial@4500 { + // Interrupt source '42' that is active high level-sensitive. + // Note that there are only two cells as specified in the interrupt + // parent's '#interrupt-cells' property. + interrupts = <42 2>; + + // The interrupt controller that this device is wired to. + interrupt-parent = <&mpic>; + }; + +* References + +[1] Power.org (TM) Standard for Embedded Power Architecture (TM) Platform + Requirements (ePAPR), Version 1.0, July 2008. + (http://www.power.org/resources/downloads/Power_ePAPR_APPROVED_v1.0.pdf) + diff --git a/arch/parisc/Kconfig b/arch/parisc/Kconfig index fed2946f733..fafdf30bea9 100644 --- a/arch/parisc/Kconfig +++ b/arch/parisc/Kconfig @@ -15,6 +15,7 @@ config PARISC select HAVE_GENERIC_HARDIRQS select GENERIC_IRQ_PROBE select IRQ_PER_CPU + select GENERIC_HARDIRQS_NO_DEPRECATED help The PA-RISC microprocessor is designed by Hewlett-Packard and used diff --git a/arch/parisc/include/asm/cacheflush.h b/arch/parisc/include/asm/cacheflush.h index f388a85bba1..d18328b3f93 100644 --- a/arch/parisc/include/asm/cacheflush.h +++ b/arch/parisc/include/asm/cacheflush.h @@ -26,8 +26,6 @@ void flush_user_dcache_range_asm(unsigned long, unsigned long); void flush_kernel_dcache_range_asm(unsigned long, unsigned long); void flush_kernel_dcache_page_asm(void *); void flush_kernel_icache_page(void *); -void flush_user_dcache_page(unsigned long); -void flush_user_icache_page(unsigned long); void flush_user_dcache_range(unsigned long, unsigned long); void flush_user_icache_range(unsigned long, unsigned long); @@ -37,6 +35,13 @@ void flush_cache_all_local(void); void flush_cache_all(void); void flush_cache_mm(struct mm_struct *mm); +#define ARCH_HAS_FLUSH_KERNEL_DCACHE_PAGE +void flush_kernel_dcache_page_addr(void *addr); +static inline void flush_kernel_dcache_page(struct page *page) +{ + flush_kernel_dcache_page_addr(page_address(page)); +} + #define flush_kernel_dcache_range(start,size) \ flush_kernel_dcache_range_asm((start), (start)+(size)); /* vmap range flushes and invalidates. Architecturally, we don't need @@ -50,6 +55,16 @@ static inline void flush_kernel_vmap_range(void *vaddr, int size) } static inline void invalidate_kernel_vmap_range(void *vaddr, int size) { + unsigned long start = (unsigned long)vaddr; + void *cursor = vaddr; + + for ( ; cursor < vaddr + size; cursor += PAGE_SIZE) { + struct page *page = vmalloc_to_page(cursor); + + if (test_and_clear_bit(PG_dcache_dirty, &page->flags)) + flush_kernel_dcache_page(page); + } + flush_kernel_dcache_range_asm(start, start + size); } #define flush_cache_vmap(start, end) flush_cache_all() @@ -90,19 +105,15 @@ void flush_cache_page(struct vm_area_struct *vma, unsigned long vmaddr, unsigned void flush_cache_range(struct vm_area_struct *vma, unsigned long start, unsigned long end); +/* defined in pacache.S exported in cache.c used by flush_anon_page */ +void flush_dcache_page_asm(unsigned long phys_addr, unsigned long vaddr); + #define ARCH_HAS_FLUSH_ANON_PAGE static inline void flush_anon_page(struct vm_area_struct *vma, struct page *page, unsigned long vmaddr) { if (PageAnon(page)) - flush_user_dcache_page(vmaddr); -} - -#define ARCH_HAS_FLUSH_KERNEL_DCACHE_PAGE -void flush_kernel_dcache_page_addr(void *addr); -static inline void flush_kernel_dcache_page(struct page *page) -{ - flush_kernel_dcache_page_addr(page_address(page)); + flush_dcache_page_asm(page_to_phys(page), vmaddr); } #ifdef CONFIG_DEBUG_RODATA diff --git a/arch/parisc/include/asm/irq.h b/arch/parisc/include/asm/irq.h index c67dccf2e31..1073599a7be 100644 --- a/arch/parisc/include/asm/irq.h +++ b/arch/parisc/include/asm/irq.h @@ -32,15 +32,10 @@ static __inline__ int irq_canonicalize(int irq) } struct irq_chip; +struct irq_data; -/* - * Some useful "we don't have to do anything here" handlers. Should - * probably be provided by the generic code. - */ -void no_ack_irq(unsigned int irq); -void no_end_irq(unsigned int irq); -void cpu_ack_irq(unsigned int irq); -void cpu_eoi_irq(unsigned int irq); +void cpu_ack_irq(struct irq_data *d); +void cpu_eoi_irq(struct irq_data *d); extern int txn_alloc_irq(unsigned int nbits); extern int txn_claim_irq(int); @@ -49,7 +44,7 @@ extern unsigned long txn_alloc_addr(unsigned int); extern unsigned long txn_affinity_addr(unsigned int irq, int cpu); extern int cpu_claim_irq(unsigned int irq, struct irq_chip *, void *); -extern int cpu_check_affinity(unsigned int irq, const struct cpumask *dest); +extern int cpu_check_affinity(struct irq_data *d, const struct cpumask *dest); /* soft power switch support (power.c) */ extern struct tasklet_struct power_tasklet; diff --git a/arch/parisc/include/asm/pgtable.h b/arch/parisc/include/asm/pgtable.h index 6f1f65d3c0e..5d7b8ce9fdf 100644 --- a/arch/parisc/include/asm/pgtable.h +++ b/arch/parisc/include/asm/pgtable.h @@ -138,8 +138,7 @@ struct vm_area_struct; #define _PAGE_NO_CACHE_BIT 24 /* (0x080) Uncached Page (U bit) */ #define _PAGE_ACCESSED_BIT 23 /* (0x100) Software: Page Accessed */ #define _PAGE_PRESENT_BIT 22 /* (0x200) Software: translation valid */ -#define _PAGE_FLUSH_BIT 21 /* (0x400) Software: translation valid */ - /* for cache flushing only */ +/* bit 21 was formerly the FLUSH bit but is now unused */ #define _PAGE_USER_BIT 20 /* (0x800) Software: User accessible page */ /* N.B. The bits are defined in terms of a 32 bit word above, so the */ @@ -173,7 +172,6 @@ struct vm_area_struct; #define _PAGE_NO_CACHE (1 << xlate_pabit(_PAGE_NO_CACHE_BIT)) #define _PAGE_ACCESSED (1 << xlate_pabit(_PAGE_ACCESSED_BIT)) #define _PAGE_PRESENT (1 << xlate_pabit(_PAGE_PRESENT_BIT)) -#define _PAGE_FLUSH (1 << xlate_pabit(_PAGE_FLUSH_BIT)) #define _PAGE_USER (1 << xlate_pabit(_PAGE_USER_BIT)) #define _PAGE_FILE (1 << xlate_pabit(_PAGE_FILE_BIT)) @@ -213,7 +211,6 @@ struct vm_area_struct; #define PAGE_KERNEL_RO __pgprot(_PAGE_KERNEL & ~_PAGE_WRITE) #define PAGE_KERNEL_UNC __pgprot(_PAGE_KERNEL | _PAGE_NO_CACHE) #define PAGE_GATEWAY __pgprot(_PAGE_PRESENT | _PAGE_USER | _PAGE_ACCESSED | _PAGE_GATEWAY| _PAGE_READ) -#define PAGE_FLUSH __pgprot(_PAGE_FLUSH) /* @@ -261,7 +258,7 @@ extern unsigned long *empty_zero_page; #define ZERO_PAGE(vaddr) (virt_to_page(empty_zero_page)) -#define pte_none(x) ((pte_val(x) == 0) || (pte_val(x) & _PAGE_FLUSH)) +#define pte_none(x) (pte_val(x) == 0) #define pte_present(x) (pte_val(x) & _PAGE_PRESENT) #define pte_clear(mm,addr,xp) do { pte_val(*(xp)) = 0; } while (0) @@ -444,13 +441,10 @@ struct mm_struct; static inline pte_t ptep_get_and_clear(struct mm_struct *mm, unsigned long addr, pte_t *ptep) { pte_t old_pte; - pte_t pte; spin_lock(&pa_dbit_lock); - pte = old_pte = *ptep; - pte_val(pte) &= ~_PAGE_PRESENT; - pte_val(pte) |= _PAGE_FLUSH; - set_pte_at(mm,addr,ptep,pte); + old_pte = *ptep; + pte_clear(mm,addr,ptep); spin_unlock(&pa_dbit_lock); return old_pte; diff --git a/arch/parisc/kernel/cache.c b/arch/parisc/kernel/cache.c index d054f3da3ff..3f11331c277 100644 --- a/arch/parisc/kernel/cache.c +++ b/arch/parisc/kernel/cache.c @@ -27,12 +27,17 @@ #include <asm/pgalloc.h> #include <asm/processor.h> #include <asm/sections.h> +#include <asm/shmparam.h> int split_tlb __read_mostly; int dcache_stride __read_mostly; int icache_stride __read_mostly; EXPORT_SYMBOL(dcache_stride); +void flush_dcache_page_asm(unsigned long phys_addr, unsigned long vaddr); +EXPORT_SYMBOL(flush_dcache_page_asm); +void flush_icache_page_asm(unsigned long phys_addr, unsigned long vaddr); + /* On some machines (e.g. ones with the Merced bus), there can be * only a single PxTLB broadcast at a time; this must be guaranteed @@ -259,81 +264,13 @@ void disable_sr_hashing(void) panic("SpaceID hashing is still on!\n"); } -/* Simple function to work out if we have an existing address translation - * for a user space vma. */ -static inline int translation_exists(struct vm_area_struct *vma, - unsigned long addr, unsigned long pfn) -{ - pgd_t *pgd = pgd_offset(vma->vm_mm, addr); - pmd_t *pmd; - pte_t pte; - - if(pgd_none(*pgd)) - return 0; - - pmd = pmd_offset(pgd, addr); - if(pmd_none(*pmd) || pmd_bad(*pmd)) - return 0; - - /* We cannot take the pte lock here: flush_cache_page is usually - * called with pte lock already held. Whereas flush_dcache_page - * takes flush_dcache_mmap_lock, which is lower in the hierarchy: - * the vma itself is secure, but the pte might come or go racily. - */ - pte = *pte_offset_map(pmd, addr); - /* But pte_unmap() does nothing on this architecture */ - - /* Filter out coincidental file entries and swap entries */ - if (!(pte_val(pte) & (_PAGE_FLUSH|_PAGE_PRESENT))) - return 0; - - return pte_pfn(pte) == pfn; -} - -/* Private function to flush a page from the cache of a non-current - * process. cr25 contains the Page Directory of the current user - * process; we're going to hijack both it and the user space %sr3 to - * temporarily make the non-current process current. We have to do - * this because cache flushing may cause a non-access tlb miss which - * the handlers have to fill in from the pgd of the non-current - * process. */ static inline void -flush_user_cache_page_non_current(struct vm_area_struct *vma, - unsigned long vmaddr) +__flush_cache_page(struct vm_area_struct *vma, unsigned long vmaddr, + unsigned long physaddr) { - /* save the current process space and pgd */ - unsigned long space = mfsp(3), pgd = mfctl(25); - - /* we don't mind taking interrupts since they may not - * do anything with user space, but we can't - * be preempted here */ - preempt_disable(); - - /* make us current */ - mtctl(__pa(vma->vm_mm->pgd), 25); - mtsp(vma->vm_mm->context, 3); - - flush_user_dcache_page(vmaddr); - if(vma->vm_flags & VM_EXEC) - flush_user_icache_page(vmaddr); - - /* put the old current process back */ - mtsp(space, 3); - mtctl(pgd, 25); - preempt_enable(); -} - - -static inline void -__flush_cache_page(struct vm_area_struct *vma, unsigned long vmaddr) -{ - if (likely(vma->vm_mm->context == mfsp(3))) { - flush_user_dcache_page(vmaddr); - if (vma->vm_flags & VM_EXEC) - flush_user_icache_page(vmaddr); - } else { - flush_user_cache_page_non_current(vma, vmaddr); - } + flush_dcache_page_asm(physaddr, vmaddr); + if (vma->vm_flags & VM_EXEC) + flush_icache_page_asm(physaddr, vmaddr); } void flush_dcache_page(struct page *page) @@ -342,10 +279,8 @@ void flush_dcache_page(struct page *page) struct vm_area_struct *mpnt; struct prio_tree_iter iter; unsigned long offset; - unsigned long addr; + unsigned long addr, old_addr = 0; pgoff_t pgoff; - unsigned long pfn = page_to_pfn(page); - if (mapping && !mapping_mapped(mapping)) { set_bit(PG_dcache_dirty, &page->flags); @@ -369,20 +304,11 @@ void flush_dcache_page(struct page *page) offset = (pgoff - mpnt->vm_pgoff) << PAGE_SHIFT; addr = mpnt->vm_start + offset; - /* Flush instructions produce non access tlb misses. - * On PA, we nullify these instructions rather than - * taking a page fault if the pte doesn't exist. - * This is just for speed. If the page translation - * isn't there, there's no point exciting the - * nadtlb handler into a nullification frenzy. - * - * Make sure we really have this page: the private - * mappings may cover this area but have COW'd this - * particular page. - */ - if (translation_exists(mpnt, addr, pfn)) { - __flush_cache_page(mpnt, addr); - break; + if (old_addr == 0 || (old_addr & (SHMLBA - 1)) != (addr & (SHMLBA - 1))) { + __flush_cache_page(mpnt, addr, page_to_phys(page)); + if (old_addr) + printk(KERN_ERR "INEQUIVALENT ALIASES 0x%lx and 0x%lx in file %s\n", old_addr, addr, mpnt->vm_file ? mpnt->vm_file->f_path.dentry->d_name.name : "(null)"); + old_addr = addr; } } flush_dcache_mmap_unlock(mapping); @@ -573,7 +499,6 @@ flush_cache_page(struct vm_area_struct *vma, unsigned long vmaddr, unsigned long { BUG_ON(!vma->vm_mm->context); - if (likely(translation_exists(vma, vmaddr, pfn))) - __flush_cache_page(vma, vmaddr); + __flush_cache_page(vma, vmaddr, page_to_phys(pfn_to_page(pfn))); } diff --git a/arch/parisc/kernel/entry.S b/arch/parisc/kernel/entry.S index 6337adef30f..e5477092a5d 100644 --- a/arch/parisc/kernel/entry.S +++ b/arch/parisc/kernel/entry.S @@ -225,22 +225,13 @@ #ifndef CONFIG_64BIT /* * naitlb miss interruption handler (parisc 1.1 - 32 bit) - * - * Note: naitlb misses will be treated - * as an ordinary itlb miss for now. - * However, note that naitlb misses - * have the faulting address in the - * IOR/ISR. */ .macro naitlb_11 code mfctl %isr,spc - b itlb_miss_11 + b naitlb_miss_11 mfctl %ior,va - /* FIXME: If user causes a naitlb miss, the priv level may not be in - * lower bits of va, where the itlb miss handler is expecting them - */ .align 32 .endm @@ -248,26 +239,17 @@ /* * naitlb miss interruption handler (parisc 2.0) - * - * Note: naitlb misses will be treated - * as an ordinary itlb miss for now. - * However, note that naitlb misses - * have the faulting address in the - * IOR/ISR. */ .macro naitlb_20 code mfctl %isr,spc #ifdef CONFIG_64BIT - b itlb_miss_20w + b naitlb_miss_20w #else - b itlb_miss_20 + b naitlb_miss_20 #endif mfctl %ior,va - /* FIXME: If user causes a naitlb miss, the priv level may not be in - * lower bits of va, where the itlb miss handler is expecting them - */ .align 32 .endm @@ -581,7 +563,24 @@ copy \va,\tmp1 depi 0,31,23,\tmp1 cmpb,COND(<>),n \tmp,\tmp1,\fault - ldi (_PAGE_DIRTY|_PAGE_WRITE|_PAGE_READ),\prot + mfctl %cr19,\tmp /* iir */ + /* get the opcode (first six bits) into \tmp */ + extrw,u \tmp,5,6,\tmp + /* + * Only setting the T bit prevents data cache movein + * Setting access rights to zero prevents instruction cache movein + * + * Note subtlety here: _PAGE_GATEWAY, _PAGE_EXEC and _PAGE_WRITE go + * to type field and _PAGE_READ goes to top bit of PL1 + */ + ldi (_PAGE_REFTRAP|_PAGE_READ|_PAGE_WRITE),\prot + /* + * so if the opcode is one (i.e. this is a memory management + * instruction) nullify the next load so \prot is only T. + * Otherwise this is a normal data operation + */ + cmpiclr,= 0x01,\tmp,%r0 + ldi (_PAGE_DIRTY|_PAGE_READ|_PAGE_WRITE),\prot depd,z \prot,8,7,\prot /* * OK, it is in the temp alias region, check whether "from" or "to". @@ -631,11 +630,7 @@ ENTRY(fault_vector_20) def 13 def 14 dtlb_20 15 -#if 0 naitlb_20 16 -#else - def 16 -#endif nadtlb_20 17 def 18 def 19 @@ -678,11 +673,7 @@ ENTRY(fault_vector_11) def 13 def 14 dtlb_11 15 -#if 0 naitlb_11 16 |