From f84a0134072cfd50496a98b125f7290484a8f51c Mon Sep 17 00:00:00 2001 From: Jamie Liu Date: Fri, 10 May 2024 15:35:45 -0700 Subject: [PATCH] procfs: add topology-related x86 cpuinfo fields Linux prints these fields when the kernel is built with support for multiple processors/cores (CONFIG_SMP), in arch/x86/kernel/cpu/proc.c:show_cpuinfo_core(). Fixes #10205 PiperOrigin-RevId: 632621375 --- pkg/cpuid/cpuid_amd64.go | 8 +++++++- pkg/cpuid/cpuid_arm64.go | 2 +- pkg/sentry/fsimpl/proc/tasks.go | 2 +- test/syscalls/linux/proc.cc | 6 ++++++ 4 files changed, 15 insertions(+), 3 deletions(-) diff --git a/pkg/cpuid/cpuid_amd64.go b/pkg/cpuid/cpuid_amd64.go index 178428d44..f444210cd 100644 --- a/pkg/cpuid/cpuid_amd64.go +++ b/pkg/cpuid/cpuid_amd64.go @@ -309,7 +309,7 @@ func (fs FeatureSet) HasFeature(feature Feature) bool { // WriteCPUInfoTo is to generate a section of one cpu in /proc/cpuinfo. This is // a minimal /proc/cpuinfo, it is missing some fields like "microcode" that are // not always printed in Linux. The bogomips field is simply made up. -func (fs FeatureSet) WriteCPUInfoTo(cpu uint, w io.Writer) { +func (fs FeatureSet) WriteCPUInfoTo(cpu, numCPU uint, w io.Writer) { // Avoid many redundant calls here, since this can occasionally appear // in the hot path. Read all basic information up front, see above. ax, _, _, _ := fs.query(featureInfo) @@ -322,6 +322,12 @@ func (fs FeatureSet) WriteCPUInfoTo(cpu uint, w io.Writer) { fmt.Fprintf(w, "model name\t: %s\n", "unknown") // Unknown for now. fmt.Fprintf(w, "stepping\t: %s\n", "unknown") // Unknown for now. fmt.Fprintf(w, "cpu MHz\t\t: %.3f\n", cpuFreqMHz) + fmt.Fprintf(w, "physical id\t: 0\n") // Pretend all CPUs are in the same socket. + fmt.Fprintf(w, "siblings\t: %d\n", numCPU) + fmt.Fprintf(w, "core id\t\t: %d\n", cpu) + fmt.Fprintf(w, "cpu cores\t: %d\n", numCPU) // Pretend each CPU is a distinct core (rather than a hyperthread). + fmt.Fprintf(w, "apicid\t\t: %d\n", cpu) + fmt.Fprintf(w, "initial apicid\t: %d\n", cpu) fmt.Fprintf(w, "fpu\t\t: yes\n") fmt.Fprintf(w, "fpu_exception\t: yes\n") fmt.Fprintf(w, "cpuid level\t: %d\n", uint32(xSaveInfo)) // Same as ax in vendorID. diff --git a/pkg/cpuid/cpuid_arm64.go b/pkg/cpuid/cpuid_arm64.go index 7a22e98b3..964f33acb 100644 --- a/pkg/cpuid/cpuid_arm64.go +++ b/pkg/cpuid/cpuid_arm64.go @@ -92,7 +92,7 @@ func (fs FeatureSet) HasFeature(feature Feature) bool { // WriteCPUInfoTo is to generate a section of one cpu in /proc/cpuinfo. This is // a minimal /proc/cpuinfo, and the bogomips field is simply made up. -func (fs FeatureSet) WriteCPUInfoTo(cpu uint, w io.Writer) { +func (fs FeatureSet) WriteCPUInfoTo(cpu, numCPU uint, w io.Writer) { fmt.Fprintf(w, "processor\t: %d\n", cpu) fmt.Fprintf(w, "BogoMIPS\t: %.02f\n", fs.cpuFreqMHz) // It's bogus anyway. fmt.Fprintf(w, "Features\t\t: %s\n", fs.FlagString()) diff --git a/pkg/sentry/fsimpl/proc/tasks.go b/pkg/sentry/fsimpl/proc/tasks.go index b3239f8bd..36cc34d65 100644 --- a/pkg/sentry/fsimpl/proc/tasks.go +++ b/pkg/sentry/fsimpl/proc/tasks.go @@ -266,7 +266,7 @@ func cpuInfoData(k *kernel.Kernel) string { features := k.FeatureSet() var buf bytes.Buffer for i, max := uint(0), k.ApplicationCores(); i < max; i++ { - features.WriteCPUInfoTo(i, &buf) + features.WriteCPUInfoTo(i, max, &buf) } return buf.String() } diff --git a/test/syscalls/linux/proc.cc b/test/syscalls/linux/proc.cc index 59ffe0a4c..cf77088df 100644 --- a/test/syscalls/linux/proc.cc +++ b/test/syscalls/linux/proc.cc @@ -131,6 +131,12 @@ static const char* required_fields[] = { "model name", "stepping", "cpu MHz", + "physical id", + "siblings", + "core id", + "cpu cores", + "apicid\t\t:", + "initial apicid", "fpu\t\t:", "fpu_exception", "cpuid level",