Commit 82430821 authored by Matthew Wilcox's avatar Matthew Wilcox Committed by Linus Torvalds

[PATCH] arch/parisc/kernel

Update arch/parisc/kernel.
parent 6b3efc2a
...@@ -2,29 +2,30 @@ ...@@ -2,29 +2,30 @@
# Makefile for the linux kernel. # Makefile for the linux kernel.
# #
EXTRA_TARGETS := head.o init_task.o process.o pdc_cons.o ifdef CONFIG_PARISC64
EXTRA_TARGETS := init_task.o pdc_cons.o process.o head64.o unaligned.o perf.o perf_asm.o
else
EXTRA_TARGETS := init_task.o pdc_cons.o process.o head.o unaligned.o
endif
# Object file lists. AFLAGS_entry.o := -traditional
AFLAGS_pacache.o := -traditional
obj-y := cache.o setup.o traps.o time.o irq.o \ export-objs := parisc_ksyms.o keyboard.o
syscall.o entry.o sys_parisc.o pdc.o ptrace.o hardware.o \
inventory.o drivers.o semaphore.o pa7300lc.o pci-dma.o \
signal.o hpmc.o \
real1.o real2.o led.o parisc_ksyms.o
export-objs := parisc_ksyms.o obj-y := cache.o pacache.o setup.o traps.o time.o irq.o \
pa7300lc.o syscall.o entry.o sys_parisc.o firmware.o \
ptrace.o hardware.o inventory.o drivers.o semaphore.o \
signal.o hpmc.o real2.o parisc_ksyms.o unaligned.o \
processor.o pdc_chassis.o
obj-$(CONFIG_SMP) += smp.o
obj-$(CONFIG_PA11) += pci-dma.o
obj-$(CONFIG_PCI) += pci.o obj-$(CONFIG_PCI) += pci.o
obj-$(CONFIG_VT) += keyboard.o obj-$(CONFIG_VT) += keyboard.o
obj-$(CONFIG_PCI_LBA) += lba_pci.o obj-$(CONFIG_PARISC64) += binfmt_elf32.o sys_parisc32.o \
# I/O SAPIC is also on IA64 platforms. ioctl32.o signal32.o
# The two could be merged into a common source some day. # only supported for PCX-W/U in 64-bit mode at the moment
obj-$(CONFIG_IOSAPIC) += iosapic.o obj-$(CONFIG_PARISC64) += perf.o perf_asm.o
obj-$(CONFIG_IOMMU_SBA) += sba_iommu.o
# Only use one of them: ccio-rm-dma is for PCX-W systems *only*
# obj-$(CONFIG_IOMMU_CCIO) += ccio-rm-dma.o
obj-$(CONFIG_IOMMU_CCIO) += ccio-dma.o
EXTRA_AFLAGS := -traditional
include $(TOPDIR)/Rules.make include $(TOPDIR)/Rules.make
This diff is collapsed.
/*
* Support for 32-bit Linux/Parisc ELF binaries on 64 bit kernels
*
* Copyright (C) 2000 John Marvin
* Copyright (C) 2000 Hewlett Packard Co.
*
* Heavily inspired from various other efforts to do the same thing
* (ia64,sparc64/mips64)
*/
/* Make sure include/asm-parisc/elf.h does the right thing */
#define ELF_CLASS ELFCLASS32
typedef unsigned int elf_greg_t;
#include <linux/spinlock.h>
#include <asm/processor.h>
#include <linux/module.h>
#include <linux/config.h>
#include <linux/elfcore.h>
#include "sys32.h" /* struct timeval32 */
#define elf_prstatus elf_prstatus32
struct elf_prstatus32
{
struct elf_siginfo pr_info; /* Info associated with signal */
short pr_cursig; /* Current signal */
unsigned int pr_sigpend; /* Set of pending signals */
unsigned int pr_sighold; /* Set of held signals */
pid_t pr_pid;
pid_t pr_ppid;
pid_t pr_pgrp;
pid_t pr_sid;
struct timeval32 pr_utime; /* User time */
struct timeval32 pr_stime; /* System time */
struct timeval32 pr_cutime; /* Cumulative user time */
struct timeval32 pr_cstime; /* Cumulative system time */
elf_gregset_t pr_reg; /* GP registers */
int pr_fpvalid; /* True if math co-processor being used. */
};
#define elf_prpsinfo elf_prpsinfo32
struct elf_prpsinfo32
{
char pr_state; /* numeric process state */
char pr_sname; /* char for pr_state */
char pr_zomb; /* zombie */
char pr_nice; /* nice val */
unsigned int pr_flag; /* flags */
u16 pr_uid;
u16 pr_gid;
pid_t pr_pid, pr_ppid, pr_pgrp, pr_sid;
/* Lots missing */
char pr_fname[16]; /* filename of executable */
char pr_psargs[ELF_PRARGSZ]; /* initial part of arg list */
};
#define elf_addr_t unsigned int
#define init_elf_binfmt init_elf32_binfmt
#define ELF_PLATFORM ("PARISC32\0")
#define ELF_CORE_COPY_REGS(dst, pt) \
memset(dst, 0, sizeof(dst)); /* don't leak any "random" bits */ \
{ int i; \
for (i = 0; i < 32; i++) dst[i] = (elf_greg_t) pt->gr[i]; \
for (i = 0; i < 8; i++) dst[32 + i] = (elf_greg_t) pt->sr[i]; \
} \
dst[40] = (elf_greg_t) pt->iaoq[0]; dst[41] = (elf_greg_t) pt->iaoq[1]; \
dst[42] = (elf_greg_t) pt->iasq[0]; dst[43] = (elf_greg_t) pt->iasq[1]; \
dst[44] = (elf_greg_t) pt->sar; dst[45] = (elf_greg_t) pt->iir; \
dst[46] = (elf_greg_t) pt->isr; dst[47] = (elf_greg_t) pt->ior; \
dst[48] = (elf_greg_t) mfctl(22); dst[49] = (elf_greg_t) mfctl(0); \
dst[50] = (elf_greg_t) mfctl(24); dst[51] = (elf_greg_t) mfctl(25); \
dst[52] = (elf_greg_t) mfctl(26); dst[53] = (elf_greg_t) mfctl(27); \
dst[54] = (elf_greg_t) mfctl(28); dst[55] = (elf_greg_t) mfctl(29); \
dst[56] = (elf_greg_t) mfctl(30); dst[57] = (elf_greg_t) mfctl(31); \
dst[58] = (elf_greg_t) mfctl( 8); dst[59] = (elf_greg_t) mfctl( 9); \
dst[60] = (elf_greg_t) mfctl(12); dst[61] = (elf_greg_t) mfctl(13); \
dst[62] = (elf_greg_t) mfctl(10); dst[63] = (elf_greg_t) mfctl(15);
/*
* We should probably use this macro to set a flag somewhere to indicate
* this is a 32 on 64 process. We could use PER_LINUX_32BIT, or we
* could set a processor dependent flag in the thread_struct.
*/
#define SET_PERSONALITY(ex, ibcs2) \
current->personality = PER_LINUX_32BIT
#include "../../../fs/binfmt_elf.c"
...@@ -15,202 +15,87 @@ ...@@ -15,202 +15,87 @@
#include <linux/init.h> #include <linux/init.h>
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/mm.h> #include <linux/mm.h>
#include <linux/seq_file.h>
#include <asm/pdc.h> #include <asm/pdc.h>
#include <asm/cache.h> #include <asm/cache.h>
#include <asm/cacheflush.h>
#include <asm/tlbflush.h>
#include <asm/system.h> #include <asm/system.h>
#include <asm/page.h> #include <asm/page.h>
#include <asm/pgalloc.h> #include <asm/pgalloc.h>
#include <asm/processor.h>
int split_tlb;
int dcache_stride;
int icache_stride;
struct pdc_cache_info cache_info; struct pdc_cache_info cache_info;
#ifndef __LP64__ #ifndef CONFIG_PA20
static struct pdc_btlb_info btlb_info; static struct pdc_btlb_info btlb_info;
#endif #endif
#ifdef CONFIG_SMP
void __flush_page_to_ram(unsigned long address) void
{ flush_data_cache(void)
__flush_dcache_range(address, PAGE_SIZE);
__flush_icache_range(address, PAGE_SIZE);
}
void flush_data_cache(void)
{ {
register unsigned long base = cache_info.dc_base; smp_call_function((void (*)(void *))flush_data_cache_local, NULL, 1, 1);
register unsigned long count = cache_info.dc_count; flush_data_cache_local();
register unsigned long loop = cache_info.dc_loop;
register unsigned long stride = cache_info.dc_stride;
register unsigned long addr;
register long i, j;
for(i=0,addr=base; i<count; i++,addr+=stride)
for(j=0; j<loop; j++)
fdce(addr);
} }
#endif
static inline void flush_data_tlb_space(void) void
flush_cache_all_local(void)
{ {
unsigned long base = cache_info.dt_off_base; flush_instruction_cache_local();
unsigned long count = cache_info.dt_off_count; flush_data_cache_local();
unsigned long stride = cache_info.dt_off_stride;
unsigned long loop = cache_info.dt_loop;
unsigned long addr;
long i,j;
for(i=0,addr=base; i<count; i++,addr+=stride)
for(j=0; j<loop; j++)
pdtlbe(addr);
} }
/* flushes EVERYTHING (tlb & cache) */
void
void flush_data_tlb(void) flush_all_caches(void)
{ {
unsigned long base = cache_info.dt_sp_base; flush_cache_all();
unsigned long count = cache_info.dt_sp_count; flush_tlb_all();
unsigned long stride = cache_info.dt_sp_stride;
unsigned long space;
unsigned long old_sr1;
long i;
old_sr1 = mfsp(1);
for(i=0,space=base; i<count; i++, space+=stride) {
mtsp(space,1);
flush_data_tlb_space();
}
mtsp(old_sr1, 1);
} }
static inline void flush_instruction_tlb_space(void) void
update_mmu_cache(struct vm_area_struct *vma, unsigned long address, pte_t pte)
{ {
unsigned long base = cache_info.it_off_base; struct page *page = pte_page(pte);
unsigned long count = cache_info.it_off_count;
unsigned long stride = cache_info.it_off_stride;
unsigned long loop = cache_info.it_loop;
unsigned long addr;
long i,j;
for(i=0,addr=base; i<count; i++,addr+=stride) if (VALID_PAGE(page) && page->mapping &&
for(j=0; j<loop; j++) test_bit(PG_dcache_dirty, &page->flags)) {
pitlbe(addr);
}
void flush_instruction_tlb(void) flush_kernel_dcache_page(page_address(page));
{ clear_bit(PG_dcache_dirty, &page->flags);
unsigned long base = cache_info.it_sp_base;
unsigned long count = cache_info.it_sp_count;
unsigned long stride = cache_info.it_sp_stride;
unsigned long space;
unsigned long old_sr1;
unsigned int i;
old_sr1 = mfsp(1);
for(i=0,space=base; i<count; i++, space+=stride) {
mtsp(space,1);
flush_instruction_tlb_space();
} }
mtsp(old_sr1, 1);
}
void __flush_tlb_space(unsigned long space)
{
unsigned long old_sr1;
old_sr1 = mfsp(1);
mtsp(space, 1);
flush_data_tlb_space();
flush_instruction_tlb_space();
mtsp(old_sr1, 1);
}
void flush_instruction_cache(void)
{
register unsigned long base = cache_info.ic_base;
register unsigned long count = cache_info.ic_count;
register unsigned long loop = cache_info.ic_loop;
register unsigned long stride = cache_info.ic_stride;
register unsigned long addr;
register long i, j;
unsigned long old_sr1;
old_sr1 = mfsp(1);
mtsp(0,1);
/*
* Note: fice instruction has 3 bit space field, so one must
* be specified (otherwise you are justing using whatever
* happens to be in sr0).
*/
for(i=0,addr=base; i<count; i++,addr+=stride)
for(j=0; j<loop; j++)
fice(addr);
mtsp(old_sr1, 1);
} }
/* not yet ... fdc() needs to be implemented in cache.h ! void
void flush_datacache_range( unsigned int base, unsigned int end ) show_cache_info(struct seq_file *m)
{ {
register long offset,offset_add; seq_printf(m, "I-cache\t\t: %ld KB\n",
offset_add = ( (1<<(cache_info.dc_conf.cc_block-1)) *
cache_info.dc_conf.cc_line ) << 4;
for (offset=base; offset<=end; offset+=offset_add)
fdc(space,offset);
fdc(space,end);
}
*/
/* flushes code and data-cache */
void flush_all_caches(void)
{
flush_instruction_cache();
flush_data_cache();
flush_instruction_tlb();
flush_data_tlb();
asm volatile("sync");
asm volatile("syncdma");
asm volatile("sync");
}
int get_cache_info(char *buffer)
{
char *p = buffer;
p += sprintf(p, "I-cache\t\t: %ld KB\n",
cache_info.ic_size/1024 ); cache_info.ic_size/1024 );
p += sprintf(p, "D-cache\t\t: %ld KB (%s)%s\n", seq_printf(m, "D-cache\t\t: %ld KB (%s)%s\n",
cache_info.dc_size/1024, cache_info.dc_size/1024,
(cache_info.dc_conf.cc_wt ? "WT":"WB"), (cache_info.dc_conf.cc_wt ? "WT":"WB"),
(cache_info.dc_conf.cc_sh ? " - shared I/D":"") (cache_info.dc_conf.cc_sh ? " - shared I/D":"")
); );
p += sprintf(p, "ITLB entries\t: %ld\n" "DTLB entries\t: %ld%s\n", seq_printf(m, "ITLB entries\t: %ld\n" "DTLB entries\t: %ld%s\n",
cache_info.it_size, cache_info.it_size,
cache_info.dt_size, cache_info.dt_size,
cache_info.dt_conf.tc_sh ? " - shared with ITLB":"" cache_info.dt_conf.tc_sh ? " - shared with ITLB":""
); );
#ifndef __LP64__ #ifndef CONFIG_PA20
/* BTLB - Block TLB */ /* BTLB - Block TLB */
if (btlb_info.max_size==0) { if (btlb_info.max_size==0) {
p += sprintf(p, "BTLB\t\t: not supported\n" ); seq_printf(m, "BTLB\t\t: not supported\n" );
} else { } else {
p += sprintf(p, seq_printf(m,
"BTLB fixed\t: max. %d pages, pagesize=%d (%dMB)\n" "BTLB fixed\t: max. %d pages, pagesize=%d (%dMB)\n"
"BTLB fix-entr.\t: %d instruction, %d data (%d combined)\n" "BTLB fix-entr.\t: %d instruction, %d data (%d combined)\n"
"BTLB var-entr.\t: %d instruction, %d data (%d combined)\n", "BTLB var-entr.\t: %d instruction, %d data (%d combined)\n",
...@@ -225,29 +110,117 @@ int get_cache_info(char *buffer) ...@@ -225,29 +110,117 @@ int get_cache_info(char *buffer)
); );
} }
#endif #endif
return p - buffer;
} }
void __init void __init
cache_init(void) parisc_cache_init(void)
{ {
if(pdc_cache_info(&cache_info)<0) if(pdc_cache_info(&cache_info)<0)
panic("cache_init: pdc_cache_info failed"); panic("parisc_cache_init: pdc_cache_info failed");
#if 0 #if 0
printk("ic_size %lx dc_size %lx it_size %lx pdc_cache_info %d*long pdc_cache_cf %d\n", printk(KERN_DEBUG "ic_size %lx dc_size %lx it_size %lx pdc_cache_info %d*long pdc_cache_cf %d\n",
cache_info.ic_size, cache_info.ic_size,
cache_info.dc_size, cache_info.dc_size,
cache_info.it_size, cache_info.it_size,
sizeof (struct pdc_cache_info) / sizeof (long), sizeof (struct pdc_cache_info) / sizeof (long),
sizeof (struct pdc_cache_cf) sizeof (struct pdc_cache_cf)
); );
printk(KERN_DEBUG "dc base %x dc stride %x dc count %x dc loop %d\n",
cache_info.dc_base,
cache_info.dc_stride,
cache_info.dc_count,
cache_info.dc_loop);
printk(KERN_DEBUG "dc conf: alias %d block %d line %d wt %d sh %d cst %d assoc %d\n",
cache_info.dc_conf.cc_alias,
cache_info.dc_conf.cc_block,
cache_info.dc_conf.cc_line,
cache_info.dc_conf.cc_wt,
cache_info.dc_conf.cc_sh,
cache_info.dc_conf.cc_cst,
cache_info.dc_conf.cc_assoc);
printk(KERN_DEBUG "ic conf: alias %d block %d line %d wt %d sh %d cst %d assoc %d\n",
cache_info.ic_conf.cc_alias,
cache_info.ic_conf.cc_block,
cache_info.ic_conf.cc_line,
cache_info.ic_conf.cc_wt,
cache_info.ic_conf.cc_sh,
cache_info.ic_conf.cc_cst,
cache_info.ic_conf.cc_assoc);
printk(KERN_DEBUG "dt conf: sh %d page %d cst %d aid %d pad1 %d \n",
cache_info.dt_conf.tc_sh,
cache_info.dt_conf.tc_page,
cache_info.dt_conf.tc_cst,
cache_info.dt_conf.tc_aid,
cache_info.dt_conf.tc_pad1);
printk(KERN_DEBUG "it conf: sh %d page %d cst %d aid %d pad1 %d \n",
cache_info.it_conf.tc_sh,
cache_info.it_conf.tc_page,
cache_info.it_conf.tc_cst,
cache_info.it_conf.tc_aid,
cache_info.it_conf.tc_pad1);
#endif #endif
#ifndef __LP64__
split_tlb = 0;
if (cache_info.dt_conf.tc_sh == 0 || cache_info.dt_conf.tc_sh == 2) {
if (cache_info.dt_conf.tc_sh == 2)
printk(KERN_WARNING "Unexpected TLB configuration. "
"Will flush I/D separately (could be optimized).\n");
split_tlb = 1;
}
dcache_stride = ( (1<<(cache_info.dc_conf.cc_block+3)) *
cache_info.dc_conf.cc_line );
icache_stride = ( (1<<(cache_info.ic_conf.cc_block+3)) *
cache_info.ic_conf.cc_line );
#ifndef CONFIG_PA20
if(pdc_btlb_info(&btlb_info)<0) { if(pdc_btlb_info(&btlb_info)<0) {
memset(&btlb_info, 0, sizeof btlb_info); memset(&btlb_info, 0, sizeof btlb_info);
} }
#endif #endif
if ((boot_cpu_data.pdc.capabilities & PDC_MODEL_NVA_MASK) == PDC_MODEL_NVA_UNSUPPORTED) {
printk(KERN_WARNING "Only equivalent aliasing supported\n");
#ifndef CONFIG_SMP
panic("SMP kernel required to avoid non-equivalent aliasing");
#endif
}
}
void disable_sr_hashing(void)
{
int srhash_type;
if (boot_cpu_data.cpu_type == pcxl2)
return; /* pcxl2 doesn't support space register hashing */
switch (boot_cpu_data.cpu_type) {
case pcx:
BUG(); /* We shouldn't get here. code in setup.c should prevent it */
return;
case pcxs:
case pcxt:
case pcxt_:
srhash_type = SRHASH_PCXST;
break;
case pcxl:
srhash_type = SRHASH_PCXL;
break;
default: /* Currently all PA2.0 machines use the same ins. sequence */
srhash_type = SRHASH_PA20;
break;
}
disable_sr_hashing_asm(srhash_type);
} }
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
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