From 0ea4313255ff5a00e97d82798a62f134d998fc95 Mon Sep 17 00:00:00 2001 From: "Bobby R. Bruce" Date: Thu, 5 Mar 2020 11:56:11 -0800 Subject: [PATCH] tests: Migrated 10.linux-boot scons-based test to testlib This test has purposely been designed to be easily extendible for future x86 boot tests. Right now, it only runs two basic Ubuntu boot test setups. Change-Id: I81385b5dfc0764af2ec02999eb26e523bd09a595 Issue-on: https://gem5.atlassian.net/browse/GEM5-109 Reviewed-on: https://gem5-review.googlesource.com/c/public/gem5/+/26324 Reviewed-by: Jason Lowe-Power Maintainer: Jason Lowe-Power Tested-by: kokoro --- tests/gem5/x86-boot-tests/run_exit.py | 79 +++++ tests/gem5/x86-boot-tests/system/caches.py | 143 ++++++++ tests/gem5/x86-boot-tests/system/system.py | 322 +++++++++++++++++++ tests/gem5/x86-boot-tests/test_linux_boot.py | 72 +++++ 4 files changed, 616 insertions(+) create mode 100644 tests/gem5/x86-boot-tests/run_exit.py create mode 100755 tests/gem5/x86-boot-tests/system/caches.py create mode 100755 tests/gem5/x86-boot-tests/system/system.py create mode 100644 tests/gem5/x86-boot-tests/test_linux_boot.py diff --git a/tests/gem5/x86-boot-tests/run_exit.py b/tests/gem5/x86-boot-tests/run_exit.py new file mode 100644 index 000000000..24edcc528 --- /dev/null +++ b/tests/gem5/x86-boot-tests/run_exit.py @@ -0,0 +1,79 @@ +# Copyright (c) 2016 Jason Lowe-Power +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer; +# redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution; +# neither the name of the copyright holders nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +import argparse +import sys +import os + +import m5 +import m5.ticks +from m5.objects import * + +sys.path.append(os.path.dirname(__file__) + '/system') +sys.path.append(os.path.dirname(__file__) + '/../../../configs/common/') +from system import * + +parser = argparse.ArgumentParser(description="") +parser.add_argument('--kernel', type=str) +parser.add_argument('--disk', type=str) +parser.add_argument('--cpu-type', choices=['atomic', 'kvm', 'o3', 'simple',]) +parser.add_argument('--num-cpus', type=int) +parser.add_argument('--boot-type', choices=['init', 'systemd',]) + +#(options, args) = parser.parse_args() +args = parser.parse_args() + +# create the system we are going to simulate +system = MySystem(args.kernel, args.disk, args.cpu_type, args.num_cpus) + +if args.boot_type == "init": + # Simply run "exit.sh" + system.boot_osflags += ' init=/root/exit.sh' +else: + if args.boot_type != "systemd": + m5.fatal("Bad option for boot_type. init or systemd.") + +# set up the root SimObject and start the simulation +root = Root(full_system = True, system = system) + +if system.getHostParallel(): + # Required for running kvm on multiple host cores. + # Uses gem5's parallel event queue feature + # Note: The simulator is quite picky about this number! + root.sim_quantum = int(1e9) # 1 ms + +# instantiate all of the objects we've created above +m5.instantiate() + +print("Running the simulation") +exit_event = m5.simulate() + +if exit_event.getCause() != "m5_exit instruction encountered": + print("Failed to exit correctly") + exit(1) +else: + print("Success!") + exit(0) diff --git a/tests/gem5/x86-boot-tests/system/caches.py b/tests/gem5/x86-boot-tests/system/caches.py new file mode 100755 index 000000000..2c2e520e7 --- /dev/null +++ b/tests/gem5/x86-boot-tests/system/caches.py @@ -0,0 +1,143 @@ +# Copyright (c) 2016 Jason Lowe-Power +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer; +# redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution; +# neither the name of the copyright holders nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +""" Caches with options for a simple gem5 configuration script + +This file contains L1 I/D and L2 caches to be used in the simple +gem5 configuration script. +""" + +import m5 +from m5.objects import Cache, L2XBar, StridePrefetcher, SubSystem +from m5.params import AddrRange, AllMemory, MemorySize +from m5.util.convert import toMemorySize + +# Some specific options for caches +# For all options see src/mem/cache/BaseCache.py + +class PrefetchCache(Cache): + + def __init__(self, options): + super(PrefetchCache, self).__init__() + +class L1Cache(PrefetchCache): + """Simple L1 Cache with default values""" + + assoc = 8 + tag_latency = 1 + data_latency = 1 + response_latency = 1 + mshrs = 16 + tgts_per_mshr = 20 + writeback_clean = True + + def __init__(self, options=None): + super(L1Cache, self).__init__(options) + pass + + def connectBus(self, bus): + """Connect this cache to a memory-side bus""" + self.mem_side = bus.slave + + def connectCPU(self, cpu): + """Connect this cache's port to a CPU-side port + This must be defined in a subclass""" + raise NotImplementedError + +class L1ICache(L1Cache): + """Simple L1 instruction cache with default values""" + + # Set the size + size = '32kB' + + def __init__(self, opts=None): + super(L1ICache, self).__init__(opts) + + def connectCPU(self, cpu): + """Connect this cache's port to a CPU icache port""" + self.cpu_side = cpu.icache_port + +class L1DCache(L1Cache): + """Simple L1 data cache with default values""" + + # Set the size + size = '32kB' + + def __init__(self, opts=None): + super(L1DCache, self).__init__(opts) + + def connectCPU(self, cpu): + """Connect this cache's port to a CPU dcache port""" + self.cpu_side = cpu.dcache_port + +class MMUCache(Cache): + # Default parameters + size = '8kB' + assoc = 4 + tag_latency = 1 + data_latency = 1 + response_latency = 1 + mshrs = 20 + tgts_per_mshr = 12 + writeback_clean = True + + def __init__(self): + super(MMUCache, self).__init__() + + def connectCPU(self, cpu): + """Connect the CPU itb and dtb to the cache + Note: This creates a new crossbar + """ + self.mmubus = L2XBar() + self.cpu_side = self.mmubus.master + for tlb in [cpu.itb, cpu.dtb]: + self.mmubus.slave = tlb.walker.port + + def connectBus(self, bus): + """Connect this cache to a memory-side bus""" + self.mem_side = bus.slave + +class L2Cache(PrefetchCache): + """Simple L2 Cache with default values""" + + # Default parameters + size = '256kB' + assoc = 16 + tag_latency = 10 + data_latency = 10 + response_latency = 1 + mshrs = 20 + tgts_per_mshr = 12 + writeback_clean = True + + def __init__(self, opts=None): + super(L2Cache, self).__init__(opts) + + def connectCPUSideBus(self, bus): + self.cpu_side = bus.master + + def connectMemSideBus(self, bus): + self.mem_side = bus.slave diff --git a/tests/gem5/x86-boot-tests/system/system.py b/tests/gem5/x86-boot-tests/system/system.py new file mode 100755 index 000000000..0b69be970 --- /dev/null +++ b/tests/gem5/x86-boot-tests/system/system.py @@ -0,0 +1,322 @@ +# Copyright (c) 2016 Jason Lowe-Power +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer; +# redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution; +# neither the name of the copyright holders nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +import m5 +from m5.objects import * +from m5.util import convert +from caches import * +import sys + +class MySystem(LinuxX86System): + + def __init__(self, kernel, disk, cpu_type, num_cpus): + super(MySystem, self).__init__() + + self._host_parallel = cpu_type == "kvm" + + # Set up the clock domain and the voltage domain + self.clk_domain = SrcClockDomain() + self.clk_domain.clock = '3GHz' + self.clk_domain.voltage_domain = VoltageDomain() + + self.mem_ranges = [AddrRange(Addr('3GB')), # All data + AddrRange(0xC0000000, size=0x100000), # For I/0 + ] + + # Create the main memory bus + # This connects to main memory + self.membus = SystemXBar(width = 64) # 64-byte width + self.membus.badaddr_responder = BadAddr() + self.membus.default = Self.badaddr_responder.pio + + # Set up the system port for functional access from the simulator + self.system_port = self.membus.slave + + self.initFS(self.membus, num_cpus) + + # Replace these paths with the path to your disk images. + # The first disk is the root disk. The second could be used for swap + # or anything else. + self.setDiskImages(disk, disk) + + # Change this path to point to the kernel you want to use + self.kernel = kernel + # Options specified on the kernel command line + boot_options = ['earlyprintk=ttyS0', 'console=ttyS0', 'lpj=7999923', + 'root=/dev/hda1'] + + self.boot_osflags = ' '.join(boot_options) + + # Create the CPUs for our system. + self.createCPU(cpu_type, num_cpus) + + # Create the cache heirarchy for the system. + self.createCacheHierarchy() + + # Set up the interrupt controllers for the system (x86 specific) + self.setupInterrupts() + + self.createMemoryControllersDDR3() + + if self._host_parallel: + # To get the KVM CPUs to run on different host CPUs + # Specify a different event queue for each CPU + for i,cpu in enumerate(self.cpu): + for obj in cpu.descendants(): + obj.eventq_index = 0 + cpu.eventq_index = i + 1 + + def getHostParallel(self): + return self._host_parallel + + def totalInsts(self): + return sum([cpu.totalInsts() for cpu in self.cpu]) + + def createCPU(self, cpu_type, num_cpus): + if cpu_type == "atomic": + self.cpu = [AtomicSimpleCPU(cpu_id = i) + for i in range(num_cpus)] + self.mem_mode = 'atomic' + elif cpu_type == "kvm": + # Note KVM needs a VM and atomic_noncaching + self.cpu = [X86KvmCPU(cpu_id = i) + for i in range(num_cpus)] + self.kvm_vm = KvmVM() + self.mem_mode = 'atomic_noncaching' + elif cpu_type == "o3": + self.cpu = [DerivO3CPU(cpu_id = i) + for i in range(num_cpus)] + self.mem_mode = 'timing' + elif cpu_type == "simple": + self.cpu = [TimingSimpleCPU(cpu_id = i) + for i in range(num_cpus)] + self.mem_mode = 'timing' + else: + m5.fatal("No CPU type {}".format(cpu_type)) + + map(lambda c: c.createThreads(), self.cpu) + + def setDiskImages(self, img_path_1, img_path_2): + disk0 = CowDisk(img_path_1) + disk2 = CowDisk(img_path_2) + self.pc.south_bridge.ide.disks = [disk0, disk2] + + def createCacheHierarchy(self): + for cpu in self.cpu: + # Create a memory bus, a coherent crossbar, in this case + cpu.l2bus = L2XBar() + + # Create an L1 instruction and data cache + cpu.icache = L1ICache() + cpu.dcache = L1DCache() + cpu.mmucache = MMUCache() + + # Connect the instruction and data caches to the CPU + cpu.icache.connectCPU(cpu) + cpu.dcache.connectCPU(cpu) + cpu.mmucache.connectCPU(cpu) + + # Hook the CPU ports up to the l2bus + cpu.icache.connectBus(cpu.l2bus) + cpu.dcache.connectBus(cpu.l2bus) + cpu.mmucache.connectBus(cpu.l2bus) + + # Create an L2 cache and connect it to the l2bus + cpu.l2cache = L2Cache() + cpu.l2cache.connectCPUSideBus(cpu.l2bus) + + # Connect the L2 cache to the L3 bus + cpu.l2cache.connectMemSideBus(self.membus) + + def setupInterrupts(self): + for cpu in self.cpu: + # create the interrupt controller CPU and connect to the membus + cpu.createInterruptController() + + # For x86 only, connect interrupts to the memory + # Note: these are directly connected to the memory bus and + # not cached + cpu.interrupts[0].pio = self.membus.master + cpu.interrupts[0].int_master = self.membus.slave + cpu.interrupts[0].int_slave = self.membus.master + + + def createMemoryControllersDDR3(self): + self._createMemoryControllers(1, DDR3_1600_8x8) + + def _createMemoryControllers(self, num, cls): + self.mem_cntrls = [ + cls(range = self.mem_ranges[0], + port = self.membus.master) + for i in range(num) + ] + + def initFS(self, membus, cpus): + self.pc = Pc() + + # Constants similar to x86_traits.hh + IO_address_space_base = 0x8000000000000000 + pci_config_address_space_base = 0xc000000000000000 + interrupts_address_space_base = 0xa000000000000000 + APIC_range_size = 1 << 12; + + # North Bridge + self.iobus = IOXBar() + self.bridge = Bridge(delay='50ns') + self.bridge.master = self.iobus.slave + self.bridge.slave = membus.master + # Allow the bridge to pass through: + # 1) kernel configured PCI device memory map address: address range + # [0xC0000000, 0xFFFF0000). (The upper 64kB are reserved for m5ops.) + # 2) the bridge to pass through the IO APIC (two pages, already + # contained in 1), + # 3) everything in the IO address range up to the local APIC, and + # 4) then the entire PCI address space and beyond. + self.bridge.ranges = \ + [ + AddrRange(0xC0000000, 0xFFFF0000), + AddrRange(IO_address_space_base, + interrupts_address_space_base - 1), + AddrRange(pci_config_address_space_base, + Addr.max) + ] + + # Create a bridge from the IO bus to the memory bus to allow access + # to the local APIC (two pages) + self.apicbridge = Bridge(delay='50ns') + self.apicbridge.slave = self.iobus.master + self.apicbridge.master = membus.slave + self.apicbridge.ranges = [AddrRange(interrupts_address_space_base, + interrupts_address_space_base + + cpus * APIC_range_size + - 1)] + + # connect the io bus + self.pc.attachIO(self.iobus) + + # Add a tiny cache to the IO bus. + # This cache is required for the classic memory model for coherence + self.iocache = Cache(assoc=8, + tag_latency = 50, + data_latency = 50, + response_latency = 50, + mshrs = 20, + size = '1kB', + tgts_per_mshr = 12, + addr_ranges = self.mem_ranges) + self.iocache.cpu_side = self.iobus.master + self.iocache.mem_side = self.membus.slave + + self.intrctrl = IntrControl() + + ############################################### + + # Add in a Bios information structure. + self.smbios_table.structures = [X86SMBiosBiosInformation()] + + # Set up the Intel MP table + base_entries = [] + ext_entries = [] + for i in range(cpus): + bp = X86IntelMPProcessor( + local_apic_id = i, + local_apic_version = 0x14, + enable = True, + bootstrap = (i ==0)) + base_entries.append(bp) + io_apic = X86IntelMPIOAPIC( + id = cpus, + version = 0x11, + enable = True, + address = 0xfec00000) + self.pc.south_bridge.io_apic.apic_id = io_apic.id + base_entries.append(io_apic) + pci_bus = X86IntelMPBus(bus_id = 0, bus_type='PCI ') + base_entries.append(pci_bus) + isa_bus = X86IntelMPBus(bus_id = 1, bus_type='ISA ') + base_entries.append(isa_bus) + connect_busses = X86IntelMPBusHierarchy(bus_id=1, + subtractive_decode=True, parent_bus=0) + ext_entries.append(connect_busses) + pci_dev4_inta = X86IntelMPIOIntAssignment( + interrupt_type = 'INT', + polarity = 'ConformPolarity', + trigger = 'ConformTrigger', + source_bus_id = 0, + source_bus_irq = 0 + (4 << 2), + dest_io_apic_id = io_apic.id, + dest_io_apic_intin = 16) + base_entries.append(pci_dev4_inta) + def assignISAInt(irq, apicPin): + assign_8259_to_apic = X86IntelMPIOIntAssignment( + interrupt_type = 'ExtInt', + polarity = 'ConformPolarity', + trigger = 'ConformTrigger', + source_bus_id = 1, + source_bus_irq = irq, + dest_io_apic_id = io_apic.id, + dest_io_apic_intin = 0) + base_entries.append(assign_8259_to_apic) + assign_to_apic = X86IntelMPIOIntAssignment( + interrupt_type = 'INT', + polarity = 'ConformPolarity', + trigger = 'ConformTrigger', + source_bus_id = 1, + source_bus_irq = irq, + dest_io_apic_id = io_apic.id, + dest_io_apic_intin = apicPin) + base_entries.append(assign_to_apic) + assignISAInt(0, 2) + assignISAInt(1, 1) + for i in range(3, 15): + assignISAInt(i, i) + self.intel_mp_table.base_entries = base_entries + self.intel_mp_table.ext_entries = ext_entries + + entries = \ + [ + # Mark the first megabyte of memory as reserved + X86E820Entry(addr = 0, size = '639kB', range_type = 1), + X86E820Entry(addr = 0x9fc00, size = '385kB', range_type = 2), + # Mark the rest of physical memory as available + X86E820Entry(addr = 0x100000, + size = '%dB' % (self.mem_ranges[0].size() - 0x100000), + range_type = 1), + ] + + # Reserve the last 16kB of the 32-bit address space for m5ops + entries.append(X86E820Entry(addr = 0xFFFF0000, size = '64kB', + range_type=2)) + + self.e820_table.entries = entries + +class CowDisk(IdeDisk): + def __init__(self, filename): + super(CowDisk, self).__init__() + self.driveID = 'master' + self.image = CowDiskImage(child=RawDiskImage(read_only=True), + read_only=False) + self.image.child.image_file = filename diff --git a/tests/gem5/x86-boot-tests/test_linux_boot.py b/tests/gem5/x86-boot-tests/test_linux_boot.py new file mode 100644 index 000000000..0417eb9b7 --- /dev/null +++ b/tests/gem5/x86-boot-tests/test_linux_boot.py @@ -0,0 +1,72 @@ +# Copyright (c) 2020 The Regents of the University of California +# All Rights Reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer; +# redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution; +# neither the name of the copyright holders nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +import os +from testlib import * + + +if config.bin_path: + base_path = config.bin_path +else: + base_path = joinpath(absdirpath(__file__), '..', 'resources', + 'ubuntu-boot') + +image_url = 'http://dist.gem5.org/images/x86/ubuntu-18-04/base.img' +kernel_url = 'http://dist.gem5.org/kernels/x86/static/vmlinux-4.19.83' + +image_name = 'ubuntu-18-04-base.img' +kernel_name = 'vmlinux-4.19.83' # 4.19 is LTS (Projected EOL: Dec, 2020) + +image = DownloadedProgram(image_url, base_path, image_name) +kernel = DownloadedProgram(kernel_url, base_path, kernel_name) + + +def test_boot(cpu_type, num_cpus, boot_type): + gem5_verify_config( + name = 'test-ubuntu_boot-' + cpu_type + '_cpu-' + num_cpus + '_cpus-' + + boot_type + '_boot', + verifiers = (), + fixtures = (image, kernel,), + config = joinpath(joinpath(absdirpath(__file__), 'run_exit.py')), + config_args = [ + '--kernel', joinpath(base_path, kernel_name), + '--disk', joinpath(base_path, image_name), + '--cpu-type', cpu_type, + '--num-cpus', num_cpus, + '--boot-type', boot_type, + ], + valid_isas = ('X86',), + valid_hosts = constants.supported_hosts, + length = constants.long_tag, + ) + +# Test every CPU type +cpu_types = ('atomic', 'simple',) +for cpu_type in cpu_types: + test_boot(cpu_type, '1', 'init') + +# Test a multicore system +test_boot('atomic', '4', 'systemd') -- 2.30.2