mirror of
https://github.com/izzy2lost/xemu.git
synced 2026-07-06 00:20:22 -07:00
Merge remote-tracking branch 'remotes/pmaydell/tags/pull-target-arm-20210217' into staging
target-arm queue: * Support ARMv8.5-MemTag for linux-user * ncpm7xx: Support SMBus * MAINTAINERS: add section for Clock framework # gpg: Signature made Wed 17 Feb 2021 11:01:45 GMT # gpg: using RSA key E1A5C593CD419DE28E8315CF3C2525ED14360CDE # gpg: issuer "peter.maydell@linaro.org" # gpg: Good signature from "Peter Maydell <peter.maydell@linaro.org>" [ultimate] # gpg: aka "Peter Maydell <pmaydell@gmail.com>" [ultimate] # gpg: aka "Peter Maydell <pmaydell@chiark.greenend.org.uk>" [ultimate] # Primary key fingerprint: E1A5 C593 CD41 9DE2 8E83 15CF 3C25 25ED 1436 0CDE * remotes/pmaydell/tags/pull-target-arm-20210217: (37 commits) MAINTAINERS: add myself maintainer for the clock framework hw/i2c: Implement NPCM7XX SMBus Module FIFO Mode hw/i2c: Add a QTest for NPCM7XX SMBus Device hw/arm: Add I2C sensors and EEPROM for GSJ machine hw/arm: Add I2C sensors for NPCM750 eval board hw/i2c: Implement NPCM7XX SMBus Module Single Mode tests/tcg/aarch64: Add mte smoke tests target/arm: Enable MTE for user-only target/arm: Add allocation tag storage for user mode linux-user/aarch64: Signal SEGV_MTEAERR for async tag check error linux-user/aarch64: Signal SEGV_MTESERR for sync tag check fault linux-user/aarch64: Pass syndrome to EXC_*_ABORT target/arm: Split out syndrome.h from internals.h linux-user/aarch64: Implement PROT_MTE linux-user/aarch64: Implement PR_MTE_TCF and PR_MTE_TAG target/arm: Use the proper TBI settings for linux-user target/arm: Improve gen_top_byte_ignore linux-user/aarch64: Implement PR_TAGGED_ADDR_ENABLE linux-user: Handle tags in lock_user/unlock_user linux-user: Fix types in uaccess.c ... Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
+11
@@ -2855,6 +2855,17 @@ F: pc-bios/opensbi-*
|
||||
F: .gitlab-ci.d/opensbi.yml
|
||||
F: .gitlab-ci.d/opensbi/
|
||||
|
||||
Clock framework
|
||||
M: Luc Michel <luc@lmichel.fr>
|
||||
R: Damien Hedde <damien.hedde@greensocs.com>
|
||||
S: Maintained
|
||||
F: include/hw/clock.h
|
||||
F: include/hw/qdev-clock.h
|
||||
F: hw/core/clock.c
|
||||
F: hw/core/clock-vmstate.c
|
||||
F: hw/core/qdev-clock.c
|
||||
F: docs/devel/clocks.rst
|
||||
|
||||
Usermode Emulation
|
||||
------------------
|
||||
Overall usermode emulation
|
||||
|
||||
@@ -114,6 +114,7 @@ typedef struct PageDesc {
|
||||
unsigned int code_write_count;
|
||||
#else
|
||||
unsigned long flags;
|
||||
void *target_data;
|
||||
#endif
|
||||
#ifndef CONFIG_USER_ONLY
|
||||
QemuSpin lock;
|
||||
@@ -1761,7 +1762,7 @@ static inline void tb_page_add(PageDesc *p, TranslationBlock *tb,
|
||||
prot |= p2->flags;
|
||||
p2->flags &= ~PAGE_WRITE;
|
||||
}
|
||||
mprotect(g2h(page_addr), qemu_host_page_size,
|
||||
mprotect(g2h_untagged(page_addr), qemu_host_page_size,
|
||||
(prot & PAGE_BITS) & ~PAGE_WRITE);
|
||||
if (DEBUG_TB_INVALIDATE_GATE) {
|
||||
printf("protecting code page: 0x" TB_PAGE_ADDR_FMT "\n", page_addr);
|
||||
@@ -2740,6 +2741,7 @@ int page_get_flags(target_ulong address)
|
||||
void page_set_flags(target_ulong start, target_ulong end, int flags)
|
||||
{
|
||||
target_ulong addr, len;
|
||||
bool reset_target_data;
|
||||
|
||||
/* This function should never be called with addresses outside the
|
||||
guest address space. If this assert fires, it probably indicates
|
||||
@@ -2754,6 +2756,8 @@ void page_set_flags(target_ulong start, target_ulong end, int flags)
|
||||
if (flags & PAGE_WRITE) {
|
||||
flags |= PAGE_WRITE_ORG;
|
||||
}
|
||||
reset_target_data = !(flags & PAGE_VALID) || (flags & PAGE_RESET);
|
||||
flags &= ~PAGE_RESET;
|
||||
|
||||
for (addr = start, len = end - start;
|
||||
len != 0;
|
||||
@@ -2767,10 +2771,34 @@ void page_set_flags(target_ulong start, target_ulong end, int flags)
|
||||
p->first_tb) {
|
||||
tb_invalidate_phys_page(addr, 0);
|
||||
}
|
||||
if (reset_target_data && p->target_data) {
|
||||
g_free(p->target_data);
|
||||
p->target_data = NULL;
|
||||
}
|
||||
p->flags = flags;
|
||||
}
|
||||
}
|
||||
|
||||
void *page_get_target_data(target_ulong address)
|
||||
{
|
||||
PageDesc *p = page_find(address >> TARGET_PAGE_BITS);
|
||||
return p ? p->target_data : NULL;
|
||||
}
|
||||
|
||||
void *page_alloc_target_data(target_ulong address, size_t size)
|
||||
{
|
||||
PageDesc *p = page_find(address >> TARGET_PAGE_BITS);
|
||||
void *ret = NULL;
|
||||
|
||||
if (p->flags & PAGE_VALID) {
|
||||
ret = p->target_data;
|
||||
if (!ret) {
|
||||
p->target_data = ret = g_malloc0(size);
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
int page_check_range(target_ulong start, target_ulong len, int flags)
|
||||
{
|
||||
PageDesc *p;
|
||||
@@ -2884,7 +2912,7 @@ int page_unprotect(target_ulong address, uintptr_t pc)
|
||||
}
|
||||
#endif
|
||||
}
|
||||
mprotect((void *)g2h(host_start), qemu_host_page_size,
|
||||
mprotect((void *)g2h_untagged(host_start), qemu_host_page_size,
|
||||
prot & PAGE_BITS);
|
||||
}
|
||||
mmap_unlock();
|
||||
|
||||
+26
-25
@@ -213,7 +213,8 @@ static int probe_access_internal(CPUArchState *env, target_ulong addr,
|
||||
g_assert_not_reached();
|
||||
}
|
||||
|
||||
if (!guest_addr_valid(addr) || page_check_range(addr, 1, flags) < 0) {
|
||||
if (!guest_addr_valid_untagged(addr) ||
|
||||
page_check_range(addr, 1, flags) < 0) {
|
||||
if (nonfault) {
|
||||
return TLB_INVALID_MASK;
|
||||
} else {
|
||||
@@ -234,7 +235,7 @@ int probe_access_flags(CPUArchState *env, target_ulong addr,
|
||||
int flags;
|
||||
|
||||
flags = probe_access_internal(env, addr, 0, access_type, nonfault, ra);
|
||||
*phost = flags ? NULL : g2h(addr);
|
||||
*phost = flags ? NULL : g2h(env_cpu(env), addr);
|
||||
return flags;
|
||||
}
|
||||
|
||||
@@ -247,7 +248,7 @@ void *probe_access(CPUArchState *env, target_ulong addr, int size,
|
||||
flags = probe_access_internal(env, addr, size, access_type, false, ra);
|
||||
g_assert(flags == 0);
|
||||
|
||||
return size ? g2h(addr) : NULL;
|
||||
return size ? g2h(env_cpu(env), addr) : NULL;
|
||||
}
|
||||
|
||||
#if defined(__i386__)
|
||||
@@ -842,7 +843,7 @@ uint32_t cpu_ldub_data(CPUArchState *env, abi_ptr ptr)
|
||||
uint16_t meminfo = trace_mem_get_info(MO_UB, MMU_USER_IDX, false);
|
||||
|
||||
trace_guest_mem_before_exec(env_cpu(env), ptr, meminfo);
|
||||
ret = ldub_p(g2h(ptr));
|
||||
ret = ldub_p(g2h(env_cpu(env), ptr));
|
||||
qemu_plugin_vcpu_mem_cb(env_cpu(env), ptr, meminfo);
|
||||
return ret;
|
||||
}
|
||||
@@ -853,7 +854,7 @@ int cpu_ldsb_data(CPUArchState *env, abi_ptr ptr)
|
||||
uint16_t meminfo = trace_mem_get_info(MO_SB, MMU_USER_IDX, false);
|
||||
|
||||
trace_guest_mem_before_exec(env_cpu(env), ptr, meminfo);
|
||||
ret = ldsb_p(g2h(ptr));
|
||||
ret = ldsb_p(g2h(env_cpu(env), ptr));
|
||||
qemu_plugin_vcpu_mem_cb(env_cpu(env), ptr, meminfo);
|
||||
return ret;
|
||||
}
|
||||
@@ -864,7 +865,7 @@ uint32_t cpu_lduw_be_data(CPUArchState *env, abi_ptr ptr)
|
||||
uint16_t meminfo = trace_mem_get_info(MO_BEUW, MMU_USER_IDX, false);
|
||||
|
||||
trace_guest_mem_before_exec(env_cpu(env), ptr, meminfo);
|
||||
ret = lduw_be_p(g2h(ptr));
|
||||
ret = lduw_be_p(g2h(env_cpu(env), ptr));
|
||||
qemu_plugin_vcpu_mem_cb(env_cpu(env), ptr, meminfo);
|
||||
return ret;
|
||||
}
|
||||
@@ -875,7 +876,7 @@ int cpu_ldsw_be_data(CPUArchState *env, abi_ptr ptr)
|
||||
uint16_t meminfo = trace_mem_get_info(MO_BESW, MMU_USER_IDX, false);
|
||||
|
||||
trace_guest_mem_before_exec(env_cpu(env), ptr, meminfo);
|
||||
ret = ldsw_be_p(g2h(ptr));
|
||||
ret = ldsw_be_p(g2h(env_cpu(env), ptr));
|
||||
qemu_plugin_vcpu_mem_cb(env_cpu(env), ptr, meminfo);
|
||||
return ret;
|
||||
}
|
||||
@@ -886,7 +887,7 @@ uint32_t cpu_ldl_be_data(CPUArchState *env, abi_ptr ptr)
|
||||
uint16_t meminfo = trace_mem_get_info(MO_BEUL, MMU_USER_IDX, false);
|
||||
|
||||
trace_guest_mem_before_exec(env_cpu(env), ptr, meminfo);
|
||||
ret = ldl_be_p(g2h(ptr));
|
||||
ret = ldl_be_p(g2h(env_cpu(env), ptr));
|
||||
qemu_plugin_vcpu_mem_cb(env_cpu(env), ptr, meminfo);
|
||||
return ret;
|
||||
}
|
||||
@@ -897,7 +898,7 @@ uint64_t cpu_ldq_be_data(CPUArchState *env, abi_ptr ptr)
|
||||
uint16_t meminfo = trace_mem_get_info(MO_BEQ, MMU_USER_IDX, false);
|
||||
|
||||
trace_guest_mem_before_exec(env_cpu(env), ptr, meminfo);
|
||||
ret = ldq_be_p(g2h(ptr));
|
||||
ret = ldq_be_p(g2h(env_cpu(env), ptr));
|
||||
qemu_plugin_vcpu_mem_cb(env_cpu(env), ptr, meminfo);
|
||||
return ret;
|
||||
}
|
||||
@@ -908,7 +909,7 @@ uint32_t cpu_lduw_le_data(CPUArchState *env, abi_ptr ptr)
|
||||
uint16_t meminfo = trace_mem_get_info(MO_LEUW, MMU_USER_IDX, false);
|
||||
|
||||
trace_guest_mem_before_exec(env_cpu(env), ptr, meminfo);
|
||||
ret = lduw_le_p(g2h(ptr));
|
||||
ret = lduw_le_p(g2h(env_cpu(env), ptr));
|
||||
qemu_plugin_vcpu_mem_cb(env_cpu(env), ptr, meminfo);
|
||||
return ret;
|
||||
}
|
||||
@@ -919,7 +920,7 @@ int cpu_ldsw_le_data(CPUArchState *env, abi_ptr ptr)
|
||||
uint16_t meminfo = trace_mem_get_info(MO_LESW, MMU_USER_IDX, false);
|
||||
|
||||
trace_guest_mem_before_exec(env_cpu(env), ptr, meminfo);
|
||||
ret = ldsw_le_p(g2h(ptr));
|
||||
ret = ldsw_le_p(g2h(env_cpu(env), ptr));
|
||||
qemu_plugin_vcpu_mem_cb(env_cpu(env), ptr, meminfo);
|
||||
return ret;
|
||||
}
|
||||
@@ -930,7 +931,7 @@ uint32_t cpu_ldl_le_data(CPUArchState *env, abi_ptr ptr)
|
||||
uint16_t meminfo = trace_mem_get_info(MO_LEUL, MMU_USER_IDX, false);
|
||||
|
||||
trace_guest_mem_before_exec(env_cpu(env), ptr, meminfo);
|
||||
ret = ldl_le_p(g2h(ptr));
|
||||
ret = ldl_le_p(g2h(env_cpu(env), ptr));
|
||||
qemu_plugin_vcpu_mem_cb(env_cpu(env), ptr, meminfo);
|
||||
return ret;
|
||||
}
|
||||
@@ -941,7 +942,7 @@ uint64_t cpu_ldq_le_data(CPUArchState *env, abi_ptr ptr)
|
||||
uint16_t meminfo = trace_mem_get_info(MO_LEQ, MMU_USER_IDX, false);
|
||||
|
||||
trace_guest_mem_before_exec(env_cpu(env), ptr, meminfo);
|
||||
ret = ldq_le_p(g2h(ptr));
|
||||
ret = ldq_le_p(g2h(env_cpu(env), ptr));
|
||||
qemu_plugin_vcpu_mem_cb(env_cpu(env), ptr, meminfo);
|
||||
return ret;
|
||||
}
|
||||
@@ -1051,7 +1052,7 @@ void cpu_stb_data(CPUArchState *env, abi_ptr ptr, uint32_t val)
|
||||
uint16_t meminfo = trace_mem_get_info(MO_UB, MMU_USER_IDX, true);
|
||||
|
||||
trace_guest_mem_before_exec(env_cpu(env), ptr, meminfo);
|
||||
stb_p(g2h(ptr), val);
|
||||
stb_p(g2h(env_cpu(env), ptr), val);
|
||||
qemu_plugin_vcpu_mem_cb(env_cpu(env), ptr, meminfo);
|
||||
}
|
||||
|
||||
@@ -1060,7 +1061,7 @@ void cpu_stw_be_data(CPUArchState *env, abi_ptr ptr, uint32_t val)
|
||||
uint16_t meminfo = trace_mem_get_info(MO_BEUW, MMU_USER_IDX, true);
|
||||
|
||||
trace_guest_mem_before_exec(env_cpu(env), ptr, meminfo);
|
||||
stw_be_p(g2h(ptr), val);
|
||||
stw_be_p(g2h(env_cpu(env), ptr), val);
|
||||
qemu_plugin_vcpu_mem_cb(env_cpu(env), ptr, meminfo);
|
||||
}
|
||||
|
||||
@@ -1069,7 +1070,7 @@ void cpu_stl_be_data(CPUArchState *env, abi_ptr ptr, uint32_t val)
|
||||
uint16_t meminfo = trace_mem_get_info(MO_BEUL, MMU_USER_IDX, true);
|
||||
|
||||
trace_guest_mem_before_exec(env_cpu(env), ptr, meminfo);
|
||||
stl_be_p(g2h(ptr), val);
|
||||
stl_be_p(g2h(env_cpu(env), ptr), val);
|
||||
qemu_plugin_vcpu_mem_cb(env_cpu(env), ptr, meminfo);
|
||||
}
|
||||
|
||||
@@ -1078,7 +1079,7 @@ void cpu_stq_be_data(CPUArchState *env, abi_ptr ptr, uint64_t val)
|
||||
uint16_t meminfo = trace_mem_get_info(MO_BEQ, MMU_USER_IDX, true);
|
||||
|
||||
trace_guest_mem_before_exec(env_cpu(env), ptr, meminfo);
|
||||
stq_be_p(g2h(ptr), val);
|
||||
stq_be_p(g2h(env_cpu(env), ptr), val);
|
||||
qemu_plugin_vcpu_mem_cb(env_cpu(env), ptr, meminfo);
|
||||
}
|
||||
|
||||
@@ -1087,7 +1088,7 @@ void cpu_stw_le_data(CPUArchState *env, abi_ptr ptr, uint32_t val)
|
||||
uint16_t meminfo = trace_mem_get_info(MO_LEUW, MMU_USER_IDX, true);
|
||||
|
||||
trace_guest_mem_before_exec(env_cpu(env), ptr, meminfo);
|
||||
stw_le_p(g2h(ptr), val);
|
||||
stw_le_p(g2h(env_cpu(env), ptr), val);
|
||||
qemu_plugin_vcpu_mem_cb(env_cpu(env), ptr, meminfo);
|
||||
}
|
||||
|
||||
@@ -1096,7 +1097,7 @@ void cpu_stl_le_data(CPUArchState *env, abi_ptr ptr, uint32_t val)
|
||||
uint16_t meminfo = trace_mem_get_info(MO_LEUL, MMU_USER_IDX, true);
|
||||
|
||||
trace_guest_mem_before_exec(env_cpu(env), ptr, meminfo);
|
||||
stl_le_p(g2h(ptr), val);
|
||||
stl_le_p(g2h(env_cpu(env), ptr), val);
|
||||
qemu_plugin_vcpu_mem_cb(env_cpu(env), ptr, meminfo);
|
||||
}
|
||||
|
||||
@@ -1105,7 +1106,7 @@ void cpu_stq_le_data(CPUArchState *env, abi_ptr ptr, uint64_t val)
|
||||
uint16_t meminfo = trace_mem_get_info(MO_LEQ, MMU_USER_IDX, true);
|
||||
|
||||
trace_guest_mem_before_exec(env_cpu(env), ptr, meminfo);
|
||||
stq_le_p(g2h(ptr), val);
|
||||
stq_le_p(g2h(env_cpu(env), ptr), val);
|
||||
qemu_plugin_vcpu_mem_cb(env_cpu(env), ptr, meminfo);
|
||||
}
|
||||
|
||||
@@ -1170,7 +1171,7 @@ uint32_t cpu_ldub_code(CPUArchState *env, abi_ptr ptr)
|
||||
uint32_t ret;
|
||||
|
||||
set_helper_retaddr(1);
|
||||
ret = ldub_p(g2h(ptr));
|
||||
ret = ldub_p(g2h_untagged(ptr));
|
||||
clear_helper_retaddr();
|
||||
return ret;
|
||||
}
|
||||
@@ -1180,7 +1181,7 @@ uint32_t cpu_lduw_code(CPUArchState *env, abi_ptr ptr)
|
||||
uint32_t ret;
|
||||
|
||||
set_helper_retaddr(1);
|
||||
ret = lduw_p(g2h(ptr));
|
||||
ret = lduw_p(g2h_untagged(ptr));
|
||||
clear_helper_retaddr();
|
||||
return ret;
|
||||
}
|
||||
@@ -1190,7 +1191,7 @@ uint32_t cpu_ldl_code(CPUArchState *env, abi_ptr ptr)
|
||||
uint32_t ret;
|
||||
|
||||
set_helper_retaddr(1);
|
||||
ret = ldl_p(g2h(ptr));
|
||||
ret = ldl_p(g2h_untagged(ptr));
|
||||
clear_helper_retaddr();
|
||||
return ret;
|
||||
}
|
||||
@@ -1200,7 +1201,7 @@ uint64_t cpu_ldq_code(CPUArchState *env, abi_ptr ptr)
|
||||
uint64_t ret;
|
||||
|
||||
set_helper_retaddr(1);
|
||||
ret = ldq_p(g2h(ptr));
|
||||
ret = ldq_p(g2h_untagged(ptr));
|
||||
clear_helper_retaddr();
|
||||
return ret;
|
||||
}
|
||||
@@ -1213,7 +1214,7 @@ static void *atomic_mmu_lookup(CPUArchState *env, target_ulong addr,
|
||||
if (unlikely(addr & (size - 1))) {
|
||||
cpu_loop_exit_atomic(env_cpu(env), retaddr);
|
||||
}
|
||||
void *ret = g2h(addr);
|
||||
void *ret = g2h(env_cpu(env), addr);
|
||||
set_helper_retaddr(retaddr);
|
||||
return ret;
|
||||
}
|
||||
|
||||
+1
-1
@@ -737,7 +737,7 @@ static void padzero(abi_ulong elf_bss, abi_ulong last_bss)
|
||||
end_addr1 = REAL_HOST_PAGE_ALIGN(elf_bss);
|
||||
end_addr = HOST_PAGE_ALIGN(elf_bss);
|
||||
if (end_addr1 < end_addr) {
|
||||
mmap((void *)g2h(end_addr1), end_addr - end_addr1,
|
||||
mmap((void *)g2h_untagged(end_addr1), end_addr - end_addr1,
|
||||
PROT_READ|PROT_WRITE|PROT_EXEC,
|
||||
MAP_FIXED|MAP_PRIVATE|MAP_ANON, -1, 0);
|
||||
}
|
||||
|
||||
+4
-4
@@ -42,7 +42,7 @@
|
||||
|
||||
int singlestep;
|
||||
unsigned long mmap_min_addr;
|
||||
unsigned long guest_base;
|
||||
uintptr_t guest_base;
|
||||
bool have_guest_base;
|
||||
unsigned long reserved_va;
|
||||
|
||||
@@ -970,7 +970,7 @@ int main(int argc, char **argv)
|
||||
g_free(target_environ);
|
||||
|
||||
if (qemu_loglevel_mask(CPU_LOG_PAGE)) {
|
||||
qemu_log("guest_base 0x%lx\n", guest_base);
|
||||
qemu_log("guest_base %p\n", (void *)guest_base);
|
||||
log_page_dump("binary load");
|
||||
|
||||
qemu_log("start_brk 0x" TARGET_ABI_FMT_lx "\n", info->start_brk);
|
||||
@@ -1055,7 +1055,7 @@ int main(int argc, char **argv)
|
||||
env->idt.base = target_mmap(0, sizeof(uint64_t) * (env->idt.limit + 1),
|
||||
PROT_READ|PROT_WRITE,
|
||||
MAP_ANONYMOUS|MAP_PRIVATE, -1, 0);
|
||||
idt_table = g2h(env->idt.base);
|
||||
idt_table = g2h_untagged(env->idt.base);
|
||||
set_idt(0, 0);
|
||||
set_idt(1, 0);
|
||||
set_idt(2, 0);
|
||||
@@ -1085,7 +1085,7 @@ int main(int argc, char **argv)
|
||||
PROT_READ|PROT_WRITE,
|
||||
MAP_ANONYMOUS|MAP_PRIVATE, -1, 0);
|
||||
env->gdt.limit = sizeof(uint64_t) * TARGET_GDT_ENTRIES - 1;
|
||||
gdt_table = g2h(env->gdt.base);
|
||||
gdt_table = g2h_untagged(env->gdt.base);
|
||||
#ifdef TARGET_ABI32
|
||||
write_dt(&gdt_table[__USER_CS >> 3], 0, 0xfffff,
|
||||
DESC_G_MASK | DESC_B_MASK | DESC_P_MASK | DESC_S_MASK |
|
||||
|
||||
+12
-11
@@ -102,7 +102,8 @@ int target_mprotect(abi_ulong start, abi_ulong len, int prot)
|
||||
}
|
||||
end = host_end;
|
||||
}
|
||||
ret = mprotect(g2h(host_start), qemu_host_page_size, prot1 & PAGE_BITS);
|
||||
ret = mprotect(g2h_untagged(host_start),
|
||||
qemu_host_page_size, prot1 & PAGE_BITS);
|
||||
if (ret != 0)
|
||||
goto error;
|
||||
host_start += qemu_host_page_size;
|
||||
@@ -112,8 +113,8 @@ int target_mprotect(abi_ulong start, abi_ulong len, int prot)
|
||||
for(addr = end; addr < host_end; addr += TARGET_PAGE_SIZE) {
|
||||
prot1 |= page_get_flags(addr);
|
||||
}
|
||||
ret = mprotect(g2h(host_end - qemu_host_page_size), qemu_host_page_size,
|
||||
prot1 & PAGE_BITS);
|
||||
ret = mprotect(g2h_untagged(host_end - qemu_host_page_size),
|
||||
qemu_host_page_size, prot1 & PAGE_BITS);
|
||||
if (ret != 0)
|
||||
goto error;
|
||||
host_end -= qemu_host_page_size;
|
||||
@@ -121,7 +122,7 @@ int target_mprotect(abi_ulong start, abi_ulong len, int prot)
|
||||
|
||||
/* handle the pages in the middle */
|
||||
if (host_start < host_end) {
|
||||
ret = mprotect(g2h(host_start), host_end - host_start, prot);
|
||||
ret = mprotect(g2h_untagged(host_start), host_end - host_start, prot);
|
||||
if (ret != 0)
|
||||
goto error;
|
||||
}
|
||||
@@ -143,7 +144,7 @@ static int mmap_frag(abi_ulong real_start,
|
||||
int prot1, prot_new;
|
||||
|
||||
real_end = real_start + qemu_host_page_size;
|
||||
host_start = g2h(real_start);
|
||||
host_start = g2h_untagged(real_start);
|
||||
|
||||
/* get the protection of the target pages outside the mapping */
|
||||
prot1 = 0;
|
||||
@@ -175,7 +176,7 @@ static int mmap_frag(abi_ulong real_start,
|
||||
mprotect(host_start, qemu_host_page_size, prot1 | PROT_WRITE);
|
||||
|
||||
/* read the corresponding file data */
|
||||
pread(fd, g2h(start), end - start, offset);
|
||||
pread(fd, g2h_untagged(start), end - start, offset);
|
||||
|
||||
/* put final protection */
|
||||
if (prot_new != (prot1 | PROT_WRITE))
|
||||
@@ -300,7 +301,7 @@ abi_long target_mmap(abi_ulong start, abi_ulong len, int prot,
|
||||
/* Note: we prefer to control the mapping address. It is
|
||||
especially important if qemu_host_page_size >
|
||||
qemu_real_host_page_size */
|
||||
p = mmap(g2h(mmap_start),
|
||||
p = mmap(g2h_untagged(mmap_start),
|
||||
host_len, prot, flags | MAP_FIXED, fd, host_offset);
|
||||
if (p == MAP_FAILED)
|
||||
goto fail;
|
||||
@@ -344,7 +345,7 @@ abi_long target_mmap(abi_ulong start, abi_ulong len, int prot,
|
||||
-1, 0);
|
||||
if (retaddr == -1)
|
||||
goto fail;
|
||||
pread(fd, g2h(start), len, offset);
|
||||
pread(fd, g2h_untagged(start), len, offset);
|
||||
if (!(prot & PROT_WRITE)) {
|
||||
ret = target_mprotect(start, len, prot);
|
||||
if (ret != 0) {
|
||||
@@ -390,7 +391,7 @@ abi_long target_mmap(abi_ulong start, abi_ulong len, int prot,
|
||||
offset1 = 0;
|
||||
else
|
||||
offset1 = offset + real_start - start;
|
||||
p = mmap(g2h(real_start), real_end - real_start,
|
||||
p = mmap(g2h_untagged(real_start), real_end - real_start,
|
||||
prot, flags, fd, offset1);
|
||||
if (p == MAP_FAILED)
|
||||
goto fail;
|
||||
@@ -456,7 +457,7 @@ int target_munmap(abi_ulong start, abi_ulong len)
|
||||
ret = 0;
|
||||
/* unmap what we can */
|
||||
if (real_start < real_end) {
|
||||
ret = munmap(g2h(real_start), real_end - real_start);
|
||||
ret = munmap(g2h_untagged(real_start), real_end - real_start);
|
||||
}
|
||||
|
||||
if (ret == 0)
|
||||
@@ -479,5 +480,5 @@ int target_msync(abi_ulong start, abi_ulong len, int flags)
|
||||
return 0;
|
||||
|
||||
start &= qemu_host_page_mask;
|
||||
return msync(g2h(start), end - start, flags);
|
||||
return msync(g2h_untagged(start), end - start, flags);
|
||||
}
|
||||
|
||||
+8
-9
@@ -218,13 +218,12 @@ extern unsigned long x86_stack_size;
|
||||
|
||||
/* user access */
|
||||
|
||||
#define VERIFY_READ 0
|
||||
#define VERIFY_WRITE 1 /* implies read access */
|
||||
#define VERIFY_READ PAGE_READ
|
||||
#define VERIFY_WRITE (PAGE_READ | PAGE_WRITE)
|
||||
|
||||
static inline int access_ok(int type, abi_ulong addr, abi_ulong size)
|
||||
static inline bool access_ok(int type, abi_ulong addr, abi_ulong size)
|
||||
{
|
||||
return page_check_range((target_ulong)addr, size,
|
||||
(type == VERIFY_READ) ? PAGE_READ : (PAGE_READ | PAGE_WRITE)) == 0;
|
||||
return page_check_range((target_ulong)addr, size, type) == 0;
|
||||
}
|
||||
|
||||
/* NOTE __get_user and __put_user use host pointers and don't check access. */
|
||||
@@ -357,13 +356,13 @@ static inline void *lock_user(int type, abi_ulong guest_addr, long len, int copy
|
||||
void *addr;
|
||||
addr = g_malloc(len);
|
||||
if (copy)
|
||||
memcpy(addr, g2h(guest_addr), len);
|
||||
memcpy(addr, g2h_untagged(guest_addr), len);
|
||||
else
|
||||
memset(addr, 0, len);
|
||||
return addr;
|
||||
}
|
||||
#else
|
||||
return g2h(guest_addr);
|
||||
return g2h_untagged(guest_addr);
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -377,10 +376,10 @@ static inline void unlock_user(void *host_ptr, abi_ulong guest_addr,
|
||||
#ifdef DEBUG_REMAP
|
||||
if (!host_ptr)
|
||||
return;
|
||||
if (host_ptr == g2h(guest_addr))
|
||||
if (host_ptr == g2h_untagged(guest_addr))
|
||||
return;
|
||||
if (len > 0)
|
||||
memcpy(g2h(guest_addr), host_ptr, len);
|
||||
memcpy(g2h_untagged(guest_addr), host_ptr, len);
|
||||
g_free(host_ptr);
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -43,6 +43,7 @@ Supported devices
|
||||
* GPIO controller
|
||||
* Analog to Digital Converter (ADC)
|
||||
* Pulse Width Modulation (PWM)
|
||||
* SMBus controller (SMBF)
|
||||
|
||||
Missing devices
|
||||
---------------
|
||||
@@ -58,7 +59,6 @@ Missing devices
|
||||
|
||||
* Ethernet controllers (GMAC and EMC)
|
||||
* USB device (USBD)
|
||||
* SMBus controller (SMBF)
|
||||
* Peripheral SPI controller (PSPI)
|
||||
* SD/MMC host
|
||||
* PECI interface
|
||||
|
||||
@@ -370,6 +370,7 @@ config NPCM7XX
|
||||
bool
|
||||
select A9MPCORE
|
||||
select ARM_GIC
|
||||
select AT24C # EEPROM
|
||||
select PL310 # cache controller
|
||||
select SERIAL
|
||||
select SSI
|
||||
|
||||
+52
-16
@@ -102,6 +102,22 @@ enum NPCM7xxInterrupt {
|
||||
NPCM7XX_WDG2_IRQ, /* Timer Module 2 Watchdog */
|
||||
NPCM7XX_EHCI_IRQ = 61,
|
||||
NPCM7XX_OHCI_IRQ = 62,
|
||||
NPCM7XX_SMBUS0_IRQ = 64,
|
||||
NPCM7XX_SMBUS1_IRQ,
|
||||
NPCM7XX_SMBUS2_IRQ,
|
||||
NPCM7XX_SMBUS3_IRQ,
|
||||
NPCM7XX_SMBUS4_IRQ,
|
||||
NPCM7XX_SMBUS5_IRQ,
|
||||
NPCM7XX_SMBUS6_IRQ,
|
||||
NPCM7XX_SMBUS7_IRQ,
|
||||
NPCM7XX_SMBUS8_IRQ,
|
||||
NPCM7XX_SMBUS9_IRQ,
|
||||
NPCM7XX_SMBUS10_IRQ,
|
||||
NPCM7XX_SMBUS11_IRQ,
|
||||
NPCM7XX_SMBUS12_IRQ,
|
||||
NPCM7XX_SMBUS13_IRQ,
|
||||
NPCM7XX_SMBUS14_IRQ,
|
||||
NPCM7XX_SMBUS15_IRQ,
|
||||
NPCM7XX_PWM0_IRQ = 93, /* PWM module 0 */
|
||||
NPCM7XX_PWM1_IRQ, /* PWM module 1 */
|
||||
NPCM7XX_GPIO0_IRQ = 116,
|
||||
@@ -152,6 +168,26 @@ static const hwaddr npcm7xx_pwm_addr[] = {
|
||||
0xf0104000,
|
||||
};
|
||||
|
||||
/* Direct memory-mapped access to each SMBus Module. */
|
||||
static const hwaddr npcm7xx_smbus_addr[] = {
|
||||
0xf0080000,
|
||||
0xf0081000,
|
||||
0xf0082000,
|
||||
0xf0083000,
|
||||
0xf0084000,
|
||||
0xf0085000,
|
||||
0xf0086000,
|
||||
0xf0087000,
|
||||
0xf0088000,
|
||||
0xf0089000,
|
||||
0xf008a000,
|
||||
0xf008b000,
|
||||
0xf008c000,
|
||||
0xf008d000,
|
||||
0xf008e000,
|
||||
0xf008f000,
|
||||
};
|
||||
|
||||
static const struct {
|
||||
hwaddr regs_addr;
|
||||
uint32_t unconnected_pins;
|
||||
@@ -353,6 +389,11 @@ static void npcm7xx_init(Object *obj)
|
||||
object_initialize_child(obj, "gpio[*]", &s->gpio[i], TYPE_NPCM7XX_GPIO);
|
||||
}
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(s->smbus); i++) {
|
||||
object_initialize_child(obj, "smbus[*]", &s->smbus[i],
|
||||
TYPE_NPCM7XX_SMBUS);
|
||||
}
|
||||
|
||||
object_initialize_child(obj, "ehci", &s->ehci, TYPE_NPCM7XX_EHCI);
|
||||
object_initialize_child(obj, "ohci", &s->ohci, TYPE_SYSBUS_OHCI);
|
||||
|
||||
@@ -509,6 +550,17 @@ static void npcm7xx_realize(DeviceState *dev, Error **errp)
|
||||
npcm7xx_irq(s, NPCM7XX_GPIO0_IRQ + i));
|
||||
}
|
||||
|
||||
/* SMBus modules. Cannot fail. */
|
||||
QEMU_BUILD_BUG_ON(ARRAY_SIZE(npcm7xx_smbus_addr) != ARRAY_SIZE(s->smbus));
|
||||
for (i = 0; i < ARRAY_SIZE(s->smbus); i++) {
|
||||
Object *obj = OBJECT(&s->smbus[i]);
|
||||
|
||||
sysbus_realize(SYS_BUS_DEVICE(obj), &error_abort);
|
||||
sysbus_mmio_map(SYS_BUS_DEVICE(obj), 0, npcm7xx_smbus_addr[i]);
|
||||
sysbus_connect_irq(SYS_BUS_DEVICE(obj), 0,
|
||||
npcm7xx_irq(s, NPCM7XX_SMBUS0_IRQ + i));
|
||||
}
|
||||
|
||||
/* USB Host */
|
||||
object_property_set_bool(OBJECT(&s->ehci), "companion-enable", true,
|
||||
&error_abort);
|
||||
@@ -576,22 +628,6 @@ static void npcm7xx_realize(DeviceState *dev, Error **errp)
|
||||
create_unimplemented_device("npcm7xx.pcierc", 0xe1000000, 64 * KiB);
|
||||
create_unimplemented_device("npcm7xx.kcs", 0xf0007000, 4 * KiB);
|
||||
create_unimplemented_device("npcm7xx.gfxi", 0xf000e000, 4 * KiB);
|
||||
create_unimplemented_device("npcm7xx.smbus[0]", 0xf0080000, 4 * KiB);
|
||||
create_unimplemented_device("npcm7xx.smbus[1]", 0xf0081000, 4 * KiB);
|
||||
create_unimplemented_device("npcm7xx.smbus[2]", 0xf0082000, 4 * KiB);
|
||||
create_unimplemented_device("npcm7xx.smbus[3]", 0xf0083000, 4 * KiB);
|
||||
create_unimplemented_device("npcm7xx.smbus[4]", 0xf0084000, 4 * KiB);
|
||||
create_unimplemented_device("npcm7xx.smbus[5]", 0xf0085000, 4 * KiB);
|
||||
create_unimplemented_device("npcm7xx.smbus[6]", 0xf0086000, 4 * KiB);
|
||||
create_unimplemented_device("npcm7xx.smbus[7]", 0xf0087000, 4 * KiB);
|
||||
create_unimplemented_device("npcm7xx.smbus[8]", 0xf0088000, 4 * KiB);
|
||||
create_unimplemented_device("npcm7xx.smbus[9]", 0xf0089000, 4 * KiB);
|
||||
create_unimplemented_device("npcm7xx.smbus[10]", 0xf008a000, 4 * KiB);
|
||||
create_unimplemented_device("npcm7xx.smbus[11]", 0xf008b000, 4 * KiB);
|
||||
create_unimplemented_device("npcm7xx.smbus[12]", 0xf008c000, 4 * KiB);
|
||||
create_unimplemented_device("npcm7xx.smbus[13]", 0xf008d000, 4 * KiB);
|
||||
create_unimplemented_device("npcm7xx.smbus[14]", 0xf008e000, 4 * KiB);
|
||||
create_unimplemented_device("npcm7xx.smbus[15]", 0xf008f000, 4 * KiB);
|
||||
create_unimplemented_device("npcm7xx.espi", 0xf009f000, 4 * KiB);
|
||||
create_unimplemented_device("npcm7xx.peci", 0xf0100000, 4 * KiB);
|
||||
create_unimplemented_device("npcm7xx.siox[1]", 0xf0101000, 4 * KiB);
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
#include "exec/address-spaces.h"
|
||||
#include "hw/arm/npcm7xx.h"
|
||||
#include "hw/core/cpu.h"
|
||||
#include "hw/i2c/smbus_eeprom.h"
|
||||
#include "hw/loader.h"
|
||||
#include "hw/qdev-properties.h"
|
||||
#include "qapi/error.h"
|
||||
@@ -98,6 +99,49 @@ static NPCM7xxState *npcm7xx_create_soc(MachineState *machine,
|
||||
return NPCM7XX(obj);
|
||||
}
|
||||
|
||||
static I2CBus *npcm7xx_i2c_get_bus(NPCM7xxState *soc, uint32_t num)
|
||||
{
|
||||
g_assert(num < ARRAY_SIZE(soc->smbus));
|
||||
return I2C_BUS(qdev_get_child_bus(DEVICE(&soc->smbus[num]), "i2c-bus"));
|
||||
}
|
||||
|
||||
static void at24c_eeprom_init(NPCM7xxState *soc, int bus, uint8_t addr,
|
||||
uint32_t rsize)
|
||||
{
|
||||
I2CBus *i2c_bus = npcm7xx_i2c_get_bus(soc, bus);
|
||||
I2CSlave *i2c_dev = i2c_slave_new("at24c-eeprom", addr);
|
||||
DeviceState *dev = DEVICE(i2c_dev);
|
||||
|
||||
qdev_prop_set_uint32(dev, "rom-size", rsize);
|
||||
i2c_slave_realize_and_unref(i2c_dev, i2c_bus, &error_abort);
|
||||
}
|
||||
|
||||
static void npcm750_evb_i2c_init(NPCM7xxState *soc)
|
||||
{
|
||||
/* lm75 temperature sensor on SVB, tmp105 is compatible */
|
||||
i2c_slave_create_simple(npcm7xx_i2c_get_bus(soc, 0), "tmp105", 0x48);
|
||||
/* lm75 temperature sensor on EB, tmp105 is compatible */
|
||||
i2c_slave_create_simple(npcm7xx_i2c_get_bus(soc, 1), "tmp105", 0x48);
|
||||
/* tmp100 temperature sensor on EB, tmp105 is compatible */
|
||||
i2c_slave_create_simple(npcm7xx_i2c_get_bus(soc, 2), "tmp105", 0x48);
|
||||
/* tmp100 temperature sensor on SVB, tmp105 is compatible */
|
||||
i2c_slave_create_simple(npcm7xx_i2c_get_bus(soc, 6), "tmp105", 0x48);
|
||||
}
|
||||
|
||||
static void quanta_gsj_i2c_init(NPCM7xxState *soc)
|
||||
{
|
||||
/* GSJ machine have 4 max31725 temperature sensors, tmp105 is compatible. */
|
||||
i2c_slave_create_simple(npcm7xx_i2c_get_bus(soc, 1), "tmp105", 0x5c);
|
||||
i2c_slave_create_simple(npcm7xx_i2c_get_bus(soc, 2), "tmp105", 0x5c);
|
||||
i2c_slave_create_simple(npcm7xx_i2c_get_bus(soc, 3), "tmp105", 0x5c);
|
||||
i2c_slave_create_simple(npcm7xx_i2c_get_bus(soc, 4), "tmp105", 0x5c);
|
||||
|
||||
at24c_eeprom_init(soc, 9, 0x55, 8192);
|
||||
at24c_eeprom_init(soc, 10, 0x55, 8192);
|
||||
|
||||
/* TODO: Add additional i2c devices. */
|
||||
}
|
||||
|
||||
static void npcm750_evb_init(MachineState *machine)
|
||||
{
|
||||
NPCM7xxState *soc;
|
||||
@@ -108,6 +152,7 @@ static void npcm750_evb_init(MachineState *machine)
|
||||
|
||||
npcm7xx_load_bootrom(machine, soc);
|
||||
npcm7xx_connect_flash(&soc->fiu[0], 0, "w25q256", drive_get(IF_MTD, 0, 0));
|
||||
npcm750_evb_i2c_init(soc);
|
||||
npcm7xx_load_kernel(machine, soc);
|
||||
}
|
||||
|
||||
@@ -122,6 +167,7 @@ static void quanta_gsj_init(MachineState *machine)
|
||||
npcm7xx_load_bootrom(machine, soc);
|
||||
npcm7xx_connect_flash(&soc->fiu[0], 0, "mx25l25635e",
|
||||
drive_get(IF_MTD, 0, 0));
|
||||
quanta_gsj_i2c_init(soc);
|
||||
npcm7xx_load_kernel(machine, soc);
|
||||
}
|
||||
|
||||
|
||||
@@ -9,6 +9,7 @@ i2c_ss.add(when: 'CONFIG_EXYNOS4', if_true: files('exynos4210_i2c.c'))
|
||||
i2c_ss.add(when: 'CONFIG_IMX_I2C', if_true: files('imx_i2c.c'))
|
||||
i2c_ss.add(when: 'CONFIG_MPC_I2C', if_true: files('mpc_i2c.c'))
|
||||
i2c_ss.add(when: 'CONFIG_NRF51_SOC', if_true: files('microbit_i2c.c'))
|
||||
i2c_ss.add(when: 'CONFIG_NPCM7XX', if_true: files('npcm7xx_smbus.c'))
|
||||
i2c_ss.add(when: 'CONFIG_SMBUS_EEPROM', if_true: files('smbus_eeprom.c'))
|
||||
i2c_ss.add(when: 'CONFIG_VERSATILE_I2C', if_true: files('versatile_i2c.c'))
|
||||
i2c_ss.add(when: 'CONFIG_OMAP', if_true: files('omap_i2c.c'))
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -14,3 +14,15 @@ aspeed_i2c_bus_read(uint32_t busid, uint64_t offset, unsigned size, uint64_t val
|
||||
aspeed_i2c_bus_write(uint32_t busid, uint64_t offset, unsigned size, uint64_t value) "bus[%d]: To 0x%" PRIx64 " of size %u: 0x%" PRIx64
|
||||
aspeed_i2c_bus_send(const char *mode, int i, int count, uint8_t byte) "%s send %d/%d 0x%02x"
|
||||
aspeed_i2c_bus_recv(const char *mode, int i, int count, uint8_t byte) "%s recv %d/%d 0x%02x"
|
||||
|
||||
# npcm7xx_smbus.c
|
||||
|
||||
npcm7xx_smbus_read(const char *id, uint64_t offset, uint64_t value, unsigned size) "%s offset: 0x%04" PRIx64 " value: 0x%02" PRIx64 " size: %u"
|
||||
npcm7xx_smbus_write(const char *id, uint64_t offset, uint64_t value, unsigned size) "%s offset: 0x%04" PRIx64 " value: 0x%02" PRIx64 " size: %u"
|
||||
npcm7xx_smbus_start(const char *id, int success) "%s starting, success: %d"
|
||||
npcm7xx_smbus_send_address(const char *id, uint8_t addr, int recv, int success) "%s sending address: 0x%02x, recv: %d, success: %d"
|
||||
npcm7xx_smbus_send_byte(const char *id, uint8_t value, int success) "%s send byte: 0x%02x, success: %d"
|
||||
npcm7xx_smbus_recv_byte(const char *id, uint8_t value) "%s recv byte: 0x%02x"
|
||||
npcm7xx_smbus_stop(const char *id) "%s stopping"
|
||||
npcm7xx_smbus_nack(const char *id) "%s nacking"
|
||||
npcm7xx_smbus_recv_fifo(const char *id, uint8_t received, uint8_t expected) "%s recv fifo: received %u, expected %u"
|
||||
|
||||
+40
-7
@@ -150,7 +150,7 @@ static inline void tswap64s(uint64_t *s)
|
||||
/* On some host systems the guest address space is reserved on the host.
|
||||
* This allows the guest address space to be offset to a convenient location.
|
||||
*/
|
||||
extern unsigned long guest_base;
|
||||
extern uintptr_t guest_base;
|
||||
extern bool have_guest_base;
|
||||
extern unsigned long reserved_va;
|
||||
|
||||
@@ -256,18 +256,27 @@ extern intptr_t qemu_host_page_mask;
|
||||
#define PAGE_EXEC 0x0004
|
||||
#define PAGE_BITS (PAGE_READ | PAGE_WRITE | PAGE_EXEC)
|
||||
#define PAGE_VALID 0x0008
|
||||
/* original state of the write flag (used when tracking self-modifying
|
||||
code */
|
||||
/*
|
||||
* Original state of the write flag (used when tracking self-modifying code)
|
||||
*/
|
||||
#define PAGE_WRITE_ORG 0x0010
|
||||
/* Invalidate the TLB entry immediately, helpful for s390x
|
||||
* Low-Address-Protection. Used with PAGE_WRITE in tlb_set_page_with_attrs() */
|
||||
#define PAGE_WRITE_INV 0x0040
|
||||
/*
|
||||
* Invalidate the TLB entry immediately, helpful for s390x
|
||||
* Low-Address-Protection. Used with PAGE_WRITE in tlb_set_page_with_attrs()
|
||||
*/
|
||||
#define PAGE_WRITE_INV 0x0020
|
||||
/* For use with page_set_flags: page is being replaced; target_data cleared. */
|
||||
#define PAGE_RESET 0x0040
|
||||
/* For linux-user, indicates that the page is MAP_ANON. */
|
||||
#define PAGE_ANON 0x0080
|
||||
|
||||
#if defined(CONFIG_BSD) && defined(CONFIG_USER_ONLY)
|
||||
/* FIXME: Code that sets/uses this is broken and needs to go away. */
|
||||
#define PAGE_RESERVED 0x0020
|
||||
#define PAGE_RESERVED 0x0100
|
||||
#endif
|
||||
/* Target-specific bits that will be used via page_get_flags(). */
|
||||
#define PAGE_TARGET_1 0x0080
|
||||
#define PAGE_TARGET_2 0x0200
|
||||
|
||||
#if defined(CONFIG_USER_ONLY)
|
||||
void page_dump(FILE *f);
|
||||
@@ -279,6 +288,30 @@ int walk_memory_regions(void *, walk_memory_regions_fn);
|
||||
int page_get_flags(target_ulong address);
|
||||
void page_set_flags(target_ulong start, target_ulong end, int flags);
|
||||
int page_check_range(target_ulong start, target_ulong len, int flags);
|
||||
|
||||
/**
|
||||
* page_alloc_target_data(address, size)
|
||||
* @address: guest virtual address
|
||||
* @size: size of data to allocate
|
||||
*
|
||||
* Allocate @size bytes of out-of-band data to associate with the
|
||||
* guest page at @address. If the page is not mapped, NULL will
|
||||
* be returned. If there is existing data associated with @address,
|
||||
* no new memory will be allocated.
|
||||
*
|
||||
* The memory will be freed when the guest page is deallocated,
|
||||
* e.g. with the munmap system call.
|
||||
*/
|
||||
void *page_alloc_target_data(target_ulong address, size_t size);
|
||||
|
||||
/**
|
||||
* page_get_target_data(address)
|
||||
* @address: guest virtual address
|
||||
*
|
||||
* Return any out-of-bound memory assocated with the guest page
|
||||
* at @address, as per page_alloc_target_data.
|
||||
*/
|
||||
void *page_get_target_data(target_ulong address);
|
||||
#endif
|
||||
|
||||
CPUArchState *cpu_copy(CPUArchState *env);
|
||||
|
||||
+28
-11
@@ -69,23 +69,40 @@ typedef uint64_t abi_ptr;
|
||||
#define TARGET_ABI_FMT_ptr "%"PRIx64
|
||||
#endif
|
||||
|
||||
/* All direct uses of g2h and h2g need to go away for usermode softmmu. */
|
||||
#define g2h(x) ((void *)((unsigned long)(abi_ptr)(x) + guest_base))
|
||||
|
||||
#if HOST_LONG_BITS <= TARGET_VIRT_ADDR_SPACE_BITS
|
||||
#define guest_addr_valid(x) (1)
|
||||
#else
|
||||
#define guest_addr_valid(x) ((x) <= GUEST_ADDR_MAX)
|
||||
#ifndef TARGET_TAGGED_ADDRESSES
|
||||
static inline abi_ptr cpu_untagged_addr(CPUState *cs, abi_ptr x)
|
||||
{
|
||||
return x;
|
||||
}
|
||||
#endif
|
||||
#define h2g_valid(x) guest_addr_valid((unsigned long)(x) - guest_base)
|
||||
|
||||
static inline int guest_range_valid(unsigned long start, unsigned long len)
|
||||
/* All direct uses of g2h and h2g need to go away for usermode softmmu. */
|
||||
static inline void *g2h_untagged(abi_ptr x)
|
||||
{
|
||||
return (void *)((uintptr_t)(x) + guest_base);
|
||||
}
|
||||
|
||||
static inline void *g2h(CPUState *cs, abi_ptr x)
|
||||
{
|
||||
return g2h_untagged(cpu_untagged_addr(cs, x));
|
||||
}
|
||||
|
||||
static inline bool guest_addr_valid_untagged(abi_ulong x)
|
||||
{
|
||||
return x <= GUEST_ADDR_MAX;
|
||||
}
|
||||
|
||||
static inline bool guest_range_valid_untagged(abi_ulong start, abi_ulong len)
|
||||
{
|
||||
return len - 1 <= GUEST_ADDR_MAX && start <= GUEST_ADDR_MAX - len + 1;
|
||||
}
|
||||
|
||||
#define h2g_valid(x) \
|
||||
(HOST_LONG_BITS <= TARGET_VIRT_ADDR_SPACE_BITS || \
|
||||
(uintptr_t)(x) - guest_base <= GUEST_ADDR_MAX)
|
||||
|
||||
#define h2g_nocheck(x) ({ \
|
||||
unsigned long __ret = (unsigned long)(x) - guest_base; \
|
||||
uintptr_t __ret = (uintptr_t)(x) - guest_base; \
|
||||
(abi_ptr)__ret; \
|
||||
})
|
||||
|
||||
@@ -439,7 +456,7 @@ static inline int cpu_ldsw_code(CPUArchState *env, abi_ptr addr)
|
||||
static inline void *tlb_vaddr_to_host(CPUArchState *env, abi_ptr addr,
|
||||
MMUAccessType access_type, int mmu_idx)
|
||||
{
|
||||
return g2h(addr);
|
||||
return g2h(env_cpu(env), addr);
|
||||
}
|
||||
#else
|
||||
void *tlb_vaddr_to_host(CPUArchState *env, abi_ptr addr,
|
||||
|
||||
@@ -616,7 +616,7 @@ static inline tb_page_addr_t get_page_addr_code_hostp(CPUArchState *env,
|
||||
void **hostp)
|
||||
{
|
||||
if (hostp) {
|
||||
*hostp = g2h(addr);
|
||||
*hostp = g2h_untagged(addr);
|
||||
}
|
||||
return addr;
|
||||
}
|
||||
|
||||
@@ -20,6 +20,7 @@
|
||||
#include "hw/adc/npcm7xx_adc.h"
|
||||
#include "hw/cpu/a9mpcore.h"
|
||||
#include "hw/gpio/npcm7xx_gpio.h"
|
||||
#include "hw/i2c/npcm7xx_smbus.h"
|
||||
#include "hw/mem/npcm7xx_mc.h"
|
||||
#include "hw/misc/npcm7xx_clk.h"
|
||||
#include "hw/misc/npcm7xx_gcr.h"
|
||||
@@ -85,6 +86,7 @@ typedef struct NPCM7xxState {
|
||||
NPCM7xxMCState mc;
|
||||
NPCM7xxRNGState rng;
|
||||
NPCM7xxGPIOState gpio[8];
|
||||
NPCM7xxSMBusState smbus[16];
|
||||
EHCISysBusState ehci;
|
||||
OHCISysBusState ohci;
|
||||
NPCM7xxFIUState fiu[2];
|
||||
|
||||
@@ -0,0 +1,113 @@
|
||||
/*
|
||||
* Nuvoton NPCM7xx SMBus Module.
|
||||
*
|
||||
* Copyright 2020 Google LLC
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* for more details.
|
||||
*/
|
||||
#ifndef NPCM7XX_SMBUS_H
|
||||
#define NPCM7XX_SMBUS_H
|
||||
|
||||
#include "exec/memory.h"
|
||||
#include "hw/i2c/i2c.h"
|
||||
#include "hw/irq.h"
|
||||
#include "hw/sysbus.h"
|
||||
|
||||
/*
|
||||
* Number of addresses this module contains. Do not change this without
|
||||
* incrementing the version_id in the vmstate.
|
||||
*/
|
||||
#define NPCM7XX_SMBUS_NR_ADDRS 10
|
||||
|
||||
/* Size of the FIFO buffer. */
|
||||
#define NPCM7XX_SMBUS_FIFO_SIZE 16
|
||||
|
||||
typedef enum NPCM7xxSMBusStatus {
|
||||
NPCM7XX_SMBUS_STATUS_IDLE,
|
||||
NPCM7XX_SMBUS_STATUS_SENDING,
|
||||
NPCM7XX_SMBUS_STATUS_RECEIVING,
|
||||
NPCM7XX_SMBUS_STATUS_NEGACK,
|
||||
NPCM7XX_SMBUS_STATUS_STOPPING_LAST_RECEIVE,
|
||||
NPCM7XX_SMBUS_STATUS_STOPPING_NEGACK,
|
||||
} NPCM7xxSMBusStatus;
|
||||
|
||||
/*
|
||||
* struct NPCM7xxSMBusState - System Management Bus device state.
|
||||
* @bus: The underlying I2C Bus.
|
||||
* @irq: GIC interrupt line to fire on events (if enabled).
|
||||
* @sda: The serial data register.
|
||||
* @st: The status register.
|
||||
* @cst: The control status register.
|
||||
* @cst2: The control status register 2.
|
||||
* @cst3: The control status register 3.
|
||||
* @ctl1: The control register 1.
|
||||
* @ctl2: The control register 2.
|
||||
* @ctl3: The control register 3.
|
||||
* @ctl4: The control register 4.
|
||||
* @ctl5: The control register 5.
|
||||
* @addr: The SMBus module's own addresses on the I2C bus.
|
||||
* @scllt: The SCL low time register.
|
||||
* @sclht: The SCL high time register.
|
||||
* @fif_ctl: The FIFO control register.
|
||||
* @fif_cts: The FIFO control status register.
|
||||
* @fair_per: The fair preriod register.
|
||||
* @txf_ctl: The transmit FIFO control register.
|
||||
* @t_out: The SMBus timeout register.
|
||||
* @txf_sts: The transmit FIFO status register.
|
||||
* @rxf_sts: The receive FIFO status register.
|
||||
* @rxf_ctl: The receive FIFO control register.
|
||||
* @rx_fifo: The FIFO buffer for receiving in FIFO mode.
|
||||
* @rx_cur: The current position of rx_fifo.
|
||||
* @status: The current status of the SMBus.
|
||||
*/
|
||||
typedef struct NPCM7xxSMBusState {
|
||||
SysBusDevice parent;
|
||||
|
||||
MemoryRegion iomem;
|
||||
|
||||
I2CBus *bus;
|
||||
qemu_irq irq;
|
||||
|
||||
uint8_t sda;
|
||||
uint8_t st;
|
||||
uint8_t cst;
|
||||
uint8_t cst2;
|
||||
uint8_t cst3;
|
||||
uint8_t ctl1;
|
||||
uint8_t ctl2;
|
||||
uint8_t ctl3;
|
||||
uint8_t ctl4;
|
||||
uint8_t ctl5;
|
||||
uint8_t addr[NPCM7XX_SMBUS_NR_ADDRS];
|
||||
|
||||
uint8_t scllt;
|
||||
uint8_t sclht;
|
||||
|
||||
uint8_t fif_ctl;
|
||||
uint8_t fif_cts;
|
||||
uint8_t fair_per;
|
||||
uint8_t txf_ctl;
|
||||
uint8_t t_out;
|
||||
uint8_t txf_sts;
|
||||
uint8_t rxf_sts;
|
||||
uint8_t rxf_ctl;
|
||||
|
||||
uint8_t rx_fifo[NPCM7XX_SMBUS_FIFO_SIZE];
|
||||
uint8_t rx_cur;
|
||||
|
||||
NPCM7xxSMBusStatus status;
|
||||
} NPCM7xxSMBusState;
|
||||
|
||||
#define TYPE_NPCM7XX_SMBUS "npcm7xx-smbus"
|
||||
#define NPCM7XX_SMBUS(obj) OBJECT_CHECK(NPCM7xxSMBusState, (obj), \
|
||||
TYPE_NPCM7XX_SMBUS)
|
||||
|
||||
#endif /* NPCM7XX_SMBUS_H */
|
||||
@@ -23,6 +23,7 @@
|
||||
#include "cpu_loop-common.h"
|
||||
#include "qemu/guest-random.h"
|
||||
#include "hw/semihosting/common-semi.h"
|
||||
#include "target/arm/syndrome.h"
|
||||
|
||||
#define get_user_code_u32(x, gaddr, env) \
|
||||
({ abi_long __r = get_user_u32((x), (gaddr)); \
|
||||
@@ -76,7 +77,7 @@
|
||||
void cpu_loop(CPUARMState *env)
|
||||
{
|
||||
CPUState *cs = env_cpu(env);
|
||||
int trapnr;
|
||||
int trapnr, ec, fsc;
|
||||
abi_long ret;
|
||||
target_siginfo_t info;
|
||||
|
||||
@@ -117,9 +118,29 @@ void cpu_loop(CPUARMState *env)
|
||||
case EXCP_DATA_ABORT:
|
||||
info.si_signo = TARGET_SIGSEGV;
|
||||
info.si_errno = 0;
|
||||
/* XXX: check env->error_code */
|
||||
info.si_code = TARGET_SEGV_MAPERR;
|
||||
info._sifields._sigfault._addr = env->exception.vaddress;
|
||||
|
||||
/* We should only arrive here with EC in {DATAABORT, INSNABORT}. */
|
||||
ec = syn_get_ec(env->exception.syndrome);
|
||||
assert(ec == EC_DATAABORT || ec == EC_INSNABORT);
|
||||
|
||||
/* Both EC have the same format for FSC, or close enough. */
|
||||
fsc = extract32(env->exception.syndrome, 0, 6);
|
||||
switch (fsc) {
|
||||
case 0x04 ... 0x07: /* Translation fault, level {0-3} */
|
||||
info.si_code = TARGET_SEGV_MAPERR;
|
||||
break;
|
||||
case 0x09 ... 0x0b: /* Access flag fault, level {1-3} */
|
||||
case 0x0d ... 0x0f: /* Permission fault, level {1-3} */
|
||||
info.si_code = TARGET_SEGV_ACCERR;
|
||||
break;
|
||||
case 0x11: /* Synchronous Tag Check Fault */
|
||||
info.si_code = TARGET_SEGV_MTESERR;
|
||||
break;
|
||||
default:
|
||||
g_assert_not_reached();
|
||||
}
|
||||
|
||||
queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info);
|
||||
break;
|
||||
case EXCP_DEBUG:
|
||||
@@ -143,6 +164,17 @@ void cpu_loop(CPUARMState *env)
|
||||
EXCP_DUMP(env, "qemu: unhandled CPU exception 0x%x - aborting\n", trapnr);
|
||||
abort();
|
||||
}
|
||||
|
||||
/* Check for MTE asynchronous faults */
|
||||
if (unlikely(env->cp15.tfsr_el[0])) {
|
||||
env->cp15.tfsr_el[0] = 0;
|
||||
info.si_signo = TARGET_SIGSEGV;
|
||||
info.si_errno = 0;
|
||||
info._sifields._sigfault._addr = 0;
|
||||
info.si_code = TARGET_SEGV_MTEAERR;
|
||||
queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info);
|
||||
}
|
||||
|
||||
process_pending_signals(env);
|
||||
/* Exception return on AArch64 always clears the exclusive monitor,
|
||||
* so any return to running guest code implies this.
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user