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

target-arm and miscellaneous queue:
 * fix KVM state save/restore for GICv3 priority registers for high IRQ numbers
 * hw/arm/mps2-tz: Put ethernet controller behind PPC
 * hw/sh/sh7750: Convert away from old_mmio
 * hw/m68k/mcf5206: Convert away from old_mmio
 * hw/block/pflash_cfi02: Convert away from old_mmio
 * hw/watchdog/wdt_i6300esb: Convert away from old_mmio
 * hw/input/pckbd: Convert away from old_mmio
 * hw/char/parallel: Convert away from old_mmio
 * armv7m: refactor to get rid of armv7m_init() function
 * arm: Don't crash if user tries to use a Cortex-M CPU without an NVIC
 * hw/core/or-irq: Support more than 16 inputs to an OR gate
 * cpu-defs.h: Document CPUIOTLBEntry 'addr' field
 * cputlb: Pass cpu_transaction_failed() the correct physaddr
 * CODING_STYLE: Define our preferred form for multiline comments
 * Add and use new stn_*_p() and ldn_*_p() memory access functions
 * target/arm: More parts of the upcoming SVE support
 * aspeed_scu: Implement RNG register
 * m25p80: add support for two bytes WRSR for Macronix chips
 * exec.c: Handle IOMMUs being in the path of TCG CPU memory accesses
 * target/arm: Allow ARMv6-M Thumb2 instructions

# gpg: Signature made Fri 15 Jun 2018 15:24:03 BST
# gpg:                using RSA key 3C2525ED14360CDE
# gpg: Good signature from "Peter Maydell <peter.maydell@linaro.org>"
# gpg:                 aka "Peter Maydell <pmaydell@gmail.com>"
# gpg:                 aka "Peter Maydell <pmaydell@chiark.greenend.org.uk>"
# Primary key fingerprint: E1A5 C593 CD41 9DE2 8E83  15CF 3C25 25ED 1436 0CDE

* remotes/pmaydell/tags/pull-target-arm-20180615: (43 commits)
  target/arm: Allow ARMv6-M Thumb2 instructions
  exec.c: Handle IOMMUs in address_space_translate_for_iotlb()
  iommu: Add IOMMU index argument to translate method
  iommu: Add IOMMU index argument to notifier APIs
  iommu: Add IOMMU index concept to IOMMU API
  m25p80: add support for two bytes WRSR for Macronix chips
  aspeed_scu: Implement RNG register
  target/arm: Implement SVE Floating Point Arithmetic - Unpredicated Group
  target/arm: Implement SVE Integer Wide Immediate - Unpredicated Group
  target/arm: Implement FDUP/DUP
  target/arm: Implement SVE Integer Compare - Scalars Group
  target/arm: Implement SVE Predicate Count Group
  target/arm: Implement SVE Partition Break Group
  target/arm: Implement SVE Integer Compare - Immediate Group
  target/arm: Implement SVE Integer Compare - Vectors Group
  target/arm: Implement SVE Select Vectors Group
  target/arm: Implement SVE vector splice (predicated)
  target/arm: Implement SVE reverse within elements
  target/arm: Implement SVE copy to vector (predicated)
  target/arm: Implement SVE conditionally broadcast/extract element
  ...

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
Peter Maydell
2018-06-15 15:27:48 +01:00
48 changed files with 4114 additions and 363 deletions
+17
View File
@@ -124,6 +124,23 @@ We use traditional C-style /* */ comments and avoid // comments.
Rationale: The // form is valid in C99, so this is purely a matter of
consistency of style. The checkpatch script will warn you about this.
Multiline comment blocks should have a row of stars on the left,
and the initial /* and terminating */ both on their own lines:
/*
* like
* this
*/
This is the same format required by the Linux kernel coding style.
(Some of the existing comments in the codebase use the GNU Coding
Standards form which does not have stars on the left, or other
variations; avoid these when writing new comments, but don't worry
about converting to the preferred form unless you're editing that
comment anyway.)
Rationale: Consistency, and ease of visually picking out a multiline
comment from the surrounding code.
8. trace-events style
8.1 0x prefix
+45 -14
View File
@@ -632,7 +632,8 @@ void tlb_set_page_with_attrs(CPUState *cpu, target_ulong vaddr,
}
sz = size;
section = address_space_translate_for_iotlb(cpu, asidx, paddr, &xlat, &sz);
section = address_space_translate_for_iotlb(cpu, asidx, paddr, &xlat, &sz,
attrs, &prot);
assert(sz >= TARGET_PAGE_SIZE);
tlb_debug("vaddr=" TARGET_FMT_lx " paddr=0x" TARGET_FMT_plx
@@ -664,6 +665,18 @@ void tlb_set_page_with_attrs(CPUState *cpu, target_ulong vaddr,
env->iotlb_v[mmu_idx][vidx] = env->iotlb[mmu_idx][index];
/* refill the tlb */
/*
* At this point iotlb contains a physical section number in the lower
* TARGET_PAGE_BITS, and either
* + the ram_addr_t of the page base of the target RAM (if NOTDIRTY or ROM)
* + the offset within section->mr of the page base (otherwise)
* We subtract the vaddr (which is page aligned and thus won't
* disturb the low bits) to give an offset which can be added to the
* (non-page-aligned) vaddr of the eventual memory access to get
* the MemoryRegion offset for the access. Note that the vaddr we
* subtract here is that of the page base, and not the same as the
* vaddr we add back in io_readx()/io_writex()/get_page_addr_code().
*/
env->iotlb[mmu_idx][index].addr = iotlb - vaddr;
env->iotlb[mmu_idx][index].attrs = attrs;
@@ -765,13 +778,16 @@ static uint64_t io_readx(CPUArchState *env, CPUIOTLBEntry *iotlbentry,
target_ulong addr, uintptr_t retaddr, int size)
{
CPUState *cpu = ENV_GET_CPU(env);
hwaddr physaddr = iotlbentry->addr;
MemoryRegion *mr = iotlb_to_region(cpu, physaddr, iotlbentry->attrs);
hwaddr mr_offset;
MemoryRegionSection *section;
MemoryRegion *mr;
uint64_t val;
bool locked = false;
MemTxResult r;
physaddr = (physaddr & TARGET_PAGE_MASK) + addr;
section = iotlb_to_section(cpu, iotlbentry->addr, iotlbentry->attrs);
mr = section->mr;
mr_offset = (iotlbentry->addr & TARGET_PAGE_MASK) + addr;
cpu->mem_io_pc = retaddr;
if (mr != &io_mem_rom && mr != &io_mem_notdirty && !cpu->can_do_io) {
cpu_io_recompile(cpu, retaddr);
@@ -783,9 +799,13 @@ static uint64_t io_readx(CPUArchState *env, CPUIOTLBEntry *iotlbentry,
qemu_mutex_lock_iothread();
locked = true;
}
r = memory_region_dispatch_read(mr, physaddr,
r = memory_region_dispatch_read(mr, mr_offset,
&val, size, iotlbentry->attrs);
if (r != MEMTX_OK) {
hwaddr physaddr = mr_offset +
section->offset_within_address_space -
section->offset_within_region;
cpu_transaction_failed(cpu, physaddr, addr, size, MMU_DATA_LOAD,
mmu_idx, iotlbentry->attrs, r, retaddr);
}
@@ -802,12 +822,15 @@ static void io_writex(CPUArchState *env, CPUIOTLBEntry *iotlbentry,
uintptr_t retaddr, int size)
{
CPUState *cpu = ENV_GET_CPU(env);
hwaddr physaddr = iotlbentry->addr;
MemoryRegion *mr = iotlb_to_region(cpu, physaddr, iotlbentry->attrs);
hwaddr mr_offset;
MemoryRegionSection *section;
MemoryRegion *mr;
bool locked = false;
MemTxResult r;
physaddr = (physaddr & TARGET_PAGE_MASK) + addr;
section = iotlb_to_section(cpu, iotlbentry->addr, iotlbentry->attrs);
mr = section->mr;
mr_offset = (iotlbentry->addr & TARGET_PAGE_MASK) + addr;
if (mr != &io_mem_rom && mr != &io_mem_notdirty && !cpu->can_do_io) {
cpu_io_recompile(cpu, retaddr);
}
@@ -818,9 +841,13 @@ static void io_writex(CPUArchState *env, CPUIOTLBEntry *iotlbentry,
qemu_mutex_lock_iothread();
locked = true;
}
r = memory_region_dispatch_write(mr, physaddr,
r = memory_region_dispatch_write(mr, mr_offset,
val, size, iotlbentry->attrs);
if (r != MEMTX_OK) {
hwaddr physaddr = mr_offset +
section->offset_within_address_space -
section->offset_within_region;
cpu_transaction_failed(cpu, physaddr, addr, size, MMU_DATA_STORE,
mmu_idx, iotlbentry->attrs, r, retaddr);
}
@@ -868,12 +895,13 @@ static bool victim_tlb_hit(CPUArchState *env, size_t mmu_idx, size_t index,
*/
tb_page_addr_t get_page_addr_code(CPUArchState *env, target_ulong addr)
{
int mmu_idx, index, pd;
int mmu_idx, index;
void *p;
MemoryRegion *mr;
MemoryRegionSection *section;
CPUState *cpu = ENV_GET_CPU(env);
CPUIOTLBEntry *iotlbentry;
hwaddr physaddr;
hwaddr physaddr, mr_offset;
index = (addr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1);
mmu_idx = cpu_mmu_index(env, true);
@@ -884,8 +912,8 @@ tb_page_addr_t get_page_addr_code(CPUArchState *env, target_ulong addr)
}
}
iotlbentry = &env->iotlb[mmu_idx][index];
pd = iotlbentry->addr & ~TARGET_PAGE_MASK;
mr = iotlb_to_region(cpu, pd, iotlbentry->attrs);
section = iotlb_to_section(cpu, iotlbentry->addr, iotlbentry->attrs);
mr = section->mr;
if (memory_region_is_unassigned(mr)) {
qemu_mutex_lock_iothread();
if (memory_region_request_mmio_ptr(mr, addr)) {
@@ -906,7 +934,10 @@ tb_page_addr_t get_page_addr_code(CPUArchState *env, target_ulong addr)
* and use the MemTXResult it produced). However it is the
* simplest place we have currently available for the check.
*/
physaddr = (iotlbentry->addr & TARGET_PAGE_MASK) + addr;
mr_offset = (iotlbentry->addr & TARGET_PAGE_MASK) + addr;
physaddr = mr_offset +
section->offset_within_address_space -
section->offset_within_region;
cpu_transaction_failed(cpu, physaddr, addr, 0, MMU_INST_FETCH, mmu_idx,
iotlbentry->attrs, MEMTX_DECODE_ERROR, 0);
+15
View File
@@ -53,9 +53,24 @@ The ``_{endian}`` infix is omitted for target-endian accesses.
The target endian accessors are only available to source
files which are built per-target.
There are also functions which take the size as an argument:
load: ``ldn{endian}_p(ptr, sz)``
which performs an unsigned load of ``sz`` bytes from ``ptr``
as an ``{endian}`` order value and returns it in a uint64_t.
store: ``stn{endian}_p(ptr, sz, val)``
which stores ``val`` to ``ptr`` as an ``{endian}`` order value
of size ``sz`` bytes.
Regexes for git grep
- ``\<ldf\?[us]\?[bwlq]\(_[hbl]e\)\?_p\>``
- ``\<stf\?[bwlq]\(_[hbl]e\)\?_p\>``
- ``\<ldn_\([hbl]e\)?_p\>``
- ``\<stn_\([hbl]e\)?_p\>``
``cpu_{ld,st}_*``
~~~~~~~~~~~~~~~~~
+153 -110
View File
@@ -501,8 +501,15 @@ static MemoryRegionSection address_space_translate_iommu(IOMMUMemoryRegion *iomm
do {
hwaddr addr = *xlat;
IOMMUMemoryRegionClass *imrc = memory_region_get_iommu_class_nocheck(iommu_mr);
IOMMUTLBEntry iotlb = imrc->translate(iommu_mr, addr, is_write ?
IOMMU_WO : IOMMU_RO);
int iommu_idx = 0;
IOMMUTLBEntry iotlb;
if (imrc->attrs_to_index) {
iommu_idx = imrc->attrs_to_index(iommu_mr, attrs);
}
iotlb = imrc->translate(iommu_mr, addr, is_write ?
IOMMU_WO : IOMMU_RO, iommu_idx);
if (!(iotlb.perm & (1 << is_write))) {
goto unassigned;
@@ -646,18 +653,144 @@ MemoryRegion *flatview_translate(FlatView *fv, hwaddr addr, hwaddr *xlat,
return mr;
}
typedef struct TCGIOMMUNotifier {
IOMMUNotifier n;
MemoryRegion *mr;
CPUState *cpu;
int iommu_idx;
bool active;
} TCGIOMMUNotifier;
static void tcg_iommu_unmap_notify(IOMMUNotifier *n, IOMMUTLBEntry *iotlb)
{
TCGIOMMUNotifier *notifier = container_of(n, TCGIOMMUNotifier, n);
if (!notifier->active) {
return;
}
tlb_flush(notifier->cpu);
notifier->active = false;
/* We leave the notifier struct on the list to avoid reallocating it later.
* Generally the number of IOMMUs a CPU deals with will be small.
* In any case we can't unregister the iommu notifier from a notify
* callback.
*/
}
static void tcg_register_iommu_notifier(CPUState *cpu,
IOMMUMemoryRegion *iommu_mr,
int iommu_idx)
{
/* Make sure this CPU has an IOMMU notifier registered for this
* IOMMU/IOMMU index combination, so that we can flush its TLB
* when the IOMMU tells us the mappings we've cached have changed.
*/
MemoryRegion *mr = MEMORY_REGION(iommu_mr);
TCGIOMMUNotifier *notifier;
int i;
for (i = 0; i < cpu->iommu_notifiers->len; i++) {
notifier = &g_array_index(cpu->iommu_notifiers, TCGIOMMUNotifier, i);
if (notifier->mr == mr && notifier->iommu_idx == iommu_idx) {
break;
}
}
if (i == cpu->iommu_notifiers->len) {
/* Not found, add a new entry at the end of the array */
cpu->iommu_notifiers = g_array_set_size(cpu->iommu_notifiers, i + 1);
notifier = &g_array_index(cpu->iommu_notifiers, TCGIOMMUNotifier, i);
notifier->mr = mr;
notifier->iommu_idx = iommu_idx;
notifier->cpu = cpu;
/* Rather than trying to register interest in the specific part
* of the iommu's address space that we've accessed and then
* expand it later as subsequent accesses touch more of it, we
* just register interest in the whole thing, on the assumption
* that iommu reconfiguration will be rare.
*/
iommu_notifier_init(&notifier->n,
tcg_iommu_unmap_notify,
IOMMU_NOTIFIER_UNMAP,
0,
HWADDR_MAX,
iommu_idx);
memory_region_register_iommu_notifier(notifier->mr, &notifier->n);
}
if (!notifier->active) {
notifier->active = true;
}
}
static void tcg_iommu_free_notifier_list(CPUState *cpu)
{
/* Destroy the CPU's notifier list */
int i;
TCGIOMMUNotifier *notifier;
for (i = 0; i < cpu->iommu_notifiers->len; i++) {
notifier = &g_array_index(cpu->iommu_notifiers, TCGIOMMUNotifier, i);
memory_region_unregister_iommu_notifier(notifier->mr, &notifier->n);
}
g_array_free(cpu->iommu_notifiers, true);
}
/* Called from RCU critical section */
MemoryRegionSection *
address_space_translate_for_iotlb(CPUState *cpu, int asidx, hwaddr addr,
hwaddr *xlat, hwaddr *plen)
hwaddr *xlat, hwaddr *plen,
MemTxAttrs attrs, int *prot)
{
MemoryRegionSection *section;
IOMMUMemoryRegion *iommu_mr;
IOMMUMemoryRegionClass *imrc;
IOMMUTLBEntry iotlb;
int iommu_idx;
AddressSpaceDispatch *d = atomic_rcu_read(&cpu->cpu_ases[asidx].memory_dispatch);
section = address_space_translate_internal(d, addr, xlat, plen, false);
for (;;) {
section = address_space_translate_internal(d, addr, &addr, plen, false);
iommu_mr = memory_region_get_iommu(section->mr);
if (!iommu_mr) {
break;
}
imrc = memory_region_get_iommu_class_nocheck(iommu_mr);
iommu_idx = imrc->attrs_to_index(iommu_mr, attrs);
tcg_register_iommu_notifier(cpu, iommu_mr, iommu_idx);
/* We need all the permissions, so pass IOMMU_NONE so the IOMMU
* doesn't short-cut its translation table walk.
*/
iotlb = imrc->translate(iommu_mr, addr, IOMMU_NONE, iommu_idx);
addr = ((iotlb.translated_addr & ~iotlb.addr_mask)
| (addr & iotlb.addr_mask));
/* Update the caller's prot bits to remove permissions the IOMMU
* is giving us a failure response for. If we get down to no
* permissions left at all we can give up now.
*/
if (!(iotlb.perm & IOMMU_RO)) {
*prot &= ~(PAGE_READ | PAGE_EXEC);
}
if (!(iotlb.perm & IOMMU_WO)) {
*prot &= ~PAGE_WRITE;
}
if (!*prot) {
goto translate_fail;
}
d = flatview_to_dispatch(address_space_to_flatview(iotlb.target_as));
}
assert(!memory_region_is_iommu(section->mr));
*xlat = addr;
return section;
translate_fail:
return &d->map.sections[PHYS_SECTION_UNASSIGNED];
}
#endif
@@ -816,6 +949,9 @@ void cpu_exec_unrealizefn(CPUState *cpu)
if (qdev_get_vmsd(DEVICE(cpu)) == NULL) {
vmstate_unregister(NULL, &vmstate_cpu_common, cpu);
}
#ifndef CONFIG_USER_ONLY
tcg_iommu_free_notifier_list(cpu);
#endif
}
Property cpu_common_props[] = {
@@ -863,6 +999,8 @@ void cpu_exec_realizefn(CPUState *cpu, Error **errp)
if (cc->vmsd != NULL) {
vmstate_register(NULL, cpu->cpu_index, cc->vmsd, cpu);
}
cpu->iommu_notifiers = g_array_new(false, true, sizeof(TCGIOMMUNotifier));
#endif
}
@@ -2544,22 +2682,7 @@ static void notdirty_mem_write(void *opaque, hwaddr ram_addr,
memory_notdirty_write_prepare(&ndi, current_cpu, current_cpu->mem_io_vaddr,
ram_addr, size);
switch (size) {
case 1:
stb_p(qemu_map_ram_ptr(NULL, ram_addr), val);
break;
case 2:
stw_p(qemu_map_ram_ptr(NULL, ram_addr), val);
break;
case 4:
stl_p(qemu_map_ram_ptr(NULL, ram_addr), val);
break;
case 8:
stq_p(qemu_map_ram_ptr(NULL, ram_addr), val);
break;
default:
abort();
}
stn_p(qemu_map_ram_ptr(NULL, ram_addr), size, val);
memory_notdirty_write_complete(&ndi);
}
@@ -2739,22 +2862,8 @@ static MemTxResult subpage_read(void *opaque, hwaddr addr, uint64_t *data,
if (res) {
return res;
}
switch (len) {
case 1:
*data = ldub_p(buf);
return MEMTX_OK;
case 2:
*data = lduw_p(buf);
return MEMTX_OK;
case 4:
*data = ldl_p(buf);
return MEMTX_OK;
case 8:
*data = ldq_p(buf);
return MEMTX_OK;
default:
abort();
}
*data = ldn_p(buf, len);
return MEMTX_OK;
}
static MemTxResult subpage_write(void *opaque, hwaddr addr,
@@ -2768,22 +2877,7 @@ static MemTxResult subpage_write(void *opaque, hwaddr addr,
" value %"PRIx64"\n",
__func__, subpage, len, addr, value);
#endif
switch (len) {
case 1:
stb_p(buf, value);
break;
case 2:
stw_p(buf, value);
break;
case 4:
stl_p(buf, value);
break;
case 8:
stq_p(buf, value);
break;
default:
abort();
}
stn_p(buf, len, value);
return flatview_write(subpage->fv, addr + subpage->base, attrs, buf, len);
}
@@ -2897,14 +2991,15 @@ static const MemoryRegionOps readonly_mem_ops = {
},
};
MemoryRegion *iotlb_to_region(CPUState *cpu, hwaddr index, MemTxAttrs attrs)
MemoryRegionSection *iotlb_to_section(CPUState *cpu,
hwaddr index, MemTxAttrs attrs)
{
int asidx = cpu_asidx_from_attrs(cpu, attrs);
CPUAddressSpace *cpuas = &cpu->cpu_ases[asidx];
AddressSpaceDispatch *d = atomic_rcu_read(&cpuas->memory_dispatch);
MemoryRegionSection *sections = d->map.sections;
return sections[index & ~TARGET_PAGE_MASK].mr;
return &sections[index & ~TARGET_PAGE_MASK];
}
static void io_mem_init(void)
@@ -3128,34 +3223,8 @@ static MemTxResult flatview_write_continue(FlatView *fv, hwaddr addr,
l = memory_access_size(mr, l, addr1);
/* XXX: could force current_cpu to NULL to avoid
potential bugs */
switch (l) {
case 8:
/* 64 bit write access */
val = ldq_p(buf);
result |= memory_region_dispatch_write(mr, addr1, val, 8,
attrs);
break;
case 4:
/* 32 bit write access */
val = (uint32_t)ldl_p(buf);
result |= memory_region_dispatch_write(mr, addr1, val, 4,
attrs);
break;
case 2:
/* 16 bit write access */
val = lduw_p(buf);
result |= memory_region_dispatch_write(mr, addr1, val, 2,
attrs);
break;
case 1:
/* 8 bit write access */
val = ldub_p(buf);
result |= memory_region_dispatch_write(mr, addr1, val, 1,
attrs);
break;
default:
abort();
}
val = ldn_p(buf, l);
result |= memory_region_dispatch_write(mr, addr1, val, l, attrs);
} else {
/* RAM case */
ptr = qemu_ram_ptr_length(mr->ram_block, addr1, &l, false);
@@ -3216,34 +3285,8 @@ MemTxResult flatview_read_continue(FlatView *fv, hwaddr addr,
/* I/O case */
release_lock |= prepare_mmio_access(mr);
l = memory_access_size(mr, l, addr1);
switch (l) {
case 8:
/* 64 bit read access */
result |= memory_region_dispatch_read(mr, addr1, &val, 8,
attrs);
stq_p(buf, val);
break;
case 4:
/* 32 bit read access */
result |= memory_region_dispatch_read(mr, addr1, &val, 4,
attrs);
stl_p(buf, val);
break;
case 2:
/* 16 bit read access */
result |= memory_region_dispatch_read(mr, addr1, &val, 2,
attrs);
stw_p(buf, val);
break;
case 1:
/* 8 bit read access */
result |= memory_region_dispatch_read(mr, addr1, &val, 1,
attrs);
stb_p(buf, val);
break;
default:
abort();
}
result |= memory_region_dispatch_read(mr, addr1, &val, l, attrs);
stn_p(buf, l, val);
} else {
/* RAM case */
ptr = qemu_ram_ptr_length(mr->ram_block, addr1, &l, false);
+2 -1
View File
@@ -666,7 +666,8 @@ static bool window_translate(TyphoonWindow *win, hwaddr addr,
Pchip and generate a machine check interrupt. */
static IOMMUTLBEntry typhoon_translate_iommu(IOMMUMemoryRegion *iommu,
hwaddr addr,
IOMMUAccessFlags flag)
IOMMUAccessFlags flag,
int iommu_idx)
{
TyphoonPchip *pchip = container_of(iommu, TyphoonPchip, iommu);
IOMMUTLBEntry ret;
+6 -22
View File
@@ -178,6 +178,12 @@ static void armv7m_realize(DeviceState *dev, Error **errp)
return;
}
}
/* Tell the CPU where the NVIC is; it will fail realize if it doesn't
* have one.
*/
s->cpu->env.nvic = &s->nvic;
object_property_set_bool(OBJECT(s->cpu), true, "realized", &err);
if (err != NULL) {
error_propagate(errp, err);
@@ -202,7 +208,6 @@ static void armv7m_realize(DeviceState *dev, Error **errp)
sbd = SYS_BUS_DEVICE(&s->nvic);
sysbus_connect_irq(sbd, 0,
qdev_get_gpio_in(DEVICE(s->cpu), ARM_CPU_IRQ));
s->cpu->env.nvic = &s->nvic;
memory_region_add_subregion(&s->container, 0xe000e000,
sysbus_mmio_get_region(sbd, 0));
@@ -261,27 +266,6 @@ static void armv7m_reset(void *opaque)
cpu_reset(CPU(cpu));
}
/* Init CPU and memory for a v7-M based board.
mem_size is in bytes.
Returns the ARMv7M device. */
DeviceState *armv7m_init(MemoryRegion *system_memory, int mem_size, int num_irq,
const char *kernel_filename, const char *cpu_type)
{
DeviceState *armv7m;
armv7m = qdev_create(NULL, TYPE_ARMV7M);
qdev_prop_set_uint32(armv7m, "num-irq", num_irq);
qdev_prop_set_string(armv7m, "cpu-type", cpu_type);
object_property_set_link(OBJECT(armv7m), OBJECT(get_system_memory()),
"memory", &error_abort);
/* This will exit with an error if the user passed us a bad cpu_type */
qdev_init_nofail(armv7m);
armv7m_load_kernel(ARM_CPU(first_cpu), kernel_filename, mem_size);
return armv7m;
}
void armv7m_load_kernel(ARMCPU *cpu, const char *kernel_filename, int mem_size)
{
int image_size;
+23 -9
View File
@@ -74,12 +74,13 @@ typedef struct {
UnimplementedDeviceState spi[5];
UnimplementedDeviceState i2c[4];
UnimplementedDeviceState i2s_audio;
UnimplementedDeviceState gpio[5];
UnimplementedDeviceState gpio[4];
UnimplementedDeviceState dma[4];
UnimplementedDeviceState gfx;
CMSDKAPBUART uart[5];
SplitIRQ sec_resp_splitter;
qemu_or_irq uart_irq_orgate;
DeviceState *lan9118;
} MPS2TZMachineState;
#define TYPE_MPS2TZ_MACHINE "mps2tz"
@@ -224,6 +225,26 @@ static MemoryRegion *make_fpgaio(MPS2TZMachineState *mms, void *opaque,
return sysbus_mmio_get_region(SYS_BUS_DEVICE(fpgaio), 0);
}
static MemoryRegion *make_eth_dev(MPS2TZMachineState *mms, void *opaque,
const char *name, hwaddr size)
{
SysBusDevice *s;
DeviceState *iotkitdev = DEVICE(&mms->iotkit);
NICInfo *nd = &nd_table[0];
/* In hardware this is a LAN9220; the LAN9118 is software compatible
* except that it doesn't support the checksum-offload feature.
*/
qemu_check_nic_model(nd, "lan9118");
mms->lan9118 = qdev_create(NULL, "lan9118");
qdev_set_nic_properties(mms->lan9118, nd);
qdev_init_nofail(mms->lan9118);
s = SYS_BUS_DEVICE(mms->lan9118);
sysbus_connect_irq(s, 0, qdev_get_gpio_in_named(iotkitdev, "EXP_IRQ", 16));
return sysbus_mmio_get_region(s, 0);
}
static void mps2tz_common_init(MachineState *machine)
{
MPS2TZMachineState *mms = MPS2TZ_MACHINE(machine);
@@ -363,7 +384,7 @@ static void mps2tz_common_init(MachineState *machine)
{ "gpio1", make_unimp_dev, &mms->gpio[1], 0x40101000, 0x1000 },
{ "gpio2", make_unimp_dev, &mms->gpio[2], 0x40102000, 0x1000 },
{ "gpio3", make_unimp_dev, &mms->gpio[3], 0x40103000, 0x1000 },
{ "gpio4", make_unimp_dev, &mms->gpio[4], 0x40104000, 0x1000 },
{ "eth", make_eth_dev, NULL, 0x42000000, 0x100000 },
},
}, {
.name = "ahb_ppcexp1",
@@ -447,13 +468,6 @@ static void mps2tz_common_init(MachineState *machine)
"cfg_sec_resp", 0));
}
/* In hardware this is a LAN9220; the LAN9118 is software compatible
* except that it doesn't support the checksum-offload feature.
* The ethernet controller is not behind a PPC.
*/
lan9118_init(&nd_table[0], 0x42000000,
qdev_get_gpio_in_named(iotkitdev, "EXP_IRQ", 16));
create_unimplemented_device("FPGA NS PC", 0x48007000, 0x1000);
armv7m_load_kernel(ARM_CPU(first_cpu), machine->kernel_filename, 0x400000);
+1 -1
View File
@@ -538,7 +538,7 @@ static int smmuv3_decode_config(IOMMUMemoryRegion *mr, SMMUTransCfg *cfg,
}
static IOMMUTLBEntry smmuv3_translate(IOMMUMemoryRegion *mr, hwaddr addr,
IOMMUAccessFlags flag)
IOMMUAccessFlags flag, int iommu_idx)
{
SMMUDevice *sdev = container_of(mr, SMMUDevice, iommu);
SMMUv3State *s = sdev->smmu;
+10 -2
View File
@@ -20,6 +20,7 @@
#include "qemu/log.h"
#include "exec/address-spaces.h"
#include "sysemu/sysemu.h"
#include "hw/arm/armv7m.h"
#include "hw/char/pl011.h"
#include "hw/misc/unimp.h"
#include "cpu.h"
@@ -1298,8 +1299,13 @@ static void stellaris_init(MachineState *ms, stellaris_board_info *board)
&error_fatal);
memory_region_add_subregion(system_memory, 0x20000000, sram);
nvic = armv7m_init(system_memory, flash_size, NUM_IRQ_LINES,
ms->kernel_filename, ms->cpu_type);
nvic = qdev_create(NULL, TYPE_ARMV7M);
qdev_prop_set_uint32(nvic, "num-irq", NUM_IRQ_LINES);
qdev_prop_set_string(nvic, "cpu-type", ms->cpu_type);
object_property_set_link(OBJECT(nvic), OBJECT(get_system_memory()),
"memory", &error_abort);
/* This will exit with an error if the user passed us a bad cpu_type */
qdev_init_nofail(nvic);
qdev_connect_gpio_out_named(nvic, "SYSRESETREQ", 0,
qemu_allocate_irq(&do_sys_reset, NULL, 0));
@@ -1431,6 +1437,8 @@ static void stellaris_init(MachineState *ms, stellaris_board_info *board)
create_unimplemented_device("analogue-comparator", 0x4003c000, 0x1000);
create_unimplemented_device("hibernation", 0x400fc000, 0x1000);
create_unimplemented_device("flash-control", 0x400fd000, 0x1000);
armv7m_load_kernel(ARM_CPU(first_cpu), ms->kernel_filename, flash_size);
}
/* FIXME: Figure out how to generate these from stellaris_boards. */
+1
View File
@@ -698,6 +698,7 @@ static void complete_collecting_data(Flash *s)
case MAN_MACRONIX:
s->quad_enable = extract32(s->data[0], 6, 1);
if (s->len > 1) {
s->volatile_cfg = s->data[1];
s->four_bytes_address_mode = extract32(s->data[1], 5, 1);
}
break;
+18 -79
View File
@@ -493,102 +493,41 @@ static void pflash_write (pflash_t *pfl, hwaddr offset,
pfl->cmd = 0;
}
static uint32_t pflash_readb_be(void *opaque, hwaddr addr)
static uint64_t pflash_be_readfn(void *opaque, hwaddr addr, unsigned size)
{
return pflash_read(opaque, addr, 1, 1);
return pflash_read(opaque, addr, size, 1);
}
static uint32_t pflash_readb_le(void *opaque, hwaddr addr)
static void pflash_be_writefn(void *opaque, hwaddr addr,
uint64_t value, unsigned size)
{
return pflash_read(opaque, addr, 1, 0);
pflash_write(opaque, addr, value, size, 1);
}
static uint32_t pflash_readw_be(void *opaque, hwaddr addr)
static uint64_t pflash_le_readfn(void *opaque, hwaddr addr, unsigned size)
{
pflash_t *pfl = opaque;
return pflash_read(pfl, addr, 2, 1);
return pflash_read(opaque, addr, size, 0);
}
static uint32_t pflash_readw_le(void *opaque, hwaddr addr)
static void pflash_le_writefn(void *opaque, hwaddr addr,
uint64_t value, unsigned size)
{
pflash_t *pfl = opaque;
return pflash_read(pfl, addr, 2, 0);
}
static uint32_t pflash_readl_be(void *opaque, hwaddr addr)
{
pflash_t *pfl = opaque;
return pflash_read(pfl, addr, 4, 1);
}
static uint32_t pflash_readl_le(void *opaque, hwaddr addr)
{
pflash_t *pfl = opaque;
return pflash_read(pfl, addr, 4, 0);
}
static void pflash_writeb_be(void *opaque, hwaddr addr,
uint32_t value)
{
pflash_write(opaque, addr, value, 1, 1);
}
static void pflash_writeb_le(void *opaque, hwaddr addr,
uint32_t value)
{
pflash_write(opaque, addr, value, 1, 0);
}
static void pflash_writew_be(void *opaque, hwaddr addr,
uint32_t value)
{
pflash_t *pfl = opaque;
pflash_write(pfl, addr, value, 2, 1);
}
static void pflash_writew_le(void *opaque, hwaddr addr,
uint32_t value)
{
pflash_t *pfl = opaque;
pflash_write(pfl, addr, value, 2, 0);
}
static void pflash_writel_be(void *opaque, hwaddr addr,
uint32_t value)
{
pflash_t *pfl = opaque;
pflash_write(pfl, addr, value, 4, 1);
}
static void pflash_writel_le(void *opaque, hwaddr addr,
uint32_t value)
{
pflash_t *pfl = opaque;
pflash_write(pfl, addr, value, 4, 0);
pflash_write(opaque, addr, value, size, 0);
}
static const MemoryRegionOps pflash_cfi02_ops_be = {
.old_mmio = {
.read = { pflash_readb_be, pflash_readw_be, pflash_readl_be, },
.write = { pflash_writeb_be, pflash_writew_be, pflash_writel_be, },
},
.read = pflash_be_readfn,
.write = pflash_be_writefn,
.valid.min_access_size = 1,
.valid.max_access_size = 4,
.endianness = DEVICE_NATIVE_ENDIAN,
};
static const MemoryRegionOps pflash_cfi02_ops_le = {
.old_mmio = {
.read = { pflash_readb_le, pflash_readw_le, pflash_readl_le, },
.write = { pflash_writeb_le, pflash_writew_le, pflash_writel_le, },
},
.read = pflash_le_readfn,
.write = pflash_le_writefn,
.valid.min_access_size = 1,
.valid.max_access_size = 4,
.endianness = DEVICE_NATIVE_ENDIAN,
};
+11 -39
View File
@@ -554,56 +554,28 @@ static void parallel_isa_realizefn(DeviceState *dev, Error **errp)
}
/* Memory mapped interface */
static uint32_t parallel_mm_readb (void *opaque, hwaddr addr)
static uint64_t parallel_mm_readfn(void *opaque, hwaddr addr, unsigned size)
{
ParallelState *s = opaque;
return parallel_ioport_read_sw(s, addr >> s->it_shift) & 0xFF;
return parallel_ioport_read_sw(s, addr >> s->it_shift) &
MAKE_64BIT_MASK(0, size * 8);
}
static void parallel_mm_writeb (void *opaque,
hwaddr addr, uint32_t value)
static void parallel_mm_writefn(void *opaque, hwaddr addr,
uint64_t value, unsigned size)
{
ParallelState *s = opaque;
parallel_ioport_write_sw(s, addr >> s->it_shift, value & 0xFF);
}
static uint32_t parallel_mm_readw (void *opaque, hwaddr addr)
{
ParallelState *s = opaque;
return parallel_ioport_read_sw(s, addr >> s->it_shift) & 0xFFFF;
}
static void parallel_mm_writew (void *opaque,
hwaddr addr, uint32_t value)
{
ParallelState *s = opaque;
parallel_ioport_write_sw(s, addr >> s->it_shift, value & 0xFFFF);
}
static uint32_t parallel_mm_readl (void *opaque, hwaddr addr)
{
ParallelState *s = opaque;
return parallel_ioport_read_sw(s, addr >> s->it_shift);
}
static void parallel_mm_writel (void *opaque,
hwaddr addr, uint32_t value)
{
ParallelState *s = opaque;
parallel_ioport_write_sw(s, addr >> s->it_shift, value);
parallel_ioport_write_sw(s, addr >> s->it_shift,
value & MAKE_64BIT_MASK(0, size * 8));
}
static const MemoryRegionOps parallel_mm_ops = {
.old_mmio = {
.read = { parallel_mm_readb, parallel_mm_readw, parallel_mm_readl },
.write = { parallel_mm_writeb, parallel_mm_writew, parallel_mm_writel },
},
.read = parallel_mm_readfn,
.write = parallel_mm_writefn,
.valid.min_access_size = 1,
.valid.max_access_size = 4,
.endianness = DEVICE_NATIVE_ENDIAN,
};
+37 -2
View File
@@ -66,14 +66,49 @@ static void or_irq_init(Object *obj)
qdev_init_gpio_out(DEVICE(obj), &s->out_irq, 1);
}
/* The original version of this device had a fixed 16 entries in its
* VMState array; devices with more inputs than this need to
* migrate the extra lines via a subsection.
* The subsection migrates as much of the levels[] array as is needed
* (including repeating the first 16 elements), to avoid the awkwardness
* of splitting it in two to meet the requirements of VMSTATE_VARRAY_UINT16.
*/
#define OLD_MAX_OR_LINES 16
#if MAX_OR_LINES < OLD_MAX_OR_LINES
#error MAX_OR_LINES must be at least 16 for migration compatibility
#endif
static bool vmstate_extras_needed(void *opaque)
{
qemu_or_irq *s = OR_IRQ(opaque);
return s->num_lines >= OLD_MAX_OR_LINES;
}
static const VMStateDescription vmstate_or_irq_extras = {
.name = "or-irq-extras",
.version_id = 1,
.minimum_version_id = 1,
.needed = vmstate_extras_needed,
.fields = (VMStateField[]) {
VMSTATE_VARRAY_UINT16_UNSAFE(levels, qemu_or_irq, num_lines, 0,
vmstate_info_bool, bool),
VMSTATE_END_OF_LIST(),
},
};
static const VMStateDescription vmstate_or_irq = {
.name = TYPE_OR_IRQ,
.version_id = 1,
.minimum_version_id = 1,
.fields = (VMStateField[]) {
VMSTATE_BOOL_ARRAY(levels, qemu_or_irq, MAX_OR_LINES),
VMSTATE_BOOL_SUB_ARRAY(levels, qemu_or_irq, 0, OLD_MAX_OR_LINES),
VMSTATE_END_OF_LIST(),
}
},
.subsections = (const VMStateDescription*[]) {
&vmstate_or_irq_extras,
NULL
},
};
static Property or_irq_properties[] = {
+1 -1
View File
@@ -491,7 +491,7 @@ static const MemoryRegionOps jazzio_ops = {
};
static IOMMUTLBEntry rc4030_dma_translate(IOMMUMemoryRegion *iommu, hwaddr addr,
IOMMUAccessFlags flag)
IOMMUAccessFlags flag, int iommu_idx)
{
rc4030State *s = container_of(iommu, rc4030State, dma_mr);
IOMMUTLBEntry ret = {
+1 -1
View File
@@ -991,7 +991,7 @@ static inline bool amdvi_is_interrupt_addr(hwaddr addr)
}
static IOMMUTLBEntry amdvi_translate(IOMMUMemoryRegion *iommu, hwaddr addr,
IOMMUAccessFlags flag)
IOMMUAccessFlags flag, int iommu_idx)
{
AMDVIAddressSpace *as = container_of(iommu, AMDVIAddressSpace, iommu);
AMDVIState *s = as->iommu_state;
+4 -4
View File
@@ -1023,7 +1023,7 @@ static int vtd_dev_to_context_entry(IntelIOMMUState *s, uint8_t bus_num,
static int vtd_sync_shadow_page_hook(IOMMUTLBEntry *entry,
void *private)
{
memory_region_notify_iommu((IOMMUMemoryRegion *)private, *entry);
memory_region_notify_iommu((IOMMUMemoryRegion *)private, 0, *entry);
return 0;
}
@@ -1581,7 +1581,7 @@ static void vtd_iotlb_page_invalidate_notify(IntelIOMMUState *s,
.addr_mask = size - 1,
.perm = IOMMU_NONE,
};
memory_region_notify_iommu(&vtd_as->iommu, entry);
memory_region_notify_iommu(&vtd_as->iommu, 0, entry);
}
}
}
@@ -2015,7 +2015,7 @@ static bool vtd_process_device_iotlb_desc(IntelIOMMUState *s,
entry.iova = addr;
entry.perm = IOMMU_NONE;
entry.translated_addr = 0;
memory_region_notify_iommu(&vtd_dev_as->iommu, entry);
memory_region_notify_iommu(&vtd_dev_as->iommu, 0, entry);
done:
return true;
@@ -2471,7 +2471,7 @@ static void vtd_mem_write(void *opaque, hwaddr addr,
}
static IOMMUTLBEntry vtd_iommu_translate(IOMMUMemoryRegion *iommu, hwaddr addr,
IOMMUAccessFlags flag)
IOMMUAccessFlags flag, int iommu_idx)
{
VTDAddressSpace *vtd_as = container_of(iommu, VTDAddressSpace, iommu);
IntelIOMMUState *s = vtd_as->iommu_state;
+8 -6
View File
@@ -434,7 +434,7 @@ static const VMStateDescription vmstate_kbd = {
};
/* Memory mapped interface */
static uint32_t kbd_mm_readb (void *opaque, hwaddr addr)
static uint64_t kbd_mm_readfn(void *opaque, hwaddr addr, unsigned size)
{
KBDState *s = opaque;
@@ -444,7 +444,8 @@ static uint32_t kbd_mm_readb (void *opaque, hwaddr addr)
return kbd_read_data(s, 0, 1) & 0xff;
}
static void kbd_mm_writeb (void *opaque, hwaddr addr, uint32_t value)
static void kbd_mm_writefn(void *opaque, hwaddr addr,
uint64_t value, unsigned size)
{
KBDState *s = opaque;
@@ -454,12 +455,13 @@ static void kbd_mm_writeb (void *opaque, hwaddr addr, uint32_t value)
kbd_write_data(s, 0, value & 0xff, 1);
}
static const MemoryRegionOps i8042_mmio_ops = {
.read = kbd_mm_readfn,
.write = kbd_mm_writefn,
.valid.min_access_size = 1,
.valid.max_access_size = 4,
.endianness = DEVICE_NATIVE_ENDIAN,
.old_mmio = {
.read = { kbd_mm_readb, kbd_mm_readb, kbd_mm_readb },
.write = { kbd_mm_writeb, kbd_mm_writeb, kbd_mm_writeb },
},
};
void i8042_mm_init(qemu_irq kbd_irq, qemu_irq mouse_irq,
+16 -2
View File
@@ -135,7 +135,14 @@ static void kvm_dist_get_priority(GICv3State *s, uint32_t offset, uint8_t *bmp)
uint32_t reg, *field;
int irq;
field = (uint32_t *)bmp;
/* For the KVM GICv3, affinity routing is always enabled, and the first 8
* GICD_IPRIORITYR<n> registers are always RAZ/WI. The corresponding
* functionality is replaced by GICR_IPRIORITYR<n>. It doesn't need to
* sync them. So it needs to skip the field of GIC_INTERNAL irqs in bmp and
* offset.
*/
field = (uint32_t *)(bmp + GIC_INTERNAL);
offset += (GIC_INTERNAL * 8) / 8;
for_each_dist_irq_reg(irq, s->num_irq, 8) {
kvm_gicd_access(s, offset, &reg, false);
*field = reg;
@@ -149,7 +156,14 @@ static void kvm_dist_put_priority(GICv3State *s, uint32_t offset, uint8_t *bmp)
uint32_t reg, *field;
int irq;
field = (uint32_t *)bmp;
/* For the KVM GICv3, affinity routing is always enabled, and the first 8
* GICD_IPRIORITYR<n> registers are always RAZ/WI. The corresponding
* functionality is replaced by GICR_IPRIORITYR<n>. It doesn't need to
* sync them. So it needs to skip the field of GIC_INTERNAL irqs in bmp and
* offset.
*/
field = (uint32_t *)(bmp + GIC_INTERNAL);
offset += (GIC_INTERNAL * 8) / 8;
for_each_dist_irq_reg(irq, s->num_irq, 8) {
reg = *field;
kvm_gicd_access(s, offset, &reg, true);
+5 -1
View File
@@ -2183,7 +2183,11 @@ static void armv7m_nvic_realize(DeviceState *dev, Error **errp)
int regionlen;
s->cpu = ARM_CPU(qemu_get_cpu(0));
assert(s->cpu);
if (!s->cpu || !arm_feature(&s->cpu->env, ARM_FEATURE_M)) {
error_setg(errp, "The NVIC can only be used with a Cortex-M CPU");
return;
}
if (s->num_irq > NVIC_MAX_IRQ) {
error_setg(errp, "num-irq %d exceeds NVIC maximum", s->num_irq);
+36 -12
View File
@@ -512,19 +512,43 @@ static void m5206_mbar_writel(void *opaque, hwaddr offset,
m5206_mbar_write(s, offset, value, 4);
}
static uint64_t m5206_mbar_readfn(void *opaque, hwaddr addr, unsigned size)
{
switch (size) {
case 1:
return m5206_mbar_readb(opaque, addr);
case 2:
return m5206_mbar_readw(opaque, addr);
case 4:
return m5206_mbar_readl(opaque, addr);
default:
g_assert_not_reached();
}
}
static void m5206_mbar_writefn(void *opaque, hwaddr addr,
uint64_t value, unsigned size)
{
switch (size) {
case 1:
m5206_mbar_writeb(opaque, addr, value);
break;
case 2:
m5206_mbar_writew(opaque, addr, value);
break;
case 4:
m5206_mbar_writel(opaque, addr, value);
break;
default:
g_assert_not_reached();
}
}
static const MemoryRegionOps m5206_mbar_ops = {
.old_mmio = {
.read = {
m5206_mbar_readb,
m5206_mbar_readw,
m5206_mbar_readl,
},
.write = {
m5206_mbar_writeb,
m5206_mbar_writew,
m5206_mbar_writel,
},
},
.read = m5206_mbar_readfn,
.write = m5206_mbar_writefn,
.valid.min_access_size = 1,
.valid.max_access_size = 4,
.endianness = DEVICE_NATIVE_ENDIAN,
};

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