m1n1.proxutils: Add ProxyUtils.{read,write}

These implement generic-size read/write. Use them for hypervisor MMIO
handling and for regmaps.

Signed-off-by: Hector Martin <marcan@marcan.st>
This commit is contained in:
Hector Martin 2021-06-18 02:19:39 +09:00
parent 990f5b3995
commit 0ee96c7ffd
4 changed files with 35 additions and 20 deletions

View file

@ -52,7 +52,7 @@ class DART(RegMap):
TTBR3 = irange(0x20c, 16, 16), R_TTBR
def __init__(self, base):
super().__init__(p, base)
super().__init__(u, base)
self.base = base
def dump_table2(self, base, l1_addr):

View file

@ -130,21 +130,7 @@ class HV(Reloadable):
"p": self.p,
"u": self.u,
"TraceMode": TraceMode,
}
self.mmio_rd = [
lambda addr: [proxy.read8(addr)],
lambda addr: [proxy.read16(addr)],
lambda addr: [proxy.read32(addr)],
lambda addr: [proxy.read64(addr)],
lambda addr: [proxy.read64(addr), proxy.read64(addr + 8)],
]
self.mmio_wr = [
lambda addr, data: proxy.write8(addr, data),
lambda addr, data: proxy.write16(addr, data),
lambda addr, data: proxy.write32(addr, data),
lambda addr, data: proxy.write64(addr, data),
lambda addr, data: (proxy.write64(addr, data[0]), proxy.write64(addr + 8, data[1])),
]
})
for attr in dir(self):
a = getattr(self, attr)
@ -336,9 +322,11 @@ class HV(Reloadable):
first += 1
elif mode == TraceMode.SYNC:
if data.flags.WRITE:
self.mmio_wr[data.flags.WIDTH](data.addr, wval)
self.u.write(data.addr, wval, 8 << data.flags.WIDTH)
else:
val = self.mmio_rd[data.flags.WIDTH](data.addr)
val = self.u.read(data.addr, 8 << data.flags.WIDTH)
if not isinstance(val, list) and not isinstance(val, tuple):
val = [val]
else:
raise Exception(f"VM hook with unexpected mapping at {data.addr:#x}: {maps[0][0].name}")

View file

@ -68,6 +68,33 @@ class ProxyUtils(Reloadable):
"gl2": (self.proxy.gl2_call, REGION_RX_EL1),
"gl1": (self.proxy.gl1_call, 0),
}
self._read = {
8: lambda addr: self.proxy.read8(addr),
16: lambda addr: self.proxy.read16(addr),
32: lambda addr: self.proxy.read32(addr),
64: lambda addr: self.proxy.read64(addr),
128: lambda addr: [self.proxy.read64(addr),
self.proxy.read64(addr + 8)],
}
self._write = {
8: lambda addr, data: self.proxy.write8(addr, data),
16: lambda addr, data: self.proxy.write16(addr, data),
32: lambda addr, data: self.proxy.write32(addr, data),
64: lambda addr, data: self.proxy.write64(addr, data),
128: lambda addr, data: (self.proxy.write64(addr, data[0]),
self.proxy.write64(addr + 8, data[1])),
}
def read(self, addr, width):
val = self._read[width](addr)
if self.proxy.get_exc_count():
raise ProxyError("Exception occurred")
return val
def write(self, addr, data, width):
self._write[width](addr, data)
if self.proxy.get_exc_count():
raise ProxyError("Exception occurred")
def mrs(self, reg, *, silent=False, call=None):
op0, op1, CRn, CRm, op2 = sysreg_parse(reg)

View file

@ -558,8 +558,8 @@ class RegMap(Reloadable, metaclass=RegMeta):
for name, (addr, rcls) in self._namemap.items():
width = rcls.__WIDTH__
rd = getattr(backend, f"read{width}")
wr = getattr(backend, f"write{width}")
rd = lambda addr: backend.read(addr, width)
wr = lambda addr, data: backend.write(addr, data, width)
if isinstance(addr, range):
self._accessor[name] = RegArrayAccessor(addr, rcls, rd, wr, base)
else: