Skip to content

Commit

Permalink
dev-arm: Handle translation aborts and add IRQ support to the SMMU (#920
Browse files Browse the repository at this point in the history
)

At the moment the SMMU is not handling translation errors gracefully the
way it is described by the SMMUv3 spec: whenever a translation fault
arises, simulation aborts as a whole. With this PR we add minimal
support for
translation fault handling, which means:

1) Not aborting simulation, but rather:
2) Writing an event entry to the SMMU_EVENTQ (event queue)
3) Signaling the PE an error arose and there is an event entry to be
consumed. The signaling is achieved
with the addition of the eventq SPI. Using an MSI is also possible
though it is currently disabled by the SMMU_IDR0.MSI being set to zero.

The PR is addressing issues reported by
https://github.com/orgs/gem5/discussions/898
  • Loading branch information
giactra committed Mar 8, 2024
2 parents f70dc88 + 5161195 commit bbde68c
Show file tree
Hide file tree
Showing 9 changed files with 389 additions and 102 deletions.
8 changes: 6 additions & 2 deletions src/dev/arm/RealView.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# Copyright (c) 2009-2022 Arm Limited
# Copyright (c) 2009-2022, 2024 Arm Limited
# All rights reserved.
#
# The license below extends only to copyright in the software and shall
Expand Down Expand Up @@ -1283,6 +1283,7 @@ class VExpress_GEM5_Base(RealView):
95 : HDLCD
96- 98: GPU (reserved)
100-103: PCI
106 : SMMU event queue
130 : System Watchdog (SP805)
256-319: MSI frame 0 (gem5-specific, SPIs)
320-511: Unused
Expand Down Expand Up @@ -1508,7 +1509,10 @@ def attachSmmu(self, devices, bus):
if hasattr(self, "smmu"):
m5.fatal("A SMMU has already been instantiated\n")

self.smmu = SMMUv3(reg_map=AddrRange(0x2B400000, size=0x00020000))
self.smmu = SMMUv3(
reg_map=AddrRange(0x2B400000, size=0x00020000),
eventq_irq=ArmSPI(num=106),
)

self.smmu.request = bus.cpu_side_ports
self.smmu.control = bus.mem_side_ports
Expand Down
1 change: 1 addition & 0 deletions src/dev/arm/SConscript
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,7 @@ Source('kmi.cc', tags='arm isa')
Source('smmu_v3.cc', tags='arm isa');
Source('smmu_v3_caches.cc', tags='arm isa');
Source('smmu_v3_cmdexec.cc', tags='arm isa');
Source('smmu_v3_defs.cc', tags='arm isa');
Source('smmu_v3_events.cc', tags='arm isa');
Source('smmu_v3_ports.cc', tags='arm isa');
Source('smmu_v3_proc.cc', tags='arm isa');
Expand Down
32 changes: 24 additions & 8 deletions src/dev/arm/SMMUv3.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# Copyright (c) 2013, 2018-2020 ARM Limited
# Copyright (c) 2013, 2018-2020, 2024 Arm Limited
# All rights reserved
#
# The license below extends only to copyright in the software and shall
Expand Down Expand Up @@ -100,13 +100,6 @@ class SMMUv3(ClockedObject):
reg_map = Param.AddrRange("Address range for control registers")
system = Param.System(Parent.any, "System this device is part of")

irq_interface_enable = Param.Bool(
False,
"This flag enables software to program SMMU_IRQ_CTRL and "
"SMMU_IRQ_CTRLACK as if the model implemented architectural "
"interrupt sources",
)

device_interfaces = VectorParam.SMMUv3DeviceInterface(
[], "Responder interfaces"
)
Expand Down Expand Up @@ -200,6 +193,13 @@ class SMMUv3(ClockedObject):
# [7:0] (0 = SMMUv3.0) (1 = SMMUv3.1)
smmu_aidr = Param.UInt32(0, "SMMU_AIDR register")

eventq_irq = Param.ArmSPI(
NULL,
"Event Queue Interrupt. If set to NULL it means a wired "
"implementation of the interrupt is not supported. "
"In that case MSIs should be used",
)

def generateDeviceTree(self, state):
reg_addr = self.reg_map.start
reg_size = self.reg_map.size()
Expand All @@ -210,6 +210,22 @@ def generateDeviceTree(self, state):
"reg", state.addrCells(reg_addr) + state.sizeCells(reg_size)
)
)

gic = self._parent.unproxy(self).gic

wired_interrupts = []
if self.eventq_irq != NULL:
wired_interrupts += self.eventq_irq.generateFdtProperty(gic)

if wired_interrupts:
node.append(FdtPropertyWords("interrupts", wired_interrupts))
node.append(
FdtPropertyWords(
"interrupt-names",
["eventq"],
)
)

node.append(FdtPropertyWords("#iommu-cells", [1]))

node.appendPhandle(self)
Expand Down
12 changes: 6 additions & 6 deletions src/dev/arm/smmu_v3.cc
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2013, 2018-2020 ARM Limited
* Copyright (c) 2013, 2018-2020, 2024 Arm Limited
* All rights reserved
*
* The license below extends only to copyright in the software and shall
Expand Down Expand Up @@ -48,6 +48,7 @@
#include "base/types.hh"
#include "debug/Checkpoint.hh"
#include "debug/SMMUv3.hh"
#include "dev/arm/base_gic.hh"
#include "dev/arm/smmu_v3_transl.hh"
#include "mem/packet_access.hh"
#include "sim/system.hh"
Expand All @@ -62,7 +63,7 @@ SMMUv3::SMMUv3(const SMMUv3Params &params) :
requestPort(name() + ".request", *this),
tableWalkPort(name() + ".walker", *this),
controlPort(name() + ".control", *this, params.reg_map),
irqInterfaceEnable(params.irq_interface_enable),
eventqInterrupt(params.eventq_irq ? params.eventq_irq->get() : nullptr),
tlb(params.tlb_entries, params.tlb_assoc, params.tlb_policy, this),
configCache(params.cfg_entries, params.cfg_assoc, params.cfg_policy, this),
ipaCache(params.ipa_entries, params.ipa_assoc, params.ipa_policy, this),
Expand Down Expand Up @@ -618,10 +619,9 @@ SMMUv3::writeControl(PacketPtr pkt)
break;
case offsetof(SMMURegs, irq_ctrl):
assert(pkt->getSize() == sizeof(uint32_t));
if (irqInterfaceEnable) {
warn("SMMUv3::%s No support for interrupt sources", __func__);
regs.irq_ctrl = regs.irq_ctrlack = pkt->getLE<uint32_t>();
}
warn("SMMUv3::%s No support for GERROR and PRI interrupt sources",
__func__);
regs.irq_ctrl = regs.irq_ctrlack = pkt->getLE<uint32_t>();
break;

case offsetof(SMMURegs, cr1):
Expand Down
8 changes: 6 additions & 2 deletions src/dev/arm/smmu_v3.hh
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2013, 2018-2020 ARM Limited
* Copyright (c) 2013, 2018-2020, 2024 ARM Limited
* All rights reserved
*
* The license below extends only to copyright in the software and shall
Expand Down Expand Up @@ -79,6 +79,8 @@
namespace gem5
{

class ArmInterruptPin;

class SMMUTranslationProcess;

class SMMUv3 : public ClockedObject
Expand All @@ -97,7 +99,9 @@ class SMMUv3 : public ClockedObject
SMMUTableWalkPort tableWalkPort;
SMMUControlPort controlPort;

const bool irqInterfaceEnable;
// This could be nullptr if wired implementation of the
// event queue interrupt is not supported
ArmInterruptPin * const eventqInterrupt;

ARMArchTLB tlb;
ConfigCache configCache;
Expand Down
51 changes: 51 additions & 0 deletions src/dev/arm/smmu_v3_defs.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
/*
* Copyright (c) 2024 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.
*/

#include "dev/arm/smmu_v3_defs.hh"

namespace gem5
{

std::string
SMMUEvent::print() const
{
return csprintf("type=%#x sid=%#x ssid=%#x va=%#08x\n",
data.dw0.eventType, data.dw0.streamId, data.dw0.substreamId,
data.dw2.inputAddr);
}

} // namespace gem5
86 changes: 67 additions & 19 deletions src/dev/arm/smmu_v3_defs.hh
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2013, 2018-2019 ARM Limited
* Copyright (c) 2013, 2018-2019, 2024 Arm Limited
* All rights reserved
*
* The license below extends only to copyright in the software and shall
Expand Down Expand Up @@ -102,10 +102,42 @@ enum
Q_BASE_ADDR_MASK = 0x0000ffffffffffe0ULL,
Q_BASE_SIZE_MASK = 0x000000000000001fULL,

E_BASE_ENABLE_MASK = 0x8000000000000000ULL,
E_BASE_ADDR_MASK = 0x0000fffffffffffcULL,
};

BitUnion32(IDR0)
Bitfield<0> s2p;
Bitfield<1> s1p;
Bitfield<3, 2> ttf;
Bitfield<4> cohacc;
Bitfield<5> btm;
Bitfield<7, 6> httu;
Bitfield<8> dormhint;
Bitfield<9> hyp;
Bitfield<10> ats;
Bitfield<11> ns1ats;
Bitfield<12> asid16;
Bitfield<13> msi;
Bitfield<14> sev;
Bitfield<15> atos;
Bitfield<16> pri;
Bitfield<17> vmw;
Bitfield<18> vmid16;
Bitfield<19> cd2l;
Bitfield<20> vatos;
Bitfield<22, 21> ttEndian;
Bitfield<23> atsRecErr;
Bitfield<25, 24> stallModel;
Bitfield<26> termModel;
Bitfield<28, 27> stLevel;
EndBitUnion(IDR0)

BitUnion32(IRQCtrl)
Bitfield<0> gerrorIrqEn;
Bitfield<1> priqIrqEn;
Bitfield<2> eventqIrqEn;
EndBitUnion(IRQCtrl)

union SMMURegs
{
uint8_t data[SMMU_REG_SIZE];
Expand Down Expand Up @@ -384,25 +416,41 @@ struct SMMUCommand
}
};

enum SMMUEventTypes
{
EVT_FAULT = 0x0001,
};

enum SMMUEventFlags
{
EVF_WRITE = 0x0001,
};

struct SMMUEvent
{
uint16_t type;
uint16_t stag;
uint32_t flags;
uint32_t streamId;
uint32_t substreamId;
uint64_t va;
uint64_t ipa;
struct Data {
BitUnion64(DWORD0)
Bitfield<7, 0> eventType;
Bitfield<11> ssv;
Bitfield<31, 12> substreamId;
Bitfield<63, 32> streamId;
EndBitUnion(DWORD0)
DWORD0 dw0;

BitUnion64(DWORD1)
Bitfield<16, 0> stag;
Bitfield<33> pnu;
Bitfield<34> ind;
Bitfield<35> rnw;
Bitfield<38> nsipa;
Bitfield<39> s2;
Bitfield<41, 40> clss;
EndBitUnion(DWORD1)
DWORD1 dw1;

BitUnion64(DWORD2)
Bitfield<63, 0> inputAddr;
EndBitUnion(DWORD2)
DWORD2 dw2;

BitUnion64(DWORD3)
Bitfield<51, 3> fetchAddr;
Bitfield<51, 12> ipa;
EndBitUnion(DWORD3)
DWORD3 dw3;
} data;

std::string print() const;
};

enum
Expand Down
Loading

0 comments on commit bbde68c

Please sign in to comment.