diff options
Diffstat (limited to 'arch/parisc/kernel')
-rw-r--r-- | arch/parisc/kernel/cache.c | 5 | ||||
-rw-r--r-- | arch/parisc/kernel/firmware.c | 62 | ||||
-rw-r--r-- | arch/parisc/kernel/irq.c | 2 | ||||
-rw-r--r-- | arch/parisc/kernel/pci-dma.c | 3 | ||||
-rw-r--r-- | arch/parisc/kernel/pdt.c | 280 | ||||
-rw-r--r-- | arch/parisc/kernel/perf.c | 4 | ||||
-rw-r--r-- | arch/parisc/kernel/processor.c | 30 | ||||
-rw-r--r-- | arch/parisc/kernel/real2.S | 4 | ||||
-rw-r--r-- | arch/parisc/kernel/signal32.c | 31 | ||||
-rw-r--r-- | arch/parisc/kernel/unwind.c | 4 |
10 files changed, 341 insertions, 84 deletions
diff --git a/arch/parisc/kernel/cache.c b/arch/parisc/kernel/cache.c index 85a92db70afc..19c0c141bc3f 100644 --- a/arch/parisc/kernel/cache.c +++ b/arch/parisc/kernel/cache.c @@ -587,13 +587,12 @@ void flush_cache_range(struct vm_area_struct *vma, if (parisc_requires_coherency()) flush_tlb_range(vma, start, end); - if ((end - start) >= parisc_cache_flush_threshold) { + if ((end - start) >= parisc_cache_flush_threshold + || vma->vm_mm->context != mfsp(3)) { flush_cache_all(); return; } - BUG_ON(vma->vm_mm->context != mfsp(3)); - flush_user_dcache_range_asm(start, end); if (vma->vm_flags & VM_EXEC) flush_user_icache_range_asm(start, end); diff --git a/arch/parisc/kernel/firmware.c b/arch/parisc/kernel/firmware.c index f622a311d04a..ab80e5c6f651 100644 --- a/arch/parisc/kernel/firmware.c +++ b/arch/parisc/kernel/firmware.c @@ -69,7 +69,15 @@ #include <asm/pdcpat.h> #include <asm/processor.h> /* for boot_cpu_data */ +#if defined(BOOTLOADER) +# undef spin_lock_irqsave +# define spin_lock_irqsave(a, b) { b = 1; } +# undef spin_unlock_irqrestore +# define spin_unlock_irqrestore(a, b) +#else static DEFINE_SPINLOCK(pdc_lock); +#endif + extern unsigned long pdc_result[NUM_PDC_RESULT]; extern unsigned long pdc_result2[NUM_PDC_RESULT]; @@ -142,8 +150,8 @@ static void convert_to_wide(unsigned long *addr) int i; unsigned int *p = (unsigned int *)addr; - if(unlikely(parisc_narrow_firmware)) { - for(i = 31; i >= 0; --i) + if (unlikely(parisc_narrow_firmware)) { + for (i = (NUM_PDC_RESULT-1); i >= 0; --i) addr[i] = p[i]; } #endif @@ -186,6 +194,8 @@ void set_firmware_width(void) } #endif /*CONFIG_64BIT*/ + +#if !defined(BOOTLOADER) /** * pdc_emergency_unlock - Unlock the linux pdc lock * @@ -979,16 +989,22 @@ int pdc_mem_pdt_read_entries(struct pdc_mem_read_pdt *pret, spin_lock_irqsave(&pdc_lock, flags); retval = mem_pdc_call(PDC_MEM, PDC_MEM_READ_PDT, __pa(pdc_result), - __pa(pdc_result2)); + __pa(pdt_entries_ptr)); if (retval == PDC_OK) { convert_to_wide(pdc_result); memcpy(pret, pdc_result, sizeof(*pret)); - convert_to_wide(pdc_result2); - memcpy(pdt_entries_ptr, pdc_result2, - pret->pdt_entries * sizeof(*pdt_entries_ptr)); } spin_unlock_irqrestore(&pdc_lock, flags); +#ifdef CONFIG_64BIT + /* + * 64-bit kernels should not call this PDT function in narrow mode. + * The pdt_entries_ptr array above will now contain 32-bit values + */ + if (WARN_ON_ONCE((retval == PDC_OK) && parisc_narrow_firmware)) + return PDC_ERROR; +#endif + return retval; } @@ -1143,6 +1159,8 @@ void pdc_io_reset_devices(void) spin_unlock_irqrestore(&pdc_lock, flags); } +#endif /* defined(BOOTLOADER) */ + /* locked by pdc_console_lock */ static int __attribute__((aligned(8))) iodc_retbuf[32]; static char __attribute__((aligned(64))) iodc_dbuf[4096]; @@ -1187,6 +1205,7 @@ print: return i; } +#if !defined(BOOTLOADER) /** * pdc_iodc_getc - Read a character (non-blocking) from the PDC console. * @@ -1440,6 +1459,29 @@ int pdc_pat_mem_pdt_info(struct pdc_pat_mem_retinfo *rinfo) } /** + * pdc_pat_mem_pdt_cell_info - Retrieve information about page deallocation + * table of a cell + * @rinfo: memory pdt information + * @cell: cell number + * + */ +int pdc_pat_mem_pdt_cell_info(struct pdc_pat_mem_cell_pdt_retinfo *rinfo, + unsigned long cell) +{ + int retval; + unsigned long flags; + + spin_lock_irqsave(&pdc_lock, flags); + retval = mem_pdc_call(PDC_PAT_MEM, PDC_PAT_MEM_CELL_INFO, + __pa(&pdc_result), cell); + if (retval == PDC_OK) + memcpy(rinfo, &pdc_result, sizeof(*rinfo)); + spin_unlock_irqrestore(&pdc_lock, flags); + + return retval; +} + +/** * pdc_pat_mem_read_cell_pdt - Read PDT entries from (old) PAT firmware * @pret: array of PDT entries * @pdt_entries_ptr: ptr to hold number of PDT entries @@ -1455,14 +1497,14 @@ int pdc_pat_mem_read_cell_pdt(struct pdc_pat_mem_read_pd_retinfo *pret, spin_lock_irqsave(&pdc_lock, flags); /* PDC_PAT_MEM_CELL_READ is available on early PAT machines only */ retval = mem_pdc_call(PDC_PAT_MEM, PDC_PAT_MEM_CELL_READ, - __pa(&pdc_result), parisc_cell_num, __pa(&pdc_result2)); + __pa(&pdc_result), parisc_cell_num, + __pa(pdt_entries_ptr)); if (retval == PDC_OK) { /* build up return value as for PDC_PAT_MEM_PD_READ */ entries = min(pdc_result[0], max_entries); pret->pdt_entries = entries; pret->actual_count_bytes = entries * sizeof(unsigned long); - memcpy(pdt_entries_ptr, &pdc_result2, pret->actual_count_bytes); } spin_unlock_irqrestore(&pdc_lock, flags); @@ -1474,6 +1516,8 @@ int pdc_pat_mem_read_cell_pdt(struct pdc_pat_mem_read_pd_retinfo *pret, * pdc_pat_mem_read_pd_pdt - Read PDT entries from (newer) PAT firmware * @pret: array of PDT entries * @pdt_entries_ptr: ptr to hold number of PDT entries + * @count: number of bytes to read + * @offset: offset to start (in bytes) * */ int pdc_pat_mem_read_pd_pdt(struct pdc_pat_mem_read_pd_retinfo *pret, @@ -1524,6 +1568,7 @@ int pdc_pat_mem_get_dimm_phys_location( return retval; } #endif /* CONFIG_64BIT */ +#endif /* defined(BOOTLOADER) */ /***************** 32-bit real-mode calls ***********/ @@ -1633,4 +1678,3 @@ long real64_call(unsigned long fn, ...) } #endif /* CONFIG_64BIT */ - diff --git a/arch/parisc/kernel/irq.c b/arch/parisc/kernel/irq.c index 5404e4086cb9..0ca254085a66 100644 --- a/arch/parisc/kernel/irq.c +++ b/arch/parisc/kernel/irq.c @@ -380,7 +380,7 @@ static inline int eirr_to_irq(unsigned long eirr) /* * IRQ STACK - used for irq handler */ -#define IRQ_STACK_SIZE (4096 << 2) /* 16k irq stack size */ +#define IRQ_STACK_SIZE (4096 << 3) /* 32k irq stack size */ union irq_stack_union { unsigned long stack[IRQ_STACK_SIZE/sizeof(unsigned long)]; diff --git a/arch/parisc/kernel/pci-dma.c b/arch/parisc/kernel/pci-dma.c index 5f0067a62738..bd4c0a7471d3 100644 --- a/arch/parisc/kernel/pci-dma.c +++ b/arch/parisc/kernel/pci-dma.c @@ -41,7 +41,7 @@ static unsigned long pcxl_used_bytes __read_mostly = 0; static unsigned long pcxl_used_pages __read_mostly = 0; extern unsigned long pcxl_dma_start; /* Start of pcxl dma mapping area */ -static spinlock_t pcxl_res_lock; +static DEFINE_SPINLOCK(pcxl_res_lock); static char *pcxl_res_map; static int pcxl_res_hint; static int pcxl_res_size; @@ -390,7 +390,6 @@ pcxl_dma_init(void) if (pcxl_dma_start == 0) return 0; - spin_lock_init(&pcxl_res_lock); pcxl_res_size = PCXL_DMA_MAP_SIZE >> (PAGE_SHIFT + 3); pcxl_res_hint = 0; pcxl_res_map = (char *)__get_free_pages(GFP_KERNEL, diff --git a/arch/parisc/kernel/pdt.c b/arch/parisc/kernel/pdt.c index d02874ecb94d..05730a83895c 100644 --- a/arch/parisc/kernel/pdt.c +++ b/arch/parisc/kernel/pdt.c @@ -1,19 +1,20 @@ /* * Page Deallocation Table (PDT) support * - * The Page Deallocation Table (PDT) holds a table with pointers to bad - * memory (broken RAM modules) which is maintained by firmware. + * The Page Deallocation Table (PDT) is maintained by firmware and holds a + * list of memory addresses in which memory errors were detected. + * The list contains both single-bit (correctable) and double-bit + * (uncorrectable) errors. * * Copyright 2017 by Helge Deller <deller@gmx.de> * - * TODO: - * - check regularily for new bad memory - * - add userspace interface with procfs or sysfs - * - increase number of PDT entries dynamically + * possible future enhancements: + * - add userspace interface via procfs or sysfs to clear PDT */ #include <linux/memblock.h> #include <linux/seq_file.h> +#include <linux/kthread.h> #include <asm/pdc.h> #include <asm/pdcpat.h> @@ -24,11 +25,16 @@ enum pdt_access_type { PDT_NONE, PDT_PDC, PDT_PAT_NEW, - PDT_PAT_OLD + PDT_PAT_CELL }; static enum pdt_access_type pdt_type; +/* PDT poll interval: 1 minute if errors, 5 minutes if everything OK. */ +#define PDT_POLL_INTERVAL_DEFAULT (5*60*HZ) +#define PDT_POLL_INTERVAL_SHORT (1*60*HZ) +static unsigned long pdt_poll_interval = PDT_POLL_INTERVAL_DEFAULT; + /* global PDT status information */ static struct pdc_mem_retinfo pdt_status; @@ -36,6 +42,21 @@ static struct pdc_mem_retinfo pdt_status; #define MAX_PDT_ENTRIES (MAX_PDT_TABLE_SIZE / sizeof(unsigned long)) static unsigned long pdt_entry[MAX_PDT_ENTRIES] __page_aligned_bss; +/* + * Constants for the pdt_entry format: + * A pdt_entry holds the physical address in bits 0-57, bits 58-61 are + * reserved, bit 62 is the perm bit and bit 63 is the error_type bit. + * The perm bit indicates whether the error have been verified as a permanent + * error (value of 1) or has not been verified, and may be transient (value + * of 0). The error_type bit indicates whether the error is a single bit error + * (value of 1) or a multiple bit error. + * On non-PAT machines phys_addr is encoded in bits 0-59 and error_type in bit + * 63. Those machines don't provide the perm bit. + */ + +#define PDT_ADDR_PHYS_MASK (pdt_type != PDT_PDC ? ~0x3f : ~0x0f) +#define PDT_ADDR_PERM_ERR (pdt_type != PDT_PDC ? 2UL : 0UL) +#define PDT_ADDR_SINGLE_ERR 1UL /* report PDT entries via /proc/meminfo */ void arch_report_meminfo(struct seq_file *m) @@ -49,6 +70,68 @@ void arch_report_meminfo(struct seq_file *m) pdt_status.pdt_entries); } +static int get_info_pat_new(void) +{ + struct pdc_pat_mem_retinfo pat_rinfo; + int ret; + + /* newer PAT machines like C8000 report info for all cells */ + if (is_pdc_pat()) + ret = pdc_pat_mem_pdt_info(&pat_rinfo); + else + return PDC_BAD_PROC; + + pdt_status.pdt_size = pat_rinfo.max_pdt_entries; + pdt_status.pdt_entries = pat_rinfo.current_pdt_entries; + pdt_status.pdt_status = 0; + pdt_status.first_dbe_loc = pat_rinfo.first_dbe_loc; + pdt_status.good_mem = pat_rinfo.good_mem; + + return ret; +} + +static int get_info_pat_cell(void) +{ + struct pdc_pat_mem_cell_pdt_retinfo cell_rinfo; + int ret; + + /* older PAT machines like rp5470 report cell info only */ + if (is_pdc_pat()) + ret = pdc_pat_mem_pdt_cell_info(&cell_rinfo, parisc_cell_num); + else + return PDC_BAD_PROC; + + pdt_status.pdt_size = cell_rinfo.max_pdt_entries; + pdt_status.pdt_entries = cell_rinfo.current_pdt_entries; + pdt_status.pdt_status = 0; + pdt_status.first_dbe_loc = cell_rinfo.first_dbe_loc; + pdt_status.good_mem = cell_rinfo.good_mem; + + return ret; +} + +static void report_mem_err(unsigned long pde) +{ + struct pdc_pat_mem_phys_mem_location loc; + unsigned long addr; + char dimm_txt[32]; + + addr = pde & PDT_ADDR_PHYS_MASK; + + /* show DIMM slot description on PAT machines */ + if (is_pdc_pat()) { + pdc_pat_mem_get_dimm_phys_location(&loc, addr); + sprintf(dimm_txt, "DIMM slot %02x, ", loc.dimm_slot); + } else + dimm_txt[0] = 0; + + pr_warn("PDT: BAD MEMORY at 0x%08lx, %s%s%s-bit error.\n", + addr, dimm_txt, + pde & PDT_ADDR_PERM_ERR ? "permanent ":"", + pde & PDT_ADDR_SINGLE_ERR ? "single":"multi"); +} + + /* * pdc_pdt_init() * @@ -63,18 +146,17 @@ void __init pdc_pdt_init(void) unsigned long entries; struct pdc_mem_read_pdt pdt_read_ret; - if (is_pdc_pat()) { - struct pdc_pat_mem_retinfo pat_rinfo; + pdt_type = PDT_PAT_NEW; + ret = get_info_pat_new(); - pdt_type = PDT_PAT_NEW; - ret = pdc_pat_mem_pdt_info(&pat_rinfo); - pdt_status.pdt_size = pat_rinfo.max_pdt_entries; - pdt_status.pdt_entries = pat_rinfo.current_pdt_entries; - pdt_status.pdt_status = 0; - pdt_status.first_dbe_loc = pat_rinfo.first_dbe_loc; - pdt_status.good_mem = pat_rinfo.good_mem; - } else { + if (ret != PDC_OK) { + pdt_type = PDT_PAT_CELL; + ret = get_info_pat_cell(); + } + + if (ret != PDC_OK) { pdt_type = PDT_PDC; + /* non-PAT machines provide the standard PDC call */ ret = pdc_mem_pdt_info(&pdt_status); } @@ -86,13 +168,17 @@ void __init pdc_pdt_init(void) } entries = pdt_status.pdt_entries; - WARN_ON(entries > MAX_PDT_ENTRIES); + if (WARN_ON(entries > MAX_PDT_ENTRIES)) + entries = pdt_status.pdt_entries = MAX_PDT_ENTRIES; - pr_info("PDT: size %lu, entries %lu, status %lu, dbe_loc 0x%lx," - " good_mem %lu\n", + pr_info("PDT: type %s, size %lu, entries %lu, status %lu, dbe_loc 0x%lx," + " good_mem %lu MB\n", + pdt_type == PDT_PDC ? __stringify(PDT_PDC) : + pdt_type == PDT_PAT_CELL ? __stringify(PDT_PAT_CELL) + : __stringify(PDT_PAT_NEW), pdt_status.pdt_size, pdt_status.pdt_entries, pdt_status.pdt_status, pdt_status.first_dbe_loc, - pdt_status.good_mem); + pdt_status.good_mem / 1024 / 1024); if (entries == 0) { pr_info("PDT: Firmware reports all memory OK.\n"); @@ -112,15 +198,12 @@ void __init pdc_pdt_init(void) #ifdef CONFIG_64BIT struct pdc_pat_mem_read_pd_retinfo pat_pret; - /* try old obsolete PAT firmware function first */ - pdt_type = PDT_PAT_OLD; - ret = pdc_pat_mem_read_cell_pdt(&pat_pret, pdt_entry, - MAX_PDT_ENTRIES); - if (ret != PDC_OK) { - pdt_type = PDT_PAT_NEW; + if (pdt_type == PDT_PAT_CELL) + ret = pdc_pat_mem_read_cell_pdt(&pat_pret, pdt_entry, + MAX_PDT_ENTRIES); + else ret = pdc_pat_mem_read_pd_pdt(&pat_pret, pdt_entry, MAX_PDT_TABLE_SIZE, 0); - } #else ret = PDC_BAD_PROC; #endif @@ -128,27 +211,142 @@ void __init pdc_pdt_init(void) if (ret != PDC_OK) { pdt_type = PDT_NONE; - pr_debug("PDT type %d, retval = %d\n", pdt_type, ret); + pr_warn("PDT: Get PDT entries failed with %d\n", ret); return; } for (i = 0; i < pdt_status.pdt_entries; i++) { - struct pdc_pat_mem_phys_mem_location loc; + report_mem_err(pdt_entry[i]); + + /* mark memory page bad */ + memblock_reserve(pdt_entry[i] & PAGE_MASK, PAGE_SIZE); + } +} - /* get DIMM slot number */ - loc.dimm_slot = 0xff; + +/* + * This is the PDT kernel thread main loop. + */ + +static int pdt_mainloop(void *unused) +{ + struct pdc_mem_read_pdt pdt_read_ret; + struct pdc_pat_mem_read_pd_retinfo pat_pret __maybe_unused; + unsigned long old_num_entries; + unsigned long *bad_mem_ptr; + int num, ret; + + for (;;) { + set_current_state(TASK_INTERRUPTIBLE); + + old_num_entries = pdt_status.pdt_entries; + + schedule_timeout(pdt_poll_interval); + if (kthread_should_stop()) + break; + + /* Do we have new PDT entries? */ + switch (pdt_type) { + case PDT_PAT_NEW: + ret = get_info_pat_new(); + break; + case PDT_PAT_CELL: + ret = get_info_pat_cell(); + break; + default: + ret = pdc_mem_pdt_info(&pdt_status); + break; + } + + if (ret != PDC_OK) { + pr_warn("PDT: unexpected failure %d\n", ret); + return -EINVAL; + } + + /* if no new PDT entries, just wait again */ + num = pdt_status.pdt_entries - old_num_entries; + if (num <= 0) + continue; + + /* decrease poll interval in case we found memory errors */ + if (pdt_status.pdt_entries && + pdt_poll_interval == PDT_POLL_INTERVAL_DEFAULT) + pdt_poll_interval = PDT_POLL_INTERVAL_SHORT; + + /* limit entries to get */ + if (num > MAX_PDT_ENTRIES) { + num = MAX_PDT_ENTRIES; + pdt_status.pdt_entries = old_num_entries + num; + } + + /* get new entries */ + switch (pdt_type) { #ifdef CONFIG_64BIT - pdc_pat_mem_get_dimm_phys_location(&loc, pdt_entry[i]); + case PDT_PAT_CELL: + if (pdt_status.pdt_entries > MAX_PDT_ENTRIES) { + pr_crit("PDT: too many entries.\n"); + return -ENOMEM; + } + ret = pdc_pat_mem_read_cell_pdt(&pat_pret, pdt_entry, + MAX_PDT_ENTRIES); + bad_mem_ptr = &pdt_entry[old_num_entries]; + break; + case PDT_PAT_NEW: + ret = pdc_pat_mem_read_pd_pdt(&pat_pret, + pdt_entry, + num * sizeof(unsigned long), + old_num_entries * sizeof(unsigned long)); + bad_mem_ptr = &pdt_entry[0]; + break; #endif + default: + ret = pdc_mem_pdt_read_entries(&pdt_read_ret, + pdt_entry); + bad_mem_ptr = &pdt_entry[old_num_entries]; + break; + } - pr_warn("PDT: BAD PAGE #%d at 0x%08lx, " - "DIMM slot %02x (error_type = %lu)\n", - i, - pdt_entry[i] & PAGE_MASK, - loc.dimm_slot, - pdt_entry[i] & 1); + /* report and mark memory broken */ + while (num--) { + unsigned long pde = *bad_mem_ptr++; - /* mark memory page bad */ - memblock_reserve(pdt_entry[i] & PAGE_MASK, PAGE_SIZE); + report_mem_err(pde); + +#ifdef CONFIG_MEMORY_FAILURE + if ((pde & PDT_ADDR_PERM_ERR) || + ((pde & PDT_ADDR_SINGLE_ERR) == 0)) + memory_failure(pde >> PAGE_SHIFT, 0, 0); + else + soft_offline_page( + pfn_to_page(pde >> PAGE_SHIFT), 0); +#else + pr_crit("PDT: memory error at 0x%lx ignored.\n" + "Rebuild kernel with CONFIG_MEMORY_FAILURE=y " + "for real handling.\n", + pde & PDT_ADDR_PHYS_MASK); +#endif + + } } + + return 0; } + + +static int __init pdt_initcall(void) +{ + struct task_struct *kpdtd_task; + + if (pdt_type == PDT_NONE) + return -ENODEV; + + kpdtd_task = kthread_create(pdt_mainloop, NULL, "kpdtd"); + if (IS_ERR(kpdtd_task)) + return PTR_ERR(kpdtd_task); + + wake_up_process(kpdtd_task); + + return 0; +} + +late_initcall(pdt_initcall); diff --git a/arch/parisc/kernel/perf.c b/arch/parisc/kernel/perf.c index 6017a5af2e6e..0813359049ae 100644 --- a/arch/parisc/kernel/perf.c +++ b/arch/parisc/kernel/perf.c @@ -69,7 +69,7 @@ struct rdr_tbl_ent { static int perf_processor_interface __read_mostly = UNKNOWN_INTF; static int perf_enabled __read_mostly; -static spinlock_t perf_lock; +static DEFINE_SPINLOCK(perf_lock); struct parisc_device *cpu_device __read_mostly; /* RDRs to write for PCX-W */ @@ -533,8 +533,6 @@ static int __init perf_init(void) /* Patch the images to match the system */ perf_patch_images(); - spin_lock_init(&perf_lock); - /* TODO: this only lets us access the first cpu.. what to do for SMP? */ cpu_device = per_cpu(cpu_data, 0).dev; printk("Performance monitoring counters enabled for %s\n", diff --git a/arch/parisc/kernel/processor.c b/arch/parisc/kernel/processor.c index 0ab32779dfa7..a778bd3c107c 100644 --- a/arch/parisc/kernel/processor.c +++ b/arch/parisc/kernel/processor.c @@ -30,6 +30,7 @@ #include <linux/mm.h> #include <linux/module.h> #include <linux/seq_file.h> +#include <linux/random.h> #include <linux/slab.h> #include <linux/cpu.h> #include <asm/param.h> @@ -89,7 +90,7 @@ init_percpu_prof(unsigned long cpunum) * (return 1). If so, initialize the chip and tell other partners in crime * they have work to do. */ -static int processor_probe(struct parisc_device *dev) +static int __init processor_probe(struct parisc_device *dev) { unsigned long txn_addr; unsigned long cpuid; @@ -237,28 +238,45 @@ static int processor_probe(struct parisc_device *dev) */ void __init collect_boot_cpu_data(void) { + unsigned long cr16_seed; + memset(&boot_cpu_data, 0, sizeof(boot_cpu_data)); + cr16_seed = get_cycles(); + add_device_randomness(&cr16_seed, sizeof(cr16_seed)); + boot_cpu_data.cpu_hz = 100 * PAGE0->mem_10msec; /* Hz of this PARISC */ /* get CPU-Model Information... */ #define p ((unsigned long *)&boot_cpu_data.pdc.model) - if (pdc_model_info(&boot_cpu_data.pdc.model) == PDC_OK) + if (pdc_model_info(&boot_cpu_data.pdc.model) == PDC_OK) { printk(KERN_INFO "model %08lx %08lx %08lx %08lx %08lx %08lx %08lx %08lx %08lx\n", p[0], p[1], p[2], p[3], p[4], p[5], p[6], p[7], p[8]); + + add_device_randomness(&boot_cpu_data.pdc.model, + sizeof(boot_cpu_data.pdc.model)); + } #undef p - if (pdc_model_versions(&boot_cpu_data.pdc.versions, 0) == PDC_OK) + if (pdc_model_versions(&boot_cpu_data.pdc.versions, 0) == PDC_OK) { printk(KERN_INFO "vers %08lx\n", boot_cpu_data.pdc.versions); - if (pdc_model_cpuid(&boot_cpu_data.pdc.cpuid) == PDC_OK) + add_device_randomness(&boot_cpu_data.pdc.versions, + sizeof(boot_cpu_data.pdc.versions)); + } + + if (pdc_model_cpuid(&boot_cpu_data.pdc.cpuid) == PDC_OK) { printk(KERN_INFO "CPUID vers %ld rev %ld (0x%08lx)\n", (boot_cpu_data.pdc.cpuid >> 5) & 127, boot_cpu_data.pdc.cpuid & 31, boot_cpu_data.pdc.cpuid); + add_device_randomness(&boot_cpu_data.pdc.cpuid, + sizeof(boot_cpu_data.pdc.cpuid)); + } + if (pdc_model_capabilities(&boot_cpu_data.pdc.capabilities) == PDC_OK) printk(KERN_INFO "capabilities 0x%lx\n", boot_cpu_data.pdc.capabilities); @@ -414,12 +432,12 @@ show_cpuinfo (struct seq_file *m, void *v) return 0; } -static const struct parisc_device_id processor_tbl[] = { +static const struct parisc_device_id processor_tbl[] __initconst = { { HPHW_NPROC, HVERSION_REV_ANY_ID, HVERSION_ANY_ID, SVERSION_ANY_ID }, { 0, } }; -static struct parisc_driver cpu_driver = { +static struct parisc_driver cpu_driver __refdata = { .name = "CPU", .id_table = processor_tbl, .probe = processor_probe diff --git a/arch/parisc/kernel/real2.S b/arch/parisc/kernel/real2.S index 1db58e546230..cc9963421a19 100644 --- a/arch/parisc/kernel/real2.S +++ b/arch/parisc/kernel/real2.S @@ -162,6 +162,7 @@ ENDPROC_CFI(restore_control_regs) .text .align 128 ENTRY_CFI(rfi_virt2real) +#if !defined(BOOTLOADER) /* switch to real mode... */ rsm PSW_SM_I,%r0 load32 PA(rfi_v2r_1), %r1 @@ -191,6 +192,7 @@ ENTRY_CFI(rfi_virt2real) nop rfi_v2r_1: tophys_r1 %r2 +#endif /* defined(BOOTLOADER) */ bv 0(%r2) nop ENDPROC_CFI(rfi_virt2real) @@ -198,6 +200,7 @@ ENDPROC_CFI(rfi_virt2real) .text .align 128 ENTRY_CFI(rfi_real2virt) +#if !defined(BOOTLOADER) rsm PSW_SM_I,%r0 load32 (rfi_r2v_1), %r1 nop @@ -226,6 +229,7 @@ ENTRY_CFI(rfi_real2virt) nop rfi_r2v_1: tovirt_r1 %r2 +#endif /* defined(BOOTLOADER) */ bv 0(%r2) nop ENDPROC_CFI(rfi_real2virt) diff --git a/arch/parisc/kernel/signal32.c b/arch/parisc/kernel/signal32.c index 70aaabb8b3cb..9e0cb6a577d6 100644 --- a/arch/parisc/kernel/signal32.c +++ b/arch/parisc/kernel/signal32.c @@ -290,25 +290,25 @@ copy_siginfo_from_user32 (siginfo_t *to, compat_siginfo_t __user *from) if (to->si_code < 0) err |= __copy_from_user(&to->_sifields._pad, &from->_sifields._pad, SI_PAD_SIZE); else { - switch (to->si_code >> 16) { - case __SI_CHLD >> 16: + switch (siginfo_layout(to->si_signo, to->si_code)) { + case SIL_CHLD: err |= __get_user(to->si_utime, &from->si_utime); err |= __get_user(to->si_stime, &from->si_stime); err |= __get_user(to->si_status, &from->si_status); default: + case SIL_KILL: err |= __get_user(to->si_pid, &from->si_pid); err |= __get_user(to->si_uid, &from->si_uid); break; - case __SI_FAULT >> 16: + case SIL_FAULT: err |= __get_user(addr, &from->si_addr); to->si_addr = compat_ptr(addr); break; - case __SI_POLL >> 16: + case SIL_POLL: err |= __get_user(to->si_band, &from->si_band); err |= __get_user(to->si_fd, &from->si_fd); break; - case __SI_RT >> 16: /* This is not generated by the kernel as of now. */ - case __SI_MESGQ >> 16: + case SIL_RT: err |= __get_user(to->si_pid, &from->si_pid); err |= __get_user(to->si_uid, &from->si_uid); err |= __get_user(to->si_int, &from->si_int); @@ -337,41 +337,40 @@ copy_siginfo_to_user32 (compat_siginfo_t __user *to, const siginfo_t *from) at the same time. */ err = __put_user(from->si_signo, &to->si_signo); err |= __put_user(from->si_errno, &to->si_errno); - err |= __put_user((short)from->si_code, &to->si_code); + err |= __put_user(from->si_code, &to->si_code); if (from->si_code < 0) err |= __copy_to_user(&to->_sifields._pad, &from->_sifields._pad, SI_PAD_SIZE); else { - switch (from->si_code >> 16) { - case __SI_CHLD >> 16: + switch (siginfo_layout(from->si_signo, from->si_code)) { + case SIL_CHLD: err |= __put_user(from->si_utime, &to->si_utime); err |= __put_user(from->si_stime, &to->si_stime); err |= __put_user(from->si_status, &to->si_status); - default: + case SIL_KILL: err |= __put_user(from->si_pid, &to->si_pid); err |= __put_user(from->si_uid, &to->si_uid); break; - case __SI_FAULT >> 16: + case SIL_FAULT: addr = ptr_to_compat(from->si_addr); err |= __put_user(addr, &to->si_addr); break; - case __SI_POLL >> 16: + case SIL_POLL: err |= __put_user(from->si_band, &to->si_band); err |= __put_user(from->si_fd, &to->si_fd); break; - case __SI_TIMER >> 16: + case SIL_TIMER: err |= __put_user(from->si_tid, &to->si_tid); err |= __put_user(from->si_overrun, &to->si_overrun); val = (compat_int_t)from->si_int; err |= __put_user(val, &to->si_int); break; - case __SI_RT >> 16: /* Not generated by the kernel as of now. */ - case __SI_MESGQ >> 16: + case SIL_RT: err |= __put_user(from->si_uid, &to->si_uid); err |= __put_user(from->si_pid, &to->si_pid); val = (compat_int_t)from->si_int; err |= __put_user(val, &to->si_int); break; - case __SI_SYS >> 16: + case SIL_SYS: err |= __put_user(ptr_to_compat(from->si_call_addr), &to->si_call_addr); err |= __put_user(from->si_syscall, &to->si_syscall); err |= __put_user(from->si_arch, &to->si_arch); diff --git a/arch/parisc/kernel/unwind.c b/arch/parisc/kernel/unwind.c index 1b73690477c5..48dc7d4d20bb 100644 --- a/arch/parisc/kernel/unwind.c +++ b/arch/parisc/kernel/unwind.c @@ -34,7 +34,7 @@ extern struct unwind_table_entry __start___unwind[]; extern struct unwind_table_entry __stop___unwind[]; -static spinlock_t unwind_lock; +static DEFINE_SPINLOCK(unwind_lock); /* * the kernel unwind block is not dynamically allocated so that * we can call unwind_init as early in the bootup process as @@ -181,8 +181,6 @@ int __init unwind_init(void) start = (long)&__start___unwind[0]; stop = (long)&__stop___unwind[0]; - spin_lock_init(&unwind_lock); - printk("unwind_init: start = 0x%lx, end = 0x%lx, entries = %lu\n", start, stop, (stop - start) / sizeof(struct unwind_table_entry)); |