From d307c28ca9dba7a0677035c9244198b05164c873 Mon Sep 17 00:00:00 2001 From: Corey Minyard Date: Mon, 9 Jan 2017 11:40:20 +0000 Subject: [PATCH 01/21] i2c: Allow I2C devices to NAK start events Add a return value to the event handler. Some I2C devices will NAK if they have no data, so allow them to do this. This required the following changes: Go through all the event handlers and change them to return int and return 0. Modify i2c_start_transfer to terminate the transaction on a NAK. Modify smbus handing to not assert if a NAK occurs on a second operation, and terminate the transaction and return -1 instead. Add some information on semantics to I2CSlaveClass. Signed-off-by: Corey Minyard Reviewed-by: Peter Maydell Signed-off-by: Peter Maydell --- hw/arm/pxa2xx.c | 4 +++- hw/arm/tosa.c | 4 +++- hw/arm/z2.c | 4 +++- hw/audio/wm8750.c | 4 +++- hw/display/ssd0303.c | 4 +++- hw/gpio/max7310.c | 4 +++- hw/i2c/core.c | 33 ++++++++++++++++++++++++++------- hw/i2c/i2c-ddc.c | 4 +++- hw/i2c/smbus.c | 13 +++++++++---- hw/input/lm832x.c | 4 +++- hw/misc/tmp105.c | 3 ++- hw/timer/ds1338.c | 4 +++- hw/timer/twl92230.c | 4 +++- include/hw/i2c/i2c.h | 16 ++++++++++++---- 14 files changed, 79 insertions(+), 26 deletions(-) diff --git a/hw/arm/pxa2xx.c b/hw/arm/pxa2xx.c index bdcf6bcce7..d31b4577f0 100644 --- a/hw/arm/pxa2xx.c +++ b/hw/arm/pxa2xx.c @@ -1258,7 +1258,7 @@ static void pxa2xx_i2c_update(PXA2xxI2CState *s) } /* These are only stubs now. */ -static void pxa2xx_i2c_event(I2CSlave *i2c, enum i2c_event event) +static int pxa2xx_i2c_event(I2CSlave *i2c, enum i2c_event event) { PXA2xxI2CSlaveState *slave = PXA2XX_I2C_SLAVE(i2c); PXA2xxI2CState *s = slave->host; @@ -1280,6 +1280,8 @@ static void pxa2xx_i2c_event(I2CSlave *i2c, enum i2c_event event) break; } pxa2xx_i2c_update(s); + + return 0; } static int pxa2xx_i2c_rx(I2CSlave *i2c) diff --git a/hw/arm/tosa.c b/hw/arm/tosa.c index 39d9dbbae6..c3db996930 100644 --- a/hw/arm/tosa.c +++ b/hw/arm/tosa.c @@ -172,7 +172,7 @@ static int tosa_dac_send(I2CSlave *i2c, uint8_t data) return 0; } -static void tosa_dac_event(I2CSlave *i2c, enum i2c_event event) +static int tosa_dac_event(I2CSlave *i2c, enum i2c_event event) { TosaDACState *s = TOSA_DAC(i2c); @@ -194,6 +194,8 @@ static void tosa_dac_event(I2CSlave *i2c, enum i2c_event event) default: break; } + + return 0; } static int tosa_dac_recv(I2CSlave *s) diff --git a/hw/arm/z2.c b/hw/arm/z2.c index b3a6bbd210..1607cbdb03 100644 --- a/hw/arm/z2.c +++ b/hw/arm/z2.c @@ -220,7 +220,7 @@ static int aer915_send(I2CSlave *i2c, uint8_t data) return 0; } -static void aer915_event(I2CSlave *i2c, enum i2c_event event) +static int aer915_event(I2CSlave *i2c, enum i2c_event event) { AER915State *s = AER915(i2c); @@ -238,6 +238,8 @@ static void aer915_event(I2CSlave *i2c, enum i2c_event event) default: break; } + + return 0; } static int aer915_recv(I2CSlave *slave) diff --git a/hw/audio/wm8750.c b/hw/audio/wm8750.c index 0c6500e96a..f8b5bebfc2 100644 --- a/hw/audio/wm8750.c +++ b/hw/audio/wm8750.c @@ -303,7 +303,7 @@ static void wm8750_reset(I2CSlave *i2c) s->i2c_len = 0; } -static void wm8750_event(I2CSlave *i2c, enum i2c_event event) +static int wm8750_event(I2CSlave *i2c, enum i2c_event event) { WM8750State *s = WM8750(i2c); @@ -321,6 +321,8 @@ static void wm8750_event(I2CSlave *i2c, enum i2c_event event) default: break; } + + return 0; } #define WM8750_LINVOL 0x00 diff --git a/hw/display/ssd0303.c b/hw/display/ssd0303.c index d3017563f3..68a80b9d64 100644 --- a/hw/display/ssd0303.c +++ b/hw/display/ssd0303.c @@ -179,7 +179,7 @@ static int ssd0303_send(I2CSlave *i2c, uint8_t data) return 0; } -static void ssd0303_event(I2CSlave *i2c, enum i2c_event event) +static int ssd0303_event(I2CSlave *i2c, enum i2c_event event) { ssd0303_state *s = SSD0303(i2c); @@ -193,6 +193,8 @@ static void ssd0303_event(I2CSlave *i2c, enum i2c_event event) /* Nothing to do. */ break; } + + return 0; } static void ssd0303_update_display(void *opaque) diff --git a/hw/gpio/max7310.c b/hw/gpio/max7310.c index 1bd5eaf911..f82e3e6555 100644 --- a/hw/gpio/max7310.c +++ b/hw/gpio/max7310.c @@ -129,7 +129,7 @@ static int max7310_tx(I2CSlave *i2c, uint8_t data) return 0; } -static void max7310_event(I2CSlave *i2c, enum i2c_event event) +static int max7310_event(I2CSlave *i2c, enum i2c_event event) { MAX7310State *s = MAX7310(i2c); s->len = 0; @@ -147,6 +147,8 @@ static void max7310_event(I2CSlave *i2c, enum i2c_event event) default: break; } + + return 0; } static const VMStateDescription vmstate_max7310 = { diff --git a/hw/i2c/core.c b/hw/i2c/core.c index e40781ea3b..2c1234cdff 100644 --- a/hw/i2c/core.c +++ b/hw/i2c/core.c @@ -88,18 +88,26 @@ int i2c_bus_busy(I2CBus *bus) return !QLIST_EMPTY(&bus->current_devs); } -/* - * Returns non-zero if the address is not valid. If this is called - * again without an intervening i2c_end_transfer(), like in the SMBus - * case where the operation is switched from write to read, this - * function will not rescan the bus and thus cannot fail. - */ /* TODO: Make this handle multiple masters. */ +/* + * Start or continue an i2c transaction. When this is called for the + * first time or after an i2c_end_transfer(), if it returns an error + * the bus transaction is terminated (or really never started). If + * this is called after another i2c_start_transfer() without an + * intervening i2c_end_transfer(), and it returns an error, the + * transaction will not be terminated. The caller must do it. + * + * This corresponds with the way real hardware works. The SMBus + * protocol uses a start transfer to switch from write to read mode + * without releasing the bus. If that fails, the bus is still + * in a transaction. + */ int i2c_start_transfer(I2CBus *bus, uint8_t address, int recv) { BusChild *kid; I2CSlaveClass *sc; I2CNode *node; + bool bus_scanned = false; if (address == I2C_BROADCAST) { /* @@ -130,6 +138,7 @@ int i2c_start_transfer(I2CBus *bus, uint8_t address, int recv) } } } + bus_scanned = true; } if (QLIST_EMPTY(&bus->current_devs)) { @@ -137,11 +146,21 @@ int i2c_start_transfer(I2CBus *bus, uint8_t address, int recv) } QLIST_FOREACH(node, &bus->current_devs, next) { + int rv; + sc = I2C_SLAVE_GET_CLASS(node->elt); /* If the bus is already busy, assume this is a repeated start condition. */ + if (sc->event) { - sc->event(node->elt, recv ? I2C_START_RECV : I2C_START_SEND); + rv = sc->event(node->elt, recv ? I2C_START_RECV : I2C_START_SEND); + if (rv && !bus->broadcast) { + if (bus_scanned) { + /* First call, terminate the transfer. */ + i2c_end_transfer(bus); + } + return rv; + } } } return 0; diff --git a/hw/i2c/i2c-ddc.c b/hw/i2c/i2c-ddc.c index 1227212934..66899d7233 100644 --- a/hw/i2c/i2c-ddc.c +++ b/hw/i2c/i2c-ddc.c @@ -230,13 +230,15 @@ static void i2c_ddc_reset(DeviceState *ds) s->reg = 0; } -static void i2c_ddc_event(I2CSlave *i2c, enum i2c_event event) +static int i2c_ddc_event(I2CSlave *i2c, enum i2c_event event) { I2CDDCState *s = I2CDDC(i2c); if (event == I2C_START_SEND) { s->firstbyte = true; } + + return 0; } static int i2c_ddc_rx(I2CSlave *i2c) diff --git a/hw/i2c/smbus.c b/hw/i2c/smbus.c index 5b4dd3eba4..2d1b79a689 100644 --- a/hw/i2c/smbus.c +++ b/hw/i2c/smbus.c @@ -67,7 +67,7 @@ static void smbus_do_write(SMBusDevice *dev) } } -static void smbus_i2c_event(I2CSlave *s, enum i2c_event event) +static int smbus_i2c_event(I2CSlave *s, enum i2c_event event) { SMBusDevice *dev = SMBUS_DEVICE(s); @@ -148,6 +148,8 @@ static void smbus_i2c_event(I2CSlave *s, enum i2c_event event) break; } } + + return 0; } static int smbus_i2c_recv(I2CSlave *s) @@ -249,7 +251,8 @@ int smbus_read_byte(I2CBus *bus, uint8_t addr, uint8_t command) } i2c_send(bus, command); if (i2c_start_transfer(bus, addr, 1)) { - assert(0); + i2c_end_transfer(bus); + return -1; } data = i2c_recv(bus); i2c_nack(bus); @@ -276,7 +279,8 @@ int smbus_read_word(I2CBus *bus, uint8_t addr, uint8_t command) } i2c_send(bus, command); if (i2c_start_transfer(bus, addr, 1)) { - assert(0); + i2c_end_transfer(bus); + return -1; } data = i2c_recv(bus); data |= i2c_recv(bus) << 8; @@ -307,7 +311,8 @@ int smbus_read_block(I2CBus *bus, uint8_t addr, uint8_t command, uint8_t *data) } i2c_send(bus, command); if (i2c_start_transfer(bus, addr, 1)) { - assert(0); + i2c_end_transfer(bus); + return -1; } len = i2c_recv(bus); if (len > 32) { diff --git a/hw/input/lm832x.c b/hw/input/lm832x.c index 539682cac8..2340523da0 100644 --- a/hw/input/lm832x.c +++ b/hw/input/lm832x.c @@ -383,7 +383,7 @@ static void lm_kbd_write(LM823KbdState *s, int reg, int byte, uint8_t value) } } -static void lm_i2c_event(I2CSlave *i2c, enum i2c_event event) +static int lm_i2c_event(I2CSlave *i2c, enum i2c_event event) { LM823KbdState *s = LM8323(i2c); @@ -397,6 +397,8 @@ static void lm_i2c_event(I2CSlave *i2c, enum i2c_event event) default: break; } + + return 0; } static int lm_i2c_rx(I2CSlave *i2c) diff --git a/hw/misc/tmp105.c b/hw/misc/tmp105.c index f5c2472b5b..04e83787d4 100644 --- a/hw/misc/tmp105.c +++ b/hw/misc/tmp105.c @@ -176,7 +176,7 @@ static int tmp105_tx(I2CSlave *i2c, uint8_t data) return 0; } -static void tmp105_event(I2CSlave *i2c, enum i2c_event event) +static int tmp105_event(I2CSlave *i2c, enum i2c_event event) { TMP105State *s = TMP105(i2c); @@ -185,6 +185,7 @@ static void tmp105_event(I2CSlave *i2c, enum i2c_event event) } s->len = 0; + return 0; } static int tmp105_post_load(void *opaque, int version_id) diff --git a/hw/timer/ds1338.c b/hw/timer/ds1338.c index f5d04dd5d7..3849b74a68 100644 --- a/hw/timer/ds1338.c +++ b/hw/timer/ds1338.c @@ -94,7 +94,7 @@ static void inc_regptr(DS1338State *s) } } -static void ds1338_event(I2CSlave *i2c, enum i2c_event event) +static int ds1338_event(I2CSlave *i2c, enum i2c_event event) { DS1338State *s = DS1338(i2c); @@ -113,6 +113,8 @@ static void ds1338_event(I2CSlave *i2c, enum i2c_event event) default: break; } + + return 0; } static int ds1338_recv(I2CSlave *i2c) diff --git a/hw/timer/twl92230.c b/hw/timer/twl92230.c index 7ba4e9a7c9..b8d914e49b 100644 --- a/hw/timer/twl92230.c +++ b/hw/timer/twl92230.c @@ -713,12 +713,14 @@ static void menelaus_write(void *opaque, uint8_t addr, uint8_t value) } } -static void menelaus_event(I2CSlave *i2c, enum i2c_event event) +static int menelaus_event(I2CSlave *i2c, enum i2c_event event) { MenelausState *s = TWL92230(i2c); if (event == I2C_START_SEND) s->firstbyte = 1; + + return 0; } static int menelaus_tx(I2CSlave *i2c, uint8_t data) diff --git a/include/hw/i2c/i2c.h b/include/hw/i2c/i2c.h index c4085aa366..2ce611d4c8 100644 --- a/include/hw/i2c/i2c.h +++ b/include/hw/i2c/i2c.h @@ -32,14 +32,22 @@ typedef struct I2CSlaveClass /* Callbacks provided by the device. */ int (*init)(I2CSlave *dev); - /* Master to slave. */ + /* Master to slave. Returns non-zero for a NAK, 0 for success. */ int (*send)(I2CSlave *s, uint8_t data); - /* Slave to master. */ + /* + * Slave to master. This cannot fail, the device should always + * return something here. Negative values probably result in 0xff + * and a possible log from the driver, and shouldn't be used. + */ int (*recv)(I2CSlave *s); - /* Notify the slave of a bus state change. */ - void (*event)(I2CSlave *s, enum i2c_event event); + /* + * Notify the slave of a bus state change. For start event, + * returns non-zero to NAK an operation. For other events the + * return code is not used and should be zero. + */ + int (*event)(I2CSlave *s, enum i2c_event event); } I2CSlaveClass; struct I2CSlave From 5b982482c1c1f6170361b9c80dce60b5222242da Mon Sep 17 00:00:00 2001 From: xiaoqiang zhao Date: Mon, 9 Jan 2017 11:40:21 +0000 Subject: [PATCH 02/21] hw/char: QOM'ify exynos4210_uart.c Drop the old Sysbus init and use instance_init and DeviceClass::realize instead Signed-off-by: xiaoqiang zhao Reviewed-by: Peter Maydell Signed-off-by: Peter Maydell --- hw/char/exynos4210_uart.c | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/hw/char/exynos4210_uart.c b/hw/char/exynos4210_uart.c index 571c324004..820d1abeb9 100644 --- a/hw/char/exynos4210_uart.c +++ b/hw/char/exynos4210_uart.c @@ -629,22 +629,26 @@ DeviceState *exynos4210_uart_create(hwaddr addr, return dev; } -static int exynos4210_uart_init(SysBusDevice *dev) +static void exynos4210_uart_init(Object *obj) { + SysBusDevice *dev = SYS_BUS_DEVICE(obj); Exynos4210UartState *s = EXYNOS4210_UART(dev); /* memory mapping */ - memory_region_init_io(&s->iomem, OBJECT(s), &exynos4210_uart_ops, s, + memory_region_init_io(&s->iomem, obj, &exynos4210_uart_ops, s, "exynos4210.uart", EXYNOS4210_UART_REGS_MEM_SIZE); sysbus_init_mmio(dev, &s->iomem); sysbus_init_irq(dev, &s->irq); +} + +static void exynos4210_uart_realize(DeviceState *dev, Error **errp) +{ + Exynos4210UartState *s = EXYNOS4210_UART(dev); qemu_chr_fe_set_handlers(&s->chr, exynos4210_uart_can_receive, exynos4210_uart_receive, exynos4210_uart_event, s, NULL, true); - - return 0; } static Property exynos4210_uart_properties[] = { @@ -658,9 +662,8 @@ static Property exynos4210_uart_properties[] = { static void exynos4210_uart_class_init(ObjectClass *klass, void *data) { DeviceClass *dc = DEVICE_CLASS(klass); - SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass); - k->init = exynos4210_uart_init; + dc->realize = exynos4210_uart_realize; dc->reset = exynos4210_uart_reset; dc->props = exynos4210_uart_properties; dc->vmsd = &vmstate_exynos4210_uart; @@ -670,6 +673,7 @@ static const TypeInfo exynos4210_uart_info = { .name = TYPE_EXYNOS4210_UART, .parent = TYPE_SYS_BUS_DEVICE, .instance_size = sizeof(Exynos4210UartState), + .instance_init = exynos4210_uart_init, .class_init = exynos4210_uart_class_init, }; From 9ac4ef77c1b43d1c105975a3d469551886e65c35 Mon Sep 17 00:00:00 2001 From: Peter Maydell Date: Mon, 9 Jan 2017 11:40:21 +0000 Subject: [PATCH 03/21] hw/arm/virt: Merge VirtBoardInfo and VirtMachineState One of the purposes of VirtBoardInfo was to hold various bits of state about the board. Now we have MachineState and the subclass VirtMachineState to do this. Fold the VirtBoardInfo into VirtMachineState rather than having some flags in one struct and some in another with no useful way to get between them. In the process we drop the code for looking up the memory map and irq map from the CPU model, because in practice we always use the same maps in all cases. For easier code review, this change removes the VirtBoardInfo type but leaves all the variables which used to be VirtBoardInfo* and are now VirtMachineState* with their now-confusing 'vbi' names. Signed-off-by: Peter Maydell Reviewed-by: Andrew Jones --- hw/arm/virt.c | 118 ++++++++++++++++++++++---------------------------- 1 file changed, 51 insertions(+), 67 deletions(-) diff --git a/hw/arm/virt.c b/hw/arm/virt.c index 11c53a56e0..fd4eed953e 100644 --- a/hw/arm/virt.c +++ b/hw/arm/virt.c @@ -66,23 +66,8 @@ static ARMPlatformBusSystemParams platform_bus_params; -typedef struct VirtBoardInfo { - struct arm_boot_info bootinfo; - const char *cpu_model; - const MemMapEntry *memmap; - const int *irqmap; - int smp_cpus; - void *fdt; - int fdt_size; - uint32_t clock_phandle; - uint32_t gic_phandle; - uint32_t msi_phandle; - bool using_psci; -} VirtBoardInfo; - typedef struct { MachineClass parent; - VirtBoardInfo *daughterboard; bool disallow_affinity_adjustment; bool no_its; bool no_pmu; @@ -93,6 +78,16 @@ typedef struct { bool secure; bool highmem; int32_t gic_version; + struct arm_boot_info bootinfo; + const MemMapEntry *memmap; + const int *irqmap; + int smp_cpus; + void *fdt; + int fdt_size; + uint32_t clock_phandle; + uint32_t gic_phandle; + uint32_t msi_phandle; + bool using_psci; } VirtMachineState; #define TYPE_VIRT_MACHINE MACHINE_TYPE_NAME("virt") @@ -202,42 +197,27 @@ static const int a15irqmap[] = { [VIRT_PLATFORM_BUS] = 112, /* ...to 112 + PLATFORM_BUS_NUM_IRQS -1 */ }; -static VirtBoardInfo machines[] = { - { - .cpu_model = "cortex-a15", - .memmap = a15memmap, - .irqmap = a15irqmap, - }, - { - .cpu_model = "cortex-a53", - .memmap = a15memmap, - .irqmap = a15irqmap, - }, - { - .cpu_model = "cortex-a57", - .memmap = a15memmap, - .irqmap = a15irqmap, - }, - { - .cpu_model = "host", - .memmap = a15memmap, - .irqmap = a15irqmap, - }, +static const char *valid_cpus[] = { + "cortex-a15", + "cortex-a53", + "cortex-a57", + "host", + NULL }; -static VirtBoardInfo *find_machine_info(const char *cpu) +static bool cpuname_valid(const char *cpu) { int i; - for (i = 0; i < ARRAY_SIZE(machines); i++) { - if (strcmp(cpu, machines[i].cpu_model) == 0) { - return &machines[i]; + for (i = 0; i < ARRAY_SIZE(valid_cpus); i++) { + if (strcmp(cpu, valid_cpus[i]) == 0) { + return true; } } - return NULL; + return false; } -static void create_fdt(VirtBoardInfo *vbi) +static void create_fdt(VirtMachineState *vbi) { void *fdt = create_device_tree(&vbi->fdt_size); @@ -277,7 +257,7 @@ static void create_fdt(VirtBoardInfo *vbi) } -static void fdt_add_psci_node(const VirtBoardInfo *vbi) +static void fdt_add_psci_node(const VirtMachineState *vbi) { uint32_t cpu_suspend_fn; uint32_t cpu_off_fn; @@ -327,7 +307,7 @@ static void fdt_add_psci_node(const VirtBoardInfo *vbi) qemu_fdt_setprop_cell(fdt, "/psci", "migrate", migrate_fn); } -static void fdt_add_timer_nodes(const VirtBoardInfo *vbi, int gictype) +static void fdt_add_timer_nodes(const VirtMachineState *vbi, int gictype) { /* Note that on A15 h/w these interrupts are level-triggered, * but for the GIC implementation provided by both QEMU and KVM @@ -361,7 +341,7 @@ static void fdt_add_timer_nodes(const VirtBoardInfo *vbi, int gictype) GIC_FDT_IRQ_TYPE_PPI, ARCH_TIMER_NS_EL2_IRQ, irqflags); } -static void fdt_add_cpu_nodes(const VirtBoardInfo *vbi) +static void fdt_add_cpu_nodes(const VirtMachineState *vbi) { int cpu; int addr_cells = 1; @@ -424,7 +404,7 @@ static void fdt_add_cpu_nodes(const VirtBoardInfo *vbi) } } -static void fdt_add_its_gic_node(VirtBoardInfo *vbi) +static void fdt_add_its_gic_node(VirtMachineState *vbi) { vbi->msi_phandle = qemu_fdt_alloc_phandle(vbi->fdt); qemu_fdt_add_subnode(vbi->fdt, "/intc/its"); @@ -437,7 +417,7 @@ static void fdt_add_its_gic_node(VirtBoardInfo *vbi) qemu_fdt_setprop_cell(vbi->fdt, "/intc/its", "phandle", vbi->msi_phandle); } -static void fdt_add_v2m_gic_node(VirtBoardInfo *vbi) +static void fdt_add_v2m_gic_node(VirtMachineState *vbi) { vbi->msi_phandle = qemu_fdt_alloc_phandle(vbi->fdt); qemu_fdt_add_subnode(vbi->fdt, "/intc/v2m"); @@ -450,7 +430,7 @@ static void fdt_add_v2m_gic_node(VirtBoardInfo *vbi) qemu_fdt_setprop_cell(vbi->fdt, "/intc/v2m", "phandle", vbi->msi_phandle); } -static void fdt_add_gic_node(VirtBoardInfo *vbi, int type) +static void fdt_add_gic_node(VirtMachineState *vbi, int type) { vbi->gic_phandle = qemu_fdt_alloc_phandle(vbi->fdt); qemu_fdt_setprop_cell(vbi->fdt, "/", "interrupt-parent", vbi->gic_phandle); @@ -483,7 +463,7 @@ static void fdt_add_gic_node(VirtBoardInfo *vbi, int type) qemu_fdt_setprop_cell(vbi->fdt, "/intc", "phandle", vbi->gic_phandle); } -static void fdt_add_pmu_nodes(const VirtBoardInfo *vbi, int gictype) +static void fdt_add_pmu_nodes(const VirtMachineState *vbi, int gictype) { CPUState *cpu; ARMCPU *armcpu; @@ -514,7 +494,7 @@ static void fdt_add_pmu_nodes(const VirtBoardInfo *vbi, int gictype) } } -static void create_its(VirtBoardInfo *vbi, DeviceState *gicdev) +static void create_its(VirtMachineState *vbi, DeviceState *gicdev) { const char *itsclass = its_class_name(); DeviceState *dev; @@ -534,7 +514,7 @@ static void create_its(VirtBoardInfo *vbi, DeviceState *gicdev) fdt_add_its_gic_node(vbi); } -static void create_v2m(VirtBoardInfo *vbi, qemu_irq *pic) +static void create_v2m(VirtMachineState *vbi, qemu_irq *pic) { int i; int irq = vbi->irqmap[VIRT_GIC_V2M]; @@ -553,7 +533,7 @@ static void create_v2m(VirtBoardInfo *vbi, qemu_irq *pic) fdt_add_v2m_gic_node(vbi); } -static void create_gic(VirtBoardInfo *vbi, qemu_irq *pic, int type, +static void create_gic(VirtMachineState *vbi, qemu_irq *pic, int type, bool secure, bool no_its) { /* We create a standalone GIC */ @@ -625,7 +605,7 @@ static void create_gic(VirtBoardInfo *vbi, qemu_irq *pic, int type, } } -static void create_uart(const VirtBoardInfo *vbi, qemu_irq *pic, int uart, +static void create_uart(const VirtMachineState *vbi, qemu_irq *pic, int uart, MemoryRegion *mem, CharDriverState *chr) { char *nodename; @@ -669,7 +649,7 @@ static void create_uart(const VirtBoardInfo *vbi, qemu_irq *pic, int uart, g_free(nodename); } -static void create_rtc(const VirtBoardInfo *vbi, qemu_irq *pic) +static void create_rtc(const VirtMachineState *vbi, qemu_irq *pic) { char *nodename; hwaddr base = vbi->memmap[VIRT_RTC].base; @@ -703,7 +683,7 @@ static Notifier virt_system_powerdown_notifier = { .notify = virt_powerdown_req }; -static void create_gpio(const VirtBoardInfo *vbi, qemu_irq *pic) +static void create_gpio(const VirtMachineState *vbi, qemu_irq *pic) { char *nodename; DeviceState *pl061_dev; @@ -750,7 +730,7 @@ static void create_gpio(const VirtBoardInfo *vbi, qemu_irq *pic) g_free(nodename); } -static void create_virtio_devices(const VirtBoardInfo *vbi, qemu_irq *pic) +static void create_virtio_devices(const VirtMachineState *vbi, qemu_irq *pic) { int i; hwaddr size = vbi->memmap[VIRT_MMIO].size; @@ -870,7 +850,7 @@ static void create_one_flash(const char *name, hwaddr flashbase, } } -static void create_flash(const VirtBoardInfo *vbi, +static void create_flash(const VirtMachineState *vbi, MemoryRegion *sysmem, MemoryRegion *secure_sysmem) { @@ -925,7 +905,7 @@ static void create_flash(const VirtBoardInfo *vbi, } } -static void create_fw_cfg(const VirtBoardInfo *vbi, AddressSpace *as) +static void create_fw_cfg(const VirtMachineState *vbi, AddressSpace *as) { hwaddr base = vbi->memmap[VIRT_FW_CFG].base; hwaddr size = vbi->memmap[VIRT_FW_CFG].size; @@ -944,7 +924,8 @@ static void create_fw_cfg(const VirtBoardInfo *vbi, AddressSpace *as) g_free(nodename); } -static void create_pcie_irq_map(const VirtBoardInfo *vbi, uint32_t gic_phandle, +static void create_pcie_irq_map(const VirtMachineState *vbi, + uint32_t gic_phandle, int first_irq, const char *nodename) { int devfn, pin; @@ -979,7 +960,7 @@ static void create_pcie_irq_map(const VirtBoardInfo *vbi, uint32_t gic_phandle, 0x7 /* PCI irq */); } -static void create_pcie(const VirtBoardInfo *vbi, qemu_irq *pic, +static void create_pcie(const VirtMachineState *vbi, qemu_irq *pic, bool use_highmem) { hwaddr base_mmio = vbi->memmap[VIRT_PCIE_MMIO].base; @@ -1095,7 +1076,7 @@ static void create_pcie(const VirtBoardInfo *vbi, qemu_irq *pic, g_free(nodename); } -static void create_platform_bus(VirtBoardInfo *vbi, qemu_irq *pic) +static void create_platform_bus(VirtMachineState *vbi, qemu_irq *pic) { DeviceState *dev; SysBusDevice *s; @@ -1136,7 +1117,8 @@ static void create_platform_bus(VirtBoardInfo *vbi, qemu_irq *pic) sysbus_mmio_get_region(s, 0)); } -static void create_secure_ram(VirtBoardInfo *vbi, MemoryRegion *secure_sysmem) +static void create_secure_ram(VirtMachineState *vbi, + MemoryRegion *secure_sysmem) { MemoryRegion *secram = g_new(MemoryRegion, 1); char *nodename; @@ -1159,7 +1141,8 @@ static void create_secure_ram(VirtBoardInfo *vbi, MemoryRegion *secure_sysmem) static void *machvirt_dtb(const struct arm_boot_info *binfo, int *fdt_size) { - const VirtBoardInfo *board = (const VirtBoardInfo *)binfo; + const VirtMachineState *board = container_of(binfo, VirtMachineState, + bootinfo); *fdt_size = board->fdt_size; return board->fdt; @@ -1214,7 +1197,7 @@ static void machvirt_init(MachineState *machine) int n, virt_max_cpus; MemoryRegion *ram = g_new(MemoryRegion, 1); const char *cpu_model = machine->cpu_model; - VirtBoardInfo *vbi; + VirtMachineState *vbi = vms; VirtGuestInfoState *guest_info_state = g_malloc0(sizeof *guest_info_state); VirtGuestInfo *guest_info = &guest_info_state->info; char **cpustr; @@ -1248,9 +1231,7 @@ static void machvirt_init(MachineState *machine) /* Separate the actual CPU model name from any appended features */ cpustr = g_strsplit(cpu_model, ",", 2); - vbi = find_machine_info(cpustr[0]); - - if (!vbi) { + if (!cpuname_valid(cpustr[0])) { error_report("mach-virt: CPU %s not supported", cpustr[0]); exit(1); } @@ -1556,6 +1537,9 @@ static void virt_2_9_instance_init(Object *obj) object_property_set_description(obj, "gic-version", "Set GIC version. " "Valid values are 2, 3 and host", NULL); + + vms->memmap = a15memmap; + vms->irqmap = a15irqmap; } static void virt_machine_2_9_options(MachineClass *mc) From c8ef2bda05af317819427c2fde7ebf061129c142 Mon Sep 17 00:00:00 2001 From: Peter Maydell Date: Mon, 9 Jan 2017 11:40:21 +0000 Subject: [PATCH 04/21] hw/arm/virt: Rename 'vbi' variables to 'vms' Rename all the variables which used to be VirtBoardInfo* and are now VirtMachineState* so their names are in line with the type being used. Apart from the removal of the line 'VirtMachineState *vbi = vms;' this commit is purely a search-and-replace of 'vbi' with 'vms'. Signed-off-by: Peter Maydell Reviewed-by: Andrew Jones --- hw/arm/virt.c | 487 +++++++++++++++++++++++++------------------------- 1 file changed, 243 insertions(+), 244 deletions(-) diff --git a/hw/arm/virt.c b/hw/arm/virt.c index fd4eed953e..54498ead23 100644 --- a/hw/arm/virt.c +++ b/hw/arm/virt.c @@ -217,16 +217,16 @@ static bool cpuname_valid(const char *cpu) return false; } -static void create_fdt(VirtMachineState *vbi) +static void create_fdt(VirtMachineState *vms) { - void *fdt = create_device_tree(&vbi->fdt_size); + void *fdt = create_device_tree(&vms->fdt_size); if (!fdt) { error_report("create_device_tree() failed"); exit(1); } - vbi->fdt = fdt; + vms->fdt = fdt; /* Header */ qemu_fdt_setprop_string(fdt, "/", "compatible", "linux,dummy-virt"); @@ -246,27 +246,27 @@ static void create_fdt(VirtMachineState *vbi) * optional but in practice if you omit them the kernel refuses to * probe for the device. */ - vbi->clock_phandle = qemu_fdt_alloc_phandle(fdt); + vms->clock_phandle = qemu_fdt_alloc_phandle(fdt); qemu_fdt_add_subnode(fdt, "/apb-pclk"); qemu_fdt_setprop_string(fdt, "/apb-pclk", "compatible", "fixed-clock"); qemu_fdt_setprop_cell(fdt, "/apb-pclk", "#clock-cells", 0x0); qemu_fdt_setprop_cell(fdt, "/apb-pclk", "clock-frequency", 24000000); qemu_fdt_setprop_string(fdt, "/apb-pclk", "clock-output-names", "clk24mhz"); - qemu_fdt_setprop_cell(fdt, "/apb-pclk", "phandle", vbi->clock_phandle); + qemu_fdt_setprop_cell(fdt, "/apb-pclk", "phandle", vms->clock_phandle); } -static void fdt_add_psci_node(const VirtMachineState *vbi) +static void fdt_add_psci_node(const VirtMachineState *vms) { uint32_t cpu_suspend_fn; uint32_t cpu_off_fn; uint32_t cpu_on_fn; uint32_t migrate_fn; - void *fdt = vbi->fdt; + void *fdt = vms->fdt; ARMCPU *armcpu = ARM_CPU(qemu_get_cpu(0)); - if (!vbi->using_psci) { + if (!vms->using_psci) { return; } @@ -307,7 +307,7 @@ static void fdt_add_psci_node(const VirtMachineState *vbi) qemu_fdt_setprop_cell(fdt, "/psci", "migrate", migrate_fn); } -static void fdt_add_timer_nodes(const VirtMachineState *vbi, int gictype) +static void fdt_add_timer_nodes(const VirtMachineState *vms, int gictype) { /* Note that on A15 h/w these interrupts are level-triggered, * but for the GIC implementation provided by both QEMU and KVM @@ -319,29 +319,29 @@ static void fdt_add_timer_nodes(const VirtMachineState *vbi, int gictype) if (gictype == 2) { irqflags = deposit32(irqflags, GIC_FDT_IRQ_PPI_CPU_START, GIC_FDT_IRQ_PPI_CPU_WIDTH, - (1 << vbi->smp_cpus) - 1); + (1 << vms->smp_cpus) - 1); } - qemu_fdt_add_subnode(vbi->fdt, "/timer"); + qemu_fdt_add_subnode(vms->fdt, "/timer"); armcpu = ARM_CPU(qemu_get_cpu(0)); if (arm_feature(&armcpu->env, ARM_FEATURE_V8)) { const char compat[] = "arm,armv8-timer\0arm,armv7-timer"; - qemu_fdt_setprop(vbi->fdt, "/timer", "compatible", + qemu_fdt_setprop(vms->fdt, "/timer", "compatible", compat, sizeof(compat)); } else { - qemu_fdt_setprop_string(vbi->fdt, "/timer", "compatible", + qemu_fdt_setprop_string(vms->fdt, "/timer", "compatible", "arm,armv7-timer"); } - qemu_fdt_setprop(vbi->fdt, "/timer", "always-on", NULL, 0); - qemu_fdt_setprop_cells(vbi->fdt, "/timer", "interrupts", + qemu_fdt_setprop(vms->fdt, "/timer", "always-on", NULL, 0); + qemu_fdt_setprop_cells(vms->fdt, "/timer", "interrupts", GIC_FDT_IRQ_TYPE_PPI, ARCH_TIMER_S_EL1_IRQ, irqflags, GIC_FDT_IRQ_TYPE_PPI, ARCH_TIMER_NS_EL1_IRQ, irqflags, GIC_FDT_IRQ_TYPE_PPI, ARCH_TIMER_VIRT_IRQ, irqflags, GIC_FDT_IRQ_TYPE_PPI, ARCH_TIMER_NS_EL2_IRQ, irqflags); } -static void fdt_add_cpu_nodes(const VirtMachineState *vbi) +static void fdt_add_cpu_nodes(const VirtMachineState *vms) { int cpu; int addr_cells = 1; @@ -360,7 +360,7 @@ static void fdt_add_cpu_nodes(const VirtMachineState *vbi) * The simplest way to go is to examine affinity IDs of all our CPUs. If * at least one of them has Aff3 populated, we set #address-cells to 2. */ - for (cpu = 0; cpu < vbi->smp_cpus; cpu++) { + for (cpu = 0; cpu < vms->smp_cpus; cpu++) { ARMCPU *armcpu = ARM_CPU(qemu_get_cpu(cpu)); if (armcpu->mp_affinity & ARM_AFF3_MASK) { @@ -369,101 +369,101 @@ static void fdt_add_cpu_nodes(const VirtMachineState *vbi) } } - qemu_fdt_add_subnode(vbi->fdt, "/cpus"); - qemu_fdt_setprop_cell(vbi->fdt, "/cpus", "#address-cells", addr_cells); - qemu_fdt_setprop_cell(vbi->fdt, "/cpus", "#size-cells", 0x0); + qemu_fdt_add_subnode(vms->fdt, "/cpus"); + qemu_fdt_setprop_cell(vms->fdt, "/cpus", "#address-cells", addr_cells); + qemu_fdt_setprop_cell(vms->fdt, "/cpus", "#size-cells", 0x0); - for (cpu = vbi->smp_cpus - 1; cpu >= 0; cpu--) { + for (cpu = vms->smp_cpus - 1; cpu >= 0; cpu--) { char *nodename = g_strdup_printf("/cpus/cpu@%d", cpu); ARMCPU *armcpu = ARM_CPU(qemu_get_cpu(cpu)); - qemu_fdt_add_subnode(vbi->fdt, nodename); - qemu_fdt_setprop_string(vbi->fdt, nodename, "device_type", "cpu"); - qemu_fdt_setprop_string(vbi->fdt, nodename, "compatible", + qemu_fdt_add_subnode(vms->fdt, nodename); + qemu_fdt_setprop_string(vms->fdt, nodename, "device_type", "cpu"); + qemu_fdt_setprop_string(vms->fdt, nodename, "compatible", armcpu->dtb_compatible); - if (vbi->using_psci && vbi->smp_cpus > 1) { - qemu_fdt_setprop_string(vbi->fdt, nodename, + if (vms->using_psci && vms->smp_cpus > 1) { + qemu_fdt_setprop_string(vms->fdt, nodename, "enable-method", "psci"); } if (addr_cells == 2) { - qemu_fdt_setprop_u64(vbi->fdt, nodename, "reg", + qemu_fdt_setprop_u64(vms->fdt, nodename, "reg", armcpu->mp_affinity); } else { - qemu_fdt_setprop_cell(vbi->fdt, nodename, "reg", + qemu_fdt_setprop_cell(vms->fdt, nodename, "reg", armcpu->mp_affinity); } i = numa_get_node_for_cpu(cpu); if (i < nb_numa_nodes) { - qemu_fdt_setprop_cell(vbi->fdt, nodename, "numa-node-id", i); + qemu_fdt_setprop_cell(vms->fdt, nodename, "numa-node-id", i); } g_free(nodename); } } -static void fdt_add_its_gic_node(VirtMachineState *vbi) +static void fdt_add_its_gic_node(VirtMachineState *vms) { - vbi->msi_phandle = qemu_fdt_alloc_phandle(vbi->fdt); - qemu_fdt_add_subnode(vbi->fdt, "/intc/its"); - qemu_fdt_setprop_string(vbi->fdt, "/intc/its", "compatible", + vms->msi_phandle = qemu_fdt_alloc_phandle(vms->fdt); + qemu_fdt_add_subnode(vms->fdt, "/intc/its"); + qemu_fdt_setprop_string(vms->fdt, "/intc/its", "compatible", "arm,gic-v3-its"); - qemu_fdt_setprop(vbi->fdt, "/intc/its", "msi-controller", NULL, 0); - qemu_fdt_setprop_sized_cells(vbi->fdt, "/intc/its", "reg", - 2, vbi->memmap[VIRT_GIC_ITS].base, - 2, vbi->memmap[VIRT_GIC_ITS].size); - qemu_fdt_setprop_cell(vbi->fdt, "/intc/its", "phandle", vbi->msi_phandle); + qemu_fdt_setprop(vms->fdt, "/intc/its", "msi-controller", NULL, 0); + qemu_fdt_setprop_sized_cells(vms->fdt, "/intc/its", "reg", + 2, vms->memmap[VIRT_GIC_ITS].base, + 2, vms->memmap[VIRT_GIC_ITS].size); + qemu_fdt_setprop_cell(vms->fdt, "/intc/its", "phandle", vms->msi_phandle); } -static void fdt_add_v2m_gic_node(VirtMachineState *vbi) +static void fdt_add_v2m_gic_node(VirtMachineState *vms) { - vbi->msi_phandle = qemu_fdt_alloc_phandle(vbi->fdt); - qemu_fdt_add_subnode(vbi->fdt, "/intc/v2m"); - qemu_fdt_setprop_string(vbi->fdt, "/intc/v2m", "compatible", + vms->msi_phandle = qemu_fdt_alloc_phandle(vms->fdt); + qemu_fdt_add_subnode(vms->fdt, "/intc/v2m"); + qemu_fdt_setprop_string(vms->fdt, "/intc/v2m", "compatible", "arm,gic-v2m-frame"); - qemu_fdt_setprop(vbi->fdt, "/intc/v2m", "msi-controller", NULL, 0); - qemu_fdt_setprop_sized_cells(vbi->fdt, "/intc/v2m", "reg", - 2, vbi->memmap[VIRT_GIC_V2M].base, - 2, vbi->memmap[VIRT_GIC_V2M].size); - qemu_fdt_setprop_cell(vbi->fdt, "/intc/v2m", "phandle", vbi->msi_phandle); + qemu_fdt_setprop(vms->fdt, "/intc/v2m", "msi-controller", NULL, 0); + qemu_fdt_setprop_sized_cells(vms->fdt, "/intc/v2m", "reg", + 2, vms->memmap[VIRT_GIC_V2M].base, + 2, vms->memmap[VIRT_GIC_V2M].size); + qemu_fdt_setprop_cell(vms->fdt, "/intc/v2m", "phandle", vms->msi_phandle); } -static void fdt_add_gic_node(VirtMachineState *vbi, int type) +static void fdt_add_gic_node(VirtMachineState *vms, int type) { - vbi->gic_phandle = qemu_fdt_alloc_phandle(vbi->fdt); - qemu_fdt_setprop_cell(vbi->fdt, "/", "interrupt-parent", vbi->gic_phandle); + vms->gic_phandle = qemu_fdt_alloc_phandle(vms->fdt); + qemu_fdt_setprop_cell(vms->fdt, "/", "interrupt-parent", vms->gic_phandle); - qemu_fdt_add_subnode(vbi->fdt, "/intc"); - qemu_fdt_setprop_cell(vbi->fdt, "/intc", "#interrupt-cells", 3); - qemu_fdt_setprop(vbi->fdt, "/intc", "interrupt-controller", NULL, 0); - qemu_fdt_setprop_cell(vbi->fdt, "/intc", "#address-cells", 0x2); - qemu_fdt_setprop_cell(vbi->fdt, "/intc", "#size-cells", 0x2); - qemu_fdt_setprop(vbi->fdt, "/intc", "ranges", NULL, 0); + qemu_fdt_add_subnode(vms->fdt, "/intc"); + qemu_fdt_setprop_cell(vms->fdt, "/intc", "#interrupt-cells", 3); + qemu_fdt_setprop(vms->fdt, "/intc", "interrupt-controller", NULL, 0); + qemu_fdt_setprop_cell(vms->fdt, "/intc", "#address-cells", 0x2); + qemu_fdt_setprop_cell(vms->fdt, "/intc", "#size-cells", 0x2); + qemu_fdt_setprop(vms->fdt, "/intc", "ranges", NULL, 0); if (type == 3) { - qemu_fdt_setprop_string(vbi->fdt, "/intc", "compatible", + qemu_fdt_setprop_string(vms->fdt, "/intc", "compatible", "arm,gic-v3"); - qemu_fdt_setprop_sized_cells(vbi->fdt, "/intc", "reg", - 2, vbi->memmap[VIRT_GIC_DIST].base, - 2, vbi->memmap[VIRT_GIC_DIST].size, - 2, vbi->memmap[VIRT_GIC_REDIST].base, - 2, vbi->memmap[VIRT_GIC_REDIST].size); + qemu_fdt_setprop_sized_cells(vms->fdt, "/intc", "reg", + 2, vms->memmap[VIRT_GIC_DIST].base, + 2, vms->memmap[VIRT_GIC_DIST].size, + 2, vms->memmap[VIRT_GIC_REDIST].base, + 2, vms->memmap[VIRT_GIC_REDIST].size); } else { /* 'cortex-a15-gic' means 'GIC v2' */ - qemu_fdt_setprop_string(vbi->fdt, "/intc", "compatible", + qemu_fdt_setprop_string(vms->fdt, "/intc", "compatible", "arm,cortex-a15-gic"); - qemu_fdt_setprop_sized_cells(vbi->fdt, "/intc", "reg", - 2, vbi->memmap[VIRT_GIC_DIST].base, - 2, vbi->memmap[VIRT_GIC_DIST].size, - 2, vbi->memmap[VIRT_GIC_CPU].base, - 2, vbi->memmap[VIRT_GIC_CPU].size); + qemu_fdt_setprop_sized_cells(vms->fdt, "/intc", "reg", + 2, vms->memmap[VIRT_GIC_DIST].base, + 2, vms->memmap[VIRT_GIC_DIST].size, + 2, vms->memmap[VIRT_GIC_CPU].base, + 2, vms->memmap[VIRT_GIC_CPU].size); } - qemu_fdt_setprop_cell(vbi->fdt, "/intc", "phandle", vbi->gic_phandle); + qemu_fdt_setprop_cell(vms->fdt, "/intc", "phandle", vms->gic_phandle); } -static void fdt_add_pmu_nodes(const VirtMachineState *vbi, int gictype) +static void fdt_add_pmu_nodes(const VirtMachineState *vms, int gictype) { CPUState *cpu; ARMCPU *armcpu; @@ -480,21 +480,21 @@ static void fdt_add_pmu_nodes(const VirtMachineState *vbi, int gictype) if (gictype == 2) { irqflags = deposit32(irqflags, GIC_FDT_IRQ_PPI_CPU_START, GIC_FDT_IRQ_PPI_CPU_WIDTH, - (1 << vbi->smp_cpus) - 1); + (1 << vms->smp_cpus) - 1); } armcpu = ARM_CPU(qemu_get_cpu(0)); - qemu_fdt_add_subnode(vbi->fdt, "/pmu"); + qemu_fdt_add_subnode(vms->fdt, "/pmu"); if (arm_feature(&armcpu->env, ARM_FEATURE_V8)) { const char compat[] = "arm,armv8-pmuv3"; - qemu_fdt_setprop(vbi->fdt, "/pmu", "compatible", + qemu_fdt_setprop(vms->fdt, "/pmu", "compatible", compat, sizeof(compat)); - qemu_fdt_setprop_cells(vbi->fdt, "/pmu", "interrupts", + qemu_fdt_setprop_cells(vms->fdt, "/pmu", "interrupts", GIC_FDT_IRQ_TYPE_PPI, VIRTUAL_PMU_IRQ, irqflags); } } -static void create_its(VirtMachineState *vbi, DeviceState *gicdev) +static void create_its(VirtMachineState *vms, DeviceState *gicdev) { const char *itsclass = its_class_name(); DeviceState *dev; @@ -509,19 +509,19 @@ static void create_its(VirtMachineState *vbi, DeviceState *gicdev) object_property_set_link(OBJECT(dev), OBJECT(gicdev), "parent-gicv3", &error_abort); qdev_init_nofail(dev); - sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, vbi->memmap[VIRT_GIC_ITS].base); + sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, vms->memmap[VIRT_GIC_ITS].base); - fdt_add_its_gic_node(vbi); + fdt_add_its_gic_node(vms); } -static void create_v2m(VirtMachineState *vbi, qemu_irq *pic) +static void create_v2m(VirtMachineState *vms, qemu_irq *pic) { int i; - int irq = vbi->irqmap[VIRT_GIC_V2M]; + int irq = vms->irqmap[VIRT_GIC_V2M]; DeviceState *dev; dev = qdev_create(NULL, "arm-gicv2m"); - sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, vbi->memmap[VIRT_GIC_V2M].base); + sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, vms->memmap[VIRT_GIC_V2M].base); qdev_prop_set_uint32(dev, "base-spi", irq); qdev_prop_set_uint32(dev, "num-spi", NUM_GICV2M_SPIS); qdev_init_nofail(dev); @@ -530,10 +530,10 @@ static void create_v2m(VirtMachineState *vbi, qemu_irq *pic) sysbus_connect_irq(SYS_BUS_DEVICE(dev), i, pic[irq + i]); } - fdt_add_v2m_gic_node(vbi); + fdt_add_v2m_gic_node(vms); } -static void create_gic(VirtMachineState *vbi, qemu_irq *pic, int type, +static void create_gic(VirtMachineState *vms, qemu_irq *pic, int type, bool secure, bool no_its) { /* We create a standalone GIC */ @@ -556,11 +556,11 @@ static void create_gic(VirtMachineState *vbi, qemu_irq *pic, int type, } qdev_init_nofail(gicdev); gicbusdev = SYS_BUS_DEVICE(gicdev); - sysbus_mmio_map(gicbusdev, 0, vbi->memmap[VIRT_GIC_DIST].base); + sysbus_mmio_map(gicbusdev, 0, vms->memmap[VIRT_GIC_DIST].base); if (type == 3) { - sysbus_mmio_map(gicbusdev, 1, vbi->memmap[VIRT_GIC_REDIST].base); + sysbus_mmio_map(gicbusdev, 1, vms->memmap[VIRT_GIC_REDIST].base); } else { - sysbus_mmio_map(gicbusdev, 1, vbi->memmap[VIRT_GIC_CPU].base); + sysbus_mmio_map(gicbusdev, 1, vms->memmap[VIRT_GIC_CPU].base); } /* Wire the outputs from each CPU's generic timer to the @@ -596,22 +596,22 @@ static void create_gic(VirtMachineState *vbi, qemu_irq *pic, int type, pic[i] = qdev_get_gpio_in(gicdev, i); } - fdt_add_gic_node(vbi, type); + fdt_add_gic_node(vms, type); if (type == 3 && !no_its) { - create_its(vbi, gicdev); + create_its(vms, gicdev); } else if (type == 2) { - create_v2m(vbi, pic); + create_v2m(vms, pic); } } -static void create_uart(const VirtMachineState *vbi, qemu_irq *pic, int uart, +static void create_uart(const VirtMachineState *vms, qemu_irq *pic, int uart, MemoryRegion *mem, CharDriverState *chr) { char *nodename; - hwaddr base = vbi->memmap[uart].base; - hwaddr size = vbi->memmap[uart].size; - int irq = vbi->irqmap[uart]; + hwaddr base = vms->memmap[uart].base; + hwaddr size = vms->memmap[uart].size; + int irq = vms->irqmap[uart]; const char compat[] = "arm,pl011\0arm,primecell"; const char clocknames[] = "uartclk\0apb_pclk"; DeviceState *dev = qdev_create(NULL, "pl011"); @@ -624,51 +624,51 @@ static void create_uart(const VirtMachineState *vbi, qemu_irq *pic, int uart, sysbus_connect_irq(s, 0, pic[irq]); nodename = g_strdup_printf("/pl011@%" PRIx64, base); - qemu_fdt_add_subnode(vbi->fdt, nodename); + qemu_fdt_add_subnode(vms->fdt, nodename); /* Note that we can't use setprop_string because of the embedded NUL */ - qemu_fdt_setprop(vbi->fdt, nodename, "compatible", + qemu_fdt_setprop(vms->fdt, nodename, "compatible", compat, sizeof(compat)); - qemu_fdt_setprop_sized_cells(vbi->fdt, nodename, "reg", + qemu_fdt_setprop_sized_cells(vms->fdt, nodename, "reg", 2, base, 2, size); - qemu_fdt_setprop_cells(vbi->fdt, nodename, "interrupts", + qemu_fdt_setprop_cells(vms->fdt, nodename, "interrupts", GIC_FDT_IRQ_TYPE_SPI, irq, GIC_FDT_IRQ_FLAGS_LEVEL_HI); - qemu_fdt_setprop_cells(vbi->fdt, nodename, "clocks", - vbi->clock_phandle, vbi->clock_phandle); - qemu_fdt_setprop(vbi->fdt, nodename, "clock-names", + qemu_fdt_setprop_cells(vms->fdt, nodename, "clocks", + vms->clock_phandle, vms->clock_phandle); + qemu_fdt_setprop(vms->fdt, nodename, "clock-names", clocknames, sizeof(clocknames)); if (uart == VIRT_UART) { - qemu_fdt_setprop_string(vbi->fdt, "/chosen", "stdout-path", nodename); + qemu_fdt_setprop_string(vms->fdt, "/chosen", "stdout-path", nodename); } else { /* Mark as not usable by the normal world */ - qemu_fdt_setprop_string(vbi->fdt, nodename, "status", "disabled"); - qemu_fdt_setprop_string(vbi->fdt, nodename, "secure-status", "okay"); + qemu_fdt_setprop_string(vms->fdt, nodename, "status", "disabled"); + qemu_fdt_setprop_string(vms->fdt, nodename, "secure-status", "okay"); } g_free(nodename); } -static void create_rtc(const VirtMachineState *vbi, qemu_irq *pic) +static void create_rtc(const VirtMachineState *vms, qemu_irq *pic) { char *nodename; - hwaddr base = vbi->memmap[VIRT_RTC].base; - hwaddr size = vbi->memmap[VIRT_RTC].size; - int irq = vbi->irqmap[VIRT_RTC]; + hwaddr base = vms->memmap[VIRT_RTC].base; + hwaddr size = vms->memmap[VIRT_RTC].size; + int irq = vms->irqmap[VIRT_RTC]; const char compat[] = "arm,pl031\0arm,primecell"; sysbus_create_simple("pl031", base, pic[irq]); nodename = g_strdup_printf("/pl031@%" PRIx64, base); - qemu_fdt_add_subnode(vbi->fdt, nodename); - qemu_fdt_setprop(vbi->fdt, nodename, "compatible", compat, sizeof(compat)); - qemu_fdt_setprop_sized_cells(vbi->fdt, nodename, "reg", + qemu_fdt_add_subnode(vms->fdt, nodename); + qemu_fdt_setprop(vms->fdt, nodename, "compatible", compat, sizeof(compat)); + qemu_fdt_setprop_sized_cells(vms->fdt, nodename, "reg", 2, base, 2, size); - qemu_fdt_setprop_cells(vbi->fdt, nodename, "interrupts", + qemu_fdt_setprop_cells(vms->fdt, nodename, "interrupts", GIC_FDT_IRQ_TYPE_SPI, irq, GIC_FDT_IRQ_FLAGS_LEVEL_HI); - qemu_fdt_setprop_cell(vbi->fdt, nodename, "clocks", vbi->clock_phandle); - qemu_fdt_setprop_string(vbi->fdt, nodename, "clock-names", "apb_pclk"); + qemu_fdt_setprop_cell(vms->fdt, nodename, "clocks", vms->clock_phandle); + qemu_fdt_setprop_string(vms->fdt, nodename, "clock-names", "apb_pclk"); g_free(nodename); } @@ -683,45 +683,45 @@ static Notifier virt_system_powerdown_notifier = { .notify = virt_powerdown_req }; -static void create_gpio(const VirtMachineState *vbi, qemu_irq *pic) +static void create_gpio(const VirtMachineState *vms, qemu_irq *pic) { char *nodename; DeviceState *pl061_dev; - hwaddr base = vbi->memmap[VIRT_GPIO].base; - hwaddr size = vbi->memmap[VIRT_GPIO].size; - int irq = vbi->irqmap[VIRT_GPIO]; + hwaddr base = vms->memmap[VIRT_GPIO].base; + hwaddr size = vms->memmap[VIRT_GPIO].size; + int irq = vms->irqmap[VIRT_GPIO]; const char compat[] = "arm,pl061\0arm,primecell"; pl061_dev = sysbus_create_simple("pl061", base, pic[irq]); - uint32_t phandle = qemu_fdt_alloc_phandle(vbi->fdt); + uint32_t phandle = qemu_fdt_alloc_phandle(vms->fdt); nodename = g_strdup_printf("/pl061@%" PRIx64, base); - qemu_fdt_add_subnode(vbi->fdt, nodename); - qemu_fdt_setprop_sized_cells(vbi->fdt, nodename, "reg", + qemu_fdt_add_subnode(vms->fdt, nodename); + qemu_fdt_setprop_sized_cells(vms->fdt, nodename, "reg", 2, base, 2, size); - qemu_fdt_setprop(vbi->fdt, nodename, "compatible", compat, sizeof(compat)); - qemu_fdt_setprop_cell(vbi->fdt, nodename, "#gpio-cells", 2); - qemu_fdt_setprop(vbi->fdt, nodename, "gpio-controller", NULL, 0); - qemu_fdt_setprop_cells(vbi->fdt, nodename, "interrupts", + qemu_fdt_setprop(vms->fdt, nodename, "compatible", compat, sizeof(compat)); + qemu_fdt_setprop_cell(vms->fdt, nodename, "#gpio-cells", 2); + qemu_fdt_setprop(vms->fdt, nodename, "gpio-controller", NULL, 0); + qemu_fdt_setprop_cells(vms->fdt, nodename, "interrupts", GIC_FDT_IRQ_TYPE_SPI, irq, GIC_FDT_IRQ_FLAGS_LEVEL_HI); - qemu_fdt_setprop_cell(vbi->fdt, nodename, "clocks", vbi->clock_phandle); - qemu_fdt_setprop_string(vbi->fdt, nodename, "clock-names", "apb_pclk"); - qemu_fdt_setprop_cell(vbi->fdt, nodename, "phandle", phandle); + qemu_fdt_setprop_cell(vms->fdt, nodename, "clocks", vms->clock_phandle); + qemu_fdt_setprop_string(vms->fdt, nodename, "clock-names", "apb_pclk"); + qemu_fdt_setprop_cell(vms->fdt, nodename, "phandle", phandle); gpio_key_dev = sysbus_create_simple("gpio-key", -1, qdev_get_gpio_in(pl061_dev, 3)); - qemu_fdt_add_subnode(vbi->fdt, "/gpio-keys"); - qemu_fdt_setprop_string(vbi->fdt, "/gpio-keys", "compatible", "gpio-keys"); - qemu_fdt_setprop_cell(vbi->fdt, "/gpio-keys", "#size-cells", 0); - qemu_fdt_setprop_cell(vbi->fdt, "/gpio-keys", "#address-cells", 1); + qemu_fdt_add_subnode(vms->fdt, "/gpio-keys"); + qemu_fdt_setprop_string(vms->fdt, "/gpio-keys", "compatible", "gpio-keys"); + qemu_fdt_setprop_cell(vms->fdt, "/gpio-keys", "#size-cells", 0); + qemu_fdt_setprop_cell(vms->fdt, "/gpio-keys", "#address-cells", 1); - qemu_fdt_add_subnode(vbi->fdt, "/gpio-keys/poweroff"); - qemu_fdt_setprop_string(vbi->fdt, "/gpio-keys/poweroff", + qemu_fdt_add_subnode(vms->fdt, "/gpio-keys/poweroff"); + qemu_fdt_setprop_string(vms->fdt, "/gpio-keys/poweroff", "label", "GPIO Key Poweroff"); - qemu_fdt_setprop_cell(vbi->fdt, "/gpio-keys/poweroff", "linux,code", + qemu_fdt_setprop_cell(vms->fdt, "/gpio-keys/poweroff", "linux,code", KEY_POWER); - qemu_fdt_setprop_cells(vbi->fdt, "/gpio-keys/poweroff", + qemu_fdt_setprop_cells(vms->fdt, "/gpio-keys/poweroff", "gpios", phandle, 3, 0); /* connect powerdown request */ @@ -730,10 +730,10 @@ static void create_gpio(const VirtMachineState *vbi, qemu_irq *pic) g_free(nodename); } -static void create_virtio_devices(const VirtMachineState *vbi, qemu_irq *pic) +static void create_virtio_devices(const VirtMachineState *vms, qemu_irq *pic) { int i; - hwaddr size = vbi->memmap[VIRT_MMIO].size; + hwaddr size = vms->memmap[VIRT_MMIO].size; /* We create the transports in forwards order. Since qbus_realize() * prepends (not appends) new child buses, the incrementing loop below will @@ -763,8 +763,8 @@ static void create_virtio_devices(const VirtMachineState *vbi, qemu_irq *pic) * of disks users must use UUIDs or similar mechanisms. */ for (i = 0; i < NUM_VIRTIO_TRANSPORTS; i++) { - int irq = vbi->irqmap[VIRT_MMIO] + i; - hwaddr base = vbi->memmap[VIRT_MMIO].base + i * size; + int irq = vms->irqmap[VIRT_MMIO] + i; + hwaddr base = vms->memmap[VIRT_MMIO].base + i * size; sysbus_create_simple("virtio-mmio", base, pic[irq]); } @@ -778,16 +778,16 @@ static void create_virtio_devices(const VirtMachineState *vbi, qemu_irq *pic) */ for (i = NUM_VIRTIO_TRANSPORTS - 1; i >= 0; i--) { char *nodename; - int irq = vbi->irqmap[VIRT_MMIO] + i; - hwaddr base = vbi->memmap[VIRT_MMIO].base + i * size; + int irq = vms->irqmap[VIRT_MMIO] + i; + hwaddr base = vms->memmap[VIRT_MMIO].base + i * size; nodename = g_strdup_printf("/virtio_mmio@%" PRIx64, base); - qemu_fdt_add_subnode(vbi->fdt, nodename); - qemu_fdt_setprop_string(vbi->fdt, nodename, + qemu_fdt_add_subnode(vms->fdt, nodename); + qemu_fdt_setprop_string(vms->fdt, nodename, "compatible", "virtio,mmio"); - qemu_fdt_setprop_sized_cells(vbi->fdt, nodename, "reg", + qemu_fdt_setprop_sized_cells(vms->fdt, nodename, "reg", 2, base, 2, size); - qemu_fdt_setprop_cells(vbi->fdt, nodename, "interrupts", + qemu_fdt_setprop_cells(vms->fdt, nodename, "interrupts", GIC_FDT_IRQ_TYPE_SPI, irq, GIC_FDT_IRQ_FLAGS_EDGE_LO_HI); g_free(nodename); @@ -850,7 +850,7 @@ static void create_one_flash(const char *name, hwaddr flashbase, } } -static void create_flash(const VirtMachineState *vbi, +static void create_flash(const VirtMachineState *vms, MemoryRegion *sysmem, MemoryRegion *secure_sysmem) { @@ -862,8 +862,8 @@ static void create_flash(const VirtMachineState *vbi, * If sysmem == secure_sysmem this means there is no separate Secure * address space and both flash devices are generally visible. */ - hwaddr flashsize = vbi->memmap[VIRT_FLASH].size / 2; - hwaddr flashbase = vbi->memmap[VIRT_FLASH].base; + hwaddr flashsize = vms->memmap[VIRT_FLASH].size / 2; + hwaddr flashbase = vms->memmap[VIRT_FLASH].base; char *nodename; create_one_flash("virt.flash0", flashbase, flashsize, @@ -874,41 +874,41 @@ static void create_flash(const VirtMachineState *vbi, if (sysmem == secure_sysmem) { /* Report both flash devices as a single node in the DT */ nodename = g_strdup_printf("/flash@%" PRIx64, flashbase); - qemu_fdt_add_subnode(vbi->fdt, nodename); - qemu_fdt_setprop_string(vbi->fdt, nodename, "compatible", "cfi-flash"); - qemu_fdt_setprop_sized_cells(vbi->fdt, nodename, "reg", + qemu_fdt_add_subnode(vms->fdt, nodename); + qemu_fdt_setprop_string(vms->fdt, nodename, "compatible", "cfi-flash"); + qemu_fdt_setprop_sized_cells(vms->fdt, nodename, "reg", 2, flashbase, 2, flashsize, 2, flashbase + flashsize, 2, flashsize); - qemu_fdt_setprop_cell(vbi->fdt, nodename, "bank-width", 4); + qemu_fdt_setprop_cell(vms->fdt, nodename, "bank-width", 4); g_free(nodename); } else { /* Report the devices as separate nodes so we can mark one as * only visible to the secure world. */ nodename = g_strdup_printf("/secflash@%" PRIx64, flashbase); - qemu_fdt_add_subnode(vbi->fdt, nodename); - qemu_fdt_setprop_string(vbi->fdt, nodename, "compatible", "cfi-flash"); - qemu_fdt_setprop_sized_cells(vbi->fdt, nodename, "reg", + qemu_fdt_add_subnode(vms->fdt, nodename); + qemu_fdt_setprop_string(vms->fdt, nodename, "compatible", "cfi-flash"); + qemu_fdt_setprop_sized_cells(vms->fdt, nodename, "reg", 2, flashbase, 2, flashsize); - qemu_fdt_setprop_cell(vbi->fdt, nodename, "bank-width", 4); - qemu_fdt_setprop_string(vbi->fdt, nodename, "status", "disabled"); - qemu_fdt_setprop_string(vbi->fdt, nodename, "secure-status", "okay"); + qemu_fdt_setprop_cell(vms->fdt, nodename, "bank-width", 4); + qemu_fdt_setprop_string(vms->fdt, nodename, "status", "disabled"); + qemu_fdt_setprop_string(vms->fdt, nodename, "secure-status", "okay"); g_free(nodename); nodename = g_strdup_printf("/flash@%" PRIx64, flashbase); - qemu_fdt_add_subnode(vbi->fdt, nodename); - qemu_fdt_setprop_string(vbi->fdt, nodename, "compatible", "cfi-flash"); - qemu_fdt_setprop_sized_cells(vbi->fdt, nodename, "reg", + qemu_fdt_add_subnode(vms->fdt, nodename); + qemu_fdt_setprop_string(vms->fdt, nodename, "compatible", "cfi-flash"); + qemu_fdt_setprop_sized_cells(vms->fdt, nodename, "reg", 2, flashbase + flashsize, 2, flashsize); - qemu_fdt_setprop_cell(vbi->fdt, nodename, "bank-width", 4); + qemu_fdt_setprop_cell(vms->fdt, nodename, "bank-width", 4); g_free(nodename); } } -static void create_fw_cfg(const VirtMachineState *vbi, AddressSpace *as) +static void create_fw_cfg(const VirtMachineState *vms, AddressSpace *as) { - hwaddr base = vbi->memmap[VIRT_FW_CFG].base; - hwaddr size = vbi->memmap[VIRT_FW_CFG].size; + hwaddr base = vms->memmap[VIRT_FW_CFG].base; + hwaddr size = vms->memmap[VIRT_FW_CFG].size; FWCfgState *fw_cfg; char *nodename; @@ -916,15 +916,15 @@ static void create_fw_cfg(const VirtMachineState *vbi, AddressSpace *as) fw_cfg_add_i16(fw_cfg, FW_CFG_NB_CPUS, (uint16_t)smp_cpus); nodename = g_strdup_printf("/fw-cfg@%" PRIx64, base); - qemu_fdt_add_subnode(vbi->fdt, nodename); - qemu_fdt_setprop_string(vbi->fdt, nodename, + qemu_fdt_add_subnode(vms->fdt, nodename); + qemu_fdt_setprop_string(vms->fdt, nodename, "compatible", "qemu,fw-cfg-mmio"); - qemu_fdt_setprop_sized_cells(vbi->fdt, nodename, "reg", + qemu_fdt_setprop_sized_cells(vms->fdt, nodename, "reg", 2, base, 2, size); g_free(nodename); } -static void create_pcie_irq_map(const VirtMachineState *vbi, +static void create_pcie_irq_map(const VirtMachineState *vms, uint32_t gic_phandle, int first_irq, const char *nodename) { @@ -952,28 +952,28 @@ static void create_pcie_irq_map(const VirtMachineState *vbi, } } - qemu_fdt_setprop(vbi->fdt, nodename, "interrupt-map", + qemu_fdt_setprop(vms->fdt, nodename, "interrupt-map", full_irq_map, sizeof(full_irq_map)); - qemu_fdt_setprop_cells(vbi->fdt, nodename, "interrupt-map-mask", + qemu_fdt_setprop_cells(vms->fdt, nodename, "interrupt-map-mask", 0x1800, 0, 0, /* devfn (PCI_SLOT(3)) */ 0x7 /* PCI irq */); } -static void create_pcie(const VirtMachineState *vbi, qemu_irq *pic, +static void create_pcie(const VirtMachineState *vms, qemu_irq *pic, bool use_highmem) { - hwaddr base_mmio = vbi->memmap[VIRT_PCIE_MMIO].base; - hwaddr size_mmio = vbi->memmap[VIRT_PCIE_MMIO].size; - hwaddr base_mmio_high = vbi->memmap[VIRT_PCIE_MMIO_HIGH].base; - hwaddr size_mmio_high = vbi->memmap[VIRT_PCIE_MMIO_HIGH].size; - hwaddr base_pio = vbi->memmap[VIRT_PCIE_PIO].base; - hwaddr size_pio = vbi->memmap[VIRT_PCIE_PIO].size; - hwaddr base_ecam = vbi->memmap[VIRT_PCIE_ECAM].base; - hwaddr size_ecam = vbi->memmap[VIRT_PCIE_ECAM].size; + hwaddr base_mmio = vms->memmap[VIRT_PCIE_MMIO].base; + hwaddr size_mmio = vms->memmap[VIRT_PCIE_MMIO].size; + hwaddr base_mmio_high = vms->memmap[VIRT_PCIE_MMIO_HIGH].base; + hwaddr size_mmio_high = vms->memmap[VIRT_PCIE_MMIO_HIGH].size; + hwaddr base_pio = vms->memmap[VIRT_PCIE_PIO].base; + hwaddr size_pio = vms->memmap[VIRT_PCIE_PIO].size; + hwaddr base_ecam = vms->memmap[VIRT_PCIE_ECAM].base; + hwaddr size_ecam = vms->memmap[VIRT_PCIE_ECAM].size; hwaddr base = base_mmio; int nr_pcie_buses = size_ecam / PCIE_MMCFG_SIZE_MIN; - int irq = vbi->irqmap[VIRT_PCIE]; + int irq = vms->irqmap[VIRT_PCIE]; MemoryRegion *mmio_alias; MemoryRegion *mmio_reg; MemoryRegion *ecam_alias; @@ -1035,26 +1035,26 @@ static void create_pcie(const VirtMachineState *vbi, qemu_irq *pic, } nodename = g_strdup_printf("/pcie@%" PRIx64, base); - qemu_fdt_add_subnode(vbi->fdt, nodename); - qemu_fdt_setprop_string(vbi->fdt, nodename, + qemu_fdt_add_subnode(vms->fdt, nodename); + qemu_fdt_setprop_string(vms->fdt, nodename, "compatible", "pci-host-ecam-generic"); - qemu_fdt_setprop_string(vbi->fdt, nodename, "device_type", "pci"); - qemu_fdt_setprop_cell(vbi->fdt, nodename, "#address-cells", 3); - qemu_fdt_setprop_cell(vbi->fdt, nodename, "#size-cells", 2); - qemu_fdt_setprop_cells(vbi->fdt, nodename, "bus-range", 0, + qemu_fdt_setprop_string(vms->fdt, nodename, "device_type", "pci"); + qemu_fdt_setprop_cell(vms->fdt, nodename, "#address-cells", 3); + qemu_fdt_setprop_cell(vms->fdt, nodename, "#size-cells", 2); + qemu_fdt_setprop_cells(vms->fdt, nodename, "bus-range", 0, nr_pcie_buses - 1); - qemu_fdt_setprop(vbi->fdt, nodename, "dma-coherent", NULL, 0); + qemu_fdt_setprop(vms->fdt, nodename, "dma-coherent", NULL, 0); - if (vbi->msi_phandle) { - qemu_fdt_setprop_cells(vbi->fdt, nodename, "msi-parent", - vbi->msi_phandle); + if (vms->msi_phandle) { + qemu_fdt_setprop_cells(vms->fdt, nodename, "msi-parent", + vms->msi_phandle); } - qemu_fdt_setprop_sized_cells(vbi->fdt, nodename, "reg", + qemu_fdt_setprop_sized_cells(vms->fdt, nodename, "reg", 2, base_ecam, 2, size_ecam); if (use_highmem) { - qemu_fdt_setprop_sized_cells(vbi->fdt, nodename, "ranges", + qemu_fdt_setprop_sized_cells(vms->fdt, nodename, "ranges", 1, FDT_PCI_RANGE_IOPORT, 2, 0, 2, base_pio, 2, size_pio, 1, FDT_PCI_RANGE_MMIO, 2, base_mmio, @@ -1063,20 +1063,20 @@ static void create_pcie(const VirtMachineState *vbi, qemu_irq *pic, 2, base_mmio_high, 2, base_mmio_high, 2, size_mmio_high); } else { - qemu_fdt_setprop_sized_cells(vbi->fdt, nodename, "ranges", + qemu_fdt_setprop_sized_cells(vms->fdt, nodename, "ranges", 1, FDT_PCI_RANGE_IOPORT, 2, 0, 2, base_pio, 2, size_pio, 1, FDT_PCI_RANGE_MMIO, 2, base_mmio, 2, base_mmio, 2, size_mmio); } - qemu_fdt_setprop_cell(vbi->fdt, nodename, "#interrupt-cells", 1); - create_pcie_irq_map(vbi, vbi->gic_phandle, irq, nodename); + qemu_fdt_setprop_cell(vms->fdt, nodename, "#interrupt-cells", 1); + create_pcie_irq_map(vms, vms->gic_phandle, irq, nodename); g_free(nodename); } -static void create_platform_bus(VirtMachineState *vbi, qemu_irq *pic) +static void create_platform_bus(VirtMachineState *vms, qemu_irq *pic) { DeviceState *dev; SysBusDevice *s; @@ -1084,13 +1084,13 @@ static void create_platform_bus(VirtMachineState *vbi, qemu_irq *pic) ARMPlatformBusFDTParams *fdt_params = g_new(ARMPlatformBusFDTParams, 1); MemoryRegion *sysmem = get_system_memory(); - platform_bus_params.platform_bus_base = vbi->memmap[VIRT_PLATFORM_BUS].base; - platform_bus_params.platform_bus_size = vbi->memmap[VIRT_PLATFORM_BUS].size; - platform_bus_params.platform_bus_first_irq = vbi->irqmap[VIRT_PLATFORM_BUS]; + platform_bus_params.platform_bus_base = vms->memmap[VIRT_PLATFORM_BUS].base; + platform_bus_params.platform_bus_size = vms->memmap[VIRT_PLATFORM_BUS].size; + platform_bus_params.platform_bus_first_irq = vms->irqmap[VIRT_PLATFORM_BUS]; platform_bus_params.platform_bus_num_irqs = PLATFORM_BUS_NUM_IRQS; fdt_params->system_params = &platform_bus_params; - fdt_params->binfo = &vbi->bootinfo; + fdt_params->binfo = &vms->bootinfo; fdt_params->intc = "/intc"; /* * register a machine init done notifier that creates the device tree @@ -1117,24 +1117,24 @@ static void create_platform_bus(VirtMachineState *vbi, qemu_irq *pic) sysbus_mmio_get_region(s, 0)); } -static void create_secure_ram(VirtMachineState *vbi, +static void create_secure_ram(VirtMachineState *vms, MemoryRegion *secure_sysmem) { MemoryRegion *secram = g_new(MemoryRegion, 1); char *nodename; - hwaddr base = vbi->memmap[VIRT_SECURE_MEM].base; - hwaddr size = vbi->memmap[VIRT_SECURE_MEM].size; + hwaddr base = vms->memmap[VIRT_SECURE_MEM].base; + hwaddr size = vms->memmap[VIRT_SECURE_MEM].size; memory_region_init_ram(secram, NULL, "virt.secure-ram", size, &error_fatal); vmstate_register_ram_global(secram); memory_region_add_subregion(secure_sysmem, base, secram); nodename = g_strdup_printf("/secram@%" PRIx64, base); - qemu_fdt_add_subnode(vbi->fdt, nodename); - qemu_fdt_setprop_string(vbi->fdt, nodename, "device_type", "memory"); - qemu_fdt_setprop_sized_cells(vbi->fdt, nodename, "reg", 2, base, 2, size); - qemu_fdt_setprop_string(vbi->fdt, nodename, "status", "disabled"); - qemu_fdt_setprop_string(vbi->fdt, nodename, "secure-status", "okay"); + qemu_fdt_add_subnode(vms->fdt, nodename); + qemu_fdt_setprop_string(vms->fdt, nodename, "device_type", "memory"); + qemu_fdt_setprop_sized_cells(vms->fdt, nodename, "reg", 2, base, 2, size); + qemu_fdt_setprop_string(vms->fdt, nodename, "status", "disabled"); + qemu_fdt_setprop_string(vms->fdt, nodename, "secure-status", "okay"); g_free(nodename); } @@ -1197,7 +1197,6 @@ static void machvirt_init(MachineState *machine) int n, virt_max_cpus; MemoryRegion *ram = g_new(MemoryRegion, 1); const char *cpu_model = machine->cpu_model; - VirtMachineState *vbi = vms; VirtGuestInfoState *guest_info_state = g_malloc0(sizeof *guest_info_state); VirtGuestInfo *guest_info = &guest_info_state->info; char **cpustr; @@ -1243,13 +1242,13 @@ static void machvirt_init(MachineState *machine) * let the boot ROM sort them out. * The usual case is that we do use QEMU's PSCI implementation. */ - vbi->using_psci = !(vms->secure && firmware_loaded); + vms->using_psci = !(vms->secure && firmware_loaded); /* The maximum number of CPUs depends on the GIC version, or on how * many redistributors we can fit into the memory map. */ if (gic_version == 3) { - virt_max_cpus = vbi->memmap[VIRT_GIC_REDIST].size / 0x20000; + virt_max_cpus = vms->memmap[VIRT_GIC_REDIST].size / 0x20000; clustersz = GICV3_TARGETLIST_BITS; } else { virt_max_cpus = GIC_NCPU; @@ -1263,9 +1262,9 @@ static void machvirt_init(MachineState *machine) exit(1); } - vbi->smp_cpus = smp_cpus; + vms->smp_cpus = smp_cpus; - if (machine->ram_size > vbi->memmap[VIRT_MEM].size) { + if (machine->ram_size > vms->memmap[VIRT_MEM].size) { error_report("mach-virt: cannot model more than %dGB RAM", RAMLIMIT_GB); exit(1); } @@ -1287,7 +1286,7 @@ static void machvirt_init(MachineState *machine) memory_region_add_subregion_overlap(secure_sysmem, 0, sysmem, -1); } - create_fdt(vbi); + create_fdt(vms); oc = cpu_class_by_name(TYPE_ARM_CPU, cpustr[0]); if (!oc) { @@ -1326,7 +1325,7 @@ static void machvirt_init(MachineState *machine) object_property_set_bool(cpuobj, false, "has_el3", NULL); } - if (vbi->using_psci) { + if (vms->using_psci) { object_property_set_int(cpuobj, QEMU_PSCI_CONDUIT_HVC, "psci-conduit", NULL); @@ -1342,7 +1341,7 @@ static void machvirt_init(MachineState *machine) } if (object_property_find(cpuobj, "reset-cbar", NULL)) { - object_property_set_int(cpuobj, vbi->memmap[VIRT_CPUPERIPHS].base, + object_property_set_int(cpuobj, vms->memmap[VIRT_CPUPERIPHS].base, "reset-cbar", &error_abort); } @@ -1355,62 +1354,62 @@ static void machvirt_init(MachineState *machine) object_property_set_bool(cpuobj, true, "realized", NULL); } - fdt_add_timer_nodes(vbi, gic_version); - fdt_add_cpu_nodes(vbi); - fdt_add_psci_node(vbi); + fdt_add_timer_nodes(vms, gic_version); + fdt_add_cpu_nodes(vms); + fdt_add_psci_node(vms); memory_region_allocate_system_memory(ram, NULL, "mach-virt.ram", machine->ram_size); - memory_region_add_subregion(sysmem, vbi->memmap[VIRT_MEM].base, ram); + memory_region_add_subregion(sysmem, vms->memmap[VIRT_MEM].base, ram); - create_flash(vbi, sysmem, secure_sysmem ? secure_sysmem : sysmem); + create_flash(vms, sysmem, secure_sysmem ? secure_sysmem : sysmem); - create_gic(vbi, pic, gic_version, vms->secure, vmc->no_its); + create_gic(vms, pic, gic_version, vms->secure, vmc->no_its); - fdt_add_pmu_nodes(vbi, gic_version); + fdt_add_pmu_nodes(vms, gic_version); - create_uart(vbi, pic, VIRT_UART, sysmem, serial_hds[0]); + create_uart(vms, pic, VIRT_UART, sysmem, serial_hds[0]); if (vms->secure) { - create_secure_ram(vbi, secure_sysmem); - create_uart(vbi, pic, VIRT_SECURE_UART, secure_sysmem, serial_hds[1]); + create_secure_ram(vms, secure_sysmem); + create_uart(vms, pic, VIRT_SECURE_UART, secure_sysmem, serial_hds[1]); } - create_rtc(vbi, pic); + create_rtc(vms, pic); - create_pcie(vbi, pic, vms->highmem); + create_pcie(vms, pic, vms->highmem); - create_gpio(vbi, pic); + create_gpio(vms, pic); /* Create mmio transports, so the user can create virtio backends * (which will be automatically plugged in to the transports). If * no backend is created the transport will just sit harmlessly idle. */ - create_virtio_devices(vbi, pic); + create_virtio_devices(vms, pic); - create_fw_cfg(vbi, &address_space_memory); + create_fw_cfg(vms, &address_space_memory); rom_set_fw(fw_cfg_find()); guest_info->smp_cpus = smp_cpus; guest_info->fw_cfg = fw_cfg_find(); - guest_info->memmap = vbi->memmap; - guest_info->irqmap = vbi->irqmap; + guest_info->memmap = vms->memmap; + guest_info->irqmap = vms->irqmap; guest_info->use_highmem = vms->highmem; guest_info->gic_version = gic_version; guest_info->no_its = vmc->no_its; guest_info_state->machine_done.notify = virt_guest_info_machine_done; qemu_add_machine_init_done_notifier(&guest_info_state->machine_done); - vbi->bootinfo.ram_size = machine->ram_size; - vbi->bootinfo.kernel_filename = machine->kernel_filename; - vbi->bootinfo.kernel_cmdline = machine->kernel_cmdline; - vbi->bootinfo.initrd_filename = machine->initrd_filename; - vbi->bootinfo.nb_cpus = smp_cpus; - vbi->bootinfo.board_id = -1; - vbi->bootinfo.loader_start = vbi->memmap[VIRT_MEM].base; - vbi->bootinfo.get_dtb = machvirt_dtb; - vbi->bootinfo.firmware_loaded = firmware_loaded; - arm_load_kernel(ARM_CPU(first_cpu), &vbi->bootinfo); + vms->bootinfo.ram_size = machine->ram_size; + vms->bootinfo.kernel_filename = machine->kernel_filename; + vms->bootinfo.kernel_cmdline = machine->kernel_cmdline; + vms->bootinfo.initrd_filename = machine->initrd_filename; + vms->bootinfo.nb_cpus = smp_cpus; + vms->bootinfo.board_id = -1; + vms->bootinfo.loader_start = vms->memmap[VIRT_MEM].base; + vms->bootinfo.get_dtb = machvirt_dtb; + vms->bootinfo.firmware_loaded = firmware_loaded; + arm_load_kernel(ARM_CPU(first_cpu), &vms->bootinfo); /* * arm_load_kernel machine init done notifier registration must @@ -1418,7 +1417,7 @@ static void machvirt_init(MachineState *machine) * another notifier is registered which adds platform bus nodes. * Notifiers are executed in registration reverse order. */ - create_platform_bus(vbi, pic); + create_platform_bus(vms, pic); } static bool virt_get_secure(Object *obj, Error **errp) From 156bc9a5ea877e8252a07f35543a24157d4ab822 Mon Sep 17 00:00:00 2001 From: Peter Maydell Date: Mon, 9 Jan 2017 11:40:21 +0000 Subject: [PATCH 05/21] hw/arm/virt: Don't incorrectly claim architectural timer to be edge-triggered The architectural timers in ARM CPUs all have level triggered interrupts (unless you're using KVM on a host kernel before 4.4, which misimplemented them as edge-triggered). We were incorrectly describing them in the device tree as edge triggered. This can cause problems for guest kernels in 4.8 before rc6: * pre-4.8 kernels ignore the values in the DT * 4.8 before rc6 write the DT values to the GIC config registers * newer than rc6 ignore the DT and insist that the timer interrupts are level triggered regardless Fix the DT so we're describing reality. For backwards-compatibility purposes, only do this for the virt-2.9 machine onward. Signed-off-by: Peter Maydell Reviewed-by: Andrew Jones --- hw/arm/virt.c | 34 ++++++++++++++++++++++++++++++---- 1 file changed, 30 insertions(+), 4 deletions(-) diff --git a/hw/arm/virt.c b/hw/arm/virt.c index 54498ead23..2ca9527ba4 100644 --- a/hw/arm/virt.c +++ b/hw/arm/virt.c @@ -71,6 +71,7 @@ typedef struct { bool disallow_affinity_adjustment; bool no_its; bool no_pmu; + bool claim_edge_triggered_timers; } VirtMachineClass; typedef struct { @@ -309,12 +310,31 @@ static void fdt_add_psci_node(const VirtMachineState *vms) static void fdt_add_timer_nodes(const VirtMachineState *vms, int gictype) { - /* Note that on A15 h/w these interrupts are level-triggered, - * but for the GIC implementation provided by both QEMU and KVM - * they are edge-triggered. + /* On real hardware these interrupts are level-triggered. + * On KVM they were edge-triggered before host kernel version 4.4, + * and level-triggered afterwards. + * On emulated QEMU they are level-triggered. + * + * Getting the DTB info about them wrong is awkward for some + * guest kernels: + * pre-4.8 ignore the DT and leave the interrupt configured + * with whatever the GIC reset value (or the bootloader) left it at + * 4.8 before rc6 honour the incorrect data by programming it back + * into the GIC, causing problems + * 4.8rc6 and later ignore the DT and always write "level triggered" + * into the GIC + * + * For backwards-compatibility, virt-2.8 and earlier will continue + * to say these are edge-triggered, but later machines will report + * the correct information. */ ARMCPU *armcpu; - uint32_t irqflags = GIC_FDT_IRQ_FLAGS_EDGE_LO_HI; + VirtMachineClass *vmc = VIRT_MACHINE_GET_CLASS(vms); + uint32_t irqflags = GIC_FDT_IRQ_FLAGS_LEVEL_HI; + + if (vmc->claim_edge_triggered_timers) { + irqflags = GIC_FDT_IRQ_FLAGS_EDGE_LO_HI; + } if (gictype == 2) { irqflags = deposit32(irqflags, GIC_FDT_IRQ_PPI_CPU_START, @@ -1556,8 +1576,14 @@ static void virt_2_8_instance_init(Object *obj) static void virt_machine_2_8_options(MachineClass *mc) { + VirtMachineClass *vmc = VIRT_MACHINE_CLASS(OBJECT_CLASS(mc)); + virt_machine_2_9_options(mc); SET_MACHINE_COMPAT(mc, VIRT_COMPAT_2_8); + /* For 2.8 and earlier we falsely claimed in the DT that + * our timers were edge-triggered, not level-triggered. + */ + vmc->claim_edge_triggered_timers = true; } DEFINE_VIRT_MACHINE(2, 8) From 330afe059909d8dc11d70d6a059408d430689d3f Mon Sep 17 00:00:00 2001 From: Andrew Jones Date: Mon, 9 Jan 2017 11:40:21 +0000 Subject: [PATCH 06/21] hw/arm/virt-acpi-build: add all missing cpu_to_le's Signed-off-by: Andrew Jones Message-id: 20170102200153.28864-2-drjones@redhat.com Signed-off-by: Peter Maydell --- hw/arm/virt-acpi-build.c | 27 ++++++++++++++------------- 1 file changed, 14 insertions(+), 13 deletions(-) diff --git a/hw/arm/virt-acpi-build.c b/hw/arm/virt-acpi-build.c index 7102686882..0e255b7520 100644 --- a/hw/arm/virt-acpi-build.c +++ b/hw/arm/virt-acpi-build.c @@ -542,17 +542,18 @@ build_gtdt(GArray *table_data, BIOSLinker *linker) gtdt = acpi_data_push(table_data, sizeof *gtdt); /* The interrupt values are the same with the device tree when adding 16 */ - gtdt->secure_el1_interrupt = ARCH_TIMER_S_EL1_IRQ + 16; - gtdt->secure_el1_flags = ACPI_EDGE_SENSITIVE; + gtdt->secure_el1_interrupt = cpu_to_le32(ARCH_TIMER_S_EL1_IRQ + 16); + gtdt->secure_el1_flags = cpu_to_le32(ACPI_EDGE_SENSITIVE); - gtdt->non_secure_el1_interrupt = ARCH_TIMER_NS_EL1_IRQ + 16; - gtdt->non_secure_el1_flags = ACPI_EDGE_SENSITIVE | ACPI_GTDT_ALWAYS_ON; + gtdt->non_secure_el1_interrupt = cpu_to_le32(ARCH_TIMER_NS_EL1_IRQ + 16); + gtdt->non_secure_el1_flags = cpu_to_le32(ACPI_EDGE_SENSITIVE | + ACPI_GTDT_ALWAYS_ON); - gtdt->virtual_timer_interrupt = ARCH_TIMER_VIRT_IRQ + 16; - gtdt->virtual_timer_flags = ACPI_EDGE_SENSITIVE; + gtdt->virtual_timer_interrupt = cpu_to_le32(ARCH_TIMER_VIRT_IRQ + 16); + gtdt->virtual_timer_flags = cpu_to_le32(ACPI_EDGE_SENSITIVE); - gtdt->non_secure_el2_interrupt = ARCH_TIMER_NS_EL2_IRQ + 16; - gtdt->non_secure_el2_flags = ACPI_EDGE_SENSITIVE; + gtdt->non_secure_el2_interrupt = cpu_to_le32(ARCH_TIMER_NS_EL2_IRQ + 16); + gtdt->non_secure_el2_flags = cpu_to_le32(ACPI_EDGE_SENSITIVE); build_header(linker, table_data, (void *)(table_data->data + gtdt_start), "GTDT", @@ -576,7 +577,7 @@ build_madt(GArray *table_data, BIOSLinker *linker, VirtGuestInfo *guest_info) gicd = acpi_data_push(table_data, sizeof *gicd); gicd->type = ACPI_APIC_GENERIC_DISTRIBUTOR; gicd->length = sizeof(*gicd); - gicd->base_address = memmap[VIRT_GIC_DIST].base; + gicd->base_address = cpu_to_le64(memmap[VIRT_GIC_DIST].base); gicd->version = guest_info->gic_version; for (i = 0; i < guest_info->smp_cpus; i++) { @@ -587,11 +588,11 @@ build_madt(GArray *table_data, BIOSLinker *linker, VirtGuestInfo *guest_info) gicc->type = ACPI_APIC_GENERIC_INTERRUPT; gicc->length = sizeof(*gicc); if (guest_info->gic_version == 2) { - gicc->base_address = memmap[VIRT_GIC_CPU].base; + gicc->base_address = cpu_to_le64(memmap[VIRT_GIC_CPU].base); } - gicc->cpu_interface_number = i; - gicc->arm_mpidr = armcpu->mp_affinity; - gicc->uid = i; + gicc->cpu_interface_number = cpu_to_le32(i); + gicc->arm_mpidr = cpu_to_le64(armcpu->mp_affinity); + gicc->uid = cpu_to_le32(i); gicc->flags = cpu_to_le32(ACPI_GICC_ENABLED); if (arm_feature(&armcpu->env, ARM_FEATURE_PMU)) { From 6e2ed65f4a523afa740f61ffe887a5fd62ef2644 Mon Sep 17 00:00:00 2001 From: Andrew Jones Date: Mon, 9 Jan 2017 11:40:21 +0000 Subject: [PATCH 07/21] hw/arm/virt-acpi-build: name GIC CPU Interface Structure appropriately Also move the enabled flag definition from mach-virt code to acpi common. Signed-off-by: Andrew Jones Message-id: 20170102200153.28864-3-drjones@redhat.com Reviewed-by: Peter Maydell Signed-off-by: Peter Maydell --- hw/arm/virt-acpi-build.c | 8 ++++---- include/hw/acpi/acpi-defs.h | 9 ++++++--- include/hw/arm/virt-acpi-build.h | 2 -- 3 files changed, 10 insertions(+), 9 deletions(-) diff --git a/hw/arm/virt-acpi-build.c b/hw/arm/virt-acpi-build.c index 0e255b7520..5071a0b3d7 100644 --- a/hw/arm/virt-acpi-build.c +++ b/hw/arm/virt-acpi-build.c @@ -581,11 +581,11 @@ build_madt(GArray *table_data, BIOSLinker *linker, VirtGuestInfo *guest_info) gicd->version = guest_info->gic_version; for (i = 0; i < guest_info->smp_cpus; i++) { - AcpiMadtGenericInterrupt *gicc = acpi_data_push(table_data, - sizeof *gicc); + AcpiMadtGenericCpuInterface *gicc = acpi_data_push(table_data, + sizeof(*gicc)); ARMCPU *armcpu = ARM_CPU(qemu_get_cpu(i)); - gicc->type = ACPI_APIC_GENERIC_INTERRUPT; + gicc->type = ACPI_APIC_GENERIC_CPU_INTERFACE; gicc->length = sizeof(*gicc); if (guest_info->gic_version == 2) { gicc->base_address = cpu_to_le64(memmap[VIRT_GIC_CPU].base); @@ -593,7 +593,7 @@ build_madt(GArray *table_data, BIOSLinker *linker, VirtGuestInfo *guest_info) gicc->cpu_interface_number = cpu_to_le32(i); gicc->arm_mpidr = cpu_to_le64(armcpu->mp_affinity); gicc->uid = cpu_to_le32(i); - gicc->flags = cpu_to_le32(ACPI_GICC_ENABLED); + gicc->flags = cpu_to_le32(ACPI_MADT_GICC_ENABLED); if (arm_feature(&armcpu->env, ARM_FEATURE_PMU)) { gicc->performance_interrupt = cpu_to_le32(PPI(VIRTUAL_PMU_IRQ)); diff --git a/include/hw/acpi/acpi-defs.h b/include/hw/acpi/acpi-defs.h index 154f3b82f6..510f23c931 100644 --- a/include/hw/acpi/acpi-defs.h +++ b/include/hw/acpi/acpi-defs.h @@ -290,7 +290,7 @@ typedef struct AcpiMultipleApicTable AcpiMultipleApicTable; #define ACPI_APIC_XRUPT_SOURCE 8 #define ACPI_APIC_LOCAL_X2APIC 9 #define ACPI_APIC_LOCAL_X2APIC_NMI 10 -#define ACPI_APIC_GENERIC_INTERRUPT 11 +#define ACPI_APIC_GENERIC_CPU_INTERFACE 11 #define ACPI_APIC_GENERIC_DISTRIBUTOR 12 #define ACPI_APIC_GENERIC_MSI_FRAME 13 #define ACPI_APIC_GENERIC_REDISTRIBUTOR 14 @@ -361,7 +361,7 @@ struct AcpiMadtLocalX2ApicNmi { } QEMU_PACKED; typedef struct AcpiMadtLocalX2ApicNmi AcpiMadtLocalX2ApicNmi; -struct AcpiMadtGenericInterrupt { +struct AcpiMadtGenericCpuInterface { ACPI_SUB_HEADER_DEF uint16_t reserved; uint32_t cpu_interface_number; @@ -378,7 +378,10 @@ struct AcpiMadtGenericInterrupt { uint64_t arm_mpidr; } QEMU_PACKED; -typedef struct AcpiMadtGenericInterrupt AcpiMadtGenericInterrupt; +typedef struct AcpiMadtGenericCpuInterface AcpiMadtGenericCpuInterface; + +/* GICC CPU Interface Flags */ +#define ACPI_MADT_GICC_ENABLED 1 struct AcpiMadtGenericDistributor { ACPI_SUB_HEADER_DEF diff --git a/include/hw/arm/virt-acpi-build.h b/include/hw/arm/virt-acpi-build.h index f5ec749b8f..2bcd22265c 100644 --- a/include/hw/arm/virt-acpi-build.h +++ b/include/hw/arm/virt-acpi-build.h @@ -24,8 +24,6 @@ #include "hw/arm/virt.h" #include "qemu/notify.h" -#define ACPI_GICC_ENABLED 1 - typedef struct VirtGuestInfo { int smp_cpus; FWCfgState *fw_cfg; From aca4bbf4a36fcaff6b7dbe45e2fc5bcb6b2dc4ab Mon Sep 17 00:00:00 2001 From: Andrew Jones Date: Mon, 9 Jan 2017 11:40:21 +0000 Subject: [PATCH 08/21] hw/arm/virt-acpi-build: gtdt: improve flag naming Also remove all unused flags. Signed-off-by: Andrew Jones Message-id: 20170102200153.28864-4-drjones@redhat.com Reviewed-by: Peter Maydell Signed-off-by: Peter Maydell --- hw/arm/virt-acpi-build.c | 10 +++++----- include/hw/acpi/acpi-defs.h | 17 ++--------------- 2 files changed, 7 insertions(+), 20 deletions(-) diff --git a/hw/arm/virt-acpi-build.c b/hw/arm/virt-acpi-build.c index 5071a0b3d7..420cd21644 100644 --- a/hw/arm/virt-acpi-build.c +++ b/hw/arm/virt-acpi-build.c @@ -543,17 +543,17 @@ build_gtdt(GArray *table_data, BIOSLinker *linker) gtdt = acpi_data_push(table_data, sizeof *gtdt); /* The interrupt values are the same with the device tree when adding 16 */ gtdt->secure_el1_interrupt = cpu_to_le32(ARCH_TIMER_S_EL1_IRQ + 16); - gtdt->secure_el1_flags = cpu_to_le32(ACPI_EDGE_SENSITIVE); + gtdt->secure_el1_flags = cpu_to_le32(ACPI_GTDT_INTERRUPT_MODE_EDGE); gtdt->non_secure_el1_interrupt = cpu_to_le32(ARCH_TIMER_NS_EL1_IRQ + 16); - gtdt->non_secure_el1_flags = cpu_to_le32(ACPI_EDGE_SENSITIVE | - ACPI_GTDT_ALWAYS_ON); + gtdt->non_secure_el1_flags = cpu_to_le32(ACPI_GTDT_INTERRUPT_MODE_EDGE | + ACPI_GTDT_CAP_ALWAYS_ON); gtdt->virtual_timer_interrupt = cpu_to_le32(ARCH_TIMER_VIRT_IRQ + 16); - gtdt->virtual_timer_flags = cpu_to_le32(ACPI_EDGE_SENSITIVE); + gtdt->virtual_timer_flags = cpu_to_le32(ACPI_GTDT_INTERRUPT_MODE_EDGE); gtdt->non_secure_el2_interrupt = cpu_to_le32(ARCH_TIMER_NS_EL2_IRQ + 16); - gtdt->non_secure_el2_flags = cpu_to_le32(ACPI_EDGE_SENSITIVE); + gtdt->non_secure_el2_flags = cpu_to_le32(ACPI_GTDT_INTERRUPT_MODE_EDGE); build_header(linker, table_data, (void *)(table_data->data + gtdt_start), "GTDT", diff --git a/include/hw/acpi/acpi-defs.h b/include/hw/acpi/acpi-defs.h index 510f23c931..8fe0996e15 100644 --- a/include/hw/acpi/acpi-defs.h +++ b/include/hw/acpi/acpi-defs.h @@ -430,21 +430,8 @@ typedef struct AcpiMadtGenericTranslator AcpiMadtGenericTranslator; /* * Generic Timer Description Table (GTDT) */ - -#define ACPI_GTDT_INTERRUPT_MODE (1 << 0) -#define ACPI_GTDT_INTERRUPT_POLARITY (1 << 1) -#define ACPI_GTDT_ALWAYS_ON (1 << 2) - -/* Triggering */ - -#define ACPI_LEVEL_SENSITIVE ((uint8_t) 0x00) -#define ACPI_EDGE_SENSITIVE ((uint8_t) 0x01) - -/* Polarity */ - -#define ACPI_ACTIVE_HIGH ((uint8_t) 0x00) -#define ACPI_ACTIVE_LOW ((uint8_t) 0x01) -#define ACPI_ACTIVE_BOTH ((uint8_t) 0x02) +#define ACPI_GTDT_INTERRUPT_MODE_EDGE (1 << 0) +#define ACPI_GTDT_CAP_ALWAYS_ON (1 << 2) struct AcpiGenericTimerTable { ACPI_TABLE_HEADER_DEF From 8c92c6a43e3d0aabe5bb81e5fb709d2791e9c4c4 Mon Sep 17 00:00:00 2001 From: Andrew Jones Date: Mon, 9 Jan 2017 11:40:21 +0000 Subject: [PATCH 09/21] hw/arm/virt-acpi-build: fadt: improve flag naming Signed-off-by: Andrew Jones Message-id: 20170102200153.28864-5-drjones@redhat.com Reviewed-by: Peter Maydell Signed-off-by: Peter Maydell --- hw/arm/virt-acpi-build.c | 4 ++-- include/hw/acpi/acpi-defs.h | 6 ++---- 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/hw/arm/virt-acpi-build.c b/hw/arm/virt-acpi-build.c index 420cd21644..ef0efb84e2 100644 --- a/hw/arm/virt-acpi-build.c +++ b/hw/arm/virt-acpi-build.c @@ -642,8 +642,8 @@ build_fadt(GArray *table_data, BIOSLinker *linker, unsigned dsdt_tbl_offset) /* Hardware Reduced = 1 and use PSCI 0.2+ and with HVC */ fadt->flags = cpu_to_le32(1 << ACPI_FADT_F_HW_REDUCED_ACPI); - fadt->arm_boot_flags = cpu_to_le16((1 << ACPI_FADT_ARM_USE_PSCI_G_0_2) | - (1 << ACPI_FADT_ARM_PSCI_USE_HVC)); + fadt->arm_boot_flags = cpu_to_le16(ACPI_FADT_ARM_PSCI_COMPLIANT | + ACPI_FADT_ARM_PSCI_USE_HVC); /* ACPI v5.1 (fadt->revision.fadt->minor_revision) */ fadt->minor_revision = 0x1; diff --git a/include/hw/acpi/acpi-defs.h b/include/hw/acpi/acpi-defs.h index 8fe0996e15..d15b7e5cd3 100644 --- a/include/hw/acpi/acpi-defs.h +++ b/include/hw/acpi/acpi-defs.h @@ -191,10 +191,8 @@ struct AcpiFadtDescriptorRev5_1 { typedef struct AcpiFadtDescriptorRev5_1 AcpiFadtDescriptorRev5_1; -enum { - ACPI_FADT_ARM_USE_PSCI_G_0_2 = 0, - ACPI_FADT_ARM_PSCI_USE_HVC = 1, -}; +#define ACPI_FADT_ARM_PSCI_COMPLIANT (1 << 0) +#define ACPI_FADT_ARM_PSCI_USE_HVC (1 << 1) /* * Serial Port Console Redirection Table (SPCR), Rev. 1.02 From 0127937b203a7fa87da34bf096faa23e7793cec6 Mon Sep 17 00:00:00 2001 From: Andrew Jones Date: Mon, 9 Jan 2017 11:40:22 +0000 Subject: [PATCH 10/21] hw/arm/virt: parameter passing cleanups Some simple cleanups made possible by "hw/arm/virt: Merge VirtBoardInfo and VirtMachineState" Signed-off-by: Andrew Jones Reviewed-by: Igor Mammedov Acked-by: Michael S. Tsirkin Message-id: 20170102200153.28864-6-drjones@redhat.com Signed-off-by: Peter Maydell --- hw/arm/virt.c | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/hw/arm/virt.c b/hw/arm/virt.c index 2ca9527ba4..a39fbd2dbe 100644 --- a/hw/arm/virt.c +++ b/hw/arm/virt.c @@ -553,10 +553,10 @@ static void create_v2m(VirtMachineState *vms, qemu_irq *pic) fdt_add_v2m_gic_node(vms); } -static void create_gic(VirtMachineState *vms, qemu_irq *pic, int type, - bool secure, bool no_its) +static void create_gic(VirtMachineState *vms, qemu_irq *pic, int type) { /* We create a standalone GIC */ + VirtMachineClass *vmc = VIRT_MACHINE_GET_CLASS(vms); DeviceState *gicdev; SysBusDevice *gicbusdev; const char *gictype; @@ -572,7 +572,7 @@ static void create_gic(VirtMachineState *vms, qemu_irq *pic, int type, */ qdev_prop_set_uint32(gicdev, "num-irq", NUM_IRQS + 32); if (!kvm_irqchip_in_kernel()) { - qdev_prop_set_bit(gicdev, "has-security-extensions", secure); + qdev_prop_set_bit(gicdev, "has-security-extensions", vms->secure); } qdev_init_nofail(gicdev); gicbusdev = SYS_BUS_DEVICE(gicdev); @@ -618,7 +618,7 @@ static void create_gic(VirtMachineState *vms, qemu_irq *pic, int type, fdt_add_gic_node(vms, type); - if (type == 3 && !no_its) { + if (type == 3 && !vmc->no_its) { create_its(vms, gicdev); } else if (type == 2) { create_v2m(vms, pic); @@ -980,8 +980,7 @@ static void create_pcie_irq_map(const VirtMachineState *vms, 0x7 /* PCI irq */); } -static void create_pcie(const VirtMachineState *vms, qemu_irq *pic, - bool use_highmem) +static void create_pcie(const VirtMachineState *vms, qemu_irq *pic) { hwaddr base_mmio = vms->memmap[VIRT_PCIE_MMIO].base; hwaddr size_mmio = vms->memmap[VIRT_PCIE_MMIO].size; @@ -1024,7 +1023,7 @@ static void create_pcie(const VirtMachineState *vms, qemu_irq *pic, mmio_reg, base_mmio, size_mmio); memory_region_add_subregion(get_system_memory(), base_mmio, mmio_alias); - if (use_highmem) { + if (vms->highmem) { /* Map high MMIO space */ MemoryRegion *high_mmio_alias = g_new0(MemoryRegion, 1); @@ -1073,7 +1072,7 @@ static void create_pcie(const VirtMachineState *vms, qemu_irq *pic, qemu_fdt_setprop_sized_cells(vms->fdt, nodename, "reg", 2, base_ecam, 2, size_ecam); - if (use_highmem) { + if (vms->highmem) { qemu_fdt_setprop_sized_cells(vms->fdt, nodename, "ranges", 1, FDT_PCI_RANGE_IOPORT, 2, 0, 2, base_pio, 2, size_pio, @@ -1384,7 +1383,7 @@ static void machvirt_init(MachineState *machine) create_flash(vms, sysmem, secure_sysmem ? secure_sysmem : sysmem); - create_gic(vms, pic, gic_version, vms->secure, vmc->no_its); + create_gic(vms, pic, gic_version); fdt_add_pmu_nodes(vms, gic_version); @@ -1397,7 +1396,7 @@ static void machvirt_init(MachineState *machine) create_rtc(vms, pic); - create_pcie(vms, pic, vms->highmem); + create_pcie(vms, pic); create_gpio(vms, pic); From 055a7f2b0aefdd6b75bf2866171c4fe11f9a9e00 Mon Sep 17 00:00:00 2001 From: Andrew Jones Date: Mon, 9 Jan 2017 11:40:22 +0000 Subject: [PATCH 11/21] hw/arm/virt: use VirtMachineState.gic_version machvirt_init may need to probe for the gic version. If so, then make sure the result is written to VirtMachineState. With the state up to date, use it instead of a local variable. This is a cleanup that prepares for VirtMachineState to be passed to functions even outside hw/arm/virt.c Signed-off-by: Andrew Jones Reviewed-by: Igor Mammedov Acked-by: Michael S. Tsirkin Message-id: 20170102200153.28864-7-drjones@redhat.com Signed-off-by: Peter Maydell --- hw/arm/virt.c | 35 +++++++++++++++++------------------ 1 file changed, 17 insertions(+), 18 deletions(-) diff --git a/hw/arm/virt.c b/hw/arm/virt.c index a39fbd2dbe..8ba50ad6c2 100644 --- a/hw/arm/virt.c +++ b/hw/arm/virt.c @@ -308,7 +308,7 @@ static void fdt_add_psci_node(const VirtMachineState *vms) qemu_fdt_setprop_cell(fdt, "/psci", "migrate", migrate_fn); } -static void fdt_add_timer_nodes(const VirtMachineState *vms, int gictype) +static void fdt_add_timer_nodes(const VirtMachineState *vms) { /* On real hardware these interrupts are level-triggered. * On KVM they were edge-triggered before host kernel version 4.4, @@ -336,7 +336,7 @@ static void fdt_add_timer_nodes(const VirtMachineState *vms, int gictype) irqflags = GIC_FDT_IRQ_FLAGS_EDGE_LO_HI; } - if (gictype == 2) { + if (vms->gic_version == 2) { irqflags = deposit32(irqflags, GIC_FDT_IRQ_PPI_CPU_START, GIC_FDT_IRQ_PPI_CPU_WIDTH, (1 << vms->smp_cpus) - 1); @@ -450,7 +450,7 @@ static void fdt_add_v2m_gic_node(VirtMachineState *vms) qemu_fdt_setprop_cell(vms->fdt, "/intc/v2m", "phandle", vms->msi_phandle); } -static void fdt_add_gic_node(VirtMachineState *vms, int type) +static void fdt_add_gic_node(VirtMachineState *vms) { vms->gic_phandle = qemu_fdt_alloc_phandle(vms->fdt); qemu_fdt_setprop_cell(vms->fdt, "/", "interrupt-parent", vms->gic_phandle); @@ -461,7 +461,7 @@ static void fdt_add_gic_node(VirtMachineState *vms, int type) qemu_fdt_setprop_cell(vms->fdt, "/intc", "#address-cells", 0x2); qemu_fdt_setprop_cell(vms->fdt, "/intc", "#size-cells", 0x2); qemu_fdt_setprop(vms->fdt, "/intc", "ranges", NULL, 0); - if (type == 3) { + if (vms->gic_version == 3) { qemu_fdt_setprop_string(vms->fdt, "/intc", "compatible", "arm,gic-v3"); qemu_fdt_setprop_sized_cells(vms->fdt, "/intc", "reg", @@ -483,7 +483,7 @@ static void fdt_add_gic_node(VirtMachineState *vms, int type) qemu_fdt_setprop_cell(vms->fdt, "/intc", "phandle", vms->gic_phandle); } -static void fdt_add_pmu_nodes(const VirtMachineState *vms, int gictype) +static void fdt_add_pmu_nodes(const VirtMachineState *vms) { CPUState *cpu; ARMCPU *armcpu; @@ -497,7 +497,7 @@ static void fdt_add_pmu_nodes(const VirtMachineState *vms, int gictype) } } - if (gictype == 2) { + if (vms->gic_version == 2) { irqflags = deposit32(irqflags, GIC_FDT_IRQ_PPI_CPU_START, GIC_FDT_IRQ_PPI_CPU_WIDTH, (1 << vms->smp_cpus) - 1); @@ -553,14 +553,14 @@ static void create_v2m(VirtMachineState *vms, qemu_irq *pic) fdt_add_v2m_gic_node(vms); } -static void create_gic(VirtMachineState *vms, qemu_irq *pic, int type) +static void create_gic(VirtMachineState *vms, qemu_irq *pic) { /* We create a standalone GIC */ VirtMachineClass *vmc = VIRT_MACHINE_GET_CLASS(vms); DeviceState *gicdev; SysBusDevice *gicbusdev; const char *gictype; - int i; + int type = vms->gic_version, i; gictype = (type == 3) ? gicv3_class_name() : gic_class_name(); @@ -616,7 +616,7 @@ static void create_gic(VirtMachineState *vms, qemu_irq *pic, int type) pic[i] = qdev_get_gpio_in(gicdev, i); } - fdt_add_gic_node(vms, type); + fdt_add_gic_node(vms); if (type == 3 && !vmc->no_its) { create_its(vms, gicdev); @@ -1212,7 +1212,6 @@ static void machvirt_init(MachineState *machine) qemu_irq pic[NUM_IRQS]; MemoryRegion *sysmem = get_system_memory(); MemoryRegion *secure_sysmem = NULL; - int gic_version = vms->gic_version; int n, virt_max_cpus; MemoryRegion *ram = g_new(MemoryRegion, 1); const char *cpu_model = machine->cpu_model; @@ -1233,14 +1232,14 @@ static void machvirt_init(MachineState *machine) /* We can probe only here because during property set * KVM is not available yet */ - if (!gic_version) { + if (!vms->gic_version) { if (!kvm_enabled()) { error_report("gic-version=host requires KVM"); exit(1); } - gic_version = kvm_arm_vgic_probe(); - if (!gic_version) { + vms->gic_version = kvm_arm_vgic_probe(); + if (!vms->gic_version) { error_report("Unable to determine GIC version supported by host"); exit(1); } @@ -1266,7 +1265,7 @@ static void machvirt_init(MachineState *machine) /* The maximum number of CPUs depends on the GIC version, or on how * many redistributors we can fit into the memory map. */ - if (gic_version == 3) { + if (vms->gic_version == 3) { virt_max_cpus = vms->memmap[VIRT_GIC_REDIST].size / 0x20000; clustersz = GICV3_TARGETLIST_BITS; } else { @@ -1373,7 +1372,7 @@ static void machvirt_init(MachineState *machine) object_property_set_bool(cpuobj, true, "realized", NULL); } - fdt_add_timer_nodes(vms, gic_version); + fdt_add_timer_nodes(vms); fdt_add_cpu_nodes(vms); fdt_add_psci_node(vms); @@ -1383,9 +1382,9 @@ static void machvirt_init(MachineState *machine) create_flash(vms, sysmem, secure_sysmem ? secure_sysmem : sysmem); - create_gic(vms, pic, gic_version); + create_gic(vms, pic); - fdt_add_pmu_nodes(vms, gic_version); + fdt_add_pmu_nodes(vms); create_uart(vms, pic, VIRT_UART, sysmem, serial_hds[0]); @@ -1414,7 +1413,7 @@ static void machvirt_init(MachineState *machine) guest_info->memmap = vms->memmap; guest_info->irqmap = vms->irqmap; guest_info->use_highmem = vms->highmem; - guest_info->gic_version = gic_version; + guest_info->gic_version = vms->gic_version; guest_info->no_its = vmc->no_its; guest_info_state->machine_done.notify = virt_guest_info_machine_done; qemu_add_machine_init_done_notifier(&guest_info_state->machine_done); From 054f4dc961490b81139304106e4312c356303a6f Mon Sep 17 00:00:00 2001 From: Andrew Jones Date: Mon, 9 Jan 2017 11:40:22 +0000 Subject: [PATCH 12/21] hw/arm/virt: eliminate struct VirtGuestInfoState Instead of allocating a new struct just for VirtGuestInfo and the machine_done Notifier, place them inside VirtMachineState. This is the mach-virt equivalent of "pc: Eliminate struct PcGuestInfoState" Suggested-by: Eduardo Habkost Signed-off-by: Andrew Jones Reviewed-by: Igor Mammedov Acked-by: Michael S. Tsirkin Message-id: 20170102200153.28864-8-drjones@redhat.com Reviewed-by: Peter Maydell Signed-off-by: Peter Maydell --- hw/arm/virt.c | 20 +++++++++++--------- include/hw/arm/virt-acpi-build.h | 6 ------ 2 files changed, 11 insertions(+), 15 deletions(-) diff --git a/hw/arm/virt.c b/hw/arm/virt.c index 8ba50ad6c2..9b55ef05a6 100644 --- a/hw/arm/virt.c +++ b/hw/arm/virt.c @@ -76,6 +76,8 @@ typedef struct { typedef struct { MachineState parent; + VirtGuestInfo acpi_guest_info; + Notifier machine_done; bool secure; bool highmem; int32_t gic_version; @@ -1197,12 +1199,13 @@ static void virt_build_smbios(VirtGuestInfo *guest_info) } static -void virt_guest_info_machine_done(Notifier *notifier, void *data) +void virt_machine_done(Notifier *notifier, void *data) { - VirtGuestInfoState *guest_info_state = container_of(notifier, - VirtGuestInfoState, machine_done); - virt_acpi_setup(&guest_info_state->info); - virt_build_smbios(&guest_info_state->info); + VirtMachineState *vms = container_of(notifier, VirtMachineState, + machine_done); + + virt_acpi_setup(&vms->acpi_guest_info); + virt_build_smbios(&vms->acpi_guest_info); } static void machvirt_init(MachineState *machine) @@ -1215,8 +1218,7 @@ static void machvirt_init(MachineState *machine) int n, virt_max_cpus; MemoryRegion *ram = g_new(MemoryRegion, 1); const char *cpu_model = machine->cpu_model; - VirtGuestInfoState *guest_info_state = g_malloc0(sizeof *guest_info_state); - VirtGuestInfo *guest_info = &guest_info_state->info; + VirtGuestInfo *guest_info = &vms->acpi_guest_info; char **cpustr; ObjectClass *oc; const char *typename; @@ -1415,8 +1417,8 @@ static void machvirt_init(MachineState *machine) guest_info->use_highmem = vms->highmem; guest_info->gic_version = vms->gic_version; guest_info->no_its = vmc->no_its; - guest_info_state->machine_done.notify = virt_guest_info_machine_done; - qemu_add_machine_init_done_notifier(&guest_info_state->machine_done); + vms->machine_done.notify = virt_machine_done; + qemu_add_machine_init_done_notifier(&vms->machine_done); vms->bootinfo.ram_size = machine->ram_size; vms->bootinfo.kernel_filename = machine->kernel_filename; diff --git a/include/hw/arm/virt-acpi-build.h b/include/hw/arm/virt-acpi-build.h index 2bcd22265c..925c434738 100644 --- a/include/hw/arm/virt-acpi-build.h +++ b/include/hw/arm/virt-acpi-build.h @@ -34,12 +34,6 @@ typedef struct VirtGuestInfo { bool no_its; } VirtGuestInfo; - -typedef struct VirtGuestInfoState { - VirtGuestInfo info; - Notifier machine_done; -} VirtGuestInfoState; - void virt_acpi_setup(VirtGuestInfo *guest_info); #endif From d05fdab46d9c5a33654de1bd54fca375347341ce Mon Sep 17 00:00:00 2001 From: Andrew Jones Date: Mon, 9 Jan 2017 11:40:22 +0000 Subject: [PATCH 13/21] hw/arm/virt: remove include/hw/arm/virt-acpi-build.h include/hw/arm/virt-acpi-build.h is only used for VirtGuestInfo, which doesn't even necessarily have to be ACPI specific. Move VirtGuestInfo to include/hw/arm/virt.h, allowing us to remove include/hw/arm/virt-acpi-build.h, and to prepare for even more code motion. Signed-off-by: Andrew Jones Reviewed-by: Igor Mammedov Acked-by: Michael S. Tsirkin Message-id: 20170102200153.28864-9-drjones@redhat.com Reviewed-by: Peter Maydell Signed-off-by: Peter Maydell --- MAINTAINERS | 2 -- hw/arm/virt-acpi-build.c | 2 +- hw/arm/virt.c | 1 - include/hw/arm/virt-acpi-build.h | 39 -------------------------------- include/hw/arm/virt.h | 14 +++++++++++- 5 files changed, 14 insertions(+), 44 deletions(-) delete mode 100644 include/hw/arm/virt-acpi-build.h diff --git a/MAINTAINERS b/MAINTAINERS index 585cd5abd7..ed884b2f19 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -508,7 +508,6 @@ M: Shannon Zhao L: qemu-arm@nongnu.org S: Maintained F: hw/arm/virt-acpi-build.c -F: include/hw/arm/virt-acpi-build.h STM32F205 M: Alistair Francis @@ -885,7 +884,6 @@ F: hw/acpi/* F: hw/smbios/* F: hw/i386/acpi-build.[hc] F: hw/arm/virt-acpi-build.c -F: include/hw/arm/virt-acpi-build.h ppc4xx M: Alexander Graf diff --git a/hw/arm/virt-acpi-build.c b/hw/arm/virt-acpi-build.c index ef0efb84e2..4fd52dac76 100644 --- a/hw/arm/virt-acpi-build.c +++ b/hw/arm/virt-acpi-build.c @@ -29,7 +29,6 @@ #include "qemu/osdep.h" #include "qapi/error.h" #include "qemu-common.h" -#include "hw/arm/virt-acpi-build.h" #include "qemu/bitmap.h" #include "trace.h" #include "qom/cpu.h" @@ -43,6 +42,7 @@ #include "hw/acpi/aml-build.h" #include "hw/pci/pcie_host.h" #include "hw/pci/pci.h" +#include "hw/arm/virt.h" #include "sysemu/numa.h" #include "kvm_arm.h" diff --git a/hw/arm/virt.c b/hw/arm/virt.c index 9b55ef05a6..1b88b5043d 100644 --- a/hw/arm/virt.c +++ b/hw/arm/virt.c @@ -48,7 +48,6 @@ #include "qemu/bitops.h" #include "qemu/error-report.h" #include "hw/pci-host/gpex.h" -#include "hw/arm/virt-acpi-build.h" #include "hw/arm/sysbus-fdt.h" #include "hw/platform-bus.h" #include "hw/arm/fdt.h" diff --git a/include/hw/arm/virt-acpi-build.h b/include/hw/arm/virt-acpi-build.h deleted file mode 100644 index 925c434738..0000000000 --- a/include/hw/arm/virt-acpi-build.h +++ /dev/null @@ -1,39 +0,0 @@ -/* - * - * Copyright (c) 2015 HUAWEI TECHNOLOGIES CO.,LTD. - * - * Author: Shannon Zhao - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2 or later, as published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along with - * this program. If not, see . - */ - -#ifndef QEMU_VIRT_ACPI_BUILD_H -#define QEMU_VIRT_ACPI_BUILD_H - -#include "qemu-common.h" -#include "hw/arm/virt.h" -#include "qemu/notify.h" - -typedef struct VirtGuestInfo { - int smp_cpus; - FWCfgState *fw_cfg; - const MemMapEntry *memmap; - const int *irqmap; - bool use_highmem; - int gic_version; - bool no_its; -} VirtGuestInfo; - -void virt_acpi_setup(VirtGuestInfo *guest_info); - -#endif diff --git a/include/hw/arm/virt.h b/include/hw/arm/virt.h index 9650193253..69f78474e0 100644 --- a/include/hw/arm/virt.h +++ b/include/hw/arm/virt.h @@ -32,6 +32,7 @@ #include "qemu-common.h" #include "exec/hwaddr.h" +#include "qemu/notify.h" #define NUM_GICV2M_SPIS 64 #define NUM_VIRTIO_TRANSPORTS 32 @@ -74,5 +75,16 @@ typedef struct MemMapEntry { hwaddr size; } MemMapEntry; +typedef struct VirtGuestInfo { + int smp_cpus; + FWCfgState *fw_cfg; + const MemMapEntry *memmap; + const int *irqmap; + bool use_highmem; + int gic_version; + bool no_its; +} VirtGuestInfo; -#endif +void virt_acpi_setup(VirtGuestInfo *guest_info); + +#endif /* QEMU_ARM_VIRT_H */ From a72d4363875ed086acedab657d34f6fc82a7d8aa Mon Sep 17 00:00:00 2001 From: Andrew Jones Date: Mon, 9 Jan 2017 11:40:22 +0000 Subject: [PATCH 14/21] hw/arm/virt: move VirtMachineState/Class to virt.h In preparation to share more Virt machine state than just guest-info with other mach-virt source files, move the State and Class structures to virt.h Signed-off-by: Andrew Jones Reviewed-by: Igor Mammedov Acked-by: Michael S. Tsirkin Message-id: 20170102200153.28864-10-drjones@redhat.com Reviewed-by: Peter Maydell Signed-off-by: Peter Maydell --- hw/arm/virt.c | 51 ++++++------------------------------------- include/hw/arm/virt.h | 37 +++++++++++++++++++++++++++++++ 2 files changed, 44 insertions(+), 44 deletions(-) diff --git a/hw/arm/virt.c b/hw/arm/virt.c index 1b88b5043d..8556ff27c3 100644 --- a/hw/arm/virt.c +++ b/hw/arm/virt.c @@ -41,7 +41,6 @@ #include "sysemu/numa.h" #include "sysemu/sysemu.h" #include "sysemu/kvm.h" -#include "hw/boards.h" #include "hw/compat.h" #include "hw/loader.h" #include "exec/address-spaces.h" @@ -58,49 +57,6 @@ #include "qapi/visitor.h" #include "standard-headers/linux/input.h" -/* Number of external interrupt lines to configure the GIC with */ -#define NUM_IRQS 256 - -#define PLATFORM_BUS_NUM_IRQS 64 - -static ARMPlatformBusSystemParams platform_bus_params; - -typedef struct { - MachineClass parent; - bool disallow_affinity_adjustment; - bool no_its; - bool no_pmu; - bool claim_edge_triggered_timers; -} VirtMachineClass; - -typedef struct { - MachineState parent; - VirtGuestInfo acpi_guest_info; - Notifier machine_done; - bool secure; - bool highmem; - int32_t gic_version; - struct arm_boot_info bootinfo; - const MemMapEntry *memmap; - const int *irqmap; - int smp_cpus; - void *fdt; - int fdt_size; - uint32_t clock_phandle; - uint32_t gic_phandle; - uint32_t msi_phandle; - bool using_psci; -} VirtMachineState; - -#define TYPE_VIRT_MACHINE MACHINE_TYPE_NAME("virt") -#define VIRT_MACHINE(obj) \ - OBJECT_CHECK(VirtMachineState, (obj), TYPE_VIRT_MACHINE) -#define VIRT_MACHINE_GET_CLASS(obj) \ - OBJECT_GET_CLASS(VirtMachineClass, obj, TYPE_VIRT_MACHINE) -#define VIRT_MACHINE_CLASS(klass) \ - OBJECT_CLASS_CHECK(VirtMachineClass, klass, TYPE_VIRT_MACHINE) - - #define DEFINE_VIRT_MACHINE_LATEST(major, minor, latest) \ static void virt_##major##_##minor##_class_init(ObjectClass *oc, \ void *data) \ @@ -130,6 +86,13 @@ typedef struct { DEFINE_VIRT_MACHINE_LATEST(major, minor, false) +/* Number of external interrupt lines to configure the GIC with */ +#define NUM_IRQS 256 + +#define PLATFORM_BUS_NUM_IRQS 64 + +static ARMPlatformBusSystemParams platform_bus_params; + /* RAM limit in GB. Since VIRT_MEM starts at the 1GB mark, this means * RAM can go up to the 256GB mark, leaving 256GB of the physical * address space unallocated and free for future use between 256G and 512G. diff --git a/include/hw/arm/virt.h b/include/hw/arm/virt.h index 69f78474e0..91dbd69def 100644 --- a/include/hw/arm/virt.h +++ b/include/hw/arm/virt.h @@ -33,6 +33,8 @@ #include "qemu-common.h" #include "exec/hwaddr.h" #include "qemu/notify.h" +#include "hw/boards.h" +#include "hw/arm/arm.h" #define NUM_GICV2M_SPIS 64 #define NUM_VIRTIO_TRANSPORTS 32 @@ -85,6 +87,41 @@ typedef struct VirtGuestInfo { bool no_its; } VirtGuestInfo; +typedef struct { + MachineClass parent; + bool disallow_affinity_adjustment; + bool no_its; + bool no_pmu; + bool claim_edge_triggered_timers; +} VirtMachineClass; + +typedef struct { + MachineState parent; + VirtGuestInfo acpi_guest_info; + Notifier machine_done; + bool secure; + bool highmem; + int32_t gic_version; + struct arm_boot_info bootinfo; + const MemMapEntry *memmap; + const int *irqmap; + int smp_cpus; + void *fdt; + int fdt_size; + uint32_t clock_phandle; + uint32_t gic_phandle; + uint32_t msi_phandle; + bool using_psci; +} VirtMachineState; + +#define TYPE_VIRT_MACHINE MACHINE_TYPE_NAME("virt") +#define VIRT_MACHINE(obj) \ + OBJECT_CHECK(VirtMachineState, (obj), TYPE_VIRT_MACHINE) +#define VIRT_MACHINE_GET_CLASS(obj) \ + OBJECT_GET_CLASS(VirtMachineClass, obj, TYPE_VIRT_MACHINE) +#define VIRT_MACHINE_CLASS(klass) \ + OBJECT_CLASS_CHECK(VirtMachineClass, klass, TYPE_VIRT_MACHINE) + void virt_acpi_setup(VirtGuestInfo *guest_info); #endif /* QEMU_ARM_VIRT_H */ From e9a8e474fbdedca787623f0c55f7b6e9cb97bdfc Mon Sep 17 00:00:00 2001 From: Andrew Jones Date: Mon, 9 Jan 2017 11:40:22 +0000 Subject: [PATCH 15/21] hw/arm/virt: pass VirtMachineState instead of VirtGuestInfo Only two functions take VirtGuestInfo parameters. Now that guest-info is part of VirtMachineState, and VirtMachineState is defined in the virt header, pass that instead. Signed-off-by: Andrew Jones Reviewed-by: Igor Mammedov Acked-by: Michael S. Tsirkin Message-id: 20170102200153.28864-11-drjones@redhat.com Reviewed-by: Peter Maydell Signed-off-by: Peter Maydell --- hw/arm/virt-acpi-build.c | 3 ++- hw/arm/virt.c | 8 ++++---- include/hw/arm/virt.h | 2 +- 3 files changed, 7 insertions(+), 6 deletions(-) diff --git a/hw/arm/virt-acpi-build.c b/hw/arm/virt-acpi-build.c index 4fd52dac76..ac507d6589 100644 --- a/hw/arm/virt-acpi-build.c +++ b/hw/arm/virt-acpi-build.c @@ -823,8 +823,9 @@ static const VMStateDescription vmstate_virt_acpi_build = { }, }; -void virt_acpi_setup(VirtGuestInfo *guest_info) +void virt_acpi_setup(VirtMachineState *vms) { + VirtGuestInfo *guest_info = &vms->acpi_guest_info; AcpiBuildTables tables; AcpiBuildState *build_state; diff --git a/hw/arm/virt.c b/hw/arm/virt.c index 8556ff27c3..2201517de0 100644 --- a/hw/arm/virt.c +++ b/hw/arm/virt.c @@ -1131,9 +1131,9 @@ static void *machvirt_dtb(const struct arm_boot_info *binfo, int *fdt_size) return board->fdt; } -static void virt_build_smbios(VirtGuestInfo *guest_info) +static void virt_build_smbios(VirtMachineState *vms) { - FWCfgState *fw_cfg = guest_info->fw_cfg; + FWCfgState *fw_cfg = vms->acpi_guest_info.fw_cfg; uint8_t *smbios_tables, *smbios_anchor; size_t smbios_tables_len, smbios_anchor_len; const char *product = "QEMU Virtual Machine"; @@ -1166,8 +1166,8 @@ void virt_machine_done(Notifier *notifier, void *data) VirtMachineState *vms = container_of(notifier, VirtMachineState, machine_done); - virt_acpi_setup(&vms->acpi_guest_info); - virt_build_smbios(&vms->acpi_guest_info); + virt_acpi_setup(vms); + virt_build_smbios(vms); } static void machvirt_init(MachineState *machine) diff --git a/include/hw/arm/virt.h b/include/hw/arm/virt.h index 91dbd69def..b1eed52d3b 100644 --- a/include/hw/arm/virt.h +++ b/include/hw/arm/virt.h @@ -122,6 +122,6 @@ typedef struct { #define VIRT_MACHINE_CLASS(klass) \ OBJECT_CLASS_CHECK(VirtMachineClass, klass, TYPE_VIRT_MACHINE) -void virt_acpi_setup(VirtGuestInfo *guest_info); +void virt_acpi_setup(VirtMachineState *vms); #endif /* QEMU_ARM_VIRT_H */ From da4f09a7dce6878b6fd27a0fb70d08701551df17 Mon Sep 17 00:00:00 2001 From: Andrew Jones Date: Mon, 9 Jan 2017 11:40:22 +0000 Subject: [PATCH 16/21] hw/arm/virt-acpi-build: remove redundant members from VirtGuestInfo Now that we pass VirtMachineState, and guest-info is just part of that state, we can remove all the redundant members and access the VirtMachineState directly. Signed-off-by: Andrew Jones Reviewed-by: Igor Mammedov Acked-by: Michael S. Tsirkin Message-id: 20170102200153.28864-12-drjones@redhat.com Signed-off-by: Peter Maydell --- hw/arm/virt-acpi-build.c | 72 +++++++++++++++++++++------------------- hw/arm/virt.c | 6 ---- include/hw/arm/virt.h | 6 ---- 3 files changed, 37 insertions(+), 47 deletions(-) diff --git a/hw/arm/virt-acpi-build.c b/hw/arm/virt-acpi-build.c index ac507d6589..a3848a9ed0 100644 --- a/hw/arm/virt-acpi-build.c +++ b/hw/arm/virt-acpi-build.c @@ -384,7 +384,7 @@ build_rsdp(GArray *rsdp_table, BIOSLinker *linker, unsigned rsdt_tbl_offset) } static void -build_iort(GArray *table_data, BIOSLinker *linker, VirtGuestInfo *guest_info) +build_iort(GArray *table_data, BIOSLinker *linker) { int iort_start = table_data->len; AcpiIortIdMapping *idmap; @@ -439,11 +439,11 @@ build_iort(GArray *table_data, BIOSLinker *linker, VirtGuestInfo *guest_info) } static void -build_spcr(GArray *table_data, BIOSLinker *linker, VirtGuestInfo *guest_info) +build_spcr(GArray *table_data, BIOSLinker *linker, VirtMachineState *vms) { AcpiSerialPortConsoleRedirection *spcr; - const MemMapEntry *uart_memmap = &guest_info->memmap[VIRT_UART]; - int irq = guest_info->irqmap[VIRT_UART] + ARM_SPI_BASE; + const MemMapEntry *uart_memmap = &vms->memmap[VIRT_UART]; + int irq = vms->irqmap[VIRT_UART] + ARM_SPI_BASE; spcr = acpi_data_push(table_data, sizeof(*spcr)); @@ -472,16 +472,16 @@ build_spcr(GArray *table_data, BIOSLinker *linker, VirtGuestInfo *guest_info) } static void -build_srat(GArray *table_data, BIOSLinker *linker, VirtGuestInfo *guest_info) +build_srat(GArray *table_data, BIOSLinker *linker, VirtMachineState *vms) { AcpiSystemResourceAffinityTable *srat; AcpiSratProcessorGiccAffinity *core; AcpiSratMemoryAffinity *numamem; int i, j, srat_start; uint64_t mem_base; - uint32_t *cpu_node = g_malloc0(guest_info->smp_cpus * sizeof(uint32_t)); + uint32_t *cpu_node = g_malloc0(vms->smp_cpus * sizeof(uint32_t)); - for (i = 0; i < guest_info->smp_cpus; i++) { + for (i = 0; i < vms->smp_cpus; i++) { j = numa_get_node_for_cpu(i); if (j < nb_numa_nodes) { cpu_node[i] = j; @@ -492,7 +492,7 @@ build_srat(GArray *table_data, BIOSLinker *linker, VirtGuestInfo *guest_info) srat = acpi_data_push(table_data, sizeof(*srat)); srat->reserved1 = cpu_to_le32(1); - for (i = 0; i < guest_info->smp_cpus; ++i) { + for (i = 0; i < vms->smp_cpus; ++i) { core = acpi_data_push(table_data, sizeof(*core)); core->type = ACPI_SRAT_PROCESSOR_GICC; core->length = sizeof(*core); @@ -502,7 +502,7 @@ build_srat(GArray *table_data, BIOSLinker *linker, VirtGuestInfo *guest_info) } g_free(cpu_node); - mem_base = guest_info->memmap[VIRT_MEM].base; + mem_base = vms->memmap[VIRT_MEM].base; for (i = 0; i < nb_numa_nodes; ++i) { numamem = acpi_data_push(table_data, sizeof(*numamem)); build_srat_memory(numamem, mem_base, numa_info[i].node_mem, i, @@ -515,10 +515,10 @@ build_srat(GArray *table_data, BIOSLinker *linker, VirtGuestInfo *guest_info) } static void -build_mcfg(GArray *table_data, BIOSLinker *linker, VirtGuestInfo *guest_info) +build_mcfg(GArray *table_data, BIOSLinker *linker, VirtMachineState *vms) { AcpiTableMcfg *mcfg; - const MemMapEntry *memmap = guest_info->memmap; + const MemMapEntry *memmap = vms->memmap; int len = sizeof(*mcfg) + sizeof(mcfg->allocation[0]); mcfg = acpi_data_push(table_data, len); @@ -562,11 +562,12 @@ build_gtdt(GArray *table_data, BIOSLinker *linker) /* MADT */ static void -build_madt(GArray *table_data, BIOSLinker *linker, VirtGuestInfo *guest_info) +build_madt(GArray *table_data, BIOSLinker *linker, VirtMachineState *vms) { + VirtMachineClass *vmc = VIRT_MACHINE_GET_CLASS(vms); int madt_start = table_data->len; - const MemMapEntry *memmap = guest_info->memmap; - const int *irqmap = guest_info->irqmap; + const MemMapEntry *memmap = vms->memmap; + const int *irqmap = vms->irqmap; AcpiMultipleApicTable *madt; AcpiMadtGenericDistributor *gicd; AcpiMadtGenericMsiFrame *gic_msi; @@ -578,16 +579,16 @@ build_madt(GArray *table_data, BIOSLinker *linker, VirtGuestInfo *guest_info) gicd->type = ACPI_APIC_GENERIC_DISTRIBUTOR; gicd->length = sizeof(*gicd); gicd->base_address = cpu_to_le64(memmap[VIRT_GIC_DIST].base); - gicd->version = guest_info->gic_version; + gicd->version = vms->gic_version; - for (i = 0; i < guest_info->smp_cpus; i++) { + for (i = 0; i < vms->smp_cpus; i++) { AcpiMadtGenericCpuInterface *gicc = acpi_data_push(table_data, sizeof(*gicc)); ARMCPU *armcpu = ARM_CPU(qemu_get_cpu(i)); gicc->type = ACPI_APIC_GENERIC_CPU_INTERFACE; gicc->length = sizeof(*gicc); - if (guest_info->gic_version == 2) { + if (vms->gic_version == 2) { gicc->base_address = cpu_to_le64(memmap[VIRT_GIC_CPU].base); } gicc->cpu_interface_number = cpu_to_le32(i); @@ -600,7 +601,7 @@ build_madt(GArray *table_data, BIOSLinker *linker, VirtGuestInfo *guest_info) } } - if (guest_info->gic_version == 3) { + if (vms->gic_version == 3) { AcpiMadtGenericTranslator *gic_its; AcpiMadtGenericRedistributor *gicr = acpi_data_push(table_data, sizeof *gicr); @@ -610,7 +611,7 @@ build_madt(GArray *table_data, BIOSLinker *linker, VirtGuestInfo *guest_info) gicr->base_address = cpu_to_le64(memmap[VIRT_GIC_REDIST].base); gicr->range_length = cpu_to_le32(memmap[VIRT_GIC_REDIST].size); - if (its_class_name() && !guest_info->no_its) { + if (its_class_name() && !vmc->no_its) { gic_its = acpi_data_push(table_data, sizeof *gic_its); gic_its->type = ACPI_APIC_GENERIC_TRANSLATOR; gic_its->length = sizeof(*gic_its); @@ -659,11 +660,11 @@ build_fadt(GArray *table_data, BIOSLinker *linker, unsigned dsdt_tbl_offset) /* DSDT */ static void -build_dsdt(GArray *table_data, BIOSLinker *linker, VirtGuestInfo *guest_info) +build_dsdt(GArray *table_data, BIOSLinker *linker, VirtMachineState *vms) { Aml *scope, *dsdt; - const MemMapEntry *memmap = guest_info->memmap; - const int *irqmap = guest_info->irqmap; + const MemMapEntry *memmap = vms->memmap; + const int *irqmap = vms->irqmap; dsdt = init_aml_allocator(); /* Reserve space for header */ @@ -675,7 +676,7 @@ build_dsdt(GArray *table_data, BIOSLinker *linker, VirtGuestInfo *guest_info) * the RTC ACPI device at all when using UEFI. */ scope = aml_scope("\\_SB"); - acpi_dsdt_add_cpus(scope, guest_info->smp_cpus); + acpi_dsdt_add_cpus(scope, vms->smp_cpus); acpi_dsdt_add_uart(scope, &memmap[VIRT_UART], (irqmap[VIRT_UART] + ARM_SPI_BASE)); acpi_dsdt_add_flash(scope, &memmap[VIRT_FLASH]); @@ -683,7 +684,7 @@ build_dsdt(GArray *table_data, BIOSLinker *linker, VirtGuestInfo *guest_info) acpi_dsdt_add_virtio(scope, &memmap[VIRT_MMIO], (irqmap[VIRT_MMIO] + ARM_SPI_BASE), NUM_VIRTIO_TRANSPORTS); acpi_dsdt_add_pci(scope, memmap, (irqmap[VIRT_PCIE] + ARM_SPI_BASE), - guest_info->use_highmem); + vms->highmem); acpi_dsdt_add_gpio(scope, &memmap[VIRT_GPIO], (irqmap[VIRT_GPIO] + ARM_SPI_BASE)); acpi_dsdt_add_power_button(scope); @@ -710,8 +711,9 @@ struct AcpiBuildState { } AcpiBuildState; static -void virt_acpi_build(VirtGuestInfo *guest_info, AcpiBuildTables *tables) +void virt_acpi_build(VirtMachineState *vms, AcpiBuildTables *tables) { + VirtMachineClass *vmc = VIRT_MACHINE_GET_CLASS(vms); GArray *table_offsets; unsigned dsdt, rsdt; GArray *tables_blob = tables->table_data; @@ -725,32 +727,32 @@ void virt_acpi_build(VirtGuestInfo *guest_info, AcpiBuildTables *tables) /* DSDT is pointed to by FADT */ dsdt = tables_blob->len; - build_dsdt(tables_blob, tables->linker, guest_info); + build_dsdt(tables_blob, tables->linker, vms); /* FADT MADT GTDT MCFG SPCR pointed to by RSDT */ acpi_add_table(table_offsets, tables_blob); build_fadt(tables_blob, tables->linker, dsdt); acpi_add_table(table_offsets, tables_blob); - build_madt(tables_blob, tables->linker, guest_info); + build_madt(tables_blob, tables->linker, vms); acpi_add_table(table_offsets, tables_blob); build_gtdt(tables_blob, tables->linker); acpi_add_table(table_offsets, tables_blob); - build_mcfg(tables_blob, tables->linker, guest_info); + build_mcfg(tables_blob, tables->linker, vms); acpi_add_table(table_offsets, tables_blob); - build_spcr(tables_blob, tables->linker, guest_info); + build_spcr(tables_blob, tables->linker, vms); if (nb_numa_nodes > 0) { acpi_add_table(table_offsets, tables_blob); - build_srat(tables_blob, tables->linker, guest_info); + build_srat(tables_blob, tables->linker, vms); } - if (its_class_name() && !guest_info->no_its) { + if (its_class_name() && !vmc->no_its) { acpi_add_table(table_offsets, tables_blob); - build_iort(tables_blob, tables->linker, guest_info); + build_iort(tables_blob, tables->linker); } /* RSDT is pointed to by RSDP */ @@ -789,13 +791,13 @@ static void virt_acpi_build_update(void *build_opaque) acpi_build_tables_init(&tables); - virt_acpi_build(build_state->guest_info, &tables); + virt_acpi_build(container_of(build_state->guest_info, + VirtMachineState, acpi_guest_info), &tables); acpi_ram_update(build_state->table_mr, tables.table_data); acpi_ram_update(build_state->rsdp_mr, tables.rsdp); acpi_ram_update(build_state->linker_mr, tables.linker->cmd_blob); - acpi_build_tables_cleanup(&tables, true); } @@ -843,7 +845,7 @@ void virt_acpi_setup(VirtMachineState *vms) build_state->guest_info = guest_info; acpi_build_tables_init(&tables); - virt_acpi_build(build_state->guest_info, &tables); + virt_acpi_build(vms, &tables); /* Now expose it all to Guest */ build_state->table_mr = acpi_add_rom_blob(build_state, tables.table_data, diff --git a/hw/arm/virt.c b/hw/arm/virt.c index 2201517de0..6832b8befc 100644 --- a/hw/arm/virt.c +++ b/hw/arm/virt.c @@ -1372,13 +1372,7 @@ static void machvirt_init(MachineState *machine) create_fw_cfg(vms, &address_space_memory); rom_set_fw(fw_cfg_find()); - guest_info->smp_cpus = smp_cpus; guest_info->fw_cfg = fw_cfg_find(); - guest_info->memmap = vms->memmap; - guest_info->irqmap = vms->irqmap; - guest_info->use_highmem = vms->highmem; - guest_info->gic_version = vms->gic_version; - guest_info->no_its = vmc->no_its; vms->machine_done.notify = virt_machine_done; qemu_add_machine_init_done_notifier(&vms->machine_done); diff --git a/include/hw/arm/virt.h b/include/hw/arm/virt.h index b1eed52d3b..d200542d0d 100644 --- a/include/hw/arm/virt.h +++ b/include/hw/arm/virt.h @@ -78,13 +78,7 @@ typedef struct MemMapEntry { } MemMapEntry; typedef struct VirtGuestInfo { - int smp_cpus; FWCfgState *fw_cfg; - const MemMapEntry *memmap; - const int *irqmap; - bool use_highmem; - int gic_version; - bool no_its; } VirtGuestInfo; typedef struct { From 4dad9e7478ec9614f7c1cbe2ff5c5f5101acd6e2 Mon Sep 17 00:00:00 2001 From: Andrew Jones Date: Mon, 9 Jan 2017 11:40:22 +0000 Subject: [PATCH 17/21] hw/arm/virt-acpi-build: don't save VirtGuestInfo on AcpiBuildState We can get to VirtMachineState without the need for saving a pointer on AcpiBuildState. This is the mach-virt equivalent to "acpi: Don't save PcGuestInfo on AcpiBuildState" Signed-off-by: Andrew Jones Acked-by: Michael S. Tsirkin Message-id: 20170102200153.28864-13-drjones@redhat.com Reviewed-by: Peter Maydell Signed-off-by: Peter Maydell --- hw/arm/virt-acpi-build.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/hw/arm/virt-acpi-build.c b/hw/arm/virt-acpi-build.c index a3848a9ed0..3791b81d40 100644 --- a/hw/arm/virt-acpi-build.c +++ b/hw/arm/virt-acpi-build.c @@ -707,7 +707,6 @@ struct AcpiBuildState { MemoryRegion *linker_mr; /* Is table patched? */ bool patched; - VirtGuestInfo *guest_info; } AcpiBuildState; static @@ -791,8 +790,7 @@ static void virt_acpi_build_update(void *build_opaque) acpi_build_tables_init(&tables); - virt_acpi_build(container_of(build_state->guest_info, - VirtMachineState, acpi_guest_info), &tables); + virt_acpi_build(VIRT_MACHINE(qdev_get_machine()), &tables); acpi_ram_update(build_state->table_mr, tables.table_data); acpi_ram_update(build_state->rsdp_mr, tables.rsdp); @@ -842,7 +840,6 @@ void virt_acpi_setup(VirtMachineState *vms) } build_state = g_malloc0(sizeof *build_state); - build_state->guest_info = guest_info; acpi_build_tables_init(&tables); virt_acpi_build(vms, &tables); From af1f60a4022664b0169f9d10a3f7d732e8571617 Mon Sep 17 00:00:00 2001 From: Andrew Jones Date: Mon, 9 Jan 2017 11:40:23 +0000 Subject: [PATCH 18/21] hw/arm/virt: remove VirtGuestInfo by moving VirtGuestInfo.fw_cfg to VirtMachineState. This is the mach-virt equivalent of "pc: Move PcGuestInfo.fw_cfg to PCMachineState" and "pc: Eliminate PcGuestInfo struct" combined. Signed-off-by: Andrew Jones Acked-by: Michael S. Tsirkin Message-id: 20170102200153.28864-14-drjones@redhat.com Reviewed-by: Peter Maydell Signed-off-by: Peter Maydell --- hw/arm/virt-acpi-build.c | 7 +++---- hw/arm/virt.c | 16 +++++++--------- include/hw/arm/virt.h | 6 +----- 3 files changed, 11 insertions(+), 18 deletions(-) diff --git a/hw/arm/virt-acpi-build.c b/hw/arm/virt-acpi-build.c index 3791b81d40..44b5234636 100644 --- a/hw/arm/virt-acpi-build.c +++ b/hw/arm/virt-acpi-build.c @@ -825,11 +825,10 @@ static const VMStateDescription vmstate_virt_acpi_build = { void virt_acpi_setup(VirtMachineState *vms) { - VirtGuestInfo *guest_info = &vms->acpi_guest_info; AcpiBuildTables tables; AcpiBuildState *build_state; - if (!guest_info->fw_cfg) { + if (!vms->fw_cfg) { trace_virt_acpi_setup(); return; } @@ -854,8 +853,8 @@ void virt_acpi_setup(VirtMachineState *vms) acpi_add_rom_blob(build_state, tables.linker->cmd_blob, "etc/table-loader", 0); - fw_cfg_add_file(guest_info->fw_cfg, ACPI_BUILD_TPMLOG_FILE, - tables.tcpalog->data, acpi_data_len(tables.tcpalog)); + fw_cfg_add_file(vms->fw_cfg, ACPI_BUILD_TPMLOG_FILE, tables.tcpalog->data, + acpi_data_len(tables.tcpalog)); build_state->rsdp_mr = acpi_add_rom_blob(build_state, tables.rsdp, ACPI_BUILD_RSDP_FILE, 0); diff --git a/hw/arm/virt.c b/hw/arm/virt.c index 6832b8befc..7a03f84051 100644 --- a/hw/arm/virt.c +++ b/hw/arm/virt.c @@ -889,7 +889,7 @@ static void create_flash(const VirtMachineState *vms, } } -static void create_fw_cfg(const VirtMachineState *vms, AddressSpace *as) +static FWCfgState *create_fw_cfg(const VirtMachineState *vms, AddressSpace *as) { hwaddr base = vms->memmap[VIRT_FW_CFG].base; hwaddr size = vms->memmap[VIRT_FW_CFG].size; @@ -906,6 +906,7 @@ static void create_fw_cfg(const VirtMachineState *vms, AddressSpace *as) qemu_fdt_setprop_sized_cells(vms->fdt, nodename, "reg", 2, base, 2, size); g_free(nodename); + return fw_cfg; } static void create_pcie_irq_map(const VirtMachineState *vms, @@ -1133,12 +1134,11 @@ static void *machvirt_dtb(const struct arm_boot_info *binfo, int *fdt_size) static void virt_build_smbios(VirtMachineState *vms) { - FWCfgState *fw_cfg = vms->acpi_guest_info.fw_cfg; uint8_t *smbios_tables, *smbios_anchor; size_t smbios_tables_len, smbios_anchor_len; const char *product = "QEMU Virtual Machine"; - if (!fw_cfg) { + if (!vms->fw_cfg) { return; } @@ -1153,9 +1153,9 @@ static void virt_build_smbios(VirtMachineState *vms) &smbios_anchor, &smbios_anchor_len); if (smbios_anchor) { - fw_cfg_add_file(fw_cfg, "etc/smbios/smbios-tables", + fw_cfg_add_file(vms->fw_cfg, "etc/smbios/smbios-tables", smbios_tables, smbios_tables_len); - fw_cfg_add_file(fw_cfg, "etc/smbios/smbios-anchor", + fw_cfg_add_file(vms->fw_cfg, "etc/smbios/smbios-anchor", smbios_anchor, smbios_anchor_len); } } @@ -1180,7 +1180,6 @@ static void machvirt_init(MachineState *machine) int n, virt_max_cpus; MemoryRegion *ram = g_new(MemoryRegion, 1); const char *cpu_model = machine->cpu_model; - VirtGuestInfo *guest_info = &vms->acpi_guest_info; char **cpustr; ObjectClass *oc; const char *typename; @@ -1369,10 +1368,9 @@ static void machvirt_init(MachineState *machine) */ create_virtio_devices(vms, pic); - create_fw_cfg(vms, &address_space_memory); - rom_set_fw(fw_cfg_find()); + vms->fw_cfg = create_fw_cfg(vms, &address_space_memory); + rom_set_fw(vms->fw_cfg); - guest_info->fw_cfg = fw_cfg_find(); vms->machine_done.notify = virt_machine_done; qemu_add_machine_init_done_notifier(&vms->machine_done); diff --git a/include/hw/arm/virt.h b/include/hw/arm/virt.h index d200542d0d..eb1c63d688 100644 --- a/include/hw/arm/virt.h +++ b/include/hw/arm/virt.h @@ -77,10 +77,6 @@ typedef struct MemMapEntry { hwaddr size; } MemMapEntry; -typedef struct VirtGuestInfo { - FWCfgState *fw_cfg; -} VirtGuestInfo; - typedef struct { MachineClass parent; bool disallow_affinity_adjustment; @@ -91,8 +87,8 @@ typedef struct { typedef struct { MachineState parent; - VirtGuestInfo acpi_guest_info; Notifier machine_done; + FWCfgState *fw_cfg; bool secure; bool highmem; int32_t gic_version; From 8dd845d3c434cf2c799e0f86a1b53b33057b61ab Mon Sep 17 00:00:00 2001 From: Andrew Jones Date: Mon, 9 Jan 2017 11:40:23 +0000 Subject: [PATCH 19/21] hw/arm/virt-acpi-build: Don't incorrectly claim architectural timer to be edge-triggered This is the ACPI equivalent to "hw/arm/virt: Don't incorrectly claim architectural timer to be edge-triggered" which fixes the DT for machine types 2.9 and later. Signed-off-by: Andrew Jones Acked-by: Michael S. Tsirkin Message-id: 20170102200153.28864-15-drjones@redhat.com Reviewed-by: Peter Maydell Signed-off-by: Peter Maydell --- hw/arm/virt-acpi-build.c | 20 ++++++++++++++------ include/hw/acpi/acpi-defs.h | 1 + 2 files changed, 15 insertions(+), 6 deletions(-) diff --git a/hw/arm/virt-acpi-build.c b/hw/arm/virt-acpi-build.c index 44b5234636..085a611173 100644 --- a/hw/arm/virt-acpi-build.c +++ b/hw/arm/virt-acpi-build.c @@ -535,25 +535,33 @@ build_mcfg(GArray *table_data, BIOSLinker *linker, VirtMachineState *vms) /* GTDT */ static void -build_gtdt(GArray *table_data, BIOSLinker *linker) +build_gtdt(GArray *table_data, BIOSLinker *linker, VirtMachineState *vms) { + VirtMachineClass *vmc = VIRT_MACHINE_GET_CLASS(vms); int gtdt_start = table_data->len; AcpiGenericTimerTable *gtdt; + uint32_t irqflags; + + if (vmc->claim_edge_triggered_timers) { + irqflags = ACPI_GTDT_INTERRUPT_MODE_EDGE; + } else { + irqflags = ACPI_GTDT_INTERRUPT_MODE_LEVEL; + } gtdt = acpi_data_push(table_data, sizeof *gtdt); /* The interrupt values are the same with the device tree when adding 16 */ gtdt->secure_el1_interrupt = cpu_to_le32(ARCH_TIMER_S_EL1_IRQ + 16); - gtdt->secure_el1_flags = cpu_to_le32(ACPI_GTDT_INTERRUPT_MODE_EDGE); + gtdt->secure_el1_flags = cpu_to_le32(irqflags); gtdt->non_secure_el1_interrupt = cpu_to_le32(ARCH_TIMER_NS_EL1_IRQ + 16); - gtdt->non_secure_el1_flags = cpu_to_le32(ACPI_GTDT_INTERRUPT_MODE_EDGE | + gtdt->non_secure_el1_flags = cpu_to_le32(irqflags | ACPI_GTDT_CAP_ALWAYS_ON); gtdt->virtual_timer_interrupt = cpu_to_le32(ARCH_TIMER_VIRT_IRQ + 16); - gtdt->virtual_timer_flags = cpu_to_le32(ACPI_GTDT_INTERRUPT_MODE_EDGE); + gtdt->virtual_timer_flags = cpu_to_le32(irqflags); gtdt->non_secure_el2_interrupt = cpu_to_le32(ARCH_TIMER_NS_EL2_IRQ + 16); - gtdt->non_secure_el2_flags = cpu_to_le32(ACPI_GTDT_INTERRUPT_MODE_EDGE); + gtdt->non_secure_el2_flags = cpu_to_le32(irqflags); build_header(linker, table_data, (void *)(table_data->data + gtdt_start), "GTDT", @@ -736,7 +744,7 @@ void virt_acpi_build(VirtMachineState *vms, AcpiBuildTables *tables) build_madt(tables_blob, tables->linker, vms); acpi_add_table(table_offsets, tables_blob); - build_gtdt(tables_blob, tables->linker); + build_gtdt(tables_blob, tables->linker, vms); acpi_add_table(table_offsets, tables_blob); build_mcfg(tables_blob, tables->linker, vms); diff --git a/include/hw/acpi/acpi-defs.h b/include/hw/acpi/acpi-defs.h index d15b7e5cd3..d43ec005cb 100644 --- a/include/hw/acpi/acpi-defs.h +++ b/include/hw/acpi/acpi-defs.h @@ -428,6 +428,7 @@ typedef struct AcpiMadtGenericTranslator AcpiMadtGenericTranslator; /* * Generic Timer Description Table (GTDT) */ +#define ACPI_GTDT_INTERRUPT_MODE_LEVEL (0 << 0) #define ACPI_GTDT_INTERRUPT_MODE_EDGE (1 << 0) #define ACPI_GTDT_CAP_ALWAYS_ON (1 << 2) From 24cb2e0d57cea0cbc163f23fa47d530b35425a21 Mon Sep 17 00:00:00 2001 From: Jean-Christophe Dubois Date: Mon, 9 Jan 2017 11:40:23 +0000 Subject: [PATCH 20/21] m25p80: don't let rogue SPI controllers cause buffer overruns In normal operation we should never attempt to put more data into the data[] array than it can hold. However if the SPI controller connected to us misbehaves then it can send us a sequence of commands that attempt this. Since the controller might be in the guest (if the hardware does SPI via bit-banging), catch the possible overrun conditions and reset the flash internal state, logging them as guest errors. Signed-off-by: Jean-Christophe Dubois Message-id: 20170107111631.24444-1-jcd@tribudubois.net Reviewed-by: Peter Maydell [PMM: rewrote commit message to be more exact about when this can happen] Signed-off-by: Peter Maydell --- hw/block/m25p80.c | 29 +++++++++++++++++++++++++++-- 1 file changed, 27 insertions(+), 2 deletions(-) diff --git a/hw/block/m25p80.c b/hw/block/m25p80.c index e3c1166ea6..4c5f8c3590 100644 --- a/hw/block/m25p80.c +++ b/hw/block/m25p80.c @@ -28,6 +28,7 @@ #include "hw/ssi/ssi.h" #include "qemu/bitops.h" #include "qemu/log.h" +#include "qemu/error-report.h" #include "qapi/error.h" #ifndef M25P80_ERR_DEBUG @@ -377,6 +378,8 @@ typedef enum { MAN_GENERIC, } Manufacturer; +#define M25P80_INTERNAL_DATA_BUFFER_SZ 16 + typedef struct Flash { SSISlave parent_obj; @@ -387,7 +390,7 @@ typedef struct Flash { int page_size; uint8_t state; - uint8_t data[16]; + uint8_t data[M25P80_INTERNAL_DATA_BUFFER_SZ]; uint32_t len; uint32_t pos; uint8_t needed_bytes; @@ -1115,6 +1118,17 @@ static uint32_t m25p80_transfer8(SSISlave *ss, uint32_t tx) case STATE_COLLECTING_DATA: case STATE_COLLECTING_VAR_LEN_DATA: + + if (s->len >= M25P80_INTERNAL_DATA_BUFFER_SZ) { + qemu_log_mask(LOG_GUEST_ERROR, + "M25P80: Write overrun internal data buffer. " + "SPI controller (QEMU emulator or guest driver) " + "is misbehaving\n"); + s->len = s->pos = 0; + s->state = STATE_IDLE; + break; + } + s->data[s->len] = (uint8_t)tx; s->len++; @@ -1124,6 +1138,17 @@ static uint32_t m25p80_transfer8(SSISlave *ss, uint32_t tx) break; case STATE_READING_DATA: + + if (s->pos >= M25P80_INTERNAL_DATA_BUFFER_SZ) { + qemu_log_mask(LOG_GUEST_ERROR, + "M25P80: Read overrun internal data buffer. " + "SPI controller (QEMU emulator or guest driver) " + "is misbehaving\n"); + s->len = s->pos = 0; + s->state = STATE_IDLE; + break; + } + r = s->data[s->pos]; s->pos++; if (s->pos == s->len) { @@ -1196,7 +1221,7 @@ static const VMStateDescription vmstate_m25p80 = { .pre_save = m25p80_pre_save, .fields = (VMStateField[]) { VMSTATE_UINT8(state, Flash), - VMSTATE_UINT8_ARRAY(data, Flash, 16), + VMSTATE_UINT8_ARRAY(data, Flash, M25P80_INTERNAL_DATA_BUFFER_SZ), VMSTATE_UINT32(len, Flash), VMSTATE_UINT32(pos, Flash), VMSTATE_UINT8(needed_bytes, Flash), From 556899fc1965d82f5c4a3ba6a0be3b1193e2c4b2 Mon Sep 17 00:00:00 2001 From: Jean-Christophe Dubois Date: Mon, 9 Jan 2017 11:40:23 +0000 Subject: [PATCH 21/21] hw/ssi/imx_spi.c: Remove MSGDATA register support From the documentation it is not clear what this SPI register is about. Moreover, neither linux driver nor xvisor driver are using this SPI register. For now we just remove it and issue a log on register write access. Signed-off-by: Jean-Christophe Dubois Message-id: 20170107122047.26300-1-jcd@tribudubois.net Reviewed-by: Peter Maydell Signed-off-by: Peter Maydell --- hw/ssi/imx_spi.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/hw/ssi/imx_spi.c b/hw/ssi/imx_spi.c index e4e395fa67..b66505ca49 100644 --- a/hw/ssi/imx_spi.c +++ b/hw/ssi/imx_spi.c @@ -320,9 +320,6 @@ static void imx_spi_write(void *opaque, hwaddr offset, uint64_t value, TYPE_IMX_SPI, __func__); break; case ECSPI_TXDATA: - case ECSPI_MSGDATA: - /* Is there any difference between TXDATA and MSGDATA ? */ - /* I'll have to look in the linux driver */ if (!imx_spi_is_enabled(s)) { /* Ignore writes if device is disabled */ break; @@ -380,6 +377,14 @@ static void imx_spi_write(void *opaque, hwaddr offset, uint64_t value, } break; + case ECSPI_MSGDATA: + /* it is not clear from the spec what MSGDATA is for */ + /* Anyway it is not used by Linux driver */ + /* So for now we just ignore it */ + qemu_log_mask(LOG_UNIMP, + "[%s]%s: Trying to write to MSGDATA, ignoring\n", + TYPE_IMX_SPI, __func__); + break; default: s->regs[index] = value;