From 1b930bfa098ebad8abfc5ceff5d943133e7513f4 Mon Sep 17 00:00:00 2001 From: Jan Kiszka Date: Sat, 6 Aug 2011 14:23:29 +0200 Subject: [PATCH 01/24] slirp: Fix bit field types in IP header structs -mms-bitfields prevents that the bitfields in current IP header structs are packed into a single byte as it is required. Fix this by using uint8_t as backing type. Signed-off-by: Jan Kiszka --- slirp/ip.h | 8 ++++---- slirp/tcp.h | 4 ++-- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/slirp/ip.h b/slirp/ip.h index 48ea38e5e..72dbe9a5d 100644 --- a/slirp/ip.h +++ b/slirp/ip.h @@ -74,10 +74,10 @@ typedef uint32_t n_long; /* long as received from the net */ */ struct ip { #ifdef HOST_WORDS_BIGENDIAN - u_int ip_v:4, /* version */ + uint8_t ip_v:4, /* version */ ip_hl:4; /* header length */ #else - u_int ip_hl:4, /* header length */ + uint8_t ip_hl:4, /* header length */ ip_v:4; /* version */ #endif uint8_t ip_tos; /* type of service */ @@ -140,10 +140,10 @@ struct ip_timestamp { uint8_t ipt_len; /* size of structure (variable) */ uint8_t ipt_ptr; /* index of current entry */ #ifdef HOST_WORDS_BIGENDIAN - u_int ipt_oflw:4, /* overflow counter */ + uint8_t ipt_oflw:4, /* overflow counter */ ipt_flg:4; /* flags, see below */ #else - u_int ipt_flg:4, /* flags, see below */ + uint8_t ipt_flg:4, /* flags, see below */ ipt_oflw:4; /* overflow counter */ #endif union ipt_timestamp { diff --git a/slirp/tcp.h b/slirp/tcp.h index 9d0683662..b3817cb13 100644 --- a/slirp/tcp.h +++ b/slirp/tcp.h @@ -51,10 +51,10 @@ struct tcphdr { tcp_seq th_seq; /* sequence number */ tcp_seq th_ack; /* acknowledgement number */ #ifdef HOST_WORDS_BIGENDIAN - u_int th_off:4, /* data offset */ + uint8_t th_off:4, /* data offset */ th_x2:4; /* (unused) */ #else - u_int th_x2:4, /* (unused) */ + uint8_t th_x2:4, /* (unused) */ th_off:4; /* data offset */ #endif uint8_t th_flags; From 4fbf55568bb53a27a8c6270f1d3e2f6daf05c705 Mon Sep 17 00:00:00 2001 From: Peter Maydell Date: Fri, 22 Jul 2011 13:19:33 +0000 Subject: [PATCH 02/24] hw/pl110: Model the PL111 CLCD controller Model the PL111 CLCD controller. This is a minor variation on the PL110; the major programmer visible differences are support for hardware cursor (unimplemented) and two new pixel formats. Since syborg_fb.c borrows the pl11x pixel drawing routines, we also update it to cope with the new slightly larger array of function pointers. Signed-off-by: Peter Maydell --- hw/pl110.c | 94 ++++++++++++++++++++++++++++++++-------- hw/pl110_template.h | 102 +++++++++++++++++++++++++++++++++++++++++--- hw/syborg_fb.c | 17 ++++++-- 3 files changed, 184 insertions(+), 29 deletions(-) diff --git a/hw/pl110.c b/hw/pl110.c index 62aba17ad..384eba219 100644 --- a/hw/pl110.c +++ b/hw/pl110.c @@ -24,15 +24,25 @@ enum pl110_bppmode BPP_4, BPP_8, BPP_16, - BPP_32 + BPP_32, + BPP_16_565, /* PL111 only */ + BPP_12 /* PL111 only */ +}; + + +/* The Versatile/PB uses a slightly modified PL110 controller. */ +enum pl110_version +{ + PL110, + PL110_VERSATILE, + PL111 }; typedef struct { SysBusDevice busdev; DisplayState *ds; - /* The Versatile/PB uses a slightly modified PL110 controller. */ - int versatile; + int version; uint32_t timing[4]; uint32_t cr; uint32_t upbase; @@ -53,7 +63,7 @@ static const VMStateDescription vmstate_pl110 = { .version_id = 1, .minimum_version_id = 1, .fields = (VMStateField[]) { - VMSTATE_INT32(versatile, pl110_state), + VMSTATE_INT32(version, pl110_state), VMSTATE_UINT32_ARRAY(timing, pl110_state, 4), VMSTATE_UINT32(cr, pl110_state), VMSTATE_UINT32(upbase, pl110_state), @@ -82,6 +92,17 @@ static const unsigned char pl110_versatile_id[] = #define pl110_versatile_id pl110_id #endif +static const unsigned char pl111_id[] = { + 0x11, 0x11, 0x24, 0x00, 0x0d, 0xf0, 0x05, 0xb1 +}; + +/* Indexed by pl110_version */ +static const unsigned char *idregs[] = { + pl110_id, + pl110_versatile_id, + pl111_id +}; + #include "pixel_ops.h" #define BITS 8 @@ -144,12 +165,30 @@ static void pl110_update_display(void *opaque) if (s->cr & PL110_CR_BGR) bpp_offset = 0; else - bpp_offset = 18; + bpp_offset = 24; + + if ((s->version != PL111) && (s->bpp == BPP_16)) { + /* The PL110's native 16 bit mode is 5551; however + * most boards with a PL110 implement an external + * mux which allows bits to be reshuffled to give + * 565 format. The mux is typically controlled by + * an external system register. + * This should be controlled by a GPIO input pin + * so boards can wire it up to their register. + * For now, force 16 bit to be 565, to match + * previous QEMU PL110 model behaviour. + * + * The PL111 straightforwardly implements both + * 5551 and 565 under control of the bpp field + * in the LCDControl register. + */ + bpp_offset += (BPP_16_565 - BPP_16); + } if (s->cr & PL110_CR_BEBO) - fn = fntable[s->bpp + 6 + bpp_offset]; + fn = fntable[s->bpp + 8 + bpp_offset]; else if (s->cr & PL110_CR_BEPO) - fn = fntable[s->bpp + 12 + bpp_offset]; + fn = fntable[s->bpp + 16 + bpp_offset]; else fn = fntable[s->bpp + bpp_offset]; @@ -167,6 +206,8 @@ static void pl110_update_display(void *opaque) case BPP_8: break; case BPP_16: + case BPP_16_565: + case BPP_12: src_width <<= 1; break; case BPP_32: @@ -253,10 +294,7 @@ static uint32_t pl110_read(void *opaque, target_phys_addr_t offset) pl110_state *s = (pl110_state *)opaque; if (offset >= 0xfe0 && offset < 0x1000) { - if (s->versatile) - return pl110_versatile_id[(offset - 0xfe0) >> 2]; - else - return pl110_id[(offset - 0xfe0) >> 2]; + return idregs[s->version][(offset - 0xfe0) >> 2]; } if (offset >= 0x200 && offset < 0x400) { return s->raw_pallette[(offset - 0x200) >> 2]; @@ -275,12 +313,14 @@ static uint32_t pl110_read(void *opaque, target_phys_addr_t offset) case 5: /* LCDLPBASE */ return s->lpbase; case 6: /* LCDIMSC */ - if (s->versatile) - return s->cr; + if (s->version != PL110) { + return s->cr; + } return s->int_mask; case 7: /* LCDControl */ - if (s->versatile) - return s->int_mask; + if (s->version != PL110) { + return s->int_mask; + } return s->cr; case 8: /* LCDRIS */ return s->int_status; @@ -337,15 +377,17 @@ static void pl110_write(void *opaque, target_phys_addr_t offset, s->lpbase = val; break; case 6: /* LCDIMSC */ - if (s->versatile) + if (s->version != PL110) { goto control; + } imsc: s->int_mask = val; pl110_update(s); break; case 7: /* LCDControl */ - if (s->versatile) + if (s->version != PL110) { goto imsc; + } control: s->cr = val; s->bpp = (val >> 1) & 7; @@ -393,7 +435,14 @@ static int pl110_init(SysBusDevice *dev) static int pl110_versatile_init(SysBusDevice *dev) { pl110_state *s = FROM_SYSBUS(pl110_state, dev); - s->versatile = 1; + s->version = PL110_VERSATILE; + return pl110_init(dev); +} + +static int pl111_init(SysBusDevice *dev) +{ + pl110_state *s = FROM_SYSBUS(pl110_state, dev); + s->version = PL111; return pl110_init(dev); } @@ -413,10 +462,19 @@ static SysBusDeviceInfo pl110_versatile_info = { .qdev.no_user = 1, }; +static SysBusDeviceInfo pl111_info = { + .init = pl111_init, + .qdev.name = "pl111", + .qdev.size = sizeof(pl110_state), + .qdev.vmsd = &vmstate_pl110, + .qdev.no_user = 1, +}; + static void pl110_register_devices(void) { sysbus_register_withprop(&pl110_info); sysbus_register_withprop(&pl110_versatile_info); + sysbus_register_withprop(&pl111_info); } device_init(pl110_register_devices) diff --git a/hw/pl110_template.h b/hw/pl110_template.h index d30333678..1dce32a0c 100644 --- a/hw/pl110_template.h +++ b/hw/pl110_template.h @@ -43,49 +43,61 @@ #include "pl110_template.h" #undef BORDER -static drawfn glue(pl110_draw_fn_,BITS)[36] = +static drawfn glue(pl110_draw_fn_,BITS)[48] = { glue(pl110_draw_line1_lblp_bgr,BITS), glue(pl110_draw_line2_lblp_bgr,BITS), glue(pl110_draw_line4_lblp_bgr,BITS), glue(pl110_draw_line8_lblp_bgr,BITS), - glue(pl110_draw_line16_lblp_bgr,BITS), + glue(pl110_draw_line16_555_lblp_bgr,BITS), glue(pl110_draw_line32_lblp_bgr,BITS), + glue(pl110_draw_line16_lblp_bgr,BITS), + glue(pl110_draw_line12_lblp_bgr,BITS), glue(pl110_draw_line1_bbbp_bgr,BITS), glue(pl110_draw_line2_bbbp_bgr,BITS), glue(pl110_draw_line4_bbbp_bgr,BITS), glue(pl110_draw_line8_bbbp_bgr,BITS), - glue(pl110_draw_line16_bbbp_bgr,BITS), + glue(pl110_draw_line16_555_bbbp_bgr,BITS), glue(pl110_draw_line32_bbbp_bgr,BITS), + glue(pl110_draw_line16_bbbp_bgr,BITS), + glue(pl110_draw_line12_bbbp_bgr,BITS), glue(pl110_draw_line1_lbbp_bgr,BITS), glue(pl110_draw_line2_lbbp_bgr,BITS), glue(pl110_draw_line4_lbbp_bgr,BITS), glue(pl110_draw_line8_lbbp_bgr,BITS), - glue(pl110_draw_line16_lbbp_bgr,BITS), + glue(pl110_draw_line16_555_lbbp_bgr,BITS), glue(pl110_draw_line32_lbbp_bgr,BITS), + glue(pl110_draw_line16_lbbp_bgr,BITS), + glue(pl110_draw_line12_lbbp_bgr,BITS), glue(pl110_draw_line1_lblp_rgb,BITS), glue(pl110_draw_line2_lblp_rgb,BITS), glue(pl110_draw_line4_lblp_rgb,BITS), glue(pl110_draw_line8_lblp_rgb,BITS), - glue(pl110_draw_line16_lblp_rgb,BITS), + glue(pl110_draw_line16_555_lblp_rgb,BITS), glue(pl110_draw_line32_lblp_rgb,BITS), + glue(pl110_draw_line16_lblp_rgb,BITS), + glue(pl110_draw_line12_lblp_rgb,BITS), glue(pl110_draw_line1_bbbp_rgb,BITS), glue(pl110_draw_line2_bbbp_rgb,BITS), glue(pl110_draw_line4_bbbp_rgb,BITS), glue(pl110_draw_line8_bbbp_rgb,BITS), - glue(pl110_draw_line16_bbbp_rgb,BITS), + glue(pl110_draw_line16_555_bbbp_rgb,BITS), glue(pl110_draw_line32_bbbp_rgb,BITS), + glue(pl110_draw_line16_bbbp_rgb,BITS), + glue(pl110_draw_line12_bbbp_rgb,BITS), glue(pl110_draw_line1_lbbp_rgb,BITS), glue(pl110_draw_line2_lbbp_rgb,BITS), glue(pl110_draw_line4_lbbp_rgb,BITS), glue(pl110_draw_line8_lbbp_rgb,BITS), - glue(pl110_draw_line16_lbbp_rgb,BITS), + glue(pl110_draw_line16_555_lbbp_rgb,BITS), glue(pl110_draw_line32_lbbp_rgb,BITS), + glue(pl110_draw_line16_lbbp_rgb,BITS), + glue(pl110_draw_line12_lbbp_rgb,BITS), }; #undef BITS @@ -299,6 +311,82 @@ static void glue(pl110_draw_line32_,NAME)(void *opaque, uint8_t *d, const uint8_ } } +static void glue(pl110_draw_line16_555_,NAME)(void *opaque, uint8_t *d, const uint8_t *src, int width, int deststep) +{ + /* RGB 555 plus an intensity bit (which we ignore) */ + uint32_t data; + unsigned int r, g, b; + while (width > 0) { + data = *(uint32_t *)src; +#ifdef SWAP_WORDS + data = bswap32(data); +#endif +#ifdef RGB +#define LSB r +#define MSB b +#else +#define LSB b +#define MSB r +#endif + LSB = (data & 0x1f) << 3; + data >>= 5; + g = (data & 0x1f) << 3; + data >>= 5; + MSB = (data & 0x1f) << 3; + data >>= 5; + COPY_PIXEL(d, glue(rgb_to_pixel,BITS)(r, g, b)); + LSB = (data & 0x1f) << 3; + data >>= 5; + g = (data & 0x1f) << 3; + data >>= 5; + MSB = (data & 0x1f) << 3; + data >>= 6; + COPY_PIXEL(d, glue(rgb_to_pixel,BITS)(r, g, b)); +#undef MSB +#undef LSB + width -= 2; + src += 4; + } +} + +static void glue(pl110_draw_line12_,NAME)(void *opaque, uint8_t *d, const uint8_t *src, int width, int deststep) +{ + /* RGB 444 with 4 bits of zeroes at the top of each halfword */ + uint32_t data; + unsigned int r, g, b; + while (width > 0) { + data = *(uint32_t *)src; +#ifdef SWAP_WORDS + data = bswap32(data); +#endif +#ifdef RGB +#define LSB r +#define MSB b +#else +#define LSB b +#define MSB r +#endif + LSB = (data & 0xf) << 4; + data >>= 4; + g = (data & 0xf) << 4; + data >>= 4; + MSB = (data & 0xf) << 4; + data >>= 8; + COPY_PIXEL(d, glue(rgb_to_pixel,BITS)(r, g, b)); + LSB = (data & 0xf) << 4; + data >>= 4; + g = (data & 0xf) << 4; + data >>= 4; + MSB = (data & 0xf) << 4; + data >>= 8; + COPY_PIXEL(d, glue(rgb_to_pixel,BITS)(r, g, b)); +#undef MSB +#undef LSB + width -= 2; + src += 4; + } +} + #undef SWAP_PIXELS #undef NAME #undef SWAP_WORDS diff --git a/hw/syborg_fb.c b/hw/syborg_fb.c index 7e3736454..ae3e0ebc6 100644 --- a/hw/syborg_fb.c +++ b/hw/syborg_fb.c @@ -217,15 +217,24 @@ static void syborg_fb_update_display(void *opaque) } if (s->rgb) { - bpp_offset = 18; + bpp_offset = 24; } else { bpp_offset = 0; } if (s->endian) { - bpp_offset += 6; + bpp_offset += 8; } - - fn = fntable[s->bpp + bpp_offset]; + /* Our bpp constants mostly match the PL110/PL111 but + * not for the 16 bit case + */ + switch (s->bpp) { + case BPP_SRC_16: + bpp_offset += 6; + break; + default: + bpp_offset += s->bpp; + } + fn = fntable[bpp_offset]; if (s->pitch) { src_width = s->pitch; From 242ea2c6bc96473d37894b258a28a2162208228c Mon Sep 17 00:00:00 2001 From: Peter Maydell Date: Fri, 22 Jul 2011 13:42:39 +0000 Subject: [PATCH 03/24] versatilepb: Implement SYS_CLCD mux control register bits On the Versatile PB, PL110 graphics adaptor only natively supports 5551 pixel format; an external mux swaps bits around to allow RGB565 and BGR565, under the control of bits [1:0] in the SYS_CLCD system register. Implement these SYS_CLCD register bits, and use a gpio line to feed them out of the system register model, across the versatilepb board and into the pl110 so we can select the right format. This is necessary as recent Linux versatile kernels default to programming the CLCD and mux for 16 bit BGR rather than 16 bit RGB. Signed-off-by: Peter Maydell --- hw/arm_sysctl.c | 49 +++++++++++++++++++++++++++++++++++++++++++++--- hw/pl110.c | 29 +++++++++++++++++++++++----- hw/versatilepb.c | 13 ++++++++++--- 3 files changed, 80 insertions(+), 11 deletions(-) diff --git a/hw/arm_sysctl.c b/hw/arm_sysctl.c index fd0c8bc3d..22c62dfeb 100644 --- a/hw/arm_sysctl.c +++ b/hw/arm_sysctl.c @@ -17,6 +17,8 @@ typedef struct { SysBusDevice busdev; + qemu_irq pl110_mux_ctrl; + uint32_t sys_id; uint32_t leds; uint16_t lockval; @@ -30,11 +32,12 @@ typedef struct { uint32_t sys_cfgdata; uint32_t sys_cfgctrl; uint32_t sys_cfgstat; + uint32_t sys_clcd; } arm_sysctl_state; static const VMStateDescription vmstate_arm_sysctl = { .name = "realview_sysctl", - .version_id = 2, + .version_id = 3, .minimum_version_id = 1, .fields = (VMStateField[]) { VMSTATE_UINT32(leds, arm_sysctl_state), @@ -48,6 +51,7 @@ static const VMStateDescription vmstate_arm_sysctl = { VMSTATE_UINT32_V(sys_cfgdata, arm_sysctl_state, 2), VMSTATE_UINT32_V(sys_cfgctrl, arm_sysctl_state, 2), VMSTATE_UINT32_V(sys_cfgstat, arm_sysctl_state, 2), + VMSTATE_UINT32_V(sys_clcd, arm_sysctl_state, 3), VMSTATE_END_OF_LIST() } }; @@ -78,6 +82,13 @@ static void arm_sysctl_reset(DeviceState *d) s->cfgdata2 = 0; s->flags = 0; s->resetlevel = 0; + if (board_id(s) == BOARD_ID_VEXPRESS) { + /* On VExpress this register will RAZ/WI */ + s->sys_clcd = 0; + } else { + /* All others: CLCDID 0x1f, indicating VGA */ + s->sys_clcd = 0x1f00; + } } static uint32_t arm_sysctl_read(void *opaque, target_phys_addr_t offset) @@ -124,7 +135,7 @@ static uint32_t arm_sysctl_read(void *opaque, target_phys_addr_t offset) case 0x4c: /* FLASH */ return 0; case 0x50: /* CLCD */ - return 0x1000; + return s->sys_clcd; case 0x54: /* CLCDSER */ return 0; case 0x58: /* BOOTCS */ @@ -232,7 +243,39 @@ static void arm_sysctl_write(void *opaque, target_phys_addr_t offset, /* nothing to do. */ break; case 0x4c: /* FLASH */ + break; case 0x50: /* CLCD */ + switch (board_id(s)) { + case BOARD_ID_PB926: + /* On 926 bits 13:8 are R/O, bits 1:0 control + * the mux that defines how to interpret the PL110 + * graphics format, and other bits are r/w but we + * don't implement them to do anything. + */ + s->sys_clcd &= 0x3f00; + s->sys_clcd |= val & ~0x3f00; + qemu_set_irq(s->pl110_mux_ctrl, val & 3); + break; + case BOARD_ID_EB: + /* The EB is the same except that there is no mux since + * the EB has a PL111. + */ + s->sys_clcd &= 0x3f00; + s->sys_clcd |= val & ~0x3f00; + break; + case BOARD_ID_PBA8: + case BOARD_ID_PBX: + /* On PBA8 and PBX bit 7 is r/w and all other bits + * are either r/o or RAZ/WI. + */ + s->sys_clcd &= (1 << 7); + s->sys_clcd |= val & ~(1 << 7); + break; + case BOARD_ID_VEXPRESS: + default: + /* On VExpress this register is unimplemented and will RAZ/WI */ + break; + } case 0x54: /* CLCDSER */ case 0x64: /* DMAPSR0 */ case 0x68: /* DMAPSR1 */ @@ -334,7 +377,7 @@ static int arm_sysctl_init1(SysBusDevice *dev) DEVICE_NATIVE_ENDIAN); sysbus_init_mmio(dev, 0x1000, iomemtype); qdev_init_gpio_in(&s->busdev.qdev, arm_sysctl_gpio_set, 2); - /* ??? Save/restore. */ + qdev_init_gpio_out(&s->busdev.qdev, &s->pl110_mux_ctrl, 1); return 0; } diff --git a/hw/pl110.c b/hw/pl110.c index 384eba219..4ac710a6e 100644 --- a/hw/pl110.c +++ b/hw/pl110.c @@ -53,6 +53,7 @@ typedef struct { int rows; enum pl110_bppmode bpp; int invalidate; + uint32_t mux_ctrl; uint32_t pallette[256]; uint32_t raw_pallette[128]; qemu_irq irq; @@ -60,7 +61,7 @@ typedef struct { static const VMStateDescription vmstate_pl110 = { .name = "pl110", - .version_id = 1, + .version_id = 2, .minimum_version_id = 1, .fields = (VMStateField[]) { VMSTATE_INT32(version, pl110_state), @@ -76,6 +77,7 @@ static const VMStateDescription vmstate_pl110 = { VMSTATE_INT32(invalidate, pl110_state), VMSTATE_UINT32_ARRAY(pallette, pl110_state, 256), VMSTATE_UINT32_ARRAY(raw_pallette, pl110_state, 128), + VMSTATE_UINT32_V(mux_ctrl, pl110_state, 2), VMSTATE_END_OF_LIST() } }; @@ -173,16 +175,26 @@ static void pl110_update_display(void *opaque) * mux which allows bits to be reshuffled to give * 565 format. The mux is typically controlled by * an external system register. - * This should be controlled by a GPIO input pin + * This is controlled by a GPIO input pin * so boards can wire it up to their register. - * For now, force 16 bit to be 565, to match - * previous QEMU PL110 model behaviour. * * The PL111 straightforwardly implements both * 5551 and 565 under control of the bpp field * in the LCDControl register. */ - bpp_offset += (BPP_16_565 - BPP_16); + switch (s->mux_ctrl) { + case 3: /* 565 BGR */ + bpp_offset = (BPP_16_565 - BPP_16); + break; + case 1: /* 5551 */ + break; + case 0: /* 888; also if we have loaded vmstate from an old version */ + case 2: /* 565 RGB */ + default: + /* treat as 565 but honour BGR bit */ + bpp_offset += (BPP_16_565 - BPP_16); + break; + } } if (s->cr & PL110_CR_BEBO) @@ -416,6 +428,12 @@ static CPUWriteMemoryFunc * const pl110_writefn[] = { pl110_write }; +static void pl110_mux_ctrl_set(void *opaque, int line, int level) +{ + pl110_state *s = (pl110_state *)opaque; + s->mux_ctrl = level; +} + static int pl110_init(SysBusDevice *dev) { pl110_state *s = FROM_SYSBUS(pl110_state, dev); @@ -426,6 +444,7 @@ static int pl110_init(SysBusDevice *dev) DEVICE_NATIVE_ENDIAN); sysbus_init_mmio(dev, 0x1000, iomemtype); sysbus_init_irq(dev, &s->irq); + qdev_init_gpio_in(&s->busdev.qdev, pl110_mux_ctrl_set, 1); s->ds = graphic_console_init(pl110_update_display, pl110_invalidate_display, NULL, NULL, s); diff --git a/hw/versatilepb.c b/hw/versatilepb.c index 147fe29b6..49f8f5fc5 100644 --- a/hw/versatilepb.c +++ b/hw/versatilepb.c @@ -180,7 +180,7 @@ static void versatile_init(ram_addr_t ram_size, qemu_irq *cpu_pic; qemu_irq pic[32]; qemu_irq sic[32]; - DeviceState *dev; + DeviceState *dev, *sysctl; PCIBus *pci_bus; NICInfo *nd; int n; @@ -198,7 +198,12 @@ static void versatile_init(ram_addr_t ram_size, /* SDRAM at address zero. */ cpu_register_physical_memory(0, ram_size, ram_offset | IO_MEM_RAM); - arm_sysctl_init(0x10000000, 0x41007004, 0x02000000); + sysctl = qdev_create(NULL, "realview_sysctl"); + qdev_prop_set_uint32(sysctl, "sys_id", 0x41007004); + qdev_init_nofail(sysctl); + qdev_prop_set_uint32(sysctl, "proc_id", 0x02000000); + sysbus_mmio_map(sysbus_from_qdev(sysctl), 0, 0x10000000); + cpu_pic = arm_pic_init_cpu(env); dev = sysbus_create_varargs("pl190", 0x10140000, cpu_pic[0], cpu_pic[1], NULL); @@ -250,7 +255,9 @@ static void versatile_init(ram_addr_t ram_size, /* The versatile/PB actually has a modified Color LCD controller that includes hardware cursor support from the PL111. */ - sysbus_create_simple("pl110_versatile", 0x10120000, pic[16]); + dev = sysbus_create_simple("pl110_versatile", 0x10120000, pic[16]); + /* Wire up the mux control signals from the SYS_CLCD register */ + qdev_connect_gpio_out(sysctl, 0, qdev_get_gpio_in(dev, 0)); sysbus_create_varargs("pl181", 0x10005000, sic[22], sic[1], NULL); sysbus_create_varargs("pl181", 0x1000b000, sic[23], sic[2], NULL); From acb9b72240543307e061db5986532db402807e3c Mon Sep 17 00:00:00 2001 From: Peter Maydell Date: Fri, 22 Jul 2011 15:36:54 +0000 Subject: [PATCH 04/24] vexpress, realview: Use pl111, not pl110 The Versatile Express, Realview EB, PBX A9 and PB A8 boards all use a PL111 for their graphics, not a PL110. Now we model the PL111, use it on these board models. Signed-off-by: Peter Maydell --- hw/realview.c | 2 +- hw/vexpress.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/hw/realview.c b/hw/realview.c index 94ab90051..549bb150c 100644 --- a/hw/realview.c +++ b/hw/realview.c @@ -251,7 +251,7 @@ static void realview_init(ram_addr_t ram_size, sysbus_create_simple("pl061", 0x10014000, pic[7]); gpio2 = sysbus_create_simple("pl061", 0x10015000, pic[8]); - sysbus_create_simple("pl110_versatile", 0x10020000, pic[23]); + sysbus_create_simple("pl111", 0x10020000, pic[23]); dev = sysbus_create_varargs("pl181", 0x10005000, pic[17], pic[18], NULL); /* Wire up MMC card detect and read-only signals. These have diff --git a/hw/vexpress.c b/hw/vexpress.c index 9ffd332de..c9766dd0c 100644 --- a/hw/vexpress.c +++ b/hw/vexpress.c @@ -150,7 +150,7 @@ static void vexpress_a9_init(ram_addr_t ram_size, /* Daughterboard peripherals : 0x10020000 .. 0x20000000 */ /* 0x10020000 PL111 CLCD (daughterboard) */ - sysbus_create_simple("pl110", 0x10020000, pic[44]); + sysbus_create_simple("pl111", 0x10020000, pic[44]); /* 0x10060000 AXI RAM */ /* 0x100e0000 PL341 Dynamic Memory Controller */ From a35faa94c8e8d851a1d07e17c98f4ab2202b8a38 Mon Sep 17 00:00:00 2001 From: Peter Maydell Date: Wed, 3 Aug 2011 23:13:45 +0100 Subject: [PATCH 05/24] hw/pl061: Convert to VMState Convert the PL061 to VMState. We choose to widen the struct members to uint32_t rather than the other two options of breaking migration compatibility or using vmstate hacks to read/write a 32 bit value into an 8 bit struct field. Signed-off-by: Peter Maydell --- hw/pl061.c | 174 ++++++++++++++++++++++++----------------------------- 1 file changed, 79 insertions(+), 95 deletions(-) diff --git a/hw/pl061.c b/hw/pl061.c index 79e5c53e8..27de824ba 100644 --- a/hw/pl061.c +++ b/hw/pl061.c @@ -30,31 +30,60 @@ static const uint8_t pl061_id_luminary[12] = typedef struct { SysBusDevice busdev; - int locked; - uint8_t data; - uint8_t old_data; - uint8_t dir; - uint8_t isense; - uint8_t ibe; - uint8_t iev; - uint8_t im; - uint8_t istate; - uint8_t afsel; - uint8_t dr2r; - uint8_t dr4r; - uint8_t dr8r; - uint8_t odr; - uint8_t pur; - uint8_t pdr; - uint8_t slr; - uint8_t den; - uint8_t cr; - uint8_t float_high; + uint32_t locked; + uint32_t data; + uint32_t old_data; + uint32_t dir; + uint32_t isense; + uint32_t ibe; + uint32_t iev; + uint32_t im; + uint32_t istate; + uint32_t afsel; + uint32_t dr2r; + uint32_t dr4r; + uint32_t dr8r; + uint32_t odr; + uint32_t pur; + uint32_t pdr; + uint32_t slr; + uint32_t den; + uint32_t cr; + uint32_t float_high; qemu_irq irq; qemu_irq out[8]; const unsigned char *id; } pl061_state; +static const VMStateDescription vmstate_pl061 = { + .name = "pl061", + .version_id = 1, + .minimum_version_id = 1, + .fields = (VMStateField[]) { + VMSTATE_UINT32(locked, pl061_state), + VMSTATE_UINT32(data, pl061_state), + VMSTATE_UINT32(old_data, pl061_state), + VMSTATE_UINT32(dir, pl061_state), + VMSTATE_UINT32(isense, pl061_state), + VMSTATE_UINT32(ibe, pl061_state), + VMSTATE_UINT32(iev, pl061_state), + VMSTATE_UINT32(im, pl061_state), + VMSTATE_UINT32(istate, pl061_state), + VMSTATE_UINT32(afsel, pl061_state), + VMSTATE_UINT32(dr2r, pl061_state), + VMSTATE_UINT32(dr4r, pl061_state), + VMSTATE_UINT32(dr8r, pl061_state), + VMSTATE_UINT32(odr, pl061_state), + VMSTATE_UINT32(pur, pl061_state), + VMSTATE_UINT32(pdr, pl061_state), + VMSTATE_UINT32(slr, pl061_state), + VMSTATE_UINT32(den, pl061_state), + VMSTATE_UINT32(cr, pl061_state), + VMSTATE_UINT32(float_high, pl061_state), + VMSTATE_END_OF_LIST() + } +}; + static void pl061_update(pl061_state *s) { uint8_t changed; @@ -148,19 +177,19 @@ static void pl061_write(void *opaque, target_phys_addr_t offset, } switch (offset) { case 0x400: /* Direction */ - s->dir = value; + s->dir = value & 0xff; break; case 0x404: /* Interrupt sense */ - s->isense = value; + s->isense = value & 0xff; break; case 0x408: /* Interrupt both edges */ - s->ibe = value; + s->ibe = value & 0xff; break; case 0x40c: /* Interrupt event */ - s->iev = value; + s->iev = value & 0xff; break; case 0x410: /* Interrupt mask */ - s->im = value; + s->im = value & 0xff; break; case 0x41c: /* Interrupt clear */ s->istate &= ~value; @@ -170,35 +199,35 @@ static void pl061_write(void *opaque, target_phys_addr_t offset, s->afsel = (s->afsel & ~mask) | (value & mask); break; case 0x500: /* 2mA drive */ - s->dr2r = value; + s->dr2r = value & 0xff; break; case 0x504: /* 4mA drive */ - s->dr4r = value; + s->dr4r = value & 0xff; break; case 0x508: /* 8mA drive */ - s->dr8r = value; + s->dr8r = value & 0xff; break; case 0x50c: /* Open drain */ - s->odr = value; + s->odr = value & 0xff; break; case 0x510: /* Pull-up */ - s->pur = value; + s->pur = value & 0xff; break; case 0x514: /* Pull-down */ - s->pdr = value; + s->pdr = value & 0xff; break; case 0x518: /* Slew rate control */ - s->slr = value; + s->slr = value & 0xff; break; case 0x51c: /* Digital enable */ - s->den = value; + s->den = value & 0xff; break; case 0x520: /* Lock */ s->locked = (value != 0xacce551); break; case 0x524: /* Commit */ if (!s->locked) - s->cr = value; + s->cr = value & 0xff; break; default: hw_error("pl061_write: Bad offset %x\n", (int)offset); @@ -238,62 +267,6 @@ static CPUWriteMemoryFunc * const pl061_writefn[] = { pl061_write }; -static void pl061_save(QEMUFile *f, void *opaque) -{ - pl061_state *s = (pl061_state *)opaque; - - qemu_put_be32(f, s->locked); - qemu_put_be32(f, s->data); - qemu_put_be32(f, s->old_data); - qemu_put_be32(f, s->dir); - qemu_put_be32(f, s->isense); - qemu_put_be32(f, s->ibe); - qemu_put_be32(f, s->iev); - qemu_put_be32(f, s->im); - qemu_put_be32(f, s->istate); - qemu_put_be32(f, s->afsel); - qemu_put_be32(f, s->dr2r); - qemu_put_be32(f, s->dr4r); - qemu_put_be32(f, s->dr8r); - qemu_put_be32(f, s->odr); - qemu_put_be32(f, s->pur); - qemu_put_be32(f, s->pdr); - qemu_put_be32(f, s->slr); - qemu_put_be32(f, s->den); - qemu_put_be32(f, s->cr); - qemu_put_be32(f, s->float_high); -} - -static int pl061_load(QEMUFile *f, void *opaque, int version_id) -{ - pl061_state *s = (pl061_state *)opaque; - if (version_id != 1) - return -EINVAL; - - s->locked = qemu_get_be32(f); - s->data = qemu_get_be32(f); - s->old_data = qemu_get_be32(f); - s->dir = qemu_get_be32(f); - s->isense = qemu_get_be32(f); - s->ibe = qemu_get_be32(f); - s->iev = qemu_get_be32(f); - s->im = qemu_get_be32(f); - s->istate = qemu_get_be32(f); - s->afsel = qemu_get_be32(f); - s->dr2r = qemu_get_be32(f); - s->dr4r = qemu_get_be32(f); - s->dr8r = qemu_get_be32(f); - s->odr = qemu_get_be32(f); - s->pur = qemu_get_be32(f); - s->pdr = qemu_get_be32(f); - s->slr = qemu_get_be32(f); - s->den = qemu_get_be32(f); - s->cr = qemu_get_be32(f); - s->float_high = qemu_get_be32(f); - - return 0; -} - static int pl061_init(SysBusDevice *dev, const unsigned char *id) { int iomemtype; @@ -307,7 +280,6 @@ static int pl061_init(SysBusDevice *dev, const unsigned char *id) qdev_init_gpio_in(&dev->qdev, pl061_set_irq, 8); qdev_init_gpio_out(&dev->qdev, s->out, 8); pl061_reset(s); - register_savevm(&dev->qdev, "pl061_gpio", -1, 1, pl061_save, pl061_load, s); return 0; } @@ -321,12 +293,24 @@ static int pl061_init_arm(SysBusDevice *dev) return pl061_init(dev, pl061_id); } +static SysBusDeviceInfo pl061_info = { + .init = pl061_init_arm, + .qdev.name = "pl061", + .qdev.size = sizeof(pl061_state), + .qdev.vmsd = &vmstate_pl061, +}; + +static SysBusDeviceInfo pl061_luminary_info = { + .init = pl061_init_luminary, + .qdev.name = "pl061_luminary", + .qdev.size = sizeof(pl061_state), + .qdev.vmsd = &vmstate_pl061, +}; + static void pl061_register_devices(void) { - sysbus_register_dev("pl061", sizeof(pl061_state), - pl061_init_arm); - sysbus_register_dev("pl061_luminary", sizeof(pl061_state), - pl061_init_luminary); + sysbus_register_withprop(&pl061_info); + sysbus_register_withprop(&pl061_luminary_info); } device_init(pl061_register_devices) From b3aaff11ec0a4c9c9c7f089b74406d926accfd17 Mon Sep 17 00:00:00 2001 From: Peter Maydell Date: Wed, 3 Aug 2011 23:04:49 +0100 Subject: [PATCH 06/24] hw/pl061.c: Support GPIOAMSEL register Support the GPIOAMSEL register found on some Stellaris boards. Signed-off-by: Peter Maydell --- hw/pl061.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/hw/pl061.c b/hw/pl061.c index 27de824ba..d13746cfe 100644 --- a/hw/pl061.c +++ b/hw/pl061.c @@ -50,6 +50,7 @@ typedef struct { uint32_t den; uint32_t cr; uint32_t float_high; + uint32_t amsel; qemu_irq irq; qemu_irq out[8]; const unsigned char *id; @@ -57,7 +58,7 @@ typedef struct { static const VMStateDescription vmstate_pl061 = { .name = "pl061", - .version_id = 1, + .version_id = 2, .minimum_version_id = 1, .fields = (VMStateField[]) { VMSTATE_UINT32(locked, pl061_state), @@ -80,6 +81,7 @@ static const VMStateDescription vmstate_pl061 = { VMSTATE_UINT32(den, pl061_state), VMSTATE_UINT32(cr, pl061_state), VMSTATE_UINT32(float_high, pl061_state), + VMSTATE_UINT32_V(amsel, pl061_state, 2), VMSTATE_END_OF_LIST() } }; @@ -157,6 +159,8 @@ static uint32_t pl061_read(void *opaque, target_phys_addr_t offset) return s->locked; case 0x524: /* Commit */ return s->cr; + case 0x528: /* Analog mode select */ + return s->amsel; default: hw_error("pl061_read: Bad offset %x\n", (int)offset); return 0; @@ -229,6 +233,9 @@ static void pl061_write(void *opaque, target_phys_addr_t offset, if (!s->locked) s->cr = value & 0xff; break; + case 0x528: + s->amsel = value & 0xff; + break; default: hw_error("pl061_write: Bad offset %x\n", (int)offset); } From dc804ab77630f5f3d28a9fb7487966d29f505829 Mon Sep 17 00:00:00 2001 From: Engin AYDOGAN Date: Wed, 3 Aug 2011 22:15:23 +0100 Subject: [PATCH 07/24] hw/stellaris: Add support for RCC2 register Add support for the RCC2 register on Fury class devices. Based on a patch by Vijay Kumar. Signed-off-by: Engin AYDOGAN [Peter Maydell: fixed comment typos, minor cleanup of unreachable code] Signed-off-by: Peter Maydell --- hw/stellaris.c | 72 +++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 68 insertions(+), 4 deletions(-) diff --git a/hw/stellaris.c b/hw/stellaris.c index a28093043..70db99ff9 100644 --- a/hw/stellaris.c +++ b/hw/stellaris.c @@ -332,6 +332,7 @@ typedef struct { uint32_t int_mask; uint32_t resc; uint32_t rcc; + uint32_t rcc2; uint32_t rcgc[3]; uint32_t scgc[3]; uint32_t dcgc[3]; @@ -386,6 +387,32 @@ static uint32_t pllcfg_fury[16] = { 0xb11c /* 8.192 Mhz */ }; +#define DID0_VER_MASK 0x70000000 +#define DID0_VER_0 0x00000000 +#define DID0_VER_1 0x10000000 + +#define DID0_CLASS_MASK 0x00FF0000 +#define DID0_CLASS_SANDSTORM 0x00000000 +#define DID0_CLASS_FURY 0x00010000 + +static int ssys_board_class(const ssys_state *s) +{ + uint32_t did0 = s->board->did0; + switch (did0 & DID0_VER_MASK) { + case DID0_VER_0: + return DID0_CLASS_SANDSTORM; + case DID0_VER_1: + switch (did0 & DID0_CLASS_MASK) { + case DID0_CLASS_SANDSTORM: + case DID0_CLASS_FURY: + return did0 & DID0_CLASS_MASK; + } + /* for unknown classes, fall through */ + default: + hw_error("ssys_board_class: Unknown class 0x%08x\n", did0); + } +} + static uint32_t ssys_read(void *opaque, target_phys_addr_t offset) { ssys_state *s = (ssys_state *)opaque; @@ -429,12 +456,18 @@ static uint32_t ssys_read(void *opaque, target_phys_addr_t offset) { int xtal; xtal = (s->rcc >> 6) & 0xf; - if (s->board->did0 & (1 << 16)) { + switch (ssys_board_class(s)) { + case DID0_CLASS_FURY: return pllcfg_fury[xtal]; - } else { + case DID0_CLASS_SANDSTORM: return pllcfg_sandstorm[xtal]; + default: + hw_error("ssys_read: Unhandled class for PLLCFG read.\n"); + return 0; } } + case 0x070: /* RCC2 */ + return s->rcc2; case 0x100: /* RCGC0 */ return s->rcgc[0]; case 0x104: /* RCGC1 */ @@ -467,9 +500,21 @@ static uint32_t ssys_read(void *opaque, target_phys_addr_t offset) } } +static bool ssys_use_rcc2(ssys_state *s) +{ + return (s->rcc2 >> 31) & 0x1; +} + +/* + * Caculate the sys. clock period in ms. + */ static void ssys_calculate_system_clock(ssys_state *s) { - system_clock_scale = 5 * (((s->rcc >> 23) & 0xf) + 1); + if (ssys_use_rcc2(s)) { + system_clock_scale = 5 * (((s->rcc2 >> 23) & 0x3f) + 1); + } else { + system_clock_scale = 5 * (((s->rcc >> 23) & 0xf) + 1); + } } static void ssys_write(void *opaque, target_phys_addr_t offset, uint32_t value) @@ -505,6 +550,18 @@ static void ssys_write(void *opaque, target_phys_addr_t offset, uint32_t value) s->rcc = value; ssys_calculate_system_clock(s); break; + case 0x070: /* RCC2 */ + if (ssys_board_class(s) == DID0_CLASS_SANDSTORM) { + break; + } + + if ((s->rcc2 & (1 << 13)) != 0 && (value & (1 << 13)) == 0) { + /* PLL enable. */ + s->int_status |= (1 << 6); + } + s->rcc2 = value; + ssys_calculate_system_clock(s); + break; case 0x100: /* RCGC0 */ s->rcgc[0] = value; break; @@ -562,6 +619,12 @@ static void ssys_reset(void *opaque) s->pborctl = 0x7ffd; s->rcc = 0x078e3ac0; + + if (ssys_board_class(s) == DID0_CLASS_SANDSTORM) { + s->rcc2 = 0; + } else { + s->rcc2 = 0x07802810; + } s->rcgc[0] = 1; s->scgc[0] = 1; s->dcgc[0] = 1; @@ -578,7 +641,7 @@ static int stellaris_sys_post_load(void *opaque, int version_id) static const VMStateDescription vmstate_stellaris_sys = { .name = "stellaris_sys", - .version_id = 1, + .version_id = 2, .minimum_version_id = 1, .minimum_version_id_old = 1, .post_load = stellaris_sys_post_load, @@ -589,6 +652,7 @@ static const VMStateDescription vmstate_stellaris_sys = { VMSTATE_UINT32(int_status, ssys_state), VMSTATE_UINT32(resc, ssys_state), VMSTATE_UINT32(rcc, ssys_state), + VMSTATE_UINT32_V(rcc2, ssys_state, 2), VMSTATE_UINT32_ARRAY(rcgc, ssys_state, 3), VMSTATE_UINT32_ARRAY(scgc, ssys_state, 3), VMSTATE_UINT32_ARRAY(dcgc, ssys_state, 3), From 94ac5cd20c6e441e0ed3aec5c98d6cbefb7f503f Mon Sep 17 00:00:00 2001 From: Austin Clements Date: Sun, 21 Aug 2011 14:49:45 -0400 Subject: [PATCH 08/24] monitor: Prevent sign-extension of 32-bit addresses printed by info tlb This is the same fix that was recently applied to info mem. Before this change, info tlb output looked like: ffffffffffffc000: 000000000fffc000 --------W ffffffffffffd000: 000000000fffd000 --------W ffffffffffffe000: 000000000fffe000 --------W fffffffffffff000: 000000000ffff000 --------W With this change, it looks like 00000000ffffc000: 000000000fffc000 --------W 00000000ffffd000: 000000000fffd000 --------W 00000000ffffe000: 000000000fffe000 --------W 00000000fffff000: 000000000ffff000 --------W Signed-off-by: Austin Clements Signed-off-by: Blue Swirl --- monitor.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/monitor.c b/monitor.c index 0e101f541..39791dc55 100644 --- a/monitor.c +++ b/monitor.c @@ -2054,7 +2054,7 @@ static void print_pte(Monitor *mon, target_phys_addr_t addr, static void tlb_info_32(Monitor *mon, CPUState *env) { - int l1, l2; + unsigned int l1, l2; uint32_t pgd, pde, pte; pgd = env->cr[3] & ~0xfff; @@ -2082,7 +2082,7 @@ static void tlb_info_32(Monitor *mon, CPUState *env) static void tlb_info_pae32(Monitor *mon, CPUState *env) { - int l1, l2, l3; + unsigned int l1, l2, l3; uint64_t pdpe, pde, pte; uint64_t pdp_addr, pd_addr, pt_addr; From f90074f49309de9dd65b978a95d10f089017960a Mon Sep 17 00:00:00 2001 From: Blue Swirl Date: Sun, 7 Aug 2011 19:00:23 +0000 Subject: [PATCH 09/24] slavio_timer: avoid structure holes spotted by pahole Report from pahole on amd64 host: struct SLAVIO_TIMERState { SysBusDevice busdev; /* 0 5648 */ /* --- cacheline 88 boundary (5632 bytes) was 16 bytes ago --- */ uint32_t num_cpus; /* 5648 4 */ /* XXX 4 bytes hole, try to pack */ CPUTimerState cputimer[17]; /* 5656 816 */ /* --- cacheline 101 boundary (6464 bytes) was 8 bytes ago --- */ uint32_t cputimer_mode; /* 6472 4 */ /* size: 6480, cachelines: 102 */ /* sum members: 6472, holes: 1, sum holes: 4 */ /* padding: 4 */ /* last cacheline: 16 bytes */ }; /* definitions: 1 */ struct CPUTimerState { qemu_irq irq; /* 0 8 */ ptimer_state * timer; /* 8 8 */ uint32_t count; /* 16 4 */ uint32_t counthigh; /* 20 4 */ uint32_t reached; /* 24 4 */ /* XXX 4 bytes hole, try to pack */ uint64_t limit; /* 32 8 */ uint32_t running; /* 40 4 */ /* size: 48, cachelines: 1 */ /* sum members: 40, holes: 1, sum holes: 4 */ /* padding: 4 */ /* last cacheline: 48 bytes */ }; /* definitions: 1 */ Fix by rearranging the structures to avoid padding. Signed-off-by: Blue Swirl --- hw/slavio_timer.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/hw/slavio_timer.c b/hw/slavio_timer.c index f89b4fb5b..84449baa7 100644 --- a/hw/slavio_timer.c +++ b/hw/slavio_timer.c @@ -48,16 +48,16 @@ typedef struct CPUTimerState { qemu_irq irq; ptimer_state *timer; uint32_t count, counthigh, reached; - uint64_t limit; - // processor only + /* processor only */ uint32_t running; + uint64_t limit; } CPUTimerState; typedef struct SLAVIO_TIMERState { SysBusDevice busdev; uint32_t num_cpus; - CPUTimerState cputimer[MAX_CPUS + 1]; uint32_t cputimer_mode; + CPUTimerState cputimer[MAX_CPUS + 1]; } SLAVIO_TIMERState; typedef struct TimerContext { From 97bbb109b1349051390f6b2ad77b1bfb44e3d760 Mon Sep 17 00:00:00 2001 From: Blue Swirl Date: Sun, 7 Aug 2011 19:03:18 +0000 Subject: [PATCH 10/24] slavio_misc: avoid structure holes spotted by pahole Report from pahole on amd64 host: struct MiscState { SysBusDevice busdev; /* 0 5648 */ /* --- cacheline 88 boundary (5632 bytes) was 16 bytes ago --- */ qemu_irq irq; /* 5648 8 */ uint32_t dummy; /* 5656 4 */ uint8_t config; /* 5660 1 */ uint8_t aux1; /* 5661 1 */ uint8_t aux2; /* 5662 1 */ uint8_t diag; /* 5663 1 */ uint8_t mctrl; /* 5664 1 */ uint8_t sysctrl; /* 5665 1 */ uint16_t leds; /* 5666 2 */ /* XXX 4 bytes hole, try to pack */ qemu_irq fdc_tc; /* 5672 8 */ /* size: 5680, cachelines: 89 */ /* sum members: 5676, holes: 1, sum holes: 4 */ /* last cacheline: 48 bytes */ }; /* definitions: 1 */ Fix by rearranging the structure to avoid padding. Signed-off-by: Blue Swirl --- hw/slavio_misc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hw/slavio_misc.c b/hw/slavio_misc.c index 198360d57..1f5a2d733 100644 --- a/hw/slavio_misc.c +++ b/hw/slavio_misc.c @@ -37,13 +37,13 @@ typedef struct MiscState { SysBusDevice busdev; qemu_irq irq; + qemu_irq fdc_tc; uint32_t dummy; uint8_t config; uint8_t aux1, aux2; uint8_t diag, mctrl; uint8_t sysctrl; uint16_t leds; - qemu_irq fdc_tc; } MiscState; typedef struct APCState { From 07dd0035d83727ed2b1922a85cd5aea5b010025b Mon Sep 17 00:00:00 2001 From: Blue Swirl Date: Sun, 7 Aug 2011 19:06:26 +0000 Subject: [PATCH 11/24] slavio_intctl: avoid structure holes spotted by pahole Report from pahole on amd64 host: struct SLAVIO_INTCTLState { SysBusDevice busdev; /* 0 5648 */ /* --- cacheline 88 boundary (5632 bytes) was 16 bytes ago --- */ uint32_t intregm_pending; /* 5648 4 */ uint32_t intregm_disabled; /* 5652 4 */ uint32_t target_cpu; /* 5656 4 */ /* XXX 4 bytes hole, try to pack */ qemu_irq cpu_irqs[16][16]; /* 5664 2048 */ /* --- cacheline 120 boundary (7680 bytes) was 32 bytes ago --- */ SLAVIO_CPUINTCTLState slaves[16]; /* 7712 384 */ /* --- cacheline 126 boundary (8064 bytes) was 32 bytes ago --- */ /* size: 8096, cachelines: 127 */ /* sum members: 8092, holes: 1, sum holes: 4 */ /* last cacheline: 32 bytes */ }; /* definitions: 1 */ struct SLAVIO_CPUINTCTLState { uint32_t intreg_pending; /* 0 4 */ /* XXX 4 bytes hole, try to pack */ struct SLAVIO_INTCTLState * master; /* 8 8 */ uint32_t cpu; /* 16 4 */ uint32_t irl_out; /* 20 4 */ /* size: 24, cachelines: 1 */ /* sum members: 20, holes: 1, sum holes: 4 */ /* last cacheline: 24 bytes */ }; /* definitions: 1 */ Fix by rearranging the structures to avoid padding. Signed-off-by: Blue Swirl --- hw/slavio_intctl.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/hw/slavio_intctl.c b/hw/slavio_intctl.c index a83e5b827..329c25184 100644 --- a/hw/slavio_intctl.c +++ b/hw/slavio_intctl.c @@ -46,22 +46,22 @@ struct SLAVIO_INTCTLState; typedef struct SLAVIO_CPUINTCTLState { - uint32_t intreg_pending; struct SLAVIO_INTCTLState *master; + uint32_t intreg_pending; uint32_t cpu; uint32_t irl_out; } SLAVIO_CPUINTCTLState; typedef struct SLAVIO_INTCTLState { SysBusDevice busdev; - uint32_t intregm_pending; - uint32_t intregm_disabled; - uint32_t target_cpu; #ifdef DEBUG_IRQ_COUNT uint64_t irq_count[32]; #endif qemu_irq cpu_irqs[MAX_CPUS][MAX_PILS]; SLAVIO_CPUINTCTLState slaves[MAX_CPUS]; + uint32_t intregm_pending; + uint32_t intregm_disabled; + uint32_t target_cpu; } SLAVIO_INTCTLState; #define INTCTL_MAXADDR 0xf From 149e1ea154efebf0b3a7aae20538ce7673d78b77 Mon Sep 17 00:00:00 2001 From: Blue Swirl Date: Sun, 7 Aug 2011 19:09:50 +0000 Subject: [PATCH 12/24] sun4m_iommu: avoid structure holes spotted by pahole Report from pahole on amd64 host: struct IOMMUState { SysBusDevice busdev; /* 0 5648 */ /* --- cacheline 88 boundary (5632 bytes) was 16 bytes ago --- */ uint32_t regs[4096]; /* 5648 16384 */ /* --- cacheline 344 boundary (22016 bytes) was 16 bytes ago --- */ target_phys_addr_t iostart; /* 22032 8 */ uint32_t version; /* 22040 4 */ /* XXX 4 bytes hole, try to pack */ qemu_irq irq; /* 22048 8 */ /* size: 22056, cachelines: 345 */ /* sum members: 22052, holes: 1, sum holes: 4 */ /* last cacheline: 40 bytes */ }; /* definitions: 1 */ Fix by rearranging the structure to avoid padding. Signed-off-by: Blue Swirl --- hw/sun4m_iommu.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hw/sun4m_iommu.c b/hw/sun4m_iommu.c index 7f5dad535..6eeadfa18 100644 --- a/hw/sun4m_iommu.c +++ b/hw/sun4m_iommu.c @@ -130,8 +130,8 @@ typedef struct IOMMUState { SysBusDevice busdev; uint32_t regs[IOMMU_NREGS]; target_phys_addr_t iostart; - uint32_t version; qemu_irq irq; + uint32_t version; } IOMMUState; static uint32_t iommu_mem_readl(void *opaque, target_phys_addr_t addr) From 427a66c3a5674cf69efcd2d82f32ffdf91f2044a Mon Sep 17 00:00:00 2001 From: Blue Swirl Date: Sun, 7 Aug 2011 19:13:24 +0000 Subject: [PATCH 13/24] tcx: avoid structure holes spotted by pahole Report from pahole on amd64 host: struct TCXState { SysBusDevice busdev; /* 0 5648 */ /* --- cacheline 88 boundary (5632 bytes) was 16 bytes ago --- */ target_phys_addr_t addr; /* 5648 8 */ DisplayState * ds; /* 5656 8 */ uint8_t * vram; /* 5664 8 */ uint32_t * vram24; /* 5672 8 */ uint32_t * cplane; /* 5680 8 */ ram_addr_t vram_offset; /* 5688 8 */ /* --- cacheline 89 boundary (5696 bytes) --- */ ram_addr_t vram24_offset; /* 5696 8 */ ram_addr_t cplane_offset; /* 5704 8 */ uint32_t vram_size; /* 5712 4 */ uint16_t width; /* 5716 2 */ uint16_t height; /* 5718 2 */ uint16_t depth; /* 5720 2 */ uint8_t r[256]; /* 5722 256 */ /* --- cacheline 93 boundary (5952 bytes) was 26 bytes ago --- */ uint8_t g[256]; /* 5978 256 */ /* --- cacheline 97 boundary (6208 bytes) was 26 bytes ago --- */ uint8_t b[256]; /* 6234 256 */ /* XXX 2 bytes hole, try to pack */ /* --- cacheline 101 boundary (6464 bytes) was 28 bytes ago --- */ uint32_t palette[256]; /* 6492 1024 */ /* --- cacheline 117 boundary (7488 bytes) was 28 bytes ago --- */ uint8_t dac_index; /* 7516 1 */ uint8_t dac_state; /* 7517 1 */ /* size: 7520, cachelines: 118 */ /* sum members: 7516, holes: 1, sum holes: 2 */ /* padding: 2 */ /* last cacheline: 32 bytes */ }; /* definitions: 1 */ Fix by rearranging the structure to avoid padding. Signed-off-by: Blue Swirl --- hw/tcx.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/hw/tcx.c b/hw/tcx.c index 0e32830a8..309600d24 100644 --- a/hw/tcx.c +++ b/hw/tcx.c @@ -42,9 +42,9 @@ typedef struct TCXState { uint32_t *vram24, *cplane; ram_addr_t vram_offset, vram24_offset, cplane_offset; uint32_t vram_size; - uint16_t width, height, depth; - uint8_t r[256], g[256], b[256]; uint32_t palette[256]; + uint8_t r[256], g[256], b[256]; + uint16_t width, height, depth; uint8_t dac_index, dac_state; } TCXState; From 61999750d3df96ee3f2b111420c7d0a117e57df7 Mon Sep 17 00:00:00 2001 From: Blue Swirl Date: Sun, 7 Aug 2011 19:22:46 +0000 Subject: [PATCH 14/24] sun4m: avoid structure holes spotted by pahole Edited report from pahole on amd64 host: struct sun4c_hwdef { ... uint8_t nvram_machine_id; /* 112 1 */ /* XXX 1 byte hole, try to pack */ ... /* size: 136, cachelines: 3 */ /* sum members: 135, holes: 1, sum holes: 1 */ /* last cacheline: 8 bytes */ }; /* definitions: 1 */ struct sun4d_hwdef { ... uint8_t nvram_machine_id; /* 128 1 */ /* XXX 1 byte hole, try to pack */ ... /* size: 152, cachelines: 3 */ /* sum members: 151, holes: 1, sum holes: 1 */ /* last cacheline: 24 bytes */ }; /* definitions: 1 */ struct sun4m_hwdef { ... uint8_t nvram_machine_id; /* 260 1 */ /* XXX 1 byte hole, try to pack */ uint16_t machine_id; /* 262 2 */ uint32_t iommu_version; /* 264 4 */ /* XXX 4 bytes hole, try to pack */ ... /* size: 288, cachelines: 5 */ /* sum members: 283, holes: 2, sum holes: 5 */ /* last cacheline: 32 bytes */ }; /* definitions: 1 */ Fix by rearranging the structures to avoid padding. Signed-off-by: Blue Swirl --- hw/sun4m.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/hw/sun4m.c b/hw/sun4m.c index 7516703a5..dcaed3877 100644 --- a/hw/sun4m.c +++ b/hw/sun4m.c @@ -97,12 +97,12 @@ struct sun4m_hwdef { target_phys_addr_t reg_base, vram_base; } vsimm[MAX_VSIMMS]; target_phys_addr_t ecc_base; - uint32_t ecc_version; - uint8_t nvram_machine_id; - uint16_t machine_id; - uint32_t iommu_version; uint64_t max_mem; const char * const default_cpu_model; + uint32_t ecc_version; + uint32_t iommu_version; + uint16_t machine_id; + uint8_t nvram_machine_id; }; #define MAX_IOUNITS 5 @@ -115,11 +115,11 @@ struct sun4d_hwdef { target_phys_addr_t ledma_base, le_base; target_phys_addr_t tcx_base; target_phys_addr_t sbi_base; - uint8_t nvram_machine_id; - uint16_t machine_id; - uint32_t iounit_version; uint64_t max_mem; const char * const default_cpu_model; + uint32_t iounit_version; + uint16_t machine_id; + uint8_t nvram_machine_id; }; struct sun4c_hwdef { @@ -128,11 +128,11 @@ struct sun4c_hwdef { target_phys_addr_t serial_base, fd_base; target_phys_addr_t idreg_base, dma_base, esp_base, le_base; target_phys_addr_t tcx_base, aux1_base; - uint8_t nvram_machine_id; - uint16_t machine_id; - uint32_t iommu_version; uint64_t max_mem; const char * const default_cpu_model; + uint32_t iommu_version; + uint16_t machine_id; + uint8_t nvram_machine_id; }; int DMA_get_channel_mode (int nchan) From 9a975d63563c2d09279b0e9a7fb7c2abcbd512b9 Mon Sep 17 00:00:00 2001 From: Blue Swirl Date: Sun, 7 Aug 2011 19:33:30 +0000 Subject: [PATCH 15/24] esp: avoid structure holes spotted by pahole Report from pahole on amd64 host: struct ESPState { SysBusDevice busdev; /* 0 5648 */ /* --- cacheline 88 boundary (5632 bytes) was 16 bytes ago --- */ uint32_t it_shift; /* 5648 4 */ /* XXX 4 bytes hole, try to pack */ qemu_irq irq; /* 5656 8 */ uint8_t rregs[16]; /* 5664 16 */ uint8_t wregs[16]; /* 5680 16 */ /* --- cacheline 89 boundary (5696 bytes) --- */ int32_t ti_size; /* 5696 4 */ uint32_t ti_rptr; /* 5700 4 */ uint32_t ti_wptr; /* 5704 4 */ uint8_t ti_buf[16]; /* 5708 16 */ uint32_t status; /* 5724 4 */ uint32_t dma; /* 5728 4 */ /* XXX 4 bytes hole, try to pack */ SCSIBus bus; /* 5736 2120 */ /* --- cacheline 122 boundary (7808 bytes) was 48 bytes ago --- */ SCSIDevice * current_dev; /* 7856 8 */ SCSIRequest * current_req; /* 7864 8 */ /* --- cacheline 123 boundary (7872 bytes) --- */ uint8_t cmdbuf[16]; /* 7872 16 */ uint32_t cmdlen; /* 7888 4 */ uint32_t do_cmd; /* 7892 4 */ uint32_t dma_left; /* 7896 4 */ uint32_t dma_counter; /* 7900 4 */ uint8_t * async_buf; /* 7904 8 */ uint32_t async_len; /* 7912 4 */ /* XXX 4 bytes hole, try to pack */ ESPDMAMemoryReadWriteFunc dma_memory_read; /* 7920 8 */ ESPDMAMemoryReadWriteFunc dma_memory_write; /* 7928 8 */ /* --- cacheline 124 boundary (7936 bytes) --- */ void * dma_opaque; /* 7936 8 */ int dma_enabled; /* 7944 4 */ /* XXX 4 bytes hole, try to pack */ void (*dma_cb)(ESPState *); /* 7952 8 */ /* size: 7960, cachelines: 125 */ /* sum members: 7944, holes: 4, sum holes: 16 */ /* last cacheline: 24 bytes */ }; /* definitions: 1 */ Fix by rearranging the structure to avoid padding. Signed-off-by: Blue Swirl --- hw/esp.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/hw/esp.c b/hw/esp.c index be3a35dac..ca41f80f8 100644 --- a/hw/esp.c +++ b/hw/esp.c @@ -54,15 +54,15 @@ typedef struct ESPState ESPState; struct ESPState { SysBusDevice busdev; - uint32_t it_shift; - qemu_irq irq; uint8_t rregs[ESP_REGS]; uint8_t wregs[ESP_REGS]; + qemu_irq irq; + uint32_t it_shift; int32_t ti_size; uint32_t ti_rptr, ti_wptr; - uint8_t ti_buf[TI_BUFSZ]; uint32_t status; uint32_t dma; + uint8_t ti_buf[TI_BUFSZ]; SCSIBus bus; SCSIDevice *current_dev; SCSIRequest *current_req; @@ -75,13 +75,14 @@ struct ESPState { /* The size of the current DMA transfer. Zero if no transfer is in progress. */ uint32_t dma_counter; - uint8_t *async_buf; + int dma_enabled; + uint32_t async_len; + uint8_t *async_buf; ESPDMAMemoryReadWriteFunc dma_memory_read; ESPDMAMemoryReadWriteFunc dma_memory_write; void *dma_opaque; - int dma_enabled; void (*dma_cb)(ESPState *s); }; From fe87aa83c6d0c78bc29230ace4598363cdf4c835 Mon Sep 17 00:00:00 2001 From: Blue Swirl Date: Sun, 7 Aug 2011 19:38:49 +0000 Subject: [PATCH 16/24] pcnet: avoid structure holes spotted by pahole Edited report from pahole on amd64 host: struct PCNetState_st { ... uint16_t bcr[32]; /* 340 64 */ /* XXX 4 bytes hole, try to pack */ ... int tx_busy; /* 4520 4 */ /* XXX 4 bytes hole, try to pack */ qemu_irq irq; /* 4528 8 */ void (*phys_mem_read)(void *, target_phys_addr_t, uint8_t *, int, int); /* 4536 8 */ /* --- cacheline 71 boundary (4544 bytes) --- */ void (*phys_mem_write)(void *, target_phys_addr_t, uint8_t *, int, int); /* 4544 8 */ void * dma_opaque; /* 4552 8 */ int looptest; /* 4560 4 */ /* size: 4568, cachelines: 72 */ /* sum members: 4556, holes: 2, sum holes: 8 */ /* padding: 4 */ /* last cacheline: 24 bytes */ }; /* definitions: 2 */ Fix by rearranging the structure to avoid padding. Signed-off-by: Blue Swirl --- hw/pcnet.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/hw/pcnet.h b/hw/pcnet.h index 7e1c6853d..cd86bde9d 100644 --- a/hw/pcnet.h +++ b/hw/pcnet.h @@ -17,17 +17,17 @@ struct PCNetState_st { uint8_t prom[16]; uint16_t csr[128]; uint16_t bcr[32]; + int xmit_pos; uint64_t timer; MemoryRegion mmio; - int xmit_pos; uint8_t buffer[4096]; - int tx_busy; qemu_irq irq; void (*phys_mem_read)(void *dma_opaque, target_phys_addr_t addr, uint8_t *buf, int len, int do_bswap); void (*phys_mem_write)(void *dma_opaque, target_phys_addr_t addr, uint8_t *buf, int len, int do_bswap); void *dma_opaque; + int tx_busy; int looptest; }; From 242cca4fdfadafca39fa918e78fea6ef89d6decc Mon Sep 17 00:00:00 2001 From: Blue Swirl Date: Sun, 7 Aug 2011 19:43:38 +0000 Subject: [PATCH 17/24] fdc: avoid structure holes spotted by pahole Edited report from pahole on amd64 host: struct FDCtrl { uint8_t version; /* 0 1 */ /* XXX 7 bytes hole, try to pack */ qemu_irq irq; /* 8 8 */ int dma_chann; /* 16 4 */ /* XXX 4 bytes hole, try to pack */ ... uint8_t status2; /* 42 1 */ /* XXX 5 bytes hole, try to pack */ uint8_t * fifo; /* 48 8 */ ... uint8_t pwrd; /* 76 1 */ /* XXX 3 bytes hole, try to pack */ int sun4m; /* 80 4 */ uint8_t num_floppies; /* 84 1 */ /* XXX 3 bytes hole, try to pack */ FDrive drives[2]; /* 88 64 */ /* --- cacheline 2 boundary (128 bytes) was 24 bytes ago --- */ int reset_sensei; /* 152 4 */ /* size: 160, cachelines: 3 */ /* sum members: 134, holes: 5, sum holes: 22 */ /* padding: 4 */ /* last cacheline: 32 bytes */ }; /* definitions: 1 */ Fix by rearranging the structure to avoid padding. Signed-off-by: Blue Swirl --- hw/fdc.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/hw/fdc.c b/hw/fdc.c index edf0360d1..580b65779 100644 --- a/hw/fdc.c +++ b/hw/fdc.c @@ -374,13 +374,13 @@ enum { #define FD_FORMAT_CMD(state) ((state) & FD_STATE_FORMAT) struct FDCtrl { + qemu_irq irq; + /* Controller state */ + QEMUTimer *result_timer; + int dma_chann; /* Controller's identification */ uint8_t version; /* HW */ - qemu_irq irq; - int dma_chann; - /* Controller state */ - QEMUTimer *result_timer; uint8_t sra; uint8_t srb; uint8_t dor; @@ -401,21 +401,21 @@ struct FDCtrl { uint8_t data_dir; uint8_t eot; /* last wanted sector */ /* States kept only to be returned back */ - /* Timers state */ - uint8_t timer0; - uint8_t timer1; /* precompensation */ uint8_t precomp_trk; uint8_t config; uint8_t lock; /* Power down config (also with status regB access mode */ uint8_t pwrd; - /* Sun4m quirks? */ - int sun4m; /* Floppy drives */ uint8_t num_floppies; + /* Sun4m quirks? */ + int sun4m; FDrive drives[MAX_FD]; int reset_sensei; + /* Timers state */ + uint8_t timer0; + uint8_t timer1; }; typedef struct FDCtrlSysBus { From d7b9553489f896bbcdb47403edb92f0bfb02eeaa Mon Sep 17 00:00:00 2001 From: Blue Swirl Date: Sun, 7 Aug 2011 19:55:23 +0000 Subject: [PATCH 18/24] escc: avoid structure holes spotted by pahole Edited report from pahole on amd64 host: struct ChannelState { ... ChnType type; /* 32 4 */ /* XXX 4 bytes hole, try to pack */ ... uint8_t rregs[16]; /* 66 16 */ /* XXX 2 bytes hole, try to pack */ ... /* size: 392, cachelines: 7 */ /* sum members: 382, holes: 2, sum holes: 6 */ /* padding: 4 */ /* last cacheline: 8 bytes */ }; /* definitions: 1 */ Fix by rearranging the structure to avoid padding. Signed-off-by: Blue Swirl --- hw/escc.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/hw/escc.c b/hw/escc.c index bea5873a0..ffcd746e0 100644 --- a/hw/escc.c +++ b/hw/escc.c @@ -108,18 +108,19 @@ typedef struct { #define SERIAL_REGS 16 typedef struct ChannelState { qemu_irq irq; - uint32_t reg; uint32_t rxint, txint, rxint_under_svc, txint_under_svc; - ChnID chn; // this channel, A (base+4) or B (base+0) - ChnType type; struct ChannelState *otherchn; - uint8_t rx, tx, wregs[SERIAL_REGS], rregs[SERIAL_REGS]; + uint32_t reg; + uint8_t wregs[SERIAL_REGS], rregs[SERIAL_REGS]; SERIOQueue queue; CharDriverState *chr; int e0_mode, led_mode, caps_lock_mode, num_lock_mode; int disabled; int clock; uint32_t vmstate_dummy; + ChnID chn; // this channel, A (base+4) or B (base+0) + ChnType type; + uint8_t rx, tx; } ChannelState; struct SerialState { From 42c812b98bbdb1d9e12b111f779a4cc6d987727d Mon Sep 17 00:00:00 2001 From: Blue Swirl Date: Sun, 7 Aug 2011 20:02:02 +0000 Subject: [PATCH 19/24] m48t59: avoid structure holes spotted by pahole Report from pahole on amd64 host: struct M48t59State { uint32_t type; /* 0 4 */ /* XXX 4 bytes hole, try to pack */ qemu_irq IRQ; /* 8 8 */ uint32_t io_base; /* 16 4 */ uint32_t size; /* 20 4 */ time_t time_offset; /* 24 8 */ time_t stop_time; /* 32 8 */ struct tm alarm; /* 40 56 */ /* --- cacheline 1 boundary (64 bytes) was 32 bytes ago --- */ struct QEMUTimer * alrm_timer; /* 96 8 */ struct QEMUTimer * wd_timer; /* 104 8 */ uint8_t lock; /* 112 1 */ /* XXX 1 byte hole, try to pack */ uint16_t addr; /* 114 2 */ /* XXX 4 bytes hole, try to pack */ uint8_t * buffer; /* 120 8 */ /* --- cacheline 2 boundary (128 bytes) --- */ /* size: 128, cachelines: 2 */ /* sum members: 119, holes: 3, sum holes: 9 */ }; /* definitions: 1 */ Fix by rearranging the structure to avoid padding. Signed-off-by: Blue Swirl --- hw/m48t59.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/hw/m48t59.c b/hw/m48t59.c index 401b9693e..0cc361eed 100644 --- a/hw/m48t59.c +++ b/hw/m48t59.c @@ -50,8 +50,6 @@ */ struct M48t59State { - /* Model parameters */ - uint32_t type; // 2 = m48t02, 8 = m48t08, 59 = m48t59 /* Hardware parameters */ qemu_irq IRQ; uint32_t io_base; @@ -64,9 +62,12 @@ struct M48t59State { struct QEMUTimer *alrm_timer; struct QEMUTimer *wd_timer; /* NVRAM storage */ - uint8_t lock; - uint16_t addr; uint8_t *buffer; + /* Model parameters */ + uint32_t type; /* 2 = m48t02, 8 = m48t08, 59 = m48t59 */ + /* NVRAM storage */ + uint16_t addr; + uint8_t lock; }; typedef struct M48t59ISAState { From 30c2f2388ab083074b3ab0de8e7f87aed9c62c7a Mon Sep 17 00:00:00 2001 From: Blue Swirl Date: Sun, 7 Aug 2011 11:01:05 +0000 Subject: [PATCH 20/24] escc: replace DPRINTFs with tracepoints Signed-off-by: Blue Swirl --- hw/escc.c | 60 ++++++++++++---------------------------------------- trace-events | 15 +++++++++++++ 2 files changed, 29 insertions(+), 46 deletions(-) diff --git a/hw/escc.c b/hw/escc.c index ffcd746e0..76d94f30f 100644 --- a/hw/escc.c +++ b/hw/escc.c @@ -27,15 +27,7 @@ #include "escc.h" #include "qemu-char.h" #include "console.h" - -/* debug serial */ -//#define DEBUG_SERIAL - -/* debug keyboard */ -//#define DEBUG_KBD - -/* debug mouse */ -//#define DEBUG_MOUSE +#include "trace.h" /* * Chipset docs: @@ -69,25 +61,6 @@ * 2010-May-23 Artyom Tarasenko: Reworked IUS logic */ -#ifdef DEBUG_SERIAL -#define SER_DPRINTF(fmt, ...) \ - do { printf("SER: " fmt , ## __VA_ARGS__); } while (0) -#else -#define SER_DPRINTF(fmt, ...) -#endif -#ifdef DEBUG_KBD -#define KBD_DPRINTF(fmt, ...) \ - do { printf("KBD: " fmt , ## __VA_ARGS__); } while (0) -#else -#define KBD_DPRINTF(fmt, ...) -#endif -#ifdef DEBUG_MOUSE -#define MS_DPRINTF(fmt, ...) \ - do { printf("MSC: " fmt , ## __VA_ARGS__); } while (0) -#else -#define MS_DPRINTF(fmt, ...) -#endif - typedef enum { chn_a, chn_b, } ChnID; @@ -250,7 +223,7 @@ static void put_queue(void *opaque, int b) ChannelState *s = opaque; SERIOQueue *q = &s->queue; - SER_DPRINTF("channel %c put: 0x%02x\n", CHN_C(s), b); + trace_escc_put_queue(CHN_C(s), b); if (q->count >= SERIO_QUEUE_SIZE) return; q->data[q->wptr] = b; @@ -274,7 +247,7 @@ static uint32_t get_queue(void *opaque) q->rptr = 0; q->count--; } - SER_DPRINTF("channel %c get 0x%02x\n", CHN_C(s), val); + trace_escc_get_queue(CHN_C(s), val); if (q->count > 0) serial_receive_byte(s, 0); return val; @@ -301,7 +274,7 @@ static void escc_update_irq(ChannelState *s) irq = escc_update_irq_chn(s); irq |= escc_update_irq_chn(s->otherchn); - SER_DPRINTF("IRQ = %d\n", irq); + trace_escc_update_irq(irq); qemu_set_irq(s->irq, irq); } @@ -486,8 +459,7 @@ static void escc_update_parameters(ChannelState *s) ssp.parity = parity; ssp.data_bits = data_bits; ssp.stop_bits = stop_bits; - SER_DPRINTF("channel %c: speed=%d parity=%c data=%d stop=%d\n", CHN_C(s), - speed, parity, data_bits, stop_bits); + trace_escc_update_parameters(CHN_C(s), speed, parity, data_bits, stop_bits); qemu_chr_ioctl(s->chr, CHR_IOCTL_SERIAL_SET_PARAMS, &ssp); } @@ -505,8 +477,7 @@ static void escc_mem_write(void *opaque, target_phys_addr_t addr, s = &serial->chn[channel]; switch (saddr) { case SERIAL_CTRL: - SER_DPRINTF("Write channel %c, reg[%d] = %2.2x\n", CHN_C(s), s->reg, - val & 0xff); + trace_escc_mem_writeb_ctrl(CHN_C(s), s->reg, val & 0xff); newreg = 0; switch (s->reg) { case W_CMD: @@ -576,7 +547,7 @@ static void escc_mem_write(void *opaque, target_phys_addr_t addr, s->reg = 0; break; case SERIAL_DATA: - SER_DPRINTF("Write channel %c, ch %d\n", CHN_C(s), val); + trace_escc_mem_writeb_data(CHN_C(s), val); s->tx = val; if (s->wregs[W_TXCTRL2] & TXCTRL2_TXEN) { // tx enabled if (s->chr) @@ -608,8 +579,7 @@ static uint64_t escc_mem_read(void *opaque, target_phys_addr_t addr, s = &serial->chn[channel]; switch (saddr) { case SERIAL_CTRL: - SER_DPRINTF("Read channel %c, reg[%d] = %2.2x\n", CHN_C(s), s->reg, - s->rregs[s->reg]); + trace_escc_mem_readb_ctrl(CHN_C(s), s->reg, s->rregs[s->reg]); ret = s->rregs[s->reg]; s->reg = 0; return ret; @@ -620,7 +590,7 @@ static uint64_t escc_mem_read(void *opaque, target_phys_addr_t addr, ret = get_queue(s); else ret = s->rx; - SER_DPRINTF("Read channel %c, ch %d\n", CHN_C(s), ret); + trace_escc_mem_readb_data(CHN_C(s), ret); if (s->chr) qemu_chr_accept_input(s->chr); return ret; @@ -656,7 +626,7 @@ static int serial_can_receive(void *opaque) static void serial_receive_byte(ChannelState *s, int ch) { - SER_DPRINTF("channel %c put ch %d\n", CHN_C(s), ch); + trace_escc_serial_receive_byte(CHN_C(s), ch); s->rregs[R_STATUS] |= STATUS_RXAV; s->rx = ch; set_rxint(s); @@ -768,8 +738,7 @@ static void sunkbd_event(void *opaque, int ch) ChannelState *s = opaque; int release = ch & 0x80; - KBD_DPRINTF("Untranslated keycode %2.2x (%s)\n", ch, release? "release" : - "press"); + trace_escc_sunkbd_event_in(ch); switch (ch) { case 58: // Caps lock press s->caps_lock_mode ^= 1; @@ -803,13 +772,13 @@ static void sunkbd_event(void *opaque, int ch) } else { ch = keycodes[ch & 0x7f]; } - KBD_DPRINTF("Translated keycode %2.2x\n", ch); + trace_escc_sunkbd_event_out(ch); put_queue(s, ch | release); } static void handle_kbd_command(ChannelState *s, int val) { - KBD_DPRINTF("Command %d\n", val); + trace_escc_kbd_command(val); if (s->led_mode) { // Ignore led byte s->led_mode = 0; return; @@ -841,8 +810,7 @@ static void sunmouse_event(void *opaque, ChannelState *s = opaque; int ch; - MS_DPRINTF("dx=%d dy=%d buttons=%01x\n", dx, dy, buttons_state); - + trace_escc_sunmouse_event(dx, dy, buttons_state); ch = 0x80 | 0x7; /* protocol start byte, no buttons pressed */ if (buttons_state & MOUSE_EVENT_LBUTTON) diff --git a/trace-events b/trace-events index 246704c77..14e6f8b1a 100644 --- a/trace-events +++ b/trace-events @@ -446,3 +446,18 @@ disable qemu_co_mutex_lock_entry(void *mutex, void *self) "mutex %p self %p" disable qemu_co_mutex_lock_return(void *mutex, void *self) "mutex %p self %p" disable qemu_co_mutex_unlock_entry(void *mutex, void *self) "mutex %p self %p" disable qemu_co_mutex_unlock_return(void *mutex, void *self) "mutex %p self %p" + +# hw/escc.c +disable escc_put_queue(char channel, int b) "channel %c put: 0x%02x" +disable escc_get_queue(char channel, int val) "channel %c get 0x%02x" +disable escc_update_irq(int irq) "IRQ = %d" +disable escc_update_parameters(char channel, int speed, int parity, int data_bits, int stop_bits) "channel %c: speed=%d parity=%c data=%d stop=%d" +disable escc_mem_writeb_ctrl(char channel, uint32_t reg, uint32_t val) "Write channel %c, reg[%d] = %2.2x" +disable escc_mem_writeb_data(char channel, uint32_t val) "Write channel %c, ch %d" +disable escc_mem_readb_ctrl(char channel, uint32_t reg, uint8_t val) "Read channel %c, reg[%d] = %2.2x" +disable escc_mem_readb_data(char channel, uint32_t ret) "Read channel %c, ch %d" +disable escc_serial_receive_byte(char channel, int ch) "channel %c put ch %d" +disable escc_sunkbd_event_in(int ch) "Untranslated keycode %2.2x" +disable escc_sunkbd_event_out(int ch) "Translated keycode %2.2x" +disable escc_kbd_command(int val) "Command %d" +disable escc_sunmouse_event(int dx, int dy, int buttons_state) "dx=%d dy=%d buttons=%01x" From 164a4dcd8d90a0db5ffa2174f693195744374418 Mon Sep 17 00:00:00 2001 From: Avi Kivity Date: Thu, 11 Aug 2011 10:40:25 +0300 Subject: [PATCH 21/24] memory: abstract cracking of write access ops into a function The memory API automatically cracks large reads and writes into smaller ones when needed. Factor out this mechanism, which is now duplicated between memory reads and memory writes, into a function. Signed-off-by: Avi Kivity Signed-off-by: Anthony Liguori --- memory.c | 109 ++++++++++++++++++++++++++++++++++--------------------- 1 file changed, 68 insertions(+), 41 deletions(-) diff --git a/memory.c b/memory.c index 24439f386..8e6dd35cb 100644 --- a/memory.c +++ b/memory.c @@ -226,6 +226,65 @@ static void flatview_simplify(FlatView *view) } } +static void memory_region_read_accessor(void *opaque, + target_phys_addr_t addr, + uint64_t *value, + unsigned size, + unsigned shift, + uint64_t mask) +{ + MemoryRegion *mr = opaque; + uint64_t tmp; + + tmp = mr->ops->read(mr->opaque, addr, size); + *value |= (tmp & mask) << shift; +} + +static void memory_region_write_accessor(void *opaque, + target_phys_addr_t addr, + uint64_t *value, + unsigned size, + unsigned shift, + uint64_t mask) +{ + MemoryRegion *mr = opaque; + uint64_t tmp; + + tmp = (*value >> shift) & mask; + mr->ops->write(mr->opaque, addr, tmp, size); +} + +static void access_with_adjusted_size(target_phys_addr_t addr, + uint64_t *value, + unsigned size, + unsigned access_size_min, + unsigned access_size_max, + void (*access)(void *opaque, + target_phys_addr_t addr, + uint64_t *value, + unsigned size, + unsigned shift, + uint64_t mask), + void *opaque) +{ + uint64_t access_mask; + unsigned access_size; + unsigned i; + + if (!access_size_min) { + access_size_min = 1; + } + if (!access_size_max) { + access_size_max = 4; + } + access_size = MAX(MIN(size, access_size_max), access_size_min); + access_mask = -1ULL >> (64 - access_size * 8); + for (i = 0; i < size; i += access_size) { + /* FIXME: big-endian support */ + access(opaque, addr + i, value, access_size, i * 8, access_mask); + } +} + static void memory_region_prepare_ram_addr(MemoryRegion *mr); static void as_memory_range_add(AddressSpace *as, FlatRange *fr) @@ -744,10 +803,7 @@ static uint32_t memory_region_read_thunk_n(void *_mr, unsigned size) { MemoryRegion *mr = _mr; - unsigned access_size, access_size_min, access_size_max; - uint64_t access_mask; - uint32_t data = 0, tmp; - unsigned i; + uint64_t data = 0; if (!memory_region_access_valid(mr, addr, size)) { return -1U; /* FIXME: better signalling */ @@ -758,23 +814,10 @@ static uint32_t memory_region_read_thunk_n(void *_mr, } /* FIXME: support unaligned access */ - - access_size_min = mr->ops->impl.min_access_size; - if (!access_size_min) { - access_size_min = 1; - } - access_size_max = mr->ops->impl.max_access_size; - if (!access_size_max) { - access_size_max = 4; - } - access_size = MAX(MIN(size, access_size_max), access_size_min); - access_mask = -1ULL >> (64 - access_size * 8); - addr += mr->offset; - for (i = 0; i < size; i += access_size) { - /* FIXME: big-endian support */ - tmp = mr->ops->read(mr->opaque, addr + i, access_size); - data |= (tmp & access_mask) << (i * 8); - } + access_with_adjusted_size(addr + mr->offset, &data, size, + mr->ops->impl.min_access_size, + mr->ops->impl.max_access_size, + memory_region_read_accessor, mr); return data; } @@ -785,9 +828,6 @@ static void memory_region_write_thunk_n(void *_mr, uint64_t data) { MemoryRegion *mr = _mr; - unsigned access_size, access_size_min, access_size_max; - uint64_t access_mask; - unsigned i; if (!memory_region_access_valid(mr, addr, size)) { return; /* FIXME: better signalling */ @@ -799,23 +839,10 @@ static void memory_region_write_thunk_n(void *_mr, } /* FIXME: support unaligned access */ - - access_size_min = mr->ops->impl.min_access_size; - if (!access_size_min) { - access_size_min = 1; - } - access_size_max = mr->ops->impl.max_access_size; - if (!access_size_max) { - access_size_max = 4; - } - access_size = MAX(MIN(size, access_size_max), access_size_min); - access_mask = -1ULL >> (64 - access_size * 8); - addr += mr->offset; - for (i = 0; i < size; i += access_size) { - /* FIXME: big-endian support */ - mr->ops->write(mr->opaque, addr + i, (data >> (i * 8)) & access_mask, - access_size); - } + access_with_adjusted_size(addr + mr->offset, &data, size, + mr->ops->impl.min_access_size, + mr->ops->impl.max_access_size, + memory_region_write_accessor, mr); } static uint32_t memory_region_read_thunk_b(void *mr, target_phys_addr_t addr) From 3a130f4ef07f4532500473aeab43c86a3c2991c8 Mon Sep 17 00:00:00 2001 From: Avi Kivity Date: Thu, 11 Aug 2011 10:40:26 +0300 Subject: [PATCH 22/24] memory: crack wide ioport accesses into smaller ones when needed The memory API supports cracking wide accesses into narrower ones when needed; but this was no implemented for the pio address space, causing lsi53c895a's IO BAR to malfunction. Fix by correctly cracking wide accesses when needed. Signed-off-by: Avi Kivity Signed-off-by: Anthony Liguori --- memory.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/memory.c b/memory.c index 8e6dd35cb..30ba4a4b3 100644 --- a/memory.c +++ b/memory.c @@ -400,7 +400,11 @@ static void memory_region_iorange_read(IORange *iorange, } return; } - *data = mr->ops->read(mr->opaque, offset, width); + *data = 0; + access_with_adjusted_size(offset, data, width, + mr->ops->impl.min_access_size, + mr->ops->impl.max_access_size, + memory_region_read_accessor, mr); } static void memory_region_iorange_write(IORange *iorange, @@ -418,7 +422,10 @@ static void memory_region_iorange_write(IORange *iorange, } return; } - mr->ops->write(mr->opaque, offset, data, width); + access_with_adjusted_size(offset, &data, width, + mr->ops->impl.min_access_size, + mr->ops->impl.max_access_size, + memory_region_write_accessor, mr); } static const IORangeOps memory_region_iorange_ops = { From 8f4774789947bc4bc4c8d026a289fe980d3d2ee1 Mon Sep 17 00:00:00 2001 From: Michael Roth Date: Thu, 11 Aug 2011 15:38:11 -0500 Subject: [PATCH 23/24] guest agent: remove g_strcmp0 usage g_strcmp0 isn't in all version of glib 2.0, so don't use it to avoid build breakage on older distros. Signed-off-by: Michael Roth Signed-off-by: Michael Roth Signed-off-by: Anthony Liguori --- qemu-ga.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/qemu-ga.c b/qemu-ga.c index eb632b7b5..858d75a36 100644 --- a/qemu-ga.c +++ b/qemu-ga.c @@ -146,7 +146,7 @@ static void ga_log(const gchar *domain, GLogLevelFlags level, } level &= G_LOG_LEVEL_MASK; - if (g_strcmp0(domain, "syslog") == 0) { + if (domain && strcmp(domain, "syslog") == 0) { syslog(LOG_INFO, "%s: %s", level_str, msg); } else if (level & s->log_level) { g_get_current_time(&time); From 957f1f99f263d57612807a9535f75ca4473f05f0 Mon Sep 17 00:00:00 2001 From: Michael Roth Date: Thu, 11 Aug 2011 15:38:12 -0500 Subject: [PATCH 24/24] guest agent: remove uneeded dependencies This patch tries to cull any uneeded library dependencies from the guest agent to improve portability across various distros. We do so by being as explicit as possible about in-tree dependencies rather than relying on existing *-obj-y targets, and by manually setting LIBS for the qemu-ga target to avoid pulling in LIBS_TOOLS libraries discovered by configure. Signed-off-by: Michael Roth Signed-off-by: Anthony Liguori --- Makefile | 8 ++++---- Makefile.objs | 9 +++++++++ configure | 3 +++ 3 files changed, 16 insertions(+), 4 deletions(-) diff --git a/Makefile b/Makefile index eb3e33820..86068498e 100644 --- a/Makefile +++ b/Makefile @@ -166,6 +166,7 @@ test-coroutine: test-coroutine.o qemu-timer-common.o async.o $(coroutine-obj-y) $(qapi-obj-y): $(GENERATED_HEADERS) qapi-dir := qapi-generated test-visitor.o test-qmp-commands.o qemu-ga$(EXESUF): QEMU_CFLAGS += -I $(qapi-dir) +qemu-ga$(EXESUF): LIBS = $(LIBS_QGA) $(qapi-dir)/test-qapi-types.c: $(qapi-dir)/test-qapi-types.h $(qapi-dir)/test-qapi-types.h: $(SRC_PATH)/qapi-schema-test.json $(SRC_PATH)/scripts/qapi-types.py @@ -192,12 +193,11 @@ test-visitor: test-visitor.o qfloat.o qint.o qdict.o qstring.o qlist.o qbool.o $ test-qmp-commands.o: $(addprefix $(qapi-dir)/, test-qapi-types.c test-qapi-types.h test-qapi-visit.c test-qapi-visit.h test-qmp-marshal.c test-qmp-commands.h) $(qapi-obj-y) test-qmp-commands: test-qmp-commands.o qfloat.o qint.o qdict.o qstring.o qlist.o qbool.o $(qapi-obj-y) error.o osdep.o $(oslib-obj-y) qjson.o json-streamer.o json-lexer.o json-parser.o qerror.o qemu-error.o qemu-tool.o $(qapi-dir)/test-qapi-visit.o $(qapi-dir)/test-qapi-types.o $(qapi-dir)/test-qmp-marshal.o module.o -QGALIB=qga/guest-agent-command-state.o qga/guest-agent-commands.o QGALIB_GEN=$(addprefix $(qapi-dir)/, qga-qapi-types.c qga-qapi-types.h qga-qapi-visit.c qga-qmp-marshal.c) - $(QGALIB_GEN): $(GENERATED_HEADERS) -$(QGALIB) qemu-ga.o: $(QGALIB_GEN) $(qapi-obj-y) -qemu-ga$(EXESUF): qemu-ga.o $(QGALIB) qemu-tool.o qemu-error.o error.o $(oslib-obj-y) $(trace-obj-y) $(block-obj-y) $(qobject-obj-y) $(version-obj-y) $(qapi-obj-y) qemu-timer-common.o qemu-sockets.o module.o qapi/qmp-dispatch.o qapi/qmp-registry.o $(qapi-dir)/qga-qapi-visit.o $(qapi-dir)/qga-qapi-types.o $(qapi-dir)/qga-qmp-marshal.o +$(qga-obj-y) qemu-ga.o: $(QGALIB_GEN) + +qemu-ga$(EXESUF): qemu-ga.o $(qga-obj-y) $(qapi-obj-y) $(trace-obj-y) $(qobject-obj-y) $(version-obj-y) $(addprefix $(qapi-dir)/, qga-qapi-visit.o qga-qapi-types.o qga-qmp-marshal.o) QEMULIBS=libhw32 libhw64 libuser libdis libdis-user diff --git a/Makefile.objs b/Makefile.objs index 91b71b697..abd867a0c 100644 --- a/Makefile.objs +++ b/Makefile.objs @@ -396,6 +396,15 @@ qapi-nested-y = qapi-visit-core.o qmp-input-visitor.o qmp-output-visitor.o qapi- qapi-nested-y += qmp-registry.o qmp-dispatch.o qapi-obj-y = $(addprefix qapi/, $(qapi-nested-y)) +###################################################################### +# guest agent + +qga-nested-y = guest-agent-commands.o guest-agent-command-state.o +qga-obj-y = $(addprefix qga/, $(qga-nested-y)) +qga-obj-y += qemu-ga.o qemu-tool.o qemu-error.o qemu-sockets.o module.o qemu-option.o cutils.o osdep.o +qga-obj-$(CONFIG_WIN32) += oslib-win32.o +qga-obj-$(CONFIG_POSIX) += oslib-posix.o + vl.o: QEMU_CFLAGS+=$(GPROF_CFLAGS) vl.o: QEMU_CFLAGS+=$(SDL_CFLAGS) diff --git a/configure b/configure index 851387556..234a4c503 100755 --- a/configure +++ b/configure @@ -92,6 +92,7 @@ libs_tools="" audio_pt_int="" audio_win_int="" cc_i386=i386-pc-linux-gnu-gcc +libs_qga="" target_list="" @@ -1849,6 +1850,7 @@ if $pkg_config --modversion gthread-2.0 > /dev/null 2>&1 ; then glib_cflags=`$pkg_config --cflags gthread-2.0 2>/dev/null` glib_libs=`$pkg_config --libs gthread-2.0 2>/dev/null` LIBS="$glib_libs $LIBS" + libs_qga="$glib_libs $libs_qga" else echo "glib-2.0 required to compile QEMU" exit 1 @@ -3107,6 +3109,7 @@ echo "ARLIBS_END=$arlibs_end" >> $config_host_mak echo "LIBS+=$LIBS" >> $config_host_mak echo "LIBS_TOOLS+=$libs_tools" >> $config_host_mak echo "EXESUF=$EXESUF" >> $config_host_mak +echo "LIBS_QGA+=$libs_qga" >> $config_host_mak # generate list of library paths for linker script