mirror of
https://github.com/izzy2lost/xemu.git
synced 2026-07-06 00:20:22 -07:00
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:
@@ -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
@@ -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);
|
||||
|
||||
|
||||
@@ -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}_*``
|
||||
~~~~~~~~~~~~~~~~~
|
||||
|
||||
@@ -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(¬ifier->n,
|
||||
tcg_iommu_unmap_notify,
|
||||
IOMMU_NOTIFIER_UNMAP,
|
||||
0,
|
||||
HWADDR_MAX,
|
||||
iommu_idx);
|
||||
memory_region_register_iommu_notifier(notifier->mr, ¬ifier->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, ¬ifier->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 §ions[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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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. */
|
||||
|
||||
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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;
|
||||
|
||||
@@ -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
@@ -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
@@ -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, ®, 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, ®, true);
|
||||
|
||||
@@ -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
@@ -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
Reference in New Issue
Block a user