Merge git://git.kernel.org/pub/scm/linux/kernel/git/paulus/powerpc

* git://git.kernel.org/pub/scm/linux/kernel/git/paulus/powerpc: (43 commits)
  [POWERPC] Use little-endian bit from firmware ibm,pa-features property
  [POWERPC] Make sure smp_processor_id works very early in boot
  [POWERPC] U4 DART improvements
  [POWERPC] todc: add support for Time-Of-Day-Clock
  [POWERPC] Make lparcfg.c work when both iseries and pseries are selected
  [POWERPC] Fix idr locking in init_new_context
  [POWERPC] mpc7448hpc2 (taiga) board config file
  [POWERPC] Add tsi108 pci and platform device data register function
  [POWERPC] Add general support for mpc7448hpc2 (Taiga) platform
  [POWERPC] Correct the MAX_CONTEXT definition
  powerpc: minor cleanups for mpc86xx
  [POWERPC] Make sure we select CONFIG_NEW_LEDS if ADB_PMU_LED is set
  [POWERPC] Simplify the code defining the 64-bit CPU features
  [POWERPC] powerpc: kconfig warning fix
  [POWERPC] Consolidate some of kernel/misc*.S
  [POWERPC] Remove unused function call_with_mmu_off
  [POWERPC] update asm-powerpc/time.h
  [POWERPC] Clean up it_lp_queue.h
  [POWERPC] Skip the "copy down" of the kernel if it is already at zero.
  [POWERPC] Add the use of the firmware soft-reset-nmi to kdump.
  ...
This commit is contained in:
Linus Torvalds
2006-06-29 11:32:34 -07:00
77 changed files with 4088 additions and 1112 deletions

View File

@@ -50,7 +50,8 @@ extra-$(CONFIG_FSL_BOOKE) := head_fsl_booke.o
extra-$(CONFIG_8xx) := head_8xx.o
extra-y += vmlinux.lds
obj-y += time.o prom.o traps.o setup-common.o udbg.o
obj-y += time.o prom.o traps.o setup-common.o \
udbg.o misc.o
obj-$(CONFIG_PPC32) += entry_32.o setup_32.o misc_32.o
obj-$(CONFIG_PPC64) += misc_64.o dma_64.o iommu.o
obj-$(CONFIG_PPC_MULTIPLATFORM) += prom_init.o

View File

@@ -125,7 +125,12 @@ _GLOBAL(__save_cpu_setup)
cmpwi r0,0x44
bne 2f
1: /* Save HID0,1,4 and 5 */
1: /* skip if not running in HV mode */
mfmsr r0
rldicl. r0,r0,4,63
beq 2f
/* Save HID0,1,4 and 5 */
mfspr r3,SPRN_HID0
std r3,CS_HID0(r5)
mfspr r3,SPRN_HID1
@@ -159,7 +164,12 @@ _GLOBAL(__restore_cpu_setup)
cmpwi r0,0x44
bnelr
1: /* Before accessing memory, we make sure rm_ci is clear */
1: /* skip if not running in HV mode */
mfmsr r0
rldicl. r0,r0,4,63
beqlr
/* Before accessing memory, we make sure rm_ci is clear */
li r0,0
mfspr r3,SPRN_HID4
rldimi r3,r0,40,23 /* clear bit 23 (rm_ci) */

View File

@@ -722,18 +722,6 @@ struct cpu_spec cpu_specs[] = {
.oprofile_type = PPC_OPROFILE_G4,
.platform = "ppc7450",
},
{ /* 8641 */
.pvr_mask = 0xffffffff,
.pvr_value = 0x80040010,
.cpu_name = "8641",
.cpu_features = CPU_FTRS_7447A,
.cpu_user_features = COMMON_USER | PPC_FEATURE_HAS_ALTIVEC_COMP,
.icache_bsize = 32,
.dcache_bsize = 32,
.num_pmcs = 6,
.cpu_setup = __setup_cpu_745x
},
{ /* 82xx (8240, 8245, 8260 are all 603e cores) */
.pvr_mask = 0x7fff0000,
.pvr_value = 0x00810000,

View File

@@ -24,9 +24,11 @@
#include <linux/init.h>
#include <linux/irq.h>
#include <linux/types.h>
#include <linux/irq.h>
#include <asm/processor.h>
#include <asm/machdep.h>
#include <asm/kexec.h>
#include <asm/kdump.h>
#include <asm/lmb.h>
#include <asm/firmware.h>
@@ -41,6 +43,7 @@
/* This keeps a track of which one is crashing cpu. */
int crashing_cpu = -1;
static cpumask_t cpus_in_crash = CPU_MASK_NONE;
static u32 *append_elf_note(u32 *buf, char *name, unsigned type, void *data,
size_t data_len)
@@ -98,34 +101,66 @@ static void crash_save_this_cpu(struct pt_regs *regs, int cpu)
}
#ifdef CONFIG_SMP
static atomic_t waiting_for_crash_ipi;
static atomic_t enter_on_soft_reset = ATOMIC_INIT(0);
void crash_ipi_callback(struct pt_regs *regs)
{
int cpu = smp_processor_id();
if (cpu == crashing_cpu)
return;
if (!cpu_online(cpu))
return;
local_irq_disable();
if (!cpu_isset(cpu, cpus_in_crash))
crash_save_this_cpu(regs, cpu);
cpu_set(cpu, cpus_in_crash);
/*
* Entered via soft-reset - could be the kdump
* process is invoked using soft-reset or user activated
* it if some CPU did not respond to an IPI.
* For soft-reset, the secondary CPU can enter this func
* twice. 1 - using IPI, and 2. soft-reset.
* Tell the kexec CPU that entered via soft-reset and ready
* to go down.
*/
if (cpu_isset(cpu, cpus_in_sr)) {
cpu_clear(cpu, cpus_in_sr);
atomic_inc(&enter_on_soft_reset);
}
/*
* Starting the kdump boot.
* This barrier is needed to make sure that all CPUs are stopped.
* If not, soft-reset will be invoked to bring other CPUs.
*/
while (!cpu_isset(crashing_cpu, cpus_in_crash))
cpu_relax();
if (ppc_md.kexec_cpu_down)
ppc_md.kexec_cpu_down(1, 1);
local_irq_disable();
crash_save_this_cpu(regs, cpu);
atomic_dec(&waiting_for_crash_ipi);
kexec_smp_wait();
/* NOTREACHED */
}
static void crash_kexec_prepare_cpus(void)
/*
* Wait until all CPUs are entered via soft-reset.
*/
static void crash_soft_reset_check(int cpu)
{
unsigned int ncpus = num_online_cpus() - 1;/* Excluding the panic cpu */
cpu_clear(cpu, cpus_in_sr);
while (atomic_read(&enter_on_soft_reset) != ncpus)
cpu_relax();
}
static void crash_kexec_prepare_cpus(int cpu)
{
unsigned int msecs;
atomic_set(&waiting_for_crash_ipi, num_online_cpus() - 1);
unsigned int ncpus = num_online_cpus() - 1;/* Excluding the panic cpu */
crash_send_ipi(crash_ipi_callback);
smp_wmb();
@@ -133,14 +168,13 @@ static void crash_kexec_prepare_cpus(void)
/*
* FIXME: Until we will have the way to stop other CPUSs reliabally,
* the crash CPU will send an IPI and wait for other CPUs to
* respond. If not, proceed the kexec boot even though we failed to
* capture other CPU states.
* respond.
* Delay of at least 10 seconds.
*/
printk(KERN_ALERT "Sending IPI to other cpus...\n");
printk(KERN_EMERG "Sending IPI to other cpus...\n");
msecs = 10000;
while ((atomic_read(&waiting_for_crash_ipi) > 0) && (--msecs > 0)) {
barrier();
while ((cpus_weight(cpus_in_crash) < ncpus) && (--msecs > 0)) {
cpu_relax();
mdelay(1);
}
@@ -149,18 +183,71 @@ static void crash_kexec_prepare_cpus(void)
/*
* FIXME: In case if we do not get all CPUs, one possibility: ask the
* user to do soft reset such that we get all.
* IPI handler is already set by the panic cpu initially. Therefore,
* all cpus could invoke this handler from die() and the panic CPU
* will call machine_kexec() directly from this handler to do
* kexec boot.
* Soft-reset will be used until better mechanism is implemented.
*/
if (atomic_read(&waiting_for_crash_ipi))
printk(KERN_ALERT "done waiting: %d cpus not responding\n",
atomic_read(&waiting_for_crash_ipi));
if (cpus_weight(cpus_in_crash) < ncpus) {
printk(KERN_EMERG "done waiting: %d cpu(s) not responding\n",
ncpus - cpus_weight(cpus_in_crash));
printk(KERN_EMERG "Activate soft-reset to stop other cpu(s)\n");
cpus_in_sr = CPU_MASK_NONE;
atomic_set(&enter_on_soft_reset, 0);
while (cpus_weight(cpus_in_crash) < ncpus)
cpu_relax();
}
/*
* Make sure all CPUs are entered via soft-reset if the kdump is
* invoked using soft-reset.
*/
if (cpu_isset(cpu, cpus_in_sr))
crash_soft_reset_check(cpu);
/* Leave the IPI callback set */
}
/*
* This function will be called by secondary cpus or by kexec cpu
* if soft-reset is activated to stop some CPUs.
*/
void crash_kexec_secondary(struct pt_regs *regs)
{
int cpu = smp_processor_id();
unsigned long flags;
int msecs = 5;
local_irq_save(flags);
/* Wait 5ms if the kexec CPU is not entered yet. */
while (crashing_cpu < 0) {
if (--msecs < 0) {
/*
* Either kdump image is not loaded or
* kdump process is not started - Probably xmon
* exited using 'x'(exit and recover) or
* kexec_should_crash() failed for all running tasks.
*/
cpu_clear(cpu, cpus_in_sr);
local_irq_restore(flags);
return;
}
mdelay(1);
cpu_relax();
}
if (cpu == crashing_cpu) {
/*
* Panic CPU will enter this func only via soft-reset.
* Wait until all secondary CPUs entered and
* then start kexec boot.
*/
crash_soft_reset_check(cpu);
cpu_set(crashing_cpu, cpus_in_crash);
if (ppc_md.kexec_cpu_down)
ppc_md.kexec_cpu_down(1, 0);
machine_kexec(kexec_crash_image);
/* NOTREACHED */
}
crash_ipi_callback(regs);
}
#else
static void crash_kexec_prepare_cpus(void)
static void crash_kexec_prepare_cpus(int cpu)
{
/*
* move the secondarys to us so that we can copy
@@ -171,6 +258,10 @@ static void crash_kexec_prepare_cpus(void)
smp_release_cpus();
}
void crash_kexec_secondary(struct pt_regs *regs)
{
cpus_in_sr = CPU_MASK_NONE;
}
#endif
void default_machine_crash_shutdown(struct pt_regs *regs)
@@ -199,14 +290,14 @@ void default_machine_crash_shutdown(struct pt_regs *regs)
desc->chip->disable(irq);
}
if (ppc_md.kexec_cpu_down)
ppc_md.kexec_cpu_down(1, 0);
/*
* Make a note of crashing cpu. Will be used in machine_kexec
* such that another IPI will not be sent.
*/
crashing_cpu = smp_processor_id();
crash_kexec_prepare_cpus();
crash_save_this_cpu(regs, crashing_cpu);
crash_kexec_prepare_cpus(crashing_cpu);
cpu_set(crashing_cpu, cpus_in_crash);
if (ppc_md.kexec_cpu_down)
ppc_md.kexec_cpu_down(1, 0);
}

View File

@@ -85,34 +85,6 @@ END_FTR_SECTION(0, 1)
/* Catch branch to 0 in real mode */
trap
#ifdef CONFIG_PPC_ISERIES
/*
* At offset 0x20, there is a pointer to iSeries LPAR data.
* This is required by the hypervisor
*/
. = 0x20
.llong hvReleaseData-KERNELBASE
/*
* At offset 0x28 and 0x30 are offsets to the mschunks_map
* array (used by the iSeries LPAR debugger to do translation
* between physical addresses and absolute addresses) and
* to the pidhash table (also used by the debugger)
*/
.llong mschunks_map-KERNELBASE
.llong 0 /* pidhash-KERNELBASE SFRXXX */
/* Offset 0x38 - Pointer to start of embedded System.map */
.globl embedded_sysmap_start
embedded_sysmap_start:
.llong 0
/* Offset 0x40 - Pointer to end of embedded System.map */
.globl embedded_sysmap_end
embedded_sysmap_end:
.llong 0
#endif /* CONFIG_PPC_ISERIES */
/* Secondary processors spin on this value until it goes to 1. */
.globl __secondary_hold_spinloop
__secondary_hold_spinloop:
@@ -124,6 +96,15 @@ __secondary_hold_spinloop:
__secondary_hold_acknowledge:
.llong 0x0
#ifdef CONFIG_PPC_ISERIES
/*
* At offset 0x20, there is a pointer to iSeries LPAR data.
* This is required by the hypervisor
*/
. = 0x20
.llong hvReleaseData-KERNELBASE
#endif /* CONFIG_PPC_ISERIES */
. = 0x60
/*
* The following code is used on pSeries to hold secondary processors
@@ -1602,9 +1583,6 @@ _GLOBAL(__start_initialization_multiplatform)
/* Setup some critical 970 SPRs before switching MMU off */
bl .__970_cpu_preinit
/* cpu # */
li r24,0
/* Switch off MMU if not already */
LOAD_REG_IMMEDIATE(r4, .__after_prom_start - KERNELBASE)
add r4,r4,r30
@@ -1683,6 +1661,9 @@ _STATIC(__after_prom_start)
/* i.e. where we are running */
/* the source addr */
cmpdi r4,0 /* In some cases the loader may */
beq .start_here_multiplatform /* have already put us at zero */
/* so we can skip the copy. */
LOAD_REG_IMMEDIATE(r5,copy_to_here) /* # bytes of memory to copy */
sub r5,r5,r27
@@ -1962,14 +1943,6 @@ _STATIC(start_here_common)
li r3,0
bl .do_cpu_ftr_fixups
LOAD_REG_IMMEDIATE(r26, boot_cpuid)
lwz r26,0(r26)
LOAD_REG_IMMEDIATE(r24, paca) /* Get base vaddr of paca array */
mulli r13,r26,PACA_SIZE /* Calculate vaddr of right paca */
add r13,r13,r24 /* for this processor. */
mtspr SPRN_SPRG3,r13
/* ptr to current */
LOAD_REG_IMMEDIATE(r4, init_task)
std r4,PACACURRENT(r13)
@@ -1995,17 +1968,6 @@ _STATIC(start_here_common)
/* Not reached */
BUG_OPCODE
/* Put the paca pointer into r13 and SPRG3 */
_GLOBAL(setup_boot_paca)
LOAD_REG_IMMEDIATE(r3, boot_cpuid)
lwz r3,0(r3)
LOAD_REG_IMMEDIATE(r4, paca) /* Get base vaddr of paca array */
mulli r3,r3,PACA_SIZE /* Calculate vaddr of right paca */
add r13,r3,r4 /* for this processor. */
mtspr SPRN_SPRG3,r13
blr
/*
* We put a few things here that have to be page-aligned.
* This stuff goes at the beginning of the bss, which is page-aligned.

View File

@@ -38,6 +38,7 @@
#include <asm/iommu.h>
#include <asm/pci-bridge.h>
#include <asm/machdep.h>
#include <asm/kdump.h>
#define DBG(...)
@@ -440,8 +441,37 @@ struct iommu_table *iommu_init_table(struct iommu_table *tbl, int nid)
tbl->it_largehint = tbl->it_halfpoint;
spin_lock_init(&tbl->it_lock);
#ifdef CONFIG_CRASH_DUMP
if (ppc_md.tce_get) {
unsigned long index, tceval;
unsigned long tcecount = 0;
/*
* Reserve the existing mappings left by the first kernel.
*/
for (index = 0; index < tbl->it_size; index++) {
tceval = ppc_md.tce_get(tbl, index + tbl->it_offset);
/*
* Freed TCE entry contains 0x7fffffffffffffff on JS20
*/
if (tceval && (tceval != 0x7fffffffffffffffUL)) {
__set_bit(index, tbl->it_map);
tcecount++;
}
}
if ((tbl->it_size - tcecount) < KDUMP_MIN_TCE_ENTRIES) {
printk(KERN_WARNING "TCE table is full; ");
printk(KERN_WARNING "freeing %d entries for the kdump boot\n",
KDUMP_MIN_TCE_ENTRIES);
for (index = tbl->it_size - KDUMP_MIN_TCE_ENTRIES;
index < tbl->it_size; index++)
__clear_bit(index, tbl->it_map);
}
}
#else
/* Clear the hardware table in case firmware left allocations in it */
ppc_md.tce_free(tbl, tbl->it_offset, tbl->it_size);
#endif
if (!welcomed) {
printk(KERN_INFO "IOMMU table initialized, virtual merging %s\n",

View File

@@ -302,6 +302,17 @@ void __init find_legacy_serial_ports(void)
of_node_put(isa);
}
/* First fill our array with tsi-bridge ports */
for (np = NULL; (np = of_find_compatible_node(np, "serial", "ns16550")) != NULL;) {
struct device_node *tsi = of_get_parent(np);
if (tsi && !strcmp(tsi->type, "tsi-bridge")) {
index = add_legacy_soc_port(np, np);
if (index >= 0 && np == stdout)
legacy_serial_console = index;
}
of_node_put(tsi);
}
#ifdef CONFIG_PCI
/* Next, try to locate PCI ports */
for (np = NULL; (np = of_find_all_nodes(np));) {

View File

@@ -45,11 +45,9 @@
static struct proc_dir_entry *proc_ppc64_lparcfg;
#define LPARCFG_BUFF_SIZE 4096
#ifdef CONFIG_PPC_ISERIES
/*
* For iSeries legacy systems, the PPA purr function is available from the
* emulated_time_base field in the paca.
* Track sum of all purrs across all processors. This is used to further
* calculate usage values by different applications
*/
static unsigned long get_purr(void)
{
@@ -57,48 +55,31 @@ static unsigned long get_purr(void)
int cpu;
for_each_possible_cpu(cpu) {
sum_purr += lppaca[cpu].emulated_time_base;
if (firmware_has_feature(FW_FEATURE_ISERIES))
sum_purr += lppaca[cpu].emulated_time_base;
else {
struct cpu_usage *cu;
#ifdef PURR_DEBUG
printk(KERN_INFO "get_purr for cpu (%d) has value (%ld) \n",
cpu, lppaca[cpu].emulated_time_base);
#endif
cu = &per_cpu(cpu_usage_array, cpu);
sum_purr += cu->current_tb;
}
}
return sum_purr;
}
#define lparcfg_write NULL
#ifdef CONFIG_PPC_ISERIES
/*
* Methods used to fetch LPAR data when running on an iSeries platform.
*/
static int lparcfg_data(struct seq_file *m, void *v)
static int iseries_lparcfg_data(struct seq_file *m, void *v)
{
unsigned long pool_id, lp_index;
unsigned long pool_id;
int shared, entitled_capacity, max_entitled_capacity;
int processors, max_processors;
unsigned long purr = get_purr();
seq_printf(m, "%s %s \n", MODULE_NAME, MODULE_VERS);
shared = (int)(get_lppaca()->shared_proc);
seq_printf(m, "serial_number=%c%c%c%c%c%c%c\n",
e2a(xItExtVpdPanel.mfgID[2]),
e2a(xItExtVpdPanel.mfgID[3]),
e2a(xItExtVpdPanel.systemSerial[1]),
e2a(xItExtVpdPanel.systemSerial[2]),
e2a(xItExtVpdPanel.systemSerial[3]),
e2a(xItExtVpdPanel.systemSerial[4]),
e2a(xItExtVpdPanel.systemSerial[5]));
seq_printf(m, "system_type=%c%c%c%c\n",
e2a(xItExtVpdPanel.machineType[0]),
e2a(xItExtVpdPanel.machineType[1]),
e2a(xItExtVpdPanel.machineType[2]),
e2a(xItExtVpdPanel.machineType[3]));
lp_index = HvLpConfig_getLpIndex();
seq_printf(m, "partition_id=%d\n", (int)lp_index);
seq_printf(m, "system_active_processors=%d\n",
(int)HvLpConfig_getSystemPhysicalProcessors());
@@ -137,6 +118,14 @@ static int lparcfg_data(struct seq_file *m, void *v)
return 0;
}
#else /* CONFIG_PPC_ISERIES */
static int iseries_lparcfg_data(struct seq_file *m, void *v)
{
return 0;
}
#endif /* CONFIG_PPC_ISERIES */
#ifdef CONFIG_PPC_PSERIES
@@ -213,22 +202,6 @@ static void h_pic(unsigned long *pool_idle_time, unsigned long *num_procs)
log_plpar_hcall_return(rc, "H_PIC");
}
/* Track sum of all purrs across all processors. This is used to further */
/* calculate usage values by different applications */
static unsigned long get_purr(void)
{
unsigned long sum_purr = 0;
int cpu;
struct cpu_usage *cu;
for_each_possible_cpu(cpu) {
cu = &per_cpu(cpu_usage_array, cpu);
sum_purr += cu->current_tb;
}
return sum_purr;
}
#define SPLPAR_CHARACTERISTICS_TOKEN 20
#define SPLPAR_MAXLENGTH 1026*(sizeof(char))
@@ -333,35 +306,13 @@ static int lparcfg_count_active_processors(void)
return count;
}
static int lparcfg_data(struct seq_file *m, void *v)
static int pseries_lparcfg_data(struct seq_file *m, void *v)
{
int partition_potential_processors;
int partition_active_processors;
struct device_node *rootdn;
const char *model = "";
const char *system_id = "";
unsigned int *lp_index_ptr, lp_index = 0;
struct device_node *rtas_node;
int *lrdrp = NULL;
rootdn = find_path_device("/");
if (rootdn) {
model = get_property(rootdn, "model", NULL);
system_id = get_property(rootdn, "system-id", NULL);
lp_index_ptr = (unsigned int *)
get_property(rootdn, "ibm,partition-no", NULL);
if (lp_index_ptr)
lp_index = *lp_index_ptr;
}
seq_printf(m, "%s %s \n", MODULE_NAME, MODULE_VERS);
seq_printf(m, "serial_number=%s\n", system_id);
seq_printf(m, "system_type=%s\n", model);
seq_printf(m, "partition_id=%d\n", (int)lp_index);
rtas_node = find_path_device("/rtas");
if (rtas_node)
lrdrp = (int *)get_property(rtas_node, "ibm,lrdr-capacity",
@@ -549,8 +500,61 @@ out:
return retval;
}
#else /* CONFIG_PPC_PSERIES */
static int pseries_lparcfg_data(struct seq_file *m, void *v)
{
return 0;
}
static ssize_t lparcfg_write(struct file *file, const char __user * buf,
size_t count, loff_t * off)
{
return count;
}
#endif /* CONFIG_PPC_PSERIES */
static int lparcfg_data(struct seq_file *m, void *v)
{
struct device_node *rootdn;
const char *model = "";
const char *system_id = "";
const char *tmp;
unsigned int *lp_index_ptr, lp_index = 0;
seq_printf(m, "%s %s \n", MODULE_NAME, MODULE_VERS);
rootdn = find_path_device("/");
if (rootdn) {
tmp = get_property(rootdn, "model", NULL);
if (tmp) {
model = tmp;
/* Skip "IBM," - see platforms/iseries/dt.c */
if (firmware_has_feature(FW_FEATURE_ISERIES))
model += 4;
}
tmp = get_property(rootdn, "system-id", NULL);
if (tmp) {
system_id = tmp;
/* Skip "IBM," - see platforms/iseries/dt.c */
if (firmware_has_feature(FW_FEATURE_ISERIES))
system_id += 4;
}
lp_index_ptr = (unsigned int *)
get_property(rootdn, "ibm,partition-no", NULL);
if (lp_index_ptr)
lp_index = *lp_index_ptr;
}
seq_printf(m, "serial_number=%s\n", system_id);
seq_printf(m, "system_type=%s\n", model);
seq_printf(m, "partition_id=%d\n", (int)lp_index);
if (firmware_has_feature(FW_FEATURE_ISERIES))
return iseries_lparcfg_data(m, v);
return pseries_lparcfg_data(m, v);
}
static int lparcfg_open(struct inode *inode, struct file *file)
{
return single_open(file, lparcfg_data, NULL);
@@ -569,7 +573,8 @@ int __init lparcfg_init(void)
mode_t mode = S_IRUSR | S_IRGRP | S_IROTH;
/* Allow writing if we have FW_FEATURE_SPLPAR */
if (firmware_has_feature(FW_FEATURE_SPLPAR)) {
if (firmware_has_feature(FW_FEATURE_SPLPAR) &&
!firmware_has_feature(FW_FEATURE_ISERIES)) {
lparcfg_fops.write = lparcfg_write;
mode |= S_IWUSR;
}

View File

@@ -378,11 +378,13 @@ static void __init export_crashk_values(void)
of_node_put(node);
}
void __init kexec_setup(void)
static int __init kexec_setup(void)
{
export_htab_values();
export_crashk_values();
return 0;
}
__initcall(kexec_setup);
static int __init early_parse_crashk(char *p)
{

203
arch/powerpc/kernel/misc.S Normal file
View File

@@ -0,0 +1,203 @@
/*
* This file contains miscellaneous low-level functions.
* Copyright (C) 1995-1996 Gary Thomas (gdt@linuxppc.org)
*
* Largely rewritten by Cort Dougan (cort@cs.nmt.edu)
* and Paul Mackerras.
*
* Adapted for iSeries by Mike Corrigan (mikejc@us.ibm.com)
* PPC64 updates by Dave Engebretsen (engebret@us.ibm.com)
*
* 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.
*/
#include <asm/ppc_asm.h>
.text
#ifdef CONFIG_PPC64
#define IN_SYNC twi 0,r5,0; isync
#define EIEIO_32
#define SYNC_64 sync
#else /* CONFIG_PPC32 */
#define IN_SYNC
#define EIEIO_32 eieio
#define SYNC_64
#endif
/*
* Returns (address we are running at) - (address we were linked at)
* for use before the text and data are mapped to KERNELBASE.
*/
_GLOBAL(reloc_offset)
mflr r0
bl 1f
1: mflr r3
LOAD_REG_IMMEDIATE(r4,1b)
subf r3,r4,r3
mtlr r0
blr
/*
* add_reloc_offset(x) returns x + reloc_offset().
*/
_GLOBAL(add_reloc_offset)
mflr r0
bl 1f
1: mflr r5
LOAD_REG_IMMEDIATE(r4,1b)
subf r5,r4,r5
add r3,r3,r5
mtlr r0
blr
/*
* I/O string operations
*
* insb(port, buf, len)
* outsb(port, buf, len)
* insw(port, buf, len)
* outsw(port, buf, len)
* insl(port, buf, len)
* outsl(port, buf, len)
* insw_ns(port, buf, len)
* outsw_ns(port, buf, len)
* insl_ns(port, buf, len)
* outsl_ns(port, buf, len)
*
* The *_ns versions don't do byte-swapping.
*/
_GLOBAL(_insb)
cmpwi 0,r5,0
mtctr r5
subi r4,r4,1
blelr-
00: lbz r5,0(r3)
eieio
stbu r5,1(r4)
bdnz 00b
IN_SYNC
blr
_GLOBAL(_outsb)
cmpwi 0,r5,0
mtctr r5
subi r4,r4,1
blelr-
00: lbzu r5,1(r4)
stb r5,0(r3)
EIEIO_32
bdnz 00b
SYNC_64
blr
_GLOBAL(_insw)
cmpwi 0,r5,0
mtctr r5
subi r4,r4,2
blelr-
00: lhbrx r5,0,r3
eieio
sthu r5,2(r4)
bdnz 00b
IN_SYNC
blr
_GLOBAL(_outsw)
cmpwi 0,r5,0
mtctr r5
subi r4,r4,2
blelr-
00: lhzu r5,2(r4)
EIEIO_32
sthbrx r5,0,r3
bdnz 00b
SYNC_64
blr
_GLOBAL(_insl)
cmpwi 0,r5,0
mtctr r5
subi r4,r4,4
blelr-
00: lwbrx r5,0,r3
eieio
stwu r5,4(r4)
bdnz 00b
IN_SYNC
blr
_GLOBAL(_outsl)
cmpwi 0,r5,0
mtctr r5
subi r4,r4,4
blelr-
00: lwzu r5,4(r4)
stwbrx r5,0,r3
EIEIO_32
bdnz 00b
SYNC_64
blr
#ifdef CONFIG_PPC32
_GLOBAL(__ide_mm_insw)
#endif
_GLOBAL(_insw_ns)
cmpwi 0,r5,0
mtctr r5
subi r4,r4,2
blelr-
00: lhz r5,0(r3)
eieio
sthu r5,2(r4)
bdnz 00b
IN_SYNC
blr
#ifdef CONFIG_PPC32
_GLOBAL(__ide_mm_outsw)
#endif
_GLOBAL(_outsw_ns)
cmpwi 0,r5,0
mtctr r5
subi r4,r4,2
blelr-
00: lhzu r5,2(r4)
sth r5,0(r3)
EIEIO_32
bdnz 00b
SYNC_64
blr
#ifdef CONFIG_PPC32
_GLOBAL(__ide_mm_insl)
#endif
_GLOBAL(_insl_ns)
cmpwi 0,r5,0
mtctr r5
subi r4,r4,4
blelr-
00: lwz r5,0(r3)
eieio
stwu r5,4(r4)
bdnz 00b
IN_SYNC
blr
#ifdef CONFIG_PPC32
_GLOBAL(__ide_mm_outsl)
#endif
_GLOBAL(_outsl_ns)
cmpwi 0,r5,0
mtctr r5
subi r4,r4,4
blelr-
00: lwzu r5,4(r4)
stw r5,0(r3)
EIEIO_32
bdnz 00b
SYNC_64
blr

View File

@@ -60,32 +60,6 @@ _GLOBAL(mulhdu)
addze r3,r3
blr
/*
* Returns (address we're running at) - (address we were linked at)
* for use before the text and data are mapped to KERNELBASE.
*/
_GLOBAL(reloc_offset)
mflr r0
bl 1f
1: mflr r3
LOAD_REG_IMMEDIATE(r4,1b)
subf r3,r4,r3
mtlr r0
blr
/*
* add_reloc_offset(x) returns x + reloc_offset().
*/
_GLOBAL(add_reloc_offset)
mflr r0
bl 1f
1: mflr r5
LOAD_REG_IMMEDIATE(r4,1b)
subf r5,r4,r5
add r3,r3,r5
mtlr r0
blr
/*
* sub_reloc_offset(x) returns x - reloc_offset().
*/
@@ -780,136 +754,6 @@ _GLOBAL(atomic_set_mask)
bne- 10b
blr
/*
* I/O string operations
*
* insb(port, buf, len)
* outsb(port, buf, len)
* insw(port, buf, len)
* outsw(port, buf, len)
* insl(port, buf, len)
* outsl(port, buf, len)
* insw_ns(port, buf, len)
* outsw_ns(port, buf, len)
* insl_ns(port, buf, len)
* outsl_ns(port, buf, len)
*
* The *_ns versions don't do byte-swapping.
*/
_GLOBAL(_insb)
cmpwi 0,r5,0
mtctr r5
subi r4,r4,1
blelr-
00: lbz r5,0(r3)
eieio
stbu r5,1(r4)
bdnz 00b
blr
_GLOBAL(_outsb)
cmpwi 0,r5,0
mtctr r5
subi r4,r4,1
blelr-
00: lbzu r5,1(r4)
stb r5,0(r3)
eieio
bdnz 00b
blr
_GLOBAL(_insw)
cmpwi 0,r5,0
mtctr r5
subi r4,r4,2
blelr-
00: lhbrx r5,0,r3
eieio
sthu r5,2(r4)
bdnz 00b
blr
_GLOBAL(_outsw)
cmpwi 0,r5,0
mtctr r5
subi r4,r4,2
blelr-
00: lhzu r5,2(r4)
eieio
sthbrx r5,0,r3
bdnz 00b
blr
_GLOBAL(_insl)
cmpwi 0,r5,0
mtctr r5
subi r4,r4,4
blelr-
00: lwbrx r5,0,r3
eieio
stwu r5,4(r4)
bdnz 00b
blr
_GLOBAL(_outsl)
cmpwi 0,r5,0
mtctr r5
subi r4,r4,4
blelr-
00: lwzu r5,4(r4)
stwbrx r5,0,r3
eieio
bdnz 00b
blr
_GLOBAL(__ide_mm_insw)
_GLOBAL(_insw_ns)
cmpwi 0,r5,0
mtctr r5
subi r4,r4,2
blelr-
00: lhz r5,0(r3)
eieio
sthu r5,2(r4)
bdnz 00b
blr
_GLOBAL(__ide_mm_outsw)
_GLOBAL(_outsw_ns)
cmpwi 0,r5,0
mtctr r5
subi r4,r4,2
blelr-
00: lhzu r5,2(r4)
sth r5,0(r3)
eieio
bdnz 00b
blr
_GLOBAL(__ide_mm_insl)
_GLOBAL(_insl_ns)
cmpwi 0,r5,0
mtctr r5
subi r4,r4,4
blelr-
00: lwz r5,0(r3)
eieio
stwu r5,4(r4)
bdnz 00b
blr
_GLOBAL(__ide_mm_outsl)
_GLOBAL(_outsl_ns)
cmpwi 0,r5,0
mtctr r5
subi r4,r4,4
blelr-
00: lwzu r5,4(r4)
stw r5,0(r3)
eieio
bdnz 00b
blr
/*
* Extended precision shifts.
*

View File

@@ -1,14 +1,12 @@
/*
* arch/powerpc/kernel/misc64.S
*
* This file contains miscellaneous low-level functions.
* Copyright (C) 1995-1996 Gary Thomas (gdt@linuxppc.org)
*
* Largely rewritten by Cort Dougan (cort@cs.nmt.edu)
* and Paul Mackerras.
* Adapted for iSeries by Mike Corrigan (mikejc@us.ibm.com)
* PPC64 updates by Dave Engebretsen (engebret@us.ibm.com)
*
* PPC64 updates by Dave Engebretsen (engebret@us.ibm.com)
*
* 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
@@ -30,41 +28,10 @@
.text
/*
* Returns (address we are running at) - (address we were linked at)
* for use before the text and data are mapped to KERNELBASE.
*/
_GLOBAL(reloc_offset)
mflr r0
bl 1f
1: mflr r3
LOAD_REG_IMMEDIATE(r4,1b)
subf r3,r4,r3
mtlr r0
blr
/*
* add_reloc_offset(x) returns x + reloc_offset().
*/
_GLOBAL(add_reloc_offset)
mflr r0
bl 1f
1: mflr r5
LOAD_REG_IMMEDIATE(r4,1b)
subf r5,r4,r5
add r3,r3,r5
mtlr r0
blr
_GLOBAL(get_msr)
mfmsr r3
blr
_GLOBAL(get_dar)
mfdar r3
blr
_GLOBAL(get_srr0)
mfsrr0 r3
blr
@@ -72,10 +39,6 @@ _GLOBAL(get_srr0)
_GLOBAL(get_srr1)
mfsrr1 r3
blr
_GLOBAL(get_sp)
mr r3,r1
blr
#ifdef CONFIG_IRQSTACKS
_GLOBAL(call_do_softirq)
@@ -101,48 +64,6 @@ _GLOBAL(call___do_IRQ)
blr
#endif /* CONFIG_IRQSTACKS */
/*
* To be called by C code which needs to do some operations with MMU
* disabled. Note that interrupts have to be disabled by the caller
* prior to calling us. The code called _MUST_ be in the RMO of course
* and part of the linear mapping as we don't attempt to translate the
* stack pointer at all. The function is called with the stack switched
* to this CPU emergency stack
*
* prototype is void *call_with_mmu_off(void *func, void *data);
*
* the called function is expected to be of the form
*
* void *called(void *data);
*/
_GLOBAL(call_with_mmu_off)
mflr r0 /* get link, save it on stackframe */
std r0,16(r1)
mr r1,r5 /* save old stack ptr */
ld r1,PACAEMERGSP(r13) /* get emerg. stack */
subi r1,r1,STACK_FRAME_OVERHEAD
std r0,16(r1) /* save link on emerg. stack */
std r5,0(r1) /* save old stack ptr in backchain */
ld r3,0(r3) /* get to real function ptr (assume same TOC) */
bl 2f /* we need LR to return, continue at label 2 */
ld r0,16(r1) /* we return here from the call, get LR and */
ld r1,0(r1) /* .. old stack ptr */
mtspr SPRN_SRR0,r0 /* and get back to virtual mode with these */
mfmsr r4
ori r4,r4,MSR_IR|MSR_DR
mtspr SPRN_SRR1,r4
rfid
2: mtspr SPRN_SRR0,r3 /* coming from above, enter real mode */
mr r3,r4 /* get parameter */
mfmsr r0
ori r0,r0,MSR_IR|MSR_DR
xori r0,r0,MSR_IR|MSR_DR
mtspr SPRN_SRR1,r0
rfid
.section ".toc","aw"
PPC64_CACHES:
.tc ppc64_caches[TC],ppc64_caches
@@ -323,144 +244,6 @@ _GLOBAL(__flush_dcache_icache)
bdnz 1b
isync
blr
/*
* I/O string operations
*
* insb(port, buf, len)
* outsb(port, buf, len)
* insw(port, buf, len)
* outsw(port, buf, len)
* insl(port, buf, len)
* outsl(port, buf, len)
* insw_ns(port, buf, len)
* outsw_ns(port, buf, len)
* insl_ns(port, buf, len)
* outsl_ns(port, buf, len)
*
* The *_ns versions don't do byte-swapping.
*/
_GLOBAL(_insb)
cmpwi 0,r5,0
mtctr r5
subi r4,r4,1
blelr-
00: lbz r5,0(r3)
eieio
stbu r5,1(r4)
bdnz 00b
twi 0,r5,0
isync
blr
_GLOBAL(_outsb)
cmpwi 0,r5,0
mtctr r5
subi r4,r4,1
blelr-
00: lbzu r5,1(r4)
stb r5,0(r3)
bdnz 00b
sync
blr
_GLOBAL(_insw)
cmpwi 0,r5,0
mtctr r5
subi r4,r4,2
blelr-
00: lhbrx r5,0,r3
eieio
sthu r5,2(r4)
bdnz 00b
twi 0,r5,0
isync
blr
_GLOBAL(_outsw)
cmpwi 0,r5,0
mtctr r5
subi r4,r4,2
blelr-
00: lhzu r5,2(r4)
sthbrx r5,0,r3
bdnz 00b
sync
blr
_GLOBAL(_insl)
cmpwi 0,r5,0
mtctr r5
subi r4,r4,4
blelr-
00: lwbrx r5,0,r3
eieio
stwu r5,4(r4)
bdnz 00b
twi 0,r5,0
isync
blr
_GLOBAL(_outsl)
cmpwi 0,r5,0
mtctr r5
subi r4,r4,4
blelr-
00: lwzu r5,4(r4)
stwbrx r5,0,r3
bdnz 00b
sync
blr
/* _GLOBAL(ide_insw) now in drivers/ide/ide-iops.c */
_GLOBAL(_insw_ns)
cmpwi 0,r5,0
mtctr r5
subi r4,r4,2
blelr-
00: lhz r5,0(r3)
eieio
sthu r5,2(r4)
bdnz 00b
twi 0,r5,0
isync
blr
/* _GLOBAL(ide_outsw) now in drivers/ide/ide-iops.c */
_GLOBAL(_outsw_ns)
cmpwi 0,r5,0
mtctr r5
subi r4,r4,2
blelr-
00: lhzu r5,2(r4)
sth r5,0(r3)
bdnz 00b
sync
blr
_GLOBAL(_insl_ns)
cmpwi 0,r5,0
mtctr r5
subi r4,r4,4
blelr-
00: lwz r5,0(r3)
eieio
stwu r5,4(r4)
bdnz 00b
twi 0,r5,0
isync
blr
_GLOBAL(_outsl_ns)
cmpwi 0,r5,0
mtctr r5
subi r4,r4,4
blelr-
00: lwzu r5,4(r4)
stw r5,0(r3)
bdnz 00b
sync
blr
/*
* identify_cpu and calls setup_cpu
@@ -605,6 +388,7 @@ _GLOBAL(real_writeb)
blr
#endif /* defined(CONFIG_PPC_PMAC) || defined(CONFIG_PPC_MAPLE) */
#ifdef CONFIG_CPU_FREQ_PMAC64
/*
* SCOM access functions for 970 (FX only for now)
*
@@ -673,6 +457,7 @@ _GLOBAL(scom970_write)
/* restore interrupts */
mtmsrd r5,1
blr
#endif /* CONFIG_CPU_FREQ_PMAC64 */
/*

View File

@@ -16,7 +16,6 @@
#include <asm/ptrace.h>
#include <asm/page.h>
#include <asm/lppaca.h>
#include <asm/iseries/it_lp_queue.h>
#include <asm/iseries/it_lp_reg_save.h>
#include <asm/paca.h>

View File

@@ -30,6 +30,7 @@
#include <linux/bitops.h>
#include <linux/module.h>
#include <linux/kexec.h>
#include <linux/debugfs.h>
#include <asm/prom.h>
#include <asm/rtas.h>
@@ -952,6 +953,7 @@ static struct ibm_pa_feature {
/* put this back once we know how to test if firmware does 64k IO */
{CPU_FTR_CI_LARGE_PAGE, 0, 1, 2, 0},
#endif
{CPU_FTR_REAL_LE, PPC_FEATURE_TRUE_LE, 5, 0, 0},
};
static void __init check_cpu_pa_features(unsigned long node)
@@ -1124,24 +1126,6 @@ static int __init early_init_dt_scan_chosen(unsigned long node,
tce_alloc_end = *lprop;
#endif
#ifdef CONFIG_PPC_RTAS
/* To help early debugging via the front panel, we retrieve a minimal
* set of RTAS infos now if available
*/
{
u64 *basep, *entryp, *sizep;
basep = of_get_flat_dt_prop(node, "linux,rtas-base", NULL);
entryp = of_get_flat_dt_prop(node, "linux,rtas-entry", NULL);
sizep = of_get_flat_dt_prop(node, "linux,rtas-size", NULL);
if (basep && entryp && sizep) {
rtas.base = *basep;
rtas.entry = *entryp;
rtas.size = *sizep;
}
}
#endif /* CONFIG_PPC_RTAS */
#ifdef CONFIG_KEXEC
lprop = (u64*)of_get_flat_dt_prop(node, "linux,crashkernel-base", NULL);
if (lprop)
@@ -1326,6 +1310,11 @@ void __init early_init_devtree(void *params)
/* Setup flat device-tree pointer */
initial_boot_params = params;
#ifdef CONFIG_PPC_RTAS
/* Some machines might need RTAS info for debugging, grab it now. */
of_scan_flat_dt(early_init_dt_scan_rtas, NULL);
#endif
/* Retrieve various informations from the /chosen node of the
* device-tree, including the platform type, initrd location and
* size, TCE reserve, and more ...
@@ -2148,3 +2137,27 @@ struct device_node *of_get_cpu_node(int cpu, unsigned int *thread)
}
return NULL;
}
#ifdef DEBUG
static struct debugfs_blob_wrapper flat_dt_blob;
static int __init export_flat_device_tree(void)
{
struct dentry *d;
d = debugfs_create_dir("powerpc", NULL);
if (!d)
return 1;
flat_dt_blob.data = initial_boot_params;
flat_dt_blob.size = initial_boot_params->totalsize;
d = debugfs_create_blob("flat-device-tree", S_IFREG | S_IRUSR,
d, &flat_dt_blob);
if (!d)
return 1;
return 0;
}
__initcall(export_flat_device_tree);
#endif

View File

@@ -38,16 +38,19 @@
struct rtas_t rtas = {
.lock = SPIN_LOCK_UNLOCKED
};
EXPORT_SYMBOL(rtas);
struct rtas_suspend_me_data {
long waiting;
struct rtas_args *args;
};
EXPORT_SYMBOL(rtas);
DEFINE_SPINLOCK(rtas_data_buf_lock);
EXPORT_SYMBOL(rtas_data_buf_lock);
char rtas_data_buf[RTAS_DATA_BUF_SIZE] __cacheline_aligned;
EXPORT_SYMBOL(rtas_data_buf);
unsigned long rtas_rmo_buf;
/*
@@ -106,11 +109,71 @@ static void call_rtas_display_status_delay(char c)
}
}
void __init udbg_init_rtas(void)
void __init udbg_init_rtas_panel(void)
{
udbg_putc = call_rtas_display_status_delay;
}
#ifdef CONFIG_UDBG_RTAS_CONSOLE
/* If you think you're dying before early_init_dt_scan_rtas() does its
* work, you can hard code the token values for your firmware here and
* hardcode rtas.base/entry etc.
*/
static unsigned int rtas_putchar_token = RTAS_UNKNOWN_SERVICE;
static unsigned int rtas_getchar_token = RTAS_UNKNOWN_SERVICE;
static void udbg_rtascon_putc(char c)
{
int tries;
if (!rtas.base)
return;
/* Add CRs before LFs */
if (c == '\n')
udbg_rtascon_putc('\r');
/* if there is more than one character to be displayed, wait a bit */
for (tries = 0; tries < 16; tries++) {
if (rtas_call(rtas_putchar_token, 1, 1, NULL, c) == 0)
break;
udelay(1000);
}
}
static int udbg_rtascon_getc_poll(void)
{
int c;
if (!rtas.base)
return -1;
if (rtas_call(rtas_getchar_token, 0, 2, &c))
return -1;
return c;
}
static int udbg_rtascon_getc(void)
{
int c;
while ((c = udbg_rtascon_getc_poll()) == -1)
;
return c;
}
void __init udbg_init_rtas_console(void)
{
udbg_putc = udbg_rtascon_putc;
udbg_getc = udbg_rtascon_getc;
udbg_getc_poll = udbg_rtascon_getc_poll;
}
#endif /* CONFIG_UDBG_RTAS_CONSOLE */
void rtas_progress(char *s, unsigned short hex)
{
struct device_node *root;
@@ -236,6 +299,7 @@ int rtas_token(const char *service)
tokp = (int *) get_property(rtas.dev, service, NULL);
return tokp ? *tokp : RTAS_UNKNOWN_SERVICE;
}
EXPORT_SYMBOL(rtas_token);
#ifdef CONFIG_RTAS_ERROR_LOGGING
/*
@@ -328,7 +392,7 @@ int rtas_call(int token, int nargs, int nret, int *outputs, ...)
char *buff_copy = NULL;
int ret;
if (token == RTAS_UNKNOWN_SERVICE)
if (!rtas.entry || token == RTAS_UNKNOWN_SERVICE)
return -1;
/* Gotta do something different here, use global lock for now... */
@@ -369,6 +433,7 @@ int rtas_call(int token, int nargs, int nret, int *outputs, ...)
}
return ret;
}
EXPORT_SYMBOL(rtas_call);
/* For RTAS_BUSY (-2), delay for 1 millisecond. For an extended busy status
* code of 990n, perform the hinted delay of 10^n (last digit) milliseconds.
@@ -388,6 +453,7 @@ unsigned int rtas_busy_delay_time(int status)
return ms;
}
EXPORT_SYMBOL(rtas_busy_delay_time);
/* For an RTAS busy status code, perform the hinted delay. */
unsigned int rtas_busy_delay(int status)
@@ -401,6 +467,7 @@ unsigned int rtas_busy_delay(int status)
return ms;
}
EXPORT_SYMBOL(rtas_busy_delay);
int rtas_error_rc(int rtas_rc)
{
@@ -446,6 +513,7 @@ int rtas_get_power_level(int powerdomain, int *level)
return rtas_error_rc(rc);
return rc;
}
EXPORT_SYMBOL(rtas_get_power_level);
int rtas_set_power_level(int powerdomain, int level, int *setlevel)
{
@@ -463,6 +531,7 @@ int rtas_set_power_level(int powerdomain, int level, int *setlevel)
return rtas_error_rc(rc);
return rc;
}
EXPORT_SYMBOL(rtas_set_power_level);
int rtas_get_sensor(int sensor, int index, int *state)
{
@@ -480,6 +549,7 @@ int rtas_get_sensor(int sensor, int index, int *state)
return rtas_error_rc(rc);
return rc;
}
EXPORT_SYMBOL(rtas_get_sensor);
int rtas_set_indicator(int indicator, int index, int new_value)
{
@@ -497,6 +567,7 @@ int rtas_set_indicator(int indicator, int index, int new_value)
return rtas_error_rc(rc);
return rc;
}
EXPORT_SYMBOL(rtas_set_indicator);
void rtas_restart(char *cmd)
{
@@ -791,14 +862,34 @@ void __init rtas_initialize(void)
#endif
}
int __init early_init_dt_scan_rtas(unsigned long node,
const char *uname, int depth, void *data)
{
u32 *basep, *entryp, *sizep;
EXPORT_SYMBOL(rtas_token);
EXPORT_SYMBOL(rtas_call);
EXPORT_SYMBOL(rtas_data_buf);
EXPORT_SYMBOL(rtas_data_buf_lock);
EXPORT_SYMBOL(rtas_busy_delay_time);
EXPORT_SYMBOL(rtas_busy_delay);
EXPORT_SYMBOL(rtas_get_sensor);
EXPORT_SYMBOL(rtas_get_power_level);
EXPORT_SYMBOL(rtas_set_power_level);
EXPORT_SYMBOL(rtas_set_indicator);
if (depth != 1 || strcmp(uname, "rtas") != 0)
return 0;
basep = of_get_flat_dt_prop(node, "linux,rtas-base", NULL);
entryp = of_get_flat_dt_prop(node, "linux,rtas-entry", NULL);
sizep = of_get_flat_dt_prop(node, "rtas-size", NULL);
if (basep && entryp && sizep) {
rtas.base = *basep;
rtas.entry = *entryp;
rtas.size = *sizep;
}
#ifdef CONFIG_UDBG_RTAS_CONSOLE
basep = of_get_flat_dt_prop(node, "put-term-char", NULL);
if (basep)
rtas_putchar_token = *basep;
basep = of_get_flat_dt_prop(node, "get-term-char", NULL);
if (basep)
rtas_getchar_token = *basep;
#endif
/* break now */
return 1;
}

View File

@@ -149,6 +149,13 @@ early_param("smt-enabled", early_smt_enabled);
#define check_smt_enabled()
#endif /* CONFIG_SMP */
/* Put the paca pointer into r13 and SPRG3 */
void __init setup_paca(int cpu)
{
local_paca = &paca[cpu];
mtspr(SPRN_SPRG3, local_paca);
}
/*
* Early initialization entry point. This is called by head.S
* with MMU translation disabled. We rely on the "feature" of
@@ -170,6 +177,9 @@ early_param("smt-enabled", early_smt_enabled);
void __init early_setup(unsigned long dt_ptr)
{
/* Assume we're on cpu 0 for now. Don't write to the paca yet! */
setup_paca(0);
/* Enable early debugging if any specified (see udbg.h) */
udbg_early_init();
@@ -183,7 +193,7 @@ void __init early_setup(unsigned long dt_ptr)
early_init_devtree(__va(dt_ptr));
/* Now we know the logical id of our boot cpu, setup the paca. */
setup_boot_paca();
setup_paca(boot_cpuid);
/* Fix up paca fields required for the boot cpu */
get_paca()->cpu_start = 1;
@@ -350,19 +360,11 @@ void __init setup_system(void)
*/
unflatten_device_tree();
#ifdef CONFIG_KEXEC
kexec_setup(); /* requires unflattened device tree. */
#endif
/*
* Fill the ppc64_caches & systemcfg structures with informations
* retrieved from the device-tree. Need to be called before
* finish_device_tree() since the later requires some of the
* informations filled up here to properly parse the interrupt
* tree.
* It also sets up the cache line sizes which allows to call
* routines like flush_icache_range (used by the hash init
* later on).
* informations filled up here to properly parse the interrupt tree.
*/
initialize_cache_info();

View File

@@ -52,9 +52,13 @@
#include <asm/firmware.h>
#include <asm/processor.h>
#endif
#include <asm/kexec.h>
#ifdef CONFIG_PPC64 /* XXX */
#define _IO_BASE pci_io_base
#ifdef CONFIG_KEXEC
cpumask_t cpus_in_sr = CPU_MASK_NONE;
#endif
#endif
#ifdef CONFIG_DEBUGGER
@@ -97,7 +101,7 @@ static DEFINE_SPINLOCK(die_lock);
int die(const char *str, struct pt_regs *regs, long err)
{
static int die_counter, crash_dump_start = 0;
static int die_counter;
if (debugger(regs))
return 1;
@@ -137,21 +141,12 @@ int die(const char *str, struct pt_regs *regs, long err)
print_modules();
show_regs(regs);
bust_spinlocks(0);
if (!crash_dump_start && kexec_should_crash(current)) {
crash_dump_start = 1;
spin_unlock_irq(&die_lock);
crash_kexec(regs);
/* NOTREACHED */
}
spin_unlock_irq(&die_lock);
if (crash_dump_start)
/*
* Only for soft-reset: Other CPUs will be responded to an IPI
* sent by first kexec CPU.
*/
for(;;)
;
if (kexec_should_crash(current) ||
kexec_sr_activated(smp_processor_id()))
crash_kexec(regs);
crash_kexec_secondary(regs);
if (in_interrupt())
panic("Fatal exception in interrupt");
@@ -215,6 +210,10 @@ void system_reset_exception(struct pt_regs *regs)
return;
}
#ifdef CONFIG_KEXEC
cpu_set(smp_processor_id(), cpus_in_sr);
#endif
die("System Reset", regs, SIGABRT);
/* Must die if the interrupt is not recoverable */

View File

@@ -34,9 +34,12 @@ void __init udbg_early_init(void)
#elif defined(CONFIG_PPC_EARLY_DEBUG_G5)
/* For use on Apple G5 machines */
udbg_init_pmac_realmode();
#elif defined(CONFIG_PPC_EARLY_DEBUG_RTAS)
#elif defined(CONFIG_PPC_EARLY_DEBUG_RTAS_PANEL)
/* RTAS panel debug */
udbg_init_rtas();
udbg_init_rtas_panel();
#elif defined(CONFIG_PPC_EARLY_DEBUG_RTAS_CONSOLE)
/* RTAS console debug */
udbg_init_rtas_console();
#elif defined(CONFIG_PPC_EARLY_DEBUG_MAPLE)
/* Maple real mode debug */
udbg_init_maple_realmode();