From 1c0416cbdd536c4d06bca5b7f9ac6fdf6b5938c1 Mon Sep 17 00:00:00 2001 From: "jinhyung.jo" Date: Mon, 8 Jul 2013 16:18:03 +0900 Subject: [PATCH] merge some files, and delete some duplicated files Signed-off-by: Jinhyung Jo --- arch_init.h | 38 - console.h | 405 -------- cpu-defs.h | 221 ----- exec-all.h | 418 --------- hw/acpi_piix4.c | 626 ------------- hw/apic_common.c | 405 -------- hw/block/pc_sysfw.c | 30 + hw/display/vga-pci.c | 8 + hw/i386/pc.c | 21 + hw/input/pl050.c | 5 + hw/input/ps2.c | 20 + hw/intc/apic_common.c | 2 + hw/pc.c | 1191 ------------------------ hw/pc_sysfw.c | 297 ------ hw/pci-hotplug.c | 327 ------- hw/pci.c | 2092 ------------------------------------------ hw/pci.h | 679 -------------- hw/pci/pci-hotplug.c | 40 + hw/pci/pci.c | 4 + hw/pl050.c | 203 ---- hw/ps2.c | 687 -------------- hw/vga-pci.c | 171 ---- hw/vga-pci.h | 16 - hw/vga_int.h | 223 ----- include/exec/cpu-defs.h | 4 + include/hw/pci/pci.h | 3 + include/qemu/main-loop.h | 10 + include/sysemu/arch_init.h | 1 + include/sysemu/kvm.h | 18 + include/sysemu/sysemu.h | 12 + include/ui/console.h | 8 + input.c | 326 ------- kvm.h | 292 ------ main-loop.h | 376 -------- oslib-posix.c | 282 ------ oslib-win32.c | 230 ----- qemu-sockets.c | 697 -------------- softmmu_defs.h | 71 -- softmmu_template.h | 372 -------- sysemu.h | 204 ---- test-qmp-input-visitor.c | 289 ------ test-qmp-output-visitor.c | 457 --------- test-string-input-visitor.c | 195 ---- test-string-output-visitor.c | 188 ---- ui/input.c | 57 ++ util/oslib-posix.c | 20 + util/oslib-win32.c | 100 ++ util/qemu-sockets.c | 8 + vl.c | 14 +- 49 files changed, 384 insertions(+), 11979 deletions(-) delete mode 100644 arch_init.h delete mode 100644 console.h delete mode 100644 cpu-defs.h delete mode 100644 exec-all.h delete mode 100644 hw/acpi_piix4.c delete mode 100644 hw/apic_common.c delete mode 100644 hw/pc.c delete mode 100644 hw/pc_sysfw.c delete mode 100644 hw/pci-hotplug.c delete mode 100644 hw/pci.c delete mode 100644 hw/pci.h delete mode 100644 hw/pl050.c delete mode 100644 hw/ps2.c delete mode 100644 hw/vga-pci.c delete mode 100644 hw/vga-pci.h delete mode 100644 hw/vga_int.h delete mode 100644 input.c delete mode 100644 kvm.h delete mode 100644 main-loop.h delete mode 100644 oslib-posix.c delete mode 100644 oslib-win32.c delete mode 100644 qemu-sockets.c delete mode 100644 softmmu_defs.h delete mode 100644 softmmu_template.h delete mode 100644 sysemu.h delete mode 100644 test-qmp-input-visitor.c delete mode 100644 test-qmp-output-visitor.c delete mode 100644 test-string-input-visitor.c delete mode 100644 test-string-output-visitor.c diff --git a/arch_init.h b/arch_init.h deleted file mode 100644 index 86283c1..0000000 --- a/arch_init.h +++ /dev/null @@ -1,38 +0,0 @@ -#ifndef QEMU_ARCH_INIT_H -#define QEMU_ARCH_INIT_H - -#include "qmp-commands.h" - -enum { - QEMU_ARCH_ALL = -1, - QEMU_ARCH_ALPHA = 1, - QEMU_ARCH_ARM = 2, - QEMU_ARCH_CRIS = 4, - QEMU_ARCH_I386 = 8, - QEMU_ARCH_M68K = 16, - QEMU_ARCH_LM32 = 32, - QEMU_ARCH_MICROBLAZE = 64, - QEMU_ARCH_MIPS = 128, - QEMU_ARCH_PPC = 256, - QEMU_ARCH_S390X = 512, - QEMU_ARCH_SH4 = 1024, - QEMU_ARCH_SPARC = 2048, - QEMU_ARCH_XTENSA = 4096, - QEMU_ARCH_OPENRISC = 8192, - QEMU_ARCH_UNICORE32 = 0x4000, -}; - -extern const uint32_t arch_type; - -void select_soundhw(const char *optarg); -void do_acpitable_option(const char *optarg); -void do_smbios_option(const char *optarg); -void cpudef_init(void); -int audio_available(void); -void audio_init(ISABus *isa_bus, PCIBus *pci_bus); -int tcg_available(void); -int kvm_available(void); -int xen_available(void); -int hax_available(void); -CpuDefinitionInfoList GCC_WEAK_DECL *arch_query_cpu_definitions(Error **errp); -#endif diff --git a/console.h b/console.h deleted file mode 100644 index dee8a37..0000000 --- a/console.h +++ /dev/null @@ -1,405 +0,0 @@ -#ifndef CONSOLE_H -#define CONSOLE_H - -#include "qemu-char.h" -#include "qdict.h" -#include "notify.h" -#include "monitor.h" -#include "trace.h" - -/* keyboard/mouse support */ - -#define MOUSE_EVENT_LBUTTON 0x01 -#define MOUSE_EVENT_RBUTTON 0x02 -#define MOUSE_EVENT_MBUTTON 0x04 - -/* identical to the ps/2 keyboard bits */ -#define QEMU_SCROLL_LOCK_LED (1 << 0) -#define QEMU_NUM_LOCK_LED (1 << 1) -#define QEMU_CAPS_LOCK_LED (1 << 2) - -/* in ms */ -#define GUI_REFRESH_INTERVAL 30 - -typedef void QEMUPutKBDEvent(void *opaque, int keycode); -typedef void QEMUPutLEDEvent(void *opaque, int ledstate); -typedef void QEMUPutMouseEvent(void *opaque, int dx, int dy, int dz, int buttons_state); - -typedef struct QEMUPutMouseEntry { - QEMUPutMouseEvent *qemu_put_mouse_event; - void *qemu_put_mouse_event_opaque; - int qemu_put_mouse_event_absolute; - char *qemu_put_mouse_event_name; - - int index; - - /* used internally by qemu for handling mice */ - QTAILQ_ENTRY(QEMUPutMouseEntry) node; -} QEMUPutMouseEntry; - -typedef struct QEMUPutLEDEntry { - QEMUPutLEDEvent *put_led; - void *opaque; - QTAILQ_ENTRY(QEMUPutLEDEntry) next; -} QEMUPutLEDEntry; - -void qemu_add_kbd_event_handler(QEMUPutKBDEvent *func, void *opaque); -void qemu_remove_kbd_event_handler(void); -QEMUPutMouseEntry *qemu_add_mouse_event_handler(QEMUPutMouseEvent *func, - void *opaque, int absolute, - const char *name); -void qemu_remove_mouse_event_handler(QEMUPutMouseEntry *entry); -void qemu_activate_mouse_event_handler(QEMUPutMouseEntry *entry); - -QEMUPutLEDEntry *qemu_add_led_event_handler(QEMUPutLEDEvent *func, void *opaque); -void qemu_remove_led_event_handler(QEMUPutLEDEntry *entry); - -void kbd_put_keycode(int keycode); -#ifdef CONFIG_MARU -void qemu_add_ps2kbd_event_handler(QEMUPutKBDEvent *func, void *opaque); -void qemu_remove_ps2kbd_event_handler(void); -void ps2kbd_put_keycode(int keycode); -#endif -void kbd_put_ledstate(int ledstate); -void kbd_mouse_event(int dx, int dy, int dz, int buttons_state); - -/* Does the current mouse generate absolute events */ -int kbd_mouse_is_absolute(void); -void qemu_add_mouse_mode_change_notifier(Notifier *notify); -void qemu_remove_mouse_mode_change_notifier(Notifier *notify); - -/* Of all the mice, is there one that generates absolute events */ -int kbd_mouse_has_absolute(void); - -struct MouseTransformInfo { - /* Touchscreen resolution */ - int x; - int y; - /* Calibration values as used/generated by tslib */ - int a[7]; -}; - -void do_mouse_set(Monitor *mon, const QDict *qdict); - -/* keysym is a unicode code except for special keys (see QEMU_KEY_xxx - constants) */ -#define QEMU_KEY_ESC1(c) ((c) | 0xe100) -#define QEMU_KEY_BACKSPACE 0x007f -#define QEMU_KEY_UP QEMU_KEY_ESC1('A') -#define QEMU_KEY_DOWN QEMU_KEY_ESC1('B') -#define QEMU_KEY_RIGHT QEMU_KEY_ESC1('C') -#define QEMU_KEY_LEFT QEMU_KEY_ESC1('D') -#define QEMU_KEY_HOME QEMU_KEY_ESC1(1) -#define QEMU_KEY_END QEMU_KEY_ESC1(4) -#define QEMU_KEY_PAGEUP QEMU_KEY_ESC1(5) -#define QEMU_KEY_PAGEDOWN QEMU_KEY_ESC1(6) -#define QEMU_KEY_DELETE QEMU_KEY_ESC1(3) - -#define QEMU_KEY_CTRL_UP 0xe400 -#define QEMU_KEY_CTRL_DOWN 0xe401 -#define QEMU_KEY_CTRL_LEFT 0xe402 -#define QEMU_KEY_CTRL_RIGHT 0xe403 -#define QEMU_KEY_CTRL_HOME 0xe404 -#define QEMU_KEY_CTRL_END 0xe405 -#define QEMU_KEY_CTRL_PAGEUP 0xe406 -#define QEMU_KEY_CTRL_PAGEDOWN 0xe407 - -void kbd_put_keysym(int keysym); - -/* consoles */ - -#define QEMU_BIG_ENDIAN_FLAG 0x01 -#define QEMU_ALLOCATED_FLAG 0x02 -#define QEMU_REALPIXELS_FLAG 0x04 - -struct PixelFormat { - uint8_t bits_per_pixel; - uint8_t bytes_per_pixel; - uint8_t depth; /* color depth in bits */ - uint32_t rmask, gmask, bmask, amask; - uint8_t rshift, gshift, bshift, ashift; - uint8_t rmax, gmax, bmax, amax; - uint8_t rbits, gbits, bbits, abits; -}; - -struct DisplaySurface { - uint8_t flags; - int width; - int height; - int linesize; /* bytes per line */ - uint8_t *data; - - struct PixelFormat pf; -}; - -/* cursor data format is 32bit RGBA */ -typedef struct QEMUCursor { - int width, height; - int hot_x, hot_y; - int refcount; - uint32_t data[]; -} QEMUCursor; - -QEMUCursor *cursor_alloc(int width, int height); -void cursor_get(QEMUCursor *c); -void cursor_put(QEMUCursor *c); -QEMUCursor *cursor_builtin_hidden(void); -QEMUCursor *cursor_builtin_left_ptr(void); -void cursor_print_ascii_art(QEMUCursor *c, const char *prefix); -int cursor_get_mono_bpl(QEMUCursor *c); -void cursor_set_mono(QEMUCursor *c, - uint32_t foreground, uint32_t background, uint8_t *image, - int transparent, uint8_t *mask); -void cursor_get_mono_image(QEMUCursor *c, int foreground, uint8_t *mask); -void cursor_get_mono_mask(QEMUCursor *c, int transparent, uint8_t *mask); - -struct DisplayChangeListener { - int idle; - uint64_t gui_timer_interval; - - void (*dpy_update)(struct DisplayState *s, int x, int y, int w, int h); - void (*dpy_resize)(struct DisplayState *s); - void (*dpy_setdata)(struct DisplayState *s); - void (*dpy_refresh)(struct DisplayState *s); - void (*dpy_copy)(struct DisplayState *s, int src_x, int src_y, - int dst_x, int dst_y, int w, int h); - void (*dpy_fill)(struct DisplayState *s, int x, int y, - int w, int h, uint32_t c); - void (*dpy_text_cursor)(struct DisplayState *s, int x, int y); - - struct DisplayChangeListener *next; -}; - -struct DisplayAllocator { - DisplaySurface* (*create_displaysurface)(int width, int height); - DisplaySurface* (*resize_displaysurface)(DisplaySurface *surface, int width, int height); - void (*free_displaysurface)(DisplaySurface *surface); -}; - -struct DisplayState { - struct DisplaySurface *surface; - void *opaque; - struct QEMUTimer *gui_timer; - - struct DisplayAllocator* allocator; - struct DisplayChangeListener* listeners; - - void (*mouse_set)(int x, int y, int on); - void (*cursor_define)(QEMUCursor *cursor); - - struct DisplayState *next; -}; - -void register_displaystate(DisplayState *ds); -DisplayState *get_displaystate(void); -DisplaySurface* qemu_create_displaysurface_from(int width, int height, int bpp, - int linesize, uint8_t *data); -void qemu_alloc_display(DisplaySurface *surface, int width, int height, - int linesize, PixelFormat pf, int newflags); -PixelFormat qemu_different_endianness_pixelformat(int bpp); -PixelFormat qemu_default_pixelformat(int bpp); - -DisplayAllocator *register_displayallocator(DisplayState *ds, DisplayAllocator *da); - -static inline DisplaySurface* qemu_create_displaysurface(DisplayState *ds, int width, int height) -{ - return ds->allocator->create_displaysurface(width, height); -} - -static inline DisplaySurface* qemu_resize_displaysurface(DisplayState *ds, int width, int height) -{ - trace_displaysurface_resize(ds, ds->surface, width, height); - return ds->allocator->resize_displaysurface(ds->surface, width, height); -} - -static inline void qemu_free_displaysurface(DisplayState *ds) -{ - trace_displaysurface_free(ds, ds->surface); - ds->allocator->free_displaysurface(ds->surface); -} - -static inline int is_surface_bgr(DisplaySurface *surface) -{ - if (surface->pf.bits_per_pixel == 32 && surface->pf.rshift == 0) - return 1; - else - return 0; -} - -static inline int is_buffer_shared(DisplaySurface *surface) -{ - return (!(surface->flags & QEMU_ALLOCATED_FLAG) && - !(surface->flags & QEMU_REALPIXELS_FLAG)); -} - -static inline void register_displaychangelistener(DisplayState *ds, DisplayChangeListener *dcl) -{ - dcl->next = ds->listeners; - ds->listeners = dcl; -} - -static inline void dpy_update(DisplayState *s, int x, int y, int w, int h) -{ - struct DisplayChangeListener *dcl = s->listeners; - while (dcl != NULL) { - dcl->dpy_update(s, x, y, w, h); - dcl = dcl->next; - } -} - -static inline void dpy_resize(DisplayState *s) -{ - struct DisplayChangeListener *dcl = s->listeners; - while (dcl != NULL) { - dcl->dpy_resize(s); - dcl = dcl->next; - } -} - -static inline void dpy_setdata(DisplayState *s) -{ - struct DisplayChangeListener *dcl = s->listeners; - while (dcl != NULL) { - if (dcl->dpy_setdata) dcl->dpy_setdata(s); - dcl = dcl->next; - } -} - -static inline void dpy_refresh(DisplayState *s) -{ - struct DisplayChangeListener *dcl = s->listeners; - while (dcl != NULL) { - if (dcl->dpy_refresh) dcl->dpy_refresh(s); - dcl = dcl->next; - } -} - -static inline void dpy_copy(struct DisplayState *s, int src_x, int src_y, - int dst_x, int dst_y, int w, int h) { - struct DisplayChangeListener *dcl = s->listeners; - while (dcl != NULL) { - if (dcl->dpy_copy) - dcl->dpy_copy(s, src_x, src_y, dst_x, dst_y, w, h); - else /* TODO */ - dcl->dpy_update(s, dst_x, dst_y, w, h); - dcl = dcl->next; - } -} - -static inline void dpy_fill(struct DisplayState *s, int x, int y, - int w, int h, uint32_t c) { - struct DisplayChangeListener *dcl = s->listeners; - while (dcl != NULL) { - if (dcl->dpy_fill) dcl->dpy_fill(s, x, y, w, h, c); - dcl = dcl->next; - } -} - -static inline void dpy_cursor(struct DisplayState *s, int x, int y) { - struct DisplayChangeListener *dcl = s->listeners; - while (dcl != NULL) { - if (dcl->dpy_text_cursor) dcl->dpy_text_cursor(s, x, y); - dcl = dcl->next; - } -} - -static inline int ds_get_linesize(DisplayState *ds) -{ - return ds->surface->linesize; -} - -static inline uint8_t* ds_get_data(DisplayState *ds) -{ - return ds->surface->data; -} - -static inline int ds_get_width(DisplayState *ds) -{ - return ds->surface->width; -} - -static inline int ds_get_height(DisplayState *ds) -{ - return ds->surface->height; -} - -static inline int ds_get_bits_per_pixel(DisplayState *ds) -{ - return ds->surface->pf.bits_per_pixel; -} - -static inline int ds_get_bytes_per_pixel(DisplayState *ds) -{ - return ds->surface->pf.bytes_per_pixel; -} - -#ifdef CONFIG_CURSES -#include -typedef chtype console_ch_t; -#else -typedef unsigned long console_ch_t; -#endif -static inline void console_write_ch(console_ch_t *dest, uint32_t ch) -{ - if (!(ch & 0xff)) - ch |= ' '; - *dest = ch; -} - -typedef void (*vga_hw_update_ptr)(void *); -typedef void (*vga_hw_invalidate_ptr)(void *); -typedef void (*vga_hw_screen_dump_ptr)(void *, const char *, bool cswitch); -typedef void (*vga_hw_text_update_ptr)(void *, console_ch_t *); - -DisplayState *graphic_console_init(vga_hw_update_ptr update, - vga_hw_invalidate_ptr invalidate, - vga_hw_screen_dump_ptr screen_dump, - vga_hw_text_update_ptr text_update, - void *opaque); - -void vga_hw_update(void); -void vga_hw_invalidate(void); -void vga_hw_screen_dump(const char *filename); -void vga_hw_text_update(console_ch_t *chardata); - -int is_graphic_console(void); -int is_fixedsize_console(void); -CharDriverState *text_console_init(QemuOpts *opts); -void text_consoles_set_display(DisplayState *ds); -void console_select(unsigned int index); -void console_color_init(DisplayState *ds); -void qemu_console_resize(DisplayState *ds, int width, int height); -void qemu_console_copy(DisplayState *ds, int src_x, int src_y, - int dst_x, int dst_y, int w, int h); - -/* sdl.c */ -void sdl_display_init(DisplayState *ds, int full_screen, int no_frame); - -/* cocoa.m */ -void cocoa_display_init(DisplayState *ds, int full_screen); - -/* vnc.c */ -void vnc_display_init(DisplayState *ds); -void vnc_display_close(DisplayState *ds); -int vnc_display_open(DisplayState *ds, const char *display); -void vnc_display_add_client(DisplayState *ds, int csock, int skipauth); -int vnc_display_disable_login(DisplayState *ds); -char *vnc_display_local_addr(DisplayState *ds); -#ifdef CONFIG_VNC -int vnc_display_password(DisplayState *ds, const char *password); -int vnc_display_pw_expire(DisplayState *ds, time_t expires); -#else -static inline int vnc_display_password(DisplayState *ds, const char *password) -{ - return -ENODEV; -} -static inline int vnc_display_pw_expire(DisplayState *ds, time_t expires) -{ - return -ENODEV; -}; -#endif - -/* curses.c */ -void curses_display_init(DisplayState *ds, int full_screen); - -#endif diff --git a/cpu-defs.h b/cpu-defs.h deleted file mode 100644 index 935de12..0000000 --- a/cpu-defs.h +++ /dev/null @@ -1,221 +0,0 @@ -/* - * common defines for all CPUs - * - * Copyright (c) 2003 Fabrice Bellard - * - * 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 . - */ -#ifndef CPU_DEFS_H -#define CPU_DEFS_H - -#ifndef NEED_CPU_H -#error cpu.h included from common code -#endif - -#include "config.h" -#include -#include -#include -#include "osdep.h" -#include "qemu-queue.h" -#include "targphys.h" - -#ifndef TARGET_LONG_BITS -#error TARGET_LONG_BITS must be defined before including this header -#endif - -#define TARGET_LONG_SIZE (TARGET_LONG_BITS / 8) - -typedef int16_t target_short __attribute__ ((aligned(TARGET_SHORT_ALIGNMENT))); -typedef uint16_t target_ushort __attribute__((aligned(TARGET_SHORT_ALIGNMENT))); -typedef int32_t target_int __attribute__((aligned(TARGET_INT_ALIGNMENT))); -typedef uint32_t target_uint __attribute__((aligned(TARGET_INT_ALIGNMENT))); -typedef int64_t target_llong __attribute__((aligned(TARGET_LLONG_ALIGNMENT))); -typedef uint64_t target_ullong __attribute__((aligned(TARGET_LLONG_ALIGNMENT))); -/* target_ulong is the type of a virtual address */ -#if TARGET_LONG_SIZE == 4 -typedef int32_t target_long __attribute__((aligned(TARGET_LONG_ALIGNMENT))); -typedef uint32_t target_ulong __attribute__((aligned(TARGET_LONG_ALIGNMENT))); -#define TARGET_FMT_lx "%08x" -#define TARGET_FMT_ld "%d" -#define TARGET_FMT_lu "%u" -#elif TARGET_LONG_SIZE == 8 -typedef int64_t target_long __attribute__((aligned(TARGET_LONG_ALIGNMENT))); -typedef uint64_t target_ulong __attribute__((aligned(TARGET_LONG_ALIGNMENT))); -#define TARGET_FMT_lx "%016" PRIx64 -#define TARGET_FMT_ld "%" PRId64 -#define TARGET_FMT_lu "%" PRIu64 -#else -#error TARGET_LONG_SIZE undefined -#endif - -#define EXCP_INTERRUPT 0x10000 /* async interruption */ -#define EXCP_HLT 0x10001 /* hlt instruction reached */ -#define EXCP_DEBUG 0x10002 /* cpu stopped after a breakpoint or singlestep */ -#define EXCP_HALTED 0x10003 /* cpu is halted (waiting for external event) */ - -#define TB_JMP_CACHE_BITS 12 -#define TB_JMP_CACHE_SIZE (1 << TB_JMP_CACHE_BITS) - -/* Only the bottom TB_JMP_PAGE_BITS of the jump cache hash bits vary for - addresses on the same page. The top bits are the same. This allows - TLB invalidation to quickly clear a subset of the hash table. */ -#define TB_JMP_PAGE_BITS (TB_JMP_CACHE_BITS / 2) -#define TB_JMP_PAGE_SIZE (1 << TB_JMP_PAGE_BITS) -#define TB_JMP_ADDR_MASK (TB_JMP_PAGE_SIZE - 1) -#define TB_JMP_PAGE_MASK (TB_JMP_CACHE_SIZE - TB_JMP_PAGE_SIZE) - -#if !defined(CONFIG_USER_ONLY) -#define CPU_TLB_BITS 8 -#define CPU_TLB_SIZE (1 << CPU_TLB_BITS) - -#if HOST_LONG_BITS == 32 && TARGET_LONG_BITS == 32 -#define CPU_TLB_ENTRY_BITS 4 -#else -#define CPU_TLB_ENTRY_BITS 5 -#endif - -typedef struct CPUTLBEntry { - /* bit TARGET_LONG_BITS to TARGET_PAGE_BITS : virtual address - bit TARGET_PAGE_BITS-1..4 : Nonzero for accesses that should not - go directly to ram. - bit 3 : indicates that the entry is invalid - bit 2..0 : zero - */ - target_ulong addr_read; - target_ulong addr_write; - target_ulong addr_code; - /* Addend to virtual address to get host address. IO accesses - use the corresponding iotlb value. */ - uintptr_t addend; - /* padding to get a power of two size */ - uint8_t dummy[(1 << CPU_TLB_ENTRY_BITS) - - (sizeof(target_ulong) * 3 + - ((-sizeof(target_ulong) * 3) & (sizeof(uintptr_t) - 1)) + - sizeof(uintptr_t))]; -} CPUTLBEntry; - -extern int CPUTLBEntry_wrong_size[sizeof(CPUTLBEntry) == (1 << CPU_TLB_ENTRY_BITS) ? 1 : -1]; - -#define CPU_COMMON_TLB \ - /* The meaning of the MMU modes is defined in the target code. */ \ - CPUTLBEntry tlb_table[NB_MMU_MODES][CPU_TLB_SIZE]; \ - target_phys_addr_t iotlb[NB_MMU_MODES][CPU_TLB_SIZE]; \ - target_ulong tlb_flush_addr; \ - target_ulong tlb_flush_mask; - -#else - -#define CPU_COMMON_TLB - -#endif - - -#ifdef HOST_WORDS_BIGENDIAN -typedef struct icount_decr_u16 { - uint16_t high; - uint16_t low; -} icount_decr_u16; -#else -typedef struct icount_decr_u16 { - uint16_t low; - uint16_t high; -} icount_decr_u16; -#endif - -struct kvm_run; -struct KVMState; -struct qemu_work_item; - -typedef struct CPUBreakpoint { - target_ulong pc; - int flags; /* BP_* */ - QTAILQ_ENTRY(CPUBreakpoint) entry; -} CPUBreakpoint; - -typedef struct CPUWatchpoint { - target_ulong vaddr; - target_ulong len_mask; - int flags; /* BP_* */ - QTAILQ_ENTRY(CPUWatchpoint) entry; -} CPUWatchpoint; - -#define CPU_TEMP_BUF_NLONGS 128 -#define CPU_COMMON \ - struct TranslationBlock *current_tb; /* currently executing TB */ \ - /* soft mmu support */ \ - /* in order to avoid passing too many arguments to the MMIO \ - helpers, we store some rarely used information in the CPU \ - context) */ \ - uintptr_t mem_io_pc; /* host pc at which the memory was \ - accessed */ \ - target_ulong mem_io_vaddr; /* target virtual addr at which the \ - memory was accessed */ \ - uint32_t halted; /* Nonzero if the CPU is in suspend state */ \ - uint32_t interrupt_request; \ - volatile sig_atomic_t exit_request; \ - CPU_COMMON_TLB \ - struct TranslationBlock *tb_jmp_cache[TB_JMP_CACHE_SIZE]; \ - /* buffer for temporaries in the code generator */ \ - long temp_buf[CPU_TEMP_BUF_NLONGS]; \ - \ - int64_t icount_extra; /* Instructions until next timer event. */ \ - /* Number of cycles left, with interrupt flag in high bit. \ - This allows a single read-compare-cbranch-write sequence to test \ - for both decrementer underflow and exceptions. */ \ - union { \ - uint32_t u32; \ - icount_decr_u16 u16; \ - } icount_decr; \ - uint32_t can_do_io; /* nonzero if memory mapped IO is safe. */ \ - \ - /* from this point: preserved by CPU reset */ \ - /* ice debug support */ \ - QTAILQ_HEAD(breakpoints_head, CPUBreakpoint) breakpoints; \ - int singlestep_enabled; \ - \ - QTAILQ_HEAD(watchpoints_head, CPUWatchpoint) watchpoints; \ - CPUWatchpoint *watchpoint_hit; \ - \ - struct GDBRegisterState *gdb_regs; \ - \ - /* Core interrupt code */ \ - jmp_buf jmp_env; \ - int exception_index; \ - \ - CPUArchState *next_cpu; /* next CPU sharing TB cache */ \ - int cpu_index; /* CPU index (informative) */ \ - uint32_t host_tid; /* host thread ID */ \ - int numa_node; /* NUMA node this cpu is belonging to */ \ - int nr_cores; /* number of cores within this CPU package */ \ - int nr_threads;/* number of threads within this CPU */ \ - int running; /* Nonzero if cpu is currently running(usermode). */ \ - int thread_id; \ - /* user data */ \ - void *opaque; \ - \ - uint32_t created; \ - uint32_t stop; /* Stop request */ \ - uint32_t stopped; /* Artificially stopped */ \ - struct QemuCond *halt_cond; \ - struct qemu_work_item *queued_work_first, *queued_work_last; \ - const char *cpu_model_str; \ - struct KVMState *kvm_state; \ - struct kvm_run *kvm_run; \ - int kvm_fd; \ - int kvm_vcpu_dirty; \ - int hax_vcpu_dirty; \ - struct hax_vcpu_state *hax_vcpu; - -#endif diff --git a/exec-all.h b/exec-all.h deleted file mode 100644 index 2d35a60..0000000 --- a/exec-all.h +++ /dev/null @@ -1,418 +0,0 @@ -/* - * internal execution defines for qemu - * - * Copyright (c) 2003 Fabrice Bellard - * - * 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 . - */ - -#ifndef _EXEC_ALL_H_ -#define _EXEC_ALL_H_ - -#include "qemu-common.h" - -/* allow to see translation results - the slowdown should be negligible, so we leave it */ -#define DEBUG_DISAS - -/* Page tracking code uses ram addresses in system mode, and virtual - addresses in userspace mode. Define tb_page_addr_t to be an appropriate - type. */ -#if defined(CONFIG_USER_ONLY) -typedef abi_ulong tb_page_addr_t; -#else -typedef ram_addr_t tb_page_addr_t; -#endif - -/* is_jmp field values */ -#define DISAS_NEXT 0 /* next instruction can be analyzed */ -#define DISAS_JUMP 1 /* only pc was modified dynamically */ -#define DISAS_UPDATE 2 /* cpu state was modified dynamically */ -#define DISAS_TB_JUMP 3 /* only pc was modified statically */ - -struct TranslationBlock; -typedef struct TranslationBlock TranslationBlock; - -/* XXX: make safe guess about sizes */ -#define MAX_OP_PER_INSTR 208 - -#if HOST_LONG_BITS == 32 -#define MAX_OPC_PARAM_PER_ARG 2 -#else -#define MAX_OPC_PARAM_PER_ARG 1 -#endif -#define MAX_OPC_PARAM_IARGS 4 -#define MAX_OPC_PARAM_OARGS 1 -#define MAX_OPC_PARAM_ARGS (MAX_OPC_PARAM_IARGS + MAX_OPC_PARAM_OARGS) - -/* A Call op needs up to 4 + 2N parameters on 32-bit archs, - * and up to 4 + N parameters on 64-bit archs - * (N = number of input arguments + output arguments). */ -#define MAX_OPC_PARAM (4 + (MAX_OPC_PARAM_PER_ARG * MAX_OPC_PARAM_ARGS)) -#define OPC_BUF_SIZE 640 -#define OPC_MAX_SIZE (OPC_BUF_SIZE - MAX_OP_PER_INSTR) - -/* Maximum size a TCG op can expand to. This is complicated because a - single op may require several host instructions and register reloads. - For now take a wild guess at 192 bytes, which should allow at least - a couple of fixup instructions per argument. */ -#define TCG_MAX_OP_SIZE 192 - -#define OPPARAM_BUF_SIZE (OPC_BUF_SIZE * MAX_OPC_PARAM) - -extern target_ulong gen_opc_pc[OPC_BUF_SIZE]; -extern uint8_t gen_opc_instr_start[OPC_BUF_SIZE]; -extern uint16_t gen_opc_icount[OPC_BUF_SIZE]; - -#include "qemu-log.h" - -void gen_intermediate_code(CPUArchState *env, struct TranslationBlock *tb); -void gen_intermediate_code_pc(CPUArchState *env, struct TranslationBlock *tb); -void restore_state_to_opc(CPUArchState *env, struct TranslationBlock *tb, - int pc_pos); - -void cpu_gen_init(void); -int cpu_gen_code(CPUArchState *env, struct TranslationBlock *tb, - int *gen_code_size_ptr); -int cpu_restore_state(struct TranslationBlock *tb, - CPUArchState *env, uintptr_t searched_pc); -void QEMU_NORETURN cpu_resume_from_signal(CPUArchState *env1, void *puc); -void QEMU_NORETURN cpu_io_recompile(CPUArchState *env, uintptr_t retaddr); -TranslationBlock *tb_gen_code(CPUArchState *env, - target_ulong pc, target_ulong cs_base, int flags, - int cflags); -void cpu_exec_init(CPUArchState *env); -void QEMU_NORETURN cpu_loop_exit(CPUArchState *env1); -int page_unprotect(target_ulong address, uintptr_t pc, void *puc); -void tb_invalidate_phys_page_range(tb_page_addr_t start, tb_page_addr_t end, - int is_cpu_write_access); -void tb_invalidate_phys_range(tb_page_addr_t start, tb_page_addr_t end, - int is_cpu_write_access); -#if !defined(CONFIG_USER_ONLY) -/* cputlb.c */ -void tlb_flush_page(CPUArchState *env, target_ulong addr); -void tlb_flush(CPUArchState *env, int flush_global); -void tlb_set_page(CPUArchState *env, target_ulong vaddr, - target_phys_addr_t paddr, int prot, - int mmu_idx, target_ulong size); -void tb_invalidate_phys_addr(target_phys_addr_t addr); -#else -static inline void tlb_flush_page(CPUArchState *env, target_ulong addr) -{ -} - -static inline void tlb_flush(CPUArchState *env, int flush_global) -{ -} -#endif - -#define CODE_GEN_ALIGN 16 /* must be >= of the size of a icache line */ - -#define CODE_GEN_PHYS_HASH_BITS 15 -#define CODE_GEN_PHYS_HASH_SIZE (1 << CODE_GEN_PHYS_HASH_BITS) - -#define MIN_CODE_GEN_BUFFER_SIZE (1024 * 1024) - -/* estimated block size for TB allocation */ -/* XXX: use a per code average code fragment size and modulate it - according to the host CPU */ -#if defined(CONFIG_SOFTMMU) -#define CODE_GEN_AVG_BLOCK_SIZE 128 -#else -#define CODE_GEN_AVG_BLOCK_SIZE 64 -#endif - -#if defined(_ARCH_PPC) || defined(__x86_64__) || defined(__arm__) || defined(__i386__) -#define USE_DIRECT_JUMP -#elif defined(CONFIG_TCG_INTERPRETER) -#define USE_DIRECT_JUMP -#endif - -struct TranslationBlock { - target_ulong pc; /* simulated PC corresponding to this block (EIP + CS base) */ - target_ulong cs_base; /* CS base for this block */ - uint64_t flags; /* flags defining in which context the code was generated */ - uint16_t size; /* size of target code for this block (1 <= - size <= TARGET_PAGE_SIZE) */ - uint16_t cflags; /* compile flags */ -#define CF_COUNT_MASK 0x7fff -#define CF_LAST_IO 0x8000 /* Last insn may be an IO access. */ - - uint8_t *tc_ptr; /* pointer to the translated code */ - /* next matching tb for physical address. */ - struct TranslationBlock *phys_hash_next; - /* first and second physical page containing code. The lower bit - of the pointer tells the index in page_next[] */ - struct TranslationBlock *page_next[2]; - tb_page_addr_t page_addr[2]; - - /* the following data are used to directly call another TB from - the code of this one. */ - uint16_t tb_next_offset[2]; /* offset of original jump target */ -#ifdef USE_DIRECT_JUMP - uint16_t tb_jmp_offset[2]; /* offset of jump instruction */ -#else - uintptr_t tb_next[2]; /* address of jump generated code */ -#endif - /* list of TBs jumping to this one. This is a circular list using - the two least significant bits of the pointers to tell what is - the next pointer: 0 = jmp_next[0], 1 = jmp_next[1], 2 = - jmp_first */ - struct TranslationBlock *jmp_next[2]; - struct TranslationBlock *jmp_first; - uint32_t icount; -}; - -static inline unsigned int tb_jmp_cache_hash_page(target_ulong pc) -{ - target_ulong tmp; - tmp = pc ^ (pc >> (TARGET_PAGE_BITS - TB_JMP_PAGE_BITS)); - return (tmp >> (TARGET_PAGE_BITS - TB_JMP_PAGE_BITS)) & TB_JMP_PAGE_MASK; -} - -static inline unsigned int tb_jmp_cache_hash_func(target_ulong pc) -{ - target_ulong tmp; - tmp = pc ^ (pc >> (TARGET_PAGE_BITS - TB_JMP_PAGE_BITS)); - return (((tmp >> (TARGET_PAGE_BITS - TB_JMP_PAGE_BITS)) & TB_JMP_PAGE_MASK) - | (tmp & TB_JMP_ADDR_MASK)); -} - -static inline unsigned int tb_phys_hash_func(tb_page_addr_t pc) -{ - return (pc >> 2) & (CODE_GEN_PHYS_HASH_SIZE - 1); -} - -void tb_free(TranslationBlock *tb); -void tb_flush(CPUArchState *env); -void tb_link_page(TranslationBlock *tb, - tb_page_addr_t phys_pc, tb_page_addr_t phys_page2); -void tb_phys_invalidate(TranslationBlock *tb, tb_page_addr_t page_addr); - -extern TranslationBlock *tb_phys_hash[CODE_GEN_PHYS_HASH_SIZE]; - -#if defined(USE_DIRECT_JUMP) - -#if defined(CONFIG_TCG_INTERPRETER) -static inline void tb_set_jmp_target1(uintptr_t jmp_addr, uintptr_t addr) -{ - /* patch the branch destination */ - *(uint32_t *)jmp_addr = addr - (jmp_addr + 4); - /* no need to flush icache explicitly */ -} -#elif defined(_ARCH_PPC) -void ppc_tb_set_jmp_target(unsigned long jmp_addr, unsigned long addr); -#define tb_set_jmp_target1 ppc_tb_set_jmp_target -#elif defined(__i386__) || defined(__x86_64__) -static inline void tb_set_jmp_target1(uintptr_t jmp_addr, uintptr_t addr) -{ - /* patch the branch destination */ - *(uint32_t *)jmp_addr = addr - (jmp_addr + 4); - /* no need to flush icache explicitly */ -} -#elif defined(__arm__) -static inline void tb_set_jmp_target1(uintptr_t jmp_addr, uintptr_t addr) -{ -#if !QEMU_GNUC_PREREQ(4, 1) - register unsigned long _beg __asm ("a1"); - register unsigned long _end __asm ("a2"); - register unsigned long _flg __asm ("a3"); -#endif - - /* we could use a ldr pc, [pc, #-4] kind of branch and avoid the flush */ - *(uint32_t *)jmp_addr = - (*(uint32_t *)jmp_addr & ~0xffffff) - | (((addr - (jmp_addr + 8)) >> 2) & 0xffffff); - -#if QEMU_GNUC_PREREQ(4, 1) - __builtin___clear_cache((char *) jmp_addr, (char *) jmp_addr + 4); -#else - /* flush icache */ - _beg = jmp_addr; - _end = jmp_addr + 4; - _flg = 0; - __asm __volatile__ ("swi 0x9f0002" : : "r" (_beg), "r" (_end), "r" (_flg)); -#endif -} -#else -#error tb_set_jmp_target1 is missing -#endif - -static inline void tb_set_jmp_target(TranslationBlock *tb, - int n, uintptr_t addr) -{ - uint16_t offset = tb->tb_jmp_offset[n]; - tb_set_jmp_target1((uintptr_t)(tb->tc_ptr + offset), addr); -} - -#else - -/* set the jump target */ -static inline void tb_set_jmp_target(TranslationBlock *tb, - int n, uintptr_t addr) -{ - tb->tb_next[n] = addr; -} - -#endif - -static inline void tb_add_jump(TranslationBlock *tb, int n, - TranslationBlock *tb_next) -{ - /* NOTE: this test is only needed for thread safety */ - if (!tb->jmp_next[n]) { - /* patch the native jump address */ - tb_set_jmp_target(tb, n, (uintptr_t)tb_next->tc_ptr); - - /* add in TB jmp circular list */ - tb->jmp_next[n] = tb_next->jmp_first; - tb_next->jmp_first = (TranslationBlock *)((uintptr_t)(tb) | (n)); - } -} - -TranslationBlock *tb_find_pc(uintptr_t pc_ptr); - -#include "qemu-lock.h" - -extern spinlock_t tb_lock; - -extern int tb_invalidated_flag; - -/* The return address may point to the start of the next instruction. - Subtracting one gets us the call instruction itself. */ -#if defined(CONFIG_TCG_INTERPRETER) -/* Alpha and SH4 user mode emulations and Softmmu call GETPC(). - For all others, GETPC remains undefined (which makes TCI a little faster. */ -# if defined(CONFIG_SOFTMMU) || defined(TARGET_ALPHA) || defined(TARGET_SH4) -extern uintptr_t tci_tb_ptr; -# define GETPC() tci_tb_ptr -# endif -#elif defined(__s390__) && !defined(__s390x__) -# define GETPC() \ - (((uintptr_t)__builtin_return_address(0) & 0x7fffffffUL) - 1) -#elif defined(__arm__) -/* Thumb return addresses have the low bit set, so we need to subtract two. - This is still safe in ARM mode because instructions are 4 bytes. */ -# define GETPC() ((uintptr_t)__builtin_return_address(0) - 2) -#else -# define GETPC() ((uintptr_t)__builtin_return_address(0) - 1) -#endif - -#if defined(CONFIG_QEMU_LDST_OPTIMIZATION) && defined(CONFIG_SOFTMMU) -/* qemu_ld/st optimization split code generation to fast and slow path, thus, - it needs special handling for an MMU helper which is called from the slow - path, to get the fast path's pc without any additional argument. - It uses a tricky solution which embeds the fast path pc into the slow path. - - Code flow in slow path: - (1) pre-process - (2) call MMU helper - (3) jump to (5) - (4) fast path information (implementation specific) - (5) post-process (e.g. stack adjust) - (6) jump to corresponding code of the next of fast path - */ -# if defined(__i386__) || defined(__x86_64__) -/* To avoid broken disassembling, long jmp is used for embedding fast path pc, - so that the destination is the next code of fast path, though this jmp is - never executed. - - call MMU helper - jmp POST_PROC (2byte) <- GETRA() - jmp NEXT_CODE (5byte) - POST_PROCESS ... <- GETRA() + 7 - */ -# define GETRA() ((uintptr_t)__builtin_return_address(0)) -# define GETPC_LDST() ((uintptr_t)(GETRA() + 7 + \ - *(int32_t *)((void *)GETRA() + 3) - 1)) -# else -# error "CONFIG_QEMU_LDST_OPTIMIZATION needs GETPC_LDST() implementation!" -# endif -bool is_tcg_gen_code(uintptr_t pc_ptr); -# define GETPC_EXT() (is_tcg_gen_code(GETRA()) ? GETPC_LDST() : GETPC()) -#else -# define GETPC_EXT() GETPC() -#endif - -#if !defined(CONFIG_USER_ONLY) - -struct MemoryRegion *iotlb_to_region(target_phys_addr_t index); -uint64_t io_mem_read(struct MemoryRegion *mr, target_phys_addr_t addr, - unsigned size); -void io_mem_write(struct MemoryRegion *mr, target_phys_addr_t addr, - uint64_t value, unsigned size); - -void tlb_fill(CPUArchState *env1, target_ulong addr, int is_write, int mmu_idx, - uintptr_t retaddr); - -#include "softmmu_defs.h" - -#define ACCESS_TYPE (NB_MMU_MODES + 1) -#define MEMSUFFIX _code -#ifndef CONFIG_TCG_PASS_AREG0 -#define env cpu_single_env -#endif - -#define DATA_SIZE 1 -#include "softmmu_header.h" - -#define DATA_SIZE 2 -#include "softmmu_header.h" - -#define DATA_SIZE 4 -#include "softmmu_header.h" - -#define DATA_SIZE 8 -#include "softmmu_header.h" - -#undef ACCESS_TYPE -#undef MEMSUFFIX -#undef env - -#endif - -#if defined(CONFIG_USER_ONLY) -static inline tb_page_addr_t get_page_addr_code(CPUArchState *env1, target_ulong addr) -{ - return addr; -} -#else -/* cputlb.c */ -tb_page_addr_t get_page_addr_code(CPUArchState *env1, target_ulong addr); -#endif - -typedef void (CPUDebugExcpHandler)(CPUArchState *env); - -void cpu_set_debug_excp_handler(CPUDebugExcpHandler *handler); - -/* vl.c */ -extern int singlestep; - -/* cpu-exec.c */ -extern volatile sig_atomic_t exit_request; - -/* Deterministic execution requires that IO only be performed on the last - instruction of a TB so that interrupts take effect immediately. */ -static inline int can_do_io(CPUArchState *env) -{ - if (!use_icount) { - return 1; - } - /* If not executing code then assume we are ok. */ - if (!env->current_tb) { - return 1; - } - return env->can_do_io != 0; -} - -#endif diff --git a/hw/acpi_piix4.c b/hw/acpi_piix4.c deleted file mode 100644 index e22e354..0000000 --- a/hw/acpi_piix4.c +++ /dev/null @@ -1,626 +0,0 @@ -/* - * ACPI implementation - * - * Copyright (c) 2006 Fabrice Bellard - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License version 2 as published by the Free Software Foundation. - * - * 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 - * - * Contributions after 2012-01-13 are licensed under the terms of the - * GNU GPL, version 2 or (at your option) any later version. - */ -#include "hw.h" -#include "pc.h" -#include "apm.h" -#include "pm_smbus.h" -#include "pci.h" -#include "acpi.h" -#include "sysemu.h" -#include "range.h" -#include "ioport.h" -#include "fw_cfg.h" - -//#define DEBUG - -#ifdef DEBUG -# define PIIX4_DPRINTF(format, ...) printf(format, ## __VA_ARGS__) -#else -# define PIIX4_DPRINTF(format, ...) do { } while (0) -#endif - -#define ACPI_DBG_IO_ADDR 0xb044 - -#define GPE_BASE 0xafe0 -#define GPE_LEN 4 -#define PCI_UP_BASE 0xae00 -#define PCI_DOWN_BASE 0xae04 -#define PCI_EJ_BASE 0xae08 -#define PCI_RMV_BASE 0xae0c - -#define PIIX4_PCI_HOTPLUG_STATUS 2 - -struct pci_status { - uint32_t up; /* deprecated, maintained for migration compatibility */ - uint32_t down; -}; - -typedef struct PIIX4PMState { - PCIDevice dev; - IORange ioport; - ACPIREGS ar; - - APMState apm; - - PMSMBus smb; - uint32_t smb_io_base; - - qemu_irq irq; - qemu_irq smi_irq; - int kvm_enabled; - Notifier machine_ready; - - /* for pci hotplug */ - struct pci_status pci0_status; - uint32_t pci0_hotplug_enable; - uint32_t pci0_slot_device_present; - - uint8_t disable_s3; - uint8_t disable_s4; - uint8_t s4_val; -} PIIX4PMState; - -static void piix4_acpi_system_hot_add_init(PCIBus *bus, PIIX4PMState *s); - -#define ACPI_ENABLE 0xf1 -#define ACPI_DISABLE 0xf0 - -static void pm_update_sci(PIIX4PMState *s) -{ - int sci_level, pmsts; - - pmsts = acpi_pm1_evt_get_sts(&s->ar); - sci_level = (((pmsts & s->ar.pm1.evt.en) & - (ACPI_BITMASK_RT_CLOCK_ENABLE | - ACPI_BITMASK_POWER_BUTTON_ENABLE | - ACPI_BITMASK_GLOBAL_LOCK_ENABLE | - ACPI_BITMASK_TIMER_ENABLE)) != 0) || - (((s->ar.gpe.sts[0] & s->ar.gpe.en[0]) - & PIIX4_PCI_HOTPLUG_STATUS) != 0); - - qemu_set_irq(s->irq, sci_level); - /* schedule a timer interruption if needed */ - acpi_pm_tmr_update(&s->ar, (s->ar.pm1.evt.en & ACPI_BITMASK_TIMER_ENABLE) && - !(pmsts & ACPI_BITMASK_TIMER_STATUS)); -} - -static void pm_tmr_timer(ACPIREGS *ar) -{ - PIIX4PMState *s = container_of(ar, PIIX4PMState, ar); - pm_update_sci(s); -} - -static void pm_ioport_write(IORange *ioport, uint64_t addr, unsigned width, - uint64_t val) -{ - PIIX4PMState *s = container_of(ioport, PIIX4PMState, ioport); - - if (width != 2) { - PIIX4_DPRINTF("PM write port=0x%04x width=%d val=0x%08x\n", - (unsigned)addr, width, (unsigned)val); - } - - switch(addr) { - case 0x00: - acpi_pm1_evt_write_sts(&s->ar, val); - pm_update_sci(s); - break; - case 0x02: - acpi_pm1_evt_write_en(&s->ar, val); - pm_update_sci(s); - break; - case 0x04: - acpi_pm1_cnt_write(&s->ar, val, s->s4_val); - break; - default: - break; - } - PIIX4_DPRINTF("PM writew port=0x%04x val=0x%04x\n", (unsigned int)addr, - (unsigned int)val); -} - -static void pm_ioport_read(IORange *ioport, uint64_t addr, unsigned width, - uint64_t *data) -{ - PIIX4PMState *s = container_of(ioport, PIIX4PMState, ioport); - uint32_t val; - - switch(addr) { - case 0x00: - val = acpi_pm1_evt_get_sts(&s->ar); - break; - case 0x02: - val = s->ar.pm1.evt.en; - break; - case 0x04: - val = s->ar.pm1.cnt.cnt; - break; - case 0x08: - val = acpi_pm_tmr_get(&s->ar); - break; - default: - val = 0; - break; - } - PIIX4_DPRINTF("PM readw port=0x%04x val=0x%04x\n", (unsigned int)addr, val); - *data = val; -} - -static const IORangeOps pm_iorange_ops = { - .read = pm_ioport_read, - .write = pm_ioport_write, -}; - -static void apm_ctrl_changed(uint32_t val, void *arg) -{ - PIIX4PMState *s = arg; - - /* ACPI specs 3.0, 4.7.2.5 */ - acpi_pm1_cnt_update(&s->ar, val == ACPI_ENABLE, val == ACPI_DISABLE); - - if (s->dev.config[0x5b] & (1 << 1)) { - if (s->smi_irq) { - qemu_irq_raise(s->smi_irq); - } - } -} - -static void acpi_dbg_writel(void *opaque, uint32_t addr, uint32_t val) -{ - PIIX4_DPRINTF("ACPI: DBG: 0x%08x\n", val); -} - -static void pm_io_space_update(PIIX4PMState *s) -{ - uint32_t pm_io_base; - - if (s->dev.config[0x80] & 1) { - pm_io_base = le32_to_cpu(*(uint32_t *)(s->dev.config + 0x40)); - pm_io_base &= 0xffc0; - - /* XXX: need to improve memory and ioport allocation */ - PIIX4_DPRINTF("PM: mapping to 0x%x\n", pm_io_base); - iorange_init(&s->ioport, &pm_iorange_ops, pm_io_base, 64); - ioport_register(&s->ioport); - } -} - -static void pm_write_config(PCIDevice *d, - uint32_t address, uint32_t val, int len) -{ - pci_default_write_config(d, address, val, len); - if (range_covers_byte(address, len, 0x80)) - pm_io_space_update((PIIX4PMState *)d); -} - -static void vmstate_pci_status_pre_save(void *opaque) -{ - struct pci_status *pci0_status = opaque; - PIIX4PMState *s = container_of(pci0_status, PIIX4PMState, pci0_status); - - /* We no longer track up, so build a safe value for migrating - * to a version that still does... of course these might get lost - * by an old buggy implementation, but we try. */ - pci0_status->up = s->pci0_slot_device_present & s->pci0_hotplug_enable; -} - -static int vmstate_acpi_post_load(void *opaque, int version_id) -{ - PIIX4PMState *s = opaque; - - pm_io_space_update(s); - return 0; -} - -#define VMSTATE_GPE_ARRAY(_field, _state) \ - { \ - .name = (stringify(_field)), \ - .version_id = 0, \ - .num = GPE_LEN, \ - .info = &vmstate_info_uint16, \ - .size = sizeof(uint16_t), \ - .flags = VMS_ARRAY | VMS_POINTER, \ - .offset = vmstate_offset_pointer(_state, _field, uint8_t), \ - } - -static const VMStateDescription vmstate_gpe = { - .name = "gpe", - .version_id = 1, - .minimum_version_id = 1, - .minimum_version_id_old = 1, - .fields = (VMStateField []) { - VMSTATE_GPE_ARRAY(sts, ACPIGPE), - VMSTATE_GPE_ARRAY(en, ACPIGPE), - VMSTATE_END_OF_LIST() - } -}; - -static const VMStateDescription vmstate_pci_status = { - .name = "pci_status", - .version_id = 1, - .minimum_version_id = 1, - .minimum_version_id_old = 1, - .pre_save = vmstate_pci_status_pre_save, - .fields = (VMStateField []) { - VMSTATE_UINT32(up, struct pci_status), - VMSTATE_UINT32(down, struct pci_status), - VMSTATE_END_OF_LIST() - } -}; - -static const VMStateDescription vmstate_acpi = { - .name = "piix4_pm", - .version_id = 2, - .minimum_version_id = 1, - .minimum_version_id_old = 1, - .post_load = vmstate_acpi_post_load, - .fields = (VMStateField []) { - VMSTATE_PCI_DEVICE(dev, PIIX4PMState), - VMSTATE_UINT16(ar.pm1.evt.sts, PIIX4PMState), - VMSTATE_UINT16(ar.pm1.evt.en, PIIX4PMState), - VMSTATE_UINT16(ar.pm1.cnt.cnt, PIIX4PMState), - VMSTATE_STRUCT(apm, PIIX4PMState, 0, vmstate_apm, APMState), - VMSTATE_TIMER(ar.tmr.timer, PIIX4PMState), - VMSTATE_INT64(ar.tmr.overflow_time, PIIX4PMState), - VMSTATE_STRUCT(ar.gpe, PIIX4PMState, 2, vmstate_gpe, ACPIGPE), - VMSTATE_STRUCT(pci0_status, PIIX4PMState, 2, vmstate_pci_status, - struct pci_status), - VMSTATE_END_OF_LIST() - } -}; - -static void acpi_piix_eject_slot(PIIX4PMState *s, unsigned slots) -{ - BusChild *kid, *next; - BusState *bus = qdev_get_parent_bus(&s->dev.qdev); - int slot = ffs(slots) - 1; - bool slot_free = true; - - /* Mark request as complete */ - s->pci0_status.down &= ~(1U << slot); - - QTAILQ_FOREACH_SAFE(kid, &bus->children, sibling, next) { - DeviceState *qdev = kid->child; - PCIDevice *dev = PCI_DEVICE(qdev); - PCIDeviceClass *pc = PCI_DEVICE_GET_CLASS(dev); - if (PCI_SLOT(dev->devfn) == slot) { - if (pc->no_hotplug) { - slot_free = false; - } else { - qdev_free(qdev); - } - } - } - if (slot_free) { - s->pci0_slot_device_present &= ~(1U << slot); - } -} - -static void piix4_update_hotplug(PIIX4PMState *s) -{ - PCIDevice *dev = &s->dev; - BusState *bus = qdev_get_parent_bus(&dev->qdev); - BusChild *kid, *next; - - /* Execute any pending removes during reset */ - while (s->pci0_status.down) { - acpi_piix_eject_slot(s, s->pci0_status.down); - } - - s->pci0_hotplug_enable = ~0; - s->pci0_slot_device_present = 0; - - QTAILQ_FOREACH_SAFE(kid, &bus->children, sibling, next) { - DeviceState *qdev = kid->child; - PCIDevice *pdev = PCI_DEVICE(qdev); - PCIDeviceClass *pc = PCI_DEVICE_GET_CLASS(pdev); - int slot = PCI_SLOT(pdev->devfn); - - if (pc->no_hotplug) { - s->pci0_hotplug_enable &= ~(1U << slot); - } - - s->pci0_slot_device_present |= (1U << slot); - } -} - -static void piix4_reset(void *opaque) -{ - PIIX4PMState *s = opaque; - uint8_t *pci_conf = s->dev.config; - - pci_conf[0x58] = 0; - pci_conf[0x59] = 0; - pci_conf[0x5a] = 0; - pci_conf[0x5b] = 0; - - pci_conf[0x40] = 0x01; /* PM io base read only bit */ - pci_conf[0x80] = 0; - - if (s->kvm_enabled) { - /* Mark SMM as already inited (until KVM supports SMM). */ - pci_conf[0x5B] = 0x02; - } - piix4_update_hotplug(s); -} - -static void piix4_powerdown(void *opaque, int irq, int power_failing) -{ - PIIX4PMState *s = opaque; - - assert(s != NULL); - acpi_pm1_evt_power_down(&s->ar); -} - -static void piix4_pm_machine_ready(Notifier *n, void *opaque) -{ - PIIX4PMState *s = container_of(n, PIIX4PMState, machine_ready); - uint8_t *pci_conf; - - pci_conf = s->dev.config; - pci_conf[0x5f] = (isa_is_ioport_assigned(0x378) ? 0x80 : 0) | 0x10; - pci_conf[0x63] = 0x60; - pci_conf[0x67] = (isa_is_ioport_assigned(0x3f8) ? 0x08 : 0) | - (isa_is_ioport_assigned(0x2f8) ? 0x90 : 0); - -} - -static int piix4_pm_initfn(PCIDevice *dev) -{ - PIIX4PMState *s = DO_UPCAST(PIIX4PMState, dev, dev); - uint8_t *pci_conf; - - pci_conf = s->dev.config; - pci_conf[0x06] = 0x80; - pci_conf[0x07] = 0x02; - pci_conf[0x09] = 0x00; - pci_conf[0x3d] = 0x01; // interrupt pin 1 - - /* APM */ - apm_init(&s->apm, apm_ctrl_changed, s); - - register_ioport_write(ACPI_DBG_IO_ADDR, 4, 4, acpi_dbg_writel, s); - - if (s->kvm_enabled) { - /* Mark SMM as already inited to prevent SMM from running. KVM does not - * support SMM mode. */ - pci_conf[0x5B] = 0x02; - } - - /* XXX: which specification is used ? The i82731AB has different - mappings */ - pci_conf[0x90] = s->smb_io_base | 1; - pci_conf[0x91] = s->smb_io_base >> 8; - pci_conf[0xd2] = 0x09; - register_ioport_write(s->smb_io_base, 64, 1, smb_ioport_writeb, &s->smb); - register_ioport_read(s->smb_io_base, 64, 1, smb_ioport_readb, &s->smb); - - acpi_pm_tmr_init(&s->ar, pm_tmr_timer); - acpi_gpe_init(&s->ar, GPE_LEN); - - qemu_system_powerdown = *qemu_allocate_irqs(piix4_powerdown, s, 1); - - pm_smbus_init(&s->dev.qdev, &s->smb); - s->machine_ready.notify = piix4_pm_machine_ready; - qemu_add_machine_init_done_notifier(&s->machine_ready); - qemu_register_reset(piix4_reset, s); - piix4_acpi_system_hot_add_init(dev->bus, s); - - return 0; -} - -i2c_bus *piix4_pm_init(PCIBus *bus, int devfn, uint32_t smb_io_base, - qemu_irq sci_irq, qemu_irq smi_irq, - int kvm_enabled, void *fw_cfg) -{ - PCIDevice *dev; - PIIX4PMState *s; - -#if 0 //#if defined(CONFIG_MARU) && defined(__x86_64__) - dev = pci_create(bus, devfn, "MARU_PM"); -#else - dev = pci_create(bus, devfn, "PIIX4_PM"); -#endif - qdev_prop_set_uint32(&dev->qdev, "smb_io_base", smb_io_base); - - s = DO_UPCAST(PIIX4PMState, dev, dev); - s->irq = sci_irq; - acpi_pm1_cnt_init(&s->ar); - s->smi_irq = smi_irq; - s->kvm_enabled = kvm_enabled; - - qdev_init_nofail(&dev->qdev); - - if (fw_cfg) { - uint8_t suspend[6] = {128, 0, 0, 129, 128, 128}; - suspend[3] = 1 | ((!s->disable_s3) << 7); - suspend[4] = s->s4_val | ((!s->disable_s4) << 7); - - fw_cfg_add_file(fw_cfg, "etc/system-states", g_memdup(suspend, 6), 6); - } - - return s->smb.smbus; -} - -static Property piix4_pm_properties[] = { - DEFINE_PROP_UINT32("smb_io_base", PIIX4PMState, smb_io_base, 0), - DEFINE_PROP_UINT8("disable_s3", PIIX4PMState, disable_s3, 0), - DEFINE_PROP_UINT8("disable_s4", PIIX4PMState, disable_s4, 0), - DEFINE_PROP_UINT8("s4_val", PIIX4PMState, s4_val, 2), - DEFINE_PROP_END_OF_LIST(), -}; - -static void piix4_pm_class_init(ObjectClass *klass, void *data) -{ - DeviceClass *dc = DEVICE_CLASS(klass); - PCIDeviceClass *k = PCI_DEVICE_CLASS(klass); - - k->no_hotplug = 1; - k->init = piix4_pm_initfn; - k->config_write = pm_write_config; - k->vendor_id = PCI_VENDOR_ID_INTEL; - k->device_id = PCI_DEVICE_ID_INTEL_82371AB_3; - k->revision = 0x03; - k->class_id = PCI_CLASS_BRIDGE_OTHER; - dc->desc = "PM"; - dc->no_user = 1; - dc->vmsd = &vmstate_acpi; - dc->props = piix4_pm_properties; -} - -static TypeInfo piix4_pm_info = { -#if 0 //#if defined(CONFIG_MARU) && defined(__x86_64__) - .name = "MARU_PM", -#else - .name = "PIIX4_PM", -#endif - .parent = TYPE_PCI_DEVICE, - .instance_size = sizeof(PIIX4PMState), - .class_init = piix4_pm_class_init, -}; - -static void piix4_pm_register_types(void) -{ - type_register_static(&piix4_pm_info); -} - -type_init(piix4_pm_register_types) - -static uint32_t gpe_readb(void *opaque, uint32_t addr) -{ - PIIX4PMState *s = opaque; - uint32_t val = acpi_gpe_ioport_readb(&s->ar, addr); - - PIIX4_DPRINTF("gpe read %x == %x\n", addr, val); - return val; -} - -static void gpe_writeb(void *opaque, uint32_t addr, uint32_t val) -{ - PIIX4PMState *s = opaque; - - acpi_gpe_ioport_writeb(&s->ar, addr, val); - pm_update_sci(s); - - PIIX4_DPRINTF("gpe write %x <== %d\n", addr, val); -} - -static uint32_t pci_up_read(void *opaque, uint32_t addr) -{ - PIIX4PMState *s = opaque; - uint32_t val; - - /* Manufacture an "up" value to cause a device check on any hotplug - * slot with a device. Extra device checks are harmless. */ - val = s->pci0_slot_device_present & s->pci0_hotplug_enable; - - PIIX4_DPRINTF("pci_up_read %x\n", val); - return val; -} - -static uint32_t pci_down_read(void *opaque, uint32_t addr) -{ - PIIX4PMState *s = opaque; - uint32_t val = s->pci0_status.down; - - PIIX4_DPRINTF("pci_down_read %x\n", val); - return val; -} - -static uint32_t pci_features_read(void *opaque, uint32_t addr) -{ - /* No feature defined yet */ - PIIX4_DPRINTF("pci_features_read %x\n", 0); - return 0; -} - -static void pciej_write(void *opaque, uint32_t addr, uint32_t val) -{ - acpi_piix_eject_slot(opaque, val); - - PIIX4_DPRINTF("pciej write %x <== %d\n", addr, val); -} - -static uint32_t pcirmv_read(void *opaque, uint32_t addr) -{ - PIIX4PMState *s = opaque; - - return s->pci0_hotplug_enable; -} - -static int piix4_device_hotplug(DeviceState *qdev, PCIDevice *dev, - PCIHotplugState state); - -static void piix4_acpi_system_hot_add_init(PCIBus *bus, PIIX4PMState *s) -{ - - register_ioport_write(GPE_BASE, GPE_LEN, 1, gpe_writeb, s); - register_ioport_read(GPE_BASE, GPE_LEN, 1, gpe_readb, s); - acpi_gpe_blk(&s->ar, GPE_BASE); - - register_ioport_read(PCI_UP_BASE, 4, 4, pci_up_read, s); - register_ioport_read(PCI_DOWN_BASE, 4, 4, pci_down_read, s); - - register_ioport_write(PCI_EJ_BASE, 4, 4, pciej_write, s); - register_ioport_read(PCI_EJ_BASE, 4, 4, pci_features_read, s); - - register_ioport_read(PCI_RMV_BASE, 4, 4, pcirmv_read, s); - - pci_bus_hotplug(bus, piix4_device_hotplug, &s->dev.qdev); -} - -static void enable_device(PIIX4PMState *s, int slot) -{ - s->ar.gpe.sts[0] |= PIIX4_PCI_HOTPLUG_STATUS; - s->pci0_slot_device_present |= (1U << slot); -} - -static void disable_device(PIIX4PMState *s, int slot) -{ - s->ar.gpe.sts[0] |= PIIX4_PCI_HOTPLUG_STATUS; - s->pci0_status.down |= (1U << slot); -} - -static int piix4_device_hotplug(DeviceState *qdev, PCIDevice *dev, - PCIHotplugState state) -{ - int slot = PCI_SLOT(dev->devfn); - PIIX4PMState *s = DO_UPCAST(PIIX4PMState, dev, - PCI_DEVICE(qdev)); - - /* Don't send event when device is enabled during qemu machine creation: - * it is present on boot, no hotplug event is necessary. We do send an - * event when the device is disabled later. */ - if (state == PCI_COLDPLUG_ENABLED) { - s->pci0_slot_device_present |= (1U << slot); - return 0; - } - - if (state == PCI_HOTPLUG_ENABLED) { - enable_device(s, slot); - } else { - disable_device(s, slot); - } - - pm_update_sci(s); - - return 0; -} diff --git a/hw/apic_common.c b/hw/apic_common.c deleted file mode 100644 index 4db9e83..0000000 --- a/hw/apic_common.c +++ /dev/null @@ -1,405 +0,0 @@ -/* - * APIC support - common bits of emulated and KVM kernel model - * - * Copyright (c) 2004-2005 Fabrice Bellard - * Copyright (c) 2011 Jan Kiszka, Siemens AG - * - * 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 - */ -#include "apic.h" -#include "apic_internal.h" -#include "trace.h" -#include "kvm.h" - -static int apic_irq_delivered; -bool apic_report_tpr_access; - -void cpu_set_apic_base(DeviceState *d, uint64_t val) -{ - trace_cpu_set_apic_base(val); - - if (d) { - APICCommonState *s = APIC_COMMON(d); - APICCommonClass *info = APIC_COMMON_GET_CLASS(s); - info->set_base(s, val); - } -} - -uint64_t cpu_get_apic_base(DeviceState *d) -{ - if (d) { - APICCommonState *s = APIC_COMMON(d); - trace_cpu_get_apic_base((uint64_t)s->apicbase); - return s->apicbase; - } else { - trace_cpu_get_apic_base(MSR_IA32_APICBASE_BSP); - return MSR_IA32_APICBASE_BSP; - } -} - -void cpu_set_apic_tpr(DeviceState *d, uint8_t val) -{ - APICCommonState *s; - APICCommonClass *info; - - if (!d) { - return; - } - - s = APIC_COMMON(d); - info = APIC_COMMON_GET_CLASS(s); - - info->set_tpr(s, val); -} - -uint8_t cpu_get_apic_tpr(DeviceState *d) -{ - APICCommonState *s; - APICCommonClass *info; - - if (!d) { - return 0; - } - - s = APIC_COMMON(d); - info = APIC_COMMON_GET_CLASS(s); - - return info->get_tpr(s); -} - -void apic_enable_tpr_access_reporting(DeviceState *d, bool enable) -{ - APICCommonState *s = DO_UPCAST(APICCommonState, busdev.qdev, d); - APICCommonClass *info = APIC_COMMON_GET_CLASS(s); - - apic_report_tpr_access = enable; - if (info->enable_tpr_reporting) { - info->enable_tpr_reporting(s, enable); - } -} - -void apic_enable_vapic(DeviceState *d, target_phys_addr_t paddr) -{ - APICCommonState *s = DO_UPCAST(APICCommonState, busdev.qdev, d); - APICCommonClass *info = APIC_COMMON_GET_CLASS(s); - - s->vapic_paddr = paddr; - info->vapic_base_update(s); -} - -void apic_handle_tpr_access_report(DeviceState *d, target_ulong ip, - TPRAccess access) -{ - APICCommonState *s = DO_UPCAST(APICCommonState, busdev.qdev, d); - - vapic_report_tpr_access(s->vapic, s->cpu_env, ip, access); -} - -void apic_report_irq_delivered(int delivered) -{ - apic_irq_delivered += delivered; - - trace_apic_report_irq_delivered(apic_irq_delivered); -} - -void apic_reset_irq_delivered(void) -{ - trace_apic_reset_irq_delivered(apic_irq_delivered); - - apic_irq_delivered = 0; -} - -int apic_get_irq_delivered(void) -{ - trace_apic_get_irq_delivered(apic_irq_delivered); - - return apic_irq_delivered; -} - -void apic_deliver_nmi(DeviceState *d) -{ - APICCommonState *s = APIC_COMMON(d); - APICCommonClass *info = APIC_COMMON_GET_CLASS(s); - - info->external_nmi(s); -} - -bool apic_next_timer(APICCommonState *s, int64_t current_time) -{ - int64_t d; - - /* We need to store the timer state separately to support APIC - * implementations that maintain a non-QEMU timer, e.g. inside the - * host kernel. This open-coded state allows us to migrate between - * both models. */ - s->timer_expiry = -1; - - if (s->lvt[APIC_LVT_TIMER] & APIC_LVT_MASKED) { - return false; - } - - d = (current_time - s->initial_count_load_time) >> s->count_shift; - - if (s->lvt[APIC_LVT_TIMER] & APIC_LVT_TIMER_PERIODIC) { - if (!s->initial_count) { - return false; - } - d = ((d / ((uint64_t)s->initial_count + 1)) + 1) * - ((uint64_t)s->initial_count + 1); - } else { - if (d >= s->initial_count) { - return false; - } - d = (uint64_t)s->initial_count + 1; - } - s->next_time = s->initial_count_load_time + (d << s->count_shift); - s->timer_expiry = s->next_time; - return true; -} - -void apic_init_reset(DeviceState *d) -{ - APICCommonState *s = DO_UPCAST(APICCommonState, busdev.qdev, d); - int i; - - if (!s) { - return; - } - s->tpr = 0; - s->spurious_vec = 0xff; - s->log_dest = 0; - s->dest_mode = 0xf; - memset(s->isr, 0, sizeof(s->isr)); - memset(s->tmr, 0, sizeof(s->tmr)); - memset(s->irr, 0, sizeof(s->irr)); - for (i = 0; i < APIC_LVT_NB; i++) { - s->lvt[i] = APIC_LVT_MASKED; - } - s->esr = 0; - memset(s->icr, 0, sizeof(s->icr)); - s->divide_conf = 0; - s->count_shift = 0; - s->initial_count = 0; - s->initial_count_load_time = 0; - s->next_time = 0; - s->wait_for_sipi = 1; - - if (s->timer) { - qemu_del_timer(s->timer); - } - s->timer_expiry = -1; -} - -void apic_designate_bsp(DeviceState *d) -{ - if (d == NULL) { - return; - } - - APICCommonState *s = APIC_COMMON(d); - s->apicbase |= MSR_IA32_APICBASE_BSP; -} - -static void apic_reset_common(DeviceState *d) -{ - APICCommonState *s = DO_UPCAST(APICCommonState, busdev.qdev, d); - APICCommonClass *info = APIC_COMMON_GET_CLASS(s); - bool bsp; - - bsp = cpu_is_bsp(x86_env_get_cpu(s->cpu_env)); - s->apicbase = 0xfee00000 | - (bsp ? MSR_IA32_APICBASE_BSP : 0) | MSR_IA32_APICBASE_ENABLE; - - s->vapic_paddr = 0; - info->vapic_base_update(s); - - apic_init_reset(d); - - if (bsp) { - /* - * LINT0 delivery mode on CPU #0 is set to ExtInt at initialization - * time typically by BIOS, so PIC interrupt can be delivered to the - * processor when local APIC is enabled. - */ - s->lvt[APIC_LVT_LINT0] = 0x700; - } -} - -/* This function is only used for old state version 1 and 2 */ -static int apic_load_old(QEMUFile *f, void *opaque, int version_id) -{ - APICCommonState *s = opaque; - APICCommonClass *info = APIC_COMMON_GET_CLASS(s); - int i; - - if (version_id > 2) { - return -EINVAL; - } - - /* XXX: what if the base changes? (registered memory regions) */ - qemu_get_be32s(f, &s->apicbase); - qemu_get_8s(f, &s->id); - qemu_get_8s(f, &s->arb_id); - qemu_get_8s(f, &s->tpr); - qemu_get_be32s(f, &s->spurious_vec); - qemu_get_8s(f, &s->log_dest); - qemu_get_8s(f, &s->dest_mode); - for (i = 0; i < 8; i++) { - qemu_get_be32s(f, &s->isr[i]); - qemu_get_be32s(f, &s->tmr[i]); - qemu_get_be32s(f, &s->irr[i]); - } - for (i = 0; i < APIC_LVT_NB; i++) { - qemu_get_be32s(f, &s->lvt[i]); - } - qemu_get_be32s(f, &s->esr); - qemu_get_be32s(f, &s->icr[0]); - qemu_get_be32s(f, &s->icr[1]); - qemu_get_be32s(f, &s->divide_conf); - s->count_shift = qemu_get_be32(f); - qemu_get_be32s(f, &s->initial_count); - s->initial_count_load_time = qemu_get_be64(f); - s->next_time = qemu_get_be64(f); - - if (version_id >= 2) { - s->timer_expiry = qemu_get_be64(f); - } - - if (info->post_load) { - info->post_load(s); - } - return 0; -} - -static int apic_init_common(SysBusDevice *dev) -{ - APICCommonState *s = APIC_COMMON(dev); - APICCommonClass *info; - static DeviceState *vapic; - static int apic_no; - - if (apic_no >= MAX_APICS) { - return -1; - } - s->idx = apic_no++; - - info = APIC_COMMON_GET_CLASS(s); - info->init(s); - - sysbus_init_mmio(dev, &s->io_memory); - - #ifndef CONFIG_MARU - /* Note: We need at least 1M to map the VAPIC option ROM */ - if (!vapic && s->vapic_control & VAPIC_ENABLE_MASK && - ram_size >= 1024 * 1024) { - vapic = sysbus_create_simple("kvmvapic", -1, NULL); - } - #endif - s->vapic = vapic; - if (apic_report_tpr_access && info->enable_tpr_reporting) { - info->enable_tpr_reporting(s, true); - } - - return 0; -} - -static void apic_dispatch_pre_save(void *opaque) -{ - APICCommonState *s = APIC_COMMON(opaque); - APICCommonClass *info = APIC_COMMON_GET_CLASS(s); - - if (info->pre_save) { - info->pre_save(s); - } -} - -static int apic_dispatch_post_load(void *opaque, int version_id) -{ - APICCommonState *s = APIC_COMMON(opaque); - APICCommonClass *info = APIC_COMMON_GET_CLASS(s); - - if (info->post_load) { - info->post_load(s); - } - return 0; -} - -static const VMStateDescription vmstate_apic_common = { - .name = "apic", - .version_id = 3, - .minimum_version_id = 3, - .minimum_version_id_old = 1, - .load_state_old = apic_load_old, - .pre_save = apic_dispatch_pre_save, - .post_load = apic_dispatch_post_load, - .fields = (VMStateField[]) { - VMSTATE_UINT32(apicbase, APICCommonState), - VMSTATE_UINT8(id, APICCommonState), - VMSTATE_UINT8(arb_id, APICCommonState), - VMSTATE_UINT8(tpr, APICCommonState), - VMSTATE_UINT32(spurious_vec, APICCommonState), - VMSTATE_UINT8(log_dest, APICCommonState), - VMSTATE_UINT8(dest_mode, APICCommonState), - VMSTATE_UINT32_ARRAY(isr, APICCommonState, 8), - VMSTATE_UINT32_ARRAY(tmr, APICCommonState, 8), - VMSTATE_UINT32_ARRAY(irr, APICCommonState, 8), - VMSTATE_UINT32_ARRAY(lvt, APICCommonState, APIC_LVT_NB), - VMSTATE_UINT32(esr, APICCommonState), - VMSTATE_UINT32_ARRAY(icr, APICCommonState, 2), - VMSTATE_UINT32(divide_conf, APICCommonState), - VMSTATE_INT32(count_shift, APICCommonState), - VMSTATE_UINT32(initial_count, APICCommonState), - VMSTATE_INT64(initial_count_load_time, APICCommonState), - VMSTATE_INT64(next_time, APICCommonState), - VMSTATE_INT64(timer_expiry, - APICCommonState), /* open-coded timer state */ - VMSTATE_END_OF_LIST() - } -}; - -static Property apic_properties_common[] = { - DEFINE_PROP_UINT8("id", APICCommonState, id, -1), - DEFINE_PROP_PTR("cpu_env", APICCommonState, cpu_env), - DEFINE_PROP_BIT("vapic", APICCommonState, vapic_control, VAPIC_ENABLE_BIT, - true), - DEFINE_PROP_END_OF_LIST(), -}; - -static void apic_common_class_init(ObjectClass *klass, void *data) -{ - SysBusDeviceClass *sc = SYS_BUS_DEVICE_CLASS(klass); - DeviceClass *dc = DEVICE_CLASS(klass); - - dc->vmsd = &vmstate_apic_common; - dc->reset = apic_reset_common; - dc->no_user = 1; - dc->props = apic_properties_common; - sc->init = apic_init_common; -} - -static TypeInfo apic_common_type = { - .name = TYPE_APIC_COMMON, - .parent = TYPE_SYS_BUS_DEVICE, - .instance_size = sizeof(APICCommonState), - .class_size = sizeof(APICCommonClass), - .class_init = apic_common_class_init, - .abstract = true, -}; - -static void register_types(void) -{ - type_register_static(&apic_common_type); -} - -type_init(register_types) diff --git a/hw/block/pc_sysfw.c b/hw/block/pc_sysfw.c index 4f17668..e3b4c02 100644 --- a/hw/block/pc_sysfw.c +++ b/hw/block/pc_sysfw.c @@ -34,6 +34,10 @@ #include "hw/block/flash.h" #include "sysemu/kvm.h" +#ifdef CONFIG_MARU +#include "../../tizen/src/maru_err_table.h" +#endif + #define BIOS_FILENAME "bios.bin" typedef struct PcSysFwDevice { @@ -139,6 +143,10 @@ static void pc_system_flash_init(MemoryRegion *rom_memory, pc_isa_bios_init(rom_memory, flash_mem, size); } +#ifdef CONFIG_MARU +extern char* qemu_get_data_dir(void); +#endif + static void old_pc_system_rom_init(MemoryRegion *rom_memory) { char *filename; @@ -168,6 +176,28 @@ static void old_pc_system_rom_init(MemoryRegion *rom_memory) if (ret != 0) { bios_error: fprintf(stderr, "qemu: could not load PC BIOS '%s'\n", bios_name); +#ifdef CONFIG_MARU + char *error_msg = NULL; + const char *path = qemu_get_data_dir(); + char *bios_path = NULL; + int bios_len = 0; + + bios_len = strlen(path) + strlen("/") + strlen(bios_name) + 1; + bios_path = g_malloc(bios_len * sizeof(char)); + if (!bios_path) { + fprintf(stderr, "qemu: failed to allocate memory\n"); + } + snprintf(bios_path, bios_len, "%s/%s", path, bios_name); + error_msg = maru_convert_path(error_msg, bios_path); + maru_register_exit_msg(MARU_EXIT_BIOS_FILE_EXCEPTION, error_msg); + + if (bios_path) { + g_free(bios_path); + } + if (error_msg) { + g_free(error_msg); + } +#endif exit(1); } if (filename) { diff --git a/hw/display/vga-pci.c b/hw/display/vga-pci.c index cea8db7..a3b1cd8 100644 --- a/hw/display/vga-pci.c +++ b/hw/display/vga-pci.c @@ -191,7 +191,11 @@ static void vga_class_init(ObjectClass *klass, void *data) k->no_hotplug = 1; k->init = pci_std_vga_initfn; +#ifdef CONFIG_MARU + k->romfile = "vgabios-maruvga.bin"; +#else k->romfile = "vgabios-stdvga.bin"; +#endif k->vendor_id = PCI_VENDOR_ID_QEMU; k->device_id = PCI_DEVICE_ID_QEMU_VGA; k->class_id = PCI_CLASS_DISPLAY_VGA; @@ -200,7 +204,11 @@ static void vga_class_init(ObjectClass *klass, void *data) } static const TypeInfo vga_info = { +#ifdef CONFIG_MARU + .name = "MARU_VGA", +#else .name = "VGA", +#endif .parent = TYPE_PCI_DEVICE, .instance_size = sizeof(PCIVGAState), .class_init = vga_class_init, diff --git a/hw/i386/pc.c b/hw/i386/pc.c index e2c44f8..e84c38d 100644 --- a/hw/i386/pc.c +++ b/hw/i386/pc.c @@ -56,6 +56,11 @@ #include "hw/cpu/icc_bus.h" #include "hw/boards.h" +#ifdef CONFIG_MARU +#include "../../tizen/src/hw/maru_overlay.h" +#include "../../tizen/src/hw/maru_brightness.h" +#include "../../tizen/src/maru_err_table.h" +#endif /* debug PC/ISA interrupts */ //#define DEBUG_IRQ @@ -698,6 +703,16 @@ static void load_linux(void *fw_cfg, MIN(ARRAY_SIZE(header), kernel_size)) { fprintf(stderr, "qemu: could not load kernel '%s': %s\n", kernel_filename, strerror(errno)); + +#ifdef CONFIG_MARU + char *error_msg = NULL; + + error_msg = maru_convert_path(error_msg, kernel_filename); + maru_register_exit_msg(MARU_EXIT_KERNEL_FILE_EXCEPTION, error_msg); + if (error_msg) { + g_free(error_msg); + } +#endif exit(1); } @@ -1091,6 +1106,12 @@ DeviceState *pc_vga_init(ISABus *isa_bus, PCIBus *pci_bus) if (pci_bus) { PCIDevice *pcidev = pci_vga_init(pci_bus); dev = pcidev ? &pcidev->qdev : NULL; +#ifdef CONFIG_MARU + if (maru_vga_enabled) { + pci_maru_overlay_init(pci_bus); + pci_maru_brightness_init(pci_bus); + } +#endif } else if (isa_bus) { ISADevice *isadev = isa_vga_init(isa_bus); dev = isadev ? &isadev->qdev : NULL; diff --git a/hw/input/pl050.c b/hw/input/pl050.c index 7dd8a59..ae82eb6 100644 --- a/hw/input/pl050.c +++ b/hw/input/pl050.c @@ -121,6 +121,11 @@ static void pl050_write(void *opaque, hwaddr offset, break; case 3: /* KMICLKDIV */ s->clk = value; +#ifdef CONFIG_MARU + if (!s->is_mouse) { + ps2_keyboard_set_translation(s->dev, 1); + } +#endif return; default: qemu_log_mask(LOG_GUEST_ERROR, diff --git a/hw/input/ps2.c b/hw/input/ps2.c index 3412079..d46d61b 100644 --- a/hw/input/ps2.c +++ b/hw/input/ps2.c @@ -26,6 +26,11 @@ #include "ui/console.h" #include "sysemu/sysemu.h" +#ifdef CONFIG_MARU +/* to guarantee safe serialization of input event by Munkyu Im */ +#include "qemu/thread.h" +static QemuMutex mutex; +#endif /* debug PC keyboard */ //#define DEBUG_KBD @@ -379,7 +384,14 @@ static void ps2_mouse_event(void *opaque, for(;;) { /* if not remote, send event. Multiple events are sent if too big deltas */ +#ifdef CONFIG_MARU +/* to guarantee safe serialization of input event by Munkyu Im */ + qemu_mutex_lock(&mutex); + ps2_mouse_send_packet(s); + qemu_mutex_unlock(&mutex); +#else ps2_mouse_send_packet(s); +#endif if (s->mouse_dx == 0 && s->mouse_dy == 0 && s->mouse_dz == 0) break; } @@ -658,7 +670,11 @@ void *ps2_kbd_init(void (*update_irq)(void *, int), void *update_arg) s->common.update_arg = update_arg; s->scancode_set = 2; vmstate_register(NULL, 0, &vmstate_ps2_keyboard, s); +#ifdef CONFIG_MARU + qemu_add_ps2kbd_event_handler(ps2_put_keycode, s); +#else qemu_add_kbd_event_handler(ps2_put_keycode, s); +#endif qemu_register_reset(ps2_kbd_reset, s); return s; } @@ -672,5 +688,9 @@ void *ps2_mouse_init(void (*update_irq)(void *, int), void *update_arg) vmstate_register(NULL, 0, &vmstate_ps2_mouse, s); qemu_add_mouse_event_handler(ps2_mouse_event, s, 0, "QEMU PS/2 Mouse"); qemu_register_reset(ps2_mouse_reset, s); +#ifdef CONFIG_MARU + /* to guarantee safe serialization of input event by Munkyu Im */ + qemu_mutex_init(&mutex); +#endif return s; } diff --git a/hw/intc/apic_common.c b/hw/intc/apic_common.c index b03e904..b7c8efd 100644 --- a/hw/intc/apic_common.c +++ b/hw/intc/apic_common.c @@ -305,11 +305,13 @@ static int apic_init_common(ICCDevice *dev) mmio_registered = true; } +#ifndef CONFIG_MARU /* Note: We need at least 1M to map the VAPIC option ROM */ if (!vapic && s->vapic_control & VAPIC_ENABLE_MASK && ram_size >= 1024 * 1024) { vapic = sysbus_create_simple("kvmvapic", -1, NULL); } +#endif s->vapic = vapic; if (apic_report_tpr_access && info->enable_tpr_reporting) { info->enable_tpr_reporting(s, true); diff --git a/hw/pc.c b/hw/pc.c deleted file mode 100644 index 12642d8..0000000 --- a/hw/pc.c +++ /dev/null @@ -1,1191 +0,0 @@ -/* - * QEMU PC System Emulator - * - * Copyright (c) 2003-2004 Fabrice Bellard - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -#include "hw.h" -#include "pc.h" -#include "apic.h" -#include "fdc.h" -#include "ide.h" -#include "pci.h" -#include "vmware_vga.h" -#include "monitor.h" -#include "fw_cfg.h" -#include "hpet_emul.h" -#include "smbios.h" -#include "loader.h" -#include "elf.h" -#include "multiboot.h" -#include "mc146818rtc.h" -#include "i8254.h" -#include "pcspk.h" -#include "msi.h" -#include "sysbus.h" -#include "sysemu.h" -#include "kvm.h" -#include "kvm_i386.h" -#include "xen.h" -#include "blockdev.h" -#include "hw/block-common.h" -#include "ui/qemu-spice.h" -#include "memory.h" -#include "exec-memory.h" -#include "arch_init.h" -#include "bitmap.h" -#include "vga-pci.h" - -#ifdef CONFIG_MARU -#include "../tizen/src/hw/maru_overlay.h" -#include "../tizen/src/hw/maru_brightness.h" -#include "../tizen/src/maru_err_table.h" -#endif - -/* output Bochs bios info messages */ -//#define DEBUG_BIOS - -/* debug PC/ISA interrupts */ -//#define DEBUG_IRQ - -#ifdef DEBUG_IRQ -#define DPRINTF(fmt, ...) \ - do { printf("CPUIRQ: " fmt , ## __VA_ARGS__); } while (0) -#else -#define DPRINTF(fmt, ...) -#endif - -/* Leave a chunk of memory at the top of RAM for the BIOS ACPI tables. */ -#define ACPI_DATA_SIZE 0x10000 -#define BIOS_CFG_IOPORT 0x510 -#define FW_CFG_ACPI_TABLES (FW_CFG_ARCH_LOCAL + 0) -#define FW_CFG_SMBIOS_ENTRIES (FW_CFG_ARCH_LOCAL + 1) -#define FW_CFG_IRQ0_OVERRIDE (FW_CFG_ARCH_LOCAL + 2) -#define FW_CFG_E820_TABLE (FW_CFG_ARCH_LOCAL + 3) -#define FW_CFG_HPET (FW_CFG_ARCH_LOCAL + 4) - -#define MSI_ADDR_BASE 0xfee00000 - -#define E820_NR_ENTRIES 16 - -struct e820_entry { - uint64_t address; - uint64_t length; - uint32_t type; -} QEMU_PACKED __attribute((__aligned__(4))); - -struct e820_table { - uint32_t count; - struct e820_entry entry[E820_NR_ENTRIES]; -} QEMU_PACKED __attribute((__aligned__(4))); - -static struct e820_table e820_table; -struct hpet_fw_config hpet_cfg = {.count = UINT8_MAX}; - -void gsi_handler(void *opaque, int n, int level) -{ - GSIState *s = opaque; - - DPRINTF("pc: %s GSI %d\n", level ? "raising" : "lowering", n); - if (n < ISA_NUM_IRQS) { - qemu_set_irq(s->i8259_irq[n], level); - } - qemu_set_irq(s->ioapic_irq[n], level); -} - -static void ioport80_write(void *opaque, uint32_t addr, uint32_t data) -{ -} - -/* MSDOS compatibility mode FPU exception support */ -static qemu_irq ferr_irq; - -void pc_register_ferr_irq(qemu_irq irq) -{ - ferr_irq = irq; -} - -/* XXX: add IGNNE support */ -void cpu_set_ferr(CPUX86State *s) -{ - qemu_irq_raise(ferr_irq); -} - -static void ioportF0_write(void *opaque, uint32_t addr, uint32_t data) -{ - qemu_irq_lower(ferr_irq); -} - -/* TSC handling */ -uint64_t cpu_get_tsc(CPUX86State *env) -{ - return cpu_get_ticks(); -} - -/* SMM support */ - -static cpu_set_smm_t smm_set; -static void *smm_arg; - -void cpu_smm_register(cpu_set_smm_t callback, void *arg) -{ - assert(smm_set == NULL); - assert(smm_arg == NULL); - smm_set = callback; - smm_arg = arg; -} - -void cpu_smm_update(CPUX86State *env) -{ - if (smm_set && smm_arg && env == first_cpu) - smm_set(!!(env->hflags & HF_SMM_MASK), smm_arg); -} - - -/* IRQ handling */ -int cpu_get_pic_interrupt(CPUX86State *env) -{ - int intno; - - intno = apic_get_interrupt(env->apic_state); - if (intno >= 0) { - return intno; - } - /* read the irq from the PIC */ - if (!apic_accept_pic_intr(env->apic_state)) { - return -1; - } - - intno = pic_read_irq(isa_pic); - return intno; -} - -static void pic_irq_request(void *opaque, int irq, int level) -{ - CPUX86State *env = first_cpu; - - DPRINTF("pic_irqs: %s irq %d\n", level? "raise" : "lower", irq); - if (env->apic_state) { - while (env) { - if (apic_accept_pic_intr(env->apic_state)) { - apic_deliver_pic_intr(env->apic_state, level); - } - env = env->next_cpu; - } - } else { - if (level) - cpu_interrupt(env, CPU_INTERRUPT_HARD); - else - cpu_reset_interrupt(env, CPU_INTERRUPT_HARD); - } -} - -/* PC cmos mappings */ - -#define REG_EQUIPMENT_BYTE 0x14 - -static int cmos_get_fd_drive_type(FDriveType fd0) -{ - int val; - - switch (fd0) { - case FDRIVE_DRV_144: - /* 1.44 Mb 3"5 drive */ - val = 4; - break; - case FDRIVE_DRV_288: - /* 2.88 Mb 3"5 drive */ - val = 5; - break; - case FDRIVE_DRV_120: - /* 1.2 Mb 5"5 drive */ - val = 2; - break; - case FDRIVE_DRV_NONE: - default: - val = 0; - break; - } - return val; -} - -static void cmos_init_hd(ISADevice *s, int type_ofs, int info_ofs, - int16_t cylinders, int8_t heads, int8_t sectors) -{ - rtc_set_memory(s, type_ofs, 47); - rtc_set_memory(s, info_ofs, cylinders); - rtc_set_memory(s, info_ofs + 1, cylinders >> 8); - rtc_set_memory(s, info_ofs + 2, heads); - rtc_set_memory(s, info_ofs + 3, 0xff); - rtc_set_memory(s, info_ofs + 4, 0xff); - rtc_set_memory(s, info_ofs + 5, 0xc0 | ((heads > 8) << 3)); - rtc_set_memory(s, info_ofs + 6, cylinders); - rtc_set_memory(s, info_ofs + 7, cylinders >> 8); - rtc_set_memory(s, info_ofs + 8, sectors); -} - -/* convert boot_device letter to something recognizable by the bios */ -static int boot_device2nibble(char boot_device) -{ - switch(boot_device) { - case 'a': - case 'b': - return 0x01; /* floppy boot */ - case 'c': - return 0x02; /* hard drive boot */ - case 'd': - return 0x03; /* CD-ROM boot */ - case 'n': - return 0x04; /* Network boot */ - } - return 0; -} - -static int set_boot_dev(ISADevice *s, const char *boot_device, int fd_bootchk) -{ -#define PC_MAX_BOOT_DEVICES 3 - int nbds, bds[3] = { 0, }; - int i; - - nbds = strlen(boot_device); - if (nbds > PC_MAX_BOOT_DEVICES) { - error_report("Too many boot devices for PC"); - return(1); - } - for (i = 0; i < nbds; i++) { - bds[i] = boot_device2nibble(boot_device[i]); - if (bds[i] == 0) { - error_report("Invalid boot device for PC: '%c'", - boot_device[i]); - return(1); - } - } - rtc_set_memory(s, 0x3d, (bds[1] << 4) | bds[0]); - rtc_set_memory(s, 0x38, (bds[2] << 4) | (fd_bootchk ? 0x0 : 0x1)); - return(0); -} - -static int pc_boot_set(void *opaque, const char *boot_device) -{ - return set_boot_dev(opaque, boot_device, 0); -} - -typedef struct pc_cmos_init_late_arg { - ISADevice *rtc_state; - BusState *idebus[2]; -} pc_cmos_init_late_arg; - -static void pc_cmos_init_late(void *opaque) -{ - pc_cmos_init_late_arg *arg = opaque; - ISADevice *s = arg->rtc_state; - int16_t cylinders; - int8_t heads, sectors; - int val; - int i, trans; - - val = 0; - if (ide_get_geometry(arg->idebus[0], 0, - &cylinders, &heads, §ors) >= 0) { - cmos_init_hd(s, 0x19, 0x1b, cylinders, heads, sectors); - val |= 0xf0; - } - if (ide_get_geometry(arg->idebus[0], 1, - &cylinders, &heads, §ors) >= 0) { - cmos_init_hd(s, 0x1a, 0x24, cylinders, heads, sectors); - val |= 0x0f; - } - rtc_set_memory(s, 0x12, val); - - val = 0; - for (i = 0; i < 4; i++) { - /* NOTE: ide_get_geometry() returns the physical - geometry. It is always such that: 1 <= sects <= 63, 1 - <= heads <= 16, 1 <= cylinders <= 16383. The BIOS - geometry can be different if a translation is done. */ - if (ide_get_geometry(arg->idebus[i / 2], i % 2, - &cylinders, &heads, §ors) >= 0) { - trans = ide_get_bios_chs_trans(arg->idebus[i / 2], i % 2) - 1; - assert((trans & ~3) == 0); - val |= trans << (i * 2); - } - } - rtc_set_memory(s, 0x39, val); - - qemu_unregister_reset(pc_cmos_init_late, opaque); -} - -void pc_cmos_init(ram_addr_t ram_size, ram_addr_t above_4g_mem_size, - const char *boot_device, - ISADevice *floppy, BusState *idebus0, BusState *idebus1, - ISADevice *s) -{ - int val, nb, i; - FDriveType fd_type[2] = { FDRIVE_DRV_NONE, FDRIVE_DRV_NONE }; - static pc_cmos_init_late_arg arg; - - /* various important CMOS locations needed by PC/Bochs bios */ - - /* memory size */ - /* base memory (first MiB) */ - val = MIN(ram_size / 1024, 640); - rtc_set_memory(s, 0x15, val); - rtc_set_memory(s, 0x16, val >> 8); - /* extended memory (next 64MiB) */ - if (ram_size > 1024 * 1024) { - val = (ram_size - 1024 * 1024) / 1024; - } else { - val = 0; - } - if (val > 65535) - val = 65535; - rtc_set_memory(s, 0x17, val); - rtc_set_memory(s, 0x18, val >> 8); - rtc_set_memory(s, 0x30, val); - rtc_set_memory(s, 0x31, val >> 8); - /* memory between 16MiB and 4GiB */ - if (ram_size > 16 * 1024 * 1024) { - val = (ram_size - 16 * 1024 * 1024) / 65536; - } else { - val = 0; - } - if (val > 65535) - val = 65535; - rtc_set_memory(s, 0x34, val); - rtc_set_memory(s, 0x35, val >> 8); - /* memory above 4GiB */ - val = above_4g_mem_size / 65536; - rtc_set_memory(s, 0x5b, val); - rtc_set_memory(s, 0x5c, val >> 8); - rtc_set_memory(s, 0x5d, val >> 16); - - /* set the number of CPU */ - rtc_set_memory(s, 0x5f, smp_cpus - 1); - - /* set boot devices, and disable floppy signature check if requested */ - if (set_boot_dev(s, boot_device, fd_bootchk)) { - exit(1); - } - - /* floppy type */ - if (floppy) { - for (i = 0; i < 2; i++) { - fd_type[i] = isa_fdc_get_drive_type(floppy, i); - } - } - val = (cmos_get_fd_drive_type(fd_type[0]) << 4) | - cmos_get_fd_drive_type(fd_type[1]); - rtc_set_memory(s, 0x10, val); - - val = 0; - nb = 0; - if (fd_type[0] < FDRIVE_DRV_NONE) { - nb++; - } - if (fd_type[1] < FDRIVE_DRV_NONE) { - nb++; - } - switch (nb) { - case 0: - break; - case 1: - val |= 0x01; /* 1 drive, ready for boot */ - break; - case 2: - val |= 0x41; /* 2 drives, ready for boot */ - break; - } - val |= 0x02; /* FPU is there */ - val |= 0x04; /* PS/2 mouse installed */ - rtc_set_memory(s, REG_EQUIPMENT_BYTE, val); - - /* hard drives */ - arg.rtc_state = s; - arg.idebus[0] = idebus0; - arg.idebus[1] = idebus1; - qemu_register_reset(pc_cmos_init_late, &arg); -} - -/* port 92 stuff: could be split off */ -typedef struct Port92State { - ISADevice dev; - MemoryRegion io; - uint8_t outport; - qemu_irq *a20_out; -} Port92State; - -static void port92_write(void *opaque, uint32_t addr, uint32_t val) -{ - Port92State *s = opaque; - - DPRINTF("port92: write 0x%02x\n", val); - s->outport = val; - qemu_set_irq(*s->a20_out, (val >> 1) & 1); - if (val & 1) { - qemu_system_reset_request(); - } -} - -static uint32_t port92_read(void *opaque, uint32_t addr) -{ - Port92State *s = opaque; - uint32_t ret; - - ret = s->outport; - DPRINTF("port92: read 0x%02x\n", ret); - return ret; -} - -static void port92_init(ISADevice *dev, qemu_irq *a20_out) -{ - Port92State *s = DO_UPCAST(Port92State, dev, dev); - - s->a20_out = a20_out; -} - -static const VMStateDescription vmstate_port92_isa = { - .name = "port92", - .version_id = 1, - .minimum_version_id = 1, - .minimum_version_id_old = 1, - .fields = (VMStateField []) { - VMSTATE_UINT8(outport, Port92State), - VMSTATE_END_OF_LIST() - } -}; - -static void port92_reset(DeviceState *d) -{ - Port92State *s = container_of(d, Port92State, dev.qdev); - - s->outport &= ~1; -} - -static const MemoryRegionPortio port92_portio[] = { - { 0, 1, 1, .read = port92_read, .write = port92_write }, - PORTIO_END_OF_LIST(), -}; - -static const MemoryRegionOps port92_ops = { - .old_portio = port92_portio -}; - -static int port92_initfn(ISADevice *dev) -{ - Port92State *s = DO_UPCAST(Port92State, dev, dev); - - memory_region_init_io(&s->io, &port92_ops, s, "port92", 1); - isa_register_ioport(dev, &s->io, 0x92); - - s->outport = 0; - return 0; -} - -static void port92_class_initfn(ObjectClass *klass, void *data) -{ - DeviceClass *dc = DEVICE_CLASS(klass); - ISADeviceClass *ic = ISA_DEVICE_CLASS(klass); - ic->init = port92_initfn; - dc->no_user = 1; - dc->reset = port92_reset; - dc->vmsd = &vmstate_port92_isa; -} - -static TypeInfo port92_info = { - .name = "port92", - .parent = TYPE_ISA_DEVICE, - .instance_size = sizeof(Port92State), - .class_init = port92_class_initfn, -}; - -static void port92_register_types(void) -{ - type_register_static(&port92_info); -} - -type_init(port92_register_types) - -static void handle_a20_line_change(void *opaque, int irq, int level) -{ - CPUX86State *cpu = opaque; - - /* XXX: send to all CPUs ? */ - /* XXX: add logic to handle multiple A20 line sources */ - cpu_x86_set_a20(cpu, level); -} - -/***********************************************************/ -/* Bochs BIOS debug ports */ - -static void bochs_bios_write(void *opaque, uint32_t addr, uint32_t val) -{ - static const char shutdown_str[8] = "Shutdown"; - static int shutdown_index = 0; - - switch(addr) { - /* Bochs BIOS messages */ - case 0x400: - case 0x401: - /* used to be panic, now unused */ - break; - case 0x402: - case 0x403: -#ifdef DEBUG_BIOS - fprintf(stderr, "%c", val); -#endif - break; - case 0x8900: - /* same as Bochs power off */ - if (val == shutdown_str[shutdown_index]) { - shutdown_index++; - if (shutdown_index == 8) { - shutdown_index = 0; - qemu_system_shutdown_request(); - } - } else { - shutdown_index = 0; - } - break; - - /* LGPL'ed VGA BIOS messages */ - case 0x501: - case 0x502: - exit((val << 1) | 1); - case 0x500: - case 0x503: -#ifdef DEBUG_BIOS - fprintf(stderr, "%c", val); -#endif - break; - } -} - -int e820_add_entry(uint64_t address, uint64_t length, uint32_t type) -{ - int index = le32_to_cpu(e820_table.count); - struct e820_entry *entry; - - if (index >= E820_NR_ENTRIES) - return -EBUSY; - entry = &e820_table.entry[index++]; - - entry->address = cpu_to_le64(address); - entry->length = cpu_to_le64(length); - entry->type = cpu_to_le32(type); - - e820_table.count = cpu_to_le32(index); - return index; -} - -static void *bochs_bios_init(void) -{ - void *fw_cfg; - uint8_t *smbios_table; - size_t smbios_len; - uint64_t *numa_fw_cfg; - int i, j; - - register_ioport_write(0x400, 1, 2, bochs_bios_write, NULL); - register_ioport_write(0x401, 1, 2, bochs_bios_write, NULL); - register_ioport_write(0x402, 1, 1, bochs_bios_write, NULL); - register_ioport_write(0x403, 1, 1, bochs_bios_write, NULL); - register_ioport_write(0x8900, 1, 1, bochs_bios_write, NULL); - - register_ioport_write(0x501, 1, 1, bochs_bios_write, NULL); - register_ioport_write(0x501, 1, 2, bochs_bios_write, NULL); - register_ioport_write(0x502, 1, 2, bochs_bios_write, NULL); - register_ioport_write(0x500, 1, 1, bochs_bios_write, NULL); - register_ioport_write(0x503, 1, 1, bochs_bios_write, NULL); - - fw_cfg = fw_cfg_init(BIOS_CFG_IOPORT, BIOS_CFG_IOPORT + 1, 0, 0); - - fw_cfg_add_i32(fw_cfg, FW_CFG_ID, 1); - fw_cfg_add_i64(fw_cfg, FW_CFG_RAM_SIZE, (uint64_t)ram_size); - fw_cfg_add_bytes(fw_cfg, FW_CFG_ACPI_TABLES, (uint8_t *)acpi_tables, - acpi_tables_len); - fw_cfg_add_i32(fw_cfg, FW_CFG_IRQ0_OVERRIDE, kvm_allows_irq0_override()); - - smbios_table = smbios_get_table(&smbios_len); - if (smbios_table) - fw_cfg_add_bytes(fw_cfg, FW_CFG_SMBIOS_ENTRIES, - smbios_table, smbios_len); - fw_cfg_add_bytes(fw_cfg, FW_CFG_E820_TABLE, (uint8_t *)&e820_table, - sizeof(struct e820_table)); - - fw_cfg_add_bytes(fw_cfg, FW_CFG_HPET, (uint8_t *)&hpet_cfg, - sizeof(struct hpet_fw_config)); - /* allocate memory for the NUMA channel: one (64bit) word for the number - * of nodes, one word for each VCPU->node and one word for each node to - * hold the amount of memory. - */ - numa_fw_cfg = g_malloc0((1 + max_cpus + nb_numa_nodes) * 8); - numa_fw_cfg[0] = cpu_to_le64(nb_numa_nodes); - for (i = 0; i < max_cpus; i++) { - for (j = 0; j < nb_numa_nodes; j++) { - if (test_bit(i, node_cpumask[j])) { - numa_fw_cfg[i + 1] = cpu_to_le64(j); - break; - } - } - } - for (i = 0; i < nb_numa_nodes; i++) { - numa_fw_cfg[max_cpus + 1 + i] = cpu_to_le64(node_mem[i]); - } - fw_cfg_add_bytes(fw_cfg, FW_CFG_NUMA, (uint8_t *)numa_fw_cfg, - (1 + max_cpus + nb_numa_nodes) * 8); - - return fw_cfg; -} - -static long get_file_size(FILE *f) -{ - long where, size; - - /* XXX: on Unix systems, using fstat() probably makes more sense */ - - where = ftell(f); - fseek(f, 0, SEEK_END); - size = ftell(f); - fseek(f, where, SEEK_SET); - - return size; -} - -static void load_linux(void *fw_cfg, - const char *kernel_filename, - const char *initrd_filename, - const char *kernel_cmdline, - target_phys_addr_t max_ram_size) -{ - uint16_t protocol; - int setup_size, kernel_size, initrd_size = 0, cmdline_size; - uint32_t initrd_max; - uint8_t header[8192], *setup, *kernel, *initrd_data; - target_phys_addr_t real_addr, prot_addr, cmdline_addr, initrd_addr = 0; - FILE *f; - char *vmode; - - /* Align to 16 bytes as a paranoia measure */ - cmdline_size = (strlen(kernel_cmdline)+16) & ~15; - - /* load the kernel header */ - f = fopen(kernel_filename, "rb"); - if (!f || !(kernel_size = get_file_size(f)) || - fread(header, 1, MIN(ARRAY_SIZE(header), kernel_size), f) != - MIN(ARRAY_SIZE(header), kernel_size)) { - fprintf(stderr, "qemu: could not load kernel '%s': %s\n", - kernel_filename, strerror(errno)); - -#ifdef CONFIG_MARU - char *error_msg = NULL; - - error_msg = maru_convert_path(error_msg, kernel_filename); - maru_register_exit_msg(MARU_EXIT_KERNEL_FILE_EXCEPTION, error_msg); - if (error_msg) { - g_free(error_msg); - } -#endif - - exit(1); - } - - /* kernel protocol version */ -#if 0 - fprintf(stderr, "header magic: %#x\n", ldl_p(header+0x202)); -#endif - if (ldl_p(header+0x202) == 0x53726448) - protocol = lduw_p(header+0x206); - else { - /* This looks like a multiboot kernel. If it is, let's stop - treating it like a Linux kernel. */ - if (load_multiboot(fw_cfg, f, kernel_filename, initrd_filename, - kernel_cmdline, kernel_size, header)) - return; - protocol = 0; - } - - if (protocol < 0x200 || !(header[0x211] & 0x01)) { - /* Low kernel */ - real_addr = 0x90000; - cmdline_addr = 0x9a000 - cmdline_size; - prot_addr = 0x10000; - } else if (protocol < 0x202) { - /* High but ancient kernel */ - real_addr = 0x90000; - cmdline_addr = 0x9a000 - cmdline_size; - prot_addr = 0x100000; - } else { - /* High and recent kernel */ - real_addr = 0x10000; - cmdline_addr = 0x20000; - prot_addr = 0x100000; - } - -#if 0 - fprintf(stderr, - "qemu: real_addr = 0x" TARGET_FMT_plx "\n" - "qemu: cmdline_addr = 0x" TARGET_FMT_plx "\n" - "qemu: prot_addr = 0x" TARGET_FMT_plx "\n", - real_addr, - cmdline_addr, - prot_addr); -#endif - - /* highest address for loading the initrd */ - if (protocol >= 0x203) - initrd_max = ldl_p(header+0x22c); - else - initrd_max = 0x37ffffff; - - if (initrd_max >= max_ram_size-ACPI_DATA_SIZE) - initrd_max = max_ram_size-ACPI_DATA_SIZE-1; - - fw_cfg_add_i32(fw_cfg, FW_CFG_CMDLINE_ADDR, cmdline_addr); - fw_cfg_add_i32(fw_cfg, FW_CFG_CMDLINE_SIZE, strlen(kernel_cmdline)+1); - fw_cfg_add_bytes(fw_cfg, FW_CFG_CMDLINE_DATA, - (uint8_t*)strdup(kernel_cmdline), - strlen(kernel_cmdline)+1); - - if (protocol >= 0x202) { - stl_p(header+0x228, cmdline_addr); - } else { - stw_p(header+0x20, 0xA33F); - stw_p(header+0x22, cmdline_addr-real_addr); - } - - /* handle vga= parameter */ - vmode = strstr(kernel_cmdline, "vga="); - if (vmode) { - unsigned int video_mode; - /* skip "vga=" */ - vmode += 4; - if (!strncmp(vmode, "normal", 6)) { - video_mode = 0xffff; - } else if (!strncmp(vmode, "ext", 3)) { - video_mode = 0xfffe; - } else if (!strncmp(vmode, "ask", 3)) { - video_mode = 0xfffd; - } else { - video_mode = strtol(vmode, NULL, 0); - } - stw_p(header+0x1fa, video_mode); - } - - /* loader type */ - /* High nybble = B reserved for QEMU; low nybble is revision number. - If this code is substantially changed, you may want to consider - incrementing the revision. */ - if (protocol >= 0x200) - header[0x210] = 0xB0; - - /* heap */ - if (protocol >= 0x201) { - header[0x211] |= 0x80; /* CAN_USE_HEAP */ - stw_p(header+0x224, cmdline_addr-real_addr-0x200); - } - - /* load initrd */ - if (initrd_filename) { - if (protocol < 0x200) { - fprintf(stderr, "qemu: linux kernel too old to load a ram disk\n"); - exit(1); - } - - initrd_size = get_image_size(initrd_filename); - if (initrd_size < 0) { - fprintf(stderr, "qemu: error reading initrd %s\n", - initrd_filename); - exit(1); - } - - initrd_addr = (initrd_max-initrd_size) & ~4095; - - initrd_data = g_malloc(initrd_size); - load_image(initrd_filename, initrd_data); - - fw_cfg_add_i32(fw_cfg, FW_CFG_INITRD_ADDR, initrd_addr); - fw_cfg_add_i32(fw_cfg, FW_CFG_INITRD_SIZE, initrd_size); - fw_cfg_add_bytes(fw_cfg, FW_CFG_INITRD_DATA, initrd_data, initrd_size); - - stl_p(header+0x218, initrd_addr); - stl_p(header+0x21c, initrd_size); - } - - /* load kernel and setup */ - setup_size = header[0x1f1]; - if (setup_size == 0) - setup_size = 4; - setup_size = (setup_size+1)*512; - kernel_size -= setup_size; - - setup = g_malloc(setup_size); - kernel = g_malloc(kernel_size); - fseek(f, 0, SEEK_SET); - if (fread(setup, 1, setup_size, f) != setup_size) { - fprintf(stderr, "fread() failed\n"); - exit(1); - } - if (fread(kernel, 1, kernel_size, f) != kernel_size) { - fprintf(stderr, "fread() failed\n"); - exit(1); - } - fclose(f); - memcpy(setup, header, MIN(sizeof(header), setup_size)); - - fw_cfg_add_i32(fw_cfg, FW_CFG_KERNEL_ADDR, prot_addr); - fw_cfg_add_i32(fw_cfg, FW_CFG_KERNEL_SIZE, kernel_size); - fw_cfg_add_bytes(fw_cfg, FW_CFG_KERNEL_DATA, kernel, kernel_size); - - fw_cfg_add_i32(fw_cfg, FW_CFG_SETUP_ADDR, real_addr); - fw_cfg_add_i32(fw_cfg, FW_CFG_SETUP_SIZE, setup_size); - fw_cfg_add_bytes(fw_cfg, FW_CFG_SETUP_DATA, setup, setup_size); - - option_rom[nb_option_roms].name = "linuxboot.bin"; - option_rom[nb_option_roms].bootindex = 0; - nb_option_roms++; -} - -#define NE2000_NB_MAX 6 - -static const int ne2000_io[NE2000_NB_MAX] = { 0x300, 0x320, 0x340, 0x360, - 0x280, 0x380 }; -static const int ne2000_irq[NE2000_NB_MAX] = { 9, 10, 11, 3, 4, 5 }; - -static const int parallel_io[MAX_PARALLEL_PORTS] = { 0x378, 0x278, 0x3bc }; -static const int parallel_irq[MAX_PARALLEL_PORTS] = { 7, 7, 7 }; - -void pc_init_ne2k_isa(ISABus *bus, NICInfo *nd) -{ - static int nb_ne2k = 0; - - if (nb_ne2k == NE2000_NB_MAX) - return; - isa_ne2000_init(bus, ne2000_io[nb_ne2k], - ne2000_irq[nb_ne2k], nd); - nb_ne2k++; -} - -DeviceState *cpu_get_current_apic(void) -{ - if (cpu_single_env) { - return cpu_single_env->apic_state; - } else { - return NULL; - } -} - -static DeviceState *apic_init(void *env, uint8_t apic_id) -{ - DeviceState *dev; - static int apic_mapped; - - if (kvm_irqchip_in_kernel()) { - dev = qdev_create(NULL, "kvm-apic"); - } else if (xen_enabled()) { - dev = qdev_create(NULL, "xen-apic"); - } else { - dev = qdev_create(NULL, "apic"); - } - - qdev_prop_set_uint8(dev, "id", apic_id); - qdev_prop_set_ptr(dev, "cpu_env", env); - qdev_init_nofail(dev); - - /* XXX: mapping more APICs at the same memory location */ - if (apic_mapped == 0) { - /* NOTE: the APIC is directly connected to the CPU - it is not - on the global memory bus. */ - /* XXX: what if the base changes? */ - sysbus_mmio_map(sysbus_from_qdev(dev), 0, MSI_ADDR_BASE); - apic_mapped = 1; - } - - return dev; -} - -void pc_acpi_smi_interrupt(void *opaque, int irq, int level) -{ - CPUX86State *s = opaque; - - if (level) { - cpu_interrupt(s, CPU_INTERRUPT_SMI); - } -} - -static X86CPU *pc_new_cpu(const char *cpu_model) -{ - X86CPU *cpu; - CPUX86State *env; - - cpu = cpu_x86_init(cpu_model); - if (cpu == NULL) { - fprintf(stderr, "Unable to find x86 CPU definition\n"); - exit(1); - } - env = &cpu->env; - if ((env->cpuid_features & CPUID_APIC) || smp_cpus > 1) { - env->apic_state = apic_init(env, env->cpuid_apic_id); - } - cpu_reset(CPU(cpu)); - return cpu; -} - -void pc_cpus_init(const char *cpu_model) -{ - int i; - - /* init CPUs */ - if (cpu_model == NULL) { -#ifdef TARGET_X86_64 - cpu_model = "qemu64"; -#else - cpu_model = "qemu32"; -#endif - } - - for(i = 0; i < smp_cpus; i++) { - pc_new_cpu(cpu_model); - } -} - -void *pc_memory_init(MemoryRegion *system_memory, - const char *kernel_filename, - const char *kernel_cmdline, - const char *initrd_filename, - ram_addr_t below_4g_mem_size, - ram_addr_t above_4g_mem_size, - MemoryRegion *rom_memory, - MemoryRegion **ram_memory) -{ - int linux_boot, i; - MemoryRegion *ram, *option_rom_mr; - MemoryRegion *ram_below_4g, *ram_above_4g; - void *fw_cfg; - - linux_boot = (kernel_filename != NULL); - - /* Allocate RAM. We allocate it as a single memory region and use - * aliases to address portions of it, mostly for backwards compatibility - * with older qemus that used qemu_ram_alloc(). - */ - ram = g_malloc(sizeof(*ram)); - memory_region_init_ram(ram, "pc.ram", - below_4g_mem_size + above_4g_mem_size); - vmstate_register_ram_global(ram); - *ram_memory = ram; - ram_below_4g = g_malloc(sizeof(*ram_below_4g)); - memory_region_init_alias(ram_below_4g, "ram-below-4g", ram, - 0, below_4g_mem_size); - memory_region_add_subregion(system_memory, 0, ram_below_4g); - if (above_4g_mem_size > 0) { - ram_above_4g = g_malloc(sizeof(*ram_above_4g)); - memory_region_init_alias(ram_above_4g, "ram-above-4g", ram, - below_4g_mem_size, above_4g_mem_size); - memory_region_add_subregion(system_memory, 0x100000000ULL, - ram_above_4g); - } - - - /* Initialize PC system firmware */ - pc_system_firmware_init(rom_memory); - - option_rom_mr = g_malloc(sizeof(*option_rom_mr)); - memory_region_init_ram(option_rom_mr, "pc.rom", PC_ROM_SIZE); - vmstate_register_ram_global(option_rom_mr); - memory_region_add_subregion_overlap(rom_memory, - PC_ROM_MIN_VGA, - option_rom_mr, - 1); - - fw_cfg = bochs_bios_init(); - rom_set_fw(fw_cfg); - - if (linux_boot) { - load_linux(fw_cfg, kernel_filename, initrd_filename, kernel_cmdline, below_4g_mem_size); - } - - for (i = 0; i < nb_option_roms; i++) { - rom_add_option(option_rom[i].name, option_rom[i].bootindex); - } - return fw_cfg; -} - -qemu_irq *pc_allocate_cpu_irq(void) -{ - return qemu_allocate_irqs(pic_irq_request, NULL, 1); -} - -DeviceState *pc_vga_init(ISABus *isa_bus, PCIBus *pci_bus) -{ - DeviceState *dev = NULL; - - if (cirrus_vga_enabled) { - if (pci_bus) { - dev = pci_cirrus_vga_init(pci_bus); - } else { - dev = &isa_create_simple(isa_bus, "isa-cirrus-vga")->qdev; - } - } else if (vmsvga_enabled) { - if (pci_bus) { - dev = pci_vmsvga_init(pci_bus); - } else { - fprintf(stderr, "%s: vmware_vga: no PCI bus\n", __FUNCTION__); - } -#ifdef CONFIG_SPICE - } else if (qxl_enabled) { - if (pci_bus) { - dev = &pci_create_simple(pci_bus, -1, "qxl-vga")->qdev; - } else { - fprintf(stderr, "%s: qxl: no PCI bus\n", __FUNCTION__); - } -#endif - } else if (std_vga_enabled) { - if (pci_bus) { - dev = pci_vga_init(pci_bus); - } else { - dev = isa_vga_init(isa_bus); - } -#ifdef CONFIG_MARU - } else if (maru_vga_enabled) { - if (pci_bus) { - dev = pci_maru_vga_init(pci_bus); - pci_maru_overlay_init(pci_bus); - pci_maru_brightness_init(pci_bus); - } else { - dev = isa_vga_init(isa_bus); - } - } -#else - } -#endif - return dev; - -} - -static void cpu_request_exit(void *opaque, int irq, int level) -{ - CPUX86State *env = cpu_single_env; - - if (env && level) { - cpu_exit(env); - } -} - -void pc_basic_device_init(ISABus *isa_bus, qemu_irq *gsi, - ISADevice **rtc_state, - ISADevice **floppy, - bool no_vmport) -{ - int i; - DriveInfo *fd[MAX_FD]; - DeviceState *hpet = NULL; - int pit_isa_irq = 0; - qemu_irq pit_alt_irq = NULL; - qemu_irq rtc_irq = NULL; - qemu_irq *a20_line; - ISADevice *i8042, *port92, *vmmouse, *pit = NULL; - qemu_irq *cpu_exit_irq; - - register_ioport_write(0x80, 1, 1, ioport80_write, NULL); - - register_ioport_write(0xf0, 1, 1, ioportF0_write, NULL); - - /* - * Check if an HPET shall be created. - * - * Without KVM_CAP_PIT_STATE2, we cannot switch off the in-kernel PIT - * when the HPET wants to take over. Thus we have to disable the latter. - */ - if (!no_hpet && (!kvm_irqchip_in_kernel() || kvm_has_pit_state2())) { - hpet = sysbus_try_create_simple("hpet", HPET_BASE, NULL); - - if (hpet) { - for (i = 0; i < GSI_NUM_PINS; i++) { - sysbus_connect_irq(sysbus_from_qdev(hpet), i, gsi[i]); - } - pit_isa_irq = -1; - pit_alt_irq = qdev_get_gpio_in(hpet, HPET_LEGACY_PIT_INT); - rtc_irq = qdev_get_gpio_in(hpet, HPET_LEGACY_RTC_INT); - } - } - *rtc_state = rtc_init(isa_bus, 2000, rtc_irq); - - qemu_register_boot_set(pc_boot_set, *rtc_state); - - if (!xen_enabled()) { - if (kvm_irqchip_in_kernel()) { - pit = kvm_pit_init(isa_bus, 0x40); - } else { - pit = pit_init(isa_bus, 0x40, pit_isa_irq, pit_alt_irq); - } - if (hpet) { - /* connect PIT to output control line of the HPET */ - qdev_connect_gpio_out(hpet, 0, qdev_get_gpio_in(&pit->qdev, 0)); - } - pcspk_init(isa_bus, pit); - } - - for(i = 0; i < MAX_SERIAL_PORTS; i++) { - if (serial_hds[i]) { - serial_isa_init(isa_bus, i, serial_hds[i]); - } - } - - for(i = 0; i < MAX_PARALLEL_PORTS; i++) { - if (parallel_hds[i]) { - parallel_init(isa_bus, i, parallel_hds[i]); - } - } - - a20_line = qemu_allocate_irqs(handle_a20_line_change, first_cpu, 2); - i8042 = isa_create_simple(isa_bus, "i8042"); - i8042_setup_a20_line(i8042, &a20_line[0]); - if (!no_vmport) { - vmport_init(isa_bus); - vmmouse = isa_try_create(isa_bus, "vmmouse"); - } else { - vmmouse = NULL; - } - if (vmmouse) { - qdev_prop_set_ptr(&vmmouse->qdev, "ps2_mouse", i8042); - qdev_init_nofail(&vmmouse->qdev); - } - port92 = isa_create_simple(isa_bus, "port92"); - port92_init(port92, &a20_line[1]); - - cpu_exit_irq = qemu_allocate_irqs(cpu_request_exit, NULL, 1); - DMA_init(0, cpu_exit_irq); - - for(i = 0; i < MAX_FD; i++) { - fd[i] = drive_get(IF_FLOPPY, 0, i); - } - *floppy = fdctrl_init_isa(isa_bus, fd); -} - -void pc_pci_device_init(PCIBus *pci_bus) -{ - int max_bus; - int bus; - - max_bus = drive_get_max_bus(IF_SCSI); - for (bus = 0; bus <= max_bus; bus++) { - pci_create_simple(pci_bus, -1, "lsi53c895a"); - } -} diff --git a/hw/pc_sysfw.c b/hw/pc_sysfw.c deleted file mode 100644 index 923a624..0000000 --- a/hw/pc_sysfw.c +++ /dev/null @@ -1,297 +0,0 @@ -/* - * QEMU PC System Firmware - * - * Copyright (c) 2003-2004 Fabrice Bellard - * Copyright (c) 2011-2012 Intel Corporation - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - -#include "blockdev.h" -#include "sysbus.h" -#include "hw.h" -#include "pc.h" -#include "hw/boards.h" -#include "loader.h" -#include "sysemu.h" -#include "flash.h" -#include "kvm.h" - -#ifdef CONFIG_MARU -#include "../tizen/src/maru_err_table.h" -#endif - -#define BIOS_FILENAME "bios.bin" - -typedef struct PcSysFwDevice { - SysBusDevice busdev; - uint8_t rom_only; -} PcSysFwDevice; - -static void pc_isa_bios_init(MemoryRegion *rom_memory, - MemoryRegion *flash_mem, - int ram_size) -{ - int isa_bios_size; - MemoryRegion *isa_bios; - uint64_t flash_size; - void *flash_ptr, *isa_bios_ptr; - - flash_size = memory_region_size(flash_mem); - - /* map the last 128KB of the BIOS in ISA space */ - isa_bios_size = flash_size; - if (isa_bios_size > (128 * 1024)) { - isa_bios_size = 128 * 1024; - } - isa_bios = g_malloc(sizeof(*isa_bios)); - memory_region_init_ram(isa_bios, "isa-bios", isa_bios_size); - vmstate_register_ram_global(isa_bios); - memory_region_add_subregion_overlap(rom_memory, - 0x100000 - isa_bios_size, - isa_bios, - 1); - - /* copy ISA rom image from top of flash memory */ - flash_ptr = memory_region_get_ram_ptr(flash_mem); - isa_bios_ptr = memory_region_get_ram_ptr(isa_bios); - memcpy(isa_bios_ptr, - ((uint8_t*)flash_ptr) + (flash_size - isa_bios_size), - isa_bios_size); - - memory_region_set_readonly(isa_bios, true); -} - -static void pc_fw_add_pflash_drv(void) -{ - QemuOpts *opts; - QEMUMachine *machine; - char *filename; - - if (bios_name == NULL) { - bios_name = BIOS_FILENAME; - } - filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name); - - opts = drive_add(IF_PFLASH, -1, filename, "readonly=on"); - - g_free(filename); - - if (opts == NULL) { - return; - } - - machine = find_default_machine(); - if (machine == NULL) { - return; - } - - drive_init(opts, machine->use_scsi); -} - -static void pc_system_flash_init(MemoryRegion *rom_memory, - DriveInfo *pflash_drv) -{ - BlockDriverState *bdrv; - int64_t size; - target_phys_addr_t phys_addr; - int sector_bits, sector_size; - pflash_t *system_flash; - MemoryRegion *flash_mem; - - bdrv = pflash_drv->bdrv; - size = bdrv_getlength(pflash_drv->bdrv); - sector_bits = 12; - sector_size = 1 << sector_bits; - - if ((size % sector_size) != 0) { - fprintf(stderr, - "qemu: PC system firmware (pflash) must be a multiple of 0x%x\n", - sector_size); - exit(1); - } - - phys_addr = 0x100000000ULL - size; - system_flash = pflash_cfi01_register(phys_addr, NULL, "system.flash", size, - bdrv, sector_size, size >> sector_bits, - 1, 0x0000, 0x0000, 0x0000, 0x0000, 0); - flash_mem = pflash_cfi01_get_memory(system_flash); - - pc_isa_bios_init(rom_memory, flash_mem, size); -} - -#ifdef CONFIG_MARU -extern char* qemu_get_data_dir(void); -#endif - -static void old_pc_system_rom_init(MemoryRegion *rom_memory) -{ - char *filename; - MemoryRegion *bios, *isa_bios; - int bios_size, isa_bios_size; - int ret; - - /* BIOS load */ - if (bios_name == NULL) { - bios_name = BIOS_FILENAME; - } - filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name); - if (filename) { - bios_size = get_image_size(filename); - } else { - bios_size = -1; - } - if (bios_size <= 0 || - (bios_size % 65536) != 0) { - goto bios_error; - } - bios = g_malloc(sizeof(*bios)); - memory_region_init_ram(bios, "pc.bios", bios_size); - vmstate_register_ram_global(bios); - memory_region_set_readonly(bios, true); - ret = rom_add_file_fixed(bios_name, (uint32_t)(-bios_size), -1); - if (ret != 0) { - bios_error: - fprintf(stderr, "qemu: could not load PC BIOS '%s'\n", bios_name); -#ifdef CONFIG_MARU - char *error_msg = NULL; - const char *path = qemu_get_data_dir(); - char *bios_path = NULL; - int bios_len = 0; - - bios_len = strlen(path) + strlen("/") + strlen(bios_name) + 1; - bios_path = g_malloc(bios_len * sizeof(char)); - if (!bios_path) { - fprintf(stderr, "qemu: failed to allocate memory\n"); - } - snprintf(bios_path, bios_len, "%s/%s", path, bios_name); - error_msg = maru_convert_path(error_msg, bios_path); - maru_register_exit_msg(MARU_EXIT_BIOS_FILE_EXCEPTION, error_msg); - - if (bios_path) { - g_free(bios_path); - } - if (error_msg) { - g_free(error_msg); - } -#endif - - exit(1); - } - if (filename) { - g_free(filename); - } - - /* map the last 128KB of the BIOS in ISA space */ - isa_bios_size = bios_size; - if (isa_bios_size > (128 * 1024)) { - isa_bios_size = 128 * 1024; - } - isa_bios = g_malloc(sizeof(*isa_bios)); - memory_region_init_alias(isa_bios, "isa-bios", bios, - bios_size - isa_bios_size, isa_bios_size); - memory_region_add_subregion_overlap(rom_memory, - 0x100000 - isa_bios_size, - isa_bios, - 1); - memory_region_set_readonly(isa_bios, true); - - /* map all the bios at the top of memory */ - memory_region_add_subregion(rom_memory, - (uint32_t)(-bios_size), - bios); -} - -void pc_system_firmware_init(MemoryRegion *rom_memory) -{ - DriveInfo *pflash_drv; - PcSysFwDevice *sysfw_dev; - - sysfw_dev = (PcSysFwDevice*) qdev_create(NULL, "pc-sysfw"); - - qdev_init_nofail(DEVICE(sysfw_dev)); - - if (sysfw_dev->rom_only) { - old_pc_system_rom_init(rom_memory); - return; - } - - pflash_drv = drive_get(IF_PFLASH, 0, 0); - - /* Currently KVM cannot execute from device memory. - Use old rom based firmware initialization for KVM. */ - if (kvm_enabled()) { - if (pflash_drv != NULL) { - fprintf(stderr, "qemu: pflash cannot be used with kvm enabled\n"); - exit(1); - } else { - sysfw_dev->rom_only = 1; - old_pc_system_rom_init(rom_memory); - return; - } - } - - /* If a pflash drive is not found, then create one using - the bios filename. */ - if (pflash_drv == NULL) { - pc_fw_add_pflash_drv(); - pflash_drv = drive_get(IF_PFLASH, 0, 0); - } - - if (pflash_drv != NULL) { - pc_system_flash_init(rom_memory, pflash_drv); - } else { - fprintf(stderr, "qemu: PC system firmware (pflash) not available\n"); - exit(1); - } -} - -static Property pcsysfw_properties[] = { - DEFINE_PROP_UINT8("rom_only", PcSysFwDevice, rom_only, 0), - DEFINE_PROP_END_OF_LIST(), -}; - -static int pcsysfw_init(DeviceState *dev) -{ - return 0; -} - -static void pcsysfw_class_init (ObjectClass *klass, void *data) -{ - DeviceClass *dc = DEVICE_CLASS (klass); - - dc->desc = "PC System Firmware"; - dc->init = pcsysfw_init; - dc->props = pcsysfw_properties; -} - -static TypeInfo pcsysfw_info = { - .name = "pc-sysfw", - .parent = TYPE_SYS_BUS_DEVICE, - .instance_size = sizeof (PcSysFwDevice), - .class_init = pcsysfw_class_init, -}; - -static void pcsysfw_register (void) -{ - type_register_static (&pcsysfw_info); -} - -type_init (pcsysfw_register); - diff --git a/hw/pci-hotplug.c b/hw/pci-hotplug.c deleted file mode 100644 index 33d1bac..0000000 --- a/hw/pci-hotplug.c +++ /dev/null @@ -1,327 +0,0 @@ -/* - * QEMU PCI hotplug support - * - * Copyright (c) 2004 Fabrice Bellard - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - -#include "hw.h" -#include "boards.h" -#include "pci.h" -#include "net.h" -#include "pc.h" -#include "monitor.h" -#include "scsi.h" -#include "virtio-blk.h" -#include "qemu-config.h" -#include "blockdev.h" -#include "error.h" - -#if defined(TARGET_I386) -static PCIDevice *qemu_pci_hot_add_nic(Monitor *mon, - const char *devaddr, - const char *opts_str) -{ - Error *local_err = NULL; - QemuOpts *opts; - PCIBus *bus; - int ret, devfn; - - bus = pci_get_bus_devfn(&devfn, devaddr); - if (!bus) { - monitor_printf(mon, "Invalid PCI device address %s\n", devaddr); - return NULL; - } - if (!((BusState*)bus)->allow_hotplug) { - monitor_printf(mon, "PCI bus doesn't support hotplug\n"); - return NULL; - } - - opts = qemu_opts_parse(qemu_find_opts("net"), opts_str ? opts_str : "", 0); - if (!opts) { - return NULL; - } - - qemu_opt_set(opts, "type", "nic"); - - ret = net_client_init(opts, 0, &local_err); - if (error_is_set(&local_err)) { - qerror_report_err(local_err); - error_free(local_err); - return NULL; - } - if (nd_table[ret].devaddr) { - monitor_printf(mon, "Parameter addr not supported\n"); - return NULL; - } - return pci_nic_init(&nd_table[ret], "rtl8139", devaddr); -} - -static int scsi_hot_add(Monitor *mon, DeviceState *adapter, - DriveInfo *dinfo, int printinfo) -{ - SCSIBus *scsibus; - SCSIDevice *scsidev; - - scsibus = SCSI_BUS(QLIST_FIRST(&adapter->child_bus)); - - /* - * drive_init() tries to find a default for dinfo->unit. Doesn't - * work at all for hotplug though as we assign the device to a - * specific bus instead of the first bus with spare scsi ids. - * - * Ditch the calculated value and reload from option string (if - * specified). - */ - dinfo->unit = qemu_opt_get_number(dinfo->opts, "unit", -1); - dinfo->bus = scsibus->busnr; - scsidev = scsi_bus_legacy_add_drive(scsibus, dinfo->bdrv, dinfo->unit, - false, -1); - if (!scsidev) { - return -1; - } - dinfo->unit = scsidev->id; - - if (printinfo) - monitor_printf(mon, "OK bus %d, unit %d\n", - scsibus->busnr, scsidev->id); - return 0; -} - -int pci_drive_hot_add(Monitor *mon, const QDict *qdict, - DriveInfo *dinfo, int type) -{ - int dom, pci_bus; - unsigned slot; - PCIDevice *dev; - const char *pci_addr = qdict_get_str(qdict, "pci_addr"); - - switch (type) { - case IF_SCSI: - if (pci_read_devaddr(mon, pci_addr, &dom, &pci_bus, &slot)) { - goto err; - } - dev = pci_find_device(pci_find_root_bus(dom), pci_bus, - PCI_DEVFN(slot, 0)); - if (!dev) { - monitor_printf(mon, "no pci device with address %s\n", pci_addr); - goto err; - } - if (scsi_hot_add(mon, &dev->qdev, dinfo, 1) != 0) { - goto err; - } - break; - default: - monitor_printf(mon, "Can't hot-add drive to type %d\n", type); - goto err; - } - - return 0; -err: - return -1; -} - -static PCIDevice *qemu_pci_hot_add_storage(Monitor *mon, - const char *devaddr, - const char *opts) -{ - PCIDevice *dev; - DriveInfo *dinfo = NULL; - int type = -1; - char buf[128]; - PCIBus *bus; - int devfn; - - if (get_param_value(buf, sizeof(buf), "if", opts)) { - if (!strcmp(buf, "scsi")) - type = IF_SCSI; - else if (!strcmp(buf, "virtio")) { - type = IF_VIRTIO; - } else { - monitor_printf(mon, "type %s not a hotpluggable PCI device.\n", buf); - return NULL; - } - } else { - monitor_printf(mon, "no if= specified\n"); - return NULL; - } - - if (get_param_value(buf, sizeof(buf), "file", opts)) { - dinfo = add_init_drive(opts); - if (!dinfo) - return NULL; - if (dinfo->devaddr) { - monitor_printf(mon, "Parameter addr not supported\n"); - return NULL; - } - } else { - dinfo = NULL; - } - - bus = pci_get_bus_devfn(&devfn, devaddr); - if (!bus) { - monitor_printf(mon, "Invalid PCI device address %s\n", devaddr); - return NULL; - } - if (!((BusState*)bus)->allow_hotplug) { - monitor_printf(mon, "PCI bus doesn't support hotplug\n"); - return NULL; - } - - switch (type) { - case IF_SCSI: - dev = pci_create(bus, devfn, "lsi53c895a"); - if (qdev_init(&dev->qdev) < 0) - dev = NULL; - if (dev && dinfo) { - if (scsi_hot_add(mon, &dev->qdev, dinfo, 0) != 0) { - qdev_unplug(&dev->qdev, NULL); - dev = NULL; - } - } - break; - case IF_VIRTIO: - if (!dinfo) { - monitor_printf(mon, "virtio requires a backing file/device.\n"); - return NULL; - } - dev = pci_create(bus, devfn, "virtio-blk-pci"); - if (qdev_prop_set_drive(&dev->qdev, "drive", dinfo->bdrv) < 0) { - qdev_free(&dev->qdev); - dev = NULL; - break; - } - if (qdev_init(&dev->qdev) < 0) - dev = NULL; - break; - default: - dev = NULL; - } - return dev; -} - -#ifdef CONFIG_MARU -static PCIDevice *qemu_pci_hot_add_keyboard(Monitor *mon, - const char *devaddr, - const char *opts) -{ - PCIDevice *dev; - PCIBus *bus; - int devfn; - - bus = pci_get_bus_devfn(&devfn, devaddr); - if (!bus) { - monitor_printf(mon, "Invalid PCI device address %s\n", devaddr); - return NULL; - } - - if (!((BusState*)bus)->allow_hotplug) { - monitor_printf(mon, "PCI bus doesn't support hotplug\n"); - return NULL; - } - - dev = pci_create(bus, devfn, "virtio-keyboard-pci"); - if (qdev_init(&dev->qdev) < 0) { - dev = NULL; - } - - return dev; -} -#endif /* CONFIG_MARU */ - -#ifdef CONFIG_MARU -PCIDevice *pci_device_hot_add(Monitor *mon, const QDict *qdict) -#else -void pci_device_hot_add(Monitor *mon, const QDict *qdict) -#endif -{ - PCIDevice *dev = NULL; - const char *pci_addr = qdict_get_str(qdict, "pci_addr"); - const char *type = qdict_get_str(qdict, "type"); - const char *opts = qdict_get_try_str(qdict, "opts"); - - /* strip legacy tag */ - if (!strncmp(pci_addr, "pci_addr=", 9)) { - pci_addr += 9; - } - - if (!opts) { - opts = ""; - } - - if (!strcmp(pci_addr, "auto")) - pci_addr = NULL; - - if (strcmp(type, "nic") == 0) { - dev = qemu_pci_hot_add_nic(mon, pci_addr, opts); - } else if (strcmp(type, "storage") == 0) { - dev = qemu_pci_hot_add_storage(mon, pci_addr, opts); -#ifdef CONFIG_MARU - } else if (strcmp(type, "keyboard") == 0) { - dev = qemu_pci_hot_add_keyboard(mon, pci_addr, opts); -#endif - } else { - monitor_printf(mon, "invalid type: %s\n", type); - } - - if (dev) { - monitor_printf(mon, "OK domain %d, bus %d, slot %d, function %d\n", - pci_find_domain(dev->bus), - pci_bus_num(dev->bus), PCI_SLOT(dev->devfn), - PCI_FUNC(dev->devfn)); - } else - monitor_printf(mon, "failed to add %s\n", opts); -#ifdef CONFIG_MARU - return dev; -#endif -} -#endif - -static int pci_device_hot_remove(Monitor *mon, const char *pci_addr) -{ - PCIDevice *d; - int dom, bus; - unsigned slot; - Error *local_err = NULL; - - if (pci_read_devaddr(mon, pci_addr, &dom, &bus, &slot)) { - return -1; - } - - d = pci_find_device(pci_find_root_bus(dom), bus, PCI_DEVFN(slot, 0)); - if (!d) { - monitor_printf(mon, "slot %d empty\n", slot); - return -1; - } - - qdev_unplug(&d->qdev, &local_err); - if (error_is_set(&local_err)) { - monitor_printf(mon, "%s\n", error_get_pretty(local_err)); - error_free(local_err); - return -1; - } - - return 0; -} - -void do_pci_device_hot_remove(Monitor *mon, const QDict *qdict) -{ - pci_device_hot_remove(mon, qdict_get_str(qdict, "pci_addr")); -} diff --git a/hw/pci.c b/hw/pci.c deleted file mode 100644 index 476eab8..0000000 --- a/hw/pci.c +++ /dev/null @@ -1,2092 +0,0 @@ -/* - * QEMU PCI bus manager - * - * Copyright (c) 2004 Fabrice Bellard - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -#include "hw.h" -#include "pci.h" -#include "pci_bridge.h" -#include "pci_internals.h" -#include "monitor.h" -#include "net.h" -#include "sysemu.h" -#include "loader.h" -#include "range.h" -#include "qmp-commands.h" -#include "msi.h" -#include "msix.h" - -//#define DEBUG_PCI -#ifdef DEBUG_PCI -# define PCI_DPRINTF(format, ...) printf(format, ## __VA_ARGS__) -#else -# define PCI_DPRINTF(format, ...) do { } while (0) -#endif - -static void pcibus_dev_print(Monitor *mon, DeviceState *dev, int indent); -static char *pcibus_get_dev_path(DeviceState *dev); -static char *pcibus_get_fw_dev_path(DeviceState *dev); -static int pcibus_reset(BusState *qbus); - -static Property pci_props[] = { - DEFINE_PROP_PCI_DEVFN("addr", PCIDevice, devfn, -1), - DEFINE_PROP_STRING("romfile", PCIDevice, romfile), - DEFINE_PROP_UINT32("rombar", PCIDevice, rom_bar, 1), - DEFINE_PROP_BIT("multifunction", PCIDevice, cap_present, - QEMU_PCI_CAP_MULTIFUNCTION_BITNR, false), - DEFINE_PROP_BIT("command_serr_enable", PCIDevice, cap_present, - QEMU_PCI_CAP_SERR_BITNR, true), - DEFINE_PROP_END_OF_LIST() -}; - -static void pci_bus_class_init(ObjectClass *klass, void *data) -{ - BusClass *k = BUS_CLASS(klass); - - k->print_dev = pcibus_dev_print; - k->get_dev_path = pcibus_get_dev_path; - k->get_fw_dev_path = pcibus_get_fw_dev_path; - k->reset = pcibus_reset; -} - -static const TypeInfo pci_bus_info = { - .name = TYPE_PCI_BUS, - .parent = TYPE_BUS, - .instance_size = sizeof(PCIBus), - .class_init = pci_bus_class_init, -}; - -static PCIBus *pci_find_bus_nr(PCIBus *bus, int bus_num); -static void pci_update_mappings(PCIDevice *d); -static void pci_set_irq(void *opaque, int irq_num, int level); -static void pci_del_option_rom(PCIDevice *pdev); - -static uint16_t pci_default_sub_vendor_id = PCI_SUBVENDOR_ID_REDHAT_QUMRANET; -static uint16_t pci_default_sub_device_id = PCI_SUBDEVICE_ID_QEMU; - -struct PCIHostBus { - int domain; - struct PCIBus *bus; - QLIST_ENTRY(PCIHostBus) next; -}; -static QLIST_HEAD(, PCIHostBus) host_buses; - -static const VMStateDescription vmstate_pcibus = { - .name = "PCIBUS", - .version_id = 1, - .minimum_version_id = 1, - .minimum_version_id_old = 1, - .fields = (VMStateField []) { - VMSTATE_INT32_EQUAL(nirq, PCIBus), - VMSTATE_VARRAY_INT32(irq_count, PCIBus, nirq, 0, vmstate_info_int32, int32_t), - VMSTATE_END_OF_LIST() - } -}; -static int pci_bar(PCIDevice *d, int reg) -{ - uint8_t type; - - if (reg != PCI_ROM_SLOT) - return PCI_BASE_ADDRESS_0 + reg * 4; - - type = d->config[PCI_HEADER_TYPE] & ~PCI_HEADER_TYPE_MULTI_FUNCTION; - return type == PCI_HEADER_TYPE_BRIDGE ? PCI_ROM_ADDRESS1 : PCI_ROM_ADDRESS; -} - -static inline int pci_irq_state(PCIDevice *d, int irq_num) -{ - return (d->irq_state >> irq_num) & 0x1; -} - -static inline void pci_set_irq_state(PCIDevice *d, int irq_num, int level) -{ - d->irq_state &= ~(0x1 << irq_num); - d->irq_state |= level << irq_num; -} - -static void pci_change_irq_level(PCIDevice *pci_dev, int irq_num, int change) -{ - PCIBus *bus; - for (;;) { - bus = pci_dev->bus; - irq_num = bus->map_irq(pci_dev, irq_num); - if (bus->set_irq) - break; - pci_dev = bus->parent_dev; - } - bus->irq_count[irq_num] += change; - bus->set_irq(bus->irq_opaque, irq_num, bus->irq_count[irq_num] != 0); -} - -int pci_bus_get_irq_level(PCIBus *bus, int irq_num) -{ - assert(irq_num >= 0); - assert(irq_num < bus->nirq); - return !!bus->irq_count[irq_num]; -} - -/* Update interrupt status bit in config space on interrupt - * state change. */ -static void pci_update_irq_status(PCIDevice *dev) -{ - if (dev->irq_state) { - dev->config[PCI_STATUS] |= PCI_STATUS_INTERRUPT; - } else { - dev->config[PCI_STATUS] &= ~PCI_STATUS_INTERRUPT; - } -} - -void pci_device_deassert_intx(PCIDevice *dev) -{ - int i; - for (i = 0; i < PCI_NUM_PINS; ++i) { - qemu_set_irq(dev->irq[i], 0); - } -} - -/* - * This function is called on #RST and FLR. - * FLR if PCI_EXP_DEVCTL_BCR_FLR is set - */ -void pci_device_reset(PCIDevice *dev) -{ - int r; - - qdev_reset_all(&dev->qdev); - - dev->irq_state = 0; - pci_update_irq_status(dev); - pci_device_deassert_intx(dev); - /* Clear all writable bits */ - pci_word_test_and_clear_mask(dev->config + PCI_COMMAND, - pci_get_word(dev->wmask + PCI_COMMAND) | - pci_get_word(dev->w1cmask + PCI_COMMAND)); - pci_word_test_and_clear_mask(dev->config + PCI_STATUS, - pci_get_word(dev->wmask + PCI_STATUS) | - pci_get_word(dev->w1cmask + PCI_STATUS)); - dev->config[PCI_CACHE_LINE_SIZE] = 0x0; - dev->config[PCI_INTERRUPT_LINE] = 0x0; - for (r = 0; r < PCI_NUM_REGIONS; ++r) { - PCIIORegion *region = &dev->io_regions[r]; - if (!region->size) { - continue; - } - - if (!(region->type & PCI_BASE_ADDRESS_SPACE_IO) && - region->type & PCI_BASE_ADDRESS_MEM_TYPE_64) { - pci_set_quad(dev->config + pci_bar(dev, r), region->type); - } else { - pci_set_long(dev->config + pci_bar(dev, r), region->type); - } - } - pci_update_mappings(dev); - - msi_reset(dev); - msix_reset(dev); -} - -/* - * Trigger pci bus reset under a given bus. - * To be called on RST# assert. - */ -void pci_bus_reset(PCIBus *bus) -{ - int i; - - for (i = 0; i < bus->nirq; i++) { - bus->irq_count[i] = 0; - } - for (i = 0; i < ARRAY_SIZE(bus->devices); ++i) { - if (bus->devices[i]) { - pci_device_reset(bus->devices[i]); - } - } -} - -static int pcibus_reset(BusState *qbus) -{ - pci_bus_reset(DO_UPCAST(PCIBus, qbus, qbus)); - - /* topology traverse is done by pci_bus_reset(). - Tell qbus/qdev walker not to traverse the tree */ - return 1; -} - -static void pci_host_bus_register(int domain, PCIBus *bus) -{ - struct PCIHostBus *host; - host = g_malloc0(sizeof(*host)); - host->domain = domain; - host->bus = bus; - QLIST_INSERT_HEAD(&host_buses, host, next); -} - -PCIBus *pci_find_root_bus(int domain) -{ - struct PCIHostBus *host; - - QLIST_FOREACH(host, &host_buses, next) { - if (host->domain == domain) { - return host->bus; - } - } - - return NULL; -} - -int pci_find_domain(const PCIBus *bus) -{ - PCIDevice *d; - struct PCIHostBus *host; - - /* obtain root bus */ - while ((d = bus->parent_dev) != NULL) { - bus = d->bus; - } - - QLIST_FOREACH(host, &host_buses, next) { - if (host->bus == bus) { - return host->domain; - } - } - - abort(); /* should not be reached */ - return -1; -} - -void pci_bus_new_inplace(PCIBus *bus, DeviceState *parent, - const char *name, - MemoryRegion *address_space_mem, - MemoryRegion *address_space_io, - uint8_t devfn_min) -{ - qbus_create_inplace(&bus->qbus, TYPE_PCI_BUS, parent, name); - assert(PCI_FUNC(devfn_min) == 0); - bus->devfn_min = devfn_min; - bus->address_space_mem = address_space_mem; - bus->address_space_io = address_space_io; - - /* host bridge */ - QLIST_INIT(&bus->child); - pci_host_bus_register(0, bus); /* for now only pci domain 0 is supported */ - - vmstate_register(NULL, -1, &vmstate_pcibus, bus); -} - -PCIBus *pci_bus_new(DeviceState *parent, const char *name, - MemoryRegion *address_space_mem, - MemoryRegion *address_space_io, - uint8_t devfn_min) -{ - PCIBus *bus; - - bus = g_malloc0(sizeof(*bus)); - bus->qbus.glib_allocated = true; - pci_bus_new_inplace(bus, parent, name, address_space_mem, - address_space_io, devfn_min); - return bus; -} - -void pci_bus_irqs(PCIBus *bus, pci_set_irq_fn set_irq, pci_map_irq_fn map_irq, - void *irq_opaque, int nirq) -{ - bus->set_irq = set_irq; - bus->map_irq = map_irq; - bus->irq_opaque = irq_opaque; - bus->nirq = nirq; - bus->irq_count = g_malloc0(nirq * sizeof(bus->irq_count[0])); -} - -void pci_bus_hotplug(PCIBus *bus, pci_hotplug_fn hotplug, DeviceState *qdev) -{ - bus->qbus.allow_hotplug = 1; - bus->hotplug = hotplug; - bus->hotplug_qdev = qdev; -} - -PCIBus *pci_register_bus(DeviceState *parent, const char *name, - pci_set_irq_fn set_irq, pci_map_irq_fn map_irq, - void *irq_opaque, - MemoryRegion *address_space_mem, - MemoryRegion *address_space_io, - uint8_t devfn_min, int nirq) -{ - PCIBus *bus; - - bus = pci_bus_new(parent, name, address_space_mem, - address_space_io, devfn_min); - pci_bus_irqs(bus, set_irq, map_irq, irq_opaque, nirq); - return bus; -} - -int pci_bus_num(PCIBus *s) -{ - if (!s->parent_dev) - return 0; /* pci host bridge */ - return s->parent_dev->config[PCI_SECONDARY_BUS]; -} - -static int get_pci_config_device(QEMUFile *f, void *pv, size_t size) -{ - PCIDevice *s = container_of(pv, PCIDevice, config); - uint8_t *config; - int i; - - assert(size == pci_config_size(s)); - config = g_malloc(size); - - qemu_get_buffer(f, config, size); - for (i = 0; i < size; ++i) { - if ((config[i] ^ s->config[i]) & - s->cmask[i] & ~s->wmask[i] & ~s->w1cmask[i]) { - g_free(config); - return -EINVAL; - } - } - memcpy(s->config, config, size); - - pci_update_mappings(s); - - g_free(config); - return 0; -} - -/* just put buffer */ -static void put_pci_config_device(QEMUFile *f, void *pv, size_t size) -{ - const uint8_t **v = pv; - assert(size == pci_config_size(container_of(pv, PCIDevice, config))); - qemu_put_buffer(f, *v, size); -} - -static VMStateInfo vmstate_info_pci_config = { - .name = "pci config", - .get = get_pci_config_device, - .put = put_pci_config_device, -}; - -static int get_pci_irq_state(QEMUFile *f, void *pv, size_t size) -{ - PCIDevice *s = container_of(pv, PCIDevice, irq_state); - uint32_t irq_state[PCI_NUM_PINS]; - int i; - for (i = 0; i < PCI_NUM_PINS; ++i) { - irq_state[i] = qemu_get_be32(f); - if (irq_state[i] != 0x1 && irq_state[i] != 0) { - fprintf(stderr, "irq state %d: must be 0 or 1.\n", - irq_state[i]); - return -EINVAL; - } - } - - for (i = 0; i < PCI_NUM_PINS; ++i) { - pci_set_irq_state(s, i, irq_state[i]); - } - - return 0; -} - -static void put_pci_irq_state(QEMUFile *f, void *pv, size_t size) -{ - int i; - PCIDevice *s = container_of(pv, PCIDevice, irq_state); - - for (i = 0; i < PCI_NUM_PINS; ++i) { - qemu_put_be32(f, pci_irq_state(s, i)); - } -} - -static VMStateInfo vmstate_info_pci_irq_state = { - .name = "pci irq state", - .get = get_pci_irq_state, - .put = put_pci_irq_state, -}; - -const VMStateDescription vmstate_pci_device = { - .name = "PCIDevice", - .version_id = 2, - .minimum_version_id = 1, - .minimum_version_id_old = 1, - .fields = (VMStateField []) { - VMSTATE_INT32_LE(version_id, PCIDevice), - VMSTATE_BUFFER_UNSAFE_INFO(config, PCIDevice, 0, - vmstate_info_pci_config, - PCI_CONFIG_SPACE_SIZE), - VMSTATE_BUFFER_UNSAFE_INFO(irq_state, PCIDevice, 2, - vmstate_info_pci_irq_state, - PCI_NUM_PINS * sizeof(int32_t)), - VMSTATE_END_OF_LIST() - } -}; - -const VMStateDescription vmstate_pcie_device = { - .name = "PCIDevice", - .version_id = 2, - .minimum_version_id = 1, - .minimum_version_id_old = 1, - .fields = (VMStateField []) { - VMSTATE_INT32_LE(version_id, PCIDevice), - VMSTATE_BUFFER_UNSAFE_INFO(config, PCIDevice, 0, - vmstate_info_pci_config, - PCIE_CONFIG_SPACE_SIZE), - VMSTATE_BUFFER_UNSAFE_INFO(irq_state, PCIDevice, 2, - vmstate_info_pci_irq_state, - PCI_NUM_PINS * sizeof(int32_t)), - VMSTATE_END_OF_LIST() - } -}; - -static inline const VMStateDescription *pci_get_vmstate(PCIDevice *s) -{ - return pci_is_express(s) ? &vmstate_pcie_device : &vmstate_pci_device; -} - -void pci_device_save(PCIDevice *s, QEMUFile *f) -{ - /* Clear interrupt status bit: it is implicit - * in irq_state which we are saving. - * This makes us compatible with old devices - * which never set or clear this bit. */ - s->config[PCI_STATUS] &= ~PCI_STATUS_INTERRUPT; - vmstate_save_state(f, pci_get_vmstate(s), s); - /* Restore the interrupt status bit. */ - pci_update_irq_status(s); -} - -int pci_device_load(PCIDevice *s, QEMUFile *f) -{ - int ret; - ret = vmstate_load_state(f, pci_get_vmstate(s), s, s->version_id); - /* Restore the interrupt status bit. */ - pci_update_irq_status(s); - return ret; -} - -static void pci_set_default_subsystem_id(PCIDevice *pci_dev) -{ - pci_set_word(pci_dev->config + PCI_SUBSYSTEM_VENDOR_ID, - pci_default_sub_vendor_id); - pci_set_word(pci_dev->config + PCI_SUBSYSTEM_ID, - pci_default_sub_device_id); -} - -/* - * Parse [[:]:], return -1 on error if funcp == NULL - * [[:]:]., return -1 on error - */ -static int pci_parse_devaddr(const char *addr, int *domp, int *busp, - unsigned int *slotp, unsigned int *funcp) -{ - const char *p; - char *e; - unsigned long val; - unsigned long dom = 0, bus = 0; - unsigned int slot = 0; - unsigned int func = 0; - - p = addr; - val = strtoul(p, &e, 16); - if (e == p) - return -1; - if (*e == ':') { - bus = val; - p = e + 1; - val = strtoul(p, &e, 16); - if (e == p) - return -1; - if (*e == ':') { - dom = bus; - bus = val; - p = e + 1; - val = strtoul(p, &e, 16); - if (e == p) - return -1; - } - } - - slot = val; - - if (funcp != NULL) { - if (*e != '.') - return -1; - - p = e + 1; - val = strtoul(p, &e, 16); - if (e == p) - return -1; - - func = val; - } - - /* if funcp == NULL func is 0 */ - if (dom > 0xffff || bus > 0xff || slot > 0x1f || func > 7) - return -1; - - if (*e) - return -1; - - *domp = dom; - *busp = bus; - *slotp = slot; - if (funcp != NULL) - *funcp = func; - return 0; -} - -int pci_read_devaddr(Monitor *mon, const char *addr, int *domp, int *busp, - unsigned *slotp) -{ - /* strip legacy tag */ - if (!strncmp(addr, "pci_addr=", 9)) { - addr += 9; - } - if (pci_parse_devaddr(addr, domp, busp, slotp, NULL)) { - monitor_printf(mon, "Invalid pci address\n"); - return -1; - } - return 0; -} - -PCIBus *pci_get_bus_devfn(int *devfnp, const char *devaddr) -{ - int dom, bus; - unsigned slot; - - if (!devaddr) { - *devfnp = -1; - return pci_find_bus_nr(pci_find_root_bus(0), 0); - } - - if (pci_parse_devaddr(devaddr, &dom, &bus, &slot, NULL) < 0) { - return NULL; - } - - *devfnp = PCI_DEVFN(slot, 0); - return pci_find_bus_nr(pci_find_root_bus(dom), bus); -} - -static void pci_init_cmask(PCIDevice *dev) -{ - pci_set_word(dev->cmask + PCI_VENDOR_ID, 0xffff); - pci_set_word(dev->cmask + PCI_DEVICE_ID, 0xffff); - dev->cmask[PCI_STATUS] = PCI_STATUS_CAP_LIST; - dev->cmask[PCI_REVISION_ID] = 0xff; - dev->cmask[PCI_CLASS_PROG] = 0xff; - pci_set_word(dev->cmask + PCI_CLASS_DEVICE, 0xffff); - dev->cmask[PCI_HEADER_TYPE] = 0xff; - dev->cmask[PCI_CAPABILITY_LIST] = 0xff; -} - -static void pci_init_wmask(PCIDevice *dev) -{ - int config_size = pci_config_size(dev); - - dev->wmask[PCI_CACHE_LINE_SIZE] = 0xff; - dev->wmask[PCI_INTERRUPT_LINE] = 0xff; - pci_set_word(dev->wmask + PCI_COMMAND, - PCI_COMMAND_IO | PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER | - PCI_COMMAND_INTX_DISABLE); - if (dev->cap_present & QEMU_PCI_CAP_SERR) { - pci_word_test_and_set_mask(dev->wmask + PCI_COMMAND, PCI_COMMAND_SERR); - } - - memset(dev->wmask + PCI_CONFIG_HEADER_SIZE, 0xff, - config_size - PCI_CONFIG_HEADER_SIZE); -} - -static void pci_init_w1cmask(PCIDevice *dev) -{ - /* - * Note: It's okay to set w1cmask even for readonly bits as - * long as their value is hardwired to 0. - */ - pci_set_word(dev->w1cmask + PCI_STATUS, - PCI_STATUS_PARITY | PCI_STATUS_SIG_TARGET_ABORT | - PCI_STATUS_REC_TARGET_ABORT | PCI_STATUS_REC_MASTER_ABORT | - PCI_STATUS_SIG_SYSTEM_ERROR | PCI_STATUS_DETECTED_PARITY); -} - -static void pci_init_mask_bridge(PCIDevice *d) -{ - /* PCI_PRIMARY_BUS, PCI_SECONDARY_BUS, PCI_SUBORDINATE_BUS and - PCI_SEC_LETENCY_TIMER */ - memset(d->wmask + PCI_PRIMARY_BUS, 0xff, 4); - - /* base and limit */ - d->wmask[PCI_IO_BASE] = PCI_IO_RANGE_MASK & 0xff; - d->wmask[PCI_IO_LIMIT] = PCI_IO_RANGE_MASK & 0xff; - pci_set_word(d->wmask + PCI_MEMORY_BASE, - PCI_MEMORY_RANGE_MASK & 0xffff); - pci_set_word(d->wmask + PCI_MEMORY_LIMIT, - PCI_MEMORY_RANGE_MASK & 0xffff); - pci_set_word(d->wmask + PCI_PREF_MEMORY_BASE, - PCI_PREF_RANGE_MASK & 0xffff); - pci_set_word(d->wmask + PCI_PREF_MEMORY_LIMIT, - PCI_PREF_RANGE_MASK & 0xffff); - - /* PCI_PREF_BASE_UPPER32 and PCI_PREF_LIMIT_UPPER32 */ - memset(d->wmask + PCI_PREF_BASE_UPPER32, 0xff, 8); - - /* Supported memory and i/o types */ - d->config[PCI_IO_BASE] |= PCI_IO_RANGE_TYPE_16; - d->config[PCI_IO_LIMIT] |= PCI_IO_RANGE_TYPE_16; - pci_word_test_and_set_mask(d->config + PCI_PREF_MEMORY_BASE, - PCI_PREF_RANGE_TYPE_64); - pci_word_test_and_set_mask(d->config + PCI_PREF_MEMORY_LIMIT, - PCI_PREF_RANGE_TYPE_64); - -/* TODO: add this define to pci_regs.h in linux and then in qemu. */ -#define PCI_BRIDGE_CTL_VGA_16BIT 0x10 /* VGA 16-bit decode */ -#define PCI_BRIDGE_CTL_DISCARD 0x100 /* Primary discard timer */ -#define PCI_BRIDGE_CTL_SEC_DISCARD 0x200 /* Secondary discard timer */ -#define PCI_BRIDGE_CTL_DISCARD_STATUS 0x400 /* Discard timer status */ -#define PCI_BRIDGE_CTL_DISCARD_SERR 0x800 /* Discard timer SERR# enable */ - pci_set_word(d->wmask + PCI_BRIDGE_CONTROL, - PCI_BRIDGE_CTL_PARITY | - PCI_BRIDGE_CTL_SERR | - PCI_BRIDGE_CTL_ISA | - PCI_BRIDGE_CTL_VGA | - PCI_BRIDGE_CTL_VGA_16BIT | - PCI_BRIDGE_CTL_MASTER_ABORT | - PCI_BRIDGE_CTL_BUS_RESET | - PCI_BRIDGE_CTL_FAST_BACK | - PCI_BRIDGE_CTL_DISCARD | - PCI_BRIDGE_CTL_SEC_DISCARD | - PCI_BRIDGE_CTL_DISCARD_SERR); - /* Below does not do anything as we never set this bit, put here for - * completeness. */ - pci_set_word(d->w1cmask + PCI_BRIDGE_CONTROL, - PCI_BRIDGE_CTL_DISCARD_STATUS); - d->cmask[PCI_IO_BASE] |= PCI_IO_RANGE_TYPE_MASK; - d->cmask[PCI_IO_LIMIT] |= PCI_IO_RANGE_TYPE_MASK; - pci_word_test_and_set_mask(d->cmask + PCI_PREF_MEMORY_BASE, - PCI_PREF_RANGE_TYPE_MASK); - pci_word_test_and_set_mask(d->cmask + PCI_PREF_MEMORY_LIMIT, - PCI_PREF_RANGE_TYPE_MASK); -} - -static int pci_init_multifunction(PCIBus *bus, PCIDevice *dev) -{ - uint8_t slot = PCI_SLOT(dev->devfn); - uint8_t func; - - if (dev->cap_present & QEMU_PCI_CAP_MULTIFUNCTION) { - dev->config[PCI_HEADER_TYPE] |= PCI_HEADER_TYPE_MULTI_FUNCTION; - } - - /* - * multifunction bit is interpreted in two ways as follows. - * - all functions must set the bit to 1. - * Example: Intel X53 - * - function 0 must set the bit, but the rest function (> 0) - * is allowed to leave the bit to 0. - * Example: PIIX3(also in qemu), PIIX4(also in qemu), ICH10, - * - * So OS (at least Linux) checks the bit of only function 0, - * and doesn't see the bit of function > 0. - * - * The below check allows both interpretation. - */ - if (PCI_FUNC(dev->devfn)) { - PCIDevice *f0 = bus->devices[PCI_DEVFN(slot, 0)]; - if (f0 && !(f0->cap_present & QEMU_PCI_CAP_MULTIFUNCTION)) { - /* function 0 should set multifunction bit */ - error_report("PCI: single function device can't be populated " - "in function %x.%x", slot, PCI_FUNC(dev->devfn)); - return -1; - } - return 0; - } - - if (dev->cap_present & QEMU_PCI_CAP_MULTIFUNCTION) { - return 0; - } - /* function 0 indicates single function, so function > 0 must be NULL */ - for (func = 1; func < PCI_FUNC_MAX; ++func) { - if (bus->devices[PCI_DEVFN(slot, func)]) { - error_report("PCI: %x.0 indicates single function, " - "but %x.%x is already populated.", - slot, slot, func); - return -1; - } - } - return 0; -} - -static void pci_config_alloc(PCIDevice *pci_dev) -{ - int config_size = pci_config_size(pci_dev); - - pci_dev->config = g_malloc0(config_size); - pci_dev->cmask = g_malloc0(config_size); - pci_dev->wmask = g_malloc0(config_size); - pci_dev->w1cmask = g_malloc0(config_size); - pci_dev->used = g_malloc0(config_size); -} - -static void pci_config_free(PCIDevice *pci_dev) -{ - g_free(pci_dev->config); - g_free(pci_dev->cmask); - g_free(pci_dev->wmask); - g_free(pci_dev->w1cmask); - g_free(pci_dev->used); -} - -/* -1 for devfn means auto assign */ -static PCIDevice *do_pci_register_device(PCIDevice *pci_dev, PCIBus *bus, - const char *name, int devfn) -{ - PCIDeviceClass *pc = PCI_DEVICE_GET_CLASS(pci_dev); - PCIConfigReadFunc *config_read = pc->config_read; - PCIConfigWriteFunc *config_write = pc->config_write; - - if (devfn < 0) { - for(devfn = bus->devfn_min ; devfn < ARRAY_SIZE(bus->devices); - devfn += PCI_FUNC_MAX) { - if (!bus->devices[devfn]) - goto found; - } - error_report("PCI: no slot/function available for %s, all in use", name); - return NULL; - found: ; - } else if (bus->devices[devfn]) { - error_report("PCI: slot %d function %d not available for %s, in use by %s", - PCI_SLOT(devfn), PCI_FUNC(devfn), name, bus->devices[devfn]->name); - return NULL; - } - pci_dev->bus = bus; - if (bus->dma_context_fn) { - pci_dev->dma = bus->dma_context_fn(bus, bus->dma_context_opaque, devfn); - } - pci_dev->devfn = devfn; - pstrcpy(pci_dev->name, sizeof(pci_dev->name), name); - pci_dev->irq_state = 0; - pci_config_alloc(pci_dev); - - pci_config_set_vendor_id(pci_dev->config, pc->vendor_id); - pci_config_set_device_id(pci_dev->config, pc->device_id); - pci_config_set_revision(pci_dev->config, pc->revision); - pci_config_set_class(pci_dev->config, pc->class_id); - - if (!pc->is_bridge) { - if (pc->subsystem_vendor_id || pc->subsystem_id) { - pci_set_word(pci_dev->config + PCI_SUBSYSTEM_VENDOR_ID, - pc->subsystem_vendor_id); - pci_set_word(pci_dev->config + PCI_SUBSYSTEM_ID, - pc->subsystem_id); - } else { - pci_set_default_subsystem_id(pci_dev); - } - } else { - /* subsystem_vendor_id/subsystem_id are only for header type 0 */ - assert(!pc->subsystem_vendor_id); - assert(!pc->subsystem_id); - } - pci_init_cmask(pci_dev); - pci_init_wmask(pci_dev); - pci_init_w1cmask(pci_dev); - if (pc->is_bridge) { - pci_init_mask_bridge(pci_dev); - } - if (pci_init_multifunction(bus, pci_dev)) { - pci_config_free(pci_dev); - return NULL; - } - - if (!config_read) - config_read = pci_default_read_config; - if (!config_write) - config_write = pci_default_write_config; - pci_dev->config_read = config_read; - pci_dev->config_write = config_write; - bus->devices[devfn] = pci_dev; - pci_dev->irq = qemu_allocate_irqs(pci_set_irq, pci_dev, PCI_NUM_PINS); - pci_dev->version_id = 2; /* Current pci device vmstate version */ - return pci_dev; -} - -static void do_pci_unregister_device(PCIDevice *pci_dev) -{ - qemu_free_irqs(pci_dev->irq); - pci_dev->bus->devices[pci_dev->devfn] = NULL; - pci_config_free(pci_dev); -} - -static void pci_unregister_io_regions(PCIDevice *pci_dev) -{ - PCIIORegion *r; - int i; - - for(i = 0; i < PCI_NUM_REGIONS; i++) { - r = &pci_dev->io_regions[i]; - if (!r->size || r->addr == PCI_BAR_UNMAPPED) - continue; - memory_region_del_subregion(r->address_space, r->memory); - } -} - -static int pci_unregister_device(DeviceState *dev) -{ - PCIDevice *pci_dev = PCI_DEVICE(dev); - PCIDeviceClass *pc = PCI_DEVICE_GET_CLASS(pci_dev); - - pci_unregister_io_regions(pci_dev); - pci_del_option_rom(pci_dev); - - if (pc->exit) { - pc->exit(pci_dev); - } - - do_pci_unregister_device(pci_dev); - return 0; -} - -void pci_register_bar(PCIDevice *pci_dev, int region_num, - uint8_t type, MemoryRegion *memory) -{ - PCIIORegion *r; - uint32_t addr; - uint64_t wmask; - pcibus_t size = memory_region_size(memory); - - assert(region_num >= 0); - assert(region_num < PCI_NUM_REGIONS); - if (size & (size-1)) { - fprintf(stderr, "ERROR: PCI region size must be pow2 " - "type=0x%x, size=0x%"FMT_PCIBUS"\n", type, size); - exit(1); - } - - r = &pci_dev->io_regions[region_num]; - r->addr = PCI_BAR_UNMAPPED; - r->size = size; - r->type = type; - r->memory = NULL; - - wmask = ~(size - 1); - addr = pci_bar(pci_dev, region_num); - if (region_num == PCI_ROM_SLOT) { - /* ROM enable bit is writable */ - wmask |= PCI_ROM_ADDRESS_ENABLE; - } - pci_set_long(pci_dev->config + addr, type); - if (!(r->type & PCI_BASE_ADDRESS_SPACE_IO) && - r->type & PCI_BASE_ADDRESS_MEM_TYPE_64) { - pci_set_quad(pci_dev->wmask + addr, wmask); - pci_set_quad(pci_dev->cmask + addr, ~0ULL); - } else { - pci_set_long(pci_dev->wmask + addr, wmask & 0xffffffff); - pci_set_long(pci_dev->cmask + addr, 0xffffffff); - } - pci_dev->io_regions[region_num].memory = memory; - pci_dev->io_regions[region_num].address_space - = type & PCI_BASE_ADDRESS_SPACE_IO - ? pci_dev->bus->address_space_io - : pci_dev->bus->address_space_mem; -} - -pcibus_t pci_get_bar_addr(PCIDevice *pci_dev, int region_num) -{ - return pci_dev->io_regions[region_num].addr; -} - -static pcibus_t pci_bar_address(PCIDevice *d, - int reg, uint8_t type, pcibus_t size) -{ - pcibus_t new_addr, last_addr; - int bar = pci_bar(d, reg); - uint16_t cmd = pci_get_word(d->config + PCI_COMMAND); - - if (type & PCI_BASE_ADDRESS_SPACE_IO) { - if (!(cmd & PCI_COMMAND_IO)) { - return PCI_BAR_UNMAPPED; - } - new_addr = pci_get_long(d->config + bar) & ~(size - 1); - last_addr = new_addr + size - 1; - /* NOTE: we have only 64K ioports on PC */ - if (last_addr <= new_addr || new_addr == 0 || last_addr > UINT16_MAX) { - return PCI_BAR_UNMAPPED; - } - return new_addr; - } - - if (!(cmd & PCI_COMMAND_MEMORY)) { - return PCI_BAR_UNMAPPED; - } - if (type & PCI_BASE_ADDRESS_MEM_TYPE_64) { - new_addr = pci_get_quad(d->config + bar); - } else { - new_addr = pci_get_long(d->config + bar); - } - /* the ROM slot has a specific enable bit */ - if (reg == PCI_ROM_SLOT && !(new_addr & PCI_ROM_ADDRESS_ENABLE)) { - return PCI_BAR_UNMAPPED; - } - new_addr &= ~(size - 1); - last_addr = new_addr + size - 1; - /* NOTE: we do not support wrapping */ - /* XXX: as we cannot support really dynamic - mappings, we handle specific values as invalid - mappings. */ - if (last_addr <= new_addr || new_addr == 0 || - last_addr == PCI_BAR_UNMAPPED) { - return PCI_BAR_UNMAPPED; - } - - /* Now pcibus_t is 64bit. - * Check if 32 bit BAR wraps around explicitly. - * Without this, PC ide doesn't work well. - * TODO: remove this work around. - */ - if (!(type & PCI_BASE_ADDRESS_MEM_TYPE_64) && last_addr >= UINT32_MAX) { - return PCI_BAR_UNMAPPED; - } - - /* - * OS is allowed to set BAR beyond its addressable - * bits. For example, 32 bit OS can set 64bit bar - * to >4G. Check it. TODO: we might need to support - * it in the future for e.g. PAE. - */ - if (last_addr >= TARGET_PHYS_ADDR_MAX) { - return PCI_BAR_UNMAPPED; - } - - return new_addr; -} - -static void pci_update_mappings(PCIDevice *d) -{ - PCIIORegion *r; - int i; - pcibus_t new_addr; - - for(i = 0; i < PCI_NUM_REGIONS; i++) { - r = &d->io_regions[i]; - - /* this region isn't registered */ - if (!r->size) - continue; - - new_addr = pci_bar_address(d, i, r->type, r->size); - - /* This bar isn't changed */ - if (new_addr == r->addr) - continue; - - /* now do the real mapping */ - if (r->addr != PCI_BAR_UNMAPPED) { - memory_region_del_subregion(r->address_space, r->memory); - } - r->addr = new_addr; - if (r->addr != PCI_BAR_UNMAPPED) { - memory_region_add_subregion_overlap(r->address_space, - r->addr, r->memory, 1); - } - } -} - -static inline int pci_irq_disabled(PCIDevice *d) -{ - return pci_get_word(d->config + PCI_COMMAND) & PCI_COMMAND_INTX_DISABLE; -} - -/* Called after interrupt disabled field update in config space, - * assert/deassert interrupts if necessary. - * Gets original interrupt disable bit value (before update). */ -static void pci_update_irq_disabled(PCIDevice *d, int was_irq_disabled) -{ - int i, disabled = pci_irq_disabled(d); - if (disabled == was_irq_disabled) - return; - for (i = 0; i < PCI_NUM_PINS; ++i) { - int state = pci_irq_state(d, i); - pci_change_irq_level(d, i, disabled ? -state : state); - } -} - -uint32_t pci_default_read_config(PCIDevice *d, - uint32_t address, int len) -{ - uint32_t val = 0; - - memcpy(&val, d->config + address, len); - return le32_to_cpu(val); -} - -void pci_default_write_config(PCIDevice *d, uint32_t addr, uint32_t val, int l) -{ - int i, was_irq_disabled = pci_irq_disabled(d); - - for (i = 0; i < l; val >>= 8, ++i) { - uint8_t wmask = d->wmask[addr + i]; - uint8_t w1cmask = d->w1cmask[addr + i]; - assert(!(wmask & w1cmask)); - d->config[addr + i] = (d->config[addr + i] & ~wmask) | (val & wmask); - d->config[addr + i] &= ~(val & w1cmask); /* W1C: Write 1 to Clear */ - } - if (ranges_overlap(addr, l, PCI_BASE_ADDRESS_0, 24) || - ranges_overlap(addr, l, PCI_ROM_ADDRESS, 4) || - ranges_overlap(addr, l, PCI_ROM_ADDRESS1, 4) || - range_covers_byte(addr, l, PCI_COMMAND)) - pci_update_mappings(d); - - if (range_covers_byte(addr, l, PCI_COMMAND)) - pci_update_irq_disabled(d, was_irq_disabled); - - msi_write_config(d, addr, val, l); - msix_write_config(d, addr, val, l); -} - -/***********************************************************/ -/* generic PCI irq support */ - -/* 0 <= irq_num <= 3. level must be 0 or 1 */ -static void pci_set_irq(void *opaque, int irq_num, int level) -{ - PCIDevice *pci_dev = opaque; - int change; - - change = level - pci_irq_state(pci_dev, irq_num); - if (!change) - return; - - pci_set_irq_state(pci_dev, irq_num, level); - pci_update_irq_status(pci_dev); - if (pci_irq_disabled(pci_dev)) - return; - pci_change_irq_level(pci_dev, irq_num, change); -} - -/* Special hooks used by device assignment */ -void pci_bus_set_route_irq_fn(PCIBus *bus, pci_route_irq_fn route_intx_to_irq) -{ - assert(!bus->parent_dev); - bus->route_intx_to_irq = route_intx_to_irq; -} - -PCIINTxRoute pci_device_route_intx_to_irq(PCIDevice *dev, int pin) -{ - PCIBus *bus; - - do { - bus = dev->bus; - pin = bus->map_irq(dev, pin); - dev = bus->parent_dev; - } while (dev); - assert(bus->route_intx_to_irq); - return bus->route_intx_to_irq(bus->irq_opaque, pin); -} - -void pci_bus_fire_intx_routing_notifier(PCIBus *bus) -{ - PCIDevice *dev; - PCIBus *sec; - int i; - - for (i = 0; i < ARRAY_SIZE(bus->devices); ++i) { - dev = bus->devices[i]; - if (dev && dev->intx_routing_notifier) { - dev->intx_routing_notifier(dev); - } - QLIST_FOREACH(sec, &bus->child, sibling) { - pci_bus_fire_intx_routing_notifier(sec); - } - } -} - -void pci_device_set_intx_routing_notifier(PCIDevice *dev, - PCIINTxRoutingNotifier notifier) -{ - dev->intx_routing_notifier = notifier; -} - -/***********************************************************/ -/* monitor info on PCI */ - -typedef struct { - uint16_t class; - const char *desc; - const char *fw_name; - uint16_t fw_ign_bits; -} pci_class_desc; - -static const pci_class_desc pci_class_descriptions[] = -{ - { 0x0001, "VGA controller", "display"}, - { 0x0100, "SCSI controller", "scsi"}, - { 0x0101, "IDE controller", "ide"}, - { 0x0102, "Floppy controller", "fdc"}, - { 0x0103, "IPI controller", "ipi"}, - { 0x0104, "RAID controller", "raid"}, - { 0x0106, "SATA controller"}, - { 0x0107, "SAS controller"}, - { 0x0180, "Storage controller"}, - { 0x0200, "Ethernet controller", "ethernet"}, - { 0x0201, "Token Ring controller", "token-ring"}, - { 0x0202, "FDDI controller", "fddi"}, - { 0x0203, "ATM controller", "atm"}, - { 0x0280, "Network controller"}, - { 0x0300, "VGA controller", "display", 0x00ff}, - { 0x0301, "XGA controller"}, - { 0x0302, "3D controller"}, - { 0x0380, "Display controller"}, - { 0x0400, "Video controller", "video"}, - { 0x0401, "Audio controller", "sound"}, - { 0x0402, "Phone"}, - { 0x0403, "Audio controller", "sound"}, - { 0x0480, "Multimedia controller"}, - { 0x0500, "RAM controller", "memory"}, - { 0x0501, "Flash controller", "flash"}, - { 0x0580, "Memory controller"}, - { 0x0600, "Host bridge", "host"}, - { 0x0601, "ISA bridge", "isa"}, - { 0x0602, "EISA bridge", "eisa"}, - { 0x0603, "MC bridge", "mca"}, - { 0x0604, "PCI bridge", "pci"}, - { 0x0605, "PCMCIA bridge", "pcmcia"}, - { 0x0606, "NUBUS bridge", "nubus"}, - { 0x0607, "CARDBUS bridge", "cardbus"}, - { 0x0608, "RACEWAY bridge"}, - { 0x0680, "Bridge"}, - { 0x0700, "Serial port", "serial"}, - { 0x0701, "Parallel port", "parallel"}, - { 0x0800, "Interrupt controller", "interrupt-controller"}, - { 0x0801, "DMA controller", "dma-controller"}, - { 0x0802, "Timer", "timer"}, - { 0x0803, "RTC", "rtc"}, - { 0x0900, "Keyboard", "keyboard"}, - { 0x0901, "Pen", "pen"}, - { 0x0902, "Mouse", "mouse"}, - { 0x0A00, "Dock station", "dock", 0x00ff}, - { 0x0B00, "i386 cpu", "cpu", 0x00ff}, - { 0x0c00, "Fireware contorller", "fireware"}, - { 0x0c01, "Access bus controller", "access-bus"}, - { 0x0c02, "SSA controller", "ssa"}, - { 0x0c03, "USB controller", "usb"}, - { 0x0c04, "Fibre channel controller", "fibre-channel"}, - { 0, NULL} -}; - -static void pci_for_each_device_under_bus(PCIBus *bus, - void (*fn)(PCIBus *b, PCIDevice *d, - void *opaque), - void *opaque) -{ - PCIDevice *d; - int devfn; - - for(devfn = 0; devfn < ARRAY_SIZE(bus->devices); devfn++) { - d = bus->devices[devfn]; - if (d) { - fn(bus, d, opaque); - } - } -} - -void pci_for_each_device(PCIBus *bus, int bus_num, - void (*fn)(PCIBus *b, PCIDevice *d, void *opaque), - void *opaque) -{ - bus = pci_find_bus_nr(bus, bus_num); - - if (bus) { - pci_for_each_device_under_bus(bus, fn, opaque); - } -} - -static const pci_class_desc *get_class_desc(int class) -{ - const pci_class_desc *desc; - - desc = pci_class_descriptions; - while (desc->desc && class != desc->class) { - desc++; - } - - return desc; -} - -static PciDeviceInfoList *qmp_query_pci_devices(PCIBus *bus, int bus_num); - -static PciMemoryRegionList *qmp_query_pci_regions(const PCIDevice *dev) -{ - PciMemoryRegionList *head = NULL, *cur_item = NULL; - int i; - - for (i = 0; i < PCI_NUM_REGIONS; i++) { - const PCIIORegion *r = &dev->io_regions[i]; - PciMemoryRegionList *region; - - if (!r->size) { - continue; - } - - region = g_malloc0(sizeof(*region)); - region->value = g_malloc0(sizeof(*region->value)); - - if (r->type & PCI_BASE_ADDRESS_SPACE_IO) { - region->value->type = g_strdup("io"); - } else { - region->value->type = g_strdup("memory"); - region->value->has_prefetch = true; - region->value->prefetch = !!(r->type & PCI_BASE_ADDRESS_MEM_PREFETCH); - region->value->has_mem_type_64 = true; - region->value->mem_type_64 = !!(r->type & PCI_BASE_ADDRESS_MEM_TYPE_64); - } - - region->value->bar = i; - region->value->address = r->addr; - region->value->size = r->size; - - /* XXX: waiting for the qapi to support GSList */ - if (!cur_item) { - head = cur_item = region; - } else { - cur_item->next = region; - cur_item = region; - } - } - - return head; -} - -static PciBridgeInfo *qmp_query_pci_bridge(PCIDevice *dev, PCIBus *bus, - int bus_num) -{ - PciBridgeInfo *info; - - info = g_malloc0(sizeof(*info)); - - info->bus.number = dev->config[PCI_PRIMARY_BUS]; - info->bus.secondary = dev->config[PCI_SECONDARY_BUS]; - info->bus.subordinate = dev->config[PCI_SUBORDINATE_BUS]; - - info->bus.io_range = g_malloc0(sizeof(*info->bus.io_range)); - info->bus.io_range->base = pci_bridge_get_base(dev, PCI_BASE_ADDRESS_SPACE_IO); - info->bus.io_range->limit = pci_bridge_get_limit(dev, PCI_BASE_ADDRESS_SPACE_IO); - - info->bus.memory_range = g_malloc0(sizeof(*info->bus.memory_range)); - info->bus.memory_range->base = pci_bridge_get_base(dev, PCI_BASE_ADDRESS_SPACE_MEMORY); - info->bus.memory_range->limit = pci_bridge_get_limit(dev, PCI_BASE_ADDRESS_SPACE_MEMORY); - - info->bus.prefetchable_range = g_malloc0(sizeof(*info->bus.prefetchable_range)); - info->bus.prefetchable_range->base = pci_bridge_get_base(dev, PCI_BASE_ADDRESS_MEM_PREFETCH); - info->bus.prefetchable_range->limit = pci_bridge_get_limit(dev, PCI_BASE_ADDRESS_MEM_PREFETCH); - - if (dev->config[PCI_SECONDARY_BUS] != 0) { - PCIBus *child_bus = pci_find_bus_nr(bus, dev->config[PCI_SECONDARY_BUS]); - if (child_bus) { - info->has_devices = true; - info->devices = qmp_query_pci_devices(child_bus, dev->config[PCI_SECONDARY_BUS]); - } - } - - return info; -} - -static PciDeviceInfo *qmp_query_pci_device(PCIDevice *dev, PCIBus *bus, - int bus_num) -{ - const pci_class_desc *desc; - PciDeviceInfo *info; - uint8_t type; - int class; - - info = g_malloc0(sizeof(*info)); - info->bus = bus_num; - info->slot = PCI_SLOT(dev->devfn); - info->function = PCI_FUNC(dev->devfn); - - class = pci_get_word(dev->config + PCI_CLASS_DEVICE); - info->class_info.class = class; - desc = get_class_desc(class); - if (desc->desc) { - info->class_info.has_desc = true; - info->class_info.desc = g_strdup(desc->desc); - } - - info->id.vendor = pci_get_word(dev->config + PCI_VENDOR_ID); - info->id.device = pci_get_word(dev->config + PCI_DEVICE_ID); - info->regions = qmp_query_pci_regions(dev); - info->qdev_id = g_strdup(dev->qdev.id ? dev->qdev.id : ""); - - if (dev->config[PCI_INTERRUPT_PIN] != 0) { - info->has_irq = true; - info->irq = dev->config[PCI_INTERRUPT_LINE]; - } - - type = dev->config[PCI_HEADER_TYPE] & ~PCI_HEADER_TYPE_MULTI_FUNCTION; - if (type == PCI_HEADER_TYPE_BRIDGE) { - info->has_pci_bridge = true; - info->pci_bridge = qmp_query_pci_bridge(dev, bus, bus_num); - } - - return info; -} - -static PciDeviceInfoList *qmp_query_pci_devices(PCIBus *bus, int bus_num) -{ - PciDeviceInfoList *info, *head = NULL, *cur_item = NULL; - PCIDevice *dev; - int devfn; - - for (devfn = 0; devfn < ARRAY_SIZE(bus->devices); devfn++) { - dev = bus->devices[devfn]; - if (dev) { - info = g_malloc0(sizeof(*info)); - info->value = qmp_query_pci_device(dev, bus, bus_num); - - /* XXX: waiting for the qapi to support GSList */ - if (!cur_item) { - head = cur_item = info; - } else { - cur_item->next = info; - cur_item = info; - } - } - } - - return head; -} - -static PciInfo *qmp_query_pci_bus(PCIBus *bus, int bus_num) -{ - PciInfo *info = NULL; - - bus = pci_find_bus_nr(bus, bus_num); - if (bus) { - info = g_malloc0(sizeof(*info)); - info->bus = bus_num; - info->devices = qmp_query_pci_devices(bus, bus_num); - } - - return info; -} - -PciInfoList *qmp_query_pci(Error **errp) -{ - PciInfoList *info, *head = NULL, *cur_item = NULL; - struct PCIHostBus *host; - - QLIST_FOREACH(host, &host_buses, next) { - info = g_malloc0(sizeof(*info)); - info->value = qmp_query_pci_bus(host->bus, 0); - - /* XXX: waiting for the qapi to support GSList */ - if (!cur_item) { - head = cur_item = info; - } else { - cur_item->next = info; - cur_item = info; - } - } - - return head; -} - -static const char * const pci_nic_models[] = { - "ne2k_pci", - "i82551", - "i82557b", - "i82559er", - "rtl8139", - "e1000", - "pcnet", - "virtio", - NULL -}; - -static const char * const pci_nic_names[] = { - "ne2k_pci", - "i82551", - "i82557b", - "i82559er", - "rtl8139", - "e1000", - "pcnet", - "virtio-net-pci", - NULL -}; - -/* Initialize a PCI NIC. */ -/* FIXME callers should check for failure, but don't */ -PCIDevice *pci_nic_init(NICInfo *nd, const char *default_model, - const char *default_devaddr) -{ - const char *devaddr = nd->devaddr ? nd->devaddr : default_devaddr; - PCIBus *bus; - int devfn; - PCIDevice *pci_dev; - DeviceState *dev; - int i; - - i = qemu_find_nic_model(nd, pci_nic_models, default_model); - if (i < 0) - return NULL; - - bus = pci_get_bus_devfn(&devfn, devaddr); - if (!bus) { - error_report("Invalid PCI device address %s for device %s", - devaddr, pci_nic_names[i]); - return NULL; - } - - pci_dev = pci_create(bus, devfn, pci_nic_names[i]); - dev = &pci_dev->qdev; - qdev_set_nic_properties(dev, nd); - if (qdev_init(dev) < 0) - return NULL; - return pci_dev; -} - -PCIDevice *pci_nic_init_nofail(NICInfo *nd, const char *default_model, - const char *default_devaddr) -{ - PCIDevice *res; - - if (qemu_show_nic_models(nd->model, pci_nic_models)) - exit(0); - - res = pci_nic_init(nd, default_model, default_devaddr); - if (!res) - exit(1); - return res; -} - -/* Whether a given bus number is in range of the secondary - * bus of the given bridge device. */ -static bool pci_secondary_bus_in_range(PCIDevice *dev, int bus_num) -{ - return !(pci_get_word(dev->config + PCI_BRIDGE_CONTROL) & - PCI_BRIDGE_CTL_BUS_RESET) /* Don't walk the bus if it's reset. */ && - dev->config[PCI_SECONDARY_BUS] < bus_num && - bus_num <= dev->config[PCI_SUBORDINATE_BUS]; -} - -static PCIBus *pci_find_bus_nr(PCIBus *bus, int bus_num) -{ - PCIBus *sec; - - if (!bus) { - return NULL; - } - - if (pci_bus_num(bus) == bus_num) { - return bus; - } - - /* Consider all bus numbers in range for the host pci bridge. */ - if (bus->parent_dev && - !pci_secondary_bus_in_range(bus->parent_dev, bus_num)) { - return NULL; - } - - /* try child bus */ - for (; bus; bus = sec) { - QLIST_FOREACH(sec, &bus->child, sibling) { - assert(sec->parent_dev); - if (sec->parent_dev->config[PCI_SECONDARY_BUS] == bus_num) { - return sec; - } - if (pci_secondary_bus_in_range(sec->parent_dev, bus_num)) { - break; - } - } - } - - return NULL; -} - -PCIDevice *pci_find_device(PCIBus *bus, int bus_num, uint8_t devfn) -{ - bus = pci_find_bus_nr(bus, bus_num); - - if (!bus) - return NULL; - - return bus->devices[devfn]; -} - -static int pci_qdev_init(DeviceState *qdev) -{ - PCIDevice *pci_dev = (PCIDevice *)qdev; - PCIDeviceClass *pc = PCI_DEVICE_GET_CLASS(pci_dev); - PCIBus *bus; - int rc; - bool is_default_rom; - - /* initialize cap_present for pci_is_express() and pci_config_size() */ - if (pc->is_express) { - pci_dev->cap_present |= QEMU_PCI_CAP_EXPRESS; - } - - bus = FROM_QBUS(PCIBus, qdev_get_parent_bus(qdev)); - pci_dev = do_pci_register_device(pci_dev, bus, - object_get_typename(OBJECT(qdev)), - pci_dev->devfn); - if (pci_dev == NULL) - return -1; - if (qdev->hotplugged && pc->no_hotplug) { - qerror_report(QERR_DEVICE_NO_HOTPLUG, object_get_typename(OBJECT(pci_dev))); - do_pci_unregister_device(pci_dev); - return -1; - } - if (pc->init) { - rc = pc->init(pci_dev); - if (rc != 0) { - do_pci_unregister_device(pci_dev); - return rc; - } - } - - /* rom loading */ - is_default_rom = false; - if (pci_dev->romfile == NULL && pc->romfile != NULL) { - pci_dev->romfile = g_strdup(pc->romfile); - is_default_rom = true; - } - pci_add_option_rom(pci_dev, is_default_rom); - - if (bus->hotplug) { - /* Let buses differentiate between hotplug and when device is - * enabled during qemu machine creation. */ - rc = bus->hotplug(bus->hotplug_qdev, pci_dev, - qdev->hotplugged ? PCI_HOTPLUG_ENABLED: - PCI_COLDPLUG_ENABLED); - if (rc != 0) { - int r = pci_unregister_device(&pci_dev->qdev); - assert(!r); - return rc; - } - } - return 0; -} - -static int pci_unplug_device(DeviceState *qdev) -{ - PCIDevice *dev = PCI_DEVICE(qdev); - PCIDeviceClass *pc = PCI_DEVICE_GET_CLASS(dev); - - if (pc->no_hotplug) { - qerror_report(QERR_DEVICE_NO_HOTPLUG, object_get_typename(OBJECT(dev))); - return -1; - } - return dev->bus->hotplug(dev->bus->hotplug_qdev, dev, - PCI_HOTPLUG_DISABLED); -} - -PCIDevice *pci_create_multifunction(PCIBus *bus, int devfn, bool multifunction, - const char *name) -{ - DeviceState *dev; - - dev = qdev_create(&bus->qbus, name); - qdev_prop_set_int32(dev, "addr", devfn); - qdev_prop_set_bit(dev, "multifunction", multifunction); - return PCI_DEVICE(dev); -} - -PCIDevice *pci_create_simple_multifunction(PCIBus *bus, int devfn, - bool multifunction, - const char *name) -{ - PCIDevice *dev = pci_create_multifunction(bus, devfn, multifunction, name); - qdev_init_nofail(&dev->qdev); - return dev; -} - -PCIDevice *pci_create(PCIBus *bus, int devfn, const char *name) -{ - return pci_create_multifunction(bus, devfn, false, name); -} - -PCIDevice *pci_create_simple(PCIBus *bus, int devfn, const char *name) -{ - return pci_create_simple_multifunction(bus, devfn, false, name); -} - -static int pci_find_space(PCIDevice *pdev, uint8_t size) -{ - int config_size = pci_config_size(pdev); - int offset = PCI_CONFIG_HEADER_SIZE; - int i; - for (i = PCI_CONFIG_HEADER_SIZE; i < config_size; ++i) - if (pdev->used[i]) - offset = i + 1; - else if (i - offset + 1 == size) - return offset; - return 0; -} - -static uint8_t pci_find_capability_list(PCIDevice *pdev, uint8_t cap_id, - uint8_t *prev_p) -{ - uint8_t next, prev; - - if (!(pdev->config[PCI_STATUS] & PCI_STATUS_CAP_LIST)) - return 0; - - for (prev = PCI_CAPABILITY_LIST; (next = pdev->config[prev]); - prev = next + PCI_CAP_LIST_NEXT) - if (pdev->config[next + PCI_CAP_LIST_ID] == cap_id) - break; - - if (prev_p) - *prev_p = prev; - return next; -} - -static uint8_t pci_find_capability_at_offset(PCIDevice *pdev, uint8_t offset) -{ - uint8_t next, prev, found = 0; - - if (!(pdev->used[offset])) { - return 0; - } - - assert(pdev->config[PCI_STATUS] & PCI_STATUS_CAP_LIST); - - for (prev = PCI_CAPABILITY_LIST; (next = pdev->config[prev]); - prev = next + PCI_CAP_LIST_NEXT) { - if (next <= offset && next > found) { - found = next; - } - } - return found; -} - -/* Patch the PCI vendor and device ids in a PCI rom image if necessary. - This is needed for an option rom which is used for more than one device. */ -static void pci_patch_ids(PCIDevice *pdev, uint8_t *ptr, int size) -{ - uint16_t vendor_id; - uint16_t device_id; - uint16_t rom_vendor_id; - uint16_t rom_device_id; - uint16_t rom_magic; - uint16_t pcir_offset; - uint8_t checksum; - - /* Words in rom data are little endian (like in PCI configuration), - so they can be read / written with pci_get_word / pci_set_word. */ - - /* Only a valid rom will be patched. */ - rom_magic = pci_get_word(ptr); - if (rom_magic != 0xaa55) { - PCI_DPRINTF("Bad ROM magic %04x\n", rom_magic); - return; - } - pcir_offset = pci_get_word(ptr + 0x18); - if (pcir_offset + 8 >= size || memcmp(ptr + pcir_offset, "PCIR", 4)) { - PCI_DPRINTF("Bad PCIR offset 0x%x or signature\n", pcir_offset); - return; - } - - vendor_id = pci_get_word(pdev->config + PCI_VENDOR_ID); - device_id = pci_get_word(pdev->config + PCI_DEVICE_ID); - rom_vendor_id = pci_get_word(ptr + pcir_offset + 4); - rom_device_id = pci_get_word(ptr + pcir_offset + 6); - - PCI_DPRINTF("%s: ROM id %04x%04x / PCI id %04x%04x\n", pdev->romfile, - vendor_id, device_id, rom_vendor_id, rom_device_id); - - checksum = ptr[6]; - - if (vendor_id != rom_vendor_id) { - /* Patch vendor id and checksum (at offset 6 for etherboot roms). */ - checksum += (uint8_t)rom_vendor_id + (uint8_t)(rom_vendor_id >> 8); - checksum -= (uint8_t)vendor_id + (uint8_t)(vendor_id >> 8); - PCI_DPRINTF("ROM checksum %02x / %02x\n", ptr[6], checksum); - ptr[6] = checksum; - pci_set_word(ptr + pcir_offset + 4, vendor_id); - } - - if (device_id != rom_device_id) { - /* Patch device id and checksum (at offset 6 for etherboot roms). */ - checksum += (uint8_t)rom_device_id + (uint8_t)(rom_device_id >> 8); - checksum -= (uint8_t)device_id + (uint8_t)(device_id >> 8); - PCI_DPRINTF("ROM checksum %02x / %02x\n", ptr[6], checksum); - ptr[6] = checksum; - pci_set_word(ptr + pcir_offset + 6, device_id); - } -} - -/* Add an option rom for the device */ -int pci_add_option_rom(PCIDevice *pdev, bool is_default_rom) -{ - int size; - char *path; - void *ptr; - char name[32]; - const VMStateDescription *vmsd; - - if (!pdev->romfile) - return 0; - if (strlen(pdev->romfile) == 0) - return 0; - - if (!pdev->rom_bar) { - /* - * Load rom via fw_cfg instead of creating a rom bar, - * for 0.11 compatibility. - */ - int class = pci_get_word(pdev->config + PCI_CLASS_DEVICE); - if (class == 0x0300) { - rom_add_vga(pdev->romfile); - } else { - rom_add_option(pdev->romfile, -1); - } - return 0; - } - - path = qemu_find_file(QEMU_FILE_TYPE_BIOS, pdev->romfile); - if (path == NULL) { - path = g_strdup(pdev->romfile); - } - - size = get_image_size(path); - if (size < 0) { - error_report("%s: failed to find romfile \"%s\"", - __FUNCTION__, pdev->romfile); - g_free(path); - return -1; - } - if (size & (size - 1)) { - size = 1 << qemu_fls(size); - } - - vmsd = qdev_get_vmsd(DEVICE(pdev)); - - if (vmsd) { - snprintf(name, sizeof(name), "%s.rom", vmsd->name); - } else { - snprintf(name, sizeof(name), "%s.rom", object_get_typename(OBJECT(pdev))); - } - pdev->has_rom = true; - memory_region_init_ram(&pdev->rom, name, size); - vmstate_register_ram(&pdev->rom, &pdev->qdev); - ptr = memory_region_get_ram_ptr(&pdev->rom); - load_image(path, ptr); - g_free(path); - - if (is_default_rom) { - /* Only the default rom images will be patched (if needed). */ - pci_patch_ids(pdev, ptr, size); - } - - qemu_put_ram_ptr(ptr); - - pci_register_bar(pdev, PCI_ROM_SLOT, 0, &pdev->rom); - - return 0; -} - -static void pci_del_option_rom(PCIDevice *pdev) -{ - if (!pdev->has_rom) - return; - - vmstate_unregister_ram(&pdev->rom, &pdev->qdev); - memory_region_destroy(&pdev->rom); - pdev->has_rom = false; -} - -/* - * if !offset - * Reserve space and add capability to the linked list in pci config space - * - * if offset = 0, - * Find and reserve space and add capability to the linked list - * in pci config space */ -int pci_add_capability(PCIDevice *pdev, uint8_t cap_id, - uint8_t offset, uint8_t size) -{ - uint8_t *config; - int i, overlapping_cap; - - if (!offset) { - offset = pci_find_space(pdev, size); - if (!offset) { - return -ENOSPC; - } - } else { - /* Verify that capabilities don't overlap. Note: device assignment - * depends on this check to verify that the device is not broken. - * Should never trigger for emulated devices, but it's helpful - * for debugging these. */ - for (i = offset; i < offset + size; i++) { - overlapping_cap = pci_find_capability_at_offset(pdev, i); - if (overlapping_cap) { - fprintf(stderr, "ERROR: %04x:%02x:%02x.%x " - "Attempt to add PCI capability %x at offset " - "%x overlaps existing capability %x at offset %x\n", - pci_find_domain(pdev->bus), pci_bus_num(pdev->bus), - PCI_SLOT(pdev->devfn), PCI_FUNC(pdev->devfn), - cap_id, offset, overlapping_cap, i); - return -EINVAL; - } - } - } - - config = pdev->config + offset; - config[PCI_CAP_LIST_ID] = cap_id; - config[PCI_CAP_LIST_NEXT] = pdev->config[PCI_CAPABILITY_LIST]; - pdev->config[PCI_CAPABILITY_LIST] = offset; - pdev->config[PCI_STATUS] |= PCI_STATUS_CAP_LIST; - memset(pdev->used + offset, 0xFF, size); - /* Make capability read-only by default */ - memset(pdev->wmask + offset, 0, size); - /* Check capability by default */ - memset(pdev->cmask + offset, 0xFF, size); - return offset; -} - -/* Unlink capability from the pci config space. */ -void pci_del_capability(PCIDevice *pdev, uint8_t cap_id, uint8_t size) -{ - uint8_t prev, offset = pci_find_capability_list(pdev, cap_id, &prev); - if (!offset) - return; - pdev->config[prev] = pdev->config[offset + PCI_CAP_LIST_NEXT]; - /* Make capability writable again */ - memset(pdev->wmask + offset, 0xff, size); - memset(pdev->w1cmask + offset, 0, size); - /* Clear cmask as device-specific registers can't be checked */ - memset(pdev->cmask + offset, 0, size); - memset(pdev->used + offset, 0, size); - - if (!pdev->config[PCI_CAPABILITY_LIST]) - pdev->config[PCI_STATUS] &= ~PCI_STATUS_CAP_LIST; -} - -uint8_t pci_find_capability(PCIDevice *pdev, uint8_t cap_id) -{ - return pci_find_capability_list(pdev, cap_id, NULL); -} - -static void pcibus_dev_print(Monitor *mon, DeviceState *dev, int indent) -{ - PCIDevice *d = (PCIDevice *)dev; - const pci_class_desc *desc; - char ctxt[64]; - PCIIORegion *r; - int i, class; - - class = pci_get_word(d->config + PCI_CLASS_DEVICE); - desc = pci_class_descriptions; - while (desc->desc && class != desc->class) - desc++; - if (desc->desc) { - snprintf(ctxt, sizeof(ctxt), "%s", desc->desc); - } else { - snprintf(ctxt, sizeof(ctxt), "Class %04x", class); - } - - monitor_printf(mon, "%*sclass %s, addr %02x:%02x.%x, " - "pci id %04x:%04x (sub %04x:%04x)\n", - indent, "", ctxt, pci_bus_num(d->bus), - PCI_SLOT(d->devfn), PCI_FUNC(d->devfn), - pci_get_word(d->config + PCI_VENDOR_ID), - pci_get_word(d->config + PCI_DEVICE_ID), - pci_get_word(d->config + PCI_SUBSYSTEM_VENDOR_ID), - pci_get_word(d->config + PCI_SUBSYSTEM_ID)); - for (i = 0; i < PCI_NUM_REGIONS; i++) { - r = &d->io_regions[i]; - if (!r->size) - continue; - monitor_printf(mon, "%*sbar %d: %s at 0x%"FMT_PCIBUS - " [0x%"FMT_PCIBUS"]\n", - indent, "", - i, r->type & PCI_BASE_ADDRESS_SPACE_IO ? "i/o" : "mem", - r->addr, r->addr + r->size - 1); - } -} - -static char *pci_dev_fw_name(DeviceState *dev, char *buf, int len) -{ - PCIDevice *d = (PCIDevice *)dev; - const char *name = NULL; - const pci_class_desc *desc = pci_class_descriptions; - int class = pci_get_word(d->config + PCI_CLASS_DEVICE); - - while (desc->desc && - (class & ~desc->fw_ign_bits) != - (desc->class & ~desc->fw_ign_bits)) { - desc++; - } - - if (desc->desc) { - name = desc->fw_name; - } - - if (name) { - pstrcpy(buf, len, name); - } else { - snprintf(buf, len, "pci%04x,%04x", - pci_get_word(d->config + PCI_VENDOR_ID), - pci_get_word(d->config + PCI_DEVICE_ID)); - } - - return buf; -} - -static char *pcibus_get_fw_dev_path(DeviceState *dev) -{ - PCIDevice *d = (PCIDevice *)dev; - char path[50], name[33]; - int off; - - off = snprintf(path, sizeof(path), "%s@%x", - pci_dev_fw_name(dev, name, sizeof name), - PCI_SLOT(d->devfn)); - if (PCI_FUNC(d->devfn)) - snprintf(path + off, sizeof(path) + off, ",%x", PCI_FUNC(d->devfn)); - return strdup(path); -} - -static char *pcibus_get_dev_path(DeviceState *dev) -{ - PCIDevice *d = container_of(dev, PCIDevice, qdev); - PCIDevice *t; - int slot_depth; - /* Path format: Domain:00:Slot.Function:Slot.Function....:Slot.Function. - * 00 is added here to make this format compatible with - * domain:Bus:Slot.Func for systems without nested PCI bridges. - * Slot.Function list specifies the slot and function numbers for all - * devices on the path from root to the specific device. */ - char domain[] = "DDDD:00"; - char slot[] = ":SS.F"; - int domain_len = sizeof domain - 1 /* For '\0' */; - int slot_len = sizeof slot - 1 /* For '\0' */; - int path_len; - char *path, *p; - int s; - - /* Calculate # of slots on path between device and root. */; - slot_depth = 0; - for (t = d; t; t = t->bus->parent_dev) { - ++slot_depth; - } - - path_len = domain_len + slot_len * slot_depth; - - /* Allocate memory, fill in the terminating null byte. */ - path = g_malloc(path_len + 1 /* For '\0' */); - path[path_len] = '\0'; - - /* First field is the domain. */ - s = snprintf(domain, sizeof domain, "%04x:00", pci_find_domain(d->bus)); - assert(s == domain_len); - memcpy(path, domain, domain_len); - - /* Fill in slot numbers. We walk up from device to root, so need to print - * them in the reverse order, last to first. */ - p = path + path_len; - for (t = d; t; t = t->bus->parent_dev) { - p -= slot_len; - s = snprintf(slot, sizeof slot, ":%02x.%x", - PCI_SLOT(t->devfn), PCI_FUNC(t->devfn)); - assert(s == slot_len); - memcpy(p, slot, slot_len); - } - - return path; -} - -static int pci_qdev_find_recursive(PCIBus *bus, - const char *id, PCIDevice **pdev) -{ - DeviceState *qdev = qdev_find_recursive(&bus->qbus, id); - if (!qdev) { - return -ENODEV; - } - - /* roughly check if given qdev is pci device */ - if (object_dynamic_cast(OBJECT(qdev), TYPE_PCI_DEVICE)) { - *pdev = PCI_DEVICE(qdev); - return 0; - } - return -EINVAL; -} - -int pci_qdev_find_device(const char *id, PCIDevice **pdev) -{ - struct PCIHostBus *host; - int rc = -ENODEV; - - QLIST_FOREACH(host, &host_buses, next) { - int tmp = pci_qdev_find_recursive(host->bus, id, pdev); - if (!tmp) { - rc = 0; - break; - } - if (tmp != -ENODEV) { - rc = tmp; - } - } - - return rc; -} - -MemoryRegion *pci_address_space(PCIDevice *dev) -{ - return dev->bus->address_space_mem; -} - -MemoryRegion *pci_address_space_io(PCIDevice *dev) -{ - return dev->bus->address_space_io; -} - -static void pci_device_class_init(ObjectClass *klass, void *data) -{ - DeviceClass *k = DEVICE_CLASS(klass); - k->init = pci_qdev_init; - k->unplug = pci_unplug_device; - k->exit = pci_unregister_device; - k->bus_type = TYPE_PCI_BUS; - k->props = pci_props; -} - -void pci_setup_iommu(PCIBus *bus, PCIDMAContextFunc fn, void *opaque) -{ - bus->dma_context_fn = fn; - bus->dma_context_opaque = opaque; -} - -static TypeInfo pci_device_type_info = { - .name = TYPE_PCI_DEVICE, - .parent = TYPE_DEVICE, - .instance_size = sizeof(PCIDevice), - .abstract = true, - .class_size = sizeof(PCIDeviceClass), - .class_init = pci_device_class_init, -}; - -static void pci_register_types(void) -{ - type_register_static(&pci_bus_info); - type_register_static(&pci_device_type_info); -} - -type_init(pci_register_types) diff --git a/hw/pci.h b/hw/pci.h deleted file mode 100644 index 5071d3a..0000000 --- a/hw/pci.h +++ /dev/null @@ -1,679 +0,0 @@ -#ifndef QEMU_PCI_H -#define QEMU_PCI_H - -#include "qemu-common.h" - -#include "qdev.h" -#include "memory.h" -#include "dma.h" - -/* PCI includes legacy ISA access. */ -#include "isa.h" - -#include "pcie.h" - -/* PCI bus */ - -#define PCI_DEVFN(slot, func) ((((slot) & 0x1f) << 3) | ((func) & 0x07)) -#define PCI_SLOT(devfn) (((devfn) >> 3) & 0x1f) -#define PCI_FUNC(devfn) ((devfn) & 0x07) -#define PCI_SLOT_MAX 32 -#define PCI_FUNC_MAX 8 - -/* Class, Vendor and Device IDs from Linux's pci_ids.h */ -#include "pci_ids.h" - -/* QEMU-specific Vendor and Device ID definitions */ - -/* IBM (0x1014) */ -#define PCI_DEVICE_ID_IBM_440GX 0x027f -#define PCI_DEVICE_ID_IBM_OPENPIC2 0xffff - -/* Hitachi (0x1054) */ -#define PCI_VENDOR_ID_HITACHI 0x1054 -#define PCI_DEVICE_ID_HITACHI_SH7751R 0x350e - -/* Apple (0x106b) */ -#define PCI_DEVICE_ID_APPLE_343S1201 0x0010 -#define PCI_DEVICE_ID_APPLE_UNI_N_I_PCI 0x001e -#define PCI_DEVICE_ID_APPLE_UNI_N_PCI 0x001f -#define PCI_DEVICE_ID_APPLE_UNI_N_KEYL 0x0022 -#define PCI_DEVICE_ID_APPLE_IPID_USB 0x003f - -/* Realtek (0x10ec) */ -#define PCI_DEVICE_ID_REALTEK_8029 0x8029 - -/* Xilinx (0x10ee) */ -#define PCI_DEVICE_ID_XILINX_XC2VP30 0x0300 - -/* Marvell (0x11ab) */ -#define PCI_DEVICE_ID_MARVELL_GT6412X 0x4620 - -/* QEMU/Bochs VGA (0x1234) */ -#define PCI_VENDOR_ID_QEMU 0x1234 -#define PCI_DEVICE_ID_QEMU_VGA 0x1111 - -/* VMWare (0x15ad) */ -#define PCI_VENDOR_ID_VMWARE 0x15ad -#define PCI_DEVICE_ID_VMWARE_SVGA2 0x0405 -#define PCI_DEVICE_ID_VMWARE_SVGA 0x0710 -#define PCI_DEVICE_ID_VMWARE_NET 0x0720 -#define PCI_DEVICE_ID_VMWARE_SCSI 0x0730 -#define PCI_DEVICE_ID_VMWARE_IDE 0x1729 - -/* Intel (0x8086) */ -#define PCI_DEVICE_ID_INTEL_82551IT 0x1209 -#define PCI_DEVICE_ID_INTEL_82557 0x1229 -#define PCI_DEVICE_ID_INTEL_82801IR 0x2922 - -/* Red Hat / Qumranet (for QEMU) -- see pci-ids.txt */ -#define PCI_VENDOR_ID_REDHAT_QUMRANET 0x1af4 -#define PCI_SUBVENDOR_ID_REDHAT_QUMRANET 0x1af4 -#define PCI_SUBDEVICE_ID_QEMU 0x1100 - -#define PCI_DEVICE_ID_VIRTIO_NET 0x1000 -#define PCI_DEVICE_ID_VIRTIO_BLOCK 0x1001 -#define PCI_DEVICE_ID_VIRTIO_BALLOON 0x1002 -#define PCI_DEVICE_ID_VIRTIO_CONSOLE 0x1003 -#define PCI_DEVICE_ID_VIRTIO_SCSI 0x1004 - -#define PCI_DEVICE_ID_VIRTIO_GL 0x1006 - -#define FMT_PCIBUS PRIx64 - -typedef void PCIConfigWriteFunc(PCIDevice *pci_dev, - uint32_t address, uint32_t data, int len); -typedef uint32_t PCIConfigReadFunc(PCIDevice *pci_dev, - uint32_t address, int len); -typedef void PCIMapIORegionFunc(PCIDevice *pci_dev, int region_num, - pcibus_t addr, pcibus_t size, int type); -typedef void PCIUnregisterFunc(PCIDevice *pci_dev); - -typedef struct PCIIORegion { - pcibus_t addr; /* current PCI mapping address. -1 means not mapped */ -#define PCI_BAR_UNMAPPED (~(pcibus_t)0) - pcibus_t size; - uint8_t type; - MemoryRegion *memory; - MemoryRegion *address_space; -} PCIIORegion; - -#define PCI_ROM_SLOT 6 -#define PCI_NUM_REGIONS 7 - -#include "pci_regs.h" - -/* PCI HEADER_TYPE */ -#define PCI_HEADER_TYPE_MULTI_FUNCTION 0x80 - -/* Size of the standard PCI config header */ -#define PCI_CONFIG_HEADER_SIZE 0x40 -/* Size of the standard PCI config space */ -#define PCI_CONFIG_SPACE_SIZE 0x100 -/* Size of the standart PCIe config space: 4KB */ -#define PCIE_CONFIG_SPACE_SIZE 0x1000 - -#define PCI_NUM_PINS 4 /* A-D */ - -/* Bits in cap_present field. */ -enum { - QEMU_PCI_CAP_MSI = 0x1, - QEMU_PCI_CAP_MSIX = 0x2, - QEMU_PCI_CAP_EXPRESS = 0x4, - - /* multifunction capable device */ -#define QEMU_PCI_CAP_MULTIFUNCTION_BITNR 3 - QEMU_PCI_CAP_MULTIFUNCTION = (1 << QEMU_PCI_CAP_MULTIFUNCTION_BITNR), - - /* command register SERR bit enabled */ -#define QEMU_PCI_CAP_SERR_BITNR 4 - QEMU_PCI_CAP_SERR = (1 << QEMU_PCI_CAP_SERR_BITNR), - /* Standard hot plug controller. */ -#define QEMU_PCI_SHPC_BITNR 5 - QEMU_PCI_CAP_SHPC = (1 << QEMU_PCI_SHPC_BITNR), -#define QEMU_PCI_SLOTID_BITNR 6 - QEMU_PCI_CAP_SLOTID = (1 << QEMU_PCI_SLOTID_BITNR), -}; - -#define TYPE_PCI_DEVICE "pci-device" -#define PCI_DEVICE(obj) \ - OBJECT_CHECK(PCIDevice, (obj), TYPE_PCI_DEVICE) -#define PCI_DEVICE_CLASS(klass) \ - OBJECT_CLASS_CHECK(PCIDeviceClass, (klass), TYPE_PCI_DEVICE) -#define PCI_DEVICE_GET_CLASS(obj) \ - OBJECT_GET_CLASS(PCIDeviceClass, (obj), TYPE_PCI_DEVICE) - -typedef struct PCIINTxRoute { - enum { - PCI_INTX_ENABLED, - PCI_INTX_INVERTED, - PCI_INTX_DISABLED, - } mode; - int irq; -} PCIINTxRoute; - -typedef struct PCIDeviceClass { - DeviceClass parent_class; - - int (*init)(PCIDevice *dev); - PCIUnregisterFunc *exit; - PCIConfigReadFunc *config_read; - PCIConfigWriteFunc *config_write; - - uint16_t vendor_id; - uint16_t device_id; - uint8_t revision; - uint16_t class_id; - uint16_t subsystem_vendor_id; /* only for header type = 0 */ - uint16_t subsystem_id; /* only for header type = 0 */ - - /* - * pci-to-pci bridge or normal device. - * This doesn't mean pci host switch. - * When card bus bridge is supported, this would be enhanced. - */ - int is_bridge; - - /* pcie stuff */ - int is_express; /* is this device pci express? */ - - /* device isn't hot-pluggable */ - int no_hotplug; - - /* rom bar */ - const char *romfile; -} PCIDeviceClass; - -typedef void (*PCIINTxRoutingNotifier)(PCIDevice *dev); -typedef int (*MSIVectorUseNotifier)(PCIDevice *dev, unsigned int vector, - MSIMessage msg); -typedef void (*MSIVectorReleaseNotifier)(PCIDevice *dev, unsigned int vector); - -struct PCIDevice { - DeviceState qdev; - - /* PCI config space */ - uint8_t *config; - - /* Used to enable config checks on load. Note that writable bits are - * never checked even if set in cmask. */ - uint8_t *cmask; - - /* Used to implement R/W bytes */ - uint8_t *wmask; - - /* Used to implement RW1C(Write 1 to Clear) bytes */ - uint8_t *w1cmask; - - /* Used to allocate config space for capabilities. */ - uint8_t *used; - - /* the following fields are read only */ - PCIBus *bus; - int32_t devfn; - char name[64]; - PCIIORegion io_regions[PCI_NUM_REGIONS]; - DMAContext *dma; - - /* do not access the following fields */ - PCIConfigReadFunc *config_read; - PCIConfigWriteFunc *config_write; - - /* IRQ objects for the INTA-INTD pins. */ - qemu_irq *irq; - - /* Current IRQ levels. Used internally by the generic PCI code. */ - uint8_t irq_state; - - /* Capability bits */ - uint32_t cap_present; - - /* Offset of MSI-X capability in config space */ - uint8_t msix_cap; - - /* MSI-X entries */ - int msix_entries_nr; - - /* Space to store MSIX table & pending bit array */ - uint8_t *msix_table; - uint8_t *msix_pba; - /* MemoryRegion container for msix exclusive BAR setup */ - MemoryRegion msix_exclusive_bar; - /* Memory Regions for MSIX table and pending bit entries. */ - MemoryRegion msix_table_mmio; - MemoryRegion msix_pba_mmio; - /* Reference-count for entries actually in use by driver. */ - unsigned *msix_entry_used; - /* MSIX function mask set or MSIX disabled */ - bool msix_function_masked; - /* Version id needed for VMState */ - int32_t version_id; - - /* Offset of MSI capability in config space */ - uint8_t msi_cap; - - /* PCI Express */ - PCIExpressDevice exp; - - /* SHPC */ - SHPCDevice *shpc; - - /* Location of option rom */ - char *romfile; - bool has_rom; - MemoryRegion rom; - uint32_t rom_bar; - - /* INTx routing notifier */ - PCIINTxRoutingNotifier intx_routing_notifier; - - /* MSI-X notifiers */ - MSIVectorUseNotifier msix_vector_use_notifier; - MSIVectorReleaseNotifier msix_vector_release_notifier; -}; - -void pci_register_bar(PCIDevice *pci_dev, int region_num, - uint8_t attr, MemoryRegion *memory); -pcibus_t pci_get_bar_addr(PCIDevice *pci_dev, int region_num); - -int pci_add_option_rom(PCIDevice *pdev, bool is_default_rom); - -int pci_add_capability(PCIDevice *pdev, uint8_t cap_id, - uint8_t offset, uint8_t size); - -void pci_del_capability(PCIDevice *pci_dev, uint8_t cap_id, uint8_t cap_size); - -uint8_t pci_find_capability(PCIDevice *pci_dev, uint8_t cap_id); - - -uint32_t pci_default_read_config(PCIDevice *d, - uint32_t address, int len); -void pci_default_write_config(PCIDevice *d, - uint32_t address, uint32_t val, int len); -void pci_device_save(PCIDevice *s, QEMUFile *f); -int pci_device_load(PCIDevice *s, QEMUFile *f); -MemoryRegion *pci_address_space(PCIDevice *dev); -MemoryRegion *pci_address_space_io(PCIDevice *dev); - -typedef void (*pci_set_irq_fn)(void *opaque, int irq_num, int level); -typedef int (*pci_map_irq_fn)(PCIDevice *pci_dev, int irq_num); -typedef PCIINTxRoute (*pci_route_irq_fn)(void *opaque, int pin); - -typedef enum { - PCI_HOTPLUG_DISABLED, - PCI_HOTPLUG_ENABLED, - PCI_COLDPLUG_ENABLED, -} PCIHotplugState; - -typedef int (*pci_hotplug_fn)(DeviceState *qdev, PCIDevice *pci_dev, - PCIHotplugState state); -void pci_bus_new_inplace(PCIBus *bus, DeviceState *parent, - const char *name, - MemoryRegion *address_space_mem, - MemoryRegion *address_space_io, - uint8_t devfn_min); -PCIBus *pci_bus_new(DeviceState *parent, const char *name, - MemoryRegion *address_space_mem, - MemoryRegion *address_space_io, - uint8_t devfn_min); -void pci_bus_irqs(PCIBus *bus, pci_set_irq_fn set_irq, pci_map_irq_fn map_irq, - void *irq_opaque, int nirq); -int pci_bus_get_irq_level(PCIBus *bus, int irq_num); -void pci_bus_hotplug(PCIBus *bus, pci_hotplug_fn hotplug, DeviceState *dev); -PCIBus *pci_register_bus(DeviceState *parent, const char *name, - pci_set_irq_fn set_irq, pci_map_irq_fn map_irq, - void *irq_opaque, - MemoryRegion *address_space_mem, - MemoryRegion *address_space_io, - uint8_t devfn_min, int nirq); -void pci_bus_set_route_irq_fn(PCIBus *, pci_route_irq_fn); -PCIINTxRoute pci_device_route_intx_to_irq(PCIDevice *dev, int pin); -void pci_bus_fire_intx_routing_notifier(PCIBus *bus); -void pci_device_set_intx_routing_notifier(PCIDevice *dev, - PCIINTxRoutingNotifier notifier); -void pci_device_reset(PCIDevice *dev); -void pci_bus_reset(PCIBus *bus); - -PCIDevice *pci_nic_init(NICInfo *nd, const char *default_model, - const char *default_devaddr); -PCIDevice *pci_nic_init_nofail(NICInfo *nd, const char *default_model, - const char *default_devaddr); -int pci_bus_num(PCIBus *s); -void pci_for_each_device(PCIBus *bus, int bus_num, - void (*fn)(PCIBus *bus, PCIDevice *d, void *opaque), - void *opaque); -PCIBus *pci_find_root_bus(int domain); -int pci_find_domain(const PCIBus *bus); -PCIDevice *pci_find_device(PCIBus *bus, int bus_num, uint8_t devfn); -int pci_qdev_find_device(const char *id, PCIDevice **pdev); -PCIBus *pci_get_bus_devfn(int *devfnp, const char *devaddr); - -int pci_read_devaddr(Monitor *mon, const char *addr, int *domp, int *busp, - unsigned *slotp); - -void pci_device_deassert_intx(PCIDevice *dev); - -typedef DMAContext *(*PCIDMAContextFunc)(PCIBus *, void *, int); - -void pci_setup_iommu(PCIBus *bus, PCIDMAContextFunc fn, void *opaque); - -static inline void -pci_set_byte(uint8_t *config, uint8_t val) -{ - *config = val; -} - -static inline uint8_t -pci_get_byte(const uint8_t *config) -{ - return *config; -} - -static inline void -pci_set_word(uint8_t *config, uint16_t val) -{ - cpu_to_le16wu((uint16_t *)config, val); -} - -static inline uint16_t -pci_get_word(const uint8_t *config) -{ - return le16_to_cpupu((const uint16_t *)config); -} - -static inline void -pci_set_long(uint8_t *config, uint32_t val) -{ - cpu_to_le32wu((uint32_t *)config, val); -} - -static inline uint32_t -pci_get_long(const uint8_t *config) -{ - return le32_to_cpupu((const uint32_t *)config); -} - -static inline void -pci_set_quad(uint8_t *config, uint64_t val) -{ - cpu_to_le64w((uint64_t *)config, val); -} - -static inline uint64_t -pci_get_quad(const uint8_t *config) -{ - return le64_to_cpup((const uint64_t *)config); -} - -static inline void -pci_config_set_vendor_id(uint8_t *pci_config, uint16_t val) -{ - pci_set_word(&pci_config[PCI_VENDOR_ID], val); -} - -static inline void -pci_config_set_device_id(uint8_t *pci_config, uint16_t val) -{ - pci_set_word(&pci_config[PCI_DEVICE_ID], val); -} - -static inline void -pci_config_set_revision(uint8_t *pci_config, uint8_t val) -{ - pci_set_byte(&pci_config[PCI_REVISION_ID], val); -} - -static inline void -pci_config_set_class(uint8_t *pci_config, uint16_t val) -{ - pci_set_word(&pci_config[PCI_CLASS_DEVICE], val); -} - -static inline void -pci_config_set_prog_interface(uint8_t *pci_config, uint8_t val) -{ - pci_set_byte(&pci_config[PCI_CLASS_PROG], val); -} - -static inline void -pci_config_set_interrupt_pin(uint8_t *pci_config, uint8_t val) -{ - pci_set_byte(&pci_config[PCI_INTERRUPT_PIN], val); -} - -/* - * helper functions to do bit mask operation on configuration space. - * Just to set bit, use test-and-set and discard returned value. - * Just to clear bit, use test-and-clear and discard returned value. - * NOTE: They aren't atomic. - */ -static inline uint8_t -pci_byte_test_and_clear_mask(uint8_t *config, uint8_t mask) -{ - uint8_t val = pci_get_byte(config); - pci_set_byte(config, val & ~mask); - return val & mask; -} - -static inline uint8_t -pci_byte_test_and_set_mask(uint8_t *config, uint8_t mask) -{ - uint8_t val = pci_get_byte(config); - pci_set_byte(config, val | mask); - return val & mask; -} - -static inline uint16_t -pci_word_test_and_clear_mask(uint8_t *config, uint16_t mask) -{ - uint16_t val = pci_get_word(config); - pci_set_word(config, val & ~mask); - return val & mask; -} - -static inline uint16_t -pci_word_test_and_set_mask(uint8_t *config, uint16_t mask) -{ - uint16_t val = pci_get_word(config); - pci_set_word(config, val | mask); - return val & mask; -} - -static inline uint32_t -pci_long_test_and_clear_mask(uint8_t *config, uint32_t mask) -{ - uint32_t val = pci_get_long(config); - pci_set_long(config, val & ~mask); - return val & mask; -} - -static inline uint32_t -pci_long_test_and_set_mask(uint8_t *config, uint32_t mask) -{ - uint32_t val = pci_get_long(config); - pci_set_long(config, val | mask); - return val & mask; -} - -static inline uint64_t -pci_quad_test_and_clear_mask(uint8_t *config, uint64_t mask) -{ - uint64_t val = pci_get_quad(config); - pci_set_quad(config, val & ~mask); - return val & mask; -} - -static inline uint64_t -pci_quad_test_and_set_mask(uint8_t *config, uint64_t mask) -{ - uint64_t val = pci_get_quad(config); - pci_set_quad(config, val | mask); - return val & mask; -} - -/* Access a register specified by a mask */ -static inline void -pci_set_byte_by_mask(uint8_t *config, uint8_t mask, uint8_t reg) -{ - uint8_t val = pci_get_byte(config); - uint8_t rval = reg << (ffs(mask) - 1); - pci_set_byte(config, (~mask & val) | (mask & rval)); -} - -static inline uint8_t -pci_get_byte_by_mask(uint8_t *config, uint8_t mask) -{ - uint8_t val = pci_get_byte(config); - return (val & mask) >> (ffs(mask) - 1); -} - -static inline void -pci_set_word_by_mask(uint8_t *config, uint16_t mask, uint16_t reg) -{ - uint16_t val = pci_get_word(config); - uint16_t rval = reg << (ffs(mask) - 1); - pci_set_word(config, (~mask & val) | (mask & rval)); -} - -static inline uint16_t -pci_get_word_by_mask(uint8_t *config, uint16_t mask) -{ - uint16_t val = pci_get_word(config); - return (val & mask) >> (ffs(mask) - 1); -} - -static inline void -pci_set_long_by_mask(uint8_t *config, uint32_t mask, uint32_t reg) -{ - uint32_t val = pci_get_long(config); - uint32_t rval = reg << (ffs(mask) - 1); - pci_set_long(config, (~mask & val) | (mask & rval)); -} - -static inline uint32_t -pci_get_long_by_mask(uint8_t *config, uint32_t mask) -{ - uint32_t val = pci_get_long(config); - return (val & mask) >> (ffs(mask) - 1); -} - -static inline void -pci_set_quad_by_mask(uint8_t *config, uint64_t mask, uint64_t reg) -{ - uint64_t val = pci_get_quad(config); - uint64_t rval = reg << (ffs(mask) - 1); - pci_set_quad(config, (~mask & val) | (mask & rval)); -} - -static inline uint64_t -pci_get_quad_by_mask(uint8_t *config, uint64_t mask) -{ - uint64_t val = pci_get_quad(config); - return (val & mask) >> (ffs(mask) - 1); -} - -PCIDevice *pci_create_multifunction(PCIBus *bus, int devfn, bool multifunction, - const char *name); -PCIDevice *pci_create_simple_multifunction(PCIBus *bus, int devfn, - bool multifunction, - const char *name); -PCIDevice *pci_create(PCIBus *bus, int devfn, const char *name); -PCIDevice *pci_create_simple(PCIBus *bus, int devfn, const char *name); - -static inline int pci_is_express(const PCIDevice *d) -{ - return d->cap_present & QEMU_PCI_CAP_EXPRESS; -} - -static inline uint32_t pci_config_size(const PCIDevice *d) -{ - return pci_is_express(d) ? PCIE_CONFIG_SPACE_SIZE : PCI_CONFIG_SPACE_SIZE; -} - -/* DMA access functions */ -static inline DMAContext *pci_dma_context(PCIDevice *dev) -{ - return dev->dma; -} - -static inline int pci_dma_rw(PCIDevice *dev, dma_addr_t addr, - void *buf, dma_addr_t len, DMADirection dir) -{ - dma_memory_rw(pci_dma_context(dev), addr, buf, len, dir); - return 0; -} - -static inline int pci_dma_read(PCIDevice *dev, dma_addr_t addr, - void *buf, dma_addr_t len) -{ - return pci_dma_rw(dev, addr, buf, len, DMA_DIRECTION_TO_DEVICE); -} - -static inline int pci_dma_write(PCIDevice *dev, dma_addr_t addr, - const void *buf, dma_addr_t len) -{ - return pci_dma_rw(dev, addr, (void *) buf, len, DMA_DIRECTION_FROM_DEVICE); -} - -#define PCI_DMA_DEFINE_LDST(_l, _s, _bits) \ - static inline uint##_bits##_t ld##_l##_pci_dma(PCIDevice *dev, \ - dma_addr_t addr) \ - { \ - return ld##_l##_dma(pci_dma_context(dev), addr); \ - } \ - static inline void st##_s##_pci_dma(PCIDevice *dev, \ - dma_addr_t addr, uint##_bits##_t val) \ - { \ - st##_s##_dma(pci_dma_context(dev), addr, val); \ - } - -PCI_DMA_DEFINE_LDST(ub, b, 8); -PCI_DMA_DEFINE_LDST(uw_le, w_le, 16) -PCI_DMA_DEFINE_LDST(l_le, l_le, 32); -PCI_DMA_DEFINE_LDST(q_le, q_le, 64); -PCI_DMA_DEFINE_LDST(uw_be, w_be, 16) -PCI_DMA_DEFINE_LDST(l_be, l_be, 32); -PCI_DMA_DEFINE_LDST(q_be, q_be, 64); - -#undef PCI_DMA_DEFINE_LDST - -static inline void *pci_dma_map(PCIDevice *dev, dma_addr_t addr, - dma_addr_t *plen, DMADirection dir) -{ - void *buf; - - buf = dma_memory_map(pci_dma_context(dev), addr, plen, dir); - return buf; -} - -static inline void pci_dma_unmap(PCIDevice *dev, void *buffer, dma_addr_t len, - DMADirection dir, dma_addr_t access_len) -{ - dma_memory_unmap(pci_dma_context(dev), buffer, len, dir, access_len); -} - -static inline void pci_dma_sglist_init(QEMUSGList *qsg, PCIDevice *dev, - int alloc_hint) -{ - qemu_sglist_init(qsg, alloc_hint, pci_dma_context(dev)); -} - -extern const VMStateDescription vmstate_pci_device; - -#define VMSTATE_PCI_DEVICE(_field, _state) { \ - .name = (stringify(_field)), \ - .size = sizeof(PCIDevice), \ - .vmsd = &vmstate_pci_device, \ - .flags = VMS_STRUCT, \ - .offset = vmstate_offset_value(_state, _field, PCIDevice), \ -} - -#define VMSTATE_PCI_DEVICE_POINTER(_field, _state) { \ - .name = (stringify(_field)), \ - .size = sizeof(PCIDevice), \ - .vmsd = &vmstate_pci_device, \ - .flags = VMS_STRUCT|VMS_POINTER, \ - .offset = vmstate_offset_pointer(_state, _field, PCIDevice), \ -} - -#endif diff --git a/hw/pci/pci-hotplug.c b/hw/pci/pci-hotplug.c index 12287d1..b53bee4 100644 --- a/hw/pci/pci-hotplug.c +++ b/hw/pci/pci-hotplug.c @@ -222,7 +222,40 @@ static PCIDevice *qemu_pci_hot_add_storage(Monitor *mon, return dev; } +#ifdef CONFIG_MARU +static PCIDevice *qemu_pci_hot_add_keyboard(Monitor *mon, + const char *devaddr, + const char *opts) +{ + PCIDevice *dev; + PCIBus *bus; + int devfn; + + bus = pci_get_bus_devfn(&devfn, devaddr); + if (!bus) { + monitor_printf(mon, "Invalid PCI device address %s\n", devaddr); + return NULL; + } + + if (!((BusState*)bus)->allow_hotplug) { + monitor_printf(mon, "PCI bus doesn't support hotplug\n"); + return NULL; + } + + dev = pci_create(bus, devfn, "virtio-keyboard-pci"); + if (qdev_init(&dev->qdev) < 0) { + dev = NULL; + } + + return dev; +} +#endif /* CONFIG_MARU */ + +#ifdef CONFIG_MARU +PCIDevice *pci_device_hot_add(Monitor *mon, const QDict *qdict) +#else void pci_device_hot_add(Monitor *mon, const QDict *qdict) +#endif { PCIDevice *dev = NULL; const char *pci_addr = qdict_get_str(qdict, "pci_addr"); @@ -245,6 +278,10 @@ void pci_device_hot_add(Monitor *mon, const QDict *qdict) dev = qemu_pci_hot_add_nic(mon, pci_addr, opts); } else if (strcmp(type, "storage") == 0) { dev = qemu_pci_hot_add_storage(mon, pci_addr, opts); +#ifdef CONFIG_MARU + } else if (strcmp(type, "keyboard") == 0) { + dev = qemu_pci_hot_add_keyboard(mon, pci_addr, opts); +#endif } else { monitor_printf(mon, "invalid type: %s\n", type); } @@ -256,6 +293,9 @@ void pci_device_hot_add(Monitor *mon, const QDict *qdict) PCI_FUNC(dev->devfn)); } else monitor_printf(mon, "failed to add %s\n", opts); +#ifdef CONFIG_MARU + return dev; +#endif } #endif diff --git a/hw/pci/pci.c b/hw/pci/pci.c index d5257ed..cfb62c2 100644 --- a/hw/pci/pci.c +++ b/hw/pci/pci.c @@ -1626,6 +1626,10 @@ PCIDevice *pci_vga_init(PCIBus *bus) return pci_create_simple(bus, -1, "VGA"); case VGA_VMWARE: return pci_create_simple(bus, -1, "vmware-svga"); +#ifdef CONFIG_VGA + case VGA_MARU: + return pci_create_simple(bus, -1, "MARU_VGA"); +#endif case VGA_NONE: default: /* Other non-PCI types. Checking for unsupported types is already done in vl.c. */ diff --git a/hw/pl050.c b/hw/pl050.c deleted file mode 100644 index 119b543..0000000 --- a/hw/pl050.c +++ /dev/null @@ -1,203 +0,0 @@ -/* - * Arm PrimeCell PL050 Keyboard / Mouse Interface - * - * Copyright (c) 2006-2007 CodeSourcery. - * Written by Paul Brook - * - * This code is licensed under the GPL. - */ - -#include "sysbus.h" -#include "ps2.h" - -typedef struct { - SysBusDevice busdev; - MemoryRegion iomem; - void *dev; - uint32_t cr; - uint32_t clk; - uint32_t last; - int pending; - qemu_irq irq; - int is_mouse; -} pl050_state; - -static const VMStateDescription vmstate_pl050 = { - .name = "pl050", - .version_id = 1, - .minimum_version_id = 1, - .fields = (VMStateField[]) { - VMSTATE_UINT32(cr, pl050_state), - VMSTATE_UINT32(clk, pl050_state), - VMSTATE_UINT32(last, pl050_state), - VMSTATE_INT32(pending, pl050_state), - VMSTATE_INT32(is_mouse, pl050_state), - VMSTATE_END_OF_LIST() - } -}; - -#define PL050_TXEMPTY (1 << 6) -#define PL050_TXBUSY (1 << 5) -#define PL050_RXFULL (1 << 4) -#define PL050_RXBUSY (1 << 3) -#define PL050_RXPARITY (1 << 2) -#define PL050_KMIC (1 << 1) -#define PL050_KMID (1 << 0) - -static const unsigned char pl050_id[] = -{ 0x50, 0x10, 0x04, 0x00, 0x0d, 0xf0, 0x05, 0xb1 }; - -static void pl050_update(void *opaque, int level) -{ - pl050_state *s = (pl050_state *)opaque; - int raise; - - s->pending = level; - raise = (s->pending && (s->cr & 0x10) != 0) - || (s->cr & 0x08) != 0; - qemu_set_irq(s->irq, raise); -} - -static uint64_t pl050_read(void *opaque, target_phys_addr_t offset, - unsigned size) -{ - pl050_state *s = (pl050_state *)opaque; - if (offset >= 0xfe0 && offset < 0x1000) - return pl050_id[(offset - 0xfe0) >> 2]; - - switch (offset >> 2) { - case 0: /* KMICR */ - return s->cr; - case 1: /* KMISTAT */ - { - uint8_t val; - uint32_t stat; - - val = s->last; - val = val ^ (val >> 4); - val = val ^ (val >> 2); - val = (val ^ (val >> 1)) & 1; - - stat = PL050_TXEMPTY; - if (val) - stat |= PL050_RXPARITY; - if (s->pending) - stat |= PL050_RXFULL; - - return stat; - } - case 2: /* KMIDATA */ - if (s->pending) - s->last = ps2_read_data(s->dev); - return s->last; - case 3: /* KMICLKDIV */ - return s->clk; - case 4: /* KMIIR */ - return s->pending | 2; - default: - hw_error("pl050_read: Bad offset %x\n", (int)offset); - return 0; - } -} - -static void pl050_write(void *opaque, target_phys_addr_t offset, - uint64_t value, unsigned size) -{ - pl050_state *s = (pl050_state *)opaque; - switch (offset >> 2) { - case 0: /* KMICR */ - s->cr = value; - pl050_update(s, s->pending); - /* ??? Need to implement the enable/disable bit. */ - break; - case 2: /* KMIDATA */ - /* ??? This should toggle the TX interrupt line. */ - /* ??? This means kbd/mouse can block each other. */ - if (s->is_mouse) { - ps2_write_mouse(s->dev, value); - } else { - ps2_write_keyboard(s->dev, value); - } - break; - case 3: /* KMICLKDIV */ - s->clk = value; -#ifdef CONFIG_MARU - if (!s->is_mouse) { - ps2_keyboard_set_translation(s->dev, 1); - } -#endif - return; - default: - hw_error("pl050_write: Bad offset %x\n", (int)offset); - } -} -static const MemoryRegionOps pl050_ops = { - .read = pl050_read, - .write = pl050_write, - .endianness = DEVICE_NATIVE_ENDIAN, -}; - -static int pl050_init(SysBusDevice *dev, int is_mouse) -{ - pl050_state *s = FROM_SYSBUS(pl050_state, dev); - - memory_region_init_io(&s->iomem, &pl050_ops, s, "pl050", 0x1000); - sysbus_init_mmio(dev, &s->iomem); - sysbus_init_irq(dev, &s->irq); - s->is_mouse = is_mouse; - if (s->is_mouse) - s->dev = ps2_mouse_init(pl050_update, s); - else - s->dev = ps2_kbd_init(pl050_update, s); - return 0; -} - -static int pl050_init_keyboard(SysBusDevice *dev) -{ - return pl050_init(dev, 0); -} - -static int pl050_init_mouse(SysBusDevice *dev) -{ - return pl050_init(dev, 1); -} - -static void pl050_kbd_class_init(ObjectClass *klass, void *data) -{ - DeviceClass *dc = DEVICE_CLASS(klass); - SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass); - - k->init = pl050_init_keyboard; - dc->vmsd = &vmstate_pl050; -} - -static TypeInfo pl050_kbd_info = { - .name = "pl050_keyboard", - .parent = TYPE_SYS_BUS_DEVICE, - .instance_size = sizeof(pl050_state), - .class_init = pl050_kbd_class_init, -}; - -static void pl050_mouse_class_init(ObjectClass *klass, void *data) -{ - DeviceClass *dc = DEVICE_CLASS(klass); - SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass); - - k->init = pl050_init_mouse; - dc->vmsd = &vmstate_pl050; -} - -static TypeInfo pl050_mouse_info = { - .name = "pl050_mouse", - .parent = TYPE_SYS_BUS_DEVICE, - .instance_size = sizeof(pl050_state), - .class_init = pl050_mouse_class_init, -}; - -static void pl050_register_types(void) -{ - type_register_static(&pl050_kbd_info); - type_register_static(&pl050_mouse_info); -} - -type_init(pl050_register_types) diff --git a/hw/ps2.c b/hw/ps2.c deleted file mode 100644 index 4c7abdd..0000000 --- a/hw/ps2.c +++ /dev/null @@ -1,687 +0,0 @@ -/* - * QEMU PS/2 keyboard/mouse emulation - * - * Copyright (c) 2003 Fabrice Bellard - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -#include "hw.h" -#include "ps2.h" -#include "console.h" -#include "sysemu.h" -#include "qemu-thread.h" - -/* debug PC keyboard */ -//#define DEBUG_KBD - -/* debug PC keyboard : only mouse */ -//#define DEBUG_MOUSE - -/* Keyboard Commands */ -#define KBD_CMD_SET_LEDS 0xED /* Set keyboard leds */ -#define KBD_CMD_ECHO 0xEE -#define KBD_CMD_SCANCODE 0xF0 /* Get/set scancode set */ -#define KBD_CMD_GET_ID 0xF2 /* get keyboard ID */ -#define KBD_CMD_SET_RATE 0xF3 /* Set typematic rate */ -#define KBD_CMD_ENABLE 0xF4 /* Enable scanning */ -#define KBD_CMD_RESET_DISABLE 0xF5 /* reset and disable scanning */ -#define KBD_CMD_RESET_ENABLE 0xF6 /* reset and enable scanning */ -#define KBD_CMD_RESET 0xFF /* Reset */ - -/* Keyboard Replies */ -#define KBD_REPLY_POR 0xAA /* Power on reset */ -#define KBD_REPLY_ID 0xAB /* Keyboard ID */ -#define KBD_REPLY_ACK 0xFA /* Command ACK */ -#define KBD_REPLY_RESEND 0xFE /* Command NACK, send the cmd again */ - -/* Mouse Commands */ -#define AUX_SET_SCALE11 0xE6 /* Set 1:1 scaling */ -#define AUX_SET_SCALE21 0xE7 /* Set 2:1 scaling */ -#define AUX_SET_RES 0xE8 /* Set resolution */ -#define AUX_GET_SCALE 0xE9 /* Get scaling factor */ -#define AUX_SET_STREAM 0xEA /* Set stream mode */ -#define AUX_POLL 0xEB /* Poll */ -#define AUX_RESET_WRAP 0xEC /* Reset wrap mode */ -#define AUX_SET_WRAP 0xEE /* Set wrap mode */ -#define AUX_SET_REMOTE 0xF0 /* Set remote mode */ -#define AUX_GET_TYPE 0xF2 /* Get type */ -#define AUX_SET_SAMPLE 0xF3 /* Set sample rate */ -#define AUX_ENABLE_DEV 0xF4 /* Enable aux device */ -#define AUX_DISABLE_DEV 0xF5 /* Disable aux device */ -#define AUX_SET_DEFAULT 0xF6 -#define AUX_RESET 0xFF /* Reset aux device */ -#define AUX_ACK 0xFA /* Command byte ACK. */ - -#define MOUSE_STATUS_REMOTE 0x40 -#define MOUSE_STATUS_ENABLED 0x20 -#define MOUSE_STATUS_SCALE21 0x10 - -#define PS2_QUEUE_SIZE 256 - -typedef struct { - uint8_t data[PS2_QUEUE_SIZE]; - int rptr, wptr, count; -} PS2Queue; - -typedef struct { - PS2Queue queue; - int32_t write_cmd; - void (*update_irq)(void *, int); - void *update_arg; -} PS2State; - -typedef struct { - PS2State common; - int scan_enabled; - /* QEMU uses translated PC scancodes internally. To avoid multiple - conversions we do the translation (if any) in the PS/2 emulation - not the keyboard controller. */ - int translate; - int scancode_set; /* 1=XT, 2=AT, 3=PS/2 */ - int ledstate; -} PS2KbdState; - -typedef struct { - PS2State common; - uint8_t mouse_status; - uint8_t mouse_resolution; - uint8_t mouse_sample_rate; - uint8_t mouse_wrap; - uint8_t mouse_type; /* 0 = PS2, 3 = IMPS/2, 4 = IMEX */ - uint8_t mouse_detect_state; - int mouse_dx; /* current values, needed for 'poll' mode */ - int mouse_dy; - int mouse_dz; - uint8_t mouse_buttons; -} PS2MouseState; - -/* Table to convert from PC scancodes to raw scancodes. */ -static const unsigned char ps2_raw_keycode[128] = { - 0, 118, 22, 30, 38, 37, 46, 54, 61, 62, 70, 69, 78, 85, 102, 13, - 21, 29, 36, 45, 44, 53, 60, 67, 68, 77, 84, 91, 90, 20, 28, 27, - 35, 43, 52, 51, 59, 66, 75, 76, 82, 14, 18, 93, 26, 34, 33, 42, - 50, 49, 58, 65, 73, 74, 89, 124, 17, 41, 88, 5, 6, 4, 12, 3, - 11, 2, 10, 1, 9, 119, 126, 108, 117, 125, 123, 107, 115, 116, 121, 105, -114, 122, 112, 113, 127, 96, 97, 120, 7, 15, 23, 31, 39, 47, 55, 63, - 71, 79, 86, 94, 8, 16, 24, 32, 40, 48, 56, 64, 72, 80, 87, 111, - 19, 25, 57, 81, 83, 92, 95, 98, 99, 100, 101, 103, 104, 106, 109, 110 -}; -static const unsigned char ps2_raw_keycode_set3[128] = { - 0, 8, 22, 30, 38, 37, 46, 54, 61, 62, 70, 69, 78, 85, 102, 13, - 21, 29, 36, 45, 44, 53, 60, 67, 68, 77, 84, 91, 90, 17, 28, 27, - 35, 43, 52, 51, 59, 66, 75, 76, 82, 14, 18, 92, 26, 34, 33, 42, - 50, 49, 58, 65, 73, 74, 89, 126, 25, 41, 20, 7, 15, 23, 31, 39, - 47, 2, 63, 71, 79, 118, 95, 108, 117, 125, 132, 107, 115, 116, 124, 105, -114, 122, 112, 113, 127, 96, 97, 86, 94, 15, 23, 31, 39, 47, 55, 63, - 71, 79, 86, 94, 8, 16, 24, 32, 40, 48, 56, 64, 72, 80, 87, 111, - 19, 25, 57, 81, 83, 92, 95, 98, 99, 100, 101, 103, 104, 106, 109, 110 -}; - -static QemuMutex mutex; - -void ps2_queue(void *opaque, int b) -{ - PS2State *s = (PS2State *)opaque; - PS2Queue *q = &s->queue; - - if (q->count >= PS2_QUEUE_SIZE) - return; - q->data[q->wptr] = b; - if (++q->wptr == PS2_QUEUE_SIZE) - q->wptr = 0; - q->count++; - s->update_irq(s->update_arg, 1); -} - -/* - keycode is expressed as follow: - bit 7 - 0 key pressed, 1 = key released - bits 6-0 - translated scancode set 2 - */ -static void ps2_put_keycode(void *opaque, int keycode) -{ - PS2KbdState *s = opaque; - - qemu_system_wakeup_request(QEMU_WAKEUP_REASON_OTHER); - /* XXX: add support for scancode set 1 */ - if (!s->translate && keycode < 0xe0 && s->scancode_set > 1) { - if (keycode & 0x80) { - ps2_queue(&s->common, 0xf0); - } - if (s->scancode_set == 2) { - keycode = ps2_raw_keycode[keycode & 0x7f]; - } else if (s->scancode_set == 3) { - keycode = ps2_raw_keycode_set3[keycode & 0x7f]; - } - } - ps2_queue(&s->common, keycode); -} - -uint32_t ps2_read_data(void *opaque) -{ - PS2State *s = (PS2State *)opaque; - PS2Queue *q; - int val, index; - - q = &s->queue; - if (q->count == 0) { - /* NOTE: if no data left, we return the last keyboard one - (needed for EMM386) */ - /* XXX: need a timer to do things correctly */ - index = q->rptr - 1; - if (index < 0) - index = PS2_QUEUE_SIZE - 1; - val = q->data[index]; - } else { - val = q->data[q->rptr]; - if (++q->rptr == PS2_QUEUE_SIZE) - q->rptr = 0; - q->count--; - /* reading deasserts IRQ */ - s->update_irq(s->update_arg, 0); - /* reassert IRQs if data left */ - s->update_irq(s->update_arg, q->count != 0); - } - return val; -} - -static void ps2_set_ledstate(PS2KbdState *s, int ledstate) -{ - s->ledstate = ledstate; - kbd_put_ledstate(ledstate); -} - -static void ps2_reset_keyboard(PS2KbdState *s) -{ - s->scan_enabled = 1; - s->scancode_set = 2; - ps2_set_ledstate(s, 0); -} - -void ps2_write_keyboard(void *opaque, int val) -{ - PS2KbdState *s = (PS2KbdState *)opaque; - - switch(s->common.write_cmd) { - default: - case -1: - switch(val) { - case 0x00: - ps2_queue(&s->common, KBD_REPLY_ACK); - break; - case 0x05: - ps2_queue(&s->common, KBD_REPLY_RESEND); - break; - case KBD_CMD_GET_ID: - ps2_queue(&s->common, KBD_REPLY_ACK); - /* We emulate a MF2 AT keyboard here */ - ps2_queue(&s->common, KBD_REPLY_ID); - if (s->translate) - ps2_queue(&s->common, 0x41); - else - ps2_queue(&s->common, 0x83); - break; - case KBD_CMD_ECHO: - ps2_queue(&s->common, KBD_CMD_ECHO); - break; - case KBD_CMD_ENABLE: - s->scan_enabled = 1; - ps2_queue(&s->common, KBD_REPLY_ACK); - break; - case KBD_CMD_SCANCODE: - case KBD_CMD_SET_LEDS: - case KBD_CMD_SET_RATE: - s->common.write_cmd = val; - ps2_queue(&s->common, KBD_REPLY_ACK); - break; - case KBD_CMD_RESET_DISABLE: - ps2_reset_keyboard(s); - s->scan_enabled = 0; - ps2_queue(&s->common, KBD_REPLY_ACK); - break; - case KBD_CMD_RESET_ENABLE: - ps2_reset_keyboard(s); - s->scan_enabled = 1; - ps2_queue(&s->common, KBD_REPLY_ACK); - break; - case KBD_CMD_RESET: - ps2_reset_keyboard(s); - ps2_queue(&s->common, KBD_REPLY_ACK); - ps2_queue(&s->common, KBD_REPLY_POR); - break; - default: - ps2_queue(&s->common, KBD_REPLY_ACK); - break; - } - break; - case KBD_CMD_SCANCODE: - if (val == 0) { - if (s->scancode_set == 1) - ps2_put_keycode(s, 0x43); - else if (s->scancode_set == 2) - ps2_put_keycode(s, 0x41); - else if (s->scancode_set == 3) - ps2_put_keycode(s, 0x3f); - } else { - if (val >= 1 && val <= 3) - s->scancode_set = val; - ps2_queue(&s->common, KBD_REPLY_ACK); - } - s->common.write_cmd = -1; - break; - case KBD_CMD_SET_LEDS: - ps2_set_ledstate(s, val); - ps2_queue(&s->common, KBD_REPLY_ACK); - s->common.write_cmd = -1; - break; - case KBD_CMD_SET_RATE: - ps2_queue(&s->common, KBD_REPLY_ACK); - s->common.write_cmd = -1; - break; - } -} - -/* Set the scancode translation mode. - 0 = raw scancodes. - 1 = translated scancodes (used by qemu internally). */ - -void ps2_keyboard_set_translation(void *opaque, int mode) -{ - PS2KbdState *s = (PS2KbdState *)opaque; - s->translate = mode; -} - -static void ps2_mouse_send_packet(PS2MouseState *s) -{ - unsigned int b; - int dx1, dy1, dz1; - - dx1 = s->mouse_dx; - dy1 = s->mouse_dy; - dz1 = s->mouse_dz; - /* XXX: increase range to 8 bits ? */ - if (dx1 > 127) - dx1 = 127; - else if (dx1 < -127) - dx1 = -127; - if (dy1 > 127) - dy1 = 127; - else if (dy1 < -127) - dy1 = -127; - b = 0x08 | ((dx1 < 0) << 4) | ((dy1 < 0) << 5) | (s->mouse_buttons & 0x07); - ps2_queue(&s->common, b); - ps2_queue(&s->common, dx1 & 0xff); - ps2_queue(&s->common, dy1 & 0xff); - /* extra byte for IMPS/2 or IMEX */ - switch(s->mouse_type) { - default: - break; - case 3: - if (dz1 > 127) - dz1 = 127; - else if (dz1 < -127) - dz1 = -127; - ps2_queue(&s->common, dz1 & 0xff); - break; - case 4: - if (dz1 > 7) - dz1 = 7; - else if (dz1 < -7) - dz1 = -7; - b = (dz1 & 0x0f) | ((s->mouse_buttons & 0x18) << 1); - ps2_queue(&s->common, b); - break; - } - - /* update deltas */ - s->mouse_dx -= dx1; - s->mouse_dy -= dy1; - s->mouse_dz -= dz1; -} - -static void ps2_mouse_event(void *opaque, - int dx, int dy, int dz, int buttons_state) -{ - PS2MouseState *s = opaque; - - /* check if deltas are recorded when disabled */ - if (!(s->mouse_status & MOUSE_STATUS_ENABLED)) - return; - - s->mouse_dx += dx; - s->mouse_dy -= dy; - s->mouse_dz += dz; - /* XXX: SDL sometimes generates nul events: we delete them */ - if (s->mouse_dx == 0 && s->mouse_dy == 0 && s->mouse_dz == 0 && - s->mouse_buttons == buttons_state) - return; - s->mouse_buttons = buttons_state; - - if (buttons_state) { - qemu_system_wakeup_request(QEMU_WAKEUP_REASON_OTHER); - } - - if (!(s->mouse_status & MOUSE_STATUS_REMOTE) && - (s->common.queue.count < (PS2_QUEUE_SIZE - 16))) { - for(;;) { - /* if not remote, send event. Multiple events are sent if - too big deltas */ - qemu_mutex_lock(&mutex); - ps2_mouse_send_packet(s); - qemu_mutex_unlock(&mutex); - if (s->mouse_dx == 0 && s->mouse_dy == 0 && s->mouse_dz == 0) - break; - } - } -} - -void ps2_mouse_fake_event(void *opaque) -{ - ps2_mouse_event(opaque, 1, 0, 0, 0); -} - -void ps2_write_mouse(void *opaque, int val) -{ - PS2MouseState *s = (PS2MouseState *)opaque; -#ifdef DEBUG_MOUSE - printf("kbd: write mouse 0x%02x\n", val); -#endif - switch(s->common.write_cmd) { - default: - case -1: - /* mouse command */ - if (s->mouse_wrap) { - if (val == AUX_RESET_WRAP) { - s->mouse_wrap = 0; - ps2_queue(&s->common, AUX_ACK); - return; - } else if (val != AUX_RESET) { - ps2_queue(&s->common, val); - return; - } - } - switch(val) { - case AUX_SET_SCALE11: - s->mouse_status &= ~MOUSE_STATUS_SCALE21; - ps2_queue(&s->common, AUX_ACK); - break; - case AUX_SET_SCALE21: - s->mouse_status |= MOUSE_STATUS_SCALE21; - ps2_queue(&s->common, AUX_ACK); - break; - case AUX_SET_STREAM: - s->mouse_status &= ~MOUSE_STATUS_REMOTE; - ps2_queue(&s->common, AUX_ACK); - break; - case AUX_SET_WRAP: - s->mouse_wrap = 1; - ps2_queue(&s->common, AUX_ACK); - break; - case AUX_SET_REMOTE: - s->mouse_status |= MOUSE_STATUS_REMOTE; - ps2_queue(&s->common, AUX_ACK); - break; - case AUX_GET_TYPE: - ps2_queue(&s->common, AUX_ACK); - ps2_queue(&s->common, s->mouse_type); - break; - case AUX_SET_RES: - case AUX_SET_SAMPLE: - s->common.write_cmd = val; - ps2_queue(&s->common, AUX_ACK); - break; - case AUX_GET_SCALE: - ps2_queue(&s->common, AUX_ACK); - ps2_queue(&s->common, s->mouse_status); - ps2_queue(&s->common, s->mouse_resolution); - ps2_queue(&s->common, s->mouse_sample_rate); - break; - case AUX_POLL: - ps2_queue(&s->common, AUX_ACK); - ps2_mouse_send_packet(s); - break; - case AUX_ENABLE_DEV: - s->mouse_status |= MOUSE_STATUS_ENABLED; - ps2_queue(&s->common, AUX_ACK); - break; - case AUX_DISABLE_DEV: - s->mouse_status &= ~MOUSE_STATUS_ENABLED; - ps2_queue(&s->common, AUX_ACK); - break; - case AUX_SET_DEFAULT: - s->mouse_sample_rate = 100; - s->mouse_resolution = 2; - s->mouse_status = 0; - ps2_queue(&s->common, AUX_ACK); - break; - case AUX_RESET: - s->mouse_sample_rate = 100; - s->mouse_resolution = 2; - s->mouse_status = 0; - s->mouse_type = 0; - ps2_queue(&s->common, AUX_ACK); - ps2_queue(&s->common, 0xaa); - ps2_queue(&s->common, s->mouse_type); - break; - default: - break; - } - break; - case AUX_SET_SAMPLE: - s->mouse_sample_rate = val; - /* detect IMPS/2 or IMEX */ - switch(s->mouse_detect_state) { - default: - case 0: - if (val == 200) - s->mouse_detect_state = 1; - break; - case 1: - if (val == 100) - s->mouse_detect_state = 2; - else if (val == 200) - s->mouse_detect_state = 3; - else - s->mouse_detect_state = 0; - break; - case 2: - if (val == 80) - s->mouse_type = 3; /* IMPS/2 */ - s->mouse_detect_state = 0; - break; - case 3: - if (val == 80) - s->mouse_type = 4; /* IMEX */ - s->mouse_detect_state = 0; - break; - } - ps2_queue(&s->common, AUX_ACK); - s->common.write_cmd = -1; - break; - case AUX_SET_RES: - s->mouse_resolution = val; - ps2_queue(&s->common, AUX_ACK); - s->common.write_cmd = -1; - break; - } -} - -static void ps2_common_reset(PS2State *s) -{ - PS2Queue *q; - s->write_cmd = -1; - q = &s->queue; - q->rptr = 0; - q->wptr = 0; - q->count = 0; - s->update_irq(s->update_arg, 0); -} - -static void ps2_kbd_reset(void *opaque) -{ - PS2KbdState *s = (PS2KbdState *) opaque; - - ps2_common_reset(&s->common); - s->scan_enabled = 0; - s->translate = 0; - s->scancode_set = 0; -} - -static void ps2_mouse_reset(void *opaque) -{ - PS2MouseState *s = (PS2MouseState *) opaque; - - ps2_common_reset(&s->common); - s->mouse_status = 0; - s->mouse_resolution = 0; - s->mouse_sample_rate = 0; - s->mouse_wrap = 0; - s->mouse_type = 0; - s->mouse_detect_state = 0; - s->mouse_dx = 0; - s->mouse_dy = 0; - s->mouse_dz = 0; - s->mouse_buttons = 0; -} - -static const VMStateDescription vmstate_ps2_common = { - .name = "PS2 Common State", - .version_id = 3, - .minimum_version_id = 2, - .minimum_version_id_old = 2, - .fields = (VMStateField []) { - VMSTATE_INT32(write_cmd, PS2State), - VMSTATE_INT32(queue.rptr, PS2State), - VMSTATE_INT32(queue.wptr, PS2State), - VMSTATE_INT32(queue.count, PS2State), - VMSTATE_BUFFER(queue.data, PS2State), - VMSTATE_END_OF_LIST() - } -}; - -static bool ps2_keyboard_ledstate_needed(void *opaque) -{ - PS2KbdState *s = opaque; - - return s->ledstate != 0; /* 0 is default state */ -} - -static int ps2_kbd_ledstate_post_load(void *opaque, int version_id) -{ - PS2KbdState *s = opaque; - - kbd_put_ledstate(s->ledstate); - return 0; -} - -static const VMStateDescription vmstate_ps2_keyboard_ledstate = { - .name = "ps2kbd/ledstate", - .version_id = 3, - .minimum_version_id = 2, - .minimum_version_id_old = 2, - .post_load = ps2_kbd_ledstate_post_load, - .fields = (VMStateField []) { - VMSTATE_INT32(ledstate, PS2KbdState), - VMSTATE_END_OF_LIST() - } -}; - -static int ps2_kbd_post_load(void* opaque, int version_id) -{ - PS2KbdState *s = (PS2KbdState*)opaque; - - if (version_id == 2) - s->scancode_set=2; - return 0; -} - -static const VMStateDescription vmstate_ps2_keyboard = { - .name = "ps2kbd", - .version_id = 3, - .minimum_version_id = 2, - .minimum_version_id_old = 2, - .post_load = ps2_kbd_post_load, - .fields = (VMStateField []) { - VMSTATE_STRUCT(common, PS2KbdState, 0, vmstate_ps2_common, PS2State), - VMSTATE_INT32(scan_enabled, PS2KbdState), - VMSTATE_INT32(translate, PS2KbdState), - VMSTATE_INT32_V(scancode_set, PS2KbdState,3), - VMSTATE_END_OF_LIST() - }, - .subsections = (VMStateSubsection []) { - { - .vmsd = &vmstate_ps2_keyboard_ledstate, - .needed = ps2_keyboard_ledstate_needed, - }, { - /* empty */ - } - } -}; - -static const VMStateDescription vmstate_ps2_mouse = { - .name = "ps2mouse", - .version_id = 2, - .minimum_version_id = 2, - .minimum_version_id_old = 2, - .fields = (VMStateField []) { - VMSTATE_STRUCT(common, PS2MouseState, 0, vmstate_ps2_common, PS2State), - VMSTATE_UINT8(mouse_status, PS2MouseState), - VMSTATE_UINT8(mouse_resolution, PS2MouseState), - VMSTATE_UINT8(mouse_sample_rate, PS2MouseState), - VMSTATE_UINT8(mouse_wrap, PS2MouseState), - VMSTATE_UINT8(mouse_type, PS2MouseState), - VMSTATE_UINT8(mouse_detect_state, PS2MouseState), - VMSTATE_INT32(mouse_dx, PS2MouseState), - VMSTATE_INT32(mouse_dy, PS2MouseState), - VMSTATE_INT32(mouse_dz, PS2MouseState), - VMSTATE_UINT8(mouse_buttons, PS2MouseState), - VMSTATE_END_OF_LIST() - } -}; - -void *ps2_kbd_init(void (*update_irq)(void *, int), void *update_arg) -{ - PS2KbdState *s = (PS2KbdState *)g_malloc0(sizeof(PS2KbdState)); - - s->common.update_irq = update_irq; - s->common.update_arg = update_arg; - s->scancode_set = 2; - vmstate_register(NULL, 0, &vmstate_ps2_keyboard, s); -#ifdef CONFIG_MARU - qemu_add_ps2kbd_event_handler(ps2_put_keycode, s); -#else - qemu_add_kbd_event_handler(ps2_put_keycode, s); -#endif - qemu_register_reset(ps2_kbd_reset, s); - return s; -} - -void *ps2_mouse_init(void (*update_irq)(void *, int), void *update_arg) -{ - PS2MouseState *s = (PS2MouseState *)g_malloc0(sizeof(PS2MouseState)); - - s->common.update_irq = update_irq; - s->common.update_arg = update_arg; - vmstate_register(NULL, 0, &vmstate_ps2_mouse, s); - qemu_add_mouse_event_handler(ps2_mouse_event, s, 0, "QEMU PS/2 Mouse"); - qemu_register_reset(ps2_mouse_reset, s); - qemu_mutex_init(&mutex); - - return s; -} diff --git a/hw/vga-pci.c b/hw/vga-pci.c deleted file mode 100644 index 3c2278d..0000000 --- a/hw/vga-pci.c +++ /dev/null @@ -1,171 +0,0 @@ -/* - * QEMU PCI VGA Emulator. - * - * Copyright (c) 2003 Fabrice Bellard - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -#include "hw.h" -#include "console.h" -#include "pci.h" -#include "vga-pci.h" -#include "vga_int.h" -#include "pixel_ops.h" -#include "qemu-timer.h" -#include "loader.h" -#ifdef CONFIG_MARU -#include "../tizen/src/hw/maru_device_ids.h" -#include "../tizen/src/hw/maru_vga_int.h" -#endif - -typedef struct PCIVGAState { - PCIDevice dev; - VGACommonState vga; -} PCIVGAState; - -static const VMStateDescription vmstate_vga_pci = { - .name = "vga", - .version_id = 2, - .minimum_version_id = 2, - .minimum_version_id_old = 2, - .fields = (VMStateField []) { - VMSTATE_PCI_DEVICE(dev, PCIVGAState), - VMSTATE_STRUCT(vga, PCIVGAState, 0, vmstate_vga_common, VGACommonState), - VMSTATE_END_OF_LIST() - } -}; - -static int pci_vga_initfn(PCIDevice *dev) -{ - PCIVGAState *d = DO_UPCAST(PCIVGAState, dev, dev); - VGACommonState *s = &d->vga; - - // vga + console init - vga_common_init(s); - vga_init(s, pci_address_space(dev), pci_address_space_io(dev), true); - - s->ds = graphic_console_init(s->update, s->invalidate, - s->screen_dump, s->text_update, s); - - /* XXX: VGA_RAM_SIZE must be a power of two */ - pci_register_bar(&d->dev, 0, PCI_BASE_ADDRESS_MEM_PREFETCH, &s->vram); - - if (!dev->rom_bar) { - /* compatibility with pc-0.13 and older */ - vga_init_vbe(s, pci_address_space(dev)); - } - - return 0; -} - -DeviceState *pci_vga_init(PCIBus *bus) -{ - return &pci_create_simple(bus, -1, "VGA")->qdev; -} - -static Property vga_pci_properties[] = { - DEFINE_PROP_UINT32("vgamem_mb", PCIVGAState, vga.vram_size_mb, 16), - DEFINE_PROP_END_OF_LIST(), -}; - -static void vga_class_init(ObjectClass *klass, void *data) -{ - DeviceClass *dc = DEVICE_CLASS(klass); - PCIDeviceClass *k = PCI_DEVICE_CLASS(klass); - - k->no_hotplug = 1; - k->init = pci_vga_initfn; - k->romfile = "vgabios-stdvga.bin"; - k->vendor_id = PCI_VENDOR_ID_QEMU; - k->device_id = PCI_DEVICE_ID_QEMU_VGA; - k->class_id = PCI_CLASS_DISPLAY_VGA; - dc->vmsd = &vmstate_vga_pci; - dc->props = vga_pci_properties; -} - -static TypeInfo vga_info = { - .name = "VGA", - .parent = TYPE_PCI_DEVICE, - .instance_size = sizeof(PCIVGAState), - .class_init = vga_class_init, -}; - -#ifdef CONFIG_MARU - -DeviceState *pci_maru_vga_init(PCIBus *bus) -{ - return &pci_create_simple(bus, -1, "MARU_VGA")->qdev; -} - -static int maru_pci_vga_initfn(PCIDevice *dev) -{ - PCIVGAState *d = DO_UPCAST(PCIVGAState, dev, dev); - VGACommonState *s = &d->vga; - - // vga + console init - maru_vga_common_init(s); - vga_init(s, pci_address_space(dev), pci_address_space_io(dev), true); - - s->ds = graphic_console_init(s->update, s->invalidate, - s->screen_dump, s->text_update, s); - - /* XXX: VGA_RAM_SIZE must be a power of two */ - pci_register_bar(&d->dev, 0, PCI_BASE_ADDRESS_MEM_PREFETCH, &s->vram); - - if (!dev->rom_bar) { - /* compatibility with pc-0.13 and older */ - vga_init_vbe(s, pci_address_space(dev)); - } - - return 0; -} - -static void maru_pci_vga_classinit(ObjectClass *klass, void *data) -{ - DeviceClass *dc = DEVICE_CLASS(klass); - PCIDeviceClass *k = PCI_DEVICE_CLASS(klass); - - k->no_hotplug = 1; - k->init = maru_pci_vga_initfn; - k->romfile = "vgabios-maruvga.bin"; - k->vendor_id = PCI_VENDOR_ID_QEMU; - k->device_id = PCI_DEVICE_ID_QEMU_VGA; - k->class_id = PCI_CLASS_DISPLAY_VGA; - dc->vmsd = &vmstate_vga_pci; - dc->props = vga_pci_properties; -} - -static TypeInfo maru_vga_info = { - .name = "MARU_VGA", - .parent = TYPE_PCI_DEVICE, - .instance_size = sizeof(PCIVGAState), - .class_init = maru_pci_vga_classinit, -}; - -#endif // CONFIG_MARU - -static void vga_register_types(void) -{ - type_register_static(&vga_info); -#ifdef CONFIG_MARU - type_register_static(&maru_vga_info); -#endif -} - -type_init(vga_register_types) diff --git a/hw/vga-pci.h b/hw/vga-pci.h deleted file mode 100644 index 2d02920..0000000 --- a/hw/vga-pci.h +++ /dev/null @@ -1,16 +0,0 @@ -#ifndef VGA_PCI_H -#define VGA_PCI_H - -#include "qemu-common.h" - -/* vga-pci.c */ -DeviceState *pci_vga_init(PCIBus *bus); - -/* cirrus_vga.c */ -DeviceState *pci_cirrus_vga_init(PCIBus *bus); - -#ifdef CONFIG_MARU -DeviceState *pci_maru_vga_init(PCIBus *bus); -#endif - -#endif diff --git a/hw/vga_int.h b/hw/vga_int.h deleted file mode 100644 index 9865002..0000000 --- a/hw/vga_int.h +++ /dev/null @@ -1,223 +0,0 @@ -/* - * QEMU internal VGA defines. - * - * Copyright (c) 2003-2004 Fabrice Bellard - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - -#include -#include "memory.h" - -#define ST01_V_RETRACE 0x08 -#define ST01_DISP_ENABLE 0x01 - -/* bochs VBE support */ -#define CONFIG_BOCHS_VBE - -#if CONFIG_MARU -#define VBE_DISPI_MAX_XRES 2600 -#define VBE_DISPI_MAX_YRES 2600 -#else -#define VBE_DISPI_MAX_XRES 1600 -#define VBE_DISPI_MAX_YRES 1200 -#endif -#define VBE_DISPI_MAX_BPP 32 - -#define VBE_DISPI_INDEX_ID 0x0 -#define VBE_DISPI_INDEX_XRES 0x1 -#define VBE_DISPI_INDEX_YRES 0x2 -#define VBE_DISPI_INDEX_BPP 0x3 -#define VBE_DISPI_INDEX_ENABLE 0x4 -#define VBE_DISPI_INDEX_BANK 0x5 -#define VBE_DISPI_INDEX_VIRT_WIDTH 0x6 -#define VBE_DISPI_INDEX_VIRT_HEIGHT 0x7 -#define VBE_DISPI_INDEX_X_OFFSET 0x8 -#define VBE_DISPI_INDEX_Y_OFFSET 0x9 -#define VBE_DISPI_INDEX_NB 0xa /* size of vbe_regs[] */ -#define VBE_DISPI_INDEX_VIDEO_MEMORY_64K 0xa /* read-only, not in vbe_regs */ - -#define VBE_DISPI_ID0 0xB0C0 -#define VBE_DISPI_ID1 0xB0C1 -#define VBE_DISPI_ID2 0xB0C2 -#define VBE_DISPI_ID3 0xB0C3 -#define VBE_DISPI_ID4 0xB0C4 -#define VBE_DISPI_ID5 0xB0C5 - -#define VBE_DISPI_DISABLED 0x00 -#define VBE_DISPI_ENABLED 0x01 -#define VBE_DISPI_GETCAPS 0x02 -#define VBE_DISPI_8BIT_DAC 0x20 -#define VBE_DISPI_LFB_ENABLED 0x40 -#define VBE_DISPI_NOCLEARMEM 0x80 - -#define VBE_DISPI_LFB_PHYSICAL_ADDRESS 0xE0000000 - -#ifdef CONFIG_BOCHS_VBE - -#define VGA_STATE_COMMON_BOCHS_VBE \ - uint16_t vbe_index; \ - uint16_t vbe_regs[VBE_DISPI_INDEX_NB]; \ - uint32_t vbe_start_addr; \ - uint32_t vbe_line_offset; \ - uint32_t vbe_bank_mask; \ - int vbe_mapped; -#else - -#define VGA_STATE_COMMON_BOCHS_VBE - -#endif /* !CONFIG_BOCHS_VBE */ - -#define CH_ATTR_SIZE (160 * 100) -#define VGA_MAX_HEIGHT 2048 - -struct vga_precise_retrace { - int64_t ticks_per_char; - int64_t total_chars; - int htotal; - int hstart; - int hend; - int vstart; - int vend; - int freq; -}; - -union vga_retrace { - struct vga_precise_retrace precise; -}; - -struct VGACommonState; -typedef uint8_t (* vga_retrace_fn)(struct VGACommonState *s); -typedef void (* vga_update_retrace_info_fn)(struct VGACommonState *s); - -typedef struct VGACommonState { - MemoryRegion *legacy_address_space; - uint8_t *vram_ptr; - MemoryRegion vram; - MemoryRegion vram_vbe; - uint32_t vram_size; - uint32_t vram_size_mb; /* property */ - uint32_t latch; - MemoryRegion *chain4_alias; - uint8_t sr_index; - uint8_t sr[256]; - uint8_t gr_index; - uint8_t gr[256]; - uint8_t ar_index; - uint8_t ar[21]; - int ar_flip_flop; - uint8_t cr_index; - uint8_t cr[256]; /* CRT registers */ - uint8_t msr; /* Misc Output Register */ - uint8_t fcr; /* Feature Control Register */ - uint8_t st00; /* status 0 */ - uint8_t st01; /* status 1 */ - uint8_t dac_state; - uint8_t dac_sub_index; - uint8_t dac_read_index; - uint8_t dac_write_index; - uint8_t dac_cache[3]; /* used when writing */ - int dac_8bit; - uint8_t palette[768]; - int32_t bank_offset; - int (*get_bpp)(struct VGACommonState *s); - void (*get_offsets)(struct VGACommonState *s, - uint32_t *pline_offset, - uint32_t *pstart_addr, - uint32_t *pline_compare); - void (*get_resolution)(struct VGACommonState *s, - int *pwidth, - int *pheight); - VGA_STATE_COMMON_BOCHS_VBE - /* display refresh support */ - DisplayState *ds; - uint32_t font_offsets[2]; - int graphic_mode; - uint8_t shift_control; - uint8_t double_scan; - uint32_t line_offset; - uint32_t line_compare; - uint32_t start_addr; - uint32_t plane_updated; - uint32_t last_line_offset; - uint8_t last_cw, last_ch; - uint32_t last_width, last_height; /* in chars or pixels */ - uint32_t last_scr_width, last_scr_height; /* in pixels */ - uint32_t last_depth; /* in bits */ - uint8_t cursor_start, cursor_end; - bool cursor_visible_phase; - int64_t cursor_blink_time; - uint32_t cursor_offset; - unsigned int (*rgb_to_pixel)(unsigned int r, - unsigned int g, unsigned b); - vga_hw_update_ptr update; - vga_hw_invalidate_ptr invalidate; - vga_hw_screen_dump_ptr screen_dump; - vga_hw_text_update_ptr text_update; - /* hardware mouse cursor support */ - uint32_t invalidated_y_table[VGA_MAX_HEIGHT / 32]; - void (*cursor_invalidate)(struct VGACommonState *s); - void (*cursor_draw_line)(struct VGACommonState *s, uint8_t *d, int y); - /* tell for each page if it has been updated since the last time */ - uint32_t last_palette[256]; - uint32_t last_ch_attr[CH_ATTR_SIZE]; /* XXX: make it dynamic */ - /* retrace */ - vga_retrace_fn retrace; - vga_update_retrace_info_fn update_retrace_info; - union vga_retrace retrace_info; - uint8_t is_vbe_vmstate; -} VGACommonState; - -static inline int c6_to_8(int v) -{ - int b; - v &= 0x3f; - b = v & 1; - return (v << 2) | (b << 1) | b; -} - -void vga_common_init(VGACommonState *s); -void vga_init(VGACommonState *s, MemoryRegion *address_space, - MemoryRegion *address_space_io, bool init_vga_ports); -MemoryRegion *vga_init_io(VGACommonState *s, - const MemoryRegionPortio **vga_ports, - const MemoryRegionPortio **vbe_ports); -void vga_common_reset(VGACommonState *s); - -void vga_dirty_log_start(VGACommonState *s); -void vga_dirty_log_stop(VGACommonState *s); - -extern const VMStateDescription vmstate_vga_common; -uint32_t vga_ioport_read(void *opaque, uint32_t addr); -void vga_ioport_write(void *opaque, uint32_t addr, uint32_t val); -uint32_t vga_mem_readb(VGACommonState *s, target_phys_addr_t addr); -void vga_mem_writeb(VGACommonState *s, target_phys_addr_t addr, uint32_t val); -void vga_invalidate_scanlines(VGACommonState *s, int y1, int y2); -int ppm_save(const char *filename, struct DisplaySurface *ds); - -int vga_ioport_invalid(VGACommonState *s, uint32_t addr); -void vga_init_vbe(VGACommonState *s, MemoryRegion *address_space); - -extern const uint8_t sr_mask[8]; -extern const uint8_t gr_mask[16]; - -#define VGABIOS_FILENAME "vgabios.bin" -#define VGABIOS_CIRRUS_FILENAME "vgabios-cirrus.bin" - -extern const MemoryRegionOps vga_mem_ops; diff --git a/include/exec/cpu-defs.h b/include/exec/cpu-defs.h index d8c64e9..3a4486c 100644 --- a/include/exec/cpu-defs.h +++ b/include/exec/cpu-defs.h @@ -179,6 +179,10 @@ typedef struct CPUWatchpoint { sigjmp_buf jmp_env; \ int exception_index; \ \ + /* for hax */ \ + int hax_vcpu_dirty; \ + struct hax_vcpu_state *hax_vcpu; \ + \ CPUArchState *next_cpu; /* next CPU sharing TB cache */ \ /* user data */ \ void *opaque; \ diff --git a/include/hw/pci/pci.h b/include/hw/pci/pci.h index 8d075ab..238c15f 100644 --- a/include/hw/pci/pci.h +++ b/include/hw/pci/pci.h @@ -80,6 +80,9 @@ #define PCI_DEVICE_ID_VIRTIO_SCSI 0x1004 #define PCI_DEVICE_ID_VIRTIO_RNG 0x1005 #define PCI_DEVICE_ID_VIRTIO_9P 0x1009 +#ifdef CONFIG_MARU +#define PCI_DEVICE_ID_VIRTIO_GL 0x1006 +#endif #define PCI_VENDOR_ID_REDHAT 0x1b36 #define PCI_DEVICE_ID_REDHAT_BRIDGE 0x0001 diff --git a/include/qemu/main-loop.h b/include/qemu/main-loop.h index 6f0200a..6014714 100644 --- a/include/qemu/main-loop.h +++ b/include/qemu/main-loop.h @@ -101,6 +101,16 @@ AioContext *qemu_get_aio_context(void); */ void qemu_notify_event(void); +// TODO: Mark HAX related code... +#ifdef CONFIG_HAX_BACKEND +void qemu_notify_hax_event(void); +#else +static inline void qemu_notify_hax_event(void) +{ +} +#endif +// + #ifdef _WIN32 /* return TRUE if no sleep should be done afterwards */ typedef int PollingFunc(void *opaque); diff --git a/include/sysemu/arch_init.h b/include/sysemu/arch_init.h index dece913..c9621d9 100644 --- a/include/sysemu/arch_init.h +++ b/include/sysemu/arch_init.h @@ -34,6 +34,7 @@ void audio_init(void); int tcg_available(void); int kvm_available(void); int xen_available(void); +int hax_available(void); CpuDefinitionInfoList *arch_query_cpu_definitions(Error **errp); diff --git a/include/sysemu/kvm.h b/include/sysemu/kvm.h index 08284ef..f7dfce2 100644 --- a/include/sysemu/kvm.h +++ b/include/sysemu/kvm.h @@ -250,6 +250,9 @@ int kvm_check_extension(KVMState *s, unsigned int extension); uint32_t kvm_arch_get_supported_cpuid(KVMState *env, uint32_t function, uint32_t index, int reg); void kvm_cpu_synchronize_state(CPUArchState *env); +#ifdef CONFIG_HAX +void hax_cpu_synchronize_state(CPUArchState *env); +#endif /* generic hooks - to be moved/refactored once there are more users */ @@ -258,6 +261,9 @@ static inline void cpu_synchronize_state(CPUArchState *env) if (kvm_enabled()) { kvm_cpu_synchronize_state(env); } +#ifdef CONFIG_HAX + hax_cpu_synchronize_state(env); +#endif } #if !defined(CONFIG_USER_ONLY) @@ -269,12 +275,20 @@ int kvm_physical_memory_addr_from_host(KVMState *s, void *ram_addr, void kvm_cpu_synchronize_post_reset(CPUState *cpu); void kvm_cpu_synchronize_post_init(CPUState *cpu); +#ifdef CONFIG_HAX +void hax_cpu_synchronize_post_reset(CPUArchState *env); +void hax_cpu_synchronize_post_init(CPUArchState *env); +#endif static inline void cpu_synchronize_post_reset(CPUState *cpu) { if (kvm_enabled()) { kvm_cpu_synchronize_post_reset(cpu); } +#ifdef CONFIG_HAX + CPUArchState *env = cpu->env_ptr; + hax_cpu_synchronize_post_reset(env); +#endif } static inline void cpu_synchronize_post_init(CPUState *cpu) @@ -282,6 +296,10 @@ static inline void cpu_synchronize_post_init(CPUState *cpu) if (kvm_enabled()) { kvm_cpu_synchronize_post_init(cpu); } +#ifdef CONFIG_HAX + CPUArchState *env = cpu->env_ptr; + hax_cpu_synchronize_post_init(env); +#endif } int kvm_irqchip_add_msi_route(KVMState *s, MSIMessage msg); diff --git a/include/sysemu/sysemu.h b/include/sysemu/sysemu.h index 2fb71af..515d34c 100644 --- a/include/sysemu/sysemu.h +++ b/include/sysemu/sysemu.h @@ -92,6 +92,9 @@ typedef enum DisplayType DT_SDL, DT_GTK, DT_NOGRAPHIC, +#ifdef CONFIG_MARU + DT_MARU, +#endif DT_NONE, } DisplayType; @@ -99,11 +102,17 @@ extern int autostart; typedef enum { VGA_NONE, VGA_STD, VGA_CIRRUS, VGA_VMWARE, VGA_XENFB, VGA_QXL, +#ifdef CONFIG_MARU + VGA_MARU, +#endif } VGAInterfaceType; extern int vga_interface_type; #define xenfb_enabled (vga_interface_type == VGA_XENFB) #define qxl_enabled (vga_interface_type == VGA_QXL) +#ifdef CONFIG_MARU +#define maru_vga_enabled (vga_interface_type == VGA_MARU) +#endif extern int graphic_width; extern int graphic_height; @@ -146,6 +155,9 @@ extern const char *prom_envs[MAX_PROM_ENVS]; extern unsigned int nb_prom_envs; /* pci-hotplug */ +#ifdef CONFIG_MARU +PCIDevice *pci_device_hot_add(Monitor *mon, const QDict *qdict); +#endif void pci_device_hot_add(Monitor *mon, const QDict *qdict); int pci_drive_hot_add(Monitor *mon, const QDict *qdict, DriveInfo *dinfo); void do_pci_device_hot_remove(Monitor *mon, const QDict *qdict); diff --git a/include/ui/console.h b/include/ui/console.h index 4307b5f..cc3e391 100644 --- a/include/ui/console.h +++ b/include/ui/console.h @@ -49,6 +49,14 @@ void kbd_put_keycode(int keycode); void kbd_put_ledstate(int ledstate); void kbd_mouse_event(int dx, int dy, int dz, int buttons_state); +#ifdef CONFIG_MARU +QEMUPutKbdEntry *qemu_add_ps2kbd_event_handler(QEMUPutKBDEvent *func, + void *opaque); +void qemu_remove_ps2kbd_event_handler(QEMUPutKbdEntry *entry); +void ps2kbd_put_keycode(int keycode); +#endif + + /* Does the current mouse generate absolute events */ int kbd_mouse_is_absolute(void); void qemu_add_mouse_mode_change_notifier(Notifier *notify); diff --git a/input.c b/input.c deleted file mode 100644 index c46bbc1..0000000 --- a/input.c +++ /dev/null @@ -1,326 +0,0 @@ -/* - * QEMU System Emulator - * - * Copyright (c) 2003-2008 Fabrice Bellard - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - -#include "sysemu.h" -#include "net.h" -#include "monitor.h" -#include "console.h" -#include "error.h" -#include "qmp-commands.h" -#include "tizen/src/debug_ch.h" - -MULTI_DEBUG_CHANNEL(tizen, input); - -static QEMUPutKBDEvent *qemu_put_kbd_event; -static void *qemu_put_kbd_event_opaque; -#ifdef CONFIG_MARU -static QEMUPutKBDEvent *qemu_put_ps2kbd_event; -static void *qemu_put_ps2kbd_event_opaque; -#endif -static QTAILQ_HEAD(, QEMUPutLEDEntry) led_handlers = QTAILQ_HEAD_INITIALIZER(led_handlers); -static QTAILQ_HEAD(, QEMUPutMouseEntry) mouse_handlers = - QTAILQ_HEAD_INITIALIZER(mouse_handlers); -static NotifierList mouse_mode_notifiers = - NOTIFIER_LIST_INITIALIZER(mouse_mode_notifiers); - -void qemu_add_kbd_event_handler(QEMUPutKBDEvent *func, void *opaque) -{ - qemu_put_kbd_event_opaque = opaque; - qemu_put_kbd_event = func; -} - -void qemu_remove_kbd_event_handler(void) -{ - qemu_put_kbd_event_opaque = NULL; - qemu_put_kbd_event = NULL; -} - -#ifdef CONFIG_MARU -/* use ps2kbd device as a hardkey device. */ -void qemu_add_ps2kbd_event_handler(QEMUPutKBDEvent *func, void *opaque) -{ - qemu_put_ps2kbd_event_opaque = opaque; - qemu_put_ps2kbd_event = func; -} - -void qemu_remove_ps2kbd_event_handler(void) -{ - qemu_put_ps2kbd_event_opaque = NULL; - qemu_put_ps2kbd_event = NULL; -} - -void ps2kbd_put_keycode(int keycode) -{ - if (qemu_put_ps2kbd_event) { - qemu_put_ps2kbd_event(qemu_put_ps2kbd_event_opaque, keycode); - } -} -#endif - -static void check_mode_change(void) -{ - static int current_is_absolute, current_has_absolute; - int is_absolute; - int has_absolute; - - is_absolute = kbd_mouse_is_absolute(); - has_absolute = kbd_mouse_has_absolute(); - - if (is_absolute != current_is_absolute || - has_absolute != current_has_absolute) { - notifier_list_notify(&mouse_mode_notifiers, NULL); - } - - current_is_absolute = is_absolute; - current_has_absolute = has_absolute; -} - -QEMUPutMouseEntry *qemu_add_mouse_event_handler(QEMUPutMouseEvent *func, - void *opaque, int absolute, - const char *name) -{ - QEMUPutMouseEntry *s; - static int mouse_index = 0; - - s = g_malloc0(sizeof(QEMUPutMouseEntry)); - - s->qemu_put_mouse_event = func; - s->qemu_put_mouse_event_opaque = opaque; - s->qemu_put_mouse_event_absolute = absolute; - s->qemu_put_mouse_event_name = g_strdup(name); - s->index = mouse_index++; - - QTAILQ_INSERT_TAIL(&mouse_handlers, s, node); - - check_mode_change(); - - return s; -} - -void qemu_activate_mouse_event_handler(QEMUPutMouseEntry *entry) -{ - QTAILQ_REMOVE(&mouse_handlers, entry, node); - QTAILQ_INSERT_HEAD(&mouse_handlers, entry, node); - - check_mode_change(); -} - -void qemu_remove_mouse_event_handler(QEMUPutMouseEntry *entry) -{ - QTAILQ_REMOVE(&mouse_handlers, entry, node); - - g_free(entry->qemu_put_mouse_event_name); - g_free(entry); - - check_mode_change(); -} - -QEMUPutLEDEntry *qemu_add_led_event_handler(QEMUPutLEDEvent *func, - void *opaque) -{ - QEMUPutLEDEntry *s; - - s = g_malloc0(sizeof(QEMUPutLEDEntry)); - - s->put_led = func; - s->opaque = opaque; - QTAILQ_INSERT_TAIL(&led_handlers, s, next); - return s; -} - -void qemu_remove_led_event_handler(QEMUPutLEDEntry *entry) -{ - if (entry == NULL) - return; - QTAILQ_REMOVE(&led_handlers, entry, next); - g_free(entry); -} - -void kbd_put_keycode(int keycode) -{ - if (!runstate_is_running() && !runstate_check(RUN_STATE_SUSPENDED)) { - return; - } - if (qemu_put_kbd_event) { - qemu_put_kbd_event(qemu_put_kbd_event_opaque, keycode); - } -} - -void kbd_put_ledstate(int ledstate) -{ - QEMUPutLEDEntry *cursor; - - QTAILQ_FOREACH(cursor, &led_handlers, next) { - cursor->put_led(cursor->opaque, ledstate); - } -} - -void kbd_mouse_event(int dx, int dy, int dz, int buttons_state) -{ - QEMUPutMouseEntry *entry; - QEMUPutMouseEvent *mouse_event; - void *mouse_event_opaque; - int width, height; - - if (!runstate_is_running() && !runstate_check(RUN_STATE_SUSPENDED)) { - return; - } - if (QTAILQ_EMPTY(&mouse_handlers)) { - return; - } -#if defined (CONFIG_MARU) - QTAILQ_FOREACH(entry, &mouse_handlers, node) { - /* if mouse event is wheelup ,wheeldown or move - then go to ps2 mouse event(index == 0) */ - if((buttons_state > 3 && entry->index == 0)) { - //INFO("input device: %s, event: %d\n", entry->qemu_put_mouse_event_name, buttons_state); - buttons_state = 0; - mouse_event = entry->qemu_put_mouse_event; - mouse_event_opaque = entry->qemu_put_mouse_event_opaque; - break; - } - } - /* other events(mouse up, down and drag), go to touch screen */ - if(!entry) { - entry = QTAILQ_FIRST(&mouse_handlers); - mouse_event = entry->qemu_put_mouse_event; - mouse_event_opaque = entry->qemu_put_mouse_event_opaque; - //INFO("input device: %s, event: %d\n", entry->qemu_put_mouse_event_name, buttons_state); - } -#else - entry = QTAILQ_FIRST(&mouse_handlers); - - mouse_event = entry->qemu_put_mouse_event; - mouse_event_opaque = entry->qemu_put_mouse_event_opaque; -#endif - if (mouse_event) { - if (entry->qemu_put_mouse_event_absolute) { - width = 0x7fff; - height = 0x7fff; - } else { - width = graphic_width - 1; - height = graphic_height - 1; - } - - switch (graphic_rotate) { - case 0: - mouse_event(mouse_event_opaque, - dx, dy, dz, buttons_state); - break; - case 90: - mouse_event(mouse_event_opaque, - width - dy, dx, dz, buttons_state); - break; - case 180: - mouse_event(mouse_event_opaque, - width - dx, height - dy, dz, buttons_state); - break; - case 270: - mouse_event(mouse_event_opaque, - dy, height - dx, dz, buttons_state); - break; - } - } -} - -int kbd_mouse_is_absolute(void) -{ - if (QTAILQ_EMPTY(&mouse_handlers)) { - return 0; - } - - return QTAILQ_FIRST(&mouse_handlers)->qemu_put_mouse_event_absolute; -} - -int kbd_mouse_has_absolute(void) -{ - QEMUPutMouseEntry *entry; - - QTAILQ_FOREACH(entry, &mouse_handlers, node) { - if (entry->qemu_put_mouse_event_absolute) { - return 1; - } - } - - return 0; -} - -MouseInfoList *qmp_query_mice(Error **errp) -{ - MouseInfoList *mice_list = NULL; - QEMUPutMouseEntry *cursor; - bool current = true; - - QTAILQ_FOREACH(cursor, &mouse_handlers, node) { - MouseInfoList *info = g_malloc0(sizeof(*info)); - info->value = g_malloc0(sizeof(*info->value)); - info->value->name = g_strdup(cursor->qemu_put_mouse_event_name); - info->value->index = cursor->index; - info->value->absolute = !!cursor->qemu_put_mouse_event_absolute; - info->value->current = current; - - current = false; - - info->next = mice_list; - mice_list = info; - } - - return mice_list; -} - -void do_mouse_set(Monitor *mon, const QDict *qdict) -{ - QEMUPutMouseEntry *cursor; - int index = qdict_get_int(qdict, "index"); - int found = 0; - - if (QTAILQ_EMPTY(&mouse_handlers)) { - monitor_printf(mon, "No mouse devices connected\n"); - return; - } - - QTAILQ_FOREACH(cursor, &mouse_handlers, node) { - if (cursor->index == index) { - found = 1; - qemu_activate_mouse_event_handler(cursor); - break; - } - } - - if (!found) { - monitor_printf(mon, "Mouse at given index not found\n"); - } - - check_mode_change(); -} - -void qemu_add_mouse_mode_change_notifier(Notifier *notify) -{ - notifier_list_add(&mouse_mode_notifiers, notify); -} - -void qemu_remove_mouse_mode_change_notifier(Notifier *notify) -{ - notifier_remove(notify); -} diff --git a/kvm.h b/kvm.h deleted file mode 100644 index 086cd3b..0000000 --- a/kvm.h +++ /dev/null @@ -1,292 +0,0 @@ -/* - * QEMU KVM support - * - * Copyright IBM, Corp. 2008 - * - * Authors: - * Anthony Liguori - * - * This work is licensed under the terms of the GNU GPL, version 2 or later. - * See the COPYING file in the top-level directory. - * - */ - -#ifndef QEMU_KVM_H -#define QEMU_KVM_H - -#include -#include "config-host.h" -#include "qemu-queue.h" - -#ifdef CONFIG_KVM -#include -#endif - -extern int kvm_allowed; -extern bool kvm_kernel_irqchip; -extern bool kvm_async_interrupts_allowed; -extern bool kvm_irqfds_allowed; -extern bool kvm_msi_via_irqfd_allowed; -extern bool kvm_gsi_routing_allowed; - -#if defined CONFIG_KVM || !defined NEED_CPU_H -#define kvm_enabled() (kvm_allowed) -/** - * kvm_irqchip_in_kernel: - * - * Returns: true if the user asked us to create an in-kernel - * irqchip via the "kernel_irqchip=on" machine option. - * What this actually means is architecture and machine model - * specific: on PC, for instance, it means that the LAPIC, - * IOAPIC and PIT are all in kernel. This function should never - * be used from generic target-independent code: use one of the - * following functions or some other specific check instead. - */ -#define kvm_irqchip_in_kernel() (kvm_kernel_irqchip) - -/** - * kvm_async_interrupts_enabled: - * - * Returns: true if we can deliver interrupts to KVM - * asynchronously (ie by ioctl from any thread at any time) - * rather than having to do interrupt delivery synchronously - * (where the vcpu must be stopped at a suitable point first). - */ -#define kvm_async_interrupts_enabled() (kvm_async_interrupts_allowed) - -/** - * kvm_irqfds_enabled: - * - * Returns: true if we can use irqfds to inject interrupts into - * a KVM CPU (ie the kernel supports irqfds and we are running - * with a configuration where it is meaningful to use them). - */ -#define kvm_irqfds_enabled() (kvm_irqfds_allowed) - -/** - * kvm_msi_via_irqfd_enabled: - * - * Returns: true if we can route a PCI MSI (Message Signaled Interrupt) - * to a KVM CPU via an irqfd. This requires that the kernel supports - * this and that we're running in a configuration that permits it. - */ -#define kvm_msi_via_irqfd_enabled() (kvm_msi_via_irqfd_allowed) - -/** - * kvm_gsi_routing_enabled: - * - * Returns: true if GSI routing is enabled (ie the kernel supports - * it and we're running in a configuration that permits it). - */ -#define kvm_gsi_routing_enabled() (kvm_gsi_routing_allowed) - -#else -#define kvm_enabled() (0) -#define kvm_irqchip_in_kernel() (false) -#define kvm_async_interrupts_enabled() (false) -#define kvm_irqfds_enabled() (false) -#define kvm_msi_via_irqfd_enabled() (false) -#define kvm_gsi_routing_allowed() (false) -#endif - -struct kvm_run; -struct kvm_lapic_state; - -typedef struct KVMCapabilityInfo { - const char *name; - int value; -} KVMCapabilityInfo; - -#define KVM_CAP_INFO(CAP) { "KVM_CAP_" stringify(CAP), KVM_CAP_##CAP } -#define KVM_CAP_LAST_INFO { NULL, 0 } - -struct KVMState; -typedef struct KVMState KVMState; -extern KVMState *kvm_state; - -/* external API */ - -int kvm_init(void); - -int kvm_has_sync_mmu(void); -int kvm_has_vcpu_events(void); -int kvm_has_robust_singlestep(void); -int kvm_has_debugregs(void); -int kvm_has_xsave(void); -int kvm_has_xcrs(void); -int kvm_has_pit_state2(void); -int kvm_has_many_ioeventfds(void); -int kvm_has_gsi_routing(void); - -#ifdef NEED_CPU_H -int kvm_init_vcpu(CPUArchState *env); - -int kvm_cpu_exec(CPUArchState *env); - -#if !defined(CONFIG_USER_ONLY) -void *kvm_vmalloc(ram_addr_t size); -void *kvm_arch_vmalloc(ram_addr_t size); -void kvm_setup_guest_memory(void *start, size_t size); - -int kvm_coalesce_mmio_region(target_phys_addr_t start, ram_addr_t size); -int kvm_uncoalesce_mmio_region(target_phys_addr_t start, ram_addr_t size); -void kvm_flush_coalesced_mmio_buffer(void); -#endif - -int kvm_insert_breakpoint(CPUArchState *current_env, target_ulong addr, - target_ulong len, int type); -int kvm_remove_breakpoint(CPUArchState *current_env, target_ulong addr, - target_ulong len, int type); -void kvm_remove_all_breakpoints(CPUArchState *current_env); -int kvm_update_guest_debug(CPUArchState *env, unsigned long reinject_trap); -#ifndef _WIN32 -int kvm_set_signal_mask(CPUArchState *env, const sigset_t *sigset); -#endif - -int kvm_on_sigbus_vcpu(CPUArchState *env, int code, void *addr); -int kvm_on_sigbus(int code, void *addr); - -/* internal API */ - -int kvm_ioctl(KVMState *s, int type, ...); - -int kvm_vm_ioctl(KVMState *s, int type, ...); - -int kvm_vcpu_ioctl(CPUArchState *env, int type, ...); - -/* Arch specific hooks */ - -extern const KVMCapabilityInfo kvm_arch_required_capabilities[]; - -void kvm_arch_pre_run(CPUArchState *env, struct kvm_run *run); -void kvm_arch_post_run(CPUArchState *env, struct kvm_run *run); - -int kvm_arch_handle_exit(CPUArchState *env, struct kvm_run *run); - -int kvm_arch_process_async_events(CPUArchState *env); - -int kvm_arch_get_registers(CPUArchState *env); - -/* state subset only touched by the VCPU itself during runtime */ -#define KVM_PUT_RUNTIME_STATE 1 -/* state subset modified during VCPU reset */ -#define KVM_PUT_RESET_STATE 2 -/* full state set, modified during initialization or on vmload */ -#define KVM_PUT_FULL_STATE 3 - -int kvm_arch_put_registers(CPUArchState *env, int level); - -int kvm_arch_init(KVMState *s); - -int kvm_arch_init_vcpu(CPUArchState *env); - -void kvm_arch_reset_vcpu(CPUArchState *env); - -int kvm_arch_on_sigbus_vcpu(CPUArchState *env, int code, void *addr); -int kvm_arch_on_sigbus(int code, void *addr); - -void kvm_arch_init_irq_routing(KVMState *s); - -int kvm_set_irq(KVMState *s, int irq, int level); -int kvm_irqchip_send_msi(KVMState *s, MSIMessage msg); - -void kvm_irqchip_add_irq_route(KVMState *s, int gsi, int irqchip, int pin); - -void kvm_put_apic_state(DeviceState *d, struct kvm_lapic_state *kapic); -void kvm_get_apic_state(DeviceState *d, struct kvm_lapic_state *kapic); - -struct kvm_guest_debug; -struct kvm_debug_exit_arch; - -struct kvm_sw_breakpoint { - target_ulong pc; - target_ulong saved_insn; - int use_count; - QTAILQ_ENTRY(kvm_sw_breakpoint) entry; -}; - -QTAILQ_HEAD(kvm_sw_breakpoint_head, kvm_sw_breakpoint); - -struct kvm_sw_breakpoint *kvm_find_sw_breakpoint(CPUArchState *env, - target_ulong pc); - -int kvm_sw_breakpoints_active(CPUArchState *env); - -int kvm_arch_insert_sw_breakpoint(CPUArchState *current_env, - struct kvm_sw_breakpoint *bp); -int kvm_arch_remove_sw_breakpoint(CPUArchState *current_env, - struct kvm_sw_breakpoint *bp); -int kvm_arch_insert_hw_breakpoint(target_ulong addr, - target_ulong len, int type); -int kvm_arch_remove_hw_breakpoint(target_ulong addr, - target_ulong len, int type); -void kvm_arch_remove_all_hw_breakpoints(void); - -void kvm_arch_update_guest_debug(CPUArchState *env, struct kvm_guest_debug *dbg); - -bool kvm_arch_stop_on_emulation_error(CPUArchState *env); - -int kvm_check_extension(KVMState *s, unsigned int extension); - -uint32_t kvm_arch_get_supported_cpuid(KVMState *env, uint32_t function, - uint32_t index, int reg); -void kvm_cpu_synchronize_state(CPUArchState *env); -void kvm_cpu_synchronize_post_reset(CPUArchState *env); -void kvm_cpu_synchronize_post_init(CPUArchState *env); - -/* generic hooks - to be moved/refactored once there are more users */ -#ifdef CONFIG_HAX -void hax_cpu_synchronize_state(CPUArchState *env); -void hax_cpu_synchronize_post_reset(CPUArchState *env); -void hax_cpu_synchronize_post_init(CPUArchState *env); -#endif -static inline void cpu_synchronize_state(CPUArchState *env) -{ - if (kvm_enabled()) { - kvm_cpu_synchronize_state(env); - } -#ifdef CONFIG_HAX - hax_cpu_synchronize_state(env); -#endif -} - -static inline void cpu_synchronize_post_reset(CPUArchState *env) -{ - if (kvm_enabled()) { - kvm_cpu_synchronize_post_reset(env); - } -#ifdef CONFIG_HAX - hax_cpu_synchronize_post_reset(env); -#endif -} - -static inline void cpu_synchronize_post_init(CPUArchState *env) -{ - if (kvm_enabled()) { - kvm_cpu_synchronize_post_init(env); - } -#ifdef CONFIG_HAX - hax_cpu_synchronize_post_init(env); -#endif -} - - -#if !defined(CONFIG_USER_ONLY) -int kvm_physical_memory_addr_from_host(KVMState *s, void *ram_addr, - target_phys_addr_t *phys_addr); -#endif - -#endif -int kvm_set_ioeventfd_mmio(int fd, uint32_t adr, uint32_t val, bool assign, - uint32_t size); - -int kvm_set_ioeventfd_pio_word(int fd, uint16_t adr, uint16_t val, bool assign); - -int kvm_irqchip_add_msi_route(KVMState *s, MSIMessage msg); -void kvm_irqchip_release_virq(KVMState *s, int virq); - -int kvm_irqchip_add_irqfd(KVMState *s, int fd, int virq); -int kvm_irqchip_remove_irqfd(KVMState *s, int fd, int virq); -int kvm_irqchip_add_irq_notifier(KVMState *s, EventNotifier *n, int virq); -int kvm_irqchip_remove_irq_notifier(KVMState *s, EventNotifier *n, int virq); -#endif diff --git a/main-loop.h b/main-loop.h deleted file mode 100644 index e875785..0000000 --- a/main-loop.h +++ /dev/null @@ -1,376 +0,0 @@ -/* - * QEMU System Emulator - * - * Copyright (c) 2003-2008 Fabrice Bellard - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - -#ifndef QEMU_MAIN_LOOP_H -#define QEMU_MAIN_LOOP_H 1 - -#define SIG_IPI SIGUSR1 - -/** - * qemu_init_main_loop: Set up the process so that it can run the main loop. - * - * This includes setting up signal handlers. It should be called before - * any other threads are created. In addition, threads other than the - * main one should block signals that are trapped by the main loop. - * For simplicity, you can consider these signals to be safe: SIGUSR1, - * SIGUSR2, thread signals (SIGFPE, SIGILL, SIGSEGV, SIGBUS) and real-time - * signals if available. Remember that Windows in practice does not have - * signals, though. - * - * In the case of QEMU tools, this will also start/initialize timers. - */ -int qemu_init_main_loop(void); - -/** - * main_loop_init: Initializes main loop - * - * Internal (but shared for compatibility reasons) initialization routine - * for the main loop. This should not be used by applications directly, - * use qemu_init_main_loop() instead. - * - */ -int main_loop_init(void); - -/** - * main_loop_wait: Run one iteration of the main loop. - * - * If @nonblocking is true, poll for events, otherwise suspend until - * one actually occurs. The main loop usually consists of a loop that - * repeatedly calls main_loop_wait(false). - * - * Main loop services include file descriptor callbacks, bottom halves - * and timers (defined in qemu-timer.h). Bottom halves are similar to timers - * that execute immediately, but have a lower overhead and scheduling them - * is wait-free, thread-safe and signal-safe. - * - * It is sometimes useful to put a whole program in a coroutine. In this - * case, the coroutine actually should be started from within the main loop, - * so that the main loop can run whenever the coroutine yields. To do this, - * you can use a bottom half to enter the coroutine as soon as the main loop - * starts: - * - * void enter_co_bh(void *opaque) { - * QEMUCoroutine *co = opaque; - * qemu_coroutine_enter(co, NULL); - * } - * - * ... - * QEMUCoroutine *co = qemu_coroutine_create(coroutine_entry); - * QEMUBH *start_bh = qemu_bh_new(enter_co_bh, co); - * qemu_bh_schedule(start_bh); - * while (...) { - * main_loop_wait(false); - * } - * - * (In the future we may provide a wrapper for this). - * - * @nonblocking: Whether the caller should block until an event occurs. - */ -int main_loop_wait(int nonblocking); - -/** - * qemu_notify_event: Force processing of pending events. - * - * Similar to signaling a condition variable, qemu_notify_event forces - * main_loop_wait to look at pending events and exit. The caller of - * main_loop_wait will usually call it again very soon, so qemu_notify_event - * also has the side effect of recalculating the sets of file descriptors - * that the main loop waits for. - * - * Calling qemu_notify_event is rarely necessary, because main loop - * services (bottom halves and timers) call it themselves. One notable - * exception occurs when using qemu_set_fd_handler2 (see below). - */ -void qemu_notify_event(void); - -// TODO: Mark HAX related code... -#ifdef CONFIG_HAX_BACKEND -void qemu_notify_hax_event(void); -#else -static inline void qemu_notify_hax_event(void) -{ -} -#endif -// - -#ifdef _WIN32 -/* return TRUE if no sleep should be done afterwards */ -typedef int PollingFunc(void *opaque); - -/** - * qemu_add_polling_cb: Register a Windows-specific polling callback - * - * Currently, under Windows some events are polled rather than waited for. - * Polling callbacks do not ensure that @func is called timely, because - * the main loop might wait for an arbitrarily long time. If possible, - * you should instead create a separate thread that does a blocking poll - * and set a Win32 event object. The event can then be passed to - * qemu_add_wait_object. - * - * Polling callbacks really have nothing Windows specific in them, but - * as they are a hack and are currently not necessary under POSIX systems, - * they are only available when QEMU is running under Windows. - * - * @func: The function that does the polling, and returns 1 to force - * immediate completion of main_loop_wait. - * @opaque: A pointer-size value that is passed to @func. - */ -int qemu_add_polling_cb(PollingFunc *func, void *opaque); - -/** - * qemu_del_polling_cb: Unregister a Windows-specific polling callback - * - * This function removes a callback that was registered with - * qemu_add_polling_cb. - * - * @func: The function that was passed to qemu_add_polling_cb. - * @opaque: A pointer-size value that was passed to qemu_add_polling_cb. - */ -void qemu_del_polling_cb(PollingFunc *func, void *opaque); - -/* Wait objects handling */ -typedef void WaitObjectFunc(void *opaque); - -/** - * qemu_add_wait_object: Register a callback for a Windows handle - * - * Under Windows, the iohandler mechanism can only be used with sockets. - * QEMU must use the WaitForMultipleObjects API to wait on other handles. - * This function registers a #HANDLE with QEMU, so that it will be included - * in the main loop's calls to WaitForMultipleObjects. When the handle - * is in a signaled state, QEMU will call @func. - * - * @handle: The Windows handle to be observed. - * @func: A function to be called when @handle is in a signaled state. - * @opaque: A pointer-size value that is passed to @func. - */ -int qemu_add_wait_object(HANDLE handle, WaitObjectFunc *func, void *opaque); - -/** - * qemu_del_wait_object: Unregister a callback for a Windows handle - * - * This function removes a callback that was registered with - * qemu_add_wait_object. - * - * @func: The function that was passed to qemu_add_wait_object. - * @opaque: A pointer-size value that was passed to qemu_add_wait_object. - */ -void qemu_del_wait_object(HANDLE handle, WaitObjectFunc *func, void *opaque); -#endif - -/* async I/O support */ - -typedef void IOReadHandler(void *opaque, const uint8_t *buf, int size); -typedef int IOCanReadHandler(void *opaque); -typedef void IOHandler(void *opaque); - -/** - * qemu_set_fd_handler2: Register a file descriptor with the main loop - * - * This function tells the main loop to wake up whenever one of the - * following conditions is true: - * - * 1) if @fd_write is not %NULL, when the file descriptor is writable; - * - * 2) if @fd_read is not %NULL, when the file descriptor is readable. - * - * @fd_read_poll can be used to disable the @fd_read callback temporarily. - * This is useful to avoid calling qemu_set_fd_handler2 every time the - * client becomes interested in reading (or dually, stops being interested). - * A typical example is when @fd is a listening socket and you want to bound - * the number of active clients. Remember to call qemu_notify_event whenever - * the condition may change from %false to %true. - * - * The callbacks that are set up by qemu_set_fd_handler2 are level-triggered. - * If @fd_read does not read from @fd, or @fd_write does not write to @fd - * until its buffers are full, they will be called again on the next - * iteration. - * - * @fd: The file descriptor to be observed. Under Windows it must be - * a #SOCKET. - * - * @fd_read_poll: A function that returns 1 if the @fd_read callback - * should be fired. If the function returns 0, the main loop will not - * end its iteration even if @fd becomes readable. - * - * @fd_read: A level-triggered callback that is fired if @fd is readable - * at the beginning of a main loop iteration, or if it becomes readable - * during one. - * - * @fd_write: A level-triggered callback that is fired when @fd is writable - * at the beginning of a main loop iteration, or if it becomes writable - * during one. - * - * @opaque: A pointer-sized value that is passed to @fd_read_poll, - * @fd_read and @fd_write. - */ -int qemu_set_fd_handler2(int fd, - IOCanReadHandler *fd_read_poll, - IOHandler *fd_read, - IOHandler *fd_write, - void *opaque); - -/** - * qemu_set_fd_handler: Register a file descriptor with the main loop - * - * This function tells the main loop to wake up whenever one of the - * following conditions is true: - * - * 1) if @fd_write is not %NULL, when the file descriptor is writable; - * - * 2) if @fd_read is not %NULL, when the file descriptor is readable. - * - * The callbacks that are set up by qemu_set_fd_handler are level-triggered. - * If @fd_read does not read from @fd, or @fd_write does not write to @fd - * until its buffers are full, they will be called again on the next - * iteration. - * - * @fd: The file descriptor to be observed. Under Windows it must be - * a #SOCKET. - * - * @fd_read: A level-triggered callback that is fired if @fd is readable - * at the beginning of a main loop iteration, or if it becomes readable - * during one. - * - * @fd_write: A level-triggered callback that is fired when @fd is writable - * at the beginning of a main loop iteration, or if it becomes writable - * during one. - * - * @opaque: A pointer-sized value that is passed to @fd_read and @fd_write. - */ -int qemu_set_fd_handler(int fd, - IOHandler *fd_read, - IOHandler *fd_write, - void *opaque); - -typedef struct QEMUBH QEMUBH; -typedef void QEMUBHFunc(void *opaque); - -/** - * qemu_bh_new: Allocate a new bottom half structure. - * - * Bottom halves are lightweight callbacks whose invocation is guaranteed - * to be wait-free, thread-safe and signal-safe. The #QEMUBH structure - * is opaque and must be allocated prior to its use. - */ -QEMUBH *qemu_bh_new(QEMUBHFunc *cb, void *opaque); - -/** - * qemu_bh_schedule: Schedule a bottom half. - * - * Scheduling a bottom half interrupts the main loop and causes the - * execution of the callback that was passed to qemu_bh_new. - * - * Bottom halves that are scheduled from a bottom half handler are instantly - * invoked. This can create an infinite loop if a bottom half handler - * schedules itself. - * - * @bh: The bottom half to be scheduled. - */ -void qemu_bh_schedule(QEMUBH *bh); - -/** - * qemu_bh_cancel: Cancel execution of a bottom half. - * - * Canceling execution of a bottom half undoes the effect of calls to - * qemu_bh_schedule without freeing its resources yet. While cancellation - * itself is also wait-free and thread-safe, it can of course race with the - * loop that executes bottom halves unless you are holding the iothread - * mutex. This makes it mostly useless if you are not holding the mutex. - * - * @bh: The bottom half to be canceled. - */ -void qemu_bh_cancel(QEMUBH *bh); - -/** - *qemu_bh_delete: Cancel execution of a bottom half and free its resources. - * - * Deleting a bottom half frees the memory that was allocated for it by - * qemu_bh_new. It also implies canceling the bottom half if it was - * scheduled. - * - * @bh: The bottom half to be deleted. - */ -void qemu_bh_delete(QEMUBH *bh); - -#ifdef CONFIG_POSIX -/** - * qemu_add_child_watch: Register a child process for reaping. - * - * Under POSIX systems, a parent process must read the exit status of - * its child processes using waitpid, or the operating system will not - * free some of the resources attached to that process. - * - * This function directs the QEMU main loop to observe a child process - * and call waitpid as soon as it exits; the watch is then removed - * automatically. It is useful whenever QEMU forks a child process - * but will find out about its termination by other means such as a - * "broken pipe". - * - * @pid: The pid that QEMU should observe. - */ -int qemu_add_child_watch(pid_t pid); -#endif - -/** - * qemu_mutex_lock_iothread: Lock the main loop mutex. - * - * This function locks the main loop mutex. The mutex is taken by - * qemu_init_main_loop and always taken except while waiting on - * external events (such as with select). The mutex should be taken - * by threads other than the main loop thread when calling - * qemu_bh_new(), qemu_set_fd_handler() and basically all other - * functions documented in this file. - * - * NOTE: tools currently are single-threaded and qemu_mutex_lock_iothread - * is a no-op there. - */ -void qemu_mutex_lock_iothread(void); - -/** - * qemu_mutex_unlock_iothread: Unlock the main loop mutex. - * - * This function unlocks the main loop mutex. The mutex is taken by - * qemu_init_main_loop and always taken except while waiting on - * external events (such as with select). The mutex should be unlocked - * as soon as possible by threads other than the main loop thread, - * because it prevents the main loop from processing callbacks, - * including timers and bottom halves. - * - * NOTE: tools currently are single-threaded and qemu_mutex_unlock_iothread - * is a no-op there. - */ -void qemu_mutex_unlock_iothread(void); - -/* internal interfaces */ - -void qemu_fd_register(int fd); -void qemu_iohandler_fill(int *pnfds, fd_set *readfds, fd_set *writefds, fd_set *xfds); -void qemu_iohandler_poll(fd_set *readfds, fd_set *writefds, fd_set *xfds, int rc); - -void qemu_bh_schedule_idle(QEMUBH *bh); -int qemu_bh_poll(void); -void qemu_bh_update_timeout(uint32_t *timeout); - -#endif diff --git a/oslib-posix.c b/oslib-posix.c deleted file mode 100644 index 24b9207..0000000 --- a/oslib-posix.c +++ /dev/null @@ -1,282 +0,0 @@ -/* - * os-posix-lib.c - * - * Copyright (c) 2003-2008 Fabrice Bellard - * Copyright (c) 2010 Red Hat, Inc. - * - * QEMU library functions on POSIX which are shared between QEMU and - * the QEMU tools. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - -/* The following block of code temporarily renames the daemon() function so the - compiler does not see the warning associated with it in stdlib.h on OSX */ -#ifdef __APPLE__ -#define daemon qemu_fake_daemon_function -#include -#undef daemon -extern int daemon(int, int); -#endif - -#if defined(__linux__) && defined(__x86_64__) - /* Use 2 MiB alignment so transparent hugepages can be used by KVM. - Valgrind does not support alignments larger than 1 MiB, - therefore we need special code which handles running on Valgrind. */ -# define QEMU_VMALLOC_ALIGN (512 * 4096) -# define CONFIG_VALGRIND -#elif defined(__linux__) && defined(__s390x__) - /* Use 1 MiB (segment size) alignment so gmap can be used by KVM. */ -# define QEMU_VMALLOC_ALIGN (256 * 4096) -#else -# define QEMU_VMALLOC_ALIGN getpagesize() -#endif - -#include "config-host.h" -#include "sysemu.h" -#include "trace.h" -#include "qemu_socket.h" - - -#ifdef CONFIG_MARU -#include "../tizen/src/skin/maruskin_client.h" -#endif - -#if defined(CONFIG_VALGRIND) -static int running_on_valgrind = -1; -#else -# define running_on_valgrind 0 -#endif -#ifdef CONFIG_LINUX -#include -#endif -#ifdef CONFIG_EVENTFD -#include -#endif - -int qemu_get_thread_id(void) -{ -#if defined(__linux__) - return syscall(SYS_gettid); -#else - return getpid(); -#endif -} - -int qemu_daemon(int nochdir, int noclose) -{ - return daemon(nochdir, noclose); -} - -void *qemu_oom_check(void *ptr) -{ - if (ptr == NULL) { - fprintf(stderr, "Failed to allocate memory: %s\n", strerror(errno)); - -#ifdef CONFIG_MARU - char _msg[] = "Failed to allocate memory in qemu."; - char cmd[JAVA_MAX_COMMAND_LENGTH] = { 0, }; - - int len = strlen(JAVA_EXEFILE_PATH) + strlen(JAVA_EXEOPTION) + strlen(JAR_SKINFILE) + - strlen(JAVA_SIMPLEMODE_OPTION) + strlen(_msg) + 7; - if (len > JAVA_MAX_COMMAND_LENGTH) { - len = JAVA_MAX_COMMAND_LENGTH; - } - - snprintf(cmd, len, "%s %s %s %s=\"%s\"", - JAVA_EXEFILE_PATH, JAVA_EXEOPTION, JAR_SKINFILE, JAVA_SIMPLEMODE_OPTION, _msg); - if(system(cmd) == -1) { - // TODO: Handle error... - } -#endif - - abort(); - } - return ptr; -} - -void *qemu_memalign(size_t alignment, size_t size) -{ - void *ptr; -#if defined(_POSIX_C_SOURCE) && !defined(__sun__) - int ret; - ret = posix_memalign(&ptr, alignment, size); - if (ret != 0) { - fprintf(stderr, "Failed to allocate %zu B: %s\n", - size, strerror(ret)); - abort(); - } -#elif defined(CONFIG_BSD) - ptr = qemu_oom_check(valloc(size)); -#else - ptr = qemu_oom_check(memalign(alignment, size)); -#endif - trace_qemu_memalign(alignment, size, ptr); - return ptr; -} - -/* conflicts with qemu_vmalloc in bsd-user/mmap.c */ -#if !defined(CONFIG_BSD_USER) -/* alloc shared memory pages */ -void *qemu_vmalloc(size_t size) -{ - void *ptr; - size_t align = QEMU_VMALLOC_ALIGN; - -#if defined(CONFIG_VALGRIND) - if (running_on_valgrind < 0) { - /* First call, test whether we are running on Valgrind. - This is a substitute for RUNNING_ON_VALGRIND from valgrind.h. */ - const char *ld = getenv("LD_PRELOAD"); - running_on_valgrind = (ld != NULL && strstr(ld, "vgpreload")); - } -#endif - - if (size < align || running_on_valgrind) { - align = getpagesize(); - } - ptr = qemu_memalign(align, size); - trace_qemu_vmalloc(size, ptr); - return ptr; -} -#endif - -void qemu_vfree(void *ptr) -{ - trace_qemu_vfree(ptr); - free(ptr); -} - -void socket_set_block(int fd) -{ - int f; - f = fcntl(fd, F_GETFL); - fcntl(fd, F_SETFL, f & ~O_NONBLOCK); -} - -void socket_set_nonblock(int fd) -{ - int f; - f = fcntl(fd, F_GETFL); - fcntl(fd, F_SETFL, f | O_NONBLOCK); -} - -void qemu_set_cloexec(int fd) -{ - int f; - f = fcntl(fd, F_GETFD); - fcntl(fd, F_SETFD, f | FD_CLOEXEC); -} - -/* - * Creates a pipe with FD_CLOEXEC set on both file descriptors - */ -int qemu_pipe(int pipefd[2]) -{ - int ret; - -#ifdef CONFIG_PIPE2 - ret = pipe2(pipefd, O_CLOEXEC); - if (ret != -1 || errno != ENOSYS) { - return ret; - } -#endif - ret = pipe(pipefd); - if (ret == 0) { - qemu_set_cloexec(pipefd[0]); - qemu_set_cloexec(pipefd[1]); - } - - return ret; -} - -/* - * Creates an eventfd that looks like a pipe and has EFD_CLOEXEC set. - */ -int qemu_eventfd(int fds[2]) -{ -#ifdef CONFIG_EVENTFD - int ret; - - ret = eventfd(0, 0); - if (ret >= 0) { - fds[0] = ret; - fds[1] = dup(ret); - if (fds[1] == -1) { - close(ret); - return -1; - } - qemu_set_cloexec(ret); - qemu_set_cloexec(fds[1]); - return 0; - } - if (errno != ENOSYS) { - return -1; - } -#endif - - return qemu_pipe(fds); -} - -int qemu_utimens(const char *path, const struct timespec *times) -{ - struct timeval tv[2], tv_now; - struct stat st; - int i; -#ifdef CONFIG_UTIMENSAT - int ret; - - ret = utimensat(AT_FDCWD, path, times, AT_SYMLINK_NOFOLLOW); - if (ret != -1 || errno != ENOSYS) { - return ret; - } -#endif - /* Fallback: use utimes() instead of utimensat() */ - - /* happy if special cases */ - if (times[0].tv_nsec == UTIME_OMIT && times[1].tv_nsec == UTIME_OMIT) { - return 0; - } - if (times[0].tv_nsec == UTIME_NOW && times[1].tv_nsec == UTIME_NOW) { - return utimes(path, NULL); - } - - /* prepare for hard cases */ - if (times[0].tv_nsec == UTIME_NOW || times[1].tv_nsec == UTIME_NOW) { - gettimeofday(&tv_now, NULL); - } - if (times[0].tv_nsec == UTIME_OMIT || times[1].tv_nsec == UTIME_OMIT) { - stat(path, &st); - } - - for (i = 0; i < 2; i++) { - if (times[i].tv_nsec == UTIME_NOW) { - tv[i].tv_sec = tv_now.tv_sec; - tv[i].tv_usec = tv_now.tv_usec; - } else if (times[i].tv_nsec == UTIME_OMIT) { - tv[i].tv_sec = (i == 0) ? st.st_atime : st.st_mtime; - tv[i].tv_usec = 0; - } else { - tv[i].tv_sec = times[i].tv_sec; - tv[i].tv_usec = times[i].tv_nsec / 1000; - } - } - - return utimes(path, &tv[0]); -} diff --git a/oslib-win32.c b/oslib-win32.c deleted file mode 100644 index dc7adba..0000000 --- a/oslib-win32.c +++ /dev/null @@ -1,230 +0,0 @@ -/* - * os-win32.c - * - * Copyright (c) 2003-2008 Fabrice Bellard - * Copyright (c) 2010 Red Hat, Inc. - * - * QEMU library functions for win32 which are shared between QEMU and - * the QEMU tools. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -#include -#include "config-host.h" -#include "sysemu.h" -#include "main-loop.h" -#include "trace.h" -#include "qemu_socket.h" - -#ifdef CONFIG_MARU -#include "../tizen/src/skin/maruskin_client.h" - -#ifdef CONFIG_WIN32 -typedef BOOL (WINAPI *LPFN_ISWOW64PROCESS) (HANDLE, PBOOL); -LPFN_ISWOW64PROCESS fnIsWow64Process; - -int is_wow64_temp(void) -{ - int result = 0; - - //IsWow64Process is not available on all supported versions of Windows. - //Use GetModuleHandle to get a handle to the DLL that contains the function - //and GetProcAddress to get a pointer to the function if available. - - fnIsWow64Process = (LPFN_ISWOW64PROCESS) GetProcAddress( - GetModuleHandle(TEXT("kernel32")),"IsWow64Process"); - - if(NULL != fnIsWow64Process) - { - if (!fnIsWow64Process(GetCurrentProcess(),&result)) - { - //handle error - //INFO("Can not find 'IsWow64Process'\n"); - } - } - return result; -} - -int get_java_path_temp(char** java_path) -{ - HKEY hKeyNew; - HKEY hKey; - //char strJavaRuntimePath[JAVA_MAX_COMMAND_LENGTH] = {0}; - char strChoosenName[JAVA_MAX_COMMAND_LENGTH] = {0}; - char strSubKeyName[JAVA_MAX_COMMAND_LENGTH] = {0}; - char strJavaHome[JAVA_MAX_COMMAND_LENGTH] = {0}; - int index; - DWORD dwSubKeyNameMax = JAVA_MAX_COMMAND_LENGTH; - DWORD dwBufLen = JAVA_MAX_COMMAND_LENGTH; - - RegOpenKeyEx(HKEY_LOCAL_MACHINE, "SOFTWARE\\JavaSoft\\Java Runtime Environment", 0, - KEY_QUERY_VALUE | KEY_ENUMERATE_SUB_KEYS | MY_KEY_WOW64_64KEY, &hKey); - RegEnumKeyEx(hKey, 0, (LPSTR)strSubKeyName, &dwSubKeyNameMax, NULL, NULL, NULL, NULL); - strcpy(strChoosenName, strSubKeyName); - - index = 1; - while (ERROR_SUCCESS == RegEnumKeyEx(hKey, index, (LPSTR)strSubKeyName, &dwSubKeyNameMax, - NULL, NULL, NULL, NULL)) { - if (strcmp(strChoosenName, strSubKeyName) < 0) { - strcpy(strChoosenName, strSubKeyName); - } - index++; - } - - RegOpenKeyEx(hKey, strChoosenName, 0, KEY_QUERY_VALUE | MY_KEY_WOW64_64KEY, &hKeyNew); - RegQueryValueEx(hKeyNew, "JavaHome", NULL, NULL, (LPBYTE)strJavaHome, &dwBufLen); - RegCloseKey(hKey); - if (strJavaHome[0] != '\0') { - sprintf(*java_path, "\"%s\\bin\\java\"", strJavaHome); - //strcpy(*java_path, strJavaHome); - //strcat(*java_path, "\\bin\\java"); - } else { - return 0; - } - return 1; -} -#endif -#endif // CONFIG_MARU - -void *qemu_oom_check(void *ptr) -{ - if (ptr == NULL) { - fprintf(stderr, "Failed to allocate memory: %lu\n", GetLastError()); - -#ifdef CONFIG_MARU - char _msg[] = "Failed to allocate memory in qemu."; - char cmd[JAVA_MAX_COMMAND_LENGTH] = { 0, }; - -#ifdef CONFIG_WIN32 - char* JAVA_EXEFILE_PATH = malloc(JAVA_MAX_COMMAND_LENGTH); - memset(JAVA_EXEFILE_PATH, 0, JAVA_MAX_COMMAND_LENGTH); - if (is_wow64_temp()) { - if (!get_java_path_temp(&JAVA_EXEFILE_PATH)) { - strcpy(JAVA_EXEFILE_PATH, "java"); - } - } else { - strcpy(JAVA_EXEFILE_PATH, "java"); - } -#endif - int len = strlen(JAVA_EXEFILE_PATH) + strlen(JAVA_EXEOPTION) + strlen(JAR_SKINFILE) + - strlen(JAVA_SIMPLEMODE_OPTION) + strlen(_msg) + 7; - if (len > JAVA_MAX_COMMAND_LENGTH) { - len = JAVA_MAX_COMMAND_LENGTH; - } - - snprintf(cmd, len, "%s %s %s %s=\"%s\"", - JAVA_EXEFILE_PATH, JAVA_EXEOPTION, JAR_SKINFILE, JAVA_SIMPLEMODE_OPTION, _msg); - int ret = WinExec(cmd, SW_SHOW); -#ifdef CONFIG_WIN32 - // for 64bit windows - free(JAVA_EXEFILE_PATH); - JAVA_EXEFILE_PATH=0; -#endif -#endif - - abort(); - } - return ptr; -} - -void *qemu_memalign(size_t alignment, size_t size) -{ - void *ptr; - - if (!size) { - abort(); - } - ptr = qemu_oom_check(VirtualAlloc(NULL, size, MEM_COMMIT, PAGE_READWRITE)); - trace_qemu_memalign(alignment, size, ptr); - return ptr; -} - -void *qemu_vmalloc(size_t size) -{ - void *ptr; - - /* FIXME: this is not exactly optimal solution since VirtualAlloc - has 64Kb granularity, but at least it guarantees us that the - memory is page aligned. */ - if (!size) { - abort(); - } - ptr = qemu_oom_check(VirtualAlloc(NULL, size, MEM_COMMIT, PAGE_READWRITE)); - trace_qemu_vmalloc(size, ptr); - return ptr; -} - -void qemu_vfree(void *ptr) -{ - trace_qemu_vfree(ptr); - VirtualFree(ptr, 0, MEM_RELEASE); -} - -void socket_set_block(int fd) -{ - unsigned long opt = 0; - WSAEventSelect(fd, NULL, 0); - ioctlsocket(fd, FIONBIO, &opt); -} - -void socket_set_nonblock(int fd) -{ - unsigned long opt = 1; - ioctlsocket(fd, FIONBIO, &opt); - qemu_fd_register(fd); -} - -int inet_aton(const char *cp, struct in_addr *ia) -{ - uint32_t addr = inet_addr(cp); - if (addr == 0xffffffff) { - return 0; - } - ia->s_addr = addr; - return 1; -} - -void qemu_set_cloexec(int fd) -{ -} - -/* Offset between 1/1/1601 and 1/1/1970 in 100 nanosec units */ -#define _W32_FT_OFFSET (116444736000000000ULL) - -int qemu_gettimeofday(qemu_timeval *tp) -{ - union { - unsigned long long ns100; /*time since 1 Jan 1601 in 100ns units */ - FILETIME ft; - } _now; - - if(tp) { - GetSystemTimeAsFileTime (&_now.ft); - tp->tv_usec=(long)((_now.ns100 / 10ULL) % 1000000ULL ); - tp->tv_sec= (long)((_now.ns100 - _W32_FT_OFFSET) / 10000000ULL); - } - /* Always return 0 as per Open Group Base Specifications Issue 6. - Do not set errno on error. */ - return 0; -} - -int qemu_get_thread_id(void) -{ - return GetCurrentThreadId(); -} diff --git a/qemu-sockets.c b/qemu-sockets.c deleted file mode 100644 index 34cbbde..0000000 --- a/qemu-sockets.c +++ /dev/null @@ -1,697 +0,0 @@ -/* - * inet and unix socket functions for qemu - * - * (c) 2008 Gerd Hoffmann - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; under version 2 of the License. - * - * This program 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 General Public License for more details. - * - * Contributions after 2012-01-13 are licensed under the terms of the - * GNU GPL, version 2 or (at your option) any later version. - */ -#include -#include -#include -#include -#include -#include - -#include "qemu_socket.h" -#include "qemu-common.h" /* for qemu_isdigit */ - -#ifndef AI_ADDRCONFIG -# define AI_ADDRCONFIG 0 -#endif - -static const int on=1, off=0; - -/* used temporarely until all users are converted to QemuOpts */ -static QemuOptsList dummy_opts = { - .name = "dummy", - .head = QTAILQ_HEAD_INITIALIZER(dummy_opts.head), - .desc = { - { - .name = "path", - .type = QEMU_OPT_STRING, - },{ - .name = "host", - .type = QEMU_OPT_STRING, - },{ - .name = "port", - .type = QEMU_OPT_STRING, - },{ - .name = "to", - .type = QEMU_OPT_NUMBER, - },{ - .name = "ipv4", - .type = QEMU_OPT_BOOL, - },{ - .name = "ipv6", - .type = QEMU_OPT_BOOL, - },{ - .name = "block", - .type = QEMU_OPT_BOOL, - }, - { /* end if list */ } - }, -}; - -static int inet_getport(struct addrinfo *e) -{ - struct sockaddr_in *i4; - struct sockaddr_in6 *i6; - - switch (e->ai_family) { - case PF_INET6: - i6 = (void*)e->ai_addr; - return ntohs(i6->sin6_port); - case PF_INET: - i4 = (void*)e->ai_addr; - return ntohs(i4->sin_port); - default: - return 0; - } -} - -static void inet_setport(struct addrinfo *e, int port) -{ - struct sockaddr_in *i4; - struct sockaddr_in6 *i6; - - switch (e->ai_family) { - case PF_INET6: - i6 = (void*)e->ai_addr; - i6->sin6_port = htons(port); - break; - case PF_INET: - i4 = (void*)e->ai_addr; - i4->sin_port = htons(port); - break; - } -} - -const char *inet_strfamily(int family) -{ - switch (family) { - case PF_INET6: return "ipv6"; - case PF_INET: return "ipv4"; - case PF_UNIX: return "unix"; - } - return "unknown"; -} - -int inet_listen_opts(QemuOpts *opts, int port_offset, Error **errp) -{ - struct addrinfo ai,*res,*e; - const char *addr; - char port[33]; - char uaddr[INET6_ADDRSTRLEN+1]; - char uport[33]; - int slisten, rc, to, port_min, port_max, p; - - memset(&ai,0, sizeof(ai)); - ai.ai_flags = AI_PASSIVE | AI_ADDRCONFIG; - ai.ai_family = PF_UNSPEC; - ai.ai_socktype = SOCK_STREAM; - - if ((qemu_opt_get(opts, "host") == NULL) || - (qemu_opt_get(opts, "port") == NULL)) { - fprintf(stderr, "%s: host and/or port not specified\n", __FUNCTION__); - error_set(errp, QERR_SOCKET_CREATE_FAILED); - return -1; - } - pstrcpy(port, sizeof(port), qemu_opt_get(opts, "port")); - addr = qemu_opt_get(opts, "host"); - - to = qemu_opt_get_number(opts, "to", 0); - if (qemu_opt_get_bool(opts, "ipv4", 0)) - ai.ai_family = PF_INET; - if (qemu_opt_get_bool(opts, "ipv6", 0)) - ai.ai_family = PF_INET6; - - /* lookup */ - if (port_offset) - snprintf(port, sizeof(port), "%d", atoi(port) + port_offset); - rc = getaddrinfo(strlen(addr) ? addr : NULL, port, &ai, &res); - if (rc != 0) { - fprintf(stderr,"getaddrinfo(%s,%s): %s\n", addr, port, - gai_strerror(rc)); - error_set(errp, QERR_SOCKET_CREATE_FAILED); - return -1; - } - - /* create socket + bind */ - for (e = res; e != NULL; e = e->ai_next) { - getnameinfo((struct sockaddr*)e->ai_addr,e->ai_addrlen, - uaddr,INET6_ADDRSTRLEN,uport,32, - NI_NUMERICHOST | NI_NUMERICSERV); - slisten = qemu_socket(e->ai_family, e->ai_socktype, e->ai_protocol); - if (slisten < 0) { - fprintf(stderr,"%s: socket(%s): %s\n", __FUNCTION__, - inet_strfamily(e->ai_family), strerror(errno)); - if (!e->ai_next) { - error_set(errp, QERR_SOCKET_CREATE_FAILED); - } - continue; - } - - setsockopt(slisten,SOL_SOCKET,SO_REUSEADDR,(void*)&on,sizeof(on)); -#ifdef IPV6_V6ONLY - if (e->ai_family == PF_INET6) { - /* listen on both ipv4 and ipv6 */ - setsockopt(slisten,IPPROTO_IPV6,IPV6_V6ONLY,(void*)&off, - sizeof(off)); - } -#endif - - port_min = inet_getport(e); - port_max = to ? to + port_offset : port_min; - for (p = port_min; p <= port_max; p++) { - inet_setport(e, p); - if (bind(slisten, e->ai_addr, e->ai_addrlen) == 0) { - goto listen; - } - if (p == port_max) { - fprintf(stderr,"%s: bind(%s,%s,%d): %s\n", __FUNCTION__, - inet_strfamily(e->ai_family), uaddr, inet_getport(e), - strerror(errno)); - if (!e->ai_next) { - error_set(errp, QERR_SOCKET_BIND_FAILED); - } - } - } - closesocket(slisten); - } - fprintf(stderr, "%s: FAILED\n", __FUNCTION__); - freeaddrinfo(res); - return -1; - -listen: - if (listen(slisten,1) != 0) { - error_set(errp, QERR_SOCKET_LISTEN_FAILED); - perror("listen"); - closesocket(slisten); - freeaddrinfo(res); - return -1; - } - snprintf(uport, sizeof(uport), "%d", inet_getport(e) - port_offset); - qemu_opt_set(opts, "host", uaddr); - qemu_opt_set(opts, "port", uport); - qemu_opt_set(opts, "ipv6", (e->ai_family == PF_INET6) ? "on" : "off"); - qemu_opt_set(opts, "ipv4", (e->ai_family != PF_INET6) ? "on" : "off"); - freeaddrinfo(res); - return slisten; -} - -int inet_connect_opts(QemuOpts *opts, bool *in_progress, Error **errp) -{ - struct addrinfo ai,*res,*e; - const char *addr; - const char *port; - char uaddr[INET6_ADDRSTRLEN+1]; - char uport[33]; - int sock,rc; - bool block; - - memset(&ai,0, sizeof(ai)); - ai.ai_flags = AI_CANONNAME | AI_ADDRCONFIG; - ai.ai_family = PF_UNSPEC; - ai.ai_socktype = SOCK_STREAM; - - if (in_progress) { - *in_progress = false; - } - - addr = qemu_opt_get(opts, "host"); - port = qemu_opt_get(opts, "port"); - block = qemu_opt_get_bool(opts, "block", 0); - if (addr == NULL || port == NULL) { - fprintf(stderr, "inet_connect: host and/or port not specified\n"); - error_set(errp, QERR_SOCKET_CREATE_FAILED); - return -1; - } - - if (qemu_opt_get_bool(opts, "ipv4", 0)) - ai.ai_family = PF_INET; - if (qemu_opt_get_bool(opts, "ipv6", 0)) - ai.ai_family = PF_INET6; - -#ifdef CONFIG_MARU - // for lookup loopback interface... - if (addr[0] == '\0') { - ai.ai_flags = 0; - addr = NULL; - } -#endif - - /* lookup */ - if (0 != (rc = getaddrinfo(addr, port, &ai, &res))) { - fprintf(stderr,"getaddrinfo(%s,%s): %s\n", addr, port, - gai_strerror(rc)); - error_set(errp, QERR_SOCKET_CREATE_FAILED); - return -1; - } - - for (e = res; e != NULL; e = e->ai_next) { - if (getnameinfo((struct sockaddr*)e->ai_addr,e->ai_addrlen, - uaddr,INET6_ADDRSTRLEN,uport,32, - NI_NUMERICHOST | NI_NUMERICSERV) != 0) { - fprintf(stderr,"%s: getnameinfo: oops\n", __FUNCTION__); - continue; - } - sock = qemu_socket(e->ai_family, e->ai_socktype, e->ai_protocol); - if (sock < 0) { - fprintf(stderr,"%s: socket(%s): %s\n", __FUNCTION__, - inet_strfamily(e->ai_family), strerror(errno)); - continue; - } - setsockopt(sock,SOL_SOCKET,SO_REUSEADDR,(void*)&on,sizeof(on)); - if (!block) { - socket_set_nonblock(sock); - } - /* connect to peer */ - do { - rc = 0; - if (connect(sock, e->ai_addr, e->ai_addrlen) < 0) { - rc = -socket_error(); - } - } while (rc == -EINTR); - - #ifdef _WIN32 - if (!block && (rc == -EINPROGRESS || rc == -EWOULDBLOCK - || rc == -WSAEALREADY)) { - #else - if (!block && (rc == -EINPROGRESS)) { - #endif - if (in_progress) { - *in_progress = true; - } - } else if (rc < 0) { - if (NULL == e->ai_next) - fprintf(stderr, "%s: connect(%s,%s,%s,%s): %s\n", __FUNCTION__, - inet_strfamily(e->ai_family), - e->ai_canonname, uaddr, uport, strerror(errno)); - closesocket(sock); - continue; - } - freeaddrinfo(res); - return sock; - } - error_set(errp, QERR_SOCKET_CONNECT_FAILED); - freeaddrinfo(res); - return -1; -} - -int inet_dgram_opts(QemuOpts *opts) -{ - struct addrinfo ai, *peer = NULL, *local = NULL; - const char *addr; - const char *port; - char uaddr[INET6_ADDRSTRLEN+1]; - char uport[33]; - int sock = -1, rc; - - /* lookup peer addr */ - memset(&ai,0, sizeof(ai)); - ai.ai_flags = AI_CANONNAME | AI_ADDRCONFIG; - ai.ai_family = PF_UNSPEC; - ai.ai_socktype = SOCK_DGRAM; - - addr = qemu_opt_get(opts, "host"); - port = qemu_opt_get(opts, "port"); - if (addr == NULL || strlen(addr) == 0) { - addr = "localhost"; - } - if (port == NULL || strlen(port) == 0) { - fprintf(stderr, "inet_dgram: port not specified\n"); - return -1; - } - - if (qemu_opt_get_bool(opts, "ipv4", 0)) - ai.ai_family = PF_INET; - if (qemu_opt_get_bool(opts, "ipv6", 0)) - ai.ai_family = PF_INET6; - - if (0 != (rc = getaddrinfo(addr, port, &ai, &peer))) { - fprintf(stderr,"getaddrinfo(%s,%s): %s\n", addr, port, - gai_strerror(rc)); - return -1; - } - - /* lookup local addr */ - memset(&ai,0, sizeof(ai)); - ai.ai_flags = AI_PASSIVE; - ai.ai_family = peer->ai_family; - ai.ai_socktype = SOCK_DGRAM; - - addr = qemu_opt_get(opts, "localaddr"); - port = qemu_opt_get(opts, "localport"); - if (addr == NULL || strlen(addr) == 0) { - addr = NULL; - } - if (!port || strlen(port) == 0) - port = "0"; - - if (0 != (rc = getaddrinfo(addr, port, &ai, &local))) { - fprintf(stderr,"getaddrinfo(%s,%s): %s\n", addr, port, - gai_strerror(rc)); - return -1; - } - - /* create socket */ - sock = qemu_socket(peer->ai_family, peer->ai_socktype, peer->ai_protocol); - if (sock < 0) { - fprintf(stderr,"%s: socket(%s): %s\n", __FUNCTION__, - inet_strfamily(peer->ai_family), strerror(errno)); - goto err; - } - setsockopt(sock,SOL_SOCKET,SO_REUSEADDR,(void*)&on,sizeof(on)); - - /* bind socket */ - if (getnameinfo((struct sockaddr*)local->ai_addr,local->ai_addrlen, - uaddr,INET6_ADDRSTRLEN,uport,32, - NI_NUMERICHOST | NI_NUMERICSERV) != 0) { - fprintf(stderr, "%s: getnameinfo: oops\n", __FUNCTION__); - goto err; - } - if (bind(sock, local->ai_addr, local->ai_addrlen) < 0) { - fprintf(stderr,"%s: bind(%s,%s,%d): OK\n", __FUNCTION__, - inet_strfamily(local->ai_family), uaddr, inet_getport(local)); - goto err; - } - - /* connect to peer */ - if (getnameinfo((struct sockaddr*)peer->ai_addr, peer->ai_addrlen, - uaddr, INET6_ADDRSTRLEN, uport, 32, - NI_NUMERICHOST | NI_NUMERICSERV) != 0) { - fprintf(stderr, "%s: getnameinfo: oops\n", __FUNCTION__); - goto err; - } - if (connect(sock,peer->ai_addr,peer->ai_addrlen) < 0) { - fprintf(stderr, "%s: connect(%s,%s,%s,%s): %s\n", __FUNCTION__, - inet_strfamily(peer->ai_family), - peer->ai_canonname, uaddr, uport, strerror(errno)); - goto err; - } - - freeaddrinfo(local); - freeaddrinfo(peer); - return sock; - -err: - if (-1 != sock) - closesocket(sock); - if (local) - freeaddrinfo(local); - if (peer) - freeaddrinfo(peer); - return -1; -} - -/* compatibility wrapper */ -static int inet_parse(QemuOpts *opts, const char *str) -{ - const char *optstr, *h; - char addr[64]; - char port[33]; - int pos; - - /* parse address */ - if (str[0] == ':') { - /* no host given */ - addr[0] = '\0'; - if (1 != sscanf(str,":%32[^,]%n",port,&pos)) { - fprintf(stderr, "%s: portonly parse error (%s)\n", - __FUNCTION__, str); - return -1; - } - } else if (str[0] == '[') { - /* IPv6 addr */ - if (2 != sscanf(str,"[%64[^]]]:%32[^,]%n",addr,port,&pos)) { - fprintf(stderr, "%s: ipv6 parse error (%s)\n", - __FUNCTION__, str); - return -1; - } - qemu_opt_set(opts, "ipv6", "on"); - } else if (qemu_isdigit(str[0])) { - /* IPv4 addr */ - if (2 != sscanf(str,"%64[0-9.]:%32[^,]%n",addr,port,&pos)) { - fprintf(stderr, "%s: ipv4 parse error (%s)\n", - __FUNCTION__, str); - return -1; - } - qemu_opt_set(opts, "ipv4", "on"); - } else { - /* hostname */ - if (2 != sscanf(str,"%64[^:]:%32[^,]%n",addr,port,&pos)) { - fprintf(stderr, "%s: hostname parse error (%s)\n", - __FUNCTION__, str); - return -1; - } - } - qemu_opt_set(opts, "host", addr); - qemu_opt_set(opts, "port", port); - - /* parse options */ - optstr = str + pos; - h = strstr(optstr, ",to="); - if (h) - qemu_opt_set(opts, "to", h+4); - if (strstr(optstr, ",ipv4")) - qemu_opt_set(opts, "ipv4", "on"); - if (strstr(optstr, ",ipv6")) - qemu_opt_set(opts, "ipv6", "on"); - return 0; -} - -int inet_listen(const char *str, char *ostr, int olen, - int socktype, int port_offset, Error **errp) -{ - QemuOpts *opts; - char *optstr; - int sock = -1; - - opts = qemu_opts_create(&dummy_opts, NULL, 0, NULL); - if (inet_parse(opts, str) == 0) { - sock = inet_listen_opts(opts, port_offset, errp); - if (sock != -1 && ostr) { - optstr = strchr(str, ','); - if (qemu_opt_get_bool(opts, "ipv6", 0)) { - snprintf(ostr, olen, "[%s]:%s%s", - qemu_opt_get(opts, "host"), - qemu_opt_get(opts, "port"), - optstr ? optstr : ""); - } else { - snprintf(ostr, olen, "%s:%s%s", - qemu_opt_get(opts, "host"), - qemu_opt_get(opts, "port"), - optstr ? optstr : ""); - } - } - } else { - error_set(errp, QERR_SOCKET_CREATE_FAILED); - } - qemu_opts_del(opts); - return sock; -} - -int inet_connect(const char *str, bool block, bool *in_progress, Error **errp) -{ - QemuOpts *opts; - int sock = -1; - - opts = qemu_opts_create(&dummy_opts, NULL, 0, NULL); - if (inet_parse(opts, str) == 0) { - if (block) { - qemu_opt_set(opts, "block", "on"); - } - sock = inet_connect_opts(opts, in_progress, errp); - } else { - error_set(errp, QERR_SOCKET_CREATE_FAILED); - } - qemu_opts_del(opts); - return sock; -} - -#ifndef _WIN32 - -int unix_listen_opts(QemuOpts *opts) -{ - struct sockaddr_un un; - const char *path = qemu_opt_get(opts, "path"); - int sock, fd; - - sock = qemu_socket(PF_UNIX, SOCK_STREAM, 0); - if (sock < 0) { - perror("socket(unix)"); - return -1; - } - - memset(&un, 0, sizeof(un)); - un.sun_family = AF_UNIX; - if (path && strlen(path)) { - snprintf(un.sun_path, sizeof(un.sun_path), "%s", path); - } else { - char *tmpdir = getenv("TMPDIR"); - snprintf(un.sun_path, sizeof(un.sun_path), "%s/qemu-socket-XXXXXX", - tmpdir ? tmpdir : "/tmp"); - /* - * This dummy fd usage silences the mktemp() unsecure warning. - * Using mkstemp() doesn't make things more secure here - * though. bind() complains about existing files, so we have - * to unlink first and thus re-open the race window. The - * worst case possible is bind() failing, i.e. a DoS attack. - */ - fd = mkstemp(un.sun_path); close(fd); - qemu_opt_set(opts, "path", un.sun_path); - } - - unlink(un.sun_path); - if (bind(sock, (struct sockaddr*) &un, sizeof(un)) < 0) { - fprintf(stderr, "bind(unix:%s): %s\n", un.sun_path, strerror(errno)); - goto err; - } - if (listen(sock, 1) < 0) { - fprintf(stderr, "listen(unix:%s): %s\n", un.sun_path, strerror(errno)); - goto err; - } - - return sock; - -err: - closesocket(sock); - return -1; -} - -int unix_connect_opts(QemuOpts *opts) -{ - struct sockaddr_un un; - const char *path = qemu_opt_get(opts, "path"); - int sock; - - if (NULL == path) { - fprintf(stderr, "unix connect: no path specified\n"); - return -1; - } - - sock = qemu_socket(PF_UNIX, SOCK_STREAM, 0); - if (sock < 0) { - perror("socket(unix)"); - return -1; - } - - memset(&un, 0, sizeof(un)); - un.sun_family = AF_UNIX; - snprintf(un.sun_path, sizeof(un.sun_path), "%s", path); - if (connect(sock, (struct sockaddr*) &un, sizeof(un)) < 0) { - fprintf(stderr, "connect(unix:%s): %s\n", path, strerror(errno)); - close(sock); - return -1; - } - - return sock; -} - -/* compatibility wrapper */ -int unix_listen(const char *str, char *ostr, int olen) -{ - QemuOpts *opts; - char *path, *optstr; - int sock, len; - - opts = qemu_opts_create(&dummy_opts, NULL, 0, NULL); - - optstr = strchr(str, ','); - if (optstr) { - len = optstr - str; - if (len) { - path = g_malloc(len+1); - snprintf(path, len+1, "%.*s", len, str); - qemu_opt_set(opts, "path", path); - g_free(path); - } - } else { - qemu_opt_set(opts, "path", str); - } - - sock = unix_listen_opts(opts); - - if (sock != -1 && ostr) - snprintf(ostr, olen, "%s%s", qemu_opt_get(opts, "path"), optstr ? optstr : ""); - qemu_opts_del(opts); - return sock; -} - -int unix_connect(const char *path) -{ - QemuOpts *opts; - int sock; - - opts = qemu_opts_create(&dummy_opts, NULL, 0, NULL); - qemu_opt_set(opts, "path", path); - sock = unix_connect_opts(opts); - qemu_opts_del(opts); - return sock; -} - -#else - -int unix_listen_opts(QemuOpts *opts) -{ - fprintf(stderr, "unix sockets are not available on windows\n"); - errno = ENOTSUP; - return -1; -} - -int unix_connect_opts(QemuOpts *opts) -{ - fprintf(stderr, "unix sockets are not available on windows\n"); - errno = ENOTSUP; - return -1; -} - -int unix_listen(const char *path, char *ostr, int olen) -{ - fprintf(stderr, "unix sockets are not available on windows\n"); - errno = ENOTSUP; - return -1; -} - -int unix_connect(const char *path) -{ - fprintf(stderr, "unix sockets are not available on windows\n"); - errno = ENOTSUP; - return -1; -} - -#endif - -#ifdef _WIN32 -static void socket_cleanup(void) -{ - WSACleanup(); -} -#endif - -int socket_init(void) -{ -#ifdef _WIN32 - WSADATA Data; - int ret, err; - - ret = WSAStartup(MAKEWORD(2,2), &Data); - if (ret != 0) { - err = WSAGetLastError(); - fprintf(stderr, "WSAStartup: %d\n", err); - return -1; - } - atexit(socket_cleanup); -#endif - return 0; -} diff --git a/softmmu_defs.h b/softmmu_defs.h deleted file mode 100644 index e3f6156..0000000 --- a/softmmu_defs.h +++ /dev/null @@ -1,71 +0,0 @@ -/* - * Software MMU support - * - * Declare helpers used by TCG for qemu_ld/st ops. - * - * Used by softmmu_exec.h, TCG targets and exec-all.h. - * - */ -#ifndef SOFTMMU_DEFS_H -#define SOFTMMU_DEFS_H - -#ifndef CONFIG_TCG_PASS_AREG0 -uint8_t __ldb_mmu(target_ulong addr, int mmu_idx); -void __stb_mmu(target_ulong addr, uint8_t val, int mmu_idx); -uint16_t __ldw_mmu(target_ulong addr, int mmu_idx); -void __stw_mmu(target_ulong addr, uint16_t val, int mmu_idx); -uint32_t __ldl_mmu(target_ulong addr, int mmu_idx); -void __stl_mmu(target_ulong addr, uint32_t val, int mmu_idx); -uint64_t __ldq_mmu(target_ulong addr, int mmu_idx); -void __stq_mmu(target_ulong addr, uint64_t val, int mmu_idx); - -#if defined(CONFIG_QEMU_LDST_OPTIMIZATION) && defined(CONFIG_SOFTMMU) -/* Extended versions of MMU helpers for qemu_ld/st optimization. - They get return address arguments because the caller PCs are not where helpers return to. */ -uint8_t __ext_ldb_mmu(target_ulong addr, int mmu_idx, uintptr_t ra); -void __ext_stb_mmu(target_ulong addr, uint8_t val, int mmu_idx, uintptr_t ra); -uint16_t __ext_ldw_mmu(target_ulong addr, int mmu_idx, uintptr_t ra); -void __ext_stw_mmu(target_ulong addr, uint16_t val, int mmu_idx, uintptr_t ra); -uint32_t __ext_ldl_mmu(target_ulong addr, int mmu_idx, uintptr_t ra); -void __ext_stl_mmu(target_ulong addr, uint32_t val, int mmu_idx, uintptr_t ra); -uint64_t __ext_ldq_mmu(target_ulong addr, int mmu_idx, uintptr_t ra); -void __ext_stq_mmu(target_ulong addr, uint64_t val, int mmu_idx, uintptr_t ra); -#endif /* CONFIG_QEMU_LDST_OPTIMIZATION && CONFIG_SOFTMMU */ - -uint8_t __ldb_cmmu(target_ulong addr, int mmu_idx); -void __stb_cmmu(target_ulong addr, uint8_t val, int mmu_idx); -uint16_t __ldw_cmmu(target_ulong addr, int mmu_idx); -void __stw_cmmu(target_ulong addr, uint16_t val, int mmu_idx); -uint32_t __ldl_cmmu(target_ulong addr, int mmu_idx); -void __stl_cmmu(target_ulong addr, uint32_t val, int mmu_idx); -uint64_t __ldq_cmmu(target_ulong addr, int mmu_idx); -void __stq_cmmu(target_ulong addr, uint64_t val, int mmu_idx); -#else -uint8_t helper_ldb_mmu(CPUArchState *env, target_ulong addr, int mmu_idx); -void helper_stb_mmu(CPUArchState *env, target_ulong addr, uint8_t val, - int mmu_idx); -uint16_t helper_ldw_mmu(CPUArchState *env, target_ulong addr, int mmu_idx); -void helper_stw_mmu(CPUArchState *env, target_ulong addr, uint16_t val, - int mmu_idx); -uint32_t helper_ldl_mmu(CPUArchState *env, target_ulong addr, int mmu_idx); -void helper_stl_mmu(CPUArchState *env, target_ulong addr, uint32_t val, - int mmu_idx); -uint64_t helper_ldq_mmu(CPUArchState *env, target_ulong addr, int mmu_idx); -void helper_stq_mmu(CPUArchState *env, target_ulong addr, uint64_t val, - int mmu_idx); - -uint8_t helper_ldb_cmmu(CPUArchState *env, target_ulong addr, int mmu_idx); -void helper_stb_cmmu(CPUArchState *env, target_ulong addr, uint8_t val, -int mmu_idx); -uint16_t helper_ldw_cmmu(CPUArchState *env, target_ulong addr, int mmu_idx); -void helper_stw_cmmu(CPUArchState *env, target_ulong addr, uint16_t val, - int mmu_idx); -uint32_t helper_ldl_cmmu(CPUArchState *env, target_ulong addr, int mmu_idx); -void helper_stl_cmmu(CPUArchState *env, target_ulong addr, uint32_t val, - int mmu_idx); -uint64_t helper_ldq_cmmu(CPUArchState *env, target_ulong addr, int mmu_idx); -void helper_stq_cmmu(CPUArchState *env, target_ulong addr, uint64_t val, - int mmu_idx); -#endif - -#endif diff --git a/softmmu_template.h b/softmmu_template.h deleted file mode 100644 index 0366e67..0000000 --- a/softmmu_template.h +++ /dev/null @@ -1,372 +0,0 @@ -/* - * Software MMU support - * - * Generate helpers used by TCG for qemu_ld/st ops and code load - * functions. - * - * Included from target op helpers and exec.c. - * - * Copyright (c) 2003 Fabrice Bellard - * - * 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 . - */ -#include "qemu-timer.h" -#include "memory.h" - -#define DATA_SIZE (1 << SHIFT) - -#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 -#elif DATA_SIZE == 1 -#define SUFFIX b -#define USUFFIX ub -#define DATA_TYPE uint8_t -#else -#error unsupported data size -#endif - -#ifdef SOFTMMU_CODE_ACCESS -#define READ_ACCESS_TYPE 2 -#define ADDR_READ addr_code -#else -#define READ_ACCESS_TYPE 0 -#define ADDR_READ addr_read -#endif - -#ifndef CONFIG_TCG_PASS_AREG0 -#define ENV_PARAM -#define ENV_VAR -#define CPU_PREFIX -#define HELPER_PREFIX __ -#else -#define ENV_PARAM CPUArchState *env, -#define ENV_VAR env, -#define CPU_PREFIX cpu_ -#define HELPER_PREFIX helper_ -#endif - -static DATA_TYPE glue(glue(slow_ld, SUFFIX), MMUSUFFIX)(ENV_PARAM - target_ulong addr, - int mmu_idx, - uintptr_t retaddr); -static inline DATA_TYPE glue(io_read, SUFFIX)(ENV_PARAM - target_phys_addr_t physaddr, - target_ulong addr, - uintptr_t retaddr) -{ - DATA_TYPE res; - MemoryRegion *mr = iotlb_to_region(physaddr); - - physaddr = (physaddr & TARGET_PAGE_MASK) + addr; - env->mem_io_pc = retaddr; - if (mr != &io_mem_ram && mr != &io_mem_rom - && mr != &io_mem_unassigned - && mr != &io_mem_notdirty - && !can_do_io(env)) { - cpu_io_recompile(env, retaddr); - } - - env->mem_io_vaddr = addr; -#if SHIFT <= 2 - res = io_mem_read(mr, physaddr, 1 << SHIFT); -#else -#ifdef TARGET_WORDS_BIGENDIAN - res = io_mem_read(mr, physaddr, 4) << 32; - res |= io_mem_read(mr, physaddr + 4, 4); -#else - res = io_mem_read(mr, physaddr, 4); - res |= io_mem_read(mr, physaddr + 4, 4) << 32; -#endif -#endif /* SHIFT > 2 */ - return res; -} - -/* handle all cases except unaligned access which span two pages */ -DATA_TYPE -glue(glue(glue(HELPER_PREFIX, ld), SUFFIX), MMUSUFFIX)(ENV_PARAM - target_ulong addr, - int mmu_idx) -{ - DATA_TYPE res; - int index; - target_ulong tlb_addr; - target_phys_addr_t ioaddr; - uintptr_t retaddr; - - /* test if there is match for unaligned or IO access */ - /* XXX: could done more in memory macro in a non portable way */ - index = (addr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1); - redo: - tlb_addr = env->tlb_table[mmu_idx][index].ADDR_READ; - if ((addr & TARGET_PAGE_MASK) == (tlb_addr & (TARGET_PAGE_MASK | TLB_INVALID_MASK))) { - if (tlb_addr & ~TARGET_PAGE_MASK) { - /* IO access */ - if ((addr & (DATA_SIZE - 1)) != 0) - goto do_unaligned_access; - retaddr = GETPC_EXT(); - ioaddr = env->iotlb[mmu_idx][index]; - res = glue(io_read, SUFFIX)(ENV_VAR ioaddr, addr, retaddr); - } else if (((addr & ~TARGET_PAGE_MASK) + DATA_SIZE - 1) >= TARGET_PAGE_SIZE) { - /* slow unaligned access (it spans two pages or IO) */ - do_unaligned_access: - retaddr = GETPC_EXT(); -#ifdef ALIGNED_ONLY - do_unaligned_access(ENV_VAR addr, READ_ACCESS_TYPE, mmu_idx, retaddr); -#endif - res = glue(glue(slow_ld, SUFFIX), MMUSUFFIX)(ENV_VAR addr, - mmu_idx, retaddr); - } else { - /* unaligned/aligned access in the same page */ - uintptr_t addend; -#ifdef ALIGNED_ONLY - if ((addr & (DATA_SIZE - 1)) != 0) { - retaddr = GETPC_EXT(); - do_unaligned_access(ENV_VAR addr, READ_ACCESS_TYPE, mmu_idx, retaddr); - } -#endif - addend = env->tlb_table[mmu_idx][index].addend; - res = glue(glue(ld, USUFFIX), _raw)((uint8_t *)(intptr_t) - (addr + addend)); - } - } else { - /* the page is not in the TLB : fill it */ - retaddr = GETPC_EXT(); -#ifdef ALIGNED_ONLY - if ((addr & (DATA_SIZE - 1)) != 0) - do_unaligned_access(ENV_VAR addr, READ_ACCESS_TYPE, mmu_idx, retaddr); -#endif - tlb_fill(env, addr, READ_ACCESS_TYPE, mmu_idx, retaddr); - goto redo; - } - return res; -} - -/* handle all unaligned cases */ -static DATA_TYPE -glue(glue(slow_ld, SUFFIX), MMUSUFFIX)(ENV_PARAM - target_ulong addr, - int mmu_idx, - uintptr_t retaddr) -{ - DATA_TYPE res, res1, res2; - int index, shift; - target_phys_addr_t ioaddr; - target_ulong tlb_addr, addr1, addr2; - - index = (addr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1); - redo: - tlb_addr = env->tlb_table[mmu_idx][index].ADDR_READ; - if ((addr & TARGET_PAGE_MASK) == (tlb_addr & (TARGET_PAGE_MASK | TLB_INVALID_MASK))) { - if (tlb_addr & ~TARGET_PAGE_MASK) { - /* IO access */ - if ((addr & (DATA_SIZE - 1)) != 0) - goto do_unaligned_access; - ioaddr = env->iotlb[mmu_idx][index]; - res = glue(io_read, SUFFIX)(ENV_VAR ioaddr, addr, retaddr); - } else if (((addr & ~TARGET_PAGE_MASK) + DATA_SIZE - 1) >= TARGET_PAGE_SIZE) { - do_unaligned_access: - /* slow unaligned access (it spans two pages) */ - addr1 = addr & ~(DATA_SIZE - 1); - addr2 = addr1 + DATA_SIZE; - res1 = glue(glue(slow_ld, SUFFIX), MMUSUFFIX)(ENV_VAR addr1, - mmu_idx, retaddr); - res2 = glue(glue(slow_ld, SUFFIX), MMUSUFFIX)(ENV_VAR addr2, - mmu_idx, retaddr); - shift = (addr & (DATA_SIZE - 1)) * 8; -#ifdef TARGET_WORDS_BIGENDIAN - res = (res1 << shift) | (res2 >> ((DATA_SIZE * 8) - shift)); -#else - res = (res1 >> shift) | (res2 << ((DATA_SIZE * 8) - shift)); -#endif - res = (DATA_TYPE)res; - } else { - /* unaligned/aligned access in the same page */ - uintptr_t addend = env->tlb_table[mmu_idx][index].addend; - res = glue(glue(ld, USUFFIX), _raw)((uint8_t *)(intptr_t) - (addr + addend)); - } - } else { - /* the page is not in the TLB : fill it */ - tlb_fill(env, addr, READ_ACCESS_TYPE, mmu_idx, retaddr); - goto redo; - } - return res; -} - -#ifndef SOFTMMU_CODE_ACCESS - -static void glue(glue(slow_st, SUFFIX), MMUSUFFIX)(ENV_PARAM - target_ulong addr, - DATA_TYPE val, - int mmu_idx, - uintptr_t retaddr); - -static inline void glue(io_write, SUFFIX)(ENV_PARAM - target_phys_addr_t physaddr, - DATA_TYPE val, - target_ulong addr, - uintptr_t retaddr) -{ - MemoryRegion *mr = iotlb_to_region(physaddr); - - physaddr = (physaddr & TARGET_PAGE_MASK) + addr; - if (mr != &io_mem_ram && mr != &io_mem_rom - && mr != &io_mem_unassigned - && mr != &io_mem_notdirty - && !can_do_io(env)) { - cpu_io_recompile(env, retaddr); - } - - env->mem_io_vaddr = addr; - env->mem_io_pc = retaddr; -#if SHIFT <= 2 - io_mem_write(mr, physaddr, val, 1 << SHIFT); -#else -#ifdef TARGET_WORDS_BIGENDIAN - io_mem_write(mr, physaddr, (val >> 32), 4); - io_mem_write(mr, physaddr + 4, (uint32_t)val, 4); -#else - io_mem_write(mr, physaddr, (uint32_t)val, 4); - io_mem_write(mr, physaddr + 4, val >> 32, 4); -#endif -#endif /* SHIFT > 2 */ -} - -void glue(glue(glue(HELPER_PREFIX, st), SUFFIX), MMUSUFFIX)(ENV_PARAM - target_ulong addr, - DATA_TYPE val, - int mmu_idx) -{ - target_phys_addr_t ioaddr; - target_ulong tlb_addr; - uintptr_t retaddr; - int index; - - index = (addr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1); - redo: - tlb_addr = env->tlb_table[mmu_idx][index].addr_write; - if ((addr & TARGET_PAGE_MASK) == (tlb_addr & (TARGET_PAGE_MASK | TLB_INVALID_MASK))) { - if (tlb_addr & ~TARGET_PAGE_MASK) { - /* IO access */ - if ((addr & (DATA_SIZE - 1)) != 0) - goto do_unaligned_access; - retaddr = GETPC_EXT(); - ioaddr = env->iotlb[mmu_idx][index]; - glue(io_write, SUFFIX)(ENV_VAR ioaddr, val, addr, retaddr); - } else if (((addr & ~TARGET_PAGE_MASK) + DATA_SIZE - 1) >= TARGET_PAGE_SIZE) { - do_unaligned_access: - retaddr = GETPC_EXT(); -#ifdef ALIGNED_ONLY - do_unaligned_access(ENV_VAR addr, 1, mmu_idx, retaddr); -#endif - glue(glue(slow_st, SUFFIX), MMUSUFFIX)(ENV_VAR addr, val, - mmu_idx, retaddr); - } else { - /* aligned/unaligned access in the same page */ - uintptr_t addend; -#ifdef ALIGNED_ONLY - if ((addr & (DATA_SIZE - 1)) != 0) { - retaddr = GETPC_EXT(); - do_unaligned_access(ENV_VAR addr, 1, mmu_idx, retaddr); - } -#endif - addend = env->tlb_table[mmu_idx][index].addend; - glue(glue(st, SUFFIX), _raw)((uint8_t *)(intptr_t) - (addr + addend), val); - } - } else { - /* the page is not in the TLB : fill it */ - retaddr = GETPC_EXT(); -#ifdef ALIGNED_ONLY - if ((addr & (DATA_SIZE - 1)) != 0) - do_unaligned_access(ENV_VAR addr, 1, mmu_idx, retaddr); -#endif - tlb_fill(env, addr, 1, mmu_idx, retaddr); - goto redo; - } -} - -/* handles all unaligned cases */ -static void glue(glue(slow_st, SUFFIX), MMUSUFFIX)(ENV_PARAM - target_ulong addr, - DATA_TYPE val, - int mmu_idx, - uintptr_t retaddr) -{ - target_phys_addr_t ioaddr; - target_ulong tlb_addr; - int index, i; - - index = (addr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1); - redo: - tlb_addr = env->tlb_table[mmu_idx][index].addr_write; - if ((addr & TARGET_PAGE_MASK) == (tlb_addr & (TARGET_PAGE_MASK | TLB_INVALID_MASK))) { - if (tlb_addr & ~TARGET_PAGE_MASK) { - /* IO access */ - if ((addr & (DATA_SIZE - 1)) != 0) - goto do_unaligned_access; - ioaddr = env->iotlb[mmu_idx][index]; - glue(io_write, SUFFIX)(ENV_VAR ioaddr, val, addr, retaddr); - } else if (((addr & ~TARGET_PAGE_MASK) + DATA_SIZE - 1) >= TARGET_PAGE_SIZE) { - do_unaligned_access: - /* XXX: not efficient, but simple */ - /* Note: relies on the fact that tlb_fill() does not remove the - * previous page from the TLB cache. */ - for(i = DATA_SIZE - 1; i >= 0; i--) { -#ifdef TARGET_WORDS_BIGENDIAN - glue(slow_stb, MMUSUFFIX)(ENV_VAR addr + i, - val >> (((DATA_SIZE - 1) * 8) - (i * 8)), - mmu_idx, retaddr); -#else - glue(slow_stb, MMUSUFFIX)(ENV_VAR addr + i, - val >> (i * 8), - mmu_idx, retaddr); -#endif - } - } else { - /* aligned/unaligned access in the same page */ - uintptr_t addend = env->tlb_table[mmu_idx][index].addend; - glue(glue(st, SUFFIX), _raw)((uint8_t *)(intptr_t) - (addr + addend), val); - } - } else { - /* the page is not in the TLB : fill it */ - tlb_fill(env, addr, 1, mmu_idx, retaddr); - goto redo; - } -} - -#endif /* !defined(SOFTMMU_CODE_ACCESS) */ - -#undef READ_ACCESS_TYPE -#undef SHIFT -#undef DATA_TYPE -#undef SUFFIX -#undef USUFFIX -#undef DATA_SIZE -#undef ADDR_READ -#undef ENV_PARAM -#undef ENV_VAR -#undef CPU_PREFIX -#undef HELPER_PREFIX diff --git a/sysemu.h b/sysemu.h deleted file mode 100644 index 3a23fb9..0000000 --- a/sysemu.h +++ /dev/null @@ -1,204 +0,0 @@ -#ifndef SYSEMU_H -#define SYSEMU_H -/* Misc. things related to the system emulator. */ - -#include "qemu-common.h" -#include "qemu-option.h" -#include "qemu-queue.h" -#include "qemu-timer.h" -#include "qapi-types.h" -#include "notify.h" -#include "main-loop.h" - -/* vl.c */ - -extern const char *bios_name; - -extern const char *qemu_name; -extern uint8_t qemu_uuid[]; -int qemu_uuid_parse(const char *str, uint8_t *uuid); -#define UUID_FMT "%02hhx%02hhx%02hhx%02hhx-%02hhx%02hhx-%02hhx%02hhx-%02hhx%02hhx-%02hhx%02hhx%02hhx%02hhx%02hhx%02hhx" - -void runstate_init(void); -bool runstate_check(RunState state); -void runstate_set(RunState new_state); -int runstate_is_running(void); -typedef struct vm_change_state_entry VMChangeStateEntry; -typedef void VMChangeStateHandler(void *opaque, int running, RunState state); - -VMChangeStateEntry *qemu_add_vm_change_state_handler(VMChangeStateHandler *cb, - void *opaque); -void qemu_del_vm_change_state_handler(VMChangeStateEntry *e); -void vm_state_notify(int running, RunState state); - -#define VMRESET_SILENT false -#define VMRESET_REPORT true - -void vm_start(void); -void vm_stop(RunState state); -void vm_stop_force_state(RunState state); - -typedef enum WakeupReason { - QEMU_WAKEUP_REASON_OTHER = 0, - QEMU_WAKEUP_REASON_RTC, - QEMU_WAKEUP_REASON_PMTIMER, -} WakeupReason; - -void qemu_system_reset_request(void); -void qemu_system_suspend_request(void); -void qemu_register_suspend_notifier(Notifier *notifier); -void qemu_system_wakeup_request(WakeupReason reason); -void qemu_system_wakeup_enable(WakeupReason reason, bool enabled); -void qemu_register_wakeup_notifier(Notifier *notifier); -void qemu_system_shutdown_request(void); -void qemu_system_powerdown_request(void); -void qemu_system_debug_request(void); -void qemu_system_vmstop_request(RunState reason); -int qemu_shutdown_requested_get(void); -int qemu_reset_requested_get(void); -int qemu_shutdown_requested(void); -int qemu_reset_requested(void); -int qemu_powerdown_requested(void); -void qemu_system_killed(int signal, pid_t pid); -void qemu_kill_report(void); -extern qemu_irq qemu_system_powerdown; -void qemu_devices_reset(void); -void qemu_system_reset(bool report); - -void qemu_add_exit_notifier(Notifier *notify); -void qemu_remove_exit_notifier(Notifier *notify); - -void qemu_add_machine_init_done_notifier(Notifier *notify); - -void do_savevm(Monitor *mon, const QDict *qdict); -int load_vmstate(const char *name); -void do_delvm(Monitor *mon, const QDict *qdict); -void do_info_snapshots(Monitor *mon); - -void qemu_announce_self(void); - -bool qemu_savevm_state_blocked(Error **errp); -int qemu_savevm_state_begin(QEMUFile *f, - const MigrationParams *params); -int qemu_savevm_state_iterate(QEMUFile *f); -int qemu_savevm_state_complete(QEMUFile *f); -void qemu_savevm_state_cancel(QEMUFile *f); -int qemu_loadvm_state(QEMUFile *f); - -/* SLIRP */ -void do_info_slirp(Monitor *mon); - -typedef enum DisplayType -{ - DT_DEFAULT, - DT_CURSES, - DT_SDL, - DT_NOGRAPHIC, -#ifdef CONFIG_MARU - DT_MARU, -#endif - DT_NONE, -} DisplayType; - -extern int autostart; -extern int bios_size; - -typedef enum { - VGA_NONE, VGA_STD, VGA_CIRRUS, VGA_VMWARE, VGA_XENFB, VGA_QXL, -#ifdef CONFIG_MARU - VGA_MARU, -#endif -} VGAInterfaceType; - -extern int vga_interface_type; -#define cirrus_vga_enabled (vga_interface_type == VGA_CIRRUS) -#define std_vga_enabled (vga_interface_type == VGA_STD) -#define xenfb_enabled (vga_interface_type == VGA_XENFB) -#define vmsvga_enabled (vga_interface_type == VGA_VMWARE) -#define qxl_enabled (vga_interface_type == VGA_QXL) -#ifdef CONFIG_MARU -#define maru_vga_enabled (vga_interface_type == VGA_MARU) -#endif -extern int graphic_width; -extern int graphic_height; -extern int graphic_depth; -extern DisplayType display_type; -extern const char *keyboard_layout; -extern int win2k_install_hack; -extern int alt_grab; -extern int ctrl_grab; -extern int usb_enabled; -extern int smp_cpus; -extern int max_cpus; -extern int cursor_hide; -extern int graphic_rotate; -extern int no_quit; -extern int no_shutdown; -extern int semihosting_enabled; -extern int old_param; -extern int boot_menu; -extern uint8_t *boot_splash_filedata; -extern int boot_splash_filedata_size; -extern uint8_t qemu_extra_params_fw[2]; -extern QEMUClock *rtc_clock; - -#define MAX_NODES 64 -#define MAX_CPUMASK_BITS 255 -extern int nb_numa_nodes; -extern uint64_t node_mem[MAX_NODES]; -extern unsigned long *node_cpumask[MAX_NODES]; - -#define MAX_OPTION_ROMS 16 -typedef struct QEMUOptionRom { - const char *name; - int32_t bootindex; -} QEMUOptionRom; -extern QEMUOptionRom option_rom[MAX_OPTION_ROMS]; -extern int nb_option_roms; - -#define MAX_PROM_ENVS 128 -extern const char *prom_envs[MAX_PROM_ENVS]; -extern unsigned int nb_prom_envs; - -/* pci-hotplug */ -#ifdef CONFIG_MARU -PCIDevice *pci_device_hot_add(Monitor *mon, const QDict *qdict); -#else -void pci_device_hot_add(Monitor *mon, const QDict *qdict); -#endif -int pci_drive_hot_add(Monitor *mon, const QDict *qdict, - DriveInfo *dinfo, int type); -void do_pci_device_hot_remove(Monitor *mon, const QDict *qdict); - -/* generic hotplug */ -void drive_hot_add(Monitor *mon, const QDict *qdict); - -/* pcie aer error injection */ -void pcie_aer_inject_error_print(Monitor *mon, const QObject *data); -int do_pcie_aer_inject_error(Monitor *mon, - const QDict *qdict, QObject **ret_data); - -/* serial ports */ - -#define MAX_SERIAL_PORTS 4 - -extern CharDriverState *serial_hds[MAX_SERIAL_PORTS]; - -/* parallel ports */ - -#define MAX_PARALLEL_PORTS 3 - -extern CharDriverState *parallel_hds[MAX_PARALLEL_PORTS]; - -void do_usb_add(Monitor *mon, const QDict *qdict); -void do_usb_del(Monitor *mon, const QDict *qdict); -void usb_info(Monitor *mon); - -void rtc_change_mon_event(struct tm *tm); - -void register_devices(void); - -void add_boot_device_path(int32_t bootindex, DeviceState *dev, - const char *suffix); -char *get_boot_devices_list(uint32_t *size); -#endif diff --git a/test-qmp-input-visitor.c b/test-qmp-input-visitor.c deleted file mode 100644 index 1996e49..0000000 --- a/test-qmp-input-visitor.c +++ /dev/null @@ -1,289 +0,0 @@ -/* - * QMP Input Visitor unit-tests. - * - * Copyright (C) 2011 Red Hat Inc. - * - * Authors: - * Luiz Capitulino - * - * This work is licensed under the terms of the GNU GPL, version 2 or later. - * See the COPYING file in the top-level directory. - */ - -#include -#include - -#include "qapi/qmp-input-visitor.h" -#include "test-qapi-types.h" -#include "test-qapi-visit.h" -#include "qemu-objects.h" - -typedef struct TestInputVisitorData { - QObject *obj; - QmpInputVisitor *qiv; -} TestInputVisitorData; - -static void visitor_input_teardown(TestInputVisitorData *data, - const void *unused) -{ - qobject_decref(data->obj); - data->obj = NULL; - - if (data->qiv) { - qmp_input_visitor_cleanup(data->qiv); - data->qiv = NULL; - } -} - -/* This is provided instead of a test setup function so that the JSON - string used by the tests are kept in the test functions (and not - int main()) */ -static GCC_FMT_ATTR(2, 3) -Visitor *visitor_input_test_init(TestInputVisitorData *data, - const char *json_string, ...) -{ - Visitor *v; - va_list ap; - - va_start(ap, json_string); - data->obj = qobject_from_jsonv(json_string, &ap); - va_end(ap); - - g_assert(data->obj != NULL); - - data->qiv = qmp_input_visitor_new(data->obj); - g_assert(data->qiv != NULL); - - v = qmp_input_get_visitor(data->qiv); - g_assert(v != NULL); - - return v; -} - -static void test_visitor_in_int(TestInputVisitorData *data, - const void *unused) -{ - int64_t res = 0, value = -42; - Error *errp = NULL; - Visitor *v; - - v = visitor_input_test_init(data, "%" PRId64, value); - - visit_type_int(v, &res, NULL, &errp); - g_assert(!error_is_set(&errp)); - g_assert_cmpint(res, ==, value); -} - -static void test_visitor_in_bool(TestInputVisitorData *data, - const void *unused) -{ - Error *errp = NULL; - bool res = false; - Visitor *v; - - v = visitor_input_test_init(data, "true"); - - visit_type_bool(v, &res, NULL, &errp); - g_assert(!error_is_set(&errp)); - g_assert_cmpint(res, ==, true); -} - -static void test_visitor_in_number(TestInputVisitorData *data, - const void *unused) -{ - double res = 0, value = 3.14; - Error *errp = NULL; - Visitor *v; - - v = visitor_input_test_init(data, "%f", value); - - visit_type_number(v, &res, NULL, &errp); - g_assert(!error_is_set(&errp)); - g_assert_cmpfloat(res, ==, value); -} - -static void test_visitor_in_string(TestInputVisitorData *data, - const void *unused) -{ - char *res = NULL, *value = (char *) "Q E M U"; - Error *errp = NULL; - Visitor *v; - - v = visitor_input_test_init(data, "%s", value); - - visit_type_str(v, &res, NULL, &errp); - g_assert(!error_is_set(&errp)); - g_assert_cmpstr(res, ==, value); - - g_free(res); -} - -static void test_visitor_in_enum(TestInputVisitorData *data, - const void *unused) -{ - Error *errp = NULL; - Visitor *v; - EnumOne i; - - for (i = 0; EnumOne_lookup[i]; i++) { - EnumOne res = -1; - - v = visitor_input_test_init(data, "%s", EnumOne_lookup[i]); - - visit_type_EnumOne(v, &res, NULL, &errp); - g_assert(!error_is_set(&errp)); - g_assert_cmpint(i, ==, res); - - visitor_input_teardown(data, NULL); - } - - data->obj = NULL; - data->qiv = NULL; -} - -typedef struct TestStruct -{ - int64_t integer; - bool boolean; - char *string; -} TestStruct; - -static void visit_type_TestStruct(Visitor *v, TestStruct **obj, - const char *name, Error **errp) -{ - visit_start_struct(v, (void **)obj, "TestStruct", name, sizeof(TestStruct), - errp); - - visit_type_int(v, &(*obj)->integer, "integer", errp); - visit_type_bool(v, &(*obj)->boolean, "boolean", errp); - visit_type_str(v, &(*obj)->string, "string", errp); - - visit_end_struct(v, errp); -} - -static void test_visitor_in_struct(TestInputVisitorData *data, - const void *unused) -{ - TestStruct *p = NULL; - Error *errp = NULL; - Visitor *v; - - v = visitor_input_test_init(data, "{ 'integer': -42, 'boolean': true, 'string': 'foo' }"); - - visit_type_TestStruct(v, &p, NULL, &errp); - g_assert(!error_is_set(&errp)); - g_assert_cmpint(p->integer, ==, -42); - g_assert(p->boolean == true); - g_assert_cmpstr(p->string, ==, "foo"); - - g_free(p->string); - g_free(p); -} - -static void check_and_free_str(char *str, const char *cmp) -{ - g_assert_cmpstr(str, ==, cmp); - g_free(str); -} - -static void test_visitor_in_struct_nested(TestInputVisitorData *data, - const void *unused) -{ - UserDefNested *udp = NULL; - Error *errp = NULL; - Visitor *v; - - v = visitor_input_test_init(data, "{ 'string0': 'string0', 'dict1': { 'string1': 'string1', 'dict2': { 'userdef1': { 'integer': 42, 'string': 'string' }, 'string2': 'string2'}}}"); - - visit_type_UserDefNested(v, &udp, NULL, &errp); - g_assert(!error_is_set(&errp)); - - check_and_free_str(udp->string0, "string0"); - check_and_free_str(udp->dict1.string1, "string1"); - g_assert_cmpint(udp->dict1.dict2.userdef1->integer, ==, 42); - check_and_free_str(udp->dict1.dict2.userdef1->string, "string"); - check_and_free_str(udp->dict1.dict2.string2, "string2"); - g_assert(udp->dict1.has_dict3 == false); - - g_free(udp->dict1.dict2.userdef1); - g_free(udp); -} - -static void test_visitor_in_list(TestInputVisitorData *data, - const void *unused) -{ - UserDefOneList *item, *head = NULL; - Error *errp = NULL; - Visitor *v; - int i; - - v = visitor_input_test_init(data, "[ { 'string': 'string0', 'integer': 42 }, { 'string': 'string1', 'integer': 43 }, { 'string': 'string2', 'integer': 44 } ]"); - - visit_type_UserDefOneList(v, &head, NULL, &errp); - g_assert(!error_is_set(&errp)); - g_assert(head != NULL); - - for (i = 0, item = head; item; item = item->next, i++) { - char string[12]; - - snprintf(string, sizeof(string), "string%d", i); - g_assert_cmpstr(item->value->string, ==, string); - g_assert_cmpint(item->value->integer, ==, 42 + i); - } - - qapi_free_UserDefOneList(head); -} - -static void test_visitor_in_union(TestInputVisitorData *data, - const void *unused) -{ - Visitor *v; - Error *err = NULL; - UserDefUnion *tmp; - - v = visitor_input_test_init(data, "{ 'type': 'b', 'data' : { 'integer': 42 } }"); - - visit_type_UserDefUnion(v, &tmp, NULL, &err); - g_assert(err == NULL); - g_assert_cmpint(tmp->kind, ==, USER_DEF_UNION_KIND_B); - g_assert_cmpint(tmp->b->integer, ==, 42); - qapi_free_UserDefUnion(tmp); -} - -static void input_visitor_test_add(const char *testpath, - TestInputVisitorData *data, - void (*test_func)(TestInputVisitorData *data, const void *user_data)) -{ - g_test_add(testpath, TestInputVisitorData, data, NULL, test_func, - visitor_input_teardown); -} - -int main(int argc, char **argv) -{ - TestInputVisitorData in_visitor_data; - - g_test_init(&argc, &argv, NULL); - - input_visitor_test_add("/visitor/input/int", - &in_visitor_data, test_visitor_in_int); - input_visitor_test_add("/visitor/input/bool", - &in_visitor_data, test_visitor_in_bool); - input_visitor_test_add("/visitor/input/number", - &in_visitor_data, test_visitor_in_number); - input_visitor_test_add("/visitor/input/string", - &in_visitor_data, test_visitor_in_string); - input_visitor_test_add("/visitor/input/enum", - &in_visitor_data, test_visitor_in_enum); - input_visitor_test_add("/visitor/input/struct", - &in_visitor_data, test_visitor_in_struct); - input_visitor_test_add("/visitor/input/struct-nested", - &in_visitor_data, test_visitor_in_struct_nested); - input_visitor_test_add("/visitor/input/list", - &in_visitor_data, test_visitor_in_list); - input_visitor_test_add("/visitor/input/union", - &in_visitor_data, test_visitor_in_union); - - g_test_run(); - - return 0; -} diff --git a/test-qmp-output-visitor.c b/test-qmp-output-visitor.c deleted file mode 100644 index 4d6c4d4..0000000 --- a/test-qmp-output-visitor.c +++ /dev/null @@ -1,457 +0,0 @@ -/* - * QMP Output Visitor unit-tests. - * - * Copyright (C) 2011 Red Hat Inc. - * - * Authors: - * Luiz Capitulino - * - * This work is licensed under the terms of the GNU GPL, version 2 or later. - * See the COPYING file in the top-level directory. - */ - -#include - -#include "qapi/qmp-output-visitor.h" -#include "test-qapi-types.h" -#include "test-qapi-visit.h" -#include "qemu-objects.h" - -typedef struct TestOutputVisitorData { - QmpOutputVisitor *qov; - Visitor *ov; -} TestOutputVisitorData; - -static void visitor_output_setup(TestOutputVisitorData *data, - const void *unused) -{ - data->qov = qmp_output_visitor_new(); - g_assert(data->qov != NULL); - - data->ov = qmp_output_get_visitor(data->qov); - g_assert(data->ov != NULL); -} - -static void visitor_output_teardown(TestOutputVisitorData *data, - const void *unused) -{ - qmp_output_visitor_cleanup(data->qov); - data->qov = NULL; - data->ov = NULL; -} - -static void test_visitor_out_int(TestOutputVisitorData *data, - const void *unused) -{ - int64_t value = -42; - Error *errp = NULL; - QObject *obj; - - visit_type_int(data->ov, &value, NULL, &errp); - g_assert(error_is_set(&errp) == 0); - - obj = qmp_output_get_qobject(data->qov); - g_assert(obj != NULL); - g_assert(qobject_type(obj) == QTYPE_QINT); - g_assert_cmpint(qint_get_int(qobject_to_qint(obj)), ==, value); - - qobject_decref(obj); -} - -static void test_visitor_out_bool(TestOutputVisitorData *data, - const void *unused) -{ - Error *errp = NULL; - bool value = true; - QObject *obj; - - visit_type_bool(data->ov, &value, NULL, &errp); - g_assert(error_is_set(&errp) == 0); - - obj = qmp_output_get_qobject(data->qov); - g_assert(obj != NULL); - g_assert(qobject_type(obj) == QTYPE_QBOOL); - g_assert(qbool_get_int(qobject_to_qbool(obj)) == value); - - qobject_decref(obj); -} - -static void test_visitor_out_number(TestOutputVisitorData *data, - const void *unused) -{ - double value = 3.14; - Error *errp = NULL; - QObject *obj; - - visit_type_number(data->ov, &value, NULL, &errp); - g_assert(error_is_set(&errp) == 0); - - obj = qmp_output_get_qobject(data->qov); - g_assert(obj != NULL); - g_assert(qobject_type(obj) == QTYPE_QFLOAT); - g_assert(qfloat_get_double(qobject_to_qfloat(obj)) == value); - - qobject_decref(obj); -} - -static void test_visitor_out_string(TestOutputVisitorData *data, - const void *unused) -{ - char *string = (char *) "Q E M U"; - Error *errp = NULL; - QObject *obj; - - visit_type_str(data->ov, &string, NULL, &errp); - g_assert(error_is_set(&errp) == 0); - - obj = qmp_output_get_qobject(data->qov); - g_assert(obj != NULL); - g_assert(qobject_type(obj) == QTYPE_QSTRING); - g_assert_cmpstr(qstring_get_str(qobject_to_qstring(obj)), ==, string); - - qobject_decref(obj); -} - -static void test_visitor_out_no_string(TestOutputVisitorData *data, - const void *unused) -{ - char *string = NULL; - Error *errp = NULL; - QObject *obj; - - /* A null string should return "" */ - visit_type_str(data->ov, &string, NULL, &errp); - g_assert(error_is_set(&errp) == 0); - - obj = qmp_output_get_qobject(data->qov); - g_assert(obj != NULL); - g_assert(qobject_type(obj) == QTYPE_QSTRING); - g_assert_cmpstr(qstring_get_str(qobject_to_qstring(obj)), ==, ""); - - qobject_decref(obj); -} - -static void test_visitor_out_enum(TestOutputVisitorData *data, - const void *unused) -{ - Error *errp = NULL; - QObject *obj; - EnumOne i; - - for (i = 0; i < ENUM_ONE_MAX; i++) { - visit_type_EnumOne(data->ov, &i, "unused", &errp); - g_assert(!error_is_set(&errp)); - - obj = qmp_output_get_qobject(data->qov); - g_assert(obj != NULL); - g_assert(qobject_type(obj) == QTYPE_QSTRING); - g_assert_cmpstr(qstring_get_str(qobject_to_qstring(obj)), ==, - EnumOne_lookup[i]); - qobject_decref(obj); - } -} - -static void test_visitor_out_enum_errors(TestOutputVisitorData *data, - const void *unused) -{ - EnumOne i, bad_values[] = { ENUM_ONE_MAX, -1 }; - Error *errp; - - for (i = 0; i < ARRAY_SIZE(bad_values) ; i++) { - errp = NULL; - visit_type_EnumOne(data->ov, &bad_values[i], "unused", &errp); - g_assert(error_is_set(&errp) == true); - error_free(errp); - } -} - -typedef struct TestStruct -{ - int64_t integer; - bool boolean; - char *string; -} TestStruct; - -static void visit_type_TestStruct(Visitor *v, TestStruct **obj, - const char *name, Error **errp) -{ - visit_start_struct(v, (void **)obj, "TestStruct", name, sizeof(TestStruct), - errp); - - visit_type_int(v, &(*obj)->integer, "integer", errp); - visit_type_bool(v, &(*obj)->boolean, "boolean", errp); - visit_type_str(v, &(*obj)->string, "string", errp); - - visit_end_struct(v, errp); -} - -static void test_visitor_out_struct(TestOutputVisitorData *data, - const void *unused) -{ - TestStruct test_struct = { .integer = 42, - .boolean = false, - .string = (char *) "foo"}; - TestStruct *p = &test_struct; - Error *errp = NULL; - QObject *obj; - QDict *qdict; - - visit_type_TestStruct(data->ov, &p, NULL, &errp); - g_assert(!error_is_set(&errp)); - - obj = qmp_output_get_qobject(data->qov); - g_assert(obj != NULL); - g_assert(qobject_type(obj) == QTYPE_QDICT); - - qdict = qobject_to_qdict(obj); - g_assert_cmpint(qdict_size(qdict), ==, 3); - g_assert_cmpint(qdict_get_int(qdict, "integer"), ==, 42); - g_assert_cmpint(qdict_get_bool(qdict, "boolean"), ==, 0); - g_assert_cmpstr(qdict_get_str(qdict, "string"), ==, "foo"); - - QDECREF(qdict); -} - -static void test_visitor_out_struct_nested(TestOutputVisitorData *data, - const void *unused) -{ - int64_t value = 42; - Error *errp = NULL; - UserDefNested *ud2; - QObject *obj; - QDict *qdict, *dict1, *dict2, *dict3, *userdef; - const char *string = "user def string"; - const char *strings[] = { "forty two", "forty three", "forty four", - "forty five" }; - - ud2 = g_malloc0(sizeof(*ud2)); - ud2->string0 = g_strdup(strings[0]); - - ud2->dict1.string1 = g_strdup(strings[1]); - ud2->dict1.dict2.userdef1 = g_malloc0(sizeof(UserDefOne)); - ud2->dict1.dict2.userdef1->string = g_strdup(string); - ud2->dict1.dict2.userdef1->integer = value; - ud2->dict1.dict2.string2 = g_strdup(strings[2]); - - ud2->dict1.has_dict3 = true; - ud2->dict1.dict3.userdef2 = g_malloc0(sizeof(UserDefOne)); - ud2->dict1.dict3.userdef2->string = g_strdup(string); - ud2->dict1.dict3.userdef2->integer = value; - ud2->dict1.dict3.string3 = g_strdup(strings[3]); - - visit_type_UserDefNested(data->ov, &ud2, "unused", &errp); - g_assert(!error_is_set(&errp)); - - obj = qmp_output_get_qobject(data->qov); - g_assert(obj != NULL); - g_assert(qobject_type(obj) == QTYPE_QDICT); - - qdict = qobject_to_qdict(obj); - g_assert_cmpint(qdict_size(qdict), ==, 2); - g_assert_cmpstr(qdict_get_str(qdict, "string0"), ==, strings[0]); - - dict1 = qdict_get_qdict(qdict, "dict1"); - g_assert_cmpint(qdict_size(dict1), ==, 3); - g_assert_cmpstr(qdict_get_str(dict1, "string1"), ==, strings[1]); - - dict2 = qdict_get_qdict(dict1, "dict2"); - g_assert_cmpint(qdict_size(dict2), ==, 2); - g_assert_cmpstr(qdict_get_str(dict2, "string2"), ==, strings[2]); - userdef = qdict_get_qdict(dict2, "userdef1"); - g_assert_cmpint(qdict_size(userdef), ==, 2); - g_assert_cmpint(qdict_get_int(userdef, "integer"), ==, value); - g_assert_cmpstr(qdict_get_str(userdef, "string"), ==, string); - - dict3 = qdict_get_qdict(dict1, "dict3"); - g_assert_cmpint(qdict_size(dict3), ==, 2); - g_assert_cmpstr(qdict_get_str(dict3, "string3"), ==, strings[3]); - userdef = qdict_get_qdict(dict3, "userdef2"); - g_assert_cmpint(qdict_size(userdef), ==, 2); - g_assert_cmpint(qdict_get_int(userdef, "integer"), ==, value); - g_assert_cmpstr(qdict_get_str(userdef, "string"), ==, string); - - QDECREF(qdict); - qapi_free_UserDefNested(ud2); -} - -typedef struct TestStructList -{ - TestStruct *value; - struct TestStructList *next; -} TestStructList; - -static void visit_type_TestStructList(Visitor *v, TestStructList **obj, - const char *name, Error **errp) -{ - GenericList *i, **head = (GenericList **)obj; - - visit_start_list(v, name, errp); - - for (*head = i = visit_next_list(v, head, errp); i; i = visit_next_list(v, &i, errp)) { - TestStructList *native_i = (TestStructList *)i; - visit_type_TestStruct(v, &native_i->value, NULL, errp); - } - - visit_end_list(v, errp); -} - -static void test_visitor_out_list(TestOutputVisitorData *data, - const void *unused) -{ - char *value_str = (char *) "list value"; - TestStructList *p, *head = NULL; - const int max_items = 10; - bool value_bool = true; - int value_int = 10; - Error *errp = NULL; - QListEntry *entry; - QObject *obj; - QList *qlist; - int i; - - for (i = 0; i < max_items; i++) { - p = g_malloc0(sizeof(*p)); - p->value = g_malloc0(sizeof(*p->value)); - p->value->integer = value_int; - p->value->boolean = value_bool; - p->value->string = value_str; - - p->next = head; - head = p; - } - - visit_type_TestStructList(data->ov, &head, NULL, &errp); - g_assert(!error_is_set(&errp)); - - obj = qmp_output_get_qobject(data->qov); - g_assert(obj != NULL); - g_assert(qobject_type(obj) == QTYPE_QLIST); - - qlist = qobject_to_qlist(obj); - g_assert(!qlist_empty(qlist)); - - i = 0; - QLIST_FOREACH_ENTRY(qlist, entry) { - QDict *qdict; - - g_assert(qobject_type(entry->value) == QTYPE_QDICT); - qdict = qobject_to_qdict(entry->value); - g_assert_cmpint(qdict_size(qdict), ==, 3); - g_assert_cmpint(qdict_get_int(qdict, "integer"), ==, value_int); - g_assert_cmpint(qdict_get_bool(qdict, "boolean"), ==, value_bool); - g_assert_cmpstr(qdict_get_str(qdict, "string"), ==, value_str); - i++; - } - g_assert_cmpint(i, ==, max_items); - - QDECREF(qlist); - - for (p = head; p;) { - TestStructList *tmp = p->next; - g_free(p->value); - g_free(p); - p = tmp; - } -} - -static void test_visitor_out_list_qapi_free(TestOutputVisitorData *data, - const void *unused) -{ - UserDefNestedList *p, *head = NULL; - const char string[] = "foo bar"; - int i, max_count = 1024; - - for (i = 0; i < max_count; i++) { - p = g_malloc0(sizeof(*p)); - p->value = g_malloc0(sizeof(*p->value)); - - p->value->string0 = g_strdup(string); - p->value->dict1.string1 = g_strdup(string); - p->value->dict1.dict2.userdef1 = g_malloc0(sizeof(UserDefOne)); - p->value->dict1.dict2.userdef1->string = g_strdup(string); - p->value->dict1.dict2.userdef1->integer = 42; - p->value->dict1.dict2.string2 = g_strdup(string); - p->value->dict1.has_dict3 = false; - - p->next = head; - head = p; - } - - qapi_free_UserDefNestedList(head); -} - -static void test_visitor_out_union(TestOutputVisitorData *data, - const void *unused) -{ - QObject *arg, *qvalue; - QDict *qdict, *value; - - Error *err = NULL; - - UserDefUnion *tmp = g_malloc0(sizeof(UserDefUnion)); - tmp->kind = USER_DEF_UNION_KIND_A; - tmp->a = g_malloc0(sizeof(UserDefA)); - tmp->a->boolean = true; - - visit_type_UserDefUnion(data->ov, &tmp, NULL, &err); - g_assert(err == NULL); - arg = qmp_output_get_qobject(data->qov); - - g_assert(qobject_type(arg) == QTYPE_QDICT); - qdict = qobject_to_qdict(arg); - - g_assert_cmpstr(qdict_get_str(qdict, "type"), ==, "a"); - - qvalue = qdict_get(qdict, "data"); - g_assert(data != NULL); - g_assert(qobject_type(qvalue) == QTYPE_QDICT); - value = qobject_to_qdict(qvalue); - g_assert_cmpint(qdict_get_bool(value, "boolean"), ==, true); - - qapi_free_UserDefUnion(tmp); - QDECREF(qdict); -} - -static void output_visitor_test_add(const char *testpath, - TestOutputVisitorData *data, - void (*test_func)(TestOutputVisitorData *data, const void *user_data)) -{ - g_test_add(testpath, TestOutputVisitorData, data, visitor_output_setup, - test_func, visitor_output_teardown); -} - -int main(int argc, char **argv) -{ - TestOutputVisitorData out_visitor_data; - - g_test_init(&argc, &argv, NULL); - - output_visitor_test_add("/visitor/output/int", - &out_visitor_data, test_visitor_out_int); - output_visitor_test_add("/visitor/output/bool", - &out_visitor_data, test_visitor_out_bool); - output_visitor_test_add("/visitor/output/number", - &out_visitor_data, test_visitor_out_number); - output_visitor_test_add("/visitor/output/string", - &out_visitor_data, test_visitor_out_string); - output_visitor_test_add("/visitor/output/no-string", - &out_visitor_data, test_visitor_out_no_string); - output_visitor_test_add("/visitor/output/enum", - &out_visitor_data, test_visitor_out_enum); - output_visitor_test_add("/visitor/output/enum-errors", - &out_visitor_data, test_visitor_out_enum_errors); - output_visitor_test_add("/visitor/output/struct", - &out_visitor_data, test_visitor_out_struct); - output_visitor_test_add("/visitor/output/struct-nested", - &out_visitor_data, test_visitor_out_struct_nested); - output_visitor_test_add("/visitor/output/list", - &out_visitor_data, test_visitor_out_list); - output_visitor_test_add("/visitor/output/list-qapi-free", - &out_visitor_data, test_visitor_out_list_qapi_free); - output_visitor_test_add("/visitor/output/union", - &out_visitor_data, test_visitor_out_union); - - g_test_run(); - - return 0; -} diff --git a/test-string-input-visitor.c b/test-string-input-visitor.c deleted file mode 100644 index 5370e32..0000000 --- a/test-string-input-visitor.c +++ /dev/null @@ -1,195 +0,0 @@ -/* - * String Input Visitor unit-tests. - * - * Copyright (C) 2012 Red Hat Inc. - * - * Authors: - * Paolo Bonzini (based on test-qmp-input-visitor) - * - * This work is licensed under the terms of the GNU GPL, version 2 or later. - * See the COPYING file in the top-level directory. - */ - -#include -#include - -#include "qapi/string-input-visitor.h" -#include "test-qapi-types.h" -#include "test-qapi-visit.h" -#include "qemu-objects.h" - -typedef struct TestInputVisitorData { - StringInputVisitor *siv; -} TestInputVisitorData; - -static void visitor_input_teardown(TestInputVisitorData *data, - const void *unused) -{ - if (data->siv) { - string_input_visitor_cleanup(data->siv); - data->siv = NULL; - } -} - -/* This is provided instead of a test setup function so that the JSON - string used by the tests are kept in the test functions (and not - int main()) */ -static -Visitor *visitor_input_test_init(TestInputVisitorData *data, - const char *string) -{ - Visitor *v; - - data->siv = string_input_visitor_new(string); - g_assert(data->siv != NULL); - - v = string_input_get_visitor(data->siv); - g_assert(v != NULL); - - return v; -} - -static void test_visitor_in_int(TestInputVisitorData *data, - const void *unused) -{ - int64_t res = 0, value = -42; - Error *errp = NULL; - Visitor *v; - - v = visitor_input_test_init(data, "-42"); - - visit_type_int(v, &res, NULL, &errp); - g_assert(!error_is_set(&errp)); - g_assert_cmpint(res, ==, value); -} - -static void test_visitor_in_bool(TestInputVisitorData *data, - const void *unused) -{ - Error *errp = NULL; - bool res = false; - Visitor *v; - - v = visitor_input_test_init(data, "true"); - - visit_type_bool(v, &res, NULL, &errp); - g_assert(!error_is_set(&errp)); - g_assert_cmpint(res, ==, true); - visitor_input_teardown(data, unused); - - v = visitor_input_test_init(data, "yes"); - - visit_type_bool(v, &res, NULL, &errp); - g_assert(!error_is_set(&errp)); - g_assert_cmpint(res, ==, true); - visitor_input_teardown(data, unused); - - v = visitor_input_test_init(data, "on"); - - visit_type_bool(v, &res, NULL, &errp); - g_assert(!error_is_set(&errp)); - g_assert_cmpint(res, ==, true); - visitor_input_teardown(data, unused); - - v = visitor_input_test_init(data, "false"); - - visit_type_bool(v, &res, NULL, &errp); - g_assert(!error_is_set(&errp)); - g_assert_cmpint(res, ==, false); - visitor_input_teardown(data, unused); - - v = visitor_input_test_init(data, "no"); - - visit_type_bool(v, &res, NULL, &errp); - g_assert(!error_is_set(&errp)); - g_assert_cmpint(res, ==, false); - visitor_input_teardown(data, unused); - - v = visitor_input_test_init(data, "off"); - - visit_type_bool(v, &res, NULL, &errp); - g_assert(!error_is_set(&errp)); - g_assert_cmpint(res, ==, false); -} - -static void test_visitor_in_number(TestInputVisitorData *data, - const void *unused) -{ - double res = 0, value = 3.14; - Error *errp = NULL; - Visitor *v; - - v = visitor_input_test_init(data, "3.14"); - - visit_type_number(v, &res, NULL, &errp); - g_assert(!error_is_set(&errp)); - g_assert_cmpfloat(res, ==, value); -} - -static void test_visitor_in_string(TestInputVisitorData *data, - const void *unused) -{ - char *res = NULL, *value = (char *) "Q E M U"; - Error *errp = NULL; - Visitor *v; - - v = visitor_input_test_init(data, value); - - visit_type_str(v, &res, NULL, &errp); - g_assert(!error_is_set(&errp)); - g_assert_cmpstr(res, ==, value); - - g_free(res); -} - -static void test_visitor_in_enum(TestInputVisitorData *data, - const void *unused) -{ - Error *errp = NULL; - Visitor *v; - EnumOne i; - - for (i = 0; EnumOne_lookup[i]; i++) { - EnumOne res = -1; - - v = visitor_input_test_init(data, EnumOne_lookup[i]); - - visit_type_EnumOne(v, &res, NULL, &errp); - g_assert(!error_is_set(&errp)); - g_assert_cmpint(i, ==, res); - - visitor_input_teardown(data, NULL); - } - - data->siv = NULL; -} - -static void input_visitor_test_add(const char *testpath, - TestInputVisitorData *data, - void (*test_func)(TestInputVisitorData *data, const void *user_data)) -{ - g_test_add(testpath, TestInputVisitorData, data, NULL, test_func, - visitor_input_teardown); -} - -int main(int argc, char **argv) -{ - TestInputVisitorData in_visitor_data; - - g_test_init(&argc, &argv, NULL); - - input_visitor_test_add("/string-visitor/input/int", - &in_visitor_data, test_visitor_in_int); - input_visitor_test_add("/string-visitor/input/bool", - &in_visitor_data, test_visitor_in_bool); - input_visitor_test_add("/string-visitor/input/number", - &in_visitor_data, test_visitor_in_number); - input_visitor_test_add("/string-visitor/input/string", - &in_visitor_data, test_visitor_in_string); - input_visitor_test_add("/string-visitor/input/enum", - &in_visitor_data, test_visitor_in_enum); - - g_test_run(); - - return 0; -} diff --git a/test-string-output-visitor.c b/test-string-output-visitor.c deleted file mode 100644 index 22909b8..0000000 --- a/test-string-output-visitor.c +++ /dev/null @@ -1,188 +0,0 @@ -/* - * String Output Visitor unit-tests. - * - * Copyright (C) 2012 Red Hat Inc. - * - * Authors: - * Paolo Bonzini (based on test-qmp-output-visitor) - * - * This work is licensed under the terms of the GNU GPL, version 2 or later. - * See the COPYING file in the top-level directory. - */ - -#include - -#include "qapi/string-output-visitor.h" -#include "test-qapi-types.h" -#include "test-qapi-visit.h" -#include "qemu-objects.h" - -typedef struct TestOutputVisitorData { - StringOutputVisitor *sov; - Visitor *ov; -} TestOutputVisitorData; - -static void visitor_output_setup(TestOutputVisitorData *data, - const void *unused) -{ - data->sov = string_output_visitor_new(); - g_assert(data->sov != NULL); - - data->ov = string_output_get_visitor(data->sov); - g_assert(data->ov != NULL); -} - -static void visitor_output_teardown(TestOutputVisitorData *data, - const void *unused) -{ - string_output_visitor_cleanup(data->sov); - data->sov = NULL; - data->ov = NULL; -} - -static void test_visitor_out_int(TestOutputVisitorData *data, - const void *unused) -{ - int64_t value = -42; - Error *errp = NULL; - char *str; - - visit_type_int(data->ov, &value, NULL, &errp); - g_assert(error_is_set(&errp) == 0); - - str = string_output_get_string(data->sov); - g_assert(str != NULL); - g_assert_cmpstr(str, ==, "-42"); - g_free(str); -} - -static void test_visitor_out_bool(TestOutputVisitorData *data, - const void *unused) -{ - Error *errp = NULL; - bool value = true; - char *str; - - visit_type_bool(data->ov, &value, NULL, &errp); - g_assert(error_is_set(&errp) == 0); - - str = string_output_get_string(data->sov); - g_assert(str != NULL); - g_assert_cmpstr(str, ==, "true"); - g_free(str); -} - -static void test_visitor_out_number(TestOutputVisitorData *data, - const void *unused) -{ - double value = 3.14; - Error *errp = NULL; - char *str; - - visit_type_number(data->ov, &value, NULL, &errp); - g_assert(error_is_set(&errp) == 0); - - str = string_output_get_string(data->sov); - g_assert(str != NULL); - g_assert_cmpstr(str, ==, "3.14"); - g_free(str); -} - -static void test_visitor_out_string(TestOutputVisitorData *data, - const void *unused) -{ - char *string = (char *) "Q E M U"; - Error *errp = NULL; - char *str; - - visit_type_str(data->ov, &string, NULL, &errp); - g_assert(error_is_set(&errp) == 0); - - str = string_output_get_string(data->sov); - g_assert(str != NULL); - g_assert_cmpstr(str, ==, string); - g_free(str); -} - -static void test_visitor_out_no_string(TestOutputVisitorData *data, - const void *unused) -{ - char *string = NULL; - Error *errp = NULL; - char *str; - - /* A null string should return "" */ - visit_type_str(data->ov, &string, NULL, &errp); - g_assert(error_is_set(&errp) == 0); - - str = string_output_get_string(data->sov); - g_assert(str != NULL); - g_assert_cmpstr(str, ==, ""); - g_free(str); -} - -static void test_visitor_out_enum(TestOutputVisitorData *data, - const void *unused) -{ - Error *errp = NULL; - char *str; - EnumOne i; - - for (i = 0; i < ENUM_ONE_MAX; i++) { - visit_type_EnumOne(data->ov, &i, "unused", &errp); - g_assert(!error_is_set(&errp)); - - str = string_output_get_string(data->sov); - g_assert(str != NULL); - g_assert_cmpstr(str, ==, EnumOne_lookup[i]); - g_free(str); - } -} - -static void test_visitor_out_enum_errors(TestOutputVisitorData *data, - const void *unused) -{ - EnumOne i, bad_values[] = { ENUM_ONE_MAX, -1 }; - Error *errp; - - for (i = 0; i < ARRAY_SIZE(bad_values) ; i++) { - errp = NULL; - visit_type_EnumOne(data->ov, &bad_values[i], "unused", &errp); - g_assert(error_is_set(&errp) == true); - error_free(errp); - } -} - -static void output_visitor_test_add(const char *testpath, - TestOutputVisitorData *data, - void (*test_func)(TestOutputVisitorData *data, const void *user_data)) -{ - g_test_add(testpath, TestOutputVisitorData, data, visitor_output_setup, - test_func, visitor_output_teardown); -} - -int main(int argc, char **argv) -{ - TestOutputVisitorData out_visitor_data; - - g_test_init(&argc, &argv, NULL); - - output_visitor_test_add("/string-visitor/output/int", - &out_visitor_data, test_visitor_out_int); - output_visitor_test_add("/string-visitor/output/bool", - &out_visitor_data, test_visitor_out_bool); - output_visitor_test_add("/string-visitor/output/number", - &out_visitor_data, test_visitor_out_number); - output_visitor_test_add("/string-visitor/output/string", - &out_visitor_data, test_visitor_out_string); - output_visitor_test_add("/string-visitor/output/no-string", - &out_visitor_data, test_visitor_out_no_string); - output_visitor_test_add("/string-visitor/output/enum", - &out_visitor_data, test_visitor_out_enum); - output_visitor_test_add("/string-visitor/output/enum-errors", - &out_visitor_data, test_visitor_out_enum_errors); - - g_test_run(); - - return 0; -} diff --git a/ui/input.c b/ui/input.c index 8ca1a03..b4a43e8 100644 --- a/ui/input.c +++ b/ui/input.c @@ -28,6 +28,9 @@ #include "qapi/error.h" #include "qmp-commands.h" #include "qapi-types.h" +//#include "tizen/src/debug_ch.h" + +//MULTI_DEBUG_CHANNEL(tizen, input); struct QEMUPutMouseEntry { QEMUPutMouseEvent *qemu_put_mouse_event; @@ -61,6 +64,10 @@ static QTAILQ_HEAD(, QEMUPutMouseEntry) mouse_handlers = QTAILQ_HEAD_INITIALIZER(mouse_handlers); static NotifierList mouse_mode_notifiers = NOTIFIER_LIST_INITIALIZER(mouse_mode_notifiers); +#ifdef CONFIG_MARU +static QTAILQ_HEAD(, QEMUPutKbdEntry) ps2kbd_handlers = + QTAILQ_HEAD_INITIALIZER(ps2kbd_handlers); +#endif static const int key_defs[] = { [Q_KEY_CODE_SHIFT] = 0x2a, @@ -327,6 +334,25 @@ void qemu_remove_kbd_event_handler(QEMUPutKbdEntry *entry) QTAILQ_REMOVE(&kbd_handlers, entry, next); } +#ifdef CONFIG_MARU +/* use ps2kbd device as a hardkey device. */ +QEMUPutKbdEntry *qemu_add_ps2kbd_event_handler(QEMUPutKBDEvent *func, void *opaque) +{ + QEMUPutKbdEntry *entry; + + entry = g_malloc0(sizeof(QEMUPutKbdEntry)); + entry->put_kbd = func; + entry->opaque = opaque; + QTAILQ_INSERT_HEAD(&ps2kbd_handlers, entry, next); + return entry; +} + +void qemu_remove_ps2kbd_event_handler(QEMUPutKbdEntry *entry) +{ + QTAILQ_REMOVE(&ps2kbd_handlers, entry, next); +} +#endif + static void check_mode_change(void) { static int current_is_absolute, current_has_absolute; @@ -417,6 +443,16 @@ void kbd_put_keycode(int keycode) entry->put_kbd(entry->opaque, keycode); } } +#ifdef CONFIG_MARU +void kbd_put_keycode(int keycode) +{ + QEMUPutKbdEntry *entry = QTAILQ_FIRST(&ps2kbd_handlers); + + if (entry) { + entry->put_kbd(entry->opaque, keycode); + } +} +#endif void kbd_put_ledstate(int ledstate) { @@ -440,11 +476,32 @@ void kbd_mouse_event(int dx, int dy, int dz, int buttons_state) if (QTAILQ_EMPTY(&mouse_handlers)) { return; } +#if defined (CONFIG_MARU) + QTAILQ_FOREACH(entry, &mouse_handlers, node) { + /* if mouse event is wheelup ,wheeldown or move + then go to ps2 mouse event(index == 0) */ + if((buttons_state > 3 && entry->index == 0)) { + //INFO("input device: %s, event: %d\n", entry->qemu_put_mouse_event_name, buttons_state); + buttons_state = 0;~ + mouse_event = entry->qemu_put_mouse_event; + mouse_event_opaque = entry->qemu_put_mouse_event_opaque; + break; + } + } + /* other events(mouse up, down and drag), go to touch screen */ + if(!entry) { + entry = QTAILQ_FIRST(&mouse_handlers); + mouse_event = entry->qemu_put_mouse_event; + mouse_event_opaque = entry->qemu_put_mouse_event_opaque; + //INFO("input device: %s, event: %d\n", entry->qemu_put_mouse_event_name, buttons_state); + } +#else entry = QTAILQ_FIRST(&mouse_handlers); mouse_event = entry->qemu_put_mouse_event; mouse_event_opaque = entry->qemu_put_mouse_event_opaque; +#endif if (mouse_event) { if (entry->qemu_put_mouse_event_absolute) { diff --git a/util/oslib-posix.c b/util/oslib-posix.c index 631a1de..8303b16 100644 --- a/util/oslib-posix.c +++ b/util/oslib-posix.c @@ -53,6 +53,10 @@ extern int daemon(int, int); #include "qemu/sockets.h" #include +#ifdef CONFIG_MARU +#include "../../tizen/src/skin/maruskin_client.h" +#endif + #ifdef CONFIG_LINUX #include #endif @@ -75,6 +79,22 @@ void *qemu_oom_check(void *ptr) { if (ptr == NULL) { fprintf(stderr, "Failed to allocate memory: %s\n", strerror(errno)); +#ifdef CONFIG_MARU + char _msg[] = "Failed to allocate memory in qemu."; + char cmd[JAVA_MAX_COMMAND_LENGTH] = { 0, }; + + int len = strlen(JAVA_EXEFILE_PATH) + strlen(JAVA_EXEOPTION) + strlen(JAR_SKINFILE) + + strlen(JAVA_SIMPLEMODE_OPTION) + strlen(_msg) + 7; + if (len > JAVA_MAX_COMMAND_LENGTH) { + len = JAVA_MAX_COMMAND_LENGTH; + } + + snprintf(cmd, len, "%s %s %s %s=\"%s\"", + JAVA_EXEFILE_PATH, JAVA_EXEOPTION, JAR_SKINFILE, JAVA_SIMPLEMODE_OPTION, _msg); + if(system(cmd) == -1) { + // TODO: Handle error...~ + } +#endif abort(); } return ptr; diff --git a/util/oslib-win32.c b/util/oslib-win32.c index df2ecbd..bdd37bc 100644 --- a/util/oslib-win32.c +++ b/util/oslib-win32.c @@ -32,10 +32,110 @@ #include "trace.h" #include "qemu/sockets.h" +#ifdef CONFIG_MARU +#include "../../tizen/src/skin/maruskin_client.h" +#endif + +typedef BOOL (WINAPI *LPFN_ISWOW64PROCESS) (HANDLE, PBOOL); +LPFN_ISWOW64PROCESS fnIsWow64Process; + +int is_wow64_temp(void) +{ + int result = 0; + + /* IsWow64Process is not available on all supported versions of Windows. + Use GetModuleHandle to get a handle to the DLL that contains + the function and GetProcAddress to get a pointer to the function + if available. */ + + fnIsWow64Process = (LPFN_ISWOW64PROCESS)GetProcAddress( + GetModuleHandle(TEXT("kernel32")), "IsWow64Process"); + + if (NULL != fnIsWow64Process) { + if (!fnIsWow64Process(GetCurrentProcess(),&result)) { + /* handle error */ + /* INFO("Can not find 'IsWow64Process'\n"); */ + } + } + return result; +} + +int get_java_path_temp(char** java_path) +{ + HKEY hKeyNew; + HKEY hKey; + //char strJavaRuntimePath[JAVA_MAX_COMMAND_LENGTH] = {0}; + char strChoosenName[JAVA_MAX_COMMAND_LENGTH] = {0}; + char strSubKeyName[JAVA_MAX_COMMAND_LENGTH] = {0}; + char strJavaHome[JAVA_MAX_COMMAND_LENGTH] = {0}; + int index; + DWORD dwSubKeyNameMax = JAVA_MAX_COMMAND_LENGTH; + DWORD dwBufLen = JAVA_MAX_COMMAND_LENGTH; + + RegOpenKeyEx(HKEY_LOCAL_MACHINE, "SOFTWARE\\JavaSoft\\Java Runtime Environment", 0, + KEY_QUERY_VALUE | KEY_ENUMERATE_SUB_KEYS | MY_KEY_WOW64_64KEY, &hKey); + RegEnumKeyEx(hKey, 0, (LPSTR)strSubKeyName, &dwSubKeyNameMax, + NULL, NULL, NULL, NULL); + strcpy(strChoosenName, strSubKeyName); + + index = 1; + while (ERROR_SUCCESS == RegEnumKeyEx(hKey, index, + (LPSTR)strSubKeyName, &dwSubKeyNameMax, + NULL, NULL, NULL, NULL)) { + if (strcmp(strChoosenName, strSubKeyName) < 0) { + strcpy(strChoosenName, strSubKeyName); + } + index++; + } + + RegOpenKeyEx(hKey, strChoosenName, 0, KEY_QUERY_VALUE | MY_KEY_WOW64_64KEY, + &hKeyNew); + RegQueryValueEx(hKeyNew, "JavaHome", NULL, NULL, (LPBYTE)strJavaHome, &dwBufLen); + RegCloseKey(hKey); + + if (strJavaHome[0] != '\0') { + sprintf(*java_path, "\"%s\\bin\\java\"", strJavaHome); + //strcpy(*java_path, strJavaHome); + //strcat(*java_path, "\\bin\\java"); + } else { + return 0; + } + return 1; +} +#endif + void *qemu_oom_check(void *ptr) { if (ptr == NULL) { fprintf(stderr, "Failed to allocate memory: %lu\n", GetLastError()); +#ifdef CONFIG_MARU + char _msg[] = "Failed to allocate memory in qemu."; + char cmd[JAVA_MAX_COMMAND_LENGTH] = { 0, }; + char *JAVA_EXEFILE_PATH = malloc(JAVA_MAX_COMMAND_LENGTH); + memset(JAVA_EXEFILE_PATH, 0, JAVA_MAX_COMMAND_LENGTH); + if (is_wow64_temp()) { + if (!get_java_path_temp(&JAVA_EXEFILE_PATH)) { + strcpy(JAVA_EXEFILE_PATH, "java"); + } + } else { + strcpy(JAVA_EXEFILE_PATH, "java"); + } + int len = strlen(JAVA_EXEFILE_PATH) + strlen(JAVA_EXEOPTION) + + strlen(JAR_SKINFILE) + strlen(JAVA_SIMPLEMODE_OPTION) + + strlen(_msg) + 7; + if (len > JAVA_MAX_COMMAND_LENGTH) { + len = JAVA_MAX_COMMAND_LENGTH; + } + + snprintf(cmd, len, "%s %s %s %s=\"%s\"", + JAVA_EXEFILE_PATH, JAVA_EXEOPTION, JAR_SKINFILE, + JAVA_SIMPLEMODE_OPTION, _msg); + int ret = WinExec(cmd, SW_SHOW); + + /* for 64bit windows */ + free(JAVA_EXEFILE_PATH); + JAVA_EXEFILE_PATH=0; +#endif abort(); } return ptr; diff --git a/util/qemu-sockets.c b/util/qemu-sockets.c index 96eca2a..89347a8 100644 --- a/util/qemu-sockets.c +++ b/util/qemu-sockets.c @@ -326,6 +326,14 @@ static struct addrinfo *inet_parse_connect_opts(QemuOpts *opts, Error **errp) ai.ai_family = PF_INET6; } +#ifdef CONFIG_MARU + // for lookup loopback interface... + if (addr[0] == '\0') { + ai.ai_flags = 0; + addr = NULL; + } +#endif + /* lookup */ rc = getaddrinfo(addr, port, &ai, &res); if (rc != 0) { diff --git a/vl.c b/vl.c index 0f45f8b..e0c72c1 100644 --- a/vl.c +++ b/vl.c @@ -2134,6 +2134,13 @@ static bool qxl_vga_available(void) return object_class_by_name("qxl-vga"); } +#ifdef CONFIG_MARU +static bool maru_vga_available(void) +{ + return object_class_by_name("MARU_VGA"); +} +#endif + static void select_vgahw (const char *p) { const char *opts; @@ -2171,7 +2178,12 @@ static void select_vgahw (const char *p) } #ifdef CONFIG_MARU } else if (strstart(p, "maru", &opts)) { - vga_interface_type = VGA_MARU; + if (maru_vga_available()) { + vga_interface_type = VGA_MARU; + } else { + fprintf(stderr, "Error: MARU VGA not available\n"); + exit(0); + } #endif } else if (!strstart(p, "none", &opts)) { invalid_vga: -- 2.7.4