1 /* 2 * Copyright (C) 2021 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 #pragma once 17 18 #include <string> 19 #include <unordered_map> 20 #include <vector> 21 22 #include "common/libs/fs/shared_fd.h" 23 #include "common/libs/utils/result.h" 24 #include "host/libs/config/command_source.h" 25 #include "host/libs/vm_manager/vm_manager.h" 26 27 namespace cuttlefish { 28 namespace vm_manager { 29 30 // Starts a guest VM using the gem5 command directly. It requires the host 31 // package to support the gem5 capability. 32 class Gem5Manager : public VmManager { 33 public: name()34 static std::string name() { return "gem5"; } 35 36 Gem5Manager(Arch); 37 virtual ~Gem5Manager() = default; 38 39 bool IsSupported() override; 40 41 Result<std::unordered_map<std::string, std::string>> ConfigureGraphics( 42 const CuttlefishConfig::InstanceSpecific& instance) override; 43 44 Result<std::unordered_map<std::string, std::string>> ConfigureBootDevices( 45 int num_disks, bool have_gpu) override; 46 47 Result<std::vector<MonitorCommand>> StartCommands( 48 const CuttlefishConfig& config) override; 49 50 private: 51 Arch arch_; 52 }; 53 54 const std::string fs_header = R"CPP_STR_END(import argparse 55 import devices 56 import os 57 import shutil 58 import m5 59 from m5.util import addToPath 60 from m5.objects import * 61 from m5.options import * 62 from m5.objects.Ethernet import NSGigE, IGbE_igb, IGbE_e1000, EtherTap 63 from common import SysPaths 64 from common import ObjectList 65 from common import MemConfig 66 from common.cores.arm import HPI 67 m5.util.addToPath('../..') 68 )CPP_STR_END"; 69 70 const std::string fs_mem_pci = R"CPP_STR_END( 71 MemConfig.config_mem(args, root.system) 72 73 pci_devices = [] 74 pci_devices.append(PciVirtIO(vio=VirtIOConsole(device=Terminal(number=0)))) 75 pci_devices.append(PciVirtIO(vio=VirtIOConsole(device=Terminal(number=1, outfile="none")))) 76 pci_devices.append(PciVirtIO(vio=VirtIOConsole(device=Terminal(number=2)))) 77 pci_devices.append(PciVirtIO(vio=VirtIOConsole(device=Terminal(number=3, outfile="none")))) 78 pci_devices.append(PciVirtIO(vio=VirtIOConsole(device=Terminal(number=4, outfile="none")))) 79 pci_devices.append(PciVirtIO(vio=VirtIOConsole(device=Terminal(number=5, outfile="none")))) 80 pci_devices.append(PciVirtIO(vio=VirtIOConsole(device=Terminal(number=6, outfile="none")))) 81 pci_devices.append(PciVirtIO(vio=VirtIOConsole(device=Terminal(number=7, outfile="none")))) 82 pci_devices.append(PciVirtIO(vio=VirtIOConsole(device=Terminal(number=8, outfile="none")))) 83 pci_devices.append(PciVirtIO(vio=VirtIOConsole(device=Terminal(number=9, outfile="none")))) 84 85 for each_item in args.disk_image: 86 disk_image = CowDiskImage() 87 disk_image.child.image_file = SysPaths.disk(each_item) 88 pci_devices.append(PciVirtIO(vio=VirtIOBlock(image=disk_image))) 89 90 nic = IGbE_e1000(pci_bus=0, pci_dev=0, pci_func=0, InterruptLine=1, InterruptPin=1) 91 pci_devices.append(nic) 92 root.system.pci_devices = pci_devices 93 for pci_device in root.system.pci_devices: 94 root.system.attach_pci(pci_device) 95 96 root.tap = EtherTap(tun_clone_device='/dev/net/tun', tap_device_name='cvd-mtap-01') 97 root.tap.tap = nic.interface 98 root.system.connect() 99 )CPP_STR_END"; 100 101 const std::string fs_kernel_cmd = R"CPP_STR_END( 102 kernel_cmd = [ 103 "lpj=19988480", 104 "norandmaps", 105 "mem=%s" % args.mem_size, 106 "console=hvc0", 107 "panic=-1", 108 "earlycon=pl011,mmio32,0x1c090000", 109 "audit=1", 110 "printk.devkmsg=on", 111 "firmware_class.path=/vendor/etc/", 112 "kfence.sample_interval=500", 113 "loop.max_part=7", 114 "bootconfig", 115 "androidboot.force_normal_boot=1", 116 ] 117 root.system.workload.command_line = " ".join(kernel_cmd) 118 if args.restore is not None: 119 m5.instantiate(args.restore) 120 else: 121 m5.instantiate() 122 123 while True: 124 event = m5.simulate() 125 msg = event.getCause() 126 cur_tick = m5.curTick() 127 if msg == "checkpoint": 128 backup_path = backup_path = os.path.join(root_dir, "gem5_checkpoint") 129 if not os.path.isdir(backup_path): 130 os.mkdir(backup_path) 131 132 print("Checkpoint @", cur_tick) 133 src_dir = os.path.join(m5.options.outdir, "cpt.%d" % cur_tick) 134 backup_path = os.path.join(backup_path, "cpt.%d" % cur_tick) 135 m5.checkpoint(src_dir) 136 shutil.copytree(src_dir, backup_path) 137 print("Checkpoint done.") 138 else: 139 print("Exit msg: " + msg + " @", cur_tick) 140 break 141 sys.exit(event.getCode()) 142 )CPP_STR_END"; 143 144 const std::string fs_exe_main = R"CPP_STR_END( 145 if __name__ == "__m5_main__": 146 main() 147 )CPP_STR_END"; 148 149 } // namespace vm_manager 150 } // namespace cuttlefish 151