diff options
Diffstat (limited to 'hw')
| -rw-r--r-- | hw/acpi/vmgenid.c | 1 | ||||
| -rw-r--r-- | hw/char/virtio-serial-bus.c | 1 | ||||
| -rw-r--r-- | hw/core/machine.c | 39 | ||||
| -rw-r--r-- | hw/core/ptimer.c | 1 | ||||
| -rw-r--r-- | hw/display/cirrus_vga.c | 106 | ||||
| -rw-r--r-- | hw/display/cirrus_vga_rop.h | 191 | ||||
| -rw-r--r-- | hw/display/cirrus_vga_rop2.h | 125 | ||||
| -rw-r--r-- | hw/i386/kvm/clock.c | 6 | ||||
| -rw-r--r-- | hw/ide/ahci.c | 12 | ||||
| -rw-r--r-- | hw/ide/core.c | 8 | ||||
| -rw-r--r-- | hw/ide/qdev.c | 12 | ||||
| -rw-r--r-- | hw/intc/arm_gic.c | 13 | ||||
| -rw-r--r-- | hw/misc/imx6_src.c | 8 | ||||
| -rw-r--r-- | hw/net/e1000e.c | 2 | ||||
| -rw-r--r-- | hw/net/mcf_fec.c | 115 | ||||
| -rw-r--r-- | hw/pci/pci.c | 11 | ||||
| -rw-r--r-- | hw/pci/pcie.c | 20 | ||||
| -rw-r--r-- | hw/ppc/pnv.c | 1 | ||||
| -rw-r--r-- | hw/ppc/spapr.c | 9 | ||||
| -rw-r--r-- | hw/ppc/spapr_pci.c | 4 | ||||
| -rw-r--r-- | hw/scsi/mptsas.c | 6 | ||||
| -rw-r--r-- | hw/sparc/sun4m.c | 3 | ||||
| -rw-r--r-- | hw/sparc64/sparc64.c | 3 | ||||
| -rw-r--r-- | hw/virtio/virtio-pci.c | 37 | ||||
| -rw-r--r-- | hw/virtio/virtio-pci.h | 12 | ||||
| -rw-r--r-- | hw/virtio/virtio.c | 104 |
26 files changed, 633 insertions, 217 deletions
diff --git a/hw/acpi/vmgenid.c b/hw/acpi/vmgenid.c index 744f2847da..7a3ad17d66 100644 --- a/hw/acpi/vmgenid.c +++ b/hw/acpi/vmgenid.c @@ -248,6 +248,7 @@ GuidInfo *qmp_query_vm_generation_id(Error **errp) Object *obj = find_vmgenid_dev(); if (!obj) { + error_setg(errp, "VM Generation ID device not found"); return NULL; } vms = VMGENID(obj); diff --git a/hw/char/virtio-serial-bus.c b/hw/char/virtio-serial-bus.c index d544cd91c0..d797a6796e 100644 --- a/hw/char/virtio-serial-bus.c +++ b/hw/char/virtio-serial-bus.c @@ -724,6 +724,7 @@ static void virtio_serial_post_load_timer_cb(void *opaque) } } g_free(s->post_load->connected); + timer_del(s->post_load->timer); timer_free(s->post_load->timer); g_free(s->post_load); s->post_load = NULL; diff --git a/hw/core/machine.c b/hw/core/machine.c index 0699750336..0d92672203 100644 --- a/hw/core/machine.c +++ b/hw/core/machine.c @@ -585,11 +585,31 @@ static void machine_class_finalize(ObjectClass *klass, void *data) g_free(mc->name); } +static void register_compat_prop(const char *driver, + const char *property, + const char *value) +{ + GlobalProperty *p = g_new0(GlobalProperty, 1); + /* Machine compat_props must never cause errors: */ + p->errp = &error_abort; + p->driver = driver; + p->property = property; + p->value = value; + qdev_prop_register_global(p); +} + +static void machine_register_compat_for_subclass(ObjectClass *oc, void *opaque) +{ + GlobalProperty *p = opaque; + register_compat_prop(object_class_get_name(oc), p->property, p->value); +} + void machine_register_compat_props(MachineState *machine) { MachineClass *mc = MACHINE_GET_CLASS(machine); int i; GlobalProperty *p; + ObjectClass *oc; if (!mc->compat_props) { return; @@ -597,9 +617,22 @@ void machine_register_compat_props(MachineState *machine) for (i = 0; i < mc->compat_props->len; i++) { p = g_array_index(mc->compat_props, GlobalProperty *, i); - /* Machine compat_props must never cause errors: */ - p->errp = &error_abort; - qdev_prop_register_global(p); + oc = object_class_by_name(p->driver); + if (oc && object_class_is_abstract(oc)) { + /* temporary hack to make sure we do not override + * globals set explicitly on -global: if an abstract class + * is on compat_props, register globals for all its + * non-abstract subtypes instead. + * + * This doesn't solve the problem for cases where + * a non-abstract typename mentioned on compat_props + * has subclasses, like spapr-pci-host-bridge. + */ + object_class_foreach(machine_register_compat_for_subclass, + p->driver, false, p); + } else { + register_compat_prop(p->driver, p->property, p->value); + } } } diff --git a/hw/core/ptimer.c b/hw/core/ptimer.c index 59ccb00550..7221c68a98 100644 --- a/hw/core/ptimer.c +++ b/hw/core/ptimer.c @@ -13,6 +13,7 @@ #include "sysemu/replay.h" #include "sysemu/qtest.h" #include "block/aio.h" +#include "sysemu/cpus.h" #define DELTA_ADJUST 1 #define DELTA_NO_ADJUST -1 diff --git a/hw/display/cirrus_vga.c b/hw/display/cirrus_vga.c index b9e7cb1df1..afc290ab91 100644 --- a/hw/display/cirrus_vga.c +++ b/hw/display/cirrus_vga.c @@ -178,11 +178,12 @@ struct CirrusVGAState; typedef void (*cirrus_bitblt_rop_t) (struct CirrusVGAState *s, - uint8_t * dst, const uint8_t * src, + uint32_t dstaddr, uint32_t srcaddr, int dstpitch, int srcpitch, int bltwidth, int bltheight); typedef void (*cirrus_fill_t)(struct CirrusVGAState *s, - uint8_t *dst, int dst_pitch, int width, int height); + uint32_t dstaddr, int dst_pitch, + int width, int height); typedef struct CirrusVGAState { VGACommonState vga; @@ -205,6 +206,7 @@ typedef struct CirrusVGAState { uint32_t cirrus_bank_base[2]; uint32_t cirrus_bank_limit[2]; uint8_t cirrus_hidden_palette[48]; + bool enable_blitter; int cirrus_blt_pixelwidth; int cirrus_blt_width; int cirrus_blt_height; @@ -320,18 +322,57 @@ static bool blit_is_unsafe(struct CirrusVGAState *s, bool dst_only) } static void cirrus_bitblt_rop_nop(CirrusVGAState *s, - uint8_t *dst,const uint8_t *src, + uint32_t dstaddr, uint32_t srcaddr, int dstpitch,int srcpitch, int bltwidth,int bltheight) { } static void cirrus_bitblt_fill_nop(CirrusVGAState *s, - uint8_t *dst, + uint32_t dstaddr, int dstpitch, int bltwidth,int bltheight) { } +static inline uint8_t cirrus_src(CirrusVGAState *s, uint32_t srcaddr) +{ + if (s->cirrus_srccounter) { + /* cputovideo */ + return s->cirrus_bltbuf[srcaddr & (CIRRUS_BLTBUFSIZE - 1)]; + } else { + /* videotovideo */ + return s->vga.vram_ptr[srcaddr & s->cirrus_addr_mask]; + } +} + +static inline uint16_t cirrus_src16(CirrusVGAState *s, uint32_t srcaddr) +{ + uint16_t *src; + + if (s->cirrus_srccounter) { + /* cputovideo */ + src = (void *)&s->cirrus_bltbuf[srcaddr & (CIRRUS_BLTBUFSIZE - 1) & ~1]; + } else { + /* videotovideo */ + src = (void *)&s->vga.vram_ptr[srcaddr & s->cirrus_addr_mask & ~1]; + } + return *src; +} + +static inline uint32_t cirrus_src32(CirrusVGAState *s, uint32_t srcaddr) +{ + uint32_t *src; + + if (s->cirrus_srccounter) { + /* cputovideo */ + src = (void *)&s->cirrus_bltbuf[srcaddr & (CIRRUS_BLTBUFSIZE - 1) & ~3]; + } else { + /* videotovideo */ + src = (void *)&s->vga.vram_ptr[srcaddr & s->cirrus_addr_mask & ~3]; + } + return *src; +} + #define ROP_NAME 0 #define ROP_FN(d, s) 0 #include "cirrus_vga_rop.h" @@ -666,21 +707,18 @@ static void cirrus_invalidate_region(CirrusVGAState * s, int off_begin, } for (y = 0; y < lines; y++) { - off_cur = off_begin; - off_cur_end = (off_cur + bytesperline) & s->cirrus_addr_mask; + off_cur = off_begin; + off_cur_end = ((off_cur + bytesperline - 1) & s->cirrus_addr_mask) + 1; assert(off_cur_end >= off_cur); memory_region_set_dirty(&s->vga.vram, off_cur, off_cur_end - off_cur); - off_begin += off_pitch; + off_begin += off_pitch; } } -static int cirrus_bitblt_common_patterncopy(CirrusVGAState *s, bool videosrc) +static int cirrus_bitblt_common_patterncopy(CirrusVGAState *s) { uint32_t patternsize; - uint8_t *dst; - uint8_t *src; - - dst = s->vga.vram_ptr + s->cirrus_blt_dstaddr; + bool videosrc = !s->cirrus_srccounter; if (videosrc) { switch (s->vga.get_bpp(&s->vga)) { @@ -701,16 +739,14 @@ static int cirrus_bitblt_common_patterncopy(CirrusVGAState *s, bool videosrc) if (s->cirrus_blt_srcaddr + patternsize > s->vga.vram_size) { return 0; } - src = s->vga.vram_ptr + s->cirrus_blt_srcaddr; - } else { - src = s->cirrus_bltbuf; } if (blit_is_unsafe(s, true)) { return 0; } - (*s->cirrus_rop) (s, dst, src, + (*s->cirrus_rop) (s, s->cirrus_blt_dstaddr, + videosrc ? s->cirrus_blt_srcaddr : 0, s->cirrus_blt_dstpitch, 0, s->cirrus_blt_width, s->cirrus_blt_height); cirrus_invalidate_region(s, s->cirrus_blt_dstaddr, @@ -729,7 +765,7 @@ static int cirrus_bitblt_solidfill(CirrusVGAState *s, int blt_rop) return 0; } rop_func = cirrus_fill[rop_to_index[blt_rop]][s->cirrus_blt_pixelwidth - 1]; - rop_func(s, s->vga.vram_ptr + s->cirrus_blt_dstaddr, + rop_func(s, s->cirrus_blt_dstaddr, s->cirrus_blt_dstpitch, s->cirrus_blt_width, s->cirrus_blt_height); cirrus_invalidate_region(s, s->cirrus_blt_dstaddr, @@ -747,7 +783,7 @@ static int cirrus_bitblt_solidfill(CirrusVGAState *s, int blt_rop) static int cirrus_bitblt_videotovideo_patterncopy(CirrusVGAState * s) { - return cirrus_bitblt_common_patterncopy(s, true); + return cirrus_bitblt_common_patterncopy(s); } static int cirrus_do_copy(CirrusVGAState *s, int dst, int src, int w, int h) @@ -796,21 +832,15 @@ static int cirrus_do_copy(CirrusVGAState *s, int dst, int src, int w, int h) } } - /* we have to flush all pending changes so that the copy - is generated at the appropriate moment in time */ - if (notify) - graphic_hw_update(s->vga.con); - - (*s->cirrus_rop) (s, s->vga.vram_ptr + s->cirrus_blt_dstaddr, - s->vga.vram_ptr + s->cirrus_blt_srcaddr, + (*s->cirrus_rop) (s, s->cirrus_blt_dstaddr, + s->cirrus_blt_srcaddr, s->cirrus_blt_dstpitch, s->cirrus_blt_srcpitch, s->cirrus_blt_width, s->cirrus_blt_height); if (notify) { - qemu_console_copy(s->vga.con, - sx, sy, dx, dy, - s->cirrus_blt_width / depth, - s->cirrus_blt_height); + dpy_gfx_update(s->vga.con, dx, dy, + s->cirrus_blt_width / depth, + s->cirrus_blt_height); } /* we don't have to notify the display that this portion has @@ -846,15 +876,15 @@ static void cirrus_bitblt_cputovideo_next(CirrusVGAState * s) if (s->cirrus_srccounter > 0) { if (s->cirrus_blt_mode & CIRRUS_BLTMODE_PATTERNCOPY) { - cirrus_bitblt_common_patterncopy(s, false); + cirrus_bitblt_common_patterncopy(s); the_end: s->cirrus_srccounter = 0; cirrus_bitblt_reset(s); } else { /* at least one scan line */ do { - (*s->cirrus_rop)(s, s->vga.vram_ptr + s->cirrus_blt_dstaddr, - s->cirrus_bltbuf, 0, 0, s->cirrus_blt_width, 1); + (*s->cirrus_rop)(s, s->cirrus_blt_dstaddr, + 0, 0, 0, s->cirrus_blt_width, 1); cirrus_invalidate_region(s, s->cirrus_blt_dstaddr, 0, s->cirrus_blt_width, 1); s->cirrus_blt_dstaddr += s->cirrus_blt_dstpitch; @@ -966,6 +996,10 @@ static void cirrus_bitblt_start(CirrusVGAState * s) { uint8_t blt_rop; + if (!s->enable_blitter) { + goto bitblt_ignore; + } + s->vga.gr[0x31] |= CIRRUS_BLT_BUSY; s->cirrus_blt_width = (s->vga.gr[0x20] | (s->vga.gr[0x21] << 8)) + 1; @@ -3029,7 +3063,9 @@ static void isa_cirrus_vga_realizefn(DeviceState *dev, Error **errp) static Property isa_cirrus_vga_properties[] = { DEFINE_PROP_UINT32("vgamem_mb", struct ISACirrusVGAState, - cirrus_vga.vga.vram_size_mb, 8), + cirrus_vga.vga.vram_size_mb, 4), + DEFINE_PROP_BOOL("blitter", struct ISACirrusVGAState, + cirrus_vga.enable_blitter, true), DEFINE_PROP_END_OF_LIST(), }; @@ -3098,7 +3134,9 @@ static void pci_cirrus_vga_realize(PCIDevice *dev, Error **errp) static Property pci_vga_cirrus_properties[] = { DEFINE_PROP_UINT32("vgamem_mb", struct PCICirrusVGAState, - cirrus_vga.vga.vram_size_mb, 8), + cirrus_vga.vga.vram_size_mb, 4), + DEFINE_PROP_BOOL("blitter", struct PCICirrusVGAState, + cirrus_vga.enable_blitter, true), DEFINE_PROP_END_OF_LIST(), }; diff --git a/hw/display/cirrus_vga_rop.h b/hw/display/cirrus_vga_rop.h index 0925a009fe..c61a677353 100644 --- a/hw/display/cirrus_vga_rop.h +++ b/hw/display/cirrus_vga_rop.h @@ -22,31 +22,65 @@ * THE SOFTWARE. */ -static inline void glue(rop_8_,ROP_NAME)(uint8_t *dst, uint8_t src) +static inline void glue(rop_8_, ROP_NAME)(CirrusVGAState *s, + uint32_t dstaddr, uint8_t src) { + uint8_t *dst = &s->vga.vram_ptr[dstaddr & s->cirrus_addr_mask]; *dst = ROP_FN(*dst, src); } -static inline void glue(rop_16_,ROP_NAME)(uint16_t *dst, uint16_t src) +static inline void glue(rop_tr_8_, ROP_NAME)(CirrusVGAState *s, + uint32_t dstaddr, uint8_t src, + uint8_t transp) { + uint8_t *dst = &s->vga.vram_ptr[dstaddr & s->cirrus_addr_mask]; + uint8_t pixel = ROP_FN(*dst, src); + if (pixel != transp) { + *dst = pixel; + } +} + +static inline void glue(rop_16_, ROP_NAME)(CirrusVGAState *s, + uint32_t dstaddr, uint16_t src) +{ + uint16_t *dst = (uint16_t *) + (&s->vga.vram_ptr[dstaddr & s->cirrus_addr_mask & ~1]); *dst = ROP_FN(*dst, src); } -static inline void glue(rop_32_,ROP_NAME)(uint32_t *dst, uint32_t src) +static inline void glue(rop_tr_16_, ROP_NAME)(CirrusVGAState *s, + uint32_t dstaddr, uint16_t src, + uint16_t transp) { + uint16_t *dst = (uint16_t *) + (&s->vga.vram_ptr[dstaddr & s->cirrus_addr_mask & ~1]); + uint16_t pixel = ROP_FN(*dst, src); + if (pixel != transp) { + *dst = pixel; + } +} + +static inline void glue(rop_32_, ROP_NAME)(CirrusVGAState *s, + uint32_t dstaddr, uint32_t src) +{ + uint32_t *dst = (uint32_t *) + (&s->vga.vram_ptr[dstaddr & s->cirrus_addr_mask & ~3]); *dst = ROP_FN(*dst, src); } -#define ROP_OP(d, s) glue(rop_8_,ROP_NAME)(d, s) -#define ROP_OP_16(d, s) glue(rop_16_,ROP_NAME)(d, s) -#define ROP_OP_32(d, s) glue(rop_32_,ROP_NAME)(d, s) +#define ROP_OP(st, d, s) glue(rop_8_, ROP_NAME)(st, d, s) +#define ROP_OP_TR(st, d, s, t) glue(rop_tr_8_, ROP_NAME)(st, d, s, t) +#define ROP_OP_16(st, d, s) glue(rop_16_, ROP_NAME)(st, d, s) +#define ROP_OP_TR_16(st, d, s, t) glue(rop_tr_16_, ROP_NAME)(st, d, s, t) +#define ROP_OP_32(st, d, s) glue(rop_32_, ROP_NAME)(st, d, s) #undef ROP_FN static void glue(cirrus_bitblt_rop_fwd_, ROP_NAME)(CirrusVGAState *s, - uint8_t *dst,const uint8_t *src, - int dstpitch,int srcpitch, - int bltwidth,int bltheight) + uint32_t dstaddr, + uint32_t srcaddr, + int dstpitch, int srcpitch, + int bltwidth, int bltheight) { int x,y; dstpitch -= bltwidth; @@ -58,134 +92,139 @@ glue(cirrus_bitblt_rop_fwd_, ROP_NAME)(CirrusVGAState *s, for (y = 0; y < bltheight; y++) { for (x = 0; x < bltwidth; x++) { - ROP_OP(dst, *src); - dst++; - src++; + ROP_OP(s, dstaddr, cirrus_src(s, srcaddr)); + dstaddr++; + srcaddr++; } - dst += dstpitch; - src += srcpitch; + dstaddr += dstpitch; + srcaddr += srcpitch; } } static void glue(cirrus_bitblt_rop_bkwd_, ROP_NAME)(CirrusVGAState *s, - uint8_t *dst,const uint8_t *src, - int dstpitch,int srcpitch, - int bltwidth,int bltheight) + uint32_t dstaddr, + uint32_t srcaddr, + int dstpitch, int srcpitch, + int bltwidth, int bltheight) { int x,y; dstpitch += bltwidth; srcpitch += bltwidth; for (y = 0; y < bltheight; y++) { for (x = 0; x < bltwidth; x++) { - ROP_OP(dst, *src); - dst--; - src--; + ROP_OP(s, dstaddr, cirrus_src(s, srcaddr)); + dstaddr--; + srcaddr--; } - dst += dstpitch; - src += srcpitch; + dstaddr += dstpitch; + srcaddr += srcpitch; } } static void glue(glue(cirrus_bitblt_rop_fwd_transp_, ROP_NAME),_8)(CirrusVGAState *s, - uint8_t *dst,const uint8_t *src, - int dstpitch,int srcpitch, - int bltwidth,int bltheight) + uint32_t dstaddr, + uint32_t srcaddr, + int dstpitch, + int srcpitch, + int bltwidth, + int bltheight) { int x,y; - uint8_t p; + uint8_t transp = s->vga.gr[0x34]; dstpitch -= bltwidth; srcpitch -= bltwidth; + + if (bltheight > 1 && (dstpitch < 0 || srcpitch < 0)) { + return; + } + for (y = 0; y < bltheight; y++) { for (x = 0; x < bltwidth; x++) { - p = *dst; - ROP_OP(&p, *src); - if (p != s->vga.gr[0x34]) *dst = p; - dst++; - src++; + ROP_OP_TR(s, dstaddr, cirrus_src(s, srcaddr), transp); + dstaddr++; + srcaddr++; } - dst += dstpitch; - src += srcpitch; + dstaddr += dstpitch; + srcaddr += srcpitch; } } static void glue(glue(cirrus_bitblt_rop_bkwd_transp_, ROP_NAME),_8)(CirrusVGAState *s, - uint8_t *dst,const uint8_t *src, - int dstpitch,int srcpitch, - int bltwidth,int bltheight) + uint32_t dstaddr, + uint32_t srcaddr, + int dstpitch, + int srcpitch, + int bltwidth, + int bltheight) { int x,y; - uint8_t p; + uint8_t transp = s->vga.gr[0x34]; dstpitch += bltwidth; srcpitch += bltwidth; for (y = 0; y < bltheight; y++) { for (x = 0; x < bltwidth; x++) { - p = *dst; - ROP_OP(&p, *src); - if (p != s->vga.gr[0x34]) *dst = p; - dst--; - src--; + ROP_OP_TR(s, dstaddr, cirrus_src(s, srcaddr), transp); + dstaddr--; + srcaddr--; } - dst += dstpitch; - src += srcpitch; + dstaddr += dstpitch; + srcaddr += srcpitch; } } static void glue(glue(cirrus_bitblt_rop_fwd_transp_, ROP_NAME),_16)(CirrusVGAState *s, - uint8_t *dst,const uint8_t *src, - int dstpitch,int srcpitch, - int bltwidth,int bltheight) + uint32_t dstaddr, + uint32_t srcaddr, + int dstpitch, + int srcpitch, + int bltwidth, + int bltheight) { int x,y; - uint8_t p1, p2; + uint16_t transp = s->vga.gr[0x34] | (uint16_t)s->vga.gr[0x35] << 8; dstpitch -= bltwidth; srcpitch -= bltwidth; + + if (bltheight > 1 && (dstpitch < 0 || srcpitch < 0)) { + return; + } + for (y = 0; y < bltheight; y++) { for (x = 0; x < bltwidth; x+=2) { - p1 = *dst; - p2 = *(dst+1); - ROP_OP(&p1, *src); - ROP_OP(&p2, *(src + 1)); - if ((p1 != s->vga.gr[0x34]) || (p2 != s->vga.gr[0x35])) { - *dst = p1; - *(dst+1) = p2; - } - dst+=2; - src+=2; + ROP_OP_TR_16(s, dstaddr, cirrus_src16(s, srcaddr), transp); + dstaddr += 2; + srcaddr += 2; } - dst += dstpitch; - src += srcpitch; + dstaddr += dstpitch; + srcaddr += srcpitch; } } static void glue(glue(cirrus_bitblt_rop_bkwd_transp_, ROP_NAME),_16)(CirrusVGAState *s, - uint8_t *dst,const uint8_t *src, - int dstpitch,int srcpitch, - int bltwidth,int bltheight) + uint32_t dstaddr, + uint32_t srcaddr, + int dstpitch, + int srcpitch, + int bltwidth, + int bltheight) { int x,y; - uint8_t p1, p2; + uint16_t transp = s->vga.gr[0x34] | (uint16_t)s->vga.gr[0x35] << 8; dstpitch += bltwidth; srcpitch += bltwidth; for (y = 0; y < bltheight; y++) { for (x = 0; x < bltwidth; x+=2) { - p1 = *(dst-1); - p2 = *dst; - ROP_OP(&p1, *(src - 1)); - ROP_OP(&p2, *src); - if ((p1 != s->vga.gr[0x34]) || (p2 != s->vga.gr[0x35])) { - *(dst-1) = p1; - *dst = p2; - } - dst-=2; - src-=2; + ROP_OP_TR_16(s, dstaddr, cirrus_src16(s, srcaddr), transp); + dstaddr -= 2; + srcaddr -= 2; } - dst += dstpitch; - src += srcpitch; + dstaddr += dstpitch; + srcaddr += srcpitch; } } diff --git a/hw/display/cirrus_vga_rop2.h b/hw/display/cirrus_vga_rop2.h index d28bcc6f25..b86bcd6e09 100644 --- a/hw/display/cirrus_vga_rop2.h +++ b/hw/display/cirrus_vga_rop2.h @@ -23,30 +23,32 @@ */ #if DEPTH == 8 -#define PUTPIXEL() ROP_OP(&d[0], col) +#define PUTPIXEL(s, a, c) ROP_OP(s, a, c) #elif DEPTH == 16 -#define PUTPIXEL() ROP_OP_16((uint16_t *)&d[0], col) +#define PUTPIXEL(s, a, c) ROP_OP_16(s, a, c) #elif DEPTH == 24 -#define PUTPIXEL() ROP_OP(&d[0], col); \ - ROP_OP(&d[1], (col >> 8)); \ - ROP_OP(&d[2], (col >> 16)) +#define PUTPIXEL(s, a, c) do { \ + ROP_OP(s, a, c); \ + ROP_OP(s, a + 1, (col >> 8)); \ + ROP_OP(s, a + 2, (col >> 16)); \ + } while (0) #elif DEPTH == 32 -#define PUTPIXEL() ROP_OP_32(((uint32_t *)&d[0]), col) +#define PUTPIXEL(s, a, c) ROP_OP_32(s, a, c) #else #error unsupported DEPTH #endif static void glue(glue(glue(cirrus_patternfill_, ROP_NAME), _),DEPTH) - (CirrusVGAState * s, uint8_t * dst, - const uint8_t * src, + (CirrusVGAState *s, uint32_t dstaddr, + uint32_t srcaddr, int dstpitch, int srcpitch, int bltwidth, int bltheight) { - uint8_t *d; + uint32_t addr; int x, y, pattern_y, pattern_pitch, pattern_x; unsigned int col; - const uint8_t *src1; + uint32_t src1addr; #if DEPTH == 24 int skipleft = s->vga.gr[0x2f] & 0x1f; #else @@ -63,42 +65,44 @@ glue(glue(glue(cirrus_patternfill_, ROP_NAME), _),DEPTH) pattern_y = s->cirrus_blt_srcaddr & 7; for(y = 0; y < bltheight; y++) { pattern_x = skipleft; - d = dst + skipleft; - src1 = src + pattern_y * pattern_pitch; + addr = dstaddr + skipleft; + src1addr = srcaddr + pattern_y * pattern_pitch; for (x = skipleft; x < bltwidth; x += (DEPTH / 8)) { #if DEPTH == 8 - col = src1[pattern_x]; + col = cirrus_src(s, src1addr + pattern_x); pattern_x = (pattern_x + 1) & 7; #elif DEPTH == 16 - col = ((uint16_t *)(src1 + pattern_x))[0]; + col = cirrus_src16(s, src1addr + pattern_x); pattern_x = (pattern_x + 2) & 15; #elif DEPTH == 24 { - const uint8_t *src2 = src1 + pattern_x * 3; - col = src2[0] | (src2[1] << 8) | (src2[2] << 16); + uint32_t src2addr = src1addr + pattern_x * 3; + col = cirrus_src(s, src2addr) | + (cirrus_src(s, src2addr + 1) << 8) | + (cirrus_src(s, src2addr + 2) << 16); pattern_x = (pattern_x + 1) & 7; } #else - col = ((uint32_t *)(src1 + pattern_x))[0]; + col = cirrus_src32(s, src1addr + pattern_x); pattern_x = (pattern_x + 4) & 31; #endif - PUTPIXEL(); - d += (DEPTH / 8); + PUTPIXEL(s, addr, col); + addr += (DEPTH / 8); } pattern_y = (pattern_y + 1) & 7; - dst += dstpitch; + dstaddr += dstpitch; } } /* NOTE: srcpitch is ignored */ static void glue(glue(glue(cirrus_colorexpand_transp_, ROP_NAME), _),DEPTH) - (CirrusVGAState * s, uint8_t * dst, - const uint8_t * src, + (CirrusVGAState *s, uint32_t dstaddr, + uint32_t srcaddr, int dstpitch, int srcpitch, int bltwidth, int bltheight) { - uint8_t *d; + uint32_t addr; int x, y; unsigned bits, bits_xor; unsigned int col; @@ -122,33 +126,33 @@ glue(glue(glue(cirrus_colorexpand_transp_, ROP_NAME), _),DEPTH) for(y = 0; y < bltheight; y++) { bitmask = 0x80 >> srcskipleft; - bits = *src++ ^ bits_xor; - d = dst + dstskipleft; + bits = cirrus_src(s, srcaddr++) ^ bits_xor; + addr = dstaddr + dstskipleft; for (x = dstskipleft; x < bltwidth; x += (DEPTH / 8)) { if ((bitmask & 0xff) == 0) { bitmask = 0x80; - bits = *src++ ^ bits_xor; + bits = cirrus_src(s, srcaddr++) ^ bits_xor; } index = (bits & bitmask); if (index) { - PUTPIXEL(); + PUTPIXEL(s, addr, col); } - d += (DEPTH / 8); + addr += (DEPTH / 8); bitmask >>= 1; } - dst += dstpitch; + dstaddr += dstpitch; } } static void glue(glue(glue(cirrus_colorexpand_, ROP_NAME), _),DEPTH) - (CirrusVGAState * s, uint8_t * dst, - const uint8_t * src, + (CirrusVGAState *s, uint32_t dstaddr, + uint32_t srcaddr, int dstpitch, int srcpitch, int bltwidth, int bltheight) { uint32_t colors[2]; - uint8_t *d; + uint32_t addr; int x, y; unsigned bits; unsigned int col; @@ -160,30 +164,30 @@ glue(glue(glue(cirrus_colorexpand_, ROP_NAME), _),DEPTH) colors[1] = s->cirrus_blt_fgcol; for(y = 0; y < bltheight; y++) { bitmask = 0x80 >> srcskipleft; - bits = *src++; - d = dst + dstskipleft; + bits = cirrus_src(s, srcaddr++); + addr = dstaddr + dstskipleft; for (x = dstskipleft; x < bltwidth; x += (DEPTH / 8)) { if ((bitmask & 0xff) == 0) { bitmask = 0x80; - bits = *src++; + bits = cirrus_src(s, srcaddr++); } col = colors[!!(bits & bitmask)]; - PUTPIXEL(); - d += (DEPTH / 8); + PUTPIXEL(s, addr, col); + addr += (DEPTH / 8); bitmask >>= 1; } - dst += dstpitch; + dstaddr += dstpitch; } } static void glue(glue(glue(cirrus_colorexpand_pattern_transp_, ROP_NAME), _),DEPTH) - (CirrusVGAState * s, uint8_t * dst, - const uint8_t * src, + (CirrusVGAState *s, uint32_t dstaddr, + uint32_t srcaddr, int dstpitch, int srcpitch, int bltwidth, int bltheight) { - uint8_t *d; + uint32_t addr; int x, y, bitpos, pattern_y; unsigned int bits, bits_xor; unsigned int col; @@ -205,30 +209,30 @@ glue(glue(glue(cirrus_colorexpand_pattern_transp_, ROP_NAME), _),DEPTH) pattern_y = s->cirrus_blt_srcaddr & 7; for(y = 0; y < bltheight; y++) { - bits = src[pattern_y] ^ bits_xor; + bits = cirrus_src(s, srcaddr + pattern_y) ^ bits_xor; bitpos = 7 - srcskipleft; - d = dst + dstskipleft; + addr = dstaddr + dstskipleft; for (x = dstskipleft; x < bltwidth; x += (DEPTH / 8)) { if ((bits >> bitpos) & 1) { - PUTPIXEL(); + PUTPIXEL(s, addr, col); } - d += (DEPTH / 8); + addr += (DEPTH / 8); bitpos = (bitpos - 1) & 7; } pattern_y = (pattern_y + 1) & 7; - dst += dstpitch; + dstaddr += dstpitch; } } static void glue(glue(glue(cirrus_colorexpand_pattern_, ROP_NAME), _),DEPTH) - (CirrusVGAState * s, uint8_t * dst, - const uint8_t * src, + (CirrusVGAState *s, uint32_t dstaddr, + uint32_t srcaddr, int dstpitch, int srcpitch, int bltwidth, int bltheight) { uint32_t colors[2]; - uint8_t *d; + uint32_t addr; int x, y, bitpos, pattern_y; unsigned int bits; unsigned int col; @@ -240,40 +244,39 @@ glue(glue(glue(cirrus_colorexpand_pattern_, ROP_NAME), _),DEPTH) pattern_y = s->cirrus_blt_srcaddr & 7; for(y = 0; y < bltheight; y++) { - bits = src[pattern_y]; + bits = cirrus_src(s, srcaddr + pattern_y); bitpos = 7 - srcskipleft; - d = dst + dstskipleft; + addr = dstaddr + dstskipleft; for (x = dstskipleft; x < bltwidth; x += (DEPTH / 8)) { col = colors[(bits >> bitpos) & 1]; - PUTPIXEL(); - d += (DEPTH / 8); + PUTPIXEL(s, addr, col); + addr += (DEPTH / 8); bitpos = (bitpos - 1) & 7; } pattern_y = (pattern_y + 1) & 7; - dst += dstpitch; + dstaddr += dstpitch; } } static void glue(glue(glue(cirrus_fill_, ROP_NAME), _),DEPTH) (CirrusVGAState *s, - uint8_t *dst, int dst_pitch, + uint32_t dstaddr, int dst_pitch, int width, int height) { - uint8_t *d, *d1; + uint32_t addr; uint32_t col; int x, y; col = s->cirrus_blt_fgcol; - d1 = dst; for(y = 0; y < height; y++) { - d = d1; + addr = dstaddr; for(x = 0; x < width; x += (DEPTH / 8)) { - PUTPIXEL(); - d += (DEPTH / 8); + PUTPIXEL(s, addr, col); + addr += (DEPTH / 8); } - d1 += dst_pitch; + dstaddr += dst_pitch; } } diff --git a/hw/i386/kvm/clock.c b/hw/i386/kvm/clock.c index ef9d560f9c..13eca374cd 100644 --- a/hw/i386/kvm/clock.c +++ b/hw/i386/kvm/clock.c @@ -22,6 +22,7 @@ #include "kvm_i386.h" #include "hw/sysbus.h" #include "hw/kvm/clock.h" +#include "qapi/error.h" #include <linux/kvm.h> #include <linux/kvm_para.h> @@ -208,6 +209,11 @@ static void kvmclock_realize(DeviceState *dev, Error **errp) { KVMClockState *s = KVM_CLOCK(dev); + if (!kvm_enabled()) { + error_setg(errp, "kvmclock device requires KVM"); + return; + } + kvm_update_clock(s); qemu_add_vm_change_state_handler(kvmclock_vm_state_change, s); diff --git a/hw/ide/ahci.c b/hw/ide/ahci.c index 6a17acf639..f60826d6e0 100644 --- a/hw/ide/ahci.c +++ b/hw/ide/ahci.c @@ -1485,6 +1485,18 @@ void ahci_realize(AHCIState *s, DeviceState *qdev, AddressSpace *as, int ports) void ahci_uninit(AHCIState *s) { + int i, j; + + for (i = 0; i < s->ports; i++) { + AHCIDevice *ad = &s->dev[i]; + + for (j = 0; j < 2; j++) { + IDEState *s = &ad->port.ifs[j]; + + ide_exit(s); + } + } + g_free(s->dev); } diff --git a/hw/ide/core.c b/hw/ide/core.c index db509b3e15..0b48b64d3a 100644 --- a/hw/ide/core.c +++ b/hw/ide/core.c @@ -2603,6 +2603,14 @@ void ide_init2(IDEBus *bus, qemu_irq irq) bus->dma = &ide_dma_nop; } +void ide_exit(IDEState *s) +{ + timer_del(s->sector_write_timer); + timer_free(s->sector_write_timer); + qemu_vfree(s->smart_selftest_data); + qemu_vfree(s->io_buffer); +} + static const MemoryRegionPortio ide_portio_list[] = { { 0, 8, 1, .read = ide_ioport_read, .write = ide_ioport_write }, { 0, 1, 2, .read = ide_data_readw, .write = ide_data_writew }, diff --git a/hw/ide/qdev.c b/hw/ide/qdev.c index 4383cd111d..299e592fa2 100644 --- a/hw/ide/qdev.c +++ b/hw/ide/qdev.c @@ -31,7 +31,7 @@ /* --------------------------------- */ static char *idebus_get_fw_dev_path(DeviceState *dev); -static void idebus_unrealize(DeviceState *qdev, Error **errp); +static void idebus_unrealize(BusState *qdev, Error **errp); static Property ide_props[] = { DEFINE_PROP_UINT32("unit", IDEDevice, unit, -1), @@ -43,14 +43,15 @@ static void ide_bus_class_init(ObjectClass *klass, void *data) BusClass *k = BUS_CLASS(klass); k->get_fw_dev_path = idebus_get_fw_dev_path; + k->unrealize = idebus_unrealize; } -static void idebus_unrealize(DeviceState *qdev, Error **errp) +static void idebus_unrealize(BusState *bus, Error **errp) { - IDEBus *bus = DO_UPCAST(IDEBus, qbus, qdev->parent_bus); + IDEBus *ibus = IDE_BUS(bus); - if (bus->vmstate) { - qemu_del_vm_change_state_handler(bus->vmstate); + if (ibus->vmstate) { + qemu_del_vm_change_state_handler(ibus->vmstate); } } @@ -370,7 +371,6 @@ static void ide_device_class_init(ObjectClass *klass, void *data) k->init = ide_qdev_init; set_bit(DEVICE_CATEGORY_STORAGE, k->categories); k->bus_type = TYPE_IDE_BUS; - k->unrealize = idebus_unrealize; k->props = ide_props; } diff --git a/hw/intc/arm_gic.c b/hw/intc/arm_gic.c index 8e5a9d8a3e..b305d9032a 100644 --- a/hw/intc/arm_gic.c +++ b/hw/intc/arm_gic.c @@ -26,15 +26,20 @@ #include "qemu/log.h" #include "trace.h" -//#define DEBUG_GIC +/* #define DEBUG_GIC */ #ifdef DEBUG_GIC -#define DPRINTF(fmt, ...) \ -do { fprintf(stderr, "arm_gic: " fmt , ## __VA_ARGS__); } while (0) +#define DEBUG_GIC_GATE 1 #else -#define DPRINTF(fmt, ...) do {} while(0) +#define DEBUG_GIC_GATE 0 #endif +#define DPRINTF(fmt, ...) do { \ + if (DEBUG_GIC_GATE) { \ + fprintf(stderr, "%s: " fmt, __func__, ## __VA_ARGS__); \ + } \ + } while (0) + static const uint8_t gic_id_11mpcore[] = { 0x00, 0x00, 0x00, 0x00, 0x90, 0x13, 0x04, 0x00, 0x0d, 0xf0, 0x05, 0xb1 }; diff --git a/hw/misc/imx6_src.c b/hw/misc/imx6_src.c index edbb756c36..cfb08710fb 100644 --- a/hw/misc/imx6_src.c +++ b/hw/misc/imx6_src.c @@ -143,13 +143,17 @@ static void imx6_defer_clear_reset_bit(int cpuid, unsigned long reset_shift) { struct SRCSCRResetInfo *ri; + CPUState *cpu = arm_get_cpu_by_id(cpuid); + + if (!cpu) { + return; + } ri = g_malloc(sizeof(struct SRCSCRResetInfo)); ri->s = s; ri->reset_bit = reset_shift; - async_run_on_cpu(arm_get_cpu_by_id(cpuid), imx6_clear_reset_bit, - RUN_ON_CPU_HOST_PTR(ri)); + async_run_on_cpu(cpu, imx6_clear_reset_bit, RUN_ON_CPU_HOST_PTR(ri)); } diff --git a/hw/net/e1000e.c b/hw/net/e1000e.c index b0f429b8e5..6e234938db 100644 --- a/hw/net/e1000e.c +++ b/hw/net/e1000e.c @@ -306,7 +306,7 @@ e1000e_init_msix(E1000EState *s) static void e1000e_cleanup_msix(E1000EState *s) { - if (msix_enabled(PCI_DEVICE(s))) { + if (msix_present(PCI_DEVICE(s))) { e1000e_unuse_msix_vectors(s, E1000E_MSIX_VEC_NUM); msix_uninit(PCI_DEVICE(s), &s->msix, &s->msix); } diff --git a/hw/net/mcf_fec.c b/hw/net/mcf_fec.c index a3eca7e0f5..bfa6b4bcce 100644 --- a/hw/net/mcf_fec.c +++ b/hw/net/mcf_fec.c @@ -27,6 +27,7 @@ do { printf("mcf_fec: " fmt , ## __VA_ARGS__); } while (0) #define FEC_MAX_DESC 1024 #define FEC_MAX_FRAME_SIZE 2032 +#define FEC_MIB_SIZE 64 typedef struct { SysBusDevice parent_obj; @@ -51,6 +52,7 @@ typedef struct { uint32_t erdsr; uint32_t etdsr; uint32_t emrbr; + uint32_t mib[FEC_MIB_SIZE]; } mcf_fec_state; #define FEC_INT_HB 0x80000000 @@ -111,6 +113,63 @@ typedef struct { #define FEC_BD_OV 0x0002 #define FEC_BD_TR 0x0001 +#define MIB_RMON_T_DROP 0 +#define MIB_RMON_T_PACKETS 1 +#define MIB_RMON_T_BC_PKT 2 +#define MIB_RMON_T_MC_PKT 3 +#define MIB_RMON_T_CRC_ALIGN 4 +#define MIB_RMON_T_UNDERSIZE 5 +#define MIB_RMON_T_OVERSIZE 6 +#define MIB_RMON_T_FRAG 7 +#define MIB_RMON_T_JAB 8 +#define MIB_RMON_T_COL 9 +#define MIB_RMON_T_P64 10 +#define MIB_RMON_T_P65TO127 11 +#define MIB_RMON_T_P128TO255 12 +#define MIB_RMON_T_P256TO511 13 +#define MIB_RMON_T_P512TO1023 14 +#define MIB_RMON_T_P1024TO2047 15 +#define MIB_RMON_T_P_GTE2048 16 +#define MIB_RMON_T_OCTETS 17 +#define MIB_IEEE_T_DROP 18 +#define MIB_IEEE_T_FRAME_OK 19 +#define MIB_IEEE_T_1COL 20 +#define MIB_IEEE_T_MCOL 21 +#define MIB_IEEE_T_DEF 22 +#define MIB_IEEE_T_LCOL 23 +#define MIB_IEEE_T_EXCOL 24 +#define MIB_IEEE_T_MACERR 25 +#define MIB_IEEE_T_CSERR 26 +#define MIB_IEEE_T_SQE 27 +#define MIB_IEEE_T_FDXFC 28 +#define MIB_IEEE_T_OCTETS_OK 29 + +#define MIB_RMON_R_DROP 32 +#define MIB_RMON_R_PACKETS 33 +#define MIB_RMON_R_BC_PKT 34 +#define MIB_RMON_R_MC_PKT 35 +#define MIB_RMON_R_CRC_ALIGN 36 +#define MIB_RMON_R_UNDERSIZE 37 +#define MIB_RMON_R_OVERSIZE 38 +#define MIB_RMON_R_FRAG 39 +#define MIB_RMON_R_JAB 40 +#define MIB_RMON_R_RESVD_0 41 +#define MIB_RMON_R_P64 42 +#define MIB_RMON_R_P65TO127 43 +#define MIB_RMON_R_P128TO255 44 +#define MIB_RMON_R_P256TO511 45 +#define MIB_RMON_R_P512TO1023 46 +#define MIB_RMON_R_P1024TO2047 47 +#define MIB_RMON_R_P_GTE2048 48 +#define MIB_RMON_R_OCTETS 49 +#define MIB_IEEE_R_DROP 50 +#define MIB_IEEE_R_FRAME_OK 51 +#define MIB_IEEE_R_CRC 52 +#define MIB_IEEE_R_ALIGN 53 +#define MIB_IEEE_R_MACERR 54 +#define MIB_IEEE_R_FDXFC 55 +#define MIB_IEEE_R_OCTETS_OK 56 + static void mcf_fec_read_bd(mcf_fec_bd *bd, uint32_t addr) { cpu_physical_memory_read(addr, bd, sizeof(*bd)); @@ -147,6 +206,31 @@ static void mcf_fec_update(mcf_fec_state *s) s->irq_state = active; } +static void mcf_fec_tx_stats(mcf_fec_state *s, int size) +{ + s->mib[MIB_RMON_T_PACKETS]++; + s->mib[MIB_RMON_T_OCTETS] += size; + if (size < 64) { + s->mib[MIB_RMON_T_FRAG]++; + } else if (size == 64) { + s->mib[MIB_RMON_T_P64]++; + } else if (size < 128) { + s->mib[MIB_RMON_T_P65TO127]++; + } else if (size < 256) { + s->mib[MIB_RMON_T_P128TO255]++; + } else if (size < 512) { + s->mib[MIB_RMON_T_P256TO511]++; + } else if (size < 1024) { + s->mib[MIB_RMON_T_P512TO1023]++; + } else if (size < 2048) { + s->mib[MIB_RMON_T_P1024TO2047]++; + } else { + s->mib[MIB_RMON_T_P_GTE2048]++; + } + s->mib[MIB_IEEE_T_FRAME_OK]++; + s->mib[MIB_IEEE_T_OCTETS_OK] += size; +} + static void mcf_fec_do_tx(mcf_fec_state *s) { uint32_t addr; @@ -180,6 +264,7 @@ static void mcf_fec_do_tx(mcf_fec_state *s) /* Last buffer in frame. */ DPRINTF("Sending packet\n"); qemu_send_packet(qemu_get_queue(s->nic), frame, frame_size); + mcf_fec_tx_stats(s, frame_size); ptr = frame; frame_size = 0; s->eir |= FEC_INT_TXF; @@ -302,6 +387,7 @@ static uint64_t mcf_fec_read(void *opaque, hwaddr addr, case 0x180: return s->erdsr; case 0x184: return s->etdsr; case 0x188: return s->emrbr; + case 0x200 ... 0x2e0: return s->mib[(addr & 0x1ff) / 4]; default: hw_error("mcf_fec_read: Bad address 0x%x\n", (int)addr); return 0; @@ -399,12 +485,40 @@ static void mcf_fec_write(void *opaque, hwaddr addr, case 0x188: s->emrbr = value > 0 ? value & 0x7F0 : 0x7F0; break; + case 0x200 ... 0x2e0: + s->mib[(addr & 0x1ff) / 4] = value; + break; default: hw_error("mcf_fec_write Bad address 0x%x\n", (int)addr); } mcf_fec_update(s); } +static void mcf_fec_rx_stats(mcf_fec_state *s, int size) +{ + s->mib[MIB_RMON_R_PACKETS]++; + s->mib[MIB_RMON_R_OCTETS] += size; + if (size < 64) { + s->mib[MIB_RMON_R_FRAG]++; + } else if (size == 64) { + s->mib[MIB_RMON_R_P64]++; + } else if (size < 128) { + s->mib[MIB_RMON_R_P65TO127]++; + } else if (size < 256) { + s->mib[MIB_RMON_R_P128TO255]++; + } else if (size < 512) { + s->mib[MIB_RMON_R_P256TO511]++; + } else if (size < 1024) { + s->mib[MIB_RMON_R_P512TO1023]++; + } else if (size < 2048) { + s->mib[MIB_RMON_R_P1024TO2047]++; + } else { + s->mib[MIB_RMON_R_P_GTE2048]++; + } + s->mib[MIB_IEEE_R_FRAME_OK]++; + s->mib[MIB_IEEE_R_OCTETS_OK] += size; +} + static int mcf_fec_have_receive_space(mcf_fec_state *s, size_t want) { mcf_fec_bd bd; @@ -500,6 +614,7 @@ static ssize_t mcf_fec_receive(NetClientState *nc, const uint8_t *buf, size_t si } } s->rx_descriptor = addr; + mcf_fec_rx_stats(s, retsize); mcf_fec_enable_rx(s); mcf_fec_update(s); return retsize; diff --git a/hw/pci/pci.c b/hw/pci/pci.c index 273f1e4602..e6b08e1988 100644 --- a/hw/pci/pci.c +++ b/hw/pci/pci.c @@ -64,6 +64,8 @@ static Property pci_props[] = { QEMU_PCI_CAP_SERR_BITNR, true), DEFINE_PROP_BIT("x-pcie-lnksta-dllla", PCIDevice, cap_present, QEMU_PCIE_LNKSTA_DLLLA_BITNR, true), + DEFINE_PROP_BIT("x-pcie-extcap-init", PCIDevice, cap_present, + QEMU_PCIE_EXTCAP_INIT_BITNR, true), DEFINE_PROP_END_OF_LIST() }; @@ -88,8 +90,8 @@ static void pci_init_bus_master(PCIDevice *pci_dev) OBJECT(pci_dev), "bus master", dma_as->root, 0, memory_region_size(dma_as->root)); memory_region_set_enabled(&pci_dev->bus_master_enable_region, false); - address_space_init(&pci_dev->bus_master_as, - &pci_dev->bus_master_enable_region, pci_dev->name); + memory_region_add_subregion(&pci_dev->bus_master_container_region, 0, + &pci_dev->bus_master_enable_region); } static void pcibus_machine_done(Notifier *notifier, void *data) @@ -995,6 +997,11 @@ static PCIDevice *do_pci_register_device(PCIDevice *pci_dev, PCIBus *bus, pci_dev->devfn = devfn; pci_dev->requester_id_cache = pci_req_id_cache_get(pci_dev); + memory_region_init(&pci_dev->bus_master_container_region, OBJECT(pci_dev), + "bus master container", UINT64_MAX); + address_space_init(&pci_dev->bus_master_as, + &pci_dev->bus_master_container_region, pci_dev->name); + if (qdev_hotplug) { pci_init_bus_master(pci_dev); } diff --git a/hw/pci/pcie.c b/hw/pci/pcie.c index fc54bfd53d..18e634f577 100644 --- a/hw/pci/pcie.c +++ b/hw/pci/pcie.c @@ -109,6 +109,12 @@ int pcie_cap_init(PCIDevice *dev, uint8_t offset, uint8_t type, uint8_t port) PCI_EXP_DEVCAP2_EFF | PCI_EXP_DEVCAP2_EETLPP); pci_set_word(dev->wmask + pos + PCI_EXP_DEVCTL2, PCI_EXP_DEVCTL2_EETLPPB); + + if (dev->cap_present & QEMU_PCIE_EXTCAP_INIT) { + /* read-only to behave like a 'NULL' Extended Capability Header */ + pci_set_long(dev->wmask + PCI_CONFIG_SPACE_SIZE, 0); + } + return pos; } @@ -217,6 +223,20 @@ void pcie_cap_deverr_reset(PCIDevice *dev) PCI_EXP_DEVCTL_FERE | PCI_EXP_DEVCTL_URRE); } +void pcie_cap_lnkctl_init(PCIDevice *dev) +{ + uint32_t pos = dev->exp.exp_cap; + pci_long_test_and_set_mask(dev->wmask + pos + PCI_EXP_LNKCTL, + PCI_EXP_LNKCTL_CCC | PCI_EXP_LNKCTL_ES); +} + +void pcie_cap_lnkctl_reset(PCIDevice *dev) +{ + uint8_t *lnkctl = dev->config + dev->exp.exp_cap + PCI_EXP_LNKCTL; + pci_long_test_and_clear_mask(lnkctl, + PCI_EXP_LNKCTL_CCC | PCI_EXP_LNKCTL_ES); +} + static void hotplug_event_update_event_status(PCIDevice *dev) { uint32_t pos = dev->exp.exp_cap; diff --git a/hw/ppc/pnv.c b/hw/ppc/pnv.c index 09f0d22def..3fa722af82 100644 --- a/hw/ppc/pnv.c +++ b/hw/ppc/pnv.c @@ -21,6 +21,7 @@ #include "qapi/error.h" #include "sysemu/sysemu.h" #include "sysemu/numa.h" +#include "sysemu/cpus.h" #include "hw/hw.h" #include "target/ppc/cpu.h" #include "qemu/log.h" diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c index c3bb991605..6ee566d658 100644 --- a/hw/ppc/spapr.c +++ b/hw/ppc/spapr.c @@ -3163,8 +3163,13 @@ DEFINE_SPAPR_MACHINE(2_9, "2.9", true); /* * pseries-2.8 */ -#define SPAPR_COMPAT_2_8 \ - HW_COMPAT_2_8 +#define SPAPR_COMPAT_2_8 \ + HW_COMPAT_2_8 \ + { \ + .driver = TYPE_SPAPR_PCI_HOST_BRIDGE, \ + .property = "pcie-extended-configuration-space", \ + .value = "off", \ + }, static void spapr_machine_2_8_instance_options(MachineState *machine) { diff --git a/hw/ppc/spapr_pci.c b/hw/ppc/spapr_pci.c index 919d3c2c59..98c52e411f 100644 --- a/hw/ppc/spapr_pci.c +++ b/hw/ppc/spapr_pci.c @@ -1321,7 +1321,7 @@ static int spapr_populate_pci_child_dt(PCIDevice *dev, void *fdt, int offset, _FDT(fdt_setprop(fdt, offset, "assigned-addresses", (uint8_t *)rp.assigned, rp.assigned_len)); - if (pci_is_express(dev)) { + if (sphb->pcie_ecs && pci_is_express(dev)) { _FDT(fdt_setprop_cell(fdt, offset, "ibm,pci-config-space-type", 0x1)); } @@ -1858,6 +1858,8 @@ static Property spapr_phb_properties[] = { DEFINE_PROP_UINT32("numa_node", sPAPRPHBState, numa_node, -1), DEFINE_PROP_BOOL("pre-2.8-migration", sPAPRPHBState, pre_2_8_migration, false), + DEFINE_PROP_BOOL("pcie-extended-configuration-space", sPAPRPHBState, + pcie_ecs, true), DEFINE_PROP_END_OF_LIST(), }; diff --git a/hw/scsi/mptsas.c b/hw/scsi/mptsas.c index 2e091c0156..765ab53c34 100644 --- a/hw/scsi/mptsas.c +++ b/hw/scsi/mptsas.c @@ -756,7 +756,7 @@ static void mptsas_fetch_request(MPTSASState *s) /* Read the message header from the guest first. */ addr = s->host_mfa_high_addr | MPTSAS_FIFO_GET(s, request_post); - pci_dma_read(pci, addr, req, sizeof(hdr)); + pci_dma_read(pci, addr, req, sizeof(*hdr)); if (hdr->Function < ARRAY_SIZE(mpi_request_sizes) && mpi_request_sizes[hdr->Function]) { @@ -766,8 +766,8 @@ static void mptsas_fetch_request(MPTSASState *s) */ size = mpi_request_sizes[hdr->Function]; assert(size <= MPTSAS_MAX_REQUEST_SIZE); - pci_dma_read(pci, addr + sizeof(hdr), &req[sizeof(hdr)], - size - sizeof(hdr)); + pci_dma_read(pci, addr + sizeof(*hdr), &req[sizeof(*hdr)], + size - sizeof(*hdr)); } if (hdr->Function == MPI_FUNCTION_SCSI_IO_REQUEST) { diff --git a/hw/sparc/sun4m.c b/hw/sparc/sun4m.c index 61416a6426..873cd7df9a 100644 --- a/hw/sparc/sun4m.c +++ b/hw/sparc/sun4m.c @@ -142,6 +142,9 @@ void cpu_check_irqs(CPUSPARCState *env) { CPUState *cs; + /* We should be holding the BQL before we mess with IRQs */ + g_assert(qemu_mutex_iothread_locked()); + if (env->pil_in && (env->interrupt_index == 0 || (env->interrupt_index & ~15) == TT_EXTINT)) { unsigned int i; diff --git a/hw/sparc64/sparc64.c b/hw/sparc64/sparc64.c index b3d219c769..4e4fdab065 100644 --- a/hw/sparc64/sparc64.c +++ b/hw/sparc64/sparc64.c @@ -55,6 +55,9 @@ void cpu_check_irqs(CPUSPARCState *env) uint32_t pil = env->pil_in | (env->softint & ~(SOFTINT_TIMER | SOFTINT_STIMER)); + /* We should be holding the BQL before we mess with IRQs */ + g_assert(qemu_mutex_iothread_locked()); + /* TT_IVEC has a higher priority (16) than TT_EXTINT (31..17) */ if (env->ivec_status & 0x20) { return; diff --git a/hw/virtio/virtio-pci.c b/hw/virtio/virtio-pci.c index b76f3f62a0..f9b7244808 100644 --- a/hw/virtio/virtio-pci.c +++ b/hw/virtio/virtio-pci.c @@ -1153,7 +1153,7 @@ static AddressSpace *virtio_pci_get_dma_as(DeviceState *d) VirtIOPCIProxy *proxy = VIRTIO_PCI(d); PCIDevice *dev = &proxy->pci_dev; - return pci_device_iommu_address_space(dev); + return pci_get_address_space(dev); } static int virtio_pci_add_mem_cap(VirtIOPCIProxy *proxy, @@ -1812,6 +1812,7 @@ static void virtio_pci_realize(PCIDevice *pci_dev, Error **errp) pos = pci_add_capability(pci_dev, PCI_CAP_ID_PM, 0, PCI_PM_SIZEOF); assert(pos > 0); + pci_dev->exp.pm_cap = pos; /* * Indicates that this function complies with revision 1.2 of the @@ -1819,6 +1820,22 @@ static void virtio_pci_realize(PCIDevice *pci_dev, Error **errp) */ pci_set_word(pci_dev->config + pos + PCI_PM_PMC, 0x3); + if (proxy->flags & VIRTIO_PCI_FLAG_INIT_DEVERR) { + /* Init error enabling flags */ + pcie_cap_deverr_init(pci_dev); + } + + if (proxy->flags & VIRTIO_PCI_FLAG_INIT_LNKCTL) { + /* Init Link Control Register */ + pcie_cap_lnkctl_init(pci_dev); + } + + if (proxy->flags & VIRTIO_PCI_FLAG_INIT_PM) { + /* Init Power Management Control Register */ + pci_set_word(pci_dev->wmask + pos + PCI_PM_CTRL, + PCI_PM_CTRL_STATE_MASK); + } + if (proxy->flags & VIRTIO_PCI_FLAG_ATS) { pcie_ats_init(pci_dev, 256); } @@ -1849,6 +1866,7 @@ static void virtio_pci_reset(DeviceState *qdev) { VirtIOPCIProxy *proxy = VIRTIO_PCI(qdev); VirtioBusState *bus = VIRTIO_BUS(&proxy->bus); + PCIDevice *dev = PCI_DEVICE(qdev); int i; virtio_pci_stop_ioeventfd(proxy); @@ -1857,6 +1875,17 @@ static void virtio_pci_reset(DeviceState *qdev) for (i = 0; i < VIRTIO_QUEUE_MAX; i++) { proxy->vqs[i].enabled = 0; + proxy->vqs[i].num = 0; + proxy->vqs[i].desc[0] = proxy->vqs[i].desc[1] = 0; + proxy->vqs[i].avail[0] = proxy->vqs[i].avail[1] = 0; + proxy->vqs[i].used[0] = proxy->vqs[i].used[1] = 0; + } + + if (pci_is_express(dev)) { + pcie_cap_deverr_reset(dev); + pcie_cap_lnkctl_reset(dev); + + pci_set_word(dev->config + dev->exp.pm_cap + PCI_PM_CTRL, 0); } } @@ -1878,6 +1907,12 @@ static Property virtio_pci_properties[] = { ignore_backend_features, false), DEFINE_PROP_BIT("ats", VirtIOPCIProxy, flags, VIRTIO_PCI_FLAG_ATS_BIT, false), + DEFINE_PROP_BIT("x-pcie-deverr-init", VirtIOPCIProxy, flags, + VIRTIO_PCI_FLAG_INIT_DEVERR_BIT, true), + DEFINE_PROP_BIT("x-pcie-lnkctl-init", VirtIOPCIProxy, flags, + VIRTIO_PCI_FLAG_INIT_LNKCTL_BIT, true), + DEFINE_PROP_BIT("x-pcie-pm-init", VirtIOPCIProxy, flags, + VIRTIO_PCI_FLAG_INIT_PM_BIT, true), DEFINE_PROP_END_OF_LIST(), }; diff --git a/hw/virtio/virtio-pci.h b/hw/virtio/virtio-pci.h index d00064cc0c..b095dfc6d9 100644 --- a/hw/virtio/virtio-pci.h +++ b/hw/virtio/virtio-pci.h @@ -73,6 +73,9 @@ enum { VIRTIO_PCI_FLAG_DISABLE_PCIE_BIT, VIRTIO_PCI_FLAG_PAGE_PER_VQ_BIT, VIRTIO_PCI_FLAG_ATS_BIT, + VIRTIO_PCI_FLAG_INIT_DEVERR_BIT, + VIRTIO_PCI_FLAG_INIT_LNKCTL_BIT, + VIRTIO_PCI_FLAG_INIT_PM_BIT, }; /* Need to activate work-arounds for buggy guests at vmstate load. */ @@ -100,6 +103,15 @@ enum { /* address space translation service */ #define VIRTIO_PCI_FLAG_ATS (1 << VIRTIO_PCI_FLAG_ATS_BIT) +/* Init error enabling flags */ +#define VIRTIO_PCI_FLAG_INIT_DEVERR (1 << VIRTIO_PCI_FLAG_INIT_DEVERR_BIT) + +/* Init Link Control register */ +#define VIRTIO_PCI_FLAG_INIT_LNKCTL (1 << VIRTIO_PCI_FLAG_INIT_LNKCTL_BIT) + +/* Init Power Management */ +#define VIRTIO_PCI_FLAG_INIT_PM (1 << VIRTIO_PCI_FLAG_INIT_PM_BIT) + typedef struct { MSIMessage msg; int virq; diff --git a/hw/virtio/virtio.c b/hw/virtio/virtio.c index efce4b343a..82b6060b2a 100644 --- a/hw/virtio/virtio.c +++ b/hw/virtio/virtio.c @@ -131,6 +131,7 @@ static void virtio_init_region_cache(VirtIODevice *vdev, int n) VRingMemoryRegionCaches *new; hwaddr addr, size; int event_size; + int64_t len; event_size = virtio_vdev_has_feature(vq->vdev, VIRTIO_RING_F_EVENT_IDX) ? 2 : 0; @@ -140,21 +141,41 @@ static void virtio_init_region_cache(VirtIODevice *vdev, int n) } new = g_new0(VRingMemoryRegionCaches, 1); size = virtio_queue_get_desc_size(vdev, n); - address_space_cache_init(&new->desc, vdev->dma_as, - addr, size, false); + len = address_space_cache_init(&new->desc, vdev->dma_as, + addr, size, false); + if (len < size) { + virtio_error(vdev, "Cannot map desc"); + goto err_desc; + } size = virtio_queue_get_used_size(vdev, n) + event_size; - address_space_cache_init(&new->used, vdev->dma_as, - vq->vring.used, size, true); + len = address_space_cache_init(&new->used, vdev->dma_as, + vq->vring.used, size, true); + if (len < size) { + virtio_error(vdev, "Cannot map used"); + goto err_used; + } size = virtio_queue_get_avail_size(vdev, n) + event_size; - address_space_cache_init(&new->avail, vdev->dma_as, - vq->vring.avail, size, false); + len = address_space_cache_init(&new->avail, vdev->dma_as, + vq->vring.avail, size, false); + if (len < size) { + virtio_error(vdev, "Cannot map avail"); + goto err_avail; + } atomic_rcu_set(&vq->vring.caches, new); if (old) { call_rcu(old, virtio_free_region_cache, rcu); } + return; + +err_avail: + address_space_cache_destroy(&new->used); +err_used: + address_space_cache_destroy(&new->desc); +err_desc: + g_free(new); } /* virt queue functions */ @@ -185,10 +206,16 @@ static void vring_desc_read(VirtIODevice *vdev, VRingDesc *desc, virtio_tswap16s(vdev, &desc->next); } +static VRingMemoryRegionCaches *vring_get_region_caches(struct VirtQueue *vq) +{ + VRingMemoryRegionCaches *caches = atomic_rcu_read(&vq->vring.caches); + assert(caches != NULL); + return caches; +} /* Called within rcu_read_lock(). */ static inline uint16_t vring_avail_flags(VirtQueue *vq) { - VRingMemoryRegionCaches *caches = atomic_rcu_read(&vq->vring.caches); + VRingMemoryRegionCaches *caches = vring_get_region_caches(vq); hwaddr pa = offsetof(VRingAvail, flags); return virtio_lduw_phys_cached(vq->vdev, &caches->avail, pa); } @@ -196,7 +223,7 @@ static inline uint16_t vring_avail_flags(VirtQueue *vq) /* Called within rcu_read_lock(). */ static inline uint16_t vring_avail_idx(VirtQueue *vq) { - VRingMemoryRegionCaches *caches = atomic_rcu_read(&vq->vring.caches); + VRingMemoryRegionCaches *caches = vring_get_region_caches(vq); hwaddr pa = offsetof(VRingAvail, idx); vq->shadow_avail_idx = virtio_lduw_phys_cached(vq->vdev, &caches->avail, pa); return vq->shadow_avail_idx; @@ -205,7 +232,7 @@ static inline uint16_t vring_avail_idx(VirtQueue *vq) /* Called within rcu_read_lock(). */ static inline uint16_t vring_avail_ring(VirtQueue *vq, int i) { - VRingMemoryRegionCaches *caches = atomic_rcu_read(&vq->vring.caches); + VRingMemoryRegionCaches *caches = vring_get_region_caches(vq); hwaddr pa = offsetof(VRingAvail, ring[i]); return virtio_lduw_phys_cached(vq->vdev, &caches->avail, pa); } @@ -220,7 +247,7 @@ static inline uint16_t vring_get_used_event(VirtQueue *vq) static inline void vring_used_write(VirtQueue *vq, VRingUsedElem *uelem, int i) { - VRingMemoryRegionCaches *caches = atomic_rcu_read(&vq->vring.caches); + VRingMemoryRegionCaches *caches = vring_get_region_caches(vq); hwaddr pa = offsetof(VRingUsed, ring[i]); virtio_tswap32s(vq->vdev, &uelem->id); virtio_tswap32s(vq->vdev, &uelem->len); @@ -231,7 +258,7 @@ static inline void vring_used_write(VirtQueue *vq, VRingUsedElem *uelem, /* Called within rcu_read_lock(). */ static uint16_t vring_used_idx(VirtQueue *vq) { - VRingMemoryRegionCaches *caches = atomic_rcu_read(&vq->vring.caches); + VRingMemoryRegionCaches *caches = vring_get_region_caches(vq); hwaddr pa = offsetof(VRingUsed, idx); return virtio_lduw_phys_cached(vq->vdev, &caches->used, pa); } @@ -239,7 +266,7 @@ static uint16_t vring_used_idx(VirtQueue *vq) /* Called within rcu_read_lock(). */ static inline void vring_used_idx_set(VirtQueue *vq, uint16_t val) { - VRingMemoryRegionCaches *caches = atomic_rcu_read(&vq->vring.caches); + VRingMemoryRegionCaches *caches = vring_get_region_caches(vq); hwaddr pa = offsetof(VRingUsed, idx); virtio_stw_phys_cached(vq->vdev, &caches->used, pa, val); address_space_cache_invalidate(&caches->used, pa, sizeof(val)); @@ -249,7 +276,7 @@ static inline void vring_used_idx_set(VirtQueue *vq, uint16_t val) /* Called within rcu_read_lock(). */ static inline void vring_used_flags_set_bit(VirtQueue *vq, int mask) { - VRingMemoryRegionCaches *caches = atomic_rcu_read(&vq->vring.caches); + VRingMemoryRegionCaches *caches = vring_get_region_caches(vq); VirtIODevice *vdev = vq->vdev; hwaddr pa = offsetof(VRingUsed, flags); uint16_t flags = virtio_lduw_phys_cached(vq->vdev, &caches->used, pa); @@ -261,7 +288,7 @@ static inline void vring_used_flags_set_bit(VirtQueue *vq, int mask) /* Called within rcu_read_lock(). */ static inline void vring_used_flags_unset_bit(VirtQueue *vq, int mask) { - VRingMemoryRegionCaches *caches = atomic_rcu_read(&vq->vring.caches); + VRingMemoryRegionCaches *caches = vring_get_region_caches(vq); VirtIODevice *vdev = vq->vdev; hwaddr pa = offsetof(VRingUsed, flags); uint16_t flags = virtio_lduw_phys_cached(vq->vdev, &caches->used, pa); @@ -279,7 +306,7 @@ static inline void vring_set_avail_event(VirtQueue *vq, uint16_t val) return; } - caches = atomic_rcu_read(&vq->vring.caches); + caches = vring_get_region_caches(vq); pa = offsetof(VRingUsed, ring[vq->vring.num]); virtio_stw_phys_cached(vq->vdev, &caches->used, pa, val); address_space_cache_invalidate(&caches->used, pa, sizeof(val)); @@ -318,6 +345,10 @@ int virtio_queue_ready(VirtQueue *vq) * Called within rcu_read_lock(). */ static int virtio_queue_empty_rcu(VirtQueue *vq) { + if (unlikely(!vq->vring.avail)) { + return 1; + } + if (vq->shadow_avail_idx != vq->last_avail_idx) { return 0; } @@ -329,6 +360,10 @@ int virtio_queue_empty(VirtQueue *vq) { bool empty; + if (unlikely(!vq->vring.avail)) { + return 1; + } + if (vq->shadow_avail_idx != vq->last_avail_idx) { return 0; } @@ -431,6 +466,10 @@ void virtqueue_fill(VirtQueue *vq, const VirtQueueElement *elem, return; } + if (unlikely(!vq->vring.used)) { + return; + } + idx = (idx + vq->used_idx) % vq->vring.num; uelem.id = elem->index; @@ -448,6 +487,10 @@ void virtqueue_flush(VirtQueue *vq, unsigned int count) return; } + if (unlikely(!vq->vring.used)) { + return; + } + /* Make sure buffer is written before we update index. */ smp_wmb(); trace_virtqueue_flush(vq, count); @@ -546,12 +589,22 @@ void virtqueue_get_avail_bytes(VirtQueue *vq, unsigned int *in_bytes, int64_t len = 0; int rc; + if (unlikely(!vq->vring.desc)) { + if (in_bytes) { + *in_bytes = 0; + } + if (out_bytes) { + *out_bytes = 0; + } + return; + } + rcu_read_lock(); idx = vq->last_avail_idx; total_bufs = in_total = out_total = 0; max = vq->vring.num; - caches = atomic_rcu_read(&vq->vring.caches); + caches = vring_get_region_caches(vq); if (caches->desc.len < max * sizeof(VRingDesc)) { virtio_error(vdev, "Cannot map descriptor ring"); goto err; @@ -818,7 +871,7 @@ void *virtqueue_pop(VirtQueue *vq, size_t sz) i = head; - caches = atomic_rcu_read(&vq->vring.caches); + caches = vring_get_region_caches(vq); if (caches->desc.len < max * sizeof(VRingDesc)) { virtio_error(vdev, "Cannot map descriptor ring"); goto done; @@ -1117,6 +1170,17 @@ static enum virtio_device_endian virtio_current_cpu_endian(void) } } +static void virtio_virtqueue_reset_region_cache(struct VirtQueue *vq) +{ + VRingMemoryRegionCaches *caches; + + caches = atomic_read(&vq->vring.caches); + atomic_rcu_set(&vq->vring.caches, NULL); + if (caches) { + call_rcu(caches, virtio_free_region_cache, rcu); + } +} + void virtio_reset(void *opaque) { VirtIODevice *vdev = opaque; @@ -1157,6 +1221,7 @@ void virtio_reset(void *opaque) vdev->vq[i].notification = true; vdev->vq[i].vring.num = vdev->vq[i].vring.num_default; vdev->vq[i].inuse = 0; + virtio_virtqueue_reset_region_cache(&vdev->vq[i]); } } @@ -2451,13 +2516,10 @@ static void virtio_device_free_virtqueues(VirtIODevice *vdev) } for (i = 0; i < VIRTIO_QUEUE_MAX; i++) { - VRingMemoryRegionCaches *caches; if (vdev->vq[i].vring.num == 0) { break; } - caches = atomic_read(&vdev->vq[i].vring.caches); - atomic_set(&vdev->vq[i].vring.caches, NULL); - virtio_free_region_cache(caches); + virtio_virtqueue_reset_region_cache(&vdev->vq[i]); } g_free(vdev->vq); } |