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

target-arm queue:
 * Fix validation of 32-bit address spaces for aa32 (fixes an assert introduced in ba97be9f4a)
 * v8m: Ensure IDAU is respected if SAU is disabled
 * gdbstub: fix gdb_get_cpu(s, pid, tid) when pid and/or tid are 0
 * exec.c: Use correct attrs in cpu_memory_rw_debug()
 * accel/tcg/user-exec: Don't parse aarch64 insns to test for read vs write
 * target/arm: Don't clear supported PMU events when initializing PMCEID1
 * memory: add memory_region_flush_rom_device()
 * microbit: Add stub NRF51 TWI magnetometer/accelerometer detection
 * tests/microbit-test: extend testing of microbit devices
 * checkpatch: Don't emit spurious warnings about block comments
 * aspeed/smc: misc bug fixes
 * xlnx-zynqmp: Don't create rpu-cluster if there are no RPUs
 * xlnx-zynqmp: Realize cluster after putting RPUs in it
 * accel/tcg: Add cluster number to TCG TB hash so differently configured
   CPUs don't pick up cached TBs for the wrong kind of CPU

# gpg: Signature made Tue 29 Jan 2019 11:59:10 GMT
# 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-20190129: (23 commits)
  gdbstub: Simplify gdb_get_cpu_pid() to use cpu->cluster_index
  accel/tcg: Add cluster number to TCG TB hash
  qom/cpu: Add cluster_index to CPUState
  hw/arm/xlnx-zynqmp: Realize cluster after putting RPUs in it
  aspeed/smc: snoop SPI transfers to fake dummy cycles
  aspeed/smc: Add dummy data register
  aspeed/smc: define registers for all possible CS
  aspeed/smc: fix default read value
  xlnx-zynqmp: Don't create rpu-cluster if there are no RPUs
  checkpatch: Don't emit spurious warnings about block comments
  tests/microbit-test: Check nRF51 UART functionality
  tests/microbit-test: Make test independent of global_qtest
  tests/libqtest: Introduce qtest_init_with_serial()
  memory: add memory_region_flush_rom_device()
  target/arm: Don't clear supported PMU events when initializing PMCEID1
  MAINTAINERS: update microbit ARM board files
  accel/tcg/user-exec: Don't parse aarch64 insns to test for read vs write
  exec.c: Use correct attrs in cpu_memory_rw_debug()
  tests/microbit-test: add TWI stub device test
  arm: Stub out NRF51 TWI magnetometer/accelerometer detection
  ...

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
Peter Maydell
2019-01-29 12:00:19 +00:00
28 changed files with 874 additions and 243 deletions
+5 -3
View File
@@ -829,9 +829,11 @@ M: Joel Stanley <joel@jms.id.au>
M: Peter Maydell <peter.maydell@linaro.org>
L: qemu-arm@nongnu.org
S: Maintained
F: hw/arm/nrf51_soc.c
F: hw/arm/microbit.c
F: include/hw/arm/nrf51_soc.h
F: hw/*/nrf51*.c
F: hw/*/microbit*.c
F: include/hw/*/nrf51*.h
F: include/hw/*/microbit*.h
F: tests/microbit-test.c
CRIS Machines
-------------
+3
View File
@@ -325,6 +325,9 @@ TranslationBlock *tb_htable_lookup(CPUState *cpu, target_ulong pc,
struct tb_desc desc;
uint32_t h;
cf_mask &= ~CF_CLUSTER_MASK;
cf_mask |= cpu->cluster_index << CF_CLUSTER_SHIFT;
desc.env = (CPUArchState *)cpu->env_ptr;
desc.cs_base = cs_base;
desc.flags = flags;
+3
View File
@@ -1688,6 +1688,9 @@ TranslationBlock *tb_gen_code(CPUState *cpu,
cflags |= CF_NOCACHE | 1;
}
cflags &= ~CF_CLUSTER_MASK;
cflags |= cpu->cluster_index << CF_CLUSTER_SHIFT;
buffer_overflow:
tb = tb_alloc(pc);
if (unlikely(!tb)) {
+52 -14
View File
@@ -479,28 +479,66 @@ int cpu_signal_handler(int host_signum, void *pinfo,
#elif defined(__aarch64__)
#ifndef ESR_MAGIC
/* Pre-3.16 kernel headers don't have these, so provide fallback definitions */
#define ESR_MAGIC 0x45535201
struct esr_context {
struct _aarch64_ctx head;
uint64_t esr;
};
#endif
static inline struct _aarch64_ctx *first_ctx(ucontext_t *uc)
{
return (struct _aarch64_ctx *)&uc->uc_mcontext.__reserved;
}
static inline struct _aarch64_ctx *next_ctx(struct _aarch64_ctx *hdr)
{
return (struct _aarch64_ctx *)((char *)hdr + hdr->size);
}
int cpu_signal_handler(int host_signum, void *pinfo, void *puc)
{
siginfo_t *info = pinfo;
ucontext_t *uc = puc;
uintptr_t pc = uc->uc_mcontext.pc;
uint32_t insn = *(uint32_t *)pc;
bool is_write;
struct _aarch64_ctx *hdr;
struct esr_context const *esrctx = NULL;
/* XXX: need kernel patch to get write flag faster. */
is_write = ( (insn & 0xbfff0000) == 0x0c000000 /* C3.3.1 */
|| (insn & 0xbfe00000) == 0x0c800000 /* C3.3.2 */
|| (insn & 0xbfdf0000) == 0x0d000000 /* C3.3.3 */
|| (insn & 0xbfc00000) == 0x0d800000 /* C3.3.4 */
|| (insn & 0x3f400000) == 0x08000000 /* C3.3.6 */
|| (insn & 0x3bc00000) == 0x39000000 /* C3.3.13 */
|| (insn & 0x3fc00000) == 0x3d800000 /* ... 128bit */
/* Ingore bits 10, 11 & 21, controlling indexing. */
|| (insn & 0x3bc00000) == 0x38000000 /* C3.3.8-12 */
|| (insn & 0x3fe00000) == 0x3c800000 /* ... 128bit */
/* Ignore bits 23 & 24, controlling indexing. */
|| (insn & 0x3a400000) == 0x28000000); /* C3.3.7,14-16 */
/* Find the esr_context, which has the WnR bit in it */
for (hdr = first_ctx(uc); hdr->magic; hdr = next_ctx(hdr)) {
if (hdr->magic == ESR_MAGIC) {
esrctx = (struct esr_context const *)hdr;
break;
}
}
if (esrctx) {
/* For data aborts ESR.EC is 0b10010x: then bit 6 is the WnR bit */
uint64_t esr = esrctx->esr;
is_write = extract32(esr, 27, 5) == 0x12 && extract32(esr, 6, 1) == 1;
} else {
/*
* Fall back to parsing instructions; will only be needed
* for really ancient (pre-3.16) kernels.
*/
uint32_t insn = *(uint32_t *)pc;
is_write = ((insn & 0xbfff0000) == 0x0c000000 /* C3.3.1 */
|| (insn & 0xbfe00000) == 0x0c800000 /* C3.3.2 */
|| (insn & 0xbfdf0000) == 0x0d000000 /* C3.3.3 */
|| (insn & 0xbfc00000) == 0x0d800000 /* C3.3.4 */
|| (insn & 0x3f400000) == 0x08000000 /* C3.3.6 */
|| (insn & 0x3bc00000) == 0x39000000 /* C3.3.13 */
|| (insn & 0x3fc00000) == 0x3d800000 /* ... 128bit */
/* Ignore bits 10, 11 & 21, controlling indexing. */
|| (insn & 0x3bc00000) == 0x38000000 /* C3.3.8-12 */
|| (insn & 0x3fe00000) == 0x3c800000 /* ... 128bit */
/* Ignore bits 23 & 24, controlling indexing. */
|| (insn & 0x3a400000) == 0x28000000); /* C3.3.7,14-16 */
}
return handle_cpu_signal(pc, info, is_write, &uc->uc_sigmask);
}
+15 -4
View File
@@ -3162,6 +3162,19 @@ static void invalidate_and_set_dirty(MemoryRegion *mr, hwaddr addr,
cpu_physical_memory_set_dirty_range(addr, length, dirty_log_mask);
}
void memory_region_flush_rom_device(MemoryRegion *mr, hwaddr addr, hwaddr size)
{
/*
* In principle this function would work on other memory region types too,
* but the ROM device use case is the only one where this operation is
* necessary. Other memory regions should use the
* address_space_read/write() APIs.
*/
assert(memory_region_is_romd(mr));
invalidate_and_set_dirty(mr, addr, size);
}
static int memory_access_size(MemoryRegion *mr, unsigned l, hwaddr addr)
{
unsigned access_size_max = mr->ops->valid.max_access_size;
@@ -3882,12 +3895,10 @@ int cpu_memory_rw_debug(CPUState *cpu, target_ulong addr,
phys_addr += (addr & ~TARGET_PAGE_MASK);
if (is_write) {
address_space_write_rom(cpu->cpu_ases[asidx].as, phys_addr,
MEMTXATTRS_UNSPECIFIED,
buf, l);
attrs, buf, l);
} else {
address_space_rw(cpu->cpu_ases[asidx].as, phys_addr,
MEMTXATTRS_UNSPECIFIED,
buf, l, 0);
attrs, buf, l, 0);
}
len -= l;
buf += l;
+48 -72
View File
@@ -644,50 +644,12 @@ static int memtox(char *buf, const char *mem, int len)
static uint32_t gdb_get_cpu_pid(const GDBState *s, CPUState *cpu)
{
#ifndef CONFIG_USER_ONLY
gchar *path, *name = NULL;
Object *obj;
CPUClusterState *cluster;
uint32_t ret;
path = object_get_canonical_path(OBJECT(cpu));
if (path == NULL) {
/* Return the default process' PID */
ret = s->processes[s->process_num - 1].pid;
goto out;
}
name = object_get_canonical_path_component(OBJECT(cpu));
assert(name != NULL);
/*
* Retrieve the CPU parent path by removing the last '/' and the CPU name
* from the CPU canonical path.
*/
path[strlen(path) - strlen(name) - 1] = '\0';
obj = object_resolve_path_type(path, TYPE_CPU_CLUSTER, NULL);
if (obj == NULL) {
/* Return the default process' PID */
ret = s->processes[s->process_num - 1].pid;
goto out;
}
cluster = CPU_CLUSTER(obj);
ret = cluster->cluster_id + 1;
out:
g_free(name);
g_free(path);
return ret;
#else
/* TODO: In user mode, we should use the task state PID */
return s->processes[s->process_num - 1].pid;
#endif
if (cpu->cluster_index == UNASSIGNED_CLUSTER_INDEX) {
/* Return the default process' PID */
return s->processes[s->process_num - 1].pid;
}
return cpu->cluster_index + 1;
}
static GDBProcess *gdb_get_process(const GDBState *s, uint32_t pid)
@@ -756,35 +718,6 @@ static CPUState *gdb_next_cpu_in_process(const GDBState *s, CPUState *cpu)
return cpu;
}
static CPUState *gdb_get_cpu(const GDBState *s, uint32_t pid, uint32_t tid)
{
GDBProcess *process;
CPUState *cpu;
if (!tid) {
/* 0 means any thread, we take the first one */
tid = 1;
}
cpu = find_cpu(tid);
if (cpu == NULL) {
return NULL;
}
process = gdb_get_cpu_process(s, cpu);
if (process->pid != pid) {
return NULL;
}
if (!process->attached) {
return NULL;
}
return cpu;
}
/* Return the cpu following @cpu, while ignoring unattached processes. */
static CPUState *gdb_next_attached_cpu(const GDBState *s, CPUState *cpu)
{
@@ -814,6 +747,49 @@ static CPUState *gdb_first_attached_cpu(const GDBState *s)
return cpu;
}
static CPUState *gdb_get_cpu(const GDBState *s, uint32_t pid, uint32_t tid)
{
GDBProcess *process;
CPUState *cpu;
if (!pid && !tid) {
/* 0 means any process/thread, we take the first attached one */
return gdb_first_attached_cpu(s);
} else if (pid && !tid) {
/* any thread in a specific process */
process = gdb_get_process(s, pid);
if (process == NULL) {
return NULL;
}
if (!process->attached) {
return NULL;
}
return get_first_cpu_in_process(s, process);
} else {
/* a specific thread */
cpu = find_cpu(tid);
if (cpu == NULL) {
return NULL;
}
process = gdb_get_cpu_process(s, cpu);
if (pid && process->pid != pid) {
return NULL;
}
if (!process->attached) {
return NULL;
}
return cpu;
}
}
static const char *get_feature_xml(const GDBState *s, const char *p,
const char **newp, GDBProcess *process)
{
+16
View File
@@ -16,11 +16,13 @@
#include "exec/address-spaces.h"
#include "hw/arm/nrf51_soc.h"
#include "hw/i2c/microbit_i2c.h"
typedef struct {
MachineState parent;
NRF51State nrf51;
MicrobitI2CState i2c;
} MicrobitMachineState;
#define TYPE_MICROBIT_MACHINE MACHINE_TYPE_NAME("microbit")
@@ -32,7 +34,9 @@ static void microbit_init(MachineState *machine)
{
MicrobitMachineState *s = MICROBIT_MACHINE(machine);
MemoryRegion *system_memory = get_system_memory();
MemoryRegion *mr;
Object *soc = OBJECT(&s->nrf51);
Object *i2c = OBJECT(&s->i2c);
sysbus_init_child_obj(OBJECT(machine), "nrf51", soc, sizeof(s->nrf51),
TYPE_NRF51_SOC);
@@ -41,6 +45,18 @@ static void microbit_init(MachineState *machine)
&error_fatal);
object_property_set_bool(soc, true, "realized", &error_fatal);
/*
* Overlap the TWI stub device into the SoC. This is a microbit-specific
* hack until we implement the nRF51 TWI controller properly and the
* magnetometer/accelerometer devices.
*/
sysbus_init_child_obj(OBJECT(machine), "microbit.twi", i2c,
sizeof(s->i2c), TYPE_MICROBIT_I2C);
object_property_set_bool(i2c, true, "realized", &error_fatal);
mr = sysbus_mmio_get_region(SYS_BUS_DEVICE(i2c), 0);
memory_region_add_subregion_overlap(&s->nrf51.container, NRF51_TWI_BASE,
mr, -1);
armv7m_load_kernel(ARM_CPU(first_cpu), machine->kernel_filename,
NRF51_SOC(soc)->flash_size);
}
+7 -2
View File
@@ -178,13 +178,16 @@ static void xlnx_zynqmp_create_rpu(XlnxZynqMPState *s, const char *boot_cpu,
int i;
int num_rpus = MIN(smp_cpus - XLNX_ZYNQMP_NUM_APU_CPUS, XLNX_ZYNQMP_NUM_RPU_CPUS);
if (num_rpus <= 0) {
/* Don't create rpu-cluster object if there's nothing to put in it */
return;
}
object_initialize_child(OBJECT(s), "rpu-cluster", &s->rpu_cluster,
sizeof(s->rpu_cluster), TYPE_CPU_CLUSTER,
&error_abort, NULL);
qdev_prop_set_uint32(DEVICE(&s->rpu_cluster), "cluster-id", 1);
qdev_init_nofail(DEVICE(&s->rpu_cluster));
for (i = 0; i < num_rpus; i++) {
char *name;
@@ -212,6 +215,8 @@ static void xlnx_zynqmp_create_rpu(XlnxZynqMPState *s, const char *boot_cpu,
return;
}
}
qdev_init_nofail(DEVICE(&s->rpu_cluster));
}
static void xlnx_zynqmp_init(Object *obj)
+46
View File
@@ -20,19 +20,65 @@
#include "qemu/osdep.h"
#include "hw/cpu/cluster.h"
#include "qom/cpu.h"
#include "qapi/error.h"
#include "qemu/module.h"
#include "qemu/cutils.h"
static Property cpu_cluster_properties[] = {
DEFINE_PROP_UINT32("cluster-id", CPUClusterState, cluster_id, 0),
DEFINE_PROP_END_OF_LIST()
};
typedef struct CallbackData {
CPUClusterState *cluster;
int cpu_count;
} CallbackData;
static int add_cpu_to_cluster(Object *obj, void *opaque)
{
CallbackData *cbdata = opaque;
CPUState *cpu = (CPUState *)object_dynamic_cast(obj, TYPE_CPU);
if (cpu) {
cpu->cluster_index = cbdata->cluster->cluster_id;
cbdata->cpu_count++;
}
return 0;
}
static void cpu_cluster_realize(DeviceState *dev, Error **errp)
{
/* Iterate through all our CPU children and set their cluster_index */
CPUClusterState *cluster = CPU_CLUSTER(dev);
Object *cluster_obj = OBJECT(dev);
CallbackData cbdata = {
.cluster = cluster,
.cpu_count = 0,
};
if (cluster->cluster_id >= MAX_CLUSTERS) {
error_setg(errp, "cluster-id must be less than %d", MAX_CLUSTERS);
return;
}
object_child_foreach_recursive(cluster_obj, add_cpu_to_cluster, &cbdata);
/*
* A cluster with no CPUs is a bug in the board/SoC code that created it;
* if you hit this during development of new code, check that you have
* created the CPUs and parented them into the cluster object before
* realizing the cluster object.
*/
assert(cbdata.cpu_count > 0);
}
static void cpu_cluster_class_init(ObjectClass *klass, void *data)
{
DeviceClass *dc = DEVICE_CLASS(klass);
dc->props = cpu_cluster_properties;
dc->realize = cpu_cluster_realize;
}
static const TypeInfo cpu_cluster_type_info = {
+1
View File
@@ -7,5 +7,6 @@ common-obj-$(CONFIG_BITBANG_I2C) += bitbang_i2c.o
common-obj-$(CONFIG_EXYNOS4) += exynos4210_i2c.o
common-obj-$(CONFIG_IMX_I2C) += imx_i2c.o
common-obj-$(CONFIG_ASPEED_SOC) += aspeed_i2c.o
common-obj-$(CONFIG_NRF51_SOC) += microbit_i2c.o
obj-$(CONFIG_OMAP) += omap_i2c.o
obj-$(CONFIG_PPC4XX) += ppc4xx_i2c.o
+127
View File
@@ -0,0 +1,127 @@
/*
* Microbit stub for Nordic Semiconductor nRF51 SoC Two-Wire Interface
* http://infocenter.nordicsemi.com/pdf/nRF51_RM_v3.0.1.pdf
*
* This is a microbit-specific stub for the TWI controller on the nRF51 SoC.
* We don't emulate I2C devices but the firmware probes the
* accelerometer/magnetometer on startup and panics if they are not found.
* Therefore we stub out the probing.
*
* In the future this file could evolve into a full nRF51 TWI controller
* device.
*
* Copyright 2018 Steffen Görtz <contrib@steffen-goertz.de>
* Copyright 2019 Red Hat, Inc.
*
* This code is licensed under the GPL version 2 or later. See
* the COPYING file in the top-level directory.
*/
#include "qemu/osdep.h"
#include "qemu/log.h"
#include "hw/i2c/microbit_i2c.h"
static const uint32_t twi_read_sequence[] = {0x5A, 0x5A, 0x40};
static uint64_t microbit_i2c_read(void *opaque, hwaddr addr, unsigned int size)
{
MicrobitI2CState *s = opaque;
uint64_t data = 0x00;
switch (addr) {
case NRF51_TWI_EVENT_STOPPED:
data = 0x01;
break;
case NRF51_TWI_EVENT_RXDREADY:
data = 0x01;
break;
case NRF51_TWI_EVENT_TXDSENT:
data = 0x01;
break;
case NRF51_TWI_REG_RXD:
data = twi_read_sequence[s->read_idx];
if (s->read_idx < G_N_ELEMENTS(twi_read_sequence)) {
s->read_idx++;
}
break;
default:
data = s->regs[addr / sizeof(s->regs[0])];
break;
}
qemu_log_mask(LOG_UNIMP, "%s: 0x%" HWADDR_PRIx " [%u] = %" PRIx32 "\n",
__func__, addr, size, (uint32_t)data);
return data;
}
static void microbit_i2c_write(void *opaque, hwaddr addr, uint64_t data,
unsigned int size)
{
MicrobitI2CState *s = opaque;
qemu_log_mask(LOG_UNIMP, "%s: 0x%" HWADDR_PRIx " <- 0x%" PRIx64 " [%u]\n",
__func__, addr, data, size);
s->regs[addr / sizeof(s->regs[0])] = data;
}
static const MemoryRegionOps microbit_i2c_ops = {
.read = microbit_i2c_read,
.write = microbit_i2c_write,
.endianness = DEVICE_LITTLE_ENDIAN,
.impl.min_access_size = 4,
.impl.max_access_size = 4,
};
static const VMStateDescription microbit_i2c_vmstate = {
.name = TYPE_MICROBIT_I2C,
.version_id = 1,
.minimum_version_id = 1,
.fields = (VMStateField[]) {
VMSTATE_UINT32_ARRAY(regs, MicrobitI2CState, MICROBIT_I2C_NREGS),
VMSTATE_UINT32(read_idx, MicrobitI2CState),
},
};
static void microbit_i2c_reset(DeviceState *dev)
{
MicrobitI2CState *s = MICROBIT_I2C(dev);
memset(s->regs, 0, sizeof(s->regs));
s->read_idx = 0;
}
static void microbit_i2c_realize(DeviceState *dev, Error **errp)
{
SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
MicrobitI2CState *s = MICROBIT_I2C(dev);
memory_region_init_io(&s->iomem, OBJECT(s), &microbit_i2c_ops, s,
"microbit.twi", NRF51_TWI_SIZE);
sysbus_init_mmio(sbd, &s->iomem);
}
static void microbit_i2c_class_init(ObjectClass *klass, void *data)
{
DeviceClass *dc = DEVICE_CLASS(klass);
dc->vmsd = &microbit_i2c_vmstate;
dc->reset = microbit_i2c_reset;
dc->realize = microbit_i2c_realize;
dc->desc = "Microbit I2C controller";
}
static const TypeInfo microbit_i2c_info = {
.name = TYPE_MICROBIT_I2C,
.parent = TYPE_SYS_BUS_DEVICE,
.instance_size = sizeof(MicrobitI2CState),
.class_init = microbit_i2c_class_init,
};
static void microbit_i2c_register_types(void)
{
type_register_static(&microbit_i2c_info);
}
type_init(microbit_i2c_register_types)
+120 -8
View File
@@ -98,8 +98,8 @@
/* Misc Control Register #1 */
#define R_MISC_CTRL1 (0x50 / 4)
/* Misc Control Register #2 */
#define R_MISC_CTRL2 (0x54 / 4)
/* SPI dummy cycle data */
#define R_DUMMY_DATA (0x54 / 4)
/* DMA Control/Status Register */
#define R_DMA_CTRL (0x80 / 4)
@@ -145,6 +145,9 @@
/* Flash opcodes. */
#define SPI_OP_READ 0x03 /* Read data bytes (low frequency) */
#define SNOOP_OFF 0xFF
#define SNOOP_START 0x0
/*
* Default segments mapping addresses and size for each slave per
* controller. These can be changed when board is initialized with the
@@ -529,7 +532,7 @@ static void aspeed_smc_flash_setup(AspeedSMCFlash *fl, uint32_t addr)
*/
if (aspeed_smc_flash_mode(fl) == CTRL_FREADMODE) {
for (i = 0; i < aspeed_smc_flash_dummies(fl); i++) {
ssi_transfer(fl->controller->spi, 0xFF);
ssi_transfer(fl->controller->spi, s->regs[R_DUMMY_DATA] & 0xff);
}
}
}
@@ -566,6 +569,101 @@ static uint64_t aspeed_smc_flash_read(void *opaque, hwaddr addr, unsigned size)
return ret;
}
/*
* TODO (clg@kaod.org): stolen from xilinx_spips.c. Should move to a
* common include header.
*/
typedef enum {
READ = 0x3, READ_4 = 0x13,
FAST_READ = 0xb, FAST_READ_4 = 0x0c,
DOR = 0x3b, DOR_4 = 0x3c,
QOR = 0x6b, QOR_4 = 0x6c,
DIOR = 0xbb, DIOR_4 = 0xbc,
QIOR = 0xeb, QIOR_4 = 0xec,
PP = 0x2, PP_4 = 0x12,
DPP = 0xa2,
QPP = 0x32, QPP_4 = 0x34,
} FlashCMD;
static int aspeed_smc_num_dummies(uint8_t command)
{
switch (command) { /* check for dummies */
case READ: /* no dummy bytes/cycles */
case PP:
case DPP:
case QPP:
case READ_4:
case PP_4:
case QPP_4:
return 0;
case FAST_READ:
case DOR:
case QOR:
case DOR_4:
case QOR_4:
return 1;
case DIOR:
case FAST_READ_4:
case DIOR_4:
return 2;
case QIOR:
case QIOR_4:
return 4;
default:
return -1;
}
}
static bool aspeed_smc_do_snoop(AspeedSMCFlash *fl, uint64_t data,
unsigned size)
{
AspeedSMCState *s = fl->controller;
uint8_t addr_width = aspeed_smc_flash_is_4byte(fl) ? 4 : 3;
if (s->snoop_index == SNOOP_OFF) {
return false; /* Do nothing */
} else if (s->snoop_index == SNOOP_START) {
uint8_t cmd = data & 0xff;
int ndummies = aspeed_smc_num_dummies(cmd);
/*
* No dummy cycles are expected with the current command. Turn
* off snooping and let the transfer proceed normally.
*/
if (ndummies <= 0) {
s->snoop_index = SNOOP_OFF;
return false;
}
s->snoop_dummies = ndummies * 8;
} else if (s->snoop_index >= addr_width + 1) {
/* The SPI transfer has reached the dummy cycles sequence */
for (; s->snoop_dummies; s->snoop_dummies--) {
ssi_transfer(s->spi, s->regs[R_DUMMY_DATA] & 0xff);
}
/* If no more dummy cycles are expected, turn off snooping */
if (!s->snoop_dummies) {
s->snoop_index = SNOOP_OFF;
} else {
s->snoop_index += size;
}
/*
* Dummy cycles have been faked already. Ignore the current
* SPI transfer
*/
return true;
}
s->snoop_index += size;
return false;
}
static void aspeed_smc_flash_write(void *opaque, hwaddr addr, uint64_t data,
unsigned size)
{
@@ -581,6 +679,10 @@ static void aspeed_smc_flash_write(void *opaque, hwaddr addr, uint64_t data,
switch (aspeed_smc_flash_mode(fl)) {
case CTRL_USERMODE:
if (aspeed_smc_do_snoop(fl, data, size)) {
break;
}
for (i = 0; i < size; i++) {
ssi_transfer(s->spi, (data >> (8 * i)) & 0xff);
}
@@ -613,7 +715,9 @@ static const MemoryRegionOps aspeed_smc_flash_ops = {
static void aspeed_smc_flash_update_cs(AspeedSMCFlash *fl)
{
const AspeedSMCState *s = fl->controller;
AspeedSMCState *s = fl->controller;
s->snoop_index = aspeed_smc_is_ce_stop_active(fl) ? SNOOP_OFF : SNOOP_START;
qemu_set_irq(s->cs_lines[fl->id], aspeed_smc_is_ce_stop_active(fl));
}
@@ -652,6 +756,9 @@ static void aspeed_smc_reset(DeviceState *d)
if (s->ctrl->segments == aspeed_segments_fmc) {
s->regs[s->r_conf] |= (CONF_FLASH_TYPE_SPI << CONF_FLASH_TYPE0);
}
s->snoop_index = SNOOP_OFF;
s->snoop_dummies = 0;
}
static uint64_t aspeed_smc_read(void *opaque, hwaddr addr, unsigned int size)
@@ -664,13 +771,14 @@ static uint64_t aspeed_smc_read(void *opaque, hwaddr addr, unsigned int size)
addr == s->r_timings ||
addr == s->r_ce_ctrl ||
addr == R_INTR_CTRL ||
addr == R_DUMMY_DATA ||
(addr >= R_SEG_ADDR0 && addr < R_SEG_ADDR0 + s->ctrl->max_slaves) ||
(addr >= s->r_ctrl0 && addr < s->r_ctrl0 + s->num_cs)) {
(addr >= s->r_ctrl0 && addr < s->r_ctrl0 + s->ctrl->max_slaves)) {
return s->regs[addr];
} else {
qemu_log_mask(LOG_UNIMP, "%s: not implemented: 0x%" HWADDR_PRIx "\n",
__func__, addr);
return 0;
return -1;
}
}
@@ -697,6 +805,8 @@ static void aspeed_smc_write(void *opaque, hwaddr addr, uint64_t data,
if (value != s->regs[R_SEG_ADDR0 + cs]) {
aspeed_smc_flash_set_segment(s, cs, value);
}
} else if (addr == R_DUMMY_DATA) {
s->regs[addr] = value & 0xff;
} else {
qemu_log_mask(LOG_UNIMP, "%s: not implemented: 0x%" HWADDR_PRIx "\n",
__func__, addr);
@@ -790,10 +900,12 @@ static void aspeed_smc_realize(DeviceState *dev, Error **errp)
static const VMStateDescription vmstate_aspeed_smc = {
.name = "aspeed.smc",
.version_id = 1,
.minimum_version_id = 1,
.version_id = 2,
.minimum_version_id = 2,
.fields = (VMStateField[]) {
VMSTATE_UINT32_ARRAY(regs, AspeedSMCState, ASPEED_SMC_R_MAX),
VMSTATE_UINT8(snoop_index, AspeedSMCState),
VMSTATE_UINT8(snoop_dummies, AspeedSMCState),
VMSTATE_END_OF_LIST()
}
};
+3 -1
View File
@@ -351,9 +351,11 @@ struct TranslationBlock {
#define CF_USE_ICOUNT 0x00020000
#define CF_INVALID 0x00040000 /* TB is stale. Set with @jmp_lock held */
#define CF_PARALLEL 0x00080000 /* Generate code for a parallel context */
#define CF_CLUSTER_MASK 0xff000000 /* Top 8 bits are cluster ID */
#define CF_CLUSTER_SHIFT 24
/* cflags' mask for hashing/comparison */
#define CF_HASH_MASK \
(CF_COUNT_MASK | CF_LAST_IO | CF_USE_ICOUNT | CF_PARALLEL)
(CF_COUNT_MASK | CF_LAST_IO | CF_USE_ICOUNT | CF_PARALLEL | CF_CLUSTER_MASK)
/* Per-vCPU dynamic tracing state used to generate this TB */
uint32_t trace_vcpu_dstate;
+18
View File
@@ -1344,6 +1344,24 @@ bool memory_region_snapshot_get_dirty(MemoryRegion *mr,
void memory_region_reset_dirty(MemoryRegion *mr, hwaddr addr,
hwaddr size, unsigned client);
/**
* memory_region_flush_rom_device: Mark a range of pages dirty and invalidate
* TBs (for self-modifying code).
*
* The MemoryRegionOps->write() callback of a ROM device must use this function
* to mark byte ranges that have been modified internally, such as by directly
* accessing the memory returned by memory_region_get_ram_ptr().
*
* This function marks the range dirty and invalidates TBs so that TCG can
* detect self-modifying code.
*
* @mr: the region being flushed.
* @addr: the start, relative to the start of the region, of the range being
* flushed.
* @size: the size, in bytes, of the range being flushed.
*/
void memory_region_flush_rom_device(MemoryRegion *mr, hwaddr addr, hwaddr size);
/**
* memory_region_set_readonly: Turn a memory region read-only (or read-write)
*
+2
View File
@@ -25,6 +25,8 @@
#define NRF51_IOMEM_SIZE 0x20000000
#define NRF51_UART_BASE 0x40002000
#define NRF51_TWI_BASE 0x40003000
#define NRF51_TWI_SIZE 0x00001000
#define NRF51_TIMER_BASE 0x40008000
#define NRF51_TIMER_SIZE 0x00001000
#define NRF51_RNG_BASE 0x4000D000
+1
View File
@@ -39,6 +39,7 @@ typedef struct NRF51State {
MemoryRegion sram;
MemoryRegion flash;
MemoryRegion clock;
MemoryRegion twi;
uint32_t sram_size;
uint32_t flash_size;
+24
View File
@@ -34,12 +34,36 @@
* Arm big.LITTLE system) they should be in different clusters. If the CPUs do
* not have the same view of memory (for example the main CPU and a management
* controller processor) they should be in different clusters.
*
* A cluster is created by creating an object of TYPE_CPU_CLUSTER, and then
* adding the CPUs to it as QOM child objects (e.g. using the
* object_initialize_child() or object_property_add_child() functions).
* The CPUs may be either direct children of the cluster object, or indirect
* children (e.g. children of children of the cluster object).
*
* All CPUs must be added as children before the cluster is realized.
* (Regrettably QOM provides no way to prevent adding children to a realized
* object and no way for the parent to be notified when a new child is added
* to it, so this restriction is not checked for, but the system will not
* behave correctly if it is not adhered to. The cluster will assert that
* it contains at least one CPU, which should catch most inadvertent
* violations of this constraint.)
*
* A CPU which is not put into any cluster will be considered implicitly
* to be in a cluster with all the other "loose" CPUs, so all CPUs that are
* not assigned to clusters must be identical.
*/
#define TYPE_CPU_CLUSTER "cpu-cluster"
#define CPU_CLUSTER(obj) \
OBJECT_CHECK(CPUClusterState, (obj), TYPE_CPU_CLUSTER)
/*
* This limit is imposed by TCG, which puts the cluster ID into an
* 8 bit field (and uses all-1s for the default "not in any cluster").
*/
#define MAX_CLUSTERS 255
/**
* CPUClusterState:
* @cluster_id: The cluster ID. This value is for internal use only and should
+42
View File
@@ -0,0 +1,42 @@
/*
* Microbit stub for Nordic Semiconductor nRF51 SoC Two-Wire Interface
* http://infocenter.nordicsemi.com/pdf/nRF51_RM_v3.0.1.pdf
*
* Copyright 2019 Red Hat, Inc.
*
* This code is licensed under the GPL version 2 or later. See
* the COPYING file in the top-level directory.
*/
#ifndef MICROBIT_I2C_H
#define MICROBIT_I2C_H
#include "hw/sysbus.h"
#include "hw/arm/nrf51.h"
#define NRF51_TWI_TASK_STARTRX 0x000
#define NRF51_TWI_TASK_STARTTX 0x008
#define NRF51_TWI_TASK_STOP 0x014
#define NRF51_TWI_EVENT_STOPPED 0x104
#define NRF51_TWI_EVENT_RXDREADY 0x108
#define NRF51_TWI_EVENT_TXDSENT 0x11c
#define NRF51_TWI_REG_ENABLE 0x500
#define NRF51_TWI_REG_RXD 0x518
#define NRF51_TWI_REG_TXD 0x51c
#define NRF51_TWI_REG_ADDRESS 0x588
#define TYPE_MICROBIT_I2C "microbit.i2c"
#define MICROBIT_I2C(obj) \
OBJECT_CHECK(MicrobitI2CState, (obj), TYPE_MICROBIT_I2C)
#define MICROBIT_I2C_NREGS (NRF51_TWI_SIZE / sizeof(uint32_t))
typedef struct {
SysBusDevice parent_obj;
MemoryRegion iomem;
uint32_t regs[MICROBIT_I2C_NREGS];
uint32_t read_idx;
} MicrobitI2CState;
#endif /* MICROBIT_I2C_H */
+3
View File
@@ -98,6 +98,9 @@ typedef struct AspeedSMCState {
uint8_t conf_enable_w0;
AspeedSMCFlash *flashes;
uint8_t snoop_index;
uint8_t snoop_dummies;
} AspeedSMCState;
#endif /* ASPEED_SMC_H */
+7
View File
@@ -280,6 +280,11 @@ struct qemu_work_item;
/**
* CPUState:
* @cpu_index: CPU index (informative).
* @cluster_index: Identifies which cluster this CPU is in.
* For boards which don't define clusters or for "loose" CPUs not assigned
* to a cluster this will be UNASSIGNED_CLUSTER_INDEX; otherwise it will
* be the same as the cluster-id property of the CPU object's TYPE_CPU_CLUSTER
* QOM parent.
* @nr_cores: Number of cores within this CPU package.
* @nr_threads: Number of threads within this CPU.
* @running: #true if CPU is currently running (lockless).
@@ -405,6 +410,7 @@ struct CPUState {
/* TODO Move common fields from CPUArchState here. */
int cpu_index;
int cluster_index;
uint32_t halted;
uint32_t can_do_io;
int32_t exception_index;
@@ -1111,5 +1117,6 @@ extern const struct VMStateDescription vmstate_cpu_common;
#endif /* NEED_CPU_H */
#define UNASSIGNED_CPU_INDEX -1
#define UNASSIGNED_CLUSTER_INDEX -1
#endif

Some files were not shown because too many files have changed in this diff Show More