⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 prom.c

📁 linux 内核源代码
💻 C
📖 第 1 页 / 共 3 页
字号:
}/* * ibm,pa-features is a per-cpu property that contains a string of * attribute descriptors, each of which has a 2 byte header plus up * to 254 bytes worth of processor attribute bits.  First header * byte specifies the number of bytes following the header. * Second header byte is an "attribute-specifier" type, of which * zero is the only currently-defined value. * Implementation:  Pass in the byte and bit offset for the feature * that we are interested in.  The function will return -1 if the * pa-features property is missing, or a 1/0 to indicate if the feature * is supported/not supported.  Note that the bit numbers are * big-endian to match the definition in PAPR. */static struct ibm_pa_feature {	unsigned long	cpu_features;	/* CPU_FTR_xxx bit */	unsigned int	cpu_user_ftrs;	/* PPC_FEATURE_xxx bit */	unsigned char	pabyte;		/* byte number in ibm,pa-features */	unsigned char	pabit;		/* bit number (big-endian) */	unsigned char	invert;		/* if 1, pa bit set => clear feature */} ibm_pa_features[] __initdata = {	{0, PPC_FEATURE_HAS_MMU,	0, 0, 0},	{0, PPC_FEATURE_HAS_FPU,	0, 1, 0},	{CPU_FTR_SLB, 0,		0, 2, 0},	{CPU_FTR_CTRL, 0,		0, 3, 0},	{CPU_FTR_NOEXECUTE, 0,		0, 6, 0},	{CPU_FTR_NODSISRALIGN, 0,	1, 1, 1},	{CPU_FTR_CI_LARGE_PAGE, 0,	1, 2, 0},	{CPU_FTR_REAL_LE, PPC_FEATURE_TRUE_LE, 5, 0, 0},};static void __init scan_features(unsigned long node, unsigned char *ftrs,				 unsigned long tablelen,				 struct ibm_pa_feature *fp,				 unsigned long ft_size){	unsigned long i, len, bit;	/* find descriptor with type == 0 */	for (;;) {		if (tablelen < 3)			return;		len = 2 + ftrs[0];		if (tablelen < len)			return;		/* descriptor 0 not found */		if (ftrs[1] == 0)			break;		tablelen -= len;		ftrs += len;	}	/* loop over bits we know about */	for (i = 0; i < ft_size; ++i, ++fp) {		if (fp->pabyte >= ftrs[0])			continue;		bit = (ftrs[2 + fp->pabyte] >> (7 - fp->pabit)) & 1;		if (bit ^ fp->invert) {			cur_cpu_spec->cpu_features |= fp->cpu_features;			cur_cpu_spec->cpu_user_features |= fp->cpu_user_ftrs;		} else {			cur_cpu_spec->cpu_features &= ~fp->cpu_features;			cur_cpu_spec->cpu_user_features &= ~fp->cpu_user_ftrs;		}	}}static void __init check_cpu_pa_features(unsigned long node){	unsigned char *pa_ftrs;	unsigned long tablelen;	pa_ftrs = of_get_flat_dt_prop(node, "ibm,pa-features", &tablelen);	if (pa_ftrs == NULL)		return;	scan_features(node, pa_ftrs, tablelen,		      ibm_pa_features, ARRAY_SIZE(ibm_pa_features));}static struct feature_property {	const char *name;	u32 min_value;	unsigned long cpu_feature;	unsigned long cpu_user_ftr;} feature_properties[] __initdata = {#ifdef CONFIG_ALTIVEC	{"altivec", 0, CPU_FTR_ALTIVEC, PPC_FEATURE_HAS_ALTIVEC},	{"ibm,vmx", 1, CPU_FTR_ALTIVEC, PPC_FEATURE_HAS_ALTIVEC},#endif /* CONFIG_ALTIVEC */#ifdef CONFIG_PPC64	{"ibm,dfp", 1, 0, PPC_FEATURE_HAS_DFP},	{"ibm,purr", 1, CPU_FTR_PURR, 0},	{"ibm,spurr", 1, CPU_FTR_SPURR, 0},#endif /* CONFIG_PPC64 */};static void __init check_cpu_feature_properties(unsigned long node){	unsigned long i;	struct feature_property *fp = feature_properties;	const u32 *prop;	for (i = 0; i < ARRAY_SIZE(feature_properties); ++i, ++fp) {		prop = of_get_flat_dt_prop(node, fp->name, NULL);		if (prop && *prop >= fp->min_value) {			cur_cpu_spec->cpu_features |= fp->cpu_feature;			cur_cpu_spec->cpu_user_features |= fp->cpu_user_ftr;		}	}}static int __init early_init_dt_scan_cpus(unsigned long node,					  const char *uname, int depth,					  void *data){	static int logical_cpuid = 0;	char *type = of_get_flat_dt_prop(node, "device_type", NULL);	const u32 *prop;	const u32 *intserv;	int i, nthreads;	unsigned long len;	int found = 0;	/* We are scanning "cpu" nodes only */	if (type == NULL || strcmp(type, "cpu") != 0)		return 0;	/* Get physical cpuid */	intserv = of_get_flat_dt_prop(node, "ibm,ppc-interrupt-server#s", &len);	if (intserv) {		nthreads = len / sizeof(int);	} else {		intserv = of_get_flat_dt_prop(node, "reg", NULL);		nthreads = 1;	}	/*	 * Now see if any of these threads match our boot cpu.	 * NOTE: This must match the parsing done in smp_setup_cpu_maps.	 */	for (i = 0; i < nthreads; i++) {		/*		 * version 2 of the kexec param format adds the phys cpuid of		 * booted proc.		 */		if (initial_boot_params && initial_boot_params->version >= 2) {			if (intserv[i] ==					initial_boot_params->boot_cpuid_phys) {				found = 1;				break;			}		} else {			/*			 * Check if it's the boot-cpu, set it's hw index now,			 * unfortunately this format did not support booting			 * off secondary threads.			 */			if (of_get_flat_dt_prop(node,					"linux,boot-cpu", NULL) != NULL) {				found = 1;				break;			}		}#ifdef CONFIG_SMP		/* logical cpu id is always 0 on UP kernels */		logical_cpuid++;#endif	}	if (found) {		DBG("boot cpu: logical %d physical %d\n", logical_cpuid,			intserv[i]);		boot_cpuid = logical_cpuid;		set_hard_smp_processor_id(boot_cpuid, intserv[i]);		/*		 * PAPR defines "logical" PVR values for cpus that		 * meet various levels of the architecture:		 * 0x0f000001	Architecture version 2.04		 * 0x0f000002	Architecture version 2.05		 * If the cpu-version property in the cpu node contains		 * such a value, we call identify_cpu again with the		 * logical PVR value in order to use the cpu feature		 * bits appropriate for the architecture level.		 *		 * A POWER6 partition in "POWER6 architected" mode		 * uses the 0x0f000002 PVR value; in POWER5+ mode		 * it uses 0x0f000001.		 */		prop = of_get_flat_dt_prop(node, "cpu-version", NULL);		if (prop && (*prop & 0xff000000) == 0x0f000000)			identify_cpu(0, *prop);#if defined(CONFIG_44x) && defined(CONFIG_PPC_FPU)		/*		 * Since 440GR(x)/440EP(x) processors have the same pvr,		 * we check the node path and set bit 28 in the cur_cpu_spec		 * pvr for EP(x) processor version. This bit is always 0 in		 * the "real" pvr. Then we call identify_cpu again with		 * the new logical pvr to enable FPU support.		 */		if (strstr(uname, "440EP")) {			identify_cpu(0, cur_cpu_spec->pvr_value | 0x8);		}#endif	}	check_cpu_feature_properties(node);	check_cpu_pa_features(node);#ifdef CONFIG_PPC_PSERIES	if (nthreads > 1)		cur_cpu_spec->cpu_features |= CPU_FTR_SMT;	else		cur_cpu_spec->cpu_features &= ~CPU_FTR_SMT;#endif	return 0;}#ifdef CONFIG_BLK_DEV_INITRDstatic void __init early_init_dt_check_for_initrd(unsigned long node){	unsigned long l;	u32 *prop;	DBG("Looking for initrd properties... ");	prop = of_get_flat_dt_prop(node, "linux,initrd-start", &l);	if (prop) {		initrd_start = (unsigned long)__va(of_read_ulong(prop, l/4));		prop = of_get_flat_dt_prop(node, "linux,initrd-end", &l);		if (prop) {			initrd_end = (unsigned long)					__va(of_read_ulong(prop, l/4));			initrd_below_start_ok = 1;		} else {			initrd_start = 0;		}	}	DBG("initrd_start=0x%lx  initrd_end=0x%lx\n", initrd_start, initrd_end);}#elsestatic inline void early_init_dt_check_for_initrd(unsigned long node){}#endif /* CONFIG_BLK_DEV_INITRD */static int __init early_init_dt_scan_chosen(unsigned long node,					    const char *uname, int depth, void *data){	unsigned long *lprop;	unsigned long l;	char *p;	DBG("search \"chosen\", depth: %d, uname: %s\n", depth, uname);	if (depth != 1 ||	    (strcmp(uname, "chosen") != 0 && strcmp(uname, "chosen@0") != 0))		return 0;#ifdef CONFIG_PPC64	/* check if iommu is forced on or off */	if (of_get_flat_dt_prop(node, "linux,iommu-off", NULL) != NULL)		iommu_is_off = 1;	if (of_get_flat_dt_prop(node, "linux,iommu-force-on", NULL) != NULL)		iommu_force_on = 1;#endif	/* mem=x on the command line is the preferred mechanism */ 	lprop = of_get_flat_dt_prop(node, "linux,memory-limit", NULL); 	if (lprop) 		memory_limit = *lprop;#ifdef CONFIG_PPC64 	lprop = of_get_flat_dt_prop(node, "linux,tce-alloc-start", NULL); 	if (lprop) 		tce_alloc_start = *lprop; 	lprop = of_get_flat_dt_prop(node, "linux,tce-alloc-end", NULL); 	if (lprop) 		tce_alloc_end = *lprop;#endif#ifdef CONFIG_KEXEC	lprop = (u64*)of_get_flat_dt_prop(node, "linux,crashkernel-base", NULL);	if (lprop)		crashk_res.start = *lprop;	lprop = (u64*)of_get_flat_dt_prop(node, "linux,crashkernel-size", NULL);	if (lprop)		crashk_res.end = crashk_res.start + *lprop - 1;#endif	early_init_dt_check_for_initrd(node);	/* Retreive command line */ 	p = of_get_flat_dt_prop(node, "bootargs", &l);	if (p != NULL && l > 0)		strlcpy(cmd_line, p, min((int)l, COMMAND_LINE_SIZE));#ifdef CONFIG_CMDLINE	if (p == NULL || l == 0 || (l == 1 && (*p) == 0))		strlcpy(cmd_line, CONFIG_CMDLINE, COMMAND_LINE_SIZE);#endif /* CONFIG_CMDLINE */	DBG("Command line is: %s\n", cmd_line);	/* break now */	return 1;}static int __init early_init_dt_scan_root(unsigned long node,					  const char *uname, int depth, void *data){	u32 *prop;	if (depth != 0)		return 0;	prop = of_get_flat_dt_prop(node, "#size-cells", NULL);	dt_root_size_cells = (prop == NULL) ? 1 : *prop;	DBG("dt_root_size_cells = %x\n", dt_root_size_cells);	prop = of_get_flat_dt_prop(node, "#address-cells", NULL);	dt_root_addr_cells = (prop == NULL) ? 2 : *prop;	DBG("dt_root_addr_cells = %x\n", dt_root_addr_cells);		/* break now */	return 1;}static unsigned long __init dt_mem_next_cell(int s, cell_t **cellp){	cell_t *p = *cellp;	*cellp = p + s;	return of_read_ulong(p, s);}#ifdef CONFIG_PPC_PSERIES/* * Interpret the ibm,dynamic-memory property in the * /ibm,dynamic-reconfiguration-memory node. * This contains a list of memory blocks along with NUMA affinity * information. */static int __init early_init_dt_scan_drconf_memory(unsigned long node){	cell_t *dm, *ls;	unsigned long l, n;	unsigned long base, size, lmb_size, flags;	ls = (cell_t *)of_get_flat_dt_prop(node, "ibm,lmb-size", &l);	if (ls == NULL || l < dt_root_size_cells * sizeof(cell_t))		return 0;	lmb_size = dt_mem_next_cell(dt_root_size_cells, &ls);	dm = (cell_t *)of_get_flat_dt_prop(node, "ibm,dynamic-memory", &l);	if (dm == NULL || l < sizeof(cell_t))		return 0;	n = *dm++;	/* number of entries */	if (l < (n * (dt_root_addr_cells + 4) + 1) * sizeof(cell_t))		return 0;	for (; n != 0; --n) {		base = dt_mem_next_cell(dt_root_addr_cells, &dm);		flags = dm[3];		/* skip DRC index, pad, assoc. list index, flags */		dm += 4;		/* skip this block if the reserved bit is set in flags (0x80)		   or if the block is not assigned to this partition (0x8) */		if ((flags & 0x80) || !(flags & 0x8))			continue;		size = lmb_size;		if (iommu_is_off) {			if (base >= 0x80000000ul)				continue;			if ((base + size) > 0x80000000ul)				size = 0x80000000ul - base;		}		lmb_add(base, size);	}	lmb_dump_all();	return 0;}#else#define early_init_dt_scan_drconf_memory(node)	0#endif /* CONFIG_PPC_PSERIES */static int __init early_init_dt_scan_memory(unsigned long node,					    const char *uname, int depth, void *data){	char *type = of_get_flat_dt_prop(node, "device_type", NULL);	cell_t *reg, *endp;	unsigned long l;	/* Look for the ibm,dynamic-reconfiguration-memory node */	if (depth == 1 &&	    strcmp(uname, "ibm,dynamic-reconfiguration-memory") == 0)		return early_init_dt_scan_drconf_memory(node);	/* We are scanning "memory" nodes only */	if (type == NULL) {		/*		 * The longtrail doesn't have a device_type on the		 * /memory node, so look for the node called /memory@0.		 */		if (depth != 1 || strcmp(uname, "memory@0") != 0)			return 0;	} else if (strcmp(type, "memory") != 0)		return 0;	reg = (cell_t *)of_get_flat_dt_prop(node, "linux,usable-memory", &l);	if (reg == NULL)		reg = (cell_t *)of_get_flat_dt_prop(node, "reg", &l);	if (reg == NULL)		return 0;	endp = reg + (l / sizeof(cell_t));	DBG("memory scan node %s, reg size %ld, data: %x %x %x %x,\n",	    uname, l, reg[0], reg[1], reg[2], reg[3]);	while ((endp - reg) >= (dt_root_addr_cells + dt_root_size_cells)) {		unsigned long base, size;		base = dt_mem_next_cell(dt_root_addr_cells, &reg);		size = dt_mem_next_cell(dt_root_size_cells, &reg);		if (size == 0)			continue;		DBG(" - %lx ,  %lx\n", base, size);#ifdef CONFIG_PPC64		if (iommu_is_off) {			if (base >= 0x80000000ul)				continue;			if ((base + size) > 0x80000000ul)				size = 0x80000000ul - base;		}#endif		lmb_add(base, size);	}	return 0;}static void __init early_reserve_mem(void){	u64 base, size;	u64 *reserve_map;	unsigned long self_base;	unsigned long self_size;	reserve_map = (u64 *)(((unsigned long)initial_boot_params) +					initial_boot_params->off_mem_rsvmap);	/* before we do anything, lets reserve the dt blob */	self_base = __pa((unsigned long)initial_boot_params);	self_size = initial_boot_params->totalsize;	lmb_reserve(self_base, self_size);#ifdef CONFIG_BLK_DEV_INITRD	/* then reserve the initrd, if any */	if (initrd_start && (initrd_end > initrd_start))		lmb_reserve(__pa(initrd_start), initrd_end - initrd_start);#endif /* CONFIG_BLK_DEV_INITRD */#ifdef CONFIG_PPC32	/* 	 * Handle the case where we might be booting from an old kexec	 * image that setup the mem_rsvmap as pairs of 32-bit values	 */	if (*reserve_map > 0xffffffffull) {		u32 base_32, size_32;		u32 *reserve_map_32 = (u32 *)reserve_map;		while (1) {			base_32 = *(reserve_map_32++);			size_32 = *(reserve_map_32++);			if (size_32 == 0)				break;			/* skip if the reservation is for the blob */			if (base_32 == self_base && size_32 == self_size)				continue;			DBG("reserving: %x -> %x\n", base_32, size_32);			lmb_reserve(base_32, size_32);		}		return;	}#endif	while (1) {		base = *(reserve_map++);		size = *(reserve_map++);		if (size == 0)			break;		DBG("reserving: %llx -> %llx\n", base, size);		lmb_reserve(base, size);	}#if 0	DBG("memory reserved, lmbs :\n");      	lmb_dump_all();

⌨️ 快捷键说明

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