Add nuvoton sd module for NPCM7XX

Add gdb-xml for MVE
 More uses of tcg_constant_* in target/arm
 Fix parameter naming for default-bus-bypass-iommu
 Ignore cache operations to mmio in HVF
 -----BEGIN PGP SIGNATURE-----
 
 iQFRBAABCgA7FiEEekgeeIaLTbaoWgXAZN846K9+IV8FAmGBgjkdHHJpY2hhcmQu
 aGVuZGVyc29uQGxpbmFyby5vcmcACgkQZN846K9+IV8sAAgAsHaW2sHH/W4TzCwl
 DfqFar4u047Q+ZtQHjNehGHF9Bxp4NS4A0qL52vk0hVoqeWlyF1N29MOnewgVDqY
 q1x+uxJtG9xjTse7oEEshEEFF/7J8eB8dN4E78TFn/6IhvVhGiUeeRu29s44Ot6N
 E2KABcXfd+4gEdqhepLGEbi5n0TnA8ARmmeffZNWVEbsxQjHnMQQYmqGmllB3xV3
 qPpnp3avvD1015zMwrLVmlDO+tSRr/1bed7k3k26ebga2B/zitxcpXFNCDlgePx0
 LNT5QYvBDpE7HOruGQjf4iXPJHfYw5VMtopK7K++rY9KWiJgBVSjQUcB462sdCPk
 wNAp0g==
 =vlZ5
 -----END PGP SIGNATURE-----

Merge remote-tracking branch 'remotes/rth/tags/pull-arm-20211102-2' into staging

Add nuvoton sd module for NPCM7XX
Add gdb-xml for MVE
More uses of tcg_constant_* in target/arm
Fix parameter naming for default-bus-bypass-iommu
Ignore cache operations to mmio in HVF

# gpg: Signature made Tue 02 Nov 2021 02:23:53 PM EDT
# gpg:                using RSA key 7A481E78868B4DB6A85A05C064DF38E8AF7E215F
# gpg:                issuer "richard.henderson@linaro.org"
# gpg: Good signature from "Richard Henderson <richard.henderson@linaro.org>" [ultimate]

* remotes/rth/tags/pull-arm-20211102-2:
  hvf: arm: Ignore cache operations on MMIO
  hw/arm/virt: Rename default_bus_bypass_iommu
  target/arm: Use tcg_constant_i32() in gen_rev16()
  target/arm: Use tcg_constant_i64() in do_sat_addsub_64()
  target/arm: Use the constant variant of store_cpu_field() when possible
  target/arm: Introduce store_cpu_field_constant() helper
  target/arm: Use tcg_constant_i32() in op_smlad()
  target/arm: Advertise MVE to gdb when present
  tests/qtest/libqos: add SDHCI commands
  hw/arm: Attach MMC to quanta-gbs-bmc
  hw/arm: Add Nuvoton SD module to board
  hw/sd: add nuvoton MMC

Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
This commit is contained in:
Richard Henderson 2021-11-03 09:31:25 -04:00
commit cc23377516
20 changed files with 544 additions and 35 deletions

View File

@ -1,5 +1,5 @@
TARGET_ARCH=aarch64
TARGET_BASE_ARCH=arm
TARGET_SUPPORTS_MTTCG=y
TARGET_XML_FILES= gdb-xml/aarch64-core.xml gdb-xml/aarch64-fpu.xml gdb-xml/arm-core.xml gdb-xml/arm-vfp.xml gdb-xml/arm-vfp3.xml gdb-xml/arm-vfp-sysregs.xml gdb-xml/arm-neon.xml gdb-xml/arm-m-profile.xml
TARGET_XML_FILES= gdb-xml/aarch64-core.xml gdb-xml/aarch64-fpu.xml gdb-xml/arm-core.xml gdb-xml/arm-vfp.xml gdb-xml/arm-vfp3.xml gdb-xml/arm-vfp-sysregs.xml gdb-xml/arm-neon.xml gdb-xml/arm-m-profile.xml gdb-xml/arm-m-profile-mve.xml
TARGET_NEED_FDT=y

View File

@ -1,6 +1,6 @@
TARGET_ARCH=arm
TARGET_SYSTBL_ABI=common,oabi
TARGET_SYSTBL=syscall.tbl
TARGET_XML_FILES= gdb-xml/arm-core.xml gdb-xml/arm-vfp.xml gdb-xml/arm-vfp3.xml gdb-xml/arm-vfp-sysregs.xml gdb-xml/arm-neon.xml gdb-xml/arm-m-profile.xml
TARGET_XML_FILES= gdb-xml/arm-core.xml gdb-xml/arm-vfp.xml gdb-xml/arm-vfp3.xml gdb-xml/arm-vfp-sysregs.xml gdb-xml/arm-neon.xml gdb-xml/arm-m-profile.xml gdb-xml/arm-m-profile-mve.xml
TARGET_HAS_BFLT=y
CONFIG_ARM_COMPATIBLE_SEMIHOSTING=y

View File

@ -1,4 +1,4 @@
TARGET_ARCH=arm
TARGET_SUPPORTS_MTTCG=y
TARGET_XML_FILES= gdb-xml/arm-core.xml gdb-xml/arm-vfp.xml gdb-xml/arm-vfp3.xml gdb-xml/arm-vfp-sysregs.xml gdb-xml/arm-neon.xml gdb-xml/arm-m-profile.xml
TARGET_XML_FILES= gdb-xml/arm-core.xml gdb-xml/arm-vfp.xml gdb-xml/arm-vfp3.xml gdb-xml/arm-vfp-sysregs.xml gdb-xml/arm-neon.xml gdb-xml/arm-m-profile.xml gdb-xml/arm-m-profile-mve.xml
TARGET_NEED_FDT=y

View File

@ -2,6 +2,6 @@ TARGET_ARCH=arm
TARGET_SYSTBL_ABI=common,oabi
TARGET_SYSTBL=syscall.tbl
TARGET_WORDS_BIGENDIAN=y
TARGET_XML_FILES= gdb-xml/arm-core.xml gdb-xml/arm-vfp.xml gdb-xml/arm-vfp3.xml gdb-xml/arm-vfp-sysregs.xml gdb-xml/arm-neon.xml gdb-xml/arm-m-profile.xml
TARGET_XML_FILES= gdb-xml/arm-core.xml gdb-xml/arm-vfp.xml gdb-xml/arm-vfp3.xml gdb-xml/arm-vfp-sysregs.xml gdb-xml/arm-neon.xml gdb-xml/arm-m-profile.xml gdb-xml/arm-m-profile-mve.xml
TARGET_HAS_BFLT=y
CONFIG_ARM_COMPATIBLE_SEMIHOSTING=y

View File

@ -0,0 +1,19 @@
<?xml version="1.0"?>
<!-- Copyright (C) 2021 Free Software Foundation, Inc.
Copying and distribution of this file, with or without modification,
are permitted in any medium without royalty provided the copyright
notice and this notice are preserved. -->
<!DOCTYPE feature SYSTEM "gdb-target.dtd">
<feature name="org.gnu.gdb.arm.m-profile-mve">
<flags id="vpr_reg" size="4">
<!-- ARMv8.1-M and MVE: Unprivileged and privileged Access. -->
<field name="P0" start="0" end="15"/>
<!-- ARMv8.1-M: Privileged Access only. -->
<field name="MASK01" start="16" end="19"/>
<!-- ARMv8.1-M: Privileged Access only. -->
<field name="MASK23" start="20" end="23"/>
</flags>
<reg name="vpr" bitsize="32" type="vpr_reg"/>
</feature>

View File

@ -63,6 +63,8 @@
#define NPCM7XX_ROM_BA (0xffff0000)
#define NPCM7XX_ROM_SZ (64 * KiB)
/* SDHCI Modules */
#define NPCM7XX_MMC_BA (0xf0842000)
/* Clock configuration values to be fixed up when bypassing bootloader */
@ -83,6 +85,7 @@ enum NPCM7xxInterrupt {
NPCM7XX_UART3_IRQ,
NPCM7XX_EMC1RX_IRQ = 15,
NPCM7XX_EMC1TX_IRQ,
NPCM7XX_MMC_IRQ = 26,
NPCM7XX_TIMER0_IRQ = 32, /* Timer Module 0 */
NPCM7XX_TIMER1_IRQ,
NPCM7XX_TIMER2_IRQ,
@ -443,6 +446,8 @@ static void npcm7xx_init(Object *obj)
for (i = 0; i < ARRAY_SIZE(s->emc); i++) {
object_initialize_child(obj, "emc[*]", &s->emc[i], TYPE_NPCM7XX_EMC);
}
object_initialize_child(obj, "mmc", &s->mmc, TYPE_NPCM7XX_SDHCI);
}
static void npcm7xx_realize(DeviceState *dev, Error **errp)
@ -707,6 +712,12 @@ static void npcm7xx_realize(DeviceState *dev, Error **errp)
&error_abort);
memory_region_add_subregion(get_system_memory(), NPCM7XX_ROM_BA, &s->irom);
/* SDHCI */
sysbus_realize(SYS_BUS_DEVICE(&s->mmc), &error_abort);
sysbus_mmio_map(SYS_BUS_DEVICE(&s->mmc), 0, NPCM7XX_MMC_BA);
sysbus_connect_irq(SYS_BUS_DEVICE(&s->mmc), 0,
npcm7xx_irq(s, NPCM7XX_MMC_IRQ));
create_unimplemented_device("npcm7xx.shm", 0xc0001000, 4 * KiB);
create_unimplemented_device("npcm7xx.vdmx", 0xe0800000, 4 * KiB);
create_unimplemented_device("npcm7xx.pcierc", 0xe1000000, 64 * KiB);
@ -736,7 +747,6 @@ static void npcm7xx_realize(DeviceState *dev, Error **errp)
create_unimplemented_device("npcm7xx.usbd[8]", 0xf0838000, 4 * KiB);
create_unimplemented_device("npcm7xx.usbd[9]", 0xf0839000, 4 * KiB);
create_unimplemented_device("npcm7xx.sd", 0xf0840000, 8 * KiB);
create_unimplemented_device("npcm7xx.mmc", 0xf0842000, 8 * KiB);
create_unimplemented_device("npcm7xx.pcimbx", 0xf0848000, 512 * KiB);
create_unimplemented_device("npcm7xx.aes", 0xf0858000, 4 * KiB);
create_unimplemented_device("npcm7xx.des", 0xf0859000, 4 * KiB);

View File

@ -27,6 +27,9 @@
#include "qemu-common.h"
#include "qemu/datadir.h"
#include "qemu/units.h"
#include "sysemu/blockdev.h"
#include "sysemu/sysemu.h"
#include "sysemu/block-backend.h"
#define NPCM750_EVB_POWER_ON_STRAPS 0x00001ff7
#define QUANTA_GSJ_POWER_ON_STRAPS 0x00001fff
@ -81,6 +84,22 @@ static void npcm7xx_connect_dram(NPCM7xxState *soc, MemoryRegion *dram)
&error_abort);
}
static void sdhci_attach_drive(SDHCIState *sdhci)
{
DriveInfo *di = drive_get_next(IF_SD);
BlockBackend *blk = di ? blk_by_legacy_dinfo(di) : NULL;
BusState *bus = qdev_get_child_bus(DEVICE(sdhci), "sd-bus");
if (bus == NULL) {
error_report("No SD bus found in SOC object");
exit(1);
}
DeviceState *carddev = qdev_new(TYPE_SD_CARD);
qdev_prop_set_drive_err(carddev, "drive", blk, &error_fatal);
qdev_realize_and_unref(carddev, bus, &error_fatal);
}
static NPCM7xxState *npcm7xx_create_soc(MachineState *machine,
uint32_t hw_straps)
{
@ -355,6 +374,7 @@ static void quanta_gbs_init(MachineState *machine)
drive_get(IF_MTD, 0, 0));
quanta_gbs_i2c_init(soc);
sdhci_attach_drive(&soc->mmc.sdhci);
npcm7xx_load_kernel(machine, soc);
}

View File

@ -2737,10 +2737,10 @@ static void virt_machine_class_init(ObjectClass *oc, void *data)
"Set the IOMMU type. "
"Valid values are none and smmuv3");
object_class_property_add_bool(oc, "default_bus_bypass_iommu",
object_class_property_add_bool(oc, "default-bus-bypass-iommu",
virt_get_default_bus_bypass_iommu,
virt_set_default_bus_bypass_iommu);
object_class_property_set_description(oc, "default_bus_bypass_iommu",
object_class_property_set_description(oc, "default-bus-bypass-iommu",
"Set on/off to enable/disable "
"bypass_iommu for default root bus");

View File

@ -9,4 +9,5 @@ softmmu_ss.add(when: 'CONFIG_PXA2XX', if_true: files('pxa2xx_mmci.c'))
softmmu_ss.add(when: 'CONFIG_RASPI', if_true: files('bcm2835_sdhost.c'))
softmmu_ss.add(when: 'CONFIG_ASPEED_SOC', if_true: files('aspeed_sdhci.c'))
softmmu_ss.add(when: 'CONFIG_ALLWINNER_H3', if_true: files('allwinner-sdhost.c'))
softmmu_ss.add(when: 'CONFIG_NPCM7XX', if_true: files('npcm7xx_sdhci.c'))
softmmu_ss.add(when: 'CONFIG_CADENCE_SDHCI', if_true: files('cadence_sdhci.c'))

182
hw/sd/npcm7xx_sdhci.c Normal file
View File

@ -0,0 +1,182 @@
/*
* NPCM7xx SD-3.0 / eMMC-4.51 Host Controller
*
* Copyright (c) 2021 Google LLC
*
* 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 of the License, or
* (at your option) any later version.
*
* 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.
*/
#include "qemu/osdep.h"
#include "hw/sd/npcm7xx_sdhci.h"
#include "migration/vmstate.h"
#include "sdhci-internal.h"
#include "qemu/log.h"
static uint64_t npcm7xx_sdhci_read(void *opaque, hwaddr addr, unsigned int size)
{
NPCM7xxSDHCIState *s = opaque;
uint64_t val = 0;
switch (addr) {
case NPCM7XX_PRSTVALS_0:
case NPCM7XX_PRSTVALS_1:
case NPCM7XX_PRSTVALS_2:
case NPCM7XX_PRSTVALS_3:
case NPCM7XX_PRSTVALS_4:
case NPCM7XX_PRSTVALS_5:
val = s->regs.prstvals[(addr - NPCM7XX_PRSTVALS_0) / 2];
break;
case NPCM7XX_BOOTTOCTRL:
val = s->regs.boottoctrl;
break;
default:
qemu_log_mask(LOG_GUEST_ERROR, "SDHCI read of nonexistent reg: 0x%02"
HWADDR_PRIx, addr);
break;
}
return val;
}
static void npcm7xx_sdhci_write(void *opaque, hwaddr addr, uint64_t val,
unsigned int size)
{
NPCM7xxSDHCIState *s = opaque;
switch (addr) {
case NPCM7XX_BOOTTOCTRL:
s->regs.boottoctrl = val;
break;
default:
qemu_log_mask(LOG_GUEST_ERROR, "SDHCI write of nonexistent reg: 0x%02"
HWADDR_PRIx, addr);
break;
}
}
static bool npcm7xx_sdhci_check_mem_op(void *opaque, hwaddr addr,
unsigned size, bool is_write,
MemTxAttrs attrs)
{
switch (addr) {
case NPCM7XX_PRSTVALS_0:
case NPCM7XX_PRSTVALS_1:
case NPCM7XX_PRSTVALS_2:
case NPCM7XX_PRSTVALS_3:
case NPCM7XX_PRSTVALS_4:
case NPCM7XX_PRSTVALS_5:
/* RO Word */
return !is_write && size == 2;
case NPCM7XX_BOOTTOCTRL:
/* R/W Dword */
return size == 4;
default:
return false;
}
}
static const MemoryRegionOps npcm7xx_sdhci_ops = {
.read = npcm7xx_sdhci_read,
.write = npcm7xx_sdhci_write,
.endianness = DEVICE_NATIVE_ENDIAN,
.valid = {
.min_access_size = 1,
.max_access_size = 4,
.unaligned = false,
.accepts = npcm7xx_sdhci_check_mem_op,
},
};
static void npcm7xx_sdhci_realize(DeviceState *dev, Error **errp)
{
NPCM7xxSDHCIState *s = NPCM7XX_SDHCI(dev);
SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
SysBusDevice *sbd_sdhci = SYS_BUS_DEVICE(&s->sdhci);
memory_region_init(&s->container, OBJECT(s),
"npcm7xx.sdhci-container", 0x1000);
sysbus_init_mmio(sbd, &s->container);
memory_region_init_io(&s->iomem, OBJECT(s), &npcm7xx_sdhci_ops, s,
TYPE_NPCM7XX_SDHCI, NPCM7XX_SDHCI_REGSIZE);
memory_region_add_subregion_overlap(&s->container, NPCM7XX_PRSTVALS,
&s->iomem, 1);
sysbus_realize(sbd_sdhci, errp);
memory_region_add_subregion(&s->container, 0,
sysbus_mmio_get_region(sbd_sdhci, 0));
/* propagate irq and "sd-bus" from generic-sdhci */
sysbus_pass_irq(sbd, sbd_sdhci);
s->bus = qdev_get_child_bus(DEVICE(sbd_sdhci), "sd-bus");
/* Set the read only preset values. */
memset(s->regs.prstvals, 0, sizeof(s->regs.prstvals));
s->regs.prstvals[0] = NPCM7XX_PRSTVALS_0_RESET;
s->regs.prstvals[1] = NPCM7XX_PRSTVALS_1_RESET;
s->regs.prstvals[3] = NPCM7XX_PRSTVALS_3_RESET;
}
static void npcm7xx_sdhci_reset(DeviceState *dev)
{
NPCM7xxSDHCIState *s = NPCM7XX_SDHCI(dev);
device_cold_reset(DEVICE(&s->sdhci));
s->regs.boottoctrl = 0;
s->sdhci.prnsts = NPCM7XX_PRSNTS_RESET;
s->sdhci.blkgap = NPCM7XX_BLKGAP_RESET;
s->sdhci.capareg = NPCM7XX_CAPAB_RESET;
s->sdhci.maxcurr = NPCM7XX_MAXCURR_RESET;
s->sdhci.version = NPCM7XX_HCVER_RESET;
}
static const VMStateDescription vmstate_npcm7xx_sdhci = {
.name = TYPE_NPCM7XX_SDHCI,
.version_id = 0,
.fields = (VMStateField[]) {
VMSTATE_UINT32(regs.boottoctrl, NPCM7xxSDHCIState),
VMSTATE_END_OF_LIST(),
},
};
static void npcm7xx_sdhci_class_init(ObjectClass *classp, void *data)
{
DeviceClass *dc = DEVICE_CLASS(classp);
dc->desc = "NPCM7xx SD/eMMC Host Controller";
dc->realize = npcm7xx_sdhci_realize;
dc->reset = npcm7xx_sdhci_reset;
dc->vmsd = &vmstate_npcm7xx_sdhci;
}
static void npcm7xx_sdhci_instance_init(Object *obj)
{
NPCM7xxSDHCIState *s = NPCM7XX_SDHCI(obj);
object_initialize_child(OBJECT(s), "generic-sdhci", &s->sdhci,
TYPE_SYSBUS_SDHCI);
}
static TypeInfo npcm7xx_sdhci_info = {
.name = TYPE_NPCM7XX_SDHCI,
.parent = TYPE_SYS_BUS_DEVICE,
.instance_size = sizeof(NPCM7xxSDHCIState),
.instance_init = npcm7xx_sdhci_instance_init,
.class_init = npcm7xx_sdhci_class_init,
};
static void npcm7xx_sdhci_register_types(void)
{
type_register_static(&npcm7xx_sdhci_info);
}
type_init(npcm7xx_sdhci_register_types)

View File

@ -35,6 +35,7 @@
#include "hw/usb/hcd-ehci.h"
#include "hw/usb/hcd-ohci.h"
#include "target/arm/cpu.h"
#include "hw/sd/npcm7xx_sdhci.h"
#define NPCM7XX_MAX_NUM_CPUS (2)
@ -103,6 +104,7 @@ typedef struct NPCM7xxState {
OHCISysBusState ohci;
NPCM7xxFIUState fiu[2];
NPCM7xxEMCState emc[2];
NPCM7xxSDHCIState mmc;
} NPCM7xxState;
#define TYPE_NPCM7XX "npcm7xx"

View File

@ -0,0 +1,65 @@
/*
* NPCM7xx SD-3.0 / eMMC-4.51 Host Controller
*
* Copyright (c) 2021 Google LLC
*
* 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 of the License, or
* (at your option) any later version.
*
* 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.
*/
#ifndef NPCM7XX_SDHCI_H
#define NPCM7XX_SDHCI_H
#include "hw/sd/sdhci.h"
#include "qom/object.h"
#define TYPE_NPCM7XX_SDHCI "npcm7xx.sdhci"
#define NPCM7XX_PRSTVALS_SIZE 6
#define NPCM7XX_PRSTVALS 0x60
#define NPCM7XX_PRSTVALS_0 0x0
#define NPCM7XX_PRSTVALS_1 0x2
#define NPCM7XX_PRSTVALS_2 0x4
#define NPCM7XX_PRSTVALS_3 0x6
#define NPCM7XX_PRSTVALS_4 0x8
#define NPCM7XX_PRSTVALS_5 0xA
#define NPCM7XX_BOOTTOCTRL 0x10
#define NPCM7XX_SDHCI_REGSIZE 0x20
#define NPCM7XX_PRSNTS_RESET 0x04A00000
#define NPCM7XX_BLKGAP_RESET 0x80
#define NPCM7XX_CAPAB_RESET 0x0100200161EE0399
#define NPCM7XX_MAXCURR_RESET 0x0000000000000005
#define NPCM7XX_HCVER_RESET 0x1002
#define NPCM7XX_PRSTVALS_0_RESET 0x0040
#define NPCM7XX_PRSTVALS_1_RESET 0x0001
#define NPCM7XX_PRSTVALS_3_RESET 0x0001
OBJECT_DECLARE_SIMPLE_TYPE(NPCM7xxSDHCIState, NPCM7XX_SDHCI)
typedef struct NPCM7xxRegs {
/* Preset Values Register Field, read-only */
uint16_t prstvals[NPCM7XX_PRSTVALS_SIZE];
/* Boot Timeout Control Register, read-write */
uint32_t boottoctrl;
} NPCM7xxRegisters;
typedef struct NPCM7xxSDHCIState {
SysBusDevice parent;
MemoryRegion container;
MemoryRegion iomem;
BusState *bus;
NPCM7xxRegisters regs;
SDHCIState sdhci;
} NPCM7xxSDHCIState;
#endif /* NPCM7XX_SDHCI_H */

View File

@ -199,6 +199,27 @@ static int vfp_gdb_set_sysreg(CPUARMState *env, uint8_t *buf, int reg)
return 0;
}
static int mve_gdb_get_reg(CPUARMState *env, GByteArray *buf, int reg)
{
switch (reg) {
case 0:
return gdb_get_reg32(buf, env->v7m.vpr);
default:
return 0;
}
}
static int mve_gdb_set_reg(CPUARMState *env, uint8_t *buf, int reg)
{
switch (reg) {
case 0:
env->v7m.vpr = ldl_p(buf);
return 4;
default:
return 0;
}
}
/**
* arm_get/set_gdb_*: get/set a gdb register
* @env: the CPU state
@ -468,6 +489,10 @@ void arm_cpu_register_gdb_regs_for_features(ARMCPU *cpu)
2, "arm-vfp-sysregs.xml", 0);
}
}
if (cpu_isar_feature(aa32_mve, cpu)) {
gdb_register_coprocessor(cs, mve_gdb_get_reg, mve_gdb_set_reg,
1, "arm-m-profile-mve.xml", 0);
}
gdb_register_coprocessor(cs, arm_gdb_get_sysreg, arm_gdb_set_sysreg,
arm_gen_dynamic_sysreg_xml(cs, cs->gdb_num_regs),
"system-registers.xml", 0);

View File

@ -1150,12 +1150,19 @@ int hvf_vcpu_exec(CPUState *cpu)
uint32_t sas = (syndrome >> 22) & 3;
uint32_t len = 1 << sas;
uint32_t srt = (syndrome >> 16) & 0x1f;
uint32_t cm = (syndrome >> 8) & 0x1;
uint64_t val = 0;
trace_hvf_data_abort(env->pc, hvf_exit->exception.virtual_address,
hvf_exit->exception.physical_address, isv,
iswrite, s1ptw, len, srt);
if (cm) {
/* We don't cache MMIO regions */
advance_pc = true;
break;
}
assert(isv);
if (iswrite) {

View File

@ -70,6 +70,9 @@ static inline void store_cpu_offset(TCGv_i32 var, int offset)
#define store_cpu_field(var, name) \
store_cpu_offset(var, offsetof(CPUARMState, name))
#define store_cpu_field_constant(val, name) \
tcg_gen_st_i32(tcg_constant_i32(val), cpu_env, offsetof(CPUARMState, name))
/* Create a new temporary and set it to the value of a CPU register. */
static inline TCGv_i32 load_reg(DisasContext *s, int reg)
{

View File

@ -1943,20 +1943,20 @@ static void do_sat_addsub_32(TCGv_i64 reg, TCGv_i64 val, bool u, bool d)
static void do_sat_addsub_64(TCGv_i64 reg, TCGv_i64 val, bool u, bool d)
{
TCGv_i64 t0 = tcg_temp_new_i64();
TCGv_i64 t1 = tcg_temp_new_i64();
TCGv_i64 t2;
if (u) {
if (d) {
tcg_gen_sub_i64(t0, reg, val);
tcg_gen_movi_i64(t1, 0);
tcg_gen_movcond_i64(TCG_COND_LTU, reg, reg, val, t1, t0);
t2 = tcg_constant_i64(0);
tcg_gen_movcond_i64(TCG_COND_LTU, reg, reg, val, t2, t0);
} else {
tcg_gen_add_i64(t0, reg, val);
tcg_gen_movi_i64(t1, -1);
tcg_gen_movcond_i64(TCG_COND_LTU, reg, t0, reg, t1, t0);
t2 = tcg_constant_i64(-1);
tcg_gen_movcond_i64(TCG_COND_LTU, reg, t0, reg, t2, t0);
}
} else {
TCGv_i64 t1 = tcg_temp_new_i64();
if (d) {
/* Detect signed overflow for subtraction. */
tcg_gen_xor_i64(t0, reg, val);
@ -1966,7 +1966,7 @@ static void do_sat_addsub_64(TCGv_i64 reg, TCGv_i64 val, bool u, bool d)
/* Bound the result. */
tcg_gen_movi_i64(reg, INT64_MIN);
t2 = tcg_const_i64(0);
t2 = tcg_constant_i64(0);
tcg_gen_movcond_i64(TCG_COND_LT, reg, t0, t2, reg, t1);
} else {
/* Detect signed overflow for addition. */
@ -1977,13 +1977,12 @@ static void do_sat_addsub_64(TCGv_i64 reg, TCGv_i64 val, bool u, bool d)
/* Bound the result. */
tcg_gen_movi_i64(t1, INT64_MAX);
t2 = tcg_const_i64(0);
t2 = tcg_constant_i64(0);
tcg_gen_movcond_i64(TCG_COND_LT, reg, t0, t2, t1, reg);
}
tcg_temp_free_i64(t2);
tcg_temp_free_i64(t1);
}
tcg_temp_free_i64(t0);
tcg_temp_free_i64(t1);
}
/* Similarly with a vector and a scalar operand. */

View File

@ -364,8 +364,7 @@ void clear_eci_state(DisasContext *s)
* multiple insn executes.
*/
if (s->eci) {
TCGv_i32 tmp = tcg_const_i32(0);
store_cpu_field(tmp, condexec_bits);
store_cpu_field_constant(0, condexec_bits);
s->eci = 0;
}
}
@ -389,13 +388,12 @@ static void gen_smul_dual(TCGv_i32 a, TCGv_i32 b)
void gen_rev16(TCGv_i32 dest, TCGv_i32 var)
{
TCGv_i32 tmp = tcg_temp_new_i32();
TCGv_i32 mask = tcg_const_i32(0x00ff00ff);
TCGv_i32 mask = tcg_constant_i32(0x00ff00ff);
tcg_gen_shri_i32(tmp, var, 8);
tcg_gen_and_i32(tmp, tmp, mask);
tcg_gen_and_i32(var, var, mask);
tcg_gen_shli_i32(var, var, 8);
tcg_gen_or_i32(dest, var, tmp);
tcg_temp_free_i32(mask);
tcg_temp_free_i32(tmp);
}
@ -740,9 +738,8 @@ void gen_set_condexec(DisasContext *s)
{
if (s->condexec_mask) {
uint32_t val = (s->condexec_cond << 4) | (s->condexec_mask >> 1);
TCGv_i32 tmp = tcg_temp_new_i32();
tcg_gen_movi_i32(tmp, val);
store_cpu_field(tmp, condexec_bits);
store_cpu_field_constant(val, condexec_bits);
}
}
@ -7849,10 +7846,9 @@ static bool op_smlad(DisasContext *s, arg_rrrr *a, bool m_swap, bool sub)
t3 = tcg_temp_new_i32();
tcg_gen_sari_i32(t3, t1, 31);
qf = load_cpu_field(QF);
one = tcg_const_i32(1);
one = tcg_constant_i32(1);
tcg_gen_movcond_i32(TCG_COND_NE, qf, t2, t3, one, qf);
store_cpu_field(qf, QF);
tcg_temp_free_i32(one);
tcg_temp_free_i32(t3);
tcg_temp_free_i32(t2);
}
@ -8363,8 +8359,6 @@ static bool trans_BL(DisasContext *s, arg_i *a)
static bool trans_BLX_i(DisasContext *s, arg_BLX_i *a)
{
TCGv_i32 tmp;
/*
* BLX <imm> would be useless on M-profile; the encoding space
* is used for other insns from v8.1M onward, and UNDEFs before that.
@ -8378,8 +8372,7 @@ static bool trans_BLX_i(DisasContext *s, arg_BLX_i *a)
return false;
}
tcg_gen_movi_i32(cpu_R[14], s->base.pc_next | s->thumb);
tmp = tcg_const_i32(!s->thumb);
store_cpu_field(tmp, thumb);
store_cpu_field_constant(!s->thumb, thumb);
gen_jmp(s, (read_pc(s) & ~3) + a->imm);
return true;
}
@ -8678,7 +8671,6 @@ static bool trans_LCTP(DisasContext *s, arg_LCTP *a)
* doesn't cache branch information, all we need to do is reset
* FPSCR.LTPSIZE to 4.
*/
TCGv_i32 ltpsize;
if (!dc_isar_feature(aa32_lob, s) ||
!dc_isar_feature(aa32_mve, s)) {
@ -8689,8 +8681,7 @@ static bool trans_LCTP(DisasContext *s, arg_LCTP *a)
return true;
}
ltpsize = tcg_const_i32(4);
store_cpu_field(ltpsize, v7m.ltpsize);
store_cpu_field_constant(4, v7m.ltpsize);
return true;
}
@ -9488,9 +9479,7 @@ static void arm_tr_tb_start(DisasContextBase *dcbase, CPUState *cpu)
/* Reset the conditional execution bits immediately. This avoids
complications trying to do it at the end of the block. */
if (dc->condexec_mask || dc->condexec_cond) {
TCGv_i32 tmp = tcg_temp_new_i32();
tcg_gen_movi_i32(tmp, 0);
store_cpu_field(tmp, condexec_bits);
store_cpu_field_constant(0, condexec_bits);
}
}

View File

@ -5,6 +5,7 @@ libqos_srcs = files('../libqtest.c',
'fw_cfg.c',
'malloc.c',
'libqos.c',
'sdhci-cmd.c',
# spapr
'malloc-spapr.c',

View File

@ -0,0 +1,116 @@
/*
* MMC Host Controller Commands
*
* Copyright (c) 2021 Google LLC
*
* 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 of the License, or
* (at your option) any later version.
*
* 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.
*/
#include "qemu/osdep.h"
#include "sdhci-cmd.h"
#include "libqtest.h"
static ssize_t read_fifo(QTestState *qts, uint64_t reg, char *msg, size_t count)
{
uint32_t mask = 0xff;
size_t index = 0;
uint32_t msg_frag;
int size;
while (index < count) {
size = count - index;
if (size > 4) {
size = 4;
}
msg_frag = qtest_readl(qts, reg);
while (size > 0) {
msg[index] = msg_frag & mask;
if (msg[index++] == 0) {
return index;
}
msg_frag >>= 8;
--size;
}
}
return index;
}
static void write_fifo(QTestState *qts, uint64_t reg, const char *msg,
size_t count)
{
size_t index = 0;
uint32_t msg_frag;
int size;
int frag_i;
while (index < count) {
size = count - index;
if (size > 4) {
size = 4;
}
msg_frag = 0;
frag_i = 0;
while (frag_i < size) {
msg_frag |= ((uint32_t)msg[index++]) << (frag_i * 8);
++frag_i;
}
qtest_writel(qts, reg, msg_frag);
}
}
static void fill_block(QTestState *qts, uint64_t reg, int count)
{
while (--count >= 0) {
qtest_writel(qts, reg, 0);
}
}
void sdhci_cmd_regs(QTestState *qts, uint64_t base_addr, uint16_t blksize,
uint16_t blkcnt, uint32_t argument, uint16_t trnmod,
uint16_t cmdreg)
{
qtest_writew(qts, base_addr + SDHC_BLKSIZE, blksize);
qtest_writew(qts, base_addr + SDHC_BLKCNT, blkcnt);
qtest_writel(qts, base_addr + SDHC_ARGUMENT, argument);
qtest_writew(qts, base_addr + SDHC_TRNMOD, trnmod);
qtest_writew(qts, base_addr + SDHC_CMDREG, cmdreg);
}
ssize_t sdhci_read_cmd(QTestState *qts, uint64_t base_addr, char *msg,
size_t count)
{
sdhci_cmd_regs(qts, base_addr, count, 1, 0,
SDHC_TRNS_MULTI | SDHC_TRNS_READ | SDHC_TRNS_BLK_CNT_EN,
SDHC_READ_MULTIPLE_BLOCK | SDHC_CMD_DATA_PRESENT);
/* read sd fifo_buffer */
ssize_t bytes_read = read_fifo(qts, base_addr + SDHC_BDATA, msg, count);
sdhci_cmd_regs(qts, base_addr, 0, 0, 0,
SDHC_TRNS_MULTI | SDHC_TRNS_READ | SDHC_TRNS_BLK_CNT_EN,
SDHC_STOP_TRANSMISSION);
return bytes_read;
}
void sdhci_write_cmd(QTestState *qts, uint64_t base_addr, const char *msg,
size_t count, size_t blksize)
{
sdhci_cmd_regs(qts, base_addr, blksize, 1, 0,
SDHC_TRNS_MULTI | SDHC_TRNS_WRITE | SDHC_TRNS_BLK_CNT_EN,
SDHC_WRITE_MULTIPLE_BLOCK | SDHC_CMD_DATA_PRESENT);
/* write to sd fifo_buffer */
write_fifo(qts, base_addr + SDHC_BDATA, msg, count);
fill_block(qts, base_addr + SDHC_BDATA, (blksize - count) / 4);
sdhci_cmd_regs(qts, base_addr, 0, 0, 0,
SDHC_TRNS_MULTI | SDHC_TRNS_WRITE | SDHC_TRNS_BLK_CNT_EN,
SDHC_STOP_TRANSMISSION);
}

View File

@ -0,0 +1,70 @@
/*
* MMC Host Controller Commands
*
* Copyright (c) 2021 Google LLC
*
* 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 of the License, or
* (at your option) any later version.
*
* 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.
*/
#include "libqtest.h"
/* more details at hw/sd/sdhci-internal.h */
#define SDHC_BLKSIZE 0x04
#define SDHC_BLKCNT 0x06
#define SDHC_ARGUMENT 0x08
#define SDHC_TRNMOD 0x0C
#define SDHC_CMDREG 0x0E
#define SDHC_BDATA 0x20
#define SDHC_PRNSTS 0x24
#define SDHC_BLKGAP 0x2A
#define SDHC_CLKCON 0x2C
#define SDHC_SWRST 0x2F
#define SDHC_CAPAB 0x40
#define SDHC_MAXCURR 0x48
#define SDHC_HCVER 0xFE
/* TRNSMOD Reg */
#define SDHC_TRNS_BLK_CNT_EN 0x0002
#define SDHC_TRNS_READ 0x0010
#define SDHC_TRNS_WRITE 0x0000
#define SDHC_TRNS_MULTI 0x0020
/* CMD Reg */
#define SDHC_CMD_DATA_PRESENT (1 << 5)
#define SDHC_ALL_SEND_CID (2 << 8)
#define SDHC_SEND_RELATIVE_ADDR (3 << 8)
#define SDHC_SELECT_DESELECT_CARD (7 << 8)
#define SDHC_SEND_CSD (9 << 8)
#define SDHC_STOP_TRANSMISSION (12 << 8)
#define SDHC_READ_MULTIPLE_BLOCK (18 << 8)
#define SDHC_WRITE_MULTIPLE_BLOCK (25 << 8)
#define SDHC_APP_CMD (55 << 8)
/* SWRST Reg */
#define SDHC_RESET_ALL 0x01
/* CLKCTRL Reg */
#define SDHC_CLOCK_INT_EN 0x0001
#define SDHC_CLOCK_INT_STABLE 0x0002
#define SDHC_CLOCK_SDCLK_EN (1 << 2)
/* Set registers needed to send commands to SD */
void sdhci_cmd_regs(QTestState *qts, uint64_t base_addr, uint16_t blksize,
uint16_t blkcnt, uint32_t argument, uint16_t trnmod,
uint16_t cmdreg);
/* Read at most 1 block of SD using non-DMA */
ssize_t sdhci_read_cmd(QTestState *qts, uint64_t base_addr, char *msg,
size_t count);
/* Write at most 1 block of SD using non-DMA */
void sdhci_write_cmd(QTestState *qts, uint64_t base_addr, const char *msg,
size_t count, size_t blksize);