Re: [U-Boot] [PATCH 1/4] x86: Display more detailed CPU information on boot
Hi Bin, On 8 November 2014 08:18, Bin Meng wrote: > Hi Simon, > > On Fri, Nov 7, 2014 at 10:22 AM, Simon Glass wrote: >> Hi Bin, >> >> On 4 November 2014 07:58, Bin Meng wrote: >>> Currently only basic CPU information (x86 or x86_64) is displayed >>> on boot. This commit adds more detailed information output including >>> CPU vendor name, device id, family, model and stepping as well as >>> the CPU brand string, all of which are extracted from CPUID result. >>> >>> The CPU identification happens in x86_cpu_init_f() and corresponding >>> fields are saved in the global data. Later print_cpuinfo() just uses >>> these fields to display CPU information without the need to probe >>> again in real time. >>> >>> Signed-off-by: Bin Meng >>> --- >>> arch/x86/cpu/cpu.c | 282 >>> +++-- >>> arch/x86/include/asm/cpu.h | 142 +++ >>> arch/x86/include/asm/global_data.h | 5 + >>> 3 files changed, 385 insertions(+), 44 deletions(-) >>> >>> diff --git a/arch/x86/cpu/cpu.c b/arch/x86/cpu/cpu.c >>> index 2e25253..e9058f7 100644 >>> --- a/arch/x86/cpu/cpu.c >>> +++ b/arch/x86/cpu/cpu.c >>> @@ -13,6 +13,9 @@ >>> * Sysgo Real-Time Solutions, GmbH >>> * Alex Zuepke >>> * >>> + * Part of this file is adapted from coreboot >>> + * src/arch/x86/lib/cpu.c >>> + * >>> * SPDX-License-Identifier:GPL-2.0+ >>> */ >>> >>> @@ -27,6 +30,8 @@ >>> #include >>> #include >>> >>> +DECLARE_GLOBAL_DATA_PTR; >>> + >>> /* >>> * Constructor for a conventional segment GDT (or LDT) entry >>> * This is a macro so it can be used in initialisers >>> @@ -43,6 +48,51 @@ struct gdt_ptr { >>> u32 ptr; >>> } __packed; >>> >>> +struct cpu_device_id { >>> + unsigned vendor; >>> + unsigned device; >>> +}; >>> + >>> +struct cpuinfo_x86 { >>> +uint8_tx86;/* CPU family */ >>> +uint8_tx86_vendor; /* CPU vendor */ >>> +uint8_tx86_model; >>> +uint8_tx86_mask; >>> +}; >>> + >>> +/* List of cpu vendor strings along with their normalized >> >> Can we put /* on its own line? >> >> /* >> * List of CPU vendor strings ... >> * ... >> */ >> > > Sure. > >>> + * id values. >>> + */ >>> +static struct { >>> + int vendor; >>> + const char *name; >>> +} x86_vendors[] = { >>> + { X86_VENDOR_INTEL, "GenuineIntel", }, >>> + { X86_VENDOR_CYRIX, "CyrixInstead", }, >>> + { X86_VENDOR_AMD, "AuthenticAMD", }, >>> + { X86_VENDOR_UMC, "UMC UMC UMC ", }, >>> + { X86_VENDOR_NEXGEN,"NexGenDriven", }, >>> + { X86_VENDOR_CENTAUR, "CentaurHauls", }, >>> + { X86_VENDOR_RISE, "RiseRiseRise", }, >>> + { X86_VENDOR_TRANSMETA, "GenuineTMx86", }, >>> + { X86_VENDOR_TRANSMETA, "TransmetaCPU", }, >>> + { X86_VENDOR_NSC, "Geode by NSC", }, >>> + { X86_VENDOR_SIS, "SiS SiS SiS ", }, >>> +}; >>> + >>> +static const char *x86_vendor_name[] = { >>> + [X86_VENDOR_INTEL] = "Intel", >>> + [X86_VENDOR_CYRIX] = "Cyrix", >>> + [X86_VENDOR_AMD] = "AMD", >>> + [X86_VENDOR_UMC] = "UMC", >>> + [X86_VENDOR_NEXGEN]= "NexGen", >>> + [X86_VENDOR_CENTAUR] = "Centaur", >>> + [X86_VENDOR_RISE] = "Rise", >>> + [X86_VENDOR_TRANSMETA] = "Transmeta", >>> + [X86_VENDOR_NSC] = "NSC", >>> + [X86_VENDOR_SIS] = "SiS", >>> +}; >>> + >>> static void load_ds(u32 segment) >>> { >>> asm volatile("movl %0, %%ds" : : "r" (segment * >>> X86_GDT_ENTRY_SIZE)); >>> @@ -115,6 +165,131 @@ int __weak x86_cleanup_before_linux(void) >>> return 0; >>> } >>> >>> +/* >>> + * Cyrix CPUs without cpuid or with cpuid not yet enabled can be detected >>> + * by the fact that they preserve the flags across the division of 5/2. >>> + * PII and PPro exhibit this behavior too, but they have cpuid available. >>> + */ >>> + >>> +/* >>> + * Perform the Cyrix 5/2 test. A Cyrix won't change >>> + * the flags, while other 486 chips will. >>> + */ >>> +static inline int test_cyrix_52div(void) >>> +{ >>> + unsigned int test; >>> + >>> + __asm__ __volatile__( >>> +"sahf\n\t" /* clear flags (%eax = 0x0005) */ >>> +"div %b2\n\t" /* divide 5 by 2 */ >>> +"lahf" /* store flags into %ah */ >>> +: "=a" (test) >>> +: "0" (5), "q" (2) >>> +: "cc"); >>> + >>> + /* AH is 0x02 on Cyrix after the divide.. */ >>> + return (unsigned char) (test >> 8) == 0x02; >>> +} >>> + >>> +/* >>> + * Detect a NexGen CPU running without BIOS hypercode new enough >>> + * to have CPUID. (Thanks to Herbert Oppmann) >>> + */ >>> + >>> +static int deep_magic_nexgen_probe(void) >>> +{ >>> + int ret; >>> + >>> + __asm__ __volatile__ ( >>> + " movw$0x, %%ax\n" >>> + " xorw%%dx,%%dx\n" >>>
Re: [U-Boot] [PATCH 1/4] x86: Display more detailed CPU information on boot
Hi Simon, On Fri, Nov 7, 2014 at 10:23 AM, Simon Glass wrote: > Hi Bin, > > On 6 November 2014 19:22, Simon Glass wrote: >> Hi Bin, >> >> On 4 November 2014 07:58, Bin Meng wrote: >>> Currently only basic CPU information (x86 or x86_64) is displayed >>> on boot. This commit adds more detailed information output including >>> CPU vendor name, device id, family, model and stepping as well as >>> the CPU brand string, all of which are extracted from CPUID result. >>> >>> The CPU identification happens in x86_cpu_init_f() and corresponding >>> fields are saved in the global data. Later print_cpuinfo() just uses >>> these fields to display CPU information without the need to probe >>> again in real time. > > Sorry...one more point. For CPU info it should fit on one line. So > maybe use debug() for the extra stuff. If you like you can create a > 'cpuinfo' command or similar to get more detailed information, but > U-Boot should start up with the minimum of verbiage. OK, I will rework the patch. Regards, Bin ___ U-Boot mailing list U-Boot@lists.denx.de http://lists.denx.de/mailman/listinfo/u-boot
Re: [U-Boot] [PATCH 1/4] x86: Display more detailed CPU information on boot
Hi Simon, On Fri, Nov 7, 2014 at 10:22 AM, Simon Glass wrote: > Hi Bin, > > On 4 November 2014 07:58, Bin Meng wrote: >> Currently only basic CPU information (x86 or x86_64) is displayed >> on boot. This commit adds more detailed information output including >> CPU vendor name, device id, family, model and stepping as well as >> the CPU brand string, all of which are extracted from CPUID result. >> >> The CPU identification happens in x86_cpu_init_f() and corresponding >> fields are saved in the global data. Later print_cpuinfo() just uses >> these fields to display CPU information without the need to probe >> again in real time. >> >> Signed-off-by: Bin Meng >> --- >> arch/x86/cpu/cpu.c | 282 >> +++-- >> arch/x86/include/asm/cpu.h | 142 +++ >> arch/x86/include/asm/global_data.h | 5 + >> 3 files changed, 385 insertions(+), 44 deletions(-) >> >> diff --git a/arch/x86/cpu/cpu.c b/arch/x86/cpu/cpu.c >> index 2e25253..e9058f7 100644 >> --- a/arch/x86/cpu/cpu.c >> +++ b/arch/x86/cpu/cpu.c >> @@ -13,6 +13,9 @@ >> * Sysgo Real-Time Solutions, GmbH >> * Alex Zuepke >> * >> + * Part of this file is adapted from coreboot >> + * src/arch/x86/lib/cpu.c >> + * >> * SPDX-License-Identifier:GPL-2.0+ >> */ >> >> @@ -27,6 +30,8 @@ >> #include >> #include >> >> +DECLARE_GLOBAL_DATA_PTR; >> + >> /* >> * Constructor for a conventional segment GDT (or LDT) entry >> * This is a macro so it can be used in initialisers >> @@ -43,6 +48,51 @@ struct gdt_ptr { >> u32 ptr; >> } __packed; >> >> +struct cpu_device_id { >> + unsigned vendor; >> + unsigned device; >> +}; >> + >> +struct cpuinfo_x86 { >> +uint8_tx86;/* CPU family */ >> +uint8_tx86_vendor; /* CPU vendor */ >> +uint8_tx86_model; >> +uint8_tx86_mask; >> +}; >> + >> +/* List of cpu vendor strings along with their normalized > > Can we put /* on its own line? > > /* > * List of CPU vendor strings ... > * ... > */ > Sure. >> + * id values. >> + */ >> +static struct { >> + int vendor; >> + const char *name; >> +} x86_vendors[] = { >> + { X86_VENDOR_INTEL, "GenuineIntel", }, >> + { X86_VENDOR_CYRIX, "CyrixInstead", }, >> + { X86_VENDOR_AMD, "AuthenticAMD", }, >> + { X86_VENDOR_UMC, "UMC UMC UMC ", }, >> + { X86_VENDOR_NEXGEN,"NexGenDriven", }, >> + { X86_VENDOR_CENTAUR, "CentaurHauls", }, >> + { X86_VENDOR_RISE, "RiseRiseRise", }, >> + { X86_VENDOR_TRANSMETA, "GenuineTMx86", }, >> + { X86_VENDOR_TRANSMETA, "TransmetaCPU", }, >> + { X86_VENDOR_NSC, "Geode by NSC", }, >> + { X86_VENDOR_SIS, "SiS SiS SiS ", }, >> +}; >> + >> +static const char *x86_vendor_name[] = { >> + [X86_VENDOR_INTEL] = "Intel", >> + [X86_VENDOR_CYRIX] = "Cyrix", >> + [X86_VENDOR_AMD] = "AMD", >> + [X86_VENDOR_UMC] = "UMC", >> + [X86_VENDOR_NEXGEN]= "NexGen", >> + [X86_VENDOR_CENTAUR] = "Centaur", >> + [X86_VENDOR_RISE] = "Rise", >> + [X86_VENDOR_TRANSMETA] = "Transmeta", >> + [X86_VENDOR_NSC] = "NSC", >> + [X86_VENDOR_SIS] = "SiS", >> +}; >> + >> static void load_ds(u32 segment) >> { >> asm volatile("movl %0, %%ds" : : "r" (segment * X86_GDT_ENTRY_SIZE)); >> @@ -115,6 +165,131 @@ int __weak x86_cleanup_before_linux(void) >> return 0; >> } >> >> +/* >> + * Cyrix CPUs without cpuid or with cpuid not yet enabled can be detected >> + * by the fact that they preserve the flags across the division of 5/2. >> + * PII and PPro exhibit this behavior too, but they have cpuid available. >> + */ >> + >> +/* >> + * Perform the Cyrix 5/2 test. A Cyrix won't change >> + * the flags, while other 486 chips will. >> + */ >> +static inline int test_cyrix_52div(void) >> +{ >> + unsigned int test; >> + >> + __asm__ __volatile__( >> +"sahf\n\t" /* clear flags (%eax = 0x0005) */ >> +"div %b2\n\t" /* divide 5 by 2 */ >> +"lahf" /* store flags into %ah */ >> +: "=a" (test) >> +: "0" (5), "q" (2) >> +: "cc"); >> + >> + /* AH is 0x02 on Cyrix after the divide.. */ >> + return (unsigned char) (test >> 8) == 0x02; >> +} >> + >> +/* >> + * Detect a NexGen CPU running without BIOS hypercode new enough >> + * to have CPUID. (Thanks to Herbert Oppmann) >> + */ >> + >> +static int deep_magic_nexgen_probe(void) >> +{ >> + int ret; >> + >> + __asm__ __volatile__ ( >> + " movw$0x, %%ax\n" >> + " xorw%%dx,%%dx\n" >> + " movw$2, %%cx\n" >> + " divw%%cx\n" >> + " movl$0, %%eax\n" >> + " jnz 1f\n" >> + " movl$1
Re: [U-Boot] [PATCH 1/4] x86: Display more detailed CPU information on boot
Hi Bin, On 6 November 2014 19:22, Simon Glass wrote: > Hi Bin, > > On 4 November 2014 07:58, Bin Meng wrote: >> Currently only basic CPU information (x86 or x86_64) is displayed >> on boot. This commit adds more detailed information output including >> CPU vendor name, device id, family, model and stepping as well as >> the CPU brand string, all of which are extracted from CPUID result. >> >> The CPU identification happens in x86_cpu_init_f() and corresponding >> fields are saved in the global data. Later print_cpuinfo() just uses >> these fields to display CPU information without the need to probe >> again in real time. Sorry...one more point. For CPU info it should fit on one line. So maybe use debug() for the extra stuff. If you like you can create a 'cpuinfo' command or similar to get more detailed information, but U-Boot should start up with the minimum of verbiage. Regards, Simon ___ U-Boot mailing list U-Boot@lists.denx.de http://lists.denx.de/mailman/listinfo/u-boot
Re: [U-Boot] [PATCH 1/4] x86: Display more detailed CPU information on boot
Hi Bin, On 4 November 2014 07:58, Bin Meng wrote: > Currently only basic CPU information (x86 or x86_64) is displayed > on boot. This commit adds more detailed information output including > CPU vendor name, device id, family, model and stepping as well as > the CPU brand string, all of which are extracted from CPUID result. > > The CPU identification happens in x86_cpu_init_f() and corresponding > fields are saved in the global data. Later print_cpuinfo() just uses > these fields to display CPU information without the need to probe > again in real time. > > Signed-off-by: Bin Meng > --- > arch/x86/cpu/cpu.c | 282 > +++-- > arch/x86/include/asm/cpu.h | 142 +++ > arch/x86/include/asm/global_data.h | 5 + > 3 files changed, 385 insertions(+), 44 deletions(-) > > diff --git a/arch/x86/cpu/cpu.c b/arch/x86/cpu/cpu.c > index 2e25253..e9058f7 100644 > --- a/arch/x86/cpu/cpu.c > +++ b/arch/x86/cpu/cpu.c > @@ -13,6 +13,9 @@ > * Sysgo Real-Time Solutions, GmbH > * Alex Zuepke > * > + * Part of this file is adapted from coreboot > + * src/arch/x86/lib/cpu.c > + * > * SPDX-License-Identifier:GPL-2.0+ > */ > > @@ -27,6 +30,8 @@ > #include > #include > > +DECLARE_GLOBAL_DATA_PTR; > + > /* > * Constructor for a conventional segment GDT (or LDT) entry > * This is a macro so it can be used in initialisers > @@ -43,6 +48,51 @@ struct gdt_ptr { > u32 ptr; > } __packed; > > +struct cpu_device_id { > + unsigned vendor; > + unsigned device; > +}; > + > +struct cpuinfo_x86 { > +uint8_tx86;/* CPU family */ > +uint8_tx86_vendor; /* CPU vendor */ > +uint8_tx86_model; > +uint8_tx86_mask; > +}; > + > +/* List of cpu vendor strings along with their normalized Can we put /* on its own line? /* * List of CPU vendor strings ... * ... */ > + * id values. > + */ > +static struct { > + int vendor; > + const char *name; > +} x86_vendors[] = { > + { X86_VENDOR_INTEL, "GenuineIntel", }, > + { X86_VENDOR_CYRIX, "CyrixInstead", }, > + { X86_VENDOR_AMD, "AuthenticAMD", }, > + { X86_VENDOR_UMC, "UMC UMC UMC ", }, > + { X86_VENDOR_NEXGEN,"NexGenDriven", }, > + { X86_VENDOR_CENTAUR, "CentaurHauls", }, > + { X86_VENDOR_RISE, "RiseRiseRise", }, > + { X86_VENDOR_TRANSMETA, "GenuineTMx86", }, > + { X86_VENDOR_TRANSMETA, "TransmetaCPU", }, > + { X86_VENDOR_NSC, "Geode by NSC", }, > + { X86_VENDOR_SIS, "SiS SiS SiS ", }, > +}; > + > +static const char *x86_vendor_name[] = { > + [X86_VENDOR_INTEL] = "Intel", > + [X86_VENDOR_CYRIX] = "Cyrix", > + [X86_VENDOR_AMD] = "AMD", > + [X86_VENDOR_UMC] = "UMC", > + [X86_VENDOR_NEXGEN]= "NexGen", > + [X86_VENDOR_CENTAUR] = "Centaur", > + [X86_VENDOR_RISE] = "Rise", > + [X86_VENDOR_TRANSMETA] = "Transmeta", > + [X86_VENDOR_NSC] = "NSC", > + [X86_VENDOR_SIS] = "SiS", > +}; > + > static void load_ds(u32 segment) > { > asm volatile("movl %0, %%ds" : : "r" (segment * X86_GDT_ENTRY_SIZE)); > @@ -115,6 +165,131 @@ int __weak x86_cleanup_before_linux(void) > return 0; > } > > +/* > + * Cyrix CPUs without cpuid or with cpuid not yet enabled can be detected > + * by the fact that they preserve the flags across the division of 5/2. > + * PII and PPro exhibit this behavior too, but they have cpuid available. > + */ > + > +/* > + * Perform the Cyrix 5/2 test. A Cyrix won't change > + * the flags, while other 486 chips will. > + */ > +static inline int test_cyrix_52div(void) > +{ > + unsigned int test; > + > + __asm__ __volatile__( > +"sahf\n\t" /* clear flags (%eax = 0x0005) */ > +"div %b2\n\t" /* divide 5 by 2 */ > +"lahf" /* store flags into %ah */ > +: "=a" (test) > +: "0" (5), "q" (2) > +: "cc"); > + > + /* AH is 0x02 on Cyrix after the divide.. */ > + return (unsigned char) (test >> 8) == 0x02; > +} > + > +/* > + * Detect a NexGen CPU running without BIOS hypercode new enough > + * to have CPUID. (Thanks to Herbert Oppmann) > + */ > + > +static int deep_magic_nexgen_probe(void) > +{ > + int ret; > + > + __asm__ __volatile__ ( > + " movw$0x, %%ax\n" > + " xorw%%dx,%%dx\n" > + " movw$2, %%cx\n" > + " divw%%cx\n" > + " movl$0, %%eax\n" > + " jnz 1f\n" > + " movl$1, %%eax\n" > + "1:\n" > + : "=a" (ret) : : "cx", "dx" ); > + return ret; > +} > + > +static bool has_cpuid(void) > +{ > + return flag_is_changeable_p(X86_EFLAGS_ID); > +} > + > +static void