aboutsummaryrefslogtreecommitdiff
path: root/include
diff options
context:
space:
mode:
authorPeter Maydell <peter.maydell@linaro.org>2015-04-28 10:31:03 +0100
committerPeter Maydell <peter.maydell@linaro.org>2015-04-28 10:31:03 +0100
commitda378d014d27fe3a243bd8e7e060e9eb8c1a272b (patch)
treef6ae00c4b474a297c436330e1d2ddd2033992e8d /include
parent3d27b09cf6f62ec61c1330d0a811811a91e7514d (diff)
parent4eb276408363aef5435a72a8e818f24220b5edd0 (diff)
Merge remote-tracking branch 'remotes/pmaydell/tags/pull-target-arm-20150427' into staging
target-arm queue: * memory system updates to support transaction attributes * set user-mode and secure attributes for accesses made by ARM CPUs * rename c1_coproc to cpacr_el1 * adjust id_aa64pfr0 when has_el3 CPU property disabled * allow ARMv8 SCR.SMD updates # gpg: Signature made Mon Apr 27 16:14:30 2015 BST using RSA key ID 14360CDE # gpg: Good signature from "Peter Maydell <peter.maydell@linaro.org>" * remotes/pmaydell/tags/pull-target-arm-20150427: Allow ARMv8 SCR.SMD updates target-arm: Adjust id_aa64pfr0 when has_el3 CPU property disabled target-arm: rename c1_coproc to cpacr_el1 target-arm: Check watchpoints against CPU security state target-arm: Use attribute info to handle user-only watchpoints target-arm: Add user-mode transaction attribute target-arm: Use correct memory attributes for page table walks target-arm: Honour NS bits in page tables Switch non-CPU callers from ld/st*_phys to address_space_ld/st* exec.c: Capture the memory attributes for a watchpoint hit exec.c: Add new address_space_ld*/st* functions exec.c: Make address_space_rw take transaction attributes exec.c: Convert subpage memory ops to _with_attrs Add MemTxAttrs to the IOTLB Make CPU iotlb a structure rather than a plain hwaddr memory: Replace io_mem_read/write with memory_region_dispatch_read/write memory: Define API for MemoryRegionOps to take attrs and return status Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Diffstat (limited to 'include')
-rw-r--r--include/exec/cpu-defs.h15
-rw-r--r--include/exec/exec-all.h7
-rw-r--r--include/exec/memattrs.h45
-rw-r--r--include/exec/memory.h151
-rw-r--r--include/qom/cpu.h2
-rw-r--r--include/sysemu/dma.h3
6 files changed, 205 insertions, 18 deletions
diff --git a/include/exec/cpu-defs.h b/include/exec/cpu-defs.h
index 0ca6f0b953..3f56546066 100644
--- a/include/exec/cpu-defs.h
+++ b/include/exec/cpu-defs.h
@@ -30,6 +30,7 @@
#ifndef CONFIG_USER_ONLY
#include "exec/hwaddr.h"
#endif
+#include "exec/memattrs.h"
#ifndef TARGET_LONG_BITS
#error TARGET_LONG_BITS must be defined before including this header
@@ -102,12 +103,22 @@ typedef struct CPUTLBEntry {
QEMU_BUILD_BUG_ON(sizeof(CPUTLBEntry) != (1 << CPU_TLB_ENTRY_BITS));
+/* The IOTLB is not accessed directly inline by generated TCG code,
+ * so the CPUIOTLBEntry layout is not as critical as that of the
+ * CPUTLBEntry. (This is also why we don't want to combine the two
+ * structs into one.)
+ */
+typedef struct CPUIOTLBEntry {
+ hwaddr addr;
+ MemTxAttrs attrs;
+} CPUIOTLBEntry;
+
#define CPU_COMMON_TLB \
/* The meaning of the MMU modes is defined in the target code. */ \
CPUTLBEntry tlb_table[NB_MMU_MODES][CPU_TLB_SIZE]; \
CPUTLBEntry tlb_v_table[NB_MMU_MODES][CPU_VTLB_SIZE]; \
- hwaddr iotlb[NB_MMU_MODES][CPU_TLB_SIZE]; \
- hwaddr iotlb_v[NB_MMU_MODES][CPU_VTLB_SIZE]; \
+ CPUIOTLBEntry iotlb[NB_MMU_MODES][CPU_TLB_SIZE]; \
+ CPUIOTLBEntry iotlb_v[NB_MMU_MODES][CPU_VTLB_SIZE]; \
target_ulong tlb_flush_addr; \
target_ulong tlb_flush_mask; \
target_ulong vtlb_index; \
diff --git a/include/exec/exec-all.h b/include/exec/exec-all.h
index 8eb0db3910..b58cd47ced 100644
--- a/include/exec/exec-all.h
+++ b/include/exec/exec-all.h
@@ -105,6 +105,9 @@ void tlb_flush(CPUState *cpu, int flush_global);
void tlb_set_page(CPUState *cpu, target_ulong vaddr,
hwaddr paddr, int prot,
int mmu_idx, target_ulong size);
+void tlb_set_page_with_attrs(CPUState *cpu, target_ulong vaddr,
+ hwaddr paddr, MemTxAttrs attrs,
+ int prot, int mmu_idx, target_ulong size);
void tb_invalidate_phys_addr(AddressSpace *as, hwaddr addr);
#else
static inline void tlb_flush_page(CPUState *cpu, target_ulong addr)
@@ -341,10 +344,6 @@ void phys_mem_set_alloc(void *(*alloc)(size_t, uint64_t *align));
struct MemoryRegion *iotlb_to_region(CPUState *cpu,
hwaddr index);
-bool io_mem_read(struct MemoryRegion *mr, hwaddr addr,
- uint64_t *pvalue, unsigned size);
-bool io_mem_write(struct MemoryRegion *mr, hwaddr addr,
- uint64_t value, unsigned size);
void tlb_fill(CPUState *cpu, target_ulong addr, int is_write, int mmu_idx,
uintptr_t retaddr);
diff --git a/include/exec/memattrs.h b/include/exec/memattrs.h
new file mode 100644
index 0000000000..1389b4b01d
--- /dev/null
+++ b/include/exec/memattrs.h
@@ -0,0 +1,45 @@
+/*
+ * Memory transaction attributes
+ *
+ * Copyright (c) 2015 Linaro Limited.
+ *
+ * Authors:
+ * Peter Maydell <peter.maydell@linaro.org>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ *
+ */
+
+#ifndef MEMATTRS_H
+#define MEMATTRS_H
+
+/* Every memory transaction has associated with it a set of
+ * attributes. Some of these are generic (such as the ID of
+ * the bus master); some are specific to a particular kind of
+ * bus (such as the ARM Secure/NonSecure bit). We define them
+ * all as non-overlapping bitfields in a single struct to avoid
+ * confusion if different parts of QEMU used the same bit for
+ * different semantics.
+ */
+typedef struct MemTxAttrs {
+ /* Bus masters which don't specify any attributes will get this
+ * (via the MEMTXATTRS_UNSPECIFIED constant), so that we can
+ * distinguish "all attributes deliberately clear" from
+ * "didn't specify" if necessary.
+ */
+ unsigned int unspecified:1;
+ /* ARM/AMBA TrustZone Secure access */
+ unsigned int secure:1;
+ /* Memory access is usermode (unprivileged) */
+ unsigned int user:1;
+} MemTxAttrs;
+
+/* Bus masters which don't specify any attributes will get this,
+ * which has all attribute bits clear except the topmost one
+ * (so that we can distinguish "all attributes deliberately clear"
+ * from "didn't specify" if necessary).
+ */
+#define MEMTXATTRS_UNSPECIFIED ((MemTxAttrs) { .unspecified = 1 })
+
+#endif
diff --git a/include/exec/memory.h b/include/exec/memory.h
index 06ffa1d185..2f386cecb7 100644
--- a/include/exec/memory.h
+++ b/include/exec/memory.h
@@ -28,6 +28,7 @@
#ifndef CONFIG_USER_ONLY
#include "exec/hwaddr.h"
#endif
+#include "exec/memattrs.h"
#include "qemu/queue.h"
#include "qemu/int128.h"
#include "qemu/notify.h"
@@ -68,6 +69,16 @@ struct IOMMUTLBEntry {
IOMMUAccessFlags perm;
};
+/* New-style MMIO accessors can indicate that the transaction failed.
+ * A zero (MEMTX_OK) response means success; anything else is a failure
+ * of some kind. The memory subsystem will bitwise-OR together results
+ * if it is synthesizing an operation from multiple smaller accesses.
+ */
+#define MEMTX_OK 0
+#define MEMTX_ERROR (1U << 0) /* device returned an error */
+#define MEMTX_DECODE_ERROR (1U << 1) /* nothing at that address */
+typedef uint32_t MemTxResult;
+
/*
* Memory region callbacks
*/
@@ -84,6 +95,17 @@ struct MemoryRegionOps {
uint64_t data,
unsigned size);
+ MemTxResult (*read_with_attrs)(void *opaque,
+ hwaddr addr,
+ uint64_t *data,
+ unsigned size,
+ MemTxAttrs attrs);
+ MemTxResult (*write_with_attrs)(void *opaque,
+ hwaddr addr,
+ uint64_t data,
+ unsigned size,
+ MemTxAttrs attrs);
+
enum device_endian endianness;
/* Guest-visible constraints: */
struct {
@@ -1031,6 +1053,37 @@ void memory_global_dirty_log_stop(void);
void mtree_info(fprintf_function mon_printf, void *f);
/**
+ * memory_region_dispatch_read: perform a read directly to the specified
+ * MemoryRegion.
+ *
+ * @mr: #MemoryRegion to access
+ * @addr: address within that region
+ * @pval: pointer to uint64_t which the data is written to
+ * @size: size of the access in bytes
+ * @attrs: memory transaction attributes to use for the access
+ */
+MemTxResult memory_region_dispatch_read(MemoryRegion *mr,
+ hwaddr addr,
+ uint64_t *pval,
+ unsigned size,
+ MemTxAttrs attrs);
+/**
+ * memory_region_dispatch_write: perform a write directly to the specified
+ * MemoryRegion.
+ *
+ * @mr: #MemoryRegion to access
+ * @addr: address within that region
+ * @data: data to write
+ * @size: size of the access in bytes
+ * @attrs: memory transaction attributes to use for the access
+ */
+MemTxResult memory_region_dispatch_write(MemoryRegion *mr,
+ hwaddr addr,
+ uint64_t data,
+ unsigned size,
+ MemTxAttrs attrs);
+
+/**
* address_space_init: initializes an address space
*
* @as: an uninitialized #AddressSpace
@@ -1055,41 +1108,117 @@ void address_space_destroy(AddressSpace *as);
/**
* address_space_rw: read from or write to an address space.
*
- * Return true if the operation hit any unassigned memory or encountered an
- * IOMMU fault.
+ * Return a MemTxResult indicating whether the operation succeeded
+ * or failed (eg unassigned memory, device rejected the transaction,
+ * IOMMU fault).
*
* @as: #AddressSpace to be accessed
* @addr: address within that address space
+ * @attrs: memory transaction attributes
* @buf: buffer with the data transferred
* @is_write: indicates the transfer direction
*/
-bool address_space_rw(AddressSpace *as, hwaddr addr, uint8_t *buf,
- int len, bool is_write);
+MemTxResult address_space_rw(AddressSpace *as, hwaddr addr,
+ MemTxAttrs attrs, uint8_t *buf,
+ int len, bool is_write);
/**
* address_space_write: write to address space.
*
- * Return true if the operation hit any unassigned memory or encountered an
- * IOMMU fault.
+ * Return a MemTxResult indicating whether the operation succeeded
+ * or failed (eg unassigned memory, device rejected the transaction,
+ * IOMMU fault).
*
* @as: #AddressSpace to be accessed
* @addr: address within that address space
+ * @attrs: memory transaction attributes
* @buf: buffer with the data transferred
*/
-bool address_space_write(AddressSpace *as, hwaddr addr,
- const uint8_t *buf, int len);
+MemTxResult address_space_write(AddressSpace *as, hwaddr addr,
+ MemTxAttrs attrs,
+ const uint8_t *buf, int len);
/**
* address_space_read: read from an address space.
*
- * Return true if the operation hit any unassigned memory or encountered an
- * IOMMU fault.
+ * Return a MemTxResult indicating whether the operation succeeded
+ * or failed (eg unassigned memory, device rejected the transaction,
+ * IOMMU fault).
*
* @as: #AddressSpace to be accessed
* @addr: address within that address space
+ * @attrs: memory transaction attributes
* @buf: buffer with the data transferred
*/
-bool address_space_read(AddressSpace *as, hwaddr addr, uint8_t *buf, int len);
+MemTxResult address_space_read(AddressSpace *as, hwaddr addr, MemTxAttrs attrs,
+ uint8_t *buf, int len);
+
+/**
+ * address_space_ld*: load from an address space
+ * address_space_st*: store to an address space
+ *
+ * These functions perform a load or store of the byte, word,
+ * longword or quad to the specified address within the AddressSpace.
+ * The _le suffixed functions treat the data as little endian;
+ * _be indicates big endian; no suffix indicates "same endianness
+ * as guest CPU".
+ *
+ * The "guest CPU endianness" accessors are deprecated for use outside
+ * target-* code; devices should be CPU-agnostic and use either the LE
+ * or the BE accessors.
+ *
+ * @as #AddressSpace to be accessed
+ * @addr: address within that address space
+ * @val: data value, for stores
+ * @attrs: memory transaction attributes
+ * @result: location to write the success/failure of the transaction;
+ * if NULL, this information is discarded
+ */
+uint32_t address_space_ldub(AddressSpace *as, hwaddr addr,
+ MemTxAttrs attrs, MemTxResult *result);
+uint32_t address_space_lduw_le(AddressSpace *as, hwaddr addr,
+ MemTxAttrs attrs, MemTxResult *result);
+uint32_t address_space_lduw_be(AddressSpace *as, hwaddr addr,
+ MemTxAttrs attrs, MemTxResult *result);
+uint32_t address_space_ldl_le(AddressSpace *as, hwaddr addr,
+ MemTxAttrs attrs, MemTxResult *result);
+uint32_t address_space_ldl_be(AddressSpace *as, hwaddr addr,
+ MemTxAttrs attrs, MemTxResult *result);
+uint64_t address_space_ldq_le(AddressSpace *as, hwaddr addr,
+ MemTxAttrs attrs, MemTxResult *result);
+uint64_t address_space_ldq_be(AddressSpace *as, hwaddr addr,
+ MemTxAttrs attrs, MemTxResult *result);
+void address_space_stb(AddressSpace *as, hwaddr addr, uint32_t val,
+ MemTxAttrs attrs, MemTxResult *result);
+void address_space_stw_le(AddressSpace *as, hwaddr addr, uint32_t val,
+ MemTxAttrs attrs, MemTxResult *result);
+void address_space_stw_be(AddressSpace *as, hwaddr addr, uint32_t val,
+ MemTxAttrs attrs, MemTxResult *result);
+void address_space_stl_le(AddressSpace *as, hwaddr addr, uint32_t val,
+ MemTxAttrs attrs, MemTxResult *result);
+void address_space_stl_be(AddressSpace *as, hwaddr addr, uint32_t val,
+ MemTxAttrs attrs, MemTxResult *result);
+void address_space_stq_le(AddressSpace *as, hwaddr addr, uint64_t val,
+ MemTxAttrs attrs, MemTxResult *result);
+void address_space_stq_be(AddressSpace *as, hwaddr addr, uint64_t val,
+ MemTxAttrs attrs, MemTxResult *result);
+
+#ifdef NEED_CPU_H
+uint32_t address_space_lduw(AddressSpace *as, hwaddr addr,
+ MemTxAttrs attrs, MemTxResult *result);
+uint32_t address_space_ldl(AddressSpace *as, hwaddr addr,
+ MemTxAttrs attrs, MemTxResult *result);
+uint64_t address_space_ldq(AddressSpace *as, hwaddr addr,
+ MemTxAttrs attrs, MemTxResult *result);
+void address_space_stl_notdirty(AddressSpace *as, hwaddr addr, uint32_t val,
+ MemTxAttrs attrs, MemTxResult *result);
+void address_space_stw(AddressSpace *as, hwaddr addr, uint32_t val,
+ MemTxAttrs attrs, MemTxResult *result);
+void address_space_stl(AddressSpace *as, hwaddr addr, uint32_t val,
+ MemTxAttrs attrs, MemTxResult *result);
+void address_space_stq(AddressSpace *as, hwaddr addr, uint64_t val,
+ MemTxAttrs attrs, MemTxResult *result);
+#endif
/* address_space_translate: translate an address range into an address space
* into a MemoryRegion and an address range into that section
diff --git a/include/qom/cpu.h b/include/qom/cpu.h
index 9dafb4817e..39f0f19fb0 100644
--- a/include/qom/cpu.h
+++ b/include/qom/cpu.h
@@ -24,6 +24,7 @@
#include <setjmp.h>
#include "hw/qdev-core.h"
#include "exec/hwaddr.h"
+#include "exec/memattrs.h"
#include "qemu/queue.h"
#include "qemu/thread.h"
#include "qemu/tls.h"
@@ -195,6 +196,7 @@ typedef struct CPUWatchpoint {
vaddr vaddr;
vaddr len;
vaddr hitaddr;
+ MemTxAttrs hitattrs;
int flags; /* BP_* */
QTAILQ_ENTRY(CPUWatchpoint) entry;
} CPUWatchpoint;
diff --git a/include/sysemu/dma.h b/include/sysemu/dma.h
index 3f2f4c89e3..efa8b9993a 100644
--- a/include/sysemu/dma.h
+++ b/include/sysemu/dma.h
@@ -88,7 +88,8 @@ static inline int dma_memory_rw_relaxed(AddressSpace *as, dma_addr_t addr,
void *buf, dma_addr_t len,
DMADirection dir)
{
- return address_space_rw(as, addr, buf, len, dir == DMA_DIRECTION_FROM_DEVICE);
+ return (bool)address_space_rw(as, addr, MEMTXATTRS_UNSPECIFIED,
+ buf, len, dir == DMA_DIRECTION_FROM_DEVICE);
}
static inline int dma_memory_read_relaxed(AddressSpace *as, dma_addr_t addr,