@@ -41,8 +41,28 @@ import (
41
41
42
42
const (
43
43
networkNamespaceRuncName = "network"
44
+ cacheTopologyPath = "/sys/devices/system/cpu/cpu0/cache"
45
+ cacheFolderPrefix = "index"
44
46
)
45
47
48
+ var cacheTopologyPaths = []string {
49
+ "sys" ,
50
+ "devices" ,
51
+ "system" ,
52
+ "cpu" ,
53
+ "cpu0" ,
54
+ "cache" ,
55
+ }
56
+
57
+ var cacheTopologyFiles = []string {
58
+ "level" ,
59
+ "type" ,
60
+ "size" ,
61
+ "number_of_sets" ,
62
+ "shared_cpu_map" ,
63
+ "coherency_line_size" ,
64
+ }
65
+
46
66
// runcJailer uses runc to set up a jailed environment for the Firecracker VM.
47
67
type runcJailer struct {
48
68
ctx context.Context
@@ -255,6 +275,10 @@ func (j *runcJailer) BuildJailedRootHandler(cfg *config.Config, machineConfig *f
255
275
m .Cfg .VsockDevices [i ] = v
256
276
}
257
277
278
+ if err := j .setupCacheTopology (rootPath ); err != nil {
279
+ return err
280
+ }
281
+
258
282
j .logger .Debugf ("Writing %q for runc" , rootPathToConfig )
259
283
// we pass m.Cfg as opposed to machineConfig as we want the populated
260
284
// config defaults when calling NewMachine
@@ -640,3 +664,57 @@ func (j runcJailer) Stop(force bool) error {
640
664
}
641
665
return j .runcClient .Kill (j .ctx , j .vmID , int (signal ), & runc.KillOpts {All : true })
642
666
}
667
+
668
+ // setupCacheTopology will copy indexed contents from the cacheTopologyPath to
669
+ // the jailer. This is needed for arm architecture as arm does not
670
+ // automatically setup any cache topology
671
+ func (j runcJailer ) setupCacheTopology (path string ) error {
672
+ j .logger .WithField ("path" , path ).Debug ("Creating cache topology" )
673
+ const mode = os .FileMode (0700 )
674
+
675
+ // builds the cache topology path from the root directory
676
+ for _ , p := range cacheTopologyPaths {
677
+ path = filepath .Join (path , p )
678
+ if err := mkdirAndChown (path , mode , j .Config .UID , j .Config .GID ); err != nil {
679
+ return err
680
+ }
681
+ }
682
+
683
+ err := filepath .Walk (cacheTopologyPath , func (cachePath string , info os.FileInfo , err error ) error {
684
+ if err != nil {
685
+ return err
686
+ }
687
+ if ! info .IsDir () {
688
+ return nil
689
+ }
690
+
691
+ folder := filepath .Base (cachePath )
692
+ if ! strings .HasPrefix (folder , cacheFolderPrefix ) {
693
+ return nil
694
+ }
695
+
696
+ indexPath := filepath .Join (path , folder )
697
+ if err := mkdirAndChown (indexPath , info .Mode (), j .Config .UID , j .Config .GID ); err != nil {
698
+ return err
699
+ }
700
+
701
+ j .logger .WithField ("src path" , cachePath ).WithField ("dst path" , indexPath ).Debug ("copying cache folder" )
702
+ for _ , file := range cacheTopologyFiles {
703
+ cacheFilePath := filepath .Join (cachePath , file )
704
+ info , err := os .Stat (cacheFilePath )
705
+ if err != nil {
706
+ return err
707
+ }
708
+
709
+ // This is suppose to be a hard copy as intructed by the Firecracker team.
710
+ // Bind mounting here may cause some issues on the host's machine
711
+ if err := j .copyFileToJail (cacheFilePath , filepath .Join (indexPath , file ), info .Mode ()); err != nil {
712
+ return err
713
+ }
714
+ }
715
+
716
+ return nil
717
+ })
718
+
719
+ return err
720
+ }
0 commit comments