Processor : ARMv7 Processor rev 5 (v7l)
BogoMIPS : 799.53
Features : swp half thumb fastmult vfp edsp neon vfpv3
CPU implementer : 0x41
CPU architecture: 7
CPU variant : 0x2
CPU part : 0xc08
CPU revision : 5
按照ARM datasheet,ARMv7的Architecture应该是0xF Defined by CPUID scheme,为什么看到的是7?
static int __init proc_cpuinfo_init(void) { proc_create("cpuinfo", 0, NULL, &proc_cpuinfo_operations); return 0; }
static const struct file_operations proc_cpuinfo_operations = { .open = cpuinfo_open,//一般只有open函数需要自己实现,主要是将指定的seq_file和file关联起来 .read = seq_read,//系统实现 .llseek = seq_lseek,//系统实现 .release = seq_release,//系统实现 };
static int cpuinfo_open(struct inode *inode, struct file *file) { return seq_open(file, &cpuinfo_op); }
cpuinfo_op结构是架构相关,对于arm架构的定义在arch/arm/kernel/setup.c
const struct seq_operations cpuinfo_op = { .start = c_start, .next = c_next, .stop = c_stop, .show = c_show };
int seq_open(struct file *file, const struct seq_operations *op) { struct seq_file *p = file->private_data; if (!p) { //如果file->private_data为空,则为它申请空间 p = kmalloc(sizeof(*p), GFP_KERNEL); if (!p) return -ENOMEM; file->private_data = p; } memset(p, 0, sizeof(*p));//清0 mutex_init(&p->lock); //初始化mutex p->op = op; //将上面传进来的cpuinfo_op赋值给file的p,以后通过file的private_data成员就能找到cpuinfo_op了 file->f_version = 0; file->f_mode &= ~FMODE_PWRITE; return 0; }
seq_file文件的内核读取过程
static void *c_start(struct seq_file *m, loff_t *pos) { return *pos < 1 ? (void *)1 : NULL; }
检查文件位置,如果是0,返回1,否则NULL。
static void *c_next(struct seq_file *m, void *v, loff_t *pos) { ++*pos; return NULL; }
文件位置指针增加,指向下一个位置。
static void c_stop(struct seq_file *m, void *v) { }
static int c_show(struct seq_file *m, void *v) { int i; /*打印cpu的processor,例如例子中的Processor : ARMv7 Processor rev 5 (v7l)*/ seq_printf(m, "Processor\t: %s rev %d (%s)\n", cpu_name, read_cpuid_id() & 15, elf_platform); #if defined(CONFIG_SMP)//如果是多核处理器,则分别打印cpu的processor信息和主频信息 for_each_online_cpu(i) { /* * glibc reads /proc/cpuinfo to determine the number of * online processors, looking for lines beginning with * "processor". Give glibc what it expects. */ seq_printf(m, "processor\t: %d\n", i); seq_printf(m, "BogoMIPS\t: %lu.%02lu\n\n", per_cpu(cpu_data, i).loops_per_jiffy / (500000UL/HZ), (per_cpu(cpu_data, i).loops_per_jiffy / (5000UL/HZ)) % 100); } #else /* CONFIG_SMP */ seq_printf(m, "BogoMIPS\t: %lu.%02lu\n", loops_per_jiffy / (500000/HZ), (loops_per_jiffy / (5000/HZ)) % 100); #endif /* dump out the processor features */ seq_puts(m, "Features\t: ");//下面打印feature信息 for (i = 0; hwcap_str; i++) if (elf_hwcap & (1 << i)) seq_printf(m, "%s ", hwcap_str); seq_printf(m, "\nCPU implementer\t: 0x%02x\n", read_cpuid_id() >> 24); seq_printf(m, "CPU architecture: %s\n", proc_arch[cpu_architecture()]); if ((read_cpuid_id() & 0x0008f000) == 0x00000000) { /* pre-ARM7 */ seq_printf(m, "CPU part\t: %07x\n", read_cpuid_id() >> 4); } else { if ((read_cpuid_id() & 0x0008f000) == 0x00007000) { /* ARM7 */ seq_printf(m, "CPU variant\t: 0x%02x\n", (read_cpuid_id() >> 16) & 127); } else { /* post-ARM7 */ seq_printf(m, "CPU variant\t: 0x%x\n", (read_cpuid_id() >> 20) & 15); } seq_printf(m, "CPU part\t: 0x%03x\n", (read_cpuid_id() >> 4) & 0xfff); } seq_printf(m, "CPU revision\t: %d\n", read_cpuid_id() & 15); seq_puts(m, "\n"); seq_printf(m, "Hardware\t: %s\n", machine_name); seq_printf(m, "Revision\t: %04x\n", system_rev); seq_printf(m, "Serial\t\t: %08x%08x\n", system_serial_high, system_serial_low);//这里我们终于看到serial打印的地方了。我们发现主要打印 system_serial_high,和system_serial_low两个变量的值。如果没有赋值,则打印0。我们要做的工作就是为这两个变量赋值。 return 0; }
CPU architecture信息是由proc_arch[cpu_architecture()]决定的,并不是直接打印从MIDR中的Architecture。
int __pure cpu_architecture(void) { BUG_ON(__cpu_architecture == CPU_ARCH_UNKNOWN); return __cpu_architecture; }
setup_processer()->__cpu_architecture = __get_cpu_architecture()
对于ARMv7返回的是CPU_ARCH_ARMv7为9,proc_arch[9] = ‘7’,就是代表v7。