diff options
-rw-r--r-- | Makefile.android | 1 | ||||
-rw-r--r-- | cpu-all.h | 64 | ||||
-rw-r--r-- | hw/hw.h | 5 | ||||
-rw-r--r-- | hw/isa.h | 9 | ||||
-rw-r--r-- | ioport-user.c | 60 | ||||
-rw-r--r-- | ioport.c | 235 | ||||
-rw-r--r-- | ioport.h | 53 | ||||
-rw-r--r-- | monitor.c | 8 | ||||
-rw-r--r-- | vl-android.c | 138 |
9 files changed, 392 insertions, 181 deletions
diff --git a/Makefile.android b/Makefile.android index 0639bfd..188450d 100644 --- a/Makefile.android +++ b/Makefile.android @@ -557,6 +557,7 @@ VL_SOURCES := vl-android.c osdep.c cutils.c \ buffered_file.c \ cbuffer.c \ gdbstub.c \ + ioport.c \ vnc-android.c disas.c arm-dis.c \ shaper.c charpipe.c loadpng.c \ framebuffer.c \ @@ -14,8 +14,7 @@ * 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, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA + * License along with this library; if not, see <http://www.gnu.org/licenses/>. */ #ifndef CPU_ALL_H #define CPU_ALL_H @@ -625,8 +624,13 @@ static inline void stfq_be_p(void *ptr, float64 v) /* On some host systems the guest address space is reserved on the host. * This allows the guest address space to be offset to a convenient location. */ -//#define GUEST_BASE 0x20000000 -#define GUEST_BASE 0 +#if defined(CONFIG_USE_GUEST_BASE) +extern unsigned long guest_base; +extern int have_guest_base; +#define GUEST_BASE guest_base +#else +#define GUEST_BASE 0ul +#endif /* All direct uses of g2h and h2g need to go away for usermode softmmu. */ #define g2h(x) ((void *)((unsigned long)(x) + GUEST_BASE)) @@ -768,6 +772,9 @@ extern int use_icount; #define CPU_INTERRUPT_DEBUG 0x80 /* Debug event occured. */ #define CPU_INTERRUPT_VIRQ 0x100 /* virtual interrupt pending. */ #define CPU_INTERRUPT_NMI 0x200 /* NMI pending. */ +#define CPU_INTERRUPT_INIT 0x400 /* INIT pending. */ +#define CPU_INTERRUPT_SIPI 0x800 /* SIPI pending. */ +#define CPU_INTERRUPT_MCE 0x1000 /* (x86 only) MCE pending. */ void cpu_interrupt(CPUState *s, int mask); void cpu_reset_interrupt(CPUState *env, int mask); @@ -834,17 +841,7 @@ void cpu_set_log_filename(const char *filename); int cpu_str_to_log_mask(const char *str); /* IO ports API */ - -/* NOTE: as these functions may be even used when there is an isa - brige on non x86 targets, we always defined them */ -#ifndef NO_CPU_IO_DEFS -void cpu_outb(CPUState *env, int addr, int val); -void cpu_outw(CPUState *env, int addr, int val); -void cpu_outl(CPUState *env, int addr, int val); -int cpu_inb(CPUState *env, int addr); -int cpu_inw(CPUState *env, int addr); -int cpu_inl(CPUState *env, int addr); -#endif +#include "ioport.h" /* memory API */ @@ -876,7 +873,6 @@ int cpu_memory_rw_debug(CPUState *env, target_ulong addr, #define VGA_DIRTY_FLAG 0x01 #define CODE_DIRTY_FLAG 0x02 -#define KQEMU_DIRTY_FLAG 0x04 #define MIGRATION_DIRTY_FLAG 0x08 /* read dirty bit (return 0 or 1) */ @@ -1021,24 +1017,34 @@ static inline int64_t cpu_get_real_ticks (void) #endif } -#elif defined(__mips__) +#elif defined(__mips__) && \ + ((defined(__mips_isa_rev) && __mips_isa_rev >= 2) || defined(__linux__)) +/* + * binutils wants to use rdhwr only on mips32r2 + * but as linux kernel emulate it, it's fine + * to use it. + * + */ +#define MIPS_RDHWR(rd, value) { \ + __asm__ __volatile__ ( \ + ".set push\n\t" \ + ".set mips32r2\n\t" \ + "rdhwr %0, "rd"\n\t" \ + ".set pop" \ + : "=r" (value)); \ +} static inline int64_t cpu_get_real_ticks(void) { -#if __mips_isa_rev >= 2 +/* On kernels >= 2.6.25 rdhwr <reg>, $2 and $3 are emulated */ uint32_t count; static uint32_t cyc_per_count = 0; if (!cyc_per_count) - __asm__ __volatile__("rdhwr %0, $3" : "=r" (cyc_per_count)); + MIPS_RDHWR("$3", cyc_per_count); - __asm__ __volatile__("rdhwr %1, $2" : "=r" (count)); + MIPS_RDHWR("$2", count); return (int64_t)(count * cyc_per_count); -#else - /* FIXME */ - static int64_t ticks = 0; - return ticks++; -#endif } #else @@ -1059,14 +1065,12 @@ static inline int64_t profile_getclock(void) return cpu_get_real_ticks(); } -extern int64_t kqemu_time, kqemu_time_start; extern int64_t qemu_time, qemu_time_start; extern int64_t tlb_flush_time; -extern int64_t kqemu_exec_count; extern int64_t dev_time; -extern int64_t kqemu_ret_int_count; -extern int64_t kqemu_ret_excp_count; -extern int64_t kqemu_ret_intr_count; #endif +void cpu_inject_x86_mce(CPUState *cenv, int bank, uint64_t status, + uint64_t mcg_status, uint64_t addr, uint64_t misc); + #endif /* CPU_ALL_H */ @@ -35,6 +35,7 @@ typedef int (QEMUFileRateLimit)(void *opaque); * the old rate otherwise */ typedef size_t (QEMUFileSetRateLimit)(void *opaque, size_t new_rate); +typedef size_t (QEMUFileGetRateLimit)(void *opaque); QEMUFile *qemu_fopen_ops(void *opaque, QEMUFilePutBufferFunc *put_buffer, QEMUFileGetBufferFunc *get_buffer, @@ -260,8 +261,4 @@ void qemu_register_reset(QEMUResetHandler *func, int order, void *opaque); typedef int QEMUBootSetHandler(void *opaque, const char *boot_device); void qemu_register_boot_set(QEMUBootSetHandler *func, void *opaque); -/* These should really be in isa.h, but are here to make pc.h happy. */ -typedef void (IOPortWriteFunc)(void *opaque, uint32_t address, uint32_t data); -typedef uint32_t (IOPortReadFunc)(void *opaque, uint32_t address); - #endif @@ -2,13 +2,8 @@ #define HW_ISA_H /* ISA bus */ -extern target_phys_addr_t isa_mem_base; - -int register_ioport_read(int start, int length, int size, - IOPortReadFunc *func, void *opaque); -int register_ioport_write(int start, int length, int size, - IOPortWriteFunc *func, void *opaque); -void isa_unassign_ioport(int start, int length); +#include "ioport.h" +#include "qdev.h" void isa_mmio_init(target_phys_addr_t base, target_phys_addr_t size); diff --git a/ioport-user.c b/ioport-user.c new file mode 100644 index 0000000..03fac22 --- /dev/null +++ b/ioport-user.c @@ -0,0 +1,60 @@ +/* + * qemu user ioport functions + * + * Copyright (c) 2003-2008 Fabrice Bellard + * + * 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; either version 2 of the License, or + * (at your option) any later version. + * + * 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. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see <http://www.gnu.org/licenses/>. + */ + +#include <stdio.h> + +#include "qemu.h" +#include "qemu-common.h" +#include "ioport.h" + +void cpu_outb(pio_addr_t addr, uint8_t val) +{ + fprintf(stderr, "outb: port=0x%04"FMT_pioaddr", data=%02"PRIx8"\n", + addr, val); +} + +void cpu_outw(pio_addr_t addr, uint16_t val) +{ + fprintf(stderr, "outw: port=0x%04"FMT_pioaddr", data=%04"PRIx16"\n", + addr, val); +} + +void cpu_outl(pio_addr_t addr, uint32_t val) +{ + fprintf(stderr, "outl: port=0x%04"FMT_pioaddr", data=%08"PRIx32"\n", + addr, val); +} + +uint8_t cpu_inb(pio_addr_t addr) +{ + fprintf(stderr, "inb: port=0x%04"FMT_pioaddr"\n", addr); + return 0; +} + +uint16_t cpu_inw(pio_addr_t addr) +{ + fprintf(stderr, "inw: port=0x%04"FMT_pioaddr"\n", addr); + return 0; +} + +uint32_t cpu_inl(pio_addr_t addr) +{ + fprintf(stderr, "inl: port=0x%04"FMT_pioaddr"\n", addr); + return 0; +} diff --git a/ioport.c b/ioport.c new file mode 100644 index 0000000..53dd87a --- /dev/null +++ b/ioport.c @@ -0,0 +1,235 @@ +/* + * 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. + */ +/* + * splitted out ioport related stuffs from vl.c. + */ + +#include "ioport.h" + +/***********************************************************/ +/* IO Port */ + +//#define DEBUG_UNUSED_IOPORT +//#define DEBUG_IOPORT + +#ifdef DEBUG_UNUSED_IOPORT +# define LOG_UNUSED_IOPORT(fmt, ...) fprintf(stderr, fmt, ## __VA_ARGS__) +#else +# define LOG_UNUSED_IOPORT(fmt, ...) do{ } while (0) +#endif + +#ifdef DEBUG_IOPORT +# define LOG_IOPORT(...) qemu_log_mask(CPU_LOG_IOPORT, ## __VA_ARGS__) +#else +# define LOG_IOPORT(...) do { } while (0) +#endif + +/* XXX: use a two level table to limit memory usage */ + +static void *ioport_opaque[MAX_IOPORTS]; +static IOPortReadFunc *ioport_read_table[3][MAX_IOPORTS]; +static IOPortWriteFunc *ioport_write_table[3][MAX_IOPORTS]; + +static IOPortReadFunc default_ioport_readb, default_ioport_readw, default_ioport_readl; +static IOPortWriteFunc default_ioport_writeb, default_ioport_writew, default_ioport_writel; + +static uint32_t ioport_read(int index, uint32_t address) +{ + static IOPortReadFunc * const default_func[3] = { + default_ioport_readb, + default_ioport_readw, + default_ioport_readl + }; + IOPortReadFunc *func = ioport_read_table[index][address]; + if (!func) + func = default_func[index]; + return func(ioport_opaque[address], address); +} + +static void ioport_write(int index, uint32_t address, uint32_t data) +{ + static IOPortWriteFunc * const default_func[3] = { + default_ioport_writeb, + default_ioport_writew, + default_ioport_writel + }; + IOPortWriteFunc *func = ioport_write_table[index][address]; + if (!func) + func = default_func[index]; + func(ioport_opaque[address], address, data); +} + +static uint32_t default_ioport_readb(void *opaque, uint32_t address) +{ + LOG_UNUSED_IOPORT("unused inb: port=0x%04"PRIx32"\n", address); + return 0xff; +} + +static void default_ioport_writeb(void *opaque, uint32_t address, uint32_t data) +{ + LOG_UNUSED_IOPORT("unused outb: port=0x%04"PRIx32" data=0x%02"PRIx32"\n", + address, data); +} + +/* default is to make two byte accesses */ +static uint32_t default_ioport_readw(void *opaque, uint32_t address) +{ + uint32_t data; + data = ioport_read(0, address); + address = (address + 1) & IOPORTS_MASK; + data |= ioport_read(0, address) << 8; + return data; +} + +static void default_ioport_writew(void *opaque, uint32_t address, uint32_t data) +{ + ioport_write(0, address, data & 0xff); + address = (address + 1) & IOPORTS_MASK; + ioport_write(0, address, (data >> 8) & 0xff); +} + +static uint32_t default_ioport_readl(void *opaque, uint32_t address) +{ + LOG_UNUSED_IOPORT("unused inl: port=0x%04"PRIx32"\n", address); + return 0xffffffff; +} + +static void default_ioport_writel(void *opaque, uint32_t address, uint32_t data) +{ + LOG_UNUSED_IOPORT("unused outl: port=0x%04"PRIx32" data=0x%02"PRIx32"\n", + address, data); +} + +static int ioport_bsize(int size, int *bsize) +{ + if (size == 1) { + *bsize = 0; + } else if (size == 2) { + *bsize = 1; + } else if (size == 4) { + *bsize = 2; + } else { + return -1; + } + return 0; +} + +/* size is the word size in byte */ +int register_ioport_read(pio_addr_t start, int length, int size, + IOPortReadFunc *func, void *opaque) +{ + int i, bsize; + + if (ioport_bsize(size, &bsize)) { + hw_error("register_ioport_read: invalid size"); + return -1; + } + for(i = start; i < start + length; i += size) { + ioport_read_table[bsize][i] = func; + if (ioport_opaque[i] != NULL && ioport_opaque[i] != opaque) + hw_error("register_ioport_read: invalid opaque"); + ioport_opaque[i] = opaque; + } + return 0; +} + +/* size is the word size in byte */ +int register_ioport_write(pio_addr_t start, int length, int size, + IOPortWriteFunc *func, void *opaque) +{ + int i, bsize; + + if (ioport_bsize(size, &bsize)) { + hw_error("register_ioport_write: invalid size"); + return -1; + } + for(i = start; i < start + length; i += size) { + ioport_write_table[bsize][i] = func; + if (ioport_opaque[i] != NULL && ioport_opaque[i] != opaque) + hw_error("register_ioport_write: invalid opaque"); + ioport_opaque[i] = opaque; + } + return 0; +} + +void isa_unassign_ioport(pio_addr_t start, int length) +{ + int i; + + for(i = start; i < start + length; i++) { + ioport_read_table[0][i] = default_ioport_readb; + ioport_read_table[1][i] = default_ioport_readw; + ioport_read_table[2][i] = default_ioport_readl; + + ioport_write_table[0][i] = default_ioport_writeb; + ioport_write_table[1][i] = default_ioport_writew; + ioport_write_table[2][i] = default_ioport_writel; + + ioport_opaque[i] = NULL; + } +} + +/***********************************************************/ + +void cpu_outb(pio_addr_t addr, uint8_t val) +{ + LOG_IOPORT("outb: %04"FMT_pioaddr" %02"PRIx8"\n", addr, val); + ioport_write(0, addr, val); +} + +void cpu_outw(pio_addr_t addr, uint16_t val) +{ + LOG_IOPORT("outw: %04"FMT_pioaddr" %04"PRIx16"\n", addr, val); + ioport_write(1, addr, val); +} + +void cpu_outl(pio_addr_t addr, uint32_t val) +{ + LOG_IOPORT("outl: %04"FMT_pioaddr" %08"PRIx32"\n", addr, val); + ioport_write(2, addr, val); +} + +uint8_t cpu_inb(pio_addr_t addr) +{ + uint8_t val; + val = ioport_read(0, addr); + LOG_IOPORT("inb : %04"FMT_pioaddr" %02"PRIx8"\n", addr, val); + return val; +} + +uint16_t cpu_inw(pio_addr_t addr) +{ + uint16_t val; + val = ioport_read(1, addr); + LOG_IOPORT("inw : %04"FMT_pioaddr" %04"PRIx16"\n", addr, val); + return val; +} + +uint32_t cpu_inl(pio_addr_t addr) +{ + uint32_t val; + val = ioport_read(2, addr); + LOG_IOPORT("inl : %04"FMT_pioaddr" %08"PRIx32"\n", addr, val); + return val; +} diff --git a/ioport.h b/ioport.h new file mode 100644 index 0000000..3d3c8a3 --- /dev/null +++ b/ioport.h @@ -0,0 +1,53 @@ +/* + * defines ioport related functions + * + * 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 <http://www.gnu.org/licenses/>. + */ + +/************************************************************************** + * IO ports API + */ + +#ifndef IOPORT_H +#define IOPORT_H + +#include "qemu-common.h" + +typedef uint32_t pio_addr_t; +#define FMT_pioaddr PRIx32 + +#define MAX_IOPORTS (64 * 1024) +#define IOPORTS_MASK (MAX_IOPORTS - 1) + +/* These should really be in isa.h, but are here to make pc.h happy. */ +typedef void (IOPortWriteFunc)(void *opaque, uint32_t address, uint32_t data); +typedef uint32_t (IOPortReadFunc)(void *opaque, uint32_t address); + +int register_ioport_read(pio_addr_t start, int length, int size, + IOPortReadFunc *func, void *opaque); +int register_ioport_write(pio_addr_t start, int length, int size, + IOPortWriteFunc *func, void *opaque); +void isa_unassign_ioport(pio_addr_t start, int length); + + +void cpu_outb(pio_addr_t addr, uint8_t val); +void cpu_outw(pio_addr_t addr, uint16_t val); +void cpu_outl(pio_addr_t addr, uint32_t val); +uint8_t cpu_inb(pio_addr_t addr); +uint16_t cpu_inw(pio_addr_t addr); +uint32_t cpu_inl(pio_addr_t addr); + +#endif /* IOPORT_H */ @@ -1161,7 +1161,7 @@ static void do_ioport_read(Monitor *mon, int count, int format, int size, int suffix; if (has_index) { - cpu_outb(NULL, addr & 0xffff, index & 0xff); + cpu_outb(addr & 0xffff, index & 0xff); addr++; } addr &= 0xffff; @@ -1169,15 +1169,15 @@ static void do_ioport_read(Monitor *mon, int count, int format, int size, switch(size) { default: case 1: - val = cpu_inb(NULL, addr); + val = cpu_inb(addr); suffix = 'b'; break; case 2: - val = cpu_inw(NULL, addr); + val = cpu_inw(addr); suffix = 'w'; break; case 4: - val = cpu_inl(NULL, addr); + val = cpu_inl(addr); suffix = 'l'; break; } diff --git a/vl-android.c b/vl-android.c index ad89651..bb8b759 100644 --- a/vl-android.c +++ b/vl-android.c @@ -223,7 +223,6 @@ #define MAX_BT_CMDLINE 10 /* XXX: use a two level table to limit memory usage */ -#define MAX_IOPORTS 65536 static const char *data_dir; const char *bios_name = NULL; @@ -412,141 +411,6 @@ static void default_ioport_writel(void *opaque, uint32_t address, uint32_t data) #endif } -/* size is the word size in byte */ -int register_ioport_read(int start, int length, int size, - IOPortReadFunc *func, void *opaque) -{ - int i, bsize; - - if (size == 1) { - bsize = 0; - } else if (size == 2) { - bsize = 1; - } else if (size == 4) { - bsize = 2; - } else { - hw_error("register_ioport_read: invalid size"); - return -1; - } - for(i = start; i < start + length; i += size) { - ioport_read_table[bsize][i] = func; - if (ioport_opaque[i] != NULL && ioport_opaque[i] != opaque) - hw_error("register_ioport_read: invalid opaque"); - ioport_opaque[i] = opaque; - } - return 0; -} - -/* size is the word size in byte */ -int register_ioport_write(int start, int length, int size, - IOPortWriteFunc *func, void *opaque) -{ - int i, bsize; - - if (size == 1) { - bsize = 0; - } else if (size == 2) { - bsize = 1; - } else if (size == 4) { - bsize = 2; - } else { - hw_error("register_ioport_write: invalid size"); - return -1; - } - for(i = start; i < start + length; i += size) { - ioport_write_table[bsize][i] = func; - if (ioport_opaque[i] != NULL && ioport_opaque[i] != opaque) - hw_error("register_ioport_write: invalid opaque"); - ioport_opaque[i] = opaque; - } - return 0; -} - -void isa_unassign_ioport(int start, int length) -{ - int i; - - for(i = start; i < start + length; i++) { - ioport_read_table[0][i] = default_ioport_readb; - ioport_read_table[1][i] = default_ioport_readw; - ioport_read_table[2][i] = default_ioport_readl; - - ioport_write_table[0][i] = default_ioport_writeb; - ioport_write_table[1][i] = default_ioport_writew; - ioport_write_table[2][i] = default_ioport_writel; - - ioport_opaque[i] = NULL; - } -} - -/***********************************************************/ - -void cpu_outb(CPUState *env, int addr, int val) -{ - LOG_IOPORT("outb: %04x %02x\n", addr, val); - ioport_write(0, addr, val); -#ifdef CONFIG_KQEMU - if (env) - env->last_io_time = cpu_get_time_fast(); -#endif -} - -void cpu_outw(CPUState *env, int addr, int val) -{ - LOG_IOPORT("outw: %04x %04x\n", addr, val); - ioport_write(1, addr, val); -#ifdef CONFIG_KQEMU - if (env) - env->last_io_time = cpu_get_time_fast(); -#endif -} - -void cpu_outl(CPUState *env, int addr, int val) -{ - LOG_IOPORT("outl: %04x %08x\n", addr, val); - ioport_write(2, addr, val); -#ifdef CONFIG_KQEMU - if (env) - env->last_io_time = cpu_get_time_fast(); -#endif -} - -int cpu_inb(CPUState *env, int addr) -{ - int val; - val = ioport_read(0, addr); - LOG_IOPORT("inb : %04x %02x\n", addr, val); -#ifdef CONFIG_KQEMU - if (env) - env->last_io_time = cpu_get_time_fast(); -#endif - return val; -} - -int cpu_inw(CPUState *env, int addr) -{ - int val; - val = ioport_read(1, addr); - LOG_IOPORT("inw : %04x %04x\n", addr, val); -#ifdef CONFIG_KQEMU - if (env) - env->last_io_time = cpu_get_time_fast(); -#endif - return val; -} - -int cpu_inl(CPUState *env, int addr) -{ - int val; - val = ioport_read(2, addr); - LOG_IOPORT("inl : %04x %08x\n", addr, val); -#ifdef CONFIG_KQEMU - if (env) - env->last_io_time = cpu_get_time_fast(); -#endif - return val; -} - /***********************************************************/ void hw_error(const char *fmt, ...) { @@ -2777,6 +2641,7 @@ int usb_device_add_dev(USBDevice *dev) return 0; } +#if 0 static void usb_msd_password_cb(void *opaque, int err) { USBDevice *dev = opaque; @@ -2786,6 +2651,7 @@ static void usb_msd_password_cb(void *opaque, int err) else dev->handle_destroy(dev); } +#endif static int usb_device_add(const char *devname, int is_hotplug) { |