target-arm:
* target-arm: kvm: use AddressSpace-specific listener * aspeed: add SMC controllers * hw/arm/boot: allow using a command line specified dtb without a kernel * hw/dma/pl080: Fix bad bit mask * hw/intc/arm_gic_kvm: Fix build on aarch64 with some compilers * hw/arm/virt: fix ACPI tables for ITS * tests: add a m25p80 test * tests: cleanup ptimer-test * pxa2xx: Auto-assign name for i2c bus in i2c_init_bus * target-arm: handle tagged addresses in A64 code * target-arm: Fix masking of PC lower bits when doing exception returns * target-arm: Implement dummy MDCCINT_EL1 * target-arm: Add trace events for the generic timers * hw/intc/arm_gicv3: Fix ICC register tracepoints * hw/char/pl011: Add trace events -----BEGIN PGP SIGNATURE----- Version: GnuPG v1 iQIcBAABCAAGBQJYBRruAAoJEDwlJe0UNgzeMw4P/0+3OG+APNCAp9AWNzlR23T6 sjDnk4R3thtHECpsu606Hl1F2tYYxXJiBf6gJbZb2TK8iaqTvJ6WB/i1FqcFrrtw RXUsWDlrezTcEmzs4oW7FYK4bmqUrjHM6LrWgZm5IdxZ3QSwCwuZhHlHfl0ZRPDd qomaF+k2fTSNVV3zxUy5J2jdLhhaM+6Hfi4IIafQV9RDahBOGJfzRxqwL7u3Cbys 3KY7ayKJrnzH8z4HNVmrYO9WM5c+M+5EiHV92ieoDrD2P85vFXdodvWsdYr/HyLb 7g+bLR/4LaSNfgNqGO/zzzxeF7JcipqHRfjPzEJMVnxF/vOusSY/8YYE3ODwf38k 8xbp1WO3rpNFdn3Dt5zsNOqClBxfgTUiQLw3PnaN3HfmhvaShWGBO9d7sN+kBKkw lIV5rc69D74chbdmG7TLRouPHduYmHnAYer6bio9MfIfBj6Vf+ZypKNHwKjnf+3s dVP5GjNZO1doUn9NUKrKfG1jElkEJBnt+u8mN+pEn2SxA+Qya6pYS263PHa7l8Uc E0qN7YN3vaeSxO3tE/vDcvDFGNpwLOM5iW5ljKsf/khbCivElfvmkCEzSgrh514Y tc/MczeWxewxKNnCy3Q3l1JC1eAQuKNjQV+u2bVjfBfVucX3c8n+OOMUNdlImR/T R7t2hbXn+GAkE2oXAUrz =L99V -----END PGP SIGNATURE----- Merge remote-tracking branch 'remotes/pmaydell/tags/pull-target-arm-20161017' into staging target-arm: * target-arm: kvm: use AddressSpace-specific listener * aspeed: add SMC controllers * hw/arm/boot: allow using a command line specified dtb without a kernel * hw/dma/pl080: Fix bad bit mask * hw/intc/arm_gic_kvm: Fix build on aarch64 with some compilers * hw/arm/virt: fix ACPI tables for ITS * tests: add a m25p80 test * tests: cleanup ptimer-test * pxa2xx: Auto-assign name for i2c bus in i2c_init_bus * target-arm: handle tagged addresses in A64 code * target-arm: Fix masking of PC lower bits when doing exception returns * target-arm: Implement dummy MDCCINT_EL1 * target-arm: Add trace events for the generic timers * hw/intc/arm_gicv3: Fix ICC register tracepoints * hw/char/pl011: Add trace events # gpg: Signature made Mon 17 Oct 2016 19:39:42 BST # gpg: using RSA key 0x3C2525ED14360CDE # gpg: Good signature from "Peter Maydell <peter.maydell@linaro.org>" # gpg: aka "Peter Maydell <pmaydell@gmail.com>" # gpg: aka "Peter Maydell <pmaydell@chiark.greenend.org.uk>" # Primary key fingerprint: E1A5 C593 CD41 9DE2 8E83 15CF 3C25 25ED 1436 0CDE * remotes/pmaydell/tags/pull-target-arm-20161017: (25 commits) hw/char/pl011: Add trace events hw/intc/arm_gicv3: Fix ICC register tracepoints target-arm: Add trace events for the generic timers target-arm: Implement dummy MDCCINT_EL1 Fix masking of PC lower bits when doing exception returns target-arm: Comments added to identify cases in a switch target-arm: Code changes to implement overwrite of tag field on PC load target-arm: Infrastucture changes to enable handling of tagged address loading into PC pxa2xx: Auto-assign name for i2c bus in i2c_init_bus. tests: cleanup ptimer-test tests: add a m25p80 test hw/arm/virt: no ITS on older machine types hw/arm/virt-acpi-build: fix MADT generation hw/intc/arm_gic_kvm: Fix build on aarch64 hw/dma/pl080: Fix bad bit mask (PL080_CONF_M1 | PL080_CONF_M1) hw/arm/boot: allow using a command line specified dtb without a kernel aspeed: add support for the SMC segment registers aspeed: create mapping regions for the maximum number of slaves aspeed: add support for the AST2500 SoC SMC controllers aspeed: extend the number of host SPI controllers ... Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
		
						commit
						2d02ac10b6
					
				@ -155,6 +155,7 @@ trace-events-y += hw/alpha/trace-events
 | 
				
			|||||||
trace-events-y += ui/trace-events
 | 
					trace-events-y += ui/trace-events
 | 
				
			||||||
trace-events-y += audio/trace-events
 | 
					trace-events-y += audio/trace-events
 | 
				
			||||||
trace-events-y += net/trace-events
 | 
					trace-events-y += net/trace-events
 | 
				
			||||||
 | 
					trace-events-y += target-arm/trace-events
 | 
				
			||||||
trace-events-y += target-i386/trace-events
 | 
					trace-events-y += target-i386/trace-events
 | 
				
			||||||
trace-events-y += target-sparc/trace-events
 | 
					trace-events-y += target-sparc/trace-events
 | 
				
			||||||
trace-events-y += target-s390x/trace-events
 | 
					trace-events-y += target-s390x/trace-events
 | 
				
			||||||
 | 
				
			|||||||
@ -8,7 +8,7 @@ The 'loader' device allows the user to load multiple images or values into
 | 
				
			|||||||
QEMU at startup.
 | 
					QEMU at startup.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Loading Data into Memory Values
 | 
					Loading Data into Memory Values
 | 
				
			||||||
---------------------
 | 
					-------------------------------
 | 
				
			||||||
The loader device allows memory values to be set from the command line. This
 | 
					The loader device allows memory values to be set from the command line. This
 | 
				
			||||||
can be done by following the syntax below:
 | 
					can be done by following the syntax below:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -36,7 +36,7 @@ An example of loading value 0x8000000e to address 0xfd1a0104 is:
 | 
				
			|||||||
    -device loader,addr=0xfd1a0104,data=0x8000000e,data-len=4
 | 
					    -device loader,addr=0xfd1a0104,data=0x8000000e,data-len=4
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Setting a CPU's Program Counter
 | 
					Setting a CPU's Program Counter
 | 
				
			||||||
---------------------
 | 
					-------------------------------
 | 
				
			||||||
The loader device allows the CPU's PC to be set from the command line. This
 | 
					The loader device allows the CPU's PC to be set from the command line. This
 | 
				
			||||||
can be done by following the syntax below:
 | 
					can be done by following the syntax below:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -55,9 +55,10 @@ An example of setting CPU 0's PC to 0x8000 is:
 | 
				
			|||||||
    -device loader,addr=0x8000,cpu-num=0
 | 
					    -device loader,addr=0x8000,cpu-num=0
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Loading Files
 | 
					Loading Files
 | 
				
			||||||
---------------------
 | 
					-------------
 | 
				
			||||||
The loader device also allows files to be loaded into memory. This can be done
 | 
					The loader device also allows files to be loaded into memory. It can load raw
 | 
				
			||||||
similarly to setting memory values. The syntax is shown below:
 | 
					files and ELF executable files.  Raw files are loaded verbatim.  ELF executable
 | 
				
			||||||
 | 
					files are loaded by an ELF loader.  The syntax is shown below:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    -device loader,file=<file>[,addr=<addr>][,cpu-num=<cpu-num>][,force-raw=<raw>]
 | 
					    -device loader,file=<file>[,addr=<addr>][,cpu-num=<cpu-num>][,force-raw=<raw>]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -72,8 +73,8 @@ similarly to setting memory values. The syntax is shown below:
 | 
				
			|||||||
                  for the boot image.
 | 
					                  for the boot image.
 | 
				
			||||||
                  This will also cause the image to be written to the specified
 | 
					                  This will also cause the image to be written to the specified
 | 
				
			||||||
                  CPU's address space. If not specified, the default is CPU 0.
 | 
					                  CPU's address space. If not specified, the default is CPU 0.
 | 
				
			||||||
    <force-raw> - Forces the file to be treated as a raw image. This can be
 | 
					    <force-raw> - Setting force-raw=on forces the file to be treated as a raw
 | 
				
			||||||
                  used to specify the load address of ELF files.
 | 
					                  image.  This can be used to load ELF files as if they were raw.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
All values are parsed using the standard QemuOps parsing. This allows the user
 | 
					All values are parsed using the standard QemuOps parsing. This allows the user
 | 
				
			||||||
to specify any values in any format supported. By default the values
 | 
					to specify any values in any format supported. By default the values
 | 
				
			||||||
@ -82,3 +83,10 @@ with a '0x'.
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
An example of loading an ELF file which CPU0 will boot is shown below:
 | 
					An example of loading an ELF file which CPU0 will boot is shown below:
 | 
				
			||||||
    -device loader,file=./images/boot.elf,cpu-num=0
 | 
					    -device loader,file=./images/boot.elf,cpu-num=0
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Restrictions and ToDos
 | 
				
			||||||
 | 
					----------------------
 | 
				
			||||||
 | 
					 - At the moment it is just assumed that if you specify a cpu-num then you
 | 
				
			||||||
 | 
					   want to set the PC as well. This might not always be the case. In future
 | 
				
			||||||
 | 
					   the internal state 'set_pc' (which exists in the generic loader now) should
 | 
				
			||||||
 | 
					   be exposed to the user so that they can choose if the PC is set or not.
 | 
				
			||||||
 | 
				
			|||||||
@ -128,8 +128,8 @@ static void aspeed_board_init(MachineState *machine,
 | 
				
			|||||||
    object_property_add_const_link(OBJECT(&bmc->soc), "ram", OBJECT(&bmc->ram),
 | 
					    object_property_add_const_link(OBJECT(&bmc->soc), "ram", OBJECT(&bmc->ram),
 | 
				
			||||||
                                   &error_abort);
 | 
					                                   &error_abort);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    aspeed_board_init_flashes(&bmc->soc.smc, "n25q256a", &error_abort);
 | 
					    aspeed_board_init_flashes(&bmc->soc.fmc, "n25q256a", &error_abort);
 | 
				
			||||||
    aspeed_board_init_flashes(&bmc->soc.spi, "mx25l25635e", &error_abort);
 | 
					    aspeed_board_init_flashes(&bmc->soc.spi[0], "mx25l25635e", &error_abort);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    aspeed_board_binfo.kernel_filename = machine->kernel_filename;
 | 
					    aspeed_board_binfo.kernel_filename = machine->kernel_filename;
 | 
				
			||||||
    aspeed_board_binfo.initrd_filename = machine->initrd_filename;
 | 
					    aspeed_board_binfo.initrd_filename = machine->initrd_filename;
 | 
				
			||||||
 | 
				
			|||||||
@ -25,25 +25,37 @@
 | 
				
			|||||||
#define ASPEED_SOC_IOMEM_BASE       0x1E600000
 | 
					#define ASPEED_SOC_IOMEM_BASE       0x1E600000
 | 
				
			||||||
#define ASPEED_SOC_FMC_BASE         0x1E620000
 | 
					#define ASPEED_SOC_FMC_BASE         0x1E620000
 | 
				
			||||||
#define ASPEED_SOC_SPI_BASE         0x1E630000
 | 
					#define ASPEED_SOC_SPI_BASE         0x1E630000
 | 
				
			||||||
 | 
					#define ASPEED_SOC_SPI2_BASE        0x1E631000
 | 
				
			||||||
#define ASPEED_SOC_VIC_BASE         0x1E6C0000
 | 
					#define ASPEED_SOC_VIC_BASE         0x1E6C0000
 | 
				
			||||||
#define ASPEED_SOC_SDMC_BASE        0x1E6E0000
 | 
					#define ASPEED_SOC_SDMC_BASE        0x1E6E0000
 | 
				
			||||||
#define ASPEED_SOC_SCU_BASE         0x1E6E2000
 | 
					#define ASPEED_SOC_SCU_BASE         0x1E6E2000
 | 
				
			||||||
#define ASPEED_SOC_TIMER_BASE       0x1E782000
 | 
					#define ASPEED_SOC_TIMER_BASE       0x1E782000
 | 
				
			||||||
#define ASPEED_SOC_I2C_BASE         0x1E78A000
 | 
					#define ASPEED_SOC_I2C_BASE         0x1E78A000
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define ASPEED_SOC_FMC_FLASH_BASE   0x20000000
 | 
					 | 
				
			||||||
#define ASPEED_SOC_SPI_FLASH_BASE   0x30000000
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static const int uart_irqs[] = { 9, 32, 33, 34, 10 };
 | 
					static const int uart_irqs[] = { 9, 32, 33, 34, 10 };
 | 
				
			||||||
static const int timer_irqs[] = { 16, 17, 18, 35, 36, 37, 38, 39, };
 | 
					static const int timer_irqs[] = { 16, 17, 18, 35, 36, 37, 38, 39, };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define AST2400_SDRAM_BASE       0x40000000
 | 
					#define AST2400_SDRAM_BASE       0x40000000
 | 
				
			||||||
#define AST2500_SDRAM_BASE       0x80000000
 | 
					#define AST2500_SDRAM_BASE       0x80000000
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static const hwaddr aspeed_soc_ast2400_spi_bases[] = { ASPEED_SOC_SPI_BASE };
 | 
				
			||||||
 | 
					static const char *aspeed_soc_ast2400_typenames[] = { "aspeed.smc.spi" };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static const hwaddr aspeed_soc_ast2500_spi_bases[] = { ASPEED_SOC_SPI_BASE,
 | 
				
			||||||
 | 
					                                                       ASPEED_SOC_SPI2_BASE};
 | 
				
			||||||
 | 
					static const char *aspeed_soc_ast2500_typenames[] = {
 | 
				
			||||||
 | 
					    "aspeed.smc.ast2500-spi1", "aspeed.smc.ast2500-spi2" };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static const AspeedSoCInfo aspeed_socs[] = {
 | 
					static const AspeedSoCInfo aspeed_socs[] = {
 | 
				
			||||||
    { "ast2400-a0", "arm926", AST2400_A0_SILICON_REV, AST2400_SDRAM_BASE },
 | 
					    { "ast2400-a0", "arm926", AST2400_A0_SILICON_REV, AST2400_SDRAM_BASE,
 | 
				
			||||||
    { "ast2400",    "arm926", AST2400_A0_SILICON_REV, AST2400_SDRAM_BASE },
 | 
					      1, aspeed_soc_ast2400_spi_bases,
 | 
				
			||||||
    { "ast2500-a1", "arm1176", AST2500_A1_SILICON_REV, AST2500_SDRAM_BASE },
 | 
					      "aspeed.smc.fmc", aspeed_soc_ast2400_typenames },
 | 
				
			||||||
 | 
					    { "ast2400",    "arm926", AST2400_A0_SILICON_REV, AST2400_SDRAM_BASE,
 | 
				
			||||||
 | 
					      1, aspeed_soc_ast2400_spi_bases,
 | 
				
			||||||
 | 
					     "aspeed.smc.fmc", aspeed_soc_ast2400_typenames },
 | 
				
			||||||
 | 
					    { "ast2500-a1", "arm1176", AST2500_A1_SILICON_REV, AST2500_SDRAM_BASE,
 | 
				
			||||||
 | 
					      2, aspeed_soc_ast2500_spi_bases,
 | 
				
			||||||
 | 
					      "aspeed.smc.ast2500-fmc", aspeed_soc_ast2500_typenames },
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/*
 | 
					/*
 | 
				
			||||||
@ -75,6 +87,7 @@ static void aspeed_soc_init(Object *obj)
 | 
				
			|||||||
{
 | 
					{
 | 
				
			||||||
    AspeedSoCState *s = ASPEED_SOC(obj);
 | 
					    AspeedSoCState *s = ASPEED_SOC(obj);
 | 
				
			||||||
    AspeedSoCClass *sc = ASPEED_SOC_GET_CLASS(s);
 | 
					    AspeedSoCClass *sc = ASPEED_SOC_GET_CLASS(s);
 | 
				
			||||||
 | 
					    int i;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    s->cpu = cpu_arm_init(sc->info->cpu_model);
 | 
					    s->cpu = cpu_arm_init(sc->info->cpu_model);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -100,13 +113,16 @@ static void aspeed_soc_init(Object *obj)
 | 
				
			|||||||
    object_property_add_alias(obj, "hw-strap2", OBJECT(&s->scu),
 | 
					    object_property_add_alias(obj, "hw-strap2", OBJECT(&s->scu),
 | 
				
			||||||
                              "hw-strap2", &error_abort);
 | 
					                              "hw-strap2", &error_abort);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    object_initialize(&s->smc, sizeof(s->smc), "aspeed.smc.fmc");
 | 
					    object_initialize(&s->fmc, sizeof(s->fmc), sc->info->fmc_typename);
 | 
				
			||||||
    object_property_add_child(obj, "smc", OBJECT(&s->smc), NULL);
 | 
					    object_property_add_child(obj, "fmc", OBJECT(&s->fmc), NULL);
 | 
				
			||||||
    qdev_set_parent_bus(DEVICE(&s->smc), sysbus_get_default());
 | 
					    qdev_set_parent_bus(DEVICE(&s->fmc), sysbus_get_default());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    object_initialize(&s->spi, sizeof(s->spi), "aspeed.smc.spi");
 | 
					    for (i = 0; i < sc->info->spis_num; i++) {
 | 
				
			||||||
    object_property_add_child(obj, "spi", OBJECT(&s->spi), NULL);
 | 
					        object_initialize(&s->spi[i], sizeof(s->spi[i]),
 | 
				
			||||||
    qdev_set_parent_bus(DEVICE(&s->spi), sysbus_get_default());
 | 
					                          sc->info->spi_typename[i]);
 | 
				
			||||||
 | 
					        object_property_add_child(obj, "spi", OBJECT(&s->spi[i]), NULL);
 | 
				
			||||||
 | 
					        qdev_set_parent_bus(DEVICE(&s->spi[i]), sysbus_get_default());
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    object_initialize(&s->sdmc, sizeof(s->sdmc), TYPE_ASPEED_SDMC);
 | 
					    object_initialize(&s->sdmc, sizeof(s->sdmc), TYPE_ASPEED_SDMC);
 | 
				
			||||||
    object_property_add_child(obj, "sdmc", OBJECT(&s->sdmc), NULL);
 | 
					    object_property_add_child(obj, "sdmc", OBJECT(&s->sdmc), NULL);
 | 
				
			||||||
@ -121,6 +137,7 @@ static void aspeed_soc_realize(DeviceState *dev, Error **errp)
 | 
				
			|||||||
{
 | 
					{
 | 
				
			||||||
    int i;
 | 
					    int i;
 | 
				
			||||||
    AspeedSoCState *s = ASPEED_SOC(dev);
 | 
					    AspeedSoCState *s = ASPEED_SOC(dev);
 | 
				
			||||||
 | 
					    AspeedSoCClass *sc = ASPEED_SOC_GET_CLASS(s);
 | 
				
			||||||
    Error *err = NULL, *local_err = NULL;
 | 
					    Error *err = NULL, *local_err = NULL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /* IO space */
 | 
					    /* IO space */
 | 
				
			||||||
@ -178,29 +195,34 @@ static void aspeed_soc_realize(DeviceState *dev, Error **errp)
 | 
				
			|||||||
    sysbus_connect_irq(SYS_BUS_DEVICE(&s->i2c), 0,
 | 
					    sysbus_connect_irq(SYS_BUS_DEVICE(&s->i2c), 0,
 | 
				
			||||||
                       qdev_get_gpio_in(DEVICE(&s->vic), 12));
 | 
					                       qdev_get_gpio_in(DEVICE(&s->vic), 12));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /* SMC */
 | 
					    /* FMC */
 | 
				
			||||||
    object_property_set_int(OBJECT(&s->smc), 1, "num-cs", &err);
 | 
					    object_property_set_int(OBJECT(&s->fmc), 1, "num-cs", &err);
 | 
				
			||||||
    object_property_set_bool(OBJECT(&s->smc), true, "realized", &local_err);
 | 
					    object_property_set_bool(OBJECT(&s->fmc), true, "realized", &local_err);
 | 
				
			||||||
    error_propagate(&err, local_err);
 | 
					    error_propagate(&err, local_err);
 | 
				
			||||||
    if (err) {
 | 
					    if (err) {
 | 
				
			||||||
        error_propagate(errp, err);
 | 
					        error_propagate(errp, err);
 | 
				
			||||||
        return;
 | 
					        return;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    sysbus_mmio_map(SYS_BUS_DEVICE(&s->smc), 0, ASPEED_SOC_FMC_BASE);
 | 
					    sysbus_mmio_map(SYS_BUS_DEVICE(&s->fmc), 0, ASPEED_SOC_FMC_BASE);
 | 
				
			||||||
    sysbus_mmio_map(SYS_BUS_DEVICE(&s->smc), 1, ASPEED_SOC_FMC_FLASH_BASE);
 | 
					    sysbus_mmio_map(SYS_BUS_DEVICE(&s->fmc), 1,
 | 
				
			||||||
    sysbus_connect_irq(SYS_BUS_DEVICE(&s->smc), 0,
 | 
					                    s->fmc.ctrl->flash_window_base);
 | 
				
			||||||
 | 
					    sysbus_connect_irq(SYS_BUS_DEVICE(&s->fmc), 0,
 | 
				
			||||||
                       qdev_get_gpio_in(DEVICE(&s->vic), 19));
 | 
					                       qdev_get_gpio_in(DEVICE(&s->vic), 19));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /* SPI */
 | 
					    /* SPI */
 | 
				
			||||||
    object_property_set_int(OBJECT(&s->spi), 1, "num-cs", &err);
 | 
					    for (i = 0; i < sc->info->spis_num; i++) {
 | 
				
			||||||
    object_property_set_bool(OBJECT(&s->spi), true, "realized", &local_err);
 | 
					        object_property_set_int(OBJECT(&s->spi[i]), 1, "num-cs", &err);
 | 
				
			||||||
 | 
					        object_property_set_bool(OBJECT(&s->spi[i]), true, "realized",
 | 
				
			||||||
 | 
					                                 &local_err);
 | 
				
			||||||
        error_propagate(&err, local_err);
 | 
					        error_propagate(&err, local_err);
 | 
				
			||||||
        if (err) {
 | 
					        if (err) {
 | 
				
			||||||
            error_propagate(errp, err);
 | 
					            error_propagate(errp, err);
 | 
				
			||||||
            return;
 | 
					            return;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    sysbus_mmio_map(SYS_BUS_DEVICE(&s->spi), 0, ASPEED_SOC_SPI_BASE);
 | 
					        sysbus_mmio_map(SYS_BUS_DEVICE(&s->spi[i]), 0, sc->info->spi_bases[i]);
 | 
				
			||||||
    sysbus_mmio_map(SYS_BUS_DEVICE(&s->spi), 1, ASPEED_SOC_SPI_FLASH_BASE);
 | 
					        sysbus_mmio_map(SYS_BUS_DEVICE(&s->spi[i]), 1,
 | 
				
			||||||
 | 
					                        s->spi[i].ctrl->flash_window_base);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /* SDMC - SDRAM Memory Controller */
 | 
					    /* SDMC - SDRAM Memory Controller */
 | 
				
			||||||
    object_property_set_bool(OBJECT(&s->sdmc), true, "realized", &err);
 | 
					    object_property_set_bool(OBJECT(&s->sdmc), true, "realized", &err);
 | 
				
			||||||
 | 
				
			|||||||
@ -773,6 +773,8 @@ static void arm_load_kernel_notify(Notifier *notifier, void *data)
 | 
				
			|||||||
     */
 | 
					     */
 | 
				
			||||||
    assert(!(info->secure_board_setup && kvm_enabled()));
 | 
					    assert(!(info->secure_board_setup && kvm_enabled()));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    info->dtb_filename = qemu_opt_get(qemu_get_machine_opts(), "dtb");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /* Load the kernel.  */
 | 
					    /* Load the kernel.  */
 | 
				
			||||||
    if (!info->kernel_filename || info->firmware_loaded) {
 | 
					    if (!info->kernel_filename || info->firmware_loaded) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -833,8 +835,6 @@ static void arm_load_kernel_notify(Notifier *notifier, void *data)
 | 
				
			|||||||
        elf_machine = EM_ARM;
 | 
					        elf_machine = EM_ARM;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    info->dtb_filename = qemu_opt_get(qemu_get_machine_opts(), "dtb");
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    if (!info->secondary_cpu_reset_hook) {
 | 
					    if (!info->secondary_cpu_reset_hook) {
 | 
				
			||||||
        info->secondary_cpu_reset_hook = default_reset_secondary;
 | 
					        info->secondary_cpu_reset_hook = default_reset_secondary;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
				
			|||||||
@ -1505,7 +1505,7 @@ static void pxa2xx_i2c_initfn(Object *obj)
 | 
				
			|||||||
    PXA2xxI2CState *s = PXA2XX_I2C(obj);
 | 
					    PXA2xxI2CState *s = PXA2XX_I2C(obj);
 | 
				
			||||||
    SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
 | 
					    SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    s->bus = i2c_init_bus(dev, "i2c");
 | 
					    s->bus = i2c_init_bus(dev, NULL);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    memory_region_init_io(&s->iomem, obj, &pxa2xx_i2c_ops, s,
 | 
					    memory_region_init_io(&s->iomem, obj, &pxa2xx_i2c_ops, s,
 | 
				
			||||||
                          "pxa2xx-i2c", s->region_size);
 | 
					                          "pxa2xx-i2c", s->region_size);
 | 
				
			||||||
 | 
				
			|||||||
@ -554,15 +554,13 @@ build_madt(GArray *table_data, BIOSLinker *linker, VirtGuestInfo *guest_info)
 | 
				
			|||||||
        gicr->base_address = cpu_to_le64(memmap[VIRT_GIC_REDIST].base);
 | 
					        gicr->base_address = cpu_to_le64(memmap[VIRT_GIC_REDIST].base);
 | 
				
			||||||
        gicr->range_length = cpu_to_le32(memmap[VIRT_GIC_REDIST].size);
 | 
					        gicr->range_length = cpu_to_le32(memmap[VIRT_GIC_REDIST].size);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if (!its_class_name()) {
 | 
					        if (its_class_name() && !guest_info->no_its) {
 | 
				
			||||||
            return;
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            gic_its = acpi_data_push(table_data, sizeof *gic_its);
 | 
					            gic_its = acpi_data_push(table_data, sizeof *gic_its);
 | 
				
			||||||
            gic_its->type = ACPI_APIC_GENERIC_TRANSLATOR;
 | 
					            gic_its->type = ACPI_APIC_GENERIC_TRANSLATOR;
 | 
				
			||||||
            gic_its->length = sizeof(*gic_its);
 | 
					            gic_its->length = sizeof(*gic_its);
 | 
				
			||||||
            gic_its->translation_id = 0;
 | 
					            gic_its->translation_id = 0;
 | 
				
			||||||
            gic_its->base_address = cpu_to_le64(memmap[VIRT_GIC_ITS].base);
 | 
					            gic_its->base_address = cpu_to_le64(memmap[VIRT_GIC_ITS].base);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
    } else {
 | 
					    } else {
 | 
				
			||||||
        gic_msi = acpi_data_push(table_data, sizeof *gic_msi);
 | 
					        gic_msi = acpi_data_push(table_data, sizeof *gic_msi);
 | 
				
			||||||
        gic_msi->type = ACPI_APIC_GENERIC_MSI_FRAME;
 | 
					        gic_msi->type = ACPI_APIC_GENERIC_MSI_FRAME;
 | 
				
			||||||
 | 
				
			|||||||
@ -84,6 +84,7 @@ typedef struct {
 | 
				
			|||||||
    MachineClass parent;
 | 
					    MachineClass parent;
 | 
				
			||||||
    VirtBoardInfo *daughterboard;
 | 
					    VirtBoardInfo *daughterboard;
 | 
				
			||||||
    bool disallow_affinity_adjustment;
 | 
					    bool disallow_affinity_adjustment;
 | 
				
			||||||
 | 
					    bool no_its;
 | 
				
			||||||
} VirtMachineClass;
 | 
					} VirtMachineClass;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
typedef struct {
 | 
					typedef struct {
 | 
				
			||||||
@ -551,7 +552,8 @@ static void create_v2m(VirtBoardInfo *vbi, qemu_irq *pic)
 | 
				
			|||||||
    fdt_add_v2m_gic_node(vbi);
 | 
					    fdt_add_v2m_gic_node(vbi);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void create_gic(VirtBoardInfo *vbi, qemu_irq *pic, int type, bool secure)
 | 
					static void create_gic(VirtBoardInfo *vbi, qemu_irq *pic, int type,
 | 
				
			||||||
 | 
					                       bool secure, bool no_its)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    /* We create a standalone GIC */
 | 
					    /* We create a standalone GIC */
 | 
				
			||||||
    DeviceState *gicdev;
 | 
					    DeviceState *gicdev;
 | 
				
			||||||
@ -615,9 +617,9 @@ static void create_gic(VirtBoardInfo *vbi, qemu_irq *pic, int type, bool secure)
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    fdt_add_gic_node(vbi, type);
 | 
					    fdt_add_gic_node(vbi, type);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (type == 3) {
 | 
					    if (type == 3 && !no_its) {
 | 
				
			||||||
        create_its(vbi, gicdev);
 | 
					        create_its(vbi, gicdev);
 | 
				
			||||||
    } else {
 | 
					    } else if (type == 2) {
 | 
				
			||||||
        create_v2m(vbi, pic);
 | 
					        create_v2m(vbi, pic);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@ -1375,7 +1377,7 @@ static void machvirt_init(MachineState *machine)
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    create_flash(vbi, sysmem, secure_sysmem ? secure_sysmem : sysmem);
 | 
					    create_flash(vbi, sysmem, secure_sysmem ? secure_sysmem : sysmem);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    create_gic(vbi, pic, gic_version, vms->secure);
 | 
					    create_gic(vbi, pic, gic_version, vms->secure, vmc->no_its);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    fdt_add_pmu_nodes(vbi, gic_version);
 | 
					    fdt_add_pmu_nodes(vbi, gic_version);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -1407,6 +1409,7 @@ static void machvirt_init(MachineState *machine)
 | 
				
			|||||||
    guest_info->irqmap = vbi->irqmap;
 | 
					    guest_info->irqmap = vbi->irqmap;
 | 
				
			||||||
    guest_info->use_highmem = vms->highmem;
 | 
					    guest_info->use_highmem = vms->highmem;
 | 
				
			||||||
    guest_info->gic_version = gic_version;
 | 
					    guest_info->gic_version = gic_version;
 | 
				
			||||||
 | 
					    guest_info->no_its = vmc->no_its;
 | 
				
			||||||
    guest_info_state->machine_done.notify = virt_guest_info_machine_done;
 | 
					    guest_info_state->machine_done.notify = virt_guest_info_machine_done;
 | 
				
			||||||
    qemu_add_machine_init_done_notifier(&guest_info_state->machine_done);
 | 
					    qemu_add_machine_init_done_notifier(&guest_info_state->machine_done);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -1561,8 +1564,12 @@ static void virt_2_7_instance_init(Object *obj)
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
static void virt_machine_2_7_options(MachineClass *mc)
 | 
					static void virt_machine_2_7_options(MachineClass *mc)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
 | 
					    VirtMachineClass *vmc = VIRT_MACHINE_CLASS(OBJECT_CLASS(mc));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    virt_machine_2_8_options(mc);
 | 
					    virt_machine_2_8_options(mc);
 | 
				
			||||||
    SET_MACHINE_COMPAT(mc, VIRT_COMPAT_2_7);
 | 
					    SET_MACHINE_COMPAT(mc, VIRT_COMPAT_2_7);
 | 
				
			||||||
 | 
					    /* ITS was introduced with 2.8 */
 | 
				
			||||||
 | 
					    vmc->no_its = true;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
DEFINE_VIRT_MACHINE(2, 7)
 | 
					DEFINE_VIRT_MACHINE(2, 7)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -11,6 +11,7 @@
 | 
				
			|||||||
#include "hw/sysbus.h"
 | 
					#include "hw/sysbus.h"
 | 
				
			||||||
#include "sysemu/char.h"
 | 
					#include "sysemu/char.h"
 | 
				
			||||||
#include "qemu/log.h"
 | 
					#include "qemu/log.h"
 | 
				
			||||||
 | 
					#include "trace.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define TYPE_PL011 "pl011"
 | 
					#define TYPE_PL011 "pl011"
 | 
				
			||||||
#define PL011(obj) OBJECT_CHECK(PL011State, (obj), TYPE_PL011)
 | 
					#define PL011(obj) OBJECT_CHECK(PL011State, (obj), TYPE_PL011)
 | 
				
			||||||
@ -58,6 +59,7 @@ static void pl011_update(PL011State *s)
 | 
				
			|||||||
    uint32_t flags;
 | 
					    uint32_t flags;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    flags = s->int_level & s->int_enabled;
 | 
					    flags = s->int_level & s->int_enabled;
 | 
				
			||||||
 | 
					    trace_pl011_irq_state(flags != 0);
 | 
				
			||||||
    qemu_set_irq(s->irq, flags != 0);
 | 
					    qemu_set_irq(s->irq, flags != 0);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -66,10 +68,8 @@ static uint64_t pl011_read(void *opaque, hwaddr offset,
 | 
				
			|||||||
{
 | 
					{
 | 
				
			||||||
    PL011State *s = (PL011State *)opaque;
 | 
					    PL011State *s = (PL011State *)opaque;
 | 
				
			||||||
    uint32_t c;
 | 
					    uint32_t c;
 | 
				
			||||||
 | 
					    uint64_t r;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (offset >= 0xfe0 && offset < 0x1000) {
 | 
					 | 
				
			||||||
        return s->id[(offset - 0xfe0) >> 2];
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    switch (offset >> 2) {
 | 
					    switch (offset >> 2) {
 | 
				
			||||||
    case 0: /* UARTDR */
 | 
					    case 0: /* UARTDR */
 | 
				
			||||||
        s->flags &= ~PL011_FLAG_RXFF;
 | 
					        s->flags &= ~PL011_FLAG_RXFF;
 | 
				
			||||||
@ -84,41 +84,62 @@ static uint64_t pl011_read(void *opaque, hwaddr offset,
 | 
				
			|||||||
        }
 | 
					        }
 | 
				
			||||||
        if (s->read_count == s->read_trigger - 1)
 | 
					        if (s->read_count == s->read_trigger - 1)
 | 
				
			||||||
            s->int_level &= ~ PL011_INT_RX;
 | 
					            s->int_level &= ~ PL011_INT_RX;
 | 
				
			||||||
 | 
					        trace_pl011_read_fifo(s->read_count);
 | 
				
			||||||
        s->rsr = c >> 8;
 | 
					        s->rsr = c >> 8;
 | 
				
			||||||
        pl011_update(s);
 | 
					        pl011_update(s);
 | 
				
			||||||
        if (s->chr) {
 | 
					        if (s->chr) {
 | 
				
			||||||
            qemu_chr_accept_input(s->chr);
 | 
					            qemu_chr_accept_input(s->chr);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        return c;
 | 
					        r = c;
 | 
				
			||||||
 | 
					        break;
 | 
				
			||||||
    case 1: /* UARTRSR */
 | 
					    case 1: /* UARTRSR */
 | 
				
			||||||
        return s->rsr;
 | 
					        r = s->rsr;
 | 
				
			||||||
 | 
					        break;
 | 
				
			||||||
    case 6: /* UARTFR */
 | 
					    case 6: /* UARTFR */
 | 
				
			||||||
        return s->flags;
 | 
					        r = s->flags;
 | 
				
			||||||
 | 
					        break;
 | 
				
			||||||
    case 8: /* UARTILPR */
 | 
					    case 8: /* UARTILPR */
 | 
				
			||||||
        return s->ilpr;
 | 
					        r = s->ilpr;
 | 
				
			||||||
 | 
					        break;
 | 
				
			||||||
    case 9: /* UARTIBRD */
 | 
					    case 9: /* UARTIBRD */
 | 
				
			||||||
        return s->ibrd;
 | 
					        r = s->ibrd;
 | 
				
			||||||
 | 
					        break;
 | 
				
			||||||
    case 10: /* UARTFBRD */
 | 
					    case 10: /* UARTFBRD */
 | 
				
			||||||
        return s->fbrd;
 | 
					        r = s->fbrd;
 | 
				
			||||||
 | 
					        break;
 | 
				
			||||||
    case 11: /* UARTLCR_H */
 | 
					    case 11: /* UARTLCR_H */
 | 
				
			||||||
        return s->lcr;
 | 
					        r = s->lcr;
 | 
				
			||||||
 | 
					        break;
 | 
				
			||||||
    case 12: /* UARTCR */
 | 
					    case 12: /* UARTCR */
 | 
				
			||||||
        return s->cr;
 | 
					        r = s->cr;
 | 
				
			||||||
 | 
					        break;
 | 
				
			||||||
    case 13: /* UARTIFLS */
 | 
					    case 13: /* UARTIFLS */
 | 
				
			||||||
        return s->ifl;
 | 
					        r = s->ifl;
 | 
				
			||||||
 | 
					        break;
 | 
				
			||||||
    case 14: /* UARTIMSC */
 | 
					    case 14: /* UARTIMSC */
 | 
				
			||||||
        return s->int_enabled;
 | 
					        r = s->int_enabled;
 | 
				
			||||||
 | 
					        break;
 | 
				
			||||||
    case 15: /* UARTRIS */
 | 
					    case 15: /* UARTRIS */
 | 
				
			||||||
        return s->int_level;
 | 
					        r = s->int_level;
 | 
				
			||||||
 | 
					        break;
 | 
				
			||||||
    case 16: /* UARTMIS */
 | 
					    case 16: /* UARTMIS */
 | 
				
			||||||
        return s->int_level & s->int_enabled;
 | 
					        r = s->int_level & s->int_enabled;
 | 
				
			||||||
 | 
					        break;
 | 
				
			||||||
    case 18: /* UARTDMACR */
 | 
					    case 18: /* UARTDMACR */
 | 
				
			||||||
        return s->dmacr;
 | 
					        r = s->dmacr;
 | 
				
			||||||
 | 
					        break;
 | 
				
			||||||
 | 
					    case 0x3f8 ... 0x400:
 | 
				
			||||||
 | 
					        r = s->id[(offset - 0xfe0) >> 2];
 | 
				
			||||||
 | 
					        break;
 | 
				
			||||||
    default:
 | 
					    default:
 | 
				
			||||||
        qemu_log_mask(LOG_GUEST_ERROR,
 | 
					        qemu_log_mask(LOG_GUEST_ERROR,
 | 
				
			||||||
                      "pl011_read: Bad offset %x\n", (int)offset);
 | 
					                      "pl011_read: Bad offset %x\n", (int)offset);
 | 
				
			||||||
        return 0;
 | 
					        r = 0;
 | 
				
			||||||
 | 
					        break;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    trace_pl011_read(offset, r);
 | 
				
			||||||
 | 
					    return r;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void pl011_set_read_trigger(PL011State *s)
 | 
					static void pl011_set_read_trigger(PL011State *s)
 | 
				
			||||||
@ -141,6 +162,8 @@ static void pl011_write(void *opaque, hwaddr offset,
 | 
				
			|||||||
    PL011State *s = (PL011State *)opaque;
 | 
					    PL011State *s = (PL011State *)opaque;
 | 
				
			||||||
    unsigned char ch;
 | 
					    unsigned char ch;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    trace_pl011_write(offset, value);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    switch (offset >> 2) {
 | 
					    switch (offset >> 2) {
 | 
				
			||||||
    case 0: /* UARTDR */
 | 
					    case 0: /* UARTDR */
 | 
				
			||||||
        /* ??? Check if transmitter is enabled.  */
 | 
					        /* ??? Check if transmitter is enabled.  */
 | 
				
			||||||
@ -207,11 +230,15 @@ static void pl011_write(void *opaque, hwaddr offset,
 | 
				
			|||||||
static int pl011_can_receive(void *opaque)
 | 
					static int pl011_can_receive(void *opaque)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    PL011State *s = (PL011State *)opaque;
 | 
					    PL011State *s = (PL011State *)opaque;
 | 
				
			||||||
 | 
					    int r;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (s->lcr & 0x10)
 | 
					    if (s->lcr & 0x10) {
 | 
				
			||||||
        return s->read_count < 16;
 | 
					        r = s->read_count < 16;
 | 
				
			||||||
    else
 | 
					    } else {
 | 
				
			||||||
        return s->read_count < 1;
 | 
					        r = s->read_count < 1;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    trace_pl011_can_receive(s->lcr, s->read_count, r);
 | 
				
			||||||
 | 
					    return r;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void pl011_put_fifo(void *opaque, uint32_t value)
 | 
					static void pl011_put_fifo(void *opaque, uint32_t value)
 | 
				
			||||||
@ -225,7 +252,9 @@ static void pl011_put_fifo(void *opaque, uint32_t value)
 | 
				
			|||||||
    s->read_fifo[slot] = value;
 | 
					    s->read_fifo[slot] = value;
 | 
				
			||||||
    s->read_count++;
 | 
					    s->read_count++;
 | 
				
			||||||
    s->flags &= ~PL011_FLAG_RXFE;
 | 
					    s->flags &= ~PL011_FLAG_RXFE;
 | 
				
			||||||
 | 
					    trace_pl011_put_fifo(value, s->read_count);
 | 
				
			||||||
    if (!(s->lcr & 0x10) || s->read_count == 16) {
 | 
					    if (!(s->lcr & 0x10) || s->read_count == 16) {
 | 
				
			||||||
 | 
					        trace_pl011_put_fifo_full();
 | 
				
			||||||
        s->flags |= PL011_FLAG_RXFF;
 | 
					        s->flags |= PL011_FLAG_RXFF;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    if (s->read_count == s->read_trigger) {
 | 
					    if (s->read_count == s->read_trigger) {
 | 
				
			||||||
 | 
				
			|||||||
@ -47,3 +47,12 @@ escc_sunkbd_event_in(int ch, const char *name, int down) "QKeyCode 0x%2.2x [%s],
 | 
				
			|||||||
escc_sunkbd_event_out(int ch) "Translated keycode 0x%2.2x"
 | 
					escc_sunkbd_event_out(int ch) "Translated keycode 0x%2.2x"
 | 
				
			||||||
escc_kbd_command(int val) "Command %d"
 | 
					escc_kbd_command(int val) "Command %d"
 | 
				
			||||||
escc_sunmouse_event(int dx, int dy, int buttons_state) "dx=%d dy=%d buttons=%01x"
 | 
					escc_sunmouse_event(int dx, int dy, int buttons_state) "dx=%d dy=%d buttons=%01x"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# hw/char/pl011.c
 | 
				
			||||||
 | 
					pl011_irq_state(int level) "irq state %d"
 | 
				
			||||||
 | 
					pl011_read(uint32_t addr, uint32_t value) "addr 0x%08x value 0x%08x"
 | 
				
			||||||
 | 
					pl011_read_fifo(int read_count) "FIFO read, read_count now %d"
 | 
				
			||||||
 | 
					pl011_write(uint32_t addr, uint32_t value) "addr 0x%08x value 0x%08x"
 | 
				
			||||||
 | 
					pl011_can_receive(uint32_t lcr, int read_count, int r) "LCR %08x read_count %d returning %d"
 | 
				
			||||||
 | 
					pl011_put_fifo(uint32_t c, int read_count) "new char 0x%x read_count now %d"
 | 
				
			||||||
 | 
					pl011_put_fifo_full(void) "FIFO now full, RXFF set"
 | 
				
			||||||
 | 
				
			|||||||
@ -351,7 +351,7 @@ static void pl080_write(void *opaque, hwaddr offset,
 | 
				
			|||||||
        break;
 | 
					        break;
 | 
				
			||||||
    case 12: /* Configuration */
 | 
					    case 12: /* Configuration */
 | 
				
			||||||
        s->conf = value;
 | 
					        s->conf = value;
 | 
				
			||||||
        if (s->conf & (PL080_CONF_M1 | PL080_CONF_M1)) {
 | 
					        if (s->conf & (PL080_CONF_M1 | PL080_CONF_M2)) {
 | 
				
			||||||
            qemu_log_mask(LOG_UNIMP,
 | 
					            qemu_log_mask(LOG_UNIMP,
 | 
				
			||||||
                          "pl080_write: Big-endian DMA not implemented\n");
 | 
					                          "pl080_write: Big-endian DMA not implemented\n");
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
				
			|||||||
@ -111,6 +111,7 @@ struct Stream {
 | 
				
			|||||||
    unsigned int complete_cnt;
 | 
					    unsigned int complete_cnt;
 | 
				
			||||||
    uint32_t regs[R_MAX];
 | 
					    uint32_t regs[R_MAX];
 | 
				
			||||||
    uint8_t app[20];
 | 
					    uint8_t app[20];
 | 
				
			||||||
 | 
					    unsigned char txbuf[16 * 1024];
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct XilinxAXIDMAStreamSlave {
 | 
					struct XilinxAXIDMAStreamSlave {
 | 
				
			||||||
@ -256,7 +257,6 @@ static void stream_process_mem2s(struct Stream *s, StreamSlave *tx_data_dev,
 | 
				
			|||||||
                                 StreamSlave *tx_control_dev)
 | 
					                                 StreamSlave *tx_control_dev)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    uint32_t prev_d;
 | 
					    uint32_t prev_d;
 | 
				
			||||||
    unsigned char txbuf[16 * 1024];
 | 
					 | 
				
			||||||
    unsigned int txlen;
 | 
					    unsigned int txlen;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (!stream_running(s) || stream_idle(s)) {
 | 
					    if (!stream_running(s) || stream_idle(s)) {
 | 
				
			||||||
@ -277,17 +277,17 @@ static void stream_process_mem2s(struct Stream *s, StreamSlave *tx_data_dev,
 | 
				
			|||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        txlen = s->desc.control & SDESC_CTRL_LEN_MASK;
 | 
					        txlen = s->desc.control & SDESC_CTRL_LEN_MASK;
 | 
				
			||||||
        if ((txlen + s->pos) > sizeof txbuf) {
 | 
					        if ((txlen + s->pos) > sizeof s->txbuf) {
 | 
				
			||||||
            hw_error("%s: too small internal txbuf! %d\n", __func__,
 | 
					            hw_error("%s: too small internal txbuf! %d\n", __func__,
 | 
				
			||||||
                     txlen + s->pos);
 | 
					                     txlen + s->pos);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        cpu_physical_memory_read(s->desc.buffer_address,
 | 
					        cpu_physical_memory_read(s->desc.buffer_address,
 | 
				
			||||||
                                 txbuf + s->pos, txlen);
 | 
					                                 s->txbuf + s->pos, txlen);
 | 
				
			||||||
        s->pos += txlen;
 | 
					        s->pos += txlen;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if (stream_desc_eof(&s->desc)) {
 | 
					        if (stream_desc_eof(&s->desc)) {
 | 
				
			||||||
            stream_push(tx_data_dev, txbuf, s->pos);
 | 
					            stream_push(tx_data_dev, s->txbuf, s->pos);
 | 
				
			||||||
            s->pos = 0;
 | 
					            s->pos = 0;
 | 
				
			||||||
            stream_complete(s);
 | 
					            stream_complete(s);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
				
			|||||||
@ -30,20 +30,6 @@
 | 
				
			|||||||
#include "gic_internal.h"
 | 
					#include "gic_internal.h"
 | 
				
			||||||
#include "vgic_common.h"
 | 
					#include "vgic_common.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
//#define DEBUG_GIC_KVM
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#ifdef DEBUG_GIC_KVM
 | 
					 | 
				
			||||||
static const int debug_gic_kvm = 1;
 | 
					 | 
				
			||||||
#else
 | 
					 | 
				
			||||||
static const int debug_gic_kvm = 0;
 | 
					 | 
				
			||||||
#endif
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#define DPRINTF(fmt, ...) do { \
 | 
					 | 
				
			||||||
        if (debug_gic_kvm) { \
 | 
					 | 
				
			||||||
            printf("arm_gic: " fmt , ## __VA_ARGS__); \
 | 
					 | 
				
			||||||
        } \
 | 
					 | 
				
			||||||
    } while (0)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#define TYPE_KVM_ARM_GIC "kvm-arm-gic"
 | 
					#define TYPE_KVM_ARM_GIC "kvm-arm-gic"
 | 
				
			||||||
#define KVM_ARM_GIC(obj) \
 | 
					#define KVM_ARM_GIC(obj) \
 | 
				
			||||||
     OBJECT_CHECK(GICState, (obj), TYPE_KVM_ARM_GIC)
 | 
					     OBJECT_CHECK(GICState, (obj), TYPE_KVM_ARM_GIC)
 | 
				
			||||||
 | 
				
			|||||||
@ -454,7 +454,8 @@ static void icc_eoir_write(CPUARMState *env, const ARMCPRegInfo *ri,
 | 
				
			|||||||
    int irq = value & 0xffffff;
 | 
					    int irq = value & 0xffffff;
 | 
				
			||||||
    int grp;
 | 
					    int grp;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    trace_gicv3_icc_eoir_write(gicv3_redist_affid(cs), value);
 | 
					    trace_gicv3_icc_eoir_write(ri->crm == 8 ? 0 : 1,
 | 
				
			||||||
 | 
					                               gicv3_redist_affid(cs), value);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (ri->crm == 8) {
 | 
					    if (ri->crm == 8) {
 | 
				
			||||||
        /* EOIR0 */
 | 
					        /* EOIR0 */
 | 
				
			||||||
@ -542,7 +543,7 @@ static uint64_t icc_bpr_read(CPUARMState *env, const ARMCPRegInfo *ri)
 | 
				
			|||||||
        bpr = MIN(bpr, 7);
 | 
					        bpr = MIN(bpr, 7);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    trace_gicv3_icc_bpr_read(gicv3_redist_affid(cs), bpr);
 | 
					    trace_gicv3_icc_bpr_read(ri->crm == 8 ? 0 : 1, gicv3_redist_affid(cs), bpr);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    return bpr;
 | 
					    return bpr;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@ -553,7 +554,8 @@ static void icc_bpr_write(CPUARMState *env, const ARMCPRegInfo *ri,
 | 
				
			|||||||
    GICv3CPUState *cs = icc_cs_from_env(env);
 | 
					    GICv3CPUState *cs = icc_cs_from_env(env);
 | 
				
			||||||
    int grp = (ri->crm == 8) ? GICV3_G0 : GICV3_G1;
 | 
					    int grp = (ri->crm == 8) ? GICV3_G0 : GICV3_G1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    trace_gicv3_icc_pmr_write(gicv3_redist_affid(cs), value);
 | 
					    trace_gicv3_icc_bpr_write(ri->crm == 8 ? 0 : 1,
 | 
				
			||||||
 | 
					                              gicv3_redist_affid(cs), value);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (grp == GICV3_G1 && gicv3_use_ns_bank(env)) {
 | 
					    if (grp == GICV3_G1 && gicv3_use_ns_bank(env)) {
 | 
				
			||||||
        grp = GICV3_G1NS;
 | 
					        grp = GICV3_G1NS;
 | 
				
			||||||
@ -591,7 +593,7 @@ static uint64_t icc_ap_read(CPUARMState *env, const ARMCPRegInfo *ri)
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    value = cs->icc_apr[grp][regno];
 | 
					    value = cs->icc_apr[grp][regno];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    trace_gicv3_icc_ap_read(regno, gicv3_redist_affid(cs), value);
 | 
					    trace_gicv3_icc_ap_read(ri->crm & 1, regno, gicv3_redist_affid(cs), value);
 | 
				
			||||||
    return value;
 | 
					    return value;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -603,7 +605,7 @@ static void icc_ap_write(CPUARMState *env, const ARMCPRegInfo *ri,
 | 
				
			|||||||
    int regno = ri->opc2 & 3;
 | 
					    int regno = ri->opc2 & 3;
 | 
				
			||||||
    int grp = ri->crm & 1 ? GICV3_G0 : GICV3_G1;
 | 
					    int grp = ri->crm & 1 ? GICV3_G0 : GICV3_G1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    trace_gicv3_icc_ap_write(regno, gicv3_redist_affid(cs), value);
 | 
					    trace_gicv3_icc_ap_write(ri->crm & 1, regno, gicv3_redist_affid(cs), value);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (grp == GICV3_G1 && gicv3_use_ns_bank(env)) {
 | 
					    if (grp == GICV3_G1 && gicv3_use_ns_bank(env)) {
 | 
				
			||||||
        grp = GICV3_G1NS;
 | 
					        grp = GICV3_G1NS;
 | 
				
			||||||
@ -820,7 +822,8 @@ static uint64_t icc_igrpen_read(CPUARMState *env, const ARMCPRegInfo *ri)
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    value = cs->icc_igrpen[grp];
 | 
					    value = cs->icc_igrpen[grp];
 | 
				
			||||||
    trace_gicv3_icc_igrpen_read(gicv3_redist_affid(cs), value);
 | 
					    trace_gicv3_icc_igrpen_read(ri->opc2 & 1 ? 1 : 0,
 | 
				
			||||||
 | 
					                                gicv3_redist_affid(cs), value);
 | 
				
			||||||
    return value;
 | 
					    return value;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -830,7 +833,8 @@ static void icc_igrpen_write(CPUARMState *env, const ARMCPRegInfo *ri,
 | 
				
			|||||||
    GICv3CPUState *cs = icc_cs_from_env(env);
 | 
					    GICv3CPUState *cs = icc_cs_from_env(env);
 | 
				
			||||||
    int grp = ri->opc2 & 1 ? GICV3_G1 : GICV3_G0;
 | 
					    int grp = ri->opc2 & 1 ? GICV3_G1 : GICV3_G0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    trace_gicv3_icc_igrpen_write(gicv3_redist_affid(cs), value);
 | 
					    trace_gicv3_icc_igrpen_write(ri->opc2 & 1 ? 1 : 0,
 | 
				
			||||||
 | 
					                                 gicv3_redist_affid(cs), value);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (grp == GICV3_G1 && gicv3_use_ns_bank(env)) {
 | 
					    if (grp == GICV3_G1 && gicv3_use_ns_bank(env)) {
 | 
				
			||||||
        grp = GICV3_G1NS;
 | 
					        grp = GICV3_G1NS;
 | 
				
			||||||
@ -843,9 +847,12 @@ static void icc_igrpen_write(CPUARMState *env, const ARMCPRegInfo *ri,
 | 
				
			|||||||
static uint64_t icc_igrpen1_el3_read(CPUARMState *env, const ARMCPRegInfo *ri)
 | 
					static uint64_t icc_igrpen1_el3_read(CPUARMState *env, const ARMCPRegInfo *ri)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    GICv3CPUState *cs = icc_cs_from_env(env);
 | 
					    GICv3CPUState *cs = icc_cs_from_env(env);
 | 
				
			||||||
 | 
					    uint64_t value;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /* IGRPEN1_EL3 bits 0 and 1 are r/w aliases into IGRPEN1_EL1 NS and S */
 | 
					    /* IGRPEN1_EL3 bits 0 and 1 are r/w aliases into IGRPEN1_EL1 NS and S */
 | 
				
			||||||
    return cs->icc_igrpen[GICV3_G1NS] | (cs->icc_igrpen[GICV3_G1] << 1);
 | 
					    value = cs->icc_igrpen[GICV3_G1NS] | (cs->icc_igrpen[GICV3_G1] << 1);
 | 
				
			||||||
 | 
					    trace_gicv3_icc_igrpen1_el3_read(gicv3_redist_affid(cs), value);
 | 
				
			||||||
 | 
					    return value;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void icc_igrpen1_el3_write(CPUARMState *env, const ARMCPRegInfo *ri,
 | 
					static void icc_igrpen1_el3_write(CPUARMState *env, const ARMCPRegInfo *ri,
 | 
				
			||||||
 | 
				
			|||||||
@ -85,12 +85,12 @@ gic_acknowledge_irq(int cpu, int irq) "cpu %d acknowledged irq %d"
 | 
				
			|||||||
# hw/intc/arm_gicv3_cpuif.c
 | 
					# hw/intc/arm_gicv3_cpuif.c
 | 
				
			||||||
gicv3_icc_pmr_read(uint32_t cpu, uint64_t val) "GICv3 ICC_PMR read cpu %x value 0x%" PRIx64
 | 
					gicv3_icc_pmr_read(uint32_t cpu, uint64_t val) "GICv3 ICC_PMR read cpu %x value 0x%" PRIx64
 | 
				
			||||||
gicv3_icc_pmr_write(uint32_t cpu, uint64_t val) "GICv3 ICC_PMR write cpu %x value 0x%" PRIx64
 | 
					gicv3_icc_pmr_write(uint32_t cpu, uint64_t val) "GICv3 ICC_PMR write cpu %x value 0x%" PRIx64
 | 
				
			||||||
gicv3_icc_bpr_read(uint32_t cpu, uint64_t val) "GICv3 ICC_BPR read cpu %x value 0x%" PRIx64
 | 
					gicv3_icc_bpr_read(int grp, uint32_t cpu, uint64_t val) "GICv3 ICC_BPR%d read cpu %x value 0x%" PRIx64
 | 
				
			||||||
gicv3_icc_bpr_write(uint32_t cpu, uint64_t val) "GICv3 ICC_BPR write cpu %x value 0x%" PRIx64
 | 
					gicv3_icc_bpr_write(int grp, uint32_t cpu, uint64_t val) "GICv3 ICC_BPR%d write cpu %x value 0x%" PRIx64
 | 
				
			||||||
gicv3_icc_ap_read(int regno, uint32_t cpu, uint64_t val) "GICv3 ICC_AP%dR read cpu %x value 0x%" PRIx64
 | 
					gicv3_icc_ap_read(int grp, int regno, uint32_t cpu, uint64_t val) "GICv3 ICC_AP%dR%d read cpu %x value 0x%" PRIx64
 | 
				
			||||||
gicv3_icc_ap_write(int regno, uint32_t cpu, uint64_t val) "GICv3 ICC_AP%dR write cpu %x value 0x%" PRIx64
 | 
					gicv3_icc_ap_write(int grp, int regno, uint32_t cpu, uint64_t val) "GICv3 ICC_AP%dR%d write cpu %x value 0x%" PRIx64
 | 
				
			||||||
gicv3_icc_igrpen_read(uint32_t cpu, uint64_t val) "GICv3 ICC_IGRPEN read cpu %x value 0x%" PRIx64
 | 
					gicv3_icc_igrpen_read(int grp, uint32_t cpu, uint64_t val) "GICv3 ICC_IGRPEN%d read cpu %x value 0x%" PRIx64
 | 
				
			||||||
gicv3_icc_igrpen_write(uint32_t cpu, uint64_t val) "GICv3 ICC_IGRPEN write cpu %x value 0x%" PRIx64
 | 
					gicv3_icc_igrpen_write(int grp, uint32_t cpu, uint64_t val) "GICv3 ICC_IGRPEN%d write cpu %x value 0x%" PRIx64
 | 
				
			||||||
gicv3_icc_igrpen1_el3_read(uint32_t cpu, uint64_t val) "GICv3 ICC_IGRPEN1_EL3 read cpu %x value 0x%" PRIx64
 | 
					gicv3_icc_igrpen1_el3_read(uint32_t cpu, uint64_t val) "GICv3 ICC_IGRPEN1_EL3 read cpu %x value 0x%" PRIx64
 | 
				
			||||||
gicv3_icc_igrpen1_el3_write(uint32_t cpu, uint64_t val) "GICv3 ICC_IGRPEN1_EL3 write cpu %x value 0x%" PRIx64
 | 
					gicv3_icc_igrpen1_el3_write(uint32_t cpu, uint64_t val) "GICv3 ICC_IGRPEN1_EL3 write cpu %x value 0x%" PRIx64
 | 
				
			||||||
gicv3_icc_ctlr_read(uint32_t cpu, uint64_t val) "GICv3 ICC_CTLR read cpu %x value 0x%" PRIx64
 | 
					gicv3_icc_ctlr_read(uint32_t cpu, uint64_t val) "GICv3 ICC_CTLR read cpu %x value 0x%" PRIx64
 | 
				
			||||||
@ -102,7 +102,7 @@ gicv3_cpuif_set_irqs(uint32_t cpuid, int fiqlevel, int irqlevel) "GICv3 CPU i/f
 | 
				
			|||||||
gicv3_icc_generate_sgi(uint32_t cpuid, int irq, int irm, uint32_t aff, uint32_t targetlist) "GICv3 CPU i/f %x generating SGI %d IRM %d target affinity 0x%xxx targetlist 0x%x"
 | 
					gicv3_icc_generate_sgi(uint32_t cpuid, int irq, int irm, uint32_t aff, uint32_t targetlist) "GICv3 CPU i/f %x generating SGI %d IRM %d target affinity 0x%xxx targetlist 0x%x"
 | 
				
			||||||
gicv3_icc_iar0_read(uint32_t cpu, uint64_t val) "GICv3 ICC_IAR0 read cpu %x value 0x%" PRIx64
 | 
					gicv3_icc_iar0_read(uint32_t cpu, uint64_t val) "GICv3 ICC_IAR0 read cpu %x value 0x%" PRIx64
 | 
				
			||||||
gicv3_icc_iar1_read(uint32_t cpu, uint64_t val) "GICv3 ICC_IAR1 read cpu %x value 0x%" PRIx64
 | 
					gicv3_icc_iar1_read(uint32_t cpu, uint64_t val) "GICv3 ICC_IAR1 read cpu %x value 0x%" PRIx64
 | 
				
			||||||
gicv3_icc_eoir_write(uint32_t cpu, uint64_t val) "GICv3 ICC_EOIR write cpu %x value 0x%" PRIx64
 | 
					gicv3_icc_eoir_write(int grp, uint32_t cpu, uint64_t val) "GICv3 ICC_EOIR%d write cpu %x value 0x%" PRIx64
 | 
				
			||||||
gicv3_icc_hppir0_read(uint32_t cpu, uint64_t val) "GICv3 ICC_HPPIR0 read cpu %x value 0x%" PRIx64
 | 
					gicv3_icc_hppir0_read(uint32_t cpu, uint64_t val) "GICv3 ICC_HPPIR0 read cpu %x value 0x%" PRIx64
 | 
				
			||||||
gicv3_icc_hppir1_read(uint32_t cpu, uint64_t val) "GICv3 ICC_HPPIR1 read cpu %x value 0x%" PRIx64
 | 
					gicv3_icc_hppir1_read(uint32_t cpu, uint64_t val) "GICv3 ICC_HPPIR1 read cpu %x value 0x%" PRIx64
 | 
				
			||||||
gicv3_icc_dir_write(uint32_t cpu, uint64_t val) "GICv3 ICC_DIR write cpu %x value 0x%" PRIx64
 | 
					gicv3_icc_dir_write(uint32_t cpu, uint64_t val) "GICv3 ICC_DIR write cpu %x value 0x%" PRIx64
 | 
				
			||||||
 | 
				
			|||||||
@ -79,10 +79,10 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
/* CEx Segment Address Register */
 | 
					/* CEx Segment Address Register */
 | 
				
			||||||
#define R_SEG_ADDR0       (0x30 / 4)
 | 
					#define R_SEG_ADDR0       (0x30 / 4)
 | 
				
			||||||
#define   SEG_SIZE_SHIFT       24   /* 8MB units */
 | 
					#define   SEG_END_SHIFT        24   /* 8MB units */
 | 
				
			||||||
#define   SEG_SIZE_MASK        0x7f
 | 
					#define   SEG_END_MASK         0xff
 | 
				
			||||||
#define   SEG_START_SHIFT      16   /* address bit [A29-A23] */
 | 
					#define   SEG_START_SHIFT      16   /* address bit [A29-A23] */
 | 
				
			||||||
#define   SEG_START_MASK       0x7f
 | 
					#define   SEG_START_MASK       0xff
 | 
				
			||||||
#define R_SEG_ADDR1       (0x34 / 4)
 | 
					#define R_SEG_ADDR1       (0x34 / 4)
 | 
				
			||||||
#define R_SEG_ADDR2       (0x38 / 4)
 | 
					#define R_SEG_ADDR2       (0x38 / 4)
 | 
				
			||||||
#define R_SEG_ADDR3       (0x3C / 4)
 | 
					#define R_SEG_ADDR3       (0x3C / 4)
 | 
				
			||||||
@ -127,18 +127,22 @@
 | 
				
			|||||||
#define R_SPI_MISC_CTRL   (0x10 / 4)
 | 
					#define R_SPI_MISC_CTRL   (0x10 / 4)
 | 
				
			||||||
#define R_SPI_TIMINGS     (0x14 / 4)
 | 
					#define R_SPI_TIMINGS     (0x14 / 4)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define ASPEED_SOC_SMC_FLASH_BASE   0x10000000
 | 
				
			||||||
 | 
					#define ASPEED_SOC_FMC_FLASH_BASE   0x20000000
 | 
				
			||||||
 | 
					#define ASPEED_SOC_SPI_FLASH_BASE   0x30000000
 | 
				
			||||||
 | 
					#define ASPEED_SOC_SPI2_FLASH_BASE  0x38000000
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/*
 | 
					/*
 | 
				
			||||||
 * Default segments mapping addresses and size for each slave per
 | 
					 * Default segments mapping addresses and size for each slave per
 | 
				
			||||||
 * controller. These can be changed when board is initialized with the
 | 
					 * controller. These can be changed when board is initialized with the
 | 
				
			||||||
 * Segment Address Registers but they don't seem do be used on the
 | 
					 * Segment Address Registers.
 | 
				
			||||||
 * field.
 | 
					 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
static const AspeedSegments aspeed_segments_legacy[] = {
 | 
					static const AspeedSegments aspeed_segments_legacy[] = {
 | 
				
			||||||
    { 0x10000000, 32 * 1024 * 1024 },
 | 
					    { 0x10000000, 32 * 1024 * 1024 },
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static const AspeedSegments aspeed_segments_fmc[] = {
 | 
					static const AspeedSegments aspeed_segments_fmc[] = {
 | 
				
			||||||
    { 0x20000000, 64 * 1024 * 1024 },
 | 
					    { 0x20000000, 64 * 1024 * 1024 }, /* start address is readonly */
 | 
				
			||||||
    { 0x24000000, 32 * 1024 * 1024 },
 | 
					    { 0x24000000, 32 * 1024 * 1024 },
 | 
				
			||||||
    { 0x26000000, 32 * 1024 * 1024 },
 | 
					    { 0x26000000, 32 * 1024 * 1024 },
 | 
				
			||||||
    { 0x28000000, 32 * 1024 * 1024 },
 | 
					    { 0x28000000, 32 * 1024 * 1024 },
 | 
				
			||||||
@ -149,15 +153,155 @@ static const AspeedSegments aspeed_segments_spi[] = {
 | 
				
			|||||||
    { 0x30000000, 64 * 1024 * 1024 },
 | 
					    { 0x30000000, 64 * 1024 * 1024 },
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static const AspeedSegments aspeed_segments_ast2500_fmc[] = {
 | 
				
			||||||
 | 
					    { 0x20000000, 128 * 1024 * 1024 }, /* start address is readonly */
 | 
				
			||||||
 | 
					    { 0x28000000,  32 * 1024 * 1024 },
 | 
				
			||||||
 | 
					    { 0x2A000000,  32 * 1024 * 1024 },
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static const AspeedSegments aspeed_segments_ast2500_spi1[] = {
 | 
				
			||||||
 | 
					    { 0x30000000, 32 * 1024 * 1024 }, /* start address is readonly */
 | 
				
			||||||
 | 
					    { 0x32000000, 96 * 1024 * 1024 }, /* end address is readonly */
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static const AspeedSegments aspeed_segments_ast2500_spi2[] = {
 | 
				
			||||||
 | 
					    { 0x38000000, 32 * 1024 * 1024 }, /* start address is readonly */
 | 
				
			||||||
 | 
					    { 0x3A000000, 96 * 1024 * 1024 }, /* end address is readonly */
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static const AspeedSMCController controllers[] = {
 | 
					static const AspeedSMCController controllers[] = {
 | 
				
			||||||
    { "aspeed.smc.smc", R_CONF, R_CE_CTRL, R_CTRL0, R_TIMINGS,
 | 
					    { "aspeed.smc.smc", R_CONF, R_CE_CTRL, R_CTRL0, R_TIMINGS,
 | 
				
			||||||
      CONF_ENABLE_W0, 5, aspeed_segments_legacy, 0x6000000 },
 | 
					      CONF_ENABLE_W0, 5, aspeed_segments_legacy,
 | 
				
			||||||
 | 
					      ASPEED_SOC_SMC_FLASH_BASE, 0x6000000 },
 | 
				
			||||||
    { "aspeed.smc.fmc", R_CONF, R_CE_CTRL, R_CTRL0, R_TIMINGS,
 | 
					    { "aspeed.smc.fmc", R_CONF, R_CE_CTRL, R_CTRL0, R_TIMINGS,
 | 
				
			||||||
      CONF_ENABLE_W0, 5, aspeed_segments_fmc, 0x10000000 },
 | 
					      CONF_ENABLE_W0, 5, aspeed_segments_fmc,
 | 
				
			||||||
 | 
					      ASPEED_SOC_FMC_FLASH_BASE, 0x10000000 },
 | 
				
			||||||
    { "aspeed.smc.spi", R_SPI_CONF, 0xff, R_SPI_CTRL0, R_SPI_TIMINGS,
 | 
					    { "aspeed.smc.spi", R_SPI_CONF, 0xff, R_SPI_CTRL0, R_SPI_TIMINGS,
 | 
				
			||||||
      SPI_CONF_ENABLE_W0, 1, aspeed_segments_spi, 0x10000000 },
 | 
					      SPI_CONF_ENABLE_W0, 1, aspeed_segments_spi,
 | 
				
			||||||
 | 
					      ASPEED_SOC_SPI_FLASH_BASE, 0x10000000 },
 | 
				
			||||||
 | 
					    { "aspeed.smc.ast2500-fmc", R_CONF, R_CE_CTRL, R_CTRL0, R_TIMINGS,
 | 
				
			||||||
 | 
					      CONF_ENABLE_W0, 3, aspeed_segments_ast2500_fmc,
 | 
				
			||||||
 | 
					      ASPEED_SOC_FMC_FLASH_BASE, 0x10000000 },
 | 
				
			||||||
 | 
					    { "aspeed.smc.ast2500-spi1", R_CONF, R_CE_CTRL, R_CTRL0, R_TIMINGS,
 | 
				
			||||||
 | 
					      CONF_ENABLE_W0, 2, aspeed_segments_ast2500_spi1,
 | 
				
			||||||
 | 
					      ASPEED_SOC_SPI_FLASH_BASE, 0x8000000 },
 | 
				
			||||||
 | 
					    { "aspeed.smc.ast2500-spi2", R_CONF, R_CE_CTRL, R_CTRL0, R_TIMINGS,
 | 
				
			||||||
 | 
					      CONF_ENABLE_W0, 2, aspeed_segments_ast2500_spi2,
 | 
				
			||||||
 | 
					      ASPEED_SOC_SPI2_FLASH_BASE, 0x8000000 },
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * The Segment Register uses a 8MB unit to encode the start address
 | 
				
			||||||
 | 
					 * and the end address of the mapping window of a flash SPI slave :
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 *        | byte 1 | byte 2 | byte 3 | byte 4 |
 | 
				
			||||||
 | 
					 *        +--------+--------+--------+--------+
 | 
				
			||||||
 | 
					 *        |  end   |  start |   0    |   0    |
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					static inline uint32_t aspeed_smc_segment_to_reg(const AspeedSegments *seg)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    uint32_t reg = 0;
 | 
				
			||||||
 | 
					    reg |= ((seg->addr >> 23) & SEG_START_MASK) << SEG_START_SHIFT;
 | 
				
			||||||
 | 
					    reg |= (((seg->addr + seg->size) >> 23) & SEG_END_MASK) << SEG_END_SHIFT;
 | 
				
			||||||
 | 
					    return reg;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static inline void aspeed_smc_reg_to_segment(uint32_t reg, AspeedSegments *seg)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    seg->addr = ((reg >> SEG_START_SHIFT) & SEG_START_MASK) << 23;
 | 
				
			||||||
 | 
					    seg->size = (((reg >> SEG_END_SHIFT) & SEG_END_MASK) << 23) - seg->addr;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static bool aspeed_smc_flash_overlap(const AspeedSMCState *s,
 | 
				
			||||||
 | 
					                                     const AspeedSegments *new,
 | 
				
			||||||
 | 
					                                     int cs)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    AspeedSegments seg;
 | 
				
			||||||
 | 
					    int i;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    for (i = 0; i < s->ctrl->max_slaves; i++) {
 | 
				
			||||||
 | 
					        if (i == cs) {
 | 
				
			||||||
 | 
					            continue;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        aspeed_smc_reg_to_segment(s->regs[R_SEG_ADDR0 + i], &seg);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (new->addr + new->size > seg.addr &&
 | 
				
			||||||
 | 
					            new->addr < seg.addr + seg.size) {
 | 
				
			||||||
 | 
					            qemu_log_mask(LOG_GUEST_ERROR, "%s: new segment CS%d [ 0x%"
 | 
				
			||||||
 | 
					                          HWADDR_PRIx" - 0x%"HWADDR_PRIx" ] overlaps with "
 | 
				
			||||||
 | 
					                          "CS%d [ 0x%"HWADDR_PRIx" - 0x%"HWADDR_PRIx" ]\n",
 | 
				
			||||||
 | 
					                          s->ctrl->name, cs, new->addr, new->addr + new->size,
 | 
				
			||||||
 | 
					                          i, seg.addr, seg.addr + seg.size);
 | 
				
			||||||
 | 
					            return true;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    return false;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void aspeed_smc_flash_set_segment(AspeedSMCState *s, int cs,
 | 
				
			||||||
 | 
					                                         uint64_t new)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    AspeedSMCFlash *fl = &s->flashes[cs];
 | 
				
			||||||
 | 
					    AspeedSegments seg;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    aspeed_smc_reg_to_segment(new, &seg);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /* The start address of CS0 is read-only */
 | 
				
			||||||
 | 
					    if (cs == 0 && seg.addr != s->ctrl->flash_window_base) {
 | 
				
			||||||
 | 
					        qemu_log_mask(LOG_GUEST_ERROR,
 | 
				
			||||||
 | 
					                      "%s: Tried to change CS0 start address to 0x%"
 | 
				
			||||||
 | 
					                      HWADDR_PRIx "\n", s->ctrl->name, seg.addr);
 | 
				
			||||||
 | 
					        return;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /*
 | 
				
			||||||
 | 
					     * The end address of the AST2500 spi controllers is also
 | 
				
			||||||
 | 
					     * read-only.
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    if ((s->ctrl->segments == aspeed_segments_ast2500_spi1 ||
 | 
				
			||||||
 | 
					         s->ctrl->segments == aspeed_segments_ast2500_spi2) &&
 | 
				
			||||||
 | 
					        cs == s->ctrl->max_slaves &&
 | 
				
			||||||
 | 
					        seg.addr + seg.size != s->ctrl->segments[cs].addr +
 | 
				
			||||||
 | 
					        s->ctrl->segments[cs].size) {
 | 
				
			||||||
 | 
					        qemu_log_mask(LOG_GUEST_ERROR,
 | 
				
			||||||
 | 
					                      "%s: Tried to change CS%d end address to 0x%"
 | 
				
			||||||
 | 
					                      HWADDR_PRIx "\n", s->ctrl->name, cs, seg.addr);
 | 
				
			||||||
 | 
					        return;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /* Keep the segment in the overall flash window */
 | 
				
			||||||
 | 
					    if (seg.addr + seg.size <= s->ctrl->flash_window_base ||
 | 
				
			||||||
 | 
					        seg.addr > s->ctrl->flash_window_base + s->ctrl->flash_window_size) {
 | 
				
			||||||
 | 
					        qemu_log_mask(LOG_GUEST_ERROR, "%s: new segment for CS%d is invalid : "
 | 
				
			||||||
 | 
					                      "[ 0x%"HWADDR_PRIx" - 0x%"HWADDR_PRIx" ]\n",
 | 
				
			||||||
 | 
					                      s->ctrl->name, cs, seg.addr, seg.addr + seg.size);
 | 
				
			||||||
 | 
					        return;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /* Check start address vs. alignment */
 | 
				
			||||||
 | 
					    if (seg.addr % seg.size) {
 | 
				
			||||||
 | 
					        qemu_log_mask(LOG_GUEST_ERROR, "%s: new segment for CS%d is not "
 | 
				
			||||||
 | 
					                      "aligned : [ 0x%"HWADDR_PRIx" - 0x%"HWADDR_PRIx" ]\n",
 | 
				
			||||||
 | 
					                      s->ctrl->name, cs, seg.addr, seg.addr + seg.size);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /* And segments should not overlap */
 | 
				
			||||||
 | 
					    if (aspeed_smc_flash_overlap(s, &seg, cs)) {
 | 
				
			||||||
 | 
					        return;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /* All should be fine now to move the region */
 | 
				
			||||||
 | 
					    memory_region_transaction_begin();
 | 
				
			||||||
 | 
					    memory_region_set_size(&fl->mmio, seg.size);
 | 
				
			||||||
 | 
					    memory_region_set_address(&fl->mmio, seg.addr - s->ctrl->flash_window_base);
 | 
				
			||||||
 | 
					    memory_region_set_enabled(&fl->mmio, true);
 | 
				
			||||||
 | 
					    memory_region_transaction_commit();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    s->regs[R_SEG_ADDR0 + cs] = new;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static uint64_t aspeed_smc_flash_default_read(void *opaque, hwaddr addr,
 | 
					static uint64_t aspeed_smc_flash_default_read(void *opaque, hwaddr addr,
 | 
				
			||||||
                                              unsigned size)
 | 
					                                              unsigned size)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
@ -281,6 +425,12 @@ static void aspeed_smc_reset(DeviceState *d)
 | 
				
			|||||||
        s->regs[s->r_ctrl0 + i] |= CTRL_CE_STOP_ACTIVE;
 | 
					        s->regs[s->r_ctrl0 + i] |= CTRL_CE_STOP_ACTIVE;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /* setup default segment register values for all */
 | 
				
			||||||
 | 
					    for (i = 0; i < s->ctrl->max_slaves; ++i) {
 | 
				
			||||||
 | 
					        s->regs[R_SEG_ADDR0 + i] =
 | 
				
			||||||
 | 
					            aspeed_smc_segment_to_reg(&s->ctrl->segments[i]);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    aspeed_smc_update_cs(s);
 | 
					    aspeed_smc_update_cs(s);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -301,6 +451,7 @@ static uint64_t aspeed_smc_read(void *opaque, hwaddr addr, unsigned int size)
 | 
				
			|||||||
        addr == s->r_timings ||
 | 
					        addr == s->r_timings ||
 | 
				
			||||||
        addr == s->r_ce_ctrl ||
 | 
					        addr == s->r_ce_ctrl ||
 | 
				
			||||||
        addr == R_INTR_CTRL ||
 | 
					        addr == R_INTR_CTRL ||
 | 
				
			||||||
 | 
					        (addr >= R_SEG_ADDR0 && addr < R_SEG_ADDR0 + s->ctrl->max_slaves) ||
 | 
				
			||||||
        (addr >= s->r_ctrl0 && addr < s->r_ctrl0 + s->num_cs)) {
 | 
					        (addr >= s->r_ctrl0 && addr < s->r_ctrl0 + s->num_cs)) {
 | 
				
			||||||
        return s->regs[addr];
 | 
					        return s->regs[addr];
 | 
				
			||||||
    } else {
 | 
					    } else {
 | 
				
			||||||
@ -332,6 +483,13 @@ static void aspeed_smc_write(void *opaque, hwaddr addr, uint64_t data,
 | 
				
			|||||||
    } else if (addr >= s->r_ctrl0 && addr < s->r_ctrl0 + s->num_cs) {
 | 
					    } else if (addr >= s->r_ctrl0 && addr < s->r_ctrl0 + s->num_cs) {
 | 
				
			||||||
        s->regs[addr] = value;
 | 
					        s->regs[addr] = value;
 | 
				
			||||||
        aspeed_smc_update_cs(s);
 | 
					        aspeed_smc_update_cs(s);
 | 
				
			||||||
 | 
					    } else if (addr >= R_SEG_ADDR0 &&
 | 
				
			||||||
 | 
					               addr < R_SEG_ADDR0 + s->ctrl->max_slaves) {
 | 
				
			||||||
 | 
					        int cs = addr - R_SEG_ADDR0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (value != s->regs[R_SEG_ADDR0 + cs]) {
 | 
				
			||||||
 | 
					            aspeed_smc_flash_set_segment(s, cs, value);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
    } else {
 | 
					    } else {
 | 
				
			||||||
        qemu_log_mask(LOG_UNIMP, "%s: not implemented: 0x%" HWADDR_PRIx "\n",
 | 
					        qemu_log_mask(LOG_UNIMP, "%s: not implemented: 0x%" HWADDR_PRIx "\n",
 | 
				
			||||||
                      __func__, addr);
 | 
					                      __func__, addr);
 | 
				
			||||||
@ -384,23 +542,33 @@ static void aspeed_smc_realize(DeviceState *dev, Error **errp)
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    aspeed_smc_reset(dev);
 | 
					    aspeed_smc_reset(dev);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /* The memory region for the controller registers */
 | 
				
			||||||
    memory_region_init_io(&s->mmio, OBJECT(s), &aspeed_smc_ops, s,
 | 
					    memory_region_init_io(&s->mmio, OBJECT(s), &aspeed_smc_ops, s,
 | 
				
			||||||
                          s->ctrl->name, ASPEED_SMC_R_MAX * 4);
 | 
					                          s->ctrl->name, ASPEED_SMC_R_MAX * 4);
 | 
				
			||||||
    sysbus_init_mmio(sbd, &s->mmio);
 | 
					    sysbus_init_mmio(sbd, &s->mmio);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /*
 | 
					    /*
 | 
				
			||||||
     * Memory region where flash modules are remapped
 | 
					     * The container memory region representing the address space
 | 
				
			||||||
 | 
					     * window in which the flash modules are mapped. The size and
 | 
				
			||||||
 | 
					     * address depends on the SoC model and controller type.
 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
    snprintf(name, sizeof(name), "%s.flash", s->ctrl->name);
 | 
					    snprintf(name, sizeof(name), "%s.flash", s->ctrl->name);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    memory_region_init_io(&s->mmio_flash, OBJECT(s),
 | 
					    memory_region_init_io(&s->mmio_flash, OBJECT(s),
 | 
				
			||||||
                          &aspeed_smc_flash_default_ops, s, name,
 | 
					                          &aspeed_smc_flash_default_ops, s, name,
 | 
				
			||||||
                          s->ctrl->mapping_window_size);
 | 
					                          s->ctrl->flash_window_size);
 | 
				
			||||||
    sysbus_init_mmio(sbd, &s->mmio_flash);
 | 
					    sysbus_init_mmio(sbd, &s->mmio_flash);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    s->flashes = g_new0(AspeedSMCFlash, s->num_cs);
 | 
					    s->flashes = g_new0(AspeedSMCFlash, s->ctrl->max_slaves);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    for (i = 0; i < s->num_cs; ++i) {
 | 
					    /*
 | 
				
			||||||
 | 
					     * Let's create a sub memory region for each possible slave. All
 | 
				
			||||||
 | 
					     * have a configurable memory segment in the overall flash mapping
 | 
				
			||||||
 | 
					     * window of the controller but, there is not necessarily a flash
 | 
				
			||||||
 | 
					     * module behind to handle the memory accesses. This depends on
 | 
				
			||||||
 | 
					     * the board configuration.
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    for (i = 0; i < s->ctrl->max_slaves; ++i) {
 | 
				
			||||||
        AspeedSMCFlash *fl = &s->flashes[i];
 | 
					        AspeedSMCFlash *fl = &s->flashes[i];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        snprintf(name, sizeof(name), "%s.%d", s->ctrl->name, i);
 | 
					        snprintf(name, sizeof(name), "%s.%d", s->ctrl->name, i);
 | 
				
			||||||
 | 
				
			|||||||
@ -20,6 +20,8 @@
 | 
				
			|||||||
#include "hw/i2c/aspeed_i2c.h"
 | 
					#include "hw/i2c/aspeed_i2c.h"
 | 
				
			||||||
#include "hw/ssi/aspeed_smc.h"
 | 
					#include "hw/ssi/aspeed_smc.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define ASPEED_SPIS_NUM  2
 | 
				
			||||||
 | 
					
 | 
				
			||||||
typedef struct AspeedSoCState {
 | 
					typedef struct AspeedSoCState {
 | 
				
			||||||
    /*< private >*/
 | 
					    /*< private >*/
 | 
				
			||||||
    DeviceState parent;
 | 
					    DeviceState parent;
 | 
				
			||||||
@ -31,8 +33,8 @@ typedef struct AspeedSoCState {
 | 
				
			|||||||
    AspeedTimerCtrlState timerctrl;
 | 
					    AspeedTimerCtrlState timerctrl;
 | 
				
			||||||
    AspeedI2CState i2c;
 | 
					    AspeedI2CState i2c;
 | 
				
			||||||
    AspeedSCUState scu;
 | 
					    AspeedSCUState scu;
 | 
				
			||||||
    AspeedSMCState smc;
 | 
					    AspeedSMCState fmc;
 | 
				
			||||||
    AspeedSMCState spi;
 | 
					    AspeedSMCState spi[ASPEED_SPIS_NUM];
 | 
				
			||||||
    AspeedSDMCState sdmc;
 | 
					    AspeedSDMCState sdmc;
 | 
				
			||||||
} AspeedSoCState;
 | 
					} AspeedSoCState;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -44,6 +46,10 @@ typedef struct AspeedSoCInfo {
 | 
				
			|||||||
    const char *cpu_model;
 | 
					    const char *cpu_model;
 | 
				
			||||||
    uint32_t silicon_rev;
 | 
					    uint32_t silicon_rev;
 | 
				
			||||||
    hwaddr sdram_base;
 | 
					    hwaddr sdram_base;
 | 
				
			||||||
 | 
					    int spis_num;
 | 
				
			||||||
 | 
					    const hwaddr *spi_bases;
 | 
				
			||||||
 | 
					    const char *fmc_typename;
 | 
				
			||||||
 | 
					    const char **spi_typename;
 | 
				
			||||||
} AspeedSoCInfo;
 | 
					} AspeedSoCInfo;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
typedef struct AspeedSoCClass {
 | 
					typedef struct AspeedSoCClass {
 | 
				
			||||||
 | 
				
			|||||||
@ -33,6 +33,7 @@ typedef struct VirtGuestInfo {
 | 
				
			|||||||
    const int *irqmap;
 | 
					    const int *irqmap;
 | 
				
			||||||
    bool use_highmem;
 | 
					    bool use_highmem;
 | 
				
			||||||
    int gic_version;
 | 
					    int gic_version;
 | 
				
			||||||
 | 
					    bool no_its;
 | 
				
			||||||
} VirtGuestInfo;
 | 
					} VirtGuestInfo;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -42,7 +42,8 @@ typedef struct AspeedSMCController {
 | 
				
			|||||||
    uint8_t conf_enable_w0;
 | 
					    uint8_t conf_enable_w0;
 | 
				
			||||||
    uint8_t max_slaves;
 | 
					    uint8_t max_slaves;
 | 
				
			||||||
    const AspeedSegments *segments;
 | 
					    const AspeedSegments *segments;
 | 
				
			||||||
    uint32_t mapping_window_size;
 | 
					    hwaddr flash_window_base;
 | 
				
			||||||
 | 
					    uint32_t flash_window_size;
 | 
				
			||||||
} AspeedSMCController;
 | 
					} AspeedSMCController;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
typedef struct AspeedSMCFlash {
 | 
					typedef struct AspeedSMCFlash {
 | 
				
			||||||
 | 
				
			|||||||
@ -3,11 +3,6 @@
 | 
				
			|||||||
#include "migration/vmstate.h"
 | 
					#include "migration/vmstate.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const VMStateDescription vmstate_dummy = {};
 | 
					const VMStateDescription vmstate_dummy = {};
 | 
				
			||||||
const VMStateInfo vmstate_info_uint8;
 | 
					 | 
				
			||||||
const VMStateInfo vmstate_info_uint32;
 | 
					 | 
				
			||||||
const VMStateInfo vmstate_info_uint64;
 | 
					 | 
				
			||||||
const VMStateInfo vmstate_info_int64;
 | 
					 | 
				
			||||||
const VMStateInfo vmstate_info_timer;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
int vmstate_register_with_alias_id(DeviceState *dev,
 | 
					int vmstate_register_with_alias_id(DeviceState *dev,
 | 
				
			||||||
                                   int instance_id,
 | 
					                                   int instance_id,
 | 
				
			||||||
 | 
				
			|||||||
@ -2191,7 +2191,11 @@ static inline bool arm_cpu_data_is_big_endian(CPUARMState *env)
 | 
				
			|||||||
#define ARM_TBFLAG_BE_DATA_SHIFT    20
 | 
					#define ARM_TBFLAG_BE_DATA_SHIFT    20
 | 
				
			||||||
#define ARM_TBFLAG_BE_DATA_MASK     (1 << ARM_TBFLAG_BE_DATA_SHIFT)
 | 
					#define ARM_TBFLAG_BE_DATA_MASK     (1 << ARM_TBFLAG_BE_DATA_SHIFT)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* Bit usage when in AArch64 state: currently we have no A64 specific bits */
 | 
					/* Bit usage when in AArch64 state */
 | 
				
			||||||
 | 
					#define ARM_TBFLAG_TBI0_SHIFT 0        /* TBI0 for EL0/1 or TBI for EL2/3 */
 | 
				
			||||||
 | 
					#define ARM_TBFLAG_TBI0_MASK (0x1ull << ARM_TBFLAG_TBI0_SHIFT)
 | 
				
			||||||
 | 
					#define ARM_TBFLAG_TBI1_SHIFT 1        /* TBI1 for EL0/1  */
 | 
				
			||||||
 | 
					#define ARM_TBFLAG_TBI1_MASK (0x1ull << ARM_TBFLAG_TBI1_SHIFT)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* some convenience accessor macros */
 | 
					/* some convenience accessor macros */
 | 
				
			||||||
#define ARM_TBFLAG_AARCH64_STATE(F) \
 | 
					#define ARM_TBFLAG_AARCH64_STATE(F) \
 | 
				
			||||||
@ -2222,6 +2226,10 @@ static inline bool arm_cpu_data_is_big_endian(CPUARMState *env)
 | 
				
			|||||||
    (((F) & ARM_TBFLAG_NS_MASK) >> ARM_TBFLAG_NS_SHIFT)
 | 
					    (((F) & ARM_TBFLAG_NS_MASK) >> ARM_TBFLAG_NS_SHIFT)
 | 
				
			||||||
#define ARM_TBFLAG_BE_DATA(F) \
 | 
					#define ARM_TBFLAG_BE_DATA(F) \
 | 
				
			||||||
    (((F) & ARM_TBFLAG_BE_DATA_MASK) >> ARM_TBFLAG_BE_DATA_SHIFT)
 | 
					    (((F) & ARM_TBFLAG_BE_DATA_MASK) >> ARM_TBFLAG_BE_DATA_SHIFT)
 | 
				
			||||||
 | 
					#define ARM_TBFLAG_TBI0(F) \
 | 
				
			||||||
 | 
					    (((F) & ARM_TBFLAG_TBI0_MASK) >> ARM_TBFLAG_TBI0_SHIFT)
 | 
				
			||||||
 | 
					#define ARM_TBFLAG_TBI1(F) \
 | 
				
			||||||
 | 
					    (((F) & ARM_TBFLAG_TBI1_MASK) >> ARM_TBFLAG_TBI1_SHIFT)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static inline bool bswap_code(bool sctlr_b)
 | 
					static inline bool bswap_code(bool sctlr_b)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
@ -2319,12 +2327,51 @@ static inline bool arm_cpu_bswap_data(CPUARMState *env)
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifndef CONFIG_USER_ONLY
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * arm_regime_tbi0:
 | 
				
			||||||
 | 
					 * @env: CPUARMState
 | 
				
			||||||
 | 
					 * @mmu_idx: MMU index indicating required translation regime
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Extracts the TBI0 value from the appropriate TCR for the current EL
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Returns: the TBI0 value.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					uint32_t arm_regime_tbi0(CPUARMState *env, ARMMMUIdx mmu_idx);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * arm_regime_tbi1:
 | 
				
			||||||
 | 
					 * @env: CPUARMState
 | 
				
			||||||
 | 
					 * @mmu_idx: MMU index indicating required translation regime
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Extracts the TBI1 value from the appropriate TCR for the current EL
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Returns: the TBI1 value.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					uint32_t arm_regime_tbi1(CPUARMState *env, ARMMMUIdx mmu_idx);
 | 
				
			||||||
 | 
					#else
 | 
				
			||||||
 | 
					/* We can't handle tagged addresses properly in user-only mode */
 | 
				
			||||||
 | 
					static inline uint32_t arm_regime_tbi0(CPUARMState *env, ARMMMUIdx mmu_idx)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    return 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static inline uint32_t arm_regime_tbi1(CPUARMState *env, ARMMMUIdx mmu_idx)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    return 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static inline void cpu_get_tb_cpu_state(CPUARMState *env, target_ulong *pc,
 | 
					static inline void cpu_get_tb_cpu_state(CPUARMState *env, target_ulong *pc,
 | 
				
			||||||
                                        target_ulong *cs_base, uint32_t *flags)
 | 
					                                        target_ulong *cs_base, uint32_t *flags)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
 | 
					    ARMMMUIdx mmu_idx = cpu_mmu_index(env, false);
 | 
				
			||||||
    if (is_a64(env)) {
 | 
					    if (is_a64(env)) {
 | 
				
			||||||
        *pc = env->pc;
 | 
					        *pc = env->pc;
 | 
				
			||||||
        *flags = ARM_TBFLAG_AARCH64_STATE_MASK;
 | 
					        *flags = ARM_TBFLAG_AARCH64_STATE_MASK;
 | 
				
			||||||
 | 
					        /* Get control bits for tagged addresses */
 | 
				
			||||||
 | 
					        *flags |= (arm_regime_tbi0(env, mmu_idx) << ARM_TBFLAG_TBI0_SHIFT);
 | 
				
			||||||
 | 
					        *flags |= (arm_regime_tbi1(env, mmu_idx) << ARM_TBFLAG_TBI1_SHIFT);
 | 
				
			||||||
    } else {
 | 
					    } else {
 | 
				
			||||||
        *pc = env->regs[15];
 | 
					        *pc = env->regs[15];
 | 
				
			||||||
        *flags = (env->thumb << ARM_TBFLAG_THUMB_SHIFT)
 | 
					        *flags = (env->thumb << ARM_TBFLAG_THUMB_SHIFT)
 | 
				
			||||||
@ -2343,7 +2390,8 @@ static inline void cpu_get_tb_cpu_state(CPUARMState *env, target_ulong *pc,
 | 
				
			|||||||
                   << ARM_TBFLAG_XSCALE_CPAR_SHIFT);
 | 
					                   << ARM_TBFLAG_XSCALE_CPAR_SHIFT);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    *flags |= (cpu_mmu_index(env, false) << ARM_TBFLAG_MMUIDX_SHIFT);
 | 
					    *flags |= (mmu_idx << ARM_TBFLAG_MMUIDX_SHIFT);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /* The SS_ACTIVE and PSTATE_SS bits correspond to the state machine
 | 
					    /* The SS_ACTIVE and PSTATE_SS bits correspond to the state machine
 | 
				
			||||||
     * states defined in the ARM ARM for software singlestep:
 | 
					     * states defined in the ARM ARM for software singlestep:
 | 
				
			||||||
     *  SS_ACTIVE   PSTATE.SS   State
 | 
					     *  SS_ACTIVE   PSTATE.SS   State
 | 
				
			||||||
 | 
				
			|||||||
@ -1,4 +1,5 @@
 | 
				
			|||||||
#include "qemu/osdep.h"
 | 
					#include "qemu/osdep.h"
 | 
				
			||||||
 | 
					#include "trace.h"
 | 
				
			||||||
#include "cpu.h"
 | 
					#include "cpu.h"
 | 
				
			||||||
#include "internals.h"
 | 
					#include "internals.h"
 | 
				
			||||||
#include "exec/gdbstub.h"
 | 
					#include "exec/gdbstub.h"
 | 
				
			||||||
@ -1560,10 +1561,13 @@ static void gt_recalc_timer(ARMCPU *cpu, int timeridx)
 | 
				
			|||||||
        /* Note that this must be unsigned 64 bit arithmetic: */
 | 
					        /* Note that this must be unsigned 64 bit arithmetic: */
 | 
				
			||||||
        int istatus = count - offset >= gt->cval;
 | 
					        int istatus = count - offset >= gt->cval;
 | 
				
			||||||
        uint64_t nexttick;
 | 
					        uint64_t nexttick;
 | 
				
			||||||
 | 
					        int irqstate;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        gt->ctl = deposit32(gt->ctl, 2, 1, istatus);
 | 
					        gt->ctl = deposit32(gt->ctl, 2, 1, istatus);
 | 
				
			||||||
        qemu_set_irq(cpu->gt_timer_outputs[timeridx],
 | 
					
 | 
				
			||||||
                     (istatus && !(gt->ctl & 2)));
 | 
					        irqstate = (istatus && !(gt->ctl & 2));
 | 
				
			||||||
 | 
					        qemu_set_irq(cpu->gt_timer_outputs[timeridx], irqstate);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if (istatus) {
 | 
					        if (istatus) {
 | 
				
			||||||
            /* Next transition is when count rolls back over to zero */
 | 
					            /* Next transition is when count rolls back over to zero */
 | 
				
			||||||
            nexttick = UINT64_MAX;
 | 
					            nexttick = UINT64_MAX;
 | 
				
			||||||
@ -1580,11 +1584,13 @@ static void gt_recalc_timer(ARMCPU *cpu, int timeridx)
 | 
				
			|||||||
            nexttick = INT64_MAX / GTIMER_SCALE;
 | 
					            nexttick = INT64_MAX / GTIMER_SCALE;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        timer_mod(cpu->gt_timer[timeridx], nexttick);
 | 
					        timer_mod(cpu->gt_timer[timeridx], nexttick);
 | 
				
			||||||
 | 
					        trace_arm_gt_recalc(timeridx, irqstate, nexttick);
 | 
				
			||||||
    } else {
 | 
					    } else {
 | 
				
			||||||
        /* Timer disabled: ISTATUS and timer output always clear */
 | 
					        /* Timer disabled: ISTATUS and timer output always clear */
 | 
				
			||||||
        gt->ctl &= ~4;
 | 
					        gt->ctl &= ~4;
 | 
				
			||||||
        qemu_set_irq(cpu->gt_timer_outputs[timeridx], 0);
 | 
					        qemu_set_irq(cpu->gt_timer_outputs[timeridx], 0);
 | 
				
			||||||
        timer_del(cpu->gt_timer[timeridx]);
 | 
					        timer_del(cpu->gt_timer[timeridx]);
 | 
				
			||||||
 | 
					        trace_arm_gt_recalc_disabled(timeridx);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -1610,6 +1616,7 @@ static void gt_cval_write(CPUARMState *env, const ARMCPRegInfo *ri,
 | 
				
			|||||||
                          int timeridx,
 | 
					                          int timeridx,
 | 
				
			||||||
                          uint64_t value)
 | 
					                          uint64_t value)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
 | 
					    trace_arm_gt_cval_write(timeridx, value);
 | 
				
			||||||
    env->cp15.c14_timer[timeridx].cval = value;
 | 
					    env->cp15.c14_timer[timeridx].cval = value;
 | 
				
			||||||
    gt_recalc_timer(arm_env_get_cpu(env), timeridx);
 | 
					    gt_recalc_timer(arm_env_get_cpu(env), timeridx);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@ -1629,6 +1636,7 @@ static void gt_tval_write(CPUARMState *env, const ARMCPRegInfo *ri,
 | 
				
			|||||||
{
 | 
					{
 | 
				
			||||||
    uint64_t offset = timeridx == GTIMER_VIRT ? env->cp15.cntvoff_el2 : 0;
 | 
					    uint64_t offset = timeridx == GTIMER_VIRT ? env->cp15.cntvoff_el2 : 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    trace_arm_gt_tval_write(timeridx, value);
 | 
				
			||||||
    env->cp15.c14_timer[timeridx].cval = gt_get_countervalue(env) - offset +
 | 
					    env->cp15.c14_timer[timeridx].cval = gt_get_countervalue(env) - offset +
 | 
				
			||||||
                                         sextract64(value, 0, 32);
 | 
					                                         sextract64(value, 0, 32);
 | 
				
			||||||
    gt_recalc_timer(arm_env_get_cpu(env), timeridx);
 | 
					    gt_recalc_timer(arm_env_get_cpu(env), timeridx);
 | 
				
			||||||
@ -1641,6 +1649,7 @@ static void gt_ctl_write(CPUARMState *env, const ARMCPRegInfo *ri,
 | 
				
			|||||||
    ARMCPU *cpu = arm_env_get_cpu(env);
 | 
					    ARMCPU *cpu = arm_env_get_cpu(env);
 | 
				
			||||||
    uint32_t oldval = env->cp15.c14_timer[timeridx].ctl;
 | 
					    uint32_t oldval = env->cp15.c14_timer[timeridx].ctl;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    trace_arm_gt_ctl_write(timeridx, value);
 | 
				
			||||||
    env->cp15.c14_timer[timeridx].ctl = deposit64(oldval, 0, 2, value);
 | 
					    env->cp15.c14_timer[timeridx].ctl = deposit64(oldval, 0, 2, value);
 | 
				
			||||||
    if ((oldval ^ value) & 1) {
 | 
					    if ((oldval ^ value) & 1) {
 | 
				
			||||||
        /* Enable toggled */
 | 
					        /* Enable toggled */
 | 
				
			||||||
@ -1649,8 +1658,10 @@ static void gt_ctl_write(CPUARMState *env, const ARMCPRegInfo *ri,
 | 
				
			|||||||
        /* IMASK toggled: don't need to recalculate,
 | 
					        /* IMASK toggled: don't need to recalculate,
 | 
				
			||||||
         * just set the interrupt line based on ISTATUS
 | 
					         * just set the interrupt line based on ISTATUS
 | 
				
			||||||
         */
 | 
					         */
 | 
				
			||||||
        qemu_set_irq(cpu->gt_timer_outputs[timeridx],
 | 
					        int irqstate = (oldval & 4) && !(value & 2);
 | 
				
			||||||
                     (oldval & 4) && !(value & 2));
 | 
					
 | 
				
			||||||
 | 
					        trace_arm_gt_imask_toggle(timeridx, irqstate);
 | 
				
			||||||
 | 
					        qemu_set_irq(cpu->gt_timer_outputs[timeridx], irqstate);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -1715,6 +1726,7 @@ static void gt_cntvoff_write(CPUARMState *env, const ARMCPRegInfo *ri,
 | 
				
			|||||||
{
 | 
					{
 | 
				
			||||||
    ARMCPU *cpu = arm_env_get_cpu(env);
 | 
					    ARMCPU *cpu = arm_env_get_cpu(env);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    trace_arm_gt_cntvoff_write(value);
 | 
				
			||||||
    raw_write(env, ri, value);
 | 
					    raw_write(env, ri, value);
 | 
				
			||||||
    gt_recalc_timer(cpu, GTIMER_VIRT);
 | 
					    gt_recalc_timer(cpu, GTIMER_VIRT);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@ -4060,6 +4072,14 @@ static const ARMCPRegInfo debug_cp_reginfo[] = {
 | 
				
			|||||||
      .cp = 14, .opc1 = 0, .crn = 0, .crm = 7, .opc2 = 0,
 | 
					      .cp = 14, .opc1 = 0, .crn = 0, .crm = 7, .opc2 = 0,
 | 
				
			||||||
      .access = PL1_RW, .accessfn = access_tda,
 | 
					      .access = PL1_RW, .accessfn = access_tda,
 | 
				
			||||||
      .type = ARM_CP_NOP },
 | 
					      .type = ARM_CP_NOP },
 | 
				
			||||||
 | 
					    /* Dummy MDCCINT_EL1, since we don't implement the Debug Communications
 | 
				
			||||||
 | 
					     * Channel but Linux may try to access this register. The 32-bit
 | 
				
			||||||
 | 
					     * alias is DBGDCCINT.
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    { .name = "MDCCINT_EL1", .state = ARM_CP_STATE_BOTH,
 | 
				
			||||||
 | 
					      .cp = 14, .opc0 = 2, .opc1 = 0, .crn = 0, .crm = 2, .opc2 = 0,
 | 
				
			||||||
 | 
					      .access = PL1_RW, .accessfn = access_tda,
 | 
				
			||||||
 | 
					      .type = ARM_CP_NOP },
 | 
				
			||||||
    REGINFO_SENTINEL
 | 
					    REGINFO_SENTINEL
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -6720,6 +6740,52 @@ static inline TCR *regime_tcr(CPUARMState *env, ARMMMUIdx mmu_idx)
 | 
				
			|||||||
    return &env->cp15.tcr_el[regime_el(env, mmu_idx)];
 | 
					    return &env->cp15.tcr_el[regime_el(env, mmu_idx)];
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Returns TBI0 value for current regime el */
 | 
				
			||||||
 | 
					uint32_t arm_regime_tbi0(CPUARMState *env, ARMMMUIdx mmu_idx)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    TCR *tcr;
 | 
				
			||||||
 | 
					    uint32_t el;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /* For EL0 and EL1, TBI is controlled by stage 1's TCR, so convert
 | 
				
			||||||
 | 
					       * a stage 1+2 mmu index into the appropriate stage 1 mmu index.
 | 
				
			||||||
 | 
					       */
 | 
				
			||||||
 | 
					    if (mmu_idx == ARMMMUIdx_S12NSE0 || mmu_idx == ARMMMUIdx_S12NSE1) {
 | 
				
			||||||
 | 
					        mmu_idx += ARMMMUIdx_S1NSE0;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    tcr = regime_tcr(env, mmu_idx);
 | 
				
			||||||
 | 
					    el = regime_el(env, mmu_idx);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (el > 1) {
 | 
				
			||||||
 | 
					        return extract64(tcr->raw_tcr, 20, 1);
 | 
				
			||||||
 | 
					    } else {
 | 
				
			||||||
 | 
					        return extract64(tcr->raw_tcr, 37, 1);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Returns TBI1 value for current regime el */
 | 
				
			||||||
 | 
					uint32_t arm_regime_tbi1(CPUARMState *env, ARMMMUIdx mmu_idx)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    TCR *tcr;
 | 
				
			||||||
 | 
					    uint32_t el;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /* For EL0 and EL1, TBI is controlled by stage 1's TCR, so convert
 | 
				
			||||||
 | 
					       * a stage 1+2 mmu index into the appropriate stage 1 mmu index.
 | 
				
			||||||
 | 
					       */
 | 
				
			||||||
 | 
					    if (mmu_idx == ARMMMUIdx_S12NSE0 || mmu_idx == ARMMMUIdx_S12NSE1) {
 | 
				
			||||||
 | 
					        mmu_idx += ARMMMUIdx_S1NSE0;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    tcr = regime_tcr(env, mmu_idx);
 | 
				
			||||||
 | 
					    el = regime_el(env, mmu_idx);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (el > 1) {
 | 
				
			||||||
 | 
					        return 0;
 | 
				
			||||||
 | 
					    } else {
 | 
				
			||||||
 | 
					        return extract64(tcr->raw_tcr, 38, 1);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* Return the TTBR associated with this translation regime */
 | 
					/* Return the TTBR associated with this translation regime */
 | 
				
			||||||
static inline uint64_t regime_ttbr(CPUARMState *env, ARMMMUIdx mmu_idx,
 | 
					static inline uint64_t regime_ttbr(CPUARMState *env, ARMMMUIdx mmu_idx,
 | 
				
			||||||
                                   int ttbrn)
 | 
					                                   int ttbrn)
 | 
				
			||||||
 | 
				
			|||||||
@ -23,6 +23,7 @@
 | 
				
			|||||||
#include "internals.h"
 | 
					#include "internals.h"
 | 
				
			||||||
#include "hw/arm/arm.h"
 | 
					#include "hw/arm/arm.h"
 | 
				
			||||||
#include "exec/memattrs.h"
 | 
					#include "exec/memattrs.h"
 | 
				
			||||||
 | 
					#include "exec/address-spaces.h"
 | 
				
			||||||
#include "hw/boards.h"
 | 
					#include "hw/boards.h"
 | 
				
			||||||
#include "qemu/log.h"
 | 
					#include "qemu/log.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -283,7 +284,7 @@ void kvm_arm_register_device(MemoryRegion *mr, uint64_t devid, uint64_t group,
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (QSLIST_EMPTY(&kvm_devices_head)) {
 | 
					    if (QSLIST_EMPTY(&kvm_devices_head)) {
 | 
				
			||||||
        memory_listener_register(&devlistener, NULL);
 | 
					        memory_listener_register(&devlistener, &address_space_memory);
 | 
				
			||||||
        qemu_add_machine_init_done_notifier(¬ify);
 | 
					        qemu_add_machine_init_done_notifier(¬ify);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    kd = g_new0(KVMDevice, 1);
 | 
					    kd = g_new0(KVMDevice, 1);
 | 
				
			||||||
 | 
				
			|||||||
@ -479,6 +479,13 @@ void HELPER(cpsr_write_eret)(CPUARMState *env, uint32_t val)
 | 
				
			|||||||
{
 | 
					{
 | 
				
			||||||
    cpsr_write(env, val, CPSR_ERET_MASK, CPSRWriteExceptionReturn);
 | 
					    cpsr_write(env, val, CPSR_ERET_MASK, CPSRWriteExceptionReturn);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /* Generated code has already stored the new PC value, but
 | 
				
			||||||
 | 
					     * without masking out its low bits, because which bits need
 | 
				
			||||||
 | 
					     * masking depends on whether we're returning to Thumb or ARM
 | 
				
			||||||
 | 
					     * state. Do the masking now.
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    env->regs[15] &= (env->thumb ? ~1 : ~3);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    arm_call_el_change_hook(arm_env_get_cpu(env));
 | 
					    arm_call_el_change_hook(arm_env_get_cpu(env));
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										10
									
								
								target-arm/trace-events
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										10
									
								
								target-arm/trace-events
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,10 @@
 | 
				
			|||||||
 | 
					# See docs/tracing.txt for syntax documentation.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# target-arm/helper.c
 | 
				
			||||||
 | 
					arm_gt_recalc(int timer, int irqstate, uint64_t nexttick) "gt recalc: timer %d irqstate %d next tick %" PRIx64
 | 
				
			||||||
 | 
					arm_gt_recalc_disabled(int timer) "gt recalc: timer %d irqstate 0 timer disabled"
 | 
				
			||||||
 | 
					arm_gt_cval_write(int timer, uint64_t value) "gt_cval_write: timer %d value %" PRIx64
 | 
				
			||||||
 | 
					arm_gt_tval_write(int timer, uint64_t value) "gt_tval_write: timer %d value %" PRIx64
 | 
				
			||||||
 | 
					arm_gt_ctl_write(int timer, uint64_t value) "gt_ctl_write: timer %d value %" PRIx64
 | 
				
			||||||
 | 
					arm_gt_imask_toggle(int timer, int irqstate) "gt_ctl_write: timer %d IMASK toggle, new irqstate %d"
 | 
				
			||||||
 | 
					arm_gt_cntvoff_write(uint64_t value) "gt_cntvoff_write: value %" PRIx64
 | 
				
			||||||
@ -41,6 +41,7 @@ static TCGv_i64 cpu_pc;
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
/* Load/store exclusive handling */
 | 
					/* Load/store exclusive handling */
 | 
				
			||||||
static TCGv_i64 cpu_exclusive_high;
 | 
					static TCGv_i64 cpu_exclusive_high;
 | 
				
			||||||
 | 
					static TCGv_i64 cpu_reg(DisasContext *s, int reg);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static const char *regnames[] = {
 | 
					static const char *regnames[] = {
 | 
				
			||||||
    "x0", "x1", "x2", "x3", "x4", "x5", "x6", "x7",
 | 
					    "x0", "x1", "x2", "x3", "x4", "x5", "x6", "x7",
 | 
				
			||||||
@ -176,6 +177,76 @@ void gen_a64_set_pc_im(uint64_t val)
 | 
				
			|||||||
    tcg_gen_movi_i64(cpu_pc, val);
 | 
					    tcg_gen_movi_i64(cpu_pc, val);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Load the PC from a generic TCG variable.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * If address tagging is enabled via the TCR TBI bits, then loading
 | 
				
			||||||
 | 
					 * an address into the PC will clear out any tag in the it:
 | 
				
			||||||
 | 
					 *  + for EL2 and EL3 there is only one TBI bit, and if it is set
 | 
				
			||||||
 | 
					 *    then the address is zero-extended, clearing bits [63:56]
 | 
				
			||||||
 | 
					 *  + for EL0 and EL1, TBI0 controls addresses with bit 55 == 0
 | 
				
			||||||
 | 
					 *    and TBI1 controls addressses with bit 55 == 1.
 | 
				
			||||||
 | 
					 *    If the appropriate TBI bit is set for the address then
 | 
				
			||||||
 | 
					 *    the address is sign-extended from bit 55 into bits [63:56]
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * We can avoid doing this for relative-branches, because the
 | 
				
			||||||
 | 
					 * PC + offset can never overflow into the tag bits (assuming
 | 
				
			||||||
 | 
					 * that virtual addresses are less than 56 bits wide, as they
 | 
				
			||||||
 | 
					 * are currently), but we must handle it for branch-to-register.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					static void gen_a64_set_pc(DisasContext *s, TCGv_i64 src)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (s->current_el <= 1) {
 | 
				
			||||||
 | 
					        /* Test if NEITHER or BOTH TBI values are set.  If so, no need to
 | 
				
			||||||
 | 
					         * examine bit 55 of address, can just generate code.
 | 
				
			||||||
 | 
					         * If mixed, then test via generated code
 | 
				
			||||||
 | 
					         */
 | 
				
			||||||
 | 
					        if (s->tbi0 && s->tbi1) {
 | 
				
			||||||
 | 
					            TCGv_i64 tmp_reg = tcg_temp_new_i64();
 | 
				
			||||||
 | 
					            /* Both bits set, sign extension from bit 55 into [63:56] will
 | 
				
			||||||
 | 
					             * cover both cases
 | 
				
			||||||
 | 
					             */
 | 
				
			||||||
 | 
					            tcg_gen_shli_i64(tmp_reg, src, 8);
 | 
				
			||||||
 | 
					            tcg_gen_sari_i64(cpu_pc, tmp_reg, 8);
 | 
				
			||||||
 | 
					            tcg_temp_free_i64(tmp_reg);
 | 
				
			||||||
 | 
					        } else if (!s->tbi0 && !s->tbi1) {
 | 
				
			||||||
 | 
					            /* Neither bit set, just load it as-is */
 | 
				
			||||||
 | 
					            tcg_gen_mov_i64(cpu_pc, src);
 | 
				
			||||||
 | 
					        } else {
 | 
				
			||||||
 | 
					            TCGv_i64 tcg_tmpval = tcg_temp_new_i64();
 | 
				
			||||||
 | 
					            TCGv_i64 tcg_bit55  = tcg_temp_new_i64();
 | 
				
			||||||
 | 
					            TCGv_i64 tcg_zero   = tcg_const_i64(0);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            tcg_gen_andi_i64(tcg_bit55, src, (1ull << 55));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            if (s->tbi0) {
 | 
				
			||||||
 | 
					                /* tbi0==1, tbi1==0, so 0-fill upper byte if bit 55 = 0 */
 | 
				
			||||||
 | 
					                tcg_gen_andi_i64(tcg_tmpval, src,
 | 
				
			||||||
 | 
					                                 0x00FFFFFFFFFFFFFFull);
 | 
				
			||||||
 | 
					                tcg_gen_movcond_i64(TCG_COND_EQ, cpu_pc, tcg_bit55, tcg_zero,
 | 
				
			||||||
 | 
					                                    tcg_tmpval, src);
 | 
				
			||||||
 | 
					            } else {
 | 
				
			||||||
 | 
					                /* tbi0==0, tbi1==1, so 1-fill upper byte if bit 55 = 1 */
 | 
				
			||||||
 | 
					                tcg_gen_ori_i64(tcg_tmpval, src,
 | 
				
			||||||
 | 
					                                0xFF00000000000000ull);
 | 
				
			||||||
 | 
					                tcg_gen_movcond_i64(TCG_COND_NE, cpu_pc, tcg_bit55, tcg_zero,
 | 
				
			||||||
 | 
					                                    tcg_tmpval, src);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            tcg_temp_free_i64(tcg_zero);
 | 
				
			||||||
 | 
					            tcg_temp_free_i64(tcg_bit55);
 | 
				
			||||||
 | 
					            tcg_temp_free_i64(tcg_tmpval);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    } else {  /* EL > 1 */
 | 
				
			||||||
 | 
					        if (s->tbi0) {
 | 
				
			||||||
 | 
					            /* Force tag byte to all zero */
 | 
				
			||||||
 | 
					            tcg_gen_andi_i64(cpu_pc, src, 0x00FFFFFFFFFFFFFFull);
 | 
				
			||||||
 | 
					        } else {
 | 
				
			||||||
 | 
					            /* Load unmodified address */
 | 
				
			||||||
 | 
					            tcg_gen_mov_i64(cpu_pc, src);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
typedef struct DisasCompare64 {
 | 
					typedef struct DisasCompare64 {
 | 
				
			||||||
    TCGCond cond;
 | 
					    TCGCond cond;
 | 
				
			||||||
    TCGv_i64 value;
 | 
					    TCGv_i64 value;
 | 
				
			||||||
@ -1596,12 +1667,12 @@ static void disas_exc(DisasContext *s, uint32_t insn)
 | 
				
			|||||||
         * instruction works properly.
 | 
					         * instruction works properly.
 | 
				
			||||||
         */
 | 
					         */
 | 
				
			||||||
        switch (op2_ll) {
 | 
					        switch (op2_ll) {
 | 
				
			||||||
        case 1:
 | 
					        case 1:                                                     /* SVC */
 | 
				
			||||||
            gen_ss_advance(s);
 | 
					            gen_ss_advance(s);
 | 
				
			||||||
            gen_exception_insn(s, 0, EXCP_SWI, syn_aa64_svc(imm16),
 | 
					            gen_exception_insn(s, 0, EXCP_SWI, syn_aa64_svc(imm16),
 | 
				
			||||||
                               default_exception_el(s));
 | 
					                               default_exception_el(s));
 | 
				
			||||||
            break;
 | 
					            break;
 | 
				
			||||||
        case 2:
 | 
					        case 2:                                                     /* HVC */
 | 
				
			||||||
            if (s->current_el == 0) {
 | 
					            if (s->current_el == 0) {
 | 
				
			||||||
                unallocated_encoding(s);
 | 
					                unallocated_encoding(s);
 | 
				
			||||||
                break;
 | 
					                break;
 | 
				
			||||||
@ -1614,7 +1685,7 @@ static void disas_exc(DisasContext *s, uint32_t insn)
 | 
				
			|||||||
            gen_ss_advance(s);
 | 
					            gen_ss_advance(s);
 | 
				
			||||||
            gen_exception_insn(s, 0, EXCP_HVC, syn_aa64_hvc(imm16), 2);
 | 
					            gen_exception_insn(s, 0, EXCP_HVC, syn_aa64_hvc(imm16), 2);
 | 
				
			||||||
            break;
 | 
					            break;
 | 
				
			||||||
        case 3:
 | 
					        case 3:                                                     /* SMC */
 | 
				
			||||||
            if (s->current_el == 0) {
 | 
					            if (s->current_el == 0) {
 | 
				
			||||||
                unallocated_encoding(s);
 | 
					                unallocated_encoding(s);
 | 
				
			||||||
                break;
 | 
					                break;
 | 
				
			||||||
@ -1704,12 +1775,13 @@ static void disas_uncond_b_reg(DisasContext *s, uint32_t insn)
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    switch (opc) {
 | 
					    switch (opc) {
 | 
				
			||||||
    case 0: /* BR */
 | 
					    case 0: /* BR */
 | 
				
			||||||
    case 2: /* RET */
 | 
					 | 
				
			||||||
        tcg_gen_mov_i64(cpu_pc, cpu_reg(s, rn));
 | 
					 | 
				
			||||||
        break;
 | 
					 | 
				
			||||||
    case 1: /* BLR */
 | 
					    case 1: /* BLR */
 | 
				
			||||||
        tcg_gen_mov_i64(cpu_pc, cpu_reg(s, rn));
 | 
					    case 2: /* RET */
 | 
				
			||||||
 | 
					        gen_a64_set_pc(s, cpu_reg(s, rn));
 | 
				
			||||||
 | 
					        /* BLR also needs to load return address */
 | 
				
			||||||
 | 
					        if (opc == 1) {
 | 
				
			||||||
            tcg_gen_movi_i64(cpu_reg(s, 30), s->pc);
 | 
					            tcg_gen_movi_i64(cpu_reg(s, 30), s->pc);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
        break;
 | 
					        break;
 | 
				
			||||||
    case 4: /* ERET */
 | 
					    case 4: /* ERET */
 | 
				
			||||||
        if (s->current_el == 0) {
 | 
					        if (s->current_el == 0) {
 | 
				
			||||||
@ -11175,6 +11247,8 @@ void gen_intermediate_code_a64(ARMCPU *cpu, TranslationBlock *tb)
 | 
				
			|||||||
    dc->condexec_mask = 0;
 | 
					    dc->condexec_mask = 0;
 | 
				
			||||||
    dc->condexec_cond = 0;
 | 
					    dc->condexec_cond = 0;
 | 
				
			||||||
    dc->mmu_idx = ARM_TBFLAG_MMUIDX(tb->flags);
 | 
					    dc->mmu_idx = ARM_TBFLAG_MMUIDX(tb->flags);
 | 
				
			||||||
 | 
					    dc->tbi0 = ARM_TBFLAG_TBI0(tb->flags);
 | 
				
			||||||
 | 
					    dc->tbi1 = ARM_TBFLAG_TBI1(tb->flags);
 | 
				
			||||||
    dc->current_el = arm_mmu_idx_to_el(dc->mmu_idx);
 | 
					    dc->current_el = arm_mmu_idx_to_el(dc->mmu_idx);
 | 
				
			||||||
#if !defined(CONFIG_USER_ONLY)
 | 
					#if !defined(CONFIG_USER_ONLY)
 | 
				
			||||||
    dc->user = (dc->current_el == 0);
 | 
					    dc->user = (dc->current_el == 0);
 | 
				
			||||||
 | 
				
			|||||||
@ -4363,26 +4363,35 @@ static void gen_mrs_banked(DisasContext *s, int r, int sysm, int rn)
 | 
				
			|||||||
    s->is_jmp = DISAS_UPDATE;
 | 
					    s->is_jmp = DISAS_UPDATE;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* Generate an old-style exception return. Marks pc as dead. */
 | 
					/* Store value to PC as for an exception return (ie don't
 | 
				
			||||||
static void gen_exception_return(DisasContext *s, TCGv_i32 pc)
 | 
					 * mask bits). The subsequent call to gen_helper_cpsr_write_eret()
 | 
				
			||||||
 | 
					 * will do the masking based on the new value of the Thumb bit.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					static void store_pc_exc_ret(DisasContext *s, TCGv_i32 pc)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    TCGv_i32 tmp;
 | 
					    tcg_gen_mov_i32(cpu_R[15], pc);
 | 
				
			||||||
    store_reg(s, 15, pc);
 | 
					    tcg_temp_free_i32(pc);
 | 
				
			||||||
    tmp = load_cpu_field(spsr);
 | 
					 | 
				
			||||||
    gen_helper_cpsr_write_eret(cpu_env, tmp);
 | 
					 | 
				
			||||||
    tcg_temp_free_i32(tmp);
 | 
					 | 
				
			||||||
    s->is_jmp = DISAS_JUMP;
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* Generate a v6 exception return.  Marks both values as dead.  */
 | 
					/* Generate a v6 exception return.  Marks both values as dead.  */
 | 
				
			||||||
static void gen_rfe(DisasContext *s, TCGv_i32 pc, TCGv_i32 cpsr)
 | 
					static void gen_rfe(DisasContext *s, TCGv_i32 pc, TCGv_i32 cpsr)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
 | 
					    store_pc_exc_ret(s, pc);
 | 
				
			||||||
 | 
					    /* The cpsr_write_eret helper will mask the low bits of PC
 | 
				
			||||||
 | 
					     * appropriately depending on the new Thumb bit, so it must
 | 
				
			||||||
 | 
					     * be called after storing the new PC.
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
    gen_helper_cpsr_write_eret(cpu_env, cpsr);
 | 
					    gen_helper_cpsr_write_eret(cpu_env, cpsr);
 | 
				
			||||||
    tcg_temp_free_i32(cpsr);
 | 
					    tcg_temp_free_i32(cpsr);
 | 
				
			||||||
    store_reg(s, 15, pc);
 | 
					 | 
				
			||||||
    s->is_jmp = DISAS_JUMP;
 | 
					    s->is_jmp = DISAS_JUMP;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Generate an old-style exception return. Marks pc as dead. */
 | 
				
			||||||
 | 
					static void gen_exception_return(DisasContext *s, TCGv_i32 pc)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    gen_rfe(s, pc, load_cpu_field(spsr));
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void gen_nop_hint(DisasContext *s, int val)
 | 
					static void gen_nop_hint(DisasContext *s, int val)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    switch (val) {
 | 
					    switch (val) {
 | 
				
			||||||
@ -9366,6 +9375,8 @@ static void disas_arm_insn(DisasContext *s, unsigned int insn)
 | 
				
			|||||||
                            } else if (i == rn) {
 | 
					                            } else if (i == rn) {
 | 
				
			||||||
                                loaded_var = tmp;
 | 
					                                loaded_var = tmp;
 | 
				
			||||||
                                loaded_base = 1;
 | 
					                                loaded_base = 1;
 | 
				
			||||||
 | 
					                            } else if (rn == 15 && exc_return) {
 | 
				
			||||||
 | 
					                                store_pc_exc_ret(s, tmp);
 | 
				
			||||||
                            } else {
 | 
					                            } else {
 | 
				
			||||||
                                store_reg_from_load(s, i, tmp);
 | 
					                                store_reg_from_load(s, i, tmp);
 | 
				
			||||||
                            }
 | 
					                            }
 | 
				
			||||||
 | 
				
			|||||||
@ -22,6 +22,8 @@ typedef struct DisasContext {
 | 
				
			|||||||
    int user;
 | 
					    int user;
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
    ARMMMUIdx mmu_idx; /* MMU index to use for normal loads/stores */
 | 
					    ARMMMUIdx mmu_idx; /* MMU index to use for normal loads/stores */
 | 
				
			||||||
 | 
					    bool tbi0;         /* TBI0 for EL0/1 or TBI for EL2/3 */
 | 
				
			||||||
 | 
					    bool tbi1;         /* TBI1 for EL0/1, not used for EL2/3 */
 | 
				
			||||||
    bool ns;        /* Use non-secure CPREG bank on access */
 | 
					    bool ns;        /* Use non-secure CPREG bank on access */
 | 
				
			||||||
    int fp_excp_el; /* FP exception EL or 0 if enabled */
 | 
					    int fp_excp_el; /* FP exception EL or 0 if enabled */
 | 
				
			||||||
    /* Flag indicating that exceptions from secure mode are routed to EL3. */
 | 
					    /* Flag indicating that exceptions from secure mode are routed to EL3. */
 | 
				
			||||||
 | 
				
			|||||||
@ -116,6 +116,8 @@ check-unit-$(CONFIG_REPLICATION) += tests/test-replication$(EXESUF)
 | 
				
			|||||||
check-unit-y += tests/test-bufferiszero$(EXESUF)
 | 
					check-unit-y += tests/test-bufferiszero$(EXESUF)
 | 
				
			||||||
gcov-files-check-bufferiszero-y = util/bufferiszero.c
 | 
					gcov-files-check-bufferiszero-y = util/bufferiszero.c
 | 
				
			||||||
check-unit-y += tests/test-uuid$(EXESUF)
 | 
					check-unit-y += tests/test-uuid$(EXESUF)
 | 
				
			||||||
 | 
					check-unit-y += tests/ptimer-test$(EXESUF)
 | 
				
			||||||
 | 
					gcov-files-ptimer-test-y = hw/core/ptimer.c
 | 
				
			||||||
 | 
					
 | 
				
			||||||
check-block-$(CONFIG_POSIX) += tests/qemu-iotests-quick.sh
 | 
					check-block-$(CONFIG_POSIX) += tests/qemu-iotests-quick.sh
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -295,6 +297,7 @@ check-qtest-sparc64-y = tests/endianness-test$(EXESUF)
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
check-qtest-arm-y = tests/tmp105-test$(EXESUF)
 | 
					check-qtest-arm-y = tests/tmp105-test$(EXESUF)
 | 
				
			||||||
check-qtest-arm-y += tests/ds1338-test$(EXESUF)
 | 
					check-qtest-arm-y += tests/ds1338-test$(EXESUF)
 | 
				
			||||||
 | 
					check-qtest-arm-y += tests/m25p80-test$(EXESUF)
 | 
				
			||||||
gcov-files-arm-y += hw/misc/tmp105.c
 | 
					gcov-files-arm-y += hw/misc/tmp105.c
 | 
				
			||||||
check-qtest-arm-y += tests/virtio-blk-test$(EXESUF)
 | 
					check-qtest-arm-y += tests/virtio-blk-test$(EXESUF)
 | 
				
			||||||
gcov-files-arm-y += arm-softmmu/hw/block/virtio-blk.c
 | 
					gcov-files-arm-y += arm-softmmu/hw/block/virtio-blk.c
 | 
				
			||||||
@ -306,7 +309,6 @@ check-qtest-xtensaeb-y = $(check-qtest-xtensa-y)
 | 
				
			|||||||
check-qtest-s390x-y = tests/boot-serial-test$(EXESUF)
 | 
					check-qtest-s390x-y = tests/boot-serial-test$(EXESUF)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
check-qtest-generic-y += tests/qom-test$(EXESUF)
 | 
					check-qtest-generic-y += tests/qom-test$(EXESUF)
 | 
				
			||||||
check-qtest-generic-y += tests/ptimer-test$(EXESUF)
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
qapi-schema += alternate-any.json
 | 
					qapi-schema += alternate-any.json
 | 
				
			||||||
qapi-schema += alternate-array.json
 | 
					qapi-schema += alternate-array.json
 | 
				
			||||||
@ -514,6 +516,7 @@ tests/test-timed-average$(EXESUF): tests/test-timed-average.o qemu-timer.o \
 | 
				
			|||||||
	$(test-util-obj-y)
 | 
						$(test-util-obj-y)
 | 
				
			||||||
tests/test-base64$(EXESUF): tests/test-base64.o \
 | 
					tests/test-base64$(EXESUF): tests/test-base64.o \
 | 
				
			||||||
	libqemuutil.a libqemustub.a
 | 
						libqemuutil.a libqemustub.a
 | 
				
			||||||
 | 
					tests/ptimer-test$(EXESUF): tests/ptimer-test.o tests/ptimer-test-stubs.o hw/core/ptimer.o libqemustub.a
 | 
				
			||||||
 | 
					
 | 
				
			||||||
tests/test-logging$(EXESUF): tests/test-logging.o $(test-util-obj-y)
 | 
					tests/test-logging$(EXESUF): tests/test-logging.o $(test-util-obj-y)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -626,6 +629,7 @@ tests/bios-tables-test$(EXESUF): tests/bios-tables-test.o \
 | 
				
			|||||||
tests/pxe-test$(EXESUF): tests/pxe-test.o tests/boot-sector.o $(libqos-obj-y)
 | 
					tests/pxe-test$(EXESUF): tests/pxe-test.o tests/boot-sector.o $(libqos-obj-y)
 | 
				
			||||||
tests/tmp105-test$(EXESUF): tests/tmp105-test.o $(libqos-omap-obj-y)
 | 
					tests/tmp105-test$(EXESUF): tests/tmp105-test.o $(libqos-omap-obj-y)
 | 
				
			||||||
tests/ds1338-test$(EXESUF): tests/ds1338-test.o $(libqos-imx-obj-y)
 | 
					tests/ds1338-test$(EXESUF): tests/ds1338-test.o $(libqos-imx-obj-y)
 | 
				
			||||||
 | 
					tests/m25p80-test$(EXESUF): tests/m25p80-test.o
 | 
				
			||||||
tests/i440fx-test$(EXESUF): tests/i440fx-test.o $(libqos-pc-obj-y)
 | 
					tests/i440fx-test$(EXESUF): tests/i440fx-test.o $(libqos-pc-obj-y)
 | 
				
			||||||
tests/q35-test$(EXESUF): tests/q35-test.o $(libqos-pc-obj-y)
 | 
					tests/q35-test$(EXESUF): tests/q35-test.o $(libqos-pc-obj-y)
 | 
				
			||||||
tests/fw_cfg-test$(EXESUF): tests/fw_cfg-test.o $(libqos-pc-obj-y)
 | 
					tests/fw_cfg-test$(EXESUF): tests/fw_cfg-test.o $(libqos-pc-obj-y)
 | 
				
			||||||
@ -675,7 +679,6 @@ tests/test-filter-redirector$(EXESUF): tests/test-filter-redirector.o $(qtest-ob
 | 
				
			|||||||
tests/test-x86-cpuid-compat$(EXESUF): tests/test-x86-cpuid-compat.o $(qtest-obj-y)
 | 
					tests/test-x86-cpuid-compat$(EXESUF): tests/test-x86-cpuid-compat.o $(qtest-obj-y)
 | 
				
			||||||
tests/ivshmem-test$(EXESUF): tests/ivshmem-test.o contrib/ivshmem-server/ivshmem-server.o $(libqos-pc-obj-y)
 | 
					tests/ivshmem-test$(EXESUF): tests/ivshmem-test.o contrib/ivshmem-server/ivshmem-server.o $(libqos-pc-obj-y)
 | 
				
			||||||
tests/vhost-user-bridge$(EXESUF): tests/vhost-user-bridge.o
 | 
					tests/vhost-user-bridge$(EXESUF): tests/vhost-user-bridge.o
 | 
				
			||||||
tests/ptimer-test$(EXESUF): tests/ptimer-test.o tests/ptimer-test-stubs.o hw/core/ptimer.o
 | 
					 | 
				
			||||||
tests/test-uuid$(EXESUF): tests/test-uuid.o $(test-util-obj-y)
 | 
					tests/test-uuid$(EXESUF): tests/test-uuid.o $(test-util-obj-y)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
tests/migration/stress$(EXESUF): tests/migration/stress.o
 | 
					tests/migration/stress$(EXESUF): tests/migration/stress.o
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										252
									
								
								tests/m25p80-test.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										252
									
								
								tests/m25p80-test.c
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,252 @@
 | 
				
			|||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * QTest testcase for the M25P80 Flash (Using the Aspeed SPI
 | 
				
			||||||
 | 
					 * Controller)
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Copyright (C) 2016 IBM Corp.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Permission is hereby granted, free of charge, to any person obtaining a copy
 | 
				
			||||||
 | 
					 * of this software and associated documentation files (the "Software"), to deal
 | 
				
			||||||
 | 
					 * in the Software without restriction, including without limitation the rights
 | 
				
			||||||
 | 
					 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 | 
				
			||||||
 | 
					 * copies of the Software, and to permit persons to whom the Software is
 | 
				
			||||||
 | 
					 * furnished to do so, subject to the following conditions:
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * The above copyright notice and this permission notice shall be included in
 | 
				
			||||||
 | 
					 * all copies or substantial portions of the Software.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 | 
				
			||||||
 | 
					 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 | 
				
			||||||
 | 
					 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
 | 
				
			||||||
 | 
					 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 | 
				
			||||||
 | 
					 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 | 
				
			||||||
 | 
					 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 | 
				
			||||||
 | 
					 * THE SOFTWARE.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "qemu/osdep.h"
 | 
				
			||||||
 | 
					#include "qemu/bswap.h"
 | 
				
			||||||
 | 
					#include "libqtest.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * ASPEED SPI Controller registers
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					#define R_CONF              0x00
 | 
				
			||||||
 | 
					#define   CONF_ENABLE_W0       (1 << 16)
 | 
				
			||||||
 | 
					#define R_CE_CTRL           0x04
 | 
				
			||||||
 | 
					#define   CRTL_EXTENDED0       0  /* 32 bit addressing for SPI */
 | 
				
			||||||
 | 
					#define R_CTRL0             0x10
 | 
				
			||||||
 | 
					#define   CTRL_CE_STOP_ACTIVE  (1 << 2)
 | 
				
			||||||
 | 
					#define   CTRL_USERMODE        0x3
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define ASPEED_FMC_BASE    0x1E620000
 | 
				
			||||||
 | 
					#define ASPEED_FLASH_BASE  0x20000000
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * Flash commands
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					enum {
 | 
				
			||||||
 | 
					    JEDEC_READ = 0x9f,
 | 
				
			||||||
 | 
					    BULK_ERASE = 0xc7,
 | 
				
			||||||
 | 
					    READ = 0x03,
 | 
				
			||||||
 | 
					    PP = 0x02,
 | 
				
			||||||
 | 
					    WREN = 0x6,
 | 
				
			||||||
 | 
					    EN_4BYTE_ADDR = 0xB7,
 | 
				
			||||||
 | 
					    ERASE_SECTOR = 0xd8,
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define FLASH_JEDEC         0x20ba19  /* n25q256a */
 | 
				
			||||||
 | 
					#define FLASH_SIZE          (32 * 1024 * 1024)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define PAGE_SIZE           256
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * Use an explicit bswap for the values read/wrote to the flash region
 | 
				
			||||||
 | 
					 * as they are BE and the Aspeed CPU is LE.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					static inline uint32_t make_be32(uint32_t data)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    return bswap32(data);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void spi_conf(uint32_t value)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    uint32_t conf = readl(ASPEED_FMC_BASE + R_CONF);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    conf |= value;
 | 
				
			||||||
 | 
					    writel(ASPEED_FMC_BASE + R_CONF, conf);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void spi_ctrl_start_user(void)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    uint32_t ctrl = readl(ASPEED_FMC_BASE + R_CTRL0);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    ctrl |= CTRL_USERMODE | CTRL_CE_STOP_ACTIVE;
 | 
				
			||||||
 | 
					    writel(ASPEED_FMC_BASE + R_CTRL0, ctrl);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    ctrl &= ~CTRL_CE_STOP_ACTIVE;
 | 
				
			||||||
 | 
					    writel(ASPEED_FMC_BASE + R_CTRL0, ctrl);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void spi_ctrl_stop_user(void)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    uint32_t ctrl = readl(ASPEED_FMC_BASE + R_CTRL0);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    ctrl |= CTRL_USERMODE | CTRL_CE_STOP_ACTIVE;
 | 
				
			||||||
 | 
					    writel(ASPEED_FMC_BASE + R_CTRL0, ctrl);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void test_read_jedec(void)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    uint32_t jedec = 0x0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    spi_conf(CONF_ENABLE_W0);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    spi_ctrl_start_user();
 | 
				
			||||||
 | 
					    writeb(ASPEED_FLASH_BASE, JEDEC_READ);
 | 
				
			||||||
 | 
					    jedec |= readb(ASPEED_FLASH_BASE) << 16;
 | 
				
			||||||
 | 
					    jedec |= readb(ASPEED_FLASH_BASE) << 8;
 | 
				
			||||||
 | 
					    jedec |= readb(ASPEED_FLASH_BASE);
 | 
				
			||||||
 | 
					    spi_ctrl_stop_user();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    g_assert_cmphex(jedec, ==, FLASH_JEDEC);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void read_page(uint32_t addr, uint32_t *page)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    int i;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    spi_ctrl_start_user();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    writeb(ASPEED_FLASH_BASE, EN_4BYTE_ADDR);
 | 
				
			||||||
 | 
					    writeb(ASPEED_FLASH_BASE, READ);
 | 
				
			||||||
 | 
					    writel(ASPEED_FLASH_BASE, make_be32(addr));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /* Continuous read are supported */
 | 
				
			||||||
 | 
					    for (i = 0; i < PAGE_SIZE / 4; i++) {
 | 
				
			||||||
 | 
					        page[i] = make_be32(readl(ASPEED_FLASH_BASE));
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    spi_ctrl_stop_user();
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void test_erase_sector(void)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    uint32_t some_page_addr = 0x600 * PAGE_SIZE;
 | 
				
			||||||
 | 
					    uint32_t page[PAGE_SIZE / 4];
 | 
				
			||||||
 | 
					    int i;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    spi_conf(CONF_ENABLE_W0);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    spi_ctrl_start_user();
 | 
				
			||||||
 | 
					    writeb(ASPEED_FLASH_BASE, WREN);
 | 
				
			||||||
 | 
					    writeb(ASPEED_FLASH_BASE, EN_4BYTE_ADDR);
 | 
				
			||||||
 | 
					    writeb(ASPEED_FLASH_BASE, ERASE_SECTOR);
 | 
				
			||||||
 | 
					    writel(ASPEED_FLASH_BASE, make_be32(some_page_addr));
 | 
				
			||||||
 | 
					    spi_ctrl_stop_user();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /* Previous page should be full of zeroes as backend is not
 | 
				
			||||||
 | 
					     * initialized */
 | 
				
			||||||
 | 
					    read_page(some_page_addr - PAGE_SIZE, page);
 | 
				
			||||||
 | 
					    for (i = 0; i < PAGE_SIZE / 4; i++) {
 | 
				
			||||||
 | 
					        g_assert_cmphex(page[i], ==, 0x0);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /* But this one was erased */
 | 
				
			||||||
 | 
					    read_page(some_page_addr, page);
 | 
				
			||||||
 | 
					    for (i = 0; i < PAGE_SIZE / 4; i++) {
 | 
				
			||||||
 | 
					        g_assert_cmphex(page[i], ==, 0xffffffff);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void test_erase_all(void)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    uint32_t some_page_addr = 0x15000 * PAGE_SIZE;
 | 
				
			||||||
 | 
					    uint32_t page[PAGE_SIZE / 4];
 | 
				
			||||||
 | 
					    int i;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    spi_conf(CONF_ENABLE_W0);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /* Check some random page. Should be full of zeroes as backend is
 | 
				
			||||||
 | 
					     * not initialized */
 | 
				
			||||||
 | 
					    read_page(some_page_addr, page);
 | 
				
			||||||
 | 
					    for (i = 0; i < PAGE_SIZE / 4; i++) {
 | 
				
			||||||
 | 
					        g_assert_cmphex(page[i], ==, 0x0);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    spi_ctrl_start_user();
 | 
				
			||||||
 | 
					    writeb(ASPEED_FLASH_BASE, WREN);
 | 
				
			||||||
 | 
					    writeb(ASPEED_FLASH_BASE, BULK_ERASE);
 | 
				
			||||||
 | 
					    spi_ctrl_stop_user();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /* Recheck that some random page */
 | 
				
			||||||
 | 
					    read_page(some_page_addr, page);
 | 
				
			||||||
 | 
					    for (i = 0; i < PAGE_SIZE / 4; i++) {
 | 
				
			||||||
 | 
					        g_assert_cmphex(page[i], ==, 0xffffffff);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void test_write_page(void)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    uint32_t my_page_addr = 0x14000 * PAGE_SIZE; /* beyond 16MB */
 | 
				
			||||||
 | 
					    uint32_t some_page_addr = 0x15000 * PAGE_SIZE;
 | 
				
			||||||
 | 
					    uint32_t page[PAGE_SIZE / 4];
 | 
				
			||||||
 | 
					    int i;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    spi_conf(CONF_ENABLE_W0);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    spi_ctrl_start_user();
 | 
				
			||||||
 | 
					    writeb(ASPEED_FLASH_BASE, EN_4BYTE_ADDR);
 | 
				
			||||||
 | 
					    writeb(ASPEED_FLASH_BASE, PP);
 | 
				
			||||||
 | 
					    writel(ASPEED_FLASH_BASE, make_be32(my_page_addr));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /* Fill the page with its own addresses */
 | 
				
			||||||
 | 
					    for (i = 0; i < PAGE_SIZE / 4; i++) {
 | 
				
			||||||
 | 
					        writel(ASPEED_FLASH_BASE, make_be32(my_page_addr + i * 4));
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    spi_ctrl_stop_user();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /* Check what was written */
 | 
				
			||||||
 | 
					    read_page(my_page_addr, page);
 | 
				
			||||||
 | 
					    for (i = 0; i < PAGE_SIZE / 4; i++) {
 | 
				
			||||||
 | 
					        g_assert_cmphex(page[i], ==, my_page_addr + i * 4);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /* Check some other page. It should be full of 0xff */
 | 
				
			||||||
 | 
					    read_page(some_page_addr, page);
 | 
				
			||||||
 | 
					    for (i = 0; i < PAGE_SIZE / 4; i++) {
 | 
				
			||||||
 | 
					        g_assert_cmphex(page[i], ==, 0xffffffff);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static char tmp_path[] = "/tmp/qtest.m25p80.XXXXXX";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int main(int argc, char **argv)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    int ret;
 | 
				
			||||||
 | 
					    int fd;
 | 
				
			||||||
 | 
					    char *args;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    g_test_init(&argc, &argv, NULL);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    fd = mkstemp(tmp_path);
 | 
				
			||||||
 | 
					    g_assert(fd >= 0);
 | 
				
			||||||
 | 
					    ret = ftruncate(fd, FLASH_SIZE);
 | 
				
			||||||
 | 
					    g_assert(ret == 0);
 | 
				
			||||||
 | 
					    close(fd);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    args = g_strdup_printf("-m 256 -machine palmetto-bmc "
 | 
				
			||||||
 | 
					                           "-drive file=%s,format=raw,if=mtd",
 | 
				
			||||||
 | 
					                           tmp_path);
 | 
				
			||||||
 | 
					    qtest_start(args);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    qtest_add_func("/m25p80/read_jedec", test_read_jedec);
 | 
				
			||||||
 | 
					    qtest_add_func("/m25p80/erase_sector", test_erase_sector);
 | 
				
			||||||
 | 
					    qtest_add_func("/m25p80/erase_all",  test_erase_all);
 | 
				
			||||||
 | 
					    qtest_add_func("/m25p80/write_page", test_write_page);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    ret = g_test_run();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    qtest_quit(global_qtest);
 | 
				
			||||||
 | 
					    unlink(tmp_path);
 | 
				
			||||||
 | 
					    g_free(args);
 | 
				
			||||||
 | 
					    return ret;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -11,9 +11,16 @@
 | 
				
			|||||||
#include "qemu/osdep.h"
 | 
					#include "qemu/osdep.h"
 | 
				
			||||||
#include "qemu/main-loop.h"
 | 
					#include "qemu/main-loop.h"
 | 
				
			||||||
#include "sysemu/replay.h"
 | 
					#include "sysemu/replay.h"
 | 
				
			||||||
 | 
					#include "migration/vmstate.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include "ptimer-test.h"
 | 
					#include "ptimer-test.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const VMStateInfo vmstate_info_uint8;
 | 
				
			||||||
 | 
					const VMStateInfo vmstate_info_uint32;
 | 
				
			||||||
 | 
					const VMStateInfo vmstate_info_uint64;
 | 
				
			||||||
 | 
					const VMStateInfo vmstate_info_int64;
 | 
				
			||||||
 | 
					const VMStateInfo vmstate_info_timer;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct QEMUBH {
 | 
					struct QEMUBH {
 | 
				
			||||||
    QEMUBHFunc *cb;
 | 
					    QEMUBHFunc *cb;
 | 
				
			||||||
    void *opaque;
 | 
					    void *opaque;
 | 
				
			||||||
 | 
				
			|||||||
@ -505,47 +505,47 @@ static void add_ptimer_tests(uint8_t policy)
 | 
				
			|||||||
        g_sprintf(policy_name, "default");
 | 
					        g_sprintf(policy_name, "default");
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    qtest_add_data_func(
 | 
					    g_test_add_data_func(
 | 
				
			||||||
        g_strdup_printf("/ptimer/set_count policy=%s", policy_name),
 | 
					        g_strdup_printf("/ptimer/set_count policy=%s", policy_name),
 | 
				
			||||||
        ppolicy, check_set_count);
 | 
					        ppolicy, check_set_count);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    qtest_add_data_func(
 | 
					    g_test_add_data_func(
 | 
				
			||||||
        g_strdup_printf("/ptimer/set_limit policy=%s", policy_name),
 | 
					        g_strdup_printf("/ptimer/set_limit policy=%s", policy_name),
 | 
				
			||||||
        ppolicy, check_set_limit);
 | 
					        ppolicy, check_set_limit);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    qtest_add_data_func(
 | 
					    g_test_add_data_func(
 | 
				
			||||||
        g_strdup_printf("/ptimer/oneshot policy=%s", policy_name),
 | 
					        g_strdup_printf("/ptimer/oneshot policy=%s", policy_name),
 | 
				
			||||||
        ppolicy, check_oneshot);
 | 
					        ppolicy, check_oneshot);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    qtest_add_data_func(
 | 
					    g_test_add_data_func(
 | 
				
			||||||
        g_strdup_printf("/ptimer/periodic policy=%s", policy_name),
 | 
					        g_strdup_printf("/ptimer/periodic policy=%s", policy_name),
 | 
				
			||||||
        ppolicy, check_periodic);
 | 
					        ppolicy, check_periodic);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    qtest_add_data_func(
 | 
					    g_test_add_data_func(
 | 
				
			||||||
        g_strdup_printf("/ptimer/on_the_fly_mode_change policy=%s", policy_name),
 | 
					        g_strdup_printf("/ptimer/on_the_fly_mode_change policy=%s", policy_name),
 | 
				
			||||||
        ppolicy, check_on_the_fly_mode_change);
 | 
					        ppolicy, check_on_the_fly_mode_change);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    qtest_add_data_func(
 | 
					    g_test_add_data_func(
 | 
				
			||||||
        g_strdup_printf("/ptimer/on_the_fly_period_change policy=%s", policy_name),
 | 
					        g_strdup_printf("/ptimer/on_the_fly_period_change policy=%s", policy_name),
 | 
				
			||||||
        ppolicy, check_on_the_fly_period_change);
 | 
					        ppolicy, check_on_the_fly_period_change);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    qtest_add_data_func(
 | 
					    g_test_add_data_func(
 | 
				
			||||||
        g_strdup_printf("/ptimer/on_the_fly_freq_change policy=%s", policy_name),
 | 
					        g_strdup_printf("/ptimer/on_the_fly_freq_change policy=%s", policy_name),
 | 
				
			||||||
        ppolicy, check_on_the_fly_freq_change);
 | 
					        ppolicy, check_on_the_fly_freq_change);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    qtest_add_data_func(
 | 
					    g_test_add_data_func(
 | 
				
			||||||
        g_strdup_printf("/ptimer/run_with_period_0 policy=%s", policy_name),
 | 
					        g_strdup_printf("/ptimer/run_with_period_0 policy=%s", policy_name),
 | 
				
			||||||
        ppolicy, check_run_with_period_0);
 | 
					        ppolicy, check_run_with_period_0);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    qtest_add_data_func(
 | 
					    g_test_add_data_func(
 | 
				
			||||||
        g_strdup_printf("/ptimer/run_with_delta_0 policy=%s", policy_name),
 | 
					        g_strdup_printf("/ptimer/run_with_delta_0 policy=%s", policy_name),
 | 
				
			||||||
        ppolicy, check_run_with_delta_0);
 | 
					        ppolicy, check_run_with_delta_0);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    qtest_add_data_func(
 | 
					    g_test_add_data_func(
 | 
				
			||||||
        g_strdup_printf("/ptimer/periodic_with_load_0 policy=%s", policy_name),
 | 
					        g_strdup_printf("/ptimer/periodic_with_load_0 policy=%s", policy_name),
 | 
				
			||||||
        ppolicy, check_periodic_with_load_0);
 | 
					        ppolicy, check_periodic_with_load_0);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    qtest_add_data_func(
 | 
					    g_test_add_data_func(
 | 
				
			||||||
        g_strdup_printf("/ptimer/oneshot_with_load_0 policy=%s", policy_name),
 | 
					        g_strdup_printf("/ptimer/oneshot_with_load_0 policy=%s", policy_name),
 | 
				
			||||||
        ppolicy, check_oneshot_with_load_0);
 | 
					        ppolicy, check_oneshot_with_load_0);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										5
									
								
								vl.c
									
									
									
									
									
								
							
							
						
						
									
										5
									
								
								vl.c
									
									
									
									
									
								
							@ -4389,11 +4389,6 @@ int main(int argc, char **argv, char **envp)
 | 
				
			|||||||
        exit(1);
 | 
					        exit(1);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (!linux_boot && qemu_opt_get(machine_opts, "dtb")) {
 | 
					 | 
				
			||||||
        error_report("-dtb only allowed with -kernel option");
 | 
					 | 
				
			||||||
        exit(1);
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    if (semihosting_enabled() && !semihosting_get_argc() && kernel_filename) {
 | 
					    if (semihosting_enabled() && !semihosting_get_argc() && kernel_filename) {
 | 
				
			||||||
        /* fall back to the -kernel/-append */
 | 
					        /* fall back to the -kernel/-append */
 | 
				
			||||||
        semihosting_arg_fallback(kernel_filename, kernel_cmdline);
 | 
					        semihosting_arg_fallback(kernel_filename, kernel_cmdline);
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user