Skip to content

Commit

Permalink
ppc/pnv: Add HIOMAP commands
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
legoater authored and dgibson committed Dec 16, 2019
1 parent ed8da05 commit ca661fa
Show file tree
Hide file tree
Showing 5 changed files with 122 additions and 0 deletions.
1 change: 1 addition & 0 deletions hw/ppc/pnv.c
Expand Up @@ -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);
Expand Down
102 changes: 102 additions & 0 deletions hw/ppc/pnv_bmc.c
Expand Up @@ -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);
}
13 changes: 13 additions & 0 deletions hw/ppc/pnv_lpc.c
Expand Up @@ -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
Expand All @@ -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;
}
1 change: 1 addition & 0 deletions include/hw/ppc/pnv.h
Expand Up @@ -198,6 +198,7 @@ static inline bool pnv_is_power9(PnvMachineState *pnv)
*/
void pnv_dt_bmc_sensors(IPMIBmc *bmc, void *fdt);
void pnv_bmc_powerdown(IPMIBmc *bmc);
int pnv_bmc_hiomap(IPMIBmc *bmc);

/*
* POWER8 MMIO base addresses
Expand Down
5 changes: 5 additions & 0 deletions include/hw/ppc/pnv_pnor.h
Expand Up @@ -9,6 +9,11 @@
#ifndef _PPC_PNV_PNOR_H
#define _PPC_PNV_PNOR_H

/*
* PNOR offset on the LPC FW address space
*/
#define PNOR_SPI_OFFSET 0x0c000000UL

#define TYPE_PNV_PNOR "pnv-pnor"
#define PNV_PNOR(obj) OBJECT_CHECK(PnvPnor, (obj), TYPE_PNV_PNOR)

Expand Down

0 comments on commit ca661fa

Please sign in to comment.