Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 5 additions & 2 deletions include/cpu_features_cache_info.h
Original file line number Diff line number Diff line change
Expand Up @@ -40,9 +40,12 @@ typedef struct {
int partitioning; // number of lines per sector
} CacheLevelInfo;

// Increase this value if more cache levels are needed.
// This structure is CPU-agnostic; increase CPU_FEATURES_MAX_CACHE_LEVEL if a
// backend needs to report more cache levels. On x86 it must be at least 15 so
// that ParseLeaf2 cannot overflow CacheInfo::levels: a single CPUID leaf 2 can
// report up to 15 descriptors (the AL count byte is ignored).
#ifndef CPU_FEATURES_MAX_CACHE_LEVEL
#define CPU_FEATURES_MAX_CACHE_LEVEL 10
#define CPU_FEATURES_MAX_CACHE_LEVEL 16
#endif
typedef struct {
int size;
Expand Down
18 changes: 18 additions & 0 deletions test/cpuinfo_x86_test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -1398,6 +1398,24 @@ flags : fpu mmx sse sse2 pni ssse3 sse4_1 sse4_2
EXPECT_TRUE(info.features.sse4_2);
}

// Regression test: a CPUID leaf 2 advertising the maximum number of cache/TLB
// descriptors must not overflow CacheInfo::levels.
TEST_F(CpuidX86Test, Leaf2_TooManyDescriptors_DoesNotOverflow) {
cpu().SetLeaves({
{{0x00000000, 0}, Leaf{0x00000002, 0x756E6547, 0x6C65746E, 0x49656E69}},
{{0x00000001, 0}, Leaf{0x00000F0A, 0x00010808, 0x00000000, 0x3FEBFBFF}},
// Leaf 2 encodes one descriptor per byte across its four registers (16
// bytes total). AL, the low byte of EAX, is the ignored count byte, so
// these all-0x01 registers forge 15 non-zero descriptors -- more than the
// old 10-entry CacheInfo::levels array and exactly filling the new 16.
{{0x00000002, 0}, Leaf{0x01010101, 0x01010101, 0x01010101, 0x01010101}},

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add a comment below to indicate that we're forging 16 descriptors (one per byte). AL being discarded. so 15 descriptors.

});

const auto info = GetX86CacheInfo();
// All 15 descriptors are recorded, saturating the resized levels array.
EXPECT_EQ(info.size, 15);
}

// https://www.felixcloutier.com/x86/cpuid#example-3-1--example-of-cache-and-tlb-interpretation
TEST_F(CpuidX86Test, P4_CacheInfo) {
cpu().SetLeaves({
Expand Down