Compare commits
	
		
			28 Commits
		
	
	
		
			pull-conso
			...
			pull-input
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
|  | 0ee4de5840 | ||
|  | ba4d26064e | ||
|  | 4083ae311d | ||
|  | 699eae17b8 | ||
|  | de5ee4a888 | ||
|  | db5fd8d709 | ||
|  | 82f11917c9 | ||
|  | 800e2ecc89 | ||
|  | 355392329e | ||
|  | 9220fe54c6 | ||
|  | 177ea79f65 | ||
|  | 5a0826f7d2 | ||
|  | 1535300119 | ||
|  | d8d5119cae | ||
|  | 5899d6d0b4 | ||
|  | b8d6ac9f90 | ||
|  | 2ccf97ec0f | ||
|  | eb513f82f0 | ||
|  | 24e60305c5 | ||
|  | 0c021c1fd2 | ||
|  | ec53b45bcd | ||
|  | 83ecb22ba2 | ||
|  | a5bd4470ed | ||
|  | 86a6a9bf55 | ||
|  | 9b6d7b365d | ||
|  | 3996e85c18 | ||
|  | 707ff80021 | ||
|  | 74acb99737 | 
| @@ -351,8 +351,10 @@ static inline void init_thread(struct target_pt_regs *_regs, struct image_info * | |||||||
|  |  | ||||||
|     _regs->gpr[1] = infop->start_stack; |     _regs->gpr[1] = infop->start_stack; | ||||||
| #if defined(TARGET_PPC64) && !defined(TARGET_ABI32) | #if defined(TARGET_PPC64) && !defined(TARGET_ABI32) | ||||||
|     entry = ldq_raw(infop->entry) + infop->load_addr; |     get_user_u64(entry, infop->entry); | ||||||
|     toc = ldq_raw(infop->entry + 8) + infop->load_addr; |     entry += infop->load_addr; | ||||||
|  |     get_user_u64(toc, infop->entry + 8); | ||||||
|  |     toc += infop->load_addr; | ||||||
|     _regs->gpr[2] = toc; |     _regs->gpr[2] = toc; | ||||||
|     infop->entry = entry; |     infop->entry = entry; | ||||||
| #endif | #endif | ||||||
| @@ -365,8 +367,9 @@ static inline void init_thread(struct target_pt_regs *_regs, struct image_info * | |||||||
|     get_user_ual(_regs->gpr[3], pos); |     get_user_ual(_regs->gpr[3], pos); | ||||||
|     pos += sizeof(abi_ulong); |     pos += sizeof(abi_ulong); | ||||||
|     _regs->gpr[4] = pos; |     _regs->gpr[4] = pos; | ||||||
|     for (tmp = 1; tmp != 0; pos += sizeof(abi_ulong)) |     for (tmp = 1; tmp != 0; pos += sizeof(abi_ulong)) { | ||||||
|         tmp = ldl(pos); |         get_user_ual(tmp, pos); | ||||||
|  |     } | ||||||
|     _regs->gpr[5] = pos; |     _regs->gpr[5] = pos; | ||||||
| } | } | ||||||
|  |  | ||||||
|   | |||||||
							
								
								
									
										29
									
								
								configure
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										29
									
								
								configure
									
									
									
									
										vendored
									
									
								
							| @@ -1869,6 +1869,32 @@ EOF | |||||||
| #if !defined(HVM_MAX_VCPUS) | #if !defined(HVM_MAX_VCPUS) | ||||||
| # error HVM_MAX_VCPUS not defined | # error HVM_MAX_VCPUS not defined | ||||||
| #endif | #endif | ||||||
|  | int main(void) { | ||||||
|  |   xc_interface *xc; | ||||||
|  |   xs_daemon_open(); | ||||||
|  |   xc = xc_interface_open(0, 0, 0); | ||||||
|  |   xc_hvm_set_mem_type(0, 0, HVMMEM_ram_ro, 0, 0); | ||||||
|  |   xc_gnttab_open(NULL, 0); | ||||||
|  |   xc_domain_add_to_physmap(0, 0, XENMAPSPACE_gmfn, 0, 0); | ||||||
|  |   xc_hvm_inject_msi(xc, 0, 0xf0000000, 0x00000000); | ||||||
|  |   xc_hvm_create_ioreq_server(xc, 0, 0, NULL); | ||||||
|  |   return 0; | ||||||
|  | } | ||||||
|  | EOF | ||||||
|  |       compile_prog "" "$xen_libs" | ||||||
|  |     then | ||||||
|  |     xen_ctrl_version=450 | ||||||
|  |     xen=yes | ||||||
|  |  | ||||||
|  |   elif | ||||||
|  |       cat > $TMPC <<EOF && | ||||||
|  | #include <xenctrl.h> | ||||||
|  | #include <xenstore.h> | ||||||
|  | #include <stdint.h> | ||||||
|  | #include <xen/hvm/hvm_info_table.h> | ||||||
|  | #if !defined(HVM_MAX_VCPUS) | ||||||
|  | # error HVM_MAX_VCPUS not defined | ||||||
|  | #endif | ||||||
| int main(void) { | int main(void) { | ||||||
|   xc_interface *xc; |   xc_interface *xc; | ||||||
|   xs_daemon_open(); |   xs_daemon_open(); | ||||||
| @@ -4283,6 +4309,9 @@ if test -n "$sparc_cpu"; then | |||||||
|     echo "Target Sparc Arch $sparc_cpu" |     echo "Target Sparc Arch $sparc_cpu" | ||||||
| fi | fi | ||||||
| echo "xen support       $xen" | echo "xen support       $xen" | ||||||
|  | if test "$xen" = "yes" ; then | ||||||
|  |   echo "xen ctrl version  $xen_ctrl_version" | ||||||
|  | fi | ||||||
| echo "brlapi support    $brlapi" | echo "brlapi support    $brlapi" | ||||||
| echo "bluez  support    $bluez" | echo "bluez  support    $bluez" | ||||||
| echo "Documentation     $docs" | echo "Documentation     $docs" | ||||||
|   | |||||||
							
								
								
									
										16
									
								
								exec.c
									
									
									
									
									
								
							
							
						
						
									
										16
									
								
								exec.c
									
									
									
									
									
								
							| @@ -553,7 +553,6 @@ void cpu_exec_init(CPUArchState *env) | |||||||
|     } |     } | ||||||
| } | } | ||||||
|  |  | ||||||
| #if defined(TARGET_HAS_ICE) |  | ||||||
| #if defined(CONFIG_USER_ONLY) | #if defined(CONFIG_USER_ONLY) | ||||||
| static void breakpoint_invalidate(CPUState *cpu, target_ulong pc) | static void breakpoint_invalidate(CPUState *cpu, target_ulong pc) | ||||||
| { | { | ||||||
| @@ -569,7 +568,6 @@ static void breakpoint_invalidate(CPUState *cpu, target_ulong pc) | |||||||
|     } |     } | ||||||
| } | } | ||||||
| #endif | #endif | ||||||
| #endif /* TARGET_HAS_ICE */ |  | ||||||
|  |  | ||||||
| #if defined(CONFIG_USER_ONLY) | #if defined(CONFIG_USER_ONLY) | ||||||
| void cpu_watchpoint_remove_all(CPUState *cpu, int mask) | void cpu_watchpoint_remove_all(CPUState *cpu, int mask) | ||||||
| @@ -689,7 +687,6 @@ static inline bool cpu_watchpoint_address_matches(CPUWatchpoint *wp, | |||||||
| int cpu_breakpoint_insert(CPUState *cpu, vaddr pc, int flags, | int cpu_breakpoint_insert(CPUState *cpu, vaddr pc, int flags, | ||||||
|                           CPUBreakpoint **breakpoint) |                           CPUBreakpoint **breakpoint) | ||||||
| { | { | ||||||
| #if defined(TARGET_HAS_ICE) |  | ||||||
|     CPUBreakpoint *bp; |     CPUBreakpoint *bp; | ||||||
|  |  | ||||||
|     bp = g_malloc(sizeof(*bp)); |     bp = g_malloc(sizeof(*bp)); | ||||||
| @@ -710,15 +707,11 @@ int cpu_breakpoint_insert(CPUState *cpu, vaddr pc, int flags, | |||||||
|         *breakpoint = bp; |         *breakpoint = bp; | ||||||
|     } |     } | ||||||
|     return 0; |     return 0; | ||||||
| #else |  | ||||||
|     return -ENOSYS; |  | ||||||
| #endif |  | ||||||
| } | } | ||||||
|  |  | ||||||
| /* Remove a specific breakpoint.  */ | /* Remove a specific breakpoint.  */ | ||||||
| int cpu_breakpoint_remove(CPUState *cpu, vaddr pc, int flags) | int cpu_breakpoint_remove(CPUState *cpu, vaddr pc, int flags) | ||||||
| { | { | ||||||
| #if defined(TARGET_HAS_ICE) |  | ||||||
|     CPUBreakpoint *bp; |     CPUBreakpoint *bp; | ||||||
|  |  | ||||||
|     QTAILQ_FOREACH(bp, &cpu->breakpoints, entry) { |     QTAILQ_FOREACH(bp, &cpu->breakpoints, entry) { | ||||||
| @@ -728,27 +721,21 @@ int cpu_breakpoint_remove(CPUState *cpu, vaddr pc, int flags) | |||||||
|         } |         } | ||||||
|     } |     } | ||||||
|     return -ENOENT; |     return -ENOENT; | ||||||
| #else |  | ||||||
|     return -ENOSYS; |  | ||||||
| #endif |  | ||||||
| } | } | ||||||
|  |  | ||||||
| /* Remove a specific breakpoint by reference.  */ | /* Remove a specific breakpoint by reference.  */ | ||||||
| void cpu_breakpoint_remove_by_ref(CPUState *cpu, CPUBreakpoint *breakpoint) | void cpu_breakpoint_remove_by_ref(CPUState *cpu, CPUBreakpoint *breakpoint) | ||||||
| { | { | ||||||
| #if defined(TARGET_HAS_ICE) |  | ||||||
|     QTAILQ_REMOVE(&cpu->breakpoints, breakpoint, entry); |     QTAILQ_REMOVE(&cpu->breakpoints, breakpoint, entry); | ||||||
|  |  | ||||||
|     breakpoint_invalidate(cpu, breakpoint->pc); |     breakpoint_invalidate(cpu, breakpoint->pc); | ||||||
|  |  | ||||||
|     g_free(breakpoint); |     g_free(breakpoint); | ||||||
| #endif |  | ||||||
| } | } | ||||||
|  |  | ||||||
| /* Remove all matching breakpoints. */ | /* Remove all matching breakpoints. */ | ||||||
| void cpu_breakpoint_remove_all(CPUState *cpu, int mask) | void cpu_breakpoint_remove_all(CPUState *cpu, int mask) | ||||||
| { | { | ||||||
| #if defined(TARGET_HAS_ICE) |  | ||||||
|     CPUBreakpoint *bp, *next; |     CPUBreakpoint *bp, *next; | ||||||
|  |  | ||||||
|     QTAILQ_FOREACH_SAFE(bp, &cpu->breakpoints, entry, next) { |     QTAILQ_FOREACH_SAFE(bp, &cpu->breakpoints, entry, next) { | ||||||
| @@ -756,14 +743,12 @@ void cpu_breakpoint_remove_all(CPUState *cpu, int mask) | |||||||
|             cpu_breakpoint_remove_by_ref(cpu, bp); |             cpu_breakpoint_remove_by_ref(cpu, bp); | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| #endif |  | ||||||
| } | } | ||||||
|  |  | ||||||
| /* enable or disable single step mode. EXCP_DEBUG is returned by the | /* enable or disable single step mode. EXCP_DEBUG is returned by the | ||||||
|    CPU loop after each instruction */ |    CPU loop after each instruction */ | ||||||
| void cpu_single_step(CPUState *cpu, int enabled) | void cpu_single_step(CPUState *cpu, int enabled) | ||||||
| { | { | ||||||
| #if defined(TARGET_HAS_ICE) |  | ||||||
|     if (cpu->singlestep_enabled != enabled) { |     if (cpu->singlestep_enabled != enabled) { | ||||||
|         cpu->singlestep_enabled = enabled; |         cpu->singlestep_enabled = enabled; | ||||||
|         if (kvm_enabled()) { |         if (kvm_enabled()) { | ||||||
| @@ -775,7 +760,6 @@ void cpu_single_step(CPUState *cpu, int enabled) | |||||||
|             tb_flush(env); |             tb_flush(env); | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| #endif |  | ||||||
| } | } | ||||||
|  |  | ||||||
| void cpu_abort(CPUState *cpu, const char *fmt, ...) | void cpu_abort(CPUState *cpu, const char *fmt, ...) | ||||||
|   | |||||||
| @@ -189,6 +189,56 @@ int qdev_init(DeviceState *dev) | |||||||
|     return 0; |     return 0; | ||||||
| } | } | ||||||
|  |  | ||||||
|  | static QTAILQ_HEAD(device_listeners, DeviceListener) device_listeners | ||||||
|  |     = QTAILQ_HEAD_INITIALIZER(device_listeners); | ||||||
|  |  | ||||||
|  | enum ListenerDirection { Forward, Reverse }; | ||||||
|  |  | ||||||
|  | #define DEVICE_LISTENER_CALL(_callback, _direction, _args...)     \ | ||||||
|  |     do {                                                          \ | ||||||
|  |         DeviceListener *_listener;                                \ | ||||||
|  |                                                                   \ | ||||||
|  |         switch (_direction) {                                     \ | ||||||
|  |         case Forward:                                             \ | ||||||
|  |             QTAILQ_FOREACH(_listener, &device_listeners, link) {  \ | ||||||
|  |                 if (_listener->_callback) {                       \ | ||||||
|  |                     _listener->_callback(_listener, ##_args);     \ | ||||||
|  |                 }                                                 \ | ||||||
|  |             }                                                     \ | ||||||
|  |             break;                                                \ | ||||||
|  |         case Reverse:                                             \ | ||||||
|  |             QTAILQ_FOREACH_REVERSE(_listener, &device_listeners,  \ | ||||||
|  |                                    device_listeners, link) {      \ | ||||||
|  |                 if (_listener->_callback) {                       \ | ||||||
|  |                     _listener->_callback(_listener, ##_args);     \ | ||||||
|  |                 }                                                 \ | ||||||
|  |             }                                                     \ | ||||||
|  |             break;                                                \ | ||||||
|  |         default:                                                  \ | ||||||
|  |             abort();                                              \ | ||||||
|  |         }                                                         \ | ||||||
|  |     } while (0) | ||||||
|  |  | ||||||
|  | static int device_listener_add(DeviceState *dev, void *opaque) | ||||||
|  | { | ||||||
|  |     DEVICE_LISTENER_CALL(realize, Forward, dev); | ||||||
|  |  | ||||||
|  |     return 0; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | void device_listener_register(DeviceListener *listener) | ||||||
|  | { | ||||||
|  |     QTAILQ_INSERT_TAIL(&device_listeners, listener, link); | ||||||
|  |  | ||||||
|  |     qbus_walk_children(sysbus_get_default(), NULL, NULL, device_listener_add, | ||||||
|  |                        NULL, NULL); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | void device_listener_unregister(DeviceListener *listener) | ||||||
|  | { | ||||||
|  |     QTAILQ_REMOVE(&device_listeners, listener, link); | ||||||
|  | } | ||||||
|  |  | ||||||
| static void device_realize(DeviceState *dev, Error **errp) | static void device_realize(DeviceState *dev, Error **errp) | ||||||
| { | { | ||||||
|     DeviceClass *dc = DEVICE_GET_CLASS(dev); |     DeviceClass *dc = DEVICE_GET_CLASS(dev); | ||||||
| @@ -994,6 +1044,8 @@ static void device_set_realized(Object *obj, bool value, Error **errp) | |||||||
|             goto fail; |             goto fail; | ||||||
|         } |         } | ||||||
|  |  | ||||||
|  |         DEVICE_LISTENER_CALL(realize, Forward, dev); | ||||||
|  |  | ||||||
|         hotplug_ctrl = qdev_get_hotplug_handler(dev); |         hotplug_ctrl = qdev_get_hotplug_handler(dev); | ||||||
|         if (hotplug_ctrl) { |         if (hotplug_ctrl) { | ||||||
|             hotplug_handler_plug(hotplug_ctrl, dev, &local_err); |             hotplug_handler_plug(hotplug_ctrl, dev, &local_err); | ||||||
| @@ -1035,6 +1087,7 @@ static void device_set_realized(Object *obj, bool value, Error **errp) | |||||||
|             dc->unrealize(dev, local_errp); |             dc->unrealize(dev, local_errp); | ||||||
|         } |         } | ||||||
|         dev->pending_deleted_event = true; |         dev->pending_deleted_event = true; | ||||||
|  |         DEVICE_LISTENER_CALL(unrealize, Reverse, dev); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     if (local_err != NULL) { |     if (local_err != NULL) { | ||||||
|   | |||||||
| @@ -41,7 +41,7 @@ static const uint8_t hid_usage_keys[0x100] = { | |||||||
|     0x07, 0x09, 0x0a, 0x0b, 0x0d, 0x0e, 0x0f, 0x33, |     0x07, 0x09, 0x0a, 0x0b, 0x0d, 0x0e, 0x0f, 0x33, | ||||||
|     0x34, 0x35, 0xe1, 0x31, 0x1d, 0x1b, 0x06, 0x19, |     0x34, 0x35, 0xe1, 0x31, 0x1d, 0x1b, 0x06, 0x19, | ||||||
|     0x05, 0x11, 0x10, 0x36, 0x37, 0x38, 0xe5, 0x55, |     0x05, 0x11, 0x10, 0x36, 0x37, 0x38, 0xe5, 0x55, | ||||||
|     0xe2, 0x2c, 0x32, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, |     0xe2, 0x2c, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, | ||||||
|     0x3f, 0x40, 0x41, 0x42, 0x43, 0x53, 0x47, 0x5f, |     0x3f, 0x40, 0x41, 0x42, 0x43, 0x53, 0x47, 0x5f, | ||||||
|     0x60, 0x61, 0x56, 0x5c, 0x5d, 0x5e, 0x57, 0x59, |     0x60, 0x61, 0x56, 0x5c, 0x5d, 0x5e, 0x57, 0x59, | ||||||
|     0x5a, 0x5b, 0x62, 0x63, 0x00, 0x00, 0x00, 0x44, |     0x5a, 0x5b, 0x62, 0x63, 0x00, 0x00, 0x00, 0x44, | ||||||
| @@ -514,6 +514,27 @@ static int hid_post_load(void *opaque, int version_id) | |||||||
|     HIDState *s = opaque; |     HIDState *s = opaque; | ||||||
|  |  | ||||||
|     hid_set_next_idle(s); |     hid_set_next_idle(s); | ||||||
|  |  | ||||||
|  |     if (s->n == QUEUE_LENGTH && (s->kind == HID_TABLET || | ||||||
|  |                                  s->kind == HID_MOUSE)) { | ||||||
|  |         /* | ||||||
|  |          * Handle ptr device migration from old qemu with full queue. | ||||||
|  |          * | ||||||
|  |          * Throw away everything but the last event, so we propagate | ||||||
|  |          * at least the current button state to the guest.  Also keep | ||||||
|  |          * current position for the tablet, signal "no motion" for the | ||||||
|  |          * mouse. | ||||||
|  |          */ | ||||||
|  |         HIDPointerEvent evt; | ||||||
|  |         evt = s->ptr.queue[(s->head+s->n) & QUEUE_MASK]; | ||||||
|  |         if (s->kind == HID_MOUSE) { | ||||||
|  |             evt.xdx = 0; | ||||||
|  |             evt.ydy = 0; | ||||||
|  |         } | ||||||
|  |         s->ptr.queue[0] = evt; | ||||||
|  |         s->head = 0; | ||||||
|  |         s->n = 1; | ||||||
|  |     } | ||||||
|     return 0; |     return 0; | ||||||
| } | } | ||||||
|  |  | ||||||
|   | |||||||
| @@ -115,43 +115,9 @@ static inline void tswap64s(uint64_t *s) | |||||||
| #define bswaptls(s) bswap64s(s) | #define bswaptls(s) bswap64s(s) | ||||||
| #endif | #endif | ||||||
|  |  | ||||||
| /* CPU memory access without any memory or io remapping */ | /* Target-endianness CPU memory access functions. These fit into the | ||||||
|  |  * {ld,st}{type}{sign}{size}{endian}_p naming scheme described in bswap.h. | ||||||
| /* |  | ||||||
|  * the generic syntax for the memory accesses is: |  | ||||||
|  * |  | ||||||
|  * load: ld{type}{sign}{size}{endian}_{access_type}(ptr) |  | ||||||
|  * |  | ||||||
|  * store: st{type}{size}{endian}_{access_type}(ptr, val) |  | ||||||
|  * |  | ||||||
|  * type is: |  | ||||||
|  * (empty): integer access |  | ||||||
|  *   f    : float access |  | ||||||
|  * |  | ||||||
|  * sign is: |  | ||||||
|  * (empty): for floats or 32 bit size |  | ||||||
|  *   u    : unsigned |  | ||||||
|  *   s    : signed |  | ||||||
|  * |  | ||||||
|  * size is: |  | ||||||
|  *   b: 8 bits |  | ||||||
|  *   w: 16 bits |  | ||||||
|  *   l: 32 bits |  | ||||||
|  *   q: 64 bits |  | ||||||
|  * |  | ||||||
|  * endian is: |  | ||||||
|  * (empty): target cpu endianness or 8 bit access |  | ||||||
|  *   r    : reversed target cpu endianness (not implemented yet) |  | ||||||
|  *   be   : big endian (not implemented yet) |  | ||||||
|  *   le   : little endian (not implemented yet) |  | ||||||
|  * |  | ||||||
|  * access_type is: |  | ||||||
|  *   raw    : host memory access |  | ||||||
|  *   user   : user mode access using soft MMU |  | ||||||
|  *   kernel : kernel mode access using soft MMU |  | ||||||
|  */ |  */ | ||||||
|  |  | ||||||
| /* target-endianness CPU memory access functions */ |  | ||||||
| #if defined(TARGET_WORDS_BIGENDIAN) | #if defined(TARGET_WORDS_BIGENDIAN) | ||||||
| #define lduw_p(p) lduw_be_p(p) | #define lduw_p(p) lduw_be_p(p) | ||||||
| #define ldsw_p(p) ldsw_be_p(p) | #define ldsw_p(p) ldsw_be_p(p) | ||||||
|   | |||||||
| @@ -23,7 +23,26 @@ | |||||||
|  * |  * | ||||||
|  * Used by target op helpers. |  * Used by target op helpers. | ||||||
|  * |  * | ||||||
|  * MMU mode suffixes are defined in target cpu.h. |  * The syntax for the accessors is: | ||||||
|  |  * | ||||||
|  |  * load: cpu_ld{sign}{size}_{mmusuffix}(env, ptr) | ||||||
|  |  * | ||||||
|  |  * store: cpu_st{sign}{size}_{mmusuffix}(env, ptr, val) | ||||||
|  |  * | ||||||
|  |  * sign is: | ||||||
|  |  * (empty): for 32 and 64 bit sizes | ||||||
|  |  *   u    : unsigned | ||||||
|  |  *   s    : signed | ||||||
|  |  * | ||||||
|  |  * size is: | ||||||
|  |  *   b: 8 bits | ||||||
|  |  *   w: 16 bits | ||||||
|  |  *   l: 32 bits | ||||||
|  |  *   q: 64 bits | ||||||
|  |  * | ||||||
|  |  * mmusuffix is one of the generic suffixes "data" or "code", or | ||||||
|  |  * (for softmmu configs)  a target-specific MMU mode suffix as defined | ||||||
|  |  * in target cpu.h. | ||||||
|  */ |  */ | ||||||
| #ifndef CPU_LDST_H | #ifndef CPU_LDST_H | ||||||
| #define CPU_LDST_H | #define CPU_LDST_H | ||||||
| @@ -53,113 +72,44 @@ | |||||||
|     h2g_nocheck(x); \ |     h2g_nocheck(x); \ | ||||||
| }) | }) | ||||||
|  |  | ||||||
| #define saddr(x) g2h(x) |  | ||||||
| #define laddr(x) g2h(x) |  | ||||||
|  |  | ||||||
| #else /* !CONFIG_USER_ONLY */ |  | ||||||
| /* NOTE: we use double casts if pointers and target_ulong have |  | ||||||
|    different sizes */ |  | ||||||
| #define saddr(x) (uint8_t *)(intptr_t)(x) |  | ||||||
| #define laddr(x) (uint8_t *)(intptr_t)(x) |  | ||||||
| #endif | #endif | ||||||
|  |  | ||||||
| #define ldub_raw(p) ldub_p(laddr((p))) |  | ||||||
| #define ldsb_raw(p) ldsb_p(laddr((p))) |  | ||||||
| #define lduw_raw(p) lduw_p(laddr((p))) |  | ||||||
| #define ldsw_raw(p) ldsw_p(laddr((p))) |  | ||||||
| #define ldl_raw(p) ldl_p(laddr((p))) |  | ||||||
| #define ldq_raw(p) ldq_p(laddr((p))) |  | ||||||
| #define ldfl_raw(p) ldfl_p(laddr((p))) |  | ||||||
| #define ldfq_raw(p) ldfq_p(laddr((p))) |  | ||||||
| #define stb_raw(p, v) stb_p(saddr((p)), v) |  | ||||||
| #define stw_raw(p, v) stw_p(saddr((p)), v) |  | ||||||
| #define stl_raw(p, v) stl_p(saddr((p)), v) |  | ||||||
| #define stq_raw(p, v) stq_p(saddr((p)), v) |  | ||||||
| #define stfl_raw(p, v) stfl_p(saddr((p)), v) |  | ||||||
| #define stfq_raw(p, v) stfq_p(saddr((p)), v) |  | ||||||
|  |  | ||||||
|  |  | ||||||
| #if defined(CONFIG_USER_ONLY) | #if defined(CONFIG_USER_ONLY) | ||||||
|  |  | ||||||
| /* if user mode, no other memory access functions */ | /* In user-only mode we provide only the _code and _data accessors. */ | ||||||
| #define ldub(p) ldub_raw(p) |  | ||||||
| #define ldsb(p) ldsb_raw(p) |  | ||||||
| #define lduw(p) lduw_raw(p) |  | ||||||
| #define ldsw(p) ldsw_raw(p) |  | ||||||
| #define ldl(p) ldl_raw(p) |  | ||||||
| #define ldq(p) ldq_raw(p) |  | ||||||
| #define ldfl(p) ldfl_raw(p) |  | ||||||
| #define ldfq(p) ldfq_raw(p) |  | ||||||
| #define stb(p, v) stb_raw(p, v) |  | ||||||
| #define stw(p, v) stw_raw(p, v) |  | ||||||
| #define stl(p, v) stl_raw(p, v) |  | ||||||
| #define stq(p, v) stq_raw(p, v) |  | ||||||
| #define stfl(p, v) stfl_raw(p, v) |  | ||||||
| #define stfq(p, v) stfq_raw(p, v) |  | ||||||
|  |  | ||||||
| #define cpu_ldub_code(env1, p) ldub_raw(p) | #define MEMSUFFIX _data | ||||||
| #define cpu_ldsb_code(env1, p) ldsb_raw(p) | #define DATA_SIZE 1 | ||||||
| #define cpu_lduw_code(env1, p) lduw_raw(p) | #include "exec/cpu_ldst_useronly_template.h" | ||||||
| #define cpu_ldsw_code(env1, p) ldsw_raw(p) |  | ||||||
| #define cpu_ldl_code(env1, p) ldl_raw(p) |  | ||||||
| #define cpu_ldq_code(env1, p) ldq_raw(p) |  | ||||||
|  |  | ||||||
| #define cpu_ldub_data(env, addr) ldub_raw(addr) | #define DATA_SIZE 2 | ||||||
| #define cpu_lduw_data(env, addr) lduw_raw(addr) | #include "exec/cpu_ldst_useronly_template.h" | ||||||
| #define cpu_ldsw_data(env, addr) ldsw_raw(addr) |  | ||||||
| #define cpu_ldl_data(env, addr) ldl_raw(addr) |  | ||||||
| #define cpu_ldq_data(env, addr) ldq_raw(addr) |  | ||||||
|  |  | ||||||
| #define cpu_stb_data(env, addr, data) stb_raw(addr, data) | #define DATA_SIZE 4 | ||||||
| #define cpu_stw_data(env, addr, data) stw_raw(addr, data) | #include "exec/cpu_ldst_useronly_template.h" | ||||||
| #define cpu_stl_data(env, addr, data) stl_raw(addr, data) |  | ||||||
| #define cpu_stq_data(env, addr, data) stq_raw(addr, data) |  | ||||||
|  |  | ||||||
| #define cpu_ldub_kernel(env, addr) ldub_raw(addr) | #define DATA_SIZE 8 | ||||||
| #define cpu_lduw_kernel(env, addr) lduw_raw(addr) | #include "exec/cpu_ldst_useronly_template.h" | ||||||
| #define cpu_ldsw_kernel(env, addr) ldsw_raw(addr) | #undef MEMSUFFIX | ||||||
| #define cpu_ldl_kernel(env, addr) ldl_raw(addr) |  | ||||||
| #define cpu_ldq_kernel(env, addr) ldq_raw(addr) |  | ||||||
|  |  | ||||||
| #define cpu_stb_kernel(env, addr, data) stb_raw(addr, data) | #define MEMSUFFIX _code | ||||||
| #define cpu_stw_kernel(env, addr, data) stw_raw(addr, data) | #define CODE_ACCESS | ||||||
| #define cpu_stl_kernel(env, addr, data) stl_raw(addr, data) | #define DATA_SIZE 1 | ||||||
| #define cpu_stq_kernel(env, addr, data) stq_raw(addr, data) | #include "exec/cpu_ldst_useronly_template.h" | ||||||
|  |  | ||||||
| #define ldub_kernel(p) ldub_raw(p) | #define DATA_SIZE 2 | ||||||
| #define ldsb_kernel(p) ldsb_raw(p) | #include "exec/cpu_ldst_useronly_template.h" | ||||||
| #define lduw_kernel(p) lduw_raw(p) |  | ||||||
| #define ldsw_kernel(p) ldsw_raw(p) |  | ||||||
| #define ldl_kernel(p) ldl_raw(p) |  | ||||||
| #define ldq_kernel(p) ldq_raw(p) |  | ||||||
| #define ldfl_kernel(p) ldfl_raw(p) |  | ||||||
| #define ldfq_kernel(p) ldfq_raw(p) |  | ||||||
| #define stb_kernel(p, v) stb_raw(p, v) |  | ||||||
| #define stw_kernel(p, v) stw_raw(p, v) |  | ||||||
| #define stl_kernel(p, v) stl_raw(p, v) |  | ||||||
| #define stq_kernel(p, v) stq_raw(p, v) |  | ||||||
| #define stfl_kernel(p, v) stfl_raw(p, v) |  | ||||||
| #define stfq_kernel(p, vt) stfq_raw(p, v) |  | ||||||
|  |  | ||||||
| #define cpu_ldub_data(env, addr) ldub_raw(addr) | #define DATA_SIZE 4 | ||||||
| #define cpu_lduw_data(env, addr) lduw_raw(addr) | #include "exec/cpu_ldst_useronly_template.h" | ||||||
| #define cpu_ldl_data(env, addr) ldl_raw(addr) |  | ||||||
|  |  | ||||||
| #define cpu_stb_data(env, addr, data) stb_raw(addr, data) | #define DATA_SIZE 8 | ||||||
| #define cpu_stw_data(env, addr, data) stw_raw(addr, data) | #include "exec/cpu_ldst_useronly_template.h" | ||||||
| #define cpu_stl_data(env, addr, data) stl_raw(addr, data) | #undef MEMSUFFIX | ||||||
|  | #undef CODE_ACCESS | ||||||
|  |  | ||||||
| #else | #else | ||||||
|  |  | ||||||
| /* XXX: find something cleaner. |  | ||||||
|  * Furthermore, this is false for 64 bits targets |  | ||||||
|  */ |  | ||||||
| #define ldul_user       ldl_user |  | ||||||
| #define ldul_kernel     ldl_kernel |  | ||||||
| #define ldul_hypv       ldl_hypv |  | ||||||
| #define ldul_executive  ldl_executive |  | ||||||
| #define ldul_supervisor ldl_supervisor |  | ||||||
|  |  | ||||||
| /* The memory helpers for tcg-generated code need tcg_target_long etc.  */ | /* The memory helpers for tcg-generated code need tcg_target_long etc.  */ | ||||||
| #include "tcg.h" | #include "tcg.h" | ||||||
|  |  | ||||||
| @@ -182,6 +132,7 @@ uint16_t helper_ldw_cmmu(CPUArchState *env, target_ulong addr, int mmu_idx); | |||||||
| uint32_t helper_ldl_cmmu(CPUArchState *env, target_ulong addr, int mmu_idx); | uint32_t helper_ldl_cmmu(CPUArchState *env, target_ulong addr, int mmu_idx); | ||||||
| uint64_t helper_ldq_cmmu(CPUArchState *env, target_ulong addr, int mmu_idx); | uint64_t helper_ldq_cmmu(CPUArchState *env, target_ulong addr, int mmu_idx); | ||||||
|  |  | ||||||
|  | #ifdef MMU_MODE0_SUFFIX | ||||||
| #define CPU_MMU_INDEX 0 | #define CPU_MMU_INDEX 0 | ||||||
| #define MEMSUFFIX MMU_MODE0_SUFFIX | #define MEMSUFFIX MMU_MODE0_SUFFIX | ||||||
| #define DATA_SIZE 1 | #define DATA_SIZE 1 | ||||||
| @@ -197,7 +148,9 @@ uint64_t helper_ldq_cmmu(CPUArchState *env, target_ulong addr, int mmu_idx); | |||||||
| #include "exec/cpu_ldst_template.h" | #include "exec/cpu_ldst_template.h" | ||||||
| #undef CPU_MMU_INDEX | #undef CPU_MMU_INDEX | ||||||
| #undef MEMSUFFIX | #undef MEMSUFFIX | ||||||
|  | #endif | ||||||
|  |  | ||||||
|  | #if (NB_MMU_MODES >= 2) && defined(MMU_MODE1_SUFFIX) | ||||||
| #define CPU_MMU_INDEX 1 | #define CPU_MMU_INDEX 1 | ||||||
| #define MEMSUFFIX MMU_MODE1_SUFFIX | #define MEMSUFFIX MMU_MODE1_SUFFIX | ||||||
| #define DATA_SIZE 1 | #define DATA_SIZE 1 | ||||||
| @@ -213,8 +166,9 @@ uint64_t helper_ldq_cmmu(CPUArchState *env, target_ulong addr, int mmu_idx); | |||||||
| #include "exec/cpu_ldst_template.h" | #include "exec/cpu_ldst_template.h" | ||||||
| #undef CPU_MMU_INDEX | #undef CPU_MMU_INDEX | ||||||
| #undef MEMSUFFIX | #undef MEMSUFFIX | ||||||
|  | #endif | ||||||
|  |  | ||||||
| #if (NB_MMU_MODES >= 3) | #if (NB_MMU_MODES >= 3) && defined(MMU_MODE2_SUFFIX) | ||||||
|  |  | ||||||
| #define CPU_MMU_INDEX 2 | #define CPU_MMU_INDEX 2 | ||||||
| #define MEMSUFFIX MMU_MODE2_SUFFIX | #define MEMSUFFIX MMU_MODE2_SUFFIX | ||||||
| @@ -233,7 +187,7 @@ uint64_t helper_ldq_cmmu(CPUArchState *env, target_ulong addr, int mmu_idx); | |||||||
| #undef MEMSUFFIX | #undef MEMSUFFIX | ||||||
| #endif /* (NB_MMU_MODES >= 3) */ | #endif /* (NB_MMU_MODES >= 3) */ | ||||||
|  |  | ||||||
| #if (NB_MMU_MODES >= 4) | #if (NB_MMU_MODES >= 4) && defined(MMU_MODE3_SUFFIX) | ||||||
|  |  | ||||||
| #define CPU_MMU_INDEX 3 | #define CPU_MMU_INDEX 3 | ||||||
| #define MEMSUFFIX MMU_MODE3_SUFFIX | #define MEMSUFFIX MMU_MODE3_SUFFIX | ||||||
| @@ -252,7 +206,7 @@ uint64_t helper_ldq_cmmu(CPUArchState *env, target_ulong addr, int mmu_idx); | |||||||
| #undef MEMSUFFIX | #undef MEMSUFFIX | ||||||
| #endif /* (NB_MMU_MODES >= 4) */ | #endif /* (NB_MMU_MODES >= 4) */ | ||||||
|  |  | ||||||
| #if (NB_MMU_MODES >= 5) | #if (NB_MMU_MODES >= 5) && defined(MMU_MODE4_SUFFIX) | ||||||
|  |  | ||||||
| #define CPU_MMU_INDEX 4 | #define CPU_MMU_INDEX 4 | ||||||
| #define MEMSUFFIX MMU_MODE4_SUFFIX | #define MEMSUFFIX MMU_MODE4_SUFFIX | ||||||
| @@ -271,7 +225,7 @@ uint64_t helper_ldq_cmmu(CPUArchState *env, target_ulong addr, int mmu_idx); | |||||||
| #undef MEMSUFFIX | #undef MEMSUFFIX | ||||||
| #endif /* (NB_MMU_MODES >= 5) */ | #endif /* (NB_MMU_MODES >= 5) */ | ||||||
|  |  | ||||||
| #if (NB_MMU_MODES >= 6) | #if (NB_MMU_MODES >= 6) && defined(MMU_MODE5_SUFFIX) | ||||||
|  |  | ||||||
| #define CPU_MMU_INDEX 5 | #define CPU_MMU_INDEX 5 | ||||||
| #define MEMSUFFIX MMU_MODE5_SUFFIX | #define MEMSUFFIX MMU_MODE5_SUFFIX | ||||||
| @@ -311,18 +265,6 @@ uint64_t helper_ldq_cmmu(CPUArchState *env, target_ulong addr, int mmu_idx); | |||||||
| #undef CPU_MMU_INDEX | #undef CPU_MMU_INDEX | ||||||
| #undef MEMSUFFIX | #undef MEMSUFFIX | ||||||
|  |  | ||||||
| #define ldub(p) ldub_data(p) |  | ||||||
| #define ldsb(p) ldsb_data(p) |  | ||||||
| #define lduw(p) lduw_data(p) |  | ||||||
| #define ldsw(p) ldsw_data(p) |  | ||||||
| #define ldl(p) ldl_data(p) |  | ||||||
| #define ldq(p) ldq_data(p) |  | ||||||
|  |  | ||||||
| #define stb(p, v) stb_data(p, v) |  | ||||||
| #define stw(p, v) stw_data(p, v) |  | ||||||
| #define stl(p, v) stl_data(p, v) |  | ||||||
| #define stq(p, v) stq_data(p, v) |  | ||||||
|  |  | ||||||
| #define CPU_MMU_INDEX (cpu_mmu_index(env)) | #define CPU_MMU_INDEX (cpu_mmu_index(env)) | ||||||
| #define MEMSUFFIX _code | #define MEMSUFFIX _code | ||||||
| #define SOFTMMU_CODE_ACCESS | #define SOFTMMU_CODE_ACCESS | ||||||
|   | |||||||
| @@ -4,9 +4,7 @@ | |||||||
|  * Generate inline load/store functions for one MMU mode and data |  * Generate inline load/store functions for one MMU mode and data | ||||||
|  * size. |  * size. | ||||||
|  * |  * | ||||||
|  * Generate a store function as well as signed and unsigned loads. For |  * Generate a store function as well as signed and unsigned loads. | ||||||
|  * 32 and 64 bit cases, also generate floating point functions with |  | ||||||
|  * the same size. |  | ||||||
|  * |  * | ||||||
|  * Not used directly but included from cpu_ldst.h. |  * Not used directly but included from cpu_ldst.h. | ||||||
|  * |  * | ||||||
| @@ -79,7 +77,7 @@ glue(glue(cpu_ld, USUFFIX), MEMSUFFIX)(CPUArchState *env, target_ulong ptr) | |||||||
|         res = glue(glue(helper_ld, SUFFIX), MMUSUFFIX)(env, addr, mmu_idx); |         res = glue(glue(helper_ld, SUFFIX), MMUSUFFIX)(env, addr, mmu_idx); | ||||||
|     } else { |     } else { | ||||||
|         uintptr_t hostaddr = addr + env->tlb_table[mmu_idx][page_index].addend; |         uintptr_t hostaddr = addr + env->tlb_table[mmu_idx][page_index].addend; | ||||||
|         res = glue(glue(ld, USUFFIX), _raw)(hostaddr); |         res = glue(glue(ld, USUFFIX), _p)((uint8_t *)hostaddr); | ||||||
|     } |     } | ||||||
|     return res; |     return res; | ||||||
| } | } | ||||||
| @@ -101,7 +99,7 @@ glue(glue(cpu_lds, SUFFIX), MEMSUFFIX)(CPUArchState *env, target_ulong ptr) | |||||||
|                                MMUSUFFIX)(env, addr, mmu_idx); |                                MMUSUFFIX)(env, addr, mmu_idx); | ||||||
|     } else { |     } else { | ||||||
|         uintptr_t hostaddr = addr + env->tlb_table[mmu_idx][page_index].addend; |         uintptr_t hostaddr = addr + env->tlb_table[mmu_idx][page_index].addend; | ||||||
|         res = glue(glue(lds, SUFFIX), _raw)(hostaddr); |         res = glue(glue(lds, SUFFIX), _p)((uint8_t *)hostaddr); | ||||||
|     } |     } | ||||||
|     return res; |     return res; | ||||||
| } | } | ||||||
| @@ -127,60 +125,10 @@ glue(glue(cpu_st, SUFFIX), MEMSUFFIX)(CPUArchState *env, target_ulong ptr, | |||||||
|         glue(glue(helper_st, SUFFIX), MMUSUFFIX)(env, addr, v, mmu_idx); |         glue(glue(helper_st, SUFFIX), MMUSUFFIX)(env, addr, v, mmu_idx); | ||||||
|     } else { |     } else { | ||||||
|         uintptr_t hostaddr = addr + env->tlb_table[mmu_idx][page_index].addend; |         uintptr_t hostaddr = addr + env->tlb_table[mmu_idx][page_index].addend; | ||||||
|         glue(glue(st, SUFFIX), _raw)(hostaddr, v); |         glue(glue(st, SUFFIX), _p)((uint8_t *)hostaddr, v); | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
| #if DATA_SIZE == 8 |  | ||||||
| static inline float64 glue(cpu_ldfq, MEMSUFFIX)(CPUArchState *env, |  | ||||||
|                                                 target_ulong ptr) |  | ||||||
| { |  | ||||||
|     union { |  | ||||||
|         float64 d; |  | ||||||
|         uint64_t i; |  | ||||||
|     } u; |  | ||||||
|     u.i = glue(cpu_ldq, MEMSUFFIX)(env, ptr); |  | ||||||
|     return u.d; |  | ||||||
| } |  | ||||||
|  |  | ||||||
| static inline void glue(cpu_stfq, MEMSUFFIX)(CPUArchState *env, |  | ||||||
|                                              target_ulong ptr, float64 v) |  | ||||||
| { |  | ||||||
|     union { |  | ||||||
|         float64 d; |  | ||||||
|         uint64_t i; |  | ||||||
|     } u; |  | ||||||
|     u.d = v; |  | ||||||
|     glue(cpu_stq, MEMSUFFIX)(env, ptr, u.i); |  | ||||||
| } |  | ||||||
| #endif /* DATA_SIZE == 8 */ |  | ||||||
|  |  | ||||||
| #if DATA_SIZE == 4 |  | ||||||
| static inline float32 glue(cpu_ldfl, MEMSUFFIX)(CPUArchState *env, |  | ||||||
|                                                 target_ulong ptr) |  | ||||||
| { |  | ||||||
|     union { |  | ||||||
|         float32 f; |  | ||||||
|         uint32_t i; |  | ||||||
|     } u; |  | ||||||
|     u.i = glue(cpu_ldl, MEMSUFFIX)(env, ptr); |  | ||||||
|     return u.f; |  | ||||||
| } |  | ||||||
|  |  | ||||||
| static inline void glue(cpu_stfl, MEMSUFFIX)(CPUArchState *env, |  | ||||||
|                                              target_ulong ptr, float32 v) |  | ||||||
| { |  | ||||||
|     union { |  | ||||||
|         float32 f; |  | ||||||
|         uint32_t i; |  | ||||||
|     } u; |  | ||||||
|     u.f = v; |  | ||||||
|     glue(cpu_stl, MEMSUFFIX)(env, ptr, u.i); |  | ||||||
| } |  | ||||||
| #endif /* DATA_SIZE == 4 */ |  | ||||||
|  |  | ||||||
| #endif /* !SOFTMMU_CODE_ACCESS */ | #endif /* !SOFTMMU_CODE_ACCESS */ | ||||||
|  |  | ||||||
| #undef RES_TYPE | #undef RES_TYPE | ||||||
|   | |||||||
							
								
								
									
										81
									
								
								include/exec/cpu_ldst_useronly_template.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										81
									
								
								include/exec/cpu_ldst_useronly_template.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,81 @@ | |||||||
|  | /* | ||||||
|  |  *  User-only accessor function support | ||||||
|  |  * | ||||||
|  |  * Generate inline load/store functions for one data size. | ||||||
|  |  * | ||||||
|  |  * Generate a store function as well as signed and unsigned loads. | ||||||
|  |  * | ||||||
|  |  * Not used directly but included from cpu_ldst.h. | ||||||
|  |  * | ||||||
|  |  *  Copyright (c) 2015 Linaro Limited | ||||||
|  |  * | ||||||
|  |  * This library is free software; you can redistribute it and/or | ||||||
|  |  * modify it under the terms of the GNU Lesser General Public | ||||||
|  |  * License as published by the Free Software Foundation; either | ||||||
|  |  * version 2 of the License, or (at your option) any later version. | ||||||
|  |  * | ||||||
|  |  * This library 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 | ||||||
|  |  * Lesser General Public License for more details. | ||||||
|  |  * | ||||||
|  |  * You should have received a copy of the GNU Lesser General Public | ||||||
|  |  * License along with this library; if not, see <http://www.gnu.org/licenses/>. | ||||||
|  |  */ | ||||||
|  | #if DATA_SIZE == 8 | ||||||
|  | #define SUFFIX q | ||||||
|  | #define USUFFIX q | ||||||
|  | #define DATA_TYPE uint64_t | ||||||
|  | #elif DATA_SIZE == 4 | ||||||
|  | #define SUFFIX l | ||||||
|  | #define USUFFIX l | ||||||
|  | #define DATA_TYPE uint32_t | ||||||
|  | #elif DATA_SIZE == 2 | ||||||
|  | #define SUFFIX w | ||||||
|  | #define USUFFIX uw | ||||||
|  | #define DATA_TYPE uint16_t | ||||||
|  | #define DATA_STYPE int16_t | ||||||
|  | #elif DATA_SIZE == 1 | ||||||
|  | #define SUFFIX b | ||||||
|  | #define USUFFIX ub | ||||||
|  | #define DATA_TYPE uint8_t | ||||||
|  | #define DATA_STYPE int8_t | ||||||
|  | #else | ||||||
|  | #error unsupported data size | ||||||
|  | #endif | ||||||
|  |  | ||||||
|  | #if DATA_SIZE == 8 | ||||||
|  | #define RES_TYPE uint64_t | ||||||
|  | #else | ||||||
|  | #define RES_TYPE uint32_t | ||||||
|  | #endif | ||||||
|  |  | ||||||
|  | static inline RES_TYPE | ||||||
|  | glue(glue(cpu_ld, USUFFIX), MEMSUFFIX)(CPUArchState *env, target_ulong ptr) | ||||||
|  | { | ||||||
|  |     return glue(glue(ld, USUFFIX), _p)(g2h(ptr)); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | #if DATA_SIZE <= 2 | ||||||
|  | static inline int | ||||||
|  | glue(glue(cpu_lds, SUFFIX), MEMSUFFIX)(CPUArchState *env, target_ulong ptr) | ||||||
|  | { | ||||||
|  |     return glue(glue(lds, SUFFIX), _p)(g2h(ptr)); | ||||||
|  | } | ||||||
|  | #endif | ||||||
|  |  | ||||||
|  | #ifndef CODE_ACCESS | ||||||
|  | static inline void | ||||||
|  | glue(glue(cpu_st, SUFFIX), MEMSUFFIX)(CPUArchState *env, target_ulong ptr, | ||||||
|  |                                       RES_TYPE v) | ||||||
|  | { | ||||||
|  |     glue(glue(st, SUFFIX), _p)(g2h(ptr), v); | ||||||
|  | } | ||||||
|  | #endif | ||||||
|  |  | ||||||
|  | #undef RES_TYPE | ||||||
|  | #undef DATA_TYPE | ||||||
|  | #undef DATA_STYPE | ||||||
|  | #undef SUFFIX | ||||||
|  | #undef USUFFIX | ||||||
|  | #undef DATA_SIZE | ||||||
| @@ -165,6 +165,12 @@ struct DeviceState { | |||||||
|     int alias_required_for_version; |     int alias_required_for_version; | ||||||
| }; | }; | ||||||
|  |  | ||||||
|  | struct DeviceListener { | ||||||
|  |     void (*realize)(DeviceListener *listener, DeviceState *dev); | ||||||
|  |     void (*unrealize)(DeviceListener *listener, DeviceState *dev); | ||||||
|  |     QTAILQ_ENTRY(DeviceListener) link; | ||||||
|  | }; | ||||||
|  |  | ||||||
| #define TYPE_BUS "bus" | #define TYPE_BUS "bus" | ||||||
| #define BUS(obj) OBJECT_CHECK(BusState, (obj), TYPE_BUS) | #define BUS(obj) OBJECT_CHECK(BusState, (obj), TYPE_BUS) | ||||||
| #define BUS_CLASS(klass) OBJECT_CLASS_CHECK(BusClass, (klass), TYPE_BUS) | #define BUS_CLASS(klass) OBJECT_CLASS_CHECK(BusClass, (klass), TYPE_BUS) | ||||||
| @@ -376,4 +382,8 @@ static inline bool qbus_is_hotpluggable(BusState *bus) | |||||||
| { | { | ||||||
|    return bus->hotplug_handler; |    return bus->hotplug_handler; | ||||||
| } | } | ||||||
|  |  | ||||||
|  | void device_listener_register(DeviceListener *listener); | ||||||
|  | void device_listener_unregister(DeviceListener *listener); | ||||||
|  |  | ||||||
| #endif | #endif | ||||||
|   | |||||||
| @@ -16,7 +16,9 @@ | |||||||
|  |  | ||||||
| #include "hw/hw.h" | #include "hw/hw.h" | ||||||
| #include "hw/xen/xen.h" | #include "hw/xen/xen.h" | ||||||
|  | #include "hw/pci/pci.h" | ||||||
| #include "qemu/queue.h" | #include "qemu/queue.h" | ||||||
|  | #include "trace.h" | ||||||
|  |  | ||||||
| /* | /* | ||||||
|  * We don't support Xen prior to 3.3.0. |  * We don't support Xen prior to 3.3.0. | ||||||
| @@ -179,4 +181,225 @@ static inline int xen_get_vmport_regs_pfn(XenXC xc, domid_t dom, | |||||||
| } | } | ||||||
| #endif | #endif | ||||||
|  |  | ||||||
|  | /* Xen before 4.5 */ | ||||||
|  | #if CONFIG_XEN_CTRL_INTERFACE_VERSION < 450 | ||||||
|  |  | ||||||
|  | #ifndef HVM_PARAM_BUFIOREQ_EVTCHN | ||||||
|  | #define HVM_PARAM_BUFIOREQ_EVTCHN 26 | ||||||
|  | #endif | ||||||
|  |  | ||||||
|  | #define IOREQ_TYPE_PCI_CONFIG 2 | ||||||
|  |  | ||||||
|  | typedef uint32_t ioservid_t; | ||||||
|  |  | ||||||
|  | static inline void xen_map_memory_section(XenXC xc, domid_t dom, | ||||||
|  |                                           ioservid_t ioservid, | ||||||
|  |                                           MemoryRegionSection *section) | ||||||
|  | { | ||||||
|  | } | ||||||
|  |  | ||||||
|  | static inline void xen_unmap_memory_section(XenXC xc, domid_t dom, | ||||||
|  |                                             ioservid_t ioservid, | ||||||
|  |                                             MemoryRegionSection *section) | ||||||
|  | { | ||||||
|  | } | ||||||
|  |  | ||||||
|  | static inline void xen_map_io_section(XenXC xc, domid_t dom, | ||||||
|  |                                       ioservid_t ioservid, | ||||||
|  |                                       MemoryRegionSection *section) | ||||||
|  | { | ||||||
|  | } | ||||||
|  |  | ||||||
|  | static inline void xen_unmap_io_section(XenXC xc, domid_t dom, | ||||||
|  |                                         ioservid_t ioservid, | ||||||
|  |                                         MemoryRegionSection *section) | ||||||
|  | { | ||||||
|  | } | ||||||
|  |  | ||||||
|  | static inline void xen_map_pcidev(XenXC xc, domid_t dom, | ||||||
|  |                                   ioservid_t ioservid, | ||||||
|  |                                   PCIDevice *pci_dev) | ||||||
|  | { | ||||||
|  | } | ||||||
|  |  | ||||||
|  | static inline void xen_unmap_pcidev(XenXC xc, domid_t dom, | ||||||
|  |                                     ioservid_t ioservid, | ||||||
|  |                                     PCIDevice *pci_dev) | ||||||
|  | { | ||||||
|  | } | ||||||
|  |  | ||||||
|  | static inline int xen_create_ioreq_server(XenXC xc, domid_t dom, | ||||||
|  |                                           ioservid_t *ioservid) | ||||||
|  | { | ||||||
|  |     return 0; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | static inline void xen_destroy_ioreq_server(XenXC xc, domid_t dom, | ||||||
|  |                                             ioservid_t ioservid) | ||||||
|  | { | ||||||
|  | } | ||||||
|  |  | ||||||
|  | static inline int xen_get_ioreq_server_info(XenXC xc, domid_t dom, | ||||||
|  |                                             ioservid_t ioservid, | ||||||
|  |                                             xen_pfn_t *ioreq_pfn, | ||||||
|  |                                             xen_pfn_t *bufioreq_pfn, | ||||||
|  |                                             evtchn_port_t *bufioreq_evtchn) | ||||||
|  | { | ||||||
|  |     unsigned long param; | ||||||
|  |     int rc; | ||||||
|  |  | ||||||
|  |     rc = xc_get_hvm_param(xc, dom, HVM_PARAM_IOREQ_PFN, ¶m); | ||||||
|  |     if (rc < 0) { | ||||||
|  |         fprintf(stderr, "failed to get HVM_PARAM_IOREQ_PFN\n"); | ||||||
|  |         return -1; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     *ioreq_pfn = param; | ||||||
|  |  | ||||||
|  |     rc = xc_get_hvm_param(xc, dom, HVM_PARAM_BUFIOREQ_PFN, ¶m); | ||||||
|  |     if (rc < 0) { | ||||||
|  |         fprintf(stderr, "failed to get HVM_PARAM_BUFIOREQ_PFN\n"); | ||||||
|  |         return -1; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     *bufioreq_pfn = param; | ||||||
|  |  | ||||||
|  |     rc = xc_get_hvm_param(xc, dom, HVM_PARAM_BUFIOREQ_EVTCHN, | ||||||
|  |                           ¶m); | ||||||
|  |     if (rc < 0) { | ||||||
|  |         fprintf(stderr, "failed to get HVM_PARAM_BUFIOREQ_EVTCHN\n"); | ||||||
|  |         return -1; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     *bufioreq_evtchn = param; | ||||||
|  |  | ||||||
|  |     return 0; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | static inline int xen_set_ioreq_server_state(XenXC xc, domid_t dom, | ||||||
|  |                                              ioservid_t ioservid, | ||||||
|  |                                              bool enable) | ||||||
|  | { | ||||||
|  |     return 0; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /* Xen 4.5 */ | ||||||
|  | #else | ||||||
|  |  | ||||||
|  | static inline void xen_map_memory_section(XenXC xc, domid_t dom, | ||||||
|  |                                           ioservid_t ioservid, | ||||||
|  |                                           MemoryRegionSection *section) | ||||||
|  | { | ||||||
|  |     hwaddr start_addr = section->offset_within_address_space; | ||||||
|  |     ram_addr_t size = int128_get64(section->size); | ||||||
|  |     hwaddr end_addr = start_addr + size - 1; | ||||||
|  |  | ||||||
|  |     trace_xen_map_mmio_range(ioservid, start_addr, end_addr); | ||||||
|  |     xc_hvm_map_io_range_to_ioreq_server(xc, dom, ioservid, 1, | ||||||
|  |                                         start_addr, end_addr); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | static inline void xen_unmap_memory_section(XenXC xc, domid_t dom, | ||||||
|  |                                             ioservid_t ioservid, | ||||||
|  |                                             MemoryRegionSection *section) | ||||||
|  | { | ||||||
|  |     hwaddr start_addr = section->offset_within_address_space; | ||||||
|  |     ram_addr_t size = int128_get64(section->size); | ||||||
|  |     hwaddr end_addr = start_addr + size - 1; | ||||||
|  |  | ||||||
|  |     trace_xen_unmap_mmio_range(ioservid, start_addr, end_addr); | ||||||
|  |     xc_hvm_unmap_io_range_from_ioreq_server(xc, dom, ioservid, 1, | ||||||
|  |                                             start_addr, end_addr); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | static inline void xen_map_io_section(XenXC xc, domid_t dom, | ||||||
|  |                                       ioservid_t ioservid, | ||||||
|  |                                       MemoryRegionSection *section) | ||||||
|  | { | ||||||
|  |     hwaddr start_addr = section->offset_within_address_space; | ||||||
|  |     ram_addr_t size = int128_get64(section->size); | ||||||
|  |     hwaddr end_addr = start_addr + size - 1; | ||||||
|  |  | ||||||
|  |     trace_xen_map_portio_range(ioservid, start_addr, end_addr); | ||||||
|  |     xc_hvm_map_io_range_to_ioreq_server(xc, dom, ioservid, 0, | ||||||
|  |                                         start_addr, end_addr); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | static inline void xen_unmap_io_section(XenXC xc, domid_t dom, | ||||||
|  |                                         ioservid_t ioservid, | ||||||
|  |                                         MemoryRegionSection *section) | ||||||
|  | { | ||||||
|  |     hwaddr start_addr = section->offset_within_address_space; | ||||||
|  |     ram_addr_t size = int128_get64(section->size); | ||||||
|  |     hwaddr end_addr = start_addr + size - 1; | ||||||
|  |  | ||||||
|  |     trace_xen_unmap_portio_range(ioservid, start_addr, end_addr); | ||||||
|  |     xc_hvm_unmap_io_range_from_ioreq_server(xc, dom, ioservid, 0, | ||||||
|  |                                             start_addr, end_addr); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | static inline void xen_map_pcidev(XenXC xc, domid_t dom, | ||||||
|  |                                   ioservid_t ioservid, | ||||||
|  |                                   PCIDevice *pci_dev) | ||||||
|  | { | ||||||
|  |     trace_xen_map_pcidev(ioservid, pci_bus_num(pci_dev->bus), | ||||||
|  |                          PCI_SLOT(pci_dev->devfn), PCI_FUNC(pci_dev->devfn)); | ||||||
|  |     xc_hvm_map_pcidev_to_ioreq_server(xc, dom, ioservid, | ||||||
|  |                                       0, pci_bus_num(pci_dev->bus), | ||||||
|  |                                       PCI_SLOT(pci_dev->devfn), | ||||||
|  |                                       PCI_FUNC(pci_dev->devfn)); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | static inline void xen_unmap_pcidev(XenXC xc, domid_t dom, | ||||||
|  |                                     ioservid_t ioservid, | ||||||
|  |                                     PCIDevice *pci_dev) | ||||||
|  | { | ||||||
|  |     trace_xen_unmap_pcidev(ioservid, pci_bus_num(pci_dev->bus), | ||||||
|  |                            PCI_SLOT(pci_dev->devfn), PCI_FUNC(pci_dev->devfn)); | ||||||
|  |     xc_hvm_unmap_pcidev_from_ioreq_server(xc, dom, ioservid, | ||||||
|  |                                           0, pci_bus_num(pci_dev->bus), | ||||||
|  |                                           PCI_SLOT(pci_dev->devfn), | ||||||
|  |                                           PCI_FUNC(pci_dev->devfn)); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | static inline int xen_create_ioreq_server(XenXC xc, domid_t dom, | ||||||
|  |                                           ioservid_t *ioservid) | ||||||
|  | { | ||||||
|  |     int rc = xc_hvm_create_ioreq_server(xc, dom, 1, ioservid); | ||||||
|  |  | ||||||
|  |     if (rc == 0) { | ||||||
|  |         trace_xen_ioreq_server_create(*ioservid); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     return rc; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | static inline void xen_destroy_ioreq_server(XenXC xc, domid_t dom, | ||||||
|  |                                             ioservid_t ioservid) | ||||||
|  | { | ||||||
|  |     trace_xen_ioreq_server_destroy(ioservid); | ||||||
|  |     xc_hvm_destroy_ioreq_server(xc, dom, ioservid); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | static inline int xen_get_ioreq_server_info(XenXC xc, domid_t dom, | ||||||
|  |                                             ioservid_t ioservid, | ||||||
|  |                                             xen_pfn_t *ioreq_pfn, | ||||||
|  |                                             xen_pfn_t *bufioreq_pfn, | ||||||
|  |                                             evtchn_port_t *bufioreq_evtchn) | ||||||
|  | { | ||||||
|  |     return xc_hvm_get_ioreq_server_info(xc, dom, ioservid, | ||||||
|  |                                         ioreq_pfn, bufioreq_pfn, | ||||||
|  |                                         bufioreq_evtchn); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | static inline int xen_set_ioreq_server_state(XenXC xc, domid_t dom, | ||||||
|  |                                              ioservid_t ioservid, | ||||||
|  |                                              bool enable) | ||||||
|  | { | ||||||
|  |     trace_xen_ioreq_server_state(ioservid, enable); | ||||||
|  |     return xc_hvm_set_ioreq_server_state(xc, dom, ioservid, enable); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | #endif | ||||||
|  |  | ||||||
| #endif /* QEMU_HW_XEN_COMMON_H */ | #endif /* QEMU_HW_XEN_COMMON_H */ | ||||||
|   | |||||||
| @@ -204,7 +204,7 @@ typedef union { | |||||||
|  *   f    : float access |  *   f    : float access | ||||||
|  * |  * | ||||||
|  * sign is: |  * sign is: | ||||||
|  * (empty): for floats or 32 bit size |  * (empty): for 32 or 64 bit sizes (including floats and doubles) | ||||||
|  *   u    : unsigned |  *   u    : unsigned | ||||||
|  *   s    : signed |  *   s    : signed | ||||||
|  * |  * | ||||||
| @@ -218,7 +218,16 @@ typedef union { | |||||||
|  *   he   : host endian |  *   he   : host endian | ||||||
|  *   be   : big endian |  *   be   : big endian | ||||||
|  *   le   : little endian |  *   le   : little endian | ||||||
|  |  *   te   : target endian | ||||||
|  * (except for byte accesses, which have no endian infix). |  * (except for byte accesses, which have no endian infix). | ||||||
|  |  * | ||||||
|  |  * The target endian accessors are obviously only available to source | ||||||
|  |  * files which are built per-target; they are defined in cpu-all.h. | ||||||
|  |  * | ||||||
|  |  * In all cases these functions take a host pointer. | ||||||
|  |  * For accessors that take a guest address rather than a | ||||||
|  |  * host address, see the cpu_{ld,st}_* accessors defined in | ||||||
|  |  * cpu_ldst.h. | ||||||
|  */ |  */ | ||||||
|  |  | ||||||
| static inline int ldub_p(const void *ptr) | static inline int ldub_p(const void *ptr) | ||||||
|   | |||||||
| @@ -17,6 +17,7 @@ typedef struct BusState BusState; | |||||||
| typedef struct CharDriverState CharDriverState; | typedef struct CharDriverState CharDriverState; | ||||||
| typedef struct CompatProperty CompatProperty; | typedef struct CompatProperty CompatProperty; | ||||||
| typedef struct DeviceState DeviceState; | typedef struct DeviceState DeviceState; | ||||||
|  | typedef struct DeviceListener DeviceListener; | ||||||
| typedef struct DisplayChangeListener DisplayChangeListener; | typedef struct DisplayChangeListener DisplayChangeListener; | ||||||
| typedef struct DisplayState DisplayState; | typedef struct DisplayState DisplayState; | ||||||
| typedef struct DisplaySurface DisplaySurface; | typedef struct DisplaySurface DisplaySurface; | ||||||
|   | |||||||
| @@ -829,8 +829,11 @@ static inline void init_thread(struct target_pt_regs *_regs, struct image_info * | |||||||
|     _regs->gpr[1] = infop->start_stack; |     _regs->gpr[1] = infop->start_stack; | ||||||
| #if defined(TARGET_PPC64) && !defined(TARGET_ABI32) | #if defined(TARGET_PPC64) && !defined(TARGET_ABI32) | ||||||
|     if (get_ppc64_abi(infop) < 2) { |     if (get_ppc64_abi(infop) < 2) { | ||||||
|         _regs->gpr[2] = ldq_raw(infop->entry + 8) + infop->load_bias; |         uint64_t val; | ||||||
|         infop->entry = ldq_raw(infop->entry) + infop->load_bias; |         get_user_u64(val, infop->entry + 8); | ||||||
|  |         _regs->gpr[2] = val + infop->load_bias; | ||||||
|  |         get_user_u64(val, infop->entry); | ||||||
|  |         infop->entry = val + infop->load_bias; | ||||||
|     } else { |     } else { | ||||||
|         _regs->gpr[12] = infop->entry;  /* r12 set to global entry address */ |         _regs->gpr[12] = infop->entry;  /* r12 set to global entry address */ | ||||||
|     } |     } | ||||||
|   | |||||||
| @@ -2972,7 +2972,7 @@ void cpu_loop(CPUM68KState *env) | |||||||
|             { |             { | ||||||
|                 if (ts->sim_syscalls) { |                 if (ts->sim_syscalls) { | ||||||
|                     uint16_t nr; |                     uint16_t nr; | ||||||
|                     nr = lduw(env->pc + 2); |                     get_user_u16(nr, env->pc + 2); | ||||||
|                     env->pc += 4; |                     env->pc += 4; | ||||||
|                     do_m68k_simcall(env, nr); |                     do_m68k_simcall(env, nr); | ||||||
|                 } else { |                 } else { | ||||||
| @@ -3436,10 +3436,8 @@ CPUArchState *cpu_copy(CPUArchState *env) | |||||||
|     CPUState *cpu = ENV_GET_CPU(env); |     CPUState *cpu = ENV_GET_CPU(env); | ||||||
|     CPUArchState *new_env = cpu_init(cpu_model); |     CPUArchState *new_env = cpu_init(cpu_model); | ||||||
|     CPUState *new_cpu = ENV_GET_CPU(new_env); |     CPUState *new_cpu = ENV_GET_CPU(new_env); | ||||||
| #if defined(TARGET_HAS_ICE) |  | ||||||
|     CPUBreakpoint *bp; |     CPUBreakpoint *bp; | ||||||
|     CPUWatchpoint *wp; |     CPUWatchpoint *wp; | ||||||
| #endif |  | ||||||
|  |  | ||||||
|     /* Reset non arch specific state */ |     /* Reset non arch specific state */ | ||||||
|     cpu_reset(new_cpu); |     cpu_reset(new_cpu); | ||||||
| @@ -3451,14 +3449,12 @@ CPUArchState *cpu_copy(CPUArchState *env) | |||||||
|        BP_CPU break/watchpoints are handled correctly on clone. */ |        BP_CPU break/watchpoints are handled correctly on clone. */ | ||||||
|     QTAILQ_INIT(&cpu->breakpoints); |     QTAILQ_INIT(&cpu->breakpoints); | ||||||
|     QTAILQ_INIT(&cpu->watchpoints); |     QTAILQ_INIT(&cpu->watchpoints); | ||||||
| #if defined(TARGET_HAS_ICE) |  | ||||||
|     QTAILQ_FOREACH(bp, &cpu->breakpoints, entry) { |     QTAILQ_FOREACH(bp, &cpu->breakpoints, entry) { | ||||||
|         cpu_breakpoint_insert(new_cpu, bp->pc, bp->flags, NULL); |         cpu_breakpoint_insert(new_cpu, bp->pc, bp->flags, NULL); | ||||||
|     } |     } | ||||||
|     QTAILQ_FOREACH(wp, &cpu->watchpoints, entry) { |     QTAILQ_FOREACH(wp, &cpu->watchpoints, entry) { | ||||||
|         cpu_watchpoint_insert(new_cpu, wp->vaddr, wp->len, wp->flags, NULL); |         cpu_watchpoint_insert(new_cpu, wp->vaddr, wp->len, wp->flags, NULL); | ||||||
|     } |     } | ||||||
| #endif |  | ||||||
|  |  | ||||||
|     return new_env; |     return new_env; | ||||||
| } | } | ||||||
|   | |||||||
| @@ -45,29 +45,34 @@ static inline int is_revectored(int nr, struct target_revectored_struct *bitmap) | |||||||
|     return (((uint8_t *)bitmap)[nr >> 3] >> (nr & 7)) & 1; |     return (((uint8_t *)bitmap)[nr >> 3] >> (nr & 7)) & 1; | ||||||
| } | } | ||||||
|  |  | ||||||
| static inline void vm_putw(uint32_t segptr, unsigned int reg16, unsigned int val) | static inline void vm_putw(CPUX86State *env, uint32_t segptr, | ||||||
|  |                            unsigned int reg16, unsigned int val) | ||||||
| { | { | ||||||
|     stw(segptr + (reg16 & 0xffff), val); |     cpu_stw_data(env, segptr + (reg16 & 0xffff), val); | ||||||
| } | } | ||||||
|  |  | ||||||
| static inline void vm_putl(uint32_t segptr, unsigned int reg16, unsigned int val) | static inline void vm_putl(CPUX86State *env, uint32_t segptr, | ||||||
|  |                            unsigned int reg16, unsigned int val) | ||||||
| { | { | ||||||
|     stl(segptr + (reg16 & 0xffff), val); |     cpu_stl_data(env, segptr + (reg16 & 0xffff), val); | ||||||
| } | } | ||||||
|  |  | ||||||
| static inline unsigned int vm_getb(uint32_t segptr, unsigned int reg16) | static inline unsigned int vm_getb(CPUX86State *env, | ||||||
|  |                                    uint32_t segptr, unsigned int reg16) | ||||||
| { | { | ||||||
|     return ldub(segptr + (reg16 & 0xffff)); |     return cpu_ldub_data(env, segptr + (reg16 & 0xffff)); | ||||||
| } | } | ||||||
|  |  | ||||||
| static inline unsigned int vm_getw(uint32_t segptr, unsigned int reg16) | static inline unsigned int vm_getw(CPUX86State *env, | ||||||
|  |                                    uint32_t segptr, unsigned int reg16) | ||||||
| { | { | ||||||
|     return lduw(segptr + (reg16 & 0xffff)); |     return cpu_lduw_data(env, segptr + (reg16 & 0xffff)); | ||||||
| } | } | ||||||
|  |  | ||||||
| static inline unsigned int vm_getl(uint32_t segptr, unsigned int reg16) | static inline unsigned int vm_getl(CPUX86State *env, | ||||||
|  |                                    uint32_t segptr, unsigned int reg16) | ||||||
| { | { | ||||||
|     return ldl(segptr + (reg16 & 0xffff)); |     return cpu_ldl_data(env, segptr + (reg16 & 0xffff)); | ||||||
| } | } | ||||||
|  |  | ||||||
| void save_v86_state(CPUX86State *env) | void save_v86_state(CPUX86State *env) | ||||||
| @@ -221,7 +226,7 @@ static void do_int(CPUX86State *env, int intno) | |||||||
|                                        &ts->vm86plus.int21_revectored)) |                                        &ts->vm86plus.int21_revectored)) | ||||||
|         goto cannot_handle; |         goto cannot_handle; | ||||||
|     int_addr = (intno << 2); |     int_addr = (intno << 2); | ||||||
|     segoffs = ldl(int_addr); |     segoffs = cpu_ldl_data(env, int_addr); | ||||||
|     if ((segoffs >> 16) == TARGET_BIOSSEG) |     if ((segoffs >> 16) == TARGET_BIOSSEG) | ||||||
|         goto cannot_handle; |         goto cannot_handle; | ||||||
|     LOG_VM86("VM86: emulating int 0x%x. CS:IP=%04x:%04x\n", |     LOG_VM86("VM86: emulating int 0x%x. CS:IP=%04x:%04x\n", | ||||||
| @@ -229,9 +234,9 @@ static void do_int(CPUX86State *env, int intno) | |||||||
|     /* save old state */ |     /* save old state */ | ||||||
|     ssp = env->segs[R_SS].selector << 4; |     ssp = env->segs[R_SS].selector << 4; | ||||||
|     sp = env->regs[R_ESP] & 0xffff; |     sp = env->regs[R_ESP] & 0xffff; | ||||||
|     vm_putw(ssp, sp - 2, get_vflags(env)); |     vm_putw(env, ssp, sp - 2, get_vflags(env)); | ||||||
|     vm_putw(ssp, sp - 4, env->segs[R_CS].selector); |     vm_putw(env, ssp, sp - 4, env->segs[R_CS].selector); | ||||||
|     vm_putw(ssp, sp - 6, env->eip); |     vm_putw(env, ssp, sp - 6, env->eip); | ||||||
|     ADD16(env->regs[R_ESP], -6); |     ADD16(env->regs[R_ESP], -6); | ||||||
|     /* goto interrupt handler */ |     /* goto interrupt handler */ | ||||||
|     env->eip = segoffs & 0xffff; |     env->eip = segoffs & 0xffff; | ||||||
| @@ -285,7 +290,7 @@ void handle_vm86_fault(CPUX86State *env) | |||||||
|     data32 = 0; |     data32 = 0; | ||||||
|     pref_done = 0; |     pref_done = 0; | ||||||
|     do { |     do { | ||||||
|         opcode = vm_getb(csp, ip); |         opcode = vm_getb(env, csp, ip); | ||||||
|         ADD16(ip, 1); |         ADD16(ip, 1); | ||||||
|         switch (opcode) { |         switch (opcode) { | ||||||
|         case 0x66:      /* 32-bit data */     data32=1; break; |         case 0x66:      /* 32-bit data */     data32=1; break; | ||||||
| @@ -306,10 +311,10 @@ void handle_vm86_fault(CPUX86State *env) | |||||||
|     switch(opcode) { |     switch(opcode) { | ||||||
|     case 0x9c: /* pushf */ |     case 0x9c: /* pushf */ | ||||||
|         if (data32) { |         if (data32) { | ||||||
|             vm_putl(ssp, sp - 4, get_vflags(env)); |             vm_putl(env, ssp, sp - 4, get_vflags(env)); | ||||||
|             ADD16(env->regs[R_ESP], -4); |             ADD16(env->regs[R_ESP], -4); | ||||||
|         } else { |         } else { | ||||||
|             vm_putw(ssp, sp - 2, get_vflags(env)); |             vm_putw(env, ssp, sp - 2, get_vflags(env)); | ||||||
|             ADD16(env->regs[R_ESP], -2); |             ADD16(env->regs[R_ESP], -2); | ||||||
|         } |         } | ||||||
|         env->eip = ip; |         env->eip = ip; | ||||||
| @@ -317,10 +322,10 @@ void handle_vm86_fault(CPUX86State *env) | |||||||
|  |  | ||||||
|     case 0x9d: /* popf */ |     case 0x9d: /* popf */ | ||||||
|         if (data32) { |         if (data32) { | ||||||
|             newflags = vm_getl(ssp, sp); |             newflags = vm_getl(env, ssp, sp); | ||||||
|             ADD16(env->regs[R_ESP], 4); |             ADD16(env->regs[R_ESP], 4); | ||||||
|         } else { |         } else { | ||||||
|             newflags = vm_getw(ssp, sp); |             newflags = vm_getw(env, ssp, sp); | ||||||
|             ADD16(env->regs[R_ESP], 2); |             ADD16(env->regs[R_ESP], 2); | ||||||
|         } |         } | ||||||
|         env->eip = ip; |         env->eip = ip; | ||||||
| @@ -335,7 +340,7 @@ void handle_vm86_fault(CPUX86State *env) | |||||||
|         VM86_FAULT_RETURN; |         VM86_FAULT_RETURN; | ||||||
|  |  | ||||||
|     case 0xcd: /* int */ |     case 0xcd: /* int */ | ||||||
|         intno = vm_getb(csp, ip); |         intno = vm_getb(env, csp, ip); | ||||||
|         ADD16(ip, 1); |         ADD16(ip, 1); | ||||||
|         env->eip = ip; |         env->eip = ip; | ||||||
|         if (ts->vm86plus.vm86plus.flags & TARGET_vm86dbg_active) { |         if (ts->vm86plus.vm86plus.flags & TARGET_vm86dbg_active) { | ||||||
| @@ -350,14 +355,14 @@ void handle_vm86_fault(CPUX86State *env) | |||||||
|  |  | ||||||
|     case 0xcf: /* iret */ |     case 0xcf: /* iret */ | ||||||
|         if (data32) { |         if (data32) { | ||||||
|             newip = vm_getl(ssp, sp) & 0xffff; |             newip = vm_getl(env, ssp, sp) & 0xffff; | ||||||
|             newcs = vm_getl(ssp, sp + 4) & 0xffff; |             newcs = vm_getl(env, ssp, sp + 4) & 0xffff; | ||||||
|             newflags = vm_getl(ssp, sp + 8); |             newflags = vm_getl(env, ssp, sp + 8); | ||||||
|             ADD16(env->regs[R_ESP], 12); |             ADD16(env->regs[R_ESP], 12); | ||||||
|         } else { |         } else { | ||||||
|             newip = vm_getw(ssp, sp); |             newip = vm_getw(env, ssp, sp); | ||||||
|             newcs = vm_getw(ssp, sp + 2); |             newcs = vm_getw(env, ssp, sp + 2); | ||||||
|             newflags = vm_getw(ssp, sp + 4); |             newflags = vm_getw(env, ssp, sp + 4); | ||||||
|             ADD16(env->regs[R_ESP], 6); |             ADD16(env->regs[R_ESP], 6); | ||||||
|         } |         } | ||||||
|         env->eip = newip; |         env->eip = newip; | ||||||
|   | |||||||
| @@ -1292,16 +1292,16 @@ static void memory_dump(Monitor *mon, int count, int format, int wsize, | |||||||
|             switch(wsize) { |             switch(wsize) { | ||||||
|             default: |             default: | ||||||
|             case 1: |             case 1: | ||||||
|                 v = ldub_raw(buf + i); |                 v = ldub_p(buf + i); | ||||||
|                 break; |                 break; | ||||||
|             case 2: |             case 2: | ||||||
|                 v = lduw_raw(buf + i); |                 v = lduw_p(buf + i); | ||||||
|                 break; |                 break; | ||||||
|             case 4: |             case 4: | ||||||
|                 v = (uint32_t)ldl_raw(buf + i); |                 v = (uint32_t)ldl_p(buf + i); | ||||||
|                 break; |                 break; | ||||||
|             case 8: |             case 8: | ||||||
|                 v = ldq_raw(buf + i); |                 v = ldq_p(buf + i); | ||||||
|                 break; |                 break; | ||||||
|             } |             } | ||||||
|             monitor_printf(mon, " "); |             monitor_printf(mon, " "); | ||||||
|   | |||||||
| @@ -3258,6 +3258,18 @@ | |||||||
| # Send input event(s) to guest. | # Send input event(s) to guest. | ||||||
| # | # | ||||||
| # @console: #optional console to send event(s) to. | # @console: #optional console to send event(s) to. | ||||||
|  | #           This parameter can be used to send the input event to | ||||||
|  | #           specific input devices in case (a) multiple input devices | ||||||
|  | #           of the same kind are added to the virtual machine and (b) | ||||||
|  | #           you have configured input routing (see docs/multiseat.txt) | ||||||
|  | #           for those input devices.  If input routing is not | ||||||
|  | #           configured this parameter has no effect. | ||||||
|  | #           If @console is missing, only devices that aren't associated | ||||||
|  | #           with a console are admissible. | ||||||
|  | #           If @console is specified, it must exist, and both devices | ||||||
|  | #           associated with that console and devices not associated with a | ||||||
|  | #           console are admissible, but the former take precedence. | ||||||
|  |  | ||||||
| # | # | ||||||
| # @events: List of InputEvent union. | # @events: List of InputEvent union. | ||||||
| # | # | ||||||
|   | |||||||
| @@ -99,6 +99,14 @@ struct %(name)s | |||||||
|  |  | ||||||
|     ret += generate_struct_fields(members) |     ret += generate_struct_fields(members) | ||||||
|  |  | ||||||
|  |     # Make sure that all structs have at least one field; this avoids | ||||||
|  |     # potential issues with attempting to malloc space for zero-length structs | ||||||
|  |     # in C, and also incompatibility with C++ (where an empty struct is size 1). | ||||||
|  |     if not base and not members: | ||||||
|  |             ret += mcgen(''' | ||||||
|  |     char qapi_dummy_field_for_empty_struct; | ||||||
|  | ''') | ||||||
|  |  | ||||||
|     if len(fieldname): |     if len(fieldname): | ||||||
|         fieldname = " " + fieldname |         fieldname = " " + fieldname | ||||||
|     ret += mcgen(''' |     ret += mcgen(''' | ||||||
|   | |||||||
| @@ -32,8 +32,6 @@ | |||||||
|  |  | ||||||
| #include "fpu/softfloat.h" | #include "fpu/softfloat.h" | ||||||
|  |  | ||||||
| #define TARGET_HAS_ICE 1 |  | ||||||
|  |  | ||||||
| #define ELF_MACHINE     EM_ALPHA | #define ELF_MACHINE     EM_ALPHA | ||||||
|  |  | ||||||
| #define ICACHE_LINE_SIZE 32 | #define ICACHE_LINE_SIZE 32 | ||||||
|   | |||||||
| @@ -39,8 +39,6 @@ | |||||||
|  |  | ||||||
| #include "fpu/softfloat.h" | #include "fpu/softfloat.h" | ||||||
|  |  | ||||||
| #define TARGET_HAS_ICE 1 |  | ||||||
|  |  | ||||||
| #define EXCP_UDEF            1   /* undefined instruction */ | #define EXCP_UDEF            1   /* undefined instruction */ | ||||||
| #define EXCP_SWI             2   /* software interrupt */ | #define EXCP_SWI             2   /* software interrupt */ | ||||||
| #define EXCP_PREFETCH_ABORT  3 | #define EXCP_PREFETCH_ABORT  3 | ||||||
|   | |||||||
| @@ -29,8 +29,6 @@ | |||||||
|  |  | ||||||
| #include "exec/cpu-defs.h" | #include "exec/cpu-defs.h" | ||||||
|  |  | ||||||
| #define TARGET_HAS_ICE 1 |  | ||||||
|  |  | ||||||
| #define ELF_MACHINE	EM_CRIS | #define ELF_MACHINE	EM_CRIS | ||||||
|  |  | ||||||
| #define EXCP_NMI        1 | #define EXCP_NMI        1 | ||||||
|   | |||||||
| @@ -37,8 +37,6 @@ | |||||||
|    close to the modifying instruction */ |    close to the modifying instruction */ | ||||||
| #define TARGET_HAS_PRECISE_SMC | #define TARGET_HAS_PRECISE_SMC | ||||||
|  |  | ||||||
| #define TARGET_HAS_ICE 1 |  | ||||||
|  |  | ||||||
| #ifdef TARGET_X86_64 | #ifdef TARGET_X86_64 | ||||||
| #define ELF_MACHINE     EM_X86_64 | #define ELF_MACHINE     EM_X86_64 | ||||||
| #define ELF_MACHINE_UNAME "x86_64" | #define ELF_MACHINE_UNAME "x86_64" | ||||||
|   | |||||||
| @@ -34,7 +34,21 @@ | |||||||
| # define LOG_PCALL_STATE(cpu) do { } while (0) | # define LOG_PCALL_STATE(cpu) do { } while (0) | ||||||
| #endif | #endif | ||||||
|  |  | ||||||
| #ifndef CONFIG_USER_ONLY | #ifdef CONFIG_USER_ONLY | ||||||
|  | #define MEMSUFFIX _kernel | ||||||
|  | #define DATA_SIZE 1 | ||||||
|  | #include "exec/cpu_ldst_useronly_template.h" | ||||||
|  |  | ||||||
|  | #define DATA_SIZE 2 | ||||||
|  | #include "exec/cpu_ldst_useronly_template.h" | ||||||
|  |  | ||||||
|  | #define DATA_SIZE 4 | ||||||
|  | #include "exec/cpu_ldst_useronly_template.h" | ||||||
|  |  | ||||||
|  | #define DATA_SIZE 8 | ||||||
|  | #include "exec/cpu_ldst_useronly_template.h" | ||||||
|  | #undef MEMSUFFIX | ||||||
|  | #else | ||||||
| #define CPU_MMU_INDEX (cpu_mmu_index_kernel(env)) | #define CPU_MMU_INDEX (cpu_mmu_index_kernel(env)) | ||||||
| #define MEMSUFFIX _kernel | #define MEMSUFFIX _kernel | ||||||
| #define DATA_SIZE 1 | #define DATA_SIZE 1 | ||||||
|   | |||||||
| @@ -30,8 +30,6 @@ | |||||||
| struct CPULM32State; | struct CPULM32State; | ||||||
| typedef struct CPULM32State CPULM32State; | typedef struct CPULM32State CPULM32State; | ||||||
|  |  | ||||||
| #define TARGET_HAS_ICE 1 |  | ||||||
|  |  | ||||||
| #define ELF_MACHINE EM_LATTICEMICO32 | #define ELF_MACHINE EM_LATTICEMICO32 | ||||||
|  |  | ||||||
| #define NB_MMU_MODES 1 | #define NB_MMU_MODES 1 | ||||||
|   | |||||||
| @@ -32,8 +32,6 @@ | |||||||
|  |  | ||||||
| #define MAX_QREGS 32 | #define MAX_QREGS 32 | ||||||
|  |  | ||||||
| #define TARGET_HAS_ICE 1 |  | ||||||
|  |  | ||||||
| #define ELF_MACHINE	EM_68K | #define ELF_MACHINE	EM_68K | ||||||
|  |  | ||||||
| #define EXCP_ACCESS         2   /* Access (MMU) error.  */ | #define EXCP_ACCESS         2   /* Access (MMU) error.  */ | ||||||
|   | |||||||
| @@ -34,8 +34,6 @@ typedef struct CPUMBState CPUMBState; | |||||||
| #include "mmu.h" | #include "mmu.h" | ||||||
| #endif | #endif | ||||||
|  |  | ||||||
| #define TARGET_HAS_ICE 1 |  | ||||||
|  |  | ||||||
| #define ELF_MACHINE	EM_MICROBLAZE | #define ELF_MACHINE	EM_MICROBLAZE | ||||||
|  |  | ||||||
| #define EXCP_NMI        1 | #define EXCP_NMI        1 | ||||||
|   | |||||||
| @@ -4,7 +4,6 @@ | |||||||
| //#define DEBUG_OP | //#define DEBUG_OP | ||||||
|  |  | ||||||
| #define ALIGNED_ONLY | #define ALIGNED_ONLY | ||||||
| #define TARGET_HAS_ICE 1 |  | ||||||
|  |  | ||||||
| #define ELF_MACHINE	EM_MIPS | #define ELF_MACHINE	EM_MIPS | ||||||
|  |  | ||||||
|   | |||||||
| @@ -74,7 +74,7 @@ void helper_raise_exception(CPUMIPSState *env, uint32_t exception) | |||||||
| static inline type do_##name(CPUMIPSState *env, target_ulong addr,      \ | static inline type do_##name(CPUMIPSState *env, target_ulong addr,      \ | ||||||
|                              int mem_idx)                               \ |                              int mem_idx)                               \ | ||||||
| {                                                                       \ | {                                                                       \ | ||||||
|     return (type) insn##_raw(addr);                                     \ |     return (type) cpu_##insn##_data(env, addr);                         \ | ||||||
| } | } | ||||||
| #else | #else | ||||||
| #define HELPER_LD(name, insn, type)                                     \ | #define HELPER_LD(name, insn, type)                                     \ | ||||||
| @@ -101,7 +101,7 @@ HELPER_LD(ld, ldq, int64_t) | |||||||
| static inline void do_##name(CPUMIPSState *env, target_ulong addr,      \ | static inline void do_##name(CPUMIPSState *env, target_ulong addr,      \ | ||||||
|                              type val, int mem_idx)                     \ |                              type val, int mem_idx)                     \ | ||||||
| {                                                                       \ | {                                                                       \ | ||||||
|     insn##_raw(addr, val);                                              \ |     cpu_##insn##_data(env, addr, val);                                  \ | ||||||
| } | } | ||||||
| #else | #else | ||||||
| #define HELPER_ST(name, insn, type)                                     \ | #define HELPER_ST(name, insn, type)                                     \ | ||||||
|   | |||||||
| @@ -26,8 +26,6 @@ | |||||||
|  |  | ||||||
| #define CPUArchState struct CPUMoxieState | #define CPUArchState struct CPUMoxieState | ||||||
|  |  | ||||||
| #define TARGET_HAS_ICE 1 |  | ||||||
|  |  | ||||||
| #define ELF_MACHINE     0xFEED /* EM_MOXIE */ | #define ELF_MACHINE     0xFEED /* EM_MOXIE */ | ||||||
|  |  | ||||||
| #define MOXIE_EX_DIV0        0 | #define MOXIE_EX_DIV0        0 | ||||||
|   | |||||||
| @@ -79,8 +79,6 @@ | |||||||
|  |  | ||||||
| #include "fpu/softfloat.h" | #include "fpu/softfloat.h" | ||||||
|  |  | ||||||
| #define TARGET_HAS_ICE 1 |  | ||||||
|  |  | ||||||
| #if defined (TARGET_PPC64) | #if defined (TARGET_PPC64) | ||||||
| #define ELF_MACHINE     EM_PPC64 | #define ELF_MACHINE     EM_PPC64 | ||||||
| #else | #else | ||||||
|   | |||||||
| @@ -886,8 +886,6 @@ int sclp_service_call(CPUS390XState *env, uint64_t sccb, uint32_t code); | |||||||
| uint32_t calc_cc(CPUS390XState *env, uint32_t cc_op, uint64_t src, uint64_t dst, | uint32_t calc_cc(CPUS390XState *env, uint32_t cc_op, uint64_t src, uint64_t dst, | ||||||
|                  uint64_t vr); |                  uint64_t vr); | ||||||
|  |  | ||||||
| #define TARGET_HAS_ICE 1 |  | ||||||
|  |  | ||||||
| /* The value of the TOD clock for 1.1.1970. */ | /* The value of the TOD clock for 1.1.1970. */ | ||||||
| #define TOD_UNIX_EPOCH 0x7d91048bca000000ULL | #define TOD_UNIX_EPOCH 0x7d91048bca000000ULL | ||||||
|  |  | ||||||
|   | |||||||
| @@ -23,7 +23,6 @@ | |||||||
| #include "qemu-common.h" | #include "qemu-common.h" | ||||||
|  |  | ||||||
| #define TARGET_LONG_BITS 32 | #define TARGET_LONG_BITS 32 | ||||||
| #define TARGET_HAS_ICE 1 |  | ||||||
|  |  | ||||||
| #define ELF_MACHINE	EM_SH | #define ELF_MACHINE	EM_SH | ||||||
|  |  | ||||||
|   | |||||||
| @@ -31,8 +31,6 @@ | |||||||
|  |  | ||||||
| #include "fpu/softfloat.h" | #include "fpu/softfloat.h" | ||||||
|  |  | ||||||
| #define TARGET_HAS_ICE 1 |  | ||||||
|  |  | ||||||
| #if !defined(TARGET_SPARC64) | #if !defined(TARGET_SPARC64) | ||||||
| #define ELF_MACHINE     EM_SPARC | #define ELF_MACHINE     EM_SPARC | ||||||
| #else | #else | ||||||
|   | |||||||
| @@ -1122,17 +1122,17 @@ uint64_t helper_ld_asi(CPUSPARCState *env, target_ulong addr, int asi, int size, | |||||||
|         { |         { | ||||||
|             switch (size) { |             switch (size) { | ||||||
|             case 1: |             case 1: | ||||||
|                 ret = ldub_raw(addr); |                 ret = cpu_ldub_data(env, addr); | ||||||
|                 break; |                 break; | ||||||
|             case 2: |             case 2: | ||||||
|                 ret = lduw_raw(addr); |                 ret = cpu_lduw_data(env, addr); | ||||||
|                 break; |                 break; | ||||||
|             case 4: |             case 4: | ||||||
|                 ret = ldl_raw(addr); |                 ret = cpu_ldl_data(env, addr); | ||||||
|                 break; |                 break; | ||||||
|             default: |             default: | ||||||
|             case 8: |             case 8: | ||||||
|                 ret = ldq_raw(addr); |                 ret = cpu_ldq_data(env, addr); | ||||||
|                 break; |                 break; | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
| @@ -1239,17 +1239,17 @@ void helper_st_asi(CPUSPARCState *env, target_ulong addr, target_ulong val, | |||||||
|         { |         { | ||||||
|             switch (size) { |             switch (size) { | ||||||
|             case 1: |             case 1: | ||||||
|                 stb_raw(addr, val); |                 cpu_stb_data(env, addr, val); | ||||||
|                 break; |                 break; | ||||||
|             case 2: |             case 2: | ||||||
|                 stw_raw(addr, val); |                 cpu_stw_data(env, addr, val); | ||||||
|                 break; |                 break; | ||||||
|             case 4: |             case 4: | ||||||
|                 stl_raw(addr, val); |                 cpu_stl_data(env, addr, val); | ||||||
|                 break; |                 break; | ||||||
|             case 8: |             case 8: | ||||||
|             default: |             default: | ||||||
|                 stq_raw(addr, val); |                 cpu_stq_data(env, addr, val); | ||||||
|                 break; |                 break; | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
| @@ -2289,8 +2289,8 @@ void helper_ldqf(CPUSPARCState *env, target_ulong addr, int mem_idx) | |||||||
|         break; |         break; | ||||||
|     } |     } | ||||||
| #else | #else | ||||||
|     u.ll.upper = ldq_raw(address_mask(env, addr)); |     u.ll.upper = cpu_ldq_data(env, address_mask(env, addr)); | ||||||
|     u.ll.lower = ldq_raw(address_mask(env, addr + 8)); |     u.ll.lower = cpu_ldq_data(env, address_mask(env, addr + 8)); | ||||||
|     QT0 = u.q; |     QT0 = u.q; | ||||||
| #endif | #endif | ||||||
| } | } | ||||||
| @@ -2326,8 +2326,8 @@ void helper_stqf(CPUSPARCState *env, target_ulong addr, int mem_idx) | |||||||
|     } |     } | ||||||
| #else | #else | ||||||
|     u.q = QT0; |     u.q = QT0; | ||||||
|     stq_raw(address_mask(env, addr), u.ll.upper); |     cpu_stq_data(env, address_mask(env, addr), u.ll.upper); | ||||||
|     stq_raw(address_mask(env, addr + 8), u.ll.lower); |     cpu_stq_data(env, address_mask(env, addr + 8), u.ll.lower); | ||||||
| #endif | #endif | ||||||
| } | } | ||||||
|  |  | ||||||
|   | |||||||
| @@ -39,8 +39,6 @@ | |||||||
| #include "exec/cpu-defs.h" | #include "exec/cpu-defs.h" | ||||||
| #include "fpu/softfloat.h" | #include "fpu/softfloat.h" | ||||||
|  |  | ||||||
| #define TARGET_HAS_ICE 1 |  | ||||||
|  |  | ||||||
| #define NB_MMU_MODES 4 | #define NB_MMU_MODES 4 | ||||||
|  |  | ||||||
| #define TARGET_PHYS_ADDR_SPACE_BITS 32 | #define TARGET_PHYS_ADDR_SPACE_BITS 32 | ||||||
|   | |||||||
| @@ -897,6 +897,15 @@ pvscsi_tx_rings_num_pages(const char* label, uint32_t num) "Number of %s pages: | |||||||
| # xen-hvm.c | # xen-hvm.c | ||||||
| xen_ram_alloc(unsigned long ram_addr, unsigned long size) "requested: %#lx, size %#lx" | xen_ram_alloc(unsigned long ram_addr, unsigned long size) "requested: %#lx, size %#lx" | ||||||
| xen_client_set_memory(uint64_t start_addr, unsigned long size, bool log_dirty) "%#"PRIx64" size %#lx, log_dirty %i" | xen_client_set_memory(uint64_t start_addr, unsigned long size, bool log_dirty) "%#"PRIx64" size %#lx, log_dirty %i" | ||||||
|  | xen_ioreq_server_create(uint32_t id) "id: %u" | ||||||
|  | xen_ioreq_server_destroy(uint32_t id) "id: %u" | ||||||
|  | xen_ioreq_server_state(uint32_t id, bool enable) "id: %u: enable: %i" | ||||||
|  | xen_map_mmio_range(uint32_t id, uint64_t start_addr, uint64_t end_addr) "id: %u start: %#"PRIx64" end: %#"PRIx64 | ||||||
|  | xen_unmap_mmio_range(uint32_t id, uint64_t start_addr, uint64_t end_addr) "id: %u start: %#"PRIx64" end: %#"PRIx64 | ||||||
|  | xen_map_portio_range(uint32_t id, uint64_t start_addr, uint64_t end_addr) "id: %u start: %#"PRIx64" end: %#"PRIx64 | ||||||
|  | xen_unmap_portio_range(uint32_t id, uint64_t start_addr, uint64_t end_addr) "id: %u start: %#"PRIx64" end: %#"PRIx64 | ||||||
|  | xen_map_pcidev(uint32_t id, uint8_t bus, uint8_t dev, uint8_t func) "id: %u bdf: %02x.%02x.%02x" | ||||||
|  | xen_unmap_pcidev(uint32_t id, uint8_t bus, uint8_t dev, uint8_t func) "id: %u bdf: %02x.%02x.%02x" | ||||||
|  |  | ||||||
| # xen-mapcache.c | # xen-mapcache.c | ||||||
| xen_map_cache(uint64_t phys_addr) "want %#"PRIx64 | xen_map_cache(uint64_t phys_addr) "want %#"PRIx64 | ||||||
|   | |||||||
| @@ -1451,7 +1451,7 @@ static TranslationBlock *tb_find_pc(uintptr_t tc_ptr) | |||||||
|     return &tcg_ctx.tb_ctx.tbs[m_max]; |     return &tcg_ctx.tb_ctx.tbs[m_max]; | ||||||
| } | } | ||||||
|  |  | ||||||
| #if defined(TARGET_HAS_ICE) && !defined(CONFIG_USER_ONLY) | #if !defined(CONFIG_USER_ONLY) | ||||||
| void tb_invalidate_phys_addr(AddressSpace *as, hwaddr addr) | void tb_invalidate_phys_addr(AddressSpace *as, hwaddr addr) | ||||||
| { | { | ||||||
|     ram_addr_t ram_addr; |     ram_addr_t ram_addr; | ||||||
| @@ -1467,7 +1467,7 @@ void tb_invalidate_phys_addr(AddressSpace *as, hwaddr addr) | |||||||
|         + addr; |         + addr; | ||||||
|     tb_invalidate_phys_page_range(ram_addr, ram_addr + 1, 0); |     tb_invalidate_phys_page_range(ram_addr, ram_addr + 1, 0); | ||||||
| } | } | ||||||
| #endif /* TARGET_HAS_ICE && !defined(CONFIG_USER_ONLY) */ | #endif /* !defined(CONFIG_USER_ONLY) */ | ||||||
|  |  | ||||||
| void tb_check_watchpoint(CPUState *cpu) | void tb_check_watchpoint(CPUState *cpu) | ||||||
| { | { | ||||||
|   | |||||||
							
								
								
									
										160
									
								
								xen-hvm.c
									
									
									
									
									
								
							
							
						
						
									
										160
									
								
								xen-hvm.c
									
									
									
									
									
								
							| @@ -85,9 +85,6 @@ static inline ioreq_t *xen_vcpu_ioreq(shared_iopage_t *shared_page, int vcpu) | |||||||
| } | } | ||||||
| #  define FMT_ioreq_size "u" | #  define FMT_ioreq_size "u" | ||||||
| #endif | #endif | ||||||
| #ifndef HVM_PARAM_BUFIOREQ_EVTCHN |  | ||||||
| #define HVM_PARAM_BUFIOREQ_EVTCHN 26 |  | ||||||
| #endif |  | ||||||
|  |  | ||||||
| #define BUFFER_IO_MAX_DELAY  100 | #define BUFFER_IO_MAX_DELAY  100 | ||||||
| /* Leave some slack so that hvmloader does not complain about lack of | /* Leave some slack so that hvmloader does not complain about lack of | ||||||
| @@ -107,6 +104,7 @@ typedef struct XenPhysmap { | |||||||
| } XenPhysmap; | } XenPhysmap; | ||||||
|  |  | ||||||
| typedef struct XenIOState { | typedef struct XenIOState { | ||||||
|  |     ioservid_t ioservid; | ||||||
|     shared_iopage_t *shared_page; |     shared_iopage_t *shared_page; | ||||||
|     shared_vmport_iopage_t *shared_vmport_page; |     shared_vmport_iopage_t *shared_vmport_page; | ||||||
|     buffered_iopage_t *buffered_io_page; |     buffered_iopage_t *buffered_io_page; | ||||||
| @@ -123,6 +121,8 @@ typedef struct XenIOState { | |||||||
|  |  | ||||||
|     struct xs_handle *xenstore; |     struct xs_handle *xenstore; | ||||||
|     MemoryListener memory_listener; |     MemoryListener memory_listener; | ||||||
|  |     MemoryListener io_listener; | ||||||
|  |     DeviceListener device_listener; | ||||||
|     QLIST_HEAD(, XenPhysmap) physmap; |     QLIST_HEAD(, XenPhysmap) physmap; | ||||||
|     hwaddr free_phys_offset; |     hwaddr free_phys_offset; | ||||||
|     const XenPhysmap *log_for_dirtybit; |     const XenPhysmap *log_for_dirtybit; | ||||||
| @@ -491,12 +491,23 @@ static void xen_set_memory(struct MemoryListener *listener, | |||||||
|     bool log_dirty = memory_region_is_logging(section->mr); |     bool log_dirty = memory_region_is_logging(section->mr); | ||||||
|     hvmmem_type_t mem_type; |     hvmmem_type_t mem_type; | ||||||
|  |  | ||||||
|  |     if (section->mr == &ram_memory) { | ||||||
|  |         return; | ||||||
|  |     } else { | ||||||
|  |         if (add) { | ||||||
|  |             xen_map_memory_section(xen_xc, xen_domid, state->ioservid, | ||||||
|  |                                    section); | ||||||
|  |         } else { | ||||||
|  |             xen_unmap_memory_section(xen_xc, xen_domid, state->ioservid, | ||||||
|  |                                      section); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |  | ||||||
|     if (!memory_region_is_ram(section->mr)) { |     if (!memory_region_is_ram(section->mr)) { | ||||||
|         return; |         return; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     if (!(section->mr != &ram_memory |     if (log_dirty != add) { | ||||||
|           && ( (log_dirty && add) || (!log_dirty && !add)))) { |  | ||||||
|         return; |         return; | ||||||
|     } |     } | ||||||
|  |  | ||||||
| @@ -539,6 +550,50 @@ static void xen_region_del(MemoryListener *listener, | |||||||
|     memory_region_unref(section->mr); |     memory_region_unref(section->mr); | ||||||
| } | } | ||||||
|  |  | ||||||
|  | static void xen_io_add(MemoryListener *listener, | ||||||
|  |                        MemoryRegionSection *section) | ||||||
|  | { | ||||||
|  |     XenIOState *state = container_of(listener, XenIOState, io_listener); | ||||||
|  |  | ||||||
|  |     memory_region_ref(section->mr); | ||||||
|  |  | ||||||
|  |     xen_map_io_section(xen_xc, xen_domid, state->ioservid, section); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | static void xen_io_del(MemoryListener *listener, | ||||||
|  |                        MemoryRegionSection *section) | ||||||
|  | { | ||||||
|  |     XenIOState *state = container_of(listener, XenIOState, io_listener); | ||||||
|  |  | ||||||
|  |     xen_unmap_io_section(xen_xc, xen_domid, state->ioservid, section); | ||||||
|  |  | ||||||
|  |     memory_region_unref(section->mr); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | static void xen_device_realize(DeviceListener *listener, | ||||||
|  | 			       DeviceState *dev) | ||||||
|  | { | ||||||
|  |     XenIOState *state = container_of(listener, XenIOState, device_listener); | ||||||
|  |  | ||||||
|  |     if (object_dynamic_cast(OBJECT(dev), TYPE_PCI_DEVICE)) { | ||||||
|  |         PCIDevice *pci_dev = PCI_DEVICE(dev); | ||||||
|  |  | ||||||
|  |         xen_map_pcidev(xen_xc, xen_domid, state->ioservid, pci_dev); | ||||||
|  |     } | ||||||
|  | } | ||||||
|  |  | ||||||
|  | static void xen_device_unrealize(DeviceListener *listener, | ||||||
|  | 				 DeviceState *dev) | ||||||
|  | { | ||||||
|  |     XenIOState *state = container_of(listener, XenIOState, device_listener); | ||||||
|  |  | ||||||
|  |     if (object_dynamic_cast(OBJECT(dev), TYPE_PCI_DEVICE)) { | ||||||
|  |         PCIDevice *pci_dev = PCI_DEVICE(dev); | ||||||
|  |  | ||||||
|  |         xen_unmap_pcidev(xen_xc, xen_domid, state->ioservid, pci_dev); | ||||||
|  |     } | ||||||
|  | } | ||||||
|  |  | ||||||
| static void xen_sync_dirty_bitmap(XenIOState *state, | static void xen_sync_dirty_bitmap(XenIOState *state, | ||||||
|                                   hwaddr start_addr, |                                   hwaddr start_addr, | ||||||
|                                   ram_addr_t size) |                                   ram_addr_t size) | ||||||
| @@ -639,6 +694,17 @@ static MemoryListener xen_memory_listener = { | |||||||
|     .priority = 10, |     .priority = 10, | ||||||
| }; | }; | ||||||
|  |  | ||||||
|  | static MemoryListener xen_io_listener = { | ||||||
|  |     .region_add = xen_io_add, | ||||||
|  |     .region_del = xen_io_del, | ||||||
|  |     .priority = 10, | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | static DeviceListener xen_device_listener = { | ||||||
|  |     .realize = xen_device_realize, | ||||||
|  |     .unrealize = xen_device_unrealize, | ||||||
|  | }; | ||||||
|  |  | ||||||
| /* get the ioreq packets from share mem */ | /* get the ioreq packets from share mem */ | ||||||
| static ioreq_t *cpu_get_ioreq_from_shared_memory(XenIOState *state, int vcpu) | static ioreq_t *cpu_get_ioreq_from_shared_memory(XenIOState *state, int vcpu) | ||||||
| { | { | ||||||
| @@ -887,6 +953,27 @@ static void handle_ioreq(XenIOState *state, ioreq_t *req) | |||||||
|         case IOREQ_TYPE_INVALIDATE: |         case IOREQ_TYPE_INVALIDATE: | ||||||
|             xen_invalidate_map_cache(); |             xen_invalidate_map_cache(); | ||||||
|             break; |             break; | ||||||
|  |         case IOREQ_TYPE_PCI_CONFIG: { | ||||||
|  |             uint32_t sbdf = req->addr >> 32; | ||||||
|  |             uint32_t val; | ||||||
|  |  | ||||||
|  |             /* Fake a write to port 0xCF8 so that | ||||||
|  |              * the config space access will target the | ||||||
|  |              * correct device model. | ||||||
|  |              */ | ||||||
|  |             val = (1u << 31) | | ||||||
|  |                   ((req->addr & 0x0f00) << 16) | | ||||||
|  |                   ((sbdf & 0xffff) << 8) | | ||||||
|  |                   (req->addr & 0xfc); | ||||||
|  |             do_outp(0xcf8, 4, val); | ||||||
|  |  | ||||||
|  |             /* Now issue the config space access via | ||||||
|  |              * port 0xCFC | ||||||
|  |              */ | ||||||
|  |             req->addr = 0xcfc | (req->addr & 0x03); | ||||||
|  |             cpu_ioreq_pio(req); | ||||||
|  |             break; | ||||||
|  |         } | ||||||
|         default: |         default: | ||||||
|             hw_error("Invalid ioreq type 0x%x\n", req->type); |             hw_error("Invalid ioreq type 0x%x\n", req->type); | ||||||
|     } |     } | ||||||
| @@ -1017,9 +1104,15 @@ static void xen_main_loop_prepare(XenIOState *state) | |||||||
| static void xen_hvm_change_state_handler(void *opaque, int running, | static void xen_hvm_change_state_handler(void *opaque, int running, | ||||||
|                                          RunState rstate) |                                          RunState rstate) | ||||||
| { | { | ||||||
|  |     XenIOState *state = opaque; | ||||||
|  |  | ||||||
|     if (running) { |     if (running) { | ||||||
|         xen_main_loop_prepare((XenIOState *)opaque); |         xen_main_loop_prepare(state); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  |     xen_set_ioreq_server_state(xen_xc, xen_domid, | ||||||
|  |                                state->ioservid, | ||||||
|  |                                (rstate == RUN_STATE_RUNNING)); | ||||||
| } | } | ||||||
|  |  | ||||||
| static void xen_exit_notifier(Notifier *n, void *data) | static void xen_exit_notifier(Notifier *n, void *data) | ||||||
| @@ -1088,8 +1181,9 @@ int xen_hvm_init(ram_addr_t *below_4g_mem_size, ram_addr_t *above_4g_mem_size, | |||||||
|                  MemoryRegion **ram_memory) |                  MemoryRegion **ram_memory) | ||||||
| { | { | ||||||
|     int i, rc; |     int i, rc; | ||||||
|     unsigned long ioreq_pfn; |     xen_pfn_t ioreq_pfn; | ||||||
|     unsigned long bufioreq_evtchn; |     xen_pfn_t bufioreq_pfn; | ||||||
|  |     evtchn_port_t bufioreq_evtchn; | ||||||
|     XenIOState *state; |     XenIOState *state; | ||||||
|  |  | ||||||
|     state = g_malloc0(sizeof (XenIOState)); |     state = g_malloc0(sizeof (XenIOState)); | ||||||
| @@ -1106,6 +1200,12 @@ int xen_hvm_init(ram_addr_t *below_4g_mem_size, ram_addr_t *above_4g_mem_size, | |||||||
|         return -1; |         return -1; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  |     rc = xen_create_ioreq_server(xen_xc, xen_domid, &state->ioservid); | ||||||
|  |     if (rc < 0) { | ||||||
|  |         perror("xen: ioreq server create"); | ||||||
|  |         return -1; | ||||||
|  |     } | ||||||
|  |  | ||||||
|     state->exit.notify = xen_exit_notifier; |     state->exit.notify = xen_exit_notifier; | ||||||
|     qemu_add_exit_notifier(&state->exit); |     qemu_add_exit_notifier(&state->exit); | ||||||
|  |  | ||||||
| @@ -1115,8 +1215,18 @@ int xen_hvm_init(ram_addr_t *below_4g_mem_size, ram_addr_t *above_4g_mem_size, | |||||||
|     state->wakeup.notify = xen_wakeup_notifier; |     state->wakeup.notify = xen_wakeup_notifier; | ||||||
|     qemu_register_wakeup_notifier(&state->wakeup); |     qemu_register_wakeup_notifier(&state->wakeup); | ||||||
|  |  | ||||||
|     xc_get_hvm_param(xen_xc, xen_domid, HVM_PARAM_IOREQ_PFN, &ioreq_pfn); |     rc = xen_get_ioreq_server_info(xen_xc, xen_domid, state->ioservid, | ||||||
|  |                                    &ioreq_pfn, &bufioreq_pfn, | ||||||
|  |                                    &bufioreq_evtchn); | ||||||
|  |     if (rc < 0) { | ||||||
|  |         hw_error("failed to get ioreq server info: error %d handle=" XC_INTERFACE_FMT, | ||||||
|  |                  errno, xen_xc); | ||||||
|  |     } | ||||||
|  |  | ||||||
|     DPRINTF("shared page at pfn %lx\n", ioreq_pfn); |     DPRINTF("shared page at pfn %lx\n", ioreq_pfn); | ||||||
|  |     DPRINTF("buffered io page at pfn %lx\n", bufioreq_pfn); | ||||||
|  |     DPRINTF("buffered io evtchn is %x\n", bufioreq_evtchn); | ||||||
|  |  | ||||||
|     state->shared_page = xc_map_foreign_range(xen_xc, xen_domid, XC_PAGE_SIZE, |     state->shared_page = xc_map_foreign_range(xen_xc, xen_domid, XC_PAGE_SIZE, | ||||||
|                                               PROT_READ|PROT_WRITE, ioreq_pfn); |                                               PROT_READ|PROT_WRITE, ioreq_pfn); | ||||||
|     if (state->shared_page == NULL) { |     if (state->shared_page == NULL) { | ||||||
| @@ -1138,10 +1248,10 @@ int xen_hvm_init(ram_addr_t *below_4g_mem_size, ram_addr_t *above_4g_mem_size, | |||||||
|         hw_error("get vmport regs pfn returned error %d, rc=%d", errno, rc); |         hw_error("get vmport regs pfn returned error %d, rc=%d", errno, rc); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     xc_get_hvm_param(xen_xc, xen_domid, HVM_PARAM_BUFIOREQ_PFN, &ioreq_pfn); |     state->buffered_io_page = xc_map_foreign_range(xen_xc, xen_domid, | ||||||
|     DPRINTF("buffered io page at pfn %lx\n", ioreq_pfn); |                                                    XC_PAGE_SIZE, | ||||||
|     state->buffered_io_page = xc_map_foreign_range(xen_xc, xen_domid, XC_PAGE_SIZE, |                                                    PROT_READ|PROT_WRITE, | ||||||
|                                                    PROT_READ|PROT_WRITE, ioreq_pfn); |                                                    bufioreq_pfn); | ||||||
|     if (state->buffered_io_page == NULL) { |     if (state->buffered_io_page == NULL) { | ||||||
|         hw_error("map buffered IO page returned error %d", errno); |         hw_error("map buffered IO page returned error %d", errno); | ||||||
|     } |     } | ||||||
| @@ -1149,6 +1259,12 @@ int xen_hvm_init(ram_addr_t *below_4g_mem_size, ram_addr_t *above_4g_mem_size, | |||||||
|     /* Note: cpus is empty at this point in init */ |     /* Note: cpus is empty at this point in init */ | ||||||
|     state->cpu_by_vcpu_id = g_malloc0(max_cpus * sizeof(CPUState *)); |     state->cpu_by_vcpu_id = g_malloc0(max_cpus * sizeof(CPUState *)); | ||||||
|  |  | ||||||
|  |     rc = xen_set_ioreq_server_state(xen_xc, xen_domid, state->ioservid, true); | ||||||
|  |     if (rc < 0) { | ||||||
|  |         hw_error("failed to enable ioreq server info: error %d handle=" XC_INTERFACE_FMT, | ||||||
|  |                  errno, xen_xc); | ||||||
|  |     } | ||||||
|  |  | ||||||
|     state->ioreq_local_port = g_malloc0(max_cpus * sizeof (evtchn_port_t)); |     state->ioreq_local_port = g_malloc0(max_cpus * sizeof (evtchn_port_t)); | ||||||
|  |  | ||||||
|     /* FIXME: how about if we overflow the page here? */ |     /* FIXME: how about if we overflow the page here? */ | ||||||
| @@ -1156,22 +1272,16 @@ int xen_hvm_init(ram_addr_t *below_4g_mem_size, ram_addr_t *above_4g_mem_size, | |||||||
|         rc = xc_evtchn_bind_interdomain(state->xce_handle, xen_domid, |         rc = xc_evtchn_bind_interdomain(state->xce_handle, xen_domid, | ||||||
|                                         xen_vcpu_eport(state->shared_page, i)); |                                         xen_vcpu_eport(state->shared_page, i)); | ||||||
|         if (rc == -1) { |         if (rc == -1) { | ||||||
|             fprintf(stderr, "bind interdomain ioctl error %d\n", errno); |             fprintf(stderr, "shared evtchn %d bind error %d\n", i, errno); | ||||||
|             return -1; |             return -1; | ||||||
|         } |         } | ||||||
|         state->ioreq_local_port[i] = rc; |         state->ioreq_local_port[i] = rc; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     rc = xc_get_hvm_param(xen_xc, xen_domid, HVM_PARAM_BUFIOREQ_EVTCHN, |  | ||||||
|             &bufioreq_evtchn); |  | ||||||
|     if (rc < 0) { |  | ||||||
|         fprintf(stderr, "failed to get HVM_PARAM_BUFIOREQ_EVTCHN\n"); |  | ||||||
|         return -1; |  | ||||||
|     } |  | ||||||
|     rc = xc_evtchn_bind_interdomain(state->xce_handle, xen_domid, |     rc = xc_evtchn_bind_interdomain(state->xce_handle, xen_domid, | ||||||
|             (uint32_t)bufioreq_evtchn); |                                     bufioreq_evtchn); | ||||||
|     if (rc == -1) { |     if (rc == -1) { | ||||||
|         fprintf(stderr, "bind interdomain ioctl error %d\n", errno); |         fprintf(stderr, "buffered evtchn bind error %d\n", errno); | ||||||
|         return -1; |         return -1; | ||||||
|     } |     } | ||||||
|     state->bufioreq_local_port = rc; |     state->bufioreq_local_port = rc; | ||||||
| @@ -1187,6 +1297,12 @@ int xen_hvm_init(ram_addr_t *below_4g_mem_size, ram_addr_t *above_4g_mem_size, | |||||||
|     memory_listener_register(&state->memory_listener, &address_space_memory); |     memory_listener_register(&state->memory_listener, &address_space_memory); | ||||||
|     state->log_for_dirtybit = NULL; |     state->log_for_dirtybit = NULL; | ||||||
|  |  | ||||||
|  |     state->io_listener = xen_io_listener; | ||||||
|  |     memory_listener_register(&state->io_listener, &address_space_io); | ||||||
|  |  | ||||||
|  |     state->device_listener = xen_device_listener; | ||||||
|  |     device_listener_register(&state->device_listener); | ||||||
|  |  | ||||||
|     /* Initialize backend core & drivers */ |     /* Initialize backend core & drivers */ | ||||||
|     if (xen_be_init() != 0) { |     if (xen_be_init() != 0) { | ||||||
|         fprintf(stderr, "%s: xen backend core setup failed\n", __FUNCTION__); |         fprintf(stderr, "%s: xen backend core setup failed\n", __FUNCTION__); | ||||||
|   | |||||||
| @@ -49,9 +49,6 @@ | |||||||
|  */ |  */ | ||||||
| #define NON_MCACHE_MEMORY_SIZE (80 * 1024 * 1024) | #define NON_MCACHE_MEMORY_SIZE (80 * 1024 * 1024) | ||||||
|  |  | ||||||
| #define mapcache_lock()   ((void)0) |  | ||||||
| #define mapcache_unlock() ((void)0) |  | ||||||
|  |  | ||||||
| typedef struct MapCacheEntry { | typedef struct MapCacheEntry { | ||||||
|     hwaddr paddr_index; |     hwaddr paddr_index; | ||||||
|     uint8_t *vaddr_base; |     uint8_t *vaddr_base; | ||||||
| @@ -79,11 +76,22 @@ typedef struct MapCache { | |||||||
|     unsigned int mcache_bucket_shift; |     unsigned int mcache_bucket_shift; | ||||||
|  |  | ||||||
|     phys_offset_to_gaddr_t phys_offset_to_gaddr; |     phys_offset_to_gaddr_t phys_offset_to_gaddr; | ||||||
|  |     QemuMutex lock; | ||||||
|     void *opaque; |     void *opaque; | ||||||
| } MapCache; | } MapCache; | ||||||
|  |  | ||||||
| static MapCache *mapcache; | static MapCache *mapcache; | ||||||
|  |  | ||||||
|  | static inline void mapcache_lock(void) | ||||||
|  | { | ||||||
|  |     qemu_mutex_lock(&mapcache->lock); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | static inline void mapcache_unlock(void) | ||||||
|  | { | ||||||
|  |     qemu_mutex_unlock(&mapcache->lock); | ||||||
|  | } | ||||||
|  |  | ||||||
| static inline int test_bits(int nr, int size, const unsigned long *addr) | static inline int test_bits(int nr, int size, const unsigned long *addr) | ||||||
| { | { | ||||||
|     unsigned long res = find_next_zero_bit(addr, size + nr, nr); |     unsigned long res = find_next_zero_bit(addr, size + nr, nr); | ||||||
| @@ -102,6 +110,7 @@ void xen_map_cache_init(phys_offset_to_gaddr_t f, void *opaque) | |||||||
|  |  | ||||||
|     mapcache->phys_offset_to_gaddr = f; |     mapcache->phys_offset_to_gaddr = f; | ||||||
|     mapcache->opaque = opaque; |     mapcache->opaque = opaque; | ||||||
|  |     qemu_mutex_init(&mapcache->lock); | ||||||
|  |  | ||||||
|     QTAILQ_INIT(&mapcache->locked_entries); |     QTAILQ_INIT(&mapcache->locked_entries); | ||||||
|  |  | ||||||
| @@ -193,14 +202,14 @@ static void xen_remap_bucket(MapCacheEntry *entry, | |||||||
|     g_free(err); |     g_free(err); | ||||||
| } | } | ||||||
|  |  | ||||||
| uint8_t *xen_map_cache(hwaddr phys_addr, hwaddr size, | static uint8_t *xen_map_cache_unlocked(hwaddr phys_addr, hwaddr size, | ||||||
|                                        uint8_t lock) |                                        uint8_t lock) | ||||||
| { | { | ||||||
|     MapCacheEntry *entry, *pentry = NULL; |     MapCacheEntry *entry, *pentry = NULL; | ||||||
|     hwaddr address_index; |     hwaddr address_index; | ||||||
|     hwaddr address_offset; |     hwaddr address_offset; | ||||||
|     hwaddr __size = size; |     hwaddr cache_size = size; | ||||||
|     hwaddr __test_bit_size = size; |     hwaddr test_bit_size; | ||||||
|     bool translated = false; |     bool translated = false; | ||||||
|  |  | ||||||
| tryagain: | tryagain: | ||||||
| @@ -209,22 +218,22 @@ tryagain: | |||||||
|  |  | ||||||
|     trace_xen_map_cache(phys_addr); |     trace_xen_map_cache(phys_addr); | ||||||
|  |  | ||||||
|     /* __test_bit_size is always a multiple of XC_PAGE_SIZE */ |     /* test_bit_size is always a multiple of XC_PAGE_SIZE */ | ||||||
|     if (size) { |     if (size) { | ||||||
|         __test_bit_size = size + (phys_addr & (XC_PAGE_SIZE - 1)); |         test_bit_size = size + (phys_addr & (XC_PAGE_SIZE - 1)); | ||||||
|  |  | ||||||
|         if (__test_bit_size % XC_PAGE_SIZE) { |         if (test_bit_size % XC_PAGE_SIZE) { | ||||||
|             __test_bit_size += XC_PAGE_SIZE - (__test_bit_size % XC_PAGE_SIZE); |             test_bit_size += XC_PAGE_SIZE - (test_bit_size % XC_PAGE_SIZE); | ||||||
|         } |         } | ||||||
|     } else { |     } else { | ||||||
|         __test_bit_size = XC_PAGE_SIZE; |         test_bit_size = XC_PAGE_SIZE; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     if (mapcache->last_entry != NULL && |     if (mapcache->last_entry != NULL && | ||||||
|         mapcache->last_entry->paddr_index == address_index && |         mapcache->last_entry->paddr_index == address_index && | ||||||
|         !lock && !__size && |         !lock && !size && | ||||||
|         test_bits(address_offset >> XC_PAGE_SHIFT, |         test_bits(address_offset >> XC_PAGE_SHIFT, | ||||||
|                   __test_bit_size >> XC_PAGE_SHIFT, |                   test_bit_size >> XC_PAGE_SHIFT, | ||||||
|                   mapcache->last_entry->valid_mapping)) { |                   mapcache->last_entry->valid_mapping)) { | ||||||
|         trace_xen_map_cache_return(mapcache->last_entry->vaddr_base + address_offset); |         trace_xen_map_cache_return(mapcache->last_entry->vaddr_base + address_offset); | ||||||
|         return mapcache->last_entry->vaddr_base + address_offset; |         return mapcache->last_entry->vaddr_base + address_offset; | ||||||
| @@ -232,20 +241,20 @@ tryagain: | |||||||
|  |  | ||||||
|     /* size is always a multiple of MCACHE_BUCKET_SIZE */ |     /* size is always a multiple of MCACHE_BUCKET_SIZE */ | ||||||
|     if (size) { |     if (size) { | ||||||
|         __size = size + address_offset; |         cache_size = size + address_offset; | ||||||
|         if (__size % MCACHE_BUCKET_SIZE) { |         if (cache_size % MCACHE_BUCKET_SIZE) { | ||||||
|             __size += MCACHE_BUCKET_SIZE - (__size % MCACHE_BUCKET_SIZE); |             cache_size += MCACHE_BUCKET_SIZE - (cache_size % MCACHE_BUCKET_SIZE); | ||||||
|         } |         } | ||||||
|     } else { |     } else { | ||||||
|         __size = MCACHE_BUCKET_SIZE; |         cache_size = MCACHE_BUCKET_SIZE; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     entry = &mapcache->entry[address_index % mapcache->nr_buckets]; |     entry = &mapcache->entry[address_index % mapcache->nr_buckets]; | ||||||
|  |  | ||||||
|     while (entry && entry->lock && entry->vaddr_base && |     while (entry && entry->lock && entry->vaddr_base && | ||||||
|             (entry->paddr_index != address_index || entry->size != __size || |             (entry->paddr_index != address_index || entry->size != cache_size || | ||||||
|              !test_bits(address_offset >> XC_PAGE_SHIFT, |              !test_bits(address_offset >> XC_PAGE_SHIFT, | ||||||
|                  __test_bit_size >> XC_PAGE_SHIFT, |                  test_bit_size >> XC_PAGE_SHIFT, | ||||||
|                  entry->valid_mapping))) { |                  entry->valid_mapping))) { | ||||||
|         pentry = entry; |         pentry = entry; | ||||||
|         entry = entry->next; |         entry = entry->next; | ||||||
| @@ -253,19 +262,19 @@ tryagain: | |||||||
|     if (!entry) { |     if (!entry) { | ||||||
|         entry = g_malloc0(sizeof (MapCacheEntry)); |         entry = g_malloc0(sizeof (MapCacheEntry)); | ||||||
|         pentry->next = entry; |         pentry->next = entry; | ||||||
|         xen_remap_bucket(entry, __size, address_index); |         xen_remap_bucket(entry, cache_size, address_index); | ||||||
|     } else if (!entry->lock) { |     } else if (!entry->lock) { | ||||||
|         if (!entry->vaddr_base || entry->paddr_index != address_index || |         if (!entry->vaddr_base || entry->paddr_index != address_index || | ||||||
|                 entry->size != __size || |                 entry->size != cache_size || | ||||||
|                 !test_bits(address_offset >> XC_PAGE_SHIFT, |                 !test_bits(address_offset >> XC_PAGE_SHIFT, | ||||||
|                     __test_bit_size >> XC_PAGE_SHIFT, |                     test_bit_size >> XC_PAGE_SHIFT, | ||||||
|                     entry->valid_mapping)) { |                     entry->valid_mapping)) { | ||||||
|             xen_remap_bucket(entry, __size, address_index); |             xen_remap_bucket(entry, cache_size, address_index); | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     if(!test_bits(address_offset >> XC_PAGE_SHIFT, |     if(!test_bits(address_offset >> XC_PAGE_SHIFT, | ||||||
|                 __test_bit_size >> XC_PAGE_SHIFT, |                 test_bit_size >> XC_PAGE_SHIFT, | ||||||
|                 entry->valid_mapping)) { |                 entry->valid_mapping)) { | ||||||
|         mapcache->last_entry = NULL; |         mapcache->last_entry = NULL; | ||||||
|         if (!translated && mapcache->phys_offset_to_gaddr) { |         if (!translated && mapcache->phys_offset_to_gaddr) { | ||||||
| @@ -291,14 +300,27 @@ tryagain: | |||||||
|     return mapcache->last_entry->vaddr_base + address_offset; |     return mapcache->last_entry->vaddr_base + address_offset; | ||||||
| } | } | ||||||
|  |  | ||||||
|  | uint8_t *xen_map_cache(hwaddr phys_addr, hwaddr size, | ||||||
|  |                        uint8_t lock) | ||||||
|  | { | ||||||
|  |     uint8_t *p; | ||||||
|  |  | ||||||
|  |     mapcache_lock(); | ||||||
|  |     p = xen_map_cache_unlocked(phys_addr, size, lock); | ||||||
|  |     mapcache_unlock(); | ||||||
|  |     return p; | ||||||
|  | } | ||||||
|  |  | ||||||
| ram_addr_t xen_ram_addr_from_mapcache(void *ptr) | ram_addr_t xen_ram_addr_from_mapcache(void *ptr) | ||||||
| { | { | ||||||
|     MapCacheEntry *entry = NULL; |     MapCacheEntry *entry = NULL; | ||||||
|     MapCacheRev *reventry; |     MapCacheRev *reventry; | ||||||
|     hwaddr paddr_index; |     hwaddr paddr_index; | ||||||
|     hwaddr size; |     hwaddr size; | ||||||
|  |     ram_addr_t raddr; | ||||||
|     int found = 0; |     int found = 0; | ||||||
|  |  | ||||||
|  |     mapcache_lock(); | ||||||
|     QTAILQ_FOREACH(reventry, &mapcache->locked_entries, next) { |     QTAILQ_FOREACH(reventry, &mapcache->locked_entries, next) { | ||||||
|         if (reventry->vaddr_req == ptr) { |         if (reventry->vaddr_req == ptr) { | ||||||
|             paddr_index = reventry->paddr_index; |             paddr_index = reventry->paddr_index; | ||||||
| @@ -323,13 +345,16 @@ ram_addr_t xen_ram_addr_from_mapcache(void *ptr) | |||||||
|     } |     } | ||||||
|     if (!entry) { |     if (!entry) { | ||||||
|         DPRINTF("Trying to find address %p that is not in the mapcache!\n", ptr); |         DPRINTF("Trying to find address %p that is not in the mapcache!\n", ptr); | ||||||
|         return 0; |         raddr = 0; | ||||||
|     } |     } else { | ||||||
|     return (reventry->paddr_index << MCACHE_BUCKET_SHIFT) + |         raddr = (reventry->paddr_index << MCACHE_BUCKET_SHIFT) + | ||||||
|              ((unsigned long) ptr - (unsigned long) entry->vaddr_base); |              ((unsigned long) ptr - (unsigned long) entry->vaddr_base); | ||||||
|     } |     } | ||||||
|  |     mapcache_unlock(); | ||||||
|  |     return raddr; | ||||||
|  | } | ||||||
|  |  | ||||||
| void xen_invalidate_map_cache_entry(uint8_t *buffer) | static void xen_invalidate_map_cache_entry_unlocked(uint8_t *buffer) | ||||||
| { | { | ||||||
|     MapCacheEntry *entry = NULL, *pentry = NULL; |     MapCacheEntry *entry = NULL, *pentry = NULL; | ||||||
|     MapCacheRev *reventry; |     MapCacheRev *reventry; | ||||||
| @@ -383,6 +408,13 @@ void xen_invalidate_map_cache_entry(uint8_t *buffer) | |||||||
|     g_free(entry); |     g_free(entry); | ||||||
| } | } | ||||||
|  |  | ||||||
|  | void xen_invalidate_map_cache_entry(uint8_t *buffer) | ||||||
|  | { | ||||||
|  |     mapcache_lock(); | ||||||
|  |     xen_invalidate_map_cache_entry_unlocked(buffer); | ||||||
|  |     mapcache_unlock(); | ||||||
|  | } | ||||||
|  |  | ||||||
| void xen_invalidate_map_cache(void) | void xen_invalidate_map_cache(void) | ||||||
| { | { | ||||||
|     unsigned long i; |     unsigned long i; | ||||||
| @@ -391,14 +423,14 @@ void xen_invalidate_map_cache(void) | |||||||
|     /* Flush pending AIO before destroying the mapcache */ |     /* Flush pending AIO before destroying the mapcache */ | ||||||
|     bdrv_drain_all(); |     bdrv_drain_all(); | ||||||
|  |  | ||||||
|  |     mapcache_lock(); | ||||||
|  |  | ||||||
|     QTAILQ_FOREACH(reventry, &mapcache->locked_entries, next) { |     QTAILQ_FOREACH(reventry, &mapcache->locked_entries, next) { | ||||||
|         DPRINTF("There should be no locked mappings at this time, " |         DPRINTF("There should be no locked mappings at this time, " | ||||||
|                 "but "TARGET_FMT_plx" -> %p is present\n", |                 "but "TARGET_FMT_plx" -> %p is present\n", | ||||||
|                 reventry->paddr_index, reventry->vaddr_req); |                 reventry->paddr_index, reventry->vaddr_req); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     mapcache_lock(); |  | ||||||
|  |  | ||||||
|     for (i = 0; i < mapcache->nr_buckets; i++) { |     for (i = 0; i < mapcache->nr_buckets; i++) { | ||||||
|         MapCacheEntry *entry = &mapcache->entry[i]; |         MapCacheEntry *entry = &mapcache->entry[i]; | ||||||
|  |  | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user