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

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

target-arm queue:
 * util/oslib-posix : qemu_init_exec_dir implementation for Mac
 * target/arm: Last parts of neon decodetree conversion
 * hw/arm/virt: Add 5.0 HW compat props
 * hw/watchdog/cmsdk-apb-watchdog: Add trace event for lock status
 * mps2: Add CMSDK APB watchdog, FPGAIO block, S2I devices and I2C devices
 * mps2: Add some unimplemented-device stubs for audio and GPIO
 * mps2-tz: Use the ARM SBCon two-wire serial bus interface
 * target/arm: Check supported KVM features globally (not per vCPU)
 * tests/qtest/arm-cpu-features: Add feature setting tests
 * arm/virt: Add memory hot remove support

# gpg: Signature made Tue 23 Jun 2020 12:38:31 BST
# gpg:                using RSA key E1A5C593CD419DE28E8315CF3C2525ED14360CDE
# gpg:                issuer "peter.maydell@linaro.org"
# gpg: Good signature from "Peter Maydell <peter.maydell@linaro.org>" [ultimate]
# gpg:                 aka "Peter Maydell <pmaydell@gmail.com>" [ultimate]
# gpg:                 aka "Peter Maydell <pmaydell@chiark.greenend.org.uk>" [ultimate]
# Primary key fingerprint: E1A5 C593 CD41 9DE2 8E83  15CF 3C25 25ED 1436 0CDE

* remotes/pmaydell/tags/pull-target-arm-20200623: (42 commits)
  arm/virt: Add memory hot remove support
  tests/qtest/arm-cpu-features: Add feature setting tests
  target/arm: Check supported KVM features globally (not per vCPU)
  hw/arm/mps2-tz: Use the ARM SBCon two-wire serial bus interface
  hw/arm/mps2: Add audio I2S interface as unimplemented device
  hw/arm/mps2: Add I2C devices
  hw/arm/mps2: Add SPI devices
  hw/arm/mps2: Map the FPGA I/O block
  hw/arm/mps2: Add CMSDK AHB GPIO peripherals as unimplemented devices
  hw/arm/mps2: Add CMSDK APB watchdog device
  hw/arm/mps2: Rename CMSDK AHB peripheral region
  hw/arm/mps2: Document CMSDK/FPGA APB subsystem sections
  hw/arm: Use TYPE_VERSATILE_I2C instead of hardcoded string
  hw/i2c: Add header for ARM SBCon two-wire serial bus interface
  hw/i2c/versatile_i2c: Add SCL/SDA definitions
  hw/i2c/versatile_i2c: Add definitions for register addresses
  hw/watchdog/cmsdk-apb-watchdog: Add trace event for lock status
  target/arm: Remove dead code relating to SABA and UABA
  target/arm: Remove unnecessary gen_io_end() calls
  target/arm: Move some functions used only in translate-neon.inc.c to that file
  ...
Signed-off-by: NPeter Maydell <peter.maydell@linaro.org>
......@@ -842,6 +842,7 @@ M: Peter Maydell <peter.maydell@linaro.org>
L: qemu-arm@nongnu.org
S: Maintained
F: hw/*/versatile*
F: include/hw/i2c/arm_sbcon_i2c.h
F: hw/misc/arm_sysctl.c
F: docs/system/arm/versatile.rst
......
......@@ -193,6 +193,33 @@ static void acpi_ged_device_plug_cb(HotplugHandler *hotplug_dev,
}
}
static void acpi_ged_unplug_request_cb(HotplugHandler *hotplug_dev,
DeviceState *dev, Error **errp)
{
AcpiGedState *s = ACPI_GED(hotplug_dev);
if ((object_dynamic_cast(OBJECT(dev), TYPE_PC_DIMM) &&
!(object_dynamic_cast(OBJECT(dev), TYPE_NVDIMM)))) {
acpi_memory_unplug_request_cb(hotplug_dev, &s->memhp_state, dev, errp);
} else {
error_setg(errp, "acpi: device unplug request for unsupported device"
" type: %s", object_get_typename(OBJECT(dev)));
}
}
static void acpi_ged_unplug_cb(HotplugHandler *hotplug_dev,
DeviceState *dev, Error **errp)
{
AcpiGedState *s = ACPI_GED(hotplug_dev);
if (object_dynamic_cast(OBJECT(dev), TYPE_PC_DIMM)) {
acpi_memory_unplug_cb(&s->memhp_state, dev, errp);
} else {
error_setg(errp, "acpi: device unplug for unsupported device"
" type: %s", object_get_typename(OBJECT(dev)));
}
}
static void acpi_ged_send_event(AcpiDeviceIf *adev, AcpiEventStatusBits ev)
{
AcpiGedState *s = ACPI_GED(adev);
......@@ -318,6 +345,8 @@ static void acpi_ged_class_init(ObjectClass *class, void *data)
dc->vmsd = &vmstate_acpi_ged;
hc->plug = acpi_ged_device_plug_cb;
hc->unplug_request = acpi_ged_unplug_request_cb;
hc->unplug = acpi_ged_unplug_cb;
adevc->send_event = acpi_ged_send_event;
}
......
......@@ -59,7 +59,7 @@ config HIGHBANK
select ARM_TIMER # sp804
select ARM_V7M
select PL011 # UART
select PL022 # Serial port
select PL022 # SPI
select PL031 # RTC
select PL061 # GPIO
select PL310 # cache controller
......@@ -222,7 +222,7 @@ config STELLARIS
select CMSDK_APB_WATCHDOG
select I2C
select PL011 # UART
select PL022 # Serial port
select PL022 # SPI
select PL061 # GPIO
select SSD0303 # OLED display
select SSD0323 # OLED display
......@@ -401,10 +401,12 @@ config MPS2
select MPS2_FPGAIO
select MPS2_SCC
select OR_IRQ
select PL022 # Serial port
select PL022 # SPI
select PL080 # DMA controller
select SPLIT_IRQ
select UNIMP
select CMSDK_APB_WATCHDOG
select VERSATILE_I2C
config FSL_IMX7
bool
......
......@@ -58,6 +58,7 @@
#include "hw/arm/armsse.h"
#include "hw/dma/pl080.h"
#include "hw/ssi/pl022.h"
#include "hw/i2c/arm_sbcon_i2c.h"
#include "hw/net/lan9118.h"
#include "net/net.h"
#include "hw/core/split-irq.h"
......@@ -87,7 +88,7 @@ typedef struct {
TZPPC ppc[5];
TZMPC ssram_mpc[3];
PL022State spi[5];
UnimplementedDeviceState i2c[4];
ArmSbconI2CState i2c[4];
UnimplementedDeviceState i2s_audio;
UnimplementedDeviceState gpio[4];
UnimplementedDeviceState gfx;
......@@ -365,6 +366,18 @@ static MemoryRegion *make_spi(MPS2TZMachineState *mms, void *opaque,
return sysbus_mmio_get_region(s, 0);
}
static MemoryRegion *make_i2c(MPS2TZMachineState *mms, void *opaque,
const char *name, hwaddr size)
{
ArmSbconI2CState *i2c = opaque;
SysBusDevice *s;
object_initialize_child(OBJECT(mms), name, i2c, TYPE_ARM_SBCON_I2C);
s = SYS_BUS_DEVICE(i2c);
sysbus_realize(s, &error_fatal);
return sysbus_mmio_get_region(s, 0);
}
static void mps2tz_common_init(MachineState *machine)
{
MPS2TZMachineState *mms = MPS2TZ_MACHINE(machine);
......@@ -499,10 +512,10 @@ static void mps2tz_common_init(MachineState *machine)
{ "uart2", make_uart, &mms->uart[2], 0x40202000, 0x1000 },
{ "uart3", make_uart, &mms->uart[3], 0x40203000, 0x1000 },
{ "uart4", make_uart, &mms->uart[4], 0x40204000, 0x1000 },
{ "i2c0", make_unimp_dev, &mms->i2c[0], 0x40207000, 0x1000 },
{ "i2c1", make_unimp_dev, &mms->i2c[1], 0x40208000, 0x1000 },
{ "i2c2", make_unimp_dev, &mms->i2c[2], 0x4020c000, 0x1000 },
{ "i2c3", make_unimp_dev, &mms->i2c[3], 0x4020d000, 0x1000 },
{ "i2c0", make_i2c, &mms->i2c[0], 0x40207000, 0x1000 },
{ "i2c1", make_i2c, &mms->i2c[1], 0x40208000, 0x1000 },
{ "i2c2", make_i2c, &mms->i2c[2], 0x4020c000, 0x1000 },
{ "i2c3", make_i2c, &mms->i2c[3], 0x4020d000, 0x1000 },
},
}, {
.name = "apb_ppcexp2",
......
......@@ -38,8 +38,12 @@
#include "hw/timer/cmsdk-apb-timer.h"
#include "hw/timer/cmsdk-apb-dualtimer.h"
#include "hw/misc/mps2-scc.h"
#include "hw/misc/mps2-fpgaio.h"
#include "hw/ssi/pl022.h"
#include "hw/i2c/arm_sbcon_i2c.h"
#include "hw/net/lan9118.h"
#include "net/net.h"
#include "hw/watchdog/cmsdk-apb-watchdog.h"
typedef enum MPS2FPGAType {
FPGA_AN385,
......@@ -65,8 +69,12 @@ typedef struct {
MemoryRegion blockram_m2;
MemoryRegion blockram_m3;
MemoryRegion sram;
/* FPGA APB subsystem */
MPS2SCC scc;
MPS2FPGAIO fpgaio;
/* CMSDK APB subsystem */
CMSDKAPBDualTimer dualtimer;
CMSDKAPBWatchdog watchdog;
} MPS2MachineState;
#define TYPE_MPS2_MACHINE "mps2"
......@@ -111,6 +119,7 @@ static void mps2_common_init(MachineState *machine)
MemoryRegion *system_memory = get_system_memory();
MachineClass *mc = MACHINE_GET_CLASS(machine);
DeviceState *armv7m, *sccdev;
int i;
if (strcmp(machine->cpu_type, mc->default_cpu_type) != 0) {
error_report("This board can only be used with CPU %s",
......@@ -210,10 +219,11 @@ static void mps2_common_init(MachineState *machine)
*/
create_unimplemented_device("CMSDK APB peripheral region @0x40000000",
0x40000000, 0x00010000);
create_unimplemented_device("CMSDK peripheral region @0x40010000",
create_unimplemented_device("CMSDK AHB peripheral region @0x40010000",
0x40010000, 0x00010000);
create_unimplemented_device("Extra peripheral region @0x40020000",
0x40020000, 0x00010000);
create_unimplemented_device("RESERVED 4", 0x40030000, 0x001D0000);
create_unimplemented_device("VGA", 0x41000000, 0x0200000);
......@@ -225,7 +235,6 @@ static void mps2_common_init(MachineState *machine)
*/
Object *orgate;
DeviceState *orgate_dev;
int i;
orgate = object_new(TYPE_OR_IRQ);
object_property_set_int(orgate, 6, "num-lines", &error_fatal);
......@@ -262,7 +271,6 @@ static void mps2_common_init(MachineState *machine)
*/
Object *orgate;
DeviceState *orgate_dev;
int i;
orgate = object_new(TYPE_OR_IRQ);
object_property_set_int(orgate, 10, "num-lines", &error_fatal);
......@@ -298,10 +306,15 @@ static void mps2_common_init(MachineState *machine)
default:
g_assert_not_reached();
}
for (i = 0; i < 4; i++) {
static const hwaddr gpiobase[] = {0x40010000, 0x40011000,
0x40012000, 0x40013000};
create_unimplemented_device("cmsdk-ahb-gpio", gpiobase[i], 0x1000);
}
/* CMSDK APB subsystem */
cmsdk_apb_timer_create(0x40000000, qdev_get_gpio_in(armv7m, 8), SYSCLK_FRQ);
cmsdk_apb_timer_create(0x40001000, qdev_get_gpio_in(armv7m, 9), SYSCLK_FRQ);
object_initialize_child(OBJECT(mms), "dualtimer", &mms->dualtimer,
TYPE_CMSDK_APB_DUALTIMER);
qdev_prop_set_uint32(DEVICE(&mms->dualtimer), "pclk-frq", SYSCLK_FRQ);
......@@ -309,7 +322,15 @@ static void mps2_common_init(MachineState *machine)
sysbus_connect_irq(SYS_BUS_DEVICE(&mms->dualtimer), 0,
qdev_get_gpio_in(armv7m, 10));
sysbus_mmio_map(SYS_BUS_DEVICE(&mms->dualtimer), 0, 0x40002000);
object_initialize_child(OBJECT(mms), "watchdog", &mms->watchdog,
TYPE_CMSDK_APB_WATCHDOG);
qdev_prop_set_uint32(DEVICE(&mms->watchdog), "wdogclk-frq", SYSCLK_FRQ);
sysbus_realize(SYS_BUS_DEVICE(&mms->watchdog), &error_fatal);
sysbus_connect_irq(SYS_BUS_DEVICE(&mms->watchdog), 0,
qdev_get_gpio_in_named(armv7m, "NMI", 0));
sysbus_mmio_map(SYS_BUS_DEVICE(&mms->watchdog), 0, 0x40008000);
/* FPGA APB subsystem */
object_initialize_child(OBJECT(mms), "scc", &mms->scc, TYPE_MPS2_SCC);
sccdev = DEVICE(&mms->scc);
qdev_prop_set_uint32(sccdev, "scc-cfg4", 0x2);
......@@ -317,6 +338,42 @@ static void mps2_common_init(MachineState *machine)
qdev_prop_set_uint32(sccdev, "scc-id", mmc->scc_id);
sysbus_realize(SYS_BUS_DEVICE(&mms->scc), &error_fatal);
sysbus_mmio_map(SYS_BUS_DEVICE(sccdev), 0, 0x4002f000);
object_initialize_child(OBJECT(mms), "fpgaio",
&mms->fpgaio, TYPE_MPS2_FPGAIO);
qdev_prop_set_uint32(DEVICE(&mms->fpgaio), "prescale-clk", 25000000);
sysbus_realize(SYS_BUS_DEVICE(&mms->fpgaio), &error_fatal);
sysbus_mmio_map(SYS_BUS_DEVICE(&mms->fpgaio), 0, 0x40028000);
sysbus_create_simple(TYPE_PL022, 0x40025000, /* External ADC */
qdev_get_gpio_in(armv7m, 22));
for (i = 0; i < 2; i++) {
static const int spi_irqno[] = {11, 24};
static const hwaddr spibase[] = {0x40020000, /* APB */
0x40021000, /* LCD */
0x40026000, /* Shield0 */
0x40027000}; /* Shield1 */
DeviceState *orgate_dev;
Object *orgate;
int j;
orgate = object_new(TYPE_OR_IRQ);
object_property_set_int(orgate, 2, "num-lines", &error_fatal);
orgate_dev = DEVICE(orgate);
qdev_realize(orgate_dev, NULL, &error_fatal);
qdev_connect_gpio_out(orgate_dev, 0,
qdev_get_gpio_in(armv7m, spi_irqno[i]));
for (j = 0; j < 2; j++) {
sysbus_create_simple(TYPE_PL022, spibase[2 * i + j],
qdev_get_gpio_in(orgate_dev, j));
}
}
for (i = 0; i < 4; i++) {
static const hwaddr i2cbase[] = {0x40022000, /* Touch */
0x40023000, /* Audio */
0x40029000, /* Shield0 */
0x4002a000}; /* Shield1 */
sysbus_create_simple(TYPE_ARM_SBCON_I2C, i2cbase[i], NULL);
}
create_unimplemented_device("i2s", 0x40024000, 0x400);
/* In hardware this is a LAN9220; the LAN9118 is software compatible
* except that it doesn't support the checksum-offload feature.
......
......@@ -26,6 +26,7 @@
#include "hw/cpu/a9mpcore.h"
#include "hw/intc/realview_gic.h"
#include "hw/irq.h"
#include "hw/i2c/arm_sbcon_i2c.h"
#define SMP_BOOT_ADDR 0xe0000000
#define SMP_BOOTREG_ADDR 0x10000030
......@@ -282,7 +283,7 @@ static void realview_init(MachineState *machine,
}
}
dev = sysbus_create_simple("versatile_i2c", 0x10002000, NULL);
dev = sysbus_create_simple(TYPE_VERSATILE_I2C, 0x10002000, NULL);
i2c = (I2CBus *)qdev_get_child_bus(dev, "i2c");
i2c_create_slave(i2c, "ds1338", 0x68);
......
......@@ -18,6 +18,7 @@
#include "sysemu/sysemu.h"
#include "hw/pci/pci.h"
#include "hw/i2c/i2c.h"
#include "hw/i2c/arm_sbcon_i2c.h"
#include "hw/irq.h"
#include "hw/boards.h"
#include "exec/address-spaces.h"
......@@ -314,7 +315,7 @@ static void versatile_init(MachineState *machine, int board_id)
/* Add PL031 Real Time Clock. */
sysbus_create_simple("pl031", 0x101e8000, pic[10]);
dev = sysbus_create_simple("versatile_i2c", 0x10002000, NULL);
dev = sysbus_create_simple(TYPE_VERSATILE_I2C, 0x10002000, NULL);
i2c = (I2CBus *)qdev_get_child_bus(dev, "i2c");
i2c_create_slave(i2c, "ds1338", 0x68);
......
......@@ -42,6 +42,7 @@
#include "hw/char/pl011.h"
#include "hw/cpu/a9mpcore.h"
#include "hw/cpu/a15mpcore.h"
#include "hw/i2c/arm_sbcon_i2c.h"
#define VEXPRESS_BOARD_ID 0x8e0
#define VEXPRESS_FLASH_SIZE (64 * 1024 * 1024)
......@@ -640,7 +641,7 @@ static void vexpress_common_init(MachineState *machine)
sysbus_create_simple("sp804", map[VE_TIMER01], pic[2]);
sysbus_create_simple("sp804", map[VE_TIMER23], pic[3]);
dev = sysbus_create_simple("versatile_i2c", map[VE_SERIALDVI], NULL);
dev = sysbus_create_simple(TYPE_VERSATILE_I2C, map[VE_SERIALDVI], NULL);
i2c = (I2CBus *)qdev_get_child_bus(dev, "i2c");
i2c_create_slave(i2c, "sii9022", 0x39);
......
......@@ -2177,11 +2177,68 @@ static void virt_machine_device_plug_cb(HotplugHandler *hotplug_dev,
}
}
static void virt_dimm_unplug_request(HotplugHandler *hotplug_dev,
DeviceState *dev, Error **errp)
{
VirtMachineState *vms = VIRT_MACHINE(hotplug_dev);
Error *local_err = NULL;
if (!vms->acpi_dev) {
error_setg(&local_err,
"memory hotplug is not enabled: missing acpi-ged device");
goto out;
}
if (object_dynamic_cast(OBJECT(dev), TYPE_NVDIMM)) {
error_setg(&local_err,
"nvdimm device hot unplug is not supported yet.");
goto out;
}
hotplug_handler_unplug_request(HOTPLUG_HANDLER(vms->acpi_dev), dev,
&local_err);
out:
error_propagate(errp, local_err);
}
static void virt_dimm_unplug(HotplugHandler *hotplug_dev,
DeviceState *dev, Error **errp)
{
VirtMachineState *vms = VIRT_MACHINE(hotplug_dev);
Error *local_err = NULL;
hotplug_handler_unplug(HOTPLUG_HANDLER(vms->acpi_dev), dev, &local_err);
if (local_err) {
goto out;
}
pc_dimm_unplug(PC_DIMM(dev), MACHINE(vms));
qdev_unrealize(dev);
out:
error_propagate(errp, local_err);
}
static void virt_machine_device_unplug_request_cb(HotplugHandler *hotplug_dev,
DeviceState *dev, Error **errp)
{
error_setg(errp, "device unplug request for unsupported device"
" type: %s", object_get_typename(OBJECT(dev)));
if (object_dynamic_cast(OBJECT(dev), TYPE_PC_DIMM)) {
virt_dimm_unplug_request(hotplug_dev, dev, errp);
} else {
error_setg(errp, "device unplug request for unsupported device"
" type: %s", object_get_typename(OBJECT(dev)));
}
}
static void virt_machine_device_unplug_cb(HotplugHandler *hotplug_dev,
DeviceState *dev, Error **errp)
{
if (object_dynamic_cast(OBJECT(dev), TYPE_PC_DIMM)) {
virt_dimm_unplug(hotplug_dev, dev, errp);
} else {
error_setg(errp, "virt: device unplug for unsupported device"
" type: %s", object_get_typename(OBJECT(dev)));
}
}
static HotplugHandler *virt_machine_get_hotplug_handler(MachineState *machine,
......@@ -2262,6 +2319,7 @@ static void virt_machine_class_init(ObjectClass *oc, void *data)
hc->pre_plug = virt_machine_device_pre_plug_cb;
hc->plug = virt_machine_device_plug_cb;
hc->unplug_request = virt_machine_device_unplug_request_cb;
hc->unplug = virt_machine_device_unplug_cb;
mc->numa_mem_supported = true;
mc->nvdimm_supported = true;
mc->auto_enable_numa_with_memhp = true;
......@@ -2375,6 +2433,7 @@ DEFINE_VIRT_MACHINE_AS_LATEST(5, 1)
static void virt_machine_5_0_options(MachineClass *mc)
{
virt_machine_5_1_options(mc);
compat_props_add(mc->compat_props, hw_compat_5_0, hw_compat_5_0_len);
}
DEFINE_VIRT_MACHINE(5, 0)
......
/*
* ARM Versatile I2C controller
* ARM SBCon two-wire serial bus interface (I2C bitbang)
* a.k.a. ARM Versatile I2C controller
*
* Copyright (c) 2006-2007 CodeSourcery.
* Copyright (c) 2012 Oskar Andero <oskar.andero@gmail.com>
......@@ -22,32 +23,33 @@
*/
#include "qemu/osdep.h"
#include "hw/sysbus.h"
#include "hw/i2c/bitbang_i2c.h"
#include "hw/i2c/arm_sbcon_i2c.h"
#include "hw/registerfields.h"
#include "qemu/log.h"
#include "qemu/module.h"
#define TYPE_VERSATILE_I2C "versatile_i2c"
#define VERSATILE_I2C(obj) \
OBJECT_CHECK(VersatileI2CState, (obj), TYPE_VERSATILE_I2C)
typedef struct VersatileI2CState {
SysBusDevice parent_obj;
typedef ArmSbconI2CState VersatileI2CState;
MemoryRegion iomem;
bitbang_i2c_interface bitbang;
int out;
int in;
} VersatileI2CState;
REG32(CONTROL_GET, 0)
REG32(CONTROL_SET, 0)
REG32(CONTROL_CLR, 4)
#define SCL BIT(0)
#define SDA BIT(1)
static uint64_t versatile_i2c_read(void *opaque, hwaddr offset,
unsigned size)
{
VersatileI2CState *s = (VersatileI2CState *)opaque;
if (offset == 0) {
switch (offset) {
case A_CONTROL_SET:
return (s->out & 1) | (s->in << 1);
} else {
default:
qemu_log_mask(LOG_GUEST_ERROR,
"%s: Bad offset 0x%x\n", __func__, (int)offset);
return -1;
......@@ -60,18 +62,18 @@ static void versatile_i2c_write(void *opaque, hwaddr offset,
VersatileI2CState *s = (VersatileI2CState *)opaque;
switch (offset) {
case 0:
case A_CONTROL_SET:
s->out |= value & 3;
break;
case 4:
case A_CONTROL_CLR:
s->out &= ~value;
break;
default:
qemu_log_mask(LOG_GUEST_ERROR,
"%s: Bad offset 0x%x\n", __func__, (int)offset);
}
bitbang_i2c_set(&s->bitbang, BITBANG_I2C_SCL, (s->out & 1) != 0);
s->in = bitbang_i2c_set(&s->bitbang, BITBANG_I2C_SDA, (s->out & 2) != 0);
bitbang_i2c_set(&s->bitbang, BITBANG_I2C_SCL, (s->out & SCL) != 0);
s->in = bitbang_i2c_set(&s->bitbang, BITBANG_I2C_SDA, (s->out & SDA) != 0);
}
static const MemoryRegionOps versatile_i2c_ops = {
......@@ -90,7 +92,7 @@ static void versatile_i2c_init(Object *obj)
bus = i2c_init_bus(dev, "i2c");
bitbang_i2c_init(&s->bitbang, bus);
memory_region_init_io(&s->iomem, obj, &versatile_i2c_ops, s,
"versatile_i2c", 0x1000);
"arm_sbcon_i2c", 0x1000);
sysbus_init_mmio(sbd, &s->iomem);
}
......
......@@ -225,6 +225,7 @@ static void cmsdk_apb_watchdog_write(void *opaque, hwaddr offset,
break;
case A_WDOGLOCK:
s->lock = (value != WDOG_UNLOCK_VALUE);
trace_cmsdk_apb_watchdog_lock(s->lock);
break;
case A_WDOGITCR:
if (s->is_luminary) {
......
......@@ -4,3 +4,4 @@
cmsdk_apb_watchdog_read(uint64_t offset, uint64_t data, unsigned size) "CMSDK APB watchdog read: offset 0x%" PRIx64 " data 0x%" PRIx64 " size %u"
cmsdk_apb_watchdog_write(uint64_t offset, uint64_t data, unsigned size) "CMSDK APB watchdog write: offset 0x%" PRIx64 " data 0x%" PRIx64 " size %u"
cmsdk_apb_watchdog_reset(void) "CMSDK APB watchdog: reset"
cmsdk_apb_watchdog_lock(uint32_t lock) "CMSDK APB watchdog: lock %" PRIu32
/*
* ARM SBCon two-wire serial bus interface (I2C bitbang)
* a.k.a.
* ARM Versatile I2C controller
*
* Copyright (c) 2006-2007 CodeSourcery.
* Copyright (c) 2012 Oskar Andero <oskar.andero@gmail.com>
* Copyright (C) 2020 Philippe Mathieu-Daudé <f4bug@amsat.org>
*
* SPDX-License-Identifier: GPL-2.0-or-later
*/
#ifndef HW_I2C_ARM_SBCON_H
#define HW_I2C_ARM_SBCON_H
#include "hw/sysbus.h"
#include "hw/i2c/bitbang_i2c.h"
#define TYPE_VERSATILE_I2C "versatile_i2c"
#define TYPE_ARM_SBCON_I2C TYPE_VERSATILE_I2C
#define ARM_SBCON_I2C(obj) \
OBJECT_CHECK(ArmSbconI2CState, (obj), TYPE_ARM_SBCON_I2C)
typedef struct ArmSbconI2CState {
/*< private >*/
SysBusDevice parent_obj;
/*< public >*/
MemoryRegion iomem;
bitbang_i2c_interface bitbang;
int out;
int in;
} ArmSbconI2CState;
#endif /* HW_I2C_ARM_SBCON_H */
......@@ -1108,7 +1108,7 @@ static void arm_set_pmu(Object *obj, bool value, Error **errp)
ARMCPU *cpu = ARM_CPU(obj);
if (value) {
if (kvm_enabled() && !kvm_arm_pmu_supported(CPU(cpu))) {
if (kvm_enabled() && !kvm_arm_pmu_supported()) {
error_setg(errp, "'pmu' feature not supported by KVM on this host");
return;
}
......
......@@ -2334,7 +2334,7 @@ static inline uint64_t cpreg_to_kvm_id(uint32_t cpregid)
* migration or KVM state synchronization. (Typically this is for "registers"
* which are actually used as instructions for cache maintenance and so on.)
* IO indicates that this register does I/O and therefore its accesses
* need to be surrounded by gen_io_start()/gen_io_end(). In particular,
* need to be marked with gen_io_start() and also end the TB. In particular,
* registers which implement clocks or timers require this.
* RAISES_EXC is for when the read or write hook might raise an exception;
* the generated code will synchronize the CPU state before calling the hook
......
......@@ -266,7 +266,7 @@ void arm_cpu_sve_finalize(ARMCPU *cpu, Error **errp)
/* Collect the set of vector lengths supported by KVM. */
bitmap_zero(kvm_supported, ARM_MAX_VQ);
if (kvm_enabled() && kvm_arm_sve_supported(CPU(cpu))) {
if (kvm_enabled() && kvm_arm_sve_supported()) {
kvm_arm_sve_get_vls(CPU(cpu), kvm_supported);
} else if (kvm_enabled()) {
assert(!cpu_isar_feature(aa64_sve, cpu));
......@@ -473,7 +473,7 @@ static void cpu_max_set_sve_max_vq(Object *obj, Visitor *v, const char *name,
return;
}
if (kvm_enabled() && !kvm_arm_sve_supported(CPU(cpu))) {
if (kvm_enabled() && !kvm_arm_sve_supported()) {
error_setg(errp, "cannot set sve-max-vq");
error_append_hint(errp, "SVE not supported by KVM on this host\n");
return;
......@@ -519,7 +519,7 @@ static void cpu_arm_set_sve_vq(Object *obj, Visitor *v, const char *name,
return;
}
if (value && kvm_enabled() && !kvm_arm_sve_supported(CPU(cpu))) {
if (value && kvm_enabled() && !kvm_arm_sve_supported()) {
error_setg(errp, "cannot enable %s", name);
error_append_hint(errp, "SVE not supported by KVM on this host\n");
return;
......@@ -556,7 +556,7 @@ static void cpu_arm_set_sve(Object *obj, Visitor *v, const char *name,
return;
}
if (value && kvm_enabled() && !kvm_arm_sve_supported(CPU(cpu))) {
if (value && kvm_enabled() && !kvm_arm_sve_supported()) {
error_setg(errp, "'sve' feature not supported by KVM on this host");
return;
}
......@@ -751,7 +751,7 @@ static void aarch64_cpu_set_aarch64(Object *obj, bool value, Error **errp)
* uniform execution state like do_interrupt.
*/
if (value == false) {
if (!kvm_enabled() || !kvm_arm_aarch32_supported(CPU(cpu))) {
if (!kvm_enabled() || !kvm_arm_aarch32_supported()) {
error_setg(errp, "'aarch64' feature cannot be disabled "
"unless KVM is enabled and 32-bit EL1 "
"is supported");
......
......@@ -208,9 +208,9 @@ void kvm_arm_add_vcpu_properties(Object *obj)
}
}
bool kvm_arm_pmu_supported(CPUState *cpu)
bool kvm_arm_pmu_supported(void)
{
return kvm_check_extension(cpu->kvm_state, KVM_CAP_ARM_PMU_V3);
return kvm_check_extension(kvm_state, KVM_CAP_ARM_PMU_V3);
}
int kvm_arm_get_max_vm_ipa_size(MachineState *ms)
......
......@@ -652,18 +652,14 @@ bool kvm_arm_get_host_cpu_features(ARMHostCPUFeatures *ahcf)
return true;
}
bool kvm_arm_aarch32_supported(CPUState *cpu)
bool kvm_arm_aarch32_supported(void)
{
KVMState *s = KVM_STATE(current_accel());
return kvm_check_extension(s, KVM_CAP_ARM_EL1_32BIT);
return kvm_check_extension(kvm_state, KVM_CAP_ARM_EL1_32BIT);
}
bool kvm_arm_sve_supported(CPUState *cpu)
bool kvm_arm_sve_supported(void)
{
KVMState *s = KVM_STATE(current_accel());
return kvm_check_extension(s, KVM_CAP_ARM_SVE);
return kvm_check_extension(kvm_state, KVM_CAP_ARM_SVE);
}
QEMU_BUILD_BUG_ON(KVM_ARM64_SVE_VQ_MIN != 1);
......@@ -798,7 +794,7 @@ int kvm_arch_init_vcpu(CPUState *cs)
env->features &= ~(1ULL << ARM_FEATURE_PMU);
}
if (cpu_isar_feature(aa64_sve, cpu)) {
assert(kvm_arm_sve_supported(cs));
assert(kvm_arm_sve_supported());
cpu->kvm_init_features[0] |= 1 << KVM_ARM_VCPU_SVE;
}
......
......@@ -269,29 +269,26 @@ void kvm_arm_add_vcpu_properties(Object *obj);
/**
* kvm_arm_aarch32_supported:
* @cs: CPUState
*
* Returns: true if the KVM VCPU can enable AArch32 mode
* Returns: true if KVM can enable AArch32 mode
* and false otherwise.
*/
bool kvm_arm_aarch32_supported(CPUState *cs);
bool kvm_arm_aarch32_supported(void);
/**
* kvm_arm_pmu_supported:
* @cs: CPUState
*
* Returns: true if the KVM VCPU can enable its PMU
* Returns: true if KVM can enable the PMU
* and false otherwise.
*/
bool kvm_arm_pmu_supported(CPUState *cs);
bool kvm_arm_pmu_supported(void);
/**
* kvm_arm_sve_supported:
* @cs: CPUState
*
* Returns true if the KVM VCPU can enable SVE and false otherwise.
* Returns true if KVM can enable SVE and false otherwise.
*/
bool kvm_arm_sve_supported(CPUState *cs);
bool kvm_arm_sve_supported(void);
/**
* kvm_arm_get_max_vm_ipa_size:
......@@ -359,17 +356,17 @@ static inline void kvm_arm_set_cpu_features_from_host(ARMCPU *cpu)
static inline void kvm_arm_add_vcpu_properties(Object *obj) {}
static inline bool kvm_arm_aarch32_supported(CPUState *cs)
static inline bool kvm_arm_aarch32_supported(void)
{
return false;
}
static inline bool kvm_arm_pmu_supported(CPUState *cs)
static inline bool kvm_arm_pmu_supported(void)
{
return false;
}
static inline bool kvm_arm_sve_supported(CPUState *cs)
static inline bool kvm_arm_sve_supported(void)
{
return false;
}
......
......@@ -429,6 +429,112 @@ Vimm_1r 1111 001 . 1 . 000 ... .... cmode:4 0 . op:1 1 .... @1reg_imm
vm=%vm_dp vd=%vd_dp size=1
VDUP_scalar 1111 001 1 1 . 11 index:1 100 .... 11 000 q:1 . 0 .... \
vm=%vm_dp vd=%vd_dp size=2
##################################################################
# 2-reg-misc grouping:
# 1111 001 11 D 11 size:2 opc1:2 Vd:4 0 opc2:4 q:1 M 0 Vm:4
##################################################################
&2misc vd vm q size
@2misc .... ... .. . .. size:2 .. .... . .... q:1 . . .... \
&2misc vm=%vm_dp vd=%vd_dp
@2misc_q0 .... ... .. . .. size:2 .. .... . .... . . . .... \
&2misc vm=%vm_dp vd=%vd_dp q=0
@2misc_q1 .... ... .. . .. size:2 .. .... . .... . . . .... \
&2misc vm=%vm_dp vd=%vd_dp q=1
VREV64 1111 001 11 . 11 .. 00 .... 0 0000 . . 0 .... @2misc
VREV32 1111 001 11 . 11 .. 00 .... 0 0001 . . 0 .... @2misc
VREV16 1111 001 11 . 11 .. 00 .... 0 0010 . . 0 .... @2misc
VPADDL_S 1111 001 11 . 11 .. 00 .... 0 0100 . . 0 .... @2misc
VPADDL_U 1111 001 11 . 11 .. 00 .... 0 0101 . . 0 .... @2misc
AESE 1111 001 11 . 11 .. 00 .... 0 0110 0 . 0 .... @2misc_q1
AESD 1111 001 11 . 11 .. 00 .... 0 0110 1 . 0 .... @2misc_q1
AESMC 1111 001 11 . 11 .. 00 .... 0 0111 0 . 0 .... @2misc_q1
AESIMC 1111 001 11 . 11 .. 00 .... 0 0111 1 . 0 .... @2misc_q1
VCLS 1111 001 11 . 11 .. 00 .... 0 1000 . . 0 .... @2misc
VCLZ 1111 001 11 . 11 .. 00 .... 0 1001 . . 0 .... @2misc
VCNT 1111 001 11 . 11 .. 00 .... 0 1010 . . 0 .... @2misc
VMVN 1111 001 11 . 11 .. 00 .... 0 1011 . . 0 .... @2misc
VPADAL_S 1111 001 11 . 11 .. 00 .... 0 1100 . . 0 .... @2misc
VPADAL_U 1111 001 11 . 11 .. 00 .... 0 1101 . . 0 .... @2misc
VQABS 1111 001 11 . 11 .. 00 .... 0 1110 . . 0 .... @2misc
VQNEG 1111 001 11 . 11 .. 00 .... 0 1111 . . 0 .... @2misc
VCGT0 1111 001 11 . 11 .. 01 .... 0 0000 . . 0 .... @2misc
VCGE0 1111 001 11 . 11 .. 01 .... 0 0001 . . 0 .... @2misc
VCEQ0 1111 001 11 . 11 .. 01 .... 0 0010 . . 0 .... @2misc
VCLE0 1111 001 11 . 11 .. 01 .... 0 0011 . . 0 .... @2misc
VCLT0 1111 001 11 . 11 .. 01 .... 0 0100 . . 0 .... @2misc
SHA1H 1111 001 11 . 11 .. 01 .... 0 0101 1 . 0 .... @2misc_q1
VABS 1111 001 11 . 11 .. 01 .... 0 0110 . . 0 .... @2misc
VNEG 1111 001 11 . 11 .. 01 .... 0 0111 . . 0 .... @2misc
VCGT0_F 1111 001 11 . 11 .. 01 .... 0 1000 . . 0 .... @2misc
VCGE0_F 1111 001 11 . 11 .. 01 .... 0 1001 . . 0 .... @2misc
VCEQ0_F 1111 001 11 . 11 .. 01 .... 0 1010 . . 0 .... @2misc
VCLE0_F 1111 001 11 . 11 .. 01 .... 0 1011 . . 0 .... @2misc
VCLT0_F 1111 001 11 . 11 .. 01 .... 0 1100 . . 0 .... @2misc
VABS_F 1111 001 11 . 11 .. 01 .... 0 1110 . . 0 .... @2misc
VNEG_F 1111 001 11 . 11 .. 01 .... 0 1111 . . 0 .... @2misc
VSWP 1111 001 11 . 11 .. 10 .... 0 0000 . . 0 .... @2misc
VTRN 1111 001 11 . 11 .. 10 .... 0 0001 . . 0 .... @2misc
VUZP 1111 001 11 . 11 .. 10 .... 0 0010 . . 0 .... @2misc
VZIP 1111 001 11 . 11 .. 10 .... 0 0011 . . 0 .... @2misc
VMOVN 1111 001 11 . 11 .. 10 .... 0 0100 0 . 0 .... @2misc_q0
# VQMOVUN: unsigned result (source is always signed)
VQMOVUN 1111 001 11 . 11 .. 10 .... 0 0100 1 . 0 .... @2misc_q0
# VQMOVN: signed result, source may be signed (_S) or unsigned (_U)
VQMOVN_S 1111 001 11 . 11 .. 10 .... 0 0101 0 . 0 .... @2misc_q0
VQMOVN_U 1111 001 11 . 11 .. 10 .... 0 0101 1 . 0 .... @2misc_q0
VSHLL 1111 001 11 . 11 .. 10 .... 0 0110 0 . 0 .... @2misc_q0
SHA1SU1 1111 001 11 . 11 .. 10 .... 0 0111 0 . 0 .... @2misc_q1
SHA256SU0 1111 001 11 . 11 .. 10 .... 0 0111 1 . 0 .... @2misc_q1
VRINTN 1111 001 11 . 11 .. 10 .... 0 1000 . . 0 .... @2misc
VRINTX 1111 001 11 . 11 .. 10 .... 0 1001 . . 0 .... @2misc
VRINTA 1111 001 11 . 11 .. 10 .... 0 1010 . . 0 .... @2misc
VRINTZ 1111 001 11 . 11 .. 10 .... 0 1011 . . 0 .... @2misc
VCVT_F16_F32 1111 001 11 . 11 .. 10 .... 0 1100 0 . 0 .... @2misc_q0
VRINTM 1111 001 11 . 11 .. 10 .... 0 1101 . . 0 .... @2misc
VCVT_F32_F16 1111 001 11 . 11 .. 10 .... 0 1110 0 . 0 .... @2misc_q0
VRINTP 1111 001 11 . 11 .. 10 .... 0 1111 . . 0 .... @2misc
VCVTAS 1111 001 11 . 11 .. 11 .... 0 0000 . . 0 .... @2misc
VCVTAU 1111 001 11 . 11 .. 11 .... 0 0001 . . 0 .... @2misc
VCVTNS 1111 001 11 . 11 .. 11 .... 0 0010 . . 0 .... @2misc
VCVTNU 1111 001 11 . 11 .. 11 .... 0 0011 . . 0 .... @2misc
VCVTPS 1111 001 11 . 11 .. 11 .... 0 0100 . . 0 .... @2misc
VCVTPU 1111 001 11 . 11 .. 11 .... 0 0101 . . 0 .... @2misc
VCVTMS 1111 001 11 . 11 .. 11 .... 0 0110 . . 0 .... @2misc
VCVTMU 1111 001 11 . 11 .. 11 .... 0 0111 . . 0 .... @2misc
VRECPE 1111 001 11 . 11 .. 11 .... 0 1000 . . 0 .... @2misc
VRSQRTE 1111 001 11 . 11 .. 11 .... 0 1001 . . 0 .... @2misc
VRECPE_F 1111 001 11 . 11 .. 11 .... 0 1010 . . 0 .... @2misc
VRSQRTE_F 1111 001 11 . 11 .. 11 .... 0 1011 . . 0 .... @2misc
VCVT_FS 1111 001 11 . 11 .. 11 .... 0 1100 . . 0 .... @2misc
VCVT_FU 1111 001 11 . 11 .. 11 .... 0 1101 . . 0 .... @2misc
VCVT_SF 1111 001 11 . 11 .. 11 .... 0 1110 . . 0 .... @2misc
VCVT_UF 1111 001 11 . 11 .. 11 .... 0 1111 . . 0 .... @2misc
]
# Subgroup for size != 0b11
......
......@@ -9534,7 +9534,7 @@ static void handle_2misc_fcmp_zero(DisasContext *s, int opcode,
TCGv_i64 tcg_op = tcg_temp_new_i64();
TCGv_i64 tcg_zero = tcg_const_i64(0);
TCGv_i64 tcg_res = tcg_temp_new_i64();
NeonGenTwoDoubleOPFn *genfn;
NeonGenTwoDoubleOpFn *genfn;
bool swap = false;
int pass;
......@@ -9576,7 +9576,7 @@ static void handle_2misc_fcmp_zero(DisasContext *s, int opcode,
TCGv_i32 tcg_op = tcg_temp_new_i32();
TCGv_i32 tcg_zero = tcg_const_i32(0);
TCGv_i32 tcg_res = tcg_temp_new_i32();
NeonGenTwoSingleOPFn *genfn;
NeonGenTwoSingleOpFn *genfn;
bool swap = false;
int pass, maxpasses;
......@@ -11370,18 +11370,6 @@ static void disas_simd_3same_int(DisasContext *s, uint32_t insn)
genfn(tcg_res, tcg_op1, tcg_op2);
}
if (opcode == 0xf) {
/* SABA, UABA: accumulating ops */
static NeonGenTwoOpFn * const fns[3] = {
gen_helper_neon_add_u8,
gen_helper_neon_add_u16,
tcg_gen_add_i32,
};
read_vec_element_i32(s, tcg_op1, rd, pass, MO_32);
fns[size](tcg_res, tcg_op1, tcg_res);
}
write_vec_element_i32(s, tcg_res, rd, pass, MO_32);
tcg_temp_free_i32(tcg_res);
......@@ -11917,8 +11905,8 @@ static void handle_2misc_pairwise(DisasContext *s, int opcode, bool u,
} else {
for (pass = 0; pass < maxpass; pass++) {
TCGv_i64 tcg_op = tcg_temp_new_i64();
NeonGenOneOpFn *genfn;
static NeonGenOneOpFn * const fns[2][2] = {
NeonGenOne64OpFn *genfn;
static NeonGenOne64OpFn * const fns[2][2] = {
{ gen_helper_neon_addlp_s8, gen_helper_neon_addlp_u8 },
{ gen_helper_neon_addlp_s16, gen_helper_neon_addlp_u16 },
};
......
此差异已折叠。
......@@ -119,15 +119,14 @@ static bool full_vfp_access_check(DisasContext *s, bool ignore_vfp_enabled)
if (s->v7m_lspact) {
/*
* Lazy state saving affects external memory and also the NVIC,
* so we must mark it as an IO operation for icount.
* so we must mark it as an IO operation for icount (and cause
* this to be the last insn in the TB).
*/
if (tb_cflags(s->base.tb) & CF_USE_ICOUNT) {
s->base.is_jmp = DISAS_UPDATE;
gen_io_start();
}
gen_helper_v7m_preserve_fp_state(cpu_env);
if (tb_cflags(s->base.tb) & CF_USE_ICOUNT) {
gen_io_end();
}
/*
* If the preserve_fp_state helper doesn't throw an exception
* then it will clear LSPACT; we don't need to repeat this for
......
此差异已折叠。
......@@ -363,6 +363,7 @@ typedef void GVecGen4Fn(unsigned, uint32_t, uint32_t, uint32_t,
uint32_t, uint32_t, uint32_t);
/* Function prototype for gen_ functions for calling Neon helpers */
typedef void NeonGenOneOpFn(TCGv_i32, TCGv_i32);
typedef void NeonGenOneOpEnvFn(TCGv_i32, TCGv_ptr, TCGv_i32);
typedef void NeonGenTwoOpFn(TCGv_i32, TCGv_i32, TCGv_i32);
typedef void NeonGenTwoOpEnvFn(TCGv_i32, TCGv_ptr, TCGv_i32, TCGv_i32);
......@@ -372,9 +373,10 @@ typedef void NeonGenNarrowFn(TCGv_i32, TCGv_i64);
typedef void NeonGenNarrowEnvFn(TCGv_i32, TCGv_ptr, TCGv_i64);
typedef void NeonGenWidenFn(TCGv_i64, TCGv_i32);
typedef void NeonGenTwoOpWidenFn(TCGv_i64, TCGv_i32, TCGv_i32);
typedef void NeonGenTwoSingleOPFn(TCGv_i32, TCGv_i32, TCGv_i32, TCGv_ptr);
typedef void NeonGenTwoDoubleOPFn(TCGv_i64, TCGv_i64, TCGv_i64, TCGv_ptr);
typedef void NeonGenOneOpFn(TCGv_i64, TCGv_i64);
typedef void NeonGenOneSingleOpFn(TCGv_i32, TCGv_i32, TCGv_ptr);
typedef void NeonGenTwoSingleOpFn(TCGv_i32, TCGv_i32, TCGv_i32, TCGv_ptr);
typedef void NeonGenTwoDoubleOpFn(TCGv_i64, TCGv_i64, TCGv_i64, TCGv_ptr);
typedef void NeonGenOne64OpFn(TCGv_i64, TCGv_i64);
typedef void CryptoTwoOpFn(TCGv_ptr, TCGv_ptr);
typedef void CryptoThreeOpIntFn(TCGv_ptr, TCGv_ptr, TCGv_i32);
typedef void CryptoThreeOpFn(TCGv_ptr, TCGv_ptr, TCGv_ptr);
......
......@@ -159,16 +159,35 @@ static bool resp_get_feature(QDict *resp, const char *feature)
qobject_unref(_resp); \
})
#define assert_feature(qts, cpu_type, feature, expected_value) \
#define resp_assert_feature(resp, feature, expected_value) \
({ \
QDict *_resp, *_props; \
QDict *_props; \
\
_resp = do_query_no_props(qts, cpu_type); \
g_assert(_resp); \
g_assert(resp_has_props(_resp)); \
_props = resp_get_props(_resp); \
g_assert(qdict_get(_props, feature)); \
g_assert(qdict_get_bool(_props, feature) == (expected_value)); \
})
#define assert_feature(qts, cpu_type, feature, expected_value) \
({ \
QDict *_resp; \
\
_resp = do_query_no_props(qts, cpu_type); \
g_assert(_resp); \
resp_assert_feature(_resp, feature, expected_value); \
qobject_unref(_resp); \
})
#define assert_set_feature(qts, cpu_type, feature, value) \
({ \
const char *_fmt = (value) ? "{ %s: true }" : "{ %s: false }"; \
QDict *_resp; \
\
_resp = do_query(qts, cpu_type, _fmt, feature); \
g_assert(_resp); \
resp_assert_feature(_resp, feature, value); \
qobject_unref(_resp); \
})
......@@ -424,10 +443,14 @@ static void test_query_cpu_model_expansion(const void *data)
assert_error(qts, "host", "The CPU type 'host' requires KVM", NULL);
/* Test expected feature presence/absence for some cpu types */
assert_has_feature_enabled(qts, "max", "pmu");
assert_has_feature_enabled(qts, "cortex-a15", "pmu");
assert_has_not_feature(qts, "cortex-a15", "aarch64");
/* Enabling and disabling pmu should always work. */
assert_has_feature_enabled(qts, "max", "pmu");
assert_set_feature(qts, "max", "pmu", false);
assert_set_feature(qts, "max", "pmu", true);
assert_has_not_feature(qts, "max", "kvm-no-adjvtime");
if (g_str_equal(qtest_get_arch(), "aarch64")) {
......@@ -464,7 +487,10 @@ static void test_query_cpu_model_expansion_kvm(const void *data)
return;
}
/* Enabling and disabling kvm-no-adjvtime should always work. */
assert_has_feature_disabled(qts, "host", "kvm-no-adjvtime");
assert_set_feature(qts, "host", "kvm-no-adjvtime", true);
assert_set_feature(qts, "host", "kvm-no-adjvtime", false);
if (g_str_equal(qtest_get_arch(), "aarch64")) {
bool kvm_supports_sve;
......@@ -475,7 +501,11 @@ static void test_query_cpu_model_expansion_kvm(const void *data)
char *error;
assert_has_feature_enabled(qts, "host", "aarch64");
/* Enabling and disabling pmu should always work. */
assert_has_feature_enabled(qts, "host", "pmu");
assert_set_feature(qts, "host", "pmu", false);
assert_set_feature(qts, "host", "pmu", true);
assert_error(qts, "cortex-a15",
"We cannot guarantee the CPU type 'cortex-a15' works "
......
......@@ -57,6 +57,10 @@
#include <lwp.h>
#endif
#ifdef __APPLE__
#include <mach-o/dyld.h>
#endif
#include "qemu/mmap-alloc.h"
#ifdef CONFIG_DEBUG_STACK_USAGE
......@@ -375,6 +379,17 @@ void qemu_init_exec_dir(const char *argv0)
p = buf;
}
}
#elif defined(__APPLE__)
{
char fpath[PATH_MAX];
uint32_t len = sizeof(fpath);
if (_NSGetExecutablePath(fpath, &len) == 0) {
p = realpath(fpath, buf);
if (!p) {
return;
}
}
}
#endif
/* If we don't have any way of figuring out the actual executable
location then try argv[0]. */
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册