#include <linux/string.h>
#include <linux/sched.h>
#include <linux/init.h>
+#include <linux/kernel.h>
#include <linux/reboot.h>
#include <linux/delay.h>
#include <linux/initrd.h>
#include <asm/elf.h>
#include <asm/machdep.h>
#include <asm/iSeries/LparData.h>
-#include <asm/naca.h>
#include <asm/paca.h>
#include <asm/ppcdebug.h>
#include <asm/time.h>
#include <asm/rtas.h>
#include <asm/iommu.h>
#include <asm/serial.h>
+#include <asm/cache.h>
+#include <asm/page.h>
+#include <asm/mmu.h>
#ifdef DEBUG
#define DBG(fmt...) udbg_printf(fmt)
#endif
/* extern void *stab; */
-extern HTAB htab_data;
extern unsigned long klimit;
extern void mm_init_ppc64(void);
extern void smp_release_cpus(void);
-unsigned long decr_overclock = 1;
-unsigned long decr_overclock_proc0 = 1;
-unsigned long decr_overclock_set = 0;
-unsigned long decr_overclock_proc0_set = 0;
-
int have_of = 1;
int boot_cpuid = 0;
int boot_cpuid_phys = 0;
dev_t boot_dev;
+u64 ppc64_pft_size;
+u64 ppc64_debug_switch;
+
+struct ppc64_caches ppc64_caches;
+EXPORT_SYMBOL_GPL(ppc64_caches);
/*
* These are used in binfmt_elf.c to put aux entries on the stack
/* The main machine-dep calls structure
*/
struct machdep_calls ppc_md;
+EXPORT_SYMBOL(ppc_md);
#ifdef CONFIG_MAGIC_SYSRQ
unsigned long SYSRQ_KEY;
*/
void __init ppcdbg_initialize(void)
{
- naca->debug_switch = PPC_DEBUG_DEFAULT; /* | PPCDBG_BUSWALK | */
+ ppc64_debug_switch = PPC_DEBUG_DEFAULT; /* | PPCDBG_BUSWALK | */
/* PPCDBG_PHBINIT | PPCDBG_MM | PPCDBG_MMINIT | PPCDBG_TCEINIT | PPCDBG_TCE */;
}
nthreads = len / sizeof(u32);
for (j = 0; j < nthreads && cpu < NR_CPUS; j++) {
- /*
- * Only spin up secondary threads if SMT is enabled.
- * We must leave space in the logical map for the
- * threads.
- */
- if (j == 0 || smt_enabled_at_boot) {
- cpu_set(cpu, cpu_present_map);
- set_hard_smp_processor_id(cpu, intserv[j]);
- }
+ cpu_set(cpu, cpu_present_map);
+ set_hard_smp_processor_id(cpu, intserv[j]);
+
if (intserv[j] == boot_cpuid_phys)
swap_cpuid = cpu;
cpu_set(cpu, cpu_possible_map);
maxcpus = ireg[num_addr_cell + num_size_cell];
/* Double maxcpus for processors which have SMT capability */
- if (cur_cpu_spec->cpu_features & CPU_FTR_SMT)
+ if (cpu_has_feature(CPU_FTR_SMT))
maxcpus *= 2;
if (maxcpus > NR_CPUS) {
*/
for_each_cpu(cpu) {
cpu_set(cpu, cpu_sibling_map[cpu]);
- if (cur_cpu_spec->cpu_features & CPU_FTR_SMT)
+ if (cpu_has_feature(CPU_FTR_SMT))
cpu_set(cpu ^ 0x1, cpu_sibling_map[cpu]);
}
DBG(" -> early_setup()\n");
/*
- * Fill the default DBG level in naca (do we want to keep
+ * Fill the default DBG level (do we want to keep
* that old mecanism around forever ?)
*/
ppcdbg_initialize();
/*
- * Initialize some remaining members of the naca and systemcfg structures
+ * Initialize some remaining members of the ppc64_caches and systemcfg structures
* (at least until we get rid of them completely). This is mostly some
* cache informations about the CPU that will be used by cache flush
* routines and/or provided to userland
*/
-static void __init initialize_naca(void)
+static void __init initialize_cache_info(void)
{
struct device_node *np;
unsigned long num_cpus = 0;
- DBG(" -> initialize_naca()\n");
+ DBG(" -> initialize_cache_info()\n");
for (np = NULL; (np = of_find_node_by_type(np, "cpu"));) {
num_cpus += 1;
lsizep = (u32 *) get_property(np, dc, NULL);
if (lsizep != NULL)
lsize = *lsizep;
-
if (sizep == 0 || lsizep == 0)
DBG("Argh, can't find dcache properties ! "
"sizep: %p, lsizep: %p\n", sizep, lsizep);
- systemcfg->dCacheL1Size = size;
- systemcfg->dCacheL1LineSize = lsize;
- naca->dCacheL1LogLineSize = __ilog2(lsize);
- naca->dCacheL1LinesPerPage = PAGE_SIZE/(lsize);
+ systemcfg->dcache_size = ppc64_caches.dsize = size;
+ systemcfg->dcache_line_size =
+ ppc64_caches.dline_size = lsize;
+ ppc64_caches.log_dline_size = __ilog2(lsize);
+ ppc64_caches.dlines_per_page = PAGE_SIZE / lsize;
size = 0;
lsize = cur_cpu_spec->icache_bsize;
DBG("Argh, can't find icache properties ! "
"sizep: %p, lsizep: %p\n", sizep, lsizep);
- systemcfg->iCacheL1Size = size;
- systemcfg->iCacheL1LineSize = lsize;
- naca->iCacheL1LogLineSize = __ilog2(lsize);
- naca->iCacheL1LinesPerPage = PAGE_SIZE/(lsize);
-
+ systemcfg->icache_size = ppc64_caches.isize = size;
+ systemcfg->icache_line_size =
+ ppc64_caches.iline_size = lsize;
+ ppc64_caches.log_iline_size = __ilog2(lsize);
+ ppc64_caches.ilines_per_page = PAGE_SIZE / lsize;
}
}
systemcfg->version.minor = SYSTEMCFG_MINOR;
systemcfg->processor = mfspr(SPRN_PVR);
- DBG(" <- initialize_naca()\n");
+ DBG(" <- initialize_cache_info()\n");
}
static void __init check_for_initrd(void)
unflatten_device_tree();
/*
- * Fill the naca & systemcfg structures with informations
+ * Fill the ppc64_caches & systemcfg structures with informations
* retreived 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
* routines like flush_icache_range (used by the hash init
* later on).
*/
- initialize_naca();
+ initialize_cache_info();
-#ifdef CONFIG_PPC_PSERIES
+#ifdef CONFIG_PPC_RTAS
/*
* Initialize RTAS if available
*/
rtas_initialize();
-#endif /* CONFIG_PPC_PSERIES */
+#endif /* CONFIG_PPC_RTAS */
/*
* Check if we have an initrd provided via the device-tree
early_console_initialized = 1;
register_console(&udbg_console);
-#endif /* !CONFIG_PPC_ISERIES */
-
/* Save unparsed command line copy for /proc/cmdline */
strlcpy(saved_command_line, cmd_line, COMMAND_LINE_SIZE);
parse_early_param();
+#endif /* !CONFIG_PPC_ISERIES */
#if defined(CONFIG_SMP) && !defined(CONFIG_PPC_ISERIES)
/*
printk("Starting Linux PPC64 %s\n", UTS_RELEASE);
printk("-----------------------------------------------------\n");
- printk("naca = 0x%p\n", naca);
- printk("naca->pftSize = 0x%lx\n", naca->pftSize);
- printk("naca->debug_switch = 0x%lx\n", naca->debug_switch);
- printk("naca->interrupt_controller = 0x%ld\n", naca->interrupt_controller);
+ printk("ppc64_pft_size = 0x%lx\n", ppc64_pft_size);
+ printk("ppc64_debug_switch = 0x%lx\n", ppc64_debug_switch);
+ printk("ppc64_interrupt_controller = 0x%ld\n", ppc64_interrupt_controller);
printk("systemcfg = 0x%p\n", systemcfg);
printk("systemcfg->platform = 0x%x\n", systemcfg->platform);
printk("systemcfg->processorCount = 0x%lx\n", systemcfg->processorCount);
printk("systemcfg->physicalMemorySize = 0x%lx\n", systemcfg->physicalMemorySize);
- printk("systemcfg->dCacheL1LineSize = 0x%x\n", systemcfg->dCacheL1LineSize);
- printk("systemcfg->iCacheL1LineSize = 0x%x\n", systemcfg->iCacheL1LineSize);
- printk("htab_data.htab = 0x%p\n", htab_data.htab);
- printk("htab_data.num_ptegs = 0x%lx\n", htab_data.htab_num_ptegs);
+ printk("ppc64_caches.dcache_line_size = 0x%x\n",
+ ppc64_caches.dline_size);
+ printk("ppc64_caches.icache_line_size = 0x%x\n",
+ ppc64_caches.iline_size);
+ printk("htab_address = 0x%p\n", htab_address);
+ printk("htab_hash_mask = 0x%lx\n", htab_hash_mask);
printk("-----------------------------------------------------\n");
mm_init_ppc64();
seq_printf(m, "unknown (%08x)", pvr);
#ifdef CONFIG_ALTIVEC
- if (cur_cpu_spec->cpu_features & CPU_FTR_ALTIVEC)
+ if (cpu_has_feature(CPU_FTR_ALTIVEC))
seq_printf(m, ", altivec supported");
#endif /* CONFIG_ALTIVEC */
.show = show_cpuinfo,
};
-#if 0 /* XXX not currently used */
+/*
+ * These three variables are used to save values passed to us by prom_init()
+ * via the device tree. The TCE variables are needed because with a memory_limit
+ * in force we may need to explicitly map the TCE are at the top of RAM.
+ */
unsigned long memory_limit;
+unsigned long tce_alloc_start;
+unsigned long tce_alloc_end;
+#ifdef CONFIG_PPC_ISERIES
+/*
+ * On iSeries we just parse the mem=X option from the command line.
+ * On pSeries it's a bit more complicated, see prom_init_mem()
+ */
static int __init early_parsemem(char *p)
{
if (!p)
return 0;
- memory_limit = memparse(p, &p);
+ memory_limit = ALIGN(memparse(p, &p), PAGE_SIZE);
return 0;
}
early_param("mem", early_parsemem);
-#endif
+#endif /* CONFIG_PPC_ISERIES */
#ifdef CONFIG_PPC_MULTIPLATFORM
static int __init set_preferred_console(void)
limit)) + PAGE_SIZE;
}
+/*
+ * Called from setup_arch to initialize the bitmap of available
+ * syscalls in the systemcfg page
+ */
+void __init setup_syscall_map(void)
+{
+ unsigned int i, count64 = 0, count32 = 0;
+ extern unsigned long *sys_call_table;
+ extern unsigned long *sys_call_table32;
+ extern unsigned long sys_ni_syscall;
+
+
+ for (i = 0; i < __NR_syscalls; i++) {
+ if (sys_call_table[i] == sys_ni_syscall)
+ continue;
+ count64++;
+ systemcfg->syscall_map_64[i >> 5] |= 0x80000000UL >> (i & 0x1f);
+ }
+ for (i = 0; i < __NR_syscalls; i++) {
+ if (sys_call_table32[i] == sys_ni_syscall)
+ continue;
+ count32++;
+ systemcfg->syscall_map_32[i >> 5] |= 0x80000000UL >> (i & 0x1f);
+ }
+ printk(KERN_INFO "Syscall map setup, %d 32 bits and %d 64 bits syscalls\n",
+ count32, count64);
+}
+
/*
* Called into from start_kernel, after lock_kernel has been called.
* Initializes bootmem, which is unsed to manage page allocation until
*/
void __init setup_arch(char **cmdline_p)
{
- extern int panic_timeout;
extern void do_init_bootmem(void);
ppc64_boot_msg(0x12, "Setup Arch");
* Systems with OF can look in the properties on the cpu node(s)
* for a possibly more accurate value.
*/
- dcache_bsize = systemcfg->dCacheL1LineSize;
- icache_bsize = systemcfg->iCacheL1LineSize;
+ dcache_bsize = ppc64_caches.dline_size;
+ icache_bsize = ppc64_caches.iline_size;
/* reboot on panic */
panic_timeout = 180;
/* set up the bootmem stuff with available memory */
do_init_bootmem();
+ /* initialize the syscall map in systemcfg */
+ setup_syscall_map();
+
ppc_md.setup_arch();
/* Select the correct idle loop for the platform. */
printk("[dump]%04x %s\n", src, msg);
}
-int set_spread_lpevents( char * str )
-{
- /* The parameter is the number of processors to share in processing lp events */
- unsigned long i;
- unsigned long val = simple_strtoul( str, NULL, 0 );
- if ( ( val > 0 ) && ( val <= NR_CPUS ) ) {
- for ( i=1; i<val; ++i )
- paca[i].lpqueue_ptr = paca[0].lpqueue_ptr;
- printk("lpevent processing spread over %ld processors\n", val);
- }
- else
- printk("invalid spreaqd_lpevents %ld\n", val);
- return 1;
-}
-
/* This should only be called on processor 0 during calibrate decr */
void setup_default_decr(void)
{
struct paca_struct *lpaca = get_paca();
- if ( decr_overclock_set && !decr_overclock_proc0_set )
- decr_overclock_proc0 = decr_overclock;
-
- lpaca->default_decr = tb_ticks_per_jiffy / decr_overclock_proc0;
+ lpaca->default_decr = tb_ticks_per_jiffy;
lpaca->next_jiffy_update_tb = get_tb() + tb_ticks_per_jiffy;
}
-int set_decr_overclock_proc0( char * str )
-{
- unsigned long val = simple_strtoul( str, NULL, 0 );
- if ( ( val >= 1 ) && ( val <= 48 ) ) {
- decr_overclock_proc0_set = 1;
- decr_overclock_proc0 = val;
- printk("proc 0 decrementer overclock factor of %ld\n", val);
- }
- else
- printk("invalid proc 0 decrementer overclock factor of %ld\n", val);
- return 1;
-}
-
-int set_decr_overclock( char * str )
-{
- unsigned long val = simple_strtoul( str, NULL, 0 );
- if ( ( val >= 1 ) && ( val <= 48 ) ) {
- decr_overclock_set = 1;
- decr_overclock = val;
- printk("decrementer overclock factor of %ld\n", val);
- }
- else
- printk("invalid decrementer overclock factor of %ld\n", val);
- return 1;
-
-}
-
-__setup("spread_lpevents=", set_spread_lpevents );
-__setup("decr_overclock_proc0=", set_decr_overclock_proc0 );
-__setup("decr_overclock=", set_decr_overclock );
-
#ifndef CONFIG_PPC_ISERIES
/*
* This function can be used by platforms to "find" legacy serial ports.
static struct plat_serial8250_port serial_ports[MAX_LEGACY_SERIAL_PORTS+1];
static unsigned int old_serial_count;
-void __init generic_find_legacy_serial_ports(unsigned int *default_speed)
+void __init generic_find_legacy_serial_ports(u64 *physport,
+ unsigned int *default_speed)
{
struct device_node *np;
u32 *sizeprop;
DBG(" -> generic_find_legacy_serial_port()\n");
- naca->serialPortAddr = 0;
+ *physport = 0;
if (default_speed)
*default_speed = 0;
io_base = (io_base << 32) | rangesp[4];
}
if (io_base != 0) {
- naca->serialPortAddr = io_base + reg->address;
+ *physport = io_base + reg->address;
if (default_speed && spd)
*default_speed = *spd;
}
static int __init early_xmon(char *p)
{
/* ensure xmon is enabled */
+ if (p) {
+ if (strncmp(p, "on", 2) == 0)
+ xmon_init();
+ if (strncmp(p, "early", 5) != 0)
+ return 0;
+ }
xmon_init();
debugger(NULL);
{
if (ppc_md.cpu_die)
ppc_md.cpu_die();
- local_irq_disable();
- for (;;);
}