mirror of
https://github.com/izzy2lost/xemu.git
synced 2026-07-06 00:20:22 -07:00
Merge remote-tracking branch 'remotes/bonzini-gitlab/tags/for-upstream' into staging
* avoid deprecation warnings for SASL on macOS 10.11 or newer * fix -readconfig when config blocks have an id (like [chardev "qmp"]) * Error* initialization fixes * Improvements to ESP emulation (Mark) * Allow creating noreserve memory backends (David) * Improvements to query-memdev (David) * Bump compiler to C11 (Richard) * First round of SVM fixes from GSoC project (Lara) # gpg: Signature made Wed 16 Jun 2021 16:37:49 BST # gpg: using RSA key F13338574B662389866C7682BFFBD25F78C7AE83 # gpg: issuer "pbonzini@redhat.com" # gpg: Good signature from "Paolo Bonzini <bonzini@gnu.org>" [full] # gpg: aka "Paolo Bonzini <pbonzini@redhat.com>" [full] # Primary key fingerprint: 46F5 9FBD 57D6 12E7 BFD4 E2F7 7E15 100C CD36 69B1 # Subkey fingerprint: F133 3857 4B66 2389 866C 7682 BFFB D25F 78C7 AE83 * remotes/bonzini-gitlab/tags/for-upstream: (45 commits) configure: Remove probe for _Static_assert qemu/compiler: Remove QEMU_GENERIC include/qemu/lockable: Use _Generic instead of QEMU_GENERIC util: Use unique type for QemuRecMutex in thread-posix.h util: Pass file+line to qemu_rec_mutex_unlock_impl util: Use real functions for thread-posix QemuRecMutex softfloat: Use _Generic instead of QEMU_GENERIC configure: Use -std=gnu11 target/i386: Added Intercept CR0 writes check target/i386: Added consistency checks for CR0 target/i386: Added consistency checks for VMRUN intercept and ASID target/i386: Refactored intercept checks into cpu_svm_has_intercept configure: map x32 to cpu_family x86_64 for meson hmp: Print "reserve" property of memory backends with "info memdev" qmp: Include "reserve" property of memory backends hmp: Print "share" property of memory backends with "info memdev" qmp: Include "share" property of memory backends qmp: Clarify memory backend properties returned via query-memdev hostmem: Wire up RAM_NORESERVE via "reserve" property util/mmap-alloc: Support RAM_NORESERVE via MAP_NORESERVE under Linux ... Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
@@ -39,6 +39,7 @@ file_backend_memory_alloc(HostMemoryBackend *backend, Error **errp)
|
||||
object_get_typename(OBJECT(backend)));
|
||||
#else
|
||||
HostMemoryBackendFile *fb = MEMORY_BACKEND_FILE(backend);
|
||||
uint32_t ram_flags;
|
||||
gchar *name;
|
||||
|
||||
if (!backend->size) {
|
||||
@@ -51,11 +52,11 @@ file_backend_memory_alloc(HostMemoryBackend *backend, Error **errp)
|
||||
}
|
||||
|
||||
name = host_memory_backend_get_name(backend);
|
||||
memory_region_init_ram_from_file(&backend->mr, OBJECT(backend),
|
||||
name,
|
||||
backend->size, fb->align,
|
||||
(backend->share ? RAM_SHARED : 0) |
|
||||
(fb->is_pmem ? RAM_PMEM : 0),
|
||||
ram_flags = backend->share ? RAM_SHARED : 0;
|
||||
ram_flags |= backend->reserve ? 0 : RAM_NORESERVE;
|
||||
ram_flags |= fb->is_pmem ? RAM_PMEM : 0;
|
||||
memory_region_init_ram_from_file(&backend->mr, OBJECT(backend), name,
|
||||
backend->size, fb->align, ram_flags,
|
||||
fb->mem_path, fb->readonly, errp);
|
||||
g_free(name);
|
||||
#endif
|
||||
|
||||
@@ -35,6 +35,7 @@ static void
|
||||
memfd_backend_memory_alloc(HostMemoryBackend *backend, Error **errp)
|
||||
{
|
||||
HostMemoryBackendMemfd *m = MEMORY_BACKEND_MEMFD(backend);
|
||||
uint32_t ram_flags;
|
||||
char *name;
|
||||
int fd;
|
||||
|
||||
@@ -52,9 +53,10 @@ memfd_backend_memory_alloc(HostMemoryBackend *backend, Error **errp)
|
||||
}
|
||||
|
||||
name = host_memory_backend_get_name(backend);
|
||||
memory_region_init_ram_from_fd(&backend->mr, OBJECT(backend),
|
||||
name, backend->size,
|
||||
backend->share, fd, 0, errp);
|
||||
ram_flags = backend->share ? RAM_SHARED : 0;
|
||||
ram_flags |= backend->reserve ? 0 : RAM_NORESERVE;
|
||||
memory_region_init_ram_from_fd(&backend->mr, OBJECT(backend), name,
|
||||
backend->size, ram_flags, fd, 0, errp);
|
||||
g_free(name);
|
||||
}
|
||||
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
static void
|
||||
ram_backend_memory_alloc(HostMemoryBackend *backend, Error **errp)
|
||||
{
|
||||
uint32_t ram_flags;
|
||||
char *name;
|
||||
|
||||
if (!backend->size) {
|
||||
@@ -27,8 +28,10 @@ ram_backend_memory_alloc(HostMemoryBackend *backend, Error **errp)
|
||||
}
|
||||
|
||||
name = host_memory_backend_get_name(backend);
|
||||
memory_region_init_ram_shared_nomigrate(&backend->mr, OBJECT(backend), name,
|
||||
backend->size, backend->share, errp);
|
||||
ram_flags = backend->share ? RAM_SHARED : 0;
|
||||
ram_flags |= backend->reserve ? 0 : RAM_NORESERVE;
|
||||
memory_region_init_ram_flags_nomigrate(&backend->mr, OBJECT(backend), name,
|
||||
backend->size, ram_flags, errp);
|
||||
g_free(name);
|
||||
}
|
||||
|
||||
|
||||
@@ -216,6 +216,11 @@ static void host_memory_backend_set_prealloc(Object *obj, bool value,
|
||||
Error *local_err = NULL;
|
||||
HostMemoryBackend *backend = MEMORY_BACKEND(obj);
|
||||
|
||||
if (!backend->reserve && value) {
|
||||
error_setg(errp, "'prealloc=on' and 'reserve=off' are incompatible");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!host_memory_backend_mr_inited(backend)) {
|
||||
backend->prealloc = value;
|
||||
return;
|
||||
@@ -267,6 +272,7 @@ static void host_memory_backend_init(Object *obj)
|
||||
/* TODO: convert access to globals to compat properties */
|
||||
backend->merge = machine_mem_merge(machine);
|
||||
backend->dump = machine_dump_guest_core(machine);
|
||||
backend->reserve = true;
|
||||
backend->prealloc_threads = 1;
|
||||
}
|
||||
|
||||
@@ -425,6 +431,30 @@ static void host_memory_backend_set_share(Object *o, bool value, Error **errp)
|
||||
backend->share = value;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_LINUX
|
||||
static bool host_memory_backend_get_reserve(Object *o, Error **errp)
|
||||
{
|
||||
HostMemoryBackend *backend = MEMORY_BACKEND(o);
|
||||
|
||||
return backend->reserve;
|
||||
}
|
||||
|
||||
static void host_memory_backend_set_reserve(Object *o, bool value, Error **errp)
|
||||
{
|
||||
HostMemoryBackend *backend = MEMORY_BACKEND(o);
|
||||
|
||||
if (host_memory_backend_mr_inited(backend)) {
|
||||
error_setg(errp, "cannot change property value");
|
||||
return;
|
||||
}
|
||||
if (backend->prealloc && !value) {
|
||||
error_setg(errp, "'prealloc=on' and 'reserve=off' are incompatible");
|
||||
return;
|
||||
}
|
||||
backend->reserve = value;
|
||||
}
|
||||
#endif /* CONFIG_LINUX */
|
||||
|
||||
static bool
|
||||
host_memory_backend_get_use_canonical_path(Object *obj, Error **errp)
|
||||
{
|
||||
@@ -493,6 +523,12 @@ host_memory_backend_class_init(ObjectClass *oc, void *data)
|
||||
host_memory_backend_get_share, host_memory_backend_set_share);
|
||||
object_class_property_set_description(oc, "share",
|
||||
"Mark the memory as private to QEMU or shared");
|
||||
#ifdef CONFIG_LINUX
|
||||
object_class_property_add_bool(oc, "reserve",
|
||||
host_memory_backend_get_reserve, host_memory_backend_set_reserve);
|
||||
object_class_property_set_description(oc, "reserve",
|
||||
"Reserve swap space (or huge pages) if applicable");
|
||||
#endif /* CONFIG_LINUX */
|
||||
/*
|
||||
* Do not delete/rename option. This option must be considered stable
|
||||
* (as if it didn't have the 'x-' prefix including deprecation period) as
|
||||
|
||||
@@ -6366,7 +6366,7 @@ if test "$skip_meson" = no; then
|
||||
i386)
|
||||
echo "cpu_family = 'x86'" >> $cross
|
||||
;;
|
||||
x86_64)
|
||||
x86_64|x32)
|
||||
echo "cpu_family = 'x86_64'" >> $cross
|
||||
;;
|
||||
ppc64le)
|
||||
|
||||
@@ -110,6 +110,12 @@ void hmp_info_memdev(Monitor *mon, const QDict *qdict)
|
||||
m->value->dump ? "true" : "false");
|
||||
monitor_printf(mon, " prealloc: %s\n",
|
||||
m->value->prealloc ? "true" : "false");
|
||||
monitor_printf(mon, " share: %s\n",
|
||||
m->value->share ? "true" : "false");
|
||||
if (m->value->has_reserve) {
|
||||
monitor_printf(mon, " reserve: %s\n",
|
||||
m->value->reserve ? "true" : "false");
|
||||
}
|
||||
monitor_printf(mon, " policy: %s\n",
|
||||
HostMemPolicy_str(m->value->policy));
|
||||
visit_complete(v, &str);
|
||||
|
||||
@@ -157,6 +157,7 @@ void qmp_set_numa_node(NumaOptions *cmd, Error **errp)
|
||||
|
||||
static int query_memdev(Object *obj, void *opaque)
|
||||
{
|
||||
Error *err = NULL;
|
||||
MemdevList **list = opaque;
|
||||
Memdev *m;
|
||||
QObject *host_nodes;
|
||||
@@ -172,6 +173,13 @@ static int query_memdev(Object *obj, void *opaque)
|
||||
m->merge = object_property_get_bool(obj, "merge", &error_abort);
|
||||
m->dump = object_property_get_bool(obj, "dump", &error_abort);
|
||||
m->prealloc = object_property_get_bool(obj, "prealloc", &error_abort);
|
||||
m->share = object_property_get_bool(obj, "share", &error_abort);
|
||||
m->reserve = object_property_get_bool(obj, "reserve", &err);
|
||||
if (err) {
|
||||
error_free_or_abort(&err);
|
||||
} else {
|
||||
m->has_reserve = true;
|
||||
}
|
||||
m->policy = object_property_get_enum(obj, "policy", "HostMemPolicy",
|
||||
&error_abort);
|
||||
host_nodes = object_property_get_qobject(obj,
|
||||
|
||||
+2
-2
@@ -984,8 +984,8 @@ static void next_cube_init(MachineState *machine)
|
||||
sysbus_mmio_map(SYS_BUS_DEVICE(pcdev), 1, 0x02100000);
|
||||
|
||||
/* BMAP memory */
|
||||
memory_region_init_ram_shared_nomigrate(bmapm1, NULL, "next.bmapmem", 64,
|
||||
true, &error_fatal);
|
||||
memory_region_init_ram_flags_nomigrate(bmapm1, NULL, "next.bmapmem", 64,
|
||||
RAM_SHARED, &error_fatal);
|
||||
memory_region_add_subregion(sysmem, 0x020c0000, bmapm1);
|
||||
/* The Rev_2.5_v66.bin firmware accesses it at 0x820c0020, too */
|
||||
memory_region_init_alias(bmapm2, NULL, "next.bmapmem2", bmapm1, 0x0, 64);
|
||||
|
||||
+2
-3
@@ -493,9 +493,8 @@ static void process_msg_shmem(IVShmemState *s, int fd, Error **errp)
|
||||
size = buf.st_size;
|
||||
|
||||
/* mmap the region and map into the BAR2 */
|
||||
memory_region_init_ram_from_fd(&s->server_bar2, OBJECT(s),
|
||||
"ivshmem.bar2", size, true, fd, 0,
|
||||
&local_err);
|
||||
memory_region_init_ram_from_fd(&s->server_bar2, OBJECT(s), "ivshmem.bar2",
|
||||
size, RAM_SHARED, fd, 0, &local_err);
|
||||
if (local_err) {
|
||||
error_propagate(errp, local_err);
|
||||
return;
|
||||
|
||||
+125
-74
@@ -213,7 +213,7 @@ static int esp_select(ESPState *s)
|
||||
if (!s->current_dev) {
|
||||
/* No such drive */
|
||||
s->rregs[ESP_RSTAT] = 0;
|
||||
s->rregs[ESP_RINTR] |= INTR_DC;
|
||||
s->rregs[ESP_RINTR] = INTR_DC;
|
||||
s->rregs[ESP_RSEQ] = SEQ_0;
|
||||
esp_raise_irq(s);
|
||||
return -1;
|
||||
@@ -221,7 +221,7 @@ static int esp_select(ESPState *s)
|
||||
|
||||
/*
|
||||
* Note that we deliberately don't raise the IRQ here: this will be done
|
||||
* either in do_busid_cmd() for DATA OUT transfers or by the deferred
|
||||
* either in do_command_phase() for DATA OUT transfers or by the deferred
|
||||
* IRQ mechanism in esp_transfer_data() for DATA IN transfers
|
||||
*/
|
||||
s->rregs[ESP_RINTR] |= INTR_FC;
|
||||
@@ -260,9 +260,6 @@ static uint32_t get_cmd(ESPState *s, uint32_t maxlen)
|
||||
return 0;
|
||||
}
|
||||
n = esp_fifo_pop_buf(&s->fifo, buf, dmalen);
|
||||
if (n >= 3) {
|
||||
buf[0] = buf[2] >> 5;
|
||||
}
|
||||
n = MIN(fifo8_num_free(&s->cmdfifo), n);
|
||||
fifo8_push_all(&s->cmdfifo, buf, n);
|
||||
}
|
||||
@@ -275,24 +272,22 @@ static uint32_t get_cmd(ESPState *s, uint32_t maxlen)
|
||||
return dmalen;
|
||||
}
|
||||
|
||||
static void do_busid_cmd(ESPState *s, uint8_t busid)
|
||||
static void do_command_phase(ESPState *s)
|
||||
{
|
||||
uint32_t cmdlen;
|
||||
int32_t datalen;
|
||||
int lun;
|
||||
SCSIDevice *current_lun;
|
||||
uint8_t buf[ESP_CMDFIFO_SZ];
|
||||
|
||||
trace_esp_do_busid_cmd(busid);
|
||||
lun = busid & 7;
|
||||
trace_esp_do_command_phase(s->lun);
|
||||
cmdlen = fifo8_num_used(&s->cmdfifo);
|
||||
if (!cmdlen || !s->current_dev) {
|
||||
return;
|
||||
}
|
||||
esp_fifo_pop_buf(&s->cmdfifo, buf, cmdlen);
|
||||
|
||||
current_lun = scsi_device_find(&s->bus, 0, s->current_dev->id, lun);
|
||||
s->current_req = scsi_req_new(current_lun, 0, lun, buf, s);
|
||||
current_lun = scsi_device_find(&s->bus, 0, s->current_dev->id, s->lun);
|
||||
s->current_req = scsi_req_new(current_lun, 0, s->lun, buf, s);
|
||||
datalen = scsi_req_enqueue(s->current_req);
|
||||
s->ti_size = datalen;
|
||||
fifo8_reset(&s->cmdfifo);
|
||||
@@ -319,28 +314,36 @@ static void do_busid_cmd(ESPState *s, uint8_t busid)
|
||||
}
|
||||
}
|
||||
|
||||
static void do_cmd(ESPState *s)
|
||||
static void do_message_phase(ESPState *s)
|
||||
{
|
||||
uint8_t busid = esp_fifo_pop(&s->cmdfifo);
|
||||
int len;
|
||||
if (s->cmdfifo_cdb_offset) {
|
||||
uint8_t message = esp_fifo_pop(&s->cmdfifo);
|
||||
|
||||
s->cmdfifo_cdb_offset--;
|
||||
trace_esp_do_identify(message);
|
||||
s->lun = message & 7;
|
||||
s->cmdfifo_cdb_offset--;
|
||||
}
|
||||
|
||||
/* Ignore extended messages for now */
|
||||
if (s->cmdfifo_cdb_offset) {
|
||||
len = MIN(s->cmdfifo_cdb_offset, fifo8_num_used(&s->cmdfifo));
|
||||
int len = MIN(s->cmdfifo_cdb_offset, fifo8_num_used(&s->cmdfifo));
|
||||
esp_fifo_pop_buf(&s->cmdfifo, NULL, len);
|
||||
s->cmdfifo_cdb_offset = 0;
|
||||
}
|
||||
}
|
||||
|
||||
do_busid_cmd(s, busid);
|
||||
static void do_cmd(ESPState *s)
|
||||
{
|
||||
do_message_phase(s);
|
||||
assert(s->cmdfifo_cdb_offset == 0);
|
||||
do_command_phase(s);
|
||||
}
|
||||
|
||||
static void satn_pdma_cb(ESPState *s)
|
||||
{
|
||||
s->do_cmd = 0;
|
||||
if (!fifo8_is_empty(&s->cmdfifo)) {
|
||||
if (!esp_get_tc(s) && !fifo8_is_empty(&s->cmdfifo)) {
|
||||
s->cmdfifo_cdb_offset = 1;
|
||||
s->do_cmd = 0;
|
||||
do_cmd(s);
|
||||
}
|
||||
}
|
||||
@@ -369,13 +372,10 @@ static void handle_satn(ESPState *s)
|
||||
|
||||
static void s_without_satn_pdma_cb(ESPState *s)
|
||||
{
|
||||
uint32_t len;
|
||||
|
||||
s->do_cmd = 0;
|
||||
len = fifo8_num_used(&s->cmdfifo);
|
||||
if (len) {
|
||||
if (!esp_get_tc(s) && !fifo8_is_empty(&s->cmdfifo)) {
|
||||
s->cmdfifo_cdb_offset = 0;
|
||||
do_busid_cmd(s, 0);
|
||||
s->do_cmd = 0;
|
||||
do_cmd(s);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -392,7 +392,7 @@ static void handle_s_without_atn(ESPState *s)
|
||||
if (cmdlen > 0) {
|
||||
s->cmdfifo_cdb_offset = 0;
|
||||
s->do_cmd = 0;
|
||||
do_busid_cmd(s, 0);
|
||||
do_cmd(s);
|
||||
} else if (cmdlen == 0) {
|
||||
s->do_cmd = 1;
|
||||
/* Target present, but no cmd yet - switch to command phase */
|
||||
@@ -403,8 +403,7 @@ static void handle_s_without_atn(ESPState *s)
|
||||
|
||||
static void satn_stop_pdma_cb(ESPState *s)
|
||||
{
|
||||
s->do_cmd = 0;
|
||||
if (!fifo8_is_empty(&s->cmdfifo)) {
|
||||
if (!esp_get_tc(s) && !fifo8_is_empty(&s->cmdfifo)) {
|
||||
trace_esp_handle_satn_stop(fifo8_num_used(&s->cmdfifo));
|
||||
s->do_cmd = 1;
|
||||
s->cmdfifo_cdb_offset = 1;
|
||||
@@ -481,7 +480,6 @@ static void esp_dma_done(ESPState *s)
|
||||
{
|
||||
s->rregs[ESP_RSTAT] |= STAT_TC;
|
||||
s->rregs[ESP_RINTR] |= INTR_BS;
|
||||
s->rregs[ESP_RSEQ] = 0;
|
||||
s->rregs[ESP_RFLAGS] = 0;
|
||||
esp_set_tc(s, 0);
|
||||
esp_raise_irq(s);
|
||||
@@ -494,10 +492,32 @@ static void do_dma_pdma_cb(ESPState *s)
|
||||
uint32_t n;
|
||||
|
||||
if (s->do_cmd) {
|
||||
/* Ensure we have received complete command after SATN and stop */
|
||||
if (esp_get_tc(s) || fifo8_is_empty(&s->cmdfifo)) {
|
||||
return;
|
||||
}
|
||||
|
||||
s->ti_size = 0;
|
||||
s->do_cmd = 0;
|
||||
do_cmd(s);
|
||||
esp_lower_drq(s);
|
||||
if ((s->rregs[ESP_RSTAT] & 7) == STAT_CD) {
|
||||
/* No command received */
|
||||
if (s->cmdfifo_cdb_offset == fifo8_num_used(&s->cmdfifo)) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* Command has been received */
|
||||
s->do_cmd = 0;
|
||||
do_cmd(s);
|
||||
} else {
|
||||
/*
|
||||
* Extra message out bytes received: update cmdfifo_cdb_offset
|
||||
* and then switch to commmand phase
|
||||
*/
|
||||
s->cmdfifo_cdb_offset = fifo8_num_used(&s->cmdfifo);
|
||||
s->rregs[ESP_RSTAT] = STAT_TC | STAT_CD;
|
||||
s->rregs[ESP_RSEQ] = SEQ_CD;
|
||||
s->rregs[ESP_RINTR] |= INTR_BS;
|
||||
esp_raise_irq(s);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -740,20 +760,17 @@ static void esp_do_nodma(ESPState *s)
|
||||
s->async_len -= len;
|
||||
s->ti_size += len;
|
||||
} else {
|
||||
len = MIN(s->ti_size, s->async_len);
|
||||
len = MIN(len, fifo8_num_free(&s->fifo));
|
||||
fifo8_push_all(&s->fifo, s->async_buf, len);
|
||||
s->async_buf += len;
|
||||
s->async_len -= len;
|
||||
s->ti_size -= len;
|
||||
if (fifo8_is_empty(&s->fifo)) {
|
||||
fifo8_push(&s->fifo, s->async_buf[0]);
|
||||
s->async_buf++;
|
||||
s->async_len--;
|
||||
s->ti_size--;
|
||||
}
|
||||
}
|
||||
|
||||
if (s->async_len == 0) {
|
||||
scsi_req_continue(s->current_req);
|
||||
|
||||
if (to_device || s->ti_size == 0) {
|
||||
return;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
s->rregs[ESP_RINTR] |= INTR_BS;
|
||||
@@ -763,20 +780,37 @@ static void esp_do_nodma(ESPState *s)
|
||||
void esp_command_complete(SCSIRequest *req, size_t resid)
|
||||
{
|
||||
ESPState *s = req->hba_private;
|
||||
int to_device = ((s->rregs[ESP_RSTAT] & 7) == STAT_DO);
|
||||
|
||||
trace_esp_command_complete();
|
||||
if (s->ti_size != 0) {
|
||||
trace_esp_command_complete_unexpected();
|
||||
|
||||
/*
|
||||
* Non-DMA transfers from the target will leave the last byte in
|
||||
* the FIFO so don't reset ti_size in this case
|
||||
*/
|
||||
if (s->dma || to_device) {
|
||||
if (s->ti_size != 0) {
|
||||
trace_esp_command_complete_unexpected();
|
||||
}
|
||||
s->ti_size = 0;
|
||||
}
|
||||
s->ti_size = 0;
|
||||
|
||||
s->async_len = 0;
|
||||
if (req->status) {
|
||||
trace_esp_command_complete_fail();
|
||||
}
|
||||
s->status = req->status;
|
||||
s->rregs[ESP_RSTAT] = STAT_ST;
|
||||
esp_dma_done(s);
|
||||
esp_lower_drq(s);
|
||||
|
||||
/*
|
||||
* If the transfer is finished, switch to status phase. For non-DMA
|
||||
* transfers from the target the last byte is still in the FIFO
|
||||
*/
|
||||
if (s->ti_size == 0) {
|
||||
s->rregs[ESP_RSTAT] = STAT_TC | STAT_ST;
|
||||
esp_dma_done(s);
|
||||
esp_lower_drq(s);
|
||||
}
|
||||
|
||||
if (s->current_req) {
|
||||
scsi_req_unref(s->current_req);
|
||||
s->current_req = NULL;
|
||||
@@ -804,16 +838,6 @@ void esp_transfer_data(SCSIRequest *req, uint32_t len)
|
||||
s->rregs[ESP_RSTAT] |= STAT_TC;
|
||||
s->rregs[ESP_RINTR] |= INTR_BS;
|
||||
esp_raise_irq(s);
|
||||
|
||||
/*
|
||||
* If data is ready to transfer and the TI command has already
|
||||
* been executed, start DMA immediately. Otherwise DMA will start
|
||||
* when host sends the TI command
|
||||
*/
|
||||
if (s->ti_size && (s->rregs[ESP_CMD] == (CMD_TI | CMD_DMA))) {
|
||||
esp_do_dma(s);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (s->ti_cmd == 0) {
|
||||
@@ -827,7 +851,7 @@ void esp_transfer_data(SCSIRequest *req, uint32_t len)
|
||||
return;
|
||||
}
|
||||
|
||||
if (s->ti_cmd & CMD_DMA) {
|
||||
if (s->ti_cmd == (CMD_TI | CMD_DMA)) {
|
||||
if (dmalen) {
|
||||
esp_do_dma(s);
|
||||
} else if (s->ti_size <= 0) {
|
||||
@@ -838,7 +862,7 @@ void esp_transfer_data(SCSIRequest *req, uint32_t len)
|
||||
esp_dma_done(s);
|
||||
esp_lower_drq(s);
|
||||
}
|
||||
} else {
|
||||
} else if (s->ti_cmd == CMD_TI) {
|
||||
esp_do_nodma(s);
|
||||
}
|
||||
}
|
||||
@@ -905,6 +929,17 @@ uint64_t esp_reg_read(ESPState *s, uint32_t saddr)
|
||||
qemu_log_mask(LOG_UNIMP, "esp: PIO data read not implemented\n");
|
||||
s->rregs[ESP_FIFO] = 0;
|
||||
} else {
|
||||
if ((s->rregs[ESP_RSTAT] & 0x7) == STAT_DI) {
|
||||
if (s->ti_size) {
|
||||
esp_do_nodma(s);
|
||||
} else {
|
||||
/*
|
||||
* The last byte of a non-DMA transfer has been read out
|
||||
* of the FIFO so switch to status phase
|
||||
*/
|
||||
s->rregs[ESP_RSTAT] = STAT_TC | STAT_ST;
|
||||
}
|
||||
}
|
||||
s->rregs[ESP_FIFO] = esp_fifo_pop(&s->fifo);
|
||||
}
|
||||
val = s->rregs[ESP_FIFO];
|
||||
@@ -917,7 +952,15 @@ uint64_t esp_reg_read(ESPState *s, uint32_t saddr)
|
||||
val = s->rregs[ESP_RINTR];
|
||||
s->rregs[ESP_RINTR] = 0;
|
||||
s->rregs[ESP_RSTAT] &= ~STAT_TC;
|
||||
s->rregs[ESP_RSEQ] = SEQ_0;
|
||||
/*
|
||||
* According to the datasheet ESP_RSEQ should be cleared, but as the
|
||||
* emulation currently defers information transfers to the next TI
|
||||
* command leave it for now so that pedantic guests such as the old
|
||||
* Linux 2.6 driver see the correct flags before the next SCSI phase
|
||||
* transition.
|
||||
*
|
||||
* s->rregs[ESP_RSEQ] = SEQ_0;
|
||||
*/
|
||||
esp_lower_irq(s);
|
||||
break;
|
||||
case ESP_TCHI:
|
||||
@@ -955,15 +998,18 @@ void esp_reg_write(ESPState *s, uint32_t saddr, uint64_t val)
|
||||
case ESP_FIFO:
|
||||
if (s->do_cmd) {
|
||||
esp_fifo_push(&s->cmdfifo, val);
|
||||
|
||||
/*
|
||||
* If any unexpected message out/command phase data is
|
||||
* transferred using non-DMA, raise the interrupt
|
||||
*/
|
||||
if (s->rregs[ESP_CMD] == CMD_TI) {
|
||||
s->rregs[ESP_RINTR] |= INTR_BS;
|
||||
esp_raise_irq(s);
|
||||
}
|
||||
} else {
|
||||
esp_fifo_push(&s->fifo, val);
|
||||
}
|
||||
|
||||
/* Non-DMA transfers raise an interrupt after every byte */
|
||||
if (s->rregs[ESP_CMD] == CMD_TI) {
|
||||
s->rregs[ESP_RINTR] |= INTR_FC | INTR_BS;
|
||||
esp_raise_irq(s);
|
||||
}
|
||||
break;
|
||||
case ESP_CMD:
|
||||
s->rregs[saddr] = val;
|
||||
@@ -1088,7 +1134,15 @@ static bool esp_is_version_5(void *opaque, int version_id)
|
||||
ESPState *s = ESP(opaque);
|
||||
|
||||
version_id = MIN(version_id, s->mig_version_id);
|
||||
return version_id == 5;
|
||||
return version_id >= 5;
|
||||
}
|
||||
|
||||
static bool esp_is_version_6(void *opaque, int version_id)
|
||||
{
|
||||
ESPState *s = ESP(opaque);
|
||||
|
||||
version_id = MIN(version_id, s->mig_version_id);
|
||||
return version_id >= 6;
|
||||
}
|
||||
|
||||
int esp_pre_save(void *opaque)
|
||||
@@ -1128,7 +1182,7 @@ static int esp_post_load(void *opaque, int version_id)
|
||||
|
||||
const VMStateDescription vmstate_esp = {
|
||||
.name = "esp",
|
||||
.version_id = 5,
|
||||
.version_id = 6,
|
||||
.minimum_version_id = 3,
|
||||
.post_load = esp_post_load,
|
||||
.fields = (VMStateField[]) {
|
||||
@@ -1157,6 +1211,7 @@ const VMStateDescription vmstate_esp = {
|
||||
VMSTATE_FIFO8_TEST(fifo, ESPState, esp_is_version_5),
|
||||
VMSTATE_FIFO8_TEST(cmdfifo, ESPState, esp_is_version_5),
|
||||
VMSTATE_UINT8_TEST(ti_cmd, ESPState, esp_is_version_5),
|
||||
VMSTATE_UINT8_TEST(lun, ESPState, esp_is_version_6),
|
||||
VMSTATE_END_OF_LIST()
|
||||
},
|
||||
};
|
||||
@@ -1195,7 +1250,6 @@ static void sysbus_esp_pdma_write(void *opaque, hwaddr addr,
|
||||
{
|
||||
SysBusESPState *sysbus = opaque;
|
||||
ESPState *s = ESP(&sysbus->esp);
|
||||
uint32_t dmalen;
|
||||
|
||||
trace_esp_pdma_write(size);
|
||||
|
||||
@@ -1208,10 +1262,7 @@ static void sysbus_esp_pdma_write(void *opaque, hwaddr addr,
|
||||
esp_pdma_write(s, val);
|
||||
break;
|
||||
}
|
||||
dmalen = esp_get_tc(s);
|
||||
if (dmalen == 0 || fifo8_num_free(&s->fifo) < 2) {
|
||||
s->pdma_cb(s);
|
||||
}
|
||||
s->pdma_cb(s);
|
||||
}
|
||||
|
||||
static uint64_t sysbus_esp_pdma_read(void *opaque, hwaddr addr,
|
||||
|
||||
@@ -147,7 +147,7 @@ static int execute_command(BlockBackend *blk,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void scsi_handle_inquiry_reply(SCSIGenericReq *r, SCSIDevice *s)
|
||||
static int scsi_handle_inquiry_reply(SCSIGenericReq *r, SCSIDevice *s, int len)
|
||||
{
|
||||
uint8_t page, page_idx;
|
||||
|
||||
@@ -213,8 +213,13 @@ static void scsi_handle_inquiry_reply(SCSIGenericReq *r, SCSIDevice *s)
|
||||
r->buf[page_idx] = 0xb0;
|
||||
}
|
||||
stw_be_p(r->buf + 2, lduw_be_p(r->buf + 2) + 1);
|
||||
|
||||
if (len < r->buflen) {
|
||||
len++;
|
||||
}
|
||||
}
|
||||
}
|
||||
return len;
|
||||
}
|
||||
|
||||
static int scsi_generic_emulate_block_limits(SCSIGenericReq *r, SCSIDevice *s)
|
||||
@@ -332,7 +337,7 @@ static void scsi_read_complete(void * opaque, int ret)
|
||||
}
|
||||
}
|
||||
if (r->req.cmd.buf[0] == INQUIRY) {
|
||||
scsi_handle_inquiry_reply(r, s);
|
||||
len = scsi_handle_inquiry_reply(r, s, len);
|
||||
}
|
||||
|
||||
req_complete:
|
||||
|
||||
@@ -166,7 +166,8 @@ esp_dma_disable(void) "Lower enable"
|
||||
esp_pdma_read(int size) "pDMA read %u bytes"
|
||||
esp_pdma_write(int size) "pDMA write %u bytes"
|
||||
esp_get_cmd(uint32_t dmalen, int target) "len %d target %d"
|
||||
esp_do_busid_cmd(uint8_t busid) "busid 0x%x"
|
||||
esp_do_command_phase(uint8_t busid) "busid 0x%x"
|
||||
esp_do_identify(uint8_t byte) "0x%x"
|
||||
esp_handle_satn_stop(uint32_t cmdlen) "cmdlen %d"
|
||||
esp_write_response(uint32_t status) "Transfer status (status=%d)"
|
||||
esp_do_dma(uint32_t cmdlen, uint32_t len) "command len %d + %d"
|
||||
|
||||
@@ -59,6 +59,7 @@ ram_addr_t qemu_ram_get_offset(RAMBlock *rb);
|
||||
ram_addr_t qemu_ram_get_used_length(RAMBlock *rb);
|
||||
ram_addr_t qemu_ram_get_max_length(RAMBlock *rb);
|
||||
bool qemu_ram_is_shared(RAMBlock *rb);
|
||||
bool qemu_ram_is_noreserve(RAMBlock *rb);
|
||||
bool qemu_ram_is_uf_zeroable(RAMBlock *rb);
|
||||
void qemu_ram_set_uf_zeroable(RAMBlock *rb);
|
||||
bool qemu_ram_is_migratable(RAMBlock *rb);
|
||||
|
||||
+24
-18
@@ -155,6 +155,13 @@ typedef struct IOMMUTLBEvent {
|
||||
*/
|
||||
#define RAM_UF_WRITEPROTECT (1 << 6)
|
||||
|
||||
/*
|
||||
* RAM is mmap-ed with MAP_NORESERVE. When set, reserving swap space (or huge
|
||||
* pages if applicable) is skipped: will bail out if not supported. When not
|
||||
* set, the OS will do the reservation, if supported for the memory type.
|
||||
*/
|
||||
#define RAM_NORESERVE (1 << 7)
|
||||
|
||||
static inline void iommu_notifier_init(IOMMUNotifier *n, IOMMUNotify fn,
|
||||
IOMMUNotifierFlag flags,
|
||||
hwaddr start, hwaddr end,
|
||||
@@ -940,27 +947,27 @@ void memory_region_init_ram_nomigrate(MemoryRegion *mr,
|
||||
Error **errp);
|
||||
|
||||
/**
|
||||
* memory_region_init_ram_shared_nomigrate: Initialize RAM memory region.
|
||||
* Accesses into the region will
|
||||
* modify memory directly.
|
||||
* memory_region_init_ram_flags_nomigrate: Initialize RAM memory region.
|
||||
* Accesses into the region will
|
||||
* modify memory directly.
|
||||
*
|
||||
* @mr: the #MemoryRegion to be initialized.
|
||||
* @owner: the object that tracks the region's reference count
|
||||
* @name: Region name, becomes part of RAMBlock name used in migration stream
|
||||
* must be unique within any device
|
||||
* @size: size of the region.
|
||||
* @share: allow remapping RAM to different addresses
|
||||
* @ram_flags: RamBlock flags. Supported flags: RAM_SHARED, RAM_NORESERVE.
|
||||
* @errp: pointer to Error*, to store an error if it happens.
|
||||
*
|
||||
* Note that this function is similar to memory_region_init_ram_nomigrate.
|
||||
* The only difference is part of the RAM region can be remapped.
|
||||
* Note that this function does not do anything to cause the data in the
|
||||
* RAM memory region to be migrated; that is the responsibility of the caller.
|
||||
*/
|
||||
void memory_region_init_ram_shared_nomigrate(MemoryRegion *mr,
|
||||
Object *owner,
|
||||
const char *name,
|
||||
uint64_t size,
|
||||
bool share,
|
||||
Error **errp);
|
||||
void memory_region_init_ram_flags_nomigrate(MemoryRegion *mr,
|
||||
Object *owner,
|
||||
const char *name,
|
||||
uint64_t size,
|
||||
uint32_t ram_flags,
|
||||
Error **errp);
|
||||
|
||||
/**
|
||||
* memory_region_init_resizeable_ram: Initialize memory region with resizeable
|
||||
@@ -1005,10 +1012,8 @@ void memory_region_init_resizeable_ram(MemoryRegion *mr,
|
||||
* @size: size of the region.
|
||||
* @align: alignment of the region base address; if 0, the default alignment
|
||||
* (getpagesize()) will be used.
|
||||
* @ram_flags: Memory region features:
|
||||
* - RAM_SHARED: memory must be mmaped with the MAP_SHARED flag
|
||||
* - RAM_PMEM: the memory is persistent memory
|
||||
* Other bits are ignored now.
|
||||
* @ram_flags: RamBlock flags. Supported flags: RAM_SHARED, RAM_PMEM,
|
||||
* RAM_NORESERVE,
|
||||
* @path: the path in which to allocate the RAM.
|
||||
* @readonly: true to open @path for reading, false for read/write.
|
||||
* @errp: pointer to Error*, to store an error if it happens.
|
||||
@@ -1034,7 +1039,8 @@ void memory_region_init_ram_from_file(MemoryRegion *mr,
|
||||
* @owner: the object that tracks the region's reference count
|
||||
* @name: the name of the region.
|
||||
* @size: size of the region.
|
||||
* @share: %true if memory must be mmaped with the MAP_SHARED flag
|
||||
* @ram_flags: RamBlock flags. Supported flags: RAM_SHARED, RAM_PMEM,
|
||||
* RAM_NORESERVE.
|
||||
* @fd: the fd to mmap.
|
||||
* @offset: offset within the file referenced by fd
|
||||
* @errp: pointer to Error*, to store an error if it happens.
|
||||
@@ -1046,7 +1052,7 @@ void memory_region_init_ram_from_fd(MemoryRegion *mr,
|
||||
Object *owner,
|
||||
const char *name,
|
||||
uint64_t size,
|
||||
bool share,
|
||||
uint32_t ram_flags,
|
||||
int fd,
|
||||
ram_addr_t offset,
|
||||
Error **errp);
|
||||
|
||||
@@ -104,11 +104,8 @@ long qemu_maxrampagesize(void);
|
||||
* Parameters:
|
||||
* @size: the size in bytes of the ram block
|
||||
* @mr: the memory region where the ram block is
|
||||
* @ram_flags: specify the properties of the ram block, which can be one
|
||||
* or bit-or of following values
|
||||
* - RAM_SHARED: mmap the backing file or device with MAP_SHARED
|
||||
* - RAM_PMEM: the backend @mem_path or @fd is persistent memory
|
||||
* Other bits are ignored.
|
||||
* @ram_flags: RamBlock flags. Supported flags: RAM_SHARED, RAM_PMEM,
|
||||
* RAM_NORESERVE.
|
||||
* @mem_path or @fd: specify the backing file or device
|
||||
* @readonly: true to open @path for reading, false for read/write.
|
||||
* @errp: pointer to Error*, to store an error if it happens
|
||||
@@ -126,7 +123,7 @@ RAMBlock *qemu_ram_alloc_from_fd(ram_addr_t size, MemoryRegion *mr,
|
||||
|
||||
RAMBlock *qemu_ram_alloc_from_ptr(ram_addr_t size, void *host,
|
||||
MemoryRegion *mr, Error **errp);
|
||||
RAMBlock *qemu_ram_alloc(ram_addr_t size, bool share, MemoryRegion *mr,
|
||||
RAMBlock *qemu_ram_alloc(ram_addr_t size, uint32_t ram_flags, MemoryRegion *mr,
|
||||
Error **errp);
|
||||
RAMBlock *qemu_ram_alloc_resizeable(ram_addr_t size, ram_addr_t max_size,
|
||||
void (*resized)(const char*,
|
||||
|
||||
@@ -37,6 +37,7 @@ struct ESPState {
|
||||
SCSIRequest *current_req;
|
||||
Fifo8 cmdfifo;
|
||||
uint8_t cmdfifo_cdb_offset;
|
||||
uint8_t lun;
|
||||
uint32_t do_cmd;
|
||||
|
||||
bool data_in_ready;
|
||||
|
||||
@@ -7,18 +7,22 @@ size_t qemu_fd_getpagesize(int fd);
|
||||
size_t qemu_mempath_getpagesize(const char *mem_path);
|
||||
|
||||
/**
|
||||
* qemu_ram_mmap: mmap the specified file or device.
|
||||
* qemu_ram_mmap: mmap anonymous memory, the specified file or device.
|
||||
*
|
||||
* mmap() abstraction to map guest RAM, simplifying flag handling, taking
|
||||
* care of alignment requirements and installing guard pages.
|
||||
*
|
||||
* Parameters:
|
||||
* @fd: the file or the device to mmap
|
||||
* @size: the number of bytes to be mmaped
|
||||
* @align: if not zero, specify the alignment of the starting mapping address;
|
||||
* otherwise, the alignment in use will be determined by QEMU.
|
||||
* @readonly: true for a read-only mapping, false for read/write.
|
||||
* @shared: map has RAM_SHARED flag.
|
||||
* @is_pmem: map has RAM_PMEM flag.
|
||||
* @qemu_map_flags: QEMU_MAP_* flags
|
||||
* @map_offset: map starts at offset of map_offset from the start of fd
|
||||
*
|
||||
* Internally, MAP_PRIVATE, MAP_ANONYMOUS and MAP_SHARED_VALIDATE are set
|
||||
* implicitly based on other parameters.
|
||||
*
|
||||
* Return:
|
||||
* On success, return a pointer to the mapped area.
|
||||
* On failure, return MAP_FAILED.
|
||||
@@ -26,9 +30,7 @@ size_t qemu_mempath_getpagesize(const char *mem_path);
|
||||
void *qemu_ram_mmap(int fd,
|
||||
size_t size,
|
||||
size_t align,
|
||||
bool readonly,
|
||||
bool shared,
|
||||
bool is_pmem,
|
||||
uint32_t qemu_map_flags,
|
||||
off_t map_offset);
|
||||
|
||||
void qemu_ram_munmap(int fd, void *ptr, size_t size);
|
||||
|
||||
+31
-3
@@ -195,6 +195,9 @@ extern "C" {
|
||||
#ifndef MAP_FIXED_NOREPLACE
|
||||
#define MAP_FIXED_NOREPLACE 0
|
||||
#endif
|
||||
#ifndef MAP_NORESERVE
|
||||
#define MAP_NORESERVE 0
|
||||
#endif
|
||||
#ifndef ENOMEDIUM
|
||||
#define ENOMEDIUM ENODEV
|
||||
#endif
|
||||
@@ -362,10 +365,35 @@ extern "C" {
|
||||
int qemu_daemon(int nochdir, int noclose);
|
||||
void *qemu_try_memalign(size_t alignment, size_t size);
|
||||
void *qemu_memalign(size_t alignment, size_t size);
|
||||
void *qemu_anon_ram_alloc(size_t size, uint64_t *align, bool shared);
|
||||
void *qemu_anon_ram_alloc(size_t size, uint64_t *align, bool shared,
|
||||
bool noreserve);
|
||||
void qemu_vfree(void *ptr);
|
||||
void qemu_anon_ram_free(void *ptr, size_t size);
|
||||
|
||||
/*
|
||||
* Abstraction of PROT_ and MAP_ flags as passed to mmap(), for example,
|
||||
* consumed by qemu_ram_mmap().
|
||||
*/
|
||||
|
||||
/* Map PROT_READ instead of PROT_READ | PROT_WRITE. */
|
||||
#define QEMU_MAP_READONLY (1 << 0)
|
||||
|
||||
/* Use MAP_SHARED instead of MAP_PRIVATE. */
|
||||
#define QEMU_MAP_SHARED (1 << 1)
|
||||
|
||||
/*
|
||||
* Use MAP_SYNC | MAP_SHARED_VALIDATE if supported. Ignored without
|
||||
* QEMU_MAP_SHARED. If mapping fails, warn and fallback to !QEMU_MAP_SYNC.
|
||||
*/
|
||||
#define QEMU_MAP_SYNC (1 << 2)
|
||||
|
||||
/*
|
||||
* Use MAP_NORESERVE to skip reservation of swap space (or huge pages if
|
||||
* applicable). Bail out if not supported/effective.
|
||||
*/
|
||||
#define QEMU_MAP_NORESERVE (1 << 3)
|
||||
|
||||
|
||||
#define QEMU_MADV_INVALID -1
|
||||
|
||||
#if defined(CONFIG_MADVISE)
|
||||
@@ -410,7 +438,7 @@ void qemu_anon_ram_free(void *ptr, size_t size);
|
||||
#ifdef MADV_REMOVE
|
||||
#define QEMU_MADV_REMOVE MADV_REMOVE
|
||||
#else
|
||||
#define QEMU_MADV_REMOVE QEMU_MADV_INVALID
|
||||
#define QEMU_MADV_REMOVE QEMU_MADV_DONTNEED
|
||||
#endif
|
||||
|
||||
#elif defined(CONFIG_POSIX_MADVISE)
|
||||
@@ -424,7 +452,7 @@ void qemu_anon_ram_free(void *ptr, size_t size);
|
||||
#define QEMU_MADV_DONTDUMP QEMU_MADV_INVALID
|
||||
#define QEMU_MADV_HUGEPAGE QEMU_MADV_INVALID
|
||||
#define QEMU_MADV_NOHUGEPAGE QEMU_MADV_INVALID
|
||||
#define QEMU_MADV_REMOVE QEMU_MADV_INVALID
|
||||
#define QEMU_MADV_REMOVE QEMU_MADV_DONTNEED
|
||||
|
||||
#else /* no-op */
|
||||
|
||||
|
||||
@@ -64,7 +64,7 @@ struct HostMemoryBackend {
|
||||
/* protected */
|
||||
uint64_t size;
|
||||
bool merge, dump, use_canonical_path;
|
||||
bool prealloc, is_mapped, share;
|
||||
bool prealloc, is_mapped, share, reserve;
|
||||
uint32_t prealloc_threads;
|
||||
DECLARE_BITMAP(host_nodes, MAX_NODES + 1);
|
||||
HostMemPolicy policy;
|
||||
|
||||
+1
-2
@@ -3343,8 +3343,7 @@ int colo_init_ram_cache(void)
|
||||
WITH_RCU_READ_LOCK_GUARD() {
|
||||
RAMBLOCK_FOREACH_NOT_IGNORED(block) {
|
||||
block->colo_cache = qemu_anon_ram_alloc(block->used_length,
|
||||
NULL,
|
||||
false);
|
||||
NULL, false, false);
|
||||
if (!block->colo_cache) {
|
||||
error_report("%s: Can't alloc memory for COLO cache of block %s,"
|
||||
"size 0x" RAM_ADDR_FMT, __func__, block->idstr,
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user