/* Initialisation routine */ void *ds1225y_init(target_phys_addr_t mem_base, const char *filename) { ds1225y_t *s; int mem_indexRW, mem_indexRP; QEMUFile *file; s = qemu_mallocz(sizeof(ds1225y_t)); s->chip_size = 0x2000; /* Fixed for ds1225y chip: 8 KiB */ s->contents = qemu_mallocz(s->chip_size); s->protection = 7; /* Read current file */ file = qemu_fopen(filename, "rb"); if (file) { /* Read nvram contents */ qemu_get_buffer(file, s->contents, s->chip_size); qemu_fclose(file); } s->file = qemu_fopen(filename, "wb"); if (s->file) { /* Write back contents, as 'wb' mode cleaned the file */ qemu_put_buffer(s->file, s->contents, s->chip_size); qemu_fflush(s->file); } /* Read/write memory */ mem_indexRW = cpu_register_io_memory(nvram_read, nvram_write, s); cpu_register_physical_memory(mem_base, s->chip_size, mem_indexRW); /* Read/write protected memory */ mem_indexRP = cpu_register_io_memory(nvram_read, nvram_write_protected, s); cpu_register_physical_memory(mem_base + s->chip_size, s->chip_size, mem_indexRP); return s; }
void qemu_put_buffer(QEMUFile *f, const uint8_t *buf, size_t size) { size_t l; if (f->last_error) { return; } while (size > 0) { l = IO_BUF_SIZE - f->buf_index; if (l > size) { l = size; } memcpy(f->buf + f->buf_index, buf, l); f->bytes_xfer += l; add_to_iovec(f, f->buf + f->buf_index, l); f->buf_index += l; if (f->buf_index == IO_BUF_SIZE) { qemu_fflush(f); } if (qemu_file_get_error(f)) { break; } buf += l; size -= l; } }
void qemu_put_buffer(QEMUFile *f, const uint8_t *buf, int size) { int l; #ifdef CONFIG_S2E if (s2e_dev_snapshot_enable) { assert(!f); s2e_qemu_put_buffer(g_s2e_state, buf, size); return; } #endif if (!f->has_error && f->is_write == 0 && f->buf_index > 0) { fprintf(stderr, "Attempted to write to buffer while read buffer is not empty\n"); abort(); } while (!f->has_error && size > 0) { l = IO_BUF_SIZE - f->buf_index; if (l > size) l = size; memcpy(f->buf + f->buf_index, buf, l); f->is_write = 1; f->buf_index += l; buf += l; size -= l; if (f->buf_index >= IO_BUF_SIZE) qemu_fflush(f); } }
int qemu_fclose(QEMUFile *f) { int ret = 0; qemu_fflush(f); if (f->close) ret = f->close(f->opaque); qemu_free(f); return ret; }
const QEMUSizedBuffer *qemu_buf_get(QEMUFile *f) { QEMUBuffer *p; qemu_fflush(f); p = f->opaque; return p->qsb; }
void qemu_put_byte(QEMUFile *f, int v) { if (!f->has_error && f->is_write == 0 && f->buf_index > 0) { fprintf(stderr, "Attempted to write to buffer while read buffer is not empty\n"); abort(); } f->buf[f->buf_index++] = v; f->is_write = 1; if (f->buf_index >= IO_BUF_SIZE) qemu_fflush(f); }
void qemu_put_byte(QEMUFile *f, int v) { if (f->last_error) { return; } f->buf[f->buf_index] = v; f->bytes_xfer++; add_to_iovec(f, f->buf + f->buf_index, 1); f->buf_index++; if (f->buf_index == IO_BUF_SIZE) { qemu_fflush(f); } }
static void nvram_writeb (void *opaque, target_phys_addr_t addr, uint32_t val) { ds1225y_t *s = opaque; #ifdef DEBUG_NVRAM printf("nvram: write 0x%x at " TARGET_FMT_lx "\n", val, addr); #endif s->contents[addr] = val & 0xff; if (s->file) { qemu_fseek(s->file, addr, SEEK_SET); qemu_put_byte(s->file, (int)val); qemu_fflush(s->file); } }
static void add_to_iovec(QEMUFile *f, const uint8_t *buf, size_t size) { /* check for adjacent buffer and coalesce them */ if (f->iovcnt > 0 && buf == f->iov[f->iovcnt - 1].iov_base + f->iov[f->iovcnt - 1].iov_len) { f->iov[f->iovcnt - 1].iov_len += size; } else { f->iov[f->iovcnt].iov_base = (uint8_t *)buf; f->iov[f->iovcnt++].iov_len = size; } if (f->iovcnt >= MAX_IOV_SIZE) { qemu_fflush(f); } }
static void colo_send_message(QEMUFile *f, COLOMessage msg, Error **errp) { int ret; if (msg >= COLO_MESSAGE__MAX) { error_setg(errp, "%s: Invalid message", __func__); return; } qemu_put_be32(f, msg); qemu_fflush(f); ret = qemu_file_get_error(f); if (ret < 0) { error_setg_errno(errp, -ret, "Can't send COLO message"); } trace_colo_send_message(COLOMessage_lookup[msg]); }
int64_t qemu_fseek(QEMUFile *f, int64_t pos, int whence) { if (whence == SEEK_SET) { /* nothing to do */ } else if (whence == SEEK_CUR) { pos += qemu_ftell(f); } else { /* SEEK_END not supported */ return -1; } if (f->put_buffer) { qemu_fflush(f); f->buf_offset = pos; } else { f->buf_offset = pos; f->buf_index = 0; f->buf_size = 0; } return pos; }
static void colo_send_message_value(QEMUFile *f, COLOMessage msg, uint64_t value, Error **errp) { Error *local_err = NULL; int ret; colo_send_message(f, msg, &local_err); if (local_err) { error_propagate(errp, local_err); return; } qemu_put_be64(f, value); qemu_fflush(f); ret = qemu_file_get_error(f); if (ret < 0) { error_setg_errno(errp, -ret, "Failed to send value for message:%s", COLOMessage_lookup[msg]); } }
void qemu_put_byte(QEMUFile *f, int v) { #ifdef CONFIG_S2E if (s2e_dev_snapshot_enable) { assert(!f); s2e_qemu_put_byte(g_s2e_state, v); return; } #endif if (!f->has_error && f->is_write == 0 && f->buf_index > 0) { fprintf(stderr, "Attempted to write to buffer while read buffer is not empty\n"); abort(); } f->buf[f->buf_index++] = v; f->is_write = 1; if (f->buf_index >= IO_BUF_SIZE) qemu_fflush(f); }
/** Closes the file * * Returns negative error value if any error happened on previous operations or * while closing the file. Returns 0 or positive number on success. * * The meaning of return value on success depends on the specific backend * being used. */ int qemu_fclose(QEMUFile *f) { int ret; qemu_fflush(f); ret = qemu_file_get_error(f); if (f->ops->close) { int ret2 = f->ops->close(f->opaque); if (ret >= 0) { ret = ret2; } } /* If any error was spotted before closing, we should report it * instead of the close() return value. */ if (f->last_error) { ret = f->last_error; } g_free(f); trace_qemu_file_fclose(); return ret; }
void qemu_put_buffer(QEMUFile *f, const uint8_t *buf, int size) { int l; if (!f->has_error && f->is_write == 0 && f->buf_index > 0) { fprintf(stderr, "Attempted to write to buffer while read buffer is not empty\n"); abort(); } while (!f->has_error && size > 0) { l = IO_BUF_SIZE - f->buf_index; if (l > size) l = size; memcpy(f->buf + f->buf_index, buf, l); f->is_write = 1; f->buf_index += l; buf += l; size -= l; if (f->buf_index >= IO_BUF_SIZE) qemu_fflush(f); } }
static int colo_do_checkpoint_transaction(MigrationState *s, QIOChannelBuffer *bioc, QEMUFile *fb) { Error *local_err = NULL; int ret = -1; colo_send_message(s->to_dst_file, COLO_MESSAGE_CHECKPOINT_REQUEST, &local_err); if (local_err) { goto out; } colo_receive_check_message(s->rp_state.from_dst_file, COLO_MESSAGE_CHECKPOINT_REPLY, &local_err); if (local_err) { goto out; } /* Reset channel-buffer directly */ qio_channel_io_seek(QIO_CHANNEL(bioc), 0, 0, NULL); bioc->usage = 0; qemu_mutex_lock_iothread(); if (failover_get_state() != FAILOVER_STATUS_NONE) { qemu_mutex_unlock_iothread(); goto out; } vm_stop_force_state(RUN_STATE_COLO); qemu_mutex_unlock_iothread(); trace_colo_vm_state_change("run", "stop"); /* * Failover request bh could be called after vm_stop_force_state(), * So we need check failover_request_is_active() again. */ if (failover_get_state() != FAILOVER_STATUS_NONE) { goto out; } colo_notify_compares_event(NULL, COLO_EVENT_CHECKPOINT, &local_err); if (local_err) { goto out; } /* Disable block migration */ migrate_set_block_enabled(false, &local_err); qemu_mutex_lock_iothread(); #ifdef CONFIG_REPLICATION replication_do_checkpoint_all(&local_err); if (local_err) { qemu_mutex_unlock_iothread(); goto out; } #else abort(); #endif colo_send_message(s->to_dst_file, COLO_MESSAGE_VMSTATE_SEND, &local_err); if (local_err) { qemu_mutex_unlock_iothread(); goto out; } /* Note: device state is saved into buffer */ ret = qemu_save_device_state(fb); qemu_mutex_unlock_iothread(); if (ret < 0) { goto out; } /* * Only save VM's live state, which not including device state. * TODO: We may need a timeout mechanism to prevent COLO process * to be blocked here. */ qemu_savevm_live_state(s->to_dst_file); qemu_fflush(fb); /* * We need the size of the VMstate data in Secondary side, * With which we can decide how much data should be read. */ colo_send_message_value(s->to_dst_file, COLO_MESSAGE_VMSTATE_SIZE, bioc->usage, &local_err); if (local_err) { goto out; } qemu_put_buffer(s->to_dst_file, bioc->data, bioc->usage); qemu_fflush(s->to_dst_file); ret = qemu_file_get_error(s->to_dst_file); if (ret < 0) { goto out; } colo_receive_check_message(s->rp_state.from_dst_file, COLO_MESSAGE_VMSTATE_RECEIVED, &local_err); if (local_err) { goto out; } colo_receive_check_message(s->rp_state.from_dst_file, COLO_MESSAGE_VMSTATE_LOADED, &local_err); if (local_err) { goto out; } ret = 0; qemu_mutex_lock_iothread(); vm_start(); qemu_mutex_unlock_iothread(); trace_colo_vm_state_change("stop", "run"); out: if (local_err) { error_report_err(local_err); } return ret; }
static int colo_do_checkpoint_transaction(MigrationState *s, QIOChannelBuffer *bioc, QEMUFile *fb) { Error *local_err = NULL; int ret = -1; colo_send_message(s->to_dst_file, COLO_MESSAGE_CHECKPOINT_REQUEST, &local_err); if (local_err) { goto out; } colo_receive_check_message(s->rp_state.from_dst_file, COLO_MESSAGE_CHECKPOINT_REPLY, &local_err); if (local_err) { goto out; } /* Reset channel-buffer directly */ qio_channel_io_seek(QIO_CHANNEL(bioc), 0, 0, NULL); bioc->usage = 0; qemu_mutex_lock_iothread(); if (failover_get_state() != FAILOVER_STATUS_NONE) { qemu_mutex_unlock_iothread(); goto out; } vm_stop_force_state(RUN_STATE_COLO); qemu_mutex_unlock_iothread(); trace_colo_vm_state_change("run", "stop"); /* * Failover request bh could be called after vm_stop_force_state(), * So we need check failover_request_is_active() again. */ if (failover_get_state() != FAILOVER_STATUS_NONE) { goto out; } /* Disable block migration */ s->params.blk = 0; s->params.shared = 0; qemu_savevm_state_header(fb); qemu_savevm_state_begin(fb, &s->params); qemu_mutex_lock_iothread(); qemu_savevm_state_complete_precopy(fb, false); qemu_mutex_unlock_iothread(); qemu_fflush(fb); colo_send_message(s->to_dst_file, COLO_MESSAGE_VMSTATE_SEND, &local_err); if (local_err) { goto out; } /* * We need the size of the VMstate data in Secondary side, * With which we can decide how much data should be read. */ colo_send_message_value(s->to_dst_file, COLO_MESSAGE_VMSTATE_SIZE, bioc->usage, &local_err); if (local_err) { goto out; } qemu_put_buffer(s->to_dst_file, bioc->data, bioc->usage); qemu_fflush(s->to_dst_file); ret = qemu_file_get_error(s->to_dst_file); if (ret < 0) { goto out; } colo_receive_check_message(s->rp_state.from_dst_file, COLO_MESSAGE_VMSTATE_RECEIVED, &local_err); if (local_err) { goto out; } colo_receive_check_message(s->rp_state.from_dst_file, COLO_MESSAGE_VMSTATE_LOADED, &local_err); if (local_err) { goto out; } ret = 0; qemu_mutex_lock_iothread(); vm_start(); qemu_mutex_unlock_iothread(); trace_colo_vm_state_change("stop", "run"); out: if (local_err) { error_report_err(local_err); } return ret; }
int64_t qemu_ftell(QEMUFile *f) { qemu_fflush(f); return f->pos; }