summaryrefslogtreecommitdiffstats
path: root/arch/parisc
diff options
context:
space:
mode:
Diffstat (limited to 'arch/parisc')
-rw-r--r--arch/parisc/Kconfig6
-rw-r--r--arch/parisc/include/asm/cacheflush.h1
-rw-r--r--arch/parisc/include/asm/io.h12
-rw-r--r--arch/parisc/include/asm/processor.h2
-rw-r--r--arch/parisc/include/uapi/asm/mman.h2
-rw-r--r--arch/parisc/kernel/cache.c93
-rw-r--r--arch/parisc/kernel/drivers.c197
-rw-r--r--arch/parisc/kernel/hardware.c12
-rw-r--r--arch/parisc/kernel/head.S18
-rw-r--r--arch/parisc/kernel/hpmc.S6
-rw-r--r--arch/parisc/kernel/pacache.S22
-rw-r--r--arch/parisc/kernel/process.c6
-rw-r--r--arch/parisc/kernel/smp.c7
-rw-r--r--arch/parisc/kernel/sys_parisc.c30
-rw-r--r--arch/parisc/kernel/time.c11
-rw-r--r--arch/parisc/math-emu/fcnvff.c2
-rw-r--r--arch/parisc/mm/init.c7
17 files changed, 343 insertions, 91 deletions
diff --git a/arch/parisc/Kconfig b/arch/parisc/Kconfig
index 9792d8c..7e0bb98 100644
--- a/arch/parisc/Kconfig
+++ b/arch/parisc/Kconfig
@@ -276,10 +276,8 @@ config SMP
than one CPU, say Y.
If you say N here, the kernel will run on uni- and multiprocessor
- machines, but will use only one CPU of a multiprocessor machine. If
- you say Y here, the kernel will run on many, but not all,
- uniprocessor machines. On a uniprocessor machine, the kernel
- will run faster if you say N here.
+ machines, but will use only one CPU of a multiprocessor machine.
+ On a uniprocessor machine, the kernel will run faster if you say N.
See also <file:Documentation/nmi_watchdog.txt> and the SMP-HOWTO
available at <http://www.tldp.org/docs.html#howto>.
diff --git a/arch/parisc/include/asm/cacheflush.h b/arch/parisc/include/asm/cacheflush.h
index 3742508..bd5ce31 100644
--- a/arch/parisc/include/asm/cacheflush.h
+++ b/arch/parisc/include/asm/cacheflush.h
@@ -26,6 +26,7 @@ void flush_user_icache_range_asm(unsigned long, unsigned long);
void flush_kernel_icache_range_asm(unsigned long, unsigned long);
void flush_user_dcache_range_asm(unsigned long, unsigned long);
void flush_kernel_dcache_range_asm(unsigned long, unsigned long);
+void purge_kernel_dcache_range_asm(unsigned long, unsigned long);
void flush_kernel_dcache_page_asm(void *);
void flush_kernel_icache_page(void *);
diff --git a/arch/parisc/include/asm/io.h b/arch/parisc/include/asm/io.h
index 27c62ba..afe493b 100644
--- a/arch/parisc/include/asm/io.h
+++ b/arch/parisc/include/asm/io.h
@@ -183,15 +183,15 @@ static inline unsigned char readb(const volatile void __iomem *addr)
}
static inline unsigned short readw(const volatile void __iomem *addr)
{
- return le16_to_cpu(__raw_readw(addr));
+ return le16_to_cpu((__le16 __force) __raw_readw(addr));
}
static inline unsigned int readl(const volatile void __iomem *addr)
{
- return le32_to_cpu(__raw_readl(addr));
+ return le32_to_cpu((__le32 __force) __raw_readl(addr));
}
static inline unsigned long long readq(const volatile void __iomem *addr)
{
- return le64_to_cpu(__raw_readq(addr));
+ return le64_to_cpu((__le64 __force) __raw_readq(addr));
}
static inline void writeb(unsigned char b, volatile void __iomem *addr)
@@ -200,15 +200,15 @@ static inline void writeb(unsigned char b, volatile void __iomem *addr)
}
static inline void writew(unsigned short w, volatile void __iomem *addr)
{
- __raw_writew(cpu_to_le16(w), addr);
+ __raw_writew((__u16 __force) cpu_to_le16(w), addr);
}
static inline void writel(unsigned int l, volatile void __iomem *addr)
{
- __raw_writel(cpu_to_le32(l), addr);
+ __raw_writel((__u32 __force) cpu_to_le32(l), addr);
}
static inline void writeq(unsigned long long q, volatile void __iomem *addr)
{
- __raw_writeq(cpu_to_le64(q), addr);
+ __raw_writeq((__u64 __force) cpu_to_le64(q), addr);
}
#define readb readb
diff --git a/arch/parisc/include/asm/processor.h b/arch/parisc/include/asm/processor.h
index 0e6ab6e..2dbe558 100644
--- a/arch/parisc/include/asm/processor.h
+++ b/arch/parisc/include/asm/processor.h
@@ -316,6 +316,8 @@ extern int _parisc_requires_coherency;
#define parisc_requires_coherency() (0)
#endif
+extern int running_on_qemu;
+
#endif /* __ASSEMBLY__ */
#endif /* __ASM_PARISC_PROCESSOR_H */
diff --git a/arch/parisc/include/uapi/asm/mman.h b/arch/parisc/include/uapi/asm/mman.h
index 80510ba..a056a64 100644
--- a/arch/parisc/include/uapi/asm/mman.h
+++ b/arch/parisc/include/uapi/asm/mman.h
@@ -13,7 +13,7 @@
#define MAP_SHARED 0x01 /* Share changes */
#define MAP_PRIVATE 0x02 /* Changes are private */
#define MAP_SHARED_VALIDATE 0x03 /* share + validate extension flags */
-#define MAP_TYPE 0x03 /* Mask for type of mapping */
+#define MAP_TYPE 0x2b /* Mask for type of mapping, includes bits 0x08 and 0x20 */
#define MAP_FIXED 0x04 /* Interpret addr exactly */
#define MAP_ANONYMOUS 0x10 /* don't use a file */
diff --git a/arch/parisc/kernel/cache.c b/arch/parisc/kernel/cache.c
index 19c0c14..a99da95 100644
--- a/arch/parisc/kernel/cache.c
+++ b/arch/parisc/kernel/cache.c
@@ -88,7 +88,8 @@ update_mmu_cache(struct vm_area_struct *vma, unsigned long address, pte_t *ptep)
return;
page = pfn_to_page(pfn);
- if (page_mapping(page) && test_bit(PG_dcache_dirty, &page->flags)) {
+ if (page_mapping_file(page) &&
+ test_bit(PG_dcache_dirty, &page->flags)) {
flush_kernel_dcache_page_addr(pfn_va(pfn));
clear_bit(PG_dcache_dirty, &page->flags);
} else if (parisc_requires_coherency())
@@ -304,7 +305,7 @@ __flush_cache_page(struct vm_area_struct *vma, unsigned long vmaddr,
void flush_dcache_page(struct page *page)
{
- struct address_space *mapping = page_mapping(page);
+ struct address_space *mapping = page_mapping_file(page);
struct vm_area_struct *mpnt;
unsigned long offset;
unsigned long addr, old_addr = 0;
@@ -465,10 +466,10 @@ EXPORT_SYMBOL(copy_user_page);
int __flush_tlb_range(unsigned long sid, unsigned long start,
unsigned long end)
{
- unsigned long flags, size;
+ unsigned long flags;
- size = (end - start);
- if (size >= parisc_tlb_flush_threshold) {
+ if ((!IS_ENABLED(CONFIG_SMP) || !arch_irqs_disabled()) &&
+ end - start >= parisc_tlb_flush_threshold) {
flush_tlb_all();
return 1;
}
@@ -539,13 +540,12 @@ void flush_cache_mm(struct mm_struct *mm)
struct vm_area_struct *vma;
pgd_t *pgd;
- /* Flush the TLB to avoid speculation if coherency is required. */
- if (parisc_requires_coherency())
- flush_tlb_all();
-
/* Flushing the whole cache on each cpu takes forever on
rp3440, etc. So, avoid it if the mm isn't too big. */
- if (mm_total_size(mm) >= parisc_cache_flush_threshold) {
+ if ((!IS_ENABLED(CONFIG_SMP) || !arch_irqs_disabled()) &&
+ mm_total_size(mm) >= parisc_cache_flush_threshold) {
+ if (mm->context)
+ flush_tlb_all();
flush_cache_all();
return;
}
@@ -553,9 +553,9 @@ void flush_cache_mm(struct mm_struct *mm)
if (mm->context == mfsp(3)) {
for (vma = mm->mmap; vma; vma = vma->vm_next) {
flush_user_dcache_range_asm(vma->vm_start, vma->vm_end);
- if ((vma->vm_flags & VM_EXEC) == 0)
- continue;
- flush_user_icache_range_asm(vma->vm_start, vma->vm_end);
+ if (vma->vm_flags & VM_EXEC)
+ flush_user_icache_range_asm(vma->vm_start, vma->vm_end);
+ flush_tlb_range(vma, vma->vm_start, vma->vm_end);
}
return;
}
@@ -573,6 +573,8 @@ void flush_cache_mm(struct mm_struct *mm)
pfn = pte_pfn(*ptep);
if (!pfn_valid(pfn))
continue;
+ if (unlikely(mm->context))
+ flush_tlb_page(vma, addr);
__flush_cache_page(vma, addr, PFN_PHYS(pfn));
}
}
@@ -581,30 +583,45 @@ void flush_cache_mm(struct mm_struct *mm)
void flush_cache_range(struct vm_area_struct *vma,
unsigned long start, unsigned long end)
{
- BUG_ON(!vma->vm_mm->context);
-
- /* Flush the TLB to avoid speculation if coherency is required. */
- if (parisc_requires_coherency())
- flush_tlb_range(vma, start, end);
+ pgd_t *pgd;
+ unsigned long addr;
- if ((end - start) >= parisc_cache_flush_threshold
- || vma->vm_mm->context != mfsp(3)) {
+ if ((!IS_ENABLED(CONFIG_SMP) || !arch_irqs_disabled()) &&
+ end - start >= parisc_cache_flush_threshold) {
+ if (vma->vm_mm->context)
+ flush_tlb_range(vma, start, end);
flush_cache_all();
return;
}
- flush_user_dcache_range_asm(start, end);
- if (vma->vm_flags & VM_EXEC)
- flush_user_icache_range_asm(start, end);
+ if (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);
+ flush_tlb_range(vma, start, end);
+ return;
+ }
+
+ pgd = vma->vm_mm->pgd;
+ for (addr = vma->vm_start; addr < vma->vm_end; addr += PAGE_SIZE) {
+ unsigned long pfn;
+ pte_t *ptep = get_ptep(pgd, addr);
+ if (!ptep)
+ continue;
+ pfn = pte_pfn(*ptep);
+ if (pfn_valid(pfn)) {
+ if (unlikely(vma->vm_mm->context))
+ flush_tlb_page(vma, addr);
+ __flush_cache_page(vma, addr, PFN_PHYS(pfn));
+ }
+ }
}
void
flush_cache_page(struct vm_area_struct *vma, unsigned long vmaddr, unsigned long pfn)
{
- BUG_ON(!vma->vm_mm->context);
-
if (pfn_valid(pfn)) {
- if (parisc_requires_coherency())
+ if (likely(vma->vm_mm->context))
flush_tlb_page(vma, vmaddr);
__flush_cache_page(vma, vmaddr, PFN_PHYS(pfn));
}
@@ -613,21 +630,33 @@ flush_cache_page(struct vm_area_struct *vma, unsigned long vmaddr, unsigned long
void flush_kernel_vmap_range(void *vaddr, int size)
{
unsigned long start = (unsigned long)vaddr;
+ unsigned long end = start + size;
- if ((unsigned long)size > parisc_cache_flush_threshold)
+ if ((!IS_ENABLED(CONFIG_SMP) || !arch_irqs_disabled()) &&
+ (unsigned long)size >= parisc_cache_flush_threshold) {
+ flush_tlb_kernel_range(start, end);
flush_data_cache();
- else
- flush_kernel_dcache_range_asm(start, start + size);
+ return;
+ }
+
+ flush_kernel_dcache_range_asm(start, end);
+ flush_tlb_kernel_range(start, end);
}
EXPORT_SYMBOL(flush_kernel_vmap_range);
void invalidate_kernel_vmap_range(void *vaddr, int size)
{
unsigned long start = (unsigned long)vaddr;
+ unsigned long end = start + size;
- if ((unsigned long)size > parisc_cache_flush_threshold)
+ if ((!IS_ENABLED(CONFIG_SMP) || !arch_irqs_disabled()) &&
+ (unsigned long)size >= parisc_cache_flush_threshold) {
+ flush_tlb_kernel_range(start, end);
flush_data_cache();
- else
- flush_kernel_dcache_range_asm(start, start + size);
+ return;
+ }
+
+ purge_kernel_dcache_range_asm(start, end);
+ flush_tlb_kernel_range(start, end);
}
EXPORT_SYMBOL(invalidate_kernel_vmap_range);
diff --git a/arch/parisc/kernel/drivers.c b/arch/parisc/kernel/drivers.c
index 29b99b8..3b8507f 100644
--- a/arch/parisc/kernel/drivers.c
+++ b/arch/parisc/kernel/drivers.c
@@ -135,7 +135,7 @@ static int parisc_driver_probe(struct device *dev)
return rc;
}
-static int parisc_driver_remove(struct device *dev)
+static int __exit parisc_driver_remove(struct device *dev)
{
struct parisc_device *pa_dev = to_parisc_device(dev);
struct parisc_driver *pa_drv = to_parisc_driver(dev->driver);
@@ -205,7 +205,7 @@ static int match_and_count(struct device * dev, void * data)
* Use by IOMMU support to "guess" the right size IOPdir.
* Formula is something like memsize/(num_iommu * entry_size).
*/
-int count_parisc_driver(struct parisc_driver *driver)
+int __init count_parisc_driver(struct parisc_driver *driver)
{
struct match_count m = {
.driver = driver,
@@ -268,7 +268,7 @@ static struct parisc_device *find_device_by_addr(unsigned long hpa)
* Walks up the device tree looking for a device of the specified type.
* If it finds it, it returns it. If not, it returns NULL.
*/
-const struct parisc_device *
+const struct parisc_device * __init
find_pa_parent_type(const struct parisc_device *padev, int type)
{
const struct device *dev = &padev->dev;
@@ -397,7 +397,7 @@ static void setup_bus_id(struct parisc_device *padev)
dev_set_name(&padev->dev, name);
}
-struct parisc_device * create_tree_node(char id, struct device *parent)
+struct parisc_device * __init create_tree_node(char id, struct device *parent)
{
struct parisc_device *dev = kzalloc(sizeof(*dev), GFP_KERNEL);
if (!dev)
@@ -471,7 +471,7 @@ static struct parisc_device *create_parisc_device(struct hardware_path *modpath)
return alloc_tree_node(parent, modpath->mod);
}
-struct parisc_device *
+struct parisc_device * __init
alloc_pa_dev(unsigned long hpa, struct hardware_path *mod_path)
{
int status;
@@ -609,7 +609,7 @@ struct bus_type parisc_bus_type = {
.uevent = parisc_uevent,
.dev_groups = parisc_device_groups,
.probe = parisc_driver_probe,
- .remove = parisc_driver_remove,
+ .remove = __exit_p(parisc_driver_remove),
};
/**
@@ -619,7 +619,7 @@ struct bus_type parisc_bus_type = {
* Search the driver list for a driver that is willing to manage
* this device.
*/
-int register_parisc_device(struct parisc_device *dev)
+int __init register_parisc_device(struct parisc_device *dev)
{
if (!dev)
return 0;
@@ -651,6 +651,10 @@ static int match_pci_device(struct device *dev, int index,
(modpath->mod == PCI_FUNC(devfn)));
}
+ /* index might be out of bounds for bc[] */
+ if (index >= 6)
+ return 0;
+
id = PCI_SLOT(pdev->devfn) | (PCI_FUNC(pdev->devfn) << 5);
return (modpath->bc[index] == id);
}
@@ -791,7 +795,7 @@ EXPORT_SYMBOL(device_to_hwpath);
static void walk_native_bus(unsigned long io_io_low, unsigned long io_io_high,
struct device *parent);
-void walk_lower_bus(struct parisc_device *dev)
+static void walk_lower_bus(struct parisc_device *dev)
{
unsigned long io_io_low, io_io_high;
@@ -857,7 +861,7 @@ static void walk_native_bus(unsigned long io_io_low, unsigned long io_io_high,
* PDC doesn't tell us about all devices in the system. This routine
* finds devices connected to the central bus.
*/
-void walk_central_bus(void)
+void __init walk_central_bus(void)
{
walk_native_bus(CENTRAL_BUS_ADDR,
CENTRAL_BUS_ADDR + (MAX_NATIVE_DEVICES * NATIVE_DEVICE_OFFSET),
@@ -886,7 +890,7 @@ static void print_parisc_device(struct parisc_device *dev)
/**
* init_parisc_bus - Some preparation to be done before inventory
*/
-void init_parisc_bus(void)
+void __init init_parisc_bus(void)
{
if (bus_register(&parisc_bus_type))
panic("Could not register PA-RISC bus type\n");
@@ -895,6 +899,171 @@ void init_parisc_bus(void)
get_device(&root);
}
+static __init void qemu_header(void)
+{
+ int num;
+ unsigned long *p;
+
+ pr_info("--- cut here ---\n");
+ pr_info("/* AUTO-GENERATED HEADER FILE FOR SEABIOS FIRMWARE */\n");
+ pr_cont("/* generated with Linux kernel */\n");
+ pr_cont("/* search for PARISC_QEMU_MACHINE_HEADER in Linux */\n\n");
+
+ pr_info("#define PARISC_MODEL \"%s\"\n\n",
+ boot_cpu_data.pdc.sys_model_name);
+
+ pr_info("#define PARISC_PDC_MODEL 0x%lx, 0x%lx, 0x%lx, "
+ "0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx\n\n",
+ #define p ((unsigned long *)&boot_cpu_data.pdc.model)
+ p[0], p[1], p[2], p[3], p[4], p[5], p[6], p[7], p[8]);
+ #undef p
+
+ pr_info("#define PARISC_PDC_VERSION 0x%04lx\n\n",
+ boot_cpu_data.pdc.versions);
+
+ pr_info("#define PARISC_PDC_CPUID 0x%04lx\n\n",
+ boot_cpu_data.pdc.cpuid);
+
+ pr_info("#define PARISC_PDC_CAPABILITIES 0x%04lx\n\n",
+ boot_cpu_data.pdc.capabilities);
+
+ pr_info("#define PARISC_PDC_ENTRY_ORG 0x%04lx\n\n",
+#ifdef CONFIG_64BIT
+ (unsigned long)(PAGE0->mem_pdc_hi) << 32 |
+#endif
+ (unsigned long)PAGE0->mem_pdc);
+
+ pr_info("#define PARISC_PDC_CACHE_INFO");
+ p = (unsigned long *) &cache_info;
+ for (num = 0; num < sizeof(cache_info); num += sizeof(unsigned long)) {
+ if (((num % 5) == 0)) {
+ pr_cont(" \\\n");
+ pr_info("\t");
+ }
+ pr_cont("%s0x%04lx",
+ num?", ":"", *p++);
+ }
+ pr_cont("\n\n");
+}
+
+static __init int qemu_print_hpa(struct device *lin_dev, void *data)
+{
+ struct parisc_device *dev = to_parisc_device(lin_dev);
+ unsigned long hpa = dev->hpa.start;
+
+ pr_cont("\t{\t.hpa = 0x%08lx,\\\n", hpa);
+ pr_cont("\t\t.iodc = &iodc_data_hpa_%08lx,\\\n", hpa);
+ pr_cont("\t\t.mod_info = &mod_info_hpa_%08lx,\\\n", hpa);
+ pr_cont("\t\t.mod_path = &mod_path_hpa_%08lx,\\\n", hpa);
+ pr_cont("\t\t.num_addr = HPA_%08lx_num_addr,\\\n", hpa);
+ pr_cont("\t\t.add_addr = { HPA_%08lx_add_addr } },\\\n", hpa);
+ return 0;
+}
+
+
+static __init void qemu_footer(void)
+{
+ pr_info("\n\n#define PARISC_DEVICE_LIST \\\n");
+ for_each_padev(qemu_print_hpa, NULL);
+ pr_cont("\t{ 0, }\n");
+ pr_info("--- cut here ---\n");
+}
+
+/* print iodc data of the various hpa modules for qemu inclusion */
+static __init int qemu_print_iodc_data(struct device *lin_dev, void *data)
+{
+ struct parisc_device *dev = to_parisc_device(lin_dev);
+ unsigned long count;
+ unsigned long hpa = dev->hpa.start;
+ int status;
+ struct pdc_iodc iodc_data;
+
+ int mod_index;
+ struct pdc_system_map_mod_info pdc_mod_info;
+ struct pdc_module_path mod_path;
+
+ status = pdc_iodc_read(&count, hpa, 0,
+ &iodc_data, sizeof(iodc_data));
+ if (status != PDC_OK) {
+ pr_info("No IODC data for hpa 0x%08lx\n", hpa);
+ return 0;
+ }
+
+ pr_info("\n");
+
+ pr_info("#define HPA_%08lx_DESCRIPTION \"%s\"\n",
+ hpa, parisc_hardware_description(&dev->id));
+
+ mod_index = 0;
+ do {
+ status = pdc_system_map_find_mods(&pdc_mod_info,
+ &mod_path, mod_index++);
+ } while (status == PDC_OK && pdc_mod_info.mod_addr != hpa);
+
+ pr_info("static struct pdc_system_map_mod_info"
+ " mod_info_hpa_%08lx = {\n", hpa);
+ #define DO(member) \
+ pr_cont("\t." #member " = 0x%x,\n", \
+ (unsigned int)pdc_mod_info.member)
+ DO(mod_addr);
+ DO(mod_pgs);
+ DO(add_addrs);
+ pr_cont("};\n");
+ #undef DO
+ pr_info("static struct pdc_module_path "
+ "mod_path_hpa_%08lx = {\n", hpa);
+ pr_cont("\t.path = { ");
+ pr_cont(".flags = 0x%x, ", mod_path.path.flags);
+ pr_cont(".bc = { 0x%x, 0x%x, 0x%x, 0x%x, 0x%x, 0x%x }, ",
+ (unsigned char)mod_path.path.bc[0],
+ (unsigned char)mod_path.path.bc[1],
+ (unsigned char)mod_path.path.bc[2],
+ (unsigned char)mod_path.path.bc[3],
+ (unsigned char)mod_path.path.bc[4],
+ (unsigned char)mod_path.path.bc[5]);
+ pr_cont(".mod = 0x%x ", mod_path.path.mod);
+ pr_cont(" },\n");
+ pr_cont("\t.layers = { 0x%x, 0x%x, 0x%x, 0x%x, 0x%x, 0x%x }\n",
+ mod_path.layers[0], mod_path.layers[1], mod_path.layers[2],
+ mod_path.layers[3], mod_path.layers[4], mod_path.layers[5]);
+ pr_cont("};\n");
+
+ pr_info("static struct pdc_iodc iodc_data_hpa_%08lx = {\n", hpa);
+ #define DO(member) \
+ pr_cont("\t." #member " = 0x%04lx,\n", \
+ (unsigned long)iodc_data.member)
+ DO(hversion_model);
+ DO(hversion);
+ DO(spa);
+ DO(type);
+ DO(sversion_rev);
+ DO(sversion_model);
+ DO(sversion_opt);
+ DO(rev);
+ DO(dep);
+ DO(features);
+ DO(checksum);
+ DO(length);
+ #undef DO
+ pr_cont("\t/* pad: 0x%04x, 0x%04x */\n",
+ iodc_data.pad[0], iodc_data.pad[1]);
+ pr_cont("};\n");
+
+ pr_info("#define HPA_%08lx_num_addr %d\n", hpa, dev->num_addrs);
+ pr_info("#define HPA_%08lx_add_addr ", hpa);
+ count = 0;
+ if (dev->num_addrs == 0)
+ pr_cont("0");
+ while (count < dev->num_addrs) {
+ pr_cont("0x%08lx, ", dev->addr[count]);
+ count++;
+ }
+ pr_cont("\n\n");
+
+ return 0;
+}
+
+
static int print_one_device(struct device * dev, void * data)
{
@@ -908,7 +1077,13 @@ static int print_one_device(struct device * dev, void * data)
/**
* print_parisc_devices - Print out a list of devices found in this system
*/
-void print_parisc_devices(void)
+void __init print_parisc_devices(void)
{
for_each_padev(print_one_device, NULL);
+ #define PARISC_QEMU_MACHINE_HEADER 0
+ if (PARISC_QEMU_MACHINE_HEADER) {
+ qemu_header();
+ for_each_padev(qemu_print_iodc_data, NULL);
+ qemu_footer();
+ }
}
diff --git a/arch/parisc/kernel/hardware.c b/arch/parisc/kernel/hardware.c
index af3bc35..a205895 100644
--- a/arch/parisc/kernel/hardware.c
+++ b/arch/parisc/kernel/hardware.c
@@ -41,7 +41,7 @@
* are guessed. If you know the correct name, please let us know.
*/
-static struct hp_hardware hp_hardware_list[] = {
+static struct hp_hardware hp_hardware_list[] __initdata = {
{HPHW_NPROC,0x01,0x4,0x0,"Indigo (840, 930)"},
{HPHW_NPROC,0x8,0x4,0x01,"Firefox(825,925)"},
{HPHW_NPROC,0xA,0x4,0x01,"Top Gun (835,834,935,635)"},
@@ -1238,7 +1238,7 @@ static struct hp_cpu_type_mask {
unsigned short model;
unsigned short mask;
enum cpu_type cpu;
-} hp_cpu_type_mask_list[] = {
+} hp_cpu_type_mask_list[] __initdata = {
{ 0x0000, 0x0ff0, pcx }, /* 0x0000 - 0x000f */
{ 0x0048, 0x0ff0, pcxl }, /* 0x0040 - 0x004f */
@@ -1325,17 +1325,17 @@ const char * const cpu_name_version[][2] = {
[pcxt] = { "PA7100 (PCX-T)", "1.1b" },
[pcxt_] = { "PA7200 (PCX-T')", "1.1c" },
[pcxl] = { "PA7100LC (PCX-L)", "1.1d" },
- [pcxl2] = { "PA7300LC (PCX-L2)", "1.1e" },
+ [pcxl2] = { "PA7300LC (PCX-L2)","1.1e" },
[pcxu] = { "PA8000 (PCX-U)", "2.0" },
[pcxu_] = { "PA8200 (PCX-U+)", "2.0" },
[pcxw] = { "PA8500 (PCX-W)", "2.0" },
[pcxw_] = { "PA8600 (PCX-W+)", "2.0" },
[pcxw2] = { "PA8700 (PCX-W2)", "2.0" },
[mako] = { "PA8800 (Mako)", "2.0" },
- [mako2] = { "PA8900 (Shortfin)", "2.0" }
+ [mako2] = { "PA8900 (Shortfin)","2.0" }
};
-const char *parisc_hardware_description(struct parisc_device_id *id)
+const char * __init parisc_hardware_description(struct parisc_device_id *id)
{
struct hp_hardware *listptr;
@@ -1373,7 +1373,7 @@ const char *parisc_hardware_description(struct parisc_device_id *id)
/* Interpret hversion (ret[0]) from PDC_MODEL(4)/PDC_MODEL_INFO(0) */
-enum cpu_type
+enum cpu_type __init
parisc_get_cpu_type(unsigned long hversion)
{
struct hp_cpu_type_mask *ptr;
diff --git a/arch/parisc/kernel/head.S b/arch/parisc/kernel/head.S
index bbbe360..fbb4e43 100644
--- a/arch/parisc/kernel/head.S
+++ b/arch/parisc/kernel/head.S
@@ -138,6 +138,16 @@ $pgt_fill_loop:
std %dp,0x18(%r10)
#endif
+#ifdef CONFIG_64BIT
+ /* Get PDCE_PROC for monarch CPU. */
+#define MEM_PDC_LO 0x388
+#define MEM_PDC_HI 0x35C
+ ldw MEM_PDC_LO(%r0),%r3
+ ldw MEM_PDC_HI(%r0),%r10
+ depd %r10, 31, 32, %r3 /* move to upper word */
+#endif
+
+
#ifdef CONFIG_SMP
/* Set the smp rendezvous address into page zero.
** It would be safer to do this in init_smp_config() but
@@ -196,12 +206,6 @@ common_stext:
** Someday, palo might not do this for the Monarch either.
*/
2:
-#define MEM_PDC_LO 0x388
-#define MEM_PDC_HI 0x35C
- ldw MEM_PDC_LO(%r0),%r3
- ldw MEM_PDC_HI(%r0),%r6
- depd %r6, 31, 32, %r3 /* move to upper word */
-
mfctl %cr30,%r6 /* PCX-W2 firmware bug */
ldo PDC_PSW(%r0),%arg0 /* 21 */
@@ -268,6 +272,8 @@ $install_iva:
aligned_rfi:
pcxt_ssm_bug
+ copy %r3, %arg0 /* PDCE_PROC for smp_callin() */
+
rsm PSW_SM_QUIET,%r0 /* off troublesome PSW bits */
/* Don't need NOPs, have 8 compliant insn before rfi */
diff --git a/arch/parisc/kernel/hpmc.S b/arch/parisc/kernel/hpmc.S
index 8d072c4..781c3b9 100644
--- a/arch/parisc/kernel/hpmc.S
+++ b/arch/parisc/kernel/hpmc.S
@@ -84,6 +84,7 @@ END(hpmc_pim_data)
.text
.import intr_save, code
+ .align 16
ENTRY_CFI(os_hpmc)
.os_hpmc:
@@ -300,12 +301,15 @@ os_hpmc_6:
b .
nop
+ .align 16 /* make function length multiple of 16 bytes */
ENDPROC_CFI(os_hpmc)
.os_hpmc_end:
__INITRODATA
+.globl os_hpmc_size
.align 4
- .export os_hpmc_size
+ .type os_hpmc_size, @object
+ .size os_hpmc_size, 4
os_hpmc_size:
.word .os_hpmc_end-.os_hpmc
diff --git a/arch/parisc/kernel/pacache.S b/arch/parisc/kernel/pacache.S
index 2d40c4f..67b0f75 100644
--- a/arch/parisc/kernel/pacache.S
+++ b/arch/parisc/kernel/pacache.S
@@ -1110,6 +1110,28 @@ ENTRY_CFI(flush_kernel_dcache_range_asm)
.procend
ENDPROC_CFI(flush_kernel_dcache_range_asm)
+ENTRY_CFI(purge_kernel_dcache_range_asm)
+ .proc
+ .callinfo NO_CALLS
+ .entry
+
+ ldil L%dcache_stride, %r1
+ ldw R%dcache_stride(%r1), %r23
+ ldo -1(%r23), %r21
+ ANDCM %r26, %r21, %r26
+
+1: cmpb,COND(<<),n %r26, %r25,1b
+ pdc,m %r23(%r26)
+
+ sync
+ syncdma
+ bv %r0(%r2)
+ nop
+ .exit
+
+ .procend
+ENDPROC_CFI(purge_kernel_dcache_range_asm)
+
ENTRY_CFI(flush_user_icache_range_asm)
.proc
.callinfo NO_CALLS
diff --git a/arch/parisc/kernel/process.c b/arch/parisc/kernel/process.c
index 6975a06..bbe4657 100644
--- a/arch/parisc/kernel/process.c
+++ b/arch/parisc/kernel/process.c
@@ -138,6 +138,10 @@ void machine_power_off(void)
pdc_soft_power_button(0);
pdc_chassis_send_status(PDC_CHASSIS_DIRECT_SHUTDOWN);
+
+ /* ipmi_poweroff may have been installed. */
+ if (pm_power_off)
+ pm_power_off();
/* It seems we have no way to power the system off via
* software. The user has to press the button himself. */
@@ -151,7 +155,7 @@ void machine_power_off(void)
for (;;);
}
-void (*pm_power_off)(void) = machine_power_off;
+void (*pm_power_off)(void);
EXPORT_SYMBOL(pm_power_off);
void flush_thread(void)
diff --git a/arch/parisc/kernel/smp.c b/arch/parisc/kernel/smp.c
index 30c28ab..4065b5e 100644
--- a/arch/parisc/kernel/smp.c
+++ b/arch/parisc/kernel/smp.c
@@ -292,10 +292,15 @@ smp_cpu_init(int cpunum)
* Slaves start using C here. Indirectly called from smp_slave_stext.
* Do what start_kernel() and main() do for boot strap processor (aka monarch)
*/
-void __init smp_callin(void)
+void __init smp_callin(unsigned long pdce_proc)
{
int slave_id = cpu_now_booting;
+#ifdef CONFIG_64BIT
+ WARN_ON(((unsigned long)(PAGE0->mem_pdc_hi) << 32
+ | PAGE0->mem_pdc) != pdce_proc);
+#endif
+
smp_cpu_init(slave_id);
preempt_disable();
diff --git a/arch/parisc/kernel/sys_parisc.c b/arch/parisc/kernel/sys_parisc.c
index 378a754..8c99ebb 100644
--- a/arch/parisc/kernel/sys_parisc.c
+++ b/arch/parisc/kernel/sys_parisc.c
@@ -270,8 +270,8 @@ asmlinkage unsigned long sys_mmap2(unsigned long addr, unsigned long len,
{
/* Make sure the shift for mmap2 is constant (12), no matter what PAGE_SIZE
we have. */
- return sys_mmap_pgoff(addr, len, prot, flags, fd,
- pgoff >> (PAGE_SHIFT - 12));
+ return ksys_mmap_pgoff(addr, len, prot, flags, fd,
+ pgoff >> (PAGE_SHIFT - 12));
}
asmlinkage unsigned long sys_mmap(unsigned long addr, unsigned long len,
@@ -279,7 +279,7 @@ asmlinkage unsigned long sys_mmap(unsigned long addr, unsigned long len,
unsigned long offset)
{
if (!(offset & ~PAGE_MASK)) {
- return sys_mmap_pgoff(addr, len, prot, flags, fd,
+ return ksys_mmap_pgoff(addr, len, prot, flags, fd,
offset >> PAGE_SHIFT);
} else {
return -EINVAL;
@@ -292,24 +292,24 @@ asmlinkage unsigned long sys_mmap(unsigned long addr, unsigned long len,
asmlinkage long parisc_truncate64(const char __user * path,
unsigned int high, unsigned int low)
{
- return sys_truncate(path, (long)high << 32 | low);
+ return ksys_truncate(path, (long)high << 32 | low);
}
asmlinkage long parisc_ftruncate64(unsigned int fd,
unsigned int high, unsigned int low)
{
- return sys_ftruncate(fd, (long)high << 32 | low);
+ return ksys_ftruncate(fd, (long)high << 32 | low);
}
/* stubs for the benefit of the syscall_table since truncate64 and truncate
* are identical on LP64 */
asmlinkage long sys_truncate64(const char __user * path, unsigned long length)
{
- return sys_truncate(path, length);
+ return ksys_truncate(path, length);
}
asmlinkage long sys_ftruncate64(unsigned int fd, unsigned long length)
{
- return sys_ftruncate(fd, length);
+ return ksys_ftruncate(fd, length);
}
asmlinkage long sys_fcntl64(unsigned int fd, unsigned int cmd, unsigned long arg)
{
@@ -320,7 +320,7 @@ asmlinkage long sys_fcntl64(unsigned int fd, unsigned int cmd, unsigned long arg
asmlinkage long parisc_truncate64(const char __user * path,
unsigned int high, unsigned int low)
{
- return sys_truncate64(path, (loff_t)high << 32 | low);
+ return ksys_truncate(path, (loff_t)high << 32 | low);
}
asmlinkage long parisc_ftruncate64(unsigned int fd,
@@ -333,26 +333,26 @@ asmlinkage long parisc_ftruncate64(unsigned int fd,
asmlinkage ssize_t parisc_pread64(unsigned int fd, char __user *buf, size_t count,
unsigned int high, unsigned int low)
{
- return sys_pread64(fd, buf, count, (loff_t)high << 32 | low);
+ return ksys_pread64(fd, buf, count, (loff_t)high << 32 | low);
}
asmlinkage ssize_t parisc_pwrite64(unsigned int fd, const char __user *buf,
size_t count, unsigned int high, unsigned int low)
{
- return sys_pwrite64(fd, buf, count, (loff_t)high << 32 | low);
+ return ksys_pwrite64(fd, buf, count, (loff_t)high << 32 | low);
}
asmlinkage ssize_t parisc_readahead(int fd, unsigned int high, unsigned int low,
size_t count)
{
- return sys_readahead(fd, (loff_t)high << 32 | low, count);
+ return ksys_readahead(fd, (loff_t)high << 32 | low, count);
}
asmlinkage long parisc_fadvise64_64(int fd,
unsigned int high_off, unsigned int low_off,
unsigned int high_len, unsigned int low_len, int advice)
{
- return sys_fadvise64_64(fd, (loff_t)high_off << 32 | low_off,
+ return ksys_fadvise64_64(fd, (loff_t)high_off << 32 | low_off,
(loff_t)high_len << 32 | low_len, advice);
}
@@ -360,15 +360,15 @@ asmlinkage long parisc_sync_file_range(int fd,
u32 hi_off, u32 lo_off, u32 hi_nbytes, u32 lo_nbytes,
unsigned int flags)
{
- return sys_sync_file_range(fd, (loff_t)hi_off << 32 | lo_off,
+ return ksys_sync_file_range(fd, (loff_t)hi_off << 32 | lo_off,
(loff_t)hi_nbytes << 32 | lo_nbytes, flags);
}
asmlinkage long parisc_fallocate(int fd, int mode, u32 offhi, u32 offlo,
u32 lenhi, u32 lenlo)
{
- return sys_fallocate(fd, mode, ((u64)offhi << 32) | offlo,
- ((u64)lenhi << 32) | lenlo);
+ return ksys_fallocate(fd, mode, ((u64)offhi << 32) | offlo,
+ ((u64)lenhi << 32) | lenlo);
}
long parisc_personality(unsigned long personality)
diff --git a/arch/parisc/kernel/time.c b/arch/parisc/kernel/time.c
index f2890bd..c383040 100644
--- a/arch/parisc/kernel/time.c
+++ b/arch/parisc/kernel/time.c
@@ -76,10 +76,10 @@ irqreturn_t __irq_entry timer_interrupt(int irq, void *dev_id)
next_tick = cpuinfo->it_value;
/* Calculate how many ticks have elapsed. */
+ now = mfctl(16);
do {
++ticks_elapsed;
next_tick += cpt;
- now = mfctl(16);
} while (next_tick - now > cpt);
/* Store (in CR16 cycles) up to when we are accounting right now. */
@@ -103,16 +103,17 @@ irqreturn_t __irq_entry timer_interrupt(int irq, void *dev_id)
* if one or the other wrapped. If "now" is "bigger" we'll end up
* with a very large unsigned number.
*/
- while (next_tick - mfctl(16) > cpt)
+ now = mfctl(16);
+ while (next_tick - now > cpt)
next_tick += cpt;
/* Program the IT when to deliver the next interrupt.
* Only bottom 32-bits of next_tick are writable in CR16!
* Timer interrupt will be delivered at least a few hundred cycles
- * after the IT fires, so if we are too close (<= 500 cycles) to the
+ * after the IT fires, so if we are too close (<= 8000 cycles) to the
* next cycle, simply skip it.
*/
- if (next_tick - mfctl(16) <= 500)
+ if (next_tick - now <= 8000)
next_tick += cpt;
mtctl(next_tick, 16);
@@ -248,7 +249,7 @@ static int __init init_cr16_clocksource(void)
* different sockets, so mark them unstable and lower rating on
* multi-socket SMP systems.
*/
- if (num_online_cpus() > 1) {
+ if (num_online_cpus() > 1 && !running_on_qemu) {
int cpu;
unsigned long cpu0_loc;
cpu0_loc = per_cpu(cpu_data, 0).cpu_loc;
diff --git a/arch/parisc/math-emu/fcnvff.c b/arch/parisc/math-emu/fcnvff.c
index 76c063f..f9357d9 100644
--- a/arch/parisc/math-emu/fcnvff.c
+++ b/arch/parisc/math-emu/fcnvff.c
@@ -148,7 +148,7 @@ dbl_to_sgl_fcnvff(
register int src_exponent, dest_exponent, dest_mantissa;
register boolean inexact = FALSE, guardbit = FALSE, stickybit = FALSE;
register boolean lsb_odd = FALSE;
- boolean is_tiny;
+ boolean is_tiny = FALSE;
Dbl_copyfromptr(srcptr,srcp1,srcp2);
src_exponent = Dbl_exponent(srcp1);
diff --git a/arch/parisc/mm/init.c b/arch/parisc/mm/init.c
index 48f4139..cab32ee 100644
--- a/arch/parisc/mm/init.c
+++ b/arch/parisc/mm/init.c
@@ -629,7 +629,12 @@ void __init mem_init(void)
#endif
mem_init_print_info(NULL);
-#ifdef CONFIG_DEBUG_KERNEL /* double-sanity-check paranoia */
+
+#if 0
+ /*
+ * Do not expose the virtual kernel memory layout to userspace.
+ * But keep code for debugging purposes.
+ */
printk("virtual kernel memory layout:\n"
" vmalloc : 0x%px - 0x%px (%4ld MB)\n"
" memory : 0x%px - 0x%px (%4ld MB)\n"
OpenPOWER on IntegriCloud