From: Gabe Black Date: Thu, 6 Feb 2020 03:40:26 +0000 (-0800) Subject: arch,cpu,dev,sim,mem: Collect System thread elements into a subclass. X-Git-Tag: v20.1.0.0~600 X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=0dfa59f0bb0f0b8beb970debd3b6b992f1c37e65;p=gem5.git arch,cpu,dev,sim,mem: Collect System thread elements into a subclass. The System class has a few different arrays of values which each correspond to a thread of execution based on their position. This change collects them together into a single class to make managing them easier and less error prone. It also collects methods for manipulating those threads as an API for that class. This class acts as a collection point for thread based state which the System class can look into to get at all its state. It also acts as an interface for interacting with threads for other classes. This forces external consumers to use the API instead of accessing the individual arrays which improves consistency. Change-Id: Idc4575c5a0b56fe75f5c497809ad91c22bfe26cc Reviewed-on: https://gem5-review.googlesource.com/c/public/gem5/+/25144 Reviewed-by: Bobby R. Bruce Maintainer: Bobby R. Bruce Tested-by: kokoro --- diff --git a/src/arch/arm/freebsd/fs_workload.cc b/src/arch/arm/freebsd/fs_workload.cc index d15e1a2e2..080dc35e9 100644 --- a/src/arch/arm/freebsd/fs_workload.cc +++ b/src/arch/arm/freebsd/fs_workload.cc @@ -113,7 +113,7 @@ FsFreebsd::initState() delete dtb_file; // Kernel boot requirements to set up r0, r1 and r2 in ARMv7 - for (auto tc: system->threadContexts) { + for (auto *tc: system->threads) { tc->setIntReg(0, 0); tc->setIntReg(1, params()->machine_type); tc->setIntReg(2, params()->atags_addr + _loadAddrOffset); diff --git a/src/arch/arm/fs_workload.cc b/src/arch/arm/fs_workload.cc index 5bd534fb4..0cafb1b70 100644 --- a/src/arch/arm/fs_workload.cc +++ b/src/arch/arm/fs_workload.cc @@ -103,7 +103,7 @@ FsWorkload::initState() // FPEXC.EN = 0 - for (auto *tc: system->threadContexts) { + for (auto *tc: system->threads) { Reset().invoke(tc); tc->activate(); } @@ -126,7 +126,7 @@ FsWorkload::initState() fatal_if(!arm_sys->params()->gic_cpu_addr && is_gic_v2, "gic_cpu_addr must be set with bootloader"); - for (auto tc: arm_sys->threadContexts) { + for (auto *tc: arm_sys->threads) { if (!arm_sys->highestELIs64()) tc->setIntReg(3, kernelEntry); if (is_gic_v2) @@ -137,7 +137,7 @@ FsWorkload::initState() } else { // Set the initial PC to be at start of the kernel code if (!arm_sys->highestELIs64()) - arm_sys->threadContexts[0]->pcState(kernelObj->entryPoint()); + arm_sys->threads[0]->pcState(kernelObj->entryPoint()); } } diff --git a/src/arch/arm/isa.cc b/src/arch/arm/isa.cc index b18bbb055..b3ea91ef4 100644 --- a/src/arch/arm/isa.cc +++ b/src/arch/arm/isa.cc @@ -683,7 +683,7 @@ ISA::readMiscReg(int misc_reg, ThreadContext *tc) // mostly unimplemented, just set NumCPUs field from sim and return L2CTLR l2ctlr = 0; // b00:1CPU to b11:4CPUs - l2ctlr.numCPUs = tc->getSystemPtr()->numContexts() - 1; + l2ctlr.numCPUs = tc->getSystemPtr()->threads.size() - 1; return l2ctlr; } case MISCREG_DBGDIDR: diff --git a/src/arch/arm/isa/insts/misc.isa b/src/arch/arm/isa/insts/misc.isa index 88c473d6a..cd4438733 100644 --- a/src/arch/arm/isa/insts/misc.isa +++ b/src/arch/arm/isa/insts/misc.isa @@ -780,8 +780,8 @@ let {{ sevCode = ''' SevMailbox = 1; System *sys = xc->tcBase()->getSystemPtr(); - for (int x = 0; x < sys->numContexts(); x++) { - ThreadContext *oc = sys->getThreadContext(x); + for (int x = 0; x < sys->threads.size(); x++) { + ThreadContext *oc = sys->threads[x]; if (oc == xc->tcBase()) continue; diff --git a/src/arch/arm/kvm/gic.cc b/src/arch/arm/kvm/gic.cc index 14829b386..97f0fa383 100644 --- a/src/arch/arm/kvm/gic.cc +++ b/src/arch/arm/kvm/gic.cc @@ -302,7 +302,7 @@ void MuxingKvmGic::copyBankedDistRange(BaseGicRegisters* from, BaseGicRegisters* to, Addr daddr, size_t size) { - for (int ctx = 0; ctx < system.numContexts(); ++ctx) + for (int ctx = 0; ctx < system.threads.size(); ++ctx) for (auto a = daddr; a < daddr + size; a += 4) copyDistRegister(from, to, ctx, a); } @@ -311,7 +311,7 @@ void MuxingKvmGic::clearBankedDistRange(BaseGicRegisters* to, Addr daddr, size_t size) { - for (int ctx = 0; ctx < system.numContexts(); ++ctx) + for (int ctx = 0; ctx < system.threads.size(); ++ctx) for (auto a = daddr; a < daddr + size; a += 4) to->writeDistributor(ctx, a, 0xFFFFFFFF); } @@ -342,7 +342,7 @@ MuxingKvmGic::copyGicState(BaseGicRegisters* from, BaseGicRegisters* to) // Copy CPU Interface Control Register (CTLR), // Interrupt Priority Mask Register (PMR), and // Binary Point Register (BPR) - for (int ctx = 0; ctx < system.numContexts(); ++ctx) { + for (int ctx = 0; ctx < system.threads.size(); ++ctx) { copyCpuRegister(from, to, ctx, GICC_CTLR); copyCpuRegister(from, to, ctx, GICC_PMR); copyCpuRegister(from, to, ctx, GICC_BPR); @@ -420,7 +420,7 @@ MuxingKvmGic::fromKvmToGicV2() // have been shifted by three bits due to its having been emulated by // a VGIC with only 5 PMR bits in its VMCR register. Presently the // Linux kernel does not repair this inaccuracy, so we correct it here. - for (int cpu = 0; cpu < system.numContexts(); ++cpu) { + for (int cpu = 0; cpu < system.threads.size(); ++cpu) { cpuPriority[cpu] <<= 3; assert((cpuPriority[cpu] & ~0xff) == 0); } diff --git a/src/arch/arm/linux/fs_workload.cc b/src/arch/arm/linux/fs_workload.cc index d45c7f02c..12e3164c3 100644 --- a/src/arch/arm/linux/fs_workload.cc +++ b/src/arch/arm/linux/fs_workload.cc @@ -159,7 +159,7 @@ FsLinux::initState() } // Kernel boot requirements to set up r0, r1 and r2 in ARMv7 - for (auto tc: system->threadContexts) { + for (auto *tc: system->threads) { tc->setIntReg(0, 0); tc->setIntReg(1, params()->machine_type); tc->setIntReg(2, params()->atags_addr + _loadAddrOffset); @@ -194,7 +194,7 @@ FsLinux::startup() std::string task_filename = "tasks.txt"; taskFile = simout.create(name() + "." + task_filename); - for (const auto tc : system->threadContexts) { + for (auto *tc: system->threads) { uint32_t pid = tc->getCpuPtr()->getPid(); if (pid != BaseCPU::invldPid) { mapPid(tc, pid); @@ -265,7 +265,7 @@ FsLinux::mapPid(ThreadContext *tc, uint32_t pid) void FsLinux::dumpDmesg() { - Linux::dumpDmesg(system->getThreadContext(0), std::cout); + Linux::dumpDmesg(system->threads[0], std::cout); } /** diff --git a/src/arch/arm/linux/process.cc b/src/arch/arm/linux/process.cc index 4c679b3ca..a78c8e2ac 100644 --- a/src/arch/arm/linux/process.cc +++ b/src/arch/arm/linux/process.cc @@ -866,7 +866,7 @@ ArmLinuxProcess32::initState() { ArmProcess32::initState(); allocateMem(commPage, PageBytes); - ThreadContext *tc = system->getThreadContext(contextIds[0]); + ThreadContext *tc = system->threads[contextIds[0]]; uint8_t swiNeg1[] = { 0xff, 0xff, 0xff, 0xef // swi -1 diff --git a/src/arch/arm/process.cc b/src/arch/arm/process.cc index 93598b0b3..c5ef141e3 100644 --- a/src/arch/arm/process.cc +++ b/src/arch/arm/process.cc @@ -104,8 +104,8 @@ ArmProcess32::initState() { Process::initState(); argsInit(PageBytes, INTREG_SP); - for (int i = 0; i < contextIds.size(); i++) { - ThreadContext * tc = system->getThreadContext(contextIds[i]); + for (auto id: contextIds) { + ThreadContext *tc = system->threads[id]; CPACR cpacr = tc->readMiscReg(MISCREG_CPACR); // Enable the floating point coprocessors. cpacr.cp10 = 0x3; @@ -123,8 +123,8 @@ ArmProcess64::initState() { Process::initState(); argsInit(PageBytes, INTREG_SP0); - for (int i = 0; i < contextIds.size(); i++) { - ThreadContext * tc = system->getThreadContext(contextIds[i]); + for (auto id: contextIds) { + ThreadContext *tc = system->threads[id]; CPSR cpsr = tc->readMiscReg(MISCREG_CPSR); cpsr.mode = MODE_EL0T; tc->setMiscReg(MISCREG_CPSR, cpsr); @@ -206,7 +206,7 @@ ArmProcess64::armHwcapImpl() const uint32_t hwcap = 0; - ThreadContext *tc = system->getThreadContext(contextIds[0]); + ThreadContext *tc = system->threads[contextIds[0]]; const AA64PFR0 pf_r0 = tc->readMiscReg(MISCREG_ID_AA64PFR0_EL1); @@ -441,7 +441,7 @@ ArmProcess::argsInit(int pageSize, IntRegIndex spIndex) initVirtMem->writeBlob(argc_base, &guestArgc, intSize); - ThreadContext *tc = system->getThreadContext(contextIds[0]); + ThreadContext *tc = system->threads[contextIds[0]]; //Set the stack pointer register tc->setIntReg(spIndex, memState->getStackMin()); //A pointer to a function to run when the program exits. We'll set this diff --git a/src/arch/arm/tlbi_op.hh b/src/arch/arm/tlbi_op.hh index 03a0a3ee9..8706d3d7a 100644 --- a/src/arch/arm/tlbi_op.hh +++ b/src/arch/arm/tlbi_op.hh @@ -68,11 +68,8 @@ class TLBIOp void broadcast(ThreadContext *tc) { - System *sys = tc->getSystemPtr(); - for (int x = 0; x < sys->numContexts(); x++) { - ThreadContext *oc = sys->getThreadContext(x); + for (auto *oc: tc->getSystemPtr()->threads) (*this)(oc); - } } protected: diff --git a/src/arch/mips/process.cc b/src/arch/mips/process.cc index f6587ab8d..cdda2b293 100644 --- a/src/arch/mips/process.cc +++ b/src/arch/mips/process.cc @@ -193,7 +193,7 @@ MipsProcess::argsInit(int pageSize) initVirtMem->write(auxv_array_end, zero); auxv_array_end += sizeof(zero); - ThreadContext *tc = system->getThreadContext(contextIds[0]); + ThreadContext *tc = system->threads[contextIds[0]]; tc->setIntReg(FirstArgumentReg, argc); tc->setIntReg(FirstArgumentReg + 1, argv_array_base); diff --git a/src/arch/power/process.cc b/src/arch/power/process.cc index 01a2c9faf..767c3ebef 100644 --- a/src/arch/power/process.cc +++ b/src/arch/power/process.cc @@ -267,7 +267,7 @@ PowerProcess::argsInit(int intSize, int pageSize) initVirtMem->writeBlob(argc_base, &guestArgc, intSize); - ThreadContext *tc = system->getThreadContext(contextIds[0]); + ThreadContext *tc = system->threads[contextIds[0]]; //Set the stack pointer register tc->setIntReg(StackPointerReg, stack_min); diff --git a/src/arch/riscv/bare_metal/fs_workload.cc b/src/arch/riscv/bare_metal/fs_workload.cc index 6a0c86ce6..9c90c6811 100644 --- a/src/arch/riscv/bare_metal/fs_workload.cc +++ b/src/arch/riscv/bare_metal/fs_workload.cc @@ -54,7 +54,7 @@ BareMetal::initState() { RiscvISA::FsWorkload::initState(); - for (auto *tc: system->threadContexts) { + for (auto *tc: system->threads) { RiscvISA::Reset().invoke(tc); tc->activate(); } @@ -62,7 +62,7 @@ BareMetal::initState() warn_if(!bootloader->buildImage().write(system->physProxy), "Could not load sections to memory."); - for (auto *tc: system->threadContexts) { + for (auto *tc: system->threads) { RiscvISA::Reset().invoke(tc); tc->activate(); } diff --git a/src/arch/riscv/process.cc b/src/arch/riscv/process.cc index 9c0540012..a17b5154a 100644 --- a/src/arch/riscv/process.cc +++ b/src/arch/riscv/process.cc @@ -99,7 +99,7 @@ RiscvProcess64::initState() argsInit(PageBytes); for (ContextID ctx: contextIds) - system->getThreadContext(ctx)->setMiscRegNoEffect(MISCREG_PRV, PRV_U); + system->threads[ctx]->setMiscRegNoEffect(MISCREG_PRV, PRV_U); } void @@ -109,10 +109,11 @@ RiscvProcess32::initState() argsInit(PageBytes); for (ContextID ctx: contextIds) { - system->getThreadContext(ctx)->setMiscRegNoEffect(MISCREG_PRV, PRV_U); - PCState pc = system->getThreadContext(ctx)->pcState(); + auto *tc = system->threads[ctx]; + tc->setMiscRegNoEffect(MISCREG_PRV, PRV_U); + PCState pc = tc->pcState(); pc.rv32(true); - system->getThreadContext(ctx)->pcState(pc); + tc->pcState(pc); } } @@ -239,7 +240,7 @@ RiscvProcess::argsInit(int pageSize) pushOntoStack(aux.val); } - ThreadContext *tc = system->getThreadContext(contextIds[0]); + ThreadContext *tc = system->threads[contextIds[0]]; tc->setIntReg(StackPointerReg, memState->getStackMin()); tc->pcState(getStartPC()); diff --git a/src/arch/sparc/fs_workload.cc b/src/arch/sparc/fs_workload.cc index 71c3b4514..b812f5967 100644 --- a/src/arch/sparc/fs_workload.cc +++ b/src/arch/sparc/fs_workload.cc @@ -40,11 +40,11 @@ FsWorkload::initState() { Workload::initState(); - if (system->threadContexts.empty()) + if (system->threads.empty()) return; // Other CPUs will get activated by IPIs. - auto *tc = system->threadContexts[0]; + auto *tc = system->threads[0]; SparcISA::PowerOnReset().invoke(tc); tc->activate(); } diff --git a/src/arch/sparc/process.cc b/src/arch/sparc/process.cc index 3edbdf57d..ca0df08e6 100644 --- a/src/arch/sparc/process.cc +++ b/src/arch/sparc/process.cc @@ -111,7 +111,7 @@ SparcProcess::initState() { Process::initState(); - ThreadContext *tc = system->getThreadContext(contextIds[0]); + ThreadContext *tc = system->threads[contextIds[0]]; // From the SPARC ABI // Setup default FP state @@ -155,7 +155,7 @@ Sparc32Process::initState() { SparcProcess::initState(); - ThreadContext *tc = system->getThreadContext(contextIds[0]); + ThreadContext *tc = system->threads[contextIds[0]]; // The process runs in user mode with 32 bit addresses PSTATE pstate = 0; pstate.ie = 1; @@ -170,7 +170,7 @@ Sparc64Process::initState() { SparcProcess::initState(); - ThreadContext *tc = system->getThreadContext(contextIds[0]); + ThreadContext *tc = system->threads[contextIds[0]]; // The process runs in user mode PSTATE pstate = 0; pstate.ie = 1; @@ -393,7 +393,7 @@ SparcProcess::argsInit(int pageSize) fillStart = memState->getStackBase(); spillStart = fillStart + sizeof(MachInst) * numFillInsts; - ThreadContext *tc = system->getThreadContext(contextIds[0]); + ThreadContext *tc = system->threads[contextIds[0]]; // Set up the thread context to start running the process // assert(NumArgumentRegs >= 2); // tc->setIntReg(ArgumentReg[0], argc); diff --git a/src/arch/sparc/tlb.cc b/src/arch/sparc/tlb.cc index e67ae9aa7..fcb097345 100644 --- a/src/arch/sparc/tlb.cc +++ b/src/arch/sparc/tlb.cc @@ -1372,8 +1372,8 @@ TLB::doMmuRegWrite(ThreadContext *tc, Packet *pkt) } break; case ASI_SWVR_UDB_INTR_W: - tc->getSystemPtr()->threadContexts[bits(data,12,8)]->getCpuPtr()-> - postInterrupt(0, bits(data, 5, 0), 0); + tc->getSystemPtr()->threads[bits(data,12,8)]-> + getCpuPtr()->postInterrupt(0, bits(data, 5, 0), 0); break; default: doMmuWriteError: diff --git a/src/arch/sparc/ua2005.cc b/src/arch/sparc/ua2005.cc index 389549b40..3403451b5 100644 --- a/src/arch/sparc/ua2005.cc +++ b/src/arch/sparc/ua2005.cc @@ -287,12 +287,12 @@ ISA::readFSReg(int miscReg, ThreadContext * tc) temp = readMiscRegNoEffect(miscReg) & (STS::active | STS::speculative); // Check that the CPU array is fully populated // (by calling getNumCPus()) - assert(sys->numContexts() > tc->contextId()); + assert(sys->threads.size() > tc->contextId()); temp |= tc->contextId() << STS::shft_id; - for (x = tc->contextId() & ~3; x < sys->threadContexts.size(); x++) { - switch (sys->threadContexts[x]->status()) { + for (x = tc->contextId() & ~3; x < sys->threads.size(); x++) { + switch (sys->threads[x]->status()) { case ThreadContext::Active: temp |= STS::st_run << (STS::shft_fsm0 - ((x & 0x3) * (STS::shft_fsm0-STS::shft_fsm1))); diff --git a/src/arch/x86/fs_workload.cc b/src/arch/x86/fs_workload.cc index 3f46ebaf3..44c01d779 100644 --- a/src/arch/x86/fs_workload.cc +++ b/src/arch/x86/fs_workload.cc @@ -106,7 +106,7 @@ FsWorkload::initState() { KernelWorkload::initState(); - for (auto *tc: system->threadContexts) { + for (auto *tc: system->threads) { X86ISA::InitInterrupt(0).invoke(tc); if (tc->contextId() == 0) { @@ -124,7 +124,7 @@ FsWorkload::initState() fatal_if(kernelObj->getArch() == Loader::I386, "Loading a 32 bit x86 kernel is not supported."); - ThreadContext *tc = system->threadContexts[0]; + ThreadContext *tc = system->threads[0]; auto phys_proxy = system->physProxy; // This is the boot strap processor (BSP). Initialize it to look like diff --git a/src/arch/x86/interrupts.cc b/src/arch/x86/interrupts.cc index c2dcb3249..c81cf62c5 100644 --- a/src/arch/x86/interrupts.cc +++ b/src/arch/x86/interrupts.cc @@ -479,7 +479,7 @@ X86ISA::Interrupts::setReg(ApicRegIndex reg, uint32_t val) message.level = low.level; message.trigger = low.trigger; std::list apics; - int numContexts = sys->numContexts(); + int numContexts = sys->threads.size(); switch (low.destShorthand) { case 0: if (message.deliveryMode == DeliveryMode::LowestPriority) { diff --git a/src/arch/x86/linux/fs_workload.cc b/src/arch/x86/linux/fs_workload.cc index 4f8388458..0303cc800 100644 --- a/src/arch/x86/linux/fs_workload.cc +++ b/src/arch/x86/linux/fs_workload.cc @@ -123,7 +123,7 @@ FsLinux::initState() * Pass the location of the real mode data structure to the kernel * using register %esi. We'll use %rsi which should be equivalent. */ - system->threadContexts[0]->setIntReg(INTREG_RSI, realModeData); + system->threads[0]->setIntReg(INTREG_RSI, realModeData); } } // namespace X86ISA diff --git a/src/arch/x86/process.cc b/src/arch/x86/process.cc index 1b7fd3e8b..0324e9420 100644 --- a/src/arch/x86/process.cc +++ b/src/arch/x86/process.cc @@ -303,7 +303,7 @@ X86_64Process::initState() tss_attr.unusable = 0; for (int i = 0; i < contextIds.size(); i++) { - ThreadContext * tc = system->getThreadContext(contextIds[i]); + ThreadContext *tc = system->threads[contextIds[i]]; tc->setMiscReg(MISCREG_CS, cs); tc->setMiscReg(MISCREG_DS, ds); @@ -514,7 +514,7 @@ X86_64Process::initState() 16 * PageBytes, false); } else { for (int i = 0; i < contextIds.size(); i++) { - ThreadContext * tc = system->getThreadContext(contextIds[i]); + ThreadContext * tc = system->threads[contextIds[i]]; SegAttr dataAttr = 0; dataAttr.dpl = 3; @@ -625,7 +625,7 @@ I386Process::initState() vsysexitBlob, sizeof(vsysexitBlob)); for (int i = 0; i < contextIds.size(); i++) { - ThreadContext * tc = system->getThreadContext(contextIds[i]); + ThreadContext * tc = system->threads[contextIds[i]]; SegAttr dataAttr = 0; dataAttr.dpl = 3; @@ -975,7 +975,7 @@ X86Process::argsInit(int pageSize, initVirtMem->writeBlob(argc_base, &guestArgc, intSize); - ThreadContext *tc = system->getThreadContext(contextIds[0]); + ThreadContext *tc = system->threads[contextIds[0]]; // Set the stack pointer register tc->setIntReg(StackPointerReg, stack_min); diff --git a/src/cpu/base.hh b/src/cpu/base.hh index a33d1bd8f..810f2672c 100644 --- a/src/cpu/base.hh +++ b/src/cpu/base.hh @@ -54,6 +54,7 @@ #include "arch/isa_traits.hh" #include "arch/microcode_rom.hh" #include "base/statistics.hh" +#include "mem/port_proxy.hh" #include "sim/clocked_object.hh" #include "sim/eventq.hh" #include "sim/full_system.hh" diff --git a/src/cpu/intr_control.cc b/src/cpu/intr_control.cc index 9274b375d..9b4a352c1 100644 --- a/src/cpu/intr_control.cc +++ b/src/cpu/intr_control.cc @@ -47,7 +47,7 @@ void IntrControl::post(int cpu_id, int int_num, int index) { DPRINTF(IntrControl, "post %d:%d (cpu %d)\n", int_num, index, cpu_id); - ThreadContext *tc = sys->getThreadContext(cpu_id); + auto *tc = sys->threads[cpu_id]; tc->getCpuPtr()->postInterrupt(tc->threadId(), int_num, index); } @@ -55,7 +55,7 @@ void IntrControl::clear(int cpu_id, int int_num, int index) { DPRINTF(IntrControl, "clear %d:%d (cpu %d)\n", int_num, index, cpu_id); - ThreadContext *tc = sys->getThreadContext(cpu_id); + auto *tc = sys->threads[cpu_id]; tc->getCpuPtr()->clearInterrupt(tc->threadId(), int_num, index); } @@ -63,7 +63,7 @@ void IntrControl::clearAll(int cpu_id) { DPRINTF(IntrControl, "Clear all pending interrupts for CPU %d\n", cpu_id); - ThreadContext *tc = sys->getThreadContext(cpu_id); + auto *tc = sys->threads[cpu_id]; tc->getCpuPtr()->clearInterrupts(tc->threadId()); } @@ -71,7 +71,7 @@ bool IntrControl::havePosted(int cpu_id) const { DPRINTF(IntrControl, "Check pending interrupts for CPU %d\n", cpu_id); - ThreadContext *tc = sys->getThreadContext(cpu_id); + auto *tc = sys->threads[cpu_id]; return tc->getCpuPtr()->checkInterrupts(tc); } diff --git a/src/cpu/kvm/vm.cc b/src/cpu/kvm/vm.cc index 9808d61e9..720548c8f 100644 --- a/src/cpu/kvm/vm.cc +++ b/src/cpu/kvm/vm.cc @@ -539,7 +539,7 @@ KvmVM::contextIdToVCpuId(ContextID ctx) const { assert(system != nullptr); return dynamic_cast - (system->getThreadContext(ctx)->getCpuPtr())->getVCpuID(); + (system->threads[ctx]->getCpuPtr())->getVCpuID(); } int diff --git a/src/cpu/o3/cpu.cc b/src/cpu/o3/cpu.cc index 5f0a98b24..5230ee944 100644 --- a/src/cpu/o3/cpu.cc +++ b/src/cpu/o3/cpu.cc @@ -757,7 +757,7 @@ FullO3CPU::insertThread(ThreadID tid) // and not in the ThreadContext. ThreadContext *src_tc; if (FullSystem) - src_tc = system->threadContexts[tid]; + src_tc = system->threads[tid]; else src_tc = tcBase(tid); diff --git a/src/dev/arm/a9scu.cc b/src/dev/arm/a9scu.cc index 629fdd922..5101682a2 100644 --- a/src/dev/arm/a9scu.cc +++ b/src/dev/arm/a9scu.cc @@ -60,20 +60,23 @@ A9SCU::read(PacketPtr pkt) pkt->setLE(1); // SCU already enabled break; case Config: - /* Without making a completely new SCU, we can use the core count field - * as 4 bits and inform the OS of up to 16 CPUs. Although the core - * count is technically bits [1:0] only, bits [3:2] are SBZ for future - * expansion like this. - */ - if (sys->numContexts() > 4) { - warn_once("A9SCU with >4 CPUs is unsupported\n"); - if (sys->numContexts() > 15) - fatal("Too many CPUs (%d) for A9SCU!\n", sys->numContexts()); + { + /* Without making a completely new SCU, we can use the core count + * field as 4 bits and inform the OS of up to 16 CPUs. Although + * the core count is technically bits [1:0] only, bits [3:2] are + * SBZ for future expansion like this. + */ + int threads = sys->threads.size(); + if (threads > 4) { + warn_once("A9SCU with >4 CPUs is unsupported"); + fatal_if(threads > 15, + "Too many CPUs (%d) for A9SCU!", threads); + } + int smp_bits, core_cnt; + smp_bits = (1 << threads) - 1; + core_cnt = threads - 1; + pkt->setLE(smp_bits << 4 | core_cnt); } - int smp_bits, core_cnt; - smp_bits = (1 << sys->numContexts()) - 1; - core_cnt = sys->numContexts() - 1; - pkt->setLE(smp_bits << 4 | core_cnt); break; default: // Only configuration register is implemented diff --git a/src/dev/arm/fvp_base_pwr_ctrl.cc b/src/dev/arm/fvp_base_pwr_ctrl.cc index 5113c926e..7ab4e4091 100644 --- a/src/dev/arm/fvp_base_pwr_ctrl.cc +++ b/src/dev/arm/fvp_base_pwr_ctrl.cc @@ -61,8 +61,8 @@ void FVPBasePwrCtrl::init() { // All cores are ON by default (PwrStatus.{l0,l1} = 0b1) - corePwrStatus.resize(sys->numContexts(), 0x60000000); - for (const auto &tc : sys->threadContexts) + corePwrStatus.resize(sys->threads.size(), 0x60000000); + for (const auto &tc : sys->threads) poweredCoresPerCluster[tc->socketId()] += 1; BasicPioDevice::init(); } @@ -200,7 +200,7 @@ FVPBasePwrCtrl::write(PacketPtr pkt) regs.pcoffr = ~0; } else if (pwrs->l0) { // Power off all cores in the cluster - for (const auto &tco : sys->threadContexts) { + for (const auto &tco : sys->threads) { if (tc->socketId() == tco->socketId()) { PwrStatus *npwrs = getCorePwrStatus(tco); // Set pending cluster power off @@ -257,7 +257,7 @@ FVPBasePwrCtrl::getCorePwrStatus(ThreadContext *const tc) ThreadContext * FVPBasePwrCtrl::getThreadContextByMPID(uint32_t mpid) const { - for (auto &tc : sys->threadContexts) { + for (auto &tc : sys->threads) { if (mpid == ArmISA::getAffinity(&system, tc)) return tc; } @@ -274,7 +274,7 @@ FVPBasePwrCtrl::powerCoreOn(ThreadContext *const tc, PwrStatus *const pwrs) // Clear pending power-offs to the core pwrs->pp = 0; // Clear pending power-offs to the core's cluster - for (const auto &tco : sys->threadContexts) { + for (const auto &tco : sys->threads) { if (tc->socketId() == tco->socketId()) { PwrStatus *npwrs = getCorePwrStatus(tco); npwrs->pc = 0; diff --git a/src/dev/arm/generic_timer.cc b/src/dev/arm/generic_timer.cc index 51a52c723..4f92dac87 100644 --- a/src/dev/arm/generic_timer.cc +++ b/src/dev/arm/generic_timer.cc @@ -440,7 +440,7 @@ GenericTimer::createTimers(unsigned cpus) timers.resize(cpus); for (unsigned i = old_cpu_count; i < cpus; ++i) { - ThreadContext *tc = system.getThreadContext(i); + ThreadContext *tc = system.threads[i]; timers[i].reset( new CoreTimers(*this, system, i, @@ -481,7 +481,7 @@ void GenericTimer::setMiscReg(int reg, unsigned cpu, RegVal val) { CoreTimers &core(getTimers(cpu)); - ThreadContext *tc = system.getThreadContext(cpu); + ThreadContext *tc = system.threads[cpu]; switch (reg) { case MISCREG_CNTFRQ: @@ -695,7 +695,7 @@ GenericTimer::CoreTimers::CoreTimers(GenericTimer &_parent, ArmInterruptPin *_irqVirt, ArmInterruptPin *_irqHyp) : parent(_parent), cntfrq(parent.params()->cntfrq), - threadContext(system.getThreadContext(cpu)), + threadContext(system.threads[cpu]), irqPhysS(_irqPhysS), irqPhysNS(_irqPhysNS), irqVirt(_irqVirt), diff --git a/src/dev/arm/gic_v2.cc b/src/dev/arm/gic_v2.cc index c4834eccb..4ef15173d 100644 --- a/src/dev/arm/gic_v2.cc +++ b/src/dev/arm/gic_v2.cc @@ -263,7 +263,7 @@ GicV2::readDistributor(ContextID ctx, Addr daddr, size_t resp_sz) /* The 0x100 is a made-up flag to show that gem5 extensions * are available, * write 0x200 to this register to enable it. */ - return (((sys->numRunningContexts() - 1) << 5) | + return (((sys->threads.numRunning() - 1) << 5) | (itLines/INT_BITS_MAX -1) | (haveGem5Extensions ? 0x100 : 0x0)); case GICD_PIDR0: @@ -291,10 +291,9 @@ GicV2::readCpu(PacketPtr pkt) assert(pkt->req->hasContextId()); const ContextID ctx = pkt->req->contextId(); - assert(ctx < sys->numRunningContexts()); + assert(ctx < sys->threads.numRunning()); - DPRINTF(GIC, "gic cpu read register %#x cpu context: %d\n", daddr, - ctx); + DPRINTF(GIC, "gic cpu read register %#x cpu context: %d\n", daddr, ctx); pkt->setLE(readCpu(ctx, daddr)); @@ -326,7 +325,7 @@ GicV2::readCpu(ContextID ctx, Addr daddr) panic_if(!cpuSgiPending[active_int], "Interrupt %d active but no CPU generated it?\n", active_int); - for (int x = 0; x < sys->numRunningContexts(); x++) { + for (int x = 0; x < sys->threads.numRunning(); x++) { // See which CPU generated the interrupt uint8_t cpugen = bits(cpuSgiPending[active_int], 7 + 8 * x, 8 * x); @@ -660,7 +659,7 @@ GicV2::softInt(ContextID ctx, SWI swi) } break; case 1: { // interrupt all - for (int i = 0; i < sys->numContexts(); i++) { + for (int i = 0; i < sys->threads.size(); i++) { DPRINTF(IPI, "Processing CPU %d\n", i); if (!cpuEnabled(i)) continue; @@ -686,7 +685,7 @@ GicV2::softInt(ContextID ctx, SWI swi) // interrupt all uint8_t cpu_list; cpu_list = 0; - for (int x = 0; x < sys->numContexts(); x++) + for (int x = 0; x < sys->threads.size(); x++) cpu_list |= cpuEnabled(x) ? 1 << x : 0; swi.cpu_list = cpu_list; break; @@ -699,7 +698,7 @@ GicV2::softInt(ContextID ctx, SWI swi) DPRINTF(IPI, "Generating softIRQ from CPU %d for %#x\n", ctx, swi.cpu_list); - for (int i = 0; i < sys->numContexts(); i++) { + for (int i = 0; i < sys->threads.size(); i++) { DPRINTF(IPI, "Processing CPU %d\n", i); if (!cpuEnabled(i)) continue; @@ -715,8 +714,7 @@ GicV2::softInt(ContextID ctx, SWI swi) uint64_t GicV2::genSwiMask(int cpu) { - if (cpu > sys->numContexts()) - panic("Invalid CPU ID\n"); + panic_if(cpu > sys->threads.size(), "Invalid CPU ID."); return ULL(0x0101010101010101) << cpu; } @@ -734,7 +732,7 @@ GicV2::getCpuPriority(unsigned cpu) void GicV2::updateIntState(int hint) { - for (int cpu = 0; cpu < sys->numContexts(); cpu++) { + for (int cpu = 0; cpu < sys->threads.size(); cpu++) { if (!cpuEnabled(cpu)) continue; @@ -773,7 +771,7 @@ GicV2::updateIntState(int hint) } } - bool mp_sys = sys->numRunningContexts() > 1; + bool mp_sys = sys->threads.numRunning() > 1; // Check other ints for (int x = 0; x < (itLines/INT_BITS_MAX); x++) { if (getIntEnabled(cpu, x) & getPendingInt(cpu, x)) { @@ -832,7 +830,7 @@ GicV2::updateIntState(int hint) void GicV2::updateRunPri() { - for (int cpu = 0; cpu < sys->numContexts(); cpu++) { + for (int cpu = 0; cpu < sys->threads.size(); cpu++) { if (!cpuEnabled(cpu)) continue; uint8_t maxPriority = 0xff; diff --git a/src/dev/arm/gic_v2.hh b/src/dev/arm/gic_v2.hh index 5bc74b2a4..600f9afa8 100644 --- a/src/dev/arm/gic_v2.hh +++ b/src/dev/arm/gic_v2.hh @@ -297,7 +297,7 @@ class GicV2 : public BaseGic, public BaseGicRegisters uint8_t cpuTarget[GLOBAL_INT_LINES]; uint8_t getCpuTarget(ContextID ctx, uint32_t ix) { - assert(ctx < sys->numRunningContexts()); + assert(ctx < sys->threads.numRunning()); assert(ix < INT_LINES_MAX); if (ix < SGI_MAX + PPI_MAX) { // "GICD_ITARGETSR0 to GICD_ITARGETSR7 are read-only, and each diff --git a/src/dev/arm/gic_v3.cc b/src/dev/arm/gic_v3.cc index 2103c0e6c..b4046017a 100644 --- a/src/dev/arm/gic_v3.cc +++ b/src/dev/arm/gic_v3.cc @@ -60,15 +60,15 @@ void Gicv3::init() { distributor = new Gicv3Distributor(this, params()->it_lines); - redistributors.resize(sys->numContexts(), nullptr); - cpuInterfaces.resize(sys->numContexts(), nullptr); + int threads = sys->threads.size(); + redistributors.resize(threads, nullptr); + cpuInterfaces.resize(threads, nullptr); - panic_if(sys->numContexts() > params()->cpu_max, + panic_if(threads > params()->cpu_max, "Exceeding maximum number of PEs supported by GICv3: " - "using %u while maximum is %u\n", sys->numContexts(), - params()->cpu_max); + "using %u while maximum is %u.", threads, params()->cpu_max); - for (int i = 0; i < sys->numContexts(); i++) { + for (int i = 0; i < threads; i++) { redistributors[i] = new Gicv3Redistributor(this, i); cpuInterfaces[i] = new Gicv3CPUInterface(this, i); } @@ -77,14 +77,13 @@ Gicv3::init() Gicv3Distributor::ADDR_RANGE_SIZE - 1); redistSize = redistributors[0]->addrRangeSize; - redistRange = RangeSize(params()->redist_addr, - redistSize * sys->numContexts() - 1); + redistRange = RangeSize(params()->redist_addr, redistSize * threads - 1); addrRanges = {distRange, redistRange}; distributor->init(); - for (int i = 0; i < sys->numContexts(); i++) { + for (int i = 0; i < threads; i++) { redistributors[i]->init(); cpuInterfaces[i]->init(); } @@ -205,7 +204,7 @@ void Gicv3::postInt(uint32_t cpu, ArmISA::InterruptTypes int_type) { platform->intrctrl->post(cpu, int_type, 0); - ArmSystem::callClearStandByWfi(sys->getThreadContext(cpu)); + ArmSystem::callClearStandByWfi(sys->threads[cpu]); } bool diff --git a/src/dev/arm/gic_v3_cpu_interface.cc b/src/dev/arm/gic_v3_cpu_interface.cc index 73bd3bc66..5e1f8719e 100644 --- a/src/dev/arm/gic_v3_cpu_interface.cc +++ b/src/dev/arm/gic_v3_cpu_interface.cc @@ -1776,7 +1776,7 @@ Gicv3CPUInterface::generateSGI(RegVal val, Gicv3::GroupId group) bool ns = !inSecureState(); - for (int i = 0; i < gic->getSystem()->numContexts(); i++) { + for (int i = 0; i < gic->getSystem()->threads.size(); i++) { Gicv3Redistributor * redistributor_i = gic->getRedistributor(i); uint32_t affinity_i = redistributor_i->getAffinity(); @@ -2587,7 +2587,7 @@ Gicv3CPUInterface::clearPendingInterrupts() void Gicv3CPUInterface::assertWakeRequest() { - ThreadContext *tc = gic->getSystem()->getThreadContext(cpuId); + auto *tc = gic->getSystem()->threads[cpuId]; if (ArmSystem::callSetWakeRequest(tc)) { Reset().invoke(tc); tc->activate(); @@ -2597,7 +2597,7 @@ Gicv3CPUInterface::assertWakeRequest() void Gicv3CPUInterface::deassertWakeRequest() { - ThreadContext *tc = gic->getSystem()->getThreadContext(cpuId); + auto *tc = gic->getSystem()->threads[cpuId]; ArmSystem::callClearWakeRequest(tc); } diff --git a/src/dev/arm/gic_v3_distributor.cc b/src/dev/arm/gic_v3_distributor.cc index 4ce97822c..485ba7284 100644 --- a/src/dev/arm/gic_v3_distributor.cc +++ b/src/dev/arm/gic_v3_distributor.cc @@ -1021,7 +1021,7 @@ Gicv3Distributor::route(uint32_t int_id) if (affinity_routing.IRM) { // Interrupts routed to any PE defined as a participating node - for (int i = 0; i < gic->getSystem()->numContexts(); i++) { + for (int i = 0; i < gic->getSystem()->threads.size(); i++) { Gicv3Redistributor * redistributor_i = gic->getRedistributor(i); @@ -1086,7 +1086,7 @@ Gicv3Distributor::update() } // Update all redistributors - for (int i = 0; i < gic->getSystem()->numContexts(); i++) { + for (int i = 0; i < gic->getSystem()->threads.size(); i++) { gic->getRedistributor(i)->update(); } } diff --git a/src/dev/arm/gic_v3_redistributor.cc b/src/dev/arm/gic_v3_redistributor.cc index 740894947..5fceed573 100644 --- a/src/dev/arm/gic_v3_redistributor.cc +++ b/src/dev/arm/gic_v3_redistributor.cc @@ -158,7 +158,7 @@ Gicv3Redistributor::read(Addr addr, size_t size, bool is_secure_access) * (physical LPIs supported) */ uint64_t affinity = getAffinity(); - int last = cpuId == (gic->getSystem()->numContexts() - 1); + int last = cpuId == (gic->getSystem()->threads.size() - 1); return (affinity << 32) | (1 << 24) | (cpuId << 8) | (1 << 5) | (last << 4) | (1 << 3) | (1 << 0); } @@ -990,7 +990,7 @@ Gicv3Redistributor::deactivateIRQ(uint32_t int_id) uint32_t Gicv3Redistributor::getAffinity() const { - ThreadContext * tc = gic->getSystem()->getThreadContext(cpuId); + ThreadContext *tc = gic->getSystem()->threads[cpuId]; uint64_t mpidr = getMPIDR(gic->getSystem(), tc); /* * Aff3 = MPIDR[39:32] diff --git a/src/dev/arm/timer_cpulocal.cc b/src/dev/arm/timer_cpulocal.cc index 41cdbc387..5ba0b16ba 100644 --- a/src/dev/arm/timer_cpulocal.cc +++ b/src/dev/arm/timer_cpulocal.cc @@ -56,8 +56,8 @@ CpuLocalTimer::init() { auto p = params(); // Initialize the timer registers for each per cpu timer - for (int i = 0; i < sys->numContexts(); i++) { - ThreadContext* tc = sys->getThreadContext(i); + for (int i = 0; i < sys->threads.size(); i++) { + ThreadContext* tc = sys->threads[i]; std::stringstream oss; oss << name() << ".timer" << i; @@ -429,14 +429,14 @@ CpuLocalTimer::Timer::unserialize(CheckpointIn &cp) void CpuLocalTimer::serialize(CheckpointOut &cp) const { - for (int i = 0; i < sys->numContexts(); i++) + for (int i = 0; i < sys->threads.size(); i++) localTimer[i]->serializeSection(cp, csprintf("timer%d", i)); } void CpuLocalTimer::unserialize(CheckpointIn &cp) { - for (int i = 0; i < sys->numContexts(); i++) + for (int i = 0; i < sys->threads.size(); i++) localTimer[i]->unserializeSection(cp, csprintf("timer%d", i)); } diff --git a/src/dev/arm/vgic.cc b/src/dev/arm/vgic.cc index 0bb1fef38..5ac597ba8 100644 --- a/src/dev/arm/vgic.cc +++ b/src/dev/arm/vgic.cc @@ -56,7 +56,7 @@ VGic::VGic(const Params *p) maintIntPosted[x] = false; vIntPosted[x] = false; } - assert(sys->numRunningContexts() <= VGIC_CPU_MAX); + assert(sys->threads.numRunning() <= VGIC_CPU_MAX); } VGic::~VGic() @@ -414,8 +414,8 @@ VGic::updateIntState(ContextID ctx_id) } } - assert(sys->numRunningContexts() <= VGIC_CPU_MAX); - for (int i = 0; i < sys->numRunningContexts(); i++) { + assert(sys->threads.numRunning() <= VGIC_CPU_MAX); + for (int i = 0; i < sys->threads.numRunning(); i++) { struct vcpuIntData *vid = &vcpuData[i]; // Are any LRs active that weren't before? if (!vIntPosted[i]) { diff --git a/src/dev/mips/malta_cchip.cc b/src/dev/mips/malta_cchip.cc index 001202eac..c8fe7a840 100644 --- a/src/dev/mips/malta_cchip.cc +++ b/src/dev/mips/malta_cchip.cc @@ -102,7 +102,7 @@ MaltaCChip::postRTC() void MaltaCChip::postIntr(uint32_t interrupt) { - uint64_t size = sys->threadContexts.size(); + uint64_t size = sys->threads.size(); assert(size <= Malta::Max_CPUs); for (int i=0; i < size; i++) { @@ -117,7 +117,7 @@ MaltaCChip::postIntr(uint32_t interrupt) void MaltaCChip::clearIntr(uint32_t interrupt) { - uint64_t size = sys->threadContexts.size(); + uint64_t size = sys->threads.size(); assert(size <= Malta::Max_CPUs); for (int i=0; i < size; i++) { diff --git a/src/dev/net/dist_iface.cc b/src/dev/net/dist_iface.cc index 46933507c..cc408e0c1 100644 --- a/src/dev/net/dist_iface.cc +++ b/src/dev/net/dist_iface.cc @@ -410,9 +410,7 @@ DistIface::SyncEvent::process() start(); } else { // Wake up thread contexts on non-switch nodes. - for (int i = 0; i < DistIface::master->sys->numContexts(); i++) { - ThreadContext *tc = - DistIface::master->sys->getThreadContext(i); + for (auto *tc: master->sys->threads) { if (tc->status() == ThreadContext::Suspended) tc->activate(); else @@ -868,8 +866,7 @@ DistIface::toggleSync(ThreadContext *tc) // Dist-gem5 will reactivate all thread contexts when everyone has // reached the sync stop point. #if THE_ISA != NULL_ISA - for (int i = 0; i < master->sys->numContexts(); i++) { - ThreadContext *tc = master->sys->getThreadContext(i); + for (auto *tc: master->sys->threads) { if (tc->status() == ThreadContext::Active) tc->quiesce(); } @@ -883,8 +880,7 @@ DistIface::toggleSync(ThreadContext *tc) // activation here, since we know exactly when the next sync will // occur. #if THE_ISA != NULL_ISA - for (int i = 0; i < master->sys->numContexts(); i++) { - ThreadContext *tc = master->sys->getThreadContext(i); + for (auto *tc: master->sys->threads) { if (tc->status() == ThreadContext::Active) tc->quiesceTick(master->syncEvent->when() + 1); } diff --git a/src/dev/sparc/iob.cc b/src/dev/sparc/iob.cc index 347872ee6..44e7dc867 100644 --- a/src/dev/sparc/iob.cc +++ b/src/dev/sparc/iob.cc @@ -58,7 +58,7 @@ Iob::Iob(const Params *p) iobManSize = ULL(0x0100000000); iobJBusAddr = ULL(0x9F00000000); iobJBusSize = ULL(0x0100000000); - assert (params()->system->threadContexts.size() <= MaxNiagaraProcs); + assert(params()->system->threads.size() <= MaxNiagaraProcs); pioDelay = p->pio_latency; @@ -276,7 +276,7 @@ void Iob::generateIpi(Type type, int cpu_id, int vector) { SparcISA::SparcFault *por = new SparcISA::PowerOnReset(); - if (cpu_id >= sys->numContexts()) + if (cpu_id >= sys->threads.size()) return; switch (type) { @@ -289,16 +289,16 @@ Iob::generateIpi(Type type, int cpu_id, int vector) warn("Sending reset to CPU: %d\n", cpu_id); if (vector != por->trapType()) panic("Don't know how to set non-POR reset to cpu\n"); - por->invoke(sys->threadContexts[cpu_id]); - sys->threadContexts[cpu_id]->activate(); + por->invoke(sys->threads[cpu_id]); + sys->threads[cpu_id]->activate(); break; case 2: // idle -- this means stop executing and don't wake on interrupts DPRINTF(Iob, "Idling CPU because of I/O write cpu: %d\n", cpu_id); - sys->threadContexts[cpu_id]->halt(); + sys->threads[cpu_id]->halt(); break; case 3: // resume DPRINTF(Iob, "Resuming CPU because of I/O write cpu: %d\n", cpu_id); - sys->threadContexts[cpu_id]->activate(); + sys->threads[cpu_id]->activate(); break; default: panic("Invalid type to generate ipi\n"); diff --git a/src/dev/x86/i82094aa.cc b/src/dev/x86/i82094aa.cc index cc51d5c70..8d91cc61a 100644 --- a/src/dev/x86/i82094aa.cc +++ b/src/dev/x86/i82094aa.cc @@ -198,7 +198,7 @@ X86ISA::I82094AA::signalInterrupt(int line) message.level = entry.polarity; message.trigger = entry.trigger; std::list apics; - int numContexts = sys->numContexts(); + int numContexts = sys->threads.size(); if (message.destMode == 0) { if (message.deliveryMode == DeliveryMode::LowestPriority) { panic("Lowest priority delivery mode from the " @@ -214,7 +214,7 @@ X86ISA::I82094AA::signalInterrupt(int line) } } else { for (int i = 0; i < numContexts; i++) { - BaseInterrupts *base_int = sys->getThreadContext(i)-> + BaseInterrupts *base_int = sys->threads[i]-> getCpuPtr()->getInterruptController(0); auto *localApic = dynamic_cast(base_int); if ((localApic->readReg(APIC_LOGICAL_DESTINATION) >> 24) & diff --git a/src/kern/linux/linux.cc b/src/kern/linux/linux.cc index ae1d47c3f..c27d05338 100644 --- a/src/kern/linux/linux.cc +++ b/src/kern/linux/linux.cc @@ -110,8 +110,7 @@ Linux::procSelfMaps(Process *process, ThreadContext *tc) std::string Linux::cpuOnline(Process *process, ThreadContext *tc) { - return csprintf("0-%d\n", - tc->getSystemPtr()->numContexts() - 1); + return csprintf("0-%d\n", tc->getSystemPtr()->threads.size() - 1); } std::string diff --git a/src/mem/abstract_mem.cc b/src/mem/abstract_mem.cc index 70d462615..2f72ebef0 100644 --- a/src/mem/abstract_mem.cc +++ b/src/mem/abstract_mem.cc @@ -328,7 +328,7 @@ AbstractMemory::checkLockedAddrList(PacketPtr pkt) req->contextId() : InvalidContextID; if (owner_cid != requester_cid) { - ThreadContext* ctx = system()->getThreadContext(owner_cid); + ThreadContext* ctx = system()->threads[owner_cid]; TheISA::globalClearExclusive(ctx); } i = lockedAddrList.erase(i); diff --git a/src/mem/cache/prefetch/queued.cc b/src/mem/cache/prefetch/queued.cc index e6d2b7cd8..c2ae090d3 100644 --- a/src/mem/cache/prefetch/queued.cc +++ b/src/mem/cache/prefetch/queued.cc @@ -439,7 +439,7 @@ Queued::insert(const PacketPtr &pkt, PrefetchInfo &new_pfi, } else { // Add the translation request and try to resolve it later dpp.setTranslationRequest(translation_req); - dpp.tc = cache->system->getThreadContext(translation_req->contextId()); + dpp.tc = cache->system->threads[translation_req->contextId()]; DPRINTF(HWPrefetch, "Prefetch queued with no translation. " "addr:%#x priority: %3d\n", new_pfi.getAddr(), priority); addToQueue(pfqMissingTranslation, dpp); diff --git a/src/sim/mem_state.cc b/src/sim/mem_state.cc index f998fffe9..bfee9dab5 100644 --- a/src/sim/mem_state.cc +++ b/src/sim/mem_state.cc @@ -256,7 +256,7 @@ MemState::unmapRegion(Addr start_addr, Addr length) * There is currently no general method across all TLB implementations * that can flush just part of the address space. */ - for (auto tc : _ownerProcess->system->threadContexts) { + for (auto *tc: _ownerProcess->system->threads) { tc->getDTBPtr()->flushAll(); tc->getITBPtr()->flushAll(); } @@ -358,7 +358,7 @@ MemState::remapRegion(Addr start_addr, Addr new_start_addr, Addr length) * There is currently no general method across all TLB implementations * that can flush just part of the address space. */ - for (auto tc : _ownerProcess->system->threadContexts) { + for (auto *tc: _ownerProcess->system->threads) { tc->getDTBPtr()->flushAll(); tc->getITBPtr()->flushAll(); } @@ -405,8 +405,7 @@ MemState::fixupFault(Addr vaddr) * ThreadContexts associated with this process. */ for (auto &cid : _ownerProcess->contextIds) { - ThreadContext *tc = - _ownerProcess->system->getThreadContext(cid); + auto *tc = _ownerProcess->system->threads[cid]; SETranslatingPortProxy virt_mem(tc, SETranslatingPortProxy::Always); vma.fillMemPages(vpage_start, _pageBytes, virt_mem); diff --git a/src/sim/process.cc b/src/sim/process.cc index 3fab8536d..28c0b542e 100644 --- a/src/sim/process.cc +++ b/src/sim/process.cc @@ -293,7 +293,7 @@ Process::initState() fatal("Process %s is not associated with any HW contexts!\n", name()); // first thread context for this process... initialize & enable - ThreadContext *tc = system->getThreadContext(contextIds[0]); + ThreadContext *tc = system->threads[contextIds[0]]; // mark this context as active so it will start ticking. tc->activate(); diff --git a/src/sim/pseudo_inst.cc b/src/sim/pseudo_inst.cc index 2d87b0595..41201eae7 100644 --- a/src/sim/pseudo_inst.cc +++ b/src/sim/pseudo_inst.cc @@ -170,13 +170,13 @@ wakeCPU(ThreadContext *tc, uint64_t cpuid) DPRINTF(PseudoInst, "PseudoInst::wakeCPU(%i)\n", cpuid); System *sys = tc->getSystemPtr(); - if (sys->numContexts() <= cpuid) { + if (sys->threads.size() <= cpuid) { warn("PseudoInst::wakeCPU(%i), cpuid greater than number of contexts" - "(%i)\n",cpuid, sys->numContexts()); + "(%i)\n", cpuid, sys->threads.size()); return; } - ThreadContext *other_tc = sys->threadContexts[cpuid]; + ThreadContext *other_tc = sys->threads[cpuid]; if (other_tc->status() == ThreadContext::Suspended) other_tc->activate(); } diff --git a/src/sim/syscall_emul.cc b/src/sim/syscall_emul.cc index 6d39823b4..4a4160963 100644 --- a/src/sim/syscall_emul.cc +++ b/src/sim/syscall_emul.cc @@ -119,9 +119,9 @@ exitImpl(SyscallDesc *desc, ThreadContext *tc, bool group, int status) bool last_thread = true; Process *parent = nullptr, *tg_lead = nullptr; - for (int i = 0; last_thread && i < sys->numContexts(); i++) { + for (int i = 0; last_thread && i < sys->threads.size(); i++) { Process *walk; - if (!(walk = sys->threadContexts[i]->getProcessPtr())) + if (!(walk = sys->threads[i]->getProcessPtr())) continue; /** @@ -133,8 +133,9 @@ exitImpl(SyscallDesc *desc, ThreadContext *tc, bool group, int status) if (walk->pid() == p->tgid()) tg_lead = walk; - if ((sys->threadContexts[i]->status() != ThreadContext::Halted) && - (sys->threadContexts[i]->status() != ThreadContext::Halting) && + auto *tc = sys->threads[i]; + if ((tc->status() != ThreadContext::Halted) && + (tc->status() != ThreadContext::Halting) && (walk != p)) { /** * Check if we share thread group with the pointer; this denotes @@ -156,7 +157,7 @@ exitImpl(SyscallDesc *desc, ThreadContext *tc, bool group, int status) * all threads in the group. */ if (*(p->exitGroup)) { - sys->threadContexts[i]->halt(); + tc->halt(); } else { last_thread = false; } @@ -201,7 +202,7 @@ exitImpl(SyscallDesc *desc, ThreadContext *tc, bool group, int status) */ int activeContexts = 0; for (auto &system: sys->systemList) - activeContexts += system->numRunningContexts(); + activeContexts += system->threads.numRunning(); if (activeContexts == 0) { /** @@ -905,9 +906,9 @@ setpgidFunc(SyscallDesc *desc, ThreadContext *tc, int pid, int pgid) System *sysh = tc->getSystemPtr(); // Retrieves process pointer from active/suspended thread contexts. - for (int i = 0; i < sysh->numContexts(); i++) { - if (sysh->threadContexts[i]->status() != ThreadContext::Halted) { - Process *temp_h = sysh->threadContexts[i]->getProcessPtr(); + for (auto *tc: sysh->threads) { + if (tc->status() != ThreadContext::Halted) { + Process *temp_h = tc->getProcessPtr(); Process *walk_ph = (Process*)temp_h; if (walk_ph && walk_ph->pid() == process->pid()) diff --git a/src/sim/syscall_emul.hh b/src/sim/syscall_emul.hh index f2cc22c2a..aa81e14b3 100644 --- a/src/sim/syscall_emul.hh +++ b/src/sim/syscall_emul.hh @@ -1440,7 +1440,7 @@ cloneFunc(SyscallDesc *desc, ThreadContext *tc, RegVal flags, RegVal newStack, return -EINVAL; ThreadContext *ctc; - if (!(ctc = tc->getSystemPtr()->findFreeContext())) { + if (!(ctc = tc->getSystemPtr()->threads.findFree())) { DPRINTF_SYSCALL(Verbose, "clone: no spare thread context in system" "[cpu %d, thread %d]", tc->cpuId(), tc->threadId()); return -EAGAIN; @@ -1861,7 +1861,7 @@ getrlimitFunc(SyscallDesc *desc, ThreadContext *tc, break; case OS::TGT_RLIMIT_NPROC: - rlp->rlim_cur = rlp->rlim_max = tc->getSystemPtr()->numContexts(); + rlp->rlim_cur = rlp->rlim_max = tc->getSystemPtr()->threads.size(); rlp->rlim_cur = htog(rlp->rlim_cur, bo); rlp->rlim_max = htog(rlp->rlim_max, bo); break; @@ -2198,8 +2198,8 @@ tgkillFunc(SyscallDesc *desc, ThreadContext *tc, int tgid, int tid, int sig) System *sys = tc->getSystemPtr(); Process *tgt_proc = nullptr; - for (int i = 0; i < sys->numContexts(); i++) { - Process *temp = sys->threadContexts[i]->getProcessPtr(); + for (auto *tc: sys->threads) { + Process *temp = tc->getProcessPtr(); if (temp->pid() == tid) { tgt_proc = temp; break; diff --git a/src/sim/system.cc b/src/sim/system.cc index 0bae99aeb..557ad7dc6 100644 --- a/src/sim/system.cc +++ b/src/sim/system.cc @@ -57,6 +57,7 @@ #include "cpu/base.hh" #include "cpu/thread_context.hh" #include "debug/Loader.hh" +#include "debug/Quiesce.hh" #include "debug/WorkItems.hh" #include "mem/abstract_mem.hh" #include "mem/physical.hh" @@ -80,6 +81,68 @@ using namespace TheISA; vector System::systemList; +ContextID +System::Threads::insert(ThreadContext *tc, ContextID id) +{ + if (id == InvalidContextID) { + for (id = 0; id < size(); id++) { + if (!threads[id].context) + break; + } + } + + if (id >= size()) + threads.resize(id + 1); + + fatal_if(threads[id].context, + "Cannot have two thread contexts with the same id (%d).", id); + + auto &t = thread(id); + t.context = tc; +# if THE_ISA != NULL_ISA + int port = getRemoteGDBPort(); + if (port) { + t.gdb = new RemoteGDB(tc->getSystemPtr(), tc, port + id); + t.gdb->listen(); + } +# endif + + return id; +} + +void +System::Threads::replace(ThreadContext *tc, ContextID id) +{ + auto &t = thread(id); + t.context = tc; + if (t.gdb) + t.gdb->replaceThreadContext(tc); +} + +ThreadContext * +System::Threads::findFree() +{ + for (auto &thread: threads) { + if (thread.context->status() == ThreadContext::Halted) + return thread.context; + } + return nullptr; +} + +int +System::Threads::numRunning() const +{ + int count = 0; + for (auto &thread: threads) { + auto status = thread.context->status(); + if (status != ThreadContext::Halted && + status != ThreadContext::Halting) { + count++; + } + } + return count; +} + int System::numSystemsRunning = 0; System::System(Params *p) @@ -164,18 +227,13 @@ System::startup() // Now that we're about to start simulation, wait for GDB connections if // requested. #if THE_ISA != NULL_ISA - for (auto *tc: threadContexts) { - auto *cpu = tc->getCpuPtr(); - auto id = tc->contextId(); - if (remoteGDB.size() <= id) - continue; - auto *rgdb = remoteGDB[id]; - - if (cpu->waitForRemoteGDB()) { - inform("%s: Waiting for a remote GDB connection on port %d.\n", - cpu->name(), rgdb->port()); - - rgdb->connect(); + for (int i = 0; i < threads.size(); i++) { + auto *gdb = threads.thread(i).gdb; + auto *cpu = threads[i]->getCpuPtr(); + if (gdb && cpu->waitForRemoteGDB()) { + inform("%s: Waiting for a remote GDB connection on port %d.", + cpu->name(), gdb->port()); + gdb->connect(); } } #endif @@ -197,66 +255,31 @@ System::setMemoryMode(Enums::MemoryMode mode) bool System::breakpoint() { - if (remoteGDB.size()) - return remoteGDB[0]->breakpoint(); - return false; + if (!threads.size()) + return false; + auto *gdb = threads.thread(0).gdb; + if (!gdb) + return false; + return gdb->breakpoint(); } ContextID System::registerThreadContext(ThreadContext *tc, ContextID assigned) { - int id = assigned; - if (id == InvalidContextID) { - // Find an unused context ID for this thread. - id = 0; - while (id < threadContexts.size() && threadContexts[id]) - id++; - } - - if (threadContexts.size() <= id) - threadContexts.resize(id + 1); + ContextID id = threads.insert(tc, assigned); - fatal_if(threadContexts[id], - "Cannot have two CPUs with the same id (%d)\n", id); - - threadContexts[id] = tc; for (auto *e: liveEvents) tc->schedule(e); -#if THE_ISA != NULL_ISA - int port = getRemoteGDBPort(); - if (port) { - RemoteGDB *rgdb = new RemoteGDB(this, tc, port + id); - rgdb->listen(); - - if (remoteGDB.size() <= id) - remoteGDB.resize(id + 1); - - remoteGDB[id] = rgdb; - } -#endif - - activeCpus.push_back(false); - return id; } -ThreadContext * -System::findFreeContext() -{ - for (auto &it : threadContexts) { - if (ThreadContext::Halted == it->status()) - return it; - } - return nullptr; -} - bool System::schedule(PCEvent *event) { bool all = true; liveEvents.push_back(event); - for (auto *tc: threadContexts) + for (auto *tc: threads) all = tc->schedule(event) && all; return all; } @@ -266,53 +289,35 @@ System::remove(PCEvent *event) { bool all = true; liveEvents.remove(event); - for (auto *tc: threadContexts) + for (auto *tc: threads) all = tc->remove(event) && all; return all; } -int -System::numRunningContexts() -{ - return std::count_if( - threadContexts.cbegin(), - threadContexts.cend(), - [] (ThreadContext* tc) { - return ((tc->status() != ThreadContext::Halted) && - (tc->status() != ThreadContext::Halting)); - } - ); -} - void System::replaceThreadContext(ThreadContext *tc, ContextID context_id) { - if (context_id >= threadContexts.size()) { - panic("replaceThreadContext: bad id, %d >= %d\n", - context_id, threadContexts.size()); - } + auto *otc = threads[context_id]; + threads.replace(tc, context_id); for (auto *e: liveEvents) { - threadContexts[context_id]->remove(e); + otc->remove(e); tc->schedule(e); } - threadContexts[context_id] = tc; - if (context_id < remoteGDB.size()) - remoteGDB[context_id]->replaceThreadContext(tc); } bool System::validKvmEnvironment() const { #if USE_KVM - if (threadContexts.empty()) + if (threads.empty()) return false; - for (auto tc : threadContexts) { - if (dynamic_cast(tc->getCpuPtr()) == nullptr) { + for (auto *tc: threads) { + if (!dynamic_cast(tc->getCpuPtr())) return false; - } } + return true; #else return false; diff --git a/src/sim/system.hh b/src/sim/system.hh index fa59765ba..530c5ea06 100644 --- a/src/sim/system.hh +++ b/src/sim/system.hh @@ -52,6 +52,7 @@ #include "base/loader/symtab.hh" #include "base/statistics.hh" #include "config/the_isa.hh" +#include "cpu/base.hh" #include "cpu/pc_event.hh" #include "enums/MemoryMode.hh" #include "mem/mem_master.hh" @@ -99,6 +100,123 @@ class System : public SimObject, public PCEventScope public: + class Threads + { + private: + struct Thread + { + ThreadContext *context = nullptr; + bool active = false; + BaseRemoteGDB *gdb = nullptr; + }; + + std::vector threads; + + Thread & + thread(ContextID id) + { + assert(id < size()); + return threads[id]; + } + + const Thread & + thread(ContextID id) const + { + assert(id < size()); + return threads[id]; + } + + ContextID insert(ThreadContext *tc, ContextID id=InvalidContextID); + void replace(ThreadContext *tc, ContextID id); + + friend class System; + + public: + class const_iterator + { + private: + const Threads &threads; + int pos; + + friend class Threads; + + const_iterator(const Threads &_threads, int _pos) : + threads(_threads), pos(_pos) + {} + + public: + const_iterator(const const_iterator &) = default; + const_iterator &operator = (const const_iterator &) = default; + + using iterator_category = std::forward_iterator_tag; + using value_type = ThreadContext *; + using difference_type = int; + using pointer = const value_type *; + using reference = const value_type &; + + const_iterator & + operator ++ () + { + pos++; + return *this; + } + + const_iterator + operator ++ (int) + { + return const_iterator(threads, pos++); + } + + reference operator * () { return threads.thread(pos).context; } + pointer operator -> () { return &threads.thread(pos).context; } + + bool + operator == (const const_iterator &other) const + { + return &threads == &other.threads && pos == other.pos; + } + + bool + operator != (const const_iterator &other) const + { + return !(*this == other); + } + }; + + ThreadContext *findFree(); + + ThreadContext * + operator [](ContextID id) const + { + return thread(id).context; + } + + void markActive(ContextID id) { thread(id).active = true; } + + int size() const { return threads.size(); } + bool empty() const { return threads.empty(); } + int numRunning() const; + int + numActive() const + { + int count = 0; + for (auto &thread: threads) { + if (thread.active) + count++; + } + return count; + } + + void resume(ContextID id, Tick when); + + const_iterator begin() const { return const_iterator(*this, 0); } + const_iterator end() const { return const_iterator(*this, size()); } + }; + + /** + * After all objects have been created and all ports are + * connected, check that the system port is connected. + */ void init() override; void startup() override; @@ -179,14 +297,7 @@ class System : public SimObject, public PCEventScope */ unsigned int cacheLineSize() const { return _cacheLineSize; } - std::vector threadContexts; - ThreadContext *findFreeContext(); - - ThreadContext * - getThreadContext(ContextID tid) const - { - return threadContexts[tid]; - } + Threads threads; const bool multiThread; @@ -195,12 +306,6 @@ class System : public SimObject, public PCEventScope bool schedule(PCEvent *event) override; bool remove(PCEvent *event) override; - unsigned numContexts() const { return threadContexts.size(); } - - /** Return number of running (non-halted) thread contexts in - * system. These threads could be Active or Suspended. */ - int numRunningContexts(); - Addr pagePtr; uint64_t init_param; @@ -288,7 +393,6 @@ class System : public SimObject, public PCEventScope uint64_t workItemsBegin; uint64_t workItemsEnd; uint32_t numWorkIds; - std::vector activeCpus; /** This array is a per-system list of all devices capable of issuing a * memory system request and an associated string for each master id. @@ -415,14 +519,8 @@ class System : public SimObject, public PCEventScope int markWorkItem(int index) { - int count = 0; - assert(index < activeCpus.size()); - activeCpus[index] = true; - for (std::vector::iterator i = activeCpus.begin(); - i < activeCpus.end(); i++) { - if (*i) count++; - } - return count; + threads.markActive(index); + return threads.numActive(); } inline void workItemBegin(uint32_t tid, uint32_t workid) @@ -467,8 +565,8 @@ class System : public SimObject, public PCEventScope /// @return Starting address of first page Addr allocPhysPages(int npages); - ContextID registerThreadContext(ThreadContext *tc, - ContextID assigned = InvalidContextID); + ContextID registerThreadContext( + ThreadContext *tc, ContextID assigned=InvalidContextID); void replaceThreadContext(ThreadContext *tc, ContextID context_id); void serialize(CheckpointOut &cp) const override;