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'
 -----BEGIN PGP SIGNATURE-----
 Version: GnuPG v1
 
 iQIcBAABCAAGBQJX5BLWAAoJEDwlJe0UNgzedDEP/0eyPOuB4VLDdPGxnd/JbExh
 WZfXZ43CzgYQqiSlRtS+rmDSsVHXV7xlPuV5VV4FkuPPdk/+ek3pw11Ou5Tv+98T
 BP4ucRmL5D58koMqrwJb9GAf3a606D1Gk1NaOcl4XthdiuMRi8ARj98GwltHZmkg
 vjYY6ouYhGYeoJwblQ9N9466VcenrhXgL0fOSPWT48ymO9tqNHFvek267QTL3EyN
 6WkrS7nak7tN2V8UyXk7oGtei54BaWjW65bMcJO6UaVbXck3u3HRdjMZhyXbXyKE
 6H6bIav3Y4k+qmyFXkiA9PgsA9ZdAVge0LRwLIFDmGD6ELOwzTe+/C5sxAuZVjuO
 vcQv7wLPy/1gSR9yNy95mTiMJ79DvdQbnciOfSmVbm8bAglBCiiVOiCswEPjWIcp
 1XrQlK7j0ZKfR7+U2Ggu6f89ruiQmIgiJmGvxeb51EbVoNLQjR8VsN+podCTX7B+
 BmGx8dZYZ3DacqcaTmixdY5cnyu7AP5GXEGmOzgYvpe/vvgkpbs7xphBynFq+4j4
 1CUlDlvCBZqRmy4G1zeQCl8dOLpYOMPMrYYg/2GHcYsEn+GfKTjBrTyEpcpSo889
 XKCNdgLBd+bzVIpXn5GFuoHyG/M0p/OQKWx8hhxNazfAUfYpLkrGgCh++7p7UjRP
 yIcvj0asSHYM+HL9uIX0
 =qIm/
 -----END PGP SIGNATURE-----

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: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
Peter Maydell 2016-09-22 18:23:14 +01:00
commit e678c56f16
55 changed files with 2092 additions and 557 deletions

View File

@ -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;

View File

@ -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

197
hw/arm/aspeed.c Normal file
View File

@ -0,0 +1,197 @@
/*
* OpenPOWER Palmetto BMC
*
* Andrew Jeffery <andrew@aj.id.au>
*
* Copyright 2016 IBM Corp.
*
* This code is licensed under the GPL version 2 or later. See
* the COPYING file in the top-level directory.
*/
#include "qemu/osdep.h"
#include "qapi/error.h"
#include "qemu-common.h"
#include "cpu.h"
#include "exec/address-spaces.h"
#include "hw/arm/arm.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 aspeed_board_binfo = {
.board_id = -1, /* device-tree-only board */
.nb_cpus = 1,
};
typedef struct AspeedBoardState {
AspeedSoCState soc;
MemoryRegion ram;
} AspeedBoardState;
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 ;
for (i = 0; i < s->num_cs; ++i) {
AspeedSMCFlash *fl = &s->flashes[i];
DriveInfo *dinfo = drive_get_next(IF_MTD);
qemu_irq cs_line;
/*
* FIXME: check that we are not using a flash module exceeding
* the controller segment size
*/
fl->flash = ssi_create_slave_no_init(s->spi, flashtype);
if (dinfo) {
qdev_prop_set_drive(fl->flash, "drive", blk_by_legacy_dinfo(dinfo),
errp);
}
qdev_init_nofail(fl->flash);
cs_line = qdev_get_gpio_in_named(fl->flash, SSI_GPIO_CS, 0);
sysbus_connect_irq(SYS_BUS_DEVICE(s), i + 1, cs_line);
}
}
static void aspeed_board_init(MachineState *machine,
const AspeedBoardConfig *cfg)
{
AspeedBoardState *bmc;
AspeedSoCClass *sc;
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(), sc->info->sdram_base,
&bmc->ram);
object_property_add_const_link(OBJECT(&bmc->soc), "ram", OBJECT(&bmc->ram),
&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;
arm_load_kernel(ARM_CPU(first_cpu), &aspeed_board_binfo);
}
static void palmetto_bmc_init(MachineState *machine)
{
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;
}
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)

View File

@ -1,5 +1,5 @@
/*
* 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 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 AST2400_FMC_FLASH_BASE 0x20000000
#define AST2400_SPI_FLASH_BASE 0x30000000
#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)

View File

@ -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,

View File

@ -1,102 +0,0 @@
/*
* OpenPOWER Palmetto BMC
*
* Andrew Jeffery <andrew@aj.id.au>
*
* Copyright 2016 IBM Corp.
*
* This code is licensed under the GPL version 2 or later. See
* the COPYING file in the top-level directory.
*/
#include "qemu/osdep.h"
#include "qapi/error.h"
#include "qemu-common.h"
#include "cpu.h"
#include "exec/address-spaces.h"
#include "hw/arm/arm.h"
#include "hw/arm/ast2400.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,
.nb_cpus = 1,
};
typedef struct PalmettoBMCState {
AST2400State soc;
MemoryRegion ram;
} PalmettoBMCState;
static void palmetto_bmc_init_flashes(AspeedSMCState *s, const char *flashtype,
Error **errp)
{
int i ;
for (i = 0; i < s->num_cs; ++i) {
AspeedSMCFlash *fl = &s->flashes[i];
DriveInfo *dinfo = drive_get_next(IF_MTD);
qemu_irq cs_line;
/*
* FIXME: check that we are not using a flash module exceeding
* the controller segment size
*/
fl->flash = ssi_create_slave_no_init(s->spi, flashtype);
if (dinfo) {
qdev_prop_set_drive(fl->flash, "drive", blk_by_legacy_dinfo(dinfo),
errp);
}
qdev_init_nofail(fl->flash);
cs_line = qdev_get_gpio_in_named(fl->flash, SSI_GPIO_CS, 0);
sysbus_connect_irq(SYS_BUS_DEVICE(s), i + 1, cs_line);
}
}
static void palmetto_bmc_init(MachineState *machine)
{
PalmettoBMCState *bmc;
bmc = g_new0(PalmettoBMCState, 1);
object_initialize(&bmc->soc, (sizeof(bmc->soc)), TYPE_AST2400);
object_property_add_child(OBJECT(machine), "soc", OBJECT(&bmc->soc),
&error_abort);
memory_region_allocate_system_memory(&bmc->ram, NULL, "ram", ram_size);
memory_region_add_subregion(get_system_memory(), AST2400_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);
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);
}
static void palmetto_bmc_machine_init(MachineClass *mc)
{
mc->desc = "OpenPOWER Palmetto BMC";
mc->init = palmetto_bmc_init;
mc->max_cpus = 1;
mc->no_sdcard = 1;
mc->no_floppy = 1;
mc->no_cdrom = 1;
mc->no_sdcard = 1;
mc->no_parallel = 1;
}
DEFINE_MACHINE("palmetto-bmc", palmetto_bmc_machine_init);

View File

@ -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);

View File

@ -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;

View File

@ -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;
}

View File

@ -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 = {

View File

@ -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;

View File

@ -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;

View File

@ -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,

View File

@ -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)
{

View File

@ -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(),
};

View File

@ -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];

View File

@ -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];

View File

@ -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];

View File

@ -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];

View File

@ -26,6 +26,8 @@
#include <zlib.h> /* For crc32 */
#include "hw/net/cadence_gem.h"
#include "qapi/error.h"
#include "qemu/log.h"
#include "net/checksum.h"
#ifdef CADENCE_GEM_ERR_DEBUG
@ -141,6 +143,61 @@
#define GEM_DESCONF6 (0x00000294/4)
#define GEM_DESCONF7 (0x00000298/4)
#define GEM_INT_Q1_STATUS (0x00000400 / 4)
#define GEM_INT_Q1_MASK (0x00000640 / 4)
#define GEM_TRANSMIT_Q1_PTR (0x00000440 / 4)
#define GEM_TRANSMIT_Q15_PTR (GEM_TRANSMIT_Q1_PTR + 14)
#define GEM_RECEIVE_Q1_PTR (0x00000480 / 4)
#define GEM_RECEIVE_Q15_PTR (GEM_RECEIVE_Q1_PTR + 14)
#define GEM_INT_Q1_ENABLE (0x00000600 / 4)
#define GEM_INT_Q7_ENABLE (GEM_INT_Q1_ENABLE + 6)
#define GEM_INT_Q8_ENABLE (0x00000660 / 4)
#define GEM_INT_Q15_ENABLE (GEM_INT_Q8_ENABLE + 7)
#define GEM_INT_Q1_DISABLE (0x00000620 / 4)
#define GEM_INT_Q7_DISABLE (GEM_INT_Q1_DISABLE + 6)
#define GEM_INT_Q8_DISABLE (0x00000680 / 4)
#define GEM_INT_Q15_DISABLE (GEM_INT_Q8_DISABLE + 7)
#define GEM_INT_Q1_MASK (0x00000640 / 4)
#define GEM_INT_Q7_MASK (GEM_INT_Q1_MASK + 6)
#define GEM_INT_Q8_MASK (0x000006A0 / 4)
#define GEM_INT_Q15_MASK (GEM_INT_Q8_MASK + 7)
#define GEM_SCREENING_TYPE1_REGISTER_0 (0x00000500 / 4)
#define GEM_ST1R_UDP_PORT_MATCH_ENABLE (1 << 29)
#define GEM_ST1R_DSTC_ENABLE (1 << 28)
#define GEM_ST1R_UDP_PORT_MATCH_SHIFT (12)
#define GEM_ST1R_UDP_PORT_MATCH_WIDTH (27 - GEM_ST1R_UDP_PORT_MATCH_SHIFT + 1)
#define GEM_ST1R_DSTC_MATCH_SHIFT (4)
#define GEM_ST1R_DSTC_MATCH_WIDTH (11 - GEM_ST1R_DSTC_MATCH_SHIFT + 1)
#define GEM_ST1R_QUEUE_SHIFT (0)
#define GEM_ST1R_QUEUE_WIDTH (3 - GEM_ST1R_QUEUE_SHIFT + 1)
#define GEM_SCREENING_TYPE2_REGISTER_0 (0x00000540 / 4)
#define GEM_ST2R_COMPARE_A_ENABLE (1 << 18)
#define GEM_ST2R_COMPARE_A_SHIFT (13)
#define GEM_ST2R_COMPARE_WIDTH (17 - GEM_ST2R_COMPARE_A_SHIFT + 1)
#define GEM_ST2R_ETHERTYPE_ENABLE (1 << 12)
#define GEM_ST2R_ETHERTYPE_INDEX_SHIFT (9)
#define GEM_ST2R_ETHERTYPE_INDEX_WIDTH (11 - GEM_ST2R_ETHERTYPE_INDEX_SHIFT \
+ 1)
#define GEM_ST2R_QUEUE_SHIFT (0)
#define GEM_ST2R_QUEUE_WIDTH (3 - GEM_ST2R_QUEUE_SHIFT + 1)
#define GEM_SCREENING_TYPE2_ETHERTYPE_REG_0 (0x000006e0 / 4)
#define GEM_TYPE2_COMPARE_0_WORD_0 (0x00000700 / 4)
#define GEM_T2CW1_COMPARE_OFFSET_SHIFT (7)
#define GEM_T2CW1_COMPARE_OFFSET_WIDTH (8 - GEM_T2CW1_COMPARE_OFFSET_SHIFT + 1)
#define GEM_T2CW1_OFFSET_VALUE_SHIFT (0)
#define GEM_T2CW1_OFFSET_VALUE_WIDTH (6 - GEM_T2CW1_OFFSET_VALUE_SHIFT + 1)
/*****************************************/
#define GEM_NWCTRL_TXSTART 0x00000200 /* Transmit Enable */
#define GEM_NWCTRL_TXENA 0x00000008 /* Transmit Enable */
@ -284,9 +341,9 @@ static inline unsigned tx_desc_get_length(unsigned *desc)
return desc[1] & DESC_1_LENGTH;
}
static inline void print_gem_tx_desc(unsigned *desc)
static inline void print_gem_tx_desc(unsigned *desc, uint8_t queue)
{
DB_PRINT("TXDESC:\n");
DB_PRINT("TXDESC (queue %" PRId8 "):\n", queue);
DB_PRINT("bufaddr: 0x%08x\n", *desc);
DB_PRINT("used_hw: %d\n", tx_desc_get_used(desc));
DB_PRINT("wrap: %d\n", tx_desc_get_wrap(desc));
@ -416,6 +473,7 @@ static void phy_update_link(CadenceGEMState *s)
static int gem_can_receive(NetClientState *nc)
{
CadenceGEMState *s;
int i;
s = qemu_get_nic_opaque(nc);
@ -428,18 +486,20 @@ static int gem_can_receive(NetClientState *nc)
return 0;
}
if (rx_desc_get_ownership(s->rx_desc) == 1) {
if (s->can_rx_state != 2) {
s->can_rx_state = 2;
DB_PRINT("can't receive - busy buffer descriptor 0x%x\n",
s->rx_desc_addr);
for (i = 0; i < s->num_priority_queues; i++) {
if (rx_desc_get_ownership(s->rx_desc[i]) == 1) {
if (s->can_rx_state != 2) {
s->can_rx_state = 2;
DB_PRINT("can't receive - busy buffer descriptor (q%d) 0x%x\n",
i, s->rx_desc_addr[i]);
}
return 0;
}
return 0;
}
if (s->can_rx_state != 0) {
s->can_rx_state = 0;
DB_PRINT("can receive 0x%x\n", s->rx_desc_addr);
DB_PRINT("can receive\n");
}
return 1;
}
@ -450,9 +510,20 @@ static int gem_can_receive(NetClientState *nc)
*/
static void gem_update_int_status(CadenceGEMState *s)
{
if (s->regs[GEM_ISR]) {
DB_PRINT("asserting int. (0x%08x)\n", s->regs[GEM_ISR]);
qemu_set_irq(s->irq, 1);
int i;
if ((s->num_priority_queues == 1) && s->regs[GEM_ISR]) {
/* No priority queues, just trigger the interrupt */
DB_PRINT("asserting int.\n", i);
qemu_set_irq(s->irq[0], 1);
return;
}
for (i = 0; i < s->num_priority_queues; ++i) {
if (s->regs[GEM_INT_Q1_STATUS + i]) {
DB_PRINT("asserting int. (q=%d)\n", i);
qemu_set_irq(s->irq[i], 1);
}
}
}
@ -601,17 +672,137 @@ static int gem_mac_address_filter(CadenceGEMState *s, const uint8_t *packet)
return GEM_RX_REJECT;
}
static void gem_get_rx_desc(CadenceGEMState *s)
/* Figure out which queue the received data should be sent to */
static int get_queue_from_screen(CadenceGEMState *s, uint8_t *rxbuf_ptr,
unsigned rxbufsize)
{
DB_PRINT("read descriptor 0x%x\n", (unsigned)s->rx_desc_addr);
uint32_t reg;
bool matched, mismatched;
int i, j;
for (i = 0; i < s->num_type1_screeners; i++) {
reg = s->regs[GEM_SCREENING_TYPE1_REGISTER_0 + i];
matched = false;
mismatched = false;
/* Screening is based on UDP Port */
if (reg & GEM_ST1R_UDP_PORT_MATCH_ENABLE) {
uint16_t udp_port = rxbuf_ptr[14 + 22] << 8 | rxbuf_ptr[14 + 23];
if (udp_port == extract32(reg, GEM_ST1R_UDP_PORT_MATCH_SHIFT,
GEM_ST1R_UDP_PORT_MATCH_WIDTH)) {
matched = true;
} else {
mismatched = true;
}
}
/* Screening is based on DS/TC */
if (reg & GEM_ST1R_DSTC_ENABLE) {
uint8_t dscp = rxbuf_ptr[14 + 1];
if (dscp == extract32(reg, GEM_ST1R_DSTC_MATCH_SHIFT,
GEM_ST1R_DSTC_MATCH_WIDTH)) {
matched = true;
} else {
mismatched = true;
}
}
if (matched && !mismatched) {
return extract32(reg, GEM_ST1R_QUEUE_SHIFT, GEM_ST1R_QUEUE_WIDTH);
}
}
for (i = 0; i < s->num_type2_screeners; i++) {
reg = s->regs[GEM_SCREENING_TYPE2_REGISTER_0 + i];
matched = false;
mismatched = false;
if (reg & GEM_ST2R_ETHERTYPE_ENABLE) {
uint16_t type = rxbuf_ptr[12] << 8 | rxbuf_ptr[13];
int et_idx = extract32(reg, GEM_ST2R_ETHERTYPE_INDEX_SHIFT,
GEM_ST2R_ETHERTYPE_INDEX_WIDTH);
if (et_idx > s->num_type2_screeners) {
qemu_log_mask(LOG_GUEST_ERROR, "Out of range ethertype "
"register index: %d\n", et_idx);
}
if (type == s->regs[GEM_SCREENING_TYPE2_ETHERTYPE_REG_0 +
et_idx]) {
matched = true;
} else {
mismatched = true;
}
}
/* Compare A, B, C */
for (j = 0; j < 3; j++) {
uint32_t cr0, cr1, mask;
uint16_t rx_cmp;
int offset;
int cr_idx = extract32(reg, GEM_ST2R_COMPARE_A_SHIFT + j * 6,
GEM_ST2R_COMPARE_WIDTH);
if (!(reg & (GEM_ST2R_COMPARE_A_ENABLE << (j * 6)))) {
continue;
}
if (cr_idx > s->num_type2_screeners) {
qemu_log_mask(LOG_GUEST_ERROR, "Out of range compare "
"register index: %d\n", cr_idx);
}
cr0 = s->regs[GEM_TYPE2_COMPARE_0_WORD_0 + cr_idx * 2];
cr1 = s->regs[GEM_TYPE2_COMPARE_0_WORD_0 + cr_idx * 2 + 1];
offset = extract32(cr1, GEM_T2CW1_OFFSET_VALUE_SHIFT,
GEM_T2CW1_OFFSET_VALUE_WIDTH);
switch (extract32(cr1, GEM_T2CW1_COMPARE_OFFSET_SHIFT,
GEM_T2CW1_COMPARE_OFFSET_WIDTH)) {
case 3: /* Skip UDP header */
qemu_log_mask(LOG_UNIMP, "TCP compare offsets"
"unimplemented - assuming UDP\n");
offset += 8;
/* Fallthrough */
case 2: /* skip the IP header */
offset += 20;
/* Fallthrough */
case 1: /* Count from after the ethertype */
offset += 14;
break;
case 0:
/* Offset from start of frame */
break;
}
rx_cmp = rxbuf_ptr[offset] << 8 | rxbuf_ptr[offset];
mask = extract32(cr0, 0, 16);
if ((rx_cmp & mask) == (extract32(cr0, 16, 16) & mask)) {
matched = true;
} else {
mismatched = true;
}
}
if (matched && !mismatched) {
return extract32(reg, GEM_ST2R_QUEUE_SHIFT, GEM_ST2R_QUEUE_WIDTH);
}
}
/* We made it here, assume it's queue 0 */
return 0;
}
static void gem_get_rx_desc(CadenceGEMState *s, int q)
{
DB_PRINT("read descriptor 0x%x\n", (unsigned)s->rx_desc_addr[q]);
/* read current descriptor */
cpu_physical_memory_read(s->rx_desc_addr,
(uint8_t *)s->rx_desc, sizeof(s->rx_desc));
cpu_physical_memory_read(s->rx_desc_addr[0],
(uint8_t *)s->rx_desc[0], sizeof(s->rx_desc[0]));
/* Descriptor owned by software ? */
if (rx_desc_get_ownership(s->rx_desc) == 1) {
if (rx_desc_get_ownership(s->rx_desc[q]) == 1) {
DB_PRINT("descriptor 0x%x owned by sw.\n",
(unsigned)s->rx_desc_addr);
(unsigned)s->rx_desc_addr[q]);
s->regs[GEM_RXSTATUS] |= GEM_RXSTATUS_NOBUF;
s->regs[GEM_ISR] |= GEM_INT_RXUSED & ~(s->regs[GEM_IMR]);
/* Handle interrupt consequences */
@ -632,6 +823,7 @@ static ssize_t gem_receive(NetClientState *nc, const uint8_t *buf, size_t size)
uint8_t *rxbuf_ptr;
bool first_desc = true;
int maf;
int q = 0;
s = qemu_get_nic_opaque(nc);
@ -710,6 +902,9 @@ static ssize_t gem_receive(NetClientState *nc, const uint8_t *buf, size_t size)
DB_PRINT("config bufsize: %d packet size: %ld\n", rxbufsize, size);
/* Find which queue we are targetting */
q = get_queue_from_screen(s, rxbuf_ptr, rxbufsize);
while (bytes_to_copy) {
/* Do nothing if receive is not enabled. */
if (!gem_can_receive(nc)) {
@ -718,56 +913,59 @@ static ssize_t gem_receive(NetClientState *nc, const uint8_t *buf, size_t size)
}
DB_PRINT("copy %d bytes to 0x%x\n", MIN(bytes_to_copy, rxbufsize),
rx_desc_get_buffer(s->rx_desc));
rx_desc_get_buffer(s->rx_desc[q]));
/* Copy packet data to emulated DMA buffer */
cpu_physical_memory_write(rx_desc_get_buffer(s->rx_desc) + rxbuf_offset,
cpu_physical_memory_write(rx_desc_get_buffer(s->rx_desc[q]) +
rxbuf_offset,
rxbuf_ptr, MIN(bytes_to_copy, rxbufsize));
rxbuf_ptr += MIN(bytes_to_copy, rxbufsize);
bytes_to_copy -= MIN(bytes_to_copy, rxbufsize);
/* Update the descriptor. */
if (first_desc) {
rx_desc_set_sof(s->rx_desc);
rx_desc_set_sof(s->rx_desc[q]);
first_desc = false;
}
if (bytes_to_copy == 0) {
rx_desc_set_eof(s->rx_desc);
rx_desc_set_length(s->rx_desc, size);
rx_desc_set_eof(s->rx_desc[q]);
rx_desc_set_length(s->rx_desc[q], size);
}
rx_desc_set_ownership(s->rx_desc);
rx_desc_set_ownership(s->rx_desc[q]);
switch (maf) {
case GEM_RX_PROMISCUOUS_ACCEPT:
break;
case GEM_RX_BROADCAST_ACCEPT:
rx_desc_set_broadcast(s->rx_desc);
rx_desc_set_broadcast(s->rx_desc[q]);
break;
case GEM_RX_UNICAST_HASH_ACCEPT:
rx_desc_set_unicast_hash(s->rx_desc);
rx_desc_set_unicast_hash(s->rx_desc[q]);
break;
case GEM_RX_MULTICAST_HASH_ACCEPT:
rx_desc_set_multicast_hash(s->rx_desc);
rx_desc_set_multicast_hash(s->rx_desc[q]);
break;
case GEM_RX_REJECT:
abort();
default: /* SAR */
rx_desc_set_sar(s->rx_desc, maf);
rx_desc_set_sar(s->rx_desc[q], maf);
}
/* Descriptor write-back. */
cpu_physical_memory_write(s->rx_desc_addr,
(uint8_t *)s->rx_desc, sizeof(s->rx_desc));
cpu_physical_memory_write(s->rx_desc_addr[q],
(uint8_t *)s->rx_desc[q],
sizeof(s->rx_desc[q]));
/* Next descriptor */
if (rx_desc_get_wrap(s->rx_desc)) {
if (rx_desc_get_wrap(s->rx_desc[q])) {
DB_PRINT("wrapping RX descriptor list\n");
s->rx_desc_addr = s->regs[GEM_RXQBASE];
s->rx_desc_addr[q] = s->regs[GEM_RXQBASE];
} else {
DB_PRINT("incrementing RX descriptor list\n");
s->rx_desc_addr += 8;
s->rx_desc_addr[q] += 8;
}
gem_get_rx_desc(s);
gem_get_rx_desc(s, q);
}
/* Count it */
@ -839,6 +1037,7 @@ static void gem_transmit(CadenceGEMState *s)
uint8_t tx_packet[2048];
uint8_t *p;
unsigned total_bytes;
int q = 0;
/* Do nothing if transmit is not enabled. */
if (!(s->regs[GEM_NWCTRL] & GEM_NWCTRL_TXENA)) {
@ -854,110 +1053,123 @@ static void gem_transmit(CadenceGEMState *s)
p = tx_packet;
total_bytes = 0;
/* read current descriptor */
packet_desc_addr = s->tx_desc_addr;
for (q = s->num_priority_queues - 1; q >= 0; q--) {
/* read current descriptor */
packet_desc_addr = s->tx_desc_addr[q];
DB_PRINT("read descriptor 0x%" HWADDR_PRIx "\n", packet_desc_addr);
cpu_physical_memory_read(packet_desc_addr,
(uint8_t *)desc, sizeof(desc));
/* Handle all descriptors owned by hardware */
while (tx_desc_get_used(desc) == 0) {
/* Do nothing if transmit is not enabled. */
if (!(s->regs[GEM_NWCTRL] & GEM_NWCTRL_TXENA)) {
return;
}
print_gem_tx_desc(desc);
/* The real hardware would eat this (and possibly crash).
* For QEMU let's lend a helping hand.
*/
if ((tx_desc_get_buffer(desc) == 0) ||
(tx_desc_get_length(desc) == 0)) {
DB_PRINT("Invalid TX descriptor @ 0x%x\n",
(unsigned)packet_desc_addr);
break;
}
if (tx_desc_get_length(desc) > sizeof(tx_packet) - (p - tx_packet)) {
DB_PRINT("TX descriptor @ 0x%x too large: size 0x%x space 0x%x\n",
(unsigned)packet_desc_addr,
(unsigned)tx_desc_get_length(desc),
sizeof(tx_packet) - (p - tx_packet));
break;
}
/* Gather this fragment of the packet from "dma memory" to our contig.
* buffer.
*/
cpu_physical_memory_read(tx_desc_get_buffer(desc), p,
tx_desc_get_length(desc));
p += tx_desc_get_length(desc);
total_bytes += tx_desc_get_length(desc);
/* Last descriptor for this packet; hand the whole thing off */
if (tx_desc_get_last(desc)) {
unsigned desc_first[2];
/* Modify the 1st descriptor of this packet to be owned by
* the processor.
*/
cpu_physical_memory_read(s->tx_desc_addr, (uint8_t *)desc_first,
sizeof(desc_first));
tx_desc_set_used(desc_first);
cpu_physical_memory_write(s->tx_desc_addr, (uint8_t *)desc_first,
sizeof(desc_first));
/* Advance the hardware current descriptor past this packet */
if (tx_desc_get_wrap(desc)) {
s->tx_desc_addr = s->regs[GEM_TXQBASE];
} else {
s->tx_desc_addr = packet_desc_addr + 8;
}
DB_PRINT("TX descriptor next: 0x%08x\n", s->tx_desc_addr);
s->regs[GEM_TXSTATUS] |= GEM_TXSTATUS_TXCMPL;
s->regs[GEM_ISR] |= GEM_INT_TXCMPL & ~(s->regs[GEM_IMR]);
/* Handle interrupt consequences */
gem_update_int_status(s);
/* Is checksum offload enabled? */
if (s->regs[GEM_DMACFG] & GEM_DMACFG_TXCSUM_OFFL) {
net_checksum_calculate(tx_packet, total_bytes);
}
/* Update MAC statistics */
gem_transmit_updatestats(s, tx_packet, total_bytes);
/* Send the packet somewhere */
if (s->phy_loop || (s->regs[GEM_NWCTRL] & GEM_NWCTRL_LOCALLOOP)) {
gem_receive(qemu_get_queue(s->nic), tx_packet, total_bytes);
} else {
qemu_send_packet(qemu_get_queue(s->nic), tx_packet,
total_bytes);
}
/* Prepare for next packet */
p = tx_packet;
total_bytes = 0;
}
/* read next descriptor */
if (tx_desc_get_wrap(desc)) {
tx_desc_set_last(desc);
packet_desc_addr = s->regs[GEM_TXQBASE];
} else {
packet_desc_addr += 8;
}
DB_PRINT("read descriptor 0x%" HWADDR_PRIx "\n", packet_desc_addr);
cpu_physical_memory_read(packet_desc_addr,
(uint8_t *)desc, sizeof(desc));
}
/* Handle all descriptors owned by hardware */
while (tx_desc_get_used(desc) == 0) {
if (tx_desc_get_used(desc)) {
s->regs[GEM_TXSTATUS] |= GEM_TXSTATUS_USED;
s->regs[GEM_ISR] |= GEM_INT_TXUSED & ~(s->regs[GEM_IMR]);
gem_update_int_status(s);
/* Do nothing if transmit is not enabled. */
if (!(s->regs[GEM_NWCTRL] & GEM_NWCTRL_TXENA)) {
return;
}
print_gem_tx_desc(desc, q);
/* The real hardware would eat this (and possibly crash).
* For QEMU let's lend a helping hand.
*/
if ((tx_desc_get_buffer(desc) == 0) ||
(tx_desc_get_length(desc) == 0)) {
DB_PRINT("Invalid TX descriptor @ 0x%x\n",
(unsigned)packet_desc_addr);
break;
}
if (tx_desc_get_length(desc) > sizeof(tx_packet) -
(p - tx_packet)) {
DB_PRINT("TX descriptor @ 0x%x too large: size 0x%x space " \
"0x%x\n", (unsigned)packet_desc_addr,
(unsigned)tx_desc_get_length(desc),
sizeof(tx_packet) - (p - tx_packet));
break;
}
/* Gather this fragment of the packet from "dma memory" to our
* contig buffer.
*/
cpu_physical_memory_read(tx_desc_get_buffer(desc), p,
tx_desc_get_length(desc));
p += tx_desc_get_length(desc);
total_bytes += tx_desc_get_length(desc);
/* Last descriptor for this packet; hand the whole thing off */
if (tx_desc_get_last(desc)) {
unsigned desc_first[2];
/* Modify the 1st descriptor of this packet to be owned by
* the processor.
*/
cpu_physical_memory_read(s->tx_desc_addr[q],
(uint8_t *)desc_first,
sizeof(desc_first));
tx_desc_set_used(desc_first);
cpu_physical_memory_write(s->tx_desc_addr[q],
(uint8_t *)desc_first,
sizeof(desc_first));
/* Advance the hardware current descriptor past this packet */
if (tx_desc_get_wrap(desc)) {
s->tx_desc_addr[q] = s->regs[GEM_TXQBASE];
} else {
s->tx_desc_addr[q] = packet_desc_addr + 8;
}
DB_PRINT("TX descriptor next: 0x%08x\n", s->tx_desc_addr[q]);
s->regs[GEM_TXSTATUS] |= GEM_TXSTATUS_TXCMPL;
s->regs[GEM_ISR] |= GEM_INT_TXCMPL & ~(s->regs[GEM_IMR]);
/* Update queue interrupt status */
if (s->num_priority_queues > 1) {
s->regs[GEM_INT_Q1_STATUS + q] |=
GEM_INT_TXCMPL & ~(s->regs[GEM_INT_Q1_MASK + q]);
}
/* Handle interrupt consequences */
gem_update_int_status(s);
/* Is checksum offload enabled? */
if (s->regs[GEM_DMACFG] & GEM_DMACFG_TXCSUM_OFFL) {
net_checksum_calculate(tx_packet, total_bytes);
}
/* Update MAC statistics */
gem_transmit_updatestats(s, tx_packet, total_bytes);
/* Send the packet somewhere */
if (s->phy_loop || (s->regs[GEM_NWCTRL] &
GEM_NWCTRL_LOCALLOOP)) {
gem_receive(qemu_get_queue(s->nic), tx_packet,
total_bytes);
} else {
qemu_send_packet(qemu_get_queue(s->nic), tx_packet,
total_bytes);
}
/* Prepare for next packet */
p = tx_packet;
total_bytes = 0;
}
/* read next descriptor */
if (tx_desc_get_wrap(desc)) {
tx_desc_set_last(desc);
packet_desc_addr = s->regs[GEM_TXQBASE];
} else {
packet_desc_addr += 8;
}
DB_PRINT("read descriptor 0x%" HWADDR_PRIx "\n", packet_desc_addr);
cpu_physical_memory_read(packet_desc_addr,
(uint8_t *)desc, sizeof(desc));
}
if (tx_desc_get_used(desc)) {
s->regs[GEM_TXSTATUS] |= GEM_TXSTATUS_USED;
s->regs[GEM_ISR] |= GEM_INT_TXUSED & ~(s->regs[GEM_IMR]);
gem_update_int_status(s);
}
}
}
@ -1065,7 +1277,7 @@ static uint64_t gem_read(void *opaque, hwaddr offset, unsigned size)
{
CadenceGEMState *s;
uint32_t retval;
int i;
s = (CadenceGEMState *)opaque;
offset >>= 2;
@ -1075,8 +1287,10 @@ static uint64_t gem_read(void *opaque, hwaddr offset, unsigned size)
switch (offset) {
case GEM_ISR:
DB_PRINT("lowering irq on ISR read\n");
qemu_set_irq(s->irq, 0);
DB_PRINT("lowering irqs on ISR read\n");
for (i = 0; i < s->num_priority_queues; ++i) {
qemu_set_irq(s->irq[i], 0);
}
break;
case GEM_PHYMNTNC:
if (retval & GEM_PHYMNTNC_OP_R) {
@ -1101,6 +1315,7 @@ static uint64_t gem_read(void *opaque, hwaddr offset, unsigned size)
retval &= ~(s->regs_wo[offset]);
DB_PRINT("0x%08x\n", retval);
gem_update_int_status(s);
return retval;
}
@ -1113,6 +1328,7 @@ static void gem_write(void *opaque, hwaddr offset, uint64_t val,
{
CadenceGEMState *s = (CadenceGEMState *)opaque;
uint32_t readonly;
int i;
DB_PRINT("offset: 0x%04x write: 0x%08x ", (unsigned)offset, (unsigned)val);
offset >>= 2;
@ -1132,14 +1348,18 @@ static void gem_write(void *opaque, hwaddr offset, uint64_t val,
switch (offset) {
case GEM_NWCTRL:
if (val & GEM_NWCTRL_RXENA) {
gem_get_rx_desc(s);
for (i = 0; i < s->num_priority_queues; ++i) {
gem_get_rx_desc(s, i);
}
}
if (val & GEM_NWCTRL_TXSTART) {
gem_transmit(s);
}
if (!(val & GEM_NWCTRL_TXENA)) {
/* Reset to start of Q when transmit disabled. */
s->tx_desc_addr = s->regs[GEM_TXQBASE];
for (i = 0; i < s->num_priority_queues; i++) {
s->tx_desc_addr[i] = s->regs[GEM_TXQBASE];
}
}
if (gem_can_receive(qemu_get_queue(s->nic))) {
qemu_flush_queued_packets(qemu_get_queue(s->nic));
@ -1150,10 +1370,16 @@ static void gem_write(void *opaque, hwaddr offset, uint64_t val,
gem_update_int_status(s);
break;
case GEM_RXQBASE:
s->rx_desc_addr = val;
s->rx_desc_addr[0] = val;
break;
case GEM_RECEIVE_Q1_PTR ... GEM_RECEIVE_Q15_PTR:
s->rx_desc_addr[offset - GEM_RECEIVE_Q1_PTR + 1] = val;
break;
case GEM_TXQBASE:
s->tx_desc_addr = val;
s->tx_desc_addr[0] = val;
break;
case GEM_TRANSMIT_Q1_PTR ... GEM_TRANSMIT_Q15_PTR:
s->tx_desc_addr[offset - GEM_TRANSMIT_Q1_PTR + 1] = val;
break;
case GEM_RXSTATUS:
gem_update_int_status(s);
@ -1162,10 +1388,26 @@ static void gem_write(void *opaque, hwaddr offset, uint64_t val,
s->regs[GEM_IMR] &= ~val;
gem_update_int_status(s);
break;
case GEM_INT_Q1_ENABLE ... GEM_INT_Q7_ENABLE:
s->regs[GEM_INT_Q1_MASK + offset - GEM_INT_Q1_ENABLE] &= ~val;
gem_update_int_status(s);
break;
case GEM_INT_Q8_ENABLE ... GEM_INT_Q15_ENABLE:
s->regs[GEM_INT_Q8_MASK + offset - GEM_INT_Q8_ENABLE] &= ~val;
gem_update_int_status(s);
break;
case GEM_IDR:
s->regs[GEM_IMR] |= val;
gem_update_int_status(s);
break;
case GEM_INT_Q1_DISABLE ... GEM_INT_Q7_DISABLE:
s->regs[GEM_INT_Q1_MASK + offset - GEM_INT_Q1_DISABLE] |= val;
gem_update_int_status(s);
break;
case GEM_INT_Q8_DISABLE ... GEM_INT_Q15_DISABLE:
s->regs[GEM_INT_Q8_MASK + offset - GEM_INT_Q8_DISABLE] |= val;
gem_update_int_status(s);
break;
case GEM_SPADDR1LO:
case GEM_SPADDR2LO:
case GEM_SPADDR3LO:
@ -1202,8 +1444,11 @@ static const MemoryRegionOps gem_ops = {
static void gem_set_link(NetClientState *nc)
{
CadenceGEMState *s = qemu_get_nic_opaque(nc);
DB_PRINT("\n");
phy_update_link(qemu_get_nic_opaque(nc));
phy_update_link(s);
gem_update_int_status(s);
}
static NetClientInfo net_gem_info = {
@ -1214,36 +1459,62 @@ static NetClientInfo net_gem_info = {
.link_status_changed = gem_set_link,
};
static int gem_init(SysBusDevice *sbd)
static void gem_realize(DeviceState *dev, Error **errp)
{
DeviceState *dev = DEVICE(sbd);
CadenceGEMState *s = CADENCE_GEM(dev);
int i;
if (s->num_priority_queues == 0 ||
s->num_priority_queues > MAX_PRIORITY_QUEUES) {
error_setg(errp, "Invalid num-priority-queues value: %" PRIx8,
s->num_priority_queues);
return;
} else if (s->num_type1_screeners > MAX_TYPE1_SCREENERS) {
error_setg(errp, "Invalid num-type1-screeners value: %" PRIx8,
s->num_type1_screeners);
return;
} else if (s->num_type2_screeners > MAX_TYPE2_SCREENERS) {
error_setg(errp, "Invalid num-type2-screeners value: %" PRIx8,
s->num_type2_screeners);
return;
}
for (i = 0; i < s->num_priority_queues; ++i) {
sysbus_init_irq(SYS_BUS_DEVICE(dev), &s->irq[i]);
}
qemu_macaddr_default_if_unset(&s->conf.macaddr);
s->nic = qemu_new_nic(&net_gem_info, &s->conf,
object_get_typename(OBJECT(dev)), dev->id, s);
}
static void gem_init(Object *obj)
{
CadenceGEMState *s = CADENCE_GEM(obj);
DeviceState *dev = DEVICE(obj);
DB_PRINT("\n");
gem_init_register_masks(s);
memory_region_init_io(&s->iomem, OBJECT(s), &gem_ops, s,
"enet", sizeof(s->regs));
sysbus_init_mmio(sbd, &s->iomem);
sysbus_init_irq(sbd, &s->irq);
qemu_macaddr_default_if_unset(&s->conf.macaddr);
s->nic = qemu_new_nic(&net_gem_info, &s->conf,
object_get_typename(OBJECT(dev)), dev->id, s);
return 0;
sysbus_init_mmio(SYS_BUS_DEVICE(dev), &s->iomem);
}
static const VMStateDescription vmstate_cadence_gem = {
.name = "cadence_gem",
.version_id = 2,
.minimum_version_id = 2,
.version_id = 4,
.minimum_version_id = 4,
.fields = (VMStateField[]) {
VMSTATE_UINT32_ARRAY(regs, CadenceGEMState, CADENCE_GEM_MAXREG),
VMSTATE_UINT16_ARRAY(phy_regs, CadenceGEMState, 32),
VMSTATE_UINT8(phy_loop, CadenceGEMState),
VMSTATE_UINT32(rx_desc_addr, CadenceGEMState),
VMSTATE_UINT32(tx_desc_addr, CadenceGEMState),
VMSTATE_UINT32_ARRAY(rx_desc_addr, CadenceGEMState,
MAX_PRIORITY_QUEUES),
VMSTATE_UINT32_ARRAY(tx_desc_addr, CadenceGEMState,
MAX_PRIORITY_QUEUES),
VMSTATE_BOOL_ARRAY(sar_active, CadenceGEMState, 4),
VMSTATE_END_OF_LIST(),
}
@ -1251,15 +1522,20 @@ static const VMStateDescription vmstate_cadence_gem = {
static Property gem_properties[] = {
DEFINE_NIC_PROPERTIES(CadenceGEMState, conf),
DEFINE_PROP_UINT8("num-priority-queues", CadenceGEMState,
num_priority_queues, 1),
DEFINE_PROP_UINT8("num-type1-screeners", CadenceGEMState,
num_type1_screeners, 4),
DEFINE_PROP_UINT8("num-type2-screeners", CadenceGEMState,
num_type2_screeners, 4),
DEFINE_PROP_END_OF_LIST(),
};
static void gem_class_init(ObjectClass *klass, void *data)
{
DeviceClass *dc = DEVICE_CLASS(klass);
SysBusDeviceClass *sdc = SYS_BUS_DEVICE_CLASS(klass);
sdc->init = gem_init;
dc->realize = gem_realize;
dc->props = gem_properties;
dc->vmsd = &vmstate_cadence_gem;
dc->reset = gem_reset;
@ -1269,6 +1545,7 @@ static const TypeInfo gem_info = {
.name = TYPE_CADENCE_GEM,
.parent = TYPE_SYS_BUS_DEVICE,
.instance_size = sizeof(CadenceGEMState),
.instance_init = gem_init,
.class_init = gem_class_init,
};

View File

@ -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);
}

View File

@ -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);

View File

@ -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 = {

View File

@ -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];

View File

@ -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);
}
}

View File

@ -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;
}

View File

@ -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

View File

@ -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);

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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);

View File

@ -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 */

View File

@ -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)

View File

@ -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)

View File

@ -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);

View File

@ -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);

View File

@ -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",

View File

@ -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);

View File

@ -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;

View File

@ -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);
}

View File

@ -0,0 +1,59 @@
/*
* ASPEED SoC family
*
* Andrew Jeffery <andrew@aj.id.au>
*
* Copyright 2016 IBM Corp.
*
* This code is licensed under the GPL version 2 or later. See
* the COPYING file in the top-level directory.
*/
#ifndef ASPEED_SOC_H
#define ASPEED_SOC_H
#include "hw/arm/arm.h"
#include "hw/intc/aspeed_vic.h"
#include "hw/misc/aspeed_scu.h"
#include "hw/misc/aspeed_sdmc.h"
#include "hw/timer/aspeed_timer.h"
#include "hw/i2c/aspeed_i2c.h"
#include "hw/ssi/aspeed_smc.h"
typedef struct AspeedSoCState {
/*< private >*/
DeviceState parent;
/*< public >*/
ARMCPU *cpu;
MemoryRegion iomem;
AspeedVICState vic;
AspeedTimerCtrlState timerctrl;
AspeedI2CState i2c;
AspeedSCUState scu;
AspeedSMCState smc;
AspeedSMCState spi;
AspeedSDMCState sdmc;
} AspeedSoCState;
#define TYPE_ASPEED_SOC "aspeed-soc"
#define ASPEED_SOC(obj) OBJECT_CHECK(AspeedSoCState, (obj), TYPE_ASPEED_SOC)
typedef struct AspeedSoCInfo {
const char *name;
const char *cpu_model;
uint32_t silicon_rev;
hwaddr sdram_base;
} AspeedSoCInfo;
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 */

View File

@ -1,44 +0,0 @@
/*
* ASPEED AST2400 SoC
*
* Andrew Jeffery <andrew@aj.id.au>
*
* Copyright 2016 IBM Corp.
*
* This code is licensed under the GPL version 2 or later. See
* the COPYING file in the top-level directory.
*/
#ifndef AST2400_H
#define AST2400_H
#include "hw/arm/arm.h"
#include "hw/intc/aspeed_vic.h"
#include "hw/misc/aspeed_scu.h"
#include "hw/misc/aspeed_sdmc.h"
#include "hw/timer/aspeed_timer.h"
#include "hw/i2c/aspeed_i2c.h"
#include "hw/ssi/aspeed_smc.h"
typedef struct AST2400State {
/*< private >*/
DeviceState parent;
/*< public >*/
ARMCPU *cpu;
MemoryRegion iomem;
AspeedVICState vic;
AspeedTimerCtrlState timerctrl;
AspeedI2CState i2c;
AspeedSCUState scu;
AspeedSMCState smc;
AspeedSMCState spi;
AspeedSDMCState sdmc;
} AST2400State;
#define TYPE_AST2400 "ast2400"
#define AST2400(obj) OBJECT_CHECK(AST2400State, (obj), TYPE_AST2400)
#define AST2400_SDRAM_BASE 0x40000000
#endif /* AST2400_H */

View File

@ -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

View File

@ -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)

View File

@ -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

View File

@ -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 */

View File

@ -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;

View File

@ -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;

View File

@ -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);

View File

@ -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,

View File

@ -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 },

View File

@ -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)$@")

107
tests/ptimer-test-stubs.c Normal file
View File

@ -0,0 +1,107 @@
/*
* 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);
}

568
tests/ptimer-test.c Normal file
View File

@ -0,0 +1,568 @@
/*
* 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();
}

22
tests/ptimer-test.h Normal file
View File

@ -0,0 +1,22 @@
/*
* 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