提交 e678c56f 编写于 作者: P Peter Maydell

Merge remote-tracking branch 'remotes/pmaydell/tags/pull-target-arm-20160922' into staging

target-arm queue:
 * add Cortex-A7 CPU
 * new ast2500 SoC model and evaluation board
 * palmetto-bmc: remove stray double assignment
 * aspeed: clean up RAM size handling
 * ptimer: framework for defining policy bits to change
   behaviour choices for different timer devices
 * ptimer: add some test cases
 * cadence_gem: add queue support
 * loader: support loading images to specified address spaces
 * loader: support auto-detect of ELF architecture from file
 * dma: xlnx-zynq-devcfg: Fix up XLNX_ZYNQ_DEVCFG_R_MAX
 * vmstateify ssd0323
 * vmstateify ssi-sd
 * disas/arm.c: remove unused macros
 * imx: use 'const char', not 'char const'

# gpg: Signature made Thu 22 Sep 2016 18:20:22 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-20160922: (36 commits)
  imx: Use 'const char', not 'char const'
  disas/arm.c: Remove unused macro definitions
  vmstateify ssi-sd
  vmstateify ssd0323 display
  dma: xlnx-zynq-devcfg: Fix up XLNX_ZYNQ_DEVCFG_R_MAX
  loader: Add AddressSpace loading support to targphys
  loader: Add AddressSpace loading support to uImages
  loader: Add AddressSpace loading support to ELFs
  loader: Allow a custom AddressSpace when loading ROMs
  loader: Use the specified MemoryRegion
  loader: Allow ELF loader to auto-detect the ELF arch
  xlnx-zynqmp: Set the number of priority queues
  cadence_gem: Correct indentation
  cadence_gem: Add queue support
  cadence_gem: Add support for screening
  cadence_gem: Add the num-priority-queues property
  cadence_gem: QOMify Cadence GEM
  tests: Add ptimer tests
  hw/ptimer: Suppress error messages under qtest
  hw/ptimer: Introduce timer policy feature
  ...
Signed-off-by: NPeter Maydell <peter.maydell@linaro.org>
......@@ -24,7 +24,6 @@
#include "qemu/osdep.h"
#include "disas/bfd.h"
#define ISSPACE(x) ((x) == ' ' || (x) == '\t' || (x) == '\n')
#define ARM_EXT_V1 0
#define ARM_EXT_V2 0
......@@ -73,15 +72,6 @@ static void floatformat_to_double (unsigned char *data, double *dest)
/* End of qemu specific additions. */
/* FIXME: Belongs in global header. */
#ifndef strneq
#define strneq(a,b,n) (strncmp ((a), (b), (n)) == 0)
#endif
#ifndef NUM_ELEM
#define NUM_ELEM(a) (sizeof (a) / sizeof (a)[0])
#endif
struct opcode32
{
unsigned long arch; /* Architecture defining this insn. */
......@@ -1528,7 +1518,6 @@ static const char *const iwmmxt_cregnames[] =
/* Default to GCC register name set. */
static unsigned int regname_selected = 1;
#define NUM_ARM_REGNAMES NUM_ELEM (regnames)
#define arm_regnames regnames[regname_selected].reg_names
static bfd_boolean force_thumb = false;
......
......@@ -17,4 +17,4 @@ obj-$(CONFIG_XLNX_ZYNQMP) += xlnx-zynqmp.o xlnx-ep108.o
obj-$(CONFIG_FSL_IMX25) += fsl-imx25.o imx25_pdk.o
obj-$(CONFIG_FSL_IMX31) += fsl-imx31.o kzm.o
obj-$(CONFIG_FSL_IMX6) += fsl-imx6.o sabrelite.o
obj-$(CONFIG_ASPEED_SOC) += ast2400.o palmetto-bmc.o
obj-$(CONFIG_ASPEED_SOC) += aspeed_soc.o aspeed.o
......@@ -15,24 +15,61 @@
#include "cpu.h"
#include "exec/address-spaces.h"
#include "hw/arm/arm.h"
#include "hw/arm/ast2400.h"
#include "hw/arm/aspeed_soc.h"
#include "hw/boards.h"
#include "qemu/log.h"
#include "sysemu/block-backend.h"
#include "sysemu/blockdev.h"
static struct arm_boot_info palmetto_bmc_binfo = {
.loader_start = AST2400_SDRAM_BASE,
.board_id = 0,
static struct arm_boot_info aspeed_board_binfo = {
.board_id = -1, /* device-tree-only board */
.nb_cpus = 1,
};
typedef struct PalmettoBMCState {
AST2400State soc;
typedef struct AspeedBoardState {
AspeedSoCState soc;
MemoryRegion ram;
} PalmettoBMCState;
} AspeedBoardState;
static void palmetto_bmc_init_flashes(AspeedSMCState *s, const char *flashtype,
typedef struct AspeedBoardConfig {
const char *soc_name;
uint32_t hw_strap1;
} AspeedBoardConfig;
enum {
PALMETTO_BMC,
AST2500_EVB,
};
#define PALMETTO_BMC_HW_STRAP1 ( \
SCU_AST2400_HW_STRAP_DRAM_SIZE(DRAM_SIZE_256MB) | \
SCU_AST2400_HW_STRAP_DRAM_CONFIG(2 /* DDR3 with CL=6, CWL=5 */) | \
SCU_AST2400_HW_STRAP_ACPI_DIS | \
SCU_AST2400_HW_STRAP_SET_CLK_SOURCE(AST2400_CLK_48M_IN) | \
SCU_HW_STRAP_VGA_CLASS_CODE | \
SCU_HW_STRAP_LPC_RESET_PIN | \
SCU_HW_STRAP_SPI_MODE(SCU_HW_STRAP_SPI_M_S_EN) | \
SCU_AST2400_HW_STRAP_SET_CPU_AHB_RATIO(AST2400_CPU_AHB_RATIO_2_1) | \
SCU_HW_STRAP_SPI_WIDTH | \
SCU_HW_STRAP_VGA_SIZE_SET(VGA_16M_DRAM) | \
SCU_AST2400_HW_STRAP_BOOT_MODE(AST2400_SPI_BOOT))
#define AST2500_EVB_HW_STRAP1 (( \
AST2500_HW_STRAP1_DEFAULTS | \
SCU_AST2500_HW_STRAP_SPI_AUTOFETCH_ENABLE | \
SCU_AST2500_HW_STRAP_GPIO_STRAP_ENABLE | \
SCU_AST2500_HW_STRAP_UART_DEBUG | \
SCU_AST2500_HW_STRAP_DDR4_ENABLE | \
SCU_HW_STRAP_MAC1_RGMII | \
SCU_HW_STRAP_MAC0_RGMII) & \
~SCU_HW_STRAP_2ND_BOOT_WDT)
static const AspeedBoardConfig aspeed_boards[] = {
[PALMETTO_BMC] = { "ast2400-a0", PALMETTO_BMC_HW_STRAP1 },
[AST2500_EVB] = { "ast2500-a1", AST2500_EVB_HW_STRAP1 },
};
static void aspeed_board_init_flashes(AspeedSMCState *s, const char *flashtype,
Error **errp)
{
int i ;
......@@ -58,45 +95,103 @@ static void palmetto_bmc_init_flashes(AspeedSMCState *s, const char *flashtype,
}
}
static void palmetto_bmc_init(MachineState *machine)
static void aspeed_board_init(MachineState *machine,
const AspeedBoardConfig *cfg)
{
PalmettoBMCState *bmc;
AspeedBoardState *bmc;
AspeedSoCClass *sc;
bmc = g_new0(PalmettoBMCState, 1);
object_initialize(&bmc->soc, (sizeof(bmc->soc)), TYPE_AST2400);
bmc = g_new0(AspeedBoardState, 1);
object_initialize(&bmc->soc, (sizeof(bmc->soc)), cfg->soc_name);
object_property_add_child(OBJECT(machine), "soc", OBJECT(&bmc->soc),
&error_abort);
sc = ASPEED_SOC_GET_CLASS(&bmc->soc);
object_property_set_int(OBJECT(&bmc->soc), ram_size, "ram-size",
&error_abort);
object_property_set_int(OBJECT(&bmc->soc), cfg->hw_strap1, "hw-strap1",
&error_abort);
object_property_set_bool(OBJECT(&bmc->soc), true, "realized",
&error_abort);
/*
* Allocate RAM after the memory controller has checked the size
* was valid. If not, a default value is used.
*/
ram_size = object_property_get_int(OBJECT(&bmc->soc), "ram-size",
&error_abort);
memory_region_allocate_system_memory(&bmc->ram, NULL, "ram", ram_size);
memory_region_add_subregion(get_system_memory(), AST2400_SDRAM_BASE,
memory_region_add_subregion(get_system_memory(), sc->info->sdram_base,
&bmc->ram);
object_property_add_const_link(OBJECT(&bmc->soc), "ram", OBJECT(&bmc->ram),
&error_abort);
object_property_set_int(OBJECT(&bmc->soc), 0x120CE416, "hw-strap1",
&error_abort);
object_property_set_bool(OBJECT(&bmc->soc), true, "realized",
&error_abort);
palmetto_bmc_init_flashes(&bmc->soc.smc, "n25q256a", &error_abort);
palmetto_bmc_init_flashes(&bmc->soc.spi, "mx25l25635e", &error_abort);
aspeed_board_init_flashes(&bmc->soc.smc, "n25q256a", &error_abort);
aspeed_board_init_flashes(&bmc->soc.spi, "mx25l25635e", &error_abort);
aspeed_board_binfo.kernel_filename = machine->kernel_filename;
aspeed_board_binfo.initrd_filename = machine->initrd_filename;
aspeed_board_binfo.kernel_cmdline = machine->kernel_cmdline;
aspeed_board_binfo.ram_size = ram_size;
aspeed_board_binfo.loader_start = sc->info->sdram_base;
palmetto_bmc_binfo.kernel_filename = machine->kernel_filename;
palmetto_bmc_binfo.initrd_filename = machine->initrd_filename;
palmetto_bmc_binfo.kernel_cmdline = machine->kernel_cmdline;
palmetto_bmc_binfo.ram_size = ram_size;
arm_load_kernel(ARM_CPU(first_cpu), &palmetto_bmc_binfo);
arm_load_kernel(ARM_CPU(first_cpu), &aspeed_board_binfo);
}
static void palmetto_bmc_machine_init(MachineClass *mc)
static void palmetto_bmc_init(MachineState *machine)
{
mc->desc = "OpenPOWER Palmetto BMC";
aspeed_board_init(machine, &aspeed_boards[PALMETTO_BMC]);
}
static void palmetto_bmc_class_init(ObjectClass *oc, void *data)
{
MachineClass *mc = MACHINE_CLASS(oc);
mc->desc = "OpenPOWER Palmetto BMC (ARM926EJ-S)";
mc->init = palmetto_bmc_init;
mc->max_cpus = 1;
mc->no_sdcard = 1;
mc->no_floppy = 1;
mc->no_cdrom = 1;
mc->no_parallel = 1;
}
static const TypeInfo palmetto_bmc_type = {
.name = MACHINE_TYPE_NAME("palmetto-bmc"),
.parent = TYPE_MACHINE,
.class_init = palmetto_bmc_class_init,
};
static void ast2500_evb_init(MachineState *machine)
{
aspeed_board_init(machine, &aspeed_boards[AST2500_EVB]);
}
static void ast2500_evb_class_init(ObjectClass *oc, void *data)
{
MachineClass *mc = MACHINE_CLASS(oc);
mc->desc = "Aspeed AST2500 EVB (ARM1176)";
mc->init = ast2500_evb_init;
mc->max_cpus = 1;
mc->no_sdcard = 1;
mc->no_floppy = 1;
mc->no_cdrom = 1;
mc->no_parallel = 1;
}
DEFINE_MACHINE("palmetto-bmc", palmetto_bmc_machine_init);
static const TypeInfo ast2500_evb_type = {
.name = MACHINE_TYPE_NAME("ast2500-evb"),
.parent = TYPE_MACHINE,
.class_init = ast2500_evb_class_init,
};
static void aspeed_machine_init(void)
{
type_register_static(&palmetto_bmc_type);
type_register_static(&ast2500_evb_type);
}
type_init(aspeed_machine_init)
/*
* AST2400 SoC
* ASPEED SoC family
*
* Andrew Jeffery <andrew@aj.id.au>
* Jeremy Kerr <jk@ozlabs.org>
......@@ -15,59 +15,68 @@
#include "qemu-common.h"
#include "cpu.h"
#include "exec/address-spaces.h"
#include "hw/arm/ast2400.h"
#include "hw/arm/aspeed_soc.h"
#include "hw/char/serial.h"
#include "qemu/log.h"
#include "hw/i2c/aspeed_i2c.h"
#define AST2400_UART_5_BASE 0x00184000
#define AST2400_IOMEM_SIZE 0x00200000
#define AST2400_IOMEM_BASE 0x1E600000
#define AST2400_SMC_BASE AST2400_IOMEM_BASE /* Legacy SMC */
#define AST2400_FMC_BASE 0X1E620000
#define AST2400_SPI_BASE 0X1E630000
#define AST2400_VIC_BASE 0x1E6C0000
#define AST2400_SDMC_BASE 0x1E6E0000
#define AST2400_SCU_BASE 0x1E6E2000
#define AST2400_TIMER_BASE 0x1E782000
#define AST2400_I2C_BASE 0x1E78A000
#define AST2400_FMC_FLASH_BASE 0x20000000
#define AST2400_SPI_FLASH_BASE 0x30000000
#define ASPEED_SOC_UART_5_BASE 0x00184000
#define ASPEED_SOC_IOMEM_SIZE 0x00200000
#define ASPEED_SOC_IOMEM_BASE 0x1E600000
#define ASPEED_SOC_FMC_BASE 0x1E620000
#define ASPEED_SOC_SPI_BASE 0x1E630000
#define ASPEED_SOC_VIC_BASE 0x1E6C0000
#define ASPEED_SOC_SDMC_BASE 0x1E6E0000
#define ASPEED_SOC_SCU_BASE 0x1E6E2000
#define ASPEED_SOC_TIMER_BASE 0x1E782000
#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 timer_irqs[] = { 16, 17, 18, 35, 36, 37, 38, 39, };
#define AST2400_SDRAM_BASE 0x40000000
#define AST2500_SDRAM_BASE 0x80000000
static const AspeedSoCInfo aspeed_socs[] = {
{ "ast2400-a0", "arm926", AST2400_A0_SILICON_REV, AST2400_SDRAM_BASE },
{ "ast2400", "arm926", AST2400_A0_SILICON_REV, AST2400_SDRAM_BASE },
{ "ast2500-a1", "arm1176", AST2500_A1_SILICON_REV, AST2500_SDRAM_BASE },
};
/*
* IO handlers: simply catch any reads/writes to IO addresses that aren't
* handled by a device mapping.
*/
static uint64_t ast2400_io_read(void *p, hwaddr offset, unsigned size)
static uint64_t aspeed_soc_io_read(void *p, hwaddr offset, unsigned size)
{
qemu_log_mask(LOG_UNIMP, "%s: 0x%" HWADDR_PRIx " [%u]\n",
__func__, offset, size);
return 0;
}
static void ast2400_io_write(void *opaque, hwaddr offset, uint64_t value,
static void aspeed_soc_io_write(void *opaque, hwaddr offset, uint64_t value,
unsigned size)
{
qemu_log_mask(LOG_UNIMP, "%s: 0x%" HWADDR_PRIx " <- 0x%" PRIx64 " [%u]\n",
__func__, offset, value, size);
}
static const MemoryRegionOps ast2400_io_ops = {
.read = ast2400_io_read,
.write = ast2400_io_write,
static const MemoryRegionOps aspeed_soc_io_ops = {
.read = aspeed_soc_io_read,
.write = aspeed_soc_io_write,
.endianness = DEVICE_LITTLE_ENDIAN,
};
static void ast2400_init(Object *obj)
static void aspeed_soc_init(Object *obj)
{
AST2400State *s = AST2400(obj);
AspeedSoCState *s = ASPEED_SOC(obj);
AspeedSoCClass *sc = ASPEED_SOC_GET_CLASS(s);
s->cpu = cpu_arm_init("arm926");
s->cpu = cpu_arm_init(sc->info->cpu_model);
object_initialize(&s->vic, sizeof(s->vic), TYPE_ASPEED_VIC);
object_property_add_child(obj, "vic", OBJECT(&s->vic), NULL);
......@@ -85,7 +94,7 @@ static void ast2400_init(Object *obj)
object_property_add_child(obj, "scu", OBJECT(&s->scu), NULL);
qdev_set_parent_bus(DEVICE(&s->scu), sysbus_get_default());
qdev_prop_set_uint32(DEVICE(&s->scu), "silicon-rev",
AST2400_A0_SILICON_REV);
sc->info->silicon_rev);
object_property_add_alias(obj, "hw-strap1", OBJECT(&s->scu),
"hw-strap1", &error_abort);
object_property_add_alias(obj, "hw-strap2", OBJECT(&s->scu),
......@@ -103,20 +112,22 @@ static void ast2400_init(Object *obj)
object_property_add_child(obj, "sdmc", OBJECT(&s->sdmc), NULL);
qdev_set_parent_bus(DEVICE(&s->sdmc), sysbus_get_default());
qdev_prop_set_uint32(DEVICE(&s->sdmc), "silicon-rev",
AST2400_A0_SILICON_REV);
sc->info->silicon_rev);
object_property_add_alias(obj, "ram-size", OBJECT(&s->sdmc),
"ram-size", &error_abort);
}
static void ast2400_realize(DeviceState *dev, Error **errp)
static void aspeed_soc_realize(DeviceState *dev, Error **errp)
{
int i;
AST2400State *s = AST2400(dev);
AspeedSoCState *s = ASPEED_SOC(dev);
Error *err = NULL, *local_err = NULL;
/* IO space */
memory_region_init_io(&s->iomem, NULL, &ast2400_io_ops, NULL,
"ast2400.io", AST2400_IOMEM_SIZE);
memory_region_add_subregion_overlap(get_system_memory(), AST2400_IOMEM_BASE,
&s->iomem, -1);
memory_region_init_io(&s->iomem, NULL, &aspeed_soc_io_ops, NULL,
"aspeed_soc.io", ASPEED_SOC_IOMEM_SIZE);
memory_region_add_subregion_overlap(get_system_memory(),
ASPEED_SOC_IOMEM_BASE, &s->iomem, -1);
/* VIC */
object_property_set_bool(OBJECT(&s->vic), true, "realized", &err);
......@@ -124,7 +135,7 @@ static void ast2400_realize(DeviceState *dev, Error **errp)
error_propagate(errp, err);
return;
}
sysbus_mmio_map(SYS_BUS_DEVICE(&s->vic), 0, AST2400_VIC_BASE);
sysbus_mmio_map(SYS_BUS_DEVICE(&s->vic), 0, ASPEED_SOC_VIC_BASE);
sysbus_connect_irq(SYS_BUS_DEVICE(&s->vic), 0,
qdev_get_gpio_in(DEVICE(s->cpu), ARM_CPU_IRQ));
sysbus_connect_irq(SYS_BUS_DEVICE(&s->vic), 1,
......@@ -136,7 +147,7 @@ static void ast2400_realize(DeviceState *dev, Error **errp)
error_propagate(errp, err);
return;
}
sysbus_mmio_map(SYS_BUS_DEVICE(&s->timerctrl), 0, AST2400_TIMER_BASE);
sysbus_mmio_map(SYS_BUS_DEVICE(&s->timerctrl), 0, ASPEED_SOC_TIMER_BASE);
for (i = 0; i < ARRAY_SIZE(timer_irqs); i++) {
qemu_irq irq = qdev_get_gpio_in(DEVICE(&s->vic), timer_irqs[i]);
sysbus_connect_irq(SYS_BUS_DEVICE(&s->timerctrl), i, irq);
......@@ -148,12 +159,12 @@ static void ast2400_realize(DeviceState *dev, Error **errp)
error_propagate(errp, err);
return;
}
sysbus_mmio_map(SYS_BUS_DEVICE(&s->scu), 0, AST2400_SCU_BASE);
sysbus_mmio_map(SYS_BUS_DEVICE(&s->scu), 0, ASPEED_SOC_SCU_BASE);
/* UART - attach an 8250 to the IO space as our UART5 */
if (serial_hds[0]) {
qemu_irq uart5 = qdev_get_gpio_in(DEVICE(&s->vic), uart_irqs[4]);
serial_mm_init(&s->iomem, AST2400_UART_5_BASE, 2,
serial_mm_init(&s->iomem, ASPEED_SOC_UART_5_BASE, 2,
uart5, 38400, serial_hds[0], DEVICE_LITTLE_ENDIAN);
}
......@@ -163,7 +174,7 @@ static void ast2400_realize(DeviceState *dev, Error **errp)
error_propagate(errp, err);
return;
}
sysbus_mmio_map(SYS_BUS_DEVICE(&s->i2c), 0, AST2400_I2C_BASE);
sysbus_mmio_map(SYS_BUS_DEVICE(&s->i2c), 0, ASPEED_SOC_I2C_BASE);
sysbus_connect_irq(SYS_BUS_DEVICE(&s->i2c), 0,
qdev_get_gpio_in(DEVICE(&s->vic), 12));
......@@ -175,8 +186,8 @@ static void ast2400_realize(DeviceState *dev, Error **errp)
error_propagate(errp, err);
return;
}
sysbus_mmio_map(SYS_BUS_DEVICE(&s->smc), 0, AST2400_FMC_BASE);
sysbus_mmio_map(SYS_BUS_DEVICE(&s->smc), 1, AST2400_FMC_FLASH_BASE);
sysbus_mmio_map(SYS_BUS_DEVICE(&s->smc), 0, ASPEED_SOC_FMC_BASE);
sysbus_mmio_map(SYS_BUS_DEVICE(&s->smc), 1, ASPEED_SOC_FMC_FLASH_BASE);
sysbus_connect_irq(SYS_BUS_DEVICE(&s->smc), 0,
qdev_get_gpio_in(DEVICE(&s->vic), 19));
......@@ -188,8 +199,8 @@ static void ast2400_realize(DeviceState *dev, Error **errp)
error_propagate(errp, err);
return;
}
sysbus_mmio_map(SYS_BUS_DEVICE(&s->spi), 0, AST2400_SPI_BASE);
sysbus_mmio_map(SYS_BUS_DEVICE(&s->spi), 1, AST2400_SPI_FLASH_BASE);
sysbus_mmio_map(SYS_BUS_DEVICE(&s->spi), 0, ASPEED_SOC_SPI_BASE);
sysbus_mmio_map(SYS_BUS_DEVICE(&s->spi), 1, ASPEED_SOC_SPI_FLASH_BASE);
/* SDMC - SDRAM Memory Controller */
object_property_set_bool(OBJECT(&s->sdmc), true, "realized", &err);
......@@ -197,14 +208,16 @@ static void ast2400_realize(DeviceState *dev, Error **errp)
error_propagate(errp, err);
return;
}
sysbus_mmio_map(SYS_BUS_DEVICE(&s->sdmc), 0, AST2400_SDMC_BASE);
sysbus_mmio_map(SYS_BUS_DEVICE(&s->sdmc), 0, ASPEED_SOC_SDMC_BASE);
}
static void ast2400_class_init(ObjectClass *oc, void *data)
static void aspeed_soc_class_init(ObjectClass *oc, void *data)
{
DeviceClass *dc = DEVICE_CLASS(oc);
AspeedSoCClass *sc = ASPEED_SOC_CLASS(oc);
dc->realize = ast2400_realize;
sc->info = (AspeedSoCInfo *) data;
dc->realize = aspeed_soc_realize;
/*
* Reason: creates an ARM CPU, thus use after free(), see
......@@ -213,17 +226,29 @@ static void ast2400_class_init(ObjectClass *oc, void *data)
dc->cannot_destroy_with_object_finalize_yet = true;
}
static const TypeInfo ast2400_type_info = {
.name = TYPE_AST2400,
.parent = TYPE_SYS_BUS_DEVICE,
.instance_size = sizeof(AST2400State),
.instance_init = ast2400_init,
.class_init = ast2400_class_init,
static const TypeInfo aspeed_soc_type_info = {
.name = TYPE_ASPEED_SOC,
.parent = TYPE_DEVICE,
.instance_init = aspeed_soc_init,
.instance_size = sizeof(AspeedSoCState),
.class_size = sizeof(AspeedSoCClass),
.abstract = true,
};
static void ast2400_register_types(void)
static void aspeed_soc_register_types(void)
{
type_register_static(&ast2400_type_info);
int i;
type_register_static(&aspeed_soc_type_info);
for (i = 0; i < ARRAY_SIZE(aspeed_socs); ++i) {
TypeInfo ti = {
.name = aspeed_socs[i].name,
.parent = TYPE_ASPEED_SOC,
.class_init = aspeed_soc_class_init,
.class_data = (void *) &aspeed_socs[i],
};
type_register(&ti);
}
}
type_init(ast2400_register_types)
type_init(aspeed_soc_register_types)
......@@ -837,7 +837,7 @@ static void mv88w8618_timer_init(SysBusDevice *dev, mv88w8618_timer_state *s,
s->freq = freq;
bh = qemu_bh_new(mv88w8618_timer_tick, s);
s->ptimer = ptimer_init(bh);
s->ptimer = ptimer_init(bh, PTIMER_POLICY_DEFAULT);
}
static uint64_t mv88w8618_pit_read(void *opaque, hwaddr offset,
......
......@@ -332,6 +332,8 @@ static void xlnx_zynqmp_realize(DeviceState *dev, Error **errp)
qemu_check_nic_model(nd, TYPE_CADENCE_GEM);
qdev_set_nic_properties(DEVICE(&s->gem[i]), nd);
}
object_property_set_int(OBJECT(&s->gem[i]), 2, "num-priority-queues",
&error_abort);
object_property_set_bool(OBJECT(&s->gem[i]), true, "realized", &err);
if (err) {
error_propagate(errp, err);
......
......@@ -133,9 +133,15 @@ ssize_t read_targphys(const char *name,
return did;
}
/* return the size or -1 if error */
int load_image_targphys(const char *filename,
hwaddr addr, uint64_t max_sz)
{
return load_image_targphys_as(filename, addr, max_sz, NULL);
}
/* return the size or -1 if error */
int load_image_targphys_as(const char *filename,
hwaddr addr, uint64_t max_sz, AddressSpace *as)
{
int size;
......@@ -144,7 +150,7 @@ int load_image_targphys(const char *filename,
return -1;
}
if (size > 0) {
rom_add_file_fixed(filename, addr, -1);
rom_add_file_fixed_as(filename, addr, -1, as);
}
return size;
}
......@@ -416,6 +422,18 @@ int load_elf(const char *filename, uint64_t (*translate_fn)(void *, uint64_t),
void *translate_opaque, uint64_t *pentry, uint64_t *lowaddr,
uint64_t *highaddr, int big_endian, int elf_machine,
int clear_lsb, int data_swab)
{
return load_elf_as(filename, translate_fn, translate_opaque, pentry,
lowaddr, highaddr, big_endian, elf_machine, clear_lsb,
data_swab, NULL);
}
/* return < 0 if error, otherwise the number of bytes loaded in memory */
int load_elf_as(const char *filename,
uint64_t (*translate_fn)(void *, uint64_t),
void *translate_opaque, uint64_t *pentry, uint64_t *lowaddr,
uint64_t *highaddr, int big_endian, int elf_machine,
int clear_lsb, int data_swab, AddressSpace *as)
{
int fd, data_order, target_data_order, must_swab, ret = ELF_LOAD_FAILED;
uint8_t e_ident[EI_NIDENT];
......@@ -455,11 +473,11 @@ int load_elf(const char *filename, uint64_t (*translate_fn)(void *, uint64_t),
if (e_ident[EI_CLASS] == ELFCLASS64) {
ret = load_elf64(filename, fd, translate_fn, translate_opaque, must_swab,
pentry, lowaddr, highaddr, elf_machine, clear_lsb,
data_swab);
data_swab, as);
} else {
ret = load_elf32(filename, fd, translate_fn, translate_opaque, must_swab,
pentry, lowaddr, highaddr, elf_machine, clear_lsb,
data_swab);
data_swab, as);
}
fail:
......@@ -569,7 +587,7 @@ static ssize_t gunzip(void *dst, size_t dstlen, uint8_t *src,
static int load_uboot_image(const char *filename, hwaddr *ep, hwaddr *loadaddr,
int *is_linux, uint8_t image_type,
uint64_t (*translate_fn)(void *, uint64_t),
void *translate_opaque)
void *translate_opaque, AddressSpace *as)
{
int fd;
int size;
......@@ -670,7 +688,7 @@ static int load_uboot_image(const char *filename, hwaddr *ep, hwaddr *loadaddr,
hdr->ih_size = bytes;
}
rom_add_blob_fixed(filename, data, hdr->ih_size, address);
rom_add_blob_fixed_as(filename, data, hdr->ih_size, address, as);
ret = hdr->ih_size;
......@@ -686,14 +704,23 @@ int load_uimage(const char *filename, hwaddr *ep, hwaddr *loadaddr,
void *translate_opaque)
{
return load_uboot_image(filename, ep, loadaddr, is_linux, IH_TYPE_KERNEL,
translate_fn, translate_opaque);
translate_fn, translate_opaque, NULL);
}
int load_uimage_as(const char *filename, hwaddr *ep, hwaddr *loadaddr,
int *is_linux,
uint64_t (*translate_fn)(void *, uint64_t),
void *translate_opaque, AddressSpace *as)
{
return load_uboot_image(filename, ep, loadaddr, is_linux, IH_TYPE_KERNEL,
translate_fn, translate_opaque, as);
}
/* Load a ramdisk. */
int load_ramdisk(const char *filename, hwaddr addr, uint64_t max_sz)
{
return load_uboot_image(filename, NULL, &addr, NULL, IH_TYPE_RAMDISK,
NULL, NULL);
NULL, NULL, NULL);
}
/* Load a gzip-compressed kernel to a dynamically allocated buffer. */
......@@ -777,6 +804,7 @@ struct Rom {
uint8_t *data;
MemoryRegion *mr;
AddressSpace *as;
int isrom;
char *fw_dir;
char *fw_file;
......@@ -788,6 +816,12 @@ struct Rom {
static FWCfgState *fw_cfg;
static QTAILQ_HEAD(, Rom) roms = QTAILQ_HEAD_INITIALIZER(roms);
static inline bool rom_order_compare(Rom *rom, Rom *item)
{
return (rom->as > item->as) ||
(rom->as == item->as && rom->addr >= item->addr);
}
static void rom_insert(Rom *rom)
{
Rom *item;
......@@ -796,10 +830,16 @@ static void rom_insert(Rom *rom)
hw_error ("ROM images must be loaded at startup\n");
}
/* list is ordered by load address */
/* The user didn't specify an address space, this is the default */
if (!rom->as) {
rom->as = &address_space_memory;
}
/* List is ordered by load address in the same address space */
QTAILQ_FOREACH(item, &roms, next) {
if (rom->addr >= item->addr)
if (rom_order_compare(rom, item)) {
continue;
}
QTAILQ_INSERT_BEFORE(item, rom, next);
return;
}
......@@ -833,16 +873,25 @@ static void *rom_set_mr(Rom *rom, Object *owner, const char *name)
int rom_add_file(const char *file, const char *fw_dir,
hwaddr addr, int32_t bootindex,
bool option_rom, MemoryRegion *mr)
bool option_rom, MemoryRegion *mr,
AddressSpace *as)
{
MachineClass *mc = MACHINE_GET_CLASS(qdev_get_machine());
Rom *rom;
int rc, fd = -1;
char devpath[100];
if (as && mr) {
fprintf(stderr, "Specifying an Address Space and Memory Region is " \
"not valid when loading a rom\n");
/* We haven't allocated anything so we don't need any cleanup */
return -1;
}
rom = g_malloc0(sizeof(*rom));
rom->name = g_strdup(file);
rom->path = qemu_find_file(QEMU_FILE_TYPE_BIOS, rom->name);
rom->as = as;
if (rom->path == NULL) {
rom->path = g_strdup(file);
}
......@@ -969,7 +1018,7 @@ MemoryRegion *rom_add_blob(const char *name, const void *blob, size_t len,
* memory ownership of "data", so we don't have to allocate and copy the buffer.
*/
int rom_add_elf_program(const char *name, void *data, size_t datasize,
size_t romsize, hwaddr addr)
size_t romsize, hwaddr addr, AddressSpace *as)
{
Rom *rom;
......@@ -979,18 +1028,19 @@ int rom_add_elf_program(const char *name, void *data, size_t datasize,
rom->datasize = datasize;
rom->romsize = romsize;
rom->data = data;
rom->as = as;
rom_insert(rom);
return 0;
}
int rom_add_vga(const char *file)
{
return rom_add_file(file, "vgaroms", 0, -1, true, NULL);
return rom_add_file(file, "vgaroms", 0, -1, true, NULL, NULL);
}
int rom_add_option(const char *file, int32_t bootindex)
{
return rom_add_file(file, "genroms", 0, bootindex, true, NULL);
return rom_add_file(file, "genroms", 0, bootindex, true, NULL, NULL);
}
static void rom_reset(void *unused)
......@@ -1008,8 +1058,8 @@ static void rom_reset(void *unused)
void *host = memory_region_get_ram_ptr(rom->mr);
memcpy(host, rom->data, rom->datasize);
} else {
cpu_physical_memory_write_rom(&address_space_memory,
rom->addr, rom->data, rom->datasize);
cpu_physical_memory_write_rom(rom->as, rom->addr, rom->data,
rom->datasize);
}
if (rom->isrom) {
/* rom needs to be written only once */
......@@ -1031,12 +1081,13 @@ int rom_check_and_register_reset(void)
hwaddr addr = 0;
MemoryRegionSection section;
Rom *rom;
AddressSpace *as = NULL;
QTAILQ_FOREACH(rom, &roms, next) {
if (rom->fw_file) {
continue;
}
if (addr > rom->addr) {
if ((addr > rom->addr) && (as == rom->as)) {
fprintf(stderr, "rom: requested regions overlap "
"(rom %s. free=0x" TARGET_FMT_plx
", addr=0x" TARGET_FMT_plx ")\n",
......@@ -1045,9 +1096,11 @@ int rom_check_and_register_reset(void)
}
addr = rom->addr;
addr += rom->romsize;
section = memory_region_find(get_system_memory(), rom->addr, 1);
section = memory_region_find(rom->mr ? rom->mr : get_system_memory(),
rom->addr, 1);
rom->isrom = int128_nz(section.size) && memory_region_is_rom(section.mr);
memory_region_unref(section.mr);
as = rom->as;
}
qemu_register_reset(rom_reset, NULL);
roms_loaded = 1;
......
......@@ -11,6 +11,7 @@
#include "hw/ptimer.h"
#include "qemu/host-utils.h"
#include "sysemu/replay.h"
#include "sysemu/qtest.h"
struct ptimer_state
{
......@@ -21,6 +22,7 @@ struct ptimer_state
int64_t period;
int64_t last_event;
int64_t next_event;
uint8_t policy_mask;
QEMUBH *bh;
QEMUTimer *timer;
};
......@@ -43,7 +45,10 @@ static void ptimer_reload(ptimer_state *s)
s->delta = s->limit;
}
if (s->delta == 0 || s->period == 0) {
fprintf(stderr, "Timer with period zero, disabling\n");
if (!qtest_enabled()) {
fprintf(stderr, "Timer with period zero, disabling\n");
}
timer_del(s->timer);
s->enabled = 0;
return;
}
......@@ -161,7 +166,9 @@ void ptimer_run(ptimer_state *s, int oneshot)
bool was_disabled = !s->enabled;
if (was_disabled && s->period == 0) {
fprintf(stderr, "Timer with period zero, disabling\n");
if (!qtest_enabled()) {
fprintf(stderr, "Timer with period zero, disabling\n");
}
return;
}
s->enabled = oneshot ? 2 : 1;
......@@ -242,12 +249,13 @@ const VMStateDescription vmstate_ptimer = {
}
};
ptimer_state *ptimer_init(QEMUBH *bh)
ptimer_state *ptimer_init(QEMUBH *bh, uint8_t policy_mask)
{
ptimer_state *s;
s = (ptimer_state *)g_malloc0(sizeof(ptimer_state));
s->bh = bh;
s->timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, ptimer_tick, s);
s->policy_mask = policy_mask;
return s;
}
......@@ -48,18 +48,18 @@ typedef struct {
SSISlave ssidev;
QemuConsole *con;
int cmd_len;
int cmd;
int cmd_data[8];
int row;
int row_start;
int row_end;
int col;
int col_start;
int col_end;
int redraw;
int remap;
enum ssd0323_mode mode;
uint32_t cmd_len;
int32_t cmd;
int32_t cmd_data[8];
int32_t row;
int32_t row_start;
int32_t row_end;
int32_t col;
int32_t col_start;
int32_t col_end;
int32_t redraw;
int32_t remap;
uint32_t mode;
uint8_t framebuffer[128 * 80 / 2];
} ssd0323_state;
......@@ -279,83 +279,62 @@ static void ssd0323_cd(void *opaque, int n, int level)
s->mode = level ? SSD0323_DATA : SSD0323_CMD;
}
static void ssd0323_save(QEMUFile *f, void *opaque)
static int ssd0323_post_load(void *opaque, int version_id)
{
SSISlave *ss = SSI_SLAVE(opaque);
ssd0323_state *s = (ssd0323_state *)opaque;
int i;
qemu_put_be32(f, s->cmd_len);
qemu_put_be32(f, s->cmd);
for (i = 0; i < 8; i++)
qemu_put_be32(f, s->cmd_data[i]);
qemu_put_be32(f, s->row);
qemu_put_be32(f, s->row_start);
qemu_put_be32(f, s->row_end);
qemu_put_be32(f, s->col);
qemu_put_be32(f, s->col_start);
qemu_put_be32(f, s->col_end);
qemu_put_be32(f, s->redraw);
qemu_put_be32(f, s->remap);
qemu_put_be32(f, s->mode);
qemu_put_buffer(f, s->framebuffer, sizeof(s->framebuffer));
qemu_put_be32(f, ss->cs);
}
static int ssd0323_load(QEMUFile *f, void *opaque, int version_id)
{
SSISlave *ss = SSI_SLAVE(opaque);
ssd0323_state *s = (ssd0323_state *)opaque;
int i;
if (version_id != 1)
return -EINVAL;
s->cmd_len = qemu_get_be32(f);
if (s->cmd_len < 0 || s->cmd_len > ARRAY_SIZE(s->cmd_data)) {
if (s->cmd_len > ARRAY_SIZE(s->cmd_data)) {
return -EINVAL;
}
s->cmd = qemu_get_be32(f);
for (i = 0; i < 8; i++)
s->cmd_data[i] = qemu_get_be32(f);
s->row = qemu_get_be32(f);
if (s->row < 0 || s->row >= 80) {
return -EINVAL;
}
s->row_start = qemu_get_be32(f);
if (s->row_start < 0 || s->row_start >= 80) {
return -EINVAL;
}
s->row_end = qemu_get_be32(f);
if (s->row_end < 0 || s->row_end >= 80) {
return -EINVAL;
}
s->col = qemu_get_be32(f);
if (s->col < 0 || s->col >= 64) {
return -EINVAL;
}
s->col_start = qemu_get_be32(f);
if (s->col_start < 0 || s->col_start >= 64) {
return -EINVAL;
}
s->col_end = qemu_get_be32(f);
if (s->col_end < 0 || s->col_end >= 64) {
return -EINVAL;
}
s->redraw = qemu_get_be32(f);
s->remap = qemu_get_be32(f);
s->mode = qemu_get_be32(f);
if (s->mode != SSD0323_CMD && s->mode != SSD0323_DATA) {
return -EINVAL;
}
qemu_get_buffer(f, s->framebuffer, sizeof(s->framebuffer));
ss->cs = qemu_get_be32(f);
return 0;
}
static const VMStateDescription vmstate_ssd0323 = {
.name = "ssd0323_oled",
.version_id = 2,
.minimum_version_id = 2,
.post_load = ssd0323_post_load,
.fields = (VMStateField []) {
VMSTATE_UINT32(cmd_len, ssd0323_state),
VMSTATE_INT32(cmd, ssd0323_state),
VMSTATE_INT32_ARRAY(cmd_data, ssd0323_state, 8),
VMSTATE_INT32(row, ssd0323_state),
VMSTATE_INT32(row_start, ssd0323_state),
VMSTATE_INT32(row_end, ssd0323_state),
VMSTATE_INT32(col, ssd0323_state),
VMSTATE_INT32(col_start, ssd0323_state),
VMSTATE_INT32(col_end, ssd0323_state),
VMSTATE_INT32(redraw, ssd0323_state),
VMSTATE_INT32(remap, ssd0323_state),
VMSTATE_UINT32(mode, ssd0323_state),
VMSTATE_BUFFER(framebuffer, ssd0323_state),
VMSTATE_SSI_SLAVE(ssidev, ssd0323_state),
VMSTATE_END_OF_LIST()
}
};
static const GraphicHwOps ssd0323_ops = {
.invalidate = ssd0323_invalidate_display,
.gfx_update = ssd0323_update_display,
......@@ -372,18 +351,17 @@ static void ssd0323_realize(SSISlave *d, Error **errp)
qemu_console_resize(s->con, 128 * MAGNIFY, 64 * MAGNIFY);
qdev_init_gpio_in(dev, ssd0323_cd, 1);
register_savevm(dev, "ssd0323_oled", -1, 1,
ssd0323_save, ssd0323_load, s);
}
static void ssd0323_class_init(ObjectClass *klass, void *data)
{
DeviceClass *dc = DEVICE_CLASS(klass);
SSISlaveClass *k = SSI_SLAVE_CLASS(klass);
k->realize = ssd0323_realize;
k->transfer = ssd0323_transfer;
k->cs_polarity = SSI_CS_HIGH;
dc->vmsd = &vmstate_ssd0323;
}
static const TypeInfo ssd0323_info = {
......
......@@ -548,7 +548,7 @@ static void xilinx_axidma_realize(DeviceState *dev, Error **errp)
st->nr = i;
st->bh = qemu_bh_new(timer_hit, st);
st->ptimer = ptimer_init(st->bh);
st->ptimer = ptimer_init(st->bh, PTIMER_POLICY_DEFAULT);
ptimer_set_freq(st->ptimer, s->freqhz);
}
return;
......
......@@ -139,7 +139,7 @@ static m5206_timer_state *m5206_timer_init(qemu_irq irq)
s = (m5206_timer_state *)g_malloc0(sizeof(m5206_timer_state));
bh = qemu_bh_new(m5206_timer_trigger, s);
s->timer = ptimer_init(bh);
s->timer = ptimer_init(bh, PTIMER_POLICY_DEFAULT);
s->irq = irq;
m5206_timer_reset(s);
return s;
......
......@@ -183,7 +183,7 @@ static void mcf5208_sys_init(MemoryRegion *address_space, qemu_irq *pic)
for (i = 0; i < 2; i++) {
s = (m5208_timer_state *)g_malloc0(sizeof(m5208_timer_state));
bh = qemu_bh_new(m5208_timer_trigger, s);
s->timer = ptimer_init(bh);
s->timer = ptimer_init(bh, PTIMER_POLICY_DEFAULT);
memory_region_init_io(&s->iomem, NULL, &m5208_timer_ops, s,
"m5208-timer", 0x00004000);
memory_region_add_subregion(address_space, 0xfc080000 + 0x4000 * i,
......
......@@ -120,6 +120,41 @@ static const uint32_t ast2400_a0_resets[ASPEED_SCU_NR_REGS] = {
[BMC_DEV_ID] = 0x00002402U
};
/* SCU70 bit 23: 0 24Mhz. bit 11:9: 0b001 AXI:ABH ratio 2:1 */
/* AST2500 revision A1 */
static const uint32_t ast2500_a1_resets[ASPEED_SCU_NR_REGS] = {
[SYS_RST_CTRL] = 0xFFCFFEDCU,
[CLK_SEL] = 0xF3F40000U,
[CLK_STOP_CTRL] = 0x19FC3E8BU,
[D2PLL_PARAM] = 0x00026108U,
[MPLL_PARAM] = 0x00030291U,
[HPLL_PARAM] = 0x93000400U,
[MISC_CTRL1] = 0x00000010U,
[PCI_CTRL1] = 0x20001A03U,
[PCI_CTRL2] = 0x20001A03U,
[PCI_CTRL3] = 0x04000030U,
[SYS_RST_STATUS] = 0x00000001U,
[SOC_SCRATCH1] = 0x000000C0U, /* SoC completed DRAM init */
[MISC_CTRL2] = 0x00000023U,
[RNG_CTRL] = 0x0000000EU,
[PINMUX_CTRL2] = 0x0000F000U,
[PINMUX_CTRL3] = 0x03000000U,
[PINMUX_CTRL4] = 0x00000000U,
[PINMUX_CTRL5] = 0x0000A000U,
[WDT_RST_CTRL] = 0x023FFFF3U,
[PINMUX_CTRL8] = 0xFFFF0000U,
[PINMUX_CTRL9] = 0x000FFFFFU,
[FREE_CNTR4] = 0x000000FFU,
[FREE_CNTR4_EXT] = 0x000000FFU,
[CPU2_BASE_SEG1] = 0x80000000U,
[CPU2_BASE_SEG4] = 0x1E600000U,
[CPU2_BASE_SEG5] = 0xC0000000U,
[UART_HPLL_CLK] = 0x00001903U,
[PCIE_CTRL] = 0x0000007BU,
[BMC_DEV_ID] = 0x00002402U
};
static uint64_t aspeed_scu_read(void *opaque, hwaddr offset, unsigned size)
{
AspeedSCUState *s = ASPEED_SCU(opaque);
......@@ -198,6 +233,10 @@ static void aspeed_scu_reset(DeviceState *dev)
case AST2400_A0_SILICON_REV:
reset = ast2400_a0_resets;
break;
case AST2500_A0_SILICON_REV:
case AST2500_A1_SILICON_REV:
reset = ast2500_a1_resets;
break;
default:
g_assert_not_reached();
}
......@@ -208,7 +247,11 @@ static void aspeed_scu_reset(DeviceState *dev)
s->regs[HW_STRAP2] = s->hw_strap2;
}
static uint32_t aspeed_silicon_revs[] = { AST2400_A0_SILICON_REV, };
static uint32_t aspeed_silicon_revs[] = {
AST2400_A0_SILICON_REV,
AST2500_A0_SILICON_REV,
AST2500_A1_SILICON_REV,
};
bool is_supported_silicon_rev(uint32_t silicon_rev)
{
......
......@@ -9,6 +9,7 @@
#include "qemu/osdep.h"
#include "qemu/log.h"
#include "qemu/error-report.h"
#include "hw/misc/aspeed_sdmc.h"
#include "hw/misc/aspeed_scu.h"
#include "hw/qdev-properties.h"
......@@ -139,9 +140,9 @@ static const MemoryRegionOps aspeed_sdmc_ops = {
.valid.max_access_size = 4,
};
static int ast2400_rambits(void)
static int ast2400_rambits(AspeedSDMCState *s)
{
switch (ram_size >> 20) {
switch (s->ram_size >> 20) {
case 64:
return ASPEED_SDMC_DRAM_64MB;
case 128:
......@@ -151,18 +152,19 @@ static int ast2400_rambits(void)
case 512:
return ASPEED_SDMC_DRAM_512MB;
default:
qemu_log_mask(LOG_GUEST_ERROR, "%s: Invalid RAM size: 0x"
RAM_ADDR_FMT "\n", __func__, ram_size);
break;
}
/* set a minimum default */
return ASPEED_SDMC_DRAM_64MB;
/* use a common default */
error_report("warning: Invalid RAM size 0x%" PRIx64
". Using default 256M", s->ram_size);
s->ram_size = 256 << 20;
return ASPEED_SDMC_DRAM_256MB;
}
static int ast2500_rambits(void)
static int ast2500_rambits(AspeedSDMCState *s)
{
switch (ram_size >> 20) {
switch (s->ram_size >> 20) {
case 128:
return ASPEED_SDMC_AST2500_128MB;
case 256:
......@@ -172,13 +174,14 @@ static int ast2500_rambits(void)
case 1024:
return ASPEED_SDMC_AST2500_1024MB;
default:
qemu_log_mask(LOG_GUEST_ERROR, "%s: Invalid RAM size: 0x"
RAM_ADDR_FMT "\n", __func__, ram_size);
break;
}
/* set a minimum default */
return ASPEED_SDMC_AST2500_128MB;
/* use a common default */
error_report("warning: Invalid RAM size 0x%" PRIx64
". Using default 512M", s->ram_size);
s->ram_size = 512 << 20;
return ASPEED_SDMC_AST2500_512MB;
}
static void aspeed_sdmc_reset(DeviceState *dev)
......@@ -192,14 +195,15 @@ static void aspeed_sdmc_reset(DeviceState *dev)
case AST2400_A0_SILICON_REV:
s->regs[R_CONF] |=
ASPEED_SDMC_VGA_COMPAT |
ASPEED_SDMC_DRAM_SIZE(ast2400_rambits());
ASPEED_SDMC_DRAM_SIZE(s->ram_bits);
break;
case AST2500_A0_SILICON_REV:
case AST2500_A1_SILICON_REV:
s->regs[R_CONF] |=
ASPEED_SDMC_HW_VERSION(1) |
ASPEED_SDMC_VGA_APERTURE(ASPEED_SDMC_VGA_64MB) |
ASPEED_SDMC_DRAM_SIZE(ast2500_rambits());
ASPEED_SDMC_DRAM_SIZE(s->ram_bits);
break;
default:
......@@ -218,6 +222,18 @@ static void aspeed_sdmc_realize(DeviceState *dev, Error **errp)
return;
}
switch (s->silicon_rev) {
case AST2400_A0_SILICON_REV:
s->ram_bits = ast2400_rambits(s);
break;
case AST2500_A0_SILICON_REV:
case AST2500_A1_SILICON_REV:
s->ram_bits = ast2500_rambits(s);
break;
default:
g_assert_not_reached();
}
memory_region_init_io(&s->iomem, OBJECT(s), &aspeed_sdmc_ops, s,
TYPE_ASPEED_SDMC, 0x1000);
sysbus_init_mmio(sbd, &s->iomem);
......@@ -235,6 +251,7 @@ static const VMStateDescription vmstate_aspeed_sdmc = {
static Property aspeed_sdmc_properties[] = {
DEFINE_PROP_UINT32("silicon-rev", AspeedSDMCState, silicon_rev, 0),
DEFINE_PROP_UINT64("ram-size", AspeedSDMCState, ram_size, 0),
DEFINE_PROP_END_OF_LIST(),
};
......
......@@ -27,7 +27,7 @@
} \
} while (0)
static char const *imx25_ccm_reg_name(uint32_t reg)
static const char *imx25_ccm_reg_name(uint32_t reg)
{
static char unknown[20];
......
......@@ -29,7 +29,7 @@
} \
} while (0)
static char const *imx31_ccm_reg_name(uint32_t reg)
static const char *imx31_ccm_reg_name(uint32_t reg)
{
static char unknown[20];
......
......@@ -26,7 +26,7 @@
} \
} while (0)
static char const *imx6_ccm_reg_name(uint32_t reg)
static const char *imx6_ccm_reg_name(uint32_t reg)
{
static char unknown[20];
......@@ -99,7 +99,7 @@ static char const *imx6_ccm_reg_name(uint32_t reg)
}
}
static char const *imx6_analog_reg_name(uint32_t reg)
static const char *imx6_analog_reg_name(uint32_t reg)
{
static char unknown[20];
......
......@@ -27,7 +27,7 @@
} \
} while (0)
static char const *imx6_src_reg_name(uint32_t reg)
static const char *imx6_src_reg_name(uint32_t reg)
{
static char unknown[20];
......
此差异已折叠。
......@@ -387,7 +387,7 @@ static void etsec_realize(DeviceState *dev, Error **errp)
etsec->bh = qemu_bh_new(etsec_timer_hit, etsec);
etsec->ptimer = ptimer_init(etsec->bh);
etsec->ptimer = ptimer_init(etsec->bh, PTIMER_POLICY_DEFAULT);
ptimer_set_freq(etsec->ptimer, 100);
}
......
......@@ -1345,7 +1345,7 @@ static int lan9118_init1(SysBusDevice *sbd)
s->txp = &s->tx_packet;
bh = qemu_bh_new(lan9118_tick, s);
s->timer = ptimer_init(bh);
s->timer = ptimer_init(bh, PTIMER_POLICY_DEFAULT);
ptimer_set_freq(s->timer, 10000);
ptimer_set_limit(s->timer, 0xffff, 1);
......
......@@ -31,7 +31,7 @@ do { fprintf(stderr, "ssi_sd: error: " fmt , ## __VA_ARGS__);} while (0)
#endif
typedef enum {
SSI_SD_CMD,
SSI_SD_CMD = 0,
SSI_SD_CMDARG,
SSI_SD_RESPONSE,
SSI_SD_DATA_START,
......@@ -40,13 +40,13 @@ typedef enum {
typedef struct {
SSISlave ssidev;
ssi_sd_mode mode;
uint32_t mode;
int cmd;
uint8_t cmdarg[4];
uint8_t response[5];
int arglen;
int response_pos;
int stopping;
int32_t arglen;
int32_t response_pos;
int32_t stopping;
SDState *sd;
} ssi_sd_state;
......@@ -198,61 +198,46 @@ static uint32_t ssi_sd_transfer(SSISlave *dev, uint32_t val)
return 0xff;
}
static void ssi_sd_save(QEMUFile *f, void *opaque)
static int ssi_sd_post_load(void *opaque, int version_id)
{
SSISlave *ss = SSI_SLAVE(opaque);
ssi_sd_state *s = (ssi_sd_state *)opaque;
int i;
qemu_put_be32(f, s->mode);
qemu_put_be32(f, s->cmd);
for (i = 0; i < 4; i++)
qemu_put_be32(f, s->cmdarg[i]);
for (i = 0; i < 5; i++)
qemu_put_be32(f, s->response[i]);
qemu_put_be32(f, s->arglen);
qemu_put_be32(f, s->response_pos);
qemu_put_be32(f, s->stopping);
qemu_put_be32(f, ss->cs);
}
static int ssi_sd_load(QEMUFile *f, void *opaque, int version_id)
{
SSISlave *ss = SSI_SLAVE(opaque);
ssi_sd_state *s = (ssi_sd_state *)opaque;
int i;
if (version_id != 1)
if (s->mode > SSI_SD_DATA_READ) {
return -EINVAL;
s->mode = qemu_get_be32(f);
s->cmd = qemu_get_be32(f);
for (i = 0; i < 4; i++)
s->cmdarg[i] = qemu_get_be32(f);
for (i = 0; i < 5; i++)
s->response[i] = qemu_get_be32(f);
s->arglen = qemu_get_be32(f);
}
if (s->mode == SSI_SD_CMDARG &&
(s->arglen < 0 || s->arglen >= ARRAY_SIZE(s->cmdarg))) {
return -EINVAL;
}
s->response_pos = qemu_get_be32(f);
s->stopping = qemu_get_be32(f);
if (s->mode == SSI_SD_RESPONSE &&
(s->response_pos < 0 || s->response_pos >= ARRAY_SIZE(s->response) ||
(!s->stopping && s->arglen > ARRAY_SIZE(s->response)))) {
return -EINVAL;
}
ss->cs = qemu_get_be32(f);
return 0;
}
static const VMStateDescription vmstate_ssi_sd = {
.name = "ssi_sd",
.version_id = 2,
.minimum_version_id = 2,
.post_load = ssi_sd_post_load,
.fields = (VMStateField []) {
VMSTATE_UINT32(mode, ssi_sd_state),
VMSTATE_INT32(cmd, ssi_sd_state),
VMSTATE_UINT8_ARRAY(cmdarg, ssi_sd_state, 4),
VMSTATE_UINT8_ARRAY(response, ssi_sd_state, 5),
VMSTATE_INT32(arglen, ssi_sd_state),
VMSTATE_INT32(response_pos, ssi_sd_state),
VMSTATE_INT32(stopping, ssi_sd_state),
VMSTATE_SSI_SLAVE(ssidev, ssi_sd_state),
VMSTATE_END_OF_LIST()
}
};
static void ssi_sd_realize(SSISlave *d, Error **errp)
{
DeviceState *dev = DEVICE(d);
ssi_sd_state *s = FROM_SSI_SLAVE(ssi_sd_state, d);
DriveInfo *dinfo;
......@@ -264,16 +249,17 @@ static void ssi_sd_realize(SSISlave *d, Error **errp)
error_setg(errp, "Device initialization failed.");
return;
}
register_savevm(dev, "ssi_sd", -1, 1, ssi_sd_save, ssi_sd_load, s);
}
static void ssi_sd_class_init(ObjectClass *klass, void *data)
{
DeviceClass *dc = DEVICE_CLASS(klass);
SSISlaveClass *k = SSI_SLAVE_CLASS(klass);
k->realize = ssi_sd_realize;
k->transfer = ssi_sd_transfer;
k->cs_polarity = SSI_CS_LOW;
dc->vmsd = &vmstate_ssi_sd;
}
static const TypeInfo ssi_sd_info = {
......
......@@ -25,7 +25,7 @@
} \
} while (0)
static char const *imx_spi_reg_name(uint32_t reg)
static const char *imx_spi_reg_name(uint32_t reg)
{
static char unknown[20];
......
......@@ -267,7 +267,7 @@ static void a10_pit_init(Object *obj)
tc->container = s;
tc->index = i;
bh[i] = qemu_bh_new(a10_pit_timer_cb, tc);
s->timer[i] = ptimer_init(bh[i]);
s->timer[i] = ptimer_init(bh[i], PTIMER_POLICY_DEFAULT);
}
}
......
......@@ -171,7 +171,7 @@ static arm_timer_state *arm_timer_init(uint32_t freq)
s->control = TIMER_CTRL_IE;
bh = qemu_bh_new(arm_timer_tick, s);
s->timer = ptimer_init(bh);
s->timer = ptimer_init(bh, PTIMER_POLICY_DEFAULT);
vmstate_register(NULL, -1, &vmstate_arm_timer, s);
return s;
}
......
......@@ -127,7 +127,7 @@ static void digic_timer_init(Object *obj)
{
DigicTimerState *s = DIGIC_TIMER(obj);
s->ptimer = ptimer_init(NULL);
s->ptimer = ptimer_init(NULL, PTIMER_POLICY_DEFAULT);
/*
* FIXME: there is no documentation on Digic timer
......
......@@ -322,9 +322,9 @@ static int etraxfs_timer_init(SysBusDevice *dev)
t->bh_t0 = qemu_bh_new(timer0_hit, t);
t->bh_t1 = qemu_bh_new(timer1_hit, t);
t->bh_wd = qemu_bh_new(watchdog_hit, t);
t->ptimer_t0 = ptimer_init(t->bh_t0);
t->ptimer_t1 = ptimer_init(t->bh_t1);
t->ptimer_wd = ptimer_init(t->bh_wd);
t->ptimer_t0 = ptimer_init(t->bh_t0, PTIMER_POLICY_DEFAULT);
t->ptimer_t1 = ptimer_init(t->bh_t1, PTIMER_POLICY_DEFAULT);
t->ptimer_wd = ptimer_init(t->bh_wd, PTIMER_POLICY_DEFAULT);
sysbus_init_irq(dev, &t->irq);
sysbus_init_irq(dev, &t->nmi);
......
......@@ -1431,15 +1431,16 @@ static void exynos4210_mct_init(Object *obj)
/* Global timer */
bh[0] = qemu_bh_new(exynos4210_gfrc_event, s);
s->g_timer.ptimer_frc = ptimer_init(bh[0]);
s->g_timer.ptimer_frc = ptimer_init(bh[0], PTIMER_POLICY_DEFAULT);
memset(&s->g_timer.reg, 0, sizeof(struct gregs));
/* Local timers */
for (i = 0; i < 2; i++) {
bh[0] = qemu_bh_new(exynos4210_ltick_event, &s->l_timer[i]);
bh[1] = qemu_bh_new(exynos4210_lfrc_event, &s->l_timer[i]);
s->l_timer[i].tick_timer.ptimer_tick = ptimer_init(bh[0]);
s->l_timer[i].ptimer_frc = ptimer_init(bh[1]);
s->l_timer[i].tick_timer.ptimer_tick =
ptimer_init(bh[0], PTIMER_POLICY_DEFAULT);
s->l_timer[i].ptimer_frc = ptimer_init(bh[1], PTIMER_POLICY_DEFAULT);
s->l_timer[i].id = i;
}
......
......@@ -390,7 +390,7 @@ static void exynos4210_pwm_init(Object *obj)
for (i = 0; i < EXYNOS4210_PWM_TIMERS_NUM; i++) {
bh = qemu_bh_new(exynos4210_pwm_tick, &s->timer[i]);
sysbus_init_irq(dev, &s->timer[i].irq);
s->timer[i].ptimer = ptimer_init(bh);
s->timer[i].ptimer = ptimer_init(bh, PTIMER_POLICY_DEFAULT);
s->timer[i].id = i;
s->timer[i].parent = s;
}
......
......@@ -555,12 +555,12 @@ static void exynos4210_rtc_init(Object *obj)
QEMUBH *bh;
bh = qemu_bh_new(exynos4210_rtc_tick, s);
s->ptimer = ptimer_init(bh);
s->ptimer = ptimer_init(bh, PTIMER_POLICY_DEFAULT);
ptimer_set_freq(s->ptimer, RTC_BASE_FREQ);
exynos4210_rtc_update_freq(s, 0);
bh = qemu_bh_new(exynos4210_rtc_1Hz_tick, s);
s->ptimer_1Hz = ptimer_init(bh);
s->ptimer_1Hz = ptimer_init(bh, PTIMER_POLICY_DEFAULT);
ptimer_set_freq(s->ptimer_1Hz, RTC_BASE_FREQ);
sysbus_init_irq(dev, &s->alm_irq);
......
......@@ -363,7 +363,7 @@ static int grlib_gptimer_init(SysBusDevice *dev)
timer->unit = unit;
timer->bh = qemu_bh_new(grlib_gptimer_hit, timer);
timer->ptimer = ptimer_init(timer->bh);
timer->ptimer = ptimer_init(timer->bh, PTIMER_POLICY_DEFAULT);
timer->id = i;
/* One IRQ line for each timer */
......
......@@ -30,7 +30,7 @@
} \
} while (0)
static char const *imx_epit_reg_name(uint32_t reg)
static const char *imx_epit_reg_name(uint32_t reg)
{
switch (reg) {
case 0:
......@@ -314,10 +314,10 @@ static void imx_epit_realize(DeviceState *dev, Error **errp)
0x00001000);
sysbus_init_mmio(sbd, &s->iomem);
s->timer_reload = ptimer_init(NULL);
s->timer_reload = ptimer_init(NULL, PTIMER_POLICY_DEFAULT);
bh = qemu_bh_new(imx_epit_cmp, s);
s->timer_cmp = ptimer_init(bh);
s->timer_cmp = ptimer_init(bh, PTIMER_POLICY_DEFAULT);
}
static void imx_epit_class_init(ObjectClass *klass, void *data)
......
......@@ -29,7 +29,7 @@
} \
} while (0)
static char const *imx_gpt_reg_name(uint32_t reg)
static const char *imx_gpt_reg_name(uint32_t reg)
{
switch (reg) {
case 0:
......@@ -461,7 +461,7 @@ static void imx_gpt_realize(DeviceState *dev, Error **errp)
sysbus_init_mmio(sbd, &s->iomem);
bh = qemu_bh_new(imx_gpt_timeout, s);
s->timer = ptimer_init(bh);
s->timer = ptimer_init(bh, PTIMER_POLICY_DEFAULT);
}
static void imx_gpt_class_init(ObjectClass *klass, void *data)
......
......@@ -184,7 +184,7 @@ static void lm32_timer_init(Object *obj)
sysbus_init_irq(dev, &s->irq);
s->bh = qemu_bh_new(timer_hit, s);
s->ptimer = ptimer_init(s->bh);
s->ptimer = ptimer_init(s->bh, PTIMER_POLICY_DEFAULT);
memory_region_init_io(&s->iomem, obj, &timer_ops, s,
"timer", R_MAX * 4);
......
......@@ -281,8 +281,8 @@ static void milkymist_sysctl_init(Object *obj)
s->bh0 = qemu_bh_new(timer0_hit, s);
s->bh1 = qemu_bh_new(timer1_hit, s);
s->ptimer0 = ptimer_init(s->bh0);
s->ptimer1 = ptimer_init(s->bh1);
s->ptimer0 = ptimer_init(s->bh0, PTIMER_POLICY_DEFAULT);
s->ptimer1 = ptimer_init(s->bh1, PTIMER_POLICY_DEFAULT);
memory_region_init_io(&s->regs_region, obj, &sysctl_mmio_ops, s,
"milkymist-sysctl", R_MAX * 4);
......
......@@ -125,7 +125,7 @@ static int puv3_ost_init(SysBusDevice *dev)
sysbus_init_irq(dev, &s->irq);
s->bh = qemu_bh_new(puv3_ost_tick, s);
s->ptimer = ptimer_init(s->bh);
s->ptimer = ptimer_init(s->bh, PTIMER_POLICY_DEFAULT);
ptimer_set_freq(s->ptimer, 50 * 1000 * 1000);
memory_region_init_io(&s->iomem, OBJECT(s), &puv3_ost_ops, s, "puv3_ost",
......
......@@ -203,7 +203,7 @@ static void *sh_timer_init(uint32_t freq, int feat, qemu_irq irq)
s->irq = irq;
bh = qemu_bh_new(sh_timer_tick, s);
s->timer = ptimer_init(bh);
s->timer = ptimer_init(bh, PTIMER_POLICY_DEFAULT);
sh_timer_write(s, OFFSET_TCOR >> 2, s->tcor);
sh_timer_write(s, OFFSET_TCNT >> 2, s->tcnt);
......
......@@ -389,7 +389,7 @@ static int slavio_timer_init1(SysBusDevice *dev)
tc->timer_index = i;
bh = qemu_bh_new(slavio_timer_irq, tc);
s->cputimer[i].timer = ptimer_init(bh);
s->cputimer[i].timer = ptimer_init(bh, PTIMER_POLICY_DEFAULT);
ptimer_set_period(s->cputimer[i].timer, TIMER_PERIOD);
size = i == 0 ? SYS_TIMER_SIZE : CPU_TIMER_SIZE;
......
......@@ -218,7 +218,7 @@ static void xilinx_timer_realize(DeviceState *dev, Error **errp)
xt->parent = t;
xt->nr = i;
xt->bh = qemu_bh_new(timer_hit, xt);
xt->ptimer = ptimer_init(xt->bh);
xt->ptimer = ptimer_init(xt->bh, PTIMER_POLICY_DEFAULT);
ptimer_set_freq(xt->ptimer, t->freq_hz);
}
......
/*
* ASPEED AST2400 SoC
* ASPEED SoC family
*
* Andrew Jeffery <andrew@aj.id.au>
*
......@@ -9,8 +9,8 @@
* the COPYING file in the top-level directory.
*/
#ifndef AST2400_H
#define AST2400_H
#ifndef ASPEED_SOC_H
#define ASPEED_SOC_H
#include "hw/arm/arm.h"
#include "hw/intc/aspeed_vic.h"
......@@ -20,7 +20,7 @@
#include "hw/i2c/aspeed_i2c.h"
#include "hw/ssi/aspeed_smc.h"
typedef struct AST2400State {
typedef struct AspeedSoCState {
/*< private >*/
DeviceState parent;
......@@ -34,11 +34,26 @@ typedef struct AST2400State {
AspeedSMCState smc;
AspeedSMCState spi;
AspeedSDMCState sdmc;
} AST2400State;
} AspeedSoCState;
#define TYPE_AST2400 "ast2400"
#define AST2400(obj) OBJECT_CHECK(AST2400State, (obj), TYPE_AST2400)
#define TYPE_ASPEED_SOC "aspeed-soc"
#define ASPEED_SOC(obj) OBJECT_CHECK(AspeedSoCState, (obj), TYPE_ASPEED_SOC)
#define AST2400_SDRAM_BASE 0x40000000
typedef struct AspeedSoCInfo {
const char *name;
const char *cpu_model;
uint32_t silicon_rev;
hwaddr sdram_base;
} AspeedSoCInfo;
#endif /* AST2400_H */
typedef struct AspeedSoCClass {
DeviceClass parent_class;
AspeedSoCInfo *info;
} AspeedSoCClass;
#define ASPEED_SOC_CLASS(klass) \
OBJECT_CLASS_CHECK(AspeedSoCClass, (klass), TYPE_ASPEED_SOC)
#define ASPEED_SOC_GET_CLASS(obj) \
OBJECT_GET_CLASS(AspeedSoCClass, (obj), TYPE_ASPEED_SOC)
#endif /* ASPEED_SOC_H */
......@@ -34,7 +34,7 @@
#define XLNX_ZYNQ_DEVCFG(obj) \
OBJECT_CHECK(XlnxZynqDevcfg, (obj), TYPE_XLNX_ZYNQ_DEVCFG)
#define XLNX_ZYNQ_DEVCFG_R_MAX 0x118
#define XLNX_ZYNQ_DEVCFG_R_MAX (0x100 / 4)
#define XLNX_ZYNQ_DEVCFG_DMA_CMD_FIFO_LEN 10
......
......@@ -263,7 +263,8 @@ static int glue(load_elf, SZ)(const char *name, int fd,
void *translate_opaque,
int must_swab, uint64_t *pentry,
uint64_t *lowaddr, uint64_t *highaddr,
int elf_machine, int clear_lsb, int data_swab)
int elf_machine, int clear_lsb, int data_swab,
AddressSpace *as)
{
struct elfhdr ehdr;
struct elf_phdr *phdr = NULL, *ph;
......@@ -280,6 +281,11 @@ static int glue(load_elf, SZ)(const char *name, int fd,
glue(bswap_ehdr, SZ)(&ehdr);
}
if (elf_machine <= EM_NONE) {
/* The caller didn't specify an ARCH, we can figure it out */
elf_machine = ehdr.e_machine;
}
switch (elf_machine) {
case EM_PPC64:
if (ehdr.e_machine != EM_PPC64) {
......@@ -400,7 +406,7 @@ static int glue(load_elf, SZ)(const char *name, int fd,
snprintf(label, sizeof(label), "phdr #%d: %s", i, name);
/* rom_add_elf_program() seize the ownership of 'data' */
rom_add_elf_program(label, data, file_size, mem_size, addr);
rom_add_elf_program(label, data, file_size, mem_size, addr, as);
total_size += mem_size;
if (addr < low)
......
......@@ -14,8 +14,28 @@
int get_image_size(const char *filename);
int load_image(const char *filename, uint8_t *addr); /* deprecated */
ssize_t load_image_size(const char *filename, void *addr, size_t size);
/**load_image_targphys_as:
* @filename: Path to the image file
* @addr: Address to load the image to
* @max_sz: The maximum size of the image to load
* @as: The AddressSpace to load the ELF to. The value of address_space_memory
* is used if nothing is supplied here.
*
* Load a fixed image into memory.
*
* Returns the size of the loaded image on success, -1 otherwise.
*/
int load_image_targphys_as(const char *filename,
hwaddr addr, uint64_t max_sz, AddressSpace *as);
/** load_image_targphys:
* Same as load_image_targphys_as(), but doesn't allow the caller to specify
* an AddressSpace.
*/
int load_image_targphys(const char *filename, hwaddr,
uint64_t max_sz);
/**
* load_image_mr: load an image into a memory region
* @filename: Path to the image file
......@@ -45,7 +65,7 @@ int load_image_gzipped(const char *filename, hwaddr addr, uint64_t max_sz);
#define ELF_LOAD_WRONG_ENDIAN -4
const char *load_elf_strerror(int error);
/** load_elf:
/** load_elf_as:
* @filename: Path of ELF file
* @translate_fn: optional function to translate load addresses
* @translate_opaque: opaque data passed to @translate_fn
......@@ -59,6 +79,8 @@ const char *load_elf_strerror(int error);
* @data_swab: Set to order of byte swapping for data. 0 for no swap, 1
* for swapping bytes within halfwords, 2 for bytes within
* words and 3 for within doublewords.
* @as: The AddressSpace to load the ELF to. The value of address_space_memory
* is used if nothing is supplied here.
*
* Load an ELF file's contents to the emulated system's address space.
* Clients may optionally specify a callback to perform address
......@@ -68,8 +90,19 @@ const char *load_elf_strerror(int error);
* load will fail if the target ELF does not match. Some architectures
* have some architecture-specific behaviours that come into effect when
* their particular values for @elf_machine are set.
* If @elf_machine is EM_NONE then the machine type will be read from the
* ELF header and no checks will be carried out against the machine type.
*/
int load_elf_as(const char *filename,
uint64_t (*translate_fn)(void *, uint64_t),
void *translate_opaque, uint64_t *pentry, uint64_t *lowaddr,
uint64_t *highaddr, int big_endian, int elf_machine,
int clear_lsb, int data_swab, AddressSpace *as);
/** load_elf:
* Same as load_elf_as(), but doesn't allow the caller to specify an
* AddressSpace.
*/
int load_elf(const char *filename, uint64_t (*translate_fn)(void *, uint64_t),
void *translate_opaque, uint64_t *pentry, uint64_t *lowaddr,
uint64_t *highaddr, int big_endian, int elf_machine,
......@@ -89,6 +122,30 @@ void load_elf_hdr(const char *filename, void *hdr, bool *is64, Error **errp);
int load_aout(const char *filename, hwaddr addr, int max_sz,
int bswap_needed, hwaddr target_page_size);
/** load_uimage_as:
* @filename: Path of uimage file
* @ep: Populated with program entry point. Ignored if NULL.
* @loadaddr: Populated with the load address. Ignored if NULL.
* @is_linux: Is set to true if the image loaded is Linux. Ignored if NULL.
* @translate_fn: optional function to translate load addresses
* @translate_opaque: opaque data passed to @translate_fn
* @as: The AddressSpace to load the ELF to. The value of address_space_memory
* is used if nothing is supplied here.
*
* Loads a u-boot image into memory.
*
* Returns the size of the loaded image on success, -1 otherwise.
*/
int load_uimage_as(const char *filename, hwaddr *ep,
hwaddr *loadaddr, int *is_linux,
uint64_t (*translate_fn)(void *, uint64_t),
void *translate_opaque, AddressSpace *as);
/** load_uimage:
* Same as load_uimage_as(), but doesn't allow the caller to specify an
* AddressSpace.
*/
int load_uimage(const char *filename, hwaddr *ep,
hwaddr *loadaddr, int *is_linux,
uint64_t (*translate_fn)(void *, uint64_t),
......@@ -118,14 +175,14 @@ extern bool rom_file_has_mr;
int rom_add_file(const char *file, const char *fw_dir,
hwaddr addr, int32_t bootindex,
bool option_rom, MemoryRegion *mr);
bool option_rom, MemoryRegion *mr, AddressSpace *as);
MemoryRegion *rom_add_blob(const char *name, const void *blob, size_t len,
size_t max_len, hwaddr addr,
const char *fw_file_name,
FWCfgReadCallback fw_callback,
void *callback_opaque);
int rom_add_elf_program(const char *name, void *data, size_t datasize,
size_t romsize, hwaddr addr);
size_t romsize, hwaddr addr, AddressSpace *as);
int rom_check_and_register_reset(void);
void rom_set_fw(FWCfgState *f);
void rom_set_order_override(int order);
......@@ -135,11 +192,17 @@ void *rom_ptr(hwaddr addr);
void hmp_info_roms(Monitor *mon, const QDict *qdict);
#define rom_add_file_fixed(_f, _a, _i) \
rom_add_file(_f, NULL, _a, _i, false, NULL)
rom_add_file(_f, NULL, _a, _i, false, NULL, NULL)
#define rom_add_blob_fixed(_f, _b, _l, _a) \
rom_add_blob(_f, _b, _l, _l, _a, NULL, NULL, NULL)
#define rom_add_file_mr(_f, _mr, _i) \
rom_add_file(_f, NULL, 0, _i, false, _mr)
rom_add_file(_f, NULL, 0, _i, false, _mr, NULL)
#define rom_add_file_as(_f, _as, _i) \
rom_add_file(_f, NULL, 0, _i, false, NULL, _as)
#define rom_add_file_fixed_as(_f, _a, _i, _as) \
rom_add_file(_f, NULL, _a, _i, false, NULL, _as)
#define rom_add_blob_fixed_as(_f, _b, _l, _a, _as) \
rom_add_blob(_f, _b, _l, _l, _a, NULL, NULL, _as)
#define PC_ROM_MIN_VGA 0xc0000
#define PC_ROM_MIN_OPTION 0xc8000
......
......@@ -33,7 +33,200 @@ typedef struct AspeedSCUState {
#define AST2400_A0_SILICON_REV 0x02000303U
#define AST2500_A0_SILICON_REV 0x04000303U
#define AST2500_A1_SILICON_REV 0x04010303U
extern bool is_supported_silicon_rev(uint32_t silicon_rev);
/*
* Extracted from Aspeed SDK v00.03.21. Fixes and extra definitions
* were added.
*
* Original header file :
* arch/arm/mach-aspeed/include/mach/regs-scu.h
*
* Copyright (C) 2012-2020 ASPEED Technology Inc.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* History :
* 1. 2012/12/29 Ryan Chen Create
*/
/* Hardware Strapping Register definition (for Aspeed AST2400 SOC)
*
* 31:29 Software defined strapping registers
* 28:27 DRAM size setting (for VGA driver use)
* 26:24 DRAM configuration setting
* 23 Enable 25 MHz reference clock input
* 22 Enable GPIOE pass-through mode
* 21 Enable GPIOD pass-through mode
* 20 Disable LPC to decode SuperIO 0x2E/0x4E address
* 19 Disable ACPI function
* 23,18 Clock source selection
* 17 Enable BMC 2nd boot watchdog timer
* 16 SuperIO configuration address selection
* 15 VGA Class Code selection
* 14 Enable LPC dedicated reset pin function
* 13:12 SPI mode selection
* 11:10 CPU/AHB clock frequency ratio selection
* 9:8 H-PLL default clock frequency selection
* 7 Define MAC#2 interface
* 6 Define MAC#1 interface
* 5 Enable VGA BIOS ROM
* 4 Boot flash memory extended option
* 3:2 VGA memory size selection
* 1:0 BMC CPU boot code selection
*/
#define SCU_AST2400_HW_STRAP_SW_DEFINE(x) ((x) << 29)
#define SCU_AST2400_HW_STRAP_SW_DEFINE_MASK (0x7 << 29)
#define SCU_AST2400_HW_STRAP_DRAM_SIZE(x) ((x) << 27)
#define SCU_AST2400_HW_STRAP_DRAM_SIZE_MASK (0x3 << 27)
#define DRAM_SIZE_64MB 0
#define DRAM_SIZE_128MB 1
#define DRAM_SIZE_256MB 2
#define DRAM_SIZE_512MB 3
#define SCU_AST2400_HW_STRAP_DRAM_CONFIG(x) ((x) << 24)
#define SCU_AST2400_HW_STRAP_DRAM_CONFIG_MASK (0x7 << 24)
#define SCU_HW_STRAP_GPIOE_PT_EN (0x1 << 22)
#define SCU_HW_STRAP_GPIOD_PT_EN (0x1 << 21)
#define SCU_HW_STRAP_LPC_DEC_SUPER_IO (0x1 << 20)
#define SCU_AST2400_HW_STRAP_ACPI_DIS (0x1 << 19)
/* bit 23, 18 [1,0] */
#define SCU_AST2400_HW_STRAP_SET_CLK_SOURCE(x) (((((x) & 0x3) >> 1) << 23) \
| (((x) & 0x1) << 18))
#define SCU_AST2400_HW_STRAP_GET_CLK_SOURCE(x) (((((x) >> 23) & 0x1) << 1) \
| (((x) >> 18) & 0x1))
#define SCU_AST2400_HW_STRAP_CLK_SOURCE_MASK ((0x1 << 23) | (0x1 << 18))
#define AST2400_CLK_25M_IN (0x1 << 23)
#define AST2400_CLK_24M_IN 0
#define AST2400_CLK_48M_IN 1
#define AST2400_CLK_25M_IN_24M_USB_CKI 2
#define AST2400_CLK_25M_IN_48M_USB_CKI 3
#define SCU_HW_STRAP_2ND_BOOT_WDT (0x1 << 17)
#define SCU_HW_STRAP_SUPER_IO_CONFIG (0x1 << 16)
#define SCU_HW_STRAP_VGA_CLASS_CODE (0x1 << 15)
#define SCU_HW_STRAP_LPC_RESET_PIN (0x1 << 14)
#define SCU_HW_STRAP_SPI_MODE(x) ((x) << 12)
#define SCU_HW_STRAP_SPI_MODE_MASK (0x3 << 12)
#define SCU_HW_STRAP_SPI_DIS 0
#define SCU_HW_STRAP_SPI_MASTER 1
#define SCU_HW_STRAP_SPI_M_S_EN 2
#define SCU_HW_STRAP_SPI_PASS_THROUGH 3
#define SCU_AST2400_HW_STRAP_SET_CPU_AHB_RATIO(x) ((x) << 10)
#define SCU_AST2400_HW_STRAP_GET_CPU_AHB_RATIO(x) (((x) >> 10) & 3)
#define SCU_AST2400_HW_STRAP_CPU_AHB_RATIO_MASK (0x3 << 10)
#define AST2400_CPU_AHB_RATIO_1_1 0
#define AST2400_CPU_AHB_RATIO_2_1 1
#define AST2400_CPU_AHB_RATIO_4_1 2
#define AST2400_CPU_AHB_RATIO_3_1 3
#define SCU_AST2400_HW_STRAP_GET_H_PLL_CLK(x) (((x) >> 8) & 0x3)
#define SCU_AST2400_HW_STRAP_H_PLL_CLK_MASK (0x3 << 8)
#define AST2400_CPU_384MHZ 0
#define AST2400_CPU_360MHZ 1
#define AST2400_CPU_336MHZ 2
#define AST2400_CPU_408MHZ 3
#define SCU_HW_STRAP_MAC1_RGMII (0x1 << 7)
#define SCU_HW_STRAP_MAC0_RGMII (0x1 << 6)
#define SCU_HW_STRAP_VGA_BIOS_ROM (0x1 << 5)
#define SCU_HW_STRAP_SPI_WIDTH (0x1 << 4)
#define SCU_HW_STRAP_VGA_SIZE_GET(x) (((x) >> 2) & 0x3)
#define SCU_HW_STRAP_VGA_MASK (0x3 << 2)
#define SCU_HW_STRAP_VGA_SIZE_SET(x) ((x) << 2)
#define VGA_8M_DRAM 0
#define VGA_16M_DRAM 1
#define VGA_32M_DRAM 2
#define VGA_64M_DRAM 3
#define SCU_AST2400_HW_STRAP_BOOT_MODE(x) (x)
#define AST2400_NOR_BOOT 0
#define AST2400_NAND_BOOT 1
#define AST2400_SPI_BOOT 2
#define AST2400_DIS_BOOT 3
/*
* Hardware strapping register definition (for Aspeed AST2500 SoC and
* higher)
*
* 31 Enable SPI Flash Strap Auto Fetch Mode
* 30 Enable GPIO Strap Mode
* 29 Select UART Debug Port
* 28 Reserved (1)
* 27 Enable fast reset mode for ARM ICE debugger
* 26 Enable eSPI flash mode
* 25 Enable eSPI mode
* 24 Select DDR4 SDRAM
* 23 Select 25 MHz reference clock input mode
* 22 Enable GPIOE pass-through mode
* 21 Enable GPIOD pass-through mode
* 20 Disable LPC to decode SuperIO 0x2E/0x4E address
* 19 Enable ACPI function
* 18 Select USBCKI input frequency
* 17 Enable BMC 2nd boot watchdog timer
* 16 SuperIO configuration address selection
* 15 VGA Class Code selection
* 14 Select dedicated LPC reset input
* 13:12 SPI mode selection
* 11:9 AXI/AHB clock frequency ratio selection
* 8 Reserved (0)
* 7 Define MAC#2 interface
* 6 Define MAC#1 interface
* 5 Enable dedicated VGA BIOS ROM
* 4 Reserved (0)
* 3:2 VGA memory size selection
* 1 Reserved (1)
* 0 Disable CPU boot
*/
#define SCU_AST2500_HW_STRAP_SPI_AUTOFETCH_ENABLE (0x1 << 31)
#define SCU_AST2500_HW_STRAP_GPIO_STRAP_ENABLE (0x1 << 30)
#define SCU_AST2500_HW_STRAP_UART_DEBUG (0x1 << 29)
#define UART_DEBUG_UART1 0
#define UART_DEBUG_UART5 1
#define SCU_AST2500_HW_STRAP_RESERVED28 (0x1 << 28)
#define SCU_AST2500_HW_STRAP_FAST_RESET_DBG (0x1 << 27)
#define SCU_AST2500_HW_STRAP_ESPI_FLASH_ENABLE (0x1 << 26)
#define SCU_AST2500_HW_STRAP_ESPI_ENABLE (0x1 << 25)
#define SCU_AST2500_HW_STRAP_DDR4_ENABLE (0x1 << 24)
#define SCU_AST2500_HW_STRAP_ACPI_ENABLE (0x1 << 19)
#define SCU_AST2500_HW_STRAP_USBCKI_FREQ (0x1 << 18)
#define USBCKI_FREQ_24MHZ 0
#define USBCKI_FREQ_28MHZ 1
#define SCU_AST2500_HW_STRAP_SET_AXI_AHB_RATIO(x) ((x) << 9)
#define SCU_AST2500_HW_STRAP_GET_AXI_AHB_RATIO(x) (((x) >> 9) & 7)
#define SCU_AST2500_HW_STRAP_CPU_AXI_RATIO_MASK (0x7 << 9)
#define AXI_AHB_RATIO_UNDEFINED 0
#define AXI_AHB_RATIO_2_1 1
#define AXI_AHB_RATIO_3_1 2
#define AXI_AHB_RATIO_4_1 3
#define AXI_AHB_RATIO_5_1 4
#define AXI_AHB_RATIO_6_1 5
#define AXI_AHB_RATIO_7_1 6
#define AXI_AHB_RATIO_8_1 7
#define SCU_AST2500_HW_STRAP_RESERVED1 (0x1 << 1)
#define SCU_AST2500_HW_STRAP_DIS_BOOT (0x1 << 0)
#define AST2500_HW_STRAP1_DEFAULTS ( \
SCU_AST2500_HW_STRAP_RESERVED28 | \
SCU_HW_STRAP_2ND_BOOT_WDT | \
SCU_HW_STRAP_VGA_CLASS_CODE | \
SCU_HW_STRAP_LPC_RESET_PIN | \
SCU_AST2500_HW_STRAP_SET_AXI_AHB_RATIO(AXI_AHB_RATIO_2_1) | \
SCU_HW_STRAP_VGA_SIZE_SET(VGA_16M_DRAM) | \
SCU_AST2500_HW_STRAP_RESERVED1)
#endif /* ASPEED_SCU_H */
......@@ -25,6 +25,8 @@ typedef struct AspeedSDMCState {
uint32_t regs[ASPEED_SDMC_NR_REGS];
uint32_t silicon_rev;
uint32_t ram_bits;
uint64_t ram_size;
} AspeedSDMCState;
......
......@@ -30,7 +30,11 @@
#include "net/net.h"
#include "hw/sysbus.h"
#define CADENCE_GEM_MAXREG (0x00000640/4) /* Last valid GEM address */
#define CADENCE_GEM_MAXREG (0x00000800 / 4) /* Last valid GEM address */
#define MAX_PRIORITY_QUEUES 8
#define MAX_TYPE1_SCREENERS 16
#define MAX_TYPE2_SCREENERS 16
typedef struct CadenceGEMState {
/*< private >*/
......@@ -40,7 +44,12 @@ typedef struct CadenceGEMState {
MemoryRegion iomem;
NICState *nic;
NICConf conf;
qemu_irq irq;
qemu_irq irq[MAX_PRIORITY_QUEUES];
/* Static properties */
uint8_t num_priority_queues;
uint8_t num_type1_screeners;
uint8_t num_type2_screeners;
/* GEM registers backing store */
uint32_t regs[CADENCE_GEM_MAXREG];
......@@ -59,12 +68,12 @@ typedef struct CadenceGEMState {
uint8_t phy_loop; /* Are we in phy loopback? */
/* The current DMA descriptor pointers */
uint32_t rx_desc_addr;
uint32_t tx_desc_addr;
uint32_t rx_desc_addr[MAX_PRIORITY_QUEUES];
uint32_t tx_desc_addr[MAX_PRIORITY_QUEUES];
uint8_t can_rx_state; /* Debug only */
unsigned rx_desc[2];
unsigned rx_desc[MAX_PRIORITY_QUEUES][2];
bool sar_active[4];
} CadenceGEMState;
......
......@@ -12,11 +12,34 @@
#include "qemu/timer.h"
#include "migration/vmstate.h"
/* The default ptimer policy retains backward compatibility with the legacy
* timers. Custom policies are adjusting the default one. Consider providing
* a correct policy for your timer.
*
* The rough edges of the default policy:
* - Starting to run with a period = 0 emits error message and stops the
* timer without a trigger.
*
* - Setting period to 0 of the running timer emits error message and
* stops the timer without a trigger.
*
* - Starting to run with counter = 0 or setting it to "0" while timer
* is running causes a trigger and reloads counter with a limit value.
* If limit = 0, ptimer emits error message and stops the timer.
*
* - Counter value of the running timer is one less than the actual value.
*
* - Changing period/frequency of the running timer loses time elapsed
* since the last period, effectively restarting the timer with a
* counter = counter value at the moment of change (.i.e. one less).
*/
#define PTIMER_POLICY_DEFAULT 0
/* ptimer.c */
typedef struct ptimer_state ptimer_state;
typedef void (*ptimer_cb)(void *opaque);
ptimer_state *ptimer_init(QEMUBH *bh);
ptimer_state *ptimer_init(QEMUBH *bh, uint8_t policy_mask);
void ptimer_set_period(ptimer_state *s, int64_t period);
void ptimer_set_freq(ptimer_state *s, uint32_t freq);
uint64_t ptimer_get_limit(ptimer_state *s);
......
......@@ -3,6 +3,11 @@
#include "migration/vmstate.h"
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 instance_id,
......
......@@ -1129,6 +1129,51 @@ static const ARMCPRegInfo cortexa15_cp_reginfo[] = {
REGINFO_SENTINEL
};
static void cortex_a7_initfn(Object *obj)
{
ARMCPU *cpu = ARM_CPU(obj);
cpu->dtb_compatible = "arm,cortex-a7";
set_feature(&cpu->env, ARM_FEATURE_V7);
set_feature(&cpu->env, ARM_FEATURE_VFP4);
set_feature(&cpu->env, ARM_FEATURE_NEON);
set_feature(&cpu->env, ARM_FEATURE_THUMB2EE);
set_feature(&cpu->env, ARM_FEATURE_ARM_DIV);
set_feature(&cpu->env, ARM_FEATURE_GENERIC_TIMER);
set_feature(&cpu->env, ARM_FEATURE_DUMMY_C15_REGS);
set_feature(&cpu->env, ARM_FEATURE_CBAR_RO);
set_feature(&cpu->env, ARM_FEATURE_LPAE);
set_feature(&cpu->env, ARM_FEATURE_EL3);
cpu->kvm_target = QEMU_KVM_ARM_TARGET_CORTEX_A7;
cpu->midr = 0x410fc075;
cpu->reset_fpsid = 0x41023075;
cpu->mvfr0 = 0x10110222;
cpu->mvfr1 = 0x11111111;
cpu->ctr = 0x84448003;
cpu->reset_sctlr = 0x00c50078;
cpu->id_pfr0 = 0x00001131;
cpu->id_pfr1 = 0x00011011;
cpu->id_dfr0 = 0x02010555;
cpu->pmceid0 = 0x00000000;
cpu->pmceid1 = 0x00000000;
cpu->id_afr0 = 0x00000000;
cpu->id_mmfr0 = 0x10101105;
cpu->id_mmfr1 = 0x40000000;
cpu->id_mmfr2 = 0x01240000;
cpu->id_mmfr3 = 0x02102211;
cpu->id_isar0 = 0x01101110;
cpu->id_isar1 = 0x13112111;
cpu->id_isar2 = 0x21232041;
cpu->id_isar3 = 0x11112131;
cpu->id_isar4 = 0x10011142;
cpu->dbgdidr = 0x3515f005;
cpu->clidr = 0x0a200023;
cpu->ccsidr[0] = 0x701fe00a; /* 32K L1 dcache */
cpu->ccsidr[1] = 0x201fe00a; /* 32K L1 icache */
cpu->ccsidr[2] = 0x711fe07a; /* 4096K L2 unified cache */
define_arm_cp_regs(cpu, cortexa15_cp_reginfo); /* Same as A15 */
}
static void cortex_a15_initfn(Object *obj)
{
ARMCPU *cpu = ARM_CPU(obj);
......@@ -1385,6 +1430,7 @@ static const ARMCPUInfo arm_cpus[] = {
{ .name = "cortex-m4", .initfn = cortex_m4_initfn,
.class_init = arm_v7m_class_init },
{ .name = "cortex-r5", .initfn = cortex_r5_initfn },
{ .name = "cortex-a7", .initfn = cortex_a7_initfn },
{ .name = "cortex-a8", .initfn = cortex_a8_initfn },
{ .name = "cortex-a9", .initfn = cortex_a9_initfn },
{ .name = "cortex-a15", .initfn = cortex_a15_initfn },
......
......@@ -296,6 +296,7 @@ check-qtest-xtensaeb-y = $(check-qtest-xtensa-y)
check-qtest-s390x-y = tests/boot-serial-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-array.json
......@@ -658,6 +659,7 @@ tests/test-filter-mirror$(EXESUF): tests/test-filter-mirror.o $(qtest-obj-y)
tests/test-filter-redirector$(EXESUF): tests/test-filter-redirector.o $(qtest-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/ptimer-test$(EXESUF): tests/ptimer-test.o tests/ptimer-test-stubs.o hw/core/ptimer.o
tests/migration/stress$(EXESUF): tests/migration/stress.o
$(call quiet-command, $(LINKPROG) -static -O3 $(PTHREAD_LIB) -o $@ $< ," LINK $(TARGET_DIR)$@")
......
/*
* Stubs for the ptimer-test
*
* Author: Dmitry Osipenko <digetx@gmail.com>
*
* This work is licensed under the terms of the GNU GPL, version 2 or later.
* See the COPYING file in the top-level directory.
*
*/
#include "qemu/osdep.h"
#include "qemu/main-loop.h"
#include "sysemu/replay.h"
#include "ptimer-test.h"
struct QEMUBH {
QEMUBHFunc *cb;
void *opaque;
};
QEMUTimerListGroup main_loop_tlg;
int64_t ptimer_test_time_ns;
void timer_init_tl(QEMUTimer *ts,
QEMUTimerList *timer_list, int scale,
QEMUTimerCB *cb, void *opaque)
{
ts->timer_list = timer_list;
ts->cb = cb;
ts->opaque = opaque;
ts->scale = scale;
ts->expire_time = -1;
}
void timer_mod(QEMUTimer *ts, int64_t expire_time)
{
QEMUTimerList *timer_list = ts->timer_list;
QEMUTimer *t = &timer_list->active_timers;
while (t->next != NULL) {
if (t->next == ts) {
break;
}
t = t->next;
}
ts->expire_time = MAX(expire_time * ts->scale, 0);
ts->next = NULL;
t->next = ts;
}
void timer_del(QEMUTimer *ts)
{
QEMUTimerList *timer_list = ts->timer_list;
QEMUTimer *t = &timer_list->active_timers;
while (t->next != NULL) {
if (t->next == ts) {
t->next = ts->next;
return;
}
t = t->next;
}
}
int64_t qemu_clock_get_ns(QEMUClockType type)
{
return ptimer_test_time_ns;
}
int64_t qemu_clock_deadline_ns_all(QEMUClockType type)
{
QEMUTimerList *timer_list = main_loop_tlg.tl[type];
QEMUTimer *t = timer_list->active_timers.next;
int64_t deadline = -1;
while (t != NULL) {
if (deadline == -1) {
deadline = t->expire_time;
} else {
deadline = MIN(deadline, t->expire_time);
}
t = t->next;
}
return deadline;
}
QEMUBH *qemu_bh_new(QEMUBHFunc *cb, void *opaque)
{
QEMUBH *bh = g_new(QEMUBH, 1);
bh->cb = cb;
bh->opaque = opaque;
return bh;
}
void replay_bh_schedule_event(QEMUBH *bh)
{
bh->cb(bh->opaque);
}
/*
* QTest testcase for the ptimer
*
* Author: Dmitry Osipenko <digetx@gmail.com>
*
* This work is licensed under the terms of the GNU GPL, version 2 or later.
* See the COPYING file in the top-level directory.
*
*/
#include <glib/gprintf.h>
#include "qemu/osdep.h"
#include "qemu/main-loop.h"
#include "hw/ptimer.h"
#include "libqtest.h"
#include "ptimer-test.h"
static bool triggered;
static void ptimer_trigger(void *opaque)
{
triggered = true;
}
static void ptimer_test_expire_qemu_timers(int64_t expire_time,
QEMUClockType type)
{
QEMUTimerList *timer_list = main_loop_tlg.tl[type];
QEMUTimer *t = timer_list->active_timers.next;
while (t != NULL) {
if (t->expire_time == expire_time) {
timer_del(t);
if (t->cb != NULL) {
t->cb(t->opaque);
}
}
t = t->next;
}
}
static void ptimer_test_set_qemu_time_ns(int64_t ns)
{
ptimer_test_time_ns = ns;
}
static void qemu_clock_step(uint64_t ns)
{
int64_t deadline = qemu_clock_deadline_ns_all(QEMU_CLOCK_VIRTUAL);
int64_t advanced_time = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) + ns;
while (deadline != -1 && deadline <= advanced_time) {
ptimer_test_set_qemu_time_ns(deadline);
ptimer_test_expire_qemu_timers(deadline, QEMU_CLOCK_VIRTUAL);
deadline = qemu_clock_deadline_ns_all(QEMU_CLOCK_VIRTUAL);
}
ptimer_test_set_qemu_time_ns(advanced_time);
}
static void check_set_count(gconstpointer arg)
{
const uint8_t *policy = arg;
QEMUBH *bh = qemu_bh_new(ptimer_trigger, NULL);
ptimer_state *ptimer = ptimer_init(bh, *policy);
triggered = false;
ptimer_set_count(ptimer, 1000);
g_assert_cmpuint(ptimer_get_count(ptimer), ==, 1000);
g_assert_false(triggered);
}
static void check_set_limit(gconstpointer arg)
{
const uint8_t *policy = arg;
QEMUBH *bh = qemu_bh_new(ptimer_trigger, NULL);
ptimer_state *ptimer = ptimer_init(bh, *policy);
triggered = false;
ptimer_set_limit(ptimer, 1000, 0);
g_assert_cmpuint(ptimer_get_count(ptimer), ==, 0);
g_assert_cmpuint(ptimer_get_limit(ptimer), ==, 1000);
g_assert_false(triggered);
ptimer_set_limit(ptimer, 2000, 1);
g_assert_cmpuint(ptimer_get_count(ptimer), ==, 2000);
g_assert_cmpuint(ptimer_get_limit(ptimer), ==, 2000);
g_assert_false(triggered);
}
static void check_oneshot(gconstpointer arg)
{
const uint8_t *policy = arg;
QEMUBH *bh = qemu_bh_new(ptimer_trigger, NULL);
ptimer_state *ptimer = ptimer_init(bh, *policy);
triggered = false;
ptimer_set_period(ptimer, 2000000);
ptimer_set_count(ptimer, 10);
ptimer_run(ptimer, 1);
qemu_clock_step(2000000 * 2 + 100000);
g_assert_cmpuint(ptimer_get_count(ptimer), ==, 7);
g_assert_false(triggered);
ptimer_stop(ptimer);
g_assert_cmpuint(ptimer_get_count(ptimer), ==, 7);
g_assert_false(triggered);
qemu_clock_step(2000000 * 11);
g_assert_cmpuint(ptimer_get_count(ptimer), ==, 7);
g_assert_false(triggered);
ptimer_run(ptimer, 1);
qemu_clock_step(2000000 * 7 + 100000);
g_assert_cmpuint(ptimer_get_count(ptimer), ==, 0);
g_assert_true(triggered);
triggered = false;
qemu_clock_step(2000000);
g_assert_cmpuint(ptimer_get_count(ptimer), ==, 0);
g_assert_false(triggered);
qemu_clock_step(4000000);
g_assert_cmpuint(ptimer_get_count(ptimer), ==, 0);
g_assert_false(triggered);
ptimer_set_count(ptimer, 10);
qemu_clock_step(20000000 + 100000);
g_assert_cmpuint(ptimer_get_count(ptimer), ==, 10);
g_assert_false(triggered);
ptimer_set_limit(ptimer, 9, 1);
qemu_clock_step(20000000 + 100000);
g_assert_cmpuint(ptimer_get_count(ptimer), ==, 9);
g_assert_false(triggered);
ptimer_run(ptimer, 1);
qemu_clock_step(2000000 + 100000);
g_assert_cmpuint(ptimer_get_count(ptimer), ==, 7);
g_assert_false(triggered);
ptimer_set_count(ptimer, 20);
qemu_clock_step(2000000 * 19 + 100000);
g_assert_cmpuint(ptimer_get_count(ptimer), ==, 0);
g_assert_false(triggered);
qemu_clock_step(2000000);
g_assert_cmpuint(ptimer_get_count(ptimer), ==, 0);
g_assert_true(triggered);
ptimer_stop(ptimer);
triggered = false;
qemu_clock_step(2000000 * 12 + 100000);
g_assert_cmpuint(ptimer_get_count(ptimer), ==, 0);
g_assert_false(triggered);
}
static void check_periodic(gconstpointer arg)
{
const uint8_t *policy = arg;
QEMUBH *bh = qemu_bh_new(ptimer_trigger, NULL);
ptimer_state *ptimer = ptimer_init(bh, *policy);
triggered = false;
ptimer_set_period(ptimer, 2000000);
ptimer_set_limit(ptimer, 10, 1);
ptimer_run(ptimer, 0);
qemu_clock_step(2000000 * 10 + 100000);
g_assert_cmpuint(ptimer_get_count(ptimer), ==, 9);
g_assert_true(triggered);
triggered = false;
qemu_clock_step(2000000);
g_assert_cmpuint(ptimer_get_count(ptimer), ==, 8);
g_assert_false(triggered);
ptimer_set_count(ptimer, 20);
qemu_clock_step(2000000 * 11 + 100000);
g_assert_cmpuint(ptimer_get_count(ptimer), ==, 8);
g_assert_false(triggered);
qemu_clock_step(2000000 * 10);
g_assert_cmpuint(ptimer_get_count(ptimer), ==, 8);
g_assert_true(triggered);
ptimer_stop(ptimer);
triggered = false;
qemu_clock_step(2000000);
g_assert_cmpuint(ptimer_get_count(ptimer), ==, 8);
g_assert_false(triggered);
ptimer_set_count(ptimer, 3);
ptimer_run(ptimer, 0);
qemu_clock_step(2000000 * 3 + 100000);
g_assert_cmpuint(ptimer_get_count(ptimer), ==, 9);
g_assert_true(triggered);
triggered = false;
qemu_clock_step(2000000);
g_assert_cmpuint(ptimer_get_count(ptimer), ==, 8);
g_assert_false(triggered);
ptimer_set_count(ptimer, 0);
g_assert_cmpuint(ptimer_get_count(ptimer), ==, 10);
g_assert_true(triggered);
triggered = false;
qemu_clock_step(2000000 * 12 + 100000);
g_assert_cmpuint(ptimer_get_count(ptimer), ==, 7);
g_assert_true(triggered);
ptimer_stop(ptimer);
triggered = false;
qemu_clock_step(2000000 * 12 + 100000);
g_assert_cmpuint(ptimer_get_count(ptimer), ==, 7);
g_assert_false(triggered);
ptimer_run(ptimer, 0);
ptimer_set_period(ptimer, 0);
qemu_clock_step(2000000 + 100000);
g_assert_cmpuint(ptimer_get_count(ptimer), ==, 7);
g_assert_false(triggered);
}
static void check_on_the_fly_mode_change(gconstpointer arg)
{
const uint8_t *policy = arg;
QEMUBH *bh = qemu_bh_new(ptimer_trigger, NULL);
ptimer_state *ptimer = ptimer_init(bh, *policy);
triggered = false;
ptimer_set_period(ptimer, 2000000);
ptimer_set_limit(ptimer, 10, 1);
ptimer_run(ptimer, 1);
qemu_clock_step(2000000 * 9 + 100000);
ptimer_run(ptimer, 0);
g_assert_cmpuint(ptimer_get_count(ptimer), ==, 0);
g_assert_false(triggered);
qemu_clock_step(2000000);
g_assert_cmpuint(ptimer_get_count(ptimer), ==, 9);
g_assert_true(triggered);
triggered = false;
qemu_clock_step(2000000 * 9);
ptimer_run(ptimer, 1);
g_assert_cmpuint(ptimer_get_count(ptimer), ==, 0);
g_assert_false(triggered);
qemu_clock_step(2000000 * 3);
g_assert_cmpuint(ptimer_get_count(ptimer), ==, 0);
g_assert_true(triggered);
}
static void check_on_the_fly_period_change(gconstpointer arg)
{
const uint8_t *policy = arg;
QEMUBH *bh = qemu_bh_new(ptimer_trigger, NULL);
ptimer_state *ptimer = ptimer_init(bh, *policy);
triggered = false;
ptimer_set_period(ptimer, 2000000);
ptimer_set_limit(ptimer, 8, 1);
ptimer_run(ptimer, 1);
qemu_clock_step(2000000 * 4 + 100000);
g_assert_cmpuint(ptimer_get_count(ptimer), ==, 3);
g_assert_false(triggered);
ptimer_set_period(ptimer, 4000000);
g_assert_cmpuint(ptimer_get_count(ptimer), ==, 3);
qemu_clock_step(4000000 * 2 + 100000);
g_assert_cmpuint(ptimer_get_count(ptimer), ==, 0);
g_assert_false(triggered);
qemu_clock_step(4000000 * 2);
g_assert_cmpuint(ptimer_get_count(ptimer), ==, 0);
g_assert_true(triggered);
}
static void check_on_the_fly_freq_change(gconstpointer arg)
{
const uint8_t *policy = arg;
QEMUBH *bh = qemu_bh_new(ptimer_trigger, NULL);
ptimer_state *ptimer = ptimer_init(bh, *policy);
triggered = false;
ptimer_set_freq(ptimer, 500);
ptimer_set_limit(ptimer, 8, 1);
ptimer_run(ptimer, 1);
qemu_clock_step(2000000 * 4 + 100000);
g_assert_cmpuint(ptimer_get_count(ptimer), ==, 3);
g_assert_false(triggered);
ptimer_set_freq(ptimer, 250);
g_assert_cmpuint(ptimer_get_count(ptimer), ==, 3);
qemu_clock_step(2000000 * 4 + 100000);
g_assert_cmpuint(ptimer_get_count(ptimer), ==, 0);
g_assert_false(triggered);
qemu_clock_step(2000000 * 4);
g_assert_cmpuint(ptimer_get_count(ptimer), ==, 0);
g_assert_true(triggered);
}
static void check_run_with_period_0(gconstpointer arg)
{
const uint8_t *policy = arg;
QEMUBH *bh = qemu_bh_new(ptimer_trigger, NULL);
ptimer_state *ptimer = ptimer_init(bh, *policy);
triggered = false;
ptimer_set_count(ptimer, 99);
ptimer_run(ptimer, 1);
qemu_clock_step(10 * NANOSECONDS_PER_SECOND);
g_assert_cmpuint(ptimer_get_count(ptimer), ==, 99);
g_assert_false(triggered);
}
static void check_run_with_delta_0(gconstpointer arg)
{
const uint8_t *policy = arg;
QEMUBH *bh = qemu_bh_new(ptimer_trigger, NULL);
ptimer_state *ptimer = ptimer_init(bh, *policy);
triggered = false;
ptimer_set_period(ptimer, 2000000);
ptimer_set_limit(ptimer, 99, 0);
ptimer_run(ptimer, 1);
g_assert_cmpuint(ptimer_get_count(ptimer), ==, 99);
g_assert_true(triggered);
triggered = false;
qemu_clock_step(2000000 + 100000);
g_assert_cmpuint(ptimer_get_count(ptimer), ==, 97);
g_assert_false(triggered);
qemu_clock_step(2000000 * 97);
g_assert_cmpuint(ptimer_get_count(ptimer), ==, 0);
g_assert_false(triggered);
qemu_clock_step(2000000 * 2);
g_assert_cmpuint(ptimer_get_count(ptimer), ==, 0);
g_assert_true(triggered);
triggered = false;
ptimer_set_count(ptimer, 0);
ptimer_run(ptimer, 0);
g_assert_cmpuint(ptimer_get_count(ptimer), ==, 99);
g_assert_true(triggered);
triggered = false;
qemu_clock_step(2000000 + 100000);
g_assert_cmpuint(ptimer_get_count(ptimer), ==, 97);
g_assert_false(triggered);
qemu_clock_step(2000000 * 98);
g_assert_cmpuint(ptimer_get_count(ptimer), ==, 98);
g_assert_true(triggered);
ptimer_stop(ptimer);
}
static void check_periodic_with_load_0(gconstpointer arg)
{
const uint8_t *policy = arg;
QEMUBH *bh = qemu_bh_new(ptimer_trigger, NULL);
ptimer_state *ptimer = ptimer_init(bh, *policy);
triggered = false;
ptimer_set_period(ptimer, 2000000);
ptimer_run(ptimer, 0);
g_assert_cmpuint(ptimer_get_count(ptimer), ==, 0);
g_assert_true(triggered);
triggered = false;
qemu_clock_step(2000000 + 100000);
g_assert_cmpuint(ptimer_get_count(ptimer), ==, 0);
g_assert_false(triggered);
ptimer_stop(ptimer);
}
static void check_oneshot_with_load_0(gconstpointer arg)
{
const uint8_t *policy = arg;
QEMUBH *bh = qemu_bh_new(ptimer_trigger, NULL);
ptimer_state *ptimer = ptimer_init(bh, *policy);
triggered = false;
ptimer_set_period(ptimer, 2000000);
ptimer_run(ptimer, 1);
g_assert_cmpuint(ptimer_get_count(ptimer), ==, 0);
g_assert_true(triggered);
triggered = false;
qemu_clock_step(2000000 + 100000);
g_assert_cmpuint(ptimer_get_count(ptimer), ==, 0);
g_assert_false(triggered);
triggered = false;
qemu_clock_step(2000000 + 100000);
g_assert_false(triggered);
}
static void add_ptimer_tests(uint8_t policy)
{
uint8_t *ppolicy = g_malloc(1);
char *policy_name = g_malloc(64);
*ppolicy = policy;
if (policy == PTIMER_POLICY_DEFAULT) {
g_sprintf(policy_name, "default");
}
qtest_add_data_func(
g_strdup_printf("/ptimer/set_count policy=%s", policy_name),
ppolicy, check_set_count);
qtest_add_data_func(
g_strdup_printf("/ptimer/set_limit policy=%s", policy_name),
ppolicy, check_set_limit);
qtest_add_data_func(
g_strdup_printf("/ptimer/oneshot policy=%s", policy_name),
ppolicy, check_oneshot);
qtest_add_data_func(
g_strdup_printf("/ptimer/periodic policy=%s", policy_name),
ppolicy, check_periodic);
qtest_add_data_func(
g_strdup_printf("/ptimer/on_the_fly_mode_change policy=%s", policy_name),
ppolicy, check_on_the_fly_mode_change);
qtest_add_data_func(
g_strdup_printf("/ptimer/on_the_fly_period_change policy=%s", policy_name),
ppolicy, check_on_the_fly_period_change);
qtest_add_data_func(
g_strdup_printf("/ptimer/on_the_fly_freq_change policy=%s", policy_name),
ppolicy, check_on_the_fly_freq_change);
qtest_add_data_func(
g_strdup_printf("/ptimer/run_with_period_0 policy=%s", policy_name),
ppolicy, check_run_with_period_0);
qtest_add_data_func(
g_strdup_printf("/ptimer/run_with_delta_0 policy=%s", policy_name),
ppolicy, check_run_with_delta_0);
qtest_add_data_func(
g_strdup_printf("/ptimer/periodic_with_load_0 policy=%s", policy_name),
ppolicy, check_periodic_with_load_0);
qtest_add_data_func(
g_strdup_printf("/ptimer/oneshot_with_load_0 policy=%s", policy_name),
ppolicy, check_oneshot_with_load_0);
}
int main(int argc, char **argv)
{
int i;
g_test_init(&argc, &argv, NULL);
for (i = 0; i < QEMU_CLOCK_MAX; i++) {
main_loop_tlg.tl[i] = g_new0(QEMUTimerList, 1);
}
add_ptimer_tests(PTIMER_POLICY_DEFAULT);
qtest_allowed = true;
return g_test_run();
}
/*
* QTest testcase for the ptimer
*
* Author: Dmitry Osipenko <digetx@gmail.com>
*
* This work is licensed under the terms of the GNU GPL, version 2 or later.
* See the COPYING file in the top-level directory.
*
*/
#ifndef PTIMER_TEST_H
#define PTIMER_TEST_H
extern bool qtest_allowed;
extern int64_t ptimer_test_time_ns;
struct QEMUTimerList {
QEMUTimer active_timers;
};
#endif
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册