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>
This commit is contained in:
parent
ed8da05cdb
commit
ca661fae81
@ -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);
|
||||
|
102
hw/ppc/pnv_bmc.c
102
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);
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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)
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user