Skip to content

Commit ee9e78b

Browse files
committed
CPU templates are only available for Intel's x86_64 processors
It doesn't work AMD's x86_64 processors sadly. Fixes #525. Signed-off-by: Kazuyoshi Kato <[email protected]>
1 parent 6b96db7 commit ee9e78b

File tree

7 files changed

+136
-16
lines changed

7 files changed

+136
-16
lines changed

config/config.go

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,12 @@ func LoadConfig(path string) (*Config, error) {
9393
RuncConfigPath: runcConfigPath,
9494
},
9595
}
96-
if internal.SupportCPUTemplate() {
96+
97+
flag, err := internal.SupportCPUTemplate()
98+
if err != nil {
99+
return nil, err
100+
}
101+
if flag {
97102
cfg.CPUTemplate = string(defaultCPUTemplate)
98103
}
99104

internal/common.go

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,6 @@ import (
1717
"bytes"
1818
"fmt"
1919
"io"
20-
"runtime"
2120
)
2221

2322
const (
@@ -126,9 +125,3 @@ func GenerateStubContent(id string) (string, error) {
126125

127126
return fmt.Sprintf("%s%c%s", MagicStubBytes, byte(length), id), nil
128127
}
129-
130-
// SupportCPUTemplate returns true if Firecracker supports CPU templates on
131-
// the current architecture.
132-
func SupportCPUTemplate() bool {
133-
return runtime.GOARCH == "amd64"
134-
}

internal/cpu_template.go

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License"). You may
4+
// not use this file except in compliance with the License. A copy of the
5+
// License is located at
6+
//
7+
// http://aws.amazon.com/apache2.0/
8+
//
9+
// or in the "license" file accompanying this file. This file is distributed
10+
// on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
11+
// express or implied. See the License for the specific language governing
12+
// permissions and limitations under the License.
13+
14+
package internal
15+
16+
import (
17+
"bufio"
18+
"io"
19+
"os"
20+
"regexp"
21+
"runtime"
22+
"sync"
23+
)
24+
25+
var (
26+
isIntel bool
27+
isIntelOnce sync.Once
28+
)
29+
30+
// SupportCPUTemplate returns true if Firecracker supports CPU templates on
31+
// the current architecture.
32+
func SupportCPUTemplate() (bool, error) {
33+
if runtime.GOARCH != "amd64" {
34+
return false, nil
35+
}
36+
37+
var err error
38+
isIntelOnce.Do(func() {
39+
isIntel, err = checkIsIntel()
40+
})
41+
return isIntel, err
42+
}
43+
44+
var vendorID = regexp.MustCompile(`^vendor_id\s*:\s*(.+)$`)
45+
46+
func checkIsIntel() (bool, error) {
47+
f, err := os.Open("/proc/cpuinfo")
48+
if err != nil {
49+
return false, err
50+
}
51+
defer f.Close()
52+
53+
id, err := findFirstVendorID(f)
54+
if err != nil {
55+
return false, err
56+
}
57+
58+
return id == "GenuineIntel", nil
59+
}
60+
61+
func findFirstVendorID(r io.Reader) (string, error) {
62+
s := bufio.NewScanner(r)
63+
for s.Scan() {
64+
line := s.Text()
65+
matches := vendorID.FindStringSubmatch(line)
66+
if len(matches) == 2 {
67+
return matches[1], nil
68+
}
69+
}
70+
return "", nil
71+
}

internal/cpu_template_test.go

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License"). You may
4+
// not use this file except in compliance with the License. A copy of the
5+
// License is located at
6+
//
7+
// http://aws.amazon.com/apache2.0/
8+
//
9+
// or in the "license" file accompanying this file. This file is distributed
10+
// on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
11+
// express or implied. See the License for the specific language governing
12+
// permissions and limitations under the License.
13+
14+
package internal
15+
16+
import (
17+
"strings"
18+
"testing"
19+
20+
"github.com/stretchr/testify/assert"
21+
"github.com/stretchr/testify/require"
22+
)
23+
24+
func TestFindFirstVendorID(t *testing.T) {
25+
cases := []struct {
26+
input string
27+
vendorID string
28+
}{
29+
{"vendor_id : GenuineIntel", "GenuineIntel"},
30+
{"vendor_id : AuthenticAMD", "AuthenticAMD"},
31+
32+
// aarch64 doesn't have vendor IDs.
33+
{"", ""},
34+
}
35+
for _, c := range cases {
36+
r := strings.NewReader(c.input)
37+
id, err := findFirstVendorID(r)
38+
require.NoError(t, err)
39+
assert.Equal(t, c.vendorID, id)
40+
}
41+
}

runtime/helpers.go

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,6 @@ import (
2323
models "github.com/firecracker-microvm/firecracker-go-sdk/client/models"
2424

2525
"github.com/firecracker-microvm/firecracker-containerd/config"
26-
"github.com/firecracker-microvm/firecracker-containerd/internal"
2726
"github.com/firecracker-microvm/firecracker-containerd/proto"
2827
)
2928

@@ -34,12 +33,10 @@ const (
3433

3534
func machineConfigurationFromProto(cfg *config.Config, req *proto.FirecrackerMachineConfiguration) models.MachineConfiguration {
3635
config := models.MachineConfiguration{
37-
VcpuCount: firecracker.Int64(defaultCPUCount),
38-
MemSizeMib: firecracker.Int64(defaultMemSizeMb),
39-
HtEnabled: firecracker.Bool(cfg.HtEnabled),
40-
}
41-
if internal.SupportCPUTemplate() {
42-
config.CPUTemplate = models.CPUTemplate(cfg.CPUTemplate)
36+
CPUTemplate: models.CPUTemplate(cfg.CPUTemplate),
37+
VcpuCount: firecracker.Int64(defaultCPUCount),
38+
MemSizeMib: firecracker.Int64(defaultMemSizeMb),
39+
HtEnabled: firecracker.Bool(cfg.HtEnabled),
4340
}
4441

4542
if req == nil {

runtime/integ_test.go

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,12 @@ var defaultRuntimeConfig = config.Config{
4747
}
4848

4949
func init() {
50-
if internal.SupportCPUTemplate() {
50+
flag, err := internal.SupportCPUTemplate()
51+
if err != nil {
52+
panic(err)
53+
}
54+
55+
if flag {
5156
defaultRuntimeConfig.CPUTemplate = "T2"
5257
}
5358
}

runtime/service.go

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -967,6 +967,14 @@ func (s *service) buildVMConfiguration(req *proto.CreateVMRequest) (*firecracker
967967
VMID: s.vmID,
968968
}
969969

970+
flag, err := internal.SupportCPUTemplate()
971+
if err != nil {
972+
return nil, err
973+
}
974+
if !flag {
975+
cfg.MachineCfg.CPUTemplate = ""
976+
}
977+
970978
logPath := s.shimDir.FirecrackerLogFifoPath()
971979
if req.LogFifoPath != "" {
972980
logPath = req.LogFifoPath

0 commit comments

Comments
 (0)