Commit 24bf662b authored by Anton Blanchard's avatar Anton Blanchard

Merge samba.org:/home/anton/ppc64/linux-2.5

into samba.org:/home/anton/ppc64/for-linus-ppc64
parents a321a55f 383bbaef
......@@ -65,6 +65,3 @@ archclean:
@$(MAKEBOOT) clean
archmrproper:
prepare:
$(MAKEBOOT) dep
......@@ -120,7 +120,3 @@ imagesize.c: vmlinux.gz
clean:
rm -f piggyback note addnote $(OBJS) zImage zImage.initrd vmlinux.gz no_initrd.o imagesize.c addSystemMap vmlinux.sm addRamDisk vmlinux.initrd vmlinux.sminitrd
dep:
$(CPP) $(CPPFLAGS) -M *.S *.c > .depend
......@@ -23,12 +23,18 @@ if [ "$CONFIG_SMP" = "y" ]; then
bool ' Distribute interrupts on all CPUs by default' CONFIG_IRQ_ALL_CPUS
if [ "$CONFIG_PPC_PSERIES" = "y" ]; then
bool ' Hardware multithreading' CONFIG_HMT
bool ' Discontiguous Memory Support' CONFIG_DISCONTIGMEM
if [ "$CONFIG_DISCONTIGMEM" = "y" ]; then
bool ' NUMA support' CONFIG_NUMA
fi
fi
fi
define_bool CONFIG_PREEMPT n
if [ "$CONFIG_PPC_ISERIES" = "y" ]; then
define_bool CONFIG_MSCHUNKS y
else
tristate ' Firmware flash interface' CONFIG_RTAS_FLASH
fi
endmenu
......
......@@ -37,7 +37,9 @@ CONFIG_PPC64=y
CONFIG_SMP=y
CONFIG_IRQ_ALL_CPUS=y
# CONFIG_HMT is not set
# CONFIG_DISCONTIGMEM is not set
# CONFIG_PREEMPT is not set
# CONFIG_RTAS_FLASH is not set
#
# General setup
......@@ -60,6 +62,7 @@ CONFIG_PCI_NAMES=y
#
# CONFIG_PARPORT is not set
CONFIG_PROC_DEVICETREE=y
# CONFIG_CMDLINE_BOOL is not set
#
# Memory Technology Devices (MTD)
......@@ -83,6 +86,7 @@ CONFIG_BLK_DEV_FD=y
# CONFIG_BLK_CPQ_CISS_DA is not set
# CONFIG_CISS_SCSI_TAPE 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_NBD=y
CONFIG_BLK_DEV_RAM=y
......@@ -364,7 +368,7 @@ CONFIG_IBMOL=y
# CONFIG_WAN is not set
#
# "Tulip" family network device support
# Tulip family network device support
#
# CONFIG_NET_TULIP is not set
......@@ -397,7 +401,6 @@ CONFIG_IBMOL=y
#
CONFIG_FB=y
CONFIG_DUMMY_CONSOLE=y
# CONFIG_FB_RIVA is not set
# CONFIG_FB_CLGEN is not set
# CONFIG_FB_PM2 is not set
# CONFIG_FB_CYBER2000 is not set
......@@ -409,6 +412,7 @@ CONFIG_FB_OF=y
# CONFIG_FB_IMSTT is not set
# CONFIG_FB_S3TRIO is not set
# CONFIG_FB_VGA16 is not set
# CONFIG_FB_RIVA is not set
CONFIG_FB_MATROX=y
CONFIG_FB_MATROX_MILLENIUM=y
CONFIG_FB_MATROX_MYSTIQUE=y
......@@ -422,6 +426,8 @@ CONFIG_FB_MATROX_G100=y
# CONFIG_FB_NEOMAGIC is not set
# CONFIG_FB_3DFX 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_FBCON_ADVANCED is not set
CONFIG_FBCON_CFB8=y
......
......@@ -13,7 +13,6 @@
#include <linux/threads.h>
#include <asm/processor.h>
#include <asm/ptrace.h>
#include <asm/init.h>
#include <asm/naca.h>
#include <asm/abs_addr.h>
#include <asm/bitops.h>
......
......@@ -32,6 +32,8 @@ obj-$(CONFIG_PCI) += pSeries_pci.o pSeries_lpar.o pSeries_hvCall.o eeh.o
obj-y += rtasd.o nvram.o
endif
obj-$(CONFIG_RTAS_FLASH) += rtas_flash.o
obj-$(CONFIG_SMP) += smp.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
#
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 \
$(TOPDIR)/include/asm/mmu.h \
......
......@@ -57,7 +57,6 @@
#include <asm/machdep.h>
#include <asm/irq.h>
#include <asm/keyboard.h>
#include <asm/init.h>
#include <asm/naca.h>
#include <asm/time.h>
......@@ -98,16 +97,10 @@ int fwnmi_active; /* TRUE if an FWNMI handler is present */
kdev_t boot_dev;
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;
#ifdef CONFIG_BLK_DEV_RAM
extern int rd_doload; /* 1 = load ramdisk, 0 = don't load */
extern int rd_prompt; /* 1 = prompt for ramdisk, 0 = don't prompt */
extern int rd_image_start; /* starting block # of image */
#endif
extern unsigned long ppc_proc_freq;
extern unsigned long ppc_tb_freq;
void
chrp_get_cpuinfo(struct seq_file *m)
......@@ -115,6 +108,8 @@ chrp_get_cpuinfo(struct seq_file *m)
struct device_node *root;
const char *model = "";
seq_printf(m, "timebase\t: %lu\n", ppc_tb_freq);
root = find_path_device("/");
if (root)
model = get_property(root, "model", NULL);
......@@ -304,7 +299,7 @@ chrp_init(unsigned long r3, unsigned long r4, unsigned long r5,
ppc_md.progress("Linux ppc64\n", 0x0);
}
void __chrp
void
chrp_progress(char *s, unsigned short hex)
{
struct device_node *root;
......@@ -362,9 +357,6 @@ chrp_progress(char *s, unsigned short hex)
extern void setup_default_decr(void);
extern unsigned long ppc_proc_freq;
extern unsigned long ppc_tb_freq;
void __init pSeries_calibrate_decr(void)
{
struct device_node *cpu;
......
......@@ -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));
}
int eeh_get_state(unsigned long ea) {
int eeh_get_state(unsigned long ea)
{
return 0;
}
/* 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.
* Otherwise panic.
......@@ -113,7 +112,8 @@ unsigned long eeh_check_failure(void *token, unsigned long val)
return val; /* good case */
}
void eeh_init(void) {
void eeh_init(void)
{
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_on = strstr(cmd_line, "eeh-force-on");
......@@ -121,7 +121,7 @@ void eeh_init(void) {
ibm_set_eeh_option = rtas_token("ibm,set-eeh-option");
ibm_set_slot_reset = rtas_token("ibm,set-slot-reset");
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;
if (eeh_force_off > eeh_force_on) {
......@@ -334,6 +334,7 @@ static int __init eehoff_parm(char *str)
{
return eeh_parm(str, 0);
}
static int __init eehon_parm(char *str)
{
return eeh_parm(str, 1);
......
......@@ -353,7 +353,7 @@ recheck:
li r4,0
ori r4,r4,MSR_EE|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
#error fix iSeries soft disable
......@@ -411,7 +411,7 @@ restore:
do_work:
/* Enable interrupts */
ori r10,r10,MSR_EE|MSR_RI
mtmsrd r10
mtmsrd r10,1
andi. r0,r3,_TIF_NEED_RESCHED
beq 1f
......
......@@ -575,7 +575,8 @@ stab_bolted_user_return:
bl .do_stab_SI
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:
ld r4,_DAR(r1)
ld r5,_DSISR(r1)
......@@ -627,9 +628,8 @@ InstructionAccess_common:
bl .do_stab_SI
b 1f
2: andis. r0,r23,0x4000 /* no pte found? */
beq 1f /* if so, try to put a PTE */
mr r3,r22 /* into the hash table */
2: mr r3,r22
li r5,0x400
bl .do_hash_page_ISI /* Try to handle as hpte fault */
1:
mr r4,r22
......@@ -804,6 +804,7 @@ _GLOBAL(do_hash_page_DSI)
/*
* r3 contains the faulting address
* r4 contains the required access permissions
* r5 contains the trap number
*
* at return r3 = 0 for success
*/
......@@ -852,11 +853,13 @@ _GLOBAL(do_stab_bolted)
ld r22,8(r21) /* get SRR1 */
andi. r22,r22,MSR_PR /* check if from user */
bne+ stab_bolted_user_return /* from user, send the error on up */
#if 0
li r3,0
#ifdef CONFIG_XMON
bl .xmon
#endif
1: b 1b
#endif
2:
/* (((ea >> 28) & 0x1fff) << 15) | (ea >> 60) */
mfspr r21,DAR
......@@ -1119,7 +1122,7 @@ _GLOBAL(save_remaining_regs)
rldimi r22,r20,15,48 /* Insert desired EE value */
#endif
mtmsrd r22
mtmsrd r22,1
blr
......
......@@ -35,7 +35,6 @@
#include <asm/mmu_context.h>
#include <asm/page.h>
#include <asm/types.h>
#include <asm/init.h>
#include <asm/system.h>
#include <asm/uaccess.h>
#include <asm/naca.h>
......@@ -45,9 +44,8 @@
#include <asm/lmb.h>
#include <asm/abs_addr.h>
#include <asm/tlbflush.h>
#ifdef CONFIG_PPC_EEH
#include <asm/eeh.h>
#endif
#include <asm/tlb.h>
/*
* Note: pte --> Linux 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
*/
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 newpp, prpn;
......@@ -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
* do_page_fault
*/
if (!ptep || !pte_present(*ptep))
if (unlikely(!ptep || !pte_present(*ptep)))
return 1;
/*
......@@ -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.
*/
access |= _PAGE_PRESENT;
if (access & ~(pte_val(*ptep)))
if (unlikely(access & ~(pte_val(*ptep))))
return 1;
/*
......@@ -245,8 +243,27 @@ int __hash_page(unsigned long ea, unsigned long access, unsigned long vsid,
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) */
if (pte_val(old_pte) & _PAGE_HASHPTE) {
if (unlikely(pte_val(old_pte) & _PAGE_HASHPTE)) {
/* There MIGHT be an HPTE for this pte */
unsigned long hash, slot, secondary;
......@@ -266,7 +283,7 @@ int __hash_page(unsigned long ea, unsigned long access, unsigned long vsid,
*ptep = new_pte;
}
if (!(pte_val(old_pte) & _PAGE_HASHPTE)) {
if (likely(!(pte_val(old_pte) & _PAGE_HASHPTE))) {
/* XXX fix large pte flag */
unsigned long hash = hpt_hash(vpn, 0);
unsigned long hpte_group;
......@@ -318,7 +335,7 @@ int __hash_page(unsigned long ea, unsigned long access, unsigned long vsid,
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;
unsigned long vsid;
......@@ -346,13 +363,11 @@ int hash_page(unsigned long ea, unsigned long access)
mm = &init_mm;
vsid = get_kernel_vsid(ea);
break;
#ifdef CONFIG_PPC_EEH
case IO_UNMAPPED_REGION_ID:
udbg_printf("EEH Error ea = 0x%lx\n", ea);
PPCDBG_ENTER_DEBUGGER();
panic("EEH Error ea = 0x%lx\n", ea);
break;
#endif
case KERNEL_REGION_ID:
/*
* 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)
*/
spin_lock(&mm->page_table_lock);
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);
return ret;
......@@ -419,12 +434,11 @@ void flush_hash_range(unsigned long context, unsigned long number, int local)
ppc_md.flush_hash_range(context, number, local);
} else {
int i;
struct tlb_batch_data *ptes =
&tlb_batch_array[smp_processor_id()][0];
struct ppc64_tlb_batch *batch =
&ppc64_tlb_batch[smp_processor_id()];
for (i = 0; i < number; i++) {
flush_hash_page(context, ptes->addr, ptes->pte, local);
ptes++;
}
for (i = 0; i < number; i++)
flush_hash_page(context, batch->addr[i], batch->pte[i],
local);
}
}
......@@ -21,7 +21,6 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include <linux/config.h>
#include <linux/kernel.h>
#include <linux/list.h>
#include <linux/string.h>
......
......@@ -32,7 +32,6 @@
#include <linux/irq.h>
#include <asm/io.h>
#include <asm/init.h>
#include <asm/iSeries/HvCallPci.h>
#include <asm/iSeries/HvTypes.h>
#include <asm/iSeries/mf.h>
......
......@@ -81,7 +81,7 @@ unsigned long lpEvent_count = 0;
* this needs to be removed.
* -- Cort
*/
#define IRQ_KMALLOC_ENTRIES 8
#define IRQ_KMALLOC_ENTRIES 16
static int cache_bitmask = 0;
static struct irqaction malloc_cache[IRQ_KMALLOC_ENTRIES];
extern int mem_init_done;
......@@ -346,8 +346,10 @@ int show_interrupts(struct seq_file *p, void *v)
struct irqaction * action;
seq_printf(p, " ");
for (j=0; j<smp_num_cpus; j++)
seq_printf(p, "CPU%d ",j);
for (j=0; j<NR_CPUS; j++) {
if (cpu_online(j))
seq_printf(p, "CPU%d ",j);
}
seq_putc(p, '\n');
for (i = 0 ; i < NR_IRQS ; i++) {
......@@ -356,9 +358,10 @@ int show_interrupts(struct seq_file *p, void *v)
continue;
seq_printf(p, "%3d: ", i);
#ifdef CONFIG_SMP
for (j = 0; j < smp_num_cpus; j++)
seq_printf(p, "%10u ",
kstat.irqs[cpu_logical_map(j)][i]);
for (j = 0; j < NR_CPUS; j++) {
if (cpu_online(j))
seq_printf(p, "%10u ", kstat.irqs[j][i]);
}
#else
seq_printf(p, "%10u ", kstat_irqs(i));
#endif /* CONFIG_SMP */
......@@ -425,14 +428,14 @@ static unsigned long move(unsigned long curr_cpu, unsigned long allowed_mask,
inside:
if (direction == 1) {
cpu++;
if (cpu >= smp_num_cpus)
if (cpu >= NR_CPUS)
cpu = 0;
} else {
cpu--;
if (cpu == -1)
cpu = smp_num_cpus-1;
cpu = NR_CPUS-1;
}
} while (!IRQ_ALLOWED(cpu,allowed_mask) ||
} while (!cpu_online(cpu) || !IRQ_ALLOWED(cpu,allowed_mask) ||
(search_idle && !IDLE_ENOUGH(cpu,now)));
return cpu;
......@@ -474,7 +477,9 @@ void ppc_irq_dispatch_handler(struct pt_regs *regs, int irq)
int cpu = smp_processor_id();
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]++;
spin_lock(&desc->lock);
......@@ -651,12 +656,16 @@ static void show(char * str)
printk("\n%s, CPU %d:\n", str, cpu);
printk("irq: %d [ ", irqs_running());
for (i = 0; i < smp_num_cpus; i++)
printk("%u ", __brlock_array[i][BR_GLOBALIRQ_LOCK]);
for (i = 0; i < NR_CPUS; i++) {
if (cpu_online(i))
printk("%u ", __brlock_array[i][BR_GLOBALIRQ_LOCK]);
}
printk("]\nbh: %d [ ",
(spin_is_locked(&global_bh_lock) ? 1 : 0));
for (i = 0; i < smp_num_cpus; i++)
printk("%u ", local_bh_count(i));
for (i = 0; i < NR_CPUS; i++) {
if (cpu_online(i))
printk("%u ", local_bh_count(i));
}
printk("]\n");
}
......
......@@ -14,7 +14,6 @@
*/
#include <stddef.h>
#include <linux/config.h>
#include <linux/signal.h>
#include <linux/sched.h>
#include <linux/kernel.h>
......
......@@ -33,7 +33,6 @@ void* OpenPIC_Addr;
static volatile struct OpenPIC *OpenPIC = NULL;
u_int OpenPIC_NumInitSenses __initdata = 0;
u_char *OpenPIC_InitSenses __initdata = NULL;
extern int use_of_interrupt_tree;
void find_ISUs(void);
......@@ -86,10 +85,10 @@ unsigned int openpic_vec_spurious;
*/
#ifdef CONFIG_SMP
#define THIS_CPU Processor[cpu]
#define DECL_THIS_CPU int cpu = hard_smp_processor_id()
#define DECL_THIS_CPU int cpu = smp_processor_id()
#define CHECK_THIS_CPU check_arg_cpu(cpu)
#else
#define THIS_CPU Processor[hard_smp_processor_id()]
#define THIS_CPU Processor[smp_processor_id()]
#define DECL_THIS_CPU
#define CHECK_THIS_CPU
#endif /* CONFIG_SMP */
......@@ -357,7 +356,7 @@ void __init openpic_init(int main_pic, int offset, unsigned char* chrp_ack,
/* SIOint (8259 cascade) is special */
if (offset) {
openpic_initirq(0, 8, offset, 1, 1);
openpic_mapirq(0, 1<<get_hard_smp_processor_id(0));
openpic_mapirq(0, 1 << boot_cpuid);
}
/* Init all external sources */
......@@ -375,7 +374,7 @@ void __init openpic_init(int main_pic, int offset, unsigned char* chrp_ack,
/* Enabled, Priority 8 or 9 */
openpic_initirq(i, pri, i+offset, !sense, sense);
/* Processor 0 */
openpic_mapirq(i, 1<<get_hard_smp_processor_id(0));
openpic_mapirq(i, 1 << boot_cpuid);
}
/* Init descriptors */
......@@ -504,23 +503,10 @@ static void openpic_set_spurious(u_int vec)
vec);
}
/*
* Convert a cpu mask from logical to physical cpu numbers.
*/
static inline u32 physmask(u32 cpumask)
{
int i;
u32 mask = 0;
for (i = 0; i < smp_num_cpus; ++i, cpumask >>= 1)
mask |= (cpumask & 1) << get_hard_smp_processor_id(i);
return mask;
}
void openpic_init_processor(u_int cpumask)
{
openpic_write(&OpenPIC->Global.Processor_Initialization,
physmask(cpumask));
cpumask & cpu_online_map);
}
#ifdef CONFIG_SMP
......@@ -554,7 +540,7 @@ void openpic_cause_IPI(u_int ipi, u_int cpumask)
CHECK_THIS_CPU;
check_arg_ipi(ipi);
openpic_write(&OpenPIC->THIS_CPU.IPI_Dispatch(ipi),
physmask(cpumask));
cpumask & cpu_online_map);
}
void openpic_request_IPIs(void)
......@@ -594,7 +580,7 @@ void __init do_openpic_setup_cpu(void)
{
#ifdef CONFIG_IRQ_ALL_CPUS
int i;
u32 msk = 1 << hard_smp_processor_id();
u32 msk = 1 << smp_processor_id();
#endif
spin_lock(&openpic_setup_lock);
......@@ -639,7 +625,7 @@ static void __init openpic_maptimer(u_int timer, u_int cpumask)
{
check_arg_timer(timer);
openpic_write(&OpenPIC->Global.Timer[timer].Destination,
physmask(cpumask));
cpumask & cpu_online_map);
}
......@@ -762,7 +748,7 @@ static void openpic_end_irq(unsigned int irq_nr)
static void openpic_set_affinity(unsigned int irq_nr, unsigned long cpumask)
{
openpic_mapirq(irq_nr - open_pic_irq_offset, physmask(cpumask));
openpic_mapirq(irq_nr - open_pic_irq_offset, cpumask & cpu_online_map);
}
#ifdef CONFIG_SMP
......
......@@ -20,6 +20,7 @@
#include <asm/mmu_context.h>
#include <asm/pgtable.h>
#include <asm/tlbflush.h>
#include <asm/tlb.h>
/*
* Create a pte. Used during initialization only.
......@@ -214,7 +215,7 @@ static inline void set_pp_bit(unsigned long pp, HPTE *addr)
__asm__ __volatile__(
"1: ldarx %0,0,%3\n\
rldimi %0,%2,0,62\n\
rldimi %0,%2,0,61\n\
stdcx. %0,0,%3\n\
bne 1b"
: "=&r" (old), "=m" (*p)
......@@ -265,8 +266,6 @@ static long pSeries_hpte_updatepp(unsigned long slot, unsigned long newpp,
unsigned long vpn, avpn;
unsigned long flags;
udbg_printf("updatepp\n");
if (large)
vpn = va >> LARGE_PAGE_SHIFT;
else
......@@ -372,31 +371,32 @@ static void pSeries_flush_hash_range(unsigned long context,
{
unsigned long vsid, vpn, va, hash, secondary, slot, flags, avpn;
int i, j;
unsigned long va_array[MAX_BATCH_FLUSH];
HPTE *hptep;
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 */
unsigned long large = 0;
j = 0;
for (i = 0; i < number; i++) {
if ((ptes->addr >= USER_START) && (ptes->addr <= USER_END))
vsid = get_vsid(context, ptes->addr);
if ((batch->addr[i] >= USER_START) &&
(batch->addr[i] <= USER_END))
vsid = get_vsid(context, batch->addr[i]);
else
vsid = get_kernel_vsid(ptes->addr);
vsid = get_kernel_vsid(batch->addr[i]);
va = (vsid << 28) | (ptes->addr & 0x0fffffff);
va_array[j] = va;
va = (vsid << 28) | (batch->addr[i] & 0x0fffffff);
batch->vaddr[j] = va;
if (large)
vpn = va >> LARGE_PAGE_SHIFT;
else
vpn = va >> PAGE_SHIFT;
hash = hpt_hash(vpn, large);
secondary = (pte_val(ptes->pte) & _PAGE_SECONDARY) >> 15;
secondary = (pte_val(batch->pte[i]) & _PAGE_SECONDARY) >> 15;
if (secondary)
hash = ~hash;
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;
avpn = vpn >> 11;
......@@ -405,8 +405,6 @@ static void pSeries_flush_hash_range(unsigned long context,
dw0 = hptep->dw0.dw0;
ptes++;
if ((dw0.avpn != avpn) || !dw0.v) {
pSeries_unlock_hpte(hptep);
udbg_printf("invalidate missed\n");
......@@ -426,7 +424,7 @@ static void pSeries_flush_hash_range(unsigned long context,
asm volatile("\n\
clrldi %0,%0,16\n\
tlbiel %0"
: : "r" (va_array[i]) : "memory" );
: : "r" (batch->vaddr[i]) : "memory" );
}
asm volatile("ptesync":::"memory");
......@@ -440,7 +438,7 @@ static void pSeries_flush_hash_range(unsigned long context,
asm volatile("\n\
clrldi %0,%0,16\n\
tlbie %0"
: : "r" (va_array[i]) : "memory" );
: : "r" (batch->vaddr[i]) : "memory" );
}
asm volatile("eieio; tlbsync; ptesync":::"memory");
......
......@@ -33,6 +33,7 @@
#include <linux/pci.h>
#include <asm/naca.h>
#include <asm/tlbflush.h>
#include <asm/tlb.h>
/* Status return values */
#define H_Success 0
......@@ -308,7 +309,7 @@ static void pSeriesLP_qirr_info(int n_cpu , u8 value)
{
unsigned long lpar_rc;
lpar_rc = plpar_ipi(get_hard_smp_processor_id(n_cpu),value);
lpar_rc = plpar_ipi(n_cpu, value);
if (lpar_rc != H_Success) {
panic(" bad return code qirr -ipi - rc = %lx \n", lpar_rc);
}
......@@ -646,11 +647,9 @@ static long pSeries_lpar_hpte_updatepp(unsigned long slot, unsigned long newpp,
{
unsigned long lpar_rc;
unsigned long flags;
flags = (newpp & 3) | H_AVPN;
flags = (newpp & 7) | H_AVPN;
unsigned long vpn = va >> PAGE_SHIFT;
udbg_printf("updatepp\n");
lpar_rc = plpar_pte_protect(flags, slot, (vpn >> 4) & ~0x7fUL);
if (lpar_rc == H_Not_Found) {
......@@ -775,15 +774,14 @@ void pSeries_lpar_flush_hash_range(unsigned long context, unsigned long number,
int local)
{
int i;
struct tlb_batch_data *ptes =
&tlb_batch_array[smp_processor_id()][0];
unsigned long flags;
struct ppc64_tlb_batch *batch = &ppc64_tlb_batch[smp_processor_id()];
spin_lock_irqsave(&pSeries_lpar_tlbie_lock, flags);
for (i = 0; i < number; i++) {
flush_hash_page(context, ptes->addr, ptes->pte, local);
ptes++;
}
for (i = 0; i < number; i++)
flush_hash_page(context, batch->addr[i], batch->pte[i], local);
spin_unlock_irqrestore(&pSeries_lpar_tlbie_lock, flags);
}
......
......@@ -22,7 +22,6 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include <linux/config.h>
#include <linux/kernel.h>
#include <linux/threads.h>
#include <linux/pci.h>
......@@ -36,7 +35,6 @@
#include <asm/irq.h>
#include <asm/prom.h>
#include <asm/machdep.h>
#include <asm/init.h>
#include <asm/pci-bridge.h>
#include <asm/ppcdebug.h>
#include <asm/naca.h>
......@@ -71,7 +69,7 @@ static int s7a_workaround;
*
*****************************************************************************/
#define RTAS_PCI_READ_OP(size, type, nbytes) \
int __chrp \
int \
rtas_read_config_##size(struct device_node *dn, int offset, type val) { \
unsigned long returnval = ~0L; \
unsigned long buid; \
......@@ -96,7 +94,7 @@ rtas_read_config_##size(struct device_node *dn, int offset, type val) { \
*val = returnval; \
return ret; \
} \
int __chrp \
int \
rtas_pci_read_config_##size(struct pci_dev *dev, int offset, type val) { \
struct device_node *dn = pci_device_to_OF_node(dev); \
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) { \
}
#define RTAS_PCI_WRITE_OP(size, type, nbytes) \
int __chrp \
int \
rtas_write_config_##size(struct device_node *dn, int offset, type val) { \
unsigned long buid; \
unsigned int addr; \
......@@ -126,7 +124,7 @@ rtas_write_config_##size(struct device_node *dn, int offset, type val) { \
} \
return ret; \
} \
int __chrp \
int \
rtas_pci_write_config_##size(struct pci_dev *dev, int offset, type val) { \
struct device_node* dn = pci_device_to_OF_node(dev); \
int ret = rtas_write_config_##size(dn, offset, val); \
......
......@@ -33,7 +33,6 @@
#include <asm/irq.h>
#include <asm/prom.h>
#include <asm/machdep.h>
#include <asm/init.h>
#include <asm/pci-bridge.h>
#include <asm/ppcdebug.h>
#include <asm/naca.h>
......
......@@ -59,7 +59,9 @@ ppc64_pmc_stab(int file)
stab_faults = stab_capacity_castouts = stab_invalidations = n = 0;
if (file == -1) {
for (i = 0; i < smp_num_cpus; i++) {
for (i = 0; i < NR_CPUS; i++) {
if (!cpu_online(i))
continue;
stab_faults += pmc_sw_cpu[i].stab_faults;
stab_capacity_castouts += pmc_sw_cpu[i].stab_capacity_castouts;
stab_invalidations += pmc_sw_cpu[i].stab_invalidations;
......
......@@ -11,8 +11,6 @@
* 2 of the License, or (at your option) any later version.
*/
#include <linux/config.h>
#include <asm/ppc_asm.tmpl>
#include "ppc_defs.h"
......
......@@ -87,7 +87,6 @@ EXPORT_SYMBOL(disable_irq_nosync);
#ifdef CONFIG_SMP
EXPORT_SYMBOL(kernel_flag);
EXPORT_SYMBOL(synchronize_irq);
EXPORT_SYMBOL(smp_num_cpus);
#endif /* CONFIG_SMP */
EXPORT_SYMBOL(register_ioctl32_conversion);
......
......@@ -24,6 +24,10 @@
* End Change Activity
*/
#include <linux/config.h>
#include <linux/proc_fs.h>
#include <linux/spinlock.h>
#include <asm/proc_fs.h>
#include <asm/paca.h>
#include <asm/iSeries/ItLpPaca.h>
......@@ -33,12 +37,10 @@
#include <asm/processor.h>
#include <asm/time.h>
#include <asm/iSeries/LparData.h>
#include <linux/proc_fs.h>
#include <linux/spinlock.h>
#include <asm/pmc.h>
#include <asm/uaccess.h>
#include <asm/naca.h>
#include <asm/rtas.h>
static int proc_pmc_control_mode = 0;
......@@ -100,21 +102,26 @@ void proc_ppc64_init(void)
if (!proc_ppc64_root) return;
spin_unlock(&proc_ppc64_lock);
#ifdef CONFIG_PPC_EEH
eeh_init_proc(proc_ppc64_root);
#endif
/* Placeholder for rtas interfaces. */
rtas_proc_dir = proc_mkdir("rtas", proc_ppc64_root);
proc_ppc64_pmc_root = proc_mkdir("pmc", proc_ppc64_root);
proc_ppc64_pmc_system_root = proc_mkdir("system", proc_ppc64_pmc_root);
for (i = 0; i < naca->processorCount; i++) {
sprintf(buf, "cpu%ld", i);
proc_ppc64_pmc_cpu_root[i] = proc_mkdir(buf, proc_ppc64_pmc_root);
for (i = 0; i < NR_CPUS; i++) {
if (cpu_online(i)) {
sprintf(buf, "cpu%ld", i);
proc_ppc64_pmc_cpu_root[i] =
proc_mkdir(buf, proc_ppc64_pmc_root);
}
}
/* Create directories for the software counters. */
for (i = 0; i < naca->processorCount; i++) {
for (i = 0; i < NR_CPUS; i++) {
if (!cpu_online(i))
continue;
ent = create_proc_entry("stab", S_IRUGO | S_IWUSR,
proc_ppc64_pmc_cpu_root[i]);
if (ent) {
......@@ -153,7 +160,9 @@ void proc_ppc64_init(void)
}
/* Create directories for the hardware counters. */
for (i = 0; i < naca->processorCount; i++) {
for (i = 0; i < NR_CPUS; i++) {
if (!cpu_online(i))
continue;
ent = create_proc_entry("hardware", S_IRUGO | S_IWUSR,
proc_ppc64_pmc_cpu_root[i]);
if (ent) {
......@@ -189,7 +198,9 @@ int proc_ppc64_pmc_find_file(void *data)
(unsigned long) proc_ppc64_pmc_system_root) {
return(-1);
} else {
for (i = 0; i < naca->processorCount; i++) {
for (i = 0; i < NR_CPUS; i++) {
if (!cpu_online(i))
continue;
if ((unsigned long)data ==
(unsigned long)proc_ppc64_pmc_cpu_root[i]) {
return(i);
......@@ -324,6 +335,7 @@ void pmc_proc_init(struct proc_dir_entry *iSeries_proc)
if (!ent) return;
ent->nlink = 1;
ent->data = (void *)0;
ent->size = 0;
ent->read_proc = proc_get_titanTod;
ent->write_proc = NULL;
......@@ -380,9 +392,10 @@ int proc_get_lpevents
(unsigned long)xItLpQueue.xLpIntCountByType[i] );
}
len += sprintf( page+len, "\n events processed by processor:\n" );
for (i=0; i<naca->processorCount; ++i) {
len += sprintf( page+len, " CPU%02d %10u\n",
i, paca[i].lpEvent_count );
for (i = 0; i < NR_CPUS; ++i) {
if (cpu_online(i))
len += sprintf( page+len, " CPU%02d %10u\n",
i, paca[i].lpEvent_count );
}
return pmc_calc_metrics( page, start, off, count, eof, len );
......
......@@ -44,8 +44,6 @@
#include <asm/machdep.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 mm_struct ioremap_mm = { pgd : ioremap_dir
......@@ -306,7 +304,9 @@ void initialize_paca_hardware_interrupt_stack(void)
unsigned long stack;
unsigned long end_of_stack =0;
for (i=1; i < naca->processorCount; i++) {
for (i=1; i < NR_CPUS; i++) {
if (!cpu_possible(i))
continue;
/* Carve out storage for the hardware interrupt stack */
stack = __get_free_pages(GFP_KERNEL, get_order(8*PAGE_SIZE));
......@@ -329,7 +329,9 @@ void initialize_paca_hardware_interrupt_stack(void)
if (__is_processor(PV_POWER4))
return;
for (i=0; i < naca->processorCount; i++) {
for (i=0; i < NR_CPUS; i++) {
if (!cpu_possible(i))
continue;
/* set page at the top of stack to be protected - prevent overflow */
end_of_stack = paca[i].xHrdIntStack - (8*PAGE_SIZE - STACK_FRAME_OVERHEAD);
ppc_md.hpte_updateboltedpp(PP_RXRX,end_of_stack);
......
......@@ -48,7 +48,6 @@
#define call_yaboot(FUNC,...) do { ; } while (0)
#endif
#include <asm/init.h>
#include <linux/types.h>
#include <linux/pci.h>
#include <asm/prom.h>
......@@ -446,9 +445,12 @@ prom_initialize_naca(unsigned long mem)
}
/* We gotta have at least 1 cpu... */
if ( (_naca->processorCount = num_cpus) < 1 )
if (num_cpus < 1)
PROM_BUG();
if (num_cpus > 1)
RELOC(ppc64_is_smp) = 1;
_naca->physicalMemorySize = lmb_phys_mem_size();
if (_naca->platform == PLATFORM_PSERIES) {
......@@ -478,10 +480,6 @@ prom_initialize_naca(unsigned long mem)
_naca->slb_size = 64;
#ifdef DEBUG_PROM
prom_print(RELOC("naca->processorCount = 0x"));
prom_print_hex(_naca->processorCount);
prom_print_nl();
prom_print(RELOC("naca->physicalMemorySize = 0x"));
prom_print_hex(_naca->physicalMemorySize);
prom_print_nl();
......@@ -1045,20 +1043,15 @@ prom_hold_cpus(unsigned long mem)
phandle node;
unsigned long offset = reloc_offset();
char type[64], *path;
int cpuid = 0;
extern void __secondary_hold(void);
extern unsigned long __secondary_hold_spinloop;
extern unsigned long __secondary_hold_acknowledge;
unsigned long *spinloop = __v2a(&__secondary_hold_spinloop);
unsigned long *acknowledge = __v2a(&__secondary_hold_acknowledge);
unsigned long secondary_hold = (unsigned long)__v2a(*PTRRELOC((unsigned long *)__secondary_hold));
struct naca_struct *_naca = RELOC(naca);
struct paca_struct *_xPaca = PTRRELOC(&paca[0]);
struct prom_t *_prom = PTRRELOC(&prom);
/* Initially, we must have one active CPU. */
_naca->processorCount = 1;
#ifdef DEBUG_PROM
prom_print(RELOC("prom_hold_cpus: start...\n"));
prom_print(RELOC(" 1) spinloop = 0x"));
......@@ -1118,19 +1111,12 @@ prom_hold_cpus(unsigned long mem)
node, path, 255) < 0)
continue;
cpuid++;
#ifdef DEBUG_PROM
prom_print_nl();
prom_print(RELOC("cpuid = 0x"));
prom_print_hex(cpuid);
prom_print_nl();
prom_print(RELOC("cpu hw idx = 0x"));
prom_print_hex(reg);
prom_print_nl();
#endif
_xPaca[cpuid].xHwProcNum = reg;
prom_print(RELOC("starting cpu "));
prom_print(path);
......@@ -1156,11 +1142,9 @@ prom_hold_cpus(unsigned long mem)
prom_print(RELOC(" 3) secondary_hold = 0x"));
prom_print_hex(secondary_hold);
prom_print_nl();
prom_print(RELOC(" 3) cpuid = 0x"));
prom_print_hex(cpuid);
prom_print_nl();
#endif
call_prom(RELOC("start-cpu"), 3, 0, node, secondary_hold, cpuid);
call_prom(RELOC("start-cpu"), 3, 0, node, secondary_hold, reg);
prom_print(RELOC("..."));
for ( i = 0 ; (i < 100000000) &&
(*acknowledge == ((unsigned long)-1)); i++ ) ;
......@@ -1172,10 +1156,10 @@ prom_hold_cpus(unsigned long mem)
prom_print_nl();
}
#endif
if (*acknowledge == cpuid) {
if (*acknowledge == reg) {
prom_print(RELOC("ok\n"));
/* Set the number of active processors. */
_naca->processorCount++;
_xPaca[reg].active = 1;
} else {
prom_print(RELOC("failed: "));
prom_print_hex(*acknowledge);
......@@ -1189,10 +1173,11 @@ prom_hold_cpus(unsigned long mem)
__is_processor(PV_SSTAR)) {
prom_print(RELOC(" starting secondary threads\n"));
for (i=0; i < _naca->processorCount ;i++) {
unsigned long threadid = _naca->processorCount*2-1-i;
if (i == 0) {
for (i = 0; i < NR_CPUS; i += 2) {
if (!_xPaca[i].active)
continue;
if (i == boot_cpuid) {
unsigned long pir = _get_PIR();
if (__is_processor(PV_PULSAR)) {
RELOC(hmt_thread_data)[i].pir =
......@@ -1202,21 +1187,9 @@ prom_hold_cpus(unsigned long mem)
pir & 0x3ff;
}
}
RELOC(hmt_thread_data)[i].threadid = threadid;
#ifdef DEBUG_PROM
prom_print(RELOC(" cpuid 0x"));
prom_print_hex(i);
prom_print(RELOC(" maps to threadid 0x"));
prom_print_hex(threadid);
prom_print_nl();
prom_print(RELOC(" pir 0x"));
prom_print_hex(RELOC(hmt_thread_data)[i].pir);
prom_print_nl();
#endif
_xPaca[threadid].xHwProcNum = _xPaca[i].xHwProcNum+1;
_xPaca[i+1].active = 1;
RELOC(hmt_thread_data)[i].threadid = i+1;
}
_naca->processorCount *= 2;
} else {
prom_print(RELOC("Processor is not HMT capable\n"));
}
......@@ -1373,7 +1346,9 @@ prom_init(unsigned long r3, unsigned long r4, unsigned long pp,
cpu_pkg, RELOC("reg"),
&getprop_rval, sizeof(getprop_rval));
_prom->cpu = (int)(unsigned long)getprop_rval;
_xPaca[0].xHwProcNum = _prom->cpu;
_xPaca[_prom->cpu].active = 1;
RELOC(cpu_online_map) = 1 << _prom->cpu;
RELOC(boot_cpuid) = _prom->cpu;
#ifdef DEBUG_PROM
prom_print(RELOC("Booting CPU hw index = 0x"));
......@@ -1409,7 +1384,7 @@ prom_init(unsigned long r3, unsigned long r4, unsigned long pp,
* following, regardless of whether we have an SMP
* kernel or not.
*/
if ( _naca->processorCount > 1 )
if (RELOC(ppc64_is_smp))
prom_hold_cpus(mem);
mem = check_display(mem);
......@@ -2110,7 +2085,7 @@ find_type_devices(const char *type)
/*
* Returns all nodes linked together
*/
struct device_node * __openfirmware
struct device_node *
find_all_nodes(void)
{
struct device_node *head, **prevp, *np;
......@@ -2235,7 +2210,7 @@ get_property(struct device_node *np, const char *name, int *lenp)
/*
* Add a property to a node
*/
void __openfirmware
void
prom_add_property(struct device_node* np, struct property* prop)
{
struct property **next = &np->properties;
......@@ -2247,7 +2222,7 @@ prom_add_property(struct device_node* np, struct property* prop)
}
#if 0
void __openfirmware
void
print_properties(struct device_node *np)
{
struct property *pp;
......
/*
* linux/arch/ppc/kernel/ptrace.c
* linux/arch/ppc64/kernel/ptrace.c
*
* PowerPC version
* Copyright (C) 1995-1996 Gary Thomas (gdt@linuxppc.org)
......@@ -30,59 +30,13 @@
#include <asm/page.h>
#include <asm/pgtable.h>
#include <asm/system.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)
#include <asm/ptrace-common.h>
/*
* does not yet catch signals sent when the child dies.
* 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..
*
......@@ -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. */
case PTRACE_PEEKUSR: {
unsigned long index, tmp;
unsigned long index;
unsigned long tmp;
ret = -EIO;
/* convert to index and check */
index = (unsigned long) addr >> 3;
if ((addr & 7) || index > PT_FPSCR)
if ((addr & 7) || (index > PT_FPSCR))
break;
if (index < PT_FPR0) {
tmp = get_reg(child, (int) index);
tmp = get_reg(child, (int)index);
} else {
if (child->thread.regs->msr & MSR_FP)
giveup_fpu(child);
......@@ -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_POKEDATA:
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;
ret = -EIO;
break;
......@@ -183,7 +139,7 @@ int sys_ptrace(long request, long pid, long addr, long data)
ret = -EIO;
/* convert to index and check */
index = (unsigned long) addr >> 3;
if ((addr & 7) || index > PT_FPSCR)
if ((addr & 7) || (index > PT_FPSCR))
break;
if (index == PT_ORIG_R3)
......@@ -216,11 +172,11 @@ int sys_ptrace(long request, long pid, long addr, long data)
break;
}
/*
* 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
* exit.
*/
/*
* 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
* exit.
*/
case PTRACE_KILL: {
ret = 0;
if (child->state == TASK_ZOMBIE) /* already dead */
......@@ -249,56 +205,50 @@ int sys_ptrace(long request, long pid, long addr, long data)
ret = ptrace_detach(child, data);
break;
case PPC_PTRACE_GETREGS:
{ /* Get GPRs 0 - 31. */
case PPC_PTRACE_GETREGS: { /* Get GPRs 0 - 31. */
u64 tmp;
u64 cntr;
ret = 0;
for (cntr=0; cntr<32 && ret==0; ++cntr)
{
for (cntr=0; cntr<32 && ret==0; ++cntr) {
tmp = ((u64*)child->thread.regs)[cntr];
ret = put_user(tmp, (u64*)(data+cntr));
}
break;
}
case PPC_PTRACE_SETREGS:
{ /* Set GPRs 0 - 31. */
case PPC_PTRACE_SETREGS: { /* Set GPRs 0 - 31. */
u64 cntr;
ret = 0;
for (cntr=0; cntr<32 && ret==0; ++cntr)
{
ret = put_reg(child, cntr, *(u64*)(data+cntr));
}
break;
}
case PPC_PTRACE_GETFPREGS:
{ /* Get FPRs 0 - 31. */
case PPC_PTRACE_GETFPREGS: { /* Get FPRs 0 - 31. */
u64 tmp;
u64 cntr;
ret = -EIO;
if (child->thread.regs->msr & MSR_FP)
giveup_fpu(child);
ret = 0;
for (cntr=0; cntr<32 && ret==0; ++cntr)
{
for (cntr=0; cntr<32 && ret==0; ++cntr) {
tmp = ((u64*)child->thread.fpr)[cntr];
ret = put_user(tmp, (u64*)(data+cntr));
}
break;
}
case PPC_PTRACE_SETFPREGS:
{ /* Get FPRs 0 - 31. */
case PPC_PTRACE_SETFPREGS: { /* Get FPRs 0 - 31. */
u64 cntr;
ret = -EIO;
if (child->thread.regs->msr & MSR_FP)
giveup_fpu(child);
for (cntr=0; cntr<32; ++cntr)
{
((u64*)child->thread.fpr)[cntr] = *(u64*)(data+cntr);
}
ret = 0;
break;
}
......@@ -334,4 +284,3 @@ void do_syscall_trace(void)
current->exit_code = 0;
}
}
This diff is collapsed.
......@@ -16,15 +16,19 @@
#include <linux/types.h>
#include <linux/spinlock.h>
#include <asm/init.h>
#include <asm/prom.h>
#include <asm/rtas.h>
#include <asm/semaphore.h>
#include <asm/machdep.h>
#include <asm/paca.h>
#include <asm/page.h>
#include <asm/system.h>
#include <asm/abs_addr.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
* and data have been mapped to KERNELBASE. At this point the code
......@@ -105,7 +109,6 @@ call_rtas_display_status(char c)
#if 0
#define DEBUG_RTAS
#endif
__openfirmware
int
rtas_token(const char *service)
{
......@@ -120,7 +123,6 @@ rtas_token(const char *service)
return tokp ? *tokp : RTAS_UNKNOWN_SERVICE;
}
__openfirmware
long
rtas_call(int token, int nargs, int nret,
unsigned long *outputs, ...)
......@@ -184,25 +186,107 @@ rtas_call(int token, int nargs, int nret,
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)
{
if (rtas_firmware_flash_list.next)
rtas_flash_firmware();
printk("RTAS system-reboot returned %ld\n",
rtas_call(rtas_token("system-reboot"), 0, 1, NULL));
for (;;);
}
void __chrp
void
rtas_power_off(void)
{
if (rtas_firmware_flash_list.next)
rtas_flash_bypass_warning();
/* allow power on only with power button press */
printk("RTAS power-off returned %ld\n",
rtas_call(rtas_token("power-off"), 2, 1, NULL,0xffffffff,0xffffffff));
for (;;);
}
void __chrp
void
rtas_halt(void)
{
if (rtas_firmware_flash_list.next)
rtas_flash_bypass_warning();
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");
......@@ -220,10 +220,15 @@ static int rtasd(void *unused)
current->nice = sys_sched_get_priority_max(SCHED_FIFO) + 1;
#endif
cpu = 0;
set_cpus_allowed(current, 1UL << cpu_logical_map(cpu));
repeat:
for (cpu = 0; cpu < NR_CPUS; cpu++) {
if (!cpu_online(cpu))
continue;
DEBUG("scheduling on %d\n", cpu);
set_cpus_allowed(current, 1UL << cpu);
DEBUG("watchdog scheduled on cpu %d\n", smp_processor_id());
while(1) {
do {
memset(logdata, 0, rtas_error_log_max);
error = rtas_call(event_scan, 4, 1, NULL,
......@@ -239,25 +244,6 @@ static int rtasd(void *unused)
} while(error == 0);
DEBUG("watchdog scheduled on cpu %d\n", smp_processor_id());
cpu++;
if (cpu >= smp_num_cpus) {
if (first_pass && surveillance_requested) {
DEBUG("enabling surveillance\n");
if (enable_surveillance())
goto error_vfree;
DEBUG("surveillance enabled\n");
}
first_pass = 0;
cpu = 0;
}
set_cpus_allowed(current, 1UL << cpu_logical_map(cpu));
/* Check all cpus for pending events before sleeping*/
if (!first_pass) {
set_current_state(TASK_INTERRUPTIBLE);
......@@ -265,6 +251,17 @@ static int rtasd(void *unused)
}
}
if (first_pass && surveillance_requested) {
DEBUG("enabling surveillance\n");
if (enable_surveillance())
goto error_vfree;
DEBUG("surveillance enabled\n");
} else {
first_pass = 0;
}
goto repeat;
error_vfree:
vfree(rtas_log_buf);
error:
......
......@@ -23,7 +23,6 @@
#include <linux/ioport.h>
#include <linux/tty.h>
#include <linux/root_dev.h>
#include <asm/init.h>
#include <asm/io.h>
#include <asm/prom.h>
#include <asm/processor.h>
......@@ -43,9 +42,6 @@ extern unsigned long klimit;
extern HTAB htab_data;
extern unsigned long loops_per_jiffy;
extern unsigned long embedded_sysmap_start;
extern unsigned long embedded_sysmap_end;
int have_of = 1;
extern void chrp_init(unsigned long r3,
......@@ -54,7 +50,6 @@ extern void chrp_init(unsigned long r3,
unsigned long r6,
unsigned long r7);
extern void chrp_init_map_io_space( void );
extern void iSeries_init( void );
extern void iSeries_init_early( void );
extern void pSeries_init_early( void );
......@@ -173,10 +168,6 @@ void setup_system(unsigned long r3, unsigned long r4, unsigned long r5,
udbg_puthex((unsigned long)naca);
udbg_putc('\n');
udbg_puts("naca->processorCount = 0x");
udbg_puthex(naca->processorCount);
udbg_putc('\n');
udbg_puts("naca->physicalMemorySize = 0x");
udbg_puthex(naca->physicalMemorySize);
udbg_putc('\n');
......@@ -338,7 +329,7 @@ static int show_cpuinfo(struct seq_file *m, void *v)
if (ppc_md.setup_residual != NULL)
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;
}
......@@ -499,6 +490,7 @@ void __init ppc64_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.
......
This diff is collapsed.
This diff is collapsed.
......@@ -28,7 +28,6 @@
#define __KERNEL_SYSCALLS__
#include <linux/unistd.h>
#include <linux/init.h>
/* #include <linux/openpic.h> */
#include <linux/spinlock.h>
#include <linux/cache.h>
#include <linux/err.h>
......@@ -40,7 +39,6 @@
#include <asm/pgtable.h>
#include <asm/hardirq.h>
#include <asm/softirq.h>
#include <asm/init.h>
#include <asm/io.h>
#include <asm/prom.h>
#include <asm/smp.h>
......@@ -56,20 +54,18 @@
int smp_threads_ready = 0;
volatile int smp_commenced = 0;
int smp_num_cpus = 1;
int smp_tb_synchronized = 0;
spinlock_t kernel_flag __cacheline_aligned = SPIN_LOCK_UNLOCKED;
unsigned long cache_decay_ticks;
static int max_cpus __initdata = NR_CPUS;
unsigned long cpu_online_map;
/* initialised so it doesnt end up in bss */
unsigned long cpu_online_map = 0;
int boot_cpuid = 0;
int ppc64_is_smp = 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[];
int start_secondary(void *);
......@@ -104,7 +100,7 @@ void iSeries_smp_message_recv( struct pt_regs * regs )
int cpu = smp_processor_id();
int msg;
if ( smp_num_cpus < 2 )
if ( num_online_cpus() < 2 )
return;
for ( msg = 0; msg < 4; ++msg )
......@@ -116,11 +112,16 @@ void iSeries_smp_message_recv( struct pt_regs * regs )
static void smp_iSeries_message_pass(int target, int msg, unsigned long data, int wait)
{
int i;
for (i = 0; i < smp_num_cpus; ++i) {
if ( (target == MSG_ALL) ||
(target == i) ||
((target == MSG_ALL_BUT_SELF) && (i != smp_processor_id())) ) {
set_bit( msg, &iSeries_smp_message[i] );
for (i = 0; i < NR_CPUS; ++i) {
if (!cpu_online(i))
continue;
if ((target == MSG_ALL) ||
(target == i) ||
((target == MSG_ALL_BUT_SELF) &&
(i != smp_processor_id())) ) {
set_bit(msg, &iSeries_smp_message[i]);
HvCall_sendIPI(&(paca[i]));
}
}
......@@ -141,7 +142,7 @@ static int smp_iSeries_numProcs(void)
return np;
}
static int smp_iSeries_probe(void)
static void smp_iSeries_probe(void)
{
unsigned i;
unsigned np;
......@@ -155,9 +156,8 @@ static int smp_iSeries_probe(void)
paca[i].next_jiffy_update_tb = paca[0].next_jiffy_update_tb;
}
}
smp_tb_synchronized = 1;
return np;
}
static void smp_iSeries_kick_cpu(int nr)
......@@ -197,8 +197,10 @@ void smp_init_iSeries(void)
ppc_md.smp_probe = smp_iSeries_probe;
ppc_md.smp_kick_cpu = smp_iSeries_kick_cpu;
ppc_md.smp_setup_cpu = smp_iSeries_setup_cpu;
#ifdef CONFIG_PPC_ISERIES
#warning fix for iseries
naca->processorCount = smp_iSeries_numProcs();
#endif
}
......@@ -226,13 +228,10 @@ smp_openpic_message_pass(int target, int msg, unsigned long data, int wait)
}
}
static int
smp_chrp_probe(void)
static void smp_chrp_probe(void)
{
if (naca->processorCount > 1)
if (ppc64_is_smp)
openpic_request_IPIs();
return naca->processorCount;
}
static void
......@@ -259,14 +258,14 @@ smp_kick_cpu(int nr)
extern struct gettimeofday_struct do_gtod;
static void smp_space_timers( unsigned nr )
static void smp_space_timers()
{
unsigned long offset, i;
offset = tb_ticks_per_jiffy / nr;
for ( i=1; i<nr; ++i ) {
paca[i].next_jiffy_update_tb = paca[i-1].next_jiffy_update_tb + offset;
}
int i;
unsigned long offset = tb_ticks_per_jiffy / NR_CPUS;
for (i = 1; i < NR_CPUS; ++i)
paca[i].next_jiffy_update_tb =
paca[i-1].next_jiffy_update_tb + offset;
}
static void
......@@ -278,7 +277,7 @@ smp_chrp_setup_cpu(int cpu_nr)
if (naca->platform == PLATFORM_PSERIES_LPAR) {
/* timebases already synced under the hypervisor. */
paca[cpu_nr].next_jiffy_update_tb = tb_last_stamp = get_tb();
if (cpu_nr == 0) {
if (cpu_nr == boot_cpuid) {
do_gtod.tb_orig_stamp = tb_last_stamp;
/* Should update do_gtod.stamp_xsec.
* For now we leave it which means the time can be some
......@@ -287,9 +286,9 @@ smp_chrp_setup_cpu(int cpu_nr)
}
smp_tb_synchronized = 1;
} else {
if (cpu_nr == 0) {
if (cpu_nr == boot_cpuid) {
/* wait for all the others */
while (atomic_read(&ready) < smp_num_cpus)
while (atomic_read(&ready) < num_online_cpus())
barrier();
atomic_set(&ready, 1);
/* freeze the timebase */
......@@ -297,9 +296,9 @@ smp_chrp_setup_cpu(int cpu_nr)
mb();
frozen = 1;
set_tb(0, 0);
paca[0].next_jiffy_update_tb = 0;
smp_space_timers(smp_num_cpus);
while (atomic_read(&ready) < smp_num_cpus)
paca[boot_cpuid].next_jiffy_update_tb = 0;
smp_space_timers();
while (atomic_read(&ready) < num_online_cpus())
barrier();
/* thaw the timebase again */
rtas_call(rtas_token("thaw-time-base"), 0, 1, NULL);
......@@ -323,8 +322,8 @@ smp_chrp_setup_cpu(int cpu_nr)
if (OpenPIC_Addr) {
do_openpic_setup_cpu();
} else {
if (cpu_nr > 0)
xics_setup_cpu();
if (cpu_nr != boot_cpuid)
xics_setup_cpu();
}
}
......@@ -333,7 +332,10 @@ smp_xics_message_pass(int target, int msg, unsigned long data, int wait)
{
int i;
for (i = 0; i < smp_num_cpus; ++i) {
for (i = 0; i < NR_CPUS; ++i) {
if (!cpu_online(i))
continue;
if (target == MSG_ALL || target == i
|| (target == MSG_ALL_BUT_SELF
&& i != smp_processor_id())) {
......@@ -344,10 +346,8 @@ smp_xics_message_pass(int target, int msg, unsigned long data, int wait)
}
}
static int
smp_xics_probe(void)
static void smp_xics_probe(void)
{
return naca->processorCount;
}
/* This is called very early */
......@@ -435,7 +435,6 @@ static void stop_this_cpu(void *dummy)
void smp_send_stop(void)
{
smp_call_function(stop_this_cpu, NULL, 1, 0);
smp_num_cpus = 1;
}
/*
......@@ -473,7 +472,7 @@ int smp_call_function (void (*func) (void *info), void *info, int nonatomic,
{
struct call_data_struct data;
int ret = -1, cpus = smp_num_cpus-1;
int ret = -1, cpus = num_online_cpus()-1;
int timeout;
if (!cpus)
......@@ -560,29 +559,23 @@ struct thread_struct *current_set[NR_CPUS] = {&init_thread_union, 0};
void __init smp_boot_cpus(void)
{
int i, cpu_nr;
int i, cpu_nr = 0;
struct task_struct *p;
printk("Entering SMP Mode...\n");
smp_num_cpus = 1;
smp_store_cpu_info(0);
cpu_online_map = 1UL;
smp_store_cpu_info(boot_cpuid);
cpu_callin_map[boot_cpuid] = 1;
/*
* assume for now that the first cpu booted is
* cpu 0, the master -- Cort
*/
cpu_callin_map[0] = 1;
/* XXX buggy - Anton */
current_thread_info()->cpu = 0;
for (i = 0; i < NR_CPUS; i++) {
paca[i].prof_counter = 1;
paca[i].prof_multiplier = 1;
if(i != 0) {
if (i != boot_cpuid) {
/*
* Processor 0's segment table is statically
* the boot cpu segment table is statically
* initialized to real address 0x5000. The
* Other processor's tables are created and
* initialized here.
......@@ -595,36 +588,37 @@ void __init smp_boot_cpus(void)
}
/*
* XXX very rough. On POWER4 we optimise tlb flushes for
* tasks that only run on one cpu so we increase decay ticks.
* XXX very rough.
*/
if (__is_processor(PV_POWER4))
cache_decay_ticks = HZ/50;
else
cache_decay_ticks = HZ/100;
cache_decay_ticks = HZ/100;
/* Probe arch for CPUs */
cpu_nr = ppc_md.smp_probe();
ppc_md.smp_probe();
for (i = 0; i < NR_CPUS; i++) {
if (paca[i].active)
cpu_nr++;
}
printk("Probe found %d CPUs\n", cpu_nr);
/*
* only check for cpus we know exist. We keep the callin map
* with cpus at the bottom -- Cort
*/
if (cpu_nr > max_cpus)
cpu_nr = max_cpus;
#ifdef CONFIG_ISERIES
smp_space_timers( cpu_nr );
smp_space_timers();
#endif
printk("Waiting for %d CPUs\n", cpu_nr-1);
for ( i = 1 ; i < cpu_nr; i++ ) {
for (i = 1 ; i < NR_CPUS; i++) {
int c;
struct pt_regs regs;
if (!paca[i].active)
continue;
if (i == boot_cpuid)
continue;
if (num_online_cpus() >= max_cpus)
break;
/* create a process for the processor */
/* we don't care about the values in regs since we'll
never reschedule the forked task. */
......@@ -668,16 +662,15 @@ void __init smp_boot_cpus(void)
{
printk("Processor %d found.\n", i);
/* this sync's the decr's -- Cort */
smp_num_cpus++;
} else {
printk("Processor %d is stuck.\n", i);
}
}
/* Setup CPU 0 last (important) */
ppc_md.smp_setup_cpu(0);
if (smp_num_cpus < 2) {
/* Setup boot cpu last (important) */
ppc_md.smp_setup_cpu(boot_cpuid);
if (num_online_cpus() < 2) {
tb_last_stamp = get_tb();
smp_tb_synchronized = 1;
}
......@@ -699,8 +692,9 @@ void __init smp_callin(void)
smp_store_cpu_info(cpu);
set_dec(paca[cpu].default_decr);
cpu_callin_map[cpu] = 1;
set_bit(smp_processor_id(), &cpu_online_map);
smp_mb();
cpu_callin_map[cpu] = 1;
ppc_md.smp_setup_cpu(cpu);
......@@ -729,7 +723,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;
}
......
......@@ -53,7 +53,6 @@
#include <asm/nvram.h>
#include <asm/cache.h>
#include <asm/machdep.h>
#include <asm/init.h>
#ifdef CONFIG_PPC_ISERIES
#include <asm/iSeries/HvCallXm.h>
#endif
......
......@@ -340,7 +340,7 @@ xics_init_IRQ( void )
/* Find the server numbers for the boot cpu. */
for (np = find_type_devices("cpu"); np; np = np->next) {
ireg = (uint *)get_property(np, "reg", &ilen);
if (ireg && ireg[0] == hard_smp_processor_id()) {
if (ireg && ireg[0] == smp_processor_id()) {
ireg = (uint *)get_property(np, "ibm,ppc-interrupt-gserver#s", &ilen);
i = ilen / sizeof(int);
if (ireg && i > 0) {
......@@ -371,10 +371,12 @@ xics_init_IRQ( void )
if (naca->platform == PLATFORM_PSERIES) {
#ifdef CONFIG_SMP
for (i = 0; i < naca->processorCount; ++i) {
for (i = 0; i < NR_CPUS; ++i) {
if (!paca[i].active)
continue;
xics_info.per_cpu[i] =
__ioremap((ulong)inodes[get_hard_smp_processor_id(i)].addr,
(ulong)inodes[get_hard_smp_processor_id(i)].size, _PAGE_NO_CACHE);
__ioremap((ulong)inodes[i].addr,
(ulong)inodes[i].size, _PAGE_NO_CACHE);
}
#else
xics_info.per_cpu[0] = __ioremap((ulong)intr_base, intr_size, _PAGE_NO_CACHE);
......@@ -395,7 +397,7 @@ xics_init_IRQ( void )
for (; i < NR_IRQS; ++i)
irq_desc[i].handler = &xics_pic;
ops->cppr_info(0, 0xff);
ops->cppr_info(boot_cpuid, 0xff);
iosync();
if (xics_irq_8259_cascade != -1) {
if (request_irq(xics_irq_8259_cascade + XICS_IRQ_OFFSET, no_action,
......@@ -420,23 +422,6 @@ void xics_isa_init(void)
i8259_init();
}
/*
* Find first logical cpu and return its physical cpu number
*/
static inline u32 physmask(u32 cpumask)
{
int i;
for (i = 0; i < smp_num_cpus; ++i, cpumask >>= 1) {
if (cpumask & 1)
return get_hard_smp_processor_id(i);
}
printk(KERN_ERR "xics_set_affinity: invalid irq mask\n");
return default_distrib_server;
}
void xics_set_affinity(unsigned int virq, unsigned long cpumask)
{
irq_desc_t *desc = irq_desc + virq;
......@@ -462,10 +447,13 @@ void xics_set_affinity(unsigned int virq, unsigned long cpumask)
}
/* For the moment only implement delivery to all cpus or one cpu */
if (cpumask == 0xffffffff)
if (cpumask == 0xffffffff) {
newmask = default_distrib_server;
else
newmask = physmask(cpumask);
} else {
if (!(cpumask & cpu_online_map))
goto out;
newmask = find_first_bit(&cpumask, 32);
}
status = rtas_call(ibm_set_xive, 3, 1, NULL,
irq, newmask, xics_status[1]);
......
This diff is collapsed.
......@@ -117,19 +117,6 @@ SECTIONS
. = ALIGN(4096);
__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 :
{
......
......@@ -6,7 +6,6 @@
* as published by the Free Software Foundation; either version
* 2 of the License, or (at your option) any later version.
*/
#include <linux/config.h>
#define GETREG(reg) \
static inline unsigned long get_ ## reg (void) \
......
......@@ -123,11 +123,7 @@ static void mem_translate(void);
static void mem_check(void);
static void mem_find_real(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);
extern int print_insn_big_powerpc(FILE *, unsigned long, unsigned long);
......@@ -642,27 +638,15 @@ cmds(struct pt_regs *excp)
case 'c':
mem_check();
break;
case 'j':
mem_map_check_slab();
break;
case 'f':
mem_find_real();
break;
case 'e':
mem_find_vsid();
break;
case 'r':
mem_check_dup_rpn();
break;
case 'i':
show_mem();
break;
case 'o':
mem_check_pagetable_vsids ();
break;
case 'q':
mem_map_lock_pages() ;
break;
default:
termch = cmd;
memex();
......@@ -2458,249 +2442,6 @@ void mem_find_vsid()
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) {
unsigned long val, cmd, on;
......
......@@ -259,6 +259,12 @@ static __inline__ int ffs(int x)
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
* of bits set) of a N-bit word
......
......@@ -8,6 +8,7 @@
#define __ARCH_PPC64_CACHE_H
/* bytes per L1 cache line */
#define L1_CACHE_BYTES 128
#define L1_CACHE_SHIFT 7
#define L1_CACHE_BYTES (1 << L1_CACHE_SHIFT)
#endif
......@@ -15,7 +15,7 @@
#include <linux/config.h>
#include <linux/brlock.h>
#include <linux/spinlock.h>
#include <asm/smp.h>
typedef struct {
unsigned long __softirq_pending;
......@@ -67,8 +67,8 @@ static __inline__ int irqs_running(void)
{
int i;
for (i = 0; i < smp_num_cpus; i++)
if (local_irq_count(cpu_logical_map(i)))
for (i = 0; i < NR_CPUS; i++)
if (local_irq_count(i))
return 1;
return 0;
}
......
......@@ -130,6 +130,9 @@ enum HvCall_VaryOffChunkRc
#define HvCallBaseRouter28 HvCallBase + 28
#define HvCallBaseRouter29 HvCallBase + 29
#define HvCallBaseRouter30 HvCallBase + 30
#define HvCallCcSetDABR HvCallCc + 7
//=====================================================================================
static inline void HvCall_setVirtualDecr(void)
{
......@@ -197,6 +200,10 @@ static inline void HvCall_terminateMachineSrc(void)
HvCall0( HvCallBaseTerminateMachineSrc );
}
static inline void HvCall_setDABR(unsigned long val)
{
HvCall1(HvCallCcSetDABR, val);
}
#endif // _HVCALL_H
......@@ -106,21 +106,21 @@ static inline u64 HvCallHpt_invalidateSetSwBitsGet(u32 hpteIndex, u8 bitson, u8
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 );
// getPaca()->adjustHmtForNoOfSpinLocksHeld();
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 );
// getPaca()->adjustHmtForNoOfSpinLocksHeld();
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 );
// getPaca()->adjustHmtForNoOfSpinLocksHeld();
......@@ -128,7 +128,7 @@ static inline void HvCallHpt_get( struct HPTE *hpte, u32 hpteIndex )
//============================================================================
static inline void HvCallHpt_addValidate( u32 hpteIndex,
u32 hBit,
struct HPTE *hpte )
HPTE *hpte )
{
HvCall4( HvCallHptAddValidate, hpteIndex,
......
......@@ -25,6 +25,7 @@
#define _HVCALLSC_H
#define HvCallBase 0x8000000000000000
#define HvCallCc 0x8001000000000000
#define HvCallCfg 0x8002000000000000
#define HvCallEvent 0x8003000000000000
#define HvCallHpt 0x8004000000000000
......
#ifndef _PPC64_INIT_H
#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 */
#error "<asm/init.h> should never be used - use <linux/init.h> instead"
......@@ -13,6 +13,7 @@
* 2 of the License, or (at your option) any later version.
*/
#include <linux/config.h>
#include <asm/prom.h>
extern unsigned long reloc_offset(void);
......
......@@ -62,7 +62,7 @@ struct machdep_calls {
int msg,
unsigned long data,
int wait);
int (*smp_probe)(void);
void (*smp_probe)(void);
void (*smp_kick_cpu)(int nr);
void (*smp_setup_cpu)(int nr);
......
/*
* 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_ */
......@@ -18,7 +18,6 @@ struct naca_struct {
u64 xRamDiskSize; /* In pages */
struct paca_struct *paca; /* Ptr to an array of pacas */
u64 debug_switch; /* Bits to control debug printing */
u16 processorCount; /* # of physical processors */
u16 dCacheL1LineSize; /* Line size of L1 DCache in bytes */
u16 dCacheL1LogLineSize; /* Log-2 of DCache line size */
u16 dCacheL1LinesPerPage; /* DCache lines per page */
......
......@@ -71,7 +71,7 @@ struct paca_struct {
struct ItLpRegSave *xLpRegSavePtr; /* Pointer to LpRegSave for PLIC 0x08 */
u64 xCurrent; /* Pointer to current 0x10 */
u16 xPacaIndex; /* Logical processor number 0x18 */
u16 xHwProcNum; /* Actual Hardware Processor Number 0x1a */
u16 active; /* Is this cpu active? 0x1a */
u32 default_decr; /* Default decrementer value 0x1c */
u64 xHrdIntStack; /* Stack for hardware interrupts 0x20 */
u64 xKsave; /* Saved Kernel stack addr or zero 0x28 */
......
......@@ -33,24 +33,13 @@
#ifndef __ASSEMBLY__
#include <asm/naca.h>
#define STRICT_MM_TYPECHECKS
#undef STRICT_MM_TYPECHECKS
#define REGION_SIZE 4UL
#define OFFSET_SIZE 60UL
#define REGION_SHIFT 60UL
#define OFFSET_SHIFT 0UL
#define REGION_MASK (((1UL<<REGION_SIZE)-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)
{
unsigned long lines, line_size;
......@@ -70,8 +59,8 @@ static __inline__ void clear_page(void *addr)
extern void copy_page(void *to, void *from);
struct page;
extern void clear_user_page(void *page, unsigned long vaddr);
extern void copy_user_page(void *to, void *from, 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, struct page *p);
#ifdef STRICT_MM_TYPECHECKS
/*
......@@ -215,8 +204,15 @@ static inline int get_order(unsigned long size)
#define __a2p(x) ((void *) 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 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 pfn_valid(pfn) ((pfn) < max_mapnr)
......
......@@ -53,6 +53,8 @@ pmd_free(pmd_t *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(mm, pmd, pte_page) \
pmd_populate_kernel(mm, pmd, page_address(pte_page))
......@@ -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_tlb(tlb, pte) pte_free(pte)
#define check_pgt_cache() do { } while (0)
......
......@@ -12,11 +12,6 @@
#include <asm/page.h>
#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 */
#define PMD_SHIFT (PAGE_SHIFT + PAGE_SHIFT - 3)
#define PMD_SIZE (1UL << PMD_SHIFT)
......@@ -107,9 +102,9 @@
/* preserving _PAGE_SECONDARY | _PAGE_GROUP_IX */
#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 */
#define PAGE_NONE __pgprot(_PAGE_PRESENT | _PAGE_ACCESSED)
......@@ -330,8 +325,6 @@ static inline void pte_clear(pte_t * ptep)
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;
#define USER_PGD_PTRS (PAGE_OFFSET >> PGDIR_SHIFT)
......@@ -356,6 +349,7 @@ extern void paging_init(void);
* ahead of time, instead of waiting for the inevitable extra
* hash-table miss exception.
*/
struct vm_area_struct;
extern void update_mmu_cache(struct vm_area_struct *, unsigned long, pte_t);
/* Encode and de-code a swap entry */
......@@ -380,12 +374,8 @@ extern void update_mmu_cache(struct vm_area_struct *, unsigned long, pte_t);
*/
#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_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 /* _PPC64_PGTABLE_H */
......@@ -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_size_cells(struct device_node* np);
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 */
/*
* 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 @@
#define _PPC64_RTAS_H
#include <linux/spinlock.h>
#include <asm/page.h>
/*
* Definitions for talking to the RTAS on CHRP machines.
......@@ -128,6 +129,29 @@ struct rtas_error_log {
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 void enter_rtas(struct rtas_args *);
......@@ -140,4 +164,7 @@ extern void rtas_restart(char *cmd);
extern void rtas_power_off(void);
extern void rtas_halt(void);
extern struct proc_dir_entry *rtas_proc_dir;
#endif /* _PPC64_RTAS_H */
......@@ -39,16 +39,27 @@ extern void smp_send_reschedule_all(void);
#define NO_PROC_ID 0xFF /* No processor magic marker */
/* 1 to 1 mapping on PPC -- Cort */
#define cpu_logical_map(cpu) (cpu)
#define cpu_number_map(x) (x)
#define cpu_online(cpu) test_bit((cpu), &cpu_online_map)
#define cpu_possible(cpu) paca[cpu].active
static inline int num_online_cpus(void)
{
int i, nr = 0;
for (i = 0; i < NR_CPUS; i++)
nr += test_bit(i, &cpu_online_map);
return nr;
}
extern volatile unsigned long cpu_callin_map[NR_CPUS];
#define smp_processor_id() (get_paca()->xPacaIndex)
#define hard_smp_processor_id() (get_paca()->xHwProcNum)
#define get_hard_smp_processor_id(CPU) (paca[(CPU)].xHwProcNum)
/* remove when the boot sequence gets rewritten to use hotplug interface */
extern int boot_cpuid;
extern int ppc64_is_smp;
/* Since OpenPIC has only 4 IPIs, we use slightly different message numbers.
*
......
......@@ -8,22 +8,20 @@
* 2 of the License, or (at your option) any later version.
*/
#include <asm/atomic.h>
#include <asm/hardirq.h>
#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(); \
if (!--local_bh_count(smp_processor_id()) \
&& softirq_pending(smp_processor_id())) { \
do_softirq(); \
} \
} while (0)
#define in_softirq() (local_bh_count(smp_processor_id()) != 0)
#endif /* __ASM_SOFTIRQ_H */
......@@ -9,19 +9,11 @@
*/
#include <linux/config.h>
#include <linux/kdev_t.h>
#include <asm/page.h>
#include <asm/processor.h>
#include <asm/hw_irq.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.
* The sync instruction guarantees that all memory accesses initiated
......@@ -85,29 +77,23 @@ extern void (*xmon_fault_handler)(struct pt_regs *regs);
extern void print_backtrace(unsigned long *);
extern void show_regs(struct pt_regs * regs);
extern void flush_instruction_cache(void);
extern void hard_reset_now(void);
extern void poweroff_now(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 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_df(double *from, float *to, unsigned long *fpscr);
extern int abs(int);
struct device_node;
struct task_struct;
#define prepare_to_switch() do { } while(0)
#define switch_to(prev,next) _switch_to((prev),(next))
#define switch_to(prev,next,last) _switch_to((prev),(next))
extern void _switch_to(struct task_struct *, struct task_struct *);
#define prepare_arch_schedule(prev) do { } while(0)
#define finish_arch_schedule(prev) do { } while(0)
#define prepare_arch_switch(rq) do { } while(0)
#define finish_arch_switch(rq) spin_unlock_irq(&(rq)->lock)
struct thread_struct;
extern void _switch(struct thread_struct *prev, struct thread_struct *next);
......
......@@ -14,6 +14,7 @@
#define __PPC64_TIME_H
#ifdef __KERNEL__
#include <linux/config.h>
#include <linux/types.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>
/* 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,
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 */
......@@ -124,9 +124,6 @@ do { \
} \
} 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
* 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