aboutsummaryrefslogtreecommitdiff
path: root/hw
diff options
context:
space:
mode:
authorCédric Le Goater <clg@kaod.org>2019-10-28 08:00:27 +0100
committerDavid Gibson <david@gibson.dropbear.id.au>2019-12-17 10:39:47 +1100
commitca661fae81d3b36b72c316a63165d9318dbd2439 (patch)
tree5171d2957f99f67c48132c71de30eff9d7ace561 /hw
parented8da05cdb18a32a8a41165d5b7b367bc05fdab0 (diff)
downloadqemu-ca661fae81d3b36b72c316a63165d9318dbd2439.zip
qemu-ca661fae81d3b36b72c316a63165d9318dbd2439.tar.gz
qemu-ca661fae81d3b36b72c316a63165d9318dbd2439.tar.bz2
ppc/pnv: Add HIOMAP commands
This activates HIOMAP support on the QEMU PowerNV machine. The PnvPnor model is used to access the flash contents. The model simply maps the contents at a fix offset and enables or disables the mapping. HIOMAP Protocol description : https://github.com/openbmc/hiomapd/blob/master/Documentation/protocol.md Reviewed-by: Joel Stanley <joel@jms.id.au> Signed-off-by: Cédric Le Goater <clg@kaod.org> Message-Id: <20191028070027.22752-3-clg@kaod.org> Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
Diffstat (limited to 'hw')
-rw-r--r--hw/ppc/pnv.c1
-rw-r--r--hw/ppc/pnv_bmc.c102
-rw-r--r--hw/ppc/pnv_lpc.c13
3 files changed, 116 insertions, 0 deletions
diff --git a/hw/ppc/pnv.c b/hw/ppc/pnv.c
index a2a8b97..c3ac0d6 100644
--- a/hw/ppc/pnv.c
+++ b/hw/ppc/pnv.c
@@ -569,6 +569,7 @@ static void pnv_reset(MachineState *machine)
obj = object_resolve_path_type("", "ipmi-bmc-sim", NULL);
if (obj) {
pnv->bmc = IPMI_BMC(obj);
+ pnv_bmc_hiomap(pnv->bmc);
}
fdt = pnv_dt_create(machine);
diff --git a/hw/ppc/pnv_bmc.c b/hw/ppc/pnv_bmc.c
index dc5e918..aa5c895 100644
--- a/hw/ppc/pnv_bmc.c
+++ b/hw/ppc/pnv_bmc.c
@@ -114,3 +114,105 @@ void pnv_dt_bmc_sensors(IPMIBmc *bmc, void *fdt)
sdr->sensor_type)));
}
}
+
+/*
+ * HIOMAP protocol handler
+ */
+#define HIOMAP_C_RESET 1
+#define HIOMAP_C_GET_INFO 2
+#define HIOMAP_C_GET_FLASH_INFO 3
+#define HIOMAP_C_CREATE_READ_WINDOW 4
+#define HIOMAP_C_CLOSE_WINDOW 5
+#define HIOMAP_C_CREATE_WRITE_WINDOW 6
+#define HIOMAP_C_MARK_DIRTY 7
+#define HIOMAP_C_FLUSH 8
+#define HIOMAP_C_ACK 9
+#define HIOMAP_C_ERASE 10
+#define HIOMAP_C_DEVICE_NAME 11
+#define HIOMAP_C_LOCK 12
+
+#define BLOCK_SHIFT 12 /* 4K */
+
+static uint16_t bytes_to_blocks(uint32_t bytes)
+{
+ return bytes >> BLOCK_SHIFT;
+}
+
+static void hiomap_cmd(IPMIBmcSim *ibs, uint8_t *cmd, unsigned int cmd_len,
+ RspBuffer *rsp)
+{
+ PnvMachineState *pnv = PNV_MACHINE(qdev_get_machine());
+ PnvPnor *pnor = pnv->pnor;
+ uint32_t pnor_size = pnor->size;
+ uint32_t pnor_addr = PNOR_SPI_OFFSET;
+ bool readonly = false;
+
+ rsp_buffer_push(rsp, cmd[2]);
+ rsp_buffer_push(rsp, cmd[3]);
+
+ switch (cmd[2]) {
+ case HIOMAP_C_MARK_DIRTY:
+ case HIOMAP_C_FLUSH:
+ case HIOMAP_C_ERASE:
+ case HIOMAP_C_ACK:
+ break;
+
+ case HIOMAP_C_GET_INFO:
+ rsp_buffer_push(rsp, 2); /* Version 2 */
+ rsp_buffer_push(rsp, BLOCK_SHIFT); /* block size */
+ rsp_buffer_push(rsp, 0); /* Timeout */
+ rsp_buffer_push(rsp, 0); /* Timeout */
+ break;
+
+ case HIOMAP_C_GET_FLASH_INFO:
+ rsp_buffer_push(rsp, bytes_to_blocks(pnor_size) & 0xFF);
+ rsp_buffer_push(rsp, bytes_to_blocks(pnor_size) >> 8);
+ rsp_buffer_push(rsp, 0x01); /* erase size */
+ rsp_buffer_push(rsp, 0x00); /* erase size */
+ break;
+
+ case HIOMAP_C_CREATE_READ_WINDOW:
+ readonly = true;
+ /* Fall through */
+
+ case HIOMAP_C_CREATE_WRITE_WINDOW:
+ memory_region_set_readonly(&pnor->mmio, readonly);
+ memory_region_set_enabled(&pnor->mmio, true);
+
+ rsp_buffer_push(rsp, bytes_to_blocks(pnor_addr) & 0xFF);
+ rsp_buffer_push(rsp, bytes_to_blocks(pnor_addr) >> 8);
+ rsp_buffer_push(rsp, bytes_to_blocks(pnor_size) & 0xFF);
+ rsp_buffer_push(rsp, bytes_to_blocks(pnor_size) >> 8);
+ rsp_buffer_push(rsp, 0x00); /* offset */
+ rsp_buffer_push(rsp, 0x00); /* offset */
+ break;
+
+ case HIOMAP_C_CLOSE_WINDOW:
+ memory_region_set_enabled(&pnor->mmio, false);
+ break;
+
+ case HIOMAP_C_DEVICE_NAME:
+ case HIOMAP_C_RESET:
+ case HIOMAP_C_LOCK:
+ default:
+ qemu_log_mask(LOG_GUEST_ERROR, "HIOMAP: unknow command %02X\n", cmd[2]);
+ break;
+ }
+}
+
+#define HIOMAP 0x5a
+
+static const IPMICmdHandler hiomap_cmds[] = {
+ [HIOMAP] = { hiomap_cmd, 3 },
+};
+
+static const IPMINetfn hiomap_netfn = {
+ .cmd_nums = ARRAY_SIZE(hiomap_cmds),
+ .cmd_handlers = hiomap_cmds
+};
+
+int pnv_bmc_hiomap(IPMIBmc *bmc)
+{
+ return ipmi_sim_register_netfn(IPMI_BMC_SIMULATOR(bmc),
+ IPMI_NETFN_OEM, &hiomap_netfn);
+}
diff --git a/hw/ppc/pnv_lpc.c b/hw/ppc/pnv_lpc.c
index c5a85c3..dd5374c 100644
--- a/hw/ppc/pnv_lpc.c
+++ b/hw/ppc/pnv_lpc.c
@@ -810,6 +810,7 @@ ISABus *pnv_lpc_isa_create(PnvLpcController *lpc, bool use_cpld, Error **errp)
ISABus *isa_bus;
qemu_irq *irqs;
qemu_irq_handler handler;
+ PnvMachineState *pnv = PNV_MACHINE(qdev_get_machine());
/* let isa_bus_new() create its own bridge on SysBus otherwise
* devices speficied on the command line won't find the bus and
@@ -834,5 +835,17 @@ ISABus *pnv_lpc_isa_create(PnvLpcController *lpc, bool use_cpld, Error **errp)
irqs = qemu_allocate_irqs(handler, lpc, ISA_NUM_IRQS);
isa_bus_irqs(isa_bus, irqs);
+
+ /*
+ * TODO: Map PNOR on the LPC FW address space on demand ?
+ */
+ memory_region_add_subregion(&lpc->isa_fw, PNOR_SPI_OFFSET,
+ &pnv->pnor->mmio);
+ /*
+ * Start disabled. The HIOMAP protocol will activate the mapping
+ * with HIOMAP_C_CREATE_WRITE_WINDOW
+ */
+ memory_region_set_enabled(&pnv->pnor->mmio, false);
+
return isa_bus;
}