Merge remote-tracking branch 'sstabellini/saverestore-8' into staging
* sstabellini/saverestore-8: xen: do not allocate RAM during INMIGRATE runstate xen mapcache: check if memory region has moved. xen: record physmap changes to xenstore Set runstate to INMIGRATE earlier Introduce "xen-save-devices-state" cirrus_vga: do not reset videoram Conflicts: qapi-schema.json Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
This commit is contained in:
		
						commit
						33cf629a37
					
				
							
								
								
									
										34
									
								
								docs/xen-save-devices-state.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										34
									
								
								docs/xen-save-devices-state.txt
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,34 @@
 | 
				
			|||||||
 | 
					= Save Devices =
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					QEMU has code to load/save the state of the guest that it is running.
 | 
				
			||||||
 | 
					These are two complementary operations.  Saving the state just does
 | 
				
			||||||
 | 
					that, saves the state for each device that the guest is running.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					These operations are normally used with migration (see migration.txt),
 | 
				
			||||||
 | 
					however it is also possible to save the state of all devices to file,
 | 
				
			||||||
 | 
					without saving the RAM or the block devices of the VM.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					This operation is called "xen-save-devices-state" (see
 | 
				
			||||||
 | 
					QMP/qmp-commands.txt)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					The binary format used in the file is the following:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					-------------------------------------------
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					32 bit big endian: QEMU_VM_FILE_MAGIC
 | 
				
			||||||
 | 
					32 bit big endian: QEMU_VM_FILE_VERSION
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					for_each_device
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    8 bit:              QEMU_VM_SECTION_FULL
 | 
				
			||||||
 | 
					    32 bit big endian:  section_id
 | 
				
			||||||
 | 
					    8 bit:              idstr (ID string) length
 | 
				
			||||||
 | 
					    string:             idstr (ID string)
 | 
				
			||||||
 | 
					    32 bit big endian:  instance_id
 | 
				
			||||||
 | 
					    32 bit big endian:  version_id
 | 
				
			||||||
 | 
					    buffer:             device specific data
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					8 bit: QEMU_VM_EOF
 | 
				
			||||||
@ -2767,10 +2767,6 @@ static void cirrus_reset(void *opaque)
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
    s->vga.cr[0x27] = s->device_id;
 | 
					    s->vga.cr[0x27] = s->device_id;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /* Win2K seems to assume that the pattern buffer is at 0xff
 | 
					 | 
				
			||||||
       initially ! */
 | 
					 | 
				
			||||||
    memset(s->vga.vram_ptr, 0xff, s->real_vram_size);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    s->cirrus_hidden_dac_lockindex = 5;
 | 
					    s->cirrus_hidden_dac_lockindex = 5;
 | 
				
			||||||
    s->cirrus_hidden_dac_data = 0;
 | 
					    s->cirrus_hidden_dac_data = 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -1684,3 +1684,20 @@
 | 
				
			|||||||
##
 | 
					##
 | 
				
			||||||
{ 'command': 'migrate',
 | 
					{ 'command': 'migrate',
 | 
				
			||||||
  'data': {'uri': 'str', '*blk': 'bool', '*inc': 'bool', '*detach': 'bool' } }
 | 
					  'data': {'uri': 'str', '*blk': 'bool', '*inc': 'bool', '*detach': 'bool' } }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# @xen-save-devices-state:
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# Save the state of all devices to file. The RAM and the block devices
 | 
				
			||||||
 | 
					# of the VM are not saved by this command.
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# @filename: the file to save the state of the devices to as binary
 | 
				
			||||||
 | 
					# data. See xen-save-devices-state.txt for a description of the binary
 | 
				
			||||||
 | 
					# format.
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# Returns: Nothing on success
 | 
				
			||||||
 | 
					#          If @filename cannot be opened, OpenFileFailed
 | 
				
			||||||
 | 
					#          If an I/O error occurs while writing the file, IOError
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# Since: 1.1
 | 
				
			||||||
 | 
					##
 | 
				
			||||||
 | 
					{ 'command': 'xen-save-devices-state', 'data': {'filename': 'str'} }
 | 
				
			||||||
 | 
				
			|||||||
@ -441,6 +441,33 @@ Example:
 | 
				
			|||||||
Note: inject-nmi is only supported for x86 guest currently, it will
 | 
					Note: inject-nmi is only supported for x86 guest currently, it will
 | 
				
			||||||
      returns "Unsupported" error for non-x86 guest.
 | 
					      returns "Unsupported" error for non-x86 guest.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					EQMP
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        .name       = "xen-save-devices-state",
 | 
				
			||||||
 | 
					        .args_type  = "filename:F",
 | 
				
			||||||
 | 
					    .mhandler.cmd_new = qmp_marshal_input_xen_save_devices_state,
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					SQMP
 | 
				
			||||||
 | 
					xen-save-devices-state
 | 
				
			||||||
 | 
					-------
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Save the state of all devices to file. The RAM and the block devices
 | 
				
			||||||
 | 
					of the VM are not saved by this command.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Arguments:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					- "filename": the file to save the state of the devices to as binary
 | 
				
			||||||
 | 
					data. See xen-save-devices-state.txt for a description of the binary
 | 
				
			||||||
 | 
					format.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Example:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					-> { "execute": "xen-save-devices-state",
 | 
				
			||||||
 | 
					     "arguments": { "filename": "/tmp/save" } }
 | 
				
			||||||
 | 
					<- { "return": {} }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
EQMP
 | 
					EQMP
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										71
									
								
								savevm.c
									
									
									
									
									
								
							
							
						
						
									
										71
									
								
								savevm.c
									
									
									
									
									
								
							@ -84,6 +84,7 @@
 | 
				
			|||||||
#include "qemu-timer.h"
 | 
					#include "qemu-timer.h"
 | 
				
			||||||
#include "cpus.h"
 | 
					#include "cpus.h"
 | 
				
			||||||
#include "memory.h"
 | 
					#include "memory.h"
 | 
				
			||||||
 | 
					#include "qmp-commands.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define SELF_ANNOUNCE_ROUNDS 5
 | 
					#define SELF_ANNOUNCE_ROUNDS 5
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -1177,6 +1178,7 @@ typedef struct SaveStateEntry {
 | 
				
			|||||||
    void *opaque;
 | 
					    void *opaque;
 | 
				
			||||||
    CompatEntry *compat;
 | 
					    CompatEntry *compat;
 | 
				
			||||||
    int no_migrate;
 | 
					    int no_migrate;
 | 
				
			||||||
 | 
					    int is_ram;
 | 
				
			||||||
} SaveStateEntry;
 | 
					} SaveStateEntry;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -1241,6 +1243,10 @@ int register_savevm_live(DeviceState *dev,
 | 
				
			|||||||
    se->opaque = opaque;
 | 
					    se->opaque = opaque;
 | 
				
			||||||
    se->vmsd = NULL;
 | 
					    se->vmsd = NULL;
 | 
				
			||||||
    se->no_migrate = 0;
 | 
					    se->no_migrate = 0;
 | 
				
			||||||
 | 
					    /* if this is a live_savem then set is_ram */
 | 
				
			||||||
 | 
					    if (save_live_state != NULL) {
 | 
				
			||||||
 | 
					        se->is_ram = 1;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (dev && dev->parent_bus && dev->parent_bus->info->get_dev_path) {
 | 
					    if (dev && dev->parent_bus && dev->parent_bus->info->get_dev_path) {
 | 
				
			||||||
        char *id = dev->parent_bus->info->get_dev_path(dev);
 | 
					        char *id = dev->parent_bus->info->get_dev_path(dev);
 | 
				
			||||||
@ -1728,6 +1734,45 @@ out:
 | 
				
			|||||||
    return ret;
 | 
					    return ret;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static int qemu_save_device_state(QEMUFile *f)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    SaveStateEntry *se;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    qemu_put_be32(f, QEMU_VM_FILE_MAGIC);
 | 
				
			||||||
 | 
					    qemu_put_be32(f, QEMU_VM_FILE_VERSION);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    cpu_synchronize_all_states();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    QTAILQ_FOREACH(se, &savevm_handlers, entry) {
 | 
				
			||||||
 | 
					        int len;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (se->is_ram) {
 | 
				
			||||||
 | 
					            continue;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        if (se->save_state == NULL && se->vmsd == NULL) {
 | 
				
			||||||
 | 
					            continue;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        /* Section type */
 | 
				
			||||||
 | 
					        qemu_put_byte(f, QEMU_VM_SECTION_FULL);
 | 
				
			||||||
 | 
					        qemu_put_be32(f, se->section_id);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        /* ID string */
 | 
				
			||||||
 | 
					        len = strlen(se->idstr);
 | 
				
			||||||
 | 
					        qemu_put_byte(f, len);
 | 
				
			||||||
 | 
					        qemu_put_buffer(f, (uint8_t *)se->idstr, len);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        qemu_put_be32(f, se->instance_id);
 | 
				
			||||||
 | 
					        qemu_put_be32(f, se->version_id);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        vmstate_save(f, se);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    qemu_put_byte(f, QEMU_VM_EOF);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return qemu_file_get_error(f);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static SaveStateEntry *find_se(const char *idstr, int instance_id)
 | 
					static SaveStateEntry *find_se(const char *idstr, int instance_id)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    SaveStateEntry *se;
 | 
					    SaveStateEntry *se;
 | 
				
			||||||
@ -2109,6 +2154,32 @@ void do_savevm(Monitor *mon, const QDict *qdict)
 | 
				
			|||||||
        vm_start();
 | 
					        vm_start();
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void qmp_xen_save_devices_state(const char *filename, Error **errp)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    QEMUFile *f;
 | 
				
			||||||
 | 
					    int saved_vm_running;
 | 
				
			||||||
 | 
					    int ret;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    saved_vm_running = runstate_is_running();
 | 
				
			||||||
 | 
					    vm_stop(RUN_STATE_SAVE_VM);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    f = qemu_fopen(filename, "wb");
 | 
				
			||||||
 | 
					    if (!f) {
 | 
				
			||||||
 | 
					        error_set(errp, QERR_OPEN_FILE_FAILED, filename);
 | 
				
			||||||
 | 
					        goto the_end;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    ret = qemu_save_device_state(f);
 | 
				
			||||||
 | 
					    qemu_fclose(f);
 | 
				
			||||||
 | 
					    if (ret < 0) {
 | 
				
			||||||
 | 
					        error_set(errp, QERR_IO_ERROR);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 the_end:
 | 
				
			||||||
 | 
					    if (saved_vm_running)
 | 
				
			||||||
 | 
					        vm_start();
 | 
				
			||||||
 | 
					    return;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
int load_vmstate(const char *name)
 | 
					int load_vmstate(const char *name)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    BlockDriverState *bs, *bs_vm_state;
 | 
					    BlockDriverState *bs, *bs_vm_state;
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										2
									
								
								vl.c
									
									
									
									
									
								
							
							
						
						
									
										2
									
								
								vl.c
									
									
									
									
									
								
							@ -3099,6 +3099,7 @@ int main(int argc, char **argv, char **envp)
 | 
				
			|||||||
                break;
 | 
					                break;
 | 
				
			||||||
            case QEMU_OPTION_incoming:
 | 
					            case QEMU_OPTION_incoming:
 | 
				
			||||||
                incoming = optarg;
 | 
					                incoming = optarg;
 | 
				
			||||||
 | 
					                runstate_set(RUN_STATE_INMIGRATE);
 | 
				
			||||||
                break;
 | 
					                break;
 | 
				
			||||||
            case QEMU_OPTION_nodefaults:
 | 
					            case QEMU_OPTION_nodefaults:
 | 
				
			||||||
                default_serial = 0;
 | 
					                default_serial = 0;
 | 
				
			||||||
@ -3616,7 +3617,6 @@ int main(int argc, char **argv, char **envp)
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (incoming) {
 | 
					    if (incoming) {
 | 
				
			||||||
        runstate_set(RUN_STATE_INMIGRATE);
 | 
					 | 
				
			||||||
        int ret = qemu_start_incoming_migration(incoming);
 | 
					        int ret = qemu_start_incoming_migration(incoming);
 | 
				
			||||||
        if (ret < 0) {
 | 
					        if (ret < 0) {
 | 
				
			||||||
            fprintf(stderr, "Migration failed. Exit code %s(%d), exiting.\n",
 | 
					            fprintf(stderr, "Migration failed. Exit code %s(%d), exiting.\n",
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										104
									
								
								xen-all.c
									
									
									
									
									
								
							
							
						
						
									
										104
									
								
								xen-all.c
									
									
									
									
									
								
							@ -65,7 +65,7 @@ static inline ioreq_t *xen_vcpu_ioreq(shared_iopage_t *shared_page, int vcpu)
 | 
				
			|||||||
typedef struct XenPhysmap {
 | 
					typedef struct XenPhysmap {
 | 
				
			||||||
    target_phys_addr_t start_addr;
 | 
					    target_phys_addr_t start_addr;
 | 
				
			||||||
    ram_addr_t size;
 | 
					    ram_addr_t size;
 | 
				
			||||||
    MemoryRegion *mr;
 | 
					    char *name;
 | 
				
			||||||
    target_phys_addr_t phys_offset;
 | 
					    target_phys_addr_t phys_offset;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    QLIST_ENTRY(XenPhysmap) list;
 | 
					    QLIST_ENTRY(XenPhysmap) list;
 | 
				
			||||||
@ -190,6 +190,14 @@ void xen_ram_alloc(ram_addr_t ram_addr, ram_addr_t size, MemoryRegion *mr)
 | 
				
			|||||||
    xen_pfn_t *pfn_list;
 | 
					    xen_pfn_t *pfn_list;
 | 
				
			||||||
    int i;
 | 
					    int i;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (runstate_check(RUN_STATE_INMIGRATE)) {
 | 
				
			||||||
 | 
					        /* RAM already populated in Xen */
 | 
				
			||||||
 | 
					        fprintf(stderr, "%s: do not alloc "RAM_ADDR_FMT
 | 
				
			||||||
 | 
					                " bytes of ram at "RAM_ADDR_FMT" when runstate is INMIGRATE\n",
 | 
				
			||||||
 | 
					                __func__, size, ram_addr); 
 | 
				
			||||||
 | 
					        return;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (mr == &ram_memory) {
 | 
					    if (mr == &ram_memory) {
 | 
				
			||||||
        return;
 | 
					        return;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
@ -225,6 +233,22 @@ static XenPhysmap *get_physmapping(XenIOState *state,
 | 
				
			|||||||
    return NULL;
 | 
					    return NULL;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static target_phys_addr_t xen_phys_offset_to_gaddr(target_phys_addr_t start_addr,
 | 
				
			||||||
 | 
					                                                   ram_addr_t size, void *opaque)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    target_phys_addr_t addr = start_addr & TARGET_PAGE_MASK;
 | 
				
			||||||
 | 
					    XenIOState *xen_io_state = opaque;
 | 
				
			||||||
 | 
					    XenPhysmap *physmap = NULL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    QLIST_FOREACH(physmap, &xen_io_state->physmap, list) {
 | 
				
			||||||
 | 
					        if (range_covers_byte(physmap->phys_offset, physmap->size, addr)) {
 | 
				
			||||||
 | 
					            return physmap->start_addr;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return start_addr;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#if CONFIG_XEN_CTRL_INTERFACE_VERSION >= 340
 | 
					#if CONFIG_XEN_CTRL_INTERFACE_VERSION >= 340
 | 
				
			||||||
static int xen_add_to_physmap(XenIOState *state,
 | 
					static int xen_add_to_physmap(XenIOState *state,
 | 
				
			||||||
                              target_phys_addr_t start_addr,
 | 
					                              target_phys_addr_t start_addr,
 | 
				
			||||||
@ -237,6 +261,7 @@ static int xen_add_to_physmap(XenIOState *state,
 | 
				
			|||||||
    XenPhysmap *physmap = NULL;
 | 
					    XenPhysmap *physmap = NULL;
 | 
				
			||||||
    target_phys_addr_t pfn, start_gpfn;
 | 
					    target_phys_addr_t pfn, start_gpfn;
 | 
				
			||||||
    target_phys_addr_t phys_offset = memory_region_get_ram_addr(mr);
 | 
					    target_phys_addr_t phys_offset = memory_region_get_ram_addr(mr);
 | 
				
			||||||
 | 
					    char path[80], value[17];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (get_physmapping(state, start_addr, size)) {
 | 
					    if (get_physmapping(state, start_addr, size)) {
 | 
				
			||||||
        return 0;
 | 
					        return 0;
 | 
				
			||||||
@ -275,6 +300,7 @@ go_physmap:
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    physmap->start_addr = start_addr;
 | 
					    physmap->start_addr = start_addr;
 | 
				
			||||||
    physmap->size = size;
 | 
					    physmap->size = size;
 | 
				
			||||||
 | 
					    physmap->name = (char *)mr->name;
 | 
				
			||||||
    physmap->phys_offset = phys_offset;
 | 
					    physmap->phys_offset = phys_offset;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    QLIST_INSERT_HEAD(&state->physmap, physmap, list);
 | 
					    QLIST_INSERT_HEAD(&state->physmap, physmap, list);
 | 
				
			||||||
@ -283,6 +309,30 @@ go_physmap:
 | 
				
			|||||||
                                   start_addr >> TARGET_PAGE_BITS,
 | 
					                                   start_addr >> TARGET_PAGE_BITS,
 | 
				
			||||||
                                   (start_addr + size) >> TARGET_PAGE_BITS,
 | 
					                                   (start_addr + size) >> TARGET_PAGE_BITS,
 | 
				
			||||||
                                   XEN_DOMCTL_MEM_CACHEATTR_WB);
 | 
					                                   XEN_DOMCTL_MEM_CACHEATTR_WB);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    snprintf(path, sizeof(path),
 | 
				
			||||||
 | 
					            "/local/domain/0/device-model/%d/physmap/%"PRIx64"/start_addr",
 | 
				
			||||||
 | 
					            xen_domid, (uint64_t)phys_offset);
 | 
				
			||||||
 | 
					    snprintf(value, sizeof(value), "%"PRIx64, (uint64_t)start_addr);
 | 
				
			||||||
 | 
					    if (!xs_write(state->xenstore, 0, path, value, strlen(value))) {
 | 
				
			||||||
 | 
					        return -1;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    snprintf(path, sizeof(path),
 | 
				
			||||||
 | 
					            "/local/domain/0/device-model/%d/physmap/%"PRIx64"/size",
 | 
				
			||||||
 | 
					            xen_domid, (uint64_t)phys_offset);
 | 
				
			||||||
 | 
					    snprintf(value, sizeof(value), "%"PRIx64, (uint64_t)size);
 | 
				
			||||||
 | 
					    if (!xs_write(state->xenstore, 0, path, value, strlen(value))) {
 | 
				
			||||||
 | 
					        return -1;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    if (mr->name) {
 | 
				
			||||||
 | 
					        snprintf(path, sizeof(path),
 | 
				
			||||||
 | 
					                "/local/domain/0/device-model/%d/physmap/%"PRIx64"/name",
 | 
				
			||||||
 | 
					                xen_domid, (uint64_t)phys_offset);
 | 
				
			||||||
 | 
					        if (!xs_write(state->xenstore, 0, path, mr->name, strlen(mr->name))) {
 | 
				
			||||||
 | 
					            return -1;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    return 0;
 | 
					    return 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -942,6 +992,55 @@ int xen_init(void)
 | 
				
			|||||||
    return 0;
 | 
					    return 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void xen_read_physmap(XenIOState *state)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    XenPhysmap *physmap = NULL;
 | 
				
			||||||
 | 
					    unsigned int len, num, i;
 | 
				
			||||||
 | 
					    char path[80], *value = NULL;
 | 
				
			||||||
 | 
					    char **entries = NULL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    snprintf(path, sizeof(path),
 | 
				
			||||||
 | 
					            "/local/domain/0/device-model/%d/physmap", xen_domid);
 | 
				
			||||||
 | 
					    entries = xs_directory(state->xenstore, 0, path, &num);
 | 
				
			||||||
 | 
					    if (entries == NULL)
 | 
				
			||||||
 | 
					        return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    for (i = 0; i < num; i++) {
 | 
				
			||||||
 | 
					        physmap = g_malloc(sizeof (XenPhysmap));
 | 
				
			||||||
 | 
					        physmap->phys_offset = strtoull(entries[i], NULL, 16);
 | 
				
			||||||
 | 
					        snprintf(path, sizeof(path),
 | 
				
			||||||
 | 
					                "/local/domain/0/device-model/%d/physmap/%s/start_addr",
 | 
				
			||||||
 | 
					                xen_domid, entries[i]);
 | 
				
			||||||
 | 
					        value = xs_read(state->xenstore, 0, path, &len);
 | 
				
			||||||
 | 
					        if (value == NULL) {
 | 
				
			||||||
 | 
					            free(physmap);
 | 
				
			||||||
 | 
					            continue;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        physmap->start_addr = strtoull(value, NULL, 16);
 | 
				
			||||||
 | 
					        free(value);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        snprintf(path, sizeof(path),
 | 
				
			||||||
 | 
					                "/local/domain/0/device-model/%d/physmap/%s/size",
 | 
				
			||||||
 | 
					                xen_domid, entries[i]);
 | 
				
			||||||
 | 
					        value = xs_read(state->xenstore, 0, path, &len);
 | 
				
			||||||
 | 
					        if (value == NULL) {
 | 
				
			||||||
 | 
					            free(physmap);
 | 
				
			||||||
 | 
					            continue;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        physmap->size = strtoull(value, NULL, 16);
 | 
				
			||||||
 | 
					        free(value);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        snprintf(path, sizeof(path),
 | 
				
			||||||
 | 
					                "/local/domain/0/device-model/%d/physmap/%s/name",
 | 
				
			||||||
 | 
					                xen_domid, entries[i]);
 | 
				
			||||||
 | 
					        physmap->name = xs_read(state->xenstore, 0, path, &len);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        QLIST_INSERT_HEAD(&state->physmap, physmap, list);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    free(entries);
 | 
				
			||||||
 | 
					    return;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
int xen_hvm_init(void)
 | 
					int xen_hvm_init(void)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    int i, rc;
 | 
					    int i, rc;
 | 
				
			||||||
@ -999,7 +1098,7 @@ int xen_hvm_init(void)
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /* Init RAM management */
 | 
					    /* Init RAM management */
 | 
				
			||||||
    xen_map_cache_init();
 | 
					    xen_map_cache_init(xen_phys_offset_to_gaddr, state);
 | 
				
			||||||
    xen_ram_init(ram_size);
 | 
					    xen_ram_init(ram_size);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    qemu_add_vm_change_state_handler(xen_hvm_change_state_handler, state);
 | 
					    qemu_add_vm_change_state_handler(xen_hvm_change_state_handler, state);
 | 
				
			||||||
@ -1017,6 +1116,7 @@ int xen_hvm_init(void)
 | 
				
			|||||||
    xen_be_register("console", &xen_console_ops);
 | 
					    xen_be_register("console", &xen_console_ops);
 | 
				
			||||||
    xen_be_register("vkbd", &xen_kbdmouse_ops);
 | 
					    xen_be_register("vkbd", &xen_kbdmouse_ops);
 | 
				
			||||||
    xen_be_register("qdisk", &xen_blkdev_ops);
 | 
					    xen_be_register("qdisk", &xen_blkdev_ops);
 | 
				
			||||||
 | 
					    xen_read_physmap(state);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    return 0;
 | 
					    return 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -78,6 +78,9 @@ typedef struct MapCache {
 | 
				
			|||||||
    uint8_t *last_address_vaddr;
 | 
					    uint8_t *last_address_vaddr;
 | 
				
			||||||
    unsigned long max_mcache_size;
 | 
					    unsigned long max_mcache_size;
 | 
				
			||||||
    unsigned int mcache_bucket_shift;
 | 
					    unsigned int mcache_bucket_shift;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    phys_offset_to_gaddr_t phys_offset_to_gaddr;
 | 
				
			||||||
 | 
					    void *opaque;
 | 
				
			||||||
} MapCache;
 | 
					} MapCache;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static MapCache *mapcache;
 | 
					static MapCache *mapcache;
 | 
				
			||||||
@ -91,13 +94,16 @@ static inline int test_bits(int nr, int size, const unsigned long *addr)
 | 
				
			|||||||
        return 0;
 | 
					        return 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void xen_map_cache_init(void)
 | 
					void xen_map_cache_init(phys_offset_to_gaddr_t f, void *opaque)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    unsigned long size;
 | 
					    unsigned long size;
 | 
				
			||||||
    struct rlimit rlimit_as;
 | 
					    struct rlimit rlimit_as;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    mapcache = g_malloc0(sizeof (MapCache));
 | 
					    mapcache = g_malloc0(sizeof (MapCache));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    mapcache->phys_offset_to_gaddr = f;
 | 
				
			||||||
 | 
					    mapcache->opaque = opaque;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    QTAILQ_INIT(&mapcache->locked_entries);
 | 
					    QTAILQ_INIT(&mapcache->locked_entries);
 | 
				
			||||||
    mapcache->last_address_index = -1;
 | 
					    mapcache->last_address_index = -1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -193,9 +199,14 @@ uint8_t *xen_map_cache(target_phys_addr_t phys_addr, target_phys_addr_t size,
 | 
				
			|||||||
                       uint8_t lock)
 | 
					                       uint8_t lock)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    MapCacheEntry *entry, *pentry = NULL;
 | 
					    MapCacheEntry *entry, *pentry = NULL;
 | 
				
			||||||
    target_phys_addr_t address_index  = phys_addr >> MCACHE_BUCKET_SHIFT;
 | 
					    target_phys_addr_t address_index;
 | 
				
			||||||
    target_phys_addr_t address_offset = phys_addr & (MCACHE_BUCKET_SIZE - 1);
 | 
					    target_phys_addr_t address_offset;
 | 
				
			||||||
    target_phys_addr_t __size = size;
 | 
					    target_phys_addr_t __size = size;
 | 
				
			||||||
 | 
					    bool translated = false;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					tryagain:
 | 
				
			||||||
 | 
					    address_index  = phys_addr >> MCACHE_BUCKET_SHIFT;
 | 
				
			||||||
 | 
					    address_offset = phys_addr & (MCACHE_BUCKET_SIZE - 1);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    trace_xen_map_cache(phys_addr);
 | 
					    trace_xen_map_cache(phys_addr);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -237,6 +248,11 @@ uint8_t *xen_map_cache(target_phys_addr_t phys_addr, target_phys_addr_t size,
 | 
				
			|||||||
    if(!test_bits(address_offset >> XC_PAGE_SHIFT, size >> XC_PAGE_SHIFT,
 | 
					    if(!test_bits(address_offset >> XC_PAGE_SHIFT, size >> XC_PAGE_SHIFT,
 | 
				
			||||||
                entry->valid_mapping)) {
 | 
					                entry->valid_mapping)) {
 | 
				
			||||||
        mapcache->last_address_index = -1;
 | 
					        mapcache->last_address_index = -1;
 | 
				
			||||||
 | 
					        if (!translated && mapcache->phys_offset_to_gaddr) {
 | 
				
			||||||
 | 
					            phys_addr = mapcache->phys_offset_to_gaddr(phys_addr, size, mapcache->opaque);
 | 
				
			||||||
 | 
					            translated = true;
 | 
				
			||||||
 | 
					            goto tryagain;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
        trace_xen_map_cache_return(NULL);
 | 
					        trace_xen_map_cache_return(NULL);
 | 
				
			||||||
        return NULL;
 | 
					        return NULL;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
				
			|||||||
@ -11,9 +11,13 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
#include <stdlib.h>
 | 
					#include <stdlib.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					typedef target_phys_addr_t (*phys_offset_to_gaddr_t)(target_phys_addr_t start_addr,
 | 
				
			||||||
 | 
					                                                     ram_addr_t size,
 | 
				
			||||||
 | 
					                                                     void *opaque);
 | 
				
			||||||
#ifdef CONFIG_XEN
 | 
					#ifdef CONFIG_XEN
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void xen_map_cache_init(void);
 | 
					void xen_map_cache_init(phys_offset_to_gaddr_t f,
 | 
				
			||||||
 | 
					                        void *opaque);
 | 
				
			||||||
uint8_t *xen_map_cache(target_phys_addr_t phys_addr, target_phys_addr_t size,
 | 
					uint8_t *xen_map_cache(target_phys_addr_t phys_addr, target_phys_addr_t size,
 | 
				
			||||||
                       uint8_t lock);
 | 
					                       uint8_t lock);
 | 
				
			||||||
ram_addr_t xen_ram_addr_from_mapcache(void *ptr);
 | 
					ram_addr_t xen_ram_addr_from_mapcache(void *ptr);
 | 
				
			||||||
@ -22,7 +26,8 @@ void xen_invalidate_map_cache(void);
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
#else
 | 
					#else
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static inline void xen_map_cache_init(void)
 | 
					static inline void xen_map_cache_init(phys_offset_to_gaddr_t f,
 | 
				
			||||||
 | 
					                                      void *opaque)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user