diff options
Diffstat (limited to 'arch/ppc64/kernel')
-rw-r--r-- | arch/ppc64/kernel/LparData.c | 88 | ||||
-rw-r--r-- | arch/ppc64/kernel/head.S | 42 | ||||
-rw-r--r-- | arch/ppc64/kernel/machine_kexec.c | 12 | ||||
-rw-r--r-- | arch/ppc64/kernel/misc.S | 6 | ||||
-rw-r--r-- | arch/ppc64/kernel/mpic.c | 4 | ||||
-rw-r--r-- | arch/ppc64/kernel/mpic.h | 2 | ||||
-rw-r--r-- | arch/ppc64/kernel/pci.c | 20 | ||||
-rw-r--r-- | arch/ppc64/kernel/pmac_setup.c | 12 | ||||
-rw-r--r-- | arch/ppc64/kernel/prom.c | 2 | ||||
-rw-r--r-- | arch/ppc64/kernel/setup.c | 2 | ||||
-rw-r--r-- | arch/ppc64/kernel/smp.c | 15 | ||||
-rw-r--r-- | arch/ppc64/kernel/udbg.c | 2 | ||||
-rw-r--r-- | arch/ppc64/kernel/xics.c | 31 |
13 files changed, 150 insertions, 88 deletions
diff --git a/arch/ppc64/kernel/LparData.c b/arch/ppc64/kernel/LparData.c index 6ffcf67..76cfd14 100644 --- a/arch/ppc64/kernel/LparData.c +++ b/arch/ppc64/kernel/LparData.c @@ -33,17 +33,36 @@ * the hypervisor and Linux. */ +/* + * WARNING - magic here + * + * Ok, this is a horrid hack below, but marginally better than the + * alternatives. What we really want is just to initialize + * hvReleaseData in C as in the #if 0 section here. However, gcc + * refuses to believe that (u32)&x is a constant expression, so will + * not allow the xMsNucDataOffset field to be properly initialized. + * So, we declare hvReleaseData in inline asm instead. We use inline + * asm, rather than a .S file, because the assembler won't generate + * the necessary relocation for the LparMap either, unless that symbol + * is declared in the same source file. Finally, we put the asm in a + * dummy, attribute-used function, instead of at file scope, because + * file scope asms don't allow contraints. We want to use the "i" + * constraints to put sizeof() and offsetof() expressions in there, + * because including asm/offsets.h in C code then stringifying causes + * all manner of warnings. + */ +#if 0 struct HvReleaseData hvReleaseData = { .xDesc = 0xc8a5d9c4, /* "HvRD" ebcdic */ .xSize = sizeof(struct HvReleaseData), .xVpdAreasPtrOffset = offsetof(struct naca_struct, xItVpdAreas), .xSlicNacaAddr = &naca, /* 64-bit Naca address */ - .xMsNucDataOffset = 0x4800, /* offset of LparMap within loadarea (see head.S) */ - .xTagsMode = 1, /* tags inactive */ - .xAddressSize = 0, /* 64 bit */ - .xNoSharedProcs = 0, /* shared processors */ - .xNoHMT = 0, /* HMT allowed */ - .xRsvd2 = 6, /* TEMP: This allows non-GA driver */ + .xMsNucDataOffset = (u32)((unsigned long)&xLparMap - KERNELBASE), + .xFlags = HVREL_TAGSINACTIVE /* tags inactive */ + /* 64 bit */ + /* shared processors */ + /* HMT allowed */ + | 6, /* TEMP: This allows non-GA driver */ .xVrmIndex = 4, /* We are v5r2m0 */ .xMinSupportedPlicVrmIndex = 3, /* v5r1m0 */ .xMinCompatablePlicVrmIndex = 3, /* v5r1m0 */ @@ -51,6 +70,63 @@ struct HvReleaseData hvReleaseData = { 0xa7, 0x40, 0xf2, 0x4b, 0xf4, 0x4b, 0xf6, 0xf4 }, }; +#endif + + +extern struct HvReleaseData hvReleaseData; + +static void __attribute_used__ hvReleaseData_wrapper(void) +{ + /* This doesn't appear to need any alignment (even 4 byte) */ + asm volatile ( + " lparMapPhys = xLparMap - %3\n" + " .data\n" + " .globl hvReleaseData\n" + "hvReleaseData:\n" + " .long 0xc8a5d9c4\n" /* xDesc */ + /* "HvRD" in ebcdic */ + " .short %0\n" /* xSize */ + " .short %1\n" /* xVpdAreasPtrOffset */ + " .llong naca\n" /* xSlicNacaAddr */ + " .long lparMapPhys\n" /* xMsNucDataOffset */ + " .long 0\n" /* xRsvd1 */ + " .short %2\n" /* xFlags */ + " .short 4\n" /* xVrmIndex - v5r2m0 */ + " .short 3\n" /* xMinSupportedPlicVrmIndex - v5r1m0 */ + " .short 3\n" /* xMinCompatablePlicVrmIndex - v5r1m0 */ + " .long 0xd38995a4\n" /* xVrmName */ + " .long 0xa740f24b\n" /* "Linux 2.4.64" ebcdic */ + " .long 0xf44bf6f4\n" + " . = hvReleaseData + %0\n" + " .previous\n" + : : "i"(sizeof(hvReleaseData)), + "i"(offsetof(struct naca_struct, xItVpdAreas)), + "i"(HVREL_TAGSINACTIVE /* tags inactive, 64 bit, */ + /* shared processors, HMT allowed */ + | 6), /* TEMP: This allows non-GA drivers */ + "i"(KERNELBASE) + ); +} + +struct LparMap __attribute__((aligned (16))) xLparMap = { + .xNumberEsids = HvEsidsToMap, + .xNumberRanges = HvRangesToMap, + .xSegmentTableOffs = STAB0_PAGE, + + .xEsids = { + { .xKernelEsid = GET_ESID(KERNELBASE), + .xKernelVsid = KERNEL_VSID(KERNELBASE), }, + { .xKernelEsid = GET_ESID(VMALLOCBASE), + .xKernelVsid = KERNEL_VSID(VMALLOCBASE), }, + }, + + .xRanges = { + { .xPages = HvPagesToMap, + .xOffset = 0, + .xVPN = KERNEL_VSID(KERNELBASE) << (SID_SHIFT - PAGE_SHIFT), + }, + }, +}; extern void system_reset_iSeries(void); extern void machine_check_iSeries(void); diff --git a/arch/ppc64/kernel/head.S b/arch/ppc64/kernel/head.S index 93ebcac0..784f56d 100644 --- a/arch/ppc64/kernel/head.S +++ b/arch/ppc64/kernel/head.S @@ -522,36 +522,9 @@ __end_interrupts: #ifdef CONFIG_PPC_ISERIES .globl naca naca: - .llong itVpdAreas - - /* - * The iSeries LPAR map is at this fixed address - * so that the HvReleaseData structure can address - * it with a 32-bit offset. - * - * The VSID values below are dependent on the - * VSID generation algorithm. See include/asm/mmu_context.h. - */ - - . = 0x4800 - - .llong 2 /* # ESIDs to be mapped by hypervisor */ - .llong 1 /* # memory ranges to be mapped by hypervisor */ - .llong STAB0_PAGE /* Page # of segment table within load area */ - .llong 0 /* Reserved */ - .llong 0 /* Reserved */ - .llong 0 /* Reserved */ - .llong 0 /* Reserved */ - .llong 0 /* Reserved */ - .llong (KERNELBASE>>SID_SHIFT) - .llong 0x408f92c94 /* KERNELBASE VSID */ - /* We have to list the bolted VMALLOC segment here, too, so that it - * will be restored on shared processor switch */ - .llong (VMALLOCBASE>>SID_SHIFT) - .llong 0xf09b89af5 /* VMALLOCBASE VSID */ - .llong 8192 /* # pages to map (32 MB) */ - .llong 0 /* Offset from start of loadarea to start of map */ - .llong 0x408f92c940000 /* VPN of first page to map */ + .llong itVpdAreas + .llong 0 /* xRamDisk */ + .llong 0 /* xRamDiskSize */ . = 0x6100 @@ -2098,7 +2071,7 @@ _GLOBAL(hmt_start_secondary) blr #endif -#if defined(CONFIG_SMP) && !defined(CONFIG_PPC_ISERIES) +#if defined(CONFIG_KEXEC) || (defined(CONFIG_SMP) && !defined(CONFIG_PPC_ISERIES)) _GLOBAL(smp_release_cpus) /* All secondary cpus are spinning on a common * spinloop, release them all now so they can start @@ -2131,13 +2104,6 @@ empty_zero_page: swapper_pg_dir: .space 4096 -#ifdef CONFIG_SMP -/* 1 page segment table per cpu (max 48, cpu0 allocated at STAB0_PHYS_ADDR) */ - .globl stab_array -stab_array: - .space 4096 * 48 -#endif - /* * This space gets a copy of optional info passed to us by the bootstrap * Used to pass parameters into the kernel like root=/dev/sda1, etc. diff --git a/arch/ppc64/kernel/machine_kexec.c b/arch/ppc64/kernel/machine_kexec.c index fdb2fc6..4775f12 100644 --- a/arch/ppc64/kernel/machine_kexec.c +++ b/arch/ppc64/kernel/machine_kexec.c @@ -185,7 +185,7 @@ void kexec_copy_flush(struct kimage *image) void kexec_smp_down(void *arg) { if (ppc_md.cpu_irq_down) - ppc_md.cpu_irq_down(); + ppc_md.cpu_irq_down(1); local_irq_disable(); kexec_smp_wait(); @@ -232,7 +232,7 @@ static void kexec_prepare_cpus(void) /* after we tell the others to go down */ if (ppc_md.cpu_irq_down) - ppc_md.cpu_irq_down(); + ppc_md.cpu_irq_down(0); put_cpu(); @@ -243,15 +243,19 @@ static void kexec_prepare_cpus(void) static void kexec_prepare_cpus(void) { + extern void smp_release_cpus(void); /* * move the secondarys to us so that we can copy * the new kernel 0-0x100 safely * * do this if kexec in setup.c ? + * + * We need to release the cpus if we are ever going from an + * UP to an SMP kernel. */ - smp_relase_cpus(); + smp_release_cpus(); if (ppc_md.cpu_irq_down) - ppc_md.cpu_irq_down(); + ppc_md.cpu_irq_down(0); local_irq_disable(); } diff --git a/arch/ppc64/kernel/misc.S b/arch/ppc64/kernel/misc.S index 59f4f99..a05b50b 100644 --- a/arch/ppc64/kernel/misc.S +++ b/arch/ppc64/kernel/misc.S @@ -1129,6 +1129,9 @@ _GLOBAL(sys_call_table32) .llong .compat_sys_waitid .llong .sys32_ioprio_set .llong .sys32_ioprio_get + .llong .sys_inotify_init /* 275 */ + .llong .sys_inotify_add_watch + .llong .sys_inotify_rm_watch .balign 8 _GLOBAL(sys_call_table) @@ -1407,3 +1410,6 @@ _GLOBAL(sys_call_table) .llong .sys_waitid .llong .sys_ioprio_set .llong .sys_ioprio_get + .llong .sys_inotify_init /* 275 */ + .llong .sys_inotify_add_watch + .llong .sys_inotify_rm_watch diff --git a/arch/ppc64/kernel/mpic.c b/arch/ppc64/kernel/mpic.c index e8fbab1..cc262a0 100644 --- a/arch/ppc64/kernel/mpic.c +++ b/arch/ppc64/kernel/mpic.c @@ -794,10 +794,10 @@ void mpic_setup_this_cpu(void) /* * XXX: someone who knows mpic should check this. - * do we need to eoi the ipi here (see xics comments)? + * do we need to eoi the ipi including for kexec cpu here (see xics comments)? * or can we reset the mpic in the new kernel? */ -void mpic_teardown_this_cpu(void) +void mpic_teardown_this_cpu(int secondary) { struct mpic *mpic = mpic_primary; unsigned long flags; diff --git a/arch/ppc64/kernel/mpic.h b/arch/ppc64/kernel/mpic.h index 99fbbc9..ca78a7f 100644 --- a/arch/ppc64/kernel/mpic.h +++ b/arch/ppc64/kernel/mpic.h @@ -256,7 +256,7 @@ extern unsigned int mpic_irq_get_priority(unsigned int irq); extern void mpic_setup_this_cpu(void); /* Clean up for kexec (or cpu offline or ...) */ -extern void mpic_teardown_this_cpu(void); +extern void mpic_teardown_this_cpu(int secondary); /* Request IPIs on primary mpic */ extern void mpic_request_ipis(void); diff --git a/arch/ppc64/kernel/pci.c b/arch/ppc64/kernel/pci.c index ae6f579..d0d55c7 100644 --- a/arch/ppc64/kernel/pci.c +++ b/arch/ppc64/kernel/pci.c @@ -108,8 +108,28 @@ void pcibios_resource_to_bus(struct pci_dev *dev, struct pci_bus_region *region region->end = res->end - offset; } +void pcibios_bus_to_resource(struct pci_dev *dev, struct resource *res, + struct pci_bus_region *region) +{ + unsigned long offset = 0; + struct pci_controller *hose = pci_bus_to_host(dev->bus); + + if (!hose) + return; + + if (res->flags & IORESOURCE_IO) + offset = (unsigned long)hose->io_base_virt - pci_io_base; + + if (res->flags & IORESOURCE_MEM) + offset = hose->pci_mem_offset; + + res->start = region->start + offset; + res->end = region->end + offset; +} + #ifdef CONFIG_HOTPLUG EXPORT_SYMBOL(pcibios_resource_to_bus); +EXPORT_SYMBOL(pcibios_bus_to_resource); #endif /* diff --git a/arch/ppc64/kernel/pmac_setup.c b/arch/ppc64/kernel/pmac_setup.c index 3013cdb..e40877f 100644 --- a/arch/ppc64/kernel/pmac_setup.c +++ b/arch/ppc64/kernel/pmac_setup.c @@ -97,7 +97,7 @@ EXPORT_SYMBOL(smu_cmdbuf_abs); extern void udbg_init_scc(struct device_node *np); -void __pmac pmac_show_cpuinfo(struct seq_file *m) +static void __pmac pmac_show_cpuinfo(struct seq_file *m) { struct device_node *np; char *pp; @@ -144,7 +144,7 @@ void __pmac pmac_show_cpuinfo(struct seq_file *m) } -void __init pmac_setup_arch(void) +static void __init pmac_setup_arch(void) { /* init to some ~sane value until calibrate_delay() runs */ loops_per_jiffy = 50000000; @@ -230,7 +230,7 @@ void __pmac note_bootable_part(dev_t dev, int part, int goodness) } } -void __pmac pmac_restart(char *cmd) +static void __pmac pmac_restart(char *cmd) { switch(sys_ctrler) { #ifdef CONFIG_ADB_PMU @@ -249,7 +249,7 @@ void __pmac pmac_restart(char *cmd) } } -void __pmac pmac_power_off(void) +static void __pmac pmac_power_off(void) { switch(sys_ctrler) { #ifdef CONFIG_ADB_PMU @@ -267,7 +267,7 @@ void __pmac pmac_power_off(void) } } -void __pmac pmac_halt(void) +static void __pmac pmac_halt(void) { pmac_power_off(); } @@ -327,7 +327,7 @@ static void __init init_boot_display(void) /* * Early initialization. */ -void __init pmac_init_early(void) +static void __init pmac_init_early(void) { DBG(" -> pmac_init_early\n"); diff --git a/arch/ppc64/kernel/prom.c b/arch/ppc64/kernel/prom.c index 47727a6..5aca01d 100644 --- a/arch/ppc64/kernel/prom.c +++ b/arch/ppc64/kernel/prom.c @@ -916,6 +916,7 @@ static int __init early_init_dt_scan_cpus(unsigned long node, } } +#ifdef CONFIG_ALTIVEC /* Check if we have a VMX and eventually update CPU features */ prop = (u32 *)get_flat_dt_prop(node, "ibm,vmx", NULL); if (prop && (*prop) > 0) { @@ -929,6 +930,7 @@ static int __init early_init_dt_scan_cpus(unsigned long node, cur_cpu_spec->cpu_features |= CPU_FTR_ALTIVEC; cur_cpu_spec->cpu_user_features |= PPC_FEATURE_HAS_ALTIVEC; } +#endif /* CONFIG_ALTIVEC */ /* * Check for an SMT capable CPU and set the CPU feature. We do diff --git a/arch/ppc64/kernel/setup.c b/arch/ppc64/kernel/setup.c index e80f10c..687e855 100644 --- a/arch/ppc64/kernel/setup.c +++ b/arch/ppc64/kernel/setup.c @@ -1068,6 +1068,8 @@ void __init setup_arch(char **cmdline_p) irqstack_early_init(); emergency_stack_init(); + stabs_alloc(); + /* set up the bootmem stuff with available memory */ do_init_bootmem(); sparse_init(); diff --git a/arch/ppc64/kernel/smp.c b/arch/ppc64/kernel/smp.c index 2fcddfc..793b562 100644 --- a/arch/ppc64/kernel/smp.c +++ b/arch/ppc64/kernel/smp.c @@ -65,8 +65,6 @@ struct smp_ops_t *smp_ops; static volatile unsigned int cpu_callin_map[NR_CPUS]; -extern unsigned char stab_array[]; - void smp_call_function_interrupt(void); int smt_enabled_at_boot = 1; @@ -492,19 +490,6 @@ int __devinit __cpu_up(unsigned int cpu) paca[cpu].default_decr = tb_ticks_per_jiffy; - if (!cpu_has_feature(CPU_FTR_SLB)) { - void *tmp; - - /* maximum of 48 CPUs on machines with a segment table */ - if (cpu >= 48) - BUG(); - - tmp = &stab_array[PAGE_SIZE * cpu]; - memset(tmp, 0, PAGE_SIZE); - paca[cpu].stab_addr = (unsigned long)tmp; - paca[cpu].stab_real = virt_to_abs(tmp); - } - /* Make sure callin-map entry is 0 (can be leftover a CPU * hotplug */ diff --git a/arch/ppc64/kernel/udbg.c b/arch/ppc64/kernel/udbg.c index d4ccd6f..c0da455 100644 --- a/arch/ppc64/kernel/udbg.c +++ b/arch/ppc64/kernel/udbg.c @@ -141,7 +141,7 @@ void udbg_init_scc(struct device_node *np) #endif /* CONFIG_PPC_PMAC */ -#if CONFIG_PPC_PMAC +#ifdef CONFIG_PPC_PMAC static void udbg_real_putc(unsigned char c) { while ((real_readb(sccc) & SCC_TXRDY) == 0) diff --git a/arch/ppc64/kernel/xics.c b/arch/ppc64/kernel/xics.c index 677c445..d9dc6f2 100644 --- a/arch/ppc64/kernel/xics.c +++ b/arch/ppc64/kernel/xics.c @@ -647,29 +647,30 @@ static void xics_set_affinity(unsigned int virq, cpumask_t cpumask) } } -void xics_teardown_cpu(void) +void xics_teardown_cpu(int secondary) { int cpu = smp_processor_id(); - int status; ops->cppr_info(cpu, 0x00); iosync(); /* - * we need to EOI the IPI if we got here from kexec down IPI - * - * xics doesn't care if we duplicate an EOI as long as we - * don't EOI and raise priority. - * - * probably need to check all the other interrupts too - * should we be flagging idle loop instead? - * or creating some task to be scheduled? + * Some machines need to have at least one cpu in the GIQ, + * so leave the master cpu in the group. */ - ops->xirr_info_set(cpu, XICS_IPI); - - status = rtas_set_indicator(GLOBAL_INTERRUPT_QUEUE, - (1UL << interrupt_server_size) - 1 - default_distrib_server, 0); - WARN_ON(status != 0); + if (secondary) { + /* + * we need to EOI the IPI if we got here from kexec down IPI + * + * probably need to check all the other interrupts too + * should we be flagging idle loop instead? + * or creating some task to be scheduled? + */ + ops->xirr_info_set(cpu, XICS_IPI); + rtas_set_indicator(GLOBAL_INTERRUPT_QUEUE, + (1UL << interrupt_server_size) - 1 - + default_distrib_server, 0); + } } #ifdef CONFIG_HOTPLUG_CPU |