target-arm queue:

* vITS: Support save/restore
  * timer/aspeed: Fix timer enablement when reload is not set
  * aspped: add temperature sensor device
  * timer.h: Provide better monotonic time on ARM hosts
  * exynos4210: various cleanups
  * exynos4210: support system poweroff
 -----BEGIN PGP SIGNATURE-----
 Version: GnuPG v1
 
 iQIcBAABCAAGBQJZP/E9AAoJEDwlJe0UNgzephAQAIwy0Zc0oHWEX9lanN1FNqMI
 8bIXu+yFB+E5zdLtDOuWxmQpJ9EqTYfS7hPSR/WRro4RGJsZiYTEIDpDRSjRt+MR
 kZw+LqDaA/8O6ZqJ0dSQMsH1P9YkcJhVOwe0BLVvkt3b3sZzC7+cM+Y1THlpXeC5
 MwZ81zZNz7Q3J6LV/ZatVx+pI/cn9R6HFpMqPhGsGfn7bqIa+H+9uWKQfRbDBz32
 q6cP33TbF57Of3RNMT3E0Frn+eSxiAyZ3tH61NkjIJ7uJ+WwZts7/kUX4b4ILCJ8
 dwiTHyKwdzvlDhTbgI9UwsBIzFhBAYs8/SufOVjZFooiDapy3JaRL5OI+2JIUHHr
 SQUXLMU11Qhe4imOyL0GcW72eG9tH1r4sxc/yu7T+fr8N2wK/buSMvbTSRLPG9uD
 xb5vODyoq6A6HIs67e86SYHuOJtnTjPPyJexK39bvIvLy5vlPoL5DDzW9ZcuJSeW
 i0v/3FFUQNwFwhtsOos8XQ935ym2MXdChautu7jq/KqaIZY76kl1ux+5ejkFMKyw
 sVNoOhBrxm8278VMKKJpr7v25koRp+eE1+BeBXSvCCOUFsRRL+Fens9A+sd7Ue8H
 xihpLKUP9030/cmhpoO7uk5qsTG4z+TT4S5aUtOYv/AbkL8ckIjQrL0sup2O+YUO
 RDz8uhcU2YGs9PaU58C1
 =1qO0
 -----END PGP SIGNATURE-----

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

target-arm queue:
 * vITS: Support save/restore
 * timer/aspeed: Fix timer enablement when reload is not set
 * aspped: add temperature sensor device
 * timer.h: Provide better monotonic time on ARM hosts
 * exynos4210: various cleanups
 * exynos4210: support system poweroff

# gpg: Signature made Tue 13 Jun 2017 15:05:49 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-20170613:
  hw/intc/arm_gicv3_its: Allow save/restore
  hw/intc/arm_gicv3_kvm: Implement pending table save
  hw/intc/arm_gicv3_its: Implement state save/restore
  kvm-all: Pass an error object to kvm_device_access
  timer/aspeed: fix timer enablement when a reload is not set
  aspeed: add a temp sensor device on I2C bus 3
  hw/misc: add a TMP42{1, 2, 3} device model
  timer.h: Provide better monotonic time
  hw/misc/exynos4210_pmu: Add support for system poweroff
  hw/intc/exynos4210_gic: Constify array of combiner interrupts
  hw/arm/exynos: Use type define instead of hard-coded a9mpcore_priv string
  hw/arm/exynos: Declare local variables in some order
  hw/arm/exynos: Move DRAM initialization next boards
  hw/timer/exynos4210_mct: Remove unused defines
  hw/timer/exynos4210_mct: Cleanup indentation and empty new lines
  hw/timer/exynos4210_mct: Fix checkpatch style errors
  hw/intc/exynos4210_gic: Use more meaningful name for local variable

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
Peter Maydell 2017-06-13 15:49:07 +01:00
commit 3f0602927b
21 changed files with 741 additions and 116 deletions

View File

@ -15,6 +15,7 @@ CONFIG_TWL92230=y
CONFIG_TSC2005=y
CONFIG_LM832X=y
CONFIG_TMP105=y
CONFIG_TMP421=y
CONFIG_STELLARIS=y
CONFIG_STELLARIS_INPUT=y
CONFIG_STELLARIS_ENET=y

View File

@ -239,10 +239,19 @@ static void aspeed_board_init(MachineState *machine,
static void palmetto_bmc_i2c_init(AspeedBoardState *bmc)
{
AspeedSoCState *soc = &bmc->soc;
DeviceState *dev;
/* The palmetto platform expects a ds3231 RTC but a ds1338 is
* enough to provide basic RTC features. Alarms will be missing */
i2c_create_slave(aspeed_i2c_get_bus(DEVICE(&soc->i2c), 0), "ds1338", 0x68);
/* add a TMP423 temperature sensor */
dev = i2c_create_slave(aspeed_i2c_get_bus(DEVICE(&soc->i2c), 2),
"tmp423", 0x4c);
object_property_set_int(OBJECT(dev), 31000, "temperature0", &error_abort);
object_property_set_int(OBJECT(dev), 28000, "temperature1", &error_abort);
object_property_set_int(OBJECT(dev), 20000, "temperature2", &error_abort);
object_property_set_int(OBJECT(dev), 110000, "temperature3", &error_abort);
}
static void palmetto_bmc_init(MachineState *machine)

View File

@ -26,6 +26,7 @@
#include "qemu-common.h"
#include "qemu/log.h"
#include "cpu.h"
#include "hw/cpu/a9mpcore.h"
#include "hw/boards.h"
#include "sysemu/sysemu.h"
#include "hw/sysbus.h"
@ -160,16 +161,14 @@ static uint64_t exynos4210_calc_affinity(int cpu)
return mp_affinity;
}
Exynos4210State *exynos4210_init(MemoryRegion *system_mem,
unsigned long ram_size)
Exynos4210State *exynos4210_init(MemoryRegion *system_mem)
{
int i, n;
Exynos4210State *s = g_new(Exynos4210State, 1);
qemu_irq gate_irq[EXYNOS4210_NCPUS][EXYNOS4210_IRQ_GATE_NINPUTS];
unsigned long mem_size;
DeviceState *dev;
SysBusDevice *busdev;
ObjectClass *cpu_oc;
DeviceState *dev;
int i, n;
cpu_oc = cpu_class_by_name(TYPE_ARM_CPU, "cortex-a9");
assert(cpu_oc);
@ -213,7 +212,7 @@ Exynos4210State *exynos4210_init(MemoryRegion *system_mem,
}
/* Private memory region and Internal GIC */
dev = qdev_create(NULL, "a9mpcore_priv");
dev = qdev_create(NULL, TYPE_A9MPCORE_PRIV);
qdev_prop_set_uint32(dev, "num-cpu", EXYNOS4210_NCPUS);
qdev_init_nofail(dev);
busdev = SYS_BUS_DEVICE(dev);
@ -299,22 +298,6 @@ Exynos4210State *exynos4210_init(MemoryRegion *system_mem,
memory_region_add_subregion(system_mem, EXYNOS4210_IRAM_BASE_ADDR,
&s->iram_mem);
/* DRAM */
mem_size = ram_size;
if (mem_size > EXYNOS4210_DRAM_MAX_SIZE) {
memory_region_init_ram(&s->dram1_mem, NULL, "exynos4210.dram1",
mem_size - EXYNOS4210_DRAM_MAX_SIZE, &error_fatal);
vmstate_register_ram_global(&s->dram1_mem);
memory_region_add_subregion(system_mem, EXYNOS4210_DRAM1_BASE_ADDR,
&s->dram1_mem);
mem_size = EXYNOS4210_DRAM_MAX_SIZE;
}
memory_region_init_ram(&s->dram0_mem, NULL, "exynos4210.dram0", mem_size,
&error_fatal);
vmstate_register_ram_global(&s->dram0_mem);
memory_region_add_subregion(system_mem, EXYNOS4210_DRAM0_BASE_ADDR,
&s->dram0_mem);
/* PMU.
* The only reason of existence at the moment is that secondary CPU boot
* loader uses PMU INFORM5 register as a holding pen.

View File

@ -22,6 +22,7 @@
*/
#include "qemu/osdep.h"
#include "qapi/error.h"
#include "qemu/error-report.h"
#include "qemu-common.h"
#include "cpu.h"
@ -56,6 +57,12 @@ typedef enum Exynos4BoardType {
EXYNOS4_NUM_OF_BOARDS
} Exynos4BoardType;
typedef struct Exynos4BoardState {
Exynos4210State *soc;
MemoryRegion dram0_mem;
MemoryRegion dram1_mem;
} Exynos4BoardState;
static int exynos4_board_id[EXYNOS4_NUM_OF_BOARDS] = {
[EXYNOS4_BOARD_NURI] = 0xD33,
[EXYNOS4_BOARD_SMDKC210] = 0xB16,
@ -96,9 +103,34 @@ static void lan9215_init(uint32_t base, qemu_irq irq)
}
}
static Exynos4210State *exynos4_boards_init_common(MachineState *machine,
Exynos4BoardType board_type)
static void exynos4_boards_init_ram(Exynos4BoardState *s,
MemoryRegion *system_mem,
unsigned long ram_size)
{
unsigned long mem_size = ram_size;
if (mem_size > EXYNOS4210_DRAM_MAX_SIZE) {
memory_region_init_ram(&s->dram1_mem, NULL, "exynos4210.dram1",
mem_size - EXYNOS4210_DRAM_MAX_SIZE,
&error_fatal);
vmstate_register_ram_global(&s->dram1_mem);
memory_region_add_subregion(system_mem, EXYNOS4210_DRAM1_BASE_ADDR,
&s->dram1_mem);
mem_size = EXYNOS4210_DRAM_MAX_SIZE;
}
memory_region_init_ram(&s->dram0_mem, NULL, "exynos4210.dram0", mem_size,
&error_fatal);
vmstate_register_ram_global(&s->dram0_mem);
memory_region_add_subregion(system_mem, EXYNOS4210_DRAM0_BASE_ADDR,
&s->dram0_mem);
}
static Exynos4BoardState *
exynos4_boards_init_common(MachineState *machine,
Exynos4BoardType board_type)
{
Exynos4BoardState *s = g_new(Exynos4BoardState, 1);
MachineClass *mc = MACHINE_GET_CLASS(machine);
if (smp_cpus != EXYNOS4210_NCPUS && !qtest_enabled()) {
@ -127,8 +159,12 @@ static Exynos4210State *exynos4_boards_init_common(MachineState *machine,
machine->kernel_cmdline,
machine->initrd_filename);
return exynos4210_init(get_system_memory(),
exynos4_board_ram_size[board_type]);
exynos4_boards_init_ram(s, get_system_memory(),
exynos4_board_ram_size[board_type]);
s->soc = exynos4210_init(get_system_memory());
return s;
}
static void nuri_init(MachineState *machine)
@ -140,11 +176,11 @@ static void nuri_init(MachineState *machine)
static void smdkc210_init(MachineState *machine)
{
Exynos4210State *s = exynos4_boards_init_common(machine,
EXYNOS4_BOARD_SMDKC210);
Exynos4BoardState *s = exynos4_boards_init_common(machine,
EXYNOS4_BOARD_SMDKC210);
lan9215_init(SMDK_LAN9118_BASE_ADDR,
qemu_irq_invert(s->irq_table[exynos4210_get_irq(37, 1)]));
qemu_irq_invert(s->soc->irq_table[exynos4210_get_irq(37, 1)]));
arm_load_kernel(ARM_CPU(first_cpu), &exynos4_board_binfo);
}

View File

@ -100,14 +100,14 @@ static void kvm_gicd_access(GICState *s, int offset, int cpu,
uint32_t *val, bool write)
{
kvm_device_access(s->dev_fd, KVM_DEV_ARM_VGIC_GRP_DIST_REGS,
KVM_VGIC_ATTR(offset, cpu), val, write);
KVM_VGIC_ATTR(offset, cpu), val, write, &error_abort);
}
static void kvm_gicc_access(GICState *s, int offset, int cpu,
uint32_t *val, bool write)
{
kvm_device_access(s->dev_fd, KVM_DEV_ARM_VGIC_GRP_CPU_REGS,
KVM_VGIC_ATTR(offset, cpu), val, write);
KVM_VGIC_ATTR(offset, cpu), val, write, &error_abort);
}
#define for_each_irq_reg(_ctr, _max_irq, _field_width) \
@ -538,13 +538,14 @@ static void kvm_arm_gic_realize(DeviceState *dev, Error **errp)
if (kvm_device_check_attr(s->dev_fd, KVM_DEV_ARM_VGIC_GRP_NR_IRQS, 0)) {
uint32_t numirqs = s->num_irq;
kvm_device_access(s->dev_fd, KVM_DEV_ARM_VGIC_GRP_NR_IRQS, 0,
&numirqs, true);
&numirqs, true, &error_abort);
}
/* Tell the kernel to complete VGIC initialization now */
if (kvm_device_check_attr(s->dev_fd, KVM_DEV_ARM_VGIC_GRP_CTRL,
KVM_DEV_ARM_VGIC_CTRL_INIT)) {
kvm_device_access(s->dev_fd, KVM_DEV_ARM_VGIC_GRP_CTRL,
KVM_DEV_ARM_VGIC_CTRL_INIT, NULL, true);
KVM_DEV_ARM_VGIC_CTRL_INIT, NULL, true,
&error_abort);
}
} else if (ret != -ENODEV && ret != -ENOTSUP) {
error_setg_errno(errp, -ret, "error creating in-kernel VGIC");

View File

@ -145,6 +145,7 @@ static const VMStateDescription vmstate_gicv3 = {
.minimum_version_id = 1,
.pre_save = gicv3_pre_save,
.post_load = gicv3_post_load,
.priority = MIG_PRI_GICV3,
.fields = (VMStateField[]) {
VMSTATE_UINT32(gicd_ctlr, GICv3State),
VMSTATE_UINT32_ARRAY(gicd_statusr, GICv3State, 2),

View File

@ -48,7 +48,16 @@ static const VMStateDescription vmstate_its = {
.name = "arm_gicv3_its",
.pre_save = gicv3_its_pre_save,
.post_load = gicv3_its_post_load,
.unmigratable = true,
.priority = MIG_PRI_GICV3_ITS,
.fields = (VMStateField[]) {
VMSTATE_UINT32(ctlr, GICv3ITSState),
VMSTATE_UINT32(iidr, GICv3ITSState),
VMSTATE_UINT64(cbaser, GICv3ITSState),
VMSTATE_UINT64(cwriter, GICv3ITSState),
VMSTATE_UINT64(creadr, GICv3ITSState),
VMSTATE_UINT64_ARRAY(baser, GICv3ITSState, 8),
VMSTATE_END_OF_LIST()
},
};
static MemTxResult gicv3_its_trans_read(void *opaque, hwaddr offset,
@ -118,6 +127,7 @@ static void gicv3_its_common_reset(DeviceState *dev)
s->cbaser = 0;
s->cwriter = 0;
s->creadr = 0;
s->iidr = 0;
memset(&s->baser, 0, sizeof(s->baser));
gicv3_its_post_load(s, 0);

View File

@ -53,23 +53,38 @@ static int kvm_its_send_msi(GICv3ITSState *s, uint32_t value, uint16_t devid)
return kvm_vm_ioctl(kvm_state, KVM_SIGNAL_MSI, &msi);
}
/**
* vm_change_state_handler - VM change state callback aiming at flushing
* ITS tables into guest RAM
*
* The tables get flushed to guest RAM whenever the VM gets stopped.
*/
static void vm_change_state_handler(void *opaque, int running,
RunState state)
{
GICv3ITSState *s = (GICv3ITSState *)opaque;
Error *err = NULL;
int ret;
if (running) {
return;
}
ret = kvm_device_access(s->dev_fd, KVM_DEV_ARM_VGIC_GRP_CTRL,
KVM_DEV_ARM_ITS_SAVE_TABLES, NULL, true, &err);
if (err) {
error_report_err(err);
}
if (ret < 0 && ret != -EFAULT) {
abort();
}
}
static void kvm_arm_its_realize(DeviceState *dev, Error **errp)
{
GICv3ITSState *s = ARM_GICV3_ITS_COMMON(dev);
Error *local_err = NULL;
/*
* Block migration of a KVM GICv3 ITS device: the API for saving and
* restoring the state in the kernel is not yet available
*/
error_setg(&s->migration_blocker, "vITS migration is not implemented");
migrate_add_blocker(s->migration_blocker, &local_err);
if (local_err) {
error_propagate(errp, local_err);
error_free(s->migration_blocker);
return;
}
s->dev_fd = kvm_create_device(kvm_state, KVM_DEV_TYPE_ARM_VGIC_ITS, false);
if (s->dev_fd < 0) {
error_setg_errno(errp, -s->dev_fd, "error creating in-kernel ITS");
@ -78,7 +93,7 @@ static void kvm_arm_its_realize(DeviceState *dev, Error **errp)
/* explicit init of the ITS */
kvm_device_access(s->dev_fd, KVM_DEV_ARM_VGIC_GRP_CTRL,
KVM_DEV_ARM_VGIC_CTRL_INIT, NULL, true);
KVM_DEV_ARM_VGIC_CTRL_INIT, NULL, true, &error_abort);
/* register the base address */
kvm_arm_register_device(&s->iomem_its_cntrl, -1, KVM_DEV_ARM_VGIC_GRP_ADDR,
@ -86,9 +101,23 @@ static void kvm_arm_its_realize(DeviceState *dev, Error **errp)
gicv3_its_init_mmio(s, NULL);
if (!kvm_device_check_attr(s->dev_fd, KVM_DEV_ARM_VGIC_GRP_ITS_REGS,
GITS_CTLR)) {
error_setg(&s->migration_blocker, "This operating system kernel "
"does not support vITS migration");
migrate_add_blocker(s->migration_blocker, &local_err);
if (local_err) {
error_propagate(errp, local_err);
error_free(s->migration_blocker);
return;
}
}
kvm_msi_use_devid = true;
kvm_gsi_direct_mapping = false;
kvm_msi_via_irqfd_allowed = kvm_irqfds_enabled();
qemu_add_vm_change_state_handler(vm_change_state_handler, s);
}
static void kvm_arm_its_init(Object *obj)
@ -102,6 +131,80 @@ static void kvm_arm_its_init(Object *obj)
&error_abort);
}
/**
* kvm_arm_its_pre_save - handles the saving of ITS registers.
* ITS tables are flushed into guest RAM separately and earlier,
* through the VM change state handler, since at the moment pre_save()
* is called, the guest RAM has already been saved.
*/
static void kvm_arm_its_pre_save(GICv3ITSState *s)
{
int i;
for (i = 0; i < 8; i++) {
kvm_device_access(s->dev_fd, KVM_DEV_ARM_VGIC_GRP_ITS_REGS,
GITS_BASER + i * 8, &s->baser[i], false,
&error_abort);
}
kvm_device_access(s->dev_fd, KVM_DEV_ARM_VGIC_GRP_ITS_REGS,
GITS_CTLR, &s->ctlr, false, &error_abort);
kvm_device_access(s->dev_fd, KVM_DEV_ARM_VGIC_GRP_ITS_REGS,
GITS_CBASER, &s->cbaser, false, &error_abort);
kvm_device_access(s->dev_fd, KVM_DEV_ARM_VGIC_GRP_ITS_REGS,
GITS_CREADR, &s->creadr, false, &error_abort);
kvm_device_access(s->dev_fd, KVM_DEV_ARM_VGIC_GRP_ITS_REGS,
GITS_CWRITER, &s->cwriter, false, &error_abort);
kvm_device_access(s->dev_fd, KVM_DEV_ARM_VGIC_GRP_ITS_REGS,
GITS_IIDR, &s->iidr, false, &error_abort);
}
/**
* kvm_arm_its_post_load - Restore both the ITS registers and tables
*/
static void kvm_arm_its_post_load(GICv3ITSState *s)
{
int i;
if (!s->iidr) {
return;
}
kvm_device_access(s->dev_fd, KVM_DEV_ARM_VGIC_GRP_ITS_REGS,
GITS_IIDR, &s->iidr, true, &error_abort);
/*
* must be written before GITS_CREADR since GITS_CBASER write
* access resets GITS_CREADR.
*/
kvm_device_access(s->dev_fd, KVM_DEV_ARM_VGIC_GRP_ITS_REGS,
GITS_CBASER, &s->cbaser, true, &error_abort);
kvm_device_access(s->dev_fd, KVM_DEV_ARM_VGIC_GRP_ITS_REGS,
GITS_CREADR, &s->creadr, true, &error_abort);
kvm_device_access(s->dev_fd, KVM_DEV_ARM_VGIC_GRP_ITS_REGS,
GITS_CWRITER, &s->cwriter, true, &error_abort);
for (i = 0; i < 8; i++) {
kvm_device_access(s->dev_fd, KVM_DEV_ARM_VGIC_GRP_ITS_REGS,
GITS_BASER + i * 8, &s->baser[i], true,
&error_abort);
}
kvm_device_access(s->dev_fd, KVM_DEV_ARM_VGIC_GRP_CTRL,
KVM_DEV_ARM_ITS_RESTORE_TABLES, NULL, true,
&error_abort);
kvm_device_access(s->dev_fd, KVM_DEV_ARM_VGIC_GRP_ITS_REGS,
GITS_CTLR, &s->ctlr, true, &error_abort);
}
static void kvm_arm_its_class_init(ObjectClass *klass, void *data)
{
DeviceClass *dc = DEVICE_CLASS(klass);
@ -109,6 +212,8 @@ static void kvm_arm_its_class_init(ObjectClass *klass, void *data)
dc->realize = kvm_arm_its_realize;
icc->send_msi = kvm_its_send_msi;
icc->pre_save = kvm_arm_its_pre_save;
icc->post_load = kvm_arm_its_post_load;
}
static const TypeInfo kvm_arm_its_info = {

View File

@ -25,6 +25,7 @@
#include "hw/sysbus.h"
#include "qemu/error-report.h"
#include "sysemu/kvm.h"
#include "sysemu/sysemu.h"
#include "kvm_arm.h"
#include "gicv3_internal.h"
#include "vgic_common.h"
@ -93,7 +94,7 @@ static inline void kvm_gicd_access(GICv3State *s, int offset,
{
kvm_device_access(s->dev_fd, KVM_DEV_ARM_VGIC_GRP_DIST_REGS,
KVM_VGIC_ATTR(offset, 0),
val, write);
val, write, &error_abort);
}
static inline void kvm_gicr_access(GICv3State *s, int offset, int cpu,
@ -101,7 +102,7 @@ static inline void kvm_gicr_access(GICv3State *s, int offset, int cpu,
{
kvm_device_access(s->dev_fd, KVM_DEV_ARM_VGIC_GRP_REDIST_REGS,
KVM_VGIC_ATTR(offset, s->cpu[cpu].gicr_typer),
val, write);
val, write, &error_abort);
}
static inline void kvm_gicc_access(GICv3State *s, uint64_t reg, int cpu,
@ -109,7 +110,7 @@ static inline void kvm_gicc_access(GICv3State *s, uint64_t reg, int cpu,
{
kvm_device_access(s->dev_fd, KVM_DEV_ARM_VGIC_GRP_CPU_SYSREGS,
KVM_VGIC_ATTR(reg, s->cpu[cpu].gicr_typer),
val, write);
val, write, &error_abort);
}
static inline void kvm_gic_line_level_access(GICv3State *s, int irq, int cpu,
@ -119,7 +120,7 @@ static inline void kvm_gic_line_level_access(GICv3State *s, int irq, int cpu,
KVM_VGIC_ATTR(irq, s->cpu[cpu].gicr_typer) |
(VGIC_LEVEL_INFO_LINE_LEVEL <<
KVM_DEV_ARM_VGIC_LINE_LEVEL_INFO_SHIFT),
val, write);
val, write, &error_abort);
}
/* Loop through each distributor IRQ related register; since bits
@ -630,7 +631,7 @@ static void arm_gicv3_icc_reset(CPUARMState *env, const ARMCPRegInfo *ri)
/* Initialize to actual HW supported configuration */
kvm_device_access(s->dev_fd, KVM_DEV_ARM_VGIC_GRP_CPU_SYSREGS,
KVM_VGIC_ATTR(ICC_CTLR_EL1, cpu->mp_affinity),
&c->icc_ctlr_el1[GICV3_NS], false);
&c->icc_ctlr_el1[GICV3_NS], false, &error_abort);
c->icc_ctlr_el1[GICV3_S] = c->icc_ctlr_el1[GICV3_NS];
}
@ -680,6 +681,35 @@ static const ARMCPRegInfo gicv3_cpuif_reginfo[] = {
REGINFO_SENTINEL
};
/**
* vm_change_state_handler - VM change state callback aiming at flushing
* RDIST pending tables into guest RAM
*
* The tables get flushed to guest RAM whenever the VM gets stopped.
*/
static void vm_change_state_handler(void *opaque, int running,
RunState state)
{
GICv3State *s = (GICv3State *)opaque;
Error *err = NULL;
int ret;
if (running) {
return;
}
ret = kvm_device_access(s->dev_fd, KVM_DEV_ARM_VGIC_GRP_CTRL,
KVM_DEV_ARM_VGIC_SAVE_PENDING_TABLES,
NULL, true, &err);
if (err) {
error_report_err(err);
}
if (ret < 0 && ret != -EFAULT) {
abort();
}
}
static void kvm_arm_gicv3_realize(DeviceState *dev, Error **errp)
{
GICv3State *s = KVM_ARM_GICV3(dev);
@ -717,11 +747,11 @@ static void kvm_arm_gicv3_realize(DeviceState *dev, Error **errp)
}
kvm_device_access(s->dev_fd, KVM_DEV_ARM_VGIC_GRP_NR_IRQS,
0, &s->num_irq, true);
0, &s->num_irq, true, &error_abort);
/* Tell the kernel to complete VGIC initialization now */
kvm_device_access(s->dev_fd, KVM_DEV_ARM_VGIC_GRP_CTRL,
KVM_DEV_ARM_VGIC_CTRL_INIT, NULL, true);
KVM_DEV_ARM_VGIC_CTRL_INIT, NULL, true, &error_abort);
kvm_arm_register_device(&s->iomem_dist, -1, KVM_DEV_ARM_VGIC_GRP_ADDR,
KVM_VGIC_V3_ADDR_TYPE_DIST, s->dev_fd);
@ -751,6 +781,10 @@ static void kvm_arm_gicv3_realize(DeviceState *dev, Error **errp)
return;
}
}
if (kvm_device_check_attr(s->dev_fd, KVM_DEV_ARM_VGIC_GRP_CTRL,
KVM_DEV_ARM_VGIC_SAVE_PENDING_TABLES)) {
qemu_add_vm_change_state_handler(vm_change_state_handler, s);
}
}
static void kvm_arm_gicv3_class_init(ObjectClass *klass, void *data)

View File

@ -116,7 +116,7 @@ enum ExtInt {
* which is INTG16 in Internal Interrupt Combiner.
*/
static uint32_t
static const uint32_t
combiner_grp_to_gic_id[64-EXYNOS4210_MAX_EXT_COMBINER_OUT_IRQ][8] = {
/* int combiner groups 16-19 */
{ }, { }, { }, { },
@ -286,21 +286,21 @@ static void exynos4210_gic_init(Object *obj)
DeviceState *dev = DEVICE(obj);
Exynos4210GicState *s = EXYNOS4210_GIC(obj);
SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
uint32_t i;
const char cpu_prefix[] = "exynos4210-gic-alias_cpu";
const char dist_prefix[] = "exynos4210-gic-alias_dist";
char cpu_alias_name[sizeof(cpu_prefix) + 3];
char dist_alias_name[sizeof(cpu_prefix) + 3];
SysBusDevice *busdev;
SysBusDevice *gicbusdev;
uint32_t i;
s->gic = qdev_create(NULL, "arm_gic");
qdev_prop_set_uint32(s->gic, "num-cpu", s->num_cpu);
qdev_prop_set_uint32(s->gic, "num-irq", EXYNOS4210_GIC_NIRQ);
qdev_init_nofail(s->gic);
busdev = SYS_BUS_DEVICE(s->gic);
gicbusdev = SYS_BUS_DEVICE(s->gic);
/* Pass through outbound IRQ lines from the GIC */
sysbus_pass_irq(sbd, busdev);
sysbus_pass_irq(sbd, gicbusdev);
/* Pass through inbound GPIO lines to the GIC */
qdev_init_gpio_in(dev, exynos4210_gic_set_irq,
@ -316,7 +316,7 @@ static void exynos4210_gic_init(Object *obj)
sprintf(cpu_alias_name, "%s%x", cpu_prefix, i);
memory_region_init_alias(&s->cpu_alias[i], obj,
cpu_alias_name,
sysbus_mmio_get_region(busdev, 1),
sysbus_mmio_get_region(gicbusdev, 1),
0,
EXYNOS4210_GIC_CPU_REGION_SIZE);
memory_region_add_subregion(&s->cpu_container,
@ -326,7 +326,7 @@ static void exynos4210_gic_init(Object *obj)
sprintf(dist_alias_name, "%s%x", dist_prefix, i);
memory_region_init_alias(&s->dist_alias[i], obj,
dist_alias_name,
sysbus_mmio_get_region(busdev, 0),
sysbus_mmio_get_region(gicbusdev, 0),
0,
EXYNOS4210_GIC_DIST_REGION_SIZE);
memory_region_add_subregion(&s->dist_container,

View File

@ -1,6 +1,7 @@
common-obj-$(CONFIG_APPLESMC) += applesmc.o
common-obj-$(CONFIG_MAX111X) += max111x.o
common-obj-$(CONFIG_TMP105) += tmp105.o
common-obj-$(CONFIG_TMP421) += tmp421.o
common-obj-$(CONFIG_ISA_DEBUG) += debugexit.o
common-obj-$(CONFIG_SGA) += sga.o
common-obj-$(CONFIG_ISA_TESTDEV) += pc-testdev.o

View File

@ -26,6 +26,7 @@
#include "qemu/osdep.h"
#include "hw/sysbus.h"
#include "sysemu/sysemu.h"
#ifndef DEBUG_PMU
#define DEBUG_PMU 0
@ -350,7 +351,11 @@ static const Exynos4210PmuReg exynos4210_pmu_regs[] = {
{"PAD_RETENTION_MMCB_OPTION", PAD_RETENTION_MMCB_OPTION, 0x00000000},
{"PAD_RETENTION_EBIA_OPTION", PAD_RETENTION_EBIA_OPTION, 0x00000000},
{"PAD_RETENTION_EBIB_OPTION", PAD_RETENTION_EBIB_OPTION, 0x00000000},
{"PS_HOLD_CONTROL", PS_HOLD_CONTROL, 0x00005200},
/*
* PS_HOLD_CONTROL: reset value and manually toggle high the DATA bit.
* DATA bit high, set usually by bootloader, keeps system on.
*/
{"PS_HOLD_CONTROL", PS_HOLD_CONTROL, 0x00005200 | BIT(8)},
{"XUSBXTI_CONFIGURATION", XUSBXTI_CONFIGURATION, 0x00000001},
{"XUSBXTI_STATUS", XUSBXTI_STATUS, 0x00000001},
{"XUSBXTI_DURATION", XUSBXTI_DURATION, 0xFFF00000},
@ -397,6 +402,12 @@ typedef struct Exynos4210PmuState {
uint32_t reg[PMU_NUM_OF_REGISTERS];
} Exynos4210PmuState;
static void exynos4210_pmu_poweroff(void)
{
PRINT_DEBUG("QEMU PMU: PS_HOLD bit down, powering off\n");
qemu_system_shutdown_request(SHUTDOWN_CAUSE_GUEST_SHUTDOWN);
}
static uint64_t exynos4210_pmu_read(void *opaque, hwaddr offset,
unsigned size)
{
@ -428,6 +439,13 @@ static void exynos4210_pmu_write(void *opaque, hwaddr offset,
PRINT_DEBUG_EXTEND("%s <0x%04x> <- 0x%04x\n", reg_p->name,
(uint32_t)offset, (uint32_t)val);
s->reg[i] = val;
if ((offset == PS_HOLD_CONTROL) && ((val & BIT(8)) == 0)) {
/*
* We are interested only in setting data bit
* of PS_HOLD_CONTROL register to indicate power off request.
*/
exynos4210_pmu_poweroff();
}
return;
}
reg_p++;

402
hw/misc/tmp421.c Normal file
View File

@ -0,0 +1,402 @@
/*
* Texas Instruments TMP421 temperature sensor.
*
* Copyright (c) 2016 IBM Corporation.
*
* Largely inspired by :
*
* Texas Instruments TMP105 temperature sensor.
*
* Copyright (C) 2008 Nokia Corporation
* Written by Andrzej Zaborowski <andrew@openedhand.com>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 or
* (at your option) version 3 of the License.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, see <http://www.gnu.org/licenses/>.
*/
#include "qemu/osdep.h"
#include "hw/hw.h"
#include "hw/i2c/i2c.h"
#include "qapi/error.h"
#include "qapi/visitor.h"
/* Manufacturer / Device ID's */
#define TMP421_MANUFACTURER_ID 0x55
#define TMP421_DEVICE_ID 0x21
#define TMP422_DEVICE_ID 0x22
#define TMP423_DEVICE_ID 0x23
typedef struct DeviceInfo {
int model;
const char *name;
} DeviceInfo;
static const DeviceInfo devices[] = {
{ TMP421_DEVICE_ID, "tmp421" },
{ TMP422_DEVICE_ID, "tmp422" },
{ TMP423_DEVICE_ID, "tmp423" },
};
typedef struct TMP421State {
/*< private >*/
I2CSlave i2c;
/*< public >*/
int16_t temperature[4];
uint8_t status;
uint8_t config[2];
uint8_t rate;
uint8_t len;
uint8_t buf[2];
uint8_t pointer;
} TMP421State;
typedef struct TMP421Class {
I2CSlaveClass parent_class;
DeviceInfo *dev;
} TMP421Class;
#define TYPE_TMP421 "tmp421-generic"
#define TMP421(obj) OBJECT_CHECK(TMP421State, (obj), TYPE_TMP421)
#define TMP421_CLASS(klass) \
OBJECT_CLASS_CHECK(TMP421Class, (klass), TYPE_TMP421)
#define TMP421_GET_CLASS(obj) \
OBJECT_GET_CLASS(TMP421Class, (obj), TYPE_TMP421)
/* the TMP421 registers */
#define TMP421_STATUS_REG 0x08
#define TMP421_STATUS_BUSY (1 << 7)
#define TMP421_CONFIG_REG_1 0x09
#define TMP421_CONFIG_RANGE (1 << 2)
#define TMP421_CONFIG_SHUTDOWN (1 << 6)
#define TMP421_CONFIG_REG_2 0x0A
#define TMP421_CONFIG_RC (1 << 2)
#define TMP421_CONFIG_LEN (1 << 3)
#define TMP421_CONFIG_REN (1 << 4)
#define TMP421_CONFIG_REN2 (1 << 5)
#define TMP421_CONFIG_REN3 (1 << 6)
#define TMP421_CONVERSION_RATE_REG 0x0B
#define TMP421_ONE_SHOT 0x0F
#define TMP421_RESET 0xFC
#define TMP421_MANUFACTURER_ID_REG 0xFE
#define TMP421_DEVICE_ID_REG 0xFF
#define TMP421_TEMP_MSB0 0x00
#define TMP421_TEMP_MSB1 0x01
#define TMP421_TEMP_MSB2 0x02
#define TMP421_TEMP_MSB3 0x03
#define TMP421_TEMP_LSB0 0x10
#define TMP421_TEMP_LSB1 0x11
#define TMP421_TEMP_LSB2 0x12
#define TMP421_TEMP_LSB3 0x13
static const int32_t mins[2] = { -40000, -55000 };
static const int32_t maxs[2] = { 127000, 150000 };
static void tmp421_get_temperature(Object *obj, Visitor *v, const char *name,
void *opaque, Error **errp)
{
TMP421State *s = TMP421(obj);
bool ext_range = (s->config[0] & TMP421_CONFIG_RANGE);
int offset = ext_range * 64 * 256;
int64_t value;
int tempid;
if (sscanf(name, "temperature%d", &tempid) != 1) {
error_setg(errp, "error reading %s: %m", name);
return;
}
if (tempid >= 4 || tempid < 0) {
error_setg(errp, "error reading %s", name);
return;
}
value = ((s->temperature[tempid] - offset) * 1000 + 128) / 256;
visit_type_int(v, name, &value, errp);
}
/* Units are 0.001 centigrades relative to 0 C. s->temperature is 8.8
* fixed point, so units are 1/256 centigrades. A simple ratio will do.
*/
static void tmp421_set_temperature(Object *obj, Visitor *v, const char *name,
void *opaque, Error **errp)
{
TMP421State *s = TMP421(obj);
Error *local_err = NULL;
int64_t temp;
bool ext_range = (s->config[0] & TMP421_CONFIG_RANGE);
int offset = ext_range * 64 * 256;
int tempid;
visit_type_int(v, name, &temp, &local_err);
if (local_err) {
error_propagate(errp, local_err);
return;
}
if (temp >= maxs[ext_range] || temp < mins[ext_range]) {
error_setg(errp, "value %" PRId64 ".%03" PRIu64 " °C is out of range",
temp / 1000, temp % 1000);
return;
}
if (sscanf(name, "temperature%d", &tempid) != 1) {
error_setg(errp, "error reading %s: %m", name);
return;
}
if (tempid >= 4 || tempid < 0) {
error_setg(errp, "error reading %s", name);
return;
}
s->temperature[tempid] = (int16_t) ((temp * 256 - 128) / 1000) + offset;
}
static void tmp421_read(TMP421State *s)
{
TMP421Class *sc = TMP421_GET_CLASS(s);
s->len = 0;
switch (s->pointer) {
case TMP421_MANUFACTURER_ID_REG:
s->buf[s->len++] = TMP421_MANUFACTURER_ID;
break;
case TMP421_DEVICE_ID_REG:
s->buf[s->len++] = sc->dev->model;
break;
case TMP421_CONFIG_REG_1:
s->buf[s->len++] = s->config[0];
break;
case TMP421_CONFIG_REG_2:
s->buf[s->len++] = s->config[1];
break;
case TMP421_CONVERSION_RATE_REG:
s->buf[s->len++] = s->rate;
break;
case TMP421_STATUS_REG:
s->buf[s->len++] = s->status;
break;
/* FIXME: check for channel enablement in config registers */
case TMP421_TEMP_MSB0:
s->buf[s->len++] = (((uint16_t) s->temperature[0]) >> 8);
s->buf[s->len++] = (((uint16_t) s->temperature[0]) >> 0) & 0xf0;
break;
case TMP421_TEMP_MSB1:
s->buf[s->len++] = (((uint16_t) s->temperature[1]) >> 8);
s->buf[s->len++] = (((uint16_t) s->temperature[1]) >> 0) & 0xf0;
break;
case TMP421_TEMP_MSB2:
s->buf[s->len++] = (((uint16_t) s->temperature[2]) >> 8);
s->buf[s->len++] = (((uint16_t) s->temperature[2]) >> 0) & 0xf0;
break;
case TMP421_TEMP_MSB3:
s->buf[s->len++] = (((uint16_t) s->temperature[3]) >> 8);
s->buf[s->len++] = (((uint16_t) s->temperature[3]) >> 0) & 0xf0;
break;
case TMP421_TEMP_LSB0:
s->buf[s->len++] = (((uint16_t) s->temperature[0]) >> 0) & 0xf0;
break;
case TMP421_TEMP_LSB1:
s->buf[s->len++] = (((uint16_t) s->temperature[1]) >> 0) & 0xf0;
break;
case TMP421_TEMP_LSB2:
s->buf[s->len++] = (((uint16_t) s->temperature[2]) >> 0) & 0xf0;
break;
case TMP421_TEMP_LSB3:
s->buf[s->len++] = (((uint16_t) s->temperature[3]) >> 0) & 0xf0;
break;
}
}
static void tmp421_reset(I2CSlave *i2c);
static void tmp421_write(TMP421State *s)
{
switch (s->pointer) {
case TMP421_CONVERSION_RATE_REG:
s->rate = s->buf[0];
break;
case TMP421_CONFIG_REG_1:
s->config[0] = s->buf[0];
break;
case TMP421_CONFIG_REG_2:
s->config[1] = s->buf[0];
break;
case TMP421_RESET:
tmp421_reset(I2C_SLAVE(s));
break;
}
}
static int tmp421_rx(I2CSlave *i2c)
{
TMP421State *s = TMP421(i2c);
if (s->len < 2) {
return s->buf[s->len++];
} else {
return 0xff;
}
}
static int tmp421_tx(I2CSlave *i2c, uint8_t data)
{
TMP421State *s = TMP421(i2c);
if (s->len == 0) {
/* first byte is the register pointer for a read or write
* operation */
s->pointer = data;
s->len++;
} else if (s->len == 1) {
/* second byte is the data to write. The device only supports
* one byte writes */
s->buf[0] = data;
tmp421_write(s);
}
return 0;
}
static int tmp421_event(I2CSlave *i2c, enum i2c_event event)
{
TMP421State *s = TMP421(i2c);
if (event == I2C_START_RECV) {
tmp421_read(s);
}
s->len = 0;
return 0;
}
static const VMStateDescription vmstate_tmp421 = {
.name = "TMP421",
.version_id = 0,
.minimum_version_id = 0,
.fields = (VMStateField[]) {
VMSTATE_UINT8(len, TMP421State),
VMSTATE_UINT8_ARRAY(buf, TMP421State, 2),
VMSTATE_UINT8(pointer, TMP421State),
VMSTATE_UINT8_ARRAY(config, TMP421State, 2),
VMSTATE_UINT8(status, TMP421State),
VMSTATE_UINT8(rate, TMP421State),
VMSTATE_INT16_ARRAY(temperature, TMP421State, 4),
VMSTATE_I2C_SLAVE(i2c, TMP421State),
VMSTATE_END_OF_LIST()
}
};
static void tmp421_reset(I2CSlave *i2c)
{
TMP421State *s = TMP421(i2c);
TMP421Class *sc = TMP421_GET_CLASS(s);
memset(s->temperature, 0, sizeof(s->temperature));
s->pointer = 0;
s->config[0] = 0; /* TMP421_CONFIG_RANGE */
/* resistance correction and channel enablement */
switch (sc->dev->model) {
case TMP421_DEVICE_ID:
s->config[1] = 0x1c;
break;
case TMP422_DEVICE_ID:
s->config[1] = 0x3c;
break;
case TMP423_DEVICE_ID:
s->config[1] = 0x7c;
break;
}
s->rate = 0x7; /* 8Hz */
s->status = 0;
}
static int tmp421_init(I2CSlave *i2c)
{
TMP421State *s = TMP421(i2c);
tmp421_reset(&s->i2c);
return 0;
}
static void tmp421_initfn(Object *obj)
{
object_property_add(obj, "temperature0", "int",
tmp421_get_temperature,
tmp421_set_temperature, NULL, NULL, NULL);
object_property_add(obj, "temperature1", "int",
tmp421_get_temperature,
tmp421_set_temperature, NULL, NULL, NULL);
object_property_add(obj, "temperature2", "int",
tmp421_get_temperature,
tmp421_set_temperature, NULL, NULL, NULL);
object_property_add(obj, "temperature3", "int",
tmp421_get_temperature,
tmp421_set_temperature, NULL, NULL, NULL);
}
static void tmp421_class_init(ObjectClass *klass, void *data)
{
DeviceClass *dc = DEVICE_CLASS(klass);
I2CSlaveClass *k = I2C_SLAVE_CLASS(klass);
TMP421Class *sc = TMP421_CLASS(klass);
k->init = tmp421_init;
k->event = tmp421_event;
k->recv = tmp421_rx;
k->send = tmp421_tx;
dc->vmsd = &vmstate_tmp421;
sc->dev = (DeviceInfo *) data;
}
static const TypeInfo tmp421_info = {
.name = TYPE_TMP421,
.parent = TYPE_I2C_SLAVE,
.instance_size = sizeof(TMP421State),
.class_size = sizeof(TMP421Class),
.instance_init = tmp421_initfn,
.abstract = true,
};
static void tmp421_register_types(void)
{
int i;
type_register_static(&tmp421_info);
for (i = 0; i < ARRAY_SIZE(devices); ++i) {
TypeInfo ti = {
.name = devices[i].name,
.parent = TYPE_TMP421,
.class_init = tmp421_class_init,
.class_data = (void *) &devices[i],
};
type_register(&ti);
}
}
type_init(tmp421_register_types)

View File

@ -130,15 +130,26 @@ static uint64_t calculate_next(struct AspeedTimer *t)
next = seq[1];
} else if (now < seq[2]) {
next = seq[2];
} else {
} else if (t->reload) {
reload_ns = muldiv64(t->reload, NANOSECONDS_PER_SECOND, rate);
t->start = now - ((now - t->start) % reload_ns);
} else {
/* no reload value, return 0 */
break;
}
}
return next;
}
static void aspeed_timer_mod(AspeedTimer *t)
{
uint64_t next = calculate_next(t);
if (next) {
timer_mod(&t->timer, next);
}
}
static void aspeed_timer_expire(void *opaque)
{
AspeedTimer *t = opaque;
@ -164,7 +175,7 @@ static void aspeed_timer_expire(void *opaque)
qemu_set_irq(t->irq, t->level);
}
timer_mod(&t->timer, calculate_next(t));
aspeed_timer_mod(t);
}
static uint64_t aspeed_timer_get_value(AspeedTimer *t, int reg)
@ -227,10 +238,23 @@ static void aspeed_timer_set_value(AspeedTimerCtrlState *s, int timer, int reg,
uint32_t value)
{
AspeedTimer *t;
uint32_t old_reload;
trace_aspeed_timer_set_value(timer, reg, value);
t = &s->timers[timer];
switch (reg) {
case TIMER_REG_RELOAD:
old_reload = t->reload;
t->reload = value;
/* If the reload value was not previously set, or zero, and
* the current value is valid, try to start the timer if it is
* enabled.
*/
if (old_reload || !t->reload) {
break;
}
case TIMER_REG_STATUS:
if (timer_enabled(t)) {
uint64_t now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
@ -238,17 +262,14 @@ static void aspeed_timer_set_value(AspeedTimerCtrlState *s, int timer, int reg,
uint32_t rate = calculate_rate(t);
t->start += muldiv64(delta, NANOSECONDS_PER_SECOND, rate);
timer_mod(&t->timer, calculate_next(t));
aspeed_timer_mod(t);
}
break;
case TIMER_REG_RELOAD:
t->reload = value;
break;
case TIMER_REG_MATCH_FIRST:
case TIMER_REG_MATCH_SECOND:
t->match[reg - 2] = value;
if (timer_enabled(t)) {
timer_mod(&t->timer, calculate_next(t));
aspeed_timer_mod(t);
}
break;
default:
@ -268,7 +289,7 @@ static void aspeed_timer_ctrl_enable(AspeedTimer *t, bool enable)
trace_aspeed_timer_ctrl_enable(t->id, enable);
if (enable) {
t->start = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
timer_mod(&t->timer, calculate_next(t));
aspeed_timer_mod(t);
} else {
timer_del(&t->timer);
}

View File

@ -173,13 +173,10 @@ enum LocalTimerRegCntIndexes {
L_REG_CNT_AMOUNT
};
#define MCT_NIRQ 6
#define MCT_SFR_SIZE 0x444
#define MCT_GT_CMP_NUM 4
#define MCT_GT_MAX_VAL UINT64_MAX
#define MCT_GT_COUNTER_STEP 0x100000000ULL
#define MCT_LT_COUNTER_STEP 0x100000000ULL
#define MCT_LT_CNT_LOW_LIMIT 0x100
@ -937,7 +934,7 @@ static void exynos4210_mct_update_freq(Exynos4210MCTState *s)
{
uint32_t freq = s->freq;
s->freq = 24000000 /
((MCT_CFG_GET_PRESCALER(s->reg_mct_cfg)+1) *
((MCT_CFG_GET_PRESCALER(s->reg_mct_cfg) + 1) *
MCT_CFG_GET_DIVIDER(s->reg_mct_cfg));
if (freq != s->freq) {
@ -1016,9 +1013,9 @@ static uint64_t exynos4210_mct_read(void *opaque, hwaddr offset,
case G_COMP_L(0): case G_COMP_L(1): case G_COMP_L(2): case G_COMP_L(3):
case G_COMP_U(0): case G_COMP_U(1): case G_COMP_U(2): case G_COMP_U(3):
index = GET_G_COMP_IDX(offset);
shift = 8 * (offset & 0x4);
value = UINT32_MAX & (s->g_timer.reg.comp[index] >> shift);
index = GET_G_COMP_IDX(offset);
shift = 8 * (offset & 0x4);
value = UINT32_MAX & (s->g_timer.reg.comp[index] >> shift);
break;
case G_TCON:
@ -1067,7 +1064,6 @@ static uint64_t exynos4210_mct_read(void *opaque, hwaddr offset,
lt_i = GET_L_TIMER_IDX(offset);
value = exynos4210_lfrc_get_count(&s->l_timer[lt_i]);
break;
case L0_TCON: case L1_TCON:
@ -1153,23 +1149,23 @@ static void exynos4210_mct_write(void *opaque, hwaddr offset,
case G_COMP_L(0): case G_COMP_L(1): case G_COMP_L(2): case G_COMP_L(3):
case G_COMP_U(0): case G_COMP_U(1): case G_COMP_U(2): case G_COMP_U(3):
index = GET_G_COMP_IDX(offset);
shift = 8 * (offset & 0x4);
s->g_timer.reg.comp[index] =
(s->g_timer.reg.comp[index] &
(((uint64_t)UINT32_MAX << 32) >> shift)) +
(value << shift);
index = GET_G_COMP_IDX(offset);
shift = 8 * (offset & 0x4);
s->g_timer.reg.comp[index] =
(s->g_timer.reg.comp[index] &
(((uint64_t)UINT32_MAX << 32) >> shift)) +
(value << shift);
DPRINTF("comparator %d write 0x%llx val << %d\n", index, value, shift);
DPRINTF("comparator %d write 0x%llx val << %d\n", index, value, shift);
if (offset&0x4) {
s->g_timer.reg.wstat |= G_WSTAT_COMP_U(index);
} else {
s->g_timer.reg.wstat |= G_WSTAT_COMP_L(index);
}
if (offset & 0x4) {
s->g_timer.reg.wstat |= G_WSTAT_COMP_U(index);
} else {
s->g_timer.reg.wstat |= G_WSTAT_COMP_L(index);
}
exynos4210_gfrc_restart(s);
break;
exynos4210_gfrc_restart(s);
break;
case G_TCON:
old_val = s->g_timer.reg.tcon;
@ -1207,7 +1203,6 @@ static void exynos4210_mct_write(void *opaque, hwaddr offset,
break;
case G_INT_ENB:
/* Raise IRQ if transition from disabled to enabled and CSTAT pending */
for (i = 0; i < MCT_GT_CMP_NUM; i++) {
if ((value & G_INT_ENABLE(i)) > (s->g_timer.reg.tcon &
@ -1288,7 +1283,6 @@ static void exynos4210_mct_write(void *opaque, hwaddr offset,
break;
case L0_TCNTB: case L1_TCNTB:
lt_i = GET_L_TIMER_IDX(offset);
index = GET_L_TIMER_CNT_REG_IDX(offset, lt_i);
@ -1316,7 +1310,6 @@ static void exynos4210_mct_write(void *opaque, hwaddr offset,
break;
case L0_ICNTB: case L1_ICNTB:
lt_i = GET_L_TIMER_IDX(offset);
index = GET_L_TIMER_CNT_REG_IDX(offset, lt_i);
@ -1353,13 +1346,12 @@ static void exynos4210_mct_write(void *opaque, hwaddr offset,
if (icntb_max[lt_i] < value) {
icntb_max[lt_i] = value;
}
DPRINTF("local timer[%d] ICNTB write %llx; max=%x, min=%x\n\n",
lt_i, value, icntb_max[lt_i], icntb_min[lt_i]);
DPRINTF("local timer[%d] ICNTB write %llx; max=%x, min=%x\n\n",
lt_i, value, icntb_max[lt_i], icntb_min[lt_i]);
#endif
break;
break;
case L0_FRCNTB: case L1_FRCNTB:
lt_i = GET_L_TIMER_IDX(offset);
index = GET_L_TIMER_CNT_REG_IDX(offset, lt_i);

View File

@ -93,8 +93,6 @@ typedef struct Exynos4210State {
MemoryRegion iram_mem;
MemoryRegion irom_mem;
MemoryRegion irom_alias_mem;
MemoryRegion dram0_mem;
MemoryRegion dram1_mem;
MemoryRegion boot_secondary;
MemoryRegion bootreg_mem;
I2CBus *i2c_if[EXYNOS4210_I2C_NUMBER];
@ -103,8 +101,7 @@ typedef struct Exynos4210State {
void exynos4210_write_secondary(ARMCPU *cpu,
const struct arm_boot_info *info);
Exynos4210State *exynos4210_init(MemoryRegion *system_mem,
unsigned long ram_size);
Exynos4210State *exynos4210_init(MemoryRegion *system_mem);
/* Initialize exynos4210 IRQ subsystem stub */
qemu_irq *exynos4210_init_irq(Exynos4210Irq *env);

View File

@ -28,6 +28,13 @@
#define ITS_TRANS_SIZE 0x10000
#define ITS_SIZE (ITS_CONTROL_SIZE + ITS_TRANS_SIZE)
#define GITS_CTLR 0x0
#define GITS_IIDR 0x4
#define GITS_CBASER 0x80
#define GITS_CWRITER 0x88
#define GITS_CREADR 0x90
#define GITS_BASER 0x100
struct GICv3ITSState {
SysBusDevice parent_obj;
@ -43,6 +50,7 @@ struct GICv3ITSState {
/* Registers */
uint32_t ctlr;
uint32_t iidr;
uint64_t cbaser;
uint64_t cwriter;
uint64_t creadr;

View File

@ -149,6 +149,8 @@ enum VMStateFlags {
typedef enum {
MIG_PRI_DEFAULT = 0,
MIG_PRI_IOMMU, /* Must happen before PCI devices */
MIG_PRI_GICV3_ITS, /* Must happen before PCI devices */
MIG_PRI_GICV3, /* Must happen before the ITS */
MIG_PRI_MAX,
} MigrationPriority;

View File

@ -1020,10 +1020,9 @@ static inline int64_t cpu_get_host_ticks(void)
/* The host CPU doesn't have an easily accessible cycle counter.
Just return a monotonically increasing value. This will be
totally wrong, but hopefully better than nothing. */
static inline int64_t cpu_get_host_ticks (void)
static inline int64_t cpu_get_host_ticks(void)
{
static int64_t ticks = 0;
return ticks++;
return get_clock();
}
#endif

View File

@ -294,12 +294,15 @@ int kvm_device_check_attr(int fd, uint32_t group, uint64_t attr);
* @attr: the attribute of that group to set or get
* @val: pointer to a storage area for the value
* @write: true for set and false for get operation
* @errp: error object handle
*
* This function is not allowed to fail. Use kvm_device_check_attr()
* in order to check for the availability of optional attributes.
* Returns: 0 on success
* < 0 on error
* Use kvm_device_check_attr() in order to check for the availability
* of optional attributes.
*/
void kvm_device_access(int fd, int group, uint64_t attr,
void *val, bool write);
int kvm_device_access(int fd, int group, uint64_t attr,
void *val, bool write, Error **errp);
/**
* kvm_create_device - create a KVM device for the device control API

View File

@ -23,6 +23,7 @@
#include "qemu/option.h"
#include "qemu/config-file.h"
#include "qemu/error-report.h"
#include "qapi/error.h"
#include "hw/hw.h"
#include "hw/pci/msi.h"
#include "hw/pci/msix.h"
@ -2216,8 +2217,8 @@ int kvm_device_check_attr(int dev_fd, uint32_t group, uint64_t attr)
return kvm_device_ioctl(dev_fd, KVM_HAS_DEVICE_ATTR, &attribute) ? 0 : 1;
}
void kvm_device_access(int fd, int group, uint64_t attr,
void *val, bool write)
int kvm_device_access(int fd, int group, uint64_t attr,
void *val, bool write, Error **errp)
{
struct kvm_device_attr kvmattr;
int err;
@ -2231,11 +2232,12 @@ void kvm_device_access(int fd, int group, uint64_t attr,
write ? KVM_SET_DEVICE_ATTR : KVM_GET_DEVICE_ATTR,
&kvmattr);
if (err < 0) {
error_report("KVM_%s_DEVICE_ATTR failed: %s",
write ? "SET" : "GET", strerror(-err));
error_printf("Group %d attr 0x%016" PRIx64 "\n", group, attr);
abort();
error_setg_errno(errp, -err,
"KVM_%s_DEVICE_ATTR failed: Group %d "
"attr 0x%016" PRIx64,
write ? "SET" : "GET", group, attr);
}
return err;
}
/* Return 1 on success, 0 on failure */