17#include <sys/utsname.h>
18#if __GLIBC_PREREQ (2,16)
45# if defined(__linux__) && defined(__x86_64__)
46 inline void cpuid(uint32_t op, uint32_t op2, uint32_t *eax, uint32_t *ebx, uint32_t *ecx, uint32_t *edx)
50 :
"=a" (*eax),
"=b" (*ebx),
"=c" (*ecx),
"=d" (*edx)
51 :
"a" (op),
"c" (op2));
57 #define bit_SSE3 (1 << 0)
58 #define bit_SSSE3 (1 << 9)
59 #define bit_FMA (1 << 12)
60 #define bit_CMPXCHG16B (1 << 13)
61 #define bit_SSE4_1 (1 << 19)
62 #define bit_SSE4_2 (1 << 20)
63 #define bit_MOVBE (1 << 22)
64 #define bit_POPCNT (1 << 23)
65 #define bit_OSXSAVE (1 << 27)
66 #define bit_AVX (1 << 28)
67 #define bit_F16C (1 << 29)
71 #define bit_LAHF_LM (1 << 0)
72 #define bit_LZCNT (1 << 5)
76 #define bit_BMI (1 << 3)
77 #define bit_AVX2 (1 << 5)
78 #define bit_BMI2 (1 << 8)
79 #define bit_AVX512F (1 << 16)
80 #define bit_AVX512DQ (1 << 17)
81 #define bit_AVX512CD (1 << 28)
82 #define bit_AVX512BW (1 << 30)
83 #define bit_AVX512VL (1u << 31)
85 int get_x86_64_level(
void)
89 unsigned int op_1_ecx = 0, op_80000001_ecx = 0, op_7_ebx = 0, unused = 0;
90 cpuid(1, 0, &unused, &unused, &op_1_ecx, &unused);
91 cpuid(0x80000001, 0, &unused, &unused, &op_80000001_ecx, &unused);
92 cpuid(7, 0, &unused, &op_7_ebx, &unused, &unused);
94 const unsigned int op_1_ecx_lv2 = bit_SSE3 | bit_SSSE3 | bit_CMPXCHG16B | bit_SSE4_1 | bit_SSE4_2 | bit_POPCNT;
95 if ((op_1_ecx & op_1_ecx_lv2) == op_1_ecx_lv2 && (op_80000001_ecx & bit_LAHF_LM))
98 const unsigned int op_1_ecx_lv3 = bit_FMA | bit_MOVBE | bit_OSXSAVE | bit_AVX | bit_F16C;
99 const unsigned int op_7_ebx_lv3 = bit_BMI | bit_AVX2 | bit_BMI2;
100 if (level == 2 && (op_1_ecx & op_1_ecx_lv3) == op_1_ecx_lv3 && (op_7_ebx & op_7_ebx_lv3) == op_7_ebx_lv3
101 && (op_80000001_ecx & bit_LZCNT))
104 const unsigned int op_7_ebx_lv4 = bit_AVX512F | bit_AVX512DQ | bit_AVX512CD | bit_AVX512BW | bit_AVX512VL;
105 if (level == 3 && (op_7_ebx & op_7_ebx_lv4) == op_7_ebx_lv4)
112 Arch _autoDetectSystemArchitecture() {
113 struct ::utsname buf;
114 if ( ::uname( &buf ) < 0 )
116 ERR <<
"Can't determine system architecture" << endl;
120 Arch architecture( buf.machine );
121 MIL <<
"Uname architecture is '" << buf.machine <<
"'" << endl;
123 if ( architecture == Arch_x86_64 )
125 #if defined(__linux__) && defined(__x86_64__)
126 switch ( get_x86_64_level() )
129 architecture = Arch_x86_64_v2;
130 WAR <<
"CPU has 'x86_64': architecture upgraded to '" << architecture <<
"'" << endl;
133 architecture = Arch_x86_64_v3;
134 WAR <<
"CPU has 'x86_64': architecture upgraded to '" << architecture <<
"'" << endl;
137 architecture = Arch_x86_64_v4;
138 WAR <<
"CPU has 'x86_64': architecture upgraded to '" << architecture <<
"'" << endl;
143 else if ( architecture == Arch_i686 )
148 std::ifstream cpuinfo(
"/proc/cpuinfo" );
155 if ( in->find(
"cx8" ) == std::string::npos
156 || in->find(
"cmov" ) == std::string::npos )
158 architecture = Arch_i586;
159 WAR <<
"CPU lacks 'cx8' or 'cmov': architecture downgraded to '" << architecture <<
"'" << endl;
167 ERR <<
"Cant open " <<
PathInfo(
"/proc/cpuinfo") << endl;
170 else if ( architecture == Arch_sparc || architecture == Arch_sparc64 )
173 std::ifstream cpuinfo(
"/proc/cpuinfo" );
180 if ( in->find(
"sun4v" ) != std::string::npos )
182 architecture = ( architecture == Arch_sparc64 ? Arch_sparc64v : Arch_sparcv9v );
183 WAR <<
"CPU has 'sun4v': architecture upgraded to '" << architecture <<
"'" << endl;
185 else if ( in->find(
"sun4u" ) != std::string::npos )
187 architecture = ( architecture == Arch_sparc64 ? Arch_sparc64 : Arch_sparcv9 );
188 WAR <<
"CPU has 'sun4u': architecture upgraded to '" << architecture <<
"'" << endl;
190 else if ( in->find(
"sun4m" ) != std::string::npos )
192 architecture = Arch_sparcv8;
193 WAR <<
"CPU has 'sun4m': architecture upgraded to '" << architecture <<
"'" << endl;
201 ERR <<
"Cant open " <<
PathInfo(
"/proc/cpuinfo") << endl;
204 else if ( architecture == Arch_armv8l || architecture == Arch_armv7l || architecture == Arch_armv6l )
206 std::ifstream platform(
"/etc/rpm/platform" );
213 architecture = Arch_armv8hl;
214 WAR <<
"/etc/rpm/platform contains armv8hl-: architecture upgraded to '" << architecture <<
"'" << endl;
219 architecture = Arch_armv7hl;
220 WAR <<
"/etc/rpm/platform contains armv7hl-: architecture upgraded to '" << architecture <<
"'" << endl;
225 architecture = Arch_armv6hl;
226 WAR <<
"/etc/rpm/platform contains armv6hl-: architecture upgraded to '" << architecture <<
"'" << endl;
232 #if __GLIBC_PREREQ (2,16)
233 else if ( architecture == Arch_ppc64 )
235 const char * platform = (
const char *)getauxval( AT_PLATFORM );
237 if ( platform && sscanf( platform,
"power%d", &powerlvl ) == 1 && powerlvl > 6 )
238 architecture = Arch_ppc64p7;
311 return(
_idBit.value() < rhs.
_idBit.value() ? -1 : 1 );
347 {
return ! ( lhs == rhs ); }
371 #define DEF_BUILTIN(A) \
372 namespace { static inline const IdString & a_##A () { static IdString _str(#A); return _str; } } \
373 const Arch Arch_##A( a_##A() )
473 using Set = std::unordered_set<CompatEntry>;
474 using iterator = Set::iterator;
475 using const_iterator = Set::const_iterator;
478 static ArchCompatSet & instance()
480 static ArchCompatSet _instance;
487 const Arch::CompatEntry & assertDef(
const std::string & archStr_r )
488 {
return *_compatSet.insert( Arch::CompatEntry( archStr_r ) ).first; }
490 const Arch::CompatEntry & assertDef( IdString archStr_r )
491 {
return *_compatSet.insert( Arch::CompatEntry( archStr_r ) ).first; }
493 const_iterator begin()
const
494 {
return _compatSet.begin(); }
496 const_iterator end()
const
497 {
return _compatSet.end(); }
501 int operator()(
const CompatEntry & lhs,
const CompatEntry & rhs )
const
502 {
return lhs._idBit.value() < rhs._idBit.value(); }
505 std::ostream &
dumpOn( std::ostream & str )
const
507 str <<
"ArchCompatSet:";
508 std::list<CompatEntry> ov( _compatSet.begin(), _compatSet.end() );
509 ov.sort( DumpOnCompare() );
510 for_( it, ov.begin(), ov.end() )
512 str << endl <<
' ' << *it;
524 _compatSet.insert( Arch::CompatEntry( a_noarch(), 0 ) );
531 defCompatibleWith( a_i386(), a_noarch() );
532 defCompatibleWith( a_i486(), a_noarch(),a_i386() );
533 defCompatibleWith( a_i586(), a_noarch(),a_i386(),a_i486() );
534 defCompatibleWith( a_i686(), a_noarch(),a_i386(),a_i486(),a_i586() );
535 defCompatibleWith( a_athlon(), a_noarch(),a_i386(),a_i486(),a_i586(),a_i686() );
536 defCompatibleWith( a_x86_64(), a_noarch(),a_i386(),a_i486(),a_i586(),a_i686(),a_athlon() );
537 defCompatibleWith( a_x86_64_v2(), a_noarch(),a_i386(),a_i486(),a_i586(),a_i686(),a_athlon(),a_x86_64() );
538 defCompatibleWith( a_x86_64_v3(), a_noarch(),a_i386(),a_i486(),a_i586(),a_i686(),a_athlon(),a_x86_64(),a_x86_64_v2() );
539 defCompatibleWith( a_x86_64_v4(), a_noarch(),a_i386(),a_i486(),a_i586(),a_i686(),a_athlon(),a_x86_64(),a_x86_64_v2(),a_x86_64_v3() );
541 defCompatibleWith( a_pentium3(), a_noarch(),a_i386(),a_i486(),a_i586(),a_i686() );
542 defCompatibleWith( a_pentium4(), a_noarch(),a_i386(),a_i486(),a_i586(),a_i686(),a_pentium3() );
544 defCompatibleWith( a_ia64(), a_noarch(),a_i386(),a_i486(),a_i586(),a_i686() );
546 defCompatibleWith( a_s390(), a_noarch() );
547 defCompatibleWith( a_s390x(), a_noarch(),a_s390() );
549 defCompatibleWith( a_ppc(), a_noarch() );
550 defCompatibleWith( a_ppc64(), a_noarch(),a_ppc() );
551 defCompatibleWith( a_ppc64p7(), a_noarch(),a_ppc(),a_ppc64() );
553 defCompatibleWith( a_ppc64le(), a_noarch() );
555 defCompatibleWith( a_alpha(), a_noarch() );
556 defCompatibleWith( a_alphaev5(), a_noarch(),a_alpha() );
557 defCompatibleWith( a_alphaev56(), a_noarch(),a_alpha(),a_alphaev5() );
558 defCompatibleWith( a_alphapca56(), a_noarch(),a_alpha(),a_alphaev5(),a_alphaev56() );
559 defCompatibleWith( a_alphaev6(), a_noarch(),a_alpha(),a_alphaev5(),a_alphaev56(),a_alphapca56() );
560 defCompatibleWith( a_alphaev67(), a_noarch(),a_alpha(),a_alphaev5(),a_alphaev56(),a_alphapca56(),a_alphaev6() );
562 defCompatibleWith( a_sparc(), a_noarch() );
563 defCompatibleWith( a_sparcv8(), a_noarch(),a_sparc() );
564 defCompatibleWith( a_sparcv9(), a_noarch(),a_sparc(),a_sparcv8() );
565 defCompatibleWith( a_sparcv9v(), a_noarch(),a_sparc(),a_sparcv8(),a_sparcv9() );
567 defCompatibleWith( a_sparc64(), a_noarch(),a_sparc(),a_sparcv8(),a_sparcv9() );
568 defCompatibleWith( a_sparc64v(), a_noarch(),a_sparc(),a_sparcv8(),a_sparcv9(),a_sparcv9v(),a_sparc64() );
570 defCompatibleWith( a_armv3l(), a_noarch() );
571 defCompatibleWith( a_armv4l(), a_noarch(),a_armv3l() );
572 defCompatibleWith( a_armv4tl(), a_noarch(),a_armv3l(),a_armv4l() );
573 defCompatibleWith( a_armv5l(), a_noarch(),a_armv3l(),a_armv4l(),a_armv4tl() );
574 defCompatibleWith( a_armv5tl(), a_noarch(),a_armv3l(),a_armv4l(),a_armv4tl(),a_armv5l() );
575 defCompatibleWith( a_armv5tel(), a_noarch(),a_armv3l(),a_armv4l(),a_armv4tl(),a_armv5l(),a_armv5tl() );
576 defCompatibleWith( a_armv5tejl(), a_noarch(),a_armv3l(),a_armv4l(),a_armv4tl(),a_armv5l(),a_armv5tl(),a_armv5tel() );
577 defCompatibleWith( a_armv6l(), a_noarch(),a_armv3l(),a_armv4l(),a_armv4tl(),a_armv5l(),a_armv5tl(),a_armv5tel(),a_armv5tejl() );
578 defCompatibleWith( a_armv7l(), a_noarch(),a_armv3l(),a_armv4l(),a_armv4tl(),a_armv5l(),a_armv5tl(),a_armv5tel(),a_armv5tejl(),a_armv6l() );
579 defCompatibleWith( a_armv8l(), a_noarch(),a_armv3l(),a_armv4l(),a_armv4tl(),a_armv5l(),a_armv5tl(),a_armv5tel(),a_armv5tejl(),a_armv6l(),a_armv7l() );
581 defCompatibleWith( a_armv6hl(), a_noarch() );
582 defCompatibleWith( a_armv7hl(), a_noarch(),a_armv6hl() );
583 defCompatibleWith( a_armv8hl(), a_noarch(),a_armv7hl() );
584 defCompatibleWith( a_armv7hnl(), a_noarch(),a_armv7hl(),a_armv6hl() );
586 defCompatibleWith( a_armv7nhl(), a_noarch(),a_armv7hnl(),a_armv7hl(),a_armv6hl() );
588 defCompatibleWith( a_armv7thl(), a_noarch(),a_armv7hl() );
589 defCompatibleWith( a_armv7tnhl(), a_noarch(),a_armv7hl(),a_armv7nhl(),a_armv7thl() );
591 defCompatibleWith( a_aarch64(), a_noarch() );
593 defCompatibleWith( a_riscv64(), a_noarch() );
595 defCompatibleWith( a_sh3(), a_noarch() );
597 defCompatibleWith( a_sh4(), a_noarch() );
598 defCompatibleWith( a_sh4a(), a_noarch(),a_sh4() );
600 defCompatibleWith( a_m68k(), a_noarch() );
602 defCompatibleWith( a_mips(), a_noarch() );
603 defCompatibleWith( a_mipsel(), a_noarch() );
604 defCompatibleWith( a_mips64(), a_noarch() );
605 defCompatibleWith( a_mips64el(), a_noarch() );
607 defCompatibleWith( a_loong64(), a_noarch() );
625 ZYPP_THROW( Exception(
"Need more bits to encode architectures.") );
634 const CompatEntry & assertCompatSetEntry( IdString archStr_r )
635 {
return *_compatSet.insert( Arch::CompatEntry( archStr_r, nextIdBit() ) ).first; }
639 void defCompatibleWith( IdString targetArch_r,
651 const CompatEntry & target( assertCompatSetEntry( targetArch_r ) );
652 target.addCompatBit( assertCompatSetEntry( arch0_r )._idBit );
653#define SETARG(N) if ( arch##N##_r.empty() ) return; target.addCompatBit( assertCompatSetEntry( arch##N##_r )._idBit )
682 :
_entry( &ArchCompatSet::instance().assertDef( a_noarch() ) )
686 :
_entry( &ArchCompatSet::instance().assertDef(
IdString(id_r) ) )
690 :
_entry( &ArchCompatSet::instance().assertDef( idstr_r ) )
694 :
_entry( &ArchCompatSet::instance().assertDef( str_r ) )
698 :
_entry( &ArchCompatSet::instance().assertDef( cstr_r ) )
703 static Arch _val( _autoDetectSystemArchitecture() );
717 {
return _entry->_idStr; }
725 {
return _entry->_archStr; }
733 {
return _entry->isBuiltIn(); }
741 {
return _entry->compatibleWith( *targetArch_r.
_entry ); }
751 if (Arch_x86_64.compatibleWith(*
this))
755 if (Arch_sparc64v.compatibleWith(*
this))
757 return Arch_sparc64v;
759 if (Arch_sparc64.compatibleWith(*
this))
763 if (Arch_ppc64.compatibleWith(*
this))
767 if (Arch_s390x.compatibleWith(*
this))
773 if ( cset.size() > 2 )
775 return *(++cset.rbegin());
797 for ( ArchCompatSet::const_iterator it = ArchCompatSet::instance().begin();
798 it != ArchCompatSet::instance().end(); ++it )
800 if ( it->compatibleWith( *targetArch_r.
_entry ) )
802 ret.insert(
Arch(*it) );
#define for_(IT, BEG, END)
Convenient for-loops using iterator.
#define ZYPP_THROW(EXCPT)
Drops a logline and throws the Exception.
#define ZYPP_DEFINE_ID_HASHABLE(C)
Define hash function for id based classes.
const CompatEntry * _entry
int compare(const Arch &rhs) const
Arch comparison.
Arch()
Default ctor Arc_noarch.
static CompatSet compatSet(const Arch &targetArch_r)
Return a set of all Arch's compatibleWith a targetArch_r.
bool isBuiltIn() const
Whether this is a buitin (or known) architecture.
IdString idStr() const
String representation of Arch.
const std::string & asString() const
This is an overloaded member function, provided for convenience. It differs from the above function o...
std::set< Arch, CompareByGT< Arch > > CompatSet
Reversed arch order, best Arch first.
static Arch detectSystemArchitecture()
Determine system architecture evaluating uname and /proc/cpuinfo.
bool compatibleWith(const Arch &targetArch_r) const
Compatibility relation.
Access to the sat-pools string space.
sat::detail::IdType IdType
static const IdString Empty
Empty string.
An integral type used as BitField.
TInt value() const
Return the value.
Wrapper class for stat/lstat.
Simple lineparser: Traverse each line in a file.
bool next()
Advance to next line.
String related utilities and Regular expression matching.
boost::noncopyable NonCopyable
Ensure derived classes cannot be copied.
std::string numstring(char n, int w=0)
bool hasPrefix(const C_Str &str_r, const C_Str &prefix_r)
Return whether str_r has prefix prefix_r.
std::string form(const char *format,...) __attribute__((format(printf
Printf style construction of std::string.
Easy-to use interface to the ZYPP dependency resolver.
bool operator!=(const Capability &lhs, const Capability &rhs)
relates: Capability
bool operator==(const Capability &lhs, const Capability &rhs)
relates: Capability
const Arch Arch_empty(IdString::Empty)
std::ostream & dumpOn(std::ostream &str, const Capability &obj)
relates: Capability Detailed stream output
std::ostream & operator<<(std::ostream &str, const Capabilities &obj)
relates: Capabilities Stream output
Holds an architecture ID and its compatible relation.
void addCompatBit(const CompatBits &idBit_r) const
bool compatibleWith(const CompatEntry &targetEntry_r) const
Return whether this is compatible with targetEntry_r.
int compare(const CompatEntry &rhs) const
compare by score, then archStr.
IdString::IdType id() const
bit::BitField< uint64_t > CompatBits
Bitfield for architecture IDs and compatBits relation.
CompatEntry(IdString archStr_r, CompatBits::IntT idBit_r=1)
CompatEntry(const std::string &archStr_r, CompatBits::IntT idBit_r=1)
static const unsigned size