From 5c87c4089afed982d5bc40cddbbef72c38d0389a Mon Sep 17 00:00:00 2001 From: Pooja Dhannawat Date: Thu, 12 May 2016 13:22:24 +0100 Subject: [PATCH 01/43] blizzard: Remove support for DEPTH != 32 Removing support for DEPTH != 32 from blizzard template header and file that includes it, as macro DEPTH == 32 only used. Reviewed-by: Eric Blake Signed-off-by: Pooja Dhannawat Message-id: 1458971873-2768-1-git-send-email-dhannawatpooja1@gmail.com Signed-off-by: Peter Maydell --- hw/display/blizzard.c | 41 ++++------------------------------ hw/display/blizzard_template.h | 30 +------------------------ 2 files changed, 5 insertions(+), 66 deletions(-) diff --git a/hw/display/blizzard.c b/hw/display/blizzard.c index c231960d96..af0b51e73b 100644 --- a/hw/display/blizzard.c +++ b/hw/display/blizzard.c @@ -925,14 +925,6 @@ static void blizzard_update_display(void *opaque) s->my[1] = 0; } -#define DEPTH 8 -#include "blizzard_template.h" -#define DEPTH 15 -#include "blizzard_template.h" -#define DEPTH 16 -#include "blizzard_template.h" -#define DEPTH 24 -#include "blizzard_template.h" #define DEPTH 32 #include "blizzard_template.h" @@ -951,35 +943,10 @@ void *s1d13745_init(qemu_irq gpio_int) s->con = graphic_console_init(NULL, 0, &blizzard_ops, s); surface = qemu_console_surface(s->con); - switch (surface_bits_per_pixel(surface)) { - case 0: - s->line_fn_tab[0] = s->line_fn_tab[1] = - g_malloc0(sizeof(blizzard_fn_t) * 0x10); - break; - case 8: - s->line_fn_tab[0] = blizzard_draw_fn_8; - s->line_fn_tab[1] = blizzard_draw_fn_r_8; - break; - case 15: - s->line_fn_tab[0] = blizzard_draw_fn_15; - s->line_fn_tab[1] = blizzard_draw_fn_r_15; - break; - case 16: - s->line_fn_tab[0] = blizzard_draw_fn_16; - s->line_fn_tab[1] = blizzard_draw_fn_r_16; - break; - case 24: - s->line_fn_tab[0] = blizzard_draw_fn_24; - s->line_fn_tab[1] = blizzard_draw_fn_r_24; - break; - case 32: - s->line_fn_tab[0] = blizzard_draw_fn_32; - s->line_fn_tab[1] = blizzard_draw_fn_r_32; - break; - default: - fprintf(stderr, "%s: Bad color depth\n", __FUNCTION__); - exit(1); - } + assert(surface_bits_per_pixel(surface) == 32); + + s->line_fn_tab[0] = blizzard_draw_fn_32; + s->line_fn_tab[1] = blizzard_draw_fn_r_32; blizzard_reset(s); diff --git a/hw/display/blizzard_template.h b/hw/display/blizzard_template.h index b7ef27c808..bc38d7afad 100644 --- a/hw/display/blizzard_template.h +++ b/hw/display/blizzard_template.h @@ -19,31 +19,7 @@ */ #define SKIP_PIXEL(to) (to += deststep) -#if DEPTH == 8 -# define PIXEL_TYPE uint8_t -# define COPY_PIXEL(to, from) do { *to = from; SKIP_PIXEL(to); } while (0) -# define COPY_PIXEL1(to, from) (*to++ = from) -#elif DEPTH == 15 || DEPTH == 16 -# define PIXEL_TYPE uint16_t -# define COPY_PIXEL(to, from) do { *to = from; SKIP_PIXEL(to); } while (0) -# define COPY_PIXEL1(to, from) (*to++ = from) -#elif DEPTH == 24 -# define PIXEL_TYPE uint8_t -# define COPY_PIXEL(to, from) \ - do { \ - to[0] = from; \ - to[1] = (from) >> 8; \ - to[2] = (from) >> 16; \ - SKIP_PIXEL(to); \ - } while (0) - -# define COPY_PIXEL1(to, from) \ - do { \ - *to++ = from; \ - *to++ = (from) >> 8; \ - *to++ = (from) >> 16; \ - } while (0) -#elif DEPTH == 32 +#if DEPTH == 32 # define PIXEL_TYPE uint32_t # define COPY_PIXEL(to, from) do { *to = from; SKIP_PIXEL(to); } while (0) # define COPY_PIXEL1(to, from) (*to++ = from) @@ -58,9 +34,6 @@ static void glue(blizzard_draw_line16_, DEPTH)(PIXEL_TYPE *dest, const uint16_t *src, unsigned int width) { -#if !defined(SWAP_WORDS) && DEPTH == 16 - memcpy(dest, src, width); -#else uint16_t data; unsigned int r, g, b; const uint16_t *end = (const void *) src + width; @@ -74,7 +47,6 @@ static void glue(blizzard_draw_line16_, DEPTH)(PIXEL_TYPE *dest, data >>= 5; COPY_PIXEL1(dest, glue(rgb_to_pixel, DEPTH)(r, g, b)); } -#endif } static void glue(blizzard_draw_line24mode1_, DEPTH)(PIXEL_TYPE *dest, From ea644cf3431297cf6ce1c7562ec5aa221149d856 Mon Sep 17 00:00:00 2001 From: Pooja Dhannawat Date: Thu, 12 May 2016 13:22:24 +0100 Subject: [PATCH 02/43] omap_lcdc: Remove support for DEPTH != 32 surface_bits_per_pixel() always returns 32 so, removing other dead code which is based on DEPTH !== 32 Signed-off-by: Pooja Dhannawat Message-id: 1459260142-9144-1-git-send-email-dhannawatpooja1@gmail.com Reviewed-by: Peter Maydell Signed-off-by: Peter Maydell --- hw/display/omap_lcd_template.h | 10 ++----- hw/display/omap_lcdc.c | 48 ++++------------------------------ 2 files changed, 7 insertions(+), 51 deletions(-) diff --git a/hw/display/omap_lcd_template.h b/hw/display/omap_lcd_template.h index f0ce71fd66..1025ff3825 100644 --- a/hw/display/omap_lcd_template.h +++ b/hw/display/omap_lcd_template.h @@ -27,13 +27,7 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#if DEPTH == 8 -# define BPP 1 -# define PIXEL_TYPE uint8_t -#elif DEPTH == 15 || DEPTH == 16 -# define BPP 2 -# define PIXEL_TYPE uint16_t -#elif DEPTH == 32 +#if DEPTH == 32 # define BPP 4 # define PIXEL_TYPE uint32_t #else @@ -152,7 +146,7 @@ static void glue(draw_line12_, DEPTH)(void *opaque, static void glue(draw_line16_, DEPTH)(void *opaque, uint8_t *d, const uint8_t *s, int width, int deststep) { -#if DEPTH == 16 && defined(HOST_WORDS_BIGENDIAN) == defined(TARGET_WORDS_BIGENDIAN) +#if defined(HOST_WORDS_BIGENDIAN) == defined(TARGET_WORDS_BIGENDIAN) memcpy(d, s, width * 2); #else uint16_t v; diff --git a/hw/display/omap_lcdc.c b/hw/display/omap_lcdc.c index ce1058bf85..07a5effe04 100644 --- a/hw/display/omap_lcdc.c +++ b/hw/display/omap_lcdc.c @@ -71,47 +71,9 @@ static void omap_lcd_interrupts(struct omap_lcd_panel_s *s) #define draw_line_func drawfn -#define DEPTH 8 -#include "omap_lcd_template.h" -#define DEPTH 15 -#include "omap_lcd_template.h" -#define DEPTH 16 -#include "omap_lcd_template.h" #define DEPTH 32 #include "omap_lcd_template.h" -static draw_line_func draw_line_table2[33] = { - [0 ... 32] = NULL, - [8] = draw_line2_8, - [15] = draw_line2_15, - [16] = draw_line2_16, - [32] = draw_line2_32, -}, draw_line_table4[33] = { - [0 ... 32] = NULL, - [8] = draw_line4_8, - [15] = draw_line4_15, - [16] = draw_line4_16, - [32] = draw_line4_32, -}, draw_line_table8[33] = { - [0 ... 32] = NULL, - [8] = draw_line8_8, - [15] = draw_line8_15, - [16] = draw_line8_16, - [32] = draw_line8_32, -}, draw_line_table12[33] = { - [0 ... 32] = NULL, - [8] = draw_line12_8, - [15] = draw_line12_15, - [16] = draw_line12_16, - [32] = draw_line12_32, -}, draw_line_table16[33] = { - [0 ... 32] = NULL, - [8] = draw_line16_8, - [15] = draw_line16_15, - [16] = draw_line16_16, - [32] = draw_line16_32, -}; - static void omap_update_display(void *opaque) { struct omap_lcd_panel_s *omap_lcd = (struct omap_lcd_panel_s *) opaque; @@ -143,25 +105,25 @@ static void omap_update_display(void *opaque) /* Colour depth */ switch ((omap_lcd->palette[0] >> 12) & 7) { case 1: - draw_line = draw_line_table2[surface_bits_per_pixel(surface)]; + draw_line = draw_line2_32; bpp = 2; break; case 2: - draw_line = draw_line_table4[surface_bits_per_pixel(surface)]; + draw_line = draw_line4_32; bpp = 4; break; case 3: - draw_line = draw_line_table8[surface_bits_per_pixel(surface)]; + draw_line = draw_line8_32; bpp = 8; break; case 4 ... 7: if (!omap_lcd->tft) - draw_line = draw_line_table12[surface_bits_per_pixel(surface)]; + draw_line = draw_line12_32; else - draw_line = draw_line_table16[surface_bits_per_pixel(surface)]; + draw_line = draw_line16_32; bpp = 16; break; From b46818e9e7f1edcc32bd69cc5671cbda6cfdc7a1 Mon Sep 17 00:00:00 2001 From: "xiaoqiang.zhao" Date: Thu, 12 May 2016 13:22:24 +0100 Subject: [PATCH 03/43] hw/intc: QOM'ify etraxfs_pic.c Drop the old SysBus init function and use instance_init Signed-off-by: xiaoqiang zhao Reviewed-by: Peter Maydell Reviewed-by: Edgar E. Iglesias Tested-by: Edgar E. Iglesias Signed-off-by: Peter Maydell --- hw/intc/etraxfs_pic.c | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/hw/intc/etraxfs_pic.c b/hw/intc/etraxfs_pic.c index 48f9477065..64a6f4b4ba 100644 --- a/hw/intc/etraxfs_pic.c +++ b/hw/intc/etraxfs_pic.c @@ -146,19 +146,19 @@ static void irq_handler(void *opaque, int irq, int level) pic_update(fs); } -static int etraxfs_pic_init(SysBusDevice *sbd) +static void etraxfs_pic_init(Object *obj) { - DeviceState *dev = DEVICE(sbd); - struct etrax_pic *s = ETRAX_FS_PIC(dev); + DeviceState *dev = DEVICE(obj); + struct etrax_pic *s = ETRAX_FS_PIC(obj); + SysBusDevice *sbd = SYS_BUS_DEVICE(obj); qdev_init_gpio_in(dev, irq_handler, 32); sysbus_init_irq(sbd, &s->parent_irq); sysbus_init_irq(sbd, &s->parent_nmi); - memory_region_init_io(&s->mmio, OBJECT(s), &pic_ops, s, + memory_region_init_io(&s->mmio, obj, &pic_ops, s, "etraxfs-pic", R_MAX * 4); sysbus_init_mmio(sbd, &s->mmio); - return 0; } static Property etraxfs_pic_properties[] = { @@ -169,9 +169,7 @@ static Property etraxfs_pic_properties[] = { static void etraxfs_pic_class_init(ObjectClass *klass, void *data) { DeviceClass *dc = DEVICE_CLASS(klass); - SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass); - k->init = etraxfs_pic_init; dc->props = etraxfs_pic_properties; /* * Note: pointer property "interrupt_vector" may remain null, thus @@ -183,6 +181,7 @@ static const TypeInfo etraxfs_pic_info = { .name = TYPE_ETRAX_FS_PIC, .parent = TYPE_SYS_BUS_DEVICE, .instance_size = sizeof(struct etrax_pic), + .instance_init = etraxfs_pic_init, .class_init = etraxfs_pic_class_init, }; From d3d5a6febd989c08a432a49046b9172df6ede834 Mon Sep 17 00:00:00 2001 From: "xiaoqiang.zhao" Date: Thu, 12 May 2016 13:22:24 +0100 Subject: [PATCH 04/43] hw/intc: QOM'ify exynos4210_combiner.c Drop the old SysBus init function and use instance_init Signed-off-by: xiaoqiang zhao Reviewed-by: Peter Maydell Signed-off-by: Peter Maydell --- hw/intc/exynos4210_combiner.c | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/hw/intc/exynos4210_combiner.c b/hw/intc/exynos4210_combiner.c index dc0c903266..f19a7062be 100644 --- a/hw/intc/exynos4210_combiner.c +++ b/hw/intc/exynos4210_combiner.c @@ -406,10 +406,11 @@ static const MemoryRegionOps exynos4210_combiner_ops = { /* * Internal Combiner initialization. */ -static int exynos4210_combiner_init(SysBusDevice *sbd) +static void exynos4210_combiner_init(Object *obj) { - DeviceState *dev = DEVICE(sbd); - Exynos4210CombinerState *s = EXYNOS4210_COMBINER(dev); + DeviceState *dev = DEVICE(obj); + Exynos4210CombinerState *s = EXYNOS4210_COMBINER(obj); + SysBusDevice *sbd = SYS_BUS_DEVICE(obj); unsigned int i; /* Allocate general purpose input signals and connect a handler to each of @@ -421,11 +422,9 @@ static int exynos4210_combiner_init(SysBusDevice *sbd) sysbus_init_irq(sbd, &s->output_irq[i]); } - memory_region_init_io(&s->iomem, OBJECT(s), &exynos4210_combiner_ops, s, + memory_region_init_io(&s->iomem, obj, &exynos4210_combiner_ops, s, "exynos4210-combiner", IIC_REGION_SIZE); sysbus_init_mmio(sbd, &s->iomem); - - return 0; } static Property exynos4210_combiner_properties[] = { @@ -436,9 +435,7 @@ static Property exynos4210_combiner_properties[] = { static void exynos4210_combiner_class_init(ObjectClass *klass, void *data) { DeviceClass *dc = DEVICE_CLASS(klass); - SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass); - k->init = exynos4210_combiner_init; dc->reset = exynos4210_combiner_reset; dc->props = exynos4210_combiner_properties; dc->vmsd = &vmstate_exynos4210_combiner; @@ -448,6 +445,7 @@ static const TypeInfo exynos4210_combiner_info = { .name = TYPE_EXYNOS4210_COMBINER, .parent = TYPE_SYS_BUS_DEVICE, .instance_size = sizeof(Exynos4210CombinerState), + .instance_init = exynos4210_combiner_init, .class_init = exynos4210_combiner_class_init, }; From 68d71616c055471e59eb07b1140dcb04b25b63f9 Mon Sep 17 00:00:00 2001 From: "xiaoqiang.zhao" Date: Thu, 12 May 2016 13:22:24 +0100 Subject: [PATCH 05/43] hw/intc: QOM'ify exynos4210_gic.c * Drop the old SysBus init function and use instance_init * Split the exynos4210_irq_gate_init into an instance_init and a DeviceClass::realize function Signed-off-by: xiaoqiang zhao Reviewed-by: Peter Maydell Signed-off-by: Peter Maydell --- hw/intc/exynos4210_gic.c | 39 ++++++++++++++++++++------------------- 1 file changed, 20 insertions(+), 19 deletions(-) diff --git a/hw/intc/exynos4210_gic.c b/hw/intc/exynos4210_gic.c index 4f7e89f7b8..fd7a8f3058 100644 --- a/hw/intc/exynos4210_gic.c +++ b/hw/intc/exynos4210_gic.c @@ -281,10 +281,11 @@ static void exynos4210_gic_set_irq(void *opaque, int irq, int level) qemu_set_irq(qdev_get_gpio_in(s->gic, irq), level); } -static int exynos4210_gic_init(SysBusDevice *sbd) +static void exynos4210_gic_init(Object *obj) { - DeviceState *dev = DEVICE(sbd); - Exynos4210GicState *s = EXYNOS4210_GIC(dev); + DeviceState *dev = DEVICE(obj); + Exynos4210GicState *s = EXYNOS4210_GIC(obj); + SysBusDevice *sbd = SYS_BUS_DEVICE(obj); uint32_t i; const char cpu_prefix[] = "exynos4210-gic-alias_cpu"; const char dist_prefix[] = "exynos4210-gic-alias_dist"; @@ -305,15 +306,15 @@ static int exynos4210_gic_init(SysBusDevice *sbd) qdev_init_gpio_in(dev, exynos4210_gic_set_irq, EXYNOS4210_GIC_NIRQ - 32); - memory_region_init(&s->cpu_container, OBJECT(s), "exynos4210-cpu-container", + memory_region_init(&s->cpu_container, obj, "exynos4210-cpu-container", EXYNOS4210_EXT_GIC_CPU_REGION_SIZE); - memory_region_init(&s->dist_container, OBJECT(s), "exynos4210-dist-container", + memory_region_init(&s->dist_container, obj, "exynos4210-dist-container", EXYNOS4210_EXT_GIC_DIST_REGION_SIZE); for (i = 0; i < s->num_cpu; i++) { /* Map CPU interface per SMP Core */ sprintf(cpu_alias_name, "%s%x", cpu_prefix, i); - memory_region_init_alias(&s->cpu_alias[i], OBJECT(s), + memory_region_init_alias(&s->cpu_alias[i], obj, cpu_alias_name, sysbus_mmio_get_region(busdev, 1), 0, @@ -323,7 +324,7 @@ static int exynos4210_gic_init(SysBusDevice *sbd) /* Map Distributor per SMP Core */ sprintf(dist_alias_name, "%s%x", dist_prefix, i); - memory_region_init_alias(&s->dist_alias[i], OBJECT(s), + memory_region_init_alias(&s->dist_alias[i], obj, dist_alias_name, sysbus_mmio_get_region(busdev, 0), 0, @@ -334,8 +335,6 @@ static int exynos4210_gic_init(SysBusDevice *sbd) sysbus_init_mmio(sbd, &s->cpu_container); sysbus_init_mmio(sbd, &s->dist_container); - - return 0; } static Property exynos4210_gic_properties[] = { @@ -346,9 +345,7 @@ static Property exynos4210_gic_properties[] = { static void exynos4210_gic_class_init(ObjectClass *klass, void *data) { DeviceClass *dc = DEVICE_CLASS(klass); - SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass); - k->init = exynos4210_gic_init; dc->props = exynos4210_gic_properties; } @@ -356,6 +353,7 @@ static const TypeInfo exynos4210_gic_info = { .name = TYPE_EXYNOS4210_GIC, .parent = TYPE_SYS_BUS_DEVICE, .instance_size = sizeof(Exynos4210GicState), + .instance_init = exynos4210_gic_init, .class_init = exynos4210_gic_class_init, }; @@ -430,9 +428,16 @@ static void exynos4210_irq_gate_reset(DeviceState *d) /* * IRQ Gate initialization. */ -static int exynos4210_irq_gate_init(SysBusDevice *sbd) +static void exynos4210_irq_gate_init(Object *obj) +{ + Exynos4210IRQGateState *s = EXYNOS4210_IRQ_GATE(obj); + SysBusDevice *sbd = SYS_BUS_DEVICE(obj); + + sysbus_init_irq(sbd, &s->out); +} + +static void exynos4210_irq_gate_realize(DeviceState *dev, Error **errp) { - DeviceState *dev = DEVICE(sbd); Exynos4210IRQGateState *s = EXYNOS4210_IRQ_GATE(dev); /* Allocate general purpose input signals and connect a handler to each of @@ -440,27 +445,23 @@ static int exynos4210_irq_gate_init(SysBusDevice *sbd) qdev_init_gpio_in(dev, exynos4210_irq_gate_handler, s->n_in); s->level = g_malloc0(s->n_in * sizeof(*s->level)); - - sysbus_init_irq(sbd, &s->out); - - return 0; } static void exynos4210_irq_gate_class_init(ObjectClass *klass, void *data) { DeviceClass *dc = DEVICE_CLASS(klass); - SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass); - k->init = exynos4210_irq_gate_init; dc->reset = exynos4210_irq_gate_reset; dc->vmsd = &vmstate_exynos4210_irq_gate; dc->props = exynos4210_irq_gate_properties; + dc->realize = exynos4210_irq_gate_realize; } static const TypeInfo exynos4210_irq_gate_info = { .name = TYPE_EXYNOS4210_IRQ_GATE, .parent = TYPE_SYS_BUS_DEVICE, .instance_size = sizeof(Exynos4210IRQGateState), + .instance_init = exynos4210_irq_gate_init, .class_init = exynos4210_irq_gate_class_init, }; From f777bda60f3fb5779562e51b7969b81a9bd51f34 Mon Sep 17 00:00:00 2001 From: "xiaoqiang.zhao" Date: Thu, 12 May 2016 13:22:24 +0100 Subject: [PATCH 06/43] hw/intc: QOM'ify imx_avic.c Drop the old SysBus init function and use instance_init Signed-off-by: xiaoqiang zhao Reviewed-by: Peter Maydell Signed-off-by: Peter Maydell --- hw/intc/imx_avic.c | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/hw/intc/imx_avic.c b/hw/intc/imx_avic.c index 7027655774..d21cb97451 100644 --- a/hw/intc/imx_avic.c +++ b/hw/intc/imx_avic.c @@ -321,28 +321,26 @@ static void imx_avic_reset(DeviceState *dev) memset(s->prio, 0, sizeof s->prio); } -static int imx_avic_init(SysBusDevice *sbd) +static void imx_avic_init(Object *obj) { - DeviceState *dev = DEVICE(sbd); - IMXAVICState *s = IMX_AVIC(dev); + DeviceState *dev = DEVICE(obj); + IMXAVICState *s = IMX_AVIC(obj); + SysBusDevice *sbd = SYS_BUS_DEVICE(obj); - memory_region_init_io(&s->iomem, OBJECT(s), &imx_avic_ops, s, + memory_region_init_io(&s->iomem, obj, &imx_avic_ops, s, TYPE_IMX_AVIC, 0x1000); sysbus_init_mmio(sbd, &s->iomem); qdev_init_gpio_in(dev, imx_avic_set_irq, IMX_AVIC_NUM_IRQS); sysbus_init_irq(sbd, &s->irq); sysbus_init_irq(sbd, &s->fiq); - - return 0; } static void imx_avic_class_init(ObjectClass *klass, void *data) { DeviceClass *dc = DEVICE_CLASS(klass); - SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass); - k->init = imx_avic_init; + dc->vmsd = &vmstate_imx_avic; dc->reset = imx_avic_reset; dc->desc = "i.MX Advanced Vector Interrupt Controller"; @@ -352,6 +350,7 @@ static const TypeInfo imx_avic_info = { .name = TYPE_IMX_AVIC, .parent = TYPE_SYS_BUS_DEVICE, .instance_size = sizeof(IMXAVICState), + .instance_init = imx_avic_init, .class_init = imx_avic_class_init, }; From e3be8b4f4fcbe98b0cbd5aa6de8727af4af76dba Mon Sep 17 00:00:00 2001 From: "xiaoqiang.zhao" Date: Thu, 12 May 2016 13:22:25 +0100 Subject: [PATCH 07/43] hw/intc: QOM'ify pl190.c Drop the old SysBus init function and use instance_init Signed-off-by: xiaoqiang zhao Reviewed-by: Peter Maydell Signed-off-by: Peter Maydell --- hw/intc/pl190.c | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/hw/intc/pl190.c b/hw/intc/pl190.c index 5ecbc4a485..1e50baf237 100644 --- a/hw/intc/pl190.c +++ b/hw/intc/pl190.c @@ -236,17 +236,17 @@ static void pl190_reset(DeviceState *d) pl190_update_vectors(s); } -static int pl190_init(SysBusDevice *sbd) +static void pl190_init(Object *obj) { - DeviceState *dev = DEVICE(sbd); - PL190State *s = PL190(dev); + DeviceState *dev = DEVICE(obj); + PL190State *s = PL190(obj); + SysBusDevice *sbd = SYS_BUS_DEVICE(obj); - memory_region_init_io(&s->iomem, OBJECT(s), &pl190_ops, s, "pl190", 0x1000); + memory_region_init_io(&s->iomem, obj, &pl190_ops, s, "pl190", 0x1000); sysbus_init_mmio(sbd, &s->iomem); qdev_init_gpio_in(dev, pl190_set_irq, 32); sysbus_init_irq(sbd, &s->irq); sysbus_init_irq(sbd, &s->fiq); - return 0; } static const VMStateDescription vmstate_pl190 = { @@ -271,9 +271,7 @@ static const VMStateDescription vmstate_pl190 = { static void pl190_class_init(ObjectClass *klass, void *data) { DeviceClass *dc = DEVICE_CLASS(klass); - SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass); - k->init = pl190_init; dc->reset = pl190_reset; dc->vmsd = &vmstate_pl190; } @@ -282,6 +280,7 @@ static const TypeInfo pl190_info = { .name = TYPE_PL190, .parent = TYPE_SYS_BUS_DEVICE, .instance_size = sizeof(PL190State), + .instance_init = pl190_init, .class_init = pl190_class_init, }; From c09008d2d30e99a0a32aff0fc6b453467e62a7de Mon Sep 17 00:00:00 2001 From: "xiaoqiang.zhao" Date: Thu, 12 May 2016 13:22:25 +0100 Subject: [PATCH 08/43] hw/intc: QOM'ify slavio_intctl.c Drop the old SysBus init function and use instance_init Signed-off-by: xiaoqiang zhao Reviewed-by: Peter Maydell Signed-off-by: Peter Maydell --- hw/intc/slavio_intctl.c | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/hw/intc/slavio_intctl.c b/hw/intc/slavio_intctl.c index c9486ed999..e82e893628 100644 --- a/hw/intc/slavio_intctl.c +++ b/hw/intc/slavio_intctl.c @@ -418,15 +418,16 @@ static void slavio_intctl_reset(DeviceState *d) slavio_check_interrupts(s, 0); } -static int slavio_intctl_init1(SysBusDevice *sbd) +static void slavio_intctl_init(Object *obj) { - DeviceState *dev = DEVICE(sbd); - SLAVIO_INTCTLState *s = SLAVIO_INTCTL(dev); + DeviceState *dev = DEVICE(obj); + SLAVIO_INTCTLState *s = SLAVIO_INTCTL(obj); + SysBusDevice *sbd = SYS_BUS_DEVICE(obj); unsigned int i, j; char slave_name[45]; qdev_init_gpio_in(dev, slavio_set_irq_all, 32 + MAX_CPUS); - memory_region_init_io(&s->iomem, OBJECT(s), &slavio_intctlm_mem_ops, s, + memory_region_init_io(&s->iomem, obj, &slavio_intctlm_mem_ops, s, "master-interrupt-controller", INTCTLM_SIZE); sysbus_init_mmio(sbd, &s->iomem); @@ -443,16 +444,12 @@ static int slavio_intctl_init1(SysBusDevice *sbd) s->slaves[i].cpu = i; s->slaves[i].master = s; } - - return 0; } static void slavio_intctl_class_init(ObjectClass *klass, void *data) { DeviceClass *dc = DEVICE_CLASS(klass); - SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass); - k->init = slavio_intctl_init1; dc->reset = slavio_intctl_reset; dc->vmsd = &vmstate_intctl; } @@ -461,6 +458,7 @@ static const TypeInfo slavio_intctl_info = { .name = TYPE_SLAVIO_INTCTL, .parent = TYPE_SYS_BUS_DEVICE, .instance_size = sizeof(SLAVIO_INTCTLState), + .instance_init = slavio_intctl_init, .class_init = slavio_intctl_class_init, }; From 22c70d8a6aeb654460d9cda27e6d33ecc35c3833 Mon Sep 17 00:00:00 2001 From: "xiaoqiang.zhao" Date: Thu, 12 May 2016 13:22:25 +0100 Subject: [PATCH 09/43] hw/intc: QOM'ify grlib_irqmp.c * Split the old SysBus init into an instance_init and a DeviceClass::realize function * Drop the old SysBus init function Signed-off-by: xiaoqiang zhao Reviewed-by: Peter Maydell [PMM: corrected "can not" to "cannot" in error message] Signed-off-by: Peter Maydell --- hw/intc/grlib_irqmp.c | 27 ++++++++++++++++----------- 1 file changed, 16 insertions(+), 11 deletions(-) diff --git a/hw/intc/grlib_irqmp.c b/hw/intc/grlib_irqmp.c index f5ca8f752b..ac7e63f38b 100644 --- a/hw/intc/grlib_irqmp.c +++ b/hw/intc/grlib_irqmp.c @@ -31,6 +31,7 @@ #include "hw/sparc/grlib.h" #include "trace.h" +#include "qapi/error.h" #define IRQMP_MAX_CPU 16 #define IRQMP_REG_SIZE 256 /* Size of memory mapped registers */ @@ -323,23 +324,27 @@ static void grlib_irqmp_reset(DeviceState *d) irqmp->state->parent = irqmp; } -static int grlib_irqmp_init(SysBusDevice *dev) +static void grlib_irqmp_init(Object *obj) { - IRQMP *irqmp = GRLIB_IRQMP(dev); + IRQMP *irqmp = GRLIB_IRQMP(obj); + SysBusDevice *dev = SYS_BUS_DEVICE(obj); - /* Check parameters */ - if (irqmp->set_pil_in == NULL) { - return -1; - } - - memory_region_init_io(&irqmp->iomem, OBJECT(dev), &grlib_irqmp_ops, irqmp, + memory_region_init_io(&irqmp->iomem, obj, &grlib_irqmp_ops, irqmp, "irqmp", IRQMP_REG_SIZE); irqmp->state = g_malloc0(sizeof *irqmp->state); sysbus_init_mmio(dev, &irqmp->iomem); +} - return 0; +static void grlib_irqmp_realize(DeviceState *dev, Error **errp) +{ + IRQMP *irqmp = GRLIB_IRQMP(dev); + + /* Check parameters */ + if (irqmp->set_pil_in == NULL) { + error_setg(errp, "set_pil_in cannot be NULL."); + } } static Property grlib_irqmp_properties[] = { @@ -351,19 +356,19 @@ static Property grlib_irqmp_properties[] = { static void grlib_irqmp_class_init(ObjectClass *klass, void *data) { DeviceClass *dc = DEVICE_CLASS(klass); - SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass); - k->init = grlib_irqmp_init; dc->reset = grlib_irqmp_reset; dc->props = grlib_irqmp_properties; /* Reason: pointer properties "set_pil_in", "set_pil_in_opaque" */ dc->cannot_instantiate_with_device_add_yet = true; + dc->realize = grlib_irqmp_realize; } static const TypeInfo grlib_irqmp_info = { .name = TYPE_GRLIB_IRQMP, .parent = TYPE_SYS_BUS_DEVICE, .instance_size = sizeof(IRQMP), + .instance_init = grlib_irqmp_init, .class_init = grlib_irqmp_class_init, }; From 0a750e2a787b78ea49d2570cdf342c64ee79933d Mon Sep 17 00:00:00 2001 From: xiaoqiang zhao Date: Thu, 12 May 2016 13:22:25 +0100 Subject: [PATCH 10/43] hw/intc: QOM'ify omap_intc.c * Split the old SysBus init into an instance_init and a DeviceClass::realize function * Drop the old SysBus init function and use instance_init Signed-off-by: xiaoqiang zhao Reviewed-by: Peter Maydell Signed-off-by: Peter Maydell --- hw/intc/omap_intc.c | 64 +++++++++++++++++++++++++++------------------ 1 file changed, 38 insertions(+), 26 deletions(-) diff --git a/hw/intc/omap_intc.c b/hw/intc/omap_intc.c index 336882510b..877be67971 100644 --- a/hw/intc/omap_intc.c +++ b/hw/intc/omap_intc.c @@ -22,6 +22,7 @@ #include "hw/arm/omap.h" #include "hw/sysbus.h" #include "qemu/error-report.h" +#include "qapi/error.h" /* Interrupt Handlers */ struct omap_intr_handler_bank_s { @@ -363,23 +364,28 @@ static void omap_inth_reset(DeviceState *dev) qemu_set_irq(s->parent_intr[1], 0); } -static int omap_intc_init(SysBusDevice *sbd) +static void omap_intc_init(Object *obj) { - DeviceState *dev = DEVICE(sbd); - struct omap_intr_handler_s *s = OMAP_INTC(dev); + DeviceState *dev = DEVICE(obj); + struct omap_intr_handler_s *s = OMAP_INTC(obj); + SysBusDevice *sbd = SYS_BUS_DEVICE(obj); - if (!s->iclk) { - error_report("omap-intc: clk not connected"); - return -1; - } s->nbanks = 1; sysbus_init_irq(sbd, &s->parent_intr[0]); sysbus_init_irq(sbd, &s->parent_intr[1]); qdev_init_gpio_in(dev, omap_set_intr, s->nbanks * 32); - memory_region_init_io(&s->mmio, OBJECT(s), &omap_inth_mem_ops, s, + memory_region_init_io(&s->mmio, obj, &omap_inth_mem_ops, s, "omap-intc", s->size); sysbus_init_mmio(sbd, &s->mmio); - return 0; +} + +static void omap_intc_realize(DeviceState *dev, Error **errp) +{ + struct omap_intr_handler_s *s = OMAP_INTC(dev); + + if (!s->iclk) { + error_setg(errp, "omap-intc: clk not connected"); + } } static Property omap_intc_properties[] = { @@ -391,18 +397,18 @@ static Property omap_intc_properties[] = { static void omap_intc_class_init(ObjectClass *klass, void *data) { DeviceClass *dc = DEVICE_CLASS(klass); - SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass); - k->init = omap_intc_init; dc->reset = omap_inth_reset; dc->props = omap_intc_properties; /* Reason: pointer property "clk" */ dc->cannot_instantiate_with_device_add_yet = true; + dc->realize = omap_intc_realize; } static const TypeInfo omap_intc_info = { .name = "omap-intc", .parent = TYPE_OMAP_INTC, + .instance_init = omap_intc_init, .class_init = omap_intc_class_init, }; @@ -605,28 +611,34 @@ static const MemoryRegionOps omap2_inth_mem_ops = { }, }; -static int omap2_intc_init(SysBusDevice *sbd) +static void omap2_intc_init(Object *obj) { - DeviceState *dev = DEVICE(sbd); - struct omap_intr_handler_s *s = OMAP_INTC(dev); + DeviceState *dev = DEVICE(obj); + struct omap_intr_handler_s *s = OMAP_INTC(obj); + SysBusDevice *sbd = SYS_BUS_DEVICE(obj); - if (!s->iclk) { - error_report("omap2-intc: iclk not connected"); - return -1; - } - if (!s->fclk) { - error_report("omap2-intc: fclk not connected"); - return -1; - } s->level_only = 1; s->nbanks = 3; sysbus_init_irq(sbd, &s->parent_intr[0]); sysbus_init_irq(sbd, &s->parent_intr[1]); qdev_init_gpio_in(dev, omap_set_intr_noedge, s->nbanks * 32); - memory_region_init_io(&s->mmio, OBJECT(s), &omap2_inth_mem_ops, s, + memory_region_init_io(&s->mmio, obj, &omap2_inth_mem_ops, s, "omap2-intc", 0x1000); sysbus_init_mmio(sbd, &s->mmio); - return 0; +} + +static void omap2_intc_realize(DeviceState *dev, Error **errp) +{ + struct omap_intr_handler_s *s = OMAP_INTC(dev); + + if (!s->iclk) { + error_setg(errp, "omap2-intc: iclk not connected"); + return; + } + if (!s->fclk) { + error_setg(errp, "omap2-intc: fclk not connected"); + return; + } } static Property omap2_intc_properties[] = { @@ -640,18 +652,18 @@ static Property omap2_intc_properties[] = { static void omap2_intc_class_init(ObjectClass *klass, void *data) { DeviceClass *dc = DEVICE_CLASS(klass); - SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass); - k->init = omap2_intc_init; dc->reset = omap_inth_reset; dc->props = omap2_intc_properties; /* Reason: pointer property "iclk", "fclk" */ dc->cannot_instantiate_with_device_add_yet = true; + dc->realize = omap2_intc_realize; } static const TypeInfo omap2_intc_info = { .name = "omap2-intc", .parent = TYPE_OMAP_INTC, + .instance_init = omap2_intc_init, .class_init = omap2_intc_class_init, }; From 27a5dc7be6a55b60039e39206eed2734ea166a47 Mon Sep 17 00:00:00 2001 From: Sylvain Garrigues Date: Thu, 12 May 2016 13:22:25 +0100 Subject: [PATCH 11/43] bcm2835_property: use cached values when querying framebuffer As the framebuffer settings are copied into the result message before it is reconfigured, inconsistent behavior can happen when, for instance, you set with a single message the width, height, and depth, and ask at the same time to allocate the buffer and get the pitch and the size. In this case, the reported pitch and size would be incorrect as they were computed with the initial values of width, height and depth, not the ones the client requested. Signed-off-by: Sylvain Garrigues Reviewed-by: Andrew Baumann Message-id: 1461325343-24995-1-git-send-email-sylvain@sylvaingarrigues.com [PMM: folded a couple of long lines] Signed-off-by: Peter Maydell --- hw/misc/bcm2835_property.c | 33 ++++++++++++++++++++++++--------- 1 file changed, 24 insertions(+), 9 deletions(-) diff --git a/hw/misc/bcm2835_property.c b/hw/misc/bcm2835_property.c index 530411f841..34473469d4 100644 --- a/hw/misc/bcm2835_property.c +++ b/hw/misc/bcm2835_property.c @@ -21,6 +21,8 @@ static void bcm2835_property_mbox_push(BCM2835PropertyState *s, uint32_t value) int n; uint32_t offset, length, color; uint32_t xres, yres, xoffset, yoffset, bpp, pixo, alpha; + uint32_t tmp_xres, tmp_yres, tmp_xoffset, tmp_yoffset; + uint32_t tmp_bpp, tmp_pixo, tmp_alpha; uint32_t *newxres = NULL, *newyres = NULL, *newxoffset = NULL, *newyoffset = NULL, *newbpp = NULL, *newpixo = NULL, *newalpha = NULL; @@ -139,7 +141,11 @@ static void bcm2835_property_mbox_push(BCM2835PropertyState *s, uint32_t value) case 0x00040001: /* Allocate buffer */ stl_le_phys(&s->dma_as, value + 12, s->fbdev->base); - stl_le_phys(&s->dma_as, value + 16, s->fbdev->size); + tmp_xres = newxres != NULL ? *newxres : s->fbdev->xres; + tmp_yres = newyres != NULL ? *newyres : s->fbdev->yres; + tmp_bpp = newbpp != NULL ? *newbpp : s->fbdev->bpp; + stl_le_phys(&s->dma_as, value + 16, + tmp_xres * tmp_yres * tmp_bpp / 8); resplen = 8; break; case 0x00048001: /* Release buffer */ @@ -150,8 +156,10 @@ static void bcm2835_property_mbox_push(BCM2835PropertyState *s, uint32_t value) break; case 0x00040003: /* Get display width/height */ case 0x00040004: - stl_le_phys(&s->dma_as, value + 12, s->fbdev->xres); - stl_le_phys(&s->dma_as, value + 16, s->fbdev->yres); + tmp_xres = newxres != NULL ? *newxres : s->fbdev->xres; + tmp_yres = newyres != NULL ? *newyres : s->fbdev->yres; + stl_le_phys(&s->dma_as, value + 12, tmp_xres); + stl_le_phys(&s->dma_as, value + 16, tmp_yres); resplen = 8; break; case 0x00044003: /* Test display width/height */ @@ -167,7 +175,8 @@ static void bcm2835_property_mbox_push(BCM2835PropertyState *s, uint32_t value) resplen = 8; break; case 0x00040005: /* Get depth */ - stl_le_phys(&s->dma_as, value + 12, s->fbdev->bpp); + tmp_bpp = newbpp != NULL ? *newbpp : s->fbdev->bpp; + stl_le_phys(&s->dma_as, value + 12, tmp_bpp); resplen = 4; break; case 0x00044005: /* Test depth */ @@ -179,7 +188,8 @@ static void bcm2835_property_mbox_push(BCM2835PropertyState *s, uint32_t value) resplen = 4; break; case 0x00040006: /* Get pixel order */ - stl_le_phys(&s->dma_as, value + 12, s->fbdev->pixo); + tmp_pixo = newpixo != NULL ? *newpixo : s->fbdev->pixo; + stl_le_phys(&s->dma_as, value + 12, tmp_pixo); resplen = 4; break; case 0x00044006: /* Test pixel order */ @@ -191,7 +201,8 @@ static void bcm2835_property_mbox_push(BCM2835PropertyState *s, uint32_t value) resplen = 4; break; case 0x00040007: /* Get alpha */ - stl_le_phys(&s->dma_as, value + 12, s->fbdev->alpha); + tmp_alpha = newalpha != NULL ? *newalpha : s->fbdev->alpha; + stl_le_phys(&s->dma_as, value + 12, tmp_alpha); resplen = 4; break; case 0x00044007: /* Test pixel alpha */ @@ -203,12 +214,16 @@ static void bcm2835_property_mbox_push(BCM2835PropertyState *s, uint32_t value) resplen = 4; break; case 0x00040008: /* Get pitch */ - stl_le_phys(&s->dma_as, value + 12, s->fbdev->pitch); + tmp_xres = newxres != NULL ? *newxres : s->fbdev->xres; + tmp_bpp = newbpp != NULL ? *newbpp : s->fbdev->bpp; + stl_le_phys(&s->dma_as, value + 12, tmp_xres * tmp_bpp / 8); resplen = 4; break; case 0x00040009: /* Get virtual offset */ - stl_le_phys(&s->dma_as, value + 12, s->fbdev->xoffset); - stl_le_phys(&s->dma_as, value + 16, s->fbdev->yoffset); + tmp_xoffset = newxoffset != NULL ? *newxoffset : s->fbdev->xoffset; + tmp_yoffset = newyoffset != NULL ? *newyoffset : s->fbdev->yoffset; + stl_le_phys(&s->dma_as, value + 12, tmp_xoffset); + stl_le_phys(&s->dma_as, value + 16, tmp_yoffset); resplen = 8; break; case 0x00044009: /* Test virtual offset */ From 0b062eb090517a66f3e9b4b1ddf2e740e9517102 Mon Sep 17 00:00:00 2001 From: Zhou Jie Date: Thu, 12 May 2016 13:22:25 +0100 Subject: [PATCH 12/43] hw/arm/nseries: Allocating Large sized arrays to heap n8x0_init has a huge stack usage of 65536 bytes approx. Moving large arrays to heap to reduce stack usage. Signed-off-by: Zhou Jie Message-id: 1461651308-894-1-git-send-email-zhoujie2011@cn.fujitsu.com Reviewed-by: Peter Maydell Signed-off-by: Peter Maydell --- hw/arm/nseries.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/hw/arm/nseries.c b/hw/arm/nseries.c index 5382505559..c7068c0d38 100644 --- a/hw/arm/nseries.c +++ b/hw/arm/nseries.c @@ -1364,7 +1364,7 @@ static void n8x0_init(MachineState *machine, if (option_rom[0].name && (machine->boot_order[0] == 'n' || !machine->kernel_filename)) { - uint8_t nolo_tags[0x10000]; + uint8_t *nolo_tags = g_new(uint8_t, 0x10000); /* No, wait, better start at the ROM. */ s->mpu->cpu->env.regs[15] = OMAP2_Q2_BASE + 0x400000; @@ -1383,6 +1383,7 @@ static void n8x0_init(MachineState *machine, n800_setup_nolo_tags(nolo_tags); cpu_physical_memory_write(OMAP2_SRAM_BASE, nolo_tags, 0x10000); + g_free(nolo_tags); } } From dfda68377e20943f474505e75238cb96bc6874bf Mon Sep 17 00:00:00 2001 From: Sergey Sorokin Date: Thu, 12 May 2016 13:22:26 +0100 Subject: [PATCH 13/43] target-arm: Stage 2 permission fault was fixed in AArch32 state As described in AArch32.CheckS2Permission an instruction fetch fails if XN bit is set or there is no read permission for the address. Signed-off-by: Sergey Sorokin Message-id: 1461002400-3187-1-git-send-email-afarallax@yandex.ru Reviewed-by: Peter Maydell Signed-off-by: Peter Maydell --- target-arm/helper.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/target-arm/helper.c b/target-arm/helper.c index 09638b2e7d..59efb90366 100644 --- a/target-arm/helper.c +++ b/target-arm/helper.c @@ -6708,7 +6708,9 @@ static int get_S2prot(CPUARMState *env, int s2ap, int xn) prot |= PAGE_WRITE; } if (!xn) { - prot |= PAGE_EXEC; + if (arm_el_is_aa64(env, 2) || prot & PAGE_READ) { + prot |= PAGE_EXEC; + } } return prot; } From dddb5223413c5425ae6eaeb3b967627efc9675f7 Mon Sep 17 00:00:00 2001 From: Sergey Sorokin Date: Thu, 12 May 2016 13:22:26 +0100 Subject: [PATCH 14/43] target-arm: Fix descriptor address masking in ARM address translation There is a bug in ARM address translation regime with a long-descriptor format. On the descriptor reading its address is formed from an index which is a part of the input address. And on the first iteration this index is incorrectly masked with 'grainsize' mask. But it can be wider according to pseudo-code. On the other hand on the iterations other than first the descriptor address is formed from the previous level descriptor by masking with 'descaddrmask' value. It always clears just 12 lower bits, but it must clear 'grainsize' lower bits instead according to pseudo-code. The patch fixes both cases. Signed-off-by: Sergey Sorokin Message-id: 1460996853-22117-1-git-send-email-afarallax@yandex.ru Reviewed-by: Peter Maydell Signed-off-by: Peter Maydell --- target-arm/helper.c | 29 +++++++++++------------------ 1 file changed, 11 insertions(+), 18 deletions(-) diff --git a/target-arm/helper.c b/target-arm/helper.c index 59efb90366..3b76dc3501 100644 --- a/target-arm/helper.c +++ b/target-arm/helper.c @@ -7250,7 +7250,7 @@ static bool get_phys_addr_lpae(CPUARMState *env, target_ulong address, uint32_t tg; uint64_t ttbr; int ttbr_select; - hwaddr descaddr, descmask; + hwaddr descaddr, indexmask, indexmask_grainsize; uint32_t tableattrs; target_ulong page_size; uint32_t attrs; @@ -7439,28 +7439,20 @@ static bool get_phys_addr_lpae(CPUARMState *env, target_ulong address, level = startlevel; } - /* Clear the vaddr bits which aren't part of the within-region address, - * so that we don't have to special case things when calculating the - * first descriptor address. - */ - if (va_size != inputsize) { - address &= (1ULL << inputsize) - 1; - } - - descmask = (1ULL << (stride + 3)) - 1; + indexmask_grainsize = (1ULL << (stride + 3)) - 1; + indexmask = (1ULL << (inputsize - (stride * (4 - level)))) - 1; /* Now we can extract the actual base address from the TTBR */ descaddr = extract64(ttbr, 0, 48); - descaddr &= ~((1ULL << (inputsize - (stride * (4 - level)))) - 1); + descaddr &= ~indexmask; /* The address field in the descriptor goes up to bit 39 for ARMv7 - * but up to bit 47 for ARMv8. + * but up to bit 47 for ARMv8, but we use the descaddrmask + * up to bit 39 for AArch32, because we don't need other bits in that case + * to construct next descriptor address (anyway they should be all zeroes). */ - if (arm_feature(env, ARM_FEATURE_V8)) { - descaddrmask = 0xfffffffff000ULL; - } else { - descaddrmask = 0xfffffff000ULL; - } + descaddrmask = ((1ull << (va_size == 64 ? 48 : 40)) - 1) & + ~indexmask_grainsize; /* Secure accesses start with the page table in secure memory and * can be downgraded to non-secure at any step. Non-secure accesses @@ -7472,7 +7464,7 @@ static bool get_phys_addr_lpae(CPUARMState *env, target_ulong address, uint64_t descriptor; bool nstable; - descaddr |= (address >> (stride * (4 - level))) & descmask; + descaddr |= (address >> (stride * (4 - level))) & indexmask; descaddr &= ~7ULL; nstable = extract32(tableattrs, 4, 1); descriptor = arm_ldq_ptw(cs, descaddr, !nstable, mmu_idx, fsr, fi); @@ -7495,6 +7487,7 @@ static bool get_phys_addr_lpae(CPUARMState *env, target_ulong address, */ tableattrs |= extract64(descriptor, 59, 5); level++; + indexmask = indexmask_grainsize; continue; } /* Block entry at level 1 or 2, or page entry at level 3. From 1d41478fd428e01f057d3248292e4cdcdb048523 Mon Sep 17 00:00:00 2001 From: "Edgar E. Iglesias" Date: Thu, 12 May 2016 13:22:26 +0100 Subject: [PATCH 15/43] tcg: Add tcg_set_insn_param Add tcg_set_insn_param as a mechanism to modify an insn parameter after emiting the insn. This is useful for icount and also for embedding fault information for a specific insn. Reviewed-by: Richard Henderson Signed-off-by: Edgar E. Iglesias Message-id: 1461931684-1867-2-git-send-email-edgar.iglesias@gmail.com Signed-off-by: Peter Maydell --- tcg/tcg.h | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/tcg/tcg.h b/tcg/tcg.h index 40c8fbe2ae..01dfebd9a2 100644 --- a/tcg/tcg.h +++ b/tcg/tcg.h @@ -595,6 +595,12 @@ struct TCGContext { extern TCGContext tcg_ctx; +static inline void tcg_set_insn_param(int op_idx, int arg, TCGArg v) +{ + int op_argi = tcg_ctx.gen_op_buf[op_idx].args; + tcg_ctx.gen_opparam_buf[op_argi + arg] = v; +} + /* The number of opcodes emitted so far. */ static inline int tcg_op_buf_count(void) { From 25caa94c4a26daaab1e65c6d887e2972aeb5749e Mon Sep 17 00:00:00 2001 From: "Edgar E. Iglesias" Date: Thu, 12 May 2016 13:22:26 +0100 Subject: [PATCH 16/43] gen-icount: Use tcg_set_insn_param Use tcg_set_insn_param() instead of directly accessing internal tcg data structures to update an insn param. Reviewed-by: Richard Henderson Signed-off-by: Edgar E. Iglesias Message-id: 1461931684-1867-3-git-send-email-edgar.iglesias@gmail.com Signed-off-by: Peter Maydell --- include/exec/gen-icount.h | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/include/exec/gen-icount.h b/include/exec/gen-icount.h index 05d89d358f..a011324b92 100644 --- a/include/exec/gen-icount.h +++ b/include/exec/gen-icount.h @@ -5,14 +5,13 @@ /* Helpers for instruction counting code generation. */ -static TCGArg *icount_arg; +static int icount_start_insn_idx; static TCGLabel *icount_label; static TCGLabel *exitreq_label; static inline void gen_tb_start(TranslationBlock *tb) { TCGv_i32 count, flag, imm; - int i; exitreq_label = gen_new_label(); flag = tcg_temp_new_i32(); @@ -31,13 +30,12 @@ static inline void gen_tb_start(TranslationBlock *tb) -ENV_OFFSET + offsetof(CPUState, icount_decr.u32)); imm = tcg_temp_new_i32(); + /* We emit a movi with a dummy immediate argument. Keep the insn index + * of the movi so that we later (when we know the actual insn count) + * can update the immediate argument with the actual insn count. */ + icount_start_insn_idx = tcg_op_buf_count(); tcg_gen_movi_i32(imm, 0xdeadbeef); - /* This is a horrid hack to allow fixing up the value later. */ - i = tcg_ctx.gen_last_op_idx; - i = tcg_ctx.gen_op_buf[i].args; - icount_arg = &tcg_ctx.gen_opparam_buf[i + 1]; - tcg_gen_sub_i32(count, count, imm); tcg_temp_free_i32(imm); @@ -53,7 +51,9 @@ static void gen_tb_end(TranslationBlock *tb, int num_insns) tcg_gen_exit_tb((uintptr_t)tb + TB_EXIT_REQUESTED); if (tb->cflags & CF_USE_ICOUNT) { - *icount_arg = num_insns; + /* Update the num_insn immediate parameter now that we know + * the actual insn count. */ + tcg_set_insn_param(icount_start_insn_idx, 1, num_insns); gen_set_label(icount_label); tcg_gen_exit_tb((uintptr_t)tb + TB_EXIT_ICOUNT_EXPIRED); } From 094d028a7968236cd2b7f7b96394f7a3b8ad97c8 Mon Sep 17 00:00:00 2001 From: Peter Maydell Date: Thu, 12 May 2016 13:22:26 +0100 Subject: [PATCH 17/43] target-arm: Split data abort syndrome generator Split the data abort syndrome generator into two versions: One with a valid Instruction Specific Syndrome (ISS) and another without. The following new flags are supported by the syndrome generator with ISS: * isv - Instruction syndrome valid * sas - Syndrome access size * sse - Syndrome sign extend * srt - Syndrome register transfer * sf - Sixty-Four bit register width * ar - Acquire/Release These flags are not yet used, so this patch has no functional change except that we will now correctly set the IL bit in data abort syndromes without ISS information. Signed-off-by: Edgar E. Iglesias Message-id: 1461931684-1867-5-git-send-email-edgar.iglesias@gmail.com> [PMM: squashed in with patch which was just adding the IL bit] Reviewed-by: Peter Maydell Signed-off-by: Peter Maydell --- target-arm/internals.h | 24 +++++++++++++++++++++--- target-arm/op_helper.c | 6 ++++-- 2 files changed, 25 insertions(+), 5 deletions(-) diff --git a/target-arm/internals.h b/target-arm/internals.h index 2e70272be2..54a0fb1db7 100644 --- a/target-arm/internals.h +++ b/target-arm/internals.h @@ -263,7 +263,9 @@ enum arm_exception_class { #define ARM_EL_EC_SHIFT 26 #define ARM_EL_IL_SHIFT 25 +#define ARM_EL_ISV_SHIFT 24 #define ARM_EL_IL (1 << ARM_EL_IL_SHIFT) +#define ARM_EL_ISV (1 << ARM_EL_ISV_SHIFT) /* Utility functions for constructing various kinds of syndrome value. * Note that in general we follow the AArch64 syndrome values; in a @@ -383,11 +385,27 @@ static inline uint32_t syn_insn_abort(int same_el, int ea, int s1ptw, int fsc) | (ea << 9) | (s1ptw << 7) | fsc; } -static inline uint32_t syn_data_abort(int same_el, int ea, int cm, int s1ptw, - int wnr, int fsc) +static inline uint32_t syn_data_abort_no_iss(int same_el, + int ea, int cm, int s1ptw, + int wnr, int fsc) { return (EC_DATAABORT << ARM_EL_EC_SHIFT) | (same_el << ARM_EL_EC_SHIFT) - | (ea << 9) | (cm << 8) | (s1ptw << 7) | (wnr << 6) | fsc; + | ARM_EL_IL + | (ea << 9) | (cm << 8) | (s1ptw << 7) | (wnr << 6) | fsc; +} + +static inline uint32_t syn_data_abort_with_iss(int same_el, + int sas, int sse, int srt, + int sf, int ar, + int ea, int cm, int s1ptw, + int wnr, int fsc, + bool is_16bit) +{ + return (EC_DATAABORT << ARM_EL_EC_SHIFT) | (same_el << ARM_EL_EC_SHIFT) + | (is_16bit ? 0 : ARM_EL_IL) + | ARM_EL_ISV | (sas << 22) | (sse << 21) | (srt << 16) + | (sf << 15) | (ar << 14) + | (ea << 9) | (cm << 8) | (s1ptw << 7) | (wnr << 6) | fsc; } static inline uint32_t syn_swstep(int same_el, int isv, int ex) diff --git a/target-arm/op_helper.c b/target-arm/op_helper.c index d626ff1a20..c7fba8526c 100644 --- a/target-arm/op_helper.c +++ b/target-arm/op_helper.c @@ -115,7 +115,8 @@ void tlb_fill(CPUState *cs, target_ulong addr, int is_write, int mmu_idx, syn = syn_insn_abort(same_el, 0, fi.s1ptw, syn); exc = EXCP_PREFETCH_ABORT; } else { - syn = syn_data_abort(same_el, 0, 0, fi.s1ptw, is_write == 1, syn); + syn = syn_data_abort_no_iss(same_el, + 0, 0, fi.s1ptw, is_write == 1, syn); if (is_write == 1 && arm_feature(env, ARM_FEATURE_V6)) { fsr |= (1 << 11); } @@ -161,7 +162,8 @@ void arm_cpu_do_unaligned_access(CPUState *cs, vaddr vaddr, int is_write, } raise_exception(env, EXCP_DATA_ABORT, - syn_data_abort(same_el, 0, 0, 0, is_write == 1, 0x21), + syn_data_abort_no_iss(same_el, + 0, 0, 0, is_write == 1, 0x21), target_el); } From 026a19c3128678d4fe301fc36e8ffacdc9ecccb8 Mon Sep 17 00:00:00 2001 From: "Edgar E. Iglesias" Date: Thu, 12 May 2016 13:22:27 +0100 Subject: [PATCH 18/43] target-arm/translate-a64.c: Use extract32 in disas_ldst_reg_imm9 Use extract32 instead of open coding the bit masking when decoding is_signed and is_extended. This streamlines the decoding with some of the other ldst variants. No functional change. Reviewed-by: Sergey Fedorov Signed-off-by: Edgar E. Iglesias Message-id: 1461931684-1867-6-git-send-email-edgar.iglesias@gmail.com Signed-off-by: Peter Maydell --- target-arm/translate-a64.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/target-arm/translate-a64.c b/target-arm/translate-a64.c index b13cff756a..5c8dddbf98 100644 --- a/target-arm/translate-a64.c +++ b/target-arm/translate-a64.c @@ -2128,8 +2128,8 @@ static void disas_ldst_reg_imm9(DisasContext *s, uint32_t insn) return; } is_store = (opc == 0); - is_signed = opc & (1<<1); - is_extended = (size < 3) && (opc & 1); + is_signed = extract32(opc, 1, 1); + is_extended = (size < 3) && extract32(opc, 0, 1); } switch (idx) { From cd694521ca061a5d0436d5df4ec8c17c8f4dfcdb Mon Sep 17 00:00:00 2001 From: "Edgar E. Iglesias" Date: Thu, 12 May 2016 13:22:27 +0100 Subject: [PATCH 19/43] target-arm/translate-a64.c: Unify some of the ldst_reg decoding The various load/store variants under disas_ldst_reg can all reuse the same decoding for opc, size, rt and is_vector. This patch unifies the decoding in preparation for generating instruction syndromes for data aborts. This will allow us to reduce the number of places to hook in updates to the load/store state needed to generate the insn syndromes. No functional change. Reviewed-by: Sergey Fedorov Signed-off-by: Edgar E. Iglesias Message-id: 1461931684-1867-7-git-send-email-edgar.iglesias@gmail.com Signed-off-by: Peter Maydell --- target-arm/translate-a64.c | 41 +++++++++++++++++++++----------------- 1 file changed, 23 insertions(+), 18 deletions(-) diff --git a/target-arm/translate-a64.c b/target-arm/translate-a64.c index 5c8dddbf98..24f5e177dd 100644 --- a/target-arm/translate-a64.c +++ b/target-arm/translate-a64.c @@ -2086,19 +2086,19 @@ static void disas_ldst_pair(DisasContext *s, uint32_t insn) * size: 00 -> 8 bit, 01 -> 16 bit, 10 -> 32 bit, 11 -> 64bit * opc: 00 -> store, 01 -> loadu, 10 -> loads 64, 11 -> loads 32 */ -static void disas_ldst_reg_imm9(DisasContext *s, uint32_t insn) +static void disas_ldst_reg_imm9(DisasContext *s, uint32_t insn, + int opc, + int size, + int rt, + bool is_vector) { - int rt = extract32(insn, 0, 5); int rn = extract32(insn, 5, 5); int imm9 = sextract32(insn, 12, 9); - int opc = extract32(insn, 22, 2); - int size = extract32(insn, 30, 2); int idx = extract32(insn, 10, 2); bool is_signed = false; bool is_store = false; bool is_extended = false; bool is_unpriv = (idx == 2); - bool is_vector = extract32(insn, 26, 1); bool post_index; bool writeback; @@ -2205,19 +2205,19 @@ static void disas_ldst_reg_imm9(DisasContext *s, uint32_t insn) * Rn: address register or SP for base * Rm: offset register or ZR for offset */ -static void disas_ldst_reg_roffset(DisasContext *s, uint32_t insn) +static void disas_ldst_reg_roffset(DisasContext *s, uint32_t insn, + int opc, + int size, + int rt, + bool is_vector) { - int rt = extract32(insn, 0, 5); int rn = extract32(insn, 5, 5); int shift = extract32(insn, 12, 1); int rm = extract32(insn, 16, 5); - int opc = extract32(insn, 22, 2); int opt = extract32(insn, 13, 3); - int size = extract32(insn, 30, 2); bool is_signed = false; bool is_store = false; bool is_extended = false; - bool is_vector = extract32(insn, 26, 1); TCGv_i64 tcg_rm; TCGv_i64 tcg_addr; @@ -2294,14 +2294,14 @@ static void disas_ldst_reg_roffset(DisasContext *s, uint32_t insn) * Rn: base address register (inc SP) * Rt: target register */ -static void disas_ldst_reg_unsigned_imm(DisasContext *s, uint32_t insn) +static void disas_ldst_reg_unsigned_imm(DisasContext *s, uint32_t insn, + int opc, + int size, + int rt, + bool is_vector) { - int rt = extract32(insn, 0, 5); int rn = extract32(insn, 5, 5); unsigned int imm12 = extract32(insn, 10, 12); - bool is_vector = extract32(insn, 26, 1); - int size = extract32(insn, 30, 2); - int opc = extract32(insn, 22, 2); unsigned int offset; TCGv_i64 tcg_addr; @@ -2360,20 +2360,25 @@ static void disas_ldst_reg_unsigned_imm(DisasContext *s, uint32_t insn) /* Load/store register (all forms) */ static void disas_ldst_reg(DisasContext *s, uint32_t insn) { + int rt = extract32(insn, 0, 5); + int opc = extract32(insn, 22, 2); + bool is_vector = extract32(insn, 26, 1); + int size = extract32(insn, 30, 2); + switch (extract32(insn, 24, 2)) { case 0: if (extract32(insn, 21, 1) == 1 && extract32(insn, 10, 2) == 2) { - disas_ldst_reg_roffset(s, insn); + disas_ldst_reg_roffset(s, insn, opc, size, rt, is_vector); } else { /* Load/store register (unscaled immediate) * Load/store immediate pre/post-indexed * Load/store register unprivileged */ - disas_ldst_reg_imm9(s, insn); + disas_ldst_reg_imm9(s, insn, opc, size, rt, is_vector); } break; case 1: - disas_ldst_reg_unsigned_imm(s, insn); + disas_ldst_reg_unsigned_imm(s, insn, opc, size, rt, is_vector); break; default: unallocated_encoding(s); From 3c09d6caad07b141291a3dd1630b1043aecef3ff Mon Sep 17 00:00:00 2001 From: xiaoqiang zhao Date: Thu, 12 May 2016 13:22:27 +0100 Subject: [PATCH 20/43] hw/display: QOM'ify exynos4210_fimd.c * Drop the old SysBus init function and use instance_init * Move graphic_console_init into realize stage Signed-off-by: xiaoqiang zhao Message-id: 1462417489-28603-2-git-send-email-zxq_yx_007@163.com Reviewed-by: Peter Maydell Signed-off-by: Peter Maydell --- hw/display/exynos4210_fimd.c | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/hw/display/exynos4210_fimd.c b/hw/display/exynos4210_fimd.c index 728eb214a4..e5be713406 100644 --- a/hw/display/exynos4210_fimd.c +++ b/hw/display/exynos4210_fimd.c @@ -1909,9 +1909,10 @@ static const GraphicHwOps exynos4210_fimd_ops = { .gfx_update = exynos4210_fimd_update, }; -static int exynos4210_fimd_init(SysBusDevice *dev) +static void exynos4210_fimd_init(Object *obj) { - Exynos4210fimdState *s = EXYNOS4210_FIMD(dev); + Exynos4210fimdState *s = EXYNOS4210_FIMD(obj); + SysBusDevice *dev = SYS_BUS_DEVICE(obj); s->ifb = NULL; @@ -1919,28 +1920,32 @@ static int exynos4210_fimd_init(SysBusDevice *dev) sysbus_init_irq(dev, &s->irq[1]); sysbus_init_irq(dev, &s->irq[2]); - memory_region_init_io(&s->iomem, OBJECT(s), &exynos4210_fimd_mmio_ops, s, + memory_region_init_io(&s->iomem, obj, &exynos4210_fimd_mmio_ops, s, "exynos4210.fimd", FIMD_REGS_SIZE); sysbus_init_mmio(dev, &s->iomem); - s->console = graphic_console_init(DEVICE(dev), 0, &exynos4210_fimd_ops, s); +} - return 0; +static void exynos4210_fimd_realize(DeviceState *dev, Error **errp) +{ + Exynos4210fimdState *s = EXYNOS4210_FIMD(dev); + + s->console = graphic_console_init(dev, 0, &exynos4210_fimd_ops, s); } static void exynos4210_fimd_class_init(ObjectClass *klass, void *data) { DeviceClass *dc = DEVICE_CLASS(klass); - SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass); dc->vmsd = &exynos4210_fimd_vmstate; dc->reset = exynos4210_fimd_reset; - k->init = exynos4210_fimd_init; + dc->realize = exynos4210_fimd_realize; } static const TypeInfo exynos4210_fimd_info = { .name = TYPE_EXYNOS4210_FIMD, .parent = TYPE_SYS_BUS_DEVICE, .instance_size = sizeof(Exynos4210fimdState), + .instance_init = exynos4210_fimd_init, .class_init = exynos4210_fimd_class_init, }; From 9695200ad807d49be2f2e6f8dec818a382a1396e Mon Sep 17 00:00:00 2001 From: Shannon Zhao Date: Thu, 12 May 2016 13:22:27 +0100 Subject: [PATCH 21/43] ARM: Virt: Set numa-node-id for cpu and memory nodes Generate memory nodes according to NUMA topology. Set numa-node-id property for cpu and memory nodes. Signed-off-by: Shannon Zhao Reviewed-by: Andrew Jones Message-id: 1461667229-9216-2-git-send-email-zhaoshenglong@huawei.com Signed-off-by: Peter Maydell --- hw/arm/boot.c | 43 +++++++++++++++++++++++++++++++++++++------ hw/arm/virt.c | 8 ++++++++ 2 files changed, 45 insertions(+), 6 deletions(-) diff --git a/hw/arm/boot.c b/hw/arm/boot.c index 5876945575..1b913a43ca 100644 --- a/hw/arm/boot.c +++ b/hw/arm/boot.c @@ -14,6 +14,7 @@ #include "hw/arm/linux-boot-if.h" #include "sysemu/kvm.h" #include "sysemu/sysemu.h" +#include "sysemu/numa.h" #include "hw/boards.h" #include "hw/loader.h" #include "elf.h" @@ -405,6 +406,9 @@ static int load_dtb(hwaddr addr, const struct arm_boot_info *binfo, void *fdt = NULL; int size, rc; uint32_t acells, scells; + char *nodename; + unsigned int i; + hwaddr mem_base, mem_len; if (binfo->dtb_filename) { char *filename; @@ -456,12 +460,39 @@ static int load_dtb(hwaddr addr, const struct arm_boot_info *binfo, goto fail; } - rc = qemu_fdt_setprop_sized_cells(fdt, "/memory", "reg", - acells, binfo->loader_start, - scells, binfo->ram_size); - if (rc < 0) { - fprintf(stderr, "couldn't set /memory/reg\n"); - goto fail; + if (nb_numa_nodes > 0) { + /* + * Turn the /memory node created before into a NOP node, then create + * /memory@addr nodes for all numa nodes respectively. + */ + qemu_fdt_nop_node(fdt, "/memory"); + mem_base = binfo->loader_start; + for (i = 0; i < nb_numa_nodes; i++) { + mem_len = numa_info[i].node_mem; + nodename = g_strdup_printf("/memory@%" PRIx64, mem_base); + qemu_fdt_add_subnode(fdt, nodename); + qemu_fdt_setprop_string(fdt, nodename, "device_type", "memory"); + rc = qemu_fdt_setprop_sized_cells(fdt, nodename, "reg", + acells, mem_base, + scells, mem_len); + if (rc < 0) { + fprintf(stderr, "couldn't set %s/reg for node %d\n", nodename, + i); + goto fail; + } + + qemu_fdt_setprop_cell(fdt, nodename, "numa-node-id", i); + mem_base += mem_len; + g_free(nodename); + } + } else { + rc = qemu_fdt_setprop_sized_cells(fdt, "/memory", "reg", + acells, binfo->loader_start, + scells, binfo->ram_size); + if (rc < 0) { + fprintf(stderr, "couldn't set /memory/reg\n"); + goto fail; + } } if (binfo->kernel_cmdline && *binfo->kernel_cmdline) { diff --git a/hw/arm/virt.c b/hw/arm/virt.c index 56d35c7716..fe6b11d24e 100644 --- a/hw/arm/virt.c +++ b/hw/arm/virt.c @@ -38,6 +38,7 @@ #include "net/net.h" #include "sysemu/block-backend.h" #include "sysemu/device_tree.h" +#include "sysemu/numa.h" #include "sysemu/sysemu.h" #include "sysemu/kvm.h" #include "hw/boards.h" @@ -329,6 +330,7 @@ static void fdt_add_cpu_nodes(const VirtBoardInfo *vbi) { int cpu; int addr_cells = 1; + unsigned int i; /* * From Documentation/devicetree/bindings/arm/cpus.txt @@ -378,6 +380,12 @@ static void fdt_add_cpu_nodes(const VirtBoardInfo *vbi) armcpu->mp_affinity); } + for (i = 0; i < nb_numa_nodes; i++) { + if (test_bit(cpu, numa_info[i].node_cpu)) { + qemu_fdt_setprop_cell(vbi->fdt, nodename, "numa-node-id", i); + } + } + g_free(nodename); } } From e6e400d54f092e3aeb17889120640bd24cda2ce1 Mon Sep 17 00:00:00 2001 From: Shannon Zhao Date: Thu, 12 May 2016 13:22:27 +0100 Subject: [PATCH 22/43] ACPI: Add GICC Affinity Structure Cc: Michael S. Tsirkin Cc: Igor Mammedov Signed-off-by: Shannon Zhao Reviewed-by: Andrew Jones Message-id: 1461667229-9216-3-git-send-email-zhaoshenglong@huawei.com Signed-off-by: Peter Maydell --- hw/i386/acpi-build.c | 2 +- include/hw/acpi/acpi-defs.h | 15 ++++++++++++++- 2 files changed, 15 insertions(+), 2 deletions(-) diff --git a/hw/i386/acpi-build.c b/hw/i386/acpi-build.c index 64770034ff..9ae4c0d4ea 100644 --- a/hw/i386/acpi-build.c +++ b/hw/i386/acpi-build.c @@ -2474,7 +2474,7 @@ build_srat(GArray *table_data, GArray *linker, MachineState *machine) int apic_id = apic_ids->cpus[i].arch_id; core = acpi_data_push(table_data, sizeof *core); - core->type = ACPI_SRAT_PROCESSOR; + core->type = ACPI_SRAT_PROCESSOR_APIC; core->length = sizeof(*core); core->local_apic_id = apic_id; curnode = pcms->node_cpu[apic_id]; diff --git a/include/hw/acpi/acpi-defs.h b/include/hw/acpi/acpi-defs.h index c7a03d43b9..bcf5c3ff77 100644 --- a/include/hw/acpi/acpi-defs.h +++ b/include/hw/acpi/acpi-defs.h @@ -455,8 +455,10 @@ struct AcpiSystemResourceAffinityTable } QEMU_PACKED; typedef struct AcpiSystemResourceAffinityTable AcpiSystemResourceAffinityTable; -#define ACPI_SRAT_PROCESSOR 0 +#define ACPI_SRAT_PROCESSOR_APIC 0 #define ACPI_SRAT_MEMORY 1 +#define ACPI_SRAT_PROCESSOR_x2APIC 2 +#define ACPI_SRAT_PROCESSOR_GICC 3 struct AcpiSratProcessorAffinity { @@ -483,6 +485,17 @@ struct AcpiSratMemoryAffinity } QEMU_PACKED; typedef struct AcpiSratMemoryAffinity AcpiSratMemoryAffinity; +struct AcpiSratProcessorGiccAffinity +{ + ACPI_SUB_HEADER_DEF + uint32_t proximity; + uint32_t acpi_processor_uid; + uint32_t flags; + uint32_t clock_domain; +} QEMU_PACKED; + +typedef struct AcpiSratProcessorGiccAffinity AcpiSratProcessorGiccAffinity; + /* PCI fw r3.0 MCFG table. */ /* Subtable */ struct AcpiMcfgAllocation { From ea9fcbd7d0835c397c4a21939401a9b3e923ae90 Mon Sep 17 00:00:00 2001 From: Shannon Zhao Date: Thu, 12 May 2016 13:22:28 +0100 Subject: [PATCH 23/43] ACPI: Fix the definition of proximity in AcpiSratMemoryAffinity ACPI spec says that Proximity Domain is an "Integer that represents the proximity domain to which the processor belongs". So define it as a uint32_t. Cc: Michael S. Tsirkin Cc: Igor Mammedov Signed-off-by: Shannon Zhao Reviewed-by: Andrew Jones Message-id: 1461667229-9216-4-git-send-email-zhaoshenglong@huawei.com Signed-off-by: Peter Maydell --- hw/i386/acpi-build.c | 3 +-- include/hw/acpi/acpi-defs.h | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/hw/i386/acpi-build.c b/hw/i386/acpi-build.c index 9ae4c0d4ea..3c031aaa86 100644 --- a/hw/i386/acpi-build.c +++ b/hw/i386/acpi-build.c @@ -2440,8 +2440,7 @@ acpi_build_srat_memory(AcpiSratMemoryAffinity *numamem, uint64_t base, { numamem->type = ACPI_SRAT_MEMORY; numamem->length = sizeof(*numamem); - memset(numamem->proximity, 0, 4); - numamem->proximity[0] = node; + numamem->proximity = cpu_to_le32(node); numamem->flags = cpu_to_le32(flags); numamem->base_addr = cpu_to_le64(base); numamem->range_length = cpu_to_le64(len); diff --git a/include/hw/acpi/acpi-defs.h b/include/hw/acpi/acpi-defs.h index bcf5c3ff77..850a9626b7 100644 --- a/include/hw/acpi/acpi-defs.h +++ b/include/hw/acpi/acpi-defs.h @@ -475,7 +475,7 @@ typedef struct AcpiSratProcessorAffinity AcpiSratProcessorAffinity; struct AcpiSratMemoryAffinity { ACPI_SUB_HEADER_DEF - uint8_t proximity[4]; + uint32_t proximity; uint16_t reserved1; uint64_t base_addr; uint64_t range_length; From 64b831367b902884e57cf33b77f9a7e64d1c7f90 Mon Sep 17 00:00:00 2001 From: Shannon Zhao Date: Thu, 12 May 2016 13:22:28 +0100 Subject: [PATCH 24/43] ACPI: move acpi_build_srat_memory to common place Move acpi_build_srat_memory to common place so that it could be reused by ARM. Rename it to build_srat_memory. Cc: Michael S. Tsirkin Cc: Igor Mammedov Signed-off-by: Shannon Zhao Reviewed-by: Andrew Jones Message-id: 1461667229-9216-5-git-send-email-zhaoshenglong@huawei.com Signed-off-by: Peter Maydell --- hw/acpi/aml-build.c | 11 +++++++++++ hw/i386/acpi-build.c | 38 +++++++++---------------------------- include/hw/acpi/aml-build.h | 10 ++++++++++ 3 files changed, 30 insertions(+), 29 deletions(-) diff --git a/hw/acpi/aml-build.c b/hw/acpi/aml-build.c index ab89ca6380..cedb74e7cf 100644 --- a/hw/acpi/aml-build.c +++ b/hw/acpi/aml-build.c @@ -1563,3 +1563,14 @@ build_rsdt(GArray *table_data, GArray *linker, GArray *table_offsets, build_header(linker, table_data, (void *)rsdt, "RSDT", rsdt_len, 1, oem_id, oem_table_id); } + +void build_srat_memory(AcpiSratMemoryAffinity *numamem, uint64_t base, + uint64_t len, int node, MemoryAffinityFlags flags) +{ + numamem->type = ACPI_SRAT_MEMORY; + numamem->length = sizeof(*numamem); + numamem->proximity = cpu_to_le32(node); + numamem->flags = cpu_to_le32(flags); + numamem->base_addr = cpu_to_le64(base); + numamem->range_length = cpu_to_le64(len); +} diff --git a/hw/i386/acpi-build.c b/hw/i386/acpi-build.c index 3c031aaa86..279f0d7d05 100644 --- a/hw/i386/acpi-build.c +++ b/hw/i386/acpi-build.c @@ -2427,25 +2427,6 @@ build_tpm2(GArray *table_data, GArray *linker) (void *)tpm2_ptr, "TPM2", sizeof(*tpm2_ptr), 4, NULL, NULL); } -typedef enum { - MEM_AFFINITY_NOFLAGS = 0, - MEM_AFFINITY_ENABLED = (1 << 0), - MEM_AFFINITY_HOTPLUGGABLE = (1 << 1), - MEM_AFFINITY_NON_VOLATILE = (1 << 2), -} MemoryAffinityFlags; - -static void -acpi_build_srat_memory(AcpiSratMemoryAffinity *numamem, uint64_t base, - uint64_t len, int node, MemoryAffinityFlags flags) -{ - numamem->type = ACPI_SRAT_MEMORY; - numamem->length = sizeof(*numamem); - numamem->proximity = cpu_to_le32(node); - numamem->flags = cpu_to_le32(flags); - numamem->base_addr = cpu_to_le64(base); - numamem->range_length = cpu_to_le64(len); -} - static void build_srat(GArray *table_data, GArray *linker, MachineState *machine) { @@ -2491,7 +2472,7 @@ build_srat(GArray *table_data, GArray *linker, MachineState *machine) numa_start = table_data->len; numamem = acpi_data_push(table_data, sizeof *numamem); - acpi_build_srat_memory(numamem, 0, 640*1024, 0, MEM_AFFINITY_ENABLED); + build_srat_memory(numamem, 0, 640 * 1024, 0, MEM_AFFINITY_ENABLED); next_base = 1024 * 1024; for (i = 1; i < pcms->numa_nodes + 1; ++i) { mem_base = next_base; @@ -2507,21 +2488,21 @@ build_srat(GArray *table_data, GArray *linker, MachineState *machine) mem_len -= next_base - pcms->below_4g_mem_size; if (mem_len > 0) { numamem = acpi_data_push(table_data, sizeof *numamem); - acpi_build_srat_memory(numamem, mem_base, mem_len, i - 1, - MEM_AFFINITY_ENABLED); + build_srat_memory(numamem, mem_base, mem_len, i - 1, + MEM_AFFINITY_ENABLED); } mem_base = 1ULL << 32; mem_len = next_base - pcms->below_4g_mem_size; next_base += (1ULL << 32) - pcms->below_4g_mem_size; } numamem = acpi_data_push(table_data, sizeof *numamem); - acpi_build_srat_memory(numamem, mem_base, mem_len, i - 1, - MEM_AFFINITY_ENABLED); + build_srat_memory(numamem, mem_base, mem_len, i - 1, + MEM_AFFINITY_ENABLED); } slots = (table_data->len - numa_start) / sizeof *numamem; for (; slots < pcms->numa_nodes + 2; slots++) { numamem = acpi_data_push(table_data, sizeof *numamem); - acpi_build_srat_memory(numamem, 0, 0, 0, MEM_AFFINITY_NOFLAGS); + build_srat_memory(numamem, 0, 0, 0, MEM_AFFINITY_NOFLAGS); } /* @@ -2531,10 +2512,9 @@ build_srat(GArray *table_data, GArray *linker, MachineState *machine) */ if (hotplugabble_address_space_size) { numamem = acpi_data_push(table_data, sizeof *numamem); - acpi_build_srat_memory(numamem, pcms->hotplug_memory.base, - hotplugabble_address_space_size, 0, - MEM_AFFINITY_HOTPLUGGABLE | - MEM_AFFINITY_ENABLED); + build_srat_memory(numamem, pcms->hotplug_memory.base, + hotplugabble_address_space_size, 0, + MEM_AFFINITY_HOTPLUGGABLE | MEM_AFFINITY_ENABLED); } build_header(linker, table_data, diff --git a/include/hw/acpi/aml-build.h b/include/hw/acpi/aml-build.h index 2c994b351a..7eb51c7885 100644 --- a/include/hw/acpi/aml-build.h +++ b/include/hw/acpi/aml-build.h @@ -198,6 +198,13 @@ typedef enum { AML_PULL_NONE = 3, } AmlPinConfig; +typedef enum { + MEM_AFFINITY_NOFLAGS = 0, + MEM_AFFINITY_ENABLED = (1 << 0), + MEM_AFFINITY_HOTPLUGGABLE = (1 << 1), + MEM_AFFINITY_NON_VOLATILE = (1 << 2), +} MemoryAffinityFlags; + typedef struct AcpiBuildTables { GArray *table_data; @@ -372,4 +379,7 @@ int build_append_named_dword(GArray *array, const char *name_format, ...) GCC_FMT_ATTR(2, 3); +void build_srat_memory(AcpiSratMemoryAffinity *numamem, uint64_t base, + uint64_t len, int node, MemoryAffinityFlags flags); + #endif From 2b302e1e3cfe6a1d71679e8c229c9d5bbe1a33df Mon Sep 17 00:00:00 2001 From: Shannon Zhao Date: Thu, 12 May 2016 13:22:28 +0100 Subject: [PATCH 25/43] ACPI: Virt: Generate SRAT table To support NUMA, it needs to generate SRAT ACPI table. Signed-off-by: Shannon Zhao Reviewed-by: Andrew Jones Message-id: 1461667229-9216-6-git-send-email-zhaoshenglong@huawei.com Signed-off-by: Peter Maydell --- hw/arm/virt-acpi-build.c | 52 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 52 insertions(+) diff --git a/hw/arm/virt-acpi-build.c b/hw/arm/virt-acpi-build.c index f51fe396ce..26a7bac48f 100644 --- a/hw/arm/virt-acpi-build.c +++ b/hw/arm/virt-acpi-build.c @@ -43,6 +43,7 @@ #include "hw/acpi/aml-build.h" #include "hw/pci/pcie_host.h" #include "hw/pci/pci.h" +#include "sysemu/numa.h" #define ARM_SPI_BASE 32 #define ACPI_POWER_BUTTON_DEVICE "PWRB" @@ -413,6 +414,52 @@ build_spcr(GArray *table_data, GArray *linker, VirtGuestInfo *guest_info) NULL, NULL); } +static void +build_srat(GArray *table_data, GArray *linker, VirtGuestInfo *guest_info) +{ + AcpiSystemResourceAffinityTable *srat; + AcpiSratProcessorGiccAffinity *core; + AcpiSratMemoryAffinity *numamem; + int i, j, srat_start; + uint64_t mem_base; + uint32_t *cpu_node = g_malloc0(guest_info->smp_cpus * sizeof(uint32_t)); + + for (i = 0; i < guest_info->smp_cpus; i++) { + for (j = 0; j < nb_numa_nodes; j++) { + if (test_bit(i, numa_info[j].node_cpu)) { + cpu_node[i] = j; + break; + } + } + } + + srat_start = table_data->len; + srat = acpi_data_push(table_data, sizeof(*srat)); + srat->reserved1 = cpu_to_le32(1); + + for (i = 0; i < guest_info->smp_cpus; ++i) { + core = acpi_data_push(table_data, sizeof(*core)); + core->type = ACPI_SRAT_PROCESSOR_GICC; + core->length = sizeof(*core); + core->proximity = cpu_to_le32(cpu_node[i]); + core->acpi_processor_uid = cpu_to_le32(i); + core->flags = cpu_to_le32(1); + } + g_free(cpu_node); + + mem_base = guest_info->memmap[VIRT_MEM].base; + for (i = 0; i < nb_numa_nodes; ++i) { + numamem = acpi_data_push(table_data, sizeof(*numamem)); + build_srat_memory(numamem, mem_base, numa_info[i].node_mem, i, + MEM_AFFINITY_ENABLED); + mem_base += numa_info[i].node_mem; + } + + build_header(linker, table_data, + (void *)(table_data->data + srat_start), "SRAT", + table_data->len - srat_start, 3, NULL, NULL); +} + static void build_mcfg(GArray *table_data, GArray *linker, VirtGuestInfo *guest_info) { @@ -638,6 +685,11 @@ void virt_acpi_build(VirtGuestInfo *guest_info, AcpiBuildTables *tables) acpi_add_table(table_offsets, tables_blob); build_spcr(tables_blob, tables->linker, guest_info); + if (nb_numa_nodes > 0) { + acpi_add_table(table_offsets, tables_blob); + build_srat(tables_blob, tables->linker, guest_info); + } + /* RSDT is pointed to by RSDP */ rsdt = tables_blob->len; build_rsdt(tables_blob, tables->linker, table_offsets, NULL, NULL); From 825482adde1f971cbddf27e15fb4453ab3fae994 Mon Sep 17 00:00:00 2001 From: Jean-Christophe DUBOIS Date: Thu, 12 May 2016 13:22:28 +0100 Subject: [PATCH 26/43] ARM: Factor out ARM on/off PSCI control functions Split ARM on/off function from PSCI support code. This will allow to reuse these functions in other code. Signed-off-by: Jean-Christophe Dubois Reviewed-by: Peter Maydell Signed-off-by: Peter Maydell --- target-arm/Makefile.objs | 1 + target-arm/arm-powerctl.c | 224 ++++++++++++++++++++++++++++++++++++++ target-arm/arm-powerctl.h | 75 +++++++++++++ target-arm/psci.c | 70 ++---------- 4 files changed, 307 insertions(+), 63 deletions(-) create mode 100644 target-arm/arm-powerctl.c create mode 100644 target-arm/arm-powerctl.h diff --git a/target-arm/Makefile.objs b/target-arm/Makefile.objs index 82cbe6bbad..f20641163c 100644 --- a/target-arm/Makefile.objs +++ b/target-arm/Makefile.objs @@ -9,3 +9,4 @@ obj-y += neon_helper.o iwmmxt_helper.o obj-y += gdbstub.o obj-$(TARGET_AARCH64) += cpu64.o translate-a64.o helper-a64.o gdbstub64.o obj-y += crypto_helper.o +obj-y += arm-powerctl.o diff --git a/target-arm/arm-powerctl.c b/target-arm/arm-powerctl.c new file mode 100644 index 0000000000..cb9919b465 --- /dev/null +++ b/target-arm/arm-powerctl.c @@ -0,0 +1,224 @@ +/* + * QEMU support -- ARM Power Control specific functions. + * + * Copyright (c) 2016 Jean-Christophe Dubois + * + * This work is licensed under the terms of the GNU GPL, version 2 or later. + * See the COPYING file in the top-level directory. + * + */ + +#include "qemu/osdep.h" +#include +#include +#include "internals.h" +#include "arm-powerctl.h" + +#ifndef DEBUG_ARM_POWERCTL +#define DEBUG_ARM_POWERCTL 0 +#endif + +#define DPRINTF(fmt, args...) \ + do { \ + if (DEBUG_ARM_POWERCTL) { \ + fprintf(stderr, "[ARM]%s: " fmt , __func__, ##args); \ + } \ + } while (0) + +CPUState *arm_get_cpu_by_id(uint64_t id) +{ + CPUState *cpu; + + DPRINTF("cpu %" PRId64 "\n", id); + + CPU_FOREACH(cpu) { + ARMCPU *armcpu = ARM_CPU(cpu); + + if (armcpu->mp_affinity == id) { + return cpu; + } + } + + qemu_log_mask(LOG_GUEST_ERROR, + "[ARM]%s: Requesting unknown CPU %" PRId64 "\n", + __func__, id); + + return NULL; +} + +int arm_set_cpu_on(uint64_t cpuid, uint64_t entry, uint64_t context_id, + uint32_t target_el, bool target_aa64) +{ + CPUState *target_cpu_state; + ARMCPU *target_cpu; + + DPRINTF("cpu %" PRId64 " (EL %d, %s) @ 0x%" PRIx64 " with R0 = 0x%" PRIx64 + "\n", cpuid, target_el, target_aa64 ? "aarch64" : "aarch32", entry, + context_id); + + /* requested EL level need to be in the 1 to 3 range */ + assert((target_el > 0) && (target_el < 4)); + + if (target_aa64 && (entry & 3)) { + /* + * if we are booting in AArch64 mode then "entry" needs to be 4 bytes + * aligned. + */ + return QEMU_ARM_POWERCTL_INVALID_PARAM; + } + + /* Retrieve the cpu we are powering up */ + target_cpu_state = arm_get_cpu_by_id(cpuid); + if (!target_cpu_state) { + /* The cpu was not found */ + return QEMU_ARM_POWERCTL_INVALID_PARAM; + } + + target_cpu = ARM_CPU(target_cpu_state); + if (!target_cpu->powered_off) { + qemu_log_mask(LOG_GUEST_ERROR, + "[ARM]%s: CPU %" PRId64 " is already on\n", + __func__, cpuid); + return QEMU_ARM_POWERCTL_ALREADY_ON; + } + + /* + * The newly brought CPU is requested to enter the exception level + * "target_el" and be in the requested mode (AArch64 or AArch32). + */ + + if (((target_el == 3) && !arm_feature(&target_cpu->env, ARM_FEATURE_EL3)) || + ((target_el == 2) && !arm_feature(&target_cpu->env, ARM_FEATURE_EL2))) { + /* + * The CPU does not support requested level + */ + return QEMU_ARM_POWERCTL_INVALID_PARAM; + } + + if (!target_aa64 && arm_feature(&target_cpu->env, ARM_FEATURE_AARCH64)) { + /* + * For now we don't support booting an AArch64 CPU in AArch32 mode + * TODO: We should add this support later + */ + qemu_log_mask(LOG_UNIMP, + "[ARM]%s: Starting AArch64 CPU %" PRId64 + " in AArch32 mode is not supported yet\n", + __func__, cpuid); + return QEMU_ARM_POWERCTL_INVALID_PARAM; + } + + /* Initialize the cpu we are turning on */ + cpu_reset(target_cpu_state); + target_cpu->powered_off = false; + target_cpu_state->halted = 0; + + if (target_aa64) { + if ((target_el < 3) && arm_feature(&target_cpu->env, ARM_FEATURE_EL3)) { + /* + * As target mode is AArch64, we need to set lower + * exception level (the requested level 2) to AArch64 + */ + target_cpu->env.cp15.scr_el3 |= SCR_RW; + } + + if ((target_el < 2) && arm_feature(&target_cpu->env, ARM_FEATURE_EL2)) { + /* + * As target mode is AArch64, we need to set lower + * exception level (the requested level 1) to AArch64 + */ + target_cpu->env.cp15.hcr_el2 |= HCR_RW; + } + + target_cpu->env.pstate = aarch64_pstate_mode(target_el, true); + } else { + /* We are requested to boot in AArch32 mode */ + static uint32_t mode_for_el[] = { 0, + ARM_CPU_MODE_SVC, + ARM_CPU_MODE_HYP, + ARM_CPU_MODE_SVC }; + + cpsr_write(&target_cpu->env, mode_for_el[target_el], CPSR_M, + CPSRWriteRaw); + } + + if (target_el == 3) { + /* Processor is in secure mode */ + target_cpu->env.cp15.scr_el3 &= ~SCR_NS; + } else { + /* Processor is not in secure mode */ + target_cpu->env.cp15.scr_el3 |= SCR_NS; + } + + /* We check if the started CPU is now at the correct level */ + assert(target_el == arm_current_el(&target_cpu->env)); + + if (target_aa64) { + target_cpu->env.xregs[0] = context_id; + target_cpu->env.thumb = false; + } else { + target_cpu->env.regs[0] = context_id; + target_cpu->env.thumb = entry & 1; + entry &= 0xfffffffe; + } + + /* Start the new CPU at the requested address */ + cpu_set_pc(target_cpu_state, entry); + + /* We are good to go */ + return QEMU_ARM_POWERCTL_RET_SUCCESS; +} + +int arm_set_cpu_off(uint64_t cpuid) +{ + CPUState *target_cpu_state; + ARMCPU *target_cpu; + + DPRINTF("cpu %" PRId64 "\n", cpuid); + + /* change to the cpu we are powering up */ + target_cpu_state = arm_get_cpu_by_id(cpuid); + if (!target_cpu_state) { + return QEMU_ARM_POWERCTL_INVALID_PARAM; + } + target_cpu = ARM_CPU(target_cpu_state); + if (target_cpu->powered_off) { + qemu_log_mask(LOG_GUEST_ERROR, + "[ARM]%s: CPU %" PRId64 " is already off\n", + __func__, cpuid); + return QEMU_ARM_POWERCTL_IS_OFF; + } + + target_cpu->powered_off = true; + target_cpu_state->halted = 1; + target_cpu_state->exception_index = EXCP_HLT; + cpu_loop_exit(target_cpu_state); + /* notreached */ + + return QEMU_ARM_POWERCTL_RET_SUCCESS; +} + +int arm_reset_cpu(uint64_t cpuid) +{ + CPUState *target_cpu_state; + ARMCPU *target_cpu; + + DPRINTF("cpu %" PRId64 "\n", cpuid); + + /* change to the cpu we are resetting */ + target_cpu_state = arm_get_cpu_by_id(cpuid); + if (!target_cpu_state) { + return QEMU_ARM_POWERCTL_INVALID_PARAM; + } + target_cpu = ARM_CPU(target_cpu_state); + if (target_cpu->powered_off) { + qemu_log_mask(LOG_GUEST_ERROR, + "[ARM]%s: CPU %" PRId64 " is off\n", + __func__, cpuid); + return QEMU_ARM_POWERCTL_IS_OFF; + } + + /* Reset the cpu */ + cpu_reset(target_cpu_state); + + return QEMU_ARM_POWERCTL_RET_SUCCESS; +} diff --git a/target-arm/arm-powerctl.h b/target-arm/arm-powerctl.h new file mode 100644 index 0000000000..98ee04989b --- /dev/null +++ b/target-arm/arm-powerctl.h @@ -0,0 +1,75 @@ +/* + * QEMU support -- ARM Power Control specific functions. + * + * Copyright (c) 2016 Jean-Christophe Dubois + * + * This work is licensed under the terms of the GNU GPL, version 2 or later. + * See the COPYING file in the top-level directory. + * + */ + +#ifndef QEMU_ARM_POWERCTL_H +#define QEMU_ARM_POWERCTL_H + +#include "kvm-consts.h" + +#define QEMU_ARM_POWERCTL_RET_SUCCESS QEMU_PSCI_RET_SUCCESS +#define QEMU_ARM_POWERCTL_INVALID_PARAM QEMU_PSCI_RET_INVALID_PARAMS +#define QEMU_ARM_POWERCTL_ALREADY_ON QEMU_PSCI_RET_ALREADY_ON +#define QEMU_ARM_POWERCTL_IS_OFF QEMU_PSCI_RET_DENIED + +/* + * arm_get_cpu_by_id: + * @cpuid: the id of the CPU we want to retrieve the state + * + * Retrieve a CPUState object from its CPU ID provided in @cpuid. + * + * Returns: a pointer to the CPUState structure of the requested CPU. + */ +CPUState *arm_get_cpu_by_id(uint64_t cpuid); + +/* + * arm_set_cpu_on: + * @cpuid: the id of the CPU we want to start/wake up. + * @entry: the address the CPU shall start from. + * @context_id: the value to put in r0/x0. + * @target_el: The desired exception level. + * @target_aa64: 1 if the requested mode is AArch64. 0 otherwise. + * + * Start the cpu designated by @cpuid in @target_el exception level. The mode + * shall be AArch64 if @target_aa64 is set to 1. Otherwise the mode is + * AArch32. The CPU shall start at @entry with @context_id in r0/x0. + * + * Returns: QEMU_ARM_POWERCTL_RET_SUCCESS on success. + * QEMU_ARM_POWERCTL_INVALID_PARAM if bad parameters are provided. + * QEMU_ARM_POWERCTL_ALREADY_ON if the CPU was already started. + */ +int arm_set_cpu_on(uint64_t cpuid, uint64_t entry, uint64_t context_id, + uint32_t target_el, bool target_aa64); + +/* + * arm_set_cpu_off: + * @cpuid: the id of the CPU we want to stop/shut down. + * + * Stop the cpu designated by @cpuid. + * + * Returns: QEMU_ARM_POWERCTL_RET_SUCCESS on success. + * QEMU_ARM_POWERCTL_INVALID_PARAM if bad parameters are provided. + * QEMU_ARM_POWERCTL_IS_OFF if CPU is already off + */ + +int arm_set_cpu_off(uint64_t cpuid); + +/* + * arm_reset_cpu: + * @cpuid: the id of the CPU we want to reset. + * + * Reset the cpu designated by @cpuid. + * + * Returns: QEMU_ARM_POWERCTL_RET_SUCCESS on success. + * QEMU_ARM_POWERCTL_INVALID_PARAM if bad parameters are provided. + * QEMU_ARM_POWERCTL_IS_OFF if CPU is off + */ +int arm_reset_cpu(uint64_t cpuid); + +#endif diff --git a/target-arm/psci.c b/target-arm/psci.c index c55487f872..ce2e0dca39 100644 --- a/target-arm/psci.c +++ b/target-arm/psci.c @@ -22,6 +22,7 @@ #include #include #include "internals.h" +#include "arm-powerctl.h" bool arm_is_psci_call(ARMCPU *cpu, int excp_type) { @@ -73,21 +74,6 @@ bool arm_is_psci_call(ARMCPU *cpu, int excp_type) } } -static CPUState *get_cpu_by_id(uint64_t id) -{ - CPUState *cpu; - - CPU_FOREACH(cpu) { - ARMCPU *armcpu = ARM_CPU(cpu); - - if (armcpu->mp_affinity == id) { - return cpu; - } - } - - return NULL; -} - void arm_handle_psci_call(ARMCPU *cpu) { /* @@ -98,7 +84,6 @@ void arm_handle_psci_call(ARMCPU *cpu) * Additional information about the calling convention used is available in * the document 'SMC Calling Convention' (ARM DEN 0028) */ - CPUState *cs = CPU(cpu); CPUARMState *env = &cpu->env; uint64_t param[4]; uint64_t context_id, mpidr; @@ -123,7 +108,6 @@ void arm_handle_psci_call(ARMCPU *cpu) switch (param[0]) { CPUState *target_cpu_state; ARMCPU *target_cpu; - CPUClass *target_cpu_class; case QEMU_PSCI_0_2_FN_PSCI_VERSION: ret = QEMU_PSCI_0_2_RET_VERSION_0_2; @@ -137,7 +121,7 @@ void arm_handle_psci_call(ARMCPU *cpu) switch (param[2]) { case 0: - target_cpu_state = get_cpu_by_id(mpidr); + target_cpu_state = arm_get_cpu_by_id(mpidr); if (!target_cpu_state) { ret = QEMU_PSCI_RET_INVALID_PARAMS; break; @@ -167,52 +151,13 @@ void arm_handle_psci_call(ARMCPU *cpu) mpidr = param[1]; entry = param[2]; context_id = param[3]; - - /* change to the cpu we are powering up */ - target_cpu_state = get_cpu_by_id(mpidr); - if (!target_cpu_state) { - ret = QEMU_PSCI_RET_INVALID_PARAMS; - break; - } - target_cpu = ARM_CPU(target_cpu_state); - if (!target_cpu->powered_off) { - ret = QEMU_PSCI_RET_ALREADY_ON; - break; - } - target_cpu_class = CPU_GET_CLASS(target_cpu); - - /* Initialize the cpu we are turning on */ - cpu_reset(target_cpu_state); - target_cpu->powered_off = false; - target_cpu_state->halted = 0; - /* * The PSCI spec mandates that newly brought up CPUs enter the * exception level of the caller in the same execution mode as * the caller, with context_id in x0/r0, respectively. - * - * For now, it is sufficient to assert() that CPUs come out of - * reset in the same mode as the calling CPU, since we only - * implement EL1, which means that - * (a) there is no EL2 for the calling CPU to trap into to change - * its state - * (b) the newly brought up CPU enters EL1 immediately after coming - * out of reset in the default state */ - assert(is_a64(env) == is_a64(&target_cpu->env)); - if (is_a64(env)) { - if (entry & 1) { - ret = QEMU_PSCI_RET_INVALID_PARAMS; - break; - } - target_cpu->env.xregs[0] = context_id; - } else { - target_cpu->env.regs[0] = context_id; - target_cpu->env.thumb = entry & 1; - } - target_cpu_class->set_pc(target_cpu_state, entry); - - ret = 0; + ret = arm_set_cpu_on(mpidr, entry, context_id, arm_current_el(env), + is_a64(env)); break; case QEMU_PSCI_0_1_FN_CPU_OFF: case QEMU_PSCI_0_2_FN_CPU_OFF: @@ -250,9 +195,8 @@ err: return; cpu_off: - cpu->powered_off = true; - cs->halted = 1; - cs->exception_index = EXCP_HLT; - cpu_loop_exit(cs); + ret = arm_set_cpu_off(cpu->mp_affinity); /* notreached */ + /* sanity check in case something failed */ + assert(ret == QEMU_ARM_POWERCTL_RET_SUCCESS); } From 1983057470e719d83ed4bc0fd48e480bfaf09d8a Mon Sep 17 00:00:00 2001 From: Jean-Christophe DUBOIS Date: Thu, 12 May 2016 13:22:28 +0100 Subject: [PATCH 27/43] i.MX: Add i.MX6 System Reset Controller device. This controller is also present in i.MX5X devices but they are not yet emulated by QEMU. Reviewed-by: Peter Maydell Signed-off-by: Jean-Christophe Dubois Signed-off-by: Peter Maydell --- hw/misc/Makefile.objs | 1 + hw/misc/imx6_src.c | 264 +++++++++++++++++++++++++++++++++++++ include/hw/misc/imx6_src.h | 73 ++++++++++ 3 files changed, 338 insertions(+) create mode 100644 hw/misc/imx6_src.c create mode 100644 include/hw/misc/imx6_src.h diff --git a/hw/misc/Makefile.objs b/hw/misc/Makefile.objs index 93f952880a..bc0dd2cc75 100644 --- a/hw/misc/Makefile.objs +++ b/hw/misc/Makefile.objs @@ -29,6 +29,7 @@ obj-$(CONFIG_IMX) += imx_ccm.o obj-$(CONFIG_IMX) += imx31_ccm.o obj-$(CONFIG_IMX) += imx25_ccm.o obj-$(CONFIG_IMX) += imx6_ccm.o +obj-$(CONFIG_IMX) += imx6_src.o obj-$(CONFIG_MILKYMIST) += milkymist-hpdmc.o obj-$(CONFIG_MILKYMIST) += milkymist-pfpu.o obj-$(CONFIG_MAINSTONE) += mst_fpga.o diff --git a/hw/misc/imx6_src.c b/hw/misc/imx6_src.c new file mode 100644 index 0000000000..6b026b459f --- /dev/null +++ b/hw/misc/imx6_src.c @@ -0,0 +1,264 @@ +/* + * IMX6 System Reset Controller + * + * Copyright (c) 2015 Jean-Christophe Dubois + * + * This work is licensed under the terms of the GNU GPL, version 2 or later. + * See the COPYING file in the top-level directory. + * + */ + +#include "qemu/osdep.h" +#include "hw/misc/imx6_src.h" +#include "sysemu/sysemu.h" +#include "qemu/bitops.h" +#include "arm-powerctl.h" + +#ifndef DEBUG_IMX6_SRC +#define DEBUG_IMX6_SRC 0 +#endif + +#define DPRINTF(fmt, args...) \ + do { \ + if (DEBUG_IMX6_SRC) { \ + fprintf(stderr, "[%s]%s: " fmt , TYPE_IMX6_SRC, \ + __func__, ##args); \ + } \ + } while (0) + +static char const *imx6_src_reg_name(uint32_t reg) +{ + static char unknown[20]; + + switch (reg) { + case SRC_SCR: + return "SRC_SCR"; + case SRC_SBMR1: + return "SRC_SBMR1"; + case SRC_SRSR: + return "SRC_SRSR"; + case SRC_SISR: + return "SRC_SISR"; + case SRC_SIMR: + return "SRC_SIMR"; + case SRC_SBMR2: + return "SRC_SBMR2"; + case SRC_GPR1: + return "SRC_GPR1"; + case SRC_GPR2: + return "SRC_GPR2"; + case SRC_GPR3: + return "SRC_GPR3"; + case SRC_GPR4: + return "SRC_GPR4"; + case SRC_GPR5: + return "SRC_GPR5"; + case SRC_GPR6: + return "SRC_GPR6"; + case SRC_GPR7: + return "SRC_GPR7"; + case SRC_GPR8: + return "SRC_GPR8"; + case SRC_GPR9: + return "SRC_GPR9"; + case SRC_GPR10: + return "SRC_GPR10"; + default: + sprintf(unknown, "%d ?", reg); + return unknown; + } +} + +static const VMStateDescription vmstate_imx6_src = { + .name = TYPE_IMX6_SRC, + .version_id = 1, + .minimum_version_id = 1, + .fields = (VMStateField[]) { + VMSTATE_UINT32_ARRAY(regs, IMX6SRCState, SRC_MAX), + VMSTATE_END_OF_LIST() + }, +}; + +static void imx6_src_reset(DeviceState *dev) +{ + IMX6SRCState *s = IMX6_SRC(dev); + + DPRINTF("\n"); + + memset(s->regs, 0, sizeof(s->regs)); + + /* Set reset values */ + s->regs[SRC_SCR] = 0x521; + s->regs[SRC_SRSR] = 0x1; + s->regs[SRC_SIMR] = 0x1F; +} + +static uint64_t imx6_src_read(void *opaque, hwaddr offset, unsigned size) +{ + uint32_t value = 0; + IMX6SRCState *s = (IMX6SRCState *)opaque; + uint32_t index = offset >> 2; + + if (index < SRC_MAX) { + value = s->regs[index]; + } else { + qemu_log_mask(LOG_GUEST_ERROR, "[%s]%s: Bad register at offset 0x%" + HWADDR_PRIx "\n", TYPE_IMX6_SRC, __func__, offset); + + } + + DPRINTF("reg[%s] => 0x%" PRIx32 "\n", imx6_src_reg_name(index), value); + + return value; +} + +static void imx6_src_write(void *opaque, hwaddr offset, uint64_t value, + unsigned size) +{ + IMX6SRCState *s = (IMX6SRCState *)opaque; + uint32_t index = offset >> 2; + unsigned long change_mask; + unsigned long current_value = value; + + if (index >= SRC_MAX) { + qemu_log_mask(LOG_GUEST_ERROR, "[%s]%s: Bad register at offset 0x%" + HWADDR_PRIx "\n", TYPE_IMX6_SRC, __func__, offset); + return; + } + + DPRINTF("reg[%s] <= 0x%" PRIx32 "\n", imx6_src_reg_name(index), + (uint32_t)current_value); + + change_mask = s->regs[index] ^ (uint32_t)current_value; + + switch (index) { + case SRC_SCR: + /* + * On real hardware when the system reset controller starts a + * secondary CPU it runs through some boot ROM code which reads + * the SRC_GPRX registers controlling the start address and branches + * to it. + * Here we are taking a short cut and branching directly to the + * requested address (we don't want to run the boot ROM code inside + * QEMU) + */ + if (EXTRACT(change_mask, CORE3_ENABLE)) { + if (EXTRACT(current_value, CORE3_ENABLE)) { + /* CORE 3 is brought up */ + arm_set_cpu_on(3, s->regs[SRC_GPR7], s->regs[SRC_GPR8], + 3, false); + } else { + /* CORE 3 is shut down */ + arm_set_cpu_off(3); + } + /* We clear the reset bits as the processor changed state */ + clear_bit(CORE3_RST_SHIFT, ¤t_value); + clear_bit(CORE3_RST_SHIFT, &change_mask); + } + if (EXTRACT(change_mask, CORE2_ENABLE)) { + if (EXTRACT(current_value, CORE2_ENABLE)) { + /* CORE 2 is brought up */ + arm_set_cpu_on(2, s->regs[SRC_GPR5], s->regs[SRC_GPR6], + 3, false); + } else { + /* CORE 3 is shut down */ + arm_set_cpu_off(2); + } + /* We clear the reset bits as the processor changed state */ + clear_bit(CORE2_RST_SHIFT, ¤t_value); + clear_bit(CORE2_RST_SHIFT, &change_mask); + } + if (EXTRACT(change_mask, CORE1_ENABLE)) { + if (EXTRACT(current_value, CORE1_ENABLE)) { + /* CORE 1 is brought up */ + arm_set_cpu_on(1, s->regs[SRC_GPR3], s->regs[SRC_GPR4], + 3, false); + } else { + /* CORE 3 is shut down */ + arm_set_cpu_off(1); + } + /* We clear the reset bits as the processor changed state */ + clear_bit(CORE1_RST_SHIFT, ¤t_value); + clear_bit(CORE1_RST_SHIFT, &change_mask); + } + if (EXTRACT(change_mask, CORE0_RST)) { + arm_reset_cpu(0); + clear_bit(CORE0_RST_SHIFT, ¤t_value); + } + if (EXTRACT(change_mask, CORE1_RST)) { + arm_reset_cpu(1); + clear_bit(CORE1_RST_SHIFT, ¤t_value); + } + if (EXTRACT(change_mask, CORE2_RST)) { + arm_reset_cpu(2); + clear_bit(CORE2_RST_SHIFT, ¤t_value); + } + if (EXTRACT(change_mask, CORE3_RST)) { + arm_reset_cpu(3); + clear_bit(CORE3_RST_SHIFT, ¤t_value); + } + if (EXTRACT(change_mask, SW_IPU2_RST)) { + /* We pretend the IPU2 is reset */ + clear_bit(SW_IPU2_RST_SHIFT, ¤t_value); + } + if (EXTRACT(change_mask, SW_IPU1_RST)) { + /* We pretend the IPU1 is reset */ + clear_bit(SW_IPU1_RST_SHIFT, ¤t_value); + } + s->regs[index] = current_value; + break; + default: + s->regs[index] = current_value; + break; + } +} + +static const struct MemoryRegionOps imx6_src_ops = { + .read = imx6_src_read, + .write = imx6_src_write, + .endianness = DEVICE_NATIVE_ENDIAN, + .valid = { + /* + * Our device would not work correctly if the guest was doing + * unaligned access. This might not be a limitation on the real + * device but in practice there is no reason for a guest to access + * this device unaligned. + */ + .min_access_size = 4, + .max_access_size = 4, + .unaligned = false, + }, +}; + +static void imx6_src_realize(DeviceState *dev, Error **errp) +{ + IMX6SRCState *s = IMX6_SRC(dev); + + memory_region_init_io(&s->iomem, OBJECT(dev), &imx6_src_ops, s, + TYPE_IMX6_SRC, 0x1000); + sysbus_init_mmio(SYS_BUS_DEVICE(dev), &s->iomem); +} + +static void imx6_src_class_init(ObjectClass *klass, void *data) +{ + DeviceClass *dc = DEVICE_CLASS(klass); + + dc->realize = imx6_src_realize; + dc->reset = imx6_src_reset; + dc->vmsd = &vmstate_imx6_src; + dc->desc = "i.MX6 System Reset Controller"; +} + +static const TypeInfo imx6_src_info = { + .name = TYPE_IMX6_SRC, + .parent = TYPE_SYS_BUS_DEVICE, + .instance_size = sizeof(IMX6SRCState), + .class_init = imx6_src_class_init, +}; + +static void imx6_src_register_types(void) +{ + type_register_static(&imx6_src_info); +} + +type_init(imx6_src_register_types) diff --git a/include/hw/misc/imx6_src.h b/include/hw/misc/imx6_src.h new file mode 100644 index 0000000000..eb3640732e --- /dev/null +++ b/include/hw/misc/imx6_src.h @@ -0,0 +1,73 @@ +/* + * IMX6 System Reset Controller + * + * Copyright (C) 2012 NICTA + * Updated by Jean-Christophe Dubois + * + * This work is licensed under the terms of the GNU GPL, version 2 or later. + * See the COPYING file in the top-level directory. + */ + +#ifndef IMX6_SRC_H +#define IMX6_SRC_H + +#include "hw/sysbus.h" +#include "qemu/bitops.h" + +#define SRC_SCR 0 +#define SRC_SBMR1 1 +#define SRC_SRSR 2 +#define SRC_SISR 5 +#define SRC_SIMR 6 +#define SRC_SBMR2 7 +#define SRC_GPR1 8 +#define SRC_GPR2 9 +#define SRC_GPR3 10 +#define SRC_GPR4 11 +#define SRC_GPR5 12 +#define SRC_GPR6 13 +#define SRC_GPR7 14 +#define SRC_GPR8 15 +#define SRC_GPR9 16 +#define SRC_GPR10 17 +#define SRC_MAX 18 + +/* SRC_SCR */ +#define CORE3_ENABLE_SHIFT 24 +#define CORE3_ENABLE_LENGTH 1 +#define CORE2_ENABLE_SHIFT 23 +#define CORE2_ENABLE_LENGTH 1 +#define CORE1_ENABLE_SHIFT 22 +#define CORE1_ENABLE_LENGTH 1 +#define CORE3_RST_SHIFT 16 +#define CORE3_RST_LENGTH 1 +#define CORE2_RST_SHIFT 15 +#define CORE2_RST_LENGTH 1 +#define CORE1_RST_SHIFT 14 +#define CORE1_RST_LENGTH 1 +#define CORE0_RST_SHIFT 13 +#define CORE0_RST_LENGTH 1 +#define SW_IPU1_RST_SHIFT 3 +#define SW_IPU1_RST_LENGTH 1 +#define SW_IPU2_RST_SHIFT 12 +#define SW_IPU2_RST_LENGTH 1 +#define WARM_RST_ENABLE_SHIFT 0 +#define WARM_RST_ENABLE_LENGTH 1 + +#define EXTRACT(value, name) extract32(value, name##_SHIFT, name##_LENGTH) + +#define TYPE_IMX6_SRC "imx6.src" +#define IMX6_SRC(obj) OBJECT_CHECK(IMX6SRCState, (obj), TYPE_IMX6_SRC) + +typedef struct IMX6SRCState { + /* */ + SysBusDevice parent_obj; + + /* */ + MemoryRegion iomem; + + uint32_t regs[SRC_MAX]; + +} IMX6SRCState; + +#endif /* IMX6_SRC_H */ From 53374b16a28b204e7ee73639156f0b3a45cf01c0 Mon Sep 17 00:00:00 2001 From: Jean-Christophe DUBOIS Date: Thu, 12 May 2016 13:22:29 +0100 Subject: [PATCH 28/43] FIFO: Add a FIFO32 implementation This one is build on top of the existing FIFO8 Reviewed-by: Peter Maydell Signed-off-by: Jean-Christophe Dubois Signed-off-by: Peter Maydell --- include/qemu/fifo32.h | 191 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 191 insertions(+) create mode 100644 include/qemu/fifo32.h diff --git a/include/qemu/fifo32.h b/include/qemu/fifo32.h new file mode 100644 index 0000000000..2e5a0ccddf --- /dev/null +++ b/include/qemu/fifo32.h @@ -0,0 +1,191 @@ +/* + * Generic FIFO32 component, based on FIFO8. + * + * Copyright (c) 2016 Jean-Christophe Dubois + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, see . + */ + +#ifndef FIFO32_H +#define FIFO32_H + +#include "qemu/osdep.h" +#include "qemu/fifo8.h" + +typedef struct { + Fifo8 fifo; +} Fifo32; + +/** + * fifo32_create: + * @fifo: struct Fifo32 to initialise with new FIFO + * @capacity: capacity of the newly created FIFO expressed in 32 bit words + * + * Create a FIFO of the specified size. Clients should call fifo32_destroy() + * when finished using the fifo. The FIFO is initially empty. + */ + +static inline void fifo32_create(Fifo32 *fifo, uint32_t capacity) +{ + fifo8_create(&fifo->fifo, capacity * sizeof(uint32_t)); +} + +/** + * fifo32_destroy: + * @fifo: FIFO to cleanup + * + * Cleanup a FIFO created with fifo32_create(). Frees memory created for FIFO + * storage. The FIFO is no longer usable after this has been called. + */ + +static inline void fifo32_destroy(Fifo32 *fifo) +{ + fifo8_destroy(&fifo->fifo); +} + +/** + * fifo32_num_free: + * @fifo: FIFO to check + * + * Return the number of free uint32_t slots in the FIFO. + * + * Returns: Number of free 32 bit words. + */ + +static inline uint32_t fifo32_num_free(Fifo32 *fifo) +{ + return DIV_ROUND_UP(fifo8_num_free(&fifo->fifo), sizeof(uint32_t)); +} + +/** + * fifo32_num_used: + * @fifo: FIFO to check + * + * Return the number of used uint32_t slots in the FIFO. + * + * Returns: Number of used 32 bit words. + */ + +static inline uint32_t fifo32_num_used(Fifo32 *fifo) +{ + return DIV_ROUND_UP(fifo8_num_used(&fifo->fifo), sizeof(uint32_t)); +} + +/** + * fifo32_push: + * @fifo: FIFO to push to + * @data: 32 bits data word to push + * + * Push a 32 bits data word to the FIFO. Behaviour is undefined if the FIFO + * is full. Clients are responsible for checking for fullness using + * fifo32_is_full(). + */ + +static inline void fifo32_push(Fifo32 *fifo, uint32_t data) +{ + int i; + + for (i = 0; i < sizeof(data); i++) { + fifo8_push(&fifo->fifo, data & 0xff); + data >>= 8; + } +} + +/** + * fifo32_push_all: + * @fifo: FIFO to push to + * @data: data to push + * @size: number of 32 bit words to push + * + * Push a 32 bit word array to the FIFO. Behaviour is undefined if the FIFO + * is full. Clients are responsible for checking the space left in the FIFO + * using fifo32_num_free(). + */ + +static inline void fifo32_push_all(Fifo32 *fifo, const uint32_t *data, + uint32_t num) +{ + int i; + + for (i = 0; i < num; i++) { + fifo32_push(fifo, data[i]); + } +} + +/** + * fifo32_pop: + * @fifo: fifo to pop from + * + * Pop a 32 bits data word from the FIFO. Behaviour is undefined if the FIFO + * is empty. Clients are responsible for checking for emptiness using + * fifo32_is_empty(). + * + * Returns: The popped 32 bits data word. + */ + +static inline uint32_t fifo32_pop(Fifo32 *fifo) +{ + uint32_t ret = 0; + int i; + + for (i = 0; i < sizeof(uint32_t); i++) { + ret |= (fifo8_pop(&fifo->fifo) << (i * 8)); + } + + return ret; +} + +/** + * There is no fifo32_pop_buf() because the data is not stored in the buffer + * as a set of native-order words. + */ + +/** + * fifo32_reset: + * @fifo: FIFO to reset + * + * Reset a FIFO. All data is discarded and the FIFO is emptied. + */ + +static inline void fifo32_reset(Fifo32 *fifo) +{ + fifo8_reset(&fifo->fifo); +} + +/** + * fifo32_is_empty: + * @fifo: FIFO to check + * + * Check if a FIFO is empty. + * + * Returns: True if the fifo is empty, false otherwise. + */ + +static inline bool fifo32_is_empty(Fifo32 *fifo) +{ + return fifo8_is_empty(&fifo->fifo); +} + +/** + * fifo32_is_full: + * @fifo: FIFO to check + * + * Check if a FIFO is full. + * + * Returns: True if the fifo is full, false otherwise. + */ + +static inline bool fifo32_is_full(Fifo32 *fifo) +{ + return fifo8_num_free(&fifo->fifo) < sizeof(uint32_t); +} + +#define VMSTATE_FIFO32(_field, _state) VMSTATE_FIFO8(_field.fifo, _state) + +#endif /* FIFO32_H */ From c906a3a01582219b40a6b075ed28d4dd6f53d462 Mon Sep 17 00:00:00 2001 From: Jean-Christophe DUBOIS Date: Thu, 12 May 2016 13:22:29 +0100 Subject: [PATCH 29/43] i.MX: Add the Freescale SPI Controller Signed-off-by: Jean-Christophe Dubois Reviewed-by: Peter Maydell Signed-off-by: Peter Maydell --- hw/ssi/Makefile.objs | 1 + hw/ssi/imx_spi.c | 454 +++++++++++++++++++++++++++++++++++++++ include/hw/ssi/imx_spi.h | 103 +++++++++ 3 files changed, 558 insertions(+) create mode 100644 hw/ssi/imx_spi.c create mode 100644 include/hw/ssi/imx_spi.h diff --git a/hw/ssi/Makefile.objs b/hw/ssi/Makefile.objs index 9555825aca..fcbb79ef01 100644 --- a/hw/ssi/Makefile.objs +++ b/hw/ssi/Makefile.objs @@ -4,3 +4,4 @@ common-obj-$(CONFIG_XILINX_SPI) += xilinx_spi.o common-obj-$(CONFIG_XILINX_SPIPS) += xilinx_spips.o obj-$(CONFIG_OMAP) += omap_spi.o +obj-$(CONFIG_IMX) += imx_spi.o diff --git a/hw/ssi/imx_spi.c b/hw/ssi/imx_spi.c new file mode 100644 index 0000000000..d5dd42aca6 --- /dev/null +++ b/hw/ssi/imx_spi.c @@ -0,0 +1,454 @@ +/* + * IMX SPI Controller + * + * Copyright (c) 2016 Jean-Christophe Dubois + * + * This work is licensed under the terms of the GNU GPL, version 2 or later. + * See the COPYING file in the top-level directory. + * + */ + +#include "qemu/osdep.h" +#include "hw/ssi/imx_spi.h" +#include "sysemu/sysemu.h" + +#ifndef DEBUG_IMX_SPI +#define DEBUG_IMX_SPI 0 +#endif + +#define DPRINTF(fmt, args...) \ + do { \ + if (DEBUG_IMX_SPI) { \ + fprintf(stderr, "[%s]%s: " fmt , TYPE_IMX_SPI, \ + __func__, ##args); \ + } \ + } while (0) + +static char const *imx_spi_reg_name(uint32_t reg) +{ + static char unknown[20]; + + switch (reg) { + case ECSPI_RXDATA: + return "ECSPI_RXDATA"; + case ECSPI_TXDATA: + return "ECSPI_TXDATA"; + case ECSPI_CONREG: + return "ECSPI_CONREG"; + case ECSPI_CONFIGREG: + return "ECSPI_CONFIGREG"; + case ECSPI_INTREG: + return "ECSPI_INTREG"; + case ECSPI_DMAREG: + return "ECSPI_DMAREG"; + case ECSPI_STATREG: + return "ECSPI_STATREG"; + case ECSPI_PERIODREG: + return "ECSPI_PERIODREG"; + case ECSPI_TESTREG: + return "ECSPI_TESTREG"; + case ECSPI_MSGDATA: + return "ECSPI_MSGDATA"; + default: + sprintf(unknown, "%d ?", reg); + return unknown; + } +} + +static const VMStateDescription vmstate_imx_spi = { + .name = TYPE_IMX_SPI, + .version_id = 1, + .minimum_version_id = 1, + .fields = (VMStateField[]) { + VMSTATE_FIFO32(tx_fifo, IMXSPIState), + VMSTATE_FIFO32(rx_fifo, IMXSPIState), + VMSTATE_INT16(burst_length, IMXSPIState), + VMSTATE_UINT32_ARRAY(regs, IMXSPIState, ECSPI_MAX), + VMSTATE_END_OF_LIST() + }, +}; + +static void imx_spi_txfifo_reset(IMXSPIState *s) +{ + fifo32_reset(&s->tx_fifo); + s->regs[ECSPI_STATREG] |= ECSPI_STATREG_TE; + s->regs[ECSPI_STATREG] &= ~ECSPI_STATREG_TF; +} + +static void imx_spi_rxfifo_reset(IMXSPIState *s) +{ + fifo32_reset(&s->rx_fifo); + s->regs[ECSPI_STATREG] &= ~ECSPI_STATREG_RR; + s->regs[ECSPI_STATREG] &= ~ECSPI_STATREG_RF; + s->regs[ECSPI_STATREG] &= ~ECSPI_STATREG_RO; +} + +static void imx_spi_update_irq(IMXSPIState *s) +{ + int level; + + if (fifo32_is_empty(&s->rx_fifo)) { + s->regs[ECSPI_STATREG] &= ~ECSPI_STATREG_RR; + } else { + s->regs[ECSPI_STATREG] |= ECSPI_STATREG_RR; + } + + if (fifo32_is_full(&s->rx_fifo)) { + s->regs[ECSPI_STATREG] |= ECSPI_STATREG_RF; + } else { + s->regs[ECSPI_STATREG] &= ~ECSPI_STATREG_RF; + } + + if (fifo32_is_empty(&s->tx_fifo)) { + s->regs[ECSPI_STATREG] |= ECSPI_STATREG_TE; + } else { + s->regs[ECSPI_STATREG] &= ~ECSPI_STATREG_TE; + } + + if (fifo32_is_full(&s->tx_fifo)) { + s->regs[ECSPI_STATREG] |= ECSPI_STATREG_TF; + } else { + s->regs[ECSPI_STATREG] &= ~ECSPI_STATREG_TF; + } + + level = s->regs[ECSPI_STATREG] & s->regs[ECSPI_INTREG] ? 1 : 0; + + qemu_set_irq(s->irq, level); + + DPRINTF("IRQ level is %d\n", level); +} + +static uint8_t imx_spi_selected_channel(IMXSPIState *s) +{ + return EXTRACT(s->regs[ECSPI_CONREG], ECSPI_CONREG_CHANNEL_SELECT); +} + +static uint32_t imx_spi_burst_length(IMXSPIState *s) +{ + return EXTRACT(s->regs[ECSPI_CONREG], ECSPI_CONREG_BURST_LENGTH) + 1; +} + +static bool imx_spi_is_enabled(IMXSPIState *s) +{ + return s->regs[ECSPI_CONREG] & ECSPI_CONREG_EN; +} + +static bool imx_spi_channel_is_master(IMXSPIState *s) +{ + uint8_t mode = EXTRACT(s->regs[ECSPI_CONREG], ECSPI_CONREG_CHANNEL_MODE); + + return (mode & (1 << imx_spi_selected_channel(s))) ? true : false; +} + +static bool imx_spi_is_multiple_master_burst(IMXSPIState *s) +{ + uint8_t wave = EXTRACT(s->regs[ECSPI_CONFIGREG], ECSPI_CONFIGREG_SS_CTL); + + return imx_spi_channel_is_master(s) && + !(s->regs[ECSPI_CONREG] & ECSPI_CONREG_SMC) && + ((wave & (1 << imx_spi_selected_channel(s))) ? true : false); +} + +static void imx_spi_flush_txfifo(IMXSPIState *s) +{ + uint32_t tx; + uint32_t rx; + + DPRINTF("Begin: TX Fifo Size = %d, RX Fifo Size = %d\n", + fifo32_num_used(&s->tx_fifo), fifo32_num_used(&s->rx_fifo)); + + while (!fifo32_is_empty(&s->tx_fifo)) { + int tx_burst = 0; + int index = 0; + + if (s->burst_length <= 0) { + s->burst_length = imx_spi_burst_length(s); + + DPRINTF("Burst length = %d\n", s->burst_length); + + if (imx_spi_is_multiple_master_burst(s)) { + s->regs[ECSPI_CONREG] |= ECSPI_CONREG_XCH; + } + } + + tx = fifo32_pop(&s->tx_fifo); + + DPRINTF("data tx:0x%08x\n", tx); + + tx_burst = MIN(s->burst_length, 32); + + rx = 0; + + while (tx_burst) { + uint8_t byte = tx & 0xff; + + DPRINTF("writing 0x%02x\n", (uint32_t)byte); + + /* We need to write one byte at a time */ + byte = ssi_transfer(s->bus, byte); + + DPRINTF("0x%02x read\n", (uint32_t)byte); + + tx = tx >> 8; + rx |= (byte << (index * 8)); + + /* Remove 8 bits from the actual burst */ + tx_burst -= 8; + s->burst_length -= 8; + index++; + } + + DPRINTF("data rx:0x%08x\n", rx); + + if (fifo32_is_full(&s->rx_fifo)) { + s->regs[ECSPI_STATREG] |= ECSPI_STATREG_RO; + } else { + fifo32_push(&s->rx_fifo, (uint8_t)rx); + } + + if (s->burst_length <= 0) { + s->regs[ECSPI_CONREG] &= ~ECSPI_CONREG_XCH; + + if (!imx_spi_is_multiple_master_burst(s)) { + s->regs[ECSPI_STATREG] |= ECSPI_STATREG_TC; + break; + } + } + } + + if (fifo32_is_empty(&s->tx_fifo)) { + s->regs[ECSPI_STATREG] |= ECSPI_STATREG_TC; + } + + /* TODO: We should also use TDR and RDR bits */ + + DPRINTF("End: TX Fifo Size = %d, RX Fifo Size = %d\n", + fifo32_num_used(&s->tx_fifo), fifo32_num_used(&s->rx_fifo)); +} + +static void imx_spi_reset(DeviceState *dev) +{ + IMXSPIState *s = IMX_SPI(dev); + + DPRINTF("\n"); + + memset(s->regs, 0, sizeof(s->regs)); + + s->regs[ECSPI_STATREG] = 0x00000003; + + imx_spi_rxfifo_reset(s); + imx_spi_txfifo_reset(s); + + imx_spi_update_irq(s); + + s->burst_length = 0; +} + +static uint64_t imx_spi_read(void *opaque, hwaddr offset, unsigned size) +{ + uint32_t value = 0; + IMXSPIState *s = opaque; + uint32_t index = offset >> 2; + + if (index >= ECSPI_MAX) { + qemu_log_mask(LOG_GUEST_ERROR, "[%s]%s: Bad register at offset 0x%" + HWADDR_PRIx "\n", TYPE_IMX_SPI, __func__, offset); + return 0; + } + + switch (index) { + case ECSPI_RXDATA: + if (!imx_spi_is_enabled(s)) { + value = 0; + } else if (fifo32_is_empty(&s->rx_fifo)) { + /* value is undefined */ + value = 0xdeadbeef; + } else { + /* read from the RX FIFO */ + value = fifo32_pop(&s->rx_fifo); + } + + break; + case ECSPI_TXDATA: + qemu_log_mask(LOG_GUEST_ERROR, "[%s]%s: Trying to read from TX FIFO\n", + TYPE_IMX_SPI, __func__); + + /* Reading from TXDATA gives 0 */ + + break; + case ECSPI_MSGDATA: + qemu_log_mask(LOG_GUEST_ERROR, "[%s]%s: Trying to read from MSG FIFO\n", + TYPE_IMX_SPI, __func__); + + /* Reading from MSGDATA gives 0 */ + + break; + default: + value = s->regs[index]; + break; + } + + DPRINTF("reg[%s] => 0x%" PRIx32 "\n", imx_spi_reg_name(index), value); + + imx_spi_update_irq(s); + + return (uint64_t)value; +} + +static void imx_spi_write(void *opaque, hwaddr offset, uint64_t value, + unsigned size) +{ + IMXSPIState *s = opaque; + uint32_t index = offset >> 2; + uint32_t change_mask; + + if (index >= ECSPI_MAX) { + qemu_log_mask(LOG_GUEST_ERROR, "[%s]%s: Bad register at offset 0x%" + HWADDR_PRIx "\n", TYPE_IMX_SPI, __func__, offset); + return; + } + + DPRINTF("reg[%s] <= 0x%" PRIx32 "\n", imx_spi_reg_name(index), + (uint32_t)value); + + change_mask = s->regs[index] ^ value; + + switch (index) { + case ECSPI_RXDATA: + qemu_log_mask(LOG_GUEST_ERROR, "[%s]%s: Trying to write to RX FIFO\n", + TYPE_IMX_SPI, __func__); + break; + case ECSPI_TXDATA: + case ECSPI_MSGDATA: + /* Is there any difference between TXDATA and MSGDATA ? */ + /* I'll have to look in the linux driver */ + if (!imx_spi_is_enabled(s)) { + /* Ignore writes if device is disabled */ + break; + } else if (fifo32_is_full(&s->tx_fifo)) { + /* Ignore writes if queue is full */ + break; + } + + fifo32_push(&s->tx_fifo, (uint32_t)value); + + if (imx_spi_channel_is_master(s) && + (s->regs[ECSPI_CONREG] & ECSPI_CONREG_SMC)) { + /* + * Start emitting if current channel is master and SMC bit is + * set. + */ + imx_spi_flush_txfifo(s); + } + + break; + case ECSPI_STATREG: + /* the RO and TC bits are write-one-to-clear */ + value &= ECSPI_STATREG_RO | ECSPI_STATREG_TC; + s->regs[ECSPI_STATREG] &= ~value; + + break; + case ECSPI_CONREG: + s->regs[ECSPI_CONREG] = value; + + if (!imx_spi_is_enabled(s)) { + /* device is disabled, so this is a reset */ + imx_spi_reset(DEVICE(s)); + return; + } + + if (imx_spi_channel_is_master(s)) { + int i; + + /* We are in master mode */ + + for (i = 0; i < 4; i++) { + qemu_set_irq(s->cs_lines[i], + i == imx_spi_selected_channel(s) ? 0 : 1); + } + + if ((value & change_mask & ECSPI_CONREG_SMC) && + !fifo32_is_empty(&s->tx_fifo)) { + /* SMC bit is set and TX FIFO has some slots filled in */ + imx_spi_flush_txfifo(s); + } else if ((value & change_mask & ECSPI_CONREG_XCH) && + !(value & ECSPI_CONREG_SMC)) { + /* This is a request to start emitting */ + imx_spi_flush_txfifo(s); + } + } + + break; + default: + s->regs[index] = value; + + break; + } + + imx_spi_update_irq(s); +} + +static const struct MemoryRegionOps imx_spi_ops = { + .read = imx_spi_read, + .write = imx_spi_write, + .endianness = DEVICE_NATIVE_ENDIAN, + .valid = { + /* + * Our device would not work correctly if the guest was doing + * unaligned access. This might not be a limitation on the real + * device but in practice there is no reason for a guest to access + * this device unaligned. + */ + .min_access_size = 4, + .max_access_size = 4, + .unaligned = false, + }, +}; + +static void imx_spi_realize(DeviceState *dev, Error **errp) +{ + IMXSPIState *s = IMX_SPI(dev); + int i; + + s->bus = ssi_create_bus(dev, "spi"); + + memory_region_init_io(&s->iomem, OBJECT(dev), &imx_spi_ops, s, + TYPE_IMX_SPI, 0x1000); + sysbus_init_mmio(SYS_BUS_DEVICE(dev), &s->iomem); + sysbus_init_irq(SYS_BUS_DEVICE(dev), &s->irq); + + ssi_auto_connect_slaves(dev, s->cs_lines, s->bus); + + for (i = 0; i < 4; ++i) { + sysbus_init_irq(SYS_BUS_DEVICE(dev), &s->cs_lines[i]); + } + + s->burst_length = 0; + + fifo32_create(&s->tx_fifo, ECSPI_FIFO_SIZE); + fifo32_create(&s->rx_fifo, ECSPI_FIFO_SIZE); +} + +static void imx_spi_class_init(ObjectClass *klass, void *data) +{ + DeviceClass *dc = DEVICE_CLASS(klass); + + dc->realize = imx_spi_realize; + dc->vmsd = &vmstate_imx_spi; + dc->reset = imx_spi_reset; + dc->desc = "i.MX SPI Controller"; +} + +static const TypeInfo imx_spi_info = { + .name = TYPE_IMX_SPI, + .parent = TYPE_SYS_BUS_DEVICE, + .instance_size = sizeof(IMXSPIState), + .class_init = imx_spi_class_init, +}; + +static void imx_spi_register_types(void) +{ + type_register_static(&imx_spi_info); +} + +type_init(imx_spi_register_types) diff --git a/include/hw/ssi/imx_spi.h b/include/hw/ssi/imx_spi.h new file mode 100644 index 0000000000..7103953581 --- /dev/null +++ b/include/hw/ssi/imx_spi.h @@ -0,0 +1,103 @@ +/* + * IMX SPI Controller + * + * Copyright 2016 Jean-Christophe Dubois + * + * This work is licensed under the terms of the GNU GPL, version 2 or later. + * See the COPYING file in the top-level directory. + */ + +#ifndef IMX_SPI_H +#define IMX_SPI_H + +#include "hw/sysbus.h" +#include "hw/ssi/ssi.h" +#include "qemu/bitops.h" +#include "qemu/fifo32.h" + +#define ECSPI_FIFO_SIZE 64 + +#define ECSPI_RXDATA 0 +#define ECSPI_TXDATA 1 +#define ECSPI_CONREG 2 +#define ECSPI_CONFIGREG 3 +#define ECSPI_INTREG 4 +#define ECSPI_DMAREG 5 +#define ECSPI_STATREG 6 +#define ECSPI_PERIODREG 7 +#define ECSPI_TESTREG 8 +#define ECSPI_MSGDATA 16 +#define ECSPI_MAX 17 + +/* ECSPI_CONREG */ +#define ECSPI_CONREG_EN (1 << 0) +#define ECSPI_CONREG_HT (1 << 1) +#define ECSPI_CONREG_XCH (1 << 2) +#define ECSPI_CONREG_SMC (1 << 3) +#define ECSPI_CONREG_CHANNEL_MODE_SHIFT 4 +#define ECSPI_CONREG_CHANNEL_MODE_LENGTH 4 +#define ECSPI_CONREG_DRCTL_SHIFT 16 +#define ECSPI_CONREG_DRCTL_LENGTH 2 +#define ECSPI_CONREG_CHANNEL_SELECT_SHIFT 18 +#define ECSPI_CONREG_CHANNEL_SELECT_LENGTH 2 +#define ECSPI_CONREG_BURST_LENGTH_SHIFT 20 +#define ECSPI_CONREG_BURST_LENGTH_LENGTH 12 + +/* ECSPI_CONFIGREG */ +#define ECSPI_CONFIGREG_SS_CTL_SHIFT 8 +#define ECSPI_CONFIGREG_SS_CTL_LENGTH 4 + +/* ECSPI_INTREG */ +#define ECSPI_INTREG_TEEN (1 << 0) +#define ECSPI_INTREG_TDREN (1 << 1) +#define ECSPI_INTREG_TFEN (1 << 2) +#define ECSPI_INTREG_RREN (1 << 3) +#define ECSPI_INTREG_RDREN (1 << 4) +#define ECSPI_INTREG_RFEN (1 << 5) +#define ECSPI_INTREG_ROEN (1 << 6) +#define ECSPI_INTREG_TCEN (1 << 7) + +/* ECSPI_DMAREG */ +#define ECSPI_DMAREG_RXTDEN (1 << 31) +#define ECSPI_DMAREG_RXDEN (1 << 23) +#define ECSPI_DMAREG_TEDEN (1 << 7) +#define ECSPI_DMAREG_RX_THRESHOLD_SHIFT 16 +#define ECSPI_DMAREG_RX_THRESHOLD_LENGTH 6 + +/* ECSPI_STATREG */ +#define ECSPI_STATREG_TE (1 << 0) +#define ECSPI_STATREG_TDR (1 << 1) +#define ECSPI_STATREG_TF (1 << 2) +#define ECSPI_STATREG_RR (1 << 3) +#define ECSPI_STATREG_RDR (1 << 4) +#define ECSPI_STATREG_RF (1 << 5) +#define ECSPI_STATREG_RO (1 << 6) +#define ECSPI_STATREG_TC (1 << 7) + +#define EXTRACT(value, name) extract32(value, name##_SHIFT, name##_LENGTH) + +#define TYPE_IMX_SPI "imx.spi" +#define IMX_SPI(obj) OBJECT_CHECK(IMXSPIState, (obj), TYPE_IMX_SPI) + +typedef struct IMXSPIState { + /* */ + SysBusDevice parent_obj; + + /* */ + MemoryRegion iomem; + + qemu_irq irq; + + qemu_irq cs_lines[4]; + + SSIBus *bus; + + uint32_t regs[ECSPI_MAX]; + + Fifo32 rx_fifo; + Fifo32 tx_fifo; + + int16_t burst_length; +} IMXSPIState; + +#endif /* IMX_SPI_H */ From ec46eaa83a3c8c5677adc2ce0f956a7ab9948844 Mon Sep 17 00:00:00 2001 From: Jean-Christophe DUBOIS Date: Thu, 12 May 2016 13:22:29 +0100 Subject: [PATCH 30/43] i.MX: Add i.MX6 SOC implementation. For now we only support the following devices: * up to 4 Cortex A9 cores * A9 MPCORE (SCU, GIC, TWD) * 5 i.MX UARTs * 2 EPIT timers * 1 GPT timer * 3 I2C controllers * 7 GPIO controllers * 6 SDHC controllers * 5 SPI controllers * 1 CCM device * 1 SRC device * various ROM/RAM areas. Reviewed-by: Peter Maydell Signed-off-by: Jean-Christophe Dubois Signed-off-by: Peter Maydell --- default-configs/arm-softmmu.mak | 1 + hw/arm/Makefile.objs | 1 + hw/arm/fsl-imx6.c | 449 +++++++++++++++++++++++++++++++ include/hw/arm/fsl-imx6.h | 450 ++++++++++++++++++++++++++++++++ 4 files changed, 901 insertions(+) create mode 100644 hw/arm/fsl-imx6.c create mode 100644 include/hw/arm/fsl-imx6.h diff --git a/default-configs/arm-softmmu.mak b/default-configs/arm-softmmu.mak index c63cdd073d..c5bcba754a 100644 --- a/default-configs/arm-softmmu.mak +++ b/default-configs/arm-softmmu.mak @@ -100,6 +100,7 @@ CONFIG_ALLWINNER_A10_PIT=y CONFIG_ALLWINNER_A10_PIC=y CONFIG_ALLWINNER_A10=y +CONFIG_FSL_IMX6=y CONFIG_FSL_IMX31=y CONFIG_FSL_IMX25=y diff --git a/hw/arm/Makefile.objs b/hw/arm/Makefile.objs index 954c9fe15e..2b20e49f4e 100644 --- a/hw/arm/Makefile.objs +++ b/hw/arm/Makefile.objs @@ -16,4 +16,5 @@ obj-$(CONFIG_STM32F205_SOC) += stm32f205_soc.o obj-$(CONFIG_XLNX_ZYNQMP) += xlnx-zynqmp.o xlnx-ep108.o obj-$(CONFIG_FSL_IMX25) += fsl-imx25.o imx25_pdk.o obj-$(CONFIG_FSL_IMX31) += fsl-imx31.o kzm.o +obj-$(CONFIG_FSL_IMX6) += fsl-imx6.o obj-$(CONFIG_ASPEED_SOC) += ast2400.o palmetto-bmc.o diff --git a/hw/arm/fsl-imx6.c b/hw/arm/fsl-imx6.c new file mode 100644 index 0000000000..a5331bfd33 --- /dev/null +++ b/hw/arm/fsl-imx6.c @@ -0,0 +1,449 @@ +/* + * Copyright (c) 2015 Jean-Christophe Dubois + * + * i.MX6 SOC emulation. + * + * Based on hw/arm/fsl-imx31.c + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, see . + */ + +#include "qemu/osdep.h" +#include "qapi/error.h" +#include "qemu-common.h" +#include "hw/arm/fsl-imx6.h" +#include "sysemu/sysemu.h" +#include "sysemu/char.h" +#include "qemu/error-report.h" + +#define NAME_SIZE 20 + +static void fsl_imx6_init(Object *obj) +{ + FslIMX6State *s = FSL_IMX6(obj); + char name[NAME_SIZE]; + int i; + + if (smp_cpus > FSL_IMX6_NUM_CPUS) { + error_report("%s: Only %d CPUs are supported (%d requested)", + TYPE_FSL_IMX6, FSL_IMX6_NUM_CPUS, smp_cpus); + exit(1); + } + + for (i = 0; i < smp_cpus; i++) { + object_initialize(&s->cpu[i], sizeof(s->cpu[i]), + "cortex-a9-" TYPE_ARM_CPU); + snprintf(name, NAME_SIZE, "cpu%d", i); + object_property_add_child(obj, name, OBJECT(&s->cpu[i]), NULL); + } + + object_initialize(&s->a9mpcore, sizeof(s->a9mpcore), TYPE_A9MPCORE_PRIV); + qdev_set_parent_bus(DEVICE(&s->a9mpcore), sysbus_get_default()); + object_property_add_child(obj, "a9mpcore", OBJECT(&s->a9mpcore), NULL); + + object_initialize(&s->ccm, sizeof(s->ccm), TYPE_IMX6_CCM); + qdev_set_parent_bus(DEVICE(&s->ccm), sysbus_get_default()); + object_property_add_child(obj, "ccm", OBJECT(&s->ccm), NULL); + + object_initialize(&s->src, sizeof(s->src), TYPE_IMX6_SRC); + qdev_set_parent_bus(DEVICE(&s->src), sysbus_get_default()); + object_property_add_child(obj, "src", OBJECT(&s->src), NULL); + + for (i = 0; i < FSL_IMX6_NUM_UARTS; i++) { + object_initialize(&s->uart[i], sizeof(s->uart[i]), TYPE_IMX_SERIAL); + qdev_set_parent_bus(DEVICE(&s->uart[i]), sysbus_get_default()); + snprintf(name, NAME_SIZE, "uart%d", i + 1); + object_property_add_child(obj, name, OBJECT(&s->uart[i]), NULL); + } + + object_initialize(&s->gpt, sizeof(s->gpt), TYPE_IMX_GPT); + qdev_set_parent_bus(DEVICE(&s->gpt), sysbus_get_default()); + object_property_add_child(obj, "gpt", OBJECT(&s->gpt), NULL); + + for (i = 0; i < FSL_IMX6_NUM_EPITS; i++) { + object_initialize(&s->epit[i], sizeof(s->epit[i]), TYPE_IMX_EPIT); + qdev_set_parent_bus(DEVICE(&s->epit[i]), sysbus_get_default()); + snprintf(name, NAME_SIZE, "epit%d", i + 1); + object_property_add_child(obj, name, OBJECT(&s->epit[i]), NULL); + } + + for (i = 0; i < FSL_IMX6_NUM_I2CS; i++) { + object_initialize(&s->i2c[i], sizeof(s->i2c[i]), TYPE_IMX_I2C); + qdev_set_parent_bus(DEVICE(&s->i2c[i]), sysbus_get_default()); + snprintf(name, NAME_SIZE, "i2c%d", i + 1); + object_property_add_child(obj, name, OBJECT(&s->i2c[i]), NULL); + } + + for (i = 0; i < FSL_IMX6_NUM_GPIOS; i++) { + object_initialize(&s->gpio[i], sizeof(s->gpio[i]), TYPE_IMX_GPIO); + qdev_set_parent_bus(DEVICE(&s->gpio[i]), sysbus_get_default()); + snprintf(name, NAME_SIZE, "gpio%d", i + 1); + object_property_add_child(obj, name, OBJECT(&s->gpio[i]), NULL); + } + + for (i = 0; i < FSL_IMX6_NUM_ESDHCS; i++) { + object_initialize(&s->esdhc[i], sizeof(s->esdhc[i]), TYPE_SYSBUS_SDHCI); + qdev_set_parent_bus(DEVICE(&s->esdhc[i]), sysbus_get_default()); + snprintf(name, NAME_SIZE, "sdhc%d", i + 1); + object_property_add_child(obj, name, OBJECT(&s->esdhc[i]), NULL); + } + + for (i = 0; i < FSL_IMX6_NUM_ECSPIS; i++) { + object_initialize(&s->spi[i], sizeof(s->spi[i]), TYPE_IMX_SPI); + qdev_set_parent_bus(DEVICE(&s->spi[i]), sysbus_get_default()); + snprintf(name, NAME_SIZE, "spi%d", i + 1); + object_property_add_child(obj, name, OBJECT(&s->spi[i]), NULL); + } +} + +static void fsl_imx6_realize(DeviceState *dev, Error **errp) +{ + FslIMX6State *s = FSL_IMX6(dev); + uint16_t i; + Error *err = NULL; + + for (i = 0; i < smp_cpus; i++) { + + /* On uniprocessor, the CBAR is set to 0 */ + if (smp_cpus > 1) { + object_property_set_int(OBJECT(&s->cpu[i]), FSL_IMX6_A9MPCORE_ADDR, + "reset-cbar", &error_abort); + } + + /* All CPU but CPU 0 start in power off mode */ + if (i) { + object_property_set_bool(OBJECT(&s->cpu[i]), true, + "start-powered-off", &error_abort); + } + + object_property_set_bool(OBJECT(&s->cpu[i]), true, "realized", &err); + if (err) { + error_propagate(errp, err); + return; + } + } + + object_property_set_int(OBJECT(&s->a9mpcore), smp_cpus, "num-cpu", + &error_abort); + + object_property_set_int(OBJECT(&s->a9mpcore), + FSL_IMX6_MAX_IRQ + GIC_INTERNAL, "num-irq", + &error_abort); + + object_property_set_bool(OBJECT(&s->a9mpcore), true, "realized", &err); + if (err) { + error_propagate(errp, err); + return; + } + sysbus_mmio_map(SYS_BUS_DEVICE(&s->a9mpcore), 0, FSL_IMX6_A9MPCORE_ADDR); + + for (i = 0; i < smp_cpus; i++) { + sysbus_connect_irq(SYS_BUS_DEVICE(&s->a9mpcore), i, + qdev_get_gpio_in(DEVICE(&s->cpu[i]), ARM_CPU_IRQ)); + sysbus_connect_irq(SYS_BUS_DEVICE(&s->a9mpcore), i + smp_cpus, + qdev_get_gpio_in(DEVICE(&s->cpu[i]), ARM_CPU_FIQ)); + } + + object_property_set_bool(OBJECT(&s->ccm), true, "realized", &err); + if (err) { + error_propagate(errp, err); + return; + } + sysbus_mmio_map(SYS_BUS_DEVICE(&s->ccm), 0, FSL_IMX6_CCM_ADDR); + + object_property_set_bool(OBJECT(&s->src), true, "realized", &err); + if (err) { + error_propagate(errp, err); + return; + } + sysbus_mmio_map(SYS_BUS_DEVICE(&s->src), 0, FSL_IMX6_SRC_ADDR); + + /* Initialize all UARTs */ + for (i = 0; i < FSL_IMX6_NUM_UARTS; i++) { + static const struct { + hwaddr addr; + unsigned int irq; + } serial_table[FSL_IMX6_NUM_UARTS] = { + { FSL_IMX6_UART1_ADDR, FSL_IMX6_UART1_IRQ }, + { FSL_IMX6_UART2_ADDR, FSL_IMX6_UART2_IRQ }, + { FSL_IMX6_UART3_ADDR, FSL_IMX6_UART3_IRQ }, + { FSL_IMX6_UART4_ADDR, FSL_IMX6_UART4_IRQ }, + { FSL_IMX6_UART5_ADDR, FSL_IMX6_UART5_IRQ }, + }; + + if (i < MAX_SERIAL_PORTS) { + CharDriverState *chr; + + chr = serial_hds[i]; + + if (!chr) { + char *label = g_strdup_printf("imx6.uart%d", i + 1); + chr = qemu_chr_new(label, "null", NULL); + g_free(label); + serial_hds[i] = chr; + } + + qdev_prop_set_chr(DEVICE(&s->uart[i]), "chardev", chr); + } + + object_property_set_bool(OBJECT(&s->uart[i]), true, "realized", &err); + if (err) { + error_propagate(errp, err); + return; + } + + sysbus_mmio_map(SYS_BUS_DEVICE(&s->uart[i]), 0, serial_table[i].addr); + sysbus_connect_irq(SYS_BUS_DEVICE(&s->uart[i]), 0, + qdev_get_gpio_in(DEVICE(&s->a9mpcore), + serial_table[i].irq)); + } + + s->gpt.ccm = IMX_CCM(&s->ccm); + + object_property_set_bool(OBJECT(&s->gpt), true, "realized", &err); + if (err) { + error_propagate(errp, err); + return; + } + + sysbus_mmio_map(SYS_BUS_DEVICE(&s->gpt), 0, FSL_IMX6_GPT_ADDR); + sysbus_connect_irq(SYS_BUS_DEVICE(&s->gpt), 0, + qdev_get_gpio_in(DEVICE(&s->a9mpcore), + FSL_IMX6_GPT_IRQ)); + + /* Initialize all EPIT timers */ + for (i = 0; i < FSL_IMX6_NUM_EPITS; i++) { + static const struct { + hwaddr addr; + unsigned int irq; + } epit_table[FSL_IMX6_NUM_EPITS] = { + { FSL_IMX6_EPIT1_ADDR, FSL_IMX6_EPIT1_IRQ }, + { FSL_IMX6_EPIT2_ADDR, FSL_IMX6_EPIT2_IRQ }, + }; + + s->epit[i].ccm = IMX_CCM(&s->ccm); + + object_property_set_bool(OBJECT(&s->epit[i]), true, "realized", &err); + if (err) { + error_propagate(errp, err); + return; + } + + sysbus_mmio_map(SYS_BUS_DEVICE(&s->epit[i]), 0, epit_table[i].addr); + sysbus_connect_irq(SYS_BUS_DEVICE(&s->epit[i]), 0, + qdev_get_gpio_in(DEVICE(&s->a9mpcore), + epit_table[i].irq)); + } + + /* Initialize all I2C */ + for (i = 0; i < FSL_IMX6_NUM_I2CS; i++) { + static const struct { + hwaddr addr; + unsigned int irq; + } i2c_table[FSL_IMX6_NUM_I2CS] = { + { FSL_IMX6_I2C1_ADDR, FSL_IMX6_I2C1_IRQ }, + { FSL_IMX6_I2C2_ADDR, FSL_IMX6_I2C2_IRQ }, + { FSL_IMX6_I2C3_ADDR, FSL_IMX6_I2C3_IRQ } + }; + + object_property_set_bool(OBJECT(&s->i2c[i]), true, "realized", &err); + if (err) { + error_propagate(errp, err); + return; + } + + sysbus_mmio_map(SYS_BUS_DEVICE(&s->i2c[i]), 0, i2c_table[i].addr); + sysbus_connect_irq(SYS_BUS_DEVICE(&s->i2c[i]), 0, + qdev_get_gpio_in(DEVICE(&s->a9mpcore), + i2c_table[i].irq)); + } + + /* Initialize all GPIOs */ + for (i = 0; i < FSL_IMX6_NUM_GPIOS; i++) { + static const struct { + hwaddr addr; + unsigned int irq_low; + unsigned int irq_high; + } gpio_table[FSL_IMX6_NUM_GPIOS] = { + { + FSL_IMX6_GPIO1_ADDR, + FSL_IMX6_GPIO1_LOW_IRQ, + FSL_IMX6_GPIO1_HIGH_IRQ + }, + { + FSL_IMX6_GPIO2_ADDR, + FSL_IMX6_GPIO2_LOW_IRQ, + FSL_IMX6_GPIO2_HIGH_IRQ + }, + { + FSL_IMX6_GPIO3_ADDR, + FSL_IMX6_GPIO3_LOW_IRQ, + FSL_IMX6_GPIO3_HIGH_IRQ + }, + { + FSL_IMX6_GPIO4_ADDR, + FSL_IMX6_GPIO4_LOW_IRQ, + FSL_IMX6_GPIO4_HIGH_IRQ + }, + { + FSL_IMX6_GPIO5_ADDR, + FSL_IMX6_GPIO5_LOW_IRQ, + FSL_IMX6_GPIO5_HIGH_IRQ + }, + { + FSL_IMX6_GPIO6_ADDR, + FSL_IMX6_GPIO6_LOW_IRQ, + FSL_IMX6_GPIO6_HIGH_IRQ + }, + { + FSL_IMX6_GPIO7_ADDR, + FSL_IMX6_GPIO7_LOW_IRQ, + FSL_IMX6_GPIO7_HIGH_IRQ + }, + }; + + object_property_set_bool(OBJECT(&s->gpio[i]), true, "has-edge-sel", + &error_abort); + object_property_set_bool(OBJECT(&s->gpio[i]), true, "has-upper-pin-irq", + &error_abort); + object_property_set_bool(OBJECT(&s->gpio[i]), true, "realized", &err); + if (err) { + error_propagate(errp, err); + return; + } + + sysbus_mmio_map(SYS_BUS_DEVICE(&s->gpio[i]), 0, gpio_table[i].addr); + sysbus_connect_irq(SYS_BUS_DEVICE(&s->gpio[i]), 0, + qdev_get_gpio_in(DEVICE(&s->a9mpcore), + gpio_table[i].irq_low)); + sysbus_connect_irq(SYS_BUS_DEVICE(&s->gpio[i]), 1, + qdev_get_gpio_in(DEVICE(&s->a9mpcore), + gpio_table[i].irq_high)); + } + + /* Initialize all SDHC */ + for (i = 0; i < FSL_IMX6_NUM_ESDHCS; i++) { + static const struct { + hwaddr addr; + unsigned int irq; + } esdhc_table[FSL_IMX6_NUM_ESDHCS] = { + { FSL_IMX6_uSDHC1_ADDR, FSL_IMX6_uSDHC1_IRQ }, + { FSL_IMX6_uSDHC2_ADDR, FSL_IMX6_uSDHC2_IRQ }, + { FSL_IMX6_uSDHC3_ADDR, FSL_IMX6_uSDHC3_IRQ }, + { FSL_IMX6_uSDHC4_ADDR, FSL_IMX6_uSDHC4_IRQ }, + }; + + object_property_set_bool(OBJECT(&s->esdhc[i]), true, "realized", &err); + if (err) { + error_propagate(errp, err); + return; + } + sysbus_mmio_map(SYS_BUS_DEVICE(&s->esdhc[i]), 0, esdhc_table[i].addr); + sysbus_connect_irq(SYS_BUS_DEVICE(&s->esdhc[i]), 0, + qdev_get_gpio_in(DEVICE(&s->a9mpcore), + esdhc_table[i].irq)); + } + + /* Initialize all ECSPI */ + for (i = 0; i < FSL_IMX6_NUM_ECSPIS; i++) { + static const struct { + hwaddr addr; + unsigned int irq; + } spi_table[FSL_IMX6_NUM_ECSPIS] = { + { FSL_IMX6_eCSPI1_ADDR, FSL_IMX6_ECSPI1_IRQ }, + { FSL_IMX6_eCSPI2_ADDR, FSL_IMX6_ECSPI2_IRQ }, + { FSL_IMX6_eCSPI3_ADDR, FSL_IMX6_ECSPI3_IRQ }, + { FSL_IMX6_eCSPI4_ADDR, FSL_IMX6_ECSPI4_IRQ }, + { FSL_IMX6_eCSPI5_ADDR, FSL_IMX6_ECSPI5_IRQ }, + }; + + /* Initialize the SPI */ + object_property_set_bool(OBJECT(&s->spi[i]), true, "realized", &err); + if (err) { + error_propagate(errp, err); + return; + } + + sysbus_mmio_map(SYS_BUS_DEVICE(&s->spi[i]), 0, spi_table[i].addr); + sysbus_connect_irq(SYS_BUS_DEVICE(&s->spi[i]), 0, + qdev_get_gpio_in(DEVICE(&s->a9mpcore), + spi_table[i].irq)); + } + + /* ROM memory */ + memory_region_init_rom_device(&s->rom, NULL, NULL, NULL, "imx6.rom", + FSL_IMX6_ROM_SIZE, &err); + if (err) { + error_propagate(errp, err); + return; + } + memory_region_add_subregion(get_system_memory(), FSL_IMX6_ROM_ADDR, + &s->rom); + + /* CAAM memory */ + memory_region_init_rom_device(&s->caam, NULL, NULL, NULL, "imx6.caam", + FSL_IMX6_CAAM_MEM_SIZE, &err); + if (err) { + error_propagate(errp, err); + return; + } + memory_region_add_subregion(get_system_memory(), FSL_IMX6_CAAM_MEM_ADDR, + &s->caam); + + /* OCRAM memory */ + memory_region_init_ram(&s->ocram, NULL, "imx6.ocram", FSL_IMX6_OCRAM_SIZE, + &err); + if (err) { + error_propagate(errp, err); + return; + } + memory_region_add_subregion(get_system_memory(), FSL_IMX6_OCRAM_ADDR, + &s->ocram); + vmstate_register_ram_global(&s->ocram); + + /* internal OCRAM (256 KB) is aliased over 1 MB */ + memory_region_init_alias(&s->ocram_alias, NULL, "imx6.ocram_alias", + &s->ocram, 0, FSL_IMX6_OCRAM_ALIAS_SIZE); + memory_region_add_subregion(get_system_memory(), FSL_IMX6_OCRAM_ALIAS_ADDR, + &s->ocram_alias); +} + +static void fsl_imx6_class_init(ObjectClass *oc, void *data) +{ + DeviceClass *dc = DEVICE_CLASS(oc); + + dc->realize = fsl_imx6_realize; + + /* + * Reason: creates an ARM CPU, thus use after free(), see + * arm_cpu_class_init() + */ + dc->cannot_destroy_with_object_finalize_yet = true; + dc->desc = "i.MX6 SOC"; +} + +static const TypeInfo fsl_imx6_type_info = { + .name = TYPE_FSL_IMX6, + .parent = TYPE_DEVICE, + .instance_size = sizeof(FslIMX6State), + .instance_init = fsl_imx6_init, + .class_init = fsl_imx6_class_init, +}; + +static void fsl_imx6_register_types(void) +{ + type_register_static(&fsl_imx6_type_info); +} + +type_init(fsl_imx6_register_types) diff --git a/include/hw/arm/fsl-imx6.h b/include/hw/arm/fsl-imx6.h new file mode 100644 index 0000000000..d24aaee1c1 --- /dev/null +++ b/include/hw/arm/fsl-imx6.h @@ -0,0 +1,450 @@ +/* + * Freescale i.MX31 SoC emulation + * + * Copyright (C) 2015 Jean-Christophe Dubois + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + */ + +#ifndef FSL_IMX6_H +#define FSL_IMX6_H + +#include "hw/arm/arm.h" +#include "hw/cpu/a9mpcore.h" +#include "hw/misc/imx6_ccm.h" +#include "hw/misc/imx6_src.h" +#include "hw/char/imx_serial.h" +#include "hw/timer/imx_gpt.h" +#include "hw/timer/imx_epit.h" +#include "hw/i2c/imx_i2c.h" +#include "hw/gpio/imx_gpio.h" +#include "hw/sd/sdhci.h" +#include "hw/ssi/imx_spi.h" +#include "exec/memory.h" + +#define TYPE_FSL_IMX6 "fsl,imx6" +#define FSL_IMX6(obj) OBJECT_CHECK(FslIMX6State, (obj), TYPE_FSL_IMX6) + +#define FSL_IMX6_NUM_CPUS 4 +#define FSL_IMX6_NUM_UARTS 5 +#define FSL_IMX6_NUM_EPITS 2 +#define FSL_IMX6_NUM_I2CS 3 +#define FSL_IMX6_NUM_GPIOS 7 +#define FSL_IMX6_NUM_ESDHCS 4 +#define FSL_IMX6_NUM_ECSPIS 5 + +typedef struct FslIMX6State { + /*< private >*/ + DeviceState parent_obj; + + /*< public >*/ + ARMCPU cpu[FSL_IMX6_NUM_CPUS]; + A9MPPrivState a9mpcore; + IMX6CCMState ccm; + IMX6SRCState src; + IMXSerialState uart[FSL_IMX6_NUM_UARTS]; + IMXGPTState gpt; + IMXEPITState epit[FSL_IMX6_NUM_EPITS]; + IMXI2CState i2c[FSL_IMX6_NUM_I2CS]; + IMXGPIOState gpio[FSL_IMX6_NUM_GPIOS]; + SDHCIState esdhc[FSL_IMX6_NUM_ESDHCS]; + IMXSPIState spi[FSL_IMX6_NUM_ECSPIS]; + MemoryRegion rom; + MemoryRegion caam; + MemoryRegion ocram; + MemoryRegion ocram_alias; +} FslIMX6State; + + +#define FSL_IMX6_MMDC_ADDR 0x10000000 +#define FSL_IMX6_MMDC_SIZE 0xF0000000 +#define FSL_IMX6_EIM_MEM_ADDR 0x08000000 +#define FSL_IMX6_EIM_MEM_SIZE 0x8000000 +#define FSL_IMX6_IPU_2_ADDR 0x02800000 +#define FSL_IMX6_IPU_2_SIZE 0x400000 +#define FSL_IMX6_IPU_1_ADDR 0x02400000 +#define FSL_IMX6_IPU_1_SIZE 0x400000 +#define FSL_IMX6_MIPI_HSI_ADDR 0x02208000 +#define FSL_IMX6_MIPI_HSI_SIZE 0x4000 +#define FSL_IMX6_OPENVG_ADDR 0x02204000 +#define FSL_IMX6_OPENVG_SIZE 0x4000 +#define FSL_IMX6_SATA_ADDR 0x02200000 +#define FSL_IMX6_SATA_SIZE 0x4000 +#define FSL_IMX6_AIPS_2_ADDR 0x02100000 +#define FSL_IMX6_AIPS_2_SIZE 0x100000 +/* AIPS2 */ +#define FSL_IMX6_UART5_ADDR 0x021F4000 +#define FSL_IMX6_UART5_SIZE 0x4000 +#define FSL_IMX6_UART4_ADDR 0x021F0000 +#define FSL_IMX6_UART4_SIZE 0x4000 +#define FSL_IMX6_UART3_ADDR 0x021EC000 +#define FSL_IMX6_UART3_SIZE 0x4000 +#define FSL_IMX6_UART2_ADDR 0x021E8000 +#define FSL_IMX6_UART2_SIZE 0x4000 +#define FSL_IMX6_VDOA_ADDR 0x021E4000 +#define FSL_IMX6_VDOA_SIZE 0x4000 +#define FSL_IMX6_MIPI_DSI_ADDR 0x021E0000 +#define FSL_IMX6_MIPI_DSI_SIZE 0x4000 +#define FSL_IMX6_MIPI_CSI_ADDR 0x021DC000 +#define FSL_IMX6_MIPI_CSI_SIZE 0x4000 +#define FSL_IMX6_AUDMUX_ADDR 0x021D8000 +#define FSL_IMX6_AUDMUX_SIZE 0x4000 +#define FSL_IMX6_TZASC2_ADDR 0x021D4000 +#define FSL_IMX6_TZASC2_SIZE 0x4000 +#define FSL_IMX6_TZASC1_ADDR 0x021D0000 +#define FSL_IMX6_TZASC1_SIZE 0x4000 +#define FSL_IMX6_CSU_ADDR 0x021C0000 +#define FSL_IMX6_CSU_SIZE 0x4000 +#define FSL_IMX6_OCOTPCTRL_ADDR 0x021BC000 +#define FSL_IMX6_OCOTPCTRL_SIZE 0x4000 +#define FSL_IMX6_EIM_ADDR 0x021B8000 +#define FSL_IMX6_EIM_SIZE 0x4000 +#define FSL_IMX6_MMDC1_ADDR 0x021B4000 +#define FSL_IMX6_MMDC1_SIZE 0x4000 +#define FSL_IMX6_MMDC0_ADDR 0x021B0000 +#define FSL_IMX6_MMDC0_SIZE 0x4000 +#define FSL_IMX6_ROMCP_ADDR 0x021AC000 +#define FSL_IMX6_ROMCP_SIZE 0x4000 +#define FSL_IMX6_I2C3_ADDR 0x021A8000 +#define FSL_IMX6_I2C3_SIZE 0x4000 +#define FSL_IMX6_I2C2_ADDR 0x021A4000 +#define FSL_IMX6_I2C2_SIZE 0x4000 +#define FSL_IMX6_I2C1_ADDR 0x021A0000 +#define FSL_IMX6_I2C1_SIZE 0x4000 +#define FSL_IMX6_uSDHC4_ADDR 0x0219C000 +#define FSL_IMX6_uSDHC4_SIZE 0x4000 +#define FSL_IMX6_uSDHC3_ADDR 0x02198000 +#define FSL_IMX6_uSDHC3_SIZE 0x4000 +#define FSL_IMX6_uSDHC2_ADDR 0x02194000 +#define FSL_IMX6_uSDHC2_SIZE 0x4000 +#define FSL_IMX6_uSDHC1_ADDR 0x02190000 +#define FSL_IMX6_uSDHC1_SIZE 0x4000 +#define FSL_IMX6_MLB150_ADDR 0x0218C000 +#define FSL_IMX6_MLB150_SIZE 0x4000 +#define FSL_IMX6_ENET_ADDR 0x02188000 +#define FSL_IMX6_ENET_SIZE 0x4000 +#define FSL_IMX6_USBOH3_USB_ADDR 0x02184000 +#define FSL_IMX6_USBOH3_USB_SIZE 0x4000 +#define FSL_IMX6_AIPS2_CFG_ADDR 0x0217C000 +#define FSL_IMX6_AIPS2_CFG_SIZE 0x4000 +/* DAP */ +#define FSL_IMX6_PTF_CTRL_ADDR 0x02160000 +#define FSL_IMX6_PTF_CTRL_SIZE 0x1000 +#define FSL_IMX6_PTM3_ADDR 0x0215F000 +#define FSL_IMX6_PTM3_SIZE 0x1000 +#define FSL_IMX6_PTM2_ADDR 0x0215E000 +#define FSL_IMX6_PTM2_SIZE 0x1000 +#define FSL_IMX6_PTM1_ADDR 0x0215D000 +#define FSL_IMX6_PTM1_SIZE 0x1000 +#define FSL_IMX6_PTM0_ADDR 0x0215C000 +#define FSL_IMX6_PTM0_SIZE 0x1000 +#define FSL_IMX6_CTI3_ADDR 0x0215B000 +#define FSL_IMX6_CTI3_SIZE 0x1000 +#define FSL_IMX6_CTI2_ADDR 0x0215A000 +#define FSL_IMX6_CTI2_SIZE 0x1000 +#define FSL_IMX6_CTI1_ADDR 0x02159000 +#define FSL_IMX6_CTI1_SIZE 0x1000 +#define FSL_IMX6_CTI0_ADDR 0x02158000 +#define FSL_IMX6_CTI0_SIZE 0x1000 +#define FSL_IMX6_CPU3_PMU_ADDR 0x02157000 +#define FSL_IMX6_CPU3_PMU_SIZE 0x1000 +#define FSL_IMX6_CPU3_DEBUG_IF_ADDR 0x02156000 +#define FSL_IMX6_CPU3_DEBUG_IF_SIZE 0x1000 +#define FSL_IMX6_CPU2_PMU_ADDR 0x02155000 +#define FSL_IMX6_CPU2_PMU_SIZE 0x1000 +#define FSL_IMX6_CPU2_DEBUG_IF_ADDR 0x02154000 +#define FSL_IMX6_CPU2_DEBUG_IF_SIZE 0x1000 +#define FSL_IMX6_CPU1_PMU_ADDR 0x02153000 +#define FSL_IMX6_CPU1_PMU_SIZE 0x1000 +#define FSL_IMX6_CPU1_DEBUG_IF_ADDR 0x02152000 +#define FSL_IMX6_CPU1_DEBUG_IF_SIZE 0x1000 +#define FSL_IMX6_CPU0_PMU_ADDR 0x02151000 +#define FSL_IMX6_CPU0_PMU_SIZE 0x1000 +#define FSL_IMX6_CPU0_DEBUG_IF_ADDR 0x02150000 +#define FSL_IMX6_CPU0_DEBUG_IF_SIZE 0x1000 +#define FSL_IMX6_CA9_INTEG_ADDR 0x0214F000 +#define FSL_IMX6_CA9_INTEG_SIZE 0x1000 +#define FSL_IMX6_FUNNEL_ADDR 0x02144000 +#define FSL_IMX6_FUNNEL_SIZE 0x1000 +#define FSL_IMX6_TPIU_ADDR 0x02143000 +#define FSL_IMX6_TPIU_SIZE 0x1000 +#define FSL_IMX6_EXT_CTI_ADDR 0x02142000 +#define FSL_IMX6_EXT_CTI_SIZE 0x1000 +#define FSL_IMX6_ETB_ADDR 0x02141000 +#define FSL_IMX6_ETB_SIZE 0x1000 +#define FSL_IMX6_DAP_ROM_TABLE_ADDR 0x02140000 +#define FSL_IMX6_DAP_ROM_TABLE_SIZE 0x1000 +/* DAP end */ +#define FSL_IMX6_CAAM_ADDR 0x02100000 +#define FSL_IMX6_CAAM_SIZE 0x10000 +/* AIPS2 end */ +#define FSL_IMX6_AIPS_1_ADDR 0x02000000 +#define FSL_IMX6_AIPS_1_SIZE 0x100000 +/* AIPS1 */ +#define FSL_IMX6_SDMA_ADDR 0x020EC000 +#define FSL_IMX6_SDMA_SIZE 0x4000 +#define FSL_IMX6_DCIC2_ADDR 0x020E8000 +#define FSL_IMX6_DCIC2_SIZE 0x4000 +#define FSL_IMX6_DCIC1_ADDR 0x020E4000 +#define FSL_IMX6_DCIC1_SIZE 0x4000 +#define FSL_IMX6_IOMUXC_ADDR 0x020E0000 +#define FSL_IMX6_IOMUXC_SIZE 0x4000 +#define FSL_IMX6_PGCARM_ADDR 0x020DCA00 +#define FSL_IMX6_PGCARM_SIZE 0x20 +#define FSL_IMX6_PGCPU_ADDR 0x020DC260 +#define FSL_IMX6_PGCPU_SIZE 0x20 +#define FSL_IMX6_GPC_ADDR 0x020DC000 +#define FSL_IMX6_GPC_SIZE 0x4000 +#define FSL_IMX6_SRC_ADDR 0x020D8000 +#define FSL_IMX6_SRC_SIZE 0x4000 +#define FSL_IMX6_EPIT2_ADDR 0x020D4000 +#define FSL_IMX6_EPIT2_SIZE 0x4000 +#define FSL_IMX6_EPIT1_ADDR 0x020D0000 +#define FSL_IMX6_EPIT1_SIZE 0x4000 +#define FSL_IMX6_SNVSHP_ADDR 0x020CC000 +#define FSL_IMX6_SNVSHP_SIZE 0x4000 +#define FSL_IMX6_USBPHY2_ADDR 0x020CA000 +#define FSL_IMX6_USBPHY2_SIZE 0x1000 +#define FSL_IMX6_USBPHY1_ADDR 0x020C9000 +#define FSL_IMX6_USBPHY1_SIZE 0x1000 +#define FSL_IMX6_ANALOG_ADDR 0x020C8000 +#define FSL_IMX6_ANALOG_SIZE 0x1000 +#define FSL_IMX6_CCM_ADDR 0x020C4000 +#define FSL_IMX6_CCM_SIZE 0x4000 +#define FSL_IMX6_WDOG2_ADDR 0x020C0000 +#define FSL_IMX6_WDOG2_SIZE 0x4000 +#define FSL_IMX6_WDOG1_ADDR 0x020BC000 +#define FSL_IMX6_WDOG1_SIZE 0x4000 +#define FSL_IMX6_KPP_ADDR 0x020B8000 +#define FSL_IMX6_KPP_SIZE 0x4000 +#define FSL_IMX6_GPIO7_ADDR 0x020B4000 +#define FSL_IMX6_GPIO7_SIZE 0x4000 +#define FSL_IMX6_GPIO6_ADDR 0x020B0000 +#define FSL_IMX6_GPIO6_SIZE 0x4000 +#define FSL_IMX6_GPIO5_ADDR 0x020AC000 +#define FSL_IMX6_GPIO5_SIZE 0x4000 +#define FSL_IMX6_GPIO4_ADDR 0x020A8000 +#define FSL_IMX6_GPIO4_SIZE 0x4000 +#define FSL_IMX6_GPIO3_ADDR 0x020A4000 +#define FSL_IMX6_GPIO3_SIZE 0x4000 +#define FSL_IMX6_GPIO2_ADDR 0x020A0000 +#define FSL_IMX6_GPIO2_SIZE 0x4000 +#define FSL_IMX6_GPIO1_ADDR 0x0209C000 +#define FSL_IMX6_GPIO1_SIZE 0x4000 +#define FSL_IMX6_GPT_ADDR 0x02098000 +#define FSL_IMX6_GPT_SIZE 0x4000 +#define FSL_IMX6_CAN2_ADDR 0x02094000 +#define FSL_IMX6_CAN2_SIZE 0x4000 +#define FSL_IMX6_CAN1_ADDR 0x02090000 +#define FSL_IMX6_CAN1_SIZE 0x4000 +#define FSL_IMX6_PWM4_ADDR 0x0208C000 +#define FSL_IMX6_PWM4_SIZE 0x4000 +#define FSL_IMX6_PWM3_ADDR 0x02088000 +#define FSL_IMX6_PWM3_SIZE 0x4000 +#define FSL_IMX6_PWM2_ADDR 0x02084000 +#define FSL_IMX6_PWM2_SIZE 0x4000 +#define FSL_IMX6_PWM1_ADDR 0x02080000 +#define FSL_IMX6_PWM1_SIZE 0x4000 +#define FSL_IMX6_AIPS1_CFG_ADDR 0x0207C000 +#define FSL_IMX6_AIPS1_CFG_SIZE 0x4000 +#define FSL_IMX6_VPU_ADDR 0x02040000 +#define FSL_IMX6_VPU_SIZE 0x3C000 +#define FSL_IMX6_AIPS1_SPBA_ADDR 0x0203C000 +#define FSL_IMX6_AIPS1_SPBA_SIZE 0x4000 +#define FSL_IMX6_ASRC_ADDR 0x02034000 +#define FSL_IMX6_ASRC_SIZE 0x4000 +#define FSL_IMX6_SSI3_ADDR 0x02030000 +#define FSL_IMX6_SSI3_SIZE 0x4000 +#define FSL_IMX6_SSI2_ADDR 0x0202C000 +#define FSL_IMX6_SSI2_SIZE 0x4000 +#define FSL_IMX6_SSI1_ADDR 0x02028000 +#define FSL_IMX6_SSI1_SIZE 0x4000 +#define FSL_IMX6_ESAI_ADDR 0x02024000 +#define FSL_IMX6_ESAI_SIZE 0x4000 +#define FSL_IMX6_UART1_ADDR 0x02020000 +#define FSL_IMX6_UART1_SIZE 0x4000 +#define FSL_IMX6_eCSPI5_ADDR 0x02018000 +#define FSL_IMX6_eCSPI5_SIZE 0x4000 +#define FSL_IMX6_eCSPI4_ADDR 0x02014000 +#define FSL_IMX6_eCSPI4_SIZE 0x4000 +#define FSL_IMX6_eCSPI3_ADDR 0x02010000 +#define FSL_IMX6_eCSPI3_SIZE 0x4000 +#define FSL_IMX6_eCSPI2_ADDR 0x0200C000 +#define FSL_IMX6_eCSPI2_SIZE 0x4000 +#define FSL_IMX6_eCSPI1_ADDR 0x02008000 +#define FSL_IMX6_eCSPI1_SIZE 0x4000 +#define FSL_IMX6_SPDIF_ADDR 0x02004000 +#define FSL_IMX6_SPDIF_SIZE 0x4000 +/* AIPS1 end */ +#define FSL_IMX6_PCIe_REG_ADDR 0x01FFC000 +#define FSL_IMX6_PCIe_REG_SIZE 0x4000 +#define FSL_IMX6_PCIe_ADDR 0x01000000 +#define FSL_IMX6_PCIe_SIZE 0xFFC000 +#define FSL_IMX6_GPV_1_PL301_CFG_ADDR 0x00C00000 +#define FSL_IMX6_GPV_1_PL301_CFG_SIZE 0x100000 +#define FSL_IMX6_GPV_0_PL301_CFG_ADDR 0x00B00000 +#define FSL_IMX6_GPV_0_PL301_CFG_SIZE 0x100000 +#define FSL_IMX6_PL310_ADDR 0x00A02000 +#define FSL_IMX6_PL310_SIZE 0x1000 +#define FSL_IMX6_A9MPCORE_ADDR 0x00A00000 +#define FSL_IMX6_A9MPCORE_SIZE 0x2000 +#define FSL_IMX6_OCRAM_ALIAS_ADDR 0x00940000 +#define FSL_IMX6_OCRAM_ALIAS_SIZE 0xC0000 +#define FSL_IMX6_OCRAM_ADDR 0x00900000 +#define FSL_IMX6_OCRAM_SIZE 0x40000 +#define FSL_IMX6_GPV_4_PL301_CFG_ADDR 0x00800000 +#define FSL_IMX6_GPV_4_PL301_CFG_SIZE 0x100000 +#define FSL_IMX6_GPV_3_PL301_CFG_ADDR 0x00300000 +#define FSL_IMX6_GPV_3_PL301_CFG_SIZE 0x100000 +#define FSL_IMX6_GPV_2_PL301_CFG_ADDR 0x00200000 +#define FSL_IMX6_GPV_2_PL301_CFG_SIZE 0x100000 +#define FSL_IMX6_DTCP_ADDR 0x00138000 +#define FSL_IMX6_DTCP_SIZE 0x4000 +#define FSL_IMX6_GPU_2D_ADDR 0x00134000 +#define FSL_IMX6_GPU_2D_SIZE 0x4000 +#define FSL_IMX6_GPU_3D_ADDR 0x00130000 +#define FSL_IMX6_GPU_3D_SIZE 0x4000 +#define FSL_IMX6_HDMI_ADDR 0x00120000 +#define FSL_IMX6_HDMI_SIZE 0x9000 +#define FSL_IMX6_BCH_ADDR 0x00114000 +#define FSL_IMX6_BCH_SIZE 0x4000 +#define FSL_IMX6_GPMI_ADDR 0x00112000 +#define FSL_IMX6_GPMI_SIZE 0x2000 +#define FSL_IMX6_APBH_BRIDGE_DMA_ADDR 0x00110000 +#define FSL_IMX6_APBH_BRIDGE_DMA_SIZE 0x2000 +#define FSL_IMX6_CAAM_MEM_ADDR 0x00100000 +#define FSL_IMX6_CAAM_MEM_SIZE 0x4000 +#define FSL_IMX6_ROM_ADDR 0x00000000 +#define FSL_IMX6_ROM_SIZE 0x18000 + +#define FSL_IMX6_IOMUXC_IRQ 0 +#define FSL_IMX6_DAP_IRQ 1 +#define FSL_IMX6_SDMA_IRQ 2 +#define FSL_IMX6_VPU_JPEG_IRQ 3 +#define FSL_IMX6_SNVS_PMIC_IRQ 4 +#define FSL_IMX6_IPU1_ERROR_IRQ 5 +#define FSL_IMX6_IPU1_SYNC_IRQ 6 +#define FSL_IMX6_IPU2_ERROR_IRQ 7 +#define FSL_IMX6_IPU2_SYNC_IRQ 8 +#define FSL_IMX6_GPU3D_IRQ 9 +#define FSL_IMX6_R2D_IRQ 10 +#define FSL_IMX6_V2D_IRQ 11 +#define FSL_IMX6_VPU_IRQ 12 +#define FSL_IMX6_APBH_BRIDGE_DMA_IRQ 13 +#define FSL_IMX6_EIM_IRQ 14 +#define FSL_IMX6_BCH_IRQ 15 +#define FSL_IMX6_GPMI_IRQ 16 +#define FSL_IMX6_DTCP_IRQ 17 +#define FSL_IMX6_VDOA_IRQ 18 +#define FSL_IMX6_SNVS_CONS_IRQ 19 +#define FSL_IMX6_SNVS_SEC_IRQ 20 +#define FSL_IMX6_CSU_IRQ 21 +#define FSL_IMX6_uSDHC1_IRQ 22 +#define FSL_IMX6_uSDHC2_IRQ 23 +#define FSL_IMX6_uSDHC3_IRQ 24 +#define FSL_IMX6_uSDHC4_IRQ 25 +#define FSL_IMX6_UART1_IRQ 26 +#define FSL_IMX6_UART2_IRQ 27 +#define FSL_IMX6_UART3_IRQ 28 +#define FSL_IMX6_UART4_IRQ 29 +#define FSL_IMX6_UART5_IRQ 30 +#define FSL_IMX6_ECSPI1_IRQ 31 +#define FSL_IMX6_ECSPI2_IRQ 32 +#define FSL_IMX6_ECSPI3_IRQ 33 +#define FSL_IMX6_ECSPI4_IRQ 34 +#define FSL_IMX6_ECSPI5_IRQ 35 +#define FSL_IMX6_I2C1_IRQ 36 +#define FSL_IMX6_I2C2_IRQ 37 +#define FSL_IMX6_I2C3_IRQ 38 +#define FSL_IMX6_SATA_IRQ 39 +#define FSL_IMX6_USB_HOST1_IRQ 40 +#define FSL_IMX6_USB_HOST2_IRQ 41 +#define FSL_IMX6_USB_HOST3_IRQ 42 +#define FSL_IMX6_USB_OTG_IRQ 43 +#define FSL_IMX6_USB_PHY_UTMI0_IRQ 44 +#define FSL_IMX6_USB_PHY_UTMI1_IRQ 45 +#define FSL_IMX6_SSI1_IRQ 46 +#define FSL_IMX6_SSI2_IRQ 47 +#define FSL_IMX6_SSI3_IRQ 48 +#define FSL_IMX6_TEMP_IRQ 49 +#define FSL_IMX6_ASRC_IRQ 50 +#define FSL_IMX6_ESAI_IRQ 51 +#define FSL_IMX6_SPDIF_IRQ 52 +#define FSL_IMX6_MLB150_IRQ 53 +#define FSL_IMX6_PMU1_IRQ 54 +#define FSL_IMX6_GPT_IRQ 55 +#define FSL_IMX6_EPIT1_IRQ 56 +#define FSL_IMX6_EPIT2_IRQ 57 +#define FSL_IMX6_GPIO1_INT7_IRQ 58 +#define FSL_IMX6_GPIO1_INT6_IRQ 59 +#define FSL_IMX6_GPIO1_INT5_IRQ 60 +#define FSL_IMX6_GPIO1_INT4_IRQ 61 +#define FSL_IMX6_GPIO1_INT3_IRQ 62 +#define FSL_IMX6_GPIO1_INT2_IRQ 63 +#define FSL_IMX6_GPIO1_INT1_IRQ 64 +#define FSL_IMX6_GPIO1_INT0_IRQ 65 +#define FSL_IMX6_GPIO1_LOW_IRQ 66 +#define FSL_IMX6_GPIO1_HIGH_IRQ 67 +#define FSL_IMX6_GPIO2_LOW_IRQ 68 +#define FSL_IMX6_GPIO2_HIGH_IRQ 69 +#define FSL_IMX6_GPIO3_LOW_IRQ 70 +#define FSL_IMX6_GPIO3_HIGH_IRQ 71 +#define FSL_IMX6_GPIO4_LOW_IRQ 72 +#define FSL_IMX6_GPIO4_HIGH_IRQ 73 +#define FSL_IMX6_GPIO5_LOW_IRQ 74 +#define FSL_IMX6_GPIO5_HIGH_IRQ 75 +#define FSL_IMX6_GPIO6_LOW_IRQ 76 +#define FSL_IMX6_GPIO6_HIGH_IRQ 77 +#define FSL_IMX6_GPIO7_LOW_IRQ 78 +#define FSL_IMX6_GPIO7_HIGH_IRQ 79 +#define FSL_IMX6_WDOG1_IRQ 80 +#define FSL_IMX6_WDOG2_IRQ 81 +#define FSL_IMX6_KPP_IRQ 82 +#define FSL_IMX6_PWM1_IRQ 83 +#define FSL_IMX6_PWM2_IRQ 84 +#define FSL_IMX6_PWM3_IRQ 85 +#define FSL_IMX6_PWM4_IRQ 86 +#define FSL_IMX6_CCM1_IRQ 87 +#define FSL_IMX6_CCM2_IRQ 88 +#define FSL_IMX6_GPC_IRQ 89 +#define FSL_IMX6_SRC_IRQ 91 +#define FSL_IMX6_CPU_L2_IRQ 92 +#define FSL_IMX6_CPU_PARITY_IRQ 93 +#define FSL_IMX6_CPU_PERF_IRQ 94 +#define FSL_IMX6_CPU_CTI_IRQ 95 +#define FSL_IMX6_SRC_COMB_IRQ 96 +#define FSL_IMX6_MIPI_CSI1_IRQ 100 +#define FSL_IMX6_MIPI_CSI2_IRQ 101 +#define FSL_IMX6_MIPI_DSI_IRQ 102 +#define FSL_IMX6_MIPI_HSI_IRQ 103 +#define FSL_IMX6_SJC_IRQ 104 +#define FSL_IMX6_CAAM0_IRQ 105 +#define FSL_IMX6_CAAM1_IRQ 106 +#define FSL_IMX6_ASC1_IRQ 108 +#define FSL_IMX6_ASC2_IRQ 109 +#define FSL_IMX6_FLEXCAN1_IRQ 110 +#define FSL_IMX6_FLEXCAN2_IRQ 111 +#define FSL_IMX6_HDMI_MASTER_IRQ 115 +#define FSL_IMX6_HDMI_CEC_IRQ 116 +#define FSL_IMX6_MLB150_LOW_IRQ 117 +#define FSL_IMX6_ENET_MAC_IRQ 118 +#define FSL_IMX6_ENET_MAC_1588_IRQ 119 +#define FSL_IMX6_PCIE1_IRQ 120 +#define FSL_IMX6_PCIE2_IRQ 121 +#define FSL_IMX6_PCIE3_IRQ 122 +#define FSL_IMX6_PCIE4_IRQ 123 +#define FSL_IMX6_DCIC1_IRQ 124 +#define FSL_IMX6_DCIC2_IRQ 125 +#define FSL_IMX6_MLB150_HIGH_IRQ 126 +#define FSL_IMX6_PMU2_IRQ 127 +#define FSL_IMX6_MAX_IRQ 128 + +#endif /* FSL_IMX6_H */ From 3a0f31bcb825d37e145411c62b11c3704279de4e Mon Sep 17 00:00:00 2001 From: Jean-Christophe DUBOIS Date: Thu, 12 May 2016 13:22:29 +0100 Subject: [PATCH 31/43] i.MX: Add sabrelite i.MX6 emulation. The sabrelite supports one SPI FLASH memory on SPI1 Signed-off-by: Jean-Christophe Dubois Reviewed-by: Peter Maydell Signed-off-by: Peter Maydell --- hw/arm/Makefile.objs | 2 +- hw/arm/sabrelite.c | 121 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 122 insertions(+), 1 deletion(-) create mode 100644 hw/arm/sabrelite.c diff --git a/hw/arm/Makefile.objs b/hw/arm/Makefile.objs index 2b20e49f4e..12764ef2b7 100644 --- a/hw/arm/Makefile.objs +++ b/hw/arm/Makefile.objs @@ -16,5 +16,5 @@ obj-$(CONFIG_STM32F205_SOC) += stm32f205_soc.o obj-$(CONFIG_XLNX_ZYNQMP) += xlnx-zynqmp.o xlnx-ep108.o obj-$(CONFIG_FSL_IMX25) += fsl-imx25.o imx25_pdk.o obj-$(CONFIG_FSL_IMX31) += fsl-imx31.o kzm.o -obj-$(CONFIG_FSL_IMX6) += fsl-imx6.o +obj-$(CONFIG_FSL_IMX6) += fsl-imx6.o sabrelite.o obj-$(CONFIG_ASPEED_SOC) += ast2400.o palmetto-bmc.o diff --git a/hw/arm/sabrelite.c b/hw/arm/sabrelite.c new file mode 100644 index 0000000000..776c51e398 --- /dev/null +++ b/hw/arm/sabrelite.c @@ -0,0 +1,121 @@ +/* + * SABRELITE Board System emulation. + * + * Copyright (c) 2015 Jean-Christophe Dubois + * + * This code is licensed under the GPL, version 2 or later. + * See the file `COPYING' in the top level directory. + * + * It (partially) emulates a sabrelite board, with a Freescale + * i.MX6 SoC + */ + +#include "qemu/osdep.h" +#include "qapi/error.h" +#include "qemu-common.h" +#include "hw/arm/fsl-imx6.h" +#include "hw/boards.h" +#include "sysemu/sysemu.h" +#include "qemu/error-report.h" +#include "sysemu/qtest.h" + +typedef struct IMX6Sabrelite { + FslIMX6State soc; + MemoryRegion ram; +} IMX6Sabrelite; + +static struct arm_boot_info sabrelite_binfo = { + /* DDR memory start */ + .loader_start = FSL_IMX6_MMDC_ADDR, + /* No board ID, we boot from DT tree */ + .board_id = -1, +}; + +/* No need to do any particular setup for secondary boot */ +static void sabrelite_write_secondary(ARMCPU *cpu, + const struct arm_boot_info *info) +{ +} + +/* Secondary cores are reset through SRC device */ +static void sabrelite_reset_secondary(ARMCPU *cpu, + const struct arm_boot_info *info) +{ +} + +static void sabrelite_init(MachineState *machine) +{ + IMX6Sabrelite *s = g_new0(IMX6Sabrelite, 1); + Error *err = NULL; + + /* Check the amount of memory is compatible with the SOC */ + if (machine->ram_size > FSL_IMX6_MMDC_SIZE) { + error_report("RAM size " RAM_ADDR_FMT " above max supported (%08x)", + machine->ram_size, FSL_IMX6_MMDC_SIZE); + exit(1); + } + + object_initialize(&s->soc, sizeof(s->soc), TYPE_FSL_IMX6); + object_property_add_child(OBJECT(machine), "soc", OBJECT(&s->soc), + &error_abort); + + object_property_set_bool(OBJECT(&s->soc), true, "realized", &err); + if (err != NULL) { + error_report("%s", error_get_pretty(err)); + exit(1); + } + + memory_region_allocate_system_memory(&s->ram, NULL, "sabrelite.ram", + machine->ram_size); + memory_region_add_subregion(get_system_memory(), FSL_IMX6_MMDC_ADDR, + &s->ram); + + { + /* + * TODO: Ideally we would expose the chip select and spi bus on the + * SoC object using alias properties; then we would not need to + * directly access the underlying spi device object. + */ + /* Add the sst25vf016b NOR FLASH memory to first SPI */ + Object *spi_dev; + + spi_dev = object_resolve_path_component(OBJECT(&s->soc), "spi1"); + if (spi_dev) { + SSIBus *spi_bus; + + spi_bus = (SSIBus *)qdev_get_child_bus(DEVICE(spi_dev), "spi"); + if (spi_bus) { + DeviceState *flash_dev; + + flash_dev = ssi_create_slave(spi_bus, "sst25vf016b"); + if (flash_dev) { + qemu_irq cs_line = qdev_get_gpio_in_named(flash_dev, + SSI_GPIO_CS, 0); + sysbus_connect_irq(SYS_BUS_DEVICE(spi_dev), 1, cs_line); + } + } + } + } + + sabrelite_binfo.ram_size = machine->ram_size; + sabrelite_binfo.kernel_filename = machine->kernel_filename; + sabrelite_binfo.kernel_cmdline = machine->kernel_cmdline; + sabrelite_binfo.initrd_filename = machine->initrd_filename; + sabrelite_binfo.nb_cpus = smp_cpus; + sabrelite_binfo.secure_boot = true; + sabrelite_binfo.write_secondary_boot = sabrelite_write_secondary; + sabrelite_binfo.secondary_cpu_reset_hook = sabrelite_reset_secondary; + + if (!qtest_enabled()) { + arm_load_kernel(&s->soc.cpu[0], &sabrelite_binfo); + } +} + +static void sabrelite_machine_init(MachineClass *mc) +{ + mc->desc = "Freescale i.MX6 Quad SABRE Lite Board (Cortex A9)"; + mc->init = sabrelite_init; + mc->max_cpus = FSL_IMX6_NUM_CPUS; +} + +DEFINE_MACHINE("sabrelite", sabrelite_machine_init) From 5c8759087d9cdd12c937a704ea8225f2e4c00ba6 Mon Sep 17 00:00:00 2001 From: Peter Maydell Date: Thu, 12 May 2016 13:22:29 +0100 Subject: [PATCH 32/43] hw/display/blizzard: Expand out macros Now that we can assume that only depth 32 is possible, there's no need for the COPY_PIXEL1 and PIXEL_TYPE macros, and the SKIP_PIXEL, COPY_PIXEL and SWAP_WORDS macros aren't used at all. Expand out COPY_PIXEL1 and PIXEL_TYPE where they are used, delete the unused macro definitions, and expand out the uses of glue(name_prefix, DEPTH). Signed-off-by: Peter Maydell Reviewed-by: Gerd Hoffmann Reviewed-by: Eric Blake Message-id: 1462371352-21498-2-git-send-email-peter.maydell@linaro.org --- hw/display/blizzard_template.h | 55 +++++++++++----------------------- 1 file changed, 17 insertions(+), 38 deletions(-) diff --git a/hw/display/blizzard_template.h b/hw/display/blizzard_template.h index bc38d7afad..ed96092329 100644 --- a/hw/display/blizzard_template.h +++ b/hw/display/blizzard_template.h @@ -18,21 +18,8 @@ * with this program; if not, see . */ -#define SKIP_PIXEL(to) (to += deststep) -#if DEPTH == 32 -# define PIXEL_TYPE uint32_t -# define COPY_PIXEL(to, from) do { *to = from; SKIP_PIXEL(to); } while (0) -# define COPY_PIXEL1(to, from) (*to++ = from) -#else -# error unknown bit depth -#endif - -#ifdef HOST_WORDS_BIGENDIAN -# define SWAP_WORDS 1 -#endif - -static void glue(blizzard_draw_line16_, DEPTH)(PIXEL_TYPE *dest, - const uint16_t *src, unsigned int width) +static void blizzard_draw_line16_32(uint32_t *dest, + const uint16_t *src, unsigned int width) { uint16_t data; unsigned int r, g, b; @@ -45,12 +32,12 @@ static void glue(blizzard_draw_line16_, DEPTH)(PIXEL_TYPE *dest, data >>= 6; r = (data & 0x1f) << 3; data >>= 5; - COPY_PIXEL1(dest, glue(rgb_to_pixel, DEPTH)(r, g, b)); + *dest++ = rgb_to_pixel32(r, g, b); } } -static void glue(blizzard_draw_line24mode1_, DEPTH)(PIXEL_TYPE *dest, - const uint8_t *src, unsigned int width) +static void blizzard_draw_line24mode1_32(uint32_t *dest, + const uint8_t *src, unsigned int width) { /* TODO: check if SDL 24-bit planes are not in the same format and * if so, use memcpy */ @@ -61,15 +48,15 @@ static void glue(blizzard_draw_line24mode1_, DEPTH)(PIXEL_TYPE *dest, r[0] = *src ++; r[1] = *src ++; b[0] = *src ++; - COPY_PIXEL1(dest, glue(rgb_to_pixel, DEPTH)(r[0], g[0], b[0])); + *dest++ = rgb_to_pixel32(r[0], g[0], b[0]); b[1] = *src ++; g[1] = *src ++; - COPY_PIXEL1(dest, glue(rgb_to_pixel, DEPTH)(r[1], g[1], b[1])); + *dest++ = rgb_to_pixel32(r[1], g[1], b[1]); } } -static void glue(blizzard_draw_line24mode2_, DEPTH)(PIXEL_TYPE *dest, - const uint8_t *src, unsigned int width) +static void blizzard_draw_line24mode2_32(uint32_t *dest, + const uint8_t *src, unsigned int width) { unsigned int r, g, b; const uint8_t *end = src + width; @@ -78,24 +65,24 @@ static void glue(blizzard_draw_line24mode2_, DEPTH)(PIXEL_TYPE *dest, src ++; b = *src ++; g = *src ++; - COPY_PIXEL1(dest, glue(rgb_to_pixel, DEPTH)(r, g, b)); + *dest++ = rgb_to_pixel32(r, g, b); } } /* No rotation */ -static blizzard_fn_t glue(blizzard_draw_fn_, DEPTH)[0x10] = { +static blizzard_fn_t blizzard_draw_fn_32[0x10] = { NULL, /* RGB 5:6:5*/ - (blizzard_fn_t) glue(blizzard_draw_line16_, DEPTH), + (blizzard_fn_t) blizzard_draw_line16_32, /* RGB 6:6:6 mode 1 */ - (blizzard_fn_t) glue(blizzard_draw_line24mode1_, DEPTH), + (blizzard_fn_t) blizzard_draw_line24mode1_32, /* RGB 8:8:8 mode 1 */ - (blizzard_fn_t) glue(blizzard_draw_line24mode1_, DEPTH), + (blizzard_fn_t) blizzard_draw_line24mode1_32, NULL, NULL, /* RGB 6:6:6 mode 2 */ - (blizzard_fn_t) glue(blizzard_draw_line24mode2_, DEPTH), + (blizzard_fn_t) blizzard_draw_line24mode2_32, /* RGB 8:8:8 mode 2 */ - (blizzard_fn_t) glue(blizzard_draw_line24mode2_, DEPTH), + (blizzard_fn_t) blizzard_draw_line24mode2_32, /* YUV 4:2:2 */ NULL, /* YUV 4:2:0 */ @@ -104,15 +91,7 @@ static blizzard_fn_t glue(blizzard_draw_fn_, DEPTH)[0x10] = { }; /* 90deg, 180deg and 270deg rotation */ -static blizzard_fn_t glue(blizzard_draw_fn_r_, DEPTH)[0x10] = { +static blizzard_fn_t blizzard_draw_fn_r_32[0x10] = { /* TODO */ [0 ... 0xf] = NULL, }; - -#undef DEPTH -#undef SKIP_PIXEL -#undef COPY_PIXEL -#undef COPY_PIXEL1 -#undef PIXEL_TYPE - -#undef SWAP_WORDS From 4274d821ff586b7691a151dacd93a42e344915bb Mon Sep 17 00:00:00 2001 From: Peter Maydell Date: Thu, 12 May 2016 13:22:30 +0100 Subject: [PATCH 33/43] hw/display/blizzard: Remove blizzard_template.h We no longer need to do the "multiply include this header" trick with blizzard_template.h, and it is only used in a single .c file, so just put its contents inline in blizzard.c. Signed-off-by: Peter Maydell Reviewed-by: Gerd Hoffmann Reviewed-by: Eric Blake Message-id: 1462371352-21498-3-git-send-email-peter.maydell@linaro.org --- hw/display/blizzard.c | 79 ++++++++++++++++++++++++++- hw/display/blizzard_template.h | 97 ---------------------------------- 2 files changed, 77 insertions(+), 99 deletions(-) delete mode 100644 hw/display/blizzard_template.h diff --git a/hw/display/blizzard.c b/hw/display/blizzard.c index af0b51e73b..cbf07d14d9 100644 --- a/hw/display/blizzard.c +++ b/hw/display/blizzard.c @@ -925,8 +925,83 @@ static void blizzard_update_display(void *opaque) s->my[1] = 0; } -#define DEPTH 32 -#include "blizzard_template.h" +static void blizzard_draw_line16_32(uint32_t *dest, + const uint16_t *src, unsigned int width) +{ + uint16_t data; + unsigned int r, g, b; + const uint16_t *end = (const void *) src + width; + while (src < end) { + data = *src ++; + b = (data & 0x1f) << 3; + data >>= 5; + g = (data & 0x3f) << 2; + data >>= 6; + r = (data & 0x1f) << 3; + data >>= 5; + *dest++ = rgb_to_pixel32(r, g, b); + } +} + +static void blizzard_draw_line24mode1_32(uint32_t *dest, + const uint8_t *src, unsigned int width) +{ + /* TODO: check if SDL 24-bit planes are not in the same format and + * if so, use memcpy */ + unsigned int r[2], g[2], b[2]; + const uint8_t *end = src + width; + while (src < end) { + g[0] = *src ++; + r[0] = *src ++; + r[1] = *src ++; + b[0] = *src ++; + *dest++ = rgb_to_pixel32(r[0], g[0], b[0]); + b[1] = *src ++; + g[1] = *src ++; + *dest++ = rgb_to_pixel32(r[1], g[1], b[1]); + } +} + +static void blizzard_draw_line24mode2_32(uint32_t *dest, + const uint8_t *src, unsigned int width) +{ + unsigned int r, g, b; + const uint8_t *end = src + width; + while (src < end) { + r = *src ++; + src ++; + b = *src ++; + g = *src ++; + *dest++ = rgb_to_pixel32(r, g, b); + } +} + +/* No rotation */ +static blizzard_fn_t blizzard_draw_fn_32[0x10] = { + NULL, + /* RGB 5:6:5*/ + (blizzard_fn_t) blizzard_draw_line16_32, + /* RGB 6:6:6 mode 1 */ + (blizzard_fn_t) blizzard_draw_line24mode1_32, + /* RGB 8:8:8 mode 1 */ + (blizzard_fn_t) blizzard_draw_line24mode1_32, + NULL, NULL, + /* RGB 6:6:6 mode 2 */ + (blizzard_fn_t) blizzard_draw_line24mode2_32, + /* RGB 8:8:8 mode 2 */ + (blizzard_fn_t) blizzard_draw_line24mode2_32, + /* YUV 4:2:2 */ + NULL, + /* YUV 4:2:0 */ + NULL, + NULL, NULL, NULL, NULL, NULL, NULL, +}; + +/* 90deg, 180deg and 270deg rotation */ +static blizzard_fn_t blizzard_draw_fn_r_32[0x10] = { + /* TODO */ + [0 ... 0xf] = NULL, +}; static const GraphicHwOps blizzard_ops = { .invalidate = blizzard_invalidate_display, diff --git a/hw/display/blizzard_template.h b/hw/display/blizzard_template.h deleted file mode 100644 index ed96092329..0000000000 --- a/hw/display/blizzard_template.h +++ /dev/null @@ -1,97 +0,0 @@ -/* - * QEMU Epson S1D13744/S1D13745 templates - * - * Copyright (C) 2008 Nokia Corporation - * Written by Andrzej Zaborowski - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 or - * (at your option) version 3 of the License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, see . - */ - -static void blizzard_draw_line16_32(uint32_t *dest, - const uint16_t *src, unsigned int width) -{ - uint16_t data; - unsigned int r, g, b; - const uint16_t *end = (const void *) src + width; - while (src < end) { - data = *src ++; - b = (data & 0x1f) << 3; - data >>= 5; - g = (data & 0x3f) << 2; - data >>= 6; - r = (data & 0x1f) << 3; - data >>= 5; - *dest++ = rgb_to_pixel32(r, g, b); - } -} - -static void blizzard_draw_line24mode1_32(uint32_t *dest, - const uint8_t *src, unsigned int width) -{ - /* TODO: check if SDL 24-bit planes are not in the same format and - * if so, use memcpy */ - unsigned int r[2], g[2], b[2]; - const uint8_t *end = src + width; - while (src < end) { - g[0] = *src ++; - r[0] = *src ++; - r[1] = *src ++; - b[0] = *src ++; - *dest++ = rgb_to_pixel32(r[0], g[0], b[0]); - b[1] = *src ++; - g[1] = *src ++; - *dest++ = rgb_to_pixel32(r[1], g[1], b[1]); - } -} - -static void blizzard_draw_line24mode2_32(uint32_t *dest, - const uint8_t *src, unsigned int width) -{ - unsigned int r, g, b; - const uint8_t *end = src + width; - while (src < end) { - r = *src ++; - src ++; - b = *src ++; - g = *src ++; - *dest++ = rgb_to_pixel32(r, g, b); - } -} - -/* No rotation */ -static blizzard_fn_t blizzard_draw_fn_32[0x10] = { - NULL, - /* RGB 5:6:5*/ - (blizzard_fn_t) blizzard_draw_line16_32, - /* RGB 6:6:6 mode 1 */ - (blizzard_fn_t) blizzard_draw_line24mode1_32, - /* RGB 8:8:8 mode 1 */ - (blizzard_fn_t) blizzard_draw_line24mode1_32, - NULL, NULL, - /* RGB 6:6:6 mode 2 */ - (blizzard_fn_t) blizzard_draw_line24mode2_32, - /* RGB 8:8:8 mode 2 */ - (blizzard_fn_t) blizzard_draw_line24mode2_32, - /* YUV 4:2:2 */ - NULL, - /* YUV 4:2:0 */ - NULL, - NULL, NULL, NULL, NULL, NULL, NULL, -}; - -/* 90deg, 180deg and 270deg rotation */ -static blizzard_fn_t blizzard_draw_fn_r_32[0x10] = { - /* TODO */ - [0 ... 0xf] = NULL, -}; From 6459b94c26dd666badb3547fef1456992a08e60b Mon Sep 17 00:00:00 2001 From: Peter Maydell Date: Thu, 12 May 2016 13:22:30 +0100 Subject: [PATCH 34/43] target-arm: Avoid unnecessary TLB flush on TCR_EL2, TCR_EL3 writes The TCR_EL2 and TCR_EL3 regdefs were incorrectly using the vmsa_tcr_el1_write function for writes. Since these registers don't have the A1 bit that TCR_EL1 does, we don't need to do a tlb_flush() when they are written. Remove the unnecessary .writefn and also the harmless but unneeded .raw_writefn and .resetfn definitions. Signed-off-by: Peter Maydell Reviewed-by: Sergey Fedorov --- target-arm/helper.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/target-arm/helper.c b/target-arm/helper.c index 3b76dc3501..a2ab701ca5 100644 --- a/target-arm/helper.c +++ b/target-arm/helper.c @@ -3559,8 +3559,10 @@ static const ARMCPRegInfo el2_cp_reginfo[] = { .resetvalue = 0 }, { .name = "TCR_EL2", .state = ARM_CP_STATE_BOTH, .opc0 = 3, .opc1 = 4, .crn = 2, .crm = 0, .opc2 = 2, - .access = PL2_RW, .writefn = vmsa_tcr_el1_write, - .resetfn = vmsa_ttbcr_reset, .raw_writefn = raw_write, + .access = PL2_RW, + /* no .writefn needed as this can't cause an ASID change; + * no .raw_writefn or .resetfn needed as we never use mask/base_mask + */ .fieldoffset = offsetof(CPUARMState, cp15.tcr_el[2]) }, { .name = "VTCR", .state = ARM_CP_STATE_AA32, .cp = 15, .opc1 = 4, .crn = 2, .crm = 1, .opc2 = 2, @@ -3753,8 +3755,10 @@ static const ARMCPRegInfo el3_cp_reginfo[] = { .fieldoffset = offsetof(CPUARMState, cp15.ttbr0_el[3]) }, { .name = "TCR_EL3", .state = ARM_CP_STATE_AA64, .opc0 = 3, .opc1 = 6, .crn = 2, .crm = 0, .opc2 = 2, - .access = PL3_RW, .writefn = vmsa_tcr_el1_write, - .resetfn = vmsa_ttbcr_reset, .raw_writefn = raw_write, + .access = PL3_RW, + /* no .writefn needed as this can't cause an ASID change; + * no .raw_writefn or .resetfn needed as we never use mask/base_mask + */ .fieldoffset = offsetof(CPUARMState, cp15.tcr_el[3]) }, { .name = "ELR_EL3", .state = ARM_CP_STATE_AA64, .type = ARM_CP_ALIAS, From 3f5ab2549065229bd165d0db66b71512385dbd7a Mon Sep 17 00:00:00 2001 From: "xiaoqiang.zhao" Date: Mon, 7 Mar 2016 15:05:42 +0800 Subject: [PATCH 35/43] hw/arm: QOM'ify armv7m.c Drop the use of old SysBus init function and use instance_init Signed-off-by: xiaoqiang zhao Reviewed-by: Peter Maydell Signed-off-by: Peter Maydell --- hw/arm/armv7m.c | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/hw/arm/armv7m.c b/hw/arm/armv7m.c index bb2a22d967..49d30782c8 100644 --- a/hw/arm/armv7m.c +++ b/hw/arm/armv7m.c @@ -132,14 +132,14 @@ typedef struct { uint32_t base; } BitBandState; -static int bitband_init(SysBusDevice *dev) +static void bitband_init(Object *obj) { - BitBandState *s = BITBAND(dev); + BitBandState *s = BITBAND(obj); + SysBusDevice *dev = SYS_BUS_DEVICE(obj); - memory_region_init_io(&s->iomem, OBJECT(s), &bitband_ops, &s->base, + memory_region_init_io(&s->iomem, obj, &bitband_ops, &s->base, "bitband", 0x02000000); sysbus_init_mmio(dev, &s->iomem); - return 0; } static void armv7m_bitband_init(void) @@ -244,9 +244,7 @@ static Property bitband_properties[] = { static void bitband_class_init(ObjectClass *klass, void *data) { DeviceClass *dc = DEVICE_CLASS(klass); - SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass); - k->init = bitband_init; dc->props = bitband_properties; } @@ -254,6 +252,7 @@ static const TypeInfo bitband_info = { .name = TYPE_BITBAND, .parent = TYPE_SYS_BUS_DEVICE, .instance_size = sizeof(BitBandState), + .instance_init = bitband_init, .class_init = bitband_class_init, }; From ff7a27c15ae152e4ee7cc15a03c256ab913145e7 Mon Sep 17 00:00:00 2001 From: "xiaoqiang.zhao" Date: Mon, 7 Mar 2016 15:05:43 +0800 Subject: [PATCH 36/43] hw/arm: QOM'ify highbank.c Drop the use of old SysBus init function and use instance_init Signed-off-by: xiaoqiang zhao Reviewed-by: Peter Crosthwaite Signed-off-by: Peter Maydell --- hw/arm/highbank.c | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/hw/arm/highbank.c b/hw/arm/highbank.c index d9930c0d34..41029a651d 100644 --- a/hw/arm/highbank.c +++ b/hw/arm/highbank.c @@ -168,23 +168,20 @@ static void highbank_regs_reset(DeviceState *dev) s->regs[0x43] = 0x05F40121; } -static int highbank_regs_init(SysBusDevice *dev) +static void highbank_regs_init(Object *obj) { - HighbankRegsState *s = HIGHBANK_REGISTERS(dev); + HighbankRegsState *s = HIGHBANK_REGISTERS(obj); + SysBusDevice *dev = SYS_BUS_DEVICE(obj); - memory_region_init_io(&s->iomem, OBJECT(s), &hb_mem_ops, s->regs, + memory_region_init_io(&s->iomem, obj, &hb_mem_ops, s->regs, "highbank_regs", 0x1000); sysbus_init_mmio(dev, &s->iomem); - - return 0; } static void highbank_regs_class_init(ObjectClass *klass, void *data) { - SysBusDeviceClass *sbc = SYS_BUS_DEVICE_CLASS(klass); DeviceClass *dc = DEVICE_CLASS(klass); - sbc->init = highbank_regs_init; dc->desc = "Calxeda Highbank registers"; dc->vmsd = &vmstate_highbank_regs; dc->reset = highbank_regs_reset; @@ -194,6 +191,7 @@ static const TypeInfo highbank_regs_info = { .name = TYPE_HIGHBANK_REGISTERS, .parent = TYPE_SYS_BUS_DEVICE, .instance_size = sizeof(HighbankRegsState), + .instance_init = highbank_regs_init, .class_init = highbank_regs_class_init, }; From a1f42e0c9abc1028a8bb8686dbb3749fcd2d18e8 Mon Sep 17 00:00:00 2001 From: "xiaoqiang.zhao" Date: Mon, 7 Mar 2016 15:05:44 +0800 Subject: [PATCH 37/43] hw/arm: QOM'ify integratorcp.c * Drop the use of old SysBus init function and use instance_init * Remove the empty 'icp_pic_class_init' from Typeinfo Signed-off-by: xiaoqiang zhao Reviewed-by: Peter Maydell Signed-off-by: Peter Maydell --- hw/arm/integratorcp.c | 32 ++++++++++++-------------------- 1 file changed, 12 insertions(+), 20 deletions(-) diff --git a/hw/arm/integratorcp.c b/hw/arm/integratorcp.c index e31bca6e72..24f16874f9 100644 --- a/hw/arm/integratorcp.c +++ b/hw/arm/integratorcp.c @@ -242,9 +242,10 @@ static const MemoryRegionOps integratorcm_ops = { .endianness = DEVICE_NATIVE_ENDIAN, }; -static int integratorcm_init(SysBusDevice *dev) +static void integratorcm_init(Object *obj) { - IntegratorCMState *s = INTEGRATOR_CM(dev); + IntegratorCMState *s = INTEGRATOR_CM(obj); + SysBusDevice *dev = SYS_BUS_DEVICE(obj); s->cm_osc = 0x01000048; /* ??? What should the high bits of this value be? */ @@ -269,17 +270,16 @@ static int integratorcm_init(SysBusDevice *dev) s->cm_init = 0x00000112; s->cm_refcnt_offset = muldiv64(qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL), 24, 1000); - memory_region_init_ram(&s->flash, OBJECT(s), "integrator.flash", 0x100000, + memory_region_init_ram(&s->flash, obj, "integrator.flash", 0x100000, &error_fatal); vmstate_register_ram_global(&s->flash); - memory_region_init_io(&s->iomem, OBJECT(s), &integratorcm_ops, s, + memory_region_init_io(&s->iomem, obj, &integratorcm_ops, s, "integratorcm", 0x00800000); sysbus_init_mmio(dev, &s->iomem); integratorcm_do_remap(s); /* ??? Save/restore. */ - return 0; } /* Integrator/CP hardware emulation. */ @@ -394,18 +394,18 @@ static const MemoryRegionOps icp_pic_ops = { .endianness = DEVICE_NATIVE_ENDIAN, }; -static int icp_pic_init(SysBusDevice *sbd) +static void icp_pic_init(Object *obj) { - DeviceState *dev = DEVICE(sbd); - icp_pic_state *s = INTEGRATOR_PIC(dev); + DeviceState *dev = DEVICE(obj); + icp_pic_state *s = INTEGRATOR_PIC(obj); + SysBusDevice *sbd = SYS_BUS_DEVICE(obj); qdev_init_gpio_in(dev, icp_pic_set_irq, 32); sysbus_init_irq(sbd, &s->parent_irq); sysbus_init_irq(sbd, &s->parent_fiq); - memory_region_init_io(&s->iomem, OBJECT(s), &icp_pic_ops, s, + memory_region_init_io(&s->iomem, obj, &icp_pic_ops, s, "icp-pic", 0x00800000); sysbus_init_mmio(sbd, &s->iomem); - return 0; } /* CP control registers. */ @@ -630,9 +630,7 @@ static Property core_properties[] = { static void core_class_init(ObjectClass *klass, void *data) { DeviceClass *dc = DEVICE_CLASS(klass); - SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass); - k->init = integratorcm_init; dc->props = core_properties; } @@ -640,21 +638,15 @@ static const TypeInfo core_info = { .name = TYPE_INTEGRATOR_CM, .parent = TYPE_SYS_BUS_DEVICE, .instance_size = sizeof(IntegratorCMState), + .instance_init = integratorcm_init, .class_init = core_class_init, }; -static void icp_pic_class_init(ObjectClass *klass, void *data) -{ - SysBusDeviceClass *sdc = SYS_BUS_DEVICE_CLASS(klass); - - sdc->init = icp_pic_init; -} - static const TypeInfo icp_pic_info = { .name = TYPE_INTEGRATOR_PIC, .parent = TYPE_SYS_BUS_DEVICE, .instance_size = sizeof(icp_pic_state), - .class_init = icp_pic_class_init, + .instance_init = icp_pic_init, }; static const TypeInfo icp_ctrl_regs_info = { From 16fb31a382a195e9f2f9315829bba2f31631ff17 Mon Sep 17 00:00:00 2001 From: "xiaoqiang.zhao" Date: Mon, 7 Mar 2016 15:05:45 +0800 Subject: [PATCH 38/43] hw/arm: QOM'ify pxa2xx.c Drop the use of old SysBus init function and use instance_init Signed-off-by: xiaoqiang zhao Reviewed-by: Peter Maydell Signed-off-by: Peter Maydell --- hw/arm/pxa2xx.c | 26 +++++++++++--------------- 1 file changed, 11 insertions(+), 15 deletions(-) diff --git a/hw/arm/pxa2xx.c b/hw/arm/pxa2xx.c index 1a8c36033a..e41a7c92ab 100644 --- a/hw/arm/pxa2xx.c +++ b/hw/arm/pxa2xx.c @@ -1107,9 +1107,10 @@ static const MemoryRegionOps pxa2xx_rtc_ops = { .endianness = DEVICE_NATIVE_ENDIAN, }; -static int pxa2xx_rtc_init(SysBusDevice *dev) +static void pxa2xx_rtc_init(Object *obj) { - PXA2xxRTCState *s = PXA2XX_RTC(dev); + PXA2xxRTCState *s = PXA2XX_RTC(obj); + SysBusDevice *dev = SYS_BUS_DEVICE(obj); struct tm tm; int wom; @@ -1138,11 +1139,9 @@ static int pxa2xx_rtc_init(SysBusDevice *dev) sysbus_init_irq(dev, &s->rtc_irq); - memory_region_init_io(&s->iomem, OBJECT(s), &pxa2xx_rtc_ops, s, + memory_region_init_io(&s->iomem, obj, &pxa2xx_rtc_ops, s, "pxa2xx-rtc", 0x10000); sysbus_init_mmio(dev, &s->iomem); - - return 0; } static void pxa2xx_rtc_pre_save(void *opaque) @@ -1195,9 +1194,7 @@ static const VMStateDescription vmstate_pxa2xx_rtc_regs = { static void pxa2xx_rtc_sysbus_class_init(ObjectClass *klass, void *data) { DeviceClass *dc = DEVICE_CLASS(klass); - SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass); - k->init = pxa2xx_rtc_init; dc->desc = "PXA2xx RTC Controller"; dc->vmsd = &vmstate_pxa2xx_rtc_regs; } @@ -1206,6 +1203,7 @@ static const TypeInfo pxa2xx_rtc_sysbus_info = { .name = TYPE_PXA2XX_RTC, .parent = TYPE_SYS_BUS_DEVICE, .instance_size = sizeof(PXA2xxRTCState), + .instance_init = pxa2xx_rtc_init, .class_init = pxa2xx_rtc_sysbus_class_init, }; @@ -1501,19 +1499,18 @@ PXA2xxI2CState *pxa2xx_i2c_init(hwaddr base, return s; } -static int pxa2xx_i2c_initfn(SysBusDevice *sbd) +static void pxa2xx_i2c_initfn(Object *obj) { - DeviceState *dev = DEVICE(sbd); - PXA2xxI2CState *s = PXA2XX_I2C(dev); + DeviceState *dev = DEVICE(obj); + PXA2xxI2CState *s = PXA2XX_I2C(obj); + SysBusDevice *sbd = SYS_BUS_DEVICE(obj); s->bus = i2c_init_bus(dev, "i2c"); - memory_region_init_io(&s->iomem, OBJECT(s), &pxa2xx_i2c_ops, s, + memory_region_init_io(&s->iomem, obj, &pxa2xx_i2c_ops, s, "pxa2xx-i2c", s->region_size); sysbus_init_mmio(sbd, &s->iomem); sysbus_init_irq(sbd, &s->irq); - - return 0; } I2CBus *pxa2xx_i2c_bus(PXA2xxI2CState *s) @@ -1530,9 +1527,7 @@ static Property pxa2xx_i2c_properties[] = { static void pxa2xx_i2c_class_init(ObjectClass *klass, void *data) { DeviceClass *dc = DEVICE_CLASS(klass); - SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass); - k->init = pxa2xx_i2c_initfn; dc->desc = "PXA2xx I2C Bus Controller"; dc->vmsd = &vmstate_pxa2xx_i2c; dc->props = pxa2xx_i2c_properties; @@ -1542,6 +1537,7 @@ static const TypeInfo pxa2xx_i2c_info = { .name = TYPE_PXA2XX_I2C, .parent = TYPE_SYS_BUS_DEVICE, .instance_size = sizeof(PXA2xxI2CState), + .instance_init = pxa2xx_i2c_initfn, .class_init = pxa2xx_i2c_class_init, }; From 08ba3fde1dcb8d52d0fbcec1985a549fd53690aa Mon Sep 17 00:00:00 2001 From: "xiaoqiang.zhao" Date: Mon, 7 Mar 2016 15:05:46 +0800 Subject: [PATCH 39/43] hw/arm: QOM'ify pxa2xx_pic.c Remove the empty 'pxa2xx_pic_initfn' and it's setup code in the 'pxa2xx_pic_class_init' Signed-off-by: xiaoqiang zhao Reviewed-by: Peter Maydell Signed-off-by: Peter Maydell --- hw/arm/pxa2xx_pic.c | 7 ------- 1 file changed, 7 deletions(-) diff --git a/hw/arm/pxa2xx_pic.c b/hw/arm/pxa2xx_pic.c index 7e51532cde..b516ced8c0 100644 --- a/hw/arm/pxa2xx_pic.c +++ b/hw/arm/pxa2xx_pic.c @@ -310,17 +310,10 @@ static VMStateDescription vmstate_pxa2xx_pic_regs = { }, }; -static int pxa2xx_pic_initfn(SysBusDevice *dev) -{ - return 0; -} - static void pxa2xx_pic_class_init(ObjectClass *klass, void *data) { DeviceClass *dc = DEVICE_CLASS(klass); - SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass); - k->init = pxa2xx_pic_initfn; dc->desc = "PXA2xx PIC"; dc->vmsd = &vmstate_pxa2xx_pic_regs; } From f68575c956324692b2703b0fdb3a697047bdcdde Mon Sep 17 00:00:00 2001 From: xiaoqiang zhao Date: Mon, 7 Mar 2016 15:52:16 +0800 Subject: [PATCH 40/43] hw/arm: QOM'ify spitz.c Drop the use of old SysBus init function and use instance_init Signed-off-by: xiaoqiang zhao Reviewed-by: Peter Maydell Signed-off-by: Peter Maydell --- hw/arm/spitz.c | 23 +++++++++-------------- 1 file changed, 9 insertions(+), 14 deletions(-) diff --git a/hw/arm/spitz.c b/hw/arm/spitz.c index bf61d63b58..ba40f8302b 100644 --- a/hw/arm/spitz.c +++ b/hw/arm/spitz.c @@ -164,9 +164,10 @@ static void sl_flash_register(PXA2xxState *cpu, int size) sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, FLASH_BASE); } -static int sl_nand_init(SysBusDevice *dev) +static void sl_nand_init(Object *obj) { - SLNANDState *s = SL_NAND(dev); + SLNANDState *s = SL_NAND(obj); + SysBusDevice *dev = SYS_BUS_DEVICE(obj); DriveInfo *nand; s->ctl = 0; @@ -175,10 +176,8 @@ static int sl_nand_init(SysBusDevice *dev) s->nand = nand_init(nand ? blk_by_legacy_dinfo(nand) : NULL, s->manf_id, s->chip_id); - memory_region_init_io(&s->iomem, OBJECT(s), &sl_ops, s, "sl", 0x40); + memory_region_init_io(&s->iomem, obj, &sl_ops, s, "sl", 0x40); sysbus_init_mmio(dev, &s->iomem); - - return 0; } /* Spitz Keyboard */ @@ -501,10 +500,10 @@ static void spitz_keyboard_register(PXA2xxState *cpu) qemu_add_kbd_event_handler(spitz_keyboard_handler, s); } -static int spitz_keyboard_init(SysBusDevice *sbd) +static void spitz_keyboard_init(Object *obj) { - DeviceState *dev = DEVICE(sbd); - SpitzKeyboardState *s = SPITZ_KEYBOARD(dev); + DeviceState *dev = DEVICE(obj); + SpitzKeyboardState *s = SPITZ_KEYBOARD(obj); int i, j; for (i = 0; i < 0x80; i ++) @@ -519,8 +518,6 @@ static int spitz_keyboard_init(SysBusDevice *sbd) s->kbdtimer = timer_new_ns(QEMU_CLOCK_VIRTUAL, spitz_keyboard_tick, s); qdev_init_gpio_in(dev, spitz_keyboard_strobe, SPITZ_KEY_STROBE_NUM); qdev_init_gpio_out(dev, s->sense, SPITZ_KEY_SENSE_NUM); - - return 0; } /* LCD backlight controller */ @@ -1065,9 +1062,7 @@ static Property sl_nand_properties[] = { static void sl_nand_class_init(ObjectClass *klass, void *data) { DeviceClass *dc = DEVICE_CLASS(klass); - SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass); - k->init = sl_nand_init; dc->vmsd = &vmstate_sl_nand_info; dc->props = sl_nand_properties; /* Reason: init() method uses drive_get() */ @@ -1078,6 +1073,7 @@ static const TypeInfo sl_nand_info = { .name = TYPE_SL_NAND, .parent = TYPE_SYS_BUS_DEVICE, .instance_size = sizeof(SLNANDState), + .instance_init = sl_nand_init, .class_init = sl_nand_class_init, }; @@ -1097,9 +1093,7 @@ static VMStateDescription vmstate_spitz_kbd = { static void spitz_keyboard_class_init(ObjectClass *klass, void *data) { DeviceClass *dc = DEVICE_CLASS(klass); - SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass); - k->init = spitz_keyboard_init; dc->vmsd = &vmstate_spitz_kbd; } @@ -1107,6 +1101,7 @@ static const TypeInfo spitz_keyboard_info = { .name = TYPE_SPITZ_KEYBOARD, .parent = TYPE_SYS_BUS_DEVICE, .instance_size = sizeof(SpitzKeyboardState), + .instance_init = spitz_keyboard_init, .class_init = spitz_keyboard_class_init, }; From 15c4fff5d89de7ce353fe5f2a3fdb6a052f5941f Mon Sep 17 00:00:00 2001 From: "xiaoqiang.zhao" Date: Mon, 7 Mar 2016 15:05:48 +0800 Subject: [PATCH 41/43] hw/arm: QOM'ify stellaris.c * Drop the use of old SysBus init function and use instance_init * Use DeviceClass::vmsd instead of 'vmstate_register' function Signed-off-by: xiaoqiang zhao Reviewed-by: Peter Maydell Signed-off-by: Peter Maydell --- hw/arm/stellaris.c | 48 +++++++++++++++++++++++----------------------- 1 file changed, 24 insertions(+), 24 deletions(-) diff --git a/hw/arm/stellaris.c b/hw/arm/stellaris.c index c1766f856a..f90b9fd190 100644 --- a/hw/arm/stellaris.c +++ b/hw/arm/stellaris.c @@ -316,23 +316,22 @@ static const VMStateDescription vmstate_stellaris_gptm = { } }; -static int stellaris_gptm_init(SysBusDevice *sbd) +static void stellaris_gptm_init(Object *obj) { - DeviceState *dev = DEVICE(sbd); - gptm_state *s = STELLARIS_GPTM(dev); + DeviceState *dev = DEVICE(obj); + gptm_state *s = STELLARIS_GPTM(obj); + SysBusDevice *sbd = SYS_BUS_DEVICE(obj); sysbus_init_irq(sbd, &s->irq); qdev_init_gpio_out(dev, &s->trigger, 1); - memory_region_init_io(&s->iomem, OBJECT(s), &gptm_ops, s, + memory_region_init_io(&s->iomem, obj, &gptm_ops, s, "gptm", 0x1000); sysbus_init_mmio(sbd, &s->iomem); s->opaque[0] = s->opaque[1] = s; s->timer[0] = timer_new_ns(QEMU_CLOCK_VIRTUAL, gptm_tick, &s->opaque[0]); s->timer[1] = timer_new_ns(QEMU_CLOCK_VIRTUAL, gptm_tick, &s->opaque[1]); - vmstate_register(dev, -1, &vmstate_stellaris_gptm, s); - return 0; } @@ -873,23 +872,22 @@ static const VMStateDescription vmstate_stellaris_i2c = { } }; -static int stellaris_i2c_init(SysBusDevice *sbd) +static void stellaris_i2c_init(Object *obj) { - DeviceState *dev = DEVICE(sbd); - stellaris_i2c_state *s = STELLARIS_I2C(dev); + DeviceState *dev = DEVICE(obj); + stellaris_i2c_state *s = STELLARIS_I2C(obj); + SysBusDevice *sbd = SYS_BUS_DEVICE(obj); I2CBus *bus; sysbus_init_irq(sbd, &s->irq); bus = i2c_init_bus(dev, "i2c"); s->bus = bus; - memory_region_init_io(&s->iomem, OBJECT(s), &stellaris_i2c_ops, s, + memory_region_init_io(&s->iomem, obj, &stellaris_i2c_ops, s, "i2c", 0x1000); sysbus_init_mmio(sbd, &s->iomem); /* ??? For now we only implement the master interface. */ stellaris_i2c_reset(s); - vmstate_register(dev, -1, &vmstate_stellaris_i2c, s); - return 0; } /* Analogue to Digital Converter. This is only partially implemented, @@ -1160,23 +1158,22 @@ static const VMStateDescription vmstate_stellaris_adc = { } }; -static int stellaris_adc_init(SysBusDevice *sbd) +static void stellaris_adc_init(Object *obj) { - DeviceState *dev = DEVICE(sbd); - stellaris_adc_state *s = STELLARIS_ADC(dev); + DeviceState *dev = DEVICE(obj); + stellaris_adc_state *s = STELLARIS_ADC(obj); + SysBusDevice *sbd = SYS_BUS_DEVICE(obj); int n; for (n = 0; n < 4; n++) { sysbus_init_irq(sbd, &s->irq[n]); } - memory_region_init_io(&s->iomem, OBJECT(s), &stellaris_adc_ops, s, + memory_region_init_io(&s->iomem, obj, &stellaris_adc_ops, s, "adc", 0x1000); sysbus_init_mmio(sbd, &s->iomem); stellaris_adc_reset(s); qdev_init_gpio_in(dev, stellaris_adc_trigger, 1); - vmstate_register(dev, -1, &vmstate_stellaris_adc, s); - return 0; } static @@ -1425,43 +1422,46 @@ type_init(stellaris_machine_init) static void stellaris_i2c_class_init(ObjectClass *klass, void *data) { - SysBusDeviceClass *sdc = SYS_BUS_DEVICE_CLASS(klass); + DeviceClass *dc = DEVICE_CLASS(klass); - sdc->init = stellaris_i2c_init; + dc->vmsd = &vmstate_stellaris_i2c; } static const TypeInfo stellaris_i2c_info = { .name = TYPE_STELLARIS_I2C, .parent = TYPE_SYS_BUS_DEVICE, .instance_size = sizeof(stellaris_i2c_state), + .instance_init = stellaris_i2c_init, .class_init = stellaris_i2c_class_init, }; static void stellaris_gptm_class_init(ObjectClass *klass, void *data) { - SysBusDeviceClass *sdc = SYS_BUS_DEVICE_CLASS(klass); + DeviceClass *dc = DEVICE_CLASS(klass); - sdc->init = stellaris_gptm_init; + dc->vmsd = &vmstate_stellaris_gptm; } static const TypeInfo stellaris_gptm_info = { .name = TYPE_STELLARIS_GPTM, .parent = TYPE_SYS_BUS_DEVICE, .instance_size = sizeof(gptm_state), + .instance_init = stellaris_gptm_init, .class_init = stellaris_gptm_class_init, }; static void stellaris_adc_class_init(ObjectClass *klass, void *data) { - SysBusDeviceClass *sdc = SYS_BUS_DEVICE_CLASS(klass); + DeviceClass *dc = DEVICE_CLASS(klass); - sdc->init = stellaris_adc_init; + dc->vmsd = &vmstate_stellaris_adc; } static const TypeInfo stellaris_adc_info = { .name = TYPE_STELLARIS_ADC, .parent = TYPE_SYS_BUS_DEVICE, .instance_size = sizeof(stellaris_adc_state), + .instance_init = stellaris_adc_init, .class_init = stellaris_adc_class_init, }; From 5a67508c7acfaf8811352594f4c3b1952d32d837 Mon Sep 17 00:00:00 2001 From: "xiaoqiang.zhao" Date: Mon, 7 Mar 2016 15:05:49 +0800 Subject: [PATCH 42/43] hw/arm: QOM'ify strongarm.c Drop the use of old SysBus init function and use instance_init Signed-off-by: xiaoqiang zhao Reviewed-by: Peter Maydell Signed-off-by: Peter Maydell --- hw/arm/strongarm.c | 66 ++++++++++++++++++++-------------------------- 1 file changed, 28 insertions(+), 38 deletions(-) diff --git a/hw/arm/strongarm.c b/hw/arm/strongarm.c index 1eeb1ab391..3bc8a98150 100644 --- a/hw/arm/strongarm.c +++ b/hw/arm/strongarm.c @@ -179,19 +179,18 @@ static const MemoryRegionOps strongarm_pic_ops = { .endianness = DEVICE_NATIVE_ENDIAN, }; -static int strongarm_pic_initfn(SysBusDevice *sbd) +static void strongarm_pic_initfn(Object *obj) { - DeviceState *dev = DEVICE(sbd); - StrongARMPICState *s = STRONGARM_PIC(dev); + DeviceState *dev = DEVICE(obj); + StrongARMPICState *s = STRONGARM_PIC(obj); + SysBusDevice *sbd = SYS_BUS_DEVICE(obj); qdev_init_gpio_in(dev, strongarm_pic_set_irq, SA_PIC_SRCS); - memory_region_init_io(&s->iomem, OBJECT(s), &strongarm_pic_ops, s, + memory_region_init_io(&s->iomem, obj, &strongarm_pic_ops, s, "pic", 0x1000); sysbus_init_mmio(sbd, &s->iomem); sysbus_init_irq(sbd, &s->irq); sysbus_init_irq(sbd, &s->fiq); - - return 0; } static int strongarm_pic_post_load(void *opaque, int version_id) @@ -217,9 +216,7 @@ static VMStateDescription vmstate_strongarm_pic_regs = { static void strongarm_pic_class_init(ObjectClass *klass, void *data) { DeviceClass *dc = DEVICE_CLASS(klass); - SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass); - k->init = strongarm_pic_initfn; dc->desc = "StrongARM PIC"; dc->vmsd = &vmstate_strongarm_pic_regs; } @@ -228,6 +225,7 @@ static const TypeInfo strongarm_pic_info = { .name = TYPE_STRONGARM_PIC, .parent = TYPE_SYS_BUS_DEVICE, .instance_size = sizeof(StrongARMPICState), + .instance_init = strongarm_pic_initfn, .class_init = strongarm_pic_class_init, }; @@ -381,9 +379,10 @@ static const MemoryRegionOps strongarm_rtc_ops = { .endianness = DEVICE_NATIVE_ENDIAN, }; -static int strongarm_rtc_init(SysBusDevice *dev) +static void strongarm_rtc_init(Object *obj) { - StrongARMRTCState *s = STRONGARM_RTC(dev); + StrongARMRTCState *s = STRONGARM_RTC(obj); + SysBusDevice *dev = SYS_BUS_DEVICE(obj); struct tm tm; s->rttr = 0x0; @@ -400,11 +399,9 @@ static int strongarm_rtc_init(SysBusDevice *dev) sysbus_init_irq(dev, &s->rtc_irq); sysbus_init_irq(dev, &s->rtc_hz_irq); - memory_region_init_io(&s->iomem, OBJECT(s), &strongarm_rtc_ops, s, + memory_region_init_io(&s->iomem, obj, &strongarm_rtc_ops, s, "rtc", 0x10000); sysbus_init_mmio(dev, &s->iomem); - - return 0; } static void strongarm_rtc_pre_save(void *opaque) @@ -443,9 +440,7 @@ static const VMStateDescription vmstate_strongarm_rtc_regs = { static void strongarm_rtc_sysbus_class_init(ObjectClass *klass, void *data) { DeviceClass *dc = DEVICE_CLASS(klass); - SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass); - k->init = strongarm_rtc_init; dc->desc = "StrongARM RTC Controller"; dc->vmsd = &vmstate_strongarm_rtc_regs; } @@ -454,6 +449,7 @@ static const TypeInfo strongarm_rtc_sysbus_info = { .name = TYPE_STRONGARM_RTC, .parent = TYPE_SYS_BUS_DEVICE, .instance_size = sizeof(StrongARMRTCState), + .instance_init = strongarm_rtc_init, .class_init = strongarm_rtc_sysbus_class_init, }; @@ -646,16 +642,17 @@ static DeviceState *strongarm_gpio_init(hwaddr base, return dev; } -static int strongarm_gpio_initfn(SysBusDevice *sbd) +static void strongarm_gpio_initfn(Object *obj) { - DeviceState *dev = DEVICE(sbd); - StrongARMGPIOInfo *s = STRONGARM_GPIO(dev); + DeviceState *dev = DEVICE(obj); + StrongARMGPIOInfo *s = STRONGARM_GPIO(obj); + SysBusDevice *sbd = SYS_BUS_DEVICE(obj); int i; qdev_init_gpio_in(dev, strongarm_gpio_set, 28); qdev_init_gpio_out(dev, s->handler, 28); - memory_region_init_io(&s->iomem, OBJECT(s), &strongarm_gpio_ops, s, + memory_region_init_io(&s->iomem, obj, &strongarm_gpio_ops, s, "gpio", 0x1000); sysbus_init_mmio(sbd, &s->iomem); @@ -663,8 +660,6 @@ static int strongarm_gpio_initfn(SysBusDevice *sbd) sysbus_init_irq(sbd, &s->irqs[i]); } sysbus_init_irq(sbd, &s->irqX); - - return 0; } static const VMStateDescription vmstate_strongarm_gpio_regs = { @@ -687,9 +682,7 @@ static const VMStateDescription vmstate_strongarm_gpio_regs = { static void strongarm_gpio_class_init(ObjectClass *klass, void *data) { DeviceClass *dc = DEVICE_CLASS(klass); - SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass); - k->init = strongarm_gpio_initfn; dc->desc = "StrongARM GPIO controller"; dc->vmsd = &vmstate_strongarm_gpio_regs; } @@ -698,6 +691,7 @@ static const TypeInfo strongarm_gpio_info = { .name = TYPE_STRONGARM_GPIO, .parent = TYPE_SYS_BUS_DEVICE, .instance_size = sizeof(StrongARMGPIOInfo), + .instance_init = strongarm_gpio_initfn, .class_init = strongarm_gpio_class_init, }; @@ -824,20 +818,19 @@ static const MemoryRegionOps strongarm_ppc_ops = { .endianness = DEVICE_NATIVE_ENDIAN, }; -static int strongarm_ppc_init(SysBusDevice *sbd) +static void strongarm_ppc_init(Object *obj) { - DeviceState *dev = DEVICE(sbd); - StrongARMPPCInfo *s = STRONGARM_PPC(dev); + DeviceState *dev = DEVICE(obj); + StrongARMPPCInfo *s = STRONGARM_PPC(obj); + SysBusDevice *sbd = SYS_BUS_DEVICE(obj); qdev_init_gpio_in(dev, strongarm_ppc_set, 22); qdev_init_gpio_out(dev, s->handler, 22); - memory_region_init_io(&s->iomem, OBJECT(s), &strongarm_ppc_ops, s, + memory_region_init_io(&s->iomem, obj, &strongarm_ppc_ops, s, "ppc", 0x1000); sysbus_init_mmio(sbd, &s->iomem); - - return 0; } static const VMStateDescription vmstate_strongarm_ppc_regs = { @@ -859,9 +852,7 @@ static const VMStateDescription vmstate_strongarm_ppc_regs = { static void strongarm_ppc_class_init(ObjectClass *klass, void *data) { DeviceClass *dc = DEVICE_CLASS(klass); - SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass); - k->init = strongarm_ppc_init; dc->desc = "StrongARM PPC controller"; dc->vmsd = &vmstate_strongarm_ppc_regs; } @@ -870,6 +861,7 @@ static const TypeInfo strongarm_ppc_info = { .name = TYPE_STRONGARM_PPC, .parent = TYPE_SYS_BUS_DEVICE, .instance_size = sizeof(StrongARMPPCInfo), + .instance_init = strongarm_ppc_init, .class_init = strongarm_ppc_class_init, }; @@ -1231,11 +1223,12 @@ static const MemoryRegionOps strongarm_uart_ops = { .endianness = DEVICE_NATIVE_ENDIAN, }; -static int strongarm_uart_init(SysBusDevice *dev) +static void strongarm_uart_init(Object *obj) { - StrongARMUARTState *s = STRONGARM_UART(dev); + StrongARMUARTState *s = STRONGARM_UART(obj); + SysBusDevice *dev = SYS_BUS_DEVICE(obj); - memory_region_init_io(&s->iomem, OBJECT(s), &strongarm_uart_ops, s, + memory_region_init_io(&s->iomem, obj, &strongarm_uart_ops, s, "uart", 0x10000); sysbus_init_mmio(dev, &s->iomem); sysbus_init_irq(dev, &s->irq); @@ -1250,8 +1243,6 @@ static int strongarm_uart_init(SysBusDevice *dev) strongarm_uart_event, s); } - - return 0; } static void strongarm_uart_reset(DeviceState *dev) @@ -1321,9 +1312,7 @@ static Property strongarm_uart_properties[] = { static void strongarm_uart_class_init(ObjectClass *klass, void *data) { DeviceClass *dc = DEVICE_CLASS(klass); - SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass); - k->init = strongarm_uart_init; dc->desc = "StrongARM UART controller"; dc->reset = strongarm_uart_reset; dc->vmsd = &vmstate_strongarm_uart_regs; @@ -1334,6 +1323,7 @@ static const TypeInfo strongarm_uart_info = { .name = TYPE_STRONGARM_UART, .parent = TYPE_SYS_BUS_DEVICE, .instance_size = sizeof(StrongARMUARTState), + .instance_init = strongarm_uart_init, .class_init = strongarm_uart_class_init, }; From 0bc91ab3bb70f836d5a7a3ef6f800ef8c22e936f Mon Sep 17 00:00:00 2001 From: "xiaoqiang.zhao" Date: Mon, 7 Mar 2016 15:05:50 +0800 Subject: [PATCH 43/43] hw/arm: QOM'ify versatilepb.c Drop the use of old SysBus init function and use instance_init Signed-off-by: xiaoqiang zhao Reviewed-by: Peter Maydell Signed-off-by: Peter Maydell --- hw/arm/versatilepb.c | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/hw/arm/versatilepb.c b/hw/arm/versatilepb.c index e5a80c2d2c..d079bc9e82 100644 --- a/hw/arm/versatilepb.c +++ b/hw/arm/versatilepb.c @@ -153,10 +153,11 @@ static const MemoryRegionOps vpb_sic_ops = { .endianness = DEVICE_NATIVE_ENDIAN, }; -static int vpb_sic_init(SysBusDevice *sbd) +static void vpb_sic_init(Object *obj) { - DeviceState *dev = DEVICE(sbd); - vpb_sic_state *s = VERSATILE_PB_SIC(dev); + DeviceState *dev = DEVICE(obj); + vpb_sic_state *s = VERSATILE_PB_SIC(obj); + SysBusDevice *sbd = SYS_BUS_DEVICE(obj); int i; qdev_init_gpio_in(dev, vpb_sic_set_irq, 32); @@ -164,10 +165,9 @@ static int vpb_sic_init(SysBusDevice *sbd) sysbus_init_irq(sbd, &s->parent[i]); } s->irq = 31; - memory_region_init_io(&s->iomem, OBJECT(s), &vpb_sic_ops, s, + memory_region_init_io(&s->iomem, obj, &vpb_sic_ops, s, "vpb-sic", 0x1000); sysbus_init_mmio(sbd, &s->iomem); - return 0; } /* Board init. */ @@ -427,9 +427,7 @@ type_init(versatile_machine_init) static void vpb_sic_class_init(ObjectClass *klass, void *data) { DeviceClass *dc = DEVICE_CLASS(klass); - SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass); - k->init = vpb_sic_init; dc->vmsd = &vmstate_vpb_sic; } @@ -437,6 +435,7 @@ static const TypeInfo vpb_sic_info = { .name = TYPE_VERSATILE_PB_SIC, .parent = TYPE_SYS_BUS_DEVICE, .instance_size = sizeof(vpb_sic_state), + .instance_init = vpb_sic_init, .class_init = vpb_sic_class_init, };