setup.c

来自「Linux Kernel 2.6.9 for OMAP1710」· C语言 代码 · 共 1,121 行 · 第 1/2 页

C
1,121
字号
	/*	 * Fill the naca & 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	 * 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).	 */	initialize_naca();#ifdef CONFIG_PPC_PSERIES	/*	 * Initialize RTAS if available	 */	rtas_initialize();#endif /* CONFIG_PPC_PSERIES */	/*	 * Check if we have an initrd provided via the device-tree	 */	check_for_initrd();	/*	 * Do some platform specific early initializations, that includes	 * setting up the hash table pointers. It also sets up some interrupt-mapping	 * related options that will be used by finish_device_tree()	 */	ppc_md.init_early();	/*	 * "Finish" the device-tree, that is do the actual parsing of	 * some of the properties like the interrupt map	 */	finish_device_tree();	/*	 * Initialize xmon	 */#ifdef CONFIG_XMON_DEFAULT	xmon_init();#endif	/*	 * Register early console	 */	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();#if defined(CONFIG_SMP) && !defined(CONFIG_PPC_ISERIES)	/*	 * iSeries has already initialized the cpu maps at this point.	 */	setup_cpu_maps();#endif /* 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("systemcfg                     = 0x%p\n", systemcfg);	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("-----------------------------------------------------\n");	mm_init_ppc64();	DBG(" <- setup_system()\n");}void machine_restart(char *cmd){	if (ppc_md.nvram_sync)		ppc_md.nvram_sync();	ppc_md.restart(cmd);}EXPORT_SYMBOL(machine_restart);  void machine_power_off(void){	if (ppc_md.nvram_sync)		ppc_md.nvram_sync();	ppc_md.power_off();}EXPORT_SYMBOL(machine_power_off);  void machine_halt(void){	if (ppc_md.nvram_sync)		ppc_md.nvram_sync();	ppc_md.halt();}EXPORT_SYMBOL(machine_halt);unsigned long ppc_proc_freq;unsigned long ppc_tb_freq;static int ppc64_panic_event(struct notifier_block *this,                             unsigned long event, void *ptr){	ppc_md.panic((char *)ptr);  /* May not return */	return NOTIFY_DONE;}#ifdef CONFIG_SMPDEFINE_PER_CPU(unsigned int, pvr);#endifstatic int show_cpuinfo(struct seq_file *m, void *v){	unsigned long cpu_id = (unsigned long)v - 1;	unsigned int pvr;	unsigned short maj;	unsigned short min;	if (cpu_id == NR_CPUS) {		seq_printf(m, "timebase\t: %lu\n", ppc_tb_freq);		if (ppc_md.get_cpuinfo != NULL)			ppc_md.get_cpuinfo(m);		return 0;	}	/* We only show online cpus: disable preempt (overzealous, I	 * knew) to prevent cpu going down. */	preempt_disable();	if (!cpu_online(cpu_id)) {		preempt_enable();		return 0;	}#ifdef CONFIG_SMP	pvr = per_cpu(pvr, cpu_id);#else	pvr = mfspr(SPRN_PVR);#endif	maj = (pvr >> 8) & 0xFF;	min = pvr & 0xFF;	seq_printf(m, "processor\t: %lu\n", cpu_id);	seq_printf(m, "cpu\t\t: ");	if (cur_cpu_spec->pvr_mask)		seq_printf(m, "%s", cur_cpu_spec->cpu_name);	else		seq_printf(m, "unknown (%08x)", pvr);#ifdef CONFIG_ALTIVEC	if (cur_cpu_spec->cpu_features & CPU_FTR_ALTIVEC)		seq_printf(m, ", altivec supported");#endif /* CONFIG_ALTIVEC */	seq_printf(m, "\n");	/*	 * Assume here that all clock rates are the same in a	 * smp system.  -- Cort	 */	seq_printf(m, "clock\t\t: %lu.%06luMHz\n", ppc_proc_freq / 1000000,		   ppc_proc_freq % 1000000);	seq_printf(m, "revision\t: %hd.%hd\n\n", maj, min);	preempt_enable();	return 0;}static void *c_start(struct seq_file *m, loff_t *pos){	return *pos <= NR_CPUS ? (void *)((*pos)+1) : NULL;}static void *c_next(struct seq_file *m, void *v, loff_t *pos){	++*pos;	return c_start(m, pos);}static void c_stop(struct seq_file *m, void *v){}struct seq_operations cpuinfo_op = {	.start =c_start,	.next =	c_next,	.stop =	c_stop,	.show =	show_cpuinfo,};#if 0 /* XXX not currently used */unsigned long memory_limit;static int __init early_parsemem(char *p){	if (!p)		return 0;	memory_limit = memparse(p, &p);	return 0;}early_param("mem", early_parsemem);#endif#ifdef CONFIG_PPC_MULTIPLATFORMstatic int __init set_preferred_console(void){	struct device_node *prom_stdout;	char *name;	int offset = 0;#if  0	phandle *stdout_ph;#endif	DBG(" -> set_preferred_console()\n");	/* The user has requested a console so this is already set up. */	if (strstr(saved_command_line, "console=")) {		DBG(" console was specified !\n");		return -EBUSY;	}	if (!of_chosen) {		DBG(" of_chosen is NULL !\n");		return -ENODEV;	}	/* We are getting a weird phandle from OF ... */#if 0	stdout_ph = (phandle *)get_property(of_chosen, "linux,stdout-package", NULL);	if (stdout_ph == NULL) {		DBG(" no linux,stdout-package !\n");		return -ENODEV;	}	prom_stdout = of_find_node_by_phandle(*stdout_ph);	if (!prom_stdout) {		DBG(" can't find stdout package for phandle 0x%x !\n", *stdout_ph);		return -ENODEV;	}#endif	/* ... So use the full path instead */#if 1	name = (char *)get_property(of_chosen, "linux,stdout-path", NULL);	if (name == NULL) {		DBG(" no linux,stdout-path !\n");		return -ENODEV;	}	prom_stdout = of_find_node_by_path(name);	if (!prom_stdout) {		DBG(" can't find stdout package %s !\n", name);		return -ENODEV;	}	#endif	DBG("stdout is %s\n", prom_stdout->full_name);	name = (char *)get_property(prom_stdout, "name", NULL);	if (!name) {		DBG(" stdout package has no name !\n");		goto not_found;	}	if (strcmp(name, "serial") == 0) {		int i;		u32 *reg = (u32 *)get_property(prom_stdout, "reg", &i);		if (i > 8) {			switch (reg[1]) {				case 0x3f8:					offset = 0;					break;				case 0x2f8:					offset = 1;					break;				case 0x898:					offset = 2;					break;				case 0x890:					offset = 3;					break;				default:					/* We dont recognise the serial port */					goto not_found;			}		}	}#ifdef CONFIG_PPC_PSERIES	else if (strcmp(name, "vty") == 0) { 		u32 *reg = (u32 *)get_property(prom_stdout, "reg", NULL); 		char *compat = (char *)get_property(prom_stdout, "compatible", NULL); 		if (reg && compat && (strcmp(compat, "hvterm-protocol") == 0)) { 			/* Host Virtual Serial Interface */ 			int offset; 			switch (reg[0]) { 				case 0x30000000: 					offset = 0; 					break; 				case 0x30000001: 					offset = 1; 					break; 				default:					goto not_found; 			}			of_node_put(prom_stdout);			DBG("Found hvsi console at offset %d\n", offset); 			return add_preferred_console("hvsi", offset, NULL); 		} else { 			/* pSeries LPAR virtual console */			of_node_put(prom_stdout);			DBG("Found hvc console\n"); 			return add_preferred_console("hvc", 0, NULL); 		}	}#endif /* CONFIG_PPC_PSERIES */	else if (strcmp(name, "ch-a") == 0)		offset = 0;	else if (strcmp(name, "ch-b") == 0)		offset = 1;	else		goto not_found;	of_node_put(prom_stdout);	DBG("Found serial console at ttyS%d\n", offset);	return add_preferred_console("ttyS", offset, NULL); not_found:	DBG("No preferred console found !\n");	of_node_put(prom_stdout);	return -ENODEV;}console_initcall(set_preferred_console);#endif /* CONFIG_PPC_MULTIPLATFORM */#ifdef CONFIG_IRQSTACKSstatic void __init irqstack_early_init(void){	unsigned int i;	/*	 * interrupt stacks must be under 256MB, we cannot afford to take	 * SLB misses on them.	 */	for_each_cpu(i) {		softirq_ctx[i] = (struct thread_info *)__va(lmb_alloc_base(THREAD_SIZE,					THREAD_SIZE, 0x10000000));		hardirq_ctx[i] = (struct thread_info *)__va(lmb_alloc_base(THREAD_SIZE,					THREAD_SIZE, 0x10000000));	}}#else#define irqstack_early_init()#endif/* * Stack space used when we detect a bad kernel stack pointer, and * early in SMP boots before relocation is enabled. */static void __init emergency_stack_init(void){	unsigned long limit;	unsigned int i;	/*	 * Emergency stacks must be under 256MB, we cannot afford to take	 * SLB misses on them. The ABI also requires them to be 128-byte	 * aligned.	 *	 * Since we use these as temporary stacks during secondary CPU	 * bringup, we need to get at them in real mode. This means they	 * must also be within the RMO region.	 */	limit = min(0x10000000UL, lmb.rmo_size);	for_each_cpu(i)		paca[i].emergency_sp = __va(lmb_alloc_base(PAGE_SIZE, 128,						limit)) + PAGE_SIZE;}/* * Called into from start_kernel, after lock_kernel has been called. * Initializes bootmem, which is unsed to manage page allocation until * mem_init is called. */void __init setup_arch(char **cmdline_p){	extern int panic_timeout;	extern void do_init_bootmem(void);	ppc64_boot_msg(0x12, "Setup Arch");	*cmdline_p = cmd_line;	/*	 * Set cache line size based on type of cpu as a default.	 * 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; 	/* reboot on panic */	panic_timeout = 180;	if (ppc_md.panic)		notifier_chain_register(&panic_notifier_list, &ppc64_panic_block);	init_mm.start_code = PAGE_OFFSET;	init_mm.end_code = (unsigned long) _etext;	init_mm.end_data = (unsigned long) _edata;	init_mm.brk = klimit;		irqstack_early_init();	emergency_stack_init();	/* set up the bootmem stuff with available memory */	do_init_bootmem();	/* Select the correct idle loop for the platform. */	idle_setup();	ppc_md.setup_arch();	paging_init();	ppc64_boot_msg(0x15, "Setup Done");}/* ToDo: do something useful if ppc_md is not yet setup. */#define PPC64_LINUX_FUNCTION 0x0f000000#define PPC64_IPL_MESSAGE 0xc0000000#define PPC64_TERM_MESSAGE 0xb0000000#define PPC64_ATTN_MESSAGE 0xa0000000#define PPC64_DUMP_MESSAGE 0xd0000000static void ppc64_do_msg(unsigned int src, const char *msg){	if (ppc_md.progress) {		char buf[32];		sprintf(buf, "%08x        \n", src);		ppc_md.progress(buf, 0);		sprintf(buf, "%-16s", msg);		ppc_md.progress(buf, 0);	}}/* Print a boot progress message. */void ppc64_boot_msg(unsigned int src, const char *msg){	ppc64_do_msg(PPC64_LINUX_FUNCTION|PPC64_IPL_MESSAGE|src, msg);	printk("[boot]%04x %s\n", src, msg);}/* Print a termination message (print only -- does not stop the kernel) */void ppc64_terminate_msg(unsigned int src, const char *msg){	ppc64_do_msg(PPC64_LINUX_FUNCTION|PPC64_TERM_MESSAGE|src, msg);	printk("[terminate]%04x %s\n", src, msg);}/* Print something that needs attention (device error, etc) */void ppc64_attention_msg(unsigned int src, const char *msg){	ppc64_do_msg(PPC64_LINUX_FUNCTION|PPC64_ATTN_MESSAGE|src, msg);	printk("[attention]%04x %s\n", src, msg);}/* Print a dump progress message. */void ppc64_dump_msg(unsigned int src, const char *msg){	ppc64_do_msg(PPC64_LINUX_FUNCTION|PPC64_DUMP_MESSAGE|src, msg);	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->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 );#ifdef CONFIG_XMONstatic int __init early_xmon(char *p){	/* ensure xmon is enabled */	xmon_init();	debugger(0);	return 0;}early_param("xmon", early_xmon);#endif

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?