[bug#53895,2/5] gnu: cpu: Add detection for AMD CPUs.
Commit Message
* guix/cpu.scm <cpu>: Add vendor field.
(current-cpu): Also fill in the 'vendor' field.
(cpu->gcc-architecture): Add detection logic for AMD CPUs.
---
guix/cpu.scm | 60 ++++++++++++++++++++++++++++++++++++++++++++--------
1 file changed, 51 insertions(+), 9 deletions(-)
Comments
Efraim Flashner <efraim@flashner.co.il> skribis:
> * guix/cpu.scm <cpu>: Add vendor field.
> (current-cpu): Also fill in the 'vendor' field.
> (cpu->gcc-architecture): Add detection logic for AMD CPUs.
[...]
> + (and (equal? "AuthenticAMD" (cpu-vendor cpu))
Isn’t that equivalent to (= (cpu-family cpu) some-value)?
> + (letrec-syntax ((if-flags (syntax-rules (=>)
> + ((_)
> + #f)
> + ((_ (flags ... => name) rest ...)
> + (if (every (lambda (flag)
> + (set-contains? (cpu-flags cpu)
> + flag))
> + '(flags ...))
> + name
> + (if-flags rest ...))))))
> +
> + (when (= 22 (cpu-family cpu))
> + (if-flags ("movbe" => "btver2")))
> + (when (= 6 (cpu-family cpu))
> + (if-flags ("3dnowp" => "athalon")))
This has no effect (because ‘if-flags’ returns a value that is ignored
since it’s not returned.)
What we could do is extend ‘if-flags’ so that it can optionally check
for a family number:
(if-flags ((family 22) "movbe" => "btver2")
…)
> + (if-flags ("vaes" => "znver3")
> + ("clwb" => "znver2")
> + ("clzero" => "znver1")
However, the code in driver-i386.c seems to look at model IDs (the big
“switch (processor)” thing) and not feature flags. Or am I overlooking
something?
Thanks,
Ludo’.
On Wed, Feb 09, 2022 at 11:43:21AM +0100, Ludovic Courtès wrote:
> Efraim Flashner <efraim@flashner.co.il> skribis:
>
> > * guix/cpu.scm <cpu>: Add vendor field.
> > (current-cpu): Also fill in the 'vendor' field.
> > (cpu->gcc-architecture): Add detection logic for AMD CPUs.
>
> [...]
>
> > + (and (equal? "AuthenticAMD" (cpu-vendor cpu))
>
> Isn’t that equivalent to (= (cpu-family cpu) some-value)?
It looks to me like 'family' started as the prefix for iX86, so Intel is
mostly using family 6, except when a couple of other processors slip in.
I wasn't able to find a hard and fast rule for what family AMD typically
uses, on my machine its 23. In driver-i386.c it's sort by vendor first:
if (vendor == VENDOR_AMD)
> > + (letrec-syntax ((if-flags (syntax-rules (=>)
> > + ((_)
> > + #f)
> > + ((_ (flags ... => name) rest ...)
> > + (if (every (lambda (flag)
> > + (set-contains? (cpu-flags cpu)
> > + flag))
> > + '(flags ...))
> > + name
> > + (if-flags rest ...))))))
> > +
> > + (when (= 22 (cpu-family cpu))
> > + (if-flags ("movbe" => "btver2")))
> > + (when (= 6 (cpu-family cpu))
> > + (if-flags ("3dnowp" => "athalon")))
>
> This has no effect (because ‘if-flags’ returns a value that is ignored
> since it’s not returned.)
>
> What we could do is extend ‘if-flags’ so that it can optionally check
> for a family number:
>
> (if-flags ((family 22) "movbe" => "btver2")
> …)
That sounds like a good idea.
> > + (if-flags ("vaes" => "znver3")
> > + ("clwb" => "znver2")
> > + ("clzero" => "znver1")
>
> However, the code in driver-i386.c seems to look at model IDs (the big
> “switch (processor)” thing) and not feature flags. Or am I overlooking
> something?
switch (processor) comes after all the AMD chips are sorted. It looks
like all of Intel's i686 and x86_64 are PROCESSOR_PENTIUMPRO, while AMD
has a separate processor per chip design. The AMD chips are sorted about
90 lines above the switch (processor) line
> Thanks,
> Ludo’.
On Wed, Feb 09, 2022 at 11:43:21AM +0100, Ludovic Courtès wrote:
> Efraim Flashner <efraim@flashner.co.il> skribis:
>
> > + (letrec-syntax ((if-flags (syntax-rules (=>)
> > + ((_)
> > + #f)
> > + ((_ (flags ... => name) rest ...)
> > + (if (every (lambda (flag)
> > + (set-contains? (cpu-flags cpu)
> > + flag))
> > + '(flags ...))
> > + name
> > + (if-flags rest ...))))))
> > +
> > + (when (= 22 (cpu-family cpu))
> > + (if-flags ("movbe" => "btver2")))
> > + (when (= 6 (cpu-family cpu))
> > + (if-flags ("3dnowp" => "athalon")))
>
> This has no effect (because ‘if-flags’ returns a value that is ignored
> since it’s not returned.)
>
> What we could do is extend ‘if-flags’ so that it can optionally check
> for a family number:
>
> (if-flags ((family 22) "movbe" => "btver2")
> …)
Another option would be to just move it to the bottom of the if-flags so
it should take effect then.
Efraim Flashner <efraim@flashner.co.il> skribis:
>> What we could do is extend ‘if-flags’ so that it can optionally check
>> for a family number:
>>
>> (if-flags ((family 22) "movbe" => "btver2")
>> …)
>
> Another option would be to just move it to the bottom of the if-flags so
> it should take effect then.
Yes, your call!
Ludo’.
On Thu, Feb 10, 2022 at 09:42:44PM +0100, Ludovic Courtès wrote:
> Efraim Flashner <efraim@flashner.co.il> skribis:
>
> >> What we could do is extend ‘if-flags’ so that it can optionally check
> >> for a family number:
> >>
> >> (if-flags ((family 22) "movbe" => "btver2")
> >> …)
> >
> > Another option would be to just move it to the bottom of the if-flags so
> > it should take effect then.
>
> Yes, your call!
Just moving it to the end didn't end up being enough to make it work, my
processor was determined to be <unspecified>. I changed it to an 'or'
which seemed to make it work, and my testing seemed to show that it
would work (alternating substituting junk and my processor flags to make
it obviously one or the other).
Thanks for the review and the feedback. And for doing the work in the
first place!
@@ -27,6 +27,7 @@ (define-module (guix cpu)
#:export (current-cpu
cpu?
cpu-architecture
+ cpu-vendor
cpu-family
cpu-model
cpu-flags
@@ -42,9 +43,10 @@ (define-module (guix cpu)
;; CPU description.
(define-record-type <cpu>
- (cpu architecture family model flags)
+ (cpu architecture vendor family model flags)
cpu?
(architecture cpu-architecture) ;string, from 'uname'
+ (vendor cpu-vendor) ;string
(family cpu-family) ;integer
(model cpu-model) ;integer
(flags cpu-flags)) ;set of strings
@@ -58,28 +60,33 @@ (define (prefix? prefix)
(call-with-input-file "/proc/cpuinfo"
(lambda (port)
- (let loop ((family #f)
+ (let loop ((vendor #f)
+ (family #f)
(model #f))
(match (read-line port)
((? eof-object?)
#f)
+ ((? (prefix? "vendor_id") str)
+ (match (string-tokenize str)
+ (("vendor_id" ":" vendor)
+ (loop vendor family model))))
((? (prefix? "cpu family") str)
(match (string-tokenize str)
(("cpu" "family" ":" family)
- (loop (string->number family) model))))
+ (loop vendor (string->number family) model))))
((? (prefix? "model") str)
(match (string-tokenize str)
(("model" ":" model)
- (loop family (string->number model)))
+ (loop vendor family (string->number model)))
(_
- (loop family model))))
+ (loop vendor family model))))
((? (prefix? "flags") str)
(match (string-tokenize str)
(("flags" ":" flags ...)
(cpu (utsname:machine (uname))
- family model (list->set flags)))))
+ vendor family model (list->set flags)))))
(_
- (loop family model))))))))
+ (loop vendor family model))))))))
(define (cpu->gcc-architecture cpu)
"Return the architecture name, suitable for GCC's '-march' flag, that
@@ -87,7 +94,8 @@ (define (cpu->gcc-architecture cpu)
(match (cpu-architecture cpu)
("x86_64"
;; Transcribed from GCC's 'host_detect_local_cpu' in driver-i386.c.
- (or (and (= 6 (cpu-family cpu)) ;the "Pentium Pro" family
+ (or (and (equal? "GenuineIntel" (cpu-vendor cpu))
+ (= 6 (cpu-family cpu)) ;the "Pentium Pro" family
(letrec-syntax ((if-flags (syntax-rules (=>)
((_)
#f)
@@ -122,6 +130,40 @@ (define (cpu->gcc-architecture cpu)
("ssse3" => "core2")
("longmode" => "x86-64"))))
+ (and (equal? "AuthenticAMD" (cpu-vendor cpu))
+ (letrec-syntax ((if-flags (syntax-rules (=>)
+ ((_)
+ #f)
+ ((_ (flags ... => name) rest ...)
+ (if (every (lambda (flag)
+ (set-contains? (cpu-flags cpu)
+ flag))
+ '(flags ...))
+ name
+ (if-flags rest ...))))))
+
+ (when (= 22 (cpu-family cpu))
+ (if-flags ("movbe" => "btver2")))
+ (when (= 6 (cpu-family cpu))
+ (if-flags ("3dnowp" => "athalon")))
+
+ (if-flags ("vaes" => "znver3")
+ ("clwb" => "znver2")
+ ("clzero" => "znver1")
+ ("avx2" => "bdver4")
+ ("xsaveopt" => "bdver3")
+ ("bmi" => "bdver2")
+ ("xop" => "bdver1")
+ ("sse4a" "has_ssse3" => "btver1")
+ ("sse4a" => "amdfam10")
+ ("sse2" "sse3" => "k8-sse3")
+ ("longmode" "sse3" => "k8-sse3")
+ ("sse2" => "k8")
+ ("longmode" => "k8")
+ ("mmx" "3dnow" => "k6-3")
+ ("mmx" => "k6")
+ (_ => "pentium"))))
+
;; Fallback case for non-Intel processors or for Intel processors not
;; recognized above.
(letrec-syntax ((if-flags (syntax-rules (=>)
@@ -147,7 +189,7 @@ (define (cpu->gcc-architecture cpu)
("ssse3" "movbe" => "bonnell")
("ssse3" => "core2")))
- ;; TODO: Recognize AMD models (bdver*, znver*, etc.)?
+ ;; TODO: Recognize CENTAUR/CYRIX/NSC?
"x86_64"))
(architecture