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
 -----BEGIN PGP SIGNATURE-----
 Version: GnuPG v1
 
 iQIcBAABCAAGBQJVPlJWAAoJEDwlJe0UNgzeX6wP/3VRL+vFcgTugqLtG5MNpWl1
 FOjWikAKY6NNjddduK4e7gusy3a9NVnLJnqEfBL+9PYsWyMkDPJKgVzy+4gBl6Yy
 M5kGlemzLF1Fnx0ORXRLN4MHXDnrr7JIKtscKVMIZHG4YyqkWpd/iVWu+IlB+F2e
 S10QT+Djv3eAR/hu64CbdgQ+d2EzP5z84t+qIB/BMSklZ+wv/MFctotUb2LY+6xT
 9Sj1s1820BJGK1prFg9yb4NKsGcmwbn490bVb5Q6t5otqwns4O1LHlVLRpN5HAXB
 XReCuyaTBif1sD/iRlBTZGBdbM9p4UEPFwFDA8CEToZlRQemm7y+YZxkNgVLSVX3
 SeCUuYz81kklRmC4egKeMs1l4jKmNCKvHhoO/XpEVAwlIcf/Aap/Bm31G1hB5moI
 Ao0yEd9PXOinOxUSNUtmdM0CfVx7Rmja98Li4/7+GcgsyqOVO2M+dOp5dR5JUumf
 YbnYxegoxAGCSvXtmGqwPOnFcIpXJ/0a4mjVx40govnYC1KEc97KA+//pFQIy8s8
 cDKFYSVdpZ6VJ5M1V2fr4uUPa7phTZQDw8k7UoxzcjfL/ABQErkQG7ABcx+Q1txZ
 K7pA8LtCxInn+Ah03VPya2BRpb1eC+7ycr7ezb0Vlc7XtxgRqWGesvcWAr9z+Jtm
 eyr8k+QtnO9ic7Pgpt8M
 =hDRI
 -----END PGP SIGNATURE-----

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>
This commit is contained in:
Peter Maydell 2015-04-28 10:31:03 +01:00
commit da378d014d
42 changed files with 1090 additions and 366 deletions

View File

@ -249,9 +249,9 @@ static void tlb_add_large_page(CPUArchState *env, target_ulong vaddr,
* Called from TCG-generated code, which is under an RCU read-side * Called from TCG-generated code, which is under an RCU read-side
* critical section. * critical section.
*/ */
void tlb_set_page(CPUState *cpu, target_ulong vaddr, void tlb_set_page_with_attrs(CPUState *cpu, target_ulong vaddr,
hwaddr paddr, int prot, hwaddr paddr, MemTxAttrs attrs, int prot,
int mmu_idx, target_ulong size) int mmu_idx, target_ulong size)
{ {
CPUArchState *env = cpu->env_ptr; CPUArchState *env = cpu->env_ptr;
MemoryRegionSection *section; MemoryRegionSection *section;
@ -301,7 +301,8 @@ void tlb_set_page(CPUState *cpu, target_ulong vaddr,
env->iotlb_v[mmu_idx][vidx] = env->iotlb[mmu_idx][index]; env->iotlb_v[mmu_idx][vidx] = env->iotlb[mmu_idx][index];
/* refill the tlb */ /* refill the tlb */
env->iotlb[mmu_idx][index] = iotlb - vaddr; env->iotlb[mmu_idx][index].addr = iotlb - vaddr;
env->iotlb[mmu_idx][index].attrs = attrs;
te->addend = addend - vaddr; te->addend = addend - vaddr;
if (prot & PAGE_READ) { if (prot & PAGE_READ) {
te->addr_read = address; te->addr_read = address;
@ -331,6 +332,17 @@ void tlb_set_page(CPUState *cpu, target_ulong vaddr,
} }
} }
/* Add a new TLB entry, but without specifying the memory
* transaction attributes to be used.
*/
void tlb_set_page(CPUState *cpu, target_ulong vaddr,
hwaddr paddr, int prot,
int mmu_idx, target_ulong size)
{
tlb_set_page_with_attrs(cpu, vaddr, paddr, MEMTXATTRS_UNSPECIFIED,
prot, mmu_idx, size);
}
/* NOTE: this function can trigger an exception */ /* NOTE: this function can trigger an exception */
/* NOTE2: the returned address is not exactly the physical address: it /* NOTE2: the returned address is not exactly the physical address: it
* is actually a ram_addr_t (in system mode; the user mode emulation * is actually a ram_addr_t (in system mode; the user mode emulation
@ -349,7 +361,7 @@ tb_page_addr_t get_page_addr_code(CPUArchState *env1, target_ulong addr)
(addr & TARGET_PAGE_MASK))) { (addr & TARGET_PAGE_MASK))) {
cpu_ldub_code(env1, addr); cpu_ldub_code(env1, addr);
} }
pd = env1->iotlb[mmu_idx][page_index] & ~TARGET_PAGE_MASK; pd = env1->iotlb[mmu_idx][page_index].addr & ~TARGET_PAGE_MASK;
mr = iotlb_to_region(cpu, pd); mr = iotlb_to_region(cpu, pd);
if (memory_region_is_unassigned(mr)) { if (memory_region_is_unassigned(mr)) {
CPUClass *cc = CPU_GET_CLASS(cpu); CPUClass *cc = CPU_GET_CLASS(cpu);

View File

@ -28,7 +28,8 @@ int dma_memory_set(AddressSpace *as, dma_addr_t addr, uint8_t c, dma_addr_t len)
memset(fillbuf, c, FILLBUF_SIZE); memset(fillbuf, c, FILLBUF_SIZE);
while (len > 0) { while (len > 0) {
l = len < FILLBUF_SIZE ? len : FILLBUF_SIZE; l = len < FILLBUF_SIZE ? len : FILLBUF_SIZE;
error |= address_space_rw(as, addr, fillbuf, l, true); error |= address_space_rw(as, addr, MEMTXATTRS_UNSPECIFIED,
fillbuf, l, true);
len -= l; len -= l;
addr += l; addr += l;
} }

436
exec.c
View File

@ -1858,7 +1858,7 @@ static const MemoryRegionOps notdirty_mem_ops = {
}; };
/* Generate a debug exception if a watchpoint has been hit. */ /* Generate a debug exception if a watchpoint has been hit. */
static void check_watchpoint(int offset, int len, int flags) static void check_watchpoint(int offset, int len, MemTxAttrs attrs, int flags)
{ {
CPUState *cpu = current_cpu; CPUState *cpu = current_cpu;
CPUArchState *env = cpu->env_ptr; CPUArchState *env = cpu->env_ptr;
@ -1884,6 +1884,7 @@ static void check_watchpoint(int offset, int len, int flags)
wp->flags |= BP_WATCHPOINT_HIT_WRITE; wp->flags |= BP_WATCHPOINT_HIT_WRITE;
} }
wp->hitaddr = vaddr; wp->hitaddr = vaddr;
wp->hitattrs = attrs;
if (!cpu->watchpoint_hit) { if (!cpu->watchpoint_hit) {
cpu->watchpoint_hit = wp; cpu->watchpoint_hit = wp;
tb_check_watchpoint(cpu); tb_check_watchpoint(cpu);
@ -1905,69 +1906,93 @@ static void check_watchpoint(int offset, int len, int flags)
/* Watchpoint access routines. Watchpoints are inserted using TLB tricks, /* Watchpoint access routines. Watchpoints are inserted using TLB tricks,
so these check for a hit then pass through to the normal out-of-line so these check for a hit then pass through to the normal out-of-line
phys routines. */ phys routines. */
static uint64_t watch_mem_read(void *opaque, hwaddr addr, static MemTxResult watch_mem_read(void *opaque, hwaddr addr, uint64_t *pdata,
unsigned size) unsigned size, MemTxAttrs attrs)
{ {
check_watchpoint(addr & ~TARGET_PAGE_MASK, size, BP_MEM_READ); MemTxResult res;
switch (size) { uint64_t data;
case 1: return ldub_phys(&address_space_memory, addr);
case 2: return lduw_phys(&address_space_memory, addr);
case 4: return ldl_phys(&address_space_memory, addr);
default: abort();
}
}
static void watch_mem_write(void *opaque, hwaddr addr, check_watchpoint(addr & ~TARGET_PAGE_MASK, size, attrs, BP_MEM_READ);
uint64_t val, unsigned size)
{
check_watchpoint(addr & ~TARGET_PAGE_MASK, size, BP_MEM_WRITE);
switch (size) { switch (size) {
case 1: case 1:
stb_phys(&address_space_memory, addr, val); data = address_space_ldub(&address_space_memory, addr, attrs, &res);
break; break;
case 2: case 2:
stw_phys(&address_space_memory, addr, val); data = address_space_lduw(&address_space_memory, addr, attrs, &res);
break; break;
case 4: case 4:
stl_phys(&address_space_memory, addr, val); data = address_space_ldl(&address_space_memory, addr, attrs, &res);
break; break;
default: abort(); default: abort();
} }
*pdata = data;
return res;
}
static MemTxResult watch_mem_write(void *opaque, hwaddr addr,
uint64_t val, unsigned size,
MemTxAttrs attrs)
{
MemTxResult res;
check_watchpoint(addr & ~TARGET_PAGE_MASK, size, attrs, BP_MEM_WRITE);
switch (size) {
case 1:
address_space_stb(&address_space_memory, addr, val, attrs, &res);
break;
case 2:
address_space_stw(&address_space_memory, addr, val, attrs, &res);
break;
case 4:
address_space_stl(&address_space_memory, addr, val, attrs, &res);
break;
default: abort();
}
return res;
} }
static const MemoryRegionOps watch_mem_ops = { static const MemoryRegionOps watch_mem_ops = {
.read = watch_mem_read, .read_with_attrs = watch_mem_read,
.write = watch_mem_write, .write_with_attrs = watch_mem_write,
.endianness = DEVICE_NATIVE_ENDIAN, .endianness = DEVICE_NATIVE_ENDIAN,
}; };
static uint64_t subpage_read(void *opaque, hwaddr addr, static MemTxResult subpage_read(void *opaque, hwaddr addr, uint64_t *data,
unsigned len) unsigned len, MemTxAttrs attrs)
{ {
subpage_t *subpage = opaque; subpage_t *subpage = opaque;
uint8_t buf[8]; uint8_t buf[8];
MemTxResult res;
#if defined(DEBUG_SUBPAGE) #if defined(DEBUG_SUBPAGE)
printf("%s: subpage %p len %u addr " TARGET_FMT_plx "\n", __func__, printf("%s: subpage %p len %u addr " TARGET_FMT_plx "\n", __func__,
subpage, len, addr); subpage, len, addr);
#endif #endif
address_space_read(subpage->as, addr + subpage->base, buf, len); res = address_space_read(subpage->as, addr + subpage->base,
attrs, buf, len);
if (res) {
return res;
}
switch (len) { switch (len) {
case 1: case 1:
return ldub_p(buf); *data = ldub_p(buf);
return MEMTX_OK;
case 2: case 2:
return lduw_p(buf); *data = lduw_p(buf);
return MEMTX_OK;
case 4: case 4:
return ldl_p(buf); *data = ldl_p(buf);
return MEMTX_OK;
case 8: case 8:
return ldq_p(buf); *data = ldq_p(buf);
return MEMTX_OK;
default: default:
abort(); abort();
} }
} }
static void subpage_write(void *opaque, hwaddr addr, static MemTxResult subpage_write(void *opaque, hwaddr addr,
uint64_t value, unsigned len) uint64_t value, unsigned len, MemTxAttrs attrs)
{ {
subpage_t *subpage = opaque; subpage_t *subpage = opaque;
uint8_t buf[8]; uint8_t buf[8];
@ -1993,7 +2018,8 @@ static void subpage_write(void *opaque, hwaddr addr,
default: default:
abort(); abort();
} }
address_space_write(subpage->as, addr + subpage->base, buf, len); return address_space_write(subpage->as, addr + subpage->base,
attrs, buf, len);
} }
static bool subpage_accepts(void *opaque, hwaddr addr, static bool subpage_accepts(void *opaque, hwaddr addr,
@ -2010,8 +2036,8 @@ static bool subpage_accepts(void *opaque, hwaddr addr,
} }
static const MemoryRegionOps subpage_ops = { static const MemoryRegionOps subpage_ops = {
.read = subpage_read, .read_with_attrs = subpage_read,
.write = subpage_write, .write_with_attrs = subpage_write,
.impl.min_access_size = 1, .impl.min_access_size = 1,
.impl.max_access_size = 8, .impl.max_access_size = 8,
.valid.min_access_size = 1, .valid.min_access_size = 1,
@ -2304,15 +2330,15 @@ static int memory_access_size(MemoryRegion *mr, unsigned l, hwaddr addr)
return l; return l;
} }
bool address_space_rw(AddressSpace *as, hwaddr addr, uint8_t *buf, MemTxResult address_space_rw(AddressSpace *as, hwaddr addr, MemTxAttrs attrs,
int len, bool is_write) uint8_t *buf, int len, bool is_write)
{ {
hwaddr l; hwaddr l;
uint8_t *ptr; uint8_t *ptr;
uint64_t val; uint64_t val;
hwaddr addr1; hwaddr addr1;
MemoryRegion *mr; MemoryRegion *mr;
bool error = false; MemTxResult result = MEMTX_OK;
while (len > 0) { while (len > 0) {
l = len; l = len;
@ -2327,22 +2353,26 @@ bool address_space_rw(AddressSpace *as, hwaddr addr, uint8_t *buf,
case 8: case 8:
/* 64 bit write access */ /* 64 bit write access */
val = ldq_p(buf); val = ldq_p(buf);
error |= io_mem_write(mr, addr1, val, 8); result |= memory_region_dispatch_write(mr, addr1, val, 8,
attrs);
break; break;
case 4: case 4:
/* 32 bit write access */ /* 32 bit write access */
val = ldl_p(buf); val = ldl_p(buf);
error |= io_mem_write(mr, addr1, val, 4); result |= memory_region_dispatch_write(mr, addr1, val, 4,
attrs);
break; break;
case 2: case 2:
/* 16 bit write access */ /* 16 bit write access */
val = lduw_p(buf); val = lduw_p(buf);
error |= io_mem_write(mr, addr1, val, 2); result |= memory_region_dispatch_write(mr, addr1, val, 2,
attrs);
break; break;
case 1: case 1:
/* 8 bit write access */ /* 8 bit write access */
val = ldub_p(buf); val = ldub_p(buf);
error |= io_mem_write(mr, addr1, val, 1); result |= memory_region_dispatch_write(mr, addr1, val, 1,
attrs);
break; break;
default: default:
abort(); abort();
@ -2361,22 +2391,26 @@ bool address_space_rw(AddressSpace *as, hwaddr addr, uint8_t *buf,
switch (l) { switch (l) {
case 8: case 8:
/* 64 bit read access */ /* 64 bit read access */
error |= io_mem_read(mr, addr1, &val, 8); result |= memory_region_dispatch_read(mr, addr1, &val, 8,
attrs);
stq_p(buf, val); stq_p(buf, val);
break; break;
case 4: case 4:
/* 32 bit read access */ /* 32 bit read access */
error |= io_mem_read(mr, addr1, &val, 4); result |= memory_region_dispatch_read(mr, addr1, &val, 4,
attrs);
stl_p(buf, val); stl_p(buf, val);
break; break;
case 2: case 2:
/* 16 bit read access */ /* 16 bit read access */
error |= io_mem_read(mr, addr1, &val, 2); result |= memory_region_dispatch_read(mr, addr1, &val, 2,
attrs);
stw_p(buf, val); stw_p(buf, val);
break; break;
case 1: case 1:
/* 8 bit read access */ /* 8 bit read access */
error |= io_mem_read(mr, addr1, &val, 1); result |= memory_region_dispatch_read(mr, addr1, &val, 1,
attrs);
stb_p(buf, val); stb_p(buf, val);
break; break;
default: default:
@ -2393,25 +2427,27 @@ bool address_space_rw(AddressSpace *as, hwaddr addr, uint8_t *buf,
addr += l; addr += l;
} }
return error; return result;
} }
bool address_space_write(AddressSpace *as, hwaddr addr, MemTxResult address_space_write(AddressSpace *as, hwaddr addr, MemTxAttrs attrs,
const uint8_t *buf, int len) const uint8_t *buf, int len)
{ {
return address_space_rw(as, addr, (uint8_t *)buf, len, true); return address_space_rw(as, addr, attrs, (uint8_t *)buf, len, true);
} }
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)
{ {
return address_space_rw(as, addr, buf, len, false); return address_space_rw(as, addr, attrs, buf, len, false);
} }
void cpu_physical_memory_rw(hwaddr addr, uint8_t *buf, void cpu_physical_memory_rw(hwaddr addr, uint8_t *buf,
int len, int is_write) int len, int is_write)
{ {
address_space_rw(&address_space_memory, addr, buf, len, is_write); address_space_rw(&address_space_memory, addr, MEMTXATTRS_UNSPECIFIED,
buf, len, is_write);
} }
enum write_rom_type { enum write_rom_type {
@ -2582,7 +2618,8 @@ void *address_space_map(AddressSpace *as,
memory_region_ref(mr); memory_region_ref(mr);
bounce.mr = mr; bounce.mr = mr;
if (!is_write) { if (!is_write) {
address_space_read(as, addr, bounce.buffer, l); address_space_read(as, addr, MEMTXATTRS_UNSPECIFIED,
bounce.buffer, l);
} }
*plen = l; *plen = l;
@ -2635,7 +2672,8 @@ void address_space_unmap(AddressSpace *as, void *buffer, hwaddr len,
return; return;
} }
if (is_write) { if (is_write) {
address_space_write(as, bounce.addr, bounce.buffer, access_len); address_space_write(as, bounce.addr, MEMTXATTRS_UNSPECIFIED,
bounce.buffer, access_len);
} }
qemu_vfree(bounce.buffer); qemu_vfree(bounce.buffer);
bounce.buffer = NULL; bounce.buffer = NULL;
@ -2657,19 +2695,22 @@ void cpu_physical_memory_unmap(void *buffer, hwaddr len,
} }
/* warning: addr must be aligned */ /* warning: addr must be aligned */
static inline uint32_t ldl_phys_internal(AddressSpace *as, hwaddr addr, static inline uint32_t address_space_ldl_internal(AddressSpace *as, hwaddr addr,
enum device_endian endian) MemTxAttrs attrs,
MemTxResult *result,
enum device_endian endian)
{ {
uint8_t *ptr; uint8_t *ptr;
uint64_t val; uint64_t val;
MemoryRegion *mr; MemoryRegion *mr;
hwaddr l = 4; hwaddr l = 4;
hwaddr addr1; hwaddr addr1;
MemTxResult r;
mr = address_space_translate(as, addr, &addr1, &l, false); mr = address_space_translate(as, addr, &addr1, &l, false);
if (l < 4 || !memory_access_is_direct(mr, false)) { if (l < 4 || !memory_access_is_direct(mr, false)) {
/* I/O case */ /* I/O case */
io_mem_read(mr, addr1, &val, 4); r = memory_region_dispatch_read(mr, addr1, &val, 4, attrs);
#if defined(TARGET_WORDS_BIGENDIAN) #if defined(TARGET_WORDS_BIGENDIAN)
if (endian == DEVICE_LITTLE_ENDIAN) { if (endian == DEVICE_LITTLE_ENDIAN) {
val = bswap32(val); val = bswap32(val);
@ -2695,40 +2736,68 @@ static inline uint32_t ldl_phys_internal(AddressSpace *as, hwaddr addr,
val = ldl_p(ptr); val = ldl_p(ptr);
break; break;
} }
r = MEMTX_OK;
}
if (result) {
*result = r;
} }
return val; return val;
} }
uint32_t address_space_ldl(AddressSpace *as, hwaddr addr,
MemTxAttrs attrs, MemTxResult *result)
{
return address_space_ldl_internal(as, addr, attrs, result,
DEVICE_NATIVE_ENDIAN);
}
uint32_t address_space_ldl_le(AddressSpace *as, hwaddr addr,
MemTxAttrs attrs, MemTxResult *result)
{
return address_space_ldl_internal(as, addr, attrs, result,
DEVICE_LITTLE_ENDIAN);
}
uint32_t address_space_ldl_be(AddressSpace *as, hwaddr addr,
MemTxAttrs attrs, MemTxResult *result)
{
return address_space_ldl_internal(as, addr, attrs, result,
DEVICE_BIG_ENDIAN);
}
uint32_t ldl_phys(AddressSpace *as, hwaddr addr) uint32_t ldl_phys(AddressSpace *as, hwaddr addr)
{ {
return ldl_phys_internal(as, addr, DEVICE_NATIVE_ENDIAN); return address_space_ldl(as, addr, MEMTXATTRS_UNSPECIFIED, NULL);
} }
uint32_t ldl_le_phys(AddressSpace *as, hwaddr addr) uint32_t ldl_le_phys(AddressSpace *as, hwaddr addr)
{ {
return ldl_phys_internal(as, addr, DEVICE_LITTLE_ENDIAN); return address_space_ldl_le(as, addr, MEMTXATTRS_UNSPECIFIED, NULL);
} }
uint32_t ldl_be_phys(AddressSpace *as, hwaddr addr) uint32_t ldl_be_phys(AddressSpace *as, hwaddr addr)
{ {
return ldl_phys_internal(as, addr, DEVICE_BIG_ENDIAN); return address_space_ldl_be(as, addr, MEMTXATTRS_UNSPECIFIED, NULL);
} }
/* warning: addr must be aligned */ /* warning: addr must be aligned */
static inline uint64_t ldq_phys_internal(AddressSpace *as, hwaddr addr, static inline uint64_t address_space_ldq_internal(AddressSpace *as, hwaddr addr,
enum device_endian endian) MemTxAttrs attrs,
MemTxResult *result,
enum device_endian endian)
{ {
uint8_t *ptr; uint8_t *ptr;
uint64_t val; uint64_t val;
MemoryRegion *mr; MemoryRegion *mr;
hwaddr l = 8; hwaddr l = 8;
hwaddr addr1; hwaddr addr1;
MemTxResult r;
mr = address_space_translate(as, addr, &addr1, &l, mr = address_space_translate(as, addr, &addr1, &l,
false); false);
if (l < 8 || !memory_access_is_direct(mr, false)) { if (l < 8 || !memory_access_is_direct(mr, false)) {
/* I/O case */ /* I/O case */
io_mem_read(mr, addr1, &val, 8); r = memory_region_dispatch_read(mr, addr1, &val, 8, attrs);
#if defined(TARGET_WORDS_BIGENDIAN) #if defined(TARGET_WORDS_BIGENDIAN)
if (endian == DEVICE_LITTLE_ENDIAN) { if (endian == DEVICE_LITTLE_ENDIAN) {
val = bswap64(val); val = bswap64(val);
@ -2754,48 +2823,88 @@ static inline uint64_t ldq_phys_internal(AddressSpace *as, hwaddr addr,
val = ldq_p(ptr); val = ldq_p(ptr);
break; break;
} }
r = MEMTX_OK;
}
if (result) {
*result = r;
} }
return val; return val;
} }
uint64_t address_space_ldq(AddressSpace *as, hwaddr addr,
MemTxAttrs attrs, MemTxResult *result)
{
return address_space_ldq_internal(as, addr, attrs, result,
DEVICE_NATIVE_ENDIAN);
}
uint64_t address_space_ldq_le(AddressSpace *as, hwaddr addr,
MemTxAttrs attrs, MemTxResult *result)
{
return address_space_ldq_internal(as, addr, attrs, result,
DEVICE_LITTLE_ENDIAN);
}
uint64_t address_space_ldq_be(AddressSpace *as, hwaddr addr,
MemTxAttrs attrs, MemTxResult *result)
{
return address_space_ldq_internal(as, addr, attrs, result,
DEVICE_BIG_ENDIAN);
}
uint64_t ldq_phys(AddressSpace *as, hwaddr addr) uint64_t ldq_phys(AddressSpace *as, hwaddr addr)
{ {
return ldq_phys_internal(as, addr, DEVICE_NATIVE_ENDIAN); return address_space_ldq(as, addr, MEMTXATTRS_UNSPECIFIED, NULL);
} }
uint64_t ldq_le_phys(AddressSpace *as, hwaddr addr) uint64_t ldq_le_phys(AddressSpace *as, hwaddr addr)
{ {
return ldq_phys_internal(as, addr, DEVICE_LITTLE_ENDIAN); return address_space_ldq_le(as, addr, MEMTXATTRS_UNSPECIFIED, NULL);
} }
uint64_t ldq_be_phys(AddressSpace *as, hwaddr addr) uint64_t ldq_be_phys(AddressSpace *as, hwaddr addr)
{ {
return ldq_phys_internal(as, addr, DEVICE_BIG_ENDIAN); return address_space_ldq_be(as, addr, MEMTXATTRS_UNSPECIFIED, NULL);
} }
/* XXX: optimize */ /* XXX: optimize */
uint32_t ldub_phys(AddressSpace *as, hwaddr addr) uint32_t address_space_ldub(AddressSpace *as, hwaddr addr,
MemTxAttrs attrs, MemTxResult *result)
{ {
uint8_t val; uint8_t val;
address_space_rw(as, addr, &val, 1, 0); MemTxResult r;
r = address_space_rw(as, addr, attrs, &val, 1, 0);
if (result) {
*result = r;
}
return val; return val;
} }
uint32_t ldub_phys(AddressSpace *as, hwaddr addr)
{
return address_space_ldub(as, addr, MEMTXATTRS_UNSPECIFIED, NULL);
}
/* warning: addr must be aligned */ /* warning: addr must be aligned */
static inline uint32_t lduw_phys_internal(AddressSpace *as, hwaddr addr, static inline uint32_t address_space_lduw_internal(AddressSpace *as,
enum device_endian endian) hwaddr addr,
MemTxAttrs attrs,
MemTxResult *result,
enum device_endian endian)
{ {
uint8_t *ptr; uint8_t *ptr;
uint64_t val; uint64_t val;
MemoryRegion *mr; MemoryRegion *mr;
hwaddr l = 2; hwaddr l = 2;
hwaddr addr1; hwaddr addr1;
MemTxResult r;
mr = address_space_translate(as, addr, &addr1, &l, mr = address_space_translate(as, addr, &addr1, &l,
false); false);
if (l < 2 || !memory_access_is_direct(mr, false)) { if (l < 2 || !memory_access_is_direct(mr, false)) {
/* I/O case */ /* I/O case */
io_mem_read(mr, addr1, &val, 2); r = memory_region_dispatch_read(mr, addr1, &val, 2, attrs);
#if defined(TARGET_WORDS_BIGENDIAN) #if defined(TARGET_WORDS_BIGENDIAN)
if (endian == DEVICE_LITTLE_ENDIAN) { if (endian == DEVICE_LITTLE_ENDIAN) {
val = bswap16(val); val = bswap16(val);
@ -2821,39 +2930,66 @@ static inline uint32_t lduw_phys_internal(AddressSpace *as, hwaddr addr,
val = lduw_p(ptr); val = lduw_p(ptr);
break; break;
} }
r = MEMTX_OK;
}
if (result) {
*result = r;
} }
return val; return val;
} }
uint32_t address_space_lduw(AddressSpace *as, hwaddr addr,
MemTxAttrs attrs, MemTxResult *result)
{
return address_space_lduw_internal(as, addr, attrs, result,
DEVICE_NATIVE_ENDIAN);
}
uint32_t address_space_lduw_le(AddressSpace *as, hwaddr addr,
MemTxAttrs attrs, MemTxResult *result)
{
return address_space_lduw_internal(as, addr, attrs, result,
DEVICE_LITTLE_ENDIAN);
}
uint32_t address_space_lduw_be(AddressSpace *as, hwaddr addr,
MemTxAttrs attrs, MemTxResult *result)
{
return address_space_lduw_internal(as, addr, attrs, result,
DEVICE_BIG_ENDIAN);
}
uint32_t lduw_phys(AddressSpace *as, hwaddr addr) uint32_t lduw_phys(AddressSpace *as, hwaddr addr)
{ {
return lduw_phys_internal(as, addr, DEVICE_NATIVE_ENDIAN); return address_space_lduw(as, addr, MEMTXATTRS_UNSPECIFIED, NULL);
} }
uint32_t lduw_le_phys(AddressSpace *as, hwaddr addr) uint32_t lduw_le_phys(AddressSpace *as, hwaddr addr)
{ {
return lduw_phys_internal(as, addr, DEVICE_LITTLE_ENDIAN); return address_space_lduw_le(as, addr, MEMTXATTRS_UNSPECIFIED, NULL);
} }
uint32_t lduw_be_phys(AddressSpace *as, hwaddr addr) uint32_t lduw_be_phys(AddressSpace *as, hwaddr addr)
{ {
return lduw_phys_internal(as, addr, DEVICE_BIG_ENDIAN); return address_space_lduw_be(as, addr, MEMTXATTRS_UNSPECIFIED, NULL);
} }
/* warning: addr must be aligned. The ram page is not masked as dirty /* warning: addr must be aligned. The ram page is not masked as dirty
and the code inside is not invalidated. It is useful if the dirty and the code inside is not invalidated. It is useful if the dirty
bits are used to track modified PTEs */ bits are used to track modified PTEs */
void stl_phys_notdirty(AddressSpace *as, hwaddr addr, uint32_t val) void address_space_stl_notdirty(AddressSpace *as, hwaddr addr, uint32_t val,
MemTxAttrs attrs, MemTxResult *result)
{ {
uint8_t *ptr; uint8_t *ptr;
MemoryRegion *mr; MemoryRegion *mr;
hwaddr l = 4; hwaddr l = 4;
hwaddr addr1; hwaddr addr1;
MemTxResult r;
mr = address_space_translate(as, addr, &addr1, &l, mr = address_space_translate(as, addr, &addr1, &l,
true); true);
if (l < 4 || !memory_access_is_direct(mr, true)) { if (l < 4 || !memory_access_is_direct(mr, true)) {
io_mem_write(mr, addr1, val, 4); r = memory_region_dispatch_write(mr, addr1, val, 4, attrs);
} else { } else {
addr1 += memory_region_get_ram_addr(mr) & TARGET_PAGE_MASK; addr1 += memory_region_get_ram_addr(mr) & TARGET_PAGE_MASK;
ptr = qemu_get_ram_ptr(addr1); ptr = qemu_get_ram_ptr(addr1);
@ -2867,18 +3003,30 @@ void stl_phys_notdirty(AddressSpace *as, hwaddr addr, uint32_t val)
cpu_physical_memory_set_dirty_range_nocode(addr1, 4); cpu_physical_memory_set_dirty_range_nocode(addr1, 4);
} }
} }
r = MEMTX_OK;
}
if (result) {
*result = r;
} }
} }
void stl_phys_notdirty(AddressSpace *as, hwaddr addr, uint32_t val)
{
address_space_stl_notdirty(as, addr, val, MEMTXATTRS_UNSPECIFIED, NULL);
}
/* warning: addr must be aligned */ /* warning: addr must be aligned */
static inline void stl_phys_internal(AddressSpace *as, static inline void address_space_stl_internal(AddressSpace *as,
hwaddr addr, uint32_t val, hwaddr addr, uint32_t val,
enum device_endian endian) MemTxAttrs attrs,
MemTxResult *result,
enum device_endian endian)
{ {
uint8_t *ptr; uint8_t *ptr;
MemoryRegion *mr; MemoryRegion *mr;
hwaddr l = 4; hwaddr l = 4;
hwaddr addr1; hwaddr addr1;
MemTxResult r;
mr = address_space_translate(as, addr, &addr1, &l, mr = address_space_translate(as, addr, &addr1, &l,
true); true);
@ -2892,7 +3040,7 @@ static inline void stl_phys_internal(AddressSpace *as,
val = bswap32(val); val = bswap32(val);
} }
#endif #endif
io_mem_write(mr, addr1, val, 4); r = memory_region_dispatch_write(mr, addr1, val, 4, attrs);
} else { } else {
/* RAM case */ /* RAM case */
addr1 += memory_region_get_ram_addr(mr) & TARGET_PAGE_MASK; addr1 += memory_region_get_ram_addr(mr) & TARGET_PAGE_MASK;
@ -2909,40 +3057,79 @@ static inline void stl_phys_internal(AddressSpace *as,
break; break;
} }
invalidate_and_set_dirty(addr1, 4); invalidate_and_set_dirty(addr1, 4);
r = MEMTX_OK;
} }
if (result) {
*result = r;
}
}
void address_space_stl(AddressSpace *as, hwaddr addr, uint32_t val,
MemTxAttrs attrs, MemTxResult *result)
{
address_space_stl_internal(as, addr, val, attrs, result,
DEVICE_NATIVE_ENDIAN);
}
void address_space_stl_le(AddressSpace *as, hwaddr addr, uint32_t val,
MemTxAttrs attrs, MemTxResult *result)
{
address_space_stl_internal(as, addr, val, attrs, result,
DEVICE_LITTLE_ENDIAN);
}
void address_space_stl_be(AddressSpace *as, hwaddr addr, uint32_t val,
MemTxAttrs attrs, MemTxResult *result)
{
address_space_stl_internal(as, addr, val, attrs, result,
DEVICE_BIG_ENDIAN);
} }
void stl_phys(AddressSpace *as, hwaddr addr, uint32_t val) void stl_phys(AddressSpace *as, hwaddr addr, uint32_t val)
{ {
stl_phys_internal(as, addr, val, DEVICE_NATIVE_ENDIAN); address_space_stl(as, addr, val, MEMTXATTRS_UNSPECIFIED, NULL);
} }
void stl_le_phys(AddressSpace *as, hwaddr addr, uint32_t val) void stl_le_phys(AddressSpace *as, hwaddr addr, uint32_t val)
{ {
stl_phys_internal(as, addr, val, DEVICE_LITTLE_ENDIAN); address_space_stl_le(as, addr, val, MEMTXATTRS_UNSPECIFIED, NULL);
} }
void stl_be_phys(AddressSpace *as, hwaddr addr, uint32_t val) void stl_be_phys(AddressSpace *as, hwaddr addr, uint32_t val)
{ {
stl_phys_internal(as, addr, val, DEVICE_BIG_ENDIAN); address_space_stl_be(as, addr, val, MEMTXATTRS_UNSPECIFIED, NULL);
} }
/* XXX: optimize */ /* XXX: optimize */
void stb_phys(AddressSpace *as, hwaddr addr, uint32_t val) void address_space_stb(AddressSpace *as, hwaddr addr, uint32_t val,
MemTxAttrs attrs, MemTxResult *result)
{ {
uint8_t v = val; uint8_t v = val;
address_space_rw(as, addr, &v, 1, 1); MemTxResult r;
r = address_space_rw(as, addr, attrs, &v, 1, 1);
if (result) {
*result = r;
}
}
void stb_phys(AddressSpace *as, hwaddr addr, uint32_t val)
{
address_space_stb(as, addr, val, MEMTXATTRS_UNSPECIFIED, NULL);
} }
/* warning: addr must be aligned */ /* warning: addr must be aligned */
static inline void stw_phys_internal(AddressSpace *as, static inline void address_space_stw_internal(AddressSpace *as,
hwaddr addr, uint32_t val, hwaddr addr, uint32_t val,
enum device_endian endian) MemTxAttrs attrs,
MemTxResult *result,
enum device_endian endian)
{ {
uint8_t *ptr; uint8_t *ptr;
MemoryRegion *mr; MemoryRegion *mr;
hwaddr l = 2; hwaddr l = 2;
hwaddr addr1; hwaddr addr1;
MemTxResult r;
mr = address_space_translate(as, addr, &addr1, &l, true); mr = address_space_translate(as, addr, &addr1, &l, true);
if (l < 2 || !memory_access_is_direct(mr, true)) { if (l < 2 || !memory_access_is_direct(mr, true)) {
@ -2955,7 +3142,7 @@ static inline void stw_phys_internal(AddressSpace *as,
val = bswap16(val); val = bswap16(val);
} }
#endif #endif
io_mem_write(mr, addr1, val, 2); r = memory_region_dispatch_write(mr, addr1, val, 2, attrs);
} else { } else {
/* RAM case */ /* RAM case */
addr1 += memory_region_get_ram_addr(mr) & TARGET_PAGE_MASK; addr1 += memory_region_get_ram_addr(mr) & TARGET_PAGE_MASK;
@ -2972,41 +3159,95 @@ static inline void stw_phys_internal(AddressSpace *as,
break; break;
} }
invalidate_and_set_dirty(addr1, 2); invalidate_and_set_dirty(addr1, 2);
r = MEMTX_OK;
} }
if (result) {
*result = r;
}
}
void address_space_stw(AddressSpace *as, hwaddr addr, uint32_t val,
MemTxAttrs attrs, MemTxResult *result)
{
address_space_stw_internal(as, addr, val, attrs, result,
DEVICE_NATIVE_ENDIAN);
}
void address_space_stw_le(AddressSpace *as, hwaddr addr, uint32_t val,
MemTxAttrs attrs, MemTxResult *result)
{
address_space_stw_internal(as, addr, val, attrs, result,
DEVICE_LITTLE_ENDIAN);
}
void address_space_stw_be(AddressSpace *as, hwaddr addr, uint32_t val,
MemTxAttrs attrs, MemTxResult *result)
{
address_space_stw_internal(as, addr, val, attrs, result,
DEVICE_BIG_ENDIAN);
} }
void stw_phys(AddressSpace *as, hwaddr addr, uint32_t val) void stw_phys(AddressSpace *as, hwaddr addr, uint32_t val)
{ {
stw_phys_internal(as, addr, val, DEVICE_NATIVE_ENDIAN); address_space_stw(as, addr, val, MEMTXATTRS_UNSPECIFIED, NULL);
} }
void stw_le_phys(AddressSpace *as, hwaddr addr, uint32_t val) void stw_le_phys(AddressSpace *as, hwaddr addr, uint32_t val)
{ {
stw_phys_internal(as, addr, val, DEVICE_LITTLE_ENDIAN); address_space_stw_le(as, addr, val, MEMTXATTRS_UNSPECIFIED, NULL);
} }
void stw_be_phys(AddressSpace *as, hwaddr addr, uint32_t val) void stw_be_phys(AddressSpace *as, hwaddr addr, uint32_t val)
{ {
stw_phys_internal(as, addr, val, DEVICE_BIG_ENDIAN); address_space_stw_be(as, addr, val, MEMTXATTRS_UNSPECIFIED, NULL);
} }
/* XXX: optimize */ /* XXX: optimize */
void address_space_stq(AddressSpace *as, hwaddr addr, uint64_t val,
MemTxAttrs attrs, MemTxResult *result)
{
MemTxResult r;
val = tswap64(val);
r = address_space_rw(as, addr, attrs, (void *) &val, 8, 1);
if (result) {
*result = r;
}
}
void address_space_stq_le(AddressSpace *as, hwaddr addr, uint64_t val,
MemTxAttrs attrs, MemTxResult *result)
{
MemTxResult r;
val = cpu_to_le64(val);
r = address_space_rw(as, addr, attrs, (void *) &val, 8, 1);
if (result) {
*result = r;
}
}
void address_space_stq_be(AddressSpace *as, hwaddr addr, uint64_t val,
MemTxAttrs attrs, MemTxResult *result)
{
MemTxResult r;
val = cpu_to_be64(val);
r = address_space_rw(as, addr, attrs, (void *) &val, 8, 1);
if (result) {
*result = r;
}
}
void stq_phys(AddressSpace *as, hwaddr addr, uint64_t val) void stq_phys(AddressSpace *as, hwaddr addr, uint64_t val)
{ {
val = tswap64(val); address_space_stq(as, addr, val, MEMTXATTRS_UNSPECIFIED, NULL);
address_space_rw(as, addr, (void *) &val, 8, 1);
} }
void stq_le_phys(AddressSpace *as, hwaddr addr, uint64_t val) void stq_le_phys(AddressSpace *as, hwaddr addr, uint64_t val)
{ {
val = cpu_to_le64(val); address_space_stq_le(as, addr, val, MEMTXATTRS_UNSPECIFIED, NULL);
address_space_rw(as, addr, (void *) &val, 8, 1);
} }
void stq_be_phys(AddressSpace *as, hwaddr addr, uint64_t val) void stq_be_phys(AddressSpace *as, hwaddr addr, uint64_t val)
{ {
val = cpu_to_be64(val); address_space_stq_be(as, addr, val, MEMTXATTRS_UNSPECIFIED, NULL);
address_space_rw(as, addr, (void *) &val, 8, 1);
} }
/* virtual memory access for debug (includes writing to ROM) */ /* virtual memory access for debug (includes writing to ROM) */
@ -3030,7 +3271,8 @@ int cpu_memory_rw_debug(CPUState *cpu, target_ulong addr,
if (is_write) { if (is_write) {
cpu_physical_memory_write_rom(cpu->as, phys_addr, buf, l); cpu_physical_memory_write_rom(cpu->as, phys_addr, buf, l);
} else { } else {
address_space_rw(cpu->as, phys_addr, buf, l, 0); address_space_rw(cpu->as, phys_addr, MEMTXATTRS_UNSPECIFIED,
buf, l, 0);
} }
len -= l; len -= l;
buf += l; buf += l;

View File

@ -157,9 +157,12 @@ static void clipper_init(MachineState *machine)
load_image_targphys(initrd_filename, initrd_base, load_image_targphys(initrd_filename, initrd_base,
ram_size - initrd_base); ram_size - initrd_base);
stq_phys(&address_space_memory, address_space_stq(&address_space_memory, param_offset + 0x100,
param_offset + 0x100, initrd_base + 0xfffffc0000000000ULL); initrd_base + 0xfffffc0000000000ULL,
stq_phys(&address_space_memory, param_offset + 0x108, initrd_size); MEMTXATTRS_UNSPECIFIED,
NULL);
address_space_stq(&address_space_memory, param_offset + 0x108,
initrd_size, MEMTXATTRS_UNSPECIFIED, NULL);
} }
} }
} }

View File

@ -613,7 +613,8 @@ static bool make_iommu_tlbe(hwaddr taddr, hwaddr mask, IOMMUTLBEntry *ret)
translation, given the address of the PTE. */ translation, given the address of the PTE. */
static bool pte_translate(hwaddr pte_addr, IOMMUTLBEntry *ret) static bool pte_translate(hwaddr pte_addr, IOMMUTLBEntry *ret)
{ {
uint64_t pte = ldq_phys(&address_space_memory, pte_addr); uint64_t pte = address_space_ldq(&address_space_memory, pte_addr,
MEMTXATTRS_UNSPECIFIED, NULL);
/* Check valid bit. */ /* Check valid bit. */
if ((pte & 1) == 0) { if ((pte & 1) == 0) {

View File

@ -170,7 +170,8 @@ static void default_reset_secondary(ARMCPU *cpu,
{ {
CPUARMState *env = &cpu->env; CPUARMState *env = &cpu->env;
stl_phys_notdirty(&address_space_memory, info->smp_bootreg_addr, 0); address_space_stl_notdirty(&address_space_memory, info->smp_bootreg_addr,
0, MEMTXATTRS_UNSPECIFIED, NULL);
env->regs[15] = info->smp_loader_start; env->regs[15] = info->smp_loader_start;
} }
@ -180,7 +181,8 @@ static inline bool have_dtb(const struct arm_boot_info *info)
} }
#define WRITE_WORD(p, value) do { \ #define WRITE_WORD(p, value) do { \
stl_phys_notdirty(&address_space_memory, p, value); \ address_space_stl_notdirty(&address_space_memory, p, value, \
MEMTXATTRS_UNSPECIFIED, NULL); \
p += 4; \ p += 4; \
} while (0) } while (0)

View File

@ -69,11 +69,17 @@ static void hb_reset_secondary(ARMCPU *cpu, const struct arm_boot_info *info)
switch (info->nb_cpus) { switch (info->nb_cpus) {
case 4: case 4:
stl_phys_notdirty(&address_space_memory, SMP_BOOT_REG + 0x30, 0); address_space_stl_notdirty(&address_space_memory,
SMP_BOOT_REG + 0x30, 0,
MEMTXATTRS_UNSPECIFIED, NULL);
case 3: case 3:
stl_phys_notdirty(&address_space_memory, SMP_BOOT_REG + 0x20, 0); address_space_stl_notdirty(&address_space_memory,
SMP_BOOT_REG + 0x20, 0,
MEMTXATTRS_UNSPECIFIED, NULL);
case 2: case 2:
stl_phys_notdirty(&address_space_memory, SMP_BOOT_REG + 0x10, 0); address_space_stl_notdirty(&address_space_memory,
SMP_BOOT_REG + 0x10, 0,
MEMTXATTRS_UNSPECIFIED, NULL);
env->regs[15] = SMP_BOOT_ADDR; env->regs[15] = SMP_BOOT_ADDR;
break; break;
default: default:

View File

@ -274,7 +274,7 @@ static void pxa2xx_pwrmode_write(CPUARMState *env, const ARMCPRegInfo *ri,
s->cpu->env.uncached_cpsr = ARM_CPU_MODE_SVC; s->cpu->env.uncached_cpsr = ARM_CPU_MODE_SVC;
s->cpu->env.daif = PSTATE_A | PSTATE_F | PSTATE_I; s->cpu->env.daif = PSTATE_A | PSTATE_F | PSTATE_I;
s->cpu->env.cp15.sctlr_ns = 0; s->cpu->env.cp15.sctlr_ns = 0;
s->cpu->env.cp15.c1_coproc = 0; s->cpu->env.cp15.cpacr_el1 = 0;
s->cpu->env.cp15.ttbr0_el[1] = 0; s->cpu->env.cp15.ttbr0_el[1] = 0;
s->cpu->env.cp15.dacr_ns = 0; s->cpu->env.cp15.dacr_ns = 0;
s->pm_regs[PSSR >> 2] |= 0x8; /* Set STS */ s->pm_regs[PSSR >> 2] |= 0x8; /* Set STS */

View File

@ -205,10 +205,22 @@ again:
if (size == 0) { if (size == 0) {
/* Transfer complete. */ /* Transfer complete. */
if (ch->lli) { if (ch->lli) {
ch->src = ldl_le_phys(&address_space_memory, ch->lli); ch->src = address_space_ldl_le(&address_space_memory,
ch->dest = ldl_le_phys(&address_space_memory, ch->lli + 4); ch->lli,
ch->ctrl = ldl_le_phys(&address_space_memory, ch->lli + 12); MEMTXATTRS_UNSPECIFIED,
ch->lli = ldl_le_phys(&address_space_memory, ch->lli + 8); NULL);
ch->dest = address_space_ldl_le(&address_space_memory,
ch->lli + 4,
MEMTXATTRS_UNSPECIFIED,
NULL);
ch->ctrl = address_space_ldl_le(&address_space_memory,
ch->lli + 12,
MEMTXATTRS_UNSPECIFIED,
NULL);
ch->lli = address_space_ldl_le(&address_space_memory,
ch->lli + 8,
MEMTXATTRS_UNSPECIFIED,
NULL);
} else { } else {
ch->conf &= ~PL080_CCONF_E; ch->conf &= ~PL080_CCONF_E;
} }

View File

@ -263,7 +263,8 @@ static uint32_t iommu_page_get_flags(IOMMUState *s, hwaddr addr)
iopte = s->regs[IOMMU_BASE] << 4; iopte = s->regs[IOMMU_BASE] << 4;
addr &= ~s->iostart; addr &= ~s->iostart;
iopte += (addr >> (IOMMU_PAGE_SHIFT - 2)) & ~3; iopte += (addr >> (IOMMU_PAGE_SHIFT - 2)) & ~3;
ret = ldl_be_phys(&address_space_memory, iopte); ret = address_space_ldl_be(&address_space_memory, iopte,
MEMTXATTRS_UNSPECIFIED, NULL);
trace_sun4m_iommu_page_get_flags(pa, iopte, ret); trace_sun4m_iommu_page_get_flags(pa, iopte, ret);
return ret; return ret;
} }

View File

@ -246,7 +246,8 @@ static void vtd_generate_interrupt(IntelIOMMUState *s, hwaddr mesg_addr_reg,
data = vtd_get_long_raw(s, mesg_data_reg); data = vtd_get_long_raw(s, mesg_data_reg);
VTD_DPRINTF(FLOG, "msi: addr 0x%"PRIx64 " data 0x%"PRIx32, addr, data); VTD_DPRINTF(FLOG, "msi: addr 0x%"PRIx64 " data 0x%"PRIx32, addr, data);
stl_le_phys(&address_space_memory, addr, data); address_space_stl_le(&address_space_memory, addr, data,
MEMTXATTRS_UNSPECIFIED, NULL);
} }
/* Generate a fault event to software via MSI if conditions are met. /* Generate a fault event to software via MSI if conditions are met.

View File

@ -61,7 +61,8 @@ static void main_cpu_reset(void *opaque)
static uint64_t rtc_read(void *opaque, hwaddr addr, unsigned size) static uint64_t rtc_read(void *opaque, hwaddr addr, unsigned size)
{ {
uint8_t val; uint8_t val;
address_space_read(&address_space_memory, 0x90000071, &val, 1); address_space_read(&address_space_memory, 0x90000071,
MEMTXATTRS_UNSPECIFIED, &val, 1);
return val; return val;
} }
@ -69,7 +70,8 @@ static void rtc_write(void *opaque, hwaddr addr,
uint64_t val, unsigned size) uint64_t val, unsigned size)
{ {
uint8_t buf = val & 0xff; uint8_t buf = val & 0xff;
address_space_write(&address_space_memory, 0x90000071, &buf, 1); address_space_write(&address_space_memory, 0x90000071,
MEMTXATTRS_UNSPECIFIED, &buf, 1);
} }
static const MemoryRegionOps rtc_ops = { static const MemoryRegionOps rtc_ops = {

View File

@ -289,7 +289,8 @@ static IOMMUTLBEntry pbm_translate_iommu(MemoryRegion *iommu, hwaddr addr,
} }
} }
tte = ldq_be_phys(&address_space_memory, baseaddr + offset); tte = address_space_ldq_be(&address_space_memory, baseaddr + offset,
MEMTXATTRS_UNSPECIFIED, NULL);
if (!(tte & IOMMU_TTE_DATA_V)) { if (!(tte & IOMMU_TTE_DATA_V)) {
/* Invalid mapping */ /* Invalid mapping */

View File

@ -140,7 +140,8 @@ static uint64_t raven_io_read(void *opaque, hwaddr addr,
uint8_t buf[4]; uint8_t buf[4];
addr = raven_io_address(s, addr); addr = raven_io_address(s, addr);
address_space_read(&s->pci_io_as, addr + 0x80000000, buf, size); address_space_read(&s->pci_io_as, addr + 0x80000000,
MEMTXATTRS_UNSPECIFIED, buf, size);
if (size == 1) { if (size == 1) {
return buf[0]; return buf[0];
@ -171,7 +172,8 @@ static void raven_io_write(void *opaque, hwaddr addr,
g_assert_not_reached(); g_assert_not_reached();
} }
address_space_write(&s->pci_io_as, addr + 0x80000000, buf, size); address_space_write(&s->pci_io_as, addr + 0x80000000,
MEMTXATTRS_UNSPECIFIED, buf, size);
} }
static const MemoryRegionOps raven_io_ops = { static const MemoryRegionOps raven_io_ops = {

View File

@ -291,7 +291,8 @@ void msi_notify(PCIDevice *dev, unsigned int vector)
"notify vector 0x%x" "notify vector 0x%x"
" address: 0x%"PRIx64" data: 0x%"PRIx32"\n", " address: 0x%"PRIx64" data: 0x%"PRIx32"\n",
vector, msg.address, msg.data); vector, msg.address, msg.data);
stl_le_phys(&dev->bus_master_as, msg.address, msg.data); address_space_stl_le(&dev->bus_master_as, msg.address, msg.data,
MEMTXATTRS_UNSPECIFIED, NULL);
} }
/* Normally called by pci_default_write_config(). */ /* Normally called by pci_default_write_config(). */

View File

@ -435,7 +435,8 @@ void msix_notify(PCIDevice *dev, unsigned vector)
msg = msix_get_message(dev, vector); msg = msix_get_message(dev, vector);
stl_le_phys(&dev->bus_master_as, msg.address, msg.data); address_space_stl_le(&dev->bus_master_as, msg.address, msg.data,
MEMTXATTRS_UNSPECIFIED, NULL);
} }
void msix_reset(PCIDevice *dev) void msix_reset(PCIDevice *dev)

View File

@ -745,20 +745,27 @@ static void css_update_chnmon(SubchDev *sch)
/* Format 1, per-subchannel area. */ /* Format 1, per-subchannel area. */
uint32_t count; uint32_t count;
count = ldl_phys(&address_space_memory, sch->curr_status.mba); count = address_space_ldl(&address_space_memory,
sch->curr_status.mba,
MEMTXATTRS_UNSPECIFIED,
NULL);
count++; count++;
stl_phys(&address_space_memory, sch->curr_status.mba, count); address_space_stl(&address_space_memory, sch->curr_status.mba, count,
MEMTXATTRS_UNSPECIFIED, NULL);
} else { } else {
/* Format 0, global area. */ /* Format 0, global area. */
uint32_t offset; uint32_t offset;
uint16_t count; uint16_t count;
offset = sch->curr_status.pmcw.mbi << 5; offset = sch->curr_status.pmcw.mbi << 5;
count = lduw_phys(&address_space_memory, count = address_space_lduw(&address_space_memory,
channel_subsys->chnmon_area + offset); channel_subsys->chnmon_area + offset,
MEMTXATTRS_UNSPECIFIED,
NULL);
count++; count++;
stw_phys(&address_space_memory, address_space_stw(&address_space_memory,
channel_subsys->chnmon_area + offset, count); channel_subsys->chnmon_area + offset, count,
MEMTXATTRS_UNSPECIFIED, NULL);
} }
} }

View File

@ -278,7 +278,8 @@ static uint64_t s390_guest_io_table_walk(uint64_t guest_iota,
px = calc_px(guest_dma_address); px = calc_px(guest_dma_address);
sto_a = guest_iota + rtx * sizeof(uint64_t); sto_a = guest_iota + rtx * sizeof(uint64_t);
sto = ldq_phys(&address_space_memory, sto_a); sto = address_space_ldq(&address_space_memory, sto_a,
MEMTXATTRS_UNSPECIFIED, NULL);
sto = get_rt_sto(sto); sto = get_rt_sto(sto);
if (!sto) { if (!sto) {
pte = 0; pte = 0;
@ -286,7 +287,8 @@ static uint64_t s390_guest_io_table_walk(uint64_t guest_iota,
} }
pto_a = sto + sx * sizeof(uint64_t); pto_a = sto + sx * sizeof(uint64_t);
pto = ldq_phys(&address_space_memory, pto_a); pto = address_space_ldq(&address_space_memory, pto_a,
MEMTXATTRS_UNSPECIFIED, NULL);
pto = get_st_pto(pto); pto = get_st_pto(pto);
if (!pto) { if (!pto) {
pte = 0; pte = 0;
@ -294,7 +296,8 @@ static uint64_t s390_guest_io_table_walk(uint64_t guest_iota,
} }
px_a = pto + px * sizeof(uint64_t); px_a = pto + px * sizeof(uint64_t);
pte = ldq_phys(&address_space_memory, px_a); pte = address_space_ldq(&address_space_memory, px_a,
MEMTXATTRS_UNSPECIFIED, NULL);
out: out:
return pte; return pte;

View File

@ -331,7 +331,8 @@ int pcilg_service_call(S390CPU *cpu, uint8_t r1, uint8_t r2)
return 0; return 0;
} }
MemoryRegion *mr = pbdev->pdev->io_regions[pcias].memory; MemoryRegion *mr = pbdev->pdev->io_regions[pcias].memory;
io_mem_read(mr, offset, &data, len); memory_region_dispatch_read(mr, offset, &data, len,
MEMTXATTRS_UNSPECIFIED);
} else if (pcias == 15) { } else if (pcias == 15) {
if ((4 - (offset & 0x3)) < len) { if ((4 - (offset & 0x3)) < len) {
program_interrupt(env, PGM_OPERAND, 4); program_interrupt(env, PGM_OPERAND, 4);
@ -456,7 +457,8 @@ int pcistg_service_call(S390CPU *cpu, uint8_t r1, uint8_t r2)
mr = pbdev->pdev->io_regions[pcias].memory; mr = pbdev->pdev->io_regions[pcias].memory;
} }
io_mem_write(mr, offset, data, len); memory_region_dispatch_write(mr, offset, data, len,
MEMTXATTRS_UNSPECIFIED);
} else if (pcias == 15) { } else if (pcias == 15) {
if ((4 - (offset & 0x3)) < len) { if ((4 - (offset & 0x3)) < len) {
program_interrupt(env, PGM_OPERAND, 4); program_interrupt(env, PGM_OPERAND, 4);
@ -606,7 +608,9 @@ int pcistb_service_call(S390CPU *cpu, uint8_t r1, uint8_t r3, uint64_t gaddr)
} }
for (i = 0; i < len / 8; i++) { for (i = 0; i < len / 8; i++) {
io_mem_write(mr, env->regs[r3] + i * 8, ldq_p(buffer + i * 8), 8); memory_region_dispatch_write(mr, env->regs[r3] + i * 8,
ldq_p(buffer + i * 8), 8,
MEMTXATTRS_UNSPECIFIED);
} }
setcc(cpu, ZPCI_PCI_LS_OK); setcc(cpu, ZPCI_PCI_LS_OK);

View File

@ -75,10 +75,12 @@ void s390_virtio_reset_idx(VirtIOS390Device *dev)
for (i = 0; i < num_vq; i++) { for (i = 0; i < num_vq; i++) {
idx_addr = virtio_queue_get_avail_addr(dev->vdev, i) + idx_addr = virtio_queue_get_avail_addr(dev->vdev, i) +
VIRTIO_VRING_AVAIL_IDX_OFFS; VIRTIO_VRING_AVAIL_IDX_OFFS;
stw_phys(&address_space_memory, idx_addr, 0); address_space_stw(&address_space_memory, idx_addr, 0,
MEMTXATTRS_UNSPECIFIED, NULL);
idx_addr = virtio_queue_get_used_addr(dev->vdev, i) + idx_addr = virtio_queue_get_used_addr(dev->vdev, i) +
VIRTIO_VRING_USED_IDX_OFFS; VIRTIO_VRING_USED_IDX_OFFS;
stw_phys(&address_space_memory, idx_addr, 0); address_space_stw(&address_space_memory, idx_addr, 0,
MEMTXATTRS_UNSPECIFIED, NULL);
} }
} }
@ -336,7 +338,8 @@ static uint64_t s390_virtio_device_vq_token(VirtIOS390Device *dev, int vq)
(vq * VIRTIO_VQCONFIG_LEN) + (vq * VIRTIO_VQCONFIG_LEN) +
VIRTIO_VQCONFIG_OFFS_TOKEN; VIRTIO_VQCONFIG_OFFS_TOKEN;
return ldq_be_phys(&address_space_memory, token_off); return address_space_ldq_be(&address_space_memory, token_off,
MEMTXATTRS_UNSPECIFIED, NULL);
} }
static ram_addr_t s390_virtio_device_num_vq(VirtIOS390Device *dev) static ram_addr_t s390_virtio_device_num_vq(VirtIOS390Device *dev)
@ -371,21 +374,33 @@ void s390_virtio_device_sync(VirtIOS390Device *dev)
virtio_reset(dev->vdev); virtio_reset(dev->vdev);
/* Sync dev space */ /* Sync dev space */
stb_phys(&address_space_memory, address_space_stb(&address_space_memory,
dev->dev_offs + VIRTIO_DEV_OFFS_TYPE, dev->vdev->device_id); dev->dev_offs + VIRTIO_DEV_OFFS_TYPE,
dev->vdev->device_id,
MEMTXATTRS_UNSPECIFIED,
NULL);
stb_phys(&address_space_memory, address_space_stb(&address_space_memory,
dev->dev_offs + VIRTIO_DEV_OFFS_NUM_VQ, dev->dev_offs + VIRTIO_DEV_OFFS_NUM_VQ,
s390_virtio_device_num_vq(dev)); s390_virtio_device_num_vq(dev),
stb_phys(&address_space_memory, MEMTXATTRS_UNSPECIFIED,
dev->dev_offs + VIRTIO_DEV_OFFS_FEATURE_LEN, dev->feat_len); NULL);
address_space_stb(&address_space_memory,
dev->dev_offs + VIRTIO_DEV_OFFS_FEATURE_LEN,
dev->feat_len,
MEMTXATTRS_UNSPECIFIED,
NULL);
stb_phys(&address_space_memory, address_space_stb(&address_space_memory,
dev->dev_offs + VIRTIO_DEV_OFFS_CONFIG_LEN, dev->vdev->config_len); dev->dev_offs + VIRTIO_DEV_OFFS_CONFIG_LEN,
dev->vdev->config_len,
MEMTXATTRS_UNSPECIFIED,
NULL);
num_vq = s390_virtio_device_num_vq(dev); num_vq = s390_virtio_device_num_vq(dev);
stb_phys(&address_space_memory, address_space_stb(&address_space_memory,
dev->dev_offs + VIRTIO_DEV_OFFS_NUM_VQ, num_vq); dev->dev_offs + VIRTIO_DEV_OFFS_NUM_VQ, num_vq,
MEMTXATTRS_UNSPECIFIED, NULL);
/* Sync virtqueues */ /* Sync virtqueues */
for (i = 0; i < num_vq; i++) { for (i = 0; i < num_vq; i++) {
@ -396,11 +411,14 @@ void s390_virtio_device_sync(VirtIOS390Device *dev)
vring = s390_virtio_next_ring(bus); vring = s390_virtio_next_ring(bus);
virtio_queue_set_addr(dev->vdev, i, vring); virtio_queue_set_addr(dev->vdev, i, vring);
virtio_queue_set_vector(dev->vdev, i, i); virtio_queue_set_vector(dev->vdev, i, i);
stq_be_phys(&address_space_memory, address_space_stq_be(&address_space_memory,
vq + VIRTIO_VQCONFIG_OFFS_ADDRESS, vring); vq + VIRTIO_VQCONFIG_OFFS_ADDRESS, vring,
stw_be_phys(&address_space_memory, MEMTXATTRS_UNSPECIFIED, NULL);
vq + VIRTIO_VQCONFIG_OFFS_NUM, address_space_stw_be(&address_space_memory,
virtio_queue_get_num(dev->vdev, i)); vq + VIRTIO_VQCONFIG_OFFS_NUM,
virtio_queue_get_num(dev->vdev, i),
MEMTXATTRS_UNSPECIFIED,
NULL);
} }
cur_offs = dev->dev_offs; cur_offs = dev->dev_offs;
@ -408,7 +426,8 @@ void s390_virtio_device_sync(VirtIOS390Device *dev)
cur_offs += num_vq * VIRTIO_VQCONFIG_LEN; cur_offs += num_vq * VIRTIO_VQCONFIG_LEN;
/* Sync feature bitmap */ /* Sync feature bitmap */
stl_le_phys(&address_space_memory, cur_offs, dev->host_features); address_space_stl_le(&address_space_memory, cur_offs, dev->host_features,
MEMTXATTRS_UNSPECIFIED, NULL);
dev->feat_offs = cur_offs + dev->feat_len; dev->feat_offs = cur_offs + dev->feat_len;
cur_offs += dev->feat_len * 2; cur_offs += dev->feat_len * 2;
@ -426,12 +445,16 @@ void s390_virtio_device_update_status(VirtIOS390Device *dev)
VirtIODevice *vdev = dev->vdev; VirtIODevice *vdev = dev->vdev;
uint32_t features; uint32_t features;
virtio_set_status(vdev, ldub_phys(&address_space_memory, virtio_set_status(vdev,
dev->dev_offs + VIRTIO_DEV_OFFS_STATUS)); address_space_ldub(&address_space_memory,
dev->dev_offs + VIRTIO_DEV_OFFS_STATUS,
MEMTXATTRS_UNSPECIFIED, NULL));
/* Update guest supported feature bitmap */ /* Update guest supported feature bitmap */
features = bswap32(ldl_be_phys(&address_space_memory, dev->feat_offs)); features = bswap32(address_space_ldl_be(&address_space_memory,
dev->feat_offs,
MEMTXATTRS_UNSPECIFIED, NULL));
virtio_set_features(vdev, features); virtio_set_features(vdev, features);
} }

View File

@ -97,7 +97,9 @@ static int s390_virtio_hcall_reset(const uint64_t *args)
return -EINVAL; return -EINVAL;
} }
virtio_reset(dev->vdev); virtio_reset(dev->vdev);
stb_phys(&address_space_memory, dev->dev_offs + VIRTIO_DEV_OFFS_STATUS, 0); address_space_stb(&address_space_memory,
dev->dev_offs + VIRTIO_DEV_OFFS_STATUS, 0,
MEMTXATTRS_UNSPECIFIED, NULL);
s390_virtio_device_sync(dev); s390_virtio_device_sync(dev);
s390_virtio_reset_idx(dev); s390_virtio_reset_idx(dev);

View File

@ -335,16 +335,23 @@ static int virtio_ccw_cb(SubchDev *sch, CCW1 ccw)
if (!ccw.cda) { if (!ccw.cda) {
ret = -EFAULT; ret = -EFAULT;
} else { } else {
info.queue = ldq_phys(&address_space_memory, ccw.cda); info.queue = address_space_ldq(&address_space_memory, ccw.cda,
info.align = ldl_phys(&address_space_memory, MEMTXATTRS_UNSPECIFIED, NULL);
ccw.cda + sizeof(info.queue)); info.align = address_space_ldl(&address_space_memory,
info.index = lduw_phys(&address_space_memory, ccw.cda + sizeof(info.queue),
ccw.cda + sizeof(info.queue) MEMTXATTRS_UNSPECIFIED,
+ sizeof(info.align)); NULL);
info.num = lduw_phys(&address_space_memory, info.index = address_space_lduw(&address_space_memory,
ccw.cda + sizeof(info.queue) ccw.cda + sizeof(info.queue)
+ sizeof(info.align) + sizeof(info.align),
+ sizeof(info.index)); MEMTXATTRS_UNSPECIFIED,
NULL);
info.num = address_space_lduw(&address_space_memory,
ccw.cda + sizeof(info.queue)
+ sizeof(info.align)
+ sizeof(info.index),
MEMTXATTRS_UNSPECIFIED,
NULL);
ret = virtio_ccw_set_vqs(sch, info.queue, info.align, info.index, ret = virtio_ccw_set_vqs(sch, info.queue, info.align, info.index,
info.num); info.num);
sch->curr_status.scsw.count = 0; sch->curr_status.scsw.count = 0;
@ -369,15 +376,20 @@ static int virtio_ccw_cb(SubchDev *sch, CCW1 ccw)
if (!ccw.cda) { if (!ccw.cda) {
ret = -EFAULT; ret = -EFAULT;
} else { } else {
features.index = ldub_phys(&address_space_memory, features.index = address_space_ldub(&address_space_memory,
ccw.cda + sizeof(features.features)); ccw.cda
+ sizeof(features.features),
MEMTXATTRS_UNSPECIFIED,
NULL);
if (features.index < ARRAY_SIZE(dev->host_features)) { if (features.index < ARRAY_SIZE(dev->host_features)) {
features.features = dev->host_features[features.index]; features.features = dev->host_features[features.index];
} else { } else {
/* Return zeroes if the guest supports more feature bits. */ /* Return zeroes if the guest supports more feature bits. */
features.features = 0; features.features = 0;
} }
stl_le_phys(&address_space_memory, ccw.cda, features.features); address_space_stl_le(&address_space_memory, ccw.cda,
features.features, MEMTXATTRS_UNSPECIFIED,
NULL);
sch->curr_status.scsw.count = ccw.count - sizeof(features); sch->curr_status.scsw.count = ccw.count - sizeof(features);
ret = 0; ret = 0;
} }
@ -396,9 +408,15 @@ static int virtio_ccw_cb(SubchDev *sch, CCW1 ccw)
if (!ccw.cda) { if (!ccw.cda) {
ret = -EFAULT; ret = -EFAULT;
} else { } else {
features.index = ldub_phys(&address_space_memory, features.index = address_space_ldub(&address_space_memory,
ccw.cda + sizeof(features.features)); ccw.cda
features.features = ldl_le_phys(&address_space_memory, ccw.cda); + sizeof(features.features),
MEMTXATTRS_UNSPECIFIED,
NULL);
features.features = address_space_ldl_le(&address_space_memory,
ccw.cda,
MEMTXATTRS_UNSPECIFIED,
NULL);
if (features.index < ARRAY_SIZE(dev->host_features)) { if (features.index < ARRAY_SIZE(dev->host_features)) {
virtio_set_features(vdev, features.features); virtio_set_features(vdev, features.features);
} else { } else {
@ -474,7 +492,8 @@ static int virtio_ccw_cb(SubchDev *sch, CCW1 ccw)
if (!ccw.cda) { if (!ccw.cda) {
ret = -EFAULT; ret = -EFAULT;
} else { } else {
status = ldub_phys(&address_space_memory, ccw.cda); status = address_space_ldub(&address_space_memory, ccw.cda,
MEMTXATTRS_UNSPECIFIED, NULL);
if (!(status & VIRTIO_CONFIG_S_DRIVER_OK)) { if (!(status & VIRTIO_CONFIG_S_DRIVER_OK)) {
virtio_ccw_stop_ioeventfd(dev); virtio_ccw_stop_ioeventfd(dev);
} }
@ -508,7 +527,8 @@ static int virtio_ccw_cb(SubchDev *sch, CCW1 ccw)
if (!ccw.cda) { if (!ccw.cda) {
ret = -EFAULT; ret = -EFAULT;
} else { } else {
indicators = ldq_be_phys(&address_space_memory, ccw.cda); indicators = address_space_ldq_be(&address_space_memory, ccw.cda,
MEMTXATTRS_UNSPECIFIED, NULL);
dev->indicators = get_indicator(indicators, sizeof(uint64_t)); dev->indicators = get_indicator(indicators, sizeof(uint64_t));
sch->curr_status.scsw.count = ccw.count - sizeof(indicators); sch->curr_status.scsw.count = ccw.count - sizeof(indicators);
ret = 0; ret = 0;
@ -528,7 +548,8 @@ static int virtio_ccw_cb(SubchDev *sch, CCW1 ccw)
if (!ccw.cda) { if (!ccw.cda) {
ret = -EFAULT; ret = -EFAULT;
} else { } else {
indicators = ldq_be_phys(&address_space_memory, ccw.cda); indicators = address_space_ldq_be(&address_space_memory, ccw.cda,
MEMTXATTRS_UNSPECIFIED, NULL);
dev->indicators2 = get_indicator(indicators, sizeof(uint64_t)); dev->indicators2 = get_indicator(indicators, sizeof(uint64_t));
sch->curr_status.scsw.count = ccw.count - sizeof(indicators); sch->curr_status.scsw.count = ccw.count - sizeof(indicators);
ret = 0; ret = 0;
@ -548,15 +569,21 @@ static int virtio_ccw_cb(SubchDev *sch, CCW1 ccw)
if (!ccw.cda) { if (!ccw.cda) {
ret = -EFAULT; ret = -EFAULT;
} else { } else {
vq_config.index = lduw_be_phys(&address_space_memory, ccw.cda); vq_config.index = address_space_lduw_be(&address_space_memory,
ccw.cda,
MEMTXATTRS_UNSPECIFIED,
NULL);
if (vq_config.index >= VIRTIO_PCI_QUEUE_MAX) { if (vq_config.index >= VIRTIO_PCI_QUEUE_MAX) {
ret = -EINVAL; ret = -EINVAL;
break; break;
} }
vq_config.num_max = virtio_queue_get_num(vdev, vq_config.num_max = virtio_queue_get_num(vdev,
vq_config.index); vq_config.index);
stw_be_phys(&address_space_memory, address_space_stw_be(&address_space_memory,
ccw.cda + sizeof(vq_config.index), vq_config.num_max); ccw.cda + sizeof(vq_config.index),
vq_config.num_max,
MEMTXATTRS_UNSPECIFIED,
NULL);
sch->curr_status.scsw.count = ccw.count - sizeof(vq_config); sch->curr_status.scsw.count = ccw.count - sizeof(vq_config);
ret = 0; ret = 0;
} }
@ -1068,9 +1095,13 @@ static void virtio_ccw_notify(DeviceState *d, uint16_t vector)
css_adapter_interrupt(dev->thinint_isc); css_adapter_interrupt(dev->thinint_isc);
} }
} else { } else {
indicators = ldq_phys(&address_space_memory, dev->indicators->addr); indicators = address_space_ldq(&address_space_memory,
dev->indicators->addr,
MEMTXATTRS_UNSPECIFIED,
NULL);
indicators |= 1ULL << vector; indicators |= 1ULL << vector;
stq_phys(&address_space_memory, dev->indicators->addr, indicators); address_space_stq(&address_space_memory, dev->indicators->addr,
indicators, MEMTXATTRS_UNSPECIFIED, NULL);
css_conditional_io_interrupt(sch); css_conditional_io_interrupt(sch);
} }
} else { } else {
@ -1078,9 +1109,13 @@ static void virtio_ccw_notify(DeviceState *d, uint16_t vector)
return; return;
} }
vector = 0; vector = 0;
indicators = ldq_phys(&address_space_memory, dev->indicators2->addr); indicators = address_space_ldq(&address_space_memory,
dev->indicators2->addr,
MEMTXATTRS_UNSPECIFIED,
NULL);
indicators |= 1ULL << vector; indicators |= 1ULL << vector;
stq_phys(&address_space_memory, dev->indicators2->addr, indicators); address_space_stq(&address_space_memory, dev->indicators2->addr,
indicators, MEMTXATTRS_UNSPECIFIED, NULL);
css_conditional_io_interrupt(sch); css_conditional_io_interrupt(sch);
} }
} }

View File

@ -318,8 +318,10 @@ static void r2d_init(MachineState *machine)
} }
/* initialization which should be done by firmware */ /* initialization which should be done by firmware */
stl_phys(&address_space_memory, SH7750_BCR1, 1<<3); /* cs3 SDRAM */ address_space_stl(&address_space_memory, SH7750_BCR1, 1 << 3,
stw_phys(&address_space_memory, SH7750_BCR2, 3<<(3*2)); /* cs3 32bit */ MEMTXATTRS_UNSPECIFIED, NULL); /* cs3 SDRAM */
address_space_stw(&address_space_memory, SH7750_BCR2, 3 << (3 * 2),
MEMTXATTRS_UNSPECIFIED, NULL); /* cs3 32bit */
reset_info->vector = (SDRAM_BASE + LINUX_LOAD_OFFSET) | 0xa0000000; /* Start from P2 area */ reset_info->vector = (SDRAM_BASE + LINUX_LOAD_OFFSET) | 0xa0000000; /* Start from P2 area */
} }

View File

@ -206,8 +206,9 @@ static void update_irq(struct HPETTimer *timer, int set)
} }
} }
} else if (timer_fsb_route(timer)) { } else if (timer_fsb_route(timer)) {
stl_le_phys(&address_space_memory, address_space_stl_le(&address_space_memory, timer->fsb >> 32,
timer->fsb >> 32, timer->fsb & 0xffffffff); timer->fsb & 0xffffffff, MEMTXATTRS_UNSPECIFIED,
NULL);
} else if (timer->config & HPET_TN_TYPE_LEVEL) { } else if (timer->config & HPET_TN_TYPE_LEVEL) {
s->isr |= mask; s->isr |= mask;
/* fold the ICH PIRQ# pin's internal inversion logic into hpet */ /* fold the ICH PIRQ# pin's internal inversion logic into hpet */

View File

@ -1531,9 +1531,12 @@ static uint64_t vfio_rtl8168_window_quirk_read(void *opaque,
return 0; return 0;
} }
io_mem_read(&vdev->pdev.msix_table_mmio, memory_region_dispatch_read(&vdev->pdev.msix_table_mmio,
(hwaddr)(quirk->data.address_match & 0xfff), (hwaddr)(quirk->data.address_match
&val, size); & 0xfff),
&val,
size,
MEMTXATTRS_UNSPECIFIED);
return val; return val;
} }
} }
@ -1561,9 +1564,12 @@ static void vfio_rtl8168_window_quirk_write(void *opaque, hwaddr addr,
memory_region_name(&quirk->mem), memory_region_name(&quirk->mem),
vdev->vbasedev.name); vdev->vbasedev.name);
io_mem_write(&vdev->pdev.msix_table_mmio, memory_region_dispatch_write(&vdev->pdev.msix_table_mmio,
(hwaddr)(quirk->data.address_match & 0xfff), (hwaddr)(quirk->data.address_match
data, size); & 0xfff),
data,
size,
MEMTXATTRS_UNSPECIFIED);
} }
quirk->data.flags = 1; quirk->data.flags = 1;

View File

@ -30,6 +30,7 @@
#ifndef CONFIG_USER_ONLY #ifndef CONFIG_USER_ONLY
#include "exec/hwaddr.h" #include "exec/hwaddr.h"
#endif #endif
#include "exec/memattrs.h"
#ifndef TARGET_LONG_BITS #ifndef TARGET_LONG_BITS
#error TARGET_LONG_BITS must be defined before including this header #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)); 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 \ #define CPU_COMMON_TLB \
/* The meaning of the MMU modes is defined in the target code. */ \ /* The meaning of the MMU modes is defined in the target code. */ \
CPUTLBEntry tlb_table[NB_MMU_MODES][CPU_TLB_SIZE]; \ CPUTLBEntry tlb_table[NB_MMU_MODES][CPU_TLB_SIZE]; \
CPUTLBEntry tlb_v_table[NB_MMU_MODES][CPU_VTLB_SIZE]; \ CPUTLBEntry tlb_v_table[NB_MMU_MODES][CPU_VTLB_SIZE]; \
hwaddr iotlb[NB_MMU_MODES][CPU_TLB_SIZE]; \ CPUIOTLBEntry iotlb[NB_MMU_MODES][CPU_TLB_SIZE]; \
hwaddr iotlb_v[NB_MMU_MODES][CPU_VTLB_SIZE]; \ CPUIOTLBEntry iotlb_v[NB_MMU_MODES][CPU_VTLB_SIZE]; \
target_ulong tlb_flush_addr; \ target_ulong tlb_flush_addr; \
target_ulong tlb_flush_mask; \ target_ulong tlb_flush_mask; \
target_ulong vtlb_index; \ target_ulong vtlb_index; \

View File

@ -105,6 +105,9 @@ void tlb_flush(CPUState *cpu, int flush_global);
void tlb_set_page(CPUState *cpu, target_ulong vaddr, void tlb_set_page(CPUState *cpu, target_ulong vaddr,
hwaddr paddr, int prot, hwaddr paddr, int prot,
int mmu_idx, target_ulong size); 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); void tb_invalidate_phys_addr(AddressSpace *as, hwaddr addr);
#else #else
static inline void tlb_flush_page(CPUState *cpu, target_ulong addr) 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, struct MemoryRegion *iotlb_to_region(CPUState *cpu,
hwaddr index); 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, void tlb_fill(CPUState *cpu, target_ulong addr, int is_write, int mmu_idx,
uintptr_t retaddr); uintptr_t retaddr);

45
include/exec/memattrs.h Normal file
View File

@ -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

View File

@ -28,6 +28,7 @@
#ifndef CONFIG_USER_ONLY #ifndef CONFIG_USER_ONLY
#include "exec/hwaddr.h" #include "exec/hwaddr.h"
#endif #endif
#include "exec/memattrs.h"
#include "qemu/queue.h" #include "qemu/queue.h"
#include "qemu/int128.h" #include "qemu/int128.h"
#include "qemu/notify.h" #include "qemu/notify.h"
@ -68,6 +69,16 @@ struct IOMMUTLBEntry {
IOMMUAccessFlags perm; 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 * Memory region callbacks
*/ */
@ -84,6 +95,17 @@ struct MemoryRegionOps {
uint64_t data, uint64_t data,
unsigned size); 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; enum device_endian endianness;
/* Guest-visible constraints: */ /* Guest-visible constraints: */
struct { struct {
@ -1030,6 +1052,37 @@ void memory_global_dirty_log_stop(void);
void mtree_info(fprintf_function mon_printf, void *f); 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 * address_space_init: initializes an address space
* *
@ -1055,41 +1108,117 @@ void address_space_destroy(AddressSpace *as);
/** /**
* address_space_rw: read from or write to an address space. * address_space_rw: read from or write to an address space.
* *
* Return true if the operation hit any unassigned memory or encountered an * Return a MemTxResult indicating whether the operation succeeded
* IOMMU fault. * or failed (eg unassigned memory, device rejected the transaction,
* IOMMU fault).
* *
* @as: #AddressSpace to be accessed * @as: #AddressSpace to be accessed
* @addr: address within that address space * @addr: address within that address space
* @attrs: memory transaction attributes
* @buf: buffer with the data transferred * @buf: buffer with the data transferred
* @is_write: indicates the transfer direction * @is_write: indicates the transfer direction
*/ */
bool address_space_rw(AddressSpace *as, hwaddr addr, uint8_t *buf, MemTxResult address_space_rw(AddressSpace *as, hwaddr addr,
int len, bool is_write); MemTxAttrs attrs, uint8_t *buf,
int len, bool is_write);
/** /**
* address_space_write: write to address space. * address_space_write: write to address space.
* *
* Return true if the operation hit any unassigned memory or encountered an * Return a MemTxResult indicating whether the operation succeeded
* IOMMU fault. * or failed (eg unassigned memory, device rejected the transaction,
* IOMMU fault).
* *
* @as: #AddressSpace to be accessed * @as: #AddressSpace to be accessed
* @addr: address within that address space * @addr: address within that address space
* @attrs: memory transaction attributes
* @buf: buffer with the data transferred * @buf: buffer with the data transferred
*/ */
bool address_space_write(AddressSpace *as, hwaddr addr, MemTxResult address_space_write(AddressSpace *as, hwaddr addr,
const uint8_t *buf, int len); MemTxAttrs attrs,
const uint8_t *buf, int len);
/** /**
* address_space_read: read from an address space. * address_space_read: read from an address space.
* *
* Return true if the operation hit any unassigned memory or encountered an * Return a MemTxResult indicating whether the operation succeeded
* IOMMU fault. * or failed (eg unassigned memory, device rejected the transaction,
* IOMMU fault).
* *
* @as: #AddressSpace to be accessed * @as: #AddressSpace to be accessed
* @addr: address within that address space * @addr: address within that address space
* @attrs: memory transaction attributes
* @buf: buffer with the data transferred * @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 /* address_space_translate: translate an address range into an address space
* into a MemoryRegion and an address range into that section * into a MemoryRegion and an address range into that section

View File

@ -24,6 +24,7 @@
#include <setjmp.h> #include <setjmp.h>
#include "hw/qdev-core.h" #include "hw/qdev-core.h"
#include "exec/hwaddr.h" #include "exec/hwaddr.h"
#include "exec/memattrs.h"
#include "qemu/queue.h" #include "qemu/queue.h"
#include "qemu/thread.h" #include "qemu/thread.h"
#include "qemu/tls.h" #include "qemu/tls.h"
@ -195,6 +196,7 @@ typedef struct CPUWatchpoint {
vaddr vaddr; vaddr vaddr;
vaddr len; vaddr len;
vaddr hitaddr; vaddr hitaddr;
MemTxAttrs hitattrs;
int flags; /* BP_* */ int flags; /* BP_* */
QTAILQ_ENTRY(CPUWatchpoint) entry; QTAILQ_ENTRY(CPUWatchpoint) entry;
} CPUWatchpoint; } CPUWatchpoint;

View File

@ -88,7 +88,8 @@ static inline int dma_memory_rw_relaxed(AddressSpace *as, dma_addr_t addr,
void *buf, dma_addr_t len, void *buf, dma_addr_t len,
DMADirection dir) 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, static inline int dma_memory_read_relaxed(AddressSpace *as, dma_addr_t addr,

View File

@ -64,7 +64,8 @@ void cpu_outb(pio_addr_t addr, uint8_t val)
{ {
LOG_IOPORT("outb: %04"FMT_pioaddr" %02"PRIx8"\n", addr, val); LOG_IOPORT("outb: %04"FMT_pioaddr" %02"PRIx8"\n", addr, val);
trace_cpu_out(addr, val); trace_cpu_out(addr, val);
address_space_write(&address_space_io, addr, &val, 1); address_space_write(&address_space_io, addr, MEMTXATTRS_UNSPECIFIED,
&val, 1);
} }
void cpu_outw(pio_addr_t addr, uint16_t val) void cpu_outw(pio_addr_t addr, uint16_t val)
@ -74,7 +75,8 @@ void cpu_outw(pio_addr_t addr, uint16_t val)
LOG_IOPORT("outw: %04"FMT_pioaddr" %04"PRIx16"\n", addr, val); LOG_IOPORT("outw: %04"FMT_pioaddr" %04"PRIx16"\n", addr, val);
trace_cpu_out(addr, val); trace_cpu_out(addr, val);
stw_p(buf, val); stw_p(buf, val);
address_space_write(&address_space_io, addr, buf, 2); address_space_write(&address_space_io, addr, MEMTXATTRS_UNSPECIFIED,
buf, 2);
} }
void cpu_outl(pio_addr_t addr, uint32_t val) void cpu_outl(pio_addr_t addr, uint32_t val)
@ -84,14 +86,16 @@ void cpu_outl(pio_addr_t addr, uint32_t val)
LOG_IOPORT("outl: %04"FMT_pioaddr" %08"PRIx32"\n", addr, val); LOG_IOPORT("outl: %04"FMT_pioaddr" %08"PRIx32"\n", addr, val);
trace_cpu_out(addr, val); trace_cpu_out(addr, val);
stl_p(buf, val); stl_p(buf, val);
address_space_write(&address_space_io, addr, buf, 4); address_space_write(&address_space_io, addr, MEMTXATTRS_UNSPECIFIED,
buf, 4);
} }
uint8_t cpu_inb(pio_addr_t addr) uint8_t cpu_inb(pio_addr_t addr)
{ {
uint8_t val; uint8_t val;
address_space_read(&address_space_io, addr, &val, 1); address_space_read(&address_space_io, addr, MEMTXATTRS_UNSPECIFIED,
&val, 1);
trace_cpu_in(addr, val); trace_cpu_in(addr, val);
LOG_IOPORT("inb : %04"FMT_pioaddr" %02"PRIx8"\n", addr, val); LOG_IOPORT("inb : %04"FMT_pioaddr" %02"PRIx8"\n", addr, val);
return val; return val;
@ -102,7 +106,7 @@ uint16_t cpu_inw(pio_addr_t addr)
uint8_t buf[2]; uint8_t buf[2];
uint16_t val; uint16_t val;
address_space_read(&address_space_io, addr, buf, 2); address_space_read(&address_space_io, addr, MEMTXATTRS_UNSPECIFIED, buf, 2);
val = lduw_p(buf); val = lduw_p(buf);
trace_cpu_in(addr, val); trace_cpu_in(addr, val);
LOG_IOPORT("inw : %04"FMT_pioaddr" %04"PRIx16"\n", addr, val); LOG_IOPORT("inw : %04"FMT_pioaddr" %04"PRIx16"\n", addr, val);
@ -114,7 +118,7 @@ uint32_t cpu_inl(pio_addr_t addr)
uint8_t buf[4]; uint8_t buf[4];
uint32_t val; uint32_t val;
address_space_read(&address_space_io, addr, buf, 4); address_space_read(&address_space_io, addr, MEMTXATTRS_UNSPECIFIED, buf, 4);
val = ldl_p(buf); val = ldl_p(buf);
trace_cpu_in(addr, val); trace_cpu_in(addr, val);
LOG_IOPORT("inl : %04"FMT_pioaddr" %08"PRIx32"\n", addr, val); LOG_IOPORT("inl : %04"FMT_pioaddr" %08"PRIx32"\n", addr, val);

View File

@ -1667,7 +1667,8 @@ static void kvm_handle_io(uint16_t port, void *data, int direction, int size,
uint8_t *ptr = data; uint8_t *ptr = data;
for (i = 0; i < count; i++) { for (i = 0; i < count; i++) {
address_space_rw(&address_space_io, port, ptr, size, address_space_rw(&address_space_io, port, MEMTXATTRS_UNSPECIFIED,
ptr, size,
direction == KVM_EXIT_IO_OUT); direction == KVM_EXIT_IO_OUT);
ptr += size; ptr += size;
} }

206
memory.c
View File

@ -368,26 +368,29 @@ static void adjust_endianness(MemoryRegion *mr, uint64_t *data, unsigned size)
} }
} }
static void memory_region_oldmmio_read_accessor(MemoryRegion *mr, static MemTxResult memory_region_oldmmio_read_accessor(MemoryRegion *mr,
hwaddr addr, hwaddr addr,
uint64_t *value, uint64_t *value,
unsigned size, unsigned size,
unsigned shift, unsigned shift,
uint64_t mask) uint64_t mask,
MemTxAttrs attrs)
{ {
uint64_t tmp; uint64_t tmp;
tmp = mr->ops->old_mmio.read[ctz32(size)](mr->opaque, addr); tmp = mr->ops->old_mmio.read[ctz32(size)](mr->opaque, addr);
trace_memory_region_ops_read(mr, addr, tmp, size); trace_memory_region_ops_read(mr, addr, tmp, size);
*value |= (tmp & mask) << shift; *value |= (tmp & mask) << shift;
return MEMTX_OK;
} }
static void memory_region_read_accessor(MemoryRegion *mr, static MemTxResult memory_region_read_accessor(MemoryRegion *mr,
hwaddr addr, hwaddr addr,
uint64_t *value, uint64_t *value,
unsigned size, unsigned size,
unsigned shift, unsigned shift,
uint64_t mask) uint64_t mask,
MemTxAttrs attrs)
{ {
uint64_t tmp; uint64_t tmp;
@ -397,28 +400,52 @@ static void memory_region_read_accessor(MemoryRegion *mr,
tmp = mr->ops->read(mr->opaque, addr, size); tmp = mr->ops->read(mr->opaque, addr, size);
trace_memory_region_ops_read(mr, addr, tmp, size); trace_memory_region_ops_read(mr, addr, tmp, size);
*value |= (tmp & mask) << shift; *value |= (tmp & mask) << shift;
return MEMTX_OK;
} }
static void memory_region_oldmmio_write_accessor(MemoryRegion *mr, static MemTxResult memory_region_read_with_attrs_accessor(MemoryRegion *mr,
hwaddr addr, hwaddr addr,
uint64_t *value, uint64_t *value,
unsigned size, unsigned size,
unsigned shift, unsigned shift,
uint64_t mask) uint64_t mask,
MemTxAttrs attrs)
{
uint64_t tmp = 0;
MemTxResult r;
if (mr->flush_coalesced_mmio) {
qemu_flush_coalesced_mmio_buffer();
}
r = mr->ops->read_with_attrs(mr->opaque, addr, &tmp, size, attrs);
trace_memory_region_ops_read(mr, addr, tmp, size);
*value |= (tmp & mask) << shift;
return r;
}
static MemTxResult memory_region_oldmmio_write_accessor(MemoryRegion *mr,
hwaddr addr,
uint64_t *value,
unsigned size,
unsigned shift,
uint64_t mask,
MemTxAttrs attrs)
{ {
uint64_t tmp; uint64_t tmp;
tmp = (*value >> shift) & mask; tmp = (*value >> shift) & mask;
trace_memory_region_ops_write(mr, addr, tmp, size); trace_memory_region_ops_write(mr, addr, tmp, size);
mr->ops->old_mmio.write[ctz32(size)](mr->opaque, addr, tmp); mr->ops->old_mmio.write[ctz32(size)](mr->opaque, addr, tmp);
return MEMTX_OK;
} }
static void memory_region_write_accessor(MemoryRegion *mr, static MemTxResult memory_region_write_accessor(MemoryRegion *mr,
hwaddr addr, hwaddr addr,
uint64_t *value, uint64_t *value,
unsigned size, unsigned size,
unsigned shift, unsigned shift,
uint64_t mask) uint64_t mask,
MemTxAttrs attrs)
{ {
uint64_t tmp; uint64_t tmp;
@ -428,24 +455,46 @@ static void memory_region_write_accessor(MemoryRegion *mr,
tmp = (*value >> shift) & mask; tmp = (*value >> shift) & mask;
trace_memory_region_ops_write(mr, addr, tmp, size); trace_memory_region_ops_write(mr, addr, tmp, size);
mr->ops->write(mr->opaque, addr, tmp, size); mr->ops->write(mr->opaque, addr, tmp, size);
return MEMTX_OK;
} }
static void access_with_adjusted_size(hwaddr addr, static MemTxResult memory_region_write_with_attrs_accessor(MemoryRegion *mr,
hwaddr addr,
uint64_t *value,
unsigned size,
unsigned shift,
uint64_t mask,
MemTxAttrs attrs)
{
uint64_t tmp;
if (mr->flush_coalesced_mmio) {
qemu_flush_coalesced_mmio_buffer();
}
tmp = (*value >> shift) & mask;
trace_memory_region_ops_write(mr, addr, tmp, size);
return mr->ops->write_with_attrs(mr->opaque, addr, tmp, size, attrs);
}
static MemTxResult access_with_adjusted_size(hwaddr addr,
uint64_t *value, uint64_t *value,
unsigned size, unsigned size,
unsigned access_size_min, unsigned access_size_min,
unsigned access_size_max, unsigned access_size_max,
void (*access)(MemoryRegion *mr, MemTxResult (*access)(MemoryRegion *mr,
hwaddr addr, hwaddr addr,
uint64_t *value, uint64_t *value,
unsigned size, unsigned size,
unsigned shift, unsigned shift,
uint64_t mask), uint64_t mask,
MemoryRegion *mr) MemTxAttrs attrs),
MemoryRegion *mr,
MemTxAttrs attrs)
{ {
uint64_t access_mask; uint64_t access_mask;
unsigned access_size; unsigned access_size;
unsigned i; unsigned i;
MemTxResult r = MEMTX_OK;
if (!access_size_min) { if (!access_size_min) {
access_size_min = 1; access_size_min = 1;
@ -459,14 +508,16 @@ static void access_with_adjusted_size(hwaddr addr,
access_mask = -1ULL >> (64 - access_size * 8); access_mask = -1ULL >> (64 - access_size * 8);
if (memory_region_big_endian(mr)) { if (memory_region_big_endian(mr)) {
for (i = 0; i < size; i += access_size) { for (i = 0; i < size; i += access_size) {
access(mr, addr + i, value, access_size, r |= access(mr, addr + i, value, access_size,
(size - access_size - i) * 8, access_mask); (size - access_size - i) * 8, access_mask, attrs);
} }
} else { } else {
for (i = 0; i < size; i += access_size) { for (i = 0; i < size; i += access_size) {
access(mr, addr + i, value, access_size, i * 8, access_mask); r |= access(mr, addr + i, value, access_size, i * 8,
access_mask, attrs);
} }
} }
return r;
} }
static AddressSpace *memory_region_to_address_space(MemoryRegion *mr) static AddressSpace *memory_region_to_address_space(MemoryRegion *mr)
@ -1053,62 +1104,82 @@ bool memory_region_access_valid(MemoryRegion *mr,
return true; return true;
} }
static uint64_t memory_region_dispatch_read1(MemoryRegion *mr, static MemTxResult memory_region_dispatch_read1(MemoryRegion *mr,
hwaddr addr, hwaddr addr,
unsigned size) uint64_t *pval,
unsigned size,
MemTxAttrs attrs)
{ {
uint64_t data = 0; *pval = 0;
if (mr->ops->read) { if (mr->ops->read) {
access_with_adjusted_size(addr, &data, size, return access_with_adjusted_size(addr, pval, size,
mr->ops->impl.min_access_size, mr->ops->impl.min_access_size,
mr->ops->impl.max_access_size, mr->ops->impl.max_access_size,
memory_region_read_accessor, mr); memory_region_read_accessor,
mr, attrs);
} else if (mr->ops->read_with_attrs) {
return access_with_adjusted_size(addr, pval, size,
mr->ops->impl.min_access_size,
mr->ops->impl.max_access_size,
memory_region_read_with_attrs_accessor,
mr, attrs);
} else { } else {
access_with_adjusted_size(addr, &data, size, 1, 4, return access_with_adjusted_size(addr, pval, size, 1, 4,
memory_region_oldmmio_read_accessor, mr); memory_region_oldmmio_read_accessor,
mr, attrs);
} }
return data;
} }
static bool memory_region_dispatch_read(MemoryRegion *mr, MemTxResult memory_region_dispatch_read(MemoryRegion *mr,
hwaddr addr, hwaddr addr,
uint64_t *pval, uint64_t *pval,
unsigned size) unsigned size,
MemTxAttrs attrs)
{ {
MemTxResult r;
if (!memory_region_access_valid(mr, addr, size, false)) { if (!memory_region_access_valid(mr, addr, size, false)) {
*pval = unassigned_mem_read(mr, addr, size); *pval = unassigned_mem_read(mr, addr, size);
return true; return MEMTX_DECODE_ERROR;
} }
*pval = memory_region_dispatch_read1(mr, addr, size); r = memory_region_dispatch_read1(mr, addr, pval, size, attrs);
adjust_endianness(mr, pval, size); adjust_endianness(mr, pval, size);
return false; return r;
} }
static bool memory_region_dispatch_write(MemoryRegion *mr, MemTxResult memory_region_dispatch_write(MemoryRegion *mr,
hwaddr addr, hwaddr addr,
uint64_t data, uint64_t data,
unsigned size) unsigned size,
MemTxAttrs attrs)
{ {
if (!memory_region_access_valid(mr, addr, size, true)) { if (!memory_region_access_valid(mr, addr, size, true)) {
unassigned_mem_write(mr, addr, data, size); unassigned_mem_write(mr, addr, data, size);
return true; return MEMTX_DECODE_ERROR;
} }
adjust_endianness(mr, &data, size); adjust_endianness(mr, &data, size);
if (mr->ops->write) { if (mr->ops->write) {
access_with_adjusted_size(addr, &data, size, return access_with_adjusted_size(addr, &data, size,
mr->ops->impl.min_access_size, mr->ops->impl.min_access_size,
mr->ops->impl.max_access_size, mr->ops->impl.max_access_size,
memory_region_write_accessor, mr); memory_region_write_accessor, mr,
attrs);
} else if (mr->ops->write_with_attrs) {
return
access_with_adjusted_size(addr, &data, size,
mr->ops->impl.min_access_size,
mr->ops->impl.max_access_size,
memory_region_write_with_attrs_accessor,
mr, attrs);
} else { } else {
access_with_adjusted_size(addr, &data, size, 1, 4, return access_with_adjusted_size(addr, &data, size, 1, 4,
memory_region_oldmmio_write_accessor, mr); memory_region_oldmmio_write_accessor,
mr, attrs);
} }
return false;
} }
void memory_region_init_io(MemoryRegion *mr, void memory_region_init_io(MemoryRegion *mr,
@ -1992,17 +2063,6 @@ void address_space_destroy(AddressSpace *as)
call_rcu(as, do_address_space_destroy, rcu); call_rcu(as, do_address_space_destroy, rcu);
} }
bool io_mem_read(MemoryRegion *mr, hwaddr addr, uint64_t *pval, unsigned size)
{
return memory_region_dispatch_read(mr, addr, pval, size);
}
bool io_mem_write(MemoryRegion *mr, hwaddr addr,
uint64_t val, unsigned size)
{
return memory_region_dispatch_write(mr, addr, val, size);
}
typedef struct MemoryRegionList MemoryRegionList; typedef struct MemoryRegionList MemoryRegionList;
struct MemoryRegionList { struct MemoryRegionList {

View File

@ -1384,7 +1384,8 @@ static void hmp_sum(Monitor *mon, const QDict *qdict)
sum = 0; sum = 0;
for(addr = start; addr < (start + size); addr++) { for(addr = start; addr < (start + size); addr++) {
uint8_t val = ldub_phys(&address_space_memory, addr); uint8_t val = address_space_ldub(&address_space_memory, addr,
MEMTXATTRS_UNSPECIFIED, NULL);
/* BSD sum algorithm ('sum' Unix command) */ /* BSD sum algorithm ('sum' Unix command) */
sum = (sum >> 1) | (sum << 15); sum = (sum >> 1) | (sum << 15);
sum += val; sum += val;

View File

@ -46,6 +46,8 @@ typedef struct va_list_str *va_list;
typedef struct AddressSpace AddressSpace; typedef struct AddressSpace AddressSpace;
typedef uint64_t hwaddr; typedef uint64_t hwaddr;
typedef uint32_t MemTxResult;
typedef uint64_t MemTxAttrs;
static void __write(uint8_t *buf, ssize_t len) static void __write(uint8_t *buf, ssize_t len)
{ {
@ -65,10 +67,10 @@ static void __read(uint8_t *buf, ssize_t len)
int last = buf[len-1]; int last = buf[len-1];
} }
bool address_space_rw(AddressSpace *as, hwaddr addr, uint8_t *buf, MemTxResult address_space_rw(AddressSpace *as, hwaddr addr, MemTxAttrs attrs,
int len, bool is_write) uint8_t *buf, int len, bool is_write)
{ {
bool result; MemTxResult result;
// TODO: investigate impact of treating reads as producing // TODO: investigate impact of treating reads as producing
// tainted data, with __coverity_tainted_data_argument__(buf). // tainted data, with __coverity_tainted_data_argument__(buf).

View File

@ -123,7 +123,7 @@
* victim tlb. try to refill from the victim tlb before walking the \ * victim tlb. try to refill from the victim tlb before walking the \
* page table. */ \ * page table. */ \
int vidx; \ int vidx; \
hwaddr tmpiotlb; \ CPUIOTLBEntry tmpiotlb; \
CPUTLBEntry tmptlb; \ CPUTLBEntry tmptlb; \
for (vidx = CPU_VTLB_SIZE-1; vidx >= 0; --vidx) { \ for (vidx = CPU_VTLB_SIZE-1; vidx >= 0; --vidx) { \
if (env->tlb_v_table[mmu_idx][vidx].ty == (addr & TARGET_PAGE_MASK)) {\ if (env->tlb_v_table[mmu_idx][vidx].ty == (addr & TARGET_PAGE_MASK)) {\
@ -143,12 +143,13 @@
#ifndef SOFTMMU_CODE_ACCESS #ifndef SOFTMMU_CODE_ACCESS
static inline DATA_TYPE glue(io_read, SUFFIX)(CPUArchState *env, static inline DATA_TYPE glue(io_read, SUFFIX)(CPUArchState *env,
hwaddr physaddr, CPUIOTLBEntry *iotlbentry,
target_ulong addr, target_ulong addr,
uintptr_t retaddr) uintptr_t retaddr)
{ {
uint64_t val; uint64_t val;
CPUState *cpu = ENV_GET_CPU(env); CPUState *cpu = ENV_GET_CPU(env);
hwaddr physaddr = iotlbentry->addr;
MemoryRegion *mr = iotlb_to_region(cpu, physaddr); MemoryRegion *mr = iotlb_to_region(cpu, physaddr);
physaddr = (physaddr & TARGET_PAGE_MASK) + addr; physaddr = (physaddr & TARGET_PAGE_MASK) + addr;
@ -158,7 +159,8 @@ static inline DATA_TYPE glue(io_read, SUFFIX)(CPUArchState *env,
} }
cpu->mem_io_vaddr = addr; cpu->mem_io_vaddr = addr;
io_mem_read(mr, physaddr, &val, 1 << SHIFT); memory_region_dispatch_read(mr, physaddr, &val, 1 << SHIFT,
iotlbentry->attrs);
return val; return val;
} }
#endif #endif
@ -195,15 +197,15 @@ WORD_TYPE helper_le_ld_name(CPUArchState *env, target_ulong addr, int mmu_idx,
/* Handle an IO access. */ /* Handle an IO access. */
if (unlikely(tlb_addr & ~TARGET_PAGE_MASK)) { if (unlikely(tlb_addr & ~TARGET_PAGE_MASK)) {
hwaddr ioaddr; CPUIOTLBEntry *iotlbentry;
if ((addr & (DATA_SIZE - 1)) != 0) { if ((addr & (DATA_SIZE - 1)) != 0) {
goto do_unaligned_access; goto do_unaligned_access;
} }
ioaddr = env->iotlb[mmu_idx][index]; iotlbentry = &env->iotlb[mmu_idx][index];
/* ??? Note that the io helpers always read data in the target /* ??? Note that the io helpers always read data in the target
byte ordering. We should push the LE/BE request down into io. */ byte ordering. We should push the LE/BE request down into io. */
res = glue(io_read, SUFFIX)(env, ioaddr, addr, retaddr); res = glue(io_read, SUFFIX)(env, iotlbentry, addr, retaddr);
res = TGT_LE(res); res = TGT_LE(res);
return res; return res;
} }
@ -283,15 +285,15 @@ WORD_TYPE helper_be_ld_name(CPUArchState *env, target_ulong addr, int mmu_idx,
/* Handle an IO access. */ /* Handle an IO access. */
if (unlikely(tlb_addr & ~TARGET_PAGE_MASK)) { if (unlikely(tlb_addr & ~TARGET_PAGE_MASK)) {
hwaddr ioaddr; CPUIOTLBEntry *iotlbentry;
if ((addr & (DATA_SIZE - 1)) != 0) { if ((addr & (DATA_SIZE - 1)) != 0) {
goto do_unaligned_access; goto do_unaligned_access;
} }
ioaddr = env->iotlb[mmu_idx][index]; iotlbentry = &env->iotlb[mmu_idx][index];
/* ??? Note that the io helpers always read data in the target /* ??? Note that the io helpers always read data in the target
byte ordering. We should push the LE/BE request down into io. */ byte ordering. We should push the LE/BE request down into io. */
res = glue(io_read, SUFFIX)(env, ioaddr, addr, retaddr); res = glue(io_read, SUFFIX)(env, iotlbentry, addr, retaddr);
res = TGT_BE(res); res = TGT_BE(res);
return res; return res;
} }
@ -363,12 +365,13 @@ WORD_TYPE helper_be_lds_name(CPUArchState *env, target_ulong addr,
#endif #endif
static inline void glue(io_write, SUFFIX)(CPUArchState *env, static inline void glue(io_write, SUFFIX)(CPUArchState *env,
hwaddr physaddr, CPUIOTLBEntry *iotlbentry,
DATA_TYPE val, DATA_TYPE val,
target_ulong addr, target_ulong addr,
uintptr_t retaddr) uintptr_t retaddr)
{ {
CPUState *cpu = ENV_GET_CPU(env); CPUState *cpu = ENV_GET_CPU(env);
hwaddr physaddr = iotlbentry->addr;
MemoryRegion *mr = iotlb_to_region(cpu, physaddr); MemoryRegion *mr = iotlb_to_region(cpu, physaddr);
physaddr = (physaddr & TARGET_PAGE_MASK) + addr; physaddr = (physaddr & TARGET_PAGE_MASK) + addr;
@ -378,7 +381,8 @@ static inline void glue(io_write, SUFFIX)(CPUArchState *env,
cpu->mem_io_vaddr = addr; cpu->mem_io_vaddr = addr;
cpu->mem_io_pc = retaddr; cpu->mem_io_pc = retaddr;
io_mem_write(mr, physaddr, val, 1 << SHIFT); memory_region_dispatch_write(mr, physaddr, val, 1 << SHIFT,
iotlbentry->attrs);
} }
void helper_le_st_name(CPUArchState *env, target_ulong addr, DATA_TYPE val, void helper_le_st_name(CPUArchState *env, target_ulong addr, DATA_TYPE val,
@ -408,16 +412,16 @@ void helper_le_st_name(CPUArchState *env, target_ulong addr, DATA_TYPE val,
/* Handle an IO access. */ /* Handle an IO access. */
if (unlikely(tlb_addr & ~TARGET_PAGE_MASK)) { if (unlikely(tlb_addr & ~TARGET_PAGE_MASK)) {
hwaddr ioaddr; CPUIOTLBEntry *iotlbentry;
if ((addr & (DATA_SIZE - 1)) != 0) { if ((addr & (DATA_SIZE - 1)) != 0) {
goto do_unaligned_access; goto do_unaligned_access;
} }
ioaddr = env->iotlb[mmu_idx][index]; iotlbentry = &env->iotlb[mmu_idx][index];
/* ??? Note that the io helpers always read data in the target /* ??? Note that the io helpers always read data in the target
byte ordering. We should push the LE/BE request down into io. */ byte ordering. We should push the LE/BE request down into io. */
val = TGT_LE(val); val = TGT_LE(val);
glue(io_write, SUFFIX)(env, ioaddr, val, addr, retaddr); glue(io_write, SUFFIX)(env, iotlbentry, val, addr, retaddr);
return; return;
} }
@ -489,16 +493,16 @@ void helper_be_st_name(CPUArchState *env, target_ulong addr, DATA_TYPE val,
/* Handle an IO access. */ /* Handle an IO access. */
if (unlikely(tlb_addr & ~TARGET_PAGE_MASK)) { if (unlikely(tlb_addr & ~TARGET_PAGE_MASK)) {
hwaddr ioaddr; CPUIOTLBEntry *iotlbentry;
if ((addr & (DATA_SIZE - 1)) != 0) { if ((addr & (DATA_SIZE - 1)) != 0) {
goto do_unaligned_access; goto do_unaligned_access;
} }
ioaddr = env->iotlb[mmu_idx][index]; iotlbentry = &env->iotlb[mmu_idx][index];
/* ??? Note that the io helpers always read data in the target /* ??? Note that the io helpers always read data in the target
byte ordering. We should push the LE/BE request down into io. */ byte ordering. We should push the LE/BE request down into io. */
val = TGT_BE(val); val = TGT_BE(val);
glue(io_write, SUFFIX)(env, ioaddr, val, addr, retaddr); glue(io_write, SUFFIX)(env, iotlbentry, val, addr, retaddr);
return; return;
} }

View File

@ -111,7 +111,7 @@ static void arm_cpu_reset(CPUState *s)
/* Userspace expects access to DC ZVA, CTL_EL0 and the cache ops */ /* Userspace expects access to DC ZVA, CTL_EL0 and the cache ops */
env->cp15.sctlr_el[1] |= SCTLR_UCT | SCTLR_UCI | SCTLR_DZE; env->cp15.sctlr_el[1] |= SCTLR_UCT | SCTLR_UCI | SCTLR_DZE;
/* and to the FP/Neon instructions */ /* and to the FP/Neon instructions */
env->cp15.c1_coproc = deposit64(env->cp15.c1_coproc, 20, 2, 3); env->cp15.cpacr_el1 = deposit64(env->cp15.cpacr_el1, 20, 2, 3);
#else #else
/* Reset into the highest available EL */ /* Reset into the highest available EL */
if (arm_feature(env, ARM_FEATURE_EL3)) { if (arm_feature(env, ARM_FEATURE_EL3)) {
@ -126,7 +126,7 @@ static void arm_cpu_reset(CPUState *s)
} else { } else {
#if defined(CONFIG_USER_ONLY) #if defined(CONFIG_USER_ONLY)
/* Userspace expects access to cp10 and cp11 for FP/Neon */ /* Userspace expects access to cp10 and cp11 for FP/Neon */
env->cp15.c1_coproc = deposit64(env->cp15.c1_coproc, 20, 4, 0xf); env->cp15.cpacr_el1 = deposit64(env->cp15.cpacr_el1, 20, 4, 0xf);
#endif #endif
} }
@ -524,9 +524,10 @@ static void arm_cpu_realizefn(DeviceState *dev, Error **errp)
unset_feature(env, ARM_FEATURE_EL3); unset_feature(env, ARM_FEATURE_EL3);
/* Disable the security extension feature bits in the processor feature /* Disable the security extension feature bits in the processor feature
* register as well. This is id_pfr1[7:4]. * registers as well. These are id_pfr1[7:4] and id_aa64pfr0[15:12].
*/ */
cpu->id_pfr1 &= ~0xf0; cpu->id_pfr1 &= ~0xf0;
cpu->id_aa64pfr0 &= ~0xf000;
} }
register_cp_regs_for_features(cpu); register_cp_regs_for_features(cpu);

View File

@ -201,7 +201,7 @@ typedef struct CPUARMState {
}; };
uint64_t sctlr_el[4]; uint64_t sctlr_el[4];
}; };
uint64_t c1_coproc; /* Coprocessor access register. */ uint64_t cpacr_el1; /* Architectural feature access control register */
uint32_t c1_xscaleauxcr; /* XScale auxiliary control register. */ uint32_t c1_xscaleauxcr; /* XScale auxiliary control register. */
uint64_t sder; /* Secure debug enable register. */ uint64_t sder; /* Secure debug enable register. */
uint32_t nsacr; /* Non-secure access control register. */ uint32_t nsacr; /* Non-secure access control register. */
@ -1813,7 +1813,7 @@ static inline void cpu_get_tb_cpu_state(CPUARMState *env, target_ulong *pc,
int fpen; int fpen;
if (arm_feature(env, ARM_FEATURE_V6)) { if (arm_feature(env, ARM_FEATURE_V6)) {
fpen = extract32(env->cp15.c1_coproc, 20, 2); fpen = extract32(env->cp15.cpacr_el1, 20, 2);
} else { } else {
/* CPACR doesn't exist before v6, so VFP is always accessible */ /* CPACR doesn't exist before v6, so VFP is always accessible */
fpen = 3; fpen = 3;

View File

@ -14,7 +14,7 @@
#ifndef CONFIG_USER_ONLY #ifndef CONFIG_USER_ONLY
static inline int get_phys_addr(CPUARMState *env, target_ulong address, static inline int get_phys_addr(CPUARMState *env, target_ulong address,
int access_type, ARMMMUIdx mmu_idx, int access_type, ARMMMUIdx mmu_idx,
hwaddr *phys_ptr, int *prot, hwaddr *phys_ptr, MemTxAttrs *attrs, int *prot,
target_ulong *page_size); target_ulong *page_size);
/* Definitions for the PMCCNTR and PMCR registers */ /* Definitions for the PMCCNTR and PMCR registers */
@ -589,7 +589,7 @@ static void cpacr_write(CPUARMState *env, const ARMCPRegInfo *ri,
} }
value &= mask; value &= mask;
} }
env->cp15.c1_coproc = value; env->cp15.cpacr_el1 = value;
} }
static const ARMCPRegInfo v6_cp_reginfo[] = { static const ARMCPRegInfo v6_cp_reginfo[] = {
@ -615,7 +615,7 @@ static const ARMCPRegInfo v6_cp_reginfo[] = {
.access = PL1_RW, .type = ARM_CP_CONST, .resetvalue = 0, }, .access = PL1_RW, .type = ARM_CP_CONST, .resetvalue = 0, },
{ .name = "CPACR", .state = ARM_CP_STATE_BOTH, .opc0 = 3, { .name = "CPACR", .state = ARM_CP_STATE_BOTH, .opc0 = 3,
.crn = 1, .crm = 0, .opc1 = 0, .opc2 = 2, .crn = 1, .crm = 0, .opc1 = 0, .opc2 = 2,
.access = PL1_RW, .fieldoffset = offsetof(CPUARMState, cp15.c1_coproc), .access = PL1_RW, .fieldoffset = offsetof(CPUARMState, cp15.cpacr_el1),
.resetvalue = 0, .writefn = cpacr_write }, .resetvalue = 0, .writefn = cpacr_write },
REGINFO_SENTINEL REGINFO_SENTINEL
}; };
@ -816,8 +816,10 @@ static void scr_write(CPUARMState *env, const ARMCPRegInfo *ri, uint64_t value)
* supported if EL2 exists. The bit is UNK/SBZP when * supported if EL2 exists. The bit is UNK/SBZP when
* EL2 is unavailable. In QEMU ARMv7, we force it to always zero * EL2 is unavailable. In QEMU ARMv7, we force it to always zero
* when EL2 is unavailable. * when EL2 is unavailable.
* On ARMv8, this bit is always available.
*/ */
if (arm_feature(env, ARM_FEATURE_V7)) { if (arm_feature(env, ARM_FEATURE_V7) &&
!arm_feature(env, ARM_FEATURE_V8)) {
valid_mask &= ~SCR_SMD; valid_mask &= ~SCR_SMD;
} }
} }
@ -1466,9 +1468,10 @@ static uint64_t do_ats_write(CPUARMState *env, uint64_t value,
int prot; int prot;
int ret; int ret;
uint64_t par64; uint64_t par64;
MemTxAttrs attrs = {};
ret = get_phys_addr(env, value, access_type, mmu_idx, ret = get_phys_addr(env, value, access_type, mmu_idx,
&phys_addr, &prot, &page_size); &phys_addr, &attrs, &prot, &page_size);
if (extended_addresses_enabled(env)) { if (extended_addresses_enabled(env)) {
/* ret is a DFSR/IFSR value for the long descriptor /* ret is a DFSR/IFSR value for the long descriptor
* translation table format, but with WnR always clear. * translation table format, but with WnR always clear.
@ -1477,6 +1480,9 @@ static uint64_t do_ats_write(CPUARMState *env, uint64_t value,
par64 = (1 << 11); /* LPAE bit always set */ par64 = (1 << 11); /* LPAE bit always set */
if (ret == 0) { if (ret == 0) {
par64 |= phys_addr & ~0xfffULL; par64 |= phys_addr & ~0xfffULL;
if (!attrs.secure) {
par64 |= (1 << 9); /* NS */
}
/* We don't set the ATTR or SH fields in the PAR. */ /* We don't set the ATTR or SH fields in the PAR. */
} else { } else {
par64 |= 1; /* F */ par64 |= 1; /* F */
@ -1499,6 +1505,9 @@ static uint64_t do_ats_write(CPUARMState *env, uint64_t value,
} else { } else {
par64 = phys_addr & 0xfffff000; par64 = phys_addr & 0xfffff000;
} }
if (!attrs.secure) {
par64 |= (1 << 9); /* NS */
}
} else { } else {
par64 = ((ret & (1 << 10)) >> 5) | ((ret & (1 << 12)) >> 6) | par64 = ((ret & (1 << 10)) >> 5) | ((ret & (1 << 12)) >> 6) |
((ret & 0xf) << 1) | 1; ((ret & 0xf) << 1) | 1;
@ -4858,6 +4867,26 @@ static inline uint32_t regime_el(CPUARMState *env, ARMMMUIdx mmu_idx)
} }
} }
/* Return true if this address translation regime is secure */
static inline bool regime_is_secure(CPUARMState *env, ARMMMUIdx mmu_idx)
{
switch (mmu_idx) {
case ARMMMUIdx_S12NSE0:
case ARMMMUIdx_S12NSE1:
case ARMMMUIdx_S1NSE0:
case ARMMMUIdx_S1NSE1:
case ARMMMUIdx_S1E2:
case ARMMMUIdx_S2NS:
return false;
case ARMMMUIdx_S1E3:
case ARMMMUIdx_S1SE0:
case ARMMMUIdx_S1SE1:
return true;
default:
g_assert_not_reached();
}
}
/* Return the SCTLR value which controls this address translation regime */ /* Return the SCTLR value which controls this address translation regime */
static inline uint32_t regime_sctlr(CPUARMState *env, ARMMMUIdx mmu_idx) static inline uint32_t regime_sctlr(CPUARMState *env, ARMMMUIdx mmu_idx)
{ {
@ -5102,6 +5131,29 @@ static bool get_level1_table_address(CPUARMState *env, ARMMMUIdx mmu_idx,
return true; return true;
} }
/* All loads done in the course of a page table walk go through here.
* TODO: rather than ignoring errors from physical memory reads (which
* are external aborts in ARM terminology) we should propagate this
* error out so that we can turn it into a Data Abort if this walk
* was being done for a CPU load/store or an address translation instruction
* (but not if it was for a debug access).
*/
static uint32_t arm_ldl_ptw(CPUState *cs, hwaddr addr, bool is_secure)
{
MemTxAttrs attrs = {};
attrs.secure = is_secure;
return address_space_ldl(cs->as, addr, attrs, NULL);
}
static uint64_t arm_ldq_ptw(CPUState *cs, hwaddr addr, bool is_secure)
{
MemTxAttrs attrs = {};
attrs.secure = is_secure;
return address_space_ldq(cs->as, addr, attrs, NULL);
}
static int get_phys_addr_v5(CPUARMState *env, uint32_t address, int access_type, static int get_phys_addr_v5(CPUARMState *env, uint32_t address, int access_type,
ARMMMUIdx mmu_idx, hwaddr *phys_ptr, ARMMMUIdx mmu_idx, hwaddr *phys_ptr,
int *prot, target_ulong *page_size) int *prot, target_ulong *page_size)
@ -5124,7 +5176,7 @@ static int get_phys_addr_v5(CPUARMState *env, uint32_t address, int access_type,
code = 5; code = 5;
goto do_fault; goto do_fault;
} }
desc = ldl_phys(cs->as, table); desc = arm_ldl_ptw(cs, table, regime_is_secure(env, mmu_idx));
type = (desc & 3); type = (desc & 3);
domain = (desc >> 5) & 0x0f; domain = (desc >> 5) & 0x0f;
if (regime_el(env, mmu_idx) == 1) { if (regime_el(env, mmu_idx) == 1) {
@ -5160,7 +5212,7 @@ static int get_phys_addr_v5(CPUARMState *env, uint32_t address, int access_type,
/* Fine pagetable. */ /* Fine pagetable. */
table = (desc & 0xfffff000) | ((address >> 8) & 0xffc); table = (desc & 0xfffff000) | ((address >> 8) & 0xffc);
} }
desc = ldl_phys(cs->as, table); desc = arm_ldl_ptw(cs, table, regime_is_secure(env, mmu_idx));
switch (desc & 3) { switch (desc & 3) {
case 0: /* Page translation fault. */ case 0: /* Page translation fault. */
code = 7; code = 7;
@ -5210,6 +5262,7 @@ do_fault:
static int get_phys_addr_v6(CPUARMState *env, uint32_t address, int access_type, static int get_phys_addr_v6(CPUARMState *env, uint32_t address, int access_type,
ARMMMUIdx mmu_idx, hwaddr *phys_ptr, ARMMMUIdx mmu_idx, hwaddr *phys_ptr,
MemTxAttrs *attrs,
int *prot, target_ulong *page_size) int *prot, target_ulong *page_size)
{ {
CPUState *cs = CPU(arm_env_get_cpu(env)); CPUState *cs = CPU(arm_env_get_cpu(env));
@ -5224,6 +5277,7 @@ static int get_phys_addr_v6(CPUARMState *env, uint32_t address, int access_type,
int domain_prot; int domain_prot;
hwaddr phys_addr; hwaddr phys_addr;
uint32_t dacr; uint32_t dacr;
bool ns;
/* Pagetable walk. */ /* Pagetable walk. */
/* Lookup l1 descriptor. */ /* Lookup l1 descriptor. */
@ -5232,7 +5286,7 @@ static int get_phys_addr_v6(CPUARMState *env, uint32_t address, int access_type,
code = 5; code = 5;
goto do_fault; goto do_fault;
} }
desc = ldl_phys(cs->as, table); desc = arm_ldl_ptw(cs, table, regime_is_secure(env, mmu_idx));
type = (desc & 3); type = (desc & 3);
if (type == 0 || (type == 3 && !arm_feature(env, ARM_FEATURE_PXN))) { if (type == 0 || (type == 3 && !arm_feature(env, ARM_FEATURE_PXN))) {
/* Section translation fault, or attempt to use the encoding /* Section translation fault, or attempt to use the encoding
@ -5273,13 +5327,15 @@ static int get_phys_addr_v6(CPUARMState *env, uint32_t address, int access_type,
xn = desc & (1 << 4); xn = desc & (1 << 4);
pxn = desc & 1; pxn = desc & 1;
code = 13; code = 13;
ns = extract32(desc, 19, 1);
} else { } else {
if (arm_feature(env, ARM_FEATURE_PXN)) { if (arm_feature(env, ARM_FEATURE_PXN)) {
pxn = (desc >> 2) & 1; pxn = (desc >> 2) & 1;
} }
ns = extract32(desc, 3, 1);
/* Lookup l2 entry. */ /* Lookup l2 entry. */
table = (desc & 0xfffffc00) | ((address >> 10) & 0x3fc); table = (desc & 0xfffffc00) | ((address >> 10) & 0x3fc);
desc = ldl_phys(cs->as, table); desc = arm_ldl_ptw(cs, table, regime_is_secure(env, mmu_idx));
ap = ((desc >> 4) & 3) | ((desc >> 7) & 4); ap = ((desc >> 4) & 3) | ((desc >> 7) & 4);
switch (desc & 3) { switch (desc & 3) {
case 0: /* Page translation fault. */ case 0: /* Page translation fault. */
@ -5330,6 +5386,13 @@ static int get_phys_addr_v6(CPUARMState *env, uint32_t address, int access_type,
goto do_fault; goto do_fault;
} }
} }
if (ns) {
/* The NS bit will (as required by the architecture) have no effect if
* the CPU doesn't support TZ or this is a non-secure translation
* regime, because the attribute will already be non-secure.
*/
attrs->secure = false;
}
*phys_ptr = phys_addr; *phys_ptr = phys_addr;
return 0; return 0;
do_fault: do_fault:
@ -5347,7 +5410,7 @@ typedef enum {
static int get_phys_addr_lpae(CPUARMState *env, target_ulong address, static int get_phys_addr_lpae(CPUARMState *env, target_ulong address,
int access_type, ARMMMUIdx mmu_idx, int access_type, ARMMMUIdx mmu_idx,
hwaddr *phys_ptr, int *prot, hwaddr *phys_ptr, MemTxAttrs *txattrs, int *prot,
target_ulong *page_size_ptr) target_ulong *page_size_ptr)
{ {
CPUState *cs = CPU(arm_env_get_cpu(env)); CPUState *cs = CPU(arm_env_get_cpu(env));
@ -5487,13 +5550,20 @@ static int get_phys_addr_lpae(CPUARMState *env, target_ulong address,
descaddr = extract64(ttbr, 0, 48); descaddr = extract64(ttbr, 0, 48);
descaddr &= ~((1ULL << (va_size - tsz - (granule_sz * (4 - level)))) - 1); descaddr &= ~((1ULL << (va_size - tsz - (granule_sz * (4 - level)))) - 1);
tableattrs = 0; /* Secure accesses start with the page table in secure memory and
* can be downgraded to non-secure at any step. Non-secure accesses
* remain non-secure. We implement this by just ORing in the NSTable/NS
* bits at each step.
*/
tableattrs = regime_is_secure(env, mmu_idx) ? 0 : (1 << 4);
for (;;) { for (;;) {
uint64_t descriptor; uint64_t descriptor;
bool nstable;
descaddr |= (address >> (granule_sz * (4 - level))) & descmask; descaddr |= (address >> (granule_sz * (4 - level))) & descmask;
descaddr &= ~7ULL; descaddr &= ~7ULL;
descriptor = ldq_phys(cs->as, descaddr); nstable = extract32(tableattrs, 4, 1);
descriptor = arm_ldq_ptw(cs, descaddr, !nstable);
if (!(descriptor & 1) || if (!(descriptor & 1) ||
(!(descriptor & 2) && (level == 3))) { (!(descriptor & 2) && (level == 3))) {
/* Invalid, or the Reserved level 3 encoding */ /* Invalid, or the Reserved level 3 encoding */
@ -5528,7 +5598,7 @@ static int get_phys_addr_lpae(CPUARMState *env, target_ulong address,
if (extract32(tableattrs, 2, 1)) { if (extract32(tableattrs, 2, 1)) {
attrs &= ~(1 << 4); attrs &= ~(1 << 4);
} }
attrs |= extract32(tableattrs, 4, 1) << 3; /* NS */ attrs |= nstable << 3; /* NS */
break; break;
} }
/* Here descaddr is the final physical address, and attributes /* Here descaddr is the final physical address, and attributes
@ -5552,6 +5622,13 @@ static int get_phys_addr_lpae(CPUARMState *env, target_ulong address,
goto do_fault; goto do_fault;
} }
if (ns) {
/* The NS bit will (as required by the architecture) have no effect if
* the CPU doesn't support TZ or this is a non-secure translation
* regime, because the attribute will already be non-secure.
*/
txattrs->secure = false;
}
*phys_ptr = descaddr; *phys_ptr = descaddr;
*page_size_ptr = page_size; *page_size_ptr = page_size;
return 0; return 0;
@ -5635,8 +5712,8 @@ static int get_phys_addr_mpu(CPUARMState *env, uint32_t address,
* by doing a translation table walk on MMU based systems or using the * by doing a translation table walk on MMU based systems or using the
* MPU state on MPU based systems. * MPU state on MPU based systems.
* *
* Returns 0 if the translation was successful. Otherwise, phys_ptr, * Returns 0 if the translation was successful. Otherwise, phys_ptr, attrs,
* prot and page_size are not filled in, and the return value provides * prot and page_size may not be filled in, and the return value provides
* information on why the translation aborted, in the format of a * information on why the translation aborted, in the format of a
* DFSR/IFSR fault register, with the following caveats: * DFSR/IFSR fault register, with the following caveats:
* * we honour the short vs long DFSR format differences. * * we honour the short vs long DFSR format differences.
@ -5649,24 +5726,33 @@ static int get_phys_addr_mpu(CPUARMState *env, uint32_t address,
* @access_type: 0 for read, 1 for write, 2 for execute * @access_type: 0 for read, 1 for write, 2 for execute
* @mmu_idx: MMU index indicating required translation regime * @mmu_idx: MMU index indicating required translation regime
* @phys_ptr: set to the physical address corresponding to the virtual address * @phys_ptr: set to the physical address corresponding to the virtual address
* @attrs: set to the memory transaction attributes to use
* @prot: set to the permissions for the page containing phys_ptr * @prot: set to the permissions for the page containing phys_ptr
* @page_size: set to the size of the page containing phys_ptr * @page_size: set to the size of the page containing phys_ptr
*/ */
static inline int get_phys_addr(CPUARMState *env, target_ulong address, static inline int get_phys_addr(CPUARMState *env, target_ulong address,
int access_type, ARMMMUIdx mmu_idx, int access_type, ARMMMUIdx mmu_idx,
hwaddr *phys_ptr, int *prot, hwaddr *phys_ptr, MemTxAttrs *attrs, int *prot,
target_ulong *page_size) target_ulong *page_size)
{ {
if (mmu_idx == ARMMMUIdx_S12NSE0 || mmu_idx == ARMMMUIdx_S12NSE1) { if (mmu_idx == ARMMMUIdx_S12NSE0 || mmu_idx == ARMMMUIdx_S12NSE1) {
/* TODO: when we support EL2 we should here call ourselves recursively /* TODO: when we support EL2 we should here call ourselves recursively
* to do the stage 1 and then stage 2 translations. The ldl_phys * to do the stage 1 and then stage 2 translations. The arm_ld*_ptw
* calls for stage 1 will also need changing. * functions will also need changing to perform ARMMMUIdx_S2NS loads
* rather than direct physical memory loads when appropriate.
* For non-EL2 CPUs a stage1+stage2 translation is just stage 1. * For non-EL2 CPUs a stage1+stage2 translation is just stage 1.
*/ */
assert(!arm_feature(env, ARM_FEATURE_EL2)); assert(!arm_feature(env, ARM_FEATURE_EL2));
mmu_idx += ARMMMUIdx_S1NSE0; mmu_idx += ARMMMUIdx_S1NSE0;
} }
/* The page table entries may downgrade secure to non-secure, but
* cannot upgrade an non-secure translation regime's attributes
* to secure.
*/
attrs->secure = regime_is_secure(env, mmu_idx);
attrs->user = regime_is_user(env, mmu_idx);
/* Fast Context Switch Extension. This doesn't exist at all in v8. /* Fast Context Switch Extension. This doesn't exist at all in v8.
* In v7 and earlier it affects all stage 1 translations. * In v7 and earlier it affects all stage 1 translations.
*/ */
@ -5695,10 +5781,10 @@ static inline int get_phys_addr(CPUARMState *env, target_ulong address,
if (regime_using_lpae_format(env, mmu_idx)) { if (regime_using_lpae_format(env, mmu_idx)) {
return get_phys_addr_lpae(env, address, access_type, mmu_idx, phys_ptr, return get_phys_addr_lpae(env, address, access_type, mmu_idx, phys_ptr,
prot, page_size); attrs, prot, page_size);
} else if (regime_sctlr(env, mmu_idx) & SCTLR_XP) { } else if (regime_sctlr(env, mmu_idx) & SCTLR_XP) {
return get_phys_addr_v6(env, address, access_type, mmu_idx, phys_ptr, return get_phys_addr_v6(env, address, access_type, mmu_idx, phys_ptr,
prot, page_size); attrs, prot, page_size);
} else { } else {
return get_phys_addr_v5(env, address, access_type, mmu_idx, phys_ptr, return get_phys_addr_v5(env, address, access_type, mmu_idx, phys_ptr,
prot, page_size); prot, page_size);
@ -5716,14 +5802,16 @@ int arm_cpu_handle_mmu_fault(CPUState *cs, vaddr address,
int ret; int ret;
uint32_t syn; uint32_t syn;
bool same_el = (arm_current_el(env) != 0); bool same_el = (arm_current_el(env) != 0);
MemTxAttrs attrs = {};
ret = get_phys_addr(env, address, access_type, mmu_idx, &phys_addr, &prot, ret = get_phys_addr(env, address, access_type, mmu_idx, &phys_addr,
&page_size); &attrs, &prot, &page_size);
if (ret == 0) { if (ret == 0) {
/* Map a single [sub]page. */ /* Map a single [sub]page. */
phys_addr &= TARGET_PAGE_MASK; phys_addr &= TARGET_PAGE_MASK;
address &= TARGET_PAGE_MASK; address &= TARGET_PAGE_MASK;
tlb_set_page(cs, address, phys_addr, prot, mmu_idx, page_size); tlb_set_page_with_attrs(cs, address, phys_addr, attrs,
prot, mmu_idx, page_size);
return 0; return 0;
} }
@ -5758,9 +5846,10 @@ hwaddr arm_cpu_get_phys_page_debug(CPUState *cs, vaddr addr)
target_ulong page_size; target_ulong page_size;
int prot; int prot;
int ret; int ret;
MemTxAttrs attrs = {};
ret = get_phys_addr(env, addr, 0, cpu_mmu_index(env), &phys_addr, ret = get_phys_addr(env, addr, 0, cpu_mmu_index(env), &phys_addr,
&prot, &page_size); &attrs, &prot, &page_size);
if (ret != 0) { if (ret != 0) {
return -1; return -1;

View File

@ -600,15 +600,26 @@ static bool bp_wp_matches(ARMCPU *cpu, int n, bool is_wp)
CPUARMState *env = &cpu->env; CPUARMState *env = &cpu->env;
uint64_t cr; uint64_t cr;
int pac, hmc, ssc, wt, lbn; int pac, hmc, ssc, wt, lbn;
/* TODO: check against CPU security state when we implement TrustZone */ /* Note that for watchpoints the check is against the CPU security
bool is_secure = false; * state, not the S/NS attribute on the offending data access.
*/
bool is_secure = arm_is_secure(env);
int access_el = arm_current_el(env);
if (is_wp) { if (is_wp) {
if (!env->cpu_watchpoint[n] CPUWatchpoint *wp = env->cpu_watchpoint[n];
|| !(env->cpu_watchpoint[n]->flags & BP_WATCHPOINT_HIT)) {
if (!wp || !(wp->flags & BP_WATCHPOINT_HIT)) {
return false; return false;
} }
cr = env->cp15.dbgwcr[n]; cr = env->cp15.dbgwcr[n];
if (wp->hitattrs.user) {
/* The LDRT/STRT/LDT/STT "unprivileged access" instructions should
* match watchpoints as if they were accesses done at EL0, even if
* the CPU is at EL1 or higher.
*/
access_el = 0;
}
} else { } else {
uint64_t pc = is_a64(env) ? env->pc : env->regs[15]; uint64_t pc = is_a64(env) ? env->pc : env->regs[15];
@ -649,15 +660,7 @@ static bool bp_wp_matches(ARMCPU *cpu, int n, bool is_wp)
break; break;
} }
/* TODO: this is not strictly correct because the LDRT/STRT/LDT/STT switch (access_el) {
* "unprivileged access" instructions should match watchpoints as if
* they were accesses done at EL0, even if the CPU is at EL1 or higher.
* Implementing this would require reworking the core watchpoint code
* to plumb the mmu_idx through to this point. Luckily Linux does not
* rely on this behaviour currently.
* For breakpoints we do want to use the current CPU state.
*/
switch (arm_current_el(env)) {
case 3: case 3:
case 2: case 2:
if (!hmc) { if (!hmc) {

View File

@ -27,7 +27,7 @@ static void walk_pte(MemoryMappingList *list, AddressSpace *as,
for (i = 0; i < 512; i++) { for (i = 0; i < 512; i++) {
pte_addr = (pte_start_addr + i * 8) & a20_mask; pte_addr = (pte_start_addr + i * 8) & a20_mask;
pte = ldq_phys(as, pte_addr); pte = address_space_ldq(as, pte_addr, MEMTXATTRS_UNSPECIFIED, NULL);
if (!(pte & PG_PRESENT_MASK)) { if (!(pte & PG_PRESENT_MASK)) {
/* not present */ /* not present */
continue; continue;
@ -57,7 +57,7 @@ static void walk_pte2(MemoryMappingList *list, AddressSpace *as,
for (i = 0; i < 1024; i++) { for (i = 0; i < 1024; i++) {
pte_addr = (pte_start_addr + i * 4) & a20_mask; pte_addr = (pte_start_addr + i * 4) & a20_mask;
pte = ldl_phys(as, pte_addr); pte = address_space_ldl(as, pte_addr, MEMTXATTRS_UNSPECIFIED, NULL);
if (!(pte & PG_PRESENT_MASK)) { if (!(pte & PG_PRESENT_MASK)) {
/* not present */ /* not present */
continue; continue;
@ -89,7 +89,7 @@ static void walk_pde(MemoryMappingList *list, AddressSpace *as,
for (i = 0; i < 512; i++) { for (i = 0; i < 512; i++) {
pde_addr = (pde_start_addr + i * 8) & a20_mask; pde_addr = (pde_start_addr + i * 8) & a20_mask;
pde = ldq_phys(as, pde_addr); pde = address_space_ldq(as, pde_addr, MEMTXATTRS_UNSPECIFIED, NULL);
if (!(pde & PG_PRESENT_MASK)) { if (!(pde & PG_PRESENT_MASK)) {
/* not present */ /* not present */
continue; continue;
@ -126,7 +126,7 @@ static void walk_pde2(MemoryMappingList *list, AddressSpace *as,
for (i = 0; i < 1024; i++) { for (i = 0; i < 1024; i++) {
pde_addr = (pde_start_addr + i * 4) & a20_mask; pde_addr = (pde_start_addr + i * 4) & a20_mask;
pde = ldl_phys(as, pde_addr); pde = address_space_ldl(as, pde_addr, MEMTXATTRS_UNSPECIFIED, NULL);
if (!(pde & PG_PRESENT_MASK)) { if (!(pde & PG_PRESENT_MASK)) {
/* not present */ /* not present */
continue; continue;
@ -167,7 +167,7 @@ static void walk_pdpe2(MemoryMappingList *list, AddressSpace *as,
for (i = 0; i < 4; i++) { for (i = 0; i < 4; i++) {
pdpe_addr = (pdpe_start_addr + i * 8) & a20_mask; pdpe_addr = (pdpe_start_addr + i * 8) & a20_mask;
pdpe = ldq_phys(as, pdpe_addr); pdpe = address_space_ldq(as, pdpe_addr, MEMTXATTRS_UNSPECIFIED, NULL);
if (!(pdpe & PG_PRESENT_MASK)) { if (!(pdpe & PG_PRESENT_MASK)) {
/* not present */ /* not present */
continue; continue;
@ -192,7 +192,7 @@ static void walk_pdpe(MemoryMappingList *list, AddressSpace *as,
for (i = 0; i < 512; i++) { for (i = 0; i < 512; i++) {
pdpe_addr = (pdpe_start_addr + i * 8) & a20_mask; pdpe_addr = (pdpe_start_addr + i * 8) & a20_mask;
pdpe = ldq_phys(as, pdpe_addr); pdpe = address_space_ldq(as, pdpe_addr, MEMTXATTRS_UNSPECIFIED, NULL);
if (!(pdpe & PG_PRESENT_MASK)) { if (!(pdpe & PG_PRESENT_MASK)) {
/* not present */ /* not present */
continue; continue;
@ -228,7 +228,8 @@ static void walk_pml4e(MemoryMappingList *list, AddressSpace *as,
for (i = 0; i < 512; i++) { for (i = 0; i < 512; i++) {
pml4e_addr = (pml4e_start_addr + i * 8) & a20_mask; pml4e_addr = (pml4e_start_addr + i * 8) & a20_mask;
pml4e = ldq_phys(as, pml4e_addr); pml4e = address_space_ldq(as, pml4e_addr, MEMTXATTRS_UNSPECIFIED,
NULL);
if (!(pml4e & PG_PRESENT_MASK)) { if (!(pml4e & PG_PRESENT_MASK)) {
/* not present */ /* not present */
continue; continue;