# Copyright (c) 2023 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. """ This script demonstrates how to use KVM CPU without perf. This simulation boots Ubuntu 18.04 using 2 KVM CPUs without using perf. Usage ----- ``` scons build/X86/gem5.opt -j`nproc` ./build/X86/gem5.opt configs/example/gem5_library/x86-ubuntu-run-with-kvm-no-perf.py ``` """ from gem5.coherence_protocol import CoherenceProtocol from gem5.components.boards.x86_board import X86Board from gem5.components.cachehierarchies.ruby.mesi_two_level_cache_hierarchy import ( MESITwoLevelCacheHierarchy, ) from gem5.components.memory.single_channel import SingleChannelDDR4_2400 from gem5.components.processors.cpu_types import CPUTypes from gem5.components.processors.simple_switchable_processor import ( SimpleSwitchableProcessor, ) from gem5.isas import ISA from gem5.resources.resource import obtain_resource from gem5.simulate.exit_event import ExitEvent from gem5.simulate.simulator import Simulator from gem5.utils.requires import requires # This simulation requires using KVM with gem5 compiled for X86 simulation # and with MESI_Two_Level cache coherence protocol. requires( isa_required=ISA.X86, coherence_protocol_required=CoherenceProtocol.MESI_TWO_LEVEL, kvm_required=True, ) from gem5.components.cachehierarchies.ruby.mesi_two_level_cache_hierarchy import ( MESITwoLevelCacheHierarchy, ) cache_hierarchy = MESITwoLevelCacheHierarchy( l1d_size="32KiB", l1d_assoc=8, l1i_size="32KiB", l1i_assoc=8, l2_size="512KiB", l2_assoc=16, num_l2_banks=1, ) # Main memory memory = SingleChannelDDR4_2400(size="3GiB") # This is a switchable CPU. We first boot Ubuntu using KVM, then the guest # will exit the simulation by calling "m5 exit" (see the `command` variable # below, which contains the command to be run in the guest after booting). # Upon exiting from the simulation, the Exit Event handler will switch the # CPU type (see the ExitEvent.EXIT line below, which contains a map to # a function to be called when an exit event happens). processor = SimpleSwitchableProcessor( starting_core_type=CPUTypes.KVM, switch_core_type=CPUTypes.TIMING, isa=ISA.X86, num_cores=2, ) # Here we tell the KVM CPU (the starting CPU) not to use perf. for proc in processor.start: proc.core.usePerf = False # Here we setup the board. The X86Board allows for Full-System X86 simulations. board = X86Board( clk_freq="3GHz", processor=processor, memory=memory, cache_hierarchy=cache_hierarchy, ) # Here we set the Full System workload. # The `set_kernel_disk_workload` function for the X86Board takes a kernel, a # disk image, and, optionally, a command to run. # This is the command to run after the system has booted. The first `m5 exit` # will stop the simulation so we can switch the CPU cores from KVM to timing # and continue the simulation to run the echo command, sleep for a second, # then, again, call `m5 exit` to terminate the simulation. After simulation # has ended you may inspect `m5out/system.pc.com_1.device` to see the echo # output. command = ( "m5 exit;" + "echo 'This is running on Timing CPU cores.';" + "sleep 1;" + "m5 exit;" ) workload = obtain_resource("x86-ubuntu-18.04-boot") workload.set_parameter("readfile_contents", command) board.set_workload(workload) simulator = Simulator( board=board, on_exit_event={ # Here we want override the default behavior for the first m5 exit # exit event. Instead of exiting the simulator, we just want to # switch the processor. The 2nd m5 exit after will revert to using # default behavior where the simulator run will exit. ExitEvent.EXIT: (func() for func in [processor.switch]) }, ) simulator.run()