#include "qemu/cutils.h"
#include "qemu/cacheflush.h"
+#include "qemu/hbitmap.h"
#include "qemu/madvise.h"
#ifdef CONFIG_TCG
return cpu->cpu_ases[asidx].as;
}
-/* Add a watchpoint. */
-int cpu_watchpoint_insert(CPUState *cpu, vaddr addr, vaddr len,
- int flags, CPUWatchpoint **watchpoint)
-{
- CPUWatchpoint *wp;
- vaddr in_page;
-
- /* forbid ranges which are empty or run off the end of the address space */
- if (len == 0 || (addr + len - 1) < addr) {
- error_report("tried to set invalid watchpoint at %"
- VADDR_PRIx ", len=%" VADDR_PRIu, addr, len);
- return -EINVAL;
- }
- wp = g_malloc(sizeof(*wp));
-
- wp->vaddr = addr;
- wp->len = len;
- wp->flags = flags;
-
- /* keep all GDB-injected watchpoints in front */
- if (flags & BP_GDB) {
- QTAILQ_INSERT_HEAD(&cpu->watchpoints, wp, entry);
- } else {
- QTAILQ_INSERT_TAIL(&cpu->watchpoints, wp, entry);
- }
-
- in_page = -(addr | TARGET_PAGE_MASK);
- if (len <= in_page) {
- tlb_flush_page(cpu, addr);
- } else {
- tlb_flush(cpu);
- }
-
- if (watchpoint)
- *watchpoint = wp;
- return 0;
-}
-
-/* Remove a specific watchpoint. */
-int cpu_watchpoint_remove(CPUState *cpu, vaddr addr, vaddr len,
- int flags)
-{
- CPUWatchpoint *wp;
-
- QTAILQ_FOREACH(wp, &cpu->watchpoints, entry) {
- if (addr == wp->vaddr && len == wp->len
- && flags == (wp->flags & ~BP_WATCHPOINT_HIT)) {
- cpu_watchpoint_remove_by_ref(cpu, wp);
- return 0;
- }
- }
- return -ENOENT;
-}
-
-/* Remove a specific watchpoint by reference. */
-void cpu_watchpoint_remove_by_ref(CPUState *cpu, CPUWatchpoint *watchpoint)
-{
- QTAILQ_REMOVE(&cpu->watchpoints, watchpoint, entry);
-
- tlb_flush_page(cpu, watchpoint->vaddr);
-
- g_free(watchpoint);
-}
-
-/* Remove all matching watchpoints. */
-void cpu_watchpoint_remove_all(CPUState *cpu, int mask)
-{
- CPUWatchpoint *wp, *next;
-
- QTAILQ_FOREACH_SAFE(wp, &cpu->watchpoints, entry, next) {
- if (wp->flags & mask) {
- cpu_watchpoint_remove_by_ref(cpu, wp);
- }
- }
-}
-
-#ifdef CONFIG_TCG
-/* Return true if this watchpoint address matches the specified
- * access (ie the address range covered by the watchpoint overlaps
- * partially or completely with the address range covered by the
- * access).
- */
-static inline bool watchpoint_address_matches(CPUWatchpoint *wp,
- vaddr addr, vaddr len)
-{
- /* We know the lengths are non-zero, but a little caution is
- * required to avoid errors in the case where the range ends
- * exactly at the top of the address space and so addr + len
- * wraps round to zero.
- */
- vaddr wpend = wp->vaddr + wp->len - 1;
- vaddr addrend = addr + len - 1;
-
- return !(addr > wpend || wp->vaddr > addrend);
-}
-
-/* Return flags for watchpoints that match addr + prot. */
-int cpu_watchpoint_address_matches(CPUState *cpu, vaddr addr, vaddr len)
-{
- CPUWatchpoint *wp;
- int ret = 0;
-
- QTAILQ_FOREACH(wp, &cpu->watchpoints, entry) {
- if (watchpoint_address_matches(wp, addr, len)) {
- ret |= wp->flags;
- }
- }
- return ret;
-}
-
-/* Generate a debug exception if a watchpoint has been hit. */
-void cpu_check_watchpoint(CPUState *cpu, vaddr addr, vaddr len,
- MemTxAttrs attrs, int flags, uintptr_t ra)
-{
- CPUClass *cc = CPU_GET_CLASS(cpu);
- CPUWatchpoint *wp;
-
- assert(tcg_enabled());
- if (cpu->watchpoint_hit) {
- /*
- * We re-entered the check after replacing the TB.
- * Now raise the debug interrupt so that it will
- * trigger after the current instruction.
- */
- qemu_mutex_lock_iothread();
- cpu_interrupt(cpu, CPU_INTERRUPT_DEBUG);
- qemu_mutex_unlock_iothread();
- return;
- }
-
- if (cc->tcg_ops->adjust_watchpoint_address) {
- /* this is currently used only by ARM BE32 */
- addr = cc->tcg_ops->adjust_watchpoint_address(cpu, addr, len);
- }
- QTAILQ_FOREACH(wp, &cpu->watchpoints, entry) {
- if (watchpoint_address_matches(wp, addr, len)
- && (wp->flags & flags)) {
- if (replay_running_debug()) {
- /*
- * replay_breakpoint reads icount.
- * Force recompile to succeed, because icount may
- * be read only at the end of the block.
- */
- if (!cpu->can_do_io) {
- /* Force execution of one insn next time. */
- cpu->cflags_next_tb = 1 | CF_LAST_IO | CF_NOIRQ | curr_cflags(cpu);
- cpu_loop_exit_restore(cpu, ra);
- }
- /*
- * Don't process the watchpoints when we are
- * in a reverse debugging operation.
- */
- replay_breakpoint();
- return;
- }
- if (flags == BP_MEM_READ) {
- wp->flags |= BP_WATCHPOINT_HIT_READ;
- } else {
- wp->flags |= BP_WATCHPOINT_HIT_WRITE;
- }
- wp->hitaddr = MAX(addr, wp->vaddr);
- wp->hitattrs = attrs;
-
- if (wp->flags & BP_CPU && cc->tcg_ops->debug_check_watchpoint &&
- !cc->tcg_ops->debug_check_watchpoint(cpu, wp)) {
- wp->flags &= ~BP_WATCHPOINT_HIT;
- continue;
- }
- cpu->watchpoint_hit = wp;
-
- mmap_lock();
- /* This call also restores vCPU state */
- tb_check_watchpoint(cpu, ra);
- if (wp->flags & BP_STOP_BEFORE_ACCESS) {
- cpu->exception_index = EXCP_DEBUG;
- mmap_unlock();
- cpu_loop_exit(cpu);
- } else {
- /* Force execution of one insn next time. */
- cpu->cflags_next_tb = 1 | CF_LAST_IO | CF_NOIRQ | curr_cflags(cpu);
- mmap_unlock();
- cpu_loop_exit_noexc(cpu);
- }
- } else {
- wp->flags &= ~BP_WATCHPOINT_HIT;
- }
- }
-}
-
-#endif /* CONFIG_TCG */
-
/* Called from RCU critical section */
static RAMBlock *qemu_get_ram_block(ram_addr_t addr)
{
rb->flags &= ~RAM_MIGRATABLE;
}
+int qemu_ram_get_fd(RAMBlock *rb)
+{
+ return rb->fd;
+}
+
/* Called with iothread lock held. */
void qemu_ram_set_idstr(RAMBlock *new_block, const char *name, DeviceState *dev)
{
return block->offset + offset;
}
+ram_addr_t qemu_ram_addr_from_host_nofail(void *ptr)
+{
+ ram_addr_t ram_addr;
+
+ ram_addr = qemu_ram_addr_from_host(ptr);
+ if (ram_addr == RAM_ADDR_INVALID) {
+ error_report("Bad ram pointer %p", ptr);
+ abort();
+ }
+ return ram_addr;
+}
+
static MemTxResult flatview_read(FlatView *fv, hwaddr addr,
MemTxAttrs attrs, void *buf, hwaddr len);
static MemTxResult flatview_write(FlatView *fv, hwaddr addr, MemTxAttrs attrs,
MemTxResult res;
#if defined(DEBUG_SUBPAGE)
- printf("%s: subpage %p len %u addr " TARGET_FMT_plx "\n", __func__,
+ printf("%s: subpage %p len %u addr " HWADDR_FMT_plx "\n", __func__,
subpage, len, addr);
#endif
res = flatview_read(subpage->fv, addr + subpage->base, attrs, buf, len);
uint8_t buf[8];
#if defined(DEBUG_SUBPAGE)
- printf("%s: subpage %p len %u addr " TARGET_FMT_plx
+ printf("%s: subpage %p len %u addr " HWADDR_FMT_plx
" value %"PRIx64"\n",
__func__, subpage, len, addr, value);
#endif
{
subpage_t *subpage = opaque;
#if defined(DEBUG_SUBPAGE)
- printf("%s: subpage %p %c len %u addr " TARGET_FMT_plx "\n",
+ printf("%s: subpage %p %c len %u addr " HWADDR_FMT_plx "\n",
__func__, subpage, is_write ? 'w' : 'r', len, addr);
#endif
NULL, TARGET_PAGE_SIZE);
mmio->iomem.subpage = true;
#if defined(DEBUG_SUBPAGE)
- printf("%s: %p base " TARGET_FMT_plx " len %08x\n", __func__,
+ printf("%s: %p base " HWADDR_FMT_plx " len %08x\n", __func__,
mmio, base, TARGET_PAGE_SIZE);
#endif
hwaddr len = *plen;
hwaddr l, xlat;
MemoryRegion *mr;
- void *ptr;
FlatView *fv;
if (len == 0) {
*plen = flatview_extend_translation(fv, addr, len, mr, xlat,
l, is_write, attrs);
fuzz_dma_read_cb(addr, *plen, mr);
- ptr = qemu_ram_ptr_length(mr->ram_block, xlat, plen, true);
-
- return ptr;
+ return qemu_ram_ptr_length(mr->ram_block, xlat, plen, true);
}
/* Unmaps a memory region previously mapped by address_space_map().
{
MemoryRegion*mr;
hwaddr l = 1;
- bool res;
RCU_READ_LOCK_GUARD();
mr = address_space_translate(&address_space_memory,
phys_addr, &phys_addr, &l, false,
MEMTXATTRS_UNSPECIFIED);
- res = !(memory_region_is_ram(mr) || memory_region_is_romd(mr));
- return res;
+ return !(memory_region_is_ram(mr) || memory_region_is_romd(mr));
}
int qemu_ram_foreach_block(RAMBlockIterFunc func, void *opaque)
const char *names[] = { " [unassigned]", " [not dirty]",
" [ROM]", " [watch]" };
- qemu_printf(" #%d @" TARGET_FMT_plx ".." TARGET_FMT_plx
+ qemu_printf(" #%d @" HWADDR_FMT_plx ".." HWADDR_FMT_plx
" %s%s%s%s%s",
i,
s->offset_within_address_space,
- s->offset_within_address_space + MR_SIZE(s->mr->size),
+ s->offset_within_address_space + MR_SIZE(s->size),
s->mr->name ? s->mr->name : "(noname)",
i < ARRAY_SIZE(names) ? names[i] : "",
s->mr == root ? " [ROOT]" : "",