[ccan] [PATCH] cpuid: new module
Ahmed Samy
f.fallen45 at gmail.com
Wed Sep 25 22:17:31 EST 2013
Hi Rusty,
On Wed, Sep 25, 2013 at 5:08 AM, Rusty Russell <rusty at rustcorp.com.au>wrote:
>
> Hmm, the .S file is problematic. We haven't had one before.
>
> The rule for compiling a CCAN module is: compile *.c.
>
> So, it would be best to put that function inline. I can't see anything
> on Microsoft's web site about handling pre-cpuid CPUs (and __cpuid was
> introduced in 1998, so perhaps it was a requirement for Windows at that
> point (cpuid was introduced in 1993).
>
> So, perhaps make cpuid_is_supported() 1 on Windows, and use inline asm
Sure, I could probably do that.
> Minor nits below:
> > +#ifndef CCAN_CPUID_H
> > +#define CCAN_CPUID_H
> > +
> > +typedef enum cpuid {
>
> Not a fan of gratuitous typedefs, but I know others like them. I find
> 'enum cpuid' more explicit than 'cpuid_t'.
It won't be used in real code anyway, since you would just pass CPU_* to
cpuid().
> > +/* returns 1 if the cpuid instruction is supported, 0 otherwise.
> > + *
> > + * CPUID isn't supported on very old Intel CPUs.
> > + * Defined in issupprted.S
> > + */
> > +int cpuid_is_supported(void);
> I assume stdbool.h exists on Windows? We should use it...
It does on MinGW but not on VS since VS is stuck in C89 (not quite sure).
>
> +/* returns the highest extended function supported.
> > + *
> > + * This is the same as calling:
> > + * cpuid(CPU_HIGHEST_EEXTENDED_FUNCTION_SUPPORTED, &highest);
> > + *
> > + * This is made visible to the linker because it's easier to call it
> > + * instead of calling cpuid with less type-checking. cpuid calls this.
> > + */
> > +int highest_ext_func_supported(void);
>
> Why int, not uint32_t?
>
> > +/* Get Some information from the CPU.
> > + * This function expects buf to be a valid pointer to a string/int/...
> > + * depending on the requested information.
> > + *
> > + * For CPU_VENDOR_ID:
> > + * Returns a string into buf.
> > + *
> > + * For CPU_PROCINFO_AND_FEATUREBITS:
> > + * buf[0]:
> > + * - 3:0 - Stepping
> > + * - 7:4 - Model
> > + * - 11:8 - Family
> > + * - 13:12 - Processor Type
> > + * - 19:16 - Extended Model
> > + * - 27:20 - Extended family
> > + * buf[1] and buf[2]:
> > + * Feature flags
> > + * buf[3]:
> > + * Additional feature information.
> > + *
> > + * For CPU_HIGHEST_EXTENDED_FUNCTION_SUPPORTED:
> > + * Returns the highest supported function in *buf (expects an integer
> ofc)
> > + *
> > + * For CPU_EXTENDED_PROC_INFO_FEATURE_BITS:
> > + * Returns them in buf[0] and buf[1].
> > + *
> > + * For CPU_VIRT_PHYS_ADDR_SIZES:
> > + * Returns it as an integer in *buf.
> > + *
> > + * For CPU_PROC_BRAND_STRING:
> > + * Have a char array with at least 48 bytes assigned to it.
> > + *
> > + * If an invalid flag has been passed a 0xbaadf00d is returned in *buf.
>
> You mean "any other info value" right?
Yep.
>
> + */
> > +void cpuid(cpuid_t info, void *buf);
>
> But buf is always a uint32_t array. Maybe change to that, and create a
> simple wrapper, eg:
>
> static inline void cpuid_vendor_id(char id[48])
> {
> cpuid(CPU_VENDOR_ID, (uint32_t *)id);
> }
>
Sure, I can do that.
> > +
> > +/* Test if the CPU supports MMX/SSE*
> > + *
> > + * Returns 1 if the feature is available, 0 otherwise.
> > + */
> > +#define cpuid_has_mmx() cpuid_has_feature(CF_MMX)
> > +#define cpuid_has_sse() cpuid_has_feature(CF_SSE)
> > +#define cpuid_has_sse2() cpuid_has_feature(CF_SSE2)
> > +#define cpuid_has_sse3() cpuid_has_feature(CF_SSE3)
> > +#define cpuid_has_ssse3() cpuid_has_feature(CF_SSSE3)
> > +#define cpuid_has_sse41() cpuid_has_feature(CF_SSE41)
> > +#define cpuid_has_sse42() cpuid_has_feature(CF_SSE42)
> > +#define cpuid_has_avx() cpuid_has_feature(CF_AVX)
> > +#define cpuid_has_fma() cpuid_has_feature(CF_FMA)
> > +int cpuid_has_feature(cpufeature_t feature);
> > +
> > +/* Test if the CPU supports an extended feature.
> > + *
> > + * Returns 1 if available, 0 otherwise.
> > + */
> > +#define cpuid_has_x64() cpuid_has_ext_feature(CEF_x64)
> > +#define cpuid_has_sse4a() cpuid_has_ext_feature(CEF_SSE4a)
> > +#define cpuid_has_fma4() cpuid_has_ext_feature(CEF_FMA4)
> > +#define cpuid_has_xop() cpuid_has_ext_feature(CEF_XOP)
> > +int cpuid_has_ext_feature(cpuextfeature_t extfeature);
>
> The rest looks fine, though as David suggested, using ccan/build_assert
> would be nice, so you can create dummy macros for non-x86 which compile
> but die if they're ever called, eg:
>
> #else /* non-x86: die if they compile this in! */
>
> #define cpuid_has_feature(feature) BUILD_ASSERT_OR_ZERO(0)
> #define cpuid(info, buf) BUILD_ASSERT_OR_ZERO(0)
> ...
Okay.
Btw, would you like me to fork your tree on GitHub instead so it'd be
easier for you to pull the commits? I don't mind keeping up with the
patches.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.ozlabs.org/pipermail/ccan/attachments/20130925/ebe88446/attachment.html>
More information about the ccan
mailing list