FSConfig.py revision 13774
14120Sgblack@eecs.umich.edu# Copyright (c) 2010-2012, 2015-2019 ARM Limited 24120Sgblack@eecs.umich.edu# All rights reserved. 34120Sgblack@eecs.umich.edu# 44120Sgblack@eecs.umich.edu# The license below extends only to copyright in the software and shall 54120Sgblack@eecs.umich.edu# not be construed as granting a license to any other intellectual 64120Sgblack@eecs.umich.edu# property including but not limited to intellectual property relating 74120Sgblack@eecs.umich.edu# to a hardware implementation of the functionality of the software 84120Sgblack@eecs.umich.edu# licensed hereunder. You may use the software subject to the license 94120Sgblack@eecs.umich.edu# terms below provided that you ensure that this notice is replicated 104120Sgblack@eecs.umich.edu# unmodified and in its entirety in all distributions of the software, 114120Sgblack@eecs.umich.edu# modified or unmodified, in source code or in binary form. 124120Sgblack@eecs.umich.edu# 134120Sgblack@eecs.umich.edu# Copyright (c) 2010-2011 Advanced Micro Devices, Inc. 144120Sgblack@eecs.umich.edu# Copyright (c) 2006-2008 The Regents of The University of Michigan 154120Sgblack@eecs.umich.edu# All rights reserved. 164120Sgblack@eecs.umich.edu# 174120Sgblack@eecs.umich.edu# Redistribution and use in source and binary forms, with or without 184120Sgblack@eecs.umich.edu# modification, are permitted provided that the following conditions are 194120Sgblack@eecs.umich.edu# met: redistributions of source code must retain the above copyright 204120Sgblack@eecs.umich.edu# notice, this list of conditions and the following disclaimer; 214120Sgblack@eecs.umich.edu# redistributions in binary form must reproduce the above copyright 224120Sgblack@eecs.umich.edu# notice, this list of conditions and the following disclaimer in the 234120Sgblack@eecs.umich.edu# documentation and/or other materials provided with the distribution; 244120Sgblack@eecs.umich.edu# neither the name of the copyright holders nor the names of its 254120Sgblack@eecs.umich.edu# contributors may be used to endorse or promote products derived from 264120Sgblack@eecs.umich.edu# this software without specific prior written permission. 274120Sgblack@eecs.umich.edu# 284120Sgblack@eecs.umich.edu# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 294120Sgblack@eecs.umich.edu# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 304120Sgblack@eecs.umich.edu# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 315334Sgblack@eecs.umich.edu# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 324120Sgblack@eecs.umich.edu# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 334120Sgblack@eecs.umich.edu# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 344120Sgblack@eecs.umich.edu# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 354120Sgblack@eecs.umich.edu# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 364120Sgblack@eecs.umich.edu# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 374120Sgblack@eecs.umich.edu# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 384120Sgblack@eecs.umich.edu# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 394120Sgblack@eecs.umich.edu# 404120Sgblack@eecs.umich.edu# Authors: Kevin Lim 414120Sgblack@eecs.umich.edu 424120Sgblack@eecs.umich.edufrom __future__ import print_function 434120Sgblack@eecs.umich.edufrom __future__ import absolute_import 444120Sgblack@eecs.umich.edu 454120Sgblack@eecs.umich.edufrom m5.objects import * 464120Sgblack@eecs.umich.edufrom m5.util import * 474120Sgblack@eecs.umich.edufrom .Benchmarks import * 484120Sgblack@eecs.umich.edufrom . import PlatformConfig 494120Sgblack@eecs.umich.edu 504120Sgblack@eecs.umich.edu# Populate to reflect supported os types per target ISA 514120Sgblack@eecs.umich.eduos_types = { 'alpha' : [ 'linux' ], 524120Sgblack@eecs.umich.edu 'mips' : [ 'linux' ], 534120Sgblack@eecs.umich.edu 'sparc' : [ 'linux' ], 544120Sgblack@eecs.umich.edu 'x86' : [ 'linux' ], 554120Sgblack@eecs.umich.edu 'arm' : [ 'linux', 564120Sgblack@eecs.umich.edu 'android-gingerbread', 574120Sgblack@eecs.umich.edu 'android-ics', 584120Sgblack@eecs.umich.edu 'android-jellybean', 594120Sgblack@eecs.umich.edu 'android-kitkat', 604120Sgblack@eecs.umich.edu 'android-nougat', ], 614120Sgblack@eecs.umich.edu } 624120Sgblack@eecs.umich.edu 634120Sgblack@eecs.umich.educlass CowIdeDisk(IdeDisk): 644120Sgblack@eecs.umich.edu image = CowDiskImage(child=RawDiskImage(read_only=True), 654120Sgblack@eecs.umich.edu read_only=False) 664120Sgblack@eecs.umich.edu 674120Sgblack@eecs.umich.edu def childImage(self, ci): 684120Sgblack@eecs.umich.edu self.image.child.image_file = ci 694120Sgblack@eecs.umich.edu 704120Sgblack@eecs.umich.educlass MemBus(SystemXBar): 714120Sgblack@eecs.umich.edu badaddr_responder = BadAddr() 724120Sgblack@eecs.umich.edu default = Self.badaddr_responder.pio 734120Sgblack@eecs.umich.edu 744120Sgblack@eecs.umich.edudef fillInCmdline(mdesc, template, **kwargs): 754120Sgblack@eecs.umich.edu kwargs.setdefault('disk', mdesc.disk()) 764120Sgblack@eecs.umich.edu kwargs.setdefault('rootdev', mdesc.rootdev()) 774120Sgblack@eecs.umich.edu kwargs.setdefault('mem', mdesc.mem()) 784120Sgblack@eecs.umich.edu kwargs.setdefault('script', mdesc.script()) 794120Sgblack@eecs.umich.edu return template % kwargs 804120Sgblack@eecs.umich.edu 814120Sgblack@eecs.umich.edudef makeLinuxAlphaSystem(mem_mode, mdesc=None, ruby=False, cmdline=None): 824120Sgblack@eecs.umich.edu 834120Sgblack@eecs.umich.edu class BaseTsunami(Tsunami): 844120Sgblack@eecs.umich.edu ethernet = NSGigE(pci_bus=0, pci_dev=1, pci_func=0) 854120Sgblack@eecs.umich.edu ide = IdeController(disks=[Parent.disk0, Parent.disk2], 864202Sbinkertn@umich.edu pci_func=0, pci_dev=0, pci_bus=0) 875069Sgblack@eecs.umich.edu 884202Sbinkertn@umich.edu self = LinuxAlphaSystem() 895659Sgblack@eecs.umich.edu if not mdesc: 904601Sgblack@eecs.umich.edu # generic system 915124Sgblack@eecs.umich.edu mdesc = SysConfig() 925083Sgblack@eecs.umich.edu self.readfile = mdesc.script() 934679Sgblack@eecs.umich.edu 946515Sgblack@eecs.umich.edu self.tsunami = BaseTsunami() 955083Sgblack@eecs.umich.edu 964679Sgblack@eecs.umich.edu # Create the io bus to connect all device ports 974679Sgblack@eecs.umich.edu self.iobus = IOXBar() 986313Sgblack@eecs.umich.edu self.tsunami.attachIO(self.iobus) 996365Sgblack@eecs.umich.edu 1005124Sgblack@eecs.umich.edu self.tsunami.ide.pio = self.iobus.master 1014249Sgblack@eecs.umich.edu 1024240Sgblack@eecs.umich.edu self.tsunami.ethernet.pio = self.iobus.master 1034202Sbinkertn@umich.edu 1044997Sgblack@eecs.umich.edu if ruby: 1055135Sgblack@eecs.umich.edu # Store the dma devices for later connection to dma ruby ports. 1064997Sgblack@eecs.umich.edu # Append an underscore to dma_ports to avoid the SimObjectVector check. 1076365Sgblack@eecs.umich.edu self._dma_ports = [self.tsunami.ide.dma, self.tsunami.ethernet.dma] 1086365Sgblack@eecs.umich.edu else: 1094997Sgblack@eecs.umich.edu self.membus = MemBus() 1105800Snate@binkert.org 1115800Snate@binkert.org # By default the bridge responds to all addresses above the I/O 1124120Sgblack@eecs.umich.edu # base address (including the PCI config space) 1134202Sbinkertn@umich.edu IO_address_space_base = 0x80000000000 1145800Snate@binkert.org self.bridge = Bridge(delay='50ns', 1155904Sgblack@eecs.umich.edu ranges = [AddrRange(IO_address_space_base, Addr.max)]) 1165904Sgblack@eecs.umich.edu self.bridge.master = self.iobus.slave 1175909Sgblack@eecs.umich.edu self.bridge.slave = self.membus.master 1185649Sgblack@eecs.umich.edu 1195647Sgblack@eecs.umich.edu self.tsunami.ide.dma = self.iobus.slave 1205132Sgblack@eecs.umich.edu self.tsunami.ethernet.dma = self.iobus.slave 1215132Sgblack@eecs.umich.edu 1224202Sbinkertn@umich.edu self.system_port = self.membus.slave 1235647Sgblack@eecs.umich.edu 1245299Sgblack@eecs.umich.edu self.mem_ranges = [AddrRange(mdesc.mem())] 1255245Sgblack@eecs.umich.edu self.disk0 = CowIdeDisk(driveID='master') 1265132Sgblack@eecs.umich.edu self.disk2 = CowIdeDisk(driveID='master') 1275086Sgblack@eecs.umich.edu self.disk0.childImage(mdesc.disk()) 1285086Sgblack@eecs.umich.edu self.disk2.childImage(disk('linux-bigswap2.img')) 1294202Sbinkertn@umich.edu self.simple_disk = SimpleDisk(disk=RawDiskImage(image_file = mdesc.disk(), 1304202Sbinkertn@umich.edu read_only = True)) 1314120Sgblack@eecs.umich.edu self.intrctrl = IntrControl() 1324202Sbinkertn@umich.edu self.mem_mode = mem_mode 1334202Sbinkertn@umich.edu self.terminal = Terminal() 1344202Sbinkertn@umich.edu self.kernel = binary('vmlinux') 1354120Sgblack@eecs.umich.edu self.pal = binary('ts_osfpal') 1365069Sgblack@eecs.umich.edu self.console = binary('console') 1375081Sgblack@eecs.umich.edu if not cmdline: 1385081Sgblack@eecs.umich.edu cmdline = 'root=/dev/hda1 console=ttyS0' 1395081Sgblack@eecs.umich.edu self.boot_osflags = fillInCmdline(mdesc, cmdline) 1405081Sgblack@eecs.umich.edu 1415081Sgblack@eecs.umich.edu return self 1425081Sgblack@eecs.umich.edu 1435081Sgblack@eecs.umich.edudef makeSparcSystem(mem_mode, mdesc=None, cmdline=None): 1445081Sgblack@eecs.umich.edu # Constants from iob.cc and uart8250.cc 1455081Sgblack@eecs.umich.edu iob_man_addr = 0x9800000000 1465081Sgblack@eecs.umich.edu uart_pio_size = 8 1475081Sgblack@eecs.umich.edu 1485081Sgblack@eecs.umich.edu class CowMmDisk(MmDisk): 1495081Sgblack@eecs.umich.edu image = CowDiskImage(child=RawDiskImage(read_only=True), 1505081Sgblack@eecs.umich.edu read_only=False) 1515081Sgblack@eecs.umich.edu 1525081Sgblack@eecs.umich.edu def childImage(self, ci): 1535081Sgblack@eecs.umich.edu self.image.child.image_file = ci 1545081Sgblack@eecs.umich.edu 1555081Sgblack@eecs.umich.edu self = SparcSystem() 1565081Sgblack@eecs.umich.edu if not mdesc: 1575081Sgblack@eecs.umich.edu # generic system 1585081Sgblack@eecs.umich.edu mdesc = SysConfig() 1595081Sgblack@eecs.umich.edu self.readfile = mdesc.script() 1605081Sgblack@eecs.umich.edu self.iobus = IOXBar() 1615081Sgblack@eecs.umich.edu self.membus = MemBus() 1625081Sgblack@eecs.umich.edu self.bridge = Bridge(delay='50ns') 1635081Sgblack@eecs.umich.edu self.t1000 = T1000() 1645081Sgblack@eecs.umich.edu self.t1000.attachOnChipIO(self.membus) 1655081Sgblack@eecs.umich.edu self.t1000.attachIO(self.iobus) 1665081Sgblack@eecs.umich.edu self.mem_ranges = [AddrRange(Addr('1MB'), size = '64MB'), 1675081Sgblack@eecs.umich.edu AddrRange(Addr('2GB'), size ='256MB')] 1685081Sgblack@eecs.umich.edu self.bridge.master = self.iobus.slave 1695081Sgblack@eecs.umich.edu self.bridge.slave = self.membus.master 1705081Sgblack@eecs.umich.edu self.rom.port = self.membus.master 1715081Sgblack@eecs.umich.edu self.nvram.port = self.membus.master 1725081Sgblack@eecs.umich.edu self.hypervisor_desc.port = self.membus.master 1735081Sgblack@eecs.umich.edu self.partition_desc.port = self.membus.master 1745081Sgblack@eecs.umich.edu self.intrctrl = IntrControl() 1755081Sgblack@eecs.umich.edu self.disk0 = CowMmDisk() 1765081Sgblack@eecs.umich.edu self.disk0.childImage(mdesc.disk()) 1775081Sgblack@eecs.umich.edu self.disk0.pio = self.iobus.master 1785081Sgblack@eecs.umich.edu 1795081Sgblack@eecs.umich.edu # The puart0 and hvuart are placed on the IO bus, so create ranges 1805081Sgblack@eecs.umich.edu # for them. The remaining IO range is rather fragmented, so poke 1815081Sgblack@eecs.umich.edu # holes for the iob and partition descriptors etc. 1825081Sgblack@eecs.umich.edu self.bridge.ranges = \ 1835081Sgblack@eecs.umich.edu [ 1845081Sgblack@eecs.umich.edu AddrRange(self.t1000.puart0.pio_addr, 1855081Sgblack@eecs.umich.edu self.t1000.puart0.pio_addr + uart_pio_size - 1), 1865081Sgblack@eecs.umich.edu AddrRange(self.disk0.pio_addr, 1875081Sgblack@eecs.umich.edu self.t1000.fake_jbi.pio_addr + 1885081Sgblack@eecs.umich.edu self.t1000.fake_jbi.pio_size - 1), 1895081Sgblack@eecs.umich.edu AddrRange(self.t1000.fake_clk.pio_addr, 1905081Sgblack@eecs.umich.edu iob_man_addr - 1), 1915081Sgblack@eecs.umich.edu AddrRange(self.t1000.fake_l2_1.pio_addr, 1925680Sgblack@eecs.umich.edu self.t1000.fake_ssi.pio_addr + 1935081Sgblack@eecs.umich.edu self.t1000.fake_ssi.pio_size - 1), 1945933Sgblack@eecs.umich.edu AddrRange(self.t1000.hvuart.pio_addr, 1955173Sgblack@eecs.umich.edu self.t1000.hvuart.pio_addr + uart_pio_size - 1) 1965359Sgblack@eecs.umich.edu ] 1975081Sgblack@eecs.umich.edu self.reset_bin = binary('reset_new.bin') 1985149Sgblack@eecs.umich.edu self.hypervisor_bin = binary('q_new.bin') 1995298Sgblack@eecs.umich.edu self.openboot_bin = binary('openboot_new.bin') 2005081Sgblack@eecs.umich.edu self.nvram_bin = binary('nvram1') 2015081Sgblack@eecs.umich.edu self.hypervisor_desc_bin = binary('1up-hv.bin') 2025081Sgblack@eecs.umich.edu self.partition_desc_bin = binary('1up-md.bin') 2035081Sgblack@eecs.umich.edu 2045081Sgblack@eecs.umich.edu self.system_port = self.membus.slave 2055081Sgblack@eecs.umich.edu 2065081Sgblack@eecs.umich.edu return self 2075081Sgblack@eecs.umich.edu 2085081Sgblack@eecs.umich.edudef makeArmSystem(mem_mode, machine_type, num_cpus=1, mdesc=None, 2095081Sgblack@eecs.umich.edu dtb_filename=None, bare_metal=False, cmdline=None, 2105081Sgblack@eecs.umich.edu external_memory="", ruby=False, security=False): 2115081Sgblack@eecs.umich.edu assert machine_type 2125081Sgblack@eecs.umich.edu 2135081Sgblack@eecs.umich.edu pci_devices = [] 2145081Sgblack@eecs.umich.edu 2155081Sgblack@eecs.umich.edu if bare_metal: 2165081Sgblack@eecs.umich.edu self = ArmSystem() 2175081Sgblack@eecs.umich.edu else: 2185081Sgblack@eecs.umich.edu self = LinuxArmSystem() 2195081Sgblack@eecs.umich.edu 2205081Sgblack@eecs.umich.edu if not mdesc: 2215081Sgblack@eecs.umich.edu # generic system 2225081Sgblack@eecs.umich.edu mdesc = SysConfig() 2235081Sgblack@eecs.umich.edu 2245081Sgblack@eecs.umich.edu self.readfile = mdesc.script() 2255081Sgblack@eecs.umich.edu self.iobus = IOXBar() 2265081Sgblack@eecs.umich.edu if not ruby: 2275081Sgblack@eecs.umich.edu self.bridge = Bridge(delay='50ns') 2285081Sgblack@eecs.umich.edu self.bridge.master = self.iobus.slave 2295081Sgblack@eecs.umich.edu self.membus = MemBus() 2305081Sgblack@eecs.umich.edu self.membus.badaddr_responder.warn_access = "warn" 2315081Sgblack@eecs.umich.edu self.bridge.slave = self.membus.master 2325081Sgblack@eecs.umich.edu 2335081Sgblack@eecs.umich.edu self.mem_mode = mem_mode 2345081Sgblack@eecs.umich.edu 2355081Sgblack@eecs.umich.edu platform_class = PlatformConfig.get(machine_type) 2365081Sgblack@eecs.umich.edu # Resolve the real platform name, the original machine_type 2375081Sgblack@eecs.umich.edu # variable might have been an alias. 2385081Sgblack@eecs.umich.edu machine_type = platform_class.__name__ 2395081Sgblack@eecs.umich.edu self.realview = platform_class() 2405081Sgblack@eecs.umich.edu 2415081Sgblack@eecs.umich.edu if isinstance(self.realview, VExpress_EMM64): 2425081Sgblack@eecs.umich.edu if os.path.split(mdesc.disk())[-1] == 'linux-aarch32-ael.img': 2435081Sgblack@eecs.umich.edu print("Selected 64-bit ARM architecture, updating default " 2445081Sgblack@eecs.umich.edu "disk image...") 2455081Sgblack@eecs.umich.edu mdesc.diskname = 'linaro-minimal-aarch64.img' 2465081Sgblack@eecs.umich.edu 2475081Sgblack@eecs.umich.edu 2485081Sgblack@eecs.umich.edu # Attach any PCI devices this platform supports 2495081Sgblack@eecs.umich.edu self.realview.attachPciDevices() 2505081Sgblack@eecs.umich.edu 2515081Sgblack@eecs.umich.edu self.cf0 = CowIdeDisk(driveID='master') 2525081Sgblack@eecs.umich.edu self.cf0.childImage(mdesc.disk()) 2535081Sgblack@eecs.umich.edu # Old platforms have a built-in IDE or CF controller. Default to 2545081Sgblack@eecs.umich.edu # the IDE controller if both exist. New platforms expect the 2555081Sgblack@eecs.umich.edu # storage controller to be added from the config script. 2565081Sgblack@eecs.umich.edu if hasattr(self.realview, "ide"): 2575081Sgblack@eecs.umich.edu self.realview.ide.disks = [self.cf0] 2585081Sgblack@eecs.umich.edu elif hasattr(self.realview, "cf_ctrl"): 2595081Sgblack@eecs.umich.edu self.realview.cf_ctrl.disks = [self.cf0] 2605081Sgblack@eecs.umich.edu else: 2615081Sgblack@eecs.umich.edu self.pci_ide = IdeController(disks=[self.cf0]) 2625081Sgblack@eecs.umich.edu pci_devices.append(self.pci_ide) 2635081Sgblack@eecs.umich.edu 2645081Sgblack@eecs.umich.edu self.mem_ranges = [] 2655081Sgblack@eecs.umich.edu size_remain = long(Addr(mdesc.mem())) 2665081Sgblack@eecs.umich.edu for region in self.realview._mem_regions: 2675081Sgblack@eecs.umich.edu if size_remain > long(region.size()): 2685081Sgblack@eecs.umich.edu self.mem_ranges.append(region) 2695081Sgblack@eecs.umich.edu size_remain = size_remain - long(region.size()) 2705081Sgblack@eecs.umich.edu else: 2715081Sgblack@eecs.umich.edu self.mem_ranges.append(AddrRange(region.start, size=size_remain)) 2725081Sgblack@eecs.umich.edu size_remain = 0 2735081Sgblack@eecs.umich.edu break 2745081Sgblack@eecs.umich.edu warn("Memory size specified spans more than one region. Creating" \ 2755081Sgblack@eecs.umich.edu " another memory controller for that range.") 2765081Sgblack@eecs.umich.edu 2775081Sgblack@eecs.umich.edu if size_remain > 0: 2785081Sgblack@eecs.umich.edu fatal("The currently selected ARM platforms doesn't support" \ 2795081Sgblack@eecs.umich.edu " the amount of DRAM you've selected. Please try" \ 2805081Sgblack@eecs.umich.edu " another platform") 2815081Sgblack@eecs.umich.edu 2825081Sgblack@eecs.umich.edu self.have_security = security 2835081Sgblack@eecs.umich.edu 2845081Sgblack@eecs.umich.edu if bare_metal: 2855081Sgblack@eecs.umich.edu # EOT character on UART will end the simulation 2865081Sgblack@eecs.umich.edu self.realview.uart[0].end_on_eot = True 2875081Sgblack@eecs.umich.edu else: 2885081Sgblack@eecs.umich.edu if dtb_filename: 2895081Sgblack@eecs.umich.edu self.dtb_filename = binary(dtb_filename) 2905081Sgblack@eecs.umich.edu 2915081Sgblack@eecs.umich.edu self.machine_type = machine_type if machine_type in ArmMachineType.map \ 2925081Sgblack@eecs.umich.edu else "DTOnly" 2935081Sgblack@eecs.umich.edu 2945081Sgblack@eecs.umich.edu # Ensure that writes to the UART actually go out early in the boot 2955081Sgblack@eecs.umich.edu if not cmdline: 2965081Sgblack@eecs.umich.edu cmdline = 'earlyprintk=pl011,0x1c090000 console=ttyAMA0 ' + \ 2975081Sgblack@eecs.umich.edu 'lpj=19988480 norandmaps rw loglevel=8 ' + \ 2985081Sgblack@eecs.umich.edu 'mem=%(mem)s root=%(rootdev)s' 2995081Sgblack@eecs.umich.edu 3005081Sgblack@eecs.umich.edu # When using external memory, gem5 writes the boot loader to nvmem 3015081Sgblack@eecs.umich.edu # and then SST will read from it, but SST can only get to nvmem from 3025081Sgblack@eecs.umich.edu # iobus, as gem5's membus is only used for initialization and 3035081Sgblack@eecs.umich.edu # SST doesn't use it. Attaching nvmem to iobus solves this issue. 3045081Sgblack@eecs.umich.edu # During initialization, system_port -> membus -> iobus -> nvmem. 3055081Sgblack@eecs.umich.edu if external_memory: 3065081Sgblack@eecs.umich.edu self.realview.setupBootLoader(self.iobus, self, binary) 3075081Sgblack@eecs.umich.edu elif ruby: 3085081Sgblack@eecs.umich.edu self.realview.setupBootLoader(None, self, binary) 3095081Sgblack@eecs.umich.edu else: 3105081Sgblack@eecs.umich.edu self.realview.setupBootLoader(self.membus, self, binary) 3115081Sgblack@eecs.umich.edu 3125081Sgblack@eecs.umich.edu if hasattr(self.realview.gic, 'cpu_addr'): 3135081Sgblack@eecs.umich.edu self.gic_cpu_addr = self.realview.gic.cpu_addr 3145081Sgblack@eecs.umich.edu 3155081Sgblack@eecs.umich.edu self.flags_addr = self.realview.realview_io.pio_addr + 0x30 3165081Sgblack@eecs.umich.edu 3175081Sgblack@eecs.umich.edu # This check is for users who have previously put 'android' in 3185081Sgblack@eecs.umich.edu # the disk image filename to tell the config scripts to 3195081Sgblack@eecs.umich.edu # prepare the kernel with android-specific boot options. That 3205081Sgblack@eecs.umich.edu # behavior has been replaced with a more explicit option per 3215081Sgblack@eecs.umich.edu # the error message below. The disk can have any name now and 3225081Sgblack@eecs.umich.edu # doesn't need to include 'android' substring. 3235081Sgblack@eecs.umich.edu if (os.path.split(mdesc.disk())[-1]).lower().count('android'): 3245081Sgblack@eecs.umich.edu if 'android' not in mdesc.os_type(): 3255081Sgblack@eecs.umich.edu fatal("It looks like you are trying to boot an Android " \ 3265081Sgblack@eecs.umich.edu "platform. To boot Android, you must specify " \ 3275081Sgblack@eecs.umich.edu "--os-type with an appropriate Android release on " \ 3285081Sgblack@eecs.umich.edu "the command line.") 3295081Sgblack@eecs.umich.edu 3305081Sgblack@eecs.umich.edu # android-specific tweaks 3315081Sgblack@eecs.umich.edu if 'android' in mdesc.os_type(): 3325081Sgblack@eecs.umich.edu # generic tweaks 3335081Sgblack@eecs.umich.edu cmdline += " init=/init" 3345081Sgblack@eecs.umich.edu 3355081Sgblack@eecs.umich.edu # release-specific tweaks 3365081Sgblack@eecs.umich.edu if 'kitkat' in mdesc.os_type(): 3375081Sgblack@eecs.umich.edu cmdline += " androidboot.hardware=gem5 qemu=1 qemu.gles=0 " + \ 3385081Sgblack@eecs.umich.edu "android.bootanim=0 " 3395081Sgblack@eecs.umich.edu elif 'nougat' in mdesc.os_type(): 3405081Sgblack@eecs.umich.edu cmdline += " androidboot.hardware=gem5 qemu=1 qemu.gles=0 " + \ 3415081Sgblack@eecs.umich.edu "android.bootanim=0 " + \ 3425081Sgblack@eecs.umich.edu "vmalloc=640MB " + \ 3435081Sgblack@eecs.umich.edu "android.early.fstab=/fstab.gem5 " + \ 3445081Sgblack@eecs.umich.edu "androidboot.selinux=permissive " + \ 3455081Sgblack@eecs.umich.edu "video=Virtual-1:1920x1080-16" 3465081Sgblack@eecs.umich.edu 3475081Sgblack@eecs.umich.edu self.boot_osflags = fillInCmdline(mdesc, cmdline) 3485081Sgblack@eecs.umich.edu 3495081Sgblack@eecs.umich.edu if external_memory: 3505081Sgblack@eecs.umich.edu # I/O traffic enters iobus 3515081Sgblack@eecs.umich.edu self.external_io = ExternalMaster(port_data="external_io", 3525081Sgblack@eecs.umich.edu port_type=external_memory) 3535081Sgblack@eecs.umich.edu self.external_io.port = self.iobus.slave 3545081Sgblack@eecs.umich.edu 3555069Sgblack@eecs.umich.edu # Ensure iocache only receives traffic destined for (actual) memory. 3564202Sbinkertn@umich.edu self.iocache = ExternalSlave(port_data="iocache", 3574202Sbinkertn@umich.edu port_type=external_memory, 3584202Sbinkertn@umich.edu addr_ranges=self.mem_ranges) 3595069Sgblack@eecs.umich.edu self.iocache.port = self.iobus.master 3605069Sgblack@eecs.umich.edu 3615069Sgblack@eecs.umich.edu # Let system_port get to nvmem and nothing else. 3625069Sgblack@eecs.umich.edu self.bridge.ranges = [self.realview.nvmem.range] 3634202Sbinkertn@umich.edu 3644202Sbinkertn@umich.edu self.realview.attachOnChipIO(self.iobus) 365 # Attach off-chip devices 366 self.realview.attachIO(self.iobus) 367 elif ruby: 368 self._dma_ports = [ ] 369 self.realview.attachOnChipIO(self.iobus, dma_ports=self._dma_ports) 370 self.realview.attachIO(self.iobus, dma_ports=self._dma_ports) 371 else: 372 self.realview.attachOnChipIO(self.membus, self.bridge) 373 # Attach off-chip devices 374 self.realview.attachIO(self.iobus) 375 376 for dev_id, dev in enumerate(pci_devices): 377 dev.pci_bus, dev.pci_dev, dev.pci_func = (0, dev_id + 1, 0) 378 self.realview.attachPciDevice( 379 dev, self.iobus, 380 dma_ports=self._dma_ports if ruby else None) 381 382 self.intrctrl = IntrControl() 383 self.terminal = Terminal() 384 self.vncserver = VncServer() 385 386 if not ruby: 387 self.system_port = self.membus.slave 388 389 if ruby: 390 if buildEnv['PROTOCOL'] == 'MI_example' and num_cpus > 1: 391 fatal("The MI_example protocol cannot implement Load/Store " 392 "Exclusive operations. Multicore ARM systems configured " 393 "with the MI_example protocol will not work properly.") 394 warn("You are trying to use Ruby on ARM, which is not working " 395 "properly yet.") 396 397 return self 398 399 400def makeLinuxMipsSystem(mem_mode, mdesc=None, cmdline=None): 401 class BaseMalta(Malta): 402 ethernet = NSGigE(pci_bus=0, pci_dev=1, pci_func=0) 403 ide = IdeController(disks=[Parent.disk0, Parent.disk2], 404 pci_func=0, pci_dev=0, pci_bus=0) 405 406 self = LinuxMipsSystem() 407 if not mdesc: 408 # generic system 409 mdesc = SysConfig() 410 self.readfile = mdesc.script() 411 self.iobus = IOXBar() 412 self.membus = MemBus() 413 self.bridge = Bridge(delay='50ns') 414 self.mem_ranges = [AddrRange('1GB')] 415 self.bridge.master = self.iobus.slave 416 self.bridge.slave = self.membus.master 417 self.disk0 = CowIdeDisk(driveID='master') 418 self.disk2 = CowIdeDisk(driveID='master') 419 self.disk0.childImage(mdesc.disk()) 420 self.disk2.childImage(disk('linux-bigswap2.img')) 421 self.malta = BaseMalta() 422 self.malta.attachIO(self.iobus) 423 self.malta.ide.pio = self.iobus.master 424 self.malta.ide.dma = self.iobus.slave 425 self.malta.ethernet.pio = self.iobus.master 426 self.malta.ethernet.dma = self.iobus.slave 427 self.simple_disk = SimpleDisk(disk=RawDiskImage(image_file = mdesc.disk(), 428 read_only = True)) 429 self.intrctrl = IntrControl() 430 self.mem_mode = mem_mode 431 self.terminal = Terminal() 432 self.kernel = binary('mips/vmlinux') 433 self.console = binary('mips/console') 434 if not cmdline: 435 cmdline = 'root=/dev/hda1 console=ttyS0' 436 self.boot_osflags = fillInCmdline(mdesc, cmdline) 437 438 self.system_port = self.membus.slave 439 440 return self 441 442def x86IOAddress(port): 443 IO_address_space_base = 0x8000000000000000 444 return IO_address_space_base + port 445 446def connectX86ClassicSystem(x86_sys, numCPUs): 447 # Constants similar to x86_traits.hh 448 IO_address_space_base = 0x8000000000000000 449 pci_config_address_space_base = 0xc000000000000000 450 interrupts_address_space_base = 0xa000000000000000 451 APIC_range_size = 1 << 12; 452 453 x86_sys.membus = MemBus() 454 455 # North Bridge 456 x86_sys.iobus = IOXBar() 457 x86_sys.bridge = Bridge(delay='50ns') 458 x86_sys.bridge.master = x86_sys.iobus.slave 459 x86_sys.bridge.slave = x86_sys.membus.master 460 # Allow the bridge to pass through: 461 # 1) kernel configured PCI device memory map address: address range 462 # [0xC0000000, 0xFFFF0000). (The upper 64kB are reserved for m5ops.) 463 # 2) the bridge to pass through the IO APIC (two pages, already contained in 1), 464 # 3) everything in the IO address range up to the local APIC, and 465 # 4) then the entire PCI address space and beyond. 466 x86_sys.bridge.ranges = \ 467 [ 468 AddrRange(0xC0000000, 0xFFFF0000), 469 AddrRange(IO_address_space_base, 470 interrupts_address_space_base - 1), 471 AddrRange(pci_config_address_space_base, 472 Addr.max) 473 ] 474 475 # Create a bridge from the IO bus to the memory bus to allow access to 476 # the local APIC (two pages) 477 x86_sys.apicbridge = Bridge(delay='50ns') 478 x86_sys.apicbridge.slave = x86_sys.iobus.master 479 x86_sys.apicbridge.master = x86_sys.membus.slave 480 x86_sys.apicbridge.ranges = [AddrRange(interrupts_address_space_base, 481 interrupts_address_space_base + 482 numCPUs * APIC_range_size 483 - 1)] 484 485 # connect the io bus 486 x86_sys.pc.attachIO(x86_sys.iobus) 487 488 x86_sys.system_port = x86_sys.membus.slave 489 490def connectX86RubySystem(x86_sys): 491 # North Bridge 492 x86_sys.iobus = IOXBar() 493 494 # add the ide to the list of dma devices that later need to attach to 495 # dma controllers 496 x86_sys._dma_ports = [x86_sys.pc.south_bridge.ide.dma] 497 x86_sys.pc.attachIO(x86_sys.iobus, x86_sys._dma_ports) 498 499 500def makeX86System(mem_mode, numCPUs=1, mdesc=None, self=None, Ruby=False): 501 if self == None: 502 self = X86System() 503 504 if not mdesc: 505 # generic system 506 mdesc = SysConfig() 507 self.readfile = mdesc.script() 508 509 self.mem_mode = mem_mode 510 511 # Physical memory 512 # On the PC platform, the memory region 0xC0000000-0xFFFFFFFF is reserved 513 # for various devices. Hence, if the physical memory size is greater than 514 # 3GB, we need to split it into two parts. 515 excess_mem_size = \ 516 convert.toMemorySize(mdesc.mem()) - convert.toMemorySize('3GB') 517 if excess_mem_size <= 0: 518 self.mem_ranges = [AddrRange(mdesc.mem())] 519 else: 520 warn("Physical memory size specified is %s which is greater than " \ 521 "3GB. Twice the number of memory controllers would be " \ 522 "created." % (mdesc.mem())) 523 524 self.mem_ranges = [AddrRange('3GB'), 525 AddrRange(Addr('4GB'), size = excess_mem_size)] 526 527 # Platform 528 self.pc = Pc() 529 530 # Create and connect the busses required by each memory system 531 if Ruby: 532 connectX86RubySystem(self) 533 else: 534 connectX86ClassicSystem(self, numCPUs) 535 536 self.intrctrl = IntrControl() 537 538 # Disks 539 disk0 = CowIdeDisk(driveID='master') 540 disk2 = CowIdeDisk(driveID='master') 541 disk0.childImage(mdesc.disk()) 542 disk2.childImage(disk('linux-bigswap2.img')) 543 self.pc.south_bridge.ide.disks = [disk0, disk2] 544 545 # Add in a Bios information structure. 546 structures = [X86SMBiosBiosInformation()] 547 self.smbios_table.structures = structures 548 549 # Set up the Intel MP table 550 base_entries = [] 551 ext_entries = [] 552 for i in range(numCPUs): 553 bp = X86IntelMPProcessor( 554 local_apic_id = i, 555 local_apic_version = 0x14, 556 enable = True, 557 bootstrap = (i == 0)) 558 base_entries.append(bp) 559 io_apic = X86IntelMPIOAPIC( 560 id = numCPUs, 561 version = 0x11, 562 enable = True, 563 address = 0xfec00000) 564 self.pc.south_bridge.io_apic.apic_id = io_apic.id 565 base_entries.append(io_apic) 566 # In gem5 Pc::calcPciConfigAddr(), it required "assert(bus==0)", 567 # but linux kernel cannot config PCI device if it was not connected to PCI bus, 568 # so we fix PCI bus id to 0, and ISA bus id to 1. 569 pci_bus = X86IntelMPBus(bus_id = 0, bus_type='PCI ') 570 base_entries.append(pci_bus) 571 isa_bus = X86IntelMPBus(bus_id = 1, bus_type='ISA ') 572 base_entries.append(isa_bus) 573 connect_busses = X86IntelMPBusHierarchy(bus_id=1, 574 subtractive_decode=True, parent_bus=0) 575 ext_entries.append(connect_busses) 576 pci_dev4_inta = X86IntelMPIOIntAssignment( 577 interrupt_type = 'INT', 578 polarity = 'ConformPolarity', 579 trigger = 'ConformTrigger', 580 source_bus_id = 0, 581 source_bus_irq = 0 + (4 << 2), 582 dest_io_apic_id = io_apic.id, 583 dest_io_apic_intin = 16) 584 base_entries.append(pci_dev4_inta) 585 def assignISAInt(irq, apicPin): 586 assign_8259_to_apic = X86IntelMPIOIntAssignment( 587 interrupt_type = 'ExtInt', 588 polarity = 'ConformPolarity', 589 trigger = 'ConformTrigger', 590 source_bus_id = 1, 591 source_bus_irq = irq, 592 dest_io_apic_id = io_apic.id, 593 dest_io_apic_intin = 0) 594 base_entries.append(assign_8259_to_apic) 595 assign_to_apic = X86IntelMPIOIntAssignment( 596 interrupt_type = 'INT', 597 polarity = 'ConformPolarity', 598 trigger = 'ConformTrigger', 599 source_bus_id = 1, 600 source_bus_irq = irq, 601 dest_io_apic_id = io_apic.id, 602 dest_io_apic_intin = apicPin) 603 base_entries.append(assign_to_apic) 604 assignISAInt(0, 2) 605 assignISAInt(1, 1) 606 for i in range(3, 15): 607 assignISAInt(i, i) 608 self.intel_mp_table.base_entries = base_entries 609 self.intel_mp_table.ext_entries = ext_entries 610 611def makeLinuxX86System(mem_mode, numCPUs=1, mdesc=None, Ruby=False, 612 cmdline=None): 613 self = LinuxX86System() 614 615 # Build up the x86 system and then specialize it for Linux 616 makeX86System(mem_mode, numCPUs, mdesc, self, Ruby) 617 618 # We assume below that there's at least 1MB of memory. We'll require 2 619 # just to avoid corner cases. 620 phys_mem_size = sum(map(lambda r: r.size(), self.mem_ranges)) 621 assert(phys_mem_size >= 0x200000) 622 assert(len(self.mem_ranges) <= 2) 623 624 entries = \ 625 [ 626 # Mark the first megabyte of memory as reserved 627 X86E820Entry(addr = 0, size = '639kB', range_type = 1), 628 X86E820Entry(addr = 0x9fc00, size = '385kB', range_type = 2), 629 # Mark the rest of physical memory as available 630 X86E820Entry(addr = 0x100000, 631 size = '%dB' % (self.mem_ranges[0].size() - 0x100000), 632 range_type = 1), 633 ] 634 635 # Mark [mem_size, 3GB) as reserved if memory less than 3GB, which force 636 # IO devices to be mapped to [0xC0000000, 0xFFFF0000). Requests to this 637 # specific range can pass though bridge to iobus. 638 if len(self.mem_ranges) == 1: 639 entries.append(X86E820Entry(addr = self.mem_ranges[0].size(), 640 size='%dB' % (0xC0000000 - self.mem_ranges[0].size()), 641 range_type=2)) 642 643 # Reserve the last 16kB of the 32-bit address space for the m5op interface 644 entries.append(X86E820Entry(addr=0xFFFF0000, size='64kB', range_type=2)) 645 646 # In case the physical memory is greater than 3GB, we split it into two 647 # parts and add a separate e820 entry for the second part. This entry 648 # starts at 0x100000000, which is the first address after the space 649 # reserved for devices. 650 if len(self.mem_ranges) == 2: 651 entries.append(X86E820Entry(addr = 0x100000000, 652 size = '%dB' % (self.mem_ranges[1].size()), range_type = 1)) 653 654 self.e820_table.entries = entries 655 656 # Command line 657 if not cmdline: 658 cmdline = 'earlyprintk=ttyS0 console=ttyS0 lpj=7999923 root=/dev/hda1' 659 self.boot_osflags = fillInCmdline(mdesc, cmdline) 660 self.kernel = binary('x86_64-vmlinux-2.6.22.9') 661 return self 662 663 664def makeDualRoot(full_system, testSystem, driveSystem, dumpfile): 665 self = Root(full_system = full_system) 666 self.testsys = testSystem 667 self.drivesys = driveSystem 668 self.etherlink = EtherLink() 669 670 if hasattr(testSystem, 'realview'): 671 self.etherlink.int0 = Parent.testsys.realview.ethernet.interface 672 self.etherlink.int1 = Parent.drivesys.realview.ethernet.interface 673 elif hasattr(testSystem, 'tsunami'): 674 self.etherlink.int0 = Parent.testsys.tsunami.ethernet.interface 675 self.etherlink.int1 = Parent.drivesys.tsunami.ethernet.interface 676 else: 677 fatal("Don't know how to connect these system together") 678 679 if dumpfile: 680 self.etherdump = EtherDump(file=dumpfile) 681 self.etherlink.dump = Parent.etherdump 682 683 return self 684 685 686def makeDistRoot(testSystem, 687 rank, 688 size, 689 server_name, 690 server_port, 691 sync_repeat, 692 sync_start, 693 linkspeed, 694 linkdelay, 695 dumpfile): 696 self = Root(full_system = True) 697 self.testsys = testSystem 698 699 self.etherlink = DistEtherLink(speed = linkspeed, 700 delay = linkdelay, 701 dist_rank = rank, 702 dist_size = size, 703 server_name = server_name, 704 server_port = server_port, 705 sync_start = sync_start, 706 sync_repeat = sync_repeat) 707 708 if hasattr(testSystem, 'realview'): 709 self.etherlink.int0 = Parent.testsys.realview.ethernet.interface 710 elif hasattr(testSystem, 'tsunami'): 711 self.etherlink.int0 = Parent.testsys.tsunami.ethernet.interface 712 else: 713 fatal("Don't know how to connect DistEtherLink to this system") 714 715 if dumpfile: 716 self.etherdump = EtherDump(file=dumpfile) 717 self.etherlink.dump = Parent.etherdump 718 719 return self 720