qemu with hax to log dma reads & writes jcs.org/2018/11/12/vfio

aspeed: vic: Add support for legacy register interface

The legacy interface only supported up to 32 IRQs, which became
restrictive around the AST2400 generation. QEMU support for the SoCs
started with the AST2400 along with an effort to reimplement and
upstream drivers for Linux, so up until this point the consumers of the
QEMU ASPEED support only required the 64 IRQ register interface.

In an effort to support older BMC firmware, add support for the 32 IRQ
interface.

Signed-off-by: Andrew Jeffery <andrew@aj.id.au>
Signed-off-by: Cédric Le Goater <clg@kaod.org>
Reviewed-by: Joel Stanley <joel@jms.id.au>
Message-id: 20190618165311.27066-22-clg@kaod.org
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>

authored by

Andrew Jeffery and committed by
Peter Maydell
ebd205c0 118c82e7

+63 -42
+63 -42
hw/intc/aspeed_vic.c
··· 104 104 105 105 static uint64_t aspeed_vic_read(void *opaque, hwaddr offset, unsigned size) 106 106 { 107 + AspeedVICState *s = (AspeedVICState *)opaque; 108 + hwaddr n_offset; 107 109 uint64_t val; 108 - const bool high = !!(offset & 0x4); 109 - hwaddr n_offset = (offset & ~0x4); 110 - AspeedVICState *s = (AspeedVICState *)opaque; 110 + bool high; 111 111 112 112 if (offset < AVIC_NEW_BASE_OFFSET) { 113 - qemu_log_mask(LOG_UNIMP, "%s: Ignoring read from legacy registers " 114 - "at 0x%" HWADDR_PRIx "[%u]\n", __func__, offset, size); 115 - return 0; 113 + high = false; 114 + n_offset = offset; 115 + } else { 116 + high = !!(offset & 0x4); 117 + n_offset = (offset & ~0x4); 116 118 } 117 119 118 - n_offset -= AVIC_NEW_BASE_OFFSET; 119 - 120 120 switch (n_offset) { 121 - case 0x0: /* IRQ Status */ 121 + case 0x80: /* IRQ Status */ 122 + case 0x00: 122 123 val = s->raw & ~s->select & s->enable; 123 124 break; 124 - case 0x08: /* FIQ Status */ 125 + case 0x88: /* FIQ Status */ 126 + case 0x04: 125 127 val = s->raw & s->select & s->enable; 126 128 break; 127 - case 0x10: /* Raw Interrupt Status */ 129 + case 0x90: /* Raw Interrupt Status */ 130 + case 0x08: 128 131 val = s->raw; 129 132 break; 130 - case 0x18: /* Interrupt Selection */ 133 + case 0x98: /* Interrupt Selection */ 134 + case 0x0c: 131 135 val = s->select; 132 136 break; 133 - case 0x20: /* Interrupt Enable */ 137 + case 0xa0: /* Interrupt Enable */ 138 + case 0x10: 134 139 val = s->enable; 135 140 break; 136 - case 0x30: /* Software Interrupt */ 141 + case 0xb0: /* Software Interrupt */ 142 + case 0x18: 137 143 val = s->trigger; 138 144 break; 139 - case 0x40: /* Interrupt Sensitivity */ 145 + case 0xc0: /* Interrupt Sensitivity */ 146 + case 0x24: 140 147 val = s->sense; 141 148 break; 142 - case 0x48: /* Interrupt Both Edge Trigger Control */ 149 + case 0xc8: /* Interrupt Both Edge Trigger Control */ 150 + case 0x28: 143 151 val = s->dual_edge; 144 152 break; 145 - case 0x50: /* Interrupt Event */ 153 + case 0xd0: /* Interrupt Event */ 154 + case 0x2c: 146 155 val = s->event; 147 156 break; 148 - case 0x60: /* Edge Triggered Interrupt Status */ 157 + case 0xe0: /* Edge Triggered Interrupt Status */ 149 158 val = s->raw & ~s->sense; 150 159 break; 151 160 /* Illegal */ 152 - case 0x28: /* Interrupt Enable Clear */ 153 - case 0x38: /* Software Interrupt Clear */ 154 - case 0x58: /* Edge Triggered Interrupt Clear */ 161 + case 0xa8: /* Interrupt Enable Clear */ 162 + case 0xb8: /* Software Interrupt Clear */ 163 + case 0xd8: /* Edge Triggered Interrupt Clear */ 155 164 qemu_log_mask(LOG_GUEST_ERROR, 156 165 "%s: Read of write-only register with offset 0x%" 157 166 HWADDR_PRIx "\n", __func__, offset); ··· 166 175 } 167 176 if (high) { 168 177 val = extract64(val, 32, 19); 178 + } else { 179 + val = extract64(val, 0, 32); 169 180 } 170 181 trace_aspeed_vic_read(offset, size, val); 171 182 return val; ··· 174 185 static void aspeed_vic_write(void *opaque, hwaddr offset, uint64_t data, 175 186 unsigned size) 176 187 { 177 - const bool high = !!(offset & 0x4); 178 - hwaddr n_offset = (offset & ~0x4); 179 188 AspeedVICState *s = (AspeedVICState *)opaque; 189 + hwaddr n_offset; 190 + bool high; 180 191 181 192 if (offset < AVIC_NEW_BASE_OFFSET) { 182 - qemu_log_mask(LOG_UNIMP, 183 - "%s: Ignoring write to legacy registers at 0x%" 184 - HWADDR_PRIx "[%u] <- 0x%" PRIx64 "\n", __func__, offset, 185 - size, data); 186 - return; 193 + high = false; 194 + n_offset = offset; 195 + } else { 196 + high = !!(offset & 0x4); 197 + n_offset = (offset & ~0x4); 187 198 } 188 199 189 - n_offset -= AVIC_NEW_BASE_OFFSET; 190 200 trace_aspeed_vic_write(offset, size, data); 191 201 192 202 /* Given we have members using separate enable/clear registers, deposit64() ··· 201 211 } 202 212 203 213 switch (n_offset) { 204 - case 0x18: /* Interrupt Selection */ 214 + case 0x98: /* Interrupt Selection */ 215 + case 0x0c: 205 216 /* Register has deposit64() semantics - overwrite requested 32 bits */ 206 217 if (high) { 207 218 s->select &= AVIC_L_MASK; ··· 210 221 } 211 222 s->select |= data; 212 223 break; 213 - case 0x20: /* Interrupt Enable */ 224 + case 0xa0: /* Interrupt Enable */ 225 + case 0x10: 214 226 s->enable |= data; 215 227 break; 216 - case 0x28: /* Interrupt Enable Clear */ 228 + case 0xa8: /* Interrupt Enable Clear */ 229 + case 0x14: 217 230 s->enable &= ~data; 218 231 break; 219 - case 0x30: /* Software Interrupt */ 232 + case 0xb0: /* Software Interrupt */ 233 + case 0x18: 220 234 qemu_log_mask(LOG_UNIMP, "%s: Software interrupts unavailable. " 221 235 "IRQs requested: 0x%016" PRIx64 "\n", __func__, data); 222 236 break; 223 - case 0x38: /* Software Interrupt Clear */ 237 + case 0xb8: /* Software Interrupt Clear */ 238 + case 0x1c: 224 239 qemu_log_mask(LOG_UNIMP, "%s: Software interrupts unavailable. " 225 240 "IRQs to be cleared: 0x%016" PRIx64 "\n", __func__, data); 226 241 break; 227 - case 0x50: /* Interrupt Event */ 242 + case 0xd0: /* Interrupt Event */ 228 243 /* Register has deposit64() semantics - overwrite the top four valid 229 244 * IRQ bits, as only the top four IRQs (GPIOs) can change their event 230 245 * type */ ··· 236 251 "Ignoring invalid write to interrupt event register"); 237 252 } 238 253 break; 239 - case 0x58: /* Edge Triggered Interrupt Clear */ 254 + case 0xd8: /* Edge Triggered Interrupt Clear */ 255 + case 0x38: 240 256 s->raw &= ~(data & ~s->sense); 241 257 break; 242 - case 0x00: /* IRQ Status */ 243 - case 0x08: /* FIQ Status */ 244 - case 0x10: /* Raw Interrupt Status */ 245 - case 0x40: /* Interrupt Sensitivity */ 246 - case 0x48: /* Interrupt Both Edge Trigger Control */ 247 - case 0x60: /* Edge Triggered Interrupt Status */ 258 + case 0x80: /* IRQ Status */ 259 + case 0x00: 260 + case 0x88: /* FIQ Status */ 261 + case 0x04: 262 + case 0x90: /* Raw Interrupt Status */ 263 + case 0x08: 264 + case 0xc0: /* Interrupt Sensitivity */ 265 + case 0x24: 266 + case 0xc8: /* Interrupt Both Edge Trigger Control */ 267 + case 0x28: 268 + case 0xe0: /* Edge Triggered Interrupt Status */ 248 269 qemu_log_mask(LOG_GUEST_ERROR, 249 270 "%s: Write of read-only register with offset 0x%" 250 271 HWADDR_PRIx "\n", __func__, offset);