Commit c9195267 authored by Anton Blanchard's avatar Anton Blanchard

Merge samba.org:/scratch/anton/linux-2.5

into samba.org:/scratch/anton/linux-2.5_ppc64
parents 278b098b 99b63362
...@@ -23,12 +23,18 @@ if [ "$CONFIG_SMP" = "y" ]; then ...@@ -23,12 +23,18 @@ if [ "$CONFIG_SMP" = "y" ]; then
bool ' Distribute interrupts on all CPUs by default' CONFIG_IRQ_ALL_CPUS bool ' Distribute interrupts on all CPUs by default' CONFIG_IRQ_ALL_CPUS
if [ "$CONFIG_PPC_PSERIES" = "y" ]; then if [ "$CONFIG_PPC_PSERIES" = "y" ]; then
bool ' Hardware multithreading' CONFIG_HMT bool ' Hardware multithreading' CONFIG_HMT
bool ' Discontiguous Memory Support' CONFIG_DISCONTIGMEM
if [ "$CONFIG_DISCONTIGMEM" = "y" ]; then
bool ' NUMA support' CONFIG_NUMA
fi
fi fi
fi fi
define_bool CONFIG_PREEMPT n define_bool CONFIG_PREEMPT n
if [ "$CONFIG_PPC_ISERIES" = "y" ]; then if [ "$CONFIG_PPC_ISERIES" = "y" ]; then
define_bool CONFIG_MSCHUNKS y define_bool CONFIG_MSCHUNKS y
else
tristate ' Firmware flash interface' CONFIG_RTAS_FLASH
fi fi
endmenu endmenu
......
...@@ -37,7 +37,9 @@ CONFIG_PPC64=y ...@@ -37,7 +37,9 @@ CONFIG_PPC64=y
CONFIG_SMP=y CONFIG_SMP=y
CONFIG_IRQ_ALL_CPUS=y CONFIG_IRQ_ALL_CPUS=y
# CONFIG_HMT is not set # CONFIG_HMT is not set
# CONFIG_DISCONTIGMEM is not set
# CONFIG_PREEMPT is not set # CONFIG_PREEMPT is not set
# CONFIG_RTAS_FLASH is not set
# #
# General setup # General setup
...@@ -60,6 +62,7 @@ CONFIG_PCI_NAMES=y ...@@ -60,6 +62,7 @@ CONFIG_PCI_NAMES=y
# #
# CONFIG_PARPORT is not set # CONFIG_PARPORT is not set
CONFIG_PROC_DEVICETREE=y CONFIG_PROC_DEVICETREE=y
# CONFIG_CMDLINE_BOOL is not set
# #
# Memory Technology Devices (MTD) # Memory Technology Devices (MTD)
...@@ -83,6 +86,7 @@ CONFIG_BLK_DEV_FD=y ...@@ -83,6 +86,7 @@ CONFIG_BLK_DEV_FD=y
# CONFIG_BLK_CPQ_CISS_DA is not set # CONFIG_BLK_CPQ_CISS_DA is not set
# CONFIG_CISS_SCSI_TAPE is not set # CONFIG_CISS_SCSI_TAPE is not set
# CONFIG_BLK_DEV_DAC960 is not set # CONFIG_BLK_DEV_DAC960 is not set
# CONFIG_BLK_DEV_UMEM is not set
CONFIG_BLK_DEV_LOOP=y CONFIG_BLK_DEV_LOOP=y
CONFIG_BLK_DEV_NBD=y CONFIG_BLK_DEV_NBD=y
CONFIG_BLK_DEV_RAM=y CONFIG_BLK_DEV_RAM=y
...@@ -364,7 +368,7 @@ CONFIG_IBMOL=y ...@@ -364,7 +368,7 @@ CONFIG_IBMOL=y
# CONFIG_WAN is not set # CONFIG_WAN is not set
# #
# "Tulip" family network device support # Tulip family network device support
# #
# CONFIG_NET_TULIP is not set # CONFIG_NET_TULIP is not set
...@@ -397,7 +401,6 @@ CONFIG_IBMOL=y ...@@ -397,7 +401,6 @@ CONFIG_IBMOL=y
# #
CONFIG_FB=y CONFIG_FB=y
CONFIG_DUMMY_CONSOLE=y CONFIG_DUMMY_CONSOLE=y
# CONFIG_FB_RIVA is not set
# CONFIG_FB_CLGEN is not set # CONFIG_FB_CLGEN is not set
# CONFIG_FB_PM2 is not set # CONFIG_FB_PM2 is not set
# CONFIG_FB_CYBER2000 is not set # CONFIG_FB_CYBER2000 is not set
...@@ -409,6 +412,7 @@ CONFIG_FB_OF=y ...@@ -409,6 +412,7 @@ CONFIG_FB_OF=y
# CONFIG_FB_IMSTT is not set # CONFIG_FB_IMSTT is not set
# CONFIG_FB_S3TRIO is not set # CONFIG_FB_S3TRIO is not set
# CONFIG_FB_VGA16 is not set # CONFIG_FB_VGA16 is not set
# CONFIG_FB_RIVA is not set
CONFIG_FB_MATROX=y CONFIG_FB_MATROX=y
CONFIG_FB_MATROX_MILLENIUM=y CONFIG_FB_MATROX_MILLENIUM=y
CONFIG_FB_MATROX_MYSTIQUE=y CONFIG_FB_MATROX_MYSTIQUE=y
...@@ -422,6 +426,8 @@ CONFIG_FB_MATROX_G100=y ...@@ -422,6 +426,8 @@ CONFIG_FB_MATROX_G100=y
# CONFIG_FB_NEOMAGIC is not set # CONFIG_FB_NEOMAGIC is not set
# CONFIG_FB_3DFX is not set # CONFIG_FB_3DFX is not set
# CONFIG_FB_VOODOO1 is not set # CONFIG_FB_VOODOO1 is not set
# CONFIG_FB_TRIDENT is not set
# CONFIG_FB_PM3 is not set
# CONFIG_FB_VIRTUAL is not set # CONFIG_FB_VIRTUAL is not set
# CONFIG_FBCON_ADVANCED is not set # CONFIG_FBCON_ADVANCED is not set
CONFIG_FBCON_CFB8=y CONFIG_FBCON_CFB8=y
......
...@@ -13,7 +13,6 @@ ...@@ -13,7 +13,6 @@
#include <linux/threads.h> #include <linux/threads.h>
#include <asm/processor.h> #include <asm/processor.h>
#include <asm/ptrace.h> #include <asm/ptrace.h>
#include <asm/init.h>
#include <asm/naca.h> #include <asm/naca.h>
#include <asm/abs_addr.h> #include <asm/abs_addr.h>
#include <asm/bitops.h> #include <asm/bitops.h>
......
...@@ -32,6 +32,8 @@ obj-$(CONFIG_PCI) += pSeries_pci.o pSeries_lpar.o pSeries_hvCall.o eeh.o ...@@ -32,6 +32,8 @@ obj-$(CONFIG_PCI) += pSeries_pci.o pSeries_lpar.o pSeries_hvCall.o eeh.o
obj-y += rtasd.o nvram.o obj-y += rtasd.o nvram.o
endif endif
obj-$(CONFIG_RTAS_FLASH) += rtas_flash.o
obj-$(CONFIG_SMP) += smp.o obj-$(CONFIG_SMP) += smp.o
obj-y += prom.o lmb.o rtas.o rtas-proc.o chrp_setup.o i8259.o obj-y += prom.o lmb.o rtas.o rtas-proc.o chrp_setup.o i8259.o
...@@ -43,6 +45,11 @@ include $(TOPDIR)/Rules.make ...@@ -43,6 +45,11 @@ include $(TOPDIR)/Rules.make
# #
head.o: head.S ppc_defs.h head.o: head.S ppc_defs.h
misc.o: misc.S ppc_defs.h
entry.o: entry.S ppc_defs.h
hvCall.o: hvCall.S ppc_defs.h
pSeries_hvCall.o: pSeries_hvCall.S ppc_defs.h
sys32.o: sys32.S ppc_defs.h
ppc_defs.h: mk_defs.c ppc_defs.head \ ppc_defs.h: mk_defs.c ppc_defs.head \
$(TOPDIR)/include/asm/mmu.h \ $(TOPDIR)/include/asm/mmu.h \
......
...@@ -57,7 +57,6 @@ ...@@ -57,7 +57,6 @@
#include <asm/machdep.h> #include <asm/machdep.h>
#include <asm/irq.h> #include <asm/irq.h>
#include <asm/keyboard.h> #include <asm/keyboard.h>
#include <asm/init.h>
#include <asm/naca.h> #include <asm/naca.h>
#include <asm/time.h> #include <asm/time.h>
...@@ -98,16 +97,10 @@ int fwnmi_active; /* TRUE if an FWNMI handler is present */ ...@@ -98,16 +97,10 @@ int fwnmi_active; /* TRUE if an FWNMI handler is present */
kdev_t boot_dev; kdev_t boot_dev;
unsigned long virtPython0Facilities = 0; // python0 facility area (memory mapped io) (64-bit format) VIRTUAL address. unsigned long virtPython0Facilities = 0; // python0 facility area (memory mapped io) (64-bit format) VIRTUAL address.
extern HPTE *Hash, *Hash_end;
extern unsigned long Hash_size, Hash_mask;
extern int probingmem;
extern unsigned long loops_per_jiffy; extern unsigned long loops_per_jiffy;
#ifdef CONFIG_BLK_DEV_RAM extern unsigned long ppc_proc_freq;
extern int rd_doload; /* 1 = load ramdisk, 0 = don't load */ extern unsigned long ppc_tb_freq;
extern int rd_prompt; /* 1 = prompt for ramdisk, 0 = don't prompt */
extern int rd_image_start; /* starting block # of image */
#endif
void void
chrp_get_cpuinfo(struct seq_file *m) chrp_get_cpuinfo(struct seq_file *m)
...@@ -115,6 +108,8 @@ chrp_get_cpuinfo(struct seq_file *m) ...@@ -115,6 +108,8 @@ chrp_get_cpuinfo(struct seq_file *m)
struct device_node *root; struct device_node *root;
const char *model = ""; const char *model = "";
seq_printf(m, "timebase\t: %lu\n", ppc_tb_freq);
root = find_path_device("/"); root = find_path_device("/");
if (root) if (root)
model = get_property(root, "model", NULL); model = get_property(root, "model", NULL);
...@@ -304,7 +299,7 @@ chrp_init(unsigned long r3, unsigned long r4, unsigned long r5, ...@@ -304,7 +299,7 @@ chrp_init(unsigned long r3, unsigned long r4, unsigned long r5,
ppc_md.progress("Linux ppc64\n", 0x0); ppc_md.progress("Linux ppc64\n", 0x0);
} }
void __chrp void
chrp_progress(char *s, unsigned short hex) chrp_progress(char *s, unsigned short hex)
{ {
struct device_node *root; struct device_node *root;
...@@ -362,9 +357,6 @@ chrp_progress(char *s, unsigned short hex) ...@@ -362,9 +357,6 @@ chrp_progress(char *s, unsigned short hex)
extern void setup_default_decr(void); extern void setup_default_decr(void);
extern unsigned long ppc_proc_freq;
extern unsigned long ppc_tb_freq;
void __init pSeries_calibrate_decr(void) void __init pSeries_calibrate_decr(void)
{ {
struct device_node *cpu; struct device_node *cpu;
......
...@@ -59,15 +59,14 @@ unsigned long eeh_token(unsigned long phb, unsigned long bus, unsigned long devf ...@@ -59,15 +59,14 @@ unsigned long eeh_token(unsigned long phb, unsigned long bus, unsigned long devf
return ((IO_UNMAPPED_REGION_ID << 60) | (phb << 48UL) | ((bus & 0xff) << 40UL) | (devfn << 32UL) | (offset & 0xffffffff)); return ((IO_UNMAPPED_REGION_ID << 60) | (phb << 48UL) | ((bus & 0xff) << 40UL) | (devfn << 32UL) | (offset & 0xffffffff));
} }
int eeh_get_state(unsigned long ea)
{
int eeh_get_state(unsigned long ea) {
return 0; return 0;
} }
/* Check for an eeh failure at the given token address. /* Check for an eeh failure at the given token address.
* The given value has been read and it should be 1's (0xff, 0xffff or 0xffffffff). * The given value has been read and it should be 1's (0xff, 0xffff or
* 0xffffffff).
* *
* Probe to determine if an error actually occurred. If not return val. * Probe to determine if an error actually occurred. If not return val.
* Otherwise panic. * Otherwise panic.
...@@ -113,7 +112,8 @@ unsigned long eeh_check_failure(void *token, unsigned long val) ...@@ -113,7 +112,8 @@ unsigned long eeh_check_failure(void *token, unsigned long val)
return val; /* good case */ return val; /* good case */
} }
void eeh_init(void) { void eeh_init(void)
{
extern char cmd_line[]; /* Very early cmd line parse. Cheap, but works. */ extern char cmd_line[]; /* Very early cmd line parse. Cheap, but works. */
char *eeh_force_off = strstr(cmd_line, "eeh-force-off"); char *eeh_force_off = strstr(cmd_line, "eeh-force-off");
char *eeh_force_on = strstr(cmd_line, "eeh-force-on"); char *eeh_force_on = strstr(cmd_line, "eeh-force-on");
...@@ -121,7 +121,7 @@ void eeh_init(void) { ...@@ -121,7 +121,7 @@ void eeh_init(void) {
ibm_set_eeh_option = rtas_token("ibm,set-eeh-option"); ibm_set_eeh_option = rtas_token("ibm,set-eeh-option");
ibm_set_slot_reset = rtas_token("ibm,set-slot-reset"); ibm_set_slot_reset = rtas_token("ibm,set-slot-reset");
ibm_read_slot_reset_state = rtas_token("ibm,read-slot-reset-state"); ibm_read_slot_reset_state = rtas_token("ibm,read-slot-reset-state");
if (ibm_set_eeh_option != RTAS_UNKNOWN_SERVICE && naca->platform == PLATFORM_PSERIES_LPAR) if (ibm_set_eeh_option != RTAS_UNKNOWN_SERVICE)
eeh_implemented = 1; eeh_implemented = 1;
if (eeh_force_off > eeh_force_on) { if (eeh_force_off > eeh_force_on) {
...@@ -334,6 +334,7 @@ static int __init eehoff_parm(char *str) ...@@ -334,6 +334,7 @@ static int __init eehoff_parm(char *str)
{ {
return eeh_parm(str, 0); return eeh_parm(str, 0);
} }
static int __init eehon_parm(char *str) static int __init eehon_parm(char *str)
{ {
return eeh_parm(str, 1); return eeh_parm(str, 1);
......
...@@ -353,7 +353,7 @@ recheck: ...@@ -353,7 +353,7 @@ recheck:
li r4,0 li r4,0
ori r4,r4,MSR_EE|MSR_RI ori r4,r4,MSR_EE|MSR_RI
andc r10,r10,r4 /* clear MSR_EE and MSR_RI */ andc r10,r10,r4 /* clear MSR_EE and MSR_RI */
mtmsrd r10 /* Update machine state */ mtmsrd r10,1 /* Update machine state */
#ifdef CONFIG_PPC_ISERIES #ifdef CONFIG_PPC_ISERIES
#error fix iSeries soft disable #error fix iSeries soft disable
...@@ -411,7 +411,7 @@ restore: ...@@ -411,7 +411,7 @@ restore:
do_work: do_work:
/* Enable interrupts */ /* Enable interrupts */
ori r10,r10,MSR_EE|MSR_RI ori r10,r10,MSR_EE|MSR_RI
mtmsrd r10 mtmsrd r10,1
andi. r0,r3,_TIF_NEED_RESCHED andi. r0,r3,_TIF_NEED_RESCHED
beq 1f beq 1f
......
...@@ -575,7 +575,8 @@ stab_bolted_user_return: ...@@ -575,7 +575,8 @@ stab_bolted_user_return:
bl .do_stab_SI bl .do_stab_SI
b 1f b 1f
2: bl .do_hash_page_DSI /* Try to handle as hpte fault */ 2: li r5,0x300
bl .do_hash_page_DSI /* Try to handle as hpte fault */
1: 1:
ld r4,_DAR(r1) ld r4,_DAR(r1)
ld r5,_DSISR(r1) ld r5,_DSISR(r1)
...@@ -627,9 +628,8 @@ InstructionAccess_common: ...@@ -627,9 +628,8 @@ InstructionAccess_common:
bl .do_stab_SI bl .do_stab_SI
b 1f b 1f
2: andis. r0,r23,0x4000 /* no pte found? */ 2: mr r3,r22
beq 1f /* if so, try to put a PTE */ li r5,0x400
mr r3,r22 /* into the hash table */
bl .do_hash_page_ISI /* Try to handle as hpte fault */ bl .do_hash_page_ISI /* Try to handle as hpte fault */
1: 1:
mr r4,r22 mr r4,r22
...@@ -804,6 +804,7 @@ _GLOBAL(do_hash_page_DSI) ...@@ -804,6 +804,7 @@ _GLOBAL(do_hash_page_DSI)
/* /*
* r3 contains the faulting address * r3 contains the faulting address
* r4 contains the required access permissions * r4 contains the required access permissions
* r5 contains the trap number
* *
* at return r3 = 0 for success * at return r3 = 0 for success
*/ */
...@@ -852,11 +853,13 @@ _GLOBAL(do_stab_bolted) ...@@ -852,11 +853,13 @@ _GLOBAL(do_stab_bolted)
ld r22,8(r21) /* get SRR1 */ ld r22,8(r21) /* get SRR1 */
andi. r22,r22,MSR_PR /* check if from user */ andi. r22,r22,MSR_PR /* check if from user */
bne+ stab_bolted_user_return /* from user, send the error on up */ bne+ stab_bolted_user_return /* from user, send the error on up */
#if 0
li r3,0 li r3,0
#ifdef CONFIG_XMON #ifdef CONFIG_XMON
bl .xmon bl .xmon
#endif #endif
1: b 1b 1: b 1b
#endif
2: 2:
/* (((ea >> 28) & 0x1fff) << 15) | (ea >> 60) */ /* (((ea >> 28) & 0x1fff) << 15) | (ea >> 60) */
mfspr r21,DAR mfspr r21,DAR
...@@ -1119,7 +1122,7 @@ _GLOBAL(save_remaining_regs) ...@@ -1119,7 +1122,7 @@ _GLOBAL(save_remaining_regs)
rldimi r22,r20,15,48 /* Insert desired EE value */ rldimi r22,r20,15,48 /* Insert desired EE value */
#endif #endif
mtmsrd r22 mtmsrd r22,1
blr blr
......
...@@ -35,7 +35,6 @@ ...@@ -35,7 +35,6 @@
#include <asm/mmu_context.h> #include <asm/mmu_context.h>
#include <asm/page.h> #include <asm/page.h>
#include <asm/types.h> #include <asm/types.h>
#include <asm/init.h>
#include <asm/system.h> #include <asm/system.h>
#include <asm/uaccess.h> #include <asm/uaccess.h>
#include <asm/naca.h> #include <asm/naca.h>
...@@ -45,9 +44,8 @@ ...@@ -45,9 +44,8 @@
#include <asm/lmb.h> #include <asm/lmb.h>
#include <asm/abs_addr.h> #include <asm/abs_addr.h>
#include <asm/tlbflush.h> #include <asm/tlbflush.h>
#ifdef CONFIG_PPC_EEH
#include <asm/eeh.h> #include <asm/eeh.h>
#endif #include <asm/tlb.h>
/* /*
* Note: pte --> Linux PTE * Note: pte --> Linux PTE
...@@ -196,7 +194,7 @@ static inline unsigned long computeHptePP(unsigned long pte) ...@@ -196,7 +194,7 @@ static inline unsigned long computeHptePP(unsigned long pte)
* to be valid via Linux page tables, return 1. If handled return 0 * to be valid via Linux page tables, return 1. If handled return 0
*/ */
int __hash_page(unsigned long ea, unsigned long access, unsigned long vsid, int __hash_page(unsigned long ea, unsigned long access, unsigned long vsid,
pte_t *ptep) pte_t *ptep, unsigned long trap)
{ {
unsigned long va, vpn; unsigned long va, vpn;
unsigned long newpp, prpn; unsigned long newpp, prpn;
...@@ -212,7 +210,7 @@ int __hash_page(unsigned long ea, unsigned long access, unsigned long vsid, ...@@ -212,7 +210,7 @@ int __hash_page(unsigned long ea, unsigned long access, unsigned long vsid,
* If no pte found or not present, send the problem up to * If no pte found or not present, send the problem up to
* do_page_fault * do_page_fault
*/ */
if (!ptep || !pte_present(*ptep)) if (unlikely(!ptep || !pte_present(*ptep)))
return 1; return 1;
/* /*
...@@ -220,7 +218,7 @@ int __hash_page(unsigned long ea, unsigned long access, unsigned long vsid, ...@@ -220,7 +218,7 @@ int __hash_page(unsigned long ea, unsigned long access, unsigned long vsid,
* prevented then send the problem up to do_page_fault. * prevented then send the problem up to do_page_fault.
*/ */
access |= _PAGE_PRESENT; access |= _PAGE_PRESENT;
if (access & ~(pte_val(*ptep))) if (unlikely(access & ~(pte_val(*ptep))))
return 1; return 1;
/* /*
...@@ -245,8 +243,27 @@ int __hash_page(unsigned long ea, unsigned long access, unsigned long vsid, ...@@ -245,8 +243,27 @@ int __hash_page(unsigned long ea, unsigned long access, unsigned long vsid,
newpp = computeHptePP(pte_val(new_pte)); newpp = computeHptePP(pte_val(new_pte));
#define PPC64_HWNOEXEC (1 << 2)
/* We do lazy icache flushing on POWER4 */
if (unlikely(__is_processor(PV_POWER4) &&
pfn_valid(pte_pfn(new_pte)))) {
struct page *page = pte_page(new_pte);
/* page is dirty */
if (!PageReserved(page) &&
!test_bit(PG_arch_1, &page->flags)) {
if (trap == 0x400) {
__flush_dcache_icache(page_address(page));
set_bit(PG_arch_1, &page->flags);
} else {
newpp |= PPC64_HWNOEXEC;
}
}
}
/* Check if pte already has an hpte (case 2) */ /* Check if pte already has an hpte (case 2) */
if (pte_val(old_pte) & _PAGE_HASHPTE) { if (unlikely(pte_val(old_pte) & _PAGE_HASHPTE)) {
/* There MIGHT be an HPTE for this pte */ /* There MIGHT be an HPTE for this pte */
unsigned long hash, slot, secondary; unsigned long hash, slot, secondary;
...@@ -266,7 +283,7 @@ int __hash_page(unsigned long ea, unsigned long access, unsigned long vsid, ...@@ -266,7 +283,7 @@ int __hash_page(unsigned long ea, unsigned long access, unsigned long vsid,
*ptep = new_pte; *ptep = new_pte;
} }
if (!(pte_val(old_pte) & _PAGE_HASHPTE)) { if (likely(!(pte_val(old_pte) & _PAGE_HASHPTE))) {
/* XXX fix large pte flag */ /* XXX fix large pte flag */
unsigned long hash = hpt_hash(vpn, 0); unsigned long hash = hpt_hash(vpn, 0);
unsigned long hpte_group; unsigned long hpte_group;
...@@ -318,7 +335,7 @@ int __hash_page(unsigned long ea, unsigned long access, unsigned long vsid, ...@@ -318,7 +335,7 @@ int __hash_page(unsigned long ea, unsigned long access, unsigned long vsid,
return 0; return 0;
} }
int hash_page(unsigned long ea, unsigned long access) int hash_page(unsigned long ea, unsigned long access, unsigned long trap)
{ {
void *pgdir; void *pgdir;
unsigned long vsid; unsigned long vsid;
...@@ -346,13 +363,11 @@ int hash_page(unsigned long ea, unsigned long access) ...@@ -346,13 +363,11 @@ int hash_page(unsigned long ea, unsigned long access)
mm = &init_mm; mm = &init_mm;
vsid = get_kernel_vsid(ea); vsid = get_kernel_vsid(ea);
break; break;
#ifdef CONFIG_PPC_EEH
case IO_UNMAPPED_REGION_ID: case IO_UNMAPPED_REGION_ID:
udbg_printf("EEH Error ea = 0x%lx\n", ea); udbg_printf("EEH Error ea = 0x%lx\n", ea);
PPCDBG_ENTER_DEBUGGER(); PPCDBG_ENTER_DEBUGGER();
panic("EEH Error ea = 0x%lx\n", ea); panic("EEH Error ea = 0x%lx\n", ea);
break; break;
#endif
case KERNEL_REGION_ID: case KERNEL_REGION_ID:
/* /*
* As htab_initialize is now, we shouldn't ever get here since * As htab_initialize is now, we shouldn't ever get here since
...@@ -379,7 +394,7 @@ int hash_page(unsigned long ea, unsigned long access) ...@@ -379,7 +394,7 @@ int hash_page(unsigned long ea, unsigned long access)
*/ */
spin_lock(&mm->page_table_lock); spin_lock(&mm->page_table_lock);
ptep = find_linux_pte(pgdir, ea); ptep = find_linux_pte(pgdir, ea);
ret = __hash_page(ea, access, vsid, ptep); ret = __hash_page(ea, access, vsid, ptep, trap);
spin_unlock(&mm->page_table_lock); spin_unlock(&mm->page_table_lock);
return ret; return ret;
...@@ -419,12 +434,11 @@ void flush_hash_range(unsigned long context, unsigned long number, int local) ...@@ -419,12 +434,11 @@ void flush_hash_range(unsigned long context, unsigned long number, int local)
ppc_md.flush_hash_range(context, number, local); ppc_md.flush_hash_range(context, number, local);
} else { } else {
int i; int i;
struct tlb_batch_data *ptes = struct ppc64_tlb_batch *batch =
&tlb_batch_array[smp_processor_id()][0]; &ppc64_tlb_batch[smp_processor_id()];
for (i = 0; i < number; i++) { for (i = 0; i < number; i++)
flush_hash_page(context, ptes->addr, ptes->pte, local); flush_hash_page(context, batch->addr[i], batch->pte[i],
ptes++; local);
}
} }
} }
...@@ -21,7 +21,6 @@ ...@@ -21,7 +21,6 @@
* along with this program; if not, write to the Free Software * along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/ */
#include <linux/config.h>
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/list.h> #include <linux/list.h>
#include <linux/string.h> #include <linux/string.h>
......
...@@ -32,7 +32,6 @@ ...@@ -32,7 +32,6 @@
#include <linux/irq.h> #include <linux/irq.h>
#include <asm/io.h> #include <asm/io.h>
#include <asm/init.h>
#include <asm/iSeries/HvCallPci.h> #include <asm/iSeries/HvCallPci.h>
#include <asm/iSeries/HvTypes.h> #include <asm/iSeries/HvTypes.h>
#include <asm/iSeries/mf.h> #include <asm/iSeries/mf.h>
......
...@@ -81,7 +81,7 @@ unsigned long lpEvent_count = 0; ...@@ -81,7 +81,7 @@ unsigned long lpEvent_count = 0;
* this needs to be removed. * this needs to be removed.
* -- Cort * -- Cort
*/ */
#define IRQ_KMALLOC_ENTRIES 8 #define IRQ_KMALLOC_ENTRIES 16
static int cache_bitmask = 0; static int cache_bitmask = 0;
static struct irqaction malloc_cache[IRQ_KMALLOC_ENTRIES]; static struct irqaction malloc_cache[IRQ_KMALLOC_ENTRIES];
extern int mem_init_done; extern int mem_init_done;
...@@ -474,7 +474,9 @@ void ppc_irq_dispatch_handler(struct pt_regs *regs, int irq) ...@@ -474,7 +474,9 @@ void ppc_irq_dispatch_handler(struct pt_regs *regs, int irq)
int cpu = smp_processor_id(); int cpu = smp_processor_id();
irq_desc_t *desc = irq_desc + irq; irq_desc_t *desc = irq_desc + irq;
balance_irq(irq); /* XXX This causes bad performance and lockups on XICS - Anton */
if (naca->interrupt_controller == IC_OPEN_PIC)
balance_irq(irq);
kstat.irqs[cpu][irq]++; kstat.irqs[cpu][irq]++;
spin_lock(&desc->lock); spin_lock(&desc->lock);
......
...@@ -14,7 +14,6 @@ ...@@ -14,7 +14,6 @@
*/ */
#include <stddef.h> #include <stddef.h>
#include <linux/config.h>
#include <linux/signal.h> #include <linux/signal.h>
#include <linux/sched.h> #include <linux/sched.h>
#include <linux/kernel.h> #include <linux/kernel.h>
......
...@@ -33,7 +33,6 @@ void* OpenPIC_Addr; ...@@ -33,7 +33,6 @@ void* OpenPIC_Addr;
static volatile struct OpenPIC *OpenPIC = NULL; static volatile struct OpenPIC *OpenPIC = NULL;
u_int OpenPIC_NumInitSenses __initdata = 0; u_int OpenPIC_NumInitSenses __initdata = 0;
u_char *OpenPIC_InitSenses __initdata = NULL; u_char *OpenPIC_InitSenses __initdata = NULL;
extern int use_of_interrupt_tree;
void find_ISUs(void); void find_ISUs(void);
......
...@@ -20,6 +20,7 @@ ...@@ -20,6 +20,7 @@
#include <asm/mmu_context.h> #include <asm/mmu_context.h>
#include <asm/pgtable.h> #include <asm/pgtable.h>
#include <asm/tlbflush.h> #include <asm/tlbflush.h>
#include <asm/tlb.h>
/* /*
* Create a pte. Used during initialization only. * Create a pte. Used during initialization only.
...@@ -214,7 +215,7 @@ static inline void set_pp_bit(unsigned long pp, HPTE *addr) ...@@ -214,7 +215,7 @@ static inline void set_pp_bit(unsigned long pp, HPTE *addr)
__asm__ __volatile__( __asm__ __volatile__(
"1: ldarx %0,0,%3\n\ "1: ldarx %0,0,%3\n\
rldimi %0,%2,0,62\n\ rldimi %0,%2,0,61\n\
stdcx. %0,0,%3\n\ stdcx. %0,0,%3\n\
bne 1b" bne 1b"
: "=&r" (old), "=m" (*p) : "=&r" (old), "=m" (*p)
...@@ -265,8 +266,6 @@ static long pSeries_hpte_updatepp(unsigned long slot, unsigned long newpp, ...@@ -265,8 +266,6 @@ static long pSeries_hpte_updatepp(unsigned long slot, unsigned long newpp,
unsigned long vpn, avpn; unsigned long vpn, avpn;
unsigned long flags; unsigned long flags;
udbg_printf("updatepp\n");
if (large) if (large)
vpn = va >> LARGE_PAGE_SHIFT; vpn = va >> LARGE_PAGE_SHIFT;
else else
...@@ -372,31 +371,32 @@ static void pSeries_flush_hash_range(unsigned long context, ...@@ -372,31 +371,32 @@ static void pSeries_flush_hash_range(unsigned long context,
{ {
unsigned long vsid, vpn, va, hash, secondary, slot, flags, avpn; unsigned long vsid, vpn, va, hash, secondary, slot, flags, avpn;
int i, j; int i, j;
unsigned long va_array[MAX_BATCH_FLUSH];
HPTE *hptep; HPTE *hptep;
Hpte_dword0 dw0; Hpte_dword0 dw0;
struct tlb_batch_data *ptes = &tlb_batch_array[smp_processor_id()][0]; struct ppc64_tlb_batch *batch = &ppc64_tlb_batch[smp_processor_id()];
/* XXX fix for large ptes */ /* XXX fix for large ptes */
unsigned long large = 0; unsigned long large = 0;
j = 0; j = 0;
for (i = 0; i < number; i++) { for (i = 0; i < number; i++) {
if ((ptes->addr >= USER_START) && (ptes->addr <= USER_END)) if ((batch->addr[i] >= USER_START) &&
vsid = get_vsid(context, ptes->addr); (batch->addr[i] <= USER_END))
vsid = get_vsid(context, batch->addr[i]);
else else
vsid = get_kernel_vsid(ptes->addr); vsid = get_kernel_vsid(batch->addr[i]);
va = (vsid << 28) | (ptes->addr & 0x0fffffff); va = (vsid << 28) | (batch->addr[i] & 0x0fffffff);
va_array[j] = va; batch->vaddr[j] = va;
if (large) if (large)
vpn = va >> LARGE_PAGE_SHIFT; vpn = va >> LARGE_PAGE_SHIFT;
else else
vpn = va >> PAGE_SHIFT; vpn = va >> PAGE_SHIFT;
hash = hpt_hash(vpn, large); hash = hpt_hash(vpn, large);
secondary = (pte_val(ptes->pte) & _PAGE_SECONDARY) >> 15; secondary = (pte_val(batch->pte[i]) & _PAGE_SECONDARY) >> 15;
if (secondary) if (secondary)
hash = ~hash; hash = ~hash;
slot = (hash & htab_data.htab_hash_mask) * HPTES_PER_GROUP; slot = (hash & htab_data.htab_hash_mask) * HPTES_PER_GROUP;
slot += (pte_val(ptes->pte) & _PAGE_GROUP_IX) >> 12; slot += (pte_val(batch->pte[i]) & _PAGE_GROUP_IX) >> 12;
hptep = htab_data.htab + slot; hptep = htab_data.htab + slot;
avpn = vpn >> 11; avpn = vpn >> 11;
...@@ -405,8 +405,6 @@ static void pSeries_flush_hash_range(unsigned long context, ...@@ -405,8 +405,6 @@ static void pSeries_flush_hash_range(unsigned long context,
dw0 = hptep->dw0.dw0; dw0 = hptep->dw0.dw0;
ptes++;
if ((dw0.avpn != avpn) || !dw0.v) { if ((dw0.avpn != avpn) || !dw0.v) {
pSeries_unlock_hpte(hptep); pSeries_unlock_hpte(hptep);
udbg_printf("invalidate missed\n"); udbg_printf("invalidate missed\n");
...@@ -426,7 +424,7 @@ static void pSeries_flush_hash_range(unsigned long context, ...@@ -426,7 +424,7 @@ static void pSeries_flush_hash_range(unsigned long context,
asm volatile("\n\ asm volatile("\n\
clrldi %0,%0,16\n\ clrldi %0,%0,16\n\
tlbiel %0" tlbiel %0"
: : "r" (va_array[i]) : "memory" ); : : "r" (batch->vaddr[i]) : "memory" );
} }
asm volatile("ptesync":::"memory"); asm volatile("ptesync":::"memory");
...@@ -440,7 +438,7 @@ static void pSeries_flush_hash_range(unsigned long context, ...@@ -440,7 +438,7 @@ static void pSeries_flush_hash_range(unsigned long context,
asm volatile("\n\ asm volatile("\n\
clrldi %0,%0,16\n\ clrldi %0,%0,16\n\
tlbie %0" tlbie %0"
: : "r" (va_array[i]) : "memory" ); : : "r" (batch->vaddr[i]) : "memory" );
} }
asm volatile("eieio; tlbsync; ptesync":::"memory"); asm volatile("eieio; tlbsync; ptesync":::"memory");
......
...@@ -33,6 +33,7 @@ ...@@ -33,6 +33,7 @@
#include <linux/pci.h> #include <linux/pci.h>
#include <asm/naca.h> #include <asm/naca.h>
#include <asm/tlbflush.h> #include <asm/tlbflush.h>
#include <asm/tlb.h>
/* Status return values */ /* Status return values */
#define H_Success 0 #define H_Success 0
...@@ -646,11 +647,9 @@ static long pSeries_lpar_hpte_updatepp(unsigned long slot, unsigned long newpp, ...@@ -646,11 +647,9 @@ static long pSeries_lpar_hpte_updatepp(unsigned long slot, unsigned long newpp,
{ {
unsigned long lpar_rc; unsigned long lpar_rc;
unsigned long flags; unsigned long flags;
flags = (newpp & 3) | H_AVPN; flags = (newpp & 7) | H_AVPN;
unsigned long vpn = va >> PAGE_SHIFT; unsigned long vpn = va >> PAGE_SHIFT;
udbg_printf("updatepp\n");
lpar_rc = plpar_pte_protect(flags, slot, (vpn >> 4) & ~0x7fUL); lpar_rc = plpar_pte_protect(flags, slot, (vpn >> 4) & ~0x7fUL);
if (lpar_rc == H_Not_Found) { if (lpar_rc == H_Not_Found) {
...@@ -775,15 +774,14 @@ void pSeries_lpar_flush_hash_range(unsigned long context, unsigned long number, ...@@ -775,15 +774,14 @@ void pSeries_lpar_flush_hash_range(unsigned long context, unsigned long number,
int local) int local)
{ {
int i; int i;
struct tlb_batch_data *ptes =
&tlb_batch_array[smp_processor_id()][0];
unsigned long flags; unsigned long flags;
struct ppc64_tlb_batch *batch = &ppc64_tlb_batch[smp_processor_id()];
spin_lock_irqsave(&pSeries_lpar_tlbie_lock, flags); spin_lock_irqsave(&pSeries_lpar_tlbie_lock, flags);
for (i = 0; i < number; i++) {
flush_hash_page(context, ptes->addr, ptes->pte, local); for (i = 0; i < number; i++)
ptes++; flush_hash_page(context, batch->addr[i], batch->pte[i], local);
}
spin_unlock_irqrestore(&pSeries_lpar_tlbie_lock, flags); spin_unlock_irqrestore(&pSeries_lpar_tlbie_lock, flags);
} }
......
...@@ -22,7 +22,6 @@ ...@@ -22,7 +22,6 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/ */
#include <linux/config.h>
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/threads.h> #include <linux/threads.h>
#include <linux/pci.h> #include <linux/pci.h>
...@@ -36,7 +35,6 @@ ...@@ -36,7 +35,6 @@
#include <asm/irq.h> #include <asm/irq.h>
#include <asm/prom.h> #include <asm/prom.h>
#include <asm/machdep.h> #include <asm/machdep.h>
#include <asm/init.h>
#include <asm/pci-bridge.h> #include <asm/pci-bridge.h>
#include <asm/ppcdebug.h> #include <asm/ppcdebug.h>
#include <asm/naca.h> #include <asm/naca.h>
...@@ -71,7 +69,7 @@ static int s7a_workaround; ...@@ -71,7 +69,7 @@ static int s7a_workaround;
* *
*****************************************************************************/ *****************************************************************************/
#define RTAS_PCI_READ_OP(size, type, nbytes) \ #define RTAS_PCI_READ_OP(size, type, nbytes) \
int __chrp \ int \
rtas_read_config_##size(struct device_node *dn, int offset, type val) { \ rtas_read_config_##size(struct device_node *dn, int offset, type val) { \
unsigned long returnval = ~0L; \ unsigned long returnval = ~0L; \
unsigned long buid; \ unsigned long buid; \
...@@ -96,7 +94,7 @@ rtas_read_config_##size(struct device_node *dn, int offset, type val) { \ ...@@ -96,7 +94,7 @@ rtas_read_config_##size(struct device_node *dn, int offset, type val) { \
*val = returnval; \ *val = returnval; \
return ret; \ return ret; \
} \ } \
int __chrp \ int \
rtas_pci_read_config_##size(struct pci_dev *dev, int offset, type val) { \ rtas_pci_read_config_##size(struct pci_dev *dev, int offset, type val) { \
struct device_node *dn = pci_device_to_OF_node(dev); \ struct device_node *dn = pci_device_to_OF_node(dev); \
int ret = rtas_read_config_##size(dn, offset, val); \ int ret = rtas_read_config_##size(dn, offset, val); \
...@@ -105,7 +103,7 @@ rtas_pci_read_config_##size(struct pci_dev *dev, int offset, type val) { \ ...@@ -105,7 +103,7 @@ rtas_pci_read_config_##size(struct pci_dev *dev, int offset, type val) { \
} }
#define RTAS_PCI_WRITE_OP(size, type, nbytes) \ #define RTAS_PCI_WRITE_OP(size, type, nbytes) \
int __chrp \ int \
rtas_write_config_##size(struct device_node *dn, int offset, type val) { \ rtas_write_config_##size(struct device_node *dn, int offset, type val) { \
unsigned long buid; \ unsigned long buid; \
unsigned int addr; \ unsigned int addr; \
...@@ -126,7 +124,7 @@ rtas_write_config_##size(struct device_node *dn, int offset, type val) { \ ...@@ -126,7 +124,7 @@ rtas_write_config_##size(struct device_node *dn, int offset, type val) { \
} \ } \
return ret; \ return ret; \
} \ } \
int __chrp \ int \
rtas_pci_write_config_##size(struct pci_dev *dev, int offset, type val) { \ rtas_pci_write_config_##size(struct pci_dev *dev, int offset, type val) { \
struct device_node* dn = pci_device_to_OF_node(dev); \ struct device_node* dn = pci_device_to_OF_node(dev); \
int ret = rtas_write_config_##size(dn, offset, val); \ int ret = rtas_write_config_##size(dn, offset, val); \
......
...@@ -33,7 +33,6 @@ ...@@ -33,7 +33,6 @@
#include <asm/irq.h> #include <asm/irq.h>
#include <asm/prom.h> #include <asm/prom.h>
#include <asm/machdep.h> #include <asm/machdep.h>
#include <asm/init.h>
#include <asm/pci-bridge.h> #include <asm/pci-bridge.h>
#include <asm/ppcdebug.h> #include <asm/ppcdebug.h>
#include <asm/naca.h> #include <asm/naca.h>
......
...@@ -11,8 +11,6 @@ ...@@ -11,8 +11,6 @@
* 2 of the License, or (at your option) any later version. * 2 of the License, or (at your option) any later version.
*/ */
#include <linux/config.h>
#include <asm/ppc_asm.tmpl> #include <asm/ppc_asm.tmpl>
#include "ppc_defs.h" #include "ppc_defs.h"
......
...@@ -24,6 +24,10 @@ ...@@ -24,6 +24,10 @@
* End Change Activity * End Change Activity
*/ */
#include <linux/config.h>
#include <linux/proc_fs.h>
#include <linux/spinlock.h>
#include <asm/proc_fs.h> #include <asm/proc_fs.h>
#include <asm/paca.h> #include <asm/paca.h>
#include <asm/iSeries/ItLpPaca.h> #include <asm/iSeries/ItLpPaca.h>
...@@ -33,12 +37,10 @@ ...@@ -33,12 +37,10 @@
#include <asm/processor.h> #include <asm/processor.h>
#include <asm/time.h> #include <asm/time.h>
#include <asm/iSeries/LparData.h> #include <asm/iSeries/LparData.h>
#include <linux/proc_fs.h>
#include <linux/spinlock.h>
#include <asm/pmc.h> #include <asm/pmc.h>
#include <asm/uaccess.h> #include <asm/uaccess.h>
#include <asm/naca.h> #include <asm/naca.h>
#include <asm/rtas.h>
static int proc_pmc_control_mode = 0; static int proc_pmc_control_mode = 0;
...@@ -100,9 +102,9 @@ void proc_ppc64_init(void) ...@@ -100,9 +102,9 @@ void proc_ppc64_init(void)
if (!proc_ppc64_root) return; if (!proc_ppc64_root) return;
spin_unlock(&proc_ppc64_lock); spin_unlock(&proc_ppc64_lock);
#ifdef CONFIG_PPC_EEH /* Placeholder for rtas interfaces. */
eeh_init_proc(proc_ppc64_root); rtas_proc_dir = proc_mkdir("rtas", proc_ppc64_root);
#endif
proc_ppc64_pmc_root = proc_mkdir("pmc", proc_ppc64_root); proc_ppc64_pmc_root = proc_mkdir("pmc", proc_ppc64_root);
...@@ -324,6 +326,7 @@ void pmc_proc_init(struct proc_dir_entry *iSeries_proc) ...@@ -324,6 +326,7 @@ void pmc_proc_init(struct proc_dir_entry *iSeries_proc)
if (!ent) return; if (!ent) return;
ent->nlink = 1; ent->nlink = 1;
ent->data = (void *)0; ent->data = (void *)0;
ent->size = 0;
ent->read_proc = proc_get_titanTod; ent->read_proc = proc_get_titanTod;
ent->write_proc = NULL; ent->write_proc = NULL;
......
...@@ -44,8 +44,6 @@ ...@@ -44,8 +44,6 @@
#include <asm/machdep.h> #include <asm/machdep.h>
#include <asm/iSeries/HvCallHpt.h> #include <asm/iSeries/HvCallHpt.h>
int dump_fpu(struct pt_regs *regs, elf_fpregset_t *fpregs);
struct task_struct *last_task_used_math = NULL; struct task_struct *last_task_used_math = NULL;
struct mm_struct ioremap_mm = { pgd : ioremap_dir struct mm_struct ioremap_mm = { pgd : ioremap_dir
......
...@@ -48,7 +48,6 @@ ...@@ -48,7 +48,6 @@
#define call_yaboot(FUNC,...) do { ; } while (0) #define call_yaboot(FUNC,...) do { ; } while (0)
#endif #endif
#include <asm/init.h>
#include <linux/types.h> #include <linux/types.h>
#include <linux/pci.h> #include <linux/pci.h>
#include <asm/prom.h> #include <asm/prom.h>
...@@ -2110,7 +2109,7 @@ find_type_devices(const char *type) ...@@ -2110,7 +2109,7 @@ find_type_devices(const char *type)
/* /*
* Returns all nodes linked together * Returns all nodes linked together
*/ */
struct device_node * __openfirmware struct device_node *
find_all_nodes(void) find_all_nodes(void)
{ {
struct device_node *head, **prevp, *np; struct device_node *head, **prevp, *np;
...@@ -2235,7 +2234,7 @@ get_property(struct device_node *np, const char *name, int *lenp) ...@@ -2235,7 +2234,7 @@ get_property(struct device_node *np, const char *name, int *lenp)
/* /*
* Add a property to a node * Add a property to a node
*/ */
void __openfirmware void
prom_add_property(struct device_node* np, struct property* prop) prom_add_property(struct device_node* np, struct property* prop)
{ {
struct property **next = &np->properties; struct property **next = &np->properties;
...@@ -2247,7 +2246,7 @@ prom_add_property(struct device_node* np, struct property* prop) ...@@ -2247,7 +2246,7 @@ prom_add_property(struct device_node* np, struct property* prop)
} }
#if 0 #if 0
void __openfirmware void
print_properties(struct device_node *np) print_properties(struct device_node *np)
{ {
struct property *pp; struct property *pp;
......
/* /*
* linux/arch/ppc/kernel/ptrace.c * linux/arch/ppc64/kernel/ptrace.c
* *
* PowerPC version * PowerPC version
* Copyright (C) 1995-1996 Gary Thomas (gdt@linuxppc.org) * Copyright (C) 1995-1996 Gary Thomas (gdt@linuxppc.org)
...@@ -30,59 +30,13 @@ ...@@ -30,59 +30,13 @@
#include <asm/page.h> #include <asm/page.h>
#include <asm/pgtable.h> #include <asm/pgtable.h>
#include <asm/system.h> #include <asm/system.h>
#include <asm/ptrace-common.h>
/*
* Set of msr bits that gdb can change on behalf of a process.
*/
#define MSR_DEBUGCHANGE (MSR_FE0 | MSR_SE | MSR_BE | MSR_FE1)
/* /*
* does not yet catch signals sent when the child dies. * does not yet catch signals sent when the child dies.
* in exit.c or in signal.c. * in exit.c or in signal.c.
*/ */
/*
* Get contents of register REGNO in task TASK.
*/
static inline unsigned long get_reg(struct task_struct *task, int regno)
{
if (regno < sizeof(struct pt_regs) / sizeof(unsigned long))
return ((unsigned long *)task->thread.regs)[regno];
return (0);
}
/*
* Write contents of register REGNO in task TASK.
*/
static inline int put_reg(struct task_struct *task, int regno,
unsigned long data)
{
if (regno < PT_SOFTE) {
if (regno == PT_MSR)
data = (data & MSR_DEBUGCHANGE)
| (task->thread.regs->msr & ~MSR_DEBUGCHANGE);
((unsigned long *)task->thread.regs)[regno] = data;
return 0;
}
return -EIO;
}
static inline void
set_single_step(struct task_struct *task)
{
struct pt_regs *regs = task->thread.regs;
if (regs != NULL)
regs->msr |= MSR_SE;
}
static inline void
clear_single_step(struct task_struct *task)
{
struct pt_regs *regs = task->thread.regs;
if (regs != NULL)
regs->msr &= ~MSR_SE;
}
/* /*
* Called by kernel/ptrace.c when detaching.. * Called by kernel/ptrace.c when detaching..
* *
...@@ -148,16 +102,17 @@ int sys_ptrace(long request, long pid, long addr, long data) ...@@ -148,16 +102,17 @@ int sys_ptrace(long request, long pid, long addr, long data)
/* read the word at location addr in the USER area. */ /* read the word at location addr in the USER area. */
case PTRACE_PEEKUSR: { case PTRACE_PEEKUSR: {
unsigned long index, tmp; unsigned long index;
unsigned long tmp;
ret = -EIO; ret = -EIO;
/* convert to index and check */ /* convert to index and check */
index = (unsigned long) addr >> 3; index = (unsigned long) addr >> 3;
if ((addr & 7) || index > PT_FPSCR) if ((addr & 7) || (index > PT_FPSCR))
break; break;
if (index < PT_FPR0) { if (index < PT_FPR0) {
tmp = get_reg(child, (int) index); tmp = get_reg(child, (int)index);
} else { } else {
if (child->thread.regs->msr & MSR_FP) if (child->thread.regs->msr & MSR_FP)
giveup_fpu(child); giveup_fpu(child);
...@@ -171,7 +126,8 @@ int sys_ptrace(long request, long pid, long addr, long data) ...@@ -171,7 +126,8 @@ int sys_ptrace(long request, long pid, long addr, long data)
case PTRACE_POKETEXT: /* write the word at location addr. */ case PTRACE_POKETEXT: /* write the word at location addr. */
case PTRACE_POKEDATA: case PTRACE_POKEDATA:
ret = 0; ret = 0;
if (access_process_vm(child, addr, &data, sizeof(data), 1) == sizeof(data)) if (access_process_vm(child, addr, &data, sizeof(data), 1)
== sizeof(data))
break; break;
ret = -EIO; ret = -EIO;
break; break;
...@@ -183,7 +139,7 @@ int sys_ptrace(long request, long pid, long addr, long data) ...@@ -183,7 +139,7 @@ int sys_ptrace(long request, long pid, long addr, long data)
ret = -EIO; ret = -EIO;
/* convert to index and check */ /* convert to index and check */
index = (unsigned long) addr >> 3; index = (unsigned long) addr >> 3;
if ((addr & 7) || index > PT_FPSCR) if ((addr & 7) || (index > PT_FPSCR))
break; break;
if (index == PT_ORIG_R3) if (index == PT_ORIG_R3)
...@@ -216,11 +172,11 @@ int sys_ptrace(long request, long pid, long addr, long data) ...@@ -216,11 +172,11 @@ int sys_ptrace(long request, long pid, long addr, long data)
break; break;
} }
/* /*
* make the child exit. Best I can do is send it a sigkill. * make the child exit. Best I can do is send it a sigkill.
* perhaps it should be put in the status that it wants to * perhaps it should be put in the status that it wants to
* exit. * exit.
*/ */
case PTRACE_KILL: { case PTRACE_KILL: {
ret = 0; ret = 0;
if (child->state == TASK_ZOMBIE) /* already dead */ if (child->state == TASK_ZOMBIE) /* already dead */
...@@ -249,56 +205,50 @@ int sys_ptrace(long request, long pid, long addr, long data) ...@@ -249,56 +205,50 @@ int sys_ptrace(long request, long pid, long addr, long data)
ret = ptrace_detach(child, data); ret = ptrace_detach(child, data);
break; break;
case PPC_PTRACE_GETREGS: case PPC_PTRACE_GETREGS: { /* Get GPRs 0 - 31. */
{ /* Get GPRs 0 - 31. */
u64 tmp; u64 tmp;
u64 cntr; u64 cntr;
ret = 0; ret = 0;
for (cntr=0; cntr<32 && ret==0; ++cntr) for (cntr=0; cntr<32 && ret==0; ++cntr) {
{
tmp = ((u64*)child->thread.regs)[cntr]; tmp = ((u64*)child->thread.regs)[cntr];
ret = put_user(tmp, (u64*)(data+cntr)); ret = put_user(tmp, (u64*)(data+cntr));
} }
break; break;
} }
case PPC_PTRACE_SETREGS: case PPC_PTRACE_SETREGS: { /* Set GPRs 0 - 31. */
{ /* Set GPRs 0 - 31. */
u64 cntr; u64 cntr;
ret = 0; ret = 0;
for (cntr=0; cntr<32 && ret==0; ++cntr) for (cntr=0; cntr<32 && ret==0; ++cntr)
{
ret = put_reg(child, cntr, *(u64*)(data+cntr)); ret = put_reg(child, cntr, *(u64*)(data+cntr));
}
break; break;
} }
case PPC_PTRACE_GETFPREGS: case PPC_PTRACE_GETFPREGS: { /* Get FPRs 0 - 31. */
{ /* Get FPRs 0 - 31. */
u64 tmp; u64 tmp;
u64 cntr; u64 cntr;
ret = -EIO; ret = -EIO;
if (child->thread.regs->msr & MSR_FP) if (child->thread.regs->msr & MSR_FP)
giveup_fpu(child); giveup_fpu(child);
ret = 0; ret = 0;
for (cntr=0; cntr<32 && ret==0; ++cntr) for (cntr=0; cntr<32 && ret==0; ++cntr) {
{
tmp = ((u64*)child->thread.fpr)[cntr]; tmp = ((u64*)child->thread.fpr)[cntr];
ret = put_user(tmp, (u64*)(data+cntr)); ret = put_user(tmp, (u64*)(data+cntr));
} }
break; break;
} }
case PPC_PTRACE_SETFPREGS: case PPC_PTRACE_SETFPREGS: { /* Get FPRs 0 - 31. */
{ /* Get FPRs 0 - 31. */
u64 cntr; u64 cntr;
ret = -EIO; ret = -EIO;
if (child->thread.regs->msr & MSR_FP) if (child->thread.regs->msr & MSR_FP)
giveup_fpu(child); giveup_fpu(child);
for (cntr=0; cntr<32; ++cntr) for (cntr=0; cntr<32; ++cntr)
{
((u64*)child->thread.fpr)[cntr] = *(u64*)(data+cntr); ((u64*)child->thread.fpr)[cntr] = *(u64*)(data+cntr);
}
ret = 0; ret = 0;
break; break;
} }
...@@ -334,4 +284,3 @@ void do_syscall_trace(void) ...@@ -334,4 +284,3 @@ void do_syscall_trace(void)
current->exit_code = 0; current->exit_code = 0;
} }
} }
/* /*
* linux/arch/ppc/kernel/ptrace32.c * linux/arch/ppc64/kernel/ptrace32.c
* *
* PowerPC version * PowerPC version
* Copyright (C) 1995-1996 Gary Thomas (gdt@linuxppc.org) * Copyright (C) 1995-1996 Gary Thomas (gdt@linuxppc.org)
...@@ -30,64 +30,18 @@ ...@@ -30,64 +30,18 @@
#include <asm/page.h> #include <asm/page.h>
#include <asm/pgtable.h> #include <asm/pgtable.h>
#include <asm/system.h> #include <asm/system.h>
#include <asm/ptrace-common.h>
/*
* Set of msr bits that gdb can change on behalf of a process.
*/
#define MSR_DEBUGCHANGE (MSR_FE0 | MSR_SE | MSR_BE | MSR_FE1)
/* /*
* does not yet catch signals sent when the child dies. * does not yet catch signals sent when the child dies.
* in exit.c or in signal.c. * in exit.c or in signal.c.
*/ */
/*
* Get contents of register REGNO in task TASK.
*/
static inline unsigned long get_reg(struct task_struct *task, int regno)
{
if (regno < sizeof(struct pt_regs) / sizeof(unsigned long))
return ((unsigned long *)task->thread.regs)[regno];
return (0);
}
/*
* Write contents of register REGNO in task TASK.
* (Put DATA into task TASK's register REGNO.)
*/
static inline int put_reg(struct task_struct *task, int regno, unsigned long data)
{
if (regno < PT_SOFTE)
{
if (regno == PT_MSR)
data = (data & MSR_DEBUGCHANGE) | (task->thread.regs->msr & ~MSR_DEBUGCHANGE);
((unsigned long *)task->thread.regs)[regno] = data;
return 0;
}
return -EIO;
}
static inline void
set_single_step(struct task_struct *task)
{
struct pt_regs *regs = task->thread.regs;
if (regs != NULL)
regs->msr |= MSR_SE;
}
static inline void
clear_single_step(struct task_struct *task)
{
struct pt_regs *regs = task->thread.regs;
if (regs != NULL)
regs->msr &= ~MSR_SE;
}
int sys32_ptrace(long request, long pid, unsigned long addr, unsigned long data) int sys32_ptrace(long request, long pid, unsigned long addr, unsigned long data)
{ {
struct task_struct *child; struct task_struct *child;
int ret = -EPERM; int ret = -EPERM;
lock_kernel(); lock_kernel();
if (request == PTRACE_TRACEME) { if (request == PTRACE_TRACEME) {
/* are we already being traced? */ /* are we already being traced? */
...@@ -120,92 +74,95 @@ int sys32_ptrace(long request, long pid, unsigned long addr, unsigned long data) ...@@ -120,92 +74,95 @@ int sys32_ptrace(long request, long pid, unsigned long addr, unsigned long data)
if (ret < 0) if (ret < 0)
goto out_tsk; goto out_tsk;
switch (request) switch (request) {
{
/* Read word at location ADDR */
/* when I and D space are separate, these will need to be fixed. */ /* when I and D space are separate, these will need to be fixed. */
case PTRACE_PEEKTEXT: /* read word at location addr. */ case PTRACE_PEEKTEXT: /* read word at location addr. */
case PTRACE_PEEKDATA: case PTRACE_PEEKDATA: {
{ unsigned int tmp;
unsigned int tmp_mem_value;
int copied; int copied;
copied = access_process_vm(child, addr, &tmp_mem_value, sizeof(tmp_mem_value), 0); copied = access_process_vm(child, addr, &tmp, sizeof(tmp), 0);
ret = -EIO; ret = -EIO;
if (copied != sizeof(tmp_mem_value)) if (copied != sizeof(tmp))
break; break;
ret = put_user(tmp_mem_value, (u32*)data); // copy 4 bytes of data into the user location specified by the 8 byte pointer in "data". ret = put_user(tmp, (u32*)data);
break; break;
} }
/* Read 4 bytes of the other process' storage */ /*
/* data is a pointer specifying where the user wants the 4 bytes copied into */ * Read 4 bytes of the other process' storage
/* addr is a pointer in the user's storage that contains an 8 byte address in the other process of the 4 bytes that is to be read */ * data is a pointer specifying where the user wants the
/* (this is run in a 32-bit process looking at a 64-bit process) */ * 4 bytes copied into
/* when I and D space are separate, these will need to be fixed. */ * addr is a pointer in the user's storage that contains an 8 byte
* address in the other process of the 4 bytes that is to be read
* (this is run in a 32-bit process looking at a 64-bit process)
* when I and D space are separate, these will need to be fixed.
*/
case PPC_PTRACE_PEEKTEXT_3264: case PPC_PTRACE_PEEKTEXT_3264:
case PPC_PTRACE_PEEKDATA_3264: case PPC_PTRACE_PEEKDATA_3264: {
{ u32 tmp;
u32 tmp_mem_value; int copied;
int copied;
u32* addrOthers; u32* addrOthers;
ret = -EIO; ret = -EIO;
/* Get the addr in the other process that we want to read */ /* Get the addr in the other process that we want to read */
if (get_user(addrOthers,(u32**)addr) != 0) if (get_user(addrOthers, (u32**)addr) != 0)
break; break;
copied = access_process_vm(child, (u64)addrOthers, &tmp_mem_value, sizeof(tmp_mem_value), 0); copied = access_process_vm(child, (u64)addrOthers, &tmp,
if (copied != sizeof(tmp_mem_value)) sizeof(tmp), 0);
if (copied != sizeof(tmp))
break; break;
ret = put_user(tmp_mem_value, (u32*)data); // copy 4 bytes of data into the user location specified by the 8 byte pointer in "data". ret = put_user(tmp, (u32*)data);
break; break;
} }
/* Read a register (specified by ADDR) out of the "user area" */ /* Read a register (specified by ADDR) out of the "user area" */
case PTRACE_PEEKUSR: { case PTRACE_PEEKUSR: {
int index; int index;
unsigned int reg32bits; unsigned long tmp;
unsigned long tmp_reg_value;
ret = -EIO; ret = -EIO;
/* convert to index and check */ /* convert to index and check */
index = (unsigned long) addr >> 2; index = (unsigned long) addr >> 2;
if ((addr & 3) || index > PT_FPSCR32) if ((addr & 3) || (index > PT_FPSCR32))
break; break;
if (index < PT_FPR0) { if (index < PT_FPR0) {
tmp_reg_value = get_reg(child, index); tmp = get_reg(child, index);
} else { } else {
if (child->thread.regs->msr & MSR_FP) if (child->thread.regs->msr & MSR_FP)
giveup_fpu(child); giveup_fpu(child);
/* the user space code considers the floating point to be /*
* an array of unsigned int (32 bits) - the index passed * the user space code considers the floating point
* in is based on this assumption. * to be an array of unsigned int (32 bits) - the
* index passed in is based on this assumption.
*/ */
tmp_reg_value = ((unsigned int *)child->thread.fpr)[index - PT_FPR0]; tmp = ((unsigned int *)child->thread.fpr)[index - PT_FPR0];
} }
reg32bits = tmp_reg_value; ret = put_user((unsigned int)tmp, (u32*)data);
ret = put_user(reg32bits, (u32*)data); // copy 4 bytes of data into the user location specified by the 8 byte pointer in "data".
break; break;
} }
/* Read 4 bytes out of the other process' pt_regs area */ /*
/* data is a pointer specifying where the user wants the 4 bytes copied into */ * Read 4 bytes out of the other process' pt_regs area
/* addr is the offset into the other process' pt_regs structure that is to be read */ * data is a pointer specifying where the user wants the
/* (this is run in a 32-bit process looking at a 64-bit process) */ * 4 bytes copied into
case PPC_PTRACE_PEEKUSR_3264: * addr is the offset into the other process' pt_regs structure
{ * that is to be read
* (this is run in a 32-bit process looking at a 64-bit process)
*/
case PPC_PTRACE_PEEKUSR_3264: {
u32 index; u32 index;
u32 reg32bits; u32 reg32bits;
u64 tmp_reg_value; u64 tmp;
u32 numReg; u32 numReg;
u32 part; u32 part;
ret = -EIO; ret = -EIO;
/* Determine which register the user wants */ /* Determine which register the user wants */
index = (u64)addr >> 2; /* Divide addr by 4 */ index = (u64)addr >> 2;
numReg = index / 2; numReg = index / 2;
/* Determine which part of the register the user wants */ /* Determine which part of the register the user wants */
if (index % 2) if (index % 2)
...@@ -217,117 +174,120 @@ int sys32_ptrace(long request, long pid, unsigned long addr, unsigned long data) ...@@ -217,117 +174,120 @@ int sys32_ptrace(long request, long pid, unsigned long addr, unsigned long data)
if ((addr & 3) || numReg > PT_FPSCR) if ((addr & 3) || numReg > PT_FPSCR)
break; break;
if (numReg >= PT_FPR0) if (numReg >= PT_FPR0) {
{
if (child->thread.regs->msr & MSR_FP) if (child->thread.regs->msr & MSR_FP)
giveup_fpu(child); giveup_fpu(child);
} if (numReg == PT_FPSCR)
tmp_reg_value = get_reg(child, numReg); tmp = ((unsigned int *)child->thread.fpscr);
reg32bits = ((u32*)&tmp_reg_value)[part]; else
ret = put_user(reg32bits, (u32*)data); /* copy 4 bytes of data into the user location specified by the 8 byte pointer in "data". */ tmp = ((unsigned long int *)child->thread.fpr)[numReg - PT_FPR0];
} else { /* register within PT_REGS struct */
tmp = get_reg(child, numReg);
}
reg32bits = ((u32*)&tmp)[part];
ret = put_user(reg32bits, (u32*)data);
break; break;
} }
/* Write the word at location ADDR */
/* If I and D space are separate, this will have to be fixed. */ /* If I and D space are separate, this will have to be fixed. */
case PTRACE_POKETEXT: /* write the word at location addr. */ case PTRACE_POKETEXT: /* write the word at location addr. */
case PTRACE_POKEDATA: { case PTRACE_POKEDATA: {
unsigned int tmp_value_to_write; unsigned int tmp;
tmp_value_to_write = data; tmp = data;
ret = 0; ret = 0;
if (access_process_vm(child, addr, &tmp_value_to_write, sizeof(tmp_value_to_write), 1) == sizeof(tmp_value_to_write)) if (access_process_vm(child, addr, &tmp, sizeof(tmp), 1)
== sizeof(tmp))
break; break;
ret = -EIO; ret = -EIO;
break; break;
} }
/* Write 4 bytes into the other process' storage */ /*
/* data is the 4 bytes that the user wants written */ * Write 4 bytes into the other process' storage
/* addr is a pointer in the user's storage that contains an 8 byte address in the other process where the 4 bytes that is to be written */ * data is the 4 bytes that the user wants written
/* (this is run in a 32-bit process looking at a 64-bit process) */ * addr is a pointer in the user's storage that contains an
/* when I and D space are separate, these will need to be fixed. */ * 8 byte address in the other process where the 4 bytes
* that is to be written
* (this is run in a 32-bit process looking at a 64-bit process)
* when I and D space are separate, these will need to be fixed.
*/
case PPC_PTRACE_POKETEXT_3264: case PPC_PTRACE_POKETEXT_3264:
case PPC_PTRACE_POKEDATA_3264: case PPC_PTRACE_POKEDATA_3264: {
{ u32 tmp = data;
u32 tmp_value_to_write = data;
u32* addrOthers; u32* addrOthers;
int bytesWritten;
/* Get the addr in the other process that we want to write into */ /* Get the addr in the other process that we want to write into */
ret = -EIO; ret = -EIO;
if (get_user(addrOthers,(u32**)addr) != 0) if (get_user(addrOthers, (u32**)addr) != 0)
break; break;
ret = 0; ret = 0;
bytesWritten = access_process_vm(child, (u64)addrOthers, &tmp_value_to_write, sizeof(tmp_value_to_write), 1); if (access_process_vm(child, (u64)addrOthers, &tmp,
if (bytesWritten == sizeof(tmp_value_to_write)) sizeof(tmp), 1) == sizeof(tmp))
break; break;
ret = -EIO; ret = -EIO;
break; break;
} }
/* Write DATA into location ADDR within the USER area */ /* write the word at location addr in the USER area */
case PTRACE_POKEUSR: { case PTRACE_POKEUSR: {
unsigned long index; unsigned long index;
ret = -EIO; ret = -EIO;
/* convert to index and check */ /* convert to index and check */
index = (unsigned long) addr >> 2; index = (unsigned long) addr >> 2;
if ((addr & 3) || index > PT_FPSCR32) if ((addr & 3) || (index > PT_FPSCR32))
break; break;
if (index == PT_ORIG_R3) if (index == PT_ORIG_R3)
break; break;
if (index < PT_FPR0) { if (index < PT_FPR0) {
ret = put_reg(child, index, data); ret = put_reg(child, index, data);
} else { } else {
if (child->thread.regs->msr & MSR_FP) if (child->thread.regs->msr & MSR_FP)
giveup_fpu(child); giveup_fpu(child);
/* the user space code considers the floating point to be /*
* an array of unsigned int (32 bits) - the index passed * the user space code considers the floating point
* in is based on this assumption. * to be an array of unsigned int (32 bits) - the
*/ * index passed in is based on this assumption.
*/
((unsigned int *)child->thread.fpr)[index - PT_FPR0] = data; ((unsigned int *)child->thread.fpr)[index - PT_FPR0] = data;
ret = 0; ret = 0;
} }
break; break;
} }
/* Write 4 bytes into the other process' pt_regs area */ /*
/* data is the 4 bytes that the user wants written */ * Write 4 bytes into the other process' pt_regs area
/* addr is the offset into the other process' pt_regs structure that is to be written into */ * data is the 4 bytes that the user wants written
/* (this is run in a 32-bit process looking at a 64-bit process) */ * addr is the offset into the other process' pt_regs structure
case PPC_PTRACE_POKEUSR_3264: * that is to be written into
{ * (this is run in a 32-bit process looking at a 64-bit process)
*/
case PPC_PTRACE_POKEUSR_3264: {
u32 index; u32 index;
u32 numReg; u32 numReg;
ret = -EIO; ret = -EIO;
/* Determine which register the user wants */ /* Determine which register the user wants */
index = (u64)addr >> 2; /* Divide addr by 4 */ index = (u64)addr >> 2;
numReg = index / 2; numReg = index / 2;
/*
/* Validate the input - check to see if address is on the wrong boundary or beyond the end of the user area */ * Validate the input - check to see if address is on the
if ((addr & 3) || numReg > PT_FPSCR) * wrong boundary or beyond the end of the user area
*/
if ((addr & 3) || (numReg > PT_FPSCR))
break; break;
/* Insure it is a register we let them change */ /* Insure it is a register we let them change */
if ((numReg == PT_ORIG_R3) || ((numReg > PT_CCR) && (numReg < PT_FPR0))) if ((numReg == PT_ORIG_R3)
|| ((numReg > PT_CCR) && (numReg < PT_FPR0)))
break; break;
if (numReg >= PT_FPR0) {
if (numReg >= PT_FPR0)
{
if (child->thread.regs->msr & MSR_FP) if (child->thread.regs->msr & MSR_FP)
giveup_fpu(child); giveup_fpu(child);
} }
if (numReg == PT_MSR) if (numReg == PT_MSR)
data = (data & MSR_DEBUGCHANGE) | (child->thread.regs->msr & ~MSR_DEBUGCHANGE); data = (data & MSR_DEBUGCHANGE)
| (child->thread.regs->msr & ~MSR_DEBUGCHANGE);
((u32*)child->thread.regs)[index] = data; ((u32*)child->thread.regs)[index] = data;
ret = 0; ret = 0;
break; break;
...@@ -351,8 +311,8 @@ int sys32_ptrace(long request, long pid, unsigned long addr, unsigned long data) ...@@ -351,8 +311,8 @@ int sys32_ptrace(long request, long pid, unsigned long addr, unsigned long data)
} }
/* /*
* make the child exit. Best I can do is send it a sigkill. * make the child exit. Best I can do is send it a sigkill.
* perhaps it should be put in the status that it wants to * perhaps it should be put in the status that it wants to
* exit. * exit.
*/ */
case PTRACE_KILL: { case PTRACE_KILL: {
......
...@@ -16,15 +16,19 @@ ...@@ -16,15 +16,19 @@
#include <linux/types.h> #include <linux/types.h>
#include <linux/spinlock.h> #include <linux/spinlock.h>
#include <asm/init.h>
#include <asm/prom.h> #include <asm/prom.h>
#include <asm/rtas.h> #include <asm/rtas.h>
#include <asm/semaphore.h>
#include <asm/machdep.h> #include <asm/machdep.h>
#include <asm/paca.h> #include <asm/paca.h>
#include <asm/page.h> #include <asm/page.h>
#include <asm/system.h> #include <asm/system.h>
#include <asm/abs_addr.h>
#include <asm/udbg.h> #include <asm/udbg.h>
struct proc_dir_entry *rtas_proc_dir; /* /proc/ppc64/rtas dir */
struct flash_block_list_header rtas_firmware_flash_list = {0, 0};
/* /*
* prom_init() is called very early on, before the kernel text * prom_init() is called very early on, before the kernel text
* and data have been mapped to KERNELBASE. At this point the code * and data have been mapped to KERNELBASE. At this point the code
...@@ -105,7 +109,6 @@ call_rtas_display_status(char c) ...@@ -105,7 +109,6 @@ call_rtas_display_status(char c)
#if 0 #if 0
#define DEBUG_RTAS #define DEBUG_RTAS
#endif #endif
__openfirmware
int int
rtas_token(const char *service) rtas_token(const char *service)
{ {
...@@ -120,7 +123,6 @@ rtas_token(const char *service) ...@@ -120,7 +123,6 @@ rtas_token(const char *service)
return tokp ? *tokp : RTAS_UNKNOWN_SERVICE; return tokp ? *tokp : RTAS_UNKNOWN_SERVICE;
} }
__openfirmware
long long
rtas_call(int token, int nargs, int nret, rtas_call(int token, int nargs, int nret,
unsigned long *outputs, ...) unsigned long *outputs, ...)
...@@ -184,25 +186,107 @@ rtas_call(int token, int nargs, int nret, ...@@ -184,25 +186,107 @@ rtas_call(int token, int nargs, int nret,
return (ulong)((nret > 0) ? rtas_args->rets[0] : 0); return (ulong)((nret > 0) ? rtas_args->rets[0] : 0);
} }
void __chrp #define FLASH_BLOCK_LIST_VERSION (1UL)
static void
rtas_flash_firmware(void)
{
unsigned long image_size;
struct flash_block_list *f, *next, *flist;
unsigned long rtas_block_list;
int i, status, update_token;
update_token = rtas_token("ibm,update-flash-64-and-reboot");
if (update_token == RTAS_UNKNOWN_SERVICE) {
printk(KERN_ALERT "FLASH: ibm,update-flash-64-and-reboot is not available -- not a service partition?\n");
printk(KERN_ALERT "FLASH: firmware will not be flashed\n");
return;
}
/* NOTE: the "first" block list is a global var with no data
* blocks in the kernel data segment. We do this because
* we want to ensure this block_list addr is under 4GB.
*/
rtas_firmware_flash_list.num_blocks = 0;
flist = (struct flash_block_list *)&rtas_firmware_flash_list;
rtas_block_list = virt_to_absolute((unsigned long)flist);
if (rtas_block_list >= (4UL << 20)) {
printk(KERN_ALERT "FLASH: kernel bug...flash list header addr above 4GB\n");
return;
}
printk(KERN_ALERT "FLASH: preparing saved firmware image for flash\n");
/* Update the block_list in place. */
image_size = 0;
for (f = flist; f; f = next) {
/* Translate data addrs to absolute */
for (i = 0; i < f->num_blocks; i++) {
f->blocks[i].data = (char *)virt_to_absolute((unsigned long)f->blocks[i].data);
image_size += f->blocks[i].length;
}
next = f->next;
f->next = (struct flash_block_list *)virt_to_absolute((unsigned long)f->next);
/* make num_blocks into the version/length field */
f->num_blocks = (FLASH_BLOCK_LIST_VERSION << 56) | ((f->num_blocks+1)*16);
}
printk(KERN_ALERT "FLASH: flash image is %ld bytes\n", image_size);
printk(KERN_ALERT "FLASH: performing flash and reboot\n");
ppc_md.progress("Flashing \n", 0x0);
ppc_md.progress("Please Wait... ", 0x0);
printk(KERN_ALERT "FLASH: this will take several minutes. Do not power off!\n");
status = rtas_call(update_token, 1, 1, NULL, rtas_block_list);
switch (status) { /* should only get "bad" status */
case 0:
printk(KERN_ALERT "FLASH: success\n");
break;
case -1:
printk(KERN_ALERT "FLASH: hardware error. Firmware may not be not flashed\n");
break;
case -3:
printk(KERN_ALERT "FLASH: image is corrupt or not correct for this platform. Firmware not flashed\n");
break;
case -4:
printk(KERN_ALERT "FLASH: flash failed when partially complete. System may not reboot\n");
break;
default:
printk(KERN_ALERT "FLASH: unknown flash return code %d\n", status);
break;
}
}
void rtas_flash_bypass_warning(void)
{
printk(KERN_ALERT "FLASH: firmware flash requires a reboot\n");
printk(KERN_ALERT "FLASH: the firmware image will NOT be flashed\n");
}
void
rtas_restart(char *cmd) rtas_restart(char *cmd)
{ {
if (rtas_firmware_flash_list.next)
rtas_flash_firmware();
printk("RTAS system-reboot returned %ld\n", printk("RTAS system-reboot returned %ld\n",
rtas_call(rtas_token("system-reboot"), 0, 1, NULL)); rtas_call(rtas_token("system-reboot"), 0, 1, NULL));
for (;;); for (;;);
} }
void __chrp void
rtas_power_off(void) rtas_power_off(void)
{ {
if (rtas_firmware_flash_list.next)
rtas_flash_bypass_warning();
/* allow power on only with power button press */ /* allow power on only with power button press */
printk("RTAS power-off returned %ld\n", printk("RTAS power-off returned %ld\n",
rtas_call(rtas_token("power-off"), 2, 1, NULL,0xffffffff,0xffffffff)); rtas_call(rtas_token("power-off"), 2, 1, NULL,0xffffffff,0xffffffff));
for (;;); for (;;);
} }
void __chrp void
rtas_halt(void) rtas_halt(void)
{ {
if (rtas_firmware_flash_list.next)
rtas_flash_bypass_warning();
rtas_power_off(); rtas_power_off();
} }
/*
* c 2001 PPC 64 Team, IBM Corp
*
* 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 the Free Software Foundation; either version
* 2 of the License, or (at your option) any later version.
*
* /proc/ppc64/rtas/firmware_flash interface
*
* This file implements a firmware_flash interface to pump a firmware
* image into the kernel. At reboot time rtas_restart() will see the
* firmware image and flash it as it reboots (see rtas.c).
*/
#include <linux/module.h>
#include <linux/config.h>
#include <linux/proc_fs.h>
#include <linux/init.h>
#include <asm/uaccess.h>
#include <asm/rtas.h>
#define MODULE_VERSION "1.0"
#define MODULE_NAME "rtas_flash"
#define FIRMWARE_FLASH_NAME "firmware_flash"
/* Local copy of the flash block list.
* We only allow one open of the flash proc file and create this
* list as we go. This list will be put in the kernel's
* rtas_firmware_flash_list global var once it is fully read.
*
* For convenience as we build the list we use virtual addrs,
* we do not fill in the version number, and the length field
* is treated as the number of entries currently in the block
* (i.e. not a byte count). This is all fixed on release.
*/
static struct flash_block_list *flist;
static char *flash_msg;
static int flash_possible;
static int rtas_flash_open(struct inode *inode, struct file *file)
{
if ((file->f_mode & FMODE_WRITE) && flash_possible) {
if (flist)
return -EBUSY;
flist = (struct flash_block_list *)get_free_page(GFP_KERNEL);
if (!flist)
return -ENOMEM;
}
return 0;
}
/* Do simple sanity checks on the flash image. */
static int flash_list_valid(struct flash_block_list *flist)
{
struct flash_block_list *f;
int i;
unsigned long block_size, image_size;
flash_msg = NULL;
/* Paranoid self test here. We also collect the image size. */
image_size = 0;
for (f = flist; f; f = f->next) {
for (i = 0; i < f->num_blocks; i++) {
if (f->blocks[i].data == NULL) {
flash_msg = "error: internal error null data\n";
return 0;
}
block_size = f->blocks[i].length;
if (block_size <= 0 || block_size > PAGE_SIZE) {
flash_msg = "error: internal error bad length\n";
return 0;
}
image_size += block_size;
}
}
if (image_size < (256 << 10)) {
if (image_size < 2)
flash_msg = NULL; /* allow "clear" of image */
else
flash_msg = "error: flash image short\n";
return 0;
}
printk(KERN_INFO "FLASH: flash image with %ld bytes stored for hardware flash on reboot\n", image_size);
return 1;
}
static void free_flash_list(struct flash_block_list *f)
{
struct flash_block_list *next;
int i;
while (f) {
for (i = 0; i < f->num_blocks; i++)
free_page((unsigned long)(f->blocks[i].data));
next = f->next;
free_page((unsigned long)f);
f = next;
}
}
static int rtas_flash_release(struct inode *inode, struct file *file)
{
if (flist) {
/* Always clear saved list on a new attempt. */
if (rtas_firmware_flash_list.next) {
free_flash_list(rtas_firmware_flash_list.next);
rtas_firmware_flash_list.next = NULL;
}
if (flash_list_valid(flist))
rtas_firmware_flash_list.next = flist;
else
free_flash_list(flist);
flist = NULL;
}
return 0;
}
/* Reading the proc file will show status (not the firmware contents) */
static ssize_t rtas_flash_read(struct file *file, char *buf,
size_t count, loff_t *ppos)
{
int error;
char *msg;
int msglen;
if (!flash_possible) {
msg = "error: this partition does not have service authority\n";
} else if (flist) {
msg = "info: this file is busy for write by some process\n";
} else if (flash_msg) {
msg = flash_msg; /* message from last flash attempt */
} else if (rtas_firmware_flash_list.next) {
msg = "ready: firmware image ready for flash on reboot\n";
} else {
msg = "info: no firmware image for flash\n";
}
msglen = strlen(msg);
if (msglen > count)
msglen = count;
if (ppos && *ppos != 0)
return 0; /* be cheap */
error = verify_area(VERIFY_WRITE, buf, msglen);
if (error)
return -EINVAL;
copy_to_user(buf, msg, msglen);
if (ppos)
*ppos = msglen;
return msglen;
}
/* We could be much more efficient here. But to keep this function
* simple we allocate a page to the block list no matter how small the
* count is. If the system is low on memory it will be just as well
* that we fail....
*/
static ssize_t rtas_flash_write(struct file *file, const char *buffer,
size_t count, loff_t *off)
{
size_t len = count;
char *p;
int next_free;
struct flash_block_list *fl = flist;
if (!flash_possible || len == 0)
return len; /* discard data */
while (fl->next)
fl = fl->next; /* seek to last block_list for append */
next_free = fl->num_blocks;
if (next_free == FLASH_BLOCKS_PER_NODE) {
/* Need to allocate another block_list */
fl->next = (struct flash_block_list *)get_free_page(GFP_KERNEL);
if (!fl->next)
return -ENOMEM;
fl = fl->next;
next_free = 0;
}
if (len > PAGE_SIZE)
len = PAGE_SIZE;
p = (char *)get_free_page(GFP_KERNEL);
if (!p)
return -ENOMEM;
if(copy_from_user(p, buffer, len)) {
free_page((unsigned long)p);
return -EFAULT;
}
fl->blocks[next_free].data = p;
fl->blocks[next_free].length = len;
fl->num_blocks++;
return len;
}
static struct file_operations rtas_flash_operations = {
read: rtas_flash_read,
write: rtas_flash_write,
open: rtas_flash_open,
release: rtas_flash_release,
};
int __init rtas_flash_init(void)
{
struct proc_dir_entry *ent = NULL;
if (!rtas_proc_dir) {
printk(KERN_WARNING "rtas proc dir does not already exist");
return -ENOENT;
}
if (rtas_token("ibm,update-flash-64-and-reboot") != RTAS_UNKNOWN_SERVICE)
flash_possible = 1;
if ((ent = create_proc_entry(FIRMWARE_FLASH_NAME, S_IRUSR | S_IWUSR, rtas_proc_dir)) != NULL) {
ent->nlink = 1;
ent->proc_fops = &rtas_flash_operations;
ent->owner = THIS_MODULE;
}
return 0;
}
void __exit rtas_flash_cleanup(void)
{
if (!rtas_proc_dir)
return;
remove_proc_entry(FIRMWARE_FLASH_NAME, rtas_proc_dir);
}
module_init(rtas_flash_init);
module_exit(rtas_flash_cleanup);
MODULE_LICENSE("GPL");
...@@ -23,7 +23,6 @@ ...@@ -23,7 +23,6 @@
#include <linux/ioport.h> #include <linux/ioport.h>
#include <linux/tty.h> #include <linux/tty.h>
#include <linux/root_dev.h> #include <linux/root_dev.h>
#include <asm/init.h>
#include <asm/io.h> #include <asm/io.h>
#include <asm/prom.h> #include <asm/prom.h>
#include <asm/processor.h> #include <asm/processor.h>
...@@ -43,9 +42,6 @@ extern unsigned long klimit; ...@@ -43,9 +42,6 @@ extern unsigned long klimit;
extern HTAB htab_data; extern HTAB htab_data;
extern unsigned long loops_per_jiffy; extern unsigned long loops_per_jiffy;
extern unsigned long embedded_sysmap_start;
extern unsigned long embedded_sysmap_end;
int have_of = 1; int have_of = 1;
extern void chrp_init(unsigned long r3, extern void chrp_init(unsigned long r3,
...@@ -54,7 +50,6 @@ extern void chrp_init(unsigned long r3, ...@@ -54,7 +50,6 @@ extern void chrp_init(unsigned long r3,
unsigned long r6, unsigned long r6,
unsigned long r7); unsigned long r7);
extern void chrp_init_map_io_space( void );
extern void iSeries_init( void ); extern void iSeries_init( void );
extern void iSeries_init_early( void ); extern void iSeries_init_early( void );
extern void pSeries_init_early( void ); extern void pSeries_init_early( void );
...@@ -338,7 +333,7 @@ static int show_cpuinfo(struct seq_file *m, void *v) ...@@ -338,7 +333,7 @@ static int show_cpuinfo(struct seq_file *m, void *v)
if (ppc_md.setup_residual != NULL) if (ppc_md.setup_residual != NULL)
ppc_md.setup_residual(m, cpu_id); ppc_md.setup_residual(m, cpu_id);
seq_printf(m, "revision\t: %hd.%hd\n", maj, min); seq_printf(m, "revision\t: %hd.%hd\n\n", maj, min);
return 0; return 0;
} }
...@@ -499,6 +494,7 @@ void __init ppc64_calibrate_delay(void) ...@@ -499,6 +494,7 @@ void __init ppc64_calibrate_delay(void)
} }
extern void (*calibrate_delay)(void); extern void (*calibrate_delay)(void);
extern void sort_exception_table(void);
/* /*
* Called into from start_kernel, after lock_kernel has been called. * Called into from start_kernel, after lock_kernel has been called.
......
...@@ -26,8 +26,6 @@ ...@@ -26,8 +26,6 @@
#include <linux/unistd.h> #include <linux/unistd.h>
#include <linux/stddef.h> #include <linux/stddef.h>
#include <linux/elf.h> #include <linux/elf.h>
#include <linux/tty.h>
#include <linux/binfmts.h>
#include <asm/ppc32.h> #include <asm/ppc32.h>
#include <asm/sigcontext.h> #include <asm/sigcontext.h>
#include <asm/ucontext.h> #include <asm/ucontext.h>
...@@ -59,9 +57,36 @@ ...@@ -59,9 +57,36 @@
*/ */
#define MSR_USERCHANGE (MSR_FE0 | MSR_FE1) #define MSR_USERCHANGE (MSR_FE0 | MSR_FE1)
int do_signal(sigset_t *oldset, struct pt_regs *regs); /*
extern long sys_wait4(pid_t pid, unsigned int *stat_addr, * When we have signals to deliver, we set up on the
int options, /*unsigned long*/ struct rusage *ru); * user stack, going down from the original stack pointer:
* a sigregs struct
* one or more sigcontext structs with
* a gap of __SIGNAL_FRAMESIZE bytes
*
* Each of these things must be a multiple of 16 bytes in size.
*
*/
struct sigregs {
elf_gregset_t gp_regs;
double fp_regs[ELF_NFPREG];
unsigned int tramp[2];
/* 64 bit API allows for 288 bytes below sp before
decrementing it. */
int abigap[72];
};
struct rt_sigframe
{
unsigned long _unused[2];
struct siginfo *pinfo;
void *puc;
struct siginfo info;
struct ucontext uc;
};
extern int do_signal(sigset_t *oldset, struct pt_regs *regs);
/* /*
* Atomically swap in the new signal mask, and wait for a signal. * Atomically swap in the new signal mask, and wait for a signal.
...@@ -127,7 +152,7 @@ long sys_rt_sigsuspend(sigset_t *unewset, size_t sigsetsize, int p3, int p4, int ...@@ -127,7 +152,7 @@ long sys_rt_sigsuspend(sigset_t *unewset, size_t sigsetsize, int p3, int p4, int
long sys_sigaltstack(const stack_t *uss, stack_t *uoss) long sys_sigaltstack(const stack_t *uss, stack_t *uoss)
{ {
struct pt_regs *regs = (struct pt_regs *) &uss; struct pt_regs *regs = (struct pt_regs *)&uss;
return do_sigaltstack(uss, uoss, regs->gpr[1]); return do_sigaltstack(uss, uoss, regs->gpr[1]);
} }
...@@ -139,6 +164,7 @@ long sys_sigaction(int sig, const struct old_sigaction *act, ...@@ -139,6 +164,7 @@ long sys_sigaction(int sig, const struct old_sigaction *act,
if (act) { if (act) {
old_sigset_t mask; old_sigset_t mask;
if (verify_area(VERIFY_READ, act, sizeof(*act)) || if (verify_area(VERIFY_READ, act, sizeof(*act)) ||
__get_user(new_ka.sa.sa_handler, &act->sa_handler) || __get_user(new_ka.sa.sa_handler, &act->sa_handler) ||
__get_user(new_ka.sa.sa_restorer, &act->sa_restorer)) __get_user(new_ka.sa.sa_restorer, &act->sa_restorer))
...@@ -148,8 +174,7 @@ long sys_sigaction(int sig, const struct old_sigaction *act, ...@@ -148,8 +174,7 @@ long sys_sigaction(int sig, const struct old_sigaction *act,
siginitset(&new_ka.sa.sa_mask, mask); siginitset(&new_ka.sa.sa_mask, mask);
} }
ret = do_sigaction(sig, (act? &new_ka: NULL), (oact? &old_ka: NULL)); ret = do_sigaction(sig, act ? &new_ka : NULL, oact ? &old_ka : NULL);
if (!ret && oact) { if (!ret && oact) {
if (verify_area(VERIFY_WRITE, oact, sizeof(*oact)) || if (verify_area(VERIFY_WRITE, oact, sizeof(*oact)) ||
__put_user(old_ka.sa.sa_handler, &oact->sa_handler) || __put_user(old_ka.sa.sa_handler, &oact->sa_handler) ||
...@@ -162,35 +187,6 @@ long sys_sigaction(int sig, const struct old_sigaction *act, ...@@ -162,35 +187,6 @@ long sys_sigaction(int sig, const struct old_sigaction *act,
return ret; return ret;
} }
/*
* When we have signals to deliver, we set up on the
* user stack, going down from the original stack pointer:
* a sigregs struct
* one or more sigcontext structs with
* a gap of __SIGNAL_FRAMESIZE bytes
*
* Each of these things must be a multiple of 16 bytes in size.
*
*/
struct sigregs {
elf_gregset_t gp_regs;
double fp_regs[ELF_NFPREG];
unsigned int tramp[2];
/* 64 bit API allows for 288 bytes below sp before
decrementing it. */
int abigap[72];
};
struct rt_sigframe
{
unsigned long _unused[2];
struct siginfo *pinfo;
void *puc;
struct siginfo info;
struct ucontext uc;
};
/* /*
* When we have rt signals to deliver, we set up on the * When we have rt signals to deliver, we set up on the
* user stack, going down from the original stack pointer: * user stack, going down from the original stack pointer:
...@@ -231,7 +227,7 @@ int sys_rt_sigreturn(unsigned long r3, unsigned long r4, unsigned long r5, ...@@ -231,7 +227,7 @@ int sys_rt_sigreturn(unsigned long r3, unsigned long r4, unsigned long r5,
* preamble frame (where registers are stored) * preamble frame (where registers are stored)
* see handle_signal() * see handle_signal()
*/ */
sr = (struct sigregs *) sigctx.regs; sr = (struct sigregs *)sigctx.regs;
if (copy_from_user(saved_regs, &sr->gp_regs, sizeof(sr->gp_regs))) if (copy_from_user(saved_regs, &sr->gp_regs, sizeof(sr->gp_regs)))
goto badframe; goto badframe;
saved_regs[PT_MSR] = (regs->msr & ~MSR_USERCHANGE) saved_regs[PT_MSR] = (regs->msr & ~MSR_USERCHANGE)
...@@ -251,11 +247,10 @@ int sys_rt_sigreturn(unsigned long r3, unsigned long r4, unsigned long r5, ...@@ -251,11 +247,10 @@ int sys_rt_sigreturn(unsigned long r3, unsigned long r4, unsigned long r5,
do_exit(SIGSEGV); do_exit(SIGSEGV);
} }
static void static void setup_rt_frame(struct pt_regs *regs, struct sigregs *frame,
setup_rt_frame(struct pt_regs *regs, struct sigregs *frame,
signed long newsp) signed long newsp)
{ {
struct rt_sigframe *rt_sf = (struct rt_sigframe *) newsp; struct rt_sigframe *rt_sf = (struct rt_sigframe *)newsp;
/* Handler is *really* a pointer to the function descriptor for /* Handler is *really* a pointer to the function descriptor for
* the signal routine. The first entry in the function * the signal routine. The first entry in the function
* descriptor is the entry address of signal and the second * descriptor is the entry address of signal and the second
...@@ -277,11 +272,13 @@ setup_rt_frame(struct pt_regs *regs, struct sigregs *frame, ...@@ -277,11 +272,13 @@ setup_rt_frame(struct pt_regs *regs, struct sigregs *frame,
if (__copy_to_user(&frame->gp_regs, regs, GP_REGS_SIZE) if (__copy_to_user(&frame->gp_regs, regs, GP_REGS_SIZE)
|| __copy_to_user(&frame->fp_regs, current->thread.fpr, || __copy_to_user(&frame->fp_regs, current->thread.fpr,
ELF_NFPREG * sizeof(double)) ELF_NFPREG * sizeof(double))
|| __put_user(0x38000000UL + __NR_rt_sigreturn, &frame->tramp[0]) /* li r0, __NR_rt_sigreturn */ /* li r0, __NR_rt_sigreturn */
|| __put_user(0x44000002UL, &frame->tramp[1])) /* sc */ || __put_user(0x38000000UL + __NR_rt_sigreturn, &frame->tramp[0])
/* sc */
|| __put_user(0x44000002UL, &frame->tramp[1]))
goto badframe; goto badframe;
flush_icache_range((unsigned long) &frame->tramp[0], flush_icache_range((unsigned long)&frame->tramp[0],
(unsigned long) &frame->tramp[2]); (unsigned long)&frame->tramp[2]);
current->thread.fpscr = 0; /* turn off all fp exceptions */ current->thread.fpscr = 0; /* turn off all fp exceptions */
/* Retrieve rt_sigframe from stack and /* Retrieve rt_sigframe from stack and
...@@ -289,11 +286,11 @@ setup_rt_frame(struct pt_regs *regs, struct sigregs *frame, ...@@ -289,11 +286,11 @@ setup_rt_frame(struct pt_regs *regs, struct sigregs *frame,
*/ */
newsp -= __SIGNAL_FRAMESIZE; newsp -= __SIGNAL_FRAMESIZE;
if ( get_user(temp_ptr, &rt_sf->uc.uc_mcontext.handler)) { if (get_user(temp_ptr, &rt_sf->uc.uc_mcontext.handler)) {
goto badframe; goto badframe;
} }
funct_desc_ptr = ( struct funct_descr_entry *) temp_ptr; funct_desc_ptr = (struct funct_descr_entry *)temp_ptr;
if (put_user(regs->gpr[1], (unsigned long *)newsp) if (put_user(regs->gpr[1], (unsigned long *)newsp)
|| get_user(regs->nip, &funct_desc_ptr->entry) || get_user(regs->nip, &funct_desc_ptr->entry)
...@@ -304,8 +301,8 @@ setup_rt_frame(struct pt_regs *regs, struct sigregs *frame, ...@@ -304,8 +301,8 @@ setup_rt_frame(struct pt_regs *regs, struct sigregs *frame,
goto badframe; goto badframe;
regs->gpr[1] = newsp; regs->gpr[1] = newsp;
regs->gpr[6] = (unsigned long) rt_sf; regs->gpr[6] = (unsigned long)rt_sf;
regs->link = (unsigned long) frame->tramp; regs->link = (unsigned long)frame->tramp;
return; return;
...@@ -342,11 +339,11 @@ long sys_sigreturn(unsigned long r3, unsigned long r4, unsigned long r5, ...@@ -342,11 +339,11 @@ long sys_sigreturn(unsigned long r3, unsigned long r4, unsigned long r5,
current->blocked = set; current->blocked = set;
recalc_sigpending(); recalc_sigpending();
spin_unlock_irq(&current->sigmask_lock); spin_unlock_irq(&current->sigmask_lock);
if (regs->msr & MSR_FP ) if (regs->msr & MSR_FP)
giveup_fpu(current); giveup_fpu(current);
/* restore registers */ /* restore registers */
sr = (struct sigregs *) sigctx.regs; sr = (struct sigregs *)sigctx.regs;
if (copy_from_user(saved_regs, &sr->gp_regs, sizeof(sr->gp_regs))) if (copy_from_user(saved_regs, &sr->gp_regs, sizeof(sr->gp_regs)))
goto badframe; goto badframe;
saved_regs[PT_MSR] = (regs->msr & ~MSR_USERCHANGE) saved_regs[PT_MSR] = (regs->msr & ~MSR_USERCHANGE)
...@@ -367,8 +364,7 @@ long sys_sigreturn(unsigned long r3, unsigned long r4, unsigned long r5, ...@@ -367,8 +364,7 @@ long sys_sigreturn(unsigned long r3, unsigned long r4, unsigned long r5,
/* /*
* Set up a signal frame. * Set up a signal frame.
*/ */
static void static void setup_frame(struct pt_regs *regs, struct sigregs *frame,
setup_frame(struct pt_regs *regs, struct sigregs *frame,
unsigned long newsp) unsigned long newsp)
{ {
...@@ -385,7 +381,7 @@ setup_frame(struct pt_regs *regs, struct sigregs *frame, ...@@ -385,7 +381,7 @@ setup_frame(struct pt_regs *regs, struct sigregs *frame,
struct funct_descr_entry * funct_desc_ptr; struct funct_descr_entry * funct_desc_ptr;
unsigned long temp_ptr; unsigned long temp_ptr;
struct sigcontext_struct *sc = (struct sigcontext_struct *) newsp; struct sigcontext_struct *sc = (struct sigcontext_struct *)newsp;
if (verify_area(VERIFY_WRITE, frame, sizeof(*frame))) if (verify_area(VERIFY_WRITE, frame, sizeof(*frame)))
goto badframe; goto badframe;
...@@ -394,27 +390,29 @@ setup_frame(struct pt_regs *regs, struct sigregs *frame, ...@@ -394,27 +390,29 @@ setup_frame(struct pt_regs *regs, struct sigregs *frame,
if (__copy_to_user(&frame->gp_regs, regs, GP_REGS_SIZE) if (__copy_to_user(&frame->gp_regs, regs, GP_REGS_SIZE)
|| __copy_to_user(&frame->fp_regs, current->thread.fpr, || __copy_to_user(&frame->fp_regs, current->thread.fpr,
ELF_NFPREG * sizeof(double)) ELF_NFPREG * sizeof(double))
|| __put_user(0x38000000UL + __NR_sigreturn, &frame->tramp[0]) /* li r0, __NR_sigreturn */ /* li r0, __NR_sigreturn */
|| __put_user(0x44000002UL, &frame->tramp[1])) /* sc */ || __put_user(0x38000000UL + __NR_sigreturn, &frame->tramp[0])
/* sc */
|| __put_user(0x44000002UL, &frame->tramp[1]))
goto badframe; goto badframe;
flush_icache_range((unsigned long) &frame->tramp[0], flush_icache_range((unsigned long)&frame->tramp[0],
(unsigned long) &frame->tramp[2]); (unsigned long)&frame->tramp[2]);
current->thread.fpscr = 0; /* turn off all fp exceptions */ current->thread.fpscr = 0; /* turn off all fp exceptions */
newsp -= __SIGNAL_FRAMESIZE; newsp -= __SIGNAL_FRAMESIZE;
if ( get_user(temp_ptr, &sc->handler)) if (get_user(temp_ptr, &sc->handler))
goto badframe; goto badframe;
funct_desc_ptr = ( struct funct_descr_entry *) temp_ptr; funct_desc_ptr = (struct funct_descr_entry *)temp_ptr;
if (put_user(regs->gpr[1], (unsigned long *)newsp) if (put_user(regs->gpr[1], (unsigned long *)newsp)
|| get_user(regs->nip, & funct_desc_ptr ->entry) || get_user(regs->nip, &funct_desc_ptr ->entry)
|| get_user(regs->gpr[2],& funct_desc_ptr->toc) || get_user(regs->gpr[2],&funct_desc_ptr->toc)
|| get_user(regs->gpr[3], &sc->signal)) || get_user(regs->gpr[3], &sc->signal))
goto badframe; goto badframe;
regs->gpr[1] = newsp; regs->gpr[1] = newsp;
regs->gpr[4] = (unsigned long) sc; regs->gpr[4] = (unsigned long)sc;
regs->link = (unsigned long) frame->tramp; regs->link = (unsigned long)frame->tramp;
return; return;
...@@ -429,8 +427,7 @@ setup_frame(struct pt_regs *regs, struct sigregs *frame, ...@@ -429,8 +427,7 @@ setup_frame(struct pt_regs *regs, struct sigregs *frame,
/* /*
* OK, we're invoking a handler * OK, we're invoking a handler
*/ */
static void static void handle_signal(unsigned long sig, siginfo_t *info, sigset_t *oldset,
handle_signal(unsigned long sig, siginfo_t *info, sigset_t *oldset,
struct pt_regs * regs, unsigned long *newspp, unsigned long frame) struct pt_regs * regs, unsigned long *newspp, unsigned long frame)
{ {
struct sigcontext_struct *sc; struct sigcontext_struct *sc;
...@@ -447,11 +444,12 @@ handle_signal(unsigned long sig, siginfo_t *info, sigset_t *oldset, ...@@ -447,11 +444,12 @@ handle_signal(unsigned long sig, siginfo_t *info, sigset_t *oldset,
if (ka->sa.sa_flags & SA_SIGINFO) { if (ka->sa.sa_flags & SA_SIGINFO) {
/* Put a Real Time Context onto stack */ /* Put a Real Time Context onto stack */
*newspp -= sizeof(*rt_sf); *newspp -= sizeof(*rt_sf);
rt_sf = (struct rt_sigframe *) *newspp; rt_sf = (struct rt_sigframe *)*newspp;
if (verify_area(VERIFY_WRITE, rt_sf, sizeof(*rt_sf))) if (verify_area(VERIFY_WRITE, rt_sf, sizeof(*rt_sf)))
goto badframe; goto badframe;
if (__put_user((unsigned long) ka->sa.sa_handler, &rt_sf->uc.uc_mcontext.handler) if (__put_user((unsigned long)ka->sa.sa_handler,
&rt_sf->uc.uc_mcontext.handler)
|| __put_user(&rt_sf->info, &rt_sf->pinfo) || __put_user(&rt_sf->info, &rt_sf->pinfo)
|| __put_user(&rt_sf->uc, &rt_sf->puc) || __put_user(&rt_sf->uc, &rt_sf->puc)
/* Put the siginfo */ /* Put the siginfo */
...@@ -461,9 +459,11 @@ handle_signal(unsigned long sig, siginfo_t *info, sigset_t *oldset, ...@@ -461,9 +459,11 @@ handle_signal(unsigned long sig, siginfo_t *info, sigset_t *oldset,
|| __put_user(0, &rt_sf->uc.uc_link) || __put_user(0, &rt_sf->uc.uc_link)
|| __put_user(current->sas_ss_sp, &rt_sf->uc.uc_stack.ss_sp) || __put_user(current->sas_ss_sp, &rt_sf->uc.uc_stack.ss_sp)
|| __put_user(sas_ss_flags(regs->gpr[1]), || __put_user(sas_ss_flags(regs->gpr[1]),
&rt_sf->uc.uc_stack.ss_flags) &rt_sf->uc.uc_stack.ss_flags)
|| __put_user(current->sas_ss_size, &rt_sf->uc.uc_stack.ss_size) || __put_user(current->sas_ss_size,
|| __copy_to_user(&rt_sf->uc.uc_sigmask, oldset, sizeof(*oldset)) &rt_sf->uc.uc_stack.ss_size)
|| __copy_to_user(&rt_sf->uc.uc_sigmask,
oldset, sizeof(*oldset))
/* mcontext.regs points to preamble register frame */ /* mcontext.regs points to preamble register frame */
|| __put_user((struct pt_regs *)frame, &rt_sf->uc.uc_mcontext.regs) || __put_user((struct pt_regs *)frame, &rt_sf->uc.uc_mcontext.regs)
|| __put_user(sig, &rt_sf->uc.uc_mcontext.signal)) || __put_user(sig, &rt_sf->uc.uc_mcontext.signal))
...@@ -471,11 +471,11 @@ handle_signal(unsigned long sig, siginfo_t *info, sigset_t *oldset, ...@@ -471,11 +471,11 @@ handle_signal(unsigned long sig, siginfo_t *info, sigset_t *oldset,
} else { } else {
/* Put a sigcontext on the stack */ /* Put a sigcontext on the stack */
*newspp -= sizeof(*sc); *newspp -= sizeof(*sc);
sc = (struct sigcontext_struct *) *newspp; sc = (struct sigcontext_struct *)*newspp;
if (verify_area(VERIFY_WRITE, sc, sizeof(*sc))) if (verify_area(VERIFY_WRITE, sc, sizeof(*sc)))
goto badframe; goto badframe;
if (__put_user((unsigned long) ka->sa.sa_handler, &sc->handler) if (__put_user((unsigned long)ka->sa.sa_handler, &sc->handler)
|| __put_user(oldset->sig[0], &sc->oldmask) || __put_user(oldset->sig[0], &sc->oldmask)
#if _NSIG_WORDS > 1 #if _NSIG_WORDS > 1
|| __put_user(oldset->sig[1], &sc->_unused[3]) || __put_user(oldset->sig[1], &sc->_unused[3])
...@@ -512,6 +512,7 @@ handle_signal(unsigned long sig, siginfo_t *info, sigset_t *oldset, ...@@ -512,6 +512,7 @@ handle_signal(unsigned long sig, siginfo_t *info, sigset_t *oldset,
* mistake. * mistake.
*/ */
extern int do_signal32(sigset_t *oldset, struct pt_regs *regs); extern int do_signal32(sigset_t *oldset, struct pt_regs *regs);
int do_signal(sigset_t *oldset, struct pt_regs *regs) int do_signal(sigset_t *oldset, struct pt_regs *regs)
{ {
siginfo_t info; siginfo_t info;
...@@ -526,7 +527,7 @@ int do_signal(sigset_t *oldset, struct pt_regs *regs) ...@@ -526,7 +527,7 @@ int do_signal(sigset_t *oldset, struct pt_regs *regs)
if (test_thread_flag(TIF_32BIT)) if (test_thread_flag(TIF_32BIT))
return do_signal32(oldset, regs); return do_signal32(oldset, regs);
if (!oldset) if (!oldset)
oldset = &current->blocked; oldset = &current->blocked;
newsp = frame = 0; newsp = frame = 0;
...@@ -534,8 +535,8 @@ int do_signal(sigset_t *oldset, struct pt_regs *regs) ...@@ -534,8 +535,8 @@ int do_signal(sigset_t *oldset, struct pt_regs *regs)
signr = get_signal_to_deliver(&info, regs); signr = get_signal_to_deliver(&info, regs);
if (signr > 0) { if (signr > 0) {
ka = &current->sig->action[signr-1]; ka = &current->sig->action[signr-1];
if ( (ka->sa.sa_flags & SA_ONSTACK) if ((ka->sa.sa_flags & SA_ONSTACK)
&& (! on_sig_stack(regs->gpr[1]))) && (!on_sig_stack(regs->gpr[1])))
newsp = (current->sas_ss_sp + current->sas_ss_size); newsp = (current->sas_ss_sp + current->sas_ss_size);
else else
newsp = regs->gpr[1]; newsp = regs->gpr[1];
...@@ -557,9 +558,10 @@ int do_signal(sigset_t *oldset, struct pt_regs *regs) ...@@ -557,9 +558,10 @@ int do_signal(sigset_t *oldset, struct pt_regs *regs)
if (newsp == frame) if (newsp == frame)
return 0; /* no signals delivered */ return 0; /* no signals delivered */
/* Invoke correct stack setup routine */
if (ka->sa.sa_flags & SA_SIGINFO) if (ka->sa.sa_flags & SA_SIGINFO)
setup_rt_frame(regs, (struct sigregs *) frame, newsp); setup_rt_frame(regs, (struct sigregs *)frame, newsp);
else else
setup_frame(regs, (struct sigregs *) frame, newsp); setup_frame(regs, (struct sigregs *)frame, newsp);
return 1; return 1;
} }
...@@ -14,43 +14,19 @@ ...@@ -14,43 +14,19 @@
* 2 of the License, or (at your option) any later version. * 2 of the License, or (at your option) any later version.
*/ */
#include <asm/ptrace.h>
#include <linux/kernel.h>
#include <linux/sched.h> #include <linux/sched.h>
#include <linux/fs.h>
#include <linux/mm.h> #include <linux/mm.h>
#include <linux/file.h>
#include <linux/signal.h>
#include <linux/utime.h>
#include <linux/resource.h>
#include <linux/times.h>
#include <linux/utsname.h>
#include <linux/timex.h>
#include <linux/smp.h> #include <linux/smp.h>
#include <linux/smp_lock.h> #include <linux/smp_lock.h>
#include <linux/sem.h> #include <linux/kernel.h>
#include <linux/msg.h> #include <linux/signal.h>
#include <linux/shm.h> #include <linux/errno.h>
#include <linux/slab.h>
#include <linux/uio.h>
#include <linux/nfs_fs.h>
#include <linux/smb_fs.h>
#include <linux/smb_mount.h>
#include <linux/ncp_fs.h>
#include <linux/module.h>
#include <linux/poll.h>
#include <linux/personality.h>
#include <linux/stat.h>
#include <linux/filter.h>
#include <linux/tty.h>
#include <linux/binfmts.h>
#include <linux/elf.h> #include <linux/elf.h>
#include <asm/types.h>
#include <asm/ipc.h>
#include <asm/uaccess.h>
#include <asm/ppc32.h> #include <asm/ppc32.h>
#include <asm/uaccess.h>
#include <asm/ppcdebug.h> #include <asm/ppcdebug.h>
#include <asm/unistd.h> #include <asm/unistd.h>
#include <asm/cacheflush.h>
#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP))) #define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
/* /*
...@@ -112,9 +88,6 @@ struct rt_sigframe_32 { ...@@ -112,9 +88,6 @@ struct rt_sigframe_32 {
}; };
extern asmlinkage long sys_wait4(pid_t pid,unsigned int * stat_addr,
int options, struct rusage * ru);
/* /*
* Start of nonRT signal support * Start of nonRT signal support
...@@ -133,7 +106,7 @@ extern asmlinkage long sys_wait4(pid_t pid,unsigned int * stat_addr, ...@@ -133,7 +106,7 @@ extern asmlinkage long sys_wait4(pid_t pid,unsigned int * stat_addr,
* setup_frame32 * setup_frame32
*/ */
asmlinkage long sys32_sigaction(int sig, struct old_sigaction32 *act, long sys32_sigaction(int sig, struct old_sigaction32 *act,
struct old_sigaction32 *oact) struct old_sigaction32 *oact)
{ {
struct k_sigaction new_ka, old_ka; struct k_sigaction new_ka, old_ka;
...@@ -145,32 +118,30 @@ asmlinkage long sys32_sigaction(int sig, struct old_sigaction32 *act, ...@@ -145,32 +118,30 @@ asmlinkage long sys32_sigaction(int sig, struct old_sigaction32 *act,
if (act) { if (act) {
old_sigset_t32 mask; old_sigset_t32 mask;
ret = get_user((long)new_ka.sa.sa_handler, &act->sa_handler); if (get_user((long)new_ka.sa.sa_handler, &act->sa_handler) ||
ret |= __get_user((long)new_ka.sa.sa_restorer, &act->sa_restorer); __get_user((long)new_ka.sa.sa_restorer, &act->sa_restorer) ||
ret |= __get_user(new_ka.sa.sa_flags, &act->sa_flags); __get_user(new_ka.sa.sa_flags, &act->sa_flags) ||
ret |= __get_user(mask, &act->sa_mask); __get_user(mask, &act->sa_mask))
if (ret) return -EFAULT;
return ret;
siginitset(&new_ka.sa.sa_mask, mask); siginitset(&new_ka.sa.sa_mask, mask);
} }
ret = do_sigaction(sig, act ? &new_ka : NULL, oact ? &old_ka : NULL); ret = do_sigaction(sig, act ? &new_ka : NULL, oact ? &old_ka : NULL);
if (!ret && oact) { if (!ret && oact) {
ret = put_user((long)old_ka.sa.sa_handler, &oact->sa_handler); if (put_user((long)old_ka.sa.sa_handler, &oact->sa_handler) ||
ret |= __put_user((long)old_ka.sa.sa_restorer, &oact->sa_restorer); __put_user((long)old_ka.sa.sa_restorer, &oact->sa_restorer) ||
ret |= __put_user(old_ka.sa.sa_flags, &oact->sa_flags); __put_user(old_ka.sa.sa_flags, &oact->sa_flags) ||
ret |= __put_user(old_ka.sa.sa_mask.sig[0], &oact->sa_mask); __put_user(old_ka.sa.sa_mask.sig[0], &oact->sa_mask))
return -EFAULT;
} }
return ret; return ret;
} }
extern long sys_sigpending(old_sigset_t *set);
long sys32_sigpending(old_sigset_t32 *set)
extern asmlinkage long sys_sigpending(old_sigset_t *set);
asmlinkage long sys32_sigpending(old_sigset_t32 *set)
{ {
old_sigset_t s; old_sigset_t s;
int ret; int ret;
...@@ -185,9 +156,7 @@ asmlinkage long sys32_sigpending(old_sigset_t32 *set) ...@@ -185,9 +156,7 @@ asmlinkage long sys32_sigpending(old_sigset_t32 *set)
} }
extern long sys_sigprocmask(int how, old_sigset_t *set,
extern asmlinkage long sys_sigprocmask(int how, old_sigset_t *set,
old_sigset_t *oset); old_sigset_t *oset);
/* /*
...@@ -197,7 +166,7 @@ extern asmlinkage long sys_sigprocmask(int how, old_sigset_t *set, ...@@ -197,7 +166,7 @@ extern asmlinkage long sys_sigprocmask(int how, old_sigset_t *set,
* of a signed int (msr in 32-bit mode) and the register representation * of a signed int (msr in 32-bit mode) and the register representation
* of a signed int (msr in 64-bit mode) is performed. * of a signed int (msr in 64-bit mode) is performed.
*/ */
asmlinkage long sys32_sigprocmask(u32 how, old_sigset_t32 *set, long sys32_sigprocmask(u32 how, old_sigset_t32 *set,
old_sigset_t32 *oset) old_sigset_t32 *oset)
{ {
old_sigset_t s; old_sigset_t s;
...@@ -252,23 +221,21 @@ long sys32_sigreturn(unsigned long r3, unsigned long r4, unsigned long r5, ...@@ -252,23 +221,21 @@ long sys32_sigreturn(unsigned long r3, unsigned long r4, unsigned long r5,
* Note that PPC32 puts the upper 32 bits of the sigmask in the * Note that PPC32 puts the upper 32 bits of the sigmask in the
* unused part of the signal stackframe * unused part of the signal stackframe
*/ */
set.sig[0] = sigctx.oldmask + ((long)(sigctx._unused[3])<< 32); set.sig[0] = sigctx.oldmask + ((long)(sigctx._unused[3]) << 32);
sigdelsetmask(&set, ~_BLOCKABLE); sigdelsetmask(&set, ~_BLOCKABLE);
spin_lock_irq(&current->sigmask_lock); spin_lock_irq(&current->sigmask_lock);
current->blocked = set; current->blocked = set;
recalc_sigpending(); recalc_sigpending();
spin_unlock_irq(&current->sigmask_lock); spin_unlock_irq(&current->sigmask_lock);
/* Last stacked signal - restore registers */
sr = (struct sigregs32*)(u64)sigctx.regs;
if (regs->msr & MSR_FP ) if (regs->msr & MSR_FP )
giveup_fpu(current); giveup_fpu(current);
/* Last stacked signal - restore registers */
sr = (struct sigregs32*)(u64)sigctx.regs;
/* /*
* copy the 32 bit register values off the user stack * copy the 32 bit register values off the user stack
* into the 32 bit register area * into the 32 bit register area
*/ */
if (copy_from_user(saved_regs, &sr->gp_regs, if (copy_from_user(saved_regs, &sr->gp_regs, sizeof(sr->gp_regs)))
sizeof(sr->gp_regs)))
goto badframe; goto badframe;
/* /*
* The saved reg structure in the frame is an elf_grepset_t32, * The saved reg structure in the frame is an elf_grepset_t32,
...@@ -323,7 +290,6 @@ long sys32_sigreturn(unsigned long r3, unsigned long r4, unsigned long r5, ...@@ -323,7 +290,6 @@ long sys32_sigreturn(unsigned long r3, unsigned long r4, unsigned long r5,
goto badframe; goto badframe;
ret = regs->result; ret = regs->result;
return ret; return ret;
badframe: badframe:
...@@ -387,12 +353,13 @@ static void setup_frame32(struct pt_regs *regs, struct sigregs32 *frame, ...@@ -387,12 +353,13 @@ static void setup_frame32(struct pt_regs *regs, struct sigregs32 *frame,
*/ */
if (__copy_to_user(&frame->fp_regs, current->thread.fpr, if (__copy_to_user(&frame->fp_regs, current->thread.fpr,
ELF_NFPREG * sizeof(double)) ELF_NFPREG * sizeof(double))
|| __put_user(0x38000000U + __NR_sigreturn, &frame->tramp[0]) /* li r0, __NR_sigreturn */ /* li r0, __NR_sigreturn */
|| __put_user(0x44000002U, &frame->tramp[1])) /* sc */ || __put_user(0x38000000U + __NR_sigreturn, &frame->tramp[0])
/* sc */
|| __put_user(0x44000002U, &frame->tramp[1]))
goto badframe; goto badframe;
flush_icache_range((unsigned long)&frame->tramp[0],
flush_icache_range((unsigned long) &frame->tramp[0], (unsigned long)&frame->tramp[2]);
(unsigned long) &frame->tramp[2]);
current->thread.fpscr = 0; /* turn off all fp exceptions */ current->thread.fpscr = 0; /* turn off all fp exceptions */
newsp -= __SIGNAL_FRAMESIZE32; newsp -= __SIGNAL_FRAMESIZE32;
...@@ -438,7 +405,7 @@ static void setup_frame32(struct pt_regs *regs, struct sigregs32 *frame, ...@@ -438,7 +405,7 @@ static void setup_frame32(struct pt_regs *regs, struct sigregs32 *frame,
* *
* Other routines * Other routines
* setup_rt_frame32 * setup_rt_frame32
* siginfo64to32 * copy_siginfo_to_user32
* siginfo32to64 * siginfo32to64
*/ */
...@@ -451,50 +418,45 @@ long sys32_rt_sigreturn(unsigned long r3, unsigned long r4, unsigned long r5, ...@@ -451,50 +418,45 @@ long sys32_rt_sigreturn(unsigned long r3, unsigned long r4, unsigned long r5,
unsigned long r6, unsigned long r7, unsigned long r8, unsigned long r6, unsigned long r7, unsigned long r8,
struct pt_regs * regs) struct pt_regs * regs)
{ {
struct rt_sigframe_32 *rt_stack_frame; struct rt_sigframe_32 *rt_sf;
struct sigcontext32_struct sigctx; struct sigcontext32_struct sigctx;
struct sigregs32 *signalregs; struct sigregs32 *sr;
int ret; int ret;
elf_gregset_t32 saved_regs; /* an array of 32 bit register values */ elf_gregset_t32 saved_regs; /* an array of 32 bit register values */
sigset_t signal_set; sigset_t set;
stack_t stack; stack_t st;
int i; int i;
ret = 0;
/* Adjust the inputted reg1 to point to the first rt signal frame */ /* Adjust the inputted reg1 to point to the first rt signal frame */
rt_stack_frame = (struct rt_sigframe_32 *)(regs->gpr[1] + __SIGNAL_FRAMESIZE32); rt_sf = (struct rt_sigframe_32 *)(regs->gpr[1] + __SIGNAL_FRAMESIZE32);
/* Copy the information from the user stack */ /* Copy the information from the user stack */
if (copy_from_user(&sigctx, &rt_stack_frame->uc.uc_mcontext, if (copy_from_user(&sigctx, &rt_sf->uc.uc_mcontext, sizeof(sigctx))
sizeof(sigctx)) || copy_from_user(&set, &rt_sf->uc.uc_sigmask, sizeof(set))
|| copy_from_user(&signal_set, &rt_stack_frame->uc.uc_sigmask, || copy_from_user(&st,&rt_sf->uc.uc_stack, sizeof(st)))
sizeof(signal_set))
|| copy_from_user(&stack,&rt_stack_frame->uc.uc_stack,
sizeof(stack)))
goto badframe; goto badframe;
/* /*
* Unblock the signal that was processed * Unblock the signal that was processed
* After a signal handler runs - * After a signal handler runs -
* if the signal is blockable - the signal will be unblocked * if the signal is blockable - the signal will be unblocked
* ( sigkill and sigstop are not blockable) * (sigkill and sigstop are not blockable)
*/ */
sigdelsetmask(&signal_set, ~_BLOCKABLE); sigdelsetmask(&set, ~_BLOCKABLE);
/* update the current based on the sigmask found in the rt_stackframe */ /* update the current based on the sigmask found in the rt_stackframe */
spin_lock_irq(&current->sigmask_lock); spin_lock_irq(&current->sigmask_lock);
current->blocked = signal_set; current->blocked = set;
recalc_sigpending(); recalc_sigpending();
spin_unlock_irq(&current->sigmask_lock); spin_unlock_irq(&current->sigmask_lock);
/* If currently owning the floating point - give them up */
if (regs->msr & MSR_FP)
giveup_fpu(current);
/* /*
* Set to point to the next rt_sigframe - this is used to * Set to point to the next rt_sigframe - this is used to
* determine whether this is the last signal to process * determine whether this is the last signal to process
*/ */
signalregs = (struct sigregs32 *) (u64)sigctx.regs; sr = (struct sigregs32 *)(u64)sigctx.regs;
/* If currently owning the floating point - give them up */ if (copy_from_user(saved_regs, &sr->gp_regs, sizeof(sr->gp_regs)))
if (regs->msr & MSR_FP)
giveup_fpu(current);
if (copy_from_user(saved_regs, &signalregs->gp_regs,
sizeof(signalregs->gp_regs)))
goto badframe; goto badframe;
/* /*
* The saved reg structure in the frame is an elf_grepset_t32, * The saved reg structure in the frame is an elf_grepset_t32,
...@@ -544,7 +506,7 @@ long sys32_rt_sigreturn(unsigned long r3, unsigned long r4, unsigned long r5, ...@@ -544,7 +506,7 @@ long sys32_rt_sigreturn(unsigned long r3, unsigned long r4, unsigned long r5,
asmlinkage long sys32_rt_sigaction(int sig, const struct sigaction32 *act, long sys32_rt_sigaction(int sig, const struct sigaction32 *act,
struct sigaction32 *oact, size_t sigsetsize) struct sigaction32 *oact, size_t sigsetsize)
{ {
struct k_sigaction new_ka, old_ka; struct k_sigaction new_ka, old_ka;
...@@ -599,7 +561,7 @@ asmlinkage long sys32_rt_sigaction(int sig, const struct sigaction32 *act, ...@@ -599,7 +561,7 @@ asmlinkage long sys32_rt_sigaction(int sig, const struct sigaction32 *act,
} }
extern asmlinkage long sys_rt_sigprocmask(int how, sigset_t *set, extern long sys_rt_sigprocmask(int how, sigset_t *set,
sigset_t *oset, size_t sigsetsize); sigset_t *oset, size_t sigsetsize);
/* /*
...@@ -609,7 +571,7 @@ extern asmlinkage long sys_rt_sigprocmask(int how, sigset_t *set, ...@@ -609,7 +571,7 @@ extern asmlinkage long sys_rt_sigprocmask(int how, sigset_t *set,
* of a signed int (msr in 32-bit mode) and the register representation * of a signed int (msr in 32-bit mode) and the register representation
* of a signed int (msr in 64-bit mode) is performed. * of a signed int (msr in 64-bit mode) is performed.
*/ */
asmlinkage long sys32_rt_sigprocmask(u32 how, sigset32_t *set, long sys32_rt_sigprocmask(u32 how, sigset32_t *set,
sigset32_t *oset, size_t sigsetsize) sigset32_t *oset, size_t sigsetsize)
{ {
sigset_t s; sigset_t s;
...@@ -649,10 +611,10 @@ asmlinkage long sys32_rt_sigprocmask(u32 how, sigset32_t *set, ...@@ -649,10 +611,10 @@ asmlinkage long sys32_rt_sigprocmask(u32 how, sigset32_t *set,
} }
extern asmlinkage long sys_rt_sigpending(sigset_t *set, size_t sigsetsize); extern long sys_rt_sigpending(sigset_t *set, size_t sigsetsize);
asmlinkage long sys32_rt_sigpending(sigset32_t *set, long sys32_rt_sigpending(sigset32_t *set,
__kernel_size_t32 sigsetsize) __kernel_size_t32 sigsetsize)
{ {
sigset_t s; sigset_t s;
...@@ -677,50 +639,54 @@ asmlinkage long sys32_rt_sigpending(sigset32_t *set, ...@@ -677,50 +639,54 @@ asmlinkage long sys32_rt_sigpending(sigset32_t *set,
} }
siginfo_t32 *siginfo64to32(siginfo_t32 *d, siginfo_t *s) static int copy_siginfo_to_user32(siginfo_t32 *d, siginfo_t *s)
{ {
memset (d, 0, sizeof(siginfo_t32)); int err;
d->si_signo = s->si_signo;
d->si_errno = s->si_errno; if (!access_ok (VERIFY_WRITE, d, sizeof(*d)))
/* XXX why dont we just implement copy_siginfo_to_user32? - Anton */ return -EFAULT;
d->si_code = s->si_code & 0xffff;
err = __put_user(s->si_signo, &d->si_signo);
err |= __put_user(s->si_errno, &d->si_errno);
err |= __put_user((short)s->si_code, &d->si_code);
if (s->si_signo >= SIGRTMIN) { if (s->si_signo >= SIGRTMIN) {
d->si_pid = s->si_pid; err |= __put_user(s->si_pid, &d->si_pid);
d->si_uid = s->si_uid; err |= __put_user(s->si_uid, &d->si_uid);
d->si_int = s->si_int; err |= __put_user(s->si_int, &d->si_int);
} else { } else {
switch (s->si_signo) { switch (s->si_signo) {
/* XXX: What about POSIX1.b timers */ /* XXX: What about POSIX1.b timers */
case SIGCHLD: case SIGCHLD:
d->si_pid = s->si_pid; err |= __put_user(s->si_pid, &d->si_pid);
d->si_status = s->si_status; err |= __put_user(s->si_status, &d->si_status);
d->si_utime = s->si_utime; err |= __put_user(s->si_utime, &d->si_utime);
d->si_stime = s->si_stime; err |= __put_user(s->si_stime, &d->si_stime);
break; break;
case SIGSEGV: case SIGSEGV:
case SIGBUS: case SIGBUS:
case SIGFPE: case SIGFPE:
case SIGILL: case SIGILL:
d->si_addr = (long)(s->si_addr); err |= __put_user((long)(s->si_addr), &d->si_addr);
break; break;
case SIGPOLL: case SIGPOLL:
d->si_band = s->si_band; err |= __put_user(s->si_band, &d->si_band);
d->si_fd = s->si_fd; err |= __put_user(s->si_fd, &d->si_fd);
break; break;
default: default:
d->si_pid = s->si_pid; err |= __put_user(s->si_pid, &d->si_pid);
d->si_uid = s->si_uid; err |= __put_user(s->si_uid, &d->si_uid);
break; break;
} }
} }
return d; return err;
} }
extern asmlinkage long sys_rt_sigtimedwait(const sigset_t *uthese,
extern long sys_rt_sigtimedwait(const sigset_t *uthese,
siginfo_t *uinfo, const struct timespec *uts, siginfo_t *uinfo, const struct timespec *uts,
size_t sigsetsize); size_t sigsetsize);
asmlinkage long sys32_rt_sigtimedwait(sigset32_t *uthese, siginfo_t32 *uinfo, long sys32_rt_sigtimedwait(sigset32_t *uthese, siginfo_t32 *uinfo,
struct timespec32 *uts, __kernel_size_t32 sigsetsize) struct timespec32 *uts, __kernel_size_t32 sigsetsize)
{ {
sigset_t s; sigset_t s;
...@@ -729,8 +695,7 @@ asmlinkage long sys32_rt_sigtimedwait(sigset32_t *uthese, siginfo_t32 *uinfo, ...@@ -729,8 +695,7 @@ asmlinkage long sys32_rt_sigtimedwait(sigset32_t *uthese, siginfo_t32 *uinfo,
int ret; int ret;
mm_segment_t old_fs = get_fs(); mm_segment_t old_fs = get_fs();
siginfo_t info; siginfo_t info;
siginfo_t32 info32;
if (copy_from_user(&s32, uthese, sizeof(sigset32_t))) if (copy_from_user(&s32, uthese, sizeof(sigset32_t)))
return -EFAULT; return -EFAULT;
switch (_NSIG_WORDS) { switch (_NSIG_WORDS) {
...@@ -753,8 +718,7 @@ asmlinkage long sys32_rt_sigtimedwait(sigset32_t *uthese, siginfo_t32 *uinfo, ...@@ -753,8 +718,7 @@ asmlinkage long sys32_rt_sigtimedwait(sigset32_t *uthese, siginfo_t32 *uinfo,
sigsetsize); sigsetsize);
set_fs(old_fs); set_fs(old_fs);
if (ret >= 0 && uinfo) { if (ret >= 0 && uinfo) {
if (copy_to_user (uinfo, siginfo64to32(&info32, &info), if (copy_siginfo_to_user32(uinfo, &info))
sizeof(siginfo_t32)))
return -EFAULT; return -EFAULT;
} }
return ret; return ret;
...@@ -762,7 +726,7 @@ asmlinkage long sys32_rt_sigtimedwait(sigset32_t *uthese, siginfo_t32 *uinfo, ...@@ -762,7 +726,7 @@ asmlinkage long sys32_rt_sigtimedwait(sigset32_t *uthese, siginfo_t32 *uinfo,
siginfo_t * siginfo32to64(siginfo_t *d, siginfo_t32 *s) static siginfo_t * siginfo32to64(siginfo_t *d, siginfo_t32 *s)
{ {
d->si_signo = s->si_signo; d->si_signo = s->si_signo;
d->si_errno = s->si_errno; d->si_errno = s->si_errno;
...@@ -800,7 +764,7 @@ siginfo_t * siginfo32to64(siginfo_t *d, siginfo_t32 *s) ...@@ -800,7 +764,7 @@ siginfo_t * siginfo32to64(siginfo_t *d, siginfo_t32 *s)
} }
extern asmlinkage long sys_rt_sigqueueinfo(int pid, int sig, siginfo_t *uinfo); extern long sys_rt_sigqueueinfo(int pid, int sig, siginfo_t *uinfo);
/* /*
* Note: it is necessary to treat pid and sig as unsigned ints, with the * Note: it is necessary to treat pid and sig as unsigned ints, with the
...@@ -809,7 +773,7 @@ extern asmlinkage long sys_rt_sigqueueinfo(int pid, int sig, siginfo_t *uinfo); ...@@ -809,7 +773,7 @@ extern asmlinkage long sys_rt_sigqueueinfo(int pid, int sig, siginfo_t *uinfo);
* (msr in 32-bit mode) and the register representation of a signed int * (msr in 32-bit mode) and the register representation of a signed int
* (msr in 64-bit mode) is performed. * (msr in 64-bit mode) is performed.
*/ */
asmlinkage long sys32_rt_sigqueueinfo(u32 pid, u32 sig, siginfo_t32 *uinfo) long sys32_rt_sigqueueinfo(u32 pid, u32 sig, siginfo_t32 *uinfo)
{ {
siginfo_t info; siginfo_t info;
siginfo_t32 info32; siginfo_t32 info32;
...@@ -974,8 +938,7 @@ static void handle_signal32(unsigned long sig, siginfo_t *info, ...@@ -974,8 +938,7 @@ static void handle_signal32(unsigned long sig, siginfo_t *info,
unsigned int frame) unsigned int frame)
{ {
struct sigcontext32_struct *sc; struct sigcontext32_struct *sc;
struct rt_sigframe_32 *rt_stack_frame; struct rt_sigframe_32 *rt_sf;
siginfo_t32 siginfo32bit;
struct k_sigaction *ka = &current->sig->action[sig-1]; struct k_sigaction *ka = &current->sig->action[sig-1];
if (regs->trap == 0x0C00 /* System Call! */ if (regs->trap == 0x0C00 /* System Call! */
...@@ -986,42 +949,35 @@ static void handle_signal32(unsigned long sig, siginfo_t *info, ...@@ -986,42 +949,35 @@ static void handle_signal32(unsigned long sig, siginfo_t *info,
/* /*
* Set up the signal frame * Set up the signal frame
* Determine if an real time frame - siginfo required * Determine if a real time frame and a siginfo is required
*/ */
if (ka->sa.sa_flags & SA_SIGINFO) { if (ka->sa.sa_flags & SA_SIGINFO) {
siginfo64to32(&siginfo32bit,info); *newspp -= sizeof(*rt_sf);
*newspp -= sizeof(*rt_stack_frame); rt_sf = (struct rt_sigframe_32 *)(u64)(*newspp);
rt_stack_frame = (struct rt_sigframe_32 *)(u64)(*newspp); if (verify_area(VERIFY_WRITE, rt_sf, sizeof(*rt_sf)))
if (verify_area(VERIFY_WRITE, rt_stack_frame,
sizeof(*rt_stack_frame)))
goto badframe; goto badframe;
if (__put_user((u32)(u64)ka->sa.sa_handler, if (__put_user((u32)(u64)ka->sa.sa_handler,
&rt_stack_frame->uc.uc_mcontext.handler) &rt_sf->uc.uc_mcontext.handler)
|| __put_user((u32)(u64)&rt_stack_frame->info, || __put_user((u32)(u64)&rt_sf->info, &rt_sf->pinfo)
&rt_stack_frame->pinfo) || __put_user((u32)(u64)&rt_sf->uc, &rt_sf->puc)
|| __put_user((u32)(u64)&rt_stack_frame->uc,
&rt_stack_frame->puc)
/* put the siginfo on the user stack */ /* put the siginfo on the user stack */
|| __copy_to_user(&rt_stack_frame->info, &siginfo32bit, || copy_siginfo_to_user32(&rt_sf->info, info)
sizeof(siginfo32bit))
/* set the ucontext on the user stack */ /* set the ucontext on the user stack */
|| __put_user(0, &rt_stack_frame->uc.uc_flags) || __put_user(0, &rt_sf->uc.uc_flags)
|| __put_user(0, &rt_stack_frame->uc.uc_link) || __put_user(0, &rt_sf->uc.uc_link)
|| __put_user(current->sas_ss_sp, || __put_user(current->sas_ss_sp, &rt_sf->uc.uc_stack.ss_sp)
&rt_stack_frame->uc.uc_stack.ss_sp)
|| __put_user(sas_ss_flags(regs->gpr[1]), || __put_user(sas_ss_flags(regs->gpr[1]),
&rt_stack_frame->uc.uc_stack.ss_flags) &rt_sf->uc.uc_stack.ss_flags)
|| __put_user(current->sas_ss_size, || __put_user(current->sas_ss_size,
&rt_stack_frame->uc.uc_stack.ss_size) &rt_sf->uc.uc_stack.ss_size)
|| __copy_to_user(&rt_stack_frame->uc.uc_sigmask, || __copy_to_user(&rt_sf->uc.uc_sigmask,
oldset, sizeof(*oldset)) oldset, sizeof(*oldset))
/* point the mcontext.regs to the pramble register frame */ /* point the mcontext.regs to the pramble register frame */
|| __put_user(frame, &rt_stack_frame->uc.uc_mcontext.regs) || __put_user(frame, &rt_sf->uc.uc_mcontext.regs)
|| __put_user(sig,&rt_stack_frame->uc.uc_mcontext.signal)) || __put_user(sig,&rt_sf->uc.uc_mcontext.signal))
goto badframe; goto badframe;
} else { } else {
/* Put another sigcontext on the stack */ /* Put a sigcontext on the stack */
*newspp -= sizeof(*sc); *newspp -= sizeof(*sc);
sc = (struct sigcontext32_struct *)(u64)*newspp; sc = (struct sigcontext32_struct *)(u64)*newspp;
if (verify_area(VERIFY_WRITE, sc, sizeof(*sc))) if (verify_area(VERIFY_WRITE, sc, sizeof(*sc)))
...@@ -1048,7 +1004,6 @@ static void handle_signal32(unsigned long sig, siginfo_t *info, ...@@ -1048,7 +1004,6 @@ static void handle_signal32(unsigned long sig, siginfo_t *info,
recalc_sigpending(); recalc_sigpending();
spin_unlock_irq(&current->sigmask_lock); spin_unlock_irq(&current->sigmask_lock);
} }
return; return;
badframe: badframe:
...@@ -1068,7 +1023,7 @@ static void handle_signal32(unsigned long sig, siginfo_t *info, ...@@ -1068,7 +1023,7 @@ static void handle_signal32(unsigned long sig, siginfo_t *info,
* sigaltatck sys32_sigaltstack * sigaltatck sys32_sigaltstack
*/ */
asmlinkage int sys32_sigaltstack(u32 newstack, u32 oldstack, int p3, int sys32_sigaltstack(u32 newstack, u32 oldstack, int p3,
int p4, int p6, int p7, struct pt_regs *regs) int p4, int p6, int p7, struct pt_regs *regs)
{ {
stack_t uss, uoss; stack_t uss, uoss;
...@@ -1114,7 +1069,7 @@ asmlinkage int sys32_sigaltstack(u32 newstack, u32 oldstack, int p3, ...@@ -1114,7 +1069,7 @@ asmlinkage int sys32_sigaltstack(u32 newstack, u32 oldstack, int p3,
/* /*
* Start of do_signal32 routine * Start of do_signal32 routine
* *
* This routine gets control when a pemding signal needs to be processed * This routine gets control when a pending signal needs to be processed
* in the 32 bit target thread - * in the 32 bit target thread -
* *
* It handles both rt and non-rt signals * It handles both rt and non-rt signals
...@@ -1141,13 +1096,13 @@ int do_signal32(sigset_t *oldset, struct pt_regs *regs) ...@@ -1141,13 +1096,13 @@ int do_signal32(sigset_t *oldset, struct pt_regs *regs)
signr = get_signal_to_deliver(&info, regs); signr = get_signal_to_deliver(&info, regs);
if (signr > 0) { if (signr > 0) {
ka = &current->sig->action[signr-1]; ka = &current->sig->action[signr-1];
if ((ka->sa.sa_flags & SA_ONSTACK)
if ((ka->sa.sa_flags & SA_ONSTACK) && && (!on_sig_stack(regs->gpr[1])))
(!on_sig_stack(regs->gpr[1])))
newsp = (current->sas_ss_sp + current->sas_ss_size); newsp = (current->sas_ss_sp + current->sas_ss_size);
else else
newsp = regs->gpr[1]; newsp = regs->gpr[1];
newsp = frame = newsp - sizeof(struct sigregs32); newsp = frame = newsp - sizeof(struct sigregs32);
/* Whee! Actually deliver the signal. */ /* Whee! Actually deliver the signal. */
handle_signal32(signr, &info, oldset, regs, &newsp, frame); handle_signal32(signr, &info, oldset, regs, &newsp, frame);
} }
...@@ -1165,10 +1120,9 @@ int do_signal32(sigset_t *oldset, struct pt_regs *regs) ...@@ -1165,10 +1120,9 @@ int do_signal32(sigset_t *oldset, struct pt_regs *regs)
return 0; /* no signals delivered */ return 0; /* no signals delivered */
/* Invoke correct stack setup routine */ /* Invoke correct stack setup routine */
if (ka->sa.sa_flags & SA_SIGINFO) if (ka->sa.sa_flags & SA_SIGINFO)
setup_rt_frame32(regs, (struct sigregs32*)(u64)frame, newsp); setup_rt_frame32(regs, (struct sigregs32*)(u64)frame, newsp);
else else
setup_frame32(regs, (struct sigregs32*)(u64)frame, newsp); setup_frame32(regs, (struct sigregs32*)(u64)frame, newsp);
return 1; return 1;
} }
...@@ -28,7 +28,6 @@ ...@@ -28,7 +28,6 @@
#define __KERNEL_SYSCALLS__ #define __KERNEL_SYSCALLS__
#include <linux/unistd.h> #include <linux/unistd.h>
#include <linux/init.h> #include <linux/init.h>
/* #include <linux/openpic.h> */
#include <linux/spinlock.h> #include <linux/spinlock.h>
#include <linux/cache.h> #include <linux/cache.h>
#include <linux/err.h> #include <linux/err.h>
...@@ -40,7 +39,6 @@ ...@@ -40,7 +39,6 @@
#include <asm/pgtable.h> #include <asm/pgtable.h>
#include <asm/hardirq.h> #include <asm/hardirq.h>
#include <asm/softirq.h> #include <asm/softirq.h>
#include <asm/init.h>
#include <asm/io.h> #include <asm/io.h>
#include <asm/prom.h> #include <asm/prom.h>
#include <asm/smp.h> #include <asm/smp.h>
...@@ -66,10 +64,6 @@ unsigned long cpu_online_map; ...@@ -66,10 +64,6 @@ unsigned long cpu_online_map;
volatile unsigned long cpu_callin_map[NR_CPUS] = {0,}; volatile unsigned long cpu_callin_map[NR_CPUS] = {0,};
#define TB_SYNC_PASSES 4
volatile unsigned long __initdata tb_sync_flag = 0;
volatile unsigned long __initdata tb_offset = 0;
extern unsigned char stab_array[]; extern unsigned char stab_array[];
int start_secondary(void *); int start_secondary(void *);
...@@ -595,13 +589,9 @@ void __init smp_boot_cpus(void) ...@@ -595,13 +589,9 @@ void __init smp_boot_cpus(void)
} }
/* /*
* XXX very rough. On POWER4 we optimise tlb flushes for * XXX very rough.
* tasks that only run on one cpu so we increase decay ticks.
*/ */
if (__is_processor(PV_POWER4)) cache_decay_ticks = HZ/100;
cache_decay_ticks = HZ/50;
else
cache_decay_ticks = HZ/100;
/* Probe arch for CPUs */ /* Probe arch for CPUs */
cpu_nr = ppc_md.smp_probe(); cpu_nr = ppc_md.smp_probe();
...@@ -729,7 +719,7 @@ void __init smp_setup(char *str, int *ints) ...@@ -729,7 +719,7 @@ void __init smp_setup(char *str, int *ints)
{ {
} }
int __init setup_profiling_timer(unsigned int multiplier) int setup_profiling_timer(unsigned int multiplier)
{ {
return 0; return 0;
} }
......
...@@ -53,7 +53,6 @@ ...@@ -53,7 +53,6 @@
#include <asm/nvram.h> #include <asm/nvram.h>
#include <asm/cache.h> #include <asm/cache.h>
#include <asm/machdep.h> #include <asm/machdep.h>
#include <asm/init.h>
#ifdef CONFIG_PPC_ISERIES #ifdef CONFIG_PPC_ISERIES
#include <asm/iSeries/HvCallXm.h> #include <asm/iSeries/HvCallXm.h>
#endif #endif
......
/* /*
*
*
* PowerPC version * PowerPC version
* Copyright (C) 1995-1996 Gary Thomas (gdt@linuxppc.org) * Copyright (C) 1995-1996 Gary Thomas (gdt@linuxppc.org)
* *
...@@ -62,8 +60,6 @@ ...@@ -62,8 +60,6 @@
#include <asm/ppcdebug.h> #include <asm/ppcdebug.h>
#define PGTOKB(pages) (((pages) * PAGE_SIZE) >> 10)
#ifdef CONFIG_PPC_ISERIES #ifdef CONFIG_PPC_ISERIES
#include <asm/iSeries/iSeries_dma.h> #include <asm/iSeries/iSeries_dma.h>
#endif #endif
...@@ -76,15 +72,10 @@ static int boot_mapsize; ...@@ -76,15 +72,10 @@ static int boot_mapsize;
extern pgd_t swapper_pg_dir[]; extern pgd_t swapper_pg_dir[];
extern char __init_begin, __init_end; extern char __init_begin, __init_end;
extern char __chrp_begin, __chrp_end;
extern char __openfirmware_begin, __openfirmware_end;
extern struct _of_tce_table of_tce_table[];
extern char _start[], _end[]; extern char _start[], _end[];
extern char _stext[], etext[]; extern char _stext[], etext[];
extern struct task_struct *current_set[NR_CPUS]; extern struct task_struct *current_set[NR_CPUS];
void mm_init_ppc64(void);
extern pgd_t ioremap_dir[]; extern pgd_t ioremap_dir[];
pgd_t * ioremap_pgd = (pgd_t *)&ioremap_dir; pgd_t * ioremap_pgd = (pgd_t *)&ioremap_dir;
...@@ -107,7 +98,7 @@ mmu_gather_t mmu_gathers[NR_CPUS]; ...@@ -107,7 +98,7 @@ mmu_gather_t mmu_gathers[NR_CPUS];
void show_mem(void) void show_mem(void)
{ {
int i,free = 0,total = 0,reserved = 0; int i,total = 0,reserved = 0;
int shared = 0, cached = 0; int shared = 0, cached = 0;
printk("Mem-info:\n"); printk("Mem-info:\n");
...@@ -120,13 +111,10 @@ void show_mem(void) ...@@ -120,13 +111,10 @@ void show_mem(void)
reserved++; reserved++;
else if (PageSwapCache(mem_map+i)) else if (PageSwapCache(mem_map+i))
cached++; cached++;
else if (!atomic_read(&mem_map[i].count)) else if (page_count(mem_map+i))
free++; shared += page_count(mem_map+i) - 1;
else
shared += atomic_read(&mem_map[i].count) - 1;
} }
printk("%d pages of RAM\n",total); printk("%d pages of RAM\n",total);
printk("%d free pages\n",free);
printk("%d reserved pages\n",reserved); printk("%d reserved pages\n",reserved);
printk("%d pages shared\n",shared); printk("%d pages shared\n",shared);
printk("%d pages swap cached\n",cached); printk("%d pages swap cached\n",cached);
...@@ -179,7 +167,7 @@ __ioremap(unsigned long addr, unsigned long size, unsigned long flags) ...@@ -179,7 +167,7 @@ __ioremap(unsigned long addr, unsigned long size, unsigned long flags)
else { else {
ea = ioremap_bot; ea = ioremap_bot;
ioremap_bot += size; ioremap_bot += size;
} }
if ((flags & _PAGE_PRESENT) == 0) if ((flags & _PAGE_PRESENT) == 0)
flags |= pgprot_val(PAGE_KERNEL); flags |= pgprot_val(PAGE_KERNEL);
...@@ -196,9 +184,9 @@ __ioremap(unsigned long addr, unsigned long size, unsigned long flags) ...@@ -196,9 +184,9 @@ __ioremap(unsigned long addr, unsigned long size, unsigned long flags)
void iounmap(void *addr) void iounmap(void *addr)
{ {
#ifdef CONFIG_PPC_ISERIES #ifdef CONFIG_PPC_ISERIES
/* iSeries I/O Remap is a noop */ /* iSeries I/O Remap is a noop */
return; return;
#else #else
/* DRENG / PPPBBB todo */ /* DRENG / PPPBBB todo */
return; return;
#endif #endif
...@@ -229,7 +217,7 @@ static void map_io_page(unsigned long ea, unsigned long pa, int flags) ...@@ -229,7 +217,7 @@ static void map_io_page(unsigned long ea, unsigned long pa, int flags)
/* If the mm subsystem is not fully up, we cannot create a /* If the mm subsystem is not fully up, we cannot create a
* linux page table entry for this mapping. Simply bolt an * linux page table entry for this mapping. Simply bolt an
* entry in the hardware page table. * entry in the hardware page table.
*/ */
vsid = get_kernel_vsid(ea); vsid = get_kernel_vsid(ea);
ppc_md.make_pte(htab_data.htab, ppc_md.make_pte(htab_data.htab,
(vsid << 28) | (ea & 0xFFFFFFF), // va (NOT the ea) (vsid << 28) | (ea & 0xFFFFFFF), // va (NOT the ea)
...@@ -302,7 +290,7 @@ flush_tlb_page(struct vm_area_struct *vma, unsigned long vmaddr) ...@@ -302,7 +290,7 @@ flush_tlb_page(struct vm_area_struct *vma, unsigned long vmaddr)
} }
} }
struct tlb_batch_data tlb_batch_array[NR_CPUS][MAX_BATCH_FLUSH]; struct ppc64_tlb_batch ppc64_tlb_batch[NR_CPUS];
void void
__flush_tlb_range(struct mm_struct *mm, unsigned long start, unsigned long end) __flush_tlb_range(struct mm_struct *mm, unsigned long start, unsigned long end)
...@@ -312,81 +300,69 @@ __flush_tlb_range(struct mm_struct *mm, unsigned long start, unsigned long end) ...@@ -312,81 +300,69 @@ __flush_tlb_range(struct mm_struct *mm, unsigned long start, unsigned long end)
pte_t *ptep; pte_t *ptep;
pte_t pte; pte_t pte;
unsigned long pgd_end, pmd_end; unsigned long pgd_end, pmd_end;
unsigned long context; unsigned long context = 0;
int i = 0; struct ppc64_tlb_batch *batch = &ppc64_tlb_batch[smp_processor_id()];
struct tlb_batch_data *ptes = &tlb_batch_array[smp_processor_id()][0]; unsigned long i = 0;
int local = 0; int local = 0;
if ( start >= end ) switch(REGION_ID(start)) {
panic("flush_tlb_range: start (%016lx) greater than end (%016lx)\n", start, end );
if ( REGION_ID(start) != REGION_ID(end) )
panic("flush_tlb_range: start (%016lx) and end (%016lx) not in same region\n", start, end );
context = 0;
switch( REGION_ID(start) ) {
case VMALLOC_REGION_ID: case VMALLOC_REGION_ID:
pgd = pgd_offset_k( start ); pgd = pgd_offset_k(start);
break; break;
case IO_REGION_ID: case IO_REGION_ID:
pgd = pgd_offset_i( start ); pgd = pgd_offset_i(start);
break; break;
case USER_REGION_ID: case USER_REGION_ID:
pgd = pgd_offset( mm, start ); pgd = pgd_offset(mm, start);
context = mm->context; context = mm->context;
/* XXX are there races with checking cpu_vm_mask? - Anton */ /* XXX are there races with checking cpu_vm_mask? - Anton */
if (mm->cpu_vm_mask == (1 << smp_processor_id())) { if (mm->cpu_vm_mask == (1 << smp_processor_id()))
local = 1; local = 1;
}
break; break;
default: default:
panic("flush_tlb_range: invalid region for start (%016lx) and end (%016lx)\n", start, end); panic("flush_tlb_range: invalid region for start (%016lx) and end (%016lx)\n", start, end);
} }
do { do {
pgd_end = (start + PGDIR_SIZE) & PGDIR_MASK; pgd_end = (start + PGDIR_SIZE) & PGDIR_MASK;
if ( pgd_end > end ) if (pgd_end > end)
pgd_end = end; pgd_end = end;
if ( !pgd_none( *pgd ) ) { if (!pgd_none(*pgd)) {
pmd = pmd_offset( pgd, start ); pmd = pmd_offset(pgd, start);
do { do {
pmd_end = ( start + PMD_SIZE ) & PMD_MASK; pmd_end = (start + PMD_SIZE) & PMD_MASK;
if ( pmd_end > end ) if (pmd_end > end)
pmd_end = end; pmd_end = end;
if ( !pmd_none( *pmd ) ) { if (!pmd_none(*pmd)) {
ptep = pte_offset_kernel( pmd, start ); ptep = pte_offset_kernel(pmd, start);
do { do {
if ( pte_val(*ptep) & _PAGE_HASHPTE ) { if (pte_val(*ptep) & _PAGE_HASHPTE) {
pte = __pte(pte_update(ptep, _PAGE_HPTEFLAGS, 0)); pte = __pte(pte_update(ptep, _PAGE_HPTEFLAGS, 0));
if ( pte_val(pte) & _PAGE_HASHPTE ) { if (pte_val(pte) & _PAGE_HASHPTE) {
ptes->pte = pte; batch->pte[i] = pte;
ptes->addr = start; batch->addr[i] = start;
ptes++;
i++; i++;
if (i == MAX_BATCH_FLUSH) { if (i == PPC64_TLB_BATCH_NR) {
flush_hash_range(context, MAX_BATCH_FLUSH, local); flush_hash_range(context, i, local);
i = 0; i = 0;
ptes = &tlb_batch_array[smp_processor_id()][0];
} }
} }
} }
start += PAGE_SIZE; start += PAGE_SIZE;
++ptep; ++ptep;
} while ( start < pmd_end ); } while (start < pmd_end);
} } else {
else
start = pmd_end; start = pmd_end;
}
++pmd; ++pmd;
} while ( start < pgd_end ); } while (start < pgd_end);
} } else {
else
start = pgd_end; start = pgd_end;
}
++pgd; ++pgd;
} while ( start < end ); } while (start < end);
if (i) if (i)
flush_hash_range(context, i, local); flush_hash_range(context, i, local);
...@@ -435,12 +411,12 @@ void __init mm_init_ppc64(void) ...@@ -435,12 +411,12 @@ void __init mm_init_ppc64(void)
* The range of contexts [FIRST_USER_CONTEXT, NUM_USER_CONTEXT) * The range of contexts [FIRST_USER_CONTEXT, NUM_USER_CONTEXT)
* are stored on a stack/queue for easy allocation and deallocation. * are stored on a stack/queue for easy allocation and deallocation.
*/ */
mmu_context_queue.lock = SPIN_LOCK_UNLOCKED; mmu_context_queue.lock = SPIN_LOCK_UNLOCKED;
mmu_context_queue.head = 0; mmu_context_queue.head = 0;
mmu_context_queue.tail = NUM_USER_CONTEXT-1; mmu_context_queue.tail = NUM_USER_CONTEXT-1;
mmu_context_queue.size = NUM_USER_CONTEXT; mmu_context_queue.size = NUM_USER_CONTEXT;
for(index=0; index < NUM_USER_CONTEXT ;index++) { for(index=0; index < NUM_USER_CONTEXT ;index++) {
mmu_context_queue.elements[index] = index+FIRST_USER_CONTEXT; mmu_context_queue.elements[index] = index+FIRST_USER_CONTEXT;
} }
/* Setup guard pages for the Paca's */ /* Setup guard pages for the Paca's */
...@@ -463,7 +439,6 @@ void __init do_init_bootmem(void) ...@@ -463,7 +439,6 @@ void __init do_init_bootmem(void)
unsigned long start, bootmap_pages; unsigned long start, bootmap_pages;
unsigned long total_pages = lmb_end_of_DRAM() >> PAGE_SHIFT; unsigned long total_pages = lmb_end_of_DRAM() >> PAGE_SHIFT;
PPCDBG(PPCDBG_MMINIT, "do_init_bootmem: start\n");
/* /*
* Find an area to use for the bootmem bitmap. Calculate the size of * Find an area to use for the bootmem bitmap. Calculate the size of
* bitmap required as (Total Memory) / PAGE_SIZE / BITS_PER_BYTE. * bitmap required as (Total Memory) / PAGE_SIZE / BITS_PER_BYTE.
...@@ -472,21 +447,16 @@ void __init do_init_bootmem(void) ...@@ -472,21 +447,16 @@ void __init do_init_bootmem(void)
bootmap_pages = bootmem_bootmap_pages(total_pages); bootmap_pages = bootmem_bootmap_pages(total_pages);
start = (unsigned long)__a2p(lmb_alloc(bootmap_pages<<PAGE_SHIFT, PAGE_SIZE)); start = (unsigned long)__a2p(lmb_alloc(bootmap_pages<<PAGE_SHIFT, PAGE_SIZE));
if( start == 0 ) { if (start == 0) {
udbg_printf("do_init_bootmem: failed to allocate a bitmap.\n"); udbg_printf("do_init_bootmem: failed to allocate a bitmap.\n");
udbg_printf("\tbootmap_pages = 0x%lx.\n", bootmap_pages); udbg_printf("\tbootmap_pages = 0x%lx.\n", bootmap_pages);
PPCDBG_ENTER_DEBUGGER(); PPCDBG_ENTER_DEBUGGER();
} }
PPCDBG(PPCDBG_MMINIT, "\tstart = 0x%lx\n", start);
PPCDBG(PPCDBG_MMINIT, "\tbootmap_pages = 0x%lx\n", bootmap_pages);
PPCDBG(PPCDBG_MMINIT, "\tphysicalMemorySize = 0x%lx\n", naca->physicalMemorySize);
boot_mapsize = init_bootmem(start >> PAGE_SHIFT, total_pages); boot_mapsize = init_bootmem(start >> PAGE_SHIFT, total_pages);
PPCDBG(PPCDBG_MMINIT, "\tboot_mapsize = 0x%lx\n", boot_mapsize);
/* add all physical memory to the bootmem map */ /* add all physical memory to the bootmem map */
for (i=0; i < lmb.memory.cnt ;i++) { for (i=0; i < lmb.memory.cnt; i++) {
unsigned long physbase, size; unsigned long physbase, size;
unsigned long type = lmb.memory.region[i].type; unsigned long type = lmb.memory.region[i].type;
...@@ -497,19 +467,14 @@ void __init do_init_bootmem(void) ...@@ -497,19 +467,14 @@ void __init do_init_bootmem(void)
size = lmb.memory.region[i].size; size = lmb.memory.region[i].size;
free_bootmem(physbase, size); free_bootmem(physbase, size);
} }
/* reserve the sections we're already using */ /* reserve the sections we're already using */
for (i=0; i < lmb.reserved.cnt ;i++) { for (i=0; i < lmb.reserved.cnt; i++) {
unsigned long physbase = lmb.reserved.region[i].physbase; unsigned long physbase = lmb.reserved.region[i].physbase;
unsigned long size = lmb.reserved.region[i].size; unsigned long size = lmb.reserved.region[i].size;
#if 0 /* PPPBBB */
if ( (physbase == 0) && (size < (16<<20)) ) {
size = 16 << 20;
}
#endif
reserve_bootmem(physbase, size); reserve_bootmem(physbase, size);
} }
PPCDBG(PPCDBG_MMINIT, "do_init_bootmem: end\n");
} }
/* /*
...@@ -522,7 +487,7 @@ void __init paging_init(void) ...@@ -522,7 +487,7 @@ void __init paging_init(void)
/* /*
* All pages are DMA-able so we put them all in the DMA zone. * All pages are DMA-able so we put them all in the DMA zone.
*/ */
zones_size[0] = lmb_end_of_DRAM() >> PAGE_SHIFT; zones_size[ZONE_DMA] = lmb_end_of_DRAM() >> PAGE_SHIFT;
for (i = 1; i < MAX_NR_ZONES; i++) for (i = 1; i < MAX_NR_ZONES; i++)
zones_size[i] = 0; zones_size[i] = 0;
free_area_init(zones_size); free_area_init(zones_size);
...@@ -554,14 +519,6 @@ void __init mem_init(void) ...@@ -554,14 +519,6 @@ void __init mem_init(void)
totalram_pages += free_all_bootmem(); totalram_pages += free_all_bootmem();
ifppcdebug(PPCDBG_MMINIT) {
udbg_printf("mem_init: totalram_pages = 0x%lx\n", totalram_pages);
udbg_printf("mem_init: va_rtas_base = 0x%lx\n", va_rtas_base);
udbg_printf("mem_init: va_rtas_end = 0x%lx\n", PAGE_ALIGN(va_rtas_base+rtas.size));
udbg_printf("mem_init: pinned start = 0x%lx\n", __va(0));
udbg_printf("mem_init: pinned end = 0x%lx\n", PAGE_ALIGN(klimit));
}
if ( sysmap_size ) if ( sysmap_size )
for (addr = (unsigned long)sysmap; for (addr = (unsigned long)sysmap;
addr < PAGE_ALIGN((unsigned long)sysmap+sysmap_size) ; addr < PAGE_ALIGN((unsigned long)sysmap+sysmap_size) ;
...@@ -582,7 +539,7 @@ void __init mem_init(void) ...@@ -582,7 +539,7 @@ void __init mem_init(void)
datapages++; datapages++;
} }
printk("Memory: %luk available (%dk kernel code, %dk data, %dk init) [%08lx,%08lx]\n", printk("Memory: %luk available (%dk kernel code, %dk data, %dk init) [%08lx,%08lx]\n",
(unsigned long)nr_free_pages()<< (PAGE_SHIFT-10), (unsigned long)nr_free_pages()<< (PAGE_SHIFT-10),
codepages<< (PAGE_SHIFT-10), datapages<< (PAGE_SHIFT-10), codepages<< (PAGE_SHIFT-10), datapages<< (PAGE_SHIFT-10),
initpages<< (PAGE_SHIFT-10), initpages<< (PAGE_SHIFT-10),
...@@ -613,6 +570,12 @@ void flush_dcache_page(struct page *page) ...@@ -613,6 +570,12 @@ void flush_dcache_page(struct page *page)
void flush_icache_page(struct vm_area_struct *vma, struct page *page) void flush_icache_page(struct vm_area_struct *vma, struct page *page)
{ {
if (__is_processor(PV_POWER4))
return;
if ((vma->vm_flags & VM_EXEC) == 0)
return;
if (page->mapping && !PageReserved(page) if (page->mapping && !PageReserved(page)
&& !test_bit(PG_arch_1, &page->flags)) { && !test_bit(PG_arch_1, &page->flags)) {
__flush_dcache_icache(page_address(page)); __flush_dcache_icache(page_address(page));
...@@ -620,15 +583,35 @@ void flush_icache_page(struct vm_area_struct *vma, struct page *page) ...@@ -620,15 +583,35 @@ void flush_icache_page(struct vm_area_struct *vma, struct page *page)
} }
} }
void clear_user_page(void *page, unsigned long vaddr) void clear_user_page(void *page, unsigned long vaddr, struct page *pg)
{ {
clear_page(page); clear_page(page);
/* XXX we shouldnt have to do this, but glibc requires it */
if (__is_processor(PV_POWER4))
clear_bit(PG_arch_1, &pg->flags);
else
__flush_dcache_icache(page);
} }
void copy_user_page(void *vto, void *vfrom, unsigned long vaddr) void copy_user_page(void *vto, void *vfrom, unsigned long vaddr,
struct page *pg)
{ {
copy_page(vto, vfrom); copy_page(vto, vfrom);
__flush_dcache_icache(vto);
/*
* Unfortunately we havent always marked our GOT and PLT sections
* as executable, so we need to flush all file regions - Anton
*/
#if 0
if (!vma->vm_file && ((vma->vm_flags & VM_EXEC) == 0))
return;
#endif
if (__is_processor(PV_POWER4))
clear_bit(PG_arch_1, &pg->flags);
else
__flush_dcache_icache(vto);
} }
void flush_icache_user_range(struct vm_area_struct *vma, struct page *page, void flush_icache_user_range(struct vm_area_struct *vma, struct page *page,
...@@ -642,7 +625,7 @@ void flush_icache_user_range(struct vm_area_struct *vma, struct page *page, ...@@ -642,7 +625,7 @@ void flush_icache_user_range(struct vm_area_struct *vma, struct page *page,
extern pte_t *find_linux_pte(pgd_t *pgdir, unsigned long ea); extern pte_t *find_linux_pte(pgd_t *pgdir, unsigned long ea);
int __hash_page(unsigned long ea, unsigned long access, unsigned long vsid, int __hash_page(unsigned long ea, unsigned long access, unsigned long vsid,
pte_t *ptep); pte_t *ptep, unsigned long trap);
/* /*
* This is called at the end of handling a user page fault, when the * This is called at the end of handling a user page fault, when the
...@@ -670,5 +653,6 @@ void update_mmu_cache(struct vm_area_struct *vma, unsigned long ea, ...@@ -670,5 +653,6 @@ void update_mmu_cache(struct vm_area_struct *vma, unsigned long ea,
ptep = find_linux_pte(pgdir, ea); ptep = find_linux_pte(pgdir, ea);
vsid = get_vsid(vma->vm_mm->context, ea); vsid = get_vsid(vma->vm_mm->context, ea);
__hash_page(ea, pte_val(pte) & (_PAGE_USER|_PAGE_RW), vsid, ptep); __hash_page(ea, pte_val(pte) & (_PAGE_USER|_PAGE_RW), vsid, ptep,
0x300);
} }
...@@ -117,19 +117,6 @@ SECTIONS ...@@ -117,19 +117,6 @@ SECTIONS
. = ALIGN(4096); . = ALIGN(4096);
__init_end = .; __init_end = .;
__chrp_begin = .;
.text.chrp : { *(.text.chrp) }
.data.chrp : { *(.data.chrp) }
. = ALIGN(4096);
__chrp_end = .;
. = ALIGN(4096);
__openfirmware_begin = .;
.text.openfirmware : { *(.text.openfirmware) }
.data.openfirmware : { *(.data.openfirmware) }
. = ALIGN(4096);
__openfirmware_end = .;
__toc_start = .; __toc_start = .;
.toc : .toc :
{ {
......
...@@ -6,7 +6,6 @@ ...@@ -6,7 +6,6 @@
* as published by the Free Software Foundation; either version * as published by the Free Software Foundation; either version
* 2 of the License, or (at your option) any later version. * 2 of the License, or (at your option) any later version.
*/ */
#include <linux/config.h>
#define GETREG(reg) \ #define GETREG(reg) \
static inline unsigned long get_ ## reg (void) \ static inline unsigned long get_ ## reg (void) \
......
...@@ -123,11 +123,7 @@ static void mem_translate(void); ...@@ -123,11 +123,7 @@ static void mem_translate(void);
static void mem_check(void); static void mem_check(void);
static void mem_find_real(void); static void mem_find_real(void);
static void mem_find_vsid(void); static void mem_find_vsid(void);
static void mem_check_pagetable_vsids (void);
static void mem_map_check_slab(void);
static void mem_map_lock_pages(void);
static void mem_check_dup_rpn (void);
static void debug_trace(void); static void debug_trace(void);
extern int print_insn_big_powerpc(FILE *, unsigned long, unsigned long); extern int print_insn_big_powerpc(FILE *, unsigned long, unsigned long);
...@@ -642,27 +638,15 @@ cmds(struct pt_regs *excp) ...@@ -642,27 +638,15 @@ cmds(struct pt_regs *excp)
case 'c': case 'c':
mem_check(); mem_check();
break; break;
case 'j':
mem_map_check_slab();
break;
case 'f': case 'f':
mem_find_real(); mem_find_real();
break; break;
case 'e': case 'e':
mem_find_vsid(); mem_find_vsid();
break; break;
case 'r':
mem_check_dup_rpn();
break;
case 'i': case 'i':
show_mem(); show_mem();
break; break;
case 'o':
mem_check_pagetable_vsids ();
break;
case 'q':
mem_map_lock_pages() ;
break;
default: default:
termch = cmd; termch = cmd;
memex(); memex();
...@@ -2458,249 +2442,6 @@ void mem_find_vsid() ...@@ -2458,249 +2442,6 @@ void mem_find_vsid()
printf("\nDone -------------------\n"); printf("\nDone -------------------\n");
} }
void mem_map_check_slab()
{
int i, slab_count;
i = max_mapnr;
slab_count = 0;
while (i-- > 0) {
if (PageSlab(mem_map+i)){
printf(" slab entry - mem_map entry =%p \n", mem_map+i);
slab_count ++;
}
}
printf(" count of pages for slab = %d \n", slab_count);
}
void mem_map_lock_pages()
{
int i, lock_count;
i = max_mapnr;
lock_count = 0;
while (i-- > 0) {
if (PageLocked(mem_map+i)){
printf(" locked entry - mem_map entry =%p \n", mem_map+i);
lock_count ++;
}
}
printf(" count of locked pages = %d \n", lock_count);
}
void mem_check_dup_rpn ()
{
unsigned long htab_size_bytes;
unsigned long htab_end;
unsigned long last_rpn;
HPTE *hpte1, *hpte2;
int dup_count;
struct task_struct *p;
unsigned long kernel_vsid_c0,kernel_vsid_c1,kernel_vsid_c2,kernel_vsid_c3;
unsigned long kernel_vsid_c4,kernel_vsid_c5,kernel_vsid_d,kernel_vsid_e;
unsigned long kernel_vsid_f;
unsigned long vsid0,vsid1,vsidB,vsid2;
htab_size_bytes = htab_data.htab_num_ptegs * 128; // 128B / PTEG
htab_end = (unsigned long)htab_data.htab + htab_size_bytes;
// last_rpn = (naca->physicalMemorySize-1) >> PAGE_SHIFT;
last_rpn = 0xfffff;
printf("\nHardware Page Table Check\n-------------------\n");
printf("htab base : %.16lx\n", htab_data.htab);
printf("htab size : %.16lx\n", htab_size_bytes);
for(hpte1 = htab_data.htab; hpte1 < (HPTE *)htab_end; hpte1++) {
if ( hpte1->dw0.dw0.v != 0 ) {
if ( hpte1->dw1.dw1.rpn <= last_rpn ) {
dup_count = 0;
for(hpte2 = hpte1+1; hpte2 < (HPTE *)htab_end; hpte2++) {
if ( hpte2->dw0.dw0.v != 0 ) {
if(hpte1->dw1.dw1.rpn == hpte2->dw1.dw1.rpn) {
dup_count++;
}
}
}
if(dup_count > 5) {
printf(" Duplicate rpn: %.13lx \n", (hpte1->dw1.dw1.rpn));
printf(" mem map array entry %p count = %d \n",
(mem_map+(hpte1->dw1.dw1.rpn)), (mem_map+(hpte1->dw1.dw1.rpn))->count);
for(hpte2 = hpte1+1; hpte2 < (HPTE *)htab_end; hpte2++) {
if ( hpte2->dw0.dw0.v != 0 ) {
if(hpte1->dw1.dw1.rpn == hpte2->dw1.dw1.rpn) {
printf(" hpte2: %16.16lx *hpte2: %16.16lx %16.16lx\n",
hpte2, hpte2->dw0.dword0, hpte2->dw1.dword1);
}
}
}
}
} else {
printf(" Bogus rpn: %.13lx \n", (hpte1->dw1.dw1.rpn));
printf(" hpte: %16.16lx *hpte: %16.16lx %16.16lx\n",
hpte1, hpte1->dw0.dword0, hpte1->dw1.dword1);
}
}
if (xmon_interrupted())
return;
}
// print the kernel vsids
kernel_vsid_c0 = get_kernel_vsid(0xC000000000000000);
kernel_vsid_c1 = get_kernel_vsid(0xC000000010000000);
kernel_vsid_c2 = get_kernel_vsid(0xC000000020000000);
kernel_vsid_c3 = get_kernel_vsid(0xC000000030000000);
kernel_vsid_c4 = get_kernel_vsid(0xC000000040000000);
kernel_vsid_c5 = get_kernel_vsid(0xC000000050000000);
kernel_vsid_d = get_kernel_vsid(0xD000000000000000);
kernel_vsid_e = get_kernel_vsid(0xE000000000000000);
kernel_vsid_f = get_kernel_vsid(0xF000000000000000);
printf(" kernel vsid - seg c0 = %lx\n", kernel_vsid_c0 );
printf(" kernel vsid - seg c1 = %lx\n", kernel_vsid_c1 );
printf(" kernel vsid - seg c2 = %lx\n", kernel_vsid_c2 );
printf(" kernel vsid - seg c3 = %lx\n", kernel_vsid_c3 );
printf(" kernel vsid - seg c4 = %lx\n", kernel_vsid_c4 );
printf(" kernel vsid - seg c5 = %lx\n", kernel_vsid_c5 );
printf(" kernel vsid - seg d = %lx\n", kernel_vsid_d );
printf(" kernel vsid - seg e = %lx\n", kernel_vsid_e );
printf(" kernel vsid - seg f = %lx\n", kernel_vsid_f );
// print a list of valid vsids for the tasks
read_lock(&tasklist_lock);
for_each_task(p)
if(p->mm) {
struct mm_struct *mm = p->mm;
printf(" task = %p mm = %lx pgd %lx\n",
p, mm, mm->pgd);
vsid0 = get_vsid( mm->context, 0 );
vsid1 = get_vsid( mm->context, 0x10000000 );
vsid2 = get_vsid( mm->context, 0x20000000 );
vsidB = get_vsid( mm->context, 0xB0000000 );
printf(" context = %lx vsid seg 0 = %lx\n", mm->context, vsid0 );
printf(" vsid seg 1 = %lx\n", vsid1 );
printf(" vsid seg 2 = %lx\n", vsid2 );
printf(" vsid seg 2 = %lx\n", vsidB );
printf("\n");
};
read_unlock(&tasklist_lock);
printf("\nDone -------------------\n");
}
void mem_check_pagetable_vsids ()
{
unsigned long htab_size_bytes;
unsigned long htab_end;
unsigned long last_rpn;
struct task_struct *p;
unsigned long valid_table_count,invalid_table_count,bogus_rpn_count;
int found;
unsigned long user_address_table_count,kernel_page_table_count;
unsigned long pt_vsid;
HPTE *hpte1;
htab_size_bytes = htab_data.htab_num_ptegs * 128; // 128B / PTEG
htab_end = (unsigned long)htab_data.htab + htab_size_bytes;
// last_rpn = (naca->physicalMemorySize-1) >> PAGE_SHIFT;
last_rpn = 0xfffff;
printf("\nHardware Page Table Check\n-------------------\n");
printf("htab base : %.16lx\n", htab_data.htab);
printf("htab size : %.16lx\n", htab_size_bytes);
valid_table_count = 0;
invalid_table_count = 0;
bogus_rpn_count = 0;
user_address_table_count = 0;
kernel_page_table_count = 0;
for(hpte1 = htab_data.htab; hpte1 < (HPTE *)htab_end; hpte1++) {
if ( hpte1->dw0.dw0.v != 0 ) {
valid_table_count++;
if ( hpte1->dw1.dw1.rpn <= last_rpn ) {
pt_vsid = (hpte1->dw0.dw0.avpn) >> 5;
if ((pt_vsid == get_kernel_vsid(0xC000000000000000)) |
(pt_vsid == get_kernel_vsid(0xC000000010000000)) |
(pt_vsid == get_kernel_vsid(0xC000000020000000)) |
(pt_vsid == get_kernel_vsid(0xC000000030000000)) |
(pt_vsid == get_kernel_vsid(0xC000000040000000)) |
(pt_vsid == get_kernel_vsid(0xC000000050000000)) |
(pt_vsid == get_kernel_vsid(0xD000000000000000)) |
(pt_vsid == get_kernel_vsid(0xE000000000000000)) |
(pt_vsid == get_kernel_vsid(0xF000000000000000)) ) {
kernel_page_table_count ++;
} else {
read_lock(&tasklist_lock);
found = 0;
for_each_task(p) {
if(p->mm && (found == 0)) {
struct mm_struct *mm = p->mm;
if ((pt_vsid == get_vsid( mm->context, 0 )) |
(pt_vsid == get_vsid( mm->context, 0x10000000 )) |
(pt_vsid == get_vsid( mm->context, 0x20000000 )) |
(pt_vsid == get_vsid( mm->context, 0x30000000 )) |
(pt_vsid == get_vsid( mm->context, 0x40000000 )) |
(pt_vsid == get_vsid( mm->context, 0x50000000 )) |
(pt_vsid == get_vsid( mm->context, 0x60000000 )) |
(pt_vsid == get_vsid( mm->context, 0x70000000 )) |
(pt_vsid == get_vsid( mm->context, 0x80000000 )) |
(pt_vsid == get_vsid( mm->context, 0x90000000 )) |
(pt_vsid == get_vsid( mm->context, 0xA0000000 )) |
(pt_vsid == get_vsid( mm->context, 0xB0000000 ))) {
user_address_table_count ++;
found = 1;
}
}
}
read_unlock(&tasklist_lock);
if (found == 0)
{
printf(" vsid not found vsid = %lx, hpte = %p \n",
pt_vsid,hpte1);
printf(" rpn in entry = %lx \n", hpte1->dw1.dw1.rpn);
printf(" mem map address = %lx \n", mem_map + (hpte1->dw1.dw1.rpn));
} else // found
{
}
} // good rpn
} else {
bogus_rpn_count ++;
}
} else {
invalid_table_count++;
}
}
printf(" page table valid counts - valid entries = %lx invalid entries = %lx \n",
valid_table_count, invalid_table_count);
printf(" bogus rpn entries ( probably io) = %lx \n", bogus_rpn_count);
printf(" page table counts - kernel entries = %lx user entries = %lx \n",
kernel_page_table_count, user_address_table_count);
printf("\nDone -------------------\n");
}
static void debug_trace(void) { static void debug_trace(void) {
unsigned long val, cmd, on; unsigned long val, cmd, on;
......
...@@ -259,6 +259,12 @@ static __inline__ int ffs(int x) ...@@ -259,6 +259,12 @@ static __inline__ int ffs(int x)
return __ilog2(i & -i) + 1; return __ilog2(i & -i) + 1;
} }
/*
* fls: find last (most-significant) bit set.
* Note fls(0) = 0, fls(1) = 1, fls(0x80000000) = 32.
*/
#define fls(x) generic_fls(x)
/* /*
* hweightN: returns the hamming weight (i.e. the number * hweightN: returns the hamming weight (i.e. the number
* of bits set) of a N-bit word * of bits set) of a N-bit word
......
...@@ -8,6 +8,7 @@ ...@@ -8,6 +8,7 @@
#define __ARCH_PPC64_CACHE_H #define __ARCH_PPC64_CACHE_H
/* bytes per L1 cache line */ /* bytes per L1 cache line */
#define L1_CACHE_BYTES 128 #define L1_CACHE_SHIFT 7
#define L1_CACHE_BYTES (1 << L1_CACHE_SHIFT)
#endif #endif
...@@ -130,6 +130,9 @@ enum HvCall_VaryOffChunkRc ...@@ -130,6 +130,9 @@ enum HvCall_VaryOffChunkRc
#define HvCallBaseRouter28 HvCallBase + 28 #define HvCallBaseRouter28 HvCallBase + 28
#define HvCallBaseRouter29 HvCallBase + 29 #define HvCallBaseRouter29 HvCallBase + 29
#define HvCallBaseRouter30 HvCallBase + 30 #define HvCallBaseRouter30 HvCallBase + 30
#define HvCallCcSetDABR HvCallCc + 7
//===================================================================================== //=====================================================================================
static inline void HvCall_setVirtualDecr(void) static inline void HvCall_setVirtualDecr(void)
{ {
...@@ -197,6 +200,10 @@ static inline void HvCall_terminateMachineSrc(void) ...@@ -197,6 +200,10 @@ static inline void HvCall_terminateMachineSrc(void)
HvCall0( HvCallBaseTerminateMachineSrc ); HvCall0( HvCallBaseTerminateMachineSrc );
} }
static inline void HvCall_setDABR(unsigned long val)
{
HvCall1(HvCallCcSetDABR, val);
}
#endif // _HVCALL_H #endif // _HVCALL_H
...@@ -106,21 +106,21 @@ static inline u64 HvCallHpt_invalidateSetSwBitsGet(u32 hpteIndex, u8 bitson, u8 ...@@ -106,21 +106,21 @@ static inline u64 HvCallHpt_invalidateSetSwBitsGet(u32 hpteIndex, u8 bitson, u8
return compressedStatus; return compressedStatus;
} }
//============================================================================= //=============================================================================
static inline u64 HvCallHpt_findValid( struct HPTE *hpte, u64 vpn ) static inline u64 HvCallHpt_findValid( HPTE *hpte, u64 vpn )
{ {
u64 retIndex = HvCall3Ret16( HvCallHptFindValid, hpte, vpn, 0, 0 ); u64 retIndex = HvCall3Ret16( HvCallHptFindValid, hpte, vpn, 0, 0 );
// getPaca()->adjustHmtForNoOfSpinLocksHeld(); // getPaca()->adjustHmtForNoOfSpinLocksHeld();
return retIndex; return retIndex;
} }
//============================================================================= //=============================================================================
static inline u64 HvCallHpt_findNextValid( struct HPTE *hpte, u32 hpteIndex, u8 bitson, u8 bitsoff ) static inline u64 HvCallHpt_findNextValid( HPTE *hpte, u32 hpteIndex, u8 bitson, u8 bitsoff )
{ {
u64 retIndex = HvCall3Ret16( HvCallHptFindNextValid, hpte, hpteIndex, bitson, bitsoff ); u64 retIndex = HvCall3Ret16( HvCallHptFindNextValid, hpte, hpteIndex, bitson, bitsoff );
// getPaca()->adjustHmtForNoOfSpinLocksHeld(); // getPaca()->adjustHmtForNoOfSpinLocksHeld();
return retIndex; return retIndex;
} }
//============================================================================= //=============================================================================
static inline void HvCallHpt_get( struct HPTE *hpte, u32 hpteIndex ) static inline void HvCallHpt_get( HPTE *hpte, u32 hpteIndex )
{ {
HvCall2Ret16( HvCallHptGet, hpte, hpteIndex, 0 ); HvCall2Ret16( HvCallHptGet, hpte, hpteIndex, 0 );
// getPaca()->adjustHmtForNoOfSpinLocksHeld(); // getPaca()->adjustHmtForNoOfSpinLocksHeld();
...@@ -128,7 +128,7 @@ static inline void HvCallHpt_get( struct HPTE *hpte, u32 hpteIndex ) ...@@ -128,7 +128,7 @@ static inline void HvCallHpt_get( struct HPTE *hpte, u32 hpteIndex )
//============================================================================ //============================================================================
static inline void HvCallHpt_addValidate( u32 hpteIndex, static inline void HvCallHpt_addValidate( u32 hpteIndex,
u32 hBit, u32 hBit,
struct HPTE *hpte ) HPTE *hpte )
{ {
HvCall4( HvCallHptAddValidate, hpteIndex, HvCall4( HvCallHptAddValidate, hpteIndex,
......
...@@ -25,6 +25,7 @@ ...@@ -25,6 +25,7 @@
#define _HVCALLSC_H #define _HVCALLSC_H
#define HvCallBase 0x8000000000000000 #define HvCallBase 0x8000000000000000
#define HvCallCc 0x8001000000000000
#define HvCallCfg 0x8002000000000000 #define HvCallCfg 0x8002000000000000
#define HvCallEvent 0x8003000000000000 #define HvCallEvent 0x8003000000000000
#define HvCallHpt 0x8004000000000000 #define HvCallHpt 0x8004000000000000
......
#ifndef _PPC64_INIT_H #error "<asm/init.h> should never be used - use <linux/init.h> instead"
#define _PPC64_INIT_H
#include <linux/init.h>
#if __GNUC__ > 2 || __GNUC_MINOR__ >= 90 /* egcs */
/* DRENG add back in when we get section attribute support */
#define __chrp __attribute__ ((__section__ (".text.chrp")))
#define __chrpdata __attribute__ ((__section__ (".data.chrp")))
#define __chrpfunc(__argchrp) \
__argchrp __chrp; \
__argchrp
/* this is actually just common chrp/pmac code, not OF code -- Cort */
#define __openfirmware __attribute__ ((__section__ (".text.openfirmware")))
#define __openfirmwaredata __attribute__ ((__section__ (".data.openfirmware")))
#define __openfirmwarefunc(__argopenfirmware) \
__argopenfirmware __openfirmware; \
__argopenfirmware
#else /* not egcs */
#define __openfirmware
#define __openfirmwaredata
#define __openfirmwarefunc(x) x
#endif /* egcs */
#endif /* _PPC64_INIT_H */
...@@ -13,6 +13,7 @@ ...@@ -13,6 +13,7 @@
* 2 of the License, or (at your option) any later version. * 2 of the License, or (at your option) any later version.
*/ */
#include <linux/config.h>
#include <asm/prom.h> #include <asm/prom.h>
extern unsigned long reloc_offset(void); extern unsigned long reloc_offset(void);
......
/*
* md.h: High speed xor_block operation for RAID4/5
*
* 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 the Free Software Foundation; either version
* 2 of the License, or (at your option) any later version.
*/
#ifndef __ASM_MD_H
#define __ASM_MD_H
/* #define HAVE_ARCH_XORBLOCK */
#define MD_XORBLOCK_ALIGNMENT sizeof(long)
#endif /* __ASM_MD_H */
/*
* Written by Kanoj Sarcar (kanoj@sgi.com) Aug 99
*
* PowerPC64 port:
* Copyright (C) 2002 Anton Blanchard, IBM Corp.
*/
#ifndef _ASM_MMZONE_H_
#define _ASM_MMZONE_H_
#include <linux/config.h>
typedef struct plat_pglist_data {
pg_data_t gendata;
} plat_pg_data_t;
/*
* Following are macros that are specific to this numa platform.
*/
extern plat_pg_data_t plat_node_data[];
#define MAX_NUMNODES 4
/* XXX grab this from the device tree - Anton */
#define PHYSADDR_TO_NID(pa) ((pa) >> 36)
#define PLAT_NODE_DATA(n) (&plat_node_data[(n)])
#define PLAT_NODE_DATA_STARTNR(n) \
(PLAT_NODE_DATA(n)->gendata.node_start_mapnr)
#define PLAT_NODE_DATA_SIZE(n) (PLAT_NODE_DATA(n)->gendata.node_size)
#define PLAT_NODE_DATA_LOCALNR(p, n) \
(((p) - PLAT_NODE_DATA(n)->gendata.node_start_paddr) >> PAGE_SHIFT)
#ifdef CONFIG_DISCONTIGMEM
/*
* Following are macros that each numa implmentation must define.
*/
/*
* Given a kernel address, find the home node of the underlying memory.
*/
#define KVADDR_TO_NID(kaddr) PHYSADDR_TO_NID(__pa(kaddr))
/*
* Return a pointer to the node data for node n.
*/
#define NODE_DATA(n) (&((PLAT_NODE_DATA(n))->gendata))
/*
* NODE_MEM_MAP gives the kaddr for the mem_map of the node.
*/
#define NODE_MEM_MAP(nid) (NODE_DATA(nid)->node_mem_map)
/*
* Given a kaddr, ADDR_TO_MAPBASE finds the owning node of the memory
* and returns the mem_map of that node.
*/
#define ADDR_TO_MAPBASE(kaddr) \
NODE_MEM_MAP(KVADDR_TO_NID((unsigned long)(kaddr)))
/*
* Given a kaddr, LOCAL_BASE_ADDR finds the owning node of the memory
* and returns the kaddr corresponding to first physical page in the
* node's mem_map.
*/
#define LOCAL_BASE_ADDR(kaddr) \
((unsigned long)__va(NODE_DATA(KVADDR_TO_NID(kaddr))->node_start_paddr))
#define LOCAL_MAP_NR(kvaddr) \
(((unsigned long)(kvaddr)-LOCAL_BASE_ADDR(kvaddr)) >> PAGE_SHIFT)
#if 0
/* XXX fix - Anton */
#define kern_addr_valid(kaddr) test_bit(LOCAL_MAP_NR(kaddr), \
NODE_DATA(KVADDR_TO_NID(kaddr))->valid_addr_bitmap)
#endif
#define discontigmem_pfn_to_page(pfn) \
({ \
unsigned long kaddr = (unsigned long)__va(pfn << PAGE_SHIFT); \
(ADDR_TO_MAPBASE(kaddr) + LOCAL_MAP_NR(kaddr)); \
})
#ifdef CONFIG_NUMA
/* XXX grab this from the device tree - Anton */
#define cputonode(cpu) ((cpu) >> 3)
#define numa_node_id() cputonode(smp_processor_id())
#endif /* CONFIG_NUMA */
#endif /* CONFIG_DISCONTIGMEM */
#endif /* _ASM_MMZONE_H_ */
...@@ -33,24 +33,13 @@ ...@@ -33,24 +33,13 @@
#ifndef __ASSEMBLY__ #ifndef __ASSEMBLY__
#include <asm/naca.h> #include <asm/naca.h>
#define STRICT_MM_TYPECHECKS #undef STRICT_MM_TYPECHECKS
#define REGION_SIZE 4UL #define REGION_SIZE 4UL
#define OFFSET_SIZE 60UL
#define REGION_SHIFT 60UL #define REGION_SHIFT 60UL
#define OFFSET_SHIFT 0UL
#define REGION_MASK (((1UL<<REGION_SIZE)-1UL)<<REGION_SHIFT) #define REGION_MASK (((1UL<<REGION_SIZE)-1UL)<<REGION_SHIFT)
#define REGION_STRIDE (1UL << REGION_SHIFT) #define REGION_STRIDE (1UL << REGION_SHIFT)
typedef union ppc64_va {
struct {
unsigned long off : OFFSET_SIZE; /* intra-region offset */
unsigned long reg : REGION_SIZE; /* region number */
} f;
unsigned long l;
void *p;
} ppc64_va;
static __inline__ void clear_page(void *addr) static __inline__ void clear_page(void *addr)
{ {
unsigned long lines, line_size; unsigned long lines, line_size;
...@@ -70,8 +59,8 @@ static __inline__ void clear_page(void *addr) ...@@ -70,8 +59,8 @@ static __inline__ void clear_page(void *addr)
extern void copy_page(void *to, void *from); extern void copy_page(void *to, void *from);
struct page; struct page;
extern void clear_user_page(void *page, unsigned long vaddr); extern void clear_user_page(void *page, unsigned long vaddr, struct page *pg);
extern void copy_user_page(void *to, void *from, unsigned long vaddr); extern void copy_user_page(void *to, void *from, unsigned long vaddr, struct page *p);
#ifdef STRICT_MM_TYPECHECKS #ifdef STRICT_MM_TYPECHECKS
/* /*
...@@ -215,8 +204,15 @@ static inline int get_order(unsigned long size) ...@@ -215,8 +204,15 @@ static inline int get_order(unsigned long size)
#define __a2p(x) ((void *) absolute_to_phys(x)) #define __a2p(x) ((void *) absolute_to_phys(x))
#define __a2v(x) ((void *) __va(absolute_to_phys(x))) #define __a2v(x) ((void *) __va(absolute_to_phys(x)))
#ifdef CONFIG_DISCONTIGMEM
#define page_to_pfn(page) \
((page) - page_zone(page)->zone_mem_map + \
(page_zone(page)->zone_start_paddr >> PAGE_SHIFT))
#define pfn_to_page(pfn) discontigmem_pfn_to_page(pfn)
#else
#define pfn_to_page(pfn) (mem_map + (pfn)) #define pfn_to_page(pfn) (mem_map + (pfn))
#define page_to_pfn(pfn) ((unsigned long)((pfn) - mem_map)) #define page_to_pfn(page) ((unsigned long)((page) - mem_map))
#endif
#define virt_to_page(kaddr) pfn_to_page(__pa(kaddr) >> PAGE_SHIFT) #define virt_to_page(kaddr) pfn_to_page(__pa(kaddr) >> PAGE_SHIFT)
#define pfn_valid(pfn) ((pfn) < max_mapnr) #define pfn_valid(pfn) ((pfn) < max_mapnr)
......
...@@ -53,6 +53,8 @@ pmd_free(pmd_t *pmd) ...@@ -53,6 +53,8 @@ pmd_free(pmd_t *pmd)
free_page((unsigned long)pmd); free_page((unsigned long)pmd);
} }
#define pmd_free_tlb(tlb, pmd) pmd_free(pmd)
#define pmd_populate_kernel(mm, pmd, pte) pmd_set(pmd, pte) #define pmd_populate_kernel(mm, pmd, pte) pmd_set(pmd, pte)
#define pmd_populate(mm, pmd, pte_page) \ #define pmd_populate(mm, pmd, pte_page) \
pmd_populate_kernel(mm, pmd, page_address(pte_page)) pmd_populate_kernel(mm, pmd, page_address(pte_page))
...@@ -86,6 +88,7 @@ pte_free_kernel(pte_t *pte) ...@@ -86,6 +88,7 @@ pte_free_kernel(pte_t *pte)
} }
#define pte_free(pte_page) pte_free_kernel(page_address(pte_page)) #define pte_free(pte_page) pte_free_kernel(page_address(pte_page))
#define pte_free_tlb(tlb, pte) pte_free(pte)
#define check_pgt_cache() do { } while (0) #define check_pgt_cache() do { } while (0)
......
...@@ -12,11 +12,6 @@ ...@@ -12,11 +12,6 @@
#include <asm/page.h> #include <asm/page.h>
#endif /* __ASSEMBLY__ */ #endif /* __ASSEMBLY__ */
/* Certain architectures need to do special things when pte's
* within a page table are directly modified. Thus, the following
* hook is made available.
*/
/* PMD_SHIFT determines what a second-level page table entry can map */ /* PMD_SHIFT determines what a second-level page table entry can map */
#define PMD_SHIFT (PAGE_SHIFT + PAGE_SHIFT - 3) #define PMD_SHIFT (PAGE_SHIFT + PAGE_SHIFT - 3)
#define PMD_SIZE (1UL << PMD_SHIFT) #define PMD_SIZE (1UL << PMD_SHIFT)
...@@ -107,9 +102,9 @@ ...@@ -107,9 +102,9 @@
/* preserving _PAGE_SECONDARY | _PAGE_GROUP_IX */ /* preserving _PAGE_SECONDARY | _PAGE_GROUP_IX */
#define _PAGE_CHG_MASK (PAGE_MASK | _PAGE_ACCESSED | _PAGE_DIRTY | _PAGE_HPTEFLAGS) #define _PAGE_CHG_MASK (PAGE_MASK | _PAGE_ACCESSED | _PAGE_DIRTY | _PAGE_HPTEFLAGS)
#define _PAGE_BASE _PAGE_PRESENT | _PAGE_ACCESSED | _PAGE_COHERENT #define _PAGE_BASE (_PAGE_PRESENT | _PAGE_ACCESSED | _PAGE_COHERENT)
#define _PAGE_WRENABLE _PAGE_RW | _PAGE_DIRTY #define _PAGE_WRENABLE (_PAGE_RW | _PAGE_DIRTY)
/* __pgprot defined in asm-ppc64/page.h */ /* __pgprot defined in asm-ppc64/page.h */
#define PAGE_NONE __pgprot(_PAGE_PRESENT | _PAGE_ACCESSED) #define PAGE_NONE __pgprot(_PAGE_PRESENT | _PAGE_ACCESSED)
...@@ -330,8 +325,6 @@ static inline void pte_clear(pte_t * ptep) ...@@ -330,8 +325,6 @@ static inline void pte_clear(pte_t * ptep)
pte_update(ptep, ~_PAGE_HPTEFLAGS, 0); pte_update(ptep, ~_PAGE_HPTEFLAGS, 0);
} }
extern unsigned long va_to_phys(unsigned long address);
extern pte_t *va_to_pte(unsigned long address);
extern unsigned long ioremap_bot, ioremap_base; extern unsigned long ioremap_bot, ioremap_base;
#define USER_PGD_PTRS (PAGE_OFFSET >> PGDIR_SHIFT) #define USER_PGD_PTRS (PAGE_OFFSET >> PGDIR_SHIFT)
...@@ -356,6 +349,7 @@ extern void paging_init(void); ...@@ -356,6 +349,7 @@ extern void paging_init(void);
* ahead of time, instead of waiting for the inevitable extra * ahead of time, instead of waiting for the inevitable extra
* hash-table miss exception. * hash-table miss exception.
*/ */
struct vm_area_struct;
extern void update_mmu_cache(struct vm_area_struct *, unsigned long, pte_t); extern void update_mmu_cache(struct vm_area_struct *, unsigned long, pte_t);
/* Encode and de-code a swap entry */ /* Encode and de-code a swap entry */
...@@ -380,12 +374,8 @@ extern void update_mmu_cache(struct vm_area_struct *, unsigned long, pte_t); ...@@ -380,12 +374,8 @@ extern void update_mmu_cache(struct vm_area_struct *, unsigned long, pte_t);
*/ */
#define pgtable_cache_init() do { } while (0) #define pgtable_cache_init() do { } while (0)
extern void updateBoltedHptePP(unsigned long newpp, unsigned long ea);
extern void hpte_init_pSeries(void); extern void hpte_init_pSeries(void);
extern void hpte_init_iSeries(void); extern void hpte_init_iSeries(void);
extern void make_pte(HPTE * htab, unsigned long va, unsigned long pa,
int mode, unsigned long hash_mask, int large);
#endif /* __ASSEMBLY__ */ #endif /* __ASSEMBLY__ */
#endif /* _PPC64_PGTABLE_H */ #endif /* _PPC64_PGTABLE_H */
...@@ -195,8 +195,5 @@ extern void print_properties(struct device_node *node); ...@@ -195,8 +195,5 @@ extern void print_properties(struct device_node *node);
extern int prom_n_addr_cells(struct device_node* np); extern int prom_n_addr_cells(struct device_node* np);
extern int prom_n_size_cells(struct device_node* np); extern int prom_n_size_cells(struct device_node* np);
extern void prom_get_irq_senses(unsigned char *senses, int off, int max); extern void prom_get_irq_senses(unsigned char *senses, int off, int max);
extern void prom_drawstring(const char *c);
extern void prom_drawhex(unsigned long v);
extern void prom_drawchar(char c);
#endif /* _PPC64_PROM_H */ #endif /* _PPC64_PROM_H */
/*
* linux/arch/ppc64/kernel/ptrace-common.h
*
* Copyright (c) 2002 Stephen Rothwell, IBM Coproration
* Extracted from ptrace.c and ptrace32.c
*
* This file is subject to the terms and conditions of the GNU General
* Public License. See the file README.legal in the main directory of
* this archive for more details.
*/
/*
* Set of msr bits that gdb can change on behalf of a process.
*/
#define MSR_DEBUGCHANGE (MSR_FE0 | MSR_SE | MSR_BE | MSR_FE1)
/*
* Get contents of register REGNO in task TASK.
*/
static inline unsigned long get_reg(struct task_struct *task, int regno)
{
if (regno < (sizeof(struct pt_regs) / sizeof(unsigned long)))
return ((unsigned long *)task->thread.regs)[regno];
return 0;
}
/*
* Write contents of register REGNO in task TASK.
*/
static inline int put_reg(struct task_struct *task, int regno,
unsigned long data)
{
if (regno < PT_SOFTE) {
if (regno == PT_MSR)
data = (data & MSR_DEBUGCHANGE)
| (task->thread.regs->msr & ~MSR_DEBUGCHANGE);
((unsigned long *)task->thread.regs)[regno] = data;
return 0;
}
return -EIO;
}
static inline void set_single_step(struct task_struct *task)
{
struct pt_regs *regs = task->thread.regs;
if (regs != NULL)
regs->msr |= MSR_SE;
}
static inline void clear_single_step(struct task_struct *task)
{
struct pt_regs *regs = task->thread.regs;
if (regs != NULL)
regs->msr &= ~MSR_SE;
}
...@@ -2,6 +2,7 @@ ...@@ -2,6 +2,7 @@
#define _PPC64_RTAS_H #define _PPC64_RTAS_H
#include <linux/spinlock.h> #include <linux/spinlock.h>
#include <asm/page.h>
/* /*
* Definitions for talking to the RTAS on CHRP machines. * Definitions for talking to the RTAS on CHRP machines.
...@@ -128,6 +129,29 @@ struct rtas_error_log { ...@@ -128,6 +129,29 @@ struct rtas_error_log {
unsigned char buffer[1]; /* allocated by klimit bump */ unsigned char buffer[1]; /* allocated by klimit bump */
}; };
struct flash_block {
char *data;
unsigned long length;
};
/* This struct is very similar but not identical to
* that needed by the rtas flash update.
* All we need to do for rtas is rewrite num_blocks
* into a version/length and translate the pointers
* to absolute.
*/
#define FLASH_BLOCKS_PER_NODE ((PAGE_SIZE - 16) / sizeof(struct flash_block))
struct flash_block_list {
unsigned long num_blocks;
struct flash_block_list *next;
struct flash_block blocks[FLASH_BLOCKS_PER_NODE];
};
struct flash_block_list_header { /* just the header of flash_block_list */
unsigned long num_blocks;
struct flash_block_list *next;
};
extern struct flash_block_list_header rtas_firmware_flash_list;
extern struct rtas_t rtas; extern struct rtas_t rtas;
extern void enter_rtas(struct rtas_args *); extern void enter_rtas(struct rtas_args *);
...@@ -140,4 +164,7 @@ extern void rtas_restart(char *cmd); ...@@ -140,4 +164,7 @@ extern void rtas_restart(char *cmd);
extern void rtas_power_off(void); extern void rtas_power_off(void);
extern void rtas_halt(void); extern void rtas_halt(void);
extern struct proc_dir_entry *rtas_proc_dir;
#endif /* _PPC64_RTAS_H */ #endif /* _PPC64_RTAS_H */
...@@ -8,22 +8,20 @@ ...@@ -8,22 +8,20 @@
* 2 of the License, or (at your option) any later version. * 2 of the License, or (at your option) any later version.
*/ */
#include <asm/atomic.h>
#include <asm/hardirq.h> #include <asm/hardirq.h>
#define local_bh_disable() do { local_bh_count(smp_processor_id())++; barrier(); } while (0) #define local_bh_disable() do { local_bh_count(smp_processor_id())++; barrier(); } while (0)
#define __local_bh_enable() do { barrier(); local_bh_count(smp_processor_id())--; } while (0) #define __local_bh_enable() do { barrier(); local_bh_count(smp_processor_id())--; } while (0)
#define local_bh_enable() \ #define local_bh_enable() \
do { \ do { \
barrier(); \
if (!--local_bh_count(smp_processor_id()) \ if (!--local_bh_count(smp_processor_id()) \
&& softirq_pending(smp_processor_id())) { \ && softirq_pending(smp_processor_id())) { \
do_softirq(); \ do_softirq(); \
} \ } \
} while (0) } while (0)
#define in_softirq() (local_bh_count(smp_processor_id()) != 0) #define in_softirq() (local_bh_count(smp_processor_id()) != 0)
#endif /* __ASM_SOFTIRQ_H */ #endif /* __ASM_SOFTIRQ_H */
...@@ -9,19 +9,11 @@ ...@@ -9,19 +9,11 @@
*/ */
#include <linux/config.h> #include <linux/config.h>
#include <linux/kdev_t.h>
#include <asm/page.h> #include <asm/page.h>
#include <asm/processor.h> #include <asm/processor.h>
#include <asm/hw_irq.h> #include <asm/hw_irq.h>
#include <asm/memory.h> #include <asm/memory.h>
/*
* System defines.
*/
#define KERNEL_START_PHYS 0x800000
#define KERNEL_START (PAGE_OFFSET+KERNEL_START_PHYS)
#define START_ADDR (PAGE_OFFSET+KERNEL_START_PHYS+0x00000)
/* /*
* Memory barrier. * Memory barrier.
* The sync instruction guarantees that all memory accesses initiated * The sync instruction guarantees that all memory accesses initiated
...@@ -85,24 +77,13 @@ extern void (*xmon_fault_handler)(struct pt_regs *regs); ...@@ -85,24 +77,13 @@ extern void (*xmon_fault_handler)(struct pt_regs *regs);
extern void print_backtrace(unsigned long *); extern void print_backtrace(unsigned long *);
extern void show_regs(struct pt_regs * regs); extern void show_regs(struct pt_regs * regs);
extern void flush_instruction_cache(void); extern void flush_instruction_cache(void);
extern void hard_reset_now(void);
extern void poweroff_now(void);
extern int _get_PVR(void); extern int _get_PVR(void);
extern long _get_L2CR(void);
extern void _set_L2CR(unsigned long);
extern void via_cuda_init(void);
extern void pmac_nvram_init(void);
extern void pmac_find_display(void);
extern void giveup_fpu(struct task_struct *); extern void giveup_fpu(struct task_struct *);
extern void enable_kernel_fp(void); extern void enable_kernel_fp(void);
extern void giveup_altivec(struct task_struct *);
extern void load_up_altivec(struct task_struct *);
extern void cvt_fd(float *from, double *to, unsigned long *fpscr); extern void cvt_fd(float *from, double *to, unsigned long *fpscr);
extern void cvt_df(double *from, float *to, unsigned long *fpscr); extern void cvt_df(double *from, float *to, unsigned long *fpscr);
extern int abs(int); extern int abs(int);
struct device_node;
struct task_struct; struct task_struct;
#define prepare_to_switch() do { } while(0) #define prepare_to_switch() do { } while(0)
#define switch_to(prev,next) _switch_to((prev),(next)) #define switch_to(prev,next) _switch_to((prev),(next))
......
...@@ -14,6 +14,7 @@ ...@@ -14,6 +14,7 @@
#define __PPC64_TIME_H #define __PPC64_TIME_H
#ifdef __KERNEL__ #ifdef __KERNEL__
#include <linux/config.h>
#include <linux/types.h> #include <linux/types.h>
#include <linux/mc146818rtc.h> #include <linux/mc146818rtc.h>
......
/*
* TLB shootdown specifics for PPC64
*
* Copyright (C) 2002 Anton Blanchard, IBM Corp.
* Copyright (C) 2002 Paul Mackerras, IBM Corp.
*
* 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 the Free Software Foundation; either version
* 2 of the License, or (at your option) any later version.
*/
#ifndef _PPC64_TLB_H
#define _PPC64_TLB_H
#include <asm/pgtable.h>
#include <asm/tlbflush.h>
#include <asm/page.h>
#include <asm/mmu.h>
struct free_pte_ctx;
static inline void tlb_flush(struct free_pte_ctx *tlb);
/* Get the generic bits... */
#include <asm-generic/tlb.h> #include <asm-generic/tlb.h>
/* Nothing needed here in fact... */
#define tlb_start_vma(tlb, vma) do { } while (0)
#define tlb_end_vma(tlb, vma) do { } while (0)
/* Should make this at least as large as the generic batch size, but it
* takes up too much space */
#define PPC64_TLB_BATCH_NR 192
struct ppc64_tlb_batch {
unsigned long index;
pte_t pte[PPC64_TLB_BATCH_NR];
unsigned long addr[PPC64_TLB_BATCH_NR];
unsigned long vaddr[PPC64_TLB_BATCH_NR];
};
extern struct ppc64_tlb_batch ppc64_tlb_batch[NR_CPUS];
static inline void tlb_remove_tlb_entry(mmu_gather_t *tlb, pte_t *ptep,
unsigned long address)
{
int cpu = smp_processor_id();
struct ppc64_tlb_batch *batch = &ppc64_tlb_batch[cpu];
unsigned long i = batch->index;
pte_t pte;
if (pte_val(*ptep) & _PAGE_HASHPTE) {
pte = __pte(pte_update(ptep, _PAGE_HPTEFLAGS, 0));
if (pte_val(pte) & _PAGE_HASHPTE) {
int local = 0;
if (tlb->mm->cpu_vm_mask == (1 << cpu))
local = 1;
batch->pte[i] = pte;
batch->addr[i] = address;
i++;
if (i == PPC64_TLB_BATCH_NR) {
flush_hash_range(tlb->mm->context, i, local);
i = 0;
}
}
}
batch->index = i;
}
static inline void tlb_flush(struct free_pte_ctx *tlb)
{
int cpu = smp_processor_id();
struct ppc64_tlb_batch *batch = &ppc64_tlb_batch[cpu];
int local = 0;
if (tlb->mm->cpu_vm_mask == (1 << smp_processor_id()))
local = 1;
flush_hash_range(tlb->mm->context, batch->index, local);
batch->index = 0;
}
#endif /* _PPC64_TLB_H */
...@@ -35,12 +35,4 @@ extern void flush_hash_page(unsigned long context, unsigned long ea, pte_t pte, ...@@ -35,12 +35,4 @@ extern void flush_hash_page(unsigned long context, unsigned long ea, pte_t pte,
int local); int local);
void flush_hash_range(unsigned long context, unsigned long number, int local); void flush_hash_range(unsigned long context, unsigned long number, int local);
/* TLB flush batching */
#define MAX_BATCH_FLUSH 128
struct tlb_batch_data {
pte_t pte;
unsigned long addr;
};
extern struct tlb_batch_data tlb_batch_array[NR_CPUS][MAX_BATCH_FLUSH];
#endif /* _PPC64_TLBFLUSH_H */ #endif /* _PPC64_TLBFLUSH_H */
...@@ -124,9 +124,6 @@ do { \ ...@@ -124,9 +124,6 @@ do { \
} \ } \
} while (0) } while (0)
struct __large_struct { unsigned long buf[100]; };
#define __m(x) (*(struct __large_struct *)(x))
/* /*
* We don't tell gcc that we are accessing memory, but this is OK * We don't tell gcc that we are accessing memory, but this is OK
* because we do not write to any memory gcc knows about, so there * because we do not write to any memory gcc knows about, so there
......
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