From: Gabe Black Date: Tue, 29 Oct 2019 01:55:02 +0000 (-0700) Subject: config,arch,cpu,kern,sim: Extract kernel information from System. X-Git-Tag: v20.0.0.0~399 X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=73fdc2eb57dded37c2e0d93c1cdb179d1faa6679;p=gem5.git config,arch,cpu,kern,sim: Extract kernel information from System. Information about what kernel to load and how to load it was built into the System object and its subclasses. That overloaded the System object and made it responsible for too many things, and also was somewhat awkward when working with SE mode which doesn't have a kernel. This change extracts the kernel and information related to it from the System object and puts into into a OsKernel or Workload object. Currently the idea of a "Workload" to run and a kernel are a bit muddled, an unfortunate carry-over from the original code. It's also an implication of trying not to make too sweeping of a change, and to minimize the number of times configs need to change, ie avoiding creating a "kernel" parameter which would shortly thereafter be renamed to "workload". In future changes, the ideas of a kernel and a workload will be disentangled, and workloads will be expanded to include emulated operating systems which shephard and contain Process-es for syscall emulation. This change was originally split into pieces to make reviewing it easier. Those reviews are here: https: //gem5-review.googlesource.com/c/public/gem5/+/22243 https: //gem5-review.googlesource.com/c/public/gem5/+/24144 https: //gem5-review.googlesource.com/c/public/gem5/+/24145 https: //gem5-review.googlesource.com/c/public/gem5/+/24146 https: //gem5-review.googlesource.com/c/public/gem5/+/24147 https: //gem5-review.googlesource.com/c/public/gem5/+/24286 Change-Id: Ia3d863db276a023b6a2c7ee7a656d8142ff75589 Reviewed-on: https://gem5-review.googlesource.com/c/public/gem5/+/26466 Reviewed-by: Gabe Black Maintainer: Gabe Black Tested-by: kokoro --- diff --git a/configs/common/FSConfig.py b/configs/common/FSConfig.py index 691a04a27..b58c27380 100644 --- a/configs/common/FSConfig.py +++ b/configs/common/FSConfig.py @@ -123,10 +123,6 @@ def makeSparcSystem(mem_mode, mdesc=None, cmdline=None): AddrRange(Addr('2GB'), size ='256MB')] self.bridge.master = self.iobus.slave self.bridge.slave = self.membus.master - self.rom.port = self.membus.master - self.nvram.port = self.membus.master - self.hypervisor_desc.port = self.membus.master - self.partition_desc.port = self.membus.master self.intrctrl = IntrControl() self.disk0 = CowMmDisk() self.disk0.childImage(mdesc.disks()[0]) @@ -150,15 +146,37 @@ def makeSparcSystem(mem_mode, mdesc=None, cmdline=None): AddrRange(self.t1000.hvuart.pio_addr, self.t1000.hvuart.pio_addr + uart_pio_size - 1) ] - self.reset_bin = binary('reset_new.bin') - self.hypervisor_bin = binary('q_new.bin') - self.openboot_bin = binary('openboot_new.bin') - self.nvram_bin = binary('nvram1') - self.hypervisor_desc_bin = binary('1up-hv.bin') - self.partition_desc_bin = binary('1up-md.bin') + + workload = SparcFsWorkload( + reset_bin=binary('reset_new.bin'), + hypervisor_bin=binary('q_new.bin'), + openboot_bin=binary('openboot_new.bin'), + nvram_bin=binary('nvram1'), + hypervisor_desc_bin=binary('1up-hv.bin'), + partition_desc_bin=binary('1up-md.bin'), + ) + + # ROM for OBP/Reset/Hypervisor + self.rom = SimpleMemory(range=AddrRange(workload._rom_base, size='8MB')) + # nvram + self.nvram = SimpleMemory( + range=AddrRange(workload._nvram_base, size='8kB')) + # hypervisor description + self.hypervisor_desc = SimpleMemory( + range=AddrRange(workload._hypervisor_desc_base, size='8kB')) + # partition description + self.partition_desc = SimpleMemory( + range=AddrRange(workload._partition_desc_base, size='8kB')) + + self.rom.port = self.membus.master + self.nvram.port = self.membus.master + self.hypervisor_desc.port = self.membus.master + self.partition_desc.port = self.membus.master self.system_port = self.membus.slave + self.workload = workload + return self def makeArmSystem(mem_mode, machine_type, num_cpus=1, mdesc=None, @@ -169,10 +187,7 @@ def makeArmSystem(mem_mode, machine_type, num_cpus=1, mdesc=None, pci_devices = [] - if bare_metal: - self = ArmSystem() - else: - self = LinuxArmSystem() + self = ArmSystem() if not mdesc: # generic system @@ -242,11 +257,13 @@ def makeArmSystem(mem_mode, machine_type, num_cpus=1, mdesc=None, # EOT character on UART will end the simulation self.realview.uart[0].end_on_eot = True else: + workload = ArmFsLinux() + if dtb_filename: - self.dtb_filename = binary(dtb_filename) + workload.dtb_filename = binary(dtb_filename) - self.machine_type = machine_type if machine_type in ArmMachineType.map \ - else "DTOnly" + workload.machine_type = \ + machine_type if machine_type in ArmMachineType.map else "DTOnly" # Ensure that writes to the UART actually go out early in the boot if not cmdline: @@ -254,8 +271,6 @@ def makeArmSystem(mem_mode, machine_type, num_cpus=1, mdesc=None, 'lpj=19988480 norandmaps rw loglevel=8 ' + \ 'mem=%(mem)s root=%(rootdev)s' - self.realview.setupBootLoader(self, binary, bootloader) - if hasattr(self.realview.gic, 'cpu_addr'): self.gic_cpu_addr = self.realview.gic.cpu_addr @@ -292,7 +307,11 @@ def makeArmSystem(mem_mode, machine_type, num_cpus=1, mdesc=None, "androidboot.selinux=permissive " + \ "video=Virtual-1:1920x1080-16" - self.boot_osflags = fillInCmdline(mdesc, cmdline) + workload.command_line = fillInCmdline(mdesc, cmdline) + + self.workload = workload + + self.realview.setupBootLoader(self, binary) if external_memory: # I/O traffic enters iobus @@ -381,7 +400,7 @@ def makeLinuxMipsSystem(mem_mode, mdesc=None, cmdline=None): self.console = binary('mips/console') if not cmdline: cmdline = 'root=/dev/hda1 console=ttyS0' - self.boot_osflags = fillInCmdline(mdesc, cmdline) + self.workload = OsKernel(command_line=fillInCmdline(mdesc, cmdline)) self.system_port = self.membus.slave @@ -445,9 +464,12 @@ def connectX86RubySystem(x86_sys): x86_sys.pc.attachIO(x86_sys.iobus, x86_sys._dma_ports) -def makeX86System(mem_mode, numCPUs=1, mdesc=None, self=None, Ruby=False): - if self == None: - self = X86System() +def makeX86System(mem_mode, numCPUs=1, mdesc=None, workload=None, Ruby=False): + self = X86System() + + if workload is None: + workload = X86FsWorkload() + self.workload = workload if not mdesc: # generic system @@ -489,7 +511,7 @@ def makeX86System(mem_mode, numCPUs=1, mdesc=None, self=None, Ruby=False): # Add in a Bios information structure. structures = [X86SMBiosBiosInformation()] - self.smbios_table.structures = structures + workload.smbios_table.structures = structures # Set up the Intel MP table base_entries = [] @@ -509,8 +531,8 @@ def makeX86System(mem_mode, numCPUs=1, mdesc=None, self=None, Ruby=False): self.pc.south_bridge.io_apic.apic_id = io_apic.id base_entries.append(io_apic) # In gem5 Pc::calcPciConfigAddr(), it required "assert(bus==0)", - # but linux kernel cannot config PCI device if it was not connected to PCI bus, - # so we fix PCI bus id to 0, and ISA bus id to 1. + # but linux kernel cannot config PCI device if it was not connected to + # PCI bus, so we fix PCI bus id to 0, and ISA bus id to 1. pci_bus = X86IntelMPBus(bus_id = 0, bus_type='PCI ') base_entries.append(pci_bus) isa_bus = X86IntelMPBus(bus_id = 1, bus_type='ISA ') @@ -550,15 +572,15 @@ def makeX86System(mem_mode, numCPUs=1, mdesc=None, self=None, Ruby=False): 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 + workload.intel_mp_table.base_entries = base_entries + workload.intel_mp_table.ext_entries = ext_entries + + return self def makeLinuxX86System(mem_mode, numCPUs=1, mdesc=None, Ruby=False, cmdline=None): - self = LinuxX86System() - # Build up the x86 system and then specialize it for Linux - makeX86System(mem_mode, numCPUs, mdesc, self, Ruby) + self = makeX86System(mem_mode, numCPUs, mdesc, X86FsLinux(), Ruby) # We assume below that there's at least 1MB of memory. We'll require 2 # just to avoid corner cases. @@ -596,12 +618,12 @@ def makeLinuxX86System(mem_mode, numCPUs=1, mdesc=None, Ruby=False, entries.append(X86E820Entry(addr = 0x100000000, size = '%dB' % (self.mem_ranges[1].size()), range_type = 1)) - self.e820_table.entries = entries + self.workload.e820_table.entries = entries # Command line if not cmdline: cmdline = 'earlyprintk=ttyS0 console=ttyS0 lpj=7999923 root=/dev/hda1' - self.boot_osflags = fillInCmdline(mdesc, cmdline) + self.workload.command_line = fillInCmdline(mdesc, cmdline) return self diff --git a/configs/common/MemConfig.py b/configs/common/MemConfig.py index 85494d3f3..d1cc6558a 100644 --- a/configs/common/MemConfig.py +++ b/configs/common/MemConfig.py @@ -125,7 +125,7 @@ def config_mem(options, system): port_data=opt_tlm_memory, port=system.membus.master, addr_ranges=system.mem_ranges) - system.kernel_addr_check = False + system.workload.addr_check = False return if opt_external_memory_system: @@ -133,7 +133,7 @@ def config_mem(options, system): port_type=opt_external_memory_system, port_data="init_mem0", port=xbar.master, addr_ranges=system.mem_ranges) - subsystem.kernel_addr_check = False + subsystem.workload.addr_check = False return nbr_mem_ctrls = opt_mem_channels diff --git a/configs/example/arm/baremetal.py b/configs/example/arm/baremetal.py index 109370b43..c1628934b 100644 --- a/configs/example/arm/baremetal.py +++ b/configs/example/arm/baremetal.py @@ -98,7 +98,8 @@ def create(args): args.mem_size, platform=VExpress_GEM5_V2(), mem_mode=mem_mode, - kernel=args.kernel, + workload=ArmFsWorkload( + object_file=args.kernel), readfile=args.readfile) MemConfig.config_mem(args, system) @@ -215,7 +216,7 @@ def main(): if args.dtb_gen: # No run, autogenerate DTB and exit - root.system.generateDtb(m5.options.outdir, 'system.dtb') + root.system.generateDtb(os.path.join(m5.options.outdir, 'system.dtb')) else: run(args) diff --git a/configs/example/arm/fs_bigLITTLE.py b/configs/example/arm/fs_bigLITTLE.py index cc3e748c8..b7e794d58 100644 --- a/configs/example/arm/fs_bigLITTLE.py +++ b/configs/example/arm/fs_bigLITTLE.py @@ -118,9 +118,10 @@ def createSystem(caches, kernel, bootscript, machine_type="VExpress_GEM5", platform = ObjectList.platform_list.get(machine_type) m5.util.inform("Simulated platform: %s", platform.__name__) - sys = devices.simpleSystem(LinuxArmSystem, + sys = devices.simpleSystem(ArmSystem, caches, mem_size, platform(), - kernel=SysPaths.binary(kernel), + workload=ArmFsLinux( + object_file=SysPaths.binary(kernel)), readfile=bootscript) sys.mem_ctrls = [ SimpleMemory(range=r, port=sys.membus.master) @@ -243,9 +244,9 @@ def build(options): root.system = system if options.kernel_cmd: - system.boot_osflags = options.kernel_cmd + system.workload.command_line = options.kernel_cmd else: - system.boot_osflags = " ".join(kernel_cmd) + system.workload.command_line = " ".join(kernel_cmd) if options.big_cpus + options.little_cpus == 0: m5.util.panic("Empty CPU clusters") @@ -287,9 +288,11 @@ def build(options): # Linux device tree if options.dtb is not None: - system.dtb_filename = SysPaths.binary(options.dtb) + system.workload.dtb_filename = SysPaths.binary(options.dtb) else: - system.generateDtb(m5.options.outdir, 'system.dtb') + system.workload.dtb_filename = \ + os.path.join(m5.options.outdir, 'system.dtb') + system.generateDtb(system.workload.dtb_filename) if devices.have_fastmodel and issubclass(big_model, FastmodelCluster): from m5 import arm_fast_model as fm, systemc as sc diff --git a/configs/example/arm/starter_fs.py b/configs/example/arm/starter_fs.py index ee67cb0b4..7a202807e 100644 --- a/configs/example/arm/starter_fs.py +++ b/configs/example/arm/starter_fs.py @@ -99,11 +99,13 @@ def create(args): # Only simulate caches when using a timing CPU (e.g., the HPI model) want_caches = True if mem_mode == "timing" else False - system = devices.simpleSystem(LinuxArmSystem, + system = devices.simpleSystem(ArmSystem, want_caches, args.mem_size, mem_mode=mem_mode, - kernel=SysPaths.binary(args.kernel), + workload=ArmFsLinux( + object_file= + SysPaths.binary(args.kernel)), readfile=args.script) MemConfig.config_mem(args, system) @@ -146,10 +148,12 @@ def create(args): system.realview.setupBootLoader(system, SysPaths.binary) if args.dtb: - system.dtb_filename = args.dtb + system.workload.dtb_filename = args.dtb else: # No DTB specified: autogenerate DTB - system.generateDtb(m5.options.outdir, 'system.dtb') + system.workload.dtb_filename = \ + os.path.join(m5.options.outdir, 'system.dtb') + system.generateDtb(system.workload.dtb_filename) # Linux boot command flags kernel_cmd = [ @@ -161,13 +165,13 @@ def create(args): # memory layout. "norandmaps", # Tell Linux where to find the root disk image. - "root=/dev/vda1", + "root=/dev/vda", # Mount the root disk read-write by default. "rw", # Tell Linux about the amount of physical memory present. "mem=%s" % args.mem_size, ] - system.boot_osflags = " ".join(kernel_cmd) + system.workload.command_line = " ".join(kernel_cmd) return system diff --git a/configs/example/fs.py b/configs/example/fs.py index bf6832548..5264aa568 100644 --- a/configs/example/fs.py +++ b/configs/example/fs.py @@ -124,7 +124,7 @@ def build_test_system(np): test_sys.cpu_voltage_domain) if options.kernel is not None: - test_sys.kernel = binary(options.kernel) + test_sys.workload.object_file = binary(options.kernel) if options.script is not None: test_sys.readfile = options.script @@ -269,7 +269,7 @@ def build_drive_system(np): drive_sys.cpu.createInterruptController() drive_sys.cpu.connectAllPorts(drive_sys.membus) if options.kernel is not None: - drive_sys.kernel = binary(options.kernel) + drive_sys.workload.object_file = binary(options.kernel) if ObjectList.is_kvm_cpu(DriveCPUClass): drive_sys.kvm_vm = KvmVM() @@ -369,7 +369,9 @@ if buildEnv['TARGET_ISA'] == "arm" and not options.bare_metal \ for sysname in ('system', 'testsys', 'drivesys'): if hasattr(root, sysname): sys = getattr(root, sysname) - sys.generateDtb(m5.options.outdir, '%s.dtb' % sysname) + sys.workload.dtb_filename = \ + os.path.join(m5.options.outdir, '%s.dtb' % sysname) + sys.generateDtb(sys.workload.dtb_filename) Simulation.setWorkCountOptions(test_sys, options) Simulation.run(options, root, test_sys, FutureClass) diff --git a/configs/example/se.py b/configs/example/se.py index 25c148882..a3cd6f14d 100644 --- a/configs/example/se.py +++ b/configs/example/se.py @@ -50,6 +50,7 @@ import os import m5 from m5.defines import buildEnv from m5.objects import * +from m5.params import NULL from m5.util import addToPath, fatal, warn addToPath('../') @@ -171,7 +172,8 @@ np = options.num_cpus system = System(cpu = [CPUClass(cpu_id=i) for i in range(np)], mem_mode = test_mem_mode, mem_ranges = [AddrRange(options.mem_size)], - cache_line_size = options.cacheline_size) + cache_line_size = options.cacheline_size, + workload = NULL) if numThreads > 1: system.multi_thread = True diff --git a/src/arch/arm/ArmFsWorkload.py b/src/arch/arm/ArmFsWorkload.py new file mode 100644 index 000000000..6064d81e9 --- /dev/null +++ b/src/arch/arm/ArmFsWorkload.py @@ -0,0 +1,90 @@ +# Copyright (c) 2009, 2012-2013, 2015-2019 ARM Limited +# All rights reserved. +# +# The license below extends only to copyright in the software and shall +# not be construed as granting a license to any other intellectual +# property including but not limited to intellectual property relating +# to a hardware implementation of the functionality of the software +# licensed hereunder. You may use the software subject to the license +# terms below provided that you ensure that this notice is replicated +# unmodified and in its entirety in all distributions of the software, +# modified or unmodified, in source code or in binary form. +# +# 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. + +from m5.params import * +from m5.options import * +from m5.SimObject import * +from m5.objects.OsKernel import OsKernel + +class ArmMachineType(Enum): + map = { + 'VExpress_EMM' : 2272, + 'VExpress_EMM64' : 2272, + 'DTOnly' : -1, + } + +class ArmFsWorkload(OsKernel): + type = 'ArmFsWorkload' + cxx_header = "arch/arm/fs_workload.hh" + cxx_class = "ArmISA::FsWorkload" + + load_addr_mask = 0 + + boot_loader = VectorParam.String([], + "File that contains the boot loader code. Zero or more files may be " + "specified. The first boot loader that matches the kernel's " + "architecture will be used.") + + dtb_filename = Param.String("", + "File that contains the Device Tree Blob. Don't use DTB if empty.") + + machine_type = Param.ArmMachineType('DTOnly', + "Machine id from http://www.arm.linux.org.uk/developer/machines/") + atags_addr = Param.Addr("Address where default atags structure should " \ + "be written") + early_kernel_symbols = Param.Bool(False, + "enable early kernel symbol tables before MMU") + enable_context_switch_stats_dump = Param.Bool(False, + "enable stats/task info dumping at context switch boundaries") + + panic_on_panic = Param.Bool(False, "Trigger a gem5 panic if the " \ + "guest kernel panics") + panic_on_oops = Param.Bool(False, "Trigger a gem5 panic if the " \ + "guest kernel oopses") + +class ArmFsLinux(ArmFsWorkload): + type = 'ArmFsLinux' + cxx_header = "arch/arm/linux/fs_workload.hh" + cxx_class = "ArmISA::FsLinux" + + @cxxMethod + def dumpDmesg(self): + """Dump dmesg from the simulated kernel to standard out""" + pass + +class ArmFsFreebsd(ArmFsWorkload): + type = 'ArmFsFreebsd' + cxx_header = "arch/arm/freebsd/fs_workload.hh" + cxx_class = "ArmISA::FsFreebsd" diff --git a/src/arch/arm/ArmSystem.py b/src/arch/arm/ArmSystem.py index 5f4061feb..1b5fc907d 100644 --- a/src/arch/arm/ArmSystem.py +++ b/src/arch/arm/ArmSystem.py @@ -41,23 +41,12 @@ from m5.util.fdthelper import * from m5.objects.System import System from m5.objects.ArmSemihosting import ArmSemihosting -class ArmMachineType(Enum): - map = { - 'VExpress_EMM' : 2272, - 'VExpress_EMM64' : 2272, - 'DTOnly' : -1, - } - class SveVectorLength(UInt8): min = 1; max = 16 class ArmSystem(System): type = 'ArmSystem' cxx_header = "arch/arm/system.hh" multi_proc = Param.Bool(True, "Multiprocessor system?") - boot_loader = VectorParam.String([], - "File that contains the boot loader code. Zero or more files may be " - "specified. The first boot loader that matches the kernel's " - "architecture will be used.") gic_cpu_addr = Param.Addr(0, "Addres of the GIC CPU interface") flags_addr = Param.Addr(0, "Address of the flags register for MP booting") have_security = Param.Bool(False, @@ -90,10 +79,11 @@ class ArmSystem(System): semihosting = Param.ArmSemihosting(NULL, "Enable support for the Arm semihosting by settings this parameter") - dtb_filename = Param.String("", - "File that contains the Device Tree Blob. Don't use DTB if empty.") + m5ops_base = Param.Addr(0, + "Base of the 64KiB PA range used for memory-mapped m5ops. Set to 0 " + "to disable.") - def generateDtb(self, outdir, filename): + def generateDtb(self, filename): """ Autogenerate DTB. Arguments are the folder where the DTB will be stored, and the name of the DTB file. @@ -103,8 +93,7 @@ class ArmSystem(System): fdt = Fdt() fdt.add_rootnode(rootNode) - dtb_filename = os.path.join(outdir, filename) - self.dtb_filename = fdt.writeDtbFile(dtb_filename) + fdt.writeDtbFile(filename) def generateDeviceTree(self, state): @@ -139,37 +128,3 @@ class ArmSystem(System): root.append(node) return root - -class GenericArmSystem(ArmSystem): - type = 'GenericArmSystem' - cxx_header = "arch/arm/system.hh" - machine_type = Param.ArmMachineType('DTOnly', - "Machine id from http://www.arm.linux.org.uk/developer/machines/") - atags_addr = Param.Addr("Address where default atags structure should " \ - "be written") - early_kernel_symbols = Param.Bool(False, - "enable early kernel symbol tables before MMU") - enable_context_switch_stats_dump = Param.Bool(False, - "enable stats/task info dumping at context switch boundaries") - - panic_on_panic = Param.Bool(False, "Trigger a gem5 panic if the " \ - "guest kernel panics") - panic_on_oops = Param.Bool(False, "Trigger a gem5 panic if the " \ - "guest kernel oopses") - -class LinuxArmSystem(GenericArmSystem): - type = 'LinuxArmSystem' - cxx_header = "arch/arm/linux/system.hh" - - @cxxMethod - def dumpDmesg(self): - """Dump dmesg from the simulated kernel to standard out""" - pass - - # Have Linux systems for ARM auto-calc their load_addr_mask for proper - # kernel relocation. - load_addr_mask = 0x0 - -class FreebsdArmSystem(GenericArmSystem): - type = 'FreebsdArmSystem' - cxx_header = "arch/arm/freebsd/system.hh" diff --git a/src/arch/arm/SConscript b/src/arch/arm/SConscript index b4e9bba8e..409e287db 100644 --- a/src/arch/arm/SConscript +++ b/src/arch/arm/SConscript @@ -67,10 +67,11 @@ if env['TARGET_ISA'] == 'arm': Source('isa_device.cc') Source('linux/linux.cc') Source('linux/process.cc') - Source('linux/system.cc') + Source('linux/fs_workload.cc') Source('freebsd/freebsd.cc') Source('freebsd/process.cc') - Source('freebsd/system.cc') + Source('freebsd/fs_workload.cc') + Source('fs_workload.cc') Source('miscregs.cc') Source('nativetrace.cc') Source('pauth_helpers.cc') @@ -89,6 +90,7 @@ if env['TARGET_ISA'] == 'arm': Source('utility.cc') Source('vtophys.cc') + SimObject('ArmFsWorkload.py') SimObject('ArmInterrupts.py') SimObject('ArmISA.py') SimObject('ArmNativeTrace.py') diff --git a/src/arch/arm/freebsd/fs_workload.cc b/src/arch/arm/freebsd/fs_workload.cc new file mode 100644 index 000000000..c248ff617 --- /dev/null +++ b/src/arch/arm/freebsd/fs_workload.cc @@ -0,0 +1,135 @@ +/* + * Copyright (c) 2015 Ruslan Bukin + * All rights reserved. + * + * This software was developed by the University of Cambridge Computer + * Laboratory as part of the CTSRD Project, with support from the UK Higher + * Education Innovation Fund (HEIF). + * + * 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. + */ + +#include "arch/arm/freebsd/fs_workload.hh" + +#include "arch/arm/isa_traits.hh" +#include "arch/arm/utility.hh" +#include "arch/generic/freebsd/threadinfo.hh" +#include "base/loader/dtb_file.hh" +#include "base/loader/object_file.hh" +#include "base/loader/symtab.hh" +#include "cpu/base.hh" +#include "cpu/pc_event.hh" +#include "cpu/thread_context.hh" +#include "debug/Loader.hh" +#include "kern/freebsd/events.hh" +#include "mem/fs_translating_port_proxy.hh" +#include "mem/physical.hh" +#include "sim/stat_control.hh" + +using namespace FreeBSD; + +namespace ArmISA +{ + +FsFreebsd::FsFreebsd(Params *p) : ArmISA::FsWorkload(p), + enableContextSwitchStatsDump(p->enable_context_switch_stats_dump) +{ + if (p->panic_on_panic) { + kernelPanicEvent = addKernelFuncEventOrPanic( + "panic", "Kernel panic in simulated kernel"); + } else { +#ifndef NDEBUG + kernelPanicEvent = addKernelFuncEventOrPanic("panic"); +#endif + } + + if (p->panic_on_oops) { + kernelOopsEvent = addKernelFuncEventOrPanic( + "oops_exit", "Kernel oops in guest"); + } + + uDelaySkipEvent = addKernelFuncEvent( + "DELAY", "DELAY", 1000, 0); +} + +void +FsFreebsd::initState() +{ + ArmISA::FsWorkload::initState(); + + // Load symbols at physical address, we might not want + // to do this permanently, for but early bootup work + // it is helpful. + if (params()->early_kernel_symbols) { + obj->loadGlobalSymbols(symtab, 0, 0, loadAddrMask); + obj->loadGlobalSymbols(debugSymbolTable, 0, 0, loadAddrMask); + } + + // Check if the kernel image has a symbol that tells us it supports + // device trees. + Addr addr; + fatal_if(!symtab->findAddress("fdt_get_range", addr), + "Kernel must have fdt support."); + fatal_if(params()->dtb_filename == "", "dtb file is not specified."); + + // Kernel supports flattened device tree and dtb file specified. + // Using Device Tree Blob to describe system configuration. + inform("Loading DTB file: %s at address %#x\n", params()->dtb_filename, + params()->atags_addr + loadAddrOffset); + + DtbFile *dtb_file = new DtbFile(params()->dtb_filename); + + warn_if(!dtb_file->addBootCmdLine(commandLine.c_str(), commandLine.size()), + "Couldn't append bootargs to DTB file: %s", + params()->dtb_filename); + + Addr ra = dtb_file->findReleaseAddr(); + if (ra) + bootReleaseAddr = ra & ~ULL(0x7F); + + dtb_file->buildImage(). + offset(params()->atags_addr + loadAddrOffset). + write(system->physProxy); + delete dtb_file; + + // Kernel boot requirements to set up r0, r1 and r2 in ARMv7 + for (auto tc: system->threadContexts) { + tc->setIntReg(0, 0); + tc->setIntReg(1, params()->machine_type); + tc->setIntReg(2, params()->atags_addr + loadAddrOffset); + } +} + +FsFreebsd::~FsFreebsd() +{ + delete uDelaySkipEvent; +} + +} // namespace ArmISA + +ArmISA::FsFreebsd * +ArmFsFreebsdParams::create() +{ + return new ArmISA::FsFreebsd(this); +} diff --git a/src/arch/arm/freebsd/fs_workload.hh b/src/arch/arm/freebsd/fs_workload.hh new file mode 100644 index 000000000..7f0ac083f --- /dev/null +++ b/src/arch/arm/freebsd/fs_workload.hh @@ -0,0 +1,107 @@ +/* + * Copyright (c) 2015 Ruslan Bukin + * All rights reserved. + * + * This software was developed by the University of Cambridge Computer + * Laboratory as part of the CTSRD Project, with support from the UK Higher + * Education Innovation Fund (HEIF). + * + * 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. + */ + +#ifndef __ARCH_ARM_FREEBSD_FS_WORKLOAD_HH__ +#define __ARCH_ARM_FREEBSD_FS_WORKLOAD_HH__ + +#include + +#include "arch/arm/fs_workload.hh" +#include "kern/freebsd/events.hh" +#include "params/ArmFsFreebsd.hh" + +namespace ArmISA +{ + +class FsFreebsd : public ArmISA::FsWorkload +{ + public: + /** Boilerplate params code */ + typedef ArmFsFreebsdParams Params; + const Params * + params() const + { + return dynamic_cast(&_params); + } + + /** When enabled, dump stats/task info on context switches for + * Streamline and per-thread cache occupancy studies, etc. */ + bool enableContextSwitchStatsDump; + + /** This map stores a mapping of OS process IDs to internal Task IDs. The + * mapping is done because the stats system doesn't tend to like vectors + * that are much greater than 1000 items and the entire process space is + * 65K. */ + std::map taskMap; + + /** This is a file that is placed in the run directory that prints out + * mappings between taskIds and OS process IDs */ + std::ostream* taskFile; + + FsFreebsd(Params *p); + ~FsFreebsd(); + + void initState() override; + + /** This function creates a new task Id for the given pid. + * @param tc thread context that is currentyl executing */ + void mapPid(ThreadContext* tc, uint32_t pid); + + private: + /** Event to halt the simulator if the kernel calls panic() */ + PCEvent *kernelPanicEvent = nullptr; + + /** Event to halt the simulator if the kernel calls oopses */ + PCEvent *kernelOopsEvent = nullptr; + + /** + * PC based event to skip udelay(